summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.eslintrc.yml4
-rw-r--r--.gitattributes1
-rw-r--r--.gitignore6
-rw-r--r--.gitlab-ci.yml5
-rw-r--r--.gitlab/CODEOWNERS29
-rw-r--r--.gitlab/ci/cache-repo.gitlab-ci.yml42
-rw-r--r--.gitlab/ci/cng.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml16
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml32
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml14
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml4
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml9
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml22
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml35
-rw-r--r--.gitlab/ci/setup.gitlab-ci.yml4
-rw-r--r--.gitlab/ci/test-metadata.gitlab-ci.yml4
-rw-r--r--.gitlab/ci/yaml.gitlab-ci.yml6
-rw-r--r--.gitlab/issue_templates/Basic Proposal.md11
-rw-r--r--.gitlab/issue_templates/Feature Flag Roll Out.md12
-rw-r--r--.gitlab/issue_templates/Feature proposal.md6
-rw-r--r--.gitlab/issue_templates/Lean Feature Proposal.md99
-rw-r--r--.gitlab/merge_request_templates/Documentation.md8
-rw-r--r--.gitpod.yml17
-rw-r--r--.haml-lint_todo.yml3
-rw-r--r--.nvmrc2
-rw-r--r--.rubocop.yml10
-rw-r--r--.rubocop_manual_todo.yml759
-rw-r--r--.rubocop_todo.yml1407
-rw-r--r--.ruby-version2
-rw-r--r--.scss-lint.yml1
-rw-r--r--CHANGELOG.md57
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_KAS_VERSION2
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--Gemfile36
-rw-r--r--Gemfile.lock148
-rw-r--r--README.md4
-rw-r--r--app/assets/javascripts/access_tokens/components/expires_at_field.vue26
-rw-r--r--app/assets/javascripts/access_tokens/index.js31
-rw-r--r--app/assets/javascripts/admin/dev_ops_report/devops_adoption.js2
-rw-r--r--app/assets/javascripts/admin/dev_ops_report/devops_score_empty_state.js27
-rw-r--r--app/assets/javascripts/alert_management/components/alert_details.vue9
-rw-r--r--app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue221
-rw-r--r--app/assets/javascripts/alerts_settings/components/alert_settings_form_help_block.vue32
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue133
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue522
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_form_new.vue661
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_form_old.vue494
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue331
-rw-r--r--app/assets/javascripts/alerts_settings/components/mocks/gitlabFields.json112
-rw-r--r--app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json121
-rw-r--r--app/assets/javascripts/alerts_settings/constants.js32
-rw-r--r--app/assets/javascripts/alerts_settings/graphql.js44
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/fragments/integration_item.fragment.graphql9
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql10
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql12
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql10
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql10
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/reset_prometheus_token.mutation.graphql10
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/update_current_intergration.mutation.graphql19
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql10
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/update_prometheus_integration.mutation.graphql10
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/queries/get_current_integration.query.graphql3
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql11
-rw-r--r--app/assets/javascripts/alerts_settings/index.js39
-rw-r--r--app/assets/javascripts/alerts_settings/services/index.js5
-rw-r--r--app/assets/javascripts/alerts_settings/utils/cache_updates.js84
-rw-r--r--app/assets/javascripts/alerts_settings/utils/error_messages.js21
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/components/app.vue24
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/components/charts_config.js87
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/components/instance_statistics_count_chart.vue206
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/components/pipelines_chart.vue215
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/components/projects_and_groups_chart.vue224
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/graphql/queries/groups.query.graphql13
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/graphql/queries/instance_count.query.graphql13
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/graphql/queries/pipeline_stats.query.graphql76
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/graphql/queries/projects.query.graphql13
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/utils.js45
-rw-r--r--app/assets/javascripts/analytics/product_analytics/components/activity_chart.vue13
-rw-r--r--app/assets/javascripts/analytics/shared/components/metric_card.vue2
-rw-r--r--app/assets/javascripts/api.js59
-rw-r--r--app/assets/javascripts/awards_handler.js37
-rw-r--r--app/assets/javascripts/badges/components/badge.vue14
-rw-r--r--app/assets/javascripts/batch_comments/components/inline_draft_comment_row.vue32
-rw-r--r--app/assets/javascripts/batch_comments/components/parallel_draft_comment_row.vue49
-rw-r--r--app/assets/javascripts/batch_comments/mixins/resolved_status.js6
-rw-r--r--app/assets/javascripts/behaviors/copy_to_clipboard.js30
-rw-r--r--app/assets/javascripts/behaviors/details_behavior.js28
-rw-r--r--app/assets/javascripts/behaviors/index.js1
-rw-r--r--app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js1
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_mermaid.js2
-rw-r--r--app/assets/javascripts/behaviors/quick_submit.js16
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js17
-rw-r--r--app/assets/javascripts/behaviors/toggler_behavior.js18
-rw-r--r--app/assets/javascripts/blob/components/blob_edit_content.vue2
-rw-r--r--app/assets/javascripts/blob/components/blob_edit_header.vue1
-rw-r--r--app/assets/javascripts/blob/components/blob_header.vue2
-rw-r--r--app/assets/javascripts/blob/components/blob_header_default_actions.vue6
-rw-r--r--app/assets/javascripts/blob/components/blob_header_filepath.vue2
-rw-r--r--app/assets/javascripts/blob/pipeline_tour_success_modal.vue14
-rw-r--r--app/assets/javascripts/blob_edit/blob_bundle.js58
-rw-r--r--app/assets/javascripts/boards/components/board_assignee_dropdown.vue178
-rw-r--r--app/assets/javascripts/boards/components/board_card_layout.vue5
-rw-r--r--app/assets/javascripts/boards/components/board_column.vue49
-rw-r--r--app/assets/javascripts/boards/components/board_column_new.vue94
-rw-r--r--app/assets/javascripts/boards/components/board_configuration_options.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_content.vue8
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue4
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue15
-rw-r--r--app/assets/javascripts/boards/components/board_list_header.vue50
-rw-r--r--app/assets/javascripts/boards/components/board_list_header_new.vue358
-rw-r--r--app/assets/javascripts/boards/components/board_list_new.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue34
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue_new.vue129
-rw-r--r--app/assets/javascripts/boards/components/board_promotion_state.js1
-rw-r--r--app/assets/javascripts/boards/components/board_settings_sidebar.vue18
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue2
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.vue35
-rw-r--r--app/assets/javascripts/boards/components/modal/empty_state.vue21
-rw-r--r--app/assets/javascripts/boards/components/new_list_dropdown.js3
-rw-r--r--app/assets/javascripts/boards/components/project_select.vue12
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue111
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue14
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue71
-rw-r--r--app/assets/javascripts/boards/constants.js4
-rw-r--r--app/assets/javascripts/boards/graphql/mutations/issue_set_subscription.mutation.graphql8
-rw-r--r--app/assets/javascripts/boards/index.js12
-rw-r--r--app/assets/javascripts/boards/mixins/sortable_default_options.js5
-rw-r--r--app/assets/javascripts/boards/queries/board_labels.query.graphql23
-rw-r--r--app/assets/javascripts/boards/queries/board_list_destroy.mutation.graphql5
-rw-r--r--app/assets/javascripts/boards/queries/issue_create.mutation.graphql10
-rw-r--r--app/assets/javascripts/boards/queries/issue_set_due_date.mutation.graphql8
-rw-r--r--app/assets/javascripts/boards/queries/users_search.query.graphql11
-rw-r--r--app/assets/javascripts/boards/stores/actions.js193
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js7
-rw-r--r--app/assets/javascripts/boards/stores/getters.js11
-rw-r--r--app/assets/javascripts/boards/stores/mutation_types.js9
-rw-r--r--app/assets/javascripts/boards/stores/mutations.js41
-rw-r--r--app/assets/javascripts/boards/toggle_focus.js5
-rw-r--r--app/assets/javascripts/ci_lint/components/ci_lint.vue14
-rw-r--r--app/assets/javascripts/ci_lint/components/ci_lint_results.vue37
-rw-r--r--app/assets/javascripts/ci_lint/graphql/resolvers.js34
-rw-r--r--app/assets/javascripts/ci_lint/index.js37
-rw-r--r--app/assets/javascripts/ci_variable_list/ajax_variable_list.js128
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue4
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue8
-rw-r--r--app/assets/javascripts/clusters/components/application_row.vue2
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue15
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters.vue10
-rw-r--r--app/assets/javascripts/compare_autocomplete.js3
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue61
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue40
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/constants.js2
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/services/aws_services_facade.js21
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/store/actions.js16
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/store/index.js5
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue11
-rw-r--r--app/assets/javascripts/create_merge_request_dropdown.js6
-rw-r--r--app/assets/javascripts/dependency_proxy.js5
-rw-r--r--app/assets/javascripts/deploy_keys/components/key.vue19
-rw-r--r--app/assets/javascripts/design_management/components/design_destroyer.vue2
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_discussion.vue6
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_note.vue4
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue2
-rw-r--r--app/assets/javascripts/design_management/components/design_overlay.vue4
-rw-r--r--app/assets/javascripts/design_management/components/design_scaler.vue23
-rw-r--r--app/assets/javascripts/design_management/components/design_sidebar.vue2
-rw-r--r--app/assets/javascripts/design_management/components/toolbar/design_navigation.vue7
-rw-r--r--app/assets/javascripts/design_management/components/toolbar/index.vue16
-rw-r--r--app/assets/javascripts/design_management/components/upload/button.vue5
-rw-r--r--app/assets/javascripts/design_management/components/upload/design_dropzone.vue147
-rw-r--r--app/assets/javascripts/design_management/constants.js3
-rw-r--r--app/assets/javascripts/design_management/graphql/fragments/note_permissions.fragment.graphql1
-rw-r--r--app/assets/javascripts/design_management/graphql/mutations/reposition_image_diff_note.mutation.graphql10
-rw-r--r--app/assets/javascripts/design_management/graphql/mutations/update_image_diff_note.mutation.graphql10
-rw-r--r--app/assets/javascripts/design_management/graphql/queries/design_permissions.query.graphql10
-rw-r--r--app/assets/javascripts/design_management/graphql/queries/get_design.query.graphql7
-rw-r--r--app/assets/javascripts/design_management/graphql/queries/get_design_list.query.graphql23
-rw-r--r--app/assets/javascripts/design_management/mixins/all_designs.js18
-rw-r--r--app/assets/javascripts/design_management/mixins/all_versions.js2
-rw-r--r--app/assets/javascripts/design_management/pages/design/index.vue41
-rw-r--r--app/assets/javascripts/design_management/pages/index.vue91
-rw-r--r--app/assets/javascripts/design_management/router/index.js17
-rw-r--r--app/assets/javascripts/design_management/utils/cache_update.js14
-rw-r--r--app/assets/javascripts/design_management/utils/design_management_utils.js6
-rw-r--r--app/assets/javascripts/diffs/components/app.vue25
-rw-r--r--app/assets/javascripts/diffs/components/collapsed_files_warning.vue8
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue11
-rw-r--r--app/assets/javascripts/diffs/components/diff_comment_cell.vue69
-rw-r--r--app/assets/javascripts/diffs/components/diff_content.vue35
-rw-r--r--app/assets/javascripts/diffs/components/diff_expansion_cell.vue55
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue209
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue26
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_row.vue1
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_note_form.vue28
-rw-r--r--app/assets/javascripts/diffs/components/diff_row.vue271
-rw-r--r--app/assets/javascripts/diffs/components/diff_row_utils.js73
-rw-r--r--app/assets/javascripts/diffs/components/diff_view.vue151
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_comment_row.vue82
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_expansion_row.vue51
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_table_row.vue61
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_view.vue70
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue175
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_expansion_row.vue56
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_table_row.vue63
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_view.vue89
-rw-r--r--app/assets/javascripts/diffs/constants.js12
-rw-r--r--app/assets/javascripts/diffs/diff_file.js24
-rw-r--r--app/assets/javascripts/diffs/event_hub.js3
-rw-r--r--app/assets/javascripts/diffs/i18n.js13
-rw-r--r--app/assets/javascripts/diffs/store/actions.js57
-rw-r--r--app/assets/javascripts/diffs/store/getters.js21
-rw-r--r--app/assets/javascripts/diffs/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js52
-rw-r--r--app/assets/javascripts/diffs/store/utils.js8
-rw-r--r--app/assets/javascripts/diffs/utils/performance.js80
-rw-r--r--app/assets/javascripts/dropzone_input.js3
-rw-r--r--app/assets/javascripts/editor/editor_lite.js3
-rw-r--r--app/assets/javascripts/environments/components/container.vue2
-rw-r--r--app/assets/javascripts/environments/components/delete_environment_modal.vue42
-rw-r--r--app/assets/javascripts/environments/components/environment_delete.vue23
-rw-r--r--app/assets/javascripts/environments/components/environment_stop.vue6
-rw-r--r--app/assets/javascripts/environments/components/environments_app.vue2
-rw-r--r--app/assets/javascripts/environments/components/stop_environment_modal.vue48
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue34
-rw-r--r--app/assets/javascripts/error_tracking/components/error_tracking_list.vue57
-rw-r--r--app/assets/javascripts/error_tracking_settings/components/project_dropdown.vue16
-rw-r--r--app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue50
-rw-r--r--app/assets/javascripts/feature_flags/components/edit_feature_flag.vue2
-rw-r--r--app/assets/javascripts/feature_flags/components/feature_flags.vue4
-rw-r--r--app/assets/javascripts/feature_flags/components/form.vue22
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/flexible_rollout.vue4
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue73
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/percent_rollout.vue4
-rw-r--r--app/assets/javascripts/feature_flags/edit.js2
-rw-r--r--app/assets/javascripts/feature_flags/new.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/edit/index.js4
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js17
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/getters.js11
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js12
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/mutation_types.js5
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js19
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/state.js9
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/status.js6
-rw-r--r--app/assets/javascripts/feature_flags/store/helpers.js4
-rw-r--r--app/assets/javascripts/feature_flags/store/new/index.js4
-rw-r--r--app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js83
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_ajax_filter.js10
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_operator.js5
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_user.js2
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown.js6
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js16
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js14
-rw-r--r--app/assets/javascripts/frequent_items/index.js82
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js51
-rw-r--r--app/assets/javascripts/graphql_shared/utils.js8
-rw-r--r--app/assets/javascripts/groups/components/app.vue58
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue8
-rw-r--r--app/assets/javascripts/groups/components/item_actions.vue40
-rw-r--r--app/assets/javascripts/groups/constants.js6
-rw-r--r--app/assets/javascripts/groups/index.js7
-rw-r--r--app/assets/javascripts/groups/members/index.js3
-rw-r--r--app/assets/javascripts/groups/new_group_child.js65
-rw-r--r--app/assets/javascripts/header.js24
-rw-r--r--app/assets/javascripts/helpers/startup_css_helper.js14
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/form.vue26
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list.vue12
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue103
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_item.vue7
-rw-r--r--app/assets/javascripts/ide/components/file_row_extra.vue7
-rw-r--r--app/assets/javascripts/ide/components/ide.vue74
-rw-r--r--app/assets/javascripts/ide/components/ide_side_bar.vue10
-rw-r--r--app/assets/javascripts/ide/components/ide_status_list.vue7
-rw-r--r--app/assets/javascripts/ide/components/ide_tree.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide_tree_list.vue11
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail.vue9
-rw-r--r--app/assets/javascripts/ide/components/jobs/item.vue6
-rw-r--r--app/assets/javascripts/ide/components/mr_file_icon.vue7
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/button.vue7
-rw-r--r--app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue4
-rw-r--r--app/assets/javascripts/ide/components/pipelines/list.vue36
-rw-r--r--app/assets/javascripts/ide/components/repo_commit_section.vue5
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue45
-rw-r--r--app/assets/javascripts/ide/components/repo_file_status_icon.vue7
-rw-r--r--app/assets/javascripts/ide/components/repo_tab.vue4
-rw-r--r--app/assets/javascripts/ide/components/terminal/empty_state.vue22
-rw-r--r--app/assets/javascripts/ide/stores/actions.js4
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js24
-rw-r--r--app/assets/javascripts/ide/stores/index.js11
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/getters.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/editor/actions.js19
-rw-r--r--app/assets/javascripts/ide/stores/modules/editor/getters.js13
-rw-r--r--app/assets/javascripts/ide/stores/modules/editor/index.js12
-rw-r--r--app/assets/javascripts/ide/stores/modules/editor/mutation_types.js3
-rw-r--r--app/assets/javascripts/ide/stores/modules/editor/mutations.js25
-rw-r--r--app/assets/javascripts/ide/stores/modules/editor/setup.js19
-rw-r--r--app/assets/javascripts/ide/stores/modules/editor/state.js8
-rw-r--r--app/assets/javascripts/ide/stores/modules/editor/utils.js11
-rw-r--r--app/assets/javascripts/ide/stores/mutation_types.js3
-rw-r--r--app/assets/javascripts/ide/stores/mutations/file.js16
-rw-r--r--app/assets/javascripts/ide/stores/utils.js6
-rw-r--r--app/assets/javascripts/ide/utils.js2
-rw-r--r--app/assets/javascripts/import_projects/store/actions.js21
-rw-r--r--app/assets/javascripts/importer_status.js4
-rw-r--r--app/assets/javascripts/incidents/components/incidents_list.vue24
-rw-r--r--app/assets/javascripts/integrations/edit/components/confirmation_modal.vue6
-rw-r--r--app/assets/javascripts/integrations/edit/components/integration_form.vue41
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue7
-rw-r--r--app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue61
-rw-r--r--app/assets/javascripts/integrations/edit/index.js2
-rw-r--r--app/assets/javascripts/integrations/edit/store/actions.js2
-rw-r--r--app/assets/javascripts/integrations/edit/store/getters.js2
-rw-r--r--app/assets/javascripts/integrations/edit/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/integrations/edit/store/mutations.js3
-rw-r--r--app/assets/javascripts/integrations/edit/store/state.js1
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue85
-rw-r--r--app/assets/javascripts/invite_members/components/members_token_select.vue120
-rw-r--r--app/assets/javascripts/invite_members/constants.js1
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_modal.js1
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_bulk_edit_sidebar.vue35
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_item.vue124
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_list_root.vue153
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_tabs.vue5
-rw-r--r--app/assets/javascripts/issuable_list/constants.js51
-rw-r--r--app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue1
-rw-r--r--app/assets/javascripts/issue.js8
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue34
-rw-r--r--app/assets/javascripts/issue_show/components/header_actions.vue281
-rw-r--r--app/assets/javascripts/issue_show/constants.js11
-rw-r--r--app/assets/javascripts/issue_show/issue.js58
-rw-r--r--app/assets/javascripts/issue_show/queries/promote_to_epic.mutation.graphql8
-rw-r--r--app/assets/javascripts/issue_show/queries/update_issue.mutation.graphql5
-rw-r--r--app/assets/javascripts/issues_list/components/issuable.vue6
-rw-r--r--app/assets/javascripts/issues_list/index.js5
-rw-r--r--app/assets/javascripts/jira_connect/.eslintrc.yml5
-rw-r--r--app/assets/javascripts/jira_connect/components/app.vue7
-rw-r--r--app/assets/javascripts/jira_connect/index.js15
-rw-r--r--app/assets/javascripts/jobs/components/job_retry_forward_deployment_modal.vue66
-rw-r--r--app/assets/javascripts/jobs/components/job_sidebar_retry_button.vue45
-rw-r--r--app/assets/javascripts/jobs/components/jobs_container.vue2
-rw-r--r--app/assets/javascripts/jobs/components/log/line.vue51
-rw-r--r--app/assets/javascripts/jobs/components/sidebar.vue174
-rw-r--r--app/assets/javascripts/jobs/components/sidebar_job_details_container.vue102
-rw-r--r--app/assets/javascripts/jobs/components/stages_dropdown.vue29
-rw-r--r--app/assets/javascripts/jobs/constants.js24
-rw-r--r--app/assets/javascripts/jobs/index.js32
-rw-r--r--app/assets/javascripts/jobs/store/getters.js5
-rw-r--r--app/assets/javascripts/jobs/utils.js4
-rw-r--r--app/assets/javascripts/lib/ace.js4
-rw-r--r--app/assets/javascripts/lib/ace/ace_config_paths.js.erb34
-rw-r--r--app/assets/javascripts/lib/graphql.js3
-rw-r--r--app/assets/javascripts/lib/utils/ace_utils.js6
-rw-r--r--app/assets/javascripts/lib/utils/apollo_startup_js_link.js106
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js21
-rw-r--r--app/assets/javascripts/lib/utils/constants.js1
-rw-r--r--app/assets/javascripts/lib/utils/css_utils.js2
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js4
-rw-r--r--app/assets/javascripts/lib/utils/dom_utils.js22
-rw-r--r--app/assets/javascripts/lib/utils/http_status.js1
-rw-r--r--app/assets/javascripts/lib/utils/number_utils.js14
-rw-r--r--app/assets/javascripts/lib/utils/text_utility.js12
-rw-r--r--app/assets/javascripts/main.js11
-rw-r--r--app/assets/javascripts/merge_conflicts/components/diff_file_editor.js38
-rw-r--r--app/assets/javascripts/milestones/components/milestone_combobox.vue250
-rw-r--r--app/assets/javascripts/milestones/components/milestone_results_section.vue93
-rw-r--r--app/assets/javascripts/milestones/project_milestone_combobox.vue249
-rw-r--r--app/assets/javascripts/milestones/stores/actions.js61
-rw-r--r--app/assets/javascripts/milestones/stores/getters.js4
-rw-r--r--app/assets/javascripts/milestones/stores/mutation_types.js8
-rw-r--r--app/assets/javascripts/milestones/stores/mutations.js30
-rw-r--r--app/assets/javascripts/milestones/stores/state.js8
-rw-r--r--app/assets/javascripts/monitoring/components/charts/column.vue10
-rw-r--r--app/assets/javascripts/monitoring/components/charts/stacked_column.vue21
-rw-r--r--app/assets/javascripts/monitoring/components/charts/time_series.vue8
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue4
-rw-r--r--app/assets/javascripts/monitoring/components/embeds/embed_group.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/variables/dropdown_field.vue17
-rw-r--r--app/assets/javascripts/notebook/cells/output/html.vue2
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue9
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue6
-rw-r--r--app/assets/javascripts/notes/components/discussion_actions.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter.vue5
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter_note.vue42
-rw-r--r--app/assets/javascripts/notes/components/discussion_notes.vue2
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue118
-rw-r--r--app/assets/javascripts/notes/components/note_actions/reply_button.vue2
-rw-r--r--app/assets/javascripts/notes/components/note_attachment.vue7
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue8
-rw-r--r--app/assets/javascripts/notes/components/note_header.vue28
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue13
-rw-r--r--app/assets/javascripts/notes/components/toggle_replies_widget.vue12
-rw-r--r--app/assets/javascripts/notes/mixins/resolvable.js13
-rw-r--r--app/assets/javascripts/notes/stores/actions.js2
-rw-r--r--app/assets/javascripts/notes/stores/mutations.js38
-rw-r--r--app/assets/javascripts/notifications_form.js19
-rw-r--r--app/assets/javascripts/packages/details/components/package_title.vue35
-rw-r--r--app/assets/javascripts/pages/admin/admin.js16
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/general/index.js20
-rw-r--r--app/assets/javascripts/pages/admin/dev_ops_report/index.js30
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue23
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/index.js11
-rw-r--r--app/assets/javascripts/pages/admin/runners/index.js13
-rw-r--r--app/assets/javascripts/pages/admin/users/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/boards/index.js8
-rw-r--r--app/assets/javascripts/pages/groups/clusters/destroy/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/clusters/edit/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/clusters/index.js6
-rw-r--r--app/assets/javascripts/pages/groups/clusters/index/index.js8
-rw-r--r--app/assets/javascripts/pages/groups/clusters/new/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/clusters/show/index.js6
-rw-r--r--app/assets/javascripts/pages/groups/dependency_proxies/index.js13
-rw-r--r--app/assets/javascripts/pages/groups/details/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/group_members/index.js61
-rw-r--r--app/assets/javascripts/pages/groups/labels/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/labels/index/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/labels/new/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/merge_requests/index.js18
-rw-r--r--app/assets/javascripts/pages/groups/milestones/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/milestones/new/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/new/index.js16
-rw-r--r--app/assets/javascripts/pages/groups/packages/index/index.js8
-rw-r--r--app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js38
-rw-r--r--app/assets/javascripts/pages/groups/shared/group_details.js5
-rw-r--r--app/assets/javascripts/pages/profiles/preferences/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/alert_management/details/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/alert_management/index/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js32
-rw-r--r--app/assets/javascripts/pages/projects/ci/lints/new/index.js17
-rw-r--r--app/assets/javascripts/pages/projects/ci/lints/show/index.js18
-rw-r--r--app/assets/javascripts/pages/projects/ci/pipeline_editor/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/commit/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/error_tracking/details/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/error_tracking/index/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/graphs/charts/index.js14
-rw-r--r--app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue4
-rw-r--r--app/assets/javascripts/pages/projects/incidents/index/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/incidents/show/index.js12
-rw-r--r--app/assets/javascripts/pages/projects/integrations/jira/issues/index/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/issues/show.js5
-rw-r--r--app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue24
-rw-r--r--app/assets/javascripts/pages/projects/labels/index/index.js102
-rw-r--r--app/assets/javascripts/pages/projects/metrics_dashboard/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js34
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue23
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/show/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/project.js31
-rw-r--r--app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js59
-rw-r--r--app/assets/javascripts/pages/projects/settings/integrations/show/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/settings/operations/show/index.js18
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue25
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js1
-rw-r--r--app/assets/javascripts/pages/projects/show/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/terraform/index/index.js3
-rw-r--r--app/assets/javascripts/pages/search/show/index.js4
-rw-r--r--app/assets/javascripts/pages/search/show/search.js36
-rw-r--r--app/assets/javascripts/pages/shared/mount_runner_instructions.js32
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue49
-rw-r--r--app/assets/javascripts/pages/shared/wikis/wikis.js7
-rw-r--r--app/assets/javascripts/pages/users/activity_calendar.js11
-rw-r--r--app/assets/javascripts/pages/users/index.js5
-rw-r--r--app/assets/javascripts/pages/users/user_tabs.js17
-rw-r--r--app/assets/javascripts/performance/constants.js45
-rw-r--r--app/assets/javascripts/performance/utils.js (renamed from app/assets/javascripts/performance_utils.js)0
-rw-r--r--app/assets/javascripts/performance/vue_performance_plugin.js53
-rw-r--r--app/assets/javascripts/performance_bar/components/detailed_metric.vue64
-rw-r--r--app/assets/javascripts/performance_bar/performance_bar_log.js2
-rw-r--r--app/assets/javascripts/performance_constants.js31
-rw-r--r--app/assets/javascripts/persistent_user_callouts.js1
-rw-r--r--app/assets/javascripts/pipeline_editor/components/text_editor.vue26
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql5
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/resolvers.js16
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql7
-rw-r--r--app/assets/javascripts/pipeline_editor/index.js34
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue108
-rw-r--r--app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue11
-rw-r--r--app/assets/javascripts/pipelines/components/dag/dag.vue21
-rw-r--r--app/assets/javascripts/pipelines/components/graph/constants.js3
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue73
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue11
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue27
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue15
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue72
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue28
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/stage_pill.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue9
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/stage.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue1
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue67
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_reports.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue39
-rw-r--r--app/assets/javascripts/pipelines/graphql/mutations/cancel_pipeline.mutation.graphql5
-rw-r--r--app/assets/javascripts/pipelines/graphql/mutations/delete_pipeline.mutation.graphql5
-rw-r--r--app/assets/javascripts/pipelines/graphql/mutations/retry_pipeline.mutation.graphql5
-rw-r--r--app/assets/javascripts/pipelines/mixins/graph_pipeline_bundle_mixin.js6
-rw-r--r--app/assets/javascripts/pipelines/mixins/stage_column_mixin.js4
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js58
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_dag.js18
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_graph.js7
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_header.js6
-rw-r--r--app/assets/javascripts/popovers/components/popovers.vue92
-rw-r--r--app/assets/javascripts/popovers/index.js51
-rw-r--r--app/assets/javascripts/profile/account/components/update_username.vue44
-rw-r--r--app/assets/javascripts/profile/preferences/components/integration_view.vue81
-rw-r--r--app/assets/javascripts/profile/preferences/components/profile_preferences.vue56
-rw-r--r--app/assets/javascripts/profile/preferences/profile_preferences_bundle.js23
-rw-r--r--app/assets/javascripts/projects/commit_box/info/index.js3
-rw-r--r--app/assets/javascripts/projects/commit_box/info/init_details_button.js11
-rw-r--r--app/assets/javascripts/projects/components/project_delete_button.vue2
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/app.vue11
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue54
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/index.js2
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue33
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue25
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/index.js4
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js4
-rw-r--r--app/assets/javascripts/prometheus_metrics/prometheus_metrics.js17
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue8
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue6
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/cli_commands.vue13
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue13
-rw-r--r--app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue4
-rw-r--r--app/assets/javascripts/registry/explorer/constants/details.js4
-rw-r--r--app/assets/javascripts/registry/explorer/pages/details.vue30
-rw-r--r--app/assets/javascripts/registry/explorer/router.js3
-rw-r--r--app/assets/javascripts/registry/explorer/stores/actions.js43
-rw-r--r--app/assets/javascripts/registry/explorer/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/registry/explorer/stores/mutations.js4
-rw-r--r--app/assets/javascripts/registry/explorer/stores/state.js1
-rw-r--r--app/assets/javascripts/registry/explorer/utils.js17
-rw-r--r--app/assets/javascripts/registry/settings/components/settings_form.vue3
-rw-r--r--app/assets/javascripts/registry/shared/constants.js2
-rw-r--r--app/assets/javascripts/related_issues/components/issue_token.vue11
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_block.vue4
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_list.vue12
-rw-r--r--app/assets/javascripts/releases/components/app_edit_new.vue7
-rw-r--r--app/assets/javascripts/releases/components/app_index.vue26
-rw-r--r--app/assets/javascripts/releases/components/issuable_stats.vue97
-rw-r--r--app/assets/javascripts/releases/components/release_block.vue7
-rw-r--r--app/assets/javascripts/releases/components/release_block_milestone_info.vue150
-rw-r--r--app/assets/javascripts/releases/components/releases_sort.vue62
-rw-r--r--app/assets/javascripts/releases/components/tag_field_existing.vue20
-rw-r--r--app/assets/javascripts/releases/constants.js18
-rw-r--r--app/assets/javascripts/releases/queries/all_releases.query.graphql11
-rw-r--r--app/assets/javascripts/releases/queries/release.fragment.graphql8
-rw-r--r--app/assets/javascripts/releases/stores/modules/detail/state.js6
-rw-r--r--app/assets/javascripts/releases/stores/modules/list/actions.js11
-rw-r--r--app/assets/javascripts/releases/stores/modules/list/mutation_types.js1
-rw-r--r--app/assets/javascripts/releases/stores/modules/list/mutations.js4
-rw-r--r--app/assets/javascripts/releases/stores/modules/list/state.js6
-rw-r--r--app/assets/javascripts/releases/util.js4
-rw-r--r--app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue44
-rw-r--r--app/assets/javascripts/reports/codequality_report/constants.js17
-rw-r--r--app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue1
-rw-r--r--app/assets/javascripts/reports/codequality_report/store/getters.js3
-rw-r--r--app/assets/javascripts/reports/components/grouped_test_reports_app.vue45
-rw-r--r--app/assets/javascripts/reports/components/report_section.vue5
-rw-r--r--app/assets/javascripts/reports/components/test_issue_body.vue24
-rw-r--r--app/assets/javascripts/reports/store/mutations.js8
-rw-r--r--app/assets/javascripts/reports/store/utils.js42
-rw-r--r--app/assets/javascripts/repository/components/breadcrumbs.vue2
-rw-r--r--app/assets/javascripts/repository/components/last_commit.vue4
-rw-r--r--app/assets/javascripts/repository/components/preview/index.vue2
-rw-r--r--app/assets/javascripts/repository/components/tree_action_link.vue2
-rw-r--r--app/assets/javascripts/repository/components/tree_content.vue2
-rw-r--r--app/assets/javascripts/repository/index.js28
-rw-r--r--app/assets/javascripts/repository/mixins/preload.js2
-rw-r--r--app/assets/javascripts/repository/queries/files.query.graphql60
-rw-r--r--app/assets/javascripts/repository/queries/permissions.query.graphql9
-rw-r--r--app/assets/javascripts/search/dropdown_filter/components/dropdown_filter.vue100
-rw-r--r--app/assets/javascripts/search/dropdown_filter/constants/confidential_filter_data.js36
-rw-r--r--app/assets/javascripts/search/dropdown_filter/constants/state_filter_data.js42
-rw-r--r--app/assets/javascripts/search/dropdown_filter/index.js38
-rw-r--r--app/assets/javascripts/search/group_filter/components/group_filter.vue124
-rw-r--r--app/assets/javascripts/search/group_filter/constants.js10
-rw-r--r--app/assets/javascripts/search/group_filter/index.js28
-rw-r--r--app/assets/javascripts/search/highlight_blob_search_result.js (renamed from app/assets/javascripts/pages/search/show/highlight_blob_search_result.js)0
-rw-r--r--app/assets/javascripts/search/index.js13
-rw-r--r--app/assets/javascripts/search/sidebar/components/app.vue41
-rw-r--r--app/assets/javascripts/search/sidebar/components/confidentiality_filter.vue26
-rw-r--r--app/assets/javascripts/search/sidebar/components/radio_filter.vue68
-rw-r--r--app/assets/javascripts/search/sidebar/components/status_filter.vue26
-rw-r--r--app/assets/javascripts/search/sidebar/constants/confidential_filter_data.js36
-rw-r--r--app/assets/javascripts/search/sidebar/constants/state_filter_data.js42
-rw-r--r--app/assets/javascripts/search/sidebar/index.js19
-rw-r--r--app/assets/javascripts/search/store/actions.js29
-rw-r--r--app/assets/javascripts/search/store/index.js4
-rw-r--r--app/assets/javascripts/search/store/mutation_types.js5
-rw-r--r--app/assets/javascripts/search/store/mutations.js18
-rw-r--r--app/assets/javascripts/search/store/state.js2
-rw-r--r--app/assets/javascripts/serverless/components/area.vue4
-rw-r--r--app/assets/javascripts/set_status_modal/components/user_availability_status.vue26
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue63
-rw-r--r--app/assets/javascripts/set_status_modal/utils.js9
-rw-r--r--app/assets/javascripts/shared/milestones/form.js1
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignee_title.vue3
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue10
-rw-r--r--app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue100
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue12
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue7
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue9
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue5
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/help_state.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue30
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js5
-rw-r--r--app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql15
-rw-r--r--app/assets/javascripts/sidebar/utils.js1
-rw-r--r--app/assets/javascripts/single_file_diff.js7
-rw-r--r--app/assets/javascripts/snippets/components/edit.vue51
-rw-r--r--app/assets/javascripts/snippets/components/show.vue4
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_view.vue13
-rw-r--r--app/assets/javascripts/snippets/components/snippet_header.vue22
-rw-r--r--app/assets/javascripts/snippets/components/snippet_visibility_edit.vue27
-rw-r--r--app/assets/javascripts/snippets/constants.js2
-rw-r--r--app/assets/javascripts/snippets/index.js11
-rw-r--r--app/assets/javascripts/snippets/mixins/snippets.js12
-rw-r--r--app/assets/javascripts/snippets/queries/projectPermissions.query.graphql7
-rw-r--r--app/assets/javascripts/snippets/queries/snippet.blob.content.query.graphql14
-rw-r--r--app/assets/javascripts/snippets/queries/snippet.query.graphql15
-rw-r--r--app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql5
-rw-r--r--app/assets/javascripts/snippets/queries/userPermissions.query.graphql7
-rw-r--r--app/assets/javascripts/snippets/utils/blob.js4
-rw-r--r--app/assets/javascripts/static_site_editor/components/edit_area.vue50
-rw-r--r--app/assets/javascripts/static_site_editor/components/edit_meta_controls.vue100
-rw-r--r--app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue45
-rw-r--r--app/assets/javascripts/static_site_editor/constants.js3
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/index.js4
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/queries/app_data.query.graphql7
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/typedefs.graphql9
-rw-r--r--app/assets/javascripts/static_site_editor/image_repository.js4
-rw-r--r--app/assets/javascripts/static_site_editor/index.js9
-rw-r--r--app/assets/javascripts/static_site_editor/pages/home.vue10
-rw-r--r--app/assets/javascripts/static_site_editor/services/front_matterify.js2
-rw-r--r--app/assets/javascripts/static_site_editor/services/parse_source_file.js18
-rw-r--r--app/assets/javascripts/static_site_editor/services/renderers/render_image.js89
-rw-r--r--app/assets/javascripts/terraform/components/empty_state.vue44
-rw-r--r--app/assets/javascripts/terraform/components/states_table.vue101
-rw-r--r--app/assets/javascripts/terraform/components/terraform_list.vue134
-rw-r--r--app/assets/javascripts/terraform/constants.js1
-rw-r--r--app/assets/javascripts/terraform/graphql/fragments/state.fragment.graphql17
-rw-r--r--app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql9
-rw-r--r--app/assets/javascripts/terraform/graphql/queries/get_states.query.graphql18
-rw-r--r--app/assets/javascripts/terraform/index.js31
-rw-r--r--app/assets/javascripts/tooltips/components/tooltips.vue1
-rw-r--r--app/assets/javascripts/tooltips/index.js6
-rw-r--r--app/assets/javascripts/tracking.js1
-rw-r--r--app/assets/javascripts/users_select/index.js7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue157
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js27
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js30
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue16
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue13
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue14
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue86
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues.js66
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql13
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/index.js11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/actions_button.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/alert_details_table.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/awards_list.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_icon.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_modal.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row.vue15
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row_header.vue14
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue24
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/gl_mentions.vue36
-rw-r--r--app/assets/javascripts/vue_shared/components/gl_modal.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/integrations_help_text.vue35
-rw-r--r--app/assets/javascripts/vue_shared/components/local_storage_sync.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue44
-rw-r--r--app/assets/javascripts/vue_shared/components/members/action_buttons/user_action_buttons.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/members/constants.js1
-rw-r--r--app/assets/javascripts/vue_shared/components/members/table/expiration_datepicker.vue99
-rw-r--r--app/assets/javascripts/vue_shared/components/members/table/members_table.vue56
-rw-r--r--app/assets/javascripts/vue_shared/components/members/table/members_table_cell.vue13
-rw-r--r--app/assets/javascripts/vue_shared/components/members/table/role_dropdown.vue27
-rw-r--r--app/assets/javascripts/vue_shared/components/members/utils.js29
-rw-r--r--app/assets/javascripts/vue_shared/components/modal_copy_button.vue33
-rw-r--r--app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/title_area.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue25
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js23
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql20
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql16
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue220
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/issuable_move_dropdown.vue211
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue29
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql13
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql17
-rw-r--r--app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/upload_dropzone/constants.js9
-rw-r--r--app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue172
-rw-r--r--app/assets/javascripts/vue_shared/components/upload_dropzone/utils.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/web_ide_link.vue2
-rw-r--r--app/assets/javascripts/vue_shared/directives/validation.js132
-rw-r--r--app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/constants.js3
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue26
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js24
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js10
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutation_types.js4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js31
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/state.js16
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js24
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js10
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutation_types.js4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutations.js30
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/state.js16
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/utils.js75
-rw-r--r--app/assets/javascripts/vuex_shared/modules/members/actions.js19
-rw-r--r--app/assets/javascripts/vuex_shared/modules/members/index.js4
-rw-r--r--app/assets/javascripts/vuex_shared/modules/members/mutation_types.js3
-rw-r--r--app/assets/javascripts/vuex_shared/modules/members/mutations.js15
-rw-r--r--app/assets/javascripts/vuex_shared/modules/members/state.js2
-rw-r--r--app/assets/javascripts/whats_new/components/app.vue80
-rw-r--r--app/assets/javascripts/whats_new/store/actions.js33
-rw-r--r--app/assets/javascripts/whats_new/store/mutation_types.js5
-rw-r--r--app/assets/javascripts/whats_new/store/mutations.js13
-rw-r--r--app/assets/javascripts/whats_new/store/state.js7
-rw-r--r--app/assets/javascripts/whats_new/utils/get_drawer_body_height.js6
-rw-r--r--app/assets/stylesheets/_page_specific_files.scss5
-rw-r--r--app/assets/stylesheets/behaviors.scss25
-rw-r--r--app/assets/stylesheets/bootstrap_migration.scss14
-rw-r--r--app/assets/stylesheets/components/design_management/design.scss42
-rw-r--r--app/assets/stylesheets/components/severity/icons.scss27
-rw-r--r--app/assets/stylesheets/components/upload_dropzone/upload_dropzone.scss37
-rw-r--r--app/assets/stylesheets/components/whats_new.scss13
-rw-r--r--app/assets/stylesheets/fontawesome_custom.scss76
-rw-r--r--app/assets/stylesheets/framework/broadcast_messages.scss8
-rw-r--r--app/assets/stylesheets/framework/calendar.scss14
-rw-r--r--app/assets/stylesheets/framework/common.scss1
-rw-r--r--app/assets/stylesheets/framework/diffs.scss96
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss3
-rw-r--r--app/assets/stylesheets/framework/editor-lite.scss18
-rw-r--r--app/assets/stylesheets/framework/files.scss37
-rw-r--r--app/assets/stylesheets/framework/flash.scss8
-rw-r--r--app/assets/stylesheets/framework/mixins.scss32
-rw-r--r--app/assets/stylesheets/framework/modal.scss12
-rw-r--r--app/assets/stylesheets/framework/secondary_navigation_elements.scss68
-rw-r--r--app/assets/stylesheets/framework/spinner.scss14
-rw-r--r--app/assets/stylesheets/framework/typography.scss6
-rw-r--r--app/assets/stylesheets/highlight/common.scss10
-rw-r--r--app/assets/stylesheets/highlight/themes/dark.scss17
-rw-r--r--app/assets/stylesheets/highlight/themes/monokai.scss17
-rw-r--r--app/assets/stylesheets/highlight/themes/none.scss14
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-dark.scss17
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-light.scss17
-rw-r--r--app/assets/stylesheets/highlight/white_base.scss14
-rw-r--r--app/assets/stylesheets/lazy_bundles/select2.scss654
-rw-r--r--app/assets/stylesheets/lazy_bundles/select2_overrides.scss359
-rw-r--r--app/assets/stylesheets/mailer.scss17
-rw-r--r--app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss6
-rw-r--r--app/assets/stylesheets/page_bundles/alert_management_details.scss46
-rw-r--r--app/assets/stylesheets/page_bundles/alert_management_settings.scss24
-rw-r--r--app/assets/stylesheets/page_bundles/boards.scss89
-rw-r--r--app/assets/stylesheets/page_bundles/build.scss294
-rw-r--r--app/assets/stylesheets/page_bundles/ci_status.scss79
-rw-r--r--app/assets/stylesheets/page_bundles/experimental_separate_sign_up.scss96
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss14
-rw-r--r--app/assets/stylesheets/page_bundles/ide_themes/_dark.scss8
-rw-r--r--app/assets/stylesheets/page_bundles/ide_themes/_monokai.scss66
-rw-r--r--app/assets/stylesheets/page_bundles/ide_themes/_solarized-dark.scss8
-rw-r--r--app/assets/stylesheets/page_bundles/ide_themes/_solarized-light.scss57
-rw-r--r--app/assets/stylesheets/page_bundles/jira_connect.scss4
-rw-r--r--app/assets/stylesheets/page_bundles/merge_requests.scss12
-rw-r--r--app/assets/stylesheets/page_bundles/pipeline.scss4
-rw-r--r--app/assets/stylesheets/page_bundles/pipeline_schedules.scss68
-rw-r--r--app/assets/stylesheets/page_bundles/pipelines.scss4
-rw-r--r--app/assets/stylesheets/page_bundles/reports.scss6
-rw-r--r--app/assets/stylesheets/page_bundles/signup.scss75
-rw-r--r--app/assets/stylesheets/page_bundles/todos.scss1
-rw-r--r--app/assets/stylesheets/pages/admin.scss8
-rw-r--r--app/assets/stylesheets/pages/alert_management/details.scss42
-rw-r--r--app/assets/stylesheets/pages/alert_management/severity-icons.scss27
-rw-r--r--app/assets/stylesheets/pages/builds.scss349
-rw-r--r--app/assets/stylesheets/pages/commits.scss21
-rw-r--r--app/assets/stylesheets/pages/editor.scss18
-rw-r--r--app/assets/stylesheets/pages/groups.scss8
-rw-r--r--app/assets/stylesheets/pages/incident_management_list.scss27
-rw-r--r--app/assets/stylesheets/pages/issuable.scss45
-rw-r--r--app/assets/stylesheets/pages/issues.scss12
-rw-r--r--app/assets/stylesheets/pages/labels.scss147
-rw-r--r--app/assets/stylesheets/pages/members.scss7
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss17
-rw-r--r--app/assets/stylesheets/pages/note_form.scss49
-rw-r--r--app/assets/stylesheets/pages/notes.scss36
-rw-r--r--app/assets/stylesheets/pages/pipeline_schedules.scss70
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss61
-rw-r--r--app/assets/stylesheets/pages/projects.scss181
-rw-r--r--app/assets/stylesheets/pages/search.scss3
-rw-r--r--app/assets/stylesheets/pages/status.scss77
-rw-r--r--app/assets/stylesheets/pages/tree.scss2
-rw-r--r--app/assets/stylesheets/pages/users.scss37
-rw-r--r--app/assets/stylesheets/performance_bar.scss2
-rw-r--r--app/assets/stylesheets/print.scss2
-rw-r--r--app/assets/stylesheets/themes/_dark.scss18
-rw-r--r--app/assets/stylesheets/utilities.scss7
-rw-r--r--app/controllers/admin/application_settings_controller.rb12
-rw-r--r--app/controllers/admin/dashboard_controller.rb1
-rw-r--r--app/controllers/admin/instance_statistics_controller.rb2
-rw-r--r--app/controllers/admin/integrations_controller.rb4
-rw-r--r--app/controllers/admin/users_controller.rb5
-rw-r--r--app/controllers/application_controller.rb10
-rw-r--r--app/controllers/autocomplete_controller.rb2
-rw-r--r--app/controllers/clusters/clusters_controller.rb2
-rw-r--r--app/controllers/concerns/controller_with_feature_category.rb48
-rw-r--r--app/controllers/concerns/dependency_proxy_access.rb24
-rw-r--r--app/controllers/concerns/integrations_actions.rb2
-rw-r--r--app/controllers/concerns/issuable_actions.rb3
-rw-r--r--app/controllers/concerns/lfs_request.rb24
-rw-r--r--app/controllers/concerns/notes_actions.rb6
-rw-r--r--app/controllers/concerns/routable_actions.rb2
-rw-r--r--app/controllers/concerns/send_file_upload.rb11
-rw-r--r--app/controllers/concerns/sends_blob.rb1
-rw-r--r--app/controllers/concerns/snippets_actions.rb5
-rw-r--r--app/controllers/concerns/wiki_actions.rb15
-rw-r--r--app/controllers/groups/boards_controller.rb3
-rw-r--r--app/controllers/groups/dependency_proxies_controller.rb34
-rw-r--r--app/controllers/groups/dependency_proxy_for_containers_controller.rb63
-rw-r--r--app/controllers/groups/milestones_controller.rb2
-rw-r--r--app/controllers/groups/settings/ci_cd_controller.rb3
-rw-r--r--app/controllers/groups/settings/integrations_controller.rb8
-rw-r--r--app/controllers/groups_controller.rb17
-rw-r--r--app/controllers/import/base_controller.rb8
-rw-r--r--app/controllers/import/bitbucket_controller.rb4
-rw-r--r--app/controllers/import/bitbucket_server_controller.rb4
-rw-r--r--app/controllers/import/bulk_imports_controller.rb40
-rw-r--r--app/controllers/import/github_controller.rb20
-rw-r--r--app/controllers/invites_controller.rb16
-rw-r--r--app/controllers/jwks_controller.rb26
-rw-r--r--app/controllers/profiles/personal_access_tokens_controller.rb8
-rw-r--r--app/controllers/profiles_controller.rb2
-rw-r--r--app/controllers/projects/alert_management_controller.rb1
-rw-r--r--app/controllers/projects/alerting/notifications_controller.rb14
-rw-r--r--app/controllers/projects/autocomplete_sources_controller.rb2
-rw-r--r--app/controllers/projects/avatars_controller.rb2
-rw-r--r--app/controllers/projects/blob_controller.rb2
-rw-r--r--app/controllers/projects/boards_controller.rb3
-rw-r--r--app/controllers/projects/branches_controller.rb13
-rw-r--r--app/controllers/projects/ci/lints_controller.rb20
-rw-r--r--app/controllers/projects/ci/pipeline_editor_controller.rb17
-rw-r--r--app/controllers/projects/imports_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb7
-rw-r--r--app/controllers/projects/jobs_controller.rb3
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb18
-rw-r--r--app/controllers/projects/merge_requests_controller.rb18
-rw-r--r--app/controllers/projects/milestones_controller.rb2
-rw-r--r--app/controllers/projects/notes_controller.rb2
-rw-r--r--app/controllers/projects/pipelines_controller.rb7
-rw-r--r--app/controllers/projects/raw_controller.rb3
-rw-r--r--app/controllers/projects/releases_controller.rb2
-rw-r--r--app/controllers/projects/repositories_controller.rb2
-rw-r--r--app/controllers/projects/runners_controller.rb2
-rw-r--r--app/controllers/projects/services_controller.rb4
-rw-r--r--app/controllers/projects/settings/access_tokens_controller.rb2
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb9
-rw-r--r--app/controllers/projects/settings/operations_controller.rb5
-rw-r--r--app/controllers/projects/settings/repository_controller.rb7
-rw-r--r--app/controllers/projects/static_site_editor_controller.rb12
-rw-r--r--app/controllers/projects/tags_controller.rb1
-rw-r--r--app/controllers/projects/templates_controller.rb8
-rw-r--r--app/controllers/projects/terraform_controller.rb16
-rw-r--r--app/controllers/projects_controller.rb32
-rw-r--r--app/controllers/registrations/welcome_controller.rb73
-rw-r--r--app/controllers/registrations_controller.rb88
-rw-r--r--app/controllers/repositories/git_http_client_controller.rb8
-rw-r--r--app/controllers/repositories/lfs_api_controller.rb5
-rw-r--r--app/controllers/repositories/lfs_storage_controller.rb20
-rw-r--r--app/controllers/search_controller.rb37
-rw-r--r--app/controllers/sessions_controller.rb8
-rw-r--r--app/controllers/whats_new_controller.rb23
-rw-r--r--app/finders/alert_management/http_integrations_finder.rb54
-rw-r--r--app/finders/ci/commit_statuses_finder.rb40
-rw-r--r--app/finders/ci/jobs_finder.rb16
-rw-r--r--app/finders/concerns/finder_with_cross_project_access.rb2
-rw-r--r--app/finders/environment_names_finder.rb18
-rw-r--r--app/finders/feature_flags_user_lists_finder.rb34
-rw-r--r--app/finders/group_projects_finder.rb1
-rw-r--r--app/finders/issuable_finder.rb13
-rw-r--r--app/finders/issues_finder.rb2
-rw-r--r--app/finders/merge_requests_finder.rb30
-rw-r--r--app/finders/packages/group_packages_finder.rb9
-rw-r--r--app/finders/packages/npm/package_finder.rb2
-rw-r--r--app/finders/personal_access_tokens_finder.rb7
-rw-r--r--app/finders/security/jobs_finder.rb71
-rw-r--r--app/finders/security/license_compliance_jobs_finder.rb18
-rw-r--r--app/finders/security/security_jobs_finder.rb19
-rw-r--r--app/finders/user_groups_counter.rb30
-rw-r--r--app/graphql/gitlab_schema.rb9
-rw-r--r--app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb6
-rw-r--r--app/graphql/mutations/alert_management/base.rb8
-rw-r--r--app/graphql/mutations/alert_management/http_integration/create.rb41
-rw-r--r--app/graphql/mutations/alert_management/http_integration/destroy.rb24
-rw-r--r--app/graphql/mutations/alert_management/http_integration/http_integration_base.rb29
-rw-r--r--app/graphql/mutations/alert_management/http_integration/reset_token.rb25
-rw-r--r--app/graphql/mutations/alert_management/http_integration/update.rb33
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/create.rb50
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb42
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb27
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/update.rb35
-rw-r--r--app/graphql/mutations/alert_management/update_alert_status.rb6
-rw-r--r--app/graphql/mutations/boards/create.rb37
-rw-r--r--app/graphql/mutations/boards/lists/update.rb2
-rw-r--r--app/graphql/mutations/commits/create.rb10
-rw-r--r--app/graphql/mutations/concerns/mutations/package_eventable.rb14
-rw-r--r--app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb43
-rw-r--r--app/graphql/mutations/container_repositories/destroy.rb45
-rw-r--r--app/graphql/mutations/custom_emoji/create.rb50
-rw-r--r--app/graphql/mutations/labels/create.rb43
-rw-r--r--app/graphql/mutations/merge_requests/set_labels.rb15
-rw-r--r--app/graphql/mutations/metrics/dashboard/annotations/delete.rb3
-rw-r--r--app/graphql/mutations/notes/reposition_image_diff_note.rb65
-rw-r--r--app/graphql/mutations/notes/update/image_diff_note.rb5
-rw-r--r--app/graphql/mutations/releases/base.rb19
-rw-r--r--app/graphql/mutations/releases/create.rb68
-rw-r--r--app/graphql/mutations/snippets/destroy.rb3
-rw-r--r--app/graphql/mutations/snippets/mark_as_spam.rb3
-rw-r--r--app/graphql/mutations/snippets/update.rb3
-rw-r--r--app/graphql/mutations/terraform/state/base.rb22
-rw-r--r--app/graphql/mutations/terraform/state/delete.rb18
-rw-r--r--app/graphql/mutations/terraform/state/lock.rb29
-rw-r--r--app/graphql/mutations/terraform/state/unlock.rb18
-rw-r--r--app/graphql/mutations/todos/base.rb10
-rw-r--r--app/graphql/mutations/todos/create.rb39
-rw-r--r--app/graphql/mutations/todos/mark_all_done.rb4
-rw-r--r--app/graphql/mutations/todos/restore_many.rb8
-rw-r--r--app/graphql/queries/design_management/design_permissions.query.graphql13
-rw-r--r--app/graphql/queries/design_management/get_design_list.query.graphql40
-rw-r--r--app/graphql/queries/repository/files.query.graphql76
-rw-r--r--app/graphql/queries/repository/permissions.query.graphql11
-rw-r--r--app/graphql/queries/snippet/project_permissions.query.graphql9
-rw-r--r--app/graphql/queries/snippet/snippet.query.graphql65
-rw-r--r--app/graphql/queries/snippet/snippet_blob_content.query.graphql18
-rw-r--r--app/graphql/queries/snippet/user_permissions.query.graphql9
-rw-r--r--app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb12
-rw-r--r--app/graphql/resolvers/alert_management/alert_resolver.rb2
-rw-r--r--app/graphql/resolvers/alert_management/alert_status_counts_resolver.rb2
-rw-r--r--app/graphql/resolvers/alert_management/integrations_resolver.rb29
-rw-r--r--app/graphql/resolvers/assigned_merge_requests_resolver.rb3
-rw-r--r--app/graphql/resolvers/authored_merge_requests_resolver.rb3
-rw-r--r--app/graphql/resolvers/base_resolver.rb86
-rw-r--r--app/graphql/resolvers/board_lists_resolver.rb2
-rw-r--r--app/graphql/resolvers/boards_resolver.rb11
-rw-r--r--app/graphql/resolvers/ci/jobs_resolver.rb24
-rw-r--r--app/graphql/resolvers/ci/runner_setup_resolver.rb64
-rw-r--r--app/graphql/resolvers/commit_pipelines_resolver.rb3
-rw-r--r--app/graphql/resolvers/concerns/caching_array_resolver.rb128
-rw-r--r--app/graphql/resolvers/concerns/issue_resolver_arguments.rb2
-rw-r--r--app/graphql/resolvers/concerns/looks_ahead.rb1
-rw-r--r--app/graphql/resolvers/concerns/resolves_pipelines.rb2
-rw-r--r--app/graphql/resolvers/concerns/resolves_project.rb3
-rw-r--r--app/graphql/resolvers/concerns/resolves_snippets.rb21
-rw-r--r--app/graphql/resolvers/container_repositories_resolver.rb19
-rw-r--r--app/graphql/resolvers/design_management/design_at_version_resolver.rb9
-rw-r--r--app/graphql/resolvers/design_management/design_resolver.rb10
-rw-r--r--app/graphql/resolvers/design_management/designs_resolver.rb29
-rw-r--r--app/graphql/resolvers/design_management/version/design_at_version_resolver.rb22
-rw-r--r--app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb18
-rw-r--r--app/graphql/resolvers/design_management/version_in_collection_resolver.rb15
-rw-r--r--app/graphql/resolvers/design_management/version_resolver.rb8
-rw-r--r--app/graphql/resolvers/design_management/versions_resolver.rb20
-rw-r--r--app/graphql/resolvers/echo_resolver.rb7
-rw-r--r--app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb13
-rw-r--r--app/graphql/resolvers/error_tracking/sentry_error_collection_resolver.rb2
-rw-r--r--app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb10
-rw-r--r--app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb2
-rw-r--r--app/graphql/resolvers/group_issues_resolver.rb1
-rw-r--r--app/graphql/resolvers/group_members_resolver.rb2
-rw-r--r--app/graphql/resolvers/group_merge_requests_resolver.rb2
-rw-r--r--app/graphql/resolvers/group_milestones_resolver.rb3
-rw-r--r--app/graphql/resolvers/issues_resolver.rb2
-rw-r--r--app/graphql/resolvers/members_resolver.rb2
-rw-r--r--app/graphql/resolvers/merge_request_pipelines_resolver.rb3
-rw-r--r--app/graphql/resolvers/merge_request_resolver.rb2
-rw-r--r--app/graphql/resolvers/metadata_resolver.rb2
-rw-r--r--app/graphql/resolvers/milestones_resolver.rb2
-rw-r--r--app/graphql/resolvers/namespace_projects_resolver.rb9
-rw-r--r--app/graphql/resolvers/project_members_resolver.rb3
-rw-r--r--app/graphql/resolvers/project_merge_requests_resolver.rb1
-rw-r--r--app/graphql/resolvers/project_milestones_resolver.rb3
-rw-r--r--app/graphql/resolvers/project_pipeline_resolver.rb2
-rw-r--r--app/graphql/resolvers/project_pipelines_resolver.rb19
-rw-r--r--app/graphql/resolvers/projects/jira_imports_resolver.rb2
-rw-r--r--app/graphql/resolvers/projects/jira_projects_resolver.rb2
-rw-r--r--app/graphql/resolvers/projects/services_resolver.rb2
-rw-r--r--app/graphql/resolvers/projects/snippets_resolver.rb1
-rw-r--r--app/graphql/resolvers/releases_resolver.rb16
-rw-r--r--app/graphql/resolvers/snippets/blobs_resolver.rb2
-rw-r--r--app/graphql/resolvers/snippets_resolver.rb11
-rw-r--r--app/graphql/resolvers/todo_resolver.rb2
-rw-r--r--app/graphql/resolvers/tree_resolver.rb2
-rw-r--r--app/graphql/resolvers/user_merge_requests_resolver.rb68
-rw-r--r--app/graphql/resolvers/user_merge_requests_resolver_base.rb70
-rw-r--r--app/graphql/resolvers/user_resolver.rb2
-rw-r--r--app/graphql/resolvers/users/group_count_resolver.rb25
-rw-r--r--app/graphql/resolvers/users/snippets_resolver.rb1
-rw-r--r--app/graphql/resolvers/users_resolver.rb12
-rw-r--r--app/graphql/types/alert_management/http_integration_type.rb22
-rw-r--r--app/graphql/types/alert_management/integration_type.rb58
-rw-r--r--app/graphql/types/alert_management/integration_type_enum.rb13
-rw-r--r--app/graphql/types/alert_management/prometheus_integration_type.rb38
-rw-r--r--app/graphql/types/availability_enum.rb12
-rw-r--r--app/graphql/types/base_object.rb14
-rw-r--r--app/graphql/types/board_type.rb2
-rw-r--r--app/graphql/types/ci/detailed_status_type.rb2
-rw-r--r--app/graphql/types/ci/job_type.rb3
-rw-r--r--app/graphql/types/ci/pipeline_type.rb40
-rw-r--r--app/graphql/types/ci/runner_setup_type.rb15
-rw-r--r--app/graphql/types/commit_type.rb9
-rw-r--r--app/graphql/types/container_repository_cleanup_status_enum.rb13
-rw-r--r--app/graphql/types/container_repository_details_type.rb21
-rw-r--r--app/graphql/types/container_repository_status_enum.rb12
-rw-r--r--app/graphql/types/container_repository_tag_type.rb25
-rw-r--r--app/graphql/types/container_repository_type.rb27
-rw-r--r--app/graphql/types/countable_connection_type.rb2
-rw-r--r--app/graphql/types/custom_emoji_type.rb27
-rw-r--r--app/graphql/types/environment_type.rb5
-rw-r--r--app/graphql/types/global_id_type.rb2
-rw-r--r--app/graphql/types/grafana_integration_type.rb8
-rw-r--r--app/graphql/types/group_invitation_type.rb17
-rw-r--r--app/graphql/types/group_type.rb13
-rw-r--r--app/graphql/types/invitation_interface.rb41
-rw-r--r--app/graphql/types/issue_connection_type.rb9
-rw-r--r--app/graphql/types/issue_type.rb53
-rw-r--r--app/graphql/types/merge_request_type.rb26
-rw-r--r--app/graphql/types/mutation_type.rb16
-rw-r--r--app/graphql/types/notes/update_diff_image_position_input_type.rb8
-rw-r--r--app/graphql/types/permission_types/custom_emoji.rb11
-rw-r--r--app/graphql/types/permission_types/note.rb2
-rw-r--r--app/graphql/types/project_invitation_type.rb21
-rw-r--r--app/graphql/types/project_statistics_type.rb16
-rw-r--r--app/graphql/types/project_type.rb15
-rw-r--r--app/graphql/types/projects/namespace_project_sort_enum.rb1
-rw-r--r--app/graphql/types/projects/service_type_enum.rb2
-rw-r--r--app/graphql/types/query_type.rb23
-rw-r--r--app/graphql/types/release_asset_link_input_type.rb25
-rw-r--r--app/graphql/types/release_asset_link_type.rb6
-rw-r--r--app/graphql/types/release_asset_link_type_enum.rb2
-rw-r--r--app/graphql/types/release_assets_input_type.rb13
-rw-r--r--app/graphql/types/release_links_type.rb14
-rw-r--r--app/graphql/types/release_sort_enum.rb18
-rw-r--r--app/graphql/types/root_storage_statistics_type.rb1
-rw-r--r--app/graphql/types/security/report_type_enum.rb15
-rw-r--r--app/graphql/types/snippet_type.rb2
-rw-r--r--app/graphql/types/terraform/state_type.rb7
-rw-r--r--app/graphql/types/terraform/state_version_type.rb35
-rw-r--r--app/graphql/types/user_status_type.rb2
-rw-r--r--app/graphql/types/user_type.rb8
-rw-r--r--app/helpers/application_settings_helper.rb20
-rw-r--r--app/helpers/auth_helper.rb7
-rw-r--r--app/helpers/blob_helper.rb25
-rw-r--r--app/helpers/branches_helper.rb6
-rw-r--r--app/helpers/breadcrumbs_helper.rb49
-rw-r--r--app/helpers/ci/jobs_helper.rb3
-rw-r--r--app/helpers/ci/pipeline_editor_helper.rb12
-rw-r--r--app/helpers/ci/runners_helper.rb8
-rw-r--r--app/helpers/commits_helper.rb2
-rw-r--r--app/helpers/defer_script_tag_helper.rb4
-rw-r--r--app/helpers/diff_helper.rb30
-rw-r--r--app/helpers/dropdowns_helper.rb5
-rw-r--r--app/helpers/emails_helper.rb18
-rw-r--r--app/helpers/gitlab_routing_helper.rb16
-rw-r--r--app/helpers/gitpod_helper.rb5
-rw-r--r--app/helpers/groups_helper.rb17
-rw-r--r--app/helpers/icons_helper.rb65
-rw-r--r--app/helpers/invite_members_helper.rb4
-rw-r--r--app/helpers/issuables_helper.rb26
-rw-r--r--app/helpers/issues_helper.rb23
-rw-r--r--app/helpers/notes_helper.rb1
-rw-r--r--app/helpers/notifications_helper.rb1
-rw-r--r--app/helpers/operations_helper.rb4
-rw-r--r--app/helpers/page_layout_helper.rb51
-rw-r--r--app/helpers/preferences_helper.rb4
-rw-r--r--app/helpers/profiles_helper.rb14
-rw-r--r--app/helpers/projects/terraform_helper.rb10
-rw-r--r--app/helpers/projects_helper.rb45
-rw-r--r--app/helpers/recaptcha_experiment_helper.rb9
-rw-r--r--app/helpers/recaptcha_helper.rb7
-rw-r--r--app/helpers/releases_helper.rb9
-rw-r--r--app/helpers/search_helper.rb102
-rw-r--r--app/helpers/services_helper.rb12
-rw-r--r--app/helpers/sorting_helper.rb29
-rw-r--r--app/helpers/sourcegraph_helper.rb26
-rw-r--r--app/helpers/stat_anchors_helper.rb24
-rw-r--r--app/helpers/suggest_pipeline_helper.rb2
-rw-r--r--app/helpers/time_helper.rb4
-rw-r--r--app/helpers/tree_helper.rb20
-rw-r--r--app/helpers/user_callouts_helper.rb5
-rw-r--r--app/helpers/users_helper.rb63
-rw-r--r--app/helpers/visibility_level_helper.rb4
-rw-r--r--app/helpers/whats_new_helper.rb6
-rw-r--r--app/mailers/devise_mailer.rb4
-rw-r--r--app/mailers/emails/members.rb51
-rw-r--r--app/mailers/emails/profile.rb26
-rw-r--r--app/mailers/emails/projects.rb9
-rw-r--r--app/mailers/emails/service_desk.rb6
-rw-r--r--app/mailers/previews/devise_mailer_preview.rb4
-rw-r--r--app/models/alert_management/alert.rb2
-rw-r--r--app/models/alert_management/http_integration.rb44
-rw-r--r--app/models/analytics/devops_adoption.rb6
-rw-r--r--app/models/analytics/devops_adoption/segment.rb24
-rw-r--r--app/models/analytics/devops_adoption/segment_selection.rb36
-rw-r--r--app/models/analytics/instance_statistics/measurement.rb50
-rw-r--r--app/models/application_record.rb2
-rw-r--r--app/models/application_setting.rb21
-rw-r--r--app/models/application_setting_implementation.rb53
-rw-r--r--app/models/audit_event.rb11
-rw-r--r--app/models/authentication_event.rb8
-rw-r--r--app/models/broadcast_message.rb1
-rw-r--r--app/models/bulk_import.rb18
-rw-r--r--app/models/bulk_imports/configuration.rb2
-rw-r--r--app/models/bulk_imports/entity.rb46
-rw-r--r--app/models/bulk_imports/tracker.rb18
-rw-r--r--app/models/ci/bridge.rb6
-rw-r--r--app/models/ci/build.rb24
-rw-r--r--app/models/ci/build_trace_chunk.rb55
-rw-r--r--app/models/ci/build_trace_chunks/legacy_fog.rb77
-rw-r--r--app/models/ci/daily_build_group_report_result.rb28
-rw-r--r--app/models/ci/job_artifact.rb1
-rw-r--r--app/models/ci/pipeline.rb24
-rw-r--r--app/models/ci/processable.rb20
-rw-r--r--app/models/ci/test_case.rb35
-rw-r--r--app/models/ci/test_case_failure.rb29
-rw-r--r--app/models/clusters/agent_token.rb2
-rw-r--r--app/models/clusters/applications/cert_manager.rb4
-rw-r--r--app/models/clusters/applications/crossplane.rb2
-rw-r--r--app/models/clusters/applications/elastic_stack.rb8
-rw-r--r--app/models/clusters/applications/fluentd.rb2
-rw-r--r--app/models/clusters/applications/helm.rb12
-rw-r--r--app/models/clusters/applications/ingress.rb2
-rw-r--r--app/models/clusters/applications/jupyter.rb2
-rw-r--r--app/models/clusters/applications/knative.rb4
-rw-r--r--app/models/clusters/applications/prometheus.rb6
-rw-r--r--app/models/clusters/applications/runner.rb4
-rw-r--r--app/models/clusters/cluster.rb3
-rw-r--r--app/models/clusters/concerns/application_core.rb11
-rw-r--r--app/models/clusters/concerns/application_data.rb2
-rw-r--r--app/models/clusters/providers/aws.rb3
-rw-r--r--app/models/commit.rb16
-rw-r--r--app/models/commit_status.rb9
-rw-r--r--app/models/concerns/atomic_internal_id.rb118
-rw-r--r--app/models/concerns/enums/ci/pipeline.rb4
-rw-r--r--app/models/concerns/enums/internal_id.rb3
-rw-r--r--app/models/concerns/featurable.rb3
-rw-r--r--app/models/concerns/from_union.rb21
-rw-r--r--app/models/concerns/has_repository.rb5
-rw-r--r--app/models/concerns/issue_available_features.rb17
-rw-r--r--app/models/concerns/mentionable/reference_regexes.rb2
-rw-r--r--app/models/concerns/project_features_compatibility.rb2
-rw-r--r--app/models/concerns/project_services_loggable.rb4
-rw-r--r--app/models/concerns/protected_ref_access.rb8
-rw-r--r--app/models/concerns/storage/legacy_namespace.rb2
-rw-r--r--app/models/concerns/todoable.rb10
-rw-r--r--app/models/concerns/triggerable_hooks.rb4
-rw-r--r--app/models/container_expiration_policy.rb16
-rw-r--r--app/models/container_repository.rb6
-rw-r--r--app/models/custom_emoji.rb11
-rw-r--r--app/models/dependency_proxy.rb6
-rw-r--r--app/models/dependency_proxy/blob.rb21
-rw-r--r--app/models/dependency_proxy/group_setting.rb9
-rw-r--r--app/models/dependency_proxy/registry.rb30
-rw-r--r--app/models/deploy_key.rb13
-rw-r--r--app/models/deploy_keys_project.rb1
-rw-r--r--app/models/deploy_token.rb4
-rw-r--r--app/models/deployment.rb6
-rw-r--r--app/models/deployment_merge_request.rb5
-rw-r--r--app/models/design_management/design.rb11
-rw-r--r--app/models/design_management/version.rb5
-rw-r--r--app/models/diff_viewer/image.rb8
-rw-r--r--app/models/discussion.rb1
-rw-r--r--app/models/environment.rb6
-rw-r--r--app/models/experiment.rb19
-rw-r--r--app/models/experiment_user.rb6
-rw-r--r--app/models/group.rb26
-rw-r--r--app/models/hooks/project_hook.rb4
-rw-r--r--app/models/instance_metadata.rb10
-rw-r--r--app/models/internal_id.rb41
-rw-r--r--app/models/issue.rb3
-rw-r--r--app/models/issue_link.rb9
-rw-r--r--app/models/issues/csv_import.rb8
-rw-r--r--app/models/iteration.rb4
-rw-r--r--app/models/member.rb6
-rw-r--r--app/models/members/group_member.rb1
-rw-r--r--app/models/merge_request.rb14
-rw-r--r--app/models/merge_request/cleanup_schedule.rb14
-rw-r--r--app/models/merge_request_diff_file.rb4
-rw-r--r--app/models/milestone.rb4
-rw-r--r--app/models/namespace.rb18
-rw-r--r--app/models/namespace/root_storage_statistics.rb4
-rw-r--r--app/models/namespace_setting.rb8
-rw-r--r--app/models/note.rb4
-rw-r--r--app/models/operations/feature_flag.rb19
-rw-r--r--app/models/operations/feature_flags/user_list.rb7
-rw-r--r--app/models/packages/build_info.rb2
-rw-r--r--app/models/packages/event.rb17
-rw-r--r--app/models/packages/package.rb23
-rw-r--r--app/models/packages/package_file.rb2
-rw-r--r--app/models/packages/package_file_build_info.rb6
-rw-r--r--app/models/pages/lookup_path.rb36
-rw-r--r--app/models/pages_deployment.rb12
-rw-r--r--app/models/pages_domain.rb2
-rw-r--r--app/models/personal_access_token.rb1
-rw-r--r--app/models/project.rb54
-rw-r--r--app/models/project_repository_storage_move.rb26
-rw-r--r--app/models/project_services/alerts_service.rb10
-rw-r--r--app/models/project_services/jira_service.rb2
-rw-r--r--app/models/project_statistics.rb14
-rw-r--r--app/models/protected_branch/push_access_level.rb25
-rw-r--r--app/models/release.rb9
-rw-r--r--app/models/releases/link.rb10
-rw-r--r--app/models/releases/source.rb7
-rw-r--r--app/models/resource_timebox_event.rb4
-rw-r--r--app/models/route.rb1
-rw-r--r--app/models/service.rb52
-rw-r--r--app/models/snippet.rb6
-rw-r--r--app/models/terraform/state.rb25
-rw-r--r--app/models/terraform/state_version.rb1
-rw-r--r--app/models/user.rb49
-rw-r--r--app/models/user_callout.rb3
-rw-r--r--app/models/user_preference.rb4
-rw-r--r--app/models/user_status.rb2
-rw-r--r--app/models/vulnerability.rb21
-rw-r--r--app/policies/alert_management/http_integration_policy.rb7
-rw-r--r--app/policies/base_policy.rb2
-rw-r--r--app/policies/concerns/policy_actor.rb4
-rw-r--r--app/policies/container_registry/tag_policy.rb6
-rw-r--r--app/policies/custom_emoji_policy.rb5
-rw-r--r--app/policies/group_member_policy.rb5
-rw-r--r--app/policies/group_policy.rb20
-rw-r--r--app/policies/instance_metadata_policy.rb5
-rw-r--r--app/policies/issue_policy.rb4
-rw-r--r--app/policies/merge_request_policy.rb4
-rw-r--r--app/policies/note_policy.rb11
-rw-r--r--app/policies/project_policy.rb3
-rw-r--r--app/policies/service_policy.rb5
-rw-r--r--app/policies/terraform/state_version_policy.rb9
-rw-r--r--app/policies/user_policy.rb2
-rw-r--r--app/presenters/environment_presenter.rb4
-rw-r--r--app/presenters/invitation_presenter.rb5
-rw-r--r--app/presenters/issue_presenter.rb4
-rw-r--r--app/presenters/packages/detail/package_presenter.rb13
-rw-r--r--app/presenters/project_presenter.rb6
-rw-r--r--app/presenters/release_presenter.rb34
-rw-r--r--app/serializers/base_discussion_entity.rb55
-rw-r--r--app/serializers/diff_file_base_entity.rb2
-rw-r--r--app/serializers/diff_file_entity.rb16
-rw-r--r--app/serializers/diffs_entity.rb6
-rw-r--r--app/serializers/discussion_entity.rb48
-rw-r--r--app/serializers/environment_entity.rb5
-rw-r--r--app/serializers/merge_request_widget_entity.rb17
-rw-r--r--app/serializers/move_to_project_entity.rb1
-rw-r--r--app/serializers/note_entity.rb18
-rw-r--r--app/serializers/paginated_diff_entity.rb15
-rw-r--r--app/serializers/test_case_entity.rb1
-rw-r--r--app/serializers/test_suite_comparer_entity.rb27
-rw-r--r--app/services/admin/propagate_integration_service.rb47
-rw-r--r--app/services/alert_management/http_integrations/create_service.rb60
-rw-r--r--app/services/alert_management/http_integrations/destroy_service.rb44
-rw-r--r--app/services/alert_management/http_integrations/update_service.rb48
-rw-r--r--app/services/alert_management/process_prometheus_alert_service.rb15
-rw-r--r--app/services/alert_management/sync_alert_service_data_service.rb56
-rw-r--r--app/services/audit_event_service.rb8
-rw-r--r--app/services/bulk_create_integration_service.rb10
-rw-r--r--app/services/bulk_import_service.rb63
-rw-r--r--app/services/bulk_update_integration_service.rb4
-rw-r--r--app/services/ci/append_build_trace_service.rb65
-rw-r--r--app/services/ci/build_report_result_service.rb2
-rw-r--r--app/services/ci/compare_reports_base_service.rb8
-rw-r--r--app/services/ci/compare_test_reports_service.rb14
-rw-r--r--app/services/ci/create_pipeline_service.rb1
-rw-r--r--app/services/ci/daily_build_group_report_result_service.rb3
-rw-r--r--app/services/ci/destroy_expired_job_artifacts_service.rb73
-rw-r--r--app/services/ci/list_config_variables_service.rb5
-rw-r--r--app/services/ci/parse_dotenv_artifact_service.rb2
-rw-r--r--app/services/ci/test_cases_service.rb44
-rw-r--r--app/services/ci/update_build_state_service.rb10
-rw-r--r--app/services/clusters/aws/authorize_role_service.rb7
-rw-r--r--app/services/clusters/aws/fetch_credentials_service.rb7
-rw-r--r--app/services/clusters/kubernetes.rb2
-rw-r--r--app/services/clusters/kubernetes/create_or_update_service_account_service.rb12
-rw-r--r--app/services/concerns/admin/propagate_service.rb13
-rw-r--r--app/services/concerns/integrations/project_test_data.rb7
-rw-r--r--app/services/concerns/users/participable_service.rb3
-rw-r--r--app/services/container_expiration_policies/cleanup_service.rb53
-rw-r--r--app/services/container_expiration_policy_service.rb10
-rw-r--r--app/services/dependency_proxy/base_service.rb17
-rw-r--r--app/services/dependency_proxy/download_blob_service.rb48
-rw-r--r--app/services/dependency_proxy/find_or_create_blob_service.rb45
-rw-r--r--app/services/dependency_proxy/pull_manifest_service.rb29
-rw-r--r--app/services/dependency_proxy/request_token_service.rb29
-rw-r--r--app/services/deploy_keys/collect_keys_service.rb27
-rw-r--r--app/services/design_management/copy_design_collection/copy_service.rb30
-rw-r--r--app/services/discussions/capture_diff_note_position_service.rb3
-rw-r--r--app/services/feature_flags/update_service.rb4
-rw-r--r--app/services/git/branch_hooks_service.rb1
-rw-r--r--app/services/groups/create_service.rb2
-rw-r--r--app/services/import/github_service.rb23
-rw-r--r--app/services/integrations/test/project_service.rb2
-rw-r--r--app/services/issuable/common_system_notes_service.rb6
-rw-r--r--app/services/issuable/import_csv/base_service.rb84
-rw-r--r--app/services/issues/import_csv_service.rb61
-rw-r--r--app/services/issues/reopen_service.rb8
-rw-r--r--app/services/jira_connect/sync_service.rb4
-rw-r--r--app/services/jira_connect_subscriptions/create_service.rb17
-rw-r--r--app/services/jira_import/users_importer.rb8
-rw-r--r--app/services/jira_import/users_mapper_service.rb54
-rw-r--r--app/services/labels/promote_service.rb62
-rw-r--r--app/services/members/invite_service.rb103
-rw-r--r--app/services/merge_requests/cleanup_refs_service.rb16
-rw-r--r--app/services/merge_requests/refresh_service.rb6
-rw-r--r--app/services/merge_requests/reopen_service.rb2
-rw-r--r--app/services/notes/create_service.rb6
-rw-r--r--app/services/notes/destroy_service.rb7
-rw-r--r--app/services/notes/update_service.rb6
-rw-r--r--app/services/notification_service.rb12
-rw-r--r--app/services/packages/composer/create_package_service.rb4
-rw-r--r--app/services/packages/composer/version_parser_service.rb2
-rw-r--r--app/services/packages/create_event_service.rb28
-rw-r--r--app/services/packages/create_package_file_service.rb9
-rw-r--r--app/services/packages/debian/extract_deb_metadata_service.rb41
-rw-r--r--app/services/packages/debian/parse_debian822_service.rb66
-rw-r--r--app/services/packages/generic/create_package_file_service.rb3
-rw-r--r--app/services/packages/generic/find_or_create_package_service.rb2
-rw-r--r--app/services/packages/maven/create_package_service.rb7
-rw-r--r--app/services/packages/maven/find_or_create_package_service.rb5
-rw-r--r--app/services/packages/npm/create_package_service.rb5
-rw-r--r--app/services/pages/destroy_deployments_service.rb16
-rw-r--r--app/services/personal_access_tokens/create_service.rb27
-rw-r--r--app/services/personal_access_tokens/revoke_service.rb11
-rw-r--r--app/services/post_receive_service.rb20
-rw-r--r--app/services/projects/alerting/notify_service.rb27
-rw-r--r--app/services/projects/cleanup_service.rb22
-rw-r--r--app/services/projects/container_repository/delete_tags_service.rb6
-rw-r--r--app/services/projects/container_repository/gitlab/delete_tags_service.rb11
-rw-r--r--app/services/projects/hashed_storage/base_repository_service.rb11
-rw-r--r--app/services/projects/lfs_pointers/lfs_download_service.rb2
-rw-r--r--app/services/projects/prometheus/alerts/notify_service.rb23
-rw-r--r--app/services/projects/update_pages_service.rb34
-rw-r--r--app/services/projects/update_repository_storage_service.rb16
-rw-r--r--app/services/releases/base_service.rb4
-rw-r--r--app/services/releases/create_service.rb2
-rw-r--r--app/services/releases/update_service.rb17
-rw-r--r--app/services/resource_access_tokens/create_service.rb19
-rw-r--r--app/services/search/global_service.rb1
-rw-r--r--app/services/search/group_service.rb1
-rw-r--r--app/services/search/project_service.rb1
-rw-r--r--app/services/search_service.rb8
-rw-r--r--app/services/snippets/create_service.rb2
-rw-r--r--app/services/snippets/update_service.rb2
-rw-r--r--app/services/system_note_service.rb8
-rw-r--r--app/services/system_notes/merge_requests_service.rb10
-rw-r--r--app/services/test_hooks/project_service.rb2
-rw-r--r--app/services/users/approve_service.rb8
-rw-r--r--app/services/users/set_status_service.rb5
-rw-r--r--app/services/web_hook_service.rb1
-rw-r--r--app/uploaders/dependency_proxy/file_uploader.rb23
-rw-r--r--app/uploaders/gitlab_uploader.rb8
-rw-r--r--app/validators/rsa_key_validator.rb27
-rw-r--r--app/views/admin/application_settings/_eks.html.haml2
-rw-r--r--app/views/admin/application_settings/_gitpod.html.haml4
-rw-r--r--app/views/admin/application_settings/_outbound.html.haml4
-rw-r--r--app/views/admin/application_settings/_package_registry.html.haml2
-rw-r--r--app/views/admin/application_settings/_plantuml.html.haml2
-rw-r--r--app/views/admin/application_settings/_signin.html.haml4
-rw-r--r--app/views/admin/application_settings/_signup.html.haml54
-rw-r--r--app/views/admin/application_settings/_snowplow.html.haml2
-rw-r--r--app/views/admin/application_settings/_third_party_offers.html.haml2
-rw-r--r--app/views/admin/application_settings/ci/_header.html.haml2
-rw-r--r--app/views/admin/application_settings/ci_cd.html.haml4
-rw-r--r--app/views/admin/application_settings/general.html.haml18
-rw-r--r--app/views/admin/application_settings/network.html.haml16
-rw-r--r--app/views/admin/dashboard/index.html.haml24
-rw-r--r--app/views/admin/dev_ops_report/_report.html.haml30
-rw-r--r--app/views/admin/dev_ops_report/show.html.haml32
-rw-r--r--app/views/admin/groups/show.html.haml10
-rw-r--r--app/views/admin/health_check/show.html.haml2
-rw-r--r--app/views/admin/identities/_identity.html.haml2
-rw-r--r--app/views/admin/jobs/index.html.haml6
-rw-r--r--app/views/admin/projects/show.html.haml19
-rw-r--r--app/views/admin/runners/index.html.haml4
-rw-r--r--app/views/admin/serverless/domains/_form.html.haml2
-rw-r--r--app/views/admin/system_info/show.html.haml4
-rw-r--r--app/views/admin/users/_block_user.html.haml7
-rw-r--r--app/views/admin/users/_modals.html.haml5
-rw-r--r--app/views/admin/users/_user.html.haml12
-rw-r--r--app/views/admin/users/_user_block_effects.html.haml11
-rw-r--r--app/views/admin/users/index.html.haml9
-rw-r--r--app/views/ci/runner/_how_to_setup_runner.html.haml4
-rw-r--r--app/views/ci/runner/_how_to_setup_runner_automatically.html.haml2
-rw-r--r--app/views/ci/variables/_index.html.haml48
-rw-r--r--app/views/clusters/clusters/_details.html.haml2
-rw-r--r--app/views/clusters/clusters/_empty_state.html.haml2
-rw-r--r--app/views/clusters/clusters/_provider_details_form.html.haml2
-rw-r--r--app/views/clusters/clusters/aws/_new.html.haml2
-rw-r--r--app/views/clusters/clusters/gcp/_form.html.haml4
-rw-r--r--app/views/clusters/clusters/user/_form.html.haml2
-rw-r--r--app/views/dashboard/_groups_head.html.haml2
-rw-r--r--app/views/dashboard/_projects_head.html.haml2
-rw-r--r--app/views/dashboard/_snippets_head.html.haml2
-rw-r--r--app/views/dashboard/groups/index.html.haml3
-rw-r--r--app/views/dashboard/todos/_todo.html.haml6
-rw-r--r--app/views/dashboard/todos/index.html.haml6
-rw-r--r--app/views/devise/confirmations/new.html.haml2
-rw-r--r--app/views/devise/mailer/user_admin_approval.html.haml8
-rw-r--r--app/views/devise/mailer/user_admin_approval.text.erb7
-rw-r--r--app/views/devise/passwords/edit.html.haml2
-rw-r--r--app/views/devise/registrations/new.html.haml25
-rw-r--r--app/views/devise/sessions/_new_base.html.haml2
-rw-r--r--app/views/devise/sessions/new.html.haml17
-rw-r--r--app/views/devise/sessions/two_factor.html.haml2
-rw-r--r--app/views/devise/shared/_experimental_separate_sign_up_flow_box.html.haml39
-rw-r--r--app/views/devise/shared/_experimental_separate_sign_up_flow_omniauth_box.haml13
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml2
-rw-r--r--app/views/devise/shared/_signin_box.html.haml5
-rw-r--r--app/views/devise/shared/_signup_box.html.haml68
-rw-r--r--app/views/devise/shared/_signup_omniauth_providers.haml13
-rw-r--r--app/views/devise/shared/_tabs_ldap.html.haml8
-rw-r--r--app/views/devise/unlocks/new.html.haml2
-rw-r--r--app/views/discussions/_discussion.html.haml8
-rw-r--r--app/views/doorkeeper/applications/_delete_form.html.haml2
-rw-r--r--app/views/doorkeeper/applications/_form.html.haml2
-rw-r--r--app/views/doorkeeper/applications/index.html.haml2
-rw-r--r--app/views/doorkeeper/applications/show.html.haml6
-rw-r--r--app/views/doorkeeper/authorizations/new.html.haml4
-rw-r--r--app/views/errors/access_denied.html.haml2
-rw-r--r--app/views/errors/not_found.html.haml2
-rw-r--r--app/views/errors/omniauth_error.html.haml4
-rw-r--r--app/views/events/event/_note.html.haml2
-rw-r--r--app/views/explore/projects/_projects.html.haml3
-rw-r--r--app/views/explore/projects/index.html.haml1
-rw-r--r--app/views/explore/projects/page_out_of_bounds.html.haml2
-rw-r--r--app/views/explore/projects/trending.html.haml2
-rw-r--r--app/views/groups/_home_panel.html.haml39
-rw-r--r--app/views/groups/_invite_members_modal.html.haml5
-rw-r--r--app/views/groups/_invite_members_side_nav_link.html.haml2
-rw-r--r--app/views/groups/dependency_proxies/_url.html.haml12
-rw-r--r--app/views/groups/dependency_proxies/show.html.haml28
-rw-r--r--app/views/groups/group_members/index.html.haml29
-rw-r--r--app/views/groups/issues.html.haml3
-rw-r--r--app/views/groups/labels/index.html.haml2
-rw-r--r--app/views/groups/milestones/_form.html.haml8
-rw-r--r--app/views/groups/milestones/index.html.haml2
-rw-r--r--app/views/groups/runners/_group_runners.html.haml4
-rw-r--r--app/views/groups/settings/repository/_initial_branch_name.html.haml22
-rw-r--r--app/views/groups/settings/repository/show.html.haml1
-rw-r--r--app/views/groups/show.html.haml4
-rw-r--r--app/views/groups/sidebar/_packages.html.haml6
-rw-r--r--app/views/ide/_show.html.haml1
-rw-r--r--app/views/import/_project_status.html.haml11
-rw-r--r--app/views/import/google_code/status.html.haml2
-rw-r--r--app/views/import/shared/_new_project_form.html.haml4
-rw-r--r--app/views/invites/show.html.haml2
-rw-r--r--app/views/jira_connect/subscriptions/index.html.haml9
-rw-r--r--app/views/layouts/_flash.html.haml2
-rw-r--r--app/views/layouts/_google_tag_manager_body.html.haml4
-rw-r--r--app/views/layouts/_google_tag_manager_head.html.haml8
-rw-r--r--app/views/layouts/_head.html.haml13
-rw-r--r--app/views/layouts/_mailer.html.haml8
-rw-r--r--app/views/layouts/_page.html.haml5
-rw-r--r--app/views/layouts/_search.html.haml3
-rw-r--r--app/views/layouts/_startup_js.html.haml2
-rw-r--r--app/views/layouts/devise_experimental_onboarding_issues.html.haml2
-rw-r--r--app/views/layouts/devise_experimental_separate_sign_up_flow.html.haml20
-rw-r--r--app/views/layouts/experiment_mailer.html.haml48
-rw-r--r--app/views/layouts/header/_current_user_dropdown.html.haml9
-rw-r--r--app/views/layouts/header/_default.html.haml3
-rw-r--r--app/views/layouts/header/_registration_enabled_callout.html.haml15
-rw-r--r--app/views/layouts/mailer.html.haml9
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml4
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml10
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml21
-rw-r--r--app/views/layouts/project.html.haml1
-rw-r--r--app/views/layouts/unknown_user_mailer.html.haml8
-rw-r--r--app/views/layouts/unknown_user_mailer.text.erb9
-rw-r--r--app/views/layouts/welcome.html.haml8
-rw-r--r--app/views/notify/_issuable_csv_export.html.haml2
-rw-r--r--app/views/notify/_note_email.html.haml2
-rw-r--r--app/views/notify/instance_access_request_email.html.haml10
-rw-r--r--app/views/notify/instance_access_request_email.text.erb8
-rw-r--r--app/views/notify/member_invited_email.html.haml20
-rw-r--r--app/views/notify/member_invited_email.text.erb11
-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/prometheus_alert_fired_email.html.haml6
-rw-r--r--app/views/notify/prometheus_alert_fired_email.text.erb5
-rw-r--r--app/views/profiles/_event_table.html.haml2
-rw-r--r--app/views/profiles/preferences/_gitpod.html.haml9
-rw-r--r--app/views/profiles/preferences/_integrations.html.haml18
-rw-r--r--app/views/profiles/preferences/_sourcegraph.html.haml10
-rw-r--r--app/views/profiles/preferences/show.html.haml255
-rw-r--r--app/views/profiles/show.html.haml10
-rw-r--r--app/views/projects/_find_file_link.html.haml2
-rw-r--r--app/views/projects/_home_panel.html.haml16
-rw-r--r--app/views/projects/_invite_members_modal.html.haml7
-rw-r--r--app/views/projects/_invite_members_side_nav_link.html.haml3
-rw-r--r--app/views/projects/_merge_request_merge_options_settings.html.haml1
-rw-r--r--app/views/projects/_remove.html.haml3
-rw-r--r--app/views/projects/_remove_fork.html.haml10
-rw-r--r--app/views/projects/_service_desk_settings.html.haml2
-rw-r--r--app/views/projects/_stat_anchor_list.html.haml2
-rw-r--r--app/views/projects/_transfer.html.haml16
-rw-r--r--app/views/projects/alert_management/details.html.haml1
-rw-r--r--app/views/projects/artifacts/_artifact.html.haml4
-rw-r--r--app/views/projects/artifacts/_tree_file.html.haml2
-rw-r--r--app/views/projects/artifacts/browse.html.haml2
-rw-r--r--app/views/projects/blob/_breadcrumb.html.haml8
-rw-r--r--app/views/projects/blob/_header.html.haml4
-rw-r--r--app/views/projects/blob/_header_content.html.haml2
-rw-r--r--app/views/projects/blob/_pipeline_tour_success.html.haml2
-rw-r--r--app/views/projects/blob/_upload.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_metrics_dashboard_yml.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_route_map.html.haml4
-rw-r--r--app/views/projects/branches/_branch.html.haml4
-rw-r--r--app/views/projects/branches/_delete_protected_modal.html.haml2
-rw-r--r--app/views/projects/branches/index.html.haml4
-rw-r--r--app/views/projects/branches/new.html.haml6
-rw-r--r--app/views/projects/buttons/_clone.html.haml2
-rw-r--r--app/views/projects/buttons/_download.html.haml2
-rw-r--r--app/views/projects/buttons/_download_links.html.haml2
-rw-r--r--app/views/projects/buttons/_xcode_link.html.haml2
-rw-r--r--app/views/projects/ci/lints/_create.html.haml51
-rw-r--r--app/views/projects/ci/lints/_lint_warnings.html.haml10
-rw-r--r--app/views/projects/ci/lints/show.html.haml30
-rw-r--r--app/views/projects/ci/pipeline_editor/show.html.haml6
-rw-r--r--app/views/projects/cleanup/_show.html.haml2
-rw-r--r--app/views/projects/commit/_change.html.haml4
-rw-r--r--app/views/projects/commit/diff_files.html.haml4
-rw-r--r--app/views/projects/commits/_commit.html.haml6
-rw-r--r--app/views/projects/commits/show.html.haml3
-rw-r--r--app/views/projects/confluences/show.html.haml2
-rw-r--r--app/views/projects/cycle_analytics/show.html.haml2
-rw-r--r--app/views/projects/default_branch/_show.html.haml2
-rw-r--r--app/views/projects/deploy_keys/edit.html.haml2
-rw-r--r--app/views/projects/diffs/_diffs.html.haml2
-rw-r--r--app/views/projects/diffs/_file.html.haml7
-rw-r--r--app/views/projects/diffs/_file_header.html.haml17
-rw-r--r--app/views/projects/diffs/_line.html.haml29
-rw-r--r--app/views/projects/diffs/_stats.html.haml2
-rw-r--r--app/views/projects/edit.html.haml28
-rw-r--r--app/views/projects/environments/_external_url.html.haml2
-rw-r--r--app/views/projects/environments/_form.html.haml4
-rw-r--r--app/views/projects/environments/_metrics_button.html.haml2
-rw-r--r--app/views/projects/environments/_pin_button.html.haml2
-rw-r--r--app/views/projects/environments/_terminal_button.html.haml2
-rw-r--r--app/views/projects/environments/empty_metrics.html.haml2
-rw-r--r--app/views/projects/environments/show.html.haml11
-rw-r--r--app/views/projects/environments/terminal.html.haml2
-rw-r--r--app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml5
-rw-r--r--app/views/projects/hooks/index.html.haml2
-rw-r--r--app/views/projects/imports/new.html.haml2
-rw-r--r--app/views/projects/incidents/show.html.haml7
-rw-r--r--app/views/projects/issuable/_show.html.haml10
-rw-r--r--app/views/projects/issues/_design_management.html.haml2
-rw-r--r--app/views/projects/issues/_discussion.html.haml4
-rw-r--r--app/views/projects/issues/_issue.html.haml5
-rw-r--r--app/views/projects/issues/_issues.html.haml3
-rw-r--r--app/views/projects/issues/_nav_btns.html.haml8
-rw-r--r--app/views/projects/issues/_new_branch.html.haml4
-rw-r--r--app/views/projects/issues/_service_desk_empty_state.html.haml2
-rw-r--r--app/views/projects/issues/_service_desk_info_content.html.haml2
-rw-r--r--app/views/projects/issues/export_csv/_button.html.haml4
-rw-r--r--app/views/projects/issues/export_csv/_modal.html.haml22
-rw-r--r--app/views/projects/issues/import_csv/_modal.html.haml2
-rw-r--r--app/views/projects/issues/show.html.haml101
-rw-r--r--app/views/projects/jobs/index.html.haml1
-rw-r--r--app/views/projects/jobs/show.html.haml2
-rw-r--r--app/views/projects/labels/index.html.haml4
-rw-r--r--app/views/projects/logs/empty_logs.html.haml2
-rw-r--r--app/views/projects/mattermosts/_no_teams.html.haml4
-rw-r--r--app/views/projects/mattermosts/_team_selection.html.haml8
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml8
-rw-r--r--app/views/projects/merge_requests/_nav_btns.html.haml9
-rw-r--r--app/views/projects/merge_requests/conflicts/_submit_form.html.haml2
-rw-r--r--app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml5
-rw-r--r--app/views/projects/merge_requests/conflicts/show.html.haml2
-rw-r--r--app/views/projects/merge_requests/creations/_new_compare.html.haml3
-rw-r--r--app/views/projects/merge_requests/creations/new.html.haml1
-rw-r--r--app/views/projects/merge_requests/show.html.haml1
-rw-r--r--app/views/projects/milestones/_form.html.haml4
-rw-r--r--app/views/projects/milestones/index.html.haml2
-rw-r--r--app/views/projects/mirrors/_authentication_method.html.haml2
-rw-r--r--app/views/projects/mirrors/_mirror_repos.html.haml6
-rw-r--r--app/views/projects/mirrors/_mirror_repos_form.html.haml2
-rw-r--r--app/views/projects/mirrors/_ssh_host_keys.html.haml2
-rw-r--r--app/views/projects/new.html.haml2
-rw-r--r--app/views/projects/no_repo.html.haml9
-rw-r--r--app/views/projects/pages/_ssl_limitations_warning.html.haml2
-rw-r--r--app/views/projects/pages_domains/_dns.html.haml2
-rw-r--r--app/views/projects/pages_domains/_lets_encrypt_callout.html.haml2
-rw-r--r--app/views/projects/pages_domains/show.html.haml2
-rw-r--r--app/views/projects/pipeline_schedules/_form.html.haml2
-rw-r--r--app/views/projects/pipeline_schedules/edit.html.haml1
-rw-r--r--app/views/projects/pipeline_schedules/index.html.haml4
-rw-r--r--app/views/projects/pipeline_schedules/new.html.haml1
-rw-r--r--app/views/projects/pipelines/_info.html.haml9
-rw-r--r--app/views/projects/pipelines/_with_tabs.html.haml4
-rw-r--r--app/views/projects/pipelines/index.html.haml1
-rw-r--r--app/views/projects/pipelines/new.html.haml4
-rw-r--r--app/views/projects/pipelines/show.html.haml3
-rw-r--r--app/views/projects/project_members/_team.html.haml10
-rw-r--r--app/views/projects/project_members/index.html.haml5
-rw-r--r--app/views/projects/runners/_runner.html.haml4
-rw-r--r--app/views/projects/runners/_specific_runners.html.haml7
-rw-r--r--app/views/projects/services/prometheus/_metrics.html.haml3
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml5
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml4
-rw-r--r--app/views/projects/settings/operations/_alert_management.html.haml1
-rw-r--r--app/views/projects/settings/operations/_error_tracking.html.haml2
-rw-r--r--app/views/projects/show.html.haml1
-rw-r--r--app/views/projects/tags/_tag.html.haml7
-rw-r--r--app/views/projects/terraform/index.html.haml4
-rw-r--r--app/views/projects/tree/_tree_header.html.haml2
-rw-r--r--app/views/projects/tree/show.html.haml4
-rw-r--r--app/views/registrations/welcome.html.haml25
-rw-r--r--app/views/registrations/welcome/show.html.haml25
-rw-r--r--app/views/search/_filter.html.haml19
-rw-r--r--app/views/search/_form.html.haml2
-rw-r--r--app/views/search/_results.html.haml75
-rw-r--r--app/views/search/_sort_dropdown.html.haml16
-rw-r--r--app/views/search/results/_blob_data.html.haml2
-rw-r--r--app/views/search/results/_empty.html.haml4
-rw-r--r--app/views/search/results/_filters.html.haml7
-rw-r--r--app/views/search/results/_issuable.html.haml10
-rw-r--r--app/views/search/results/_issue.html.haml14
-rw-r--r--app/views/search/results/_merge_request.html.haml15
-rw-r--r--app/views/search/results/_wiki_blob.html.haml7
-rw-r--r--app/views/sent_notifications/unsubscribe.html.haml4
-rw-r--r--app/views/shared/_broadcast_message.html.haml4
-rw-r--r--app/views/shared/_file_highlight.html.haml5
-rw-r--r--app/views/shared/_issuable_meta_data.html.haml2
-rw-r--r--app/views/shared/_label.html.haml5
-rw-r--r--app/views/shared/_label_row.html.haml6
-rw-r--r--app/views/shared/_ping_consent.html.haml20
-rw-r--r--app/views/shared/_remote_mirror_update_button.html.haml8
-rw-r--r--app/views/shared/access_tokens/_form.html.haml5
-rw-r--r--app/views/shared/boards/_show.html.haml5
-rw-r--r--app/views/shared/boards/components/sidebar/_assignee.html.haml2
-rw-r--r--app/views/shared/boards/components/sidebar/_due_date.html.haml2
-rw-r--r--app/views/shared/boards/components/sidebar/_labels.html.haml2
-rw-r--r--app/views/shared/boards/components/sidebar/_milestone.html.haml2
-rw-r--r--app/views/shared/form_elements/_apply_template_warning.html.haml5
-rw-r--r--app/views/shared/form_elements/_description.html.haml3
-rw-r--r--app/views/shared/groups/_empty_state.html.haml11
-rw-r--r--app/views/shared/groups/_search_form.html.haml2
-rw-r--r--app/views/shared/issuable/_close_reopen_button.html.haml5
-rw-r--r--app/views/shared/issuable/_close_reopen_report_toggle.html.haml4
-rw-r--r--app/views/shared/issuable/_form.html.haml2
-rw-r--r--app/views/shared/issuable/_label_dropdown.html.haml2
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml3
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml14
-rw-r--r--app/views/shared/issuable/_sort_dropdown.html.haml2
-rw-r--r--app/views/shared/issuable/csv_export/_button.html.haml4
-rw-r--r--app/views/shared/issuable/csv_export/_modal.html.haml29
-rw-r--r--app/views/shared/issuable/form/_type_selector.html.haml2
-rw-r--r--app/views/shared/issue_type/_details_content.html.haml31
-rw-r--r--app/views/shared/issue_type/_details_header.html.haml55
-rw-r--r--app/views/shared/issue_type/_emoji_block.html.haml9
-rw-r--r--app/views/shared/issue_type/_sentry_stack_trace.html.haml4
-rw-r--r--app/views/shared/members/_filter_2fa_dropdown.html.haml4
-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.haml20
-rw-r--r--app/views/shared/members/_requests.html.haml9
-rw-r--r--app/views/shared/members/_search_field.html.haml2
-rw-r--r--app/views/shared/members/_sort_dropdown.html.haml10
-rw-r--r--app/views/shared/milestones/_delete_button.html.haml2
-rw-r--r--app/views/shared/milestones/_header.html.haml10
-rw-r--r--app/views/shared/milestones/_labels_tab.html.haml6
-rw-r--r--app/views/shared/milestones/_milestone.html.haml6
-rw-r--r--app/views/shared/notes/_comment_button.html.haml4
-rw-r--r--app/views/shared/notes/_hints.html.haml19
-rw-r--r--app/views/shared/notes/_note.html.haml2
-rw-r--r--app/views/shared/notes/_notes_with_form.html.haml2
-rw-r--r--app/views/shared/notifications/_custom_notifications.html.haml3
-rw-r--r--app/views/shared/notifications/_new_button.html.haml5
-rw-r--r--app/views/shared/projects/_search_form.html.haml1
-rw-r--r--app/views/shared/web_hooks/_form.html.haml12
-rw-r--r--app/views/shared/wikis/_sidebar.html.haml2
-rw-r--r--app/views/sherlock/transactions/_file_samples.html.haml2
-rw-r--r--app/views/sherlock/transactions/_queries.html.haml2
-rw-r--r--app/views/sherlock/transactions/index.html.haml4
-rw-r--r--app/views/snippets/notes/_actions.html.haml2
-rw-r--r--app/views/snippets/show.html.haml6
-rw-r--r--app/views/users/_groups.html.haml5
-rw-r--r--app/views/users/_overview.html.haml16
-rw-r--r--app/views/users/show.html.haml19
-rw-r--r--app/views/users/terms/index.html.haml6
-rw-r--r--app/workers/all_queues.yml58
-rw-r--r--app/workers/analytics/instance_statistics/counter_job_worker.rb10
-rw-r--r--app/workers/background_migration_worker.rb57
-rw-r--r--app/workers/build_finished_worker.rb5
-rw-r--r--app/workers/bulk_import_worker.rb15
-rw-r--r--app/workers/ci/build_trace_chunk_flush_worker.rb2
-rw-r--r--app/workers/ci/delete_objects_worker.rb8
-rw-r--r--app/workers/cleanup_container_repository_worker.rb5
-rw-r--r--app/workers/concerns/application_worker.rb2
-rw-r--r--app/workers/concerns/limited_capacity/worker.rb7
-rw-r--r--app/workers/concerns/reenqueuer.rb2
-rw-r--r--app/workers/container_expiration_policies/cleanup_container_repository_worker.rb96
-rw-r--r--app/workers/container_expiration_policy_worker.rb75
-rw-r--r--app/workers/destroy_pages_deployments_worker.rb19
-rw-r--r--app/workers/git_garbage_collect_worker.rb19
-rw-r--r--app/workers/jira_connect/sync_branch_worker.rb4
-rw-r--r--app/workers/jira_connect/sync_merge_request_worker.rb4
-rw-r--r--app/workers/jira_connect/sync_project_worker.rb30
-rw-r--r--app/workers/post_receive.rb2
-rw-r--r--app/workers/propagate_integration_inherit_descendant_worker.rb19
-rw-r--r--app/workers/propagate_integration_inherit_worker.rb4
-rw-r--r--app/workers/purge_dependency_proxy_cache_worker.rb27
-rw-r--r--app/workers/remove_expired_members_worker.rb10
-rw-r--r--app/workers/repository_cleanup_worker.rb5
-rw-r--r--app/workers/schedule_merge_request_cleanup_refs_worker.rb26
-rwxr-xr-xbin/background_jobs2
-rwxr-xr-xbin/feature-flag18
-rwxr-xr-xbin/mail_room5
-rwxr-xr-xbin/spring10
-rwxr-xr-xbin/web_unicorn5
-rw-r--r--changelogs/unreleased/10io-add-cleanup-status-to-container-repository-details-graphql.yml5
-rw-r--r--changelogs/unreleased/10io-graphql-container-repository-details-api.yml5
-rw-r--r--changelogs/unreleased/10io-graphql-destroy-mutation-for-container-repositories.yml5
-rw-r--r--changelogs/unreleased/10io-graphql-query-container-repositories.yml5
-rw-r--r--changelogs/unreleased/11752-improve-active-users-count-license-query.yml5
-rw-r--r--changelogs/unreleased/17652-trademark-and-copyright-symbols-converted-to-smiley.yml6
-rw-r--r--changelogs/unreleased/198610-remove-ace.yml5
-rw-r--r--changelogs/unreleased/20099-markdown-with-yaml-rendering-doesn-t-handle-utf8-bom.yml5
-rw-r--r--changelogs/unreleased/202279-migrate-fa-spinner-to-spinner-for-app-assets-javascripts-vue_merge.yml5
-rw-r--r--changelogs/unreleased/205578-feature-flag-pkg-events.yml5
-rw-r--r--changelogs/unreleased/205578-generate-pkg-events-file.yml5
-rw-r--r--changelogs/unreleased/207334-design-view-relax-permissions-for-updateimagediffnote-mutation.yml5
-rw-r--r--changelogs/unreleased/207334-reposition_note_graphql.yml6
-rw-r--r--changelogs/unreleased/207869-lfs-enabled-checks.yml5
-rw-r--r--changelogs/unreleased/208193-throttle-container-expiration-policy-worker-execution.yml5
-rw-r--r--changelogs/unreleased/209784-notes-etag-only-for-empty-response.yml5
-rw-r--r--changelogs/unreleased/209916-container-repository-api.yml5
-rw-r--r--changelogs/unreleased/210327-fix-pipeline-security-tab-filters.yml5
-rw-r--r--changelogs/unreleased/211339-forward-deployment-warn-users-on-retry_followup.yml5
-rw-r--r--changelogs/unreleased/211357-api-endpoint-to-get-the-gpg-signature-of-a-commit-always-returns-4.yml5
-rw-r--r--changelogs/unreleased/214607-ci-jwt-signing-key-jwks-take-3.yml5
-rw-r--r--changelogs/unreleased/216008-ec2-for-auto-deploy.yml5
-rw-r--r--changelogs/unreleased/216571-terraform-state-mutations.yml5
-rw-r--r--changelogs/unreleased/216974-optional-input-field.yml5
-rw-r--r--changelogs/unreleased/217095-design-notifications.yml5
-rw-r--r--changelogs/unreleased/217553-permanent-links-to-release-assets-not-found-404.yml5
-rw-r--r--changelogs/unreleased/218167-stop-review-for-ecs.yml5
-rw-r--r--changelogs/unreleased/218529-change-image-upload-path.yml5
-rw-r--r--changelogs/unreleased/218529-display-uploaded-images.yml5
-rw-r--r--changelogs/unreleased/218531-determine-image-relative-paths.yml5
-rw-r--r--changelogs/unreleased/218666-show-lsf-for-long-name.yml5
-rw-r--r--changelogs/unreleased/219023-jira-users-mapping.yml5
-rw-r--r--changelogs/unreleased/220104-fix-race-in-read-only-repository-logic.yml5
-rw-r--r--changelogs/unreleased/220104-git-gc-should-prune-objects.yml5
-rw-r--r--changelogs/unreleased/220104-read-only-repository-cleanup.yml5
-rw-r--r--changelogs/unreleased/220433-user-stuck-in-2fa-setup-page-even-if-group-disable-2fa-enforce.yml5
-rw-r--r--changelogs/unreleased/220985-add-npm-project-level-manager-api.yml5
-rw-r--r--changelogs/unreleased/221035-ide-solarized-light.yml5
-rw-r--r--changelogs/unreleased/221101-implement-gitlab-ui-component-for-sorting-releases.yml5
-rw-r--r--changelogs/unreleased/222507-ide-move-file-editor-props.yml5
-rw-r--r--changelogs/unreleased/223768-add-google-analytics-tracking-to-sign-in-pages.yml5
-rw-r--r--changelogs/unreleased/224509-chevron-down-svg-issuable.yml5
-rw-r--r--changelogs/unreleased/224509-chevron-down-svg-mirror.yml5
-rw-r--r--changelogs/unreleased/224509-chevron-down-svg-project-branch.yml5
-rw-r--r--changelogs/unreleased/224509-replace-add-group-member-chevron.yml5
-rw-r--r--changelogs/unreleased/224509-replace-board-sidebar-chevron.yml5
-rw-r--r--changelogs/unreleased/224510-replace-fa-chevron-up-with-gitlab-svg-chevron-up-icon.yml5
-rw-r--r--changelogs/unreleased/224587-hide-apply-suggestion-button-for-certain-users.yml5
-rw-r--r--changelogs/unreleased/225180-replace-fa-warning-icons-with-gitlab-svg-warning-solid-icon.yml5
-rw-r--r--changelogs/unreleased/225953-replace-fa-external-link-icons-with-gitlab-svg-external-link-icon.yml5
-rw-r--r--changelogs/unreleased/225956-replace-fa-check-icons-with-gitlab-svg-check-icon.yml5
-rw-r--r--changelogs/unreleased/227415-rename-or-add-a-new-draft-alias-to-the-wip-quick-action.yml5
-rw-r--r--changelogs/unreleased/227808-improve-container-registry-client-supports-tag-delete.yml5
-rw-r--r--changelogs/unreleased/229003-migrate-notifications-tooltip.yml5
-rw-r--r--changelogs/unreleased/229300-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml5
-rw-r--r--changelogs/unreleased/229308-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml5
-rw-r--r--changelogs/unreleased/229674-update-change-username-modal.yml5
-rw-r--r--changelogs/unreleased/229685-update-leave-group-modal.yml5
-rw-r--r--changelogs/unreleased/229701-aqualls-stop-jobs-modal.yml5
-rw-r--r--changelogs/unreleased/229703-aqualls-promote-label-modal.yml5
-rw-r--r--changelogs/unreleased/229704-aqualls-metrics-modal.yml5
-rw-r--r--changelogs/unreleased/229918-issuedata-comments.yml5
-rw-r--r--changelogs/unreleased/230724-matej-tabs-migration-ide-pipelines-list.yml5
-rw-r--r--changelogs/unreleased/231234-remove-unstaged-icon.yml5
-rw-r--r--changelogs/unreleased/231494-draft-system-notes.yml5
-rw-r--r--changelogs/unreleased/231777-switching-branches-in-repo-tree-view-navigates-backwards.yml5
-rw-r--r--changelogs/unreleased/232569-update-the-milestone-dropdown-combobox-to-display-separated-sectio.yml6
-rw-r--r--changelogs/unreleased/232817-display-mr-submodules-icon.yml5
-rw-r--r--changelogs/unreleased/233278-in-global-search-if-there-is-only-one-result-redirect-to-that-page.yml5
-rw-r--r--changelogs/unreleased/233387-remove-lc-temp-index.yml5
-rw-r--r--changelogs/unreleased/233479-add-test-case-move-support.yml5
-rw-r--r--changelogs/unreleased/233669-remove-bootstrap-ping.yml5
-rw-r--r--changelogs/unreleased/233965-suggest-pipeline-flow-second-step-should-open-on-page-load.yml5
-rw-r--r--changelogs/unreleased/235385-ide-monokai-theme.yml5
-rw-r--r--changelogs/unreleased/235436-add-header-fuzzing-docs.yml5
-rw-r--r--changelogs/unreleased/235460_remove_sse_erb_support_feature_flag.yml5
-rw-r--r--changelogs/unreleased/235758-track-ci-secrets-management-vault-usage.yml5
-rw-r--r--changelogs/unreleased/236465-search-results-sort-ui.yml5
-rw-r--r--changelogs/unreleased/237843-typos-when-deleting-a-project-repository.yml5
-rw-r--r--changelogs/unreleased/237905-add-signup-enabled-alert.yml5
-rw-r--r--changelogs/unreleased/238156_remove_old_security_findings_from_database.yml5
-rw-r--r--changelogs/unreleased/238594-package-detail-on-mobile-view-is-impossible-to-see-multiple-tags.yml5
-rw-r--r--changelogs/unreleased/239305-resolve-ip-address-for-audit.yml5
-rw-r--r--changelogs/unreleased/239518-package-multiple-build-infos.yml5
-rw-r--r--changelogs/unreleased/240887-packages-composer-semver-not-fully-supported.yml5
-rw-r--r--changelogs/unreleased/241194-enable-vue_group_members_list-ff-by-default.yml5
-rw-r--r--changelogs/unreleased/241267-add-partitioned-table-model.yml5
-rw-r--r--changelogs/unreleased/241267-add-postgres-partition-model.yml5
-rw-r--r--changelogs/unreleased/241378_until_executed_deduplication_strategy.yml5
-rw-r--r--changelogs/unreleased/241534-test-report-modal.yml5
-rw-r--r--changelogs/unreleased/241957-remove-v-html-from-app-assets-javascripts-notes-components-discuss.yml5
-rw-r--r--changelogs/unreleased/241980-uploads-count-as-used-storage.yml5
-rw-r--r--changelogs/unreleased/241980-uploalds-on-storage-graphql.yml5
-rw-r--r--changelogs/unreleased/241990-improve-project-labels-page-consistency.yml5
-rw-r--r--changelogs/unreleased/243555-update-whitelist-blacklist-to-allowlist-denylist-in-signup-restric.yml5
-rw-r--r--changelogs/unreleased/243607-background-migration-for-setting-jira-tracker-data-deployment-type.yml5
-rw-r--r--changelogs/unreleased/244289-quickaction-with-codeblocks.yml5
-rw-r--r--changelogs/unreleased/244380_populate_has_vulnerabilities_values.yml5
-rw-r--r--changelogs/unreleased/244831-split-pipelines-for-merged-results-and-merge-train-check-boxes.yml5
-rw-r--r--changelogs/unreleased/244868-add-search-filters-to-metadata.yml5
-rw-r--r--changelogs/unreleased/244923-feature-flag-rollout-of-search_filter_by_confidential.yml5
-rw-r--r--changelogs/unreleased/245263-fix-cleanup-service-no-repository.yml5
-rw-r--r--changelogs/unreleased/245263-mr-refs-cleanup-old-mrs.yml5
-rw-r--r--changelogs/unreleased/245263-mr-refs-cleanup-scheduler.yml5
-rw-r--r--changelogs/unreleased/247870-nomethoderror-saving-jira-integration-with-invalid-credentials.yml5
-rw-r--r--changelogs/unreleased/249145-update-blank-dag.yml5
-rw-r--r--changelogs/unreleased/249661-ci_lint_vue-default-true.yml5
-rw-r--r--changelogs/unreleased/250323-move-projects_with_error_tracking_enabled-to-core.yml5
-rw-r--r--changelogs/unreleased/250484-add-locked-and-confidential-badge-to-issue-sticky-header.yml5
-rw-r--r--changelogs/unreleased/251011-add-count_all-count_7d-count_28d-top-level-keys-to-usage-data.yml5
-rw-r--r--changelogs/unreleased/251015-add-jobs-to-pipeline-type.yml5
-rw-r--r--changelogs/unreleased/251136-delete-selected-button-in-container-registry-is-not-visible-on-nar.yml5
-rw-r--r--changelogs/unreleased/251211-add-sorting-to-search-api.yml5
-rw-r--r--changelogs/unreleased/25145-remove-expand-sha-button-pipeline.yml5
-rw-r--r--changelogs/unreleased/252137-sync-sticky-header-issue-status.yml5
-rw-r--r--changelogs/unreleased/2529-code-quality-severity-rating.yml5
-rw-r--r--changelogs/unreleased/254228-background-migration-for-pipeline-id.yml5
-rw-r--r--changelogs/unreleased/254627-include-diff-note-details-in-notes-json.yml5
-rw-r--r--changelogs/unreleased/255519-migrate-existing-generic-alert-endpoints-to-http-integrations-form.yml5
-rw-r--r--changelogs/unreleased/255889-remove-feedback-alert-ondemand-scans.yml5
-rw-r--r--changelogs/unreleased/255970-confirmation-panels-for-significant-actions-are-inconsistent-in-te.yml5
-rw-r--r--changelogs/unreleased/257822-null-byes-in-url.yml5
-rw-r--r--changelogs/unreleased/257879-user-admin-approval-admin-email-notification.yml5
-rw-r--r--changelogs/unreleased/257880-user-admin-approval-email-when-approved.yml5
-rw-r--r--changelogs/unreleased/258209-filters-params-remain-when-switching-tabs.yml5
-rw-r--r--changelogs/unreleased/258215-add-fuzzy-search-on-full-path-in-groups.yml5
-rw-r--r--changelogs/unreleased/258215-improve-fuzzy-search-on-full-path-in-groups.yml5
-rw-r--r--changelogs/unreleased/258638-feature-flag-rollout-of-enable_environment_path_in_alert_details.yml5
-rw-r--r--changelogs/unreleased/258980-feature-flag-rollout-of-admin-approval-for-new-user-signups.yml5
-rw-r--r--changelogs/unreleased/258993-render-404-to-bots.yml5
-rw-r--r--changelogs/unreleased/259024-labels-api-search-support.yml5
-rw-r--r--changelogs/unreleased/260340-wiki-render-like-issues.yml5
-rw-r--r--changelogs/unreleased/262096-change-graphql-id-types-for-global-ids.yml5
-rw-r--r--changelogs/unreleased/262112_populate_missing_dismissal_information_for_vulnerabilities.yml5
-rw-r--r--changelogs/unreleased/262395-models-for-devops-adoption-segments.yml5
-rw-r--r--changelogs/unreleased/262640-search-results-return-no-results-when-the-pagination-window-is-out.yml5
-rw-r--r--changelogs/unreleased/263106-user-admin-approval-enable-disable-toggle-require_admin_approval_a.yml6
-rw-r--r--changelogs/unreleased/263109-implement-graphql-startup-js-for-design-management-app.yml5
-rw-r--r--changelogs/unreleased/263144-commit-to-new-branch.yml5
-rw-r--r--changelogs/unreleased/263222-remove-soft-fail-count-by-state-ff.yml5
-rw-r--r--changelogs/unreleased/263252-mr-template-api.yml5
-rw-r--r--changelogs/unreleased/263482-container-scanning-version-3.yml5
-rw-r--r--changelogs/unreleased/263521-add-projects_with_enabled_alert_integrations-usage-ping.yml5
-rw-r--r--changelogs/unreleased/263552-number-of-projects-active-alerts.yml5
-rw-r--r--changelogs/unreleased/266946-minimal-access-members-are-not-listed-in-saml.yml5
-rw-r--r--changelogs/unreleased/266986-update-img-resizing-ffs.yml5
-rw-r--r--changelogs/unreleased/267010-improve-group-packages-finder.yml5
-rw-r--r--changelogs/unreleased/267113-separate-new-group-project-creation-button.yml5
-rw-r--r--changelogs/unreleased/267147-graphql-total-count.yml5
-rw-r--r--changelogs/unreleased/267147-terraform-list.yml5
-rw-r--r--changelogs/unreleased/267147-terraform-state-versions-graphql.yml5
-rw-r--r--changelogs/unreleased/267168-add-ci-build-to-terraform-state-version-graphql-type.yml5
-rw-r--r--changelogs/unreleased/267168-add-pipeline-to-ci-job-type.yml5
-rw-r--r--changelogs/unreleased/267168-set-build-on-terraform-state-version-creation.yml5
-rw-r--r--changelogs/unreleased/267191-project-access-tokens-delete-project-bot-after-it-s-removed-from-p.yml5
-rw-r--r--changelogs/unreleased/267394-improve-search-empty-message.yml5
-rw-r--r--changelogs/unreleased/267492-change-to-enabled-sp-ff.yml5
-rw-r--r--changelogs/unreleased/267495-add-sha256-of-pages-contents-to-pages_deployments.yml5
-rw-r--r--changelogs/unreleased/267568-user-admin-approval-default-for-new-instances.yml5
-rw-r--r--changelogs/unreleased/267828-remove-minimum_interval-from-backgroundmigrationworker.yml5
-rw-r--r--changelogs/unreleased/267963-related-merge-requests-icon-in-issues-list-is-rendered-incorrectly.yml5
-rw-r--r--changelogs/unreleased/268000-extend-graphql-measurements-api.yml5
-rw-r--r--changelogs/unreleased/268133-fix-propagate-integrations-for-project-callback.yml5
-rw-r--r--changelogs/unreleased/268248-remove-index-service-for-usage-data.yml5
-rw-r--r--changelogs/unreleased/268301-mr-ide-button.yml5
-rw-r--r--changelogs/unreleased/268315-restructure-project-page-title-to-show-project-name-first.yml5
-rw-r--r--changelogs/unreleased/26873-add-webhooks-for-releases.yml5
-rw-r--r--changelogs/unreleased/26952-fix-viewing-legacy-diff-notes-in-discussion.yml5
-rw-r--r--changelogs/unreleased/26963-fix-empty-state-in-explore-projects-pages.yml5
-rw-r--r--changelogs/unreleased/270051-fj-generate-sitmap-dot-com.yml5
-rw-r--r--changelogs/unreleased/270065-bs4-optimization-diffs.yml5
-rw-r--r--changelogs/unreleased/270065-bs4-optimization-issue.yml5
-rw-r--r--changelogs/unreleased/270065-bs4-optimization-mr.yml5
-rw-r--r--changelogs/unreleased/270106_enable_csp_for_sse.yml5
-rw-r--r--changelogs/unreleased/270116-region-field.yml5
-rw-r--r--changelogs/unreleased/270200-downtier-pat-apis.yml5
-rw-r--r--changelogs/unreleased/270208-add-application-settings-columns.yml5
-rw-r--r--changelogs/unreleased/270409-experiment-cleanup-discover-security.yml6
-rw-r--r--changelogs/unreleased/270412-license-error-in-template.yml5
-rw-r--r--changelogs/unreleased/270420-fj-add-explore-canonical-link.yml5
-rw-r--r--changelogs/unreleased/270439-enable-ci_seed_block_run_before_workflow_rules.yml5
-rw-r--r--changelogs/unreleased/270470-no-query-new-snippet.yml5
-rw-r--r--changelogs/unreleased/27142-divider-in-readme-is-overlaying-with-image-anchor-solution.yml5
-rw-r--r--changelogs/unreleased/271459-fix-remove-label-inconsistency.yml5
-rw-r--r--changelogs/unreleased/271528-todo-css-on-mobile.yml5
-rw-r--r--changelogs/unreleased/271542-prefetch-requests-link.yml5
-rw-r--r--changelogs/unreleased/271550-fj-forbid-realtime_changes-in-robots.yml5
-rw-r--r--changelogs/unreleased/271560-enable-ci_include_multiple_files_from_project.yml5
-rw-r--r--changelogs/unreleased/271589-report-abuse-on-merged-mr.yml5
-rw-r--r--changelogs/unreleased/271635-new-project-access-tokens-do-not-show-in-active-project-access-tok.yml5
-rw-r--r--changelogs/unreleased/272984-fj-forbid-autocomplete-projects.yml5
-rw-r--r--changelogs/unreleased/272986-fj-disallow-webide-route-in-robots.yml5
-rw-r--r--changelogs/unreleased/273001-terraform-list-update.yml5
-rw-r--r--changelogs/unreleased/273002-full-project-issue-boards-api-on-ce.yml5
-rw-r--r--changelogs/unreleased/273016-replace-ace-merge-conflicts.yml5
-rw-r--r--changelogs/unreleased/273134-add_web_usage_data_for_geo_secondaries.yml5
-rw-r--r--changelogs/unreleased/273140-fix-transaction-issue-in-container-expiration-policy-worker.yml5
-rw-r--r--changelogs/unreleased/273142-fj-enable-avatar-with-full-url.yml5
-rw-r--r--changelogs/unreleased/273148-fj-disallow-some-project-routes.yml5
-rw-r--r--changelogs/unreleased/273261-not-able-to-set-comment-settings-for-jira.yml5
-rw-r--r--changelogs/unreleased/273356-remove-sql_set_operators-feature-flag.yml5
-rw-r--r--changelogs/unreleased/273434-add-message-in-ci-linter-that-it-was-validated-with-all-the-includ.yml5
-rw-r--r--changelogs/unreleased/273541-issue-template-warning-appears-above-type-field.yml5
-rw-r--r--changelogs/unreleased/273623-replace-sign-in-text-with-sign-in-text.yml5
-rw-r--r--changelogs/unreleased/273655-dependency-proxy-to-core.yml5
-rw-r--r--changelogs/unreleased/273739-pipeline-tooltips-cover-the-entire-element.yml5
-rw-r--r--changelogs/unreleased/273750-fj-structured-data-for-users.yml5
-rw-r--r--changelogs/unreleased/273801-graphql-fuzzy-search-users.yml5
-rw-r--r--changelogs/unreleased/273813-rename-cycle-analytics-with-value-stream-analytics-in-strings-unde.yml5
-rw-r--r--changelogs/unreleased/275899-share-view-code-for-mr-issue-search-results.yml5
-rw-r--r--changelogs/unreleased/276185_alerts_integrations_list_tracking.yml5
-rw-r--r--changelogs/unreleased/276440-check-all-pipeline-jobs-for-security-artifacts-in-basic-security-m.yml5
-rw-r--r--changelogs/unreleased/276444-default-vue_issue_header-feature-flag-to-on.yml5
-rw-r--r--changelogs/unreleased/276911-fix-ruby-lexer-rouge-bug.yml5
-rw-r--r--changelogs/unreleased/277369-typeerror-can-t-quote-activesupport-hashwithindifferentaccess.yml5
-rw-r--r--changelogs/unreleased/277457-saml-admin.yml5
-rw-r--r--changelogs/unreleased/280553-cache-raw-endpoint.yml5
-rw-r--r--changelogs/unreleased/280795-stop-finding-commit-empty-ref.yml5
-rw-r--r--changelogs/unreleased/280811-mr-analytics-chart-tooltip-overlays-filter-dropdown.yml5
-rw-r--r--changelogs/unreleased/281020-dark-mode-isn-t-compabile-with-secure-mr-widget.yml5
-rw-r--r--changelogs/unreleased/281378-fj-add-absolute-urls-to-schema-breadcrumb.yml5
-rw-r--r--changelogs/unreleased/281571-fix-blob-header-button-styles.yml5
-rw-r--r--changelogs/unreleased/281697-fj-fix-snippet-resolvers.yml5
-rw-r--r--changelogs/unreleased/282499-deploy-token-read-package.yml5
-rw-r--r--changelogs/unreleased/283924-user-profile.yml5
-rw-r--r--changelogs/unreleased/30101-fix-includes.yml5
-rw-r--r--changelogs/unreleased/31528-fix-pipelines-charts-timeout.yml5
-rw-r--r--changelogs/unreleased/35404-automatic-rollback-in-case-of-failure.yml5
-rw-r--r--changelogs/unreleased/36820-fj-add-generic-canonical-url.yml5
-rw-r--r--changelogs/unreleased/36836-fj-allow-indexing-snippets-in-robots.yml5
-rw-r--r--changelogs/unreleased/36837-fj-fix-bug-robots-git-suffix.yml5
-rw-r--r--changelogs/unreleased/36844-fj-add-schema-to-breadcrumb-json.yml5
-rw-r--r--changelogs/unreleased/36846-fj-add-structured-data-for-projects.yml5
-rw-r--r--changelogs/unreleased/37102-expose-human-readable-time-estimate-via-graphql.yml5
-rw-r--r--changelogs/unreleased/46087.yml5
-rw-r--r--changelogs/unreleased/47531-fix-secure-bin-tmpl.yml5
-rw-r--r--changelogs/unreleased/7314-backup-files-noncritical-warnings.yml6
-rw-r--r--changelogs/unreleased/Add-Caching-To-BitBucket-Server-Importer.yml5
-rw-r--r--changelogs/unreleased/Change-BitBucket-Pull-Request-Import-to-a-Batched-Process.yml5
-rw-r--r--changelogs/unreleased/Fix-bad-escape-in-empty_state-vue.yml5
-rw-r--r--changelogs/unreleased/ImproveShellScriptsChangeDirException.yml5
-rw-r--r--changelogs/unreleased/ImproveShellScriptsVariable.yml5
-rw-r--r--changelogs/unreleased/Migrate-Bootstrap-dropdown-to-GitLab-UI-GlDropdown-in-app-assets-javascri.yml5
-rw-r--r--changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-er.yml5
-rw-r--r--changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-mo.yml5
-rw-r--r--changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-re.yml5
-rw-r--r--changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-sn.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-helpers.yml5
-rw-r--r--changelogs/unreleased/ab-add-missing-expression-indexes.yml5
-rw-r--r--changelogs/unreleased/ab-primary-keys.yml5
-rw-r--r--changelogs/unreleased/ab-reindex-functional.yml5
-rw-r--r--changelogs/unreleased/add-ci-status-css-to-environments.yml5
-rw-r--r--changelogs/unreleased/add-emails-disabled-field-to-project-type.yml5
-rw-r--r--changelogs/unreleased/add-get-invitations-for-group-and-project.yml5
-rw-r--r--changelogs/unreleased/add-github-host-to-api.yml5
-rw-r--r--changelogs/unreleased/add-helm3-support-for-cluster-apps.yml5
-rw-r--r--changelogs/unreleased/add-nulls-last-to-db-index.yml5
-rw-r--r--changelogs/unreleased/add-post-invitations-with-email.yml5
-rw-r--r--changelogs/unreleased/add-total-duration-to-cicd-analytics-page.yml5
-rw-r--r--changelogs/unreleased/add-user-discussions-count-to-issues-and-merge-requests.yml5
-rw-r--r--changelogs/unreleased/add_existing_column_check_to_46532.yml5
-rw-r--r--changelogs/unreleased/add_msg_for_missing_license_covfuzz.yml5
-rw-r--r--changelogs/unreleased/add_tooltips_to_design_buttons.yml5
-rw-r--r--changelogs/unreleased/ajk-214978-designs-iids.yml5
-rw-r--r--changelogs/unreleased/ajk-globalid-error-tracking.yml5
-rw-r--r--changelogs/unreleased/ajk-globalid-snippets.yml5
-rw-r--r--changelogs/unreleased/ajk-group-member-policy.yml5
-rw-r--r--changelogs/unreleased/ak-fix-chatbot-replies.yml5
-rw-r--r--changelogs/unreleased/ak-fix-loading-file.yml5
-rw-r--r--changelogs/unreleased/alexives-258262-remove_columns_for_tf_state_validation.yml5
-rw-r--r--changelogs/unreleased/alipniagov-update-workhorse-to-8-54.yml5
-rw-r--r--changelogs/unreleased/allow_repo_storage_moves_without_repo.yml5
-rw-r--r--changelogs/unreleased/arty-admin-idpid.yml5
-rw-r--r--changelogs/unreleased/ashmckenzie-gitlab-shell-release-13-13-0.yml5
-rw-r--r--changelogs/unreleased/bjk-http_requests_total_status_matrix.yml5
-rw-r--r--changelogs/unreleased/boards-css-clean-up.yml5
-rw-r--r--changelogs/unreleased/bvl-handle-invalid-headers.yml5
-rw-r--r--changelogs/unreleased/bvl-reject-more-invalid-utf8.yml5
-rw-r--r--changelogs/unreleased/cablett-231472-group-labels.yml5
-rw-r--r--changelogs/unreleased/cache-raw-endpoints-for-logged-in-users.yml5
-rw-r--r--changelogs/unreleased/cat-fix-sprite-failed-builds.yml5
-rw-r--r--changelogs/unreleased/cat-readd-logging-for-ints-273663.yml5
-rw-r--r--changelogs/unreleased/chore-disable-admin-mode-in-services.yml5
-rw-r--r--changelogs/unreleased/ci-enable-variable-expansion-in-rules-changes.yml5
-rw-r--r--changelogs/unreleased/ci-jwt-signing-key-enable-by-default.yml5
-rw-r--r--changelogs/unreleased/cleanup_policy_regex_defaults.yml5
-rw-r--r--changelogs/unreleased/cngo-remove-positive-tabindexes.yml5
-rw-r--r--changelogs/unreleased/dast-site-validation-create-mutation-233020.yml5
-rw-r--r--changelogs/unreleased/dblessing_auth_events_usage_ping_fix.yml5
-rw-r--r--changelogs/unreleased/debian_parsers.yml5
-rw-r--r--changelogs/unreleased/defect-collapsed-files-expand-renamed-files.yml5
-rw-r--r--changelogs/unreleased/defect-fork-general-settings-copy.yml5
-rw-r--r--changelogs/unreleased/delete_tags_service_logging_enhancement.yml6
-rw-r--r--changelogs/unreleased/deprecate-support-for-es6.yml5
-rw-r--r--changelogs/unreleased/design-upload-button-loading-prop.yml5
-rw-r--r--changelogs/unreleased/dj-fix-anchor-linebreak-issue.yml5
-rw-r--r--changelogs/unreleased/dmishunov-276913-snippet-copy-content.yml5
-rw-r--r--changelogs/unreleased/docs-api-boards.yml5
-rw-r--r--changelogs/unreleased/docs-for-canary-ingress-weight-change.yml5
-rw-r--r--changelogs/unreleased/dstull-update-whitelist-blacklist-to-allowlist-denylist-in-signup-restric.yml5
-rw-r--r--changelogs/unreleased/eb-remove-tracking-test-cases-feature-flag.yml5
-rw-r--r--changelogs/unreleased/eb-test-failure-history-mvc.yml5
-rw-r--r--changelogs/unreleased/ek-fix-set-status-modal-tooltip-trigger.yml5
-rw-r--r--changelogs/unreleased/emilyring-state-pagination.yml5
-rw-r--r--changelogs/unreleased/emilyring-terraform-fixes.yml5
-rw-r--r--changelogs/unreleased/enable-ci-deleted-objects-ff.yml5
-rw-r--r--changelogs/unreleased/enable-deployments-filters.yml5
-rw-r--r--changelogs/unreleased/enable_instance_statistics_ff_by_default.yml5
-rw-r--r--changelogs/unreleased/feat-scoverage-ci-regex.yml5
-rw-r--r--changelogs/unreleased/feature-change-reactive-caching-limit-environment-default-to-true.yml6
-rw-r--r--changelogs/unreleased/feature-collapsed-diff-files-larger-ui.yml5
-rw-r--r--changelogs/unreleased/feature-collapsed-diff-files-user-collapsed-flag.yml6
-rw-r--r--changelogs/unreleased/feature-flags-edit-increase-loading-icon-size.yml5
-rw-r--r--changelogs/unreleased/feature-flags-user-lists-search.yml5
-rw-r--r--changelogs/unreleased/feature-group-default-initial-branch-name.yml5
-rw-r--r--changelogs/unreleased/feature-mr-diffs-performance-marks.yml5
-rw-r--r--changelogs/unreleased/ff-export_merge_requests_as_csv-default-on.yml5
-rw-r--r--changelogs/unreleased/fix-api-boards-docs-ee.yml5
-rw-r--r--changelogs/unreleased/fix-api-boards-docs.yml5
-rw-r--r--changelogs/unreleased/fix-broken-paperclip.yml5
-rw-r--r--changelogs/unreleased/fix-ci-lint-newlines.yml5
-rw-r--r--changelogs/unreleased/fix-deprecated-stable-repository-error.yml5
-rw-r--r--changelogs/unreleased/fix-empty-user-list-dropdown-text.yml5
-rw-r--r--changelogs/unreleased/fix-issues-list-with-invalid-due-date.yml5
-rw-r--r--changelogs/unreleased/fix-modal-margins.yml5
-rw-r--r--changelogs/unreleased/fix-padding-on-failed-job-tab.yml5
-rw-r--r--changelogs/unreleased/fix-search-bar-feature-flags.yml5
-rw-r--r--changelogs/unreleased/fix_sdesk_links.yml6
-rw-r--r--changelogs/unreleased/fj-change-routable-redirect-to-301.yml5
-rw-r--r--changelogs/unreleased/fj-fix-bug-when-user-anonymous-and-import.yml5
-rw-r--r--changelogs/unreleased/fj-forbid-snippet-route.yml5
-rw-r--r--changelogs/unreleased/fj-forbid-top-level-route-sitemap.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-add-usage-ping-total-projects-imported.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-ignore-failed-to-download-project-export-uploads.yml6
-rw-r--r--changelogs/unreleased/georgekoltsov-use-github-api-for-filtering.yml5
-rw-r--r--changelogs/unreleased/gl-tooltip-for-quick-submit.yml5
-rw-r--r--changelogs/unreleased/graphql_create_label.yml5
-rw-r--r--changelogs/unreleased/gregmyers-webhook-useragent.yml5
-rw-r--r--changelogs/unreleased/group-level-integration-feature-flag-default-enable.yml5
-rw-r--r--changelogs/unreleased/gy-fix-load-perf-docs.yml5
-rw-r--r--changelogs/unreleased/himkp-fix-ide-discard.yml5
-rw-r--r--changelogs/unreleased/id-change-default-for-ci-max-artifact-size-lsif.yml5
-rw-r--r--changelogs/unreleased/id-track-git-write-operations.yml5
-rw-r--r--changelogs/unreleased/improve_performance_of_has_vulnerabilities_scope.yml5
-rw-r--r--changelogs/unreleased/increase-dotenv-variable-count.yml5
-rw-r--r--changelogs/unreleased/issue-277354.yml5
-rw-r--r--changelogs/unreleased/issue_233479-add-graphql-create-todo-mutation.yml5
-rw-r--r--changelogs/unreleased/issue_233479-add_updated_by_for_issue_type.yml5
-rw-r--r--changelogs/unreleased/issue_243790.yml5
-rw-r--r--changelogs/unreleased/jdb-fix-comment-cell-inline.yml5
-rw-r--r--changelogs/unreleased/jdb-fix-unified-diffs-inline.yml5
-rw-r--r--changelogs/unreleased/jduplessis_issue_comment_link.yml5
-rw-r--r--changelogs/unreleased/jh-235732_csv_import_gmau.yml5
-rw-r--r--changelogs/unreleased/jh-github_search.yml5
-rw-r--r--changelogs/unreleased/jh-migration_mvc_gmau.yml6
-rw-r--r--changelogs/unreleased/jira_connect_sync_namespace_worker.yml5
-rw-r--r--changelogs/unreleased/jivanvl-add-pagination-specific-runners.yml5
-rw-r--r--changelogs/unreleased/jivanvl-remove-ci-variables-table-feature-flag.yml5
-rw-r--r--changelogs/unreleased/jivanvl-runner-guided-install-frontend.yml5
-rw-r--r--changelogs/unreleased/jivanvl-update-prometheus-metrics-icons.yml5
-rw-r--r--changelogs/unreleased/job-dropdown-click.yml5
-rw-r--r--changelogs/unreleased/jv-add-rate-limit-bypass.yml5
-rw-r--r--changelogs/unreleased/kassio-bulkimport-entity-trackers.yml6
-rw-r--r--changelogs/unreleased/kassio-fix-bitbucket-server-importer-lfs.yml5
-rw-r--r--changelogs/unreleased/kerrizor-increase-default-diff_max_patch_bytes.yml5
-rw-r--r--changelogs/unreleased/kp-fix-labels-dropdown-search-autofocus.yml5
-rw-r--r--changelogs/unreleased/kubernetes_cluster_namespace_role_admin_role_ref.yml6
-rw-r--r--changelogs/unreleased/labkit-bump.yml5
-rw-r--r--changelogs/unreleased/lfs-ssh-authentication.yml5
-rw-r--r--changelogs/unreleased/lm-add-ci-lint-warnings.yml5
-rw-r--r--changelogs/unreleased/lm-upstream-downstream-pipeline.yml5
-rw-r--r--changelogs/unreleased/mb_rails_save_bang_fix5.yml5
-rw-r--r--changelogs/unreleased/mc-bug-fix-k8s-docker-runner-setup.yml5
-rw-r--r--changelogs/unreleased/mc-feature-add-ci-yaml-parmeter-to-project-lint.yml5
-rw-r--r--changelogs/unreleased/migrate-feature-flags-config-to-gitlab-ui.yml5
-rw-r--r--changelogs/unreleased/migrate-terminal-alert.yml5
-rw-r--r--changelogs/unreleased/mk-console-ruby-version.yml5
-rw-r--r--changelogs/unreleased/mk-workhorse-8-53-0.yml5
-rw-r--r--changelogs/unreleased/mo-add-default-branch-to-daily-build.yml5
-rw-r--r--changelogs/unreleased/mo-bump-codequality.yml5
-rw-r--r--changelogs/unreleased/more-coverage-badges.yml5
-rw-r--r--changelogs/unreleased/move-security-jobs-finder-out-of-ee.yml5
-rw-r--r--changelogs/unreleased/move-timebox-reports-graphql.yml5
-rw-r--r--changelogs/unreleased/msj-migrate-toggle-replies-widget.yml5
-rw-r--r--changelogs/unreleased/mvrachni-OKR-button-migration.yml5
-rw-r--r--changelogs/unreleased/mw-replace-fa-check-in-importer-status.yml5
-rw-r--r--changelogs/unreleased/mw-replace-fa-chevron-down-dropdown-button.yml5
-rw-r--r--changelogs/unreleased/mw-replace-fa-chevron-duown-in-project-level-vsa.yml5
-rw-r--r--changelogs/unreleased/mw-replace-fa-exclamation-triangle-markdown.yml5
-rw-r--r--changelogs/unreleased/mw-replace-fa-icons-custom-notifications.yml5
-rw-r--r--changelogs/unreleased/mw-replace-fa-icons-in-pipeline-action-button.yml5
-rw-r--r--changelogs/unreleased/mw-replace-fa-refresh-icons.yml5
-rw-r--r--changelogs/unreleased/mw-use-sprite-icon-in-audit-icon-helper.yml5
-rw-r--r--changelogs/unreleased/new-pipeline-form-default-true.yml5
-rw-r--r--changelogs/unreleased/nfriend-add-graphql-release-sorting.yml5
-rw-r--r--changelogs/unreleased/nfriend-add-release-create-mutation.yml5
-rw-r--r--changelogs/unreleased/nfriend-add-release-progress-link-paths.yml6
-rw-r--r--changelogs/unreleased/nfriend-fix-milestone-array-payload.yml5
-rw-r--r--changelogs/unreleased/nfriend-make-release_mr_issue_urls-enabled-by-default.yml5
-rw-r--r--changelogs/unreleased/nfriend-move-copy-branch-shortcut.yml5
-rw-r--r--changelogs/unreleased/nfriend-update-tag-name-placeholder.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-fix-bm-close-icon.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-new-invite-mail-design.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-remove-storage-size-limit-column.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-split-signin-and-signup.yml5
-rw-r--r--changelogs/unreleased/nmezzopera-refactor-details-fetch-2.yml5
-rw-r--r--changelogs/unreleased/okr-components-tooltip-ide-commit-sidebar.yml5
-rw-r--r--changelogs/unreleased/okr-compontent-tooltip-awards-list.yml5
-rw-r--r--changelogs/unreleased/okr-tooltip-merge-button-sidebar-ide.yml5
-rw-r--r--changelogs/unreleased/okr-tooltip-mr-widget-author-vue.yml5
-rw-r--r--changelogs/unreleased/pb-clear-merge-ref-sha-reopen.yml5
-rw-r--r--changelogs/unreleased/ph-225303-fixCreateBranchButtonSpinner.yml5
-rw-r--r--changelogs/unreleased/ph-227159-fixMultiLineCommentsOptionsInParallelView.yml5
-rw-r--r--changelogs/unreleased/ph-233486-removeDraftIsNotFilter.yml5
-rw-r--r--changelogs/unreleased/ph-235185-fixCreateMRDropdownReopen.yml6
-rw-r--r--changelogs/unreleased/ph-25973-mergeRequestSidebarLongPathTruncating.yml5
-rw-r--r--changelogs/unreleased/ph-280579-fixDiffMetadataStartupJS.yml5
-rw-r--r--changelogs/unreleased/ph-28750-removeResolveCommentButton.yml5
-rw-r--r--changelogs/unreleased/ph-filterTargetBranchByNotEquals.yml5
-rw-r--r--changelogs/unreleased/ph-removeResolveNoteDefaultEnabled.yml5
-rw-r--r--changelogs/unreleased/pks-require-git-v2-29-0.yml5
-rw-r--r--changelogs/unreleased/pl-fix-operations-settings-wo-pipelines.yml5
-rw-r--r--changelogs/unreleased/ps-fix-new-project-margin.yml5
-rw-r--r--changelogs/unreleased/ps-fix-repo-tree-header-button-styles.yml5
-rw-r--r--changelogs/unreleased/ps-move-haml-vue-access-tokens.yml5
-rw-r--r--changelogs/unreleased/psi-mr-space.yml5
-rw-r--r--changelogs/unreleased/queue-selector-not-experimental.yml5
-rw-r--r--changelogs/unreleased/rc-remove_sync_metrics_dashboard_ff.yml5
-rw-r--r--changelogs/unreleased/refactor-secondary_navigation_elements.yml5
-rw-r--r--changelogs/unreleased/remove-ci_always_refresh_merge_requests_from_beginning-flag.yml6
-rw-r--r--changelogs/unreleased/remove-cycle-analytics-from-en.yml5
-rw-r--r--changelogs/unreleased/remove-graphql_lazy_authorization-ff.yml5
-rw-r--r--changelogs/unreleased/remove-merge-base-pipelines-feature-flag.yml5
-rw-r--r--changelogs/unreleased/remove_scanned_resources_count_from_security_scan_229773.yml5
-rw-r--r--changelogs/unreleased/replace-GLDeprecatedBadge-in-clusters-vue.yml5
-rw-r--r--changelogs/unreleased/replace-GlDepractedBadge-in-environment_header.yml5
-rw-r--r--changelogs/unreleased/replace-GlDeprecated-Badge-for-GlBadge-in-requirements-tabs.yml5
-rw-r--r--changelogs/unreleased/reschedule_blocked_by.yml6
-rw-r--r--changelogs/unreleased/restore-spacing-mr-list-for-mobile.yml5
-rw-r--r--changelogs/unreleased/revert-15df30d0.yml5
-rw-r--r--changelogs/unreleased/revert-tz-defer-frequent-item-init.yml5
-rw-r--r--changelogs/unreleased/rmay-216344-2.yml5
-rw-r--r--changelogs/unreleased/rmay-216344.yml5
-rw-r--r--changelogs/unreleased/set-user-availability-be.yml5
-rw-r--r--changelogs/unreleased/sh-add-redis-version-to-admin-page.yml5
-rw-r--r--changelogs/unreleased/sh-build-trace-chunk-store-thread-safety.yml5
-rw-r--r--changelogs/unreleased/sh-bump-gitlab-shell-13-12.yml5
-rw-r--r--changelogs/unreleased/sh-enable-sidekiq-arg-logging-default.yml5
-rw-r--r--changelogs/unreleased/sh-fix-artifacts-not-working-with-no-nginx.yml5
-rw-r--r--changelogs/unreleased/sh-hashed-storage-no-destroy-namespace-dir.yml5
-rw-r--r--changelogs/unreleased/sh-lfs-replace-deleted-file.yml5
-rw-r--r--changelogs/unreleased/sh-remove-legacy-fog-ff.yml5
-rw-r--r--changelogs/unreleased/sh-update-rack-2-2-3.yml5
-rw-r--r--changelogs/unreleased/sh-upgrade-fog-google.yml5
-rw-r--r--changelogs/unreleased/sh-upgrade-ruby-2-7-2-ci.yml5
-rw-r--r--changelogs/unreleased/sh-upgrade-workhorse-8-52-0.yml5
-rw-r--r--changelogs/unreleased/show_build_status_in_tag_list.yml5
-rw-r--r--changelogs/unreleased/sk-220898-feature-flag-webhook.yml5
-rw-r--r--changelogs/unreleased/skip-importing-features-disabled-in-gitea.yml5
-rw-r--r--changelogs/unreleased/ss-add-assignee-dropdown.yml5
-rw-r--r--changelogs/unreleased/ss-add-multiselect-wrapper.yml5
-rw-r--r--changelogs/unreleased/ss-add-wip-limits-license-check.yml5
-rw-r--r--changelogs/unreleased/ss-assignee-dropdown-search.yml5
-rw-r--r--changelogs/unreleased/sy-add-new-incidents-to-usage-ping.yml5
-rw-r--r--changelogs/unreleased/sy-ff-removal-multiple-http-endpoints.yml5
-rw-r--r--changelogs/unreleased/sy-swap-alert-email-api.yml5
-rw-r--r--changelogs/unreleased/tancnle-fix-jupyter-notebook-overflow.yml5
-rw-r--r--changelogs/unreleased/terraform-base-avoid-before-script.yml5
-rw-r--r--changelogs/unreleased/token-revocation.yml5
-rw-r--r--changelogs/unreleased/update-cluster-applications-0-34-1.yml5
-rw-r--r--changelogs/unreleased/update-design-scaler-component.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-22-0.yml5
-rw-r--r--changelogs/unreleased/update-haml_lint-to-0-36-0.yml5
-rw-r--r--changelogs/unreleased/upgrade-pages-1-29-0.yml5
-rw-r--r--changelogs/unreleased/upgrade-pages-1-30.yml5
-rw-r--r--changelogs/unreleased/use-longer-agentk-token.yml5
-rw-r--r--changelogs/unreleased/vfazio-update-rack-oauth2.yml5
-rw-r--r--changelogs/unreleased/vij-add-cloud-license-token.yml5
-rw-r--r--changelogs/unreleased/vij-add-snippet-repo-readonly.yml5
-rw-r--r--changelogs/unreleased/vij-add-storage-move-table.yml5
-rw-r--r--changelogs/unreleased/vij-fix-inconsistent-branch-names.yml5
-rw-r--r--changelogs/unreleased/vs-admin-new-user-signups.yml5
-rw-r--r--changelogs/unreleased/whole-number-to-integer.yml5
-rw-r--r--changelogs/unreleased/wiki-delete.yml5
-rw-r--r--changelogs/unreleased/wiki-toast.yml5
-rw-r--r--changelogs/unreleased/workaround_for_non_unique_project_fingerprints.yml5
-rw-r--r--changelogs/unreleased/zip_pages_deployments_true.yml5
-rw-r--r--config/application.rb17
-rw-r--r--config/environments/development.rb2
-rw-r--r--config/environments/test.rb4
-rw-r--r--config/feature_categories.yml7
-rw-r--r--config/feature_flags/development/additional_snowplow_tracking.yml6
-rw-r--r--config/feature_flags/development/admin_approval_for_new_user_signups.yml7
-rw-r--r--config/feature_flags/development/ajax_new_deploy_token.yml3
-rw-r--r--config/feature_flags/development/allow_group_deploy_token.yml3
-rw-r--r--config/feature_flags/development/allow_possible_spam.yml3
-rw-r--r--config/feature_flags/development/allow_unsafe_ruby_regexp.yml3
-rw-r--r--config/feature_flags/development/api_json_content_type.yml8
-rw-r--r--config/feature_flags/development/application_settings_tokens_optional_encryption.yml3
-rw-r--r--config/feature_flags/development/approval_suggestions.yml5
-rw-r--r--config/feature_flags/development/approvals_commented_by.yml5
-rw-r--r--config/feature_flags/development/archive_rate_limit.yml3
-rw-r--r--config/feature_flags/development/artifacts_management_page.yml3
-rw-r--r--config/feature_flags/development/async_commit_diff_files.yml5
-rw-r--r--config/feature_flags/development/auto_create_cluster_management_project.yml3
-rw-r--r--config/feature_flags/development/auto_devops_banner_disabled.yml5
-rw-r--r--config/feature_flags/development/batch_suggestions.yml3
-rw-r--r--config/feature_flags/development/bitbucket_server_user_mapping_by_username.yml5
-rw-r--r--config/feature_flags/development/block_anonymous_global_searches.yml5
-rw-r--r--config/feature_flags/development/boards_with_swimlanes.yml9
-rw-r--r--config/feature_flags/development/branch_list_keyset_pagination.yml5
-rw-r--r--config/feature_flags/development/broadcast_issue_updates.yml3
-rw-r--r--config/feature_flags/development/build_service_proxy.yml5
-rw-r--r--config/feature_flags/development/builds.yml3
-rw-r--r--config/feature_flags/development/bulk_import.yml3
-rw-r--r--config/feature_flags/development/bulk_update_health_status.yml7
-rw-r--r--config/feature_flags/development/burnup_charts.yml9
-rw-r--r--config/feature_flags/development/cached_markdown_blob.yml1
-rw-r--r--config/feature_flags/development/canary_ingress_weight_control.yml3
-rw-r--r--config/feature_flags/development/cd_auto_rollback.yml8
-rw-r--r--config/feature_flags/development/chatops.yml3
-rw-r--r--config/feature_flags/development/ci_always_refresh_merge_requests_from_beginning.yml7
-rw-r--r--config/feature_flags/development/ci_artifacts_exclude.yml5
-rw-r--r--config/feature_flags/development/ci_auto_cancel_all_pipelines.yml8
-rw-r--r--config/feature_flags/development/ci_bridge_dependency_variables.yml7
-rw-r--r--config/feature_flags/development/ci_build_metadata_config.yml5
-rw-r--r--config/feature_flags/development/ci_delete_objects_high_concurrency.yml5
-rw-r--r--config/feature_flags/development/ci_delete_objects_low_concurrency.yml7
-rw-r--r--config/feature_flags/development/ci_delete_objects_medium_concurrency.yml5
-rw-r--r--config/feature_flags/development/ci_disable_validates_dependencies.yml3
-rw-r--r--config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml3
-rw-r--r--config/feature_flags/development/ci_dynamic_child_pipeline.yml5
-rw-r--r--config/feature_flags/development/ci_enable_live_trace.yml5
-rw-r--r--config/feature_flags/development/ci_include_multiple_files_from_project.yml8
-rw-r--r--config/feature_flags/development/ci_instance_variables_ui.yml5
-rw-r--r--config/feature_flags/development/ci_job_jwt.yml7
-rw-r--r--config/feature_flags/development/ci_job_line_links.yml8
-rw-r--r--config/feature_flags/development/ci_jobs_finder_refactor.yml7
-rw-r--r--config/feature_flags/development/ci_jwt_signing_key.yml8
-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_manual_bridges.yml1
-rw-r--r--config/feature_flags/development/ci_pipeline_editor_page.yml8
-rw-r--r--config/feature_flags/development/ci_pipeline_latest.yml5
-rw-r--r--config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml3
-rw-r--r--config/feature_flags/development/ci_pipeline_triggers_settings_vue_ui.yml3
-rw-r--r--config/feature_flags/development/ci_raise_job_rules_without_workflow_rules_warning.yml5
-rw-r--r--config/feature_flags/development/ci_runners_tokens_optional_encryption.yml5
-rw-r--r--config/feature_flags/development/ci_seed_block_run_before_workflow_rules.yml8
-rw-r--r--config/feature_flags/development/ci_send_deployment_hook_when_start.yml7
-rw-r--r--config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml3
-rw-r--r--config/feature_flags/development/ci_store_pipeline_messages.yml7
-rw-r--r--config/feature_flags/development/ci_synchronous_artifact_parsing.yml3
-rw-r--r--config/feature_flags/development/ci_trace_new_fog_store.yml7
-rw-r--r--config/feature_flags/development/ci_variable_expansion_in_rules_changes.yml7
-rw-r--r--config/feature_flags/development/ci_yaml_limit_size.yml7
-rw-r--r--config/feature_flags/development/cluster_agent_list.yml7
-rw-r--r--config/feature_flags/development/cluster_management_project.yml3
-rw-r--r--config/feature_flags/development/codequality_mr_diff.yml8
-rw-r--r--config/feature_flags/development/collect_package_events.yml8
-rw-r--r--config/feature_flags/development/collect_package_events_redis.yml7
-rw-r--r--config/feature_flags/development/consolidated_edit_button.yml5
-rw-r--r--config/feature_flags/development/container_expiration_policies_historic_entry.yml1
-rw-r--r--config/feature_flags/development/container_registry_expiration_policies_throttling.yml3
-rw-r--r--config/feature_flags/development/context_commits.yml3
-rw-r--r--config/feature_flags/development/core_security_mr_widget.yml1
-rw-r--r--config/feature_flags/development/count_uploads_size_in_storage_stats.yml8
-rw-r--r--config/feature_flags/development/coverage_fuzzing_mr_widget.yml8
-rw-r--r--config/feature_flags/development/create_cloud_run_clusters.yml5
-rw-r--r--config/feature_flags/development/custom_emoji.yml8
-rw-r--r--config/feature_flags/development/dag_pipeline_tab.yml5
-rw-r--r--config/feature_flags/development/dashboard_pipeline_status.yml3
-rw-r--r--config/feature_flags/development/debian_packages.yml3
-rw-r--r--config/feature_flags/development/default_merge_ref_for_diffs.yml3
-rw-r--r--config/feature_flags/development/deploy_boards_dedupe_instances.yml7
-rw-r--r--config/feature_flags/development/deploy_keys_on_protected_branches.yml3
-rw-r--r--config/feature_flags/development/deploy_tokens_api.yml5
-rw-r--r--config/feature_flags/development/deployment_filters.yml7
-rw-r--r--config/feature_flags/development/design_management_allow_dangerous_images.yml3
-rw-r--r--config/feature_flags/development/devops_adoption_feature.yml8
-rw-r--r--config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml5
-rw-r--r--config/feature_flags/development/disable_shared_runners_on_group.yml7
-rw-r--r--config/feature_flags/development/display_merge_conflicts_in_diff.yml3
-rw-r--r--config/feature_flags/development/drop_license_management_artifact.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.yml3
-rw-r--r--config/feature_flags/development/environment_auto_stop_start_on_create.yml8
-rw-r--r--config/feature_flags/development/export_reduce_relation_batch_size.yml7
-rw-r--r--config/feature_flags/development/expose_environment_path_in_alert_details.yml7
-rw-r--r--config/feature_flags/development/feature_flag_api.yml3
-rw-r--r--config/feature_flags/development/feature_flag_permissions.yml3
-rw-r--r--config/feature_flags/development/feature_flags_legacy_read_only.yml5
-rw-r--r--config/feature_flags/development/feature_flags_legacy_read_only_override.yml3
-rw-r--r--config/feature_flags/development/feature_flags_new_version.yml3
-rw-r--r--config/feature_flags/development/file_identifier_hash.yml3
-rw-r--r--config/feature_flags/development/filter_pipelines_search.yml7
-rw-r--r--config/feature_flags/development/force_autodevops_on_by_default.yml5
-rw-r--r--config/feature_flags/development/forking.yml3
-rw-r--r--config/feature_flags/development/forti_authenticator.yml3
-rw-r--r--config/feature_flags/development/forward_deployment_enabled.yml3
-rw-r--r--config/feature_flags/development/generic_packages.yml3
-rw-r--r--config/feature_flags/development/geo_snippet_repository_replication.yml5
-rw-r--r--config/feature_flags/development/git_push_create_all_pipelines.yml5
-rw-r--r--config/feature_flags/development/gitaly_catfile-cache.yml3
-rw-r--r--config/feature_flags/development/gitaly_deny_disk_access.yml3
-rw-r--r--config/feature_flags/development/gitaly_enforce_requests_limits.yml3
-rw-r--r--config/feature_flags/development/gitaly_mep_mep.yml3
-rw-r--r--config/feature_flags/development/gitlab_ci_yml_preview.yml3
-rw-r--r--config/feature_flags/development/gitlab_org_sitemap.yml8
-rw-r--r--config/feature_flags/development/gitpod.yml3
-rw-r--r--config/feature_flags/development/global_default_branch_name.yml5
-rw-r--r--config/feature_flags/development/go_proxy.yml5
-rw-r--r--config/feature_flags/development/go_proxy_disable_gomod_validation.yml5
-rw-r--r--config/feature_flags/development/grape_gitlab_json.yml5
-rw-r--r--config/feature_flags/development/graphql_board_lists.yml7
-rw-r--r--config/feature_flags/development/graphql_individual_release_page.yml1
-rw-r--r--config/feature_flags/development/graphql_logging.yml5
-rw-r--r--config/feature_flags/development/graphql_milestone_stats.yml5
-rw-r--r--config/feature_flags/development/graphql_pipeline_details.yml7
-rw-r--r--config/feature_flags/development/graphql_pipeline_header.yml3
-rw-r--r--config/feature_flags/development/graphql_release_data.yml5
-rw-r--r--config/feature_flags/development/graphql_releases_page.yml5
-rw-r--r--config/feature_flags/development/group_export_ndjson.yml5
-rw-r--r--config/feature_flags/development/group_import_export.yml7
-rw-r--r--config/feature_flags/development/group_import_ndjson.yml5
-rw-r--r--config/feature_flags/development/group_level_integrations.yml5
-rw-r--r--config/feature_flags/development/groups_tokens_optional_encryption.yml3
-rw-r--r--config/feature_flags/development/help_page_documentation_redirect.yml3
-rw-r--r--config/feature_flags/development/hide_jump_to_next_unresolved_in_threads.yml5
-rw-r--r--config/feature_flags/development/highlight_current_diff_row.yml5
-rw-r--r--config/feature_flags/development/http_integrations_list.yml8
-rw-r--r--config/feature_flags/development/include_lfs_blobs_in_archive.yml7
-rw-r--r--config/feature_flags/development/increased_diff_limits.yml3
-rw-r--r--config/feature_flags/development/ingress_modsecurity.yml3
-rw-r--r--config/feature_flags/development/instance_statistics.yml5
-rw-r--r--config/feature_flags/development/invisible_captcha.yml5
-rw-r--r--config/feature_flags/development/invite_email_experiment.yml7
-rw-r--r--config/feature_flags/development/invite_members_group_modal.yml3
-rw-r--r--config/feature_flags/development/invite_your_teammates_banner_a.yml5
-rw-r--r--config/feature_flags/development/issues.yml3
-rw-r--r--config/feature_flags/development/jira_connect_full_namespace_sync.yml7
-rw-r--r--config/feature_flags/development/jira_for_vulnerabilities.yml7
-rw-r--r--config/feature_flags/development/jira_issues_list.yml8
-rw-r--r--config/feature_flags/development/json_limited_encoder.yml5
-rw-r--r--config/feature_flags/development/json_wrapper_legacy_mode.yml3
-rw-r--r--config/feature_flags/development/junit_pipeline_screenshots_view.yml7
-rw-r--r--config/feature_flags/development/kubernetes_cluster_namespace_role_admin.yml7
-rw-r--r--config/feature_flags/development/lfs_check.yml5
-rw-r--r--config/feature_flags/development/lfs_link_existing_object.yml7
-rw-r--r--config/feature_flags/development/limit_projects_in_groups_api.yml3
-rw-r--r--config/feature_flags/development/log_import_export_relation_creation.yml7
-rw-r--r--config/feature_flags/development/maintenance_mode.yml3
-rw-r--r--config/feature_flags/development/merge_base_pipelines.yml7
-rw-r--r--config/feature_flags/development/merge_orchestration_service.yml3
-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.yml5
-rw-r--r--config/feature_flags/development/merge_ref_auto_sync_lock.yml5
-rw-r--r--config/feature_flags/development/merge_request_cached_pipeline_serializer.yml3
-rw-r--r--config/feature_flags/development/merge_request_draft_filter.yml5
-rw-r--r--config/feature_flags/development/merge_request_rebase_nowait_lock.yml3
-rw-r--r--config/feature_flags/development/merge_request_reviewers.yml3
-rw-r--r--config/feature_flags/development/merge_request_widget_graphql.yml5
-rw-r--r--config/feature_flags/development/merge_requests.yml3
-rw-r--r--config/feature_flags/development/metrics_dashboard.yml3
-rw-r--r--config/feature_flags/development/metrics_dashboard_exhaustive_validations.yml5
-rw-r--r--config/feature_flags/development/migrate_user_mentions.yml3
-rw-r--r--config/feature_flags/development/mr_commit_neighbor_nav.yml5
-rw-r--r--config/feature_flags/development/mrc_api_use_raw_diffs_from_gitaly.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/multiple_http_integrations_custom_mapping.yml8
-rw-r--r--config/feature_flags/development/new_pipeline_form.yml5
-rw-r--r--config/feature_flags/development/new_pipeline_form_prefilled_vars.yml1
-rw-r--r--config/feature_flags/development/new_release_page.yml5
-rw-r--r--config/feature_flags/development/new_variables_ui.yml7
-rw-r--r--config/feature_flags/development/not_issuable_queries.yml5
-rw-r--r--config/feature_flags/development/notes_create_service_tracking.yml3
-rw-r--r--config/feature_flags/development/oj_json.yml7
-rw-r--r--config/feature_flags/development/one_dimensional_matrix.yml7
-rw-r--r--config/feature_flags/development/optimized_issuable_label_filter.yml3
-rw-r--r--config/feature_flags/development/optimized_timebox_queries.yml3
-rw-r--r--config/feature_flags/development/pages.yml3
-rw-r--r--config/feature_flags/development/pages_artifacts_archive.yml7
-rw-r--r--config/feature_flags/development/pages_serve_from_artifacts_archive.yml8
-rw-r--r--config/feature_flags/development/pages_serve_from_deployments.yml8
-rw-r--r--config/feature_flags/development/pages_serve_with_zip_file_protocol.yml8
-rw-r--r--config/feature_flags/development/paginated_notes.yml3
-rw-r--r--config/feature_flags/development/pat_creation_api_for_admin.yml7
-rw-r--r--config/feature_flags/development/personal_snippet_reference_filters.yml3
-rw-r--r--config/feature_flags/development/pg_hint_plan_for_issuables.yml8
-rw-r--r--config/feature_flags/development/phabricator_import.yml3
-rw-r--r--config/feature_flags/development/pipelines_security_report_summary.yml3
-rw-r--r--config/feature_flags/development/product_analytics.yml5
-rw-r--r--config/feature_flags/development/product_analytics_aggregated_metrics.yml8
-rw-r--r--config/feature_flags/development/prohibit_hexadecimal_branch_names.yml3
-rw-r--r--config/feature_flags/development/project_export_as_ndjson.yml5
-rw-r--r--config/feature_flags/development/project_finder_similarity_sort.yml1
-rw-r--r--config/feature_flags/development/project_import_ndjson.yml5
-rw-r--r--config/feature_flags/development/project_list_filter_bar.yml3
-rw-r--r--config/feature_flags/development/project_statistics_sync.yml3
-rw-r--r--config/feature_flags/development/project_transactionless_destroy.yml3
-rw-r--r--config/feature_flags/development/projects_tokens_optional_encryption.yml3
-rw-r--r--config/feature_flags/development/prometheus_computed_alerts.yml3
-rw-r--r--config/feature_flags/development/push_rules_supersede_code_owners.yml7
-rw-r--r--config/feature_flags/development/reactive_caching_limit_environment.yml5
-rw-r--r--config/feature_flags/development/real_time_issue_sidebar.yml3
-rw-r--r--config/feature_flags/development/rebalance_issues.yml5
-rw-r--r--config/feature_flags/development/recursive_approach_for_all_projects.yml1
-rw-r--r--config/feature_flags/development/release_evidence.yml3
-rw-r--r--config/feature_flags/development/release_mr_issue_urls.yml7
-rw-r--r--config/feature_flags/development/remove_legacy_github_client.yml7
-rw-r--r--config/feature_flags/development/remove_resolve_note.yml8
-rw-r--r--config/feature_flags/development/repack_after_shard_migration.yml3
-rw-r--r--config/feature_flags/development/repository.yml3
-rw-r--r--config/feature_flags/development/repository_archive_hotlinking_interception.yml3
-rw-r--r--config/feature_flags/development/resource_access_token_feature.yml8
-rw-r--r--config/feature_flags/development/rugged_commit_is_ancestor.yml3
-rw-r--r--config/feature_flags/development/rugged_commit_tree_entry.yml5
-rw-r--r--config/feature_flags/development/rugged_find_commit.yml3
-rw-r--r--config/feature_flags/development/rugged_list_commits_by_oid.yml5
-rw-r--r--config/feature_flags/development/rugged_tree_entries.yml3
-rw-r--r--config/feature_flags/development/rugged_tree_entry.yml3
-rw-r--r--config/feature_flags/development/saml_group_links.yml8
-rw-r--r--config/feature_flags/development/save_raw_usage_data.yml5
-rw-r--r--config/feature_flags/development/schema_linting.yml3
-rw-r--r--config/feature_flags/development/search_filter_by_confidential.yml7
-rw-r--r--config/feature_flags/development/search_track_unique_users.yml3
-rw-r--r--config/feature_flags/development/security_auto_fix.yml7
-rw-r--r--config/feature_flags/development/security_on_demand_scans_http_header_validation.yml8
-rw-r--r--config/feature_flags/development/security_on_demand_scans_site_validation.yml3
-rw-r--r--config/feature_flags/development/serverless_domain.yml3
-rw-r--r--config/feature_flags/development/service_desk_custom_address.yml3
-rw-r--r--config/feature_flags/development/set_user_availability_status.yml8
-rw-r--r--config/feature_flags/development/settings_operations_prometheus_service.yml3
-rw-r--r--config/feature_flags/development/shared_group_membership_auth.yml8
-rw-r--r--config/feature_flags/development/show_author_on_note.yml5
-rw-r--r--config/feature_flags/development/show_inherited_labels.yml3
-rw-r--r--config/feature_flags/development/similarity_search.yml3
-rw-r--r--config/feature_flags/development/snippet_spam.yml1
-rw-r--r--config/feature_flags/development/snippets.yml3
-rw-r--r--config/feature_flags/development/snippets_binary_blob.yml7
-rw-r--r--config/feature_flags/development/soft_email_confirmation.yml5
-rw-r--r--config/feature_flags/development/soft_fail_count_by_state.yml7
-rw-r--r--config/feature_flags/development/specialized_project_authorization_project_share_worker.yml5
-rw-r--r--config/feature_flags/development/specialized_project_authorization_workers.yml5
-rw-r--r--config/feature_flags/development/sql_set_operators.yml7
-rw-r--r--config/feature_flags/development/squash_options.yml5
-rw-r--r--config/feature_flags/development/sse_erb_support.yml7
-rw-r--r--config/feature_flags/development/sse_image_uploads.yml7
-rw-r--r--config/feature_flags/development/startup_css.yml3
-rw-r--r--config/feature_flags/development/store_ci_pipeline_counts_by_status.yml7
-rw-r--r--config/feature_flags/development/suggest_pipeline.yml8
-rw-r--r--config/feature_flags/development/sync_metrics_dashboards.yml7
-rw-r--r--config/feature_flags/development/test_failure_history.yml8
-rw-r--r--config/feature_flags/development/track_editor_edit_actions.yml3
-rw-r--r--config/feature_flags/development/track_issue_activity_actions.yml5
-rw-r--r--config/feature_flags/development/track_unique_test_cases_parsed.yml7
-rw-r--r--config/feature_flags/development/track_unique_visits.yml3
-rw-r--r--config/feature_flags/development/track_unique_wiki_page_views.yml1
-rw-r--r--config/feature_flags/development/tribute_autocomplete.yml5
-rw-r--r--config/feature_flags/development/two_factor_for_cli.yml1
-rw-r--r--config/feature_flags/development/unified_diff_components.yml7
-rw-r--r--config/feature_flags/development/unified_diff_lines.yml3
-rw-r--r--config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml3
-rw-r--r--config/feature_flags/development/upload_middleware_jwt_params_handler.yml3
-rw-r--r--config/feature_flags/development/usage_data_a_compliance_audit_events_api.yml3
-rw-r--r--config/feature_flags/development/usage_data_api.yml3
-rw-r--r--config/feature_flags/development/usage_data_g_compliance_dashboard.yml7
-rw-r--r--config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_source_code_code_intelligence.yml5
-rw-r--r--config/feature_flags/development/usage_data_i_testing_test_case_parsed.yml5
-rw-r--r--config/feature_flags/development/usage_data_incident_management_alert_assigned.yml3
-rw-r--r--config/feature_flags/development/usage_data_incident_management_alert_status_changed.yml3
-rw-r--r--config/feature_flags/development/usage_data_incident_management_alert_todo.yml3
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_assigned.yml3
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_change_confidential.yml3
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_closed.yml3
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_comment.yml3
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_created.yml3
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_relate.yml3
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_reopened.yml3
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_todo.yml3
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_unrelate.yml3
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_zoom_meeting.yml3
-rw-r--r--config/feature_flags/development/use_workhorse_s3_client.yml5
-rw-r--r--config/feature_flags/development/user_group_counts.yml8
-rw-r--r--config/feature_flags/development/user_mode_in_session.yml3
-rw-r--r--config/feature_flags/development/user_time_settings.yml3
-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.yml3
-rw-r--r--config/feature_flags/development/vue_group_members_list.yml5
-rw-r--r--config/feature_flags/development/vue_issuable_sidebar.yml5
-rw-r--r--config/feature_flags/development/vue_issuables_list.yml3
-rw-r--r--config/feature_flags/development/vue_issue_header.yml8
-rw-r--r--config/feature_flags/development/web_ide_primary_edit.yml3
-rw-r--r--config/feature_flags/development/webauthn.yml5
-rw-r--r--config/feature_flags/development/webperf_experiment.yml7
-rw-r--r--config/feature_flags/development/whats_new_drawer.yml3
-rw-r--r--config/feature_flags/development/widget_visibility_polling.yml5
-rw-r--r--config/feature_flags/development/wiki.yml3
-rw-r--r--config/feature_flags/development/wiki_front_matter.yml3
-rw-r--r--config/feature_flags/development/workhorse_archive_cache_disabled.yml3
-rw-r--r--config/feature_flags/development/zip_pages_deployments.yml5
-rw-r--r--config/feature_flags/licensed/incident_sla.yml7
-rw-r--r--config/feature_flags/licensed/minimal_access_role.yml7
-rw-r--r--config/feature_flags/licensed/resource_access_token.yml7
-rw-r--r--config/feature_flags/ops/api_kaminari_count_with_limit.yml5
-rw-r--r--config/feature_flags/ops/ci_accept_trace.yml5
-rw-r--r--config/feature_flags/ops/ci_trace_log_invalid_chunks.yml3
-rw-r--r--config/feature_flags/ops/ci_trace_overwrite.yml5
-rw-r--r--config/feature_flags/ops/database_reindexing.yml7
-rw-r--r--config/feature_flags/ops/dynamic_image_resizing.yml8
-rw-r--r--config/feature_flags/ops/gitlab_sidekiq_enable_semi_reliable_fetcher.yml5
-rw-r--r--config/feature_flags/ops/gitlab_sidekiq_reliable_fetcher.yml3
-rw-r--r--config/feature_flags/ops/kubernetes_agent_internal_api.yml5
-rw-r--r--config/feature_flags/ops/marginalia.yml3
-rw-r--r--config/gitlab.yml.example6
-rw-r--r--config/initializers/0_inject_feature_flags.rb39
-rw-r--r--config/initializers/1_settings.rb39
-rw-r--r--config/initializers/7_prometheus_metrics.rb2
-rw-r--r--config/initializers/console_message.rb12
-rw-r--r--config/initializers/grape_validators.rb1
-rw-r--r--config/initializers/labkit_middleware.rb35
-rw-r--r--config/initializers/rack_attack.rb14
-rw-r--r--config/initializers/rack_attack_logging.rb11
-rw-r--r--config/initializers/sidekiq.rb7
-rw-r--r--config/initializers/tracing.rb3
-rw-r--r--config/initializers_before_autoloader/oj.rb (renamed from config/initializers/oj.rb)0
-rw-r--r--config/locales/devise.en.yml2
-rw-r--r--config/routes.rb20
-rw-r--r--config/routes/group.rb12
-rw-r--r--config/routes/import.rb2
-rw-r--r--config/routes/merge_requests.rb1
-rw-r--r--config/routes/project.rb12
-rw-r--r--config/sidekiq_queues.yml10
-rw-r--r--config/webpack.config.js8
-rw-r--r--danger/commit_messages/Dangerfile21
-rw-r--r--danger/documentation/Dangerfile22
-rw-r--r--danger/product_analytics/Dangerfile8
-rw-r--r--data/whats_new/202008210001_13_02.yml4
-rw-r--r--data/whats_new/202009150001_13_03.yml2
-rw-r--r--data/whats_new/202009300001_13_04.yml2
-rw-r--r--data/whats_new/202010230001_13_05.yml61
-rw-r--r--db/fixtures/development/02_application_settings.rb3
-rw-r--r--db/fixtures/development/12_snippets.rb26
-rw-r--r--db/fixtures/production/010_settings.rb4
-rw-r--r--db/migrate/20200908212414_add_feature_flag_events_to_web_hooks.rb9
-rw-r--r--db/migrate/20200920130356_add_container_expiration_policy_worker_settings_to_application_settings.rb19
-rw-r--r--db/migrate/20200928123510_add_expiration_policy_cleanup_status_to_container_repositories.rb26
-rw-r--r--db/migrate/20201008011523_add_ci_jwt_signing_key_to_application_settings.rb13
-rw-r--r--db/migrate/20201008011937_add_text_limit_to_application_settings_encrypted_ci_jwt_signing_key_iv.rb17
-rw-r--r--db/migrate/20201008013434_generate_ci_jwt_signing_key.rb32
-rw-r--r--db/migrate/20201008075620_add_releases_events_to_web_hooks.rb9
-rw-r--r--db/migrate/20201008125643_create_csv_issue_imports.rb18
-rw-r--r--db/migrate/20201008144854_set_regex_defaults_on_container_expiration_policies.rb21
-rw-r--r--db/migrate/20201008224441_add_position_into_security_findings.rb19
-rw-r--r--db/migrate/20201012073022_remove_not_null_constraint_on_framework.rb33
-rw-r--r--db/migrate/20201012122428_add_container_registry_expiration_policies_worker_capacity_constraint.rb22
-rw-r--r--db/migrate/20201012134230_create_ci_test_cases.rb27
-rw-r--r--db/migrate/20201012135330_create_ci_test_case_failures.rb22
-rw-r--r--db/migrate/20201012140110_add_projects_fk_to_ci_test_cases.rb19
-rw-r--r--db/migrate/20201012140452_add_ci_builds_fk_to_ci_test_case_failures.rb19
-rw-r--r--db/migrate/20201014163633_specify_primary_key_where_missing.rb46
-rw-r--r--db/migrate/20201015121805_add_project_foreign_key_to_csv_issue_imports.rb19
-rw-r--r--db/migrate/20201015121825_add_user_foreign_key_to_csv_issue_imports.rb19
-rw-r--r--db/migrate/20201015194852_add_index_on_state_for_dast_site_validations.rb22
-rw-r--r--db/migrate/20201015231049_add_ci_build_id_to_terraform_state_versions.rb28
-rw-r--r--db/migrate/20201016074302_add_index_project_id_and_id_to_container_repositories.rb18
-rw-r--r--db/migrate/20201019091307_add_unique_index_on_scan_id_and_position_of_security_findings.rb18
-rw-r--r--db/migrate/20201019101549_add_es_custom_analyzers_settings.rb12
-rw-r--r--db/migrate/20201019111952_add_sha256_and_filecount_to_pages_deployments.rb22
-rw-r--r--db/migrate/20201019113009_add_new_user_signups_cap_to_application_settings.rb9
-rw-r--r--db/migrate/20201019130244_remove_license_compliance_temp_index.rb18
-rw-r--r--db/migrate/20201019152046_add_default_branch_to_daily_build_group_report_result.rb11
-rw-r--r--db/migrate/20201019161924_add_partitioned_table_view.rb44
-rw-r--r--db/migrate/20201019172704_add_partitions_view.rb39
-rw-r--r--db/migrate/20201021085007_create_analytics_devops_adoption_segments.rb24
-rw-r--r--db/migrate/20201021101956_add_index_route_on_name_trigram_to_route.rb18
-rw-r--r--db/migrate/20201021102554_create_analytics_devops_adoption_segment_selections.rb17
-rw-r--r--db/migrate/20201021105347_add_foreign_key_project_id_to_segment_selection.rb19
-rw-r--r--db/migrate/20201021105600_add_foreign_key_group_id_to_segment_selection.rb19
-rw-r--r--db/migrate/20201021105959_add_check_constraint_to_segment_selection.rb19
-rw-r--r--db/migrate/20201021142812_add_index_to_ci_daily_build_group_report_results.rb24
-rw-r--r--db/migrate/20201021152210_add_secret_detection_token_revocation_application_settings.rb21
-rw-r--r--db/migrate/20201021190539_add_text_limit_to_secret_detection_token_revocation_application_settings.rb17
-rw-r--r--db/migrate/20201021220101_add_merge_trains_enabled.rb9
-rw-r--r--db/migrate/20201022080802_add_repository_read_only_to_snippets.rb9
-rw-r--r--db/migrate/20201022094845_add_historical_data_recorded_at.rb13
-rw-r--r--db/migrate/20201022094846_update_historical_data_recorded_at.rb31
-rw-r--r--db/migrate/20201022103304_add_availability_to_user_statuses.rb9
-rw-r--r--db/migrate/20201022144501_create_snippet_repository_storage_move.rb32
-rw-r--r--db/migrate/20201022191817_add_has_vulnerabilities_into_project_settings.rb19
-rw-r--r--db/migrate/20201022192254_index_project_settings_on_project_id_partially.rb18
-rw-r--r--db/migrate/20201023114628_create_merge_request_cleanup_schedules.rb27
-rw-r--r--db/migrate/20201026200736_seed_merge_trains_enabled.rb19
-rw-r--r--db/migrate/20201027002551_migrate_services_to_http_integrations.rb51
-rw-r--r--db/migrate/20201027135651_add_auto_rollback_setting.rb19
-rw-r--r--db/migrate/20201027210127_add_index_to_oauth_access_grants_resource_owner_id.rb18
-rw-r--r--db/migrate/20201027211138_increase_default_diff_max_patch_bytes.rb9
-rw-r--r--db/migrate/20201028160831_add_temporary_index_to_vulnerabilities_table.rb18
-rw-r--r--db/migrate/20201028184640_add_helm_major_version_to_clusters.rb12
-rw-r--r--db/migrate/20201028204306_migrate_default_diff_max_patch_bytes_to_minimum_200kb.rb20
-rw-r--r--db/migrate/20201029143650_rename_application_settings_to_allow_deny_names.rb21
-rw-r--r--db/migrate/20201029144444_create_vulnerability_finding_links.rb25
-rw-r--r--db/migrate/20201030092151_add_requirements_access_level_to_project_features.rb19
-rw-r--r--db/migrate/20201030200115_add_iid_to_design_management_design.rb9
-rw-r--r--db/migrate/20201030200539_add_index_on_design_management_designs_iid_project_id.rb21
-rw-r--r--db/migrate/20201102184743_add_index_to_incident_issues_on_project_and_created_at.rb30
-rw-r--r--db/migrate/20201103095752_add_issues_closed_at_index.rb17
-rw-r--r--db/migrate/20201103171537_add_index_active_billable_users_to_user.rb21
-rw-r--r--db/migrate/20201103184333_create_packages_package_file_build_infos.rb30
-rw-r--r--db/migrate/20201103202213_update_packages_build_infos_index.rb22
-rw-r--r--db/migrate/20201104204739_create_bulk_import_trackers.rb42
-rw-r--r--db/migrate/20201105021637_add_uploads_size_to_project_statistics.rb13
-rw-r--r--db/migrate/20201105024127_add_uploads_size_to_namespace_root_storage_statistics.rb13
-rw-r--r--db/migrate/20201105135051_change_default_value_of_ci_max_artifact_size_lsif_of_plan_limits_from20_to100.rb21
-rw-r--r--db/migrate/20201105143211_add_vulnerabilities_enabled_and_issuetype_to_jira_tracker_data.rb13
-rw-r--r--db/migrate/20201105143312_add_text_limit_to_jira_tracker_data_issuetype.rb17
-rw-r--r--db/migrate/20201106134139_add_pipelines_created_index.rb19
-rw-r--r--db/migrate/20201107032257_add_default_true_require_admin_approval_after_user_signup_to_application_settings.rb9
-rw-r--r--db/migrate/20201109144634_add_region_field_to_aws_role.rb21
-rw-r--r--db/migrate/20201109180311_add_secret_detection_revocation_token_types_application_settings.rb13
-rw-r--r--db/migrate/20201109184023_add_text_limit_to_secret_detection_revocation_token_types_application_settings.rb17
-rw-r--r--db/migrate/20201110035029_created_index_for_vulnerability_occurrences_on_project_fingerprint.rb18
-rw-r--r--db/migrate/20201110110454_extend_postgres_indexes_view.rb55
-rw-r--r--db/migrate/20201110133629_change_index_mr_metrics_target_project_id.rb20
-rw-r--r--db/migrate/20201111110318_add_cloud_license_auth_token_to_settings.rb13
-rw-r--r--db/migrate/20201111110918_add_cloud_license_auth_token_application_settings_text_limit.rb17
-rw-r--r--db/migrate/20201111152859_add_missing_expression_indexes.rb43
-rw-r--r--db/migrate/20201112195322_reseed_merge_trains_enabled.rb19
-rw-r--r--db/post_migrate/20201015073808_schedule_blocked_by_links_replacement.rb6
-rw-r--r--db/post_migrate/20201019094741_rename_sitemap_root_namespaces.rb24
-rw-r--r--db/post_migrate/20201020102551_remove_index_service_for_usage_data.rb18
-rw-r--r--db/post_migrate/20201026051643_remove_scanned_resources_count_from_security_scans.rb13
-rw-r--r--db/post_migrate/20201026182253_schedule_populate_vulnerability_feedback_pipeline_id.rb33
-rw-r--r--db/post_migrate/20201028160832_schedule_populate_missing_dismissal_information_for_vulnerabilities.rb23
-rw-r--r--db/post_migrate/20201028182809_backfill_jira_tracker_deployment_type2.rb32
-rw-r--r--db/post_migrate/20201029052241_migrate_geo_blob_verification_primary_worker_sidekiq_queue.rb18
-rw-r--r--db/post_migrate/20201029144157_cleanup_application_settings_to_allow_deny_rename.rb19
-rw-r--r--db/post_migrate/20201030203854_backfill_design_iids.rb27
-rw-r--r--db/post_migrate/20201102073808_schedule_blocked_by_links_replacement_second_try.rb30
-rw-r--r--db/post_migrate/20201102112206_rename_sitemap_namespace.rb24
-rw-r--r--db/post_migrate/20201102114018_remove_storage_size_limit_from_application_settings.rb13
-rw-r--r--db/post_migrate/20201102152554_add_not_null_check_on_iid_on_design_manangement_designs.rb17
-rw-r--r--db/post_migrate/20201102152945_truncate_security_findings_table.rb19
-rw-r--r--db/post_migrate/20201103013242_remove_terraform_state_verification_columns.rb29
-rw-r--r--db/post_migrate/20201103110018_schedule_merge_request_cleanup_schedules_backfill.rb30
-rw-r--r--db/post_migrate/20201103192526_schedule_populate_has_vulnerabilities.rb24
-rw-r--r--db/post_migrate/20201106082723_add_merge_request_jira_reference_indexes.rb44
-rw-r--r--db/post_migrate/20201106134950_deduplicate_epic_iids.rb121
-rw-r--r--db/schema_migrations/202009082124141
-rw-r--r--db/schema_migrations/202009201303561
-rw-r--r--db/schema_migrations/202009281235101
-rw-r--r--db/schema_migrations/202010080115231
-rw-r--r--db/schema_migrations/202010080119371
-rw-r--r--db/schema_migrations/202010080134341
-rw-r--r--db/schema_migrations/202010080756201
-rw-r--r--db/schema_migrations/202010081256431
-rw-r--r--db/schema_migrations/202010081448541
-rw-r--r--db/schema_migrations/202010082244411
-rw-r--r--db/schema_migrations/202010120730221
-rw-r--r--db/schema_migrations/202010121224281
-rw-r--r--db/schema_migrations/202010121342301
-rw-r--r--db/schema_migrations/202010121353301
-rw-r--r--db/schema_migrations/202010121401101
-rw-r--r--db/schema_migrations/202010121404521
-rw-r--r--db/schema_migrations/202010141636331
-rw-r--r--db/schema_migrations/202010151218051
-rw-r--r--db/schema_migrations/202010151218251
-rw-r--r--db/schema_migrations/202010151948521
-rw-r--r--db/schema_migrations/202010152310491
-rw-r--r--db/schema_migrations/202010160743021
-rw-r--r--db/schema_migrations/202010190913071
-rw-r--r--db/schema_migrations/202010190947411
-rw-r--r--db/schema_migrations/202010191015491
-rw-r--r--db/schema_migrations/202010191119521
-rw-r--r--db/schema_migrations/202010191130091
-rw-r--r--db/schema_migrations/202010191302441
-rw-r--r--db/schema_migrations/202010191520461
-rw-r--r--db/schema_migrations/202010191619241
-rw-r--r--db/schema_migrations/202010191727041
-rw-r--r--db/schema_migrations/202010201025511
-rw-r--r--db/schema_migrations/202010210850071
-rw-r--r--db/schema_migrations/202010211019561
-rw-r--r--db/schema_migrations/202010211025541
-rw-r--r--db/schema_migrations/202010211053471
-rw-r--r--db/schema_migrations/202010211056001
-rw-r--r--db/schema_migrations/202010211059591
-rw-r--r--db/schema_migrations/202010211428121
-rw-r--r--db/schema_migrations/202010211522101
-rw-r--r--db/schema_migrations/202010211905391
-rw-r--r--db/schema_migrations/202010212201011
-rw-r--r--db/schema_migrations/202010220808021
-rw-r--r--db/schema_migrations/202010220948451
-rw-r--r--db/schema_migrations/202010220948461
-rw-r--r--db/schema_migrations/202010221033041
-rw-r--r--db/schema_migrations/202010221445011
-rw-r--r--db/schema_migrations/202010221918171
-rw-r--r--db/schema_migrations/202010221922541
-rw-r--r--db/schema_migrations/202010231146281
-rw-r--r--db/schema_migrations/202010260516431
-rw-r--r--db/schema_migrations/202010261822531
-rw-r--r--db/schema_migrations/202010262007361
-rw-r--r--db/schema_migrations/202010270025511
-rw-r--r--db/schema_migrations/202010271356511
-rw-r--r--db/schema_migrations/202010272101271
-rw-r--r--db/schema_migrations/202010272111381
-rw-r--r--db/schema_migrations/202010281608311
-rw-r--r--db/schema_migrations/202010281608321
-rw-r--r--db/schema_migrations/202010281828091
-rw-r--r--db/schema_migrations/202010281846401
-rw-r--r--db/schema_migrations/202010282043061
-rw-r--r--db/schema_migrations/202010290522411
-rw-r--r--db/schema_migrations/202010291436501
-rw-r--r--db/schema_migrations/202010291441571
-rw-r--r--db/schema_migrations/202010291444441
-rw-r--r--db/schema_migrations/202010300921511
-rw-r--r--db/schema_migrations/202010302001151
-rw-r--r--db/schema_migrations/202010302005391
-rw-r--r--db/schema_migrations/202010302038541
-rw-r--r--db/schema_migrations/202011020738081
-rw-r--r--db/schema_migrations/202011021122061
-rw-r--r--db/schema_migrations/202011021140181
-rw-r--r--db/schema_migrations/202011021525541
-rw-r--r--db/schema_migrations/202011021529451
-rw-r--r--db/schema_migrations/202011021847431
-rw-r--r--db/schema_migrations/202011030132421
-rw-r--r--db/schema_migrations/202011030957521
-rw-r--r--db/schema_migrations/202011031100181
-rw-r--r--db/schema_migrations/202011031715371
-rw-r--r--db/schema_migrations/202011031843331
-rw-r--r--db/schema_migrations/202011031925261
-rw-r--r--db/schema_migrations/202011032022131
-rw-r--r--db/schema_migrations/202011042047391
-rw-r--r--db/schema_migrations/202011050216371
-rw-r--r--db/schema_migrations/202011050241271
-rw-r--r--db/schema_migrations/202011051350511
-rw-r--r--db/schema_migrations/202011051432111
-rw-r--r--db/schema_migrations/202011051433121
-rw-r--r--db/schema_migrations/202011060827231
-rw-r--r--db/schema_migrations/202011061341391
-rw-r--r--db/schema_migrations/202011061349501
-rw-r--r--db/schema_migrations/202011070322571
-rw-r--r--db/schema_migrations/202011091446341
-rw-r--r--db/schema_migrations/202011091803111
-rw-r--r--db/schema_migrations/202011091840231
-rw-r--r--db/schema_migrations/202011100350291
-rw-r--r--db/schema_migrations/202011101104541
-rw-r--r--db/schema_migrations/202011101336291
-rw-r--r--db/schema_migrations/202011111103181
-rw-r--r--db/schema_migrations/202011111109181
-rw-r--r--db/schema_migrations/202011111528591
-rw-r--r--db/schema_migrations/202011121953221
-rw-r--r--db/structure.sql600
-rw-r--r--doc/.vale/gitlab/Acronyms.yml16
-rw-r--r--doc/.vale/gitlab/Admin.yml2
-rw-r--r--doc/.vale/gitlab/AlertBoxCaution.yml14
-rw-r--r--doc/.vale/gitlab/AlertBoxDanger.yml14
-rw-r--r--doc/.vale/gitlab/AlertBoxNoteTip.yml15
-rw-r--r--doc/.vale/gitlab/AlertBoxStyle.yml8
-rw-r--r--doc/.vale/gitlab/CurlStringsQuoted.yml6
-rw-r--r--doc/.vale/gitlab/CurrentStatus.yml2
-rw-r--r--doc/.vale/gitlab/FutureTense.yml2
-rw-r--r--doc/.vale/gitlab/InternalLinkExtension.yml2
-rw-r--r--doc/.vale/gitlab/InternalLinkFormat.yml13
-rw-r--r--doc/.vale/gitlab/RelativeLinks.yml2
-rw-r--r--doc/.vale/gitlab/Simplicity.yml18
-rw-r--r--doc/.vale/gitlab/SubstitutionSuggestions.yml17
-rw-r--r--doc/.vale/gitlab/SubstitutionWarning.yml1
-rw-r--r--doc/.vale/gitlab/Substitutions.yml8
-rw-r--r--doc/.vale/gitlab/ToDo.yml14
-rw-r--r--doc/.vale/gitlab/VersionText.yml4
-rw-r--r--doc/.vale/gitlab/spelling-exceptions.txt2
-rw-r--r--doc/.vale/vale.tmpl51
-rw-r--r--doc/README.md321
-rw-r--r--doc/administration/audit_events.md21
-rw-r--r--doc/administration/audit_reports.md12
-rw-r--r--doc/administration/auth/crowd.md4
-rw-r--r--doc/administration/auth/ldap/index.md17
-rw-r--r--doc/administration/auth/ldap/ldap-troubleshooting.md31
-rw-r--r--doc/administration/auth/okta.md4
-rw-r--r--doc/administration/auth/smartcard.md4
-rw-r--r--doc/administration/compliance.md4
-rw-r--r--doc/administration/consul.md18
-rw-r--r--doc/administration/database_load_balancing.md4
-rw-r--r--doc/administration/feature_flags.md4
-rw-r--r--doc/administration/geo/disaster_recovery/bring_primary_back.md9
-rw-r--r--doc/administration/geo/disaster_recovery/index.md14
-rw-r--r--doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md6
-rw-r--r--doc/administration/geo/index.md9
-rw-r--r--doc/administration/geo/replication/configuration.md35
-rw-r--r--doc/administration/geo/replication/datatypes.md18
-rw-r--r--doc/administration/geo/replication/disable_geo.md2
-rw-r--r--doc/administration/geo/replication/location_aware_git_url.md4
-rw-r--r--doc/administration/geo/replication/object_storage.md2
-rw-r--r--doc/administration/geo/replication/troubleshooting.md13
-rw-r--r--doc/administration/geo/replication/updating_the_geo_nodes.md6
-rw-r--r--doc/administration/geo/replication/version_specific_updates.md142
-rw-r--r--doc/administration/geo/setup/database.md75
-rw-r--r--doc/administration/gitaly/index.md6
-rw-r--r--doc/administration/incoming_email.md188
-rw-r--r--doc/administration/index.md4
-rw-r--r--doc/administration/instance_limits.md16
-rw-r--r--doc/administration/instance_review.md10
-rw-r--r--doc/administration/job_artifacts.md2
-rw-r--r--doc/administration/job_logs.md47
-rw-r--r--doc/administration/load_balancer.md2
-rw-r--r--doc/administration/logs.md86
-rw-r--r--doc/administration/monitoring/github_imports.md13
-rw-r--r--doc/administration/monitoring/performance/gitlab_configuration.md18
-rw-r--r--doc/administration/monitoring/performance/grafana_configuration.md2
-rw-r--r--doc/administration/monitoring/performance/index.md6
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_exporter.md1
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md4
-rw-r--r--doc/administration/monitoring/prometheus/index.md8
-rw-r--r--doc/administration/monitoring/prometheus/node_exporter.md1
-rw-r--r--doc/administration/monitoring/prometheus/pgbouncer_exporter.md1
-rw-r--r--doc/administration/monitoring/prometheus/postgres_exporter.md1
-rw-r--r--doc/administration/monitoring/prometheus/redis_exporter.md1
-rw-r--r--doc/administration/nfs.md29
-rw-r--r--doc/administration/object_storage.md115
-rw-r--r--doc/administration/operations/cleaning_up_redis_sessions.md2
-rw-r--r--doc/administration/operations/extra_sidekiq_processes.md45
-rw-r--r--doc/administration/operations/fast_ssh_key_lookup.md5
-rw-r--r--doc/administration/operations/index.md5
-rw-r--r--doc/administration/operations/moving_repositories.md117
-rw-r--r--doc/administration/operations/puma.md2
-rw-r--r--doc/administration/operations/rails_console.md6
-rw-r--r--doc/administration/operations/sidekiq_memory_killer.md4
-rw-r--r--doc/administration/packages/container_registry.md48
-rw-r--r--doc/administration/packages/dependency_proxy.md7
-rw-r--r--doc/administration/packages/index.md66
-rw-r--r--doc/administration/pages/index.md49
-rw-r--r--doc/administration/polling.md6
-rw-r--r--doc/administration/postgresql/replication_and_failover.md11
-rw-r--r--doc/administration/pseudonymizer.md7
-rw-r--r--doc/administration/raketasks/check.md6
-rw-r--r--doc/administration/raketasks/doctor.md7
-rw-r--r--doc/administration/raketasks/geo.md6
-rw-r--r--doc/administration/raketasks/github_import.md6
-rw-r--r--doc/administration/raketasks/ldap.md6
-rw-r--r--doc/administration/raketasks/maintenance.md9
-rw-r--r--doc/administration/raketasks/project_import_export.md6
-rw-r--r--doc/administration/raketasks/storage.md11
-rw-r--r--doc/administration/raketasks/uploads/migrate.md12
-rw-r--r--doc/administration/raketasks/uploads/sanitize.md6
-rw-r--r--doc/administration/reference_architectures/10k_users.md21
-rw-r--r--doc/administration/reference_architectures/25k_users.md23
-rw-r--r--doc/administration/reference_architectures/2k_users.md9
-rw-r--r--doc/administration/reference_architectures/3k_users.md9
-rw-r--r--doc/administration/reference_architectures/50k_users.md21
-rw-r--r--doc/administration/reference_architectures/5k_users.md9
-rw-r--r--doc/administration/reply_by_email.md2
-rw-r--r--doc/administration/reply_by_email_postfix_setup.md18
-rw-r--r--doc/administration/repository_storage_types.md2
-rw-r--r--doc/administration/restart_gitlab.md6
-rw-r--r--doc/administration/sidekiq.md5
-rw-r--r--doc/administration/smime_signing_email.md13
-rw-r--r--doc/administration/timezone.md8
-rw-r--r--doc/administration/troubleshooting/debug.md6
-rw-r--r--doc/administration/troubleshooting/diagnostics_tools.md3
-rw-r--r--doc/administration/troubleshooting/elasticsearch.md8
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md79
-rw-r--r--doc/administration/troubleshooting/group_saml_scim.md3
-rw-r--r--doc/administration/troubleshooting/img/ADFS-determine-token-signing-certificate-fingerprint.pngbin49772 -> 36861 bytes
-rw-r--r--doc/administration/troubleshooting/img/OneLogin-encryption.pngbin9980 -> 0 bytes
-rw-r--r--doc/administration/troubleshooting/img/network_monitor_xid.pngbin131339 -> 55588 bytes
-rw-r--r--doc/administration/troubleshooting/index.md6
-rw-r--r--doc/administration/troubleshooting/kubernetes_cheat_sheet.md6
-rw-r--r--doc/administration/troubleshooting/linux_cheat_sheet.md4
-rw-r--r--doc/administration/troubleshooting/log_parsing.md8
-rw-r--r--doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md16
-rw-r--r--doc/administration/troubleshooting/postgresql.md5
-rw-r--r--doc/administration/troubleshooting/sidekiq.md45
-rw-r--r--doc/administration/troubleshooting/ssl.md3
-rw-r--r--doc/administration/troubleshooting/test_environments.md3
-rw-r--r--doc/administration/troubleshooting/tracing_correlation_id.md3
-rw-r--r--doc/administration/uploads.md23
-rw-r--r--doc/administration/user_settings.md6
-rw-r--r--doc/api/README.md410
-rw-r--r--doc/api/admin_sidekiq_queues.md6
-rw-r--r--doc/api/api_resources.md8
-rw-r--r--doc/api/appearance.md6
-rw-r--r--doc/api/applications.md6
-rw-r--r--doc/api/audit_events.md6
-rw-r--r--doc/api/avatar.md6
-rw-r--r--doc/api/boards.md111
-rw-r--r--doc/api/broadcast_messages.md14
-rw-r--r--doc/api/commits.md8
-rw-r--r--doc/api/container_registry.md44
-rw-r--r--doc/api/custom_attributes.md6
-rw-r--r--doc/api/dependencies.md6
-rw-r--r--doc/api/dependency_proxy.md14
-rw-r--r--doc/api/deploy_tokens.md4
-rw-r--r--doc/api/deployments.md6
-rw-r--r--doc/api/epic_issues.md2
-rw-r--r--doc/api/epic_links.md6
-rw-r--r--doc/api/epics.md20
-rw-r--r--doc/api/events.md7
-rw-r--r--doc/api/experiments.md6
-rw-r--r--doc/api/feature_flag_user_lists.md7
-rw-r--r--doc/api/geo_nodes.md6
-rw-r--r--doc/api/graphql/audit_report.md6
-rw-r--r--doc/api/graphql/getting_started.md6
-rw-r--r--doc/api/graphql/index.md10
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql2805
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json7914
-rw-r--r--doc/api/graphql/reference/index.md729
-rw-r--r--doc/api/graphql/removed_items.md17
-rw-r--r--doc/api/graphql/sample_issue_boards.md6
-rw-r--r--doc/api/group_activity_analytics.md6
-rw-r--r--doc/api/group_badges.md6
-rw-r--r--doc/api/group_boards.md39
-rw-r--r--doc/api/group_import_export.md6
-rw-r--r--doc/api/group_iterations.md2
-rw-r--r--doc/api/group_labels.md5
-rw-r--r--doc/api/group_level_variables.md6
-rw-r--r--doc/api/group_milestones.md2
-rw-r--r--doc/api/groups.md21
-rw-r--r--doc/api/import.md22
-rw-r--r--doc/api/instance_clusters.md6
-rw-r--r--doc/api/invitations.md107
-rw-r--r--doc/api/issue_links.md6
-rw-r--r--doc/api/issues.md37
-rw-r--r--doc/api/issues_statistics.md30
-rw-r--r--doc/api/iterations.md2
-rw-r--r--doc/api/job_artifacts.md6
-rw-r--r--doc/api/labels.md8
-rw-r--r--doc/api/license.md6
-rw-r--r--doc/api/lint.md66
-rw-r--r--doc/api/managed_licenses.md6
-rw-r--r--doc/api/members.md6
-rw-r--r--doc/api/merge_requests.md52
-rw-r--r--doc/api/milestones.md2
-rw-r--r--doc/api/namespaces.md6
-rw-r--r--doc/api/notes.md6
-rw-r--r--doc/api/notification_settings.md6
-rw-r--r--doc/api/oauth2.md31
-rw-r--r--doc/api/packages.md135
-rw-r--r--doc/api/personal_access_tokens.md15
-rw-r--r--doc/api/pipelines.md4
-rw-r--r--doc/api/project_repository_storage_moves.md25
-rw-r--r--doc/api/project_snippets.md2
-rw-r--r--doc/api/projects.md1059
-rw-r--r--doc/api/protected_environments.md17
-rw-r--r--doc/api/releases/index.md12
-rw-r--r--doc/api/releases/links.md20
-rw-r--r--doc/api/resource_label_events.md6
-rw-r--r--doc/api/scim.md22
-rw-r--r--doc/api/search.md15
-rw-r--r--doc/api/services.md22
-rw-r--r--doc/api/settings.md31
-rw-r--r--doc/api/sidekiq_metrics.md6
-rw-r--r--doc/api/snippets.md2
-rw-r--r--doc/api/statistics.md6
-rw-r--r--doc/api/system_hooks.md6
-rw-r--r--doc/api/templates/dockerfiles.md3
-rw-r--r--doc/api/templates/gitignores.md3
-rw-r--r--doc/api/templates/licenses.md3
-rw-r--r--doc/api/todos.md6
-rw-r--r--doc/api/users.md74
-rw-r--r--doc/api/v3_to_v4.md6
-rw-r--r--doc/api/version.md6
-rw-r--r--doc/architecture/blueprints/cloud_native_build_logs/index.md3
-rw-r--r--doc/architecture/blueprints/cloud_native_gitlab_pages/index.md3
-rw-r--r--doc/architecture/blueprints/feature_flags_development/index.md3
-rw-r--r--doc/architecture/blueprints/image_resizing/index.md76
-rw-r--r--doc/architecture/index.md3
-rw-r--r--doc/ci/README.md2
-rw-r--r--doc/ci/caching/index.md2
-rw-r--r--doc/ci/ci_cd_for_external_repos/github_integration.md2
-rw-r--r--doc/ci/ci_cd_for_external_repos/img/github_omniauth.pngbin29022 -> 0 bytes
-rw-r--r--doc/ci/ci_cd_for_external_repos/img/github_push_webhook.pngbin45725 -> 0 bytes
-rw-r--r--doc/ci/ci_cd_for_external_repos/index.md2
-rw-r--r--doc/ci/cloud_deployment/index.md39
-rw-r--r--doc/ci/directed_acyclic_graph/index.md16
-rw-r--r--doc/ci/docker/using_docker_build.md150
-rw-r--r--doc/ci/docker/using_docker_images.md26
-rw-r--r--doc/ci/environments/img/protected_access_group_v13_6.pngbin0 -> 17599 bytes
-rw-r--r--doc/ci/environments/index.md48
-rw-r--r--doc/ci/environments/protected_environments.md59
-rw-r--r--doc/ci/examples/README.md3
-rw-r--r--doc/ci/examples/authenticating-with-hashicorp-vault/index.md5
-rw-r--r--doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md26
-rw-r--r--doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md4
-rw-r--r--doc/ci/examples/end_to_end_testing_webdriverio/index.md4
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/index.md2
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md2
-rw-r--r--doc/ci/git_submodules.md2
-rw-r--r--doc/ci/interactive_web_terminal/img/interactive_web_terminal_running_job.pngbin55677 -> 35982 bytes
-rw-r--r--doc/ci/interactive_web_terminal/index.md2
-rw-r--r--doc/ci/introduction/img/gitlab_workflow_example_11_9.pngbin70061 -> 40769 bytes
-rw-r--r--doc/ci/introduction/img/job_running.pngbin237781 -> 99621 bytes
-rw-r--r--doc/ci/introduction/index.md16
-rw-r--r--doc/ci/jobs/img/collapsible_log_v12_6.png (renamed from doc/ci/pipelines/img/collapsible_log_v12_6.png)bin96471 -> 96471 bytes
-rw-r--r--doc/ci/jobs/img/job_failure_reason.png (renamed from doc/ci/pipelines/img/job_failure_reason.png)bin5288 -> 5288 bytes
-rw-r--r--doc/ci/jobs/img/job_group_v12_10.png (renamed from doc/ci/pipelines/img/job_group_v12_10.png)bin5436 -> 5436 bytes
-rw-r--r--doc/ci/jobs/img/manual_job_variables.pngbin0 -> 39858 bytes
-rw-r--r--doc/ci/jobs/img/pipeline_incremental_rollout.png (renamed from doc/ci/pipelines/img/pipeline_incremental_rollout.png)bin4794 -> 4794 bytes
-rw-r--r--doc/ci/jobs/img/pipelines_grouped.png (renamed from doc/ci/pipelines/img/pipelines_grouped.png)bin12888 -> 12888 bytes
-rw-r--r--doc/ci/jobs/img/pipelines_mini_graph_sorting.png (renamed from doc/ci/pipelines/img/pipelines_mini_graph_sorting.png)bin10742 -> 10742 bytes
-rw-r--r--doc/ci/jobs/index.md251
-rw-r--r--doc/ci/large_repositories/index.md33
-rw-r--r--doc/ci/lint.md9
-rw-r--r--doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_MR_v12_09.pngbin29650 -> 0 bytes
-rw-r--r--doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_branch_v12_09.pngbin29680 -> 0 bytes
-rw-r--r--doc/ci/merge_request_pipelines/index.md6
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline_config.pngbin5296 -> 0 bytes
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md2
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_config_v12_0.pngbin9012 -> 0 bytes
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_immediate_merge.pngbin13038 -> 0 bytes
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md37
-rw-r--r--doc/ci/metrics_reports.md2
-rw-r--r--doc/ci/migration/circleci.md4
-rw-r--r--doc/ci/migration/jenkins.md2
-rw-r--r--doc/ci/multi_project_pipelines.md5
-rw-r--r--doc/ci/pipelines/img/manual_job_variables.pngbin111239 -> 0 bytes
-rw-r--r--doc/ci/pipelines/index.md244
-rw-r--r--doc/ci/pipelines/job_artifacts.md12
-rw-r--r--doc/ci/pipelines/pipeline_efficiency.md2
-rw-r--r--doc/ci/pipelines/schedules.md14
-rw-r--r--doc/ci/pipelines/settings.md19
-rw-r--r--doc/ci/quick_start/README.md271
-rw-r--r--doc/ci/quick_start/img/build_log.pngbin138388 -> 0 bytes
-rw-r--r--doc/ci/quick_start/img/builds_status.pngbin47887 -> 0 bytes
-rw-r--r--doc/ci/quick_start/img/job_details_v13_6.pngbin0 -> 127827 bytes
-rw-r--r--doc/ci/quick_start/img/new_commit.pngbin5541 -> 0 bytes
-rw-r--r--doc/ci/quick_start/img/new_file_v13_6.pngbin0 -> 9653 bytes
-rw-r--r--doc/ci/quick_start/img/pipeline_graph_v13_6.pngbin0 -> 27157 bytes
-rw-r--r--doc/ci/quick_start/img/pipelines_status.pngbin64605 -> 0 bytes
-rw-r--r--doc/ci/quick_start/img/single_commit_status_pending.pngbin13631 -> 0 bytes
-rw-r--r--doc/ci/quick_start/img/three_stages_v13_6.pngbin0 -> 23531 bytes
-rw-r--r--doc/ci/review_apps/img/view_on_env_mr.pngbin295181 -> 102967 bytes
-rw-r--r--doc/ci/review_apps/index.md4
-rw-r--r--doc/ci/runners/README.md344
-rw-r--r--doc/ci/runners/img/shared_runners_admin.pngbin29192 -> 0 bytes
-rw-r--r--doc/ci/ssh_keys/README.md2
-rw-r--r--doc/ci/triggers/README.md4
-rw-r--r--doc/ci/troubleshooting.md2
-rw-r--r--doc/ci/unit_test_reports.md38
-rw-r--r--doc/ci/variables/README.md6
-rw-r--r--doc/ci/variables/predefined_variables.md12
-rw-r--r--doc/ci/variables/where_variables_can_be_used.md2
-rw-r--r--doc/ci/yaml/README.md1055
-rw-r--r--doc/ci/yaml/script.md147
-rw-r--r--doc/ci/yaml/visualization.md6
-rw-r--r--doc/development/README.md38
-rw-r--r--doc/development/adding_service_component.md10
-rw-r--r--doc/development/api_graphql_styleguide.md268
-rw-r--r--doc/development/api_styleguide.md21
-rw-r--r--doc/development/application_limits.md12
-rw-r--r--doc/development/application_secrets.md6
-rw-r--r--doc/development/approval_rules.md10
-rw-r--r--doc/development/architecture.md35
-rw-r--r--doc/development/background_migrations.md24
-rw-r--r--doc/development/cached_queries.md139
-rw-r--r--doc/development/changelog.md15
-rw-r--r--doc/development/chaos_endpoints.md19
-rw-r--r--doc/development/cicd/templates.md4
-rw-r--r--doc/development/code_comments.md6
-rw-r--r--doc/development/code_intelligence/index.md6
-rw-r--r--doc/development/code_review.md19
-rw-r--r--doc/development/contributing/index.md4
-rw-r--r--doc/development/contributing/issue_workflow.md26
-rw-r--r--doc/development/contributing/merge_request_workflow.md29
-rw-r--r--doc/development/contributing/style_guides.md48
-rw-r--r--doc/development/creating_enums.md6
-rw-r--r--doc/development/dangerbot.md6
-rw-r--r--doc/development/database/constraint_naming_convention.md26
-rw-r--r--doc/development/database/index.md7
-rw-r--r--doc/development/database/maintenance_operations.md46
-rw-r--r--doc/development/database/setting_multiple_values.md22
-rw-r--r--doc/development/database_review.md11
-rw-r--r--doc/development/deleting_migrations.md6
-rw-r--r--doc/development/deprecation_guidelines/index.md6
-rw-r--r--doc/development/diffs.md57
-rw-r--r--doc/development/distributed_tracing.md3
-rw-r--r--doc/development/documentation/feature_flags.md3
-rw-r--r--doc/development/documentation/graphql_styleguide.md2
-rw-r--r--doc/development/documentation/index.md272
-rw-r--r--doc/development/documentation/restful_api_styleguide.md29
-rw-r--r--doc/development/documentation/site_architecture/deployment_process.md6
-rw-r--r--doc/development/documentation/site_architecture/global_nav.md5
-rw-r--r--doc/development/documentation/site_architecture/index.md8
-rw-r--r--doc/development/documentation/site_architecture/release_process.md9
-rw-r--r--doc/development/documentation/structure.md9
-rw-r--r--doc/development/documentation/styleguide.md2062
-rw-r--r--doc/development/documentation/styleguide/index.md1999
-rw-r--r--doc/development/documentation/testing.md292
-rw-r--r--doc/development/documentation/workflow.md20
-rw-r--r--doc/development/ee_features.md42
-rw-r--r--doc/development/elasticsearch.md34
-rw-r--r--doc/development/emails.md6
-rw-r--r--doc/development/experiment_guide/index.md171
-rw-r--r--doc/development/fe_guide/accessibility.md6
-rw-r--r--doc/development/fe_guide/architecture.md6
-rw-r--r--doc/development/fe_guide/axios.md6
-rw-r--r--doc/development/fe_guide/dependencies.md6
-rw-r--r--doc/development/fe_guide/design_patterns.md6
-rw-r--r--doc/development/fe_guide/development_process.md6
-rw-r--r--doc/development/fe_guide/dropdowns.md2
-rw-r--r--doc/development/fe_guide/droplab/droplab.md94
-rw-r--r--doc/development/fe_guide/droplab/plugins/ajax.md28
-rw-r--r--doc/development/fe_guide/droplab/plugins/filter.md29
-rw-r--r--doc/development/fe_guide/droplab/plugins/index.md14
-rw-r--r--doc/development/fe_guide/droplab/plugins/input_setter.md38
-rw-r--r--doc/development/fe_guide/editor_lite.md224
-rw-r--r--doc/development/fe_guide/emojis.md6
-rw-r--r--doc/development/fe_guide/frontend_faq.md15
-rw-r--r--doc/development/fe_guide/graphql.md157
-rw-r--r--doc/development/fe_guide/icons.md8
-rw-r--r--doc/development/fe_guide/img/editor_lite_create_ext.pngbin0 -> 81777 bytes
-rw-r--r--doc/development/fe_guide/img/editor_lite_loading.pngbin0 -> 16411 bytes
-rw-r--r--doc/development/fe_guide/img/gl-modal.pngbin8767 -> 0 bytes
-rw-r--r--doc/development/fe_guide/index.md6
-rw-r--r--doc/development/fe_guide/keyboard_shortcuts.md6
-rw-r--r--doc/development/fe_guide/performance.md63
-rw-r--r--doc/development/fe_guide/principles.md6
-rw-r--r--doc/development/fe_guide/security.md28
-rw-r--r--doc/development/fe_guide/style/html.md6
-rw-r--r--doc/development/fe_guide/style/index.md6
-rw-r--r--doc/development/fe_guide/style/javascript.md5
-rw-r--r--doc/development/fe_guide/style/scss.md8
-rw-r--r--doc/development/fe_guide/style/vue.md261
-rw-r--r--doc/development/fe_guide/tooling.md19
-rw-r--r--doc/development/fe_guide/vue.md74
-rw-r--r--doc/development/fe_guide/vue3_migration.md7
-rw-r--r--doc/development/fe_guide/vuex.md18
-rw-r--r--doc/development/feature_categorization/index.md47
-rw-r--r--doc/development/feature_flags/controls.md5
-rw-r--r--doc/development/feature_flags/development.md113
-rw-r--r--doc/development/feature_flags/index.md1
-rw-r--r--doc/development/feature_flags/process.md2
-rw-r--r--doc/development/features_inside_dot_gitlab.md6
-rw-r--r--doc/development/file_storage.md16
-rw-r--r--doc/development/foreign_keys.md6
-rw-r--r--doc/development/gemfile.md6
-rw-r--r--doc/development/geo/framework.md109
-rw-r--r--doc/development/git_object_deduplication.md10
-rw-r--r--doc/development/github_importer.md6
-rw-r--r--doc/development/go_guide/dependencies.md6
-rw-r--r--doc/development/go_guide/index.md6
-rw-r--r--doc/development/gotchas.md14
-rw-r--r--doc/development/graphql_guide/batchloader.md121
-rw-r--r--doc/development/graphql_guide/index.md6
-rw-r--r--doc/development/graphql_guide/pagination.md173
-rw-r--r--doc/development/hash_indexes.md6
-rw-r--r--doc/development/i18n/externalization.md30
-rw-r--r--doc/development/i18n/index.md6
-rw-r--r--doc/development/i18n/merging_translations.md6
-rw-r--r--doc/development/i18n/proofreader.md16
-rw-r--r--doc/development/i18n/translation.md8
-rw-r--r--doc/development/image_scaling.md96
-rw-r--r--doc/development/img/architecture_simplified.pngbin106339 -> 38060 bytes
-rw-r--r--doc/development/img/bullet_v13_0.pngbin407482 -> 99668 bytes
-rw-r--r--doc/development/img/distributed_tracing_jaeger_ui.pngbin546331 -> 56194 bytes
-rw-r--r--doc/development/img/memory_ruby_heap_fragmentation.pngbin60230 -> 24210 bytes
-rw-r--r--doc/development/img/merge_ref_head_options_v13_6.pngbin0 -> 21605 bytes
-rw-r--r--doc/development/img/performance_bar_cached_queries.pngbin0 -> 27039 bytes
-rw-r--r--doc/development/img/performance_bar_fixed_cached_queries.pngbin0 -> 8557 bytes
-rw-r--r--doc/development/img/performance_bar_members_page.pngbin0 -> 8437 bytes
-rw-r--r--doc/development/img/telemetry_system_overview.pngbin103618 -> 0 bytes
-rw-r--r--doc/development/import_export.md74
-rw-r--r--doc/development/import_project.md7
-rw-r--r--doc/development/insert_into_tables_in_batches.md3
-rw-r--r--doc/development/integrations/jenkins.md6
-rw-r--r--doc/development/integrations/jira_connect.md38
-rw-r--r--doc/development/integrations/secure.md28
-rw-r--r--doc/development/integrations/secure_partner_integration.md8
-rw-r--r--doc/development/interacting_components.md6
-rw-r--r--doc/development/internal_users.md44
-rw-r--r--doc/development/iterating_tables_in_batches.md6
-rw-r--r--doc/development/lfs.md6
-rw-r--r--doc/development/licensed_feature_availability.md6
-rw-r--r--doc/development/licensing.md9
-rw-r--r--doc/development/mass_insert.md6
-rw-r--r--doc/development/merge_request_performance_guidelines.md75
-rw-r--r--doc/development/migration_style_guide.md18
-rw-r--r--doc/development/module_with_instance_variables.md6
-rw-r--r--doc/development/multi_version_compatibility.md6
-rw-r--r--doc/development/namespaces_storage_statistics.md20
-rw-r--r--doc/development/new_fe_guide/dependencies.md6
-rw-r--r--doc/development/new_fe_guide/development/accessibility.md8
-rw-r--r--doc/development/new_fe_guide/development/components.md6
-rw-r--r--doc/development/new_fe_guide/development/index.md6
-rw-r--r--doc/development/new_fe_guide/development/performance.md6
-rw-r--r--doc/development/new_fe_guide/index.md6
-rw-r--r--doc/development/new_fe_guide/modules/dirty_submit.md6
-rw-r--r--doc/development/new_fe_guide/modules/index.md10
-rw-r--r--doc/development/new_fe_guide/modules/widget_extensions.md56
-rw-r--r--doc/development/new_fe_guide/tips.md6
-rw-r--r--doc/development/newlines_styleguide.md6
-rw-r--r--doc/development/omnibus.md6
-rw-r--r--doc/development/ordering_table_columns.md7
-rw-r--r--doc/development/packages.md7
-rw-r--r--doc/development/performance.md48
-rw-r--r--doc/development/permissions.md6
-rw-r--r--doc/development/pipelines.md8
-rw-r--r--doc/development/policies.md6
-rw-r--r--doc/development/polling.md6
-rw-r--r--doc/development/polymorphic_associations.md6
-rw-r--r--doc/development/post_deployment_migrations.md6
-rw-r--r--doc/development/product_analytics/event_dictionary.md31
-rw-r--r--doc/development/product_analytics/index.md181
-rw-r--r--doc/development/product_analytics/snowplow.md8
-rw-r--r--doc/development/product_analytics/usage_ping.md144
-rw-r--r--doc/development/profiling.md7
-rw-r--r--doc/development/projections.md6
-rw-r--r--doc/development/prometheus.md58
-rw-r--r--doc/development/pry_debugging.md6
-rw-r--r--doc/development/python_guide/index.md6
-rw-r--r--doc/development/query_count_limits.md6
-rw-r--r--doc/development/query_recorder.md19
-rw-r--r--doc/development/rails_initializers.md6
-rw-r--r--doc/development/rake_tasks.md8
-rw-r--r--doc/development/reactive_caching.md6
-rw-r--r--doc/development/redis.md6
-rw-r--r--doc/development/refactoring_guide/index.md6
-rw-r--r--doc/development/reference_processing.md7
-rw-r--r--doc/development/renaming_features.md6
-rw-r--r--doc/development/repository_mirroring.md6
-rw-r--r--doc/development/reusing_abstractions.md6
-rw-r--r--doc/development/rolling_out_changes_using_feature_flags.md4
-rw-r--r--doc/development/routing.md6
-rw-r--r--doc/development/scalability.md6
-rw-r--r--doc/development/secure_coding_guidelines.md138
-rw-r--r--doc/development/serializing_data.md6
-rw-r--r--doc/development/service_measurement.md12
-rw-r--r--doc/development/session.md6
-rw-r--r--doc/development/sha1_as_binary.md6
-rw-r--r--doc/development/shared_files.md6
-rw-r--r--doc/development/shell_commands.md6
-rw-r--r--doc/development/shell_scripting_guide/index.md6
-rw-r--r--doc/development/sidekiq_debugging.md9
-rw-r--r--doc/development/sidekiq_style_guide.md86
-rw-r--r--doc/development/single_table_inheritance.md6
-rw-r--r--doc/development/sql.md6
-rw-r--r--doc/development/testing_guide/best_practices.md8
-rw-r--r--doc/development/testing_guide/ci.md6
-rw-r--r--doc/development/testing_guide/end_to_end/beginners_guide.md9
-rw-r--r--doc/development/testing_guide/end_to_end/best_practices.md76
-rw-r--r--doc/development/testing_guide/end_to_end/dynamic_element_validation.md6
-rw-r--r--doc/development/testing_guide/end_to_end/environment_selection.md11
-rw-r--r--doc/development/testing_guide/end_to_end/feature_flags.md6
-rw-r--r--doc/development/testing_guide/end_to_end/flows.md6
-rw-r--r--doc/development/testing_guide/end_to_end/index.md6
-rw-r--r--doc/development/testing_guide/end_to_end/page_objects.md6
-rw-r--r--doc/development/testing_guide/end_to_end/resources.md6
-rw-r--r--doc/development/testing_guide/end_to_end/rspec_metadata_tests.md25
-rw-r--r--doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md12
-rw-r--r--doc/development/testing_guide/end_to_end/style_guide.md6
-rw-r--r--doc/development/testing_guide/flaky_tests.md14
-rw-r--r--doc/development/testing_guide/frontend_testing.md119
-rw-r--r--doc/development/testing_guide/index.md6
-rw-r--r--doc/development/testing_guide/review_apps.md6
-rw-r--r--doc/development/testing_guide/smoke.md6
-rw-r--r--doc/development/testing_guide/testing_levels.md6
-rw-r--r--doc/development/testing_guide/testing_migrations_guide.md4
-rw-r--r--doc/development/testing_guide/testing_rake_tasks.md6
-rw-r--r--doc/development/understanding_explain_plans.md17
-rw-r--r--doc/development/uploads.md13
-rw-r--r--doc/development/utilities.md6
-rw-r--r--doc/development/value_stream_analytics.md10
-rw-r--r--doc/development/verifying_database_capabilities.md6
-rw-r--r--doc/development/what_requires_downtime.md22
-rw-r--r--doc/development/wikis.md6
-rw-r--r--doc/development/windows.md3
-rw-r--r--doc/downgrade_ee_to_ce/README.md6
-rw-r--r--doc/gitlab-basics/command-line-commands.md16
-rw-r--r--doc/gitlab-basics/create-project.md4
-rw-r--r--doc/gitlab-basics/img/fork_choose_namespace.pngbin13674 -> 0 bytes
-rw-r--r--doc/gitlab-basics/img/fork_new.pngbin10572 -> 0 bytes
-rw-r--r--doc/gitlab-basics/img/merge_request_page.pngbin33801 -> 0 bytes
-rw-r--r--doc/gitlab-basics/img/merge_request_select_branch.pngbin16654 -> 0 bytes
-rw-r--r--doc/gitlab-basics/img/project_clone_url.pngbin14978 -> 0 bytes
-rw-r--r--doc/install/aws/index.md6
-rw-r--r--doc/install/azure/index.md16
-rw-r--r--doc/install/digitaloceandocker.md3
-rw-r--r--doc/install/installation.md92
-rw-r--r--doc/install/kubernetes/gitlab_chart.md5
-rw-r--r--doc/install/kubernetes/gitlab_omnibus.md5
-rw-r--r--doc/install/kubernetes/gitlab_runner_chart.md5
-rw-r--r--doc/install/kubernetes/index.md5
-rw-r--r--doc/install/kubernetes/preparation/connect.md5
-rw-r--r--doc/install/kubernetes/preparation/eks.md5
-rw-r--r--doc/install/kubernetes/preparation/networking.md5
-rw-r--r--doc/install/kubernetes/preparation/rbac.md5
-rw-r--r--doc/install/kubernetes/preparation/tiller.md5
-rw-r--r--doc/install/kubernetes/preparation/tools_installation.md5
-rw-r--r--doc/install/openshift_and_gitlab/index.md26
-rw-r--r--doc/install/pivotal/index.md6
-rw-r--r--doc/install/postgresql_extensions.md6
-rw-r--r--doc/install/requirements.md5
-rw-r--r--doc/integration/README.md3
-rw-r--r--doc/integration/akismet.md37
-rw-r--r--doc/integration/auth0.md43
-rw-r--r--doc/integration/azure.md45
-rw-r--r--doc/integration/bitbucket.md72
-rw-r--r--doc/integration/cas.md6
-rw-r--r--doc/integration/elasticsearch.md29
-rw-r--r--doc/integration/external-issue-tracker.md6
-rw-r--r--doc/integration/facebook.md6
-rw-r--r--doc/integration/github.md20
-rw-r--r--doc/integration/gitlab.md6
-rw-r--r--doc/integration/gmail_action_buttons_for_gitlab.md6
-rw-r--r--doc/integration/google.md6
-rw-r--r--doc/integration/img/jira_dev_panel_jira_setup_1.pngbin29546 -> 0 bytes
-rw-r--r--doc/integration/img/spam_log.pngbin50996 -> 24643 bytes
-rw-r--r--doc/integration/img/submit_issue.pngbin45771 -> 17697 bytes
-rw-r--r--doc/integration/jenkins.md6
-rw-r--r--doc/integration/jenkins_deprecated.md6
-rw-r--r--doc/integration/jira_development_panel.md63
-rw-r--r--doc/integration/kerberos.md98
-rw-r--r--doc/integration/oauth2_generic.md6
-rw-r--r--doc/integration/oauth_provider.md6
-rw-r--r--doc/integration/omniauth.md57
-rw-r--r--doc/integration/openid_connect_provider.md6
-rw-r--r--doc/integration/recaptcha.md6
-rw-r--r--doc/integration/salesforce.md6
-rw-r--r--doc/integration/saml.md45
-rw-r--r--doc/integration/shibboleth.md6
-rw-r--r--doc/integration/slash_commands.md6
-rw-r--r--doc/integration/trello_power_up.md6
-rw-r--r--doc/integration/twitter.md6
-rw-r--r--doc/integration/vault.md12
-rw-r--r--doc/legal/README.md3
-rw-r--r--doc/legal/corporate_contributor_license_agreement.md6
-rw-r--r--doc/legal/individual_contributor_license_agreement.md6
-rw-r--r--doc/migrate_ci_to_ce/README.md3
-rw-r--r--doc/operations/error_tracking.md2
-rw-r--r--doc/operations/feature_flags.md35
-rw-r--r--doc/operations/incident_management/alert_integrations.md71
-rw-r--r--doc/operations/incident_management/alerts.md58
-rw-r--r--doc/operations/incident_management/generic_alerts.md4
-rw-r--r--doc/operations/incident_management/img/alert_detail_full_v13_1.pngbin26957 -> 0 bytes
-rw-r--r--doc/operations/incident_management/img/alert_detail_overview_v13_1.pngbin14827 -> 0 bytes
-rw-r--r--doc/operations/incident_management/img/alert_detail_system_notes_v13_1.pngbin22329 -> 0 bytes
-rw-r--r--doc/operations/incident_management/img/alert_list_search_v13_1.pngbin12166 -> 0 bytes
-rw-r--r--doc/operations/incident_management/img/alert_list_sort_v13_1.pngbin13919 -> 0 bytes
-rw-r--r--doc/operations/incident_management/img/incident_highlight_bar_v13_5.pngbin36177 -> 0 bytes
-rw-r--r--doc/operations/incident_management/img/incident_list.pngbin34194 -> 0 bytes
-rw-r--r--doc/operations/incident_management/img/incident_list_search_v13_3.pngbin29780 -> 0 bytes
-rw-r--r--doc/operations/incident_management/img/incident_sla_settings_v13_5.pngbin21480 -> 0 bytes
-rw-r--r--doc/operations/incident_management/incidents.md64
-rw-r--r--doc/operations/incident_management/status_page.md6
-rw-r--r--doc/operations/metrics/dashboards/img/metrics_settings_button_v13_3.pngbin3903 -> 0 bytes
-rw-r--r--doc/operations/metrics/dashboards/index.md16
-rw-r--r--doc/operations/metrics/dashboards/settings.md8
-rw-r--r--doc/operations/metrics/dashboards/variables.md2
-rw-r--r--doc/operations/metrics/dashboards/yaml.md4
-rw-r--r--doc/operations/metrics/index.md2
-rw-r--r--doc/policy/maintenance.md95
-rw-r--r--doc/public_access/public_access.md7
-rw-r--r--doc/raketasks/README.md3
-rw-r--r--doc/raketasks/backup_restore.md8
-rw-r--r--doc/raketasks/cleanup.md12
-rw-r--r--doc/raketasks/features.md6
-rw-r--r--doc/raketasks/generate_sample_prometheus_data.md6
-rw-r--r--doc/raketasks/import.md6
-rw-r--r--doc/raketasks/list_repos.md7
-rw-r--r--doc/raketasks/migrate_snippets.md6
-rw-r--r--doc/raketasks/spdx.md6
-rw-r--r--doc/raketasks/user_management.md8
-rw-r--r--doc/raketasks/web_hooks.md6
-rw-r--r--doc/raketasks/x509_signatures.md6
-rw-r--r--doc/security/README.md3
-rw-r--r--doc/security/asset_proxy.md6
-rw-r--r--doc/security/crime_vulnerability.md3
-rw-r--r--doc/security/information_exclusivity.md3
-rw-r--r--doc/security/password_length_limits.md47
-rw-r--r--doc/security/password_storage.md3
-rw-r--r--doc/security/passwords_for_integrated_authentication_methods.md3
-rw-r--r--doc/security/project_import_decompressed_archive_size_limits.md3
-rw-r--r--doc/security/rack_attack.md3
-rw-r--r--doc/security/rate_limits.md3
-rw-r--r--doc/security/reset_user_password.md10
-rw-r--r--doc/security/two_factor_authentication.md22
-rw-r--r--doc/security/unlock_user.md3
-rw-r--r--doc/security/webhooks.md3
-rw-r--r--doc/subscriptions/gitlab_com/index.md7
-rw-r--r--doc/subscriptions/img/additional_minutes.pngbin12668 -> 0 bytes
-rw-r--r--doc/subscriptions/img/buy_btn.pngbin10917 -> 0 bytes
-rw-r--r--doc/subscriptions/img/buy_minutes_card.pngbin11875 -> 0 bytes
-rw-r--r--doc/subscriptions/index.md5
-rw-r--r--doc/subscriptions/self_managed/index.md56
-rw-r--r--doc/system_hooks/system_hooks.md16
-rw-r--r--doc/tools/email.md3
-rw-r--r--doc/topics/application_development_platform/index.md6
-rw-r--r--doc/topics/authentication/index.md6
-rw-r--r--doc/topics/autodevops/customize.md15
-rw-r--r--doc/topics/autodevops/img/autodevops_multiple_clusters.pngbin12619 -> 0 bytes
-rw-r--r--doc/topics/autodevops/index.md112
-rw-r--r--doc/topics/autodevops/quick_start_guide.md13
-rw-r--r--doc/topics/autodevops/requirements.md8
-rw-r--r--doc/topics/autodevops/stages.md29
-rw-r--r--doc/topics/autodevops/upgrading_auto_deploy_dependencies.md4
-rw-r--r--doc/topics/autodevops/upgrading_postgresql.md6
-rw-r--r--doc/topics/cron/index.md6
-rw-r--r--doc/topics/git/git_rebase.md2
-rw-r--r--doc/topics/git/lfs/index.md13
-rw-r--r--doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md3
-rw-r--r--doc/topics/git/lfs/migrate_to_git_lfs.md3
-rw-r--r--doc/topics/git/partial_clone.md2
-rw-r--r--doc/topics/gitlab_flow.md2
-rw-r--r--doc/topics/index.md9
-rw-r--r--doc/topics/offline/index.md6
-rw-r--r--doc/topics/offline/quick_start_guide.md10
-rw-r--r--doc/topics/web_application_firewall/index.md25
-rw-r--r--doc/topics/web_application_firewall/quick_start_guide.md8
-rw-r--r--doc/university/README.md3
-rw-r--r--doc/university/training/gitlab_flow.md3
-rw-r--r--doc/university/training/index.md3
-rw-r--r--doc/university/training/topics/agile_git.md3
-rw-r--r--doc/university/training/topics/bisect.md3
-rw-r--r--doc/university/training/topics/cherry_picking.md3
-rw-r--r--doc/university/training/topics/env_setup.md36
-rw-r--r--doc/university/training/topics/feature_branching.md3
-rw-r--r--doc/university/training/topics/getting_started.md3
-rw-r--r--doc/university/training/topics/git_add.md3
-rw-r--r--doc/university/training/topics/git_intro.md3
-rw-r--r--doc/university/training/topics/git_log.md3
-rw-r--r--doc/university/training/topics/merge_conflicts.md3
-rw-r--r--doc/university/training/topics/merge_requests.md3
-rw-r--r--doc/university/training/topics/rollback_commits.md3
-rw-r--r--doc/university/training/topics/stash.md3
-rw-r--r--doc/university/training/topics/subtree.md3
-rw-r--r--doc/university/training/topics/tags.md3
-rw-r--r--doc/university/training/topics/unstage.md3
-rw-r--r--doc/university/training/user_training.md3
-rw-r--r--doc/update/README.md300
-rw-r--r--doc/update/mysql_to_postgresql.md6
-rw-r--r--doc/update/patch_versions.md3
-rw-r--r--doc/update/restore_after_failure.md6
-rw-r--r--doc/update/upgrading_from_ce_to_ee.md3
-rw-r--r--doc/update/upgrading_from_source.md11
-rw-r--r--doc/update/upgrading_postgresql_using_slony.md6
-rw-r--r--doc/user/abuse_reports.md6
-rw-r--r--doc/user/admin_area/activating_deactivating_users.md6
-rw-r--r--doc/user/admin_area/analytics/dev_ops_report.md10
-rw-r--r--doc/user/admin_area/analytics/img/instance_activity_pipelines_chart_v13_6.pngbin0 -> 45639 bytes
-rw-r--r--doc/user/admin_area/analytics/index.md12
-rw-r--r--doc/user/admin_area/analytics/instance_statistics.md46
-rw-r--r--doc/user/admin_area/analytics/user_cohorts.md10
-rw-r--r--doc/user/admin_area/appearance.md5
-rw-r--r--doc/user/admin_area/approving_users.md6
-rw-r--r--doc/user/admin_area/blocking_unblocking_users.md14
-rw-r--r--doc/user/admin_area/broadcast_messages.md10
-rw-r--r--doc/user/admin_area/credentials_inventory.md3
-rw-r--r--doc/user/admin_area/img/appearance_sign_in_preview_v12_3.pngbin330692 -> 84733 bytes
-rw-r--r--doc/user/admin_area/img/appearance_sign_in_v12_3.pngbin275303 -> 74511 bytes
-rw-r--r--doc/user/admin_area/img/mr_approval_settings_compliance_project_v13_1.pngbin36819 -> 0 bytes
-rw-r--r--doc/user/admin_area/img/scope_mr_approval_settings_v13_1.pngbin46908 -> 0 bytes
-rw-r--r--doc/user/admin_area/index.md17
-rw-r--r--doc/user/admin_area/license.md19
-rw-r--r--doc/user/admin_area/monitoring/health_check.md3
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md11
-rw-r--r--doc/user/admin_area/settings/external_authorization.md3
-rw-r--r--doc/user/admin_area/settings/help_page.md3
-rw-r--r--doc/user/admin_area/settings/img/custom_sign_in_page_v13_6.pngbin0 -> 61203 bytes
-rw-r--r--doc/user/admin_area/settings/img/disable_signup_v12_7.pngbin7928 -> 0 bytes
-rw-r--r--doc/user/admin_area/settings/img/respond_to_terms.pngbin205994 -> 81046 bytes
-rw-r--r--doc/user/admin_area/settings/img/sign_up_restrictions_v13_5.pngbin39902 -> 0 bytes
-rw-r--r--doc/user/admin_area/settings/index.md5
-rw-r--r--doc/user/admin_area/settings/project_integration_management.md74
-rw-r--r--doc/user/admin_area/settings/protected_paths.md3
-rw-r--r--doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md3
-rw-r--r--doc/user/admin_area/settings/sign_in_restrictions.md20
-rw-r--r--doc/user/admin_area/settings/sign_up_restrictions.md132
-rw-r--r--doc/user/admin_area/settings/terms.md3
-rw-r--r--doc/user/admin_area/settings/third_party_offers.md3
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md3
-rw-r--r--doc/user/admin_area/settings/user_and_ip_rate_limits.md40
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md2
-rw-r--r--doc/user/analytics/code_review_analytics.md2
-rw-r--r--doc/user/analytics/index.md5
-rw-r--r--doc/user/analytics/merge_request_analytics.md10
-rw-r--r--doc/user/analytics/productivity_analytics.md2
-rw-r--r--doc/user/analytics/repository_analytics.md2
-rw-r--r--doc/user/analytics/value_stream_analytics.md12
-rw-r--r--doc/user/application_security/api_fuzzing/index.md192
-rw-r--r--doc/user/application_security/container_scanning/index.md29
-rw-r--r--doc/user/application_security/coverage_fuzzing/img/coverage_fuzzing_report_v13_6.pngbin0 -> 14522 bytes
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md29
-rw-r--r--doc/user/application_security/dast/img/dast_on_demand_v13_2.pngbin26144 -> 0 bytes
-rw-r--r--doc/user/application_security/dast/img/dast_single_v13_0.pngbin211373 -> 135324 bytes
-rw-r--r--doc/user/application_security/dast/index.md116
-rw-r--r--doc/user/application_security/dependency_list/img/dependency_list_v12_3.pngbin156081 -> 0 bytes
-rw-r--r--doc/user/application_security/dependency_list/img/dependency_list_v12_4.pngbin137591 -> 0 bytes
-rw-r--r--doc/user/application_security/dependency_list/img/yarn_dependency_path_v13_6.pngbin0 -> 44158 bytes
-rw-r--r--doc/user/application_security/dependency_list/index.md14
-rw-r--r--doc/user/application_security/dependency_scanning/index.md18
-rw-r--r--doc/user/application_security/img/security_configuration_page_v13_2.pngbin51691 -> 0 bytes
-rw-r--r--doc/user/application_security/img/security_widget_v13_6.pngbin0 -> 3229 bytes
-rw-r--r--doc/user/application_security/img/vulnerability_page_merge_request_button_dropdown_v13_1.pngbin0 -> 53561 bytes
-rw-r--r--doc/user/application_security/img/vulnerability_page_merge_request_button_v13_1.pngbin0 -> 15394 bytes
-rw-r--r--doc/user/application_security/img/vulnerability_solution.pngbin9750 -> 0 bytes
-rw-r--r--doc/user/application_security/index.md167
-rw-r--r--doc/user/application_security/offline_deployments/index.md28
-rw-r--r--doc/user/application_security/sast/analyzers.md21
-rw-r--r--doc/user/application_security/sast/index.md58
-rw-r--r--doc/user/application_security/secret_detection/index.md44
-rw-r--r--doc/user/application_security/security_dashboard/img/group_security_dashboard_export_csv_v13_1.pngbin42309 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/project_security_dashboard_chart_v13_6.pngbin0 -> 62882 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/project_security_dashboard_export_csv_v12_10.pngbin9766 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/index.md97
-rw-r--r--doc/user/application_security/threat_monitoring/index.md2
-rw-r--r--doc/user/application_security/vulnerabilities/img/vulnerability_page_download_patch_button_v13_1.pngbin8979 -> 0 bytes
-rw-r--r--doc/user/application_security/vulnerabilities/index.md26
-rw-r--r--doc/user/clusters/agent/index.md300
-rw-r--r--doc/user/clusters/applications.md82
-rw-r--r--doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_3_1.pngbin71374 -> 0 bytes
-rw-r--r--doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_6.pngbin0 -> 64273 bytes
-rw-r--r--doc/user/compliance/compliance_dashboard/index.md14
-rw-r--r--doc/user/compliance/license_compliance/img/license_compliance_add_license_v13_0.pngbin21244 -> 0 bytes
-rw-r--r--doc/user/compliance/license_compliance/img/license_compliance_decision_v13_0.pngbin12536 -> 0 bytes
-rw-r--r--doc/user/compliance/license_compliance/img/license_compliance_pipeline_tab_v13_0.pngbin18910 -> 0 bytes
-rw-r--r--doc/user/compliance/license_compliance/img/license_compliance_search_v13_0.pngbin10686 -> 0 bytes
-rw-r--r--doc/user/compliance/license_compliance/img/license_compliance_settings_v13_0.pngbin6763 -> 0 bytes
-rw-r--r--doc/user/compliance/license_compliance/index.md17
-rw-r--r--doc/user/discussions/img/discussions_resolved.pngbin4152 -> 0 bytes
-rw-r--r--doc/user/discussions/img/mr_review_unresolve2.pngbin8971 -> 0 bytes
-rw-r--r--doc/user/discussions/img/new_issue_for_discussion.pngbin11324 -> 0 bytes
-rw-r--r--doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved.pngbin17888 -> 0 bytes
-rw-r--r--doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved_msg.pngbin4944 -> 0 bytes
-rw-r--r--doc/user/discussions/img/preview_issue_for_discussion.pngbin26965 -> 0 bytes
-rw-r--r--doc/user/discussions/img/preview_issue_for_discussions.pngbin35211 -> 0 bytes
-rw-r--r--doc/user/discussions/img/resolve_discussion_button.pngbin4683 -> 0 bytes
-rw-r--r--doc/user/discussions/img/resolve_discussion_issue_notice.pngbin4186 -> 0 bytes
-rw-r--r--doc/user/discussions/img/resolve_discussion_open_issue.pngbin7514 -> 0 bytes
-rw-r--r--doc/user/feature_highlight.md6
-rw-r--r--doc/user/gitlab_com/index.md52
-rw-r--r--doc/user/group/contribution_analytics/index.md2
-rw-r--r--doc/user/group/dependency_proxy/img/group_dependency_proxy.pngbin40162 -> 0 bytes
-rw-r--r--doc/user/group/epics/img/containing_epic.pngbin159919 -> 40208 bytes
-rw-r--r--doc/user/group/epics/index.md2
-rw-r--r--doc/user/group/epics/manage_epics.md50
-rw-r--r--doc/user/group/img/add_new_members.pngbin79358 -> 0 bytes
-rw-r--r--doc/user/group/img/add_new_members_v13_6.pngbin0 -> 43257 bytes
-rw-r--r--doc/user/group/img/create_new_project_from_group.pngbin37231 -> 0 bytes
-rw-r--r--doc/user/group/img/create_new_project_from_group_v13_6.pngbin0 -> 40062 bytes
-rw-r--r--doc/user/group/img/manual_permissions_v13_1.pngbin11115 -> 0 bytes
-rw-r--r--doc/user/group/img/manual_permissions_v13_6.pngbin0 -> 70840 bytes
-rw-r--r--doc/user/group/img/restrict-by-email.gifbin0 -> 149735 bytes
-rw-r--r--doc/user/group/img/restrict-by-ip.gifbin0 -> 147080 bytes
-rw-r--r--doc/user/group/index.md68
-rw-r--r--doc/user/group/insights/index.md2
-rw-r--r--doc/user/group/issues_analytics/index.md2
-rw-r--r--doc/user/group/iterations/index.md46
-rw-r--r--doc/user/group/repositories_analytics/index.md13
-rw-r--r--doc/user/group/roadmap/index.md2
-rw-r--r--doc/user/group/saml_sso/group_managed_accounts.md2
-rw-r--r--doc/user/group/saml_sso/index.md6
-rw-r--r--doc/user/group/saml_sso/scim_setup.md86
-rw-r--r--doc/user/group/settings/img/new_group_navigation_v13_1.pngbin83427 -> 39500 bytes
-rw-r--r--doc/user/group/subgroups/img/create_subgroup_button.pngbin11161 -> 0 bytes
-rw-r--r--doc/user/group/subgroups/img/create_subgroup_button_v13_6.pngbin0 -> 16989 bytes
-rw-r--r--doc/user/group/subgroups/index.md13
-rw-r--r--doc/user/img/unordered_check_list_render_gfm.pngbin2781 -> 0 bytes
-rw-r--r--doc/user/index.md31
-rw-r--r--doc/user/infrastructure/img/terraform_list_view_v13_5.pngbin0 -> 13849 bytes
-rw-r--r--doc/user/infrastructure/img/terraform_plan_widget_v13_0.pngbin10986 -> 0 bytes
-rw-r--r--doc/user/infrastructure/index.md543
-rw-r--r--doc/user/infrastructure/mr_integration.md205
-rw-r--r--doc/user/infrastructure/terraform_state.md360
-rw-r--r--doc/user/instance/clusters/index.md6
-rw-r--r--doc/user/markdown.md25
-rw-r--r--doc/user/operations_dashboard/index.md6
-rw-r--r--doc/user/packages/composer_repository/img/project_id_v13_5.pngbin9264 -> 0 bytes
-rw-r--r--doc/user/packages/composer_repository/index.md4
-rw-r--r--doc/user/packages/conan_repository/index.md165
-rw-r--r--doc/user/packages/container_registry/index.md10
-rw-r--r--doc/user/packages/dependency_proxy/index.md8
-rw-r--r--doc/user/packages/generic_packages/index.md12
-rw-r--r--doc/user/packages/go_proxy/index.md150
-rw-r--r--doc/user/packages/index.md50
-rw-r--r--doc/user/packages/maven_repository/index.md699
-rw-r--r--doc/user/packages/npm_registry/img/npm_package_view_v12_5.pngbin37994 -> 0 bytes
-rw-r--r--doc/user/packages/npm_registry/index.md495
-rw-r--r--doc/user/packages/nuget_repository/img/visual_studio_nuget_source_added.pngbin23888 -> 6234 bytes
-rw-r--r--doc/user/packages/nuget_repository/index.md279
-rw-r--r--doc/user/packages/package_registry/index.md21
-rw-r--r--doc/user/packages/pypi_repository/index.md363
-rw-r--r--doc/user/packages/workflows/monorepo.md2
-rw-r--r--doc/user/packages/workflows/project_registry.md8
-rw-r--r--doc/user/permissions.md18
-rw-r--r--doc/user/profile/account/create_accounts.md4
-rw-r--r--doc/user/profile/account/delete_account.md2
-rw-r--r--doc/user/profile/account/img/register_tab.pngbin69998 -> 0 bytes
-rw-r--r--doc/user/profile/account/img/register_v13_6.pngbin0 -> 42777 bytes
-rw-r--r--doc/user/profile/account/two_factor_authentication.md181
-rw-r--r--doc/user/profile/active_sessions.md3
-rw-r--r--doc/user/profile/img/busy_status_indicator_v13_6.pngbin0 -> 13763 bytes
-rw-r--r--doc/user/profile/img/unknown_sign_in_email_v13_0.pngbin20047 -> 0 bytes
-rw-r--r--doc/user/profile/index.md7
-rw-r--r--doc/user/profile/notifications.md18
-rw-r--r--doc/user/profile/preferences.md3
-rw-r--r--doc/user/profile/unknown_sign_in_notification.md2
-rw-r--r--doc/user/project/canary_deployments.md77
-rw-r--r--doc/user/project/clusters/add_eks_clusters.md7
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md12
-rw-r--r--doc/user/project/clusters/index.md18
-rw-r--r--doc/user/project/clusters/securing.md4
-rw-r--r--doc/user/project/clusters/serverless/aws.md14
-rw-r--r--doc/user/project/code_intelligence.md4
-rw-r--r--doc/user/project/code_owners.md14
-rw-r--r--doc/user/project/deploy_boards.md6
-rw-r--r--doc/user/project/deploy_tokens/index.md69
-rw-r--r--doc/user/project/description_templates.md2
-rw-r--r--doc/user/project/img/epics_swimlanes_drag_and_drop.pngbin0 -> 34381 bytes
-rw-r--r--doc/user/project/img/epics_swimlanes_v13.6.pngbin0 -> 66710 bytes
-rw-r--r--doc/user/project/img/group_issue_board.pngbin163417 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_board_add_list.pngbin6404 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_board_add_list_v13_6.pngbin0 -> 11433 bytes
-rw-r--r--doc/user/project/img/issue_board_assignee_lists.pngbin134635 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_board_assignee_lists_v13_6.pngbin0 -> 32007 bytes
-rw-r--r--doc/user/project/img/issue_board_creation.pngbin108615 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_board_creation_v13_6.pngbin0 -> 44050 bytes
-rw-r--r--doc/user/project/img/issue_board_edit_button.pngbin108114 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_board_focus_mode.gifbin1043366 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_board_milestone_lists.pngbin58740 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_board_milestone_lists_v13_6.pngbin0 -> 20456 bytes
-rw-r--r--doc/user/project/img/issue_board_move_issue_card_list.pngbin13592 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_board_move_issue_card_list_v13_6.pngbin0 -> 49895 bytes
-rw-r--r--doc/user/project/img/issue_board_summed_weights.pngbin26687 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_board_summed_weights_v13_6.pngbin0 -> 8185 bytes
-rw-r--r--doc/user/project/img/issue_board_system_notes.pngbin4893 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_board_system_notes_v13_6.pngbin0 -> 8554 bytes
-rw-r--r--doc/user/project/img/issue_board_view_scope.pngbin63529 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_boards_add_issues_modal.pngbin12415 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_boards_add_issues_modal_v13_6.pngbin0 -> 10189 bytes
-rw-r--r--doc/user/project/img/issue_boards_blocked_icon_v12_8.pngbin15487 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_boards_blocked_icon_v13_6.pngbin0 -> 16709 bytes
-rw-r--r--doc/user/project/img/issue_boards_core.pngbin119602 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_boards_core_v13_6.pngbin0 -> 78044 bytes
-rw-r--r--doc/user/project/img/issue_boards_multiple.pngbin21635 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_boards_multiple_v13_6.pngbin0 -> 9348 bytes
-rw-r--r--doc/user/project/img/issue_boards_premium.pngbin98490 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_boards_premium_v13_6.pngbin0 -> 92133 bytes
-rw-r--r--doc/user/project/img/issue_boards_remove_issue.pngbin39347 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_boards_remove_issue_v13_6.pngbin0 -> 27886 bytes
-rw-r--r--doc/user/project/img/rollout_status_canary_ingress.pngbin0 -> 35617 bytes
-rw-r--r--doc/user/project/import/img/gemnasium/connect_github.pngbin49966 -> 20802 bytes
-rw-r--r--doc/user/project/import/img/gemnasium/create_project.pngbin85728 -> 33653 bytes
-rw-r--r--doc/user/project/import/img/gemnasium/project_connected.pngbin21575 -> 10441 bytes
-rw-r--r--doc/user/project/import/img/jira/import_issues_from_jira_form_v12_10.pngbin31679 -> 0 bytes
-rw-r--r--doc/user/project/import/index.md5
-rw-r--r--doc/user/project/import/tfvc.md3
-rw-r--r--doc/user/project/index.md20
-rw-r--r--doc/user/project/insights/index.md6
-rw-r--r--doc/user/project/integrations/ewm.md6
-rw-r--r--doc/user/project/integrations/img/jira_create_new_group_name.pngbin5168 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/toggle_metrics_user_starred_dashboard_v13_0.pngbin14922 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/webex_teams_configuration.pngbin75327 -> 0 bytes
-rw-r--r--doc/user/project/integrations/project_services.md4
-rw-r--r--doc/user/project/integrations/prometheus.md49
-rw-r--r--doc/user/project/integrations/webex_teams.md6
-rw-r--r--doc/user/project/integrations/webhooks.md134
-rw-r--r--doc/user/project/issue_board.md115
-rw-r--r--doc/user/project/issues/csv_export.md6
-rw-r--r--doc/user/project/issues/csv_import.md6
-rw-r--r--doc/user/project/issues/design_management.md2
-rw-r--r--doc/user/project/issues/img/adding_note_to_design_1.pngbin486937 -> 98647 bytes
-rw-r--r--doc/user/project/issues/img/adding_note_to_design_2.pngbin495888 -> 99057 bytes
-rw-r--r--doc/user/project/issues/img/button_close_issue.pngbin12274 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/button_close_issue_v13_6.pngbin0 -> 23033 bytes
-rw-r--r--doc/user/project/issues/img/closing_and_related_issues.pngbin6395 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/confirm_design_deletion_v12_4.pngbin301886 -> 120256 bytes
-rw-r--r--doc/user/project/issues/img/delete_multiple_designs_v12_4.pngbin363274 -> 108361 bytes
-rw-r--r--doc/user/project/issues/img/delete_single_design_v12_4.pngbin921627 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/design_drag_and_drop_uploads_v12_9.pngbin245564 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/design_drag_and_drop_uploads_v13_2.pngbin350728 -> 120300 bytes
-rw-r--r--doc/user/project/issues/img/design_management_v12_3.pngbin91233 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/design_management_v13_2.pngbin286600 -> 106442 bytes
-rw-r--r--doc/user/project/issues/img/design_zooming_v12_7.pngbin591137 -> 221570 bytes
-rw-r--r--doc/user/project/issues/img/epic_tree_health_status_v12_10.pngbin38018 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/issue_health_status_v12_10.pngbin12185 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/issue_health_status_v12_9.pngbin10509 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/new_issue_from_open_issue.pngbin13346 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/new_issue_from_open_issue_v13_6.pngbin0 -> 25667 bytes
-rw-r--r--doc/user/project/issues/img/reopen-issue.pngbin1230 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/report-abuse.pngbin1255 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/select_designs_v12_4.pngbin365232 -> 109286 bytes
-rw-r--r--doc/user/project/issues/index.md7
-rw-r--r--doc/user/project/issues/issue_data_and_actions.md25
-rw-r--r--doc/user/project/issues/managing_issues.md37
-rw-r--r--doc/user/project/labels.md4
-rw-r--r--doc/user/project/members/index.md6
-rw-r--r--doc/user/project/members/share_project_with_groups.md6
-rw-r--r--doc/user/project/merge_requests/code_quality.md36
-rw-r--r--doc/user/project/merge_requests/csv_export.md45
-rw-r--r--doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.pngbin7433 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/project_merge_requests_list_view.pngbin171866 -> 62639 bytes
-rw-r--r--doc/user/project/merge_requests/load_performance_testing.md2
-rw-r--r--doc/user/project/merge_requests/test_coverage_visualization.md10
-rw-r--r--doc/user/project/merge_requests/versions.md3
-rw-r--r--doc/user/project/merge_requests/work_in_progress_merge_requests.md4
-rw-r--r--doc/user/project/milestones/burndown_and_burnup_charts.md40
-rw-r--r--doc/user/project/milestones/burndown_charts.md2
-rw-r--r--doc/user/project/milestones/img/burndown_and_burnup_charts_v13_6.png (renamed from doc/user/project/milestones/img/burndown_and_burnup_charts_v13_5.png)bin55865 -> 55865 bytes
-rw-r--r--doc/user/project/milestones/img/burndown_chart_fixed_v13_6.png (renamed from doc/user/project/milestones/img/burndown_chart_fixed_v13_5.png)bin32250 -> 32250 bytes
-rw-r--r--doc/user/project/milestones/img/burndown_chart_legacy_v13_6.png (renamed from doc/user/project/milestones/img/burndown_chart_legacy_v13_5.png)bin28180 -> 28180 bytes
-rw-r--r--doc/user/project/milestones/img/burndown_chart_v13_6.png (renamed from doc/user/project/milestones/img/burndown_chart_v13_5.png)bin48403 -> 48403 bytes
-rw-r--r--doc/user/project/milestones/img/burnup_chart_v13_6.png (renamed from doc/user/project/milestones/img/burnup_chart_v13_5.png)bin29283 -> 29283 bytes
-rw-r--r--doc/user/project/milestones/img/milestones_new_group_milestone.pngbin144554 -> 39822 bytes
-rw-r--r--doc/user/project/milestones/img/milestones_new_project_milestone.pngbin133541 -> 30379 bytes
-rw-r--r--doc/user/project/milestones/img/milestones_project_milestone_page.pngbin270005 -> 101911 bytes
-rw-r--r--doc/user/project/milestones/index.md2
-rw-r--r--doc/user/project/operations/img/alert_issue_v13_1.pngbin38546 -> 0 bytes
-rw-r--r--doc/user/project/operations/img/error_details_v12_5.pngbin148683 -> 0 bytes
-rw-r--r--doc/user/project/operations/img/error_details_v12_6.pngbin47553 -> 0 bytes
-rw-r--r--doc/user/project/operations/img/error_details_with_issue_v12_6.pngbin50767 -> 0 bytes
-rw-r--r--doc/user/project/operations/img/error_details_with_issue_v12_7.pngbin80625 -> 0 bytes
-rw-r--r--doc/user/project/operations/img/feature_flags_list_v12_7.pngbin7124 -> 0 bytes
-rw-r--r--doc/user/project/operations/img/specs_list_v12_6.pngbin28297 -> 0 bytes
-rw-r--r--doc/user/project/packages/img/maven_package_view.pngbin16105 -> 0 bytes
-rw-r--r--doc/user/project/packages/img/npm_package_view.pngbin10349 -> 0 bytes
-rw-r--r--doc/user/project/pages/getting_started/pages_from_scratch.md9
-rw-r--r--doc/user/project/pages/img/icons/click.pngbin4683 -> 0 bytes
-rw-r--r--doc/user/project/pages/img/icons/cogs.pngbin4425 -> 0 bytes
-rw-r--r--doc/user/project/pages/img/icons/fork.pngbin4380 -> 0 bytes
-rw-r--r--doc/user/project/pages/img/icons/free.pngbin3563 -> 0 bytes
-rw-r--r--doc/user/project/pages/img/icons/monitor.pngbin1982 -> 0 bytes
-rw-r--r--doc/user/project/pages/img/pages_workflow_v12_5.pngbin29541 -> 0 bytes
-rw-r--r--doc/user/project/pages/index.md4
-rw-r--r--doc/user/project/pages/introduction.md2
-rw-r--r--doc/user/project/pages/lets_encrypt_for_gitlab_pages.md3
-rw-r--r--doc/user/project/quick_actions.md5
-rw-r--r--doc/user/project/releases/img/edit_release_page_v12_10.pngbin85295 -> 0 bytes
-rw-r--r--doc/user/project/releases/img/edit_release_page_v12_6.pngbin44412 -> 0 bytes
-rw-r--r--doc/user/project/releases/img/release_with_milestone_v12_5.pngbin20197 -> 0 bytes
-rw-r--r--doc/user/project/releases/img/releases.pngbin43776 -> 0 bytes
-rw-r--r--doc/user/project/releases/img/releases_count_v12_8.pngbin27622 -> 0 bytes
-rw-r--r--doc/user/project/releases/img/releases_sort_v13_6.pngbin0 -> 5571 bytes
-rw-r--r--doc/user/project/releases/index.md17
-rw-r--r--doc/user/project/repository/branches/img/compare_branches.pngbin131046 -> 62436 bytes
-rw-r--r--doc/user/project/repository/img/file_ext_icons_repo_v12_10.pngbin187696 -> 73624 bytes
-rw-r--r--doc/user/project/repository/img/repository_mirroring_push_settings.pngbin92335 -> 31174 bytes
-rw-r--r--doc/user/project/repository/jupyter_notebooks/index.md4
-rw-r--r--doc/user/project/repository/reducing_the_repo_size_using_git.md8
-rw-r--r--doc/user/project/repository/repository_mirroring.md4
-rw-r--r--doc/user/project/repository/web_editor.md7
-rw-r--r--doc/user/project/service_desk.md4
-rw-r--r--doc/user/project/settings/import_export.md14
-rw-r--r--doc/user/project/settings/index.md1
-rw-r--r--doc/user/project/settings/project_access_tokens.md2
-rw-r--r--doc/user/project/static_site_editor/index.md36
-rw-r--r--doc/user/project/web_ide/img/command_palette_v13_6.pngbin0 -> 26660 bytes
-rw-r--r--doc/user/project/web_ide/img/commit_changes_v12_9.pngbin239448 -> 144214 bytes
-rw-r--r--doc/user/project/web_ide/img/dark_theme_v13_0.pngbin205992 -> 99238 bytes
-rw-r--r--doc/user/project/web_ide/img/solarized_light_theme_v13_0.pngbin194914 -> 77660 bytes
-rw-r--r--doc/user/project/web_ide/index.md26
-rw-r--r--doc/user/project/wiki/img/wiki_move_page_1.pngbin17270 -> 0 bytes
-rw-r--r--doc/user/project/wiki/img/wiki_move_page_2.pngbin10571 -> 0 bytes
-rw-r--r--doc/user/project/wiki/img/wiki_sidebar_v13_5.pngbin16039 -> 6022 bytes
-rw-r--r--doc/user/project/wiki/index.md41
-rw-r--r--doc/user/reserved_names.md9
-rw-r--r--doc/user/search/advanced_search_syntax.md4
-rw-r--r--doc/user/search/img/filtering_merge_requests_by_date_v13_6.pngbin0 -> 33790 bytes
-rw-r--r--doc/user/search/img/filtering_merge_requests_by_environment_v13_6.pngbin0 -> 22802 bytes
-rw-r--r--doc/user/search/img/issue_search_filter.pngbin27091 -> 0 bytes
-rw-r--r--doc/user/search/img/project_search_sha_redirect.pngbin0 -> 17031 bytes
-rw-r--r--doc/user/search/index.md32
-rw-r--r--doc/user/shortcuts.md3
-rw-r--r--doc/user/todos.md52
-rw-r--r--doc/user/upgrade_email_bypass.md6
-rw-r--r--lefthook.yml36
-rw-r--r--lib/api/access_requests.rb2
-rw-r--r--lib/api/admin/ci/variables.rb2
-rw-r--r--lib/api/admin/instance_clusters.rb2
-rw-r--r--lib/api/admin/sidekiq.rb2
-rw-r--r--lib/api/api.rb29
-rw-r--r--lib/api/appearance.rb2
-rw-r--r--lib/api/applications.rb2
-rw-r--r--lib/api/avatar.rb2
-rw-r--r--lib/api/award_emoji.rb14
-rw-r--r--lib/api/badges.rb2
-rw-r--r--lib/api/base.rb25
-rw-r--r--lib/api/boards.rb39
-rw-r--r--lib/api/boards_responses.rb35
-rw-r--r--lib/api/branches.rb2
-rw-r--r--lib/api/broadcast_messages.rb2
-rw-r--r--lib/api/ci/pipeline_schedules.rb2
-rw-r--r--lib/api/ci/pipelines.rb42
-rw-r--r--lib/api/ci/runner.rb31
-rw-r--r--lib/api/ci/runners.rb2
-rw-r--r--lib/api/commit_statuses.rb2
-rw-r--r--lib/api/commits.rb2
-rw-r--r--lib/api/composer_packages.rb2
-rw-r--r--lib/api/conan_package_endpoints.rb2
-rw-r--r--lib/api/concerns/packages/npm_endpoints.rb134
-rw-r--r--lib/api/container_registry_event.rb2
-rw-r--r--lib/api/container_repositories.rb41
-rw-r--r--lib/api/debian_package_endpoints.rb2
-rw-r--r--lib/api/dependency_proxy.rb41
-rw-r--r--lib/api/deploy_keys.rb2
-rw-r--r--lib/api/deploy_tokens.rb2
-rw-r--r--lib/api/deployments.rb2
-rw-r--r--lib/api/discussions.rb20
-rw-r--r--lib/api/entities/board.rb1
-rw-r--r--lib/api/entities/commit_signature.rb19
-rw-r--r--lib/api/entities/container_registry.rb9
-rw-r--r--lib/api/entities/invitation.rb15
-rw-r--r--lib/api/entities/merge_request_changes.rb22
-rw-r--r--lib/api/entities/package.rb3
-rw-r--r--lib/api/entities/package_file.rb1
-rw-r--r--lib/api/entities/package_version.rb2
-rw-r--r--lib/api/entities/project_hook.rb2
-rw-r--r--lib/api/entities/release.rb2
-rw-r--r--lib/api/entities/releases/link.rb6
-rw-r--r--lib/api/entities/user_status.rb1
-rw-r--r--lib/api/environments.rb2
-rw-r--r--lib/api/error_tracking.rb2
-rw-r--r--lib/api/events.rb2
-rw-r--r--lib/api/feature_flag_scopes.rb2
-rw-r--r--lib/api/feature_flags.rb2
-rw-r--r--lib/api/feature_flags_user_lists.rb7
-rw-r--r--lib/api/features.rb12
-rw-r--r--lib/api/files.rb2
-rw-r--r--lib/api/freeze_periods.rb2
-rw-r--r--lib/api/generic_packages.rb2
-rwxr-xr-xlib/api/go_proxy.rb4
-rw-r--r--lib/api/group_boards.rb2
-rw-r--r--lib/api/group_clusters.rb2
-rw-r--r--lib/api/group_container_repositories.rb2
-rw-r--r--lib/api/group_export.rb2
-rw-r--r--lib/api/group_import.rb2
-rw-r--r--lib/api/group_labels.rb16
-rw-r--r--lib/api/group_milestones.rb2
-rw-r--r--lib/api/group_packages.rb2
-rw-r--r--lib/api/group_variables.rb2
-rw-r--r--lib/api/groups.rb4
-rw-r--r--lib/api/helpers.rb15
-rw-r--r--lib/api/helpers/discussions_helpers.rb9
-rw-r--r--lib/api/helpers/issues_helpers.rb3
-rw-r--r--lib/api/helpers/label_helpers.rb12
-rw-r--r--lib/api/helpers/members_helpers.rb17
-rw-r--r--lib/api/helpers/notes_helpers.rb10
-rw-r--r--lib/api/helpers/packages/npm.rb62
-rw-r--r--lib/api/helpers/resource_label_events_helpers.rb7
-rw-r--r--lib/api/import_bitbucket_server.rb2
-rw-r--r--lib/api/import_github.rb7
-rw-r--r--lib/api/internal/base.rb40
-rw-r--r--lib/api/internal/kubernetes.rb2
-rw-r--r--lib/api/internal/lfs.rb2
-rw-r--r--lib/api/internal/pages.rb2
-rw-r--r--lib/api/invitations.rb54
-rw-r--r--lib/api/issue_links.rb2
-rw-r--r--lib/api/issues.rb4
-rw-r--r--lib/api/job_artifacts.rb2
-rw-r--r--lib/api/jobs.rb2
-rw-r--r--lib/api/keys.rb2
-rw-r--r--lib/api/labels.rb8
-rw-r--r--lib/api/lint.rb26
-rw-r--r--lib/api/markdown.rb2
-rw-r--r--lib/api/maven_packages.rb4
-rw-r--r--lib/api/members.rb6
-rw-r--r--lib/api/merge_request_approvals.rb2
-rw-r--r--lib/api/merge_request_diffs.rb2
-rw-r--r--lib/api/merge_requests.rb8
-rw-r--r--lib/api/metrics/dashboard/annotations.rb2
-rw-r--r--lib/api/metrics/user_starred_dashboards.rb2
-rw-r--r--lib/api/namespaces.rb2
-rw-r--r--lib/api/notes.rb10
-rw-r--r--lib/api/notification_settings.rb2
-rw-r--r--lib/api/npm_instance_packages.rb16
-rw-r--r--lib/api/npm_packages.rb173
-rw-r--r--lib/api/npm_project_packages.rb66
-rw-r--r--lib/api/nuget_packages.rb2
-rw-r--r--lib/api/package_files.rb2
-rw-r--r--lib/api/pages.rb2
-rw-r--r--lib/api/pages_domains.rb2
-rw-r--r--lib/api/personal_access_tokens.rb61
-rw-r--r--lib/api/project_clusters.rb2
-rw-r--r--lib/api/project_container_repositories.rb2
-rw-r--r--lib/api/project_events.rb2
-rw-r--r--lib/api/project_export.rb2
-rw-r--r--lib/api/project_hooks.rb3
-rw-r--r--lib/api/project_import.rb2
-rw-r--r--lib/api/project_milestones.rb2
-rw-r--r--lib/api/project_packages.rb2
-rw-r--r--lib/api/project_repository_storage_moves.rb2
-rw-r--r--lib/api/project_snapshots.rb2
-rw-r--r--lib/api/project_snippets.rb2
-rw-r--r--lib/api/project_statistics.rb2
-rw-r--r--lib/api/project_templates.rb2
-rw-r--r--lib/api/projects.rb50
-rw-r--r--lib/api/protected_branches.rb2
-rw-r--r--lib/api/protected_tags.rb2
-rw-r--r--lib/api/pypi_packages.rb2
-rw-r--r--lib/api/release/links.rb2
-rw-r--r--lib/api/releases.rb4
-rw-r--r--lib/api/remote_mirrors.rb2
-rw-r--r--lib/api/repositories.rb4
-rw-r--r--lib/api/resource_label_events.rb6
-rw-r--r--lib/api/resource_milestone_events.rb9
-rw-r--r--lib/api/resource_state_events.rb9
-rw-r--r--lib/api/search.rb7
-rw-r--r--lib/api/services.rb2
-rw-r--r--lib/api/settings.rb9
-rw-r--r--lib/api/sidekiq_metrics.rb2
-rw-r--r--lib/api/snippets.rb2
-rw-r--r--lib/api/statistics.rb2
-rw-r--r--lib/api/submodules.rb2
-rw-r--r--lib/api/subscriptions.rb16
-rw-r--r--lib/api/suggestions.rb2
-rw-r--r--lib/api/system_hooks.rb2
-rw-r--r--lib/api/tags.rb12
-rw-r--r--lib/api/templates.rb2
-rw-r--r--lib/api/terraform/state.rb4
-rw-r--r--lib/api/terraform/state_version.rb2
-rw-r--r--lib/api/todos.rb2
-rw-r--r--lib/api/triggers.rb2
-rw-r--r--lib/api/unleash.rb2
-rw-r--r--lib/api/usage_data.rb2
-rw-r--r--lib/api/user_counts.rb2
-rw-r--r--lib/api/users.rb131
-rw-r--r--lib/api/v3/github.rb2
-rw-r--r--lib/api/validations/validators/email_or_email_list.rb21
-rw-r--r--lib/api/variables.rb2
-rw-r--r--lib/api/version.rb2
-rw-r--r--lib/api/wikis.rb2
-rw-r--r--lib/atlassian/jira_connect/client.rb18
-rw-r--r--lib/atlassian/jira_connect/serializers/base_entity.rb6
-rw-r--r--lib/atlassian/jira_connect/serializers/pull_request_entity.rb8
-rw-r--r--lib/atlassian/jira_connect/serializers/repository_entity.rb10
-rw-r--r--lib/backup/files.rb61
-rw-r--r--lib/banzai/filter/emoji_filter.rb7
-rw-r--r--lib/banzai/filter/normalize_source_filter.rb14
-rw-r--r--lib/banzai/filter/reference_filter.rb6
-rw-r--r--lib/banzai/filter/vulnerability_reference_filter.rb22
-rw-r--r--lib/banzai/pipeline/pre_process_pipeline.rb1
-rw-r--r--lib/banzai/reference_parser/base_parser.rb5
-rw-r--r--lib/banzai/reference_parser/vulnerability_parser.rb16
-rw-r--r--lib/bitbucket_server/client.rb4
-rw-r--r--lib/bulk_imports/clients/graphql.rb49
-rw-r--r--lib/bulk_imports/clients/http.rb86
-rw-r--r--lib/bulk_imports/common/extractors/graphql_extractor.rb46
-rw-r--r--lib/bulk_imports/common/loaders/entity_loader.rb15
-rw-r--r--lib/bulk_imports/common/transformers/graphql_cleaner_transformer.rb54
-rw-r--r--lib/bulk_imports/common/transformers/underscorify_keys_transformer.rb19
-rw-r--r--lib/bulk_imports/groups/extractors/subgroups_extractor.rb29
-rw-r--r--lib/bulk_imports/groups/graphql/get_group_query.rb38
-rw-r--r--lib/bulk_imports/groups/loaders/group_loader.rb35
-rw-r--r--lib/bulk_imports/groups/pipelines/group_pipeline.rb19
-rw-r--r--lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline.rb15
-rw-r--r--lib/bulk_imports/groups/transformers/group_attributes_transformer.rb81
-rw-r--r--lib/bulk_imports/groups/transformers/subgroup_to_entity_transformer.rb21
-rw-r--r--lib/bulk_imports/importers/group_importer.rb32
-rw-r--r--lib/bulk_imports/importers/groups_importer.rb36
-rw-r--r--lib/bulk_imports/pipeline.rb12
-rw-r--r--lib/bulk_imports/pipeline/attributes.rb41
-rw-r--r--lib/bulk_imports/pipeline/context.rb33
-rw-r--r--lib/bulk_imports/pipeline/runner.rb66
-rw-r--r--lib/container_registry/client.rb6
-rw-r--r--lib/csv_builders/stream.rb17
-rw-r--r--lib/expand_variables.rb28
-rw-r--r--lib/extracts_ref.rb2
-rw-r--r--lib/feature/shared.rb4
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start.rb34
-rw-r--r--lib/gitlab/analytics/instance_statistics/workers_argument_builder.rb27
-rw-r--r--lib/gitlab/application_rate_limiter.rb3
-rw-r--r--lib/gitlab/auth.rb2
-rw-r--r--lib/gitlab/auth/auth_finders.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_design_internal_ids.rb130
-rw-r--r--lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2.rb86
-rw-r--r--lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules.rb40
-rw-r--r--lib/gitlab/background_migration/populate_has_vulnerabilities.rb62
-rw-r--r--lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb86
-rw-r--r--lib/gitlab/background_migration/populate_vulnerability_feedback_pipeline_id.rb13
-rw-r--r--lib/gitlab/background_migration/replace_blocked_by_links.rb19
-rw-r--r--lib/gitlab/badge/coverage/report.rb38
-rw-r--r--lib/gitlab/bitbucket_server_import/importer.rb71
-rw-r--r--lib/gitlab/bulk_import/client.rb72
-rw-r--r--lib/gitlab/chat/output.rb44
-rw-r--r--lib/gitlab/ci/build/rules/rule/clause/changes.rb12
-rw-r--r--lib/gitlab/ci/charts.rb81
-rw-r--r--lib/gitlab/ci/config/entry/bridge.rb11
-rw-r--r--lib/gitlab/ci/config/entry/job.rb11
-rw-r--r--lib/gitlab/ci/config/entry/processable.rb11
-rw-r--r--lib/gitlab/ci/config/entry/product/variables.rb6
-rw-r--r--lib/gitlab/ci/config/external/mapper.rb10
-rw-r--r--lib/gitlab/ci/features.rb22
-rw-r--r--lib/gitlab/ci/jwt.rb16
-rw-r--r--lib/gitlab/ci/lint.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb10
-rw-r--r--lib/gitlab/ci/pipeline/chain/seed.rb10
-rw-r--r--lib/gitlab/ci/pipeline/chain/seed_block.rb31
-rw-r--r--lib/gitlab/ci/pipeline/seed/environment.rb15
-rw-r--r--lib/gitlab/ci/reports/test_case.rb8
-rw-r--r--lib/gitlab/ci/reports/test_failure_history.rb43
-rw-r--r--lib/gitlab/ci/reports/test_suite_comparer.rb26
-rw-r--r--lib/gitlab/ci/runner_instructions.rb2
-rw-r--r--lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml10
-rw-r--r--lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml56
-rw-r--r--lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml167
-rw-r--r--lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml13
-rw-r--r--lib/gitlab/ci/trace/chunked_io.rb4
-rw-r--r--lib/gitlab/conflict/file.rb47
-rw-r--r--lib/gitlab/current_settings.rb4
-rw-r--r--lib/gitlab/danger/commit_linter.rb2
-rw-r--r--lib/gitlab/danger/helper.rb7
-rw-r--r--lib/gitlab/data_builder/feature_flag.rb19
-rw-r--r--lib/gitlab/database/batch_count.rb4
-rw-r--r--lib/gitlab/database/partitioning/monthly_strategy.rb19
-rw-r--r--lib/gitlab/database/partitioning/replace_table.rb114
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers.rb1
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb90
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb93
-rw-r--r--lib/gitlab/database/postgres_partition.rb23
-rw-r--r--lib/gitlab/database/postgres_partitioned_table.rb35
-rw-r--r--lib/gitlab/database/reindexing.rb1
-rw-r--r--lib/gitlab/dependency_linker/base_linker.rb5
-rw-r--r--lib/gitlab/design_management/copy_design_collection_model_attributes.yml1
-rw-r--r--lib/gitlab/diff/file_collection/merge_request_diff_batch.rb16
-rw-r--r--lib/gitlab/diff/line.rb4
-rw-r--r--lib/gitlab/error_tracking.rb7
-rw-r--r--lib/gitlab/etag_caching/middleware.rb27
-rw-r--r--lib/gitlab/etag_caching/router.rb44
-rw-r--r--lib/gitlab/experimentation.rb180
-rw-r--r--lib/gitlab/experimentation/controller_concern.rb127
-rw-r--r--lib/gitlab/experimentation/group_types.rb10
-rw-r--r--lib/gitlab/git/diff.rb2
-rw-r--r--lib/gitlab/git/repository.rb2
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb4
-rw-r--r--lib/gitlab/github_import.rb21
-rw-r--r--lib/gitlab/github_import/client.rb53
-rw-r--r--lib/gitlab/github_import/sequential_importer.rb5
-rw-r--r--lib/gitlab/gon_helper.rb7
-rw-r--r--lib/gitlab/grape_logging/formatters/lograge_with_timestamp.rb2
-rw-r--r--lib/gitlab/grape_logging/loggers/content_logger.rb16
-rw-r--r--lib/gitlab/graphql/authorize/authorize_field_service.rb48
-rw-r--r--lib/gitlab/graphql/docs/helper.rb6
-rw-r--r--lib/gitlab/graphql/docs/templates/default.md.haml2
-rw-r--r--lib/gitlab/graphql/lazy.rb26
-rw-r--r--lib/gitlab/graphql/loaders/batch_model_loader.rb11
-rw-r--r--lib/gitlab/graphql/present/instrumentation.rb11
-rw-r--r--lib/gitlab/group_search_results.rb4
-rw-r--r--lib/gitlab/hook_data/release_builder.rb45
-rw-r--r--lib/gitlab/i18n/po_linter.rb18
-rw-r--r--lib/gitlab/import_export/importer.rb14
-rw-r--r--lib/gitlab/import_export/json/ndjson_reader.rb9
-rw-r--r--lib/gitlab/import_export/project/import_export.yml18
-rw-r--r--lib/gitlab/import_export/project/sample/date_calculator.rb1
-rw-r--r--lib/gitlab/import_export/project/sample/relation_factory.rb42
-rw-r--r--lib/gitlab/import_export/project/sample/relation_tree_restorer.rb33
-rw-r--r--lib/gitlab/import_export/project/sample/sample_data_relation_tree_restorer.rb51
-rw-r--r--lib/gitlab/import_export/project/sample/tree_restorer.rb19
-rw-r--r--lib/gitlab/import_export/project/tree_restorer.rb6
-rw-r--r--lib/gitlab/import_export/uploads_manager.rb4
-rw-r--r--lib/gitlab/instrumentation/throttle.rb17
-rw-r--r--lib/gitlab/instrumentation_helper.rb6
-rw-r--r--lib/gitlab/json.rb36
-rw-r--r--lib/gitlab/kubernetes/helm/base_command.rb85
-rw-r--r--lib/gitlab/kubernetes/helm/certificate.rb73
-rw-r--r--lib/gitlab/kubernetes/helm/client_command.rb38
-rw-r--r--lib/gitlab/kubernetes/helm/delete_command.rb36
-rw-r--r--lib/gitlab/kubernetes/helm/init_command.rb43
-rw-r--r--lib/gitlab/kubernetes/helm/install_command.rb85
-rw-r--r--lib/gitlab/kubernetes/helm/patch_command.rb65
-rw-r--r--lib/gitlab/kubernetes/helm/pod.rb9
-rw-r--r--lib/gitlab/kubernetes/helm/reset_command.rb48
-rw-r--r--lib/gitlab/kubernetes/helm/v2/base_command.rb93
-rw-r--r--lib/gitlab/kubernetes/helm/v2/certificate.rb75
-rw-r--r--lib/gitlab/kubernetes/helm/v2/client_command.rb40
-rw-r--r--lib/gitlab/kubernetes/helm/v2/delete_command.rb38
-rw-r--r--lib/gitlab/kubernetes/helm/v2/init_command.rb45
-rw-r--r--lib/gitlab/kubernetes/helm/v2/install_command.rb87
-rw-r--r--lib/gitlab/kubernetes/helm/v2/patch_command.rb67
-rw-r--r--lib/gitlab/kubernetes/helm/v2/reset_command.rb50
-rw-r--r--lib/gitlab/kubernetes/helm/v3/base_command.rb101
-rw-r--r--lib/gitlab/kubernetes/helm/v3/delete_command.rb35
-rw-r--r--lib/gitlab/kubernetes/helm/v3/install_command.rb80
-rw-r--r--lib/gitlab/kubernetes/helm/v3/patch_command.rb60
-rw-r--r--lib/gitlab/kubernetes/kube_client.rb28
-rw-r--r--lib/gitlab/legacy_github_import/client.rb5
-rw-r--r--lib/gitlab/legacy_github_import/importer.rb4
-rw-r--r--lib/gitlab/metrics/requests_rack_middleware.rb55
-rw-r--r--lib/gitlab/middleware/handle_malformed_strings.rb103
-rw-r--r--lib/gitlab/middleware/handle_null_bytes.rb61
-rw-r--r--lib/gitlab/middleware/read_only/controller.rb39
-rw-r--r--lib/gitlab/octokit/middleware.rb2
-rw-r--r--lib/gitlab/omniauth_initializer.rb10
-rw-r--r--lib/gitlab/path_regex.rb11
-rw-r--r--lib/gitlab/project_search_results.rb13
-rw-r--r--lib/gitlab/quick_actions/extractor.rb4
-rw-r--r--lib/gitlab/quick_actions/merge_request_actions.rb12
-rw-r--r--lib/gitlab/redis/wrapper.rb4
-rw-r--r--lib/gitlab/reference_extractor.rb4
-rw-r--r--lib/gitlab/regex.rb4
-rw-r--r--lib/gitlab/repository_size_checker.rb10
-rw-r--r--lib/gitlab/repository_size_error_message.rb8
-rw-r--r--lib/gitlab/repository_url_builder.rb3
-rw-r--r--lib/gitlab/robots_txt/parser.rb60
-rw-r--r--lib/gitlab/search/found_blob.rb3
-rw-r--r--lib/gitlab/search/sort_options.rb21
-rw-r--r--lib/gitlab/search_results.rb21
-rw-r--r--lib/gitlab/setup_helper.rb1
-rw-r--r--lib/gitlab/sidekiq_cluster/cli.rb23
-rw-r--r--lib/gitlab/sidekiq_logging/logs_jobs.rb2
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies.rb1
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/base.rb37
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/deduplicates_when_scheduling.rb47
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none.rb5
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed.rb22
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing.rb40
-rw-r--r--lib/gitlab/static_site_editor/config/generated_config.rb4
-rw-r--r--lib/gitlab/template/base_template.rb14
-rw-r--r--lib/gitlab/tracking.rb25
-rw-r--r--lib/gitlab/tracking/destinations/base.rb13
-rw-r--r--lib/gitlab/tracking/destinations/snowplow.rb49
-rw-r--r--lib/gitlab/url_blocker.rb18
-rw-r--r--lib/gitlab/url_blockers/domain_allowlist_entry.rb21
-rw-r--r--lib/gitlab/url_blockers/domain_whitelist_entry.rb21
-rw-r--r--lib/gitlab/url_blockers/ip_allowlist_entry.rb22
-rw-r--r--lib/gitlab/url_blockers/ip_whitelist_entry.rb22
-rw-r--r--lib/gitlab/url_blockers/url_allowlist.rb44
-rw-r--r--lib/gitlab/url_blockers/url_whitelist.rb46
-rw-r--r--lib/gitlab/url_builder.rb2
-rw-r--r--lib/gitlab/usage_data.rb69
-rw-r--r--lib/gitlab/usage_data_counters/aggregated_metrics/common.yml17
-rw-r--r--lib/gitlab/usage_data_counters/designs_counter.rb38
-rw-r--r--lib/gitlab/usage_data_counters/hll_redis_counter.rb244
-rw-r--r--lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb42
-rw-r--r--lib/gitlab/usage_data_counters/known_events.yml305
-rw-r--r--lib/gitlab/usage_data_counters/known_events/common.yml404
-rw-r--r--lib/gitlab/usage_data_counters/known_events/package_events.yml265
-rw-r--r--lib/gitlab/usage_data_counters/static_site_editor_counter.rb2
-rw-r--r--lib/gitlab/usage_data_counters/track_unique_events.rb11
-rw-r--r--lib/gitlab/usage_data_counters/web_ide_counter.rb31
-rw-r--r--lib/gitlab/user_access.rb6
-rw-r--r--lib/gitlab/webpack/dev_server_middleware.rb12
-rw-r--r--lib/gitlab/whats_new.rb26
-rw-r--r--lib/gitlab/with_feature_category.rb50
-rw-r--r--lib/gitlab/workhorse.rb2
-rw-r--r--lib/quality/test_level.rb17
-rw-r--r--lib/rouge/formatters/html_gitlab.rb2
-rw-r--r--lib/rspec_flaky/flaky_examples_collection.rb1
-rw-r--r--lib/support/nginx/gitlab2
-rw-r--r--lib/support/nginx/gitlab-ssl2
-rw-r--r--lib/system_check/app/git_version_check.rb2
-rw-r--r--lib/tasks/gitlab/gitaly.rake2
-rw-r--r--lib/tasks/gitlab/packages/events.rake40
-rw-r--r--locale/am_ET/gitlab.po1766
-rw-r--r--locale/ar_SA/gitlab.po1802
-rw-r--r--locale/as_IN/gitlab.po1766
-rw-r--r--locale/az_AZ/gitlab.po1766
-rw-r--r--locale/ba_RU/gitlab.po1757
-rw-r--r--locale/bg/gitlab.po1768
-rw-r--r--locale/bn_BD/gitlab.po1766
-rw-r--r--locale/bn_IN/gitlab.po1766
-rw-r--r--locale/bs_BA/gitlab.po1777
-rw-r--r--locale/ca_ES/gitlab.po1766
-rw-r--r--locale/cs_CZ/gitlab.po1784
-rw-r--r--locale/cy_GB/gitlab.po1802
-rw-r--r--locale/da_DK/gitlab.po1766
-rw-r--r--locale/de/gitlab.po1792
-rw-r--r--locale/el_GR/gitlab.po1766
-rw-r--r--locale/en/gitlab.po9
-rw-r--r--locale/eo/gitlab.po1768
-rw-r--r--locale/es/gitlab.po2108
-rw-r--r--locale/et_EE/gitlab.po1766
-rw-r--r--locale/fa_IR/gitlab.po1766
-rw-r--r--locale/fi_FI/gitlab.po1766
-rw-r--r--locale/fil_PH/gitlab.po1766
-rw-r--r--locale/fr/gitlab.po1780
-rw-r--r--locale/gitlab.pot1624
-rw-r--r--locale/gl_ES/gitlab.po1766
-rw-r--r--locale/he_IL/gitlab.po1784
-rw-r--r--locale/hi_IN/gitlab.po1766
-rw-r--r--locale/hr_HR/gitlab.po1775
-rw-r--r--locale/hu_HU/gitlab.po1766
-rw-r--r--locale/id_ID/gitlab.po1757
-rw-r--r--locale/ig_NG/gitlab.po1757
-rw-r--r--locale/is_IS/gitlab.po1766
-rw-r--r--locale/it/gitlab.po1768
-rw-r--r--locale/ja/gitlab.po2089
-rw-r--r--locale/ka_GE/gitlab.po1766
-rw-r--r--locale/kab/gitlab.po1766
-rw-r--r--locale/ko/gitlab.po1777
-rw-r--r--locale/ku_TR/gitlab.po1766
-rw-r--r--locale/ky_KG/gitlab.po1766
-rw-r--r--locale/lt_LT/gitlab.po1784
-rw-r--r--locale/mk_MK/gitlab.po32619
-rw-r--r--locale/mn_MN/gitlab.po1766
-rw-r--r--locale/nb_NO/gitlab.po1908
-rw-r--r--locale/nl_NL/gitlab.po1766
-rw-r--r--locale/pa_IN/gitlab.po1766
-rw-r--r--locale/pl_PL/gitlab.po1788
-rw-r--r--locale/pt_BR/gitlab.po1810
-rw-r--r--locale/pt_PT/gitlab.po1768
-rw-r--r--locale/ro_RO/gitlab.po1775
-rw-r--r--locale/ru/gitlab.po2014
-rw-r--r--locale/si_LK/gitlab.po1766
-rw-r--r--locale/sk_SK/gitlab.po1784
-rw-r--r--locale/sl_SI/gitlab.po1784
-rw-r--r--locale/sq_AL/gitlab.po1766
-rw-r--r--locale/sr_CS/gitlab.po1775
-rw-r--r--locale/sr_SP/gitlab.po1775
-rw-r--r--locale/sv_SE/gitlab.po1766
-rw-r--r--locale/sw_KE/gitlab.po1766
-rw-r--r--locale/tr_TR/gitlab.po1790
-rw-r--r--locale/uk/gitlab.po1998
-rw-r--r--locale/ur_PK/gitlab.po1766
-rw-r--r--locale/uz_UZ/gitlab.po1766
-rw-r--r--locale/vi_VN/gitlab.po1757
-rw-r--r--locale/zh_CN/gitlab.po1981
-rw-r--r--locale/zh_HK/gitlab.po1759
-rw-r--r--locale/zh_TW/gitlab.po1761
-rw-r--r--package.json25
-rw-r--r--public/robots.txt22
-rw-r--r--qa/Dockerfile4
-rw-r--r--qa/Gemfile1
-rw-r--r--qa/Gemfile.lock2
-rwxr-xr-xqa/bin/qa16
-rw-r--r--qa/qa.rb2
-rw-r--r--qa/qa/flow/pipeline.rb17
-rw-r--r--qa/qa/page/base.rb15
-rw-r--r--qa/qa/page/component/design_management.rb2
-rw-r--r--qa/qa/page/component/issuable/sidebar.rb10
-rw-r--r--qa/qa/page/component/note.rb87
-rw-r--r--qa/qa/page/component/select2.rb10
-rw-r--r--qa/qa/page/component/snippet.rb15
-rw-r--r--qa/qa/page/dashboard/snippet/edit.rb40
-rw-r--r--qa/qa/page/file/shared/commit_message.rb8
-rw-r--r--qa/qa/page/file/show.rb21
-rw-r--r--qa/qa/page/group/members.rb19
-rw-r--r--qa/qa/page/group/show.rb37
-rw-r--r--qa/qa/page/layout/flash.rb25
-rw-r--r--qa/qa/page/main/login.rb4
-rw-r--r--qa/qa/page/main/sign_up.rb16
-rw-r--r--qa/qa/page/merge_request/show.rb10
-rw-r--r--qa/qa/page/profile/personal_access_tokens.rb5
-rw-r--r--qa/qa/page/project/import/github.rb4
-rw-r--r--qa/qa/page/project/issue/index.rb8
-rw-r--r--qa/qa/page/project/issue/show.rb73
-rw-r--r--qa/qa/page/project/pipeline/show.rb10
-rw-r--r--qa/qa/page/project/settings/advanced.rb3
-rw-r--r--qa/qa/page/project/settings/mirroring_repositories.rb2
-rw-r--r--qa/qa/page/project/show.rb12
-rw-r--r--qa/qa/resource/file.rb43
-rw-r--r--qa/qa/resource/group.rb2
-rw-r--r--qa/qa/resource/issue.rb15
-rw-r--r--qa/qa/resource/project_imported_from_github.rb1
-rw-r--r--qa/qa/resource/project_snippet.rb8
-rw-r--r--qa/qa/resource/runner.rb2
-rw-r--r--qa/qa/resource/snippet.rb32
-rw-r--r--qa/qa/resource/user.rb2
-rw-r--r--qa/qa/runtime/application_settings.rb2
-rw-r--r--qa/qa/runtime/env.rb7
-rw-r--r--qa/qa/service/docker_run/gitlab_runner.rb2
-rw-r--r--qa/qa/service/praefect_manager.rb8
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb12
-rw-r--r--qa/qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb12
-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/2fa_ssh_recovery_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/login_via_instance_wide_saml_sso_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb39
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb14
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb85
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb6
-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.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb53
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb28
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb57
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb31
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb32
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb36
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb54
-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/delete_file_from_snippet_spec.rb60
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb138
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb82
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb111
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb33
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb121
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb88
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb126
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb92
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb113
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb3
-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.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb6
-rw-r--r--qa/qa/support/page/logging.rb2
-rw-r--r--qa/qa/tools/delete_subgroups.rb9
-rw-r--r--qa/spec/service/docker_run/gitlab_runner_spec.rb2
-rw-r--r--qa/spec/service/docker_run/k3s_spec.rb2
-rw-r--r--qa/spec/spec_helper.rb3
-rw-r--r--qa/spec/support/matchers/have_file.rb15
-rw-r--r--qa/spec/support/matchers/have_text.rb48
-rw-r--r--qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb2
-rw-r--r--qa/spec/support/shared_examples/scenario_shared_examples.rb106
-rw-r--r--rubocop/cop/code_reuse/active_record.rb168
-rw-r--r--rubocop/cop/graphql/resolver_type.rb46
-rw-r--r--rubocop/cop/line_break_around_conditional_block.rb132
-rw-r--r--rubocop/qa_helpers.rb2
-rw-r--r--rubocop/rubocop-code_reuse.yml41
-rw-r--r--rubocop/rubocop-migrations.yml1
-rw-r--r--rubocop/rubocop-usage-data.yml1
-rwxr-xr-xscripts/build_assets_image10
-rwxr-xr-xscripts/generate-test-mapping19
-rwxr-xr-xscripts/lint-doc.sh21
-rwxr-xr-xscripts/lint-rugged5
-rwxr-xr-xscripts/pack-test-mapping19
-rw-r--r--scripts/review_apps/base-config.yaml4
-rwxr-xr-xscripts/review_apps/review-apps.sh2
-rw-r--r--scripts/rspec_helpers.sh41
-rwxr-xr-xscripts/unpack-test-mapping17
-rw-r--r--scripts/utils.sh4
-rwxr-xr-xscripts/verify-tff-mapping6
-rw-r--r--spec/bin/feature_flag_spec.rb29
-rw-r--r--spec/bin/sidekiq_cluster_spec.rb4
-rw-r--r--spec/controllers/admin/dashboard_controller_spec.rb12
-rw-r--r--spec/controllers/admin/users_controller_spec.rb53
-rw-r--r--spec/controllers/application_controller_spec.rb10
-rw-r--r--spec/controllers/autocomplete_controller_spec.rb11
-rw-r--r--spec/controllers/concerns/controller_with_feature_category_spec.rb60
-rw-r--r--spec/controllers/concerns/lfs_request_spec.rb75
-rw-r--r--spec/controllers/concerns/metrics_dashboard_spec.rb1
-rw-r--r--spec/controllers/concerns/send_file_upload_spec.rb55
-rw-r--r--spec/controllers/every_controller_spec.rb2
-rw-r--r--spec/controllers/groups/dependency_proxies_controller_spec.rb73
-rw-r--r--spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb161
-rw-r--r--spec/controllers/groups/registry/repositories_controller_spec.rb5
-rw-r--r--spec/controllers/groups/settings/integrations_controller_spec.rb6
-rw-r--r--spec/controllers/groups_controller_spec.rb86
-rw-r--r--spec/controllers/import/bulk_imports_controller_spec.rb36
-rw-r--r--spec/controllers/import/github_controller_spec.rb52
-rw-r--r--spec/controllers/invites_controller_spec.rb69
-rw-r--r--spec/controllers/jwks_controller_spec.rb36
-rw-r--r--spec/controllers/profiles_controller_spec.rb3
-rw-r--r--spec/controllers/projects/alerting/notifications_controller_spec.rb64
-rw-r--r--spec/controllers/projects/avatars_controller_spec.rb30
-rw-r--r--spec/controllers/projects/ci/lints_controller_spec.rb86
-rw-r--r--spec/controllers/projects/ci/pipeline_editor_controller_spec.rb53
-rw-r--r--spec/controllers/projects/cycle_analytics/events_controller_spec.rb2
-rw-r--r--spec/controllers/projects/cycle_analytics_controller_spec.rb2
-rw-r--r--spec/controllers/projects/imports_controller_spec.rb13
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb6
-rw-r--r--spec/controllers/projects/merge_requests/diffs_controller_spec.rb26
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb79
-rw-r--r--spec/controllers/projects/notes_controller_spec.rb19
-rw-r--r--spec/controllers/projects/raw_controller_spec.rb31
-rw-r--r--spec/controllers/projects/registry/repositories_controller_spec.rb16
-rw-r--r--spec/controllers/projects/registry/tags_controller_spec.rb14
-rw-r--r--spec/controllers/projects/releases_controller_spec.rb97
-rw-r--r--spec/controllers/projects/repositories_controller_spec.rb4
-rw-r--r--spec/controllers/projects/settings/operations_controller_spec.rb13
-rw-r--r--spec/controllers/projects/settings/repository_controller_spec.rb10
-rw-r--r--spec/controllers/projects/snippets_controller_spec.rb10
-rw-r--r--spec/controllers/projects/static_site_editor_controller_spec.rb7
-rw-r--r--spec/controllers/projects/tags_controller_spec.rb72
-rw-r--r--spec/controllers/projects/templates_controller_spec.rb97
-rw-r--r--spec/controllers/projects/terraform_controller_spec.rb38
-rw-r--r--spec/controllers/projects_controller_spec.rb51
-rw-r--r--spec/controllers/registrations/welcome_controller_spec.rb79
-rw-r--r--spec/controllers/registrations_controller_spec.rb198
-rw-r--r--spec/controllers/repositories/lfs_storage_controller_spec.rb35
-rw-r--r--spec/controllers/search_controller_spec.rb5
-rw-r--r--spec/controllers/sessions_controller_spec.rb11
-rw-r--r--spec/controllers/snippets_controller_spec.rb8
-rw-r--r--spec/crystalball_env.rb25
-rw-r--r--spec/db/production/settings_spec.rb7
-rw-r--r--spec/db/schema_spec.rb16
-rw-r--r--spec/factories/alert_management/http_integrations.rb6
-rw-r--r--spec/factories/alerts_service_data.rb8
-rw-r--r--spec/factories/analytics/devops_adoption/segment_selections.rb18
-rw-r--r--spec/factories/analytics/devops_adoption/segments.rb7
-rw-r--r--spec/factories/analytics/instance_statistics/measurement.rb (renamed from spec/factories/instance_statistics/measurement.rb)0
-rw-r--r--spec/factories/audit_events.rb6
-rw-r--r--spec/factories/bulk_import.rb16
-rw-r--r--spec/factories/bulk_import/entities.rb20
-rw-r--r--spec/factories/bulk_import/trackers.rb10
-rw-r--r--spec/factories/ci/builds.rb23
-rw-r--r--spec/factories/ci/daily_build_group_report_results.rb8
-rw-r--r--spec/factories/ci/job_artifacts.rb20
-rw-r--r--spec/factories/ci/pipelines.rb8
-rw-r--r--spec/factories/ci/reports/test_case.rb41
-rw-r--r--spec/factories/ci/test_case.rb39
-rw-r--r--spec/factories/ci/test_case_failure.rb9
-rw-r--r--spec/factories/clusters/applications/helm.rb4
-rw-r--r--spec/factories/container_repositories.rb20
-rw-r--r--spec/factories/custom_emoji.rb3
-rw-r--r--spec/factories/dependency_proxy.rb9
-rw-r--r--spec/factories/design_management/design_at_version.rb6
-rw-r--r--spec/factories/design_management/designs.rb6
-rw-r--r--spec/factories/design_management/versions.rb4
-rw-r--r--spec/factories/import_configurations.rb10
-rw-r--r--spec/factories/issues/csv_import.rb8
-rw-r--r--spec/factories/merge_request_cleanup_schedules.rb8
-rw-r--r--spec/factories/packages.rb22
-rw-r--r--spec/factories/packages/build_info.rb11
-rw-r--r--spec/factories/packages/package_file.rb2
-rw-r--r--spec/factories/packages/package_file_build_infos.rb11
-rw-r--r--spec/factories/pages_deployments.rb10
-rw-r--r--spec/factories/project_hooks.rb2
-rw-r--r--spec/factories/project_statistics.rb1
-rw-r--r--spec/factories/projects.rb4
-rw-r--r--spec/factories/protected_branches/push_access_levels.rb1
-rw-r--r--spec/factories/resource_label_events.rb2
-rw-r--r--spec/factories/resource_milestone_event.rb4
-rw-r--r--spec/factories/resource_state_event.rb4
-rw-r--r--spec/factories/serverless/domain.rb4
-rw-r--r--spec/factories/serverless/domain_cluster.rb6
-rw-r--r--spec/factories/services.rb16
-rw-r--r--spec/factories/terraform/state.rb6
-rw-r--r--spec/factories/terraform/state_version.rb1
-rw-r--r--spec/factories/uploads.rb12
-rw-r--r--spec/factories/usage_data.rb5
-rw-r--r--spec/factories/users.rb2
-rw-r--r--spec/factories/wiki_pages.rb8
-rw-r--r--spec/factories/wikis.rb4
-rw-r--r--spec/fast_spec_helper.rb7
-rw-r--r--spec/features/admin/admin_builds_spec.rb6
-rw-r--r--spec/features/admin/admin_dev_ops_report_spec.rb70
-rw-r--r--spec/features/admin/admin_groups_spec.rb5
-rw-r--r--spec/features/admin/admin_settings_spec.rb30
-rw-r--r--spec/features/admin/admin_users_spec.rb68
-rw-r--r--spec/features/admin/admin_uses_repository_checks_spec.rb2
-rw-r--r--spec/features/alert_management_spec.rb15
-rw-r--r--spec/features/alerts_settings/user_views_alerts_settings_spec.rb64
-rw-r--r--spec/features/boards/add_issues_modal_spec.rb7
-rw-r--r--spec/features/breadcrumbs_schema_markup_spec.rb106
-rw-r--r--spec/features/calendar_spec.rb2
-rw-r--r--spec/features/callouts/registration_enabled_spec.rb49
-rw-r--r--spec/features/canonical_link_spec.rb70
-rw-r--r--spec/features/dashboard/datetime_on_tooltips_spec.rb2
-rw-r--r--spec/features/dashboard/shortcuts_spec.rb2
-rw-r--r--spec/features/discussion_comments/merge_request_spec.rb2
-rw-r--r--spec/features/expand_collapse_diffs_spec.rb2
-rw-r--r--spec/features/explore/user_explores_projects_spec.rb107
-rw-r--r--spec/features/file_uploads/multipart_invalid_uploads_spec.rb6
-rw-r--r--spec/features/frequently_visited_projects_and_groups_spec.rb47
-rw-r--r--spec/features/global_search_spec.rb8
-rw-r--r--spec/features/group_variables_spec.rb2
-rw-r--r--spec/features/groups/container_registry_spec.rb14
-rw-r--r--spec/features/groups/dependency_proxy_spec.rb111
-rw-r--r--spec/features/groups/members/filter_members_spec.rb37
-rw-r--r--spec/features/groups/members/leave_group_spec.rb10
-rw-r--r--spec/features/groups/members/list_members_spec.rb15
-rw-r--r--spec/features/groups/members/manage_groups_spec.rb39
-rw-r--r--spec/features/groups/members/manage_members_spec.rb26
-rw-r--r--spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb34
-rw-r--r--spec/features/groups/members/master_manages_access_requests_spec.rb4
-rw-r--r--spec/features/groups/members/search_members_spec.rb13
-rw-r--r--spec/features/groups/members/sort_members_spec.rb70
-rw-r--r--spec/features/groups/milestone_spec.rb1
-rw-r--r--spec/features/groups/navbar_spec.rb14
-rw-r--r--spec/features/groups/settings/repository_spec.rb17
-rw-r--r--spec/features/groups/show_spec.rb10
-rw-r--r--spec/features/groups_spec.rb48
-rw-r--r--spec/features/ide/user_sees_editor_info_spec.rb93
-rw-r--r--spec/features/incidents/user_views_incident_spec.rb82
-rw-r--r--spec/features/invites_spec.rb19
-rw-r--r--spec/features/issuables/close_reopen_report_toggle_spec.rb56
-rw-r--r--spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb4
-rw-r--r--spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb4
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb43
-rw-r--r--spec/features/issues/user_creates_branch_and_merge_request_spec.rb4
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb27
-rw-r--r--spec/features/issues/user_interacts_with_awards_spec.rb4
-rw-r--r--spec/features/issues/user_sees_live_update_spec.rb2
-rw-r--r--spec/features/issues/user_views_issue_spec.rb2
-rw-r--r--spec/features/merge_request/user_comments_on_diff_spec.rb6
-rw-r--r--spec/features/merge_request/user_comments_on_merge_request_spec.rb21
-rw-r--r--spec/features/merge_request/user_expands_diff_spec.rb6
-rw-r--r--spec/features/merge_request/user_merges_immediately_spec.rb2
-rw-r--r--spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb13
-rw-r--r--spec/features/merge_request/user_resolves_conflicts_spec.rb8
-rw-r--r--spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb4
-rw-r--r--spec/features/merge_request/user_resolves_wip_mr_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb5
-rw-r--r--spec/features/merge_request/user_sees_suggest_pipeline_spec.rb38
-rw-r--r--spec/features/merge_request/user_suggests_changes_on_diff_spec.rb2
-rw-r--r--spec/features/merge_request/user_views_diffs_spec.rb2
-rw-r--r--spec/features/merge_requests/user_exports_as_csv_spec.rb31
-rw-r--r--spec/features/merge_requests/user_filters_by_draft_spec.rb31
-rw-r--r--spec/features/merge_requests/user_filters_by_target_branch_spec.rb10
-rw-r--r--spec/features/milestone_spec.rb4
-rw-r--r--spec/features/profile_spec.rb7
-rw-r--r--spec/features/profiles/account_spec.rb6
-rw-r--r--spec/features/profiles/personal_access_tokens_spec.rb8
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb77
-rw-r--r--spec/features/project_group_variables_spec.rb9
-rw-r--r--spec/features/project_variables_spec.rb27
-rw-r--r--spec/features/projects/blobs/edit_spec.rb12
-rw-r--r--spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb2
-rw-r--r--spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb1
-rw-r--r--spec/features/projects/ci/editor_spec.rb21
-rw-r--r--spec/features/projects/ci/lint_spec.rb12
-rw-r--r--spec/features/projects/container_registry_spec.rb18
-rw-r--r--spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb4
-rw-r--r--spec/features/projects/files/user_browses_files_spec.rb49
-rw-r--r--spec/features/projects/issues/design_management/user_uploads_designs_spec.rb2
-rw-r--r--spec/features/projects/jobs_spec.rb29
-rw-r--r--spec/features/projects/navbar_spec.rb19
-rw-r--r--spec/features/projects/pages_spec.rb2
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb2
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb5
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb1
-rw-r--r--spec/features/projects/releases/user_views_edit_release_spec.rb2
-rw-r--r--spec/features/projects/releases/user_views_releases_spec.rb102
-rw-r--r--spec/features/projects/settings/registry_settings_spec.rb12
-rw-r--r--spec/features/projects/settings/service_desk_setting_spec.rb2
-rw-r--r--spec/features/projects/settings/webhooks_settings_spec.rb1
-rw-r--r--spec/features/projects/show/schema_markup_spec.rb23
-rw-r--r--spec/features/projects/snippets/create_snippet_spec.rb2
-rw-r--r--spec/features/projects/terraform_spec.rb48
-rw-r--r--spec/features/projects_spec.rb2
-rw-r--r--spec/features/read_only_spec.rb20
-rw-r--r--spec/features/runners_spec.rb13
-rw-r--r--spec/features/search/user_searches_for_code_spec.rb5
-rw-r--r--spec/features/search/user_searches_for_issues_spec.rb25
-rw-r--r--spec/features/search/user_searches_for_merge_requests_spec.rb5
-rw-r--r--spec/features/search/user_searches_for_milestones_spec.rb5
-rw-r--r--spec/features/search/user_searches_for_wiki_pages_spec.rb5
-rw-r--r--spec/features/search/user_uses_header_search_field_spec.rb56
-rw-r--r--spec/features/search/user_uses_search_filters_spec.rb21
-rw-r--r--spec/features/static_site_editor_spec.rb40
-rw-r--r--spec/features/uploads/user_uploads_file_to_note_spec.rb6
-rw-r--r--spec/features/users/login_spec.rb74
-rw-r--r--spec/features/users/show_spec.rb68
-rw-r--r--spec/features/users/signup_spec.rb117
-rw-r--r--spec/finders/alert_management/http_integrations_finder_spec.rb70
-rw-r--r--spec/finders/ci/commit_statuses_finder_spec.rb178
-rw-r--r--spec/finders/ci/jobs_finder_spec.rb141
-rw-r--r--spec/finders/environment_names_finder_spec.rb180
-rw-r--r--spec/finders/feature_flags_user_lists_finder_spec.rb31
-rw-r--r--spec/finders/group_descendants_finder_spec.rb37
-rw-r--r--spec/finders/issues_finder_spec.rb44
-rw-r--r--spec/finders/merge_requests/by_approvals_finder_spec.rb1
-rw-r--r--spec/finders/packages/group_packages_finder_spec.rb146
-rw-r--r--spec/finders/packages/npm/package_finder_spec.rb6
-rw-r--r--spec/finders/personal_access_tokens_finder_spec.rb21
-rw-r--r--spec/finders/security/jobs_finder_spec.rb21
-rw-r--r--spec/finders/security/license_compliance_jobs_finder_spec.rb24
-rw-r--r--spec/finders/security/security_jobs_finder_spec.rb47
-rw-r--r--spec/finders/user_groups_counter_spec.rb45
-rw-r--r--spec/fixtures/api/schemas/entities/test_case.json8
-rw-r--r--spec/fixtures/api/schemas/entities/test_case/recent_failures.json12
-rw-r--r--spec/fixtures/api/schemas/environment.json1
-rw-r--r--spec/fixtures/api/schemas/graphql/container_repositories.json12
-rw-r--r--spec/fixtures/api/schemas/graphql/container_repository.json40
-rw-r--r--spec/fixtures/api/schemas/graphql/container_repository_details.json49
-rw-r--r--spec/fixtures/api/schemas/internal/pages/lookup_path.json8
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/package_files.json5
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/package_with_build.json5
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/release.json6
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/release/release_for_guest.json6
-rw-r--r--spec/fixtures/csv_no_headers.csv3
-rw-r--r--spec/fixtures/dependency_proxy/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4.gzbin0 -> 32 bytes
-rw-r--r--spec/fixtures/domain_denylist.txt (renamed from spec/fixtures/domain_blacklist.txt)0
-rw-r--r--spec/fixtures/junit/junit_with_duplicate_failed_test_names.xml.gzbin0 -> 576 bytes
-rw-r--r--spec/fixtures/junit/junit_with_three_failures.xml.gzbin0 -> 545 bytes
-rw-r--r--spec/fixtures/lib/gitlab/import_export/complex/project.json20
-rw-r--r--spec/fixtures/lib/gitlab/import_export/designs/project.json9
-rw-r--r--spec/fixtures/packages/debian/README.md21
-rw-r--r--spec/fixtures/packages/debian/libsample0_1.2.3~alpha2-1_amd64.deb1
-rw-r--r--spec/fixtures/packages/debian/libsample0_1.2.3~alpha2_amd64.debbin0 -> 1124 bytes
-rw-r--r--spec/fixtures/packages/debian/sample-dev_1.2.3~binary_amd64.debbin0 -> 1164 bytes
-rw-r--r--spec/fixtures/packages/debian/sample-udeb_1.2.3~alpha2_amd64.udebbin0 -> 736 bytes
-rw-r--r--spec/fixtures/packages/debian/sample/debian/.gitignore8
-rw-r--r--spec/fixtures/packages/debian/sample/debian/changelog5
-rw-r--r--spec/fixtures/packages/debian/sample/debian/control35
-rwxr-xr-xspec/fixtures/packages/debian/sample/debian/rules6
-rw-r--r--spec/fixtures/packages/debian/sample/debian/source/format1
-rw-r--r--spec/fixtures/packages/debian/sample_1.2.3~alpha2.dsc19
-rw-r--r--spec/fixtures/packages/debian/sample_1.2.3~alpha2.tar.xzbin0 -> 864 bytes
-rw-r--r--spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.buildinfo180
-rw-r--r--spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.changes39
-rw-r--r--spec/fixtures/whats_new/05.yml2
-rw-r--r--spec/fixtures/whats_new/20201225_01_01.yml (renamed from spec/fixtures/whats_new/01.yml)0
-rw-r--r--spec/fixtures/whats_new/20201225_01_02.yml (renamed from spec/fixtures/whats_new/02.yml)0
-rw-r--r--spec/fixtures/whats_new/20201225_01_05.yml3
-rw-r--r--spec/frontend/__mocks__/@gitlab/ui.js12
-rw-r--r--spec/frontend/access_tokens/components/__snapshots__/expires_at_field_spec.js.snap24
-rw-r--r--spec/frontend/access_tokens/components/expires_at_field_spec.js34
-rw-r--r--spec/frontend/alert_management/components/alert_details_spec.js45
-rw-r--r--spec/frontend/alert_settings/__snapshots__/alert_settings_form_spec.js.snap50
-rw-r--r--spec/frontend/alert_settings/alert_settings_form_spec.js231
-rw-r--r--spec/frontend/alert_settings/alerts_integrations_list_spec.js89
-rw-r--r--spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_new_spec.js.snap97
-rw-r--r--spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_old_spec.js.snap47
-rw-r--r--spec/frontend/alerts_settings/alert_mapping_builder_spec.js97
-rw-r--r--spec/frontend/alerts_settings/alerts_integrations_list_spec.js125
-rw-r--r--spec/frontend/alerts_settings/alerts_settings_form_new_spec.js364
-rw-r--r--spec/frontend/alerts_settings/alerts_settings_form_old_spec.js204
-rw-r--r--spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js415
-rw-r--r--spec/frontend/alerts_settings/mocks/apollo_mock.js123
-rw-r--r--spec/frontend/alerts_settings/mocks/integrations.json38
-rw-r--r--spec/frontend/alerts_settings/util.js30
-rw-r--r--spec/frontend/analytics/instance_statistics/apollo_mock_data.js62
-rw-r--r--spec/frontend/analytics/instance_statistics/components/__snapshots__/instance_statistics_count_chart_spec.js.snap41
-rw-r--r--spec/frontend/analytics/instance_statistics/components/__snapshots__/pipelines_chart_spec.js.snap161
-rw-r--r--spec/frontend/analytics/instance_statistics/components/app_spec.js17
-rw-r--r--spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js177
-rw-r--r--spec/frontend/analytics/instance_statistics/components/pipelines_chart_spec.js189
-rw-r--r--spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js216
-rw-r--r--spec/frontend/analytics/instance_statistics/components/users_chart_spec.js45
-rw-r--r--spec/frontend/analytics/instance_statistics/mock_data.js7
-rw-r--r--spec/frontend/analytics/instance_statistics/utils_spec.js55
-rw-r--r--spec/frontend/api_spec.js196
-rw-r--r--spec/frontend/awards_handler_spec.js23
-rw-r--r--spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js94
-rw-r--r--spec/frontend/blob/components/blob_header_default_actions_spec.js5
-rw-r--r--spec/frontend/blob/components/blob_header_filepath_spec.js2
-rw-r--r--spec/frontend/blob/components/blob_header_spec.js4
-rw-r--r--spec/frontend/blob/pipeline_tour_success_mock_data.js2
-rw-r--r--spec/frontend/blob/pipeline_tour_success_modal_spec.js2
-rw-r--r--spec/frontend/boards/board_list_new_spec.js2
-rw-r--r--spec/frontend/boards/components/board_assignee_dropdown_spec.js308
-rw-r--r--spec/frontend/boards/components/board_card_spec.js4
-rw-r--r--spec/frontend/boards/components/board_column_new_spec.js72
-rw-r--r--spec/frontend/boards/components/board_column_spec.js2
-rw-r--r--spec/frontend/boards/components/board_list_header_new_spec.js169
-rw-r--r--spec/frontend/boards/components/board_new_issue_new_spec.js115
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js137
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js157
-rw-r--r--spec/frontend/boards/mock_data.js30
-rw-r--r--spec/frontend/boards/stores/actions_spec.js323
-rw-r--r--spec/frontend/boards/stores/getters_spec.js30
-rw-r--r--spec/frontend/boards/stores/mutations_spec.js114
-rw-r--r--spec/frontend/ci_lint/components/ci_lint_results_spec.js35
-rw-r--r--spec/frontend/ci_lint/components/ci_lint_spec.js42
-rw-r--r--spec/frontend/ci_lint/graphql/__snapshots__/resolvers_spec.js.snap73
-rw-r--r--spec/frontend/ci_lint/graphql/resolvers_spec.js38
-rw-r--r--spec/frontend/ci_lint/mock_data.js45
-rw-r--r--spec/frontend/ci_variable_list/ci_variable_list/ajax_variable_list_spec.js203
-rw-r--r--spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js120
-rw-r--r--spec/frontend/clusters/components/__snapshots__/applications_spec.js.snap2
-rw-r--r--spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap2
-rw-r--r--spec/frontend/clusters/components/applications_spec.js2
-rw-r--r--spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap2
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js112
-rw-r--r--spec/frontend/create_cluster/eks_cluster/services/aws_services_facade_spec.js26
-rw-r--r--spec/frontend/create_cluster/eks_cluster/store/actions_spec.js61
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js3
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js2
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js3
-rw-r--r--spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js8
-rw-r--r--spec/frontend/deploy_freeze/helpers.js9
-rw-r--r--spec/frontend/deploy_freeze/store/actions_spec.js3
-rw-r--r--spec/frontend/deploy_freeze/store/mutations_spec.js8
-rw-r--r--spec/frontend/deploy_keys/components/key_spec.js10
-rw-r--r--spec/frontend/design_management/components/__snapshots__/design_scaler_spec.js.snap115
-rw-r--r--spec/frontend/design_management/components/design_overlay_spec.js18
-rw-r--r--spec/frontend/design_management/components/design_scaler_spec.js104
-rw-r--r--spec/frontend/design_management/components/toolbar/__snapshots__/index_spec.js.snap2
-rw-r--r--spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap39
-rw-r--r--spec/frontend/design_management/components/upload/__snapshots__/design_dropzone_spec.js.snap501
-rw-r--r--spec/frontend/design_management/components/upload/button_spec.js15
-rw-r--r--spec/frontend/design_management/components/upload/design_dropzone_spec.js153
-rw-r--r--spec/frontend/design_management/mock_data/apollo_mock.js23
-rw-r--r--spec/frontend/design_management/mock_data/discussion.js2
-rw-r--r--spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap268
-rw-r--r--spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap2
-rw-r--r--spec/frontend/design_management/pages/design/index_spec.js116
-rw-r--r--spec/frontend/design_management/pages/index_spec.js46
-rw-r--r--spec/frontend/design_management/utils/cache_update_spec.js16
-rw-r--r--spec/frontend/design_management/utils/design_management_utils_spec.js10
-rw-r--r--spec/frontend/diffs/components/app_spec.js14
-rw-r--r--spec/frontend/diffs/components/collapsed_files_warning_spec.js9
-rw-r--r--spec/frontend/diffs/components/diff_comment_cell_spec.js43
-rw-r--r--spec/frontend/diffs/components/diff_content_spec.js22
-rw-r--r--spec/frontend/diffs/components/diff_file_header_spec.js34
-rw-r--r--spec/frontend/diffs/components/diff_file_spec.js530
-rw-r--r--spec/frontend/diffs/components/diff_row_spec.js127
-rw-r--r--spec/frontend/diffs/components/diff_row_utils_spec.js73
-rw-r--r--spec/frontend/diffs/components/diff_view_spec.js82
-rw-r--r--spec/frontend/diffs/components/inline_diff_expansion_row_spec.js32
-rw-r--r--spec/frontend/diffs/components/inline_diff_table_row_spec.js26
-rw-r--r--spec/frontend/diffs/components/inline_diff_view_spec.js61
-rw-r--r--spec/frontend/diffs/components/parallel_diff_expansion_row_spec.js31
-rw-r--r--spec/frontend/diffs/components/parallel_diff_table_row_spec.js28
-rw-r--r--spec/frontend/diffs/components/tree_list_spec.js6
-rw-r--r--spec/frontend/diffs/mock_data/diff_file.js1
-rw-r--r--spec/frontend/diffs/mock_data/diff_file_unreadable.js1
-rw-r--r--spec/frontend/diffs/store/actions_spec.js37
-rw-r--r--spec/frontend/diffs/store/getters_spec.js56
-rw-r--r--spec/frontend/diffs/store/mutations_spec.js15
-rw-r--r--spec/frontend/diffs/store/utils_spec.js21
-rw-r--r--spec/frontend/editor/editor_lite_spec.js2
-rw-r--r--spec/frontend/environments/environment_delete_spec.js8
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_list_spec.js28
-rw-r--r--spec/frontend/error_tracking_settings/components/project_dropdown_spec.js14
-rw-r--r--spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js8
-rw-r--r--spec/frontend/feature_flags/components/form_spec.js10
-rw-r--r--spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js78
-rw-r--r--spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/strategy_parameters_spec.js12
-rw-r--r--spec/frontend/feature_flags/components/strategy_spec.js17
-rw-r--r--spec/frontend/feature_flags/mock_data.js2
-rw-r--r--spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js60
-rw-r--r--spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js69
-rw-r--r--spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js50
-rw-r--r--spec/frontend/filtered_search/filtered_search_manager_spec.js3
-rw-r--r--spec/frontend/fixtures/freeze_period.rb9
-rw-r--r--spec/frontend/fixtures/groups.rb9
-rw-r--r--spec/frontend/fixtures/issues.rb2
-rw-r--r--spec/frontend/fixtures/projects.rb24
-rw-r--r--spec/frontend/fixtures/search.rb43
-rw-r--r--spec/frontend/fixtures/static/signin_tabs.html3
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js235
-rw-r--r--spec/frontend/graphql_shared/utils_spec.js4
-rw-r--r--spec/frontend/groups/components/app_spec.js124
-rw-r--r--spec/frontend/groups/components/item_actions_spec.js89
-rw-r--r--spec/frontend/groups/members/index_spec.js13
-rw-r--r--spec/frontend/groups/mock_data.js5
-rw-r--r--spec/frontend/helpers/fake_date.js2
-rw-r--r--spec/frontend/helpers/fake_date_spec.js12
-rw-r--r--spec/frontend/helpers/mock_apollo_helper.js4
-rw-r--r--spec/frontend/helpers/startup_css_helper_spec.js20
-rw-r--r--spec/frontend/ide/components/commit_sidebar/list_collapsed_spec.js75
-rw-r--r--spec/frontend/ide/components/commit_sidebar/list_spec.js1
-rw-r--r--spec/frontend/ide/components/ide_side_bar_spec.js44
-rw-r--r--spec/frontend/ide/components/ide_spec.js214
-rw-r--r--spec/frontend/ide/components/ide_status_list_spec.js27
-rw-r--r--spec/frontend/ide/components/pipelines/list_spec.js7
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js7
-rw-r--r--spec/frontend/ide/components/repo_tab_spec.js16
-rw-r--r--spec/frontend/ide/components/terminal/empty_state_spec.js21
-rw-r--r--spec/frontend/ide/helpers.js15
-rw-r--r--spec/frontend/ide/stores/actions/file_spec.js14
-rw-r--r--spec/frontend/ide/stores/actions_spec.js12
-rw-r--r--spec/frontend/ide/stores/modules/editor/actions_spec.js36
-rw-r--r--spec/frontend/ide/stores/modules/editor/getters_spec.js31
-rw-r--r--spec/frontend/ide/stores/modules/editor/mutations_spec.js78
-rw-r--r--spec/frontend/ide/stores/modules/editor/setup_spec.js44
-rw-r--r--spec/frontend/ide/stores/mutations/file_spec.js12
-rw-r--r--spec/frontend/import_projects/components/import_projects_table_spec.js2
-rw-r--r--spec/frontend/import_projects/store/actions_spec.js51
-rw-r--r--spec/frontend/incidents/components/incidents_list_spec.js10
-rw-r--r--spec/frontend/integrations/edit/components/confirmation_modal_spec.js2
-rw-r--r--spec/frontend/integrations/edit/components/integration_form_spec.js74
-rw-r--r--spec/frontend/integrations/edit/store/actions_spec.js27
-rw-r--r--spec/frontend/integrations/edit/store/getters_spec.js32
-rw-r--r--spec/frontend/integrations/edit/store/mutations_spec.js24
-rw-r--r--spec/frontend/integrations/edit/store/state_spec.js1
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js87
-rw-r--r--spec/frontend/invite_members/components/members_token_select_spec.js112
-rw-r--r--spec/frontend/issuable/related_issues/components/issue_token_spec.js4
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_block_spec.js4
-rw-r--r--spec/frontend/issuable_list/components/issuable_bulk_edit_sidebar_spec.js97
-rw-r--r--spec/frontend/issuable_list/components/issuable_item_spec.js235
-rw-r--r--spec/frontend/issuable_list/components/issuable_list_root_spec.js198
-rw-r--r--spec/frontend/issuable_list/mock_data.js2
-rw-r--r--spec/frontend/issue_show/components/app_spec.js50
-rw-r--r--spec/frontend/issue_show/components/header_actions_spec.js328
-rw-r--r--spec/frontend/issue_show/issue_spec.js5
-rw-r--r--spec/frontend/issues_list/components/issuable_spec.js6
-rw-r--r--spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap6
-rw-r--r--spec/frontend/jobs/components/job_retry_forward_deployment_modal_spec.js76
-rw-r--r--spec/frontend/jobs/components/job_sidebar_details_container_spec.js132
-rw-r--r--spec/frontend/jobs/components/job_sidebar_retry_button_spec.js70
-rw-r--r--spec/frontend/jobs/components/log/line_spec.js149
-rw-r--r--spec/frontend/jobs/components/sidebar_spec.js201
-rw-r--r--spec/frontend/lib/utils/apollo_startup_js_link_spec.js375
-rw-r--r--spec/frontend/lib/utils/common_utils_spec.js19
-rw-r--r--spec/frontend/lib/utils/datetime_utility_spec.js9
-rw-r--r--spec/frontend/lib/utils/dom_utils_spec.js33
-rw-r--r--spec/frontend/lib/utils/number_utility_spec.js11
-rw-r--r--spec/frontend/lib/utils/text_utility_spec.js15
-rw-r--r--spec/frontend/milestones/milestone_combobox_spec.js518
-rw-r--r--spec/frontend/milestones/mock_data.js94
-rw-r--r--spec/frontend/milestones/project_milestone_combobox_spec.js186
-rw-r--r--spec/frontend/milestones/stores/actions_spec.js173
-rw-r--r--spec/frontend/milestones/stores/getter_spec.js18
-rw-r--r--spec/frontend/milestones/stores/mutations_spec.js101
-rw-r--r--spec/frontend/monitoring/components/charts/column_spec.js3
-rw-r--r--spec/frontend/monitoring/components/charts/stacked_column_spec.js12
-rw-r--r--spec/frontend/monitoring/components/charts/time_series_spec.js6
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_spec.js2
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js2
-rw-r--r--spec/frontend/monitoring/components/embeds/embed_group_spec.js4
-rw-r--r--spec/frontend/monitoring/components/variables/dropdown_field_spec.js6
-rw-r--r--spec/frontend/notes/components/discussion_actions_spec.js6
-rw-r--r--spec/frontend/notes/components/discussion_filter_note_spec.js21
-rw-r--r--spec/frontend/notes/components/note_actions_spec.js20
-rw-r--r--spec/frontend/notes/components/note_awards_list_spec.js5
-rw-r--r--spec/frontend/notes/components/note_form_spec.js22
-rw-r--r--spec/frontend/notes/components/note_header_spec.js16
-rw-r--r--spec/frontend/notes/mock_data.js5
-rw-r--r--spec/frontend/packages/details/components/package_title_spec.js10
-rw-r--r--spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap2
-rw-r--r--spec/frontend/pages/labels/components/promote_label_modal_spec.js7
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js105
-rw-r--r--spec/frontend/pages/search/show/highlight_blob_search_result_spec.js15
-rw-r--r--spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js6
-rw-r--r--spec/frontend/performance_bar/components/detailed_metric_spec.js45
-rw-r--r--spec/frontend/pipeline_editor/components/text_editor_spec.js41
-rw-r--r--spec/frontend/pipeline_editor/graphql/resolvers_spec.js42
-rw-r--r--spec/frontend/pipeline_editor/mock_data.js10
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_app_spec.js139
-rw-r--r--spec/frontend/pipeline_new/components/pipeline_new_form_spec.js22
-rw-r--r--spec/frontend/pipelines/graph/graph_component_spec.js4
-rw-r--r--spec/frontend/pipelines/graph/linked_pipeline_spec.js8
-rw-r--r--spec/frontend/pipelines/graph/linked_pipelines_column_spec.js2
-rw-r--r--spec/frontend/pipelines/header_component_spec.js73
-rw-r--r--spec/frontend/pipelines/pipeline_graph/mock_data.js15
-rw-r--r--spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js60
-rw-r--r--spec/frontend/pipelines/pipelines_spec.js2
-rw-r--r--spec/frontend/pipelines/test_reports/test_case_details_spec.js74
-rw-r--r--spec/frontend/pipelines/test_reports/test_suite_table_spec.js3
-rw-r--r--spec/frontend/popovers/components/popovers_spec.js129
-rw-r--r--spec/frontend/popovers/index_spec.js104
-rw-r--r--spec/frontend/profile/account/components/update_username_spec.js208
-rw-r--r--spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap67
-rw-r--r--spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap51
-rw-r--r--spec/frontend/profile/preferences/components/integration_view_spec.js124
-rw-r--r--spec/frontend/profile/preferences/components/profile_preferences_spec.js57
-rw-r--r--spec/frontend/profile/preferences/mock_data.js18
-rw-r--r--spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap2
-rw-r--r--spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap12
-rw-r--r--spec/frontend/projects/pipelines/charts/components/app_spec.js2
-rw-r--r--spec/frontend/projects/pipelines/charts/mock_data.js1
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js76
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js44
-rw-r--r--spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js18
-rw-r--r--spec/frontend/prometheus_metrics/prometheus_metrics_spec.js3
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js4
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_spec.js24
-rw-r--r--spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js4
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js9
-rw-r--r--spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js11
-rw-r--r--spec/frontend/registry/explorer/mock_data.js11
-rw-r--r--spec/frontend/registry/explorer/pages/details_spec.js41
-rw-r--r--spec/frontend/registry/explorer/stores/actions_spec.js79
-rw-r--r--spec/frontend/registry/explorer/stores/mutations_spec.js9
-rw-r--r--spec/frontend/registry/explorer/utils_spec.js45
-rw-r--r--spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap2
-rw-r--r--spec/frontend/releases/__snapshots__/util_spec.js.snap30
-rw-r--r--spec/frontend/releases/components/__snapshots__/issuable_stats_spec.js.snap9
-rw-r--r--spec/frontend/releases/components/app_edit_new_spec.js3
-rw-r--r--spec/frontend/releases/components/issuable_stats_spec.js114
-rw-r--r--spec/frontend/releases/components/release_block_milestone_info_spec.js77
-rw-r--r--spec/frontend/releases/components/releases_sort_spec.js66
-rw-r--r--spec/frontend/releases/components/tag_field_exsting_spec.js21
-rw-r--r--spec/frontend/releases/stores/modules/detail/actions_spec.js1
-rw-r--r--spec/frontend/releases/stores/modules/detail/mutations_spec.js1
-rw-r--r--spec/frontend/releases/stores/modules/list/actions_spec.js48
-rw-r--r--spec/frontend/releases/stores/modules/list/mutations_spec.js12
-rw-r--r--spec/frontend/releases/util_spec.js14
-rw-r--r--spec/frontend/reports/codequality_report/components/codequality_issue_body_spec.js57
-rw-r--r--spec/frontend/reports/components/grouped_test_reports_app_spec.js110
-rw-r--r--spec/frontend/reports/components/report_section_spec.js2
-rw-r--r--spec/frontend/reports/mock_data/recent_failures_report.json46
-rw-r--r--spec/frontend/reports/store/mutations_spec.js2
-rw-r--r--spec/frontend/reports/store/utils_spec.js48
-rw-r--r--spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap2
-rw-r--r--spec/frontend/repository/components/preview/__snapshots__/index_spec.js.snap1
-rw-r--r--spec/frontend/search/dropdown_filter/components/dropdown_filter_spec.js196
-rw-r--r--spec/frontend/search/dropdown_filter/mock_data.js5
-rw-r--r--spec/frontend/search/group_filter/components/group_filter_spec.js172
-rw-r--r--spec/frontend/search/highlight_blob_search_result_spec.js15
-rw-r--r--spec/frontend/search/index_spec.js47
-rw-r--r--spec/frontend/search/mock_data.js24
-rw-r--r--spec/frontend/search/sidebar/components/app_spec.js103
-rw-r--r--spec/frontend/search/sidebar/components/confidentiality_filter_spec.js65
-rw-r--r--spec/frontend/search/sidebar/components/radio_filter_spec.js111
-rw-r--r--spec/frontend/search/sidebar/components/status_filter_spec.js65
-rw-r--r--spec/frontend/search/store/actions_spec.js90
-rw-r--r--spec/frontend/search/store/mutations_spec.js48
-rw-r--r--spec/frontend/search_spec.js14
-rw-r--r--spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js257
-rw-r--r--spec/frontend/set_status_modal/user_availability_status_spec.js31
-rw-r--r--spec/frontend/sidebar/__snapshots__/todo_spec.js.snap2
-rw-r--r--spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js357
-rw-r--r--spec/frontend/sidebar/issuable_assignees_spec.js18
-rw-r--r--spec/frontend/sidebar/sidebar_labels_spec.js171
-rw-r--r--spec/frontend/sidebar/subscriptions_spec.js2
-rw-r--r--spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap10
-rw-r--r--spec/frontend/snippets/components/edit_spec.js85
-rw-r--r--spec/frontend/snippets/components/snippet_visibility_edit_spec.js25
-rw-r--r--spec/frontend/static_site_editor/components/edit_area_spec.js10
-rw-r--r--spec/frontend/static_site_editor/components/edit_meta_controls_spec.js40
-rw-r--r--spec/frontend/static_site_editor/components/edit_meta_modal_spec.js127
-rw-r--r--spec/frontend/static_site_editor/mock_data.js22
-rw-r--r--spec/frontend/static_site_editor/pages/home_spec.js11
-rw-r--r--spec/frontend/static_site_editor/services/front_matterify_spec.js8
-rw-r--r--spec/frontend/static_site_editor/services/renderers/render_image_spec.js96
-rw-r--r--spec/frontend/terraform/components/empty_state_spec.js26
-rw-r--r--spec/frontend/terraform/components/states_table_spec.js102
-rw-r--r--spec/frontend/terraform/components/terraform_list_spec.js172
-rw-r--r--spec/frontend/tooltips/components/tooltips_spec.js8
-rw-r--r--spec/frontend/tooltips/index_spec.js29
-rw-r--r--spec/frontend/tracking_spec.js1
-rw-r--r--spec/frontend/vue_mr_widget/components/extensions/index_spec.js31
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_header_spec.js35
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/mr_widget_options_spec.js15
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap32
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/file_row_header_spec.js.snap24
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/integration_help_text_spec.js.snap27
-rw-r--r--spec/frontend/vue_shared/components/alert_details_table_spec.js23
-rw-r--r--spec/frontend/vue_shared/components/awards_list_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/__snapshots__/simple_viewer_spec.js.snap2
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/confirm_modal_spec.js20
-rw-r--r--spec/frontend/vue_shared/components/dropdown/dropdown_button_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/file_row_spec.js15
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js33
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/integration_help_text_spec.js57
-rw-r--r--spec/frontend/vue_shared/components/local_storage_sync_spec.js26
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/members/mock_data.js1
-rw-r--r--spec/frontend/vue_shared/components/members/table/expiration_datepicker_spec.js166
-rw-r--r--spec/frontend/vue_shared/components/members/table/members_table_spec.js101
-rw-r--r--spec/frontend/vue_shared/components/members/table/role_dropdown_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/members/utils_spec.js97
-rw-r--r--spec/frontend/vue_shared/components/modal_copy_button_spec.js11
-rw-r--r--spec/frontend/vue_shared/components/multiselect_dropdown_spec.js31
-rw-r--r--spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/registry/title_area_spec.js57
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js21
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js26
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/mock_data.js107
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js119
-rw-r--r--spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js375
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js11
-rw-r--r--spec/frontend/vue_shared/components/stacked_progress_bar_spec.js74
-rw-r--r--spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap608
-rw-r--r--spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js174
-rw-r--r--spec/frontend/vue_shared/components/user_popover/user_popover_spec.js30
-rw-r--r--spec/frontend/vue_shared/directives/validation_spec.js132
-rw-r--r--spec/frontend/vue_shared/security_reports/security_reports_app_spec.js52
-rw-r--r--spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js203
-rw-r--r--spec/frontend/vue_shared/security_reports/store/modules/sast/mutations_spec.js84
-rw-r--r--spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js203
-rw-r--r--spec/frontend/vue_shared/security_reports/store/modules/secret_detection/mutations_spec.js84
-rw-r--r--spec/frontend/vuex_shared/modules/members/actions_spec.js134
-rw-r--r--spec/frontend/vuex_shared/modules/members/mutations_spec.js67
-rw-r--r--spec/frontend/whats_new/components/app_spec.js67
-rw-r--r--spec/frontend/whats_new/store/actions_spec.js21
-rw-r--r--spec/frontend/whats_new/store/mutations_spec.js35
-rw-r--r--spec/frontend/whats_new/utils/get_drawer_body_height_spec.js38
-rw-r--r--spec/frontend_integration/ide/__snapshots__/ide_integration_spec.js.snap22
-rw-r--r--spec/frontend_integration/test_helpers/fixtures.js2
-rw-r--r--spec/graphql/mutations/alert_management/http_integration/create_spec.rb57
-rw-r--r--spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb58
-rw-r--r--spec/graphql/mutations/alert_management/http_integration/reset_token_spec.rb58
-rw-r--r--spec/graphql/mutations/alert_management/http_integration/update_spec.rb58
-rw-r--r--spec/graphql/mutations/alert_management/prometheus_integration/create_spec.rb72
-rw-r--r--spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb58
-rw-r--r--spec/graphql/mutations/alert_management/prometheus_integration/update_spec.rb58
-rw-r--r--spec/graphql/mutations/alert_management/update_alert_status_spec.rb4
-rw-r--r--spec/graphql/mutations/commits/create_spec.rb29
-rw-r--r--spec/graphql/mutations/container_expiration_policies/update_spec.rb20
-rw-r--r--spec/graphql/mutations/container_repositories/destroy_spec.rb67
-rw-r--r--spec/graphql/mutations/issues/set_assignees_spec.rb14
-rw-r--r--spec/graphql/mutations/issues/set_confidential_spec.rb4
-rw-r--r--spec/graphql/mutations/issues/set_due_date_spec.rb4
-rw-r--r--spec/graphql/mutations/issues/set_locked_spec.rb4
-rw-r--r--spec/graphql/mutations/issues/set_severity_spec.rb6
-rw-r--r--spec/graphql/mutations/issues/update_spec.rb6
-rw-r--r--spec/graphql/mutations/labels/create_spec.rb80
-rw-r--r--spec/graphql/mutations/merge_requests/set_assignees_spec.rb14
-rw-r--r--spec/graphql/mutations/merge_requests/set_labels_spec.rb4
-rw-r--r--spec/graphql/mutations/merge_requests/set_locked_spec.rb4
-rw-r--r--spec/graphql/mutations/merge_requests/set_milestone_spec.rb2
-rw-r--r--spec/graphql/mutations/merge_requests/set_wip_spec.rb4
-rw-r--r--spec/graphql/mutations/merge_requests/update_spec.rb4
-rw-r--r--spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb60
-rw-r--r--spec/graphql/mutations/releases/create_spec.rb133
-rw-r--r--spec/graphql/mutations/terraform/state/delete_spec.rb55
-rw-r--r--spec/graphql/mutations/terraform/state/lock_spec.rb68
-rw-r--r--spec/graphql/mutations/terraform/state/unlock_spec.rb61
-rw-r--r--spec/graphql/mutations/todos/create_spec.rb44
-rw-r--r--spec/graphql/mutations/todos/mark_all_done_spec.rb2
-rw-r--r--spec/graphql/mutations/todos/restore_many_spec.rb19
-rw-r--r--spec/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver_spec.rb22
-rw-r--r--spec/graphql/resolvers/alert_management/integrations_resolver_spec.rb38
-rw-r--r--spec/graphql/resolvers/base_resolver_spec.rb184
-rw-r--r--spec/graphql/resolvers/ci/jobs_resolver_spec.rb40
-rw-r--r--spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb104
-rw-r--r--spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb208
-rw-r--r--spec/graphql/resolvers/container_repositories_resolver_spec.rb58
-rw-r--r--spec/graphql/resolvers/design_management/design_resolver_spec.rb15
-rw-r--r--spec/graphql/resolvers/design_management/designs_resolver_spec.rb24
-rw-r--r--spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb7
-rw-r--r--spec/graphql/resolvers/echo_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb8
-rw-r--r--spec/graphql/resolvers/error_tracking/sentry_error_collection_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/error_tracking/sentry_errors_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/group_members_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/merge_request_pipelines_resolver_spec.rb1
-rw-r--r--spec/graphql/resolvers/merge_requests_resolver_spec.rb8
-rw-r--r--spec/graphql/resolvers/metadata_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/project_pipeline_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/projects/services_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/projects/snippets_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/projects_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/release_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/releases_resolver_spec.rb49
-rw-r--r--spec/graphql/resolvers/snippets/blobs_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/snippets_resolver_spec.rb10
-rw-r--r--spec/graphql/resolvers/todo_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/tree_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/users/group_count_resolver_spec.rb62
-rw-r--r--spec/graphql/resolvers/users/snippets_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/users_resolver_spec.rb16
-rw-r--r--spec/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum_spec.rb5
-rw-r--r--spec/graphql/types/alert_management/http_integration_type_spec.rb9
-rw-r--r--spec/graphql/types/alert_management/integration_type_enum_spec.rb22
-rw-r--r--spec/graphql/types/alert_management/integration_type_spec.rb21
-rw-r--r--spec/graphql/types/alert_management/prometheus_integration_type_spec.rb60
-rw-r--r--spec/graphql/types/availability_enum_spec.rb11
-rw-r--r--spec/graphql/types/ci/detailed_status_type_spec.rb21
-rw-r--r--spec/graphql/types/ci/job_type_spec.rb1
-rw-r--r--spec/graphql/types/ci/runner_setup_type_spec.rb16
-rw-r--r--spec/graphql/types/commit_type_spec.rb2
-rw-r--r--spec/graphql/types/container_repository_cleanup_status_enum_spec.rb13
-rw-r--r--spec/graphql/types/container_repository_details_type_spec.rb23
-rw-r--r--spec/graphql/types/container_repository_status_enum_spec.rb9
-rw-r--r--spec/graphql/types/container_repository_tag_type_spec.rb15
-rw-r--r--spec/graphql/types/container_repository_type_spec.rb31
-rw-r--r--spec/graphql/types/countable_connection_type_spec.rb2
-rw-r--r--spec/graphql/types/custom_emoji_type_spec.rb11
-rw-r--r--spec/graphql/types/environment_type_spec.rb8
-rw-r--r--spec/graphql/types/global_id_type_spec.rb3
-rw-r--r--spec/graphql/types/grafana_integration_type_spec.rb1
-rw-r--r--spec/graphql/types/group_invitation_type_spec.rb19
-rw-r--r--spec/graphql/types/invitation_interface_spec.rb43
-rw-r--r--spec/graphql/types/issue_type_spec.rb8
-rw-r--r--spec/graphql/types/merge_request_type_spec.rb4
-rw-r--r--spec/graphql/types/permission_types/note_spec.rb4
-rw-r--r--spec/graphql/types/project_invitation_type_spec.rb19
-rw-r--r--spec/graphql/types/project_statistics_type_spec.rb2
-rw-r--r--spec/graphql/types/project_type_spec.rb3
-rw-r--r--spec/graphql/types/projects/services_enum_spec.rb2
-rw-r--r--spec/graphql/types/query_type_spec.rb14
-rw-r--r--spec/graphql/types/release_asset_link_input_type_spec.rb15
-rw-r--r--spec/graphql/types/release_assets_input_type_spec.rb15
-rw-r--r--spec/graphql/types/release_links_type_spec.rb7
-rw-r--r--spec/graphql/types/root_storage_statistics_type_spec.rb2
-rw-r--r--spec/graphql/types/security/report_types_enum_spec.rb11
-rw-r--r--spec/graphql/types/terraform/state_type_spec.rb5
-rw-r--r--spec/graphql/types/terraform/state_version_type_spec.rb20
-rw-r--r--spec/graphql/types/user_status_type_spec.rb1
-rw-r--r--spec/graphql/types/user_type_spec.rb1
-rw-r--r--spec/helpers/application_settings_helper_spec.rb28
-rw-r--r--spec/helpers/auth_helper_spec.rb37
-rw-r--r--spec/helpers/blob_helper_spec.rb65
-rw-r--r--spec/helpers/branches_helper_spec.rb18
-rw-r--r--spec/helpers/breadcrumbs_helper_spec.rb145
-rw-r--r--spec/helpers/ci/pipeline_editor_helper_spec.rb30
-rw-r--r--spec/helpers/diff_helper_spec.rb58
-rw-r--r--spec/helpers/dropdowns_helper_spec.rb4
-rw-r--r--spec/helpers/gitlab_routing_helper_spec.rb10
-rw-r--r--spec/helpers/groups_helper_spec.rb41
-rw-r--r--spec/helpers/icons_helper_spec.rb6
-rw-r--r--spec/helpers/invite_members_helper_spec.rb120
-rw-r--r--spec/helpers/issuables_helper_spec.rb45
-rw-r--r--spec/helpers/markup_helper_spec.rb1
-rw-r--r--spec/helpers/operations_helper_spec.rb4
-rw-r--r--spec/helpers/page_layout_helper_spec.rb141
-rw-r--r--spec/helpers/profiles_helper_spec.rb32
-rw-r--r--spec/helpers/projects/terraform_helper_spec.rb23
-rw-r--r--spec/helpers/projects_helper_spec.rb11
-rw-r--r--spec/helpers/recaptcha_experiment_helper_spec.rb29
-rw-r--r--spec/helpers/recaptcha_helper_spec.rb29
-rw-r--r--spec/helpers/releases_helper_spec.rb6
-rw-r--r--spec/helpers/search_helper_spec.rb120
-rw-r--r--spec/helpers/sorting_helper_spec.rb18
-rw-r--r--spec/helpers/sourcegraph_helper_spec.rb37
-rw-r--r--spec/helpers/stat_anchors_helper_spec.rb53
-rw-r--r--spec/helpers/time_helper_spec.rb10
-rw-r--r--spec/helpers/todos_helper_spec.rb2
-rw-r--r--spec/helpers/tree_helper_spec.rb31
-rw-r--r--spec/helpers/user_callouts_helper_spec.rb46
-rw-r--r--spec/helpers/users_helper_spec.rb74
-rw-r--r--spec/helpers/whats_new_helper_spec.rb27
-rw-r--r--spec/lib/api/entities/merge_request_changes_spec.rb57
-rw-r--r--spec/lib/api/every_api_endpoint_spec.rb68
-rw-r--r--spec/lib/api/helpers_spec.rb6
-rw-r--r--spec/lib/api/validations/validators/email_or_email_list_spec.rb28
-rw-r--r--spec/lib/atlassian/jira_connect/client_spec.rb29
-rw-r--r--spec/lib/atlassian/jira_connect/serializers/base_entity_spec.rb28
-rw-r--r--spec/lib/atlassian/jira_connect/serializers/pull_request_entity_spec.rb43
-rw-r--r--spec/lib/atlassian/jira_connect/serializers/repository_entity_spec.rb18
-rw-r--r--spec/lib/backup/artifacts_spec.rb3
-rw-r--r--spec/lib/backup/files_spec.rb214
-rw-r--r--spec/lib/backup/pages_spec.rb3
-rw-r--r--spec/lib/backup/uploads_spec.rb3
-rw-r--r--spec/lib/banzai/filter/emoji_filter_spec.rb14
-rw-r--r--spec/lib/banzai/filter/normalize_source_filter_spec.rb26
-rw-r--r--spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb27
-rw-r--r--spec/lib/banzai/reference_parser/base_parser_spec.rb3
-rw-r--r--spec/lib/banzai/reference_parser/design_parser_spec.rb2
-rw-r--r--spec/lib/bitbucket_server/client_spec.rb9
-rw-r--r--spec/lib/bulk_imports/clients/http_spec.rb132
-rw-r--r--spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb75
-rw-r--r--spec/lib/bulk_imports/common/loaders/entity_loader_spec.rb30
-rw-r--r--spec/lib/bulk_imports/common/transformers/graphql_cleaner_transformer_spec.rb88
-rw-r--r--spec/lib/bulk_imports/common/transformers/underscorify_keys_transformer_spec.rb27
-rw-r--r--spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb81
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb102
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb82
-rw-r--r--spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb105
-rw-r--r--spec/lib/bulk_imports/groups/transformers/subgroup_to_entity_transformer_spec.rb25
-rw-r--r--spec/lib/bulk_imports/importers/group_importer_spec.rb56
-rw-r--r--spec/lib/bulk_imports/importers/groups_importer_spec.rb36
-rw-r--r--spec/lib/bulk_imports/pipeline/attributes_spec.rb57
-rw-r--r--spec/lib/bulk_imports/pipeline/context_spec.rb27
-rw-r--r--spec/lib/bulk_imports/pipeline/runner_spec.rb74
-rw-r--r--spec/lib/container_registry/client_spec.rb163
-rw-r--r--spec/lib/csv_builders/stream_spec.rb42
-rw-r--r--spec/lib/expand_variables_spec.rb280
-rw-r--r--spec/lib/extracts_path_spec.rb13
-rw-r--r--spec/lib/extracts_ref_spec.rb17
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start_spec.rb4
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_created_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_first_mentioned_in_commit_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_stage_end_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_created_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_first_deployed_to_production_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_finished_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/instance_statistics/workers_argument_builder_spec.rb35
-rw-r--r--spec/lib/gitlab/auth/auth_finders_spec.rb1
-rw-r--r--spec/lib/gitlab/background_migration/backfill_design_internal_ids_spec.rb69
-rw-r--r--spec/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2_spec.rb65
-rw-r--r--spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb53
-rw-r--r--spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb98
-rw-r--r--spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb63
-rw-r--r--spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb65
-rw-r--r--spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb26
-rw-r--r--spec/lib/gitlab/badge/coverage/report_spec.rb103
-rw-r--r--spec/lib/gitlab/bitbucket_server_import/importer_spec.rb83
-rw-r--r--spec/lib/gitlab/bulk_import/client_spec.rb95
-rw-r--r--spec/lib/gitlab/chat/output_spec.rb99
-rw-r--r--spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb42
-rw-r--r--spec/lib/gitlab/ci/charts_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb128
-rw-r--r--spec/lib/gitlab/ci/config/entry/product/variables_spec.rb71
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb56
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb77
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb78
-rw-r--r--spec/lib/gitlab/ci/jwt_spec.rb63
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb123
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb19
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb78
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb66
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb63
-rw-r--r--spec/lib/gitlab/ci/reports/test_case_spec.rb23
-rw-r--r--spec/lib/gitlab/ci/reports/test_failure_history_spec.rb45
-rw-r--r--spec/lib/gitlab/ci/reports/test_reports_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb146
-rw-r--r--spec/lib/gitlab/ci/reports/test_suite_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/runner_instructions_spec.rb7
-rw-r--r--spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb59
-rw-r--r--spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/variables/collection/item_spec.rb4
-rw-r--r--spec/lib/gitlab/config/entry/simplifiable_spec.rb6
-rw-r--r--spec/lib/gitlab/conflict/file_spec.rb45
-rw-r--r--spec/lib/gitlab/cycle_analytics/events_spec.rb2
-rw-r--r--spec/lib/gitlab/danger/commit_linter_spec.rb7
-rw-r--r--spec/lib/gitlab/danger/helper_spec.rb23
-rw-r--r--spec/lib/gitlab/data_builder/feature_flag_spec.rb25
-rw-r--r--spec/lib/gitlab/database/batch_count_spec.rb23
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb2
-rw-r--r--spec/lib/gitlab/database/partitioning/replace_table_spec.rb113
-rw-r--r--spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb186
-rw-r--r--spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb71
-rw-r--r--spec/lib/gitlab/database/postgres_index_spec.rb44
-rw-r--r--spec/lib/gitlab/database/postgres_partition_spec.rb75
-rw-r--r--spec/lib/gitlab/database/postgres_partitioned_table_spec.rb98
-rw-r--r--spec/lib/gitlab/database/reindexing_spec.rb2
-rw-r--r--spec/lib/gitlab/email/handler/service_desk_handler_spec.rb19
-rw-r--r--spec/lib/gitlab/error_tracking_spec.rb98
-rw-r--r--spec/lib/gitlab/etag_caching/middleware_spec.rb48
-rw-r--r--spec/lib/gitlab/etag_caching/router_spec.rb8
-rw-r--r--spec/lib/gitlab/exclusive_lease_helpers_spec.rb8
-rw-r--r--spec/lib/gitlab/experimentation/controller_concern_spec.rb438
-rw-r--r--spec/lib/gitlab/experimentation/group_types_spec.rb13
-rw-r--r--spec/lib/gitlab/experimentation_spec.rb443
-rw-r--r--spec/lib/gitlab/git/diff_spec.rb14
-rw-r--r--spec/lib/gitlab/git_access_snippet_spec.rb4
-rw-r--r--spec/lib/gitlab/gitaly_client/commit_service_spec.rb4
-rw-r--r--spec/lib/gitlab/gitaly_client/repository_service_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/client_spec.rb129
-rw-r--r--spec/lib/gitlab/github_import/importer/lfs_object_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/sequential_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import_spec.rb57
-rw-r--r--spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb6
-rw-r--r--spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb226
-rw-r--r--spec/lib/gitlab/graphql/lazy_spec.rb96
-rw-r--r--spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb23
-rw-r--r--spec/lib/gitlab/hook_data/release_builder_spec.rb49
-rw-r--r--spec/lib/gitlab/i18n/po_linter_spec.rb5
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml6
-rw-r--r--spec/lib/gitlab/import_export/attributes_finder_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/importer_spec.rb20
-rw-r--r--spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb18
-rw-r--r--spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb1
-rw-r--r--spec/lib/gitlab/import_export/lfs_restorer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/project/relation_factory_spec.rb1
-rw-r--r--spec/lib/gitlab/import_export/project/sample/date_calculator_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/project/sample/relation_factory_spec.rb168
-rw-r--r--spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb100
-rw-r--r--spec/lib/gitlab/import_export/project/sample/sample_data_relation_tree_restorer_spec.rb87
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb44
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml26
-rw-r--r--spec/lib/gitlab/import_export/uploads_manager_spec.rb24
-rw-r--r--spec/lib/gitlab/instrumentation_helper_spec.rb10
-rw-r--r--spec/lib/gitlab/jira_import_spec.rb2
-rw-r--r--spec/lib/gitlab/json_spec.rb518
-rw-r--r--spec/lib/gitlab/kubernetes/helm/api_spec.rb4
-rw-r--r--spec/lib/gitlab/kubernetes/helm/base_command_spec.rb38
-rw-r--r--spec/lib/gitlab/kubernetes/helm/certificate_spec.rb28
-rw-r--r--spec/lib/gitlab/kubernetes/helm/delete_command_spec.rb38
-rw-r--r--spec/lib/gitlab/kubernetes/helm/init_command_spec.rb35
-rw-r--r--spec/lib/gitlab/kubernetes/helm/install_command_spec.rb214
-rw-r--r--spec/lib/gitlab/kubernetes/helm/patch_command_spec.rb114
-rw-r--r--spec/lib/gitlab/kubernetes/helm/pod_spec.rb121
-rw-r--r--spec/lib/gitlab/kubernetes/helm/reset_command_spec.rb50
-rw-r--r--spec/lib/gitlab/kubernetes/helm/v2/base_command_spec.rb50
-rw-r--r--spec/lib/gitlab/kubernetes/helm/v2/certificate_spec.rb28
-rw-r--r--spec/lib/gitlab/kubernetes/helm/v2/delete_command_spec.rb38
-rw-r--r--spec/lib/gitlab/kubernetes/helm/v2/init_command_spec.rb35
-rw-r--r--spec/lib/gitlab/kubernetes/helm/v2/install_command_spec.rb183
-rw-r--r--spec/lib/gitlab/kubernetes/helm/v2/patch_command_spec.rb87
-rw-r--r--spec/lib/gitlab/kubernetes/helm/v2/reset_command_spec.rb50
-rw-r--r--spec/lib/gitlab/kubernetes/helm/v3/base_command_spec.rb44
-rw-r--r--spec/lib/gitlab/kubernetes/helm/v3/delete_command_spec.rb35
-rw-r--r--spec/lib/gitlab/kubernetes/helm/v3/install_command_spec.rb168
-rw-r--r--spec/lib/gitlab/kubernetes/helm/v3/patch_command_spec.rb81
-rw-r--r--spec/lib/gitlab/kubernetes/kube_client_spec.rb32
-rw-r--r--spec/lib/gitlab/legacy_github_import/importer_spec.rb5
-rw-r--r--spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb118
-rw-r--r--spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb182
-rw-r--r--spec/lib/gitlab/middleware/handle_null_bytes_spec.rb88
-rw-r--r--spec/lib/gitlab/middleware/read_only_spec.rb202
-rw-r--r--spec/lib/gitlab/omniauth_initializer_spec.rb28
-rw-r--r--spec/lib/gitlab/path_regex_spec.rb39
-rw-r--r--spec/lib/gitlab/quick_actions/extractor_spec.rb16
-rw-r--r--spec/lib/gitlab/redis/wrapper_spec.rb6
-rw-r--r--spec/lib/gitlab/reference_extractor_spec.rb2
-rw-r--r--spec/lib/gitlab/regex_spec.rb9
-rw-r--r--spec/lib/gitlab/relative_positioning/mover_spec.rb1
-rw-r--r--spec/lib/gitlab/repository_size_checker_spec.rb6
-rw-r--r--spec/lib/gitlab/repository_size_error_message_spec.rb14
-rw-r--r--spec/lib/gitlab/robots_txt/parser_spec.rb15
-rw-r--r--spec/lib/gitlab/search/sort_options_spec.rb34
-rw-r--r--spec/lib/gitlab/sidekiq_cluster/cli_spec.rb165
-rw-r--r--spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb20
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/client_spec.rb109
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/server_spec.rb64
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed_spec.rb20
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb144
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies_spec.rb4
-rw-r--r--spec/lib/gitlab/static_site_editor/config/generated_config_spec.rb20
-rw-r--r--spec/lib/gitlab/throttle_spec.rb18
-rw-r--r--spec/lib/gitlab/tracking/destinations/snowplow_spec.rb78
-rw-r--r--spec/lib/gitlab/tracking/incident_management_spec.rb2
-rw-r--r--spec/lib/gitlab/tracking_spec.rb106
-rw-r--r--spec/lib/gitlab/url_blocker_spec.rb30
-rw-r--r--spec/lib/gitlab/url_blockers/domain_allowlist_entry_spec.rb58
-rw-r--r--spec/lib/gitlab/url_blockers/domain_whitelist_entry_spec.rb58
-rw-r--r--spec/lib/gitlab/url_blockers/ip_allowlist_entry_spec.rb75
-rw-r--r--spec/lib/gitlab/url_blockers/ip_whitelist_entry_spec.rb75
-rw-r--r--spec/lib/gitlab/url_blockers/url_allowlist_spec.rb164
-rw-r--r--spec/lib/gitlab/url_blockers/url_whitelist_spec.rb164
-rw-r--r--spec/lib/gitlab/url_builder_spec.rb1
-rw-r--r--spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb57
-rw-r--r--spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb324
-rw-r--r--spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb138
-rw-r--r--spec/lib/gitlab/usage_data_counters/static_site_editor_counter_spec.rb6
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb174
-rw-r--r--spec/lib/gitlab/with_feature_category_spec.rb69
-rw-r--r--spec/lib/quality/test_level_spec.rb18
-rw-r--r--spec/mailers/devise_mailer_spec.rb30
-rw-r--r--spec/mailers/emails/merge_requests_spec.rb3
-rw-r--r--spec/mailers/emails/projects_spec.rb36
-rw-r--r--spec/mailers/emails/service_desk_spec.rb19
-rw-r--r--spec/mailers/notify_spec.rb197
-rw-r--r--spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb2
-rw-r--r--spec/migrations/20191015154408_drop_merge_requests_require_code_owner_approval_from_projects_spec.rb2
-rw-r--r--spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb26
-rw-r--r--spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb38
-rw-r--r--spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb12
-rw-r--r--spec/migrations/deduplicate_epic_iids_spec.rb36
-rw-r--r--spec/migrations/generate_ci_jwt_signing_key_spec.rb42
-rw-r--r--spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb2
-rw-r--r--spec/migrations/rename_sitemap_namespace_spec.rb30
-rw-r--r--spec/migrations/rename_sitemap_root_namespaces_spec.rb36
-rw-r--r--spec/migrations/reseed_merge_trains_enabled_spec.rb26
-rw-r--r--spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb37
-rw-r--r--spec/migrations/schedule_blocked_by_links_replacement_spec.rb37
-rw-r--r--spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb41
-rw-r--r--spec/migrations/schedule_populate_has_vulnerabilities_spec.rb36
-rw-r--r--spec/migrations/schedule_populate_missing_dismissal_information_for_vulnerabilities_spec.rb37
-rw-r--r--spec/migrations/seed_merge_trains_enabled_spec.rb28
-rw-r--r--spec/migrations/update_historical_data_recorded_at_spec.rb31
-rw-r--r--spec/models/alert_management/http_integration_spec.rb83
-rw-r--r--spec/models/analytics/cycle_analytics/project_stage_spec.rb2
-rw-r--r--spec/models/analytics/devops_adoption/segment_selection_spec.rb69
-rw-r--r--spec/models/analytics/instance_statistics/measurement_spec.rb77
-rw-r--r--spec/models/application_record_spec.rb11
-rw-r--r--spec/models/application_setting_spec.rb32
-rw-r--r--spec/models/authentication_event_spec.rb8
-rw-r--r--spec/models/broadcast_message_spec.rb6
-rw-r--r--spec/models/bulk_imports/tracker_spec.rb27
-rw-r--r--spec/models/ci/bridge_spec.rb60
-rw-r--r--spec/models/ci/build_spec.rb19
-rw-r--r--spec/models/ci/build_trace_chunk_spec.rb66
-rw-r--r--spec/models/ci/build_trace_chunks/legacy_fog_spec.rb164
-rw-r--r--spec/models/ci/daily_build_group_report_result_spec.rb77
-rw-r--r--spec/models/ci/pipeline_spec.rb28
-rw-r--r--spec/models/ci/test_case_failure_spec.rb73
-rw-r--r--spec/models/ci/test_case_spec.rb31
-rw-r--r--spec/models/clusters/agent_token_spec.rb5
-rw-r--r--spec/models/clusters/applications/cert_manager_spec.rb4
-rw-r--r--spec/models/clusters/applications/crossplane_spec.rb2
-rw-r--r--spec/models/clusters/applications/elastic_stack_spec.rb8
-rw-r--r--spec/models/clusters/applications/fluentd_spec.rb2
-rw-r--r--spec/models/clusters/applications/helm_spec.rb6
-rw-r--r--spec/models/clusters/applications/ingress_spec.rb2
-rw-r--r--spec/models/clusters/applications/jupyter_spec.rb2
-rw-r--r--spec/models/clusters/applications/knative_spec.rb4
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb6
-rw-r--r--spec/models/clusters/applications/runner_spec.rb2
-rw-r--r--spec/models/clusters/cluster_spec.rb21
-rw-r--r--spec/models/commit_status_spec.rb137
-rw-r--r--spec/models/concerns/atomic_internal_id_spec.rb16
-rw-r--r--spec/models/concerns/from_union_spec.rb10
-rw-r--r--spec/models/concerns/optionally_search_spec.rb2
-rw-r--r--spec/models/container_expiration_policy_spec.rb55
-rw-r--r--spec/models/container_repository_spec.rb16
-rw-r--r--spec/models/custom_emoji_spec.rb14
-rw-r--r--spec/models/dependency_proxy/blob_spec.rb55
-rw-r--r--spec/models/dependency_proxy/group_setting_spec.rb13
-rw-r--r--spec/models/dependency_proxy/registry_spec.rb57
-rw-r--r--spec/models/deploy_key_spec.rb53
-rw-r--r--spec/models/deploy_keys_project_spec.rb15
-rw-r--r--spec/models/deploy_token_spec.rb33
-rw-r--r--spec/models/deployment_spec.rb8
-rw-r--r--spec/models/design_management/design_at_version_spec.rb2
-rw-r--r--spec/models/design_management/design_spec.rb52
-rw-r--r--spec/models/design_management/version_spec.rb2
-rw-r--r--spec/models/diff_viewer/image_spec.rb40
-rw-r--r--spec/models/environment_spec.rb16
-rw-r--r--spec/models/experiment_spec.rb120
-rw-r--r--spec/models/group_spec.rb143
-rw-r--r--spec/models/instance_metadata_spec.rb12
-rw-r--r--spec/models/internal_id_spec.rb23
-rw-r--r--spec/models/issue_link_spec.rb9
-rw-r--r--spec/models/issues/csv_import_spec.rb10
-rw-r--r--spec/models/key_spec.rb4
-rw-r--r--spec/models/member_spec.rb11
-rw-r--r--spec/models/members/group_member_spec.rb14
-rw-r--r--spec/models/merge_request/cleanup_schedule_spec.rb32
-rw-r--r--spec/models/merge_request_spec.rb13
-rw-r--r--spec/models/namespace/root_storage_statistics_spec.rb2
-rw-r--r--spec/models/namespace_setting_spec.rb7
-rw-r--r--spec/models/namespace_spec.rb95
-rw-r--r--spec/models/operations/feature_flag_spec.rb34
-rw-r--r--spec/models/operations/feature_flags/user_list_spec.rb19
-rw-r--r--spec/models/packages/build_info_spec.rb9
-rw-r--r--spec/models/packages/package_file_build_info_spec.rb9
-rw-r--r--spec/models/packages/package_file_spec.rb2
-rw-r--r--spec/models/packages/package_spec.rb32
-rw-r--r--spec/models/pages/lookup_path_spec.rb120
-rw-r--r--spec/models/pages_deployment_spec.rb36
-rw-r--r--spec/models/personal_access_token_spec.rb12
-rw-r--r--spec/models/personal_snippet_spec.rb3
-rw-r--r--spec/models/project_snippet_spec.rb3
-rw-r--r--spec/models/project_spec.rb99
-rw-r--r--spec/models/project_statistics_spec.rb40
-rw-r--r--spec/models/protected_branch/push_access_level_spec.rb30
-rw-r--r--spec/models/route_spec.rb9
-rw-r--r--spec/models/service_spec.rb116
-rw-r--r--spec/models/terraform/state_spec.rb8
-rw-r--r--spec/models/terraform/state_version_spec.rb1
-rw-r--r--spec/models/user_spec.rb78
-rw-r--r--spec/policies/alert_management/http_integration_policy_spec.rb23
-rw-r--r--spec/policies/base_policy_spec.rb74
-rw-r--r--spec/policies/blob_policy_spec.rb5
-rw-r--r--spec/policies/group_member_policy_spec.rb1
-rw-r--r--spec/policies/group_policy_spec.rb20
-rw-r--r--spec/policies/instance_metadata_policy_spec.rb19
-rw-r--r--spec/policies/issue_policy_spec.rb7
-rw-r--r--spec/policies/merge_request_policy_spec.rb13
-rw-r--r--spec/policies/note_policy_spec.rb117
-rw-r--r--spec/policies/project_policy_spec.rb1
-rw-r--r--spec/policies/service_policy_spec.rb26
-rw-r--r--spec/policies/terraform/state_version_policy_spec.rb33
-rw-r--r--spec/policies/user_policy_spec.rb58
-rw-r--r--spec/policies/wiki_page_policy_spec.rb5
-rw-r--r--spec/presenters/issue_presenter_spec.rb16
-rw-r--r--spec/presenters/packages/detail/package_presenter_spec.rb34
-rw-r--r--spec/presenters/release_presenter_spec.rb73
-rw-r--r--spec/requests/api/admin/instance_clusters_spec.rb1
-rw-r--r--spec/requests/api/api_spec.rb32
-rw-r--r--spec/requests/api/boards_spec.rb43
-rw-r--r--spec/requests/api/ci/pipelines_spec.rb615
-rw-r--r--spec/requests/api/commits_spec.rb11
-rw-r--r--spec/requests/api/container_repositories_spec.rb88
-rw-r--r--spec/requests/api/dependency_proxy_spec.rb72
-rw-r--r--spec/requests/api/feature_flags_user_lists_spec.rb33
-rw-r--r--spec/requests/api/files_spec.rb70
-rw-r--r--spec/requests/api/generic_packages_spec.rb4
-rw-r--r--spec/requests/api/graphql/ci/jobs_spec.rb28
-rw-r--r--spec/requests/api/graphql/ci/pipelines_spec.rb221
-rw-r--r--spec/requests/api/graphql/container_repository/container_repository_details_spec.rb108
-rw-r--r--spec/requests/api/graphql/custom_emoji_query_spec.rb37
-rw-r--r--spec/requests/api/graphql/group/container_repositories_spec.rb146
-rw-r--r--spec/requests/api/graphql/instance_statistics_measurements_spec.rb13
-rw-r--r--spec/requests/api/graphql/issue/issue_spec.rb24
-rw-r--r--spec/requests/api/graphql/metrics/dashboard/annotations_spec.rb1
-rw-r--r--spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb67
-rw-r--r--spec/requests/api/graphql/mutations/alert_management/http_integration/destroy_spec.rb55
-rw-r--r--spec/requests/api/graphql/mutations/alert_management/http_integration/reset_token_spec.rb45
-rw-r--r--spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb49
-rw-r--r--spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb67
-rw-r--r--spec/requests/api/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb59
-rw-r--r--spec/requests/api/graphql/mutations/alert_management/prometheus_integration/update_spec.rb47
-rw-r--r--spec/requests/api/graphql/mutations/commits/create_spec.rb38
-rw-r--r--spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb25
-rw-r--r--spec/requests/api/graphql/mutations/container_repository/destroy_spec.rb91
-rw-r--r--spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb43
-rw-r--r--spec/requests/api/graphql/mutations/labels/create_spec.rb86
-rw-r--r--spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb49
-rw-r--r--spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb81
-rw-r--r--spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb8
-rw-r--r--spec/requests/api/graphql/mutations/releases/create_spec.rb375
-rw-r--r--spec/requests/api/graphql/mutations/snippets/destroy_spec.rb5
-rw-r--r--spec/requests/api/graphql/mutations/todos/create_spec.rb38
-rw-r--r--spec/requests/api/graphql/mutations/todos/restore_many_spec.rb70
-rw-r--r--spec/requests/api/graphql/namespace/root_storage_statistics_spec.rb8
-rw-r--r--spec/requests/api/graphql/project/alert_management/integrations_spec.rb83
-rw-r--r--spec/requests/api/graphql/project/container_repositories_spec.rb145
-rw-r--r--spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb12
-rw-r--r--spec/requests/api/graphql/project/grafana_integration_spec.rb1
-rw-r--r--spec/requests/api/graphql/project/issue/design_collection/version_spec.rb1
-rw-r--r--spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb3
-rw-r--r--spec/requests/api/graphql/project/issue/designs/notes_spec.rb4
-rw-r--r--spec/requests/api/graphql/project/issues_spec.rb45
-rw-r--r--spec/requests/api/graphql/project/jira_import_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/merge_requests_spec.rb11
-rw-r--r--spec/requests/api/graphql/project/project_statistics_spec.rb8
-rw-r--r--spec/requests/api/graphql/project/release_spec.rb22
-rw-r--r--spec/requests/api/graphql/project/releases_spec.rb92
-rw-r--r--spec/requests/api/graphql/project/terraform/states_spec.rb81
-rw-r--r--spec/requests/api/graphql/read_only_spec.rb50
-rw-r--r--spec/requests/api/graphql/terraform/state/delete_spec.rb23
-rw-r--r--spec/requests/api/graphql/terraform/state/lock_spec.rb25
-rw-r--r--spec/requests/api/graphql/terraform/state/unlock_spec.rb24
-rw-r--r--spec/requests/api/graphql/user/group_member_query_spec.rb1
-rw-r--r--spec/requests/api/graphql/user/project_member_query_spec.rb1
-rw-r--r--spec/requests/api/graphql/user_query_spec.rb14
-rw-r--r--spec/requests/api/graphql_spec.rb2
-rw-r--r--spec/requests/api/group_labels_spec.rb129
-rw-r--r--spec/requests/api/import_github_spec.rb16
-rw-r--r--spec/requests/api/internal/base_spec.rb28
-rw-r--r--spec/requests/api/internal/pages_spec.rb50
-rw-r--r--spec/requests/api/invitations_spec.rb301
-rw-r--r--spec/requests/api/issues/get_project_issues_spec.rb2
-rw-r--r--spec/requests/api/issues/issues_spec.rb2
-rw-r--r--spec/requests/api/issues/post_projects_issues_spec.rb2
-rw-r--r--spec/requests/api/labels_spec.rb60
-rw-r--r--spec/requests/api/lint_spec.rb210
-rw-r--r--spec/requests/api/maven_packages_spec.rb42
-rw-r--r--spec/requests/api/members_spec.rb2
-rw-r--r--spec/requests/api/merge_requests_spec.rb88
-rw-r--r--spec/requests/api/npm_instance_packages_spec.rb31
-rw-r--r--spec/requests/api/npm_packages_spec.rb556
-rw-r--r--spec/requests/api/npm_project_packages_spec.rb281
-rw-r--r--spec/requests/api/personal_access_tokens_spec.rb112
-rw-r--r--spec/requests/api/project_container_repositories_spec.rb6
-rw-r--r--spec/requests/api/project_export_spec.rb2
-rw-r--r--spec/requests/api/project_hooks_spec.rb6
-rw-r--r--spec/requests/api/projects_spec.rb5
-rw-r--r--spec/requests/api/release/links_spec.rb2
-rw-r--r--spec/requests/api/releases_spec.rb27
-rw-r--r--spec/requests/api/search_spec.rb63
-rw-r--r--spec/requests/api/settings_spec.rb45
-rw-r--r--spec/requests/api/terraform/state_spec.rb14
-rw-r--r--spec/requests/api/users_spec.rb222
-rw-r--r--spec/requests/git_http_spec.rb22
-rw-r--r--spec/requests/lfs_http_spec.rb428
-rw-r--r--spec/requests/lfs_locks_api_spec.rb61
-rw-r--r--spec/requests/projects/metrics/dashboards/builder_spec.rb1
-rw-r--r--spec/requests/projects/noteable_notes_spec.rb40
-rw-r--r--spec/requests/projects/releases_controller_spec.rb60
-rw-r--r--spec/requests/rack_attack_global_spec.rb61
-rw-r--r--spec/requests/robots_txt_spec.rb93
-rw-r--r--spec/requests/search_controller_spec.rb82
-rw-r--r--spec/requests/user_sends_malformed_strings_spec.rb28
-rw-r--r--spec/requests/user_sends_null_bytes_spec.rb14
-rw-r--r--spec/requests/whats_new_controller_spec.rb39
-rw-r--r--spec/routing/group_routing_spec.rb36
-rw-r--r--spec/routing/openid_connect_spec.rb5
-rw-r--r--spec/routing/routing_spec.rb7
-rw-r--r--spec/rubocop/cop/code_reuse/active_record_spec.rb134
-rw-r--r--spec/rubocop/cop/graphql/resolver_type_spec.rb74
-rw-r--r--spec/rubocop/cop/line_break_around_conditional_block_spec.rb454
-rw-r--r--spec/rubocop/cop/rspec/be_success_matcher_spec.rb2
-rw-r--r--spec/serializers/base_discussion_entity_spec.rb69
-rw-r--r--spec/serializers/diff_file_entity_spec.rb11
-rw-r--r--spec/serializers/diffs_entity_spec.rb50
-rw-r--r--spec/serializers/discussion_entity_spec.rb4
-rw-r--r--spec/serializers/environment_entity_spec.rb2
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb27
-rw-r--r--spec/serializers/move_to_project_entity_spec.rb6
-rw-r--r--spec/serializers/paginated_diff_entity_spec.rb46
-rw-r--r--spec/serializers/test_case_entity_spec.rb13
-rw-r--r--spec/serializers/test_suite_comparer_entity_spec.rb104
-rw-r--r--spec/services/admin/propagate_integration_service_spec.rb15
-rw-r--r--spec/services/alert_management/create_alert_issue_service_spec.rb1
-rw-r--r--spec/services/alert_management/http_integrations/create_service_spec.rb66
-rw-r--r--spec/services/alert_management/http_integrations/destroy_service_spec.rb63
-rw-r--r--spec/services/alert_management/http_integrations/update_service_spec.rb77
-rw-r--r--spec/services/alert_management/process_prometheus_alert_service_spec.rb56
-rw-r--r--spec/services/alert_management/sync_alert_service_data_service_spec.rb55
-rw-r--r--spec/services/application_settings/update_service_spec.rb10
-rw-r--r--spec/services/audit_event_service_spec.rb35
-rw-r--r--spec/services/auth/container_registry_authentication_service_spec.rb131
-rw-r--r--spec/services/auto_merge/base_service_spec.rb2
-rw-r--r--spec/services/auto_merge_service_spec.rb2
-rw-r--r--spec/services/bulk_create_integration_service_spec.rb94
-rw-r--r--spec/services/bulk_import_service_spec.rb52
-rw-r--r--spec/services/bulk_update_integration_service_spec.rb74
-rw-r--r--spec/services/ci/append_build_trace_service_spec.rb57
-rw-r--r--spec/services/ci/build_report_result_service_spec.rb12
-rw-r--r--spec/services/ci/compare_test_reports_service_spec.rb51
-rw-r--r--spec/services/ci/create_downstream_pipeline_service_spec.rb35
-rw-r--r--spec/services/ci/create_pipeline_service/cache_spec.rb4
-rw-r--r--spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb4
-rw-r--r--spec/services/ci/create_pipeline_service/custom_config_content_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/dry_run_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/needs_spec.rb5
-rw-r--r--spec/services/ci/create_pipeline_service/parameter_content_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb34
-rw-r--r--spec/services/ci/create_pipeline_service/pre_post_stages_spec.rb4
-rw-r--r--spec/services/ci/create_pipeline_service/rules_spec.rb4
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb227
-rw-r--r--spec/services/ci/daily_build_group_report_result_service_spec.rb27
-rw-r--r--spec/services/ci/destroy_expired_job_artifacts_service_spec.rb115
-rw-r--r--spec/services/ci/list_config_variables_service_spec.rb39
-rw-r--r--spec/services/ci/test_cases_service_spec.rb94
-rw-r--r--spec/services/clusters/applications/check_installation_progress_service_spec.rb6
-rw-r--r--spec/services/clusters/applications/uninstall_service_spec.rb6
-rw-r--r--spec/services/clusters/aws/authorize_role_service_spec.rb6
-rw-r--r--spec/services/clusters/aws/fetch_credentials_service_spec.rb13
-rw-r--r--spec/services/clusters/kubernetes/create_or_update_namespace_service_spec.rb1
-rw-r--r--spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb71
-rw-r--r--spec/services/clusters/update_service_spec.rb4
-rw-r--r--spec/services/container_expiration_policies/cleanup_service_spec.rb62
-rw-r--r--spec/services/container_expiration_policy_service_spec.rb15
-rw-r--r--spec/services/dependency_proxy/download_blob_service_spec.rb44
-rw-r--r--spec/services/dependency_proxy/find_or_create_blob_service_spec.rb53
-rw-r--r--spec/services/dependency_proxy/pull_manifest_service_spec.rb44
-rw-r--r--spec/services/dependency_proxy/request_token_service_spec.rb52
-rw-r--r--spec/services/deploy_keys/collect_keys_service_spec.rb58
-rw-r--r--spec/services/design_management/copy_design_collection/copy_service_spec.rb37
-rw-r--r--spec/services/design_management/generate_image_versions_service_spec.rb2
-rw-r--r--spec/services/discussions/resolve_service_spec.rb4
-rw-r--r--spec/services/draft_notes/destroy_service_spec.rb4
-rw-r--r--spec/services/emails/confirm_service_spec.rb2
-rw-r--r--spec/services/feature_flags/update_service_spec.rb7
-rw-r--r--spec/services/groups/destroy_service_spec.rb2
-rw-r--r--spec/services/groups/import_export/import_service_spec.rb6
-rw-r--r--spec/services/issuable/common_system_notes_service_spec.rb8
-rw-r--r--spec/services/issues/import_csv_service_spec.rb103
-rw-r--r--spec/services/issues/move_service_spec.rb35
-rw-r--r--spec/services/issues/related_branches_service_spec.rb12
-rw-r--r--spec/services/issues/zoom_link_service_spec.rb22
-rw-r--r--spec/services/jira_connect/sync_service_spec.rb3
-rw-r--r--spec/services/jira_connect_subscriptions/create_service_spec.rb30
-rw-r--r--spec/services/jira_import/cloud_users_mapper_service_spec.rb35
-rw-r--r--spec/services/jira_import/server_users_mapper_service_spec.rb35
-rw-r--r--spec/services/jira_import/users_importer_spec.rb34
-rw-r--r--spec/services/labels/promote_service_spec.rb206
-rw-r--r--spec/services/labels/transfer_service_spec.rb7
-rw-r--r--spec/services/members/invite_service_spec.rb66
-rw-r--r--spec/services/merge_requests/add_context_service_spec.rb16
-rw-r--r--spec/services/merge_requests/cleanup_refs_service_spec.rb56
-rw-r--r--spec/services/merge_requests/refresh_service_spec.rb12
-rw-r--r--spec/services/merge_requests/reopen_service_spec.rb10
-rw-r--r--spec/services/metrics/dashboard/panel_preview_service_spec.rb1
-rw-r--r--spec/services/notes/create_service_spec.rb253
-rw-r--r--spec/services/notes/destroy_service_spec.rb55
-rw-r--r--spec/services/notes/update_service_spec.rb28
-rw-r--r--spec/services/notification_recipients/build_service_spec.rb4
-rw-r--r--spec/services/notification_service_spec.rb138
-rw-r--r--spec/services/packages/composer/version_parser_service_spec.rb2
-rw-r--r--spec/services/packages/conan/create_package_file_service_spec.rb2
-rw-r--r--spec/services/packages/create_event_service_spec.rb78
-rw-r--r--spec/services/packages/create_package_file_service_spec.rb19
-rw-r--r--spec/services/packages/debian/extract_deb_metadata_service_spec.rb37
-rw-r--r--spec/services/packages/debian/parse_debian822_service_spec.rb148
-rw-r--r--spec/services/packages/generic/create_package_file_service_spec.rb6
-rw-r--r--spec/services/packages/generic/find_or_create_package_service_spec.rb10
-rw-r--r--spec/services/packages/maven/create_package_service_spec.rb2
-rw-r--r--spec/services/packages/maven/find_or_create_package_service_spec.rb17
-rw-r--r--spec/services/packages/npm/create_package_service_spec.rb11
-rw-r--r--spec/services/pages/destroy_deployments_service_spec.rb29
-rw-r--r--spec/services/personal_access_tokens/create_service_spec.rb66
-rw-r--r--spec/services/personal_access_tokens/revoke_service_spec.rb20
-rw-r--r--spec/services/post_receive_service_spec.rb43
-rw-r--r--spec/services/projects/alerting/notify_service_spec.rb30
-rw-r--r--spec/services/projects/autocomplete_service_spec.rb28
-rw-r--r--spec/services/projects/cleanup_service_spec.rb87
-rw-r--r--spec/services/projects/container_repository/delete_tags_service_spec.rb18
-rw-r--r--spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb2
-rw-r--r--spec/services/projects/create_service_spec.rb35
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_service_spec.rb12
-rw-r--r--spec/services/projects/update_pages_service_spec.rb59
-rw-r--r--spec/services/projects/update_repository_storage_service_spec.rb18
-rw-r--r--spec/services/projects/update_service_spec.rb50
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb32
-rw-r--r--spec/services/releases/create_service_spec.rb6
-rw-r--r--spec/services/releases/update_service_spec.rb6
-rw-r--r--spec/services/reset_project_cache_service_spec.rb2
-rw-r--r--spec/services/resource_access_tokens/create_service_spec.rb70
-rw-r--r--spec/services/resource_events/change_milestone_service_spec.rb2
-rw-r--r--spec/services/search/snippet_service_spec.rb22
-rw-r--r--spec/services/search_service_spec.rb37
-rw-r--r--spec/services/snippets/create_service_spec.rb6
-rw-r--r--spec/services/snippets/update_service_spec.rb6
-rw-r--r--spec/services/system_hooks_service_spec.rb2
-rw-r--r--spec/services/system_note_service_spec.rb16
-rw-r--r--spec/services/system_notes/issuables_service_spec.rb8
-rw-r--r--spec/services/system_notes/merge_requests_service_spec.rb20
-rw-r--r--spec/services/test_hooks/project_service_spec.rb18
-rw-r--r--spec/services/todo_service_spec.rb50
-rw-r--r--spec/services/todos/destroy/confidential_issue_service_spec.rb2
-rw-r--r--spec/services/two_factor/destroy_service_spec.rb2
-rw-r--r--spec/services/users/approve_service_spec.rb118
-rw-r--r--spec/services/users/destroy_service_spec.rb88
-rw-r--r--spec/services/users/repair_ldap_blocked_service_spec.rb2
-rw-r--r--spec/services/users/set_status_service_spec.rb25
-rw-r--r--spec/services/verify_pages_domain_service_spec.rb2
-rw-r--r--spec/services/web_hook_service_spec.rb1
-rw-r--r--spec/sidekiq/cron/job_gem_dependency_spec.rb2
-rw-r--r--spec/spec_helper.rb18
-rw-r--r--spec/support/cycle_analytics_helpers/test_generation.rb6
-rw-r--r--spec/support/helpers/admin_mode_helpers.rb2
-rw-r--r--spec/support/helpers/api_helpers.rb1
-rw-r--r--spec/support/helpers/dependency_proxy_helpers.rb33
-rw-r--r--spec/support/helpers/features/members_table_helpers.rb37
-rw-r--r--spec/support/helpers/features/releases_helpers.rb4
-rw-r--r--spec/support/helpers/features/web_ide_spec_helpers.rb41
-rw-r--r--spec/support/helpers/graphql_helpers.rb25
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb21
-rw-r--r--spec/support/helpers/lfs_http_helpers.rb12
-rw-r--r--spec/support/helpers/navbar_structure_helper.rb8
-rw-r--r--spec/support/helpers/require_migration.rb24
-rw-r--r--spec/support/helpers/search_helpers.rb3
-rw-r--r--spec/support/helpers/snowplow_helpers.rb14
-rw-r--r--spec/support/helpers/table_schema_helpers.rb112
-rw-r--r--spec/support/helpers/test_env.rb16
-rw-r--r--spec/support/helpers/usage_data_helpers.rb1
-rw-r--r--spec/support/helpers/user_login_helper.rb23
-rw-r--r--spec/support/helpers/wiki_helpers.rb1
-rw-r--r--spec/support/import_export/common_util.rb2
-rw-r--r--spec/support/matchers/graphql_matchers.rb77
-rw-r--r--spec/support/patches/rspec_mocks_prepended_methods.rb55
-rw-r--r--spec/support/rspec.rb7
-rw-r--r--spec/support/services/issuable_import_csv_service_shared_examples.rb142
-rw-r--r--spec/support/shared_contexts/design_management_shared_contexts.rb2
-rw-r--r--spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb20
-rw-r--r--spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb3
-rw-r--r--spec/support/shared_contexts/lib/gitlab/middleware/with_a_mocked_gitlab_instance_shared_context.rb32
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb2
-rw-r--r--spec/support/shared_contexts/policies/project_policy_table_shared_context.rb903
-rw-r--r--spec/support/shared_contexts/requests/api/graphql/jira_import/jira_projects_context.rb1
-rw-r--r--spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb22
-rw-r--r--spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/cached_response_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/controllers/access_tokens_controller_shared_examples.rb18
-rw-r--r--spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb29
-rw-r--r--spec/support/shared_examples/controllers/trackable_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/features/discussion_comments_shared_example.rb12
-rw-r--r--spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb6
-rw-r--r--spec/support/shared_examples/features/variable_list_shared_examples.rb430
-rw-r--r--spec/support/shared_examples/features/wiki/user_deletes_wiki_page_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/finders/security/jobs_finder_shared_examples.rb87
-rw-r--r--spec/support/shared_examples/graphql/label_fields.rb4
-rw-r--r--spec/support/shared_examples/graphql/mutations/boards_create_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/graphql/mutations/create_todo_shared_examples.rb26
-rw-r--r--spec/support/shared_examples/graphql/mutations/issues/permission_check_shared_examples.rb52
-rw-r--r--spec/support/shared_examples/graphql/mutations/merge_requests/permission_check_shared_examples.rb73
-rw-r--r--spec/support/shared_examples/helm_commands_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/lib/gitlab/database/background_migration_job_shared_examples.rb23
-rw-r--r--spec/support/shared_examples/lib/gitlab/database/postgres_model_shared_examples.rb35
-rw-r--r--spec/support/shared_examples/lib/gitlab/middleware/read_only_gitlab_instance_shared_examples.rb189
-rw-r--r--spec/support/shared_examples/lib/gitlab/repository_size_checker_shared_examples.rb59
-rw-r--r--spec/support/shared_examples/lib/gitlab/search_confidential_filter_shared_examples.rb57
-rw-r--r--spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb139
-rw-r--r--spec/support/shared_examples/lib/gitlab/usage_data_counters/issue_activity_shared_examples.rb35
-rw-r--r--spec/support/shared_examples/mailers/notify_shared_examples.rb9
-rw-r--r--spec/support/shared_examples/models/application_setting_shared_examples.rb56
-rw-r--r--spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb20
-rw-r--r--spec/support/shared_examples/models/cluster_application_core_shared_examples.rb17
-rw-r--r--spec/support/shared_examples/models/cluster_application_helm_cert_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/read_only_message_shared_examples.rb17
-rw-r--r--spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/discussions_shared_examples.rb17
-rw-r--r--spec/support/shared_examples/requests/api/graphql/read_only_instance_shared_examples.rb47
-rw-r--r--spec/support/shared_examples/requests/api/labels_api_shared_examples.rb14
-rw-r--r--spec/support/shared_examples/requests/api/multiple_and_scoped_issue_boards_shared_examples.rb94
-rw-r--r--spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb270
-rw-r--r--spec/support/shared_examples/requests/api/packages_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/requests/api/packages_tags_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/requests/api/tracking_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/requests/lfs_http_shared_examples.rb224
-rw-r--r--spec/support/shared_examples/requests/rack_attack_shared_examples.rb37
-rw-r--r--spec/support/shared_examples/serializers/note_entity_shared_examples.rb50
-rw-r--r--spec/support/shared_examples/services/alert_management_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/services/common_system_notes_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/services/jira_import/user_mapper_services_shared_examples.rb22
-rw-r--r--spec/support/shared_examples/services/packages_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/services/pages_size_limit_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/uploaders/workers/object_storage/migrate_uploads_shared_examples.rb120
-rw-r--r--spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb38
-rw-r--r--spec/support/snowplow.rb8
-rw-r--r--spec/tasks/gitlab/gitaly_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/packages/events_rake_spec.rb38
-rw-r--r--spec/tooling/lib/tooling/crystalball/coverage_lines_execution_detector_spec.rb42
-rw-r--r--spec/tooling/lib/tooling/crystalball/coverage_lines_strategy_spec.rb16
-rw-r--r--spec/tooling/lib/tooling/test_file_finder_spec.rb8
-rw-r--r--spec/tooling/lib/tooling/test_map_generator_spec.rb109
-rw-r--r--spec/tooling/lib/tooling/test_map_packer_spec.rb77
-rw-r--r--spec/uploaders/dependency_proxy/file_uploader_spec.rb26
-rw-r--r--spec/uploaders/gitlab_uploader_spec.rb18
-rw-r--r--spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb114
-rw-r--r--spec/validators/rsa_key_validator_spec.rb40
-rw-r--r--spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb16
-rw-r--r--spec/views/profiles/preferences/show.html.haml_spec.rb57
-rw-r--r--spec/views/projects/ci/lints/show.html.haml_spec.rb127
-rw-r--r--spec/views/projects/merge_requests/show.html.haml_spec.rb2
-rw-r--r--spec/views/projects/settings/operations/show.html.haml_spec.rb2
-rw-r--r--spec/views/projects/tags/index.html.haml_spec.rb25
-rw-r--r--spec/views/registrations/welcome.html.haml_spec.rb26
-rw-r--r--spec/views/registrations/welcome/show.html.haml_spec.rb26
-rw-r--r--spec/views/search/_filter.html.haml_spec.rb2
-rw-r--r--spec/views/search/_results.html.haml_spec.rb36
-rw-r--r--spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb2
-rw-r--r--spec/workers/background_migration_worker_spec.rb100
-rw-r--r--spec/workers/build_finished_worker_spec.rb42
-rw-r--r--spec/workers/bulk_import_worker_spec.rb16
-rw-r--r--spec/workers/ci/delete_objects_worker_spec.rb20
-rw-r--r--spec/workers/concerns/application_worker_spec.rb4
-rw-r--r--spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb2
-rw-r--r--spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb2
-rw-r--r--spec/workers/concerns/limited_capacity/worker_spec.rb3
-rw-r--r--spec/workers/concerns/reenqueuer_spec.rb15
-rw-r--r--spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb234
-rw-r--r--spec/workers/container_expiration_policy_worker_spec.rb160
-rw-r--r--spec/workers/destroy_pages_deployments_worker_spec.rb38
-rw-r--r--spec/workers/git_garbage_collect_worker_spec.rb14
-rw-r--r--spec/workers/jira_connect/sync_branch_worker_spec.rb33
-rw-r--r--spec/workers/jira_connect/sync_merge_request_worker_spec.rb33
-rw-r--r--spec/workers/jira_connect/sync_project_worker_spec.rb77
-rw-r--r--spec/workers/propagate_integration_inherit_descendant_worker_spec.rb30
-rw-r--r--spec/workers/propagate_integration_inherit_worker_spec.rb2
-rw-r--r--spec/workers/purge_dependency_proxy_cache_worker_spec.rb58
-rw-r--r--spec/workers/remove_expired_members_worker_spec.rb44
-rw-r--r--spec/workers/repository_cleanup_worker_spec.rb10
-rw-r--r--spec/workers/schedule_merge_request_cleanup_refs_worker_spec.rb39
-rw-r--r--tooling/README.md4
-rw-r--r--tooling/eslint-config/conditionally_ignore_ee.js5
-rw-r--r--tooling/lib/tooling/crystalball/coverage_lines_execution_detector.rb44
-rw-r--r--tooling/lib/tooling/crystalball/coverage_lines_strategy.rb23
-rw-r--r--tooling/lib/tooling/helm3_client.rb3
-rw-r--r--tooling/lib/tooling/test_map_generator.rb36
-rw-r--r--tooling/lib/tooling/test_map_packer.rb58
-rw-r--r--tooling/overcommit/Gemfile2
-rw-r--r--tooling/overcommit/Gemfile.lock63
-rw-r--r--vendor/assets/javascripts/snowplow/sp.js176
-rw-r--r--[-rwxr-xr-x]vendor/gitignore/C++.gitignore0
-rw-r--r--[-rwxr-xr-x]vendor/gitignore/Java.gitignore0
-rw-r--r--yarn.lock272
5871 files changed, 250083 insertions, 63268 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml
index b8683ba803f..48294e00844 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -3,6 +3,7 @@ extends:
- plugin:@gitlab/i18n
- plugin:no-jquery/slim
- plugin:no-jquery/deprecated-3.4
+ - ./tooling/eslint-config/conditionally_ignore_ee.js
globals:
__webpack_public_path__: true
gl: false
@@ -25,9 +26,6 @@ rules:
- _links
import/no-unresolved:
- error
- - ignore:
- # https://gitlab.com/gitlab-org/gitlab/issues/38226
- - '^ee_component/'
# Disabled for now, to make the airbnb-base 12.1.0 -> 13.1.0 update smoother
no-else-return:
- error
diff --git a/.gitattributes b/.gitattributes
index ec47d175c55..8d21784ed11 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,3 +1,4 @@
VERSION merge=ours
Dangerfile gitlab-language=ruby
*.pdf filter=lfs diff=lfs merge=lfs -text
+*.rb diff=ruby
diff --git a/.gitignore b/.gitignore
index 25c42cdb56d..30cb231e83f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,12 +56,15 @@ eslint-report.html
/doc/code/*
/dump.rdb
/jsconfig.json
+/lefthook-local.yml
/log/*.log*
/node_modules
/nohup.out
/public/assets/
/public/uploads.*
/public/uploads/
+/public/sitemap.xml
+/public/sitemap.xml.gz
/shared/artifacts/
/spec/examples.txt
/rails_best_practices_output.html
@@ -73,6 +76,7 @@ eslint-report.html
/.gitlab_pages_secret
/.gitlab_kas_secret
/webpack-report/
+/crystalball/
/knapsack/
/rspec_flaky/
/locale/**/LC_MESSAGES
@@ -97,3 +101,5 @@ apollo.config.js
/tmp/matching_tests.txt
ee/changelogs/unreleased-ee
/sitespeed-result
+tags.lock
+tags.temp
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f9c9c5888db..4ea5ad1b401 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -17,7 +17,7 @@ stages:
# in cases where jobs require Docker-in-Docker, the job
# definition must be extended with `.use-docker-in-docker`
default:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.6.6-golang-1.14-git-2.28-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-golang-1.14-git-2.29-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
tags:
- gitlab-org
# All jobs are interruptible by default
@@ -59,10 +59,13 @@ variables:
GET_SOURCES_ATTEMPTS: "3"
KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/report-master.json
FLAKY_RSPEC_SUITE_REPORT_PATH: rspec_flaky/report-suite.json
+ RSPEC_TESTS_MAPPING_PATH: crystalball/mapping.json
+ RSPEC_PACKED_TESTS_MAPPING_PATH: crystalball/packed-mapping.json
BUILD_ASSETS_IMAGE: "false"
ES_JAVA_OPTS: "-Xms256m -Xmx256m"
ELASTIC_URL: "http://elastic:changeme@elasticsearch:9200"
DOCKER_VERSION: "19.03.0"
+ CACHE_CLASSES: "true"
# Preparing custom clone path to reduce space used by all random forks
# on GitLab.com's Shared Runners. Our main forks - especially the security
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 5187ac01b58..a24fef5e44d 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -207,6 +207,35 @@ Dangerfile @gl-quality/eng-prod
/ee/lib/gitlab/ci/reports/license_scanning/ @gitlab-org/secure/composition-analysis-be
/ee/lib/gitlab/ci/reports/security/ @gitlab-org/secure/composition-analysis-be @gitlab-org/secure/dynamic-analysis-be @gitlab-org/secure/static-analysis-be @gitlab-org/secure/fuzzing-be
+[Container Security]
+/ee/app/views/projects/threat_monitoring/** @gitlab-org/threat-management/defend/container-security/frontend
+/ee/app/assets/javascripts/pages/projects/threat_monitoring/** @gitlab-org/threat-management/defend/container-security/frontend
+/ee/app/assets/javascripts/threat_monitoring/** @gitlab-org/threat-management/defend/container-security/frontend
+/ee/spec/frontend/threat_monitoring/** @gitlab-org/threat-management/defend/container-security/frontend
+
+/ee/app/controllers/projects/threat_monitoring_controller.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/controllers/projects/threat_monitoring_controller_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/lib/gitlab/kubernetes/cilium_network_policy.rb @gitlab-org/threat-management/defend/container-security/backend
+/spec/lib/gitlab/kubernetes/cilium_network_policy_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/lib/gitlab/kubernetes/network_policy_common.rb @gitlab-org/threat-management/defend/container-security/backend
+/spec/support/shared_examples/lib/gitlab/kubernetes/network_policy_common_shared_examples.rb @gitlab-org/threat-management/defend/container-security/backend
+/lib/gitlab/kubernetes/network_policy.rb @gitlab-org/threat-management/defend/container-security/backend
+/spec/lib/gitlab/kubernetes/network_policy_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/app/services/network_policies/** @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/services/network_policies/** @gitlab-org/threat-management/defend/container-security/backend
+/ee/app/controllers/projects/security/waf_anomalies_controller.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/controllers/projects/security/waf_anomalies_controller_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/app/models/clusters/applications/cilium.rb @gitlab-org/threat-management/defend/container-security/backend
+/spec/models/clusters/applications/cilium_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/app/controllers/projects/security/network_policies_controller.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/controllers/projects/security/network_policies_controller_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/app/workers/network_policy_metrics_worker.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/workers/network_policy_metrics_worker_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/app/services/network_policies/** @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/services/network_policies/** @gitlab-org/threat-management/defend/container-security/backend
+/ee/lib/gitlab/usage_data_counters/network_policy_counter.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/lib/gitlab/usage_data_counters/network_policy_counter_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+
[Code Owners]
/ee/lib/gitlab/code_owners.rb @reprazent @kerrizor @garyh
/ee/lib/gitlab/code_owners/ @reprazent @kerrizor @garyh
diff --git a/.gitlab/ci/cache-repo.gitlab-ci.yml b/.gitlab/ci/cache-repo.gitlab-ci.yml
index a091785dec3..18e1ca1644d 100644
--- a/.gitlab/ci/cache-repo.gitlab-ci.yml
+++ b/.gitlab/ci/cache-repo.gitlab-ci.yml
@@ -23,14 +23,36 @@ cache-repo:
stage: sync
variables:
GIT_STRATEGY: none
- TAR_FILENAME: /tmp/gitlab-master.tar
+ SHALLOW_CLONE_TAR_FILENAME: gitlab-master-shallow.tar
+ FULL_CLONE_TAR_FILENAME: gitlab-master.tar
+ before_script:
+ - '[ -z "$CI_REPO_CACHE_CREDENTIALS" ] || gcloud auth activate-service-account --key-file=$CI_REPO_CACHE_CREDENTIALS'
script:
- - cd ..
- - rm -rf $CI_PROJECT_NAME
- - git clone --progress $CI_REPOSITORY_URL $CI_PROJECT_NAME
- - cd $CI_PROJECT_NAME
- - gcloud auth activate-service-account --key-file=$CI_REPO_CACHE_CREDENTIALS
- - git remote rm origin
- - tar cf $TAR_FILENAME .
- - gzip $TAR_FILENAME
- - gsutil cp $TAR_FILENAME.gz gs://gitlab-ci-git-repo-cache/project-$CI_PROJECT_ID/gitlab-master.tar.gz
+ # Enable shallow repo caching only if the $ENABLE_SHALLOW_REPO_CACHING variable exists
+ - if [ -n "$ENABLE_SHALLOW_REPO_CACHING" ]; then
+ cd .. && rm -rf $CI_PROJECT_NAME;
+ today=$(date +%Y-%m-%d);
+ year=$(date +%Y);
+ last_year=`expr $year - 1`;
+ one_year_ago=$(echo $today | sed "s/$year/$last_year/");
+ echo "Cloning $CI_REPOSITORY_URL into $CI_PROJECT_NAME with commits from $one_year_ago.";
+ time git clone --progress --no-checkout --shallow-since=$one_year_ago $CI_REPOSITORY_URL $CI_PROJECT_NAME;
+ cd $CI_PROJECT_NAME;
+ echo "Archiving $CI_PROJECT_NAME into /tmp/$SHALLOW_CLONE_TAR_FILENAME.";
+ time tar cf /tmp/$SHALLOW_CLONE_TAR_FILENAME .;
+ echo "GZipping /tmp/$SHALLOW_CLONE_TAR_FILENAME.";
+ time gzip /tmp/$SHALLOW_CLONE_TAR_FILENAME;
+ [ -z "$CI_REPO_CACHE_CREDENTIALS" ] || (echo "Uploading /tmp/$SHALLOW_CLONE_TAR_FILENAME.gz to GCloud." && time gsutil cp /tmp/$SHALLOW_CLONE_TAR_FILENAME.gz gs://gitlab-ci-git-repo-cache/project-$CI_PROJECT_ID/$SHALLOW_CLONE_TAR_FILENAME.gz);
+ fi
+ # By default, we want to cache the full repo, unless the $DISABLE_FULL_REPO_CACHING variable exists (in the case the shallow clone caching is working well)
+ - if [ -z "$DISABLE_FULL_REPO_CACHING" ]; then
+ cd .. && rm -rf $CI_PROJECT_NAME;
+ echo "Cloning $CI_REPOSITORY_URL into $CI_PROJECT_NAME.";
+ time git clone --progress $CI_REPOSITORY_URL $CI_PROJECT_NAME;
+ cd $CI_PROJECT_NAME;
+ echo "Archiving $CI_PROJECT_NAME into /tmp/$FULL_CLONE_TAR_FILENAME.";
+ time tar cf /tmp/$FULL_CLONE_TAR_FILENAME .;
+ echo "GZipping /tmp/$FULL_CLONE_TAR_FILENAME.";
+ time gzip /tmp/$FULL_CLONE_TAR_FILENAME;
+ [ -z "$CI_REPO_CACHE_CREDENTIALS" ] || (echo "Uploading /tmp/$FULL_CLONE_TAR_FILENAME.gz to GCloud." && time gsutil cp /tmp/$FULL_CLONE_TAR_FILENAME.gz gs://gitlab-ci-git-repo-cache/project-$CI_PROJECT_ID/$FULL_CLONE_TAR_FILENAME.gz);
+ fi
diff --git a/.gitlab/ci/cng.gitlab-ci.yml b/.gitlab/ci/cng.gitlab-ci.yml
index d7699de74e2..269996dfd09 100644
--- a/.gitlab/ci/cng.gitlab-ci.yml
+++ b/.gitlab/ci/cng.gitlab-ci.yml
@@ -1,6 +1,6 @@
cloud-native-image:
extends: .cng:rules
- image: ruby:2.6-alpine
+ image: ruby:2.7-alpine
dependencies: []
stage: post-test
variables:
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index 4b25908aa6a..b258eb73515 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -2,7 +2,7 @@
extends:
- .default-retry
- .docs:rules:review-docs
- image: ruby:2.6-alpine
+ image: ruby:2.7-alpine
stage: review
needs: []
variables:
@@ -38,15 +38,25 @@ review-docs-cleanup:
script:
- ./scripts/trigger-build docs cleanup
-docs lint:
+docs-lint markdown:
extends:
- .default-retry
- .docs:rules:docs-lint
- image: "registry.gitlab.com/gitlab-org/gitlab-docs/lint:ruby-2.7.2-alpine-3.12-vale-2.4.3-markdownlint-0.24.0"
+ # When updating the image version here, update it in /scripts/lint-doc.sh too.
+ image: "registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.12-vale-2.6.1-markdownlint-0.24.0"
stage: test
needs: []
script:
- scripts/lint-doc.sh
+
+docs-lint links:
+ extends:
+ - .default-retry
+ - .docs:rules:docs-lint
+ image: "registry.gitlab.com/gitlab-org/gitlab-docs/lint:ruby-2.7.2-alpine-3.12-vale-2.4.3-markdownlint-0.24.0"
+ stage: test
+ needs: []
+ script:
# Prepare docs for build
# The path must be 'ee/' because we have hardcoded links relying on it
# https://gitlab.com/gitlab-org/gitlab-docs/-/blob/887850752fc0e72856da6632db132f005ba77f16/content/index.erb#L44-63
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index e4c9f85cf62..0b921309ced 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -15,7 +15,7 @@
extends:
- .frontend-base
- .assets-compile-cache
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.6.6-git-2.28-lfs-2.9-node-12.18-yarn-1.22-graphicsmagick-1.3.34
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-git-2.29-lfs-2.9-node-12.18-yarn-1.22-graphicsmagick-1.3.34
variables:
WEBPACK_VENDOR_DLL: "true"
stage: prepare
@@ -97,32 +97,41 @@ update-yarn-cache:
- .rails-cache
- .use-pg11
stage: fixtures
- needs: ["setup-test-env", "compile-test-assets"]
+ needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets"]
variables:
SETUP_DB: "true"
WEBPACK_VENDOR_DLL: "true"
script:
+ - run_timed_command "gem install knapsack --no-document"
- run_timed_command "scripts/gitaly-test-build"
- run_timed_command "scripts/gitaly-test-spawn"
- - run_timed_command "bin/rake frontend:fixtures"
+ - source ./scripts/rspec_helpers.sh
+ - rspec_paralellized_job "--tag frontend_fixture"
artifacts:
name: frontend-fixtures
expire_in: 31d
when: always
paths:
- tmp/tests/frontend/
+ - knapsack/
-frontend-fixtures:
+rspec frontend_fixture:
extends:
- .frontend-fixtures-base
- .frontend:rules:default-frontend-jobs
-frontend-fixtures-as-if-foss:
+rspec frontend_fixture as-if-foss:
extends:
- .frontend-fixtures-base
- .frontend:rules:default-frontend-jobs-as-if-foss
- .as-if-foss
+rspec-ee frontend_fixture:
+ extends:
+ - .frontend-fixtures-base
+ - .frontend:rules:default-frontend-jobs
+ parallel: 2
+
.frontend-test-base:
extends:
- .frontend-base
@@ -152,7 +161,8 @@ karma:
extends:
- .karma-base
- .frontend:rules:default-frontend-jobs
- needs: ["frontend-fixtures"]
+ # Don't use `needs` since `rspec-ee frontend_fixture` doesn't exist in `gitlab-foss` pipelines.
+ dependencies: ["rspec frontend_fixture", "rspec-ee frontend_fixture"]
coverage: '/^Statements *: (\d+\.\d+%)/'
artifacts:
name: coverage-javascript
@@ -171,7 +181,7 @@ karma-as-if-foss:
- .karma-base
- .frontend:rules:default-frontend-jobs-as-if-foss
- .as-if-foss
- needs: ["frontend-fixtures-as-if-foss"]
+ needs: ["rspec frontend_fixture as-if-foss"]
.jest-base:
extends: .frontend-test-base
@@ -183,7 +193,8 @@ jest:
extends:
- .jest-base
- .frontend:rules:default-frontend-jobs
- needs: ["frontend-fixtures"]
+ # Don't use `needs` since `rspec-ee frontend_fixture` doesn't exist in `gitlab-foss` pipelines.
+ dependencies: ["rspec frontend_fixture", "rspec-ee frontend_fixture"]
artifacts:
name: coverage-frontend
expire_in: 31d
@@ -203,14 +214,15 @@ jest-integration:
script:
- *yarn-install
- run_timed_command "yarn jest:integration --ci"
- needs: ["frontend-fixtures"]
+ # Don't use `needs` since `rspec-ee frontend_fixture` doesn't exist in `gitlab-foss` pipelines.
+ dependencies: ["rspec frontend_fixture", "rspec-ee frontend_fixture"]
jest-as-if-foss:
extends:
- .jest-base
- .frontend:rules:default-frontend-jobs-as-if-foss
- .as-if-foss
- needs: ["frontend-fixtures-as-if-foss"]
+ needs: ["rspec frontend_fixture as-if-foss"]
parallel: 2
coverage-frontend:
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index fea3956bfe8..0fafd5869d9 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -18,7 +18,7 @@
.rails-cache:
cache:
- key: "rails-v2"
+ key: "rails-v3"
paths:
- vendor/ruby/
- vendor/gitaly-ruby/
@@ -27,7 +27,7 @@
.static-analysis-cache:
cache:
- key: "static-analysis-v1"
+ key: "static-analysis-v2"
paths:
- vendor/ruby/
- node_modules/
@@ -43,7 +43,7 @@
.qa-cache:
cache:
- key: "qa-v1"
+ key: "qa-v2"
paths:
- qa/vendor/ruby/
policy: pull
@@ -71,7 +71,7 @@
policy: pull
.use-pg11:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.6.6-golang-1.14-git-2.28-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-golang-1.14-git-2.29-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
services:
- name: postgres:11.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -80,7 +80,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.6.6-golang-1.14-git-2.28-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-12-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-golang-1.14-git-2.29-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-12-graphicsmagick-1.3.34"
services:
- name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -89,7 +89,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg11-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.6.6-golang-1.14-git-2.28-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-golang-1.14-git-2.29-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
services:
- name: postgres:11.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -100,7 +100,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.6.6-golang-1.14-git-2.28-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-12-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-golang-1.14-git-2.29-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-12-graphicsmagick-1.3.34"
services:
- name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index 96a8f093fea..1dc403c9d06 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -7,7 +7,7 @@
before_script:
- '[ "$FOSS_ONLY" = "1" ] && rm -rf ee/ qa/spec/ee/ qa/qa/specs/features/ee/ qa/qa/ee/ qa/qa/ee.rb'
- cd qa/
- - bundle install --clean --jobs=$(nproc) --path=vendor --retry=3 --quiet
+ - bundle install --clean --jobs=$(nproc) --path=vendor --retry=3 --without=development --quiet
- bundle check
qa:internal:
@@ -47,7 +47,7 @@ update-qa-cache:
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
.package-and-qa-base:
- image: ruby:2.6-alpine
+ image: ruby:2.7-alpine
stage: qa
retry: 0
script:
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index c4167ce7bcb..14b07dd4a2a 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -1,4 +1,4 @@
-######################
+#######################
# rspec job base specs
.rails-job-base:
extends:
@@ -20,6 +20,7 @@
variables:
RUBY_GC_MALLOC_LIMIT: 67108864
RUBY_GC_MALLOC_LIMIT_MAX: 134217728
+ CRYSTALBALL: "true"
needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets"]
script:
- *base-script
@@ -29,6 +30,7 @@
when: always
paths:
- coverage/
+ - crystalball/
- knapsack/
- rspec_flaky/
- rspec_profiling/
@@ -284,6 +286,9 @@ db:migrate-from-v12.10.0:
- '[[ -d "ee/" ]] || export TAG_TO_CHECKOUT="v12.10.0"'
- git fetch https://gitlab.com/gitlab-org/$PROJECT_TO_CHECKOUT.git $TAG_TO_CHECKOUT
- git checkout -f FETCH_HEAD
+ - sed -i -e "s/gem 'grpc', '~> 1.24.0'/gem 'grpc', '~> 1.30.2'/" Gemfile # Update gRPC for Ruby 2.7
+ - sed -i -e "s/gem 'google-protobuf', '~> 3.8.0'/gem 'google-protobuf', '~> 3.12.0'/" Gemfile
+ - gem install bundler:1.17.3
- bundle update google-protobuf grpc bootsnap
- bundle install $BUNDLE_INSTALL_FLAGS
- date
@@ -556,7 +561,7 @@ 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
+ - .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"]
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index 168f60f0f65..565ed93967c 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -15,7 +15,7 @@ code_quality:
stage: test
needs: []
variables:
- CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.10-gitlab.1"
+ CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.18"
script:
- |
if ! docker info &>/dev/null; then
@@ -152,6 +152,26 @@ dependency_scanning:
dependency_scanning: gl-dependency-scanning-report.json
expire_in: 1 week # GitLab-specific
+# The job below analysis dependencies for malicous behavior
+package_hunter:
+ extends:
+ - .reports:schedule-dast
+ stage: test
+ image:
+ name: registry.gitlab.com/gitlab-com/gl-security/security-research/package-hunter-cli:latest
+ entrypoint: [""]
+ needs: []
+ script:
+ - rm -r spec locale .git app/assets/images doc/
+ - cd .. && tar -I "gzip --best" -cf gitlab.tgz gitlab/
+ - DEBUG=* HTR_user=$PACKAGE_HUNTER_USER HTR_pass=$PACKAGE_HUNTER_PASS node /usr/src/app/cli.js analyze --format gitlab gitlab.tgz | tee $CI_PROJECT_DIR/gl-dependency-scanning-report.json
+ artifacts:
+ paths:
+ - gl-dependency-scanning-report.json # GitLab-specific
+ reports:
+ dependency_scanning: gl-dependency-scanning-report.json
+ expire_in: 1 week # GitLab-specific
+
license_scanning:
extends:
- .default-retry
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index 46a1a957692..d3069657e88 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -25,7 +25,7 @@ review-build-cng:
extends:
- .default-retry
- .review:rules:review-build-cng
- image: ruby:2.6-alpine
+ image: ruby:2.7-alpine
stage: review-prepare
before_script:
- source ./scripts/utils.sh
@@ -122,7 +122,7 @@ review-stop:
extends:
- .default-retry
- .use-docker-in-docker
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.6
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7
stage: qa
# This is needed so that manual jobs with needs don't block the pipeline.
# See https://gitlab.com/gitlab-org/gitlab/-/issues/199979.
@@ -199,7 +199,7 @@ review-performance:
parallel-spec-reports:
extends:
- .review:rules:mr-only-manual
- image: ruby:2.6-alpine
+ image: ruby:2.7-alpine
stage: post-qa
dependencies: ["review-qa-all"]
variables:
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 57d4a2a4cb7..7f469221da2 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -103,8 +103,11 @@
- ".gitlab/ci/build-images.gitlab-ci.yml"
- ".gitlab/ci/qa.gitlab-ci.yml"
-.yaml-patterns: &yaml-patterns
- - "**/*.yml"
+.yaml-lint-patterns: &yaml-lint-patterns
+ - ".gitlab-ci.yml"
+ - ".gitlab/ci/**/*.yml"
+ - "lib/gitlab/ci/templates/**/*.yml"
+ - "{,ee/}changelogs/**/*.yml"
.docs-patterns: &docs-patterns
- ".gitlab/route-map.yml"
@@ -142,8 +145,8 @@
- "{,ee/}{,spec/}lib/{,ee/}gitlab/database{,_spec}.rb"
- "{,ee/}{,spec/}lib/{,ee/}gitlab/background_migration/**/*"
- "{,ee/}{,spec/}lib/{,ee/}gitlab/background_migration{,_spec}.rb"
- - "config/prometheus/common_metrics.yml" # Used by Gitlab::DatabaseImporters::CommonMetrics::Importer
- - "{,ee/}app/models/project_statistics.rb" # Used to calculate sizes in migration specs
+ - "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"
@@ -161,7 +164,7 @@
- "vendor/assets/**/*"
- ".gitlab/ci/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo,scss-lint}.yml"
- "*_VERSION"
- "Gemfile{,.lock}"
- "Rakefile"
@@ -183,7 +186,7 @@
- "vendor/assets/**/*"
- ".gitlab/ci/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo,scss-lint}.yml"
- "*_VERSION"
- "Gemfile{,.lock}"
- "Rakefile"
@@ -207,7 +210,7 @@
- "vendor/assets/**/*"
- ".gitlab/ci/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo,scss-lint}.yml"
- "*_VERSION"
- "Gemfile{,.lock}"
- "Rakefile"
@@ -228,7 +231,7 @@
- "vendor/assets/**/*"
- ".gitlab/ci/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo,scss-lint}.yml"
- "*_VERSION"
- "Gemfile{,.lock}"
- "Rakefile"
@@ -673,10 +676,14 @@
##################
.releases:rules:canonical-dot-com-gitlab-stable-branch-only:
rules:
+ - if: '$CI_COMMIT_MESSAGE =~ /\[merge-train skip\]/'
+ when: never
- if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/gitlab" && $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable-ee$/'
.releases:rules:canonical-dot-com-security-gitlab-stable-branch-only:
rules:
+ - if: '$CI_COMMIT_MESSAGE =~ /\[merge-train skip\]/'
+ when: never
- if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/security/gitlab" && $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable-ee$/'
#################
@@ -771,7 +778,7 @@
.review:rules:review-performance:
rules:
- - if: '$DAST_RUN == "true"' # Skip this job when DAST is run
+ - if: '$DAST_RUN == "true"' # Skip this job when DAST is run
when: never
- <<: *if-not-ee
when: never
@@ -905,10 +912,10 @@
- <<: *if-dot-com-ee-schedule
changes: *code-backstage-patterns
-##############
-# YAML rules #
-##############
-.yaml:rules:
+###################
+# yaml-lint rules #
+###################
+.yaml-lint:rules:
rules:
- <<: *if-default-refs
- changes: *yaml-patterns
+ changes: *yaml-lint-patterns
diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml
index cf42d2a8a5e..abe7625c740 100644
--- a/.gitlab/ci/setup.gitlab-ci.yml
+++ b/.gitlab/ci/setup.gitlab-ci.yml
@@ -52,7 +52,7 @@ no_ee_check:
verify-tests-yml:
extends:
- .setup:rules:verify-tests-yml
- image: ruby:2.6-alpine
+ image: ruby:2.7-alpine
stage: test
needs: []
script:
@@ -61,7 +61,7 @@ verify-tests-yml:
- scripts/verify-tff-mapping
.detect-test-base:
- image: ruby:2.6-alpine
+ image: ruby:2.7-alpine
needs: []
stage: prepare
script:
diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml
index 2d83531e1db..e4b7047ef71 100644
--- a/.gitlab/ci/test-metadata.gitlab-ci.yml
+++ b/.gitlab/ci/test-metadata.gitlab-ci.yml
@@ -9,6 +9,7 @@
- knapsack/
- rspec_flaky/
- rspec_profiling/
+ - crystalball/packed-mapping.json.gz
retrieve-tests-metadata:
extends:
@@ -27,6 +28,8 @@ update-tests-metadata:
dependencies:
- setup-test-env
- rspec migration pg11
+ - rspec frontend_fixture
+ - rspec-ee frontend_fixture
- rspec unit pg11
- rspec integration pg11
- rspec system pg11
@@ -41,3 +44,4 @@ update-tests-metadata:
- run_timed_command "retry gem install fog-aws mime-types activesupport rspec_profiling postgres-copy --no-document"
- source ./scripts/rspec_helpers.sh
- update_tests_metadata
+ - update_tests_mapping
diff --git a/.gitlab/ci/yaml.gitlab-ci.yml b/.gitlab/ci/yaml.gitlab-ci.yml
index a650ee7e4b4..c597d992760 100644
--- a/.gitlab/ci/yaml.gitlab-ci.yml
+++ b/.gitlab/ci/yaml.gitlab-ci.yml
@@ -1,9 +1,9 @@
-# Yamllint of *.yml for .gitlab-ci.yml.
+# Yamllint of CI-related yaml and changelogs.
# This uses rules from project root `.yamllint`.
-lint-ci-gitlab:
+lint-yaml:
extends:
- .default-retry
- - .yaml:rules
+ - .yaml-lint:rules
image: pipelinecomponents/yamllint:latest
stage: test
needs: []
diff --git a/.gitlab/issue_templates/Basic Proposal.md b/.gitlab/issue_templates/Basic Proposal.md
new file mode 100644
index 00000000000..4232561354c
--- /dev/null
+++ b/.gitlab/issue_templates/Basic Proposal.md
@@ -0,0 +1,11 @@
+<!-- This template is a great use for issues that are feature::additions or technical tasks for larger issues.-->
+
+### Proposal
+
+<!-- Use this section to explain the feature and how it will work. It can be helpful to add technical details, design proposals, and links to related epics or issues. -->
+
+<!-- Consider adding related issues and epics to this issue. You can also reference the Feature Proposal Template (https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal.md) for additional details to consider adding to this issue. Additionally, as a data oriented organization, when your feature exits planning breakdown, consider adding the `What does success look like, and how can we measure that?` section.
+
+/label ~"group::" ~"section::" ~"Category::" ~"GitLab Core"/~"GitLab Starter"/~"GitLab Premium"/~"GitLab Ultimate"
+
+-->
diff --git a/.gitlab/issue_templates/Feature Flag Roll Out.md b/.gitlab/issue_templates/Feature Flag Roll Out.md
index 788b610a982..a0b64b53250 100644
--- a/.gitlab/issue_templates/Feature Flag Roll Out.md
+++ b/.gitlab/issue_templates/Feature Flag Roll Out.md
@@ -34,7 +34,9 @@ If applicable, any groups/projects that are happy to have this feature turned on
- [ ] Test on staging
- [ ] Ensure that documentation has been updated
- [ ] Enable on GitLab.com for individual groups/projects listed above and verify behaviour (`/chatops run feature set --project=gitlab-org/gitlab feature_name true`)
-- [ ] Coordinate a time to enable the flag with `#production` and `#g_delivery` on slack.
+- [ ] Coordinate a time to enable the flag with the SRE oncall and release managers
+ - In `#production` by pinging `@sre-oncall`
+ - In `#g_delivery` by pinging `@release-managers`
- [ ] Announce on the issue an estimated time this will be enabled on GitLab.com
- [ ] Enable on GitLab.com by running chatops command in `#production` (`/chatops run feature set feature_name true`)
- [ ] Cross post chatops Slack command to `#support_gitlab-com` ([more guidance when this is necessary in the dev docs](https://docs.gitlab.com/ee/development/feature_flags/controls.html#where-to-run-commands)) and in your team channel
@@ -42,4 +44,12 @@ If applicable, any groups/projects that are happy to have this feature turned on
- [ ] Remove feature flag and add changelog entry
- [ ] After the flag removal is deployed, [clean up the feature flag](https://docs.gitlab.com/ee/development/feature_flags/controls.html#cleaning-up) by running chatops command in `#production` channel
+## Rollback Steps
+
+- [ ] This feature can be disabled by running the following Chatops command:
+
+```
+/chatops run feature set --project=gitlab-org/gitlab feature_name false
+```
+
/label ~"feature flag"
diff --git a/.gitlab/issue_templates/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md
index c80305312c3..b6f83be9121 100644
--- a/.gitlab/issue_templates/Feature proposal.md
+++ b/.gitlab/issue_templates/Feature proposal.md
@@ -4,7 +4,7 @@
<!-- 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
+### Problem to solve
<!-- What problem do we solve? Try to define the who/what/why of the opportunity as a user story. For example, "As a (who), I want (what), so I can (why/value)." -->
@@ -28,6 +28,7 @@ Personas are described at https://about.gitlab.com/handbook/marketing/product-ma
* [Allison (Application Ops)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#allison-application-ops)
* [Priyanka (Platform Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#priyanka-platform-engineer)
* [Dana (Data Analyst)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#dana-data-analyst)
+* [Eddie (Content Editor)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#eddie-content-editor)
-->
### User experience goal
@@ -95,7 +96,8 @@ In which enterprise tier should this feature go? See https://about.gitlab.com/ha
### Links / references
-<!-- Label reminders - you should have one of each of the following labels if you can figure out the correct ones -->
+<!-- Label reminders - you should have one of each of the following labels.
+Read the descriptions on https://gitlab.com/gitlab-org/gitlab/-/labels to find the correct ones -->
/label ~devops:: ~group: ~Category:
/label ~feature
diff --git a/.gitlab/issue_templates/Lean Feature Proposal.md b/.gitlab/issue_templates/Lean Feature Proposal.md
new file mode 100644
index 00000000000..b1cb98ba5e9
--- /dev/null
+++ b/.gitlab/issue_templates/Lean Feature Proposal.md
@@ -0,0 +1,99 @@
+<!-- This issue template can be used a great starting point for feature requests. The last section "Release notes" can be used as a summary of the feature and is also required if you want to have your release post blog MR auto generated using the release post item generator: https://about.gitlab.com/handbook/marketing/blog/release-posts/#release-post-item-generator. The remaining sections are the backbone for every feature in GitLab. -->
+
+### 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
+
+<!-- What is the user problem you are trying to solve with this issue? -->
+
+### Proposal
+
+<!-- Use this section to explain the feature and how it will work. It can be helpful to add technical details, design proposals, and links to related epics or issues. -->
+
+
+
+/label ~"feature" ~"group::" ~"section::" ~"Category::" ~"GitLab Core"/~"GitLab Starter"/~"GitLab Premium"/~"GitLab Ultimate"
+
+
+<!-- Read the labels descriptions on https://gitlab.com/gitlab-org/gitlab/-/labels to find the appropriate labels. Consider adding related issues and epics to this issue. You can also reference the Feature Proposal Template (https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal.md) for additional details to consider adding to this issue. Additionally, as a data oriented organization, when your feature exits planning breakdown, consider adding the `What does success look like, and how can we measure that?` section.
+
+Other sections to consider adding:
+
+### Intended users
+
+Who will use this feature? If known, include any of the following: types of users (e.g. Developer), personas, or specific company roles (e.g. Release Manager). It's okay to write "Unknown" and fill this field in later.
+
+Personas are described at https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/
+
+* [Cameron (Compliance Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#cameron-compliance-manager)
+* [Parker (Product Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#parker-product-manager)
+* [Delaney (Development Team Lead)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#delaney-development-team-lead)
+* [Presley (Product Designer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#presley-product-designer)
+* [Sasha (Software Developer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sasha-software-developer)
+* [Devon (DevOps Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#devon-devops-engineer)
+* [Sidney (Systems Administrator)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sidney-systems-administrator)
+* [Sam (Security Analyst)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sam-security-analyst)
+* [Rachel (Release Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#rachel-release-manager)
+* [Alex (Security Operations Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#alex-security-operations-engineer)
+* [Simone (Software Engineer in Test)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#simone-software-engineer-in-test)
+* [Allison (Application Ops)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#allison-application-ops)
+* [Priyanka (Platform Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#priyanka-platform-engineer)
+* [Dana (Data Analyst)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#dana-data-analyst)
+
+
+### User experience goal
+
+What is the single user experience workflow this problem addresses?
+For example, "The user should be able to use the UI/API/.gitlab-ci.yml with GitLab to <perform a specific task>"
+https://about.gitlab.com/handbook/engineering/ux/ux-research-training/user-story-mapping/
+
+
+### Further details
+
+Include use cases, benefits, goals, or any other details that will help us understand the problem better.
+
+### Permissions and Security
+
+<!-- What permissions are required to perform the described actions? Are they consistent with the existing permissions as documented for users, groups, and projects as appropriate? Is the proposed behavior consistent between the UI, API, and other access methods (e.g. email replies)?
+Consider adding checkboxes and expectations of users with certain levels of membership https://docs.gitlab.com/ee/user/permissions.html
+* [ ] Add expected impact to members with no access (0)
+* [ ] Add expected impact to Guest (10) members
+* [ ] Add expected impact to Reporter (20) members
+* [ ] Add expected impact to Developer (30) members
+* [ ] Add expected impact to Maintainer (40) members
+* [ ] Add expected impact to Owner (50) members
+
+### Documentation
+
+ See the Feature Change Documentation Workflow https://docs.gitlab.com/ee/development/documentation/workflow.html#for-a-product-change
+
+* Add all known Documentation Requirements in this section. See https://docs.gitlab.com/ee/development/documentation/feature-change-workflow.html#documentation-requirements
+* If this feature requires changing permissions, update the permissions document. See https://docs.gitlab.com/ee/user/permissions.html
+
+### Availability & Testing
+
+This section needs to be retained and filled in during the workflow planning breakdown phase of this feature proposal, if not earlier.
+
+What risks does this change pose to our availability? How might it affect the quality of the product? What additional test coverage or changes to tests will be needed? Will it require cross-browser testing?
+
+Please list the test areas (unit, integration and end-to-end) that needs to be added or updated to ensure that this feature will work as intended. Please use the list below as guidance.
+* Unit test changes
+* Integration test changes
+* End-to-end test change
+
+See the test engineering planning process and reach out to your counterpart Software Engineer in Test for assistance: https://about.gitlab.com/handbook/engineering/quality/test-engineering/#test-planning
+
+### What does success look like, and how can we measure that?
+
+Define both the success metrics and acceptance criteria. Note that success metrics indicate the desired business outcomes, while acceptance criteria indicate when the solution is working correctly. If there is no way to measure success, link to an issue that will implement a way to measure this.
+
+### What is the type of buyer?
+
+What is the buyer persona for this feature? See https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/buyer-persona/
+In which enterprise tier should this feature go? See https://about.gitlab.com/handbook/product/pricing/#four-tiers
+
+### Is this a cross-stage feature?
+
+Communicate if this change will affect multiple Stage Groups or product areas. We recommend always start with the assumption that a feature request will have an impact into another Group. Loop in the most relevant PM and Product Designer from that Group to provide strategic support to help align the Group's broader plan and vision, as well as to avoid UX and technical debt. https://about.gitlab.com/handbook/product/#cross-stage-features -->
diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md
index 8713405033b..b059c1f68ad 100644
--- a/.gitlab/merge_request_templates/Documentation.md
+++ b/.gitlab/merge_request_templates/Documentation.md
@@ -55,6 +55,14 @@ All reviewers can help ensure accuracy, clarity, completeness, and adherence to
For more information about labels, see [Technical Writing workflows - Labels](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#labels).
+For suggestions that you are confident don't need to be reviewed, change them locally
+and push a commit directly to save others from unneeded reviews. For example:
+
+- Clear typos, like `this is a typpo`.
+- Minor issues, like single quotes instead of double quotes, Oxford commas, and periods.
+
+For more information, see our documentation on [Merging a merge request](https://docs.gitlab.com/ee/development/code_review.html#merging-a-merge-request).
+
**3. Maintainer**
1. [ ] Review by assigned maintainer, who can always request/require the above reviews. Maintainer's review can occur before or after a technical writer review.
diff --git a/.gitpod.yml b/.gitpod.yml
index 1a8a8e8555e..dc1dbc1472d 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -7,15 +7,14 @@ tasks:
- init: |
echo "$(date) – Copying GDK" | tee -a /workspace/startup.log
+ rm -r /workspace/.rvm
mv $HOME/.rvm-workspace /workspace/.rvm
cp -r $HOME/gitlab-development-kit /workspace/
(
set -e
cd /workspace/gitlab-development-kit
[[ ! -L /workspace/gitlab-development-kit/gitlab ]] && ln -fs /workspace/gitlab /workspace/gitlab-development-kit/gitlab
- # make webpack static, prevents that GitLab tries to connect to localhost webpack from browser outside the workspace
- echo "webpack:" >> gdk.yml
- echo " static: true" >> gdk.yml
+ mv /workspace/gitlab-development-kit/secrets.yml /workspace/gitlab-development-kit/gitlab/config
# reconfigure GDK
echo "$(date) – Reconfiguring GDK" | tee -a /workspace/startup.log
gdk reconfigure
@@ -41,20 +40,16 @@ tasks:
fi
# start GDK
echo "$(date) – Starting GDK" | tee -a /workspace/startup.log
+ export DEV_SERVER_PUBLIC_ADDR=$(gp url 3808)
export RAILS_HOSTS=$(gp url 3000 | sed -e 's+^http[s]*://++')
gdk start
# Run DB migrations
if [ "$GITLAB_RUN_DB_MIGRATIONS" == true ]; then
make gitlab-db-migrate
fi
- # Fix DB key
- if [ "$GITLAB_FIX_DB_KEY" = true ]; then
- echo "$(date) – Fixing DB key" | tee -a /workspace/startup.log
- cd gitlab
- # see https://gitlab.com/gitlab-org/gitlab-foss/-/issues/56403#note_132515069
- printf 'ApplicationSetting.last.update_column(:runners_registration_token_encrypted, nil)\nexit\n' | bundle exec rails c
- cd -
- fi
+ cd ../gitlab
+ git checkout db/structure.sql
+ cd ../gitlab-development-kit
# Waiting for GitLab ...
gp await-port 3000
printf "Waiting for GitLab at $(gp url 3000) ..."
diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml
index 57c0e014a03..6d6a5d2a813 100644
--- a/.haml-lint_todo.yml
+++ b/.haml-lint_todo.yml
@@ -119,7 +119,6 @@ linters:
- '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'
@@ -330,7 +329,6 @@ linters:
- 'ee/app/views/errors/kerberos_denied.html.haml'
- 'ee/app/views/groups/ee/_settings_nav.html.haml'
- 'ee/app/views/groups/group_members/_ldap_sync.html.haml'
- - '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/layouts/nav/ee/admin/_new_monitoring_sidebar.html.haml'
@@ -363,7 +361,6 @@ linters:
- 'ee/app/views/projects/services/gitlab_slack_application/_help.html.haml'
- 'ee/app/views/projects/services/gitlab_slack_application/_slack_integration_form.html.haml'
- 'ee/app/views/projects/settings/slacks/edit.html.haml'
- - 'ee/app/views/shared/_mirror_update_button.html.haml'
- 'ee/app/views/shared/epic/_search_bar.html.haml'
- 'ee/app/views/shared/issuable/_approvals.html.haml'
- 'ee/app/views/shared/issuable/_board_create_list_dropdown.html.haml'
diff --git a/.nvmrc b/.nvmrc
index 4de623cfefa..ce122aaa988 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-12.10.0
+12.18.4
diff --git a/.rubocop.yml b/.rubocop.yml
index cc65727e94d..34d6fe5e434 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -7,16 +7,18 @@ require:
- rubocop-rspec
inherit_from:
+ - .rubocop_manual_todo.yml
- .rubocop_todo.yml
- ./rubocop/rubocop-migrations.yml
- ./rubocop/rubocop-usage-data.yml
+ - ./rubocop/rubocop-code_reuse.yml
inherit_mode:
merge:
- Include
AllCops:
- TargetRubyVersion: 2.6
+ TargetRubyVersion: 2.7
TargetRailsVersion: 6.0
Exclude:
- 'vendor/**/*'
@@ -353,6 +355,12 @@ Cop/SidekiqOptionsQueue:
- 'spec/**/*.rb'
- 'ee/spec/**/*.rb'
+Graphql/ResolverType:
+ Enabled: true
+ Include:
+ - 'app/graphql/resolvers/**/*'
+ - 'ee/app/graphql/resolvers/**/*'
+
Graphql/AuthorizeTypes:
Enabled: true
Include:
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
new file mode 100644
index 00000000000..0b6e0f64942
--- /dev/null
+++ b/.rubocop_manual_todo.yml
@@ -0,0 +1,759 @@
+FactoryBot/InlineAssociation:
+ Exclude:
+ - 'ee/spec/factories/analytics/cycle_analytics/group_stages.rb'
+ - 'ee/spec/factories/geo/event_log.rb'
+ - 'ee/spec/factories/groups.rb'
+ - 'ee/spec/factories/merge_request_blocks.rb'
+ - 'ee/spec/factories/vulnerabilities/feedback.rb'
+ - 'spec/factories/atlassian_identities.rb'
+ - 'spec/factories/events.rb'
+ - 'spec/factories/git_wiki_commit_details.rb'
+ - 'spec/factories/gitaly/commit.rb'
+ - 'spec/factories/go_module_commits.rb'
+ - 'spec/factories/go_module_versions.rb'
+ - 'spec/factories/go_modules.rb'
+ - 'spec/factories/group_group_links.rb'
+ - 'spec/factories/import_export_uploads.rb'
+ - 'spec/factories/merge_requests.rb'
+ - 'spec/factories/notes.rb'
+ - 'spec/factories/sent_notifications.rb'
+ - 'spec/factories/uploads.rb'
+ - 'spec/factories/wiki_pages.rb'
+
+Graphql/IDType:
+ Exclude:
+ - 'ee/app/graphql/ee/mutations/issues/update.rb'
+ - 'ee/app/graphql/mutations/iterations/update.rb'
+ - 'ee/app/graphql/resolvers/iterations_resolver.rb'
+ - 'app/graphql/mutations/boards/issues/issue_move_list.rb'
+ - 'app/graphql/mutations/issues/update.rb'
+ - 'app/graphql/mutations/metrics/dashboard/annotations/delete.rb'
+ - 'app/graphql/resolvers/design_management/design_at_version_resolver.rb'
+ - 'app/graphql/resolvers/design_management/design_resolver.rb'
+ - 'app/graphql/resolvers/design_management/designs_resolver.rb'
+ - 'app/graphql/resolvers/design_management/version/design_at_version_resolver.rb'
+ - 'app/graphql/resolvers/design_management/version_in_collection_resolver.rb'
+ - 'app/graphql/resolvers/design_management/version_resolver.rb'
+ - 'app/graphql/resolvers/design_management/versions_resolver.rb'
+ - 'app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb'
+ - 'app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb'
+ - 'app/graphql/resolvers/user_merge_requests_resolver.rb'
+
+Graphql/ResolverType:
+ Exclude:
+ - 'app/graphql/resolvers/base_resolver.rb'
+ - 'app/graphql/resolvers/ci/jobs_resolver.rb'
+ - 'app/graphql/resolvers/ci/pipeline_stages_resolver.rb'
+ - 'app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb'
+ - 'app/graphql/resolvers/merge_requests_resolver.rb'
+ - 'app/graphql/resolvers/users/group_count_resolver.rb'
+ - 'ee/app/graphql/resolvers/geo/merge_request_diff_registries_resolver.rb'
+ - 'ee/app/graphql/resolvers/geo/package_file_registries_resolver.rb'
+ - 'ee/app/graphql/resolvers/geo/terraform_state_version_registries_resolver.rb'
+ - 'ee/app/graphql/resolvers/vulnerabilities_base_resolver.rb'
+
+Rails/SaveBang:
+ Exclude:
+ - 'ee/spec/controllers/projects/merge_requests_controller_spec.rb'
+ - 'ee/spec/controllers/subscriptions_controller_spec.rb'
+ - 'ee/spec/frontend/fixtures/analytics.rb'
+ - 'ee/spec/graphql/resolvers/vulnerabilities_resolver_spec.rb'
+ - 'ee/spec/initializers/fog_google_https_private_urls_spec.rb'
+ - 'ee/spec/lib/analytics/merge_request_metrics_calculator_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
+ - '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'
+ - 'ee/spec/lib/gitlab/auth/o_auth/user_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/saml/user_spec.rb'
+ - '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_spec.rb'
+ - 'ee/spec/lib/gitlab/git_access_spec.rb'
+ - 'ee/spec/lib/gitlab/import_export/group/relation_factory_spec.rb'
+ - 'ee/spec/lib/gitlab/mirror_spec.rb'
+ - 'ee/spec/mailers/notify_spec.rb'
+ - 'ee/spec/migrations/fix_any_approver_rule_for_projects_spec.rb'
+ - 'ee/spec/migrations/geo/migrate_ci_job_artifacts_to_separate_registry_spec.rb'
+ - 'ee/spec/migrations/geo/migrate_lfs_objects_to_separate_registry_spec.rb'
+ - 'ee/spec/migrations/schedule_merge_request_any_approval_rule_migration_spec.rb'
+ - 'ee/spec/migrations/schedule_project_any_approval_rule_migration_spec.rb'
+ - 'ee/spec/models/application_setting_spec.rb'
+ - 'ee/spec/models/approval_merge_request_rule_spec.rb'
+ - 'ee/spec/models/approval_project_rule_spec.rb'
+ - 'ee/spec/models/burndown_spec.rb'
+ - 'ee/spec/models/ci/pipeline_spec.rb'
+ - 'ee/spec/models/ci/subscriptions/project_spec.rb'
+ - 'ee/spec/models/ee/appearance_spec.rb'
+ - 'ee/spec/models/ee/ci/job_artifact_spec.rb'
+ - 'ee/spec/models/ee/protected_branch_spec.rb'
+ - 'ee/spec/models/ee/protected_ref_access_spec.rb'
+ - 'ee/spec/models/ee/protected_ref_spec.rb'
+ - 'ee/spec/models/elasticsearch_indexed_namespace_spec.rb'
+ - 'ee/spec/models/environment_spec.rb'
+ - 'ee/spec/models/epic_spec.rb'
+ - 'ee/spec/models/geo/project_registry_spec.rb'
+ - 'ee/spec/models/geo_node_spec.rb'
+ - 'ee/spec/models/geo_node_status_spec.rb'
+ - 'ee/spec/models/gitlab_subscription_spec.rb'
+ - 'ee/spec/models/group_spec.rb'
+ - 'ee/spec/models/issue_spec.rb'
+ - 'ee/spec/models/label_note_spec.rb'
+ - 'ee/spec/models/lfs_object_spec.rb'
+ - 'ee/spec/models/license_spec.rb'
+ - 'ee/spec/models/merge_request_spec.rb'
+ - 'ee/spec/models/merge_train_spec.rb'
+ - 'spec/models/packages/package_spec.rb'
+ - 'ee/spec/models/project_ci_cd_setting_spec.rb'
+ - 'ee/spec/models/project_spec.rb'
+ - 'ee/spec/models/protected_environment_spec.rb'
+ - 'ee/spec/models/repository_spec.rb'
+ - 'ee/spec/models/scim_identity_spec.rb'
+ - 'ee/spec/models/scim_oauth_access_token_spec.rb'
+ - 'ee/spec/models/upload_spec.rb'
+ - 'ee/spec/models/user_preference_spec.rb'
+ - 'ee/spec/models/user_spec.rb'
+ - 'ee/spec/models/visible_approvable_spec.rb'
+ - 'ee/spec/models/vulnerabilities/feedback_spec.rb'
+ - 'ee/spec/models/vulnerabilities/issue_link_spec.rb'
+ - 'ee/spec/presenters/audit_event_presenter_spec.rb'
+ - 'ee/spec/presenters/epic_presenter_spec.rb'
+ - 'ee/spec/requests/api/boards_spec.rb'
+ - 'ee/spec/requests/api/epic_issues_spec.rb'
+ - 'ee/spec/requests/api/epic_links_spec.rb'
+ - 'ee/spec/requests/api/epics_spec.rb'
+ - 'ee/spec/requests/api/geo_nodes_spec.rb'
+ - 'ee/spec/requests/api/geo_spec.rb'
+ - 'ee/spec/requests/api/graphql/group/epics_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/epic_tree/reorder_spec.rb'
+ - 'ee/spec/requests/api/groups_spec.rb'
+ - 'ee/spec/requests/api/issues_spec.rb'
+ - 'ee/spec/requests/api/ldap_group_links_spec.rb'
+ - 'ee/spec/requests/api/merge_request_approval_rules_spec.rb'
+ - 'ee/spec/requests/api/merge_request_approvals_spec.rb'
+ - 'ee/spec/requests/api/merge_requests_spec.rb'
+ - 'ee/spec/requests/api/project_approvals_spec.rb'
+ - 'ee/spec/requests/api/projects_spec.rb'
+ - 'ee/spec/requests/api/protected_branches_spec.rb'
+ - 'ee/spec/requests/api/scim_spec.rb'
+ - 'ee/spec/requests/api/todos_spec.rb'
+ - '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/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'
+ - 'ee/spec/services/ee/issuable/clone/attributes_rewriter_spec.rb'
+ - 'ee/spec/services/ee/issuable/common_system_notes_service_spec.rb'
+ - 'ee/spec/services/ee/issues/update_service_spec.rb'
+ - 'ee/spec/services/ee/merge_requests/refresh_service_spec.rb'
+ - '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/epic_links/create_service_spec.rb'
+ - 'ee/spec/services/epics/close_service_spec.rb'
+ - 'ee/spec/services/epics/issue_promote_service_spec.rb'
+ - 'ee/spec/services/epics/reopen_service_spec.rb'
+ - 'ee/spec/services/epics/tree_reorder_service_spec.rb'
+ - 'ee/spec/services/epics/update_dates_service_spec.rb'
+ - 'ee/spec/services/epics/update_service_spec.rb'
+ - 'ee/spec/services/geo/blob_verification_secondary_service_spec.rb'
+ - 'ee/spec/services/geo/files_expire_service_spec.rb'
+ - 'ee/spec/services/geo/metrics_update_service_spec.rb'
+ - 'ee/spec/services/geo/registry_consistency_service_spec.rb'
+ - 'ee/spec/services/geo/repository_verification_secondary_service_spec.rb'
+ - '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_trains/refresh_merge_request_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'
+ - 'ee/spec/services/status_page/trigger_publish_service_spec.rb'
+ - 'ee/spec/services/todo_service_spec.rb'
+ - 'ee/spec/services/update_build_minutes_service_spec.rb'
+ - 'ee/spec/services/vulnerability_feedback/create_service_spec.rb'
+ - 'ee/spec/support/protected_tags/access_control_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/features/protected_branches_access_control_shared_examples.rb'
+ - '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/policies/protected_environments_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'
+ - 'ee/spec/workers/elastic_namespace_rollout_worker_spec.rb'
+ - 'ee/spec/workers/geo/container_repository_sync_dispatch_worker_spec.rb'
+ - 'ee/spec/workers/geo/file_download_dispatch_worker_spec.rb'
+ - 'ee/spec/workers/geo/prune_event_log_worker_spec.rb'
+ - 'ee/spec/workers/geo/registry_sync_worker_spec.rb'
+ - 'ee/spec/workers/geo/repository_shard_sync_worker_spec.rb'
+ - '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'
+ - 'spec/controllers/admin/impersonations_controller_spec.rb'
+ - 'spec/controllers/admin/runners_controller_spec.rb'
+ - 'spec/controllers/admin/services_controller_spec.rb'
+ - 'spec/controllers/boards/issues_controller_spec.rb'
+ - 'spec/controllers/groups/milestones_controller_spec.rb'
+ - 'spec/controllers/groups/runners_controller_spec.rb'
+ - 'spec/controllers/groups/uploads_controller_spec.rb'
+ - 'spec/controllers/groups_controller_spec.rb'
+ - 'spec/controllers/oauth/authorizations_controller_spec.rb'
+ - 'spec/controllers/omniauth_callbacks_controller_spec.rb'
+ - 'spec/controllers/profiles/emails_controller_spec.rb'
+ - 'spec/controllers/profiles/notifications_controller_spec.rb'
+ - 'spec/controllers/projects/artifacts_controller_spec.rb'
+ - 'spec/controllers/projects/cycle_analytics/events_controller_spec.rb'
+ - 'spec/controllers/projects/cycle_analytics_controller_spec.rb'
+ - 'spec/controllers/projects/discussions_controller_spec.rb'
+ - 'spec/controllers/projects/forks_controller_spec.rb'
+ - 'spec/controllers/projects/group_links_controller_spec.rb'
+ - 'spec/controllers/projects/imports_controller_spec.rb'
+ - 'spec/controllers/projects/issues_controller_spec.rb'
+ - 'spec/controllers/projects/labels_controller_spec.rb'
+ - 'spec/controllers/projects/milestones_controller_spec.rb'
+ - 'spec/controllers/projects/notes_controller_spec.rb'
+ - 'spec/controllers/projects/pipelines_controller_spec.rb'
+ - 'spec/controllers/projects/releases/evidences_controller_spec.rb'
+ - 'spec/controllers/projects/runners_controller_spec.rb'
+ - 'spec/controllers/projects/starrers_controller_spec.rb'
+ - 'spec/controllers/projects/uploads_controller_spec.rb'
+ - 'spec/controllers/projects_controller_spec.rb'
+ - 'spec/controllers/sent_notifications_controller_spec.rb'
+ - 'spec/controllers/sessions_controller_spec.rb'
+ - 'spec/controllers/users_controller_spec.rb'
+ - 'spec/factories_spec.rb'
+ - 'spec/features/admin/admin_appearance_spec.rb'
+ - 'spec/features/admin/admin_labels_spec.rb'
+ - 'spec/features/admin/admin_mode/login_spec.rb'
+ - 'spec/features/admin/admin_runners_spec.rb'
+ - 'spec/features/admin/admin_sees_project_statistics_spec.rb'
+ - 'spec/features/admin/admin_sees_projects_statistics_spec.rb'
+ - 'spec/features/admin/admin_users_impersonation_tokens_spec.rb'
+ - 'spec/features/admin/admin_users_spec.rb'
+ - 'spec/features/boards/sidebar_spec.rb'
+ - 'spec/features/calendar_spec.rb'
+ - 'spec/features/commits_spec.rb'
+ - 'spec/features/dashboard/datetime_on_tooltips_spec.rb'
+ - 'spec/features/dashboard/issuables_counter_spec.rb'
+ - 'spec/features/dashboard/project_member_activity_index_spec.rb'
+ - 'spec/features/dashboard/projects_spec.rb'
+ - 'spec/features/error_tracking/user_sees_error_index_spec.rb'
+ - 'spec/features/groups/members/request_access_spec.rb'
+ - 'spec/features/issuables/close_reopen_report_toggle_spec.rb'
+ - 'spec/features/issues/bulk_assignment_labels_spec.rb'
+ - 'spec/features/issues/gfm_autocomplete_spec.rb'
+ - 'spec/features/issues/issue_sidebar_spec.rb'
+ - 'spec/features/issues/note_polling_spec.rb'
+ - 'spec/features/issues/user_creates_branch_and_merge_request_spec.rb'
+ - 'spec/features/issues/user_creates_confidential_merge_request_spec.rb'
+ - 'spec/features/issues/user_edits_issue_spec.rb'
+ - 'spec/features/issues/user_filters_issues_spec.rb'
+ - 'spec/features/issues/user_sees_live_update_spec.rb'
+ - 'spec/features/issues/user_sorts_issues_spec.rb'
+ - 'spec/features/profiles/emails_spec.rb'
+ - 'spec/features/profiles/password_spec.rb'
+ - 'spec/features/profiles/personal_access_tokens_spec.rb'
+ - 'spec/features/projects/features_visibility_spec.rb'
+ - 'spec/features/projects/fork_spec.rb'
+ - 'spec/features/projects/jobs/permissions_spec.rb'
+ - 'spec/features/projects/jobs_spec.rb'
+ - 'spec/features/projects/members/user_requests_access_spec.rb'
+ - 'spec/features/projects/pages_lets_encrypt_spec.rb'
+ - 'spec/features/projects/pages_spec.rb'
+ - 'spec/features/projects/pipelines/pipeline_spec.rb'
+ - 'spec/features/projects/pipelines/pipelines_spec.rb'
+ - 'spec/features/projects/remote_mirror_spec.rb'
+ - 'spec/features/projects/services/user_activates_slack_notifications_spec.rb'
+ - 'spec/features/projects/settings/access_tokens_spec.rb'
+ - 'spec/features/projects/show/user_sees_deletion_failure_message_spec.rb'
+ - 'spec/features/projects/user_sees_sidebar_spec.rb'
+ - 'spec/features/projects/wiki/user_updates_wiki_page_spec.rb'
+ - 'spec/features/projects/wiki/user_views_wiki_page_spec.rb'
+ - 'spec/features/projects/wiki/users_views_asciidoc_page_with_includes_spec.rb'
+ - 'spec/features/runners_spec.rb'
+ - 'spec/features/security/project/internal_access_spec.rb'
+ - 'spec/features/security/project/private_access_spec.rb'
+ - 'spec/features/security/project/public_access_spec.rb'
+ - 'spec/features/users/login_spec.rb'
+ - 'spec/features/users/show_spec.rb'
+ - 'spec/frontend/fixtures/issues.rb'
+ - 'spec/frontend/fixtures/merge_requests.rb'
+ - 'spec/graphql/mutations/merge_requests/set_locked_spec.rb'
+ - 'spec/graphql/mutations/merge_requests/set_wip_spec.rb'
+ - 'spec/graphql/resolvers/boards_resolver_spec.rb'
+ - 'spec/initializers/active_record_locking_spec.rb'
+ - 'spec/initializers/fog_google_https_private_urls_spec.rb'
+ - 'spec/lib/after_commit_queue_spec.rb'
+ - 'spec/lib/backup/manager_spec.rb'
+ - 'spec/lib/banzai/reference_parser/external_issue_parser_spec.rb'
+ - 'spec/lib/banzai/reference_redactor_spec.rb'
+ - 'spec/lib/gitlab/alerting/alert_spec.rb'
+ - 'spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb'
+ - 'spec/lib/gitlab/auth/ldap/user_spec.rb'
+ - 'spec/lib/gitlab/auth/o_auth/user_spec.rb'
+ - 'spec/lib/gitlab/auth/saml/user_spec.rb'
+ - 'spec/lib/gitlab/auth_spec.rb'
+ - 'spec/lib/gitlab/authorized_keys_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_project_repositories_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_project_settings_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_push_rules_id_in_projects_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb'
+ - 'spec/lib/gitlab/background_migration/digest_column_spec.rb'
+ - 'spec/lib/gitlab/background_migration/encrypt_columns_spec.rb'
+ - 'spec/lib/gitlab/background_migration/fix_cross_project_label_links_spec.rb'
+ - 'spec/lib/gitlab/background_migration/fix_projects_without_project_feature_spec.rb'
+ - 'spec/lib/gitlab/background_migration/fix_projects_without_prometheus_service_spec.rb'
+ - 'spec/lib/gitlab/background_migration/fix_user_namespace_names_spec.rb'
+ - 'spec/lib/gitlab/background_migration/fix_user_project_route_names_spec.rb'
+ - 'spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb'
+ - 'spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb'
+ - 'spec/lib/gitlab/background_migration/link_lfs_objects_projects_spec.rb'
+ - 'spec/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data_spec.rb'
+ - 'spec/lib/gitlab/background_migration/migrate_stage_index_spec.rb'
+ - 'spec/lib/gitlab/background_migration/migrate_users_bio_to_user_details_spec.rb'
+ - 'spec/lib/gitlab/background_migration/populate_canonical_emails_spec.rb'
+ - 'spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb'
+ - 'spec/lib/gitlab/background_migration/populate_user_highest_roles_table_spec.rb'
+ - 'spec/lib/gitlab/background_migration/recalculate_project_authorizations_spec.rb'
+ - 'spec/lib/gitlab/background_migration/remove_restricted_todos_spec.rb'
+ - 'spec/lib/gitlab/background_migration/reset_merge_status_spec.rb'
+ - 'spec/lib/gitlab/background_migration/set_confidential_note_events_on_services_spec.rb'
+ - 'spec/lib/gitlab/background_migration/set_confidential_note_events_on_webhooks_spec.rb'
+ - 'spec/lib/gitlab/bitbucket_server_import/importer_spec.rb'
+ - 'spec/lib/gitlab/ci/ansi2json/style_spec.rb'
+ - 'spec/lib/gitlab/ci/status/build/common_spec.rb'
+ - 'spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb'
+ - 'spec/lib/gitlab/database/custom_structure_spec.rb'
+ - 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
+ - 'spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb'
+ - 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
+ - 'spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb'
+ - 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
+ - 'spec/lib/gitlab/git_access_spec.rb'
+ - 'spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb'
+ - 'spec/lib/gitlab/gitaly_client/repository_service_spec.rb'
+ - 'spec/lib/gitlab/import_export/avatar_saver_spec.rb'
+ - 'spec/lib/gitlab/import_export/base/relation_factory_spec.rb'
+ - 'spec/lib/gitlab/import_export/design_repo_restorer_spec.rb'
+ - 'spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb'
+ - 'spec/lib/gitlab/import_export/fork_spec.rb'
+ - 'spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb'
+ - 'spec/lib/gitlab/import_export/group/relation_factory_spec.rb'
+ - 'spec/lib/gitlab/import_export/group/tree_saver_spec.rb'
+ - 'spec/lib/gitlab/import_export/importer_spec.rb'
+ - 'spec/lib/gitlab/import_export/lfs_restorer_spec.rb'
+ - 'spec/lib/gitlab/import_export/lfs_saver_spec.rb'
+ - 'spec/lib/gitlab/import_export/members_mapper_spec.rb'
+ - 'spec/lib/gitlab/import_export/project/relation_factory_spec.rb'
+ - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
+ - 'spec/lib/gitlab/import_export/project/tree_saver_spec.rb'
+ - 'spec/lib/gitlab/import_export/repo_restorer_spec.rb'
+ - 'spec/lib/gitlab/import_export/saver_spec.rb'
+ - 'spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb'
+ - 'spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb'
+ - 'spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb'
+ - 'spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb'
+ - 'spec/lib/gitlab/import_export/uploads_manager_spec.rb'
+ - 'spec/lib/gitlab/import_export/uploads_saver_spec.rb'
+ - 'spec/lib/gitlab/import_export/wiki_restorer_spec.rb'
+ - 'spec/lib/gitlab/legacy_github_import/importer_spec.rb'
+ - 'spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb'
+ - 'spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb'
+ - 'spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb'
+ - 'spec/lib/gitlab/lets_encrypt/client_spec.rb'
+ - 'spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb'
+ - 'spec/lib/gitlab/markdown_cache/redis/store_spec.rb'
+ - 'spec/lib/gitlab/middleware/go_spec.rb'
+ - 'spec/lib/gitlab/shard_health_cache_spec.rb'
+ - 'spec/lib/mattermost/command_spec.rb'
+ - 'spec/lib/mattermost/session_spec.rb'
+ - 'spec/lib/mattermost/team_spec.rb'
+ - 'spec/mailers/notify_spec.rb'
+ - 'spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb'
+ - 'spec/migrations/20200122123016_backfill_project_settings_spec.rb'
+ - 'spec/migrations/20200123155929_remove_invalid_jira_data_spec.rb'
+ - 'spec/migrations/20200127090233_remove_invalid_issue_tracker_data_spec.rb'
+ - 'spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb'
+ - 'spec/migrations/20200313203550_remove_orphaned_chat_names_spec.rb'
+ - 'spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb'
+ - 'spec/migrations/20200526115436_dedup_mr_metrics_spec.rb'
+ - 'spec/migrations/add_deploy_token_type_to_deploy_tokens_spec.rb'
+ - 'spec/migrations/add_incident_settings_to_all_existing_projects_spec.rb'
+ - 'spec/migrations/add_unique_constraint_to_approvals_user_id_and_merge_request_id_spec.rb'
+ - 'spec/migrations/backfill_and_add_not_null_constraint_to_released_at_column_on_releases_table_spec.rb'
+ - 'spec/migrations/backfill_imported_snippet_repositories_spec.rb'
+ - 'spec/migrations/backfill_releases_table_updated_at_and_add_not_null_constraints_to_timestamps_spec.rb'
+ - 'spec/migrations/backfill_snippet_repositories_spec.rb'
+ - 'spec/migrations/encrypt_plaintext_attributes_on_application_settings_spec.rb'
+ - 'spec/migrations/enqueue_reset_merge_status_second_run_spec.rb'
+ - 'spec/migrations/enqueue_reset_merge_status_spec.rb'
+ - 'spec/migrations/fill_file_store_lfs_objects_spec.rb'
+ - 'spec/migrations/fill_store_uploads_spec.rb'
+ - 'spec/migrations/fix_null_type_labels_spec.rb'
+ - 'spec/migrations/fix_pool_repository_source_project_id_spec.rb'
+ - 'spec/migrations/fix_projects_without_project_feature_spec.rb'
+ - 'spec/migrations/fix_projects_without_prometheus_services_spec.rb'
+ - 'spec/migrations/fix_wrong_pages_access_level_spec.rb'
+ - 'spec/migrations/insert_project_hooks_plan_limits_spec.rb'
+ - 'spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb'
+ - 'spec/migrations/move_limits_from_plans_spec.rb'
+ - 'spec/migrations/populate_project_statistics_packages_size_spec.rb'
+ - 'spec/migrations/schedule_link_lfs_objects_projects_spec.rb'
+ - 'spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb'
+ - 'spec/migrations/seed_repository_storages_weighted_spec.rb'
+ - 'spec/models/appearance_spec.rb'
+ - 'spec/models/application_record_spec.rb'
+ - 'spec/models/application_setting_spec.rb'
+ - 'spec/models/clusters/applications/helm_spec.rb'
+ - 'spec/models/commit_spec.rb'
+ - 'spec/models/commit_status_spec.rb'
+ - 'spec/models/container_repository_spec.rb'
+ - 'spec/models/deploy_keys_project_spec.rb'
+ - 'spec/models/deploy_token_spec.rb'
+ - 'spec/models/deployment_spec.rb'
+ - 'spec/models/design_management/version_spec.rb'
+ - 'spec/models/diff_discussion_spec.rb'
+ - 'spec/models/diff_note_spec.rb'
+ - 'spec/models/email_spec.rb'
+ - 'spec/models/environment_spec.rb'
+ - 'spec/models/event_spec.rb'
+ - 'spec/models/fork_network_spec.rb'
+ - 'spec/models/generic_commit_status_spec.rb'
+ - 'spec/models/grafana_integration_spec.rb'
+ - 'spec/models/group_spec.rb'
+ - 'spec/models/hooks/system_hook_spec.rb'
+ - 'spec/models/hooks/web_hook_spec.rb'
+ - 'spec/models/identity_spec.rb'
+ - 'spec/models/issue/metrics_spec.rb'
+ - 'spec/models/issue_spec.rb'
+ - 'spec/models/jira_import_state_spec.rb'
+ - 'spec/models/key_spec.rb'
+ - 'spec/models/lfs_objects_project_spec.rb'
+ - 'spec/models/member_spec.rb'
+ - 'spec/models/members/group_member_spec.rb'
+ - 'spec/models/members/project_member_spec.rb'
+ - 'spec/models/merge_request_spec.rb'
+ - 'spec/models/milestone_spec.rb'
+ - 'spec/models/namespace_spec.rb'
+ - 'spec/models/note_spec.rb'
+ - 'spec/models/notification_setting_spec.rb'
+ - 'spec/models/operations/feature_flag_scope_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_spec.rb'
+ - 'spec/models/project_team_spec.rb'
+ - 'spec/models/protectable_dropdown_spec.rb'
+ - 'spec/models/redirect_route_spec.rb'
+ - 'spec/models/release_spec.rb'
+ - 'spec/models/remote_mirror_spec.rb'
+ - 'spec/models/resource_milestone_event_spec.rb'
+ - 'spec/models/route_spec.rb'
+ - 'spec/models/sentry_issue_spec.rb'
+ - 'spec/models/service_spec.rb'
+ - 'spec/models/snippet_spec.rb'
+ - 'spec/models/upload_spec.rb'
+ - 'spec/models/user_preference_spec.rb'
+ - 'spec/models/user_spec.rb'
+ - 'spec/models/user_status_spec.rb'
+ - 'spec/models/wiki_page/meta_spec.rb'
+ - 'spec/models/wiki_page_spec.rb'
+ - '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/ci/runner_spec.rb'
+ - 'spec/requests/api/commit_statuses_spec.rb'
+ - 'spec/requests/api/conan_packages_spec.rb'
+ - 'spec/requests/api/deployments_spec.rb'
+ - 'spec/requests/api/environments_spec.rb'
+ - 'spec/requests/api/go_proxy_spec.rb'
+ - 'spec/requests/api/graphql/mutations/merge_requests/set_labels_spec.rb'
+ - 'spec/requests/api/graphql/user_query_spec.rb'
+ - 'spec/requests/api/graphql_spec.rb'
+ - 'spec/requests/api/group_import_spec.rb'
+ - 'spec/requests/api/group_milestones_spec.rb'
+ - 'spec/requests/api/internal/base_spec.rb'
+ - 'spec/requests/api/issues/get_group_issues_spec.rb'
+ - 'spec/requests/api/issues/post_projects_issues_spec.rb'
+ - 'spec/requests/api/jobs_spec.rb'
+ - 'spec/requests/api/labels_spec.rb'
+ - 'spec/requests/api/project_import_spec.rb'
+ - 'spec/requests/projects/cycle_analytics_events_spec.rb'
+
+Rails/TimeZone:
+ Enabled: true
+ Exclude:
+ - 'lib/gitlab/popen.rb'
+ - 'ee/lib/delay.rb'
+ - 'ee/lib/gitlab/elastic/helper.rb'
+ - 'ee/lib/gitlab/elastic/indexer.rb'
+ - 'ee/lib/gitlab/geo/base_request.rb'
+ - 'ee/lib/gitlab/geo/event_gap_tracking.rb'
+ - 'ee/lib/gitlab/geo/log_cursor/events/design_repository_updated_event.rb'
+ - 'ee/lib/gitlab/geo/log_cursor/events/repository_updated_event.rb'
+ - 'ee/lib/gitlab/geo/log_cursor/logger.rb'
+ - 'ee/lib/gitlab/geo/oauth/login_state.rb'
+ - 'ee/lib/gitlab/prometheus/queries/cluster_query.rb'
+ - 'ee/lib/gitlab/prometheus/queries/packet_flow_query.rb'
+ - 'ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/job_activity_spec.rb'
+ - 'ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb'
+ - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_summary_spec.rb'
+ - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/ldap/access_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/smartcard/san_extension_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/smartcard/session_spec.rb'
+ - 'ee/spec/lib/gitlab/background_migration/fix_orphan_promoted_issues_spec.rb'
+ - 'ee/spec/lib/gitlab/ci/pipeline/chain/limit/job_activity_spec.rb'
+ - 'ee/spec/lib/gitlab/elastic/client_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/base_request_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/cache_invalidation_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/container_repository_updated_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/design_repository_updated_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/hashed_storage_attachments_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/hashed_storage_migrated_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/job_artifact_deleted_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/lfs_object_deleted_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/repositories_changed_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_created_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_deleted_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_renamed_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/reset_checksum_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/upload_deleted_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/logger_spec.rb'
+ - 'ee/spec/lib/gitlab/git_access_spec.rb'
+ - 'ee/spec/lib/gitlab/prometheus/queries/additional_metrics_deployment_query_spec.rb'
+ - 'ee/spec/lib/gitlab/prometheus/queries/cluster_query_spec.rb'
+ - 'ee/spec/lib/gitlab/prometheus/queries/packet_flow_query_spec.rb'
+ - 'lib/api/helpers.rb'
+ - 'lib/api/sidekiq_metrics.rb'
+ - 'lib/backup/manager.rb'
+ - 'lib/bitbucket_server/representation/base.rb'
+ - 'lib/gitlab/auth/current_user_mode.rb'
+ - 'lib/gitlab/auth/ldap/access.rb'
+ - 'lib/gitlab/chaos.rb'
+ - 'lib/gitlab/checks/timed_logger.rb'
+ - 'lib/gitlab/ci/ansi2json/line.rb'
+ - 'lib/gitlab/ci/pipeline/chain/sequence.rb'
+ - 'lib/gitlab/ci/pipeline/duration.rb'
+ - 'lib/gitlab/cycle_analytics/summary/deployment_frequency.rb'
+ - 'lib/gitlab/database.rb'
+ - 'lib/gitlab/external_authorization/access.rb'
+ - 'lib/gitlab/external_authorization/cache.rb'
+ - 'lib/gitlab/gitaly_client.rb'
+ - 'lib/gitlab/gitaly_client/ref_service.rb'
+ - 'lib/gitlab/github_import/representation.rb'
+ - 'lib/gitlab/grape_logging/loggers/queue_duration_logger.rb'
+ - 'lib/gitlab/health_checks/base_abstract_check.rb'
+ - 'lib/gitlab/import_export.rb'
+ - 'lib/gitlab/instrumentation/elasticsearch_transport.rb'
+ - 'lib/gitlab/instrumentation/redis_interceptor.rb'
+ - 'lib/gitlab/instrumentation_helper.rb'
+ - 'lib/gitlab/kubernetes/helm/certificate.rb'
+ - 'lib/gitlab/lfs_token.rb'
+ - 'lib/gitlab/loop_helpers.rb'
+ - 'lib/gitlab/phabricator_import/representation/task.rb'
+ - 'lib/gitlab/prometheus/queries/additional_metrics_environment_query.rb'
+ - 'lib/gitlab/prometheus/queries/matched_metric_query.rb'
+ - 'lib/gitlab/prometheus_client.rb'
+ - 'lib/gitlab/sherlock/transaction.rb'
+ - 'lib/gitlab/task_helpers.rb'
+ - 'lib/gitlab/x509/tag.rb'
+ - 'lib/grafana/time_window.rb'
+ - 'lib/json_web_token/token.rb'
+ - 'lib/object_storage/direct_upload.rb'
+ - 'lib/quality/seeders/issues.rb'
+ - 'lib/rspec_flaky/flaky_example.rb'
+ - 'lib/rspec_flaky/report.rb'
+ - 'lib/tasks/gitlab/assets.rake'
+ - 'lib/tasks/gitlab/backup.rake'
+ - 'lib/tasks/gitlab/cleanup.rake'
+ - 'lib/tasks/gitlab/list_repos.rake'
+ - 'spec/lib/api/helpers_spec.rb'
+ - 'spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb'
+ - 'spec/lib/gitlab/app_json_logger_spec.rb'
+ - 'spec/lib/gitlab/app_text_logger_spec.rb'
+ - 'spec/lib/gitlab/auth/current_user_mode_spec.rb'
+ - 'spec/lib/gitlab/background_migration/recalculate_project_authorizations_spec.rb'
+ - 'spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb'
+ - 'spec/lib/gitlab/bitbucket_import/importer_spec.rb'
+ - 'spec/lib/gitlab/bitbucket_server_import/importer_spec.rb'
+ - 'spec/lib/gitlab/checks/timed_logger_spec.rb'
+ - 'spec/lib/gitlab/ci/cron_parser_spec.rb'
+ - 'spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb'
+ - 'spec/lib/gitlab/cycle_analytics/usage_data_spec.rb'
+ - 'spec/lib/gitlab/data_builder/note_spec.rb'
+ - 'spec/lib/gitlab/database/background_migration_job_spec.rb'
+ - 'spec/lib/gitlab/database_spec.rb'
+ - 'spec/lib/gitlab/discussions_diff/file_collection_spec.rb'
+ - 'spec/lib/gitlab/external_authorization/access_spec.rb'
+ - 'spec/lib/gitlab/external_authorization/cache_spec.rb'
+ - 'spec/lib/gitlab/external_authorization/logger_spec.rb'
+ - 'spec/lib/gitlab/fogbugz_import/importer_spec.rb'
+ - 'spec/lib/gitlab/git/branch_spec.rb'
+ - 'spec/lib/gitlab/git/commit_spec.rb'
+ - 'spec/lib/gitlab/git/repository_spec.rb'
+ - 'spec/lib/gitlab/git_access_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/issue_importer_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/issues_importer_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/note_importer_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/releases_importer_spec.rb'
+ - 'spec/lib/gitlab/github_import/representation/diff_note_spec.rb'
+ - 'spec/lib/gitlab/github_import/representation/issue_spec.rb'
+ - 'spec/lib/gitlab/github_import/representation/note_spec.rb'
+ - 'spec/lib/gitlab/github_import/representation/pull_request_spec.rb'
+ - 'spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb'
+ - 'spec/lib/gitlab/grape_logging/loggers/cloudflare_logger_spec.rb'
+ - 'spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb'
+ - 'spec/lib/gitlab/graphql_logger_spec.rb'
+ - 'spec/lib/gitlab/graphs/commits_spec.rb'
+ - 'spec/lib/gitlab/import_export/project/relation_factory_spec.rb'
+ - 'spec/lib/gitlab/instrumentation_helper_spec.rb'
+ - 'spec/lib/gitlab/json_logger_spec.rb'
+ - 'spec/lib/gitlab/lfs_token_spec.rb'
+ - 'spec/lib/gitlab/log_timestamp_formatter_spec.rb'
+ - 'spec/lib/gitlab/middleware/rails_queue_duration_spec.rb'
+ - 'spec/lib/gitlab/omniauth_logging/json_formatter_spec.rb'
+ - 'spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb'
+ - 'spec/lib/gitlab/phabricator_import/representation/task_spec.rb'
+ - 'spec/lib/gitlab/prometheus/queries/additional_metrics_deployment_query_spec.rb'
+ - 'spec/lib/gitlab/prometheus/queries/deployment_query_spec.rb'
+ - 'spec/lib/gitlab/prometheus/queries/validate_query_spec.rb'
+ - 'spec/lib/gitlab/sherlock/transaction_spec.rb'
+ - 'spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb'
+ - 'spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb'
+ - 'spec/lib/gitlab/updated_notes_paginator_spec.rb'
+ - 'spec/lib/gitlab/utils/json_size_estimator_spec.rb'
+ - 'spec/lib/gitlab/x509/signature_spec.rb'
+ - 'spec/lib/grafana/time_window_spec.rb'
+ - 'spec/lib/json_web_token/hmac_token_spec.rb'
+ - 'spec/lib/rspec_flaky/flaky_example_spec.rb'
+ - 'spec/lib/rspec_flaky/listener_spec.rb'
+ - 'spec/lib/rspec_flaky/report_spec.rb'
+
+RSpec/TimecopFreeze:
+ Exclude:
+ - 'ee/spec/controllers/admin/application_settings_controller_spec.rb'
+ - 'ee/spec/controllers/projects/security/network_policies_controller_spec.rb'
+ - 'ee/spec/features/admin/admin_reset_pipeline_minutes_spec.rb'
+ - 'ee/spec/features/boards/sidebar_spec.rb'
+ - 'ee/spec/features/groups/analytics/cycle_analytics/filters_and_data_spec.rb'
+ - 'ee/spec/features/groups/iteration_spec.rb'
+ - 'ee/spec/features/projects/mirror_spec.rb'
+ - 'ee/spec/features/projects/services/prometheus_custom_metrics_spec.rb'
+ - 'ee/spec/finders/productivity_analytics_finder_spec.rb'
+ - 'ee/spec/frontend/fixtures/analytics.rb'
+ - 'ee/spec/helpers/vulnerabilities_helper_spec.rb'
+ - 'ee/spec/lib/analytics/merge_request_metrics_refresh_spec.rb'
+ - 'ee/spec/lib/analytics/productivity_analytics_request_params_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/populate_vulnerability_historical_statistics_spec.rb'
+ - 'ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb'
+ - 'ee/spec/lib/gitlab/analytics/cycle_analytics/group_stage_time_summary_spec.rb'
+ - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary_spec.rb'
+ - 'ee/spec/lib/gitlab/analytics/type_of_work/tasks_by_type_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/group_saml/sso_enforcer_spec.rb'
+ - 'ee/spec/lib/gitlab/database/load_balancing/host_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/base_request_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/git_push_http_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/oauth/login_state_spec.rb'
+ - 'ee/spec/lib/gitlab/insights/reducers/count_per_period_reducer_spec.rb'
+ - 'ee/spec/lib/gitlab/prometheus/queries/additional_metrics_environment_query_spec.rb'
+ - 'ee/spec/lib/gitlab/prometheus/queries/cluster_query_spec.rb'
+ - 'ee/spec/migrations/populate_vulnerability_historical_statistics_for_year_spec.rb'
+ - 'ee/spec/migrations/remove_duplicated_cs_findings_spec.rb'
+ - 'ee/spec/migrations/remove_duplicated_cs_findings_without_vulnerability_id_spec.rb'
+ - 'ee/spec/migrations/schedule_fix_orphan_promoted_issues_spec.rb'
+ - 'ee/spec/migrations/schedule_merge_request_any_approval_rule_migration_spec.rb'
+ - 'ee/spec/migrations/schedule_populate_resolved_on_default_branch_column_spec.rb'
+ - 'ee/spec/migrations/schedule_populate_vulnerability_historical_statistics_spec.rb'
+ - 'ee/spec/migrations/schedule_project_any_approval_rule_migration_spec.rb'
+ - 'ee/spec/migrations/set_resolved_state_on_vulnerabilities_spec.rb'
+ - 'ee/spec/migrations/20190926180443_schedule_epic_issues_after_epics_move_spec.rb'
+ - 'ee/spec/models/analytics/cycle_analytics/group_level_spec.rb'
+ - 'ee/spec/models/burndown_spec.rb'
+ - 'ee/spec/models/ee/namespace_spec.rb'
+ - 'ee/spec/models/geo/project_registry_spec.rb'
+ - 'ee/spec/models/merge_train_spec.rb'
+ - 'ee/spec/models/productivity_analytics_spec.rb'
+ - 'ee/spec/models/project_spec.rb'
+ - 'ee/spec/models/vulnerabilities/export_spec.rb'
+ - 'ee/spec/requests/api/vulnerabilities_spec.rb'
+ - 'ee/spec/services/geo/file_download_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/confirm_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/dismiss_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/resolve_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/revert_to_detected_service_spec.rb'
+ - 'ee/spec/services/vulnerability_exports/export_service_spec.rb'
+ - 'ee/spec/support/shared_contexts/lib/gitlab/insights/reducers/reducers_shared_contexts.rb'
+ - 'qa/spec/support/repeater_spec.rb'
+ - 'spec/features/profiles/active_sessions_spec.rb'
+ - 'spec/features/projects/environments/environment_metrics_spec.rb'
+ - 'spec/features/users/active_sessions_spec.rb'
+ - 'spec/lib/atlassian/jira_connect/client_spec.rb'
+ - 'spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb'
+ - 'spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb'
+ - 'spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb'
+ - 'spec/lib/gitlab/anonymous_session_spec.rb'
+ - 'spec/lib/gitlab/auth/unique_ips_limiter_spec.rb'
+ - 'spec/lib/gitlab/checks/timed_logger_spec.rb'
+ - 'spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb'
+ - 'spec/lib/gitlab/cycle_analytics/usage_data_spec.rb'
+ - 'spec/lib/gitlab/instrumentation_helper_spec.rb'
+ - 'spec/lib/gitlab/omniauth_logging/json_formatter_spec.rb'
+ - 'spec/lib/gitlab/puma_logging/json_formatter_spec.rb'
+ - 'spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb'
+ - 'spec/lib/json_web_token/hmac_token_spec.rb'
+ - 'spec/lib/rspec_flaky/flaky_example_spec.rb'
+ - 'spec/lib/rspec_flaky/listener_spec.rb'
+ - 'spec/models/active_session_spec.rb'
+ - 'spec/models/container_repository_spec.rb'
+ - 'spec/models/pages/lookup_path_spec.rb'
+ - 'spec/models/project_feature_usage_spec.rb'
+ - 'spec/requests/api/v3/github_spec.rb'
+ - 'spec/serializers/entity_date_helper_spec.rb'
+ - 'spec/support/cycle_analytics_helpers/test_generation.rb'
+ - 'spec/support/helpers/cycle_analytics_helpers.rb'
+ - 'spec/support/helpers/javascript_fixtures_helpers.rb'
+ - 'spec/support/shared_contexts/rack_attack_shared_context.rb'
+ - 'spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb'
+ - 'spec/workers/concerns/reenqueuer_spec.rb'
+ - 'spec/workers/metrics/dashboard/prune_old_annotations_worker_spec.rb'
+
+RSpec/TimecopTravel:
+ Exclude:
+ - 'ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/git_push_http_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/jwt_request_decoder_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb'
+ - 'ee/spec/models/broadcast_message_spec.rb'
+ - 'ee/spec/models/burndown_spec.rb'
+ - 'qa/spec/support/repeater_spec.rb'
+ - 'spec/features/users/terms_spec.rb'
+ - 'spec/lib/feature_spec.rb'
+ - 'spec/models/broadcast_message_spec.rb'
+ - 'spec/models/concerns/issuable_spec.rb'
+ - 'spec/requests/api/ci/runner/jobs_trace_spec.rb'
+ - 'spec/requests/api/issues/put_projects_issues_spec.rb'
+ - 'spec/support/shared_contexts/cache_allowed_users_in_namespace_shared_context.rb'
+ - 'spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb'
+ - 'spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb'
+ - 'spec/workers/concerns/reenqueuer_spec.rb'
+ - 'spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index cf29b7cb1d1..293c8fccf33 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1,38 +1,49 @@
# This configuration was generated by
-# `rubocop --auto-gen-config --exclude-limit 10000`
-# on 2020-08-17 21:05:54 +1200 using RuboCop version 0.82.0.
+# `rubocop --auto-gen-config`
+# on 2020-10-29 17:35:37 UTC using RuboCop version 0.89.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
-# Offense count: 308
+# Offense count: 310
# Cop supports --auto-correct.
Capybara/CurrentPathExpectation:
Enabled: false
-# Offense count: 1715
+# Offense count: 210
+Capybara/VisibilityMatcher:
+ Enabled: false
+
+# Offense count: 1903
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: with_first_argument, with_fixed_indentation
Layout/ArgumentAlignment:
Enabled: false
-# Offense count: 413
+# Offense count: 49
+# Cop supports --auto-correct.
+# Configuration parameters: AllowAliasSyntax, AllowedMethods.
+# AllowedMethods: alias_method, public, protected, private
+Layout/EmptyLinesAroundAttributeAccessor:
+ Enabled: false
+
+# Offense count: 610
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: special_inside_parentheses, consistent, align_brackets
Layout/FirstArrayElementIndentation:
Enabled: false
-# Offense count: 1218
+# Offense count: 1535
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: special_inside_parentheses, consistent, align_braces
Layout/FirstHashElementIndentation:
Enabled: false
-# Offense count: 2164
+# Offense count: 2754
# Cop supports --auto-correct.
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
# SupportedHashRocketStyles: key, separator, table
@@ -41,33 +52,33 @@ Layout/FirstHashElementIndentation:
Layout/HashAlignment:
Enabled: false
-# Offense count: 9396
+# Offense count: 64
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Layout/LineLength:
Max: 1313
-# Offense count: 94
+# Offense count: 118
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: aligned, indented
Layout/MultilineOperationIndentation:
Enabled: false
-# Offense count: 36
+# Offense count: 52
# Cop supports --auto-correct.
Layout/SpaceAroundMethodCallOperator:
Enabled: false
-# Offense count: 642
+# Offense count: 790
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: require_no_space, require_space
Layout/SpaceInLambdaLiteral:
Enabled: false
-# Offense count: 926
+# Offense count: 1110
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
# SupportedStyles: space, no_space
@@ -75,24 +86,90 @@ Layout/SpaceInLambdaLiteral:
Layout/SpaceInsideBlockBraces:
Enabled: false
-# Offense count: 401
+# Offense count: 501
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: space, no_space
Layout/SpaceInsideParens:
Enabled: false
+# Offense count: 18
+Lint/BinaryOperatorWithIdenticalOperands:
+ Exclude:
+ - 'app/finders/concerns/time_frame_filter.rb'
+ - 'ee/spec/lib/ee/gitlab/application_context_spec.rb'
+ - 'spec/helpers/visibility_level_helper_spec.rb'
+ - 'spec/lib/gitlab/conan_token_spec.rb'
+ - 'spec/lib/gitlab/danger/sidekiq_queues_spec.rb'
+ - 'spec/lib/gitlab/git/conflict/parser_spec.rb'
+ - 'spec/lib/gitlab/graphql/lazy_spec.rb'
+ - 'spec/models/ci/build_trace_chunk_spec.rb'
+ - 'spec/models/clusters/platforms/kubernetes_spec.rb'
+ - 'spec/models/concerns/where_composite_spec.rb'
+ - 'spec/models/metrics/dashboard/annotation_spec.rb'
+ - 'spec/models/repository_spec.rb'
+ - 'spec/models/ssh_host_key_spec.rb'
+
+# Offense count: 9
+# Cop supports --auto-correct.
+Lint/DeprecatedOpenSSLConstant:
+ Exclude:
+ - 'app/services/clusters/kubernetes/configure_istio_ingress_service.rb'
+ - 'ee/lib/gitlab/geo/oauth/logout_state.rb'
+ - 'lib/gitlab/conan_token.rb'
+ - 'lib/gitlab/gitaly_client.rb'
+ - 'lib/gitlab/kubernetes/helm/certificate.rb'
+ - 'lib/gitlab/kubernetes/helm/v2/certificate.rb'
+ - 'spec/lib/gitlab/conan_token_spec.rb'
+ - 'spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb'
+ - 'spec/support/helpers/smime_helper.rb'
+ - 'spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb'
+
+# Offense count: 1
+Lint/FloatComparison:
+ Exclude:
+ - 'ee/app/models/ee/namespace.rb'
+
# Offense count: 157
# Configuration parameters: MaximumRangeSize.
Lint/MissingCopEnableDirective:
Enabled: false
-# Offense count: 27
+# Offense count: 14
+Lint/MixedRegexpCaptureTypes:
+ Exclude:
+ - 'app/models/alert_management/alert.rb'
+ - 'app/models/project_services/ewm_service.rb'
+ - 'app/uploaders/file_uploader.rb'
+ - 'ee/lib/gitlab/code_owners/reference_extractor.rb'
+ - 'lib/gitlab/ci/pipeline/expression/lexeme/string.rb'
+ - 'lib/gitlab/dependency_linker/gemfile_linker.rb'
+ - 'lib/gitlab/diff/inline_diff.rb'
+ - 'lib/gitlab/diff/suggestions_parser.rb'
+ - 'lib/gitlab/github_import/representation/note.rb'
+ - 'lib/gitlab/metrics/system.rb'
+ - 'lib/gitlab/request_profiler/profile.rb'
+ - 'lib/gitlab/slash_commands/issue_move.rb'
+ - 'lib/gitlab/slash_commands/issue_new.rb'
+ - 'lib/gitlab/slash_commands/run.rb'
+
+# Offense count: 1
+# Cop supports --auto-correct.
+Lint/NonDeterministicRequireOrder:
+ Exclude:
+ - 'rubocop/rubocop.rb'
+
+# Offense count: 118
# Cop supports --auto-correct.
Lint/RedundantCopDisableDirective:
Enabled: false
# Offense count: 1
+Lint/SelfAssignment:
+ Exclude:
+ - 'spec/lib/gitlab/search_context/builder_spec.rb'
+
+# Offense count: 1
# Cop supports --auto-correct.
Lint/SendWithMixinArgument:
Exclude:
@@ -105,13 +182,34 @@ Lint/StructNewOverride:
- 'app/serializers/environment_serializer.rb'
- 'lib/gitlab/ci/pipeline/duration.rb'
-# Offense count: 65
+# Offense count: 1
+Lint/UnreachableLoop:
+ Exclude:
+ - 'qa/qa/runtime/feature.rb'
+
+# Offense count: 5
+# Configuration parameters: IgnoredMethods.
+Metrics/AbcSize:
+ Max: 59
+
+# Offense count: 13
+# Configuration parameters: IgnoredMethods.
+Metrics/CyclomaticComplexity:
+ Max: 25
+
+# Offense count: 13
+# Configuration parameters: IgnoredMethods.
+Metrics/PerceivedComplexity:
+ Max: 25
+
+# Offense count: 1
# Cop supports --auto-correct.
Migration/DepartmentName:
- Enabled: false
+ Exclude:
+ - 'app/models/commit.rb'
-# Offense count: 156
-# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
+# Offense count: 171
+# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, Regex, IgnoreExecutableScripts, AllowedAcronyms.
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
Naming/FileName:
Enabled: false
@@ -127,7 +225,7 @@ Naming/HeredocDelimiterCase:
- 'spec/support/helpers/repo_helpers.rb'
- 'spec/support/helpers/seed_repo.rb'
-# Offense count: 239
+# Offense count: 263
# Configuration parameters: ForbiddenDelimiters.
# ForbiddenDelimiters: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$))
Naming/HeredocDelimiterNaming:
@@ -135,19 +233,30 @@ Naming/HeredocDelimiterNaming:
# Offense count: 5
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
-# AllowedNames: io, id, to, by, on, in, at, ip, db, os, pp
+# AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to
Naming/MethodParameterName:
Exclude:
- 'lib/gitlab/diff/inline_diff.rb'
- 'spec/support/helpers/key_generator_helper.rb'
-# Offense count: 162
+# Offense count: 191
# Cop supports --auto-correct.
# Configuration parameters: PreferredName.
Naming/RescuedExceptionsVariableName:
Enabled: false
-# Offense count: 20
+# Offense count: 1
+# Cop supports --auto-correct.
+Performance/AncestorsInclude:
+ Exclude:
+ - 'lib/gitlab/ci/config/extendable/entry.rb'
+
+# Offense count: 28
+# Configuration parameters: MinSize.
+Performance/CollectionLiteralInLoop:
+ Enabled: false
+
+# Offense count: 19
# Cop supports --auto-correct.
Performance/Count:
Exclude:
@@ -159,78 +268,152 @@ Performance/Count:
- 'spec/lib/gitlab/git/tree_spec.rb'
- 'spec/models/ci/build_spec.rb'
- 'spec/support/matchers/exceed_query_limit.rb'
+ - 'spec/support_specs/helpers/active_record/query_recorder_spec.rb'
-# Offense count: 25
+# Offense count: 15
+# Cop supports --auto-correct.
+# Configuration parameters: SafeMultiline.
+Performance/DeletePrefix:
+ Exclude:
+ - 'app/helpers/submodule_helper.rb'
+ - 'app/workers/concerns/application_worker.rb'
+ - 'ee/lib/gitlab/geo/git_ssh_proxy.rb'
+ - 'lib/banzai/filter/repository_link_filter.rb'
+ - 'lib/gitlab/auth/ldap/dn.rb'
+ - 'lib/gitlab/gfm/uploads_rewriter.rb'
+ - 'lib/gitlab/git/ref.rb'
+ - 'lib/gitlab/project_template.rb'
+ - 'lib/gitlab/repo_path.rb'
+ - 'lib/gitlab/setup_helper.rb'
+ - 'lib/gitlab/time_tracking_formatter.rb'
+ - 'spec/controllers/projects/artifacts_controller_spec.rb'
+ - 'spec/lib/gitlab/gfm/uploads_rewriter_spec.rb'
+ - 'spec/support/helpers/test_env.rb'
+
+# Offense count: 6
+# Cop supports --auto-correct.
+# Configuration parameters: SafeMultiline.
+Performance/DeleteSuffix:
+ Exclude:
+ - 'app/helpers/submodule_helper.rb'
+ - 'app/workers/concerns/application_worker.rb'
+ - 'ee/app/models/geo/upload_registry.rb'
+ - 'ee/app/workers/geo/file_download_dispatch_worker/attachment_job_finder.rb'
+ - 'lib/gitlab/repo_path.rb'
+ - 'lib/sentry/client/issue.rb'
+
+# Offense count: 13
# Cop supports --auto-correct.
Performance/Detect:
Exclude:
- 'ee/spec/controllers/projects/dependencies_controller_spec.rb'
+ - 'ee/spec/requests/api/dependencies_spec.rb'
+ - 'qa/qa/runtime/feature.rb'
- 'spec/lib/gitlab/git/tree_spec.rb'
- 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- 'spec/models/event_spec.rb'
- - 'spec/requests/api/jobs_spec.rb'
-# Offense count: 11832
+# Offense count: 19
+# Cop supports --auto-correct.
+# Configuration parameters: AutoCorrect.
+Performance/StringInclude:
+ Exclude:
+ - 'app/helpers/groups_helper.rb'
+ - 'app/models/snippet_repository.rb'
+ - 'config/initializers/macos.rb'
+ - 'config/spring.rb'
+ - 'ee/app/models/ee/container_registry/event.rb'
+ - 'ee/lib/gitlab/auth/smartcard/certificate.rb'
+ - 'lib/gitlab/database/migration_helpers.rb'
+ - 'lib/kramdown/parser/atlassian_document_format.rb'
+ - 'lib/prometheus/pid_provider.rb'
+ - 'qa/qa/ee/page/merge_request/show.rb'
+ - 'qa/qa/specs/runner.rb'
+ - 'spec/features/projects/jobs_spec.rb'
+ - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
+ - 'spec/spec_helper.rb'
+ - 'spec/support_specs/helpers/active_record/query_recorder_spec.rb'
+
+# Offense count: 9
+# Cop supports --auto-correct.
+Performance/Sum:
+ Exclude:
+ - 'app/models/application_setting_implementation.rb'
+ - 'app/models/ci/pipeline.rb'
+ - 'ee/spec/lib/gitlab/elastic/bulk_indexer_spec.rb'
+ - 'lib/declarative_policy/rule.rb'
+ - 'lib/declarative_policy/runner.rb'
+ - 'lib/gitlab/sherlock/transaction.rb'
+ - 'lib/gitlab/usage_data.rb'
+
+# Offense count: 13879
# Configuration parameters: Prefixes.
# Prefixes: when, with, without
RSpec/ContextWording:
Enabled: false
-# Offense count: 1121
+# Offense count: 4
+# Configuration parameters: CustomIncludeMethods.
+RSpec/EmptyExampleGroup:
+ Exclude:
+ - 'ee/spec/services/personal_access_tokens/revoke_invalid_tokens_spec.rb'
+ - 'spec/services/projects/prometheus/alerts/notify_service_spec.rb'
+
+# Offense count: 1310
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: method_call, block
RSpec/ExpectChange:
Enabled: false
-# Offense count: 47
RSpec/ExpectGitlabTracking:
Exclude:
- - 'ee/spec/controllers/groups/analytics/coverage_reports_controller_spec.rb'
- - 'ee/spec/controllers/projects/settings/operations_controller_spec.rb'
- - 'ee/spec/controllers/registrations_controller_spec.rb'
- 'ee/spec/requests/api/visual_review_discussions_spec.rb'
- 'ee/spec/services/epics/issue_promote_service_spec.rb'
- 'spec/controllers/groups/registry/repositories_controller_spec.rb'
- - 'spec/controllers/groups_controller_spec.rb'
- 'spec/controllers/projects/registry/repositories_controller_spec.rb'
- 'spec/controllers/projects/registry/tags_controller_spec.rb'
- 'spec/controllers/projects/settings/operations_controller_spec.rb'
- - 'spec/controllers/registrations_controller_spec.rb'
- 'spec/lib/api/helpers_spec.rb'
- - 'spec/lib/gitlab/experimentation_spec.rb'
- - 'spec/mailers/notify_spec.rb'
- - 'spec/models/project_services/prometheus_service_spec.rb'
- 'spec/requests/api/project_container_repositories_spec.rb'
- - 'spec/services/clusters/applications/check_installation_progress_service_spec.rb'
- - 'spec/services/issues/zoom_link_service_spec.rb'
- - 'spec/support/helpers/snowplow_helpers.rb'
- 'spec/support/shared_examples/controllers/trackable_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/container_repositories_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/discussions_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/packages_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/tracking_shared_examples.rb'
- - 'spec/support/snowplow.rb'
-# Offense count: 751
+# Offense count: 888
RSpec/ExpectInHook:
Enabled: false
-# Offense count: 2188
+# Offense count: 15945
+# Configuration parameters: AllowSubject.
+RSpec/MultipleMemoizedHelpers:
+ Max: 40
+
+# Offense count: 2297
# Cop supports --auto-correct.
# Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers.
# SupportedStyles: inflected, explicit
RSpec/PredicateMatcher:
Enabled: false
-# Offense count: 635
+# Offense count: 98
+RSpec/RepeatedExampleGroupBody:
+ Enabled: false
+
+# Offense count: 213
+RSpec/RepeatedExampleGroupDescription:
+ Enabled: false
+
+# Offense count: 636
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: and_return, block
RSpec/ReturnFromStub:
Enabled: false
-# Offense count: 518
+# Offense count: 574
+# Cop supports --auto-correct.
RSpec/ScatteredLet:
Enabled: false
@@ -240,6 +423,34 @@ RSpec/ScatteredSetup:
- 'spec/requests/api/jobs_spec.rb'
# Offense count: 10
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: symbols, strings
+RSpec/VariableDefinition:
+ Exclude:
+ - 'spec/initializers/mail_encoding_patch_spec.rb'
+
+# Offense count: 25
+# Configuration parameters: EnforcedStyle, IgnoredPatterns.
+# SupportedStyles: snake_case, camelCase
+RSpec/VariableName:
+ Exclude:
+ - 'spec/features/projects/import_export/import_file_spec.rb'
+ - 'spec/features/task_lists_spec.rb'
+ - 'spec/initializers/mail_encoding_patch_spec.rb'
+ - 'spec/lib/gitlab/experimentation_spec.rb'
+ - 'spec/models/board_spec.rb'
+ - 'spec/support/shared_contexts/url_shared_context.rb'
+ - 'spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb'
+ - 'spec/support/shared_examples/services/boards/boards_list_service_shared_examples.rb'
+
+# Offense count: 27
+# Cop supports --auto-correct.
+# Configuration parameters: Include.
+# Include: app/models/**/*.rb
+Rails/ActiveRecordCallbacksOrder:
+ Enabled: false
+
+# Offense count: 10
# Cop supports --auto-correct.
Rails/ApplicationController:
Exclude:
@@ -261,41 +472,63 @@ Rails/BelongsTo:
- 'app/models/deployment.rb'
- 'app/models/environment.rb'
-# Offense count: 71
+# Offense count: 84
# Configuration parameters: Database, Include.
# SupportedDatabases: mysql, postgresql
# Include: db/migrate/*.rb
Rails/BulkChangeTable:
Enabled: false
-# Offense count: 208
+# Offense count: 151
+# Cop supports --auto-correct.
+Rails/ContentTag:
+ Enabled: false
+
+# Offense count: 270
# Configuration parameters: Include.
# Include: db/migrate/*.rb
Rails/CreateTableWithTimestamps:
Enabled: false
-# Offense count: 346
+# Offense count: 323
# Configuration parameters: EnforcedStyle.
# SupportedStyles: slashes, arguments
Rails/FilePath:
Enabled: false
-# Offense count: 264
+# Offense count: 15
+# Cop supports --auto-correct.
+Rails/FindById:
+ Exclude:
+ - 'app/controllers/projects/pipelines_controller.rb'
+ - 'app/services/concerns/deploy_token_methods.rb'
+ - 'ee/app/controllers/ee/groups/group_members_controller.rb'
+ - 'ee/lib/api/audit_events.rb'
+ - 'ee/lib/api/merge_request_approval_rules.rb'
+ - 'ee/lib/ee/api/groups.rb'
+ - 'ee/lib/ee/api/projects.rb'
+ - 'ee/spec/finders/audit_log_finder_spec.rb'
+ - 'lib/api/snippets.rb'
+ - 'spec/finders/concerns/finder_methods_spec.rb'
+ - 'spec/finders/concerns/finder_with_cross_project_access_spec.rb'
+
+# Offense count: 329
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasManyOrHasOneDependent:
Enabled: false
-# Offense count: 467
+# Offense count: 507
# Configuration parameters: Include.
# Include: app/helpers/**/*.rb
Rails/HelperInstanceVariable:
Enabled: false
-# Offense count: 15
+# Offense count: 17
# Cop supports --auto-correct.
Rails/IndexBy:
Exclude:
+ - 'app/graphql/types/design_management/design_fields.rb'
- 'app/models/ci/pipeline.rb'
- 'app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb'
- 'ee/app/services/projects/update_mirror_service.rb'
@@ -305,21 +538,27 @@ Rails/IndexBy:
- 'ee/lib/gitlab/analytics/type_of_work/tasks_by_type.rb'
- 'ee/lib/gitlab/elastic/document_reference.rb'
- 'ee/lib/gitlab/group_plans_preloader.rb'
+ - 'lib/gitlab/danger/sidekiq_queues.rb'
- 'lib/gitlab/database/count/reltuples_count_strategy.rb'
- 'lib/gitlab/language_detection.rb'
-# Offense count: 36
+# Offense count: 44
# Cop supports --auto-correct.
Rails/IndexWith:
Enabled: false
-# Offense count: 105
+# Offense count: 1
+Rails/Inquiry:
+ Exclude:
+ - 'spec/helpers/labels_helper_spec.rb'
+
+# Offense count: 112
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/InverseOf:
Enabled: false
-# Offense count: 55
+# Offense count: 60
# Configuration parameters: Include.
# Include: app/controllers/**/*.rb
Rails/LexicallyScopedActionFilter:
@@ -333,177 +572,77 @@ Rails/LinkToBlank:
- 'app/helpers/wiki_helper.rb'
- 'ee/app/helpers/ee/user_callouts_helper.rb'
-# Offense count: 34
+# Offense count: 1
+# Cop supports --auto-correct.
+# Configuration parameters: Include.
+# Include: app/mailers/**/*.rb
+Rails/MailerName:
+ Exclude:
+ - 'app/mailers/notify.rb'
+
+# Offense count: 48
+# Cop supports --auto-correct.
+Rails/NegateInclude:
+ Enabled: false
+
+# Offense count: 41
+# Cop supports --auto-correct.
+Rails/Pick:
+ Enabled: false
+
+# Offense count: 113
+# Cop supports --auto-correct.
+Rails/Pluck:
+ Enabled: false
+
+# Offense count: 38
+# Cop supports --auto-correct.
# Configuration parameters: Include.
# Include: **/Rakefile, **/*.rake
Rails/RakeEnvironment:
Enabled: false
-# Offense count: 926
-# Configuration parameters: Blacklist, Whitelist.
-# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters
-Rails/SkipsModelValidations:
+# Offense count: 52
+# Cop supports --auto-correct.
+Rails/RedundantForeignKey:
Enabled: false
-# Offense count: 308
+Rails/RenderInline:
+ Exclude:
+ - 'ee/app/controllers/sitemap_controller.rb'
+
+# Offense count: 4
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
-# SupportedStyles: strict, flexible
-Rails/TimeZone:
- Enabled: true
+# SupportedStyles: conservative, aggressive
+Rails/ShortI18n:
Exclude:
- - 'lib/gitlab/popen.rb'
- - 'ee/lib/delay.rb'
- - 'ee/lib/gitlab/elastic/helper.rb'
- - 'ee/lib/gitlab/elastic/indexer.rb'
- - 'ee/lib/gitlab/geo/base_request.rb'
- - 'ee/lib/gitlab/geo/event_gap_tracking.rb'
- - 'ee/lib/gitlab/geo/log_cursor/events/design_repository_updated_event.rb'
- - 'ee/lib/gitlab/geo/log_cursor/events/repository_updated_event.rb'
- - 'ee/lib/gitlab/geo/log_cursor/logger.rb'
- - 'ee/lib/gitlab/geo/oauth/login_state.rb'
- - 'ee/lib/gitlab/prometheus/queries/cluster_query.rb'
- - 'ee/lib/gitlab/prometheus/queries/packet_flow_query.rb'
- - 'ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb'
- - 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/job_activity_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_summary_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary_spec.rb'
- - 'ee/spec/lib/gitlab/auth/ldap/access_spec.rb'
- - 'ee/spec/lib/gitlab/auth/smartcard/san_extension_spec.rb'
- - 'ee/spec/lib/gitlab/auth/smartcard/session_spec.rb'
- - 'ee/spec/lib/gitlab/background_migration/fix_orphan_promoted_issues_spec.rb'
- - 'ee/spec/lib/gitlab/ci/pipeline/chain/limit/job_activity_spec.rb'
- - 'ee/spec/lib/gitlab/elastic/client_spec.rb'
- - 'ee/spec/lib/gitlab/geo/base_request_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/cache_invalidation_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/container_repository_updated_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/design_repository_updated_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/hashed_storage_attachments_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/hashed_storage_migrated_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/job_artifact_deleted_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/lfs_object_deleted_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repositories_changed_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_created_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_deleted_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_renamed_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/reset_checksum_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/upload_deleted_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/logger_spec.rb'
- - 'ee/spec/lib/gitlab/git_access_spec.rb'
- - 'ee/spec/lib/gitlab/prometheus/queries/additional_metrics_deployment_query_spec.rb'
- - 'ee/spec/lib/gitlab/prometheus/queries/cluster_query_spec.rb'
- - 'ee/spec/lib/gitlab/prometheus/queries/packet_flow_query_spec.rb'
- - 'lib/api/helpers.rb'
- - 'lib/api/sidekiq_metrics.rb'
- - 'lib/backup/manager.rb'
- - 'lib/bitbucket_server/representation/base.rb'
- - 'lib/gitlab/auth/current_user_mode.rb'
- - 'lib/gitlab/auth/ldap/access.rb'
- - 'lib/gitlab/chaos.rb'
- - 'lib/gitlab/checks/timed_logger.rb'
- - 'lib/gitlab/ci/ansi2json/line.rb'
- - 'lib/gitlab/ci/pipeline/chain/sequence.rb'
- - 'lib/gitlab/ci/pipeline/duration.rb'
- - 'lib/gitlab/cycle_analytics/summary/deployment_frequency.rb'
- - 'lib/gitlab/database.rb'
- - 'lib/gitlab/external_authorization/access.rb'
- - 'lib/gitlab/external_authorization/cache.rb'
- - 'lib/gitlab/gitaly_client.rb'
- - 'lib/gitlab/gitaly_client/ref_service.rb'
- - 'lib/gitlab/github_import/representation.rb'
- - 'lib/gitlab/grape_logging/loggers/queue_duration_logger.rb'
- - 'lib/gitlab/health_checks/base_abstract_check.rb'
- - 'lib/gitlab/import_export.rb'
- - 'lib/gitlab/instrumentation/elasticsearch_transport.rb'
- - 'lib/gitlab/instrumentation/redis_interceptor.rb'
- - 'lib/gitlab/instrumentation_helper.rb'
- - 'lib/gitlab/kubernetes/helm/certificate.rb'
- - 'lib/gitlab/lfs_token.rb'
- - 'lib/gitlab/loop_helpers.rb'
- - 'lib/gitlab/phabricator_import/representation/task.rb'
- - 'lib/gitlab/prometheus/queries/additional_metrics_environment_query.rb'
- - 'lib/gitlab/prometheus/queries/matched_metric_query.rb'
- - 'lib/gitlab/prometheus_client.rb'
- - 'lib/gitlab/sherlock/transaction.rb'
- - 'lib/gitlab/task_helpers.rb'
- - 'lib/gitlab/x509/tag.rb'
- - 'lib/grafana/time_window.rb'
- - 'lib/json_web_token/token.rb'
- - 'lib/object_storage/direct_upload.rb'
- - 'lib/quality/seeders/issues.rb'
- - 'lib/rspec_flaky/flaky_example.rb'
- - 'lib/rspec_flaky/report.rb'
- - 'lib/tasks/gitlab/assets.rake'
- - 'lib/tasks/gitlab/backup.rake'
- - 'lib/tasks/gitlab/cleanup.rake'
- - 'lib/tasks/gitlab/list_repos.rake'
- - 'spec/lib/api/helpers_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb'
- - 'spec/lib/gitlab/app_json_logger_spec.rb'
- - 'spec/lib/gitlab/app_text_logger_spec.rb'
- - 'spec/lib/gitlab/auth/current_user_mode_spec.rb'
- - 'spec/lib/gitlab/background_migration/recalculate_project_authorizations_spec.rb'
- - 'spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb'
- - 'spec/lib/gitlab/bitbucket_import/importer_spec.rb'
- - 'spec/lib/gitlab/bitbucket_server_import/importer_spec.rb'
- - 'spec/lib/gitlab/checks/timed_logger_spec.rb'
- - 'spec/lib/gitlab/ci/cron_parser_spec.rb'
- - 'spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb'
- - 'spec/lib/gitlab/cycle_analytics/usage_data_spec.rb'
- - 'spec/lib/gitlab/data_builder/note_spec.rb'
- - 'spec/lib/gitlab/database/background_migration_job_spec.rb'
- - 'spec/lib/gitlab/database_spec.rb'
- - 'spec/lib/gitlab/discussions_diff/file_collection_spec.rb'
- - 'spec/lib/gitlab/external_authorization/access_spec.rb'
- - 'spec/lib/gitlab/external_authorization/cache_spec.rb'
- - 'spec/lib/gitlab/external_authorization/logger_spec.rb'
- - 'spec/lib/gitlab/fogbugz_import/importer_spec.rb'
- - 'spec/lib/gitlab/git/branch_spec.rb'
- - 'spec/lib/gitlab/git/commit_spec.rb'
- - 'spec/lib/gitlab/git/repository_spec.rb'
- - 'spec/lib/gitlab/git_access_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/issue_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/issues_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/note_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/releases_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/representation/diff_note_spec.rb'
- - 'spec/lib/gitlab/github_import/representation/issue_spec.rb'
- - 'spec/lib/gitlab/github_import/representation/note_spec.rb'
- - 'spec/lib/gitlab/github_import/representation/pull_request_spec.rb'
- - 'spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb'
- - 'spec/lib/gitlab/grape_logging/loggers/cloudflare_logger_spec.rb'
- - 'spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb'
- - 'spec/lib/gitlab/graphql_logger_spec.rb'
- - 'spec/lib/gitlab/graphs/commits_spec.rb'
- - 'spec/lib/gitlab/import_export/project/relation_factory_spec.rb'
- - 'spec/lib/gitlab/instrumentation_helper_spec.rb'
- - 'spec/lib/gitlab/json_logger_spec.rb'
- - 'spec/lib/gitlab/lfs_token_spec.rb'
- - 'spec/lib/gitlab/log_timestamp_formatter_spec.rb'
- - 'spec/lib/gitlab/middleware/rails_queue_duration_spec.rb'
- - 'spec/lib/gitlab/omniauth_logging/json_formatter_spec.rb'
- - 'spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb'
- - 'spec/lib/gitlab/phabricator_import/representation/task_spec.rb'
- - 'spec/lib/gitlab/prometheus/queries/additional_metrics_deployment_query_spec.rb'
- - 'spec/lib/gitlab/prometheus/queries/deployment_query_spec.rb'
- - 'spec/lib/gitlab/prometheus/queries/validate_query_spec.rb'
- - 'spec/lib/gitlab/sherlock/transaction_spec.rb'
- - 'spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb'
- - 'spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb'
- - 'spec/lib/gitlab/updated_notes_paginator_spec.rb'
- - 'spec/lib/gitlab/utils/json_size_estimator_spec.rb'
- - 'spec/lib/gitlab/x509/signature_spec.rb'
- - 'spec/lib/grafana/time_window_spec.rb'
- - 'spec/lib/json_web_token/hmac_token_spec.rb'
- - 'spec/lib/rspec_flaky/flaky_example_spec.rb'
- - 'spec/lib/rspec_flaky/listener_spec.rb'
- - 'spec/lib/rspec_flaky/report_spec.rb'
+ - 'app/models/project_services/chat_message/pipeline_message.rb'
+ - 'app/uploaders/content_type_whitelist.rb'
+ - 'spec/views/shared/runners/show.html.haml_spec.rb'
+
+# Offense count: 1043
+# Configuration parameters: ForbiddenMethods, AllowedMethods.
+# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all
+Rails/SkipsModelValidations:
+ Enabled: false
+
+# Offense count: 202
+# Cop supports --auto-correct.
+Rails/SquishedSQLHeredocs:
+ Enabled: false
+
+# Offense count: 37
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: exists, where
+Rails/WhereExists:
+ Enabled: false
+
+# Offense count: 21
+# Cop supports --auto-correct.
+Rails/WhereNot:
+ Enabled: false
# Offense count: 8
# Cop supports --auto-correct.
@@ -515,13 +654,58 @@ Security/YAMLLoad:
- 'spec/initializers/secret_token_spec.rb'
- 'spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb'
-# Offense count: 148
+# Offense count: 240
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: separated, grouped
+Style/AccessorGrouping:
+ Enabled: false
+
+# Offense count: 13
+# Cop supports --auto-correct.
+Style/ArrayCoercion:
+ Exclude:
+ - 'app/controllers/admin/ci/variables_controller.rb'
+ - 'app/controllers/groups/variables_controller.rb'
+ - 'app/controllers/import/bulk_imports_controller.rb'
+ - 'app/controllers/projects/variables_controller.rb'
+ - 'db/migrate/20190620105427_change_null_private_profile_to_false.rb'
+ - 'db/post_migrate/20190812070645_migrate_private_profile_nulls.rb'
+ - 'db/post_migrate/20200311130802_schedule_populate_user_highest_roles_table.rb'
+ - 'db/post_migrate/20200805152108_migrate_null_external_diff_store_to_local_value.rb'
+ - 'db/post_migrate/20200806173633_migrate_null_package_files_file_store_to_local_value.rb'
+ - 'ee/app/services/geo/blob_verification_secondary_service.rb'
+ - 'ee/app/services/geo/repository_verification_secondary_service.rb'
+ - 'ee/lib/ee/banzai/pipeline/gfm_pipeline.rb'
+ - 'spec/support/helpers/lfs_http_helpers.rb'
+
+# Offense count: 176
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: percent_q, bare_percent
Style/BarePercentLiterals:
Enabled: false
+# Offense count: 6
+# Cop supports --auto-correct.
+Style/BisectedAttrAccessor:
+ Exclude:
+ - 'lib/system_check/base_check.rb'
+ - 'qa/qa/resource/api_fabricator.rb'
+
+# Offense count: 37
+# Cop supports --auto-correct.
+Style/CaseLikeIf:
+ Enabled: false
+
+# Offense count: 1
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions.
+# SupportedStyles: assign_to_condition, assign_inside_condition
+Style/ConditionalAssignment:
+ Exclude:
+ - 'lib/gitlab/database.rb'
+
# Offense count: 5
# Cop supports --auto-correct.
Style/EachWithObject:
@@ -532,808 +716,221 @@ Style/EachWithObject:
- 'lib/gitlab/i18n/po_linter.rb'
- 'lib/gitlab/import_export/members_mapper.rb'
-# Offense count: 46
+# Offense count: 53
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: empty, nil, both
Style/EmptyElse:
Enabled: false
-# Offense count: 170
+# Offense count: 193
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: compact, expanded
Style/EmptyMethod:
Enabled: false
-# Offense count: 431
+# Offense count: 2
+# Cop supports --auto-correct.
+Style/ExpandPathArguments:
+ Exclude:
+ - 'cable/config.ru'
+ - 'config.ru'
+
+# Offense count: 118
+# Cop supports --auto-correct.
+Style/ExplicitBlockArgument:
+ Enabled: false
+
+# Offense count: 521
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: format, sprintf, percent
Style/FormatString:
Enabled: false
-# Offense count: 769
+# Offense count: 48
+# Cop supports --auto-correct.
+Style/GlobalStdStream:
+ Enabled: false
+
+# Offense count: 835
# Configuration parameters: MinBodyLength.
Style/GuardClause:
Enabled: false
-# Offense count: 47
+# Offense count: 93
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: braces, no_braces
+Style/HashAsLastArrayItem:
+ Enabled: false
+
+# Offense count: 55
# Cop supports --auto-correct.
Style/HashEachMethods:
Enabled: false
-# Offense count: 31
+# Offense count: 30
# Configuration parameters: AllowIfModifier.
Style/IfInsideElse:
Enabled: false
-# Offense count: 1313
+# Offense count: 1798
# Cop supports --auto-correct.
Style/IfUnlessModifier:
Enabled: false
-# Offense count: 377
+# Offense count: 447
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: line_count_dependent, lambda, literal
Style/Lambda:
Enabled: false
-# Offense count: 17
-Style/MethodMissingSuper:
- Enabled: false
-
-# Offense count: 17
+# Offense count: 18
Style/MissingRespondToMissing:
Enabled: false
-# Offense count: 5
-Style/MixinUsage:
- Exclude:
- - 'spec/factories/ci/builds.rb'
- - 'spec/factories/ci/job_artifacts.rb'
- - 'spec/factories/lfs_objects.rb'
- - 'spec/factories/notes.rb'
- - 'spec/lib/gitlab/import_export/version_checker_spec.rb'
-
-# Offense count: 29
+# Offense count: 32
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, MinBodyLength.
# SupportedStyles: skip_modifier_ifs, always
Style/Next:
Enabled: false
-# Offense count: 89
+# Offense count: 95
# Cop supports --auto-correct.
# Configuration parameters: EnforcedOctalStyle.
# SupportedOctalStyles: zero_with_o, zero_only
Style/NumericLiteralPrefix:
Enabled: false
-# Offense count: 117
+# Offense count: 132
# Cop supports --auto-correct.
Style/ParallelAssignment:
Enabled: false
-# Offense count: 2035
+# Offense count: 2473
# Cop supports --auto-correct.
# Configuration parameters: PreferredDelimiters.
Style/PercentLiteralDelimiters:
Enabled: false
-# Offense count: 200
+# Offense count: 246
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: compact, exploded
Style/RaiseArgs:
Enabled: false
-# Offense count: 246
+# Offense count: 66
+# Cop supports --auto-correct.
+Style/RedundantAssignment:
+ Enabled: false
+
+# Offense count: 26
+# Cop supports --auto-correct.
+# Configuration parameters: SafeForConstants.
+Style/RedundantFetchBlock:
+ Exclude:
+ - 'app/finders/admin/projects_finder.rb'
+ - 'lib/gitlab/diff/file.rb'
+ - 'spec/lib/gitlab/json_cache_spec.rb'
+ - 'spec/lib/gitlab/metrics/dashboard/cache_spec.rb'
+ - 'spec/lib/gitlab/null_request_store_spec.rb'
+ - 'spec/lib/gitlab/safe_request_store_spec.rb'
+
+# Offense count: 26
+# Cop supports --auto-correct.
+Style/RedundantFileExtensionInRequire:
+ Enabled: false
+
+# Offense count: 260
# Cop supports --auto-correct.
Style/RedundantFreeze:
Enabled: false
-# Offense count: 123
+# Offense count: 167
# Cop supports --auto-correct.
Style/RedundantInterpolation:
Enabled: false
-# Offense count: 801
+# Offense count: 11
+# Cop supports --auto-correct.
+Style/RedundantRegexpCharacterClass:
+ Exclude:
+ - 'app/models/concerns/taskable.rb'
+ - 'ee/lib/ee/gitlab/path_regex.rb'
+ - 'lib/gitlab/authorized_keys.rb'
+ - 'lib/gitlab/fogbugz_import/repository.rb'
+ - 'lib/gitlab/prometheus/internal.rb'
+ - 'lib/gitlab/quick_actions/substitution_definition.rb'
+ - 'lib/gitlab/regex.rb'
+ - 'spec/features/merge_request/user_views_open_merge_request_spec.rb'
+ - 'spec/tasks/gitlab/usage_data_rake_spec.rb'
+
+# Offense count: 250
+# Cop supports --auto-correct.
+Style/RedundantRegexpEscape:
+ Enabled: false
+
+# Offense count: 868
# Cop supports --auto-correct.
Style/RedundantSelf:
Enabled: false
-# Offense count: 120
+# Offense count: 179
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
# SupportedStyles: slashes, percent_r, mixed
Style/RegexpLiteral:
Enabled: false
-# Offense count: 46
+# Offense count: 49
# Cop supports --auto-correct.
Style/RescueModifier:
Enabled: false
-# Offense count: 286
+# Offense count: 329
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: implicit, explicit
Style/RescueStandardError:
Enabled: false
-# Offense count: 102
+# Offense count: 104
+# Cop supports --auto-correct.
+Style/SingleArgumentDig:
+ Enabled: false
+
+# Offense count: 47
+# Cop supports --auto-correct.
+Style/SlicingWithRange:
+ Enabled: false
+
+# Offense count: 109
# Cop supports --auto-correct.
# Configuration parameters: .
# SupportedStyles: use_perl_names, use_english_names
Style/SpecialGlobalVars:
EnforcedStyle: use_perl_names
-# Offense count: 93
+# Offense count: 516
+# Cop supports --auto-correct.
+Style/StringConcatenation:
+ Enabled: false
+
+# Offense count: 103
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiteralsInInterpolation:
Enabled: false
-# Offense count: 233
+# Offense count: 276
# Cop supports --auto-correct.
# Configuration parameters: IgnoredMethods.
# IgnoredMethods: respond_to, define_method
Style/SymbolProc:
Enabled: false
-
-# Offense count: 2362
-# Cop supports --auto-correct.
-# Configuration parameters: AllowImplicitReturn, AllowedReceivers.
-Rails/SaveBang:
- Exclude:
- - 'ee/spec/controllers/projects/merge_requests_controller_spec.rb'
- - 'ee/spec/controllers/subscriptions_controller_spec.rb'
- - 'ee/spec/frontend/fixtures/analytics.rb'
- - 'ee/spec/graphql/resolvers/vulnerabilities_resolver_spec.rb'
- - 'ee/spec/initializers/fog_google_https_private_urls_spec.rb'
- - 'ee/spec/lib/analytics/merge_request_metrics_calculator_spec.rb'
- - 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
- - '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'
- - 'ee/spec/lib/gitlab/auth/o_auth/user_spec.rb'
- - 'ee/spec/lib/gitlab/auth/saml/user_spec.rb'
- - '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_spec.rb'
- - 'ee/spec/lib/gitlab/git_access_spec.rb'
- - 'ee/spec/lib/gitlab/import_export/group/relation_factory_spec.rb'
- - 'ee/spec/lib/gitlab/mirror_spec.rb'
- - 'ee/spec/mailers/notify_spec.rb'
- - 'ee/spec/migrations/fix_any_approver_rule_for_projects_spec.rb'
- - 'ee/spec/migrations/geo/migrate_ci_job_artifacts_to_separate_registry_spec.rb'
- - 'ee/spec/migrations/geo/migrate_lfs_objects_to_separate_registry_spec.rb'
- - 'ee/spec/migrations/schedule_merge_request_any_approval_rule_migration_spec.rb'
- - 'ee/spec/migrations/schedule_project_any_approval_rule_migration_spec.rb'
- - 'ee/spec/models/application_setting_spec.rb'
- - 'ee/spec/models/approval_merge_request_rule_spec.rb'
- - 'ee/spec/models/approval_project_rule_spec.rb'
- - 'ee/spec/models/burndown_spec.rb'
- - 'ee/spec/models/ci/pipeline_spec.rb'
- - 'ee/spec/models/ci/subscriptions/project_spec.rb'
- - 'ee/spec/models/ee/appearance_spec.rb'
- - 'ee/spec/models/ee/ci/job_artifact_spec.rb'
- - 'ee/spec/models/ee/protected_branch_spec.rb'
- - 'ee/spec/models/ee/protected_ref_access_spec.rb'
- - 'ee/spec/models/ee/protected_ref_spec.rb'
- - 'ee/spec/models/elasticsearch_indexed_namespace_spec.rb'
- - 'ee/spec/models/environment_spec.rb'
- - 'ee/spec/models/epic_spec.rb'
- - 'ee/spec/models/geo/project_registry_spec.rb'
- - 'ee/spec/models/geo_node_spec.rb'
- - 'ee/spec/models/geo_node_status_spec.rb'
- - 'ee/spec/models/gitlab_subscription_spec.rb'
- - 'ee/spec/models/group_spec.rb'
- - 'ee/spec/models/issue_spec.rb'
- - 'ee/spec/models/label_note_spec.rb'
- - 'ee/spec/models/lfs_object_spec.rb'
- - 'ee/spec/models/license_spec.rb'
- - 'ee/spec/models/merge_request_spec.rb'
- - 'ee/spec/models/merge_train_spec.rb'
- - 'spec/models/packages/package_spec.rb'
- - 'ee/spec/models/project_ci_cd_setting_spec.rb'
- - 'ee/spec/models/project_spec.rb'
- - 'ee/spec/models/protected_environment_spec.rb'
- - 'ee/spec/models/repository_spec.rb'
- - 'ee/spec/models/scim_identity_spec.rb'
- - 'ee/spec/models/scim_oauth_access_token_spec.rb'
- - 'ee/spec/models/upload_spec.rb'
- - 'ee/spec/models/user_preference_spec.rb'
- - 'ee/spec/models/user_spec.rb'
- - 'ee/spec/models/visible_approvable_spec.rb'
- - 'ee/spec/models/vulnerabilities/feedback_spec.rb'
- - 'ee/spec/models/vulnerabilities/issue_link_spec.rb'
- - 'ee/spec/presenters/audit_event_presenter_spec.rb'
- - 'ee/spec/presenters/epic_presenter_spec.rb'
- - 'ee/spec/requests/api/boards_spec.rb'
- - 'ee/spec/requests/api/epic_issues_spec.rb'
- - 'ee/spec/requests/api/epic_links_spec.rb'
- - 'ee/spec/requests/api/epics_spec.rb'
- - 'ee/spec/requests/api/geo_nodes_spec.rb'
- - 'ee/spec/requests/api/geo_spec.rb'
- - 'ee/spec/requests/api/graphql/group/epics_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/epic_tree/reorder_spec.rb'
- - 'ee/spec/requests/api/groups_spec.rb'
- - 'ee/spec/requests/api/issues_spec.rb'
- - 'ee/spec/requests/api/ldap_group_links_spec.rb'
- - 'ee/spec/requests/api/merge_request_approval_rules_spec.rb'
- - 'ee/spec/requests/api/merge_request_approvals_spec.rb'
- - 'ee/spec/requests/api/merge_requests_spec.rb'
- - 'ee/spec/requests/api/project_approvals_spec.rb'
- - 'ee/spec/requests/api/projects_spec.rb'
- - 'ee/spec/requests/api/protected_branches_spec.rb'
- - 'ee/spec/requests/api/scim_spec.rb'
- - 'ee/spec/requests/api/todos_spec.rb'
- - '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/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'
- - 'ee/spec/services/ee/issuable/clone/attributes_rewriter_spec.rb'
- - 'ee/spec/services/ee/issuable/common_system_notes_service_spec.rb'
- - 'ee/spec/services/ee/issues/update_service_spec.rb'
- - 'ee/spec/services/ee/merge_requests/refresh_service_spec.rb'
- - '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/epic_links/create_service_spec.rb'
- - 'ee/spec/services/epics/close_service_spec.rb'
- - 'ee/spec/services/epics/issue_promote_service_spec.rb'
- - 'ee/spec/services/epics/reopen_service_spec.rb'
- - 'ee/spec/services/epics/tree_reorder_service_spec.rb'
- - 'ee/spec/services/epics/update_dates_service_spec.rb'
- - 'ee/spec/services/epics/update_service_spec.rb'
- - 'ee/spec/services/geo/blob_verification_secondary_service_spec.rb'
- - 'ee/spec/services/geo/files_expire_service_spec.rb'
- - 'ee/spec/services/geo/metrics_update_service_spec.rb'
- - 'ee/spec/services/geo/registry_consistency_service_spec.rb'
- - 'ee/spec/services/geo/repository_verification_secondary_service_spec.rb'
- - '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_trains/refresh_merge_request_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'
- - 'ee/spec/services/status_page/trigger_publish_service_spec.rb'
- - 'ee/spec/services/todo_service_spec.rb'
- - 'ee/spec/services/update_build_minutes_service_spec.rb'
- - 'ee/spec/services/vulnerability_feedback/create_service_spec.rb'
- - 'ee/spec/support/protected_tags/access_control_shared_examples.rb'
- - 'ee/spec/support/shared_examples/features/protected_branches_access_control_shared_examples.rb'
- - '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/policies/protected_environments_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'
- - 'ee/spec/workers/elastic_namespace_rollout_worker_spec.rb'
- - 'ee/spec/workers/geo/container_repository_sync_dispatch_worker_spec.rb'
- - 'ee/spec/workers/geo/file_download_dispatch_worker_spec.rb'
- - 'ee/spec/workers/geo/prune_event_log_worker_spec.rb'
- - 'ee/spec/workers/geo/registry_sync_worker_spec.rb'
- - 'ee/spec/workers/geo/repository_shard_sync_worker_spec.rb'
- - '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'
- - 'spec/controllers/admin/impersonations_controller_spec.rb'
- - 'spec/controllers/admin/runners_controller_spec.rb'
- - 'spec/controllers/admin/services_controller_spec.rb'
- - 'spec/controllers/boards/issues_controller_spec.rb'
- - 'spec/controllers/groups/milestones_controller_spec.rb'
- - 'spec/controllers/groups/runners_controller_spec.rb'
- - 'spec/controllers/groups/uploads_controller_spec.rb'
- - 'spec/controllers/groups_controller_spec.rb'
- - 'spec/controllers/oauth/authorizations_controller_spec.rb'
- - 'spec/controllers/omniauth_callbacks_controller_spec.rb'
- - 'spec/controllers/profiles/emails_controller_spec.rb'
- - 'spec/controllers/profiles/notifications_controller_spec.rb'
- - 'spec/controllers/projects/artifacts_controller_spec.rb'
- - 'spec/controllers/projects/cycle_analytics/events_controller_spec.rb'
- - 'spec/controllers/projects/cycle_analytics_controller_spec.rb'
- - 'spec/controllers/projects/discussions_controller_spec.rb'
- - 'spec/controllers/projects/forks_controller_spec.rb'
- - 'spec/controllers/projects/group_links_controller_spec.rb'
- - 'spec/controllers/projects/imports_controller_spec.rb'
- - 'spec/controllers/projects/issues_controller_spec.rb'
- - 'spec/controllers/projects/labels_controller_spec.rb'
- - 'spec/controllers/projects/merge_requests_controller_spec.rb'
- - 'spec/controllers/projects/milestones_controller_spec.rb'
- - 'spec/controllers/projects/notes_controller_spec.rb'
- - 'spec/controllers/projects/pipelines_controller_spec.rb'
- - 'spec/controllers/projects/releases/evidences_controller_spec.rb'
- - 'spec/controllers/projects/runners_controller_spec.rb'
- - 'spec/controllers/projects/starrers_controller_spec.rb'
- - 'spec/controllers/projects/uploads_controller_spec.rb'
- - 'spec/controllers/projects_controller_spec.rb'
- - 'spec/controllers/sent_notifications_controller_spec.rb'
- - 'spec/controllers/sessions_controller_spec.rb'
- - 'spec/controllers/users_controller_spec.rb'
- - 'spec/factories_spec.rb'
- - 'spec/features/admin/admin_appearance_spec.rb'
- - 'spec/features/admin/admin_labels_spec.rb'
- - 'spec/features/admin/admin_mode/login_spec.rb'
- - 'spec/features/admin/admin_runners_spec.rb'
- - 'spec/features/admin/admin_sees_project_statistics_spec.rb'
- - 'spec/features/admin/admin_sees_projects_statistics_spec.rb'
- - 'spec/features/admin/admin_users_impersonation_tokens_spec.rb'
- - 'spec/features/admin/admin_users_spec.rb'
- - 'spec/features/boards/sidebar_spec.rb'
- - 'spec/features/calendar_spec.rb'
- - 'spec/features/commits_spec.rb'
- - 'spec/features/dashboard/datetime_on_tooltips_spec.rb'
- - 'spec/features/dashboard/issuables_counter_spec.rb'
- - 'spec/features/dashboard/project_member_activity_index_spec.rb'
- - 'spec/features/dashboard/projects_spec.rb'
- - 'spec/features/error_tracking/user_sees_error_index_spec.rb'
- - 'spec/features/groups/members/request_access_spec.rb'
- - 'spec/features/issuables/close_reopen_report_toggle_spec.rb'
- - 'spec/features/issues/bulk_assignment_labels_spec.rb'
- - 'spec/features/issues/gfm_autocomplete_spec.rb'
- - 'spec/features/issues/issue_sidebar_spec.rb'
- - 'spec/features/issues/note_polling_spec.rb'
- - 'spec/features/issues/user_creates_branch_and_merge_request_spec.rb'
- - 'spec/features/issues/user_creates_confidential_merge_request_spec.rb'
- - 'spec/features/issues/user_edits_issue_spec.rb'
- - 'spec/features/issues/user_filters_issues_spec.rb'
- - 'spec/features/issues/user_sees_live_update_spec.rb'
- - 'spec/features/issues/user_sorts_issues_spec.rb'
- - 'spec/features/profiles/emails_spec.rb'
- - 'spec/features/profiles/password_spec.rb'
- - 'spec/features/profiles/personal_access_tokens_spec.rb'
- - 'spec/features/projects/features_visibility_spec.rb'
- - 'spec/features/projects/fork_spec.rb'
- - 'spec/features/projects/jobs/permissions_spec.rb'
- - 'spec/features/projects/jobs_spec.rb'
- - 'spec/features/projects/members/user_requests_access_spec.rb'
- - 'spec/features/projects/pages_lets_encrypt_spec.rb'
- - 'spec/features/projects/pages_spec.rb'
- - 'spec/features/projects/pipelines/pipeline_spec.rb'
- - 'spec/features/projects/pipelines/pipelines_spec.rb'
- - 'spec/features/projects/remote_mirror_spec.rb'
- - 'spec/features/projects/services/user_activates_slack_notifications_spec.rb'
- - 'spec/features/projects/settings/access_tokens_spec.rb'
- - 'spec/features/projects/show/user_sees_deletion_failure_message_spec.rb'
- - 'spec/features/projects/user_sees_sidebar_spec.rb'
- - 'spec/features/projects/wiki/user_updates_wiki_page_spec.rb'
- - 'spec/features/projects/wiki/user_views_wiki_page_spec.rb'
- - 'spec/features/projects/wiki/users_views_asciidoc_page_with_includes_spec.rb'
- - 'spec/features/runners_spec.rb'
- - 'spec/features/security/project/internal_access_spec.rb'
- - 'spec/features/security/project/private_access_spec.rb'
- - 'spec/features/security/project/public_access_spec.rb'
- - 'spec/features/users/login_spec.rb'
- - 'spec/features/users/show_spec.rb'
- - 'spec/frontend/fixtures/issues.rb'
- - 'spec/frontend/fixtures/merge_requests.rb'
- - 'spec/graphql/mutations/merge_requests/set_locked_spec.rb'
- - 'spec/graphql/mutations/merge_requests/set_wip_spec.rb'
- - 'spec/graphql/resolvers/boards_resolver_spec.rb'
- - 'spec/initializers/active_record_locking_spec.rb'
- - 'spec/initializers/fog_google_https_private_urls_spec.rb'
- - 'spec/lib/after_commit_queue_spec.rb'
- - 'spec/lib/backup/manager_spec.rb'
- - 'spec/lib/banzai/reference_parser/external_issue_parser_spec.rb'
- - 'spec/lib/banzai/reference_redactor_spec.rb'
- - 'spec/lib/gitlab/alerting/alert_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb'
- - 'spec/lib/gitlab/auth/ldap/user_spec.rb'
- - 'spec/lib/gitlab/auth/o_auth/user_spec.rb'
- - 'spec/lib/gitlab/auth/saml/user_spec.rb'
- - 'spec/lib/gitlab/auth_spec.rb'
- - 'spec/lib/gitlab/authorized_keys_spec.rb'
- - 'spec/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments_spec.rb'
- - 'spec/lib/gitlab/background_migration/backfill_project_repositories_spec.rb'
- - 'spec/lib/gitlab/background_migration/backfill_project_settings_spec.rb'
- - 'spec/lib/gitlab/background_migration/backfill_push_rules_id_in_projects_spec.rb'
- - 'spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb'
- - 'spec/lib/gitlab/background_migration/digest_column_spec.rb'
- - 'spec/lib/gitlab/background_migration/encrypt_columns_spec.rb'
- - 'spec/lib/gitlab/background_migration/fix_cross_project_label_links_spec.rb'
- - 'spec/lib/gitlab/background_migration/fix_projects_without_project_feature_spec.rb'
- - 'spec/lib/gitlab/background_migration/fix_projects_without_prometheus_service_spec.rb'
- - 'spec/lib/gitlab/background_migration/fix_user_namespace_names_spec.rb'
- - 'spec/lib/gitlab/background_migration/fix_user_project_route_names_spec.rb'
- - 'spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb'
- - 'spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb'
- - 'spec/lib/gitlab/background_migration/link_lfs_objects_projects_spec.rb'
- - 'spec/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data_spec.rb'
- - 'spec/lib/gitlab/background_migration/migrate_stage_index_spec.rb'
- - 'spec/lib/gitlab/background_migration/migrate_users_bio_to_user_details_spec.rb'
- - 'spec/lib/gitlab/background_migration/populate_canonical_emails_spec.rb'
- - 'spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb'
- - 'spec/lib/gitlab/background_migration/populate_user_highest_roles_table_spec.rb'
- - 'spec/lib/gitlab/background_migration/recalculate_project_authorizations_spec.rb'
- - 'spec/lib/gitlab/background_migration/remove_restricted_todos_spec.rb'
- - 'spec/lib/gitlab/background_migration/reset_merge_status_spec.rb'
- - 'spec/lib/gitlab/background_migration/set_confidential_note_events_on_services_spec.rb'
- - 'spec/lib/gitlab/background_migration/set_confidential_note_events_on_webhooks_spec.rb'
- - 'spec/lib/gitlab/bitbucket_server_import/importer_spec.rb'
- - 'spec/lib/gitlab/ci/ansi2json/style_spec.rb'
- - 'spec/lib/gitlab/ci/status/build/common_spec.rb'
- - 'spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb'
- - 'spec/lib/gitlab/database/custom_structure_spec.rb'
- - 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
- - 'spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb'
- - 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- - 'spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb'
- - 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
- - 'spec/lib/gitlab/git_access_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/repository_service_spec.rb'
- - 'spec/lib/gitlab/import_export/avatar_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/base/relation_factory_spec.rb'
- - 'spec/lib/gitlab/import_export/design_repo_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb'
- - 'spec/lib/gitlab/import_export/fork_spec.rb'
- - 'spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/group/relation_factory_spec.rb'
- - 'spec/lib/gitlab/import_export/group/tree_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/importer_spec.rb'
- - 'spec/lib/gitlab/import_export/lfs_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/lfs_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/members_mapper_spec.rb'
- - 'spec/lib/gitlab/import_export/project/relation_factory_spec.rb'
- - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/project/tree_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/repo_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/saver_spec.rb'
- - 'spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/uploads_manager_spec.rb'
- - 'spec/lib/gitlab/import_export/uploads_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/wiki_restorer_spec.rb'
- - 'spec/lib/gitlab/legacy_github_import/importer_spec.rb'
- - 'spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb'
- - 'spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb'
- - 'spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb'
- - 'spec/lib/gitlab/lets_encrypt/client_spec.rb'
- - 'spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb'
- - 'spec/lib/gitlab/markdown_cache/redis/store_spec.rb'
- - 'spec/lib/gitlab/middleware/go_spec.rb'
- - 'spec/lib/gitlab/shard_health_cache_spec.rb'
- - 'spec/lib/mattermost/command_spec.rb'
- - 'spec/lib/mattermost/session_spec.rb'
- - 'spec/lib/mattermost/team_spec.rb'
- - 'spec/mailers/notify_spec.rb'
- - 'spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb'
- - 'spec/migrations/20200122123016_backfill_project_settings_spec.rb'
- - 'spec/migrations/20200123155929_remove_invalid_jira_data_spec.rb'
- - 'spec/migrations/20200127090233_remove_invalid_issue_tracker_data_spec.rb'
- - 'spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb'
- - 'spec/migrations/20200313203550_remove_orphaned_chat_names_spec.rb'
- - 'spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb'
- - 'spec/migrations/20200526115436_dedup_mr_metrics_spec.rb'
- - 'spec/migrations/add_deploy_token_type_to_deploy_tokens_spec.rb'
- - 'spec/migrations/add_incident_settings_to_all_existing_projects_spec.rb'
- - 'spec/migrations/add_unique_constraint_to_approvals_user_id_and_merge_request_id_spec.rb'
- - 'spec/migrations/backfill_and_add_not_null_constraint_to_released_at_column_on_releases_table_spec.rb'
- - 'spec/migrations/backfill_imported_snippet_repositories_spec.rb'
- - 'spec/migrations/backfill_releases_table_updated_at_and_add_not_null_constraints_to_timestamps_spec.rb'
- - 'spec/migrations/backfill_snippet_repositories_spec.rb'
- - 'spec/migrations/encrypt_plaintext_attributes_on_application_settings_spec.rb'
- - 'spec/migrations/enqueue_reset_merge_status_second_run_spec.rb'
- - 'spec/migrations/enqueue_reset_merge_status_spec.rb'
- - 'spec/migrations/fill_file_store_lfs_objects_spec.rb'
- - 'spec/migrations/fill_store_uploads_spec.rb'
- - 'spec/migrations/fix_null_type_labels_spec.rb'
- - 'spec/migrations/fix_pool_repository_source_project_id_spec.rb'
- - 'spec/migrations/fix_projects_without_project_feature_spec.rb'
- - 'spec/migrations/fix_projects_without_prometheus_services_spec.rb'
- - 'spec/migrations/fix_wrong_pages_access_level_spec.rb'
- - 'spec/migrations/insert_project_hooks_plan_limits_spec.rb'
- - 'spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb'
- - 'spec/migrations/move_limits_from_plans_spec.rb'
- - 'spec/migrations/populate_project_statistics_packages_size_spec.rb'
- - 'spec/migrations/schedule_link_lfs_objects_projects_spec.rb'
- - 'spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb'
- - 'spec/migrations/seed_repository_storages_weighted_spec.rb'
- - 'spec/models/appearance_spec.rb'
- - 'spec/models/application_record_spec.rb'
- - 'spec/models/application_setting_spec.rb'
- - 'spec/models/clusters/applications/helm_spec.rb'
- - 'spec/models/commit_spec.rb'
- - 'spec/models/commit_status_spec.rb'
- - 'spec/models/container_repository_spec.rb'
- - 'spec/models/deploy_keys_project_spec.rb'
- - 'spec/models/deploy_token_spec.rb'
- - 'spec/models/deployment_spec.rb'
- - 'spec/models/design_management/version_spec.rb'
- - 'spec/models/diff_discussion_spec.rb'
- - 'spec/models/diff_note_spec.rb'
- - 'spec/models/email_spec.rb'
- - 'spec/models/environment_spec.rb'
- - 'spec/models/event_spec.rb'
- - 'spec/models/fork_network_spec.rb'
- - 'spec/models/generic_commit_status_spec.rb'
- - 'spec/models/grafana_integration_spec.rb'
- - 'spec/models/group_spec.rb'
- - 'spec/models/hooks/system_hook_spec.rb'
- - 'spec/models/hooks/web_hook_spec.rb'
- - 'spec/models/identity_spec.rb'
- - 'spec/models/issue/metrics_spec.rb'
- - 'spec/models/issue_spec.rb'
- - 'spec/models/jira_import_state_spec.rb'
- - 'spec/models/key_spec.rb'
- - 'spec/models/lfs_objects_project_spec.rb'
- - 'spec/models/member_spec.rb'
- - 'spec/models/members/group_member_spec.rb'
- - 'spec/models/members/project_member_spec.rb'
- - 'spec/models/merge_request_spec.rb'
- - 'spec/models/milestone_spec.rb'
- - 'spec/models/namespace_spec.rb'
- - 'spec/models/note_spec.rb'
- - 'spec/models/notification_setting_spec.rb'
- - 'spec/models/operations/feature_flag_scope_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_spec.rb'
- - 'spec/models/project_team_spec.rb'
- - 'spec/models/protectable_dropdown_spec.rb'
- - 'spec/models/redirect_route_spec.rb'
- - 'spec/models/release_spec.rb'
- - 'spec/models/remote_mirror_spec.rb'
- - 'spec/models/resource_milestone_event_spec.rb'
- - 'spec/models/route_spec.rb'
- - 'spec/models/sentry_issue_spec.rb'
- - 'spec/models/service_spec.rb'
- - 'spec/models/snippet_spec.rb'
- - 'spec/models/upload_spec.rb'
- - 'spec/models/user_preference_spec.rb'
- - 'spec/models/user_spec.rb'
- - 'spec/models/user_status_spec.rb'
- - 'spec/models/wiki_page/meta_spec.rb'
- - 'spec/models/wiki_page_spec.rb'
- - '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/ci/runner_spec.rb'
- - 'spec/requests/api/commit_statuses_spec.rb'
- - 'spec/requests/api/conan_packages_spec.rb'
- - 'spec/requests/api/deployments_spec.rb'
- - 'spec/requests/api/environments_spec.rb'
- - 'spec/requests/api/go_proxy_spec.rb'
- - 'spec/requests/api/graphql/mutations/merge_requests/set_labels_spec.rb'
- - 'spec/requests/api/graphql/user_query_spec.rb'
- - 'spec/requests/api/graphql_spec.rb'
- - 'spec/requests/api/group_import_spec.rb'
- - 'spec/requests/api/group_milestones_spec.rb'
- - 'spec/requests/api/internal/base_spec.rb'
- - 'spec/requests/api/issues/get_group_issues_spec.rb'
- - 'spec/requests/api/issues/post_projects_issues_spec.rb'
- - 'spec/requests/api/jobs_spec.rb'
- - 'spec/requests/api/labels_spec.rb'
- - 'spec/requests/api/project_import_spec.rb'
- - 'spec/requests/projects/cycle_analytics_events_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/clusters/update_service_spec.rb'
- - 'spec/services/deployments/after_create_service_spec.rb'
- - 'spec/services/design_management/generate_image_versions_service_spec.rb'
- - 'spec/services/discussions/resolve_service_spec.rb'
- - 'spec/services/draft_notes/destroy_service_spec.rb'
- - 'spec/services/emails/confirm_service_spec.rb'
- - 'spec/services/groups/destroy_service_spec.rb'
- - 'spec/services/groups/import_export/import_service_spec.rb'
- - 'spec/services/labels/promote_service_spec.rb'
- - 'spec/services/notes/create_service_spec.rb'
- - 'spec/services/notification_recipients/build_service_spec.rb'
- - 'spec/services/notification_service_spec.rb'
- - 'spec/services/packages/conan/create_package_file_service_spec.rb'
- - 'spec/services/reset_project_cache_service_spec.rb'
- - 'spec/services/resource_events/change_milestone_service_spec.rb'
- - 'spec/services/system_hooks_service_spec.rb'
- - 'spec/services/system_note_service_spec.rb'
- - 'spec/services/system_notes/issuables_service_spec.rb'
- - 'spec/services/todo_service_spec.rb'
- - 'spec/services/todos/destroy/confidential_issue_service_spec.rb'
- - 'spec/services/users/destroy_service_spec.rb'
- - 'spec/services/users/repair_ldap_blocked_service_spec.rb'
- - 'spec/services/verify_pages_domain_service_spec.rb'
- - 'spec/sidekiq/cron/job_gem_dependency_spec.rb'
-
-# Offense count: 187
-# Cop supports --auto-correct.
-RSpec/TimecopFreeze:
- Exclude:
- - 'ee/spec/controllers/admin/application_settings_controller_spec.rb'
- - 'ee/spec/controllers/projects/security/network_policies_controller_spec.rb'
- - 'ee/spec/features/admin/admin_reset_pipeline_minutes_spec.rb'
- - 'ee/spec/features/boards/sidebar_spec.rb'
- - 'ee/spec/features/groups/analytics/cycle_analytics/filters_and_data_spec.rb'
- - 'ee/spec/features/groups/iteration_spec.rb'
- - 'ee/spec/features/projects/mirror_spec.rb'
- - 'ee/spec/features/projects/services/prometheus_custom_metrics_spec.rb'
- - 'ee/spec/finders/productivity_analytics_finder_spec.rb'
- - 'ee/spec/frontend/fixtures/analytics.rb'
- - 'ee/spec/helpers/vulnerabilities_helper_spec.rb'
- - 'ee/spec/lib/analytics/merge_request_metrics_refresh_spec.rb'
- - 'ee/spec/lib/analytics/productivity_analytics_request_params_spec.rb'
- - 'ee/spec/lib/ee/gitlab/background_migration/populate_vulnerability_historical_statistics_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/group_stage_time_summary_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/type_of_work/tasks_by_type_spec.rb'
- - 'ee/spec/lib/gitlab/auth/group_saml/sso_enforcer_spec.rb'
- - 'ee/spec/lib/gitlab/database/load_balancing/host_spec.rb'
- - 'ee/spec/lib/gitlab/geo/base_request_spec.rb'
- - 'ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb'
- - 'ee/spec/lib/gitlab/geo/git_push_http_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/oauth/login_state_spec.rb'
- - 'ee/spec/lib/gitlab/insights/reducers/count_per_period_reducer_spec.rb'
- - 'ee/spec/lib/gitlab/prometheus/queries/additional_metrics_environment_query_spec.rb'
- - 'ee/spec/lib/gitlab/prometheus/queries/cluster_query_spec.rb'
- - 'ee/spec/migrations/populate_vulnerability_historical_statistics_for_year_spec.rb'
- - 'ee/spec/migrations/remove_duplicated_cs_findings_spec.rb'
- - 'ee/spec/migrations/remove_duplicated_cs_findings_without_vulnerability_id_spec.rb'
- - 'ee/spec/migrations/schedule_fix_orphan_promoted_issues_spec.rb'
- - 'ee/spec/migrations/schedule_merge_request_any_approval_rule_migration_spec.rb'
- - 'ee/spec/migrations/schedule_populate_resolved_on_default_branch_column_spec.rb'
- - 'ee/spec/migrations/schedule_populate_vulnerability_historical_statistics_spec.rb'
- - 'ee/spec/migrations/schedule_project_any_approval_rule_migration_spec.rb'
- - 'ee/spec/migrations/set_resolved_state_on_vulnerabilities_spec.rb'
- - 'ee/spec/migrations/20190926180443_schedule_epic_issues_after_epics_move_spec.rb'
- - 'ee/spec/models/analytics/cycle_analytics/group_level_spec.rb'
- - 'ee/spec/models/burndown_spec.rb'
- - 'ee/spec/models/ee/namespace_spec.rb'
- - 'ee/spec/models/geo/project_registry_spec.rb'
- - 'ee/spec/models/merge_train_spec.rb'
- - 'ee/spec/models/productivity_analytics_spec.rb'
- - 'ee/spec/models/project_spec.rb'
- - 'ee/spec/models/vulnerabilities/export_spec.rb'
- - 'ee/spec/requests/api/vulnerabilities_spec.rb'
- - 'ee/spec/services/geo/file_download_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/confirm_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/dismiss_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/resolve_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/revert_to_detected_service_spec.rb'
- - 'ee/spec/services/vulnerability_exports/export_service_spec.rb'
- - 'ee/spec/support/shared_contexts/lib/gitlab/insights/reducers/reducers_shared_contexts.rb'
- - 'qa/spec/support/repeater_spec.rb'
- - 'spec/features/profiles/active_sessions_spec.rb'
- - 'spec/features/projects/environments/environment_metrics_spec.rb'
- - 'spec/features/users/active_sessions_spec.rb'
- - 'spec/lib/atlassian/jira_connect/client_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb'
- - 'spec/lib/gitlab/anonymous_session_spec.rb'
- - 'spec/lib/gitlab/auth/unique_ips_limiter_spec.rb'
- - 'spec/lib/gitlab/checks/timed_logger_spec.rb'
- - 'spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb'
- - 'spec/lib/gitlab/cycle_analytics/usage_data_spec.rb'
- - 'spec/lib/gitlab/instrumentation_helper_spec.rb'
- - 'spec/lib/gitlab/omniauth_logging/json_formatter_spec.rb'
- - 'spec/lib/gitlab/puma_logging/json_formatter_spec.rb'
- - 'spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb'
- - 'spec/lib/json_web_token/hmac_token_spec.rb'
- - 'spec/lib/rspec_flaky/flaky_example_spec.rb'
- - 'spec/lib/rspec_flaky/listener_spec.rb'
- - 'spec/models/active_session_spec.rb'
- - 'spec/models/container_repository_spec.rb'
- - 'spec/models/pages/lookup_path_spec.rb'
- - 'spec/models/project_feature_usage_spec.rb'
- - 'spec/requests/api/v3/github_spec.rb'
- - 'spec/serializers/entity_date_helper_spec.rb'
- - 'spec/support/cycle_analytics_helpers/test_generation.rb'
- - 'spec/support/helpers/cycle_analytics_helpers.rb'
- - 'spec/support/helpers/javascript_fixtures_helpers.rb'
- - 'spec/support/shared_contexts/rack_attack_shared_context.rb'
- - 'spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb'
- - 'spec/workers/concerns/reenqueuer_spec.rb'
- - 'spec/workers/metrics/dashboard/prune_old_annotations_worker_spec.rb'
-
-# Offense count: 54
-# Cop supports --auto-correct.
-RSpec/TimecopTravel:
- Exclude:
- - 'ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb'
- - 'ee/spec/lib/gitlab/geo/git_push_http_spec.rb'
- - 'ee/spec/lib/gitlab/geo/jwt_request_decoder_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb'
- - 'ee/spec/models/broadcast_message_spec.rb'
- - 'ee/spec/models/burndown_spec.rb'
- - 'qa/spec/support/repeater_spec.rb'
- - 'spec/features/users/terms_spec.rb'
- - 'spec/lib/feature_spec.rb'
- - 'spec/models/broadcast_message_spec.rb'
- - 'spec/models/concerns/issuable_spec.rb'
- - 'spec/requests/api/ci/runner/jobs_trace_spec.rb'
- - 'spec/requests/api/issues/put_projects_issues_spec.rb'
- - 'spec/support/shared_contexts/cache_allowed_users_in_namespace_shared_context.rb'
- - 'spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb'
- - 'spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb'
- - 'spec/workers/concerns/reenqueuer_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb'
-
-# Offense count: 43
-Graphql/IDType:
- Exclude:
- - 'ee/app/graphql/ee/mutations/issues/update.rb'
- - 'ee/app/graphql/ee/types/boards/board_issue_input_base_type.rb'
- - 'ee/app/graphql/mutations/issues/set_epic.rb'
- - 'ee/app/graphql/mutations/iterations/update.rb'
- - 'ee/app/graphql/resolvers/iterations_resolver.rb'
- - 'app/graphql/mutations/boards/create.rb'
- - 'app/graphql/mutations/boards/issues/issue_move_list.rb'
- - 'app/graphql/mutations/boards/lists/update.rb'
- - 'app/graphql/mutations/issues/update.rb'
- - 'app/graphql/mutations/metrics/dashboard/annotations/delete.rb'
- - 'app/graphql/mutations/snippets/destroy.rb'
- - 'app/graphql/mutations/snippets/mark_as_spam.rb'
- - 'app/graphql/mutations/snippets/update.rb'
- - 'app/graphql/resolvers/board_lists_resolver.rb'
- - 'app/graphql/resolvers/boards_resolver.rb'
- - 'app/graphql/resolvers/design_management/design_at_version_resolver.rb'
- - 'app/graphql/resolvers/design_management/design_resolver.rb'
- - 'app/graphql/resolvers/design_management/designs_resolver.rb'
- - 'app/graphql/resolvers/design_management/version/design_at_version_resolver.rb'
- - 'app/graphql/resolvers/design_management/version_in_collection_resolver.rb'
- - 'app/graphql/resolvers/design_management/version_resolver.rb'
- - 'app/graphql/resolvers/design_management/versions_resolver.rb'
- - 'app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb'
- - 'app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb'
- - 'app/graphql/resolvers/snippets_resolver.rb'
- - 'app/graphql/resolvers/user_merge_requests_resolver.rb'
- - 'app/graphql/resolvers/user_resolver.rb'
-
-# Offense count: 86
-# Cop supports --auto-correct.
-FactoryBot/InlineAssociation:
- Exclude:
- - 'ee/spec/factories/analytics/cycle_analytics/group_stages.rb'
- - 'ee/spec/factories/geo/event_log.rb'
- - 'ee/spec/factories/groups.rb'
- - 'ee/spec/factories/merge_request_blocks.rb'
- - 'ee/spec/factories/resource_iteration_event.rb'
- - 'ee/spec/factories/resource_weight_events.rb'
- - 'ee/spec/factories/vulnerabilities/feedback.rb'
- - 'spec/factories/atlassian_identities.rb'
- - 'spec/factories/audit_events.rb'
- - 'spec/factories/design_management/design_at_version.rb'
- - 'spec/factories/design_management/designs.rb'
- - 'spec/factories/design_management/versions.rb'
- - 'spec/factories/events.rb'
- - 'spec/factories/git_wiki_commit_details.rb'
- - 'spec/factories/gitaly/commit.rb'
- - 'spec/factories/go_module_commits.rb'
- - 'spec/factories/go_module_versions.rb'
- - 'spec/factories/go_modules.rb'
- - 'spec/factories/group_group_links.rb'
- - 'spec/factories/import_export_uploads.rb'
- - 'spec/factories/merge_requests.rb'
- - 'spec/factories/notes.rb'
- - 'spec/factories/packages.rb'
- - 'spec/factories/packages/package_file.rb'
- - 'spec/factories/resource_label_events.rb'
- - 'spec/factories/resource_milestone_event.rb'
- - 'spec/factories/resource_state_event.rb'
- - 'spec/factories/sent_notifications.rb'
- - 'spec/factories/serverless/domain.rb'
- - 'spec/factories/serverless/domain_cluster.rb'
- - 'spec/factories/terraform/state.rb'
- - 'spec/factories/uploads.rb'
- - 'spec/factories/wiki_pages.rb'
diff --git a/.ruby-version b/.ruby-version
index 338a5b5d8fe..37c2961c243 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.6.6
+2.7.2
diff --git a/.scss-lint.yml b/.scss-lint.yml
index 420b15274bb..ec193e2a3db 100644
--- a/.scss-lint.yml
+++ b/.scss-lint.yml
@@ -8,6 +8,7 @@ scss_files:
exclude:
- 'app/assets/stylesheets/pages/emojis.scss'
- 'app/assets/stylesheets/startup/startup-*.scss'
+ - 'app/assets/stylesheets/lazy_bundles/select2.scss'
linters:
# Reports when you use improper spacing around ! (the "bang") in !default,
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4b6c4582b5e..9f919fc9fd6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -621,6 +621,32 @@ entry.
- Bump cluster applications CI template. !45472
+## 13.4.6 (2020-11-03)
+
+### Fixed (1 change)
+
+- Auto Deploy: fixes issues for fetching other charts from stable repo. !46531
+
+### Other (1 change)
+
+- GitLab-managed apps: Use GitLab's repo as replacement for the Helm stable repo. !44875
+
+
+## 13.4.5 (2020-11-02)
+
+### Security (9 changes)
+
+- Add CSRF protection to runner pause and resume. !1021
+- Do not expose Terraform state record in API.
+- Path traversal to RCE via LFS upload.
+- Update container_repository_name_regex to prevent catastrophic backtracking.
+- Validate nuget package names.
+- Prevent private repo from being accessed via internal Kubernetes API.
+- Validate each upload param key in multipart.rb.
+- Fix XSS vulnerability for job build dependencies.
+- Fix unauthorized user is able to access schedule pipeline variables and values.
+
+
## 13.4.4 (2020-10-15)
### Fixed (2 changes)
@@ -1279,6 +1305,37 @@ entry.
- Expand the visible highlight for collapsed diffs (re: !41393). !42343
+## 13.3.9 (2020-11-02)
+
+### Security (9 changes)
+
+- Add CSRF protection to runner pause and resume. !1021
+- Do not expose Terraform state record in API.
+- Path traversal to RCE via LFS upload.
+- Update container_repository_name_regex to prevent catastrophic backtracking.
+- Validate nuget package names.
+- Prevent private repo from being accessed via internal Kubernetes API.
+- Validate each upload param key in multipart.rb.
+- Fix XSS vulnerability for job build dependencies.
+- Fix unauthorized user is able to access schedule pipeline variables and values.
+
+
+## 13.3.8 (2020-10-21)
+
+### Fixed (2 changes)
+
+- Make SSH keys publicly accessible. !42288
+- Revert required encryption on CI runner tokens. !42623
+
+### Added (1 change)
+
+- Add missing fontawesome file icon classes. !43091
+
+### Other (1 change)
+
+- GitLab-managed apps: Use GitLab's repo as replacement for the Helm stable repo. !44875
+
+
## 13.3.4 (2020-09-02)
### Security (1 change)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 3330217f208..16e5c4e4738 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-13.5.4 \ No newline at end of file
+89c1ee804f273c9ccc7322644b9ec1cf8e38c0a4
diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION
index 1750564f270..4daad9a5c1d 100644
--- a/GITLAB_KAS_VERSION
+++ b/GITLAB_KAS_VERSION
@@ -1 +1 @@
-0.0.6
+13.6.1
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index cfc730712d5..034552a83ee 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.28.0
+1.30.0
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index fbda4b8d751..0b704f2a43a 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-13.11.0
+13.13.0
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index f66efe38785..a99caf2cdef 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-8.51.0
+8.54.0
diff --git a/Gemfile b/Gemfile
index 51f9d36cef9..d60fefe29dc 100644
--- a/Gemfile
+++ b/Gemfile
@@ -19,7 +19,7 @@ gem 'default_value_for', '~> 3.3.0'
gem 'pg', '~> 1.1'
gem 'rugged', '~> 0.28'
-gem 'grape-path-helpers', '~> 1.4'
+gem 'grape-path-helpers', '~> 1.5'
gem 'faraday', '~> 1.0'
gem 'marginalia', '~> 1.9.0'
@@ -48,7 +48,7 @@ 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 'rack-oauth2', '~> 1.16.0'
gem 'jwt', '~> 2.1.0'
# Kerberos authentication. EE-only
@@ -98,6 +98,7 @@ gem 'graphql', '~> 1.11.4'
gem 'graphiql-rails', '~> 1.4.10'
gem 'apollo_upload_server', '~> 2.0.2'
gem 'graphql-docs', '~> 1.6.0', group: [:development, :test]
+gem 'graphlient', '~> 0.4.0' # Used by BulkImport feature (group::import)
gem 'hashie'
# Disable strong_params so that Mash does not respond to :permitted?
@@ -118,7 +119,7 @@ gem 'fog-aws', '~> 3.5'
# Locked until fog-google resolves https://github.com/fog/fog-google/issues/421.
# Also see config/initializers/fog_core_patch.rb.
gem 'fog-core', '= 2.1.0'
-gem 'fog-google', '~> 1.10'
+gem 'fog-google', '~> 1.11'
gem 'fog-local', '~> 0.6'
gem 'fog-openstack', '~> 1.0'
gem 'fog-rackspace', '~> 0.1.1'
@@ -158,7 +159,7 @@ gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 2.0.10'
gem 'asciidoctor-include-ext', '~> 0.3.1', require: false
gem 'asciidoctor-plantuml', '~> 0.0.12'
-gem 'rouge', '~> 3.24.0'
+gem 'rouge', '~> 3.25.0'
gem 'truncato', '~> 0.7.11'
gem 'bootstrap_form', '~> 4.2.0'
gem 'nokogiri', '~> 1.10.9'
@@ -172,7 +173,7 @@ gem 'diffy', '~> 3.3'
gem 'diff_match_patch', '~> 0.1.0'
# Application server
-gem 'rack', '~> 2.1.4'
+gem 'rack', '~> 2.2.3'
# https://github.com/sharpstone/rack-timeout/blob/master/README.md#rails-apps-manually
gem 'rack-timeout', '~> 0.5.1', require: 'rack/timeout/base'
@@ -271,9 +272,6 @@ gem 'loofah', '~> 2.2'
# Working with license
gem 'licensee', '~> 8.9'
-# Ace editor
-gem 'ace-rails-ap', '~> 4.1.0'
-
# Detect and convert string character encoding
gem 'charlock_holmes', '~> 0.7.7'
@@ -307,13 +305,16 @@ gem 'rack-attack', '~> 6.3.0'
# Sentry integration
gem 'sentry-raven', '~> 3.0'
+# PostgreSQL query parsing
+gem 'gitlab-pg_query', '~> 1.3', require: 'pg_query'
+
gem 'premailer-rails', '~> 1.10.3'
# LabKit: Tracing and Correlation
-gem 'gitlab-labkit', '0.12.2'
+gem 'gitlab-labkit', '0.13.1'
# I18n
-gem 'ruby_parser', '~> 3.8', require: false
+gem 'ruby_parser', '~> 3.15', require: false
gem 'rails-i18n', '~> 6.0'
gem 'gettext_i18n_rails', '~> 1.8.0'
gem 'gettext_i18n_rails_js', '~> 1.3'
@@ -366,22 +367,19 @@ group :development, :test do
# Generate Fake data
gem 'ffaker', '~> 2.10'
- gem 'spring', '~> 2.0.0'
+ gem 'spring', '~> 2.1.0'
gem 'spring-commands-rspec', '~> 1.0.4'
- gem 'gitlab-styles', '~> 4.3.0', require: false
- # Pin these dependencies, otherwise a new rule could break the CI pipelines
- gem 'rubocop', '~> 0.82.0'
- gem 'rubocop-performance', '~> 1.5.2'
- gem 'rubocop-rspec', '~> 1.37.0'
+ gem 'gitlab-styles', '~> 5.1.0', require: false
- gem 'scss_lint', '~> 0.56.0', require: false
- gem 'haml_lint', '~> 0.34.0', require: false
+ gem 'scss_lint', '~> 0.59.0', require: false
+ gem 'haml_lint', '~> 0.36.0', require: false
gem 'bundler-audit', '~> 0.6.1', require: false
gem 'benchmark-ips', '~> 2.3.0', require: false
gem 'knapsack', '~> 1.17'
+ gem 'crystalball', '~> 0.7.0', require: false
gem 'simple_po_parser', '~> 1.1.2', require: false
@@ -407,7 +405,7 @@ end
group :test do
gem 'fuubar', '~> 2.2.0'
gem 'rspec-retry', '~> 0.6.1'
- gem 'rspec_profiling', '~> 0.0.5'
+ gem 'rspec_profiling', '~> 0.0.6'
gem 'rspec-parameterized', require: false
gem 'capybara', '~> 3.33.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 93670d22920..64179847dd8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -3,7 +3,6 @@ GEM
specs:
RedCloth (4.3.2)
abstract_type (0.0.7)
- ace-rails-ap (4.1.2)
acme-client (2.0.6)
faraday (>= 0.17, < 2.0.0)
actioncable (6.0.3.3)
@@ -71,7 +70,7 @@ GEM
memoizable (~> 0.4.0)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
- aes_key_wrap (1.0.1)
+ aes_key_wrap (1.1.0)
akismet (3.0.0)
android_key_attestation (0.3.0)
apollo_upload_server (2.0.2)
@@ -87,7 +86,7 @@ GEM
asciidoctor (>= 1.5.6, < 3.0.0)
asciidoctor-plantuml (0.0.12)
asciidoctor (>= 1.5.6, < 3.0.0)
- ast (2.4.0)
+ ast (2.4.1)
atlassian-jwt (0.2.0)
jwt (~> 2.1.0)
attr_encrypted (3.1.0)
@@ -133,7 +132,7 @@ GEM
coderay (>= 1.0.0)
erubi (>= 1.0.0)
rack (>= 0.9.0)
- bindata (2.4.3)
+ bindata (2.4.8)
binding_ninja (0.2.3)
bootsnap (1.4.6)
msgpack (~> 1.0)
@@ -199,6 +198,8 @@ GEM
safe_yaml (~> 1.0.0)
crass (1.0.6)
creole (0.5.0)
+ crystalball (0.7.0)
+ git
css_parser (1.7.0)
addressable
daemons (1.2.6)
@@ -368,11 +369,12 @@ GEM
excon (~> 0.58)
formatador (~> 0.2)
mime-types
- fog-google (1.10.0)
+ fog-google (1.11.0)
fog-core (<= 2.1.0)
fog-json (~> 1.2)
fog-xml (~> 0.1.0)
google-api-client (>= 0.32, < 0.34)
+ google-cloud-env (~> 1.2)
fog-json (1.2.0)
fog-core
multi_json (~> 1.10)
@@ -428,17 +430,18 @@ GEM
fog-json (~> 1.2.0)
mime-types
ms_rest_azure (~> 0.12.0)
- gitlab-labkit (0.12.2)
+ gitlab-labkit (0.13.1)
actionpack (>= 5.0.0, < 6.1.0)
activesupport (>= 5.0.0, < 6.1.0)
grpc (~> 1.19)
- jaeger-client (~> 0.10)
+ jaeger-client (~> 1.1)
opentracing (~> 0.4)
redis (> 3.0.0, < 5.0.0)
gitlab-license (1.0.0)
gitlab-mail_room (0.0.7)
gitlab-markup (1.7.1)
gitlab-net-dns (0.9.1)
+ gitlab-pg_query (1.3.0)
gitlab-puma (4.3.5.gitlab.3)
nio4r (~> 2.0)
gitlab-puma_worker_killer (0.1.1.gitlab.1)
@@ -446,12 +449,12 @@ GEM
gitlab-puma (>= 2.7, < 5)
gitlab-sidekiq-fetcher (0.5.2)
sidekiq (~> 5)
- gitlab-styles (4.3.0)
- rubocop (~> 0.82.0)
+ gitlab-styles (5.1.0)
+ rubocop (~> 0.89.1)
rubocop-gitlab-security (~> 0.1.0)
- rubocop-performance (~> 1.5.2)
- rubocop-rails (~> 2.5)
- rubocop-rspec (~> 1.36)
+ rubocop-performance (~> 1.8.1)
+ rubocop-rails (~> 2.8)
+ rubocop-rspec (~> 1.44)
gitlab_chronic_duration (0.10.6.2)
numerizer (~> 0.2)
gitlab_omniauth-ldap (2.1.1)
@@ -473,6 +476,8 @@ GEM
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.12)
+ google-cloud-env (1.4.0)
+ faraday (>= 0.17.3, < 2.0)
google-protobuf (3.12.4)
googleapis-common-protos-types (1.0.5)
google-protobuf (~> 3.11)
@@ -495,17 +500,24 @@ GEM
grape-entity (0.7.1)
activesupport (>= 4.0)
multi_json (>= 1.3.2)
- grape-path-helpers (1.4.0)
+ grape-path-helpers (1.5.0)
activesupport
grape (~> 1.3)
- rake (~> 12)
+ rake (> 12)
grape_logging (1.8.3)
grape
rack
graphiql-rails (1.4.10)
railties
sprockets-rails
+ graphlient (0.4.0)
+ faraday (>= 1.0)
+ faraday_middleware
+ graphql-client
graphql (1.11.4)
+ graphql-client (0.16.0)
+ activesupport (>= 3.0)
+ graphql (~> 1.8)
graphql-docs (1.6.0)
commonmarker (~> 0.16)
escape_utils (~> 1.2)
@@ -536,8 +548,9 @@ GEM
haml (5.1.2)
temple (>= 0.8.0)
tilt
- haml_lint (0.34.0)
- haml (>= 4.0, < 5.2)
+ haml_lint (0.36.0)
+ haml (>= 4.0, < 5.3)
+ parallel (~> 1.10)
rainbow
rubocop (>= 0.50.0)
sysexits (~> 1.1)
@@ -586,10 +599,9 @@ GEM
invisible_captcha (0.12.1)
rails (>= 3.2.0)
ipaddress (0.8.3)
- jaeger-client (0.10.0)
+ jaeger-client (1.1.0)
opentracing (~> 0.3)
thrift
- jaro_winkler (1.5.4)
jira-ruby (2.0.0)
activesupport
atlassian-jwt
@@ -601,7 +613,7 @@ GEM
regexp_parser (~> 1.5)
regexp_property_values (~> 0.3)
json (2.3.0)
- json-jwt (1.11.0)
+ json-jwt (1.13.0)
activesupport (>= 4.2)
aes_key_wrap
bindata
@@ -821,9 +833,9 @@ GEM
rubypants (~> 0.2)
orm_adapter (0.5.0)
os (1.0.0)
- parallel (1.19.1)
- parser (2.7.1.2)
- ast (~> 2.4.0)
+ parallel (1.19.2)
+ parser (2.7.2.0)
+ ast (~> 2.4.1)
parslet (1.8.2)
peek (1.1.0)
railties (>= 4.0.0)
@@ -855,19 +867,19 @@ GEM
public_suffix (4.0.6)
pyu-ruby-sasl (0.0.3.3)
raabro (1.1.6)
- rack (2.1.4)
+ rack (2.2.3)
rack-accept (0.4.5)
rack (>= 0.4)
rack-attack (6.3.0)
rack (>= 1.0, < 3)
rack-cors (1.0.6)
rack (>= 1.6.0)
- rack-oauth2 (1.9.3)
+ rack-oauth2 (1.16.0)
activesupport
attr_required
httpclient
- json-jwt (>= 1.9.0)
- rack
+ json-jwt (>= 1.11.0)
+ rack (>= 2.1.0)
rack-protection (2.0.5)
rack
rack-proxy (0.6.0)
@@ -910,7 +922,7 @@ GEM
thor (>= 0.20.3, < 2.0)
rainbow (3.0.0)
raindrops (0.19.1)
- rake (12.3.3)
+ rake (13.0.1)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
@@ -945,7 +957,7 @@ GEM
redis-store (>= 1.2, < 2)
redis-store (1.8.1)
redis (>= 4, < 5)
- regexp_parser (1.5.1)
+ regexp_parser (1.8.2)
regexp_property_values (0.3.5)
representable (3.0.4)
declarative (< 0.1.0)
@@ -965,7 +977,7 @@ GEM
rexml (3.2.4)
rinku (2.0.0)
rotp (2.1.2)
- rouge (3.24.0)
+ rouge (3.25.0)
rqrcode (0.7.0)
chunky_png
rqrcode-rails3 (0.1.7)
@@ -1001,29 +1013,34 @@ GEM
rspec-support (3.9.2)
rspec_junit_formatter (0.4.1)
rspec-core (>= 2, < 4, != 2.12.0)
- rspec_profiling (0.0.5)
+ rspec_profiling (0.0.6)
activerecord
pg
rails
sqlite3
- rubocop (0.82.0)
- jaro_winkler (~> 1.5.1)
+ rubocop (0.89.1)
parallel (~> 1.10)
- parser (>= 2.7.0.1)
+ parser (>= 2.7.1.1)
rainbow (>= 2.2.2, < 4.0)
+ regexp_parser (>= 1.7)
rexml
+ rubocop-ast (>= 0.3.0, < 1.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
+ rubocop-ast (0.8.0)
+ parser (>= 2.7.1.5)
rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51)
- rubocop-performance (1.5.2)
- rubocop (>= 0.71.0)
- rubocop-rails (2.5.2)
- activesupport
+ rubocop-performance (1.8.1)
+ rubocop (>= 0.87.0)
+ rubocop-ast (>= 0.4.0)
+ rubocop-rails (2.8.1)
+ activesupport (>= 4.2.0)
rack (>= 1.1)
- rubocop (>= 0.72.0)
- rubocop-rspec (1.37.0)
- rubocop (>= 0.68.1)
+ rubocop (>= 0.87.0)
+ rubocop-rspec (1.44.1)
+ rubocop (~> 0.87)
+ rubocop-ast (>= 0.7.1)
ruby-enum (0.7.2)
i18n
ruby-fogbugz (0.2.1)
@@ -1034,7 +1051,7 @@ GEM
nokogiri (>= 1.5.10)
ruby-statistics (2.1.2)
ruby2_keywords (0.0.2)
- ruby_parser (3.13.1)
+ ruby_parser (3.15.0)
sexp_processor (~> 4.9)
rubyntlm (0.6.2)
rubypants (0.2.0)
@@ -1064,9 +1081,8 @@ GEM
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
- scss_lint (0.56.0)
- rake (>= 0.9, < 13)
- sass (~> 3.5.3)
+ scss_lint (0.59.0)
+ sass (~> 3.5, >= 3.5.5)
securecompare (1.0.0)
seed-fu (2.3.7)
activerecord (>= 3.1)
@@ -1077,7 +1093,7 @@ GEM
sentry-raven (3.0.4)
faraday (>= 1.0)
settingslogic (2.0.9)
- sexp_processor (4.12.0)
+ sexp_processor (4.15.1)
shellany (0.0.1)
shoulda-matchers (4.0.1)
activesupport (>= 4.2.0)
@@ -1105,8 +1121,7 @@ GEM
slack-messenger (2.3.4)
snowplow-tracker (0.6.1)
contracts (~> 0.7, <= 0.11)
- spring (2.0.2)
- activesupport (>= 4.2)
+ spring (2.1.1)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
sprockets (3.7.2)
@@ -1146,7 +1161,7 @@ GEM
rack (>= 1, < 3)
thor (0.20.3)
thread_safe (0.3.6)
- thrift (0.11.0.0)
+ thrift (0.13.0)
tilt (2.0.10)
timecop (0.9.1)
timeliness (0.3.10)
@@ -1162,7 +1177,7 @@ GEM
truncato (0.7.11)
htmlentities (~> 4.3.1)
nokogiri (>= 1.7.0, <= 2.0)
- tzinfo (1.2.7)
+ tzinfo (1.2.8)
thread_safe (~> 0.1)
u2f (0.2.1)
uber (0.1.0)
@@ -1236,14 +1251,13 @@ GEM
xpath (3.2.0)
nokogiri (~> 1.8)
yajl-ruby (1.4.1)
- zeitwerk (2.4.0)
+ zeitwerk (2.4.1)
PLATFORMS
ruby
DEPENDENCIES
RedCloth (~> 4.3.2)
- ace-rails-ap (~> 4.1.0)
acme-client (~> 2.0, >= 2.0.6)
activerecord-explain-analyze (~> 0.1)
acts-as-taggable-on (~> 6.0)
@@ -1283,6 +1297,7 @@ DEPENDENCIES
connection_pool (~> 2.0)
countries (~> 3.0)
creole (~> 0.5.0)
+ crystalball (~> 0.7.0)
danger (~> 8.0.6)
database_cleaner (~> 1.7.0)
deckar01-task_list (= 2.3.1)
@@ -1316,7 +1331,7 @@ DEPENDENCIES
fog-aliyun (~> 0.3)
fog-aws (~> 3.5)
fog-core (= 2.1.0)
- fog-google (~> 1.10)
+ fog-google (~> 1.11)
fog-local (~> 0.6)
fog-openstack (~> 1.0)
fog-rackspace (~> 0.1.1)
@@ -1331,15 +1346,16 @@ DEPENDENCIES
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
gitlab-fog-azure-rm (~> 1.0)
- gitlab-labkit (= 0.12.2)
+ gitlab-labkit (= 0.13.1)
gitlab-license (~> 1.0)
gitlab-mail_room (~> 0.0.7)
gitlab-markup (~> 1.7.1)
gitlab-net-dns (~> 0.9.1)
+ gitlab-pg_query (~> 1.3)
gitlab-puma (~> 4.3.3.gitlab.2)
gitlab-puma_worker_killer (~> 0.1.1.gitlab.1)
gitlab-sidekiq-fetcher (= 0.5.2)
- gitlab-styles (~> 4.3.0)
+ gitlab-styles (~> 5.1.0)
gitlab_chronic_duration (~> 0.10.6.2)
gitlab_omniauth-ldap (~> 2.1.1)
gon (~> 6.2)
@@ -1348,15 +1364,16 @@ DEPENDENCIES
gpgme (~> 2.0.19)
grape (= 1.4.0)
grape-entity (~> 0.7.1)
- grape-path-helpers (~> 1.4)
+ grape-path-helpers (~> 1.5)
grape_logging (~> 1.7)
graphiql-rails (~> 1.4.10)
+ graphlient (~> 0.4.0)
graphql (~> 1.11.4)
graphql-docs (~> 1.6.0)
grpc (~> 1.30.2)
gssapi
guard-rspec
- haml_lint (~> 0.34.0)
+ haml_lint (~> 0.36.0)
hamlit (~> 2.11.0)
hangouts-chat (~> 0.0.5)
hashie
@@ -1429,10 +1446,10 @@ DEPENDENCIES
prometheus-client-mmap (~> 0.12.0)
pry-byebug (~> 3.9.0)
pry-rails (~> 0.3.9)
- rack (~> 2.1.4)
+ rack (~> 2.2.3)
rack-attack (~> 6.3.0)
rack-cors (~> 1.0.6)
- rack-oauth2 (~> 1.9.3)
+ rack-oauth2 (~> 1.16.0)
rack-proxy (~> 0.6.0)
rack-timeout (~> 0.5.1)
rails (~> 6.0.3.1)
@@ -1451,25 +1468,22 @@ DEPENDENCIES
request_store (~> 1.5)
responders (~> 3.0)
retriable (~> 3.1.2)
- rouge (~> 3.24.0)
+ rouge (~> 3.25.0)
rqrcode-rails3 (~> 0.1.7)
rspec-parameterized
rspec-rails (~> 4.0.0)
rspec-retry (~> 0.6.1)
rspec_junit_formatter
- rspec_profiling (~> 0.0.5)
- rubocop (~> 0.82.0)
- rubocop-performance (~> 1.5.2)
- rubocop-rspec (~> 1.37.0)
+ rspec_profiling (~> 0.0.6)
ruby-fogbugz (~> 0.2.1)
ruby-prof (~> 1.3.0)
ruby-progressbar
- ruby_parser (~> 3.8)
+ ruby_parser (~> 3.15)
rubyzip (~> 2.0.0)
rugged (~> 0.28)
sanitize (~> 5.2.1)
sassc-rails (~> 2.1.0)
- scss_lint (~> 0.56.0)
+ scss_lint (~> 0.59.0)
seed-fu (~> 2.3.7)
selenium-webdriver (~> 3.142)
sentry-raven (~> 3.0)
@@ -1482,7 +1496,7 @@ DEPENDENCIES
simplecov-cobertura (~> 1.3.1)
slack-messenger (~> 2.3.4)
snowplow-tracker (~> 0.6.1)
- spring (~> 2.0.0)
+ spring (~> 2.1.0)
spring-commands-rspec (~> 1.0.4)
sprockets (~> 3.7.0)
sshkey (~> 2.0)
@@ -1510,4 +1524,4 @@ DEPENDENCIES
yajl-ruby (~> 1.4.1)
BUNDLED WITH
- 1.17.3
+ 2.1.4
diff --git a/README.md b/README.md
index 38ecb9ea612..e3712d3f9f8 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
The canonical source of GitLab where all development takes place is [hosted on GitLab.com](https://gitlab.com/gitlab-org/gitlab).
-If you wish to clone a copy of GitLab without proprietary code, you can use the read-only mirror of GitLab located at https://gitlab.com/gitlab-org/gitlab-foss/. Please do not submit any issues and/or merge requests to this project.
+If you wish to clone a copy of GitLab without proprietary code, you can use the read-only mirror of GitLab located at https://gitlab.com/gitlab-org/gitlab-foss/. However, please do not submit any issues and/or merge requests to that project.
## Free trial
@@ -79,7 +79,7 @@ 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.6
+- Ruby (MRI) 2.7.2
- Git 2.24+
- Redis 4.0+
- PostgreSQL 11+
diff --git a/app/assets/javascripts/access_tokens/components/expires_at_field.vue b/app/assets/javascripts/access_tokens/components/expires_at_field.vue
index d0932ad80e1..1fec186f2fa 100644
--- a/app/assets/javascripts/access_tokens/components/expires_at_field.vue
+++ b/app/assets/javascripts/access_tokens/components/expires_at_field.vue
@@ -1,14 +1,32 @@
<script>
-import { GlDatepicker } from '@gitlab/ui';
+import { GlDatepicker, GlFormInput } from '@gitlab/ui';
export default {
name: 'ExpiresAtField',
- components: { GlDatepicker },
+ components: { GlDatepicker, GlFormInput },
+ props: {
+ inputAttrs: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ },
+ data() {
+ return {
+ minDate: new Date(),
+ };
+ },
};
</script>
<template>
- <gl-datepicker :target="null" :min-date="new Date()">
- <slot></slot>
+ <gl-datepicker :target="null" :min-date="minDate">
+ <gl-form-input
+ v-bind="inputAttrs"
+ class="datepicker gl-datepicker-input"
+ autocomplete="off"
+ inputmode="none"
+ data-qa-selector="expiry_date_field"
+ />
</gl-datepicker>
</template>
diff --git a/app/assets/javascripts/access_tokens/index.js b/app/assets/javascripts/access_tokens/index.js
index 9bdb2940956..319144193f1 100644
--- a/app/assets/javascripts/access_tokens/index.js
+++ b/app/assets/javascripts/access_tokens/index.js
@@ -1,11 +1,34 @@
import Vue from 'vue';
import ExpiresAtField from './components/expires_at_field.vue';
+const getInputAttrs = el => {
+ const input = el.querySelector('input');
+
+ return {
+ id: input.id,
+ name: input.name,
+ placeholder: input.placeholder,
+ };
+};
+
const initExpiresAtField = () => {
- // eslint-disable-next-line no-new
- new Vue({
- el: document.querySelector('.js-access-tokens-expires-at'),
- components: { ExpiresAtField },
+ const el = document.querySelector('.js-access-tokens-expires-at');
+
+ if (!el) {
+ return null;
+ }
+
+ const inputAttrs = getInputAttrs(el);
+
+ return new Vue({
+ el,
+ render(h) {
+ return h(ExpiresAtField, {
+ props: {
+ inputAttrs,
+ },
+ });
+ },
});
};
diff --git a/app/assets/javascripts/admin/dev_ops_report/devops_adoption.js b/app/assets/javascripts/admin/dev_ops_report/devops_adoption.js
new file mode 100644
index 00000000000..ae73033079d
--- /dev/null
+++ b/app/assets/javascripts/admin/dev_ops_report/devops_adoption.js
@@ -0,0 +1,2 @@
+// EE-specific feature. Find the implementation in the `ee/`-folder
+export default () => {};
diff --git a/app/assets/javascripts/admin/dev_ops_report/devops_score_empty_state.js b/app/assets/javascripts/admin/dev_ops_report/devops_score_empty_state.js
new file mode 100644
index 00000000000..0cb8d9be0e4
--- /dev/null
+++ b/app/assets/javascripts/admin/dev_ops_report/devops_score_empty_state.js
@@ -0,0 +1,27 @@
+import Vue from 'vue';
+import UserCallout from '~/user_callout';
+import UsagePingDisabled from './components/usage_ping_disabled.vue';
+
+export default () => {
+ // 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/alert_management/components/alert_details.vue b/app/assets/javascripts/alert_management/components/alert_details.vue
index f7a5d31b835..1f3fdd5eef2 100644
--- a/app/assets/javascripts/alert_management/components/alert_details.vue
+++ b/app/assets/javascripts/alert_management/components/alert_details.vue
@@ -30,7 +30,6 @@ import AlertSidebar from './alert_sidebar.vue';
import AlertMetrics from './alert_metrics.vue';
import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
import AlertSummaryRow from './alert_summary_row.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
const containerEl = document.querySelector('.page-with-contextual-sidebar');
@@ -77,7 +76,6 @@ export default {
SystemNote,
AlertMetrics,
},
- mixins: [glFeatureFlagsMixin()],
inject: {
projectPath: {
default: '',
@@ -150,13 +148,10 @@ export default {
},
},
environmentName() {
- return this.shouldDisplayEnvironment && this.alert?.environment?.name;
+ return this.alert?.environment?.name;
},
environmentPath() {
- return this.shouldDisplayEnvironment && this.alert?.environment?.path;
- },
- shouldDisplayEnvironment() {
- return this.glFeatures.exposeEnvironmentPathInAlertDetails;
+ return this.alert?.environment?.path;
},
},
mounted() {
diff --git a/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue b/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue
new file mode 100644
index 00000000000..f6474efcc1f
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue
@@ -0,0 +1,221 @@
+<script>
+import Vue from 'vue';
+import {
+ GlIcon,
+ GlFormInput,
+ GlDropdown,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ GlTooltipDirective as GlTooltip,
+} from '@gitlab/ui';
+import { s__, __ } from '~/locale';
+// Mocks will be removed when integrating with BE is ready
+// data format is defined and will be the same as mocked (maybe with some minor changes)
+// feature rollout plan - https://gitlab.com/gitlab-org/gitlab/-/issues/262707#note_442529171
+import gitlabFieldsMock from './mocks/gitlabFields.json';
+
+export const i18n = {
+ columns: {
+ gitlabKeyTitle: s__('AlertMappingBuilder|GitLab alert key'),
+ payloadKeyTitle: s__('AlertMappingBuilder|Payload alert key'),
+ fallbackKeyTitle: s__('AlertMappingBuilder|Define fallback'),
+ },
+ selectMappingKey: s__('AlertMappingBuilder|Select key'),
+ makeSelection: s__('AlertMappingBuilder|Make selection'),
+ fallbackTooltip: s__(
+ 'AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. ',
+ ),
+ noResults: __('No matching results'),
+};
+
+export default {
+ i18n,
+ components: {
+ GlIcon,
+ GlFormInput,
+ GlDropdown,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ },
+ directives: {
+ GlTooltip,
+ },
+ props: {
+ payloadFields: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ mapping: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
+ data() {
+ return {
+ gitlabFields: this.gitlabAlertFields,
+ };
+ },
+ inject: {
+ gitlabAlertFields: {
+ default: gitlabFieldsMock,
+ },
+ },
+ computed: {
+ mappingData() {
+ return this.gitlabFields.map(gitlabField => {
+ const mappingFields = this.payloadFields.filter(({ type }) =>
+ type.some(t => gitlabField.compatibleTypes.includes(t)),
+ );
+
+ const foundMapping = this.mapping.find(
+ ({ alertFieldName }) => alertFieldName === gitlabField.name,
+ );
+
+ const { fallbackAlertPaths, payloadAlertPaths } = foundMapping || {};
+
+ return {
+ mapping: payloadAlertPaths,
+ fallback: fallbackAlertPaths,
+ searchTerm: '',
+ fallbackSearchTerm: '',
+ mappingFields,
+ ...gitlabField,
+ };
+ });
+ },
+ },
+ methods: {
+ setMapping(gitlabKey, mappingKey, valueKey) {
+ const fieldIndex = this.gitlabFields.findIndex(field => field.name === gitlabKey);
+ const updatedField = { ...this.gitlabFields[fieldIndex], ...{ [valueKey]: mappingKey } };
+ Vue.set(this.gitlabFields, fieldIndex, updatedField);
+ },
+ setSearchTerm(search = '', searchFieldKey, gitlabKey) {
+ const fieldIndex = this.gitlabFields.findIndex(field => field.name === gitlabKey);
+ const updatedField = { ...this.gitlabFields[fieldIndex], ...{ [searchFieldKey]: search } };
+ Vue.set(this.gitlabFields, fieldIndex, updatedField);
+ },
+ filterFields(searchTerm = '', fields) {
+ const search = searchTerm.toLowerCase();
+
+ return fields.filter(field => field.label.toLowerCase().includes(search));
+ },
+ isSelected(fieldValue, mapping) {
+ return fieldValue === mapping;
+ },
+ selectedValue(name) {
+ return (
+ this.payloadFields.find(item => item.name === name)?.label ||
+ this.$options.i18n.makeSelection
+ );
+ },
+ getFieldValue({ label, type }) {
+ return `${label} (${type.join(__(' or '))})`;
+ },
+ noResults(searchTerm, fields) {
+ return !this.filterFields(searchTerm, fields).length;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-table gl-w-full gl-mt-5">
+ <div class="gl-display-table-row">
+ <h5 id="gitlabFieldsHeader" class="gl-display-table-cell gl-py-3 gl-pr-3">
+ {{ $options.i18n.columns.gitlabKeyTitle }}
+ </h5>
+ <h5 class="gl-display-table-cell gl-py-3 gl-pr-3">&nbsp;</h5>
+ <h5 id="parsedFieldsHeader" class="gl-display-table-cell gl-py-3 gl-pr-3">
+ {{ $options.i18n.columns.payloadKeyTitle }}
+ </h5>
+ <h5 id="fallbackFieldsHeader" class="gl-display-table-cell gl-py-3 gl-pr-3">
+ {{ $options.i18n.columns.fallbackKeyTitle }}
+ <gl-icon
+ v-gl-tooltip
+ name="question"
+ class="gl-text-gray-500"
+ :title="$options.i18n.fallbackTooltip"
+ />
+ </h5>
+ </div>
+
+ <div
+ v-for="(gitlabField, index) in mappingData"
+ :key="gitlabField.name"
+ class="gl-display-table-row"
+ >
+ <div class="gl-display-table-cell gl-py-3 gl-pr-3 w-30p gl-vertical-align-middle">
+ <gl-form-input
+ aria-labelledby="gitlabFieldsHeader"
+ disabled
+ :value="getFieldValue(gitlabField)"
+ />
+ </div>
+
+ <div class="gl-display-table-cell gl-py-3 gl-pr-3">
+ <div class="right-arrow" :class="{ 'gl-vertical-align-middle': index === 0 }">
+ <i class="right-arrow-head"></i>
+ </div>
+ </div>
+
+ <div class="gl-display-table-cell gl-py-3 gl-pr-3 w-30p gl-vertical-align-middle">
+ <gl-dropdown
+ :disabled="!gitlabField.mappingFields.length"
+ aria-labelledby="parsedFieldsHeader"
+ :text="selectedValue(gitlabField.mapping)"
+ class="gl-w-full"
+ :header-text="$options.i18n.selectMappingKey"
+ >
+ <gl-search-box-by-type @input="setSearchTerm($event, 'searchTerm', gitlabField.name)" />
+ <gl-dropdown-item
+ v-for="mappingField in filterFields(gitlabField.searchTerm, gitlabField.mappingFields)"
+ :key="`${mappingField.name}__mapping`"
+ :is-checked="isSelected(gitlabField.mapping, mappingField.name)"
+ is-check-item
+ @click="setMapping(gitlabField.name, mappingField.name, 'mapping')"
+ >
+ {{ mappingField.label }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="noResults(gitlabField.searchTerm, gitlabField.mappingFields)">
+ {{ $options.i18n.noResults }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+
+ <div class="gl-display-table-cell gl-py-3 w-30p">
+ <gl-dropdown
+ v-if="Boolean(gitlabField.numberOfFallbacks)"
+ :disabled="!gitlabField.mappingFields.length"
+ aria-labelledby="fallbackFieldsHeader"
+ :text="selectedValue(gitlabField.fallback)"
+ class="gl-w-full"
+ :header-text="$options.i18n.selectMappingKey"
+ >
+ <gl-search-box-by-type
+ @input="setSearchTerm($event, 'fallbackSearchTerm', gitlabField.name)"
+ />
+ <gl-dropdown-item
+ v-for="mappingField in filterFields(
+ gitlabField.fallbackSearchTerm,
+ gitlabField.mappingFields,
+ )"
+ :key="`${mappingField.name}__fallback`"
+ :is-checked="isSelected(gitlabField.fallback, mappingField.name)"
+ is-check-item
+ @click="setMapping(gitlabField.name, mappingField.name, 'fallback')"
+ >
+ {{ mappingField.label }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="noResults(gitlabField.fallbackSearchTerm, gitlabField.mappingFields)"
+ >
+ {{ $options.i18n.noResults }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/alerts_settings/components/alert_settings_form_help_block.vue b/app/assets/javascripts/alerts_settings/components/alert_settings_form_help_block.vue
new file mode 100644
index 00000000000..35b7fe84c5f
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/components/alert_settings_form_help_block.vue
@@ -0,0 +1,32 @@
+<script>
+import { GlLink, GlSprintf } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlLink,
+ GlSprintf,
+ },
+ props: {
+ message: {
+ type: String,
+ required: true,
+ },
+ link: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <span>
+ <gl-sprintf :message="message">
+ <template #link="{ content }">
+ <gl-link class="gl-display-inline-block" :href="link" target="_blank">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+</template>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
index 217442e6131..12c0409629f 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
@@ -1,8 +1,24 @@
<script>
-import { GlTable, GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import {
+ GlButtonGroup,
+ GlButton,
+ GlIcon,
+ GlLoadingIcon,
+ GlModal,
+ GlModalDirective,
+ GlTable,
+ GlTooltipDirective,
+ GlSprintf,
+} from '@gitlab/ui';
import { s__, __ } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import Tracking from '~/tracking';
-import { trackAlertIntergrationsViewsOptions } from '../constants';
+import {
+ trackAlertIntegrationsViewsOptions,
+ integrationToDeleteDefault,
+ typeSet,
+} from '../constants';
+import getCurrentIntegrationQuery from '../graphql/queries/get_current_integration.query.graphql';
export const i18n = {
title: s__('AlertsIntegrations|Current integrations'),
@@ -24,23 +40,36 @@ const bodyTrClass =
export default {
i18n,
+ typeSet,
components: {
- GlTable,
+ GlButtonGroup,
+ GlButton,
GlIcon,
+ GlLoadingIcon,
+ GlModal,
+ GlTable,
+ GlSprintf,
},
directives: {
GlTooltip: GlTooltipDirective,
+ GlModal: GlModalDirective,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
integrations: {
type: Array,
required: false,
default: () => [],
},
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
fields: [
{
- key: 'activated',
+ key: 'active',
label: __('Status'),
},
{
@@ -51,22 +80,56 @@ export default {
key: 'type',
label: __('Type'),
},
+ {
+ key: 'actions',
+ thClass: `gl-text-center`,
+ tdClass: `gl-text-center`,
+ label: __('Actions'),
+ },
],
- computed: {
- tbodyTrClass() {
- return {
- [bodyTrClass]: this.integrations.length,
- };
+ apollo: {
+ currentIntegration: {
+ query: getCurrentIntegrationQuery,
},
},
+ data() {
+ return {
+ integrationToDelete: integrationToDeleteDefault,
+ currentIntegration: null,
+ };
+ },
mounted() {
- this.trackPageViews();
+ const callback = entries => {
+ const isVisible = entries.some(entry => entry.isIntersecting);
+
+ if (isVisible) {
+ this.trackPageViews();
+ this.observer.disconnect();
+ }
+ };
+
+ this.observer = new IntersectionObserver(callback);
+ this.observer.observe(this.$el);
},
methods: {
+ tbodyTrClass(item) {
+ return {
+ [bodyTrClass]: this.integrations.length,
+ 'gl-bg-blue-50': (item !== null && item.id) === this.currentIntegration?.id,
+ };
+ },
trackPageViews() {
- const { category, action } = trackAlertIntergrationsViewsOptions;
+ const { category, action } = trackAlertIntegrationsViewsOptions;
Tracking.event(category, action);
},
+ setIntegrationToDelete({ name, id }) {
+ this.integrationToDelete.id = id;
+ this.integrationToDelete.name = name;
+ },
+ deleteIntegration() {
+ this.$emit('delete-integration', { id: this.integrationToDelete.id });
+ this.integrationToDelete = { ...integrationToDeleteDefault };
+ },
},
};
</script>
@@ -75,15 +138,16 @@ export default {
<div class="incident-management-list">
<h5 class="gl-font-lg">{{ $options.i18n.title }}</h5>
<gl-table
- :empty-text="$options.i18n.emptyState"
+ class="integration-list"
:items="integrations"
:fields="$options.fields"
+ :busy="loading"
stacked="md"
:tbody-tr-class="tbodyTrClass"
show-empty
>
- <template #cell(activated)="{ item }">
- <span v-if="item.activated" data-testid="integration-activated-status">
+ <template #cell(active)="{ item }">
+ <span v-if="item.active" data-testid="integration-activated-status">
<gl-icon
v-gl-tooltip
name="check-circle-filled"
@@ -104,6 +168,47 @@ export default {
{{ $options.i18n.status.disabled.name }}
</span>
</template>
+
+ <template #cell(actions)="{ item }">
+ <gl-button-group v-if="glFeatures.httpIntegrationsList" class="gl-ml-3">
+ <gl-button icon="pencil" @click="$emit('edit-integration', { id: item.id })" />
+ <gl-button
+ v-gl-modal.deleteIntegration
+ :disabled="item.type === $options.typeSet.prometheus"
+ icon="remove"
+ @click="setIntegrationToDelete(item)"
+ />
+ </gl-button-group>
+ </template>
+
+ <template #table-busy>
+ <gl-loading-icon size="lg" color="dark" class="mt-3" />
+ </template>
+
+ <template #empty>
+ <div
+ class="gl-border-t-solid gl-border-b-solid gl-border-1 gl-border gl-border-gray-100 mt-n3 gl-px-5"
+ >
+ <p class="gl-text-gray-400 gl-py-3 gl-my-3">{{ $options.i18n.emptyState }}</p>
+ </div>
+ </template>
</gl-table>
+ <gl-modal
+ modal-id="deleteIntegration"
+ :title="s__('AlertSettings|Delete integration')"
+ :ok-title="s__('AlertSettings|Delete integration')"
+ ok-variant="danger"
+ @ok="deleteIntegration"
+ >
+ <gl-sprintf
+ :message="
+ s__(
+ 'AlertsIntegrations|You have opted to delete the %{integrationName} integration. Do you want to proceed? It means you will no longer receive alerts from this endpoint in your alert list, and this action cannot be undone.',
+ )
+ "
+ >
+ <template #integrationName>{{ integrationToDelete.name }}</template>
+ </gl-sprintf>
+ </gl-modal>
</div>
</template>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
deleted file mode 100644
index f885afae378..00000000000
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
+++ /dev/null
@@ -1,522 +0,0 @@
-<script>
-import {
- GlAlert,
- GlButton,
- GlForm,
- GlFormGroup,
- GlFormInput,
- GlFormInputGroup,
- GlFormTextarea,
- GlLink,
- GlModal,
- GlModalDirective,
- GlSprintf,
- GlFormSelect,
-} from '@gitlab/ui';
-import { debounce } from 'lodash';
-import { s__ } from '~/locale';
-import { doesHashExistInUrl } from '~/lib/utils/url_utility';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import ToggleButton from '~/vue_shared/components/toggle_button.vue';
-import IntegrationsList from './alerts_integrations_list.vue';
-import csrf from '~/lib/utils/csrf';
-import service from '../services';
-import {
- i18n,
- serviceOptions,
- JSON_VALIDATE_DELAY,
- targetPrometheusUrlPlaceholder,
- targetOpsgenieUrlPlaceholder,
- sectionHash,
-} from '../constants';
-import createFlash, { FLASH_TYPES } from '~/flash';
-
-export default {
- i18n,
- csrf,
- targetOpsgenieUrlPlaceholder,
- targetPrometheusUrlPlaceholder,
- components: {
- GlAlert,
- GlButton,
- GlForm,
- GlFormGroup,
- GlFormInput,
- GlFormInputGroup,
- GlFormSelect,
- GlFormTextarea,
- GlLink,
- GlModal,
- GlSprintf,
- ClipboardButton,
- ToggleButton,
- IntegrationsList,
- },
- directives: {
- 'gl-modal': GlModalDirective,
- },
- inject: ['prometheus', 'generic', 'opsgenie'],
- data() {
- return {
- loading: false,
- selectedEndpoint: serviceOptions[0].value,
- options: serviceOptions,
- active: false,
- authKey: '',
- targetUrl: '',
- feedback: {
- variant: 'danger',
- feedbackMessage: '',
- isFeedbackDismissed: false,
- },
- testAlert: {
- json: null,
- error: null,
- },
- canSaveForm: false,
- serverError: null,
- };
- },
- computed: {
- sections() {
- return [
- {
- text: this.$options.i18n.usageSection,
- url: this.generic.alertsUsageUrl,
- },
- {
- text: this.$options.i18n.setupSection,
- url: this.generic.alertsSetupUrl,
- },
- ];
- },
- isPrometheus() {
- return this.selectedEndpoint === 'prometheus';
- },
- isOpsgenie() {
- return this.selectedEndpoint === 'opsgenie';
- },
- selectedService() {
- switch (this.selectedEndpoint) {
- case 'generic': {
- return {
- url: this.generic.url,
- authKey: this.generic.authorizationKey,
- activated: this.generic.activated,
- resetKey: this.resetKey.bind(this),
- };
- }
- case 'prometheus': {
- return {
- url: this.prometheus.prometheusUrl,
- authKey: this.prometheus.authorizationKey,
- activated: this.prometheus.activated,
- resetKey: this.resetKey.bind(this, 'prometheus'),
- targetUrl: this.prometheus.prometheusApiUrl,
- };
- }
- case 'opsgenie': {
- return {
- targetUrl: this.opsgenie.opsgenieMvcTargetUrl,
- activated: this.opsgenie.activated,
- };
- }
- default: {
- return {};
- }
- }
- },
- showFeedbackMsg() {
- return this.feedback.feedbackMessage && !this.isFeedbackDismissed;
- },
- showAlertSave() {
- return (
- this.feedback.feedbackMessage === this.$options.i18n.testAlertFailed &&
- !this.isFeedbackDismissed
- );
- },
- prometheusInfo() {
- return this.isPrometheus ? this.$options.i18n.prometheusInfo : '';
- },
- jsonIsValid() {
- return this.testAlert.error === null;
- },
- canTestAlert() {
- return this.active && this.testAlert.json !== null;
- },
- canSaveConfig() {
- return !this.loading && this.canSaveForm;
- },
- baseUrlPlaceholder() {
- return this.isOpsgenie
- ? this.$options.targetOpsgenieUrlPlaceholder
- : this.$options.targetPrometheusUrlPlaceholder;
- },
- integrations() {
- return [
- {
- name: s__('AlertSettings|HTTP endpoint'),
- type: s__('AlertsIntegrations|HTTP endpoint'),
- activated: this.generic.activated,
- },
- {
- name: s__('AlertSettings|External Prometheus'),
- type: s__('AlertsIntegrations|Prometheus'),
- activated: this.prometheus.activated,
- },
- ];
- },
- },
- watch: {
- 'testAlert.json': debounce(function debouncedJsonValidate() {
- this.validateJson();
- }, JSON_VALIDATE_DELAY),
- targetUrl(oldVal, newVal) {
- if (newVal && oldVal !== this.selectedService.targetUrl) {
- this.canSaveForm = true;
- }
- },
- },
- mounted() {
- if (
- this.prometheus.activated ||
- this.generic.activated ||
- !this.opsgenie.opsgenieMvcIsAvailable
- ) {
- this.removeOpsGenieOption();
- } else if (this.opsgenie.activated) {
- this.setOpsgenieAsDefault();
- }
- this.active = this.selectedService.activated;
- this.authKey = this.selectedService.authKey ?? '';
- },
- methods: {
- createUserErrorMessage(errors = {}) {
- const error = Object.entries(errors)?.[0];
- if (error) {
- const [field, [msg]] = error;
- this.serverError = `${field} ${msg}`;
- }
- },
- setOpsgenieAsDefault() {
- this.options = this.options.map(el => {
- if (el.value !== 'opsgenie') {
- return { ...el, disabled: true };
- }
- return { ...el, disabled: false };
- });
- this.selectedEndpoint = this.options.find(({ value }) => value === 'opsgenie').value;
- if (this.targetUrl === null) {
- this.targetUrl = this.selectedService.targetUrl;
- }
- },
- removeOpsGenieOption() {
- this.options = this.options.map(el => {
- if (el.value !== 'opsgenie') {
- return { ...el, disabled: false };
- }
- return { ...el, disabled: true };
- });
- },
- resetFormValues() {
- this.testAlert.json = null;
- this.targetUrl = this.selectedService.targetUrl;
- this.active = this.selectedService.activated;
- },
- dismissFeedback() {
- this.serverError = null;
- this.feedback = { ...this.feedback, feedbackMessage: null };
- this.isFeedbackDismissed = false;
- },
- resetKey(key) {
- const fn = key === 'prometheus' ? this.resetPrometheusKey() : this.resetGenericKey();
-
- return fn
- .then(({ data: { token } }) => {
- this.authKey = token;
- this.setFeedback({ feedbackMessage: this.$options.i18n.authKeyRest, variant: 'success' });
- })
- .catch(() => {
- this.setFeedback({ feedbackMessage: this.$options.i18n.errorKeyMsg, variant: 'danger' });
- });
- },
- resetGenericKey() {
- this.dismissFeedback();
- return service.updateGenericKey({
- endpoint: this.generic.formPath,
- params: { service: { token: '' } },
- });
- },
- resetPrometheusKey() {
- return service.updatePrometheusKey({ endpoint: this.prometheus.prometheusResetKeyPath });
- },
- toggleService(value) {
- this.canSaveForm = true;
- this.active = value;
- },
- toggle(value) {
- return this.isPrometheus ? this.togglePrometheusActive(value) : this.toggleActivated(value);
- },
- toggleActivated(value) {
- this.loading = true;
- return service
- .updateGenericActive({
- endpoint: this[this.selectedEndpoint].formPath,
- params: this.isOpsgenie
- ? { service: { opsgenie_mvc_target_url: this.targetUrl, opsgenie_mvc_enabled: value } }
- : { service: { active: value } },
- })
- .then(() => this.notifySuccessAndReload())
- .catch(({ response: { data: { errors } = {} } = {} }) => {
- this.createUserErrorMessage(errors);
- this.setFeedback({
- feedbackMessage: this.$options.i18n.errorMsg,
- variant: 'danger',
- });
- })
- .finally(() => {
- this.loading = false;
- this.canSaveForm = false;
- });
- },
- reload() {
- if (!doesHashExistInUrl(sectionHash)) {
- window.location.hash = sectionHash;
- }
- window.location.reload();
- },
- togglePrometheusActive(value) {
- this.loading = true;
- return service
- .updatePrometheusActive({
- endpoint: this.prometheus.prometheusFormPath,
- params: {
- token: this.$options.csrf.token,
- config: value,
- url: this.targetUrl,
- redirect: window.location,
- },
- })
- .then(() => this.notifySuccessAndReload())
- .catch(({ response: { data: { errors } = {} } = {} }) => {
- this.createUserErrorMessage(errors);
- this.setFeedback({
- feedbackMessage: this.$options.i18n.errorMsg,
- variant: 'danger',
- });
- })
- .finally(() => {
- this.loading = false;
- this.canSaveForm = false;
- });
- },
- notifySuccessAndReload() {
- createFlash({ message: this.$options.i18n.changesSaved, type: FLASH_TYPES.NOTICE });
- setTimeout(() => this.reload(), 1000);
- },
- setFeedback({ feedbackMessage, variant }) {
- this.feedback = { feedbackMessage, variant };
- },
- validateJson() {
- this.testAlert.error = null;
- try {
- JSON.parse(this.testAlert.json);
- } catch (e) {
- this.testAlert.error = JSON.stringify(e.message);
- }
- },
- validateTestAlert() {
- this.loading = true;
- this.dismissFeedback();
- this.validateJson();
- return service
- .updateTestAlert({
- endpoint: this.selectedService.url,
- data: this.testAlert.json,
- authKey: this.selectedService.authKey,
- })
- .then(() => {
- this.setFeedback({
- feedbackMessage: this.$options.i18n.testAlertSuccess,
- variant: 'success',
- });
- })
- .catch(() => {
- this.setFeedback({
- feedbackMessage: this.$options.i18n.testAlertFailed,
- variant: 'danger',
- });
- })
- .finally(() => {
- this.loading = false;
- });
- },
- onSubmit() {
- this.dismissFeedback();
- this.toggle(this.active);
- },
- onReset() {
- this.testAlert.json = null;
- this.dismissFeedback();
- this.targetUrl = this.selectedService.targetUrl;
-
- if (this.canSaveForm) {
- this.canSaveForm = false;
- this.active = this.selectedService.activated;
- }
- },
- },
-};
-</script>
-
-<template>
- <div>
- <integrations-list :integrations="integrations" />
-
- <gl-form @submit.prevent="onSubmit" @reset.prevent="onReset">
- <h5 class="gl-font-lg gl-my-5">{{ $options.i18n.integrationsLabel }}</h5>
-
- <gl-alert v-if="showFeedbackMsg" :variant="feedback.variant" @dismiss="dismissFeedback">
- {{ feedback.feedbackMessage }}
- <br />
- <i v-if="serverError">{{ __('Error message:') }} {{ serverError }}</i>
- <gl-button
- v-if="showAlertSave"
- variant="danger"
- category="primary"
- class="gl-display-block gl-mt-3"
- @click="toggle(active)"
- >
- {{ __('Save anyway') }}
- </gl-button>
- </gl-alert>
-
- <div data-testid="alert-settings-description">
- <p v-for="section in sections" :key="section.text">
- <gl-sprintf :message="section.text">
- <template #link="{ content }">
- <gl-link :href="section.url" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- </div>
-
- <gl-form-group label-for="integration-type" :label="$options.i18n.integration">
- <gl-form-select
- id="integration-type"
- v-model="selectedEndpoint"
- :options="options"
- data-testid="alert-settings-select"
- @change="resetFormValues"
- />
- <span class="gl-text-gray-500">
- <gl-sprintf :message="$options.i18n.integrationsInfo">
- <template #link="{ content }">
- <gl-link
- class="gl-display-inline-block"
- href="https://gitlab.com/groups/gitlab-org/-/epics/4390"
- target="_blank"
- >{{ content }}</gl-link
- >
- </template>
- </gl-sprintf>
- </span>
- </gl-form-group>
- <gl-form-group :label="$options.i18n.activeLabel" label-for="activated">
- <toggle-button
- id="activated"
- :disabled-input="loading"
- :is-loading="loading"
- :value="active"
- @change="toggleService"
- />
- </gl-form-group>
- <gl-form-group
- v-if="isOpsgenie || isPrometheus"
- :label="$options.i18n.apiBaseUrlLabel"
- label-for="api-url"
- >
- <gl-form-input
- id="api-url"
- v-model="targetUrl"
- type="url"
- :placeholder="baseUrlPlaceholder"
- :disabled="!active"
- />
- <span class="gl-text-gray-500">
- {{ $options.i18n.apiBaseUrlHelpText }}
- </span>
- </gl-form-group>
- <template v-if="!isOpsgenie">
- <gl-form-group :label="$options.i18n.urlLabel" label-for="url">
- <gl-form-input-group id="url" readonly :value="selectedService.url">
- <template #append>
- <clipboard-button
- :text="selectedService.url"
- :title="$options.i18n.copyToClipboard"
- class="gl-m-0!"
- />
- </template>
- </gl-form-input-group>
- <span class="gl-text-gray-500">
- {{ prometheusInfo }}
- </span>
- </gl-form-group>
- <gl-form-group :label="$options.i18n.authKeyLabel" label-for="authorization-key">
- <gl-form-input-group id="authorization-key" class="gl-mb-2" readonly :value="authKey">
- <template #append>
- <clipboard-button
- :text="authKey"
- :title="$options.i18n.copyToClipboard"
- class="gl-m-0!"
- />
- </template>
- </gl-form-input-group>
- <gl-button v-gl-modal.authKeyModal :disabled="!active" class="gl-mt-3">{{
- $options.i18n.resetKey
- }}</gl-button>
- <gl-modal
- modal-id="authKeyModal"
- :title="$options.i18n.resetKey"
- :ok-title="$options.i18n.resetKey"
- ok-variant="danger"
- @ok="selectedService.resetKey"
- >
- {{ $options.i18n.restKeyInfo }}
- </gl-modal>
- </gl-form-group>
- <gl-form-group
- :label="$options.i18n.alertJson"
- label-for="alert-json"
- :invalid-feedback="testAlert.error"
- >
- <gl-form-textarea
- id="alert-json"
- v-model.trim="testAlert.json"
- :disabled="!active"
- :state="jsonIsValid"
- :placeholder="$options.i18n.alertJsonPlaceholder"
- rows="6"
- max-rows="10"
- />
- </gl-form-group>
- <gl-button :disabled="!canTestAlert" @click="validateTestAlert">{{
- $options.i18n.testAlertInfo
- }}</gl-button>
- </template>
- <div class="footer-block row-content-block gl-display-flex gl-justify-content-space-between">
- <gl-button
- variant="success"
- category="primary"
- :disabled="!canSaveConfig"
- @click="onSubmit"
- >
- {{ __('Save changes') }}
- </gl-button>
- <gl-button category="primary" :disabled="!canSaveConfig" @click="onReset">
- {{ __('Cancel') }}
- </gl-button>
- </div>
- </gl-form>
- </div>
-</template>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_form_new.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_form_new.vue
new file mode 100644
index 00000000000..3656fc4d7ec
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_form_new.vue
@@ -0,0 +1,661 @@
+<script>
+import {
+ GlButton,
+ GlCollapse,
+ GlForm,
+ GlFormGroup,
+ GlFormSelect,
+ GlFormInput,
+ GlFormInputGroup,
+ GlFormTextarea,
+ GlModal,
+ GlModalDirective,
+ GlToggle,
+} from '@gitlab/ui';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { s__ } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import MappingBuilder from './alert_mapping_builder.vue';
+import AlertSettingsFormHelpBlock from './alert_settings_form_help_block.vue';
+import getCurrentIntegrationQuery from '../graphql/queries/get_current_integration.query.graphql';
+import service from '../services';
+import {
+ integrationTypesNew,
+ JSON_VALIDATE_DELAY,
+ targetPrometheusUrlPlaceholder,
+ targetOpsgenieUrlPlaceholder,
+ typeSet,
+ sectionHash,
+} from '../constants';
+// Mocks will be removed when integrating with BE is ready
+// data format is defined and will be the same as mocked (maybe with some minor changes)
+// feature rollout plan - https://gitlab.com/gitlab-org/gitlab/-/issues/262707#note_442529171
+import mockedCustomMapping from './mocks/parsedMapping.json';
+
+export default {
+ placeholders: {
+ prometheus: targetPrometheusUrlPlaceholder,
+ opsgenie: targetOpsgenieUrlPlaceholder,
+ },
+ JSON_VALIDATE_DELAY,
+ typeSet,
+ i18n: {
+ integrationFormSteps: {
+ step1: {
+ label: s__('AlertSettings|1. Select integration type'),
+ enterprise: s__(
+ 'AlertSettings|In free versions of GitLab, only one integration for each type can be added. %{linkStart}Upgrade your subscription%{linkEnd} to add additional integrations.',
+ ),
+ },
+ step2: {
+ label: s__('AlertSettings|2. Name integration'),
+ placeholder: s__('AlertSettings|Enter integration name'),
+ },
+ step3: {
+ label: s__('AlertSettings|3. Set up webhook'),
+ help: s__(
+ "AlertSettings|Utilize the URL and authorization key below to authorize an external service to send alerts to GitLab. Review your external service's documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.",
+ ),
+ prometheusHelp: s__(
+ 'AlertSettings|Utilize the URL and authorization key below to authorize Prometheus to send alerts to GitLab. Review the Prometheus documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.',
+ ),
+ info: s__('AlertSettings|Authorization key'),
+ reset: s__('AlertSettings|Reset Key'),
+ },
+ step4: {
+ label: s__('AlertSettings|4. Sample alert payload (optional)'),
+ help: s__(
+ 'AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to create a custom mapping (optional), or to test the integration (also optional).',
+ ),
+ prometheusHelp: s__(
+ 'AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to test the integration (optional).',
+ ),
+ placeholder: s__('AlertSettings|{ "events": [{ "application": "Name of application" }] }'),
+ resetHeader: s__('AlertSettings|Reset the mapping'),
+ resetBody: s__(
+ "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields.",
+ ),
+ resetOk: s__('AlertSettings|Proceed with editing'),
+ editPayload: s__('AlertSettings|Edit payload'),
+ submitPayload: s__('AlertSettings|Submit payload'),
+ payloadParsedSucessMsg: s__(
+ 'AlertSettings|Sample payload has been parsed. You can now map the fields.',
+ ),
+ },
+ step5: {
+ label: s__('AlertSettings|5. Map fields (optional)'),
+ intro: s__(
+ "AlertSettings|If you've provided a sample alert payload, you can create a custom mapping for your endpoint. The default GitLab alert keys are listed below. Please define which payload key should map to the specified GitLab key.",
+ ),
+ },
+ prometheusFormUrl: {
+ label: s__('AlertSettings|Prometheus API base URL'),
+ help: s__('AlertSettings|URL cannot be blank and must start with http or https'),
+ },
+ restKeyInfo: {
+ label: s__(
+ 'AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.',
+ ),
+ },
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ opsgenie: {
+ label: s__('AlertSettings|2. Add link to your Opsgenie alert list'),
+ info: s__(
+ 'AlertSettings|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature.',
+ ),
+ },
+ },
+ },
+ components: {
+ ClipboardButton,
+ GlButton,
+ GlCollapse,
+ GlForm,
+ GlFormGroup,
+ GlFormInput,
+ GlFormInputGroup,
+ GlFormTextarea,
+ GlFormSelect,
+ GlModal,
+ GlToggle,
+ AlertSettingsFormHelpBlock,
+ MappingBuilder,
+ },
+ directives: {
+ GlModal: GlModalDirective,
+ },
+ inject: {
+ generic: {
+ default: {},
+ },
+ prometheus: {
+ default: {},
+ },
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ opsgenie: {
+ default: {},
+ },
+ },
+ mixins: [glFeatureFlagsMixin()],
+ props: {
+ loading: {
+ type: Boolean,
+ required: true,
+ },
+ canAddIntegration: {
+ type: Boolean,
+ required: true,
+ },
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ canManageOpsgenie: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ apollo: {
+ currentIntegration: {
+ query: getCurrentIntegrationQuery,
+ },
+ },
+ data() {
+ return {
+ selectedIntegration: integrationTypesNew[0].value,
+ active: false,
+ formVisible: false,
+ integrationTestPayload: {
+ json: null,
+ error: null,
+ },
+ resetSamplePayloadConfirmed: false,
+ customMapping: null,
+ parsingPayload: false,
+ currentIntegration: null,
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ isManagingOpsgenie: false,
+ };
+ },
+ computed: {
+ isPrometheus() {
+ return this.selectedIntegration === this.$options.typeSet.prometheus;
+ },
+ jsonIsValid() {
+ return this.integrationTestPayload.error === null;
+ },
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ disabledIntegrations() {
+ const options = [];
+ if (this.opsgenie.active) {
+ options.push(typeSet.http, typeSet.prometheus);
+ } else if (!this.canManageOpsgenie) {
+ options.push(typeSet.opsgenie);
+ }
+
+ return options;
+ },
+ options() {
+ return integrationTypesNew.map(el => ({
+ ...el,
+ disabled: this.disabledIntegrations.includes(el.value),
+ }));
+ },
+ selectedIntegrationType() {
+ switch (this.selectedIntegration) {
+ case typeSet.http:
+ return this.generic;
+ case typeSet.prometheus:
+ return this.prometheus;
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ case typeSet.opsgenie:
+ return this.opsgenie;
+ default:
+ return {};
+ }
+ },
+ integrationForm() {
+ return {
+ name: this.currentIntegration?.name || '',
+ active: this.currentIntegration?.active || false,
+ token: this.currentIntegration?.token || this.selectedIntegrationType.token,
+ url: this.currentIntegration?.url || this.selectedIntegrationType.url,
+ apiUrl: this.currentIntegration?.apiUrl || '',
+ };
+ },
+ testAlertPayload() {
+ return {
+ data: this.integrationTestPayload.json,
+ endpoint: this.integrationForm.url,
+ token: this.integrationForm.token,
+ };
+ },
+ showMappingBuilder() {
+ return (
+ this.glFeatures.multipleHttpIntegrationsCustomMapping &&
+ this.selectedIntegration === typeSet.http
+ );
+ },
+ mappingBuilderFields() {
+ return this.customMapping?.samplePayload?.payloadAlerFields?.nodes;
+ },
+ mappingBuilderMapping() {
+ return this.customMapping?.storedMapping?.nodes;
+ },
+ hasSamplePayload() {
+ return Boolean(this.customMapping?.samplePayload);
+ },
+ canEditPayload() {
+ return this.hasSamplePayload && !this.resetSamplePayloadConfirmed;
+ },
+ isPayloadEditDisabled() {
+ return !this.active || this.canEditPayload;
+ },
+ },
+ watch: {
+ currentIntegration(val) {
+ if (val === null) {
+ return this.reset();
+ }
+ this.selectedIntegration = val.type;
+ this.active = val.active;
+ if (val.type === typeSet.http) this.getIntegrationMapping(val.id);
+ return this.integrationTypeSelect();
+ },
+ },
+ methods: {
+ integrationTypeSelect() {
+ if (this.selectedIntegration === integrationTypesNew[0].value) {
+ this.formVisible = false;
+ } else {
+ this.formVisible = true;
+ }
+
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ if (this.canManageOpsgenie && this.selectedIntegration === typeSet.opsgenie) {
+ this.isManagingOpsgenie = true;
+ this.active = this.opsgenie.active;
+ this.integrationForm.apiUrl = this.opsgenie.opsgenieMvcTargetUrl;
+ } else {
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ this.isManagingOpsgenie = false;
+ }
+ },
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ submitWithOpsgenie() {
+ return service
+ .updateGenericActive({
+ endpoint: this.opsgenie.formPath,
+ params: {
+ service: {
+ opsgenie_mvc_target_url: this.integrationForm.apiUrl,
+ opsgenie_mvc_enabled: this.active,
+ },
+ },
+ })
+ .then(() => {
+ window.location.hash = sectionHash;
+ window.location.reload();
+ });
+ },
+ submitWithTestPayload() {
+ return service
+ .updateTestAlert(this.testAlertPayload)
+ .then(() => {
+ this.submit();
+ })
+ .catch(() => {
+ this.$emit('test-payload-failure');
+ });
+ },
+ submit() {
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ if (this.isManagingOpsgenie) {
+ return this.submitWithOpsgenie();
+ }
+
+ const { name, apiUrl } = this.integrationForm;
+ const variables =
+ this.selectedIntegration === typeSet.http
+ ? { name, active: this.active }
+ : { apiUrl, active: this.active };
+ const integrationPayload = { type: this.selectedIntegration, variables };
+
+ if (this.currentIntegration) {
+ return this.$emit('update-integration', integrationPayload);
+ }
+
+ return this.$emit('create-new-integration', integrationPayload);
+ },
+ reset() {
+ this.selectedIntegration = integrationTypesNew[0].value;
+ this.integrationTypeSelect();
+
+ if (this.currentIntegration) {
+ return this.$emit('clear-current-integration');
+ }
+
+ return this.resetFormValues();
+ },
+ resetFormValues() {
+ this.integrationForm.name = '';
+ this.integrationForm.apiUrl = '';
+ this.integrationTestPayload = {
+ json: null,
+ error: null,
+ };
+ this.active = false;
+
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ this.isManagingOpsgenie = false;
+ },
+ resetAuthKey() {
+ if (!this.currentIntegration) {
+ return;
+ }
+
+ this.$emit('reset-token', {
+ type: this.selectedIntegration,
+ variables: { id: this.currentIntegration.id },
+ });
+ },
+ validateJson() {
+ this.integrationTestPayload.error = null;
+ if (this.integrationTestPayload.json === '') {
+ return;
+ }
+
+ try {
+ JSON.parse(this.integrationTestPayload.json);
+ } catch (e) {
+ this.integrationTestPayload.error = JSON.stringify(e.message);
+ }
+ },
+ parseMapping() {
+ // TODO: replace with real BE mutation when ready;
+ this.parsingPayload = true;
+
+ return new Promise(resolve => {
+ setTimeout(() => resolve(mockedCustomMapping), 1000);
+ })
+ .then(res => {
+ const mapping = { ...res };
+ delete mapping.storedMapping;
+ this.customMapping = res;
+ this.integrationTestPayload.json = res?.samplePayload.body;
+ this.resetSamplePayloadConfirmed = false;
+
+ this.$toast.show(this.$options.i18n.integrationFormSteps.step4.payloadParsedSucessMsg);
+ })
+ .finally(() => {
+ this.parsingPayload = false;
+ });
+ },
+ getIntegrationMapping() {
+ // TODO: replace with real BE mutation when ready;
+ return Promise.resolve(mockedCustomMapping).then(res => {
+ this.customMapping = res;
+ this.integrationTestPayload.json = res?.samplePayload.body;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form class="gl-mt-6" @submit.prevent="submit" @reset.prevent="reset">
+ <h5 class="gl-font-lg gl-my-5">{{ s__('AlertSettings|Add new integrations') }}</h5>
+ <gl-form-group
+ id="integration-type"
+ :label="$options.i18n.integrationFormSteps.step1.label"
+ label-for="integration-type"
+ >
+ <gl-form-select
+ v-model="selectedIntegration"
+ :disabled="currentIntegration !== null || !canAddIntegration"
+ :options="options"
+ @change="integrationTypeSelect"
+ />
+
+ <div v-if="!canAddIntegration" class="gl-my-4" data-testid="multi-integrations-not-supported">
+ <alert-settings-form-help-block
+ :message="$options.i18n.integrationFormSteps.step1.enterprise"
+ link="https://about.gitlab.com/pricing"
+ />
+ </div>
+ </gl-form-group>
+ <gl-collapse v-model="formVisible" class="gl-mt-3">
+ <!-- TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657 -->
+ <div v-if="isManagingOpsgenie">
+ <gl-form-group
+ id="integration-webhook"
+ :label="$options.i18n.integrationFormSteps.opsgenie.label"
+ label-for="integration-webhook"
+ >
+ <span class="gl-my-4">
+ {{ $options.i18n.integrationFormSteps.opsgenie.info }}
+ </span>
+
+ <gl-toggle
+ v-model="active"
+ :is-loading="loading"
+ :label="__('Active')"
+ class="gl-my-4 gl-font-weight-normal"
+ />
+
+ <gl-form-input
+ id="opsgenie-opsgenieMvcTargetUrl"
+ v-model="integrationForm.apiUrl"
+ type="text"
+ :placeholder="$options.placeholders.opsgenie"
+ />
+
+ <span class="gl-text-gray-400 gl-my-1">
+ {{ $options.i18n.integrationFormSteps.prometheusFormUrl.help }}
+ </span>
+ </gl-form-group>
+ </div>
+ <div v-else>
+ <gl-form-group
+ id="name-integration"
+ :label="$options.i18n.integrationFormSteps.step2.label"
+ label-for="name-integration"
+ >
+ <gl-form-input
+ v-model="integrationForm.name"
+ type="text"
+ :placeholder="$options.i18n.integrationFormSteps.step2.placeholder"
+ />
+ </gl-form-group>
+ <gl-form-group
+ id="integration-webhook"
+ :label="$options.i18n.integrationFormSteps.step3.label"
+ label-for="integration-webhook"
+ >
+ <alert-settings-form-help-block
+ :message="
+ isPrometheus
+ ? $options.i18n.integrationFormSteps.step3.prometheusHelp
+ : $options.i18n.integrationFormSteps.step3.help
+ "
+ link="https://docs.gitlab.com/ee/operations/incident_management/alert_integrations.html"
+ />
+
+ <gl-toggle
+ v-model="active"
+ :is-loading="loading"
+ :label="__('Active')"
+ class="gl-my-4 gl-font-weight-normal"
+ />
+
+ <div v-if="isPrometheus" class="gl-my-4">
+ <span class="gl-font-weight-bold">
+ {{ $options.i18n.integrationFormSteps.prometheusFormUrl.label }}
+ </span>
+
+ <gl-form-input
+ id="integration-apiUrl"
+ v-model="integrationForm.apiUrl"
+ type="text"
+ :placeholder="$options.placeholders.prometheus"
+ />
+
+ <span class="gl-text-gray-400">
+ {{ $options.i18n.integrationFormSteps.prometheusFormUrl.help }}
+ </span>
+ </div>
+
+ <div class="gl-my-4">
+ <span class="gl-font-weight-bold">
+ {{ s__('AlertSettings|Webhook URL') }}
+ </span>
+
+ <gl-form-input-group id="url" readonly :value="integrationForm.url">
+ <template #append>
+ <clipboard-button
+ :text="integrationForm.url || ''"
+ :title="__('Copy')"
+ class="gl-m-0!"
+ />
+ </template>
+ </gl-form-input-group>
+ </div>
+
+ <div class="gl-my-4">
+ <span class="gl-font-weight-bold">
+ {{ $options.i18n.integrationFormSteps.step3.info }}
+ </span>
+
+ <gl-form-input-group
+ id="authorization-key"
+ class="gl-mb-3"
+ readonly
+ :value="integrationForm.token"
+ >
+ <template #append>
+ <clipboard-button
+ :text="integrationForm.token || ''"
+ :title="__('Copy')"
+ class="gl-m-0!"
+ />
+ </template>
+ </gl-form-input-group>
+
+ <gl-button v-gl-modal.authKeyModal :disabled="!active">
+ {{ $options.i18n.integrationFormSteps.step3.reset }}
+ </gl-button>
+ <gl-modal
+ modal-id="authKeyModal"
+ :title="$options.i18n.integrationFormSteps.step3.reset"
+ :ok-title="$options.i18n.integrationFormSteps.step3.reset"
+ ok-variant="danger"
+ @ok="resetAuthKey"
+ >
+ {{ $options.i18n.integrationFormSteps.restKeyInfo.label }}
+ </gl-modal>
+ </div>
+ </gl-form-group>
+
+ <gl-form-group
+ id="test-integration"
+ :label="$options.i18n.integrationFormSteps.step4.label"
+ label-for="test-integration"
+ :class="{ 'gl-mb-0!': showMappingBuilder }"
+ :invalid-feedback="integrationTestPayload.error"
+ >
+ <alert-settings-form-help-block
+ :message="
+ isPrometheus || !showMappingBuilder
+ ? $options.i18n.integrationFormSteps.step4.prometheusHelp
+ : $options.i18n.integrationFormSteps.step4.help
+ "
+ :link="generic.alertsUsageUrl"
+ />
+
+ <gl-form-textarea
+ id="test-payload"
+ v-model.trim="integrationTestPayload.json"
+ :disabled="isPayloadEditDisabled"
+ :state="jsonIsValid"
+ :placeholder="$options.i18n.integrationFormSteps.step4.placeholder"
+ class="gl-my-3"
+ :debounce="$options.JSON_VALIDATE_DELAY"
+ rows="6"
+ max-rows="10"
+ @input="validateJson"
+ />
+ </gl-form-group>
+
+ <template v-if="showMappingBuilder">
+ <gl-button
+ v-if="canEditPayload"
+ v-gl-modal.resetPayloadModal
+ data-testid="payload-action-btn"
+ :disabled="!active"
+ class="gl-mt-3"
+ >
+ {{ $options.i18n.integrationFormSteps.step4.editPayload }}
+ </gl-button>
+
+ <gl-button
+ v-else
+ data-testid="payload-action-btn"
+ :class="{ 'gl-mt-3': integrationTestPayload.error }"
+ :disabled="!active"
+ :loading="parsingPayload"
+ @click="parseMapping"
+ >
+ {{ $options.i18n.integrationFormSteps.step4.submitPayload }}
+ </gl-button>
+ <gl-modal
+ modal-id="resetPayloadModal"
+ :title="$options.i18n.integrationFormSteps.step4.resetHeader"
+ :ok-title="$options.i18n.integrationFormSteps.step4.resetOk"
+ ok-variant="danger"
+ @ok="resetSamplePayloadConfirmed = true"
+ >
+ {{ $options.i18n.integrationFormSteps.step4.resetBody }}
+ </gl-modal>
+ </template>
+
+ <gl-form-group
+ v-if="showMappingBuilder"
+ id="mapping-builder"
+ class="gl-mt-5"
+ :label="$options.i18n.integrationFormSteps.step5.label"
+ label-for="mapping-builder"
+ >
+ <span>{{ $options.i18n.integrationFormSteps.step5.intro }}</span>
+ <mapping-builder
+ :payload-fields="mappingBuilderFields"
+ :mapping="mappingBuilderMapping"
+ />
+ </gl-form-group>
+ </div>
+ <div class="gl-display-flex gl-justify-content-start gl-py-3">
+ <gl-button
+ type="submit"
+ variant="success"
+ class="js-no-auto-disable"
+ data-testid="integration-form-submit"
+ >{{ s__('AlertSettings|Save integration') }}
+ </gl-button>
+ <!-- TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657 -->
+ <gl-button
+ v-if="!isManagingOpsgenie"
+ data-testid="integration-test-and-submit"
+ :disabled="Boolean(integrationTestPayload.error)"
+ category="secondary"
+ variant="success"
+ class="gl-mx-3 js-no-auto-disable"
+ @click="submitWithTestPayload"
+ >{{ s__('AlertSettings|Save and test payload') }}</gl-button
+ >
+ <gl-button
+ type="reset"
+ class="js-no-auto-disable"
+ :class="{ 'gl-ml-3': isManagingOpsgenie }"
+ >{{ __('Cancel') }}</gl-button
+ >
+ </div>
+ </gl-collapse>
+ </gl-form>
+</template>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_form_old.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_form_old.vue
new file mode 100644
index 00000000000..0246315bdc5
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_form_old.vue
@@ -0,0 +1,494 @@
+<script>
+import {
+ GlAlert,
+ GlButton,
+ GlForm,
+ GlFormGroup,
+ GlFormInput,
+ GlFormInputGroup,
+ GlFormTextarea,
+ GlLink,
+ GlModal,
+ GlModalDirective,
+ GlSprintf,
+ GlFormSelect,
+} from '@gitlab/ui';
+import { debounce } from 'lodash';
+import { doesHashExistInUrl } from '~/lib/utils/url_utility';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import ToggleButton from '~/vue_shared/components/toggle_button.vue';
+import csrf from '~/lib/utils/csrf';
+import service from '../services';
+import {
+ i18n,
+ integrationTypes,
+ JSON_VALIDATE_DELAY,
+ targetPrometheusUrlPlaceholder,
+ targetOpsgenieUrlPlaceholder,
+ sectionHash,
+} from '../constants';
+import createFlash, { FLASH_TYPES } from '~/flash';
+
+export default {
+ i18n,
+ csrf,
+ targetOpsgenieUrlPlaceholder,
+ targetPrometheusUrlPlaceholder,
+ components: {
+ GlAlert,
+ GlButton,
+ GlForm,
+ GlFormGroup,
+ GlFormInput,
+ GlFormInputGroup,
+ GlFormSelect,
+ GlFormTextarea,
+ GlLink,
+ GlModal,
+ GlSprintf,
+ ClipboardButton,
+ ToggleButton,
+ },
+ directives: {
+ 'gl-modal': GlModalDirective,
+ },
+ inject: ['prometheus', 'generic', 'opsgenie'],
+ data() {
+ return {
+ loading: false,
+ selectedIntegration: integrationTypes[0].value,
+ options: integrationTypes,
+ active: false,
+ token: '',
+ targetUrl: '',
+ feedback: {
+ variant: 'danger',
+ feedbackMessage: '',
+ isFeedbackDismissed: false,
+ },
+ testAlert: {
+ json: null,
+ error: null,
+ },
+ canSaveForm: false,
+ serverError: null,
+ };
+ },
+ computed: {
+ sections() {
+ return [
+ {
+ text: this.$options.i18n.usageSection,
+ url: this.generic.alertsUsageUrl,
+ },
+ {
+ text: this.$options.i18n.setupSection,
+ url: this.generic.alertsSetupUrl,
+ },
+ ];
+ },
+ isPrometheus() {
+ return this.selectedIntegration === 'PROMETHEUS';
+ },
+ isOpsgenie() {
+ return this.selectedIntegration === 'OPSGENIE';
+ },
+ selectedIntegrationType() {
+ switch (this.selectedIntegration) {
+ case 'HTTP': {
+ return {
+ url: this.generic.url,
+ token: this.generic.token,
+ active: this.generic.active,
+ resetKey: this.resetKey.bind(this),
+ };
+ }
+ case 'PROMETHEUS': {
+ return {
+ url: this.prometheus.url,
+ token: this.prometheus.token,
+ active: this.prometheus.active,
+ resetKey: this.resetKey.bind(this, 'PROMETHEUS'),
+ targetUrl: this.prometheus.prometheusApiUrl,
+ };
+ }
+ case 'OPSGENIE': {
+ return {
+ targetUrl: this.opsgenie.opsgenieMvcTargetUrl,
+ active: this.opsgenie.active,
+ };
+ }
+ default: {
+ return {};
+ }
+ }
+ },
+ showFeedbackMsg() {
+ return this.feedback.feedbackMessage && !this.isFeedbackDismissed;
+ },
+ showAlertSave() {
+ return (
+ this.feedback.feedbackMessage === this.$options.i18n.testAlertFailed &&
+ !this.isFeedbackDismissed
+ );
+ },
+ prometheusInfo() {
+ return this.isPrometheus ? this.$options.i18n.prometheusInfo : '';
+ },
+ jsonIsValid() {
+ return this.testAlert.error === null;
+ },
+ canTestAlert() {
+ return this.active && this.testAlert.json !== null;
+ },
+ canSaveConfig() {
+ return !this.loading && this.canSaveForm;
+ },
+ baseUrlPlaceholder() {
+ return this.isOpsgenie
+ ? this.$options.targetOpsgenieUrlPlaceholder
+ : this.$options.targetPrometheusUrlPlaceholder;
+ },
+ },
+ watch: {
+ 'testAlert.json': debounce(function debouncedJsonValidate() {
+ this.validateJson();
+ }, JSON_VALIDATE_DELAY),
+ targetUrl(oldVal, newVal) {
+ if (newVal && oldVal !== this.selectedIntegrationType.targetUrl) {
+ this.canSaveForm = true;
+ }
+ },
+ },
+ mounted() {
+ if (this.prometheus.active || this.generic.active || !this.opsgenie.opsgenieMvcIsAvailable) {
+ this.removeOpsGenieOption();
+ } else if (this.opsgenie.active) {
+ this.setOpsgenieAsDefault();
+ }
+ this.active = this.selectedIntegrationType.active;
+ this.token = this.selectedIntegrationType.token ?? '';
+ },
+ methods: {
+ createUserErrorMessage(errors = {}) {
+ const error = Object.entries(errors)?.[0];
+ if (error) {
+ const [field, [msg]] = error;
+ this.serverError = `${field} ${msg}`;
+ }
+ },
+ setOpsgenieAsDefault() {
+ this.options = this.options.map(el => {
+ if (el.value !== 'OPSGENIE') {
+ return { ...el, disabled: true };
+ }
+ return { ...el, disabled: false };
+ });
+ this.selectedIntegration = this.options.find(({ value }) => value === 'OPSGENIE').value;
+ if (this.targetUrl === null) {
+ this.targetUrl = this.selectedIntegrationType.targetUrl;
+ }
+ },
+ removeOpsGenieOption() {
+ this.options = this.options.map(el => {
+ if (el.value !== 'OPSGENIE') {
+ return { ...el, disabled: false };
+ }
+ return { ...el, disabled: true };
+ });
+ },
+ resetFormValues() {
+ this.testAlert.json = null;
+ this.targetUrl = this.selectedIntegrationType.targetUrl;
+ this.active = this.selectedIntegrationType.active;
+ },
+ dismissFeedback() {
+ this.serverError = null;
+ this.feedback = { ...this.feedback, feedbackMessage: null };
+ this.isFeedbackDismissed = false;
+ },
+ resetKey(key) {
+ const fn = key === 'PROMETHEUS' ? this.resetPrometheusKey() : this.resetGenericKey();
+
+ return fn
+ .then(({ data: { token } }) => {
+ this.token = token;
+ this.setFeedback({ feedbackMessage: this.$options.i18n.tokenRest, variant: 'success' });
+ })
+ .catch(() => {
+ this.setFeedback({ feedbackMessage: this.$options.i18n.errorKeyMsg, variant: 'danger' });
+ });
+ },
+ resetGenericKey() {
+ this.dismissFeedback();
+ return service.updateGenericKey({
+ endpoint: this.generic.formPath,
+ params: { service: { token: '' } },
+ });
+ },
+ resetPrometheusKey() {
+ return service.updatePrometheusKey({ endpoint: this.prometheus.prometheusResetKeyPath });
+ },
+ toggleService(value) {
+ this.canSaveForm = true;
+ this.active = value;
+ },
+ toggle(value) {
+ return this.isPrometheus ? this.togglePrometheusActive(value) : this.toggleActivated(value);
+ },
+ toggleActivated(value) {
+ this.loading = true;
+ const path = this.isOpsgenie ? this.opsgenie.formPath : this.generic.formPath;
+ return service
+ .updateGenericActive({
+ endpoint: path,
+ params: this.isOpsgenie
+ ? { service: { opsgenie_mvc_target_url: this.targetUrl, opsgenie_mvc_enabled: value } }
+ : { service: { active: value } },
+ })
+ .then(() => this.notifySuccessAndReload())
+ .catch(({ response: { data: { errors } = {} } = {} }) => {
+ this.createUserErrorMessage(errors);
+ this.setFeedback({
+ feedbackMessage: this.$options.i18n.errorMsg,
+ variant: 'danger',
+ });
+ })
+ .finally(() => {
+ this.loading = false;
+ this.canSaveForm = false;
+ });
+ },
+ reload() {
+ if (!doesHashExistInUrl(sectionHash)) {
+ window.location.hash = sectionHash;
+ }
+ window.location.reload();
+ },
+ togglePrometheusActive(value) {
+ this.loading = true;
+ return service
+ .updatePrometheusActive({
+ endpoint: this.prometheus.prometheusFormPath,
+ params: {
+ token: this.$options.csrf.token,
+ config: value,
+ url: this.targetUrl,
+ redirect: window.location,
+ },
+ })
+ .then(() => this.notifySuccessAndReload())
+ .catch(({ response: { data: { errors } = {} } = {} }) => {
+ this.createUserErrorMessage(errors);
+ this.setFeedback({
+ feedbackMessage: this.$options.i18n.errorMsg,
+ variant: 'danger',
+ });
+ })
+ .finally(() => {
+ this.loading = false;
+ this.canSaveForm = false;
+ });
+ },
+ notifySuccessAndReload() {
+ createFlash({ message: this.$options.i18n.changesSaved, type: FLASH_TYPES.NOTICE });
+ setTimeout(() => this.reload(), 1000);
+ },
+ setFeedback({ feedbackMessage, variant }) {
+ this.feedback = { feedbackMessage, variant };
+ },
+ validateJson() {
+ this.testAlert.error = null;
+ try {
+ JSON.parse(this.testAlert.json);
+ } catch (e) {
+ this.testAlert.error = JSON.stringify(e.message);
+ }
+ },
+ validateTestAlert() {
+ this.loading = true;
+ this.dismissFeedback();
+ this.validateJson();
+ return service
+ .updateTestAlert({
+ endpoint: this.selectedIntegrationType.url,
+ data: this.testAlert.json,
+ token: this.selectedIntegrationType.token,
+ })
+ .then(() => {
+ this.setFeedback({
+ feedbackMessage: this.$options.i18n.testAlertSuccess,
+ variant: 'success',
+ });
+ })
+ .catch(() => {
+ this.setFeedback({
+ feedbackMessage: this.$options.i18n.testAlertFailed,
+ variant: 'danger',
+ });
+ })
+ .finally(() => {
+ this.loading = false;
+ });
+ },
+ onSubmit() {
+ this.dismissFeedback();
+ this.toggle(this.active);
+ },
+ onReset() {
+ this.testAlert.json = null;
+ this.dismissFeedback();
+ this.targetUrl = this.selectedIntegrationType.targetUrl;
+
+ if (this.canSaveForm) {
+ this.canSaveForm = false;
+ this.active = this.selectedIntegrationType.active;
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form @submit.prevent="onSubmit" @reset.prevent="onReset">
+ <h5 class="gl-font-lg gl-my-5">{{ $options.i18n.integrationsLabel }}</h5>
+
+ <gl-alert v-if="showFeedbackMsg" :variant="feedback.variant" @dismiss="dismissFeedback">
+ {{ feedback.feedbackMessage }}
+ <br />
+ <i v-if="serverError">{{ __('Error message:') }} {{ serverError }}</i>
+ <gl-button
+ v-if="showAlertSave"
+ variant="danger"
+ category="primary"
+ class="gl-display-block gl-mt-3"
+ @click="toggle(active)"
+ >
+ {{ __('Save anyway') }}
+ </gl-button>
+ </gl-alert>
+
+ <div data-testid="alert-settings-description">
+ <p v-for="section in sections" :key="section.text">
+ <gl-sprintf :message="section.text">
+ <template #link="{ content }">
+ <gl-link :href="section.url" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </div>
+
+ <gl-form-group label-for="integration-type" :label="$options.i18n.integration">
+ <gl-form-select
+ id="integration-type"
+ v-model="selectedIntegration"
+ :options="options"
+ data-testid="alert-settings-select"
+ @change="resetFormValues"
+ />
+ <span class="gl-text-gray-500">
+ <gl-sprintf :message="$options.i18n.integrationsInfo">
+ <template #link="{ content }">
+ <gl-link
+ class="gl-display-inline-block"
+ href="https://gitlab.com/groups/gitlab-org/-/epics/4390"
+ target="_blank"
+ >{{ content }}</gl-link
+ >
+ </template>
+ </gl-sprintf>
+ </span>
+ </gl-form-group>
+ <gl-form-group :label="$options.i18n.activeLabel" label-for="active">
+ <toggle-button
+ id="active"
+ :disabled-input="loading"
+ :is-loading="loading"
+ :value="active"
+ @change="toggleService"
+ />
+ </gl-form-group>
+ <gl-form-group
+ v-if="isOpsgenie || isPrometheus"
+ :label="$options.i18n.apiBaseUrlLabel"
+ label-for="api-url"
+ >
+ <gl-form-input
+ id="api-url"
+ v-model="targetUrl"
+ type="url"
+ :placeholder="baseUrlPlaceholder"
+ :disabled="!active"
+ />
+ <span class="gl-text-gray-500">
+ {{ $options.i18n.apiBaseUrlHelpText }}
+ </span>
+ </gl-form-group>
+ <template v-if="!isOpsgenie">
+ <gl-form-group :label="$options.i18n.urlLabel" label-for="url">
+ <gl-form-input-group id="url" readonly :value="selectedIntegrationType.url">
+ <template #append>
+ <clipboard-button
+ :text="selectedIntegrationType.url"
+ :title="$options.i18n.copyToClipboard"
+ class="gl-m-0!"
+ />
+ </template>
+ </gl-form-input-group>
+ <span class="gl-text-gray-500">
+ {{ prometheusInfo }}
+ </span>
+ </gl-form-group>
+ <gl-form-group :label="$options.i18n.tokenLabel" label-for="authorization-key">
+ <gl-form-input-group id="authorization-key" class="gl-mb-2" readonly :value="token">
+ <template #append>
+ <clipboard-button
+ :text="token"
+ :title="$options.i18n.copyToClipboard"
+ class="gl-m-0!"
+ />
+ </template>
+ </gl-form-input-group>
+ <gl-button v-gl-modal.tokenModal :disabled="!active" class="gl-mt-3">{{
+ $options.i18n.resetKey
+ }}</gl-button>
+ <gl-modal
+ modal-id="tokenModal"
+ :title="$options.i18n.resetKey"
+ :ok-title="$options.i18n.resetKey"
+ ok-variant="danger"
+ @ok="selectedIntegrationType.resetKey"
+ >
+ {{ $options.i18n.restKeyInfo }}
+ </gl-modal>
+ </gl-form-group>
+ <gl-form-group
+ :label="$options.i18n.alertJson"
+ label-for="alert-json"
+ :invalid-feedback="testAlert.error"
+ >
+ <gl-form-textarea
+ id="alert-json"
+ v-model.trim="testAlert.json"
+ :disabled="!active"
+ :state="jsonIsValid"
+ :placeholder="$options.i18n.alertJsonPlaceholder"
+ rows="6"
+ max-rows="10"
+ />
+ </gl-form-group>
+
+ <gl-button :disabled="!canTestAlert" @click="validateTestAlert">{{
+ $options.i18n.testAlertInfo
+ }}</gl-button>
+ </template>
+ <div class="footer-block row-content-block gl-display-flex gl-justify-content-space-between">
+ <gl-button variant="success" category="primary" :disabled="!canSaveConfig" @click="onSubmit">
+ {{ __('Save changes') }}
+ </gl-button>
+ <gl-button category="primary" :disabled="!canSaveConfig" @click="onReset">
+ {{ __('Cancel') }}
+ </gl-button>
+ </div>
+ </gl-form>
+</template>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
new file mode 100644
index 00000000000..1ffc2f80148
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
@@ -0,0 +1,331 @@
+<script>
+import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { fetchPolicies } from '~/lib/graphql';
+import createFlash, { FLASH_TYPES } from '~/flash';
+import getIntegrationsQuery from '../graphql/queries/get_integrations.query.graphql';
+import getCurrentIntegrationQuery from '../graphql/queries/get_current_integration.query.graphql';
+import createHttpIntegrationMutation from '../graphql/mutations/create_http_integration.mutation.graphql';
+import createPrometheusIntegrationMutation from '../graphql/mutations/create_prometheus_integration.mutation.graphql';
+import updateHttpIntegrationMutation from '../graphql/mutations/update_http_integration.mutation.graphql';
+import updatePrometheusIntegrationMutation from '../graphql/mutations/update_prometheus_integration.mutation.graphql';
+import destroyHttpIntegrationMutation from '../graphql/mutations/destroy_http_integration.mutation.graphql';
+import resetHttpTokenMutation from '../graphql/mutations/reset_http_token.mutation.graphql';
+import resetPrometheusTokenMutation from '../graphql/mutations/reset_prometheus_token.mutation.graphql';
+import updateCurrentIntergrationMutation from '../graphql/mutations/update_current_intergration.mutation.graphql';
+import IntegrationsList from './alerts_integrations_list.vue';
+import SettingsFormOld from './alerts_settings_form_old.vue';
+import SettingsFormNew from './alerts_settings_form_new.vue';
+import { typeSet } from '../constants';
+import {
+ updateStoreAfterIntegrationDelete,
+ updateStoreAfterIntegrationAdd,
+} from '../utils/cache_updates';
+import {
+ DELETE_INTEGRATION_ERROR,
+ ADD_INTEGRATION_ERROR,
+ RESET_INTEGRATION_TOKEN_ERROR,
+ UPDATE_INTEGRATION_ERROR,
+ INTEGRATION_PAYLOAD_TEST_ERROR,
+} from '../utils/error_messages';
+
+export default {
+ typeSet,
+ i18n: {
+ changesSaved: s__(
+ 'AlertsIntegrations|The integration has been successfully saved. Alerts from this new integration should now appear on your alerts list.',
+ ),
+ integrationRemoved: s__('AlertsIntegrations|The integration has been successfully removed.'),
+ },
+ components: {
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ GlAlert,
+ GlLink,
+ GlSprintf,
+ IntegrationsList,
+ SettingsFormOld,
+ SettingsFormNew,
+ },
+ mixins: [glFeatureFlagsMixin()],
+ inject: {
+ generic: {
+ default: {},
+ },
+ prometheus: {
+ default: {},
+ },
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ opsgenie: {
+ default: {},
+ },
+ projectPath: {
+ default: '',
+ },
+ multiIntegrations: {
+ default: false,
+ },
+ },
+ apollo: {
+ integrations: {
+ fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
+ query: getIntegrationsQuery,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ };
+ },
+ update(data) {
+ const { alertManagementIntegrations: { nodes: list = [] } = {} } = data.project || {};
+
+ return {
+ list,
+ };
+ },
+ error(err) {
+ createFlash({ message: err });
+ },
+ },
+ currentIntegration: {
+ query: getCurrentIntegrationQuery,
+ },
+ },
+ data() {
+ return {
+ isUpdating: false,
+ integrations: {},
+ currentIntegration: null,
+ };
+ },
+ computed: {
+ loading() {
+ return this.$apollo.queries.integrations.loading;
+ },
+ integrationsOptionsOld() {
+ return [
+ {
+ name: s__('AlertSettings|HTTP endpoint'),
+ type: s__('AlertsIntegrations|HTTP endpoint'),
+ active: this.generic.active,
+ },
+ {
+ name: s__('AlertSettings|External Prometheus'),
+ type: s__('AlertsIntegrations|Prometheus'),
+ active: this.prometheus.active,
+ },
+ ];
+ },
+ canAddIntegration() {
+ return this.multiIntegrations || this.integrations?.list?.length < 2;
+ },
+ canManageOpsgenie() {
+ return (
+ this.integrations?.list?.every(({ active }) => active === false) ||
+ this.integrations?.list?.length === 0
+ );
+ },
+ },
+ methods: {
+ createNewIntegration({ type, variables }) {
+ const { projectPath } = this;
+
+ this.isUpdating = true;
+ this.$apollo
+ .mutate({
+ mutation:
+ type === this.$options.typeSet.http
+ ? createHttpIntegrationMutation
+ : createPrometheusIntegrationMutation,
+ variables: {
+ ...variables,
+ projectPath,
+ },
+ update(store, { data }) {
+ updateStoreAfterIntegrationAdd(store, getIntegrationsQuery, data, { projectPath });
+ },
+ })
+ .then(({ data: { httpIntegrationCreate, prometheusIntegrationCreate } = {} } = {}) => {
+ const error = httpIntegrationCreate?.errors[0] || prometheusIntegrationCreate?.errors[0];
+ if (error) {
+ return createFlash({ message: error });
+ }
+ return createFlash({
+ message: this.$options.i18n.changesSaved,
+ type: FLASH_TYPES.SUCCESS,
+ });
+ })
+ .catch(() => {
+ createFlash({ message: ADD_INTEGRATION_ERROR });
+ })
+ .finally(() => {
+ this.isUpdating = false;
+ });
+ },
+ updateIntegration({ type, variables }) {
+ this.isUpdating = true;
+ this.$apollo
+ .mutate({
+ mutation:
+ type === this.$options.typeSet.http
+ ? updateHttpIntegrationMutation
+ : updatePrometheusIntegrationMutation,
+ variables: {
+ ...variables,
+ id: this.currentIntegration.id,
+ },
+ })
+ .then(({ data: { httpIntegrationUpdate, prometheusIntegrationUpdate } = {} } = {}) => {
+ const error = httpIntegrationUpdate?.errors[0] || prometheusIntegrationUpdate?.errors[0];
+ if (error) {
+ return createFlash({ message: error });
+ }
+ return createFlash({
+ message: this.$options.i18n.changesSaved,
+ type: FLASH_TYPES.SUCCESS,
+ });
+ })
+ .catch(() => {
+ createFlash({ message: UPDATE_INTEGRATION_ERROR });
+ })
+ .finally(() => {
+ this.isUpdating = false;
+ });
+ },
+ resetToken({ type, variables }) {
+ this.isUpdating = true;
+ this.$apollo
+ .mutate({
+ mutation:
+ type === this.$options.typeSet.http
+ ? resetHttpTokenMutation
+ : resetPrometheusTokenMutation,
+ variables,
+ })
+ .then(
+ ({ data: { httpIntegrationResetToken, prometheusIntegrationResetToken } = {} } = {}) => {
+ const error =
+ httpIntegrationResetToken?.errors[0] || prometheusIntegrationResetToken?.errors[0];
+ if (error) {
+ return createFlash({ message: error });
+ }
+
+ const integration =
+ httpIntegrationResetToken?.integration ||
+ prometheusIntegrationResetToken?.integration;
+ this.currentIntegration = integration;
+
+ return createFlash({
+ message: this.$options.i18n.changesSaved,
+ type: FLASH_TYPES.SUCCESS,
+ });
+ },
+ )
+ .catch(() => {
+ createFlash({ message: RESET_INTEGRATION_TOKEN_ERROR });
+ })
+ .finally(() => {
+ this.isUpdating = false;
+ });
+ },
+ editIntegration({ id }) {
+ const currentIntegration = this.integrations.list.find(integration => integration.id === id);
+ this.$apollo.mutate({
+ mutation: updateCurrentIntergrationMutation,
+ variables: {
+ id: currentIntegration.id,
+ name: currentIntegration.name,
+ active: currentIntegration.active,
+ token: currentIntegration.token,
+ type: currentIntegration.type,
+ url: currentIntegration.url,
+ apiUrl: currentIntegration.apiUrl,
+ },
+ });
+ },
+ deleteIntegration({ id }) {
+ const { projectPath } = this;
+
+ this.isUpdating = true;
+ this.$apollo
+ .mutate({
+ mutation: destroyHttpIntegrationMutation,
+ variables: {
+ id,
+ },
+ update(store, { data }) {
+ updateStoreAfterIntegrationDelete(store, getIntegrationsQuery, data, { projectPath });
+ },
+ })
+ .then(({ data: { httpIntegrationDestroy } = {} } = {}) => {
+ const error = httpIntegrationDestroy?.errors[0];
+ if (error) {
+ return createFlash({ message: error });
+ }
+ this.clearCurrentIntegration();
+ return createFlash({
+ message: this.$options.i18n.integrationRemoved,
+ type: FLASH_TYPES.SUCCESS,
+ });
+ })
+ .catch(() => {
+ createFlash({ message: DELETE_INTEGRATION_ERROR });
+ })
+ .finally(() => {
+ this.isUpdating = false;
+ });
+ },
+ clearCurrentIntegration() {
+ this.$apollo.mutate({
+ mutation: updateCurrentIntergrationMutation,
+ variables: {},
+ });
+ },
+ testPayloadFailure() {
+ createFlash({ message: INTEGRATION_PAYLOAD_TEST_ERROR });
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <!-- TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657 -->
+ <gl-alert v-if="opsgenie.active" :dismissible="false" variant="tip">
+ <gl-sprintf
+ :message="
+ s__(
+ 'AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}',
+ )
+ "
+ >
+ <template #link="{ content }">
+ <gl-link
+ class="gl-display-inline-block"
+ href="https://gitlab.com/gitlab-org/gitlab/-/issues/273657"
+ target="_blank"
+ >{{ content }}</gl-link
+ >
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+ <integrations-list
+ v-else
+ :integrations="glFeatures.httpIntegrationsList ? integrations.list : integrationsOptionsOld"
+ :loading="loading"
+ @edit-integration="editIntegration"
+ @delete-integration="deleteIntegration"
+ />
+ <settings-form-new
+ v-if="glFeatures.httpIntegrationsList"
+ :loading="isUpdating"
+ :can-add-integration="canAddIntegration"
+ :can-manage-opsgenie="canManageOpsgenie"
+ @create-new-integration="createNewIntegration"
+ @update-integration="updateIntegration"
+ @reset-token="resetToken"
+ @clear-current-integration="clearCurrentIntegration"
+ @test-payload-failure="testPayloadFailure"
+ />
+ <settings-form-old v-else />
+ </div>
+</template>
diff --git a/app/assets/javascripts/alerts_settings/components/mocks/gitlabFields.json b/app/assets/javascripts/alerts_settings/components/mocks/gitlabFields.json
new file mode 100644
index 00000000000..ac559a30eda
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/components/mocks/gitlabFields.json
@@ -0,0 +1,112 @@
+[
+ {
+ "name": "title",
+ "label": "Title",
+ "type": [
+ "String"
+ ],
+ "compatibleTypes": [
+ "String",
+ "Number",
+ "DateTime"
+ ],
+ "numberOfFallbacks": 1
+ },
+ {
+ "name": "description",
+ "label": "Description",
+ "type": [
+ "String"
+ ],
+ "compatibleTypes": [
+ "String",
+ "Number",
+ "DateTime"
+ ]
+ },
+ {
+ "name": "startTime",
+ "label": "Start time",
+ "type": [
+ "DateTime"
+ ],
+ "compatibleTypes": [
+ "Number",
+ "DateTime"
+ ]
+ },
+ {
+ "name": "service",
+ "label": "Service",
+ "type": [
+ "String"
+ ],
+ "compatibleTypes": [
+ "String",
+ "Number",
+ "DateTime"
+ ]
+ },
+ {
+ "name": "monitoringTool",
+ "label": "Monitoring tool",
+ "type": [
+ "String"
+ ],
+ "compatibleTypes": [
+ "String",
+ "Number",
+ "DateTime"
+ ]
+ },
+ {
+ "name": "hosts",
+ "label": "Hosts",
+ "type": [
+ "String",
+ "Array"
+ ],
+ "compatibleTypes": [
+ "String",
+ "Array",
+ "Number",
+ "DateTime"
+ ]
+ },
+ {
+ "name": "severity",
+ "label": "Severity",
+ "type": [
+ "String"
+ ],
+ "compatibleTypes": [
+ "String",
+ "Number",
+ "DateTime"
+ ]
+ },
+ {
+ "name": "fingerprint",
+ "label": "Fingerprint",
+ "type": [
+ "String"
+ ],
+ "compatibleTypes": [
+ "String",
+ "Number",
+ "DateTime"
+ ]
+ },
+ {
+ "name": "environment",
+ "label": "Environment",
+ "type": [
+ "String"
+ ],
+ "compatibleTypes": [
+ "String",
+ "Number",
+ "DateTime"
+ ]
+ }
+]
diff --git a/app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json b/app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json
new file mode 100644
index 00000000000..5326678155d
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json
@@ -0,0 +1,121 @@
+{
+ "samplePayload": {
+ "body": "{\n \"dashboardId\":1,\n \"evalMatches\":[\n {\n \"value\":1,\n \"metric\":\"Count\",\n \"tags\":{}\n }\n ],\n \"imageUrl\":\"https://grafana.com/static/assets/img/blog/mixed_styles.png\",\n \"message\":\"Notification Message\",\n \"orgId\":1,\n \"panelId\":2,\n \"ruleId\":1,\n \"ruleName\":\"Panel Title alert\",\n \"ruleUrl\":\"http://localhost:3000/d/hZ7BuVbWz/test-dashboard?fullscreen\\u0026edit\\u0026tab=alert\\u0026panelId=2\\u0026orgId=1\",\n \"state\":\"alerting\",\n \"tags\":{\n \"tag name\":\"tag value\"\n },\n \"title\":\"[Alerting] Panel Title alert\"\n}\n",
+ "payloadAlerFields": {
+ "nodes": [
+ {
+ "name": "dashboardId",
+ "label": "Dashboard Id",
+ "type": [
+ "Number"
+ ]
+ },
+ {
+ "name": "evalMatches",
+ "label": "Eval Matches",
+ "type": [
+ "Array"
+ ]
+ },
+ {
+ "name": "createdAt",
+ "label": "Created At",
+ "type": [
+ "DateTime"
+ ]
+ },
+ {
+ "name": "imageUrl",
+ "label": "Image Url",
+ "type": [
+ "String"
+ ]
+ },
+ {
+ "name": "message",
+ "label": "Message",
+ "type": [
+ "String"
+ ]
+ },
+ {
+ "name": "orgId",
+ "label": "Org Id",
+ "type": [
+ "Number"
+ ]
+ },
+ {
+ "name": "panelId",
+ "label": "Panel Id",
+ "type": [
+ "String"
+ ]
+ },
+ {
+ "name": "ruleId",
+ "label": "Rule Id",
+ "type": [
+ "Number"
+ ]
+ },
+ {
+ "name": "ruleName",
+ "label": "Rule Name",
+ "type": [
+ "String"
+ ]
+ },
+ {
+ "name": "ruleUrl",
+ "label": "Rule Url",
+ "type": [
+ "String"
+ ]
+ },
+ {
+ "name": "state",
+ "label": "State",
+ "type": [
+ "String"
+ ]
+ },
+ {
+ "name": "title",
+ "label": "Title",
+ "type": [
+ "String"
+ ]
+ },
+ {
+ "name": "tags",
+ "label": "Tags",
+ "type": [
+ "Object"
+ ]
+ }
+ ]
+ }
+ },
+ "storedMapping": {
+ "nodes": [
+ {
+ "alertFieldName": "title",
+ "payloadAlertPaths": "title",
+ "fallbackAlertPaths": "ruleUrl"
+ },
+ {
+ "alertFieldName": "description",
+ "payloadAlertPaths": "message"
+ },
+ {
+ "alertFieldName": "hosts",
+ "payloadAlertPaths": "evalMatches"
+ },
+ {
+ "alertFieldName": "startTime",
+ "payloadAlertPaths": "createdAt"
+ }
+ ]
+ }
+}
diff --git a/app/assets/javascripts/alerts_settings/constants.js b/app/assets/javascripts/alerts_settings/constants.js
index 4220dbde0c7..e30dc2ad553 100644
--- a/app/assets/javascripts/alerts_settings/constants.js
+++ b/app/assets/javascripts/alerts_settings/constants.js
@@ -1,5 +1,6 @@
import { s__ } from '~/locale';
+// TODO: Remove this as part of the form old removal
export const i18n = {
usageSection: s__(
'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.',
@@ -17,11 +18,10 @@ export const i18n = {
changesSaved: s__('AlertSettings|Your integration was successfully updated.'),
prometheusInfo: s__('AlertSettings|Add URL and auth key to your Prometheus config file'),
integrationsInfo: s__(
- 'AlertSettings|Learn more about our improvements for %{linkStart}integrations%{linkEnd}',
+ 'AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}',
),
resetKey: s__('AlertSettings|Reset key'),
copyToClipboard: s__('AlertSettings|Copy'),
- integrationsLabel: s__('AlertSettings|Add new integrations'),
apiBaseUrlLabel: s__('AlertSettings|API URL'),
authKeyLabel: s__('AlertSettings|Authorization key'),
urlLabel: s__('AlertSettings|Webhook URL'),
@@ -40,12 +40,26 @@ export const i18n = {
integration: s__('AlertSettings|Integration'),
};
-export const serviceOptions = [
- { value: 'generic', text: s__('AlertSettings|HTTP Endpoint') },
- { value: 'prometheus', text: s__('AlertSettings|External Prometheus') },
- { value: 'opsgenie', text: s__('AlertSettings|Opsgenie') },
+// TODO: Delete as part of old form removal in 13.6
+export const integrationTypes = [
+ { value: 'HTTP', text: s__('AlertSettings|HTTP Endpoint') },
+ { value: 'PROMETHEUS', text: s__('AlertSettings|External Prometheus') },
+ { value: 'OPSGENIE', text: s__('AlertSettings|Opsgenie') },
];
+export const integrationTypesNew = [
+ { value: '', text: s__('AlertSettings|Select integration type') },
+ ...integrationTypes,
+];
+
+export const typeSet = {
+ http: 'HTTP',
+ prometheus: 'PROMETHEUS',
+ opsgenie: 'OPSGENIE',
+};
+
+export const integrationToDeleteDefault = { id: null, name: '' };
+
export const JSON_VALIDATE_DELAY = 250;
export const targetPrometheusUrlPlaceholder = 'http://prometheus.example.com/';
@@ -56,9 +70,9 @@ export const sectionHash = 'js-alert-management-settings';
/* eslint-disable @gitlab/require-i18n-strings */
/**
- * Tracks snowplow event when user views alerts intergration list
+ * Tracks snowplow event when user views alerts integration list
*/
-export const trackAlertIntergrationsViewsOptions = {
- category: 'Alert Intergrations',
+export const trackAlertIntegrationsViewsOptions = {
+ category: 'Alert Integrations',
action: 'view_alert_integrations_list',
};
diff --git a/app/assets/javascripts/alerts_settings/graphql.js b/app/assets/javascripts/alerts_settings/graphql.js
new file mode 100644
index 00000000000..02c2def87fa
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql.js
@@ -0,0 +1,44 @@
+import Vue from 'vue';
+import produce from 'immer';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import getCurrentIntegrationQuery from './graphql/queries/get_current_integration.query.graphql';
+
+Vue.use(VueApollo);
+
+const resolvers = {
+ Mutation: {
+ updateCurrentIntegration: (
+ _,
+ { id = null, name, active, token, type, url, apiUrl },
+ { cache },
+ ) => {
+ const sourceData = cache.readQuery({ query: getCurrentIntegrationQuery });
+ const data = produce(sourceData, draftData => {
+ if (id === null) {
+ // eslint-disable-next-line no-param-reassign
+ draftData.currentIntegration = null;
+ } else {
+ // eslint-disable-next-line no-param-reassign
+ draftData.currentIntegration = {
+ id,
+ name,
+ active,
+ token,
+ type,
+ url,
+ apiUrl,
+ };
+ }
+ });
+ cache.writeQuery({ query: getCurrentIntegrationQuery, data });
+ },
+ },
+};
+
+export default new VueApollo({
+ defaultClient: createDefaultClient(resolvers, {
+ cacheConfig: {},
+ assumeImmutableResults: true,
+ }),
+});
diff --git a/app/assets/javascripts/alerts_settings/graphql/fragments/integration_item.fragment.graphql b/app/assets/javascripts/alerts_settings/graphql/fragments/integration_item.fragment.graphql
new file mode 100644
index 00000000000..6d9307959df
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/fragments/integration_item.fragment.graphql
@@ -0,0 +1,9 @@
+fragment IntegrationItem on AlertManagementIntegration {
+ id
+ type
+ active
+ name
+ url
+ token
+ apiUrl
+}
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql
new file mode 100644
index 00000000000..d1dacbad40a
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql
@@ -0,0 +1,10 @@
+#import "../fragments/integration_item.fragment.graphql"
+
+mutation createHttpIntegration($projectPath: ID!, $name: String!, $active: Boolean!) {
+ httpIntegrationCreate(input: { projectPath: $projectPath, name: $name, active: $active }) {
+ errors
+ integration {
+ ...IntegrationItem
+ }
+ }
+}
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql
new file mode 100644
index 00000000000..bb22795ddd5
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql
@@ -0,0 +1,12 @@
+#import "../fragments/integration_item.fragment.graphql"
+
+mutation createPrometheusIntegration($projectPath: ID!, $apiUrl: String!, $active: Boolean!) {
+ prometheusIntegrationCreate(
+ input: { projectPath: $projectPath, apiUrl: $apiUrl, active: $active }
+ ) {
+ errors
+ integration {
+ ...IntegrationItem
+ }
+ }
+}
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql
new file mode 100644
index 00000000000..0a49c140e6a
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql
@@ -0,0 +1,10 @@
+#import "../fragments/integration_item.fragment.graphql"
+
+mutation destroyHttpIntegration($id: ID!) {
+ httpIntegrationDestroy(input: { id: $id }) {
+ errors
+ integration {
+ ...IntegrationItem
+ }
+ }
+}
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql
new file mode 100644
index 00000000000..178d1e13047
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql
@@ -0,0 +1,10 @@
+#import "../fragments/integration_item.fragment.graphql"
+
+mutation resetHttpIntegrationToken($id: ID!) {
+ httpIntegrationResetToken(input: { id: $id }) {
+ errors
+ integration {
+ ...IntegrationItem
+ }
+ }
+}
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/reset_prometheus_token.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/reset_prometheus_token.mutation.graphql
new file mode 100644
index 00000000000..8f34521b9fd
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/reset_prometheus_token.mutation.graphql
@@ -0,0 +1,10 @@
+#import "../fragments/integration_item.fragment.graphql"
+
+mutation resetPrometheusIntegrationToken($id: ID!) {
+ prometheusIntegrationResetToken(input: { id: $id }) {
+ errors
+ integration {
+ ...IntegrationItem
+ }
+ }
+}
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/update_current_intergration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/update_current_intergration.mutation.graphql
new file mode 100644
index 00000000000..3505241309e
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/update_current_intergration.mutation.graphql
@@ -0,0 +1,19 @@
+mutation updateCurrentIntegration(
+ $id: String
+ $name: String
+ $active: Boolean
+ $token: String
+ $type: String
+ $url: String
+ $apiUrl: String
+) {
+ updateCurrentIntegration(
+ id: $id
+ name: $name
+ active: $active
+ token: $token
+ type: $type
+ url: $url
+ apiUrl: $apiUrl
+ ) @client
+}
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql
new file mode 100644
index 00000000000..bb5b334deeb
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql
@@ -0,0 +1,10 @@
+#import "../fragments/integration_item.fragment.graphql"
+
+mutation updateHttpIntegration($id: ID!, $name: String!, $active: Boolean!) {
+ httpIntegrationUpdate(input: { id: $id, name: $name, active: $active }) {
+ errors
+ integration {
+ ...IntegrationItem
+ }
+ }
+}
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/update_prometheus_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/update_prometheus_integration.mutation.graphql
new file mode 100644
index 00000000000..62761730bd2
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/update_prometheus_integration.mutation.graphql
@@ -0,0 +1,10 @@
+#import "../fragments/integration_item.fragment.graphql"
+
+mutation updatePrometheusIntegration($id: ID!, $apiUrl: String!, $active: Boolean!) {
+ prometheusIntegrationUpdate(input: { id: $id, apiUrl: $apiUrl, active: $active }) {
+ errors
+ integration {
+ ...IntegrationItem
+ }
+ }
+}
diff --git a/app/assets/javascripts/alerts_settings/graphql/queries/get_current_integration.query.graphql b/app/assets/javascripts/alerts_settings/graphql/queries/get_current_integration.query.graphql
new file mode 100644
index 00000000000..4f22849a618
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/queries/get_current_integration.query.graphql
@@ -0,0 +1,3 @@
+query currentIntegration {
+ currentIntegration @client
+}
diff --git a/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql b/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
new file mode 100644
index 00000000000..228dd5fb176
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
@@ -0,0 +1,11 @@
+#import "../fragments/integration_item.fragment.graphql"
+
+query getIntegrations($projectPath: ID!) {
+ project(fullPath: $projectPath) {
+ alertManagementIntegrations {
+ nodes {
+ ...IntegrationItem
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/alerts_settings/index.js b/app/assets/javascripts/alerts_settings/index.js
index 8d1d342d229..41b19a675c5 100644
--- a/app/assets/javascripts/alerts_settings/index.js
+++ b/app/assets/javascripts/alerts_settings/index.js
@@ -1,6 +1,15 @@
import Vue from 'vue';
+import { GlToast } from '@gitlab/ui';
import { parseBoolean } from '~/lib/utils/common_utils';
-import AlertSettingsForm from './components/alerts_settings_form.vue';
+import AlertSettingsWrapper from './components/alerts_settings_wrapper.vue';
+import apolloProvider from './graphql';
+
+apolloProvider.clients.defaultClient.cache.writeData({
+ data: {
+ currentIntegration: null,
+ },
+});
+Vue.use(GlToast);
export default el => {
if (!el) {
@@ -24,20 +33,17 @@ export default el => {
opsgenieMvcFormPath,
opsgenieMvcEnabled,
opsgenieMvcTargetUrl,
+ projectPath,
+ multiIntegrations,
} = el.dataset;
- const genericActivated = parseBoolean(activatedStr);
- const prometheusIsActivated = parseBoolean(prometheusActivated);
- const opsgenieMvcActivated = parseBoolean(opsgenieMvcEnabled);
- const opsgenieMvcIsAvailable = parseBoolean(opsgenieMvcAvailable);
-
return new Vue({
el,
provide: {
prometheus: {
- activated: prometheusIsActivated,
- prometheusUrl,
- authorizationKey: prometheusAuthorizationKey,
+ active: parseBoolean(prometheusActivated),
+ url: prometheusUrl,
+ token: prometheusAuthorizationKey,
prometheusFormPath,
prometheusResetKeyPath,
prometheusApiUrl,
@@ -45,23 +51,26 @@ export default el => {
generic: {
alertsSetupUrl,
alertsUsageUrl,
- activated: genericActivated,
+ active: parseBoolean(activatedStr),
formPath,
- authorizationKey,
+ token: authorizationKey,
url,
},
opsgenie: {
formPath: opsgenieMvcFormPath,
- activated: opsgenieMvcActivated,
+ active: parseBoolean(opsgenieMvcEnabled),
opsgenieMvcTargetUrl,
- opsgenieMvcIsAvailable,
+ opsgenieMvcIsAvailable: parseBoolean(opsgenieMvcAvailable),
},
+ projectPath,
+ multiIntegrations: parseBoolean(multiIntegrations),
},
+ apolloProvider,
components: {
- AlertSettingsForm,
+ AlertSettingsWrapper,
},
render(createElement) {
- return createElement('alert-settings-form');
+ return createElement('alert-settings-wrapper');
},
});
};
diff --git a/app/assets/javascripts/alerts_settings/services/index.js b/app/assets/javascripts/alerts_settings/services/index.js
index c49992d4f57..1835d6b46aa 100644
--- a/app/assets/javascripts/alerts_settings/services/index.js
+++ b/app/assets/javascripts/alerts_settings/services/index.js
@@ -2,6 +2,7 @@
import axios from '~/lib/utils/axios_utils';
export default {
+ // TODO: All this code save updateTestAlert will be deleted as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/255501
updateGenericKey({ endpoint, params }) {
return axios.put(endpoint, params);
},
@@ -25,11 +26,11 @@ export default {
},
});
},
- updateTestAlert({ endpoint, data, authKey }) {
+ updateTestAlert({ endpoint, data, token }) {
return axios.post(endpoint, data, {
headers: {
'Content-Type': 'application/json',
- Authorization: `Bearer ${authKey}`,
+ Authorization: `Bearer ${token}`,
},
});
},
diff --git a/app/assets/javascripts/alerts_settings/utils/cache_updates.js b/app/assets/javascripts/alerts_settings/utils/cache_updates.js
new file mode 100644
index 00000000000..18054b29fe9
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/utils/cache_updates.js
@@ -0,0 +1,84 @@
+import produce from 'immer';
+import createFlash from '~/flash';
+
+import { DELETE_INTEGRATION_ERROR, ADD_INTEGRATION_ERROR } from './error_messages';
+
+const deleteIntegrationFromStore = (store, query, { httpIntegrationDestroy }, variables) => {
+ const integration = httpIntegrationDestroy?.integration;
+ if (!integration) {
+ return;
+ }
+
+ const sourceData = store.readQuery({
+ query,
+ variables,
+ });
+
+ const data = produce(sourceData, draftData => {
+ // eslint-disable-next-line no-param-reassign
+ draftData.project.alertManagementIntegrations.nodes = draftData.project.alertManagementIntegrations.nodes.filter(
+ ({ id }) => id !== integration.id,
+ );
+ });
+
+ store.writeQuery({
+ query,
+ variables,
+ data,
+ });
+};
+
+const addIntegrationToStore = (
+ store,
+ query,
+ { httpIntegrationCreate, prometheusIntegrationCreate },
+ variables,
+) => {
+ const integration =
+ httpIntegrationCreate?.integration || prometheusIntegrationCreate?.integration;
+ if (!integration) {
+ return;
+ }
+
+ const sourceData = store.readQuery({
+ query,
+ variables,
+ });
+
+ const data = produce(sourceData, draftData => {
+ // eslint-disable-next-line no-param-reassign
+ draftData.project.alertManagementIntegrations.nodes = [
+ integration,
+ ...draftData.project.alertManagementIntegrations.nodes,
+ ];
+ });
+
+ store.writeQuery({
+ query,
+ variables,
+ data,
+ });
+};
+
+const onError = (data, message) => {
+ createFlash({ message });
+ throw new Error(data.errors);
+};
+
+export const hasErrors = ({ errors = [] }) => errors?.length;
+
+export const updateStoreAfterIntegrationDelete = (store, query, data, variables) => {
+ if (hasErrors(data)) {
+ onError(data, DELETE_INTEGRATION_ERROR);
+ } else {
+ deleteIntegrationFromStore(store, query, data, variables);
+ }
+};
+
+export const updateStoreAfterIntegrationAdd = (store, query, data, variables) => {
+ if (hasErrors(data)) {
+ onError(data, ADD_INTEGRATION_ERROR);
+ } else {
+ addIntegrationToStore(store, query, data, variables);
+ }
+};
diff --git a/app/assets/javascripts/alerts_settings/utils/error_messages.js b/app/assets/javascripts/alerts_settings/utils/error_messages.js
new file mode 100644
index 00000000000..979d1ca3ccc
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/utils/error_messages.js
@@ -0,0 +1,21 @@
+import { s__ } from '~/locale';
+
+export const DELETE_INTEGRATION_ERROR = s__(
+ 'AlertsIntegrations|The integration could not be deleted. Please try again.',
+);
+
+export const ADD_INTEGRATION_ERROR = s__(
+ 'AlertsIntegrations|The integration could not be added. Please try again.',
+);
+
+export const UPDATE_INTEGRATION_ERROR = s__(
+ 'AlertsIntegrations|The current integration could not be updated. Please try again.',
+);
+
+export const RESET_INTEGRATION_TOKEN_ERROR = s__(
+ 'AlertsIntegrations|The integration token could not be reset. Please try again.',
+);
+
+export const INTEGRATION_PAYLOAD_TEST_ERROR = s__(
+ 'AlertsIntegrations|Integration payload is invalid. You can still save your changes.',
+);
diff --git a/app/assets/javascripts/analytics/instance_statistics/components/app.vue b/app/assets/javascripts/analytics/instance_statistics/components/app.vue
index 7aa5c98aa0b..8df4d2e2524 100644
--- a/app/assets/javascripts/analytics/instance_statistics/components/app.vue
+++ b/app/assets/javascripts/analytics/instance_statistics/components/app.vue
@@ -1,19 +1,23 @@
<script>
import InstanceCounts from './instance_counts.vue';
-import PipelinesChart from './pipelines_chart.vue';
+import InstanceStatisticsCountChart from './instance_statistics_count_chart.vue';
import UsersChart from './users_chart.vue';
+import ProjectsAndGroupsChart from './projects_and_groups_chart.vue';
+import ChartsConfig from './charts_config';
import { TODAY, TOTAL_DAYS_TO_SHOW, START_DATE } from '../constants';
export default {
name: 'InstanceStatisticsApp',
components: {
InstanceCounts,
- PipelinesChart,
+ InstanceStatisticsCountChart,
UsersChart,
+ ProjectsAndGroupsChart,
},
TOTAL_DAYS_TO_SHOW,
START_DATE,
TODAY,
+ configs: ChartsConfig,
};
</script>
@@ -25,6 +29,20 @@ export default {
:end-date="$options.TODAY"
:total-data-points="$options.TOTAL_DAYS_TO_SHOW"
/>
- <pipelines-chart />
+ <projects-and-groups-chart
+ :start-date="$options.START_DATE"
+ :end-date="$options.TODAY"
+ :total-data-points="$options.TOTAL_DAYS_TO_SHOW"
+ />
+ <instance-statistics-count-chart
+ v-for="chartOptions in $options.configs"
+ :key="chartOptions.chartTitle"
+ :queries="chartOptions.queries"
+ :x-axis-title="chartOptions.xAxisTitle"
+ :y-axis-title="chartOptions.yAxisTitle"
+ :load-chart-error-message="chartOptions.loadChartError"
+ :no-data-message="chartOptions.noDataMessage"
+ :chart-title="chartOptions.chartTitle"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/analytics/instance_statistics/components/charts_config.js b/app/assets/javascripts/analytics/instance_statistics/components/charts_config.js
new file mode 100644
index 00000000000..6fba3c56cfe
--- /dev/null
+++ b/app/assets/javascripts/analytics/instance_statistics/components/charts_config.js
@@ -0,0 +1,87 @@
+import { s__, __, sprintf } from '~/locale';
+import query from '../graphql/queries/instance_count.query.graphql';
+
+const noDataMessage = s__('InstanceStatistics|No data available.');
+
+export default [
+ {
+ loadChartError: sprintf(
+ s__(
+ 'InstanceStatistics|Could not load the pipelines chart. Please refresh the page to try again.',
+ ),
+ ),
+ noDataMessage,
+ chartTitle: s__('InstanceStatistics|Pipelines'),
+ yAxisTitle: s__('InstanceStatistics|Items'),
+ xAxisTitle: s__('InstanceStatistics|Month'),
+ queries: [
+ {
+ query,
+ title: s__('InstanceStatistics|Pipelines total'),
+ identifier: 'PIPELINES',
+ loadError: sprintf(
+ s__('InstanceStatistics|There was an error fetching the total pipelines'),
+ ),
+ },
+ {
+ query,
+ title: s__('InstanceStatistics|Pipelines succeeded'),
+ identifier: 'PIPELINES_SUCCEEDED',
+ loadError: sprintf(
+ s__('InstanceStatistics|There was an error fetching the successful pipelines'),
+ ),
+ },
+ {
+ query,
+ title: s__('InstanceStatistics|Pipelines failed'),
+ identifier: 'PIPELINES_FAILED',
+ loadError: sprintf(
+ s__('InstanceStatistics|There was an error fetching the failed pipelines'),
+ ),
+ },
+ {
+ query,
+ title: s__('InstanceStatistics|Pipelines canceled'),
+ identifier: 'PIPELINES_CANCELED',
+ loadError: sprintf(
+ s__('InstanceStatistics|There was an error fetching the cancelled pipelines'),
+ ),
+ },
+ {
+ query,
+ title: s__('InstanceStatistics|Pipelines skipped'),
+ identifier: 'PIPELINES_SKIPPED',
+ loadError: sprintf(
+ s__('InstanceStatistics|There was an error fetching the skipped pipelines'),
+ ),
+ },
+ ],
+ },
+ {
+ loadChartError: sprintf(
+ s__(
+ 'InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again.',
+ ),
+ ),
+ noDataMessage,
+ chartTitle: s__('InstanceStatistics|Issues & Merge Requests'),
+ yAxisTitle: s__('InstanceStatistics|Items'),
+ xAxisTitle: s__('InstanceStatistics|Month'),
+ queries: [
+ {
+ query,
+ title: __('Issues'),
+ identifier: 'ISSUES',
+ loadError: sprintf(s__('InstanceStatistics|There was an error fetching the issues')),
+ },
+ {
+ query,
+ title: __('Merge requests'),
+ identifier: 'MERGE_REQUESTS',
+ loadError: sprintf(
+ s__('InstanceStatistics|There was an error fetching the merge requests'),
+ ),
+ },
+ ],
+ },
+];
diff --git a/app/assets/javascripts/analytics/instance_statistics/components/instance_statistics_count_chart.vue b/app/assets/javascripts/analytics/instance_statistics/components/instance_statistics_count_chart.vue
new file mode 100644
index 00000000000..a9bd1bb2f41
--- /dev/null
+++ b/app/assets/javascripts/analytics/instance_statistics/components/instance_statistics_count_chart.vue
@@ -0,0 +1,206 @@
+<script>
+import { GlLineChart } from '@gitlab/ui/dist/charts';
+import { GlAlert } from '@gitlab/ui';
+import { some, every } from 'lodash';
+import * as Sentry from '~/sentry/wrapper';
+import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
+import {
+ differenceInMonths,
+ formatDateAsMonth,
+ getDayDifference,
+} from '~/lib/utils/datetime_utility';
+import { getAverageByMonth, getEarliestDate, generateDataKeys } from '../utils';
+import { TODAY, START_DATE } from '../constants';
+
+const QUERY_DATA_KEY = 'instanceStatisticsMeasurements';
+
+export default {
+ name: 'InstanceStatisticsCountChart',
+ components: {
+ GlLineChart,
+ GlAlert,
+ ChartSkeletonLoader,
+ },
+ startDate: START_DATE,
+ endDate: TODAY,
+ props: {
+ chartTitle: {
+ type: String,
+ required: true,
+ },
+ loadChartErrorMessage: {
+ type: String,
+ required: true,
+ },
+ noDataMessage: {
+ type: String,
+ required: true,
+ },
+ xAxisTitle: {
+ type: String,
+ required: true,
+ },
+ yAxisTitle: {
+ type: String,
+ required: true,
+ },
+ queries: {
+ type: Array,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ errors: { ...generateDataKeys(this.queries, '') },
+ ...generateDataKeys(this.queries, []),
+ };
+ },
+ computed: {
+ errorMessages() {
+ return Object.values(this.errors);
+ },
+ isLoading() {
+ return some(this.$apollo.queries, query => query?.loading);
+ },
+ allQueriesFailed() {
+ return every(this.errorMessages, message => message.length);
+ },
+ hasLoadingErrors() {
+ return some(this.errorMessages, message => message.length);
+ },
+ errorMessage() {
+ // show the generic loading message if all requests fail
+ return this.allQueriesFailed ? this.loadChartErrorMessage : this.errorMessages.join('\n\n');
+ },
+ hasEmptyDataSet() {
+ return this.chartData.every(({ data }) => data.length === 0);
+ },
+ totalDaysToShow() {
+ return getDayDifference(this.$options.startDate, this.$options.endDate);
+ },
+ chartData() {
+ const options = { shouldRound: true };
+ return this.queries.map(({ identifier, title }) => ({
+ name: title,
+ data: getAverageByMonth(this[identifier]?.nodes, options),
+ }));
+ },
+ range() {
+ return {
+ min: this.$options.startDate,
+ max: this.$options.endDate,
+ };
+ },
+ chartOptions() {
+ const { endDate, startDate } = this.$options;
+ return {
+ xAxis: {
+ ...this.range,
+ name: this.xAxisTitle,
+ type: 'time',
+ splitNumber: differenceInMonths(startDate, endDate) + 1,
+ axisLabel: {
+ interval: 0,
+ showMinLabel: false,
+ showMaxLabel: false,
+ align: 'right',
+ formatter: formatDateAsMonth,
+ },
+ },
+ yAxis: {
+ name: this.yAxisTitle,
+ },
+ };
+ },
+ },
+ created() {
+ this.queries.forEach(({ query, identifier, loadError }) => {
+ this.$apollo.addSmartQuery(identifier, {
+ query,
+ variables() {
+ return {
+ identifier,
+ first: this.totalDaysToShow,
+ after: null,
+ };
+ },
+ update(data) {
+ const { nodes = [], pageInfo } = data[QUERY_DATA_KEY] || {};
+ return {
+ nodes,
+ pageInfo,
+ };
+ },
+ result() {
+ const { pageInfo, nodes } = this[identifier];
+ if (pageInfo?.hasNextPage && this.calculateDaysToFetch(getEarliestDate(nodes)) > 0) {
+ this.fetchNextPage({
+ query: this.$apollo.queries[identifier],
+ errorMessage: loadError,
+ pageInfo,
+ identifier,
+ });
+ }
+ },
+ error(error) {
+ this.handleError({
+ message: loadError,
+ identifier,
+ error,
+ });
+ },
+ });
+ });
+ },
+ methods: {
+ calculateDaysToFetch(firstDataPointDate = null) {
+ return firstDataPointDate
+ ? Math.max(0, getDayDifference(this.$options.startDate, new Date(firstDataPointDate)))
+ : 0;
+ },
+ handleError({ identifier, error, message }) {
+ this.loadingError = true;
+ this.errors = { ...this.errors, [identifier]: message };
+ Sentry.captureException(error);
+ },
+ fetchNextPage({ query, pageInfo, identifier, errorMessage }) {
+ query
+ .fetchMore({
+ variables: {
+ identifier,
+ first: this.calculateDaysToFetch(getEarliestDate(this[identifier].nodes)),
+ after: pageInfo.endCursor,
+ },
+ updateQuery: (previousResult, { fetchMoreResult }) => {
+ const { nodes, ...rest } = fetchMoreResult[QUERY_DATA_KEY];
+ const { nodes: previousNodes } = previousResult[QUERY_DATA_KEY];
+ return {
+ [QUERY_DATA_KEY]: { ...rest, nodes: [...previousNodes, ...nodes] },
+ };
+ },
+ })
+ .catch(error => this.handleError({ identifier, error, message: errorMessage }));
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <h3>{{ chartTitle }}</h3>
+ <gl-alert v-if="hasLoadingErrors" variant="danger" :dismissible="false" class="gl-mt-3">
+ {{ errorMessage }}
+ </gl-alert>
+ <div v-if="!allQueriesFailed">
+ <chart-skeleton-loader v-if="isLoading" />
+ <gl-alert v-else-if="hasEmptyDataSet" variant="info" :dismissible="false" class="gl-mt-3">
+ {{ noDataMessage }}
+ </gl-alert>
+ <gl-line-chart
+ v-else
+ :option="chartOptions"
+ :include-legend-avg-max="true"
+ :data="chartData"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/analytics/instance_statistics/components/pipelines_chart.vue b/app/assets/javascripts/analytics/instance_statistics/components/pipelines_chart.vue
deleted file mode 100644
index b16d960402b..00000000000
--- a/app/assets/javascripts/analytics/instance_statistics/components/pipelines_chart.vue
+++ /dev/null
@@ -1,215 +0,0 @@
-<script>
-import { GlLineChart } from '@gitlab/ui/dist/charts';
-import { GlAlert } from '@gitlab/ui';
-import { mapKeys, mapValues, pick, some, sum } from 'lodash';
-import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
-import { s__ } from '~/locale';
-import {
- differenceInMonths,
- formatDateAsMonth,
- getDayDifference,
-} from '~/lib/utils/datetime_utility';
-import { getAverageByMonth, sortByDate, extractValues } from '../utils';
-import pipelineStatsQuery from '../graphql/queries/pipeline_stats.query.graphql';
-import { TODAY, START_DATE } from '../constants';
-
-const DATA_KEYS = [
- 'pipelinesTotal',
- 'pipelinesSucceeded',
- 'pipelinesFailed',
- 'pipelinesCanceled',
- 'pipelinesSkipped',
-];
-const PREFIX = 'pipelines';
-
-export default {
- name: 'PipelinesChart',
- components: {
- GlLineChart,
- GlAlert,
- ChartSkeletonLoader,
- },
- startDate: START_DATE,
- endDate: TODAY,
- i18n: {
- loadPipelineChartError: s__(
- 'InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again.',
- ),
- noDataMessage: s__('InstanceAnalytics|There is no data available.'),
- total: s__('InstanceAnalytics|Total'),
- succeeded: s__('InstanceAnalytics|Succeeded'),
- failed: s__('InstanceAnalytics|Failed'),
- canceled: s__('InstanceAnalytics|Canceled'),
- skipped: s__('InstanceAnalytics|Skipped'),
- chartTitle: s__('InstanceAnalytics|Pipelines'),
- yAxisTitle: s__('InstanceAnalytics|Items'),
- xAxisTitle: s__('InstanceAnalytics|Month'),
- },
- data() {
- return {
- loading: true,
- loadingError: null,
- };
- },
- apollo: {
- pipelineStats: {
- query: pipelineStatsQuery,
- variables() {
- return {
- firstTotal: this.totalDaysToShow,
- firstSucceeded: this.totalDaysToShow,
- firstFailed: this.totalDaysToShow,
- firstCanceled: this.totalDaysToShow,
- firstSkipped: this.totalDaysToShow,
- };
- },
- update(data) {
- const allData = extractValues(data, DATA_KEYS, PREFIX, 'nodes');
- const allPageInfo = extractValues(data, DATA_KEYS, PREFIX, 'pageInfo');
-
- return {
- ...mapValues(allData, sortByDate),
- ...allPageInfo,
- };
- },
- result() {
- if (this.hasNextPage) {
- this.fetchNextPage();
- }
- },
- error() {
- this.handleError();
- },
- },
- },
- computed: {
- isLoading() {
- return this.$apollo.queries.pipelineStats.loading;
- },
- totalDaysToShow() {
- return getDayDifference(this.$options.startDate, this.$options.endDate);
- },
- firstVariables() {
- const allData = pick(this.pipelineStats, [
- 'nodesTotal',
- 'nodesSucceeded',
- 'nodesFailed',
- 'nodesCanceled',
- 'nodesSkipped',
- ]);
- const allDayDiffs = mapValues(allData, data => {
- const firstdataPoint = data[0];
- if (!firstdataPoint) {
- return 0;
- }
-
- return Math.max(
- 0,
- getDayDifference(this.$options.startDate, new Date(firstdataPoint.recordedAt)),
- );
- });
-
- return mapKeys(allDayDiffs, (value, key) => key.replace('nodes', 'first'));
- },
- cursorVariables() {
- const pageInfoKeys = [
- 'pageInfoTotal',
- 'pageInfoSucceeded',
- 'pageInfoFailed',
- 'pageInfoCanceled',
- 'pageInfoSkipped',
- ];
-
- return extractValues(this.pipelineStats, pageInfoKeys, 'pageInfo', 'endCursor');
- },
- hasNextPage() {
- return (
- sum(Object.values(this.firstVariables)) > 0 &&
- some(this.pipelineStats, ({ hasNextPage }) => hasNextPage)
- );
- },
- hasEmptyDataSet() {
- return this.chartData.every(({ data }) => data.length === 0);
- },
- chartData() {
- const allData = pick(this.pipelineStats, [
- 'nodesTotal',
- 'nodesSucceeded',
- 'nodesFailed',
- 'nodesCanceled',
- 'nodesSkipped',
- ]);
- const options = { shouldRound: true };
- return Object.keys(allData).map(key => {
- const i18nName = key.slice('nodes'.length).toLowerCase();
- return {
- name: this.$options.i18n[i18nName],
- data: getAverageByMonth(allData[key], options),
- };
- });
- },
- range() {
- return {
- min: this.$options.startDate,
- max: this.$options.endDate,
- };
- },
- chartOptions() {
- const { endDate, startDate, i18n } = this.$options;
- return {
- xAxis: {
- ...this.range,
- name: i18n.xAxisTitle,
- type: 'time',
- splitNumber: differenceInMonths(startDate, endDate) + 1,
- axisLabel: {
- interval: 0,
- showMinLabel: false,
- showMaxLabel: false,
- align: 'right',
- formatter: formatDateAsMonth,
- },
- },
- yAxis: {
- name: i18n.yAxisTitle,
- },
- };
- },
- },
- methods: {
- handleError() {
- this.loadingError = true;
- },
- fetchNextPage() {
- this.$apollo.queries.pipelineStats
- .fetchMore({
- variables: {
- ...this.firstVariables,
- ...this.cursorVariables,
- },
- updateQuery: (previousResult, { fetchMoreResult }) => {
- return Object.keys(fetchMoreResult).reduce((memo, key) => {
- const { nodes, ...rest } = fetchMoreResult[key];
- const previousNodes = previousResult[key].nodes;
- return { ...memo, [key]: { ...rest, nodes: [...previousNodes, ...nodes] } };
- }, {});
- },
- })
- .catch(this.handleError);
- },
- },
-};
-</script>
-<template>
- <div>
- <h3>{{ $options.i18n.chartTitle }}</h3>
- <gl-alert v-if="loadingError" variant="danger" :dismissible="false" class="gl-mt-3">
- {{ this.$options.i18n.loadPipelineChartError }}
- </gl-alert>
- <chart-skeleton-loader v-else-if="isLoading" />
- <gl-alert v-else-if="hasEmptyDataSet" variant="info" :dismissible="false" class="gl-mt-3">
- {{ $options.i18n.noDataMessage }}
- </gl-alert>
- <gl-line-chart v-else :option="chartOptions" :include-legend-avg-max="true" :data="chartData" />
- </div>
-</template>
diff --git a/app/assets/javascripts/analytics/instance_statistics/components/projects_and_groups_chart.vue b/app/assets/javascripts/analytics/instance_statistics/components/projects_and_groups_chart.vue
new file mode 100644
index 00000000000..e8e35c22fe1
--- /dev/null
+++ b/app/assets/javascripts/analytics/instance_statistics/components/projects_and_groups_chart.vue
@@ -0,0 +1,224 @@
+<script>
+import { GlAlert } from '@gitlab/ui';
+import { GlLineChart } from '@gitlab/ui/dist/charts';
+import produce from 'immer';
+import { sortBy } from 'lodash';
+import * as Sentry from '~/sentry/wrapper';
+import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
+import { s__, __ } from '~/locale';
+import { formatDateAsMonth } from '~/lib/utils/datetime_utility';
+import latestGroupsQuery from '../graphql/queries/groups.query.graphql';
+import latestProjectsQuery from '../graphql/queries/projects.query.graphql';
+import { getAverageByMonth } from '../utils';
+
+const sortByDate = data => sortBy(data, item => new Date(item[0]).getTime());
+
+const averageAndSortData = (data = [], maxDataPoints) => {
+ const averaged = getAverageByMonth(
+ data.length > maxDataPoints ? data.slice(0, maxDataPoints) : data,
+ { shouldRound: true },
+ );
+ return sortByDate(averaged);
+};
+
+export default {
+ name: 'ProjectsAndGroupsChart',
+ components: { GlAlert, GlLineChart, ChartSkeletonLoader },
+ props: {
+ startDate: {
+ type: Date,
+ required: true,
+ },
+ endDate: {
+ type: Date,
+ required: true,
+ },
+ totalDataPoints: {
+ type: Number,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ loadingError: false,
+ errorMessage: '',
+ groups: [],
+ projects: [],
+ groupsPageInfo: null,
+ projectsPageInfo: null,
+ };
+ },
+ apollo: {
+ groups: {
+ query: latestGroupsQuery,
+ variables() {
+ return {
+ first: this.totalDataPoints,
+ after: null,
+ };
+ },
+ update(data) {
+ return data.groups?.nodes || [];
+ },
+ result({ data }) {
+ const {
+ groups: { pageInfo },
+ } = data;
+ this.groupsPageInfo = pageInfo;
+ this.fetchNextPage({
+ query: this.$apollo.queries.groups,
+ pageInfo: this.groupsPageInfo,
+ dataKey: 'groups',
+ errorMessage: this.$options.i18n.loadGroupsDataError,
+ });
+ },
+ error(error) {
+ this.handleError({
+ message: this.$options.i18n.loadGroupsDataError,
+ error,
+ dataKey: 'groups',
+ });
+ },
+ },
+ projects: {
+ query: latestProjectsQuery,
+ variables() {
+ return {
+ first: this.totalDataPoints,
+ after: null,
+ };
+ },
+ update(data) {
+ return data.projects?.nodes || [];
+ },
+ result({ data }) {
+ const {
+ projects: { pageInfo },
+ } = data;
+ this.projectsPageInfo = pageInfo;
+ this.fetchNextPage({
+ query: this.$apollo.queries.projects,
+ pageInfo: this.projectsPageInfo,
+ dataKey: 'projects',
+ errorMessage: this.$options.i18n.loadProjectsDataError,
+ });
+ },
+ error(error) {
+ this.handleError({
+ message: this.$options.i18n.loadProjectsDataError,
+ error,
+ dataKey: 'projects',
+ });
+ },
+ },
+ },
+ i18n: {
+ yAxisTitle: s__('InstanceStatistics|Total projects & groups'),
+ xAxisTitle: __('Month'),
+ loadChartError: s__(
+ 'InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again.',
+ ),
+ loadProjectsDataError: s__('InstanceStatistics|There was an error while loading the projects'),
+ loadGroupsDataError: s__('InstanceStatistics|There was an error while loading the groups'),
+ noDataMessage: s__('InstanceStatistics|No data available.'),
+ },
+ computed: {
+ isLoadingGroups() {
+ return this.$apollo.queries.groups.loading || this.groupsPageInfo?.hasNextPage;
+ },
+ isLoadingProjects() {
+ return this.$apollo.queries.projects.loading || this.projectsPageInfo?.hasNextPage;
+ },
+ isLoading() {
+ return this.isLoadingProjects && this.isLoadingGroups;
+ },
+ groupChartData() {
+ return averageAndSortData(this.groups, this.totalDataPoints);
+ },
+ projectChartData() {
+ return averageAndSortData(this.projects, this.totalDataPoints);
+ },
+ hasNoData() {
+ const { projectChartData, groupChartData } = this;
+ return Boolean(!projectChartData.length && !groupChartData.length);
+ },
+ options() {
+ return {
+ xAxis: {
+ name: this.$options.i18n.xAxisTitle,
+ type: 'category',
+ axisLabel: {
+ formatter: value => {
+ return formatDateAsMonth(value);
+ },
+ },
+ },
+ yAxis: {
+ name: this.$options.i18n.yAxisTitle,
+ },
+ };
+ },
+ chartData() {
+ return [
+ {
+ name: s__('InstanceStatistics|Total projects'),
+ data: this.projectChartData,
+ },
+ {
+ name: s__('InstanceStatistics|Total groups'),
+ data: this.groupChartData,
+ },
+ ];
+ },
+ },
+ methods: {
+ handleError({ error, message = this.$options.i18n.loadChartError, dataKey = null }) {
+ this.loadingError = true;
+ this.errorMessage = message;
+ if (!dataKey) {
+ this.projects = [];
+ this.groups = [];
+ } else {
+ this[dataKey] = [];
+ }
+ Sentry.captureException(error);
+ },
+ fetchNextPage({ pageInfo, query, dataKey, errorMessage }) {
+ if (pageInfo?.hasNextPage) {
+ query
+ .fetchMore({
+ variables: { first: this.totalDataPoints, after: pageInfo.endCursor },
+ updateQuery: (previousResult, { fetchMoreResult }) => {
+ const results = produce(fetchMoreResult, newData => {
+ // eslint-disable-next-line no-param-reassign
+ newData[dataKey].nodes = [
+ ...previousResult[dataKey].nodes,
+ ...newData[dataKey].nodes,
+ ];
+ });
+ return results;
+ },
+ })
+ .catch(error => {
+ this.handleError({ error, message: errorMessage, dataKey });
+ });
+ }
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <h3>{{ $options.i18n.yAxisTitle }}</h3>
+ <chart-skeleton-loader v-if="isLoading" />
+ <gl-alert v-else-if="hasNoData" variant="info" :dismissible="false" class="gl-mt-3">
+ {{ $options.i18n.noDataMessage }}
+ </gl-alert>
+ <div v-else>
+ <gl-alert v-if="loadingError" variant="danger" :dismissible="false" class="gl-mt-3">{{
+ errorMessage
+ }}</gl-alert>
+ <gl-line-chart :option="options" :include-legend-avg-max="true" :data="chartData" />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/analytics/instance_statistics/graphql/queries/groups.query.graphql b/app/assets/javascripts/analytics/instance_statistics/graphql/queries/groups.query.graphql
new file mode 100644
index 00000000000..ec56d91ffaa
--- /dev/null
+++ b/app/assets/javascripts/analytics/instance_statistics/graphql/queries/groups.query.graphql
@@ -0,0 +1,13 @@
+#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
+#import "../fragments/count.fragment.graphql"
+
+query getGroupsCount($first: Int, $after: String) {
+ groups: instanceStatisticsMeasurements(identifier: GROUPS, first: $first, after: $after) {
+ nodes {
+ ...Count
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+}
diff --git a/app/assets/javascripts/analytics/instance_statistics/graphql/queries/instance_count.query.graphql b/app/assets/javascripts/analytics/instance_statistics/graphql/queries/instance_count.query.graphql
new file mode 100644
index 00000000000..dd22a16cd51
--- /dev/null
+++ b/app/assets/javascripts/analytics/instance_statistics/graphql/queries/instance_count.query.graphql
@@ -0,0 +1,13 @@
+#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
+#import "../fragments/count.fragment.graphql"
+
+query getCount($identifier: MeasurementIdentifier!, $first: Int, $after: String) {
+ instanceStatisticsMeasurements(identifier: $identifier, first: $first, after: $after) {
+ nodes {
+ ...Count
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+}
diff --git a/app/assets/javascripts/analytics/instance_statistics/graphql/queries/pipeline_stats.query.graphql b/app/assets/javascripts/analytics/instance_statistics/graphql/queries/pipeline_stats.query.graphql
deleted file mode 100644
index 3bf40403f91..00000000000
--- a/app/assets/javascripts/analytics/instance_statistics/graphql/queries/pipeline_stats.query.graphql
+++ /dev/null
@@ -1,76 +0,0 @@
-#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
-#import "./count.fragment.graphql"
-
-query pipelineStats(
- $firstTotal: Int
- $firstSucceeded: Int
- $firstFailed: Int
- $firstCanceled: Int
- $firstSkipped: Int
- $endCursorTotal: String
- $endCursorSucceeded: String
- $endCursorFailed: String
- $endCursorCanceled: String
- $endCursorSkipped: String
-) {
- pipelinesTotal: instanceStatisticsMeasurements(
- identifier: PIPELINES
- first: $firstTotal
- after: $endCursorTotal
- ) {
- nodes {
- ...Count
- }
- pageInfo {
- ...PageInfo
- }
- }
- pipelinesSucceeded: instanceStatisticsMeasurements(
- identifier: PIPELINES_SUCCEEDED
- first: $firstSucceeded
- after: $endCursorSucceeded
- ) {
- nodes {
- ...Count
- }
- pageInfo {
- ...PageInfo
- }
- }
- pipelinesFailed: instanceStatisticsMeasurements(
- identifier: PIPELINES_FAILED
- first: $firstFailed
- after: $endCursorFailed
- ) {
- nodes {
- ...Count
- }
- pageInfo {
- ...PageInfo
- }
- }
- pipelinesCanceled: instanceStatisticsMeasurements(
- identifier: PIPELINES_CANCELED
- first: $firstCanceled
- after: $endCursorCanceled
- ) {
- nodes {
- ...Count
- }
- pageInfo {
- ...PageInfo
- }
- }
- pipelinesSkipped: instanceStatisticsMeasurements(
- identifier: PIPELINES_SKIPPED
- first: $firstSkipped
- after: $endCursorSkipped
- ) {
- nodes {
- ...Count
- }
- pageInfo {
- ...PageInfo
- }
- }
-}
diff --git a/app/assets/javascripts/analytics/instance_statistics/graphql/queries/projects.query.graphql b/app/assets/javascripts/analytics/instance_statistics/graphql/queries/projects.query.graphql
new file mode 100644
index 00000000000..0845b703435
--- /dev/null
+++ b/app/assets/javascripts/analytics/instance_statistics/graphql/queries/projects.query.graphql
@@ -0,0 +1,13 @@
+#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
+#import "../fragments/count.fragment.graphql"
+
+query getProjectsCount($first: Int, $after: String) {
+ projects: instanceStatisticsMeasurements(identifier: PROJECTS, first: $first, after: $after) {
+ nodes {
+ ...Count
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+}
diff --git a/app/assets/javascripts/analytics/instance_statistics/utils.js b/app/assets/javascripts/analytics/instance_statistics/utils.js
index 907482c0c72..e1fa5d155a2 100644
--- a/app/assets/javascripts/analytics/instance_statistics/utils.js
+++ b/app/assets/javascripts/analytics/instance_statistics/utils.js
@@ -1,5 +1,5 @@
import { masks } from 'dateformat';
-import { mapKeys, mapValues, pick, sortBy } from 'lodash';
+import { get } from 'lodash';
import { formatDate } from '~/lib/utils/datetime_utility';
const { isoDate } = masks;
@@ -41,29 +41,28 @@ export function getAverageByMonth(items = [], options = {}) {
}
/**
- * Extracts values given a data set and a set of keys
- * @example
- * const data = { fooBar: { baz: 'quis' }, ignored: 'ignored' };
- * extractValues(data, ['fooBar'], 'foo', 'baz') => { bazBar: 'quis' }
- * @param {Object} data set to extract values from
- * @param {Array} dataKeys keys describing where to look for values in the data set
- * @param {String} replaceKey name key to be replaced in the data set
- * @param {String} nestedKey key nested in the data set to be extracted,
- * this is also used to rename the newly created data set
- * @return {Object} the newly created data set with the extracted values
+ * Takes an array of instance counts and returns the last item in the list
+ * @param {Array} arr array of instance counts in the form { count: Number, recordedAt: date String }
+ * @return {String} the 'recordedAt' value of the earliest item
*/
-export function extractValues(data, dataKeys = [], replaceKey, nestedKey) {
- return mapKeys(pick(mapValues(data, nestedKey), dataKeys), (value, key) =>
- key.replace(replaceKey, nestedKey),
- );
-}
+export const getEarliestDate = (arr = []) => {
+ const len = arr.length;
+ return get(arr, `[${len - 1}].recordedAt`, null);
+};
/**
- * Creates a new array of items sorted by the date string of each item
- * @param {Array} items [description]
- * @param {String} items[0] date string
- * @return {Array} the new sorted array.
+ * Takes an array of queries and produces an object with the query identifier as key
+ * and a supplied defaultValue as its value
+ * @param {Array} queries array of chart query configs,
+ * see ./analytics/instance_statistics/components/charts_config.js
+ * @param {any} defaultValue value to set each identifier to
+ * @return {Object} key value pair of the form { queryIdentifier: defaultValue }
*/
-export function sortByDate(items = []) {
- return sortBy(items, ({ recordedAt }) => new Date(recordedAt).getTime());
-}
+export const generateDataKeys = (queries, defaultValue) =>
+ queries.reduce(
+ (acc, { identifier }) => ({
+ ...acc,
+ [identifier]: defaultValue,
+ }),
+ {},
+ );
diff --git a/app/assets/javascripts/analytics/product_analytics/components/activity_chart.vue b/app/assets/javascripts/analytics/product_analytics/components/activity_chart.vue
index a475ff8fd25..2be9ebda87a 100644
--- a/app/assets/javascripts/analytics/product_analytics/components/activity_chart.vue
+++ b/app/assets/javascripts/analytics/product_analytics/components/activity_chart.vue
@@ -17,10 +17,13 @@ export default {
},
},
computed: {
- seriesData() {
- return {
- full: this.formattedData.keys.map((val, idx) => [val, this.formattedData.values[idx]]),
- };
+ barSeriesData() {
+ return [
+ {
+ name: 'full',
+ data: this.formattedData.keys.map((val, idx) => [val, this.formattedData.values[idx]]),
+ },
+ ];
},
},
};
@@ -30,7 +33,7 @@ export default {
<div class="gl-xs-w-full">
<gl-column-chart
v-if="formattedData.keys"
- :data="seriesData"
+ :bars="barSeriesData"
:x-axis-title="__('Value')"
:y-axis-title="__('Number of events')"
:x-axis-type="'category'"
diff --git a/app/assets/javascripts/analytics/shared/components/metric_card.vue b/app/assets/javascripts/analytics/shared/components/metric_card.vue
index cee186c057c..e6e12821bec 100644
--- a/app/assets/javascripts/analytics/shared/components/metric_card.vue
+++ b/app/assets/javascripts/analytics/shared/components/metric_card.vue
@@ -43,7 +43,7 @@ export default {
};
</script>
<template>
- <gl-card>
+ <gl-card class="gl-mb-5">
<template #header>
<strong ref="title">{{ title }}</strong>
</template>
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 63b75cdb734..f469f49ce20 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -6,6 +6,7 @@ import { __ } from '~/locale';
const DEFAULT_PER_PAGE = 20;
const Api = {
+ DEFAULT_PER_PAGE,
groupsPath: '/api/:version/groups.json',
groupPath: '/api/:version/groups/:id',
groupMembersPath: '/api/:version/groups/:id/members',
@@ -22,6 +23,7 @@ const Api = {
projectLabelsPath: '/:namespace_path/:project_path/-/labels',
projectFileSchemaPath: '/:namespace_path/:project_path/-/schema/:ref/:filename',
projectUsersPath: '/api/:version/projects/:id/users',
+ projectMembersPath: '/api/:version/projects/:id/members',
projectMergeRequestsPath: '/api/:version/projects/:id/merge_requests',
projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
projectMergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes',
@@ -34,6 +36,7 @@ const Api = {
mergeRequestsPath: '/api/:version/merge_requests',
groupLabelsPath: '/groups/:namespace_path/-/labels',
issuableTemplatePath: '/:namespace_path/:project_path/templates/:type/:key',
+ issuableTemplatesPath: '/:namespace_path/:project_path/templates/:type',
projectTemplatePath: '/api/:version/projects/:id/templates/:type/:key',
projectTemplatesPath: '/api/:version/projects/:id/templates/:type',
userCountsPath: '/api/:version/user_counts',
@@ -70,6 +73,7 @@ const Api = {
featureFlagUserLists: '/api/:version/projects/:id/feature_flags_user_lists',
featureFlagUserList: '/api/:version/projects/:id/feature_flags_user_lists/:list_iid',
billableGroupMembersPath: '/api/:version/groups/:id/billable_members',
+ containerRegistryDetailsPath: '/api/:version/registry/repositories/:id/',
group(groupId, callback = () => {}) {
const url = Api.buildUrl(Api.groupPath).replace(':id', groupId);
@@ -106,6 +110,11 @@ const Api = {
return axios.delete(url);
},
+ containerRegistryDetails(registryId, options = {}) {
+ const url = Api.buildUrl(this.containerRegistryDetailsPath).replace(':id', registryId);
+ return axios.get(url, options);
+ },
+
groupMembers(id, options) {
const url = Api.buildUrl(this.groupMembersPath).replace(':id', encodeURIComponent(id));
@@ -207,6 +216,12 @@ const Api = {
.then(({ data }) => data);
},
+ inviteProjectMembers(id, data) {
+ const url = Api.buildUrl(this.projectMembersPath).replace(':id', encodeURIComponent(id));
+
+ return axios.post(url, data);
+ },
+
// Return single project
project(projectPath) {
const url = Api.buildUrl(Api.projectPath).replace(':id', encodeURIComponent(projectPath));
@@ -454,17 +469,38 @@ const Api = {
},
issueTemplate(namespacePath, projectPath, key, type, callback) {
- const url = Api.buildUrl(Api.issuableTemplatePath)
- .replace(':key', encodeURIComponent(key))
- .replace(':type', type)
- .replace(':project_path', projectPath)
- .replace(':namespace_path', namespacePath);
+ const url = this.buildIssueTemplateUrl(
+ Api.issuableTemplatePath,
+ type,
+ projectPath,
+ namespacePath,
+ ).replace(':key', encodeURIComponent(key));
+ return axios
+ .get(url)
+ .then(({ data }) => callback(null, data))
+ .catch(callback);
+ },
+
+ issueTemplates(namespacePath, projectPath, type, callback) {
+ const url = this.buildIssueTemplateUrl(
+ Api.issuableTemplatesPath,
+ type,
+ projectPath,
+ namespacePath,
+ );
return axios
.get(url)
.then(({ data }) => callback(null, data))
.catch(callback);
},
+ buildIssueTemplateUrl(path, type, projectPath, namespacePath) {
+ return Api.buildUrl(path)
+ .replace(':type', type)
+ .replace(':project_path', projectPath)
+ .replace(':namespace_path', namespacePath);
+ },
+
users(query, options) {
const url = Api.buildUrl(this.usersPath);
return axios.get(url, {
@@ -530,12 +566,13 @@ const Api = {
});
},
- postUserStatus({ emoji, message }) {
+ postUserStatus({ emoji, message, availability }) {
const url = Api.buildUrl(this.userPostStatusPath);
return axios.put(url, {
emoji,
message,
+ availability,
});
},
@@ -610,12 +647,12 @@ const Api = {
return axios.get(url);
},
- pipelineJobs(projectId, pipelineId) {
+ pipelineJobs(projectId, pipelineId, params) {
const url = Api.buildUrl(this.pipelineJobsPath)
.replace(':id', encodeURIComponent(projectId))
.replace(':pipeline_id', encodeURIComponent(pipelineId));
- return axios.get(url);
+ return axios.get(url, { params });
},
// Return all pipelines for a project or filter by query params
@@ -737,6 +774,12 @@ const Api = {
return axios.get(url, { params: { page } });
},
+ searchFeatureFlagUserLists(id, search) {
+ const url = Api.buildUrl(this.featureFlagUserLists).replace(':id', id);
+
+ return axios.get(url, { params: { search } });
+ },
+
createFeatureFlagUserList(id, list) {
const url = Api.buildUrl(this.featureFlagUserLists).replace(':id', id);
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js
index 7055cd42978..17e6255700a 100644
--- a/app/assets/javascripts/awards_handler.js
+++ b/app/assets/javascripts/awards_handler.js
@@ -5,11 +5,11 @@ import { uniq } from 'lodash';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import Cookies from 'js-cookie';
import { __ } from './locale';
-import { updateTooltipTitle } from './lib/utils/common_utils';
import { isInVueNoteablePage } from './lib/utils/dom_utils';
import { deprecatedCreateFlash as flash } from './flash';
import axios from './lib/utils/axios_utils';
import * as Emoji from '~/emoji';
+import { dispose, fixTitle } from '~/tooltips';
const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd';
const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd';
@@ -374,7 +374,7 @@ export class AwardsHandler {
counter.text(counterNumber - 1);
this.removeYouFromUserList($emojiButton);
} else if (emoji === 'thumbsup' || emoji === 'thumbsdown') {
- $emojiButton.tooltip('dispose');
+ dispose($emojiButton);
counter.text('0');
this.removeYouFromUserList($emojiButton);
if ($emojiButton.parents('.note').length) {
@@ -387,7 +387,8 @@ export class AwardsHandler {
}
removeEmoji($emojiButton) {
- $emojiButton.tooltip('dispose');
+ dispose($emojiButton);
+
$emojiButton.remove();
const $votesBlock = this.getVotesBlock();
if ($votesBlock.find('.js-emoji-btn').length === 0) {
@@ -415,13 +416,17 @@ export class AwardsHandler {
const originalTitle = this.getAwardTooltip(awardBlock);
const authors = originalTitle.split(FROM_SENTENCE_REGEX);
authors.splice(authors.indexOf('You'), 1);
- return awardBlock
+
+ awardBlock
.closest('.js-emoji-btn')
.removeData('title')
.removeAttr('data-title')
.removeAttr('data-original-title')
- .attr('title', this.toSentence(authors))
- .tooltip('_fixTitle');
+ .attr('title', this.toSentence(authors));
+
+ fixTitle(awardBlock);
+
+ return awardBlock;
}
addYouToUserList(votesBlock, emoji) {
@@ -432,7 +437,12 @@ export class AwardsHandler {
users = origTitle.trim().split(FROM_SENTENCE_REGEX);
}
users.unshift('You');
- return awardBlock.attr('title', this.toSentence(users)).tooltip('_fixTitle');
+
+ awardBlock.attr('title', this.toSentence(users));
+
+ fixTitle(awardBlock);
+
+ return awardBlock;
}
createAwardButtonForVotesBlock(votesBlock, emojiName) {
@@ -448,7 +458,7 @@ export class AwardsHandler {
.find('.emoji-icon')
.data('name', emojiName);
this.animateEmoji($emojiButton);
- $('.award-control').tooltip();
+
votesBlock.removeClass('current');
}
@@ -487,17 +497,6 @@ export class AwardsHandler {
return votesBlock.find(`.js-emoji-btn [data-name="${emoji}"]`);
}
- userAuthored($emojiButton) {
- const oldTitle = this.getAwardTooltip($emojiButton);
- const newTitle = 'You cannot vote on your own issue, MR and note';
- updateTooltipTitle($emojiButton, newTitle).tooltip('show');
- // Restore tooltip back to award list
- return setTimeout(() => {
- $emojiButton.tooltip('hide');
- updateTooltipTitle($emojiButton, oldTitle);
- }, 2800);
- }
-
scrollToAwards() {
const options = {
scrollTop: $('.awards').offset().top - 110,
diff --git a/app/assets/javascripts/badges/components/badge.vue b/app/assets/javascripts/badges/components/badge.vue
index 3dd05f73841..0b8c6aff219 100644
--- a/app/assets/javascripts/badges/components/badge.vue
+++ b/app/assets/javascripts/badges/components/badge.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlTooltipDirective, GlIcon, GlButton } from '@gitlab/ui';
export default {
// name: 'Badge' is a false positive: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/25
@@ -8,6 +8,7 @@ export default {
components: {
GlIcon,
GlLoadingIcon,
+ GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -90,15 +91,16 @@ export default {
</div>
</div>
- <button
+ <gl-button
v-show="hasError"
v-gl-tooltip.hover
:title="s__('Badges|Reload badge image')"
- class="btn btn-transparent btn-sm text-primary"
+ category="tertiary"
+ variant="success"
type="button"
+ icon="retry"
+ size="small"
@click="reloadImage"
- >
- <gl-icon :size="16" name="retry" />
- </button>
+ />
</div>
</template>
diff --git a/app/assets/javascripts/batch_comments/components/inline_draft_comment_row.vue b/app/assets/javascripts/batch_comments/components/inline_draft_comment_row.vue
deleted file mode 100644
index 385725cd109..00000000000
--- a/app/assets/javascripts/batch_comments/components/inline_draft_comment_row.vue
+++ /dev/null
@@ -1,32 +0,0 @@
-<script>
-import DraftNote from './draft_note.vue';
-
-export default {
- components: {
- DraftNote,
- },
- props: {
- draft: {
- type: Object,
- required: true,
- },
- diffFile: {
- type: Object,
- required: true,
- },
- line: {
- type: Object,
- required: false,
- default: null,
- },
- },
-};
-</script>
-
-<template>
- <tr class="notes_holder js-temp-notes-holder">
- <td class="notes-content" colspan="4">
- <div class="content"><draft-note :draft="draft" :diff-file="diffFile" :line="line" /></div>
- </td>
- </tr>
-</template>
diff --git a/app/assets/javascripts/batch_comments/components/parallel_draft_comment_row.vue b/app/assets/javascripts/batch_comments/components/parallel_draft_comment_row.vue
deleted file mode 100644
index b0916623cd2..00000000000
--- a/app/assets/javascripts/batch_comments/components/parallel_draft_comment_row.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-<script>
-import { mapGetters } from 'vuex';
-import DraftNote from './draft_note.vue';
-
-export default {
- components: {
- DraftNote,
- },
- props: {
- line: {
- type: Object,
- required: true,
- },
- diffFileContentSha: {
- type: String,
- required: true,
- },
- },
- computed: {
- ...mapGetters('batchComments', ['draftForLine']),
- className() {
- return this.leftDraft > 0 || this.rightDraft > 0 ? '' : 'js-temp-notes-holder';
- },
- leftDraft() {
- return this.draftForLine(this.diffFileContentSha, this.line, 'left');
- },
- rightDraft() {
- return this.draftForLine(this.diffFileContentSha, this.line, 'right');
- },
- },
-};
-</script>
-
-<template>
- <tr :class="className" class="notes_holder">
- <td class="notes_line old"></td>
- <td class="notes-content parallel old" colspan="2">
- <div v-if="leftDraft.isDraft" class="content">
- <draft-note :draft="leftDraft" :line="line.left" />
- </div>
- </td>
- <td class="notes_line new"></td>
- <td class="notes-content parallel new" colspan="2">
- <div v-if="rightDraft.isDraft" class="content">
- <draft-note :draft="rightDraft" :line="line.right" />
- </div>
- </td>
- </tr>
-</template>
diff --git a/app/assets/javascripts/batch_comments/mixins/resolved_status.js b/app/assets/javascripts/batch_comments/mixins/resolved_status.js
index 2517fb198f0..0b085da1ff9 100644
--- a/app/assets/javascripts/batch_comments/mixins/resolved_status.js
+++ b/app/assets/javascripts/batch_comments/mixins/resolved_status.js
@@ -1,7 +1,9 @@
import { mapGetters } from 'vuex';
import { sprintf, s__, __ } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
+ mixins: [glFeatureFlagsMixin()],
props: {
discussionId: {
type: String,
@@ -54,6 +56,10 @@ export default {
let title = __('Mark as resolved');
+ if (this.glFeatures.removeResolveNote) {
+ title = __('Resolve thread');
+ }
+
if (this.resolvedBy) {
title = sprintf(__('Resolved by %{name}'), { name: this.resolvedBy.name });
}
diff --git a/app/assets/javascripts/behaviors/copy_to_clipboard.js b/app/assets/javascripts/behaviors/copy_to_clipboard.js
index 430a8c38387..e822072d669 100644
--- a/app/assets/javascripts/behaviors/copy_to_clipboard.js
+++ b/app/assets/javascripts/behaviors/copy_to_clipboard.js
@@ -79,3 +79,33 @@ export default function initCopyToClipboard() {
clipboardData.setData('text/x-gfm', json.gfm);
});
}
+
+/**
+ * Programmatically triggers a click event on a
+ * "copy to clipboard" button, causing its
+ * contents to be copied. Handles some of the messiniess
+ * around managing the button's tooltip.
+ * @param {HTMLElement} btnElement
+ */
+export function clickCopyToClipboardButton(btnElement) {
+ const $btnElement = $(btnElement);
+
+ // Ensure the button has already been tooltip'd.
+ // If the use hasn't yet interacted (i.e. hovered or clicked)
+ // with the button, Bootstrap hasn't yet initialized
+ // the tooltip, and its `data-original-title` will be `undefined`.
+ // This value is used in the functions above.
+ $btnElement.tooltip();
+ btnElement.dispatchEvent(new MouseEvent('mouseover'));
+
+ btnElement.click();
+
+ // Manually trigger the necessary events to hide the
+ // button's tooltip and allow the button to perform its
+ // tooltip cleanup (updating the title from "Copied" back
+ // to its original title, "Copy branch name").
+ setTimeout(() => {
+ btnElement.dispatchEvent(new MouseEvent('mouseout'));
+ $btnElement.tooltip('hide');
+ }, 2000);
+}
diff --git a/app/assets/javascripts/behaviors/details_behavior.js b/app/assets/javascripts/behaviors/details_behavior.js
deleted file mode 100644
index 9bdfc21c7e4..00000000000
--- a/app/assets/javascripts/behaviors/details_behavior.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import $ from 'jquery';
-
-$(() => {
- $('body').on('click', '.js-details-target', function target() {
- $(this)
- .closest('.js-details-container')
- .toggleClass('open');
- });
-
- // Show details content. Hides link after click.
- //
- // %div
- // %a.js-details-expand
- // %div.js-details-content
- //
- $('body').on('click', '.js-details-expand', function expand(e) {
- e.preventDefault();
- $(this)
- .next('.js-details-content')
- .removeClass('hide');
- $(this).hide();
-
- const truncatedItem = $(this).siblings('.js-details-short');
- if (truncatedItem.length) {
- truncatedItem.addClass('hide');
- }
- });
-});
diff --git a/app/assets/javascripts/behaviors/index.js b/app/assets/javascripts/behaviors/index.js
index 613309a1c5a..75659bbf685 100644
--- a/app/assets/javascripts/behaviors/index.js
+++ b/app/assets/javascripts/behaviors/index.js
@@ -4,7 +4,6 @@ import './bind_in_out';
import './markdown/render_gfm';
import initCopyAsGFM from './markdown/copy_as_gfm';
import initCopyToClipboard from './copy_to_clipboard';
-import './details_behavior';
import installGlEmojiElement from './gl_emoji';
import './quick_submit';
import './requires_input';
diff --git a/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js b/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js
index 83f2ca0bdc2..d712c90242c 100644
--- a/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js
+++ b/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js
@@ -14,6 +14,7 @@ export default function initGFMInput($els) {
milestones: enableGFM,
mergeRequests: enableGFM,
labels: enableGFM,
+ vulnerabilities: enableGFM,
});
});
}
diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
index cb0e6345059..233c5f84340 100644
--- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js
+++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
@@ -25,7 +25,7 @@ function importMermaidModule() {
return import(/* webpackChunkName: 'mermaid' */ 'mermaid')
.then(mermaid => {
let theme = 'neutral';
- const ideDarkThemes = ['dark', 'solarized-dark'];
+ const ideDarkThemes = ['dark', 'solarized-dark', 'monokai'];
if (
ideDarkThemes.includes(window.gon?.user_color_scheme) &&
diff --git a/app/assets/javascripts/behaviors/quick_submit.js b/app/assets/javascripts/behaviors/quick_submit.js
index 49eab3e4f09..907cfc06e28 100644
--- a/app/assets/javascripts/behaviors/quick_submit.js
+++ b/app/assets/javascripts/behaviors/quick_submit.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import '../commons/bootstrap';
import { isInIssuePage } from '../lib/utils/common_utils';
import { __ } from '~/locale';
+import { add, show, hide } from '~/tooltips';
// Quick Submit behavior
//
@@ -65,18 +66,17 @@ $(document).on(
return;
}
- const $this = $(this);
+ const $el = $(this);
const title = isMac()
- ? __('You can also press &#8984;-Enter')
+ ? __('You can also press \u{2318}-Enter')
: __('You can also press Ctrl-Enter');
- $this.tooltip({
- container: 'body',
- html: true,
- placement: 'top',
+ add($el, {
+ triggers: 'manual',
+ show: true,
title,
- trigger: 'manual',
});
- $this.tooltip('show').one('blur click', () => $this.tooltip('hide'));
+ $el.one('blur click', () => hide($el));
+ show($el);
},
);
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
index f7b327b2af1..5a5a67334d3 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
@@ -4,6 +4,8 @@ import Sidebar from '../../right_sidebar';
import Shortcuts from './shortcuts';
import { CopyAsGFM } from '../markdown/copy_as_gfm';
import { getSelectedFragment } from '~/lib/utils/common_utils';
+import { isElementVisible } from '~/lib/utils/dom_utils';
+import { clickCopyToClipboardButton } from '~/behaviors/copy_to_clipboard';
export default class ShortcutsIssuable extends Shortcuts {
constructor() {
@@ -14,6 +16,7 @@ export default class ShortcutsIssuable extends Shortcuts {
Mousetrap.bind('l', () => ShortcutsIssuable.openSidebarDropdown('labels'));
Mousetrap.bind('r', ShortcutsIssuable.replyWithSelectedText);
Mousetrap.bind('e', ShortcutsIssuable.editIssue);
+ Mousetrap.bind('b', ShortcutsIssuable.copyBranchName);
}
static replyWithSelectedText() {
@@ -98,4 +101,18 @@ export default class ShortcutsIssuable extends Shortcuts {
Sidebar.instance.openDropdown(name);
return false;
}
+
+ static copyBranchName() {
+ // There are two buttons - one that is shown when the sidebar
+ // is expanded, and one that is shown when it's collapsed.
+ const allCopyBtns = Array.from(document.querySelectorAll('.sidebar-source-branch button'));
+
+ // Select whichever button is currently visible so that
+ // the "Copied" tooltip is shown when a click is simulated.
+ const visibleBtn = allCopyBtns.find(isElementVisible);
+
+ if (visibleBtn) {
+ clickCopyToClipboardButton(visibleBtn);
+ }
+ }
}
diff --git a/app/assets/javascripts/behaviors/toggler_behavior.js b/app/assets/javascripts/behaviors/toggler_behavior.js
index ef8b8788abf..4b63143c4ba 100644
--- a/app/assets/javascripts/behaviors/toggler_behavior.js
+++ b/app/assets/javascripts/behaviors/toggler_behavior.js
@@ -12,11 +12,19 @@ import { getLocationHash } from '../lib/utils/url_utility';
$(() => {
function toggleContainer(container, toggleState) {
const $container = $(container);
-
- $container
- .find('.js-toggle-button .fa-chevron-up, .js-toggle-button .fa-chevron-down')
- .toggleClass('fa-chevron-up', toggleState)
- .toggleClass('fa-chevron-down', toggleState !== undefined ? !toggleState : undefined);
+ const isExpanded = $container.data('is-expanded');
+ const $collapseIcon = $container.find('.js-sidebar-collapse');
+ const $expandIcon = $container.find('.js-sidebar-expand');
+
+ if (isExpanded && !toggleState) {
+ $container.data('is-expanded', false);
+ $collapseIcon.addClass('hidden');
+ $expandIcon.removeClass('hidden');
+ } else {
+ $container.data('is-expanded', true);
+ $expandIcon.addClass('hidden');
+ $collapseIcon.removeClass('hidden');
+ }
$container.find('.js-toggle-content').toggle(toggleState);
}
diff --git a/app/assets/javascripts/blob/components/blob_edit_content.vue b/app/assets/javascripts/blob/components/blob_edit_content.vue
index a013d637c1d..73ccc3289b9 100644
--- a/app/assets/javascripts/blob/components/blob_edit_content.vue
+++ b/app/assets/javascripts/blob/components/blob_edit_content.vue
@@ -1,7 +1,7 @@
<script>
import { debounce } from 'lodash';
import { initEditorLite } from '~/blob/utils';
-import { SNIPPET_MEASURE_BLOBS_CONTENT } from '~/performance_constants';
+import { SNIPPET_MEASURE_BLOBS_CONTENT } from '~/performance/constants';
import eventHub from './eventhub';
diff --git a/app/assets/javascripts/blob/components/blob_edit_header.vue b/app/assets/javascripts/blob/components/blob_edit_header.vue
index 2cbbbddceeb..5715635fd13 100644
--- a/app/assets/javascripts/blob/components/blob_edit_header.vue
+++ b/app/assets/javascripts/blob/components/blob_edit_header.vue
@@ -50,6 +50,7 @@ export default {
variant="danger"
category="secondary"
:disabled="!canDelete"
+ data-qa-selector="delete_file_button"
@click="$emit('delete')"
>{{ s__('Snippets|Delete file') }}</gl-button
>
diff --git a/app/assets/javascripts/blob/components/blob_header.vue b/app/assets/javascripts/blob/components/blob_header.vue
index fd40c51fec1..a4a43b7a94e 100644
--- a/app/assets/javascripts/blob/components/blob_header.vue
+++ b/app/assets/javascripts/blob/components/blob_header.vue
@@ -66,7 +66,7 @@ export default {
<template>
<div class="js-file-title file-title-flex-parent">
<blob-filepath :blob="blob">
- <template #filepathPrepend>
+ <template #filepath-prepend>
<slot name="prepend"></slot>
</template>
</blob-filepath>
diff --git a/app/assets/javascripts/blob/components/blob_header_default_actions.vue b/app/assets/javascripts/blob/components/blob_header_default_actions.vue
index daade611651..6eddec31166 100644
--- a/app/assets/javascripts/blob/components/blob_header_default_actions.vue
+++ b/app/assets/javascripts/blob/components/blob_header_default_actions.vue
@@ -32,6 +32,7 @@ export default {
default: false,
},
},
+ inject: ['blobHash'],
computed: {
downloadUrl() {
return `${this.rawPath}?inline=false`;
@@ -39,6 +40,9 @@ export default {
copyDisabled() {
return this.activeViewer === RICH_BLOB_VIEWER;
},
+ getBlobHashTarget() {
+ return `[data-blob-hash="${this.blobHash}"]`;
+ },
},
BTN_COPY_CONTENTS_TITLE,
BTN_DOWNLOAD_TITLE,
@@ -53,7 +57,7 @@ export default {
:aria-label="$options.BTN_COPY_CONTENTS_TITLE"
:title="$options.BTN_COPY_CONTENTS_TITLE"
:disabled="copyDisabled"
- data-clipboard-target="#blob-code-content"
+ :data-clipboard-target="getBlobHashTarget"
data-testid="copyContentsButton"
icon="copy-to-clipboard"
category="primary"
diff --git a/app/assets/javascripts/blob/components/blob_header_filepath.vue b/app/assets/javascripts/blob/components/blob_header_filepath.vue
index f99ecba2324..eb8068a8ad7 100644
--- a/app/assets/javascripts/blob/components/blob_header_filepath.vue
+++ b/app/assets/javascripts/blob/components/blob_header_filepath.vue
@@ -26,7 +26,7 @@ export default {
</script>
<template>
<div class="file-header-content d-flex align-items-center lh-100">
- <slot name="filepathPrepend"></slot>
+ <slot name="filepath-prepend"></slot>
<template v-if="blob.path">
<file-icon :file-name="blob.path" :size="18" aria-hidden="true" css-classes="mr-2" />
diff --git a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
index 1412e49836d..02a522dda9d 100644
--- a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
+++ b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
@@ -9,8 +9,6 @@ const trackingMixin = Tracking.mixin();
export default {
beginnerLink:
'https://about.gitlab.com/blog/2018/01/22/a-beginners-guide-to-continuous-integration/',
- exampleLink: 'https://docs.gitlab.com/ee/ci/examples/',
- codeQualityLink: 'https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html',
goToTrackValuePipelines: 10,
goToTrackValueMergeRequest: 20,
trackEvent: 'click_button',
@@ -39,6 +37,14 @@ export default {
type: String,
required: true,
},
+ exampleLink: {
+ type: String,
+ required: true,
+ },
+ codeQualityLink: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
@@ -93,7 +99,7 @@ export default {
<p>
<gl-sprintf :message="$options.i18n.bodyMessage">
<template #codeQualityLink="{content}">
- <gl-link :href="$options.codeQualityLink" target="_blank" class="font-size-inherit">{{
+ <gl-link :href="codeQualityLink" target="_blank" class="font-size-inherit">{{
content
}}</gl-link>
</template>
@@ -106,7 +112,7 @@ export default {
</gl-link>
</template>
<template #exampleLink="{content}">
- <gl-link :href="$options.exampleLink" target="_blank">
+ <gl-link :href="exampleLink" target="_blank">
{{ content }}
</gl-link>
</template>
diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js
index 2d426ee663a..f84e39baa53 100644
--- a/app/assets/javascripts/blob_edit/blob_bundle.js
+++ b/app/assets/javascripts/blob_edit/blob_bundle.js
@@ -8,11 +8,40 @@ import initPopover from '~/blob/suggest_gitlab_ci_yml';
import { disableButtonIfEmptyField, setCookie } from '~/lib/utils/common_utils';
import Tracking from '~/tracking';
+const initPopovers = () => {
+ const suggestEl = document.querySelector('.js-suggest-gitlab-ci-yml');
+
+ if (suggestEl) {
+ const commitButton = document.querySelector('#commit-changes');
+
+ initPopover(suggestEl);
+
+ 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, mergeRequestPath);
+
+ Tracking.event(undefined, 'click_button', {
+ label: commitTrackLabel,
+ property: humanAccess,
+ value: commitTrackValue,
+ });
+ });
+ }
+ }
+};
+
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');
if (editBlobForm.length) {
const urlRoot = editBlobForm.data('relativeUrlRoot');
@@ -33,6 +62,7 @@ export default () => {
projectId,
isMarkdown,
});
+ initPopovers();
})
.catch(e => createFlash(e));
@@ -62,30 +92,4 @@ export default () => {
if (deleteBlobForm.length) {
new NewCommitForm(deleteBlobForm);
}
-
- if (suggestEl) {
- const commitButton = document.querySelector('#commit-changes');
-
- initPopover(suggestEl);
-
- 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, mergeRequestPath);
-
- Tracking.event(undefined, 'click_button', {
- label: commitTrackLabel,
- property: humanAccess,
- value: commitTrackValue,
- });
- });
- }
- }
};
diff --git a/app/assets/javascripts/boards/components/board_assignee_dropdown.vue b/app/assets/javascripts/boards/components/board_assignee_dropdown.vue
new file mode 100644
index 00000000000..c81f171af2b
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_assignee_dropdown.vue
@@ -0,0 +1,178 @@
+<script>
+import { mapActions, mapGetters } from 'vuex';
+import {
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlAvatarLabeled,
+ GlAvatarLink,
+ GlSearchBoxByType,
+} from '@gitlab/ui';
+import { __, n__ } from '~/locale';
+import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
+import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
+import MultiSelectDropdown from '~/vue_shared/components/sidebar/multiselect_dropdown.vue';
+import getIssueParticipants from '~/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql';
+import searchUsers from '~/boards/queries/users_search.query.graphql';
+
+export default {
+ noSearchDelay: 0,
+ searchDelay: 250,
+ i18n: {
+ unassigned: __('Unassigned'),
+ assignee: __('Assignee'),
+ assignees: __('Assignees'),
+ assignTo: __('Assign to'),
+ },
+ components: {
+ BoardEditableItem,
+ IssuableAssignees,
+ MultiSelectDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlAvatarLabeled,
+ GlAvatarLink,
+ GlSearchBoxByType,
+ },
+ data() {
+ return {
+ search: '',
+ participants: [],
+ selected: this.$store.getters.activeIssue.assignees,
+ };
+ },
+ apollo: {
+ participants: {
+ query() {
+ return this.isSearchEmpty ? getIssueParticipants : searchUsers;
+ },
+ variables() {
+ if (this.isSearchEmpty) {
+ return {
+ id: `gid://gitlab/Issue/${this.activeIssue.iid}`,
+ };
+ }
+
+ return {
+ search: this.search,
+ };
+ },
+ update(data) {
+ if (this.isSearchEmpty) {
+ return data.issue?.participants?.nodes || [];
+ }
+
+ return data.users?.nodes || [];
+ },
+ debounce() {
+ const { noSearchDelay, searchDelay } = this.$options;
+
+ return this.isSearchEmpty ? noSearchDelay : searchDelay;
+ },
+ },
+ },
+ computed: {
+ ...mapGetters(['activeIssue']),
+ assigneeText() {
+ return n__('Assignee', '%d Assignees', this.selected.length);
+ },
+ unSelectedFiltered() {
+ return this.participants.filter(({ username }) => {
+ return !this.selectedUserNames.includes(username);
+ });
+ },
+ selectedIsEmpty() {
+ return this.selected.length === 0;
+ },
+ selectedUserNames() {
+ return this.selected.map(({ username }) => username);
+ },
+ isSearchEmpty() {
+ return this.search === '';
+ },
+ },
+ methods: {
+ ...mapActions(['setAssignees']),
+ clearSelected() {
+ this.selected = [];
+ },
+ selectAssignee(name) {
+ if (name === undefined) {
+ this.clearSelected();
+ return;
+ }
+
+ this.selected = this.selected.concat(name);
+ },
+ unselect(name) {
+ this.selected = this.selected.filter(user => user.username !== name);
+ },
+ saveAssignees() {
+ this.setAssignees(this.selectedUserNames);
+ },
+ isChecked(id) {
+ return this.selectedUserNames.includes(id);
+ },
+ },
+};
+</script>
+
+<template>
+ <board-editable-item :title="assigneeText" @close="saveAssignees">
+ <template #collapsed>
+ <issuable-assignees :users="activeIssue.assignees" />
+ </template>
+
+ <template #default>
+ <multi-select-dropdown
+ class="w-100"
+ :text="$options.i18n.assignees"
+ :header-text="$options.i18n.assignTo"
+ >
+ <template #search>
+ <gl-search-box-by-type v-model.trim="search" />
+ </template>
+ <template #items>
+ <gl-dropdown-item
+ :is-checked="selectedIsEmpty"
+ data-testid="unassign"
+ class="mt-2"
+ @click="selectAssignee()"
+ >{{ $options.i18n.unassigned }}</gl-dropdown-item
+ >
+ <gl-dropdown-divider data-testid="unassign-divider" />
+ <gl-dropdown-item
+ v-for="item in selected"
+ :key="item.id"
+ :is-checked="isChecked(item.username)"
+ @click="unselect(item.username)"
+ >
+ <gl-avatar-link>
+ <gl-avatar-labeled
+ :size="32"
+ :label="item.name"
+ :sub-label="item.username"
+ :src="item.avatarUrl || item.avatar"
+ />
+ </gl-avatar-link>
+ </gl-dropdown-item>
+ <gl-dropdown-divider v-if="!selectedIsEmpty" data-testid="selected-user-divider" />
+ <gl-dropdown-item
+ v-for="unselectedUser in unSelectedFiltered"
+ :key="unselectedUser.id"
+ :data-testid="`item_${unselectedUser.name}`"
+ @click="selectAssignee(unselectedUser)"
+ >
+ <gl-avatar-link>
+ <gl-avatar-labeled
+ :size="32"
+ :label="unselectedUser.name"
+ :sub-label="unselectedUser.username"
+ :src="unselectedUser.avatarUrl || unselectedUser.avatar"
+ />
+ </gl-avatar-link>
+ </gl-dropdown-item>
+ </template>
+ </multi-select-dropdown>
+ </template>
+ </board-editable-item>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_card_layout.vue b/app/assets/javascripts/boards/components/board_card_layout.vue
index 072dd87861a..f796acd2303 100644
--- a/app/assets/javascripts/boards/components/board_card_layout.vue
+++ b/app/assets/javascripts/boards/components/board_card_layout.vue
@@ -44,9 +44,6 @@ export default {
multiSelectVisible() {
return this.multiSelect.list.findIndex(issue => issue.id === this.issue.id) > -1;
},
- canMultiSelect() {
- return gon.features && gon.features.multiSelectBoard;
- },
},
methods: {
mouseDown() {
@@ -59,7 +56,7 @@ export default {
// 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);
+ const isMultiSelect = e.ctrlKey || e.metaKey;
if (this.showDetail || isMultiSelect) {
this.showDetail = false;
diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue
index 9295065b7b7..cb93340bcf8 100644
--- a/app/assets/javascripts/boards/components/board_column.vue
+++ b/app/assets/javascripts/boards/components/board_column.vue
@@ -1,14 +1,10 @@
<script>
-import { mapGetters, mapActions } from 'vuex';
+// This component is being replaced in favor of './board_column_new.vue' for GraphQL boards
import Sortable from 'sortablejs';
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 BoardList from './board_list.vue';
-import BoardListNew from './board_list_new.vue';
import boardsStore from '../stores/boards_store';
-import eventHub from '../eventhub';
import { getBoardSortableDefaultOptions, sortableEnd } from '../mixins/sortable_default_options';
import { ListType } from '../constants';
@@ -16,12 +12,8 @@ export default {
components: {
BoardPromotionState: EmptyComponent,
BoardListHeader,
- BoardList: gon.features?.graphqlBoardLists ? BoardListNew : BoardList,
+ BoardList,
},
- directives: {
- Tooltip,
- },
- mixins: [glFeatureFlagMixin()],
props: {
list: {
type: Object,
@@ -50,44 +42,25 @@ export default {
};
},
computed: {
- ...mapGetters(['getIssues']),
showBoardListAndBoardInfo() {
return this.list.type !== ListType.promotion;
},
- uniqueKey() {
- // 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;
+ return this.list.issues;
},
},
watch: {
filter: {
handler() {
- if (this.shouldFetchIssues) {
- this.fetchIssuesForList({ listId: this.list.id });
- } else {
- this.list.page = 1;
- this.list.getIssues(true).catch(() => {
- // TODO: handle request error
- });
- }
+ this.list.page = 1;
+ this.list.getIssues(true).catch(() => {
+ // TODO: handle request error
+ });
},
deep: true,
},
},
mounted() {
- if (this.shouldFetchIssues) {
- this.fetchIssuesForList({ listId: this.list.id });
- }
-
const instance = this;
const sortableOptions = getBoardSortableDefaultOptions({
@@ -113,12 +86,6 @@ export default {
Sortable.create(this.$el.parentNode, sortableOptions);
},
- methods: {
- ...mapActions(['fetchIssuesForList']),
- showListNewIssueForm(listId) {
- eventHub.$emit('showForm', listId);
- },
- },
};
</script>
@@ -131,7 +98,7 @@ export default {
'board-type-assignee': list.type === 'assignee',
}"
:data-id="list.id"
- class="board gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal"
+ class="board gl-display-inline-block gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal"
data-qa-selector="board_list"
>
<div
diff --git a/app/assets/javascripts/boards/components/board_column_new.vue b/app/assets/javascripts/boards/components/board_column_new.vue
new file mode 100644
index 00000000000..8a59355eb83
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_column_new.vue
@@ -0,0 +1,94 @@
+<script>
+import { mapGetters, mapActions, mapState } from 'vuex';
+import BoardListHeader from 'ee_else_ce/boards/components/board_list_header_new.vue';
+import BoardPromotionState from 'ee_else_ce/boards/components/board_promotion_state';
+import BoardList from './board_list_new.vue';
+import { ListType } from '../constants';
+
+export default {
+ components: {
+ BoardPromotionState,
+ BoardListHeader,
+ BoardList,
+ },
+ props: {
+ list: {
+ type: Object,
+ default: () => ({}),
+ required: false,
+ },
+ disabled: {
+ type: Boolean,
+ required: true,
+ },
+ canAdminList: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ inject: {
+ boardId: {
+ default: '',
+ },
+ },
+ computed: {
+ ...mapState(['filterParams']),
+ ...mapGetters(['getIssuesByList']),
+ showBoardListAndBoardInfo() {
+ return this.list.type !== ListType.promotion;
+ },
+ listIssues() {
+ return this.getIssuesByList(this.list.id);
+ },
+ shouldFetchIssues() {
+ return this.list.type !== ListType.blank;
+ },
+ },
+ watch: {
+ filterParams: {
+ handler() {
+ if (this.shouldFetchIssues) {
+ this.fetchIssuesForList({ listId: this.list.id });
+ }
+ },
+ deep: true,
+ immediate: true,
+ },
+ },
+ methods: {
+ ...mapActions(['fetchIssuesForList']),
+ // TODO: Reordering of lists https://gitlab.com/gitlab-org/gitlab/-/issues/280515
+ },
+};
+</script>
+
+<template>
+ <div
+ :class="{
+ 'is-draggable': !list.preset,
+ 'is-expandable': list.isExpandable,
+ 'is-collapsed': !list.isExpanded,
+ 'board-type-assignee': list.type === 'assignee',
+ }"
+ :data-id="list.id"
+ class="board gl-display-inline-block gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal"
+ data-qa-selector="board_list"
+ >
+ <div
+ class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base"
+ >
+ <board-list-header :can-admin-list="canAdminList" :list="list" :disabled="disabled" />
+ <board-list
+ v-if="showBoardListAndBoardInfo"
+ ref="board-list"
+ :disabled="disabled"
+ :issues="listIssues"
+ :list="list"
+ />
+
+ <!-- Will be only available in EE -->
+ <board-promotion-state v-if="list.id === 'promotion'" />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_configuration_options.vue b/app/assets/javascripts/boards/components/board_configuration_options.vue
index ad3d653b905..754b00b54e0 100644
--- a/app/assets/javascripts/boards/components/board_configuration_options.vue
+++ b/app/assets/javascripts/boards/components/board_configuration_options.vue
@@ -43,7 +43,7 @@ export default {
<template>
<div class="append-bottom-20">
- <label class="form-section-title label-bold" for="board-new-name">
+ <label class="label-bold gl-font-lg" for="board-new-name">
{{ __('List options') }}
</label>
<p class="text-secondary gl-mb-3">
diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue
index 2515f471379..92976574efb 100644
--- a/app/assets/javascripts/boards/components/board_content.vue
+++ b/app/assets/javascripts/boards/components/board_content.vue
@@ -1,13 +1,14 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
import { sortBy } from 'lodash';
-import BoardColumn from 'ee_else_ce/boards/components/board_column.vue';
import { GlAlert } from '@gitlab/ui';
+import BoardColumn from 'ee_else_ce/boards/components/board_column.vue';
+import BoardColumnNew from './board_column_new.vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
components: {
- BoardColumn,
+ BoardColumn: gon.features?.graphqlBoardLists ? BoardColumnNew : BoardColumn,
BoardContentSidebar: () => import('ee_component/boards/components/board_content_sidebar.vue'),
EpicsSwimlanes: () => import('ee_component/boards/components/epics_swimlanes.vue'),
GlAlert,
@@ -38,12 +39,11 @@ export default {
},
mounted() {
if (this.glFeatures.graphqlBoardLists) {
- this.fetchLists();
this.showPromotionList();
}
},
methods: {
- ...mapActions(['fetchLists', 'showPromotionList']),
+ ...mapActions(['showPromotionList']),
},
};
</script>
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index 793c594cf16..e4ef3600ff9 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -196,9 +196,7 @@ export default {
<p v-if="isDeleteForm">{{ __('Are you sure you want to delete this board?') }}</p>
<form v-else class="js-board-config-modal" @submit.prevent>
<div v-if="!readonly" class="append-bottom-20">
- <label class="form-section-title label-bold" for="board-new-name">{{
- __('Title')
- }}</label>
+ <label class="label-bold gl-font-lg" for="board-new-name">{{ __('Title') }}</label>
<input
id="board-new-name"
ref="name"
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index d01df44e7e4..53989e2d9de 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -16,9 +16,7 @@ import {
// This component is being replaced in favor of './board_list_new.vue' for GraphQL boards
-if (gon.features && gon.features.multiSelectBoard) {
- Sortable.mount(new MultiDrag());
-}
+Sortable.mount(new MultiDrag());
export default {
name: 'BoardList',
@@ -100,12 +98,11 @@ export default {
mounted() {
// TODO: Use Draggable in ./board_list_new.vue to drag & drop issue
// https://gitlab.com/gitlab-org/gitlab/-/issues/218164
- const multiSelectOpts = {};
- if (gon.features && gon.features.multiSelectBoard) {
- multiSelectOpts.multiDrag = true;
- multiSelectOpts.selectedClass = 'js-multi-select';
- multiSelectOpts.animation = 500;
- }
+ const multiSelectOpts = {
+ multiDrag: true,
+ selectedClass: 'js-multi-select',
+ animation: 500,
+ };
const options = getBoardSortableDefaultOptions({
scroll: true,
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index bb9a1b79d91..d85ba2038a7 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -17,7 +17,6 @@ import eventHub from '../eventhub';
import sidebarEventHub from '~/sidebar/event_hub';
import { inactiveId, LIST, 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 +31,6 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
- mixins: [glFeatureFlagMixin()],
props: {
list: {
type: Object,
@@ -121,12 +119,9 @@ export default {
collapsedTooltipTitle() {
return this.listTitle || this.listAssignee;
},
- shouldDisplaySwimlanes() {
- return this.glFeatures.boardsWithSwimlanes && this.isSwimlanesOn;
- },
},
methods: {
- ...mapActions(['updateList', 'setActiveId']),
+ ...mapActions(['setActiveId']),
openSidebarSettings() {
if (this.activeId === inactiveId) {
sidebarEventHub.$emit('sidebar.closeAll');
@@ -160,11 +155,7 @@ export default {
}
},
updateListFunction() {
- if (this.shouldDisplaySwimlanes || this.glFeatures.graphqlBoardLists) {
- this.updateList({ listId: this.list.id, collapsed: !this.list.isExpanded });
- } else {
- this.list.update();
- }
+ this.list.update();
},
},
};
@@ -188,8 +179,9 @@ export default {
'gl-py-3 gl-h-full': !list.isExpanded && !isSwimlanesHeader,
'gl-border-b-0': !list.isExpanded || isSwimlanesHeader,
'gl-py-2': !list.isExpanded && isSwimlanesHeader,
+ 'gl-flex-direction-column': !list.isExpanded,
}"
- class="board-title gl-m-0 gl-display-flex js-board-handle"
+ class="board-title gl-m-0 gl-display-flex gl-align-items-center gl-font-base gl-px-3 js-board-handle"
>
<gl-button
v-if="list.isExpandable"
@@ -202,7 +194,15 @@ export default {
@click="toggleExpanded"
/>
<!-- The following is only true in EE and if it is a milestone -->
- <span v-if="showMilestoneListDetails" aria-hidden="true" class="gl-mr-2 milestone-icon">
+ <span
+ v-if="showMilestoneListDetails"
+ aria-hidden="true"
+ class="milestone-icon"
+ :class="{
+ 'gl-mt-3 gl-rotate-90': !list.isExpanded,
+ 'gl-mr-2': list.isExpanded,
+ }"
+ >
<gl-icon name="timer" />
</span>
@@ -210,6 +210,9 @@ export default {
v-if="showAssigneeListDetails"
:href="list.assignee.path"
class="user-avatar-link js-no-trigger"
+ :class="{
+ 'gl-mt-3 gl-rotate-90': !list.isExpanded,
+ }"
>
<img
v-gl-tooltip.hover.bottom
@@ -223,20 +226,28 @@ export default {
</a>
<div
class="board-title-text"
- :class="{ 'gl-display-none': !list.isExpanded && isSwimlanesHeader }"
+ :class="{
+ 'gl-display-none': !list.isExpanded && isSwimlanesHeader,
+ 'gl-flex-grow-0 gl-my-3 gl-mx-0': !list.isExpanded,
+ 'gl-flex-grow-1': list.isExpanded,
+ }"
>
<span
v-if="list.type !== 'label'"
v-gl-tooltip.hover
:class="{
- 'gl-display-inline-block': list.type === 'milestone',
+ 'gl-display-block': !list.isExpanded || list.type === 'milestone',
}"
:title="listTitle"
- class="board-title-main-text block-truncated"
+ class="board-title-main-text gl-text-truncate"
>
{{ list.title }}
</span>
- <span v-if="list.type === 'assignee'" class="board-title-sub-text gl-ml-2">
+ <span
+ v-if="list.type === 'assignee'"
+ class="gl-ml-2 gl-font-weight-normal gl-text-gray-500"
+ :class="{ 'gl-display-none': !list.isExpanded }"
+ >
@{{ listAssignee }}
</span>
<gl-label
@@ -279,7 +290,10 @@ export default {
<div
v-if="showBoardListAndBoardInfo"
class="issue-count-badge gl-display-inline-flex gl-pr-0 no-drag text-secondary"
- :class="{ 'gl-display-none!': !list.isExpanded && isSwimlanesHeader }"
+ :class="{
+ 'gl-display-none!': !list.isExpanded && isSwimlanesHeader,
+ 'gl-p-0': !list.isExpanded,
+ }"
>
<span class="gl-display-inline-flex">
<gl-tooltip :target="() => $refs.issueCount" :title="issuesTooltipLabel" />
diff --git a/app/assets/javascripts/boards/components/board_list_header_new.vue b/app/assets/javascripts/boards/components/board_list_header_new.vue
new file mode 100644
index 00000000000..99347a4cd4d
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_list_header_new.vue
@@ -0,0 +1,358 @@
+<script>
+import { mapActions, mapState } from 'vuex';
+import {
+ GlButton,
+ GlButtonGroup,
+ GlLabel,
+ GlTooltip,
+ GlIcon,
+ GlSprintf,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+import { n__, s__ } from '~/locale';
+import AccessorUtilities from '../../lib/utils/accessor';
+import IssueCount from './issue_count.vue';
+import eventHub from '../eventhub';
+import sidebarEventHub from '~/sidebar/event_hub';
+import { inactiveId, LIST, ListType } from '../constants';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+
+export default {
+ components: {
+ GlButtonGroup,
+ GlButton,
+ GlLabel,
+ GlTooltip,
+ GlIcon,
+ GlSprintf,
+ IssueCount,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ list: {
+ type: Object,
+ default: () => ({}),
+ required: false,
+ },
+ disabled: {
+ type: Boolean,
+ required: true,
+ },
+ isSwimlanesHeader: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ inject: {
+ boardId: {
+ default: '',
+ },
+ weightFeatureAvailable: {
+ default: false,
+ },
+ scopedLabelsAvailable: {
+ default: false,
+ },
+ currentUserId: {
+ default: null,
+ },
+ },
+ computed: {
+ ...mapState(['activeId']),
+ isLoggedIn() {
+ return Boolean(this.currentUserId);
+ },
+ listType() {
+ return this.list.type;
+ },
+ listAssignee() {
+ return this.list?.assignee?.username || '';
+ },
+ listTitle() {
+ return this.list?.label?.description || this.list.title || '';
+ },
+ showListHeaderButton() {
+ return (
+ !this.disabled &&
+ this.listType !== ListType.closed &&
+ this.listType !== ListType.blank &&
+ this.listType !== ListType.promotion
+ );
+ },
+ showMilestoneListDetails() {
+ return (
+ this.list.type === ListType.milestone &&
+ this.list.milestone &&
+ (this.list.isExpanded || !this.isSwimlanesHeader)
+ );
+ },
+ showAssigneeListDetails() {
+ return (
+ this.list.type === ListType.assignee && (this.list.isExpanded || !this.isSwimlanesHeader)
+ );
+ },
+ issuesCount() {
+ return this.list.issuesSize;
+ },
+ issuesTooltipLabel() {
+ return n__(`%d issue`, `%d issues`, this.issuesCount);
+ },
+ chevronTooltip() {
+ return this.list.isExpanded ? s__('Boards|Collapse') : s__('Boards|Expand');
+ },
+ chevronIcon() {
+ return this.list.isExpanded ? 'chevron-right' : 'chevron-down';
+ },
+ isNewIssueShown() {
+ return this.listType === ListType.backlog || this.showListHeaderButton;
+ },
+ isSettingsShown() {
+ return (
+ this.listType !== ListType.backlog && this.showListHeaderButton && this.list.isExpanded
+ );
+ },
+ showBoardListAndBoardInfo() {
+ return this.listType !== ListType.blank && this.listType !== ListType.promotion;
+ },
+ uniqueKey() {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `boards.${this.boardId}.${this.listType}.${this.list.id}`;
+ },
+ collapsedTooltipTitle() {
+ return this.listTitle || this.listAssignee;
+ },
+ headerStyle() {
+ return { borderTopColor: this.list?.label?.color };
+ },
+ },
+ methods: {
+ ...mapActions(['updateList', 'setActiveId']),
+ openSidebarSettings() {
+ if (this.activeId === inactiveId) {
+ sidebarEventHub.$emit('sidebar.closeAll');
+ }
+
+ this.setActiveId({ id: this.list.id, sidebarType: LIST });
+ },
+ showScopedLabels(label) {
+ return this.scopedLabelsAvailable && isScopedLabel(label);
+ },
+
+ showNewIssueForm() {
+ eventHub.$emit(`toggle-issue-form-${this.list.id}`);
+ },
+ toggleExpanded() {
+ this.list.isExpanded = !this.list.isExpanded;
+
+ if (!this.isLoggedIn) {
+ this.addToLocalStorage();
+ } else {
+ this.updateListFunction();
+ }
+
+ // When expanding/collapsing, the tooltip on the caret button sometimes stays open.
+ // Close all tooltips manually to prevent dangling tooltips.
+ this.$root.$emit('bv::hide::tooltip');
+ },
+ addToLocalStorage() {
+ if (AccessorUtilities.isLocalStorageAccessSafe()) {
+ localStorage.setItem(`${this.uniqueKey}.expanded`, this.list.isExpanded);
+ }
+ },
+ updateListFunction() {
+ this.updateList({ listId: this.list.id, collapsed: !this.list.isExpanded });
+ },
+ },
+};
+</script>
+
+<template>
+ <header
+ :class="{
+ 'has-border': list.label && list.label.color,
+ 'gl-h-full': !list.isExpanded,
+ 'board-inner gl-rounded-top-left-base gl-rounded-top-right-base': isSwimlanesHeader,
+ }"
+ :style="headerStyle"
+ class="board-header gl-relative"
+ data-qa-selector="board_list_header"
+ data-testid="board-list-header"
+ >
+ <h3
+ :class="{
+ 'user-can-drag': !disabled && !list.preset,
+ 'gl-py-3 gl-h-full': !list.isExpanded && !isSwimlanesHeader,
+ 'gl-border-b-0': !list.isExpanded || isSwimlanesHeader,
+ 'gl-py-2': !list.isExpanded && isSwimlanesHeader,
+ 'gl-flex-direction-column': !list.isExpanded,
+ }"
+ class="board-title gl-m-0 gl-display-flex gl-align-items-center gl-font-base gl-px-3 js-board-handle"
+ >
+ <gl-button
+ v-if="list.isExpandable"
+ v-gl-tooltip.hover
+ :aria-label="chevronTooltip"
+ :title="chevronTooltip"
+ :icon="chevronIcon"
+ class="board-title-caret no-drag gl-cursor-pointer"
+ variant="link"
+ @click="toggleExpanded"
+ />
+ <!-- EE start -->
+ <span
+ v-if="showMilestoneListDetails"
+ aria-hidden="true"
+ class="milestone-icon"
+ :class="{
+ 'gl-mt-3 gl-rotate-90': !list.isExpanded,
+ 'gl-mr-2': list.isExpanded,
+ }"
+ >
+ <gl-icon name="timer" />
+ </span>
+
+ <a
+ v-if="showAssigneeListDetails"
+ :href="list.assignee.path"
+ class="user-avatar-link js-no-trigger"
+ :class="{
+ 'gl-mt-3 gl-rotate-90': !list.isExpanded,
+ }"
+ >
+ <img
+ v-gl-tooltip.hover.bottom
+ :title="listAssignee"
+ :alt="list.assignee.name"
+ :src="list.assignee.avatar"
+ class="avatar s20"
+ height="20"
+ width="20"
+ />
+ </a>
+ <!-- EE end -->
+ <div
+ class="board-title-text"
+ :class="{
+ 'gl-display-none': !list.isExpanded && isSwimlanesHeader,
+ 'gl-flex-grow-0 gl-my-3 gl-mx-0': !list.isExpanded,
+ 'gl-flex-grow-1': list.isExpanded,
+ }"
+ >
+ <!-- EE start -->
+ <span
+ v-if="listType !== 'label'"
+ v-gl-tooltip.hover
+ :class="{
+ 'gl-display-block': !list.isExpanded || listType === 'milestone',
+ }"
+ :title="listTitle"
+ class="board-title-main-text gl-text-truncate"
+ >
+ {{ list.title }}
+ </span>
+ <span
+ v-if="listType === 'assignee'"
+ v-show="list.isExpanded"
+ class="gl-ml-2 gl-font-weight-normal gl-text-gray-500"
+ >
+ @{{ listAssignee }}
+ </span>
+ <!-- EE end -->
+ <gl-label
+ v-if="listType === 'label'"
+ v-gl-tooltip.hover.bottom
+ :background-color="list.label.color"
+ :description="list.label.description"
+ :scoped="showScopedLabels(list.label)"
+ :size="!list.isExpanded ? 'sm' : ''"
+ :title="list.label.title"
+ />
+ </div>
+
+ <!-- EE start -->
+ <span
+ v-if="isSwimlanesHeader && !list.isExpanded"
+ ref="collapsedInfo"
+ aria-hidden="true"
+ class="board-header-collapsed-info-icon gl-mt-2 gl-cursor-pointer gl-text-gray-500"
+ >
+ <gl-icon name="information" />
+ </span>
+ <gl-tooltip v-if="isSwimlanesHeader && !list.isExpanded" :target="() => $refs.collapsedInfo">
+ <div class="gl-font-weight-bold gl-pb-2">{{ collapsedTooltipTitle }}</div>
+ <div v-if="list.maxIssueCount !== 0">
+ •
+ <gl-sprintf :message="__('%{issuesSize} with a limit of %{maxIssueCount}')">
+ <template #issuesSize>{{ issuesTooltipLabel }}</template>
+ <template #maxIssueCount>{{ list.maxIssueCount }}</template>
+ </gl-sprintf>
+ </div>
+ <div v-else>• {{ issuesTooltipLabel }}</div>
+ <div v-if="weightFeatureAvailable">
+ •
+ <gl-sprintf :message="__('%{totalWeight} total weight')">
+ <template #totalWeight>{{ list.totalWeight }}</template>
+ </gl-sprintf>
+ </div>
+ </gl-tooltip>
+ <!-- EE end -->
+
+ <div
+ v-if="showBoardListAndBoardInfo"
+ class="issue-count-badge gl-display-inline-flex gl-pr-0 no-drag gl-text-gray-500"
+ :class="{
+ 'gl-display-none!': !list.isExpanded && isSwimlanesHeader,
+ 'gl-p-0': !list.isExpanded,
+ }"
+ >
+ <span class="gl-display-inline-flex">
+ <gl-tooltip :target="() => $refs.issueCount" :title="issuesTooltipLabel" />
+ <span ref="issueCount" class="issue-count-badge-count">
+ <gl-icon class="gl-mr-2" name="issues" />
+ <issue-count :issues-size="issuesCount" :max-issue-count="list.maxIssueCount" />
+ </span>
+ <!-- EE start -->
+ <template v-if="weightFeatureAvailable">
+ <gl-tooltip :target="() => $refs.weightTooltip" :title="weightCountToolTip" />
+ <span ref="weightTooltip" class="gl-display-inline-flex gl-ml-3">
+ <gl-icon class="gl-mr-2" name="weight" />
+ {{ list.totalWeight }}
+ </span>
+ </template>
+ <!-- EE end -->
+ </span>
+ </div>
+ <gl-button-group
+ v-if="isNewIssueShown || isSettingsShown"
+ class="board-list-button-group pl-2"
+ >
+ <gl-button
+ v-if="isNewIssueShown"
+ v-show="list.isExpanded"
+ ref="newIssueBtn"
+ v-gl-tooltip.hover
+ :aria-label="__('New issue')"
+ :title="__('New issue')"
+ class="issue-count-badge-add-button no-drag"
+ icon="plus"
+ @click="showNewIssueForm"
+ />
+
+ <gl-button
+ v-if="isSettingsShown"
+ ref="settingsBtn"
+ v-gl-tooltip.hover
+ :aria-label="__('List settings')"
+ class="no-drag js-board-settings-button"
+ :title="__('List settings')"
+ icon="settings"
+ @click="openSidebarSettings"
+ />
+ <gl-tooltip :target="() => $refs.settingsBtn">{{ __('List settings') }}</gl-tooltip>
+ </gl-button-group>
+ </h3>
+ </header>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_list_new.vue b/app/assets/javascripts/boards/components/board_list_new.vue
index 0a495d05122..396aedcc557 100644
--- a/app/assets/javascripts/boards/components/board_list_new.vue
+++ b/app/assets/javascripts/boards/components/board_list_new.vue
@@ -1,7 +1,7 @@
<script>
import { mapActions, mapState } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
-import BoardNewIssue from './board_new_issue.vue';
+import BoardNewIssue from './board_new_issue_new.vue';
import BoardCard from './board_card.vue';
import eventHub from '../eventhub';
import boardsStore from '../stores/boards_store';
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index 0a665b82880..a9e6d768656 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -1,6 +1,4 @@
<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';
@@ -9,6 +7,8 @@ import ProjectSelect from './project_select.vue';
import boardsStore from '../stores/boards_store';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+// This component is being replaced in favor of './board_new_issue_new.vue' for GraphQL boards
+
export default {
name: 'BoardNewIssue',
components: {
@@ -31,23 +31,18 @@ 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();
@@ -74,31 +69,14 @@ 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();
-
- if (!this.shouldDisplaySwimlanes && !this.glFeatures.graphqlBoardLists) {
- boardsStore.setIssueDetail(issue);
- boardsStore.setListDetail(this.list);
- }
+ 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
- if (this.shouldDisplaySwimlanes || this.glFeatures.graphqlBoardLists) {
- this.addListIssueFailure({ list: this.list, issue });
- } else {
- this.list.removeIssue(issue);
- }
+ this.list.removeIssue(issue);
// Show error message
this.error = true;
@@ -137,7 +115,7 @@ export default {
<gl-button
ref="submitButton"
:disabled="disabled"
- class="float-left"
+ class="float-left js-no-auto-disable"
variant="success"
category="primary"
type="submit"
diff --git a/app/assets/javascripts/boards/components/board_new_issue_new.vue b/app/assets/javascripts/boards/components/board_new_issue_new.vue
new file mode 100644
index 00000000000..969c84ddb59
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_new_issue_new.vue
@@ -0,0 +1,129 @@
+<script>
+import { mapActions } from 'vuex';
+import { GlButton } from '@gitlab/ui';
+import { getMilestone } from 'ee_else_ce/boards/boards_util';
+import eventHub from '../eventhub';
+import ProjectSelect from './project_select.vue';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { __ } from '~/locale';
+
+export default {
+ name: 'BoardNewIssue',
+ i18n: {
+ submit: __('Submit issue'),
+ cancel: __('Cancel'),
+ },
+ components: {
+ ProjectSelect,
+ GlButton,
+ },
+ mixins: [glFeatureFlagMixin()],
+ props: {
+ list: {
+ type: Object,
+ required: true,
+ },
+ },
+ inject: ['groupId', 'weightFeatureAvailable', 'boardWeight'],
+ data() {
+ return {
+ title: '',
+ selectedProject: {},
+ };
+ },
+ computed: {
+ disabled() {
+ if (this.groupId) {
+ return this.title === '' || !this.selectedProject.name;
+ }
+ return this.title === '';
+ },
+ inputFieldId() {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `${this.list.id}-title`;
+ },
+ },
+ mounted() {
+ this.$refs.input.focus();
+ eventHub.$on('setSelectedProject', this.setSelectedProject);
+ },
+ methods: {
+ ...mapActions(['addListNewIssue']),
+ submit(e) {
+ e.preventDefault();
+
+ const labels = this.list.label ? [this.list.label] : [];
+ const assignees = this.list.assignee ? [this.list.assignee] : [];
+ const milestone = getMilestone(this.list);
+
+ const weight = this.weightFeatureAvailable ? this.boardWeight : undefined;
+
+ const { title } = this;
+
+ eventHub.$emit(`scroll-board-list-${this.list.id}`);
+
+ return this.addListNewIssue({
+ issueInput: {
+ title,
+ labelIds: labels?.map(l => l.id),
+ assigneeIds: assignees?.map(a => a?.id),
+ milestoneId: milestone?.id,
+ projectPath: this.selectedProject.path,
+ weight: weight >= 0 ? weight : null,
+ },
+ list: this.list,
+ }).then(() => {
+ this.reset();
+ });
+ },
+ reset() {
+ this.title = '';
+ eventHub.$emit(`toggle-issue-form-${this.list.id}`);
+ },
+ setSelectedProject(selectedProject) {
+ this.selectedProject = selectedProject;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="board-new-issue-form">
+ <div class="board-card position-relative p-3 rounded">
+ <form ref="submitForm" @submit="submit">
+ <label :for="inputFieldId" class="label-bold">{{ __('Title') }}</label>
+ <input
+ :id="inputFieldId"
+ ref="input"
+ v-model="title"
+ class="form-control"
+ type="text"
+ name="issue_title"
+ autocomplete="off"
+ />
+ <project-select v-if="groupId" :group-id="groupId" :list="list" />
+ <div class="clearfix gl-mt-3">
+ <gl-button
+ ref="submitButton"
+ :disabled="disabled"
+ class="float-left js-no-auto-disable"
+ variant="success"
+ category="primary"
+ type="submit"
+ >
+ {{ $options.i18n.submit }}
+ </gl-button>
+ <gl-button
+ ref="cancelButton"
+ class="float-right"
+ type="button"
+ variant="default"
+ @click="reset"
+ >
+ {{ $options.i18n.cancel }}
+ </gl-button>
+ </div>
+ </form>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_promotion_state.js b/app/assets/javascripts/boards/components/board_promotion_state.js
new file mode 100644
index 00000000000..ff8b4c56321
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_promotion_state.js
@@ -0,0 +1 @@
+export default {};
diff --git a/app/assets/javascripts/boards/components/board_settings_sidebar.vue b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
index 392e056dcbf..80070b25bd0 100644
--- a/app/assets/javascripts/boards/components/board_settings_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
@@ -36,6 +36,9 @@ export default {
computed: {
...mapGetters(['isSidebarOpen', 'shouldUseGraphQL']),
...mapState(['activeId', 'sidebarType', 'boardLists']),
+ isWipLimitsOn() {
+ return this.glFeatures.wipLimits;
+ },
activeList() {
/*
Warning: Though a computed property it is not reactive because we are
@@ -66,14 +69,18 @@ export default {
eventHub.$off('sidebar.closeAll', this.unsetActiveId);
},
methods: {
- ...mapActions(['unsetActiveId']),
+ ...mapActions(['unsetActiveId', 'removeList']),
showScopedLabels(label) {
return boardsStore.scopedLabels.enabled && isScopedLabel(label);
},
deleteBoard() {
// eslint-disable-next-line no-alert
- if (window.confirm(__('Are you sure you want to delete this list?'))) {
- this.activeList.destroy();
+ if (window.confirm(__('Are you sure you want to remove this list?'))) {
+ if (this.shouldUseGraphQL) {
+ this.removeList(this.activeId);
+ } else {
+ this.activeList.destroy();
+ }
this.unsetActiveId();
}
},
@@ -105,7 +112,10 @@ export default {
:active-list="activeList"
:board-list-type="boardListType"
/>
- <board-settings-sidebar-wip-limit :max-issue-count="activeList.maxIssueCount" />
+ <board-settings-sidebar-wip-limit
+ v-if="isWipLimitsOn"
+ :max-issue-count="activeList.maxIssueCount"
+ />
<div v-if="canAdminList && !activeList.preset && activeList.id" class="gl-m-4">
<gl-button
variant="danger"
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index 271e1fc4b5f..0b079c78209 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -261,7 +261,7 @@ export default {
>
<gl-deprecated-dropdown-item
v-show="filteredBoards.length === 0"
- class="no-pointer-events text-secondary"
+ class="gl-pointer-events-none text-secondary"
>
{{ s__('IssueBoards|No matching boards found') }}
</gl-deprecated-dropdown-item>
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue
index a181ea51c4a..45ce1e51489 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner.vue
@@ -3,7 +3,7 @@ import { sortBy } from 'lodash';
import { mapState } from 'vuex';
import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import issueCardInner from 'ee_else_ce/boards/mixins/issue_card_inner';
-import { sprintf, __ } from '~/locale';
+import { sprintf, __, n__ } from '~/locale';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import IssueDueDate from './issue_due_date.vue';
@@ -89,6 +89,12 @@ export default {
orderedLabels() {
return sortBy(this.issue.labels.filter(this.isNonListLabel), 'title');
},
+ blockedLabel() {
+ if (this.issue.blockedByCount) {
+ return n__(`Blocked by %d issue`, `Blocked by %d issues`, this.issue.blockedByCount);
+ }
+ return __('Blocked issue');
+ },
},
methods: {
isIndexLessThanlimit(index) {
@@ -133,15 +139,16 @@ export default {
</script>
<template>
<div>
- <div class="d-flex board-card-header" dir="auto">
+ <div class="gl-display-flex" dir="auto">
<h4 class="board-card-title gl-mb-0 gl-mt-0">
<gl-icon
v-if="issue.blocked"
v-gl-tooltip
name="issue-block"
- :title="__('Blocked issue')"
+ :title="blockedLabel"
class="issue-blocked-icon gl-mr-2"
- :aria-label="__('Blocked issue')"
+ :aria-label="blockedLabel"
+ data-testid="issue-blocked-icon"
/>
<gl-icon
v-if="issue.confidential"
@@ -156,7 +163,7 @@ export default {
}}</a>
</h4>
</div>
- <div v-if="showLabelFooter" class="board-card-labels gl-mt-2 d-flex flex-wrap">
+ <div v-if="showLabelFooter" class="board-card-labels gl-mt-2 gl-display-flex gl-flex-wrap">
<template v-for="label in orderedLabels">
<gl-label
:key="label.id"
@@ -169,24 +176,26 @@ export default {
/>
</template>
</div>
- <div class="board-card-footer d-flex justify-content-between align-items-end">
+ <div
+ class="board-card-footer gl-display-flex gl-justify-content-space-between gl-align-items-flex-end"
+ >
<div
- class="d-flex align-items-start flex-wrap-reverse board-card-number-container overflow-hidden js-board-card-number-container"
+ class="gl-display-flex align-items-start flex-wrap-reverse board-card-number-container gl-overflow-hidden js-board-card-number-container"
>
<span
v-if="issue.referencePath"
- class="board-card-number overflow-hidden d-flex gl-mr-3 gl-mt-3"
+ class="board-card-number gl-overflow-hidden gl-display-flex gl-mr-3 gl-mt-3"
>
<tooltip-on-truncate
v-if="issueReferencePath"
:title="issueReferencePath"
placement="bottom"
- class="board-issue-path block-truncated bold"
+ class="board-issue-path gl-text-truncate gl-font-weight-bold"
>{{ issueReferencePath }}</tooltip-on-truncate
>
#{{ issue.iid }}
</span>
- <span class="board-info-items gl-mt-3 d-inline-block">
+ <span class="board-info-items gl-mt-3 gl-display-inline-block">
<issue-due-date v-if="issue.dueDate" :date="issue.dueDate" :closed="issue.closed" />
<issue-time-estimate v-if="issue.timeEstimate" :estimate="issue.timeEstimate" />
<issue-card-weight
@@ -196,20 +205,20 @@ export default {
/>
</span>
</div>
- <div class="board-card-assignee d-flex">
+ <div class="board-card-assignee gl-display-flex">
<user-avatar-link
v-for="(assignee, index) in issue.assignees"
v-if="shouldRenderAssignee(index)"
:key="assignee.id"
:link-href="assigneeUrl(assignee)"
:img-alt="avatarUrlTitle(assignee)"
- :img-src="assignee.avatar || assignee.avatar_url"
+ :img-src="assignee.avatarUrl || assignee.avatar || assignee.avatar_url"
:img-size="24"
class="js-no-trigger"
tooltip-placement="bottom"
>
<span class="js-assignee-tooltip">
- <span class="bold d-block">{{ __('Assignee') }}</span>
+ <span class="gl-font-weight-bold gl-display-block">{{ __('Assignee') }}</span>
{{ assignee.name }}
<span class="text-white-50">@{{ assignee.username }}</span>
</span>
diff --git a/app/assets/javascripts/boards/components/modal/empty_state.vue b/app/assets/javascripts/boards/components/modal/empty_state.vue
index cd4512f320f..eb2db260717 100644
--- a/app/assets/javascripts/boards/components/modal/empty_state.vue
+++ b/app/assets/javascripts/boards/components/modal/empty_state.vue
@@ -1,13 +1,13 @@
<script>
-/* eslint-disable vue/no-v-html */
-import { GlButton } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
+import { GlButton, GlSprintf } from '@gitlab/ui';
+import { __ } from '~/locale';
import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins';
export default {
components: {
GlButton,
+ GlSprintf,
},
mixins: [modalMixin],
props: {
@@ -34,11 +34,8 @@ export default {
if (this.activeTab === 'selected') {
obj.title = __("You haven't selected any issues yet");
- obj.content = sprintf(
- __(
- 'Go back to %{startTag}Open issues%{endTag} and select some issues to add to your board.',
- ),
- { startTag: '<strong>', endTag: '</strong>' },
+ obj.content = __(
+ 'Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board.',
);
}
@@ -57,7 +54,13 @@ export default {
<div class="col-12 col-md-6 order-md-first">
<div class="text-content">
<h4>{{ contents.title }}</h4>
- <p v-html="contents.content"></p>
+ <p>
+ <gl-sprintf :message="contents.content">
+ <template #tag="{ content }">
+ <strong>{{ content }}</strong>
+ </template>
+ </gl-sprintf>
+ </p>
<gl-button
v-if="activeTab === 'all'"
:href="newIssuePath"
diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js b/app/assets/javascripts/boards/components/new_list_dropdown.js
index c8926c5ef2a..47eee5306da 100644
--- a/app/assets/javascripts/boards/components/new_list_dropdown.js
+++ b/app/assets/javascripts/boards/components/new_list_dropdown.js
@@ -7,6 +7,7 @@ import { deprecatedCreateFlash as flash } from '~/flash';
import CreateLabelDropdown from '../../create_label';
import boardsStore from '../stores/boards_store';
import { fullLabelId } from '../boards_util';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import store from '~/boards/stores';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
@@ -61,7 +62,7 @@ export default function initNewListDropdown() {
const active = boardsStore.findListByLabelId(label.id);
const $li = $('<li />');
const $a = $('<a />', {
- class: active ? `is-active js-board-list-${active.id}` : '',
+ class: active ? `is-active js-board-list-${getIdFromGraphQLId(active.id)}` : '',
text: label.title,
href: '#',
});
diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue
index 566c0081b9d..f90fe582566 100644
--- a/app/assets/javascripts/boards/components/project_select.vue
+++ b/app/assets/javascripts/boards/components/project_select.vue
@@ -44,6 +44,7 @@ export default {
this.selectedProject = {
id: $el.data('project-id'),
name: $el.data('project-name'),
+ path: $el.data('project-path'),
};
eventHub.$emit('setSelectedProject', this.selectedProject);
},
@@ -75,11 +76,12 @@ export default {
renderRow(project) {
return `
<li>
- <a href='#' class='dropdown-menu-link' data-project-id="${
- project.id
- }" data-project-name="${project.name}" data-project-name-with-namespace="${
- project.name_with_namespace
- }">
+ <a href='#' class='dropdown-menu-link'
+ data-project-id="${project.id}"
+ data-project-name="${project.name}"
+ data-project-name-with-namespace="${project.name_with_namespace}"
+ data-project-path="${project.path_with_namespace}"
+ >
${escape(project.name_with_namespace)}
</a>
</li>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
new file mode 100644
index 00000000000..6935ead2706
--- /dev/null
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
@@ -0,0 +1,111 @@
+<script>
+import { mapGetters, mapActions } from 'vuex';
+import { GlButton, GlDatepicker } from '@gitlab/ui';
+import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
+import { dateInWords, formatDate, parsePikadayDate } from '~/lib/utils/datetime_utility';
+import createFlash from '~/flash';
+import { __ } from '~/locale';
+
+export default {
+ components: {
+ BoardEditableItem,
+ GlButton,
+ GlDatepicker,
+ },
+ data() {
+ return {
+ loading: false,
+ };
+ },
+ computed: {
+ ...mapGetters({ issue: 'activeIssue', projectPathForActiveIssue: 'projectPathForActiveIssue' }),
+ hasDueDate() {
+ return this.issue.dueDate != null;
+ },
+ parsedDueDate() {
+ if (!this.hasDueDate) {
+ return null;
+ }
+
+ return parsePikadayDate(this.issue.dueDate);
+ },
+ formattedDueDate() {
+ if (!this.hasDueDate) {
+ return '';
+ }
+
+ return dateInWords(this.parsedDueDate, true);
+ },
+ },
+ methods: {
+ ...mapActions(['setActiveIssueDueDate']),
+ async openDatePicker() {
+ await this.$nextTick();
+ this.$refs.datePicker.calendar.show();
+ },
+ async setDueDate(date) {
+ this.loading = true;
+ this.$refs.sidebarItem.collapse();
+
+ try {
+ const dueDate = date ? formatDate(date, 'yyyy-mm-dd') : null;
+ await this.setActiveIssueDueDate({ dueDate, projectPath: this.projectPathForActiveIssue });
+ } catch (e) {
+ createFlash({ message: this.$options.i18n.updateDueDateError });
+ } finally {
+ this.loading = false;
+ }
+ },
+ },
+ i18n: {
+ dueDate: __('Due date'),
+ removeDueDate: __('remove due date'),
+ updateDueDateError: __('An error occurred when updating the issue due date'),
+ },
+};
+</script>
+
+<template>
+ <board-editable-item
+ ref="sidebarItem"
+ class="board-sidebar-due-date"
+ :title="$options.i18n.dueDate"
+ :loading="loading"
+ @open="openDatePicker"
+ >
+ <template v-if="hasDueDate" #collapsed>
+ <div class="gl-display-flex gl-align-items-center">
+ <strong class="gl-text-gray-900">{{ formattedDueDate }}</strong>
+ <span class="gl-mx-2">-</span>
+ <gl-button
+ variant="link"
+ class="gl-text-gray-400!"
+ data-testid="reset-button"
+ :disabled="loading"
+ @click="setDueDate(null)"
+ >
+ {{ $options.i18n.removeDueDate }}
+ </gl-button>
+ </div>
+ </template>
+ <template>
+ <gl-datepicker
+ ref="datePicker"
+ :value="parsedDueDate"
+ show-clear-button
+ @input="setDueDate"
+ @clear="setDueDate(null)"
+ />
+ </template>
+ </board-editable-item>
+</template>
+<style>
+/*
+ * This can be removed after closing:
+ * https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1048
+ */
+.board-sidebar-due-date .gl-datepicker,
+.board-sidebar-due-date .gl-datepicker-input {
+ width: 100%;
+}
+</style>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
index 0f063c7582e..9d537a4ef2c 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
@@ -21,9 +21,9 @@ export default {
},
inject: ['labelsFetchPath', 'labelsManagePath', 'labelsFilterBasePath'],
computed: {
- ...mapGetters({ issue: 'getActiveIssue' }),
+ ...mapGetters(['activeIssue', 'projectPathForActiveIssue']),
selectedLabels() {
- const { labels = [] } = this.issue;
+ const { labels = [] } = this.activeIssue;
return labels.map(label => ({
...label,
@@ -31,17 +31,13 @@ export default {
}));
},
issueLabels() {
- const { labels = [] } = this.issue;
+ const { labels = [] } = this.activeIssue;
return labels.map(label => ({
...label,
scoped: isScopedLabel(label),
}));
},
- projectPath() {
- const { referencePath = '' } = this.issue;
- return referencePath.slice(0, referencePath.indexOf('#'));
- },
},
methods: {
...mapActions(['setActiveIssueLabels']),
@@ -55,7 +51,7 @@ export default {
.filter(label => !payload.find(selected => selected.id === label.id))
.map(label => label.id);
- const input = { addLabelIds, removeLabelIds, projectPath: this.projectPath };
+ const input = { addLabelIds, removeLabelIds, projectPath: this.projectPathForActiveIssue };
await this.setActiveIssueLabels(input);
} catch (e) {
createFlash({ message: __('An error occurred while updating labels.') });
@@ -68,7 +64,7 @@ export default {
try {
const removeLabelIds = [getIdFromGraphQLId(id)];
- const input = { removeLabelIds, projectPath: this.projectPath };
+ const input = { removeLabelIds, projectPath: this.projectPathForActiveIssue };
await this.setActiveIssueLabels(input);
} catch (e) {
createFlash({ message: __('An error occurred when removing the label.') });
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
new file mode 100644
index 00000000000..ed069cea630
--- /dev/null
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
@@ -0,0 +1,71 @@
+<script>
+import { mapGetters, mapActions } from 'vuex';
+import { GlToggle } from '@gitlab/ui';
+import createFlash from '~/flash';
+import { __, s__ } from '~/locale';
+
+export default {
+ i18n: {
+ header: {
+ title: __('Notifications'),
+ /* Any change to subscribeDisabledDescription
+ must be reflected in app/helpers/notifications_helper.rb */
+ subscribeDisabledDescription: __(
+ 'Notifications have been disabled by the project or group owner',
+ ),
+ },
+ updateSubscribedErrorMessage: s__(
+ 'IssueBoards|An error occurred while setting notifications status.',
+ ),
+ },
+ components: {
+ GlToggle,
+ },
+ data() {
+ return {
+ loading: false,
+ };
+ },
+ computed: {
+ ...mapGetters(['activeIssue', 'projectPathForActiveIssue']),
+ notificationText() {
+ return this.activeIssue.emailsDisabled
+ ? this.$options.i18n.header.subscribeDisabledDescription
+ : this.$options.i18n.header.title;
+ },
+ },
+ methods: {
+ ...mapActions(['setActiveIssueSubscribed']),
+ async handleToggleSubscription() {
+ this.loading = true;
+
+ try {
+ await this.setActiveIssueSubscribed({
+ subscribed: !this.activeIssue.subscribed,
+ projectPath: this.projectPathForActiveIssue,
+ });
+ } catch (error) {
+ createFlash({ message: this.$options.i18n.updateSubscribedErrorMessage });
+ } finally {
+ this.loading = false;
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-space-between"
+ data-testid="sidebar-notifications"
+ >
+ <span data-testid="notification-header-text"> {{ notificationText }} </span>
+ <gl-toggle
+ v-if="!activeIssue.emailsDisabled"
+ :value="activeIssue.subscribed"
+ :is-loading="loading"
+ data-testid="notification-subscribe-toggle"
+ @change="handleToggleSubscription"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js
index 2f64014a949..49cb560594c 100644
--- a/app/assets/javascripts/boards/constants.js
+++ b/app/assets/javascripts/boards/constants.js
@@ -18,7 +18,11 @@ export const inactiveId = 0;
export const ISSUABLE = 'issuable';
export const LIST = 'list';
+/* eslint-disable-next-line @gitlab/require-i18n-strings */
+export const DEFAULT_LABELS = ['to do', 'doing'];
+
export default {
BoardType,
ListType,
+ DEFAULT_LABELS,
};
diff --git a/app/assets/javascripts/boards/graphql/mutations/issue_set_subscription.mutation.graphql b/app/assets/javascripts/boards/graphql/mutations/issue_set_subscription.mutation.graphql
new file mode 100644
index 00000000000..1f383245ac2
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/mutations/issue_set_subscription.mutation.graphql
@@ -0,0 +1,8 @@
+mutation issueSetSubscription($input: IssueSetSubscriptionInput!) {
+ issueSetSubscription(input: $input) {
+ issue {
+ subscribed
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index 887abe79059..d3e40299d8d 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import { mapActions, mapState } from 'vuex';
+import { mapActions, mapGetters, mapState } from 'vuex';
import 'ee_else_ce/boards/models/issue';
import 'ee_else_ce/boards/models/list';
@@ -86,10 +86,17 @@ export default () => {
boardId: $boardApp.dataset.boardId,
groupId: Number($boardApp.dataset.groupId),
rootPath: $boardApp.dataset.rootPath,
+ currentUserId: gon.current_user_id || null,
canUpdate: $boardApp.dataset.canUpdate,
labelsFetchPath: $boardApp.dataset.labelsFetchPath,
labelsManagePath: $boardApp.dataset.labelsManagePath,
labelsFilterBasePath: $boardApp.dataset.labelsFilterBasePath,
+ timeTrackingLimitToHours: parseBoolean($boardApp.dataset.timeTrackingLimitToHours),
+ weightFeatureAvailable: parseBoolean($boardApp.dataset.weightFeatureAvailable),
+ boardWeight: $boardApp.dataset.boardWeight
+ ? parseInt($boardApp.dataset.boardWeight, 10)
+ : null,
+ scopedLabelsAvailable: parseBoolean($boardApp.dataset.scopedLabels),
},
store,
apolloProvider,
@@ -108,6 +115,7 @@ export default () => {
},
computed: {
...mapState(['isShowingEpicsSwimlanes']),
+ ...mapGetters(['shouldUseGraphQL']),
detailIssueVisible() {
return Object.keys(this.detailIssue.issue).length;
},
@@ -153,7 +161,7 @@ export default () => {
boardsStore.disabled = this.disabled;
- if (!gon.features.graphqlBoardLists) {
+ if (!this.shouldUseGraphQL) {
this.initialBoardLoad();
}
},
diff --git a/app/assets/javascripts/boards/mixins/sortable_default_options.js b/app/assets/javascripts/boards/mixins/sortable_default_options.js
index fceb8c9d48e..f02c92e4230 100644
--- a/app/assets/javascripts/boards/mixins/sortable_default_options.js
+++ b/app/assets/javascripts/boards/mixins/sortable_default_options.js
@@ -1,17 +1,12 @@
/* global DocumentTouch */
-import $ from 'jquery';
import sortableConfig from 'ee_else_ce/sortable/sortable_config';
export function sortableStart() {
- $('.has-tooltip')
- .tooltip('hide')
- .tooltip('disable');
document.body.classList.add('is-dragging');
}
export function sortableEnd() {
- $('.has-tooltip').tooltip('enable');
document.body.classList.remove('is-dragging');
}
diff --git a/app/assets/javascripts/boards/queries/board_labels.query.graphql b/app/assets/javascripts/boards/queries/board_labels.query.graphql
new file mode 100644
index 00000000000..42a94419a97
--- /dev/null
+++ b/app/assets/javascripts/boards/queries/board_labels.query.graphql
@@ -0,0 +1,23 @@
+#import "~/graphql_shared/fragments/label.fragment.graphql"
+
+query BoardLabels(
+ $fullPath: ID!
+ $searchTerm: String
+ $isGroup: Boolean = false
+ $isProject: Boolean = false
+) {
+ group(fullPath: $fullPath) @include(if: $isGroup) {
+ labels(searchTerm: $searchTerm) {
+ nodes {
+ ...Label
+ }
+ }
+ }
+ project(fullPath: $fullPath) @include(if: $isProject) {
+ labels(searchTerm: $searchTerm) {
+ nodes {
+ ...Label
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/queries/board_list_destroy.mutation.graphql b/app/assets/javascripts/boards/queries/board_list_destroy.mutation.graphql
new file mode 100644
index 00000000000..ef3fd36e980
--- /dev/null
+++ b/app/assets/javascripts/boards/queries/board_list_destroy.mutation.graphql
@@ -0,0 +1,5 @@
+mutation DestroyBoardList($listId: ID!) {
+ destroyBoardList(input: { listId: $listId }) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/boards/queries/issue_create.mutation.graphql b/app/assets/javascripts/boards/queries/issue_create.mutation.graphql
new file mode 100644
index 00000000000..65be147be07
--- /dev/null
+++ b/app/assets/javascripts/boards/queries/issue_create.mutation.graphql
@@ -0,0 +1,10 @@
+#import "ee_else_ce/boards/queries/issue.fragment.graphql"
+
+mutation CreateIssue($input: CreateIssueInput!) {
+ createIssue(input: $input) {
+ issue {
+ ...IssueNode
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/boards/queries/issue_set_due_date.mutation.graphql b/app/assets/javascripts/boards/queries/issue_set_due_date.mutation.graphql
new file mode 100644
index 00000000000..bbea248cf85
--- /dev/null
+++ b/app/assets/javascripts/boards/queries/issue_set_due_date.mutation.graphql
@@ -0,0 +1,8 @@
+mutation issueSetDueDate($input: UpdateIssueInput!) {
+ updateIssue(input: $input) {
+ issue {
+ dueDate
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/boards/queries/users_search.query.graphql b/app/assets/javascripts/boards/queries/users_search.query.graphql
new file mode 100644
index 00000000000..ca016495d79
--- /dev/null
+++ b/app/assets/javascripts/boards/queries/users_search.query.graphql
@@ -0,0 +1,11 @@
+query usersSearch($search: String!) {
+ users(search: $search) {
+ nodes {
+ username
+ name
+ webUrl
+ avatarUrl
+ id
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index 1fed1228106..dd950a45076 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -1,26 +1,30 @@
-import Cookies from 'js-cookie';
import { pick } from 'lodash';
import boardListsQuery from 'ee_else_ce/boards/queries/board_lists.query.graphql';
-import { __ } from '~/locale';
-import { parseBoolean } from '~/lib/utils/common_utils';
import createGqClient, { fetchPolicies } from '~/lib/graphql';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { BoardType, ListType, inactiveId } from '~/boards/constants';
+import { BoardType, ListType, inactiveId, DEFAULT_LABELS } from '~/boards/constants';
import * as types from './mutation_types';
import {
formatBoardLists,
formatListIssues,
fullBoardId,
formatListsPageInfo,
+ formatIssue,
} from '../boards_util';
import boardStore from '~/boards/stores/boards_store';
+import updateAssignees from '~/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql';
import listsIssuesQuery from '../queries/lists_issues.query.graphql';
+import boardLabelsQuery from '../queries/board_labels.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';
+import destroyBoardListMutation from '../queries/board_list_destroy.mutation.graphql';
+import issueCreateMutation from '../queries/issue_create.mutation.graphql';
import issueSetLabels from '../queries/issue_set_labels.mutation.graphql';
+import issueSetDueDate from '../queries/issue_set_due_date.mutation.graphql';
+import issueSetSubscriptionMutation from '../graphql/mutations/issue_set_subscription.mutation.graphql';
const notImplemented = () => {
/* eslint-disable-next-line @gitlab/require-i18n-strings */
@@ -83,7 +87,7 @@ export default {
if (!lists.nodes.find(l => l.listType === ListType.backlog) && !hideBacklogList) {
dispatch('createList', { backlog: true });
}
- dispatch('showWelcomeList');
+ dispatch('generateDefaultLists');
})
.catch(() => commit(types.RECEIVE_BOARD_LISTS_FAILURE));
},
@@ -121,7 +125,32 @@ export default {
);
},
- showWelcomeList: ({ state, dispatch }) => {
+ showPromotionList: () => {},
+
+ fetchLabels: ({ state, commit }, searchTerm) => {
+ const { endpoints, boardType } = state;
+ const { fullPath } = endpoints;
+
+ const variables = {
+ fullPath,
+ searchTerm,
+ isGroup: boardType === BoardType.group,
+ isProject: boardType === BoardType.project,
+ };
+
+ return gqlClient
+ .query({
+ query: boardLabelsQuery,
+ variables,
+ })
+ .then(({ data }) => {
+ const labels = data[boardType]?.labels;
+ return labels.nodes;
+ })
+ .catch(() => commit(types.RECEIVE_LABELS_FAILURE));
+ },
+
+ generateDefaultLists: async ({ state, commit, dispatch }) => {
if (state.disabled) {
return;
}
@@ -132,22 +161,18 @@ export default {
) {
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: () => {},
+ const fetchLabelsAndCreateList = label => {
+ return dispatch('fetchLabels', label)
+ .then(res => {
+ if (res.length > 0) {
+ dispatch('createList', { labelId: res[0].id });
+ }
+ })
+ .catch(() => commit(types.GENERATE_DEFAULT_LISTS_FAILURE));
+ };
- generateDefaultLists: () => {
- notImplemented();
+ await Promise.all(DEFAULT_LABELS.map(fetchLabelsAndCreateList));
},
moveList: (
@@ -191,8 +216,26 @@ export default {
});
},
- deleteList: () => {
- notImplemented();
+ removeList: ({ state, commit }, listId) => {
+ const listsBackup = { ...state.boardLists };
+
+ commit(types.REMOVE_LIST, listId);
+
+ return gqlClient
+ .mutate({
+ mutation: destroyBoardListMutation,
+ variables: {
+ listId,
+ },
+ })
+ .then(({ data: { destroyBoardList: { errors } } }) => {
+ if (errors.length > 0) {
+ commit(types.REMOVE_LIST_FAILURE, listsBackup);
+ }
+ })
+ .catch(() => {
+ commit(types.REMOVE_LIST_FAILURE, listsBackup);
+ });
},
fetchIssuesForList: ({ state, commit }, { listId, fetchNext = false }) => {
@@ -271,20 +314,69 @@ export default {
);
},
- createNewIssue: () => {
- notImplemented();
+ setAssignees: ({ commit, getters }, assigneeUsernames) => {
+ return gqlClient
+ .mutate({
+ mutation: updateAssignees,
+ variables: {
+ iid: getters.activeIssue.iid,
+ projectPath: getters.activeIssue.referencePath.split('#')[0],
+ assigneeUsernames,
+ },
+ })
+ .then(({ data }) => {
+ commit('UPDATE_ISSUE_BY_ID', {
+ issueId: getters.activeIssue.id,
+ prop: 'assignees',
+ value: data.issueSetAssignees.issue.assignees.nodes,
+ });
+ });
+ },
+
+ createNewIssue: ({ commit, state }, issueInput) => {
+ const input = issueInput;
+ const { boardType, endpoints } = state;
+ if (boardType === BoardType.project) {
+ input.projectPath = endpoints.fullPath;
+ }
+
+ return gqlClient
+ .mutate({
+ mutation: issueCreateMutation,
+ variables: { input },
+ })
+ .then(({ data }) => {
+ if (data.createIssue.errors.length) {
+ commit(types.CREATE_ISSUE_FAILURE);
+ } else {
+ return data.createIssue?.issue;
+ }
+ return null;
+ })
+ .catch(() => commit(types.CREATE_ISSUE_FAILURE));
},
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 });
+ addListNewIssue: ({ commit, dispatch }, { issueInput, list }) => {
+ const issue = formatIssue({ ...issueInput, id: 'tmp' });
+ commit(types.ADD_ISSUE_TO_LIST, { list, issue, position: 0 });
+
+ dispatch('createNewIssue', issueInput)
+ .then(res => {
+ commit(types.ADD_ISSUE_TO_LIST, {
+ list,
+ issue: formatIssue({ ...res, id: getIdFromGraphQLId(res.id) }),
+ });
+ commit(types.REMOVE_ISSUE_FROM_LIST, { list, issue });
+ })
+ .catch(() => commit(types.ADD_ISSUE_TO_LIST_FAILURE, { list, issueId: issueInput.id }));
},
setActiveIssueLabels: async ({ commit, getters }, input) => {
- const activeIssue = getters.getActiveIssue;
+ const { activeIssue } = getters;
const { data } = await gqlClient.mutate({
mutation: issueSetLabels,
variables: {
@@ -308,6 +400,53 @@ export default {
});
},
+ setActiveIssueDueDate: async ({ commit, getters }, input) => {
+ const { activeIssue } = getters;
+ const { data } = await gqlClient.mutate({
+ mutation: issueSetDueDate,
+ variables: {
+ input: {
+ iid: String(activeIssue.iid),
+ projectPath: input.projectPath,
+ dueDate: input.dueDate,
+ },
+ },
+ });
+
+ if (data.updateIssue?.errors?.length > 0) {
+ throw new Error(data.updateIssue.errors);
+ }
+
+ commit(types.UPDATE_ISSUE_BY_ID, {
+ issueId: activeIssue.id,
+ prop: 'dueDate',
+ value: data.updateIssue.issue.dueDate,
+ });
+ },
+
+ setActiveIssueSubscribed: async ({ commit, getters }, input) => {
+ const { data } = await gqlClient.mutate({
+ mutation: issueSetSubscriptionMutation,
+ variables: {
+ input: {
+ iid: String(getters.activeIssue.iid),
+ projectPath: input.projectPath,
+ subscribedState: input.subscribed,
+ },
+ },
+ });
+
+ if (data.issueSetSubscription?.errors?.length > 0) {
+ throw new Error(data.issueSetSubscription.errors);
+ }
+
+ commit(types.UPDATE_ISSUE_BY_ID, {
+ issueId: getters.activeIssue.id,
+ prop: 'subscribed',
+ value: data.issueSetSubscription.issue.subscribed,
+ });
+ },
+
fetchBacklog: () => {
notImplemented();
},
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index d1a5db1bcc5..337b2897fe9 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -1,7 +1,6 @@
/* eslint-disable no-shadow, no-param-reassign,consistent-return */
/* global List */
/* global ListIssue */
-import $ from 'jquery';
import { sortBy, pick } from 'lodash';
import Vue from 'vue';
import Cookies from 'js-cookie';
@@ -119,8 +118,12 @@ const boardsStore = {
// https://gitlab.com/gitlab-org/gitlab-foss/issues/30821
});
},
+
updateNewListDropdown(listId) {
- $(`.js-board-list-${listId}`).removeClass('is-active');
+ // eslint-disable-next-line no-unused-expressions
+ document
+ .querySelector(`.js-board-list-${getIdFromGraphQLId(listId)}`)
+ ?.classList.remove('is-active');
},
shouldAddBlankState() {
// Decide whether to add the blank state
diff --git a/app/assets/javascripts/boards/stores/getters.js b/app/assets/javascripts/boards/stores/getters.js
index 89a3b14b262..cd28b4a0ff7 100644
--- a/app/assets/javascripts/boards/stores/getters.js
+++ b/app/assets/javascripts/boards/stores/getters.js
@@ -2,7 +2,7 @@ import { find } from 'lodash';
import { inactiveId } from '../constants';
export default {
- getLabelToggleState: state => (state.isShowingLabels ? 'on' : 'off'),
+ labelToggleState: state => (state.isShowingLabels ? 'on' : 'off'),
isSidebarOpen: state => state.activeId !== inactiveId,
isSwimlanesOn: state => {
if (!gon?.features?.boardsWithSwimlanes && !gon?.features?.swimlanes) {
@@ -15,15 +15,20 @@ export default {
return state.issues[id] || {};
},
- getIssues: (state, getters) => listId => {
+ getIssuesByList: (state, getters) => listId => {
const listIssueIds = state.issuesByListId[listId] || [];
return listIssueIds.map(id => getters.getIssueById(id));
},
- getActiveIssue: state => {
+ activeIssue: state => {
return state.issues[state.activeId] || {};
},
+ projectPathForActiveIssue: (_, getters) => {
+ const referencePath = getters.activeIssue.referencePath || '';
+ return referencePath.slice(0, referencePath.indexOf('#'));
+ },
+
getListByLabelId: state => labelId => {
return find(state.boardLists, l => l.label?.id === labelId);
},
diff --git a/app/assets/javascripts/boards/stores/mutation_types.js b/app/assets/javascripts/boards/stores/mutation_types.js
index 09ab08062df..3a57cb9b5e1 100644
--- a/app/assets/javascripts/boards/stores/mutation_types.js
+++ b/app/assets/javascripts/boards/stores/mutation_types.js
@@ -2,6 +2,8 @@ export const SET_INITIAL_BOARD_DATA = 'SET_INITIAL_BOARD_DATA';
export const SET_FILTERS = 'SET_FILTERS';
export const CREATE_LIST_SUCCESS = 'CREATE_LIST_SUCCESS';
export const CREATE_LIST_FAILURE = 'CREATE_LIST_FAILURE';
+export const RECEIVE_LABELS_FAILURE = 'RECEIVE_LABELS_FAILURE';
+export const GENERATE_DEFAULT_LISTS_FAILURE = 'GENERATE_DEFAULT_LISTS_FAILURE';
export const RECEIVE_BOARD_LISTS_SUCCESS = 'RECEIVE_BOARD_LISTS_SUCCESS';
export const RECEIVE_BOARD_LISTS_FAILURE = 'RECEIVE_BOARD_LISTS_FAILURE';
export const SHOW_PROMOTION_LIST = 'SHOW_PROMOTION_LIST';
@@ -10,12 +12,12 @@ export const RECEIVE_ADD_LIST_SUCCESS = 'RECEIVE_ADD_LIST_SUCCESS';
export const RECEIVE_ADD_LIST_ERROR = 'RECEIVE_ADD_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 REMOVE_LIST = 'REMOVE_LIST';
+export const REMOVE_LIST_FAILURE = 'REMOVE_LIST_FAILURE';
export const REQUEST_ISSUES_FOR_LIST = 'REQUEST_ISSUES_FOR_LIST';
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 CREATE_ISSUE_FAILURE = 'CREATE_ISSUE_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';
@@ -27,6 +29,7 @@ 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 REMOVE_ISSUE_FROM_LIST = 'REMOVE_ISSUE_FROM_LIST';
export const SET_CURRENT_PAGE = 'SET_CURRENT_PAGE';
export const TOGGLE_EMPTY_STATE = 'TOGGLE_EMPTY_STATE';
export const SET_ACTIVE_ID = 'SET_ACTIVE_ID';
diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js
index 0c7dbc0d2ef..bb083158c8f 100644
--- a/app/assets/javascripts/boards/stores/mutations.js
+++ b/app/assets/javascripts/boards/stores/mutations.js
@@ -62,6 +62,14 @@ export default {
state.error = s__('Boards|An error occurred while creating the list. Please try again.');
},
+ [mutationTypes.RECEIVE_LABELS_FAILURE]: state => {
+ state.error = s__('Boards|An error occurred while fetching labels. Please reload the page.');
+ },
+
+ [mutationTypes.GENERATE_DEFAULT_LISTS_FAILURE]: state => {
+ state.error = s__('Boards|An error occurred while generating lists. Please reload the page.');
+ },
+
[mutationTypes.REQUEST_ADD_LIST]: () => {
notImplemented();
},
@@ -85,16 +93,13 @@ export default {
Vue.set(state, 'boardLists', backupList);
},
- [mutationTypes.REQUEST_REMOVE_LIST]: () => {
- notImplemented();
+ [mutationTypes.REMOVE_LIST]: (state, listId) => {
+ Vue.delete(state.boardLists, listId);
},
- [mutationTypes.RECEIVE_REMOVE_LIST_SUCCESS]: () => {
- notImplemented();
- },
-
- [mutationTypes.RECEIVE_REMOVE_LIST_ERROR]: () => {
- notImplemented();
+ [mutationTypes.REMOVE_LIST_FAILURE](state, listsBackup) {
+ state.error = s__('Boards|An error occurred while removing the list. Please try again.');
+ state.boardLists = listsBackup;
},
[mutationTypes.REQUEST_ISSUES_FOR_LIST]: (state, { listId, fetchNext }) => {
@@ -196,16 +201,28 @@ export default {
notImplemented();
},
+ [mutationTypes.CREATE_ISSUE_FAILURE]: state => {
+ state.error = s__('Boards|An error occurred while creating the issue. Please try again.');
+ },
+
[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);
+ addIssueToList({
+ state,
+ listId: list.id,
+ issueId: issue.id,
+ atIndex: position,
+ });
Vue.set(state.issues, issue.id, issue);
},
- [mutationTypes.ADD_ISSUE_TO_LIST_FAILURE]: (state, { list, issue }) => {
+ [mutationTypes.ADD_ISSUE_TO_LIST_FAILURE]: (state, { list, issueId }) => {
state.error = s__('Boards|An error occurred while creating the issue. Please try again.');
+ removeIssueFromList({ state, listId: list.id, issueId });
+ },
+
+ [mutationTypes.REMOVE_ISSUE_FROM_LIST]: (state, { list, issue }) => {
removeIssueFromList({ state, listId: list.id, issueId: issue.id });
+ Vue.delete(state.issues, issue.id);
},
[mutationTypes.SET_CURRENT_PAGE]: () => {
diff --git a/app/assets/javascripts/boards/toggle_focus.js b/app/assets/javascripts/boards/toggle_focus.js
index fa13d3a9e3c..347deb81846 100644
--- a/app/assets/javascripts/boards/toggle_focus.js
+++ b/app/assets/javascripts/boards/toggle_focus.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import Vue from 'vue';
import { GlIcon } from '@gitlab/ui';
+import { hide } from '~/tooltips';
export default (ModalStore, boardsStore) => {
const issueBoardsContent = document.querySelector('.content-wrapper > .js-focus-mode-board');
@@ -17,7 +18,9 @@ export default (ModalStore, boardsStore) => {
},
methods: {
toggleFocusMode() {
- $(this.$refs.toggleFocusModeButton).tooltip('hide');
+ const $el = $(this.$refs.toggleFocusModeButton);
+ hide($el);
+
issueBoardsContent.classList.toggle('is-focused');
this.isFullscreen = !this.isFullscreen;
diff --git a/app/assets/javascripts/ci_lint/components/ci_lint.vue b/app/assets/javascripts/ci_lint/components/ci_lint.vue
index 2532f4b86d2..def45026b35 100644
--- a/app/assets/javascripts/ci_lint/components/ci_lint.vue
+++ b/app/assets/javascripts/ci_lint/components/ci_lint.vue
@@ -19,7 +19,11 @@ export default {
type: String,
required: true,
},
- helpPagePath: {
+ lintHelpPagePath: {
+ type: String,
+ required: true,
+ },
+ pipelineSimulationHelpPagePath: {
type: String,
required: true,
},
@@ -27,6 +31,7 @@ export default {
data() {
return {
content: '',
+ loading: false,
valid: false,
errors: null,
warnings: null,
@@ -44,6 +49,7 @@ export default {
},
methods: {
async lint() {
+ this.loading = true;
try {
const {
data: {
@@ -62,6 +68,8 @@ export default {
} catch (error) {
this.apiError = error;
this.isErrorDismissed = false;
+ } finally {
+ this.loading = false;
}
},
clear() {
@@ -93,6 +101,7 @@ export default {
<div class="gl-display-flex gl-align-items-center">
<gl-button
class="gl-mr-4"
+ :loading="loading"
category="primary"
variant="success"
data-testid="ci-lint-validate"
@@ -101,7 +110,7 @@ export default {
>
<gl-form-checkbox v-model="dryRun"
>{{ __('Simulate a pipeline created for the default branch') }}
- <gl-link :href="helpPagePath" target="_blank"
+ <gl-link :href="pipelineSimulationHelpPagePath" target="_blank"
><gl-icon class="gl-text-blue-600" name="question-o"/></gl-link
></gl-form-checkbox>
</div>
@@ -115,6 +124,7 @@ export default {
:errors="errors"
:warnings="warnings"
:dry-run="dryRun"
+ :lint-help-page-path="lintHelpPagePath"
/>
</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
index 28b2a028b29..8b37c94de19 100644
--- a/app/assets/javascripts/ci_lint/components/ci_lint_results.vue
+++ b/app/assets/javascripts/ci_lint/components/ci_lint_results.vue
@@ -1,5 +1,5 @@
<script>
-import { GlAlert, GlTable } from '@gitlab/ui';
+import { GlAlert, GlLink, GlSprintf, GlTable } from '@gitlab/ui';
import CiLintWarnings from './ci_lint_warnings.vue';
import CiLintResultsValue from './ci_lint_results_value.vue';
import CiLintResultsParam from './ci_lint_results_param.vue';
@@ -8,8 +8,17 @@ import { __ } from '~/locale';
const thBorderColor = 'gl-border-gray-100!';
export default {
- correct: { variant: 'success', text: __('syntax is correct') },
- incorrect: { variant: 'danger', text: __('syntax is incorrect') },
+ correct: {
+ variant: 'success',
+ text: __('syntax is correct.'),
+ },
+ incorrect: {
+ variant: 'danger',
+ text: __('syntax is incorrect.'),
+ },
+ includesText: __(
+ 'CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}',
+ ),
warningTitle: __('The form contains the following warning:'),
fields: [
{
@@ -25,6 +34,8 @@ export default {
],
components: {
GlAlert,
+ GlLink,
+ GlSprintf,
GlTable,
CiLintWarnings,
CiLintResultsValue,
@@ -51,6 +62,10 @@ export default {
type: Boolean,
required: true,
},
+ lintHelpPagePath: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
@@ -82,8 +97,20 @@ export default {
:title="__('Status:')"
:dismissible="false"
data-testid="ci-lint-status"
- >{{ status.text }}</gl-alert
- >
+ >{{ status.text }}
+ <gl-sprintf :message="$options.includesText">
+ <template #code="{content}">
+ <code>
+ {{ content }}
+ </code>
+ </template>
+ <template #link>
+ <gl-link :href="lintHelpPagePath" target="_blank">
+ {{ __('More information') }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
<pre
v-if="shouldShowError"
diff --git a/app/assets/javascripts/ci_lint/graphql/resolvers.js b/app/assets/javascripts/ci_lint/graphql/resolvers.js
new file mode 100644
index 00000000000..126b4c664b2
--- /dev/null
+++ b/app/assets/javascripts/ci_lint/graphql/resolvers.js
@@ -0,0 +1,34 @@
+import axios from '~/lib/utils/axios_utils';
+
+const resolvers = {
+ Mutation: {
+ lintCI: (_, { endpoint, content, dry_run }) => {
+ return axios.post(endpoint, { content, dry_run }).then(({ data }) => ({
+ valid: data.valid,
+ errors: data.errors,
+ warnings: data.warnings,
+ jobs: data.jobs.map(job => {
+ const only = job.only ? { refs: job.only.refs, __typename: 'CiLintJobOnlyPolicy' } : null;
+
+ return {
+ name: job.name,
+ stage: job.stage,
+ beforeScript: job.before_script,
+ script: job.script,
+ afterScript: job.after_script,
+ tagList: job.tag_list,
+ environment: job.environment,
+ when: job.when,
+ allowFailure: job.allow_failure,
+ only,
+ except: job.except,
+ __typename: 'CiLintJob',
+ };
+ }),
+ __typename: 'CiLintContent',
+ }));
+ },
+ },
+};
+
+export default resolvers;
diff --git a/app/assets/javascripts/ci_lint/index.js b/app/assets/javascripts/ci_lint/index.js
index c41e6d47d75..e4cda4cb369 100644
--- a/app/assets/javascripts/ci_lint/index.js
+++ b/app/assets/javascripts/ci_lint/index.js
@@ -1,48 +1,18 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import axios from '~/lib/utils/axios_utils';
import createDefaultClient from '~/lib/graphql';
import CiLint from './components/ci_lint.vue';
+import resolvers from './graphql/resolvers';
Vue.use(VueApollo);
-const resolvers = {
- Mutation: {
- lintCI: (_, { endpoint, content, dry_run }) => {
- return axios.post(endpoint, { content, dry_run }).then(({ data }) => ({
- valid: data.valid,
- errors: data.errors,
- warnings: data.warnings,
- jobs: data.jobs.map(job => ({
- name: job.name,
- stage: job.stage,
- beforeScript: job.before_script,
- script: job.script,
- afterScript: job.after_script,
- tagList: job.tag_list,
- environment: job.environment,
- when: job.when,
- allowFailure: job.allow_failure,
- only: {
- refs: job.only.refs,
- __typename: 'CiLintJobOnlyPolicy',
- },
- except: job.except,
- __typename: 'CiLintJob',
- })),
- __typename: 'CiLintContent',
- }));
- },
- },
-};
-
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(resolvers),
});
export default (containerId = '#js-ci-lint') => {
const containerEl = document.querySelector(containerId);
- const { endpoint, helpPagePath } = containerEl.dataset;
+ const { endpoint, lintHelpPagePath, pipelineSimulationHelpPagePath } = containerEl.dataset;
return new Vue({
el: containerEl,
@@ -51,7 +21,8 @@ export default (containerId = '#js-ci-lint') => {
return createElement(CiLint, {
props: {
endpoint,
- helpPagePath,
+ lintHelpPagePath,
+ pipelineSimulationHelpPagePath,
},
});
},
diff --git a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js
deleted file mode 100644
index b8bf363fc9d..00000000000
--- a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js
+++ /dev/null
@@ -1,128 +0,0 @@
-import { escape } from 'lodash';
-import axios from '../lib/utils/axios_utils';
-import { s__ } from '../locale';
-import { deprecatedCreateFlash as Flash } from '../flash';
-import { parseBoolean } from '../lib/utils/common_utils';
-import statusCodes from '../lib/utils/http_status';
-import VariableList from './ci_variable_list';
-
-function generateErrorBoxContent(errors) {
- const errorList = [].concat(errors).map(
- errorString => `
- <li>
- ${escape(errorString)}
- </li>
- `,
- );
-
- return `
- <p>
- ${s__('CiVariable|Validation failed')}
- </p>
- <ul>
- ${errorList.join('')}
- </ul>
- `;
-}
-
-// Used for the variable list on CI/CD projects/groups settings page
-export default class AjaxVariableList {
- constructor({
- container,
- saveButton,
- errorBox,
- formField = 'variables',
- saveEndpoint,
- maskableRegex,
- }) {
- this.container = container;
- this.saveButton = saveButton;
- this.errorBox = errorBox;
- this.saveEndpoint = saveEndpoint;
- this.maskableRegex = maskableRegex;
-
- this.variableList = new VariableList({
- container: this.container,
- formField,
- maskableRegex,
- });
-
- this.bindEvents();
- this.variableList.init();
- }
-
- bindEvents() {
- this.saveButton.addEventListener('click', this.onSaveClicked.bind(this));
- }
-
- onSaveClicked() {
- const loadingIcon = this.saveButton.querySelector('.js-ci-variables-save-loading-icon');
- loadingIcon.classList.toggle('hide', false);
- this.errorBox.classList.toggle('hide', true);
- // We use this to prevent a user from changing a key before we have a chance
- // to match it up in `updateRowsWithPersistedVariables`
- this.variableList.toggleEnableRow(false);
-
- return axios
- .patch(
- this.saveEndpoint,
- {
- variables_attributes: this.variableList.getAllData(),
- },
- {
- // We want to be able to process the `res.data` from a 400 error response
- // and print the validation messages such as duplicate variable keys
- validateStatus: status =>
- (status >= statusCodes.OK && status < statusCodes.MULTIPLE_CHOICES) ||
- status === statusCodes.BAD_REQUEST,
- },
- )
- .then(res => {
- loadingIcon.classList.toggle('hide', true);
- this.variableList.toggleEnableRow(true);
-
- if (res.status === statusCodes.OK && res.data) {
- this.updateRowsWithPersistedVariables(res.data.variables);
- this.variableList.hideValues();
- } else if (res.status === statusCodes.BAD_REQUEST) {
- // Validation failed
- this.errorBox.innerHTML = generateErrorBoxContent(res.data);
- this.errorBox.classList.toggle('hide', false);
- }
- })
- .catch(() => {
- loadingIcon.classList.toggle('hide', true);
- this.variableList.toggleEnableRow(true);
- Flash(s__('CiVariable|Error occurred while saving variables'));
- });
- }
-
- updateRowsWithPersistedVariables(persistedVariables = []) {
- const persistedVariableMap = [].concat(persistedVariables).reduce(
- (variableMap, variable) => ({
- ...variableMap,
- [variable.key]: variable,
- }),
- {},
- );
-
- this.container.querySelectorAll('.js-row').forEach(row => {
- // If we submitted a row that was destroyed, remove it so we don't try
- // to destroy it again which would cause a BE error
- const destroyInput = row.querySelector('.js-ci-variable-input-destroy');
- if (parseBoolean(destroyInput.value)) {
- row.remove();
- // Update the ID input so any future edits and `_destroy` will apply on the BE
- } else {
- const key = row.querySelector('.js-ci-variable-input-key').value;
- const persistedVariable = persistedVariableMap[key];
-
- if (persistedVariable) {
- // eslint-disable-next-line no-param-reassign
- row.querySelector('.js-ci-variable-input-id').value = persistedVariable.id;
- row.setAttribute('data-is-persisted', 'true');
- }
- }
- });
- }
-}
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 ceb94b1f0f8..83e9717041f 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
@@ -60,7 +60,7 @@ export default {
</script>
<template>
<gl-dropdown :text="value">
- <gl-search-box-by-type v-model.trim="searchTerm" />
+ <gl-search-box-by-type v-model.trim="searchTerm" data-testid="ci-environment-search" />
<gl-dropdown-item
v-for="environment in filteredResults"
:key="environment"
@@ -75,7 +75,7 @@ export default {
}}</gl-dropdown-item>
<template v-if="shouldRenderCreateButton">
<gl-dropdown-divider />
- <gl-dropdown-item @click="createClicked">
+ <gl-dropdown-item data-testid="create-wildcard-button" @click="createClicked">
{{ composedCreateButtonLabel }}
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue
index a2f4bea2f61..da816f85466 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue
@@ -236,6 +236,7 @@ export default {
:label="__('Environment scope')"
label-for="ci-variable-env"
class="w-50"
+ data-testid="environment-scope"
>
<ci-environments-dropdown
class="w-100"
@@ -247,7 +248,11 @@ export default {
</div>
<gl-form-group :label="__('Flags')" label-for="ci-variable-flags">
- <gl-form-checkbox v-model="protected_variable" class="mb-0">
+ <gl-form-checkbox
+ v-model="protected_variable"
+ class="mb-0"
+ data-testid="ci-variable-protected-checkbox"
+ >
{{ __('Protect variable') }}
<gl-link target="_blank" :href="protectedEnvironmentVariablesLink">
<gl-icon name="question" :size="12" />
@@ -261,6 +266,7 @@ export default {
ref="masked-ci-variable"
v-model="masked"
data-qa-selector="ci_variable_masked_checkbox"
+ data-testid="ci-variable-masked-checkbox"
>
{{ __('Mask variable') }}
<gl-link target="_blank" :href="maskedEnvironmentVariablesLink">
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue
index 412260da958..471c1a0b4a2 100644
--- a/app/assets/javascripts/clusters/components/application_row.vue
+++ b/app/assets/javascripts/clusters/components/application_row.vue
@@ -343,7 +343,7 @@ export default {
>
<span v-else class="js-cluster-application-title">{{ title }}</span>
</strong>
- <slot name="installedVia"></slot>
+ <slot name="installed-via"></slot>
<div>
<slot name="description"></slot>
</div>
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index b03cf6fc31b..271d862afab 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -467,6 +467,17 @@ export default {
notebooks to a class of students, a corporate data science group,
or a scientific research group.`)
}}
+ <gl-sprintf
+ :message="
+ s__(
+ 'ClusterIntegration|%{boldStart}Note:%{boldEnd} Requires Ingress to be installed.',
+ )
+ "
+ >
+ <template #bold="{ content }">
+ <b>{{ content }}</b>
+ </template>
+ </gl-sprintf>
</p>
<template v-if="ingressExternalEndpoint">
@@ -549,8 +560,8 @@ export default {
@set="setKnativeDomain"
/>
</template>
- <template v-if="cloudRun" #installedVia>
- <span data-testid="installedVia">
+ <template v-if="cloudRun" #installed-via>
+ <span data-testid="installed-via">
<gl-sprintf
:message="s__('ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}')"
>
diff --git a/app/assets/javascripts/clusters_list/components/clusters.vue b/app/assets/javascripts/clusters_list/components/clusters.vue
index f8fb58cdca2..08fd7db40a1 100644
--- a/app/assets/javascripts/clusters_list/components/clusters.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters.vue
@@ -1,17 +1,17 @@
<script>
import { mapState, mapActions } from 'vuex';
import {
- GlDeprecatedBadge as GlBadge,
+ GlBadge,
GlLink,
GlLoadingIcon,
GlPagination,
GlDeprecatedSkeletonLoading as GlSkeletonLoading,
GlSprintf,
GlTable,
+ GlTooltipDirective,
} from '@gitlab/ui';
import AncestorNotice from './ancestor_notice.vue';
import NodeErrorHelpText from './node_error_help_text.vue';
-import tooltip from '~/vue_shared/directives/tooltip';
import { CLUSTER_TYPES, STATUSES } from '../constants';
import { __, sprintf } from '~/locale';
@@ -30,7 +30,7 @@ export default {
NodeErrorHelpText,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
computed: {
...mapState([
@@ -227,7 +227,7 @@ export default {
<gl-loading-icon
v-if="item.status === 'deleting' || item.status === 'creating'"
- v-tooltip
+ v-gl-tooltip
:title="statusTitle(item.status)"
size="sm"
/>
@@ -294,7 +294,7 @@ export default {
</template>
<template #cell(cluster_type)="{value}">
- <gl-badge variant="light">
+ <gl-badge variant="muted">
{{ value }}
</gl-badge>
</template>
diff --git a/app/assets/javascripts/compare_autocomplete.js b/app/assets/javascripts/compare_autocomplete.js
index 45ac1bafd61..1c1f0664885 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 { fixTitle } from '~/tooltips';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default function initCompareAutocomplete(limitTo = null, clickHandler = () => {}) {
@@ -76,7 +77,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = (
$dropdownContainer.on('click', '.dropdown-content a', e => {
$dropdown.prop('title', e.target.text.replace(/_+?/g, '-'));
if ($dropdown.hasClass('has-tooltip')) {
- $dropdown.tooltip('_fixTitle');
+ fixTitle($dropdown);
}
});
});
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 d403f370f9d..2858561e033 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,15 +1,12 @@
<script>
import { createNamespacedHelpers, mapState, mapActions, mapGetters } from 'vuex';
-import { GlFormInput, GlFormCheckbox, GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
+import { GlFormGroup, GlFormInput, GlFormCheckbox, GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
import ClusterFormDropdown from '~/create_cluster/components/cluster_form_dropdown.vue';
import { KUBERNETES_VERSIONS } from '../constants';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
const { mapState: mapRolesState, mapActions: mapRolesActions } = createNamespacedHelpers('roles');
-const { mapState: mapRegionsState, mapActions: mapRegionsActions } = createNamespacedHelpers(
- 'regions',
-);
const { mapState: mapKeyPairsState, mapActions: mapKeyPairsActions } = createNamespacedHelpers(
'keyPairs',
);
@@ -27,6 +24,7 @@ export default {
components: {
ClusterFormDropdown,
GlFormCheckbox,
+ GlFormGroup,
GlFormInput,
GlIcon,
GlLink,
@@ -60,11 +58,10 @@ export default {
),
roleDropdownHelpPath:
'https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html#create-service-role',
- regionsDropdownHelpText: s__(
- 'ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}.',
+ regionInputLabel: s__('ClusterIntegration|Cluster Region'),
+ regionHelpText: s__(
+ 'ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions.',
),
- regionsDropdownHelpPath:
- 'https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/',
keyPairDropdownHelpText: s__(
'ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}.',
),
@@ -117,11 +114,6 @@ export default {
isLoadingRoles: 'isLoadingItems',
loadingRolesError: 'loadingItemsError',
}),
- ...mapRegionsState({
- regions: 'items',
- isLoadingRegions: 'isLoadingItems',
- loadingRegionsError: 'loadingItemsError',
- }),
...mapKeyPairsState({
keyPairs: 'items',
isLoadingKeyPairs: 'isLoadingItems',
@@ -195,8 +187,8 @@ export default {
},
},
mounted() {
- this.fetchRegions();
this.fetchRoles();
+ this.setRegionAndFetchVpcsAndKeyPairs();
},
methods: {
...mapActions([
@@ -215,20 +207,18 @@ export default {
'setGitlabManagedCluster',
'setNamespacePerEnvironment',
]),
- ...mapRegionsActions({ fetchRegions: 'fetchItems' }),
...mapVpcActions({ fetchVpcs: 'fetchItems' }),
...mapSubnetActions({ fetchSubnets: 'fetchItems' }),
...mapRolesActions({ fetchRoles: 'fetchItems' }),
...mapKeyPairsActions({ fetchKeyPairs: 'fetchItems' }),
...mapSecurityGroupsActions({ fetchSecurityGroups: 'fetchItems' }),
- setRegionAndFetchVpcsAndKeyPairs(region) {
- this.setRegion({ region });
+ setRegionAndFetchVpcsAndKeyPairs() {
this.setVpc({ vpc: null });
this.setKeyPair({ keyPair: null });
this.setSubnet({ subnet: [] });
this.setSecurityGroup({ securityGroup: null });
- this.fetchVpcs({ region });
- this.fetchKeyPairs({ region });
+ this.fetchVpcs({ region: this.selectedRegion });
+ this.fetchKeyPairs({ region: this.selectedRegion });
},
setVpcAndFetchSubnets(vpc) {
this.setVpc({ vpc });
@@ -314,33 +304,12 @@ export default {
</gl-sprintf>
</p>
</div>
- <div class="form-group">
- <label class="label-bold" for="eks-role">{{ s__('ClusterIntegration|Region') }}</label>
- <cluster-form-dropdown
- field-id="eks-region"
- field-name="eks-region"
- :value="selectedRegion"
- :items="regions"
- :loading="isLoadingRegions"
- :loading-text="s__('ClusterIntegration|Loading Regions')"
- :placeholder="s__('ClusterIntergation|Select a region')"
- :search-field-placeholder="s__('ClusterIntegration|Search regions')"
- :empty-text="s__('ClusterIntegration|No region found')"
- :has-errors="Boolean(loadingRegionsError)"
- :error-message="s__('ClusterIntegration|Could not load regions from your AWS account')"
- @input="setRegionAndFetchVpcsAndKeyPairs($event)"
- />
- <p class="form-text text-muted">
- <gl-sprintf :message="$options.i18n.regionsDropdownHelpText">
- <template #link="{ content }">
- <gl-link :href="$options.i18n.regionsDropdownHelpPath" target="_blank">
- {{ content }}
- <gl-icon name="external-link" class="gl-vertical-align-middle" />
- </gl-link>
- </template>
- </gl-sprintf>
- </p>
- </div>
+ <gl-form-group
+ :label="$options.i18n.regionInputLabel"
+ :description="$options.i18n.regionHelpText"
+ >
+ <gl-form-input id="eks-region" :value="selectedRegion" type="text" readonly />
+ </gl-form-group>
<div class="form-group">
<label class="label-bold" for="eks-key-pair">{{
s__('ClusterIntegration|Key pair name')
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 5c13cbb2775..a3f76241bf2 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,20 @@
<script>
/* eslint-disable vue/no-v-html */
-import { GlFormInput, GlButton } from '@gitlab/ui';
+import { GlButton, GlFormGroup, GlFormInput, GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
import { escape } from 'lodash';
import { mapState, mapActions } from 'vuex';
+import { DEFAULT_REGION } from '../constants';
import { sprintf, s__, __ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
export default {
components: {
- GlFormInput,
GlButton,
+ GlFormGroup,
+ GlFormInput,
+ GlIcon,
+ GlLink,
+ GlSprintf,
ClipboardButton,
},
props: {
@@ -26,9 +31,18 @@ export default {
required: true,
},
},
+ i18n: {
+ regionInputLabel: s__('ClusterIntegration|Cluster Region'),
+ regionHelpPath: 'https://aws.amazon.com/about-aws/global-infrastructure/regions_az/',
+ regionHelpText: s__(
+ 'ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}.',
+ ),
+ regionHelpTextDefaultRegion: DEFAULT_REGION,
+ },
data() {
return {
roleArn: this.$store.state.roleArn,
+ selectedRegion: this.$store.state.selectedRegion,
};
},
computed: {
@@ -130,13 +144,33 @@ export default {
<gl-form-input id="eks-provision-role-arn" v-model="roleArn" />
<p class="form-text text-muted" v-html="provisionRoleArnHelpText"></p>
</div>
+
+ <gl-form-group :label="$options.i18n.regionInputLabel">
+ <gl-form-input id="eks-region" v-model="selectedRegion" type="text" />
+
+ <template #description>
+ <gl-sprintf :message="$options.i18n.regionHelpText">
+ <template #code>
+ <code>{{ $options.i18n.regionHelpTextDefaultRegion }}</code>
+ </template>
+
+ <template #link="{ content }">
+ <gl-link :href="$options.i18n.regionHelpPath" target="_blank">
+ {{ content }}
+ <gl-icon name="external-link" />
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </template>
+ </gl-form-group>
+
<gl-button
variant="success"
category="primary"
type="submit"
:disabled="submitButtonDisabled"
:loading="isCreatingRole"
- @click.prevent="createRole({ roleArn, externalId })"
+ @click.prevent="createRole({ roleArn, selectedRegion, externalId })"
>
{{ submitButtonLabel }}
</gl-button>
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/constants.js b/app/assets/javascripts/create_cluster/eks_cluster/constants.js
index 471d6e1f0aa..0f0db2090c1 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/constants.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/constants.js
@@ -1,3 +1,5 @@
+export const DEFAULT_REGION = 'us-east-2';
+
export const KUBERNETES_VERSIONS = [
{ name: '1.14', value: '1.14' },
{ name: '1.15', value: '1.15' },
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/services/aws_services_facade.js b/app/assets/javascripts/create_cluster/eks_cluster/services/aws_services_facade.js
index 601ff6f9adc..58568b5dedb 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/services/aws_services_facade.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/services/aws_services_facade.js
@@ -8,13 +8,8 @@ const lookupVpcName = ({ Tags: tags, VpcId: id }) => {
return nameTag ? nameTag.Value : id;
};
-export const DEFAULT_REGION = 'us-east-2';
-
export const setAWSConfig = ({ awsCredentials }) => {
- AWS.config = {
- ...awsCredentials,
- region: DEFAULT_REGION,
- };
+ AWS.config = awsCredentials;
};
export const fetchRoles = () => {
@@ -26,20 +21,6 @@ export const fetchRoles = () => {
.then(({ Roles: roles }) => roles.map(({ RoleName: name, Arn: value }) => ({ name, value })));
};
-export const fetchRegions = () => {
- const ec2 = new EC2();
-
- return ec2
- .describeRegions()
- .promise()
- .then(({ Regions: regions }) =>
- regions.map(({ RegionName: name }) => ({
- name,
- value: name,
- })),
- );
-};
-
export const fetchKeyPairs = ({ region }) => {
const ec2 = new EC2({ region });
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 48c85ff627f..f3950a3343a 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js
@@ -1,4 +1,5 @@
import * as types from './mutation_types';
+import { DEFAULT_REGION } from '../constants';
import { setAWSConfig } from '../services/aws_services_facade';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
@@ -25,12 +26,22 @@ export const setKubernetesVersion = ({ commit }, payload) => {
export const createRole = ({ dispatch, state: { createRolePath } }, payload) => {
dispatch('requestCreateRole');
+ const region = payload.selectedRegion || DEFAULT_REGION;
+
return axios
.post(createRolePath, {
role_arn: payload.roleArn,
role_external_id: payload.externalId,
+ region,
+ })
+ .then(({ data }) => {
+ const awsData = {
+ ...convertObjectPropsToCamelCase(data),
+ region,
+ };
+
+ dispatch('createRoleSuccess', awsData);
})
- .then(({ data }) => dispatch('createRoleSuccess', convertObjectPropsToCamelCase(data)))
.catch(error => dispatch('createRoleError', { error }));
};
@@ -38,7 +49,8 @@ export const requestCreateRole = ({ commit }) => {
commit(types.REQUEST_CREATE_ROLE);
};
-export const createRoleSuccess = ({ commit }, awsCredentials) => {
+export const createRoleSuccess = ({ dispatch, commit }, awsCredentials) => {
+ dispatch('setRegion', { region: awsCredentials.region });
setAWSConfig({ awsCredentials });
commit(types.CREATE_ROLE_SUCCESS);
};
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/index.js b/app/assets/javascripts/create_cluster/eks_cluster/store/index.js
index 8dc55506dc2..262bbb3167a 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/store/index.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/store/index.js
@@ -8,7 +8,6 @@ import clusterDropdownStore from '~/create_cluster/store/cluster_dropdown';
import {
fetchRoles,
- fetchRegions,
fetchKeyPairs,
fetchVpcs,
fetchSubnets,
@@ -26,10 +25,6 @@ const createStore = ({ initialState }) =>
namespaced: true,
...clusterDropdownStore({ fetchFn: fetchRoles }),
},
- regions: {
- namespaced: true,
- ...clusterDropdownStore({ fetchFn: fetchRegions }),
- },
keyPairs: {
namespaced: true,
...clusterDropdownStore({ fetchFn: fetchKeyPairs }),
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue
index 979628d683d..85d9f0d66ab 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue
+++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue
@@ -1,6 +1,6 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
-import { GlSprintf, GlLink } from '@gitlab/ui';
+import { GlSprintf, GlLink, GlIcon } from '@gitlab/ui';
import { s__ } from '~/locale';
import gkeDropdownMixin from './gke_dropdown_mixin';
@@ -10,6 +10,7 @@ export default {
components: {
GlSprintf,
GlLink,
+ GlIcon,
},
mixins: [gkeDropdownMixin],
props: {
@@ -178,14 +179,14 @@ export default {
'https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral'
"
target="_blank"
- >{{ content }} <i class="fa fa-external-link" aria-hidden="true"></i
- ></gl-link>
+ >{{ content }} <gl-icon name="external-link" aria-hidden="true"
+ /></gl-link>
</template>
<template #docsLink="{ content }">
<gl-link :href="docsUrl" target="_blank"
- >{{ content }} <i class="fa fa-external-link" aria-hidden="true"></i
- ></gl-link>
+ >{{ content }} <gl-icon name="external-link" aria-hidden="true"
+ /></gl-link>
</template>
<template #error>
diff --git a/app/assets/javascripts/create_merge_request_dropdown.js b/app/assets/javascripts/create_merge_request_dropdown.js
index 010a6b073f9..49091f5f140 100644
--- a/app/assets/javascripts/create_merge_request_dropdown.js
+++ b/app/assets/javascripts/create_merge_request_dropdown.js
@@ -168,9 +168,6 @@ export default class CreateMergeRequestDropdown {
disable() {
this.disableCreateAction();
-
- this.dropdownToggle.classList.add('disabled');
- this.dropdownToggle.setAttribute('disabled', 'disabled');
}
disableCreateAction() {
@@ -189,9 +186,6 @@ export default class CreateMergeRequestDropdown {
this.createTargetButton.classList.remove('disabled');
this.createTargetButton.removeAttribute('disabled');
-
- this.dropdownToggle.classList.remove('disabled');
- this.dropdownToggle.removeAttribute('disabled');
}
static findByValue(objects, ref, returnFirstMatch = false) {
diff --git a/app/assets/javascripts/dependency_proxy.js b/app/assets/javascripts/dependency_proxy.js
new file mode 100644
index 00000000000..ddf5703b28f
--- /dev/null
+++ b/app/assets/javascripts/dependency_proxy.js
@@ -0,0 +1,5 @@
+import setupToggleButtons from '~/toggle_buttons';
+
+export default () => {
+ setupToggleButtons(document.querySelector('.js-dependency-proxy-toggle-area'));
+};
diff --git a/app/assets/javascripts/deploy_keys/components/key.vue b/app/assets/javascripts/deploy_keys/components/key.vue
index 5b41d23bd27..16eee094108 100644
--- a/app/assets/javascripts/deploy_keys/components/key.vue
+++ b/app/assets/javascripts/deploy_keys/components/key.vue
@@ -1,8 +1,7 @@
<script>
import { head, tail } from 'lodash';
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
-import tooltip from '~/vue_shared/directives/tooltip';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import actionBtn from './action_btn.vue';
@@ -13,7 +12,7 @@ export default {
GlIcon,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
mixins: [timeagoMixin],
props: {
@@ -125,7 +124,7 @@ export default {
<div class="table-mobile-content deploy-project-list">
<template v-if="projects.length > 0">
<a
- v-tooltip
+ v-gl-tooltip
:title="projectTooltipTitle(firstProject)"
class="label deploy-project-label"
>
@@ -134,7 +133,7 @@ export default {
</a>
<a
v-if="isExpandable"
- v-tooltip
+ v-gl-tooltip
:title="restProjectsTooltip"
class="label deploy-project-label"
@click="toggleExpanded"
@@ -145,7 +144,7 @@ export default {
v-for="deployKeysProject in restProjects"
v-else-if="isExpanded"
:key="deployKeysProject.project.full_path"
- v-tooltip
+ v-gl-tooltip
:href="deployKeysProject.project.full_path"
:title="projectTooltipTitle(deployKeysProject)"
class="label deploy-project-label"
@@ -160,7 +159,7 @@ export default {
<div class="table-section section-15 text-right">
<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)">
+ <span v-gl-tooltip :title="tooltipTitle(deployKey.created_at)">
<gl-icon name="calendar" /> <span>{{ timeFormatted(deployKey.created_at) }}</span>
</span>
</div>
@@ -172,7 +171,7 @@ export default {
</action-btn>
<a
v-if="deployKey.can_edit"
- v-tooltip
+ v-gl-tooltip
:href="editDeployKeyPath"
:title="__('Edit')"
class="btn btn-default text-secondary"
@@ -182,7 +181,7 @@ export default {
</a>
<action-btn
v-if="isRemovable"
- v-tooltip
+ v-gl-tooltip
:deploy-key="deployKey"
:title="__('Remove')"
btn-css-class="btn-danger"
@@ -193,7 +192,7 @@ export default {
</action-btn>
<action-btn
v-else-if="isEnabled"
- v-tooltip
+ v-gl-tooltip
:deploy-key="deployKey"
:title="__('Disable')"
btn-css-class="btn-warning"
diff --git a/app/assets/javascripts/design_management/components/design_destroyer.vue b/app/assets/javascripts/design_management/components/design_destroyer.vue
index 7ae569216f0..5d32bfd4a73 100644
--- a/app/assets/javascripts/design_management/components/design_destroyer.vue
+++ b/app/assets/javascripts/design_management/components/design_destroyer.vue
@@ -1,6 +1,6 @@
<script>
import { ApolloMutation } from 'vue-apollo';
-import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql';
+import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
import destroyDesignMutation from '../graphql/mutations/destroy_design.mutation.graphql';
import { updateStoreAfterDesignsDelete } from '../utils/cache_update';
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 845f1aec8cf..6aab4bf423e 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
@@ -210,7 +210,7 @@ export default {
:class="{ 'gl-bg-blue-50': isDiscussionActive }"
@error="$emit('update-note-error', $event)"
>
- <template v-if="discussion.resolvable" #resolveDiscussion>
+ <template v-if="discussion.resolvable" #resolve-discussion>
<button
v-gl-tooltip
:class="{ 'is-active': discussion.resolved }"
@@ -224,7 +224,7 @@ export default {
<gl-loading-icon v-else inline />
</button>
</template>
- <template v-if="discussion.resolved" #resolvedStatus>
+ <template v-if="discussion.resolved" #resolved-status>
<p class="gl-text-gray-500 gl-font-sm gl-m-0 gl-mt-5" data-testid="resolved-message">
{{ __('Resolved by') }}
<gl-link
@@ -277,7 +277,7 @@ export default {
@submit-form="mutate"
@cancel-form="hideForm"
>
- <template v-if="discussion.resolvable" #resolveCheckbox>
+ <template v-if="discussion.resolvable" #resolve-checkbox>
<label data-testid="resolve-checkbox">
<input v-model="shouldChangeResolvedStatus" type="checkbox" />
{{ resolveCheckboxText }}
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 7f4b3b31024..421a4dc274a 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
@@ -108,7 +108,7 @@ export default {
</span>
</div>
<div class="gl-display-flex gl-align-items-baseline">
- <slot name="resolveDiscussion"></slot>
+ <slot name="resolve-discussion"></slot>
<button
v-if="isEditButtonVisible"
v-gl-tooltip
@@ -127,7 +127,7 @@ export default {
class="note-text js-note-text md"
data-qa-selector="note_content"
></div>
- <slot name="resolvedStatus"></slot>
+ <slot name="resolved-status"></slot>
</template>
<apollo-mutation
v-else
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 3754e1dbbc1..7aaac58a1ce 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
@@ -110,7 +110,7 @@ export default {
</textarea>
</template>
</markdown-field>
- <slot name="resolveCheckbox"></slot>
+ <slot name="resolve-checkbox"></slot>
<div class="note-form-actions gl-display-flex gl-justify-content-space-between">
<gl-button
ref="submitButton"
diff --git a/app/assets/javascripts/design_management/components/design_overlay.vue b/app/assets/javascripts/design_management/components/design_overlay.vue
index 88f3ce0b8ea..3c2ce693bc0 100644
--- a/app/assets/javascripts/design_management/components/design_overlay.vue
+++ b/app/assets/javascripts/design_management/components/design_overlay.vue
@@ -112,9 +112,9 @@ export default {
},
canMoveNote(note) {
const { userPermissions } = note;
- const { adminNote } = userPermissions || {};
+ const { repositionNote } = userPermissions || {};
- return Boolean(adminNote);
+ return Boolean(repositionNote);
},
isPositionInOverlay(position) {
const { top, left } = this.getNoteRelativePosition(position);
diff --git a/app/assets/javascripts/design_management/components/design_scaler.vue b/app/assets/javascripts/design_management/components/design_scaler.vue
index 8d26f84641e..85c6bd4d79e 100644
--- a/app/assets/javascripts/design_management/components/design_scaler.vue
+++ b/app/assets/javascripts/design_management/components/design_scaler.vue
@@ -1,5 +1,5 @@
<script>
-import { GlIcon } from '@gitlab/ui';
+import { GlButtonGroup, GlButton } from '@gitlab/ui';
const SCALE_STEP_SIZE = 0.2;
const DEFAULT_SCALE = 1;
@@ -8,7 +8,8 @@ const MAX_SCALE = 2;
export default {
components: {
- GlIcon,
+ GlButtonGroup,
+ GlButton,
},
data() {
return {
@@ -49,17 +50,9 @@ export default {
</script>
<template>
- <div class="design-scaler btn-group" role="group">
- <button class="btn" :disabled="disableDecrease" @click="decrementScale">
- <span class="gl-display-flex gl-justify-content-center gl-align-items-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>
+ <gl-button-group class="gl-z-index-1">
+ <gl-button icon="dash" :disabled="disableDecrease" @click="decrementScale" />
+ <gl-button icon="redo" :disabled="disableReset" @click="resetScale" />
+ <gl-button icon="plus" :disabled="disableIncrease" @click="incrementScale" />
+ </gl-button-group>
</template>
diff --git a/app/assets/javascripts/design_management/components/design_sidebar.vue b/app/assets/javascripts/design_management/components/design_sidebar.vue
index fb8e74c8c4c..41dcec38abe 100644
--- a/app/assets/javascripts/design_management/components/design_sidebar.vue
+++ b/app/assets/javascripts/design_management/components/design_sidebar.vue
@@ -207,6 +207,6 @@ export default {
/>
</gl-collapse>
</template>
- <slot name="replyForm"></slot>
+ <slot name="reply-form"></slot>
</div>
</template>
diff --git a/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue b/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue
index 2719d701c12..4edc2e410c7 100644
--- a/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue
+++ b/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue
@@ -1,7 +1,7 @@
<script>
/* global Mousetrap */
import 'mousetrap';
-import { GlButton, GlButtonGroup } from '@gitlab/ui';
+import { GlButton, GlButtonGroup, GlTooltipDirective } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import allDesignsMixin from '../../mixins/all_designs';
import { DESIGN_ROUTE_NAME } from '../../router/constants';
@@ -11,6 +11,9 @@ export default {
GlButton,
GlButtonGroup,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
mixins: [allDesignsMixin],
props: {
id: {
@@ -68,6 +71,7 @@ export default {
{{ paginationText }}
<gl-button-group class="gl-mx-5">
<gl-button
+ v-gl-tooltip.bottom
:disabled="!previousDesign"
:title="s__('DesignManagement|Go to previous design')"
icon="angle-left"
@@ -75,6 +79,7 @@ export default {
@click="navigateToDesign(previousDesign)"
/>
<gl-button
+ v-gl-tooltip.bottom
:disabled="!nextDesign"
:title="s__('DesignManagement|Go to next design')"
icon="angle-right"
diff --git a/app/assets/javascripts/design_management/components/toolbar/index.vue b/app/assets/javascripts/design_management/components/toolbar/index.vue
index 8d25d467d59..4caee863df8 100644
--- a/app/assets/javascripts/design_management/components/toolbar/index.vue
+++ b/app/assets/javascripts/design_management/components/toolbar/index.vue
@@ -1,10 +1,10 @@
<script>
-import { GlButton, GlIcon } from '@gitlab/ui';
+import { GlButton, GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql';
import { __, sprintf } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import DesignNavigation from './design_navigation.vue';
import DeleteButton from '../delete_button.vue';
-import permissionsQuery from '../../graphql/queries/design_permissions.query.graphql';
import { DESIGNS_ROUTE_NAME } from '../../router/constants';
export default {
@@ -14,6 +14,9 @@ export default {
DesignNavigation,
DeleteButton,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
mixins: [timeagoMixin],
props: {
id: {
@@ -112,14 +115,21 @@ export default {
</div>
</div>
<design-navigation :id="id" class="gl-ml-auto gl-flex-shrink-0" />
- <gl-button :href="image" icon="download" />
+ <gl-button
+ v-gl-tooltip.bottom
+ :href="image"
+ icon="download"
+ :title="s__('DesignManagement|Download design')"
+ />
<delete-button
v-if="isLatestVersion && canDeleteDesign"
+ v-gl-tooltip.bottom
class="gl-ml-3"
:is-deleting="isDeleting"
button-variant="warning"
button-icon="archive"
button-category="secondary"
+ :title="s__('DesignManagement|Archive design')"
@deleteSelectedDesigns="$emit('delete')"
/>
</header>
diff --git a/app/assets/javascripts/design_management/components/upload/button.vue b/app/assets/javascripts/design_management/components/upload/button.vue
index c76041c74a8..d7b287f663b 100644
--- a/app/assets/javascripts/design_management/components/upload/button.vue
+++ b/app/assets/javascripts/design_management/components/upload/button.vue
@@ -1,11 +1,10 @@
<script>
-import { GlButton, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import { VALID_DESIGN_FILE_MIMETYPE } from '../../constants';
export default {
components: {
GlButton,
- GlLoadingIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -38,12 +37,12 @@ export default {
)
"
:disabled="isSaving"
+ :loading="isSaving"
variant="default"
size="small"
@click="openFileUpload"
>
{{ s__('DesignManagement|Upload designs') }}
- <gl-loading-icon v-if="isSaving" inline class="ml-1" />
</gl-button>
<input
diff --git a/app/assets/javascripts/design_management/components/upload/design_dropzone.vue b/app/assets/javascripts/design_management/components/upload/design_dropzone.vue
deleted file mode 100644
index 6694b0dab8d..00000000000
--- a/app/assets/javascripts/design_management/components/upload/design_dropzone.vue
+++ /dev/null
@@ -1,147 +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,
- },
- props: {
- hasDesigns: {
- type: Boolean,
- required: true,
- },
- isDraggingDesign: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- data() {
- return {
- dragCounter: 0,
- isDragDataValid: false,
- };
- },
- computed: {
- dragging() {
- return this.dragCounter !== 0;
- },
- iconStyles() {
- return {
- size: this.hasDesigns ? 24 : 16,
- class: this.hasDesigns ? 'gl-mb-2' : 'gl-mr-3 gl-text-gray-500',
- };
- },
- },
- 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="gl-w-full gl-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 gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
- @click="openFileUpload"
- >
- <div
- :class="{ 'gl-flex-direction-column': hasDesigns }"
- class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center"
- data-testid="dropzone-area"
- >
- <gl-icon name="upload" :size="iconStyles.size" :class="iconStyles.class" />
- <p class="gl-mb-0">
- <gl-sprintf :message="__('Drop or %{linkStart}upload%{linkEnd} designs to attach')">
- <template #link="{ content }">
- <gl-link @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 && !isDraggingDesign"
- class="card design-dropzone-border design-dropzone-overlay gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
- >
- <div v-show="!isDragDataValid" class="mw-50 gl-text-center">
- <h3 :class="{ 'gl-font-base gl-display-inline': !hasDesigns }">{{ __('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 gl-text-center">
- <h3 :class="{ 'gl-font-base gl-display-inline': !hasDesigns }">{{ __('Incoming!') }}</h3>
- <span>{{ __('Drop your designs to start your upload.') }}</span>
- </div>
- </div>
- </transition>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management/constants.js b/app/assets/javascripts/design_management/constants.js
index 63a92ef5ec0..92928ca429f 100644
--- a/app/assets/javascripts/design_management/constants.js
+++ b/app/assets/javascripts/design_management/constants.js
@@ -5,9 +5,6 @@ export const VALID_DESIGN_FILE_MIMETYPE = {
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',
diff --git a/app/assets/javascripts/design_management/graphql/fragments/note_permissions.fragment.graphql b/app/assets/javascripts/design_management/graphql/fragments/note_permissions.fragment.graphql
index c243e39f3d3..e599ab19c2d 100644
--- a/app/assets/javascripts/design_management/graphql/fragments/note_permissions.fragment.graphql
+++ b/app/assets/javascripts/design_management/graphql/fragments/note_permissions.fragment.graphql
@@ -1,3 +1,4 @@
fragment DesignNotePermissions on NotePermissions {
adminNote
+ repositionNote
}
diff --git a/app/assets/javascripts/design_management/graphql/mutations/reposition_image_diff_note.mutation.graphql b/app/assets/javascripts/design_management/graphql/mutations/reposition_image_diff_note.mutation.graphql
new file mode 100644
index 00000000000..78fbcf1c3c7
--- /dev/null
+++ b/app/assets/javascripts/design_management/graphql/mutations/reposition_image_diff_note.mutation.graphql
@@ -0,0 +1,10 @@
+#import "../fragments/design_note.fragment.graphql"
+
+mutation repositionImageDiffNote($input: RepositionImageDiffNoteInput!) {
+ repositionImageDiffNote(input: $input) {
+ errors
+ note {
+ ...DesignNote
+ }
+ }
+}
diff --git a/app/assets/javascripts/design_management/graphql/mutations/update_image_diff_note.mutation.graphql b/app/assets/javascripts/design_management/graphql/mutations/update_image_diff_note.mutation.graphql
deleted file mode 100644
index 5562ca9d89f..00000000000
--- a/app/assets/javascripts/design_management/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/graphql/queries/design_permissions.query.graphql b/app/assets/javascripts/design_management/graphql/queries/design_permissions.query.graphql
deleted file mode 100644
index a87b256dc95..00000000000
--- a/app/assets/javascripts/design_management/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/graphql/queries/get_design.query.graphql b/app/assets/javascripts/design_management/graphql/queries/get_design.query.graphql
index 96869a404b1..99a61191c6e 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
@@ -1,7 +1,12 @@
#import "../fragments/design.fragment.graphql"
#import "~/graphql_shared/fragments/author.fragment.graphql"
-query getDesign($fullPath: ID!, $iid: String!, $atVersion: ID, $filenames: [String!]) {
+query getDesign(
+ $fullPath: ID!
+ $iid: String!
+ $atVersion: DesignManagementVersionID
+ $filenames: [String!]
+) {
project(fullPath: $fullPath) {
id
issue(iid: $iid) {
diff --git a/app/assets/javascripts/design_management/graphql/queries/get_design_list.query.graphql b/app/assets/javascripts/design_management/graphql/queries/get_design_list.query.graphql
deleted file mode 100644
index efa61edf51a..00000000000
--- a/app/assets/javascripts/design_management/graphql/queries/get_design_list.query.graphql
+++ /dev/null
@@ -1,23 +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 {
- copyState
- designs(atVersion: $atVersion) {
- nodes {
- ...DesignListItem
- }
- }
- versions {
- nodes {
- ...VersionListItem
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/design_management/mixins/all_designs.js b/app/assets/javascripts/design_management/mixins/all_designs.js
index 62bcf216add..466f61e21fa 100644
--- a/app/assets/javascripts/design_management/mixins/all_designs.js
+++ b/app/assets/javascripts/design_management/mixins/all_designs.js
@@ -1,7 +1,7 @@
import { propertyOf } from 'lodash';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
+import createFlash, { FLASH_TYPES } from '~/flash';
import { s__ } from '~/locale';
-import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql';
import allVersionsMixin from './all_versions';
import { DESIGNS_ROUTE_NAME } from '../router/constants';
@@ -36,20 +36,20 @@ export default {
},
result() {
if (this.$route.query.version && !this.hasValidVersion) {
- createFlash(
- s__(
+ createFlash({
+ message: s__(
'DesignManagement|Requested design version does not exist. Showing latest version instead',
),
- );
+ });
this.$router.replace({ name: DESIGNS_ROUTE_NAME, query: { version: undefined } });
}
if (this.designCollection.copyState === 'ERROR') {
- createFlash(
- s__(
+ createFlash({
+ message: s__(
'DesignManagement|There was an error moving your designs. Please upload your designs below.',
),
- 'warning',
- );
+ type: FLASH_TYPES.WARNING,
+ });
}
},
},
diff --git a/app/assets/javascripts/design_management/mixins/all_versions.js b/app/assets/javascripts/design_management/mixins/all_versions.js
index 7a094f23378..07cd0fc92bd 100644
--- a/app/assets/javascripts/design_management/mixins/all_versions.js
+++ b/app/assets/javascripts/design_management/mixins/all_versions.js
@@ -1,4 +1,4 @@
-import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql';
+import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
import { findVersionId } from '../utils/design_management_utils';
export default {
diff --git a/app/assets/javascripts/design_management/pages/design/index.vue b/app/assets/javascripts/design_management/pages/design/index.vue
index 6a96b06dcd8..e07279ba39d 100644
--- a/app/assets/javascripts/design_management/pages/design/index.vue
+++ b/app/assets/javascripts/design_management/pages/design/index.vue
@@ -2,7 +2,7 @@
import Mousetrap from 'mousetrap';
import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
import { ApolloMutation } from 'vue-apollo';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { fetchPolicies } from '~/lib/graphql';
import allVersionsMixin from '../../mixins/all_versions';
import Toolbar from '../../components/toolbar/index.vue';
@@ -13,18 +13,19 @@ 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 createImageDiffNoteMutation from '../../graphql/mutations/create_image_diff_note.mutation.graphql';
-import updateImageDiffNoteMutation from '../../graphql/mutations/update_image_diff_note.mutation.graphql';
+import repositionImageDiffNoteMutation from '../../graphql/mutations/reposition_image_diff_note.mutation.graphql';
import updateActiveDiscussionMutation from '../../graphql/mutations/update_active_discussion.mutation.graphql';
import {
extractDiscussions,
extractDesign,
- updateImageDiffNoteOptimisticResponse,
+ repositionImageDiffNoteOptimisticResponse,
toDiffNoteGid,
extractDesignNoteId,
+ getPageLayoutElement,
} from '../../utils/design_management_utils';
import {
updateStoreAfterAddImageDiffNote,
- updateStoreAfterUpdateImageDiffNote,
+ updateStoreAfterRepositionImageDiffNote,
} from '../../utils/cache_update';
import {
ADD_DISCUSSION_COMMENT_ERROR,
@@ -38,7 +39,7 @@ import {
} from '../../utils/error_messages';
import { trackDesignDetailView } from '../../utils/tracking';
import { DESIGNS_ROUTE_NAME } from '../../router/constants';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../../constants';
+import { ACTIVE_DISCUSSION_SOURCE_TYPES, DESIGN_DETAIL_LAYOUT_CLASSLIST } from '../../constants';
const DEFAULT_SCALE = 1;
@@ -181,12 +182,12 @@ export default {
updateImageDiffNoteInStore(
store,
{
- data: { updateImageDiffNote },
+ data: { repositionImageDiffNote },
},
) {
- return updateStoreAfterUpdateImageDiffNote(
+ return updateStoreAfterRepositionImageDiffNote(
store,
- updateImageDiffNote,
+ repositionImageDiffNote,
getDesignQuery,
this.designVariables,
);
@@ -198,7 +199,7 @@ export default {
);
const mutationPayload = {
- optimisticResponse: updateImageDiffNoteOptimisticResponse(note, {
+ optimisticResponse: repositionImageDiffNoteOptimisticResponse(note, {
position,
}),
variables: {
@@ -207,7 +208,7 @@ export default {
position,
},
},
- mutation: updateImageDiffNoteMutation,
+ mutation: repositionImageDiffNoteMutation,
update: this.updateImageDiffNoteInStore,
};
@@ -229,7 +230,7 @@ export default {
onQueryError(message) {
// because we redirect user to /designs (the issue page),
// we want to create these flashes on the issue page
- createFlash(message);
+ createFlash({ message });
this.$router.push({ name: this.$options.DESIGNS_ROUTE_NAME });
},
onError(message, e) {
@@ -300,6 +301,22 @@ export default {
this.resolvedDiscussionsExpanded = !this.resolvedDiscussionsExpanded;
},
},
+ beforeRouteEnter(to, from, next) {
+ const pageEl = getPageLayoutElement();
+ if (pageEl) {
+ pageEl.classList.add(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
+ }
+
+ next();
+ },
+ beforeRouteLeave(to, from, next) {
+ const pageEl = getPageLayoutElement();
+ if (pageEl) {
+ pageEl.classList.remove(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
+ }
+
+ next();
+ },
createImageDiffNoteMutation,
DESIGNS_ROUTE_NAME,
};
@@ -366,7 +383,7 @@ export default {
@toggleResolvedComments="toggleResolvedComments"
@todoError="onTodoError"
>
- <template #replyForm>
+ <template #reply-form>
<apollo-mutation
v-if="isAnnotating"
#default="{ mutate, loading }"
diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue
index 6e71dca41e9..ea404692840 100644
--- a/app/assets/javascripts/design_management/pages/index.vue
+++ b/app/assets/javascripts/design_management/pages/index.vue
@@ -1,25 +1,26 @@
<script>
-import { GlLoadingIcon, GlButton, GlAlert } from '@gitlab/ui';
+import { GlLoadingIcon, GlButton, GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
import VueDraggable from 'vuedraggable';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { s__, sprintf } from '~/locale';
+import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
+import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql';
+import createFlash, { FLASH_TYPES } from '~/flash';
+import { __, s__, sprintf } from '~/locale';
import { getFilename } from '~/lib/utils/file_upload';
import UploadButton from '../components/upload/button.vue';
import 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 DesignDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
import uploadDesignMutation from '../graphql/mutations/upload_design.mutation.graphql';
import moveDesignMutation from '../graphql/mutations/move_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,
MOVE_DESIGN_ERROR,
+ UPLOAD_DESIGN_INVALID_FILETYPE_ERROR,
designUploadSkippedWarning,
designDeletionError,
} from '../utils/error_messages';
@@ -34,6 +35,7 @@ import {
} from '../utils/design_management_utils';
import { trackDesignCreate, trackDesignUpdate } from '../utils/tracking';
import { DESIGNS_ROUTE_NAME } from '../router/constants';
+import { VALID_DESIGN_FILE_MIMETYPE } from '../constants';
const MAXIMUM_FILE_UPLOAD_LIMIT = 10;
@@ -42,6 +44,8 @@ export default {
GlLoadingIcon,
GlAlert,
GlButton,
+ GlSprintf,
+ GlLink,
UploadButton,
Design,
DesignDestroyer,
@@ -50,6 +54,11 @@ export default {
DesignDropzone,
VueDraggable,
},
+ dropzoneProps: {
+ dropToStartMessage: __('Drop your designs to start your upload.'),
+ isFileValid: isValidDesignFile,
+ validFileMimetypes: [VALID_DESIGN_FILE_MIMETYPE.mimetype],
+ },
mixins: [allDesignsMixin],
apollo: {
permissions: {
@@ -139,8 +148,8 @@ export default {
if (!this.canCreateDesign) return false;
if (files.length > MAXIMUM_FILE_UPLOAD_LIMIT) {
- createFlash(
- sprintf(
+ createFlash({
+ message: sprintf(
s__(
'DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again.',
),
@@ -148,7 +157,7 @@ export default {
upload_limit: MAXIMUM_FILE_UPLOAD_LIMIT,
},
),
- );
+ });
return false;
}
@@ -191,7 +200,7 @@ export default {
const skippedFiles = res?.data?.designManagementUpload?.skippedDesigns || [];
const skippedWarningMessage = designUploadSkippedWarning(this.filesToBeSaved, skippedFiles);
if (skippedWarningMessage) {
- createFlash(skippedWarningMessage, 'warning');
+ createFlash({ message: skippedWarningMessage, types: FLASH_TYPES.WARNING });
}
// if this upload resulted in a new version being created, redirect user to the latest version
@@ -214,7 +223,7 @@ export default {
},
onUploadDesignError() {
this.resetFilesToBeSaved();
- createFlash(UPLOAD_DESIGN_ERROR);
+ createFlash({ message: UPLOAD_DESIGN_ERROR });
},
changeSelectedDesigns(filename) {
if (this.isDesignSelected(filename)) {
@@ -245,18 +254,21 @@ export default {
},
onDesignDeleteError() {
const errorMessage = designDeletionError({ singular: this.selectedDesigns.length === 1 });
- createFlash(errorMessage);
+ createFlash({ message: errorMessage });
+ },
+ onDesignDropzoneError() {
+ createFlash({ message: UPLOAD_DESIGN_INVALID_FILETYPE_ERROR });
},
onExistingDesignDropzoneChange(files, existingDesignFilename) {
const filesArr = Array.from(files);
if (filesArr.length > 1) {
- createFlash(EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE);
+ createFlash({ message: EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE });
return;
}
if (!filesArr.some(({ name }) => existingDesignFilename === name)) {
- createFlash(EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE);
+ createFlash({ message: EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE });
return;
}
@@ -307,7 +319,7 @@ export default {
optimisticResponse: moveDesignOptimisticResponse(this.reorderedDesigns),
})
.catch(() => {
- createFlash(MOVE_DESIGN_ERROR);
+ createFlash({ message: MOVE_DESIGN_ERROR });
})
.finally(() => {
this.isReorderingInProgress = false;
@@ -325,6 +337,9 @@ export default {
animation: 200,
ghostClass: 'gl-visibility-hidden',
},
+ i18n: {
+ dropzoneDescriptionText: __('Drop or %{linkStart}upload%{linkEnd} designs to attach'),
+ },
};
</script>
@@ -335,7 +350,11 @@ export default {
@mouseenter="toggleOnPasteListener"
@mouseleave="toggleOffPasteListener"
>
- <header v-if="showToolbar" class="row-content-block gl-border-t-0 gl-p-3 gl-display-flex">
+ <header
+ v-if="showToolbar"
+ class="row-content-block gl-border-t-0 gl-p-3 gl-display-flex"
+ data-testid="design-toolbar-wrapper"
+ >
<div class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-w-full">
<div>
<span class="gl-font-weight-bold gl-mr-3">{{ s__('DesignManagement|Designs') }}</span>
@@ -371,7 +390,12 @@ export default {
{{ s__('DesignManagement|Archive selected') }}
</delete-button>
</design-destroyer>
- <upload-button v-if="canCreateDesign" :is-saving="isSaving" @upload="onUploadDesign" />
+ <upload-button
+ v-if="canCreateDesign"
+ :is-saving="isSaving"
+ data-testid="design-upload-button"
+ @upload="onUploadDesign"
+ />
</div>
</div>
</header>
@@ -414,15 +438,26 @@ export default {
class="col-md-6 col-lg-3 gl-mb-3 gl-bg-transparent gl-shadow-none js-design-tile"
>
<design-dropzone
- :has-designs="hasDesigns"
- :is-dragging-design="isDraggingDesign"
+ :display-as-card="hasDesigns"
+ :enable-drag-behavior="isDraggingDesign"
+ v-bind="$options.dropzoneProps"
@change="onExistingDesignDropzoneChange($event, design.filename)"
+ @error="onDesignDropzoneError"
>
<design
v-bind="design"
:is-uploading="isDesignToBeSaved(design.filename)"
class="gl-bg-white"
/>
+ <template #upload-text="{ openFileUpload }">
+ <gl-sprintf :message="$options.i18n.dropzoneDescriptionText">
+ <template #link="{ content }">
+ <gl-link @click.stop="openFileUpload">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </template>
</design-dropzone>
<input
@@ -438,12 +473,24 @@ export default {
<template #header>
<li :class="designDropzoneWrapperClass" data-testid="design-dropzone-wrapper">
<design-dropzone
- :is-dragging-design="isDraggingDesign"
+ :enable-drag-behavior="isDraggingDesign"
:class="{ 'design-list-item design-list-item-new': !isDesignListEmpty }"
- :has-designs="hasDesigns"
+ :display-as-card="hasDesigns"
+ v-bind="$options.dropzoneProps"
data-qa-selector="design_dropzone_content"
@change="onUploadDesign"
- />
+ @error="onDesignDropzoneError"
+ >
+ <template #upload-text="{ openFileUpload }">
+ <gl-sprintf :message="$options.i18n.dropzoneDescriptionText">
+ <template #link="{ content }">
+ <gl-link @click.stop="openFileUpload">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </template>
+ </design-dropzone>
</li>
</template>
</vue-draggable>
diff --git a/app/assets/javascripts/design_management/router/index.js b/app/assets/javascripts/design_management/router/index.js
index cbeb2f7ce42..12692612bbc 100644
--- a/app/assets/javascripts/design_management/router/index.js
+++ b/app/assets/javascripts/design_management/router/index.js
@@ -1,9 +1,6 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
import routes from './routes';
-import { DESIGN_ROUTE_NAME } from './constants';
-import { getPageLayoutElement } from '~/design_management/utils/design_management_utils';
-import { DESIGN_DETAIL_LAYOUT_CLASSLIST } from '../constants';
Vue.use(VueRouter);
@@ -13,20 +10,6 @@ export default function createRouter(base) {
mode: 'history',
routes,
});
- const pageEl = getPageLayoutElement();
-
- router.beforeEach(({ name }, _, next) => {
- // 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/utils/cache_update.js b/app/assets/javascripts/design_management/utils/cache_update.js
index fc0530ff977..5bd0288d037 100644
--- a/app/assets/javascripts/design_management/utils/cache_update.js
+++ b/app/assets/javascripts/design_management/utils/cache_update.js
@@ -2,7 +2,7 @@
import { differenceBy } from 'lodash';
import produce from 'immer';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { extractCurrentDiscussion, extractDesign, extractDesigns } from './design_management_utils';
import {
ADD_IMAGE_DIFF_NOTE_ERROR,
@@ -101,7 +101,7 @@ const addImageDiffNoteToStore = (store, createImageDiffNote, query, variables) =
});
};
-const updateImageDiffNoteInStore = (store, updateImageDiffNote, query, variables) => {
+const updateImageDiffNoteInStore = (store, repositionImageDiffNote, query, variables) => {
const sourceData = store.readQuery({
query,
variables,
@@ -111,12 +111,12 @@ const updateImageDiffNoteInStore = (store, updateImageDiffNote, query, variables
const design = extractDesign(draftData);
const discussion = extractCurrentDiscussion(
design.discussions,
- updateImageDiffNote.note.discussion.id,
+ repositionImageDiffNote.note.discussion.id,
);
discussion.notes = {
...discussion.notes,
- nodes: [updateImageDiffNote.note, ...discussion.notes.nodes.slice(1)],
+ nodes: [repositionImageDiffNote.note, ...discussion.notes.nodes.slice(1)],
};
});
@@ -237,7 +237,7 @@ export const deletePendingTodoFromStore = (store, todoMarkDone, query, queryVari
};
const onError = (data, message) => {
- createFlash(message);
+ createFlash({ message });
throw new Error(data.errors);
};
@@ -268,7 +268,7 @@ export const updateStoreAfterAddImageDiffNote = (store, data, query, queryVariab
}
};
-export const updateStoreAfterUpdateImageDiffNote = (store, data, query, queryVariables) => {
+export const updateStoreAfterRepositionImageDiffNote = (store, data, query, queryVariables) => {
if (hasErrors(data)) {
onError(data, UPDATE_IMAGE_DIFF_NOTE_ERROR);
} else {
@@ -286,7 +286,7 @@ export const updateStoreAfterUploadDesign = (store, data, query) => {
export const updateDesignsOnStoreAfterReorder = (store, data, query) => {
if (hasErrors(data)) {
- createFlash(data.errors[0]);
+ createFlash({ message: data.errors[0] });
} else {
moveDesignInStore(store, data, query);
}
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 687e793d3df..a905230811c 100644
--- a/app/assets/javascripts/design_management/utils/design_management_utils.js
+++ b/app/assets/javascripts/design_management/utils/design_management_utils.js
@@ -107,12 +107,12 @@ export const designUploadOptimisticResponse = files => {
* @param {Object} note
* @param {Object} position
*/
-export const updateImageDiffNoteOptimisticResponse = (note, { position }) => ({
+export const repositionImageDiffNoteOptimisticResponse = (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',
+ repositionImageDiffNote: {
+ __typename: 'RepositionImageDiffNotePayload',
note: {
...note,
position: {
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 085f951147f..9d8d184a3f6 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -20,6 +20,8 @@ import HiddenFilesWarning from './hidden_files_warning.vue';
import MergeConflictWarning from './merge_conflict_warning.vue';
import CollapsedFilesWarning from './collapsed_files_warning.vue';
+import { diffsApp } from '../utils/performance';
+
import {
TREE_LIST_WIDTH_STORAGE_KEY,
INITIAL_TREE_WIDTH,
@@ -124,7 +126,6 @@ export default {
return {
treeWidth,
diffFilesLength: 0,
- collapsedWarningDismissed: false,
};
},
computed: {
@@ -153,7 +154,7 @@ export default {
'canMerge',
'hasConflicts',
]),
- ...mapGetters('diffs', ['hasCollapsedFile', 'isParallelView', 'currentDiffIndex']),
+ ...mapGetters('diffs', ['whichCollapsedTypes', 'isParallelView', 'currentDiffIndex']),
...mapGetters(['isNotesFetched', 'getNoteableData']),
diffs() {
if (!this.viewDiffsFileByFile) {
@@ -206,11 +207,7 @@ export default {
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
- ) {
+ } else if (this.whichCollapsedTypes.automatic && !this.viewDiffsFileByFile) {
visible = this.$options.alerts.ALERT_COLLAPSED_FILES;
}
@@ -277,8 +274,12 @@ export default {
);
}
},
+ beforeCreate() {
+ diffsApp.instrument();
+ },
created() {
this.adjustView();
+
eventHub.$once('fetchDiffData', this.fetchData);
eventHub.$on('refetchDiffData', this.refetchDiffData);
this.CENTERED_LIMITED_CONTAINER_CLASSES = CENTERED_LIMITED_CONTAINER_CLASSES;
@@ -299,6 +300,8 @@ export default {
);
},
beforeDestroy() {
+ diffsApp.deinstrument();
+
eventHub.$off('fetchDiffData', this.fetchData);
eventHub.$off('refetchDiffData', this.refetchDiffData);
this.removeEventListeners();
@@ -429,9 +432,6 @@ export default {
this.toggleShowTreeList(false);
}
},
- dismissCollapsedWarning() {
- this.collapsedWarningDismissed = true;
- },
},
minTreeWidth: MIN_TREE_WIDTH,
maxTreeWidth: MAX_TREE_WIDTH,
@@ -464,7 +464,6 @@ export default {
<collapsed-files-warning
v-if="visibleWarning == $options.alerts.ALERT_COLLAPSED_FILES"
:limited="isLimitedContainer"
- @dismiss="dismissCollapsedWarning"
/>
<div
@@ -496,9 +495,11 @@ export default {
<div v-if="isBatchLoading" class="loading"><gl-loading-icon size="lg" /></div>
<template v-else-if="renderDiffFiles">
<diff-file
- v-for="file in diffs"
+ v-for="(file, index) in diffs"
:key="file.newPath"
:file="file"
+ :is-first-file="index === 0"
+ :is-last-file="index === diffs.length - 1"
:help-page-path="helpPagePath"
:can-current-user-fork="canCurrentUserFork"
:view-diffs-file-by-file="viewDiffsFileByFile"
diff --git a/app/assets/javascripts/diffs/components/collapsed_files_warning.vue b/app/assets/javascripts/diffs/components/collapsed_files_warning.vue
index 270bbfb99b7..0cf1cdb17f8 100644
--- a/app/assets/javascripts/diffs/components/collapsed_files_warning.vue
+++ b/app/assets/javascripts/diffs/components/collapsed_files_warning.vue
@@ -1,9 +1,8 @@
<script>
-import { mapActions } from 'vuex';
-
import { GlAlert, GlButton } from '@gitlab/ui';
-import { CENTERED_LIMITED_CONTAINER_CLASSES } from '../constants';
+import { CENTERED_LIMITED_CONTAINER_CLASSES, EVT_EXPAND_ALL_FILES } from '../constants';
+import eventHub from '../event_hub';
export default {
components: {
@@ -36,13 +35,12 @@ export default {
},
methods: {
- ...mapActions('diffs', ['expandAllFiles']),
dismiss() {
this.isDismissed = true;
this.$emit('dismiss');
},
expand() {
- this.expandAllFiles();
+ eventHub.$emit(EVT_EXPAND_ALL_FILES);
this.dismiss();
},
},
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index b1ebd8e6ebc..700d5ec86c8 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -6,7 +6,8 @@ import { polyfillSticky } from '~/lib/utils/sticky';
import CompareDropdownLayout from './compare_dropdown_layout.vue';
import SettingsDropdown from './settings_dropdown.vue';
import DiffStats from './diff_stats.vue';
-import { CENTERED_LIMITED_CONTAINER_CLASSES } from '../constants';
+import { CENTERED_LIMITED_CONTAINER_CLASSES, EVT_EXPAND_ALL_FILES } from '../constants';
+import eventHub from '../event_hub';
export default {
components: {
@@ -38,7 +39,7 @@ export default {
},
computed: {
...mapGetters('diffs', [
- 'hasCollapsedFile',
+ 'whichCollapsedTypes',
'diffCompareDropdownTargetVersions',
'diffCompareDropdownSourceVersions',
]),
@@ -67,9 +68,11 @@ export default {
...mapActions('diffs', [
'setInlineDiffViewType',
'setParallelDiffViewType',
- 'expandAllFiles',
'toggleShowTreeList',
]),
+ expandAllFiles() {
+ eventHub.$emit(EVT_EXPAND_ALL_FILES);
+ },
},
};
</script>
@@ -129,7 +132,7 @@ export default {
{{ __('Show latest version') }}
</gl-button>
<gl-button
- v-show="hasCollapsedFile"
+ v-show="whichCollapsedTypes.any"
variant="default"
class="gl-mr-3"
@click="expandAllFiles"
diff --git a/app/assets/javascripts/diffs/components/diff_comment_cell.vue b/app/assets/javascripts/diffs/components/diff_comment_cell.vue
new file mode 100644
index 00000000000..4b0b603f5a5
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/diff_comment_cell.vue
@@ -0,0 +1,69 @@
+<script>
+import { mapActions } from 'vuex';
+import DiffDiscussions from './diff_discussions.vue';
+import DiffLineNoteForm from './diff_line_note_form.vue';
+import DiffDiscussionReply from './diff_discussion_reply.vue';
+
+export default {
+ components: {
+ DiffDiscussions,
+ DiffLineNoteForm,
+ DiffDiscussionReply,
+ },
+ props: {
+ line: {
+ type: Object,
+ required: true,
+ },
+ diffFileHash: {
+ type: String,
+ required: true,
+ },
+ helpPagePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ hasDraft: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ linePosition: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ methods: {
+ ...mapActions('diffs', ['showCommentForm']),
+ },
+};
+</script>
+
+<template>
+ <div class="content">
+ <diff-discussions
+ v-if="line.renderDiscussion"
+ :line="line"
+ :discussions="line.discussions"
+ :help-page-path="helpPagePath"
+ />
+ <diff-discussion-reply
+ v-if="!hasDraft"
+ :has-form="line.hasCommentForm"
+ :render-reply-placeholder="Boolean(line.discussions.length)"
+ @showNewDiscussionForm="showCommentForm({ lineCode: line.line_code, fileHash: diffFileHash })"
+ >
+ <template #form>
+ <diff-line-note-form
+ :diff-file-hash="diffFileHash"
+ :line="line"
+ :note-target-line="line"
+ :help-page-path="helpPagePath"
+ :line-position="linePosition"
+ />
+ </template>
+ </diff-discussion-reply>
+ </div>
+</template>
diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue
index e68260b3e62..401064fb18f 100644
--- a/app/assets/javascripts/diffs/components/diff_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_content.vue
@@ -10,6 +10,7 @@ import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_prev
import DiffFileDrafts from '~/batch_comments/components/diff_file_drafts.vue';
import InlineDiffView from './inline_diff_view.vue';
import ParallelDiffView from './parallel_diff_view.vue';
+import DiffView from './diff_view.vue';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import NoteForm from '../../notes/components/note_form.vue';
import ImageDiffOverlay from './image_diff_overlay.vue';
@@ -18,12 +19,14 @@ import eventHub from '../../notes/event_hub';
import { IMAGE_DIFF_POSITION_TYPE } from '../constants';
import { getDiffMode } from '../store/utils';
import { diffViewerModes } from '~/ide/constants';
+import { mapInline, mapParallel } from './diff_row_utils';
export default {
components: {
GlLoadingIcon,
InlineDiffView,
ParallelDiffView,
+ DiffView,
DiffViewer,
NoteForm,
DiffDiscussions,
@@ -83,6 +86,19 @@ export default {
author() {
return this.getUserData;
},
+ mappedLines() {
+ if (this.glFeatures.unifiedDiffLines && this.glFeatures.unifiedDiffComponents) {
+ return this.diffLines(this.diffFile, true).map(mapParallel(this)) || [];
+ }
+
+ // TODO: Everything below this line can be deleted when unifiedDiffComponents FF is removed
+ if (this.isInlineView) {
+ return this.diffFile.highlighted_diff_lines.map(mapInline(this));
+ }
+ return this.glFeatures.unifiedDiffLines
+ ? this.diffLines(this.diffFile).map(mapParallel(this))
+ : this.diffFile.parallel_diff_lines.map(mapParallel(this)) || [];
+ },
},
updated() {
this.$nextTick(() => {
@@ -113,19 +129,28 @@ export default {
<template>
<div class="diff-content">
<div class="diff-viewer">
- <template v-if="isTextFile">
+ <template
+ v-if="isTextFile && glFeatures.unifiedDiffLines && glFeatures.unifiedDiffComponents"
+ >
+ <diff-view
+ :diff-file="diffFile"
+ :diff-lines="mappedLines"
+ :help-page-path="helpPagePath"
+ :inline="isInlineView"
+ />
+ <gl-loading-icon v-if="diffFile.renderingLines" size="md" class="mt-3" />
+ </template>
+ <template v-else-if="isTextFile">
<inline-diff-view
v-if="isInlineView"
:diff-file="diffFile"
- :diff-lines="diffFile.highlighted_diff_lines"
+ :diff-lines="mappedLines"
:help-page-path="helpPagePath"
/>
<parallel-diff-view
v-else-if="isParallelView"
:diff-file="diffFile"
- :diff-lines="
- glFeatures.unifiedDiffLines ? diffLines(diffFile) : diffFile.parallel_diff_lines || []
- "
+ :diff-lines="mappedLines"
: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_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
index 0094b4f8707..4c49dfb5de9 100644
--- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
@@ -6,7 +6,6 @@ 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';
const EXPAND_ALL = 0;
const EXPAND_UP = 1;
@@ -28,9 +27,6 @@ const i18n = {
export default {
i18n,
- directives: {
- tooltip,
- },
components: {
GlIcon,
},
@@ -58,11 +54,6 @@ export default {
required: false,
default: false,
},
- colspan: {
- type: Number,
- required: false,
- default: 4,
- },
},
computed: {
...mapState({
@@ -235,28 +226,26 @@ export default {
</script>
<template>
- <td :colspan="colspan" class="text-center gl-font-regular">
- <div class="content js-line-expansion-content">
- <a
- v-if="canExpandDown"
- class="gl-mx-2 gl-cursor-pointer js-unfold-down gl-display-inline-block gl-py-4"
- @click="handleExpandLines(EXPAND_DOWN)"
- >
- <gl-icon :size="12" name="expand-down" aria-hidden="true" />
- <span>{{ $options.i18n.showMore }}</span>
- </a>
- <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="canExpandUp"
- class="gl-mx-2 gl-cursor-pointer js-unfold gl-display-inline-block gl-py-4"
- @click="handleExpandLines(EXPAND_UP)"
- >
- <gl-icon :size="12" name="expand-up" aria-hidden="true" />
- <span>{{ $options.i18n.showMore }}</span>
- </a>
- </div>
- </td>
+ <div class="content js-line-expansion-content">
+ <a
+ v-if="canExpandDown"
+ class="gl-mx-2 gl-cursor-pointer js-unfold-down gl-display-inline-block gl-py-4"
+ @click="handleExpandLines(EXPAND_DOWN)"
+ >
+ <gl-icon :size="12" name="expand-down" aria-hidden="true" />
+ <span>{{ $options.i18n.showMore }}</span>
+ </a>
+ <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="canExpandUp"
+ class="gl-mx-2 gl-cursor-pointer js-unfold gl-display-inline-block gl-py-4"
+ @click="handleExpandLines(EXPAND_UP)"
+ >
+ <gl-icon :size="12" name="expand-up" aria-hidden="true" />
+ <span>{{ $options.i18n.showMore }}</span>
+ </a>
+ </div>
</template>
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index 529723a349d..32191d7e309 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -1,20 +1,31 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import { escape } from 'lodash';
-import { GlLoadingIcon, GlSafeHtmlDirective as SafeHtml } 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 notesEventHub from '../../notes/event_hub';
import DiffFileHeader from './diff_file_header.vue';
import DiffContent from './diff_content.vue';
import { diffViewerErrors } from '~/ide/constants';
+import { collapsedType, isCollapsed } from '../diff_file';
+import {
+ DIFF_FILE_AUTOMATIC_COLLAPSE,
+ DIFF_FILE_MANUAL_COLLAPSE,
+ EVT_EXPAND_ALL_FILES,
+ EVT_PERF_MARK_DIFF_FILES_END,
+ EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN,
+} from '../constants';
+import { DIFF_FILE, GENERIC_ERROR } from '../i18n';
+import eventHub from '../event_hub';
export default {
components: {
DiffFileHeader,
DiffContent,
+ GlButton,
GlLoadingIcon,
},
directives: {
@@ -26,6 +37,16 @@ export default {
type: Object,
required: true,
},
+ isFirstFile: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isLastFile: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
canCurrentUserFork: {
type: Boolean,
required: true,
@@ -44,16 +65,20 @@ export default {
return {
isLoadingCollapsedDiff: false,
forkMessageVisible: false,
- isCollapsed: this.file.viewer.automaticallyCollapsed || false,
+ isCollapsed: isCollapsed(this.file),
};
},
+ i18n: {
+ ...DIFF_FILE,
+ genericError: GENERIC_ERROR,
+ },
computed: {
...mapState('diffs', ['currentDiffFileId']),
...mapGetters(['isNotesFetched']),
...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>',
@@ -71,13 +96,11 @@ export default {
return this.file.viewer.error === diffViewerErrors.too_large;
},
errorMessage() {
- return this.file.viewer.error_message;
+ return !this.manuallyCollapsed ? this.file.viewer.error_message : '';
},
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>',
@@ -85,62 +108,131 @@ export default {
false,
);
},
- },
- watch: {
- isCollapsed: function fileCollapsedWatch(newVal, oldVal) {
- if (!newVal && oldVal && !this.hasDiff) {
- this.handleLoadCollapsedDiff();
+ hasBodyClasses() {
+ const domParts = {
+ header: 'gl-rounded-base!',
+ contentByHash: '',
+ content: '',
+ };
+
+ if (this.showBody) {
+ domParts.header = 'gl-rounded-bottom-left-none gl-rounded-bottom-right-none';
+ domParts.contentByHash =
+ 'gl-rounded-none gl-rounded-bottom-left-base gl-rounded-bottom-right-base gl-border-1 gl-border-t-0! gl-border-solid gl-border-gray-100';
+ domParts.content = 'gl-rounded-bottom-left-base gl-rounded-bottom-right-base';
}
- this.setFileCollapsed({ filePath: this.file.file_path, collapsed: newVal });
+ return domParts;
},
+ automaticallyCollapsed() {
+ return collapsedType(this.file) === DIFF_FILE_AUTOMATIC_COLLAPSE;
+ },
+ manuallyCollapsed() {
+ return collapsedType(this.file) === DIFF_FILE_MANUAL_COLLAPSE;
+ },
+ showBody() {
+ return !this.isCollapsed || this.automaticallyCollapsed;
+ },
+ showWarning() {
+ return this.isCollapsed && (this.automaticallyCollapsed && !this.viewDiffsFileByFile);
+ },
+ showContent() {
+ return !this.isCollapsed && !this.isFileTooLarge;
+ },
+ },
+ watch: {
'file.file_hash': {
- handler: function watchFileHash() {
- if (this.viewDiffsFileByFile && this.file.viewer.automaticallyCollapsed) {
- this.isCollapsed = false;
- this.handleLoadCollapsedDiff();
- } else {
- this.isCollapsed = this.file.viewer.automaticallyCollapsed || false;
+ handler: function hashChangeWatch(newHash, oldHash) {
+ this.isCollapsed = isCollapsed(this.file);
+
+ if (newHash && oldHash && !this.hasDiff) {
+ this.requestDiff();
}
},
immediate: true,
},
- 'file.viewer.automaticallyCollapsed': function setIsCollapsed(newVal) {
- if (!this.viewDiffsFileByFile) {
- this.isCollapsed = newVal;
- }
+ 'file.viewer.automaticallyCollapsed': {
+ handler: function autoChangeWatch(automaticValue) {
+ if (collapsedType(this.file) !== DIFF_FILE_MANUAL_COLLAPSE) {
+ this.isCollapsed = this.viewDiffsFileByFile ? false : automaticValue;
+ }
+ },
+ immediate: true,
+ },
+ 'file.viewer.manuallyCollapsed': {
+ handler: function manualChangeWatch(manualValue) {
+ if (manualValue !== null) {
+ this.isCollapsed = manualValue;
+ }
+ },
+ immediate: true,
},
},
created() {
- eventHub.$on(`loadCollapsedDiff/${this.file.file_hash}`, this.handleLoadCollapsedDiff);
+ notesEventHub.$on(`loadCollapsedDiff/${this.file.file_hash}`, this.requestDiff);
+ eventHub.$on(EVT_EXPAND_ALL_FILES, this.expandAllListener);
+ },
+ mounted() {
+ if (this.hasDiff) {
+ this.postRender();
+ }
+ },
+ beforeDestroy() {
+ eventHub.$off(EVT_EXPAND_ALL_FILES, this.expandAllListener);
},
methods: {
...mapActions('diffs', [
'loadCollapsedDiff',
'assignDiscussionsToDiff',
'setRenderIt',
- 'setFileCollapsed',
+ 'setFileCollapsedByUser',
]),
+ expandAllListener() {
+ if (this.isCollapsed) {
+ this.handleToggle();
+ }
+ },
+ async postRender() {
+ const eventsForThisFile = [];
+
+ if (this.isFirstFile) {
+ eventsForThisFile.push(EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN);
+ }
+
+ if (this.isLastFile) {
+ eventsForThisFile.push(EVT_PERF_MARK_DIFF_FILES_END);
+ }
+
+ await this.$nextTick();
+
+ eventsForThisFile.forEach(event => {
+ eventHub.$emit(event);
+ });
+ },
handleToggle() {
- if (!this.hasDiff) {
- this.handleLoadCollapsedDiff();
- } else {
- this.isCollapsed = !this.isCollapsed;
- this.setRenderIt(this.file);
+ const currentCollapsedFlag = this.isCollapsed;
+
+ this.setFileCollapsedByUser({
+ filePath: this.file.file_path,
+ collapsed: !currentCollapsedFlag,
+ });
+
+ if (!this.hasDiff && currentCollapsedFlag) {
+ this.requestDiff();
}
},
- handleLoadCollapsedDiff() {
+ requestDiff() {
this.isLoadingCollapsedDiff = true;
this.loadCollapsedDiff(this.file)
.then(() => {
this.isLoadingCollapsedDiff = false;
- this.isCollapsed = false;
this.setRenderIt(this.file);
})
.then(() => {
requestIdleCallback(
() => {
+ this.postRender();
this.assignDiscussionsToDiff(this.getDiffFileDiscussions(this.file));
},
{ timeout: 1000 },
@@ -148,7 +240,7 @@ export default {
})
.catch(() => {
this.isLoadingCollapsedDiff = false;
- createFlash(__('Something went wrong on our end. Please try again!'));
+ createFlash(this.$options.i18n.genericError);
});
},
showForkMessage() {
@@ -167,9 +259,10 @@ export default {
:class="{
'is-active': currentDiffFileId === file.file_hash,
'comments-disabled': Boolean(file.brokenSymlink),
+ 'has-body': showBody,
}"
:data-path="file.new_path"
- class="diff-file file-holder"
+ class="diff-file file-holder gl-border-none"
>
<diff-file-header
:can-current-user-fork="canCurrentUserFork"
@@ -178,7 +271,8 @@ export default {
:expanded="!isCollapsed"
:add-merge-request-buttons="true"
:view-diffs-file-by-file="viewDiffsFileByFile"
- class="js-file-title file-title"
+ class="js-file-title file-title gl-border-1 gl-border-solid gl-border-gray-100"
+ :class="hasBodyClasses.header"
@toggleFile="handleToggle"
@showForkMessage="showForkMessage"
/>
@@ -188,31 +282,50 @@ export default {
<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
+ :id="`diff-content-${file.file_hash}`"
+ :class="hasBodyClasses.contentByHash"
+ data-testid="content-area"
+ >
+ <gl-loading-icon
+ v-if="showLoadingIcon"
+ class="diff-content loading gl-my-0 gl-pt-3"
+ data-testid="loader-icon"
+ />
+ <div v-else-if="errorMessage" class="diff-viewer">
<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="showWarning"
+ class="collapsed-file-warning gl-p-7 gl-bg-orange-50 gl-text-center gl-rounded-bottom-left-base gl-rounded-bottom-right-base"
+ >
+ <p class="gl-mb-8">
+ {{ $options.i18n.autoCollapsed }}
+ </p>
+ <gl-button
+ data-testid="expand-button"
+ category="secondary"
+ variant="warning"
+ @click.prevent="handleToggle"
+ >
+ {{ $options.i18n.expand }}
+ </gl-button>
</div>
<diff-content
- v-show="!isCollapsed && !isFileTooLarge"
+ v-show="showContent"
+ :class="hasBodyClasses.content"
:diff-file="file"
:help-page-path="helpPagePath"
/>
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 9f451cd759a..0d99a2e8a60 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -10,6 +10,7 @@ import {
GlDropdown,
GlDropdownItem,
GlDropdownDivider,
+ GlLoadingIcon,
} from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
@@ -18,6 +19,7 @@ import { __, s__, sprintf } from '~/locale';
import { diffViewerModes } from '~/ide/constants';
import DiffStats from './diff_stats.vue';
import { scrollToElement } from '~/lib/utils/common_utils';
+import { isCollapsed } from '../diff_file';
import { DIFF_FILE_HEADER } from '../i18n';
export default {
@@ -31,6 +33,7 @@ export default {
GlDropdown,
GlDropdownItem,
GlDropdownDivider,
+ GlLoadingIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -125,6 +128,9 @@ export default {
isUsingLfs() {
return this.diffFile.stored_externally && this.diffFile.external_storage === 'lfs';
},
+ isCollapsed() {
+ return isCollapsed(this.diffFile, { fileByFile: this.viewDiffsFileByFile });
+ },
collapseIcon() {
return this.expanded ? 'chevron-down' : 'chevron-right';
},
@@ -209,7 +215,7 @@ export default {
class="js-file-title file-title file-title-flex-parent"
@click.self="handleToggleFile"
>
- <div class="file-header-content gl-display-flex gl-align-items-center gl-pr-0!">
+ <div class="file-header-content">
<gl-icon
v-if="collapsible"
ref="collapseIcon"
@@ -222,11 +228,17 @@ export default {
<a
ref="titleWrapper"
:v-once="!viewDiffsFileByFile"
- class="gl-mr-2 gl-text-decoration-none! gl-text-truncate"
+ class="gl-mr-2 gl-text-decoration-none! gl-word-break-all"
:href="titleLink"
@click="handleFileNameClick"
>
- <file-icon :file-name="filePath" :size="18" aria-hidden="true" css-classes="gl-mr-2" />
+ <file-icon
+ :file-name="filePath"
+ :size="18"
+ aria-hidden="true"
+ css-classes="gl-mr-2"
+ :submodule="diffFile.submodule"
+ />
<span v-if="isFileRenamed">
<strong
v-gl-tooltip
@@ -270,12 +282,12 @@ export default {
{{ diffFile.a_mode }} → {{ diffFile.b_mode }}
</small>
- <span v-if="isUsingLfs" class="label label-lfs gl-mr-2"> {{ __('LFS') }} </span>
+ <span v-if="isUsingLfs" class="badge label label-lfs gl-mr-2"> {{ __('LFS') }} </span>
</div>
<div
v-if="!diffFile.submodule && addMergeRequestButtons"
- class="file-actions d-flex align-items-center flex-wrap"
+ class="file-actions d-flex align-items-center gl-ml-auto gl-align-self-start"
>
<diff-stats :added-lines="diffFile.added_lines" :removed-lines="diffFile.removed_lines" />
<gl-button-group class="gl-pt-0!">
@@ -334,7 +346,7 @@ export default {
</gl-dropdown-item>
</template>
- <template v-if="!diffFile.viewer.automaticallyCollapsed">
+ <template v-if="!isCollapsed">
<gl-dropdown-divider
v-if="!diffFile.is_fully_expanded || diffHasDiscussions(diffFile)"
/>
@@ -355,8 +367,10 @@ export default {
<gl-dropdown-item
v-if="!diffFile.is_fully_expanded"
ref="expandDiffToFullFileButton"
+ :disabled="diffFile.isLoadingFullFile"
@click="toggleFullDiff(diffFile.file_path)"
>
+ <gl-loading-icon v-if="diffFile.isLoadingFullFile" inline />
{{ expandDiffToFullFileTitle }}
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/diffs/components/diff_file_row.vue b/app/assets/javascripts/diffs/components/diff_file_row.vue
index 2856e6ae8eb..3888eb781fb 100644
--- a/app/assets/javascripts/diffs/components/diff_file_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_row.vue
@@ -62,6 +62,7 @@ export default {
v-bind="$attrs"
:class="{ 'is-active': isActive }"
class="diff-file-row"
+ truncate-middle
:file-classes="fileClasses"
v-on="$listeners"
>
diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
index 700e6302102..55f5a736cdf 100644
--- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
@@ -7,7 +7,7 @@ import noteForm from '../../notes/components/note_form.vue';
import MultilineCommentForm from '../../notes/components/multiline_comment_form.vue';
import autosave from '../../notes/mixins/autosave';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
-import { DIFF_NOTE_TYPE } from '../constants';
+import { DIFF_NOTE_TYPE, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
import {
commentLineOptions,
formatLineRange,
@@ -60,7 +60,7 @@ export default {
diffViewType: state => state.diffs.diffViewType,
}),
...mapState('diffs', ['showSuggestPopover']),
- ...mapGetters('diffs', ['getDiffFileByHash']),
+ ...mapGetters('diffs', ['getDiffFileByHash', 'diffLines']),
...mapGetters([
'isLoggedIn',
'noteableType',
@@ -88,16 +88,30 @@ export default {
commentLineOptions() {
const combineSides = (acc, { left, right }) => {
// ignore null values match lines
- if (left && left.type !== 'match') acc.push(left);
+ if (left) acc.push(left);
// if the line_codes are identically, return to avoid duplicates
- if (left?.line_code === right?.line_code) return acc;
+ if (
+ left?.line_code === right?.line_code ||
+ left?.type === 'old-nonewline' ||
+ right?.type === 'new-nonewline'
+ ) {
+ return acc;
+ }
if (right && right.type !== 'match') acc.push(right);
return acc;
};
+ const getDiffLines = () => {
+ if (this.diffViewType === PARALLEL_DIFF_VIEW_TYPE) {
+ return (this.glFeatures.unifiedDiffLines
+ ? this.diffLines(this.diffFile)
+ : this.diffFile.parallel_diff_lines
+ ).reduce(combineSides, []);
+ }
+
+ return this.diffFile.highlighted_diff_lines;
+ };
const side = this.line.type === 'new' ? 'right' : 'left';
- const lines = this.diffFile.highlighted_diff_lines.length
- ? this.diffFile.highlighted_diff_lines
- : this.diffFile.parallel_diff_lines.reduce(combineSides, []);
+ const lines = getDiffLines();
return commentLineOptions(lines, this.line, this.line.line_code, side);
},
},
diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue
new file mode 100644
index 00000000000..77a97c67f3b
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/diff_row.vue
@@ -0,0 +1,271 @@
+<script>
+import { mapActions, mapGetters, mapState } from 'vuex';
+import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import { CONTEXT_LINE_CLASS_NAME, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
+import DiffGutterAvatars from './diff_gutter_avatars.vue';
+import * as utils from './diff_row_utils';
+
+export default {
+ components: {
+ GlIcon,
+ DiffGutterAvatars,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ SafeHtml,
+ },
+ props: {
+ fileHash: {
+ type: String,
+ required: true,
+ },
+ filePath: {
+ type: String,
+ required: true,
+ },
+ line: {
+ type: Object,
+ required: true,
+ },
+ isCommented: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ inline: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ ...mapGetters('diffs', ['fileLineCoverage']),
+ ...mapGetters(['isLoggedIn']),
+ ...mapState({
+ isHighlighted(state) {
+ const line = this.line.left?.line_code ? this.line.left : this.line.right;
+ return utils.isHighlighted(state, line, this.isCommented);
+ },
+ }),
+ classNameMap() {
+ return {
+ [CONTEXT_LINE_CLASS_NAME]: this.line.isContextLineLeft,
+ [PARALLEL_DIFF_VIEW_TYPE]: true,
+ };
+ },
+ parallelViewLeftLineType() {
+ return utils.parallelViewLeftLineType(this.line, this.isHighlighted);
+ },
+ coverageState() {
+ return this.fileLineCoverage(this.filePath, this.line.right.new_line);
+ },
+ classNameMapCellLeft() {
+ return utils.classNameMapCell(this.line.left, this.isHighlighted, this.isLoggedIn);
+ },
+ classNameMapCellRight() {
+ return utils.classNameMapCell(this.line.right, this.isHighlighted, this.isLoggedIn);
+ },
+ addCommentTooltipLeft() {
+ return utils.addCommentTooltip(this.line.left);
+ },
+ addCommentTooltipRight() {
+ return utils.addCommentTooltip(this.line.right);
+ },
+ shouldRenderCommentButton() {
+ return (
+ this.isLoggedIn &&
+ !this.line.isContextLineLeft &&
+ !this.line.isMetaLineLeft &&
+ !this.line.hasDiscussionsLeft &&
+ !this.line.hasDiscussionsRight
+ );
+ },
+ },
+ mounted() {
+ this.scrollToLineIfNeededParallel(this.line);
+ },
+ methods: {
+ ...mapActions('diffs', [
+ 'scrollToLineIfNeededParallel',
+ 'showCommentForm',
+ 'setHighlightedRow',
+ 'toggleLineDiscussions',
+ ]),
+ // Prevent text selecting on both sides of parallel diff view
+ // Backport of the same code from legacy diff notes.
+ handleParallelLineMouseDown(e) {
+ const line = e.currentTarget;
+ const table = line.closest('.diff-table');
+
+ table.classList.remove('left-side-selected', 'right-side-selected');
+ const [lineClass] = ['left-side', 'right-side'].filter(name => line.classList.contains(name));
+
+ if (lineClass) {
+ table.classList.add(`${lineClass}-selected`);
+ }
+ },
+ handleCommentButton(line) {
+ this.showCommentForm({ lineCode: line.line_code, fileHash: this.fileHash });
+ },
+ },
+};
+</script>
+
+<template>
+ <div :class="classNameMap" class="diff-grid-row diff-tr line_holder">
+ <div class="diff-grid-left left-side">
+ <template v-if="line.left">
+ <div
+ :class="classNameMapCellLeft"
+ data-testid="leftLineNumber"
+ class="diff-td diff-line-num old_line"
+ >
+ <span
+ v-if="shouldRenderCommentButton"
+ v-gl-tooltip
+ data-testid="leftCommentButton"
+ class="add-diff-note tooltip-wrapper"
+ :title="addCommentTooltipLeft"
+ >
+ <button
+ type="button"
+ class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
+ :disabled="line.left.commentsDisabled"
+ @click="handleCommentButton(line.left)"
+ >
+ <gl-icon :size="12" name="comment" />
+ </button>
+ </span>
+ <a
+ v-if="line.left.old_line"
+ :data-linenumber="line.left.old_line"
+ :href="line.lineHrefOld"
+ @click="setHighlightedRow(line.lineCode)"
+ >
+ </a>
+ <diff-gutter-avatars
+ v-if="line.hasDiscussionsLeft"
+ :discussions="line.left.discussions"
+ :discussions-expanded="line.left.discussionsExpanded"
+ data-testid="leftDiscussions"
+ @toggleLineDiscussions="
+ toggleLineDiscussions({
+ lineCode: line.left.line_code,
+ fileHash,
+ expanded: !line.left.discussionsExpanded,
+ })
+ "
+ />
+ </div>
+ <div :class="classNameMapCellLeft" class="diff-td diff-line-num old_line">
+ <a
+ v-if="line.left.old_line"
+ :data-linenumber="line.left.old_line"
+ :href="line.lineHrefOld"
+ @click="setHighlightedRow(line.lineCode)"
+ >
+ </a>
+ </div>
+ <div :class="parallelViewLeftLineType" class="diff-td line-coverage left-side"></div>
+ <div
+ :id="line.left.line_code"
+ :key="line.left.line_code"
+ v-safe-html="line.left.rich_text"
+ :class="parallelViewLeftLineType"
+ class="diff-td line_content with-coverage parallel left-side"
+ data-testid="leftContent"
+ @mousedown="handleParallelLineMouseDown"
+ ></div>
+ </template>
+ <template v-else>
+ <div data-testid="leftEmptyCell" class="diff-td diff-line-num old_line empty-cell"></div>
+ <div class="diff-td diff-line-num old_line empty-cell"></div>
+ <div class="diff-td line-coverage left-side empty-cell"></div>
+ <div class="diff-td line_content with-coverage parallel left-side empty-cell"></div>
+ </template>
+ </div>
+ <div
+ v-if="!inline || (line.right && Boolean(line.right.type))"
+ class="diff-grid-right right-side"
+ >
+ <template v-if="line.right">
+ <div
+ :class="classNameMapCellRight"
+ data-testid="rightLineNumber"
+ class="diff-td diff-line-num new_line"
+ >
+ <span
+ v-if="shouldRenderCommentButton"
+ v-gl-tooltip
+ data-testid="rightCommentButton"
+ class="add-diff-note tooltip-wrapper"
+ :title="addCommentTooltipRight"
+ >
+ <button
+ type="button"
+ class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
+ :disabled="line.right.commentsDisabled"
+ @click="handleCommentButton(line.right)"
+ >
+ <gl-icon :size="12" name="comment" />
+ </button>
+ </span>
+ <a
+ v-if="line.right.new_line"
+ :data-linenumber="line.right.new_line"
+ :href="line.lineHrefNew"
+ @click="setHighlightedRow(line.lineCode)"
+ >
+ </a>
+ <diff-gutter-avatars
+ v-if="line.hasDiscussionsRight"
+ :discussions="line.right.discussions"
+ :discussions-expanded="line.right.discussionsExpanded"
+ data-testid="rightDiscussions"
+ @toggleLineDiscussions="
+ toggleLineDiscussions({
+ lineCode: line.right.line_code,
+ fileHash,
+ expanded: !line.right.discussionsExpanded,
+ })
+ "
+ />
+ </div>
+ <div :class="classNameMapCellRight" class="diff-td diff-line-num new_line">
+ <a
+ v-if="line.right.new_line"
+ :data-linenumber="line.right.new_line"
+ :href="line.lineHrefNew"
+ @click="setHighlightedRow(line.lineCode)"
+ >
+ </a>
+ </div>
+ <div
+ v-gl-tooltip.hover
+ :title="coverageState.text"
+ :class="[line.right.type, coverageState.class, { hll: isHighlighted }]"
+ class="diff-td line-coverage right-side"
+ ></div>
+ <div
+ :id="line.right.line_code"
+ :key="line.right.rich_text"
+ v-safe-html="line.right.rich_text"
+ :class="[
+ line.right.type,
+ {
+ hll: isHighlighted,
+ },
+ ]"
+ class="diff-td line_content with-coverage parallel right-side"
+ @mousedown="handleParallelLineMouseDown"
+ ></div>
+ </template>
+ <template v-else>
+ <div data-testid="rightEmptyCell" class="diff-td diff-line-num old_line empty-cell"></div>
+ <div class="diff-td diff-line-num old_line empty-cell"></div>
+ <div class="diff-td line-coverage right-side empty-cell"></div>
+ <div class="diff-td line_content with-coverage parallel right-side empty-cell"></div>
+ </template>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/diffs/components/diff_row_utils.js b/app/assets/javascripts/diffs/components/diff_row_utils.js
index 08b87a4bade..d5491d3cd56 100644
--- a/app/assets/javascripts/diffs/components/diff_row_utils.js
+++ b/app/assets/javascripts/diffs/components/diff_row_utils.js
@@ -83,3 +83,76 @@ export const parallelViewLeftLineType = (line, hll) => {
export const shouldShowCommentButton = (hover, context, meta, discussions) => {
return hover && !context && !meta && !discussions;
};
+
+export const mapParallel = content => line => {
+ let { left, right } = line;
+
+ // Dicussions/Comments
+ const hasExpandedDiscussionOnLeft =
+ left?.discussions?.length > 0 ? left?.discussionsExpanded : false;
+ const hasExpandedDiscussionOnRight =
+ right?.discussions?.length > 0 ? right?.discussionsExpanded : false;
+
+ const renderCommentRow =
+ hasExpandedDiscussionOnLeft || hasExpandedDiscussionOnRight || left?.hasForm || right?.hasForm;
+
+ if (left) {
+ left = {
+ ...left,
+ renderDiscussion: hasExpandedDiscussionOnLeft,
+ hasDraft: content.hasParallelDraftLeft(content.diffFile.file_hash, line),
+ lineDraft: content.draftForLine(content.diffFile.file_hash, line, 'left'),
+ hasCommentForm: left.hasForm,
+ };
+ }
+ if (right) {
+ right = {
+ ...right,
+ renderDiscussion: Boolean(hasExpandedDiscussionOnRight && right.type),
+ hasDraft: content.hasParallelDraftRight(content.diffFile.file_hash, line),
+ lineDraft: content.draftForLine(content.diffFile.file_hash, line, 'right'),
+ hasCommentForm: Boolean(right.hasForm && right.type),
+ };
+ }
+
+ return {
+ ...line,
+ left,
+ right,
+ isMatchLineLeft: isMatchLine(left?.type),
+ isMatchLineRight: isMatchLine(right?.type),
+ isContextLineLeft: isContextLine(left?.type),
+ isContextLineRight: isContextLine(right?.type),
+ hasDiscussionsLeft: hasDiscussions(left),
+ hasDiscussionsRight: hasDiscussions(right),
+ lineHrefOld: lineHref(left),
+ lineHrefNew: lineHref(right),
+ lineCode: lineCode(line),
+ isMetaLineLeft: isMetaLine(left?.type),
+ isMetaLineRight: isMetaLine(right?.type),
+ draftRowClasses: left?.lineDraft > 0 || right?.lineDraft > 0 ? '' : 'js-temp-notes-holder',
+ renderCommentRow,
+ commentRowClasses: hasDiscussions(left) || hasDiscussions(right) ? '' : 'js-temp-notes-holder',
+ };
+};
+
+// TODO: Delete this function when unifiedDiffComponents FF is removed
+export const mapInline = content => line => {
+ // Discussions/Comments
+ const renderCommentRow = line.hasForm || (line.discussions?.length && line.discussionsExpanded);
+
+ return {
+ ...line,
+ renderDiscussion: Boolean(line.discussions?.length),
+ isMatchLine: isMatchLine(line.type),
+ commentRowClasses: line.discussions?.length ? '' : 'js-temp-notes-holder',
+ renderCommentRow,
+ hasDraft: content.shouldRenderDraftRow(content.diffFile.file_hash, line),
+ hasCommentForm: line.hasForm,
+ isMetaLine: isMetaLine(line.type),
+ isContextLine: isContextLine(line.type),
+ hasDiscussions: hasDiscussions(line),
+ lineHref: lineHref(line),
+ lineCode: lineCode(line),
+ };
+};
diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue
new file mode 100644
index 00000000000..84429f62a1c
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/diff_view.vue
@@ -0,0 +1,151 @@
+<script>
+import { mapGetters, mapState } from 'vuex';
+import draftCommentsMixin from '~/diffs/mixins/draft_comments';
+import DraftNote from '~/batch_comments/components/draft_note.vue';
+import DiffRow from './diff_row.vue';
+import DiffCommentCell from './diff_comment_cell.vue';
+import DiffExpansionCell from './diff_expansion_cell.vue';
+import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
+
+export default {
+ components: {
+ DiffExpansionCell,
+ DiffRow,
+ DiffCommentCell,
+ DraftNote,
+ },
+ mixins: [draftCommentsMixin],
+ props: {
+ diffFile: {
+ type: Object,
+ required: true,
+ },
+ diffLines: {
+ type: Array,
+ required: true,
+ },
+ helpPagePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ inline: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ ...mapGetters('diffs', ['commitId']),
+ ...mapState({
+ selectedCommentPosition: ({ notes }) => notes.selectedCommentPosition,
+ selectedCommentPositionHover: ({ notes }) => notes.selectedCommentPositionHover,
+ }),
+ diffLinesLength() {
+ return this.diffLines.length;
+ },
+ commentedLines() {
+ return getCommentedLines(
+ this.selectedCommentPosition || this.selectedCommentPositionHover,
+ this.diffLines,
+ );
+ },
+ },
+ methods: {
+ showCommentLeft(line) {
+ return !this.inline || line.left;
+ },
+ showCommentRight(line) {
+ return !this.inline || (line.right && !line.left);
+ },
+ },
+ userColorScheme: window.gon.user_color_scheme,
+};
+</script>
+
+<template>
+ <div
+ :class="[$options.userColorScheme, { inline }]"
+ :data-commit-id="commitId"
+ class="diff-grid diff-table code diff-wrap-lines js-syntax-highlight text-file"
+ >
+ <template v-for="(line, index) in diffLines">
+ <div
+ v-if="line.isMatchLineLeft || line.isMatchLineRight"
+ :key="`expand-${index}`"
+ class="diff-tr line_expansion match"
+ >
+ <div class="diff-td text-center gl-font-regular">
+ <diff-expansion-cell
+ :file-hash="diffFile.file_hash"
+ :context-lines-path="diffFile.context_lines_path"
+ :line="line.left"
+ :is-top="index === 0"
+ :is-bottom="index + 1 === diffLinesLength"
+ />
+ </div>
+ </div>
+ <diff-row
+ v-if="!line.isMatchLineLeft && !line.isMatchLineRight"
+ :key="line.line_code"
+ :file-hash="diffFile.file_hash"
+ :file-path="diffFile.file_path"
+ :line="line"
+ :is-bottom="index + 1 === diffLinesLength"
+ :is-commented="index >= commentedLines.startLine && index <= commentedLines.endLine"
+ :inline="inline"
+ />
+ <div
+ v-if="line.renderCommentRow"
+ :key="`dcr-${line.line_code || index}`"
+ :class="line.commentRowClasses"
+ class="diff-grid-comments diff-tr notes_holder"
+ >
+ <div v-if="showCommentLeft(line)" class="diff-td notes-content parallel old">
+ <diff-comment-cell
+ v-if="line.left"
+ :line="line.left"
+ :diff-file-hash="diffFile.file_hash"
+ :help-page-path="helpPagePath"
+ :has-draft="line.left.hasDraft"
+ line-position="left"
+ />
+ </div>
+ <div v-if="showCommentRight(line)" class="diff-td notes-content parallel new">
+ <diff-comment-cell
+ v-if="line.right"
+ :line="line.right"
+ :diff-file-hash="diffFile.file_hash"
+ :line-index="index"
+ :help-page-path="helpPagePath"
+ :has-draft="line.right.hasDraft"
+ line-position="right"
+ />
+ </div>
+ </div>
+ <div
+ v-if="shouldRenderParallelDraftRow(diffFile.file_hash, line)"
+ :key="`drafts-${index}`"
+ :class="line.draftRowClasses"
+ class="diff-grid-drafts diff-tr notes_holder"
+ >
+ <div
+ v-if="!inline || (line.left && line.left.lineDraft.isDraft)"
+ class="diff-td notes-content parallel old"
+ >
+ <div v-if="line.left && line.left.lineDraft.isDraft" class="content">
+ <draft-note :draft="line.left.lineDraft" :line="line.left" />
+ </div>
+ </div>
+ <div
+ v-if="!inline || (line.right && line.right.lineDraft.isDraft)"
+ class="diff-td notes-content parallel new"
+ >
+ <div v-if="line.right && line.right.lineDraft.isDraft" class="content">
+ <draft-note :draft="line.right.lineDraft" :line="line.right" />
+ </div>
+ </div>
+ </div>
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue b/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
deleted file mode 100644
index 87f0396cf72..00000000000
--- a/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
+++ /dev/null
@@ -1,82 +0,0 @@
-<script>
-import { mapActions } from 'vuex';
-import DiffDiscussions from './diff_discussions.vue';
-import DiffLineNoteForm from './diff_line_note_form.vue';
-import DiffDiscussionReply from './diff_discussion_reply.vue';
-
-export default {
- components: {
- DiffDiscussions,
- DiffLineNoteForm,
- DiffDiscussionReply,
- },
- props: {
- line: {
- type: Object,
- required: true,
- },
- diffFileHash: {
- type: String,
- required: true,
- },
- helpPagePath: {
- type: String,
- required: false,
- default: '',
- },
- hasDraft: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- className() {
- return this.line.discussions.length ? '' : 'js-temp-notes-holder';
- },
- shouldRender() {
- if (this.line.hasForm) return true;
-
- if (!this.line.discussions || !this.line.discussions.length) {
- return false;
- }
- return this.line.discussionsExpanded;
- },
- },
- methods: {
- ...mapActions('diffs', ['showCommentForm']),
- },
-};
-</script>
-
-<template>
- <tr v-if="shouldRender" :class="className" class="notes_holder">
- <td class="notes-content" colspan="4">
- <div class="content">
- <diff-discussions
- v-if="line.discussions.length"
- :line="line"
- :discussions="line.discussions"
- :help-page-path="helpPagePath"
- />
- <diff-discussion-reply
- v-if="!hasDraft"
- :has-form="line.hasForm"
- :render-reply-placeholder="Boolean(line.discussions.length)"
- @showNewDiscussionForm="
- showCommentForm({ lineCode: line.line_code, fileHash: diffFileHash })
- "
- >
- <template #form>
- <diff-line-note-form
- :diff-file-hash="diffFileHash"
- :line="line"
- :note-target-line="line"
- :help-page-path="helpPagePath"
- />
- </template>
- </diff-discussion-reply>
- </div>
- </td>
- </tr>
-</template>
diff --git a/app/assets/javascripts/diffs/components/inline_diff_expansion_row.vue b/app/assets/javascripts/diffs/components/inline_diff_expansion_row.vue
deleted file mode 100644
index 071a988d789..00000000000
--- a/app/assets/javascripts/diffs/components/inline_diff_expansion_row.vue
+++ /dev/null
@@ -1,51 +0,0 @@
-<script>
-import DiffExpansionCell from './diff_expansion_cell.vue';
-import { MATCH_LINE_TYPE } from '../constants';
-
-export default {
- components: {
- DiffExpansionCell,
- },
- props: {
- fileHash: {
- type: String,
- required: true,
- },
- contextLinesPath: {
- type: String,
- required: true,
- },
- line: {
- type: Object,
- required: true,
- },
- isTop: {
- type: Boolean,
- required: false,
- default: false,
- },
- isBottom: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- isMatchLine() {
- return this.line.type === MATCH_LINE_TYPE;
- },
- },
-};
-</script>
-
-<template>
- <tr v-if="isMatchLine" class="line_expansion match">
- <diff-expansion-cell
- :file-hash="fileHash"
- :context-lines-path="contextLinesPath"
- :line="line"
- :is-top="isTop"
- :is-bottom="isBottom"
- />
- </tr>
-</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 99cf79a70d4..2d8ffb047ca 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
@@ -3,7 +3,13 @@ import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { CONTEXT_LINE_CLASS_NAME } from '../constants';
import DiffGutterAvatars from './diff_gutter_avatars.vue';
-import * as utils from './diff_row_utils';
+import {
+ isHighlighted,
+ shouldShowCommentButton,
+ shouldRenderCommentButton,
+ classNameMapCell,
+ addCommentTooltip,
+} from './diff_row_utils';
export default {
components: {
@@ -48,60 +54,42 @@ export default {
...mapGetters('diffs', ['fileLineCoverage']),
...mapState({
isHighlighted(state) {
- return utils.isHighlighted(state, this.line, this.isCommented);
+ return isHighlighted(state, this.line, this.isCommented);
},
}),
- isContextLine() {
- return utils.isContextLine(this.line.type);
- },
classNameMap() {
return [
this.line.type,
{
- [CONTEXT_LINE_CLASS_NAME]: this.isContextLine,
+ [CONTEXT_LINE_CLASS_NAME]: this.line.isContextLine,
},
];
},
inlineRowId() {
return this.line.line_code || `${this.fileHash}_${this.line.old_line}_${this.line.new_line}`;
},
- isMatchLine() {
- return utils.isMatchLine(this.line.type);
- },
coverageState() {
return this.fileLineCoverage(this.filePath, this.line.new_line);
},
- isMetaLine() {
- return utils.isMetaLine(this.line.type);
- },
classNameMapCell() {
- return utils.classNameMapCell(this.line, this.isHighlighted, this.isLoggedIn, this.isHover);
+ return classNameMapCell(this.line, this.isHighlighted, this.isLoggedIn, this.isHover);
},
addCommentTooltip() {
- return utils.addCommentTooltip(this.line);
+ return addCommentTooltip(this.line);
},
shouldRenderCommentButton() {
- return utils.shouldRenderCommentButton(this.isLoggedIn, true);
+ return shouldRenderCommentButton(this.isLoggedIn, true);
},
shouldShowCommentButton() {
- return utils.shouldShowCommentButton(
+ return shouldShowCommentButton(
this.isHover,
- this.isContextLine,
- this.isMetaLine,
- this.hasDiscussions,
+ this.line.isContextLine,
+ this.line.isMetaLine,
+ this.line.hasDiscussions,
);
},
- hasDiscussions() {
- return utils.hasDiscussions(this.line);
- },
- lineHref() {
- return utils.lineHref(this.line);
- },
- lineCode() {
- return utils.lineCode(this.line);
- },
shouldShowAvatarsOnGutter() {
- return this.hasDiscussions;
+ return this.line.hasDiscussions;
},
},
mounted() {
@@ -128,7 +116,6 @@ export default {
<template>
<tr
- v-if="!isMatchLine"
:id="inlineRowId"
:class="classNameMap"
class="line_holder"
@@ -158,8 +145,8 @@ export default {
v-if="line.old_line"
ref="lineNumberRefOld"
:data-linenumber="line.old_line"
- :href="lineHref"
- @click="setHighlightedRow(lineCode)"
+ :href="line.lineHref"
+ @click="setHighlightedRow(line.lineCode)"
>
</a>
<diff-gutter-avatars
@@ -167,7 +154,11 @@ export default {
:discussions="line.discussions"
:discussions-expanded="line.discussionsExpanded"
@toggleLineDiscussions="
- toggleLineDiscussions({ lineCode, fileHash, expanded: !line.discussionsExpanded })
+ toggleLineDiscussions({
+ lineCode: line.lineCode,
+ fileHash,
+ expanded: !line.discussionsExpanded,
+ })
"
/>
</td>
@@ -176,8 +167,8 @@ export default {
v-if="line.new_line"
ref="lineNumberRefNew"
:data-linenumber="line.new_line"
- :href="lineHref"
- @click="setHighlightedRow(lineCode)"
+ :href="line.lineHref"
+ @click="setHighlightedRow(line.lineCode)"
>
</a>
</td>
diff --git a/app/assets/javascripts/diffs/components/inline_diff_view.vue b/app/assets/javascripts/diffs/components/inline_diff_view.vue
index 13805910648..05f5461054f 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_view.vue
@@ -2,18 +2,18 @@
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 DraftNote from '~/batch_comments/components/draft_note.vue';
import inlineDiffTableRow from './inline_diff_table_row.vue';
-import inlineDiffCommentRow from './inline_diff_comment_row.vue';
-import inlineDiffExpansionRow from './inline_diff_expansion_row.vue';
+import DiffCommentCell from './diff_comment_cell.vue';
+import DiffExpansionCell from './diff_expansion_cell.vue';
import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
export default {
components: {
- inlineDiffCommentRow,
+ DiffCommentCell,
inlineDiffTableRow,
- InlineDraftCommentRow,
- inlineDiffExpansionRow,
+ DraftNote,
+ DiffExpansionCell,
},
mixins: [draftCommentsMixin, glFeatureFlagsMixin()],
props: {
@@ -65,15 +65,19 @@ export default {
</colgroup>
<tbody>
<template v-for="(line, index) in diffLines">
- <inline-diff-expansion-row
- :key="`expand-${index}`"
- :file-hash="diffFile.file_hash"
- :context-lines-path="diffFile.context_lines_path"
- :line="line"
- :is-top="index === 0"
- :is-bottom="index + 1 === diffLinesLength"
- />
+ <tr v-if="line.isMatchLine" :key="`expand-${index}`" class="line_expansion match">
+ <td colspan="4" class="text-center gl-font-regular">
+ <diff-expansion-cell
+ :file-hash="diffFile.file_hash"
+ :context-lines-path="diffFile.context_lines_path"
+ :line="line"
+ :is-top="index === 0"
+ :is-bottom="index + 1 === diffLinesLength"
+ />
+ </td>
+ </tr>
<inline-diff-table-row
+ v-if="!line.isMatchLine"
:key="`${line.line_code || index}`"
:file-hash="diffFile.file_hash"
:file-path="diffFile.file_path"
@@ -81,20 +85,32 @@ export default {
:is-bottom="index + 1 === diffLinesLength"
:is-commented="index >= commentedLines.startLine && index <= commentedLines.endLine"
/>
- <inline-diff-comment-row
+ <tr
+ v-if="line.renderCommentRow"
:key="`icr-${line.line_code || index}`"
- :diff-file-hash="diffFile.file_hash"
- :line="line"
- :help-page-path="helpPagePath"
- :has-draft="shouldRenderDraftRow(diffFile.file_hash, line) || false"
- />
- <inline-draft-comment-row
- v-if="shouldRenderDraftRow(diffFile.file_hash, line)"
- :key="`draft_${index}`"
- :draft="draftForLine(diffFile.file_hash, line)"
- :diff-file="diffFile"
- :line="line"
- />
+ :class="line.commentRowClasses"
+ class="notes_holder"
+ >
+ <td class="notes-content" colspan="4">
+ <diff-comment-cell
+ :diff-file-hash="diffFile.file_hash"
+ :line="line"
+ :help-page-path="helpPagePath"
+ :has-draft="line.hasDraft"
+ />
+ </td>
+ </tr>
+ <tr v-if="line.hasDraft" :key="`draft_${index}`" class="notes_holder js-temp-notes-holder">
+ <td class="notes-content" colspan="4">
+ <div class="content">
+ <draft-note
+ :draft="draftForLine(diffFile.file_hash, line)"
+ :diff-file="diffFile"
+ :line="line"
+ />
+ </div>
+ </td>
+ </tr>
</template>
</tbody>
</table>
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
deleted file mode 100644
index 127e3f214cf..00000000000
--- a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
+++ /dev/null
@@ -1,175 +0,0 @@
-<script>
-import { mapActions } from 'vuex';
-import DiffDiscussions from './diff_discussions.vue';
-import DiffLineNoteForm from './diff_line_note_form.vue';
-import DiffDiscussionReply from './diff_discussion_reply.vue';
-
-export default {
- components: {
- DiffDiscussions,
- DiffLineNoteForm,
- DiffDiscussionReply,
- },
- props: {
- line: {
- type: Object,
- required: true,
- },
- diffFileHash: {
- type: String,
- required: true,
- },
- lineIndex: {
- type: Number,
- required: true,
- },
- helpPagePath: {
- type: String,
- required: false,
- default: '',
- },
- hasDraftLeft: {
- type: Boolean,
- required: false,
- default: false,
- },
- hasDraftRight: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- hasExpandedDiscussionOnLeft() {
- return this.line.left && this.line.left.discussions.length
- ? this.line.left.discussionsExpanded
- : false;
- },
- hasExpandedDiscussionOnRight() {
- return this.line.right && this.line.right.discussions.length
- ? this.line.right.discussionsExpanded
- : false;
- },
- hasAnyExpandedDiscussion() {
- return this.hasExpandedDiscussionOnLeft || this.hasExpandedDiscussionOnRight;
- },
- shouldRenderDiscussionsOnLeft() {
- return (
- this.line.left &&
- this.line.left.discussions &&
- this.line.left.discussions.length &&
- this.hasExpandedDiscussionOnLeft
- );
- },
- shouldRenderDiscussionsOnRight() {
- return (
- this.line.right &&
- this.line.right.discussions &&
- this.line.right.discussions.length &&
- this.hasExpandedDiscussionOnRight &&
- this.line.right.type
- );
- },
- showRightSideCommentForm() {
- return this.line.right && this.line.right.type && this.line.right.hasForm;
- },
- showLeftSideCommentForm() {
- return this.line.left && this.line.left.hasForm;
- },
- className() {
- return (this.left && this.line.left.discussions.length > 0) ||
- (this.right && this.line.right.discussions.length > 0)
- ? ''
- : 'js-temp-notes-holder';
- },
- shouldRender() {
- const { line } = this;
- const hasDiscussion =
- (line.left && line.left.discussions && line.left.discussions.length) ||
- (line.right && line.right.discussions && line.right.discussions.length);
-
- if (
- hasDiscussion &&
- (this.hasExpandedDiscussionOnLeft || this.hasExpandedDiscussionOnRight)
- ) {
- return true;
- }
-
- const hasCommentFormOnLeft = line.left && line.left.hasForm;
- const hasCommentFormOnRight = line.right && line.right.hasForm;
-
- return hasCommentFormOnLeft || hasCommentFormOnRight;
- },
- shouldRenderReplyPlaceholderOnLeft() {
- return Boolean(
- this.line.left && this.line.left.discussions && this.line.left.discussions.length,
- );
- },
- shouldRenderReplyPlaceholderOnRight() {
- return Boolean(
- this.line.right && this.line.right.discussions && this.line.right.discussions.length,
- );
- },
- },
- methods: {
- ...mapActions('diffs', ['showCommentForm']),
- showNewDiscussionForm(lineCode) {
- this.showCommentForm({ lineCode, fileHash: this.diffFileHash });
- },
- },
-};
-</script>
-
-<template>
- <tr v-if="shouldRender" :class="className" class="notes_holder">
- <td class="notes-content parallel old" colspan="3">
- <div v-if="shouldRenderDiscussionsOnLeft" class="content">
- <diff-discussions
- :discussions="line.left.discussions"
- :line="line.left"
- :help-page-path="helpPagePath"
- />
- </div>
- <diff-discussion-reply
- v-if="!hasDraftLeft"
- :has-form="showLeftSideCommentForm"
- :render-reply-placeholder="shouldRenderReplyPlaceholderOnLeft"
- @showNewDiscussionForm="showNewDiscussionForm(line.left.line_code)"
- >
- <template #form>
- <diff-line-note-form
- :diff-file-hash="diffFileHash"
- :line="line.left"
- :note-target-line="line.left"
- :help-page-path="helpPagePath"
- line-position="left"
- />
- </template>
- </diff-discussion-reply>
- </td>
- <td class="notes-content parallel new" colspan="3">
- <div v-if="shouldRenderDiscussionsOnRight" class="content">
- <diff-discussions
- :discussions="line.right.discussions"
- :line="line.right"
- :help-page-path="helpPagePath"
- />
- </div>
- <diff-discussion-reply
- v-if="!hasDraftRight"
- :has-form="showRightSideCommentForm"
- :render-reply-placeholder="shouldRenderReplyPlaceholderOnRight"
- @showNewDiscussionForm="showNewDiscussionForm(line.right.line_code)"
- >
- <template #form>
- <diff-line-note-form
- :diff-file-hash="diffFileHash"
- :line="line.right"
- :note-target-line="line.right"
- line-position="right"
- />
- </template>
- </diff-discussion-reply>
- </td>
- </tr>
-</template>
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_expansion_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_expansion_row.vue
deleted file mode 100644
index 0a80107ced4..00000000000
--- a/app/assets/javascripts/diffs/components/parallel_diff_expansion_row.vue
+++ /dev/null
@@ -1,56 +0,0 @@
-<script>
-import { MATCH_LINE_TYPE } from '../constants';
-import DiffExpansionCell from './diff_expansion_cell.vue';
-
-export default {
- components: {
- DiffExpansionCell,
- },
- props: {
- fileHash: {
- type: String,
- required: true,
- },
- contextLinesPath: {
- type: String,
- required: true,
- },
- line: {
- type: Object,
- required: true,
- },
- isTop: {
- type: Boolean,
- required: false,
- default: false,
- },
- isBottom: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- isMatchLineLeft() {
- return this.line.left && this.line.left.type === MATCH_LINE_TYPE;
- },
- isMatchLineRight() {
- return this.line.right && this.line.right.type === MATCH_LINE_TYPE;
- },
- },
-};
-</script>
-<template>
- <tr class="line_expansion match">
- <template v-if="isMatchLineLeft || isMatchLineRight">
- <diff-expansion-cell
- :file-hash="fileHash"
- :context-lines-path="contextLinesPath"
- :line="line.left"
- :is-top="isTop"
- :is-bottom="isBottom"
- :colspan="6"
- />
- </template>
- </tr>
-</template>
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 cdc6db791f0..13cd0651ff2 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
@@ -55,27 +55,15 @@ export default {
return utils.isHighlighted(state, line, this.isCommented);
},
}),
- isContextLineLeft() {
- return utils.isContextLine(this.line.left?.type);
- },
- isContextLineRight() {
- return utils.isContextLine(this.line.right?.type);
- },
classNameMap() {
return {
- [CONTEXT_LINE_CLASS_NAME]: this.isContextLineLeft,
+ [CONTEXT_LINE_CLASS_NAME]: this.line.isContextLineLeft,
[PARALLEL_DIFF_VIEW_TYPE]: true,
};
},
parallelViewLeftLineType() {
return utils.parallelViewLeftLineType(this.line, this.isHighlighted);
},
- isMatchLineLeft() {
- return utils.isMatchLine(this.line.left?.type);
- },
- isMatchLineRight() {
- return utils.isMatchLine(this.line.right?.type);
- },
coverageState() {
return this.fileLineCoverage(this.filePath, this.line.right.new_line);
},
@@ -107,40 +95,19 @@ export default {
shouldShowCommentButtonLeft() {
return utils.shouldShowCommentButton(
this.isLeftHover,
- this.isContextLineLeft,
- this.isMetaLineLeft,
- this.hasDiscussionsLeft,
+ this.line.isContextLineLeft,
+ this.line.isMetaLineLeft,
+ this.line.hasDiscussionsLeft,
);
},
shouldShowCommentButtonRight() {
return utils.shouldShowCommentButton(
this.isRightHover,
- this.isContextLineRight,
- this.isMetaLineRight,
- this.hasDiscussionsRight,
+ this.line.isContextLineRight,
+ this.line.isMetaLineRight,
+ this.line.hasDiscussionsRight,
);
},
- hasDiscussionsLeft() {
- return utils.hasDiscussions(this.line.left);
- },
- hasDiscussionsRight() {
- return utils.hasDiscussions(this.line.right);
- },
- lineHrefOld() {
- return utils.lineHref(this.line.left);
- },
- lineHrefNew() {
- return utils.lineHref(this.line.right);
- },
- lineCode() {
- return utils.lineCode(this.line);
- },
- isMetaLineLeft() {
- return utils.isMetaLine(this.line.left?.type);
- },
- isMetaLineRight() {
- return utils.isMetaLine(this.line.right?.type);
- },
},
mounted() {
this.scrollToLineIfNeededParallel(this.line);
@@ -203,7 +170,7 @@ export default {
@mouseover="handleMouseMove"
@mouseout="handleMouseMove"
>
- <template v-if="line.left && !isMatchLineLeft">
+ <template v-if="line.left && !line.isMatchLineLeft">
<td ref="oldTd" :class="classNameMapCellLeft" class="diff-line-num old_line">
<span
v-if="shouldRenderCommentButton"
@@ -227,12 +194,12 @@ export default {
v-if="line.left.old_line"
ref="lineNumberRefOld"
:data-linenumber="line.left.old_line"
- :href="lineHrefOld"
- @click="setHighlightedRow(lineCode)"
+ :href="line.lineHrefOld"
+ @click="setHighlightedRow(line.lineCode)"
>
</a>
<diff-gutter-avatars
- v-if="hasDiscussionsLeft"
+ v-if="line.hasDiscussionsLeft"
:discussions="line.left.discussions"
:discussions-expanded="line.left.discussionsExpanded"
@toggleLineDiscussions="
@@ -259,7 +226,7 @@ export default {
<td class="line-coverage left-side empty-cell"></td>
<td class="line_content with-coverage parallel left-side empty-cell"></td>
</template>
- <template v-if="line.right && !isMatchLineRight">
+ <template v-if="line.right && !line.isMatchLineRight">
<td ref="newTd" :class="classNameMapCellRight" class="diff-line-num new_line">
<span
v-if="shouldRenderCommentButton"
@@ -283,12 +250,12 @@ export default {
v-if="line.right.new_line"
ref="lineNumberRefNew"
:data-linenumber="line.right.new_line"
- :href="lineHrefNew"
- @click="setHighlightedRow(lineCode)"
+ :href="line.lineHrefNew"
+ @click="setHighlightedRow(line.lineCode)"
>
</a>
<diff-gutter-avatars
- v-if="hasDiscussionsRight"
+ v-if="line.hasDiscussionsRight"
:discussions="line.right.discussions"
:discussions-expanded="line.right.discussionsExpanded"
@toggleLineDiscussions="
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_view.vue b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
index 46a691ad22d..67b599fe163 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
@@ -1,18 +1,18 @@
<script>
import { mapGetters, mapState } from 'vuex';
import draftCommentsMixin from '~/diffs/mixins/draft_comments';
-import ParallelDraftCommentRow from '~/batch_comments/components/parallel_draft_comment_row.vue';
+import DraftNote from '~/batch_comments/components/draft_note.vue';
import parallelDiffTableRow from './parallel_diff_table_row.vue';
-import parallelDiffCommentRow from './parallel_diff_comment_row.vue';
-import parallelDiffExpansionRow from './parallel_diff_expansion_row.vue';
+import DiffCommentCell from './diff_comment_cell.vue';
+import DiffExpansionCell from './diff_expansion_cell.vue';
import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
export default {
components: {
- parallelDiffExpansionRow,
+ DiffExpansionCell,
parallelDiffTableRow,
- parallelDiffCommentRow,
- ParallelDraftCommentRow,
+ DiffCommentCell,
+ DraftNote,
},
mixins: [draftCommentsMixin],
props: {
@@ -66,14 +66,21 @@ export default {
</colgroup>
<tbody>
<template v-for="(line, index) in diffLines">
- <parallel-diff-expansion-row
+ <tr
+ v-if="line.isMatchLineLeft || line.isMatchLineRight"
:key="`expand-${index}`"
- :file-hash="diffFile.file_hash"
- :context-lines-path="diffFile.context_lines_path"
- :line="line"
- :is-top="index === 0"
- :is-bottom="index + 1 === diffLinesLength"
- />
+ class="line_expansion match"
+ >
+ <td colspan="6" class="text-center gl-font-regular">
+ <diff-expansion-cell
+ :file-hash="diffFile.file_hash"
+ :context-lines-path="diffFile.context_lines_path"
+ :line="line.left"
+ :is-top="index === 0"
+ :is-bottom="index + 1 === diffLinesLength"
+ />
+ </td>
+ </tr>
<parallel-diff-table-row
:key="line.line_code"
:file-hash="diffFile.file_hash"
@@ -82,21 +89,53 @@ export default {
:is-bottom="index + 1 === diffLinesLength"
:is-commented="index >= commentedLines.startLine && index <= commentedLines.endLine"
/>
- <parallel-diff-comment-row
+ <tr
+ v-if="line.renderCommentRow"
:key="`dcr-${line.line_code || index}`"
- :line="line"
- :diff-file-hash="diffFile.file_hash"
- :line-index="index"
- :help-page-path="helpPagePath"
- :has-draft-left="hasParallelDraftLeft(diffFile.file_hash, line) || false"
- :has-draft-right="hasParallelDraftRight(diffFile.file_hash, line) || false"
- />
- <parallel-draft-comment-row
+ :class="line.commentRowClasses"
+ class="notes_holder"
+ >
+ <td class="notes-content parallel old" colspan="3">
+ <diff-comment-cell
+ v-if="line.left"
+ :line="line.left"
+ :diff-file-hash="diffFile.file_hash"
+ :help-page-path="helpPagePath"
+ :has-draft="line.left.hasDraft"
+ line-position="left"
+ />
+ </td>
+ <td class="notes-content parallel new" colspan="3">
+ <diff-comment-cell
+ v-if="line.right"
+ :line="line.right"
+ :diff-file-hash="diffFile.file_hash"
+ :line-index="index"
+ :help-page-path="helpPagePath"
+ :has-draft="line.right.hasDraft"
+ line-position="right"
+ />
+ </td>
+ </tr>
+ <tr
v-if="shouldRenderParallelDraftRow(diffFile.file_hash, line)"
:key="`drafts-${index}`"
- :line="line"
- :diff-file-content-sha="diffFile.file_hash"
- />
+ :class="line.draftRowClasses"
+ class="notes_holder"
+ >
+ <td class="notes_line old"></td>
+ <td class="notes-content parallel old" colspan="2">
+ <div v-if="line.left && line.left.lineDraft.isDraft" class="content">
+ <draft-note :draft="line.left.lineDraft" :line="line.left" />
+ </div>
+ </td>
+ <td class="notes_line new"></td>
+ <td class="notes-content parallel new" colspan="2">
+ <div v-if="line.right && line.right.lineDraft.isDraft" class="content">
+ <draft-note :draft="line.right.lineDraft" :line="line.right" />
+ </div>
+ </td>
+ </tr>
</template>
</tbody>
</table>
diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js
index dc97d9993da..79f8c08e389 100644
--- a/app/assets/javascripts/diffs/constants.js
+++ b/app/assets/javascripts/diffs/constants.js
@@ -73,6 +73,10 @@ export const ALERT_OVERFLOW_HIDDEN = 'overflow';
export const ALERT_MERGE_CONFLICT = 'merge-conflict';
export const ALERT_COLLAPSED_FILES = 'collapsed';
+// Diff File collapse types
+export const DIFF_FILE_AUTOMATIC_COLLAPSE = 'automatic';
+export const DIFF_FILE_MANUAL_COLLAPSE = 'manual';
+
// State machine states
export const STATE_IDLING = 'idle';
export const STATE_LOADING = 'loading';
@@ -91,3 +95,11 @@ export const RENAMED_DIFF_TRANSITIONS = {
[`${STATE_ERRORED}:${TRANSITION_LOAD_START}`]: STATE_LOADING,
[`${STATE_ERRORED}:${TRANSITION_ACKNOWLEDGE_ERROR}`]: STATE_IDLING,
};
+
+// MR Diffs known events
+export const EVT_EXPAND_ALL_FILES = 'mr:diffs:expandAllFiles';
+export const EVT_PERF_MARK_FILE_TREE_START = 'mr:diffs:perf:fileTreeStart';
+export const EVT_PERF_MARK_FILE_TREE_END = 'mr:diffs:perf:fileTreeEnd';
+export const EVT_PERF_MARK_DIFF_FILES_START = 'mr:diffs:perf:filesStart';
+export const EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN = 'mr:diffs:perf:firstFileShown';
+export const EVT_PERF_MARK_DIFF_FILES_END = 'mr:diffs:perf:filesEnd';
diff --git a/app/assets/javascripts/diffs/diff_file.js b/app/assets/javascripts/diffs/diff_file.js
index 933197a2c7f..a14a30b41a9 100644
--- a/app/assets/javascripts/diffs/diff_file.js
+++ b/app/assets/javascripts/diffs/diff_file.js
@@ -1,4 +1,9 @@
-import { DIFF_FILE_SYMLINK_MODE, DIFF_FILE_DELETED_MODE } from './constants';
+import {
+ DIFF_FILE_SYMLINK_MODE,
+ DIFF_FILE_DELETED_MODE,
+ DIFF_FILE_MANUAL_COLLAPSE,
+ DIFF_FILE_AUTOMATIC_COLLAPSE,
+} from './constants';
function fileSymlinkInformation(file, fileList) {
const duplicates = fileList.filter(iteratedFile => iteratedFile.file_hash === file.file_hash);
@@ -23,6 +28,7 @@ function collapsed(file) {
return {
automaticallyCollapsed: viewer.automaticallyCollapsed || viewer.collapsed || false,
+ manuallyCollapsed: null,
};
}
@@ -37,3 +43,19 @@ export function prepareRawDiffFile({ file, allFiles }) {
return file;
}
+
+export function collapsedType(file) {
+ const isManual = typeof file.viewer?.manuallyCollapsed === 'boolean';
+
+ return isManual ? DIFF_FILE_MANUAL_COLLAPSE : DIFF_FILE_AUTOMATIC_COLLAPSE;
+}
+
+export function isCollapsed(file) {
+ const type = collapsedType(file);
+ const collapsedStates = {
+ [DIFF_FILE_AUTOMATIC_COLLAPSE]: file.viewer?.automaticallyCollapsed || false,
+ [DIFF_FILE_MANUAL_COLLAPSE]: file.viewer?.manuallyCollapsed,
+ };
+
+ return collapsedStates[type];
+}
diff --git a/app/assets/javascripts/diffs/event_hub.js b/app/assets/javascripts/diffs/event_hub.js
new file mode 100644
index 00000000000..3e0c313f5e8
--- /dev/null
+++ b/app/assets/javascripts/diffs/event_hub.js
@@ -0,0 +1,3 @@
+import eventHubFactory from '~/helpers/event_hub_factory';
+
+export default eventHubFactory();
diff --git a/app/assets/javascripts/diffs/i18n.js b/app/assets/javascripts/diffs/i18n.js
index 8699cd88a18..4ec24d452bf 100644
--- a/app/assets/javascripts/diffs/i18n.js
+++ b/app/assets/javascripts/diffs/i18n.js
@@ -1,5 +1,18 @@
import { __ } from '~/locale';
+export const GENERIC_ERROR = __('Something went wrong on our end. Please try again!');
+
export const DIFF_FILE_HEADER = {
optionsDropdownTitle: __('Options'),
};
+
+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'),
+ autoCollapsed: __('Files with large changes are collapsed by default.'),
+ expand: __('Expand file'),
+};
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index 966b706fc31..91c4c51487f 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -8,7 +8,8 @@ import { __, s__ } from '~/locale';
import { handleLocationHash, historyPushState, scrollToElement } from '~/lib/utils/common_utils';
import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility';
import TreeWorker from '../workers/tree_worker';
-import eventHub from '../../notes/event_hub';
+import notesEventHub from '../../notes/event_hub';
+import eventHub from '../event_hub';
import {
getDiffPositionByLineCode,
getNoteFormData,
@@ -40,8 +41,14 @@ import {
DIFF_WHITESPACE_COOKIE_NAME,
SHOW_WHITESPACE,
NO_SHOW_WHITESPACE,
+ DIFF_FILE_MANUAL_COLLAPSE,
+ DIFF_FILE_AUTOMATIC_COLLAPSE,
+ EVT_PERF_MARK_FILE_TREE_START,
+ EVT_PERF_MARK_FILE_TREE_END,
+ EVT_PERF_MARK_DIFF_FILES_START,
} from '../constants';
import { diffViewerModes } from '~/ide/constants';
+import { isCollapsed } from '../diff_file';
export const setBaseConfig = ({ commit }, options) => {
const {
@@ -75,6 +82,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
commit(types.SET_BATCH_LOADING, true);
commit(types.SET_RETRIEVING_BATCHES, true);
+ eventHub.$emit(EVT_PERF_MARK_DIFF_FILES_START);
const getBatch = (page = 1) =>
axios
@@ -136,9 +144,11 @@ export const fetchDiffFilesMeta = ({ commit, state }) => {
};
commit(types.SET_LOADING, true);
+ eventHub.$emit(EVT_PERF_MARK_FILE_TREE_START);
worker.addEventListener('message', ({ data }) => {
commit(types.SET_TREE_DATA, data);
+ eventHub.$emit(EVT_PERF_MARK_FILE_TREE_END);
worker.terminate();
});
@@ -212,7 +222,7 @@ export const assignDiscussionsToDiff = (
}
Vue.nextTick(() => {
- eventHub.$emit('scrollToDiscussion');
+ notesEventHub.$emit('scrollToDiscussion');
});
};
@@ -237,10 +247,17 @@ export const renderFileForDiscussionId = ({ commit, rootState, state }, discussi
}
if (file.viewer.automaticallyCollapsed) {
- eventHub.$emit(`loadCollapsedDiff/${file.file_hash}`);
+ notesEventHub.$emit(`loadCollapsedDiff/${file.file_hash}`);
scrollToElement(document.getElementById(file.file_hash));
+ } else if (file.viewer.manuallyCollapsed) {
+ commit(types.SET_FILE_COLLAPSED, {
+ filePath: file.file_path,
+ collapsed: false,
+ trigger: DIFF_FILE_AUTOMATIC_COLLAPSE,
+ });
+ notesEventHub.$emit('scrollToDiscussion');
} else {
- eventHub.$emit('scrollToDiscussion');
+ notesEventHub.$emit('scrollToDiscussion');
}
}
}
@@ -252,8 +269,7 @@ export const startRenderDiffsQueue = ({ state, commit }) => {
const nextFile = state.diffFiles.find(
file =>
!file.renderIt &&
- (file.viewer &&
- (!file.viewer.automaticallyCollapsed || file.viewer.name !== diffViewerModes.text)),
+ (file.viewer && (!isCollapsed(file) || file.viewer.name !== diffViewerModes.text)),
);
if (nextFile) {
@@ -355,10 +371,6 @@ export const loadCollapsedDiff = ({ commit, getters, state }, file) =>
});
});
-export const expandAllFiles = ({ commit }) => {
- commit(types.EXPAND_ALL_FILES);
-};
-
/**
* Toggles the file discussions after user clicked on the toggle discussions button.
*
@@ -480,7 +492,7 @@ export const setShowWhitespace = ({ commit }, { showWhitespace, pushState = fals
historyPushState(mergeUrlParams({ w }, window.location.href));
}
- eventHub.$emit('refetchDiffData');
+ notesEventHub.$emit('refetchDiffData');
};
export const toggleFileFinder = ({ commit }, visible) => {
@@ -531,15 +543,20 @@ export const setExpandedDiffLines = ({ commit, state }, { file, data }) => {
}),
}),
};
+ const unifiedDiffLinesEnabled = window.gon?.features?.unifiedDiffLines;
const currentDiffLinesKey =
- state.diffViewType === INLINE_DIFF_VIEW_TYPE ? INLINE_DIFF_LINES_KEY : PARALLEL_DIFF_LINES_KEY;
+ state.diffViewType === INLINE_DIFF_VIEW_TYPE || unifiedDiffLinesEnabled
+ ? INLINE_DIFF_LINES_KEY
+ : PARALLEL_DIFF_LINES_KEY;
const hiddenDiffLinesKey =
state.diffViewType === INLINE_DIFF_VIEW_TYPE ? PARALLEL_DIFF_LINES_KEY : INLINE_DIFF_LINES_KEY;
- commit(types.SET_HIDDEN_VIEW_DIFF_FILE_LINES, {
- filePath: file.file_path,
- lines: expandedDiffLines[hiddenDiffLinesKey],
- });
+ if (!unifiedDiffLinesEnabled) {
+ commit(types.SET_HIDDEN_VIEW_DIFF_FILE_LINES, {
+ filePath: file.file_path,
+ lines: expandedDiffLines[hiddenDiffLinesKey],
+ });
+ }
if (expandedDiffLines[currentDiffLinesKey].length > MAX_RENDERING_DIFF_LINES) {
let index = START_RENDERING_INDEX;
@@ -621,7 +638,7 @@ export function switchToFullDiffFromRenamedFile({ commit, dispatch, state }, { d
.then(({ data }) => {
const lines = data.map((line, index) =>
prepareLineForRenamedFile({
- diffViewType: state.diffViewType,
+ diffViewType: window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType,
line,
diffFile,
index,
@@ -633,6 +650,7 @@ export function switchToFullDiffFromRenamedFile({ commit, dispatch, state }, { d
viewer: {
...diffFile.alternate_viewer,
automaticallyCollapsed: false,
+ manuallyCollapsed: false,
},
});
commit(types.SET_CURRENT_VIEW_DIFF_FILE_LINES, { filePath: diffFile.file_path, lines });
@@ -641,8 +659,9 @@ export function switchToFullDiffFromRenamedFile({ commit, dispatch, state }, { d
});
}
-export const setFileCollapsed = ({ commit }, { filePath, collapsed }) =>
- commit(types.SET_FILE_COLLAPSED, { filePath, collapsed });
+export const setFileCollapsedByUser = ({ commit }, { filePath, collapsed }) => {
+ commit(types.SET_FILE_COLLAPSED, { filePath, collapsed, trigger: DIFF_FILE_MANUAL_COLLAPSE });
+};
export const setSuggestPopoverDismissed = ({ commit, state }) =>
axios
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index 91425c7825b..9ee73998177 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -8,8 +8,16 @@ export const isParallelView = state => state.diffViewType === PARALLEL_DIFF_VIEW
export const isInlineView = state => state.diffViewType === INLINE_DIFF_VIEW_TYPE;
-export const hasCollapsedFile = state =>
- state.diffFiles.some(file => file.viewer && file.viewer.automaticallyCollapsed);
+export const whichCollapsedTypes = state => {
+ const automatic = state.diffFiles.some(file => file.viewer?.automaticallyCollapsed);
+ const manual = state.diffFiles.some(file => file.viewer?.manuallyCollapsed);
+
+ return {
+ any: automatic || manual,
+ automatic,
+ manual,
+ };
+};
export const commitId = state => (state.commit && state.commit.id ? state.commit.id : null);
@@ -157,10 +165,13 @@ 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) {
+export const diffLines = state => (file, unifiedDiffComponents) => {
+ if (!unifiedDiffComponents && state.diffViewType === INLINE_DIFF_VIEW_TYPE) {
return null;
}
- return parallelizeDiffLines(file.highlighted_diff_lines || []);
+ return parallelizeDiffLines(
+ file.highlighted_diff_lines || [],
+ state.diffViewType === INLINE_DIFF_VIEW_TYPE,
+ );
};
diff --git a/app/assets/javascripts/diffs/store/mutation_types.js b/app/assets/javascripts/diffs/store/mutation_types.js
index 5dba2e9d10d..19a9e65edc9 100644
--- a/app/assets/javascripts/diffs/store/mutation_types.js
+++ b/app/assets/javascripts/diffs/store/mutation_types.js
@@ -13,7 +13,6 @@ export const SET_MERGE_REQUEST_DIFFS = 'SET_MERGE_REQUEST_DIFFS';
export const TOGGLE_LINE_HAS_FORM = 'TOGGLE_LINE_HAS_FORM';
export const ADD_CONTEXT_LINES = 'ADD_CONTEXT_LINES';
export const ADD_COLLAPSED_DIFFS = 'ADD_COLLAPSED_DIFFS';
-export const EXPAND_ALL_FILES = 'EXPAND_ALL_FILES';
export const RENDER_FILE = 'RENDER_FILE';
export const SET_LINE_DISCUSSIONS_FOR_FILE = 'SET_LINE_DISCUSSIONS_FOR_FILE';
export const REMOVE_LINE_DISCUSSIONS_FOR_FILE = 'REMOVE_LINE_DISCUSSIONS_FOR_FILE';
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index 13ecf6a997d..096c4f69439 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -1,6 +1,10 @@
import Vue from 'vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import { INLINE_DIFF_VIEW_TYPE } from '../constants';
+import {
+ DIFF_FILE_MANUAL_COLLAPSE,
+ DIFF_FILE_AUTOMATIC_COLLAPSE,
+ INLINE_DIFF_VIEW_TYPE,
+} from '../constants';
import {
findDiffFile,
addLineReferences,
@@ -16,6 +20,12 @@ function updateDiffFilesInState(state, files) {
return Object.assign(state, { diffFiles: files });
}
+function renderFile(file) {
+ Object.assign(file, {
+ renderIt: true,
+ });
+}
+
export default {
[types.SET_BASE_CONFIG](state, options) {
const {
@@ -81,9 +91,7 @@ export default {
},
[types.RENDER_FILE](state, file) {
- Object.assign(file, {
- renderIt: true,
- });
+ renderFile(file);
},
[types.SET_MERGE_REQUEST_DIFFS](state, mergeRequestDiffs) {
@@ -168,16 +176,6 @@ export default {
Object.assign(selectedFile, { ...newFileData });
},
- [types.EXPAND_ALL_FILES](state) {
- state.diffFiles.forEach(file => {
- Object.assign(file, {
- viewer: Object.assign(file.viewer, {
- automaticallyCollapsed: false,
- }),
- });
- });
- },
-
[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, { discussion, diffPositionByLineCode, hash }) {
const { latestDiff } = state;
@@ -351,11 +349,24 @@ export default {
file.isShowingFullFile = true;
file.isLoadingFullFile = false;
},
- [types.SET_FILE_COLLAPSED](state, { filePath, collapsed }) {
+ [types.SET_FILE_COLLAPSED](
+ state,
+ { filePath, collapsed, trigger = DIFF_FILE_AUTOMATIC_COLLAPSE },
+ ) {
const file = state.diffFiles.find(f => f.file_path === filePath);
if (file && file.viewer) {
- file.viewer.automaticallyCollapsed = collapsed;
+ if (trigger === DIFF_FILE_MANUAL_COLLAPSE) {
+ file.viewer.automaticallyCollapsed = false;
+ file.viewer.manuallyCollapsed = collapsed;
+ } else if (trigger === DIFF_FILE_AUTOMATIC_COLLAPSE) {
+ file.viewer.automaticallyCollapsed = collapsed;
+ file.viewer.manuallyCollapsed = null;
+ }
+ }
+
+ if (file && !collapsed) {
+ renderFile(file);
}
},
[types.SET_HIDDEN_VIEW_DIFF_FILE_LINES](state, { filePath, lines }) {
@@ -367,8 +378,13 @@ export default {
},
[types.SET_CURRENT_VIEW_DIFF_FILE_LINES](state, { filePath, lines }) {
const file = state.diffFiles.find(f => f.file_path === filePath);
- const currentDiffLinesKey =
- state.diffViewType === 'inline' ? 'highlighted_diff_lines' : 'parallel_diff_lines';
+ let currentDiffLinesKey;
+
+ if (window.gon?.features?.unifiedDiffLines || state.diffViewType === 'inline') {
+ currentDiffLinesKey = 'highlighted_diff_lines';
+ } else {
+ currentDiffLinesKey = 'parallel_diff_lines';
+ }
file[currentDiffLinesKey] = lines;
},
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index 69330ffae2f..f87f57c32c3 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -36,9 +36,12 @@ export const isMeta = line => ['match', 'new-nonewline', 'old-nonewline'].includ
*
* @param {Object[]} diffLines - inline diff lines
*
+ * @param {Boolean} inline - is inline context or not
+ *
* @returns {Object[]} parallel lines
*/
-export const parallelizeDiffLines = (diffLines = []) => {
+
+export const parallelizeDiffLines = (diffLines, inline) => {
let freeRightIndex = null;
const lines = [];
@@ -57,7 +60,7 @@ export const parallelizeDiffLines = (diffLines = []) => {
}
index += 1;
} else if (isAdded(line)) {
- if (freeRightIndex !== null) {
+ if (freeRightIndex !== null && !inline) {
// 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;
@@ -664,6 +667,7 @@ export const generateTreeList = files => {
addedLines: file.added_lines,
removedLines: file.removed_lines,
parentPath: parent ? `${parent.path}/` : '/',
+ submodule: file.submodule,
});
} else {
Object.assign(entry, {
diff --git a/app/assets/javascripts/diffs/utils/performance.js b/app/assets/javascripts/diffs/utils/performance.js
new file mode 100644
index 00000000000..dcde6f4ecc4
--- /dev/null
+++ b/app/assets/javascripts/diffs/utils/performance.js
@@ -0,0 +1,80 @@
+import { performanceMarkAndMeasure } from '~/performance/utils';
+import {
+ MR_DIFFS_MARK_FILE_TREE_START,
+ MR_DIFFS_MARK_FILE_TREE_END,
+ MR_DIFFS_MARK_DIFF_FILES_START,
+ MR_DIFFS_MARK_FIRST_DIFF_FILE_SHOWN,
+ MR_DIFFS_MARK_DIFF_FILES_END,
+ MR_DIFFS_MEASURE_FILE_TREE_DONE,
+ MR_DIFFS_MEASURE_DIFF_FILES_DONE,
+} from '../../performance/constants';
+
+import eventHub from '../event_hub';
+import {
+ EVT_PERF_MARK_FILE_TREE_START,
+ EVT_PERF_MARK_FILE_TREE_END,
+ EVT_PERF_MARK_DIFF_FILES_START,
+ EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN,
+ EVT_PERF_MARK_DIFF_FILES_END,
+} from '../constants';
+
+function treeStart() {
+ performanceMarkAndMeasure({
+ mark: MR_DIFFS_MARK_FILE_TREE_START,
+ });
+}
+
+function treeEnd() {
+ performanceMarkAndMeasure({
+ mark: MR_DIFFS_MARK_FILE_TREE_END,
+ measures: [
+ {
+ name: MR_DIFFS_MEASURE_FILE_TREE_DONE,
+ start: MR_DIFFS_MARK_FILE_TREE_START,
+ end: MR_DIFFS_MARK_FILE_TREE_END,
+ },
+ ],
+ });
+}
+
+function filesStart() {
+ performanceMarkAndMeasure({
+ mark: MR_DIFFS_MARK_DIFF_FILES_START,
+ });
+}
+
+function filesEnd() {
+ performanceMarkAndMeasure({
+ mark: MR_DIFFS_MARK_DIFF_FILES_END,
+ measures: [
+ {
+ name: MR_DIFFS_MEASURE_DIFF_FILES_DONE,
+ start: MR_DIFFS_MARK_DIFF_FILES_START,
+ end: MR_DIFFS_MARK_DIFF_FILES_END,
+ },
+ ],
+ });
+}
+
+function firstFile() {
+ performanceMarkAndMeasure({
+ mark: MR_DIFFS_MARK_FIRST_DIFF_FILE_SHOWN,
+ });
+}
+
+export const diffsApp = {
+ instrument() {
+ eventHub.$on(EVT_PERF_MARK_FILE_TREE_START, treeStart);
+ eventHub.$on(EVT_PERF_MARK_FILE_TREE_END, treeEnd);
+ eventHub.$on(EVT_PERF_MARK_DIFF_FILES_START, filesStart);
+ eventHub.$on(EVT_PERF_MARK_DIFF_FILES_END, filesEnd);
+ eventHub.$on(EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN, firstFile);
+ },
+ deinstrument() {
+ eventHub.$off(EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN, firstFile);
+ eventHub.$off(EVT_PERF_MARK_DIFF_FILES_END, filesEnd);
+ eventHub.$off(EVT_PERF_MARK_DIFF_FILES_START, filesStart);
+ eventHub.$off(EVT_PERF_MARK_FILE_TREE_END, treeEnd);
+ eventHub.$off(EVT_PERF_MARK_FILE_TREE_START, treeStart);
+ },
+};
diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js
index f65e22a31c5..69961d2e07a 100644
--- a/app/assets/javascripts/dropzone_input.js
+++ b/app/assets/javascripts/dropzone_input.js
@@ -7,6 +7,7 @@ import csrf from './lib/utils/csrf';
import axios from './lib/utils/axios_utils';
import { n__, __ } from '~/locale';
import { getFilename } from '~/lib/utils/file_upload';
+import { spriteIcon } from '~/lib/utils/common_utils';
Dropzone.autoDiscover = false;
@@ -25,7 +26,7 @@ function getErrorMessage(res) {
export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
const divHover = '<div class="div-dropzone-hover"></div>';
- const iconPaperclip = '<i class="fa fa-paperclip div-dropzone-icon"></i>';
+ const iconPaperclip = spriteIcon('paperclip', 'div-dropzone-icon s24');
const $attachButton = form.find('.button-attach-file');
const $attachingFileMessage = form.find('.attaching-file-message');
const $cancelButton = form.find('.button-cancel-uploading-files');
diff --git a/app/assets/javascripts/editor/editor_lite.js b/app/assets/javascripts/editor/editor_lite.js
index e52e64d4c2d..e7535c211db 100644
--- a/app/assets/javascripts/editor/editor_lite.js
+++ b/app/assets/javascripts/editor/editor_lite.js
@@ -6,6 +6,7 @@ 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';
+import { uuids } from '~/diffs/utils/uuids';
export default class Editor {
constructor(options = {}) {
@@ -72,7 +73,7 @@ export default class Editor {
el = undefined,
blobPath = '',
blobContent = '',
- blobGlobalId = '',
+ blobGlobalId = uuids()[0],
extensions = [],
...instanceOptions
} = {}) {
diff --git a/app/assets/javascripts/environments/components/container.vue b/app/assets/javascripts/environments/components/container.vue
index 4c6d233c4d2..e7697f14802 100644
--- a/app/assets/javascripts/environments/components/container.vue
+++ b/app/assets/javascripts/environments/components/container.vue
@@ -69,7 +69,7 @@ export default {
<div class="environments-container">
<gl-loading-icon v-if="isLoading" size="md" class="gl-mt-3" label="Loading environments" />
- <slot name="emptyState"></slot>
+ <slot name="empty-state"></slot>
<div v-if="!isLoading && environments.length > 0" class="table-holder">
<environment-table
diff --git a/app/assets/javascripts/environments/components/delete_environment_modal.vue b/app/assets/javascripts/environments/components/delete_environment_modal.vue
index 29aab268fd3..2eb2be351b3 100644
--- a/app/assets/javascripts/environments/components/delete_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/delete_environment_modal.vue
@@ -1,29 +1,35 @@
<script>
-import { GlTooltipDirective } from '@gitlab/ui';
-import GlModal from '~/vue_shared/components/gl_modal.vue';
+import { GlTooltipDirective, GlModal } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import eventHub from '../event_hub';
export default {
id: 'delete-environment-modal',
name: 'DeleteEnvironmentModal',
-
components: {
GlModal,
},
-
directives: {
GlTooltip: GlTooltipDirective,
},
-
props: {
environment: {
type: Object,
required: true,
},
},
-
computed: {
+ primaryProps() {
+ return {
+ text: s__('Environments|Delete environment'),
+ attributes: [{ variant: 'danger' }],
+ };
+ },
+ cancelProps() {
+ return {
+ text: s__('Cancel'),
+ };
+ },
confirmDeleteMessage() {
return sprintf(
s__(
@@ -35,8 +41,12 @@ export default {
false,
);
},
+ modalTitle() {
+ return sprintf(s__(`Environments|Delete '%{environmentName}'?`), {
+ environmentName: this.environment.name,
+ });
+ },
},
-
methods: {
onSubmit() {
eventHub.$emit('deleteEnvironment', this.environment);
@@ -47,20 +57,12 @@ export default {
<template>
<gl-modal
- :id="$options.id"
- :footer-primary-button-text="s__('Environments|Delete environment')"
- footer-primary-button-variant="danger"
- @submit="onSubmit"
+ :modal-id="$options.id"
+ :action-primary="primaryProps"
+ :action-cancel="cancelProps"
+ :title="modalTitle"
+ @primary="onSubmit"
>
- <template #header>
- <h4 class="modal-title d-flex mw-100">
- {{ __('Delete') }}
- <span v-gl-tooltip :title="environment.name" class="text-truncate mx-1 flex-fill">
- {{ environment.name }}?
- </span>
- </h4>
- </template>
-
<p>{{ confirmDeleteMessage }}</p>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/environments/components/environment_delete.vue b/app/assets/javascripts/environments/components/environment_delete.vue
index 039b40a3596..75d92d3295d 100644
--- a/app/assets/javascripts/environments/components/environment_delete.vue
+++ b/app/assets/javascripts/environments/components/environment_delete.vue
@@ -1,21 +1,20 @@
<script>
/**
* Renders the delete button that allows deleting a stopped environment.
- * Used in the environments table and the environment detail view.
+ * Used in the environments table.
*/
-import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { GlTooltipDirective, GlButton, GlModalDirective } from '@gitlab/ui';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
-import LoadingButton from '../../vue_shared/components/loading_button.vue';
export default {
components: {
- GlIcon,
- LoadingButton,
+ GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
+ GlModalDirective,
},
props: {
environment: {
@@ -54,16 +53,16 @@ export default {
};
</script>
<template>
- <loading-button
+ <gl-button
v-gl-tooltip="{ id: $options.deleteEnvironmentTooltipId }"
+ v-gl-modal-directive="'delete-environment-modal'"
:loading="isLoading"
:title="title"
:aria-label="title"
- container-class="btn btn-danger d-none d-md-block"
- data-toggle="modal"
- data-target="#delete-environment-modal"
+ class="gl-display-none gl-display-md-block"
+ variant="danger"
+ category="primary"
+ icon="remove"
@click="onClick"
- >
- <gl-icon name="remove" />
- </loading-button>
+ />
</template>
diff --git a/app/assets/javascripts/environments/components/environment_stop.vue b/app/assets/javascripts/environments/components/environment_stop.vue
index ff74f81c98e..8e100623199 100644
--- a/app/assets/javascripts/environments/components/environment_stop.vue
+++ b/app/assets/javascripts/environments/components/environment_stop.vue
@@ -4,7 +4,7 @@
* Used in environments table.
*/
-import { GlTooltipDirective, GlButton } from '@gitlab/ui';
+import { GlTooltipDirective, GlButton, GlModalDirective } from '@gitlab/ui';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
@@ -14,6 +14,7 @@ export default {
},
directives: {
GlTooltip: GlTooltipDirective,
+ GlModalDirective,
},
props: {
environment: {
@@ -54,14 +55,13 @@ export default {
<template>
<gl-button
v-gl-tooltip="{ id: $options.stopEnvironmentTooltipId }"
+ v-gl-modal-directive="'stop-environment-modal'"
:loading="isLoading"
:title="title"
:aria-label="title"
icon="stop"
category="primary"
variant="danger"
- data-toggle="modal"
- data-target="#stop-environment-modal"
@click="onClick"
/>
</template>
diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue
index 9bafc7ed153..c1b9ba755a6 100644
--- a/app/assets/javascripts/environments/components/environments_app.vue
+++ b/app/assets/javascripts/environments/components/environments_app.vue
@@ -228,7 +228,7 @@ export default {
:deploy-boards-help-path="deployBoardsHelpPath"
@onChangePage="onChangePage"
>
- <template v-if="!isLoading && state.environments.length === 0" #emptyState>
+ <template v-if="!isLoading && state.environments.length === 0" #empty-state>
<empty-state :help-path="helpPagePath" />
</template>
</container>
diff --git a/app/assets/javascripts/environments/components/stop_environment_modal.vue b/app/assets/javascripts/environments/components/stop_environment_modal.vue
index f0dafe0620e..0832822520d 100644
--- a/app/assets/javascripts/environments/components/stop_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/stop_environment_modal.vue
@@ -1,15 +1,14 @@
<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { GlSprintf, GlTooltipDirective } from '@gitlab/ui';
-import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
+import { GlSprintf, GlTooltipDirective, GlModal } from '@gitlab/ui';
import eventHub from '../event_hub';
+import { __, s__ } from '~/locale';
export default {
id: 'stop-environment-modal',
name: 'StopEnvironmentModal',
components: {
- GlModal: DeprecatedModal2,
+ GlModal,
GlSprintf,
},
@@ -24,6 +23,20 @@ export default {
},
},
+ computed: {
+ primaryProps() {
+ return {
+ text: s__('Environments|Stop environment'),
+ attributes: [{ variant: 'danger' }],
+ };
+ },
+ cancelProps() {
+ return {
+ text: __('Cancel'),
+ };
+ },
+ },
+
methods: {
onSubmit() {
eventHub.$emit('stopEnvironment', this.environment);
@@ -34,18 +47,23 @@ export default {
<template>
<gl-modal
- :id="$options.id"
- :footer-primary-button-text="s__('Environments|Stop environment')"
- footer-primary-button-variant="danger"
- @submit="onSubmit"
+ :modal-id="$options.id"
+ :action-primary="primaryProps"
+ :action-cancel="cancelProps"
+ @primary="onSubmit"
>
- <template #header>
- <h4 class="modal-title d-flex mw-100">
- Stopping
- <span v-gl-tooltip :title="environment.name" class="text-truncate ml-1 mr-1 flex-fill">
- {{ environment.name }}?
- </span>
- </h4>
+ <template #modal-title>
+ <gl-sprintf :message="s__('Environments|Stopping %{environmentName}')">
+ <template #environmentName>
+ <span
+ v-gl-tooltip
+ :title="environment.name"
+ class="gl-text-truncate gl-ml-2 gl-mr-2 gl-flex-fill"
+ >
+ {{ environment.name }}?
+ </span>
+ </template>
+ </gl-sprintf>
</template>
<p>{{ s__('Environments|Are you sure you want to stop this environment?') }}</p>
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index 5dee3ef3ffe..8272260705b 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -8,9 +8,9 @@ import {
GlBadge,
GlAlert,
GlSprintf,
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
- GlDeprecatedDropdownDivider,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
GlIcon,
} from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash';
@@ -43,9 +43,9 @@ export default {
GlBadge,
GlAlert,
GlSprintf,
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
- GlDeprecatedDropdownDivider,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
TimeAgoTooltip,
},
directives: {
@@ -331,38 +331,38 @@ export default {
</gl-button>
</form>
</div>
- <gl-deprecated-dropdown
+ <gl-dropdown
text="Options"
class="error-details-options d-md-none"
right
:disabled="issueUpdateInProgress"
>
- <gl-deprecated-dropdown-item
+ <gl-dropdown-item
data-qa-selector="update_ignore_status_button"
@click="onIgnoreStatusUpdate"
- >{{ ignoreBtnLabel }}</gl-deprecated-dropdown-item
+ >{{ ignoreBtnLabel }}</gl-dropdown-item
>
- <gl-deprecated-dropdown-item
+ <gl-dropdown-item
data-qa-selector="update_resolve_status_button"
@click="onResolveStatusUpdate"
- >{{ resolveBtnLabel }}</gl-deprecated-dropdown-item
+ >{{ resolveBtnLabel }}</gl-dropdown-item
>
- <gl-deprecated-dropdown-divider />
- <gl-deprecated-dropdown-item
+ <gl-dropdown-divider />
+ <gl-dropdown-item
v-if="error.gitlabIssuePath"
data-qa-selector="view_issue_button"
:href="error.gitlabIssuePath"
variant="success"
- >{{ __('View issue') }}</gl-deprecated-dropdown-item
+ >{{ __('View issue') }}</gl-dropdown-item
>
- <gl-deprecated-dropdown-item
+ <gl-dropdown-item
v-if="!error.gitlabIssuePath"
:loading="issueCreationInProgress"
data-qa-selector="create_issue_button"
@click="createIssue"
- >{{ __('Create issue') }}</gl-deprecated-dropdown-item
+ >{{ __('Create issue') }}</gl-dropdown-item
>
- </gl-deprecated-dropdown>
+ </gl-dropdown>
</div>
</div>
<div>
diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
index da41dc4c9d9..7ccb6253508 100644
--- a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
+++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
@@ -8,9 +8,9 @@ import {
GlLoadingIcon,
GlTable,
GlFormInput,
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
- GlDeprecatedDropdownDivider,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
GlTooltipDirective,
GlPagination,
} from '@gitlab/ui';
@@ -72,9 +72,9 @@ export default {
components: {
GlEmptyState,
GlButton,
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
- GlDeprecatedDropdownDivider,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
GlIcon,
GlLink,
GlLoadingIcon,
@@ -233,30 +233,30 @@ export default {
>
<div class="search-box flex-fill mb-1 mb-md-0">
<div class="filtered-search-box mb-0">
- <gl-deprecated-dropdown
+ <gl-dropdown
:text="__('Recent searches')"
class="filtered-search-history-dropdown-wrapper"
- toggle-class="filtered-search-history-dropdown-toggle-button"
+ toggle-class="filtered-search-history-dropdown-toggle-button gl-shadow-none! gl-border-r-gray-200! gl-border-1! gl-rounded-0!"
:disabled="loading"
>
<div v-if="!$options.hasLocalStorage" class="px-3">
{{ __('This feature requires local storage to be enabled') }}
</div>
<template v-else-if="recentSearches.length > 0">
- <gl-deprecated-dropdown-item
+ <gl-dropdown-item
v-for="searchQuery in recentSearches"
:key="searchQuery"
@click="setSearchText(searchQuery)"
>{{ searchQuery }}
- </gl-deprecated-dropdown-item>
- <gl-deprecated-dropdown-divider />
- <gl-deprecated-dropdown-item ref="clearRecentSearches" @click="clearRecentSearches"
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ <gl-dropdown-item ref="clearRecentSearches" @click="clearRecentSearches"
>{{ __('Clear recent searches') }}
- </gl-deprecated-dropdown-item>
+ </gl-dropdown-item>
</template>
<div v-else class="px-3">{{ __("You don't have any recent searches") }}</div>
- </gl-deprecated-dropdown>
- <div class="filtered-search-input-container flex-fill">
+ </gl-dropdown>
+ <div class="filtered-search-input-container gl-flex-fill-1">
<gl-form-input
v-model="errorSearchQuery"
class="pl-2 filtered-search"
@@ -280,49 +280,44 @@ export default {
</div>
</div>
- <gl-deprecated-dropdown
+ <gl-dropdown
:text="$options.statusFilters[statusFilter]"
class="status-dropdown mx-md-1 mb-1 mb-md-0"
- menu-class="dropdown"
:disabled="loading"
+ right
>
- <gl-deprecated-dropdown-item
+ <gl-dropdown-item
v-for="(label, status) in $options.statusFilters"
:key="status"
@click="filterErrors(status, label)"
>
<span class="d-flex">
<gl-icon
- class="flex-shrink-0 append-right-4"
+ class="gl-new-dropdown-item-check-icon"
:class="{ invisible: !isCurrentStatusFilter(status) }"
name="mobile-issue-close"
/>
{{ label }}
</span>
- </gl-deprecated-dropdown-item>
- </gl-deprecated-dropdown>
+ </gl-dropdown-item>
+ </gl-dropdown>
- <gl-deprecated-dropdown
- :text="$options.sortFields[sortField]"
- left
- :disabled="loading"
- menu-class="dropdown"
- >
- <gl-deprecated-dropdown-item
+ <gl-dropdown :text="$options.sortFields[sortField]" right :disabled="loading">
+ <gl-dropdown-item
v-for="(label, field) in $options.sortFields"
:key="field"
@click="sortByField(field)"
>
<span class="d-flex">
<gl-icon
- class="flex-shrink-0 append-right-4"
+ class="gl-new-dropdown-item-check-icon"
:class="{ invisible: !isCurrentSortField(field) }"
name="mobile-issue-close"
/>
{{ label }}
</span>
- </gl-deprecated-dropdown-item>
- </gl-deprecated-dropdown>
+ </gl-dropdown-item>
+ </gl-dropdown>
</div>
<div v-if="loading" class="py-3">
diff --git a/app/assets/javascripts/error_tracking_settings/components/project_dropdown.vue b/app/assets/javascripts/error_tracking_settings/components/project_dropdown.vue
index 561b2565880..2323370a3aa 100644
--- a/app/assets/javascripts/error_tracking_settings/components/project_dropdown.vue
+++ b/app/assets/javascripts/error_tracking_settings/components/project_dropdown.vue
@@ -1,11 +1,11 @@
<script>
-import { GlDeprecatedDropdown, GlDeprecatedDropdownItem } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { getDisplayName } from '../utils';
export default {
components: {
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
},
props: {
dropdownLabel: {
@@ -52,22 +52,22 @@ export default {
<div :class="{ 'gl-show-field-errors': isProjectInvalid }">
<label class="label-bold" for="project-dropdown">{{ __('Project') }}</label>
<div class="row">
- <gl-deprecated-dropdown
+ <gl-dropdown
id="project-dropdown"
class="col-8 col-md-9 gl-pr-0"
:disabled="!hasProjects"
menu-class="w-100 mw-100"
- toggle-class="dropdown-menu-toggle w-100 gl-field-error-outline"
+ toggle-class="dropdown-menu-toggle gl-field-error-outline"
:text="dropdownLabel"
>
- <gl-deprecated-dropdown-item
+ <gl-dropdown-item
v-for="project in projects"
:key="`${project.organizationSlug}.${project.slug}`"
class="w-100"
@click="$emit('select-project', project)"
- >{{ getDisplayName(project) }}</gl-deprecated-dropdown-item
+ >{{ getDisplayName(project) }}</gl-dropdown-item
>
- </gl-deprecated-dropdown>
+ </gl-dropdown>
</div>
<p v-if="isProjectInvalid" class="js-project-dropdown-error gl-field-error">
{{ invalidProjectLabel }}
diff --git a/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue b/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue
index 686399843dd..bf47d7cf7c0 100644
--- a/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue
+++ b/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue
@@ -2,6 +2,7 @@
import {
GlFormGroup,
GlFormInput,
+ GlFormInputGroup,
GlModal,
GlTooltipDirective,
GlLoadingIcon,
@@ -17,6 +18,7 @@ export default {
components: {
GlFormGroup,
GlFormInput,
+ GlFormInputGroup,
GlModal,
ModalCopyButton,
GlIcon,
@@ -167,63 +169,47 @@ export default {
</template>
</gl-sprintf>
</callout>
- <div class="form-group">
- <label for="api_url" class="label-bold">{{ $options.translations.apiUrlLabelText }}</label>
- <div class="input-group">
- <input
- id="api_url"
- :value="unleashApiUrl"
- readonly
- class="form-control"
- type="text"
- name="api_url"
- />
- <span class="input-group-append">
+ <gl-form-group :label="$options.translations.apiUrlLabelText" label-for="api-url">
+ <gl-form-input-group id="api-url" :value="unleashApiUrl" readonly type="text" name="api-url">
+ <template #append>
<modal-copy-button
:text="unleashApiUrl"
:title="$options.translations.apiUrlCopyText"
:modal-id="modalId"
- class="input-group-text"
/>
- </span>
- </div>
- </div>
- <div class="form-group">
- <label for="instance_id" class="label-bold">{{
- $options.translations.instanceIdLabelText
- }}</label>
- <div class="input-group">
- <input
+ </template>
+ </gl-form-input-group>
+ </gl-form-group>
+ <gl-form-group :label="$options.translations.instanceIdLabelText" label-for="instance_id">
+ <gl-form-input-group>
+ <gl-form-input
id="instance_id"
:value="instanceId"
- class="form-control"
type="text"
name="instance_id"
readonly
:disabled="isRotating"
/>
-
<gl-loading-icon
v-if="isRotating"
- class="position-absolute align-self-center instance-id-loading-icon"
+ class="gl-absolute gl-align-self-center gl-right-5 gl-mr-7"
/>
- <div class="input-group-append">
+ <template #append>
<modal-copy-button
:text="instanceId"
:title="$options.translations.instanceIdCopyText"
:modal-id="modalId"
:disabled="isRotating"
- class="input-group-text"
/>
- </div>
- </div>
- </div>
+ </template>
+ </gl-form-input-group>
+ </gl-form-group>
<div
v-if="hasRotateError"
- class="text-danger d-flex align-items-center font-weight-normal mb-2"
+ class="gl-text-red-500 gl-display-flex gl-align-items-center gl-font-weight-normal gl-mb-3"
>
- <gl-icon name="warning" class="mr-1" />
+ <gl-icon name="warning" class="gl-mr-2" />
<span>{{ $options.translations.instanceIdRegenerateError }}</span>
</div>
<callout
diff --git a/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue b/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
index 26b18f9bf5a..9ec65bb0b43 100644
--- a/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
+++ b/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
@@ -103,7 +103,7 @@ export default {
>
{{ $options.translations.newFlagAlert }}
</gl-alert>
- <gl-loading-icon v-if="isLoading" />
+ <gl-loading-icon v-if="isLoading" size="xl" class="gl-mt-7" />
<template v-else-if="!isLoading && !hasError">
<gl-alert v-if="deprecatedAndEditable" variant="warning" :dismissible="false" class="gl-my-5">
diff --git a/app/assets/javascripts/feature_flags/components/feature_flags.vue b/app/assets/javascripts/feature_flags/components/feature_flags.vue
index eb7046a3d9b..340cf68793f 100644
--- a/app/assets/javascripts/feature_flags/components/feature_flags.vue
+++ b/app/assets/javascripts/feature_flags/components/feature_flags.vue
@@ -278,7 +278,7 @@ export default {
/>
</feature-flags-tab>
<template #tabs-end>
- <div
+ <li
class="gl-display-none gl-display-md-flex gl-align-items-center gl-flex-fill-1 gl-justify-content-end"
>
<gl-button
@@ -313,7 +313,7 @@ export default {
>
{{ s__('FeatureFlags|New feature flag') }}
</gl-button>
- </div>
+ </li>
</template>
</gl-tabs>
</div>
diff --git a/app/assets/javascripts/feature_flags/components/form.vue b/app/assets/javascripts/feature_flags/components/form.vue
index 3c1944d91bd..36ebf893486 100644
--- a/app/assets/javascripts/feature_flags/components/form.vue
+++ b/app/assets/javascripts/feature_flags/components/form.vue
@@ -3,7 +3,7 @@ import Vue from 'vue';
import { memoize, isString, cloneDeep, isNumber, uniqueId } from 'lodash';
import {
GlButton,
- GlDeprecatedBadge as GlBadge,
+ GlBadge,
GlTooltip,
GlTooltipDirective,
GlFormTextarea,
@@ -11,10 +11,8 @@ import {
GlSprintf,
GlIcon,
} from '@gitlab/ui';
-import Api from '~/api';
import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
import { s__ } from '~/locale';
-import { deprecatedCreateFlash as flash, FLASH_TYPES } from '~/flash';
import featureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ToggleButton from '~/vue_shared/components/toggle_button.vue';
import EnvironmentsDropdown from './environments_dropdown.vue';
@@ -89,7 +87,6 @@ export default {
},
},
inject: {
- projectId: {},
featureFlagIssuesEndpoint: {
default: '',
},
@@ -124,7 +121,6 @@ export default {
formStrategies: cloneDeep(this.strategies),
newScope: '',
- userLists: [],
};
},
computed: {
@@ -155,17 +151,6 @@ export default {
);
},
},
- mounted() {
- if (this.supportsStrategies) {
- Api.fetchFeatureFlagUserLists(this.projectId)
- .then(({ data }) => {
- this.userLists = data;
- })
- .catch(() => {
- flash(s__('FeatureFlags|There was an error retrieving user lists'), FLASH_TYPES.WARNING);
- });
- }
- },
methods: {
keyFor(strategy) {
if (strategy.id) {
@@ -346,7 +331,6 @@ export default {
:key="keyFor(strategy)"
:strategy="strategy"
:index="index"
- :user-lists="userLists"
@change="onFormStrategyChange($event, index)"
@delete="deleteStrategy(strategy)"
/>
@@ -488,7 +472,9 @@ export default {
:target="rolloutPercentageId(index)"
>
{{
- s__('FeatureFlags|Percent rollout must be a whole number between 0 and 100')
+ s__(
+ 'FeatureFlags|Percent rollout must be an integer number between 0 and 100',
+ )
}}
</gl-tooltip>
<span class="ml-1">%</span>
diff --git a/app/assets/javascripts/feature_flags/components/strategies/flexible_rollout.vue b/app/assets/javascripts/feature_flags/components/strategies/flexible_rollout.vue
index 020a0d43096..4daf8b4e6bf 100644
--- a/app/assets/javascripts/feature_flags/components/strategies/flexible_rollout.vue
+++ b/app/assets/javascripts/feature_flags/components/strategies/flexible_rollout.vue
@@ -17,8 +17,8 @@ export default {
},
},
i18n: {
- percentageDescription: __('Enter a whole number between 0 and 100'),
- percentageInvalid: __('Percent rollout must be a whole number between 0 and 100'),
+ percentageDescription: __('Enter an integer number number between 0 and 100'),
+ percentageInvalid: __('Percent rollout must be an integer number between 0 and 100'),
percentageLabel: __('Percentage'),
stickinessDescription: __('Consistency guarantee method'),
stickinessLabel: __('Based on'),
diff --git a/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue b/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue
index ec97e8b1350..6a57e9a8759 100644
--- a/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue
+++ b/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue
@@ -1,11 +1,20 @@
<script>
-import { GlFormSelect } from '@gitlab/ui';
+import { debounce } from 'lodash';
+import { createNamespacedHelpers } from 'vuex';
+import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
import { s__ } from '~/locale';
import ParameterFormGroup from './parameter_form_group.vue';
+const { mapActions, mapGetters, mapState } = createNamespacedHelpers('userLists');
+
+const { fetchUserLists, setFilter } = mapActions(['fetchUserLists', 'setFilter']);
+
export default {
components: {
- GlFormSelect,
+ GlDropdown,
+ GlDropdownItem,
+ GlLoadingIcon,
+ GlSearchBoxByType,
ParameterFormGroup,
},
props: {
@@ -13,34 +22,40 @@ export default {
required: true,
type: Object,
},
- userLists: {
- required: false,
- type: Array,
- default: () => [],
- },
},
translations: {
- rolloutUserListLabel: s__('FeatureFlag|List'),
+ rolloutUserListLabel: s__('FeatureFlag|User List'),
rolloutUserListDescription: s__('FeatureFlag|Select a user list'),
rolloutUserListNoListError: s__('FeatureFlag|There are no configured user lists'),
+ defaultDropdownText: s__('FeatureFlags|No user list selected'),
},
computed: {
- userListOptions() {
- return this.userLists.map(({ name, id }) => ({ value: id, text: name }));
- },
- hasUserLists() {
- return this.userListOptions.length > 0;
- },
+ ...mapGetters(['hasUserLists', 'isLoading', 'hasError', 'userListOptions']),
+ ...mapState(['filter', 'userLists']),
userListId() {
- return this.strategy?.userListId ?? '';
+ return this.strategy?.userList?.id ?? '';
},
+ dropdownText() {
+ return this.strategy?.userList?.name ?? this.$options.translations.defaultDropdownText;
+ },
+ },
+ mounted() {
+ fetchUserLists.apply(this);
},
methods: {
+ setFilter: debounce(setFilter, 250),
+ fetchUserLists: debounce(fetchUserLists, 250),
onUserListChange(list) {
this.$emit('change', {
- userListId: list,
+ userList: list,
});
},
+ isSelectedUserList({ id }) {
+ return id === this.userListId;
+ },
+ setFocus() {
+ this.$refs.searchBox.focusInput();
+ },
},
};
</script>
@@ -52,12 +67,26 @@ export default {
:description="hasUserLists ? $options.translations.rolloutUserListDescription : ''"
>
<template #default="{ inputId }">
- <gl-form-select
- :id="inputId"
- :value="userListId"
- :options="userListOptions"
- @change="onUserListChange"
- />
+ <gl-dropdown :id="inputId" :text="dropdownText" @shown="setFocus">
+ <gl-search-box-by-type
+ ref="searchBox"
+ class="gl-m-3"
+ :value="filter"
+ @input="setFilter"
+ @focus="fetchUserLists"
+ @keyup="fetchUserLists"
+ />
+ <gl-loading-icon v-if="isLoading" />
+ <gl-dropdown-item
+ v-for="list in userLists"
+ :key="list.id"
+ :is-checked="isSelectedUserList(list)"
+ is-check-item
+ @click="onUserListChange(list)"
+ >
+ {{ list.name }}
+ </gl-dropdown-item>
+ </gl-dropdown>
</template>
</parameter-form-group>
</template>
diff --git a/app/assets/javascripts/feature_flags/components/strategies/percent_rollout.vue b/app/assets/javascripts/feature_flags/components/strategies/percent_rollout.vue
index d262769c891..91e1b85d66e 100644
--- a/app/assets/javascripts/feature_flags/components/strategies/percent_rollout.vue
+++ b/app/assets/javascripts/feature_flags/components/strategies/percent_rollout.vue
@@ -16,9 +16,9 @@ export default {
},
},
i18n: {
- rolloutPercentageDescription: __('Enter a whole number between 0 and 100'),
+ rolloutPercentageDescription: __('Enter an integer number between 0 and 100'),
rolloutPercentageInvalid: s__(
- 'FeatureFlags|Percent rollout must be a whole number between 0 and 100',
+ 'FeatureFlags|Percent rollout must be an integer number between 0 and 100',
),
rolloutPercentageLabel: s__('FeatureFlag|Percentage'),
},
diff --git a/app/assets/javascripts/feature_flags/edit.js b/app/assets/javascripts/feature_flags/edit.js
index b4d2111acf3..05a9bbce654 100644
--- a/app/assets/javascripts/feature_flags/edit.js
+++ b/app/assets/javascripts/feature_flags/edit.js
@@ -22,7 +22,7 @@ export default () => {
} = el.dataset;
return new Vue({
- store: createStore({ endpoint, path: featureFlagsPath }),
+ store: createStore({ endpoint, projectId, path: featureFlagsPath }),
el,
provide: {
environmentsScopeDocsPath,
diff --git a/app/assets/javascripts/feature_flags/new.js b/app/assets/javascripts/feature_flags/new.js
index a1efbd87ec4..8e18213cc03 100644
--- a/app/assets/javascripts/feature_flags/new.js
+++ b/app/assets/javascripts/feature_flags/new.js
@@ -22,7 +22,7 @@ export default () => {
return new Vue({
el,
- store: createStore({ endpoint, path: featureFlagsPath }),
+ store: createStore({ endpoint, projectId, path: featureFlagsPath }),
provide: {
environmentsScopeDocsPath,
strategyTypeDocsPagePath,
diff --git a/app/assets/javascripts/feature_flags/store/edit/index.js b/app/assets/javascripts/feature_flags/store/edit/index.js
index f737e0517fc..81edc791924 100644
--- a/app/assets/javascripts/feature_flags/store/edit/index.js
+++ b/app/assets/javascripts/feature_flags/store/edit/index.js
@@ -1,4 +1,5 @@
import Vuex from 'vuex';
+import userLists from '../gitlab_user_list';
import state from './state';
import * as actions from './actions';
import mutations from './mutations';
@@ -8,4 +9,7 @@ export default data =>
actions,
mutations,
state: state(data),
+ modules: {
+ userLists: userLists(data),
+ },
});
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js
new file mode 100644
index 00000000000..d4587713fed
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js
@@ -0,0 +1,17 @@
+import Api from '~/api';
+import * as types from './mutation_types';
+
+const getErrorMessages = error => [].concat(error?.response?.data?.message ?? error.message);
+
+export const fetchUserLists = ({ commit, state: { filter, projectId } }) => {
+ commit(types.FETCH_USER_LISTS);
+
+ return Api.searchFeatureFlagUserLists(projectId, filter)
+ .then(({ data }) => commit(types.RECEIVE_USER_LISTS_SUCCESS, data))
+ .catch(error => commit(types.RECEIVE_USER_LISTS_ERROR, getErrorMessages(error)));
+};
+
+export const setFilter = ({ commit, dispatch }, filter) => {
+ commit(types.SET_FILTER, filter);
+ return dispatch('fetchUserLists');
+};
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/getters.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/getters.js
new file mode 100644
index 00000000000..164b0980120
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/getters.js
@@ -0,0 +1,11 @@
+import statuses from './status';
+
+export const userListOptions = ({ userLists }) =>
+ userLists.map(({ name, id }) => ({ value: id, text: name }));
+
+export const hasUserLists = ({ userLists, status }) =>
+ [statuses.START, statuses.LOADING].indexOf(status) > -1 || userLists.length > 0;
+
+export const isLoading = ({ status }) => status === statuses.LOADING;
+
+export const hasError = ({ status }) => status === statuses.ERROR;
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js
new file mode 100644
index 00000000000..d25b574981f
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js
@@ -0,0 +1,12 @@
+import state from './state';
+import mutations from './mutations';
+import * as actions from './actions';
+import * as getters from './getters';
+
+export default data => ({
+ state: state(data),
+ actions,
+ getters,
+ mutations,
+ namespaced: true,
+});
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutation_types.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutation_types.js
new file mode 100644
index 00000000000..0fe12f06785
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutation_types.js
@@ -0,0 +1,5 @@
+export const FETCH_USER_LISTS = 'FETCH_USER_LISTS';
+export const RECEIVE_USER_LISTS_SUCCESS = 'RECEIVE_USER_LISTS_SUCCESS';
+export const RECEIVE_USER_LISTS_ERROR = 'RECEIVE_USER_LISTS_ERROR';
+
+export const SET_FILTER = 'SET_FILTER';
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js
new file mode 100644
index 00000000000..bd7c6f68009
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js
@@ -0,0 +1,19 @@
+import statuses from './status';
+import * as types from './mutation_types';
+
+export default {
+ [types.FETCH_USER_LISTS](state) {
+ state.status = statuses.LOADING;
+ },
+ [types.RECEIVE_USER_LISTS_SUCCESS](state, lists) {
+ state.userLists = lists;
+ state.status = statuses.IDLE;
+ },
+ [types.RECEIVE_USER_LISTS_ERROR](state, error) {
+ state.error = error;
+ state.status = statuses.ERROR;
+ },
+ [types.SET_FILTER](state, filter) {
+ state.filter = filter;
+ },
+};
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/state.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/state.js
new file mode 100644
index 00000000000..2664ec794fc
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/state.js
@@ -0,0 +1,9 @@
+import statuses from './status';
+
+export default ({ projectId }) => ({
+ projectId,
+ userLists: [],
+ filter: '',
+ status: statuses.START,
+ error: '',
+});
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/status.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/status.js
new file mode 100644
index 00000000000..67f153eb58e
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/status.js
@@ -0,0 +1,6 @@
+export default {
+ START: 'START',
+ LOADING: 'LOADING',
+ IDLE: 'IDLE',
+ ERROR: 'ERROR',
+};
diff --git a/app/assets/javascripts/feature_flags/store/helpers.js b/app/assets/javascripts/feature_flags/store/helpers.js
index db6da815abf..d42e5c504db 100644
--- a/app/assets/javascripts/feature_flags/store/helpers.js
+++ b/app/assets/javascripts/feature_flags/store/helpers.js
@@ -174,7 +174,7 @@ export const mapStrategiesToViewModel = strategiesFromRails =>
id: s.id,
name: s.name,
parameters: mapStrategiesParametersToViewModel(s.parameters),
- userListId: s.user_list?.id,
+ userList: s.user_list,
// eslint-disable-next-line no-underscore-dangle
shouldBeDestroyed: Boolean(s._destroy),
scopes: mapStrategyScopesToView(s.scopes),
@@ -197,7 +197,7 @@ const mapStrategyToRails = strategy => {
};
if (strategy.name === ROLLOUT_STRATEGY_GITLAB_USER_LIST) {
- mappedStrategy.user_list_id = strategy.userListId;
+ mappedStrategy.user_list_id = strategy.userList.id;
}
return mappedStrategy;
};
diff --git a/app/assets/javascripts/feature_flags/store/new/index.js b/app/assets/javascripts/feature_flags/store/new/index.js
index f737e0517fc..81edc791924 100644
--- a/app/assets/javascripts/feature_flags/store/new/index.js
+++ b/app/assets/javascripts/feature_flags/store/new/index.js
@@ -1,4 +1,5 @@
import Vuex from 'vuex';
+import userLists from '../gitlab_user_list';
import state from './state';
import * as actions from './actions';
import mutations from './mutations';
@@ -8,4 +9,7 @@ export default data =>
actions,
mutations,
state: state(data),
+ modules: {
+ userLists: userLists(data),
+ },
});
diff --git a/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
index 51077296e20..7d4df25816b 100644
--- a/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
+++ b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
@@ -12,6 +12,7 @@ export default (IssuableTokenKeys, disableTargetBranchFilter = false) => {
tag: __('Yes or No'),
lowercaseValueOnSubmit: true,
capitalizeTokenValue: true,
+ hideNotEqual: true,
},
conditions: [
{
@@ -30,20 +31,6 @@ export default (IssuableTokenKeys, disableTargetBranchFilter = false) => {
value: __('No'),
operator: '=',
},
- {
- url: 'not[wip]=yes',
- replacementUrl: 'not[draft]=yes',
- tokenKey: 'draft',
- value: __('Yes'),
- operator: '!=',
- },
- {
- url: 'not[wip]=no',
- replacementUrl: 'not[draft]=no',
- tokenKey: 'draft',
- value: __('No'),
- operator: '!=',
- },
],
};
@@ -109,43 +96,41 @@ export default (IssuableTokenKeys, disableTargetBranchFilter = false) => {
IssuableTokenKeys.tokenKeysWithAlternative.splice(tokenPosition, 0, ...[approvedBy.token]);
IssuableTokenKeys.conditions.push(...approvedBy.condition);
- if (gon?.features?.deploymentFilters) {
- const environmentToken = {
- formattedKey: __('Environment'),
- key: 'environment',
- type: 'string',
- param: '',
- symbol: '',
- icon: 'cloud-gear',
- tag: 'environment',
- };
+ const environmentToken = {
+ formattedKey: __('Environment'),
+ key: 'environment',
+ type: 'string',
+ param: '',
+ symbol: '',
+ icon: 'cloud-gear',
+ tag: 'environment',
+ };
- const deployedBeforeToken = {
- formattedKey: __('Deployed-before'),
- key: 'deployed-before',
- type: 'string',
- param: '',
- symbol: '',
- icon: 'clock',
- tag: 'deployed_before',
- };
+ const deployedBeforeToken = {
+ formattedKey: __('Deployed-before'),
+ key: 'deployed-before',
+ type: 'string',
+ param: '',
+ symbol: '',
+ icon: 'clock',
+ tag: 'deployed_before',
+ };
- const deployedAfterToken = {
- formattedKey: __('Deployed-after'),
- key: 'deployed-after',
- type: 'string',
- param: '',
- symbol: '',
- icon: 'clock',
- tag: 'deployed_after',
- };
+ const deployedAfterToken = {
+ formattedKey: __('Deployed-after'),
+ key: 'deployed-after',
+ type: 'string',
+ param: '',
+ symbol: '',
+ icon: 'clock',
+ tag: 'deployed_after',
+ };
- IssuableTokenKeys.tokenKeys.push(environmentToken, deployedBeforeToken, deployedAfterToken);
+ IssuableTokenKeys.tokenKeys.push(environmentToken, deployedBeforeToken, deployedAfterToken);
- IssuableTokenKeys.tokenKeysWithAlternative.push(
- environmentToken,
- deployedBeforeToken,
- deployedAfterToken,
- );
- }
+ IssuableTokenKeys.tokenKeysWithAlternative.push(
+ environmentToken,
+ deployedBeforeToken,
+ deployedAfterToken,
+ );
};
diff --git a/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js b/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
index 4652dfe71c3..30f412e590f 100644
--- a/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
+++ b/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
@@ -22,7 +22,7 @@ export default class DropdownAjaxFilter extends FilteredSearchDropdown {
ajaxFilterConfig() {
return {
- endpoint: `${gon.relative_url_root || ''}${this.endpoint}`,
+ endpoint: this.endpoint,
searchKey: 'search',
searchValueFunction: this.getSearchInput.bind(this),
loadingTemplate: this.loadingTemplate,
@@ -33,9 +33,11 @@ export default class DropdownAjaxFilter extends FilteredSearchDropdown {
}
itemClicked(e) {
- super.itemClicked(e, selected =>
- selected.querySelector('.dropdown-light-content').innerText.trim(),
- );
+ super.itemClicked(e, selected => {
+ const title = selected.querySelector('.dropdown-light-content').innerText.trim();
+
+ return DropdownUtils.getEscapedText(title);
+ });
}
renderContent(forceShowList = false) {
diff --git a/app/assets/javascripts/filtered_search/dropdown_operator.js b/app/assets/javascripts/filtered_search/dropdown_operator.js
index 1bbd33b6258..8fee3385de1 100644
--- a/app/assets/javascripts/filtered_search/dropdown_operator.js
+++ b/app/assets/javascripts/filtered_search/dropdown_operator.js
@@ -39,7 +39,7 @@ export default class DropdownOperator extends FilteredSearchDropdown {
this.dispatchInputEvent();
}
- renderContent(forceShowList = false) {
+ renderContent(forceShowList = false, dropdownName = '') {
const dropdownData = [
{
tag: 'equal',
@@ -48,8 +48,9 @@ export default class DropdownOperator extends FilteredSearchDropdown {
help: __('is'),
},
];
+ const dropdownToken = this.tokenKeys.searchByKey(dropdownName.toLowerCase());
- if (gon.features?.notIssuableQueries) {
+ if (gon.features?.notIssuableQueries && !dropdownToken?.hideNotEqual) {
dropdownData.push({
tag: 'not-equal',
type: 'string',
diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js b/app/assets/javascripts/filtered_search/dropdown_user.js
index 0fb1828fc98..9a23ff25eac 100644
--- a/app/assets/javascripts/filtered_search/dropdown_user.js
+++ b/app/assets/javascripts/filtered_search/dropdown_user.js
@@ -5,7 +5,7 @@ export default class DropdownUser extends DropdownAjaxFilter {
constructor(options = {}) {
super({
...options,
- endpoint: '/-/autocomplete/users.json',
+ endpoint: `${gon.relative_url_root || ''}/-/autocomplete/users.json`,
symbol: '@',
});
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
index f7ce2ea01e0..8626e1a3d18 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
@@ -83,16 +83,16 @@ export default class FilteredSearchDropdown {
}
}
- render(forceRenderContent = false, forceShowList = false) {
+ render(forceRenderContent = false, forceShowList = false, hideNotEqual = false) {
this.setAsDropdown();
const currentHook = this.getCurrentHook();
const firstTimeInitialized = currentHook === null;
if (firstTimeInitialized || forceRenderContent) {
- this.renderContent(forceShowList);
+ this.renderContent(forceShowList, hideNotEqual);
} else if (currentHook.list.list.id !== this.dropdown.id) {
- this.renderContent(forceShowList);
+ this.renderContent(forceShowList, hideNotEqual);
}
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
index 762383f5a1d..d446e32394b 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
@@ -12,6 +12,7 @@ export default class FilteredSearchDropdownManager {
runnerTagsEndpoint = '',
labelsEndpoint = '',
milestonesEndpoint = '',
+ iterationsEndpoint = '',
releasesEndpoint = '',
environmentsEndpoint = '',
epicsEndpoint = '',
@@ -28,6 +29,7 @@ export default class FilteredSearchDropdownManager {
this.runnerTagsEndpoint = removeTrailingSlash(runnerTagsEndpoint);
this.labelsEndpoint = removeTrailingSlash(labelsEndpoint);
this.milestonesEndpoint = removeTrailingSlash(milestonesEndpoint);
+ this.iterationsEndpoint = removeTrailingSlash(iterationsEndpoint);
this.releasesEndpoint = removeTrailingSlash(releasesEndpoint);
this.epicsEndpoint = removeTrailingSlash(epicsEndpoint);
this.environmentsEndpoint = removeTrailingSlash(environmentsEndpoint);
@@ -107,7 +109,7 @@ export default class FilteredSearchDropdownManager {
this.mapping[key].reference.setOffset(offset);
}
- load(key, firstLoad = false) {
+ load(key, firstLoad = false, dropdownKey = '') {
const mappingKey = this.mapping[key];
const glClass = mappingKey.gl;
const { element } = mappingKey;
@@ -141,12 +143,12 @@ export default class FilteredSearchDropdownManager {
}
this.updateDropdownOffset(key);
- mappingKey.reference.render(firstLoad, forceShowList);
+ mappingKey.reference.render(firstLoad, forceShowList, dropdownKey);
this.currentDropdown = key;
}
- loadDropdown(dropdownName = '') {
+ loadDropdown(dropdownName = '', dropdownKey = '') {
let firstLoad = false;
if (!this.droplab) {
@@ -155,7 +157,7 @@ export default class FilteredSearchDropdownManager {
}
if (dropdownName === DROPDOWN_TYPE.operator) {
- this.load(dropdownName, firstLoad);
+ this.load(dropdownName, firstLoad, dropdownKey);
return;
}
@@ -167,7 +169,7 @@ export default class FilteredSearchDropdownManager {
if (shouldOpenFilterDropdown || shouldOpenHintDropdown) {
const key = match && match.key ? match.key : DROPDOWN_TYPE.hint;
- this.load(key, firstLoad);
+ this.load(key, firstLoad, dropdownKey);
}
}
@@ -200,11 +202,11 @@ export default class FilteredSearchDropdownManager {
dropdownToOpen = hasOperator && lastOperatorToken ? dropdownName : DROPDOWN_TYPE.operator;
}
- this.loadDropdown(dropdownToOpen);
+ this.loadDropdown(dropdownToOpen, dropdownName);
} else if (lastToken) {
const lastOperator = FilteredSearchVisualTokens.getLastTokenOperator();
// Token has been initialized into an object because it has a value
- this.loadDropdown(lastOperator ? lastToken.key : DROPDOWN_TYPE.operator);
+ this.loadDropdown(lastOperator ? lastToken.key : DROPDOWN_TYPE.operator, lastToken.key);
} else {
this.loadDropdown(DROPDOWN_TYPE.hint);
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index 261532f8867..921d686bb28 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -52,16 +52,24 @@ export default class FilteredSearchManager {
this.placeholder = placeholder;
this.anchor = anchor;
- const { multipleAssignees } = this.filteredSearchInput.dataset;
+ const {
+ multipleAssignees,
+ epicsEndpoint,
+ iterationsEndpoint,
+ } = this.filteredSearchInput.dataset;
+
if (multipleAssignees && this.filteredSearchTokenKeys.enableMultipleAssignees) {
this.filteredSearchTokenKeys.enableMultipleAssignees();
}
- const { epicsEndpoint } = this.filteredSearchInput.dataset;
if (!epicsEndpoint && this.filteredSearchTokenKeys.removeEpicToken) {
this.filteredSearchTokenKeys.removeEpicToken();
}
+ if (!iterationsEndpoint && this.filteredSearchTokenKeys.removeIterationToken) {
+ this.filteredSearchTokenKeys.removeIterationToken();
+ }
+
this.recentSearchesStore = new RecentSearchesStore({
isLocalStorageAvailable: RecentSearchesService.isAvailable(),
allowedKeys: this.filteredSearchTokenKeys.getKeys(),
@@ -112,6 +120,7 @@ export default class FilteredSearchManager {
releasesEndpoint = '',
environmentsEndpoint = '',
epicsEndpoint = '',
+ iterationsEndpoint = '',
} = this.filteredSearchInput.dataset;
this.dropdownManager = new FilteredSearchDropdownManager({
@@ -121,6 +130,7 @@ export default class FilteredSearchManager {
releasesEndpoint,
environmentsEndpoint,
epicsEndpoint,
+ iterationsEndpoint,
tokenizer: this.tokenizer,
page: this.page,
isGroup: this.isGroup,
diff --git a/app/assets/javascripts/frequent_items/index.js b/app/assets/javascripts/frequent_items/index.js
index 5b03e1d19db..1998bf4358a 100644
--- a/app/assets/javascripts/frequent_items/index.js
+++ b/app/assets/javascripts/frequent_items/index.js
@@ -16,63 +16,53 @@ const frequentItemDropdowns = [
},
];
-const initFrequentItemList = (namespace, key) => {
- const el = document.getElementById(`js-${namespace}-dropdown`);
-
- // Don't do anything if element doesn't exist (No groups dropdown)
- // This is for when the user accesses GitLab without logging in
- if (!el) {
- return;
- }
-
- import('./components/app.vue')
- .then(({ default: FrequentItems }) => {
- // eslint-disable-next-line no-new
- new Vue({
- el,
- data() {
- const { dataset } = this.$options.el;
- const item = {
- id: Number(dataset[`${key}Id`]),
- name: dataset[`${key}Name`],
- namespace: dataset[`${key}Namespace`],
- webUrl: dataset[`${key}WebUrl`],
- avatarUrl: dataset[`${key}AvatarUrl`] || null,
- lastAccessedOn: Date.now(),
- };
-
- return {
- currentUserName: dataset.userName,
- currentItem: item,
- };
- },
- render(createElement) {
- return createElement(FrequentItems, {
- props: {
- namespace,
- currentUserName: this.currentUserName,
- currentItem: this.currentItem,
- },
- });
- },
- });
- })
- .catch(() => {});
-};
-
export default function initFrequentItemDropdowns() {
frequentItemDropdowns.forEach(dropdown => {
const { namespace, key } = dropdown;
+ const el = document.getElementById(`js-${namespace}-dropdown`);
const navEl = document.getElementById(`nav-${namespace}-dropdown`);
// Don't do anything if element doesn't exist (No groups dropdown)
// This is for when the user accesses GitLab without logging in
- if (!navEl) {
+ if (!el || !navEl) {
return;
}
+ import('./components/app.vue')
+ .then(({ default: FrequentItems }) => {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ data() {
+ const { dataset } = this.$options.el;
+ const item = {
+ id: Number(dataset[`${key}Id`]),
+ name: dataset[`${key}Name`],
+ namespace: dataset[`${key}Namespace`],
+ webUrl: dataset[`${key}WebUrl`],
+ avatarUrl: dataset[`${key}AvatarUrl`] || null,
+ lastAccessedOn: Date.now(),
+ };
+
+ return {
+ currentUserName: dataset.userName,
+ currentItem: item,
+ };
+ },
+ render(createElement) {
+ return createElement(FrequentItems, {
+ props: {
+ namespace,
+ currentUserName: this.currentUserName,
+ currentItem: this.currentItem,
+ },
+ });
+ },
+ });
+ })
+ .catch(() => {});
+
$(navEl).on('shown.bs.dropdown', () => {
- initFrequentItemList(namespace, key);
eventHub.$emit(`${namespace}-dropdownOpen`);
});
});
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index 62948f74aaa..202f04f98f6 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -1,9 +1,12 @@
import $ from 'jquery';
import '~/lib/utils/jquery_at_who';
import { escape, template } from 'lodash';
+import { s__ } from '~/locale';
import SidebarMediator from '~/sidebar/sidebar_mediator';
+import { isUserBusy } from '~/set_status_modal/utils';
import glRegexp from './lib/utils/regexp';
import AjaxCache from './lib/utils/ajax_cache';
+import axios from '~/lib/utils/axios_utils';
import { spriteIcon } from './lib/utils/common_utils';
import * as Emoji from '~/emoji';
@@ -39,6 +42,7 @@ export function membersBeforeSave(members) {
title: sanitize(title),
search: sanitize(`${member.username} ${member.name}`),
icon: avatarIcon,
+ availability: member.availability,
};
});
}
@@ -52,6 +56,7 @@ export const defaultAutocompleteConfig = {
milestones: true,
labels: true,
snippets: true,
+ vulnerabilities: true,
};
class GfmAutoComplete {
@@ -59,6 +64,7 @@ class GfmAutoComplete {
this.dataSources = dataSources;
this.cachedData = {};
this.isLoadingData = {};
+ this.previousQuery = '';
}
setup(input, enableMap = defaultAutocompleteConfig) {
@@ -253,13 +259,17 @@ class GfmAutoComplete {
alias: 'users',
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
- const { avatarTag, username, title, icon } = value;
+ const { avatarTag, username, title, icon, availability } = value;
if (username != null) {
tmpl = GfmAutoComplete.Members.templateFunction({
avatarTag,
username,
title,
icon,
+ availabilityStatus:
+ availability && isUserBusy(availability)
+ ? `<span class="gl-text-gray-500"> ${s__('UserAvailability|(Busy)')}</span>`
+ : '',
});
}
return tmpl;
@@ -554,7 +564,7 @@ class GfmAutoComplete {
}
getDefaultCallbacks() {
- const fetchData = this.fetchData.bind(this);
+ const self = this;
return {
sorter(query, items, searchKey) {
@@ -567,7 +577,14 @@ class GfmAutoComplete {
},
filter(query, data, searchKey) {
if (GfmAutoComplete.isLoading(data)) {
- fetchData(this.$inputor, this.at);
+ self.fetchData(this.$inputor, this.at);
+ return data;
+ } else if (
+ GfmAutoComplete.isTypeWithBackendFiltering(this.at) &&
+ self.previousQuery !== query
+ ) {
+ self.fetchData(this.$inputor, this.at, query);
+ self.previousQuery = query;
return data;
}
return $.fn.atwho.default.callbacks.filter(query, data, searchKey);
@@ -615,13 +632,22 @@ class GfmAutoComplete {
};
}
- fetchData($input, at) {
+ fetchData($input, at, search) {
if (this.isLoadingData[at]) return;
this.isLoadingData[at] = true;
const dataSource = this.dataSources[GfmAutoComplete.atTypeMap[at]];
- if (this.cachedData[at]) {
+ if (GfmAutoComplete.isTypeWithBackendFiltering(at)) {
+ axios
+ .get(dataSource, { params: { search } })
+ .then(({ data }) => {
+ this.loadData($input, at, data);
+ })
+ .catch(() => {
+ this.isLoadingData[at] = false;
+ });
+ } else if (this.cachedData[at]) {
this.loadData($input, at, this.cachedData[at]);
} else if (GfmAutoComplete.atTypeMap[at] === 'emojis') {
this.loadEmojiData($input, at).catch(() => {});
@@ -707,7 +733,9 @@ class GfmAutoComplete {
// https://github.com/ichord/At.js
const atSymbolsWithBar = Object.keys(controllers)
.join('|')
- .replace(/[$]/, '\\$&');
+ .replace(/[$]/, '\\$&')
+ .replace(/([[\]:])/g, '\\$1');
+
const atSymbolsWithoutBar = Object.keys(controllers).join('');
const targetSubtext = subtext.split(GfmAutoComplete.regexSubtext).pop();
const resultantFlag = flag.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
@@ -738,9 +766,14 @@ GfmAutoComplete.atTypeMap = {
'~': 'labels',
'%': 'milestones',
'/': 'commands',
+ '[vulnerability:': 'vulnerabilities',
$: 'snippets',
};
+GfmAutoComplete.typesWithBackendFiltering = ['vulnerabilities'];
+GfmAutoComplete.isTypeWithBackendFiltering = type =>
+ GfmAutoComplete.typesWithBackendFiltering.includes(GfmAutoComplete.atTypeMap[type]);
+
function findEmoji(name) {
return Emoji.searchEmoji(name, { match: 'contains', raw: true }).sort((a, b) => {
if (a.index !== b.index) {
@@ -775,8 +808,10 @@ GfmAutoComplete.Emoji = {
};
// Team Members
GfmAutoComplete.Members = {
- templateFunction({ avatarTag, username, title, icon }) {
- return `<li>${avatarTag} ${username} <small>${escape(title)}</small> ${icon}</li>`;
+ templateFunction({ avatarTag, username, title, icon, availabilityStatus }) {
+ return `<li>${avatarTag} ${username} <small>${escape(
+ title,
+ )}${availabilityStatus}</small> ${icon}</li>`;
},
};
GfmAutoComplete.Labels = {
diff --git a/app/assets/javascripts/graphql_shared/utils.js b/app/assets/javascripts/graphql_shared/utils.js
index a262fbd9ac3..5487aeb9391 100644
--- a/app/assets/javascripts/graphql_shared/utils.js
+++ b/app/assets/javascripts/graphql_shared/utils.js
@@ -7,6 +7,10 @@
* @returns {Number}
*/
export const getIdFromGraphQLId = (gid = '') =>
- parseInt((gid || '').replace(/gid:\/\/gitlab\/.*\//g, ''), 10) || null;
+ parseInt(`${gid}`.replace(/gid:\/\/gitlab\/.*\//g, ''), 10) || null;
-export default {};
+export const MutationOperationMode = {
+ Append: 'APPEND',
+ Remove: 'REMOVE',
+ Replace: 'REPLACE',
+};
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue
index 871f5c9a845..e057012a246 100644
--- a/app/assets/javascripts/groups/components/app.vue
+++ b/app/assets/javascripts/groups/components/app.vue
@@ -3,9 +3,8 @@
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';
+import { GlLoadingIcon, GlModal } from '@gitlab/ui';
+import { __, s__, sprintf } from '~/locale';
import { HIDDEN_CLASS } from '~/lib/utils/constants';
import { getParameterByName } from '~/lib/utils/common_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
@@ -16,8 +15,8 @@ import groupsComponent from './groups.vue';
export default {
components: {
- DeprecatedModal,
groupsComponent,
+ GlModal,
GlLoadingIcon,
},
props: {
@@ -49,13 +48,30 @@ export default {
isLoading: true,
isSearchEmpty: false,
searchEmptyMessage: '',
- showModal: false,
- groupLeaveConfirmationMessage: '',
targetGroup: null,
targetParentGroup: null,
};
},
computed: {
+ primaryProps() {
+ return {
+ text: __('Leave group'),
+ attributes: [{ variant: 'warning' }, { category: 'primary' }],
+ };
+ },
+ cancelProps() {
+ return {
+ text: __('Cancel'),
+ };
+ },
+ groupLeaveConfirmationMessage() {
+ if (!this.targetGroup) {
+ return '';
+ }
+ return sprintf(s__('GroupsTree|Are you sure you want to leave the "%{fullName}" group?'), {
+ fullName: this.targetGroup.fullName,
+ });
+ },
groups() {
return this.store.getGroups();
},
@@ -171,27 +187,17 @@ export default {
}
},
showLeaveGroupModal(group, parentGroup) {
- const { fullName } = group;
this.targetGroup = group;
this.targetParentGroup = parentGroup;
- this.showModal = true;
- this.groupLeaveConfirmationMessage = sprintf(
- s__('GroupsTree|Are you sure you want to leave the "%{fullName}" group?'),
- { fullName },
- );
- },
- hideLeaveGroupModal() {
- this.showModal = false;
},
leaveGroup() {
- this.showModal = false;
this.targetGroup.isBeingRemoved = true;
this.service
.leaveGroup(this.targetGroup.leavePath)
.then(res => {
$.scrollTo(0);
this.store.removeGroup(this.targetGroup, this.targetParentGroup);
- Flash(res.data.notice, 'notice');
+ this.$toast.show(res.data.notice);
})
.catch(err => {
let message = COMMON_STR.FAILURE;
@@ -245,21 +251,21 @@ export default {
class="loading-animation prepend-top-20"
/>
<groups-component
- v-if="!isLoading"
+ v-else
:groups="groups"
:search-empty="isSearchEmpty"
:search-empty-message="searchEmptyMessage"
:page-info="pageInfo"
:action="action"
/>
- <deprecated-modal
- v-show="showModal"
- :primary-button-label="__('Leave')"
+ <gl-modal
+ modal-id="leave-group-modal"
:title="__('Are you sure?')"
- :text="groupLeaveConfirmationMessage"
- kind="warning"
- @cancel="hideLeaveGroupModal"
- @submit="leaveGroup"
- />
+ :action-primary="primaryProps"
+ :action-cancel="cancelProps"
+ @primary="leaveGroup"
+ >
+ {{ groupLeaveConfirmationMessage }}
+ </gl-modal>
</div>
</template>
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index 44349b33386..6e99b6ad4fa 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -1,8 +1,7 @@
<script>
/* eslint-disable vue/no-v-html */
-import { GlLoadingIcon, GlBadge } from '@gitlab/ui';
+import { GlLoadingIcon, GlBadge, GlTooltipDirective } from '@gitlab/ui';
import { visitUrl } from '../../lib/utils/url_utility';
-import tooltip from '../../vue_shared/directives/tooltip';
import identicon from '../../vue_shared/components/identicon.vue';
import eventHub from '../event_hub';
import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE } from '../constants';
@@ -17,7 +16,7 @@ import { showLearnGitLabGroupItemPopover } from '~/onboarding_issues';
export default {
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
components: {
GlBadge,
@@ -127,11 +126,10 @@ export default {
<div class="group-text flex-grow-1 flex-shrink-1">
<div class="d-flex align-items-center flex-wrap title namespace-title gl-mr-3">
<a
- v-tooltip
+ v-gl-tooltip.bottom
:href="group.relativePath"
:title="group.fullName"
class="no-expand gl-mt-3 gl-mr-3 gl-text-gray-900!"
- data-placement="bottom"
>{{
// ending bracket must be by closing tag to prevent
// link hover text-decoration from over-extending
diff --git a/app/assets/javascripts/groups/components/item_actions.vue b/app/assets/javascripts/groups/components/item_actions.vue
index 2e92a608f76..ff52f5ef51c 100644
--- a/app/assets/javascripts/groups/components/item_actions.vue
+++ b/app/assets/javascripts/groups/components/item_actions.vue
@@ -1,15 +1,15 @@
<script>
-import { GlIcon } from '@gitlab/ui';
-import tooltip from '~/vue_shared/directives/tooltip';
+import { GlTooltipDirective, GlButton, GlModalDirective } from '@gitlab/ui';
import eventHub from '../event_hub';
import { COMMON_STR } from '../constants';
export default {
components: {
- GlIcon,
+ GlButton,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
+ GlModal: GlModalDirective,
},
props: {
parentGroup: {
@@ -45,32 +45,28 @@ export default {
<template>
<div class="controls d-flex justify-content-end">
- <a
+ <gl-button
v-if="group.canLeave"
- v-tooltip
- :href="group.leavePath"
+ v-gl-tooltip.top
+ v-gl-modal.leave-group-modal
:title="leaveBtnTitle"
:aria-label="leaveBtnTitle"
- data-container="body"
- data-placement="bottom"
data-testid="leave-group-btn"
- class="leave-group btn btn-xs no-expand gl-text-gray-500 gl-ml-5"
- @click.prevent="onLeaveGroup"
- >
- <gl-icon name="leave" class="position-top-0" />
- </a>
- <a
+ size="small"
+ icon="leave"
+ class="leave-group gl-ml-3"
+ @click.stop="onLeaveGroup"
+ />
+ <gl-button
v-if="group.canEdit"
- v-tooltip
+ v-gl-tooltip.top
:href="group.editPath"
:title="editBtnTitle"
:aria-label="editBtnTitle"
- data-container="body"
- data-placement="bottom"
data-testid="edit-group-btn"
- class="edit-group btn btn-xs no-expand gl-text-gray-500 gl-ml-5"
- >
- <gl-icon name="settings" class="position-top-0 align-middle" />
- </a>
+ size="small"
+ icon="pencil"
+ class="edit-group gl-ml-3"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/groups/constants.js b/app/assets/javascripts/groups/constants.js
index c538934a37d..e2722d780dc 100644
--- a/app/assets/javascripts/groups/constants.js
+++ b/app/assets/javascripts/groups/constants.js
@@ -31,14 +31,16 @@ export const GROUP_VISIBILITY_TYPE = {
'Public - The group and any public projects can be viewed without any authentication.',
),
internal: __(
- 'Internal - The group and any internal projects can be viewed by any logged in user.',
+ 'Internal - The group and any internal projects can be viewed by any logged in user except external users.',
),
private: __('Private - The group and its projects can only be viewed by members.'),
};
export const PROJECT_VISIBILITY_TYPE = {
public: __('Public - The project can be accessed without any authentication.'),
- internal: __('Internal - The project can be accessed by any logged in user.'),
+ internal: __(
+ 'Internal - The project can be accessed by any logged in user except external users.',
+ ),
private: __(
'Private - Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group.',
),
diff --git a/app/assets/javascripts/groups/index.js b/app/assets/javascripts/groups/index.js
index 928f1fe409f..522f1d16df2 100644
--- a/app/assets/javascripts/groups/index.js
+++ b/app/assets/javascripts/groups/index.js
@@ -1,4 +1,6 @@
import Vue from 'vue';
+import { GlToast } from '@gitlab/ui';
+import UserCallout from '~/user_callout';
import { parseBoolean } from '~/lib/utils/common_utils';
import Translate from '../vue_shared/translate';
import GroupFilterableList from './groups_filterable_list';
@@ -16,6 +18,9 @@ export default (containerId = 'js-groups-tree', endpoint, action = '') => {
const containerEl = document.getElementById(containerId);
let dataEl;
+ // eslint-disable-next-line no-new
+ new UserCallout();
+
// Don't do anything if element doesn't exist (No groups)
// This is for when the user enters directly to the page via URL
if (!containerEl) {
@@ -31,6 +36,8 @@ export default (containerId = 'js-groups-tree', endpoint, action = '') => {
Vue.component('group-folder', groupFolderComponent);
Vue.component('group-item', groupItemComponent);
+ Vue.use(GlToast);
+
// eslint-disable-next-line no-new
new Vue({
el,
diff --git a/app/assets/javascripts/groups/members/index.js b/app/assets/javascripts/groups/members/index.js
index 3bbef14d199..cb28fb057c9 100644
--- a/app/assets/javascripts/groups/members/index.js
+++ b/app/assets/javascripts/groups/members/index.js
@@ -5,7 +5,7 @@ import { parseDataAttributes } from 'ee_else_ce/groups/members/utils';
import App from './components/app.vue';
import membersModule from '~/vuex_shared/modules/members';
-export const initGroupMembersApp = (el, tableFields, requestFormatter) => {
+export const initGroupMembersApp = (el, tableFields, tableAttrs, requestFormatter) => {
if (!el) {
return () => {};
}
@@ -18,6 +18,7 @@ export const initGroupMembersApp = (el, tableFields, requestFormatter) => {
...parseDataAttributes(el),
currentUserId: gon.current_user_id || null,
tableFields,
+ tableAttrs,
requestFormatter,
}),
});
diff --git a/app/assets/javascripts/groups/new_group_child.js b/app/assets/javascripts/groups/new_group_child.js
deleted file mode 100644
index bb2aea3ea76..00000000000
--- a/app/assets/javascripts/groups/new_group_child.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import { visitUrl } from '../lib/utils/url_utility';
-import DropLab from '../droplab/drop_lab';
-import ISetter from '../droplab/plugins/input_setter';
-
-const InputSetter = { ...ISetter };
-
-const NEW_PROJECT = 'new-project';
-const NEW_SUBGROUP = 'new-subgroup';
-
-export default class NewGroupChild {
- constructor(buttonWrapper) {
- this.buttonWrapper = buttonWrapper;
- this.newGroupChildButton = this.buttonWrapper.querySelector('.js-new-group-child');
- this.dropdownToggle = this.buttonWrapper.querySelector('.js-dropdown-toggle');
- this.dropdownList = this.buttonWrapper.querySelector('.dropdown-menu');
-
- this.newGroupPath = this.buttonWrapper.dataset.projectPath;
- this.subgroupPath = this.buttonWrapper.dataset.subgroupPath;
-
- this.init();
- }
-
- init() {
- this.initDroplab();
- this.bindEvents();
- }
-
- initDroplab() {
- this.droplab = new DropLab();
- this.droplab.init(
- this.dropdownToggle,
- this.dropdownList,
- [InputSetter],
- this.getDroplabConfig(),
- );
- }
-
- getDroplabConfig() {
- return {
- InputSetter: [
- {
- input: this.newGroupChildButton,
- valueAttribute: 'data-value',
- inputAttribute: 'data-action',
- },
- {
- input: this.newGroupChildButton,
- valueAttribute: 'data-text',
- },
- ],
- };
- }
-
- bindEvents() {
- this.newGroupChildButton.addEventListener('click', this.onClickNewGroupChildButton.bind(this));
- }
-
- onClickNewGroupChildButton(e) {
- if (e.target.dataset.action === NEW_PROJECT) {
- visitUrl(this.newGroupPath);
- } else if (e.target.dataset.action === NEW_SUBGROUP) {
- visitUrl(this.subgroupPath);
- }
- }
-}
diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js
index b833cca1db6..1cedb557d46 100644
--- a/app/assets/javascripts/header.js
+++ b/app/assets/javascripts/header.js
@@ -1,5 +1,6 @@
import $ from 'jquery';
import Vue from 'vue';
+import { GlToast } from '@gitlab/ui';
import Translate from '~/vue_shared/translate';
import { highCountTrim } from '~/lib/utils/text_utility';
import Tracking from '~/tracking';
@@ -34,26 +35,45 @@ function initStatusTriggers() {
const statusModalElement = document.createElement('div');
setStatusModalWrapperEl.appendChild(statusModalElement);
+ Vue.use(GlToast);
Vue.use(Translate);
// eslint-disable-next-line no-new
new Vue({
el: statusModalElement,
data() {
- const { currentEmoji, currentMessage } = setStatusModalWrapperEl.dataset;
+ const {
+ currentEmoji,
+ defaultEmoji,
+ currentMessage,
+ currentAvailability,
+ canSetUserAvailability,
+ } = setStatusModalWrapperEl.dataset;
return {
currentEmoji,
+ defaultEmoji,
currentMessage,
+ currentAvailability,
+ canSetUserAvailability,
};
},
render(createElement) {
- const { currentEmoji, currentMessage } = this;
+ const {
+ currentEmoji,
+ defaultEmoji,
+ currentMessage,
+ currentAvailability,
+ canSetUserAvailability,
+ } = this;
return createElement(SetStatusModalWrapper, {
props: {
currentEmoji,
+ defaultEmoji,
currentMessage,
+ currentAvailability,
+ canSetUserAvailability,
},
});
},
diff --git a/app/assets/javascripts/helpers/startup_css_helper.js b/app/assets/javascripts/helpers/startup_css_helper.js
index 8e25e1421c0..d41a6209898 100644
--- a/app/assets/javascripts/helpers/startup_css_helper.js
+++ b/app/assets/javascripts/helpers/startup_css_helper.js
@@ -20,19 +20,9 @@ const 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();
--*/
+/* For `waitForCSSLoaded` methods, see docs.gitlab.com/ee/development/fe_guide/performance.html#important-considerations */
export const waitForCSSLoaded = (action = () => {}) => {
- if (!gon.features.startupCss || allLinksLoaded()) {
+ if (!gon?.features?.startupCss || allLinksLoaded()) {
return new Promise(resolve => {
action();
resolve();
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/form.vue b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
index f36fe87ccfa..9d2deb1d4d0 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/form.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
@@ -1,8 +1,7 @@
<script>
import { mapState, mapActions, mapGetters } from 'vuex';
-import { GlModal, GlSafeHtmlDirective } from '@gitlab/ui';
+import { GlModal, GlSafeHtmlDirective, GlButton } from '@gitlab/ui';
import { n__, __ } from '~/locale';
-import LoadingButton from '~/vue_shared/components/loading_button.vue';
import CommitMessageField from './message_field.vue';
import Actions from './actions.vue';
import SuccessMessage from './success_message.vue';
@@ -12,10 +11,10 @@ import { createUnexpectedCommitError } from '../../lib/errors';
export default {
components: {
Actions,
- LoadingButton,
CommitMessageField,
SuccessMessage,
GlModal,
+ GlButton,
},
directives: {
SafeHtml: GlSafeHtmlDirective,
@@ -156,12 +155,16 @@ export default {
/>
<div class="clearfix gl-mt-5">
<actions />
- <loading-button
+ <gl-button
:loading="submitCommitLoading"
- :label="commitButtonText"
- container-class="btn btn-success btn-sm float-left qa-commit-button"
+ class="float-left qa-commit-button"
+ size="small"
+ category="primary"
+ variant="success"
@click="commit"
- />
+ >
+ {{ __('Commit') }}
+ </gl-button>
<button
v-if="!discardDraftButtonDisabled"
type="button"
@@ -170,14 +173,17 @@ export default {
>
{{ __('Discard draft') }}
</button>
- <button
+ <gl-button
v-else
type="button"
- class="btn btn-default btn-sm float-right"
+ class="float-right"
+ category="secondary"
+ variant="default"
+ size="small"
@click="toggleIsCompact"
>
{{ __('Collapse') }}
- </button>
+ </gl-button>
</div>
<gl-modal
ref="commitErrorModal"
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list.vue b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
index 609ce287d3f..729ff7c74ec 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
@@ -1,8 +1,7 @@
<script>
import { mapActions } from 'vuex';
-import { GlModal, GlIcon } from '@gitlab/ui';
+import { GlModal, GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import tooltip from '~/vue_shared/directives/tooltip';
import ListItem from './list_item.vue';
export default {
@@ -12,17 +11,13 @@ export default {
GlModal,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
fileList: {
type: Array,
required: true,
},
- iconName: {
- type: String,
- required: true,
- },
stagedList: {
type: Boolean,
required: false,
@@ -73,12 +68,11 @@ 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">
- <gl-icon v-once :name="iconName" :size="18" class="gl-mr-3" />
<strong> {{ titleText }} </strong>
<div class="d-flex ml-auto">
<button
v-if="!stagedList"
- v-tooltip
+ v-gl-tooltip
:title="__('Discard all changes')"
:aria-label="__('Discard all changes')"
:disabled="!filesLength"
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
deleted file mode 100644
index 4821b8389ff..00000000000
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
+++ /dev/null
@@ -1,103 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-import tooltip from '~/vue_shared/directives/tooltip';
-import { sprintf, n__, __ } from '~/locale';
-
-export default {
- components: {
- GlIcon,
- },
- directives: {
- tooltip,
- },
- props: {
- files: {
- type: Array,
- required: true,
- },
- iconName: {
- type: String,
- required: true,
- },
- title: {
- type: String,
- required: true,
- },
- },
- computed: {
- addedFilesLength() {
- return this.files.filter(f => f.tempFile).length;
- },
- modifiedFilesLength() {
- return this.files.filter(f => !f.tempFile).length;
- },
- addedFilesIconClass() {
- return this.addedFilesLength ? 'multi-file-addition' : '';
- },
- modifiedFilesClass() {
- return this.modifiedFilesLength ? 'multi-file-modified' : '';
- },
- additionsTooltip() {
- return sprintf(
- n__('1 %{type} addition', '%{count} %{type} additions', this.addedFilesLength),
- {
- type: this.title.toLowerCase(),
- count: this.addedFilesLength,
- },
- );
- },
- modifiedTooltip() {
- return sprintf(
- n__('1 %{type} modification', '%{count} %{type} modifications', this.modifiedFilesLength),
- {
- type: this.title.toLowerCase(),
- count: this.modifiedFilesLength,
- },
- );
- },
- titleTooltip() {
- return sprintf(__('%{title} changes'), { title: this.title });
- },
- additionIconName() {
- return this.title.toLowerCase() === 'staged' ? 'file-addition-solid' : 'file-addition';
- },
- modifiedIconName() {
- return this.title.toLowerCase() === 'staged' ? 'file-modified-solid' : 'file-modified';
- },
- },
-};
-</script>
-
-<template>
- <div class="multi-file-commit-list-collapsed text-center">
- <div
- v-tooltip
- :title="titleTooltip"
- data-container="body"
- data-placement="left"
- class="gl-mb-5"
- >
- <gl-icon v-once :name="iconName" :size="18" />
- </div>
- <div
- v-tooltip
- :title="additionsTooltip"
- data-container="body"
- data-placement="left"
- class="gl-mb-3"
- >
- <gl-icon :name="additionIconName" :size="18" :class="addedFilesIconClass" />
- </div>
- {{ addedFilesLength }}
- <div
- v-tooltip
- :title="modifiedTooltip"
- data-container="body"
- data-placement="left"
- class="gl-mt-3 gl-mb-3"
- >
- <gl-icon :name="modifiedIconName" :size="18" :class="modifiedFilesClass" />
- </div>
- {{ modifiedFilesLength }}
- </div>
-</template>
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 a0d6cf3c42d..123e0aba959 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
@@ -1,7 +1,6 @@
<script>
import { mapActions } from 'vuex';
-import { GlIcon } from '@gitlab/ui';
-import tooltip from '~/vue_shared/directives/tooltip';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import { viewerTypes } from '../../constants';
import getCommitIconMap from '../../commit_icon';
@@ -12,7 +11,7 @@ export default {
FileIcon,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
file: {
@@ -77,7 +76,7 @@ export default {
<template>
<div class="multi-file-commit-list-item position-relative">
<div
- v-tooltip
+ v-gl-tooltip
:title="tooltipTitle"
:class="{
'is-active': isActive,
diff --git a/app/assets/javascripts/ide/components/file_row_extra.vue b/app/assets/javascripts/ide/components/file_row_extra.vue
index 48ab58e1cb7..fb0d00dc6a1 100644
--- a/app/assets/javascripts/ide/components/file_row_extra.vue
+++ b/app/assets/javascripts/ide/components/file_row_extra.vue
@@ -1,8 +1,7 @@
<script>
import { mapGetters } from 'vuex';
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { n__ } from '~/locale';
-import tooltip from '~/vue_shared/directives/tooltip';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
import NewDropdown from './new_dropdown/index.vue';
import MrFileIcon from './mr_file_icon.vue';
@@ -10,7 +9,7 @@ import MrFileIcon from './mr_file_icon.vue';
export default {
name: 'FileRowExtra',
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
components: {
GlIcon,
@@ -70,7 +69,7 @@ export default {
<span v-if="showTreeChangesCount" class="ide-tree-changes">
{{ changesCount }}
<gl-icon
- v-tooltip
+ v-gl-tooltip.left.viewport
:title="folderChangesTooltip"
:size="12"
data-container="body"
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index 8f23856fd6c..e1d2895831a 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -1,6 +1,5 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import {
WEBIDE_MARK_APP_START,
@@ -10,19 +9,12 @@ import {
WEBIDE_MEASURE_TREE_FROM_REQUEST,
WEBIDE_MEASURE_FILE_FROM_REQUEST,
WEBIDE_MEASURE_FILE_AFTER_INTERACTION,
-} from '~/performance_constants';
-import { performanceMarkAndMeasure } from '~/performance_utils';
+} from '~/performance/constants';
+import { performanceMarkAndMeasure } from '~/performance/utils';
import { modalTypes } from '../constants';
import eventHub from '../eventhub';
-import FindFile from '~/vue_shared/components/file_finder/index.vue';
-import NewModal from './new_dropdown/modal.vue';
import IdeSidebar from './ide_side_bar.vue';
-import RepoTabs from './repo_tabs.vue';
-import IdeStatusBar from './ide_status_bar.vue';
import RepoEditor from './repo_editor.vue';
-import RightPane from './panes/right.vue';
-import ErrorMessage from './error_message.vue';
-import CommitEditorHeader from './commit_sidebar/editor_header.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { measurePerformance } from '../utils';
@@ -43,19 +35,24 @@ eventHub.$on(WEBIDE_MEASURE_FILE_AFTER_INTERACTION, () =>
export default {
components: {
- NewModal,
IdeSidebar,
- RepoTabs,
- IdeStatusBar,
RepoEditor,
- FindFile,
- ErrorMessage,
- CommitEditorHeader,
- GlButton,
- GlLoadingIcon,
- RightPane,
+ 'error-message': () => import('./error_message.vue'),
+ 'gl-button': () => import('@gitlab/ui/src/components/base/button/button.vue'),
+ 'gl-loading-icon': () => import('@gitlab/ui/src/components/base/loading_icon/loading_icon.vue'),
+ 'commit-editor-header': () => import('./commit_sidebar/editor_header.vue'),
+ 'repo-tabs': () => import('./repo_tabs.vue'),
+ 'ide-status-bar': () => import('./ide_status_bar.vue'),
+ 'find-file': () => import('~/vue_shared/components/file_finder/index.vue'),
+ 'right-pane': () => import('./panes/right.vue'),
+ 'new-modal': () => import('./new_dropdown/modal.vue'),
},
mixins: [glFeatureFlagsMixin()],
+ data() {
+ return {
+ loadDeferred: false,
+ };
+ },
computed: {
...mapState([
'openFiles',
@@ -107,6 +104,9 @@ export default {
createNewFile() {
this.$refs.newModal.open(modalTypes.blob);
},
+ loadDeferredComponents() {
+ this.loadDeferred = true;
+ },
},
};
</script>
@@ -118,19 +118,23 @@ export default {
>
<error-message v-if="errorMessage" :message="errorMessage" />
<div class="ide-view flex-grow d-flex">
- <find-file
- v-show="fileFindVisible"
- :files="allBlobs"
- :visible="fileFindVisible"
- :loading="loading"
- @toggle="toggleFileFinder"
- @click="openFile"
- />
- <ide-sidebar />
+ <template v-if="loadDeferred">
+ <find-file
+ v-show="fileFindVisible"
+ :files="allBlobs"
+ :visible="fileFindVisible"
+ :loading="loading"
+ @toggle="toggleFileFinder"
+ @click="openFile"
+ />
+ </template>
+ <ide-sidebar @tree-ready="loadDeferredComponents" />
<div class="multi-file-edit-pane">
<template v-if="activeFile">
- <commit-editor-header v-if="isCommitModeActive" :active-file="activeFile" />
- <repo-tabs v-else :active-file="activeFile" :files="openFiles" :viewer="viewer" />
+ <template v-if="loadDeferred">
+ <commit-editor-header v-if="isCommitModeActive" :active-file="activeFile" />
+ <repo-tabs v-else :active-file="activeFile" :files="openFiles" :viewer="viewer" />
+ </template>
<repo-editor :file="activeFile" class="multi-file-edit-pane-content" />
</template>
<template v-else>
@@ -177,9 +181,13 @@ export default {
</div>
</template>
</div>
- <right-pane v-if="currentProjectId" />
+ <template v-if="loadDeferred">
+ <right-pane v-if="currentProjectId" />
+ </template>
</div>
- <ide-status-bar />
- <new-modal ref="newModal" />
+ <template v-if="loadDeferred">
+ <ide-status-bar />
+ <new-modal ref="newModal" />
+ </template>
</article>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_side_bar.vue b/app/assets/javascripts/ide/components/ide_side_bar.vue
index 53dfc133fc8..99215d6c3f1 100644
--- a/app/assets/javascripts/ide/components/ide_side_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_side_bar.vue
@@ -4,21 +4,19 @@ 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';
-import RepoCommitSection from './repo_commit_section.vue';
import CommitForm from './commit_sidebar/form.vue';
-import IdeReview from './ide_review.vue';
import IdeProjectHeader from './ide_project_header.vue';
-import { SIDEBAR_INIT_WIDTH } from '../constants';
+import { SIDEBAR_INIT_WIDTH, leftSidebarViews } from '../constants';
export default {
components: {
GlSkeletonLoading,
ResizablePanel,
ActivityBar,
- RepoCommitSection,
IdeTree,
+ [leftSidebarViews.review.name]: () => import('./ide_review.vue'),
+ [leftSidebarViews.commit.name]: () => import('./repo_commit_section.vue'),
CommitForm,
- IdeReview,
IdeProjectHeader,
},
computed: {
@@ -49,7 +47,7 @@ export default {
<div class="multi-file-commit-panel-inner" data-testid="ide-side-bar-inner">
<div class="multi-file-commit-panel-inner-content">
<keep-alive>
- <component :is="currentActivityView" />
+ <component :is="currentActivityView" @tree-ready="$emit('tree-ready')" />
</keep-alive>
</div>
<commit-form />
diff --git a/app/assets/javascripts/ide/components/ide_status_list.vue b/app/assets/javascripts/ide/components/ide_status_list.vue
index caa122f6ed2..aa61c0d9b5e 100644
--- a/app/assets/javascripts/ide/components/ide_status_list.vue
+++ b/app/assets/javascripts/ide/components/ide_status_list.vue
@@ -14,6 +14,7 @@ export default {
},
computed: {
...mapGetters(['activeFile']),
+ ...mapGetters('editor', ['activeFileEditor']),
activeFileEOL() {
return getFileEOL(this.activeFile.content);
},
@@ -33,8 +34,10 @@ export default {
</gl-link>
</div>
<div>{{ activeFileEOL }}</div>
- <div v-if="activeFileIsText">{{ activeFile.editorRow }}:{{ activeFile.editorColumn }}</div>
- <div>{{ activeFile.fileLanguage }}</div>
+ <div v-if="activeFileIsText">
+ {{ activeFileEditor.editorRow }}:{{ activeFileEditor.editorColumn }}
+ </div>
+ <div>{{ activeFileEditor.fileLanguage }}</div>
</template>
<terminal-sync-status-safe />
</div>
diff --git a/app/assets/javascripts/ide/components/ide_tree.vue b/app/assets/javascripts/ide/components/ide_tree.vue
index 56fcb6c2600..e563de6659a 100644
--- a/app/assets/javascripts/ide/components/ide_tree.vue
+++ b/app/assets/javascripts/ide/components/ide_tree.vue
@@ -51,7 +51,7 @@ export default {
</script>
<template>
- <ide-tree-list>
+ <ide-tree-list @tree-ready="$emit('tree-ready')">
<template #header>
{{ __('Edit') }}
<div class="ide-tree-actions ml-auto d-flex" data-testid="ide-root-actions">
diff --git a/app/assets/javascripts/ide/components/ide_tree_list.vue b/app/assets/javascripts/ide/components/ide_tree_list.vue
index dd226f07fb0..e7e94f5b5da 100644
--- a/app/assets/javascripts/ide/components/ide_tree_list.vue
+++ b/app/assets/javascripts/ide/components/ide_tree_list.vue
@@ -6,8 +6,8 @@ import {
WEBIDE_MARK_TREE_START,
WEBIDE_MEASURE_TREE_FROM_REQUEST,
WEBIDE_MARK_FILE_CLICKED,
-} from '~/performance_constants';
-import { performanceMarkAndMeasure } from '~/performance_utils';
+} from '~/performance/constants';
+import { performanceMarkAndMeasure } from '~/performance/utils';
import eventHub from '../eventhub';
import IdeFileRow from './ide_file_row.vue';
import NavDropdown from './nav_dropdown.vue';
@@ -32,6 +32,13 @@ export default {
return !this.currentTree || this.currentTree.loading;
},
},
+ watch: {
+ showLoading(newVal) {
+ if (!newVal) {
+ this.$emit('tree-ready');
+ }
+ },
+ },
beforeCreate() {
performanceMarkAndMeasure({ mark: WEBIDE_MARK_TREE_START });
},
diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue
index a5ae8bbfe9a..d65304034c2 100644
--- a/app/assets/javascripts/ide/components/jobs/detail.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail.vue
@@ -2,7 +2,7 @@
/* eslint-disable vue/no-v-html */
import { mapActions, mapState } from 'vuex';
import { throttle } from 'lodash';
-import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { GlTooltipDirective, GlButton, GlIcon } from '@gitlab/ui';
import { __ } from '../../../locale';
import ScrollButton from './detail/scroll_button.vue';
import JobDescription from './detail/description.vue';
@@ -17,6 +17,7 @@ export default {
GlTooltip: GlTooltipDirective,
},
components: {
+ GlButton,
GlIcon,
ScrollButton,
JobDescription,
@@ -75,9 +76,9 @@ export default {
<template>
<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)">
- <gl-icon name="chevron-left" /> {{ __('View jobs') }}
- </button>
+ <gl-button category="secondary" icon="chevron-left" size="small" @click="setDetailJob(null)">
+ {{ __('View jobs') }}
+ </gl-button>
</header>
<div class="top-bar d-flex border-left-0 mr-3">
<job-description :job="detailJob" />
diff --git a/app/assets/javascripts/ide/components/jobs/item.vue b/app/assets/javascripts/ide/components/jobs/item.vue
index db3630bc1d1..f84315b63d2 100644
--- a/app/assets/javascripts/ide/components/jobs/item.vue
+++ b/app/assets/javascripts/ide/components/jobs/item.vue
@@ -1,9 +1,11 @@
<script>
+import { GlButton } from '@gitlab/ui';
import JobDescription from './detail/description.vue';
export default {
components: {
JobDescription,
+ GlButton,
},
props: {
job: {
@@ -28,9 +30,9 @@ export default {
<div class="ide-job-item">
<job-description :job="job" class="gl-mr-3" />
<div class="ml-auto align-self-center">
- <button v-if="job.started" type="button" class="btn btn-default btn-sm" @click="clickViewLog">
+ <gl-button v-if="job.started" category="secondary" size="small" @click="clickViewLog">
{{ __('View log') }}
- </button>
+ </gl-button>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/mr_file_icon.vue b/app/assets/javascripts/ide/components/mr_file_icon.vue
index c8629a869e0..af297753c28 100644
--- a/app/assets/javascripts/ide/components/mr_file_icon.vue
+++ b/app/assets/javascripts/ide/components/mr_file_icon.vue
@@ -1,20 +1,19 @@
<script>
-import { GlIcon } from '@gitlab/ui';
-import tooltip from '~/vue_shared/directives/tooltip';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
export default {
components: {
GlIcon,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
};
</script>
<template>
<gl-icon
- v-tooltip
+ v-gl-tooltip
:title="__('Part of merge request changes')"
:size="12"
name="git-merge"
diff --git a/app/assets/javascripts/ide/components/new_dropdown/button.vue b/app/assets/javascripts/ide/components/new_dropdown/button.vue
index 8ae8f97f237..ce80fbee2e0 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/button.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/button.vue
@@ -1,10 +1,9 @@
<script>
-import { GlIcon } from '@gitlab/ui';
-import tooltip from '~/vue_shared/directives/tooltip';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
export default {
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
components: {
GlIcon,
@@ -45,7 +44,7 @@ export default {
<template>
<button
- v-tooltip
+ v-gl-tooltip
:aria-label="label"
:title="tooltipTitle"
type="button"
diff --git a/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue b/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
index f1b882d8f29..87019c3b2a5 100644
--- a/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
+++ b/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
@@ -1,13 +1,9 @@
<script>
import { mapActions, mapState } from 'vuex';
-import tooltip from '~/vue_shared/directives/tooltip';
import IdeSidebarNav from '../ide_sidebar_nav.vue';
export default {
name: 'CollapsibleSidebar',
- directives: {
- tooltip,
- },
components: {
IdeSidebarNav,
},
diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue
index 91bd64a2c9c..6f15773c9ab 100644
--- a/app/assets/javascripts/ide/components/pipelines/list.vue
+++ b/app/assets/javascripts/ide/components/pipelines/list.vue
@@ -1,11 +1,16 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import { escape } from 'lodash';
-import { GlLoadingIcon, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import {
+ GlLoadingIcon,
+ GlIcon,
+ GlSafeHtmlDirective as SafeHtml,
+ GlTabs,
+ GlTab,
+ GlBadge,
+} from '@gitlab/ui';
import { sprintf, __ } from '../../../locale';
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';
import EmptyState from '../../../pipelines/components/pipelines_list/empty_state.vue';
import JobsList from '../jobs/list.vue';
@@ -15,11 +20,12 @@ export default {
components: {
GlIcon,
CiIcon,
- Tabs,
- Tab,
JobsList,
EmptyState,
GlLoadingIcon,
+ GlTabs,
+ GlTab,
+ GlBadge,
},
directives: {
SafeHtml,
@@ -88,22 +94,26 @@ export default {
<p class="gl-mb-0 break-word">{{ latestPipeline.yamlError }}</p>
<p v-safe-html="ciLintText" class="gl-mb-0"></p>
</div>
- <tabs v-else class="ide-pipeline-list">
- <tab :active="!pipelineFailed">
+ <gl-tabs v-else>
+ <gl-tab :active="!pipelineFailed">
<template #title>
{{ __('Jobs') }}
- <span v-if="jobsCount" class="badge badge-pill"> {{ jobsCount }} </span>
+ <gl-badge v-if="jobsCount" size="sm" class="gl-tab-counter-badge">{{
+ jobsCount
+ }}</gl-badge>
</template>
<jobs-list :loading="isLoadingJobs" :stages="stages" />
- </tab>
- <tab :active="pipelineFailed">
+ </gl-tab>
+ <gl-tab :active="pipelineFailed">
<template #title>
{{ __('Failed Jobs') }}
- <span v-if="failedJobsCount" class="badge badge-pill"> {{ failedJobsCount }} </span>
+ <gl-badge v-if="failedJobsCount" size="sm" class="gl-tab-counter-badge">{{
+ failedJobsCount
+ }}</gl-badge>
</template>
<jobs-list :loading="isLoadingJobs" :stages="failedStages" />
- </tab>
- </tabs>
+ </gl-tab>
+ </gl-tabs>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_commit_section.vue b/app/assets/javascripts/ide/components/repo_commit_section.vue
index 92b99b5c731..dfd25feed08 100644
--- a/app/assets/javascripts/ide/components/repo_commit_section.vue
+++ b/app/assets/javascripts/ide/components/repo_commit_section.vue
@@ -1,6 +1,5 @@
<script>
import { mapState, mapActions, mapGetters } from 'vuex';
-import tooltip from '~/vue_shared/directives/tooltip';
import CommitFilesList from './commit_sidebar/list.vue';
import EmptyState from './commit_sidebar/empty_state.vue';
import { stageKeys } from '../constants';
@@ -10,9 +9,6 @@ export default {
CommitFilesList,
EmptyState,
},
- directives: {
- tooltip,
- },
computed: {
...mapState(['changedFiles', 'stagedFiles', 'lastCommitMsg']),
...mapState('commit', ['commitMessage', 'submitCommitLoading']),
@@ -68,7 +64,6 @@ export default {
:active-file-key="activeFileKey"
:empty-state-text="__('There are no changes')"
class="is-first"
- icon-name="unstaged"
/>
</template>
<empty-state v-else />
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index 56bbb6349cd..c8a825065f1 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -9,8 +9,8 @@ import {
WEBIDE_MARK_FILE_START,
WEBIDE_MEASURE_FILE_AFTER_INTERACTION,
WEBIDE_MEASURE_FILE_FROM_REQUEST,
-} from '~/performance_constants';
-import { performanceMarkAndMeasure } from '~/performance_utils';
+} from '~/performance/constants';
+import { performanceMarkAndMeasure } from '~/performance/utils';
import eventHub from '../eventhub';
import {
leftSidebarViews,
@@ -22,6 +22,7 @@ import Editor from '../lib/editor';
import FileTemplatesBar from './file_templates/bar.vue';
import { __ } from '~/locale';
import { extractMarkdownImagesFromEntries } from '../stores/utils';
+import { getFileEditorOrDefault } from '../stores/modules/editor/utils';
import { getPathParent, readFileAsDataURL, registerSchema, isTextFile } from '../utils';
import { getRulesWithTraversal } from '../lib/editorconfig/parser';
import mapRulesToMonaco from '../lib/editorconfig/rules_mapper';
@@ -49,6 +50,7 @@ export default {
...mapState('rightPane', {
rightPaneIsOpen: 'isOpen',
}),
+ ...mapState('editor', ['fileEditors']),
...mapState([
'viewer',
'panelResizing',
@@ -67,6 +69,9 @@ export default {
'getJsonSchemaForPath',
]),
...mapGetters('fileTemplates', ['showFileTemplatesBar']),
+ fileEditor() {
+ return getFileEditorOrDefault(this.fileEditors, this.file.path);
+ },
shouldHideEditor() {
return this.file && !this.file.loading && !isTextFile(this.file);
},
@@ -80,10 +85,10 @@ export default {
return this.shouldHideEditor && this.file.mrChange && this.viewer === viewerTypes.mr;
},
isEditorViewMode() {
- return this.file.viewMode === FILE_VIEW_MODE_EDITOR;
+ return this.fileEditor.viewMode === FILE_VIEW_MODE_EDITOR;
},
isPreviewViewMode() {
- return this.file.viewMode === FILE_VIEW_MODE_PREVIEW;
+ return this.fileEditor.viewMode === FILE_VIEW_MODE_PREVIEW;
},
editTabCSS() {
return {
@@ -125,8 +130,7 @@ export default {
this.initEditor();
if (this.currentActivityView !== leftSidebarViews.edit.name) {
- this.setFileViewMode({
- file: this.file,
+ this.updateEditor({
viewMode: FILE_VIEW_MODE_EDITOR,
});
}
@@ -134,8 +138,7 @@ export default {
},
currentActivityView() {
if (this.currentActivityView !== leftSidebarViews.edit.name) {
- this.setFileViewMode({
- file: this.file,
+ this.updateEditor({
viewMode: FILE_VIEW_MODE_EDITOR,
});
}
@@ -195,13 +198,11 @@ export default {
'getFileData',
'getRawFileData',
'changeFileContent',
- 'setFileLanguage',
- 'setEditorPosition',
- 'setFileViewMode',
'removePendingTab',
'triggerFilesChange',
'addTempImage',
]),
+ ...mapActions('editor', ['updateFileEditor']),
initEditor() {
if (this.shouldHideEditor && (this.file.content || this.file.raw)) {
return;
@@ -284,19 +285,19 @@ export default {
// Handle Cursor Position
this.editor.onPositionChange((instance, e) => {
- this.setEditorPosition({
+ this.updateEditor({
editorRow: e.position.lineNumber,
editorColumn: e.position.column,
});
});
this.editor.setPosition({
- lineNumber: this.file.editorRow,
- column: this.file.editorColumn,
+ lineNumber: this.fileEditor.editorRow,
+ column: this.fileEditor.editorColumn,
});
// Handle File Language
- this.setFileLanguage({
+ this.updateEditor({
fileLanguage: this.model.language,
});
@@ -354,6 +355,16 @@ export default {
const schema = this.getJsonSchemaForPath(this.file.path);
registerSchema(schema);
},
+ updateEditor(data) {
+ // Looks like our model wrapper `.dispose` causes the monaco editor to emit some position changes after
+ // when disposing. We want to ignore these by only capturing editor changes that happen to the currently active
+ // file.
+ if (!this.file.active) {
+ return;
+ }
+
+ this.updateFileEditor({ path: this.file.path, data });
+ },
},
viewerTypes,
FILE_VIEW_MODE_EDITOR,
@@ -369,7 +380,7 @@ export default {
<a
href="javascript:void(0);"
role="button"
- @click.prevent="setFileViewMode({ file, viewMode: $options.FILE_VIEW_MODE_EDITOR })"
+ @click.prevent="updateEditor({ viewMode: $options.FILE_VIEW_MODE_EDITOR })"
>
{{ __('Edit') }}
</a>
@@ -378,7 +389,7 @@ export default {
<a
href="javascript:void(0);"
role="button"
- @click.prevent="setFileViewMode({ file, viewMode: $options.FILE_VIEW_MODE_PREVIEW })"
+ @click.prevent="updateEditor({ viewMode: $options.FILE_VIEW_MODE_PREVIEW })"
>{{ previewMode.previewTitle }}</a
>
</li>
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 1402f7aaf39..72c56daf69c 100644
--- a/app/assets/javascripts/ide/components/repo_file_status_icon.vue
+++ b/app/assets/javascripts/ide/components/repo_file_status_icon.vue
@@ -1,7 +1,6 @@
<script>
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import tooltip from '~/vue_shared/directives/tooltip';
import '~/lib/utils/datetime_utility';
export default {
@@ -9,7 +8,7 @@ export default {
GlIcon,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
file: {
@@ -28,7 +27,7 @@ export default {
</script>
<template>
- <span v-if="file.file_lock" v-tooltip :title="lockTooltip" data-container="body">
+ <span v-if="file.file_lock" v-gl-tooltip :title="lockTooltip" data-container="body">
<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 60a80a31a8b..e3c41eee15e 100644
--- a/app/assets/javascripts/ide/components/repo_tab.vue
+++ b/app/assets/javascripts/ide/components/repo_tab.vue
@@ -29,9 +29,9 @@ export default {
...mapGetters(['getUrlForPath']),
closeLabel() {
if (this.fileHasChanged) {
- return sprintf(__(`%{tabname} changed`), { tabname: this.tab.name });
+ return sprintf(__('%{tabname} changed'), { tabname: this.tab.name });
}
- return sprintf(__(`Close %{tabname}`, { tabname: this.tab.name }));
+ return sprintf(__('Close %{tabname}'), { tabname: this.tab.name });
},
showChangedIcon() {
if (this.tab.pending) return true;
diff --git a/app/assets/javascripts/ide/components/terminal/empty_state.vue b/app/assets/javascripts/ide/components/terminal/empty_state.vue
index 3668dd24e81..f4dd83b16c7 100644
--- a/app/assets/javascripts/ide/components/terminal/empty_state.vue
+++ b/app/assets/javascripts/ide/components/terminal/empty_state.vue
@@ -1,10 +1,14 @@
<script>
-/* eslint-disable vue/no-v-html */
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlButton, GlAlert, GlSafeHtmlDirective } from '@gitlab/ui';
export default {
components: {
GlLoadingIcon,
+ GlButton,
+ GlAlert,
+ },
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
},
props: {
isLoading: {
@@ -41,24 +45,26 @@ export default {
};
</script>
<template>
- <div class="text-center p-3">
+ <div class="gl-text-center gl-p-5">
<div v-if="illustrationPath" class="svg-content svg-130"><img :src="illustrationPath" /></div>
<h4>{{ __('Web Terminal') }}</h4>
<gl-loading-icon v-if="isLoading" size="lg" class="gl-mt-3" />
<template v-else>
<p>{{ __('Run tests against your code live using the Web Terminal') }}</p>
<p>
- <button
+ <gl-button
:disabled="!isValid"
- class="btn btn-info"
- type="button"
+ category="primary"
+ variant="info"
data-qa-selector="start_web_terminal_button"
@click="onStart"
>
{{ __('Start Web Terminal') }}
- </button>
+ </gl-button>
</p>
- <div v-if="!isValid && message" class="bs-callout text-left" v-html="message"></div>
+ <gl-alert v-if="!isValid && message" variant="tip" :dismissible="false">
+ <span v-safe-html="message"></span>
+ </gl-alert>
<p v-else>
<a
v-if="helpPath"
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index b8d59f8bd36..1496170447d 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -5,7 +5,7 @@ import { visitUrl } from '~/lib/utils/url_utility';
import { deprecatedCreateFlash as flash } from '~/flash';
import * as types from './mutation_types';
import { decorateFiles } from '../lib/files';
-import { stageKeys } from '../constants';
+import { stageKeys, commitActionTypes } from '../constants';
import service from '../services';
import eventHub from '../eventhub';
@@ -242,7 +242,7 @@ export const renameEntry = ({ dispatch, commit, state, getters }, { path, name,
}
}
- dispatch('triggerFilesChange');
+ dispatch('triggerFilesChange', { type: commitActionTypes.move, path, newPath });
};
export const getBranchData = ({ commit, state }, { projectId, branchId, force = false } = {}) =>
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index a0df85540f9..4b9b958ddd6 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -164,26 +164,6 @@ export const changeFileContent = ({ commit, state, getters }, { path, content })
}
};
-export const setFileLanguage = ({ getters, commit }, { fileLanguage }) => {
- if (getters.activeFile) {
- commit(types.SET_FILE_LANGUAGE, { file: getters.activeFile, fileLanguage });
- }
-};
-
-export const setEditorPosition = ({ getters, commit }, { editorRow, editorColumn }) => {
- if (getters.activeFile) {
- commit(types.SET_FILE_POSITION, {
- file: getters.activeFile,
- editorRow,
- editorColumn,
- });
- }
-};
-
-export const setFileViewMode = ({ commit }, { file, viewMode }) => {
- commit(types.SET_FILE_VIEWMODE, { file, viewMode });
-};
-
export const restoreOriginalFile = ({ dispatch, state, commit }, path) => {
const file = state.entries[path];
const isDestructiveDiscard = file.tempFile || file.prevPath;
@@ -289,7 +269,7 @@ export const removePendingTab = ({ commit }, file) => {
eventHub.$emit(`editor.update.model.dispose.${file.key}`);
};
-export const triggerFilesChange = () => {
+export const triggerFilesChange = (ctx, payload = {}) => {
// Used in EE for file mirroring
- eventHub.$emit('ide.files.change');
+ eventHub.$emit('ide.files.change', payload);
};
diff --git a/app/assets/javascripts/ide/stores/index.js b/app/assets/javascripts/ide/stores/index.js
index 324c5b0c6e4..d543209716a 100644
--- a/app/assets/javascripts/ide/stores/index.js
+++ b/app/assets/javascripts/ide/stores/index.js
@@ -12,6 +12,8 @@ import fileTemplates from './modules/file_templates';
import paneModule from './modules/pane';
import clientsideModule from './modules/clientside';
import routerModule from './modules/router';
+import editorModule from './modules/editor';
+import { setupFileEditorsSync } from './modules/editor/setup';
Vue.use(Vuex);
@@ -29,7 +31,14 @@ export const createStoreOptions = () => ({
rightPane: paneModule(),
clientside: clientsideModule(),
router: routerModule,
+ editor: editorModule,
},
});
-export const createStore = () => new Vuex.Store(createStoreOptions());
+export const createStore = () => {
+ const store = new Vuex.Store(createStoreOptions());
+
+ setupFileEditorsSync(store);
+
+ return store;
+};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/getters.js b/app/assets/javascripts/ide/stores/modules/commit/getters.js
index 37f887bcf0a..416ca88d6c9 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/getters.js
@@ -14,6 +14,8 @@ const createTranslatedTextForFiles = (files, text) => {
export const discardDraftButtonDisabled = state =>
state.commitMessage === '' || state.submitCommitLoading;
+// Note: If changing the structure of the placeholder branch name, please also
+// update #patch_branch_name in app/helpers/tree_helper.rb
export const placeholderBranchName = (state, _, rootState) =>
`${gon.current_username}-${rootState.currentBranchId}-patch-${`${new Date().getTime()}`.substr(
-BRANCH_SUFFIX_COUNT,
diff --git a/app/assets/javascripts/ide/stores/modules/editor/actions.js b/app/assets/javascripts/ide/stores/modules/editor/actions.js
new file mode 100644
index 00000000000..cc23a655235
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/editor/actions.js
@@ -0,0 +1,19 @@
+import * as types from './mutation_types';
+
+/**
+ * Action to update the current file editor info at the given `path` with the given `data`
+ *
+ * @param {} vuex
+ * @param {{ path: String, data: any }} payload
+ */
+export const updateFileEditor = ({ commit }, payload) => {
+ commit(types.UPDATE_FILE_EDITOR, payload);
+};
+
+export const removeFileEditor = ({ commit }, path) => {
+ commit(types.REMOVE_FILE_EDITOR, path);
+};
+
+export const renameFileEditor = ({ commit }, payload) => {
+ commit(types.RENAME_FILE_EDITOR, payload);
+};
diff --git a/app/assets/javascripts/ide/stores/modules/editor/getters.js b/app/assets/javascripts/ide/stores/modules/editor/getters.js
new file mode 100644
index 00000000000..dabaafa453a
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/editor/getters.js
@@ -0,0 +1,13 @@
+import { getFileEditorOrDefault } from './utils';
+
+export const activeFileEditor = (state, getters, rootState, rootGetters) => {
+ const { activeFile } = rootGetters;
+
+ if (!activeFile) {
+ return null;
+ }
+
+ const { path } = rootGetters.activeFile;
+
+ return getFileEditorOrDefault(state.fileEditors, path);
+};
diff --git a/app/assets/javascripts/ide/stores/modules/editor/index.js b/app/assets/javascripts/ide/stores/modules/editor/index.js
new file mode 100644
index 00000000000..8a7437b427d
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/editor/index.js
@@ -0,0 +1,12 @@
+import * as actions from './actions';
+import * as getters from './getters';
+import state from './state';
+import mutations from './mutations';
+
+export default {
+ namespaced: true,
+ actions,
+ state,
+ mutations,
+ getters,
+};
diff --git a/app/assets/javascripts/ide/stores/modules/editor/mutation_types.js b/app/assets/javascripts/ide/stores/modules/editor/mutation_types.js
new file mode 100644
index 00000000000..89b7e9cbc76
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/editor/mutation_types.js
@@ -0,0 +1,3 @@
+export const UPDATE_FILE_EDITOR = 'UPDATE_FILE_EDITOR';
+export const REMOVE_FILE_EDITOR = 'REMOVE_FILE_EDITOR';
+export const RENAME_FILE_EDITOR = 'RENAME_FILE_EDITOR';
diff --git a/app/assets/javascripts/ide/stores/modules/editor/mutations.js b/app/assets/javascripts/ide/stores/modules/editor/mutations.js
new file mode 100644
index 00000000000..f332fe9dce9
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/editor/mutations.js
@@ -0,0 +1,25 @@
+import Vue from 'vue';
+import * as types from './mutation_types';
+import { getFileEditorOrDefault } from './utils';
+
+export default {
+ [types.UPDATE_FILE_EDITOR](state, { path, data }) {
+ const editor = getFileEditorOrDefault(state.fileEditors, path);
+
+ Vue.set(state.fileEditors, path, Object.assign(editor, data));
+ },
+ [types.REMOVE_FILE_EDITOR](state, path) {
+ Vue.delete(state.fileEditors, path);
+ },
+ [types.RENAME_FILE_EDITOR](state, { path, newPath }) {
+ const existing = state.fileEditors[path];
+
+ // Gracefully do nothing if fileEditor isn't found.
+ if (!existing) {
+ return;
+ }
+
+ Vue.delete(state.fileEditors, path);
+ Vue.set(state.fileEditors, newPath, existing);
+ },
+};
diff --git a/app/assets/javascripts/ide/stores/modules/editor/setup.js b/app/assets/javascripts/ide/stores/modules/editor/setup.js
new file mode 100644
index 00000000000..c5a613c6baa
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/editor/setup.js
@@ -0,0 +1,19 @@
+import eventHub from '~/ide/eventhub';
+import { commitActionTypes } from '~/ide/constants';
+
+const removeUnusedFileEditors = store => {
+ Object.keys(store.state.editor.fileEditors)
+ .filter(path => !store.state.entries[path])
+ .forEach(path => store.dispatch('editor/removeFileEditor', path));
+};
+
+export const setupFileEditorsSync = store => {
+ eventHub.$on('ide.files.change', ({ type, ...payload } = {}) => {
+ if (type === commitActionTypes.move) {
+ store.dispatch('editor/renameFileEditor', payload);
+ } else {
+ // The files have changed, but the specific change is not known.
+ removeUnusedFileEditors(store);
+ }
+ });
+};
diff --git a/app/assets/javascripts/ide/stores/modules/editor/state.js b/app/assets/javascripts/ide/stores/modules/editor/state.js
new file mode 100644
index 00000000000..484aeec5cc3
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/editor/state.js
@@ -0,0 +1,8 @@
+export default () => ({
+ // Object which represents a dictionary of filePath to editor specific properties, including:
+ // - fileLanguage
+ // - editorRow
+ // - editorCol
+ // - viewMode
+ fileEditors: {},
+});
diff --git a/app/assets/javascripts/ide/stores/modules/editor/utils.js b/app/assets/javascripts/ide/stores/modules/editor/utils.js
new file mode 100644
index 00000000000..bef21d04b2b
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/editor/utils.js
@@ -0,0 +1,11 @@
+import { FILE_VIEW_MODE_EDITOR } from '../../../constants';
+
+export const createDefaultFileEditor = () => ({
+ editorRow: 1,
+ editorColumn: 1,
+ fileLanguage: '',
+ viewMode: FILE_VIEW_MODE_EDITOR,
+});
+
+export const getFileEditorOrDefault = (fileEditors, path) =>
+ fileEditors[path] || createDefaultFileEditor();
diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js
index ae119c2b1fd..22ff29e8866 100644
--- a/app/assets/javascripts/ide/stores/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/mutation_types.js
@@ -36,9 +36,6 @@ export const SET_FILE_ACTIVE = 'SET_FILE_ACTIVE';
export const SET_FILE_RAW_DATA = 'SET_FILE_RAW_DATA';
export const SET_FILE_BASE_RAW_DATA = 'SET_FILE_BASE_RAW_DATA';
export const UPDATE_FILE_CONTENT = 'UPDATE_FILE_CONTENT';
-export const SET_FILE_LANGUAGE = 'SET_FILE_LANGUAGE';
-export const SET_FILE_POSITION = 'SET_FILE_POSITION';
-export const SET_FILE_VIEWMODE = 'SET_FILE_VIEWMODE';
export const DISCARD_FILE_CHANGES = 'DISCARD_FILE_CHANGES';
export const ADD_FILE_TO_CHANGED = 'ADD_FILE_TO_CHANGED';
export const REMOVE_FILE_FROM_CHANGED = 'REMOVE_FILE_FROM_CHANGED';
diff --git a/app/assets/javascripts/ide/stores/mutations/file.js b/app/assets/javascripts/ide/stores/mutations/file.js
index a981f86fa40..61a55d45128 100644
--- a/app/assets/javascripts/ide/stores/mutations/file.js
+++ b/app/assets/javascripts/ide/stores/mutations/file.js
@@ -95,17 +95,6 @@ export default {
changed,
});
},
- [types.SET_FILE_LANGUAGE](state, { file, fileLanguage }) {
- Object.assign(state.entries[file.path], {
- fileLanguage,
- });
- },
- [types.SET_FILE_POSITION](state, { file, editorRow, editorColumn }) {
- Object.assign(state.entries[file.path], {
- editorRow,
- editorColumn,
- });
- },
[types.SET_FILE_MERGE_REQUEST_CHANGE](state, { file, mrChange }) {
let diffMode = diffModes.replaced;
if (mrChange.new_file) {
@@ -122,11 +111,6 @@ export default {
},
});
},
- [types.SET_FILE_VIEWMODE](state, { file, viewMode }) {
- Object.assign(state.entries[file.path], {
- viewMode,
- });
- },
[types.DISCARD_FILE_CHANGES](state, path) {
const stagedFile = state.stagedFiles.find(f => f.path === path);
const entry = state.entries[path];
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
index b7ced3a271a..96f3caf1e98 100644
--- a/app/assets/javascripts/ide/stores/utils.js
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -1,4 +1,4 @@
-import { commitActionTypes, FILE_VIEW_MODE_EDITOR } from '../constants';
+import { commitActionTypes } from '../constants';
import {
relativePathToAbsolute,
isAbsolute,
@@ -25,10 +25,6 @@ export const dataStructure = () => ({
rawPath: '',
raw: '',
content: '',
- editorRow: 1,
- editorColumn: 1,
- fileLanguage: '',
- viewMode: FILE_VIEW_MODE_EDITOR,
size: 0,
parentPath: null,
lastOpenedAt: 0,
diff --git a/app/assets/javascripts/ide/utils.js b/app/assets/javascripts/ide/utils.js
index 4cf4f5e1d81..1ca1b971de1 100644
--- a/app/assets/javascripts/ide/utils.js
+++ b/app/assets/javascripts/ide/utils.js
@@ -1,7 +1,7 @@
import { languages } from 'monaco-editor';
import { flatten, isString } from 'lodash';
import { SIDE_LEFT, SIDE_RIGHT } from './constants';
-import { performanceMarkAndMeasure } from '~/performance_utils';
+import { performanceMarkAndMeasure } from '~/performance/utils';
const toLowerCase = x => x.toLowerCase();
diff --git a/app/assets/javascripts/import_projects/store/actions.js b/app/assets/javascripts/import_projects/store/actions.js
index 7b70d290278..7b7afd13c55 100644
--- a/app/assets/javascripts/import_projects/store/actions.js
+++ b/app/assets/javascripts/import_projects/store/actions.js
@@ -7,11 +7,14 @@ import { visitUrl, objectToQuery } from '~/lib/utils/url_utility';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { s__, sprintf } from '~/locale';
import axios from '~/lib/utils/axios_utils';
+import httpStatusCodes from '~/lib/utils/http_status';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
let eTagPoll;
const hasRedirectInError = e => e?.response?.data?.error?.redirect;
const redirectToUrlInError = e => visitUrl(e.response.data.error.redirect);
+const tooManyRequests = e => e.response.status === httpStatusCodes.TOO_MANY_REQUESTS;
const pathWithParams = ({ path, ...params }) => {
const filteredParams = Object.fromEntries(
Object.entries(params).filter(([, value]) => value !== ''),
@@ -37,8 +40,6 @@ const restartJobsPolling = () => {
if (eTagPoll) eTagPoll.restart();
};
-const setFilter = ({ commit }, filter) => commit(types.SET_FILTER, filter);
-
const setImportTarget = ({ commit }, { repoId, importTarget }) =>
commit(types.SET_IMPORT_TARGET, { repoId, importTarget });
@@ -73,6 +74,14 @@ const fetchReposFactory = ({ reposPath = isRequired() }) => ({ state, commit })
if (hasRedirectInError(e)) {
redirectToUrlInError(e);
+ } else if (tooManyRequests(e)) {
+ createFlash(
+ sprintf(s__('ImportProjects|%{provider} rate limit exceeded. Try again later'), {
+ provider: capitalizeFirstCharacter(provider),
+ }),
+ );
+
+ commit(types.RECEIVE_REPOS_ERROR);
} else {
createFlash(
sprintf(s__('ImportProjects|Requesting your %{provider} repositories failed'), {
@@ -172,12 +181,9 @@ const fetchNamespacesFactory = (namespacesPath = isRequired()) => ({ commit }) =
});
};
-const setPage = ({ state, commit, dispatch }, page) => {
- if (page === state.pageInfo.page) {
- return null;
- }
+const setFilter = ({ commit, dispatch }, filter) => {
+ commit(types.SET_FILTER, filter);
- commit(types.SET_PAGE, page);
return dispatch('fetchRepos');
};
@@ -188,7 +194,6 @@ export default ({ endpoints = isRequired() }) => ({
setFilter,
setImportTarget,
importAll,
- setPage,
fetchRepos: fetchReposFactory({ reposPath: endpoints.reposPath }),
fetchImport: fetchImportFactory(endpoints.importPath),
fetchJobs: fetchJobsFactory(endpoints.jobsPath),
diff --git a/app/assets/javascripts/importer_status.js b/app/assets/javascripts/importer_status.js
index 349ca14b4e8..078c50ee9c6 100644
--- a/app/assets/javascripts/importer_status.js
+++ b/app/assets/javascripts/importer_status.js
@@ -3,7 +3,7 @@ import { escape } from 'lodash';
import { __, sprintf } from './locale';
import axios from './lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from './flash';
-import { parseBoolean } from './lib/utils/common_utils';
+import { parseBoolean, spriteIcon } from './lib/utils/common_utils';
class ImporterStatus {
constructor({ jobsUrl, importUrl, ciCdOnly }) {
@@ -108,7 +108,7 @@ class ImporterStatus {
switch (job.import_status) {
case 'finished':
jobItem.removeClass('table-active').addClass('table-success');
- statusField.html(`<span><i class="fa fa-check"></i> ${__('Done')}</span>`);
+ statusField.html(`<span>${spriteIcon('check', 's16')} ${__('Done')}</span>`);
break;
case 'scheduled':
statusField.html(`${spinner} ${__('Scheduled')}`);
diff --git a/app/assets/javascripts/incidents/components/incidents_list.vue b/app/assets/javascripts/incidents/components/incidents_list.vue
index e1f9d858f2b..0e3839deaf5 100644
--- a/app/assets/javascripts/incidents/components/incidents_list.vue
+++ b/app/assets/javascripts/incidents/components/incidents_list.vue
@@ -69,9 +69,12 @@ export default {
{
key: 'incidentSla',
label: s__('IncidentManagement|Time to SLA'),
- thClass: `gl-pointer-events-none gl-text-right gl-w-eighth`,
+ thClass: `gl-text-right gl-w-eighth`,
tdClass: `${tdClass} gl-text-right`,
thAttr: TH_INCIDENT_SLA_TEST_ID,
+ sortKey: 'SLA_DUE_AT',
+ sortable: true,
+ sortDirection: 'asc',
},
{
key: 'assignees',
@@ -253,13 +256,22 @@ export default {
this.redirecting = true;
},
fetchSortedData({ sortBy, sortDesc }) {
+ let sortKey;
+ // In bootstrap-vue v2.17.0, sortKey becomes natively supported and we can eliminate this function
+ const field = this.availableFields.find(({ key }) => key === sortBy);
const sortingDirection = sortDesc ? 'DESC' : 'ASC';
- const sortingColumn = convertToSnakeCase(sortBy)
- .replace(/_.*/, '')
- .toUpperCase();
+
+ // Use `sortKey` if provided, otherwise fall back to existing algorithm
+ if (field?.sortKey) {
+ sortKey = field.sortKey;
+ } else {
+ sortKey = convertToSnakeCase(sortBy)
+ .replace(/_.*/, '')
+ .toUpperCase();
+ }
this.pagination = initialPaginationState;
- this.sort = `${sortingColumn}_${sortingDirection}`;
+ this.sort = `${sortKey}_${sortingDirection}`;
},
getSeverity(severity) {
return INCIDENT_SEVERITY[severity];
@@ -407,7 +419,7 @@ export default {
</template>
</gl-table>
</template>
- <template #emtpy-state>
+ <template #empty-state>
<gl-empty-state
:title="emptyStateData.title"
:svg-path="emptyListSvgPath"
diff --git a/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue b/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue
index 890381a8f29..93ea1f4f636 100644
--- a/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue
+++ b/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue
@@ -8,14 +8,14 @@ export default {
GlModal,
},
computed: {
- ...mapGetters(['isSavingOrTesting']),
+ ...mapGetters(['isDisabled']),
primaryProps() {
return {
text: __('Save'),
attributes: [
{ variant: 'success' },
{ category: 'primary' },
- { disabled: this.isSavingOrTesting },
+ { disabled: this.isDisabled },
],
};
},
@@ -52,7 +52,7 @@ export default {
<p class="gl-mb-0">
{{
s__(
- 'Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults.',
+ 'Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults.',
)
}}
</p>
diff --git a/app/assets/javascripts/integrations/edit/components/integration_form.vue b/app/assets/javascripts/integrations/edit/components/integration_form.vue
index 0fd39c5635d..bbfa865905a 100644
--- a/app/assets/javascripts/integrations/edit/components/integration_form.vue
+++ b/app/assets/javascripts/integrations/edit/components/integration_form.vue
@@ -12,6 +12,7 @@ import JiraIssuesFields from './jira_issues_fields.vue';
import TriggerFields from './trigger_fields.vue';
import DynamicField from './dynamic_field.vue';
import ConfirmationModal from './confirmation_modal.vue';
+import ResetConfirmationModal from './reset_confirmation_modal.vue';
export default {
name: 'IntegrationForm',
@@ -23,6 +24,7 @@ export default {
TriggerFields,
DynamicField,
ConfirmationModal,
+ ResetConfirmationModal,
GlButton,
},
directives: {
@@ -30,23 +32,29 @@ export default {
},
mixins: [glFeatureFlagsMixin()],
computed: {
- ...mapGetters(['currentKey', 'propsSource', 'isSavingOrTesting']),
- ...mapState(['defaultState', 'override', 'isSaving', 'isTesting']),
+ ...mapGetters(['currentKey', 'propsSource', 'isDisabled']),
+ ...mapState(['defaultState', 'override', 'isSaving', 'isTesting', 'isResetting']),
isEditable() {
return this.propsSource.editable;
},
isJira() {
return this.propsSource.type === 'jira';
},
- isInstanceLevel() {
- return this.propsSource.integrationLevel === integrationLevels.INSTANCE;
+ isInstanceOrGroupLevel() {
+ return (
+ this.propsSource.integrationLevel === integrationLevels.INSTANCE ||
+ this.propsSource.integrationLevel === integrationLevels.GROUP
+ );
},
showJiraIssuesFields() {
return this.isJira && this.glFeatures.jiraIssuesIntegration;
},
+ showReset() {
+ return this.isInstanceOrGroupLevel && this.propsSource.resetPath;
+ },
},
methods: {
- ...mapActions(['setOverride', 'setIsSaving', 'setIsTesting']),
+ ...mapActions(['setOverride', 'setIsSaving', 'setIsTesting', 'setIsResetting']),
onSaveClick() {
this.setIsSaving(true);
eventHub.$emit('saveIntegration');
@@ -55,6 +63,7 @@ export default {
this.setIsTesting(true);
eventHub.$emit('testIntegration');
},
+ onResetClick() {},
},
};
</script>
@@ -91,13 +100,13 @@ export default {
v-bind="propsSource.jiraIssuesProps"
/>
<div v-if="isEditable" class="footer-block row-content-block">
- <template v-if="isInstanceLevel">
+ <template v-if="isInstanceOrGroupLevel">
<gl-button
v-gl-modal.confirmSaveIntegration
category="primary"
variant="success"
:loading="isSaving"
- :disabled="isSavingOrTesting"
+ :disabled="isDisabled"
data-qa-selector="save_changes_button"
>
{{ __('Save changes') }}
@@ -110,7 +119,7 @@ export default {
variant="success"
type="submit"
:loading="isSaving"
- :disabled="isSavingOrTesting"
+ :disabled="isDisabled"
data-qa-selector="save_changes_button"
@click.prevent="onSaveClick"
>
@@ -120,13 +129,27 @@ export default {
<gl-button
v-if="propsSource.canTest"
:loading="isTesting"
- :disabled="isSavingOrTesting"
+ :disabled="isDisabled"
:href="propsSource.testPath"
@click.prevent="onTestClick"
>
{{ __('Test settings') }}
</gl-button>
+ <template v-if="showReset">
+ <gl-button
+ v-gl-modal.confirmResetIntegration
+ category="secondary"
+ variant="default"
+ :loading="isResetting"
+ :disabled="isDisabled"
+ data-testid="reset-button"
+ >
+ {{ __('Reset') }}
+ </gl-button>
+ <reset-confirmation-modal @reset="onResetClick" />
+ </template>
+
<gl-button class="btn-cancel" :href="propsSource.cancelPath">{{ __('Cancel') }}</gl-button>
</div>
</div>
diff --git a/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue b/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
index 08f24ce8ab6..123d794912a 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
@@ -108,12 +108,7 @@ export default {
:label="s__('Integrations|Comment detail:')"
data-testid="comment-detail"
>
- <input
- v-if="isInheriting"
- name="service[comment_detail]"
- type="hidden"
- :value="commentDetail"
- />
+ <input name="service[comment_detail]" type="hidden" :value="commentDetail" />
<gl-form-radio
v-for="commentDetailOption in commentDetailOptions"
:key="commentDetailOption.value"
diff --git a/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue b/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue
new file mode 100644
index 00000000000..d8503910566
--- /dev/null
+++ b/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue
@@ -0,0 +1,61 @@
+<script>
+import { mapGetters } from 'vuex';
+import { GlModal } from '@gitlab/ui';
+
+import { __ } from '~/locale';
+
+export default {
+ components: {
+ GlModal,
+ },
+ computed: {
+ ...mapGetters(['isDisabled']),
+ primaryProps() {
+ return {
+ text: __('Reset'),
+ attributes: [
+ { variant: 'warning' },
+ { category: 'primary' },
+ { disabled: this.isDisabled },
+ ],
+ };
+ },
+ cancelProps() {
+ return {
+ text: __('Cancel'),
+ };
+ },
+ },
+ methods: {
+ onReset() {
+ this.$emit('reset');
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-modal
+ modal-id="confirmResetIntegration"
+ size="sm"
+ :title="s__('Integrations|Reset integration?')"
+ :action-primary="primaryProps"
+ :action-cancel="cancelProps"
+ @primary="onReset"
+ >
+ <p>
+ {{
+ s__(
+ 'Integrations|Resetting this integration will clear the settings and deactivate this integration.',
+ )
+ }}
+ </p>
+ <p>
+ {{ s__('Integrations|All projects inheriting these settings will also be reset.') }}
+ </p>
+
+ <p class="gl-mb-0">
+ {{ s__('Integrations|Projects using custom settings will not be affected.') }}
+ </p>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/integrations/edit/index.js b/app/assets/javascripts/integrations/edit/index.js
index 248ee62d43a..95a53f1beab 100644
--- a/app/assets/javascripts/integrations/edit/index.js
+++ b/app/assets/javascripts/integrations/edit/index.js
@@ -26,6 +26,7 @@ function parseDatasetToProps(data) {
integrationLevel,
cancelPath,
testPath,
+ resetPath,
...booleanAttributes
} = data;
const {
@@ -49,6 +50,7 @@ function parseDatasetToProps(data) {
editable,
canTest,
testPath,
+ resetPath,
triggerFieldsProps: {
initialTriggerCommit: commitEvents,
initialTriggerMergeRequest: mergeRequestEvents,
diff --git a/app/assets/javascripts/integrations/edit/store/actions.js b/app/assets/javascripts/integrations/edit/store/actions.js
index 199c9074ead..097304be242 100644
--- a/app/assets/javascripts/integrations/edit/store/actions.js
+++ b/app/assets/javascripts/integrations/edit/store/actions.js
@@ -3,3 +3,5 @@ import * as types from './mutation_types';
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);
+export const setIsResetting = ({ commit }, isResetting) =>
+ commit(types.SET_IS_RESETTING, isResetting);
diff --git a/app/assets/javascripts/integrations/edit/store/getters.js b/app/assets/javascripts/integrations/edit/store/getters.js
index 4ee5f11855c..310d970c73e 100644
--- a/app/assets/javascripts/integrations/edit/store/getters.js
+++ b/app/assets/javascripts/integrations/edit/store/getters.js
@@ -1,6 +1,6 @@
export const isInheriting = state => (state.defaultState === null ? false : !state.override);
-export const isSavingOrTesting = state => state.isSaving || state.isTesting;
+export const isDisabled = state => state.isSaving || state.isTesting || state.isResetting;
export const propsSource = (state, getters) =>
getters.isInheriting ? state.defaultState : state.customState;
diff --git a/app/assets/javascripts/integrations/edit/store/mutation_types.js b/app/assets/javascripts/integrations/edit/store/mutation_types.js
index 0dae8ea079e..2a84408f658 100644
--- a/app/assets/javascripts/integrations/edit/store/mutation_types.js
+++ b/app/assets/javascripts/integrations/edit/store/mutation_types.js
@@ -1,3 +1,4 @@
export const SET_OVERRIDE = 'SET_OVERRIDE';
export const SET_IS_SAVING = 'SET_IS_SAVING';
export const SET_IS_TESTING = 'SET_IS_TESTING';
+export const SET_IS_RESETTING = 'SET_IS_RESETTING';
diff --git a/app/assets/javascripts/integrations/edit/store/mutations.js b/app/assets/javascripts/integrations/edit/store/mutations.js
index 8ac3c476f9e..07e3e25ccf0 100644
--- a/app/assets/javascripts/integrations/edit/store/mutations.js
+++ b/app/assets/javascripts/integrations/edit/store/mutations.js
@@ -10,4 +10,7 @@ export default {
[types.SET_IS_TESTING](state, isTesting) {
state.isTesting = isTesting;
},
+ [types.SET_IS_RESETTING](state, isResetting) {
+ state.isResetting = isResetting;
+ },
};
diff --git a/app/assets/javascripts/integrations/edit/store/state.js b/app/assets/javascripts/integrations/edit/store/state.js
index a9ecee6c539..aae3db1583f 100644
--- a/app/assets/javascripts/integrations/edit/store/state.js
+++ b/app/assets/javascripts/integrations/edit/store/state.js
@@ -7,5 +7,6 @@ export default ({ defaultState = null, customState = {} } = {}) => {
customState,
isSaving: false,
isTesting: false,
+ isResetting: false,
};
};
diff --git a/app/assets/javascripts/invite_members/components/invite_members_modal.vue b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
index d2ea14a658b..b55ef77ae5d 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -6,13 +6,13 @@ import {
GlDatepicker,
GlLink,
GlSprintf,
- GlSearchBoxByType,
GlButton,
GlFormInput,
} from '@gitlab/ui';
import eventHub from '../event_hub';
-import { s__, sprintf } from '~/locale';
+import { s__, __, sprintf } from '~/locale';
import Api from '~/api';
+import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
export default {
name: 'InviteMembersModal',
@@ -23,16 +23,20 @@ export default {
GlDropdown,
GlDropdownItem,
GlSprintf,
- GlSearchBoxByType,
GlButton,
GlFormInput,
+ MembersTokenSelect,
},
props: {
- groupId: {
+ id: {
type: String,
required: true,
},
- groupName: {
+ isProject: {
+ type: Boolean,
+ required: true,
+ },
+ name: {
type: String,
required: true,
},
@@ -59,9 +63,16 @@ export default {
};
},
computed: {
+ inviteToName() {
+ return this.name.toUpperCase();
+ },
+ inviteToType() {
+ return this.isProject ? __('project') : __('group');
+ },
introText() {
- return sprintf(s__("InviteMembersModal|You're inviting members to the %{group_name} group"), {
- group_name: this.groupName,
+ return sprintf(s__("InviteMembersModal|You're inviting members to the %{name} %{type}"), {
+ name: this.inviteToName,
+ type: this.inviteToType,
});
},
toastOptions() {
@@ -110,13 +121,14 @@ export default {
this.selectedAccessLevel = item;
},
submitForm(formData) {
- return Api.inviteGroupMember(this.groupId, formData)
- .then(() => {
- this.showToastMessageSuccess();
- })
- .catch(error => {
- this.showToastMessageError(error);
- });
+ if (this.isProject) {
+ return Api.inviteProjectMembers(this.id, formData)
+ .then(this.showToastMessageSuccess)
+ .catch(this.showToastMessageError);
+ }
+ return Api.inviteGroupMember(this.id, formData)
+ .then(this.showToastMessageSuccess)
+ .catch(this.showToastMessageError);
},
showToastMessageSuccess() {
this.$toast.show(this.$options.labels.toastMessageSuccessful, this.toastOptions);
@@ -129,44 +141,45 @@ export default {
},
labels: {
modalTitle: s__('InviteMembersModal|Invite team members'),
- userToInvite: s__('InviteMembersModal|GitLab member or Email address'),
+ newUsersToInvite: s__('InviteMembersModal|GitLab member or Email address'),
userPlaceholder: s__('InviteMembersModal|Search for members to invite'),
accessLevel: s__('InviteMembersModal|Choose a role permission'),
accessExpireDate: s__('InviteMembersModal|Access expiration date (optional)'),
- toastMessageSuccessful: s__('InviteMembersModal|Users were succesfully added'),
- toastMessageUnsuccessful: s__('InviteMembersModal|User not invited. Feature coming soon!'),
+ toastMessageSuccessful: s__('InviteMembersModal|Members were successfully added'),
+ toastMessageUnsuccessful: s__('InviteMembersModal|Some of the members could not be added'),
readMoreText: s__(`InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions`),
inviteButtonText: s__('InviteMembersModal|Invite'),
cancelButtonText: s__('InviteMembersModal|Cancel'),
+ headerCloseLabel: s__('InviteMembersModal|Close invite team members'),
},
+ membersTokenSelectLabelId: 'invite-members-input',
};
</script>
<template>
- <gl-modal :modal-id="modalId" size="sm" :title="$options.labels.modalTitle">
+ <gl-modal
+ :modal-id="modalId"
+ size="sm"
+ :title="$options.labels.modalTitle"
+ :header-close-label="$options.labels.headerCloseLabel"
+ >
<div class="gl-ml-5 gl-mr-5">
<div>{{ introText }}</div>
- <label class="gl-font-weight-bold gl-mt-5">{{ $options.labels.userToInvite }}</label>
+ <label :id="$options.membersTokenSelectLabelId" class="gl-font-weight-bold gl-mt-5">{{
+ $options.labels.newUsersToInvite
+ }}</label>
<div class="gl-mt-2">
- <gl-search-box-by-type
+ <members-token-select
v-model="newUsersToInvite"
+ :label="$options.labels.newUsersToInvite"
+ :aria-labelledby="$options.membersTokenSelectLabelId"
:placeholder="$options.labels.userPlaceholder"
- type="text"
- autocomplete="off"
- autocorrect="off"
- autocapitalize="off"
- spellcheck="false"
/>
</div>
<label class="gl-font-weight-bold gl-mt-5">{{ $options.labels.accessLevel }}</label>
<div class="gl-mt-2 gl-w-half gl-xs-w-full">
- <gl-dropdown
- menu-class="dropdown-menu-selectable"
- class="gl-shadow-none gl-w-full"
- v-bind="$attrs"
- :text="selectedRoleName"
- >
+ <gl-dropdown class="gl-shadow-none gl-w-full" v-bind="$attrs" :text="selectedRoleName">
<template v-for="(key, item) in accessLevels">
<gl-dropdown-item
:key="key"
@@ -215,9 +228,13 @@ export default {
{{ $options.labels.cancelButtonText }}
</gl-button>
<div class="gl-mr-3"></div>
- <gl-button ref="inviteButton" variant="success" @click="sendInvite">{{
- $options.labels.inviteButtonText
- }}</gl-button>
+ <gl-button
+ ref="inviteButton"
+ :disabled="!newUsersToInvite"
+ variant="success"
+ @click="sendInvite"
+ >{{ $options.labels.inviteButtonText }}</gl-button
+ >
</div>
</template>
</gl-modal>
diff --git a/app/assets/javascripts/invite_members/components/members_token_select.vue b/app/assets/javascripts/invite_members/components/members_token_select.vue
new file mode 100644
index 00000000000..aed2e5e3236
--- /dev/null
+++ b/app/assets/javascripts/invite_members/components/members_token_select.vue
@@ -0,0 +1,120 @@
+<script>
+import { debounce } from 'lodash';
+import { GlTokenSelector, GlAvatar, GlAvatarLabeled } from '@gitlab/ui';
+import { USER_SEARCH_DELAY } from '../constants';
+import Api from '~/api';
+
+export default {
+ components: {
+ GlTokenSelector,
+ GlAvatar,
+ GlAvatarLabeled,
+ },
+ props: {
+ placeholder: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ ariaLabelledby: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ loading: false,
+ query: '',
+ users: [],
+ selectedTokens: [],
+ hasBeenFocused: false,
+ hideDropdownWithNoItems: true,
+ };
+ },
+ computed: {
+ newUsersToInvite() {
+ return this.selectedTokens
+ .map(obj => {
+ return obj.id;
+ })
+ .join(',');
+ },
+ placeholderText() {
+ if (this.selectedTokens.length === 0) {
+ return this.placeholder;
+ }
+ return '';
+ },
+ },
+ methods: {
+ handleTextInput(query) {
+ this.hideDropdownWithNoItems = false;
+ this.query = query;
+ this.loading = true;
+ this.retrieveUsers(query);
+ },
+ retrieveUsers: debounce(function debouncedRetrieveUsers() {
+ return Api.users(this.query, this.$options.queryOptions)
+ .then(response => {
+ this.users = response.data.map(token => ({
+ id: token.id,
+ name: token.name,
+ username: token.username,
+ avatar_url: token.avatar_url,
+ }));
+ this.loading = false;
+ })
+ .catch(() => {
+ this.loading = false;
+ });
+ }, USER_SEARCH_DELAY),
+ handleInput() {
+ this.$emit('input', this.newUsersToInvite);
+ },
+ handleBlur() {
+ this.hideDropdownWithNoItems = false;
+ },
+ handleFocus() {
+ // The modal auto-focuses on the input when opened.
+ // This prevents the dropdown from opening when the modal opens.
+ if (this.hasBeenFocused) {
+ this.loading = true;
+ this.retrieveUsers();
+ }
+
+ this.hasBeenFocused = true;
+ },
+ },
+ queryOptions: { exclude_internal: true, active: true },
+};
+</script>
+
+<template>
+ <gl-token-selector
+ v-model="selectedTokens"
+ :dropdown-items="users"
+ :loading="loading"
+ :allow-user-defined-tokens="false"
+ :hide-dropdown-with-no-items="hideDropdownWithNoItems"
+ :placeholder="placeholderText"
+ :aria-labelledby="ariaLabelledby"
+ @blur="handleBlur"
+ @text-input="handleTextInput"
+ @input="handleInput"
+ @focus="handleFocus"
+ >
+ <template #token-content="{ token }">
+ <gl-avatar v-if="token.avatar_url" :src="token.avatar_url" :size="16" />
+ {{ token.name }}
+ </template>
+
+ <template #dropdown-item-content="{ dropdownItem }">
+ <gl-avatar-labeled
+ :src="dropdownItem.avatar_url"
+ :size="32"
+ :label="dropdownItem.name"
+ :sub-label="dropdownItem.username"
+ />
+ </template>
+ </gl-token-selector>
+</template>
diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js
new file mode 100644
index 00000000000..1ff2125c292
--- /dev/null
+++ b/app/assets/javascripts/invite_members/constants.js
@@ -0,0 +1 @@
+export const USER_SEARCH_DELAY = 200;
diff --git a/app/assets/javascripts/invite_members/init_invite_members_modal.js b/app/assets/javascripts/invite_members/init_invite_members_modal.js
index 92aa3187fc3..db957ecacfd 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_modal.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_modal.js
@@ -18,7 +18,6 @@ export default function initInviteMembersModal() {
props: {
...el.dataset,
accessLevels: JSON.parse(el.dataset.accessLevels),
- groupName: el.dataset.groupName.toUpperCase(),
},
}),
});
diff --git a/app/assets/javascripts/issuable_list/components/issuable_bulk_edit_sidebar.vue b/app/assets/javascripts/issuable_list/components/issuable_bulk_edit_sidebar.vue
new file mode 100644
index 00000000000..5ca9e50d854
--- /dev/null
+++ b/app/assets/javascripts/issuable_list/components/issuable_bulk_edit_sidebar.vue
@@ -0,0 +1,35 @@
+<script>
+export default {
+ props: {
+ expanded: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ watch: {
+ expanded(value) {
+ const layoutPageEl = document.querySelector('.layout-page');
+
+ if (layoutPageEl) {
+ layoutPageEl.classList.toggle('right-sidebar-expanded', value);
+ layoutPageEl.classList.toggle('right-sidebar-collapsed', !value);
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <aside
+ :class="{ 'right-sidebar-expanded': expanded, 'right-sidebar-collapsed': !expanded }"
+ class="issues-bulk-update right-sidebar"
+ aria-live="polite"
+ >
+ <div
+ class="gl-display-flex gl-justify-content-space-between gl-p-4 gl-border-b-1 gl-border-b-solid gl-border-gray-100"
+ >
+ <slot name="bulk-edit-actions"></slot>
+ </div>
+ <slot name="sidebar-items"></slot>
+ </aside>
+</template>
diff --git a/app/assets/javascripts/issuable_list/components/issuable_item.vue b/app/assets/javascripts/issuable_list/components/issuable_item.vue
index d8cb1ab07cd..1ee794ab208 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_item.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_item.vue
@@ -1,15 +1,21 @@
<script>
-import { GlLink, GlLabel, GlTooltipDirective } from '@gitlab/ui';
+import { GlLink, GlIcon, GlLabel, GlFormCheckbox, GlTooltipDirective } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { getTimeago } from '~/lib/utils/datetime_utility';
import { isScopedLabel } from '~/lib/utils/common_utils';
import timeagoMixin from '~/vue_shared/mixins/timeago';
+import IssuableAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
+
export default {
components: {
GlLink,
+ GlIcon,
GlLabel,
+ GlFormCheckbox,
+ IssuableAssignees,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -24,25 +30,42 @@ export default {
type: Object,
required: true,
},
+ enableLabelPermalinks: {
+ type: Boolean,
+ required: true,
+ },
+ showCheckbox: {
+ type: Boolean,
+ required: true,
+ },
+ checked: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
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 getIdFromGraphQLId(`${this.author.id}`);
+ },
+ isIssuableUrlExternal() {
+ // Check if URL is relative, which means it is internal.
+ if (!/^https?:\/\//g.test(this.issuable.webUrl)) {
+ return false;
}
-
- return id;
+ // In case URL is absolute, it may or may not be internal,
+ // hence use `gon.gitlab_url` which is current instance domain.
+ return !this.issuable.webUrl.includes(gon.gitlab_url);
},
labels() {
return this.issuable.labels?.nodes || this.issuable.labels || [];
},
+ assignees() {
+ return this.issuable.assignees || [];
+ },
createdAt() {
return sprintf(__('created %{timeAgo}'), {
timeAgo: getTimeago().format(this.issuable.createdAt),
@@ -53,11 +76,41 @@ export default {
timeAgo: getTimeago().format(this.issuable.updatedAt),
});
},
+ issuableTitleProps() {
+ if (this.isIssuableUrlExternal) {
+ return {
+ target: '_blank',
+ };
+ }
+ return {};
+ },
+ showDiscussions() {
+ return typeof this.issuable.userDiscussionsCount === 'number';
+ },
+ showIssuableMeta() {
+ return Boolean(
+ this.hasSlotContents('status') || this.showDiscussions || this.issuable.assignees,
+ );
+ },
},
methods: {
+ hasSlotContents(slotName) {
+ return Boolean(this.$slots[slotName]);
+ },
scopedLabel(label) {
return isScopedLabel(label);
},
+ labelTitle(label) {
+ return label.title || label.name;
+ },
+ labelTarget(label) {
+ if (this.enableLabelPermalinks) {
+ const key = encodeURIComponent('label_name[]');
+ const value = encodeURIComponent(this.labelTitle(label));
+ return `?${key}=${value}`;
+ }
+ return '#';
+ },
/**
* This is needed as an independent method since
* when user changes current page, `$refs.authorLink`
@@ -74,17 +127,28 @@ export default {
</script>
<template>
- <li class="issue">
+ <li class="issue gl-px-5!">
<div class="issue-box">
+ <div v-if="showCheckbox" class="issue-check">
+ <gl-form-checkbox
+ class="gl-mr-0"
+ :checked="checked"
+ @input="$emit('checked-input', $event)"
+ />
+ </div>
<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>
+ <gl-link :href="issuable.webUrl" v-bind="issuableTitleProps"
+ >{{ issuable.title
+ }}<gl-icon v-if="isIssuableUrlExternal" name="external-link" class="gl-ml-2"
+ /></gl-link>
</span>
</div>
<div class="issuable-info">
- <span data-testid="issuable-reference" class="issuable-reference"
+ <slot v-if="hasSlotContents('reference')" name="reference"></slot>
+ <span v-else data-testid="issuable-reference" class="issuable-reference"
>{{ issuableSymbol }}{{ issuable.iid }}</span
>
<span class="issuable-authored d-none d-sm-inline-block">
@@ -96,7 +160,9 @@ export default {
>{{ createdAt }}</span
>
{{ __('by') }}
+ <slot v-if="hasSlotContents('author')" name="author"></slot>
<gl-link
+ v-else
:data-user-id="authorId"
:data-username="author.username"
:data-name="author.name"
@@ -108,20 +174,52 @@ export default {
<span class="author">{{ author.name }}</span>
</gl-link>
</span>
+ <slot name="timeframe"></slot>
&nbsp;
<gl-label
v-for="(label, index) in labels"
:key="index"
:background-color="label.color"
- :title="label.title"
+ :title="labelTitle(label)"
:description="label.description"
:scoped="scopedLabel(label)"
+ :target="labelTarget(label)"
:class="{ 'gl-ml-2': index }"
size="sm"
/>
</div>
</div>
<div class="issuable-meta">
+ <ul v-if="showIssuableMeta" class="controls">
+ <li v-if="hasSlotContents('status')" class="issuable-status">
+ <slot name="status"></slot>
+ </li>
+ <li
+ v-if="showDiscussions"
+ data-testid="issuable-discussions"
+ class="issuable-comments gl-display-none gl-display-sm-block"
+ >
+ <gl-link
+ v-gl-tooltip:tooltipcontainer.top
+ :title="__('Comments')"
+ :href="`${issuable.webUrl}#notes`"
+ :class="{ 'no-comments': !issuable.userDiscussionsCount }"
+ class="gl-reset-color!"
+ >
+ <gl-icon name="comments" />
+ {{ issuable.userDiscussionsCount }}
+ </gl-link>
+ </li>
+ <li v-if="assignees.length" class="gl-display-flex">
+ <issuable-assignees
+ :assignees="issuable.assignees"
+ :icon-size="16"
+ :max-visible="4"
+ img-css-classes="gl-mr-2!"
+ class="gl-align-items-center gl-display-flex gl-ml-3"
+ />
+ </li>
+ </ul>
<div
data-testid="issuable-updated-at"
class="float-right issuable-updated-at d-none d-sm-inline-block"
diff --git a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
index 7535203dea1..b2312c55f01 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
@@ -1,17 +1,23 @@
<script>
-import { GlLoadingIcon, GlPagination } from '@gitlab/ui';
+import { GlSkeletonLoading, GlPagination } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import IssuableTabs from './issuable_tabs.vue';
import IssuableItem from './issuable_item.vue';
+import IssuableBulkEditSidebar from './issuable_bulk_edit_sidebar.vue';
+
+import { DEFAULT_SKELETON_COUNT } from '../constants';
export default {
components: {
- GlLoadingIcon,
+ GlSkeletonLoading,
IssuableTabs,
FilteredSearchBar,
IssuableItem,
+ IssuableBulkEditSidebar,
GlPagination,
},
props: {
@@ -35,6 +41,11 @@ export default {
type: Array,
required: true,
},
+ urlParams: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
initialFilterValue: {
type: Array,
required: false,
@@ -55,7 +66,8 @@ export default {
},
tabCounts: {
type: Object,
- required: true,
+ required: false,
+ default: null,
},
currentTab: {
type: String,
@@ -76,11 +88,21 @@ export default {
required: false,
default: false,
},
+ showBulkEditSidebar: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
defaultPageSize: {
type: Number,
required: false,
default: 20,
},
+ totalItems: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
currentPage: {
type: Number,
required: false,
@@ -96,6 +118,92 @@ export default {
required: false,
default: 2,
},
+ enableLabelPermalinks: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ data() {
+ return {
+ checkedIssuables: {},
+ };
+ },
+ computed: {
+ skeletonItemCount() {
+ const { totalItems, defaultPageSize, currentPage } = this;
+ const totalPages = Math.ceil(totalItems / defaultPageSize);
+
+ if (totalPages) {
+ return currentPage < totalPages
+ ? defaultPageSize
+ : totalItems % defaultPageSize || defaultPageSize;
+ }
+ return DEFAULT_SKELETON_COUNT;
+ },
+ allIssuablesChecked() {
+ return this.bulkEditIssuables.length === this.issuables.length;
+ },
+ /**
+ * Returns all the checked issuables from `checkedIssuables` map.
+ */
+ bulkEditIssuables() {
+ return Object.keys(this.checkedIssuables).reduce((acc, issuableId) => {
+ if (this.checkedIssuables[issuableId].checked) {
+ acc.push(this.checkedIssuables[issuableId].issuable);
+ }
+ return acc;
+ }, []);
+ },
+ },
+ watch: {
+ issuables(list) {
+ this.checkedIssuables = list.reduce((acc, issuable) => {
+ const id = this.issuableId(issuable);
+ acc[id] = {
+ // By default, an issuable is not checked,
+ // But if `checkedIssuables` is already
+ // populated, use existing value.
+ checked:
+ typeof this.checkedIssuables[id] !== 'boolean'
+ ? false
+ : this.checkedIssuables[id].checked,
+ // We're caching issuable reference here
+ // for ease of populating in `bulkEditIssuables`.
+ issuable,
+ };
+ return acc;
+ }, {});
+ },
+ urlParams: {
+ deep: true,
+ immediate: true,
+ handler(params) {
+ if (Object.keys(params).length) {
+ updateHistory({
+ url: setUrlParams(params, window.location.href, true),
+ title: document.title,
+ replace: true,
+ });
+ }
+ },
+ },
+ },
+ methods: {
+ issuableId(issuable) {
+ return issuable.id || issuable.iid || uniqueId();
+ },
+ issuableChecked(issuable) {
+ return this.checkedIssuables[this.issuableId(issuable)]?.checked;
+ },
+ handleIssuableCheckedInput(issuable, value) {
+ this.checkedIssuables[this.issuableId(issuable)].checked = value;
+ },
+ handleAllIssuablesCheckedInput(value) {
+ Object.keys(this.checkedIssuables).forEach(issuableId => {
+ this.checkedIssuables[issuableId].checked = value;
+ });
+ },
},
};
</script>
@@ -120,27 +228,60 @@ export default {
:sort-options="sortOptions"
:initial-filter-value="initialFilterValue"
:initial-sort-by="initialSortBy"
+ :show-checkbox="showBulkEditSidebar"
+ :checkbox-checked="allIssuablesChecked"
class="gl-flex-grow-1 row-content-block"
+ @checked-input="handleAllIssuablesCheckedInput"
@onFilter="$emit('filter', $event)"
@onSort="$emit('sort', $event)"
/>
+ <issuable-bulk-edit-sidebar :expanded="showBulkEditSidebar">
+ <template #bulk-edit-actions>
+ <slot name="bulk-edit-actions" :checked-issuables="bulkEditIssuables"></slot>
+ </template>
+ <template #sidebar-items>
+ <slot name="sidebar-items" :checked-issuables="bulkEditIssuables"></slot>
+ </template>
+ </issuable-bulk-edit-sidebar>
<div class="issuables-holder">
- <gl-loading-icon v-if="issuablesLoading" size="md" class="gl-mt-5" />
+ <ul v-if="issuablesLoading" class="content-list">
+ <li v-for="n in skeletonItemCount" :key="n" class="issue gl-px-5! gl-py-5!">
+ <gl-skeleton-loading />
+ </li>
+ </ul>
<ul
v-if="!issuablesLoading && issuables.length"
class="content-list issuable-list issues-list"
>
<issuable-item
v-for="issuable in issuables"
- :key="issuable.id"
+ :key="issuableId(issuable)"
:issuable-symbol="issuableSymbol"
:issuable="issuable"
- />
+ :enable-label-permalinks="enableLabelPermalinks"
+ :show-checkbox="showBulkEditSidebar"
+ :checked="issuableChecked(issuable)"
+ @checked-input="handleIssuableCheckedInput(issuable, $event)"
+ >
+ <template #reference>
+ <slot name="reference" :issuable="issuable"></slot>
+ </template>
+ <template #author>
+ <slot name="author" :author="issuable.author"></slot>
+ </template>
+ <template #timeframe>
+ <slot name="timeframe" :issuable="issuable"></slot>
+ </template>
+ <template #status>
+ <slot name="status" :issuable="issuable"></slot>
+ </template>
+ </issuable-item>
</ul>
<slot v-if="!issuablesLoading && !issuables.length" name="empty-state"></slot>
<gl-pagination
v-if="showPaginationControls"
:per-page="defaultPageSize"
+ :total-items="totalItems"
:value="currentPage"
:prev-page="previousPage"
:next-page="nextPage"
diff --git a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
index df544ce69e7..d9aab004077 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
@@ -14,7 +14,8 @@ export default {
},
tabCounts: {
type: Object,
- required: true,
+ required: false,
+ default: null,
},
currentTab: {
type: String,
@@ -40,7 +41,7 @@ export default {
>
<template #title>
<span :title="tab.titleTooltip">{{ tab.title }}</span>
- <gl-badge variant="neutral" size="sm" class="gl-px-2 gl-py-1!">{{
+ <gl-badge v-if="tabCounts" variant="neutral" size="sm" class="gl-px-2 gl-py-1!">{{
tabCounts[tab.name]
}}</gl-badge>
</template>
diff --git a/app/assets/javascripts/issuable_list/constants.js b/app/assets/javascripts/issuable_list/constants.js
new file mode 100644
index 00000000000..773ad0f8e93
--- /dev/null
+++ b/app/assets/javascripts/issuable_list/constants.js
@@ -0,0 +1,51 @@
+import { __ } from '~/locale';
+
+export const IssuableStates = {
+ Opened: 'opened',
+ Closed: 'closed',
+ All: 'all',
+};
+
+export const IssuableListTabs = [
+ {
+ id: 'state-opened',
+ name: IssuableStates.Opened,
+ title: __('Open'),
+ titleTooltip: __('Filter by issues that are currently opened.'),
+ },
+ {
+ id: 'state-closed',
+ name: IssuableStates.Closed,
+ title: __('Closed'),
+ titleTooltip: __('Filter by issues that are currently closed.'),
+ },
+ {
+ id: 'state-all',
+ name: IssuableStates.All,
+ title: __('All'),
+ titleTooltip: __('Show all issues.'),
+ },
+];
+
+export const AvailableSortOptions = [
+ {
+ id: 1,
+ title: __('Created date'),
+ sortDirection: {
+ descending: 'created_desc',
+ ascending: 'created_asc',
+ },
+ },
+ {
+ id: 2,
+ title: __('Last updated'),
+ sortDirection: {
+ descending: 'updated_desc',
+ ascending: 'updated_asc',
+ },
+ },
+];
+
+export const DEFAULT_PAGE_SIZE = 20;
+
+export const DEFAULT_SKELETON_COUNT = 5;
diff --git a/app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue b/app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue
index 7d1339f833d..7cacba1cb65 100644
--- a/app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue
+++ b/app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue
@@ -29,6 +29,7 @@ export default {
},
mounted() {
window.addEventListener('resize', this.handleWindowResize);
+ this.updatePageContainerClass();
},
beforeDestroy() {
window.removeEventListener('resize', this.handleWindowResize);
diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js
index 0a0cfe918af..f65d9259e7b 100644
--- a/app/assets/javascripts/issue.js
+++ b/app/assets/javascripts/issue.js
@@ -84,13 +84,7 @@ export default class Issue {
projectIssuesCounter.text(addDelimiter(numProjectIssues));
if (this.createMergeRequestDropdown) {
- if (isClosed) {
- this.createMergeRequestDropdown.unavailable();
- this.createMergeRequestDropdown.disable();
- } else {
- // We should check in case a branch was created in another tab
- this.createMergeRequestDropdown.checkAbilityToCreateBranch();
- }
+ this.createMergeRequestDropdown.checkAbilityToCreateBranch();
}
} else {
flash(issueFailMessage);
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index 22db0f1cfc1..61e5db0970a 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -136,6 +136,16 @@ export default {
type: String,
required: true,
},
+ isConfidential: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isLocked: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
issuableType: {
type: String,
required: false,
@@ -217,8 +227,8 @@ export default {
defaultErrorMessage() {
return sprintf(s__('Error updating %{issuableType}'), { issuableType: this.issuableType });
},
- isOpenStatus() {
- return this.issuableStatus === IssuableStatus.Open;
+ isClosed() {
+ return this.issuableStatus === IssuableStatus.Closed;
},
pinnedLinkClasses() {
return this.showTitleBorder
@@ -226,13 +236,13 @@ export default {
: '';
},
statusIcon() {
- return this.isOpenStatus ? 'issue-open-m' : 'mobile-issue-close';
+ return this.isClosed ? 'mobile-issue-close' : 'issue-open-m';
},
statusText() {
return IssuableStatusText[this.issuableStatus];
},
shouldShowStickyHeader() {
- return this.isStickyHeaderShowing && this.issuableType === IssuableType.Issue;
+ return this.issuableType === IssuableType.Issue;
},
},
created() {
@@ -432,10 +442,14 @@ export default {
:show-inline-edit-button="showInlineEditButton"
/>
- <gl-intersection-observer @appear="hideStickyHeader" @disappear="showStickyHeader">
+ <gl-intersection-observer
+ v-if="shouldShowStickyHeader"
+ @appear="hideStickyHeader"
+ @disappear="showStickyHeader"
+ >
<transition name="issuable-header-slide">
<div
- v-if="shouldShowStickyHeader"
+ v-if="isStickyHeaderShowing"
class="issue-sticky-header gl-fixed gl-z-index-3 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-100 gl-py-3"
data-testid="issue-sticky-header"
>
@@ -444,11 +458,17 @@ export default {
>
<p
class="issuable-status-box status-box gl-my-0"
- :class="[isOpenStatus ? 'status-box-open' : 'status-box-issue-closed']"
+ :class="[isClosed ? 'status-box-issue-closed' : 'status-box-open']"
>
<gl-icon :name="statusIcon" class="gl-display-block d-sm-none gl-h-6!" />
<span class="gl-display-none d-sm-block">{{ statusText }}</span>
</p>
+ <span v-if="isLocked" data-testid="locked" class="issuable-warning-icon">
+ <gl-icon name="lock" :aria-label="__('Locked')" />
+ </span>
+ <span v-if="isConfidential" data-testid="confidential" class="issuable-warning-icon">
+ <gl-icon name="eye-slash" :aria-label="__('Confidential')" />
+ </span>
<p
class="gl-font-weight-bold gl-overflow-hidden gl-white-space-nowrap gl-text-overflow-ellipsis gl-my-0"
:title="state.titleText"
diff --git a/app/assets/javascripts/issue_show/components/header_actions.vue b/app/assets/javascripts/issue_show/components/header_actions.vue
new file mode 100644
index 00000000000..4c8c86390f4
--- /dev/null
+++ b/app/assets/javascripts/issue_show/components/header_actions.vue
@@ -0,0 +1,281 @@
+<script>
+import { GlButton, GlDropdown, GlDropdownItem, GlIcon, GlLink, GlModal } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
+import createFlash, { FLASH_TYPES } from '~/flash';
+import { IssuableType } from '~/issuable_show/constants';
+import { IssuableStatus, IssueStateEvent } from '~/issue_show/constants';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+import { visitUrl } from '~/lib/utils/url_utility';
+import { __, sprintf } from '~/locale';
+import promoteToEpicMutation from '../queries/promote_to_epic.mutation.graphql';
+import updateIssueMutation from '../queries/update_issue.mutation.graphql';
+
+export default {
+ components: {
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ GlIcon,
+ GlLink,
+ GlModal,
+ },
+ actionCancel: {
+ text: __('Cancel'),
+ },
+ actionPrimary: {
+ text: __('Yes, close issue'),
+ attributes: [{ variant: 'warning' }],
+ },
+ i18n: {
+ promoteErrorMessage: __(
+ 'Something went wrong while promoting the issue to an epic. Please try again.',
+ ),
+ promoteSuccessMessage: __(
+ 'The issue was successfully promoted to an epic. Redirecting to epic...',
+ ),
+ },
+ inject: {
+ canCreateIssue: {
+ default: false,
+ },
+ canPromoteToEpic: {
+ default: false,
+ },
+ canReopenIssue: {
+ default: false,
+ },
+ canReportSpam: {
+ default: false,
+ },
+ canUpdateIssue: {
+ default: false,
+ },
+ iid: {
+ default: '',
+ },
+ isIssueAuthor: {
+ default: false,
+ },
+ issueType: {
+ default: IssuableType.Issue,
+ },
+ newIssuePath: {
+ default: '',
+ },
+ projectPath: {
+ default: '',
+ },
+ reportAbusePath: {
+ default: '',
+ },
+ submitAsSpamPath: {
+ default: '',
+ },
+ },
+ data() {
+ return {
+ isUpdatingState: false,
+ };
+ },
+ computed: {
+ ...mapGetters(['getNoteableData']),
+ isClosed() {
+ return this.getNoteableData.state === IssuableStatus.Closed;
+ },
+ buttonText() {
+ return this.isClosed
+ ? sprintf(__('Reopen %{issueType}'), { issueType: this.issueType })
+ : sprintf(__('Close %{issueType}'), { issueType: this.issueType });
+ },
+ qaSelector() {
+ return this.isClosed ? 'reopen_issue_button' : 'close_issue_button';
+ },
+ buttonVariant() {
+ return this.isClosed ? 'default' : 'warning';
+ },
+ dropdownText() {
+ return sprintf(__('%{issueType} actions'), {
+ issueType: capitalizeFirstCharacter(this.issueType),
+ });
+ },
+ newIssueTypeText() {
+ return sprintf(__('New %{issueType}'), { issueType: this.issueType });
+ },
+ showToggleIssueStateButton() {
+ const canClose = !this.isClosed && this.canUpdateIssue;
+ const canReopen = this.isClosed && this.canReopenIssue;
+ return canClose || canReopen;
+ },
+ },
+ methods: {
+ toggleIssueState() {
+ if (!this.isClosed && this.getNoteableData?.blocked_by_issues?.length) {
+ this.$refs.blockedByIssuesModal.show();
+ return;
+ }
+
+ this.invokeUpdateIssueMutation();
+ },
+ invokeUpdateIssueMutation() {
+ this.isUpdatingState = true;
+
+ this.$apollo
+ .mutate({
+ mutation: updateIssueMutation,
+ variables: {
+ input: {
+ iid: this.iid.toString(),
+ projectPath: this.projectPath,
+ stateEvent: this.isClosed ? IssueStateEvent.Reopen : IssueStateEvent.Close,
+ },
+ },
+ })
+ .then(({ data }) => {
+ if (data.updateIssue.errors.length) {
+ createFlash({ message: data.updateIssue.errors.join('. ') });
+ return;
+ }
+
+ const payload = {
+ detail: {
+ data: { id: this.iid },
+ isClosed: !this.isClosed,
+ },
+ };
+
+ // Dispatch event which updates open/close state, shared among the issue show page
+ document.dispatchEvent(new CustomEvent('issuable_vue_app:change', payload));
+ })
+ .catch(() => createFlash({ message: __('Update failed. Please try again.') }))
+ .finally(() => {
+ this.isUpdatingState = false;
+ });
+ },
+ promoteToEpic() {
+ this.isUpdatingState = true;
+
+ this.$apollo
+ .mutate({
+ mutation: promoteToEpicMutation,
+ variables: {
+ input: {
+ iid: this.iid,
+ projectPath: this.projectPath,
+ },
+ },
+ })
+ .then(({ data }) => {
+ if (data.promoteToEpic.errors.length) {
+ createFlash({ message: data.promoteToEpic.errors.join('; ') });
+ return;
+ }
+
+ createFlash({
+ message: this.$options.i18n.promoteSuccessMessage,
+ type: FLASH_TYPES.SUCCESS,
+ });
+
+ visitUrl(data.promoteToEpic.epic.webPath);
+ })
+ .catch(() => createFlash({ message: this.$options.i18n.promoteErrorMessage }))
+ .finally(() => {
+ this.isUpdatingState = false;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="detail-page-header-actions">
+ <gl-dropdown class="gl-display-block gl-display-sm-none!" block :text="dropdownText">
+ <gl-dropdown-item
+ v-if="showToggleIssueStateButton"
+ :disabled="isUpdatingState"
+ @click="toggleIssueState"
+ >
+ {{ buttonText }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="canCreateIssue" :href="newIssuePath">
+ {{ newIssueTypeText }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="canPromoteToEpic" :disabled="isUpdatingState" @click="promoteToEpic">
+ {{ __('Promote to epic') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="!isIssueAuthor" :href="reportAbusePath">
+ {{ __('Report abuse') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="canReportSpam"
+ :href="submitAsSpamPath"
+ data-method="post"
+ rel="nofollow"
+ >
+ {{ __('Submit as spam') }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+
+ <gl-button
+ v-if="showToggleIssueStateButton"
+ class="gl-display-none gl-display-sm-inline-flex!"
+ category="secondary"
+ :data-qa-selector="qaSelector"
+ :loading="isUpdatingState"
+ :variant="buttonVariant"
+ @click="toggleIssueState"
+ >
+ {{ buttonText }}
+ </gl-button>
+
+ <gl-dropdown
+ class="gl-display-none gl-display-sm-inline-flex!"
+ toggle-class="gl-border-0! gl-shadow-none!"
+ no-caret
+ right
+ >
+ <template #button-content>
+ <gl-icon name="ellipsis_v" aria-hidden="true" />
+ <span class="gl-sr-only">{{ dropdownText }}</span>
+ </template>
+
+ <gl-dropdown-item v-if="canCreateIssue" :href="newIssuePath">
+ {{ newIssueTypeText }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="canPromoteToEpic"
+ :disabled="isUpdatingState"
+ data-testid="promote-button"
+ @click="promoteToEpic"
+ >
+ {{ __('Promote to epic') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="!isIssueAuthor" :href="reportAbusePath">
+ {{ __('Report abuse') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="canReportSpam"
+ :href="submitAsSpamPath"
+ data-method="post"
+ rel="nofollow"
+ >
+ {{ __('Submit as spam') }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+
+ <gl-modal
+ ref="blockedByIssuesModal"
+ modal-id="blocked-by-issues-modal"
+ :action-cancel="$options.actionCancel"
+ :action-primary="$options.actionPrimary"
+ :title="__('Are you sure you want to close this blocked issue?')"
+ @primary="invokeUpdateIssueMutation"
+ >
+ <p>{{ __('This issue is currently blocked by the following issues:') }}</p>
+ <ul>
+ <li v-for="issue in getNoteableData.blocked_by_issues" :key="issue.iid">
+ <gl-link :href="issue.web_url">#{{ issue.iid }}</gl-link>
+ </li>
+ </ul>
+ </gl-modal>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issue_show/constants.js b/app/assets/javascripts/issue_show/constants.js
index 6bc6ed2b372..a5ca91dffd4 100644
--- a/app/assets/javascripts/issue_show/constants.js
+++ b/app/assets/javascripts/issue_show/constants.js
@@ -1,13 +1,15 @@
import { __ } from '~/locale';
export const IssuableStatus = {
- Open: 'opened',
Closed: 'closed',
+ Open: 'opened',
+ Reopened: 'reopened',
};
export const IssuableStatusText = {
- [IssuableStatus.Open]: __('Open'),
[IssuableStatus.Closed]: __('Closed'),
+ [IssuableStatus.Open]: __('Open'),
+ [IssuableStatus.Reopened]: __('Open'),
};
export const IssuableType = {
@@ -16,5 +18,10 @@ export const IssuableType = {
MergeRequest: 'merge_request',
};
+export const IssueStateEvent = {
+ Close: 'CLOSE',
+ Reopen: 'REOPEN',
+};
+
export const STATUS_PAGE_PUBLISHED = __('Published on status page');
export const JOIN_ZOOM_MEETING = __('Join Zoom meeting');
diff --git a/app/assets/javascripts/issue_show/issue.js b/app/assets/javascripts/issue_show/issue.js
index f9f61d5aa64..8260460828b 100644
--- a/app/assets/javascripts/issue_show/issue.js
+++ b/app/assets/javascripts/issue_show/issue.js
@@ -1,16 +1,62 @@
import Vue from 'vue';
-import issuableApp from './components/app.vue';
+import VueApollo from 'vue-apollo';
+import { mapGetters } from 'vuex';
+import createDefaultClient from '~/lib/graphql';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import IssuableApp from './components/app.vue';
+import HeaderActions from './components/header_actions.vue';
-export default function initIssuableApp(issuableData) {
+export function initIssuableApp(issuableData, store) {
return new Vue({
el: document.getElementById('js-issuable-app'),
- components: {
- issuableApp,
+ store,
+ computed: {
+ ...mapGetters(['getNoteableData']),
},
render(createElement) {
- return createElement('issuable-app', {
- props: issuableData,
+ return createElement(IssuableApp, {
+ props: {
+ ...issuableData,
+ isConfidential: this.getNoteableData?.confidential,
+ isLocked: this.getNoteableData?.discussion_locked,
+ issuableStatus: this.getNoteableData?.state,
+ },
});
},
});
}
+
+export function initIssueHeaderActions(store) {
+ const el = document.querySelector('.js-issue-header-actions');
+
+ if (!el) {
+ return undefined;
+ }
+
+ Vue.use(VueApollo);
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ return new Vue({
+ el,
+ apolloProvider,
+ store,
+ provide: {
+ canCreateIssue: parseBoolean(el.dataset.canCreateIssue),
+ canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic),
+ canReopenIssue: parseBoolean(el.dataset.canReopenIssue),
+ canReportSpam: parseBoolean(el.dataset.canReportSpam),
+ canUpdateIssue: parseBoolean(el.dataset.canUpdateIssue),
+ iid: el.dataset.iid,
+ isIssueAuthor: parseBoolean(el.dataset.isIssueAuthor),
+ issueType: el.dataset.issueType,
+ newIssuePath: el.dataset.newIssuePath,
+ projectPath: el.dataset.projectPath,
+ reportAbusePath: el.dataset.reportAbusePath,
+ submitAsSpamPath: el.dataset.submitAsSpamPath,
+ },
+ render: createElement => createElement(HeaderActions),
+ });
+}
diff --git a/app/assets/javascripts/issue_show/queries/promote_to_epic.mutation.graphql b/app/assets/javascripts/issue_show/queries/promote_to_epic.mutation.graphql
new file mode 100644
index 00000000000..12d05af0f5e
--- /dev/null
+++ b/app/assets/javascripts/issue_show/queries/promote_to_epic.mutation.graphql
@@ -0,0 +1,8 @@
+mutation promoteToEpic($input: PromoteToEpicInput!) {
+ promoteToEpic(input: $input) {
+ epic {
+ webPath
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/issue_show/queries/update_issue.mutation.graphql b/app/assets/javascripts/issue_show/queries/update_issue.mutation.graphql
new file mode 100644
index 00000000000..9c28fdded21
--- /dev/null
+++ b/app/assets/javascripts/issue_show/queries/update_issue.mutation.graphql
@@ -0,0 +1,5 @@
+mutation updateIssue($input: UpdateIssueInput!) {
+ updateIssue(input: $input) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/issues_list/components/issuable.vue b/app/assets/javascripts/issues_list/components/issuable.vue
index dc63d613b5b..b12b20d0135 100644
--- a/app/assets/javascripts/issues_list/components/issuable.vue
+++ b/app/assets/javascripts/issues_list/components/issuable.vue
@@ -28,7 +28,6 @@ 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';
@@ -37,6 +36,7 @@ export default {
openedAgo: __('opened %{timeAgoString} by %{user}'),
openedAgoJira: __('opened %{timeAgoString} by %{user} in Jira'),
},
+ inject: ['scopedLabelsAvailable'],
components: {
IssueAssignees,
GlLink,
@@ -50,7 +50,6 @@ export default {
GlTooltip,
SafeHtml,
},
- mixins: [glFeatureFlagsMixin()],
props: {
issuable: {
type: Object,
@@ -85,9 +84,6 @@ export default {
return this.issuableLink({ milestone_title: title });
},
- scopedLabelsAvailable() {
- return this.glFeatures.scopedLabels;
- },
hasWeight() {
return isNumber(this.issuable.weight);
},
diff --git a/app/assets/javascripts/issues_list/index.js b/app/assets/javascripts/issues_list/index.js
index 1ff41c20d08..5ef86536865 100644
--- a/app/assets/javascripts/issues_list/index.js
+++ b/app/assets/javascripts/issues_list/index.js
@@ -41,10 +41,13 @@ function mountIssuablesListApp() {
}
document.querySelectorAll('.js-issuables-list').forEach(el => {
- const { canBulkEdit, emptyStateMeta = {}, ...data } = el.dataset;
+ const { canBulkEdit, emptyStateMeta = {}, scopedLabelsAvailable, ...data } = el.dataset;
return new Vue({
el,
+ provide: {
+ scopedLabelsAvailable: parseBoolean(scopedLabelsAvailable),
+ },
render(createElement) {
return createElement(IssuablesListApp, {
props: {
diff --git a/app/assets/javascripts/jira_connect/.eslintrc.yml b/app/assets/javascripts/jira_connect/.eslintrc.yml
new file mode 100644
index 00000000000..053f8c6b285
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/.eslintrc.yml
@@ -0,0 +1,5 @@
+globals:
+ AP: readonly
+rules:
+ '@gitlab/require-i18n-strings': off
+ '@gitlab/vue-require-i18n-strings': off
diff --git a/app/assets/javascripts/jira_connect/components/app.vue b/app/assets/javascripts/jira_connect/components/app.vue
new file mode 100644
index 00000000000..6d32ba41eae
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/components/app.vue
@@ -0,0 +1,7 @@
+<script>
+export default {};
+</script>
+
+<template>
+ <div></div>
+</template>
diff --git a/app/assets/javascripts/jira_connect/index.js b/app/assets/javascripts/jira_connect/index.js
new file mode 100644
index 00000000000..37f00d56a05
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/index.js
@@ -0,0 +1,15 @@
+import Vue from 'vue';
+import App from './components/app.vue';
+
+function initJiraConnect() {
+ const el = document.querySelector('.js-jira-connect-app');
+
+ return new Vue({
+ el,
+ render(createElement) {
+ return createElement(App, {});
+ },
+ });
+}
+
+document.addEventListener('DOMContentLoaded', initJiraConnect);
diff --git a/app/assets/javascripts/jobs/components/job_retry_forward_deployment_modal.vue b/app/assets/javascripts/jobs/components/job_retry_forward_deployment_modal.vue
new file mode 100644
index 00000000000..5ce9d08035d
--- /dev/null
+++ b/app/assets/javascripts/jobs/components/job_retry_forward_deployment_modal.vue
@@ -0,0 +1,66 @@
+<script>
+import { GlLink, GlModal } from '@gitlab/ui';
+import { JOB_RETRY_FORWARD_DEPLOYMENT_MODAL } from '../constants';
+
+export default {
+ name: 'JobRetryForwardDeploymentModal',
+ components: {
+ GlLink,
+ GlModal,
+ },
+ i18n: {
+ ...JOB_RETRY_FORWARD_DEPLOYMENT_MODAL,
+ },
+ props: {
+ modalId: {
+ type: String,
+ required: true,
+ },
+ href: {
+ type: String,
+ required: true,
+ },
+ },
+ inject: {
+ retryOutdatedJobDocsUrl: {
+ default: '',
+ },
+ },
+ data() {
+ return {
+ primaryProps: {
+ text: this.$options.i18n.primaryText,
+ attributes: [
+ {
+ 'data-method': 'post',
+ 'data-testid': 'retry-button-modal',
+ href: this.href,
+ variant: 'danger',
+ },
+ ],
+ },
+ cancelProps: {
+ text: this.$options.i18n.cancel,
+ attributes: [{ category: 'secondary', variant: 'default' }],
+ },
+ };
+ },
+};
+</script>
+
+<template>
+ <gl-modal
+ :action-cancel="cancelProps"
+ :action-primary="primaryProps"
+ :modal-id="modalId"
+ :title="$options.i18n.title"
+ >
+ <p>
+ {{ $options.i18n.info }}
+ <gl-link v-if="retryOutdatedJobDocsUrl" :href="retryOutdatedJobDocsUrl" target="_blank">
+ {{ $options.i18n.moreInfo }}
+ </gl-link>
+ </p>
+ <p>{{ $options.i18n.areYouSure }}</p>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/jobs/components/job_sidebar_retry_button.vue b/app/assets/javascripts/jobs/components/job_sidebar_retry_button.vue
new file mode 100644
index 00000000000..258b8cadd63
--- /dev/null
+++ b/app/assets/javascripts/jobs/components/job_sidebar_retry_button.vue
@@ -0,0 +1,45 @@
+<script>
+import { GlButton, GlLink, GlModalDirective } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
+import { JOB_SIDEBAR } from '../constants';
+
+export default {
+ name: 'JobSidebarRetryButton',
+ i18n: {
+ retryLabel: JOB_SIDEBAR.retry,
+ },
+ components: {
+ GlButton,
+ GlLink,
+ },
+ directives: {
+ GlModal: GlModalDirective,
+ },
+ props: {
+ modalId: {
+ type: String,
+ required: true,
+ },
+ href: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapGetters(['hasForwardDeploymentFailure']),
+ },
+};
+</script>
+<template>
+ <gl-button
+ v-if="hasForwardDeploymentFailure"
+ v-gl-modal="modalId"
+ :aria-label="$options.i18n.retryLabel"
+ category="primary"
+ variant="info"
+ >{{ $options.i18n.retryLabel }}</gl-button
+ >
+ <gl-link v-else :href="href" data-method="post" rel="nofollow"
+ >{{ $options.i18n.retryLabel }}
+ </gl-link>
+</template>
diff --git a/app/assets/javascripts/jobs/components/jobs_container.vue b/app/assets/javascripts/jobs/components/jobs_container.vue
index 951bcb36600..df64b6422c7 100644
--- a/app/assets/javascripts/jobs/components/jobs_container.vue
+++ b/app/assets/javascripts/jobs/components/jobs_container.vue
@@ -24,7 +24,7 @@ export default {
};
</script>
<template>
- <div class="js-jobs-container builds-container">
+ <div class="builds-container">
<job-container-item
v-for="job in jobs"
:key="job.id"
diff --git a/app/assets/javascripts/jobs/components/log/line.vue b/app/assets/javascripts/jobs/components/log/line.vue
index e68d5b8eda4..affaddcdee2 100644
--- a/app/assets/javascripts/jobs/components/log/line.vue
+++ b/app/assets/javascripts/jobs/components/log/line.vue
@@ -1,4 +1,6 @@
<script>
+import { linkRegex } from '../../utils';
+
import LineNumber from './line_number.vue';
export default {
@@ -16,15 +18,46 @@ export default {
render(h, { props }) {
const { line, path } = props;
- const chars = line.content.map(content => {
- return h(
- 'span',
- {
- class: ['gl-white-space-pre-wrap', content.style],
- },
- content.text,
- );
- });
+ let chars;
+ if (gon?.features?.ciJobLineLinks) {
+ chars = line.content.map(content => {
+ return h(
+ 'span',
+ {
+ class: ['gl-white-space-pre-wrap', content.style],
+ },
+ // Simple "tokenization": Split text in chunks of text
+ // which alternate between text and urls.
+ content.text.split(linkRegex).map(chunk => {
+ // Return normal string for non-links
+ if (!chunk.match(linkRegex)) {
+ return chunk;
+ }
+ return h(
+ 'a',
+ {
+ attrs: {
+ href: chunk,
+ class: 'gl-reset-color! gl-text-decoration-underline',
+ rel: 'nofollow noopener noreferrer', // eslint-disable-line @gitlab/require-i18n-strings
+ },
+ },
+ chunk,
+ );
+ }),
+ );
+ });
+ } else {
+ chars = line.content.map(content => {
+ return h(
+ 'span',
+ {
+ class: ['gl-white-space-pre-wrap', content.style],
+ },
+ content.text,
+ );
+ });
+ }
return h('div', { class: 'js-line log-line' }, [
h(LineNumber, {
diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue
index 8701e05a01f..0789bb54f0f 100644
--- a/app/assets/javascripts/jobs/components/sidebar.vue
+++ b/app/assets/javascripts/jobs/components/sidebar.vue
@@ -1,33 +1,40 @@
<script>
import { isEmpty } from 'lodash';
-import { mapActions, mapState } from 'vuex';
-import { GlLink, GlButton, GlIcon } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
+import { mapActions, mapGetters, mapState } from 'vuex';
+import { GlButton, GlIcon, GlLink } from '@gitlab/ui';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
-import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
-import DetailRow from './sidebar_detail_row.vue';
import ArtifactsBlock from './artifacts_block.vue';
+import JobSidebarRetryButton from './job_sidebar_retry_button.vue';
+import JobRetryForwardDeploymentModal from './job_retry_forward_deployment_modal.vue';
import TriggerBlock from './trigger_block.vue';
import CommitBlock from './commit_block.vue';
import StagesDropdown from './stages_dropdown.vue';
import JobsContainer from './jobs_container.vue';
+import JobSidebarDetailsContainer from './sidebar_job_details_container.vue';
+import { JOB_SIDEBAR } from '../constants';
+
+export const forwardDeploymentFailureModalId = 'forward-deployment-failure';
export default {
name: 'JobSidebar',
+ i18n: {
+ ...JOB_SIDEBAR,
+ },
+ forwardDeploymentFailureModalId,
components: {
ArtifactsBlock,
CommitBlock,
- DetailRow,
+ GlButton,
+ GlLink,
GlIcon,
- TriggerBlock,
- StagesDropdown,
JobsContainer,
- GlLink,
- GlButton,
+ JobSidebarRetryButton,
+ JobRetryForwardDeploymentModal,
+ JobSidebarDetailsContainer,
+ StagesDropdown,
TooltipOnTruncate,
+ TriggerBlock,
},
- mixins: [timeagoMixin],
props: {
artifactHelpUrl: {
type: String,
@@ -41,54 +48,14 @@ export default {
},
},
computed: {
+ ...mapGetters(['hasForwardDeploymentFailure']),
...mapState(['job', 'stages', 'jobs', 'selectedStage']),
- coverage() {
- return `${this.job.coverage}%`;
- },
- duration() {
- return timeIntervalInWords(this.job.duration);
- },
- queued() {
- return timeIntervalInWords(this.job.queued);
- },
- runnerId() {
- return `${this.job.runner.description} (#${this.job.runner.id})`;
- },
retryButtonClass() {
- let className = 'js-retry-button btn btn-retry';
+ let className = 'btn btn-retry';
className +=
this.job.status && this.job.recoverable ? ' btn-primary' : ' btn-inverted-secondary';
return className;
},
- hasTimeout() {
- return this.job.metadata != null && this.job.metadata.timeout_human_readable !== null;
- },
- timeout() {
- if (this.job.metadata == null) {
- return '';
- }
-
- let t = this.job.metadata.timeout_human_readable;
- if (this.job.metadata.timeout_source !== '') {
- t += sprintf(__(` (from %{timeoutSource})`), {
- timeoutSource: this.job.metadata.timeout_source,
- });
- }
-
- return t;
- },
- renderBlock() {
- return (
- this.job.duration ||
- this.job.finished_at ||
- this.job.erased_at ||
- this.job.queued ||
- this.hasTimeout ||
- this.job.runner ||
- this.job.coverage ||
- this.job.tags.length
- );
- },
hasArtifact() {
return !isEmpty(this.job.artifact);
},
@@ -96,16 +63,13 @@ export default {
return !isEmpty(this.job.trigger);
},
hasStages() {
- return (
- (this.job &&
- this.job.pipeline &&
- this.job.pipeline.stages &&
- this.job.pipeline.stages.length > 0) ||
- false
- );
+ return this.job?.pipeline?.stages?.length > 0;
},
commit() {
- return this.job.pipeline && this.job.pipeline.commit ? this.job.pipeline.commit : {};
+ return this.job?.pipeline?.commit || {};
+ },
+ shouldShowJobRetryForwardDeploymentModal() {
+ return this.job.retry_path && this.hasForwardDeploymentFailure;
},
},
methods: {
@@ -124,29 +88,29 @@ export default {
</h4>
</tooltip-on-truncate>
<div class="flex-grow-1 flex-shrink-0 text-right">
- <gl-link
+ <job-sidebar-retry-button
v-if="job.retry_path"
:class="retryButtonClass"
:href="job.retry_path"
- data-method="post"
+ :modal-id="$options.forwardDeploymentFailureModalId"
data-qa-selector="retry_button"
- rel="nofollow"
- >{{ __('Retry') }}</gl-link
- >
+ data-testid="retry-button"
+ />
<gl-link
v-if="job.cancel_path"
:href="job.cancel_path"
- class="js-cancel-job btn btn-default"
+ class="btn btn-default"
data-method="post"
+ data-testid="cancel-button"
rel="nofollow"
- >{{ __('Cancel') }}</gl-link
- >
+ >{{ $options.i18n.cancel }}
+ </gl-link>
</div>
<gl-button
- :aria-label="__('Toggle Sidebar')"
- class="d-md-none gl-ml-2 js-sidebar-build-toggle"
+ :aria-label="$options.i18n.toggleSidebar"
category="tertiary"
+ class="gl-display-md-none gl-ml-2 js-sidebar-build-toggle"
icon="chevron-double-lg-right"
@click="toggleSidebar"
/>
@@ -158,77 +122,43 @@ export default {
:href="job.new_issue_path"
class="btn btn-success btn-inverted float-left mr-2"
data-testid="job-new-issue"
- >{{ __('New issue') }}</gl-link
- >
+ >{{ $options.i18n.newIssue }}
+ </gl-link>
<gl-link
v-if="job.terminal_path"
:href="job.terminal_path"
- class="js-terminal-link btn btn-primary btn-inverted visible-md-block visible-lg-block float-left"
+ class="btn btn-primary btn-inverted visible-md-block visible-lg-block float-left"
target="_blank"
+ data-testid="terminal-link"
>
- {{ __('Debug') }} <gl-icon name="external-link" :size="14" />
+ {{ $options.i18n.debug }}
+ <gl-icon :size="14" name="external-link" />
</gl-link>
</div>
-
- <div v-if="renderBlock" class="block">
- <detail-row
- v-if="job.duration"
- :value="duration"
- class="js-job-duration"
- title="Duration"
- />
- <detail-row
- v-if="job.finished_at"
- :value="timeFormatted(job.finished_at)"
- class="js-job-finished"
- title="Finished"
- />
- <detail-row
- v-if="job.erased_at"
- :value="timeFormatted(job.erased_at)"
- class="js-job-erased"
- title="Erased"
- />
- <detail-row v-if="job.queued" :value="queued" class="js-job-queued" title="Queued" />
- <detail-row
- v-if="hasTimeout"
- :help-url="runnerHelpUrl"
- :value="timeout"
- class="js-job-timeout"
- title="Timeout"
- />
- <detail-row v-if="job.runner" :value="runnerId" class="js-job-runner" title="Runner" />
- <detail-row
- v-if="job.coverage"
- :value="coverage"
- class="js-job-coverage"
- title="Coverage"
- />
- <p v-if="job.tags.length" class="build-detail-row js-job-tags">
- <span class="font-weight-bold">{{ __('Tags:') }}</span>
- <span v-for="(tag, i) in job.tags" :key="i" class="badge badge-primary mr-1">{{
- tag
- }}</span>
- </p>
- </div>
-
+ <job-sidebar-details-container :runner-help-url="runnerHelpUrl" />
<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"
:commit="commit"
+ :is-last-block="hasStages"
:merge-request="job.merge_request"
/>
<stages-dropdown
- :stages="stages"
+ v-if="job.pipeline"
:pipeline="job.pipeline"
:selected-stage="selectedStage"
+ :stages="stages"
@requestSidebarStageDropdown="fetchJobsForStage"
/>
</div>
- <jobs-container v-if="jobs.length" :jobs="jobs" :job-id="job.id" />
+ <jobs-container v-if="jobs.length" :job-id="job.id" :jobs="jobs" />
</div>
+ <job-retry-forward-deployment-modal
+ v-if="shouldShowJobRetryForwardDeploymentModal"
+ :modal-id="$options.forwardDeploymentFailureModalId"
+ :href="job.retry_path"
+ />
</aside>
</template>
diff --git a/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue b/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
new file mode 100644
index 00000000000..8ad1008278e
--- /dev/null
+++ b/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
@@ -0,0 +1,102 @@
+<script>
+import { mapState } from 'vuex';
+import DetailRow from './sidebar_detail_row.vue';
+import { __, sprintf } from '~/locale';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
+import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
+
+export default {
+ name: 'JobSidebarDetailsContainer',
+ components: {
+ DetailRow,
+ },
+ mixins: [timeagoMixin],
+ props: {
+ runnerHelpUrl: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ ...mapState(['job']),
+ coverage() {
+ return `${this.job.coverage}%`;
+ },
+ duration() {
+ return timeIntervalInWords(this.job.duration);
+ },
+ erasedAt() {
+ return this.timeFormatted(this.job.erased_at);
+ },
+ finishedAt() {
+ return this.timeFormatted(this.job.finished_at);
+ },
+ hasTags() {
+ return this.job?.tags?.length;
+ },
+ hasTimeout() {
+ return this.job?.metadata?.timeout_human_readable ?? false;
+ },
+ hasAnyDetail() {
+ return Boolean(
+ this.job.duration ||
+ this.job.finished_at ||
+ this.job.erased_at ||
+ this.job.queued ||
+ this.job.runner ||
+ this.job.coverage,
+ );
+ },
+ queued() {
+ return timeIntervalInWords(this.job.queued);
+ },
+ runnerId() {
+ return `${this.job.runner.description} (#${this.job.runner.id})`;
+ },
+ shouldRenderBlock() {
+ return Boolean(this.hasAnyDetail || this.hasTimeout || this.hasTags);
+ },
+ timeout() {
+ return `${this.job?.metadata?.timeout_human_readable}${this.timeoutSource}`;
+ },
+ timeoutSource() {
+ if (!this.job?.metadata?.timeout_source) {
+ return '';
+ }
+
+ return sprintf(__(` (from %{timeoutSource})`), {
+ timeoutSource: this.job.metadata.timeout_source,
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div v-if="shouldRenderBlock" class="block">
+ <detail-row v-if="job.duration" :value="duration" title="Duration" />
+ <detail-row
+ v-if="job.finished_at"
+ :value="finishedAt"
+ data-testid="job-finished"
+ title="Finished"
+ />
+ <detail-row v-if="job.erased_at" :value="erasedAt" title="Erased" />
+ <detail-row v-if="job.queued" :value="queued" title="Queued" />
+ <detail-row
+ v-if="hasTimeout"
+ :help-url="runnerHelpUrl"
+ :value="timeout"
+ data-testid="job-timeout"
+ title="Timeout"
+ />
+ <detail-row v-if="job.runner" :value="runnerId" title="Runner" />
+ <detail-row v-if="job.coverage" :value="coverage" title="Coverage" />
+
+ <p v-if="hasTags" class="build-detail-row" data-testid="job-tags">
+ <span class="font-weight-bold">{{ __('Tags:') }}</span>
+ <span v-for="(tag, i) in job.tags" :key="i" class="badge badge-primary mr-1">{{ tag }}</span>
+ </p>
+ </div>
+</template>
diff --git a/app/assets/javascripts/jobs/components/stages_dropdown.vue b/app/assets/javascripts/jobs/components/stages_dropdown.vue
index 116331d9549..aeae9f26ed3 100644
--- a/app/assets/javascripts/jobs/components/stages_dropdown.vue
+++ b/app/assets/javascripts/jobs/components/stages_dropdown.vue
@@ -1,11 +1,13 @@
<script>
import { isEmpty } from 'lodash';
-import { GlLink } from '@gitlab/ui';
+import { GlLink, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
export default {
components: {
CiIcon,
+ GlDropdown,
+ GlDropdownItem,
GlLink,
},
props: {
@@ -78,20 +80,15 @@ export default {
</template>
</div>
- <button
- type="button"
- data-toggle="dropdown"
- class="js-selected-stage dropdown-menu-toggle gl-mt-3"
- >
- {{ selectedStage }} <i class="fa fa-chevron-down"></i>
- </button>
-
- <ul class="dropdown-menu">
- <li v-for="stage in stages" :key="stage.name">
- <button type="button" class="js-stage-item stage-item" @click="onStageClick(stage)">
- {{ stage.name }}
- </button>
- </li>
- </ul>
+ <gl-dropdown :text="selectedStage" class="js-selected-stage gl-w-full gl-mt-3">
+ <gl-dropdown-item
+ v-for="stage in stages"
+ :key="stage.name"
+ class="js-stage-item stage-item"
+ @click="onStageClick(stage)"
+ >
+ {{ stage.name }}
+ </gl-dropdown-item>
+ </gl-dropdown>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/constants.js b/app/assets/javascripts/jobs/constants.js
new file mode 100644
index 00000000000..d0d625d794d
--- /dev/null
+++ b/app/assets/javascripts/jobs/constants.js
@@ -0,0 +1,24 @@
+import { __, s__ } from '~/locale';
+
+const cancel = __('Cancel');
+const moreInfo = __('More information');
+
+export const JOB_SIDEBAR = {
+ cancel,
+ debug: __('Debug'),
+ newIssue: __('New issue'),
+ retry: __('Retry'),
+ toggleSidebar: __('Toggle Sidebar'),
+};
+
+export const JOB_RETRY_FORWARD_DEPLOYMENT_MODAL = {
+ cancel,
+ info: s__(
+ `Jobs|You're about to retry a job that failed because it attempted to deploy code that is older than the latest deployment.
+ Retrying this job could result in overwriting the environment with the older source code.`,
+ ),
+ areYouSure: s__('Jobs|Are you sure you want to proceed?'),
+ moreInfo,
+ primaryText: __('Retry job'),
+ title: s__('Jobs|Are you sure you want to retry this job?'),
+};
diff --git a/app/assets/javascripts/jobs/index.js b/app/assets/javascripts/jobs/index.js
index 6e15360b66c..1ad6292a030 100644
--- a/app/assets/javascripts/jobs/index.js
+++ b/app/assets/javascripts/jobs/index.js
@@ -10,27 +10,31 @@ export default () => {
// Let's start initializing the store (i.e. fetching data) right away
store.dispatch('init', element.dataset);
+ const {
+ artifactHelpUrl,
+ deploymentHelpUrl,
+ runnerHelpUrl,
+ runnerSettingsUrl,
+ variablesSettingsUrl,
+ subscriptionsMoreMinutesUrl,
+ endpoint,
+ pagePath,
+ logState,
+ buildStatus,
+ projectPath,
+ retryOutdatedJobDocsUrl,
+ } = element.dataset;
+
return new Vue({
el: element,
store,
components: {
JobApp,
},
+ provide: {
+ retryOutdatedJobDocsUrl,
+ },
render(createElement) {
- const {
- artifactHelpUrl,
- deploymentHelpUrl,
- runnerHelpUrl,
- runnerSettingsUrl,
- variablesSettingsUrl,
- subscriptionsMoreMinutesUrl,
- endpoint,
- pagePath,
- logState,
- buildStatus,
- projectPath,
- } = element.dataset;
-
return createElement('job-app', {
props: {
artifactHelpUrl,
diff --git a/app/assets/javascripts/jobs/store/getters.js b/app/assets/javascripts/jobs/store/getters.js
index dc4a3578a86..8c2d1dd8ab2 100644
--- a/app/assets/javascripts/jobs/store/getters.js
+++ b/app/assets/javascripts/jobs/store/getters.js
@@ -3,8 +3,11 @@ import { isScrolledToBottom } from '~/lib/utils/scroll_utils';
export const headerTime = state => (state.job.started ? state.job.started : state.job.created_at);
+export const hasForwardDeploymentFailure = state =>
+ state?.job?.failure_reason === 'forward_deployment_failure';
+
export const hasUnmetPrerequisitesFailure = state =>
- state.job && state.job.failure_reason && state.job.failure_reason === 'unmet_prerequisites';
+ state?.job?.failure_reason === 'unmet_prerequisites';
export const shouldRenderCalloutMessage = state =>
!isEmpty(state.job.status) && !isEmpty(state.job.callout_message);
diff --git a/app/assets/javascripts/jobs/utils.js b/app/assets/javascripts/jobs/utils.js
new file mode 100644
index 00000000000..28a125b2b8f
--- /dev/null
+++ b/app/assets/javascripts/jobs/utils.js
@@ -0,0 +1,4 @@
+// capture anything starting with http:// or https://
+// up until a disallowed character or whitespace
+export const linkRegex = /(https?:\/\/[^"<>\\^`{|}\s]+)/g;
+export default { linkRegex };
diff --git a/app/assets/javascripts/lib/ace.js b/app/assets/javascripts/lib/ace.js
deleted file mode 100644
index e90b3d2eec7..00000000000
--- a/app/assets/javascripts/lib/ace.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*= require ace/ace */
-/*= require ace/ext-modelist */
-/*= require ace/ext-searchbox */
-/*= require ./ace/ace_config_paths */
diff --git a/app/assets/javascripts/lib/ace/ace_config_paths.js.erb b/app/assets/javascripts/lib/ace/ace_config_paths.js.erb
deleted file mode 100644
index 976769ba84a..00000000000
--- a/app/assets/javascripts/lib/ace/ace_config_paths.js.erb
+++ /dev/null
@@ -1,34 +0,0 @@
-<%
-ace_gem_path = Bundler.rubygems.find_name('ace-rails-ap').first.full_gem_path
-ace_workers = Dir[ace_gem_path + '/vendor/assets/javascripts/ace/worker-*.js'].sort.map do |file|
- File.basename(file, '.js').sub(/^worker-/, '')
-end
-ace_modes = Dir[ace_gem_path + '/vendor/assets/javascripts/ace/mode-*.js'].sort.map do |file|
- File.basename(file, '.js').sub(/^mode-/, '')
-end
-%>
-// Lazy-load configuration when ace.edit is called
-(function() {
- var basePath;
- var ace = window.ace;
- var edit = ace.edit;
- ace.edit = function() {
- window.gon = window.gon || {};
- basePath = (window.gon.relative_url_root || '').replace(/\/$/, '') + '/assets/ace';
- ace.config.set('basePath', basePath);
-
- // configure paths for all worker modules
-<% ace_workers.each do |worker| %>
- ace.config.setModuleUrl('ace/mode/<%= worker %>_worker', basePath + '/<%= File.basename(asset_path("ace/worker-#{worker}.js")) %>');
-<% end %>
-
- // configure paths for all mode modules
-<% ace_modes.each do |mode| %>
- ace.config.setModuleUrl('ace/mode/<%= mode %>', basePath + '/<%= File.basename(asset_path("ace/mode-#{mode}.js")) %>');
-<% end %>
-
- // restore original method
- ace.edit = edit;
- return ace.edit.apply(ace, arguments);
- };
-})();
diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js
index 0e07f7d8e44..e0d9a903e0a 100644
--- a/app/assets/javascripts/lib/graphql.js
+++ b/app/assets/javascripts/lib/graphql.js
@@ -5,6 +5,7 @@ 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';
+import { StartupJSLink } from '~/lib/utils/apollo_startup_js_link';
export const fetchPolicies = {
CACHE_FIRST: 'cache-first',
@@ -62,7 +63,7 @@ export default (resolvers = {}, config = {}) => {
return new ApolloClient({
typeDefs: config.typeDefs,
- link: ApolloLink.from([performanceBarLink, uploadsLink]),
+ link: ApolloLink.from([performanceBarLink, new StartupJSLink(), uploadsLink]),
cache: new InMemoryCache({
...config.cacheConfig,
freezeResults: config.assumeImmutableResults,
diff --git a/app/assets/javascripts/lib/utils/ace_utils.js b/app/assets/javascripts/lib/utils/ace_utils.js
deleted file mode 100644
index ee71ae0e61a..00000000000
--- a/app/assets/javascripts/lib/utils/ace_utils.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* global ace */
-
-export default function getModeByFileExtension(path) {
- const modelist = ace.require('ace/ext/modelist');
- return modelist.getModeForPath(path).mode;
-}
diff --git a/app/assets/javascripts/lib/utils/apollo_startup_js_link.js b/app/assets/javascripts/lib/utils/apollo_startup_js_link.js
new file mode 100644
index 00000000000..5c120dd532f
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/apollo_startup_js_link.js
@@ -0,0 +1,106 @@
+import { ApolloLink, Observable } from 'apollo-link';
+import { parse } from 'graphql';
+import { isEqual, pickBy } from 'lodash';
+
+/**
+ * Remove undefined values from object
+ * @param obj
+ * @returns {Dictionary<unknown>}
+ */
+const pickDefinedValues = obj => pickBy(obj, x => x !== undefined);
+
+/**
+ * Compares two set of variables, order independent
+ *
+ * Ignores undefined values (in the top level) and supports arrays etc.
+ */
+const variablesMatch = (var1 = {}, var2 = {}) => {
+ return isEqual(pickDefinedValues(var1), pickDefinedValues(var2));
+};
+
+export class StartupJSLink extends ApolloLink {
+ constructor() {
+ super();
+ this.startupCalls = new Map();
+ this.parseStartupCalls(window.gl?.startup_graphql_calls || []);
+ }
+
+ // Extract operationNames from the queries and ensure that we can
+ // match operationName => element from result array
+ parseStartupCalls(calls) {
+ calls.forEach(call => {
+ const { query, variables, fetchCall } = call;
+ const operationName = parse(query)?.definitions?.find(x => x.kind === 'OperationDefinition')
+ ?.name?.value;
+
+ if (operationName) {
+ this.startupCalls.set(operationName, {
+ variables,
+ fetchCall,
+ });
+ }
+ });
+ }
+
+ static noopRequest = (operation, forward) => forward(operation);
+
+ disable() {
+ this.request = StartupJSLink.noopRequest;
+ this.startupCalls = null;
+ }
+
+ request(operation, forward) {
+ // Disable StartupJSLink in case all calls are done or none are set up
+ if (this.startupCalls && this.startupCalls.size === 0) {
+ this.disable();
+ return forward(operation);
+ }
+
+ const { operationName } = operation;
+
+ // Skip startup call if the operationName doesn't match
+ if (!this.startupCalls.has(operationName)) {
+ return forward(operation);
+ }
+
+ const { variables: startupVariables, fetchCall } = this.startupCalls.get(operationName);
+ this.startupCalls.delete(operationName);
+
+ // Skip startup call if the variables values do not match
+ if (!variablesMatch(startupVariables, operation.variables)) {
+ return forward(operation);
+ }
+
+ return new Observable(observer => {
+ fetchCall
+ .then(response => {
+ // Handle HTTP errors
+ if (!response.ok) {
+ throw new Error('fetchCall failed');
+ }
+ operation.setContext({ response });
+ return response.json();
+ })
+ .then(result => {
+ if (result && (result.errors || !result.data)) {
+ throw new Error('Received GraphQL error');
+ }
+
+ // we have data and can send it to back up the link chain
+ observer.next(result);
+ observer.complete();
+ })
+ .catch(() => {
+ forward(operation).subscribe({
+ next: result => {
+ observer.next(result);
+ },
+ error: error => {
+ observer.error(error);
+ },
+ complete: observer.complete.bind(observer),
+ });
+ });
+ });
+ }
+}
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index fe1ac00fd1d..42a5de68cfa 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -61,9 +61,6 @@ export const rstrip = val => {
return val;
};
-export const updateTooltipTitle = ($tooltipEl, newTitle) =>
- $tooltipEl.attr('title', newTitle).tooltip('_fixTitle');
-
export const disableButtonIfEmptyField = (fieldSelector, buttonSelector, eventName = 'input') => {
const field = $(fieldSelector);
const closestSubmit = field.closest('form').find(buttonSelector);
@@ -744,6 +741,24 @@ export const roundOffFloat = (number, precision = 0) => {
};
/**
+ * Method to round down values with decimal places
+ * with provided precision.
+ *
+ * Eg; roundDownFloat(3.141592, 3) = 3.141
+ *
+ * Refer to spec/javascripts/lib/utils/common_utils_spec.js for
+ * more supported examples.
+ *
+ * @param {Float} number
+ * @param {Number} precision
+ */
+export const roundDownFloat = (number, precision = 0) => {
+ // eslint-disable-next-line no-restricted-properties
+ const multiplier = Math.pow(10, precision);
+ return Math.floor(number * multiplier) / multiplier;
+};
+
+/**
* Represents navigation type constants of the Performance Navigation API.
* Detailed explanation see https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigation.
*/
diff --git a/app/assets/javascripts/lib/utils/constants.js b/app/assets/javascripts/lib/utils/constants.js
index 1a4ecc12f01..993d51370ec 100644
--- a/app/assets/javascripts/lib/utils/constants.js
+++ b/app/assets/javascripts/lib/utils/constants.js
@@ -1,5 +1,4 @@
export const BYTES_IN_KIB = 1024;
-export const BYTES_IN_KB = 1000;
export const HIDDEN_CLASS = 'hidden';
export const TRUNCATE_WIDTH_DEFAULT_WIDTH = 80;
export const TRUNCATE_WIDTH_DEFAULT_FONT_SIZE = 12;
diff --git a/app/assets/javascripts/lib/utils/css_utils.js b/app/assets/javascripts/lib/utils/css_utils.js
index 90213221443..02f092e73e1 100644
--- a/app/assets/javascripts/lib/utils/css_utils.js
+++ b/app/assets/javascripts/lib/utils/css_utils.js
@@ -1,5 +1,7 @@
export function loadCSSFile(path) {
return new Promise(resolve => {
+ if (!path) resolve();
+
if (document.querySelector(`link[href="${path}"]`)) {
resolve();
} else {
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index 753245147d2..46b0f0cbc70 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -206,10 +206,6 @@ export const localTimeAgo = ($timeagoEls, setTimeago = true) => {
$timeagoEls.each((i, el) => {
// Recreate with custom template
el.setAttribute('title', formatDate(el.dateTime));
- $(el).tooltip({
- template:
- '<div class="tooltip local-timeago" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',
- });
});
}
diff --git a/app/assets/javascripts/lib/utils/dom_utils.js b/app/assets/javascripts/lib/utils/dom_utils.js
index d9b0e8c4476..7bba7ba2f45 100644
--- a/app/assets/javascripts/lib/utils/dom_utils.js
+++ b/app/assets/javascripts/lib/utils/dom_utils.js
@@ -47,3 +47,25 @@ export const parseBooleanDataAttributes = ({ dataset }, names) =>
return acc;
}, {});
+
+/**
+ * Returns whether or not the provided element is currently visible.
+ * This function operates identically to jQuery's `:visible` pseudo-selector.
+ * Documentation for this selector: https://api.jquery.com/visible-selector/
+ * Implementation of this selector: https://github.com/jquery/jquery/blob/d0ce00cdfa680f1f0c38460bc51ea14079ae8b07/src/css/hiddenVisibleSelectors.js#L8
+ * @param {HTMLElement} element The element to test
+ * @returns {Boolean} `true` if the element is currently visible, otherwise false
+ */
+export const isElementVisible = element =>
+ Boolean(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
+
+/**
+ * The opposite of `isElementVisible`.
+ * Returns whether or not the provided element is currently hidden.
+ * This function operates identically to jQuery's `:hidden` pseudo-selector.
+ * Documentation for this selector: https://api.jquery.com/hidden-selector/
+ * Implementation of this selector: https://github.com/jquery/jquery/blob/d0ce00cdfa680f1f0c38460bc51ea14079ae8b07/src/css/hiddenVisibleSelectors.js#L6
+ * @param {HTMLElement} element The element to test
+ * @returns {Boolean} `true` if the element is currently hidden, otherwise false
+ */
+export const isElementHidden = element => !isElementVisible(element);
diff --git a/app/assets/javascripts/lib/utils/http_status.js b/app/assets/javascripts/lib/utils/http_status.js
index 7132986a7e6..06529f06a66 100644
--- a/app/assets/javascripts/lib/utils/http_status.js
+++ b/app/assets/javascripts/lib/utils/http_status.js
@@ -22,6 +22,7 @@ const httpStatusCodes = {
CONFLICT: 409,
GONE: 410,
UNPROCESSABLE_ENTITY: 422,
+ TOO_MANY_REQUESTS: 429,
INTERNAL_SERVER_ERROR: 500,
SERVICE_UNAVAILABLE: 503,
};
diff --git a/app/assets/javascripts/lib/utils/number_utils.js b/app/assets/javascripts/lib/utils/number_utils.js
index 2424d6cbf3b..bc87232f40b 100644
--- a/app/assets/javascripts/lib/utils/number_utils.js
+++ b/app/assets/javascripts/lib/utils/number_utils.js
@@ -1,4 +1,4 @@
-import { BYTES_IN_KIB, BYTES_IN_KB } from './constants';
+import { BYTES_IN_KIB } from './constants';
import { sprintf, __ } from '~/locale';
/**
@@ -35,18 +35,6 @@ export function formatRelevantDigits(number) {
}
/**
- * Utility function that calculates KB of the given bytes.
- * Note: This method calculates KiloBytes as opposed to
- * Kibibytes. For Kibibytes, bytesToKiB should be used.
- *
- * @param {Number} number bytes
- * @return {Number} KiB
- */
-export function bytesToKB(number) {
- return number / BYTES_IN_KB;
-}
-
-/**
* Utility function that calculates KiB of the given bytes.
*
* @param {Number} number bytes
diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js
index 8ac6a44cba9..a81ca3f211f 100644
--- a/app/assets/javascripts/lib/utils/text_utility.js
+++ b/app/assets/javascripts/lib/utils/text_utility.js
@@ -399,3 +399,15 @@ export const truncateNamespace = (string = '') => {
* @returns {Boolean}
*/
export const hasContent = obj => isString(obj) && obj.trim() !== '';
+
+/**
+ * A utility function that validates if a
+ * string is valid SHA1 hash format.
+ *
+ * @param {String} hash to validate
+ *
+ * @return {Boolean} true if valid
+ */
+export const isValidSha1Hash = str => {
+ return /^[0-9a-f]{5,40}$/.test(str);
+};
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index d60f949c49d..b404f390a2d 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -40,6 +40,7 @@ import { initUserTracking, initDefaultTrackers } from './tracking';
import { __ } from './locale';
import * as tooltips from '~/tooltips';
+import * as popovers from '~/popovers';
import 'ee_else_ce/main_ee';
@@ -81,7 +82,7 @@ document.addEventListener('beforeunload', () => {
// Close any open tooltips
tooltips.dispose(document.querySelectorAll('.has-tooltip, [data-toggle="tooltip"]'));
// Close any open popover
- $('[data-toggle="popover"]').popover('dispose');
+ popovers.dispose();
});
window.addEventListener('hashchange', handleLocationHash);
@@ -166,13 +167,7 @@ function deferredInitialisation() {
});
// Initialize popovers
- $body.popover({
- selector: '[data-toggle="popover"]',
- trigger: 'focus',
- // set the viewport to the main content, excluding the navigation bar, so
- // the navigation can't overlap the popover
- viewport: '.layout-page',
- });
+ popovers.initPopovers();
// Adding a helper class to activate animations only after all is rendered
setTimeout(() => $body.addClass('page-initialised'), 1000);
diff --git a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
index 3a67d0ad64a..356d8619fed 100644
--- a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
+++ b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
@@ -1,11 +1,10 @@
/* eslint-disable no-param-reassign */
-/* global ace */
import Vue from 'vue';
+import { debounce } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from '~/flash';
import { __ } from '~/locale';
-import getModeByFileExtension from '~/lib/utils/ace_utils';
(global => {
global.mergeConflicts = global.mergeConflicts || {};
@@ -28,7 +27,6 @@ import getModeByFileExtension from '~/lib/utils/ace_utils';
data() {
return {
saved: false,
- loading: false,
fileLoaded: false,
originalContent: '',
};
@@ -37,7 +35,6 @@ import getModeByFileExtension from '~/lib/utils/ace_utils';
classObject() {
return {
saved: this.saved,
- 'is-loading': this.loading,
};
},
},
@@ -45,7 +42,7 @@ import getModeByFileExtension from '~/lib/utils/ace_utils';
'file.showEditor': function showEditorWatcher(val) {
this.resetEditorContent();
- if (!val || this.fileLoaded || this.loading) {
+ if (!val || this.fileLoaded) {
return;
}
@@ -59,30 +56,25 @@ import getModeByFileExtension from '~/lib/utils/ace_utils';
},
methods: {
loadEditor() {
- this.loading = true;
+ const EditorPromise = import(/* webpackChunkName: 'EditorLite' */ '~/editor/editor_lite');
+ const DataPromise = axios.get(this.file.content_path);
- axios
- .get(this.file.content_path)
- .then(({ data }) => {
- const content = this.$el.querySelector('pre');
- const fileContent = document.createTextNode(data.content);
+ Promise.all([EditorPromise, DataPromise])
+ .then(([{ default: EditorLite }, { data: { content, new_path: path } }]) => {
+ const contentEl = this.$el.querySelector('.editor');
- content.textContent = fileContent.textContent;
-
- this.originalContent = data.content;
+ this.originalContent = content;
this.fileLoaded = true;
- this.editor = ace.edit(content);
- this.editor.$blockScrolling = Infinity; // Turn off annoying warning
- this.editor.getSession().setMode(getModeByFileExtension(data.new_path));
- this.editor.on('change', () => {
- this.saveDiffResolution();
+
+ this.editor = new EditorLite().createInstance({
+ el: contentEl,
+ blobPath: path,
+ blobContent: content,
});
- this.saveDiffResolution();
- this.loading = false;
+ this.editor.onDidChangeModelContent(debounce(this.saveDiffResolution.bind(this), 250));
})
.catch(() => {
flash(__('An error occurred while loading the file'));
- this.loading = false;
});
},
saveDiffResolution() {
@@ -95,7 +87,7 @@ import getModeByFileExtension from '~/lib/utils/ace_utils';
},
resetEditorContent() {
if (this.fileLoaded) {
- this.editor.setValue(this.originalContent, -1);
+ this.editor.setValue(this.originalContent);
}
},
cancelDiscardConfirmation(file) {
diff --git a/app/assets/javascripts/milestones/components/milestone_combobox.vue b/app/assets/javascripts/milestones/components/milestone_combobox.vue
new file mode 100644
index 00000000000..08fd5a5994f
--- /dev/null
+++ b/app/assets/javascripts/milestones/components/milestone_combobox.vue
@@ -0,0 +1,250 @@
+<script>
+import {
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
+ GlDropdownItem,
+ GlLoadingIcon,
+ GlSearchBoxByType,
+ GlIcon,
+} from '@gitlab/ui';
+import { debounce, isEqual } from 'lodash';
+import { mapActions, mapGetters, mapState } from 'vuex';
+import { s__, __, sprintf } from '~/locale';
+import createStore from '../stores';
+import MilestoneResultsSection from './milestone_results_section.vue';
+
+const SEARCH_DEBOUNCE_MS = 250;
+
+export default {
+ name: 'MilestoneCombobox',
+ store: createStore(),
+ components: {
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
+ GlDropdownItem,
+ GlLoadingIcon,
+ GlSearchBoxByType,
+ GlIcon,
+ MilestoneResultsSection,
+ },
+ props: {
+ value: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ projectId: {
+ type: String,
+ required: true,
+ },
+ groupId: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ groupMilestonesAvailable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ extraLinks: {
+ type: Array,
+ default: () => [],
+ required: false,
+ },
+ },
+ data() {
+ return {
+ searchQuery: '',
+ };
+ },
+ translations: {
+ milestone: s__('MilestoneCombobox|Milestone'),
+ selectMilestone: s__('MilestoneCombobox|Select milestone'),
+ noMilestone: s__('MilestoneCombobox|No milestone'),
+ noResultsLabel: s__('MilestoneCombobox|No matching results'),
+ searchMilestones: s__('MilestoneCombobox|Search Milestones'),
+ searchErrorMessage: s__('MilestoneCombobox|An error occurred while searching for milestones'),
+ projectMilestones: s__('MilestoneCombobox|Project milestones'),
+ groupMilestones: s__('MilestoneCombobox|Group milestones'),
+ },
+ computed: {
+ ...mapState(['matches', 'selectedMilestones']),
+ ...mapGetters(['isLoading', 'groupMilestonesEnabled']),
+ selectedMilestonesLabel() {
+ const { selectedMilestones } = this;
+ const firstMilestoneName = selectedMilestones[0];
+
+ if (selectedMilestones.length === 0) {
+ return this.$options.translations.noMilestone;
+ }
+
+ if (selectedMilestones.length === 1) {
+ return firstMilestoneName;
+ }
+
+ const numberOfOtherMilestones = selectedMilestones.length - 1;
+ return sprintf(__('%{firstMilestoneName} + %{numberOfOtherMilestones} more'), {
+ firstMilestoneName,
+ numberOfOtherMilestones,
+ });
+ },
+ showProjectMilestoneSection() {
+ return Boolean(
+ this.matches.projectMilestones.totalCount > 0 || this.matches.projectMilestones.error,
+ );
+ },
+ showGroupMilestoneSection() {
+ return (
+ this.groupMilestonesEnabled &&
+ Boolean(this.matches.groupMilestones.totalCount > 0 || this.matches.groupMilestones.error)
+ );
+ },
+ showNoResults() {
+ return !this.showProjectMilestoneSection && !this.showGroupMilestoneSection;
+ },
+ },
+ watch: {
+ // Keep the Vuex store synchronized if the parent
+ // component updates the selected milestones through v-model
+ value: {
+ immediate: true,
+ handler() {
+ const milestoneTitles = this.value.map(milestone =>
+ milestone.title ? milestone.title : milestone,
+ );
+ if (!isEqual(milestoneTitles, this.selectedMilestones)) {
+ this.setSelectedMilestones(milestoneTitles);
+ }
+ },
+ },
+ },
+ 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.searchQuery);
+ }, SEARCH_DEBOUNCE_MS);
+
+ this.setProjectId(this.projectId);
+ this.setGroupId(this.groupId);
+ this.setGroupMilestonesAvailable(this.groupMilestonesAvailable);
+ this.fetchMilestones();
+ },
+ methods: {
+ ...mapActions([
+ 'setProjectId',
+ 'setGroupId',
+ 'setGroupMilestonesAvailable',
+ 'setSelectedMilestones',
+ 'clearSelectedMilestones',
+ 'toggleMilestones',
+ 'search',
+ 'fetchMilestones',
+ ]),
+ focusSearchBox() {
+ this.$refs.searchBox.$el.querySelector('input').focus();
+ },
+ onSearchBoxEnter() {
+ this.debouncedSearch.cancel();
+ this.search(this.searchQuery);
+ },
+ onSearchBoxInput() {
+ this.debouncedSearch();
+ },
+ selectMilestone(milestone) {
+ this.toggleMilestones(milestone);
+ this.$emit('input', this.selectedMilestones);
+ },
+ selectNoMilestone() {
+ this.clearSelectedMilestones();
+ this.$emit('input', this.selectedMilestones);
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown v-bind="$attrs" class="milestone-combobox" @shown="focusSearchBox">
+ <template slot="button-content">
+ <span data-testid="milestone-combobox-button-content" class="gl-flex-grow-1 text-muted">{{
+ selectedMilestonesLabel
+ }}</span>
+ <gl-icon name="chevron-down" />
+ </template>
+
+ <gl-dropdown-section-header>
+ <span class="text-center d-block">{{ $options.translations.selectMilestone }}</span>
+ </gl-dropdown-section-header>
+
+ <gl-dropdown-divider />
+
+ <gl-search-box-by-type
+ ref="searchBox"
+ v-model.trim="searchQuery"
+ class="gl-m-3"
+ :placeholder="this.$options.translations.searchMilestones"
+ @input="onSearchBoxInput"
+ @keydown.enter.prevent="onSearchBoxEnter"
+ />
+
+ <gl-dropdown-item @click="selectNoMilestone()">
+ <span :class="{ 'gl-pl-6': true, 'selected-item': selectedMilestones.length === 0 }">
+ {{ $options.translations.noMilestone }}
+ </span>
+ </gl-dropdown-item>
+
+ <gl-dropdown-divider />
+
+ <template v-if="isLoading">
+ <gl-loading-icon />
+ <gl-dropdown-divider />
+ </template>
+ <template v-else-if="showNoResults">
+ <div class="dropdown-item-space">
+ <span data-testid="milestone-combobox-no-results" class="gl-pl-6">{{
+ $options.translations.noResultsLabel
+ }}</span>
+ </div>
+ <gl-dropdown-divider />
+ </template>
+ <template v-else>
+ <milestone-results-section
+ v-if="showProjectMilestoneSection"
+ :section-title="$options.translations.projectMilestones"
+ :total-count="matches.projectMilestones.totalCount"
+ :items="matches.projectMilestones.list"
+ :selected-milestones="selectedMilestones"
+ :error="matches.projectMilestones.error"
+ :error-message="$options.translations.searchErrorMessage"
+ data-testid="project-milestones-section"
+ @selected="selectMilestone($event)"
+ />
+
+ <milestone-results-section
+ v-if="showGroupMilestoneSection"
+ :section-title="$options.translations.groupMilestones"
+ :total-count="matches.groupMilestones.totalCount"
+ :items="matches.groupMilestones.list"
+ :selected-milestones="selectedMilestones"
+ :error="matches.groupMilestones.error"
+ :error-message="$options.translations.searchErrorMessage"
+ data-testid="group-milestones-section"
+ @selected="selectMilestone($event)"
+ />
+ </template>
+ <gl-dropdown-item
+ v-for="(item, idx) in extraLinks"
+ :key="idx"
+ :href="item.url"
+ data-testid="milestone-combobox-extra-links"
+ >
+ <span class="gl-pl-6">{{ item.text }}</span>
+ </gl-dropdown-item>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/milestones/components/milestone_results_section.vue b/app/assets/javascripts/milestones/components/milestone_results_section.vue
new file mode 100644
index 00000000000..d53a59e58d4
--- /dev/null
+++ b/app/assets/javascripts/milestones/components/milestone_results_section.vue
@@ -0,0 +1,93 @@
+<script>
+import {
+ GlDropdownSectionHeader,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlBadge,
+ GlIcon,
+} from '@gitlab/ui';
+import { s__ } from '~/locale';
+
+export default {
+ name: 'MilestoneResultsSection',
+ components: {
+ GlDropdownSectionHeader,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlBadge,
+ GlIcon,
+ },
+ props: {
+ sectionTitle: {
+ type: String,
+ required: true,
+ },
+ totalCount: {
+ type: Number,
+ required: true,
+ },
+ items: {
+ type: Array,
+ required: true,
+ },
+ selectedMilestones: {
+ type: Array,
+ required: true,
+ default: () => [],
+ },
+ error: {
+ type: Error,
+ required: false,
+ default: null,
+ },
+ errorMessage: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ totalCountText() {
+ return this.totalCount > 999 ? s__('TotalMilestonesIndicator|1000+') : `${this.totalCount}`;
+ },
+ },
+ methods: {
+ isSelectedMilestone(item) {
+ return this.selectedMilestones.includes(item);
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-dropdown-section-header>
+ <div
+ class="gl-display-flex gl-align-items-center gl-pl-6"
+ data-testid="milestone-results-section-header"
+ >
+ <span class="gl-mr-2 gl-mb-1">{{ sectionTitle }}</span>
+ <gl-badge variant="neutral">{{ totalCountText }}</gl-badge>
+ </div>
+ </gl-dropdown-section-header>
+ <template v-if="error">
+ <div class="gl-display-flex align-items-start gl-text-red-500 gl-ml-4 gl-mr-4 gl-mb-3">
+ <gl-icon name="error" class="gl-mr-2 gl-mt-2 gl-flex-shrink-0" />
+ <span>{{ errorMessage }}</span>
+ </div>
+ </template>
+ <template v-else>
+ <gl-dropdown-item
+ v-for="{ title } in items"
+ :key="title"
+ role="milestone option"
+ @click="$emit('selected', title)"
+ >
+ <span class="gl-pl-6" :class="{ 'selected-item': isSelectedMilestone(title) }">
+ {{ title }}
+ </span>
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/milestones/project_milestone_combobox.vue b/app/assets/javascripts/milestones/project_milestone_combobox.vue
deleted file mode 100644
index 0fa5585e858..00000000000
--- a/app/assets/javascripts/milestones/project_milestone_combobox.vue
+++ /dev/null
@@ -1,249 +0,0 @@
-<script>
-import {
- GlDropdown,
- GlDropdownDivider,
- GlDropdownSectionHeader,
- GlDropdownItem,
- GlLoadingIcon,
- GlSearchBoxByType,
- GlIcon,
-} from '@gitlab/ui';
-import { intersection, debounce } from 'lodash';
-import { __, sprintf } from '~/locale';
-import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-
-const SEARCH_DEBOUNCE_MS = 250;
-
-export default {
- components: {
- GlDropdown,
- GlDropdownDivider,
- GlDropdownSectionHeader,
- GlDropdownItem,
- GlLoadingIcon,
- GlSearchBoxByType,
- GlIcon,
- },
- model: {
- prop: 'preselectedMilestones',
- event: 'change',
- },
- props: {
- projectId: {
- type: String,
- required: true,
- },
- preselectedMilestones: {
- type: Array,
- default: () => [],
- required: false,
- },
- extraLinks: {
- type: Array,
- default: () => [],
- required: false,
- },
- },
- data() {
- return {
- searchQuery: '',
- projectMilestones: [],
- searchResults: [],
- selectedMilestones: [],
- requestCount: 0,
- };
- },
- translations: {
- milestone: __('Milestone'),
- selectMilestone: __('Select milestone'),
- noMilestone: __('No milestone'),
- noResultsLabel: __('No matching results'),
- searchMilestones: __('Search Milestones'),
- },
- computed: {
- selectedMilestonesLabel() {
- if (this.milestoneTitles.length === 1) {
- return this.milestoneTitles[0];
- }
-
- if (this.milestoneTitles.length > 1) {
- const firstMilestoneName = this.milestoneTitles[0];
- const numberOfOtherMilestones = this.milestoneTitles.length - 1;
- return sprintf(__('%{firstMilestoneName} + %{numberOfOtherMilestones} more'), {
- firstMilestoneName,
- numberOfOtherMilestones,
- });
- }
-
- return this.$options.translations.noMilestone;
- },
- milestoneTitles() {
- return this.preselectedMilestones.map(milestone => milestone.title);
- },
- dropdownItems() {
- return this.searchResults.length ? this.searchResults : this.projectMilestones;
- },
- noResults() {
- return this.searchQuery.length > 2 && this.searchResults.length === 0;
- },
- isLoading() {
- 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;
-
- Api.projectMilestones(this.projectId)
- .then(({ data }) => {
- this.projectMilestones = this.getTitles(data);
- this.selectedMilestones = intersection(this.projectMilestones, this.milestoneTitles);
- })
- .catch(() => {
- createFlash(__('An error occurred while loading milestones'));
- })
- .finally(() => {
- this.requestCount -= 1;
- });
- },
- searchMilestones() {
- this.requestCount += 1;
- const options = {
- search: this.searchQuery,
- scope: 'milestones',
- };
-
- if (this.searchQuery.length < 3) {
- this.requestCount -= 1;
- this.searchResults = [];
- return;
- }
-
- Api.projectSearch(this.projectId, options)
- .then(({ data }) => {
- const searchResults = this.getTitles(data);
-
- this.searchResults = searchResults.length ? searchResults : [];
- })
- .catch(() => {
- createFlash(__('An error occurred while searching for milestones'));
- })
- .finally(() => {
- this.requestCount -= 1;
- });
- },
- onSearchBoxInput() {
- this.debouncedSearchMilestones();
- },
- onSearchBoxEnter() {
- this.debouncedSearchMilestones.cancel();
- this.searchMilestones();
- },
- toggleMilestoneSelection(clickedMilestone) {
- if (!clickedMilestone) return [];
-
- let milestones = [...this.preselectedMilestones];
- const hasMilestone = this.milestoneTitles.includes(clickedMilestone);
-
- if (hasMilestone) {
- milestones = milestones.filter(({ title }) => title !== clickedMilestone);
- } else {
- milestones.push({ title: clickedMilestone });
- }
-
- return milestones;
- },
- onMilestoneClicked(clickedMilestone) {
- const milestones = this.toggleMilestoneSelection(clickedMilestone);
- this.$emit('change', milestones);
-
- this.selectedMilestones = intersection(
- this.projectMilestones,
- milestones.map(milestone => milestone.title),
- );
- },
- isSelectedMilestone(milestoneTitle) {
- return this.selectedMilestones.includes(milestoneTitle);
- },
- getTitles(milestones) {
- return milestones.filter(({ state }) => state === 'active').map(({ title }) => title);
- },
- },
-};
-</script>
-
-<template>
- <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
- }}</span>
- <gl-icon name="chevron-down" />
- </template>
-
- <gl-dropdown-section-header>
- <span class="text-center d-block">{{ $options.translations.selectMilestone }}</span>
- </gl-dropdown-section-header>
-
- <gl-dropdown-divider />
-
- <gl-search-box-by-type
- ref="searchBox"
- v-model.trim="searchQuery"
- :placeholder="this.$options.translations.searchMilestones"
- @input="onSearchBoxInput"
- @keydown.enter.prevent="onSearchBoxEnter"
- />
-
- <gl-dropdown-item @click="onMilestoneClicked(null)">
- <span :class="{ 'pl-4': true, 'selected-item': selectedMilestones.length === 0 }">
- {{ $options.translations.noMilestone }}
- </span>
- </gl-dropdown-item>
-
- <gl-dropdown-divider />
-
- <template v-if="isLoading">
- <gl-loading-icon />
- <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-dropdown-divider />
- </template>
- <template v-else-if="dropdownItems.length">
- <gl-dropdown-item
- v-for="item in dropdownItems"
- :key="item"
- role="milestone option"
- @click="onMilestoneClicked(item)"
- >
- <span :class="{ 'pl-4': true, 'selected-item': isSelectedMilestone(item) }">
- {{ item }}
- </span>
- </gl-dropdown-item>
- <gl-dropdown-divider />
- </template>
-
- <gl-dropdown-item v-for="(item, idx) in extraLinks" :key="idx" :href="item.url">
- <span class="pl-4">{{ item.text }}</span>
- </gl-dropdown-item>
- </gl-dropdown>
-</template>
diff --git a/app/assets/javascripts/milestones/stores/actions.js b/app/assets/javascripts/milestones/stores/actions.js
index 3859771aeba..df45c7156ad 100644
--- a/app/assets/javascripts/milestones/stores/actions.js
+++ b/app/assets/javascripts/milestones/stores/actions.js
@@ -2,10 +2,15 @@ import Api from '~/api';
import * as types from './mutation_types';
export const setProjectId = ({ commit }, projectId) => commit(types.SET_PROJECT_ID, projectId);
+export const setGroupId = ({ commit }, groupId) => commit(types.SET_GROUP_ID, groupId);
+export const setGroupMilestonesAvailable = ({ commit }, groupMilestonesAvailable) =>
+ commit(types.SET_GROUP_MILESTONES_AVAILABLE, groupMilestonesAvailable);
export const setSelectedMilestones = ({ commit }, selectedMilestones) =>
commit(types.SET_SELECTED_MILESTONES, selectedMilestones);
+export const clearSelectedMilestones = ({ commit }) => commit(types.CLEAR_SELECTED_MILESTONES);
+
export const toggleMilestones = ({ commit, state }, selectedMilestone) => {
const removeMilestone = state.selectedMilestones.includes(selectedMilestone);
@@ -16,13 +21,23 @@ export const toggleMilestones = ({ commit, state }, selectedMilestone) => {
}
};
-export const search = ({ dispatch, commit }, query) => {
- commit(types.SET_QUERY, query);
+export const search = ({ dispatch, commit, getters }, searchQuery) => {
+ commit(types.SET_SEARCH_QUERY, searchQuery);
+
+ dispatch('searchProjectMilestones');
+ if (getters.groupMilestonesEnabled) {
+ dispatch('searchGroupMilestones');
+ }
+};
- dispatch('searchMilestones');
+export const fetchMilestones = ({ dispatch, getters }) => {
+ dispatch('fetchProjectMilestones');
+ if (getters.groupMilestonesEnabled) {
+ dispatch('fetchGroupMilestones');
+ }
};
-export const fetchMilestones = ({ commit, state }) => {
+export const fetchProjectMilestones = ({ commit, state }) => {
commit(types.REQUEST_START);
Api.projectMilestones(state.projectId)
@@ -37,14 +52,29 @@ export const fetchMilestones = ({ commit, state }) => {
});
};
-export const searchMilestones = ({ commit, state }) => {
+export const fetchGroupMilestones = ({ commit, state }) => {
commit(types.REQUEST_START);
+ Api.groupMilestones(state.groupId)
+ .then(response => {
+ commit(types.RECEIVE_GROUP_MILESTONES_SUCCESS, response);
+ })
+ .catch(error => {
+ commit(types.RECEIVE_GROUP_MILESTONES_ERROR, error);
+ })
+ .finally(() => {
+ commit(types.REQUEST_FINISH);
+ });
+};
+
+export const searchProjectMilestones = ({ commit, state }) => {
const options = {
- search: state.query,
+ search: state.searchQuery,
scope: 'milestones',
};
+ commit(types.REQUEST_START);
+
Api.projectSearch(state.projectId, options)
.then(response => {
commit(types.RECEIVE_PROJECT_MILESTONES_SUCCESS, response);
@@ -56,3 +86,22 @@ export const searchMilestones = ({ commit, state }) => {
commit(types.REQUEST_FINISH);
});
};
+
+export const searchGroupMilestones = ({ commit, state }) => {
+ const options = {
+ search: state.searchQuery,
+ };
+
+ commit(types.REQUEST_START);
+
+ Api.groupMilestones(state.groupId, options)
+ .then(response => {
+ commit(types.RECEIVE_GROUP_MILESTONES_SUCCESS, response);
+ })
+ .catch(error => {
+ commit(types.RECEIVE_GROUP_MILESTONES_ERROR, error);
+ })
+ .finally(() => {
+ commit(types.REQUEST_FINISH);
+ });
+};
diff --git a/app/assets/javascripts/milestones/stores/getters.js b/app/assets/javascripts/milestones/stores/getters.js
index d8a283403ec..b5fcfbe35d5 100644
--- a/app/assets/javascripts/milestones/stores/getters.js
+++ b/app/assets/javascripts/milestones/stores/getters.js
@@ -1,2 +1,6 @@
/** Returns `true` if there is at least one in-progress request */
export const isLoading = ({ requestCount }) => requestCount > 0;
+
+/** Returns `true` if there is a group ID and group milestones are available */
+export const groupMilestonesEnabled = ({ groupId, groupMilestonesAvailable }) =>
+ Boolean(groupId && groupMilestonesAvailable);
diff --git a/app/assets/javascripts/milestones/stores/mutation_types.js b/app/assets/javascripts/milestones/stores/mutation_types.js
index 370d386dba2..22e50571e34 100644
--- a/app/assets/javascripts/milestones/stores/mutation_types.js
+++ b/app/assets/javascripts/milestones/stores/mutation_types.js
@@ -1,13 +1,19 @@
export const SET_PROJECT_ID = 'SET_PROJECT_ID';
+export const SET_GROUP_ID = 'SET_GROUP_ID';
+export const SET_GROUP_MILESTONES_AVAILABLE = 'SET_GROUP_MILESTONES_AVAILABLE';
export const SET_SELECTED_MILESTONES = 'SET_SELECTED_MILESTONES';
+export const CLEAR_SELECTED_MILESTONES = 'CLEAR_SELECTED_MILESTONES';
export const ADD_SELECTED_MILESTONE = 'ADD_SELECTED_MILESTONE';
export const REMOVE_SELECTED_MILESTONE = 'REMOVE_SELECTED_MILESTONE';
-export const SET_QUERY = 'SET_QUERY';
+export const SET_SEARCH_QUERY = 'SET_SEARCH_QUERY';
export const REQUEST_START = 'REQUEST_START';
export const REQUEST_FINISH = 'REQUEST_FINISH';
export const RECEIVE_PROJECT_MILESTONES_SUCCESS = 'RECEIVE_PROJECT_MILESTONES_SUCCESS';
export const RECEIVE_PROJECT_MILESTONES_ERROR = 'RECEIVE_PROJECT_MILESTONES_ERROR';
+
+export const RECEIVE_GROUP_MILESTONES_SUCCESS = 'RECEIVE_GROUP_MILESTONES_SUCCESS';
+export const RECEIVE_GROUP_MILESTONES_ERROR = 'RECEIVE_GROUP_MILESTONES_ERROR';
diff --git a/app/assets/javascripts/milestones/stores/mutations.js b/app/assets/javascripts/milestones/stores/mutations.js
index 7c75d09766c..601b88cb62a 100644
--- a/app/assets/javascripts/milestones/stores/mutations.js
+++ b/app/assets/javascripts/milestones/stores/mutations.js
@@ -1,14 +1,22 @@
import Vue from 'vue';
import * as types from './mutation_types';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
export default {
[types.SET_PROJECT_ID](state, projectId) {
state.projectId = projectId;
},
+ [types.SET_GROUP_ID](state, groupId) {
+ state.groupId = groupId;
+ },
+ [types.SET_GROUP_MILESTONES_AVAILABLE](state, groupMilestonesAvailable) {
+ state.groupMilestonesAvailable = groupMilestonesAvailable;
+ },
[types.SET_SELECTED_MILESTONES](state, selectedMilestones) {
Vue.set(state, 'selectedMilestones', selectedMilestones);
},
+ [types.CLEAR_SELECTED_MILESTONES](state) {
+ Vue.set(state, 'selectedMilestones', []);
+ },
[types.ADD_SELECTED_MILESTONE](state, selectedMilestone) {
state.selectedMilestones.push(selectedMilestone);
},
@@ -18,8 +26,8 @@ export default {
);
Vue.set(state, 'selectedMilestones', filteredMilestones);
},
- [types.SET_QUERY](state, query) {
- state.query = query;
+ [types.SET_SEARCH_QUERY](state, searchQuery) {
+ state.searchQuery = searchQuery;
},
[types.REQUEST_START](state) {
state.requestCount += 1;
@@ -29,7 +37,7 @@ export default {
},
[types.RECEIVE_PROJECT_MILESTONES_SUCCESS](state, response) {
state.matches.projectMilestones = {
- list: convertObjectPropsToCamelCase(response.data).map(({ title }) => ({ title })),
+ list: response.data.map(({ title }) => ({ title })),
totalCount: parseInt(response.headers['x-total'], 10),
error: null,
};
@@ -41,4 +49,18 @@ export default {
error,
};
},
+ [types.RECEIVE_GROUP_MILESTONES_SUCCESS](state, response) {
+ state.matches.groupMilestones = {
+ list: response.data.map(({ title }) => ({ title })),
+ totalCount: parseInt(response.headers['x-total'], 10),
+ error: null,
+ };
+ },
+ [types.RECEIVE_GROUP_MILESTONES_ERROR](state, error) {
+ state.matches.groupMilestones = {
+ list: [],
+ totalCount: 0,
+ error,
+ };
+ },
};
diff --git a/app/assets/javascripts/milestones/stores/state.js b/app/assets/javascripts/milestones/stores/state.js
index 0944539f367..82723ab32f9 100644
--- a/app/assets/javascripts/milestones/stores/state.js
+++ b/app/assets/javascripts/milestones/stores/state.js
@@ -1,13 +1,19 @@
export default () => ({
projectId: null,
groupId: null,
- query: '',
+ groupMilestonesAvailable: false,
+ searchQuery: '',
matches: {
projectMilestones: {
list: [],
totalCount: 0,
error: null,
},
+ groupMilestones: {
+ list: [],
+ totalCount: 0,
+ error: null,
+ },
},
selectedMilestones: [],
requestCount: 0,
diff --git a/app/assets/javascripts/monitoring/components/charts/column.vue b/app/assets/javascripts/monitoring/components/charts/column.vue
index d7d01def45e..511f77a441b 100644
--- a/app/assets/javascripts/monitoring/components/charts/column.vue
+++ b/app/assets/javascripts/monitoring/components/charts/column.vue
@@ -35,18 +35,14 @@ export default {
};
},
computed: {
- chartData() {
- const queryData = this.graphData.metrics.reduce((acc, query) => {
+ barChartData() {
+ return this.graphData.metrics.reduce((acc, query) => {
const series = makeDataSeries(query.result || [], {
name: this.formatLegendLabel(query),
});
return acc.concat(series);
}, []);
-
- return {
- values: queryData[0].data,
- };
},
chartOptions() {
const xAxis = getTimeAxisOptions({ timezone: this.timezone });
@@ -109,7 +105,7 @@ export default {
<gl-column-chart
ref="columnChart"
v-bind="$attrs"
- :data="chartData"
+ :bars="barChartData"
:option="chartOptions"
:width="width"
:height="height"
diff --git a/app/assets/javascripts/monitoring/components/charts/stacked_column.vue b/app/assets/javascripts/monitoring/components/charts/stacked_column.vue
index 9bcd4419a14..66b4d0d86e6 100644
--- a/app/assets/javascripts/monitoring/components/charts/stacked_column.vue
+++ b/app/assets/javascripts/monitoring/components/charts/stacked_column.vue
@@ -61,14 +61,16 @@ export default {
},
computed: {
chartData() {
- return this.graphData.metrics.map(({ result }) => {
- // This needs a fix. Not only metrics[0] should be shown.
- // See https://gitlab.com/gitlab-org/gitlab/-/issues/220492
- if (!result || result.length === 0) {
- return [];
- }
- return result[0].values.map(val => val[1]);
- });
+ return this.graphData.metrics
+ .map(({ label: name, result }) => {
+ // This needs a fix. Not only metrics[0] should be shown.
+ // See https://gitlab.com/gitlab-org/gitlab/-/issues/220492
+ if (!result || result.length === 0) {
+ return [];
+ }
+ return { name, data: result[0].values.map(val => val[1]) };
+ })
+ .slice(0, 1);
},
xAxisTitle() {
return this.graphData.x_label !== undefined ? this.graphData.x_label : '';
@@ -136,7 +138,7 @@ export default {
<gl-stacked-column-chart
ref="chart"
v-bind="$attrs"
- :data="chartData"
+ :bars="chartData"
:option="chartOptions"
:x-axis-title="xAxisTitle"
:y-axis-title="yAxisTitle"
@@ -144,7 +146,6 @@ export default {
:group-by="groupBy"
:width="width"
:height="height"
- :series-names="seriesNames"
:legend-layout="legendLayout"
:legend-average-text="legendAverageText"
:legend-current-text="legendCurrentText"
diff --git a/app/assets/javascripts/monitoring/components/charts/time_series.vue b/app/assets/javascripts/monitoring/components/charts/time_series.vue
index 6bae3fdcc2e..bda2adeb62a 100644
--- a/app/assets/javascripts/monitoring/components/charts/time_series.vue
+++ b/app/assets/javascripts/monitoring/components/charts/time_series.vue
@@ -402,21 +402,21 @@ export default {
@updated="onChartUpdated"
>
<template v-if="tooltip.type === 'deployments'">
- <template slot="tooltipTitle">
+ <template slot="tooltip-title">
{{ __('Deployed') }}
</template>
- <div slot="tooltipContent" class="d-flex align-items-center">
+ <div slot="tooltip-content" class="d-flex align-items-center">
<gl-icon name="commit" class="mr-2" />
<gl-link :href="tooltip.commitUrl">{{ tooltip.sha }}</gl-link>
</div>
</template>
<template v-else>
- <template slot="tooltipTitle">
+ <template slot="tooltip-title">
<div class="text-nowrap">
{{ tooltip.title }}
</div>
</template>
- <template slot="tooltipContent" :tooltip="tooltip">
+ <template slot="tooltip-content" :tooltip="tooltip">
<div
v-for="(content, key) in tooltip.content"
:key="key"
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index cbfacd73b5b..16c2c87a4b7 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -423,7 +423,7 @@ export default {
:prometheus-alerts-available="prometheusAlertsAvailable"
@timerangezoom="onTimeRangeZoom"
>
- <template #topLeft>
+ <template #top-left>
<gl-button
ref="goBackBtn"
v-gl-tooltip
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
index 18310f7c71e..597600bba07 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
@@ -365,7 +365,7 @@ export default {
<template>
<div v-gl-resize-observer="onResize" class="prometheus-graph">
<div class="d-flex align-items-center">
- <slot name="topLeft"></slot>
+ <slot name="top-left"></slot>
<h5
ref="graphTitle"
class="prometheus-graph-title gl-font-lg font-weight-bold text-truncate gl-mr-3"
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue b/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue
index 88d5a35146f..0a1b1cd2c08 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue
@@ -85,7 +85,7 @@ export default {
<template>
<div class="prometheus-panel-builder">
<div class="gl-xs-flex-direction-column gl-display-flex gl-mx-n3">
- <gl-card class="gl-flex-grow-1 gl-flex-basis-0 gl-mx-3">
+ <gl-card class="gl-flex-grow-1 gl-flex-basis-0 gl-mx-3 gl-mb-5">
<template #header>
<h2 class="gl-font-size-h2 gl-my-3">{{ s__('Metrics|1. Define and preview panel') }}</h2>
</template>
@@ -124,7 +124,7 @@ export default {
</gl-card>
<gl-card
- class="gl-flex-grow-1 gl-flex-basis-0 gl-mx-3"
+ class="gl-flex-grow-1 gl-flex-basis-0 gl-mx-3 gl-mb-5"
body-class="gl-display-flex gl-flex-direction-column"
>
<template #header>
diff --git a/app/assets/javascripts/monitoring/components/embeds/embed_group.vue b/app/assets/javascripts/monitoring/components/embeds/embed_group.vue
index f07483c34b8..481ba3636cb 100644
--- a/app/assets/javascripts/monitoring/components/embeds/embed_group.vue
+++ b/app/assets/javascripts/monitoring/components/embeds/embed_group.vue
@@ -73,7 +73,7 @@ export default {
<template>
<gl-card
v-show="numCharts > 0"
- class="collapsible-card border p-0 mb-3"
+ class="collapsible-card border p-0 gl-mb-5"
header-class="d-flex align-items-center border-bottom-0 py-2"
:body-class="bodyClass"
>
diff --git a/app/assets/javascripts/monitoring/components/variables/dropdown_field.vue b/app/assets/javascripts/monitoring/components/variables/dropdown_field.vue
index 5563a27301d..4e48292c48d 100644
--- a/app/assets/javascripts/monitoring/components/variables/dropdown_field.vue
+++ b/app/assets/javascripts/monitoring/components/variables/dropdown_field.vue
@@ -1,11 +1,11 @@
<script>
-import { GlFormGroup, GlDeprecatedDropdown, GlDeprecatedDropdownItem } from '@gitlab/ui';
+import { GlFormGroup, GlDropdown, GlDropdownItem } from '@gitlab/ui';
export default {
components: {
GlFormGroup,
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
},
props: {
name: {
@@ -41,16 +41,13 @@ export default {
</script>
<template>
<gl-form-group :label="label">
- <gl-deprecated-dropdown
- toggle-class="dropdown-menu-toggle"
- :text="text || s__('Metrics|Select a value')"
- >
- <gl-deprecated-dropdown-item
+ <gl-dropdown toggle-class="dropdown-menu-toggle" :text="text || s__('Metrics|Select a value')">
+ <gl-dropdown-item
v-for="val in options.values"
:key="val.value"
@click="onUpdate(val.value)"
- >{{ val.text }}</gl-deprecated-dropdown-item
+ >{{ val.text }}</gl-dropdown-item
>
- </gl-deprecated-dropdown>
+ </gl-dropdown>
</gl-form-group>
</template>
diff --git a/app/assets/javascripts/notebook/cells/output/html.vue b/app/assets/javascripts/notebook/cells/output/html.vue
index 4d527baf730..a3d7ddd5bad 100644
--- a/app/assets/javascripts/notebook/cells/output/html.vue
+++ b/app/assets/javascripts/notebook/cells/output/html.vue
@@ -37,6 +37,6 @@ export default {
<template>
<div class="output">
<prompt type="Out" :count="count" :show-output="showOutput" />
- <div v-html="sanitizedOutput"></div>
+ <div class="gl-overflow-auto" v-html="sanitizedOutput"></div>
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index cfdadbceaf6..9cc53a320b8 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, GlButton } from '@gitlab/ui';
+import { GlAlert, GlIntersperse, GlLink, GlSprintf, GlButton, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import { deprecatedCreateFlash as Flash } from '../../flash';
@@ -38,6 +38,7 @@ export default {
GlIntersperse,
GlLink,
GlSprintf,
+ GlIcon,
},
mixins: [issuableStateMixin],
props: {
@@ -342,7 +343,7 @@ export default {
<ul v-else-if="canCreateNote" class="notes notes-form timeline">
<timeline-entry-item class="note-form">
<div class="flash-container error-alert timeline-content"></div>
- <div class="timeline-icon d-none d-sm-none d-md-block">
+ <div class="timeline-icon d-none d-md-block">
<user-avatar-link
v-if="author"
:link-href="author.path"
@@ -457,7 +458,7 @@ export default {
class="btn btn-transparent"
@click.prevent="setNoteType('comment')"
>
- <i aria-hidden="true" class="fa fa-check icon"></i>
+ <gl-icon name="check" class="icon" />
<div class="description">
<strong>{{ __('Comment') }}</strong>
<p>
@@ -476,7 +477,7 @@ export default {
data-qa-selector="discussion_menu_item"
@click.prevent="setNoteType('discussion')"
>
- <i aria-hidden="true" class="fa fa-check icon"></i>
+ <gl-icon name="check" class="icon" />
<div class="description">
<strong>{{ __('Start thread') }}</strong>
<p>{{ startDiscussionDescription }}</p>
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index a4271852563..91cf682943e 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -7,6 +7,7 @@ import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
import { getDiffMode } from '~/diffs/store/utils';
import { diffViewerModes } from '~/ide/constants';
+import { isCollapsed } from '../../diffs/diff_file';
const FIRST_CHAR_REGEX = /^(\+|-| )/;
@@ -46,6 +47,9 @@ export default {
this.discussion.truncated_diff_lines && this.discussion.truncated_diff_lines.length !== 0
);
},
+ isCollapsed() {
+ return isCollapsed(this.discussion.diff_file);
+ },
},
mounted() {
if (this.isTextFile && !this.hasTruncatedDiffLines) {
@@ -76,7 +80,7 @@ export default {
:discussion-path="discussion.discussion_path"
:diff-file="discussion.diff_file"
:can-current-user-fork="false"
- :expanded="!discussion.diff_file.viewer.automaticallyCollapsed"
+ :expanded="!isCollapsed"
/>
<div v-if="isTextFile" class="diff-content">
<table class="code js-syntax-highlight" :class="$options.userColorSchemeClass">
diff --git a/app/assets/javascripts/notes/components/discussion_actions.vue b/app/assets/javascripts/notes/components/discussion_actions.vue
index 878a748e99a..0272790a75d 100644
--- a/app/assets/javascripts/notes/components/discussion_actions.vue
+++ b/app/assets/javascripts/notes/components/discussion_actions.vue
@@ -45,7 +45,7 @@ export default {
return this.discussion.notes.filter(x => x.resolvable);
},
userCanResolveDiscussion() {
- return this.resolvableNotes.every(note => note.current_user && note.current_user.can_resolve);
+ return this.resolvableNotes.every(note => note.current_user?.can_resolve_discussion);
},
},
};
diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue
index e4b191b55a7..08c22f0b4c6 100644
--- a/app/assets/javascripts/notes/components/discussion_filter.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter.vue
@@ -116,7 +116,8 @@ export default {
<gl-dropdown
v-if="displayFilters"
id="discussion-filter-dropdown"
- class="gl-mr-3 full-width-mobile discussion-filter-container js-discussion-filter-container qa-discussion-filter"
+ class="gl-mr-3 full-width-mobile discussion-filter-container js-discussion-filter-container"
+ data-qa-selector="discussion_filter_dropdown"
:text="currentFilter.title"
>
<div v-for="filter in filters" :key="filter.value" class="dropdown-item-wrapper">
@@ -125,7 +126,7 @@ export default {
:is-checked="filter.value === currentValue"
:class="{ 'is-active': filter.value === currentValue }"
:data-filter-type="filterType(filter.value)"
- class="qa-filter-options"
+ data-qa-selector="filter_menu_item"
@click.prevent="selectFilter(filter.value)"
>
{{ filter.title }}
diff --git a/app/assets/javascripts/notes/components/discussion_filter_note.vue b/app/assets/javascripts/notes/components/discussion_filter_note.vue
index ae6646cf96c..83326279423 100644
--- a/app/assets/javascripts/notes/components/discussion_filter_note.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter_note.vue
@@ -1,28 +1,19 @@
<script>
-/* eslint-disable vue/no-v-html */
-import { GlButton, GlIcon } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
+import { GlButton, GlIcon, GlSprintf } from '@gitlab/ui';
+import { s__ } from '~/locale';
import notesEventHub from '../event_hub';
export default {
+ i18n: {
+ information: s__(
+ "Notes|You're only seeing %{boldStart}other activity%{boldEnd} in the feed. To add a comment, switch to one of the following options.",
+ ),
+ },
components: {
GlButton,
GlIcon,
- },
- computed: {
- timelineContent() {
- return sprintf(
- __(
- "You're only seeing %{startTag}other activity%{endTag} in the feed. To add a comment, switch to one of the following options.",
- ),
- {
- startTag: `<b>`,
- endTag: `</b>`,
- },
- false,
- );
- },
+ GlSprintf,
},
methods: {
selectFilter(value) {
@@ -33,17 +24,26 @@ export default {
</script>
<template>
- <li class="timeline-entry note note-wrapper discussion-filter-note js-discussion-filter-note">
+ <li
+ class="timeline-entry note note-wrapper discussion-filter-note js-discussion-filter-note"
+ data-qa-selector="discussion_filter_container"
+ >
<div class="timeline-icon d-none d-lg-flex">
<gl-icon name="comment" />
</div>
<div class="timeline-content">
- <div ref="timelineContent" v-html="timelineContent"></div>
+ <div data-testid="discussion-filter-timeline-content">
+ <gl-sprintf :message="$options.i18n.information">
+ <template #bold="{ content }">
+ <b>{{ content }}</b>
+ </template>
+ </gl-sprintf>
+ </div>
<div class="discussion-filter-actions mt-2">
- <gl-button ref="showAllActivity" variant="default" @click="selectFilter(0)">
+ <gl-button variant="default" @click="selectFilter(0)">
{{ __('Show all activity') }}
</gl-button>
- <gl-button ref="showComments" variant="default" @click="selectFilter(1)">
+ <gl-button variant="default" @click="selectFilter(1)">
{{ __('Show comments only') }}
</gl-button>
</div>
diff --git a/app/assets/javascripts/notes/components/discussion_notes.vue b/app/assets/javascripts/notes/components/discussion_notes.vue
index a1e887c47d0..8ac915c3c03 100644
--- a/app/assets/javascripts/notes/components/discussion_notes.vue
+++ b/app/assets/javascripts/notes/components/discussion_notes.vue
@@ -127,6 +127,7 @@ export default {
:help-page-path="helpPagePath"
:show-reply-button="userCanReply"
:discussion-root="true"
+ :discussion-resolve-path="discussion.resolve_path"
@handleDeleteNote="$emit('deleteNote')"
@startReplying="$emit('startReplying')"
>
@@ -171,6 +172,7 @@ export default {
:help-page-path="helpPagePath"
:line="diffLine"
:discussion-root="index === 0"
+ :discussion-resolve-path="discussion.resolve_path"
@handleDeleteNote="$emit('deleteNote')"
>
<slot v-if="index === 0" slot="avatar-badge" name="avatar-badge"></slot>
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index c2f40b2d21a..fc131f548b4 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -1,6 +1,6 @@
<script>
import { mapGetters } from 'vuex';
-import { GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon, GlButton, GlDropdownItem } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status';
import ReplyButton from './note_actions/reply_button.vue';
@@ -14,7 +14,8 @@ export default {
components: {
GlIcon,
ReplyButton,
- GlLoadingIcon,
+ GlButton,
+ GlDropdownItem,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -170,6 +171,15 @@ export default {
name: this.projectName,
});
},
+ resolveIcon() {
+ if (!this.isResolving) {
+ return this.isResolved ? 'check-circle-filled' : 'check-circle';
+ }
+ return null;
+ },
+ resolveVariant() {
+ return this.isResolved ? 'success' : 'default';
+ },
},
methods: {
onEdit() {
@@ -233,24 +243,23 @@ export default {
:title="displayContributorBadgeText"
>{{ __('Contributor') }}</span
>
- <div v-if="canResolve" class="note-actions-item">
- <button
+ <div v-if="canResolve" class="gl-ml-2">
+ <gl-button
ref="resolveButton"
v-gl-tooltip
+ size="small"
+ category="tertiary"
+ :variant="resolveVariant"
:class="{ 'is-disabled': !resolvable, 'is-active': isResolved }"
:title="resolveButtonTitle"
:aria-label="resolveButtonTitle"
- type="button"
+ :icon="resolveIcon"
+ :loading="isResolving"
class="line-resolve-btn note-action-button"
@click="onResolve"
- >
- <template v-if="!isResolving">
- <gl-icon :name="isResolved ? 'check-circle-filled' : 'check-circle'" />
- </template>
- <gl-loading-icon v-else inline />
- </button>
+ />
</div>
- <div v-if="canAwardEmoji" class="note-actions-item">
+ <div v-if="canAwardEmoji" class="gl-ml-3 gl-mr-2">
<a
v-gl-tooltip
:class="{ 'js-user-authored': isAuthoredByCurrentUser }"
@@ -261,7 +270,7 @@ export default {
>
<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" />
+ <gl-icon class="link-highlight award-control-icon-super-positive" name="smile" />
</a>
</div>
<reply-button
@@ -270,72 +279,57 @@ export default {
class="js-reply-button"
@startReplying="$emit('startReplying')"
/>
- <div v-if="canEdit" class="note-actions-item">
- <button
+ <div v-if="canEdit" class="gl-ml-2">
+ <gl-button
v-gl-tooltip
- type="button"
title="Edit comment"
+ icon="pencil"
+ size="small"
+ category="tertiary"
class="note-action-button js-note-edit btn btn-transparent"
data-qa-selector="note_edit_button"
@click="onEdit"
- >
- <gl-icon name="pencil" class="link-highlight" />
- </button>
+ />
</div>
- <div v-if="showDeleteAction" class="note-actions-item">
- <button
+ <div v-if="showDeleteAction" class="gl-ml-2">
+ <gl-button
v-gl-tooltip
- type="button"
title="Delete comment"
+ size="small"
+ icon="remove"
+ category="tertiary"
class="note-action-button js-note-delete btn btn-transparent"
@click="onDelete"
- >
- <gl-icon name="remove" class="link-highlight" />
- </button>
+ />
</div>
- <div v-else-if="shouldShowActionsDropdown" class="dropdown more-actions note-actions-item">
- <button
+ <div v-else-if="shouldShowActionsDropdown" class="dropdown more-actions gl-ml-2">
+ <gl-button
v-gl-tooltip
- type="button"
title="More actions"
+ icon="ellipsis_v"
+ size="small"
+ category="tertiary"
class="note-action-button more-actions-toggle btn btn-transparent"
data-toggle="dropdown"
@click="closeTooltip"
- >
- <gl-icon class="icon" name="ellipsis_v" />
- </button>
+ />
<ul class="dropdown-menu more-actions-dropdown dropdown-open-left">
- <li v-if="canReportAsAbuse">
- <a :href="reportAbusePath">{{ __('Report abuse to admin') }}</a>
- </li>
- <li v-if="noteUrl">
- <button
- :data-clipboard-text="noteUrl"
- type="button"
- class="btn-default btn-transparent js-btn-copy-note-link"
- >
- {{ __('Copy link') }}
- </button>
- </li>
- <li v-if="canAssign">
- <button
- class="btn-default btn-transparent"
- data-testid="assign-user"
- type="button"
- @click="assignUser"
- >
- {{ displayAssignUserText }}
- </button>
- </li>
- <li v-if="canEdit">
- <button
- class="btn btn-transparent js-note-delete js-note-delete"
- type="button"
- @click.prevent="onDelete"
- >
- <span class="text-danger">{{ __('Delete comment') }}</span>
- </button>
- </li>
+ <gl-dropdown-item v-if="canReportAsAbuse" :href="reportAbusePath">
+ {{ __('Report abuse to admin') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="noteUrl"
+ class="js-btn-copy-note-link"
+ :data-clipboard-text="noteUrl"
+ >
+ {{ __('Copy link') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="canAssign" data-testid="assign-user" @click="assignUser">
+ {{ displayAssignUserText }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="canEdit" class="js-note-delete" @click.prevent="onDelete">
+ <span class="text-danger">{{ __('Delete comment') }}</span>
+ </gl-dropdown-item>
</ul>
</div>
</div>
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 f19b7667fb2..acbbee13a6d 100644
--- a/app/assets/javascripts/notes/components/note_actions/reply_button.vue
+++ b/app/assets/javascripts/notes/components/note_actions/reply_button.vue
@@ -13,7 +13,7 @@ export default {
</script>
<template>
- <div class="note-actions-item">
+ <div class="gl-ml-2">
<gl-button
ref="button"
v-gl-tooltip
diff --git a/app/assets/javascripts/notes/components/note_attachment.vue b/app/assets/javascripts/notes/components/note_attachment.vue
index 72f9a4c7e74..b20facc4032 100644
--- a/app/assets/javascripts/notes/components/note_attachment.vue
+++ b/app/assets/javascripts/notes/components/note_attachment.vue
@@ -1,6 +1,11 @@
<script>
+import { GlIcon } from '@gitlab/ui';
+
export default {
name: 'NoteAttachment',
+ components: {
+ GlIcon,
+ },
props: {
attachment: {
type: Object,
@@ -29,7 +34,7 @@ export default {
target="_blank"
rel="noopener noreferrer"
>
- <i class="fa fa-paperclip" aria-hidden="true"> </i> {{ attachment.filename }}
+ <gl-icon name="paperclip" /> {{ attachment.filename }}
</a>
</div>
</div>
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 4b3f23e742d..43f17c5d65c 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -121,7 +121,13 @@ export default {
return this.withBatchComments && this.noteId === '' && !this.discussion.for_commit;
},
showResolveDiscussionToggle() {
- return (this.discussion?.id && this.discussion.resolvable) || this.isDraft;
+ if (!this.discussion?.notes) return false;
+
+ return (
+ this.discussion?.notes
+ .filter(n => n.resolvable)
+ .some(n => n.current_user?.can_resolve_discussion) || this.isDraft
+ );
},
noteHash() {
if (this.noteId) {
diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue
index a13a0dbbf30..cacf209ed81 100644
--- a/app/assets/javascripts/notes/components/note_header.vue
+++ b/app/assets/javascripts/notes/components/note_header.vue
@@ -1,7 +1,8 @@
<script>
/* eslint-disable vue/no-v-html */
import { mapActions } from 'vuex';
-import { GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
+import { GlIcon, GlLoadingIcon, GlTooltipDirective, GlSprintf } from '@gitlab/ui';
+import { isUserBusy } from '~/set_status_modal/utils';
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
@@ -11,6 +12,7 @@ export default {
import('ee_component/vue_shared/components/user_avatar/badges/gitlab_team_member_badge.vue'),
GlIcon,
GlLoadingIcon,
+ GlSprintf,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -65,8 +67,8 @@ export default {
};
},
computed: {
- toggleChevronClass() {
- return this.expanded ? 'fa-chevron-up' : 'fa-chevron-down';
+ toggleChevronIconName() {
+ return this.expanded ? 'chevron-up' : 'chevron-down';
},
noteTimestampLink() {
return this.noteId ? `#note_${this.noteId}` : undefined;
@@ -85,9 +87,16 @@ export default {
authorStatus() {
return this.author.status_tooltip_html;
},
+ authorIsBusy() {
+ const { status } = this.author;
+ return status?.availability && isUserBusy(status.availability);
+ },
emojiElement() {
return this.$refs?.authorStatus?.querySelector('gl-emoji');
},
+ authorName() {
+ return this.author.name;
+ },
},
mounted() {
this.emojiTitle = this.emojiElement ? this.emojiElement.getAttribute('title') : '';
@@ -133,7 +142,7 @@ export default {
type="button"
@click="handleToggle"
>
- <i ref="chevronIcon" :class="toggleChevronClass" class="fa" aria-hidden="true"></i>
+ <gl-icon ref="chevronIcon" :name="toggleChevronIconName" aria-hidden="true" />
{{ __('Toggle thread') }}
</button>
</div>
@@ -146,7 +155,12 @@ export default {
:data-username="author.username"
>
<slot name="note-header-info"></slot>
- <span class="note-header-author-name bold">{{ author.name }}</span>
+ <span class="note-header-author-name gl-font-weight-bold">
+ <gl-sprintf v-if="authorIsBusy" :message="s__('UserAvailability|%{author} (Busy)')">
+ <template #author>{{ authorName }}</template>
+ </gl-sprintf>
+ <template v-else>{{ authorName }}</template>
+ </span>
</a>
<span
v-if="authorStatus"
@@ -170,7 +184,9 @@ export default {
</template>
<span v-else>{{ __('A deleted user') }}</span>
<span class="note-headline-light note-headline-meta">
- <span class="system-note-message"> <slot></slot> </span>
+ <span class="system-note-message" data-qa-selector="system_note_content">
+ <slot></slot>
+ </span>
<template v-if="createdAt">
<span ref="actionText" class="system-note-separator">
<template v-if="actionText">{{ actionText }}</template>
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index 4f45fcb0062..9be53fe60f2 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -73,6 +73,11 @@ export default {
required: false,
default: false,
},
+ discussionResolvePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
return {
@@ -81,6 +86,7 @@ export default {
isRequesting: false,
isResolving: false,
commentLineStart: {},
+ resolveAsThread: this.glFeatures.removeResolveNote,
};
},
computed: {
@@ -133,6 +139,10 @@ export default {
return this.note.isDraft;
},
canResolve() {
+ if (this.glFeatures.removeResolveNote && !this.discussionRoot) return false;
+
+ if (this.glFeatures.removeResolveNote) return this.note.current_user.can_resolve_discussion;
+
return (
this.note.current_user.can_resolve ||
(this.note.isDraft && this.note.discussion_id !== null)
@@ -345,7 +355,8 @@ export default {
:class="classNameBindings"
:data-award-url="note.toggle_award_path"
:data-note-id="note.id"
- class="note note-wrapper qa-noteable-note-item"
+ class="note note-wrapper"
+ data-qa-selector="noteable_note_container"
>
<div
v-if="showMultiLineComment"
diff --git a/app/assets/javascripts/notes/components/toggle_replies_widget.vue b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
index f49fd2c3fa3..0628e1d8647 100644
--- a/app/assets/javascripts/notes/components/toggle_replies_widget.vue
+++ b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
@@ -1,11 +1,12 @@
<script>
import { uniqBy } from 'lodash';
-import { GlIcon } from '@gitlab/ui';
+import { GlButton, 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: {
+ GlButton,
GlIcon,
UserAvatarLink,
TimeAgoTooltip,
@@ -57,14 +58,15 @@ export default {
tooltip-placement="bottom"
/>
</div>
- <button
- class="btn btn-link js-replies-text"
+ <gl-button
+ class="js-replies-text"
+ category="tertiary"
+ variant="link"
data-qa-selector="expand_replies_button"
- type="button"
@click="toggle"
>
{{ replies.length }} {{ n__('reply', 'replies', replies.length) }}
- </button>
+ </gl-button>
{{ __('Last reply by') }}
<a :href="lastReply.author.path" class="btn btn-link author-link">
{{ lastReply.author.name }}
diff --git a/app/assets/javascripts/notes/mixins/resolvable.js b/app/assets/javascripts/notes/mixins/resolvable.js
index 087b5828cce..cef4475ed1d 100644
--- a/app/assets/javascripts/notes/mixins/resolvable.js
+++ b/app/assets/javascripts/notes/mixins/resolvable.js
@@ -1,12 +1,18 @@
import { deprecatedCreateFlash as Flash } from '~/flash';
import { __ } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
+ mixins: [glFeatureFlagsMixin()],
computed: {
discussionResolved() {
if (this.discussion) {
const { notes, resolved } = this.discussion;
+ if (this.glFeatures.removeResolveNote) {
+ return Boolean(resolved);
+ }
+
if (notes) {
// Decide resolved state using store. Only valid for discussions.
return notes.filter(note => !note.system).every(note => note.resolved);
@@ -38,7 +44,12 @@ export default {
this.isResolving = true;
const isResolved = this.discussionResolved || resolvedState;
const discussion = this.resolveAsThread;
- const endpoint = discussion ? this.discussion.resolve_path : `${this.note.path}/resolve`;
+ let endpoint =
+ discussion && this.discussion ? this.discussion.resolve_path : `${this.note.path}/resolve`;
+
+ if (this.glFeatures.removeResolveNote && this.discussionResolvePath) {
+ endpoint = this.discussionResolvePath;
+ }
return this.toggleResolveNote({ endpoint, isResolved, discussion })
.then(() => {
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index 37986c8a02d..2c60b5ee84a 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -167,7 +167,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) {
+ } else if (note.type === constants.DIFF_NOTE && !note.base_discussion) {
debouncedFetchDiscussions(state.currentlyFetchingDiscussions);
} else {
commit(types.ADD_NEW_NOTE, note);
diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js
index 6c11d53dba3..7cc619ec1c5 100644
--- a/app/assets/javascripts/notes/stores/mutations.js
+++ b/app/assets/javascripts/notes/stores/mutations.js
@@ -11,24 +11,30 @@ export default {
const isDiscussion = type === constants.DISCUSSION_NOTE || type === constants.DIFF_NOTE;
if (!exists) {
- const noteData = {
- expanded: true,
- id: discussion_id,
- individual_note: !isDiscussion,
- notes: [note],
- reply_id: discussion_id,
- };
-
- if (isDiscussion && isInMRPage()) {
- noteData.resolvable = note.resolvable;
- noteData.resolved = false;
- noteData.active = true;
- noteData.resolve_path = note.resolve_path;
- noteData.resolve_with_issue_path = note.resolve_with_issue_path;
- noteData.diff_discussion = false;
+ let discussion = data.discussion || note.base_discussion;
+
+ if (!discussion) {
+ discussion = {
+ expanded: true,
+ id: discussion_id,
+ individual_note: !isDiscussion,
+ reply_id: discussion_id,
+ };
+
+ if (isDiscussion && isInMRPage()) {
+ discussion.resolvable = note.resolvable;
+ discussion.resolved = false;
+ discussion.active = true;
+ discussion.resolve_path = note.resolve_path;
+ discussion.resolve_with_issue_path = note.resolve_with_issue_path;
+ discussion.diff_discussion = false;
+ }
}
- state.discussions.push(noteData);
+ note.base_discussion = undefined; // No point keeping a reference to this
+ discussion.notes = [note];
+
+ state.discussions.push(discussion);
}
},
diff --git a/app/assets/javascripts/notifications_form.js b/app/assets/javascripts/notifications_form.js
index 0d1b95f75f8..1b12fece23a 100644
--- a/app/assets/javascripts/notifications_form.js
+++ b/app/assets/javascripts/notifications_form.js
@@ -22,12 +22,8 @@ export default class NotificationsForm {
// eslint-disable-next-line class-methods-use-this
showCheckboxLoadingSpinner($parent) {
- $parent
- .addClass('is-loading')
- .find('.custom-notification-event-loading')
- .removeClass('fa-check')
- .addClass('spinner align-middle')
- .removeClass('is-done');
+ $parent.find('.is-loading').removeClass('gl-display-none');
+ $parent.find('.is-done').addClass('gl-display-none');
}
saveEvent($checkbox, $parent) {
@@ -39,14 +35,11 @@ export default class NotificationsForm {
.then(({ data }) => {
$checkbox.enable();
if (data.saved) {
- $parent
- .find('.custom-notification-event-loading')
- .toggleClass('spinner fa-check is-done align-middle');
+ $parent.find('.is-loading').addClass('gl-display-none');
+ $parent.find('.is-done').removeClass('gl-display-none');
+
setTimeout(() => {
- $parent
- .removeClass('is-loading')
- .find('.custom-notification-event-loading')
- .toggleClass('spinner fa-check is-done align-middle');
+ $parent.find('.is-done').addClass('gl-display-none');
}, 2000);
}
})
diff --git a/app/assets/javascripts/packages/details/components/package_title.vue b/app/assets/javascripts/packages/details/components/package_title.vue
index 2789be30818..6b7eeacb964 100644
--- a/app/assets/javascripts/packages/details/components/package_title.vue
+++ b/app/assets/javascripts/packages/details/components/package_title.vue
@@ -1,6 +1,8 @@
<script>
+/* eslint-disable vue/v-slot-style */
import { mapState, mapGetters } from 'vuex';
-import { GlIcon, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
+import { GlIcon, GlSprintf, GlTooltipDirective, GlBadge } from '@gitlab/ui';
+import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
import PackageTags from '../../shared/components/package_tags.vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import timeagoMixin from '~/vue_shared/mixins/timeago';
@@ -16,11 +18,20 @@ export default {
GlSprintf,
PackageTags,
MetadataItem,
+ GlBadge,
},
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [timeagoMixin],
+ i18n: {
+ packageInfo: __('v%{version} published %{timeAgo}'),
+ },
+ data() {
+ return {
+ isDesktop: true,
+ };
+ },
computed: {
...mapState(['packageEntity', 'packageFiles']),
...mapGetters(['packageTypeDisplay', 'packagePipeline', 'packageIcon']),
@@ -31,8 +42,13 @@ export default {
return numberToHumanSize(this.packageFiles.reduce((acc, p) => acc + p.size, 0));
},
},
- i18n: {
- packageInfo: __('v%{version} published %{timeAgo}'),
+ mounted() {
+ this.isDesktop = GlBreakpointInstance.isDesktop();
+ },
+ methods: {
+ dynamicSlotName(index) {
+ return `metadata-tag${index}`;
+ },
},
};
</script>
@@ -75,10 +91,21 @@ export default {
<metadata-item data-testid="package-ref" icon="branch" :text="packagePipeline.ref" />
</template>
- <template v-if="hasTagsToDisplay" #metadata-tags>
+ <template v-if="isDesktop && hasTagsToDisplay" #metadata-tags>
<package-tags :tag-display-limit="2" :tags="packageEntity.tags" hide-label />
</template>
+ <!-- we need to duplicate the package tags on mobile to ensure proper styling inside the flex wrap -->
+ <template
+ v-for="(tag, index) in packageEntity.tags"
+ v-else-if="hasTagsToDisplay"
+ v-slot:[dynamicSlotName(index)]
+ >
+ <gl-badge :key="index" class="gl-my-1" data-testid="tag-badge" variant="info" size="sm">
+ {{ tag.name }}
+ </gl-badge>
+ </template>
+
<template #right-actions>
<slot name="delete-button"></slot>
</template>
diff --git a/app/assets/javascripts/pages/admin/admin.js b/app/assets/javascripts/pages/admin/admin.js
index 88967d82b2f..038bbe392ba 100644
--- a/app/assets/javascripts/pages/admin/admin.js
+++ b/app/assets/javascripts/pages/admin/admin.js
@@ -1,13 +1,13 @@
import $ from 'jquery';
import { refreshCurrentPage } from '../../lib/utils/url_utility';
-function showBlacklistType() {
- if ($('input[name="blacklist_type"]:checked').val() === 'file') {
- $('.blacklist-file').show();
- $('.blacklist-raw').hide();
+function showDenylistType() {
+ if ($('input[name="denylist_type"]:checked').val() === 'file') {
+ $('.js-denylist-file').show();
+ $('.js-denylist-raw').hide();
} else {
- $('.blacklist-file').hide();
- $('.blacklist-raw').show();
+ $('.js-denylist-file').hide();
+ $('.js-denylist-raw').show();
}
}
@@ -60,6 +60,6 @@ export default function adminInit() {
$('li.project_member, li.group_member').on('ajax:success', refreshCurrentPage);
- $("input[name='blacklist_type']").on('click', showBlacklistType);
- showBlacklistType();
+ $("input[name='denylist_type']").on('click', showDenylistType);
+ showDenylistType();
}
diff --git a/app/assets/javascripts/pages/admin/application_settings/general/index.js b/app/assets/javascripts/pages/admin/application_settings/general/index.js
index 8183e81fb02..af1595398a8 100644
--- a/app/assets/javascripts/pages/admin/application_settings/general/index.js
+++ b/app/assets/javascripts/pages/admin/application_settings/general/index.js
@@ -1,3 +1,21 @@
+import Vue from 'vue';
import initUserInternalRegexPlaceholder from '../account_and_limits';
+import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue';
-document.addEventListener('DOMContentLoaded', initUserInternalRegexPlaceholder());
+document.addEventListener('DOMContentLoaded', () => {
+ initUserInternalRegexPlaceholder();
+
+ const gitpodSettingEl = document.querySelector('#js-gitpod-settings-help-text');
+ if (!gitpodSettingEl) {
+ return;
+ }
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: gitpodSettingEl,
+ name: 'GitpodSettings',
+ components: {
+ IntegrationHelpText,
+ },
+ });
+});
diff --git a/app/assets/javascripts/pages/admin/dev_ops_report/index.js b/app/assets/javascripts/pages/admin/dev_ops_report/index.js
index 643497003ba..220fc049562 100644
--- a/app/assets/javascripts/pages/admin/dev_ops_report/index.js
+++ b/app/assets/javascripts/pages/admin/dev_ops_report/index.js
@@ -1,27 +1,5 @@
-import Vue from 'vue';
-import UserCallout from '~/user_callout';
-import UsagePingDisabled from '~/admin/dev_ops_report/components/usage_ping_disabled.vue';
+import initDevopAdoption from 'ee_else_ce/admin/dev_ops_report/devops_adoption';
+import initDevOpsScoreEmptyState from '~/admin/dev_ops_report/devops_score_empty_state';
-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);
- },
- });
-});
+initDevOpsScoreEmptyState();
+initDevopAdoption();
diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
index 120512bf15e..4b6f52c09be 100644
--- a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
+++ b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
@@ -1,13 +1,13 @@
<script>
+import { GlModal } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { redirectTo } from '~/lib/utils/url_utility';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
export default {
components: {
- GlModal: DeprecatedModal2,
+ GlModal,
},
props: {
url: {
@@ -36,17 +36,24 @@ export default {
});
},
},
+ primaryAction: {
+ text: s__('AdminArea|Stop jobs'),
+ attributes: [{ variant: 'danger' }],
+ },
+ cancelAction: {
+ text: __('Cancel'),
+ },
};
</script>
<template>
<gl-modal
- id="stop-jobs-modal"
- :header-title-text="s__('AdminArea|Stop all jobs?')"
- :footer-primary-button-text="s__('AdminArea|Stop jobs')"
- footer-primary-button-variant="danger"
- @submit="onSubmit"
+ modal-id="stop-jobs-modal"
+ :action-primary="$options.primaryAction"
+ :action-cancel="$options.cancelAction"
+ @primary="onSubmit"
>
+ <template #modal-title>{{ s__('AdminArea|Stop all jobs?') }}</template>
{{ text }}
</gl-modal>
</template>
diff --git a/app/assets/javascripts/pages/admin/jobs/index/index.js b/app/assets/javascripts/pages/admin/jobs/index/index.js
index 5a4f8c6e745..4df210debb5 100644
--- a/app/assets/javascripts/pages/admin/jobs/index/index.js
+++ b/app/assets/javascripts/pages/admin/jobs/index/index.js
@@ -5,19 +5,24 @@ import stopJobsModal from './components/stop_jobs_modal.vue';
Vue.use(Translate);
document.addEventListener('DOMContentLoaded', () => {
- const stopJobsButton = document.getElementById('stop-jobs-button');
+ const buttonId = 'js-stop-jobs-button';
+ const modalId = 'stop-jobs-modal';
+ const stopJobsButton = document.getElementById(buttonId);
if (stopJobsButton) {
// eslint-disable-next-line no-new
new Vue({
- el: '#stop-jobs-modal',
+ el: `#js-${modalId}`,
components: {
stopJobsModal,
},
mounted() {
stopJobsButton.classList.remove('disabled');
+ stopJobsButton.addEventListener('click', () => {
+ this.$root.$emit('bv::show::modal', modalId, `#${buttonId}`);
+ });
},
render(createElement) {
- return createElement('stop-jobs-modal', {
+ return createElement(modalId, {
props: {
url: stopJobsButton.dataset.url,
},
diff --git a/app/assets/javascripts/pages/admin/runners/index.js b/app/assets/javascripts/pages/admin/runners/index.js
index e60c6133c7c..104b7eeaf96 100644
--- a/app/assets/javascripts/pages/admin/runners/index.js
+++ b/app/assets/javascripts/pages/admin/runners/index.js
@@ -1,11 +1,12 @@
import initFilteredSearch from '~/pages/search/init_filtered_search';
import AdminRunnersFilteredSearchTokenKeys from '~/filtered_search/admin_runners_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
+import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
-document.addEventListener('DOMContentLoaded', () => {
- initFilteredSearch({
- page: FILTERED_SEARCH.ADMIN_RUNNERS,
- filteredSearchTokenKeys: AdminRunnersFilteredSearchTokenKeys,
- useDefaultState: true,
- });
+initFilteredSearch({
+ page: FILTERED_SEARCH.ADMIN_RUNNERS,
+ filteredSearchTokenKeys: AdminRunnersFilteredSearchTokenKeys,
+ useDefaultState: true,
});
+
+initInstallRunner();
diff --git a/app/assets/javascripts/pages/admin/users/index.js b/app/assets/javascripts/pages/admin/users/index.js
index 86c4b4f4f48..5f3cdc0bfc6 100644
--- a/app/assets/javascripts/pages/admin/users/index.js
+++ b/app/assets/javascripts/pages/admin/users/index.js
@@ -5,12 +5,12 @@ import ModalManager from './components/user_modal_manager.vue';
import DeleteUserModal from './components/delete_user_modal.vue';
import UserOperationConfirmationModal from './components/user_operation_confirmation_modal.vue';
import csrf from '~/lib/utils/csrf';
+import initConfirmModal from '~/confirm_modal';
const MODAL_TEXTS_CONTAINER_SELECTOR = '#modal-texts';
const MODAL_MANAGER_SELECTOR = '#user-modal';
const ACTION_MODALS = {
deactivate: UserOperationConfirmationModal,
- block: UserOperationConfirmationModal,
delete: DeleteUserModal,
'delete-with-contributions': DeleteUserModal,
};
@@ -62,4 +62,6 @@ document.addEventListener('DOMContentLoaded', () => {
});
},
});
+
+ initConfirmModal();
});
diff --git a/app/assets/javascripts/pages/groups/boards/index.js b/app/assets/javascripts/pages/groups/boards/index.js
index 79c3be771d0..922f39627c9 100644
--- a/app/assets/javascripts/pages/groups/boards/index.js
+++ b/app/assets/javascripts/pages/groups/boards/index.js
@@ -2,8 +2,6 @@ import UsersSelect from '~/users_select';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import initBoards from '~/boards';
-document.addEventListener('DOMContentLoaded', () => {
- new UsersSelect(); // eslint-disable-line no-new
- new ShortcutsNavigation(); // eslint-disable-line no-new
- initBoards();
-});
+new UsersSelect(); // eslint-disable-line no-new
+new ShortcutsNavigation(); // eslint-disable-line no-new
+initBoards();
diff --git a/app/assets/javascripts/pages/groups/clusters/destroy/index.js b/app/assets/javascripts/pages/groups/clusters/destroy/index.js
index 8001d2dd1da..487e7a14a16 100644
--- a/app/assets/javascripts/pages/groups/clusters/destroy/index.js
+++ b/app/assets/javascripts/pages/groups/clusters/destroy/index.js
@@ -1,5 +1,3 @@
import ClustersBundle from '~/clusters/clusters_bundle';
-document.addEventListener('DOMContentLoaded', () => {
- new ClustersBundle(); // eslint-disable-line no-new
-});
+new ClustersBundle(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/groups/clusters/edit/index.js b/app/assets/javascripts/pages/groups/clusters/edit/index.js
index 8001d2dd1da..487e7a14a16 100644
--- a/app/assets/javascripts/pages/groups/clusters/edit/index.js
+++ b/app/assets/javascripts/pages/groups/clusters/edit/index.js
@@ -1,5 +1,3 @@
import ClustersBundle from '~/clusters/clusters_bundle';
-document.addEventListener('DOMContentLoaded', () => {
- new ClustersBundle(); // eslint-disable-line no-new
-});
+new ClustersBundle(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/groups/clusters/index.js b/app/assets/javascripts/pages/groups/clusters/index.js
index 9f466e0d60a..3b92c244346 100644
--- a/app/assets/javascripts/pages/groups/clusters/index.js
+++ b/app/assets/javascripts/pages/groups/clusters/index.js
@@ -1,7 +1,5 @@
import initCreateCluster from '~/create_cluster/init_create_cluster';
import initIntegrationForm from '~/clusters/forms/show/index';
-document.addEventListener('DOMContentLoaded', () => {
- initCreateCluster(document, gon);
- initIntegrationForm();
-});
+initCreateCluster(document, gon);
+initIntegrationForm();
diff --git a/app/assets/javascripts/pages/groups/clusters/index/index.js b/app/assets/javascripts/pages/groups/clusters/index/index.js
index 744be65bfbe..3b71517f017 100644
--- a/app/assets/javascripts/pages/groups/clusters/index/index.js
+++ b/app/assets/javascripts/pages/groups/clusters/index/index.js
@@ -1,8 +1,6 @@
import PersistentUserCallout from '~/persistent_user_callout';
import initClustersListApp from '~/clusters_list';
-document.addEventListener('DOMContentLoaded', () => {
- const callout = document.querySelector('.gcp-signup-offer');
- PersistentUserCallout.factory(callout);
- initClustersListApp();
-});
+const callout = document.querySelector('.gcp-signup-offer');
+PersistentUserCallout.factory(callout);
+initClustersListApp();
diff --git a/app/assets/javascripts/pages/groups/clusters/new/index.js b/app/assets/javascripts/pages/groups/clusters/new/index.js
index 876bab0b339..de9ded87ef3 100644
--- a/app/assets/javascripts/pages/groups/clusters/new/index.js
+++ b/app/assets/javascripts/pages/groups/clusters/new/index.js
@@ -1,5 +1,3 @@
import initNewCluster from '~/clusters/new_cluster';
-document.addEventListener('DOMContentLoaded', () => {
- initNewCluster();
-});
+initNewCluster();
diff --git a/app/assets/javascripts/pages/groups/clusters/show/index.js b/app/assets/javascripts/pages/groups/clusters/show/index.js
index ccf631b2c53..5d202a8824f 100644
--- a/app/assets/javascripts/pages/groups/clusters/show/index.js
+++ b/app/assets/javascripts/pages/groups/clusters/show/index.js
@@ -1,7 +1,5 @@
import ClustersBundle from '~/clusters/clusters_bundle';
import initClusterHealth from '~/pages/projects/clusters/show/cluster_health';
-document.addEventListener('DOMContentLoaded', () => {
- new ClustersBundle(); // eslint-disable-line no-new
- initClusterHealth();
-});
+new ClustersBundle(); // eslint-disable-line no-new
+initClusterHealth();
diff --git a/app/assets/javascripts/pages/groups/dependency_proxies/index.js b/app/assets/javascripts/pages/groups/dependency_proxies/index.js
new file mode 100644
index 00000000000..77c885d3858
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/dependency_proxies/index.js
@@ -0,0 +1,13 @@
+import $ from 'jquery';
+import initDependencyProxy from '~/dependency_proxy';
+
+initDependencyProxy();
+
+const form = document.querySelector('form.edit_dependency_proxy_group_setting');
+const toggleInput = $('input.js-project-feature-toggle-input');
+
+if (form && toggleInput) {
+ toggleInput.on('trigger-change', () => {
+ form.submit();
+ });
+}
diff --git a/app/assets/javascripts/pages/groups/details/index.js b/app/assets/javascripts/pages/groups/details/index.js
index 3bcaa0f0232..0417134f2a7 100644
--- a/app/assets/javascripts/pages/groups/details/index.js
+++ b/app/assets/javascripts/pages/groups/details/index.js
@@ -1,5 +1,3 @@
import initGroupDetails from '../shared/group_details';
-document.addEventListener('DOMContentLoaded', () => {
- initGroupDetails('details');
-});
+initGroupDetails('details');
diff --git a/app/assets/javascripts/pages/groups/group_members/index.js b/app/assets/javascripts/pages/groups/group_members/index.js
index dc647f5d3cb..009a3eee526 100644
--- a/app/assets/javascripts/pages/groups/group_members/index.js
+++ b/app/assets/javascripts/pages/groups/group_members/index.js
@@ -21,35 +21,36 @@ function mountRemoveMemberModal() {
});
}
-document.addEventListener('DOMContentLoaded', () => {
- groupsSelect();
- memberExpirationDate();
- memberExpirationDate('.js-access-expiration-date-groups');
- mountRemoveMemberModal();
+const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions'];
+initGroupMembersApp(
+ document.querySelector('.js-group-members-list'),
+ SHARED_FIELDS.concat(['source', 'granted']),
+ { tr: { 'data-qa-selector': 'member_row' } },
+ memberRequestFormatter,
+);
+initGroupMembersApp(
+ document.querySelector('.js-group-linked-list'),
+ SHARED_FIELDS.concat('granted'),
+ { table: { 'data-qa-selector': 'groups_list' }, tr: { 'data-qa-selector': 'group_row' } },
+ groupLinkRequestFormatter,
+);
+initGroupMembersApp(
+ document.querySelector('.js-group-invited-members-list'),
+ SHARED_FIELDS.concat('invited'),
+ {},
+ memberRequestFormatter,
+);
+initGroupMembersApp(
+ document.querySelector('.js-group-access-requests-list'),
+ SHARED_FIELDS.concat('requested'),
+ {},
+ memberRequestFormatter,
+);
- const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions'];
+groupsSelect();
+memberExpirationDate();
+memberExpirationDate('.js-access-expiration-date-groups');
+mountRemoveMemberModal();
- initGroupMembersApp(
- document.querySelector('.js-group-members-list'),
- SHARED_FIELDS.concat(['source', 'granted']),
- memberRequestFormatter,
- );
- initGroupMembersApp(
- document.querySelector('.js-group-linked-list'),
- SHARED_FIELDS.concat('granted'),
- groupLinkRequestFormatter,
- );
- initGroupMembersApp(
- document.querySelector('.js-group-invited-members-list'),
- SHARED_FIELDS.concat('invited'),
- memberRequestFormatter,
- );
- initGroupMembersApp(
- document.querySelector('.js-group-access-requests-list'),
- SHARED_FIELDS.concat('requested'),
- memberRequestFormatter,
- );
-
- new Members(); // eslint-disable-line no-new
- new UsersSelect(); // eslint-disable-line no-new
-});
+new Members(); // eslint-disable-line no-new
+new UsersSelect(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/groups/labels/edit/index.js b/app/assets/javascripts/pages/groups/labels/edit/index.js
index 83d6ac9fd14..2e8308fe084 100644
--- a/app/assets/javascripts/pages/groups/labels/edit/index.js
+++ b/app/assets/javascripts/pages/groups/labels/edit/index.js
@@ -1,3 +1,4 @@
import Labels from 'ee_else_ce/labels';
-document.addEventListener('DOMContentLoaded', () => new Labels());
+// eslint-disable-next-line no-new
+new Labels();
diff --git a/app/assets/javascripts/pages/groups/labels/index/index.js b/app/assets/javascripts/pages/groups/labels/index/index.js
index 6e45de2a724..87d522d7654 100644
--- a/app/assets/javascripts/pages/groups/labels/index/index.js
+++ b/app/assets/javascripts/pages/groups/labels/index/index.js
@@ -1,3 +1,3 @@
import initLabels from '~/init_labels';
-document.addEventListener('DOMContentLoaded', initLabels);
+initLabels();
diff --git a/app/assets/javascripts/pages/groups/labels/new/index.js b/app/assets/javascripts/pages/groups/labels/new/index.js
index 83d6ac9fd14..2e8308fe084 100644
--- a/app/assets/javascripts/pages/groups/labels/new/index.js
+++ b/app/assets/javascripts/pages/groups/labels/new/index.js
@@ -1,3 +1,4 @@
import Labels from 'ee_else_ce/labels';
-document.addEventListener('DOMContentLoaded', () => new Labels());
+// eslint-disable-next-line no-new
+new Labels();
diff --git a/app/assets/javascripts/pages/groups/merge_requests/index.js b/app/assets/javascripts/pages/groups/merge_requests/index.js
index 71c67ac74ed..2832cbed5ac 100644
--- a/app/assets/javascripts/pages/groups/merge_requests/index.js
+++ b/app/assets/javascripts/pages/groups/merge_requests/index.js
@@ -7,15 +7,13 @@ import { FILTERED_SEARCH } from '~/pages/constants';
const ISSUABLE_BULK_UPDATE_PREFIX = 'merge_request_';
-document.addEventListener('DOMContentLoaded', () => {
- addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
- issuableInitBulkUpdateSidebar.init(ISSUABLE_BULK_UPDATE_PREFIX);
+addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
+issuableInitBulkUpdateSidebar.init(ISSUABLE_BULK_UPDATE_PREFIX);
- initFilteredSearch({
- page: FILTERED_SEARCH.MERGE_REQUESTS,
- isGroupDecendent: true,
- useDefaultState: true,
- filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
- });
- projectSelect();
+initFilteredSearch({
+ page: FILTERED_SEARCH.MERGE_REQUESTS,
+ isGroupDecendent: true,
+ useDefaultState: true,
+ filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
});
+projectSelect();
diff --git a/app/assets/javascripts/pages/groups/milestones/edit/index.js b/app/assets/javascripts/pages/groups/milestones/edit/index.js
index ddd10fe5062..af0264c7992 100644
--- a/app/assets/javascripts/pages/groups/milestones/edit/index.js
+++ b/app/assets/javascripts/pages/groups/milestones/edit/index.js
@@ -1,3 +1,3 @@
import initForm from '../../../../shared/milestones/form';
-document.addEventListener('DOMContentLoaded', () => initForm(false));
+initForm(false);
diff --git a/app/assets/javascripts/pages/groups/milestones/new/index.js b/app/assets/javascripts/pages/groups/milestones/new/index.js
index ddd10fe5062..af0264c7992 100644
--- a/app/assets/javascripts/pages/groups/milestones/new/index.js
+++ b/app/assets/javascripts/pages/groups/milestones/new/index.js
@@ -1,3 +1,3 @@
import initForm from '../../../../shared/milestones/form';
-document.addEventListener('DOMContentLoaded', () => initForm(false));
+initForm(false);
diff --git a/app/assets/javascripts/pages/groups/new/index.js b/app/assets/javascripts/pages/groups/new/index.js
index 640e64b5d3e..7021473b380 100644
--- a/app/assets/javascripts/pages/groups/new/index.js
+++ b/app/assets/javascripts/pages/groups/new/index.js
@@ -4,13 +4,11 @@ import Group from '~/group';
import GroupPathValidator from './group_path_validator';
import initFilePickers from '~/file_pickers';
-document.addEventListener('DOMContentLoaded', () => {
- const parentId = $('#group_parent_id');
- if (!parentId.val()) {
- new GroupPathValidator(); // eslint-disable-line no-new
- }
- BindInOut.initAll();
- initFilePickers();
+const parentId = $('#group_parent_id');
+if (!parentId.val()) {
+ new GroupPathValidator(); // eslint-disable-line no-new
+}
+BindInOut.initAll();
+initFilePickers();
- return new Group();
-});
+new Group(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/groups/packages/index/index.js b/app/assets/javascripts/pages/groups/packages/index/index.js
index 4836900aa28..1c4a10fd653 100644
--- a/app/assets/javascripts/pages/groups/packages/index/index.js
+++ b/app/assets/javascripts/pages/groups/packages/index/index.js
@@ -1,7 +1,5 @@
import initPackageList from '~/packages/list/packages_list_app_bundle';
-document.addEventListener('DOMContentLoaded', () => {
- if (document.getElementById('js-vue-packages-list')) {
- initPackageList();
- }
-});
+if (document.getElementById('js-vue-packages-list')) {
+ initPackageList();
+}
diff --git a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
index 67eb09da5e0..3456048d718 100644
--- a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
@@ -1,35 +1,21 @@
import initSettingsPanels from '~/settings_panels';
-import AjaxVariableList from '~/ci_variable_list/ajax_variable_list';
import initVariableList from '~/ci_variable_list';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import GroupRunnersFilteredSearchTokenKeys from '~/filtered_search/group_runners_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
import initSharedRunnersForm from '~/group_settings/mount_shared_runners';
+import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
-document.addEventListener('DOMContentLoaded', () => {
- // Initialize expandable settings panels
- initSettingsPanels();
+// Initialize expandable settings panels
+initSettingsPanels();
- initFilteredSearch({
- page: FILTERED_SEARCH.ADMIN_RUNNERS,
- filteredSearchTokenKeys: GroupRunnersFilteredSearchTokenKeys,
- anchor: FILTERED_SEARCH.GROUP_RUNNERS_ANCHOR,
- useDefaultState: false,
- });
-
- if (gon.features.newVariablesUi) {
- initVariableList();
- } else {
- const variableListEl = document.querySelector('.js-ci-variable-list-section');
- // eslint-disable-next-line no-new
- new AjaxVariableList({
- container: variableListEl,
- saveButton: variableListEl.querySelector('.js-ci-variables-save-button'),
- errorBox: variableListEl.querySelector('.js-ci-variable-error-box'),
- saveEndpoint: variableListEl.dataset.saveEndpoint,
- maskableRegex: variableListEl.dataset.maskableRegex,
- });
- }
-
- initSharedRunnersForm();
+initFilteredSearch({
+ page: FILTERED_SEARCH.ADMIN_RUNNERS,
+ filteredSearchTokenKeys: GroupRunnersFilteredSearchTokenKeys,
+ anchor: FILTERED_SEARCH.GROUP_RUNNERS_ANCHOR,
+ useDefaultState: false,
});
+
+initSharedRunnersForm();
+initVariableList();
+initInstallRunner();
diff --git a/app/assets/javascripts/pages/groups/shared/group_details.js b/app/assets/javascripts/pages/groups/shared/group_details.js
index 8546b1f759f..8d956c694c0 100644
--- a/app/assets/javascripts/pages/groups/shared/group_details.js
+++ b/app/assets/javascripts/pages/groups/shared/group_details.js
@@ -2,7 +2,6 @@
import { getPagePath, getDashPath } from '~/lib/utils/common_utils';
import { ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED } from '~/groups/constants';
-import NewGroupChild from '~/groups/new_group_child';
import notificationsDropdown from '~/notifications_dropdown';
import NotificationsForm from '~/notifications_form';
import ProjectsList from '~/projects_list';
@@ -11,7 +10,6 @@ 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');
const loadableActions = [ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED];
const dashPath = getDashPath();
let action = loadableActions.includes(dashPath) ? dashPath : getPagePath(1);
@@ -25,8 +23,5 @@ export default function initGroupDetails(actionName = 'show') {
notificationsDropdown();
new ProjectsList();
- if (newGroupChildWrapper) {
- new NewGroupChild(newGroupChildWrapper);
- }
initInviteMembersBanner();
}
diff --git a/app/assets/javascripts/pages/profiles/preferences/show/index.js b/app/assets/javascripts/pages/profiles/preferences/show/index.js
new file mode 100644
index 00000000000..d489ed80f46
--- /dev/null
+++ b/app/assets/javascripts/pages/profiles/preferences/show/index.js
@@ -0,0 +1,3 @@
+import initProfilePreferences from '~/profile/preferences/profile_preferences_bundle';
+
+document.addEventListener('DOMContentLoaded', initProfilePreferences);
diff --git a/app/assets/javascripts/pages/projects/alert_management/details/index.js b/app/assets/javascripts/pages/projects/alert_management/details/index.js
index 0124795e1af..a20f6713c9d 100644
--- a/app/assets/javascripts/pages/projects/alert_management/details/index.js
+++ b/app/assets/javascripts/pages/projects/alert_management/details/index.js
@@ -1,5 +1,3 @@
import AlertDetails from '~/alert_management/details';
-document.addEventListener('DOMContentLoaded', () => {
- AlertDetails('#js-alert_details');
-});
+AlertDetails('#js-alert_details');
diff --git a/app/assets/javascripts/pages/projects/alert_management/index/index.js b/app/assets/javascripts/pages/projects/alert_management/index/index.js
index 1e98bcfd2eb..ed352f0ad7a 100644
--- a/app/assets/javascripts/pages/projects/alert_management/index/index.js
+++ b/app/assets/javascripts/pages/projects/alert_management/index/index.js
@@ -1,5 +1,3 @@
import AlertManagementList from '~/alert_management/list';
-document.addEventListener('DOMContentLoaded', () => {
- AlertManagementList();
-});
+AlertManagementList();
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js
index f2e8cb38ef5..1879e263ce7 100644
--- a/app/assets/javascripts/pages/projects/blob/show/index.js
+++ b/app/assets/javascripts/pages/projects/blob/show/index.js
@@ -7,7 +7,6 @@ import initWebIdeLink from '~/pages/projects/shared/web_ide_link';
import '~/sourcegraph/load';
import PipelineTourSuccessModal from '~/blob/pipeline_tour_success_modal.vue';
import { parseBoolean } from '~/lib/utils/common_utils';
-import { isExperimentEnabled } from '~/lib/utils/experimentation';
const createGitlabCiYmlVisualization = (containerId = '#js-blob-toggle-graph-preview') => {
const el = document.querySelector(containerId);
@@ -74,7 +73,7 @@ document.addEventListener('DOMContentLoaded', () => {
);
}
- if (isExperimentEnabled('suggestPipeline')) {
+ if (gon.features?.suggestPipeline) {
const successPipelineEl = document.querySelector('.js-success-pipeline-modal');
if (successPipelineEl) {
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
deleted file mode 100644
index df635522e94..00000000000
--- a/app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import EditorLite from '~/editor/editor_lite';
-
-export default class CILintEditor {
- constructor() {
- this.clearYml = document.querySelector('.clear-yml');
- this.clearYml.addEventListener('click', this.clear.bind(this));
-
- return this.initEditorLite();
- }
-
- clear() {
- this.editor.setValue('');
- }
-
- initEditorLite() {
- 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();
- });
- }
-}
diff --git a/app/assets/javascripts/pages/projects/ci/lints/new/index.js b/app/assets/javascripts/pages/projects/ci/lints/new/index.js
deleted file mode 100644
index 957801320c9..00000000000
--- a/app/assets/javascripts/pages/projects/ci/lints/new/index.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import createFlash from '~/flash';
-import { __ } from '~/locale';
-
-const ERROR = __('An error occurred while rendering the linter');
-
-document.addEventListener('DOMContentLoaded', () => {
- if (gon?.features?.ciLintVue) {
- import(/* webpackChunkName: 'ciLintIndex' */ '~/ci_lint/index')
- .then(module => module.default())
- .catch(() => createFlash(ERROR));
- } else {
- import(/* webpackChunkName: 'ciLintEditor' */ '../ci_lint_editor')
- // eslint-disable-next-line new-cap
- .then(module => new module.default())
- .catch(() => createFlash(ERROR));
- }
-});
diff --git a/app/assets/javascripts/pages/projects/ci/lints/show/index.js b/app/assets/javascripts/pages/projects/ci/lints/show/index.js
index 957801320c9..6e1cdf557b5 100644
--- a/app/assets/javascripts/pages/projects/ci/lints/show/index.js
+++ b/app/assets/javascripts/pages/projects/ci/lints/show/index.js
@@ -1,17 +1,3 @@
-import createFlash from '~/flash';
-import { __ } from '~/locale';
+import initCiLint from '~/ci_lint';
-const ERROR = __('An error occurred while rendering the linter');
-
-document.addEventListener('DOMContentLoaded', () => {
- if (gon?.features?.ciLintVue) {
- import(/* webpackChunkName: 'ciLintIndex' */ '~/ci_lint/index')
- .then(module => module.default())
- .catch(() => createFlash(ERROR));
- } else {
- import(/* webpackChunkName: 'ciLintEditor' */ '../ci_lint_editor')
- // eslint-disable-next-line new-cap
- .then(module => new module.default())
- .catch(() => createFlash(ERROR));
- }
-});
+initCiLint();
diff --git a/app/assets/javascripts/pages/projects/ci/pipeline_editor/show/index.js b/app/assets/javascripts/pages/projects/ci/pipeline_editor/show/index.js
new file mode 100644
index 00000000000..67d32648ce8
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/ci/pipeline_editor/show/index.js
@@ -0,0 +1,3 @@
+import { initPipelineEditor } from '~/pipeline_editor';
+
+initPipelineEditor();
diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js
index 32fb35f97e3..e0bd49bf6ef 100644
--- a/app/assets/javascripts/pages/projects/commit/show/index.js
+++ b/app/assets/javascripts/pages/projects/commit/show/index.js
@@ -40,7 +40,7 @@ document.addEventListener('DOMContentLoaded', () => {
new Diff();
})
.catch(() => {
- flash(__('An error occurred while retrieving diff files'));
+ flash({ message: __('An error occurred while retrieving diff files') });
});
} else {
new Diff();
diff --git a/app/assets/javascripts/pages/projects/error_tracking/details/index.js b/app/assets/javascripts/pages/projects/error_tracking/details/index.js
index 25d1c744e1b..a750b3bac87 100644
--- a/app/assets/javascripts/pages/projects/error_tracking/details/index.js
+++ b/app/assets/javascripts/pages/projects/error_tracking/details/index.js
@@ -1,5 +1,3 @@
import ErrorTrackingDetails from '~/error_tracking/details';
-document.addEventListener('DOMContentLoaded', () => {
- ErrorTrackingDetails();
-});
+ErrorTrackingDetails();
diff --git a/app/assets/javascripts/pages/projects/error_tracking/index/index.js b/app/assets/javascripts/pages/projects/error_tracking/index/index.js
index ead81cd5d2d..fda0a35de9c 100644
--- a/app/assets/javascripts/pages/projects/error_tracking/index/index.js
+++ b/app/assets/javascripts/pages/projects/error_tracking/index/index.js
@@ -1,5 +1,3 @@
import ErrorTrackingList from '~/error_tracking/list';
-document.addEventListener('DOMContentLoaded', () => {
- ErrorTrackingList();
-});
+ErrorTrackingList();
diff --git a/app/assets/javascripts/pages/projects/graphs/charts/index.js b/app/assets/javascripts/pages/projects/graphs/charts/index.js
index 74abd1f67a5..6cf36463bda 100644
--- a/app/assets/javascripts/pages/projects/graphs/charts/index.js
+++ b/app/assets/javascripts/pages/projects/graphs/charts/index.js
@@ -5,6 +5,8 @@ import { __ } from '~/locale';
import CodeCoverage from '../components/code_coverage.vue';
import SeriesDataMixin from './series_data_mixin';
+const seriesDataToBarData = raw => Object.entries(raw).map(([name, data]) => ({ name, data }));
+
document.addEventListener('DOMContentLoaded', () => {
waitForCSSLoaded(() => {
const languagesContainer = document.getElementById('js-languages-chart');
@@ -41,13 +43,13 @@ document.addEventListener('DOMContentLoaded', () => {
},
computed: {
seriesData() {
- return { full: this.chartData.map(d => [d.label, d.value]) };
+ return [{ name: 'full', data: this.chartData.map(d => [d.label, d.value]) }];
},
},
render(h) {
return h(GlColumnChart, {
props: {
- data: this.seriesData,
+ bars: this.seriesData,
xAxisTitle: __('Used programming language'),
yAxisTitle: __('Percentage'),
xAxisType: 'category',
@@ -86,7 +88,7 @@ document.addEventListener('DOMContentLoaded', () => {
render(h) {
return h(GlColumnChart, {
props: {
- data: this.seriesData,
+ bars: seriesDataToBarData(this.seriesData),
xAxisTitle: __('Day of month'),
yAxisTitle: __('No. of commits'),
xAxisType: 'category',
@@ -113,13 +115,13 @@ document.addEventListener('DOMContentLoaded', () => {
acc.push([key, weekDays[key]]);
return acc;
}, []);
- return { full: data };
+ return [{ name: 'full', data }];
},
},
render(h) {
return h(GlColumnChart, {
props: {
- data: this.seriesData,
+ bars: this.seriesData,
xAxisTitle: __('Weekday'),
yAxisTitle: __('No. of commits'),
xAxisType: 'category',
@@ -143,7 +145,7 @@ document.addEventListener('DOMContentLoaded', () => {
render(h) {
return h(GlColumnChart, {
props: {
- data: this.seriesData,
+ bars: seriesDataToBarData(this.seriesData),
xAxisTitle: __('Hour (UTC)'),
yAxisTitle: __('No. of commits'),
xAxisType: 'category',
diff --git a/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue b/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue
index a9079f91f50..6dd50958fa4 100644
--- a/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue
+++ b/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue
@@ -153,10 +153,10 @@ export default {
:option="chartOptions"
:format-tooltip-text="formatTooltipText"
>
- <template v-if="canShowData" #tooltipTitle>
+ <template v-if="canShowData" #tooltip-title>
{{ tooltipTitle }}
</template>
- <template v-if="canShowData" #tooltipContent>
+ <template v-if="canShowData" #tooltip-content>
<gl-sprintf :message="__('Code Coverage: %{coveragePercentage}%{percentSymbol}')">
<template #coveragePercentage>
{{ coveragePercentage }}
diff --git a/app/assets/javascripts/pages/projects/incidents/index/index.js b/app/assets/javascripts/pages/projects/incidents/index/index.js
index c37ae862a85..bbae605b31f 100644
--- a/app/assets/javascripts/pages/projects/incidents/index/index.js
+++ b/app/assets/javascripts/pages/projects/incidents/index/index.js
@@ -1,5 +1,3 @@
import IncidentsList from '~/incidents/list';
-document.addEventListener('DOMContentLoaded', () => {
- IncidentsList();
-});
+IncidentsList();
diff --git a/app/assets/javascripts/pages/projects/incidents/show/index.js b/app/assets/javascripts/pages/projects/incidents/show/index.js
index 3324cfc0335..5b3f03cd57e 100644
--- a/app/assets/javascripts/pages/projects/incidents/show/index.js
+++ b/app/assets/javascripts/pages/projects/incidents/show/index.js
@@ -2,10 +2,8 @@ import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initRelatedIssues from '~/related_issues';
import initShow from '../../issues/show';
-document.addEventListener('DOMContentLoaded', () => {
- initShow();
- if (!gon.features?.vueIssuableSidebar) {
- initSidebarBundle();
- }
- initRelatedIssues();
-});
+initShow();
+if (!gon.features?.vueIssuableSidebar) {
+ initSidebarBundle();
+}
+initRelatedIssues();
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
deleted file mode 100644
index 534614349bf..00000000000
--- a/app/assets/javascripts/pages/projects/integrations/jira/issues/index/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import initIssuablesList from '~/issues_list';
-
-document.addEventListener('DOMContentLoaded', () => {
- initIssuablesList();
-});
diff --git a/app/assets/javascripts/pages/projects/issues/show.js b/app/assets/javascripts/pages/projects/issues/show.js
index a58b5d3f37c..4b15e435f60 100644
--- a/app/assets/javascripts/pages/projects/issues/show.js
+++ b/app/assets/javascripts/pages/projects/issues/show.js
@@ -5,7 +5,7 @@ import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import ZenMode from '~/zen_mode';
import '~/notes/index';
import { store } from '~/notes/stores';
-import initIssueApp from '~/issue_show/issue';
+import { initIssuableApp, initIssueHeaderActions } from '~/issue_show/issue';
import initIncidentApp from '~/issue_show/incident';
import initIssuableHeaderWarning from '~/vue_shared/components/issuable/init_issuable_header_warning';
import initSentryErrorStackTraceApp from '~/sentry_error_stack_trace';
@@ -24,13 +24,14 @@ export default function() {
initIncidentApp(issuableData);
break;
case IssuableType.Issue:
- initIssueApp(issuableData);
+ initIssuableApp(issuableData, store);
break;
default:
break;
}
initIssuableHeaderWarning(store);
+ initIssueHeaderActions(store);
initSentryErrorStackTraceApp();
initRelatedMergeRequestsApp();
diff --git a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue b/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
index f58e4909a08..7b5e0f70b7b 100644
--- a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
+++ b/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
@@ -1,15 +1,21 @@
<script>
-import { GlSprintf } from '@gitlab/ui';
+import { GlSprintf, GlModal } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
-import { s__, sprintf } from '~/locale';
+import { s__, __, sprintf } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
export default {
+ primaryProps: {
+ text: s__('Labels|Promote Label'),
+ attributes: [{ variant: 'warning' }, { category: 'primary' }],
+ },
+ cancelProps: {
+ text: __('Cancel'),
+ },
components: {
- GlModal: DeprecatedModal2,
+ GlModal,
GlSprintf,
},
props: {
@@ -72,12 +78,12 @@ export default {
</script>
<template>
<gl-modal
- id="promote-label-modal"
- :footer-primary-button-text="s__('Labels|Promote Label')"
- footer-primary-button-variant="warning"
- @submit="onSubmit"
+ modal-id="promote-label-modal"
+ :action-primary="$options.primaryProps"
+ :action-cancel="$options.cancelProps"
+ @primary="onSubmit"
>
- <div slot="title" class="modal-title-with-label">
+ <div slot="modal-title" class="modal-title-with-label">
<gl-sprintf
:message="
s__(
diff --git a/app/assets/javascripts/pages/projects/labels/index/index.js b/app/assets/javascripts/pages/projects/labels/index/index.js
index 36cf485f33d..ee129011f9a 100644
--- a/app/assets/javascripts/pages/projects/labels/index/index.js
+++ b/app/assets/javascripts/pages/projects/labels/index/index.js
@@ -27,71 +27,55 @@ const initLabelIndex = () => {
eventHub.$once('promoteLabelModal.requestFinished', onRequestFinished);
};
- const onDeleteButtonClick = event => {
- const button = event.currentTarget;
- const modalProps = {
- labelTitle: button.dataset.labelTitle,
- labelColor: button.dataset.labelColor,
- labelTextColor: button.dataset.labelTextColor,
- url: button.dataset.url,
- groupName: button.dataset.groupName,
- };
- eventHub.$once('promoteLabelModal.requestStarted', onRequestStarted);
- eventHub.$emit('promoteLabelModal.props', modalProps);
- };
-
const promoteLabelButtons = document.querySelectorAll('.js-promote-project-label-button');
- promoteLabelButtons.forEach(button => {
- button.addEventListener('click', onDeleteButtonClick);
- });
- eventHub.$once('promoteLabelModal.mounted', () => {
- promoteLabelButtons.forEach(button => {
- button.removeAttribute('disabled');
- });
- });
+ return new Vue({
+ el: '#js-promote-label-modal',
+ data() {
+ return {
+ modalProps: {
+ labelTitle: '',
+ labelColor: '',
+ labelTextColor: '',
+ url: '',
+ groupName: '',
+ },
+ };
+ },
+ mounted() {
+ eventHub.$on('promoteLabelModal.props', this.setModalProps);
+ eventHub.$emit('promoteLabelModal.mounted');
- const promoteLabelModal = document.getElementById('promote-label-modal');
- let promoteLabelModalComponent;
+ promoteLabelButtons.forEach(button => {
+ button.removeAttribute('disabled');
+ button.addEventListener('click', () => {
+ this.$root.$emit('bv::show::modal', 'promote-label-modal');
+ eventHub.$once('promoteLabelModal.requestStarted', onRequestStarted);
- if (promoteLabelModal) {
- promoteLabelModalComponent = new Vue({
- el: promoteLabelModal,
- components: {
- PromoteLabelModal,
- },
- data() {
- return {
- modalProps: {
- labelTitle: '',
- labelColor: '',
- labelTextColor: '',
- url: '',
- groupName: '',
- },
- };
- },
- mounted() {
- eventHub.$on('promoteLabelModal.props', this.setModalProps);
- eventHub.$emit('promoteLabelModal.mounted');
- },
- beforeDestroy() {
- eventHub.$off('promoteLabelModal.props', this.setModalProps);
- },
- methods: {
- setModalProps(modalProps) {
- this.modalProps = modalProps;
- },
- },
- render(createElement) {
- return createElement('promote-label-modal', {
- props: this.modalProps,
+ this.setModalProps({
+ labelTitle: button.dataset.labelTitle,
+ labelColor: button.dataset.labelColor,
+ labelTextColor: button.dataset.labelTextColor,
+ url: button.dataset.url,
+ groupName: button.dataset.groupName,
+ });
});
+ });
+ },
+ beforeDestroy() {
+ eventHub.$off('promoteLabelModal.props', this.setModalProps);
+ },
+ methods: {
+ setModalProps(modalProps) {
+ this.modalProps = modalProps;
},
- });
- }
-
- return promoteLabelModalComponent;
+ },
+ render(createElement) {
+ return createElement(PromoteLabelModal, {
+ props: this.modalProps,
+ });
+ },
+ });
};
document.addEventListener('DOMContentLoaded', initLabelIndex);
diff --git a/app/assets/javascripts/pages/projects/metrics_dashboard/index.js b/app/assets/javascripts/pages/projects/metrics_dashboard/index.js
index d3028aec313..606439866ea 100644
--- a/app/assets/javascripts/pages/projects/metrics_dashboard/index.js
+++ b/app/assets/javascripts/pages/projects/metrics_dashboard/index.js
@@ -1,3 +1,3 @@
import monitoringApp from '~/monitoring/monitoring_app';
-document.addEventListener('DOMContentLoaded', monitoringApp);
+monitoringApp();
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
index 6197dc8a9db..90d2df50d5a 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
@@ -1,16 +1,24 @@
import Vue from 'vue';
import PipelineSchedulesCallout from '../shared/components/pipeline_schedules_callout.vue';
-document.addEventListener(
- 'DOMContentLoaded',
- () =>
- new Vue({
- el: '#pipeline-schedules-callout',
- components: {
- 'pipeline-schedules-callout': PipelineSchedulesCallout,
- },
- render(createElement) {
- return createElement('pipeline-schedules-callout');
- },
- }),
-);
+document.addEventListener('DOMContentLoaded', () => {
+ const el = document.getElementById('pipeline-schedules-callout');
+
+ if (!el) {
+ return;
+ }
+
+ const { docsUrl, illustrationUrl } = el.dataset;
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ render(createElement) {
+ return createElement(PipelineSchedulesCallout);
+ },
+ provide: {
+ docsUrl,
+ illustrationUrl,
+ },
+ });
+});
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 a138a3a3425..8ee9d481466 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,7 +1,7 @@
<script>
import Vue from 'vue';
import Cookies from 'js-cookie';
-import { GlIcon } from '@gitlab/ui';
+import { GlButton } from '@gitlab/ui';
import Translate from '../../../../../vue_shared/translate';
import { parseBoolean } from '~/lib/utils/common_utils';
@@ -12,12 +12,11 @@ const cookieKey = 'pipeline_schedules_callout_dismissed';
export default {
name: 'PipelineSchedulesCallout',
components: {
- GlIcon,
+ GlButton,
},
+ inject: ['docsUrl', 'illustrationUrl'],
data() {
return {
- docsUrl: document.getElementById('pipeline-schedules-callout').dataset.docsUrl,
- imageUrl: document.getElementById('pipeline-schedules-callout').dataset.imageUrl,
calloutDismissed: parseBoolean(Cookies.get(cookieKey)),
};
},
@@ -31,12 +30,16 @@ export default {
</script>
<template>
<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">
- <gl-icon name="close" aria-hidden="true" />
- </button>
- <div class="svg-container">
- <img :src="imageUrl" />
+ <div class="bordered-box landing content-block" data-testid="innerContent">
+ <gl-button
+ category="tertiary"
+ icon="close"
+ :aria-label="__('Dismiss')"
+ class="gl-absolute gl-top-2 gl-right-2"
+ @click="dismissCallout"
+ />
+ <div class="svg-content">
+ <img :src="illustrationUrl" />
</div>
<div class="user-callout-copy">
<h4>{{ __('Scheduling Pipelines') }}</h4>
diff --git a/app/assets/javascripts/pages/projects/pipelines/show/index.js b/app/assets/javascripts/pages/projects/pipelines/show/index.js
index 7a57e417b41..d3f46b7e025 100644
--- a/app/assets/javascripts/pages/projects/pipelines/show/index.js
+++ b/app/assets/javascripts/pages/projects/pipelines/show/index.js
@@ -1,7 +1,5 @@
import initPipelineDetails from '~/pipelines/pipeline_details_bundle';
import initPipelines from '../init_pipelines';
-document.addEventListener('DOMContentLoaded', () => {
- initPipelines();
- initPipelineDetails();
-});
+initPipelines();
+initPipelineDetails();
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index 2f27814a692..5317093c4cf 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -57,7 +57,7 @@ export default class Project {
$('.project-refs-select').on('change', function() {
return $(this)
.parents('form')
- .submit();
+ .trigger('submit');
});
}
@@ -156,11 +156,32 @@ export default class Project {
},
clicked(options) {
const { e } = options;
- if (!shouldVisit) {
- e.preventDefault();
+ e.preventDefault();
+
+ // Since this page does not reload when changing directories in a repo
+ // the rendered links do not have the path to the current directory.
+ // This updates the path based on the current url and then opens
+ // the the url with the updated path parameter.
+ if (shouldVisit) {
+ const selectedUrl = new URL(e.target.href);
+ const loc = window.location.href;
+
+ if (loc.includes('/-/')) {
+ const refs = this.fullData.Branches.concat(this.fullData.Tags);
+ const currentRef = refs.find(ref => loc.indexOf(ref) > -1);
+ if (currentRef) {
+ const targetPath = loc.split(currentRef)[1].slice(1);
+ selectedUrl.searchParams.set('path', targetPath);
+ }
+ }
+
+ // Open in new window if "meta" key is pressed
+ if (e.metaKey) {
+ window.open(selectedUrl.href, '_blank');
+ } else {
+ window.location.href = selectedUrl.href;
+ }
}
- /* The actual process is removed since `link.href` in `RenderRow` contains the full target.
- * It makes the visitable link can be visited when opening on a new tab of browser */
},
});
});
diff --git a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
index 40816420eef..5d4c1595342 100644
--- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
@@ -1,48 +1,35 @@
import initSettingsPanels from '~/settings_panels';
import SecretValues from '~/behaviors/secret_values';
-import AjaxVariableList from '~/ci_variable_list/ajax_variable_list';
import registrySettingsApp from '~/registry/settings/registry_settings_bundle';
import initVariableList from '~/ci_variable_list';
import initDeployFreeze from '~/deploy_freeze';
import initSettingsPipelinesTriggers from '~/ci_settings_pipeline_triggers';
+import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
-document.addEventListener('DOMContentLoaded', () => {
- // Initialize expandable settings panels
- initSettingsPanels();
+// Initialize expandable settings panels
+initSettingsPanels();
- const runnerToken = document.querySelector('.js-secret-runner-token');
- if (runnerToken) {
- const runnerTokenSecretValue = new SecretValues({
- container: runnerToken,
- });
- runnerTokenSecretValue.init();
- }
-
- if (gon.features.newVariablesUi) {
- initVariableList();
- } else {
- const variableListEl = document.querySelector('.js-ci-variable-list-section');
- // eslint-disable-next-line no-new
- new AjaxVariableList({
- container: variableListEl,
- saveButton: variableListEl.querySelector('.js-ci-variables-save-button'),
- errorBox: variableListEl.querySelector('.js-ci-variable-error-box'),
- saveEndpoint: variableListEl.dataset.saveEndpoint,
- maskableRegex: variableListEl.dataset.maskableRegex,
- });
- }
-
- // hide extra auto devops settings based checkbox state
- const autoDevOpsExtraSettings = document.querySelector('.js-extra-settings');
- const instanceDefaultBadge = document.querySelector('.js-instance-default-badge');
- document.querySelector('.js-toggle-extra-settings').addEventListener('click', event => {
- const { target } = event;
- if (instanceDefaultBadge) instanceDefaultBadge.style.display = 'none';
- autoDevOpsExtraSettings.classList.toggle('hidden', !target.checked);
+const runnerToken = document.querySelector('.js-secret-runner-token');
+if (runnerToken) {
+ const runnerTokenSecretValue = new SecretValues({
+ container: runnerToken,
});
+ runnerTokenSecretValue.init();
+}
- registrySettingsApp();
- initDeployFreeze();
+initVariableList();
- initSettingsPipelinesTriggers();
+// hide extra auto devops settings based checkbox state
+const autoDevOpsExtraSettings = document.querySelector('.js-extra-settings');
+const instanceDefaultBadge = document.querySelector('.js-instance-default-badge');
+document.querySelector('.js-toggle-extra-settings').addEventListener('click', event => {
+ const { target } = event;
+ if (instanceDefaultBadge) instanceDefaultBadge.style.display = 'none';
+ autoDevOpsExtraSettings.classList.toggle('hidden', !target.checked);
});
+
+registrySettingsApp();
+initDeployFreeze();
+
+initSettingsPipelinesTriggers();
+initInstallRunner();
diff --git a/app/assets/javascripts/pages/projects/settings/integrations/show/index.js b/app/assets/javascripts/pages/projects/settings/integrations/show/index.js
index f2cf2eb9b28..bf9ccdbf9a8 100644
--- a/app/assets/javascripts/pages/projects/settings/integrations/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/integrations/show/index.js
@@ -1,6 +1,4 @@
import PersistentUserCallout from '~/persistent_user_callout';
-document.addEventListener('DOMContentLoaded', () => {
- const callout = document.querySelector('.js-webhooks-moved-alert');
- PersistentUserCallout.factory(callout);
-});
+const callout = document.querySelector('.js-webhooks-moved-alert');
+PersistentUserCallout.factory(callout);
diff --git a/app/assets/javascripts/pages/projects/settings/operations/show/index.js b/app/assets/javascripts/pages/projects/settings/operations/show/index.js
index 1b9ec44ed4a..153ccffd472 100644
--- a/app/assets/javascripts/pages/projects/settings/operations/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/operations/show/index.js
@@ -5,13 +5,11 @@ import mountGrafanaIntegration from '~/grafana_integration';
import initSettingsPanels from '~/settings_panels';
import initIncidentsSettings from '~/incidents_settings';
-document.addEventListener('DOMContentLoaded', () => {
- initIncidentsSettings();
- mountErrorTrackingForm();
- mountOperationSettings();
- mountGrafanaIntegration();
- if (!IS_EE) {
- initSettingsPanels();
- }
- mountAlertsSettings(document.querySelector('.js-alerts-settings'));
-});
+initIncidentsSettings();
+mountErrorTrackingForm();
+mountOperationSettings();
+mountGrafanaIntegration();
+if (!IS_EE) {
+ initSettingsPanels();
+}
+mountAlertsSettings(document.querySelector('.js-alerts-settings'));
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
index bcf82e264d1..e50add3b0a4 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
@@ -68,6 +68,11 @@ export default {
required: false,
default: false,
},
+ requirementsAvailable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
visibilityHelpPath: {
type: String,
required: false,
@@ -132,6 +137,7 @@ export default {
snippetsAccessLevel: featureAccessLevel.EVERYONE,
pagesAccessLevel: featureAccessLevel.EVERYONE,
metricsDashboardAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
+ requirementsAccessLevel: featureAccessLevel.EVERYONE,
containerRegistryEnabled: true,
lfsEnabled: true,
requestAccessEnabled: true,
@@ -234,6 +240,10 @@ export default {
featureAccessLevel.PROJECT_MEMBERS,
this.metricsDashboardAccessLevel,
);
+ this.requirementsAccessLevel = Math.min(
+ featureAccessLevel.PROJECT_MEMBERS,
+ this.requirementsAccessLevel,
+ );
if (this.pagesAccessLevel === featureAccessLevel.EVERYONE) {
// When from Internal->Private narrow access for only members
this.pagesAccessLevel = featureAccessLevel.PROJECT_MEMBERS;
@@ -257,6 +267,9 @@ export default {
this.pagesAccessLevel = featureAccessLevel.EVERYONE;
if (this.metricsDashboardAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.metricsDashboardAccessLevel = featureAccessLevel.EVERYONE;
+ if (this.requirementsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
+ this.requirementsAccessLevel = featureAccessLevel.EVERYONE;
+
this.highlightChanges();
}
},
@@ -482,6 +495,18 @@ export default {
</project-setting-row>
</div>
<project-setting-row
+ v-if="requirementsAvailable"
+ ref="requirements-settings"
+ :label="s__('ProjectSettings|Requirements')"
+ :help-text="s__('ProjectSettings|Requirements management system for this project')"
+ >
+ <project-feature-setting
+ v-model="requirementsAccessLevel"
+ :options="featureAccessLevelOptions"
+ name="project[project_feature_attributes][requirements_access_level]"
+ />
+ </project-setting-row>
+ <project-setting-row
ref="wiki-settings"
:label="s__('ProjectSettings|Wiki')"
:help-text="s__('ProjectSettings|Pages for project documentation')"
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js b/app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js
index f69ca6e27b3..ae0936417ad 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js
+++ b/app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js
@@ -2,6 +2,7 @@ export default {
data() {
return {
packagesEnabled: false,
+ requirementsEnabled: false,
};
},
watch: {
diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js
index dd8141d34c7..413b2d01621 100644
--- a/app/assets/javascripts/pages/projects/show/index.js
+++ b/app/assets/javascripts/pages/projects/show/index.js
@@ -10,6 +10,8 @@ import leaveByUrl from '~/namespaces/leave_by_url';
import Star from '../../../star';
import notificationsDropdown from '../../../notifications_dropdown';
import { showLearnGitLabProjectPopover } from '~/onboarding_issues';
+import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
+import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
initReadMore();
new Star(); // eslint-disable-line no-new
@@ -42,3 +44,6 @@ showLearnGitLabProjectPopover();
notificationsDropdown();
new ShortcutsNavigation(); // eslint-disable-line no-new
+
+initInviteMembersTrigger();
+initInviteMembersModal();
diff --git a/app/assets/javascripts/pages/projects/terraform/index/index.js b/app/assets/javascripts/pages/projects/terraform/index/index.js
new file mode 100644
index 00000000000..6f9f820f8e1
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/terraform/index/index.js
@@ -0,0 +1,3 @@
+import loadTerraformVues from '~/terraform';
+
+loadTerraformVues();
diff --git a/app/assets/javascripts/pages/search/show/index.js b/app/assets/javascripts/pages/search/show/index.js
index 721219874cf..88f2f30aad9 100644
--- a/app/assets/javascripts/pages/search/show/index.js
+++ b/app/assets/javascripts/pages/search/show/index.js
@@ -1,7 +1,7 @@
import Search from './search';
-import initSearchApp from '~/search';
+import { initSearchApp } from '~/search';
document.addEventListener('DOMContentLoaded', () => {
initSearchApp();
- return new Search();
+ return new Search(); // Deprecated Dropdown (Projects)
});
diff --git a/app/assets/javascripts/pages/search/show/search.js b/app/assets/javascripts/pages/search/show/search.js
index 2cd333f26e1..03675f1ce66 100644
--- a/app/assets/javascripts/pages/search/show/search.js
+++ b/app/assets/javascripts/pages/search/show/search.js
@@ -1,52 +1,26 @@
import $ from 'jquery';
+import setHighlightClass from 'ee_else_ce/search/highlight_blob_search_result';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { deprecatedCreateFlash as Flash } from '~/flash';
import Api from '~/api';
import { __ } from '~/locale';
import Project from '~/pages/projects/project';
-import { visitUrl } from '~/lib/utils/url_utility';
+import { visitUrl, queryToObject } from '~/lib/utils/url_utility';
import refreshCounts from './refresh_counts';
-import setHighlightClass from './highlight_blob_search_result';
export default class Search {
constructor() {
- setHighlightClass();
- const $groupDropdown = $('.js-search-group-dropdown');
+ setHighlightClass(); // Code Highlighting
const $projectDropdown = $('.js-search-project-dropdown');
this.searchInput = '.js-search-input';
this.searchClear = '.js-search-clear';
- this.groupId = $groupDropdown.data('groupId');
+ const query = queryToObject(window.location.search);
+ this.groupId = query?.group_id;
this.eventListeners();
refreshCounts();
- initDeprecatedJQueryDropdown($groupDropdown, {
- selectable: true,
- filterable: true,
- filterRemote: true,
- fieldName: 'group_id',
- search: {
- fields: ['full_name'],
- },
- data(term, callback) {
- return Api.groups(term, {}, data => {
- data.unshift({
- full_name: __('Any'),
- });
- data.splice(1, 0, { type: 'divider' });
- return callback(data);
- });
- },
- id(obj) {
- return obj.id;
- },
- text(obj) {
- return obj.full_name;
- },
- clicked: () => Search.submitSearch(),
- });
-
initDeprecatedJQueryDropdown($projectDropdown, {
selectable: true,
filterable: true,
diff --git a/app/assets/javascripts/pages/shared/mount_runner_instructions.js b/app/assets/javascripts/pages/shared/mount_runner_instructions.js
new file mode 100644
index 00000000000..b7662155339
--- /dev/null
+++ b/app/assets/javascripts/pages/shared/mount_runner_instructions.js
@@ -0,0 +1,32 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import InstallRunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue';
+
+Vue.use(VueApollo);
+
+export function initInstallRunner(componentId = 'js-install-runner') {
+ const installRunnerEl = document.getElementById(componentId);
+ const { projectPath, groupPath } = installRunnerEl?.dataset;
+
+ if (installRunnerEl) {
+ const defaultClient = createDefaultClient();
+
+ const apolloProvider = new VueApollo({
+ defaultClient,
+ });
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: installRunnerEl,
+ apolloProvider,
+ provide: {
+ projectPath,
+ groupPath,
+ },
+ render(createElement) {
+ return createElement(InstallRunnerInstructions);
+ },
+ });
+ }
+}
diff --git a/app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue b/app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue
index 653aad3d2f5..3792dad376b 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,7 +1,7 @@
<script>
import { GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
import { escape } from 'lodash';
-import { s__, sprintf } from '~/locale';
+import { s__, __, sprintf } from '~/locale';
export default {
components: {
@@ -29,12 +29,6 @@ export default {
},
},
computed: {
- modalId() {
- return 'delete-wiki-modal';
- },
- message() {
- return s__('WikiPageConfirmDelete|Are you sure you want to delete this page?');
- },
title() {
return sprintf(
s__('WikiPageConfirmDelete|Delete page %{pageTitle}?'),
@@ -44,6 +38,21 @@ export default {
false,
);
},
+ primaryProps() {
+ return {
+ text: this.$options.i18n.deletePageText,
+ attributes: {
+ variant: 'danger',
+ 'data-qa-selector': 'confirm_deletion_button',
+ 'data-testid': 'confirm_deletion_button',
+ },
+ };
+ },
+ cancelProps() {
+ return {
+ text: this.$options.i18n.cancelButtonText,
+ };
+ },
},
methods: {
onSubmit() {
@@ -51,30 +60,36 @@ export default {
this.$refs.form.submit();
},
},
+ i18n: {
+ deletePageText: s__('WikiPageConfirmDelete|Delete page'),
+ modalBody: s__('WikiPageConfirmDelete|Are you sure you want to delete this page?'),
+ cancelButtonText: __('Cancel'),
+ },
+ modal: {
+ modalId: 'delete-wiki-modal',
+ },
};
</script>
<template>
<div class="d-inline-block">
<gl-button
- v-gl-modal="modalId"
- category="primary"
+ v-gl-modal="$options.modal.modalId"
+ category="secondary"
variant="danger"
data-qa-selector="delete_button"
>
- {{ __('Delete') }}
+ {{ $options.i18n.deletePageText }}
</gl-button>
<gl-modal
:title="title"
- :action-primary="{
- text: s__('WikiPageConfirmDelete|Delete page'),
- attributes: { variant: 'danger', 'data-qa-selector': 'confirm_deletion_button' },
- }"
- :modal-id="modalId"
- title-tag="h4"
+ :action-primary="primaryProps"
+ :action-cancel="cancelProps"
+ :modal-id="$options.modal.modalId"
+ size="sm"
@ok="onSubmit"
>
- {{ message }}
+ {{ $options.i18n.modalBody }}
<form ref="form" :action="deleteWikiUrl" method="post" class="js-requires-input">
<input ref="method" type="hidden" name="_method" value="delete" />
<input :value="csrfToken" type="hidden" name="authenticity_token" />
diff --git a/app/assets/javascripts/pages/shared/wikis/wikis.js b/app/assets/javascripts/pages/shared/wikis/wikis.js
index ab948fd106f..fe9caba351e 100644
--- a/app/assets/javascripts/pages/shared/wikis/wikis.js
+++ b/app/assets/javascripts/pages/shared/wikis/wikis.js
@@ -1,6 +1,7 @@
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import { s__, sprintf } from '~/locale';
import Tracking from '~/tracking';
+import showToast from '~/vue_shared/plugins/global_toast';
const MARKDOWN_LINK_TEXT = {
markdown: '[Link Title](page-slug)',
@@ -63,6 +64,7 @@ export default class Wikis {
}
Wikis.trackPageView();
+ Wikis.showToasts();
}
handleWikiTitleChange(e) {
@@ -116,4 +118,9 @@ export default class Wikis {
},
});
}
+
+ static showToasts() {
+ const toasts = document.querySelectorAll('.js-toast-message');
+ toasts.forEach(toast => showToast(toast.dataset.message));
+ }
}
diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js
index eb0a5efe75c..54666af540e 100644
--- a/app/assets/javascripts/pages/users/activity_calendar.js
+++ b/app/assets/javascripts/pages/users/activity_calendar.js
@@ -125,9 +125,6 @@ export default class ActivityCalendar {
this.renderMonths();
this.renderDayTitles();
this.renderKey();
-
- // Init tooltips
- $(`${container} .js-tooltip`).tooltip({ html: true });
}
// Add extra padding for the last month label if it is also the last column
@@ -191,7 +188,8 @@ export default class ActivityCalendar {
stamp.count !== 0 ? this.color(Math.min(stamp.count, 40)) : '#ededed',
)
.attr('title', stamp => formatTooltipText(stamp))
- .attr('class', 'user-contrib-cell js-tooltip')
+ .attr('class', 'user-contrib-cell has-tooltip')
+ .attr('data-html', true)
.attr('data-container', 'body')
.on('click', this.clickDay);
}
@@ -279,9 +277,10 @@ export default class ActivityCalendar {
.attr('x', (color, i) => this.daySizeWithSpace * i)
.attr('y', 0)
.attr('fill', color => color)
- .attr('class', 'js-tooltip')
+ .attr('class', 'has-tooltip')
.attr('title', (color, i) => keyValues[i])
- .attr('data-container', 'body');
+ .attr('data-container', 'body')
+ .attr('data-html', true);
}
initColor() {
diff --git a/app/assets/javascripts/pages/users/index.js b/app/assets/javascripts/pages/users/index.js
index cfc6dc61f9f..8adbc2a8168 100644
--- a/app/assets/javascripts/pages/users/index.js
+++ b/app/assets/javascripts/pages/users/index.js
@@ -4,11 +4,6 @@ import UserCallout from '~/user_callout';
import UserTabs from './user_tabs';
function initUserProfile(action) {
- // place profile avatars to top
- $('.profile-groups-avatars').tooltip({
- placement: 'top',
- });
-
// eslint-disable-next-line no-new
new UserTabs({ parentEl: '.user-profile', action });
diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js
index 9d66c784750..2485853afc7 100644
--- a/app/assets/javascripts/pages/users/user_tabs.js
+++ b/app/assets/javascripts/pages/users/user_tabs.js
@@ -5,7 +5,6 @@ import Activities from '~/activities';
import { localTimeAgo } from '~/lib/utils/datetime_utility';
import AjaxCache from '~/lib/utils/ajax_cache';
import { __ } from '~/locale';
-import { deprecatedCreateFlash as flash } from '~/flash';
import ActivityCalendar from './activity_calendar';
import UserOverviewBlock from './user_overview_block';
@@ -63,9 +62,9 @@ import UserOverviewBlock from './user_overview_block';
*/
const CALENDAR_TEMPLATE = `
- <div class="clearfix calendar">
+ <div class="calendar">
<div class="js-contrib-calendar"></div>
- <div class="calendar-hint bottom-right"></div>
+ <div class="calendar-hint"></div>
</div>
`;
@@ -214,7 +213,17 @@ export default class UserTabs {
AjaxCache.retrieve(calendarPath)
.then(data => UserTabs.renderActivityCalendar(data, $calendarWrap))
- .catch(() => flash(__('There was an error loading users activity calendar.')));
+ .catch(() => {
+ const cWrap = $calendarWrap[0];
+ cWrap.querySelector('.spinner').classList.add('invisible');
+ cWrap.querySelector('.user-calendar-error').classList.remove('invisible');
+ cWrap.querySelector('.user-calendar-error .js-retry-load').addEventListener('click', e => {
+ e.preventDefault();
+ cWrap.querySelector('.user-calendar-error').classList.add('invisible');
+ cWrap.querySelector('.spinner').classList.remove('invisible');
+ this.loadActivityCalendar();
+ });
+ });
}
static renderActivityCalendar(data, $calendarWrap) {
diff --git a/app/assets/javascripts/performance/constants.js b/app/assets/javascripts/performance/constants.js
new file mode 100644
index 00000000000..816eb9b3a66
--- /dev/null
+++ b/app/assets/javascripts/performance/constants.js
@@ -0,0 +1,45 @@
+export const PERFORMANCE_TYPE_MARK = 'mark';
+export const PERFORMANCE_TYPE_MEASURE = 'measure';
+
+//
+// SNIPPET namespace
+//
+
+// Marks
+export const SNIPPET_MARK_VIEW_APP_START = 'snippet-view-app-start';
+export const SNIPPET_MARK_EDIT_APP_START = 'snippet-edit-app-start';
+export const SNIPPET_MARK_BLOBS_CONTENT = 'snippet-blobs-content-finished';
+
+// Measures
+export const SNIPPET_MEASURE_BLOBS_CONTENT = 'snippet-blobs-content';
+
+//
+// WebIDE namespace
+//
+
+// Marks
+export const WEBIDE_MARK_APP_START = 'webide-app-start';
+export const WEBIDE_MARK_TREE_START = 'webide-tree-start';
+export const WEBIDE_MARK_TREE_FINISH = 'webide-tree-finished';
+export const WEBIDE_MARK_FILE_START = 'webide-file-start';
+export const WEBIDE_MARK_FILE_CLICKED = 'webide-file-clicked';
+export const WEBIDE_MARK_FILE_FINISH = 'webide-file-finished';
+
+// Measures
+export const WEBIDE_MEASURE_TREE_FROM_REQUEST = 'webide-tree-loading-from-request';
+export const WEBIDE_MEASURE_FILE_FROM_REQUEST = 'webide-file-loading-from-request';
+export const WEBIDE_MEASURE_FILE_AFTER_INTERACTION = 'webide-file-loading-after-interaction';
+
+//
+// MR Diffs namespace
+
+// Marks
+export const MR_DIFFS_MARK_FILE_TREE_START = 'mr-diffs-mark-file-tree-start';
+export const MR_DIFFS_MARK_FILE_TREE_END = 'mr-diffs-mark-file-tree-end';
+export const MR_DIFFS_MARK_DIFF_FILES_START = 'mr-diffs-mark-diff-files-start';
+export const MR_DIFFS_MARK_FIRST_DIFF_FILE_SHOWN = 'mr-diffs-mark-first-diff-file-shown';
+export const MR_DIFFS_MARK_DIFF_FILES_END = 'mr-diffs-mark-diff-files-end';
+
+// Measures
+export const MR_DIFFS_MEASURE_FILE_TREE_DONE = 'mr-diffs-measure-file-tree-done';
+export const MR_DIFFS_MEASURE_DIFF_FILES_DONE = 'mr-diffs-measure-diff-files-done';
diff --git a/app/assets/javascripts/performance_utils.js b/app/assets/javascripts/performance/utils.js
index 1c87ee2086e..1c87ee2086e 100644
--- a/app/assets/javascripts/performance_utils.js
+++ b/app/assets/javascripts/performance/utils.js
diff --git a/app/assets/javascripts/performance/vue_performance_plugin.js b/app/assets/javascripts/performance/vue_performance_plugin.js
new file mode 100644
index 00000000000..7329b83b1d1
--- /dev/null
+++ b/app/assets/javascripts/performance/vue_performance_plugin.js
@@ -0,0 +1,53 @@
+const ComponentPerformancePlugin = {
+ install(Vue, options) {
+ Vue.mixin({
+ beforeCreate() {
+ /** Make sure the component you want to measure has `name` option defined
+ * and it matches the one you pass as the plugin option. Example:
+ *
+ * my_component.vue:
+ *
+ * ```
+ * export default {
+ * name: 'MyComponent'
+ * ...
+ * }
+ * ```
+ *
+ * index.js (where you initialize your Vue app containing <my-component>):
+ *
+ * ```
+ * Vue.use(PerformancePlugin, {
+ * components: [
+ * 'MyComponent',
+ * ]
+ * });
+ * ```
+ */
+ const componentName = this.$options.name;
+ if (options?.components?.indexOf(componentName) !== -1) {
+ const tagName = `<${componentName}>`;
+ if (!performance.getEntriesByName(`${tagName}-start`).length) {
+ performance.mark(`${tagName}-start`);
+ }
+ }
+ },
+ mounted() {
+ const componentName = this.$options.name;
+ if (options?.components?.indexOf(componentName) !== -1) {
+ this.$nextTick(() => {
+ window.requestAnimationFrame(() => {
+ const tagName = `<${componentName}>`;
+ if (!performance.getEntriesByName(`${tagName}-end`).length) {
+ performance.mark(`${tagName}-end`);
+ performance.measure(`${tagName}`, `${tagName}-start`);
+ }
+ });
+ });
+ }
+ },
+ });
+ },
+};
+
+export default ComponentPerformancePlugin;
diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
index 9f05ee5c7c2..90e14d8325f 100644
--- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
@@ -1,15 +1,17 @@
<script>
-import { GlIcon } from '@gitlab/ui';
+import { GlButton, GlIcon, GlModal, GlModalDirective } from '@gitlab/ui';
import RequestWarning from './request_warning.vue';
-import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
-
export default {
components: {
RequestWarning,
- GlModal: DeprecatedModal2,
+ GlButton,
+ GlModal,
GlIcon,
},
+ directives: {
+ 'gl-modal': GlModalDirective,
+ },
props: {
currentRequest: {
type: Object,
@@ -35,7 +37,15 @@ export default {
required: true,
},
},
+ data() {
+ return {
+ openedBacktraces: [],
+ };
+ },
computed: {
+ modalId() {
+ return `modal-peek-${this.metric}-details`;
+ },
metricDetails() {
return this.currentRequest.details[this.metric];
},
@@ -58,29 +68,35 @@ export default {
return '';
},
},
+ methods: {
+ toggleBacktrace(toggledIndex) {
+ const toggledOpenedIndex = this.openedBacktraces.indexOf(toggledIndex);
+
+ if (toggledOpenedIndex === -1) {
+ this.openedBacktraces = [...this.openedBacktraces, toggledIndex];
+ } else {
+ this.openedBacktraces = this.openedBacktraces.filter(
+ openedIndex => openedIndex !== toggledIndex,
+ );
+ }
+ },
+ itemHasOpenedBacktrace(toggledIndex) {
+ return this.openedBacktraces.find(openedIndex => openedIndex === toggledIndex) >= 0;
+ },
+ },
};
</script>
<template>
<div
v-if="currentRequest.details && metricDetails"
:id="`peek-view-${metric}`"
- class="view"
+ class="gl-display-flex gl-align-items-center view"
data-qa-selector="detailed_metric_content"
>
- <button
- :data-target="`#modal-peek-${metric}-details`"
- class="btn-blank btn-link bold"
- type="button"
- data-toggle="modal"
- >
+ <gl-button v-gl-modal="modalId" class="gl-mr-2" type="button" variant="link">
{{ metricDetailsLabel }}
- </button>
- <gl-modal
- :id="`modal-peek-${metric}-details`"
- :header-title-text="header"
- modal-size="xl"
- class="performance-bar-modal"
- >
+ </gl-button>
+ <gl-modal :modal-id="modalId" :title="header" size="lg" modal-class="gl-mt-7" scrollable>
<table class="table">
<template v-if="detailsList.length">
<tr v-for="(item, index) in detailsList" :key="index">
@@ -90,7 +106,7 @@ export default {
}}</span>
</td>
<td>
- <div class="js-toggle-container">
+ <div>
<div
v-for="(key, keyIndex) in keys"
:key="key"
@@ -98,16 +114,18 @@ export default {
:class="{ 'mb-3 bold': keyIndex == 0 }"
>
{{ item[key] }}
- <button
+ <gl-button
v-if="keyIndex == 0 && item.backtrace"
- class="text-expander js-toggle-button"
+ class="gl-ml-3"
+ data-testid="backtrace-expand-btn"
type="button"
:aria-label="__('Toggle backtrace')"
+ @click="toggleBacktrace(index)"
>
<gl-icon :size="12" name="ellipsis_h" />
- </button>
+ </gl-button>
</div>
- <pre v-if="item.backtrace" class="backtrace-row js-toggle-content mt-2">{{
+ <pre v-if="itemHasOpenedBacktrace(index)" class="backtrace-row mt-2">{{
item.backtrace
}}</pre>
</div>
diff --git a/app/assets/javascripts/performance_bar/performance_bar_log.js b/app/assets/javascripts/performance_bar/performance_bar_log.js
index 55b4d626e56..3ba7ff1c221 100644
--- a/app/assets/javascripts/performance_bar/performance_bar_log.js
+++ b/app/assets/javascripts/performance_bar/performance_bar_log.js
@@ -1,6 +1,6 @@
/* eslint-disable no-console */
import { getCLS, getFID, getLCP } from 'web-vitals';
-import { PERFORMANCE_TYPE_MARK, PERFORMANCE_TYPE_MEASURE } from '~/performance_constants';
+import { PERFORMANCE_TYPE_MARK, PERFORMANCE_TYPE_MEASURE } from '~/performance/constants';
const initVitalsLog = () => {
const reportVital = data => {
diff --git a/app/assets/javascripts/performance_constants.js b/app/assets/javascripts/performance_constants.js
deleted file mode 100644
index 6b6b6f1da40..00000000000
--- a/app/assets/javascripts/performance_constants.js
+++ /dev/null
@@ -1,31 +0,0 @@
-export const PERFORMANCE_TYPE_MARK = 'mark';
-export const PERFORMANCE_TYPE_MEASURE = 'measure';
-
-//
-// SNIPPET namespace
-//
-
-// Marks
-export const SNIPPET_MARK_VIEW_APP_START = 'snippet-view-app-start';
-export const SNIPPET_MARK_EDIT_APP_START = 'snippet-edit-app-start';
-export const SNIPPET_MARK_BLOBS_CONTENT = 'snippet-blobs-content-finished';
-
-// Measures
-export const SNIPPET_MEASURE_BLOBS_CONTENT = 'snippet-blobs-content';
-
-//
-// WebIDE namespace
-//
-
-// Marks
-export const WEBIDE_MARK_APP_START = 'webide-app-start';
-export const WEBIDE_MARK_TREE_START = 'webide-tree-start';
-export const WEBIDE_MARK_TREE_FINISH = 'webide-tree-finished';
-export const WEBIDE_MARK_FILE_START = 'webide-file-start';
-export const WEBIDE_MARK_FILE_CLICKED = 'webide-file-clicked';
-export const WEBIDE_MARK_FILE_FINISH = 'webide-file-finished';
-
-// Measures
-export const WEBIDE_MEASURE_TREE_FROM_REQUEST = 'webide-tree-loading-from-request';
-export const WEBIDE_MEASURE_FILE_FROM_REQUEST = 'webide-file-loading-from-request';
-export const WEBIDE_MEASURE_FILE_AFTER_INTERACTION = 'webide-file-loading-after-interaction';
diff --git a/app/assets/javascripts/persistent_user_callouts.js b/app/assets/javascripts/persistent_user_callouts.js
index ef4d5338046..8c5f45e9d34 100644
--- a/app/assets/javascripts/persistent_user_callouts.js
+++ b/app/assets/javascripts/persistent_user_callouts.js
@@ -6,6 +6,7 @@ const PERSISTENT_USER_CALLOUTS = [
'.js-admin-licensed-user-count-threshold',
'.js-buy-pipeline-minutes-notification-callout',
'.js-token-expiry-callout',
+ '.js-registration-enabled-callout',
];
const initCallouts = () => {
diff --git a/app/assets/javascripts/pipeline_editor/components/text_editor.vue b/app/assets/javascripts/pipeline_editor/components/text_editor.vue
new file mode 100644
index 00000000000..a925077c906
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/text_editor.vue
@@ -0,0 +1,26 @@
+<script>
+import EditorLite from '~/vue_shared/components/editor_lite.vue';
+
+export default {
+ components: {
+ EditorLite,
+ },
+ props: {
+ value: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-border-solid gl-border-gray-100 gl-border-1">
+ <editor-lite
+ v-model="value"
+ file-name="*.yml"
+ :editor-options="{ readOnly: true }"
+ @editor-ready="$emit('editor-ready')"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql
new file mode 100644
index 00000000000..9f1b5b13088
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql
@@ -0,0 +1,5 @@
+query getBlobContent($projectPath: ID!, $path: String, $ref: String!) {
+ blobContent(projectPath: $projectPath, path: $path, ref: $ref) @client {
+ rawData
+ }
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
new file mode 100644
index 00000000000..7b8c70ac93e
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
@@ -0,0 +1,16 @@
+import Api from '~/api';
+
+export const resolvers = {
+ Query: {
+ blobContent(_, { projectPath, path, ref }) {
+ return {
+ __typename: 'BlobContent',
+ rawData: Api.getRawFile(projectPath, path, { ref }).then(({ data }) => {
+ return data;
+ }),
+ };
+ },
+ },
+};
+
+export default resolvers;
diff --git a/app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql b/app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql
new file mode 100644
index 00000000000..f4f65262158
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql
@@ -0,0 +1,7 @@
+type BlobContent {
+ rawData: String!
+}
+
+extend type Query {
+ blobContent: BlobContent
+}
diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js
new file mode 100644
index 00000000000..ccd7b74064f
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/index.js
@@ -0,0 +1,34 @@
+import Vue from 'vue';
+
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import typeDefs from './graphql/typedefs.graphql';
+import { resolvers } from './graphql/resolvers';
+
+import PipelineEditorApp from './pipeline_editor_app.vue';
+
+export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
+ const el = document.querySelector(selector);
+
+ const { projectPath, defaultBranch, ciConfigPath } = el?.dataset;
+
+ Vue.use(VueApollo);
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(resolvers, { typeDefs }),
+ });
+
+ return new Vue({
+ el,
+ apolloProvider,
+ render(h) {
+ return h(PipelineEditorApp, {
+ props: {
+ projectPath,
+ defaultBranch,
+ ciConfigPath,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
new file mode 100644
index 00000000000..50b946af456
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -0,0 +1,108 @@
+<script>
+import { GlLoadingIcon, GlAlert, GlTabs, GlTab } from '@gitlab/ui';
+import { __, s__, sprintf } from '~/locale';
+
+import TextEditor from './components/text_editor.vue';
+import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
+
+import getBlobContent from './graphql/queries/blob_content.graphql';
+
+export default {
+ components: {
+ GlLoadingIcon,
+ GlAlert,
+ GlTabs,
+ GlTab,
+ TextEditor,
+ PipelineGraph,
+ },
+ props: {
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ defaultBranch: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ ciConfigPath: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ error: null,
+ content: '',
+ editorIsReady: false,
+ };
+ },
+ apollo: {
+ content: {
+ query: getBlobContent,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ path: this.ciConfigPath,
+ ref: this.defaultBranch,
+ };
+ },
+ update(data) {
+ return data?.blobContent?.rawData;
+ },
+ error(error) {
+ this.error = error;
+ },
+ },
+ },
+ computed: {
+ loading() {
+ return this.$apollo.queries.content.loading;
+ },
+ errorMessage() {
+ const { message: generalReason, networkError } = this.error ?? {};
+
+ const { data } = networkError?.response ?? {};
+ // 404 for missing file uses `message`
+ // 400 for a missing ref uses `error`
+ const networkReason = data?.message ?? data?.error;
+
+ const reason = networkReason ?? generalReason ?? this.$options.i18n.unknownError;
+ return sprintf(this.$options.i18n.errorMessageWithReason, { reason });
+ },
+ pipelineData() {
+ // Note data will loaded as part of https://gitlab.com/gitlab-org/gitlab/-/issues/263141
+ return {};
+ },
+ },
+ i18n: {
+ unknownError: __('Unknown Error'),
+ errorMessageWithReason: s__('Pipelines|CI file could not be loaded: %{reason}'),
+ tabEdit: s__('Pipelines|Write pipeline configuration'),
+ tabGraph: s__('Pipelines|Visualize'),
+ },
+};
+</script>
+
+<template>
+ <div class="gl-mt-4">
+ <gl-alert v-if="error" :dismissible="false" variant="danger">{{ errorMessage }}</gl-alert>
+ <div class="gl-mt-4">
+ <gl-loading-icon v-if="loading" size="lg" />
+ <div v-else class="file-editor">
+ <gl-tabs>
+ <!-- editor should be mounted when its tab is visible, so the container has a size -->
+ <gl-tab :title="$options.i18n.tabEdit" :lazy="!editorIsReady">
+ <!-- editor should be mounted only once, when the tab is displayed -->
+ <text-editor v-model="content" @editor-ready="editorIsReady = true" />
+ </gl-tab>
+
+ <gl-tab :title="$options.i18n.tabGraph">
+ <pipeline-graph :pipeline-data="pipelineData" />
+ </gl-tab>
+ </gl-tabs>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue b/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
index 20067f6646f..6552665100a 100644
--- a/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
+++ b/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
@@ -14,6 +14,7 @@ import {
GlDropdownItem,
GlSearchBoxByType,
GlSprintf,
+ GlLoadingIcon,
} from '@gitlab/ui';
import { s__, __, n__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
@@ -45,6 +46,7 @@ export default {
GlDropdownItem,
GlSearchBoxByType,
GlSprintf,
+ GlLoadingIcon,
},
props: {
pipelinesPath: {
@@ -96,6 +98,7 @@ export default {
warnings: [],
totalWarnings: 0,
isWarningDismissed: false,
+ isLoading: false,
};
},
computed: {
@@ -209,6 +212,8 @@ export default {
fetchConfigVariables(refValue) {
if (gon?.features?.newPipelineFormPrefilledVars) {
+ this.isLoading = true;
+
return axios
.get(this.configVariablesPath, {
params: {
@@ -226,6 +231,8 @@ export default {
}
});
+ this.isLoading = false;
+
return { params, descriptions };
});
}
@@ -324,7 +331,9 @@ export default {
>
</gl-form-group>
- <gl-form-group :label="s__('Pipeline|Variables')">
+ <gl-loading-icon v-if="isLoading" class="gl-mb-5" size="lg" />
+
+ <gl-form-group v-else :label="s__('Pipeline|Variables')">
<div
v-for="(variable, index) in variables"
:key="variable.uniqueId"
diff --git a/app/assets/javascripts/pipelines/components/dag/dag.vue b/app/assets/javascripts/pipelines/components/dag/dag.vue
index 6267b63328c..85171263f08 100644
--- a/app/assets/javascripts/pipelines/components/dag/dag.vue
+++ b/app/assets/javascripts/pipelines/components/dag/dag.vue
@@ -1,5 +1,5 @@
<script>
-import { GlAlert, GlButton, GlEmptyState, GlSprintf } from '@gitlab/ui';
+import { GlAlert, GlButton, GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { __ } from '~/locale';
import { fetchPolicies } from '~/lib/graphql';
@@ -17,11 +17,15 @@ export default {
DagAnnotations,
DagGraph,
GlAlert,
- GlSprintf,
- GlEmptyState,
GlButton,
+ GlEmptyState,
+ GlLink,
+ GlSprintf,
},
inject: {
+ aboutDagDocPath: {
+ default: null,
+ },
dagDocPath: {
default: null,
},
@@ -89,14 +93,14 @@ export default {
[DEFAULT]: __('An unknown error occurred while loading this graph.'),
},
emptyStateTexts: {
- title: __('Start using Directed Acyclic Graphs (DAG)'),
+ title: __('Speed up your pipelines with Needs relationships'),
firstDescription: __(
- "This pipeline does not use the %{codeStart}needs%{codeEnd} keyword and can't be represented as a directed acyclic graph.",
+ 'Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines.',
),
secondDescription: __(
- '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.',
+ "If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be able to view the %{codeStart}needs%{codeEnd} relationships between jobs in this tab as a %{linkStart}Directed Acyclic Graph (DAG)%{linkEnd}.",
),
- button: __('Learn more about job dependencies'),
+ button: __('Learn more about Needs relationships'),
},
computed: {
failure() {
@@ -222,6 +226,9 @@ export default {
<template #code="{ content }">
<code>{{ content }}</code>
</template>
+ <template #link="{ content }">
+ <gl-link :href="aboutDagDocPath">{{ content }}</gl-link>
+ </template>
</gl-sprintf>
</p>
</div>
diff --git a/app/assets/javascripts/pipelines/components/graph/constants.js b/app/assets/javascripts/pipelines/components/graph/constants.js
new file mode 100644
index 00000000000..ba1922b6dae
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/graph/constants.js
@@ -0,0 +1,3 @@
+export const DOWNSTREAM = 'downstream';
+export const MAIN = 'main';
+export const UPSTREAM = 'upstream';
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index 0f5a8cb8fbf..16ce279a591 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -5,6 +5,7 @@ import StageColumnComponent from './stage_column_component.vue';
import GraphWidthMixin from '../../mixins/graph_width_mixin';
import LinkedPipelinesColumn from './linked_pipelines_column.vue';
import GraphBundleMixin from '../../mixins/graph_pipeline_bundle_mixin';
+import { UPSTREAM, DOWNSTREAM, MAIN } from './constants';
export default {
name: 'PipelineGraph',
@@ -35,11 +36,11 @@ export default {
type: {
type: String,
required: false,
- default: 'main',
+ default: MAIN,
},
},
- upstream: 'upstream',
- downstream: 'downstream',
+ upstream: UPSTREAM,
+ downstream: DOWNSTREAM,
data() {
return {
downstreamMarginTop: null,
@@ -54,41 +55,41 @@ export default {
graph() {
return this.pipeline.details?.stages;
},
- hasTriggeredBy() {
+ hasUpstream() {
return (
this.type !== this.$options.downstream &&
- this.triggeredByPipelines &&
+ this.upstreamPipelines &&
this.pipeline.triggered_by !== null
);
},
- triggeredByPipelines() {
+ upstreamPipelines() {
return this.pipeline.triggered_by;
},
- hasTriggered() {
+ hasDownstream() {
return (
this.type !== this.$options.upstream &&
- this.triggeredPipelines &&
+ this.downstreamPipelines &&
this.pipeline.triggered.length > 0
);
},
- triggeredPipelines() {
+ downstreamPipelines() {
return this.pipeline.triggered;
},
- expandedTriggeredBy() {
+ expandedUpstream() {
return (
this.pipeline.triggered_by &&
Array.isArray(this.pipeline.triggered_by) &&
this.pipeline.triggered_by.find(el => el.isExpanded)
);
},
- expandedTriggered() {
+ expandedDownstream() {
return this.pipeline.triggered && this.pipeline.triggered.find(el => el.isExpanded);
},
pipelineTypeUpstream() {
- return this.type !== this.$options.downstream && this.expandedTriggeredBy;
+ return this.type !== this.$options.downstream && this.expandedUpstream;
},
pipelineTypeDownstream() {
- return this.type !== this.$options.upstream && this.expandedTriggered;
+ return this.type !== this.$options.upstream && this.expandedDownstream;
},
pipelineProjectId() {
return this.pipeline.project.id;
@@ -142,11 +143,11 @@ export default {
* and we want to reset the pipeline store. Triggering the reset without
* this condition would mean not allowing downstreams of downstreams to expand
*/
- if (this.expandedTriggered?.id !== pipeline.id) {
- this.$emit('onResetTriggered', this.pipeline, pipeline);
+ if (this.expandedDownstream?.id !== pipeline.id) {
+ this.$emit('onResetDownstream', this.pipeline, pipeline);
}
- this.$emit('onClickTriggered', pipeline);
+ this.$emit('onClickDownstreamPipeline', pipeline);
},
calculateMarginTop(downstreamNode, pixelDiff) {
return `${downstreamNode.offsetTop - downstreamNode.offsetParent.offsetTop - pixelDiff}px`;
@@ -154,8 +155,8 @@ export default {
hasOnlyOneJob(stage) {
return stage.groups.length === 1;
},
- hasUpstream(index) {
- return index === 0 && this.hasTriggeredBy;
+ hasUpstreamColumn(index) {
+ return index === 0 && this.hasUpstream;
},
setJob(jobName) {
this.jobName = jobName;
@@ -192,30 +193,30 @@ export default {
<pipeline-graph
v-if="pipelineTypeUpstream"
- type="upstream"
+ :type="$options.upstream"
class="d-inline-block upstream-pipeline"
- :class="`js-upstream-pipeline-${expandedTriggeredBy.id}`"
+ :class="`js-upstream-pipeline-${expandedUpstream.id}`"
:is-loading="false"
- :pipeline="expandedTriggeredBy"
+ :pipeline="expandedUpstream"
:is-linked-pipeline="true"
:mediator="mediator"
- @onClickTriggeredBy="clickTriggeredByPipeline"
+ @onClickUpstreamPipeline="clickUpstreamPipeline"
@refreshPipelineGraph="requestRefreshPipelineGraph"
/>
<linked-pipelines-column
- v-if="hasTriggeredBy"
- :linked-pipelines="triggeredByPipelines"
+ v-if="hasUpstream"
+ :type="$options.upstream"
+ :linked-pipelines="upstreamPipelines"
:column-title="__('Upstream')"
:project-id="pipelineProjectId"
- graph-position="left"
- @linkedPipelineClick="$emit('onClickTriggeredBy', $event)"
+ @linkedPipelineClick="$emit('onClickUpstreamPipeline', $event)"
/>
<ul
v-if="!isLoading"
:class="{
- 'inline js-has-linked-pipelines': hasTriggered || hasTriggeredBy,
+ 'inline js-has-linked-pipelines': hasDownstream || hasUpstream,
}"
class="stage-column-list align-top"
>
@@ -223,7 +224,7 @@ export default {
v-for="(stage, index) in graph"
:key="stage.name"
:class="{
- 'has-upstream gl-ml-11': hasUpstream(index),
+ 'has-upstream gl-ml-11': hasUpstreamColumn(index),
'has-only-one-job': hasOnlyOneJob(stage),
'gl-mr-26': shouldAddRightMargin(index),
}"
@@ -231,7 +232,7 @@ export default {
:groups="stage.groups"
:stage-connector-class="stageConnectorClass(index, stage)"
:is-first-column="isFirstColumn(index)"
- :has-triggered-by="hasTriggeredBy"
+ :has-upstream="hasUpstream"
:action="stage.status.action"
:job-hovered="jobName"
:pipeline-expanded="pipelineExpanded"
@@ -240,11 +241,11 @@ export default {
</ul>
<linked-pipelines-column
- v-if="hasTriggered"
- :linked-pipelines="triggeredPipelines"
+ v-if="hasDownstream"
+ :type="$options.downstream"
+ :linked-pipelines="downstreamPipelines"
:column-title="__('Downstream')"
:project-id="pipelineProjectId"
- graph-position="right"
@linkedPipelineClick="handleClickedDownstream"
@downstreamHovered="setJob"
@pipelineExpandToggle="setPipelineExpanded"
@@ -252,15 +253,15 @@ export default {
<pipeline-graph
v-if="pipelineTypeDownstream"
- type="downstream"
+ :type="$options.downstream"
class="d-inline-block"
- :class="`js-downstream-pipeline-${expandedTriggered.id}`"
+ :class="`js-downstream-pipeline-${expandedDownstream.id}`"
:is-loading="false"
- :pipeline="expandedTriggered"
+ :pipeline="expandedDownstream"
:is-linked-pipeline="true"
:style="{ 'margin-top': downstreamMarginTop }"
:mediator="mediator"
- @onClickTriggered="clickTriggeredPipeline"
+ @onClickDownstreamPipeline="clickDownstreamPipeline"
@refreshPipelineGraph="requestRefreshPipelineGraph"
/>
</div>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
index 7aee2573ce1..4ed0aae0d1e 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -119,6 +119,9 @@ export default {
},
},
methods: {
+ hideTooltips() {
+ this.$root.$emit('bv::hide::tooltip');
+ },
pipelineActionRequestComplete() {
this.$emit('pipelineActionRequestComplete');
},
@@ -129,24 +132,26 @@ export default {
<div class="ci-job-component" data-qa-selector="job_item_container">
<gl-link
v-if="status.has_details"
- v-gl-tooltip="{ boundary, placement: 'bottom' }"
+ v-gl-tooltip="{ boundary, placement: 'bottom', customClass: 'gl-pointer-events-none' }"
:href="status.details_path"
:title="tooltipText"
:class="jobClasses"
class="js-pipeline-graph-job-link qa-job-link menu-item"
data-testid="job-with-link"
- @click.stop
+ @click.stop="hideTooltips"
+ @mouseout="hideTooltips"
>
<job-name-component :name="job.name" :status="job.status" />
</gl-link>
<div
v-else
- v-gl-tooltip="{ boundary, placement: 'bottom' }"
+ v-gl-tooltip="{ boundary, placement: 'bottom', customClass: 'gl-pointer-events-none' }"
:title="tooltipText"
:class="jobClasses"
class="js-job-component-tooltip non-details-job-component"
data-testid="job-without-link"
+ @mouseout="hideTooltips"
>
<job-name-component :name="job.name" :status="job.status" />
</div>
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
index e359fc787c5..11f06a25984 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
@@ -2,6 +2,7 @@
import { GlTooltipDirective, GlButton, GlLink, GlLoadingIcon } from '@gitlab/ui';
import CiStatus from '~/vue_shared/components/ci_icon.vue';
import { __, sprintf } from '~/locale';
+import { UPSTREAM, DOWNSTREAM } from './constants';
export default {
directives: {
@@ -14,6 +15,10 @@ export default {
GlLoadingIcon,
},
props: {
+ columnTitle: {
+ type: String,
+ required: true,
+ },
pipeline: {
type: Object,
required: true,
@@ -22,7 +27,7 @@ export default {
type: Number,
required: true,
},
- columnTitle: {
+ type: {
type: String,
required: true,
},
@@ -50,12 +55,10 @@ export default {
return this.childPipeline ? __('child-pipeline') : this.pipeline.project.name;
},
parentPipeline() {
- // Refactor string match when BE returns Upstream/Downstream indicators
- return this.projectId === this.pipeline.project.id && this.columnTitle === __('Upstream');
+ return this.isUpstream && this.isSameProject;
},
childPipeline() {
- // Refactor string match when BE returns Upstream/Downstream indicators
- return this.projectId === this.pipeline.project.id && this.isDownstream;
+ return this.isDownstream && this.isSameProject;
},
label() {
if (this.parentPipeline) {
@@ -66,7 +69,13 @@ export default {
return __('Multi-project');
},
isDownstream() {
- return this.columnTitle === __('Downstream');
+ return this.type === DOWNSTREAM;
+ },
+ isUpstream() {
+ return this.type === UPSTREAM;
+ },
+ isSameProject() {
+ return this.projectId === this.pipeline.project.id;
},
sourceJobInfo() {
return this.isDownstream
@@ -74,13 +83,13 @@ export default {
: '';
},
expandedIcon() {
- if (this.parentPipeline) {
+ if (this.isUpstream) {
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!';
+ return this.isUpstream ? 'gl-left-0 gl-border-r-1!' : 'gl-right-0 gl-border-l-1!';
},
},
methods: {
@@ -116,7 +125,7 @@ export default {
>
<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 }"
+ :class="{ 'gl-pl-9': isUpstream }"
>
<div class="gl-display-flex">
<ci-status
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 3ad28d88345..2ca33e6d33e 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
@@ -1,6 +1,6 @@
<script>
import LinkedPipeline from './linked_pipeline.vue';
-import { __ } from '~/locale';
+import { UPSTREAM } from './constants';
export default {
components: {
@@ -15,7 +15,7 @@ export default {
type: Array,
required: true,
},
- graphPosition: {
+ type: {
type: String,
required: true,
},
@@ -32,9 +32,12 @@ export default {
};
return `graph-position-${this.graphPosition} ${positionValues[this.graphPosition]}`;
},
+ graphPosition() {
+ return this.isUpstream ? 'left' : 'right';
+ },
// Refactor string match when BE returns Upstream/Downstream indicators
isUpstream() {
- return this.columnTitle === __('Upstream');
+ return this.type === UPSTREAM;
},
},
methods: {
@@ -45,6 +48,11 @@ export default {
this.$emit('downstreamHovered', jobName);
},
onPipelineExpandToggle(jobName, expanded) {
+ // Highlighting only applies to downstream pipelines
+ if (this.isUpstream) {
+ return;
+ }
+
this.$emit('pipelineExpandToggle', jobName, expanded);
},
},
@@ -66,6 +74,7 @@ export default {
:pipeline="pipeline"
:column-title="columnTitle"
:project-id="projectId"
+ :type="type"
@pipelineClicked="onPipelineClick($event, pipeline, index)"
@downstreamHovered="onDownstreamHovered"
@pipelineExpandToggle="onPipelineExpandToggle"
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
index b26f28fa6af..741609c908a 100644
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ b/app/assets/javascripts/pipelines/components/header_component.vue
@@ -1,16 +1,22 @@
<script>
import { GlAlert, GlButton, GlLoadingIcon, GlModal, GlModalDirective } from '@gitlab/ui';
import { __ } from '~/locale';
-import axios from '~/lib/utils/axios_utils';
import ciHeader from '~/vue_shared/components/header_ci_component.vue';
import { setUrlFragment, redirectTo } from '~/lib/utils/url_utility';
import getPipelineQuery from '../graphql/queries/get_pipeline_header_data.query.graphql';
+import deletePipelineMutation from '../graphql/mutations/delete_pipeline.mutation.graphql';
+import retryPipelineMutation from '../graphql/mutations/retry_pipeline.mutation.graphql';
+import cancelPipelineMutation from '../graphql/mutations/cancel_pipeline.mutation.graphql';
import { LOAD_FAILURE, POST_FAILURE, DELETE_FAILURE, DEFAULT } from '../constants';
const DELETE_MODAL_ID = 'pipeline-delete-modal';
+const POLL_INTERVAL = 10000;
export default {
name: 'PipelineHeaderSection',
+ pipelineCancel: 'pipelineCancel',
+ pipelineRetry: 'pipelineRetry',
+ finishedStatuses: ['FAILED', 'SUCCESS', 'CANCELED'],
components: {
ciHeader,
GlAlert,
@@ -28,7 +34,7 @@ export default {
[DEFAULT]: __('An unknown error occurred.'),
},
inject: {
- // Receive `cancel`, `delete`, `fullProject` and `retry`
+ // Receive `fullProject` and `pipelinesPath`
paths: {
default: {},
},
@@ -52,7 +58,7 @@ export default {
error() {
this.reportFailure(LOAD_FAILURE);
},
- pollInterval: 10000,
+ pollInterval: POLL_INTERVAL,
watchLoading(isLoading) {
if (!isLoading) {
// To ensure apollo has updated the cache,
@@ -90,6 +96,9 @@ export default {
status() {
return this.pipeline?.status;
},
+ isFinished() {
+ return this.$options.finishedStatuses.includes(this.status);
+ },
shouldRenderContent() {
return !this.isLoadingInitialQuery && this.hasPipelineData;
},
@@ -118,35 +127,72 @@ export default {
}
},
},
+ watch: {
+ isFinished(finished) {
+ if (finished) {
+ this.$apollo.queries.pipeline.stopPolling();
+ }
+ },
+ },
methods: {
reportFailure(errorType) {
this.failureType = errorType;
},
- async postAction(path) {
+ async postPipelineAction(name, mutation) {
try {
- await axios.post(path);
- this.$apollo.queries.pipeline.refetch();
+ const {
+ data: {
+ [name]: { errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation,
+ variables: { id: this.pipeline.id },
+ });
+
+ if (errors.length > 0) {
+ this.reportFailure(POST_FAILURE);
+ } else {
+ await this.$apollo.queries.pipeline.refetch();
+ if (!this.isFinished) {
+ this.$apollo.queries.pipeline.startPolling(POLL_INTERVAL);
+ }
+ }
} catch {
this.reportFailure(POST_FAILURE);
}
},
- async cancelPipeline() {
+ cancelPipeline() {
this.isCanceling = true;
- this.postAction(this.paths.cancel);
+ this.postPipelineAction(this.$options.pipelineCancel, cancelPipelineMutation);
},
- async retryPipeline() {
+ retryPipeline() {
this.isRetrying = true;
- this.postAction(this.paths.retry);
+ this.postPipelineAction(this.$options.pipelineRetry, retryPipelineMutation);
},
async deletePipeline() {
this.isDeleting = true;
this.$apollo.queries.pipeline.stopPolling();
try {
- const { request } = await axios.delete(this.paths.delete);
- redirectTo(setUrlFragment(request.responseURL, 'delete_success'));
+ const {
+ data: {
+ pipelineDestroy: { errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation: deletePipelineMutation,
+ variables: {
+ id: this.pipeline.id,
+ },
+ });
+
+ if (errors.length > 0) {
+ this.reportFailure(DELETE_FAILURE);
+ this.isDeleting = false;
+ } else {
+ redirectTo(setUrlFragment(this.paths.pipelinesPath, 'delete_success'));
+ }
} catch {
- this.$apollo.queries.pipeline.startPolling();
+ this.$apollo.queries.pipeline.startPolling(POLL_INTERVAL);
this.reportFailure(DELETE_FAILURE);
this.isDeleting = false;
}
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
index 8eec0110865..a0c35f54c0e 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
@@ -57,7 +57,7 @@ export default {
<tooltip-on-truncate :title="jobName" truncate-target="child" placement="top">
<div
:id="jobId"
- class="pipeline-job-pill gl-bg-white gl-text-center gl-text-truncate gl-rounded-pill gl-mb-3 gl-px-5 gl-py-2 gl-relative gl-z-index-1 gl-transition-duration-slow gl-transition-timing-function-ease"
+ class="gl-w-15 gl-bg-white gl-text-center gl-text-truncate gl-rounded-pill gl-mb-3 gl-px-5 gl-py-2 gl-relative gl-z-index-1 gl-transition-duration-slow gl-transition-timing-function-ease"
:class="jobPillClasses"
@mouseover="onMouseEnter"
@mouseleave="onMouseLeave"
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
index 3a2b8a20bae..11ad2f2a3b6 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
@@ -97,15 +97,20 @@ export default {
this.reportFailure(DRAW_FAILURE);
}
},
- getStageBackgroundClass(index) {
+ getStageBackgroundClasses(index) {
const { length } = this.pipelineData.stages;
-
+ // It's possible for a graph to have only one stage, in which
+ // case we concatenate both the left and right rounding classes
if (length === 1) {
- return 'stage-rounded';
- } else if (index === 0) {
- return 'stage-left-rounded';
- } else if (index === length - 1) {
- return 'stage-right-rounded';
+ return 'gl-rounded-bottom-left-6 gl-rounded-top-left-6 gl-rounded-bottom-right-6 gl-rounded-top-right-6';
+ }
+
+ if (index === 0) {
+ return 'gl-rounded-bottom-left-6 gl-rounded-top-left-6';
+ }
+
+ if (index === length - 1) {
+ return 'gl-rounded-bottom-right-6 gl-rounded-top-right-6';
}
return '';
@@ -162,7 +167,11 @@ export default {
{{ failure.text }}
</gl-alert>
<gl-alert v-if="isPipelineDataEmpty" variant="tip" :dismissible="false">
- {{ __('No content to show') }}
+ {{
+ __(
+ 'The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax.',
+ )
+ }}
</gl-alert>
<div
v-else
@@ -190,7 +199,8 @@ export default {
>
<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="getStageBackgroundClass(index)"
+ :class="getStageBackgroundClasses(index)"
+ data-testid="stage-background"
>
<stage-pill :stage-name="stage.name" :is-empty="stage.groups.length === 0" />
</div>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/stage_pill.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/stage_pill.vue
index 7b2458db725..df48426f24e 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/stage_pill.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/stage_pill.vue
@@ -26,7 +26,7 @@ export default {
<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="gl-px-5 gl-py-2 gl-text-white gl-text-center gl-text-truncate gl-rounded-pill gl-w-20"
:class="emptyClass"
>
{{ stageName }}
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
index adba86d384b..9ee427d01fd 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
@@ -13,7 +13,6 @@ import CIPaginationMixin from '~/vue_shared/mixins/ci_pagination_api_mixin';
import PipelinesFilteredSearch from './pipelines_filtered_search.vue';
import { validateParams } from '../../utils';
import { ANY_TRIGGER_AUTHOR, RAW_TEXT_WARNING, FILTER_TAG_IDENTIFIER } from '../../constants';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
components: {
@@ -23,7 +22,7 @@ export default {
PipelinesFilteredSearch,
GlIcon,
},
- mixins: [pipelinesMixin, CIPaginationMixin, glFeatureFlagsMixin()],
+ mixins: [pipelinesMixin, CIPaginationMixin],
props: {
store: {
type: Object,
@@ -209,9 +208,6 @@ export default {
},
];
},
- canFilterPipelines() {
- return this.glFeatures.filterPipelinesSearch;
- },
validatedParams() {
return validateParams(this.params);
},
@@ -306,7 +302,6 @@ export default {
</div>
<pipelines-filtered-search
- v-if="canFilterPipelines"
:project-id="projectId"
:params="validatedParams"
@filterPipelines="filterPipelines"
@@ -342,7 +337,7 @@ export default {
:message="emptyTabMessage"
/>
- <div v-else-if="stateToRender === $options.stateMap.tableList" class="table-holder">
+ <div v-else-if="stateToRender === $options.stateMap.tableList">
<pipelines-table-component
:pipelines="state.pipelines"
:pipeline-schedule-url="pipelineScheduleUrl"
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 97595e5d2ce..e52afe08336 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue
@@ -87,7 +87,7 @@ export default {
:aria-label="__('Run manual or delayed jobs')"
>
<gl-icon name="play" class="icon-play" />
- <i class="fa fa-caret-down" aria-hidden="true"></i>
+ <gl-icon name="chevron-down" />
<gl-loading-icon v-if="isLoading" />
</button>
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 4a3d134685e..55c71e299be 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
@@ -29,7 +29,7 @@ export default {
:aria-label="__('Artifacts')"
>
<gl-icon name="download" />
- <i class="fa fa-caret-down" aria-hidden="true"></i>
+ <gl-icon name="chevron-down" />
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li v-for="(artifact, i) in artifacts" :key="i">
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue b/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue
index 4045f450104..581ea5fbb35 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue
@@ -168,7 +168,7 @@ export default {
aria-expanded="false"
@click="onClickStage"
>
- <span :aria-label="stage.title" aria-hidden="true" class="no-pointer-events">
+ <span :aria-label="stage.title" aria-hidden="true" class="gl-pointer-events-none">
<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 dd09247337c..1d117cfe34a 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
@@ -1,6 +1,5 @@
<script>
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
-import '~/lib/utils/datetime_utility';
import timeagoMixin from '~/vue_shared/mixins/timeago';
export default {
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue b/app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue
new file mode 100644
index 00000000000..504cf138d07
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue
@@ -0,0 +1,67 @@
+<script>
+import { GlModal } from '@gitlab/ui';
+import { __ } from '~/locale';
+import CodeBlock from '~/vue_shared/components/code_block.vue';
+
+export default {
+ name: 'TestCaseDetails',
+ components: {
+ CodeBlock,
+ GlModal,
+ },
+ props: {
+ modalId: {
+ type: String,
+ required: true,
+ },
+ testCase: {
+ type: Object,
+ required: true,
+ validator: ({ classname, formattedTime, name }) =>
+ Boolean(classname) && Boolean(formattedTime) && Boolean(name),
+ },
+ },
+ text: {
+ name: __('Name'),
+ duration: __('Execution time'),
+ trace: __('System output'),
+ },
+ modalCloseButton: {
+ text: __('Close'),
+ attributes: [{ variant: 'info' }],
+ },
+};
+</script>
+
+<template>
+ <gl-modal
+ :modal-id="modalId"
+ :title="testCase.classname"
+ :action-primary="$options.modalCloseButton"
+ >
+ <div class="gl-display-flex gl-flex-wrap gl-mx-n4 gl-my-3">
+ <strong class="gl-text-right col-sm-3">{{ $options.text.name }}</strong>
+ <div class="col-sm-9" data-testid="test-case-name">
+ {{ testCase.name }}
+ </div>
+ </div>
+
+ <div class="gl-display-flex gl-flex-wrap gl-mx-n4 gl-my-3">
+ <strong class="gl-text-right col-sm-3">{{ $options.text.duration }}</strong>
+ <div class="col-sm-9" data-testid="test-case-duration">
+ {{ testCase.formattedTime }}
+ </div>
+ </div>
+
+ <div
+ v-if="testCase.system_output"
+ class="gl-display-flex gl-flex-wrap gl-mx-n4 gl-my-3"
+ data-testid="test-case-trace"
+ >
+ <strong class="gl-text-right col-sm-3">{{ $options.text.trace }}</strong>
+ <div class="col-sm-9">
+ <code-block :code="testCase.system_output" />
+ </div>
+ </div>
+ </gl-modal>
+</template>
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 c3398e90895..a56dcf48d92 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue
@@ -61,7 +61,7 @@ export default {
<div
v-else-if="!isLoading && showTests"
ref="container"
- class="tests-detail position-relative"
+ class="position-relative"
data-testid="tests-detail"
>
<transition
@@ -69,13 +69,13 @@ export default {
@before-enter="beforeEnterTransition"
@after-leave="afterLeaveTransition"
>
- <div v-if="showSuite" key="detail" class="w-100 position-absolute slide-enter-to-element">
+ <div v-if="showSuite" key="detail" class="w-100 slide-enter-to-element">
<test-summary :report="getSelectedSuite" show-back @on-back-click="summaryBackClick" />
<test-suite-table />
</div>
- <div v-else key="summary" class="w-100 position-absolute slide-enter-from-element">
+ <div v-else key="summary" class="w-100 slide-enter-from-element">
<test-summary :report="testReports" />
<test-summary-table @row-click="summaryTableRowClick" />
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 2b92ffc3f26..7afbb59cbd6 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,7 +1,8 @@
<script>
import { mapGetters } from 'vuex';
-import { GlTooltipDirective, GlFriendlyWrap, GlIcon, GlButton } from '@gitlab/ui';
+import { GlModalDirective, GlTooltipDirective, GlFriendlyWrap, GlIcon, GlButton } from '@gitlab/ui';
import { __ } from '~/locale';
+import TestCaseDetails from './test_case_details.vue';
export default {
name: 'TestsSuiteTable',
@@ -9,9 +10,11 @@ export default {
GlIcon,
GlFriendlyWrap,
GlButton,
+ TestCaseDetails,
},
directives: {
GlTooltip: GlTooltipDirective,
+ GlModalDirective,
},
props: {
heading: {
@@ -43,7 +46,7 @@ export default {
<div role="rowheader" class="table-section section-20">
{{ __('Suite') }}
</div>
- <div role="rowheader" class="table-section section-20">
+ <div role="rowheader" class="table-section section-40">
{{ __('Name') }}
</div>
<div role="rowheader" class="table-section section-10">
@@ -52,12 +55,12 @@ export default {
<div role="rowheader" class="table-section section-10 text-center">
{{ __('Status') }}
</div>
- <div role="rowheader" class="table-section flex-grow-1">
- {{ __('Trace'), }}
- </div>
- <div role="rowheader" class="table-section section-10 text-right">
+ <div role="rowheader" class="table-section section-10">
{{ __('Duration') }}
</div>
+ <div role="rowheader" class="table-section section-10">
+ {{ __('Details'), }}
+ </div>
</div>
<div
@@ -72,7 +75,7 @@ export default {
</div>
</div>
- <div class="table-section section-20 section-wrap">
+ <div class="table-section section-40 section-wrap">
<div role="rowheader" class="table-mobile-header">{{ __('Name') }}</div>
<div class="table-mobile-content gl-md-pr-2 gl-overflow-wrap-break">
<gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.name" />
@@ -107,24 +110,24 @@ export default {
</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>
-
<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">
+ <div class="table-mobile-content pr-sm-1">
{{ testCase.formattedTime }}
</div>
</div>
+
+ <div class="table-section section-10 section-wrap">
+ <div role="rowheader" class="table-mobile-header">{{ __('Details'), }}</div>
+ <div class="table-mobile-content">
+ <gl-button v-gl-modal-directive="`test-case-details-${index}`">{{
+ __('View details')
+ }}</gl-button>
+ <test-case-details :modal-id="`test-case-details-${index}`" :test-case="testCase" />
+ </div>
+ </div>
</div>
</div>
diff --git a/app/assets/javascripts/pipelines/graphql/mutations/cancel_pipeline.mutation.graphql b/app/assets/javascripts/pipelines/graphql/mutations/cancel_pipeline.mutation.graphql
new file mode 100644
index 00000000000..9afb474cb17
--- /dev/null
+++ b/app/assets/javascripts/pipelines/graphql/mutations/cancel_pipeline.mutation.graphql
@@ -0,0 +1,5 @@
+mutation cancelPipeline($id: CiPipelineID!) {
+ pipelineCancel(input: { id: $id }) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/pipelines/graphql/mutations/delete_pipeline.mutation.graphql b/app/assets/javascripts/pipelines/graphql/mutations/delete_pipeline.mutation.graphql
new file mode 100644
index 00000000000..a52cecafcaf
--- /dev/null
+++ b/app/assets/javascripts/pipelines/graphql/mutations/delete_pipeline.mutation.graphql
@@ -0,0 +1,5 @@
+mutation deletePipeline($id: CiPipelineID!) {
+ pipelineDestroy(input: { id: $id }) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/pipelines/graphql/mutations/retry_pipeline.mutation.graphql b/app/assets/javascripts/pipelines/graphql/mutations/retry_pipeline.mutation.graphql
new file mode 100644
index 00000000000..2b3b0822653
--- /dev/null
+++ b/app/assets/javascripts/pipelines/graphql/mutations/retry_pipeline.mutation.graphql
@@ -0,0 +1,5 @@
+mutation retryPipeline($id: CiPipelineID!) {
+ pipelineRetry(input: { id: $id }) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/pipelines/mixins/graph_pipeline_bundle_mixin.js b/app/assets/javascripts/pipelines/mixins/graph_pipeline_bundle_mixin.js
index 886a8a78448..bd1b1664a1e 100644
--- a/app/assets/javascripts/pipelines/mixins/graph_pipeline_bundle_mixin.js
+++ b/app/assets/javascripts/pipelines/mixins/graph_pipeline_bundle_mixin.js
@@ -41,13 +41,13 @@ export default {
this.mediator.poll.enable({ data: this.mediator.getExpandedParameters() });
}
},
- resetTriggeredPipelines(parentPipeline, pipeline) {
+ resetDownstreamPipelines(parentPipeline, pipeline) {
this.mediator.store.resetTriggeredPipelines(parentPipeline, pipeline);
},
- clickTriggeredByPipeline(pipeline) {
+ clickUpstreamPipeline(pipeline) {
this.clickPipeline(pipeline, 'openPipeline', 'closePipeline');
},
- clickTriggeredPipeline(pipeline) {
+ clickDownstreamPipeline(pipeline) {
this.clickPipeline(pipeline, 'openPipeline', 'closePipeline');
},
requestRefreshPipelineGraph() {
diff --git a/app/assets/javascripts/pipelines/mixins/stage_column_mixin.js b/app/assets/javascripts/pipelines/mixins/stage_column_mixin.js
index 3f3007ba11a..578ff498358 100644
--- a/app/assets/javascripts/pipelines/mixins/stage_column_mixin.js
+++ b/app/assets/javascripts/pipelines/mixins/stage_column_mixin.js
@@ -1,6 +1,6 @@
export default {
props: {
- hasTriggeredBy: {
+ hasUpstream: {
type: Boolean,
required: false,
default: false,
@@ -8,7 +8,7 @@ export default {
},
methods: {
buildConnnectorClass(index) {
- return index === 0 && (!this.isFirstColumn || this.hasTriggeredBy) ? 'left-connector' : '';
+ return index === 0 && (!this.isFirstColumn || this.hasUpstream) ? 'left-connector' : '';
},
},
};
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index 67aec12655a..29dec2309a7 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -6,12 +6,10 @@ import { setUrlFragment, redirectTo } from '~/lib/utils/url_utility';
import pipelineGraph from './components/graph/graph_component.vue';
import createDagApp from './pipeline_details_dag';
import GraphBundleMixin from './mixins/graph_pipeline_bundle_mixin';
-import PipelinesMediator from './pipeline_details_mediator';
import legacyPipelineHeader from './components/legacy_header_component.vue';
import eventHub from './event_hub';
import TestReports from './components/test_reports/test_reports.vue';
import createTestReportsStore from './stores/test_reports';
-import { createPipelineHeaderApp } from './pipeline_details_header';
Vue.use(Translate);
@@ -22,7 +20,7 @@ const SELECTORS = {
PIPELINE_TESTS: '#js-pipeline-tests-detail',
};
-const createPipelinesDetailApp = mediator => {
+const createLegacyPipelinesDetailApp = mediator => {
if (!document.querySelector(SELECTORS.PIPELINE_GRAPH)) {
return;
}
@@ -47,10 +45,10 @@ const createPipelinesDetailApp = mediator => {
},
on: {
refreshPipelineGraph: this.requestRefreshPipelineGraph,
- onResetTriggered: (parentPipeline, pipeline) =>
- this.resetTriggeredPipelines(parentPipeline, pipeline),
- onClickTriggeredBy: pipeline => this.clickTriggeredByPipeline(pipeline),
- onClickTriggered: pipeline => this.clickTriggeredPipeline(pipeline),
+ onResetDownstream: (parentPipeline, pipeline) =>
+ this.resetDownstreamPipelines(parentPipeline, pipeline),
+ onClickUpstreamPipeline: pipeline => this.clickUpstreamPipeline(pipeline),
+ onClickDownstreamPipeline: pipeline => this.clickDownstreamPipeline(pipeline),
},
});
},
@@ -127,18 +125,48 @@ const createTestDetails = () => {
});
};
-export default () => {
+export default async function() {
+ createTestDetails();
+ createDagApp();
+
const { dataset } = document.querySelector(SELECTORS.PIPELINE_DETAILS);
- const mediator = new PipelinesMediator({ endpoint: dataset.endpoint });
- mediator.fetchPipeline();
+ let mediator;
+
+ if (!gon.features.graphqlPipelineHeader || !gon.features.graphqlPipelineDetails) {
+ try {
+ const { default: PipelinesMediator } = await import(
+ /* webpackChunkName: 'PipelinesMediator' */ './pipeline_details_mediator'
+ );
+ mediator = new PipelinesMediator({ endpoint: dataset.endpoint });
+ mediator.fetchPipeline();
+ } catch {
+ Flash(__('An error occurred while loading the pipeline.'));
+ }
+ }
- createPipelinesDetailApp(mediator);
+ if (gon.features.graphqlPipelineDetails) {
+ try {
+ const { createPipelinesDetailApp } = await import(
+ /* webpackChunkName: 'createPipelinesDetailApp' */ './pipeline_details_graph'
+ );
+ createPipelinesDetailApp();
+ } catch {
+ Flash(__('An error occurred while loading the pipeline.'));
+ }
+ } else {
+ createLegacyPipelinesDetailApp(mediator);
+ }
if (gon.features.graphqlPipelineHeader) {
- createPipelineHeaderApp(SELECTORS.PIPELINE_HEADER);
+ try {
+ const { createPipelineHeaderApp } = await import(
+ /* webpackChunkName: 'createPipelineHeaderApp' */ './pipeline_details_header'
+ );
+ createPipelineHeaderApp(SELECTORS.PIPELINE_HEADER);
+ } catch {
+ Flash(__('An error occurred while loading a section of this page.'));
+ }
} else {
createLegacyPipelineHeaderApp(mediator);
}
- createTestDetails();
- createDagApp();
-};
+}
diff --git a/app/assets/javascripts/pipelines/pipeline_details_dag.js b/app/assets/javascripts/pipelines/pipeline_details_dag.js
index dc03b457265..d37c72a4f2a 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_dag.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_dag.js
@@ -10,12 +10,19 @@ const apolloProvider = new VueApollo({
});
const createDagApp = () => {
- if (!window.gon?.features?.dagPipelineTab) {
+ const el = document.querySelector('#js-pipeline-dag-vue');
+
+ if (!window.gon?.features?.dagPipelineTab || !el) {
return;
}
- const el = document.querySelector('#js-pipeline-dag-vue');
- const { pipelineProjectPath, pipelineIid, emptySvgPath, dagDocPath } = el?.dataset;
+ const {
+ aboutDagDocPath,
+ dagDocPath,
+ emptySvgPath,
+ pipelineProjectPath,
+ pipelineIid,
+ } = el?.dataset;
// eslint-disable-next-line no-new
new Vue({
@@ -25,10 +32,11 @@ const createDagApp = () => {
},
apolloProvider,
provide: {
+ aboutDagDocPath,
+ dagDocPath,
+ emptySvgPath,
pipelineProjectPath,
pipelineIid,
- emptySvgPath,
- dagDocPath,
},
render(createElement) {
return createElement('dag', {});
diff --git a/app/assets/javascripts/pipelines/pipeline_details_graph.js b/app/assets/javascripts/pipelines/pipeline_details_graph.js
new file mode 100644
index 00000000000..880855cf21d
--- /dev/null
+++ b/app/assets/javascripts/pipelines/pipeline_details_graph.js
@@ -0,0 +1,7 @@
+const createPipelinesDetailApp = () => {
+ // Placeholder. See: https://gitlab.com/gitlab-org/gitlab/-/issues/223262
+ // eslint-disable-next-line no-useless-return
+ return;
+};
+
+export { createPipelinesDetailApp };
diff --git a/app/assets/javascripts/pipelines/pipeline_details_header.js b/app/assets/javascripts/pipelines/pipeline_details_header.js
index 27fe9ba3f19..744a8272709 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_header.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_header.js
@@ -16,7 +16,7 @@ export const createPipelineHeaderApp = elSelector => {
return;
}
- const { cancelPath, deletePath, fullPath, pipelineId, pipelineIid, retryPath } = el?.dataset;
+ const { fullPath, pipelineId, pipelineIid, pipelinesPath } = el?.dataset;
// eslint-disable-next-line no-new
new Vue({
el,
@@ -26,10 +26,8 @@ export const createPipelineHeaderApp = elSelector => {
apolloProvider,
provide: {
paths: {
- cancel: cancelPath,
- delete: deletePath,
fullProject: fullPath,
- retry: retryPath,
+ pipelinesPath,
},
pipelineId,
pipelineIid,
diff --git a/app/assets/javascripts/popovers/components/popovers.vue b/app/assets/javascripts/popovers/components/popovers.vue
new file mode 100644
index 00000000000..3bb6d284264
--- /dev/null
+++ b/app/assets/javascripts/popovers/components/popovers.vue
@@ -0,0 +1,92 @@
+<script>
+// We can't use v-safe-html here as the popover's title or content might contains SVGs that would
+// be stripped by the directive's sanitizer. Instead, we fallback on v-html and we use GitLab's
+// dompurify config that lets SVGs be rendered properly.
+// Context: https://gitlab.com/gitlab-org/gitlab/-/issues/247207
+/* eslint-disable vue/no-v-html */
+import { GlPopover } from '@gitlab/ui';
+import { sanitize } from '~/lib/dompurify';
+
+const newPopover = element => {
+ const { content, html, placement, title, triggers = 'focus' } = element.dataset;
+
+ return {
+ target: element,
+ content,
+ html,
+ placement,
+ title,
+ triggers,
+ };
+};
+
+export default {
+ components: {
+ GlPopover,
+ },
+ data() {
+ return {
+ popovers: [],
+ };
+ },
+ created() {
+ this.observer = new MutationObserver(mutations => {
+ mutations.forEach(mutation => {
+ mutation.removedNodes.forEach(this.dispose);
+ });
+ });
+ },
+ beforeDestroy() {
+ this.observer.disconnect();
+ },
+ methods: {
+ addPopovers(elements) {
+ const newPopovers = elements.reduce((acc, element) => {
+ if (this.popoverExists(element)) {
+ return acc;
+ }
+ const popover = newPopover(element);
+ this.observe(popover);
+ return [...acc, popover];
+ }, []);
+
+ this.popovers.push(...newPopovers);
+ },
+ observe(popover) {
+ this.observer.observe(popover.target.parentElement, {
+ childList: true,
+ });
+ },
+ dispose(target) {
+ if (!target) {
+ this.popovers = [];
+ } else {
+ const index = this.popovers.findIndex(popover => popover.target === target);
+
+ if (index > -1) {
+ this.popovers.splice(index, 1);
+ }
+ }
+ },
+ popoverExists(element) {
+ return this.popovers.some(popover => popover.target === element);
+ },
+ getSafeHtml(html) {
+ return sanitize(html);
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-popover v-for="(popover, index) in popovers" :key="index" v-bind="popover">
+ <template #title>
+ <span v-if="popover.html" v-html="getSafeHtml(popover.title)"></span>
+ <span v-else>{{ popover.title }}</span>
+ </template>
+ <span v-if="popover.html" v-html="getSafeHtml(popover.content)"></span>
+ <span v-else>{{ popover.content }}</span>
+ </gl-popover>
+ </div>
+</template>
diff --git a/app/assets/javascripts/popovers/index.js b/app/assets/javascripts/popovers/index.js
new file mode 100644
index 00000000000..bfb61f02a3a
--- /dev/null
+++ b/app/assets/javascripts/popovers/index.js
@@ -0,0 +1,51 @@
+import Vue from 'vue';
+import { toArray } from 'lodash';
+import PopoversComponent from './components/popovers.vue';
+
+let app;
+
+const APP_ELEMENT_ID = 'gl-popovers-app';
+
+const getPopoversApp = () => {
+ if (!app) {
+ const container = document.createElement('div');
+ container.setAttribute('id', APP_ELEMENT_ID);
+ document.body.appendChild(container);
+
+ const Popovers = Vue.extend(PopoversComponent);
+ app = new Popovers();
+ app.$mount(`#${APP_ELEMENT_ID}`);
+ }
+
+ return app;
+};
+
+const isPopover = (node, selector) => node.matches && node.matches(selector);
+
+const handlePopoverEvent = (rootTarget, e, selector) => {
+ for (let { target } = e; target && target !== rootTarget; target = target.parentNode) {
+ if (isPopover(target, selector)) {
+ getPopoversApp().addPopovers([target]);
+ break;
+ }
+ }
+};
+
+export const initPopovers = () => {
+ ['mouseenter', 'focus', 'click'].forEach(event => {
+ document.addEventListener(
+ event,
+ e => handlePopoverEvent(document, e, '[data-toggle="popover"]'),
+ true,
+ );
+ });
+
+ return getPopoversApp();
+};
+
+export const dispose = elements => toArray(elements).forEach(getPopoversApp().dispose);
+
+export const destroy = () => {
+ getPopoversApp().$destroy();
+ app = null;
+};
diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue
index 200e5ba255f..5feac7485ad 100644
--- a/app/assets/javascripts/profile/account/components/update_username.vue
+++ b/app/assets/javascripts/profile/account/components/update_username.vue
@@ -1,17 +1,19 @@
<script>
-/* eslint-disable vue/no-v-html */
import { escape } from 'lodash';
-import { GlButton } from '@gitlab/ui';
+import { GlSafeHtmlDirective as SafeHtml, GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
-import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { s__, sprintf } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
export default {
components: {
- GlModal: DeprecatedModal2,
+ GlModal,
GlButton,
},
+ directives: {
+ GlModalDirective,
+ SafeHtml,
+ },
props: {
actionUrl: {
type: String,
@@ -54,6 +56,21 @@ Please update your Git repository remotes as soon as possible.`),
false,
);
},
+ primaryProps() {
+ return {
+ text: s__('Update username'),
+ attributes: [
+ { variant: 'warning' },
+ { category: 'primary' },
+ { disabled: this.isRequestPending },
+ ],
+ };
+ },
+ cancelProps() {
+ return {
+ text: s__('Cancel'),
+ };
+ },
},
methods: {
onConfirm() {
@@ -103,22 +120,21 @@ Please update your Git repository remotes as soon as possible.`),
<p class="form-text text-muted">{{ path }}</p>
</div>
<gl-button
- :data-target="`#${$options.modalId}`"
+ v-gl-modal-directive="$options.modalId"
:disabled="isRequestPending || newUsername === username"
category="primary"
variant="warning"
- data-toggle="modal"
+ data-testid="username-change-confirmation-modal"
+ >{{ $options.buttonText }}</gl-button
>
- {{ $options.buttonText }}
- </gl-button>
<gl-modal
- :id="$options.modalId"
- :header-title-text="s__('Profiles|Change username') + '?'"
- :footer-primary-button-text="$options.buttonText"
- footer-primary-button-variant="warning"
- @submit="onConfirm"
+ :modal-id="$options.modalId"
+ :title="s__('Profiles|Change username') + '?'"
+ :action-primary="primaryProps"
+ :action-cancel="cancelProps"
+ @primary="onConfirm"
>
- <span v-html="modalText"></span>
+ <span v-safe-html="modalText"></span>
</gl-modal>
</div>
</template>
diff --git a/app/assets/javascripts/profile/preferences/components/integration_view.vue b/app/assets/javascripts/profile/preferences/components/integration_view.vue
new file mode 100644
index 00000000000..c2952629a5d
--- /dev/null
+++ b/app/assets/javascripts/profile/preferences/components/integration_view.vue
@@ -0,0 +1,81 @@
+<script>
+import { GlFormText, GlIcon, GlLink } from '@gitlab/ui';
+import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue';
+
+export default {
+ name: 'IntegrationView',
+ components: {
+ GlFormText,
+ GlIcon,
+ GlLink,
+ IntegrationHelpText,
+ },
+ inject: ['userFields'],
+ props: {
+ helpLink: {
+ type: String,
+ required: true,
+ },
+ message: {
+ type: String,
+ required: true,
+ },
+ messageUrl: {
+ type: String,
+ required: true,
+ },
+ config: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isEnabled: this.userFields[this.config.formName],
+ };
+ },
+ computed: {
+ formName() {
+ return `user[${this.config.formName}]`;
+ },
+ formId() {
+ return `user_${this.config.formName}`;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <label class="label-bold">
+ {{ config.title }}
+ </label>
+ <gl-link class="has-tooltip" title="More information" :href="helpLink">
+ <gl-icon name="question-o" class="vertical-align-middle" />
+ </gl-link>
+ <div class="form-group form-check" data-testid="profile-preferences-integration-form-group">
+ <!-- Necessary for Rails to receive the value when not checked -->
+ <input
+ :name="formName"
+ type="hidden"
+ value="0"
+ data-testid="profile-preferences-integration-hidden-field"
+ />
+ <input
+ :id="formId"
+ v-model="isEnabled"
+ type="checkbox"
+ class="form-check-input"
+ :name="formName"
+ value="1"
+ data-testid="profile-preferences-integration-checkbox"
+ />
+ <label class="form-check-label" :for="formId">
+ {{ config.label }}
+ </label>
+ <gl-form-text tag="div">
+ <integration-help-text :message="message" :message-url="messageUrl" />
+ </gl-form-text>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/profile/preferences/components/profile_preferences.vue b/app/assets/javascripts/profile/preferences/components/profile_preferences.vue
new file mode 100644
index 00000000000..8b2006b7c5b
--- /dev/null
+++ b/app/assets/javascripts/profile/preferences/components/profile_preferences.vue
@@ -0,0 +1,56 @@
+<script>
+import { s__ } from '~/locale';
+import IntegrationView from './integration_view.vue';
+
+const INTEGRATION_VIEW_CONFIGS = {
+ sourcegraph: {
+ title: s__('ProfilePreferences|Sourcegraph'),
+ label: s__('ProfilePreferences|Enable integrated code intelligence on code views'),
+ formName: 'sourcegraph_enabled',
+ },
+ gitpod: {
+ title: s__('ProfilePreferences|Gitpod'),
+ label: s__('ProfilePreferences|Enable Gitpod integration'),
+ formName: 'gitpod_enabled',
+ },
+};
+
+export default {
+ name: 'ProfilePreferences',
+ components: {
+ IntegrationView,
+ },
+ inject: {
+ integrationViews: {
+ default: [],
+ },
+ },
+ integrationViewConfigs: INTEGRATION_VIEW_CONFIGS,
+};
+</script>
+
+<template>
+ <div class="row gl-mt-3 js-preferences-form">
+ <div v-if="integrationViews.length" class="col-sm-12">
+ <hr data-testid="profile-preferences-integrations-rule" />
+ </div>
+ <div v-if="integrationViews.length" class="col-lg-4 profile-settings-sidebar">
+ <h4 class="gl-mt-0" data-testid="profile-preferences-integrations-heading">
+ {{ s__('ProfilePreferences|Integrations') }}
+ </h4>
+ <p>
+ {{ s__('ProfilePreferences|Customize integrations with third party services.') }}
+ </p>
+ </div>
+ <div v-if="integrationViews.length" class="col-lg-8">
+ <integration-view
+ v-for="view in integrationViews"
+ :key="view.name"
+ :help-link="view.help_link"
+ :message="view.message"
+ :message-url="view.message_url"
+ :config="$options.integrationViewConfigs[view.name]"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/profile/preferences/profile_preferences_bundle.js b/app/assets/javascripts/profile/preferences/profile_preferences_bundle.js
new file mode 100644
index 00000000000..bcca3140717
--- /dev/null
+++ b/app/assets/javascripts/profile/preferences/profile_preferences_bundle.js
@@ -0,0 +1,23 @@
+import Vue from 'vue';
+import ProfilePreferences from './components/profile_preferences.vue';
+
+export default () => {
+ const el = document.querySelector('#js-profile-preferences-app');
+ const shouldParse = ['integrationViews', 'userFields'];
+
+ const provide = Object.keys(el.dataset).reduce((memo, key) => {
+ let value = el.dataset[key];
+ if (shouldParse.includes(key)) {
+ value = JSON.parse(value);
+ }
+
+ return { ...memo, [key]: value };
+ }, {});
+
+ return new Vue({
+ el,
+ name: 'ProfilePreferencesApp',
+ provide,
+ render: createElement => createElement(ProfilePreferences),
+ });
+};
diff --git a/app/assets/javascripts/projects/commit_box/info/index.js b/app/assets/javascripts/projects/commit_box/info/index.js
index 352ac39f3c4..254d178f013 100644
--- a/app/assets/javascripts/projects/commit_box/info/index.js
+++ b/app/assets/javascripts/projects/commit_box/info/index.js
@@ -1,4 +1,5 @@
import { loadBranches } from './load_branches';
+import { initDetailsButton } from './init_details_button';
import { fetchCommitMergeRequests } from '~/commit_merge_requests';
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
@@ -15,4 +16,6 @@ export const initCommitBoxInfo = (containerSelector = '.js-commit-box-info') =>
new MiniPipelineGraph({
container: '.js-commit-pipeline-graph',
}).bindEvents();
+
+ initDetailsButton();
};
diff --git a/app/assets/javascripts/projects/commit_box/info/init_details_button.js b/app/assets/javascripts/projects/commit_box/info/init_details_button.js
new file mode 100644
index 00000000000..032fbf5316a
--- /dev/null
+++ b/app/assets/javascripts/projects/commit_box/info/init_details_button.js
@@ -0,0 +1,11 @@
+import $ from 'jquery';
+
+export const initDetailsButton = () => {
+ $('body').on('click', '.js-details-expand', function expand(e) {
+ e.preventDefault();
+ $(this)
+ .next('.js-details-content')
+ .removeClass('hide');
+ $(this).hide();
+ });
+};
diff --git a/app/assets/javascripts/projects/components/project_delete_button.vue b/app/assets/javascripts/projects/components/project_delete_button.vue
index 2f3ff92d7ae..5429d51dae0 100644
--- a/app/assets/javascripts/projects/components/project_delete_button.vue
+++ b/app/assets/javascripts/projects/components/project_delete_button.vue
@@ -25,7 +25,7 @@ export default {
'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 repository and all content: issues, merge requests, etc.",
+ "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc.",
),
},
};
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/app.vue b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
index 0777dddfc19..c6e2b2e1140 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/app.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
@@ -45,9 +45,12 @@ export default {
},
data() {
return {
- timesChartTransformedData: {
- full: this.mergeLabelsAndValues(this.timesChartData.labels, this.timesChartData.values),
- },
+ timesChartTransformedData: [
+ {
+ name: 'full',
+ data: this.mergeLabelsAndValues(this.timesChartData.labels, this.timesChartData.values),
+ },
+ ],
};
},
computed: {
@@ -128,7 +131,7 @@ export default {
<gl-column-chart
:height="$options.chartContainerHeight"
:option="$options.timesChartOptions"
- :data="timesChartTransformedData"
+ :bars="timesChartTransformedData"
:y-axis-title="__('Minutes')"
:x-axis-title="__('Commit')"
x-axis-type="category"
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue b/app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue
index cd9e464c5ac..aa59717ddcd 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue
@@ -1,4 +1,7 @@
<script>
+import { formatTime } from '~/lib/utils/datetime_utility';
+import { s__, n__ } from '~/locale';
+
export default {
props: {
counts: {
@@ -6,25 +9,44 @@ export default {
required: true,
},
},
+ computed: {
+ totalDuration() {
+ return formatTime(this.counts.totalDuration);
+ },
+ statistics() {
+ return [
+ {
+ title: s__('PipelineCharts|Total:'),
+ value: n__('1 pipeline', '%d pipelines', this.counts.total),
+ },
+ {
+ title: s__('PipelineCharts|Successful:'),
+ value: n__('1 pipeline', '%d pipelines', this.counts.success),
+ },
+ {
+ title: s__('PipelineCharts|Failed:'),
+ value: n__('1 pipeline', '%d pipelines', this.counts.failed),
+ },
+ {
+ title: s__('PipelineCharts|Success ratio:'),
+ value: `${this.counts.successRatio}%`,
+ },
+ {
+ title: s__('PipelineCharts|Total duration:'),
+ value: this.totalDuration,
+ },
+ ];
+ },
+ },
};
</script>
<template>
<ul>
- <li>
- <span>{{ s__('PipelineCharts|Total:') }}</span>
- <strong>{{ n__('1 pipeline', '%d pipelines', counts.total) }}</strong>
- </li>
- <li>
- <span>{{ s__('PipelineCharts|Successful:') }}</span>
- <strong>{{ n__('1 pipeline', '%d pipelines', counts.success) }}</strong>
- </li>
- <li>
- <span>{{ s__('PipelineCharts|Failed:') }}</span>
- <strong>{{ n__('1 pipeline', '%d pipelines', counts.failed) }}</strong>
- </li>
- <li>
- <span>{{ s__('PipelineCharts|Success ratio:') }}</span>
- <strong>{{ counts.successRatio }}%</strong>
- </li>
+ <template v-for="({ title, value }, index) in statistics">
+ <li :key="index">
+ <span>{{ title }}</span>
+ <strong>{{ value }}</strong>
+ </li>
+ </template>
</ul>
</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/index.js b/app/assets/javascripts/projects/pipelines/charts/index.js
index 4ae2b729200..eef1bc2d28b 100644
--- a/app/assets/javascripts/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/projects/pipelines/charts/index.js
@@ -7,6 +7,7 @@ export default () => {
countsFailed,
countsSuccess,
countsTotal,
+ countsTotalDuration,
successRatio,
timesChartLabels,
timesChartValues,
@@ -41,6 +42,7 @@ export default () => {
success: countsSuccess,
total: countsTotal,
successRatio,
+ totalDuration: countsTotalDuration,
},
timesChartData: {
labels: JSON.parse(timesChartLabels),
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 4bfed6d489d..df7d9b56aed 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
@@ -20,7 +20,12 @@ export default {
type: String,
required: true,
},
- initialIncomingEmail: {
+ incomingEmail: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ customEmail: {
type: String,
required: false,
default: '',
@@ -50,23 +55,18 @@ export default {
data() {
return {
isEnabled: this.initialIsEnabled,
- incomingEmail: this.initialIncomingEmail,
isTemplateSaving: false,
isAlertShowing: false,
alertVariant: 'danger',
alertMessage: '',
+ updatedCustomEmail: this.customEmail,
};
},
created() {
eventHub.$on('serviceDeskEnabledCheckboxToggled', this.onEnableToggled);
eventHub.$on('serviceDeskTemplateSave', this.onSaveTemplate);
-
this.service = new ServiceDeskService(this.endpoint);
-
- if (this.isEnabled && !this.incomingEmail) {
- this.fetchIncomingEmail();
- }
},
beforeDestroy() {
@@ -75,22 +75,6 @@ export default {
},
methods: {
- fetchIncomingEmail() {
- this.service
- .fetchIncomingEmail()
- .then(({ data }) => {
- const email = data.service_desk_address;
- if (!email) {
- throw new Error(__("Response didn't include `service_desk_address`"));
- }
-
- this.incomingEmail = email;
- })
- .catch(() =>
- this.showAlert(__('An error occurred while fetching the Service Desk address.')),
- );
- },
-
onEnableToggled(isChecked) {
this.isEnabled = isChecked;
this.incomingEmail = '';
@@ -119,7 +103,7 @@ export default {
this.service
.updateTemplate({ selectedTemplate, outgoingName, projectKey }, this.isEnabled)
.then(({ data }) => {
- this.incomingEmail = data?.service_desk_address;
+ this.updatedCustomEmail = data?.service_desk_address;
this.showAlert(__('Changes were successfully made.'), 'success');
})
.catch(err => {
@@ -155,6 +139,7 @@ export default {
<service-desk-setting
:is-enabled="isEnabled"
:incoming-email="incomingEmail"
+ :custom-email="updatedCustomEmail"
:initial-selected-template="selectedTemplate"
:initial-outgoing-name="outgoingName"
:initial-project-key="projectKey"
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 e18cfefc3ca..5d120fd0b3f 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
@@ -26,6 +26,11 @@ export default {
required: false,
default: '',
},
+ customEmail: {
+ type: String,
+ required: false,
+ default: '',
+ },
initialSelectedTemplate: {
type: String,
required: false,
@@ -57,7 +62,6 @@ export default {
selectedTemplate: this.initialSelectedTemplate,
outgoingName: this.initialOutgoingName || __('GitLab Support Bot'),
projectKey: this.initialProjectKey,
- baseEmail: this.incomingEmail.replace(this.initialProjectKey, ''),
};
},
computed: {
@@ -67,6 +71,12 @@ export default {
hasProjectKeySupport() {
return Boolean(this.glFeatures.serviceDeskCustomAddress);
},
+ email() {
+ return this.customEmail || this.incomingEmail;
+ },
+ hasCustomEmail() {
+ return this.customEmail && this.customEmail !== this.incomingEmail;
+ },
},
methods: {
onCheckboxToggle(isChecked) {
@@ -101,30 +111,31 @@ export default {
<strong id="incoming-email-describer" class="d-block mb-1">
{{ __('Forward external support email address to') }}
</strong>
- <template v-if="incomingEmail">
+ <template v-if="email">
<div class="input-group">
<input
ref="service-desk-incoming-email"
type="text"
- class="form-control incoming-email"
+ class="form-control"
+ data-testid="incoming-email"
:placeholder="__('Incoming email')"
:aria-label="__('Incoming email')"
aria-describedby="incoming-email-describer"
- :value="incomingEmail"
+ :value="email"
disabled="true"
/>
<div class="input-group-append">
<clipboard-button
:title="__('Copy')"
- :text="incomingEmail"
+ :text="email"
css-class="input-group-text qa-clipboard-button"
/>
</div>
</div>
- <span v-if="projectKey" class="form-text text-muted">
+ <span v-if="hasCustomEmail" class="form-text text-muted">
<gl-sprintf :message="__('Emails sent to %{email} will still be supported')">
<template #email>
- <code>{{ baseEmail }}</code>
+ <code>{{ incomingEmail }}</code>
</template>
</gl-sprintf>
</span>
diff --git a/app/assets/javascripts/projects/settings_service_desk/index.js b/app/assets/javascripts/projects/settings_service_desk/index.js
index 15c077de72e..c73163788ef 100644
--- a/app/assets/javascripts/projects/settings_service_desk/index.js
+++ b/app/assets/javascripts/projects/settings_service_desk/index.js
@@ -17,6 +17,7 @@ export default () => {
initialIsEnabled: parseBoolean(dataset.enabled),
endpoint: dataset.endpoint,
incomingEmail: dataset.incomingEmail,
+ customEmail: dataset.customEmail,
selectedTemplate: dataset.selectedTemplate,
outgoingName: dataset.outgoingName,
projectKey: dataset.projectKey,
@@ -28,7 +29,8 @@ export default () => {
props: {
initialIsEnabled: this.initialIsEnabled,
endpoint: this.endpoint,
- initialIncomingEmail: this.incomingEmail,
+ incomingEmail: this.incomingEmail,
+ customEmail: this.customEmail,
selectedTemplate: this.selectedTemplate,
outgoingName: this.outgoingName,
projectKey: this.projectKey,
diff --git a/app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js b/app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js
index d707763c64e..b68c5bb876f 100644
--- a/app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js
+++ b/app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js
@@ -5,10 +5,6 @@ class ServiceDeskService {
this.endpoint = endpoint;
}
- fetchIncomingEmail() {
- return axios.get(this.endpoint);
- }
-
toggleServiceDesk(enable) {
return axios.put(this.endpoint, { service_desk_enabled: enable });
}
diff --git a/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js b/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
index 7fc1b18bf71..bb9689f09a1 100644
--- a/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
+++ b/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
@@ -18,29 +18,32 @@ export default class PrometheusMetrics {
this.$monitoredMetricsList = this.$monitoredMetricsPanel.find('.js-metrics-list');
this.$missingEnvVarPanel = this.$wrapper.find('.js-panel-missing-env-vars');
- this.$panelToggle = this.$missingEnvVarPanel.find('.js-panel-toggle');
+ this.$panelToggleRight = this.$missingEnvVarPanel.find('.js-panel-toggle-right');
+ this.$panelToggleDown = this.$missingEnvVarPanel.find('.js-panel-toggle-down');
this.$missingEnvVarMetricCount = this.$missingEnvVarPanel.find('.js-env-var-count');
this.$missingEnvVarMetricsList = this.$missingEnvVarPanel.find('.js-missing-var-metrics-list');
this.activeMetricsEndpoint = this.$monitoredMetricsPanel.data('activeMetrics');
this.helpMetricsPath = this.$monitoredMetricsPanel.data('metrics-help-path');
- this.$panelToggle.on('click', e => this.handlePanelToggle(e));
+ this.$panelToggleRight.on('click', e => this.handlePanelToggle(e));
+ this.$panelToggleDown.on('click', e => this.handlePanelToggle(e));
}
init() {
this.loadActiveMetrics();
}
- /* eslint-disable class-methods-use-this */
handlePanelToggle(e) {
const $toggleBtn = $(e.currentTarget);
const $currentPanelBody = $toggleBtn.closest('.card').find('.card-body');
$currentPanelBody.toggleClass('hidden');
- if ($toggleBtn.hasClass('fa-caret-down')) {
- $toggleBtn.removeClass('fa-caret-down').addClass('fa-caret-right');
- } else {
- $toggleBtn.removeClass('fa-caret-right').addClass('fa-caret-down');
+ if ($toggleBtn.hasClass('js-panel-toggle-right')) {
+ $toggleBtn.addClass('hidden');
+ this.$panelToggleDown.removeClass('hidden');
+ } else if ($toggleBtn.hasClass('js-panel-toggle-down')) {
+ $toggleBtn.addClass('hidden');
+ this.$panelToggleRight.removeClass('hidden');
}
}
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 328026d0953..2844b4ffde3 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
@@ -14,9 +14,9 @@ export default {
required: false,
default: () => [],
},
- isDesktop: {
+ isMobile: {
type: Boolean,
- default: false,
+ default: true,
required: false,
},
},
@@ -34,7 +34,7 @@ export default {
return this.tags.some(tag => this.selectedItems[tag.name]);
},
showMultiDeleteButton() {
- return this.tags.some(tag => tag.destroy_path) && this.isDesktop;
+ return this.tags.some(tag => tag.destroy_path) && !this.isMobile;
},
},
methods: {
@@ -68,7 +68,7 @@ export default {
:tag="tag"
:first="index === 0"
:selected="selectedItems[tag.name]"
- :is-desktop="isDesktop"
+ :is-mobile="isMobile"
@select="updateSelectedItems(tag.name)"
@delete="$emit('delete', { [tag.name]: true })"
/>
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue b/app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue
index 0f6297ca406..2edeac1144f 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
@@ -40,9 +40,9 @@ export default {
type: Object,
required: true,
},
- isDesktop: {
+ isMobile: {
type: Boolean,
- default: false,
+ default: true,
required: false,
},
selected: {
@@ -69,7 +69,7 @@ export default {
return this.tag.layers ? n__('%d layer', '%d layers', this.tag.layers) : '';
},
mobileClasses() {
- return this.isDesktop ? '' : 'mw-s';
+ return this.isMobile ? 'mw-s' : '';
},
shortDigest() {
// remove sha256: from the string, and show only the first 7 char
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 85d87dab042..ba55822f0ca 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,5 +1,5 @@
<script>
-import { GlDeprecatedDropdown } from '@gitlab/ui';
+import { GlDropdown } from '@gitlab/ui';
import { mapGetters } from 'vuex';
import Tracking from '~/tracking';
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
@@ -17,7 +17,7 @@ const trackingLabel = 'quickstart_dropdown';
export default {
components: {
- GlDeprecatedDropdown,
+ GlDropdown,
CodeInstruction,
},
mixins: [Tracking.mixin({ label: trackingLabel })],
@@ -37,15 +37,14 @@ export default {
};
</script>
<template>
- <gl-deprecated-dropdown
+ <gl-dropdown
:text="$options.i18n.QUICK_START"
- variant="primary"
- size="sm"
+ variant="info"
right
@shown="track('click_dropdown')"
>
<!-- 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">
+ <li role="presentation" class="px-2 py-1">
<code-instruction
:label="$options.i18n.LOGIN_COMMAND_LABEL"
:instruction="dockerLoginCommand"
@@ -71,5 +70,5 @@ export default {
:tracking-label="$options.trackingLabel"
/>
</li>
- </gl-deprecated-dropdown>
+ </gl-dropdown>
</template>
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 cfd787b3f52..b0a7c4824bd 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
@@ -37,15 +37,6 @@ export default {
ROW_SCHEDULED_FOR_DELETION,
},
computed: {
- encodedItem() {
- const params = JSON.stringify({
- name: this.item.path,
- tags_path: this.item.tags_path,
- id: this.item.id,
- cleanup_policy_started_at: this.item.cleanup_policy_started_at,
- });
- return window.btoa(params);
- },
disabledDelete() {
return !this.item.destroy_path || this.item.deleting;
},
@@ -81,8 +72,8 @@ export default {
<template #left-primary>
<router-link
class="gl-text-body gl-font-weight-bold"
- data-testid="detailsLink"
- :to="{ name: 'details', params: { id: encodedItem } }"
+ data-testid="details-link"
+ :to="{ name: 'details', params: { id: item.id } }"
>
{{ item.path }}
</router-link>
diff --git a/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue b/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
index 146d1434b18..666d8b042da 100644
--- a/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
+++ b/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
@@ -30,7 +30,7 @@ export default {
return {
tagName,
className,
- text: this.$route.meta.nameGenerator(this.$route),
+ text: this.$route.meta.nameGenerator(this.$store.state),
path: { to: this.$route.name },
};
},
@@ -48,7 +48,7 @@ export default {
></li>
<li v-if="!isRootRoute">
<router-link ref="rootRouteLink" :to="rootRoute.path">
- {{ rootRoute.meta.nameGenerator(rootRoute) }}
+ {{ rootRoute.meta.nameGenerator($store.state) }}
</router-link>
<component :is="divider.tagName" v-safe-html="divider.innerHTML" :class="divider.classList" />
</li>
diff --git a/app/assets/javascripts/registry/explorer/constants/details.js b/app/assets/javascripts/registry/explorer/constants/details.js
index 1dc5882d415..306e6903a4f 100644
--- a/app/assets/javascripts/registry/explorer/constants/details.js
+++ b/app/assets/javascripts/registry/explorer/constants/details.js
@@ -15,6 +15,10 @@ export const DELETE_TAGS_SUCCESS_MESSAGE = s__(
'ContainerRegistry|Tags successfully marked for deletion.',
);
+export const FETCH_IMAGE_DETAILS_ERROR_MESSAGE = s__(
+ 'ContainerRegistry|Something went wrong while fetching the image details.',
+);
+
export const TAGS_LIST_TITLE = s__('ContainerRegistry|Image tags');
export const DIGEST_LABEL = s__('ContainerRegistry|Digest: %{imageId}');
export const CREATED_AT_LABEL = s__('ContainerRegistry|Published %{timeInfo}');
diff --git a/app/assets/javascripts/registry/explorer/pages/details.vue b/app/assets/javascripts/registry/explorer/pages/details.vue
index d2fb695dbfa..a60ef5c4982 100644
--- a/app/assets/javascripts/registry/explorer/pages/details.vue
+++ b/app/assets/javascripts/registry/explorer/pages/details.vue
@@ -11,7 +11,6 @@ import TagsList from '../components/details_page/tags_list.vue';
import TagsLoader from '../components/details_page/tags_loader.vue';
import EmptyTagsState from '../components/details_page/empty_tags_state.vue';
-import { decodeAndParse } from '../utils';
import {
ALERT_SUCCESS_TAG,
ALERT_DANGER_TAG,
@@ -37,18 +36,15 @@ export default {
data() {
return {
itemsToBeDeleted: [],
- isDesktop: true,
+ isMobile: false,
deleteAlertType: null,
dismissPartialCleanupWarning: false,
};
},
computed: {
- ...mapState(['tagsPagination', 'isLoading', 'config', 'tags']),
- queryParameters() {
- return decodeAndParse(this.$route.params.id);
- },
+ ...mapState(['tagsPagination', 'isLoading', 'config', 'tags', 'imageDetails']),
showPartialCleanupWarning() {
- return this.queryParameters.cleanup_policy_started_at && !this.dismissPartialCleanupWarning;
+ return this.imageDetails?.cleanup_policy_started_at && !this.dismissPartialCleanupWarning;
},
tracking() {
return {
@@ -61,15 +57,20 @@ export default {
return this.tagsPagination.page;
},
set(page) {
- this.requestTagsList({ pagination: { page }, params: this.$route.params.id });
+ this.requestTagsList({ page });
},
},
},
mounted() {
- this.requestTagsList({ params: this.$route.params.id });
+ this.requestImageDetailsAndTagsList(this.$route.params.id);
},
methods: {
- ...mapActions(['requestTagsList', 'requestDeleteTag', 'requestDeleteTags']),
+ ...mapActions([
+ 'requestTagsList',
+ 'requestDeleteTag',
+ 'requestDeleteTags',
+ 'requestImageDetailsAndTagsList',
+ ]),
deleteTags(toBeDeleted) {
this.itemsToBeDeleted = this.tags.filter(tag => toBeDeleted[tag.name]);
this.track('click_button');
@@ -78,7 +79,7 @@ export default {
handleSingleDelete() {
const [itemToDelete] = this.itemsToBeDeleted;
this.itemsToBeDeleted = [];
- return this.requestDeleteTag({ tag: itemToDelete, params: this.$route.params.id })
+ return this.requestDeleteTag({ tag: itemToDelete })
.then(() => {
this.deleteAlertType = ALERT_SUCCESS_TAG;
})
@@ -92,7 +93,6 @@ export default {
return this.requestDeleteTags({
ids: itemsToBeDeleted.map(x => x.name),
- params: this.$route.params.id,
})
.then(() => {
this.deleteAlertType = ALERT_SUCCESS_TAGS;
@@ -110,7 +110,7 @@ export default {
}
},
handleResize() {
- this.isDesktop = GlBreakpointInstance.isDesktop();
+ this.isMobile = GlBreakpointInstance.getBreakpointSize() === 'xs';
},
},
};
@@ -132,12 +132,12 @@ export default {
@dismiss="dismissPartialCleanupWarning = true"
/>
- <details-header :image-name="queryParameters.name" />
+ <details-header :image-name="imageDetails.name" />
<tags-loader v-if="isLoading" />
<template v-else>
<empty-tags-state v-if="tags.length === 0" :no-containers-image="config.noContainersImage" />
- <tags-list v-else :tags="tags" :is-desktop="isDesktop" @delete="deleteTags" />
+ <tags-list v-else :tags="tags" :is-mobile="isMobile" @delete="deleteTags" />
</template>
<gl-pagination
diff --git a/app/assets/javascripts/registry/explorer/router.js b/app/assets/javascripts/registry/explorer/router.js
index f570987023b..dcf1c77329d 100644
--- a/app/assets/javascripts/registry/explorer/router.js
+++ b/app/assets/javascripts/registry/explorer/router.js
@@ -2,7 +2,6 @@ import Vue from 'vue';
import VueRouter from 'vue-router';
import List from './pages/list.vue';
import Details from './pages/details.vue';
-import { decodeAndParse } from './utils';
import { CONTAINER_REGISTRY_TITLE } from './constants/index';
Vue.use(VueRouter);
@@ -26,7 +25,7 @@ export default function createRouter(base) {
path: '/:id',
component: Details,
meta: {
- nameGenerator: route => decodeAndParse(route.params.id).name,
+ nameGenerator: ({ imageDetails }) => imageDetails?.name,
},
},
],
diff --git a/app/assets/javascripts/registry/explorer/stores/actions.js b/app/assets/javascripts/registry/explorer/stores/actions.js
index 9125f573aa4..c1883095097 100644
--- a/app/assets/javascripts/registry/explorer/stores/actions.js
+++ b/app/assets/javascripts/registry/explorer/stores/actions.js
@@ -1,13 +1,15 @@
import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
+import Api from '~/api';
import * as types from './mutation_types';
import {
FETCH_IMAGES_LIST_ERROR_MESSAGE,
DEFAULT_PAGE,
DEFAULT_PAGE_SIZE,
FETCH_TAGS_LIST_ERROR_MESSAGE,
+ FETCH_IMAGE_DETAILS_ERROR_MESSAGE,
} from '../constants/index';
-import { decodeAndParse } from '../utils';
+import { pathGenerator } from '../utils';
export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_STATE, data);
export const setShowGarbageCollectionTip = ({ commit }, data) =>
@@ -36,55 +38,68 @@ export const requestImagesList = (
dispatch('receiveImagesListSuccess', { data, headers });
})
.catch(() => {
- createFlash(FETCH_IMAGES_LIST_ERROR_MESSAGE);
+ createFlash({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
})
.finally(() => {
commit(types.SET_MAIN_LOADING, false);
});
};
-export const requestTagsList = ({ commit, dispatch }, { pagination = {}, params }) => {
+export const requestTagsList = ({ commit, dispatch, state: { imageDetails } }, pagination = {}) => {
commit(types.SET_MAIN_LOADING, true);
- const { tags_path } = decodeAndParse(params);
+ const tagsPath = pathGenerator(imageDetails);
const { page = DEFAULT_PAGE, perPage = DEFAULT_PAGE_SIZE } = pagination;
return axios
- .get(tags_path, { params: { page, per_page: perPage } })
+ .get(tagsPath, { params: { page, per_page: perPage } })
.then(({ data, headers }) => {
dispatch('receiveTagsListSuccess', { data, headers });
})
.catch(() => {
- createFlash(FETCH_TAGS_LIST_ERROR_MESSAGE);
+ createFlash({ message: FETCH_TAGS_LIST_ERROR_MESSAGE });
})
.finally(() => {
commit(types.SET_MAIN_LOADING, false);
});
};
-export const requestDeleteTag = ({ commit, dispatch, state }, { tag, params }) => {
+export const requestImageDetailsAndTagsList = ({ dispatch, commit }, id) => {
+ commit(types.SET_MAIN_LOADING, true);
+ return Api.containerRegistryDetails(id)
+ .then(({ data }) => {
+ commit(types.SET_IMAGE_DETAILS, data);
+ dispatch('requestTagsList');
+ })
+ .catch(() => {
+ createFlash({ message: FETCH_IMAGE_DETAILS_ERROR_MESSAGE });
+ commit(types.SET_MAIN_LOADING, false);
+ });
+};
+
+export const requestDeleteTag = ({ commit, dispatch, state }, { tag }) => {
commit(types.SET_MAIN_LOADING, true);
return axios
.delete(tag.destroy_path)
.then(() => {
dispatch('setShowGarbageCollectionTip', true);
- return dispatch('requestTagsList', { pagination: state.tagsPagination, params });
+
+ return dispatch('requestTagsList', state.tagsPagination);
})
.finally(() => {
commit(types.SET_MAIN_LOADING, false);
});
};
-export const requestDeleteTags = ({ commit, dispatch, state }, { ids, params }) => {
+export const requestDeleteTags = ({ commit, dispatch, state }, { ids }) => {
commit(types.SET_MAIN_LOADING, true);
- const { tags_path } = decodeAndParse(params);
- const url = tags_path.replace('?format=json', '/bulk_destroy');
+ const tagsPath = pathGenerator(state.imageDetails, '/bulk_destroy');
return axios
- .delete(url, { params: { ids } })
+ .delete(tagsPath, { params: { ids } })
.then(() => {
dispatch('setShowGarbageCollectionTip', true);
- return dispatch('requestTagsList', { pagination: state.tagsPagination, params });
+ return dispatch('requestTagsList', state.tagsPagination);
})
.finally(() => {
commit(types.SET_MAIN_LOADING, false);
diff --git a/app/assets/javascripts/registry/explorer/stores/mutation_types.js b/app/assets/javascripts/registry/explorer/stores/mutation_types.js
index f32cdf90783..5dd0cec52eb 100644
--- a/app/assets/javascripts/registry/explorer/stores/mutation_types.js
+++ b/app/assets/javascripts/registry/explorer/stores/mutation_types.js
@@ -7,3 +7,4 @@ export const SET_MAIN_LOADING = 'SET_MAIN_LOADING';
export const SET_TAGS_PAGINATION = 'SET_TAGS_PAGINATION';
export const SET_TAGS_LIST_SUCCESS = 'SET_TAGS_LIST_SUCCESS';
export const SET_SHOW_GARBAGE_COLLECTION_TIP = 'SET_SHOW_GARBAGE_COLLECTION_TIP';
+export const SET_IMAGE_DETAILS = 'SET_IMAGE_DETAILS';
diff --git a/app/assets/javascripts/registry/explorer/stores/mutations.js b/app/assets/javascripts/registry/explorer/stores/mutations.js
index 706f6489287..5bdb431ad2e 100644
--- a/app/assets/javascripts/registry/explorer/stores/mutations.js
+++ b/app/assets/javascripts/registry/explorer/stores/mutations.js
@@ -47,4 +47,8 @@ export default {
const normalizedHeaders = normalizeHeaders(headers);
state.tagsPagination = parseIntPagination(normalizedHeaders);
},
+
+ [types.SET_IMAGE_DETAILS](state, details) {
+ state.imageDetails = details;
+ },
};
diff --git a/app/assets/javascripts/registry/explorer/stores/state.js b/app/assets/javascripts/registry/explorer/stores/state.js
index 694006aac81..66ee56eb47b 100644
--- a/app/assets/javascripts/registry/explorer/stores/state.js
+++ b/app/assets/javascripts/registry/explorer/stores/state.js
@@ -3,6 +3,7 @@ export default () => ({
showGarbageCollectionTip: false,
config: {},
images: [],
+ imageDetails: {},
tags: [],
pagination: {},
tagsPagination: {},
diff --git a/app/assets/javascripts/registry/explorer/utils.js b/app/assets/javascripts/registry/explorer/utils.js
index 44262a6cbb6..2c89d508c31 100644
--- a/app/assets/javascripts/registry/explorer/utils.js
+++ b/app/assets/javascripts/registry/explorer/utils.js
@@ -1 +1,16 @@
-export const decodeAndParse = param => JSON.parse(window.atob(param));
+export const pathGenerator = (imageDetails, ending = '?format=json') => {
+ // this method is a temporary workaround, to be removed with graphql implementation
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/276432
+
+ const splitPath = imageDetails.path.split('/').reverse();
+ const splitName = imageDetails.name ? imageDetails.name.split('/').reverse() : [];
+ const basePath = splitPath
+ .reduce((acc, curr, index) => {
+ if (splitPath[index] !== splitName[index]) {
+ acc.unshift(curr);
+ }
+ return acc;
+ }, [])
+ .join('/');
+ return `/${basePath}/registry/repository/${imageDetails.id}/tags${ending}`;
+};
diff --git a/app/assets/javascripts/registry/settings/components/settings_form.vue b/app/assets/javascripts/registry/settings/components/settings_form.vue
index a9b35d4e29f..fe4aee6806e 100644
--- a/app/assets/javascripts/registry/settings/components/settings_form.vue
+++ b/app/assets/javascripts/registry/settings/components/settings_form.vue
@@ -117,8 +117,9 @@ export default {
const errorMessage = data?.updateContainerExpirationPolicy?.errors[0];
if (errorMessage) {
this.$toast.show(errorMessage, { type: 'error' });
+ } else {
+ this.$toast.show(UPDATE_SETTINGS_SUCCESS_MESSAGE, { type: 'success' });
}
- this.$toast.show(UPDATE_SETTINGS_SUCCESS_MESSAGE, { type: 'success' });
})
.catch(error => {
this.setApiErrors(error);
diff --git a/app/assets/javascripts/registry/shared/constants.js b/app/assets/javascripts/registry/shared/constants.js
index 735d72972e6..d1e3d93938b 100644
--- a/app/assets/javascripts/registry/shared/constants.js
+++ b/app/assets/javascripts/registry/shared/constants.js
@@ -32,7 +32,7 @@ export const KEEP_N_LABEL = s__('ContainerRegistry|Number of tags to retain:');
export const NAME_REGEX_LABEL = s__(
'ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}',
);
-export const NAME_REGEX_PLACEHOLDER = '.*';
+export const NAME_REGEX_PLACEHOLDER = '';
export const NAME_REGEX_DESCRIPTION = s__(
'ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}',
);
diff --git a/app/assets/javascripts/related_issues/components/issue_token.vue b/app/assets/javascripts/related_issues/components/issue_token.vue
index bbbdf2cdb49..7f12c10f6a1 100644
--- a/app/assets/javascripts/related_issues/components/issue_token.vue
+++ b/app/assets/javascripts/related_issues/components/issue_token.vue
@@ -1,5 +1,5 @@
<script>
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import relatedIssuableMixin from '~/vue_shared/mixins/related_issuable_mixin';
@@ -8,6 +8,9 @@ export default {
components: {
GlIcon,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
mixins: [relatedIssuableMixin],
props: {
isCondensed: {
@@ -52,7 +55,7 @@ export default {
<component
:is="computedLinkElementType"
ref="link"
- v-tooltip
+ v-gl-tooltip
:class="{
'issue-token-link': isCondensed,
'issuable-main-info': !isCondensed,
@@ -84,7 +87,7 @@ export default {
>
<gl-icon
v-if="hasState"
- v-tooltip
+ v-gl-tooltip
:class="iconClass"
:name="iconName"
:size="12"
@@ -98,7 +101,7 @@ export default {
<button
v-if="canRemove"
ref="removeButton"
- v-tooltip
+ v-gl-tooltip
:class="{
'issue-token-remove-button': isCondensed,
'btn btn-default': !isCondensed,
diff --git a/app/assets/javascripts/related_issues/components/related_issues_block.vue b/app/assets/javascripts/related_issues/components/related_issues_block.vue
index f7a79c62716..c913745a8e1 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_block.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_block.vue
@@ -138,7 +138,7 @@ export default {
href="#related-issues"
aria-hidden="true"
/>
- <slot name="headerText">{{ __('Linked issues') }}</slot>
+ <slot name="header-text">{{ __('Linked issues') }}</slot>
<gl-link
v-if="hasHelpPath"
:href="helpPath"
@@ -167,7 +167,7 @@ export default {
/>
</div>
</h3>
- <slot name="headerActions"></slot>
+ <slot name="header-actions"></slot>
</div>
<div
class="linked-issues-card-body bg-gray-light"
diff --git a/app/assets/javascripts/related_issues/components/related_issues_list.vue b/app/assets/javascripts/related_issues/components/related_issues_list.vue
index a75fe4397bb..8021d390d95 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_list.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_list.vue
@@ -3,13 +3,9 @@ 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,
@@ -101,7 +97,11 @@ export default {
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">
+ <div
+ v-if="isFetching"
+ class="related-issues-loading-icon"
+ data-qa-selector="related_issues_loading_placeholder"
+ >
<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">
@@ -136,7 +136,7 @@ export default {
:is-locked="issue.lockIssueRemoval"
:locked-message="issue.lockedMessage"
event-namespace="relatedIssue"
- class="qa-related-issuable-item"
+ data-qa-selector="related_issuable_content"
@relatedIssueRemoveRequest="$emit('relatedIssueRemoveRequest', $event)"
/>
</li>
diff --git a/app/assets/javascripts/releases/components/app_edit_new.vue b/app/assets/javascripts/releases/components/app_edit_new.vue
index 1a07e0ed762..8d1bc44cba0 100644
--- a/app/assets/javascripts/releases/components/app_edit_new.vue
+++ b/app/assets/javascripts/releases/components/app_edit_new.vue
@@ -6,7 +6,7 @@ import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { BACK_URL_PARAM } from '~/releases/constants';
import { getParameterByName } from '~/lib/utils/common_utils';
import AssetLinksForm from './asset_links_form.vue';
-import MilestoneCombobox from '~/milestones/project_milestone_combobox.vue';
+import MilestoneCombobox from '~/milestones/components/milestone_combobox.vue';
import TagField from './tag_field.vue';
export default {
@@ -29,11 +29,12 @@ export default {
'markdownDocsPath',
'markdownPreviewPath',
'releasesPagePath',
- 'updateReleaseApiDocsPath',
'release',
'newMilestonePath',
'manageMilestonesPath',
'projectId',
+ 'groupId',
+ 'groupMilestonesAvailable',
]),
...mapGetters('detail', ['isValid', 'isExistingRelease']),
showForm() {
@@ -141,6 +142,8 @@ export default {
<milestone-combobox
v-model="releaseMilestones"
:project-id="projectId"
+ :group-id="groupId"
+ :group-milestones-available="groupMilestonesAvailable"
:extra-links="milestoneComboboxExtraLinks"
/>
</div>
diff --git a/app/assets/javascripts/releases/components/app_index.vue b/app/assets/javascripts/releases/components/app_index.vue
index 422d8bf630d..5064b7dd6ad 100644
--- a/app/assets/javascripts/releases/components/app_index.vue
+++ b/app/assets/javascripts/releases/components/app_index.vue
@@ -6,6 +6,7 @@ import { __ } from '~/locale';
import ReleaseBlock from './release_block.vue';
import ReleasesPagination from './releases_pagination.vue';
import ReleaseSkeletonLoader from './release_skeleton_loader.vue';
+import ReleasesSort from './releases_sort.vue';
export default {
name: 'ReleasesApp',
@@ -16,6 +17,7 @@ export default {
ReleaseBlock,
ReleasesPagination,
ReleaseSkeletonLoader,
+ ReleasesSort,
},
computed: {
...mapState('list', [
@@ -62,16 +64,20 @@ export default {
</script>
<template>
<div class="flex flex-column mt-2">
- <gl-button
- v-if="newReleasePath"
- :href="newReleasePath"
- :aria-describedby="shouldRenderEmptyState && 'releases-description'"
- category="primary"
- variant="success"
- class="align-self-end mb-2 js-new-release-btn"
- >
- {{ __('New release') }}
- </gl-button>
+ <div class="gl-align-self-end gl-mb-3">
+ <releases-sort class="gl-mr-2" @sort:changed="fetchReleases" />
+
+ <gl-button
+ v-if="newReleasePath"
+ :href="newReleasePath"
+ :aria-describedby="shouldRenderEmptyState && 'releases-description'"
+ category="primary"
+ variant="success"
+ class="js-new-release-btn"
+ >
+ {{ __('New release') }}
+ </gl-button>
+ </div>
<release-skeleton-loader v-if="isLoading" class="js-loading" />
diff --git a/app/assets/javascripts/releases/components/issuable_stats.vue b/app/assets/javascripts/releases/components/issuable_stats.vue
new file mode 100644
index 00000000000..d005d8e10dd
--- /dev/null
+++ b/app/assets/javascripts/releases/components/issuable_stats.vue
@@ -0,0 +1,97 @@
+<script>
+import { GlLink, GlBadge, GlSprintf } from '@gitlab/ui';
+
+export default {
+ name: 'IssuableStats',
+ components: {
+ GlLink,
+ GlBadge,
+ GlSprintf,
+ },
+ props: {
+ label: {
+ type: String,
+ required: true,
+ },
+ total: {
+ type: Number,
+ required: true,
+ },
+ closed: {
+ type: Number,
+ required: true,
+ },
+ merged: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ openedPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ closedPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ mergedPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ opened() {
+ return this.total - (this.closed + (this.merged || 0));
+ },
+ showMerged() {
+ return this.merged != null;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-flex-direction-column gl-flex-shrink-0 gl-mr-6 gl-mb-5">
+ <span class="gl-mb-2">
+ {{ label }}
+ <gl-badge variant="muted" size="sm">{{ total }}</gl-badge>
+ </span>
+ <div class="gl-display-flex">
+ <span class="gl-white-space-pre-wrap" data-testid="open-stat">
+ <gl-sprintf :message="__('Open: %{open}')">
+ <template #open>
+ <gl-link v-if="openedPath" :href="openedPath">{{ opened }}</gl-link>
+ <template v-else>{{ opened }}</template>
+ </template>
+ </gl-sprintf>
+ </span>
+
+ <template v-if="showMerged">
+ <span class="gl-mx-2">&bull;</span>
+
+ <span class="gl-white-space-pre-wrap" data-testid="merged-stat">
+ <gl-sprintf :message="__('Merged: %{merged}')">
+ <template #merged>
+ <gl-link v-if="mergedPath" :href="mergedPath">{{ merged }}</gl-link>
+ <template v-else>{{ merged }}</template>
+ </template>
+ </gl-sprintf>
+ </span>
+ </template>
+
+ <span class="gl-mx-2">&bull;</span>
+
+ <span class="gl-white-space-pre-wrap" data-testid="closed-stat">
+ <gl-sprintf :message="__('Closed: %{closed}')">
+ <template #closed>
+ <gl-link v-if="closedPath" :href="closedPath">{{ closed }}</gl-link>
+ <template v-else>{{ closed }}</template>
+ </template>
+ </gl-sprintf>
+ </span>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue
index e9163a52792..b89e5f2df3f 100644
--- a/app/assets/javascripts/releases/components/release_block.vue
+++ b/app/assets/javascripts/releases/components/release_block.vue
@@ -87,9 +87,14 @@ export default {
<release-block-header :release="release" />
<div class="card-body">
<div v-if="shouldRenderMilestoneInfo">
+ <!-- TODO: Switch open* links to opened* once fields have been updated in GraphQL -->
<release-block-milestone-info
:milestones="milestones"
- :open-issues-path="release._links.issuesUrl"
+ :opened-issues-path="release._links.openedIssuesUrl"
+ :closed-issues-path="release._links.closedIssuesUrl"
+ :opened-merge-requests-path="release._links.openedMergeRequestsUrl"
+ :merged-merge-requests-path="release._links.mergedMergeRequestsUrl"
+ :closed-merge-requests-path="release._links.closedMergeRequestsUrl"
/>
<hr class="mb-3 mt-0" />
</div>
diff --git a/app/assets/javascripts/releases/components/release_block_milestone_info.vue b/app/assets/javascripts/releases/components/release_block_milestone_info.vue
index deff673cc17..daa9c3480f4 100644
--- a/app/assets/javascripts/releases/components/release_block_milestone_info.vue
+++ b/app/assets/javascripts/releases/components/release_block_milestone_info.vue
@@ -1,24 +1,16 @@
<script>
-import {
- GlProgressBar,
- GlLink,
- GlBadge,
- GlButton,
- GlTooltipDirective,
- GlSprintf,
-} from '@gitlab/ui';
-import { sum } from 'lodash';
+import { GlProgressBar, GlLink, GlButton, GlTooltipDirective } from '@gitlab/ui';
import { __, n__, sprintf } from '~/locale';
import { MAX_MILESTONES_TO_DISPLAY } from '../constants';
+import IssuableStats from './issuable_stats.vue';
export default {
name: 'ReleaseBlockMilestoneInfo',
components: {
GlProgressBar,
GlLink,
- GlBadge,
GlButton,
- GlSprintf,
+ IssuableStats,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -28,7 +20,7 @@ export default {
type: Array,
required: true,
},
- openIssuesPath: {
+ openedIssuesPath: {
type: String,
required: false,
default: '',
@@ -38,6 +30,21 @@ export default {
required: false,
default: '',
},
+ openedMergeRequestsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ mergedMergeRequestsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ closedMergeRequestsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
return {
@@ -52,30 +59,49 @@ export default {
});
},
percentComplete() {
- const percent = Math.round((this.closedIssuesCount / this.totalIssuesCount) * 100);
+ const percent = Math.round((this.issueCounts.closed / this.issueCounts.total) * 100);
return Number.isNaN(percent) ? 0 : percent;
},
- allIssueStats() {
- return this.milestones.map(m => m.issueStats || {});
- },
- totalIssuesCount() {
- return sum(this.allIssueStats.map(stats => stats.total || 0));
- },
- closedIssuesCount() {
- return sum(this.allIssueStats.map(stats => stats.closed || 0));
- },
- openIssuesCount() {
- return this.totalIssuesCount - this.closedIssuesCount;
+ issueCounts() {
+ return this.milestones
+ .map(m => m.issueStats || {})
+ .reduce(
+ (acc, current) => {
+ acc.total += current.total || 0;
+ acc.closed += current.closed || 0;
+
+ return acc;
+ },
+ {
+ total: 0,
+ closed: 0,
+ },
+ );
+ },
+ showMergeRequestStats() {
+ return this.milestones.some(m => m.mrStats);
+ },
+ mergeRequestCounts() {
+ return this.milestones
+ .map(m => m.mrStats || {})
+ .reduce(
+ (acc, current) => {
+ acc.total += current.total || 0;
+ acc.merged += current.merged || 0;
+ acc.closed += current.closed || 0;
+
+ return acc;
+ },
+ {
+ total: 0,
+ merged: 0,
+ closed: 0,
+ },
+ );
},
milestoneLabelText() {
return n__('Milestone', 'Milestones', this.milestones.length);
},
- issueCountsText() {
- return sprintf(__('Open: %{open} • Closed: %{closed}'), {
- open: this.openIssuesCount,
- closed: this.closedIssuesCount,
- });
- },
milestonesToDisplay() {
return this.showAllMilestones
? this.milestones
@@ -106,20 +132,22 @@ export default {
};
</script>
<template>
- <div class="release-block-milestone-info d-flex align-items-start flex-wrap">
+ <div class="release-block-milestone-info gl-display-flex gl-flex-wrap">
<div
v-gl-tooltip
- class="milestone-progress-bar-container js-milestone-progress-bar-container d-flex flex-column align-items-start flex-shrink-1 mr-4 mb-3"
+ class="milestone-progress-bar-container js-milestone-progress-bar-container gl-display-flex gl-flex-direction-column gl-mr-6 gl-mb-5"
:title="__('Closed issues')"
>
- <span class="mb-2">{{ percentCompleteText }}</span>
- <span class="w-100">
- <gl-progress-bar :value="closedIssuesCount" :max="totalIssuesCount" variant="success" />
+ <span class="gl-mb-3">{{ percentCompleteText }}</span>
+ <span class="gl-w-full">
+ <gl-progress-bar :value="issueCounts.closed" :max="issueCounts.total" variant="success" />
</span>
</div>
- <div class="d-flex flex-column align-items-start mr-4 mb-3 js-milestone-list-container">
- <span class="mb-1">{{ milestoneLabelText }}</span>
- <div class="d-flex flex-wrap align-items-end">
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-mr-6 gl-mb-5 js-milestone-list-container"
+ >
+ <span class="gl-mb-2">{{ milestoneLabelText }}</span>
+ <div class="gl-display-flex gl-flex-wrap gl-align-items-flex-end">
<template v-for="(milestone, index) in milestonesToDisplay">
<gl-link
:key="milestone.id"
@@ -141,32 +169,24 @@ export default {
</template>
</div>
</div>
- <div class="d-flex flex-column align-items-start flex-shrink-0 mr-4 mb-3 js-issues-container">
- <span class="mb-1">
- {{ __('Issues') }}
- <gl-badge variant="muted" size="sm">{{ totalIssuesCount }}</gl-badge>
- </span>
- <div class="d-flex">
- <gl-link v-if="openIssuesPath" ref="openIssuesLink" :href="openIssuesPath">
- <gl-sprintf :message="__('Open: %{openIssuesCount}')">
- <template #openIssuesCount>{{ openIssuesCount }}</template>
- </gl-sprintf>
- </gl-link>
- <span v-else ref="openIssuesText">
- {{ sprintf(__('Open: %{openIssuesCount}'), { openIssuesCount }) }}
- </span>
-
- <span class="mx-1">&bull;</span>
-
- <gl-link v-if="closedIssuesPath" ref="closedIssuesLink" :href="closedIssuesPath">
- <gl-sprintf :message="__('Closed: %{closedIssuesCount}')">
- <template #closedIssuesCount>{{ closedIssuesCount }}</template>
- </gl-sprintf>
- </gl-link>
- <span v-else ref="closedIssuesText">
- {{ sprintf(__('Closed: %{closedIssuesCount}'), { closedIssuesCount }) }}
- </span>
- </div>
- </div>
+ <issuable-stats
+ :label="__('Issues')"
+ :total="issueCounts.total"
+ :closed="issueCounts.closed"
+ :opened-path="openedIssuesPath"
+ :closed-path="closedIssuesPath"
+ data-testid="issue-stats"
+ />
+ <issuable-stats
+ v-if="showMergeRequestStats"
+ :label="__('Merge Requests')"
+ :total="mergeRequestCounts.total"
+ :merged="mergeRequestCounts.merged"
+ :closed="mergeRequestCounts.closed"
+ :opened-path="openedMergeRequestsPath"
+ :merged-path="mergedMergeRequestsPath"
+ :closed-path="closedMergeRequestsPath"
+ data-testid="merge-request-stats"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/releases/components/releases_sort.vue b/app/assets/javascripts/releases/components/releases_sort.vue
new file mode 100644
index 00000000000..50f6f3c19bd
--- /dev/null
+++ b/app/assets/javascripts/releases/components/releases_sort.vue
@@ -0,0 +1,62 @@
+<script>
+import { GlSorting, GlSortingItem } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
+import { ASCENDING_ODER, DESCENDING_ORDER, SORT_OPTIONS } from '../constants';
+
+export default {
+ name: 'ReleasesSort',
+ components: {
+ GlSorting,
+ GlSortingItem,
+ },
+ computed: {
+ ...mapState('list', {
+ orderBy: state => state.sorting.orderBy,
+ sort: state => state.sorting.sort,
+ }),
+ sortOptions() {
+ return SORT_OPTIONS;
+ },
+ sortText() {
+ const option = this.sortOptions.find(s => s.orderBy === this.orderBy);
+ return option.label;
+ },
+ isSortAscending() {
+ return this.sort === ASCENDING_ODER;
+ },
+ },
+ methods: {
+ ...mapActions('list', ['setSorting']),
+ onDirectionChange() {
+ const sort = this.isSortAscending ? DESCENDING_ORDER : ASCENDING_ODER;
+ this.setSorting({ sort });
+ this.$emit('sort:changed');
+ },
+ onSortItemClick(item) {
+ this.setSorting({ orderBy: item });
+ this.$emit('sort:changed');
+ },
+ isActiveSortItem(item) {
+ return this.orderBy === item;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-sorting
+ :text="sortText"
+ :is-ascending="isSortAscending"
+ data-testid="releases-sort"
+ @sortDirectionChange="onDirectionChange"
+ >
+ <gl-sorting-item
+ v-for="item in sortOptions"
+ :key="item.orderBy"
+ :active="isActiveSortItem(item.orderBy)"
+ @click="onSortItemClick(item.orderBy)"
+ >
+ {{ item.label }}
+ </gl-sorting-item>
+ </gl-sorting>
+</template>
diff --git a/app/assets/javascripts/releases/components/tag_field_existing.vue b/app/assets/javascripts/releases/components/tag_field_existing.vue
index b84e713df26..046885fe2f6 100644
--- a/app/assets/javascripts/releases/components/tag_field_existing.vue
+++ b/app/assets/javascripts/releases/components/tag_field_existing.vue
@@ -1,14 +1,14 @@
<script>
import { mapState } from 'vuex';
import { uniqueId } from 'lodash';
-import { GlFormGroup, GlFormInput, GlLink, GlSprintf } from '@gitlab/ui';
+import { GlFormGroup, GlFormInput } from '@gitlab/ui';
import FormFieldContainer from './form_field_container.vue';
export default {
name: 'TagFieldExisting',
- components: { GlFormGroup, GlFormInput, GlSprintf, GlLink, FormFieldContainer },
+ components: { GlFormGroup, GlFormInput, FormFieldContainer },
computed: {
- ...mapState('detail', ['release', 'updateReleaseApiDocsPath']),
+ ...mapState('detail', ['release']),
inputId() {
return uniqueId('tag-name-input-');
},
@@ -32,19 +32,7 @@ export default {
</form-field-container>
<template #description>
<div :id="helpId" data-testid="tag-name-help">
- <gl-sprintf
- :message="
- __(
- 'Changing a Release tag is only supported via Releases API. %{linkStart}More information%{linkEnd}',
- )
- "
- >
- <template #link="{ content }">
- <gl-link :href="updateReleaseApiDocsPath" target="_blank">
- {{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
+ {{ __("The tag name can't be changed for an existing release.") }}
</div>
</template>
</gl-form-group>
diff --git a/app/assets/javascripts/releases/constants.js b/app/assets/javascripts/releases/constants.js
index 953e7b4189c..8979aa1394d 100644
--- a/app/assets/javascripts/releases/constants.js
+++ b/app/assets/javascripts/releases/constants.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export const MAX_MILESTONES_TO_DISPLAY = 5;
export const BACK_URL_PARAM = 'back_url';
@@ -12,3 +14,19 @@ export const ASSET_LINK_TYPE = Object.freeze({
export const DEFAULT_ASSET_LINK_TYPE = ASSET_LINK_TYPE.OTHER;
export const PAGE_SIZE = 20;
+
+export const ASCENDING_ODER = 'asc';
+export const DESCENDING_ORDER = 'desc';
+export const RELEASED_AT = 'released_at';
+export const CREATED_AT = 'created_at';
+
+export const SORT_OPTIONS = [
+ {
+ orderBy: RELEASED_AT,
+ label: __('Released date'),
+ },
+ {
+ orderBy: CREATED_AT,
+ label: __('Created date'),
+ },
+];
diff --git a/app/assets/javascripts/releases/queries/all_releases.query.graphql b/app/assets/javascripts/releases/queries/all_releases.query.graphql
index c35306f163d..a07dabb9fd6 100644
--- a/app/assets/javascripts/releases/queries/all_releases.query.graphql
+++ b/app/assets/javascripts/releases/queries/all_releases.query.graphql
@@ -1,8 +1,15 @@
#import "./release.fragment.graphql"
-query allReleases($fullPath: ID!, $first: Int, $last: Int, $before: String, $after: String) {
+query allReleases(
+ $fullPath: ID!
+ $first: Int
+ $last: Int
+ $before: String
+ $after: String
+ $sort: ReleaseSort
+) {
project(fullPath: $fullPath) {
- releases(first: $first, last: $last, before: $before, after: $after) {
+ releases(first: $first, last: $last, before: $before, after: $after, sort: $sort) {
nodes {
...Release
}
diff --git a/app/assets/javascripts/releases/queries/release.fragment.graphql b/app/assets/javascripts/releases/queries/release.fragment.graphql
index 445ed616348..3a742db7d9e 100644
--- a/app/assets/javascripts/releases/queries/release.fragment.graphql
+++ b/app/assets/javascripts/releases/queries/release.fragment.graphql
@@ -4,6 +4,7 @@ fragment Release on Release {
tagPath
descriptionHtml
releasedAt
+ createdAt
upcomingRelease
assets {
count
@@ -33,9 +34,12 @@ fragment Release on Release {
}
links {
editUrl
- issuesUrl
- mergeRequestsUrl
selfUrl
+ openedIssuesUrl
+ closedIssuesUrl
+ openedMergeRequestsUrl
+ mergedMergeRequestsUrl
+ closedMergeRequestsUrl
}
commit {
sha
diff --git a/app/assets/javascripts/releases/stores/modules/detail/state.js b/app/assets/javascripts/releases/stores/modules/detail/state.js
index 782a5c46d6c..315d07ac664 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/state.js
+++ b/app/assets/javascripts/releases/stores/modules/detail/state.js
@@ -1,9 +1,10 @@
export default ({
projectId,
+ groupId,
+ groupMilestonesAvailable = false,
projectPath,
markdownDocsPath,
markdownPreviewPath,
- updateReleaseApiDocsPath,
releaseAssetsDocsPath,
manageMilestonesPath,
newMilestonePath,
@@ -13,10 +14,11 @@ export default ({
defaultBranch = null,
}) => ({
projectId,
+ groupId,
+ groupMilestonesAvailable: Boolean(groupMilestonesAvailable),
projectPath,
markdownDocsPath,
markdownPreviewPath,
- updateReleaseApiDocsPath,
releaseAssetsDocsPath,
manageMilestonesPath,
newMilestonePath,
diff --git a/app/assets/javascripts/releases/stores/modules/list/actions.js b/app/assets/javascripts/releases/stores/modules/list/actions.js
index 02e67415e63..a62f7c25464 100644
--- a/app/assets/javascripts/releases/stores/modules/list/actions.js
+++ b/app/assets/javascripts/releases/stores/modules/list/actions.js
@@ -42,6 +42,10 @@ export const fetchReleasesGraphQl = (
) => {
commit(types.REQUEST_RELEASES);
+ const { sort, orderBy } = state.sorting;
+ const orderByParam = orderBy === 'created_at' ? 'created' : orderBy;
+ const sortParams = `${orderByParam}_${sort}`.toUpperCase();
+
let paginationParams;
if (!before && !after) {
paginationParams = { first: PAGE_SIZE };
@@ -60,6 +64,7 @@ export const fetchReleasesGraphQl = (
query: allReleasesQuery,
variables: {
fullPath: state.projectPath,
+ sort: sortParams,
...paginationParams,
},
})
@@ -80,8 +85,10 @@ export const fetchReleasesGraphQl = (
export const fetchReleasesRest = ({ dispatch, commit, state }, { page }) => {
commit(types.REQUEST_RELEASES);
+ const { sort, orderBy } = state.sorting;
+
api
- .releases(state.projectId, { page })
+ .releases(state.projectId, { page, sort, order_by: orderBy })
.then(({ data, headers }) => {
const restPageInfo = parseIntPagination(normalizeHeaders(headers));
const camelCasedReleases = convertObjectPropsToCamelCase(data, { deep: true });
@@ -98,3 +105,5 @@ export const receiveReleasesError = ({ commit }) => {
commit(types.RECEIVE_RELEASES_ERROR);
createFlash(__('An error occurred while fetching the releases. Please try again.'));
};
+
+export const setSorting = ({ commit }, data) => commit(types.SET_SORTING, data);
diff --git a/app/assets/javascripts/releases/stores/modules/list/mutation_types.js b/app/assets/javascripts/releases/stores/modules/list/mutation_types.js
index a74bf15c515..669168efb88 100644
--- a/app/assets/javascripts/releases/stores/modules/list/mutation_types.js
+++ b/app/assets/javascripts/releases/stores/modules/list/mutation_types.js
@@ -1,3 +1,4 @@
export const REQUEST_RELEASES = 'REQUEST_RELEASES';
export const RECEIVE_RELEASES_SUCCESS = 'RECEIVE_RELEASES_SUCCESS';
export const RECEIVE_RELEASES_ERROR = 'RECEIVE_RELEASES_ERROR';
+export const SET_SORTING = 'SET_SORTING';
diff --git a/app/assets/javascripts/releases/stores/modules/list/mutations.js b/app/assets/javascripts/releases/stores/modules/list/mutations.js
index 296487cfee2..e1aaa2e2a19 100644
--- a/app/assets/javascripts/releases/stores/modules/list/mutations.js
+++ b/app/assets/javascripts/releases/stores/modules/list/mutations.js
@@ -39,4 +39,8 @@ export default {
state.restPageInfo = {};
state.graphQlPageInfo = {};
},
+
+ [types.SET_SORTING](state, sorting) {
+ state.sorting = { ...state.sorting, ...sorting };
+ },
};
diff --git a/app/assets/javascripts/releases/stores/modules/list/state.js b/app/assets/javascripts/releases/stores/modules/list/state.js
index 0bffaa0f9db..164a496d450 100644
--- a/app/assets/javascripts/releases/stores/modules/list/state.js
+++ b/app/assets/javascripts/releases/stores/modules/list/state.js
@@ -1,3 +1,5 @@
+import { DESCENDING_ORDER, RELEASED_AT } from '../../../constants';
+
export default ({
projectId,
projectPath,
@@ -16,4 +18,8 @@ export default ({
releases: [],
restPageInfo: {},
graphQlPageInfo: {},
+ sorting: {
+ sort: DESCENDING_ORDER,
+ orderBy: RELEASED_AT,
+ },
});
diff --git a/app/assets/javascripts/releases/util.js b/app/assets/javascripts/releases/util.js
index 445c429fd96..464f0594b8d 100644
--- a/app/assets/javascripts/releases/util.js
+++ b/app/assets/javascripts/releases/util.js
@@ -15,7 +15,9 @@ import {
export const releaseToApiJson = (release, createFrom = null) => {
const name = release.name?.trim().length > 0 ? release.name.trim() : null;
- const milestones = release.milestones ? release.milestones.map(milestone => milestone.title) : [];
+ // Milestones may be either a list of milestone objects OR just a list
+ // of milestone titles. The API requires only the titles be sent.
+ const milestones = (release.milestones || []).map(m => m.title || m);
return convertObjectPropsToSnakeCase(
{
diff --git a/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue b/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue
index 0c758ee2b5c..d0a5615bb57 100644
--- a/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue
+++ b/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue
@@ -3,15 +3,21 @@
* Renders Code quality body text
* Fixed: [name] in [link]:[line]
*/
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import ReportLink from '~/reports/components/report_link.vue';
import { STATUS_SUCCESS } from '~/reports/constants';
+import { s__ } from '~/locale';
+import { SEVERITY_CLASSES, SEVERITY_ICONS } from '../constants';
export default {
name: 'CodequalityIssueBody',
-
components: {
+ GlIcon,
ReportLink,
},
+ directives: {
+ tooltip: GlTooltipDirective,
+ },
props: {
status: {
type: String,
@@ -23,20 +29,44 @@ export default {
},
},
computed: {
+ issueName() {
+ return `${this.severityLabel} - ${this.issue.name}`;
+ },
isStatusSuccess() {
return this.status === STATUS_SUCCESS;
},
+ severityClass() {
+ return SEVERITY_CLASSES[this.issue.severity] || SEVERITY_CLASSES.unknown;
+ },
+ severityIcon() {
+ return SEVERITY_ICONS[this.issue.severity] || SEVERITY_ICONS.unknown;
+ },
+ severityLabel() {
+ return this.$options.severityText[this.issue.severity] || this.$options.severityText.unknown;
+ },
+ },
+ severityText: {
+ info: s__('severity|Info'),
+ minor: s__('severity|Minor'),
+ major: s__('severity|Major'),
+ critical: s__('severity|Critical'),
+ blocker: s__('severity|Blocker'),
+ unknown: s__('severity|Unknown'),
},
};
</script>
<template>
- <div class="report-block-list-issue-description gl-mt-2 gl-mb-2">
- <div class="report-block-list-issue-description-text">
- <template v-if="isStatusSuccess">{{ s__('ciReport|Fixed:') }}</template>
+ <div class="gl-display-flex gl-mt-2 gl-mb-2 gl-w-full">
+ <span :class="severityClass" class="gl-mr-5" data-testid="codequality-severity-icon">
+ <gl-icon v-tooltip="severityLabel" :name="severityIcon" :size="12" />
+ </span>
+ <div class="gl-flex-fill-1">
+ <div>
+ <strong v-if="isStatusSuccess">{{ s__('ciReport|Fixed:') }}</strong>
+ {{ issueName }}
+ </div>
- {{ issue.name }}
+ <report-link v-if="issue.path" :issue="issue" />
</div>
-
- <report-link v-if="issue.path" :issue="issue" />
</div>
</template>
diff --git a/app/assets/javascripts/reports/codequality_report/constants.js b/app/assets/javascripts/reports/codequality_report/constants.js
new file mode 100644
index 00000000000..502977e714c
--- /dev/null
+++ b/app/assets/javascripts/reports/codequality_report/constants.js
@@ -0,0 +1,17 @@
+export const SEVERITY_CLASSES = {
+ info: 'text-primary-400',
+ minor: 'text-warning-200',
+ major: 'text-warning-400',
+ critical: 'text-danger-600',
+ blocker: 'text-danger-800',
+ unknown: 'text-secondary-400',
+};
+
+export const SEVERITY_ICONS = {
+ info: 'severity-info',
+ minor: 'severity-low',
+ major: 'severity-medium',
+ critical: 'severity-high',
+ blocker: 'severity-critical',
+ unknown: 'severity-unknown',
+};
diff --git a/app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue b/app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue
index f3d5b1a80f8..5c8f31d7da0 100644
--- a/app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue
+++ b/app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue
@@ -78,6 +78,7 @@ export default {
:has-issues="hasCodequalityIssues"
:component="$options.componentNames.CodequalityIssueBody"
:popover-options="codequalityPopover"
+ :show-report-section-status-icon="false"
class="js-codequality-widget mr-widget-border-top mr-report"
/>
</template>
diff --git a/app/assets/javascripts/reports/codequality_report/store/getters.js b/app/assets/javascripts/reports/codequality_report/store/getters.js
index 5df58c7f85f..d7c31bcf459 100644
--- a/app/assets/javascripts/reports/codequality_report/store/getters.js
+++ b/app/assets/javascripts/reports/codequality_report/store/getters.js
@@ -1,5 +1,6 @@
import { LOADING, ERROR, SUCCESS } from '../../constants';
import { sprintf, __, s__, n__ } from '~/locale';
+import { spriteIcon } from '~/lib/utils/common_utils';
export const hasCodequalityIssues = state =>
Boolean(state.newIssues?.length || state.resolvedIssues?.length);
@@ -48,7 +49,7 @@ export const codequalityPopover = state => {
s__('ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}'),
{
linkStartTag: `<a href="${state.helpPath}" target="_blank" rel="noopener noreferrer">`,
- linkEndTag: '<i class="fa fa-external-link" aria-hidden="true"></i></a>',
+ linkEndTag: `${spriteIcon('external-link', 's16')}</a>`,
},
false,
),
diff --git a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
index 47f04019595..c13df60198b 100644
--- a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
+++ b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
@@ -1,5 +1,6 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
+import { once } from 'lodash';
import { GlButton } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
import { componentNames } from './issue_body';
@@ -8,8 +9,14 @@ import SummaryRow from './summary_row.vue';
import IssuesList from './issues_list.vue';
import Modal from './modal.vue';
import createStore from '../store';
+import Tracking from '~/tracking';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { summaryTextBuilder, reportTextBuilder, statusIcon } from '../store/utils';
+import {
+ summaryTextBuilder,
+ reportTextBuilder,
+ statusIcon,
+ recentFailuresTextBuilder,
+} from '../store/utils';
export default {
name: 'GroupedTestReportsApp',
@@ -21,7 +28,7 @@ export default {
Modal,
GlButton,
},
- mixins: [glFeatureFlagsMixin()],
+ mixins: [glFeatureFlagsMixin(), Tracking.mixin()],
props: {
endpoint: {
type: String,
@@ -58,6 +65,11 @@ export default {
showViewFullReport() {
return this.pipelinePath.length;
},
+ handleToggleEvent() {
+ return once(() => {
+ this.track(this.$options.expandEvent);
+ });
+ },
},
created() {
this.setEndpoint(this.endpoint);
@@ -79,6 +91,12 @@ export default {
return reportTextBuilder(name, summary);
},
+ hasRecentFailures(summary) {
+ return this.glFeatures.testFailureHistory && summary?.recentlyFailed > 0;
+ },
+ recentFailuresText(summary) {
+ return recentFailuresTextBuilder(summary);
+ },
getReportIcon(report) {
return statusIcon(report.status);
},
@@ -102,6 +120,7 @@ export default {
return report.resolved_failures.concat(report.resolved_errors);
},
},
+ expandEvent: 'expand_test_report_widget',
};
</script>
<template>
@@ -111,9 +130,11 @@ export default {
:loading-text="groupedSummaryText"
:error-text="groupedSummaryText"
:has-issues="reports.length > 0"
+ :should-emit-toggle-event="true"
class="mr-widget-section grouped-security-reports mr-report"
+ @toggleEvent="handleToggleEvent"
>
- <template v-if="showViewFullReport" #actionButtons>
+ <template v-if="showViewFullReport" #action-buttons>
<gl-button
:href="testTabURL"
target="_blank"
@@ -124,14 +145,22 @@ export default {
{{ s__('ciReport|View full report') }}
</gl-button>
</template>
+ <template v-if="hasRecentFailures(summary)" #sub-heading>
+ {{ recentFailuresText(summary) }}
+ </template>
<template #body>
<div class="mr-widget-grouped-section report-block">
<template v-for="(report, i) in reports">
- <summary-row
- :key="`summary-row-${i}`"
- :summary="reportText(report)"
- :status-icon="getReportIcon(report)"
- />
+ <summary-row :key="`summary-row-${i}`" :status-icon="getReportIcon(report)">
+ <template #summary>
+ <div class="gl-display-inline-flex gl-flex-direction-column">
+ <div>{{ reportText(report) }}</div>
+ <div v-if="hasRecentFailures(report.summary)">
+ {{ recentFailuresText(report.summary) }}
+ </div>
+ </div>
+ </template>
+ </summary-row>
<issues-list
v-if="shouldRenderIssuesList(report)"
:key="`issues-list-${i}`"
diff --git a/app/assets/javascripts/reports/components/report_section.vue b/app/assets/javascripts/reports/components/report_section.vue
index 63af8a5a9ac..f245e2bfd2f 100644
--- a/app/assets/javascripts/reports/components/report_section.vue
+++ b/app/assets/javascripts/reports/components/report_section.vue
@@ -181,14 +181,15 @@ export default {
<slot :name="slotName"></slot>
<popover v-if="hasPopover" :options="popoverOptions" class="gl-ml-2" />
</div>
- <slot name="subHeading"></slot>
+ <slot name="sub-heading"></slot>
</div>
- <slot name="actionButtons"></slot>
+ <slot name="action-buttons"></slot>
<button
v-if="isCollapsible"
type="button"
+ data-testid="report-section-expand-button"
class="js-collapse-btn btn float-right btn-sm align-self-center qa-expand-report-button"
@click="toggleCollapsed"
>
diff --git a/app/assets/javascripts/reports/components/test_issue_body.vue b/app/assets/javascripts/reports/components/test_issue_body.vue
index 4e0631740d8..5e9a5b03543 100644
--- a/app/assets/javascripts/reports/components/test_issue_body.vue
+++ b/app/assets/javascripts/reports/components/test_issue_body.vue
@@ -1,8 +1,15 @@
<script>
import { mapActions } from 'vuex';
+import { GlBadge } from '@gitlab/ui';
+import { n__ } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'TestIssueBody',
+ components: {
+ GlBadge,
+ },
+ mixins: [glFeatureFlagsMixin()],
props: {
issue: {
type: Object,
@@ -19,8 +26,20 @@ export default {
default: false,
},
},
+ computed: {
+ showRecentFailures() {
+ return this.glFeatures.testFailureHistory && this.issue.recent_failures;
+ },
+ },
methods: {
...mapActions(['openModal']),
+ recentFailuresText(count) {
+ return n__(
+ 'Failed %d time in the last 14 days',
+ 'Failed %d times in the last 14 days',
+ count,
+ );
+ },
},
};
</script>
@@ -32,7 +51,10 @@ export default {
class="btn-link btn-blank text-left break-link vulnerability-name-button"
@click="openModal({ issue })"
>
- <div v-if="isNew" class="badge badge-danger gl-mr-2">{{ s__('New') }}</div>
+ <gl-badge v-if="isNew" variant="danger" class="gl-mr-2">{{ s__('New') }}</gl-badge>
+ <gl-badge v-if="showRecentFailures" variant="warning" class="gl-mr-2">
+ {{ recentFailuresText(issue.recent_failures) }}
+ </gl-badge>
{{ issue.name }}
</button>
</div>
diff --git a/app/assets/javascripts/reports/store/mutations.js b/app/assets/javascripts/reports/store/mutations.js
index 35ab72bf694..acaa98754b0 100644
--- a/app/assets/javascripts/reports/store/mutations.js
+++ b/app/assets/javascripts/reports/store/mutations.js
@@ -1,4 +1,5 @@
import * as types from './mutation_types';
+import { countRecentlyFailedTests } from './utils';
export default {
[types.SET_ENDPOINT](state, endpoint) {
@@ -16,9 +17,15 @@ export default {
state.summary.resolved = response.summary.resolved;
state.summary.failed = response.summary.failed;
state.summary.errored = response.summary.errored;
+ state.summary.recentlyFailed = countRecentlyFailedTests(response.suites);
state.status = response.status;
state.reports = response.suites;
+
+ state.reports.forEach((report, i) => {
+ if (!state.reports[i].summary) return;
+ state.reports[i].summary.recentlyFailed = countRecentlyFailedTests(report);
+ });
},
[types.RECEIVE_REPORTS_ERROR](state) {
state.isLoading = false;
@@ -30,6 +37,7 @@ export default {
resolved: 0,
failed: 0,
errored: 0,
+ recentlyFailed: 0,
};
state.status = null;
},
diff --git a/app/assets/javascripts/reports/store/utils.js b/app/assets/javascripts/reports/store/utils.js
index 5d3d9ddda3b..fd6f4933cfa 100644
--- a/app/assets/javascripts/reports/store/utils.js
+++ b/app/assets/javascripts/reports/store/utils.js
@@ -48,6 +48,48 @@ export const reportTextBuilder = (name = '', results = {}) => {
return sprintf(__('%{name} found %{resultsString}'), { name, resultsString });
};
+export const recentFailuresTextBuilder = (summary = {}) => {
+ const { failed, recentlyFailed } = summary;
+ if (!failed || !recentlyFailed) return '';
+
+ if (failed < 2) {
+ return sprintf(
+ s__(
+ 'Reports|%{recentlyFailed} out of %{failed} failed test has failed more than once in the last 14 days',
+ ),
+ { recentlyFailed, failed },
+ );
+ }
+ return sprintf(
+ n__(
+ s__(
+ 'Reports|%{recentlyFailed} out of %{failed} failed tests has failed more than once in the last 14 days',
+ ),
+ s__(
+ 'Reports|%{recentlyFailed} out of %{failed} failed tests have failed more than once in the last 14 days',
+ ),
+ recentlyFailed,
+ ),
+ { recentlyFailed, failed },
+ );
+};
+
+export const countRecentlyFailedTests = subject => {
+ // handle either a single report or an array of reports
+ const reports = !subject.length ? [subject] : subject;
+
+ return reports
+ .map(report => {
+ return (
+ [report.new_failures, report.existing_failures, report.resolved_failures]
+ // only count tests which have failed more than once
+ .map(failureArray => failureArray.filter(failure => failure.recent_failures > 1).length)
+ .reduce((total, count) => total + count, 0)
+ );
+ })
+ .reduce((total, count) => total + count, 0);
+};
+
export const statusIcon = status => {
if (status === STATUS_FAILED) {
return ICON_WARNING;
diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue
index 677cb265942..a1f1c77df2f 100644
--- a/app/assets/javascripts/repository/components/breadcrumbs.vue
+++ b/app/assets/javascripts/repository/components/breadcrumbs.vue
@@ -6,12 +6,12 @@ import {
GlDropdownItem,
GlIcon,
} from '@gitlab/ui';
+import permissionsQuery from 'shared_queries/repository/permissions.query.graphql';
import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
import { __ } from '../../locale';
import getRefMixin from '../mixins/get_ref';
import projectShortPathQuery from '../queries/project_short_path.query.graphql';
import projectPathQuery from '../queries/project_path.query.graphql';
-import permissionsQuery from '../queries/permissions.query.graphql';
const ROW_TYPES = {
header: 'header',
diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue
index 0e2bccfabdd..2626bace363 100644
--- a/app/assets/javascripts/repository/components/last_commit.vue
+++ b/app/assets/javascripts/repository/components/last_commit.vue
@@ -137,8 +137,8 @@ export default {
:href="commit.author.webPath"
class="commit-author-link js-user-link"
>
- {{ commit.author.name }}
- </gl-link>
+ {{ commit.author.name }}</gl-link
+ >
<template v-else>
{{ commit.authorName }}
</template>
diff --git a/app/assets/javascripts/repository/components/preview/index.vue b/app/assets/javascripts/repository/components/preview/index.vue
index 4e2c8332f37..c9c5aa37645 100644
--- a/app/assets/javascripts/repository/components/preview/index.vue
+++ b/app/assets/javascripts/repository/components/preview/index.vue
@@ -58,7 +58,7 @@ export default {
</gl-link>
</div>
</div>
- <div class="blob-viewer" data-qa-selector="blob_viewer_content">
+ <div class="blob-viewer" data-qa-selector="blob_viewer_content" itemprop="about">
<gl-loading-icon v-if="loading > 0" size="md" color="dark" class="my-4 mx-auto" />
<div v-else-if="readme" ref="readme" v-html="readme.html"></div>
</div>
diff --git a/app/assets/javascripts/repository/components/tree_action_link.vue b/app/assets/javascripts/repository/components/tree_action_link.vue
index 72764f3ccc9..c5ab150adaf 100644
--- a/app/assets/javascripts/repository/components/tree_action_link.vue
+++ b/app/assets/javascripts/repository/components/tree_action_link.vue
@@ -24,5 +24,5 @@ export default {
</script>
<template>
- <gl-link :href="path" :class="cssClass" class="btn">{{ text }}</gl-link>
+ <gl-link :href="path" :class="cssClass" class="btn gl-button">{{ text }}</gl-link>
</template>
diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue
index 78b8baaa75e..b42f88631b5 100644
--- a/app/assets/javascripts/repository/components/tree_content.vue
+++ b/app/assets/javascripts/repository/components/tree_content.vue
@@ -1,9 +1,9 @@
<script>
+import filesQuery from 'shared_queries/repository/files.query.graphql';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __ } from '../../locale';
import FileTable from './table/index.vue';
import getRefMixin from '../mixins/get_ref';
-import filesQuery from '../queries/files.query.graphql';
import projectPathQuery from '../queries/project_path.query.graphql';
import FilePreview from './preview/index.vue';
import { readmeFile } from '../utils/readme';
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js
index a62b2d96c54..f56b141fe5c 100644
--- a/app/assets/javascripts/repository/index.js
+++ b/app/assets/javascripts/repository/index.js
@@ -1,5 +1,4 @@
import Vue from 'vue';
-import PathLastCommitQuery from 'shared_queries/repository/path_last_commit.query.graphql';
import { escapeFileUrl } from '../lib/utils/url_utility';
import createRouter from './router';
import App from './components/app.vue';
@@ -19,10 +18,6 @@ export default function setupVueRepositoryList() {
const { dataset } = el;
const { projectPath, projectShortPath, ref, escapedRef, fullName } = dataset;
const router = createRouter(projectPath, escapedRef);
- const pathRegex = /-\/tree\/[^/]+\/(.+$)/;
- const matches = window.location.href.match(pathRegex);
-
- const currentRoutePath = matches ? matches[1] : '';
apolloProvider.clients.defaultClient.cache.writeData({
data: {
@@ -48,28 +43,7 @@ export default function setupVueRepositoryList() {
},
});
- if (window.gl.startup_graphql_calls) {
- const query = window.gl.startup_graphql_calls.find(
- call => call.operationName === 'pathLastCommit',
- );
- query.fetchCall
- .then(res => res.json())
- .then(res => {
- apolloProvider.clients.defaultClient.writeQuery({
- query: PathLastCommitQuery,
- data: res.data,
- variables: {
- projectPath,
- ref,
- path: currentRoutePath,
- },
- });
- })
- .catch(() => {})
- .finally(() => initLastCommitApp());
- } else {
- initLastCommitApp();
- }
+ initLastCommitApp();
router.afterEach(({ params: { path } }) => {
setTitle(path, ref, fullName);
diff --git a/app/assets/javascripts/repository/mixins/preload.js b/app/assets/javascripts/repository/mixins/preload.js
index cb1d7f3aac9..c1607866941 100644
--- a/app/assets/javascripts/repository/mixins/preload.js
+++ b/app/assets/javascripts/repository/mixins/preload.js
@@ -1,4 +1,4 @@
-import filesQuery from '../queries/files.query.graphql';
+import filesQuery from 'shared_queries/repository/files.query.graphql';
import getRefMixin from './get_ref';
import projectPathQuery from '../queries/project_path.query.graphql';
diff --git a/app/assets/javascripts/repository/queries/files.query.graphql b/app/assets/javascripts/repository/queries/files.query.graphql
deleted file mode 100644
index 9e9f5303dd4..00000000000
--- a/app/assets/javascripts/repository/queries/files.query.graphql
+++ /dev/null
@@ -1,60 +0,0 @@
-#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
-
-fragment TreeEntry on Entry {
- id
- sha
- name
- flatPath
- type
-}
-
-query getFiles(
- $projectPath: ID!
- $path: String
- $ref: String!
- $pageSize: Int!
- $nextPageCursor: String
-) {
- project(fullPath: $projectPath) {
- repository {
- tree(path: $path, ref: $ref) {
- trees(first: $pageSize, after: $nextPageCursor) {
- edges {
- node {
- ...TreeEntry
- webPath
- }
- }
- pageInfo {
- ...PageInfo
- }
- }
- submodules(first: $pageSize, after: $nextPageCursor) {
- edges {
- node {
- ...TreeEntry
- webUrl
- treeUrl
- }
- }
- pageInfo {
- ...PageInfo
- }
- }
- blobs(first: $pageSize, after: $nextPageCursor) {
- edges {
- node {
- ...TreeEntry
- mode
- webPath
- lfsOid
- }
- }
- pageInfo {
- ...PageInfo
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/repository/queries/permissions.query.graphql b/app/assets/javascripts/repository/queries/permissions.query.graphql
deleted file mode 100644
index 092fa44e2d0..00000000000
--- a/app/assets/javascripts/repository/queries/permissions.query.graphql
+++ /dev/null
@@ -1,9 +0,0 @@
-query getPermissions($projectPath: ID!) {
- project(fullPath: $projectPath) {
- userPermissions {
- pushCode
- forkProject
- createMergeRequestIn
- }
- }
-}
diff --git a/app/assets/javascripts/search/dropdown_filter/components/dropdown_filter.vue b/app/assets/javascripts/search/dropdown_filter/components/dropdown_filter.vue
deleted file mode 100644
index b6e2dd46358..00000000000
--- a/app/assets/javascripts/search/dropdown_filter/components/dropdown_filter.vue
+++ /dev/null
@@ -1,100 +0,0 @@
-<script>
-import { mapState } from 'vuex';
-import { GlDropdown, GlDropdownItem, GlDropdownDivider } from '@gitlab/ui';
-import { setUrlParams, visitUrl } from '~/lib/utils/url_utility';
-import { sprintf, s__ } from '~/locale';
-
-export default {
- name: 'DropdownFilter',
- components: {
- GlDropdown,
- GlDropdownItem,
- GlDropdownDivider,
- },
- props: {
- filterData: {
- type: Object,
- required: true,
- },
- },
- computed: {
- ...mapState(['query']),
- scope() {
- return this.query.scope;
- },
- supportedScopes() {
- return Object.values(this.filterData.scopes);
- },
- initialFilter() {
- return this.query[this.filterData.filterParam];
- },
- filter() {
- return this.initialFilter || this.filterData.filters.ANY.value;
- },
- filtersArray() {
- return this.filterData.filterByScope[this.scope];
- },
- selectedFilter: {
- get() {
- if (this.filtersArray.some(({ value }) => value === this.filter)) {
- return this.filter;
- }
-
- return this.filterData.filters.ANY.value;
- },
- set(filter) {
- visitUrl(setUrlParams({ [this.filterData.filterParam]: filter }));
- },
- },
- selectedFilterText() {
- const f = this.filtersArray.find(({ value }) => value === this.selectedFilter);
- if (!f || f === this.filterData.filters.ANY) {
- return sprintf(s__('Any %{header}'), { header: this.filterData.header });
- }
-
- return f.label;
- },
- showDropdown() {
- return this.supportedScopes.includes(this.scope);
- },
- },
- methods: {
- dropDownItemClass(filter) {
- return {
- 'gl-border-b-solid gl-border-b-gray-100 gl-border-b-1 gl-pb-2! gl-mb-2':
- filter === this.filterData.filters.ANY,
- };
- },
- isFilterSelected(filter) {
- return filter === this.selectedFilter;
- },
- handleFilterChange(filter) {
- this.selectedFilter = filter;
- },
- },
-};
-</script>
-
-<template>
- <gl-dropdown
- v-if="showDropdown"
- :text="selectedFilterText"
- class="col-3 gl-pt-4 gl-pl-0 gl-pr-0 gl-mr-4"
- menu-class="gl-w-full! gl-pl-0"
- >
- <header class="gl-text-center gl-font-weight-bold gl-font-lg">
- {{ filterData.header }}
- </header>
- <gl-dropdown-divider />
- <gl-dropdown-item
- v-for="f in filtersArray"
- :key="f.value"
- :is-check-item="true"
- :is-checked="isFilterSelected(f.value)"
- :class="dropDownItemClass(f)"
- @click="handleFilterChange(f.value)"
- >
- {{ f.label }}
- </gl-dropdown-item>
- </gl-dropdown>
-</template>
diff --git a/app/assets/javascripts/search/dropdown_filter/constants/confidential_filter_data.js b/app/assets/javascripts/search/dropdown_filter/constants/confidential_filter_data.js
deleted file mode 100644
index b29daca89cb..00000000000
--- a/app/assets/javascripts/search/dropdown_filter/constants/confidential_filter_data.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import { __ } from '~/locale';
-
-const header = __('Confidentiality');
-
-const filters = {
- ANY: {
- label: __('Any'),
- value: null,
- },
- CONFIDENTIAL: {
- label: __('Confidential'),
- value: 'yes',
- },
- NOT_CONFIDENTIAL: {
- label: __('Not confidential'),
- value: 'no',
- },
-};
-
-const scopes = {
- ISSUES: 'issues',
-};
-
-const filterByScope = {
- [scopes.ISSUES]: [filters.ANY, filters.CONFIDENTIAL, filters.NOT_CONFIDENTIAL],
-};
-
-const filterParam = 'confidential';
-
-export default {
- header,
- filters,
- scopes,
- filterByScope,
- filterParam,
-};
diff --git a/app/assets/javascripts/search/dropdown_filter/constants/state_filter_data.js b/app/assets/javascripts/search/dropdown_filter/constants/state_filter_data.js
deleted file mode 100644
index 0b93aa0be29..00000000000
--- a/app/assets/javascripts/search/dropdown_filter/constants/state_filter_data.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import { __ } from '~/locale';
-
-const header = __('Status');
-
-const filters = {
- ANY: {
- label: __('Any'),
- value: 'all',
- },
- OPEN: {
- label: __('Open'),
- value: 'opened',
- },
- CLOSED: {
- label: __('Closed'),
- value: 'closed',
- },
- MERGED: {
- label: __('Merged'),
- value: 'merged',
- },
-};
-
-const scopes = {
- ISSUES: 'issues',
- MERGE_REQUESTS: 'merge_requests',
-};
-
-const filterByScope = {
- [scopes.ISSUES]: [filters.ANY, filters.OPEN, filters.CLOSED],
- [scopes.MERGE_REQUESTS]: [filters.ANY, filters.OPEN, filters.MERGED, filters.CLOSED],
-};
-
-const filterParam = 'state';
-
-export default {
- header,
- filters,
- scopes,
- filterByScope,
- filterParam,
-};
diff --git a/app/assets/javascripts/search/dropdown_filter/index.js b/app/assets/javascripts/search/dropdown_filter/index.js
deleted file mode 100644
index e5e0745d990..00000000000
--- a/app/assets/javascripts/search/dropdown_filter/index.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
-import DropdownFilter from './components/dropdown_filter.vue';
-import stateFilterData from './constants/state_filter_data';
-import confidentialFilterData from './constants/confidential_filter_data';
-
-Vue.use(Translate);
-
-const mountDropdownFilter = (store, { id, filterData }) => {
- const el = document.getElementById(id);
-
- if (!el) return false;
-
- return new Vue({
- el,
- store,
- render(createElement) {
- return createElement(DropdownFilter, {
- props: {
- filterData,
- },
- });
- },
- });
-};
-
-const dropdownFilters = [
- {
- id: 'js-search-filter-by-state',
- filterData: stateFilterData,
- },
- {
- id: 'js-search-filter-by-confidential',
- filterData: confidentialFilterData,
- },
-];
-
-export default store => [...dropdownFilters].map(filter => mountDropdownFilter(store, filter));
diff --git a/app/assets/javascripts/search/group_filter/components/group_filter.vue b/app/assets/javascripts/search/group_filter/components/group_filter.vue
new file mode 100644
index 00000000000..4b7963c5187
--- /dev/null
+++ b/app/assets/javascripts/search/group_filter/components/group_filter.vue
@@ -0,0 +1,124 @@
+<script>
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ GlLoadingIcon,
+ GlIcon,
+ GlSkeletonLoader,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
+import { isEmpty } from 'lodash';
+import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
+import { ANY_GROUP, GROUP_QUERY_PARAM, PROJECT_QUERY_PARAM } from '../constants';
+
+export default {
+ name: 'GroupFilter',
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ GlLoadingIcon,
+ GlIcon,
+ GlSkeletonLoader,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ initialGroup: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ },
+ data() {
+ return {
+ groupSearch: '',
+ };
+ },
+ computed: {
+ ...mapState(['groups', 'fetchingGroups']),
+ selectedGroup: {
+ get() {
+ return isEmpty(this.initialGroup) ? ANY_GROUP : this.initialGroup;
+ },
+ set(group) {
+ visitUrl(setUrlParams({ [GROUP_QUERY_PARAM]: group.id, [PROJECT_QUERY_PARAM]: null }));
+ },
+ },
+ },
+ methods: {
+ ...mapActions(['fetchGroups']),
+ isGroupSelected(group) {
+ return group.id === this.selectedGroup.id;
+ },
+ handleGroupChange(group) {
+ this.selectedGroup = group;
+ },
+ },
+ ANY_GROUP,
+};
+</script>
+
+<template>
+ <gl-dropdown
+ ref="groupFilter"
+ class="gl-w-full"
+ menu-class="gl-w-full!"
+ toggle-class="gl-text-truncate gl-reset-line-height!"
+ :header-text="__('Filter results by group')"
+ @show="fetchGroups(groupSearch)"
+ >
+ <template #button-content>
+ <span class="dropdown-toggle-text gl-flex-grow-1 gl-text-truncate">
+ {{ selectedGroup.name }}
+ </span>
+ <gl-loading-icon v-if="fetchingGroups" inline class="mr-2" />
+ <gl-icon
+ v-if="!isGroupSelected($options.ANY_GROUP)"
+ v-gl-tooltip
+ name="clear"
+ :title="__('Clear')"
+ class="gl-text-gray-200! gl-hover-text-blue-800!"
+ @click.stop="handleGroupChange($options.ANY_GROUP)"
+ />
+ <gl-icon name="chevron-down" />
+ </template>
+ <div class="gl-sticky gl-top-0 gl-z-index-1 gl-bg-white">
+ <gl-search-box-by-type
+ v-model="groupSearch"
+ class="m-2"
+ :debounce="500"
+ @input="fetchGroups"
+ />
+ <gl-dropdown-item
+ class="gl-border-b-solid gl-border-b-gray-100 gl-border-b-1 gl-pb-2! gl-mb-2"
+ :is-check-item="true"
+ :is-checked="isGroupSelected($options.ANY_GROUP)"
+ @click="handleGroupChange($options.ANY_GROUP)"
+ >
+ {{ $options.ANY_GROUP.name }}
+ </gl-dropdown-item>
+ </div>
+ <div v-if="!fetchingGroups">
+ <gl-dropdown-item
+ v-for="group in groups"
+ :key="group.id"
+ :is-check-item="true"
+ :is-checked="isGroupSelected(group)"
+ @click="handleGroupChange(group)"
+ >
+ {{ group.full_name }}
+ </gl-dropdown-item>
+ </div>
+ <div v-if="fetchingGroups" class="mx-3 mt-2">
+ <gl-skeleton-loader :height="100">
+ <rect y="0" width="90%" height="20" rx="4" />
+ <rect y="40" width="70%" height="20" rx="4" />
+ <rect y="80" width="80%" height="20" rx="4" />
+ </gl-skeleton-loader>
+ </div>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/search/group_filter/constants.js b/app/assets/javascripts/search/group_filter/constants.js
new file mode 100644
index 00000000000..9bd92eaa130
--- /dev/null
+++ b/app/assets/javascripts/search/group_filter/constants.js
@@ -0,0 +1,10 @@
+import { __ } from '~/locale';
+
+export const ANY_GROUP = Object.freeze({
+ id: null,
+ name: __('Any'),
+});
+
+export const GROUP_QUERY_PARAM = 'group_id';
+
+export const PROJECT_QUERY_PARAM = 'project_id';
diff --git a/app/assets/javascripts/search/group_filter/index.js b/app/assets/javascripts/search/group_filter/index.js
new file mode 100644
index 00000000000..9b009bc0305
--- /dev/null
+++ b/app/assets/javascripts/search/group_filter/index.js
@@ -0,0 +1,28 @@
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import GroupFilter from './components/group_filter.vue';
+
+Vue.use(Translate);
+
+export default store => {
+ let initialGroup;
+ const el = document.getElementById('js-search-group-dropdown');
+
+ const { initialGroupData } = el.dataset;
+
+ initialGroup = JSON.parse(initialGroupData);
+ initialGroup = convertObjectPropsToCamelCase(initialGroup, { deep: true });
+
+ return new Vue({
+ el,
+ store,
+ render(createElement) {
+ return createElement(GroupFilter, {
+ props: {
+ initialGroup,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/pages/search/show/highlight_blob_search_result.js b/app/assets/javascripts/search/highlight_blob_search_result.js
index e17c87735b4..e17c87735b4 100644
--- a/app/assets/javascripts/pages/search/show/highlight_blob_search_result.js
+++ b/app/assets/javascripts/search/highlight_blob_search_result.js
diff --git a/app/assets/javascripts/search/index.js b/app/assets/javascripts/search/index.js
index 780d3ff0d25..781a564d077 100644
--- a/app/assets/javascripts/search/index.js
+++ b/app/assets/javascripts/search/index.js
@@ -1,9 +1,14 @@
import { queryToObject } from '~/lib/utils/url_utility';
import createStore from './store';
-import initDropdownFilters from './dropdown_filter';
+import { initSidebar } from './sidebar';
+import initGroupFilter from './group_filter';
-export default () => {
- const store = createStore({ query: queryToObject(window.location.search) });
+export const initSearchApp = () => {
+ // Similar to url_utility.decodeUrlParameter
+ // Our query treats + as %20. This replaces the query + symbols with %20.
+ const sanitizedSearch = window.location.search.replace(/\+/g, '%20');
+ const store = createStore({ query: queryToObject(sanitizedSearch) });
- initDropdownFilters(store);
+ initSidebar(store);
+ initGroupFilter(store);
};
diff --git a/app/assets/javascripts/search/sidebar/components/app.vue b/app/assets/javascripts/search/sidebar/components/app.vue
new file mode 100644
index 00000000000..aa11b2025f2
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/components/app.vue
@@ -0,0 +1,41 @@
+<script>
+import { mapActions, mapState } from 'vuex';
+import { GlButton, GlLink } from '@gitlab/ui';
+import StatusFilter from './status_filter.vue';
+import ConfidentialityFilter from './confidentiality_filter.vue';
+
+export default {
+ name: 'GlobalSearchSidebar',
+ components: {
+ GlButton,
+ GlLink,
+ StatusFilter,
+ ConfidentialityFilter,
+ },
+ computed: {
+ ...mapState(['query']),
+ showReset() {
+ return this.query.state || this.query.confidential;
+ },
+ },
+ methods: {
+ ...mapActions(['applyQuery', 'resetQuery']),
+ },
+};
+</script>
+
+<template>
+ <form
+ class="gl-display-flex gl-flex-direction-column col-md-3 gl-mr-4 gl-mb-6 gl-mt-5"
+ @submit.prevent="applyQuery"
+ >
+ <status-filter />
+ <confidentiality-filter />
+ <div class="gl-display-flex gl-align-items-center gl-mt-3">
+ <gl-button variant="success" type="submit">{{ __('Apply') }}</gl-button>
+ <gl-link v-if="showReset" class="gl-ml-auto" @click="resetQuery">{{
+ __('Reset filters')
+ }}</gl-link>
+ </div>
+ </form>
+</template>
diff --git a/app/assets/javascripts/search/sidebar/components/confidentiality_filter.vue b/app/assets/javascripts/search/sidebar/components/confidentiality_filter.vue
new file mode 100644
index 00000000000..38dccb9675d
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/components/confidentiality_filter.vue
@@ -0,0 +1,26 @@
+<script>
+import { mapState } from 'vuex';
+import { confidentialFilterData } from '../constants/confidential_filter_data';
+import RadioFilter from './radio_filter.vue';
+
+export default {
+ name: 'ConfidentialityFilter',
+ components: {
+ RadioFilter,
+ },
+ computed: {
+ ...mapState(['query']),
+ showDropdown() {
+ return Object.values(confidentialFilterData.scopes).includes(this.query.scope);
+ },
+ },
+ confidentialFilterData,
+};
+</script>
+
+<template>
+ <div v-if="showDropdown">
+ <radio-filter :filter-data="$options.confidentialFilterData" />
+ <hr class="gl-my-5 gl-border-gray-100" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/search/sidebar/components/radio_filter.vue b/app/assets/javascripts/search/sidebar/components/radio_filter.vue
new file mode 100644
index 00000000000..b27c4e26fb5
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/components/radio_filter.vue
@@ -0,0 +1,68 @@
+<script>
+import { mapState, mapActions } from 'vuex';
+import { GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
+import { sprintf, s__ } from '~/locale';
+
+export default {
+ name: 'RadioFilter',
+ components: {
+ GlFormRadioGroup,
+ GlFormRadio,
+ },
+ props: {
+ filterData: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState(['query']),
+ ANY() {
+ return this.filterData.filters.ANY;
+ },
+ scope() {
+ return this.query.scope;
+ },
+ initialFilter() {
+ return this.query[this.filterData.filterParam];
+ },
+ filter() {
+ return this.initialFilter || this.ANY.value;
+ },
+ filtersArray() {
+ return this.filterData.filterByScope[this.scope];
+ },
+ selectedFilter: {
+ get() {
+ if (this.filtersArray.some(({ value }) => value === this.filter)) {
+ return this.filter;
+ }
+
+ return this.ANY.value;
+ },
+ set(value) {
+ this.setQuery({ key: this.filterData.filterParam, value });
+ },
+ },
+ },
+ methods: {
+ ...mapActions(['setQuery']),
+ radioLabel(filter) {
+ return filter.value === this.ANY.value
+ ? sprintf(s__('Any %{header}'), { header: this.filterData.header.toLowerCase() })
+ : filter.label;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <h5 class="gl-mt-0">{{ filterData.header }}</h5>
+ <gl-form-radio-group v-model="selectedFilter">
+ <gl-form-radio v-for="f in filtersArray" :key="f.value" :value="f.value">
+ {{ radioLabel(f) }}
+ </gl-form-radio>
+ </gl-form-radio-group>
+ </div>
+</template>
diff --git a/app/assets/javascripts/search/sidebar/components/status_filter.vue b/app/assets/javascripts/search/sidebar/components/status_filter.vue
new file mode 100644
index 00000000000..5cec2090906
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/components/status_filter.vue
@@ -0,0 +1,26 @@
+<script>
+import { mapState } from 'vuex';
+import { stateFilterData } from '../constants/state_filter_data';
+import RadioFilter from './radio_filter.vue';
+
+export default {
+ name: 'StatusFilter',
+ components: {
+ RadioFilter,
+ },
+ computed: {
+ ...mapState(['query']),
+ showDropdown() {
+ return Object.values(stateFilterData.scopes).includes(this.query.scope);
+ },
+ },
+ stateFilterData,
+};
+</script>
+
+<template>
+ <div v-if="showDropdown">
+ <radio-filter :filter-data="$options.stateFilterData" />
+ <hr class="gl-my-5 gl-border-gray-100" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/search/sidebar/constants/confidential_filter_data.js b/app/assets/javascripts/search/sidebar/constants/confidential_filter_data.js
new file mode 100644
index 00000000000..ecb63ed9eea
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/constants/confidential_filter_data.js
@@ -0,0 +1,36 @@
+import { __ } from '~/locale';
+
+const header = __('Confidentiality');
+
+const filters = {
+ ANY: {
+ label: __('Any'),
+ value: null,
+ },
+ CONFIDENTIAL: {
+ label: __('Confidential'),
+ value: 'yes',
+ },
+ NOT_CONFIDENTIAL: {
+ label: __('Not confidential'),
+ value: 'no',
+ },
+};
+
+const scopes = {
+ ISSUES: 'issues',
+};
+
+const filterByScope = {
+ [scopes.ISSUES]: [filters.ANY, filters.CONFIDENTIAL, filters.NOT_CONFIDENTIAL],
+};
+
+const filterParam = 'confidential';
+
+export const confidentialFilterData = {
+ header,
+ filters,
+ scopes,
+ filterByScope,
+ filterParam,
+};
diff --git a/app/assets/javascripts/search/sidebar/constants/state_filter_data.js b/app/assets/javascripts/search/sidebar/constants/state_filter_data.js
new file mode 100644
index 00000000000..7c9a029ffe4
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/constants/state_filter_data.js
@@ -0,0 +1,42 @@
+import { __ } from '~/locale';
+
+const header = __('Status');
+
+const filters = {
+ ANY: {
+ label: __('Any'),
+ value: 'all',
+ },
+ OPEN: {
+ label: __('Open'),
+ value: 'opened',
+ },
+ CLOSED: {
+ label: __('Closed'),
+ value: 'closed',
+ },
+ MERGED: {
+ label: __('Merged'),
+ value: 'merged',
+ },
+};
+
+const scopes = {
+ ISSUES: 'issues',
+ MERGE_REQUESTS: 'merge_requests',
+};
+
+const filterByScope = {
+ [scopes.ISSUES]: [filters.ANY, filters.OPEN, filters.CLOSED],
+ [scopes.MERGE_REQUESTS]: [filters.ANY, filters.OPEN, filters.MERGED, filters.CLOSED],
+};
+
+const filterParam = 'state';
+
+export const stateFilterData = {
+ header,
+ filters,
+ scopes,
+ filterByScope,
+ filterParam,
+};
diff --git a/app/assets/javascripts/search/sidebar/index.js b/app/assets/javascripts/search/sidebar/index.js
new file mode 100644
index 00000000000..6419e8ac2c6
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/index.js
@@ -0,0 +1,19 @@
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
+import GlobalSearchSidebar from './components/app.vue';
+
+Vue.use(Translate);
+
+export const initSidebar = store => {
+ const el = document.getElementById('js-search-sidebar');
+
+ if (!el) return false;
+
+ return new Vue({
+ el,
+ store,
+ render(createElement) {
+ return createElement(GlobalSearchSidebar);
+ },
+ });
+};
diff --git a/app/assets/javascripts/search/store/actions.js b/app/assets/javascripts/search/store/actions.js
new file mode 100644
index 00000000000..447278aa223
--- /dev/null
+++ b/app/assets/javascripts/search/store/actions.js
@@ -0,0 +1,29 @@
+import Api from '~/api';
+import createFlash from '~/flash';
+import { __ } from '~/locale';
+import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
+import * as types from './mutation_types';
+
+export const fetchGroups = ({ commit }, search) => {
+ commit(types.REQUEST_GROUPS);
+ Api.groups(search)
+ .then(data => {
+ commit(types.RECEIVE_GROUPS_SUCCESS, data);
+ })
+ .catch(() => {
+ createFlash({ message: __('There was a problem fetching groups.') });
+ commit(types.RECEIVE_GROUPS_ERROR);
+ });
+};
+
+export const setQuery = ({ commit }, { key, value }) => {
+ commit(types.SET_QUERY, { key, value });
+};
+
+export const applyQuery = ({ state }) => {
+ visitUrl(setUrlParams({ ...state.query, page: null }));
+};
+
+export const resetQuery = ({ state }) => {
+ visitUrl(setUrlParams({ ...state.query, page: null, state: null, confidential: null }));
+};
diff --git a/app/assets/javascripts/search/store/index.js b/app/assets/javascripts/search/store/index.js
index 10cfb647a92..e0a7e488f9f 100644
--- a/app/assets/javascripts/search/store/index.js
+++ b/app/assets/javascripts/search/store/index.js
@@ -1,10 +1,14 @@
import Vue from 'vue';
import Vuex from 'vuex';
+import * as actions from './actions';
+import mutations from './mutations';
import createState from './state';
Vue.use(Vuex);
export const getStoreConfig = ({ query }) => ({
+ actions,
+ mutations,
state: createState({ query }),
});
diff --git a/app/assets/javascripts/search/store/mutation_types.js b/app/assets/javascripts/search/store/mutation_types.js
new file mode 100644
index 00000000000..2482621d4d7
--- /dev/null
+++ b/app/assets/javascripts/search/store/mutation_types.js
@@ -0,0 +1,5 @@
+export const REQUEST_GROUPS = 'REQUEST_GROUPS';
+export const RECEIVE_GROUPS_SUCCESS = 'RECEIVE_GROUPS_SUCCESS';
+export const RECEIVE_GROUPS_ERROR = 'RECEIVE_GROUPS_ERROR';
+
+export const SET_QUERY = 'SET_QUERY';
diff --git a/app/assets/javascripts/search/store/mutations.js b/app/assets/javascripts/search/store/mutations.js
new file mode 100644
index 00000000000..e57850b870e
--- /dev/null
+++ b/app/assets/javascripts/search/store/mutations.js
@@ -0,0 +1,18 @@
+import * as types from './mutation_types';
+
+export default {
+ [types.REQUEST_GROUPS](state) {
+ state.fetchingGroups = true;
+ },
+ [types.RECEIVE_GROUPS_SUCCESS](state, data) {
+ state.fetchingGroups = false;
+ state.groups = data;
+ },
+ [types.RECEIVE_GROUPS_ERROR](state) {
+ state.fetchingGroups = false;
+ state.groups = [];
+ },
+ [types.SET_QUERY](state, { key, value }) {
+ state.query[key] = value;
+ },
+};
diff --git a/app/assets/javascripts/search/store/state.js b/app/assets/javascripts/search/store/state.js
index 9115a613767..70a8aab9998 100644
--- a/app/assets/javascripts/search/store/state.js
+++ b/app/assets/javascripts/search/store/state.js
@@ -1,4 +1,6 @@
const createState = ({ query }) => ({
query,
+ groups: [],
+ fetchingGroups: false,
});
export default createState;
diff --git a/app/assets/javascripts/serverless/components/area.vue b/app/assets/javascripts/serverless/components/area.vue
index 29a61cfbbfe..71f2e948917 100644
--- a/app/assets/javascripts/serverless/components/area.vue
+++ b/app/assets/javascripts/serverless/components/area.vue
@@ -138,8 +138,8 @@ export default {
:width="width"
:include-legend-avg-max="false"
>
- <template #tooltipTitle>{{ tooltipPopoverTitle }}</template>
- <template #tooltipContent>{{ tooltipPopoverContent }}</template>
+ <template #tooltip-title>{{ tooltipPopoverTitle }}</template>
+ <template #tooltip-content>{{ tooltipPopoverContent }}</template>
</gl-area-chart>
</div>
</template>
diff --git a/app/assets/javascripts/set_status_modal/components/user_availability_status.vue b/app/assets/javascripts/set_status_modal/components/user_availability_status.vue
new file mode 100644
index 00000000000..e86d94f86c6
--- /dev/null
+++ b/app/assets/javascripts/set_status_modal/components/user_availability_status.vue
@@ -0,0 +1,26 @@
+<script>
+import { AVAILABILITY_STATUS, isUserBusy, isValidAvailibility } from '../utils';
+
+export default {
+ name: 'UserAvailabilityStatus',
+ props: {
+ availability: {
+ type: String,
+ required: true,
+ validator: isValidAvailibility,
+ },
+ },
+ computed: {
+ isBusy() {
+ const { availability = AVAILABILITY_STATUS.NOT_SET } = this;
+ return isUserBusy(availability);
+ },
+ },
+};
+</script>
+
+<template>
+ <span v-if="isBusy" class="gl-font-weight-normal gl-text-gray-500">{{
+ s__('UserAvailability|(Busy)')
+ }}</span>
+</template>
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
index 09e893ff285..30e4e92d0cc 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
@@ -2,24 +2,35 @@
/* eslint-disable vue/no-v-html */
import $ from 'jquery';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
-import { GlModal, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { GlModal, GlTooltipDirective, GlIcon, GlFormCheckbox } from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __, s__ } from '~/locale';
import Api from '~/api';
import EmojiMenuInModal from './emoji_menu_in_modal';
+import { isUserBusy, isValidAvailibility } from './utils';
import * as Emoji from '~/emoji';
const emojiMenuClass = 'js-modal-status-emoji-menu';
+export const AVAILABILITY_STATUS = {
+ BUSY: 'busy',
+ NOT_SET: 'not_set',
+};
export default {
components: {
GlIcon,
GlModal,
+ GlFormCheckbox,
},
directives: {
GlTooltip: GlTooltipDirective,
},
props: {
+ defaultEmoji: {
+ type: String,
+ required: false,
+ default: '',
+ },
currentEmoji: {
type: String,
required: true,
@@ -28,6 +39,17 @@ export default {
type: String,
required: true,
},
+ currentAvailability: {
+ type: String,
+ required: false,
+ validator: isValidAvailibility,
+ default: '',
+ },
+ canSetUserAvailability: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -39,11 +61,15 @@ export default {
message: this.currentMessage,
modalId: 'set-user-status-modal',
noEmoji: true,
+ availability: isUserBusy(this.currentAvailability),
};
},
computed: {
+ isCustomEmoji() {
+ return this.emoji !== this.defaultEmoji;
+ },
isDirty() {
- return this.message.length || this.emoji.length;
+ return Boolean(this.message.length || this.isCustomEmoji);
},
},
mounted() {
@@ -67,7 +93,7 @@ export default {
this.emojiTag = Emoji.glEmojiTag(this.emoji);
}
this.noEmoji = this.emoji === '';
- this.defaultEmojiTag = Emoji.glEmojiTag('speech_balloon');
+ this.defaultEmojiTag = Emoji.glEmojiTag(this.defaultEmoji);
this.emojiMenu = new EmojiMenuInModal(
Emoji,
@@ -76,6 +102,7 @@ export default {
this.setEmoji,
this.$refs.userStatusForm,
);
+ this.setDefaultEmoji();
})
.catch(() => createFlash(__('Failed to load emoji list.')));
},
@@ -94,7 +121,7 @@ export default {
},
setDefaultEmoji() {
const { emojiTag } = this;
- const hasStatusMessage = this.message;
+ const hasStatusMessage = Boolean(this.message.length);
if (hasStatusMessage && emojiTag) {
return;
}
@@ -126,20 +153,26 @@ export default {
this.hideEmojiMenu();
},
removeStatus() {
+ this.availability = false;
this.clearStatusInputs();
this.setStatus();
},
setStatus() {
- const { emoji, message } = this;
+ const { emoji, message, availability } = this;
Api.postUserStatus({
emoji,
message,
+ availability: availability ? AVAILABILITY_STATUS.BUSY : AVAILABILITY_STATUS.NOT_SET,
})
.then(this.onUpdateSuccess)
.catch(this.onUpdateFail);
},
onUpdateSuccess() {
+ this.$toast.show(s__('SetStatusModal|Status updated'), {
+ type: 'success',
+ position: 'top-center',
+ });
this.closeModal();
window.location.reload();
},
@@ -175,11 +208,11 @@ export default {
name="user[status][emoji]"
/>
<div ref="userStatusForm" class="form-group position-relative m-0">
- <div class="input-group">
+ <div class="input-group gl-mb-5">
<span class="input-group-prepend">
<button
ref="toggleEmojiMenuButton"
- v-gl-tooltip.bottom
+ v-gl-tooltip.bottom.hover
:title="s__('SetStatusModal|Add status emoji')"
:aria-label="s__('SetStatusModal|Add status emoji')"
name="button"
@@ -223,6 +256,22 @@ export default {
</button>
</span>
</div>
+ <div v-if="canSetUserAvailability" class="form-group">
+ <div class="gl-display-flex">
+ <gl-form-checkbox
+ v-model="availability"
+ data-testid="user-availability-checkbox"
+ class="gl-mb-0"
+ >
+ <span class="gl-font-weight-bold">{{ s__('SetStatusModal|Busy') }}</span>
+ </gl-form-checkbox>
+ </div>
+ <div class="gl-display-flex">
+ <span class="gl-text-gray-600 gl-ml-5">
+ {{ s__('SetStatusModal|"Busy" will be shown next to your name') }}
+ </span>
+ </div>
+ </div>
</div>
</div>
</gl-modal>
diff --git a/app/assets/javascripts/set_status_modal/utils.js b/app/assets/javascripts/set_status_modal/utils.js
new file mode 100644
index 00000000000..dccb66be11f
--- /dev/null
+++ b/app/assets/javascripts/set_status_modal/utils.js
@@ -0,0 +1,9 @@
+export const AVAILABILITY_STATUS = {
+ BUSY: 'busy',
+ NOT_SET: 'not_set',
+};
+
+export const isUserBusy = status => status === AVAILABILITY_STATUS.BUSY;
+
+export const isValidAvailibility = availability =>
+ availability.length ? Object.values(AVAILABILITY_STATUS).includes(availability) : true;
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.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue
index 052bb3dcb53..00f1339d7f2 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue
@@ -22,7 +22,9 @@ export default {
return sprintf(__("%{userName}'s avatar"), { userName: this.user.name });
},
avatarUrl() {
- return this.user.avatar || this.user.avatar_url || gon.default_avatar_url;
+ return (
+ this.user.avatarUrl || this.user.avatar || this.user.avatar_url || gon.default_avatar_url
+ );
},
isMergeRequest() {
return this.issuableType === 'merge_request';
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 878b331fb3c..fbbe2e341a7 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue
@@ -16,10 +16,6 @@ export default {
type: Object,
required: true,
},
- rootPath: {
- type: String,
- required: true,
- },
tooltipPlacement: {
type: String,
default: 'bottom',
@@ -76,7 +72,7 @@ export default {
<!-- use d-flex so that slot can be appropriately styled -->
<span class="d-flex">
<assignee-avatar :user="user" :img-size="32" :issuable-type="issuableType" />
- <slot :user="user"></slot>
+ <slot></slot>
</span>
</gl-link>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
index 20dc7cb07e7..5f8ba844218 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
@@ -29,7 +29,8 @@ export default {
},
changing: {
type: Boolean,
- required: true,
+ required: false,
+ default: false,
},
},
computed: {
diff --git a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
index 4697d85472b..cf6a0a4a151 100644
--- a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
@@ -26,7 +26,6 @@ export default {
<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') }}
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 95934c0ef2a..31d5d7c0077 100644
--- a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
@@ -13,10 +13,6 @@ export default {
type: Array,
required: true,
},
- rootPath: {
- type: String,
- required: true,
- },
issuableType: {
type: String,
required: false,
@@ -66,22 +62,20 @@ export default {
<template>
<assignee-avatar-link
v-if="hasOneUser"
- #default="{ user }"
tooltip-placement="left"
:tooltip-has-name="false"
:user="firstUser"
- :root-path="rootPath"
:issuable-type="issuableType"
>
<div class="ml-2 gl-line-height-normal">
- <div>{{ user.name }}</div>
+ <div>{{ firstUser.name }}</div>
<div>{{ username }}</div>
</div>
</assignee-avatar-link>
<div v-else>
<div class="user-list">
<div v-for="user in uncollapsedUsers" :key="user.id" class="user-item">
- <assignee-avatar-link :user="user" :root-path="rootPath" :issuable-type="issuableType" />
+ <assignee-avatar-link :user="user" :issuable-type="issuableType" />
</div>
</div>
<div v-if="renderShowMoreSection" class="user-list-more">
diff --git a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
index 1af1bc18e3e..1785174e8d7 100644
--- a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
+++ b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
@@ -1,11 +1,26 @@
<script>
import $ from 'jquery';
-import { difference, union } from 'lodash';
-import flash from '~/flash';
-import axios from '~/lib/utils/axios_utils';
+import { camelCase, difference, union } from 'lodash';
+import updateIssueLabelsMutation from '~/boards/queries/issue_set_labels.mutation.graphql';
+import createFlash from '~/flash';
+import { IssuableType } from '~/issue_show/constants';
import { __ } from '~/locale';
+import updateMergeRequestLabelsMutation from '~/sidebar/queries/update_merge_request_labels.mutation.graphql';
+import { toLabelGid } from '~/sidebar/utils';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
+import { getIdFromGraphQLId, MutationOperationMode } from '~/graphql_shared/utils';
+
+const mutationMap = {
+ [IssuableType.Issue]: {
+ mutation: updateIssueLabelsMutation,
+ mutationName: 'updateIssue',
+ },
+ [IssuableType.MergeRequest]: {
+ mutation: updateMergeRequestLabelsMutation,
+ mutationName: 'mergeRequestSetLabels',
+ },
+};
export default {
components: {
@@ -21,7 +36,6 @@ export default {
'issuableType',
'labelsFetchPath',
'labelsManagePath',
- 'labelsUpdatePath',
'projectIssuesPath',
'projectPath',
],
@@ -35,37 +49,79 @@ export default {
handleDropdownClose() {
$(this.$el).trigger('hidden.gl.dropdown');
},
- handleUpdateSelectedLabels(dropdownLabels) {
+ getUpdateVariables(dropdownLabels) {
const currentLabelIds = this.selectedLabels.map(label => label.id);
const userAddedLabelIds = dropdownLabels.filter(label => label.set).map(label => label.id);
const userRemovedLabelIds = dropdownLabels.filter(label => !label.set).map(label => label.id);
const labelIds = difference(union(currentLabelIds, userAddedLabelIds), userRemovedLabelIds);
- this.updateSelectedLabels(labelIds);
+ switch (this.issuableType) {
+ case IssuableType.Issue:
+ return {
+ addLabelIds: userAddedLabelIds,
+ iid: this.iid,
+ projectPath: this.projectPath,
+ removeLabelIds: userRemovedLabelIds,
+ };
+ case IssuableType.MergeRequest:
+ return {
+ iid: this.iid,
+ labelIds: labelIds.map(toLabelGid),
+ operationMode: MutationOperationMode.Replace,
+ projectPath: this.projectPath,
+ };
+ default:
+ return {};
+ }
+ },
+ handleUpdateSelectedLabels(dropdownLabels) {
+ this.updateSelectedLabels(this.getUpdateVariables(dropdownLabels));
+ },
+ getRemoveVariables(labelId) {
+ switch (this.issuableType) {
+ case IssuableType.Issue:
+ return {
+ iid: this.iid,
+ projectPath: this.projectPath,
+ removeLabelIds: [labelId],
+ };
+ case IssuableType.MergeRequest:
+ return {
+ iid: this.iid,
+ labelIds: [toLabelGid(labelId)],
+ operationMode: MutationOperationMode.Remove,
+ projectPath: this.projectPath,
+ };
+ default:
+ return {};
+ }
},
handleLabelRemove(labelId) {
- const currentLabelIds = this.selectedLabels.map(label => label.id);
- const labelIds = difference(currentLabelIds, [labelId]);
-
- this.updateSelectedLabels(labelIds);
+ this.updateSelectedLabels(this.getRemoveVariables(labelId));
},
- updateSelectedLabels(labelIds) {
+ updateSelectedLabels(inputVariables) {
this.isLabelsSelectInProgress = true;
- axios({
- data: {
- [this.issuableType]: {
- label_ids: labelIds,
- },
- },
- method: 'put',
- url: this.labelsUpdatePath,
- })
+ this.$apollo
+ .mutate({
+ mutation: mutationMap[this.issuableType].mutation,
+ variables: { input: inputVariables },
+ })
.then(({ data }) => {
- this.selectedLabels = data.labels;
+ const { mutationName } = mutationMap[this.issuableType];
+
+ if (data[mutationName]?.errors?.length) {
+ throw new Error();
+ }
+
+ const issuableType = camelCase(this.issuableType);
+ this.selectedLabels = data[mutationName]?.[issuableType]?.labels?.nodes?.map(label => ({
+ ...label,
+ id: getIdFromGraphQLId(label.id),
+ }));
})
- .catch(() => flash(__('An error occurred while updating labels.')))
+ .catch(() => createFlash({ message: __('An error occurred while updating labels.') }))
.finally(() => {
this.isLabelsSelectInProgress = false;
});
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
index 0457aad8795..6e004084077 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
@@ -1,9 +1,8 @@
<script>
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
import Tracking from '~/tracking';
import toggleButton from '~/vue_shared/components/toggle_button.vue';
-import tooltip from '~/vue_shared/directives/tooltip';
import eventHub from '../../event_hub';
const ICON_ON = 'notifications';
@@ -13,7 +12,7 @@ const LABEL_OFF = __('Notifications off');
export default {
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
components: {
GlIcon,
@@ -110,12 +109,9 @@ export default {
<div>
<span
ref="tooltip"
- v-tooltip
- class="sidebar-collapsed-icon"
+ v-gl-tooltip.viewport.left
:title="notificationTooltip"
- data-container="body"
- data-placement="left"
- data-boundary="viewport"
+ class="sidebar-collapsed-icon"
@click="onClickCollapsedIcon"
>
<gl-icon
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 9d72bf4394e..7b67c34ded6 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue
@@ -96,7 +96,12 @@ export default {
</script>
<template>
- <div v-gl-tooltip:body.viewport.left :title="tooltipText" class="sidebar-collapsed-icon">
+ <div
+ v-gl-tooltip:body.viewport.left
+ :title="tooltipText"
+ data-testid="collapsedState"
+ class="sidebar-collapsed-icon"
+ >
<gl-icon name="timer" />
<div class="time-tracking-collapsed-summary">
<div :class="divClass">
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
index d4cc98e3743..99302993b9a 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
@@ -70,14 +70,19 @@ export default {
</script>
<template>
- <div class="time-tracking-comparison-pane">
+ <div data-testid="timeTrackingComparisonPane">
<div
v-gl-tooltip
+ data-testid="compareMeter"
:title="timeRemainingTooltip"
:class="timeRemainingStatusClass"
class="compare-meter"
>
- <gl-progress-bar :value="timeRemainingPercent" :variant="progressBarVariant" />
+ <gl-progress-bar
+ data-testid="timeRemainingProgress"
+ :value="timeRemainingPercent"
+ :variant="progressBarVariant"
+ />
<div class="compare-display-container">
<div class="compare-display float-left">
<span class="compare-label">{{ s__('TimeTracking|Spent') }}</span>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue
index 305726d9725..8a80b1bf13f 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue
@@ -11,7 +11,8 @@ export default {
</script>
<template>
- <div class="time-tracking-estimate-only-pane">
- <span class="bold"> {{ s__('TimeTracking|Estimated:') }} </span> {{ timeEstimateHumanReadable }}
+ <div data-testid="estimateOnlyPane">
+ <span class="gl-font-weight-bold">{{ s__('TimeTracking|Estimated:') }} </span
+ >{{ timeEstimateHumanReadable }}
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
index b45746e789d..8bc828091c0 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
@@ -34,7 +34,7 @@ export default {
</script>
<template>
- <div class="time-tracking-help-state">
+ <div data-testid="helpPane" class="time-tracking-help-state">
<div class="time-tracking-info">
<h4>{{ __('Track time with quick actions') }}</h4>
<p>{{ __('Quick actions can be used in the issues description and comment boxes.') }}</p>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue
index 45552589e50..2d3d0ce8dc5 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue
@@ -5,7 +5,7 @@ export default {
</script>
<template>
- <div class="time-tracking-no-tracking-pane">
- <span class="no-value"> {{ __('No estimate or time spent') }} </span>
+ <div data-testid="noTrackingPane">
+ <span class="no-value">{{ __('No estimate or time spent') }}</span>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
index 406677941b7..6bef5ed67a4 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
@@ -57,7 +57,6 @@ export default {
:human-time-estimate="store.humanTimeEstimate"
:human-time-spent="store.humanTotalTimeSpent"
:limit-to-hours="store.timeTrackingLimitToHours"
- :root-path="store.rootPath"
/>
</div>
</template>
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 b2b3b289c5c..33c6ac6e2ba 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
@@ -15,7 +15,7 @@ export default {
return sprintf(
s__('TimeTracking|%{startTag}Spent: %{endTag}%{timeSpentHumanReadable}'),
{
- startTag: '<span class="bold">',
+ startTag: '<span class="gl-font-weight-bold">',
endTag: '</span>',
timeSpentHumanReadable: this.timeSpentHumanReadable,
},
@@ -27,5 +27,5 @@ export default {
</script>
<template>
- <div class="time-tracking-spend-only-pane" v-html="timeSpent"></div>
+ <div data-testid="spentOnlyPane" v-html="timeSpent"></div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
index a2fb0ebcbc6..3199ed1e615 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -44,6 +44,21 @@ export default {
default: false,
required: false,
},
+ /*
+ In issue list, "time-tracking-collapsed-state" is always rendered even if the sidebar isn't collapsed.
+ The actual hiding is controlled with css classes:
+ Hide "time-tracking-collapsed-state"
+ if .right-sidebar .right-sidebar-collapsed .sidebar-collapsed-icon
+ Show "time-tracking-collapsed-state"
+ if .right-sidebar .right-sidebar-expanded .sidebar-collapsed-icon
+
+ In Swimlanes sidebar, we do not use collapsed state at all.
+ */
+ showCollapsed: {
+ type: Boolean,
+ default: true,
+ required: false,
+ },
},
data() {
return {
@@ -93,8 +108,9 @@ export default {
</script>
<template>
- <div v-cloak class="time_tracker time-tracking-component-wrap">
+ <div v-cloak class="time-tracker time-tracking-component-wrap" data-testid="time-tracker">
<time-tracking-collapsed-state
+ v-if="showCollapsed"
:show-comparison-state="showComparisonState"
:show-no-time-tracking-state="showNoTimeTrackingState"
:show-help-state="showHelpState"
@@ -103,13 +119,19 @@ export default {
:time-spent-human-readable="humanTimeSpent"
:time-estimate-human-readable="humanTimeEstimate"
/>
- <div class="title hide-collapsed">
+ <div class="title hide-collapsed gl-mb-3">
{{ __('Time tracking') }}
- <div v-if="!showHelpState" class="help-button float-right" @click="toggleHelpState(true)">
+ <div
+ v-if="!showHelpState"
+ data-testid="helpButton"
+ class="help-button float-right"
+ @click="toggleHelpState(true)"
+ >
<gl-icon name="question-o" />
</div>
<div
- v-if="showHelpState"
+ v-else
+ data-testid="closeHelpButton"
class="close-help-button float-right"
@click="toggleHelpState(false)"
>
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 00b4e2de5e5..984cd8a3b1d 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -91,8 +91,13 @@ export function mountSidebarLabels() {
return false;
}
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
return new Vue({
el,
+ apolloProvider,
provide: {
...el.dataset,
allowLabelCreate: parseBoolean(el.dataset.allowLabelCreate),
diff --git a/app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql b/app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql
new file mode 100644
index 00000000000..3c09daad793
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql
@@ -0,0 +1,15 @@
+mutation mergeRequestSetLabels($input: MergeRequestSetLabelsInput!) {
+ mergeRequestSetLabels(input: $input) {
+ errors
+ mergeRequest {
+ labels {
+ nodes {
+ color
+ description
+ id
+ title
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/sidebar/utils.js b/app/assets/javascripts/sidebar/utils.js
new file mode 100644
index 00000000000..23730508b56
--- /dev/null
+++ b/app/assets/javascripts/sidebar/utils.js
@@ -0,0 +1 @@
+export const toLabelGid = id => `gid://gitlab/Label/${id}`;
diff --git a/app/assets/javascripts/single_file_diff.js b/app/assets/javascripts/single_file_diff.js
index 5fa6cef7195..3492f19c996 100644
--- a/app/assets/javascripts/single_file_diff.js
+++ b/app/assets/javascripts/single_file_diff.js
@@ -7,11 +7,14 @@ import { deprecatedCreateFlash as createFlash } from './flash';
import FilesCommentButton from './files_comment_button';
import initImageDiffHelper from './image_diff/helpers/init_image_diff';
import syntaxHighlight from './syntax_highlight';
+import { spriteIcon } from '~/lib/utils/common_utils';
const WRAPPER = '<div class="diff-content"></div>';
const LOADING_HTML = '<span class="spinner"></span>';
-const ERROR_HTML =
- '<div class="nothing-here-block"><i class="fa fa-warning"></i> Could not load diff</div>';
+const ERROR_HTML = `<div class="nothing-here-block">${spriteIcon(
+ 'warning-solid',
+ 's16',
+)} Could not load diff</div>`;
const COLLAPSED_HTML =
'<div class="nothing-here-block diff-collapsed">This diff is collapsed. <button class="click-to-expand btn btn-link">Click to expand it.</button></div>';
diff --git a/app/assets/javascripts/snippets/components/edit.vue b/app/assets/javascripts/snippets/components/edit.vue
index dd77d49803f..08683f25651 100644
--- a/app/assets/javascripts/snippets/components/edit.vue
+++ b/app/assets/javascripts/snippets/components/edit.vue
@@ -9,19 +9,14 @@ import FormFooterActions from '~/vue_shared/components/form/form_footer_actions.
import {
SNIPPET_MARK_EDIT_APP_START,
SNIPPET_MEASURE_BLOBS_CONTENT,
-} from '~/performance_constants';
+} from '~/performance/constants';
import eventHub from '~/blob/components/eventhub';
-import { performanceMarkAndMeasure } from '~/performance_utils';
+import { performanceMarkAndMeasure } from '~/performance/utils';
import UpdateSnippetMutation from '../mutations/updateSnippet.mutation.graphql';
import CreateSnippetMutation from '../mutations/createSnippet.mutation.graphql';
import { getSnippetMixin } from '../mixins/snippets';
-import {
- SNIPPET_CREATE_MUTATION_ERROR,
- SNIPPET_UPDATE_MUTATION_ERROR,
- SNIPPET_VISIBILITY_PRIVATE,
-} from '../constants';
-import defaultVisibilityQuery from '../queries/snippet_visibility.query.graphql';
+import { SNIPPET_CREATE_MUTATION_ERROR, SNIPPET_UPDATE_MUTATION_ERROR } from '../constants';
import { markBlobPerformance } from '../utils/blob';
import SnippetBlobActionsEdit from './snippet_blob_actions_edit.vue';
@@ -41,15 +36,7 @@ export default {
GlLoadingIcon,
},
mixins: [getSnippetMixin],
- apollo: {
- defaultVisibility: {
- query: defaultVisibilityQuery,
- manual: true,
- result({ data: { selectedLevel } }) {
- this.selectedLevelDefault = selectedLevel;
- },
- },
- },
+ inject: ['selectedLevel'],
props: {
markdownPreviewPath: {
type: String,
@@ -73,9 +60,12 @@ export default {
data() {
return {
isUpdating: false,
- newSnippet: false,
actions: [],
- selectedLevelDefault: SNIPPET_VISIBILITY_PRIVATE,
+ snippet: {
+ title: '',
+ description: '',
+ visibilityLevel: this.selectedLevel,
+ },
};
},
computed: {
@@ -112,13 +102,6 @@ export default {
}
return this.snippet.webUrl;
},
- newSnippetSchema() {
- return {
- title: '',
- description: '',
- visibilityLevel: this.selectedLevelDefault,
- };
- },
},
beforeCreate() {
performanceMarkAndMeasure({ mark: SNIPPET_MARK_EDIT_APP_START });
@@ -145,20 +128,6 @@ export default {
Flash(sprintf(defaultErrorMsg, { err }));
this.isUpdating = false;
},
- onNewSnippetFetched() {
- this.newSnippet = true;
- this.snippet = this.newSnippetSchema;
- },
- onExistingSnippetFetched() {
- this.newSnippet = false;
- },
- onSnippetFetch(snippetRes) {
- if (snippetRes.data.snippets.nodes.length === 0) {
- this.onNewSnippetFetched();
- } else {
- this.onExistingSnippetFetched();
- }
- },
getAttachedFiles() {
const fileInputs = Array.from(this.$el.querySelectorAll('[name="files[]"]'));
return fileInputs.map(node => node.value);
@@ -209,7 +178,7 @@ export default {
</script>
<template>
<form
- class="snippet-form js-requires-input js-quick-submit common-note-form"
+ class="snippet-form js-quick-submit common-note-form"
:data-snippet-type="isProjectSnippet ? 'project' : 'personal'"
data-testid="snippet-edit-form"
@submit.prevent="handleFormSubmit"
diff --git a/app/assets/javascripts/snippets/components/show.vue b/app/assets/javascripts/snippets/components/show.vue
index 4a2f060ff7c..a3e5535c5fa 100644
--- a/app/assets/javascripts/snippets/components/show.vue
+++ b/app/assets/javascripts/snippets/components/show.vue
@@ -9,8 +9,8 @@ import { SNIPPET_VISIBILITY_PUBLIC } from '~/snippets/constants';
import {
SNIPPET_MARK_VIEW_APP_START,
SNIPPET_MEASURE_BLOBS_CONTENT,
-} from '~/performance_constants';
-import { performanceMarkAndMeasure } from '~/performance_utils';
+} from '~/performance/constants';
+import { performanceMarkAndMeasure } from '~/performance/utils';
import eventHub from '~/blob/components/eventhub';
import { getSnippetMixin } from '../mixins/snippets';
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_view.vue b/app/assets/javascripts/snippets/components/snippet_blob_view.vue
index e88126ea56a..b965c15306d 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_view.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_view.vue
@@ -1,9 +1,9 @@
<script>
+import GetBlobContent from 'shared_queries/snippet/snippet_blob_content.query.graphql';
+
import BlobHeader from '~/blob/components/blob_header.vue';
import BlobContent from '~/blob/components/blob_content.vue';
-import GetBlobContent from '../queries/snippet.blob.content.query.graphql';
-
import {
SIMPLE_BLOB_VIEWER,
RICH_BLOB_VIEWER,
@@ -21,7 +21,7 @@ export default {
query: GetBlobContent,
variables() {
return {
- ids: this.snippet.id,
+ ids: [this.snippet.id],
rich: this.activeViewerType === RICH_BLOB_VIEWER,
paths: [this.blob.path],
};
@@ -51,6 +51,13 @@ export default {
required: true,
},
},
+ provide() {
+ return {
+ blobHash: Math.random()
+ .toString()
+ .split('.')[1],
+ };
+ },
data() {
return {
blobContent: '',
diff --git a/app/assets/javascripts/snippets/components/snippet_header.vue b/app/assets/javascripts/snippets/components/snippet_header.vue
index 30de5a9d0e0..32c4c1039f5 100644
--- a/app/assets/javascripts/snippets/components/snippet_header.vue
+++ b/app/assets/javascripts/snippets/components/snippet_header.vue
@@ -6,17 +6,17 @@ import {
GlModal,
GlAlert,
GlLoadingIcon,
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
GlButton,
GlTooltipDirective,
} from '@gitlab/ui';
+import CanCreatePersonalSnippet from 'shared_queries/snippet/user_permissions.query.graphql';
+import CanCreateProjectSnippet from 'shared_queries/snippet/project_permissions.query.graphql';
import { __ } from '~/locale';
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';
import { fetchPolicies } from '~/lib/graphql';
@@ -28,8 +28,8 @@ export default {
GlModal,
GlAlert,
GlLoadingIcon,
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
TimeAgoTooltip,
GlButton,
},
@@ -120,7 +120,7 @@ export default {
? __('The snippet is visible only to project members.')
: __('The snippet is visible only to me.');
case 'internal':
- return __('The snippet is visible to any logged in user.');
+ return __('The snippet is visible to any logged in user except external users.');
default:
return __('The snippet can be accessed without any authentication.');
}
@@ -231,17 +231,17 @@ export default {
</template>
</div>
<div class="d-block d-sm-none dropdown">
- <gl-deprecated-dropdown :text="__('Options')" class="w-100" toggle-class="text-center">
- <gl-deprecated-dropdown-item
+ <gl-dropdown :text="__('Options')" block>
+ <gl-dropdown-item
v-for="(action, index) in personalSnippetActions"
:key="index"
:disabled="action.disabled"
:title="action.title"
:href="action.href"
@click="action.click ? action.click() : undefined"
- >{{ action.text }}</gl-deprecated-dropdown-item
+ >{{ action.text }}</gl-dropdown-item
>
- </gl-deprecated-dropdown>
+ </gl-dropdown>
</div>
</div>
diff --git a/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue b/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
index 25ad7c214b2..ee5076835ab 100644
--- a/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
@@ -1,6 +1,5 @@
<script>
import { GlIcon, GlFormGroup, GlFormRadio, GlFormRadioGroup, GlLink } from '@gitlab/ui';
-import defaultVisibilityQuery from '../queries/snippet_visibility.query.graphql';
import { defaultSnippetVisibilityLevels } from '../utils/blob';
import { SNIPPET_LEVELS_RESTRICTED, SNIPPET_LEVELS_DISABLED } from '~/snippets/constants';
@@ -12,16 +11,7 @@ export default {
GlFormRadioGroup,
GlLink,
},
- apollo: {
- defaultVisibility: {
- query: defaultVisibilityQuery,
- manual: true,
- result({ data: { visibilityLevels, multipleLevelsRestricted } }) {
- this.visibilityLevels = defaultSnippetVisibilityLevels(visibilityLevels);
- this.multipleLevelsRestricted = multipleLevelsRestricted;
- },
- },
- },
+ inject: ['visibilityLevels', 'multipleLevelsRestricted'],
props: {
helpLink: {
type: String,
@@ -38,11 +28,10 @@ export default {
required: true,
},
},
- data() {
- return {
- visibilityLevels: [],
- multipleLevelsRestricted: false,
- };
+ computed: {
+ defaultVisibilityLevels() {
+ return defaultSnippetVisibilityLevels(this.visibilityLevels);
+ },
},
SNIPPET_LEVELS_DISABLED,
SNIPPET_LEVELS_RESTRICTED,
@@ -59,7 +48,7 @@ export default {
<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 visibilityLevels"
+ v-for="option in defaultVisibilityLevels"
:key="option.value"
:value="option.value"
class="mb-3"
@@ -78,7 +67,9 @@ export default {
</gl-form-group>
<div class="text-muted" data-testid="restricted-levels-info">
- <template v-if="!visibilityLevels.length">{{ $options.SNIPPET_LEVELS_DISABLED }}</template>
+ <template v-if="!defaultVisibilityLevels.length">{{
+ $options.SNIPPET_LEVELS_DISABLED
+ }}</template>
<template v-else-if="multipleLevelsRestricted">{{
$options.SNIPPET_LEVELS_RESTRICTED
}}</template>
diff --git a/app/assets/javascripts/snippets/constants.js b/app/assets/javascripts/snippets/constants.js
index e75922df15f..2a9ecbc27dc 100644
--- a/app/assets/javascripts/snippets/constants.js
+++ b/app/assets/javascripts/snippets/constants.js
@@ -14,7 +14,7 @@ export const SNIPPET_VISIBILITY = {
[SNIPPET_VISIBILITY_INTERNAL]: {
label: __('Internal'),
icon: 'shield',
- description: __('The snippet is visible to any logged in user.'),
+ description: __('The snippet is visible to any logged in user except external users.'),
},
[SNIPPET_VISIBILITY_PUBLIC]: {
label: __('Public'),
diff --git a/app/assets/javascripts/snippets/index.js b/app/assets/javascripts/snippets/index.js
index b55e1baf41e..853ccb0c2fe 100644
--- a/app/assets/javascripts/snippets/index.js
+++ b/app/assets/javascripts/snippets/index.js
@@ -24,17 +24,14 @@ export default function appFactory(el, Component) {
...restDataset
} = el.dataset;
- apolloProvider.clients.defaultClient.cache.writeData({
- data: {
+ return new Vue({
+ el,
+ apolloProvider,
+ provide: {
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: {
diff --git a/app/assets/javascripts/snippets/mixins/snippets.js b/app/assets/javascripts/snippets/mixins/snippets.js
index d5e69e2a889..5844a55e4f5 100644
--- a/app/assets/javascripts/snippets/mixins/snippets.js
+++ b/app/assets/javascripts/snippets/mixins/snippets.js
@@ -1,4 +1,4 @@
-import GetSnippetQuery from '../queries/snippet.query.graphql';
+import GetSnippetQuery from 'shared_queries/snippet/snippet.query.graphql';
const blobsDefault = [];
@@ -8,7 +8,7 @@ export const getSnippetMixin = {
query: GetSnippetQuery,
variables() {
return {
- ids: this.snippetGid,
+ ids: [this.snippetGid],
};
},
update: data => {
@@ -21,9 +21,9 @@ export const getSnippetMixin = {
},
result(res) {
this.blobs = res.data.snippets.nodes[0]?.blobs || blobsDefault;
- if (this.onSnippetFetch) {
- this.onSnippetFetch(res);
- }
+ },
+ skip() {
+ return this.newSnippet;
},
},
},
@@ -36,7 +36,7 @@ export const getSnippetMixin = {
data() {
return {
snippet: {},
- newSnippet: false,
+ newSnippet: !this.snippetGid,
blobs: blobsDefault,
};
},
diff --git a/app/assets/javascripts/snippets/queries/projectPermissions.query.graphql b/app/assets/javascripts/snippets/queries/projectPermissions.query.graphql
deleted file mode 100644
index 03c81460fb5..00000000000
--- a/app/assets/javascripts/snippets/queries/projectPermissions.query.graphql
+++ /dev/null
@@ -1,7 +0,0 @@
-query CanCreateProjectSnippet($fullPath: ID!) {
- project(fullPath: $fullPath) {
- userPermissions {
- createSnippet
- }
- }
-}
diff --git a/app/assets/javascripts/snippets/queries/snippet.blob.content.query.graphql b/app/assets/javascripts/snippets/queries/snippet.blob.content.query.graphql
deleted file mode 100644
index 0e04ee9b7b8..00000000000
--- a/app/assets/javascripts/snippets/queries/snippet.blob.content.query.graphql
+++ /dev/null
@@ -1,14 +0,0 @@
-query SnippetBlobContent($ids: [ID!], $rich: Boolean!, $paths: [String!]) {
- snippets(ids: $ids) {
- nodes {
- id
- blobs(paths: $paths) {
- nodes {
- path
- richData @include(if: $rich)
- plainData @skip(if: $rich)
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/snippets/queries/snippet.query.graphql b/app/assets/javascripts/snippets/queries/snippet.query.graphql
deleted file mode 100644
index 2f385050d89..00000000000
--- a/app/assets/javascripts/snippets/queries/snippet.query.graphql
+++ /dev/null
@@ -1,15 +0,0 @@
-#import '../fragments/snippetBase.fragment.graphql'
-#import '../fragments/project.fragment.graphql'
-#import "~/graphql_shared/fragments/author.fragment.graphql"
-
-query GetSnippetQuery($ids: [ID!]) {
- snippets(ids: $ids) {
- nodes {
- ...SnippetBase
- ...SnippetProject
- author {
- ...Author
- }
- }
- }
-}
diff --git a/app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql b/app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql
deleted file mode 100644
index 5bd6c131bab..00000000000
--- a/app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql
+++ /dev/null
@@ -1,5 +0,0 @@
-query defaultSnippetVisibility {
- visibilityLevels @client
- selectedLevel @client
- multipleLevelsRestricted @client
-}
diff --git a/app/assets/javascripts/snippets/queries/userPermissions.query.graphql b/app/assets/javascripts/snippets/queries/userPermissions.query.graphql
deleted file mode 100644
index c3e5519e266..00000000000
--- a/app/assets/javascripts/snippets/queries/userPermissions.query.graphql
+++ /dev/null
@@ -1,7 +0,0 @@
-query CanCreatePersonalSnippet {
- currentUser {
- userPermissions {
- createSnippet
- }
- }
-}
diff --git a/app/assets/javascripts/snippets/utils/blob.js b/app/assets/javascripts/snippets/utils/blob.js
index c47559b82b8..5081c648e36 100644
--- a/app/assets/javascripts/snippets/utils/blob.js
+++ b/app/assets/javascripts/snippets/utils/blob.js
@@ -7,8 +7,8 @@ import {
SNIPPET_LEVELS_MAP,
SNIPPET_VISIBILITY,
} from '../constants';
-import { performanceMarkAndMeasure } from '~/performance_utils';
-import { SNIPPET_MARK_BLOBS_CONTENT, SNIPPET_MEASURE_BLOBS_CONTENT } from '~/performance_constants';
+import { performanceMarkAndMeasure } from '~/performance/utils';
+import { SNIPPET_MARK_BLOBS_CONTENT, SNIPPET_MEASURE_BLOBS_CONTENT } from '~/performance/constants';
const createLocalId = () => uniqueId('blob_local_');
diff --git a/app/assets/javascripts/static_site_editor/components/edit_area.vue b/app/assets/javascripts/static_site_editor/components/edit_area.vue
index e602f26acdf..69eabfe5339 100644
--- a/app/assets/javascripts/static_site_editor/components/edit_area.vue
+++ b/app/assets/javascripts/static_site_editor/components/edit_area.vue
@@ -6,10 +6,10 @@ import EditDrawer from './edit_drawer.vue';
import UnsavedChangesConfirmDialog from './unsaved_changes_confirm_dialog.vue';
import parseSourceFile from '~/static_site_editor/services/parse_source_file';
import { EDITOR_TYPES } from '~/vue_shared/components/rich_content_editor/constants';
-import { DEFAULT_IMAGE_UPLOAD_PATH } from '../constants';
import imageRepository from '../image_repository';
import formatter from '../services/formatter';
import templater from '../services/templater';
+import renderImage from '../services/renderers/render_image';
export default {
components: {
@@ -37,21 +37,35 @@ export default {
required: false,
default: '',
},
+ branch: {
+ type: String,
+ required: true,
+ },
+ baseUrl: {
+ type: String,
+ required: true,
+ },
+ mounts: {
+ type: Array,
+ required: true,
+ },
+ project: {
+ type: String,
+ required: true,
+ },
imageRoot: {
type: String,
- required: false,
- default: DEFAULT_IMAGE_UPLOAD_PATH,
- validator: prop => prop.endsWith('/'),
+ required: true,
},
},
data() {
return {
- saveable: false,
parsedSource: parseSourceFile(this.preProcess(true, this.content)),
editorMode: EDITOR_TYPES.wysiwyg,
- isModified: false,
hasMatter: false,
isDrawerOpen: false,
+ isModified: false,
+ isSaveable: false,
};
},
imageRepository: imageRepository(),
@@ -68,6 +82,18 @@ export default {
isWysiwygMode() {
return this.editorMode === EDITOR_TYPES.wysiwyg;
},
+ customRenderers() {
+ const imageRenderer = renderImage.build(
+ this.mounts,
+ this.project,
+ this.branch,
+ this.baseUrl,
+ this.$options.imageRepository,
+ );
+ return {
+ image: [imageRenderer],
+ };
+ },
},
created() {
this.refreshEditHelpers();
@@ -81,8 +107,11 @@ export default {
return templatedContent;
},
refreshEditHelpers() {
- this.isModified = this.parsedSource.isModified();
- this.hasMatter = this.parsedSource.hasMatter();
+ const { isModified, hasMatter, isMatterValid } = this.parsedSource;
+ this.isModified = isModified();
+ this.hasMatter = hasMatter();
+ const hasValidMatter = this.hasMatter ? isMatterValid() : true;
+ this.isSaveable = this.isModified && hasValidMatter;
},
onDrawerOpen() {
this.isDrawerOpen = true;
@@ -133,17 +162,18 @@ export default {
:content="editableContent"
:initial-edit-type="editorMode"
:image-root="imageRoot"
+ :options="{ customRenderers }"
class="mb-9 pb-6 h-100"
@modeChange="onModeChange"
@input="onInputChange"
@uploadImage="onUploadImage"
/>
- <unsaved-changes-confirm-dialog :modified="isModified" />
+ <unsaved-changes-confirm-dialog :modified="isSaveable" />
<publish-toolbar
class="gl-fixed gl-left-0 gl-bottom-0 gl-w-full"
:has-settings="hasSettings"
:return-url="returnUrl"
- :saveable="isModified"
+ :saveable="isSaveable"
:saving-changes="savingChanges"
@editSettings="onDrawerOpen"
@submit="onSubmit"
diff --git a/app/assets/javascripts/static_site_editor/components/edit_meta_controls.vue b/app/assets/javascripts/static_site_editor/components/edit_meta_controls.vue
index 9f75c65a316..c6247632b6e 100644
--- a/app/assets/javascripts/static_site_editor/components/edit_meta_controls.vue
+++ b/app/assets/javascripts/static_site_editor/components/edit_meta_controls.vue
@@ -1,9 +1,21 @@
<script>
-import { GlForm, GlFormGroup, GlFormInput, GlFormTextarea } from '@gitlab/ui';
-import AccessorUtilities from '~/lib/utils/accessor';
+import {
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlForm,
+ GlFormGroup,
+ GlFormInput,
+ GlFormTextarea,
+} from '@gitlab/ui';
+
+import { __ } from '~/locale';
export default {
components: {
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
GlForm,
GlFormGroup,
GlFormInput,
@@ -18,56 +30,47 @@ export default {
type: String,
required: true,
},
- },
- data() {
- return {
- editable: {
- title: this.title,
- description: this.description,
- },
- };
+ templates: {
+ type: Array,
+ required: false,
+ default: null,
+ },
+ currentTemplate: {
+ type: Object,
+ required: false,
+ default: null,
+ },
},
computed: {
- editableStorageKey() {
- return this.getId('local-storage', 'editable');
+ dropdownLabel() {
+ return this.currentTemplate ? this.currentTemplate.name : __('None');
},
- hasLocalStorage() {
- return AccessorUtilities.isLocalStorageAccessSafe();
+ hasTemplates() {
+ return this.templates?.length > 0;
},
},
mounted() {
- this.initCachedEditable();
this.preSelect();
},
methods: {
getId(type, key) {
return `sse-merge-request-meta-${type}-${key}`;
},
- initCachedEditable() {
- if (this.hasLocalStorage) {
- const cachedEditable = JSON.parse(localStorage.getItem(this.editableStorageKey));
- if (cachedEditable) {
- this.editable = cachedEditable;
- }
- }
- },
preSelect() {
this.$nextTick(() => {
this.$refs.title.$el.select();
});
},
- resetCachedEditable() {
- if (this.hasLocalStorage) {
- window.localStorage.removeItem(this.editableStorageKey);
- }
+ onChangeTemplate(template) {
+ this.$emit('changeTemplate', template || null);
},
- onUpdate() {
- const payload = { ...this.editable };
+ onUpdate(field, value) {
+ const payload = {
+ title: this.title,
+ description: this.description,
+ [field]: value,
+ };
this.$emit('updateSettings', payload);
-
- if (this.hasLocalStorage) {
- window.localStorage.setItem(this.editableStorageKey, JSON.stringify(payload));
- }
},
},
};
@@ -83,21 +86,44 @@ export default {
<gl-form-input
:id="getId('control', 'title')"
ref="title"
- v-model.lazy="editable.title"
+ :value="title"
type="text"
- @input="onUpdate"
+ @input="onUpdate('title', $event)"
/>
</gl-form-group>
<gl-form-group
+ v-if="hasTemplates"
+ key="template"
+ :label="__('Description template')"
+ :label-for="getId('control', 'template')"
+ >
+ <gl-dropdown :text="dropdownLabel">
+ <gl-dropdown-item key="none" @click="onChangeTemplate(null)">
+ {{ __('None') }}
+ </gl-dropdown-item>
+
+ <gl-dropdown-divider />
+
+ <gl-dropdown-item
+ v-for="template in templates"
+ :key="template.key"
+ @click="onChangeTemplate(template)"
+ >
+ {{ template.name }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </gl-form-group>
+
+ <gl-form-group
key="description"
:label="__('Goal of the changes and what reviewers should be aware of')"
:label-for="getId('control', 'description')"
>
<gl-form-textarea
:id="getId('control', 'description')"
- v-model.lazy="editable.description"
- @input="onUpdate"
+ :value="description"
+ @input="onUpdate('description', $event)"
/>
</gl-form-group>
</gl-form>
diff --git a/app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue b/app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue
index 4e5245bd892..f583d2049af 100644
--- a/app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue
+++ b/app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue
@@ -1,22 +1,38 @@
<script>
import { GlModal } from '@gitlab/ui';
import { __, s__, sprintf } from '~/locale';
+import Api from '~/api';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import EditMetaControls from './edit_meta_controls.vue';
+import { ISSUABLE_TYPE, MR_META_LOCAL_STORAGE_KEY } from '../constants';
+
export default {
components: {
GlModal,
EditMetaControls,
+ LocalStorageSync,
},
props: {
sourcePath: {
type: String,
required: true,
},
+ namespace: {
+ type: String,
+ required: true,
+ },
+ project: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
+ clearStorage: false,
+ currentTemplate: null,
+ mergeRequestTemplates: null,
mergeRequestMeta: {
title: sprintf(s__(`StaticSiteEditor|Update %{sourcePath} file`), {
sourcePath: this.sourcePath,
@@ -42,24 +58,42 @@ export default {
};
},
},
+ mounted() {
+ this.initTemplates();
+ },
methods: {
hide() {
this.$refs.modal.hide();
},
+ initTemplates() {
+ const { namespace, project } = this;
+ Api.issueTemplates(namespace, project, ISSUABLE_TYPE, (err, templates) => {
+ if (err) return; // Error handled by global AJAX error handler
+ this.mergeRequestTemplates = templates;
+ });
+ },
show() {
this.$refs.modal.show();
},
onPrimary() {
this.$emit('primary', this.mergeRequestMeta);
- this.$refs.editMetaControls.resetCachedEditable();
+ this.clearStorage = true;
},
onSecondary() {
this.hide();
},
+ onChangeTemplate(template) {
+ this.currentTemplate = template;
+
+ const description = this.currentTemplate ? this.currentTemplate.content : '';
+ const mergeRequestMeta = { ...this.mergeRequestMeta, description };
+ this.onUpdateSettings(mergeRequestMeta);
+ },
onUpdateSettings(mergeRequestMeta) {
this.mergeRequestMeta = { ...mergeRequestMeta };
},
},
+ storageKey: MR_META_LOCAL_STORAGE_KEY,
};
</script>
@@ -75,11 +109,20 @@ export default {
@secondary="onSecondary"
@hide="() => $emit('hide')"
>
+ <local-storage-sync
+ v-model="mergeRequestMeta"
+ :storage-key="$options.storageKey"
+ :clear="clearStorage"
+ as-json
+ />
<edit-meta-controls
ref="editMetaControls"
:title="mergeRequestMeta.title"
:description="mergeRequestMeta.description"
+ :templates="mergeRequestTemplates"
+ :current-template="currentTemplate"
@updateSettings="onUpdateSettings"
+ @changeTemplate="onChangeTemplate"
/>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/static_site_editor/constants.js b/app/assets/javascripts/static_site_editor/constants.js
index 49db9ab7ca5..faa4026c064 100644
--- a/app/assets/javascripts/static_site_editor/constants.js
+++ b/app/assets/javascripts/static_site_editor/constants.js
@@ -2,6 +2,7 @@ import { s__, __ } from '~/locale';
export const BRANCH_SUFFIX_COUNT = 8;
export const DEFAULT_TARGET_BRANCH = 'master';
+export const ISSUABLE_TYPE = 'merge_request';
export const SUBMIT_CHANGES_BRANCH_ERROR = s__('StaticSiteEditor|Branch could not be created.');
export const SUBMIT_CHANGES_COMMIT_ERROR = s__(
@@ -20,4 +21,4 @@ export const TRACKING_ACTION_CREATE_COMMIT = 'create_commit';
export const TRACKING_ACTION_CREATE_MERGE_REQUEST = 'create_merge_request';
export const TRACKING_ACTION_INITIALIZE_EDITOR = 'initialize_editor';
-export const DEFAULT_IMAGE_UPLOAD_PATH = 'source/images/uploads/';
+export const MR_META_LOCAL_STORAGE_KEY = 'sse-merge-request-meta-storage-key';
diff --git a/app/assets/javascripts/static_site_editor/graphql/index.js b/app/assets/javascripts/static_site_editor/graphql/index.js
index cc68bc57bb0..a13f7d3ad53 100644
--- a/app/assets/javascripts/static_site_editor/graphql/index.js
+++ b/app/assets/javascripts/static_site_editor/graphql/index.js
@@ -25,11 +25,15 @@ const createApolloProvider = appData => {
},
);
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ const mounts = appData.mounts.map(mount => ({ __typename: 'Mount', ...mount }));
+
defaultClient.cache.writeData({
data: {
appData: {
__typename: 'AppData',
...appData,
+ mounts,
},
},
});
diff --git a/app/assets/javascripts/static_site_editor/graphql/queries/app_data.query.graphql b/app/assets/javascripts/static_site_editor/graphql/queries/app_data.query.graphql
index 9f4b0afe55f..e422a4b6036 100644
--- a/app/assets/javascripts/static_site_editor/graphql/queries/app_data.query.graphql
+++ b/app/assets/javascripts/static_site_editor/graphql/queries/app_data.query.graphql
@@ -6,5 +6,12 @@ query appData {
sourcePath
username
returnUrl
+ branch
+ baseUrl
+ mounts {
+ source
+ target
+ }
+ imageUploadPath
}
}
diff --git a/app/assets/javascripts/static_site_editor/graphql/typedefs.graphql b/app/assets/javascripts/static_site_editor/graphql/typedefs.graphql
index 0ded1722d26..00af6c10359 100644
--- a/app/assets/javascripts/static_site_editor/graphql/typedefs.graphql
+++ b/app/assets/javascripts/static_site_editor/graphql/typedefs.graphql
@@ -14,6 +14,11 @@ type SavedContentMeta {
branch: SavedContentField!
}
+type Mount {
+ source: String!
+ target: String
+}
+
type AppData {
isSupportedContent: Boolean!
hasSubmittedChanges: Boolean!
@@ -21,6 +26,10 @@ type AppData {
returnUrl: String
sourcePath: String!
username: String!
+ branch: String!
+ baseUrl: String!
+ mounts: [Mount]!
+ imageUploadPath: String!
}
input HasSubmittedChangesInput {
diff --git a/app/assets/javascripts/static_site_editor/image_repository.js b/app/assets/javascripts/static_site_editor/image_repository.js
index 02285ccdba3..b5ff4385d3c 100644
--- a/app/assets/javascripts/static_site_editor/image_repository.js
+++ b/app/assets/javascripts/static_site_editor/image_repository.js
@@ -12,9 +12,11 @@ const imageRepository = () => {
.catch(() => flash(__('Something went wrong while inserting your image. Please try again.')));
};
+ const get = path => images.get(path);
+
const getAll = () => images;
- return { add, getAll };
+ return { add, get, getAll };
};
export default imageRepository;
diff --git a/app/assets/javascripts/static_site_editor/index.js b/app/assets/javascripts/static_site_editor/index.js
index fceef8f9084..b58564388de 100644
--- a/app/assets/javascripts/static_site_editor/index.js
+++ b/app/assets/javascripts/static_site_editor/index.js
@@ -9,6 +9,7 @@ const initStaticSiteEditor = el => {
isSupportedContent,
path: sourcePath,
baseUrl,
+ branch,
namespace,
project,
mergeRequestsIllustrationPath,
@@ -16,13 +17,9 @@ const initStaticSiteEditor = el => {
// so we are adding them here as a convenience for future use.
// eslint-disable-next-line no-unused-vars
staticSiteGenerator,
- // eslint-disable-next-line no-unused-vars
imageUploadPath,
mounts,
} = el.dataset;
- // NOTE that the object in 'mounts' is a JSON string from the data attribute, so it must be parsed into an object.
- // eslint-disable-next-line no-unused-vars
- const mountsObject = JSON.parse(mounts);
const { current_username: username } = window.gon;
const returnUrl = el.dataset.returnUrl || null;
const router = createRouter(baseUrl);
@@ -30,9 +27,13 @@ const initStaticSiteEditor = el => {
isSupportedContent: parseBoolean(isSupportedContent),
hasSubmittedChanges: false,
project: `${namespace}/${project}`,
+ mounts: JSON.parse(mounts), // NOTE that the object in 'mounts' is a JSON string from the data attribute, so it must be parsed into an object.
+ branch,
+ baseUrl,
returnUrl,
sourcePath,
username,
+ imageUploadPath,
});
return new Vue({
diff --git a/app/assets/javascripts/static_site_editor/pages/home.vue b/app/assets/javascripts/static_site_editor/pages/home.vue
index 27bd1c99ae2..68943113c14 100644
--- a/app/assets/javascripts/static_site_editor/pages/home.vue
+++ b/app/assets/javascripts/static_site_editor/pages/home.vue
@@ -64,6 +64,9 @@ export default {
isContentLoaded() {
return Boolean(this.sourceContent);
},
+ projectSplit() {
+ return this.appData.project.split('/'); // TODO: refactor so `namespace` and `project` remain distinct
+ },
},
mounted() {
Tracking.event(document.body.dataset.page, TRACKING_ACTION_INITIALIZE_EDITOR);
@@ -138,11 +141,18 @@ export default {
:content="sourceContent.content"
:saving-changes="isSavingChanges"
:return-url="appData.returnUrl"
+ :mounts="appData.mounts"
+ :branch="appData.branch"
+ :base-url="appData.baseUrl"
+ :project="appData.project"
+ :image-root="appData.imageUploadPath"
@submit="onPrepareSubmit"
/>
<edit-meta-modal
ref="editMetaModal"
:source-path="appData.sourcePath"
+ :namespace="projectSplit[0]"
+ :project="projectSplit[1]"
@primary="onSubmit"
@hide="onHideModal"
/>
diff --git a/app/assets/javascripts/static_site_editor/services/front_matterify.js b/app/assets/javascripts/static_site_editor/services/front_matterify.js
index cbf0fffd515..60a5d799d11 100644
--- a/app/assets/javascripts/static_site_editor/services/front_matterify.js
+++ b/app/assets/javascripts/static_site_editor/services/front_matterify.js
@@ -16,6 +16,7 @@ export const frontMatterify = source => {
const NO_FRONTMATTER = {
source,
matter: null,
+ hasMatter: false,
spacing: null,
content: source,
delimiter: null,
@@ -53,6 +54,7 @@ export const frontMatterify = source => {
return {
source,
matter,
+ hasMatter: true,
spacing,
content,
delimiter,
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 d4fc8b2edb6..39126eb7bcc 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,15 +1,18 @@
import { frontMatterify, stringify } from './front_matterify';
const parseSourceFile = raw => {
- const remake = source => frontMatterify(source);
-
- let editable = remake(raw);
+ let editable;
const syncContent = (newVal, isBody) => {
if (isBody) {
editable.content = newVal;
} else {
- editable = remake(newVal);
+ try {
+ editable = frontMatterify(newVal);
+ editable.isMatterValid = true;
+ } catch (e) {
+ editable.isMatterValid = false;
+ }
}
};
@@ -23,10 +26,15 @@ const parseSourceFile = raw => {
const isModified = () => stringify(editable) !== raw;
- const hasMatter = () => Boolean(editable.matter);
+ const hasMatter = () => editable.hasMatter;
+
+ const isMatterValid = () => editable.isMatterValid;
+
+ syncContent(raw);
return {
matter,
+ isMatterValid,
syncMatter,
content,
syncContent,
diff --git a/app/assets/javascripts/static_site_editor/services/renderers/render_image.js b/app/assets/javascripts/static_site_editor/services/renderers/render_image.js
new file mode 100644
index 00000000000..b0d863bdb5a
--- /dev/null
+++ b/app/assets/javascripts/static_site_editor/services/renderers/render_image.js
@@ -0,0 +1,89 @@
+import { isAbsolute, getBaseURL, joinPaths } from '~/lib/utils/url_utility';
+
+const canRender = ({ type }) => type === 'image';
+
+let metadata;
+
+const getCachedContent = basePath => metadata.imageRepository.get(basePath);
+
+const isRelativeToCurrentDirectory = basePath => !basePath.startsWith('/');
+
+const extractSourceDirectory = url => {
+ const sourceDir = /^(.+)\/([^/]+)$/.exec(url); // Extracts the base path and fileName from an image path
+ return sourceDir || [null, null, url]; // If no source directory was extracted it means only a fileName was specified (e.g. url='file.png')
+};
+
+const parseCurrentDirectory = basePath => {
+ const baseUrl = decodeURIComponent(metadata.baseUrl);
+ const sourceDirectory = extractSourceDirectory(baseUrl)[1];
+ const currentDirectory = sourceDirectory.split(`/-/sse/${metadata.branch}`)[1];
+
+ return joinPaths(currentDirectory, basePath);
+};
+
+// For more context around this logic, please see the following comment:
+// https://gitlab.com/gitlab-org/gitlab/-/issues/241166#note_409413500
+const generateSourceDirectory = basePath => {
+ let sourceDir = '';
+ let defaultSourceDir = '';
+
+ if (!basePath || isRelativeToCurrentDirectory(basePath)) {
+ return parseCurrentDirectory(basePath);
+ }
+
+ if (!metadata.mounts.length) {
+ return basePath;
+ }
+
+ metadata.mounts.forEach(({ source, target }) => {
+ const hasTarget = target !== '';
+
+ if (hasTarget && basePath.includes(target)) {
+ sourceDir = source;
+ } else if (!hasTarget) {
+ defaultSourceDir = joinPaths(source, basePath);
+ }
+ });
+
+ return sourceDir || defaultSourceDir;
+};
+
+const resolveFullPath = (originalSrc, cachedContent) => {
+ if (cachedContent) {
+ return `data:image;base64,${cachedContent}`;
+ }
+
+ if (isAbsolute(originalSrc)) {
+ return originalSrc;
+ }
+
+ const sourceDirectory = extractSourceDirectory(originalSrc);
+ const [, basePath, fileName] = sourceDirectory;
+ const sourceDir = generateSourceDirectory(basePath);
+
+ return joinPaths(getBaseURL(), metadata.project, '/-/raw/', metadata.branch, sourceDir, fileName);
+};
+
+const render = ({ destination: originalSrc, firstChild }, { skipChildren }) => {
+ skipChildren();
+
+ const cachedContent = getCachedContent(originalSrc);
+
+ return {
+ type: 'openTag',
+ tagName: 'img',
+ selfClose: true,
+ attributes: {
+ 'data-original-src': !isAbsolute(originalSrc) || cachedContent ? originalSrc : '',
+ src: resolveFullPath(originalSrc, cachedContent),
+ alt: firstChild.literal,
+ },
+ };
+};
+
+const build = (mounts = [], project, branch, baseUrl, imageRepository) => {
+ metadata = { mounts, project, branch, baseUrl, imageRepository };
+ return { canRender, render };
+};
+
+export default { build };
diff --git a/app/assets/javascripts/terraform/components/empty_state.vue b/app/assets/javascripts/terraform/components/empty_state.vue
new file mode 100644
index 00000000000..d86ba3af2b1
--- /dev/null
+++ b/app/assets/javascripts/terraform/components/empty_state.vue
@@ -0,0 +1,44 @@
+<script>
+import { GlEmptyState, GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlEmptyState,
+ GlIcon,
+ GlLink,
+ GlSprintf,
+ },
+ props: {
+ image: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-empty-state :svg-path="image" :title="s__('Terraform|Get started with Terraform')">
+ <template #description>
+ <p>
+ <gl-sprintf
+ :message="
+ s__(
+ 'Terraform|Find out how to use the %{linkStart}GitLab managed Terraform State%{linkEnd}',
+ )
+ "
+ >
+ <template #link="{ content }">
+ <gl-link
+ href="https://docs.gitlab.com/ee/user/infrastructure/index.html"
+ target="_blank"
+ >
+ {{ content }}
+ <gl-icon name="external-link" />
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </template>
+ </gl-empty-state>
+</template>
diff --git a/app/assets/javascripts/terraform/components/states_table.vue b/app/assets/javascripts/terraform/components/states_table.vue
new file mode 100644
index 00000000000..2e4c18c5a5b
--- /dev/null
+++ b/app/assets/javascripts/terraform/components/states_table.vue
@@ -0,0 +1,101 @@
+<script>
+import { GlBadge, GlIcon, GlSprintf, GlTable, GlTooltip } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
+
+export default {
+ components: {
+ GlBadge,
+ GlIcon,
+ GlSprintf,
+ GlTable,
+ GlTooltip,
+ TimeAgoTooltip,
+ },
+ mixins: [timeagoMixin],
+ props: {
+ states: {
+ required: true,
+ type: Array,
+ },
+ },
+ computed: {
+ fields() {
+ return [
+ {
+ key: 'name',
+ thClass: 'gl-display-none',
+ },
+ {
+ key: 'updated',
+ thClass: 'gl-display-none',
+ tdClass: 'gl-text-right',
+ },
+ ];
+ },
+ },
+ methods: {
+ createdByUserName(item) {
+ return item.latestVersion?.createdByUser?.name;
+ },
+ lockedByUserName(item) {
+ return item.lockedByUser?.name || s__('Terraform|Unknown User');
+ },
+ updatedTime(item) {
+ return item.latestVersion?.updatedAt || item.updatedAt;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-table :items="states" :fields="fields" data-testid="terraform-states-table">
+ <template #cell(name)="{ item }">
+ <div class="gl-display-flex align-items-center" data-testid="terraform-states-table-name">
+ <p class="gl-font-weight-bold gl-m-0 gl-text-gray-900">
+ {{ item.name }}
+ </p>
+
+ <div v-if="item.lockedAt" id="terraformLockedBadgeContainer" class="gl-mx-2">
+ <gl-badge id="terraformLockedBadge">
+ <gl-icon name="lock" />
+ {{ s__('Terraform|Locked') }}
+ </gl-badge>
+
+ <gl-tooltip
+ container="terraformLockedBadgeContainer"
+ placement="right"
+ target="terraformLockedBadge"
+ >
+ <gl-sprintf :message="s__('Terraform|Locked by %{user} %{timeAgo}')">
+ <template #user>
+ {{ lockedByUserName(item) }}
+ </template>
+
+ <template #timeAgo>
+ {{ timeFormatted(item.lockedAt) }}
+ </template>
+ </gl-sprintf>
+ </gl-tooltip>
+ </div>
+ </div>
+ </template>
+
+ <template #cell(updated)="{ item }">
+ <p class="gl-m-0" data-testid="terraform-states-table-updated">
+ <gl-sprintf :message="s__('Terraform|%{user} updated %{timeAgo}')">
+ <template #user>
+ <span v-if="item.latestVersion">
+ {{ createdByUserName(item) }}
+ </span>
+ </template>
+
+ <template #timeAgo>
+ <time-ago-tooltip :time="updatedTime(item)" />
+ </template>
+ </gl-sprintf>
+ </p>
+ </template>
+ </gl-table>
+</template>
diff --git a/app/assets/javascripts/terraform/components/terraform_list.vue b/app/assets/javascripts/terraform/components/terraform_list.vue
new file mode 100644
index 00000000000..f614bdc8d43
--- /dev/null
+++ b/app/assets/javascripts/terraform/components/terraform_list.vue
@@ -0,0 +1,134 @@
+<script>
+import { GlAlert, GlBadge, GlKeysetPagination, GlLoadingIcon, GlTab, GlTabs } from '@gitlab/ui';
+import getStatesQuery from '../graphql/queries/get_states.query.graphql';
+import EmptyState from './empty_state.vue';
+import StatesTable from './states_table.vue';
+import { MAX_LIST_COUNT } from '../constants';
+
+export default {
+ apollo: {
+ states: {
+ query: getStatesQuery,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ ...this.cursor,
+ };
+ },
+ update: data => {
+ return {
+ count: data?.project?.terraformStates?.count,
+ list: data?.project?.terraformStates?.nodes,
+ pageInfo: data?.project?.terraformStates?.pageInfo,
+ };
+ },
+ error() {
+ this.states = null;
+ },
+ },
+ },
+ components: {
+ EmptyState,
+ GlAlert,
+ GlBadge,
+ GlKeysetPagination,
+ GlLoadingIcon,
+ GlTab,
+ GlTabs,
+ StatesTable,
+ },
+ props: {
+ emptyStateImage: {
+ required: true,
+ type: String,
+ },
+ projectPath: {
+ required: true,
+ type: String,
+ },
+ },
+ data() {
+ return {
+ cursor: {
+ first: MAX_LIST_COUNT,
+ after: null,
+ last: null,
+ before: null,
+ },
+ };
+ },
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.states.loading;
+ },
+ pageInfo() {
+ return this.states?.pageInfo || {};
+ },
+ showPagination() {
+ return this.pageInfo.hasPreviousPage || this.pageInfo.hasNextPage;
+ },
+ statesCount() {
+ return this.states?.count;
+ },
+ statesList() {
+ return this.states?.list;
+ },
+ },
+ methods: {
+ updatePagination(item) {
+ if (item === this.pageInfo.endCursor) {
+ this.cursor = {
+ first: MAX_LIST_COUNT,
+ after: item,
+ last: null,
+ before: null,
+ };
+ } else {
+ this.cursor = {
+ first: null,
+ after: null,
+ last: MAX_LIST_COUNT,
+ before: item,
+ };
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <section>
+ <gl-tabs>
+ <gl-tab>
+ <template slot="title">
+ <p class="gl-m-0">
+ {{ s__('Terraform|States') }}
+ <gl-badge v-if="statesCount">{{ statesCount }}</gl-badge>
+ </p>
+ </template>
+
+ <gl-loading-icon v-if="isLoading" size="md" class="gl-mt-3" />
+
+ <div v-else-if="statesList">
+ <div v-if="statesCount">
+ <states-table :states="statesList" />
+
+ <div v-if="showPagination" class="gl-display-flex gl-justify-content-center gl-mt-5">
+ <gl-keyset-pagination
+ v-bind="pageInfo"
+ @prev="updatePagination"
+ @next="updatePagination"
+ />
+ </div>
+ </div>
+
+ <empty-state v-else :image="emptyStateImage" />
+ </div>
+
+ <gl-alert v-else variant="danger" :dismissible="false">
+ {{ s__('Terraform|An error occurred while loading your Terraform States') }}
+ </gl-alert>
+ </gl-tab>
+ </gl-tabs>
+ </section>
+</template>
diff --git a/app/assets/javascripts/terraform/constants.js b/app/assets/javascripts/terraform/constants.js
new file mode 100644
index 00000000000..bbc4630f83b
--- /dev/null
+++ b/app/assets/javascripts/terraform/constants.js
@@ -0,0 +1 @@
+export const MAX_LIST_COUNT = 25;
diff --git a/app/assets/javascripts/terraform/graphql/fragments/state.fragment.graphql b/app/assets/javascripts/terraform/graphql/fragments/state.fragment.graphql
new file mode 100644
index 00000000000..49f9ae3dd97
--- /dev/null
+++ b/app/assets/javascripts/terraform/graphql/fragments/state.fragment.graphql
@@ -0,0 +1,17 @@
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+#import "./state_version.fragment.graphql"
+
+fragment State on TerraformState {
+ id
+ name
+ lockedAt
+ updatedAt
+
+ lockedByUser {
+ ...User
+ }
+
+ latestVersion {
+ ...StateVersion
+ }
+}
diff --git a/app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql b/app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql
new file mode 100644
index 00000000000..c7e9700c696
--- /dev/null
+++ b/app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql
@@ -0,0 +1,9 @@
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+
+fragment StateVersion on TerraformStateVersion {
+ updatedAt
+
+ createdByUser {
+ ...User
+ }
+}
diff --git a/app/assets/javascripts/terraform/graphql/queries/get_states.query.graphql b/app/assets/javascripts/terraform/graphql/queries/get_states.query.graphql
new file mode 100644
index 00000000000..9453e32b1b5
--- /dev/null
+++ b/app/assets/javascripts/terraform/graphql/queries/get_states.query.graphql
@@ -0,0 +1,18 @@
+#import "../fragments/state.fragment.graphql"
+#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
+
+query getStates($projectPath: ID!, $first: Int, $last: Int, $before: String, $after: String) {
+ project(fullPath: $projectPath) {
+ terraformStates(first: $first, last: $last, before: $before, after: $after) {
+ count
+
+ nodes {
+ ...State
+ }
+
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/terraform/index.js b/app/assets/javascripts/terraform/index.js
new file mode 100644
index 00000000000..579d2d14023
--- /dev/null
+++ b/app/assets/javascripts/terraform/index.js
@@ -0,0 +1,31 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import TerraformList from './components/terraform_list.vue';
+import createDefaultClient from '~/lib/graphql';
+
+Vue.use(VueApollo);
+
+export default () => {
+ const el = document.querySelector('#js-terraform-list');
+
+ if (!el) {
+ return null;
+ }
+
+ const defaultClient = createDefaultClient();
+
+ const { emptyStateImage, projectPath } = el.dataset;
+
+ return new Vue({
+ el,
+ apolloProvider: new VueApollo({ defaultClient }),
+ render(createElement) {
+ return createElement(TerraformList, {
+ props: {
+ emptyStateImage,
+ projectPath,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/tooltips/components/tooltips.vue b/app/assets/javascripts/tooltips/components/tooltips.vue
index 8307f878def..05927006ea6 100644
--- a/app/assets/javascripts/tooltips/components/tooltips.vue
+++ b/app/assets/javascripts/tooltips/components/tooltips.vue
@@ -108,6 +108,7 @@ export default {
:container="tooltip.container"
:boundary="tooltip.boundary"
:disabled="tooltip.disabled"
+ :show="tooltip.show"
>
<span v-if="tooltip.html" v-safe-html="tooltip.title"></span>
<span v-else>{{ tooltip.title }}</span>
diff --git a/app/assets/javascripts/tooltips/index.js b/app/assets/javascripts/tooltips/index.js
index 9f5dce4183c..f7cad6639ae 100644
--- a/app/assets/javascripts/tooltips/index.js
+++ b/app/assets/javascripts/tooltips/index.js
@@ -96,6 +96,12 @@ export const initTooltips = (config = {}) => {
return invokeBootstrapApi(document.body, config);
};
+export const add = (elements, config = {}) => {
+ if (isGlTooltipsEnabled()) {
+ return addTooltips(elements, config);
+ }
+ return invokeBootstrapApi(elements, config);
+};
export const dispose = tooltipApiInvoker({
glHandler: element => tooltipsApp().dispose(element),
bsHandler: elements => invokeBootstrapApi(elements, 'dispose'),
diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
index c1521882682..0a1211d0a76 100644
--- a/app/assets/javascripts/tracking.js
+++ b/app/assets/javascripts/tracking.js
@@ -12,6 +12,7 @@ const DEFAULT_SNOWPLOW_OPTIONS = {
contexts: { webPage: true, performanceTiming: true },
formTracking: false,
linkClickTracking: false,
+ pageUnloadTimer: 10,
};
const createEventPayload = (el, { suffix = '' } = {}) => {
diff --git a/app/assets/javascripts/users_select/index.js b/app/assets/javascripts/users_select/index.js
index 20d1a3c1fcd..dccd6807f13 100644
--- a/app/assets/javascripts/users_select/index.js
+++ b/app/assets/javascripts/users_select/index.js
@@ -14,6 +14,7 @@ import ModalStore from '../boards/stores/modal_store';
import { parseBoolean, spriteIcon } from '../lib/utils/common_utils';
import { getAjaxUsersSelectOptions, getAjaxUsersSelectParams } from './utils';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { fixTitle, dispose } from '~/tooltips';
// TODO: remove eventHub hack after code splitting refactor
window.emitSidebarEvent = window.emitSidebarEvent || $.noop;
@@ -229,7 +230,9 @@ function UsersSelect(currentUser, els, options = {}) {
tooltipTitle = s__('UsersSelect|Assignee');
}
$value.html(assigneeTemplate(user));
- $collapsedSidebar.attr('title', tooltipTitle).tooltip('_fixTitle');
+ $collapsedSidebar.attr('title', tooltipTitle);
+ fixTitle($collapsedSidebar);
+
return $collapsedSidebar.html(collapsedAssigneeTemplate(user));
});
};
@@ -423,7 +426,7 @@ function UsersSelect(currentUser, els, options = {}) {
const { $el, e, isMarking } = options;
const user = options.selectedObj;
- $el.tooltip('dispose');
+ dispose($el);
if ($dropdown.hasClass('js-multiselect')) {
const isActive = $el.hasClass('is-active');
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
new file mode 100644
index 00000000000..eff26729fa7
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
@@ -0,0 +1,157 @@
+<script>
+import { GlButton, GlLoadingIcon, GlIcon, GlLink, GlBadge, GlSafeHtmlDirective } from '@gitlab/ui';
+import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
+import StatusIcon from '../mr_widget_status_icon.vue';
+
+export const LOADING_STATES = {
+ collapsedLoading: 'collapsedLoading',
+ collapsedError: 'collapsedError',
+ expandedLoading: 'expandedLoading',
+};
+
+export default {
+ components: {
+ GlButton,
+ GlLoadingIcon,
+ GlIcon,
+ GlLink,
+ GlBadge,
+ SmartVirtualList,
+ StatusIcon,
+ },
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
+ data() {
+ return {
+ loadingState: LOADING_STATES.collapsedLoading,
+ collapsedData: null,
+ fullData: null,
+ isCollapsed: true,
+ };
+ },
+ computed: {
+ isLoadingSummary() {
+ return this.loadingState === LOADING_STATES.collapsedLoading;
+ },
+ isLoadingExpanded() {
+ return this.loadingState === LOADING_STATES.expandedLoading;
+ },
+ isCollapsible() {
+ if (this.isLoadingSummary) {
+ return false;
+ }
+
+ return true;
+ },
+ statusIconName() {
+ if (this.isLoadingSummary) {
+ return 'loading';
+ }
+
+ if (this.loadingState === LOADING_STATES.collapsedError) {
+ return 'warning';
+ }
+
+ return this.statusIcon(this.collapsedData);
+ },
+ },
+ watch: {
+ isCollapsed(newVal) {
+ if (!newVal) {
+ this.loadAllData();
+ } else {
+ this.loadingState = null;
+ }
+ },
+ },
+ mounted() {
+ this.fetchCollapsedData(this.$props)
+ .then(data => {
+ this.collapsedData = data;
+ this.loadingState = null;
+ })
+ .catch(e => {
+ this.loadingState = LOADING_STATES.collapsedError;
+ throw e;
+ });
+ },
+ methods: {
+ toggleCollapsed() {
+ this.isCollapsed = !this.isCollapsed;
+ },
+ loadAllData() {
+ if (this.fullData) return;
+
+ this.loadingState = LOADING_STATES.expandedLoading;
+
+ this.fetchFullData(this.$props)
+ .then(data => {
+ this.loadingState = null;
+ this.fullData = data;
+ })
+ .catch(e => {
+ this.loadingState = null;
+ throw e;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <section class="media-section mr-widget-border-top">
+ <div class="media gl-p-5">
+ <status-icon :status="statusIconName" class="align-self-center" />
+ <div class="media-body d-flex flex-align-self-center align-items-center">
+ <div class="code-text">
+ <template v-if="isLoadingSummary">
+ {{ __('Loading...') }}
+ </template>
+ <div v-else v-safe-html="summary(collapsedData)"></div>
+ </div>
+ <gl-button
+ v-if="isCollapsible"
+ size="small"
+ class="float-right align-self-center"
+ @click="toggleCollapsed"
+ >
+ {{ isCollapsed ? __('Expand') : __('Collapse') }}
+ </gl-button>
+ </div>
+ </div>
+ <div v-if="!isCollapsed" class="mr-widget-grouped-section">
+ <div v-if="isLoadingExpanded" class="report-block-container">
+ <gl-loading-icon inline /> {{ __('Loading...') }}
+ </div>
+ <smart-virtual-list
+ v-else-if="fullData"
+ :length="fullData.length"
+ :remain="20"
+ :size="32"
+ wtag="ul"
+ wclass="report-block-list"
+ class="report-block-container"
+ >
+ <li v-for="data in fullData" :key="data.id" class="d-flex align-items-center">
+ <div v-if="data.icon" :class="data.icon.class" class="d-flex">
+ <gl-icon :name="data.icon.name" :size="24" />
+ </div>
+ <div
+ class="gl-mt-2 gl-mb-2 align-content-around align-items-start flex-wrap align-self-center d-flex"
+ >
+ <div class="gl-mr-4">
+ {{ data.text }}
+ </div>
+ <div v-if="data.link">
+ <gl-link :href="data.link.href">{{ data.link.text }}</gl-link>
+ </div>
+ <gl-badge v-if="data.badge" :variant="data.badge.variant || 'info'">
+ {{ data.badge.text }}
+ </gl-badge>
+ </div>
+ </li>
+ </smart-virtual-list>
+ </div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js b/app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js
new file mode 100644
index 00000000000..5014c12dc30
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js
@@ -0,0 +1,27 @@
+import { extensions } from './index';
+
+export default {
+ props: {
+ mr: {
+ type: Object,
+ required: true,
+ },
+ },
+ render(h) {
+ return h(
+ 'div',
+ {},
+ extensions.map(extension =>
+ h(extension, {
+ props: extensions[0].props.reduce(
+ (acc, key) => ({
+ ...acc,
+ [key]: this.mr[key],
+ }),
+ {},
+ ),
+ }),
+ ),
+ );
+ },
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js b/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js
new file mode 100644
index 00000000000..2bfaec8a1c9
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js
@@ -0,0 +1,30 @@
+import ExtensionBase from './base.vue';
+
+// Holds all the currently registered extensions
+export const extensions = [];
+
+export const registerExtension = extension => {
+ // Pushes into the extenions array a dynamically created Vue component
+ // that gets exteneded from `base.vue`
+ extensions.push({
+ extends: ExtensionBase,
+ name: extension.name,
+ props: extension.props,
+ computed: {
+ ...Object.keys(extension.computed).reduce(
+ (acc, computedKey) => ({
+ ...acc,
+ // Making the computed property a method allows us to pass in arguments
+ // this allows for each computed property to recieve some data
+ [computedKey]() {
+ return extension.computed[computedKey];
+ },
+ }),
+ {},
+ ),
+ },
+ methods: {
+ ...extension.methods,
+ },
+ });
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue
index 598b08f4c16..5ed699acddf 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue
@@ -1,10 +1,10 @@
<script>
-import tooltip from '../../vue_shared/directives/tooltip';
+import { GlTooltipDirective } from '@gitlab/ui';
export default {
name: 'MrWidgetAuthor',
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
author: {
@@ -16,11 +16,6 @@ export default {
required: false,
default: true,
},
- showAuthorTooltip: {
- type: Boolean,
- required: false,
- default: false,
- },
},
computed: {
authorUrl() {
@@ -33,12 +28,7 @@ export default {
};
</script>
<template>
- <a
- :href="authorUrl"
- :v-tooltip="showAuthorTooltip"
- :title="author.name"
- class="author-link inline"
- >
+ <a v-gl-tooltip :href="authorUrl" :title="author.name" class="author-link inline">
<img :src="avatarUrl" class="avatar avatar-inline s16" />
<span v-if="showAuthorName" class="author">{{ author.name }}</span>
</a>
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 eb8989adb2a..d5fdbe726e9 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
@@ -1,6 +1,5 @@
<script>
/* eslint-disable vue/no-v-html */
-import Mousetrap from 'mousetrap';
import { escape } from 'lodash';
import {
GlButton,
@@ -84,17 +83,6 @@ export default {
: '';
},
},
- mounted() {
- Mousetrap.bind('b', this.copyBranchName);
- },
- beforeDestroy() {
- Mousetrap.unbind('b');
- },
- methods: {
- copyBranchName() {
- this.$refs.copyBranchNameButton.$el.click();
- },
- },
};
</script>
<template>
@@ -110,7 +98,6 @@ export default {
class="label-branch label-truncate js-source-branch"
v-html="mr.sourceBranchLink"
/><clipboard-button
- ref="copyBranchNameButton"
data-testid="mr-widget-copy-clipboard"
:text="branchNameClipboardData"
:title="__('Copy branch name')"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue
index f17e409d996..b6722de5277 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue
@@ -1,10 +1,10 @@
<script>
-import { GlDeprecatedDropdown, GlDeprecatedDropdownItem } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
export default {
components: {
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
},
props: {
commits: {
@@ -18,20 +18,20 @@ export default {
<template>
<div>
- <gl-deprecated-dropdown
+ <gl-dropdown
right
text="Use an existing commit message"
variant="link"
class="mr-commit-dropdown"
>
- <gl-deprecated-dropdown-item
+ <gl-dropdown-item
v-for="commit in commits"
:key="commit.short_id"
class="text-nowrap text-truncate"
@click="$emit('input', commit.message)"
>
<span class="monospace mr-2">{{ commit.short_id }}</span> {{ commit.title }}
- </gl-deprecated-dropdown-item>
- </gl-deprecated-dropdown>
+ </gl-dropdown-item>
+ </gl-dropdown>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
index 12f65a4c235..750014c599a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
@@ -1,4 +1,5 @@
<script>
+import { GlLoadingIcon } from '@gitlab/ui';
import autoMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/auto_merge';
import { deprecatedCreateFlash as Flash } from '../../../flash';
import statusIcon from '../mr_widget_status_icon.vue';
@@ -12,6 +13,7 @@ export default {
components: {
MrWidgetAuthor,
statusIcon,
+ GlLoadingIcon,
},
mixins: [autoMergeMixin],
props: {
@@ -100,7 +102,7 @@ export default {
class="btn btn-sm btn-default js-cancel-auto-merge"
@click.prevent="cancelAutomaticMerge"
>
- <i v-if="isCancellingAutoMerge" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
+ <gl-loading-icon v-if="isCancellingAutoMerge" inline class="gl-mr-1" />
{{ cancelButtonText }}
</a>
</h4>
@@ -122,7 +124,7 @@ export default {
href="#"
@click.prevent="removeSourceBranch"
>
- <i v-if="isRemovingSourceBranch" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
+ <gl-loading-icon v-if="isRemovingSourceBranch" inline class="gl-mr-1" />
{{ s__('mrWidget|Delete source branch') }}
</a>
</p>
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 835f7b9e9a9..2c1f2285dda 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,15 @@
<script>
import { isEmpty } from 'lodash';
-import { GlIcon, GlButton, GlSprintf, GlLink } from '@gitlab/ui';
+import {
+ GlIcon,
+ GlButton,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlSprintf,
+ GlLink,
+ GlTooltipDirective,
+} from '@gitlab/ui';
import readyToMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/ready_to_merge';
import simplePoll from '~/lib/utils/simple_poll';
import { __ } from '~/locale';
@@ -36,6 +45,9 @@ export default {
GlSprintf,
GlLink,
GlButton,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
MergeTrainHelperText: () =>
import('ee_component/vue_merge_request_widget/components/merge_train_helper_text.vue'),
MergeImmediatelyConfirmationDialog: () =>
@@ -43,6 +55,9 @@ export default {
'ee_component/vue_merge_request_widget/components/merge_immediately_confirmation_dialog.vue'
),
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
mixins: [readyToMergeMixin],
props: {
mr: { type: Object, required: true },
@@ -283,7 +298,7 @@ export default {
<status-icon :status="iconClass" />
<div class="media-body">
<div class="mr-widget-body-controls media space-children">
- <span class="btn-group">
+ <gl-button-group>
<gl-button
size="medium"
category="primary"
@@ -294,54 +309,33 @@ export default {
@click="handleMergeButtonClick(isAutoMergeAvailable)"
>{{ mergeButtonText }}</gl-button
>
- <button
+ <gl-dropdown
v-if="shouldShowMergeImmediatelyDropdown"
+ v-gl-tooltip.hover.focus="__('Select merge moment')"
:disabled="isMergeButtonDisabled"
- type="button"
- class="btn btn-sm btn-info dropdown-toggle js-merge-moment"
- data-toggle="dropdown"
+ variant="info"
data-qa-selector="merge_moment_dropdown"
- :aria-label="__('Select merge moment')"
- >
- <i class="fa fa-chevron-down" aria-hidden="true"></i>
- </button>
- <ul
- v-if="shouldShowMergeImmediatelyDropdown"
- class="dropdown-menu dropdown-menu-right"
- role="menu"
+ toggle-class="btn-icon js-merge-moment"
>
- <li>
- <a
- class="auto_merge_enabled qa-merge-when-pipeline-succeeds-option"
- href="#"
- @click.prevent="handleMergeButtonClick(true)"
- >
- <span class="media">
- <gl-icon name="status_success" class="merge-opt-icon" aria-hidden="true" />
- <span class="media-body merge-opt-title">{{ autoMergeText }}</span>
- </span>
- </a>
- </li>
- <li>
- <merge-immediately-confirmation-dialog
- ref="confirmationDialog"
- :docs-url="mr.mergeImmediatelyDocsPath"
- @mergeImmediately="onMergeImmediatelyConfirmation"
- />
- <a
- class="accept-merge-request js-merge-immediately-button"
- data-qa-selector="merge_immediately_option"
- href="#"
- @click.prevent="handleMergeImmediatelyButtonClick"
- >
- <span class="media">
- <gl-icon name="status_warning" class="merge-opt-icon" aria-hidden="true" />
- <span class="media-body merge-opt-title">{{ __('Merge immediately') }}</span>
- </span>
- </a>
- </li>
- </ul>
- </span>
+ <template #button-content>
+ <gl-icon name="chevron-down" class="mr-0" />
+ <span class="sr-only">{{ __('Select merge moment') }}</span>
+ </template>
+ <gl-dropdown-item
+ icon-name="warning"
+ button-class="accept-merge-request js-merge-immediately-button"
+ data-qa-selector="merge_immediately_option"
+ @click="handleMergeImmediatelyButtonClick"
+ >
+ {{ __('Merge immediately') }}
+ </gl-dropdown-item>
+ <merge-immediately-confirmation-dialog
+ ref="confirmationDialog"
+ :docs-url="mr.mergeImmediatelyDocsPath"
+ @mergeImmediately="onMergeImmediatelyConfirmation"
+ />
+ </gl-dropdown>
+ </gl-button-group>
<div class="media-body-wrap space-children">
<template v-if="shouldShowMergeControls">
<label v-if="mr.canRemoveSourceBranch">
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 eba3d50fdc9..1d591168a17 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
@@ -1,6 +1,7 @@
<script>
import $ from 'jquery';
import { GlButton } from '@gitlab/ui';
+import { produce } from 'immer';
import { __ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import MergeRequest from '~/merge_request';
@@ -80,12 +81,18 @@ export default {
return;
}
- const data = store.readQuery({
+ const sourceData = store.readQuery({
query: getStateQuery,
variables: mergeRequestQueryVariables,
});
- data.project.mergeRequest.workInProgress = workInProgress;
- data.project.mergeRequest.title = title;
+
+ const data = produce(sourceData, draftState => {
+ // eslint-disable-next-line no-param-reassign
+ draftState.project.mergeRequest.workInProgress = workInProgress;
+ // eslint-disable-next-line no-param-reassign
+ draftState.project.mergeRequest.title = title;
+ });
+
store.writeQuery({
query: getStateQuery,
data,
@@ -143,7 +150,7 @@ export default {
<div class="media-body">
<div class="gl-ml-3 float-left">
<span class="gl-font-weight-bold">
- {{ __('This merge request is still a work in progress.') }}
+ {{ __('This merge request is still a draft.') }}
</span>
<span class="gl-display-block text-muted">{{
__("Draft merge requests can't be merged.")
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
new file mode 100644
index 00000000000..2d21ced1b28
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
@@ -0,0 +1,66 @@
+/* eslint-disable */
+import issuesCollapsedQuery from './issues_collapsed.query.graphql';
+import issuesQuery from './issues.query.graphql';
+
+export default {
+ // Give the extension a name
+ // Make it easier to track in Vue dev tools
+ name: 'WidgetIssues',
+ // Add an array of props
+ // These then get mapped to values stored in the MR Widget store
+ props: ['targetProjectFullPath'],
+ // Add any extra computed props in here
+ computed: {
+ // Small summary text to be displayed in the collapsed state
+ // Receives the collapsed data as an argument
+ summary(count) {
+ return `<strong>${count}</strong> open issue`;
+ },
+ // Status icon to be used next to the summary text
+ // Receives the collapsed data as an argument
+ statusIcon(count) {
+ return count > 0 ? 'warning' : 'success';
+ },
+ },
+ methods: {
+ // Fetches the collapsed data
+ // Ideally, this request should return the smallest amount of data possible
+ // Receives an object of all the props passed in to the extension
+ fetchCollapsedData({ targetProjectFullPath }) {
+ return this.$apollo
+ .query({ query: issuesCollapsedQuery, variables: { projectPath: targetProjectFullPath } })
+ .then(({ data }) => data.project.issues.count);
+ },
+ // Fetches the full data when the extension is expanded
+ // Receives an object of all the props passed in to the extension
+ fetchFullData({ targetProjectFullPath }) {
+ return this.$apollo
+ .query({ query: issuesQuery, variables: { projectPath: targetProjectFullPath } })
+ .then(({ data }) => {
+ // Return some transformed data to be rendered in the expanded state
+ return data.project.issues.nodes.map(issue => ({
+ id: issue.id, // Required: The ID of the object
+ text: issue.title, // Required: The text to get used on each row
+ // Icon to get rendered on the side of each row
+ icon: {
+ // Required: Name maps to an icon in GitLabs SVG
+ name:
+ issue.state === 'closed' ? 'status_failed_borderless' : 'status_success_borderless',
+ // Optional: An extra class to be added to the icon for additional styling
+ class: issue.state === 'closed' ? 'text-danger' : 'text-success',
+ },
+ // Badges get rendered next to the text on each row
+ badge: issue.state === 'closed' && {
+ text: 'Closed', // Required: Text to be used inside of the badge
+ // variant: 'info', // Optional: The variant of the badge, maps to GitLab UI variants
+ },
+ // Each row can have its own link that will take the user elsewhere
+ // link: {
+ // href: 'https://google.com', // Required: href for the link
+ // text: 'Link text', // Required: Text to be used inside the link
+ // },
+ }));
+ });
+ },
+ },
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql
new file mode 100644
index 00000000000..690f571c083
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql
@@ -0,0 +1,13 @@
+query getAllIssues($projectPath: ID!) {
+ project(fullPath: $projectPath) {
+ issues {
+ nodes {
+ id
+ title
+ webPath
+ webUrl
+ state
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql b/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql
new file mode 100644
index 00000000000..389a81e0a61
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql
@@ -0,0 +1,7 @@
+query getIssues($projectPath: ID!) {
+ project(fullPath: $projectPath) {
+ issues {
+ count
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_merge_request_widget/index.js b/app/assets/javascripts/vue_merge_request_widget/index.js
index 87e56dfcbdf..8f2cca3309a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/index.js
@@ -3,12 +3,19 @@ import MrWidgetOptions from 'ee_else_ce/vue_merge_request_widget/mr_widget_optio
import VueApollo from 'vue-apollo';
import Translate from '../vue_shared/translate';
import createDefaultClient from '~/lib/graphql';
+import { registerExtension } from './components/extensions';
+import issueExtension from './extensions/issues';
Vue.use(Translate);
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
+ defaultClient: createDefaultClient(
+ {},
+ {
+ assumeImmutableResults: true,
+ },
+ ),
});
export default () => {
@@ -17,6 +24,8 @@ export default () => {
gl.mrWidgetData.gitlabLogo = gon.gitlab_logo;
gl.mrWidgetData.defaultAvatarUrl = gon.default_avatar_url;
+ registerExtension(issueExtension);
+
const vm = new Vue({ ...MrWidgetOptions, apolloProvider });
window.gl.mrWidget = {
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 46749fc5e87..190d790f584 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
@@ -37,6 +37,7 @@ import FailedToMerge from './components/states/mr_widget_failed_to_merge.vue';
import MrWidgetAutoMergeEnabled from './components/states/mr_widget_auto_merge_enabled.vue';
import AutoMergeFailed from './components/states/mr_widget_auto_merge_failed.vue';
import CheckingState from './components/states/mr_widget_checking.vue';
+// import ExtensionsContainer from './components/extensions/container';
import eventHub from './event_hub';
import notify from '~/lib/utils/notify';
import SourceBranchRemovalStatus from './components/source_branch_removal_status.vue';
@@ -46,7 +47,6 @@ import GroupedTestReportsApp from '../reports/components/grouped_test_reports_ap
import { setFaviconOverlay } from '../lib/utils/common_utils';
import GroupedAccessibilityReportsApp from '../reports/accessibility_report/grouped_accessibility_reports_app.vue';
import getStateQuery from './queries/get_state.query.graphql';
-import { isExperimentEnabled } from '~/lib/utils/experimentation';
export default {
el: '#js-vue-mr-widget',
@@ -58,6 +58,7 @@ export default {
},
components: {
Loading,
+ // ExtensionsContainer,
'mr-widget-header': WidgetHeader,
'mr-widget-suggest-pipeline': WidgetSuggestPipeline,
'mr-widget-merge-help': WidgetMergeHelp,
@@ -154,7 +155,7 @@ export default {
},
shouldSuggestPipelines() {
return (
- isExperimentEnabled('suggestPipeline') &&
+ gon.features?.suggestPipeline &&
!this.mr.hasCI &&
this.mr.mergeRequestAddCiConfigPath &&
!this.mr.isDismissedSuggestPipeline
@@ -455,6 +456,7 @@ export default {
:service="service"
/>
<div class="mr-section-container mr-widget-workflow">
+ <!-- <extensions-container :mr="mr" /> -->
<grouped-codequality-reports-app
v-if="shouldRenderCodeQuality"
:base-path="mr.codeclimate.base_path"
diff --git a/app/assets/javascripts/vue_shared/components/actions_button.vue b/app/assets/javascripts/vue_shared/components/actions_button.vue
index 9b21de19185..cb4c5f20377 100644
--- a/app/assets/javascripts/vue_shared/components/actions_button.vue
+++ b/app/assets/javascripts/vue_shared/components/actions_button.vue
@@ -61,7 +61,6 @@ export default {
<gl-dropdown
v-if="hasMultipleActions"
v-gl-tooltip="selectedAction.tooltip"
- class="gl-button-deprecated-adapter"
:text="selectedAction.text"
:split-href="selectedAction.href"
:variant="variant"
diff --git a/app/assets/javascripts/vue_shared/components/alert_details_table.vue b/app/assets/javascripts/vue_shared/components/alert_details_table.vue
index 34f6d384f7b..3e2b4cd35ab 100644
--- a/app/assets/javascripts/vue_shared/components/alert_details_table.vue
+++ b/app/assets/javascripts/vue_shared/components/alert_details_table.vue
@@ -7,7 +7,6 @@ import {
convertToSentenceCase,
splitCamelCase,
} from '~/lib/utils/text_utility';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
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!';
@@ -25,6 +24,7 @@ const allowedFields = [
'endedAt',
'details',
'hosts',
+ 'environment',
];
export default {
@@ -32,7 +32,6 @@ export default {
GlLoadingIcon,
GlTable,
},
- mixins: [glFeatureFlagsMixin()],
props: {
alert: {
type: Object,
@@ -60,9 +59,6 @@ export default {
},
],
computed: {
- flaggedAllowedFields() {
- return this.shouldDisplayEnvironment ? [...allowedFields, 'environment'] : allowedFields;
- },
items() {
if (!this.alert) {
return [];
@@ -84,13 +80,10 @@ export default {
[],
);
},
- shouldDisplayEnvironment() {
- return this.glFeatures.exposeEnvironmentPathInAlertDetails;
- },
},
methods: {
isAllowed(fieldName) {
- return this.flaggedAllowedFields.includes(fieldName);
+ return allowedFields.includes(fieldName);
},
},
};
diff --git a/app/assets/javascripts/vue_shared/components/awards_list.vue b/app/assets/javascripts/vue_shared/components/awards_list.vue
index 2e4b9b9a135..7a687ea4ad0 100644
--- a/app/assets/javascripts/vue_shared/components/awards_list.vue
+++ b/app/assets/javascripts/vue_shared/components/awards_list.vue
@@ -1,8 +1,7 @@
<script>
/* eslint-disable vue/no-v-html */
import { groupBy } from 'lodash';
-import { GlIcon, GlLoadingIcon } from '@gitlab/ui';
-import tooltip from '~/vue_shared/directives/tooltip';
+import { GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
import { glEmojiTag } from '../../emoji';
import { __, sprintf } from '~/locale';
@@ -15,7 +14,7 @@ export default {
GlLoadingIcon,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
awards: {
@@ -154,10 +153,9 @@ export default {
<button
v-for="awardList in groupedAwards"
:key="awardList.name"
- v-tooltip
+ v-gl-tooltip.viewport
:class="awardList.classes"
:title="awardList.title"
- data-boundary="viewport"
data-testid="award-button"
class="btn award-control"
type="button"
@@ -168,12 +166,11 @@ export default {
</button>
<div v-if="canAwardEmoji" class="award-menu-holder">
<button
- v-tooltip
+ v-gl-tooltip.viewport
:class="addButtonClass"
class="award-control btn js-add-award"
title="Add reaction"
:aria-label="__('Add reaction')"
- data-boundary="viewport"
type="button"
>
<span class="award-control-icon award-control-icon-neutral">
diff --git a/app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js b/app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js
index 7a76888c916..6f7723955bf 100644
--- a/app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js
+++ b/app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js
@@ -1,4 +1,4 @@
-import { SNIPPET_MEASURE_BLOBS_CONTENT } from '~/performance_constants';
+import { SNIPPET_MEASURE_BLOBS_CONTENT } from '~/performance/constants';
import eventHub from '~/blob/components/eventhub';
export default {
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 bbe72a2b122..646e1703f1e 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
@@ -9,6 +9,7 @@ export default {
GlIcon,
},
mixins: [ViewerMixin],
+ inject: ['blobHash'],
data() {
return {
highlightedLine: null,
@@ -64,7 +65,7 @@ export default {
</a>
</div>
<div class="blob-content">
- <pre class="code highlight"><code id="blob-code-content" v-html="content"></code></pre>
+ <pre class="code highlight"><code :data-blob-hash="blobHash" v-html="content"></code></pre>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/ci_icon.vue b/app/assets/javascripts/vue_shared/components/ci_icon.vue
index ff665d9cc58..d775a093f5f 100644
--- a/app/assets/javascripts/vue_shared/components/ci_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_icon.vue
@@ -6,11 +6,8 @@ import { GlIcon } from '@gitlab/ui';
*
* Receives status object containing:
* status: {
- * details_path: "/gitlab-org/gitlab-foss/pipelines/8150156" // url
* group:"running" // used for CSS class
* icon: "icon_status_running" // used to render the icon
- * label:"running" // used for potential tooltip
- * text:"running" // text rendered
* }
*
* Used in:
diff --git a/app/assets/javascripts/vue_shared/components/confirm_modal.vue b/app/assets/javascripts/vue_shared/components/confirm_modal.vue
index a42a606d446..96f800511d2 100644
--- a/app/assets/javascripts/vue_shared/components/confirm_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/confirm_modal.vue
@@ -1,5 +1,5 @@
<script>
-import { GlModal } from '@gitlab/ui';
+import { GlModal, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import csrf from '~/lib/utils/csrf';
@@ -7,6 +7,9 @@ export default {
components: {
GlModal,
},
+ directives: {
+ SafeHtml,
+ },
props: {
selector: {
type: String,
@@ -71,7 +74,8 @@ export default {
-->
<input type="hidden" name="_method" :value="method" />
<input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
- <div>{{ modalAttributes.message }}</div>
+ <div v-if="modalAttributes.messageHtml" v-safe-html="modalAttributes.messageHtml"></div>
+ <div v-else>{{ modalAttributes.message }}</div>
</form>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue
index 494df2d7a37..7e82d8f3f9c 100644
--- a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue
+++ b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue
@@ -1,10 +1,11 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
components: {
GlLoadingIcon,
+ GlIcon,
},
props: {
isDisabled: {
@@ -39,8 +40,10 @@ export default {
<slot v-if="$slots.default"></slot>
<span v-else class="dropdown-toggle-text"> {{ toggleText }} </span>
</template>
- <span v-show="!isLoading" class="dropdown-toggle-icon">
- <i class="fa fa-chevron-down" aria-hidden="true" data-hidden="true"></i>
- </span>
+ <gl-icon
+ v-show="!isLoading"
+ class="gl-absolute gl-top-3 gl-right-3 gl-text-gray-500"
+ name="chevron-down"
+ />
</button>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue
index c1c4f437dee..b4115b0c6a4 100644
--- a/app/assets/javascripts/vue_shared/components/file_row.vue
+++ b/app/assets/javascripts/vue_shared/components/file_row.vue
@@ -1,4 +1,5 @@
<script>
+import { GlTruncate } from '@gitlab/ui';
import FileHeader from '~/vue_shared/components/file_row_header.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import { escapeFileUrl } from '~/lib/utils/url_utility';
@@ -8,6 +9,7 @@ export default {
components: {
FileHeader,
FileIcon,
+ GlTruncate,
},
props: {
file: {
@@ -28,6 +30,11 @@ export default {
required: false,
default: '',
},
+ truncateMiddle: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
isTree() {
@@ -134,9 +141,9 @@ export default {
<span
ref="textOutput"
:style="levelIndentation"
- class="file-row-name str-truncated"
+ class="file-row-name"
data-qa-selector="file_name_content"
- :class="fileClasses"
+ :class="[fileClasses, { 'str-truncated': !truncateMiddle, 'gl-min-w-0': truncateMiddle }]"
>
<file-icon
class="file-row-icon"
@@ -146,8 +153,10 @@ export default {
:folder="isTree"
:opened="file.opened"
:size="16"
+ :submodule="file.submodule"
/>
- {{ file.name }}
+ <gl-truncate v-if="truncateMiddle" :text="file.name" position="middle" class="gl-pr-7" />
+ <template v-else>{{ file.name }}</template>
</span>
<slot></slot>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/file_row_header.vue b/app/assets/javascripts/vue_shared/components/file_row_header.vue
index 2c3e2a3a433..5afb2408c7e 100644
--- a/app/assets/javascripts/vue_shared/components/file_row_header.vue
+++ b/app/assets/javascripts/vue_shared/components/file_row_header.vue
@@ -1,25 +1,21 @@
<script>
-import { truncatePathMiddleToLength } from '~/lib/utils/text_utility';
-
-const MAX_PATH_LENGTH = 40;
+import { GlTruncate } from '@gitlab/ui';
export default {
+ components: {
+ GlTruncate,
+ },
props: {
path: {
type: String,
required: true,
},
},
- computed: {
- truncatedPath() {
- return truncatePathMiddleToLength(this.path, MAX_PATH_LENGTH);
- },
- },
};
</script>
<template>
<div class="file-row-header bg-white sticky-top p-2 js-file-row-header" :title="path">
- <span class="bold">{{ truncatedPath }}</span>
+ <gl-truncate :text="path" position="middle" class="bold" />
</div>
</template>
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 25478ad6f4f..97b4ceda033 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
@@ -5,6 +5,7 @@ import {
GlButton,
GlDropdown,
GlDropdownItem,
+ GlFormCheckbox,
GlTooltipDirective,
} from '@gitlab/ui';
@@ -25,6 +26,7 @@ export default {
GlButton,
GlDropdown,
GlDropdownItem,
+ GlFormCheckbox,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -59,10 +61,25 @@ export default {
default: '',
validator: value => value === '' || /(_desc)|(_asc)/g.test(value),
},
+ showCheckbox: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ checkboxChecked: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
searchInputPlaceholder: {
type: String,
required: true,
},
+ suggestionsListClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
let selectedSortOption = this.sortOptions[0]?.sortDirection?.descending;
@@ -291,12 +308,19 @@ export default {
<template>
<div class="vue-filtered-search-bar-container d-md-flex">
+ <gl-form-checkbox
+ v-if="showCheckbox"
+ class="gl-align-self-center"
+ :checked="checkboxChecked"
+ @input="$emit('checked-input', $event)"
+ />
<gl-filtered-search
ref="filteredSearchInput"
v-model="filterValue"
:placeholder="searchInputPlaceholder"
:available-tokens="tokens"
:history-items="filteredRecentSearches"
+ :suggestions-list-class="suggestionsListClass"
class="flex-grow-1"
@history-item-selected="handleHistoryItemSelected"
@clear-history="handleClearHistory"
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 89952623d0d..c24df5e081d 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
@@ -65,7 +65,7 @@ export default {
.then(({ data }) => {
this.milestones = data;
})
- .catch(() => createFlash(__('There was a problem fetching milestones.')))
+ .catch(() => createFlash({ message: __('There was a problem fetching milestones.') }))
.finally(() => {
this.loading = false;
});
diff --git a/app/assets/javascripts/vue_shared/components/gl_mentions.vue b/app/assets/javascripts/vue_shared/components/gl_mentions.vue
index e895a7a52ab..dde7e3ebe13 100644
--- a/app/assets/javascripts/vue_shared/components/gl_mentions.vue
+++ b/app/assets/javascripts/vue_shared/components/gl_mentions.vue
@@ -10,6 +10,8 @@ const AutoComplete = {
Labels: 'labels',
Members: 'members',
MergeRequests: 'mergeRequests',
+ Milestones: 'milestones',
+ Snippets: 'snippets',
};
const groupType = 'Group'; // eslint-disable-line @gitlab/require-i18n-strings
@@ -120,6 +122,22 @@ const autoCompleteMap = {
return `<small>${original.reference || original.iid}</small> ${escape(original.title)}`;
},
},
+ [AutoComplete.Milestones]: {
+ filterValues() {
+ return this[AutoComplete.Milestones];
+ },
+ menuItemTemplate({ original }) {
+ return escape(original.title);
+ },
+ },
+ [AutoComplete.Snippets]: {
+ filterValues() {
+ return this[AutoComplete.Snippets];
+ },
+ menuItemTemplate({ original }) {
+ return `<small>${original.id}</small> ${escape(original.title)}`;
+ },
+ },
};
export default {
@@ -157,8 +175,8 @@ export default {
menuItemTemplate: autoCompleteMap[AutoComplete.Labels].menuItemTemplate,
selectTemplate: ({ original }) =>
NON_WORD_OR_INTEGER.test(original.title)
- ? `~"${original.title}"`
- : `~${original.title}`,
+ ? `~"${escape(original.title)}"`
+ : `~${escape(original.title)}`,
values: this.getValues(AutoComplete.Labels),
},
{
@@ -168,6 +186,20 @@ export default {
selectTemplate: ({ original }) => original.reference || `!${original.iid}`,
values: this.getValues(AutoComplete.MergeRequests),
},
+ {
+ trigger: '%',
+ lookup: 'title',
+ menuItemTemplate: autoCompleteMap[AutoComplete.Milestones].menuItemTemplate,
+ selectTemplate: ({ original }) => `%"${escape(original.title)}"`,
+ values: this.getValues(AutoComplete.Milestones),
+ },
+ {
+ trigger: '$',
+ fillAttr: 'id',
+ lookup: value => value.id + value.title,
+ menuItemTemplate: autoCompleteMap[AutoComplete.Snippets].menuItemTemplate,
+ values: this.getValues(AutoComplete.Snippets),
+ },
],
});
diff --git a/app/assets/javascripts/vue_shared/components/gl_modal.vue b/app/assets/javascripts/vue_shared/components/gl_modal.vue
deleted file mode 100644
index 4b91d4c00e3..00000000000
--- a/app/assets/javascripts/vue_shared/components/gl_modal.vue
+++ /dev/null
@@ -1,6 +0,0 @@
-<script>
-// This file was only introduced to not break master and shall be delete soon.
-import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
-
-export default DeprecatedModal2;
-</script>
diff --git a/app/assets/javascripts/vue_shared/components/integrations_help_text.vue b/app/assets/javascripts/vue_shared/components/integrations_help_text.vue
new file mode 100644
index 00000000000..4939b5aa98c
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/integrations_help_text.vue
@@ -0,0 +1,35 @@
+<script>
+import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
+
+export default {
+ name: 'IntegrationsHelpText',
+ components: {
+ GlIcon,
+ GlLink,
+ GlSprintf,
+ },
+ props: {
+ message: {
+ type: String,
+ required: true,
+ },
+ messageUrl: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <span>
+ <gl-sprintf :message="message">
+ <template #link="{ content }">
+ <gl-link :href="messageUrl" target="_blank">
+ {{ content }}
+ <gl-icon name="external-link" class="gl-vertical-align-middle" :size="12" />
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/local_storage_sync.vue b/app/assets/javascripts/vue_shared/components/local_storage_sync.vue
index 80c03342f11..33e77b6510c 100644
--- a/app/assets/javascripts/vue_shared/components/local_storage_sync.vue
+++ b/app/assets/javascripts/vue_shared/components/local_storage_sync.vue
@@ -22,11 +22,21 @@ export default {
required: false,
default: true,
},
+ clear: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
watch: {
value(newVal) {
this.saveValue(this.serialize(newVal));
},
+ clear(newVal) {
+ if (newVal) {
+ localStorage.removeItem(this.storageKey);
+ }
+ },
},
mounted() {
// On mount, trigger update if we actually have a localStorageValue
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 65116ed8ca3..9cfba85e0d8 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -141,10 +141,9 @@ export default {
addMultipleToDiscussionWarning() {
return sprintf(
__(
- '%{icon}You are about to add %{usersTag} people to the discussion. They will all receive a notification.',
+ 'You are about to add %{usersTag} people to the discussion. They will all receive a notification.',
),
{
- icon: '<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>',
usersTag: `<strong><span class="js-referenced-users-count">${this.referencedUsers.length}</span></strong>`,
},
false,
@@ -175,9 +174,10 @@ export default {
issues: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
mergeRequests: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
epics: this.enableAutocomplete,
- milestones: this.enableAutocomplete,
+ milestones: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
labels: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
- snippets: this.enableAutocomplete,
+ snippets: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
+ vulnerabilities: this.enableAutocomplete,
},
true,
);
@@ -293,6 +293,7 @@ export default {
<template v-if="previewMarkdown && !markdownPreviewLoading">
<div v-if="referencedCommands" class="referenced-commands" v-html="referencedCommands"></div>
<div v-if="shouldShowReferencedUsers" class="referenced-users">
+ <gl-icon name="warning-solid" />
<span v-html="addMultipleToDiscussionWarning"></span>
</div>
</template>
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 fb9636ba734..fb51840b689 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
@@ -72,6 +72,9 @@ export default {
}
return __('Applying suggestions...');
},
+ isLoggedIn() {
+ return Boolean(gon.current_user_id);
+ },
},
methods: {
applySuggestion() {
@@ -141,6 +144,7 @@ export default {
</gl-button>
<span v-gl-tooltip.viewport="tooltipMessage" tabindex="0">
<gl-button
+ v-if="isLoggedIn"
class="btn-inverted js-apply-btn btn-grouped"
:disabled="isDisableButton"
variant="success"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index 5d47aed9643..5824cb9438f 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -61,43 +61,59 @@ export default {
<span v-if="canAttachFile" class="uploading-container">
<span class="uploading-progress-container hide">
<template>
- <gl-icon name="media" :size="16" class="gl-vertical-align-text-bottom" />
+ <gl-icon name="media" />
</template>
<span class="attaching-file-message"></span>
<!-- eslint-disable-next-line @gitlab/vue-require-i18n-strings -->
<span class="uploading-progress">0%</span>
- <gl-loading-icon inline class="align-text-bottom" />
+ <gl-loading-icon inline />
</span>
<span class="uploading-error-container hide">
<span class="uploading-error-icon">
- <template>
- <gl-icon name="media" :size="16" class="gl-vertical-align-text-bottom" />
- </template>
+ <gl-icon name="media" />
</span>
<span class="uploading-error-message"></span>
<gl-sprintf
:message="
__(
- '%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}',
+ '%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}.',
)
"
>
<template #retryButton="{content}">
- <button class="retry-uploading-link" type="button">{{ content }}</button>
+ <gl-button
+ variant="link"
+ category="primary"
+ class="retry-uploading-link gl-vertical-align-baseline"
+ >
+ {{ content }}
+ </gl-button>
</template>
<template #newFileButton="{content}">
- <button class="attach-new-file markdown-selector" type="button">{{ content }}</button>
+ <gl-button
+ variant="link"
+ category="primary"
+ class="markdown-selector attach-new-file gl-vertical-align-baseline"
+ >
+ {{ content }}
+ </gl-button>
</template>
</gl-sprintf>
</span>
- <gl-button class="markdown-selector button-attach-file" variant="link">
- <template>
- <gl-icon name="media" :size="16" />
- </template>
- <span class="text-attach-file">{{ __('Attach a file') }}</span>
+ <gl-button
+ icon="media"
+ variant="link"
+ category="primary"
+ class="markdown-selector button-attach-file gl-vertical-align-text-bottom"
+ >
+ {{ __('Attach a file') }}
</gl-button>
- <gl-button class="btn btn-default btn-sm hide button-cancel-uploading-files" variant="link">
+ <gl-button
+ variant="link"
+ category="primary"
+ class="button-cancel-uploading-files gl-vertical-align-baseline hide"
+ >
{{ __('Cancel') }}
</gl-button>
</span>
diff --git a/app/assets/javascripts/vue_shared/components/members/action_buttons/user_action_buttons.vue b/app/assets/javascripts/vue_shared/components/members/action_buttons/user_action_buttons.vue
index 8fa3d439fc1..484dbb8fef5 100644
--- a/app/assets/javascripts/vue_shared/components/members/action_buttons/user_action_buttons.vue
+++ b/app/assets/javascripts/vue_shared/components/members/action_buttons/user_action_buttons.vue
@@ -6,7 +6,13 @@ import { s__, sprintf } from '~/locale';
export default {
name: 'UserActionButtons',
- components: { ActionButtonGroup, RemoveMemberButton, LeaveButton },
+ components: {
+ ActionButtonGroup,
+ RemoveMemberButton,
+ LeaveButton,
+ LdapOverrideButton: () =>
+ import('ee_component/vue_shared/components/members/ldap/ldap_override_button.vue'),
+ },
props: {
member: {
type: Object,
@@ -57,5 +63,8 @@ export default {
:title="s__('Member|Remove member')"
/>
</div>
+ <div v-else-if="permissions.canOverride && !member.isOverridden" class="gl-px-1">
+ <ldap-override-button :member="member" />
+ </div>
</action-button-group>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/members/constants.js b/app/assets/javascripts/vue_shared/components/members/constants.js
index 6509779053e..5885420a122 100644
--- a/app/assets/javascripts/vue_shared/components/members/constants.js
+++ b/app/assets/javascripts/vue_shared/components/members/constants.js
@@ -51,6 +51,7 @@ export const FIELDS = [
key: 'actions',
thClass: 'col-actions',
tdClass: 'col-actions',
+ showFunction: 'showActionsField',
},
];
diff --git a/app/assets/javascripts/vue_shared/components/members/table/expiration_datepicker.vue b/app/assets/javascripts/vue_shared/components/members/table/expiration_datepicker.vue
new file mode 100644
index 00000000000..0a8af81c1d1
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/members/table/expiration_datepicker.vue
@@ -0,0 +1,99 @@
+<script>
+import { GlDatepicker } from '@gitlab/ui';
+import { mapActions } from 'vuex';
+import { getDateInFuture } from '~/lib/utils/datetime_utility';
+import { s__ } from '~/locale';
+
+export default {
+ name: 'ExpirationDatepicker',
+ components: { GlDatepicker },
+ props: {
+ member: {
+ type: Object,
+ required: true,
+ },
+ permissions: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ selectedDate: null,
+ busy: false,
+ };
+ },
+ computed: {
+ minDate() {
+ // Members expire at the beginning of the day.
+ // The first selectable day should be tomorrow.
+ const today = new Date();
+ const beginningOfToday = new Date(today.setHours(0, 0, 0, 0));
+
+ return getDateInFuture(beginningOfToday, 1);
+ },
+ disabled() {
+ return (
+ this.busy ||
+ !this.permissions.canUpdate ||
+ (this.permissions.canOverride && !this.member.isOverridden)
+ );
+ },
+ },
+ mounted() {
+ if (this.member.expiresAt) {
+ this.selectedDate = new Date(this.member.expiresAt);
+ }
+ },
+ methods: {
+ ...mapActions(['updateMemberExpiration']),
+ handleInput(date) {
+ this.busy = true;
+ this.updateMemberExpiration({
+ memberId: this.member.id,
+ expiresAt: date,
+ })
+ .then(() => {
+ this.$toast.show(s__('Members|Expiration date updated successfully.'));
+ this.busy = false;
+ })
+ .catch(() => {
+ this.busy = false;
+ });
+ },
+ handleClear() {
+ this.busy = true;
+
+ this.updateMemberExpiration({
+ memberId: this.member.id,
+ expiresAt: null,
+ })
+ .then(() => {
+ this.$toast.show(s__('Members|Expiration date removed successfully.'));
+ this.selectedDate = null;
+ this.busy = false;
+ })
+ .catch(() => {
+ this.busy = false;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <!-- `:target="null"` allows the datepicker to be opened on focus -->
+ <!-- `:container="null"` renders the datepicker in the body to prevent conflicting CSS table styles -->
+ <gl-datepicker
+ v-model="selectedDate"
+ class="gl-max-w-full"
+ show-clear-button
+ :target="null"
+ :container="null"
+ :min-date="minDate"
+ :placeholder="__('Expiration date')"
+ :disabled="disabled"
+ @input="handleInput"
+ @clear="handleClear"
+ />
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/members/table/members_table.vue b/app/assets/javascripts/vue_shared/components/members/table/members_table.vue
index c1a80a85dbe..a4f67caff31 100644
--- a/app/assets/javascripts/vue_shared/components/members/table/members_table.vue
+++ b/app/assets/javascripts/vue_shared/components/members/table/members_table.vue
@@ -1,6 +1,13 @@
<script>
import { mapState } from 'vuex';
import { GlTable, GlBadge } from '@gitlab/ui';
+import MembersTableCell from 'ee_else_ce/vue_shared/components/members/table/members_table_cell.vue';
+import {
+ canOverride,
+ canRemove,
+ canResend,
+ canUpdate,
+} from 'ee_else_ce/vue_shared/components/members/utils';
import { FIELDS } from '../constants';
import initUserPopovers from '~/user_popovers';
import MemberAvatar from './member_avatar.vue';
@@ -8,9 +15,9 @@ import MemberSource from './member_source.vue';
import CreatedAt from './created_at.vue';
import ExpiresAt from './expires_at.vue';
import MemberActionButtons from './member_action_buttons.vue';
-import MembersTableCell from './members_table_cell.vue';
import RoleDropdown from './role_dropdown.vue';
import RemoveGroupLinkModal from '../modals/remove_group_link_modal.vue';
+import ExpirationDatepicker from './expiration_datepicker.vue';
export default {
name: 'MembersTable',
@@ -25,23 +32,56 @@ export default {
MemberActionButtons,
RoleDropdown,
RemoveGroupLinkModal,
+ ExpirationDatepicker,
+ LdapOverrideConfirmationModal: () =>
+ import(
+ 'ee_component/vue_shared/components/members/ldap/ldap_override_confirmation_modal.vue'
+ ),
},
computed: {
- ...mapState(['members', 'tableFields']),
+ ...mapState(['members', 'tableFields', 'tableAttrs', 'currentUserId', 'sourceId']),
filteredFields() {
- return FIELDS.filter(field => this.tableFields.includes(field.key));
+ return FIELDS.filter(field => this.tableFields.includes(field.key) && this.showField(field));
+ },
+ userIsLoggedIn() {
+ return this.currentUserId !== null;
},
},
mounted() {
initUserPopovers(this.$el.querySelectorAll('.js-user-link'));
},
+ methods: {
+ showField(field) {
+ if (!Object.prototype.hasOwnProperty.call(field, 'showFunction')) {
+ return true;
+ }
+
+ return this[field.showFunction]();
+ },
+ showActionsField() {
+ if (!this.userIsLoggedIn) {
+ return false;
+ }
+
+ return this.members.some(member => {
+ return (
+ canRemove(member, this.sourceId) ||
+ canResend(member) ||
+ canUpdate(member, this.currentUserId, this.sourceId) ||
+ canOverride(member)
+ );
+ });
+ },
+ },
};
</script>
<template>
<div>
<gl-table
+ v-bind="tableAttrs.table"
class="members-table"
+ data-testid="members-table"
head-variant="white"
stacked="lg"
:fields="filteredFields"
@@ -50,6 +90,7 @@ export default {
thead-class="border-bottom"
:empty-text="__('No members found')"
show-empty
+ :tbody-tr-attr="tableAttrs.tr"
>
<template #cell(account)="{ item: member }">
<members-table-cell #default="{ memberType, isCurrentUser }" :member="member">
@@ -85,11 +126,17 @@ export default {
<template #cell(maxRole)="{ item: member }">
<members-table-cell #default="{ permissions }" :member="member">
- <role-dropdown v-if="permissions.canUpdate" :member="member" />
+ <role-dropdown v-if="permissions.canUpdate" :permissions="permissions" :member="member" />
<gl-badge v-else>{{ member.accessLevel.stringValue }}</gl-badge>
</members-table-cell>
</template>
+ <template #cell(expiration)="{ item: member }">
+ <members-table-cell #default="{ permissions }" :member="member">
+ <expiration-datepicker :permissions="permissions" :member="member" />
+ </members-table-cell>
+ </template>
+
<template #cell(actions)="{ item: member }">
<members-table-cell #default="{ memberType, isCurrentUser, permissions }" :member="member">
<member-action-buttons
@@ -106,5 +153,6 @@ export default {
</template>
</gl-table>
<remove-group-link-modal />
+ <ldap-override-confirmation-modal />
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/members/table/members_table_cell.vue b/app/assets/javascripts/vue_shared/components/members/table/members_table_cell.vue
index 5602978bb6c..11e1aef9803 100644
--- a/app/assets/javascripts/vue_shared/components/members/table/members_table_cell.vue
+++ b/app/assets/javascripts/vue_shared/components/members/table/members_table_cell.vue
@@ -1,6 +1,7 @@
<script>
import { mapState } from 'vuex';
import { MEMBER_TYPES } from '../constants';
+import { isGroup, isDirectMember, isCurrentUser, canRemove, canResend, canUpdate } from '../utils';
export default {
name: 'MembersTableCell',
@@ -13,7 +14,7 @@ export default {
computed: {
...mapState(['sourceId', 'currentUserId']),
isGroup() {
- return Boolean(this.member.sharedWithGroup);
+ return isGroup(this.member);
},
isInvite() {
return Boolean(this.member.invite);
@@ -33,19 +34,19 @@ export default {
return MEMBER_TYPES.user;
},
isDirectMember() {
- return this.isGroup || this.member.source?.id === this.sourceId;
+ return isDirectMember(this.member, this.sourceId);
},
isCurrentUser() {
- return this.member.user?.id === this.currentUserId;
+ return isCurrentUser(this.member, this.currentUserId);
},
canRemove() {
- return this.isDirectMember && this.member.canRemove;
+ return canRemove(this.member, this.sourceId);
},
canResend() {
- return Boolean(this.member.invite?.canResend);
+ return canResend(this.member);
},
canUpdate() {
- return !this.isCurrentUser && this.isDirectMember && this.member.canUpdate;
+ return canUpdate(this.member, this.currentUserId, this.sourceId);
},
},
render() {
diff --git a/app/assets/javascripts/vue_shared/components/members/table/role_dropdown.vue b/app/assets/javascripts/vue_shared/components/members/table/role_dropdown.vue
index 2b40ccc3a9d..6f6cae6072d 100644
--- a/app/assets/javascripts/vue_shared/components/members/table/role_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/components/members/table/role_dropdown.vue
@@ -9,12 +9,18 @@ export default {
components: {
GlDropdown,
GlDropdownItem,
+ LdapDropdownItem: () =>
+ import('ee_component/vue_shared/components/members/ldap/ldap_dropdown_item.vue'),
},
props: {
member: {
type: Object,
required: true,
},
+ permissions: {
+ type: Object,
+ required: true,
+ },
},
data() {
return {
@@ -22,8 +28,21 @@ export default {
busy: false,
};
},
+ computed: {
+ disabled() {
+ return this.busy || (this.permissions.canOverride && !this.member.isOverridden);
+ },
+ },
mounted() {
this.isDesktop = bp.isDesktop();
+
+ // Bootstrap Vue and GlDropdown to not support adding attributes to the dropdown toggle
+ // This can be changed once https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1060 is implemented
+ const dropdownToggle = this.$refs.glDropdown.$el.querySelector('.dropdown-toggle');
+
+ if (dropdownToggle) {
+ dropdownToggle.setAttribute('data-qa-selector', 'access_level_dropdown');
+ }
},
methods: {
...mapActions(['updateMemberRole']),
@@ -52,19 +71,25 @@ export default {
<template>
<gl-dropdown
+ ref="glDropdown"
:right="!isDesktop"
:text="member.accessLevel.stringValue"
:header-text="__('Change permissions')"
- :disabled="busy"
+ :disabled="disabled"
>
<gl-dropdown-item
v-for="(value, name) in member.validRoles"
:key="value"
is-check-item
:is-checked="value === member.accessLevel.integerValue"
+ data-qa-selector="access_level_link"
@click="handleSelect(value, name)"
>
{{ name }}
</gl-dropdown-item>
+ <ldap-dropdown-item
+ v-if="permissions.canOverride && member.isOverridden"
+ :member-id="member.id"
+ />
</gl-dropdown>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/members/utils.js b/app/assets/javascripts/vue_shared/components/members/utils.js
index 782a0b7f96b..4229a62c0a7 100644
--- a/app/assets/javascripts/vue_shared/components/members/utils.js
+++ b/app/assets/javascripts/vue_shared/components/members/utils.js
@@ -17,3 +17,32 @@ export const generateBadges = (member, isCurrentUser) => [
variant: 'info',
},
];
+
+export const isGroup = member => {
+ return Boolean(member.sharedWithGroup);
+};
+
+export const isDirectMember = (member, sourceId) => {
+ return isGroup(member) || member.source?.id === sourceId;
+};
+
+export const isCurrentUser = (member, currentUserId) => {
+ return member.user?.id === currentUserId;
+};
+
+export const canRemove = (member, sourceId) => {
+ return isDirectMember(member, sourceId) && member.canRemove;
+};
+
+export const canResend = member => {
+ return Boolean(member.invite?.canResend);
+};
+
+export const canUpdate = (member, currentUserId, sourceId) => {
+ return (
+ !isCurrentUser(member, currentUserId) && isDirectMember(member, sourceId) && member.canUpdate
+ );
+};
+
+// Defined in `ee/app/assets/javascripts/vue_shared/components/members/utils.js`
+export const canOverride = () => false;
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 cad4439ecea..de9c84dd157 100644
--- a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
+++ b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
@@ -1,8 +1,7 @@
<script>
-import $ from 'jquery';
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import Clipboard from 'clipboard';
-import { __ } from '~/locale';
+import { uniqueId } from 'lodash';
export default {
components: {
@@ -17,6 +16,11 @@ export default {
required: false,
default: '',
},
+ id: {
+ type: String,
+ required: false,
+ default: () => uniqueId('modal-copy-button-'),
+ },
container: {
type: String,
required: false,
@@ -52,7 +56,6 @@ export default {
default: null,
},
},
- copySuccessText: __('Copied'),
computed: {
modalDomId() {
return this.modalId ? `#${this.modalId}` : '';
@@ -68,11 +71,11 @@ export default {
});
this.clipboard
.on('success', e => {
- this.updateTooltip(e.trigger);
+ this.$root.$emit('bv::hide::tooltip', this.id);
this.$emit('success', e);
// Clear the selection and blur the trigger so it loses its border
e.clearSelection();
- $(e.trigger).blur();
+ e.trigger.blur();
})
.on('error', e => this.$emit('error', e));
});
@@ -82,29 +85,11 @@ export default {
this.clipboard.destroy();
}
},
- methods: {
- updateTooltip(target) {
- const $target = $(target);
- const originalTitle = $target.data('originalTitle');
-
- if ($target.tooltip) {
- /**
- * The original tooltip will continue staying there unless we remove it by hand.
- * $target.tooltip('hide') isn't working.
- */
- $('.tooltip').remove();
- $target.attr('title', this.$options.copySuccessText);
- $target.tooltip('_fixTitle');
- $target.tooltip('show');
- $target.attr('title', originalTitle);
- $target.tooltip('_fixTitle');
- }
- },
- },
};
</script>
<template>
<gl-button
+ :id="id"
v-gl-tooltip="{ placement: tooltipPlacement, container: tooltipContainer }"
:class="cssClasses"
:data-clipboard-target="target"
diff --git a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
index 8e85d93e6d1..1fc39c7cb8e 100644
--- a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
+++ b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
@@ -308,6 +308,6 @@ export default {
@input="handlePageChange"
/>
- <slot v-if="!showItems" name="emtpy-state"></slot>
+ <slot v-if="!showItems" name="empty-state"></slot>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/registry/title_area.vue b/app/assets/javascripts/vue_shared/components/registry/title_area.vue
index 06b4309ad42..4d47a34c9a3 100644
--- a/app/assets/javascripts/vue_shared/components/registry/title_area.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/title_area.vue
@@ -30,8 +30,13 @@ export default {
metadataSlots: [],
};
},
- mounted() {
- this.metadataSlots = Object.keys(this.$slots).filter(k => k.startsWith('metadata-'));
+ async mounted() {
+ const METADATA_PREFIX = 'metadata-';
+ this.metadataSlots = Object.keys(this.$slots).filter(k => k.startsWith(METADATA_PREFIX));
+
+ // we need to wait for next tick to ensure that dynamic names slots are picked up
+ await this.$nextTick();
+ this.metadataSlots = Object.keys(this.$slots).filter(k => k.startsWith(METADATA_PREFIX));
},
};
</script>
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue b/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue
index e1652f54982..82060d2e4ad 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue
@@ -1,8 +1,7 @@
<script>
import { GlModal, GlFormGroup, GlFormInput, GlTabs, GlTab } from '@gitlab/ui';
-import { isSafeURL } from '~/lib/utils/url_utility';
+import { isSafeURL, joinPaths } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { IMAGE_TABS } from '../../constants';
import UploadImageTab from './upload_image_tab.vue';
@@ -15,7 +14,6 @@ export default {
GlTabs,
GlTab,
},
- mixins: [glFeatureFlagMixin()],
props: {
imageRoot: {
type: String,
@@ -34,10 +32,10 @@ export default {
},
modalTitle: __('Image details'),
okTitle: __('Insert image'),
- urlTabTitle: __('By URL'),
+ urlTabTitle: __('Link to an image'),
urlLabel: __('Image URL'),
descriptionLabel: __('Description'),
- uploadTabTitle: __('Upload file'),
+ uploadTabTitle: __('Upload an image'),
computed: {
altText() {
return this.description;
@@ -54,7 +52,7 @@ export default {
this.$refs.modal.show();
},
onOk(event) {
- if (this.glFeatures.sseImageUploads && this.tabIndex === IMAGE_TABS.UPLOAD_TAB) {
+ if (this.tabIndex === IMAGE_TABS.UPLOAD_TAB) {
this.submitFile(event);
return;
}
@@ -74,7 +72,7 @@ export default {
return;
}
- const imageUrl = `${this.imageRoot}${file.name}`;
+ const imageUrl = joinPaths(this.imageRoot, file.name);
this.$emit('addImage', { imageUrl, file, altText: altText || file.name });
},
@@ -108,7 +106,7 @@ export default {
:ok-title="$options.okTitle"
@ok="onOk"
>
- <gl-tabs v-if="glFeatures.sseImageUploads" v-model="tabIndex">
+ <gl-tabs v-model="tabIndex">
<!-- Upload file Tab -->
<gl-tab :title="$options.uploadTabTitle">
<upload-image-tab ref="uploadImageTab" @input="setFile" />
@@ -128,17 +126,6 @@ export default {
</gl-tab>
</gl-tabs>
- <gl-form-group
- v-else
- class="gl-mt-5 gl-mb-3"
- :label="$options.urlLabel"
- label-for="url-input"
- :state="!Boolean(urlError)"
- :invalid-feedback="urlError"
- >
- <gl-form-input id="url-input" ref="urlInput" v-model="imageUrl" />
- </gl-form-group>
-
<!-- Description Input -->
<gl-form-group :label="$options.descriptionLabel" label-for="description-input">
<gl-form-input id="description-input" ref="descriptionInput" v-model="description" />
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue b/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
index c2518441506..9eacf74bba8 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
@@ -53,7 +53,6 @@ export default {
imageRoot: {
type: String,
required: true,
- validator: prop => prop.endsWith('/'),
},
},
data() {
@@ -115,10 +114,9 @@ export default {
if (file) {
this.$emit('uploadImage', { file, imageUrl });
- // TODO - ensure that the actual repo URL for the image is used in Markdown mode
}
- addImage(this.editorInstance, image);
+ addImage(this.editorInstance, image, file);
},
onOpenInsertVideoModal() {
this.$refs.insertVideoModal.show();
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 2bce691e793..9744e25a8e1 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
@@ -99,6 +99,10 @@ const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) =>
? `\n\n${node.innerText}\n\n`
: baseRenderer.convert(node, subContent);
},
+ IMG(node) {
+ const { originalSrc } = node.dataset;
+ return `![${node.alt}](${originalSrc || node.src})`;
+ },
};
};
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
index 8b3fbcabcfa..463e64b4936 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
@@ -34,6 +34,20 @@ const buildVideoIframe = src => {
return wrapper;
};
+const buildImg = (alt, originalSrc, file) => {
+ const img = document.createElement('img');
+ const src = file ? URL.createObjectURL(file) : originalSrc;
+ const attributes = { alt, src };
+
+ if (file) {
+ img.dataset.originalSrc = originalSrc;
+ }
+
+ Object.assign(img, attributes);
+
+ return img;
+};
+
export const generateToolbarItem = config => {
const { icon, classes, event, command, tooltip, isDivider } = config;
@@ -59,7 +73,14 @@ export const addCustomEventListener = (editorApi, event, handler) => {
export const removeCustomEventListener = (editorApi, event, handler) =>
editorApi.eventManager.removeEventHandler(event, handler);
-export const addImage = ({ editor }, image) => editor.exec('AddImage', image);
+export const addImage = ({ editor }, { altText, imageUrl }, file) => {
+ if (editor.isWysiwygMode()) {
+ const img = buildImg(altText, imageUrl, file);
+ editor.getSquire().insertElement(img);
+ } else {
+ editor.insertText(`![${altText}](${imageUrl})`);
+ }
+};
export const insertVideo = ({ editor }, url) => {
const videoIframe = buildVideoIframe(url);
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql
new file mode 100644
index 00000000000..ff0626167a9
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql
@@ -0,0 +1,20 @@
+query getRunnerPlatforms($projectPath: ID!, $groupPath: ID!) {
+ runnerPlatforms {
+ nodes {
+ name
+ humanReadableName
+ architectures {
+ nodes {
+ name
+ downloadLocation
+ }
+ }
+ }
+ }
+ project(fullPath: $projectPath) {
+ id
+ }
+ group(fullPath: $groupPath) {
+ id
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql
new file mode 100644
index 00000000000..643c1991807
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql
@@ -0,0 +1,16 @@
+query runnerSetupInstructions(
+ $platform: String!
+ $architecture: String!
+ $projectId: ID!
+ $groupId: ID!
+) {
+ runnerSetup(
+ platform: $platform
+ architecture: $architecture
+ projectId: $projectId
+ groupId: $groupId
+ ) {
+ installInstructions
+ registerInstructions
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
new file mode 100644
index 00000000000..b70b1277155
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
@@ -0,0 +1,220 @@
+<script>
+import {
+ GlAlert,
+ GlButton,
+ GlModal,
+ GlModalDirective,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlIcon,
+} from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+import getRunnerPlatforms from './graphql/queries/get_runner_platforms.query.graphql';
+import getRunnerSetupInstructions from './graphql/queries/get_runner_setup.query.graphql';
+
+export default {
+ components: {
+ GlAlert,
+ GlButton,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlModal,
+ GlIcon,
+ },
+ directives: {
+ GlModalDirective,
+ },
+ inject: {
+ projectPath: {
+ default: '',
+ },
+ groupPath: {
+ default: '',
+ },
+ },
+ apollo: {
+ runnerPlatforms: {
+ query: getRunnerPlatforms,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ groupPath: this.groupPath,
+ };
+ },
+ update(data) {
+ return data;
+ },
+ error() {
+ this.showAlert = true;
+ },
+ },
+ },
+ data() {
+ return {
+ showAlert: false,
+ selectedPlatformArchitectures: [],
+ selectedPlatform: {},
+ selectedArchitecture: {},
+ runnerPlatforms: {},
+ instructions: {},
+ };
+ },
+ computed: {
+ isPlatformSelected() {
+ return Object.keys(this.selectedPlatform).length > 0;
+ },
+ instructionsEmpty() {
+ return this.instructions && Object.keys(this.instructions).length === 0;
+ },
+ groupId() {
+ return this.runnerPlatforms?.group?.id ?? '';
+ },
+ projectId() {
+ return this.runnerPlatforms?.project?.id ?? '';
+ },
+ platforms() {
+ return this.runnerPlatforms.runnerPlatforms?.nodes;
+ },
+ },
+ methods: {
+ selectPlatform(name) {
+ this.selectedPlatform = this.platforms.find(platform => platform.name === name);
+ this.selectedPlatformArchitectures = this.selectedPlatform?.architectures?.nodes;
+ [this.selectedArchitecture] = this.selectedPlatformArchitectures;
+ this.selectArchitecture(this.selectedArchitecture);
+ },
+ selectArchitecture(architecture) {
+ this.selectedArchitecture = architecture;
+
+ this.$apollo.addSmartQuery('instructions', {
+ variables() {
+ return {
+ platform: this.selectedPlatform.name,
+ architecture: this.selectedArchitecture.name,
+ projectId: this.projectId,
+ groupId: this.groupId,
+ };
+ },
+ query: getRunnerSetupInstructions,
+ update(data) {
+ return data?.runnerSetup;
+ },
+ error() {
+ this.showAlert = true;
+ },
+ });
+ },
+ toggleAlert(state) {
+ this.showAlert = state;
+ },
+ },
+ modalId: 'installation-instructions-modal',
+ i18n: {
+ installARunner: __('Install a Runner'),
+ architecture: s__('Runners|Architecture'),
+ downloadInstallBinary: s__('Runners|Download and Install Binary'),
+ downloadLatestBinary: s__('Runners|Download Latest Binary'),
+ registerRunner: s__('Runners|Register Runner'),
+ method: __('Method'),
+ fetchError: s__('An error has occurred fetching instructions'),
+ instructions: __('Show Runner installation instructions'),
+ },
+ closeButton: {
+ text: __('Close'),
+ attributes: [{ variant: 'default' }],
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-button v-gl-modal-directive="$options.modalId" data-testid="show-modal-button">
+ {{ $options.i18n.instructions }}
+ </gl-button>
+ <gl-modal
+ :modal-id="$options.modalId"
+ :title="$options.i18n.installARunner"
+ :action-secondary="$options.closeButton"
+ >
+ <gl-alert v-if="showAlert" variant="danger" @dismiss="toggleAlert(false)">
+ {{ $options.i18n.fetchError }}
+ </gl-alert>
+ <h5>{{ __('Environment') }}</h5>
+ <gl-button-group class="gl-mb-5">
+ <gl-button
+ v-for="platform in platforms"
+ :key="platform.name"
+ data-testid="platform-button"
+ @click="selectPlatform(platform.name)"
+ >
+ {{ platform.humanReadableName }}
+ </gl-button>
+ </gl-button-group>
+ <template v-if="isPlatformSelected">
+ <h5>
+ {{ $options.i18n.architecture }}
+ </h5>
+ <gl-dropdown class="gl-mb-5" :text="selectedArchitecture.name">
+ <gl-dropdown-item
+ v-for="architecture in selectedPlatformArchitectures"
+ :key="architecture.name"
+ data-testid="architecture-dropdown-item"
+ @click="selectArchitecture(architecture)"
+ >
+ {{ architecture.name }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ <div class="gl-display-flex gl-align-items-center gl-mb-5">
+ <h5>{{ $options.i18n.downloadInstallBinary }}</h5>
+ <gl-button
+ class="gl-ml-auto"
+ :href="selectedArchitecture.downloadLocation"
+ download
+ data-testid="binary-download-button"
+ >
+ {{ $options.i18n.downloadLatestBinary }}
+ </gl-button>
+ </div>
+ </template>
+ <template v-if="!instructionsEmpty">
+ <div class="gl-display-flex">
+ <pre
+ class="bg-light gl-flex-fill-1 gl-white-space-pre-line"
+ data-testid="binary-instructions"
+ >
+ {{ instructions.installInstructions }}
+ </pre>
+ <gl-button
+ class="gl-align-self-start gl-ml-2 gl-mt-2"
+ category="tertiary"
+ variant="link"
+ :data-clipboard-text="instructions.installationInstructions"
+ >
+ <gl-icon name="copy-to-clipboard" />
+ </gl-button>
+ </div>
+
+ <hr />
+ <h5 class="gl-mb-5">{{ $options.i18n.registerRunner }}</h5>
+ <h5 class="gl-mb-5">{{ $options.i18n.method }}</h5>
+ <div class="gl-display-flex">
+ <pre
+ class="bg-light gl-flex-fill-1 gl-white-space-pre-line"
+ data-testid="runner-instructions"
+ >
+ {{ instructions.registerInstructions }}
+ </pre>
+ <gl-button
+ class="gl-align-self-start gl-ml-2 gl-mt-2"
+ category="tertiary"
+ variant="link"
+ :data-clipboard-text="instructions.registerInstructions"
+ >
+ <gl-icon name="copy-to-clipboard" />
+ </gl-button>
+ </div>
+ </template>
+ </gl-modal>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/issuable_move_dropdown.vue b/app/assets/javascripts/vue_shared/components/sidebar/issuable_move_dropdown.vue
new file mode 100644
index 00000000000..1d3bd312b09
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/issuable_move_dropdown.vue
@@ -0,0 +1,211 @@
+<script>
+import {
+ GlIcon,
+ GlLoadingIcon,
+ GlDropdown,
+ GlDropdownForm,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ GlButton,
+ GlTooltipDirective as GlTooltip,
+} from '@gitlab/ui';
+
+import axios from '~/lib/utils/axios_utils';
+
+export default {
+ components: {
+ GlIcon,
+ GlLoadingIcon,
+ GlDropdown,
+ GlDropdownForm,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ GlButton,
+ },
+ directives: {
+ GlTooltip,
+ },
+ props: {
+ projectsFetchPath: {
+ type: String,
+ required: true,
+ },
+ dropdownButtonTitle: {
+ type: String,
+ required: true,
+ },
+ dropdownHeaderTitle: {
+ type: String,
+ required: true,
+ },
+ moveInProgress: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ projectsListLoading: false,
+ projectsListLoadFailed: false,
+ searchKey: '',
+ projects: [],
+ selectedProject: null,
+ projectItemClick: false,
+ };
+ },
+ computed: {
+ hasNoSearchResults() {
+ return Boolean(
+ !this.projectsListLoading &&
+ !this.projectsListLoadFailed &&
+ this.searchKey &&
+ !this.projects.length,
+ );
+ },
+ failedToLoadResults() {
+ return !this.projectsListLoading && this.projectsListLoadFailed;
+ },
+ },
+ watch: {
+ searchKey(value = '') {
+ this.fetchProjects(value);
+ },
+ },
+ methods: {
+ fetchProjects(search = '') {
+ this.projectsListLoading = true;
+ this.projectsListLoadFailed = false;
+ return axios
+ .get(this.projectsFetchPath, {
+ params: {
+ search,
+ },
+ })
+ .then(({ data }) => {
+ this.projects = data;
+ this.$refs.searchInput.focusInput();
+ })
+ .catch(() => {
+ this.projectsListLoadFailed = true;
+ })
+ .finally(() => {
+ this.projectsListLoading = false;
+ });
+ },
+ isSelectedProject(project) {
+ if (this.selectedProject) {
+ return this.selectedProject.id === project.id;
+ }
+ return false;
+ },
+ /**
+ * This handler is to prevent dropdown
+ * from closing when an item is selected
+ * and emit an event only when dropdown closes.
+ */
+ handleDropdownHide(e) {
+ if (this.projectItemClick) {
+ e.preventDefault();
+ this.projectItemClick = false;
+ } else {
+ this.$emit('dropdown-close');
+ }
+ },
+ handleDropdownCloseClick() {
+ this.$refs.dropdown.hide();
+ },
+ handleProjectSelect(project) {
+ this.selectedProject = project.id === this.selectedProject?.id ? null : project;
+ this.projectItemClick = true;
+ },
+ handleMoveClick() {
+ this.$refs.dropdown.hide();
+ this.$emit('move-issuable', this.selectedProject);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="block js-issuable-move-block issuable-move-dropdown sidebar-move-issue-dropdown">
+ <div
+ v-gl-tooltip.left.viewport
+ data-testid="move-collapsed"
+ :title="dropdownButtonTitle"
+ class="sidebar-collapsed-icon"
+ @click="$emit('toggle-collapse')"
+ >
+ <gl-icon name="arrow-right" />
+ </div>
+ <gl-dropdown
+ ref="dropdown"
+ :block="true"
+ :disabled="moveInProgress"
+ class="hide-collapsed"
+ toggle-class="js-sidebar-dropdown-toggle"
+ @shown="fetchProjects"
+ @hide="handleDropdownHide"
+ >
+ <template #button-content
+ ><gl-loading-icon v-if="moveInProgress" class="gl-mr-3" />{{
+ dropdownButtonTitle
+ }}</template
+ >
+ <gl-dropdown-form class="gl-pt-0">
+ <div
+ data-testid="header"
+ class="gl-display-flex gl-pb-3 gl-border-1 gl-border-b-solid gl-border-gray-100"
+ >
+ <span class="gl-flex-grow-1 gl-text-center gl-font-weight-bold gl-py-1">{{
+ dropdownHeaderTitle
+ }}</span>
+ <gl-button
+ variant="link"
+ icon="close"
+ class="gl-mr-2 gl-w-auto! gl-p-2!"
+ @click.prevent="handleDropdownCloseClick"
+ />
+ </div>
+ <gl-search-box-by-type
+ ref="searchInput"
+ v-model.trim="searchKey"
+ :placeholder="__('Search project')"
+ :debounce="300"
+ />
+ <div data-testid="content" class="dropdown-content">
+ <gl-loading-icon v-if="projectsListLoading" size="md" class="gl-p-5" />
+ <ul v-else>
+ <gl-dropdown-item
+ v-for="project in projects"
+ :key="project.id"
+ :is-check-item="true"
+ :is-checked="isSelectedProject(project)"
+ @click.stop.prevent="handleProjectSelect(project)"
+ >{{ project.name_with_namespace }}</gl-dropdown-item
+ >
+ </ul>
+ <div v-if="hasNoSearchResults" class="gl-text-center gl-p-3">
+ {{ __('No matching results') }}
+ </div>
+ <div v-if="failedToLoadResults" class="gl-text-center gl-p-3">
+ {{ __('Failed to load projects') }}
+ </div>
+ </div>
+ <div
+ data-testid="footer"
+ class="gl-pt-3 gl-px-3 gl-border-1 gl-border-t-solid gl-border-gray-100"
+ >
+ <gl-button
+ category="primary"
+ variant="success"
+ :disabled="!Boolean(selectedProject)"
+ class="gl-text-center! issuable-move-button"
+ @click="handleMoveClick"
+ >{{ __('Move') }}</gl-button
+ >
+ </div>
+ </gl-dropdown-form>
+ </gl-dropdown>
+ </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 c2ebf78d541..973cc314ee3 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,11 +1,10 @@
<script>
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
-import tooltip from '~/vue_shared/directives/tooltip';
export default {
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
components: {
GlIcon,
@@ -45,12 +44,9 @@ export default {
<template>
<div
- v-tooltip
+ v-gl-tooltip.left.viewport
:title="labelsList"
class="sidebar-collapsed-icon"
- data-placement="left"
- data-container="body"
- data-boundary="viewport"
@click="handleClick"
>
<gl-icon name="labels" />
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue
index 353dee862d0..a365673f7a1 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue
@@ -92,6 +92,13 @@ export default {
}
}
},
+ handleComponentAppear() {
+ // We can avoid putting `catch` block here
+ // as failure is handled within actions.js already.
+ return this.fetchLabels().then(() => {
+ this.$refs.searchInput.focusInput();
+ });
+ },
/**
* We want to remove loaded labels to ensure component
* fetches fresh set of labels every time when shown.
@@ -139,7 +146,7 @@ export default {
</script>
<template>
- <gl-intersection-observer @appear="fetchLabels" @disappear="handleComponentDisappear">
+ <gl-intersection-observer @appear="handleComponentAppear" @disappear="handleComponentDisappear">
<div class="labels-select-contents-list js-labels-list" @keydown="handleKeyDown">
<div
v-if="isDropdownVariantSidebar || isDropdownVariantEmbedded"
@@ -158,8 +165,8 @@ export default {
</div>
<div class="dropdown-input" @click.stop="() => {}">
<gl-search-box-by-type
+ ref="searchInput"
v-model="searchKey"
- :autofocus="true"
:disabled="labelsFetchInProgress"
data-qa-selector="dropdown_input_field"
/>
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..14b46c1c431 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
@@ -20,7 +20,7 @@ export const receiveLabelsFailure = ({ commit }) => {
};
export const fetchLabels = ({ state, dispatch }) => {
dispatch('requestLabels');
- axios
+ return axios
.get(state.labelsFetchPath)
.then(({ data }) => {
dispatch('receiveLabelsSuccess', data);
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue b/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue
new file mode 100644
index 00000000000..c5bbe1b33fb
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue
@@ -0,0 +1,29 @@
+<script>
+import { GlDropdown, GlDropdownForm } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlDropdownForm,
+ GlDropdown,
+ },
+ props: {
+ headerText: {
+ type: String,
+ required: true,
+ },
+ text: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown class="show" :text="text" :header-text="headerText">
+ <slot name="search"></slot>
+ <gl-dropdown-form>
+ <slot name="items"></slot>
+ </gl-dropdown-form>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql
new file mode 100644
index 00000000000..612a0c02e82
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql
@@ -0,0 +1,13 @@
+query issueParticipants($id: IssueID!) {
+ issue(id: $id) {
+ participants {
+ nodes {
+ username
+ name
+ webUrl
+ avatarUrl
+ id
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql
new file mode 100644
index 00000000000..9ead95a3801
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql
@@ -0,0 +1,17 @@
+mutation issueSetAssignees($iid: String!, $assigneeUsernames: [String!]!, $projectPath: ID!) {
+ issueSetAssignees(
+ input: { iid: $iid, assigneeUsernames: $assigneeUsernames, projectPath: $projectPath }
+ ) {
+ issue {
+ assignees {
+ nodes {
+ username
+ id
+ name
+ webUrl
+ avatarUrl
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue b/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue
index f2e9c4a4fbb..9b6d0a87374 100644
--- a/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue
+++ b/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue
@@ -1,7 +1,7 @@
<script>
import { GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
-import { roundOffFloat } from '~/lib/utils/common_utils';
+import { roundDownFloat } from '~/lib/utils/common_utils';
export default {
directives: {
@@ -89,7 +89,7 @@ export default {
return 0;
}
- const percent = roundOffFloat((count / this.totalCount) * 100, 1);
+ const percent = roundDownFloat((count / this.totalCount) * 100, 1);
if (percent > 0 && percent < 1) {
return '< 1';
}
diff --git a/app/assets/javascripts/vue_shared/components/upload_dropzone/constants.js b/app/assets/javascripts/vue_shared/components/upload_dropzone/constants.js
new file mode 100644
index 00000000000..85414704cb6
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/upload_dropzone/constants.js
@@ -0,0 +1,9 @@
+// We may wish to make this more restrictive, as per
+// https://gitlab.com/gitlab-org/gitlab/issues/118611
+export const VALID_IMAGE_FILE_MIMETYPE = {
+ mimetype: 'image/*',
+ regex: /image\/.+/,
+};
+
+// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/types
+export const VALID_DATA_TRANSFER_TYPE = 'Files';
diff --git a/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue b/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue
new file mode 100644
index 00000000000..b645758d891
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue
@@ -0,0 +1,172 @@
+<script>
+import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
+import { __ } from '~/locale';
+import { isValidImage } from './utils';
+import { VALID_DATA_TRANSFER_TYPE, VALID_IMAGE_FILE_MIMETYPE } from './constants';
+
+export default {
+ components: {
+ GlIcon,
+ GlLink,
+ GlSprintf,
+ },
+ props: {
+ displayAsCard: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ enableDragBehavior: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ dropToStartMessage: {
+ type: String,
+ required: false,
+ default: __('Drop your files to start your upload.'),
+ },
+ isFileValid: {
+ type: Function,
+ required: false,
+ default: isValidImage,
+ },
+ validFileMimetypes: {
+ type: Array,
+ required: false,
+ default: () => [VALID_IMAGE_FILE_MIMETYPE.mimetype],
+ },
+ },
+ data() {
+ return {
+ dragCounter: 0,
+ isDragDataValid: false,
+ };
+ },
+ computed: {
+ dragging() {
+ return this.dragCounter !== 0;
+ },
+ iconStyles() {
+ return {
+ size: this.displayAsCard ? 24 : 16,
+ class: this.displayAsCard ? 'gl-mb-2' : 'gl-mr-3 gl-text-gray-500',
+ };
+ },
+ validMimeTypeString() {
+ return this.validFileMimetypes.join();
+ },
+ },
+ methods: {
+ isValidUpload(files) {
+ return files.every(this.isFileValid);
+ },
+ 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))) {
+ this.$emit('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();
+ },
+ onFileInputChange(e) {
+ this.$emit('change', e.target.files);
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="gl-w-full gl-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 upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ @click="openFileUpload"
+ >
+ <div
+ :class="{ 'gl-flex-direction-column': displayAsCard }"
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center"
+ data-testid="dropzone-area"
+ >
+ <gl-icon name="upload" :size="iconStyles.size" :class="iconStyles.class" />
+ <p class="gl-mb-0">
+ <slot name="upload-text" :openFileUpload="openFileUpload">
+ <gl-sprintf :message="__('Drop or %{linkStart}upload%{linkEnd} files to attach')">
+ <template #link="{ content }">
+ <gl-link @click.stop="openFileUpload">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </slot>
+ </p>
+ </div>
+ </button>
+
+ <input
+ ref="fileUpload"
+ type="file"
+ name="upload_file"
+ :accept="validFileMimetypes"
+ class="hide"
+ multiple
+ @change="onFileInputChange"
+ />
+ </slot>
+ <transition name="upload-dropzone-fade">
+ <div
+ v-show="dragging && !enableDragBehavior"
+ class="card upload-dropzone-border upload-dropzone-overlay gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
+ >
+ <div v-show="!isDragDataValid" class="mw-50 gl-text-center">
+ <slot name="invalid-drag-data-slot">
+ <h3 :class="{ 'gl-font-base gl-display-inline': !displayAsCard }">
+ {{ __('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>
+ </slot>
+ </div>
+ <div v-show="isDragDataValid" class="mw-50 gl-text-center">
+ <slot name="valid-drag-data-slot">
+ <h3 :class="{ 'gl-font-base gl-display-inline': !displayAsCard }">
+ {{ __('Incoming!') }}
+ </h3>
+ <span>{{ dropToStartMessage }}</span>
+ </slot>
+ </div>
+ </div>
+ </transition>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/upload_dropzone/utils.js b/app/assets/javascripts/vue_shared/components/upload_dropzone/utils.js
new file mode 100644
index 00000000000..cf51a570d46
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/upload_dropzone/utils.js
@@ -0,0 +1,4 @@
+import { VALID_IMAGE_FILE_MIMETYPE } from './constants';
+
+export const isValidImage = ({ type }) =>
+ (type.match(VALID_IMAGE_FILE_MIMETYPE.regex) || []).length > 0;
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 3f5738b2b93..2ab4c55d9b0 100644
--- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
@@ -6,6 +6,7 @@ import {
GlDeprecatedSkeletonLoading as GlSkeletonLoading,
GlIcon,
} from '@gitlab/ui';
+import UserAvailabilityStatus from '~/set_status_modal/components/user_availability_status.vue';
import UserAvatarImage from '../user_avatar/user_avatar_image.vue';
import { glEmojiTag } from '../../../emoji';
@@ -25,6 +26,7 @@ export default {
GlPopover,
GlSkeletonLoading,
UserAvatarImage,
+ UserAvailabilityStatus,
},
props: {
target: {
@@ -63,6 +65,9 @@ export default {
websiteUrl.length
);
},
+ availabilityStatus() {
+ return this.user?.status?.availability || null;
+ },
},
};
</script>
@@ -89,6 +94,10 @@ export default {
<div class="gl-mb-3">
<h5 class="gl-m-0">
{{ user.name }}
+ <user-availability-status
+ v-if="availabilityStatus"
+ :availability="availabilityStatus"
+ />
</h5>
<span class="gl-text-gray-500">@{{ user.username }}</span>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/web_ide_link.vue b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
index 877414519f7..dbb1a075e76 100644
--- a/app/assets/javascripts/vue_shared/components/web_ide_link.vue
+++ b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
@@ -169,7 +169,7 @@ export default {
</script>
<template>
- <div class="d-inline-block gl-ml-3">
+ <div class="gl-sm-ml-3">
<actions-button
:actions="actions"
:selected-key="selection"
diff --git a/app/assets/javascripts/vue_shared/directives/validation.js b/app/assets/javascripts/vue_shared/directives/validation.js
new file mode 100644
index 00000000000..09bec78edcc
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/directives/validation.js
@@ -0,0 +1,132 @@
+import { merge } from 'lodash';
+import { s__ } from '~/locale';
+
+/**
+ * Validation messages will take priority based on the property order.
+ *
+ * For example:
+ * { valueMissing: {...}, urlTypeMismatch: {...} }
+ *
+ * `valueMissing` will be displayed the user has entered a value
+ * after that, if the input is not a valid URL then `urlTypeMismatch` will show
+ */
+const defaultFeedbackMap = {
+ valueMissing: {
+ isInvalid: el => el.validity?.valueMissing,
+ message: s__('Please fill out this field.'),
+ },
+ urlTypeMismatch: {
+ isInvalid: el => el.type === 'url' && el.validity?.typeMismatch,
+ message: s__('Please enter a valid URL format, ex: http://www.example.com/home'),
+ },
+};
+
+const getFeedbackForElement = (feedbackMap, el) =>
+ Object.values(feedbackMap).find(f => f.isInvalid(el))?.message || el.validationMessage;
+
+const focusFirstInvalidInput = e => {
+ const { target: formEl } = e;
+ const invalidInput = formEl.querySelector('input:invalid');
+
+ if (invalidInput) {
+ invalidInput.focus();
+ }
+};
+
+const isEveryFieldValid = form => Object.values(form.fields).every(({ state }) => state === true);
+
+const createValidator = (context, feedbackMap) => ({ el, reportInvalidInput = false }) => {
+ const { form } = context;
+ const { name } = el;
+
+ if (!name) {
+ if (process.env.NODE_ENV === 'development') {
+ // eslint-disable-next-line no-console
+ console.warn(
+ '[gitlab] the validation directive requires the given input to have "name" attribute',
+ );
+ }
+ return;
+ }
+
+ const formField = form.fields[name];
+ const isValid = el.checkValidity();
+
+ // This makes sure we always report valid fields - this can be useful for cases where the consuming
+ // component's logic depends on certain fields being in a valid state.
+ // Invalid input, on the other hand, should only be reported once we want to display feedback to the user.
+ // (eg.: After a field has been touched and moved away from, a submit-button has been clicked, ...)
+ formField.state = reportInvalidInput ? isValid : isValid || null;
+ formField.feedback = reportInvalidInput ? getFeedbackForElement(feedbackMap, el) : '';
+
+ form.state = isEveryFieldValid(form);
+};
+
+/**
+ * Takes an object that allows to add or change custom feedback messages.
+ *
+ * The passed in object will be merged with the built-in feedback
+ * so it is possible to override a built-in message.
+ *
+ * @example
+ * validate({
+ * tooLong: {
+ * check: el => el.validity.tooLong === true,
+ * message: 'Your custom feedback'
+ * }
+ * })
+ *
+ * @example
+ * validate({
+ * valueMissing: {
+ * message: 'Your custom feedback'
+ * }
+ * })
+ *
+ * @param {Object<string, { message: string, isValid: ?function}>} customFeedbackMap
+ * @returns {{ inserted: function, update: function }} validateDirective
+ */
+export default function(customFeedbackMap = {}) {
+ const feedbackMap = merge(defaultFeedbackMap, customFeedbackMap);
+ const elDataMap = new WeakMap();
+
+ return {
+ inserted(el, binding, { context }) {
+ const { arg: showGlobalValidation } = binding;
+ const { form: formEl } = el;
+
+ const validate = createValidator(context, feedbackMap);
+ const elData = { validate, isTouched: false, isBlurred: false };
+
+ elDataMap.set(el, elData);
+
+ el.addEventListener('input', function markAsTouched() {
+ elData.isTouched = true;
+ // once the element has been marked as touched we can stop listening on the 'input' event
+ el.removeEventListener('input', markAsTouched);
+ });
+
+ el.addEventListener('blur', function markAsBlurred({ target }) {
+ if (elData.isTouched) {
+ elData.isBlurred = true;
+ validate({ el: target, reportInvalidInput: true });
+ // this event handler can be removed, since the live-feedback in `update` takes over
+ el.removeEventListener('blur', markAsBlurred);
+ }
+ });
+
+ if (formEl) {
+ formEl.addEventListener('submit', focusFirstInvalidInput);
+ }
+
+ validate({ el, reportInvalidInput: showGlobalValidation });
+ },
+ update(el, binding) {
+ const { arg: showGlobalValidation } = binding;
+ const { validate, isTouched, isBlurred } = elDataMap.get(el);
+ const showValidationFeedback = showGlobalValidation || (isTouched && isBlurred);
+
+ validate({ el, reportInvalidInput: showValidationFeedback });
+ },
+ };
+}
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 c0fc055a01b..56da2637825 100644
--- a/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
+++ b/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
@@ -1,7 +1,6 @@
import { isEmpty } from 'lodash';
import { sprintf, __ } from '~/locale';
import { formatDate } from '~/lib/utils/datetime_utility';
-import tooltip from '~/vue_shared/directives/tooltip';
import timeagoMixin from '~/vue_shared/mixins/timeago';
const mixins = {
@@ -99,9 +98,6 @@ const mixins = {
default: () => ({}),
},
},
- directives: {
- tooltip,
- },
mixins: [timeagoMixin],
computed: {
hasState() {
diff --git a/app/assets/javascripts/vue_shared/security_reports/constants.js b/app/assets/javascripts/vue_shared/security_reports/constants.js
new file mode 100644
index 00000000000..2f87c4e7878
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/constants.js
@@ -0,0 +1,3 @@
+export const FEEDBACK_TYPE_DISMISSAL = 'dismissal';
+export const FEEDBACK_TYPE_ISSUE = 'issue';
+export const FEEDBACK_TYPE_MERGE_REQUEST = 'merge_request';
diff --git a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
index d5696e3c8cf..89253cc7116 100644
--- a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
+++ b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
@@ -3,6 +3,7 @@ import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
import ReportSection from '~/reports/components/report_section.vue';
import { status } from '~/reports/constants';
import { s__ } from '~/locale';
+import { normalizeHeaders, parseIntPagination } from '~/lib/utils/common_utils';
import Flash from '~/flash';
import Api from '~/api';
@@ -52,12 +53,27 @@ export default {
});
},
methods: {
- checkHasSecurityReports(reportTypes) {
- return Api.pipelineJobs(this.projectId, this.pipelineId).then(({ data: jobs }) =>
- jobs.some(({ artifacts = [] }) =>
+ async checkHasSecurityReports(reportTypes) {
+ let page = 1;
+ while (page) {
+ // eslint-disable-next-line no-await-in-loop
+ const { data: jobs, headers } = await Api.pipelineJobs(this.projectId, this.pipelineId, {
+ per_page: 100,
+ page,
+ });
+
+ const hasSecurityReports = jobs.some(({ artifacts = [] }) =>
artifacts.some(({ file_type }) => reportTypes.includes(file_type)),
- ),
- );
+ );
+
+ if (hasSecurityReports) {
+ return true;
+ }
+
+ page = parseIntPagination(normalizeHeaders(headers)).nextPage;
+ }
+
+ return false;
},
activatePipelinesTab() {
if (window.mrTabs) {
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js
new file mode 100644
index 00000000000..22a45341c51
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js
@@ -0,0 +1,24 @@
+import * as types from './mutation_types';
+import { fetchDiffData } from '../../utils';
+
+export const setDiffEndpoint = ({ commit }, path) => commit(types.SET_DIFF_ENDPOINT, path);
+
+export const requestDiff = ({ commit }) => commit(types.REQUEST_DIFF);
+
+export const receiveDiffSuccess = ({ commit }, response) =>
+ commit(types.RECEIVE_DIFF_SUCCESS, response);
+
+export const receiveDiffError = ({ commit }, response) =>
+ commit(types.RECEIVE_DIFF_ERROR, response);
+
+export const fetchDiff = ({ state, rootState, dispatch }) => {
+ dispatch('requestDiff');
+
+ return fetchDiffData(rootState, state.paths.diffEndpoint, 'sast')
+ .then(data => {
+ dispatch('receiveDiffSuccess', data);
+ })
+ .catch(() => {
+ dispatch('receiveDiffError');
+ });
+};
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js
new file mode 100644
index 00000000000..68c81bb4509
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js
@@ -0,0 +1,10 @@
+import state from './state';
+import mutations from './mutations';
+import * as actions from './actions';
+
+export default {
+ namespaced: true,
+ state,
+ mutations,
+ actions,
+};
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutation_types.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutation_types.js
new file mode 100644
index 00000000000..aacec0fb679
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutation_types.js
@@ -0,0 +1,4 @@
+export const RECEIVE_DIFF_SUCCESS = 'RECEIVE_DIFF_SUCCESS';
+export const RECEIVE_DIFF_ERROR = 'RECEIVE_DIFF_ERROR';
+export const REQUEST_DIFF = 'REQUEST_DIFF';
+export const SET_DIFF_ENDPOINT = 'SET_DIFF_ENDPOINT';
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js
new file mode 100644
index 00000000000..5f6153ca3b1
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js
@@ -0,0 +1,31 @@
+import Vue from 'vue';
+import * as types from './mutation_types';
+import { parseDiff } from '../../utils';
+
+export default {
+ [types.SET_DIFF_ENDPOINT](state, path) {
+ Vue.set(state.paths, 'diffEndpoint', path);
+ },
+
+ [types.REQUEST_DIFF](state) {
+ state.isLoading = true;
+ },
+
+ [types.RECEIVE_DIFF_SUCCESS](state, { diff, enrichData }) {
+ const { added, fixed, existing } = parseDiff(diff, enrichData);
+ const baseReportOutofDate = diff.base_report_out_of_date || false;
+ const hasBaseReport = Boolean(diff.base_report_created_at);
+
+ state.isLoading = false;
+ state.newIssues = added;
+ state.resolvedIssues = fixed;
+ state.allIssues = existing;
+ state.baseReportOutofDate = baseReportOutofDate;
+ state.hasBaseReport = hasBaseReport;
+ },
+
+ [types.RECEIVE_DIFF_ERROR](state) {
+ state.isLoading = false;
+ state.hasError = true;
+ },
+};
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/state.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/state.js
new file mode 100644
index 00000000000..e860e3af924
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/state.js
@@ -0,0 +1,16 @@
+export default () => ({
+ paths: {
+ head: null,
+ base: null,
+ diffEndpoint: null,
+ },
+
+ isLoading: false,
+ hasError: false,
+
+ newIssues: [],
+ resolvedIssues: [],
+ allIssues: [],
+ baseReportOutofDate: false,
+ hasBaseReport: false,
+});
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js
new file mode 100644
index 00000000000..c9da824613d
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js
@@ -0,0 +1,24 @@
+import { fetchDiffData } from '../../utils';
+import * as types from './mutation_types';
+
+export const setDiffEndpoint = ({ commit }, path) => commit(types.SET_DIFF_ENDPOINT, path);
+
+export const requestDiff = ({ commit }) => commit(types.REQUEST_DIFF);
+
+export const receiveDiffSuccess = ({ commit }, response) =>
+ commit(types.RECEIVE_DIFF_SUCCESS, response);
+
+export const receiveDiffError = ({ commit }, response) =>
+ commit(types.RECEIVE_DIFF_ERROR, response);
+
+export const fetchDiff = ({ state, rootState, dispatch }) => {
+ dispatch('requestDiff');
+
+ return fetchDiffData(rootState, state.paths.diffEndpoint, 'secret_detection')
+ .then(data => {
+ dispatch('receiveDiffSuccess', data);
+ })
+ .catch(() => {
+ dispatch('receiveDiffError');
+ });
+};
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js
new file mode 100644
index 00000000000..68c81bb4509
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js
@@ -0,0 +1,10 @@
+import state from './state';
+import mutations from './mutations';
+import * as actions from './actions';
+
+export default {
+ namespaced: true,
+ state,
+ mutations,
+ actions,
+};
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutation_types.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutation_types.js
new file mode 100644
index 00000000000..aacec0fb679
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutation_types.js
@@ -0,0 +1,4 @@
+export const RECEIVE_DIFF_SUCCESS = 'RECEIVE_DIFF_SUCCESS';
+export const RECEIVE_DIFF_ERROR = 'RECEIVE_DIFF_ERROR';
+export const REQUEST_DIFF = 'REQUEST_DIFF';
+export const SET_DIFF_ENDPOINT = 'SET_DIFF_ENDPOINT';
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutations.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutations.js
new file mode 100644
index 00000000000..ee943b0621c
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutations.js
@@ -0,0 +1,30 @@
+import { parseDiff } from '~/vue_shared/security_reports/store/utils';
+import * as types from './mutation_types';
+
+export default {
+ [types.SET_DIFF_ENDPOINT](state, path) {
+ state.paths.diffEndpoint = path;
+ },
+
+ [types.REQUEST_DIFF](state) {
+ state.isLoading = true;
+ },
+
+ [types.RECEIVE_DIFF_SUCCESS](state, { diff, enrichData }) {
+ const { added, fixed, existing } = parseDiff(diff, enrichData);
+ const baseReportOutofDate = diff.base_report_out_of_date || false;
+ const hasBaseReport = Boolean(diff.base_report_created_at);
+
+ state.isLoading = false;
+ state.newIssues = added;
+ state.resolvedIssues = fixed;
+ state.allIssues = existing;
+ state.baseReportOutofDate = baseReportOutofDate;
+ state.hasBaseReport = hasBaseReport;
+ },
+
+ [types.RECEIVE_DIFF_ERROR](state) {
+ state.isLoading = false;
+ state.hasError = true;
+ },
+};
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/state.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/state.js
new file mode 100644
index 00000000000..e860e3af924
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/state.js
@@ -0,0 +1,16 @@
+export default () => ({
+ paths: {
+ head: null,
+ base: null,
+ diffEndpoint: null,
+ },
+
+ isLoading: false,
+ hasError: false,
+
+ newIssues: [],
+ resolvedIssues: [],
+ allIssues: [],
+ baseReportOutofDate: false,
+ hasBaseReport: false,
+});
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/utils.js b/app/assets/javascripts/vue_shared/security_reports/store/utils.js
new file mode 100644
index 00000000000..6e50efae741
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/utils.js
@@ -0,0 +1,75 @@
+import pollUntilComplete from '~/lib/utils/poll_until_complete';
+import axios from '~/lib/utils/axios_utils';
+import {
+ FEEDBACK_TYPE_DISMISSAL,
+ FEEDBACK_TYPE_ISSUE,
+ FEEDBACK_TYPE_MERGE_REQUEST,
+} from '../constants';
+
+export const fetchDiffData = (state, endpoint, category) => {
+ const requests = [pollUntilComplete(endpoint)];
+
+ if (state.canReadVulnerabilityFeedback) {
+ requests.push(axios.get(state.vulnerabilityFeedbackPath, { params: { category } }));
+ }
+
+ return Promise.all(requests).then(([diffResponse, enrichResponse]) => ({
+ diff: diffResponse.data,
+ enrichData: enrichResponse?.data ?? [],
+ }));
+};
+
+/**
+ * Returns given vulnerability enriched with the corresponding
+ * feedback (`dismissal` or `issue` type)
+ * @param {Object} vulnerability
+ * @param {Array} feedback
+ */
+export const enrichVulnerabilityWithFeedback = (vulnerability, feedback = []) =>
+ feedback
+ .filter(fb => fb.project_fingerprint === vulnerability.project_fingerprint)
+ .reduce((vuln, fb) => {
+ if (fb.feedback_type === FEEDBACK_TYPE_DISMISSAL) {
+ return {
+ ...vuln,
+ isDismissed: true,
+ dismissalFeedback: fb,
+ };
+ }
+ if (fb.feedback_type === FEEDBACK_TYPE_ISSUE && fb.issue_iid) {
+ return {
+ ...vuln,
+ hasIssue: true,
+ issue_feedback: fb,
+ };
+ }
+ if (fb.feedback_type === FEEDBACK_TYPE_MERGE_REQUEST && fb.merge_request_iid) {
+ return {
+ ...vuln,
+ hasMergeRequest: true,
+ merge_request_feedback: fb,
+ };
+ }
+ return vuln;
+ }, vulnerability);
+
+/**
+ * Generates the added, fixed, and existing vulnerabilities from the API report.
+ *
+ * @param {Object} diff The original reports.
+ * @param {Object} enrichData Feedback data to add to the reports.
+ * @returns {Object}
+ */
+export const parseDiff = (diff, enrichData) => {
+ const enrichVulnerability = vulnerability => ({
+ ...enrichVulnerabilityWithFeedback(vulnerability, enrichData),
+ category: vulnerability.report_type,
+ title: vulnerability.message || vulnerability.name,
+ });
+
+ return {
+ added: diff.added ? diff.added.map(enrichVulnerability) : [],
+ fixed: diff.fixed ? diff.fixed.map(enrichVulnerability) : [],
+ existing: diff.existing ? diff.existing.map(enrichVulnerability) : [],
+ };
+};
diff --git a/app/assets/javascripts/vuex_shared/modules/members/actions.js b/app/assets/javascripts/vuex_shared/modules/members/actions.js
index f7fdddfd070..4c31b3c9744 100644
--- a/app/assets/javascripts/vuex_shared/modules/members/actions.js
+++ b/app/assets/javascripts/vuex_shared/modules/members/actions.js
@@ -1,5 +1,6 @@
import * as types from './mutation_types';
import axios from '~/lib/utils/axios_utils';
+import { formatDate } from '~/lib/utils/datetime_utility';
export const updateMemberRole = async ({ state, commit }, { memberId, accessLevel }) => {
try {
@@ -23,3 +24,21 @@ export const showRemoveGroupLinkModal = ({ commit }, groupLink) => {
export const hideRemoveGroupLinkModal = ({ commit }) => {
commit(types.HIDE_REMOVE_GROUP_LINK_MODAL);
};
+
+export const updateMemberExpiration = async ({ state, commit }, { memberId, expiresAt }) => {
+ try {
+ await axios.put(
+ state.memberPath.replace(':id', memberId),
+ state.requestFormatter({ expires_at: expiresAt ? formatDate(expiresAt, 'isoDate') : '' }),
+ );
+
+ commit(types.RECEIVE_MEMBER_EXPIRATION_SUCCESS, {
+ memberId,
+ expiresAt: expiresAt ? formatDate(expiresAt, 'isoUtcDateTime') : null,
+ });
+ } catch (error) {
+ commit(types.RECEIVE_MEMBER_EXPIRATION_ERROR);
+
+ throw error;
+ }
+};
diff --git a/app/assets/javascripts/vuex_shared/modules/members/index.js b/app/assets/javascripts/vuex_shared/modules/members/index.js
index 682e85298ad..586d52a5288 100644
--- a/app/assets/javascripts/vuex_shared/modules/members/index.js
+++ b/app/assets/javascripts/vuex_shared/modules/members/index.js
@@ -1,6 +1,6 @@
import createState from 'ee_else_ce/vuex_shared/modules/members/state';
-import * as actions from './actions';
-import mutations from './mutations';
+import mutations from 'ee_else_ce/vuex_shared/modules/members/mutations';
+import * as actions from 'ee_else_ce/vuex_shared/modules/members/actions';
export default initialState => ({
namespaced: true,
diff --git a/app/assets/javascripts/vuex_shared/modules/members/mutation_types.js b/app/assets/javascripts/vuex_shared/modules/members/mutation_types.js
index 00f4c910669..77307aa745b 100644
--- a/app/assets/javascripts/vuex_shared/modules/members/mutation_types.js
+++ b/app/assets/javascripts/vuex_shared/modules/members/mutation_types.js
@@ -1,6 +1,9 @@
export const RECEIVE_MEMBER_ROLE_SUCCESS = 'RECEIVE_MEMBER_ROLE_SUCCESS';
export const RECEIVE_MEMBER_ROLE_ERROR = 'RECEIVE_MEMBER_ROLE_ERROR';
+export const RECEIVE_MEMBER_EXPIRATION_SUCCESS = 'RECEIVE_MEMBER_EXPIRATION_SUCCESS';
+export const RECEIVE_MEMBER_EXPIRATION_ERROR = 'RECEIVE_MEMBER_EXPIRATION_ERROR';
+
export const HIDE_ERROR = 'HIDE_ERROR';
export const SHOW_REMOVE_GROUP_LINK_MODAL = 'SHOW_REMOVE_GROUP_LINK_MODAL';
diff --git a/app/assets/javascripts/vuex_shared/modules/members/mutations.js b/app/assets/javascripts/vuex_shared/modules/members/mutations.js
index 281c947e68f..2415e744290 100644
--- a/app/assets/javascripts/vuex_shared/modules/members/mutations.js
+++ b/app/assets/javascripts/vuex_shared/modules/members/mutations.js
@@ -19,6 +19,21 @@ export default {
);
state.showError = true;
},
+ [types.RECEIVE_MEMBER_EXPIRATION_SUCCESS](state, { memberId, expiresAt }) {
+ const member = findMember(state, memberId);
+
+ if (!member) {
+ return;
+ }
+
+ Vue.set(member, 'expiresAt', expiresAt);
+ },
+ [types.RECEIVE_MEMBER_EXPIRATION_ERROR](state) {
+ state.errorMessage = s__(
+ "Members|An error occurred while updating the member's expiration date, please try again.",
+ );
+ state.showError = true;
+ },
[types.HIDE_ERROR](state) {
state.showError = false;
state.errorMessage = '';
diff --git a/app/assets/javascripts/vuex_shared/modules/members/state.js b/app/assets/javascripts/vuex_shared/modules/members/state.js
index e4867819e17..ab3ebb34616 100644
--- a/app/assets/javascripts/vuex_shared/modules/members/state.js
+++ b/app/assets/javascripts/vuex_shared/modules/members/state.js
@@ -3,6 +3,7 @@ export default ({
sourceId,
currentUserId,
tableFields,
+ tableAttrs,
memberPath,
requestFormatter,
}) => ({
@@ -10,6 +11,7 @@ export default ({
sourceId,
currentUserId,
tableFields,
+ tableAttrs,
memberPath,
requestFormatter,
showError: false,
diff --git a/app/assets/javascripts/whats_new/components/app.vue b/app/assets/javascripts/whats_new/components/app.vue
index 9400dacedc2..3c1de57252a 100644
--- a/app/assets/javascripts/whats_new/components/app.vue
+++ b/app/assets/javascripts/whats_new/components/app.vue
@@ -1,8 +1,16 @@
<script>
import { mapState, mapActions } from 'vuex';
-import { GlDrawer, GlBadge, GlIcon, GlLink } from '@gitlab/ui';
+import {
+ GlDrawer,
+ GlBadge,
+ GlIcon,
+ GlLink,
+ GlInfiniteScroll,
+ GlResizeObserverDirective,
+} from '@gitlab/ui';
import SkeletonLoader from './skeleton_loader.vue';
import Tracking from '~/tracking';
+import { getDrawerBodyHeight } from '../utils/get_drawer_body_height';
const trackingMixin = Tracking.mixin();
@@ -12,8 +20,12 @@ export default {
GlBadge,
GlIcon,
GlLink,
+ GlInfiniteScroll,
SkeletonLoader,
},
+ directives: {
+ GlResizeObserver: GlResizeObserverDirective,
+ },
mixins: [trackingMixin],
props: {
storageKey: {
@@ -23,7 +35,7 @@ export default {
},
},
computed: {
- ...mapState(['open', 'features']),
+ ...mapState(['open', 'features', 'pageInfo', 'drawerBodyHeight']),
},
mounted() {
this.openDrawer(this.storageKey);
@@ -35,36 +47,64 @@ export default {
this.track('click_whats_new_drawer', { label: 'namespace_id', value: namespaceId });
},
methods: {
- ...mapActions(['openDrawer', 'closeDrawer', 'fetchItems']),
+ ...mapActions(['openDrawer', 'closeDrawer', 'fetchItems', 'setDrawerBodyHeight']),
+ bottomReached() {
+ if (this.pageInfo.nextPage) {
+ this.fetchItems(this.pageInfo.nextPage);
+ }
+ },
+ handleResize() {
+ const height = getDrawerBodyHeight(this.$refs.drawer.$el);
+ this.setDrawerBodyHeight(height);
+ },
},
};
</script>
<template>
<div>
- <gl-drawer class="whats-new-drawer" :open="open" @close="closeDrawer">
+ <gl-drawer
+ ref="drawer"
+ v-gl-resize-observer="handleResize"
+ class="whats-new-drawer"
+ :open="open"
+ @close="closeDrawer"
+ >
<template #header>
- <h4 class="page-title my-2">{{ __("What's new at GitLab") }}</h4>
+ <h4 class="page-title gl-my-2">{{ __("What's new at GitLab") }}</h4>
</template>
- <div class="pb-6">
- <template v-if="features">
- <div v-for="feature in features" :key="feature.title" class="mb-6">
+ <gl-infinite-scroll
+ v-if="features.length"
+ :fetched-items="features.length"
+ :max-list-height="drawerBodyHeight"
+ class="gl-p-0"
+ @bottomReached="bottomReached"
+ >
+ <template #items>
+ <div
+ v-for="feature in features"
+ :key="feature.title"
+ class="gl-pb-7 gl-pt-5 gl-px-5 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100"
+ >
<gl-link
:href="feature.url"
target="_blank"
- data-testid="whats-new-title-link"
+ class="whats-new-item-title-link"
data-track-event="click_whats_new_item"
:data-track-label="feature.title"
:data-track-property="feature.url"
>
- <h5 class="gl-font-base">{{ feature.title }}</h5>
+ <h5 class="gl-font-lg">{{ feature.title }}</h5>
</gl-link>
<div v-if="feature.packages" class="gl-mb-3">
- <template v-for="package_name in feature.packages">
- <gl-badge :key="package_name" size="sm" class="whats-new-item-badge gl-mr-2">
- <gl-icon name="license" />{{ package_name }}
- </gl-badge>
- </template>
+ <gl-badge
+ v-for="package_name in feature.packages"
+ :key="package_name"
+ size="sm"
+ class="whats-new-item-badge gl-mr-2"
+ >
+ <gl-icon name="license" />{{ package_name }}
+ </gl-badge>
</div>
<gl-link
:href="feature.url"
@@ -76,7 +116,7 @@ export default {
<img
:alt="feature.title"
:src="feature.image_url"
- class="img-thumbnail px-6 gl-py-3 whats-new-item-image"
+ class="img-thumbnail gl-px-8 gl-py-3 whats-new-item-image"
/>
</gl-link>
<p class="gl-pt-3">{{ feature.body }}</p>
@@ -90,10 +130,10 @@ export default {
>
</div>
</template>
- <div v-else class="gl-mt-5">
- <skeleton-loader />
- <skeleton-loader />
- </div>
+ </gl-infinite-scroll>
+ <div v-else class="gl-mt-5">
+ <skeleton-loader />
+ <skeleton-loader />
</div>
</gl-drawer>
<div v-if="open" class="whats-new-modal-backdrop modal-backdrop"></div>
diff --git a/app/assets/javascripts/whats_new/store/actions.js b/app/assets/javascripts/whats_new/store/actions.js
index a84dfb399d8..532febd61cb 100644
--- a/app/assets/javascripts/whats_new/store/actions.js
+++ b/app/assets/javascripts/whats_new/store/actions.js
@@ -1,5 +1,6 @@
import * as types from './mutation_types';
import axios from '~/lib/utils/axios_utils';
+import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
export default {
closeDrawer({ commit }) {
@@ -12,9 +13,33 @@ export default {
localStorage.setItem(storageKey, JSON.stringify(false));
}
},
- fetchItems({ commit }) {
- return axios.get('/-/whats_new').then(({ data }) => {
- commit(types.SET_FEATURES, data);
- });
+ fetchItems({ commit, state }, page) {
+ if (state.fetching) {
+ return false;
+ }
+
+ commit(types.SET_FETCHING, true);
+
+ return axios
+ .get('/-/whats_new', {
+ params: {
+ page,
+ },
+ })
+ .then(({ data, headers }) => {
+ commit(types.ADD_FEATURES, data);
+
+ const normalizedHeaders = normalizeHeaders(headers);
+ const { nextPage } = parseIntPagination(normalizedHeaders);
+ commit(types.SET_PAGE_INFO, {
+ nextPage,
+ });
+ })
+ .finally(() => {
+ commit(types.SET_FETCHING, false);
+ });
+ },
+ setDrawerBodyHeight({ commit }, height) {
+ commit(types.SET_DRAWER_BODY_HEIGHT, height);
},
};
diff --git a/app/assets/javascripts/whats_new/store/mutation_types.js b/app/assets/javascripts/whats_new/store/mutation_types.js
index 124d33a88b1..5715c442f66 100644
--- a/app/assets/javascripts/whats_new/store/mutation_types.js
+++ b/app/assets/javascripts/whats_new/store/mutation_types.js
@@ -1,3 +1,6 @@
export const CLOSE_DRAWER = 'CLOSE_DRAWER';
export const OPEN_DRAWER = 'OPEN_DRAWER';
-export const SET_FEATURES = 'SET_FEATURES';
+export const ADD_FEATURES = 'ADD_FEATURES';
+export const SET_PAGE_INFO = 'SET_PAGE_INFO';
+export const SET_FETCHING = 'SET_FETCHING';
+export const SET_DRAWER_BODY_HEIGHT = 'SET_DRAWER_BODY_HEIGHT';
diff --git a/app/assets/javascripts/whats_new/store/mutations.js b/app/assets/javascripts/whats_new/store/mutations.js
index 4fb7b17244e..725521780dc 100644
--- a/app/assets/javascripts/whats_new/store/mutations.js
+++ b/app/assets/javascripts/whats_new/store/mutations.js
@@ -7,7 +7,16 @@ export default {
[types.OPEN_DRAWER](state) {
state.open = true;
},
- [types.SET_FEATURES](state, data) {
- state.features = data;
+ [types.ADD_FEATURES](state, data) {
+ state.features = state.features.concat(data);
+ },
+ [types.SET_PAGE_INFO](state, pageInfo) {
+ state.pageInfo = pageInfo;
+ },
+ [types.SET_FETCHING](state, fetching) {
+ state.fetching = fetching;
+ },
+ [types.SET_DRAWER_BODY_HEIGHT](state, height) {
+ state.drawerBodyHeight = height;
},
};
diff --git a/app/assets/javascripts/whats_new/store/state.js b/app/assets/javascripts/whats_new/store/state.js
index 4c76284b865..793c6aa2b98 100644
--- a/app/assets/javascripts/whats_new/store/state.js
+++ b/app/assets/javascripts/whats_new/store/state.js
@@ -1,4 +1,9 @@
export default {
open: false,
- features: null,
+ features: [],
+ fetching: false,
+ drawerBodyHeight: null,
+ pageInfo: {
+ nextPage: null,
+ },
};
diff --git a/app/assets/javascripts/whats_new/utils/get_drawer_body_height.js b/app/assets/javascripts/whats_new/utils/get_drawer_body_height.js
new file mode 100644
index 00000000000..21fc90c34a4
--- /dev/null
+++ b/app/assets/javascripts/whats_new/utils/get_drawer_body_height.js
@@ -0,0 +1,6 @@
+export const getDrawerBodyHeight = drawer => {
+ const drawerViewableHeight = drawer.clientHeight - drawer.getBoundingClientRect().top;
+ const drawerHeaderHeight = drawer.querySelector('.gl-drawer-header').clientHeight;
+
+ return drawerViewableHeight - drawerHeaderHeight;
+};
diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss
index a31cb0b0485..52bc19fddd9 100644
--- a/app/assets/stylesheets/_page_specific_files.scss
+++ b/app/assets/stylesheets/_page_specific_files.scss
@@ -1,8 +1,5 @@
@import './pages/admin';
-@import './pages/alert_management/details';
-@import './pages/alert_management/severity-icons';
@import './pages/branches';
-@import './pages/builds';
@import './pages/ci_projects';
@import './pages/clusters';
@import './pages/commits';
@@ -27,7 +24,6 @@
@import './pages/notes';
@import './pages/notifications';
@import './pages/pages';
-@import './pages/pipeline_schedules';
@import './pages/pipelines';
@import './pages/profile';
@import './pages/profiles/preferences';
@@ -39,7 +35,6 @@
@import './pages/settings';
@import './pages/settings_ci_cd';
@import './pages/sherlock';
-@import './pages/status';
@import './pages/storage_quota';
@import './pages/tree';
@import './pages/trials';
diff --git a/app/assets/stylesheets/behaviors.scss b/app/assets/stylesheets/behaviors.scss
index 120a139ff3d..bcfa5bac5d5 100644
--- a/app/assets/stylesheets/behaviors.scss
+++ b/app/assets/stylesheets/behaviors.scss
@@ -1,28 +1,3 @@
-// Details
-//--------
-.js-details-container {
- .content {
- display: none;
- &.hide { display: block; }
- }
-
- &.open .content {
- display: block;
- &.hide { display: none; }
- }
-}
-
-// Toggle between two states.
-.js-toggler-container {
- .turn-on { display: block; }
- .turn-off { display: none; }
-
- &.on {
- .turn-on { display: none; }
- .turn-off { display: block; }
- }
-}
-
// Hide element if Vue is still working on rendering it fully.
[v-cloak='true'] {
display: none !important;
diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss
index aac32e7fb2d..3d5076f485c 100644
--- a/app/assets/stylesheets/bootstrap_migration.scss
+++ b/app/assets/stylesheets/bootstrap_migration.scss
@@ -115,14 +115,10 @@ code {
background-color: $gray-50;
border-radius: $border-radius-default;
- .code > & {
- background-color: inherit;
- padding: unset;
- }
-
+ .code > &,
.build-trace & {
background-color: inherit;
- padding: inherit;
+ padding: unset;
}
}
@@ -131,12 +127,6 @@ table {
border-spacing: 0;
}
-.tooltip,
-.no-pointer-events {
- // Fix bootstrap4 bug whereby tooltips flicker when they are hovered over their borders
- pointer-events: none;
-}
-
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
diff --git a/app/assets/stylesheets/components/design_management/design.scss b/app/assets/stylesheets/components/design_management/design.scss
index 81f2091e915..579a86a94a4 100644
--- a/app/assets/stylesheets/components/design_management/design.scss
+++ b/app/assets/stylesheets/components/design_management/design.scss
@@ -75,10 +75,6 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
left: 0;
}
-.design-scaler {
- z-index: 1;
-}
-
.design-scaler-wrapper {
bottom: 0;
left: 50%;
@@ -185,41 +181,3 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
.design-card-header {
background: transparent;
}
-
-.design-dropzone-border {
- border: 2px dashed $gray-100;
-}
-
-.design-dropzone-card {
- transition: border $gl-transition-duration-medium $general-hover-transition-curve;
- color: $gl-text-color;
-
- &:focus,
- &:active {
- outline: none;
- border: 2px dashed $purple;
- color: $gl-text-color;
- }
-
- &:hover {
- border-color: $gray-300;
- }
-}
-
-.design-dropzone-overlay {
- border: 2px dashed $purple;
- top: 0;
- left: 0;
- pointer-events: none;
- opacity: 1;
-}
-
-.design-dropzone-fade-enter-active,
-.design-dropzone-fade-leave-active {
- transition: opacity $general-hover-transition-duration $general-hover-transition-curve;
-}
-
-.design-dropzone-fade-enter,
-.design-dropzone-fade-leave-to {
- opacity: 0;
-}
diff --git a/app/assets/stylesheets/components/severity/icons.scss b/app/assets/stylesheets/components/severity/icons.scss
new file mode 100644
index 00000000000..8ddf873196a
--- /dev/null
+++ b/app/assets/stylesheets/components/severity/icons.scss
@@ -0,0 +1,27 @@
+.incident-severity,
+.incident-management-list,
+.alert-management-details {
+ .icon-critical {
+ @include gl-text-red-800;
+ }
+
+ .icon-high {
+ @include gl-text-red-600;
+ }
+
+ .icon-medium {
+ @include gl-text-orange-400;
+ }
+
+ .icon-low {
+ @include gl-text-orange-300;
+ }
+
+ .icon-info {
+ @include gl-text-blue-400;
+ }
+
+ .icon-unknown {
+ @include gl-text-gray-200;
+ }
+}
diff --git a/app/assets/stylesheets/components/upload_dropzone/upload_dropzone.scss b/app/assets/stylesheets/components/upload_dropzone/upload_dropzone.scss
new file mode 100644
index 00000000000..2bc6eba3342
--- /dev/null
+++ b/app/assets/stylesheets/components/upload_dropzone/upload_dropzone.scss
@@ -0,0 +1,37 @@
+.upload-dropzone-border {
+ border: 2px dashed $gray-100;
+}
+
+.upload-dropzone-card {
+ transition: border $gl-transition-duration-medium $general-hover-transition-curve;
+ color: $gl-text-color;
+
+ &:focus,
+ &:active {
+ outline: none;
+ border: 2px dashed $purple;
+ color: $gl-text-color;
+ }
+
+ &:hover {
+ border-color: $gray-300;
+ }
+}
+
+.upload-dropzone-overlay {
+ border: 2px dashed $purple;
+ top: 0;
+ left: 0;
+ pointer-events: none;
+ opacity: 1;
+}
+
+.upload-dropzone-fade-enter-active,
+.upload-dropzone-fade-leave-active {
+ transition: opacity $general-hover-transition-duration $general-hover-transition-curve;
+}
+
+.upload-dropzone-fade-enter,
+.upload-dropzone-fade-leave-to {
+ opacity: 0;
+}
diff --git a/app/assets/stylesheets/components/whats_new.scss b/app/assets/stylesheets/components/whats_new.scss
index 6c58346b750..64e82531c30 100644
--- a/app/assets/stylesheets/components/whats_new.scss
+++ b/app/assets/stylesheets/components/whats_new.scss
@@ -1,6 +1,11 @@
.whats-new-drawer {
margin-top: $header-height;
@include gl-shadow-none;
+ overflow-y: hidden;
+
+ .gl-infinite-scroll-legend {
+ @include gl-display-none;
+ }
}
.with-performance-bar .whats-new-drawer {
@@ -13,6 +18,14 @@
@include gl-font-weight-bold;
}
+.whats-new-item-title-link {
+ &:hover,
+ &:focus,
+ &:active {
+ @include gl-text-gray-900;
+ }
+}
+
.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 a3338ff13b5..8a955cffc49 100644
--- a/app/assets/stylesheets/fontawesome_custom.scss
+++ b/app/assets/stylesheets/fontawesome_custom.scss
@@ -92,55 +92,23 @@
content: '\f0d7';
}
-.fa-check::before {
- content: '\f00c';
-}
-
.fa-warning::before,
.fa-exclamation-triangle::before {
content: '\f071';
}
-.fa-external-link::before {
- content: '\f08e';
-}
-
.fa-spinner::before {
content: '\f110';
}
-.fa-trash-o::before {
- content: '\f014';
-}
-
.fa-caret-right::before {
content: '\f0da';
}
-.fa-refresh::before {
- content: '\f021';
-}
-
-.fa-chevron-up::before {
- content: '\f077';
-}
-
-.fa-paperclip::before {
- content: '\f0c6';
-}
-
-.fa-bug::before {
- content: '\f188';
-}
-
.fa-exclamation-circle::before {
content: '\f06a';
}
-.fa-bell::before {
- content: '\f0f3';
-}
-
.fa-file-o::before {
content: '\f016';
}
@@ -153,10 +121,6 @@
content: '\f111';
}
-.fa-git::before {
- content: '\f1d3';
-}
-
.fa-thumb-tack::before {
content: '\f08d';
}
@@ -165,38 +129,6 @@
content: '\f06d';
}
-.fa-pause::before {
- content: '\f04c';
-}
-
-.fa-play::before {
- content: '\f04b';
-}
-
-.fa-share::before {
- content: '\f064';
-}
-
-.fa-book::before {
- content: '\f02d';
-}
-
-.fa-times-circle::before {
- content: '\f057';
-}
-
-.fa-skype::before {
- content: '\f17e';
-}
-
-.fa-linkedin-square::before {
- content: '\f08c';
-}
-
-.fa-twitter-square::before {
- content: '\f081';
-}
-
.fa-file-pdf-o::before {
content: '\f1c1';
}
@@ -229,6 +161,14 @@
content: '\f1c8';
}
+.fa-square-o::before {
+ content: '\f096';
+}
+
+.fa-check-square-o::before {
+ content: '\f046';
+}
+
.sr-only {
position: absolute;
width: 1px;
diff --git a/app/assets/stylesheets/framework/broadcast_messages.scss b/app/assets/stylesheets/framework/broadcast_messages.scss
index c1647c16c77..b8934d2797a 100644
--- a/app/assets/stylesheets/framework/broadcast_messages.scss
+++ b/app/assets/stylesheets/framework/broadcast_messages.scss
@@ -15,10 +15,6 @@
.broadcast-banner-message {
text-align: center;
-
- .broadcast-message-dismiss {
- color: inherit;
- }
}
.broadcast-notification-message {
@@ -36,10 +32,6 @@
&.preview {
position: static;
}
-
- .broadcast-message-dismiss {
- color: $gray-700;
- }
}
.toggle-colors {
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index de767ac3fe0..5b7f1a3f38b 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -14,14 +14,11 @@
.str-truncated {
max-width: 70%;
}
-
- .user-calendar-activities-loading {
- font-size: 24px;
- }
}
.user-calendar {
text-align: center;
+ min-height: 172px;
.calendar {
display: inline-block;
@@ -42,12 +39,9 @@
.calendar-hint {
font-size: 12px;
-
- &.bottom-right {
- direction: ltr;
- margin-top: -23px;
- float: right;
- }
+ direction: ltr;
+ margin-top: -23px;
+ float: right;
}
.pika-single.gitlab-theme {
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 8dbed9c03f2..deb2d6c4641 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -424,7 +424,6 @@ img.emoji {
.w-15p { width: 15%; }
.w-30p { width: 30%; }
.w-60p { width: 60%; }
-.w-70p { width: 70%; }
.h-12em { height: 12em; }
.h-32-px { height: 32px;}
diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss
index c0a2350d080..e16ab5ee72f 100644
--- a/app/assets/stylesheets/framework/diffs.scss
+++ b/app/assets/stylesheets/framework/diffs.scss
@@ -6,11 +6,18 @@
border-top: 1px solid $border-color;
}
+ &.has-body {
+ .file-title {
+ box-shadow: 0 -2px 0 0 var(--white);
+ }
+ }
+
+ table.code tr:last-of-type td:last-of-type {
+ @include gl-rounded-bottom-right-base();
+ }
+
.file-title,
.file-title-flex-parent {
- border-top-left-radius: $border-radius-default;
- border-top-right-radius: $border-radius-default;
- box-shadow: 0 -2px 0 0 var(--white);
cursor: pointer;
.dropdown-menu {
@@ -113,7 +120,6 @@
.diff-content {
background: $white;
color: $gl-text-color;
- border-radius: 0 0 3px 3px;
.unfold {
cursor: pointer;
@@ -443,6 +449,7 @@
}
}
+.diff-table.code,
table.code {
width: 100%;
font-family: $monospace-font;
@@ -453,14 +460,20 @@ table.code {
table-layout: fixed;
border-radius: 0 0 $border-radius-default $border-radius-default;
+ .diff-tr:first-of-type.line_expansion > .diff-td,
tr:first-of-type.line_expansion > td {
border-top: 0;
}
- tr:nth-last-of-type(2).line_expansion > td {
- border-bottom: 0;
+ .diff-tr:nth-last-of-type(2).line_expansion > .diff-td,
+ tr:nth-last-of-type(2).line_expansion,
+ tr:last-of-type.line_expansion {
+ > td {
+ border-bottom: 0;
+ }
}
+ .diff-tr.line_holder .diff-td,
tr.line_holder td {
line-height: $code-line-height;
font-size: $code-font-size;
@@ -556,24 +569,95 @@ table.code {
}
.line_holder:last-of-type {
+ .diff-td:first-child,
td:first-child {
border-bottom-left-radius: $border-radius-default;
}
}
&.left-side-selected {
+ .diff-td.line_content.parallel.right-side,
td.line_content.parallel.right-side {
user-select: none;
}
}
&.right-side-selected {
+ .diff-td.line_content.parallel.left-side,
td.line_content.parallel.left-side {
user-select: none;
}
}
}
+// Merge request diff grid layout
+.diff-grid {
+ .diff-grid-row {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ }
+
+ .diff-grid-left,
+ .diff-grid-right {
+ display: grid;
+ grid-template-columns: 50px 8px 1fr;
+
+ .diff-td:nth-child(2) {
+ display: none;
+ }
+ }
+
+ .diff-grid-comments {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ }
+
+ .diff-grid-drafts {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ }
+
+ &.inline {
+ .diff-grid-comments {
+ display: grid;
+ grid-template-columns: 1fr;
+ }
+
+ .diff-grid-drafts {
+ display: grid;
+ grid-template-columns: 1fr;
+ }
+
+ .diff-grid-row {
+ grid-template-columns: 1fr;
+ }
+
+ .diff-grid-left,
+ .diff-grid-right {
+ grid-template-columns: 50px 50px 8px 1fr;
+
+ .diff-td:nth-child(2) {
+ display: block;
+ }
+ }
+
+ .diff-grid-left .old:nth-child(1) [data-linenumber],
+ .diff-grid-right .new:nth-child(2) [data-linenumber] {
+ display: inline;
+ }
+
+ .diff-grid-left .old:nth-child(2) [data-linenumber],
+ .diff-grid-right .new:nth-child(1) [data-linenumber] {
+ display: none;
+ }
+ }
+}
+
+// Merge request diff grid layout overrides
+.diff-table.code .diff-tr.line_holder .diff-td.line_content.parallel {
+ width: unset;
+}
+
.diff-stats {
align-items: center;
padding: 0 1rem;
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index ca20b18f851..2094c824286 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -407,7 +407,8 @@
}
}
- &.droplab-item-selected i {
+ &.droplab-item-selected i,
+ &.droplab-item-selected svg {
visibility: visible;
}
diff --git a/app/assets/stylesheets/framework/editor-lite.scss b/app/assets/stylesheets/framework/editor-lite.scss
index 20fea7a82ca..c3b287a6c3d 100644
--- a/app/assets/stylesheets/framework/editor-lite.scss
+++ b/app/assets/stylesheets/framework/editor-lite.scss
@@ -1,3 +1,21 @@
+[data-editor-loading] {
+ @include gl-relative;
+ @include gl-display-flex;
+ @include gl-justify-content-center;
+ @include gl-align-items-center;
+
+ &::before {
+ content: '';
+ @include spinner(32px, 3px);
+ @include gl-absolute;
+ @include gl-z-index-1;
+ }
+
+ pre {
+ opacity: 0;
+ }
+}
+
[id^='editor-lite-'] {
height: 500px;
}
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index f8710cc1346..fe8c27ae9b6 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -45,11 +45,6 @@
}
.file-actions {
- position: absolute;
- top: 5px;
- right: 15px;
- margin-left: auto;
-
.btn:not(.btn-icon) {
padding: 0 10px;
font-size: 13px;
@@ -342,30 +337,14 @@ span.idiff {
padding: $gl-padding-8 $gl-padding;
margin: 0;
border-radius: $border-radius-default $border-radius-default 0 0;
- }
-
- .file-header-content {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- padding-right: 30px;
- position: relative;
- width: auto;
-
- @media (max-width: map-get($grid-breakpoints, sm)-1) {
- width: 100%;
- }
- }
- .file-holder & {
- .file-actions {
- position: static;
+ @include media-breakpoint-up(md) {
+ flex-wrap: nowrap;
}
}
- .btn-clipboard {
- position: absolute;
- right: 0;
+ .file-header-content {
+ padding-right: 30px;
}
a {
@@ -384,15 +363,11 @@ span.idiff {
z-index: 2;
}
- @include media-breakpoint-down(xs) {
+ @include media-breakpoint-down(sm) {
display: block;
.file-actions {
- white-space: normal;
-
- .btn-group {
- padding-top: 5px;
- }
+ margin-top: 5px;
}
}
}
diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss
index 0fb91db0afb..d5f7ec68454 100644
--- a/app/assets/stylesheets/framework/flash.scss
+++ b/app/assets/stylesheets/framework/flash.scss
@@ -9,9 +9,15 @@ $notification-box-shadow-color: rgba(0, 0, 0, 0.25);
&.sticky {
position: sticky;
- position: -webkit-sticky;
top: $flash-container-top;
z-index: 251;
+
+ .flash-alert,
+ .flash-notice,
+ .flash-success,
+ .flash-warning {
+ @include gl-mb-4;
+ }
}
&.flash-container-page {
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 63be2bdef8e..20d44b71bf6 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -3,6 +3,38 @@
* Mixins with fixed values
*/
+@keyframes blinking-dot {
+ 0% {
+ opacity: 1;
+ }
+
+ 25% {
+ opacity: 0.4;
+ }
+
+ 75% {
+ opacity: 0.4;
+ }
+
+ 100% {
+ opacity: 1;
+ }
+}
+
+@keyframes blinking-scroll-button {
+ 0% {
+ opacity: 0.2;
+ }
+
+ 50% {
+ opacity: 1;
+ }
+
+ 100% {
+ opacity: 0.2;
+ }
+}
+
@mixin str-truncated($max-width: 82%) {
display: inline-block;
overflow: hidden;
diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss
index f8c46a4495e..372e3bed6e0 100644
--- a/app/assets/stylesheets/framework/modal.scss
+++ b/app/assets/stylesheets/framework/modal.scss
@@ -117,12 +117,6 @@ body.modal-open {
border-bottom-right-radius: $modal-border-radius;
}
}
-
- @include media-breakpoint-up(sm) {
- .modal-dialog {
- margin: 64px auto;
- }
- }
}
.recaptcha-modal .recaptcha-form {
@@ -134,7 +128,7 @@ body.modal-open {
}
.issues-import-modal,
-.issues-export-modal {
+.issuable-export-modal {
.modal-header {
justify-content: flex-start;
@@ -166,8 +160,4 @@ body.modal-open {
min-height: $modal-body-height;
}
}
-
- .checkmark {
- color: $green-400;
- }
}
diff --git a/app/assets/stylesheets/framework/secondary_navigation_elements.scss b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
index 7ebc972ac37..3e218de6af9 100644
--- a/app/assets/stylesheets/framework/secondary_navigation_elements.scss
+++ b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
@@ -69,7 +69,7 @@
line-height: 28px;
white-space: normal;
- /* Small devices (phones, tablets, 768px and lower) */
+ /* Small devices (phones, 768px and lower) */
@include media-breakpoint-down(xs) {
width: 100%;
}
@@ -92,7 +92,7 @@
padding: 16px 15px 11px;
}
- /* Small devices (phones, tablets, 768px and lower) */
+ /* Small devices (phones, 768px and lower) */
@include media-breakpoint-down(sm) {
width: 100%;
}
@@ -102,15 +102,6 @@
display: inline-block;
text-align: right;
- @include media-breakpoint-down(sm) {
- margin-top: $gl-padding-8;
- }
-
- @include media-breakpoint-up(md) {
- display: flex;
- align-items: center;
- }
-
> .btn,
> .btn-group,
> .btn-container,
@@ -146,6 +137,35 @@
}
}
+ @include media-breakpoint-up(md) {
+ display: flex;
+ align-items: center;
+ }
+
+ @include media-breakpoint-down(md) {
+ $controls-margin: $btn-margin-5 - 2px;
+ flex: 0 0 100%;
+ margin-top: $gl-padding-8;
+
+ .controls-item,
+ .controls-item-full,
+ .controls-item:last-child {
+ flex: 1 1 35%;
+ display: block;
+ width: 100%;
+ margin: $controls-margin;
+
+ .btn,
+ .dropdown {
+ margin: 0;
+ }
+ }
+
+ .controls-item-full {
+ flex: 1 1 100%;
+ }
+ }
+
@include media-breakpoint-down(sm) {
padding-bottom: 0;
width: 100%;
@@ -239,32 +259,6 @@
pre {
width: 100%;
}
-
- @include media-breakpoint-down(md) {
- .nav-controls {
- $controls-margin: $btn-margin-5 - 2px;
- flex: 0 0 100%;
- margin-top: $gl-padding-8;
-
- .controls-item,
- .controls-item-full,
- .controls-item:last-child {
- flex: 1 1 35%;
- display: block;
- width: 100%;
- margin: $controls-margin;
-
- .btn,
- .dropdown {
- margin: 0;
- }
- }
-
- .controls-item-full {
- flex: 1 1 100%;
- }
- }
- }
}
.scrolling-tabs-container {
diff --git a/app/assets/stylesheets/framework/spinner.scss b/app/assets/stylesheets/framework/spinner.scss
index a74aeb9f220..2aa0ab6c1eb 100644
--- a/app/assets/stylesheets/framework/spinner.scss
+++ b/app/assets/stylesheets/framework/spinner.scss
@@ -20,7 +20,7 @@
}
}
-.spinner {
+@mixin spinner($size: 16px, $border-width: 2px, $color: $orange-400) {
border-radius: 50%;
position: relative;
margin: 0 auto;
@@ -30,8 +30,12 @@
animation-iteration-count: infinite;
border-style: solid;
display: inline-flex;
- @include spinner-size(16px, 2px);
- @include spinner-color($orange-400);
+ @include spinner-size($size, $border-width);
+ @include spinner-color($color);
+}
+
+.spinner {
+ @include spinner;
&.spinner-md {
@include spinner-size(32px, 3px);
@@ -56,3 +60,7 @@
vertical-align: text-bottom;
}
}
+
+.spin {
+ animation: spinner-rotate 2s infinite linear;
+}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index c15d46d43b2..3d09edfe181 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -453,11 +453,9 @@
h4,
h5,
h6 {
- position: relative;
-
a.anchor {
- left: -16px;
- position: absolute;
+ float: left;
+ margin-left: -16px;
text-decoration: none;
outline: none;
diff --git a/app/assets/stylesheets/highlight/common.scss b/app/assets/stylesheets/highlight/common.scss
index 31075b09b83..d9b9f3694c1 100644
--- a/app/assets/stylesheets/highlight/common.scss
+++ b/app/assets/stylesheets/highlight/common.scss
@@ -20,6 +20,7 @@
@mixin diff-expansion($background, $border, $link) {
background-color: $background;
+ .diff-td,
td {
border-top: 1px solid $border;
border-bottom: 1px solid $border;
@@ -41,3 +42,12 @@
border-left: 3px solid $no-coverage;
}
}
+
+@mixin line-number-hover($color) {
+ background-color: $color;
+ border-color: darken($color, 5%);
+
+ a {
+ color: darken($color, 15%);
+ }
+}
diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss
index 8d965ea4309..d51d5b7137d 100644
--- a/app/assets/stylesheets/highlight/themes/dark.scss
+++ b/app/assets/stylesheets/highlight/themes/dark.scss
@@ -125,6 +125,9 @@ $dark-il: #de935f;
@include dark-diff-match-line;
}
+ .diff-td.diff-line-num.hll:not(.empty-cell),
+ .diff-td.line-coverage.hll:not(.empty-cell),
+ .diff-td.line_content.hll:not(.empty-cell),
td.diff-line-num.hll:not(.empty-cell),
td.line-coverage.hll:not(.empty-cell),
td.line_content.hll:not(.empty-cell) {
@@ -158,15 +161,17 @@ $dark-il: #de935f;
}
}
+ .diff-grid-left:hover,
+ .diff-grid-right:hover {
+ .diff-line-num:not(.empty-cell) {
+ @include line-number-hover($dark-over-bg);
+ }
+ }
+
.diff-line-num {
&.is-over,
&.hll:not(.empty-cell).is-over {
- background-color: $dark-over-bg;
- border-color: darken($dark-over-bg, 5%);
-
- a {
- color: darken($dark-over-bg, 15%);
- }
+ @include line-number-hover($dark-over-bg);
}
}
diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss
index 5ef2b9dcc36..e690f9c7c74 100644
--- a/app/assets/stylesheets/highlight/themes/monokai.scss
+++ b/app/assets/stylesheets/highlight/themes/monokai.scss
@@ -125,6 +125,9 @@ $monokai-gi: #a6e22e;
@include dark-diff-match-line;
}
+ .diff-td.diff-line-num.hll:not(.empty-cell),
+ .diff-td.line-coverage.hll:not(.empty-cell),
+ .diff-td.line_content.hll:not(.empty-cell),
td.diff-line-num.hll:not(.empty-cell),
td.line-coverage.hll:not(.empty-cell),
td.line_content.hll:not(.empty-cell) {
@@ -158,15 +161,17 @@ $monokai-gi: #a6e22e;
}
}
+ .diff-grid-left:hover,
+ .diff-grid-right:hover {
+ .diff-line-num:not(.empty-cell) {
+ @include line-number-hover($monokai-over-bg);
+ }
+ }
+
.diff-line-num {
&.is-over,
&.hll:not(.empty-cell).is-over {
- background-color: $monokai-over-bg;
- border-color: darken($monokai-over-bg, 5%);
-
- a {
- color: darken($monokai-over-bg, 15%);
- }
+ @include line-number-hover($monokai-over-bg);
}
}
diff --git a/app/assets/stylesheets/highlight/themes/none.scss b/app/assets/stylesheets/highlight/themes/none.scss
index fb548a00526..4fc6e5dba39 100644
--- a/app/assets/stylesheets/highlight/themes/none.scss
+++ b/app/assets/stylesheets/highlight/themes/none.scss
@@ -59,6 +59,13 @@
}
}
+ .diff-grid-left:hover,
+ .diff-grid-right:hover {
+ .diff-line-num:not(.empty-cell) {
+ @include line-number-hover($none-over-bg);
+ }
+ }
+
.diff-line-num {
&.old {
a {
@@ -74,12 +81,7 @@
&.is-over,
&.hll:not(.empty-cell).is-over {
- background-color: $none-over-bg;
- border-color: darken($none-over-bg, 5%);
-
- a {
- color: darken($none-over-bg, 15%);
- }
+ @include line-number-hover($none-over-bg);
}
&.hll:not(.empty-cell) {
diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
index 190a6e6156a..8c532f53182 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-dark.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
@@ -129,6 +129,9 @@ $solarized-dark-il: #2aa198;
@include dark-diff-match-line;
}
+ .diff-td.diff-line-num.hll:not(.empty-cell),
+ .diff-td.line-coverage.hll:not(.empty-cell),
+ .diff-td.line_content.hll:not(.empty-cell),
td.diff-line-num.hll:not(.empty-cell),
td.line-coverage.hll:not(.empty-cell),
td.line_content.hll:not(.empty-cell) {
@@ -140,6 +143,13 @@ $solarized-dark-il: #2aa198;
@include line-coverage-border-color($solarized-dark-coverage, $solarized-dark-no-coverage);
}
+ .diff-grid-left:hover,
+ .diff-grid-right:hover {
+ .diff-line-num:not(.empty-cell) {
+ @include line-number-hover($solarized-dark-over-bg);
+ }
+ }
+
.diff-line-num.new,
.line-coverage.new,
.line_content.new {
@@ -165,12 +175,7 @@ $solarized-dark-il: #2aa198;
.diff-line-num {
&.is-over,
&.hll:not(.empty-cell).is-over {
- background-color: $solarized-dark-over-bg;
- border-color: darken($solarized-dark-over-bg, 5%);
-
- a {
- color: darken($solarized-dark-over-bg, 15%);
- }
+ @include line-number-hover($solarized-dark-over-bg);
}
}
diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss
index 71d8dd06834..1f9042a9534 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-light.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss
@@ -136,6 +136,9 @@ $solarized-light-il: #2aa198;
@include match-line;
}
+ .diff-td.diff-line-num.hll:not(.empty-cell),
+ .diff-td.line-coverage.hll:not(.empty-cell),
+ .diff-td.line_content.hll:not(.empty-cell),
td.diff-line-num.hll:not(.empty-cell),
td.line-coverage.hll:not(.empty-cell),
td.line_content.hll:not(.empty-cell) {
@@ -159,6 +162,13 @@ $solarized-light-il: #2aa198;
}
}
+ .diff-grid-left:hover,
+ .diff-grid-right:hover {
+ .diff-line-num:not(.empty-cell) {
+ @include line-number-hover($solarized-light-over-bg);
+ }
+ }
+
.diff-line-num.old,
.line-coverage.old,
.line_content.old {
@@ -173,12 +183,7 @@ $solarized-light-il: #2aa198;
.diff-line-num {
&.is-over,
&.hll:not(.empty-cell).is-over {
- background-color: $solarized-light-over-bg;
- border-color: darken($solarized-light-over-bg, 5%);
-
- a {
- color: darken($solarized-light-over-bg, 15%);
- }
+ @include line-number-hover($solarized-light-over-bg);
}
}
diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss
index 3e126a52c4b..bb5ca94af33 100644
--- a/app/assets/stylesheets/highlight/white_base.scss
+++ b/app/assets/stylesheets/highlight/white_base.scss
@@ -113,6 +113,13 @@ pre.code,
@include match-line;
}
+ .diff-grid-left:hover,
+ .diff-grid-right:hover {
+ .diff-line-num:not(.empty-cell) {
+ @include line-number-hover($white-over-bg);
+ }
+ }
+
.diff-line-num {
&.old {
background-color: $line-number-old;
@@ -134,12 +141,7 @@ pre.code,
&.is-over,
&.hll:not(.empty-cell).is-over {
- background-color: $white-over-bg;
- border-color: darken($white-over-bg, 5%);
-
- a {
- color: darken($white-over-bg, 15%);
- }
+ @include line-number-hover($white-over-bg);
}
&.hll:not(.empty-cell) {
diff --git a/app/assets/stylesheets/lazy_bundles/select2.scss b/app/assets/stylesheets/lazy_bundles/select2.scss
new file mode 100644
index 00000000000..f2c372020ef
--- /dev/null
+++ b/app/assets/stylesheets/lazy_bundles/select2.scss
@@ -0,0 +1,654 @@
+/*
+Version: 3.5.2 Timestamp: Sat Nov 1 14:43:36 EDT 2014
+Updated 2020-10-05 by TimZ
+*/
+.select2-container {
+ margin: 0;
+ position: relative;
+ display: inline-block;
+}
+
+.select2-container,
+.select2-drop,
+.select2-search,
+.select2-search input {
+ box-sizing: border-box;
+}
+
+.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;
+
+ user-select: none;
+
+ background-color: #fff;
+ 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: 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;
+ /* stylelint-disable-next-line function-url-quotes */
+ 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;
+
+ box-shadow: 0 4px 5px rgba(0, 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;
+
+ box-shadow: 0 -4px 5px rgba(0, 0, 0, 0.15);
+}
+
+.select2-drop-active {
+ border: 1px solid #5897fb;
+ border-top: 0;
+}
+
+.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: linear-gradient(to top, #ccc 0%, #eee 60%);
+}
+
+html[dir='rtl'] .select2-container .select2-choice .select2-arrow {
+ left: 0;
+ right: auto;
+
+ border-left: 0;
+ border-right: 1px solid #aaa;
+ border-radius: 4px 0 0 4px;
+}
+
+.select2-container .select2-choice .select2-arrow b {
+ display: block;
+ width: 100%;
+ height: 100%;
+ /* stylelint-disable-next-line function-url-quotes */
+ 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;
+
+ box-shadow: none;
+ /* stylelint-disable-next-line function-url-quotes */
+ 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;
+ /* stylelint-disable-next-line function-url-quotes */
+ 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 {
+ /* stylelint-disable-next-line function-url-quotes */
+ 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;
+
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
+}
+
+.select2-dropdown-open .select2-choice {
+ border-bottom-color: transparent;
+ box-shadow: 0 1px 0 #fff inset;
+
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+
+ background-color: #eee;
+ 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: linear-gradient(to bottom, #fff 0%, #eee 50%);
+}
+
+.select2-dropdown-open .select2-choice .select2-arrow {
+ background: transparent;
+ border-left: 0;
+ filter: none;
+}
+
+html[dir='rtl'] .select2-dropdown-open .select2-choice .select2-arrow {
+ border-right: 0;
+}
+
+.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;
+}
+
+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;
+
+ 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 {
+ /* stylelint-disable-next-line function-url-quotes */
+ background: #f4f4f4 url(image-path('select2-spinner.gif')) no-repeat 100%;
+}
+
+.select2-results .select2-ajax-error {
+ background: rgba(255, 50, 50, 0.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: 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 !important;
+}
+
+.select2-container-multi .select2-choices {
+ min-height: 26px;
+}
+
+.select2-container-multi.select2-container-active .select2-choices {
+ border: 1px solid #5897fb;
+ outline: none;
+
+ box-shadow: 0 0 5px rgba(0, 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;
+
+ box-shadow: none;
+ background: transparent !important;
+}
+
+.select2-container-multi .select2-choices .select2-search-field input.select2-active {
+ /* stylelint-disable-next-line function-url-quotes */
+ 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 #aaa;
+
+ border-radius: 3px;
+
+ box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
+
+ background-clip: padding-box;
+
+ user-select: none;
+
+ background-color: #e4e4e4;
+ 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;
+ /* stylelint-disable-next-line function-url-quotes */
+ 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;
+ 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: 0 !important;
+ top: 0 !important;
+}
+
+.select2-display-none {
+ display: none;
+}
+
+.select2-measure-scrollbar {
+ position: absolute;
+ top: -10000px;
+ left: -10000px;
+ width: 100px;
+ height: 100px;
+ overflow: scroll;
+}
+
+@media only screen and (min-resolution: 120dpi) {
+ .select2-search input,
+ .select2-search-choice-close,
+ .select2-container .select2-choice abbr,
+ .select2-container .select2-choice .select2-arrow b {
+ /* stylelint-disable-next-line function-url-quotes */
+ 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;
+ }
+}
+
+/* End of select2.css */
+
+@import './select2_overrides';
diff --git a/app/assets/stylesheets/lazy_bundles/select2_overrides.scss b/app/assets/stylesheets/lazy_bundles/select2_overrides.scss
new file mode 100644
index 00000000000..6c51c4b0ec3
--- /dev/null
+++ b/app/assets/stylesheets/lazy_bundles/select2_overrides.scss
@@ -0,0 +1,359 @@
+@import 'page_bundles/mixins_and_variables_and_functions';
+/** Select2 selectbox style override **/
+.select2-container {
+ width: 100% !important;
+
+ &.input-md,
+ &.input-lg {
+ display: block;
+ }
+}
+
+.select2-container,
+.select2-container.select2-drop-above {
+ .select2-choice {
+ background: $white;
+ color: $gl-text-color;
+ border-color: $border-color;
+ height: 34px;
+ padding: $gl-vert-padding $gl-input-padding;
+ font-size: $gl-font-size;
+ line-height: 1.42857143;
+ border-radius: $gl-border-radius-base;
+
+ .select2-arrow {
+ background-image: none;
+ background-color: transparent;
+ border: 0;
+ padding-top: 12px;
+ padding-right: 20px;
+ font-size: 10px;
+
+ b {
+ display: none;
+ }
+
+ &::after {
+ content: '\f078';
+ position: absolute;
+ z-index: 1;
+ text-align: center;
+ pointer-events: none;
+ box-sizing: border-box;
+ color: $gray-darkest;
+ display: inline-block;
+ font: normal normal normal 14px/1 FontAwesome;
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ }
+ }
+
+ .select2-chosen {
+ margin-right: 15px;
+ }
+
+ &:hover {
+ border-color: $gray-darkest;
+ color: $gl-text-color;
+ }
+ }
+
+ // Essentially we’re doing @include form-control-focus here (from
+ // bootstrap/scss/mixins/_forms.scss), except that the bootstrap mixin adds a
+ // `&:focus` selector and we’re never actually focusing the .select2-choice
+ // link nor the .select2-container, the Select2 library focuses an off-screen
+ // .select2-focusser element instead.
+ &.select2-container-active:not(.select2-dropdown-open) {
+ .select2-choice {
+ color: $input-focus-color;
+ background-color: $input-focus-bg;
+ border-color: $input-focus-border-color;
+ outline: 0;
+ }
+
+ // Reusable focus “glow†box-shadow
+ @mixin form-control-focus-glow {
+ @if $enable-shadows {
+ box-shadow: $input-box-shadow, $input-focus-box-shadow;
+ } @else {
+ box-shadow: $input-focus-box-shadow;
+ }
+ }
+
+ // Apply the focus “glow†shadow to the .select2-container if it also has
+ // the .block-truncated class as that applies an overflow: hidden, thereby
+ // hiding the glow of the nested .select2-choice element.
+ &.block-truncated {
+ @include form-control-focus-glow;
+ }
+
+ // Apply the glow directly to the .select2-choice link if we’re not
+ // block-truncating the container.
+ &:not(.block-truncated) .select2-choice {
+ @include form-control-focus-glow;
+ }
+ }
+
+ &.is-invalid {
+ ~ .invalid-feedback {
+ display: block;
+ }
+
+ .select2-choices,
+ .select2-choice {
+ border-color: $red-500;
+ }
+ }
+}
+
+.select2-drop,
+.select2-drop.select2-drop-above {
+ background: $white;
+ box-shadow: 0 2px 4px $dropdown-shadow-color;
+ border-radius: $gl-border-radius-base;
+ border: 1px solid $border-color;
+ min-width: 175px;
+ color: $gl-text-color;
+ z-index: 999;
+
+ .modal-open & {
+ z-index: $zindex-modal + 200;
+ }
+}
+
+.select2-drop-mask {
+ z-index: 998;
+
+ .modal-open & {
+ z-index: $zindex-modal + 100;
+ }
+}
+
+.select2-drop.select2-drop-above.select2-drop-active {
+ border-top: 1px solid $border-color;
+ margin-top: -6px;
+}
+
+.select2-container-active {
+ .select2-choice,
+ .select2-choices {
+ box-shadow: none;
+ }
+}
+
+.select2-dropdown-open,
+.select2-dropdown-open.select2-drop-above {
+ .select2-choice {
+ border-color: $gray-darkest;
+ outline: 0;
+ }
+}
+
+.select2-container-multi {
+ .select2-choices {
+ border-radius: $border-radius-default;
+ border-color: $border-color;
+ background: none;
+
+ .select2-search-field input {
+ padding: 5px $gl-input-padding;
+ height: auto;
+ font-family: inherit;
+ font-size: inherit;
+ }
+
+ .select2-search-choice {
+ margin: 5px 0 0 8px;
+ box-shadow: none;
+ border-color: $border-color;
+ color: $gl-text-color;
+ line-height: 15px;
+ background-color: $gray-light;
+ background-image: none;
+ padding: 3px 18px 3px 5px;
+
+ .select2-search-choice-close {
+ top: 5px;
+ left: initial;
+ right: 3px;
+ }
+
+ &.select2-search-choice-focus {
+ border-color: $gl-text-color;
+ }
+ }
+ }
+}
+
+.select2-drop-active {
+ margin-top: $dropdown-vertical-offset;
+ font-size: 14px;
+
+ .select2-results {
+ max-height: 350px;
+ }
+}
+
+.select2-search {
+ padding: $grid-size;
+
+ .select2-drop-auto-width & {
+ padding: $grid-size;
+ }
+
+ input {
+ padding: $grid-size;
+ background: transparent image-url('select2.png');
+ color: $gl-text-color;
+ background-clip: content-box;
+ background-origin: content-box;
+ background-repeat: no-repeat;
+ background-position: right 0 bottom 0 !important;
+ border: 1px solid $border-color;
+ border-radius: $border-radius-default;
+ line-height: 16px;
+ transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+
+ &:focus {
+ border-color: $blue-300;
+ }
+
+ &.select2-active {
+ background-color: $white;
+ background-image: image-url('select2-spinner.gif') !important;
+ background-origin: content-box;
+ background-repeat: no-repeat;
+ background-position: right 6px center !important;
+ background-size: 16px 16px !important;
+ }
+ }
+
+ + .select2-results {
+ padding-top: 0;
+ }
+}
+
+.select2-results {
+ margin: 0;
+ padding: #{$gl-padding / 2} 0;
+
+ .select2-no-results,
+ .select2-searching,
+ .select2-ajax-error,
+ .select2-selection-limit {
+ background: transparent;
+ padding: #{$gl-padding / 2} $gl-padding;
+ }
+
+ .select2-result-label,
+ .select2-more-results {
+ padding: #{$gl-padding / 2} $gl-padding;
+ }
+
+ .select2-highlighted {
+ background: transparent;
+ color: $gl-text-color;
+
+ .select2-result-label {
+ background: $gray-darker;
+ }
+ }
+
+ .select2-result {
+ padding: 0 1px;
+ }
+
+ li.select2-result-with-children > .select2-result-label {
+ font-weight: $gl-font-weight-bold;
+ color: $gl-text-color;
+ }
+}
+
+.select2-highlighted {
+ .group-result {
+ .group-path {
+ color: $gray-700;
+ }
+ }
+}
+
+.select2-result-selectable,
+.select2-result-unselectable {
+ .select2-match {
+ font-weight: $gl-font-weight-bold;
+ text-decoration: none;
+ }
+}
+
+.input-group {
+ .select2-container {
+ display: table-cell;
+ max-width: 180px;
+ }
+}
+
+.file-editor {
+ .select2 {
+ float: right;
+ }
+}
+
+.import-namespace-select {
+ > .select2-choice {
+ border-radius: $border-radius-default 0 0 $border-radius-default;
+ position: relative;
+ left: 1px;
+ }
+}
+
+.issue-form {
+ .select2-container {
+ width: 250px !important;
+ }
+}
+
+.new_project,
+.edit-project,
+.import-project {
+ .input-group {
+ .select2-container {
+ display: unset;
+ max-width: unset;
+ flex-grow: 1;
+ }
+ }
+
+ .input-group-prepend,
+ .input-group-append {
+ + .select2 a {
+ border-radius: 0 $gl-border-radius-base $gl-border-radius-base 0;
+ }
+ }
+}
+
+.project-path {
+ .select2-choice {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ }
+}
+
+.transfer-project .select2-container {
+ min-width: 200px;
+}
+
+.right-sidebar {
+ .block {
+ .select2-container span {
+ margin-top: 0;
+ }
+ }
+}
+
+.block-truncated {
+ > div:not(.block):not(.select2-display-none) {
+ display: inline;
+ }
+}
diff --git a/app/assets/stylesheets/mailer.scss b/app/assets/stylesheets/mailer.scss
index b2050c0e73f..27c6ef20269 100644
--- a/app/assets/stylesheets/mailer.scss
+++ b/app/assets/stylesheets/mailer.scss
@@ -143,4 +143,21 @@ tr.footer td {
color: $mailer-link-color;
text-decoration: none;
}
+
+ .gitlab-info {
+ padding: $gl-padding-24 0;
+ }
+
+ .gitlab-info-text {
+ max-width: 640px;
+ margin: 0 auto;
+ text-align: center;
+ color: $gray-400;
+ font-size: $gl-font-size-small;
+ }
+
+ .footer-logo {
+ width: 90px;
+ height: 33px;
+ }
}
diff --git a/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss b/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
index d1f7c2e9865..52cc7d3449e 100644
--- a/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
+++ b/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
@@ -5,7 +5,7 @@
$bs-input-focus-border: #80bdff;
$bs-input-focus-box-shadow: rgba(0, 123, 255, 0.25);
- a:not(.btn),
+ a:not(.btn):not(.gl-tab-nav-item),
.gl-button.btn-link,
.gl-button.btn-link:hover,
.gl-button.btn-link:focus,
@@ -151,7 +151,7 @@
border-color: var(--ide-border-color-alt, $gray-100);
code {
- background-color: var(--ide-border-color, inherit);
+ background-color: var(--ide-empty-state-background, inherit);
}
}
@@ -427,7 +427,7 @@
}
.md table:not(.code) tbody {
- background-color: var(--ide-border-color, $white);
+ background-color: var(--ide-empty-state-background, $white);
}
.animation-container {
diff --git a/app/assets/stylesheets/page_bundles/alert_management_details.scss b/app/assets/stylesheets/page_bundles/alert_management_details.scss
new file mode 100644
index 00000000000..beb80a14c5a
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/alert_management_details.scss
@@ -0,0 +1,46 @@
+@import 'mixins_and_variables_and_functions';
+
+.alert-management-details {
+ @include media-breakpoint-down(xs) {
+ .alert-details-incident-button {
+ @include gl-w-full;
+ }
+ }
+
+ .toggle-sidebar-mobile-button {
+ @include gl-right-0;
+ }
+
+ .dropdown-menu-toggle {
+ &:hover {
+ @include gl-bg-white;
+ }
+ }
+
+ .assignee-dropdown-item {
+ .dropdown-item {
+ @include gl-display-flex;
+ @include gl-align-items-center;
+
+ &::before {
+ top: 50% !important;
+ }
+
+ &.is-active {
+ &:last-child {
+ @include gl-border-b-gray-100;
+ @include gl-border-b-1;
+ @include gl-border-b-solid;
+ }
+ }
+ }
+ }
+
+ .main-notes-list::before {
+ left: $gl-spacing-scale-5 !important;
+ }
+
+ .note-header-info {
+ @include gl-mt-1;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/alert_management_settings.scss b/app/assets/stylesheets/page_bundles/alert_management_settings.scss
new file mode 100644
index 00000000000..fb7c1602cba
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/alert_management_settings.scss
@@ -0,0 +1,24 @@
+@import 'mixins_and_variables_and_functions';
+
+$stroke-size: 1px;
+
+.right-arrow {
+ @include gl-relative;
+ @include gl-w-full;
+ height: $stroke-size;
+ @include gl-display-inline-block;
+ background-color: var(--gray-400, $gray-400);
+ min-width: $gl-spacing-scale-5;
+
+ &-head {
+ @include gl-absolute;
+ top: -$gl-spacing-scale-2;
+ left: calc(100% - #{$gl-spacing-scale-3} - #{2 * $stroke-size});
+ border-color: var(--gray-400, $gray-400);
+ @include gl-border-solid;
+ border-width: 0 $stroke-size $stroke-size 0;
+ @include gl-display-inline-block;
+ @include gl-p-2;
+ transform: rotate(-45deg);
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/boards.scss b/app/assets/stylesheets/page_bundles/boards.scss
index e908e3622ed..ffc15af6329 100644
--- a/app/assets/stylesheets/page_bundles/boards.scss
+++ b/app/assets/stylesheets/page_bundles/boards.scss
@@ -83,9 +83,6 @@
}
.board {
- // the next line cannot be replaced with .d-inline-block because it breaks display: none of SortableJS
- // see https://gitlab.com/gitlab-org/gitlab-foss/issues/64828
- display: inline-block;
width: calc(85vw - 15px);
@include media-breakpoint-up(sm) {
@@ -116,39 +113,10 @@
&.is-collapsed {
width: 50px;
- .board-title {
- flex-direction: column;
- }
-
.board-title-caret {
margin-top: 1px;
}
- .user-avatar-link,
- .milestone-icon {
- margin-top: $gl-padding-8;
- transform: rotate(90deg);
- }
-
- .board-title-text {
- flex-grow: 0;
- margin: $gl-padding-8 0;
-
- .board-title-main-text {
- display: block;
- }
-
- .board-title-sub-text {
- display: none;
- }
- }
-
- .issue-count-badge {
- border: 0;
- white-space: nowrap;
- padding: 0;
- }
-
.board-title-text > span,
.issue-count-badge > span {
height: 16px;
@@ -197,10 +165,7 @@
}
.board-title {
- align-items: center;
- font-size: 1em;
border-bottom: 1px solid var(--gray-100, $gray-100);
- padding: 0 $gl-spacing-scale-3;
height: 3rem;
.js-max-issue-size::before {
@@ -208,21 +173,6 @@
}
}
-.board-title-text {
- flex-grow: 1;
-}
-
-.board-delete.gl-button {
- background-color: transparent;
- outline: 0;
-
- &:hover {
- color: var(--blue-600, $blue-600);
- box-shadow: none;
- }
-}
-
-.board-blank-state,
.board-promotion-state {
background-color: var(--white, $white);
flex: 1;
@@ -230,19 +180,6 @@
overflow-x: hidden;
}
-.board-blank-state-list {
- > li:not(:last-child) {
- margin-bottom: 8px;
- }
-
- .label-color {
- top: 2px;
- width: 16px;
- height: 16px;
- margin-right: 3px;
- }
-}
-
.board-list-component {
min-height: 0; // firefox fix
}
@@ -311,10 +248,6 @@
}
}
-.board-card-header {
- text-align: initial;
-}
-
.board-card-assignee {
margin-top: -$gl-padding-4;
margin-bottom: -$gl-padding-4;
@@ -586,28 +519,6 @@
}
}
-.board-swimlanes {
- overflow-x: auto;
-}
-
.board-header-collapsed-info-icon:hover {
color: var(--gray-900, $gray-900);
}
-
-$epic-icons-spacing: 40px;
-
-.board-epic-lane {
- max-width: calc(100vw - #{$contextual-sidebar-width} - #{$epic-icons-spacing});
-
- .page-with-icon-sidebar & {
- max-width: calc(100vw - #{$contextual-sidebar-collapsed-width} - #{$epic-icons-spacing});
- }
-
- .page-with-icon-sidebar .is-compact & {
- max-width: calc(100vw - #{$contextual-sidebar-collapsed-width} - #{$gutter-width} - #{$epic-icons-spacing});
- }
-
- .is-compact & {
- max-width: calc(100vw - #{$contextual-sidebar-width} - #{$gutter-width} - #{$epic-icons-spacing});
- }
-}
diff --git a/app/assets/stylesheets/page_bundles/build.scss b/app/assets/stylesheets/page_bundles/build.scss
new file mode 100644
index 00000000000..2f0f4a46658
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/build.scss
@@ -0,0 +1,294 @@
+@import 'mixins_and_variables_and_functions';
+
+.build-page {
+ .build-trace {
+ @include build-trace();
+ }
+
+ .archived-job {
+ top: $header-height;
+ border-radius: 2px 2px 0 0;
+ color: $orange-600;
+ background-color: $orange-50;
+ border: 1px solid $border-gray-normal;
+ padding: 3px 12px;
+ margin: auto;
+ align-items: center;
+ z-index: 1;
+
+ .with-performance-bar & {
+ top: $header-height + $performance-bar-height;
+ }
+ }
+
+ .top-bar {
+ @include build-trace-top-bar(50px);
+
+ &.has-archived-block {
+ top: $header-height + 28px;
+
+ .with-performance-bar & {
+ top: $header-height + $performance-bar-height + 28px;
+ }
+ }
+
+ &.affix {
+ top: $header-height;
+
+ // with sidebar
+ &.sidebar-expanded {
+ right: 306px;
+ left: 16px;
+ }
+
+ // without sidebar
+ &.sidebar-collapsed {
+ right: 16px;
+ left: 16px;
+ }
+ }
+
+ &.affix-top {
+ position: absolute;
+ right: 0;
+ left: 0;
+ top: 0;
+ }
+
+ .controllers {
+ @include build-controllers(15px, center, false, 0, inline, 0);
+ }
+ }
+
+ .environment-information {
+ border: 1px solid $border-color;
+ padding: 8px $gl-padding 12px;
+ border-radius: $border-radius-default;
+
+ svg {
+ position: relative;
+ top: 3px;
+ margin-right: 5px;
+ width: 22px;
+ height: 22px;
+ }
+ }
+
+ .build-loader-animation {
+ @include build-loader-animation;
+ float: left;
+ padding-left: $gl-padding-8;
+ }
+}
+
+.build-header {
+ .page-content-header {
+ padding: 10px 0 9px;
+ }
+
+ .header-action-buttons {
+ display: flex;
+
+ @include media-breakpoint-down(xs) {
+ .sidebar-toggle-btn {
+ margin-top: 0;
+ margin-left: 10px;
+ max-height: 34px;
+ }
+ }
+ }
+
+ .header-content {
+ a {
+ color: $gl-text-color;
+
+ &:hover {
+ color: $blue-600;
+ text-decoration: none;
+ }
+ }
+ }
+
+ code {
+ color: $code-color;
+ }
+
+ .avatar {
+ float: none;
+ margin-right: 2px;
+ margin-left: 2px;
+ }
+}
+
+.right-sidebar.build-sidebar {
+ padding: 0;
+
+ &.right-sidebar-collapsed {
+ display: none;
+ }
+
+ .sidebar-container {
+ padding-right: 100px;
+ height: 100%;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ -webkit-overflow-scrolling: touch;
+ }
+
+ .blocks-container {
+ padding: 0 $gl-padding;
+ width: 289px;
+ }
+
+ .block {
+ width: 100%;
+ word-break: break-word;
+
+ &:last-child {
+ border-bottom: 1px solid $border-gray-normal;
+ }
+
+ &.coverage {
+ padding: 0 16px 11px;
+ }
+ }
+
+ .block-last {
+ padding: 16px 0;
+ }
+
+ .trigger-variables-btn-container {
+ justify-content: space-between;
+ align-items: center;
+
+ .trigger-variables-btn {
+ margin-top: -5px;
+ margin-bottom: -5px;
+ }
+ }
+
+ .trigger-build-variables {
+ margin: 0;
+ overflow-x: auto;
+ width: 100%;
+ -ms-overflow-style: scrollbar;
+ -webkit-overflow-scrolling: touch;
+ }
+
+ .trigger-build-variable {
+ font-weight: $gl-font-weight-normal;
+ color: $code-color;
+ }
+
+ .trigger-build-value {
+ padding: 2px 4px;
+ color: $black;
+ }
+
+ .trigger-variables-table-cell {
+ font-size: $gl-font-size-small;
+ line-height: $gl-line-height;
+ border: 1px solid $gray-100;
+ padding: $gl-padding-4 6px;
+ width: 50%;
+ vertical-align: top;
+ }
+
+ .badge.badge-pill {
+ margin-left: 2px;
+ }
+
+ .retry-link {
+ display: block;
+
+ .btn-inverted-secondary {
+ color: $blue-500;
+
+ &:hover {
+ color: $white;
+ }
+ }
+ }
+
+ .stage-item {
+ cursor: pointer;
+
+ &:hover {
+ color: $gl-text-color;
+ }
+ }
+
+ .builds-container {
+ background-color: $white;
+ border-top: 1px solid $border-color;
+ border-bottom: 1px solid $border-color;
+ max-height: 300px;
+ width: 289px;
+ overflow: auto;
+
+ svg {
+ margin-right: 3px;
+ height: 14px;
+ width: 14px;
+ }
+
+ a {
+ padding: $gl-padding 10px $gl-padding 40px;
+ width: 270px;
+
+ &:hover {
+ color: $gl-text-color;
+ }
+ }
+
+ .icon-arrow-right {
+ left: 15px;
+ top: 20px;
+ }
+
+ .build-job {
+ &.active {
+ font-weight: $gl-font-weight-bold;
+ }
+
+ &.retried {
+ background-color: $gray-lightest;
+ }
+
+ &:hover {
+ background-color: $gray-darker;
+ }
+ }
+ }
+
+ .link-commit {
+ color: $blue-600;
+ }
+}
+
+.build-sidebar {
+ .container-fluid.container-limited {
+ max-width: 100%;
+ }
+
+ .content-wrapper {
+ padding-bottom: 6px;
+ }
+}
+
+.build-detail-row {
+ margin-bottom: 5px;
+
+ &:last-of-type {
+ margin-bottom: 0;
+ }
+}
+
+@include media-breakpoint-down(md) {
+ .content-list {
+ &.builds-content-list {
+ width: 100%;
+ overflow: auto;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/ci_status.scss b/app/assets/stylesheets/page_bundles/ci_status.scss
new file mode 100644
index 00000000000..8522a0a8fe4
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/ci_status.scss
@@ -0,0 +1,79 @@
+@import 'mixins_and_variables_and_functions';
+
+.ci-status {
+ padding: 2px 7px 4px;
+ border: 1px solid $gray-darker;
+ white-space: nowrap;
+ border-radius: 4px;
+
+ &:hover,
+ &:focus {
+ text-decoration: none;
+ }
+
+ svg {
+ height: 13px;
+ width: 13px;
+ overflow: visible;
+ }
+
+ &.ci-failed {
+ @include status-color($red-100, $red-500, $red-600);
+ }
+
+ &.ci-success {
+ @include green-status-color;
+ }
+
+ &.ci-canceled,
+ &.ci-disabled,
+ &.ci-scheduled,
+ &.ci-manual {
+ color: $gl-text-color;
+ border-color: $gl-text-color;
+
+ &:not(span):hover {
+ background-color: rgba($gl-text-color, 0.07);
+ }
+ }
+
+ &.ci-preparing {
+ @include status-color($gray-100, $gray-300, $gray-400);
+ }
+
+ &.ci-pending,
+ &.ci-waiting-for-resource,
+ &.ci-failed-with-warnings,
+ &.ci-success-with-warnings {
+ @include status-color($orange-50, $orange-500, $orange-700);
+ }
+
+ &.ci-info,
+ &.ci-running {
+ @include status-color($blue-100, $blue-500, $blue-600);
+ }
+
+ &.ci-created,
+ &.ci-skipped {
+ color: $gl-text-color-secondary;
+ border-color: $gl-text-color-secondary;
+
+ &:not(span):hover {
+ background-color: rgba($gl-text-color-secondary, 0.07);
+ }
+ }
+}
+
+.d-block.d-sm-none-inline {
+ .ci-status-link {
+ position: relative;
+ top: 2px;
+ left: 5px;
+ }
+}
+
+.ci-status-link {
+ svg {
+ overflow: visible;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/experimental_separate_sign_up.scss b/app/assets/stylesheets/page_bundles/experimental_separate_sign_up.scss
deleted file mode 100644
index 337b5b001fe..00000000000
--- a/app/assets/stylesheets/page_bundles/experimental_separate_sign_up.scss
+++ /dev/null
@@ -1,96 +0,0 @@
-@import 'mixins_and_variables_and_functions';
-
-.signup-page {
- .page-wrap {
- background-color: var(--gray-10, $gray-10);
- }
-
- .signup-box-container {
- max-width: 960px;
- }
-
- .signup-box {
- background-color: var(--white, $white);
- box-shadow: 0 0 0 1px var(--border-color, $border-color);
- border-radius: $border-radius;
- }
-
- .form-control {
- &:active,
- &:focus {
- background-color: var(--white, $white);
- }
- }
-
- .devise-errors {
- h2 {
- font-size: $gl-font-size;
- color: var(--red-700, $red-700);
- }
- }
-
- .omniauth-divider {
- &::before,
- &::after {
- content: '';
- flex: 1;
- border-bottom: 1px solid var(--gray-100, $gray-100);
- margin: $gl-padding-24 0;
- }
-
- &::before {
- margin-right: $gl-padding;
- }
-
- &::after {
- margin-left: $gl-padding;
- }
- }
-
- .omniauth-btn {
- width: 48%;
-
- @include media-breakpoint-down(md) {
- width: 100%;
- }
-
- img {
- width: $default-icon-size;
- height: $default-icon-size;
- }
- }
-
- .decline-page {
- width: 350px;
- }
-}
-
-.signup-page[data-page^='registrations:experience_levels'] {
- $card-shadow-color: rgba(var(--black, $black), 0.2);
-
- .page-wrap {
- background-color: var(--white, $white);
- }
-
- .card-deck {
- max-width: 828px;
- }
-
- .card {
- transition: box-shadow 0.3s ease-in-out;
- }
-
- .card:hover {
- box-shadow: 0 $gl-spacing-scale-3 $gl-spacing-scale-5 $card-shadow-color;
- }
-
- @media (min-width: $breakpoint-sm) {
- .card-deck .card {
- margin: 0 $gl-spacing-scale-3;
- }
- }
-
- .stretched-link:hover {
- text-decoration: none;
- }
-}
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index 71e74297ee8..15cc10d1532 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -5,7 +5,9 @@
@import './ide_theme_overrides';
@import './ide_themes/dark';
+@import './ide_themes/solarized-light';
@import './ide_themes/solarized-dark';
+@import './ide_themes/monokai';
$search-list-icon-width: 18px;
$ide-activity-bar-width: 60px;
@@ -176,11 +178,11 @@ $ide-commit-header-height: 48px;
height: 100%;
overflow: auto;
padding: $gl-padding;
- background-color: var(--ide-border-color, transparent);
+ background-color: var(--ide-empty-state-background, transparent);
}
.file-container {
- background-color: var(--ide-border-color, $gray-darker);
+ background-color: var(--ide-empty-state-background, $gray-darker);
display: flex;
height: 100%;
align-items: center;
@@ -491,7 +493,7 @@ $ide-commit-header-height: 48px;
height: 100vh;
align-items: center;
justify-content: center;
- background-color: var(--ide-border-color, transparent);
+ background-color: var(--ide-empty-state-background, transparent);
}
.ide {
@@ -915,12 +917,6 @@ $ide-commit-header-height: 48px;
}
}
-.ide-pipeline-list {
- flex: 1;
- overflow: auto;
- padding: 0 $gl-padding;
-}
-
.ide-pipeline-header {
min-height: 55px;
padding-left: $gl-padding;
diff --git a/app/assets/stylesheets/page_bundles/ide_themes/_dark.scss b/app/assets/stylesheets/page_bundles/ide_themes/_dark.scss
index 41f9a8e6db7..c7aae77c412 100644
--- a/app/assets/stylesheets/page_bundles/ide_themes/_dark.scss
+++ b/app/assets/stylesheets/page_bundles/ide_themes/_dark.scss
@@ -12,6 +12,7 @@
--ide-highlight-background: #252526;
--ide-link-color: #428fdc;
--ide-footer-background: #060606;
+ --ide-empty-state-background: var(--ide-border-color);
--ide-input-border: #868686;
--ide-input-background: transparent;
@@ -35,6 +36,13 @@
--ide-btn-success-hover-border-width: 2px;
--ide-btn-success-focus-box-shadow: 0 0 0 1px #2da160;
+ // Danger styles should be the same as default styles in dark theme
+ --ide-btn-danger-secondary-background: var(--ide-btn-default-background);
+ --ide-btn-danger-secondary-border: var(--ide-btn-default-border);
+ --ide-btn-danger-secondary-hover-border: var(--ide-btn-default-hover-border);
+ --ide-btn-danger-secondary-hover-border-width: var(--ide-btn-default-hover-border-width);
+ --ide-btn-danger-secondary-focus-box-shadow: var(--ide-btn-default-focus-box-shadow);
+
--ide-btn-disabled-background: transparent;
--ide-btn-disabled-border: rgba(223, 223, 223, 0.24);
--ide-btn-disabled-hover-border: rgba(223, 223, 223, 0.24);
diff --git a/app/assets/stylesheets/page_bundles/ide_themes/_monokai.scss b/app/assets/stylesheets/page_bundles/ide_themes/_monokai.scss
new file mode 100644
index 00000000000..f53ace0b6c2
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/ide_themes/_monokai.scss
@@ -0,0 +1,66 @@
+// -------
+// Please see `app/assets/stylesheets/page_bundles/ide_themes/README.md` for a guide on contributing new themes
+// -------
+.ide.theme-monokai {
+ --ide-border-color: #1a1a18;
+ --ide-border-color-alt: #3f4237;
+ --ide-highlight-accent: #fff;
+ --ide-text-color: #ccc;
+ --ide-text-color-secondary: #b7b7b7;
+ --ide-background: #282822;
+ --ide-background-hover: #2d2d2d;
+ --ide-highlight-background: #1f1f1d;
+ --ide-link-color: #428fdc;
+ --ide-footer-background: #404338;
+ --ide-empty-state-background: #1a1a18;
+
+ --ide-input-border: #7d8175;
+ --ide-input-background: transparent;
+ --ide-input-color: #fff;
+
+ --ide-btn-default-background: transparent;
+ --ide-btn-default-border: #7d8175;
+ --ide-btn-default-hover-border: #b5bda5;
+ --ide-btn-default-hover-border-width: 2px;
+ --ide-btn-default-focus-box-shadow: 0 0 0 1px #bfbfbf;
+
+ --ide-btn-primary-background: #1068bf;
+ --ide-btn-primary-border: #428fdc;
+ --ide-btn-primary-hover-border: #63a6e9;
+ --ide-btn-primary-hover-border-width: 2px;
+ --ide-btn-primary-focus-box-shadow: 0 0 0 1px #63a6e9;
+
+ --ide-btn-success-background: #217645;
+ --ide-btn-success-border: #108548;
+ --ide-btn-success-hover-border: #2da160;
+ --ide-btn-success-hover-border-width: 2px;
+ --ide-btn-success-focus-box-shadow: 0 0 0 1px #2da160;
+
+ // Danger styles should be the same as default styles in dark theme
+ --ide-btn-danger-secondary-background: var(--ide-btn-default-background);
+ --ide-btn-danger-secondary-border: var(--ide-btn-default-border);
+ --ide-btn-danger-secondary-hover-border: var(--ide-btn-default-hover-border);
+ --ide-btn-danger-secondary-hover-border-width: var(--ide-btn-default-hover-border-width);
+ --ide-btn-danger-secondary-focus-box-shadow: var(--ide-btn-default-focus-box-shadow);
+
+ --ide-btn-disabled-background: transparent;
+ --ide-btn-disabled-border: rgba(223, 223, 223, 0.24);
+ --ide-btn-disabled-hover-border: rgba(223, 223, 223, 0.24);
+ --ide-btn-disabled-hover-border-width: 1px;
+ --ide-btn-disabled-focus-box-shadow: 0 0 0 0 transparent;
+ --ide-btn-disabled-color: rgba(145, 145, 145, 0.48);
+
+ --ide-dropdown-background: #36382f;
+ --ide-dropdown-hover-background: #404338;
+
+ --ide-dropdown-btn-hover-border: #b5bda5;
+ --ide-dropdown-btn-hover-background: #3f4237;
+
+ --ide-file-row-btn-hover-background: #404338;
+
+ --ide-diff-insert: rgba(155, 185, 85, 0.2);
+ --ide-diff-remove: rgba(255, 0, 0, 0.2);
+
+ --ide-animation-gradient-1: #404338;
+ --ide-animation-gradient-2: #36382f;
+}
diff --git a/app/assets/stylesheets/page_bundles/ide_themes/_solarized-dark.scss b/app/assets/stylesheets/page_bundles/ide_themes/_solarized-dark.scss
index ccb6f7a333b..1906b3ca938 100644
--- a/app/assets/stylesheets/page_bundles/ide_themes/_solarized-dark.scss
+++ b/app/assets/stylesheets/page_bundles/ide_themes/_solarized-dark.scss
@@ -12,6 +12,7 @@
--ide-highlight-background: #003240;
--ide-link-color: #73b9ff;
--ide-footer-background: var(--ide-highlight-background);
+ --ide-empty-state-background: var(--ide-border-color);
--ide-input-border: #d8d8d8;
--ide-input-background: transparent;
@@ -35,6 +36,13 @@
--ide-btn-success-hover-border-width: 2px;
--ide-btn-success-focus-box-shadow: 0 0 0 1px #2da160;
+ // Danger styles should be the same as default styles in dark theme
+ --ide-btn-danger-secondary-background: var(--ide-btn-default-background);
+ --ide-btn-danger-secondary-border: var(--ide-btn-default-border);
+ --ide-btn-danger-secondary-hover-border: var(--ide-btn-default-hover-border);
+ --ide-btn-danger-secondary-hover-border-width: var(--ide-btn-default-hover-border-width);
+ --ide-btn-danger-secondary-focus-box-shadow: var(--ide-btn-default-focus-box-shadow);
+
--ide-btn-disabled-background: transparent;
--ide-btn-disabled-border: rgba(223, 223, 223, 0.24);
--ide-btn-disabled-hover-border: rgba(223, 223, 223, 0.24);
diff --git a/app/assets/stylesheets/page_bundles/ide_themes/_solarized-light.scss b/app/assets/stylesheets/page_bundles/ide_themes/_solarized-light.scss
new file mode 100644
index 00000000000..315a0ae6202
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/ide_themes/_solarized-light.scss
@@ -0,0 +1,57 @@
+// -------
+// Please see `app/assets/stylesheets/page_bundles/ide_themes/README.md` for a guide on contributing new themes
+// -------
+.ide.theme-solarized-light {
+ --ide-border-color: #dfd7bf;
+ --ide-border-color-alt: #dfd7bf;
+ --ide-highlight-accent: #5c4e21;
+ --ide-text-color: #616161;
+ --ide-text-color-secondary: #526f76;
+ --ide-background: #efe8d3;
+ --ide-background-hover: #ded6be;
+ --ide-highlight-background: #fef6e1;
+ --ide-link-color: #955800;
+ --ide-footer-background: #efe8d3;
+ --ide-empty-state-background: #fef6e1;
+
+ --ide-input-border: #c0b9a4;
+ --ide-input-background: transparent;
+
+ --ide-btn-default-background: transparent;
+ --ide-btn-default-border: #c0b9a4;
+ --ide-btn-default-hover-border: #c0b9a4;
+
+ --ide-btn-primary-background: #b16802;
+ --ide-btn-primary-border: #a35f00;
+ --ide-btn-primary-hover-border: #955800;
+ --ide-btn-primary-hover-border-width: 2px;
+ --ide-btn-primary-focus-box-shadow: 0 0 0 1px #dd8101;
+
+ --ide-btn-danger-secondary-background: transparent;
+
+ --ide-btn-disabled-background: transparent;
+ --ide-btn-disabled-border: rgba(192, 185, 64, 0.48);
+ --ide-btn-disabled-hover-border: rgba(192, 185, 64, 0.48);
+ --ide-btn-disabled-hover-border-width: 1px;
+ --ide-btn-disabled-focus-box-shadow: transparent;
+ --ide-btn-disabled-color: rgba(82, 82, 82, 0.48);
+
+ --ide-dropdown-background: #fef6e1;
+ --ide-dropdown-hover-background: #efe8d3;
+
+ --ide-dropdown-btn-hover-border: #dfd7bf;
+ --ide-dropdown-btn-hover-background: #efe8d3;
+
+ --ide-file-row-btn-hover-background: #ded6be;
+
+ --ide-animation-gradient-1: #d3cbb3;
+ --ide-animation-gradient-2: #efe8d3;
+
+ .ide-empty-state,
+ .ide-sidebar,
+ .ide-commit-empty-state {
+ img {
+ filter: sepia(1) brightness(0.7);
+ }
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/jira_connect.scss b/app/assets/stylesheets/page_bundles/jira_connect.scss
index b8cdd120e04..c3e49da92a6 100644
--- a/app/assets/stylesheets/page_bundles/jira_connect.scss
+++ b/app/assets/stylesheets/page_bundles/jira_connect.scss
@@ -1,4 +1,6 @@
-@import 'framework/variables';
+@import 'mixins_and_variables_and_functions';
+// We should only import styles that we actually use.
+// @import '@gitlab/ui/src/scss/gitlab_ui';
$atlaskit-border-color: #dfe1e6;
diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss
index 5553dffac05..be74503c21f 100644
--- a/app/assets/stylesheets/page_bundles/merge_requests.scss
+++ b/app/assets/stylesheets/page_bundles/merge_requests.scss
@@ -11,9 +11,19 @@
}
.diff-tree-list {
+ // This 11px value should match the additional value found in
+ // /assets/stylesheets/framework/diffs.scss
+ // for the $mr-file-header-top SCSS variable within the
+ // .file-title,
+ // .file-title-flex-parent {
+ // rule.
+ // If they don't match, the file tree and the diff files stick
+ // to the top at different heights, which is a bad-looking defect
+ $diff-file-header-top: 11px;
+ $top-pos: $header-height + $mr-tabs-height + $mr-version-controls-height + $diff-file-header-top;
+
position: -webkit-sticky;
position: sticky;
- $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/page_bundles/pipeline.scss b/app/assets/stylesheets/page_bundles/pipeline.scss
index 8e7be629481..1de66aa73da 100644
--- a/app/assets/stylesheets/page_bundles/pipeline.scss
+++ b/app/assets/stylesheets/page_bundles/pipeline.scss
@@ -482,3 +482,7 @@
@include build-trace();
}
}
+
+.progress-bar.bg-primary {
+ background-color: $blue-500 !important;
+}
diff --git a/app/assets/stylesheets/page_bundles/pipeline_schedules.scss b/app/assets/stylesheets/page_bundles/pipeline_schedules.scss
new file mode 100644
index 00000000000..412971253ca
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/pipeline_schedules.scss
@@ -0,0 +1,68 @@
+@import 'mixins_and_variables_and_functions';
+
+.pipeline-schedule-form {
+ .gl-field-error {
+ margin: 10px 0 0;
+ }
+}
+
+.interval-pattern-form-group {
+ label {
+ margin-right: 10px;
+ font-weight: $gl-font-weight-normal;
+
+ &[for='custom'] {
+ margin-right: 0;
+ }
+ }
+
+ .cron-interval-input-wrapper {
+ padding-left: 0;
+ }
+
+ .cron-interval-input {
+ margin: 10px 10px 0 0;
+ }
+}
+
+.pipeline-schedule-table-row {
+ .branch-name-cell {
+ max-width: 300px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .next-run-cell {
+ color: var(--gray-500, $gray-500);
+ }
+
+ a {
+ color: var(--gl-text-color, $gl-text-color);
+ }
+
+ svg {
+ vertical-align: middle;
+ }
+}
+
+.pipeline-schedules-user-callout {
+ .bordered-box.content-block {
+ border: 1px solid var(--border-color, $border-color);
+ background-color: transparent;
+ padding: $gl-spacing-scale-5;
+ }
+}
+
+.cron-preset-radio-input {
+ display: inline-block;
+
+ @include media-breakpoint-down(md) {
+ display: block;
+ margin: 0 0 5px 5px;
+ }
+
+ input {
+ margin-right: 3px;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/pipelines.scss b/app/assets/stylesheets/page_bundles/pipelines.scss
index 6ff07017d2e..e0e56893afc 100644
--- a/app/assets/stylesheets/page_bundles/pipelines.scss
+++ b/app/assets/stylesheets/page_bundles/pipelines.scss
@@ -5,6 +5,10 @@
* Pipelines Bundle: Pipeline lists and Mini Pipelines
*/
+.pipelines-container .top-area .nav-controls > .btn:last-child {
+ float: none;
+}
+
// Pipelines list
// Should affect pipelines table components rendered by:
// - app/assets/javascripts/commit/pipelines/pipelines_bundle.js
diff --git a/app/assets/stylesheets/page_bundles/reports.scss b/app/assets/stylesheets/page_bundles/reports.scss
index 5a9dd454970..18ca5f9a3a9 100644
--- a/app/assets/stylesheets/page_bundles/reports.scss
+++ b/app/assets/stylesheets/page_bundles/reports.scss
@@ -8,14 +8,14 @@
.report-block-list-issue-parent {
padding: $gl-padding-top $gl-padding;
- border-top: 1px solid $border-color;
+ border-top: 1px solid var(--border-color, $border-color);
}
}
.report-block-container {
- border-top: 1px solid $border-color;
+ border-top: 1px solid var(--border-color, $border-color);
padding: $gl-padding - 2;
- background-color: $gray-light;
+ background-color: var(--gray-50, $gray-10);
// Clean MR widget CSS
line-height: 20px;
diff --git a/app/assets/stylesheets/page_bundles/signup.scss b/app/assets/stylesheets/page_bundles/signup.scss
new file mode 100644
index 00000000000..9ed48b693b9
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/signup.scss
@@ -0,0 +1,75 @@
+@import 'mixins_and_variables_and_functions';
+
+.signup-page {
+ .devise-errors {
+ h2 {
+ font-size: $gl-font-size;
+ color: var(--red-700, $red-700);
+ }
+ }
+
+ .omniauth-divider {
+ &::before,
+ &::after {
+ content: '';
+ flex: 1;
+ border-bottom: 1px solid var(--gray-100, $gray-100);
+ margin: $gl-padding-24 0;
+ }
+
+ &::before {
+ margin-right: $gl-padding;
+ }
+
+ &::after {
+ margin-left: $gl-padding;
+ }
+ }
+
+ .omniauth-btn {
+ width: 48%;
+
+ @include media-breakpoint-down(md) {
+ width: 100%;
+ }
+
+ img {
+ width: $default-icon-size;
+ height: $default-icon-size;
+ }
+ }
+
+ .decline-page {
+ width: 350px;
+ }
+}
+
+.signup-page[data-page^='registrations:experience_levels'] {
+ $card-shadow-color: rgba(var(--black, $black), 0.2);
+
+ .page-wrap {
+ background-color: var(--white, $white);
+ }
+
+ .card-deck {
+ max-width: 828px;
+ }
+
+ .card {
+ transition: box-shadow 0.3s ease-in-out;
+ }
+
+ .card:hover {
+ box-shadow: 0 $gl-spacing-scale-3 $gl-spacing-scale-5 $card-shadow-color;
+ }
+
+ @media (min-width: $breakpoint-sm) {
+ .card-deck .card {
+ margin: 0 $gl-spacing-scale-3;
+ }
+ }
+
+ .stretched-link:hover {
+ text-decoration: none;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/todos.scss b/app/assets/stylesheets/page_bundles/todos.scss
index 3eec5b53a30..3e20ca9c62f 100644
--- a/app/assets/stylesheets/page_bundles/todos.scss
+++ b/app/assets/stylesheets/page_bundles/todos.scss
@@ -219,7 +219,6 @@
.todos-empty-content {
align-self: center;
max-width: 480px;
- margin-right: 20px;
}
.todos-empty-hero {
diff --git a/app/assets/stylesheets/pages/admin.scss b/app/assets/stylesheets/pages/admin.scss
index f0acb78f731..af1eefd7587 100644
--- a/app/assets/stylesheets/pages/admin.scss
+++ b/app/assets/stylesheets/pages/admin.scss
@@ -8,3 +8,11 @@
.usage-data {
max-height: 400px;
}
+
+[data-page='admin:jobs:index'] {
+ .admin-builds-table {
+ td:last-child {
+ min-width: 120px;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/pages/alert_management/details.scss b/app/assets/stylesheets/pages/alert_management/details.scss
deleted file mode 100644
index 514f228e223..00000000000
--- a/app/assets/stylesheets/pages/alert_management/details.scss
+++ /dev/null
@@ -1,42 +0,0 @@
-.alert-management-details {
- @include media-breakpoint-down(xs) {
- .alert-details-incident-button {
- width: 100%;
- }
- }
-
- .toggle-sidebar-mobile-button {
- right: 0;
- }
-
- .dropdown-menu-toggle {
- &:hover {
- background-color: $white;
- }
- }
-
- .assignee-dropdown-item {
- .dropdown-item {
- display: flex;
- align-items: center;
-
- &::before {
- top: 50% !important;
- }
-
- &.is-active {
- &:last-child {
- border-bottom: 1px solid $gray-100;
- }
- }
- }
- }
-
- .main-notes-list::before {
- left: $gl-spacing-scale-5 !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
deleted file mode 100644
index f58ad87a673..00000000000
--- a/app/assets/stylesheets/pages/alert_management/severity-icons.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-.incident-severity,
-.incident-management-list,
-.alert-management-details {
- .icon-critical {
- color: $red-800;
- }
-
- .icon-high {
- color: $red-600;
- }
-
- .icon-medium {
- color: $orange-400;
- }
-
- .icon-low {
- color: $orange-300;
- }
-
- .icon-info {
- color: $blue-400;
- }
-
- .icon-unknown {
- color: $gray-200;
- }
-}
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
deleted file mode 100644
index d7b4db3840e..00000000000
--- a/app/assets/stylesheets/pages/builds.scss
+++ /dev/null
@@ -1,349 +0,0 @@
-@keyframes fade-out-status {
- 0%,
- 50% {
- opacity: 1;
- }
-
- 100% {
- opacity: 0;
- }
-}
-
-@keyframes blinking-dot {
- 0% {
- opacity: 1;
- }
-
- 25% {
- opacity: 0.4;
- }
-
- 75% {
- opacity: 0.4;
- }
-
- 100% {
- opacity: 1;
- }
-}
-
-@keyframes blinking-scroll-button {
- 0% {
- opacity: 0.2;
- }
-
- 50% {
- opacity: 1;
- }
-
- 100% {
- opacity: 0.2;
- }
-}
-
-.build-page {
- .build-trace {
- @include build-trace();
- }
-
- .archived-job {
- top: $header-height;
- border-radius: 2px 2px 0 0;
- color: $orange-600;
- background-color: $orange-50;
- border: 1px solid $border-gray-normal;
- padding: 3px 12px;
- margin: auto;
- align-items: center;
- z-index: 1;
-
- .with-performance-bar & {
- top: $header-height + $performance-bar-height;
- }
- }
-
- .top-bar {
- @include build-trace-top-bar(50px);
-
- &.has-archived-block {
- top: $header-height + 28px;
-
- .with-performance-bar & {
- top: $header-height + $performance-bar-height + 28px;
- }
- }
-
- &.affix {
- top: $header-height;
-
- // with sidebar
- &.sidebar-expanded {
- right: 306px;
- left: 16px;
- }
-
- // without sidebar
- &.sidebar-collapsed {
- right: 16px;
- left: 16px;
- }
- }
-
- &.affix-top {
- position: absolute;
- right: 0;
- left: 0;
- top: 0;
- }
-
- .controllers {
- @include build-controllers(15px, center, false, 0, inline, 0);
- }
- }
-
- .environment-information {
- border: 1px solid $border-color;
- padding: 8px $gl-padding 12px;
- border-radius: $border-radius-default;
-
- svg {
- position: relative;
- top: 3px;
- margin-right: 5px;
- width: 22px;
- height: 22px;
- }
- }
-
- .build-loader-animation {
- @include build-loader-animation;
- float: left;
- padding-left: $gl-padding-8;
- }
-}
-
-.build-header {
- .page-content-header {
- padding: 10px 0 9px;
- }
-
- .header-action-buttons {
- display: flex;
-
- @include media-breakpoint-down(xs) {
- .sidebar-toggle-btn {
- margin-top: 0;
- margin-left: 10px;
- max-height: 34px;
- }
- }
- }
-
- .header-content {
- a {
- color: $gl-text-color;
-
- &:hover {
- color: $blue-600;
- text-decoration: none;
- }
- }
- }
-
- code {
- color: $code-color;
- }
-
- .avatar {
- float: none;
- margin-right: 2px;
- margin-left: 2px;
- }
-}
-
-.right-sidebar.build-sidebar {
- padding: 0;
-
- &.right-sidebar-collapsed {
- display: none;
- }
-
- .sidebar-container {
- padding-right: 100px;
- height: 100%;
- overflow-y: scroll;
- overflow-x: hidden;
- -webkit-overflow-scrolling: touch;
- }
-
- .blocks-container {
- padding: 0 $gl-padding;
- width: 289px;
- }
-
- .block {
- width: 100%;
- word-break: break-word;
-
- &:last-child {
- border-bottom: 1px solid $border-gray-normal;
- }
-
- &.coverage {
- padding: 0 16px 11px;
- }
- }
-
- .block-last {
- padding: 16px 0;
- }
-
- .trigger-variables-btn-container {
- justify-content: space-between;
- align-items: center;
-
- .trigger-variables-btn {
- margin-top: -5px;
- margin-bottom: -5px;
- }
- }
-
- .trigger-build-variables {
- margin: 0;
- overflow-x: auto;
- width: 100%;
- -ms-overflow-style: scrollbar;
- -webkit-overflow-scrolling: touch;
- }
-
- .trigger-build-variable {
- font-weight: $gl-font-weight-normal;
- color: $code-color;
- }
-
- .trigger-build-value {
- padding: 2px 4px;
- color: $black;
- }
-
- .trigger-variables-table-cell {
- font-size: $gl-font-size-small;
- line-height: $gl-line-height;
- border: 1px solid $gray-100;
- padding: $gl-padding-4 6px;
- width: 50%;
- vertical-align: top;
- }
-
- .badge.badge-pill {
- margin-left: 2px;
- }
-
- .retry-link {
- display: block;
-
- .btn-inverted-secondary {
- color: $blue-500;
-
- &:hover {
- color: $white;
- }
- }
- }
-
- .stage-item {
- cursor: pointer;
-
- &:hover {
- color: $gl-text-color;
- }
- }
-
- .builds-container {
- background-color: $white;
- border-top: 1px solid $border-color;
- border-bottom: 1px solid $border-color;
- max-height: 300px;
- width: 289px;
- overflow: auto;
-
- svg {
- margin-right: 3px;
- height: 14px;
- width: 14px;
- }
-
- a {
- padding: $gl-padding 10px $gl-padding 40px;
- width: 270px;
-
- &:hover {
- color: $gl-text-color;
- }
- }
-
- .icon-arrow-right {
- left: 15px;
- top: 20px;
- }
-
- .build-job {
- &.active {
- font-weight: $gl-font-weight-bold;
- }
-
- &.retried {
- background-color: $gray-lightest;
- }
-
- &:hover {
- background-color: $gray-darker;
- }
- }
- }
-
- .link-commit {
- color: $blue-600;
- }
-}
-
-.build-sidebar {
- .container-fluid.container-limited {
- max-width: 100%;
- }
-
- .content-wrapper {
- padding-bottom: 6px;
- }
-}
-
-.build-detail-row {
- margin-bottom: 5px;
-
- &:last-of-type {
- margin-bottom: 0;
- }
-}
-
-.build-light-text {
- color: $gl-text-color-secondary;
- word-wrap: break-word;
-}
-
-.build-gutter-toggle {
- position: absolute;
- top: 50%;
- right: 0;
- margin-top: -17px;
-}
-
-@include media-breakpoint-down(sm) {
- .top-bar {
- .truncated-info {
- white-space: nowrap;
- overflow: hidden;
- max-width: 220px;
- text-overflow: ellipsis;
- }
- }
-}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index c55bfeb7b15..17474b95e50 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -14,12 +14,6 @@
@extend %commit-description-base;
}
-.js-details-expand {
- &:hover {
- text-decoration: none;
- }
-}
-
.commit-box {
border-top: 1px solid $border-color;
padding: $gl-padding 0;
@@ -30,17 +24,6 @@
}
}
-.commit-hash-full {
- @include media-breakpoint-down(sm) {
- width: 80px;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- display: inline-block;
- vertical-align: bottom;
- }
-}
-
.pipeline-info {
.status-icon-container {
display: inline-block;
@@ -225,9 +208,9 @@
display: inline-flex;
.label,
- .btn {
+ .btn:not(.gl-button) {
padding: $gl-vert-padding $gl-btn-padding;
- border: 1px $border-color solid;
+ border: 1px $gray-200 solid;
font-size: $gl-font-size;
line-height: $line-height-base;
border-radius: 0;
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index 9f9964ac447..5c845c37e90 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -8,18 +8,18 @@
background: $gray-normal;
}
- #editor {
- border: 0;
- border-radius: 0;
+ #editor,
+ .editor {
+ @include gl-border-0;
+ @include gl-m-0;
+ @include gl-p-0;
+ @include gl-relative;
+ @include gl-w-full;
height: 500px;
- margin: 0;
- padding: 0;
- position: relative;
- width: 100%;
.editor-loading-content {
- height: 100%;
- border: 0;
+ @include gl-h-full;
+ @include gl-border-0;
}
}
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index ee4f74882a1..e73b6b18afd 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -43,12 +43,6 @@
}
}
-.ldap-group-links {
- .form-actions {
- margin-bottom: $gl-padding;
- }
-}
-
.save-group-loader {
margin-top: $gl-padding-50;
margin-bottom: $gl-padding-50;
@@ -343,11 +337,11 @@ table.pipeline-project-metrics tr td {
}
.user-access-role {
+ @include gl-px-3;
display: inline-block;
color: $gl-text-color-secondary;
font-size: 12px;
line-height: 20px;
- padding: 0 $label-padding;
border: 1px solid $border-color;
border-radius: $label-border-radius;
font-weight: $gl-font-weight-normal;
diff --git a/app/assets/stylesheets/pages/incident_management_list.scss b/app/assets/stylesheets/pages/incident_management_list.scss
index c0a1fa72b1f..ba363e2d119 100644
--- a/app/assets/stylesheets/pages/incident_management_list.scss
+++ b/app/assets/stylesheets/pages/incident_management_list.scss
@@ -8,13 +8,12 @@
@include gl-text-gray-500;
tbody {
- tr:not(.b-table-busy-slot) {
- // TODO replace with gitlab/ui utilities: https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1791
+ tr:not(.b-table-busy-slot):not(.b-table-empty-row) {
&:hover {
- border-top-style: double;
+ @include gl-border-t-double;
td {
- border-bottom-style: initial;
+ @include gl-border-b-initial;
}
}
}
@@ -22,7 +21,7 @@
tr {
&:focus {
- outline: none;
+ @include gl-outline-none;
}
td,
@@ -118,26 +117,34 @@
}
.gl-tabs-nav {
- border-bottom-width: 0;
+ @include gl-border-b-0;
.gl-tab-nav-item {
- color: $gray-500;
+ @include gl-text-gray-500;
> .gl-tab-counter-badge {
- color: inherit;
+ @include gl-reset-color;
@include gl-font-sm;
- background-color: $gray-50;
+ @include gl-bg-gray-50;
}
}
}
@include media-breakpoint-down(xs) {
.list-header {
- flex-direction: column-reverse;
+ @include gl-flex-direction-column-reverse;
}
.create-incident-button {
@include gl-w-full;
}
}
+
+ .integration-list {
+ .b-table-empty-row {
+ td {
+ @include gl-px-0;
+ }
+ }
+ }
}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 7097c2b10c4..cc4827f75d4 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -1,16 +1,12 @@
.issuable-warning-icon {
background-color: $orange-50;
border-radius: $border-radius-default;
+ color: $orange-600;
width: $issuable-warning-size;
height: $issuable-warning-size;
text-align: center;
margin-right: $issuable-warning-icon-margin;
line-height: $gl-line-height-24;
-
- .icon {
- fill: $orange-600;
- vertical-align: text-bottom;
- }
}
.limit-container-width {
@@ -77,14 +73,6 @@
}
}
-.issuable-filter-count {
- span {
- display: block;
- margin-bottom: -16px;
- padding: 13px 0;
- }
-}
-
.issuable-show-labels {
.gl-label {
margin-bottom: 5px;
@@ -662,12 +650,6 @@
}
}
-.issuable-form-padding-top {
- @include media-breakpoint-up(sm) {
- padding-top: 7px;
- }
-}
-
.issuable-status-box {
align-self: stretch;
display: flex;
@@ -822,11 +804,7 @@
}
}
-.time_tracker {
- padding-bottom: 0;
- border-bottom: 0;
-
-
+.time-tracker {
.sidebar-collapsed-icon {
> .stopwatch-svg {
display: inline-block;
@@ -939,6 +917,25 @@
}
}
+/*
+ * Following overrides are done to prevent
+ * legacy dropdown styles from influencing
+ * GitLab UI components used within GlDropdown
+ */
+.issuable-move-dropdown {
+ .b-dropdown-form {
+ @include gl-p-0;
+ }
+
+ .gl-search-box-by-type button.gl-clear-icon-button:hover {
+ @include gl-bg-transparent;
+ }
+
+ .issuable-move-button:not(.disabled):hover {
+ @include gl-text-white;
+ }
+}
+
.right-sidebar-collapsed {
.sidebar-grouped-item {
.sidebar-collapsed-icon {
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index d2eb00c4a4d..08faebc8ec0 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -67,7 +67,6 @@ ul.related-merge-requests > li {
}
}
-.merge-request-ci-status,
.related-merge-requests {
.ci-status-link {
display: block;
@@ -93,11 +92,6 @@ ul.related-merge-requests > li {
}
}
-.issues-footer {
- padding-top: $gl-padding;
- padding-bottom: 37px;
-}
-
.issues-nav-controls,
.new-branch-col {
font-size: 0;
@@ -194,6 +188,12 @@ ul.related-merge-requests > li {
border-width: 1px;
line-height: $line-height-base;
width: auto;
+
+ &.disabled {
+ background-color: $gray-light;
+ border-color: $gray-100;
+ color: $gl-text-color-disabled;
+ }
}
}
diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss
index 31606cb3ba5..4d93702f1c2 100644
--- a/app/assets/stylesheets/pages/labels.scss
+++ b/app/assets/stylesheets/pages/labels.scss
@@ -92,13 +92,8 @@
margin-bottom: 0;
}
- &.sortable-ghost {
- opacity: 0.3;
- }
-
.prioritized-labels:not(.is-not-draggable) & {
box-shadow: 0 1px 2px $issue-boards-card-shadow;
- cursor: move;
cursor: grab;
border: 0;
@@ -108,126 +103,20 @@
}
}
- .btn-action {
- .fa {
- font-size: 18px;
- vertical-align: middle;
- pointer-events: none;
- }
-
- &:hover {
- color: $blue-600;
-
- &.remove-row {
- color: $red-500;
- }
- }
- }
-
- .color-label {
- padding: $gl-padding-4 $grid-size;
- }
-
.prepend-description-left {
vertical-align: top;
line-height: 24px;
}
}
-.prioritized-labels {
- margin-bottom: 30px;
-
- .add-priority {
- display: none;
- color: $gray-light;
- }
-
- li:hover {
- .draggable-handler {
- display: inline-block;
- opacity: 1;
- }
- }
-}
-
-.other-labels {
- .remove-priority {
- display: none;
- }
-}
-
-.filtered-labels {
- font-size: 0;
- padding: 12px 16px;
-
- .label-row {
- margin-top: 4px;
- margin-bottom: 4px;
-
- &:not(:last-child) {
- margin-right: 8px;
- }
- }
-
- .label-remove {
- border-left: 1px solid $label-remove-border;
- z-index: 3;
- border-radius: $label-border-radius;
- padding: 6px 10px 6px 9px;
-
- &:hover {
- box-shadow: inset 0 0 0 80px $label-remove-border;
- }
- }
-
- .btn {
- color: inherit;
- }
-
- a.btn {
- padding: 0;
-
- .has-tooltip {
- top: 0;
- border-top-right-radius: 0;
- border-bottom-right-radius: 0;
- line-height: 1.1;
- }
- }
-}
-
-.label-subscription {
- vertical-align: middle;
-
- .dropdown-group-label a {
- cursor: pointer;
- }
+.prioritized-labels .add-priority,
+.other-labels .remove-priority {
+ display: none;
}
.label-subscribe-button {
width: 105px;
font-weight: 200;
-
- .label-subscribe-button-icon {
- &[disabled] {
- opacity: 0.5;
- pointer-events: none;
- }
- }
-
- .label-subscribe-button-loading {
- display: none;
- }
-
- &.disabled {
- .label-subscribe-button-icon {
- display: none;
- }
-
- .label-subscribe-button-loading {
- display: block;
- }
- }
}
.labels-container {
@@ -255,11 +144,6 @@
}
.label-list-item {
- .content-list &::before,
- .content-list &::after {
- content: none;
- }
-
.label-name {
width: 200px;
@@ -268,37 +152,16 @@
}
}
- .label {
- padding: 4px $grid-size;
- font-size: $label-font-size;
- position: relative;
- top: $gl-padding-4;
- }
-
.label-action {
color: $gray-700;
cursor: pointer;
- svg {
- fill: $gray-700;
- }
-
&:hover {
color: $blue-600;
-
- svg {
- fill: $blue-600;
- }
}
- &.remove-row {
- &:hover {
- color: $red-500;
-
- svg {
- fill: $red-500;
- }
- }
+ &.remove-row:hover {
+ color: $red-500;
}
}
}
diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss
index 922f95ff5df..a8b489f1273 100644
--- a/app/assets/stylesheets/pages/members.scss
+++ b/app/assets/stylesheets/pages/members.scss
@@ -225,9 +225,14 @@
}
.col-actions {
- width: px-to-rem(50px);
+ width: px-to-rem(65px);
}
}
+
+ .gl-datepicker-input {
+ width: px-to-rem(165px);
+ max-width: 100%;
+ }
}
.card-mobile {
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 6f71177e870..a0ac55e4c6c 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -463,8 +463,7 @@ $mr-widget-min-height: 69px;
.mr-list {
.merge-request {
- padding: 10px 0 10px 15px;
- position: relative;
+ padding: 10px $gl-padding;
display: flex;
.issuable-info-container {
@@ -737,14 +736,6 @@ $mr-widget-min-height: 69px;
border-bottom: 0;
}
- .comments-disabled-notif {
- line-height: 28px;
-
- .btn {
- margin-left: 5px;
- }
- }
-
.mr-version-dropdown,
.mr-version-compare-dropdown {
margin: 0 7px;
@@ -1048,9 +1039,3 @@ $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/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index 8b3d3268a8c..0c24ea9ccc6 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -2,6 +2,7 @@
* Note Form
*/
.diff-file .diff-content {
+ .diff-tr.line_holder:hover > .diff-td .line_note_link,
tr.line_holder:hover > td .line_note_link {
opacity: 1;
filter: alpha(opacity = 100);
@@ -226,10 +227,6 @@ table {
display: none;
}
-.parallel-comment {
- padding: 6px;
-}
-
.error-alert > .alert {
margin-top: 5px;
margin-bottom: 5px;
@@ -311,31 +308,12 @@ table {
}
}
-.discussion-notes-count {
- font-size: 16px;
-}
-
-.edit_note {
- .markdown-area {
- min-height: 140px;
- max-height: 500px;
- }
-
- .note-form-actions {
- background: transparent;
- }
-}
-
.comment-toolbar {
padding-top: $gl-padding-top;
color: $gl-text-color-secondary;
border-top: 1px solid $border-color;
}
-.md-helper {
- padding-top: 10px;
-}
-
.toolbar-button {
padding: 0;
background: none;
@@ -473,31 +451,6 @@ table {
margin-right: 5px;
}
-.attach-new-file,
-.button-attach-file,
-.retry-uploading-link {
- color: $blue-600;
- padding: 0;
- background: none;
- border: 0;
- font-size: 14px;
- line-height: 16px;
- vertical-align: initial;
-
- &:hover,
- &:focus {
- text-decoration: none;
-
- .text-attach-file {
- text-decoration: underline;
- }
- }
-
- .gl-icon:not(:last-child) {
- margin-right: 0;
- }
-}
-
.markdown-selector {
color: $blue-600;
}
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index b510822a20a..e23ec25a2f3 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -453,6 +453,8 @@ $note-form-margin-left: 72px;
}
.diff-file {
+ .diff-grid-left:hover,
+ .diff-grid-right:hover,
.is-over {
.add-diff-note {
display: inline-flex;
@@ -490,6 +492,7 @@ $note-form-margin-left: 72px;
.notes_holder {
font-family: $regular-font;
+ .diff-td,
td {
border: 1px solid $border-color;
border-left: 0;
@@ -798,21 +801,15 @@ $note-form-margin-left: 72px;
}
.note-role {
- margin: 0 3px;
-}
-
-.note-role-special {
- position: relative;
- display: inline-block;
- color: $gl-text-color-secondary;
- font-size: 12px;
- text-shadow: 0 0 15px $gl-text-color-inverted;
+ margin: 0 8px;
}
/**
* Line note button on the side of diffs
*/
+.diff-grid-left:hover,
+.diff-grid-right:hover,
.line_holder .is-over:not(.no-comment-btn) {
.add-diff-note {
opacity: 1;
@@ -895,6 +892,15 @@ $note-form-margin-left: 72px;
outline: 0;
transition: color $general-hover-transition-duration $general-hover-transition-curve;
+ &[disabled] {
+ padding: 0 8px !important;
+ box-shadow: none !important;
+
+ .gl-button-loading-indicator {
+ margin-right: 0 !important;
+ }
+ }
+
&.is-disabled {
cursor: default;
}
@@ -902,16 +908,22 @@ $note-form-margin-left: 72px;
&:not(.is-disabled) {
&:hover,
&:focus {
- color: $green-600;
+ svg {
+ color: $green-600;
+ }
}
}
&.is-active {
- color: $green-600;
+ svg {
+ @include gl-text-green-500;
+ }
&:hover,
&:focus {
- color: $green-700;
+ svg {
+ color: $green-700;
+ }
}
}
diff --git a/app/assets/stylesheets/pages/pipeline_schedules.scss b/app/assets/stylesheets/pages/pipeline_schedules.scss
deleted file mode 100644
index 81716991a36..00000000000
--- a/app/assets/stylesheets/pages/pipeline_schedules.scss
+++ /dev/null
@@ -1,70 +0,0 @@
-.pipeline-schedule-form {
- .gl-field-error {
- margin: 10px 0 0;
- }
-}
-
-.interval-pattern-form-group {
- label {
- margin-right: 10px;
- font-weight: $gl-font-weight-normal;
-
- &[for='custom'] {
- margin-right: 0;
- }
- }
-
- .cron-interval-input-wrapper {
- padding-left: 0;
- }
-
- .cron-interval-input {
- margin: 10px 10px 0 0;
- }
-}
-
-.pipeline-schedule-table-row {
- .branch-name-cell {
- max-width: 300px;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-
- .next-run-cell {
- color: $gl-text-color-secondary;
- }
-
- a {
- color: $text-color;
- }
-
- svg {
- vertical-align: middle;
- }
-}
-
-.pipeline-schedules-user-callout {
- .bordered-box.content-block {
- border: 1px solid $border-color;
- background-color: transparent;
- padding: 16px;
- }
-
- #dismiss-callout-btn {
- color: $gl-text-color;
- }
-}
-
-.cron-preset-radio-input {
- display: inline-block;
-
- @include media-breakpoint-down(md) {
- display: block;
- margin: 0 0 5px 5px;
- }
-
- input {
- margin-right: 3px;
- }
-}
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index 2df43b861b2..b37aa6cd285 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -1,11 +1,17 @@
-@include media-breakpoint-down(md) {
- .content-list {
- &.builds-content-list {
- width: 100%;
- overflow: auto;
- }
- }
-}
+/**
+ * !! NOTE: Do not add more code in this file:
+ *
+ * https://gitlab.com/gitlab-org/gitlab/-/issues/267602
+ *
+ * For new pipeline CSS please consider:
+ *
+ * For pipelines tables and lists:
+ * - `app/assets/stylesheets/page_bundles/pipelines.scss`
+ *
+ * For individual pipelines and mini-pipelines:
+ * - `app/assets/stylesheets/page_bundles/pipeline.scss`
+ *
+**/
.ci-table {
.avatar {
@@ -81,38 +87,13 @@
}
}
-[data-page='admin:jobs:index'] {
- .admin-builds-table {
- td:last-child {
- min-width: 120px;
+@include media-breakpoint-down(sm) {
+ .top-bar {
+ .truncated-info {
+ white-space: nowrap;
+ overflow: hidden;
+ max-width: 220px;
+ text-overflow: ellipsis;
}
}
}
-
-.pipelines-container .top-area .nav-controls > .btn:last-child {
- float: none;
-}
-
-.progress-bar.bg-primary {
- background-color: $blue-500 !important;
-}
-
-.pipeline-stage-pill {
- width: 10rem;
-}
-
-.pipeline-job-pill {
- width: 8rem;
-}
-
-.stage-rounded {
- border-radius: 2rem;
-}
-
-.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/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 938d8d34717..09501d3713d 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -252,15 +252,6 @@
}
}
-.split-one {
- display: inline-table;
- margin-right: 12px;
-
- > a {
- margin: -1px;
- }
-}
-
.save-project-loader {
margin-top: 50px;
margin-bottom: 50px;
@@ -505,92 +496,6 @@
}
}
-.create-project-options {
- display: flex;
-
- @include media-breakpoint-down(xs) {
- display: block;
- }
-
- .first-column {
- @include media-breakpoint-up(xs) {
- max-width: 50%;
- padding-right: 30px;
- }
-
- @include media-breakpoint-down(xs) {
- max-width: 100%;
- width: 100%;
- }
- }
-
- .second-column {
- @include media-breakpoint-up(xs) {
- width: 50%;
- flex: 1;
- padding-left: 30px;
- position: relative;
- }
-
- @include media-breakpoint-down(xs) {
- max-width: 100%;
- width: 100%;
- padding-left: 0;
- position: relative;
- }
-
- // Mobile
- @include media-breakpoint-down(xs) {
- padding-top: 30px;
- }
-
- &::before {
- content: 'OR';
- position: absolute;
- left: -10px;
- top: 50%;
- z-index: 10;
- padding: $gl-padding-8 0;
- text-align: center;
- background-color: $white;
- color: $gl-text-color-tertiary;
- transform: translateY(-50%);
- font-size: 12px;
- font-weight: $gl-font-weight-bold;
- line-height: 20px;
-
- // Mobile
- @include media-breakpoint-down(xs) {
- left: 50%;
- top: 0;
- transform: translateX(-50%);
- padding: 0 $gl-padding-8;
- }
- }
-
- &::after {
- content: '';
- position: absolute;
- background-color: $border-color;
- bottom: 0;
- left: 0;
- right: auto;
- height: 100%;
- width: 1px;
- top: 0;
-
- // Mobile
- @include media-breakpoint-down(xs) {
- top: 10px;
- left: 10px;
- right: 10px;
- height: 1px;
- width: auto;
- }
- }
- }
-}
-
.project-stats,
.project-buttons {
.scrolling-tabs-container {
@@ -754,17 +659,6 @@ pre.light-well {
}
}
-.project-footer {
- margin-top: 20px;
-
- .btn-remove {
- @include btn-middle;
- @include btn-red;
-
- float: left !important;
- }
-}
-
/*
* Projects list rendered on dashboard and user page
*/
@@ -1059,24 +953,6 @@ pre.light-well {
}
}
-.cannot-be-merged,
-.cannot-be-merged:hover {
- color: $red-500;
- margin-top: 2px;
- position: relative;
- z-index: 2;
-}
-
-.private-forks-notice .private-fork-icon {
- i:nth-child(1) {
- color: $green-600;
- }
-
- i:nth-child(2) {
- color: $white;
- }
-}
-
.new-protected-branch,
.new-protected-tag {
label {
@@ -1117,23 +993,6 @@ pre.light-well {
}
}
-.custom-notifications-form {
- .is-loading {
- .custom-notification-event-loading {
- display: inline-block;
- }
- }
-}
-
-.custom-notification-event-loading {
- display: none;
- margin-left: 5px;
-
- &.is-done {
- color: $green-600;
- }
-}
-
.project-refs-form .dropdown-menu,
.dropdown-menu-projects {
width: 300px;
@@ -1233,34 +1092,6 @@ pre.light-well {
}
}
-.variables-table {
- table-layout: fixed;
-
- &.table-responsive {
- border: 0;
- }
-
- .variable-key {
- max-width: 120px;
- overflow: hidden;
- word-wrap: break-word;
- white-space: nowrap;
- text-overflow: ellipsis;
- }
-
- .variable-value {
- max-width: 150px;
- overflow: hidden;
- word-wrap: break-word;
- white-space: nowrap;
- text-overflow: ellipsis;
- }
-
- .variable-menu {
- text-align: right;
- }
-}
-
.services-installation-info .row {
margin-bottom: 10px;
}
@@ -1286,18 +1117,6 @@ pre.light-well {
padding-bottom: 37px;
}
-.project-ci-body {
- .incorrect-syntax {
- font-size: 18px;
- color: $red-500;
- }
-
- .correct-syntax {
- font-size: 18px;
- color: $green-500;
- }
-}
-
.project-ci-linter {
.ci-editor {
height: 400px;
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index a62e28a9b8a..502a1881fd2 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -270,7 +270,8 @@ input[type='checkbox']:hover {
width: 100%;
}
- .dropdown-menu-toggle {
+ .dropdown-menu-toggle,
+ .gl-new-dropdown {
@include media-breakpoint-up(lg) {
width: 240px;
}
diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss
deleted file mode 100644
index b37c5172ad2..00000000000
--- a/app/assets/stylesheets/pages/status.scss
+++ /dev/null
@@ -1,77 +0,0 @@
-.ci-status {
- padding: 2px 7px 4px;
- border: 1px solid $gray-darker;
- white-space: nowrap;
- border-radius: 4px;
-
- &:hover,
- &:focus {
- text-decoration: none;
- }
-
- svg {
- height: 13px;
- width: 13px;
- overflow: visible;
- }
-
- &.ci-failed {
- @include status-color($red-100, $red-500, $red-600);
- }
-
- &.ci-success {
- @include green-status-color;
- }
-
- &.ci-canceled,
- &.ci-disabled,
- &.ci-scheduled,
- &.ci-manual {
- color: $gl-text-color;
- border-color: $gl-text-color;
-
- &:not(span):hover {
- background-color: rgba($gl-text-color, 0.07);
- }
- }
-
- &.ci-preparing {
- @include status-color($gray-100, $gray-300, $gray-400);
- }
-
- &.ci-pending,
- &.ci-waiting-for-resource,
- &.ci-failed-with-warnings,
- &.ci-success-with-warnings {
- @include status-color($orange-50, $orange-500, $orange-700);
- }
-
- &.ci-info,
- &.ci-running {
- @include status-color($blue-100, $blue-500, $blue-600);
- }
-
- &.ci-created,
- &.ci-skipped {
- color: $gl-text-color-secondary;
- border-color: $gl-text-color-secondary;
-
- &:not(span):hover {
- background-color: rgba($gl-text-color-secondary, 0.07);
- }
- }
-}
-
-.d-block.d-sm-none-inline {
- .ci-status-link {
- position: relative;
- top: 2px;
- left: 5px;
- }
-}
-
-.ci-status-link {
- svg {
- overflow: visible;
- }
-}
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index 73fe76f139f..429181c2ad4 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -62,7 +62,7 @@
.tree-controls {
margin-bottom: 10px;
- .btn,
+ .btn:not(.dropdown-toggle-split),
.dropdown,
.btn-group {
width: 100%;
diff --git a/app/assets/stylesheets/pages/users.scss b/app/assets/stylesheets/pages/users.scss
index 0863b573f75..917d16a9c53 100644
--- a/app/assets/stylesheets/pages/users.scss
+++ b/app/assets/stylesheets/pages/users.scss
@@ -51,43 +51,6 @@
outline: 0;
}
-.flex-users-panel {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: center;
-
- @include media-breakpoint-down(sm) {
- display: block;
-
- .flex-project-title {
- vertical-align: top;
- display: inline-block;
- max-width: 90%;
- }
- }
-
- .flex-project-title {
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- }
-
- .badge.badge-pill {
- height: 17px;
- line-height: 16px;
- margin-right: 5px;
- padding-top: 1px;
- padding-bottom: 1px;
- }
-
- .flex-users-form {
- flex-wrap: nowrap;
- white-space: nowrap;
- margin-left: auto;
- }
-}
-
.content-list.members-list li {
display: flex;
justify-content: space-between;
diff --git a/app/assets/stylesheets/performance_bar.scss b/app/assets/stylesheets/performance_bar.scss
index dc127cd2554..c6c9f3b7365 100644
--- a/app/assets/stylesheets/performance_bar.scss
+++ b/app/assets/stylesheets/performance_bar.scss
@@ -6,7 +6,7 @@
left: 0;
top: 0;
width: 100%;
- z-index: #{$zindex-modal-backdrop + 1};
+ z-index: #{$zindex-modal-backdrop - 1};
height: $performance-bar-height;
background: $black;
diff --git a/app/assets/stylesheets/print.scss b/app/assets/stylesheets/print.scss
index 9ed1600419d..7b66b61ff36 100644
--- a/app/assets/stylesheets/print.scss
+++ b/app/assets/stylesheets/print.scss
@@ -31,7 +31,7 @@ nav.navbar-collapse.collapse,
.nav,
.btn,
ul.notes-form,
-.merge-request-ci-status .ci-status-link::after,
+.ci-status-link::after,
.issuable-gutter-toggle,
.gutter-toggle,
.issuable-details .content-block-small,
diff --git a/app/assets/stylesheets/themes/_dark.scss b/app/assets/stylesheets/themes/_dark.scss
index 66cc4452858..6ab02bd5e27 100644
--- a/app/assets/stylesheets/themes/_dark.scss
+++ b/app/assets/stylesheets/themes/_dark.scss
@@ -201,6 +201,15 @@ $line-removed-dark: $red-200;
// Misc component overrides that should live elsewhere
.gl-label {
filter: brightness(0.9) contrast(1.1);
+
+ // This applies to the gl-label markups
+ // rendered and cached in the backend (labels_helper.rb)
+ &.gl-label-scoped {
+ .gl-label-text-scoped,
+ .gl-label-close {
+ color: $gray-900;
+ }
+ }
}
// white-ish text for light labels
@@ -210,6 +219,15 @@ $line-removed-dark: $red-200;
color: $gray-900;
}
+// This applies to "gl-labels" from "gitlab-ui"
+.gl-label.gl-label-scoped.gl-label-text-dark,
+.gl-label.gl-label-scoped.gl-label-text-light {
+ .gl-label-text-scoped,
+ .gl-label-close {
+ color: $gray-900;
+ }
+}
+
// duplicated class as the original .atwho-view style is added later
.atwho-view.atwho-view {
background-color: $white;
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index e236c264f5c..a3bb7c868df 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -122,3 +122,10 @@
margin-left: $gl-spacing-scale-3;
}
}
+
+// This is used to help prevent issues with margin collapsing.
+// See https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing.
+.gl-force-block-formatting-context::after {
+ content: '';
+ display: flex;
+}
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 786ba73a96f..56ec10fa43a 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -53,7 +53,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def integrations
return not_found unless instance_level_integrations?
- @integrations = Service.find_or_initialize_all(Service.for_instance).sort_by(&:title)
+ @integrations = Service.find_or_initialize_all_non_project_specific(Service.for_instance).sort_by(&:title)
end
def update
@@ -216,10 +216,10 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
remove_blank_params_for!(:elasticsearch_aws_secret_access_key, :eks_secret_access_key)
- # TODO Remove domain_blacklist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204)
- params.delete(:domain_blacklist_raw) if params[:domain_blacklist_file]
- params.delete(:domain_blacklist_raw) if params[:domain_blacklist]
- params.delete(:domain_whitelist_raw) if params[:domain_whitelist]
+ # TODO Remove domain_denylist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204)
+ params.delete(:domain_denylist_raw) if params[:domain_denylist_file]
+ params.delete(:domain_denylist_raw) if params[:domain_denylist]
+ params.delete(:domain_allowlist_raw) if params[:domain_allowlist]
params.require(:application_setting).permit(
visible_application_setting_attributes
@@ -240,7 +240,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
*ApplicationSetting.repository_storages_weighted_attributes,
:lets_encrypt_notification_email,
:lets_encrypt_terms_of_service_accepted,
- :domain_blacklist_file,
+ :domain_denylist_file,
:raw_blob_request_limit,
:issues_create_limit,
:default_branch_name,
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb
index 7d981d67840..33a8cc4ae42 100644
--- a/app/controllers/admin/dashboard_controller.rb
+++ b/app/controllers/admin/dashboard_controller.rb
@@ -16,6 +16,7 @@ class Admin::DashboardController < Admin::ApplicationController
@groups = Group.order_id_desc.with_route.limit(10)
@notices = Gitlab::ConfigChecker::PumaRuggedChecker.check
@notices += Gitlab::ConfigChecker::ExternalDatabaseChecker.check
+ @redis_versions = [Gitlab::Redis::Queues, Gitlab::Redis::SharedState, Gitlab::Redis::Cache].map(&:version).uniq
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/controllers/admin/instance_statistics_controller.rb b/app/controllers/admin/instance_statistics_controller.rb
index dfbd704cb0c..05a0a1ce314 100644
--- a/app/controllers/admin/instance_statistics_controller.rb
+++ b/app/controllers/admin/instance_statistics_controller.rb
@@ -13,6 +13,6 @@ class Admin::InstanceStatisticsController < Admin::ApplicationController
end
def check_feature_flag
- render_404 unless Feature.enabled?(:instance_statistics)
+ render_404 unless Feature.enabled?(:instance_statistics, default_enabled: true)
end
end
diff --git a/app/controllers/admin/integrations_controller.rb b/app/controllers/admin/integrations_controller.rb
index 9a1d5a11f7f..aab8705f5cb 100644
--- a/app/controllers/admin/integrations_controller.rb
+++ b/app/controllers/admin/integrations_controller.rb
@@ -8,8 +8,8 @@ class Admin::IntegrationsController < Admin::ApplicationController
private
- def find_or_initialize_integration(name)
- Service.find_or_initialize_integration(name, instance: true)
+ def find_or_initialize_non_project_specific_integration(name)
+ Service.find_or_initialize_non_project_specific_integration(name, instance: true)
end
def integrations_enabled?
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index bd7b69384b2..2d0bb0bfebc 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -6,7 +6,6 @@ class Admin::UsersController < Admin::ApplicationController
before_action :user, except: [:index, :new, :create]
before_action :check_impersonation_availability, only: :impersonate
before_action :ensure_destroy_prerequisites_met, only: [:destroy]
- before_action :check_admin_approval_feature_available!, only: [:approve]
feature_category :users
@@ -298,10 +297,6 @@ class Admin::UsersController < Admin::ApplicationController
def log_impersonation_event
Gitlab::AppLogger.info(_("User %{current_user_username} has started impersonating %{username}") % { current_user_username: current_user.username, username: user.username })
end
-
- def check_admin_approval_feature_available!
- access_denied! unless Feature.enabled?(:admin_approval_for_new_user_signups, default_enabled: true)
- end
end
Admin::UsersController.prepend_if_ee('EE::Admin::UsersController')
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 05f496c3b99..c38c6abddc1 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -22,7 +22,7 @@ class ApplicationController < ActionController::Base
include Impersonation
include Gitlab::Logging::CloudflareHelper
include Gitlab::Utils::StrongMemoize
- include ControllerWithFeatureCategory
+ include ::Gitlab::WithFeatureCategory
before_action :authenticate_user!, except: [:route_not_found]
before_action :enforce_terms!, if: :should_enforce_terms?
@@ -121,7 +121,7 @@ class ApplicationController < ActionController::Base
end
def route_not_found
- if current_user
+ if current_user || browser.bot.search_engine?
not_found
else
store_location_for(:user, request.fullpath) unless request.xhr?
@@ -266,6 +266,12 @@ class ApplicationController < ActionController::Base
end
end
+ def stream_headers
+ headers['Content-Length'] = nil
+ headers['X-Accel-Buffering'] = 'no' # Disable buffering on Nginx
+ headers['Last-Modified'] = '0' # Prevent buffering via Rack::ETag middleware
+ end
+
def default_headers
headers['X-Frame-Options'] = 'DENY'
headers['X-XSS-Protection'] = '1; mode=block'
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index ac4ee14c6a9..9ee69c7c07f 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -53,7 +53,7 @@ class AutocompleteController < ApplicationController
end
def deploy_keys_with_owners
- deploy_keys = DeployKeys::CollectKeysService.new(project, current_user).execute
+ deploy_keys = DeployKey.with_write_access_for_project(project)
render json: DeployKeySerializer.new.represent(deploy_keys, { with_owner: true, user: current_user })
end
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index 52719e90e04..9800d94964d 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -272,7 +272,7 @@ class Clusters::ClustersController < Clusters::BaseController
end
def aws_role_params
- params.require(:cluster).permit(:role_arn)
+ params.require(:cluster).permit(:role_arn, :region)
end
def generate_gcp_authorize_url
diff --git a/app/controllers/concerns/controller_with_feature_category.rb b/app/controllers/concerns/controller_with_feature_category.rb
deleted file mode 100644
index c1ff9ef2e69..00000000000
--- a/app/controllers/concerns/controller_with_feature_category.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-module ControllerWithFeatureCategory
- extend ActiveSupport::Concern
- include Gitlab::ClassAttributes
-
- class_methods do
- def feature_category(category, actions = [])
- feature_category_configuration[category] ||= []
- feature_category_configuration[category] += actions.map(&:to_s)
-
- validate_config!(feature_category_configuration)
- end
-
- def feature_category_for_action(action)
- category_config = feature_category_configuration.find do |_, actions|
- actions.empty? || actions.include?(action)
- end
-
- category_config&.first || superclass_feature_category_for_action(action)
- end
-
- private
-
- def validate_config!(config)
- empty = config.find { |_, actions| actions.empty? }
- duplicate_actions = config.values.flatten.group_by(&:itself).select { |_, v| v.count > 1 }.keys
-
- if config.length > 1 && empty
- raise ArgumentError, "#{empty.first} is defined for all actions, but other categories are set"
- end
-
- if duplicate_actions.any?
- raise ArgumentError, "Actions have multiple feature categories: #{duplicate_actions.join(', ')}"
- end
- end
-
- def feature_category_configuration
- class_attributes[:feature_category_config] ||= {}
- end
-
- def superclass_feature_category_for_action(action)
- return unless superclass.respond_to?(:feature_category_for_action)
-
- superclass.feature_category_for_action(action)
- end
- end
-end
diff --git a/app/controllers/concerns/dependency_proxy_access.rb b/app/controllers/concerns/dependency_proxy_access.rb
new file mode 100644
index 00000000000..5036d0cfce4
--- /dev/null
+++ b/app/controllers/concerns/dependency_proxy_access.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module DependencyProxyAccess
+ extend ActiveSupport::Concern
+
+ included do
+ before_action :verify_dependency_proxy_enabled!
+ before_action :authorize_read_dependency_proxy!
+ end
+
+ private
+
+ def verify_dependency_proxy_enabled!
+ render_404 unless group.dependency_proxy_feature_available?
+ end
+
+ def authorize_read_dependency_proxy!
+ access_denied! unless can?(current_user, :read_dependency_proxy, group)
+ end
+
+ def authorize_admin_dependency_proxy!
+ access_denied! unless can?(current_user, :admin_dependency_proxy, group)
+ end
+end
diff --git a/app/controllers/concerns/integrations_actions.rb b/app/controllers/concerns/integrations_actions.rb
index 39f63bbaaec..8e9b038437d 100644
--- a/app/controllers/concerns/integrations_actions.rb
+++ b/app/controllers/concerns/integrations_actions.rb
@@ -52,7 +52,7 @@ module IntegrationsActions
def integration
# Using instance variable `@service` still required as it's used in ServiceParams.
# Should be removed once that is refactored to use `@integration`.
- @integration = @service ||= find_or_initialize_integration(params[:id]) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ @integration = @service ||= find_or_initialize_non_project_specific_integration(params[:id]) # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
def success_message
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index a1a2740cde2..3b46a547d47 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -8,9 +8,6 @@ module IssuableActions
before_action :authorize_destroy_issuable!, only: :destroy
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, type: :licensed, default_enabled: true)
- end
before_action do
push_frontend_feature_flag(:not_issuable_queries, @project, default_enabled: true)
end
diff --git a/app/controllers/concerns/lfs_request.rb b/app/controllers/concerns/lfs_request.rb
index 2844acea271..bc3fd32759f 100644
--- a/app/controllers/concerns/lfs_request.rb
+++ b/app/controllers/concerns/lfs_request.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
# This concern assumes:
+# - a `#container` accessor
# - a `#project` accessor
# - a `#user` accessor
# - a `#authentication_result` accessor
@@ -11,6 +12,7 @@
# - a `#has_authentication_ability?(ability)` method
module LfsRequest
extend ActiveSupport::Concern
+ include Gitlab::Utils::StrongMemoize
CONTENT_TYPE = 'application/vnd.git-lfs+json'
@@ -29,16 +31,19 @@ module LfsRequest
message: _('Git LFS is not enabled on this GitLab server, contact your admin.'),
documentation_url: help_url
},
+ content_type: CONTENT_TYPE,
status: :not_implemented
)
end
def lfs_check_access!
- return render_lfs_not_found unless project
+ return render_lfs_not_found unless container&.lfs_enabled?
return if download_request? && lfs_download_access?
return if upload_request? && lfs_upload_access?
- if project.public? || can?(user, :read_project, project)
+ # Only return a 403 response if the user has download access permission,
+ # otherwise return a 404 to avoid exposing the existence of the container.
+ if lfs_download_access?
lfs_forbidden!
else
render_lfs_not_found
@@ -72,9 +77,9 @@ module LfsRequest
end
def lfs_download_access?
- return false unless project.lfs_enabled?
-
- ci? || lfs_deploy_token? || user_can_download_code? || build_can_download_code? || deploy_token_can_download_code?
+ strong_memoize(:lfs_download_access) do
+ ci? || lfs_deploy_token? || user_can_download_code? || build_can_download_code? || deploy_token_can_download_code?
+ end
end
def deploy_token_can_download_code?
@@ -93,11 +98,12 @@ module LfsRequest
end
def lfs_upload_access?
- return false unless project.lfs_enabled?
- return false unless has_authentication_ability?(:push_code)
- return false if limit_exceeded?
+ strong_memoize(:lfs_upload_access) do
+ next false unless has_authentication_ability?(:push_code)
+ next false if limit_exceeded?
- lfs_deploy_token? || can?(user, :push_code, project)
+ lfs_deploy_token? || can?(user, :push_code, project)
+ end
end
def lfs_deploy_token?
diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb
index 7a5b470f366..bfa7a30bc65 100644
--- a/app/controllers/concerns/notes_actions.rb
+++ b/app/controllers/concerns/notes_actions.rb
@@ -31,6 +31,10 @@ module NotesActions
# We know there's more data, so tell the frontend to poll again after 1ms
set_polling_interval_header(interval: 1) if meta[:more]
+ # Only present an ETag for the empty response to ensure pagination works
+ # as expected
+ ::Gitlab::EtagCaching::Middleware.skip!(response) if notes.present?
+
render json: meta.merge(notes: notes)
end
@@ -115,7 +119,7 @@ module NotesActions
end
def gather_some_notes
- paginator = Gitlab::UpdatedNotesPaginator.new(
+ paginator = ::Gitlab::UpdatedNotesPaginator.new(
notes_finder.execute.inc_relations_for_view,
last_fetched_at: last_fetched_at
)
diff --git a/app/controllers/concerns/routable_actions.rb b/app/controllers/concerns/routable_actions.rb
index 1b2e6461dee..bc2e7fba288 100644
--- a/app/controllers/concerns/routable_actions.rb
+++ b/app/controllers/concerns/routable_actions.rb
@@ -51,7 +51,7 @@ module RoutableActions
flash[:notice] = "#{routable.class.to_s.titleize} '#{requested_full_path}' was moved to '#{canonical_path}'. Please update any links and bookmarks that may still have the old path."
end
- redirect_to build_canonical_path(routable)
+ redirect_to build_canonical_path(routable), status: :moved_permanently
end
end
end
diff --git a/app/controllers/concerns/send_file_upload.rb b/app/controllers/concerns/send_file_upload.rb
index 2f06cd84ee5..8b053ef7c59 100644
--- a/app/controllers/concerns/send_file_upload.rb
+++ b/app/controllers/concerns/send_file_upload.rb
@@ -70,16 +70,7 @@ module SendFileUpload
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)
+ Feature.enabled?(:dynamic_image_resizing, default_enabled: true, type: :ops)
end
end
diff --git a/app/controllers/concerns/sends_blob.rb b/app/controllers/concerns/sends_blob.rb
index 9bba61fda84..381f2eba352 100644
--- a/app/controllers/concerns/sends_blob.rb
+++ b/app/controllers/concerns/sends_blob.rb
@@ -44,7 +44,6 @@ module SendsBlob
Blob::CACHE_TIME
end
- response.etag = blob.id
!stale
end
diff --git a/app/controllers/concerns/snippets_actions.rb b/app/controllers/concerns/snippets_actions.rb
index e4c3df6ccc3..0153ede2821 100644
--- a/app/controllers/concerns/snippets_actions.rb
+++ b/app/controllers/concerns/snippets_actions.rb
@@ -57,11 +57,6 @@ module SnippetsActions
render 'show'
end
- format.json do
- conditionally_expand_blob(blob)
- render_blob_json(blob)
- end
-
format.js do
if @snippet.embeddable?
conditionally_expand_blobs(blobs)
diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb
index aed109309e3..6abb2e16226 100644
--- a/app/controllers/concerns/wiki_actions.rb
+++ b/app/controllers/concerns/wiki_actions.rb
@@ -103,9 +103,10 @@ module WikiActions
@page = response.payload[:page]
if response.success?
+ flash[:toast] = _('Wiki page was successfully updated.')
+
redirect_to(
- wiki_page_path(wiki, page),
- notice: _('Wiki was successfully updated.')
+ wiki_page_path(wiki, page)
)
else
render 'shared/wikis/edit'
@@ -122,9 +123,10 @@ module WikiActions
@page = response.payload[:page]
if response.success?
+ flash[:toast] = _('Wiki page was successfully created.')
+
redirect_to(
- wiki_page_path(wiki, page),
- notice: _('Wiki was successfully updated.')
+ wiki_page_path(wiki, page)
)
else
render 'shared/wikis/edit'
@@ -169,9 +171,10 @@ module WikiActions
response = WikiPages::DestroyService.new(container: container, current_user: current_user).execute(page)
if response.success?
+ flash[:toast] = _("Wiki page was successfully deleted.")
+
redirect_to wiki_path(wiki),
- status: :found,
- notice: _("Page was successfully deleted")
+ status: :found
else
@error = response
render 'shared/wikis/edit'
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index b971c5783a8..c2d72610c66 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -7,9 +7,8 @@ class Groups::BoardsController < Groups::ApplicationController
before_action :authorize_read_board!, only: [:index, :show]
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)
+ push_frontend_feature_flag(:boards_with_swimlanes, group, default_enabled: true)
end
feature_category :boards
diff --git a/app/controllers/groups/dependency_proxies_controller.rb b/app/controllers/groups/dependency_proxies_controller.rb
new file mode 100644
index 00000000000..367dbafdd59
--- /dev/null
+++ b/app/controllers/groups/dependency_proxies_controller.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Groups
+ class DependencyProxiesController < Groups::ApplicationController
+ include DependencyProxyAccess
+
+ before_action :authorize_admin_dependency_proxy!, only: :update
+ before_action :dependency_proxy
+
+ feature_category :package_registry
+
+ def show
+ @blobs_count = group.dependency_proxy_blobs.count
+ @blobs_total_size = group.dependency_proxy_blobs.total_size
+ end
+
+ def update
+ dependency_proxy.update(dependency_proxy_params)
+
+ redirect_to group_dependency_proxy_path(group)
+ end
+
+ private
+
+ def dependency_proxy
+ @dependency_proxy ||=
+ group.dependency_proxy_setting || group.create_dependency_proxy_setting
+ end
+
+ def dependency_proxy_params
+ params.require(:dependency_proxy_group_setting).permit(:enabled)
+ end
+ end
+end
diff --git a/app/controllers/groups/dependency_proxy_for_containers_controller.rb b/app/controllers/groups/dependency_proxy_for_containers_controller.rb
new file mode 100644
index 00000000000..f46902ef90f
--- /dev/null
+++ b/app/controllers/groups/dependency_proxy_for_containers_controller.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+class Groups::DependencyProxyForContainersController < Groups::ApplicationController
+ include DependencyProxyAccess
+ include SendFileUpload
+
+ before_action :ensure_token_granted!
+ before_action :ensure_feature_enabled!
+
+ attr_reader :token
+
+ feature_category :package_registry
+
+ def manifest
+ result = DependencyProxy::PullManifestService.new(image, tag, token).execute
+
+ if result[:status] == :success
+ render json: result[:manifest]
+ else
+ render status: result[:http_status], json: result[:message]
+ end
+ end
+
+ def blob
+ result = DependencyProxy::FindOrCreateBlobService
+ .new(group, image, token, params[:sha]).execute
+
+ if result[:status] == :success
+ send_upload(result[:blob].file)
+ else
+ head result[:http_status]
+ end
+ end
+
+ private
+
+ def image
+ params[:image]
+ end
+
+ def tag
+ params[:tag]
+ end
+
+ def dependency_proxy
+ @dependency_proxy ||=
+ group.dependency_proxy_setting || group.create_dependency_proxy_setting
+ end
+
+ def ensure_feature_enabled!
+ render_404 unless dependency_proxy.enabled
+ end
+
+ def ensure_token_granted!
+ result = DependencyProxy::RequestTokenService.new(image).execute
+
+ if result[:status] == :success
+ @token = result[:token]
+ else
+ render status: result[:http_status], json: result[:message]
+ end
+ end
+end
diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb
index 173a24ceb74..03d41f1dd6d 100644
--- a/app/controllers/groups/milestones_controller.rb
+++ b/app/controllers/groups/milestones_controller.rb
@@ -6,7 +6,7 @@ class Groups::MilestonesController < Groups::ApplicationController
before_action :milestone, only: [:edit, :show, :update, :issues, :merge_requests, :participants, :labels, :destroy]
before_action :authorize_admin_milestones!, only: [:edit, :new, :create, :update, :destroy]
before_action do
- push_frontend_feature_flag(:burnup_charts, @group)
+ push_frontend_feature_flag(:burnup_charts, @group, default_enabled: true)
end
feature_category :issue_tracking
diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb
index 0c72c8a037b..723edc4b7e9 100644
--- a/app/controllers/groups/settings/ci_cd_controller.rb
+++ b/app/controllers/groups/settings/ci_cd_controller.rb
@@ -8,9 +8,6 @@ module Groups
skip_cross_project_access_check :show
before_action :authorize_admin_group!
before_action :authorize_update_max_artifacts_size!, only: [:update]
- before_action do
- push_frontend_feature_flag(:new_variables_ui, @group, default_enabled: true)
- end
before_action :define_variables, only: [:show]
feature_category :continuous_integration
diff --git a/app/controllers/groups/settings/integrations_controller.rb b/app/controllers/groups/settings/integrations_controller.rb
index b089cfdf341..a66372b3571 100644
--- a/app/controllers/groups/settings/integrations_controller.rb
+++ b/app/controllers/groups/settings/integrations_controller.rb
@@ -10,7 +10,7 @@ module Groups
feature_category :integrations
def index
- @integrations = Service.find_or_initialize_all(Service.for_group(group)).sort_by(&:title)
+ @integrations = Service.find_or_initialize_all_non_project_specific(Service.for_group(group)).sort_by(&:title)
end
def edit
@@ -21,12 +21,12 @@ module Groups
private
- def find_or_initialize_integration(name)
- Service.find_or_initialize_integration(name, group_id: group.id)
+ def find_or_initialize_non_project_specific_integration(name)
+ Service.find_or_initialize_non_project_specific_integration(name, group_id: group.id)
end
def integrations_enabled?
- Feature.enabled?(:group_level_integrations, group)
+ Feature.enabled?(:group_level_integrations, group, default_enabled: true)
end
def scoped_edit_integration_path(integration)
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 6f8dc75f6bd..8d528e123e1 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -30,7 +30,6 @@ class GroupsController < Groups::ApplicationController
before_action do
push_frontend_feature_flag(:vue_issuables_list, @group)
- push_frontend_feature_flag(:deployment_filters)
end
before_action do
@@ -133,13 +132,23 @@ class GroupsController < Groups::ApplicationController
def update
if Groups::UpdateService.new(@group, current_user, group_params).execute
- redirect_to edit_group_path(@group, anchor: params[:update_section]), notice: "Group '#{@group.name}' was successfully updated."
+ notice = "Group '#{@group.name}' was successfully updated."
+
+ redirect_to edit_group_origin_location, notice: notice
else
@group.reset
render action: "edit"
end
end
+ def edit_group_origin_location
+ if params.dig(:group, :redirect_target) == 'repository_settings'
+ group_settings_repository_path(@group, anchor: 'js-default-branch-name')
+ else
+ edit_group_path(@group, anchor: params[:update_section])
+ end
+ end
+
def destroy
Groups::DestroyService.new(@group, current_user).async_execute
@@ -181,8 +190,6 @@ class GroupsController < Groups::ApplicationController
end
def unfoldered_environment_names
- return render_404 unless Feature.enabled?(:deployment_filters)
-
respond_to do |format|
format.json do
render json: EnvironmentNamesFinder.new(@group, current_user).execute
@@ -193,6 +200,8 @@ class GroupsController < Groups::ApplicationController
protected
def render_show_html
+ record_experiment_user(:invite_members_empty_group_version_a) if ::Gitlab.com?
+
render 'groups/show', locals: { trial: params[:trial] }
end
diff --git a/app/controllers/import/base_controller.rb b/app/controllers/import/base_controller.rb
index 151ba46e629..87cda723895 100644
--- a/app/controllers/import/base_controller.rb
+++ b/app/controllers/import/base_controller.rb
@@ -48,18 +48,14 @@ class Import::BaseController < ApplicationController
private
- def filter_attribute
- :name
- end
-
def sanitized_filter_param
- @filter ||= sanitize(params[:filter])
+ @filter ||= sanitize(params[:filter])&.downcase
end
def filtered(collection)
return collection unless sanitized_filter_param
- collection.select { |item| item[filter_attribute].include?(sanitized_filter_param) }
+ collection.select { |item| item[:name].to_s.downcase.include?(sanitized_filter_param) }
end
def serialized_provider_repos
diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb
index 0ffd9ef8bdd..57bd39bbe06 100644
--- a/app/controllers/import/bitbucket_controller.rb
+++ b/app/controllers/import/bitbucket_controller.rb
@@ -132,8 +132,4 @@ class Import::BitbucketController < Import::BaseController
refresh_token: session[:bitbucket_refresh_token]
}
end
-
- def sanitized_filter_param
- @filter ||= sanitize(params[:filter])
- end
end
diff --git a/app/controllers/import/bitbucket_server_controller.rb b/app/controllers/import/bitbucket_server_controller.rb
index bee78cb3283..1846b1e0cec 100644
--- a/app/controllers/import/bitbucket_server_controller.rb
+++ b/app/controllers/import/bitbucket_server_controller.rb
@@ -170,10 +170,6 @@ class Import::BitbucketServerController < Import::BaseController
BitbucketServer::Paginator::PAGE_LENGTH
end
- def sanitized_filter_param
- sanitize(params[:filter])
- end
-
def bitbucket_connection_error(error)
flash[:alert] = _("Unable to connect to server: %{error}") % { error: error }
clear_session_data
diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb
index cb2922c2d47..78f4a0cffca 100644
--- a/app/controllers/import/bulk_imports_controller.rb
+++ b/app/controllers/import/bulk_imports_controller.rb
@@ -6,13 +6,13 @@ class Import::BulkImportsController < ApplicationController
feature_category :importers
- rescue_from Gitlab::BulkImport::Client::ConnectionError, with: :bulk_import_connection_error
+ rescue_from BulkImports::Clients::Http::ConnectionError, with: :bulk_import_connection_error
def configure
- session[access_token_key] = params[access_token_key]&.strip
- session[url_key] = params[url_key]
+ session[access_token_key] = configure_params[access_token_key]&.strip
+ session[url_key] = configure_params[url_key]
- redirect_to status_import_bulk_import_url
+ redirect_to status_import_bulk_imports_url
end
def status
@@ -25,6 +25,12 @@ class Import::BulkImportsController < ApplicationController
end
end
+ def create
+ BulkImportService.new(current_user, create_params, credentials).execute
+
+ render json: :ok
+ end
+
private
def serialized_importable_data
@@ -36,20 +42,33 @@ class Import::BulkImportsController < ApplicationController
end
def importable_data
- client.get('groups', top_level_only: true)
+ client.get('groups', top_level_only: true).parsed_response
end
def client
- @client ||= Gitlab::BulkImport::Client.new(
+ @client ||= BulkImports::Clients::Http.new(
uri: session[url_key],
token: session[access_token_key]
)
end
- def import_params
+ def configure_params
params.permit(access_token_key, url_key)
end
+ def create_params
+ params.permit(:bulk_import, [*bulk_import_params])
+ end
+
+ def bulk_import_params
+ %i[
+ source_type
+ source_full_path
+ destination_name
+ destination_namespace
+ ]
+ end
+
def ensure_group_import_enabled
render_404 unless Feature.enabled?(:bulk_import)
end
@@ -106,4 +125,11 @@ class Import::BulkImportsController < ApplicationController
session[url_key] = nil
session[access_token_key] = nil
end
+
+ def credentials
+ {
+ url: session[url_key],
+ access_token: [access_token_key]
+ }
+ end
end
diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb
index a1adc6e062a..8ac93aeb9c0 100644
--- a/app/controllers/import/github_controller.rb
+++ b/app/controllers/import/github_controller.rb
@@ -15,6 +15,7 @@ class Import::GithubController < Import::BaseController
rescue_from OAuthConfigMissingError, with: :missing_oauth_config
rescue_from Octokit::Unauthorized, with: :provider_unauthorized
rescue_from Octokit::TooManyRequests, with: :provider_rate_limit
+ rescue_from Gitlab::GithubImport::RateLimitError, with: :rate_limit_threshold_exceeded
def new
if !ci_cd_only? && github_import_configured? && logged_in_with_provider?
@@ -114,7 +115,7 @@ class Import::GithubController < Import::BaseController
def client_repos
@client_repos ||= if Feature.enabled?(:remove_legacy_github_client)
- filtered(concatenated_repos)
+ concatenated_repos
else
filtered(client.repos)
end
@@ -122,8 +123,15 @@ class Import::GithubController < Import::BaseController
def concatenated_repos
return [] unless client.respond_to?(:each_page)
+ return client.each_page(:repos).flat_map(&:objects) unless sanitized_filter_param
- client.each_page(:repos).flat_map(&:objects)
+ client.search_repos_by_name(sanitized_filter_param).flat_map(&:objects).flat_map(&:items)
+ end
+
+ def sanitized_filter_param
+ super
+
+ @filter = @filter&.tr(' ', '')&.tr(':', '')
end
def oauth_client
@@ -246,12 +254,8 @@ class Import::GithubController < Import::BaseController
{}
end
- def sanitized_filter_param
- @filter ||= sanitize(params[:filter])
- end
-
- def filter_attribute
- :name
+ def rate_limit_threshold_exceeded
+ head :too_many_requests
end
end
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index c7b8486d1c9..26fc1c11f6d 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -15,13 +15,11 @@ class InvitesController < ApplicationController
feature_category :authentication_and_authorization
def show
- track_new_user_invite_experiment('opened')
accept if skip_invitation_prompt?
end
def accept
if member.accept_invite!(current_user)
- track_new_user_invite_experiment('accepted')
track_invitation_reminders_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] }
@@ -110,25 +108,13 @@ class InvitesController < ApplicationController
end
end
- def track_new_user_invite_experiment(action)
- return unless params[:new_user_invite]
-
- property = params[:new_user_invite] == 'experiment' ? 'experiment_group' : 'control_group'
-
- track_experiment(:invite_email, action, property)
- end
-
def track_invitation_reminders_experiment(action)
return unless Gitlab::Experimentation.enabled?(:invitation_reminders)
property = Gitlab::Experimentation.enabled_for_attribute?(:invitation_reminders, member.invite_email) ? 'experimental_group' : 'control_group'
- track_experiment(:invitation_reminders, action, property)
- end
-
- def track_experiment(experiment_key, action, property)
Gitlab::Tracking.event(
- Gitlab::Experimentation.experiment(experiment_key).tracking_category,
+ Gitlab::Experimentation.experiment(:invitation_reminders).tracking_category,
action,
property: property,
label: Digest::MD5.hexdigest(member.to_global_id.to_s)
diff --git a/app/controllers/jwks_controller.rb b/app/controllers/jwks_controller.rb
new file mode 100644
index 00000000000..e7b839f5590
--- /dev/null
+++ b/app/controllers/jwks_controller.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class JwksController < ActionController::Base # rubocop:disable Rails/ApplicationController
+ def index
+ render json: { keys: keys }
+ end
+
+ private
+
+ def keys
+ [
+ # We keep openid_connect_signing_key so that we can seamlessly
+ # replace it with ci_jwt_signing_key and remove it on the next release.
+ # TODO: Remove openid_connect_signing_key in 13.7
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/221031
+ Rails.application.secrets.openid_connect_signing_key,
+ Gitlab::CurrentSettings.ci_jwt_signing_key
+ ].compact.map do |key_data|
+ OpenSSL::PKey::RSA.new(key_data)
+ .public_key
+ .to_jwk
+ .slice(:kty, :kid, :e, :n)
+ .merge(use: 'sig', alg: 'RS256')
+ end
+ end
+end
diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb
index b005347c43a..a45205c5da7 100644
--- a/app/controllers/profiles/personal_access_tokens_controller.rb
+++ b/app/controllers/profiles/personal_access_tokens_controller.rb
@@ -9,9 +9,13 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController
end
def create
- @personal_access_token = finder.build(personal_access_token_params)
+ result = ::PersonalAccessTokens::CreateService.new(
+ current_user: current_user, target_user: current_user, params: personal_access_token_params
+ ).execute
- if @personal_access_token.save
+ @personal_access_token = result.payload[:personal_access_token]
+
+ if result.success?
PersonalAccessToken.redis_store!(current_user.id, @personal_access_token.token)
redirect_to profile_personal_access_tokens_path, notice: _("Your new personal access token has been created.")
else
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index c85c83688a4..afebeafff7c 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -127,7 +127,7 @@ class ProfilesController < Profiles::ApplicationController
:include_private_contributions,
:timezone,
:job_title,
- status: [:emoji, :message]
+ status: [:emoji, :message, :availability]
)
end
end
diff --git a/app/controllers/projects/alert_management_controller.rb b/app/controllers/projects/alert_management_controller.rb
index 0d0ef9b05cb..8ecf8fadefd 100644
--- a/app/controllers/projects/alert_management_controller.rb
+++ b/app/controllers/projects/alert_management_controller.rb
@@ -10,6 +10,5 @@ class Projects::AlertManagementController < Projects::ApplicationController
def details
@alert_id = params[:id]
- push_frontend_feature_flag(:expose_environment_path_in_alert_details, @project)
end
end
diff --git a/app/controllers/projects/alerting/notifications_controller.rb b/app/controllers/projects/alerting/notifications_controller.rb
index 2241ded2db8..a3f4d784f25 100644
--- a/app/controllers/projects/alerting/notifications_controller.rb
+++ b/app/controllers/projects/alerting/notifications_controller.rb
@@ -14,7 +14,7 @@ module Projects
def create
token = extract_alert_manager_token(request)
- result = notify_service.execute(token)
+ result = notify_service.execute(token, integration)
head result.http_status
end
@@ -45,6 +45,18 @@ module Projects
end
end
+ def integration
+ AlertManagement::HttpIntegrationsFinder.new(
+ project,
+ endpoint_identifier: endpoint_identifier,
+ active: true
+ ).execute.first
+ end
+
+ def endpoint_identifier
+ params[:endpoint_identifier] || AlertManagement::HttpIntegration::LEGACY_IDENTIFIER
+ end
+
def notification_payload
@notification_payload ||= params.permit![:notification]
end
diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb
index e9c533daa80..001967b8bb4 100644
--- a/app/controllers/projects/autocomplete_sources_controller.rb
+++ b/app/controllers/projects/autocomplete_sources_controller.rb
@@ -39,7 +39,7 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController
private
def autocomplete_service
- @autocomplete_service ||= ::Projects::AutocompleteService.new(@project, current_user)
+ @autocomplete_service ||= ::Projects::AutocompleteService.new(@project, current_user, params)
end
def target
diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb
index f228206032d..fb113df137f 100644
--- a/app/controllers/projects/avatars_controller.rb
+++ b/app/controllers/projects/avatars_controller.rb
@@ -3,6 +3,8 @@
class Projects::AvatarsController < Projects::ApplicationController
include SendsBlob
+ skip_before_action :default_cache_headers, only: :show
+
before_action :authorize_admin_project!, only: [:destroy]
feature_category :projects
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index c6251d27b05..02e941db636 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -33,7 +33,7 @@ class Projects::BlobController < Projects::ApplicationController
before_action :set_last_commit_sha, only: [:edit, :update]
before_action only: :show do
- push_frontend_experiment(:suggest_pipeline)
+ push_frontend_feature_flag(:suggest_pipeline, default_enabled: true)
push_frontend_feature_flag(:gitlab_ci_yml_preview, @project, default_enabled: false)
end
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index 193352ffa70..fe4502a0e06 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -8,8 +8,7 @@ class Projects::BoardsController < Projects::ApplicationController
before_action :authorize_read_board!, only: [:index, :show]
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)
+ push_frontend_feature_flag(:boards_with_swimlanes, project, default_enabled: true)
end
feature_category :boards
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index 9124728ee25..cf1efda5d13 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -27,7 +27,7 @@ class Projects::BranchesController < Projects::ApplicationController
@refs_pipelines = @project.ci_pipelines.latest_successful_for_refs(@branches.map(&:name))
@merged_branch_names = repository.merged_branch_names(@branches.map(&:name))
- @branch_pipeline_statuses = branch_pipeline_statuses
+ @branch_pipeline_statuses = Ci::CommitStatusesFinder.new(@project, repository, current_user, @branches).execute
# https://gitlab.com/gitlab-org/gitlab/-/issues/22851
Gitlab::GitalyClient.allow_n_plus_1_calls do
@@ -197,15 +197,4 @@ class Projects::BranchesController < Projects::ApplicationController
confidential_issue_project
end
-
- def branch_pipeline_statuses
- latest_commits = @branches.map do |branch|
- [branch.name, repository.commit(branch.dereferenced_target).sha]
- end.to_h
-
- latest_pipelines = project.ci_pipelines.latest_pipeline_per_commit(latest_commits.values)
- latest_commits.transform_values do |commit_sha|
- latest_pipelines[commit_sha]&.detailed_status(current_user)
- end.compact
- end
end
diff --git a/app/controllers/projects/ci/lints_controller.rb b/app/controllers/projects/ci/lints_controller.rb
index 7e900fc6051..9dc3194df85 100644
--- a/app/controllers/projects/ci/lints_controller.rb
+++ b/app/controllers/projects/ci/lints_controller.rb
@@ -2,28 +2,22 @@
class Projects::Ci::LintsController < Projects::ApplicationController
before_action :authorize_create_pipeline!
- before_action do
- push_frontend_feature_flag(:ci_lint_vue, project)
- end
feature_category :pipeline_authoring
+ respond_to :json, only: [:create]
+
def show
end
def create
- @content = params[:content]
- @dry_run = params[:dry_run]
+ content = params[:content]
+ dry_run = params[:dry_run]
- @result = Gitlab::Ci::Lint
+ result = Gitlab::Ci::Lint
.new(project: @project, current_user: current_user)
- .validate(@content, dry_run: @dry_run)
+ .validate(content, dry_run: dry_run)
- respond_to do |format|
- format.html { render :show }
- format.json do
- render json: ::Ci::Lint::ResultSerializer.new.represent(@result)
- end
- end
+ render json: ::Ci::Lint::ResultSerializer.new.represent(result)
end
end
diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb
new file mode 100644
index 00000000000..c2428270fa6
--- /dev/null
+++ b/app/controllers/projects/ci/pipeline_editor_controller.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class Projects::Ci::PipelineEditorController < Projects::ApplicationController
+ before_action :check_can_collaborate!
+
+ feature_category :pipeline_authoring
+
+ def show
+ render_404 unless ::Gitlab::Ci::Features.ci_pipeline_editor_page_enabled?(@project)
+ end
+
+ private
+
+ def check_can_collaborate!
+ render_404 unless can_collaborate_with_project?(@project)
+ end
+end
diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb
index 6cdd1c0bc8c..c8528ad6d28 100644
--- a/app/controllers/projects/imports_controller.rb
+++ b/app/controllers/projects/imports_controller.rb
@@ -55,7 +55,7 @@ class Projects::ImportsController < Projects::ApplicationController
end
def require_namespace_project_creation_permission
- render_404 unless current_user.can?(:admin_project, @project) || current_user.can?(:create_projects, @project.namespace)
+ render_404 unless can?(current_user, :admin_project, @project) || can?(current_user, :create_projects, @project.namespace)
end
def redirect_if_progress
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 9a8965dbeb6..3a1b4f380a2 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -44,22 +44,19 @@ 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(:vue_issue_header, @project, default_enabled: true)
end
before_action only: :show do
real_time_feature_flag = :real_time_issue_sidebar
real_time_enabled = Gitlab::ActionCable::Config.in_app? || Feature.enabled?(real_time_feature_flag, @project)
- gon.push({ features: { real_time_feature_flag.to_s.camelize(:lower) => real_time_enabled } }, true)
+ push_to_gon_features(real_time_feature_flag, real_time_enabled)
record_experiment_user(:invite_members_version_a)
record_experiment_user(:invite_members_version_b)
end
- before_action only: :index do
- push_frontend_feature_flag(:scoped_labels, @project, type: :licensed)
- end
-
around_action :allow_gitaly_ref_name_caching, only: [:discussions]
respond_to :html
diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb
index 3ceb60a6aef..07e38c80291 100644
--- a/app/controllers/projects/jobs_controller.rb
+++ b/app/controllers/projects/jobs_controller.rb
@@ -14,6 +14,9 @@ class Projects::JobsController < Projects::ApplicationController
before_action :verify_api_request!, only: :terminal_websocket_authorize
before_action :authorize_create_proxy_build!, only: :proxy_websocket_authorize
before_action :verify_proxy_request!, only: :proxy_websocket_authorize
+ before_action do
+ push_frontend_feature_flag(:ci_job_line_links, @project)
+ end
layout 'project'
diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb
index 07c38431f0f..7fbeac12644 100644
--- a/app/controllers/projects/merge_requests/diffs_controller.rb
+++ b/app/controllers/projects/merge_requests/diffs_controller.rb
@@ -20,7 +20,10 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
end
def diffs_batch
- diffs = @compare.diffs_in_batch(params[:page], params[:per_page], diff_options: diff_options)
+ diff_options_hash = diff_options
+ diff_options_hash[:paths] = params[:paths] if params[:paths]
+
+ diffs = @compare.diffs_in_batch(params[:page], params[:per_page], diff_options: diff_options_hash)
positions = @merge_request.note_positions_for_paths(diffs.diff_file_paths, current_user)
environment = @merge_request.environments_for(current_user, latest: true).last
@@ -31,6 +34,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
environment: environment,
merge_request: @merge_request,
diff_view: diff_view,
+ merge_ref_head_diff: render_merge_ref_head_diff?,
pagination_data: diffs.pagination_data
}
@@ -64,7 +68,10 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
render: ->(partial, locals) { view_to_html_string(partial, locals) }
}
- options = additional_attributes.merge(diff_view: Feature.enabled?(:unified_diff_lines, @merge_request.project, default_enabled: true) ? "inline" : diff_view)
+ options = additional_attributes.merge(
+ diff_view: unified_diff_lines_view_type(@merge_request.project),
+ merge_ref_head_diff: render_merge_ref_head_diff?
+ )
if @merge_request.project.context_commits_enabled?
options[:context_commits] = @merge_request.recent_context_commits
@@ -113,7 +120,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
end
end
- if Gitlab::Utils.to_boolean(params[:diff_head]) && @merge_request.diffable_merge_ref?
+ if render_merge_ref_head_diff?
return CompareService.new(@project, @merge_request.merge_ref_head.sha)
.execute(@project, @merge_request.target_branch)
end
@@ -155,6 +162,10 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
@notes = prepare_notes_for_rendering(@grouped_diff_discussions.values.flatten.flat_map(&:notes), @merge_request)
end
+ def render_merge_ref_head_diff?
+ Gitlab::Utils.to_boolean(params[:diff_head]) && @merge_request.diffable_merge_ref?
+ end
+
def note_positions
@note_positions ||= Gitlab::Diff::PositionCollection.new(renderable_notes.map(&:position))
end
@@ -173,7 +184,6 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
end
def update_diff_discussion_positions!
- return unless Feature.enabled?(:merge_red_head_comments_position_on_demand, @merge_request.target_project, default_enabled: true)
return if @merge_request.has_any_diff_note_positions?
Discussions::CaptureDiffNotePositionsService.new(@merge_request).execute
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 91a041bb35b..f2b41294a85 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -12,7 +12,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
include SourcegraphDecorator
include DiffHelper
- skip_before_action :merge_request, only: [:index, :bulk_update]
+ skip_before_action :merge_request, only: [:index, :bulk_update, :export_csv]
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]
@@ -27,7 +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_experiment(:suggest_pipeline)
+ push_frontend_feature_flag(:suggest_pipeline, default_enabled: true)
push_frontend_feature_flag(:widget_visibility_polling, @project, default_enabled: true)
push_frontend_feature_flag(:mr_commit_neighbor_nav, @project, default_enabled: true)
push_frontend_feature_flag(:multiline_comments, @project, default_enabled: true)
@@ -37,9 +37,12 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
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, default_enabled: true)
+ push_frontend_feature_flag(:unified_diff_components, @project)
push_frontend_feature_flag(:highlight_current_diff_row, @project)
push_frontend_feature_flag(:default_merge_ref_for_diffs, @project)
push_frontend_feature_flag(:core_security_mr_widget, @project, default_enabled: true)
+ push_frontend_feature_flag(:remove_resolve_note, @project, default_enabled: true)
+ push_frontend_feature_flag(:test_failure_history, @project)
record_experiment_user(:invite_members_version_a)
record_experiment_user(:invite_members_version_b)
@@ -47,7 +50,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action do
push_frontend_feature_flag(:vue_issuable_sidebar, @project.group)
- push_frontend_feature_flag(:deployment_filters)
end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]
@@ -317,6 +319,14 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
super
end
+ def export_csv
+ IssuableExportCsvWorker.perform_async(:merge_request, current_user.id, project.id, finder_options.to_h) # rubocop:disable CodeReuse/Worker
+
+ index_path = project_merge_requests_path(project)
+ message = _('Your CSV export has started. It will be emailed to %{email} when complete.') % { email: current_user.notification_email }
+ redirect_to(index_path, notice: message)
+ end
+
protected
alias_method :subscribable_resource, :merge_request
@@ -471,7 +481,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
def endpoint_metadata_url(project, merge_request)
params = request.query_parameters
- params[:view] = cookies[:diff_view] if params[:view].blank? && cookies[:diff_view].present?
+ params[:view] = unified_diff_lines_view_type(project)
if Feature.enabled?(:default_merge_ref_for_diffs, project)
params = params.merge(diff_head: true)
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index e6c4af00b29..31189c888b7 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -7,7 +7,7 @@ class Projects::MilestonesController < Projects::ApplicationController
before_action :check_issuables_available!
before_action :milestone, only: [:edit, :update, :destroy, :show, :issues, :merge_requests, :participants, :labels, :promote]
before_action do
- push_frontend_feature_flag(:burnup_charts, @project)
+ push_frontend_feature_flag(:burnup_charts, @project, default_enabled: true)
end
# Allow read any milestone
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index e50e293a103..77fd7688caf 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -60,7 +60,7 @@ class Projects::NotesController < Projects::ApplicationController
def render_json_with_notes_serializer
prepare_notes_for_rendering([note])
- render json: note_serializer.represent(note)
+ render json: note_serializer.represent(note, render_truncated_diff_lines: true)
end
def note
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 953dce4d63c..f71a92ee874 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -12,11 +12,11 @@ class Projects::PipelinesController < Projects::ApplicationController
before_action :authorize_create_pipeline!, only: [:new, :create, :config_variables]
before_action :authorize_update_pipeline!, only: [:retry, :cancel]
before_action do
- push_frontend_feature_flag(:filter_pipelines_search, project, default_enabled: true)
push_frontend_feature_flag(:dag_pipeline_tab, project, default_enabled: true)
push_frontend_feature_flag(:pipelines_security_report_summary, project)
- push_frontend_feature_flag(:new_pipeline_form, project)
+ push_frontend_feature_flag(:new_pipeline_form, project, default_enabled: true)
push_frontend_feature_flag(:graphql_pipeline_header, project, type: :development, default_enabled: false)
+ push_frontend_feature_flag(:graphql_pipeline_details, project, type: :development, default_enabled: false)
push_frontend_feature_flag(:new_pipeline_form_prefilled_vars, project, type: :development)
end
before_action :ensure_pipeline, only: [:show]
@@ -194,6 +194,7 @@ class Projects::PipelinesController < Projects::ApplicationController
@counts[:total] = @project.all_pipelines.count(:all)
@counts[:success] = @project.all_pipelines.success.count(:all)
@counts[:failed] = @project.all_pipelines.failed.count(:all)
+ @counts[:total_duration] = @project.all_pipelines.total_duration
end
def test_report
@@ -213,7 +214,7 @@ class Projects::PipelinesController < Projects::ApplicationController
def config_variables
respond_to do |format|
format.json do
- render json: Ci::ListConfigVariablesService.new(@project).execute(params[:sha])
+ render json: Ci::ListConfigVariablesService.new(@project, current_user).execute(params[:sha])
end
end
end
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index a9490c106d4..d8ba7e4f235 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -6,13 +6,14 @@ class Projects::RawController < Projects::ApplicationController
include SendsBlob
include StaticObjectExternalStorage
+ skip_before_action :default_cache_headers, only: :show
+
prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:blob) }
before_action :require_non_empty_project
before_action :authorize_download_code!
before_action :show_rate_limit, only: [:show], unless: :external_storage_request?
before_action :assign_ref_vars
- before_action :no_cache_headers, only: [:show]
before_action :redirect_to_external_storage, only: :show, if: :static_objects_external_storage_enabled?
feature_category :source_code_management
diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb
index 4e8260d9e53..a6e795a2b91 100644
--- a/app/controllers/projects/releases_controller.rb
+++ b/app/controllers/projects/releases_controller.rb
@@ -54,7 +54,7 @@ class Projects::ReleasesController < Projects::ApplicationController
end
def sanitized_filepath
- CGI.unescape(params[:filepath])
+ "/#{CGI.unescape(params[:filepath])}"
end
def sanitized_tag_name
diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb
index ba3ab52e3af..fb6a09cff65 100644
--- a/app/controllers/projects/repositories_controller.rb
+++ b/app/controllers/projects/repositories_controller.rb
@@ -8,6 +8,8 @@ class Projects::RepositoriesController < Projects::ApplicationController
prepend_before_action(only: [:archive]) { authenticate_sessionless_user!(:archive) }
+ skip_before_action :default_cache_headers, only: :archive
+
# Authorize
before_action :require_non_empty_project, except: :create
before_action :archive_rate_limit!, only: :archive
diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb
index 544074f9840..24fa0894a9c 100644
--- a/app/controllers/projects/runners_controller.rb
+++ b/app/controllers/projects/runners_controller.rb
@@ -52,7 +52,7 @@ class Projects::RunnersController < Projects::ApplicationController
end
def toggle_shared_runners
- if Feature.enabled?(:disable_shared_runners_on_group, default_enabled: true) && !project.shared_runners_enabled && project.group && project.group.shared_runners_setting == 'disabled_and_unoverridable'
+ if !project.shared_runners_enabled && project.group && project.group.shared_runners_setting == 'disabled_and_unoverridable'
return redirect_to project_runners_path(@project), alert: _("Cannot enable shared runners because parent group does not allow it")
end
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index 93ad549bc50..6ed9f74297d 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -13,6 +13,8 @@ class Projects::ServicesController < Projects::ApplicationController
before_action :redirect_deprecated_prometheus_service, only: [:update]
before_action only: :edit do
push_frontend_feature_flag(:jira_issues_integration, @project, type: :licensed, default_enabled: true)
+ push_frontend_feature_flag(:jira_vulnerabilities_integration, @project, type: :licensed, default_enabled: true)
+ push_frontend_feature_flag(:jira_for_vulnerabilities, @project, type: :development, default_enabled: false)
end
respond_to :html
@@ -70,7 +72,7 @@ class Projects::ServicesController < Projects::ApplicationController
return { error: true, message: s_('Integrations|Connection failed. Please check your settings.'), service_response: result[:message].to_s, test_failed: true }
end
- {}
+ result[:data].presence || {}
rescue Gitlab::HTTP::BlockedUrlError => e
{ error: true, message: s_('Integrations|Connection failed. Please check your settings.'), service_response: e.message, test_failed: true }
end
diff --git a/app/controllers/projects/settings/access_tokens_controller.rb b/app/controllers/projects/settings/access_tokens_controller.rb
index cbd6716fdf7..74350147825 100644
--- a/app/controllers/projects/settings/access_tokens_controller.rb
+++ b/app/controllers/projects/settings/access_tokens_controller.rb
@@ -23,7 +23,7 @@ module Projects
redirect_to namespace_project_settings_access_tokens_path, notice: _("Your new project access token has been created.")
else
- render :index
+ redirect_to namespace_project_settings_access_tokens_path, alert: _("Failed to create new project access token: %{token_response_message}") % { token_response_message: token_response.message }
end
end
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index 2963321f803..f76278a12a4 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -5,10 +5,11 @@ module Projects
class CiCdController < Projects::ApplicationController
include RunnerSetupScripts
+ NUMBER_OF_RUNNERS_PER_PAGE = 20
+
before_action :authorize_admin_pipeline!
before_action :define_variables
before_action do
- push_frontend_feature_flag(:new_variables_ui, @project, default_enabled: true)
push_frontend_feature_flag(:ajax_new_deploy_token, @project)
end
@@ -76,7 +77,7 @@ module Projects
[
:runners_token, :builds_enabled, :build_allow_git_fetch,
:build_timeout_human_readable, :build_coverage_regex, :public_builds,
- :auto_cancel_pending_pipelines, :ci_config_path,
+ :auto_cancel_pending_pipelines, :ci_config_path, :auto_rollback_enabled,
auto_devops_attributes: [:id, :domain, :enabled, :deploy_strategy],
ci_cd_settings_attributes: [:default_git_depth, :forward_deployment_enabled]
].tap do |list|
@@ -109,13 +110,13 @@ module Projects
end
def define_runners_variables
- @project_runners = @project.runners.ordered
+ @project_runners = @project.runners.ordered.page(params[:project_page]).per(NUMBER_OF_RUNNERS_PER_PAGE).with_tags
@assignable_runners = current_user
.ci_owned_runners
.assignable_for(project)
.ordered
- .page(params[:page]).per(20)
+ .page(params[:specific_page]).per(NUMBER_OF_RUNNERS_PER_PAGE)
@shared_runners = ::Ci::Runner.instance_type.active
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
index c407b15e29f..c9386a2edec 100644
--- a/app/controllers/projects/settings/operations_controller.rb
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -6,6 +6,11 @@ module Projects
before_action :authorize_admin_operations!
before_action :authorize_read_prometheus_alerts!, only: [:reset_alerting_token]
+ before_action do
+ push_frontend_feature_flag(:http_integrations_list, @project)
+ push_frontend_feature_flag(:multiple_http_integrations_custom_mapping, @project)
+ end
+
respond_to :json, only: [:reset_alerting_token, :reset_pagerduty_token]
helper_method :error_tracking_setting
diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb
index 0994bebb1d0..dd50ab1bc7a 100644
--- a/app/controllers/projects/settings/repository_controller.rb
+++ b/app/controllers/projects/settings/repository_controller.rb
@@ -18,14 +18,13 @@ module Projects
end
def cleanup
- cleanup_params = params.require(:project).permit(:bfg_object_map)
- result = Projects::UpdateService.new(project, current_user, cleanup_params).execute
+ bfg_object_map = params.require(:project).require(:bfg_object_map)
+ result = Projects::CleanupService.enqueue(project, current_user, bfg_object_map)
if result[:status] == :success
- RepositoryCleanupWorker.perform_async(project.id, current_user.id) # rubocop:disable CodeReuse/Worker
flash[:notice] = _('Repository cleanup has started. You will receive an email once the cleanup operation is complete.')
else
- flash[:alert] = _('Failed to upload object map file')
+ flash[:alert] = status.fetch(:message, _('Failed to upload object map file'))
end
redirect_to project_settings_repository_path(project)
diff --git a/app/controllers/projects/static_site_editor_controller.rb b/app/controllers/projects/static_site_editor_controller.rb
index 7e2e32a843f..5c3d9b60877 100644
--- a/app/controllers/projects/static_site_editor_controller.rb
+++ b/app/controllers/projects/static_site_editor_controller.rb
@@ -6,12 +6,16 @@ class Projects::StaticSiteEditorController < Projects::ApplicationController
layout 'fullscreen'
+ content_security_policy do |policy|
+ next if policy.directives.blank?
+
+ frame_src_values = Array.wrap(policy.directives['frame-src']) | ['https://www.youtube.com']
+ policy.frame_src(*frame_src_values)
+ end
+
prepend_before_action :authenticate_user!, only: [:show]
before_action :assign_ref_and_path, only: [:show]
before_action :authorize_edit_tree!, only: [:show]
- before_action do
- push_frontend_feature_flag(:sse_image_uploads)
- end
feature_category :static_site_editor
@@ -47,6 +51,8 @@ class Projects::StaticSiteEditorController < Projects::ApplicationController
payload.transform_values do |value|
if value.is_a?(String) || value.is_a?(Integer)
value
+ elsif value.nil?
+ ''
else
value.to_json
end
diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb
index 1d783241196..94b0473e1f3 100644
--- a/app/controllers/projects/tags_controller.rb
+++ b/app/controllers/projects/tags_controller.rb
@@ -24,6 +24,7 @@ class Projects::TagsController < Projects::ApplicationController
tag_names = @tags.map(&:name)
@tags_pipelines = @project.ci_pipelines.latest_successful_for_refs(tag_names)
@releases = project.releases.where(tag: tag_names)
+ @tag_pipeline_statuses = Ci::CommitStatusesFinder.new(@project, @repository, current_user, @tags).execute
respond_to do |format|
format.html
diff --git a/app/controllers/projects/templates_controller.rb b/app/controllers/projects/templates_controller.rb
index 7ab23e39cf0..f4726638777 100644
--- a/app/controllers/projects/templates_controller.rb
+++ b/app/controllers/projects/templates_controller.rb
@@ -7,6 +7,14 @@ class Projects::TemplatesController < Projects::ApplicationController
feature_category :templates
+ def index
+ templates = @template_type.template_subsets(project)
+
+ respond_to do |format|
+ format.json { render json: templates.to_json }
+ end
+ end
+
def show
template = @template_type.find(params[:key], project)
diff --git a/app/controllers/projects/terraform_controller.rb b/app/controllers/projects/terraform_controller.rb
new file mode 100644
index 00000000000..aef163c98c5
--- /dev/null
+++ b/app/controllers/projects/terraform_controller.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class Projects::TerraformController < Projects::ApplicationController
+ before_action :authorize_can_read_terraform_state!
+
+ feature_category :infrastructure_as_code
+
+ def index
+ end
+
+ private
+
+ def authorize_can_read_terraform_state!
+ access_denied! unless can?(current_user, :read_terraform_state, project)
+ end
+end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 09e7563cefd..c03a820b384 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -15,7 +15,7 @@ class ProjectsController < Projects::ApplicationController
around_action :allow_gitaly_ref_name_caching, only: [:index, :show]
before_action :whitelist_query_limiting, only: [:create]
- before_action :authenticate_user!, except: [:index, :show, :activity, :refs, :resolve]
+ before_action :authenticate_user!, except: [:index, :show, :activity, :refs, :resolve, :unfoldered_environment_names]
before_action :redirect_git_extension, only: [:show]
before_action :project, except: [:index, :new, :create, :resolve]
before_action :repository, except: [:index, :new, :create, :resolve]
@@ -317,8 +317,6 @@ class ProjectsController < Projects::ApplicationController
end
def unfoldered_environment_names
- return render_404 unless Feature.enabled?(:deployment_filters)
-
respond_to do |format|
format.json do
render json: EnvironmentNamesFinder.new(@project, current_user).execute
@@ -383,6 +381,20 @@ class ProjectsController < Projects::ApplicationController
.merge(import_url_params)
end
+ def project_feature_attributes
+ %i[
+ builds_access_level
+ issues_access_level
+ forking_access_level
+ merge_requests_access_level
+ repository_access_level
+ snippets_access_level
+ wiki_access_level
+ pages_access_level
+ metrics_dashboard_access_level
+ ]
+ end
+
def project_params_attributes
[
:allow_merge_on_skipped_pipeline,
@@ -420,23 +432,11 @@ class ProjectsController < Projects::ApplicationController
:suggestion_commit_message,
:packages_enabled,
:service_desk_enabled,
-
- project_feature_attributes: %i[
- builds_access_level
- issues_access_level
- forking_access_level
- merge_requests_access_level
- repository_access_level
- snippets_access_level
- wiki_access_level
- pages_access_level
- metrics_dashboard_access_level
- ],
project_setting_attributes: %i[
show_default_award_emojis
squash_option
]
- ]
+ ] + [project_feature_attributes: project_feature_attributes]
end
def project_params_create_attributes
diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb
new file mode 100644
index 00000000000..5b3f78a92ad
--- /dev/null
+++ b/app/controllers/registrations/welcome_controller.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+module Registrations
+ class WelcomeController < ApplicationController
+ layout 'welcome'
+ skip_before_action :authenticate_user!, :required_signup_info, :check_two_factor_requirement, only: [:show, :update]
+ before_action :require_current_user
+
+ feature_category :authentication_and_authorization
+
+ def show
+ return redirect_to path_for_signed_in_user(current_user) if completed_welcome_step?
+ end
+
+ def update
+ result = ::Users::SignupService.new(current_user, update_params).execute
+
+ if result[:status] == :success
+ process_gitlab_com_tracking
+
+ return redirect_to new_users_sign_up_group_path if experiment_enabled?(:onboarding_issues) && show_onboarding_issues_experiment?
+
+ redirect_to path_for_signed_in_user(current_user)
+ else
+ render :show
+ end
+ end
+
+ private
+
+ def require_current_user
+ return redirect_to new_user_registration_path unless current_user
+ end
+
+ def completed_welcome_step?
+ current_user.role.present? && !current_user.setup_for_company.nil?
+ end
+
+ def process_gitlab_com_tracking
+ return false unless ::Gitlab.com?
+ return false unless show_onboarding_issues_experiment?
+
+ track_experiment_event(:onboarding_issues, 'signed_up')
+ record_experiment_user(:onboarding_issues)
+ end
+
+ def update_params
+ params.require(:user).permit(:role, :setup_for_company)
+ end
+
+ def requires_confirmation?(user)
+ return false if user.confirmed?
+ return false if Feature.enabled?(:soft_email_confirmation)
+
+ true
+ end
+
+ def path_for_signed_in_user(user)
+ return users_almost_there_path if requires_confirmation?(user)
+
+ stored_location_for(user) || dashboard_projects_path
+ end
+
+ def show_onboarding_issues_experiment?
+ !helpers.in_subscription_flow? &&
+ !helpers.in_invitation_flow? &&
+ !helpers.in_oauth_flow? &&
+ !helpers.in_trial_flow?
+ end
+ end
+end
+
+Registrations::WelcomeController.prepend_if_ee('EE::Registrations::WelcomeController')
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index b3dc0e986f4..04cb9616cf6 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -3,26 +3,22 @@
class RegistrationsController < Devise::RegistrationsController
include Recaptcha::Verify
include AcceptsPendingInvitations
- include RecaptchaExperimentHelper
+ include RecaptchaHelper
include InvisibleCaptchaOnSignup
BLOCKED_PENDING_APPROVAL_STATE = 'blocked_pending_approval'.freeze
- layout :choose_layout
+ layout 'devise'
- skip_before_action :required_signup_info, :check_two_factor_requirement, only: [:welcome, :update_registration]
prepend_before_action :check_captcha, only: :create
before_action :whitelist_query_limiting, :ensure_destroy_prerequisites_met, only: [:destroy]
before_action :load_recaptcha, only: :new
+ before_action :set_invite_params, only: :new
feature_category :authentication_and_authorization
def new
- if experiment_enabled?(:signup_flow)
- @resource = build_resource
- else
- redirect_to new_user_session_path(anchor: 'register-pane')
- end
+ @resource = build_resource
end
def create
@@ -32,6 +28,11 @@ class RegistrationsController < Devise::RegistrationsController
super do |new_user|
persist_accepted_terms_if_required(new_user)
set_role_required(new_user)
+
+ if pending_approval?
+ NotificationService.new.new_instance_access_request(new_user)
+ end
+
yield new_user if block_given?
end
@@ -52,31 +53,6 @@ class RegistrationsController < Devise::RegistrationsController
end
end
- def welcome
- return redirect_to new_user_registration_path unless current_user
- return redirect_to path_for_signed_in_user(current_user) if current_user.role.present? && !current_user.setup_for_company.nil?
- end
-
- def update_registration
- return redirect_to new_user_registration_path unless current_user
-
- user_params = params.require(:user).permit(:role, :setup_for_company)
- result = ::Users::SignupService.new(current_user, user_params).execute
-
- if result[:status] == :success
- if ::Gitlab.com? && show_onboarding_issues_experiment?
- track_experiment_event(:onboarding_issues, 'signed_up')
- record_experiment_user(:onboarding_issues)
- end
-
- return redirect_to new_users_sign_up_group_path if experiment_enabled?(:onboarding_issues) && show_onboarding_issues_experiment?
-
- redirect_to path_for_signed_in_user(current_user)
- else
- render :welcome
- end
- end
-
protected
def persist_accepted_terms_if_required(new_user)
@@ -160,6 +136,12 @@ class RegistrationsController < Devise::RegistrationsController
render action: 'new'
end
+ def pending_approval?
+ return false unless Gitlab::CurrentSettings.require_admin_approval_after_user_signup
+
+ resource.persisted? && resource.blocked_pending_approval?
+ end
+
def sign_up_params
params.require(:user).permit(:username, :email, :name, :first_name, :last_name, :password)
end
@@ -180,49 +162,17 @@ class RegistrationsController < Devise::RegistrationsController
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42380')
end
- def path_for_signed_in_user(user)
- if requires_confirmation?(user)
- users_almost_there_path
- else
- stored_location_for(user) || dashboard_projects_path
- end
- end
-
- def requires_confirmation?(user)
- return false if user.confirmed?
- return false if Feature.enabled?(:soft_email_confirmation)
- return false if experiment_enabled?(:signup_flow)
-
- true
- end
-
def load_recaptcha
Gitlab::Recaptcha.load_configurations!
end
- # 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 %w(welcome update_registration).include?(action_name) || experiment_enabled?(:signup_flow)
- 'devise_experimental_separate_sign_up_flow'
- else
- 'devise'
- end
- end
-
- def show_onboarding_issues_experiment?
- !helpers.in_subscription_flow? &&
- !helpers.in_invitation_flow? &&
- !helpers.in_oauth_flow? &&
- !helpers.in_trial_flow?
- end
-
def set_user_state
- return unless Feature.enabled?(:admin_approval_for_new_user_signups, default_enabled: true)
return unless Gitlab::CurrentSettings.require_admin_approval_after_user_signup
resource.state = BLOCKED_PENDING_APPROVAL_STATE
end
-end
-RegistrationsController.prepend_if_ee('EE::RegistrationsController')
+ def set_invite_params
+ @invite_email = ActionController::Base.helpers.sanitize(params[:invite_email])
+ end
+end
diff --git a/app/controllers/repositories/git_http_client_controller.rb b/app/controllers/repositories/git_http_client_controller.rb
index de452aa69b7..ec854bd0dde 100644
--- a/app/controllers/repositories/git_http_client_controller.rb
+++ b/app/controllers/repositories/git_http_client_controller.rb
@@ -6,7 +6,7 @@ module Repositories
include KerberosSpnegoHelper
include Gitlab::Utils::StrongMemoize
- attr_reader :authentication_result, :redirected_path, :container
+ attr_reader :authentication_result, :redirected_path
delegate :actor, :authentication_abilities, to: :authentication_result, allow_nil: true
delegate :type, to: :authentication_result, allow_nil: true, prefix: :auth_result
@@ -75,6 +75,12 @@ module Repositories
headers['Www-Authenticate'] = challenges.join("\n") if challenges.any?
end
+ def container
+ parse_repo_path unless defined?(@container)
+
+ @container
+ end
+
def project
parse_repo_path unless defined?(@project)
diff --git a/app/controllers/repositories/lfs_api_controller.rb b/app/controllers/repositories/lfs_api_controller.rb
index 35751a2578f..96185608c09 100644
--- a/app/controllers/repositories/lfs_api_controller.rb
+++ b/app/controllers/repositories/lfs_api_controller.rb
@@ -17,9 +17,9 @@ module Repositories
end
if download_request?
- render json: { objects: download_objects! }
+ render json: { objects: download_objects! }, content_type: LfsRequest::CONTENT_TYPE
elsif upload_request?
- render json: { objects: upload_objects! }
+ render json: { objects: upload_objects! }, content_type: LfsRequest::CONTENT_TYPE
else
raise "Never reached"
end
@@ -31,6 +31,7 @@ module Repositories
message: _('Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.'),
documentation_url: "#{Gitlab.config.gitlab.url}/help"
},
+ content_type: LfsRequest::CONTENT_TYPE,
status: :not_implemented
)
end
diff --git a/app/controllers/repositories/lfs_storage_controller.rb b/app/controllers/repositories/lfs_storage_controller.rb
index 0436b740979..48784842d48 100644
--- a/app/controllers/repositories/lfs_storage_controller.rb
+++ b/app/controllers/repositories/lfs_storage_controller.rb
@@ -29,7 +29,7 @@ module Repositories
def upload_finalize
if store_file!(oid, size)
- head 200
+ head 200, content_type: LfsRequest::CONTENT_TYPE
else
render plain: 'Unprocessable entity', status: :unprocessable_entity
end
@@ -59,10 +59,17 @@ module Repositories
params[:size].to_i
end
+ def uploaded_file
+ params[:file]
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def store_file!(oid, size)
object = LfsObject.find_by(oid: oid, size: size)
- unless object&.file&.exists?
+
+ if object
+ replace_file!(object) unless object.file&.exists?
+ else
object = create_file!(oid, size)
end
@@ -73,12 +80,19 @@ module Repositories
# rubocop: enable CodeReuse/ActiveRecord
def create_file!(oid, size)
- uploaded_file = params[:file]
return unless uploaded_file.is_a?(UploadedFile)
LfsObject.create!(oid: oid, size: size, file: uploaded_file)
end
+ def replace_file!(lfs_object)
+ raise UploadedFile::InvalidPathError unless uploaded_file.is_a?(UploadedFile)
+
+ Gitlab::AppJsonLogger.info(message: "LFS file replaced because it did not exist", oid: oid, size: size)
+ lfs_object.file = uploaded_file
+ lfs_object.save!
+ end
+
def link_to_project!(object)
return unless object
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 0380bc1c548..4b21edc98d5 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -9,6 +9,7 @@ class SearchController < ApplicationController
SCOPE_PRELOAD_METHOD = {
projects: :with_web_entity_associations,
issues: :with_web_entity_associations,
+ merge_requests: :with_web_entity_associations,
epics: :with_web_entity_associations
}.freeze
@@ -35,7 +36,10 @@ class SearchController < ApplicationController
return unless search_term_valid?
+ return if check_single_commit_result?
+
@search_term = params[:search]
+ @sort = params[:sort] || default_sort
@scope = search_service.scope
@show_snippets = search_service.show_snippets?
@@ -47,8 +51,6 @@ class SearchController < ApplicationController
eager_load_user_status if @scope == 'users'
increment_search_counters
-
- check_single_commit_result
end
def count
@@ -81,6 +83,11 @@ class SearchController < ApplicationController
SCOPE_PRELOAD_METHOD[@scope.to_sym]
end
+ # overridden in EE
+ def default_sort
+ 'created_desc'
+ end
+
def search_term_valid?
unless search_service.valid_query_length?
flash[:alert] = t('errors.messages.search_chars_too_long', count: SearchService::SEARCH_CHAR_LIMIT)
@@ -103,14 +110,23 @@ class SearchController < ApplicationController
@search_objects = @search_objects.eager_load(:status) # rubocop:disable CodeReuse/ActiveRecord
end
- def check_single_commit_result
- if @search_results.single_commit_result?
- only_commit = @search_results.objects('commits').first
- query = params[:search].strip.downcase
- found_by_commit_sha = Commit.valid_hash?(query) && only_commit.sha.start_with?(query)
+ def check_single_commit_result?
+ return false if params[:force_search_results]
+ return false unless @project.present?
+ # download_code project policy grants user the read_commit ability
+ return false unless Ability.allowed?(current_user, :download_code, @project)
- redirect_to project_commit_path(@project, only_commit) if found_by_commit_sha
- end
+ query = params[:search].strip.downcase
+ return false unless Commit.valid_hash?(query)
+
+ commit = @project.commit_by(oid: query)
+ return false unless commit.present?
+
+ link = search_path(safe_params.merge(force_search_results: true))
+ flash[:notice] = html_escape(_("You have been redirected to the only result; see the %{a_start}search results%{a_end} instead.")) % { a_start: "<a href=\"#{link}\"><u>".html_safe, a_end: '</u></a>'.html_safe }
+ redirect_to project_commit_path(@project, commit)
+
+ true
end
def increment_search_counters
@@ -130,6 +146,9 @@ class SearchController < ApplicationController
payload[:metadata]['meta.search.project_id'] = params[:project_id]
payload[:metadata]['meta.search.search'] = params[:search]
payload[:metadata]['meta.search.scope'] = params[:scope]
+ payload[:metadata]['meta.search.filters.confidential'] = params[:confidential]
+ payload[:metadata]['meta.search.filters.state'] = params[:state]
+ payload[:metadata]['meta.search.force_search_results'] = params[:force_search_results]
end
def block_anonymous_global_searches
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 61120c5b7d1..b8842b2efdb 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -300,13 +300,13 @@ class SessionsController < Devise::SessionsController
def authentication_method
if user_params[:otp_attempt]
- "two-factor"
+ AuthenticationEvent::TWO_FACTOR
elsif user_params[:device_response] && Feature.enabled?(:webauthn)
- "two-factor-via-webauthn-device"
+ AuthenticationEvent::TWO_FACTOR_WEBAUTHN
elsif user_params[:device_response] && !Feature.enabled?(:webauthn)
- "two-factor-via-u2f-device"
+ AuthenticationEvent::TWO_FACTOR_U2F
else
- "standard"
+ AuthenticationEvent::STANDARD
end
end
diff --git a/app/controllers/whats_new_controller.rb b/app/controllers/whats_new_controller.rb
index 7156faa4e49..384c984089a 100644
--- a/app/controllers/whats_new_controller.rb
+++ b/app/controllers/whats_new_controller.rb
@@ -5,14 +5,14 @@ class WhatsNewController < ApplicationController
skip_before_action :authenticate_user!
- before_action :check_feature_flag
+ before_action :check_feature_flag, :check_valid_page_param, :set_pagination_headers
feature_category :navigation
def index
respond_to do |format|
format.js do
- render json: whats_new_most_recent_release_items
+ render json: whats_new_release_items(page: current_page)
end
end
end
@@ -22,4 +22,23 @@ class WhatsNewController < ApplicationController
def check_feature_flag
render_404 unless Feature.enabled?(:whats_new_drawer, current_user)
end
+
+ def check_valid_page_param
+ render_404 if current_page < 1
+ end
+
+ def set_pagination_headers
+ response.set_header('X-Next-Page', next_page)
+ end
+
+ def current_page
+ params[:page]&.to_i || 1
+ end
+
+ def next_page
+ next_page = current_page + 1
+ next_index = next_page - 1
+
+ next_page if whats_new_file_paths[next_index]
+ end
end
diff --git a/app/finders/alert_management/http_integrations_finder.rb b/app/finders/alert_management/http_integrations_finder.rb
new file mode 100644
index 00000000000..9f511be0ace
--- /dev/null
+++ b/app/finders/alert_management/http_integrations_finder.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module AlertManagement
+ class HttpIntegrationsFinder
+ def initialize(project, params)
+ @project = project
+ @params = params
+ end
+
+ def execute
+ @collection = project.alert_management_http_integrations
+
+ filter_by_availability
+ filter_by_endpoint_identifier
+ filter_by_active
+
+ collection
+ end
+
+ private
+
+ attr_reader :project, :params, :collection
+
+ def filter_by_availability
+ return if multiple_alert_http_integrations?
+
+ first_id = project.alert_management_http_integrations
+ .ordered_by_id
+ .select(:id)
+ .at_most(1)
+
+ @collection = collection.id_in(first_id)
+ end
+
+ def filter_by_endpoint_identifier
+ return unless params[:endpoint_identifier]
+
+ @collection = collection.for_endpoint_identifier(params[:endpoint_identifier])
+ end
+
+ def filter_by_active
+ return unless params[:active]
+
+ @collection = collection.active
+ end
+
+ # Overridden in EE
+ def multiple_alert_http_integrations?
+ false
+ end
+ end
+end
+
+::AlertManagement::HttpIntegrationsFinder.prepend_if_ee('EE::AlertManagement::HttpIntegrationsFinder')
diff --git a/app/finders/ci/commit_statuses_finder.rb b/app/finders/ci/commit_statuses_finder.rb
new file mode 100644
index 00000000000..3c465eb88f3
--- /dev/null
+++ b/app/finders/ci/commit_statuses_finder.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Ci
+ class CommitStatusesFinder
+ include ::Gitlab::Utils::StrongMemoize
+
+ def initialize(project, repository, current_user, refs)
+ @project = project
+ @repository = repository
+ @current_user = current_user
+ @refs = refs
+ end
+
+ def execute
+ return [] unless Ability.allowed?(@current_user, :read_pipeline, @project)
+
+ commit_statuses
+ end
+
+ private
+
+ def latest_commits
+ strong_memoize(:latest_commits) do
+ refs.map do |ref|
+ [ref.name, @repository.commit(ref.dereferenced_target).sha]
+ end.to_h
+ end
+ end
+
+ def commit_statuses
+ latest_pipelines = project.ci_pipelines.latest_pipeline_per_commit(latest_commits.values)
+
+ latest_commits.transform_values do |commit_sha|
+ latest_pipelines[commit_sha]&.detailed_status(current_user)
+ end.compact
+ end
+
+ attr_reader :project, :repository, :current_user, :refs
+ end
+end
diff --git a/app/finders/ci/jobs_finder.rb b/app/finders/ci/jobs_finder.rb
index 40c610f8209..78791d737da 100644
--- a/app/finders/ci/jobs_finder.rb
+++ b/app/finders/ci/jobs_finder.rb
@@ -25,11 +25,7 @@ module Ci
attr_reader :current_user, :pipeline, :project, :params, :type
def init_collection
- if Feature.enabled?(:ci_jobs_finder_refactor, default_enabled: true)
- pipeline_jobs || project_jobs || all_jobs
- else
- project ? project_builds : all_jobs
- end
+ pipeline_jobs || project_jobs || all_jobs
end
def all_jobs
@@ -38,12 +34,6 @@ module Ci
type.all
end
- def project_builds
- raise Gitlab::Access::AccessDeniedError unless can?(current_user, :read_build, project)
-
- project.builds.relevant
- end
-
def project_jobs
return unless project
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :read_build, project)
@@ -59,9 +49,7 @@ module Ci
end
def filter_by_scope(builds)
- if Feature.enabled?(:ci_jobs_finder_refactor, default_enabled: true)
- return filter_by_statuses!(params[:scope], builds) if params[:scope].is_a?(Array)
- end
+ return filter_by_statuses!(params[:scope], builds) if params[:scope].is_a?(Array)
case params[:scope]
when 'pending'
diff --git a/app/finders/concerns/finder_with_cross_project_access.rb b/app/finders/concerns/finder_with_cross_project_access.rb
index a55fb58a1bc..e63b868e470 100644
--- a/app/finders/concerns/finder_with_cross_project_access.rb
+++ b/app/finders/concerns/finder_with_cross_project_access.rb
@@ -32,7 +32,7 @@ module FinderWithCrossProjectAccess
end
override :execute
- def execute(*args)
+ def execute(*args, **kwargs)
check = Gitlab::CrossProjectAccess.find_check(self)
original = -> { super }
diff --git a/app/finders/environment_names_finder.rb b/app/finders/environment_names_finder.rb
index a92998921c7..e9063ef4c90 100644
--- a/app/finders/environment_names_finder.rb
+++ b/app/finders/environment_names_finder.rb
@@ -13,7 +13,7 @@
class EnvironmentNamesFinder
attr_reader :project_or_group, :current_user
- def initialize(project_or_group, current_user)
+ def initialize(project_or_group, current_user = nil)
@project_or_group = project_or_group
@current_user = current_user
end
@@ -31,14 +31,24 @@ class EnvironmentNamesFinder
end
def namespace_environments
- projects =
- project_or_group.all_projects.public_or_visible_to_user(current_user)
+ # We assume reporter access is needed for the :read_environment permission
+ # here. This expection is also present in
+ # IssuableFinder::Params#min_access_level, which is used for filtering out
+ # merge requests that don't have the right permissions.
+ #
+ # We use this approach so we don't need to load every project into memory
+ # just to verify if we can see their environments. Doing so would not be
+ # efficient, and possibly mess up pagination if certain projects are not
+ # meant to be visible.
+ projects = project_or_group
+ .all_projects
+ .public_or_visible_to_user(current_user, Gitlab::Access::REPORTER)
Environment.for_project(projects)
end
def project_environments
- if current_user.can?(:read_environment, project_or_group)
+ if Ability.allowed?(current_user, :read_environment, project_or_group)
project_or_group.environments
else
Environment.none
diff --git a/app/finders/feature_flags_user_lists_finder.rb b/app/finders/feature_flags_user_lists_finder.rb
new file mode 100644
index 00000000000..ebe60acd711
--- /dev/null
+++ b/app/finders/feature_flags_user_lists_finder.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+class FeatureFlagsUserListsFinder
+ attr_reader :project, :current_user, :params
+
+ def initialize(project, current_user, params = {})
+ @project = project
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute
+ unless Ability.allowed?(current_user, :read_feature_flag, project)
+ return Operations::FeatureFlagsUserList.none
+ end
+
+ items = feature_flags_user_lists
+ by_search(items)
+ end
+
+ private
+
+ def feature_flags_user_lists
+ project.operations_feature_flags_user_lists
+ end
+
+ def by_search(items)
+ if params[:search].present?
+ items.for_name_like(params[:search])
+ else
+ items
+ end
+ end
+end
diff --git a/app/finders/group_projects_finder.rb b/app/finders/group_projects_finder.rb
index 5f24b15156c..8362e782ad1 100644
--- a/app/finders/group_projects_finder.rb
+++ b/app/finders/group_projects_finder.rb
@@ -12,6 +12,7 @@
# only_owned: boolean
# only_shared: boolean
# limit: integer
+# include_subgroups: boolean
# params:
# sort: string
# visibility_level: int
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 9c4aecedd93..d431c3e3699 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -153,10 +153,8 @@ class IssuableFinder
end
def row_count
- fast_fail = Feature.enabled?(:soft_fail_count_by_state, params.group || params.project)
-
Gitlab::IssuablesCountForState
- .new(self, nil, fast_fail: fast_fail)
+ .new(self, nil, fast_fail: true)
.for_state_or_opened(params[:state])
end
@@ -341,6 +339,15 @@ class IssuableFinder
cte << items
items = klass.with(cte.to_arel).from(klass.table_name)
+ elsif Feature.enabled?(:pg_hint_plan_for_issuables, params.project)
+ items = items.optimizer_hints(<<~HINTS)
+ BitmapScan(
+ issues idx_issues_on_project_id_and_created_at_and_id_and_state_id
+ idx_issues_on_project_id_and_due_date_and_id_and_state_id
+ idx_issues_on_project_id_and_updated_at_and_id_and_state_id
+ index_issues_on_project_id_and_iid
+ )
+ HINTS
end
items.full_search(search, matched_columns: params[:in], use_minimum_char_limit: !use_cte_for_search?)
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index 32be5bee0db..5c9010ee3e0 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -97,6 +97,8 @@ class IssuesFinder < IssuableFinder
items.due_between(Date.today.beginning_of_month, Date.today.end_of_month)
elsif params.filter_by_due_next_month_and_previous_two_weeks?
items.due_between(Date.today - 2.weeks, (Date.today + 1.month).end_of_month)
+ else
+ items.none
end
end
diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb
index c998de75ab2..1f847b09752 100644
--- a/app/finders/merge_requests_finder.rb
+++ b/app/finders/merge_requests_finder.rb
@@ -66,6 +66,11 @@ class MergeRequestsFinder < IssuableFinder
by_source_project_id(items)
end
+ def filter_negated_items(items)
+ items = super(items)
+ by_negated_target_branch(items)
+ end
+
private
def by_commit(items)
@@ -98,6 +103,14 @@ class MergeRequestsFinder < IssuableFinder
end
# rubocop: enable CodeReuse/ActiveRecord
+ # rubocop: disable CodeReuse/ActiveRecord
+ def by_negated_target_branch(items)
+ return items unless not_params[:target_branch]
+
+ items.where.not(target_branch: not_params[:target_branch])
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
def source_project_id
@source_project_id ||= params[:source_project_id].presence
end
@@ -142,19 +155,6 @@ class MergeRequestsFinder < IssuableFinder
.or(table[:title].matches('(Draft)%'))
end
- # rubocop: disable CodeReuse/ActiveRecord
- def by_deployment(items)
- return items unless deployment_id
-
- items.includes(:deployment_merge_requests)
- .where(deployment_merge_requests: { deployment_id: deployment_id })
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def deployment_id
- @deployment_id ||= params[:deployment_id].presence
- end
-
# Filter by merge requests that had been approved by specific users
# rubocop: disable CodeReuse/Finder
def by_approvals(items)
@@ -165,10 +165,6 @@ class MergeRequestsFinder < IssuableFinder
# rubocop: enable CodeReuse/Finder
def by_deployments(items)
- # Until this feature flag is enabled permanently, we retain the old
- # filtering behaviour/code.
- return by_deployment(items) unless Feature.enabled?(:deployment_filters)
-
env = params[:environment]
before = params[:deployed_before]
after = params[:deployed_after]
diff --git a/app/finders/packages/group_packages_finder.rb b/app/finders/packages/group_packages_finder.rb
index 8b948bb056d..a51057571f1 100644
--- a/app/finders/packages/group_packages_finder.rb
+++ b/app/finders/packages/group_packages_finder.rb
@@ -25,7 +25,7 @@ module Packages
.including_build_info
.including_project_route
.including_tags
- .for_projects(group_projects_visible_to_current_user)
+ .for_projects(group_projects_visible_to_current_user.select(:id))
.processed
.has_version
.sort_by_attribute("#{params[:order_by]}_#{params[:sort]}")
@@ -36,11 +36,14 @@ module Packages
end
def group_projects_visible_to_current_user
+ # according to project_policy.rb
+ # access to packages is ruled by:
+ # - project is public or the current user has access to it with at least the reporter level
+ # - the repository feature is available to the current_user
::Project
.in_namespace(groups)
.public_or_visible_to_user(current_user, Gitlab::Access::REPORTER)
- .with_project_feature
- .select { |project| Ability.allowed?(current_user, :read_package, project) }
+ .with_feature_available_for_user(:repository, current_user)
end
def package_type
diff --git a/app/finders/packages/npm/package_finder.rb b/app/finders/packages/npm/package_finder.rb
index 8599fd07e7f..2854226e178 100644
--- a/app/finders/packages/npm/package_finder.rb
+++ b/app/finders/packages/npm/package_finder.rb
@@ -12,6 +12,8 @@ module Packages
end
def execute
+ return Packages::Package.none unless project
+
packages
end
diff --git a/app/finders/personal_access_tokens_finder.rb b/app/finders/personal_access_tokens_finder.rb
index 93f8c520b63..4a6eed8f5ee 100644
--- a/app/finders/personal_access_tokens_finder.rb
+++ b/app/finders/personal_access_tokens_finder.rb
@@ -14,6 +14,7 @@ class PersonalAccessTokensFinder
tokens = PersonalAccessToken.all
tokens = by_current_user(tokens)
tokens = by_user(tokens)
+ tokens = by_users(tokens)
tokens = by_impersonation(tokens)
tokens = by_state(tokens)
@@ -37,6 +38,12 @@ class PersonalAccessTokensFinder
tokens.for_user(@params[:user])
end
+ def by_users(tokens)
+ return tokens unless @params[:users]
+
+ tokens.for_users(@params[:users])
+ end
+
def sort(tokens)
available_sort_orders = PersonalAccessToken.simple_sorts.keys
diff --git a/app/finders/security/jobs_finder.rb b/app/finders/security/jobs_finder.rb
new file mode 100644
index 00000000000..e2efb2e18c9
--- /dev/null
+++ b/app/finders/security/jobs_finder.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+# Security::JobsFinder
+#
+# Abstract class encapsulating common logic for finding jobs (builds) that are related to the Secure products
+# SAST, DAST, Dependency Scanning, Container Scanning and License Management, Coverage Fuzzing
+#
+# Arguments:
+# params:
+# pipeline: required, only jobs for the specified pipeline will be found
+# job_types: required, array of job types that should be returned, defaults to all job types
+
+module Security
+ class JobsFinder
+ attr_reader :pipeline
+
+ def self.allowed_job_types
+ # Example return: [:sast, :dast, :dependency_scanning, :container_scanning, :license_management, :coverage_fuzzing]
+ raise NotImplementedError, 'allowed_job_types must be overwritten to return an array of job types'
+ end
+
+ def initialize(pipeline:, job_types: [])
+ if self.class == Security::JobsFinder
+ raise NotImplementedError, 'This is an abstract class, please instantiate its descendants'
+ end
+
+ if job_types.empty?
+ @job_types = self.class.allowed_job_types
+ elsif valid_job_types?(job_types)
+ @job_types = job_types
+ else
+ raise ArgumentError, "job_types must be from the following: #{self.class.allowed_job_types}"
+ end
+
+ @pipeline = pipeline
+ end
+
+ def execute
+ return [] if @job_types.empty?
+
+ if Feature.enabled?(:ci_build_metadata_config)
+ find_jobs
+ else
+ find_jobs_legacy
+ end
+ end
+
+ private
+
+ def find_jobs
+ @pipeline.builds.with_secure_reports_from_config_options(@job_types)
+ end
+
+ def find_jobs_legacy
+ # the query doesn't guarantee accuracy, so we verify it here
+ legacy_jobs_query.select do |job|
+ @job_types.find { |job_type| job.options.dig(:artifacts, :reports, job_type) }
+ end
+ end
+
+ def legacy_jobs_query
+ @job_types.map do |job_type|
+ @pipeline.builds.with_secure_reports_from_options(job_type)
+ end.reduce(&:or)
+ end
+
+ def valid_job_types?(job_types)
+ (job_types - self.class.allowed_job_types).empty?
+ end
+ end
+end
diff --git a/app/finders/security/license_compliance_jobs_finder.rb b/app/finders/security/license_compliance_jobs_finder.rb
new file mode 100644
index 00000000000..100f94b2cc7
--- /dev/null
+++ b/app/finders/security/license_compliance_jobs_finder.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# Security::LicenseScanningJobsFinder
+#
+# Used to find jobs (builds) that are related to the License Management.
+#
+# Arguments:
+# params:
+# pipeline: required, only jobs for the specified pipeline will be found
+# job_types: required, array of job types that should be returned, defaults to all job types
+
+module Security
+ class LicenseComplianceJobsFinder < JobsFinder
+ def self.allowed_job_types
+ [:license_management, :license_scanning]
+ end
+ end
+end
diff --git a/app/finders/security/security_jobs_finder.rb b/app/finders/security/security_jobs_finder.rb
new file mode 100644
index 00000000000..2352e19c7da
--- /dev/null
+++ b/app/finders/security/security_jobs_finder.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# Security::SecurityJobsFinder
+#
+# Used to find jobs (builds) that are related to the Secure products:
+# SAST, DAST, Dependency Scanning and Container Scanning
+#
+# Arguments:
+# params:
+# pipeline: required, only jobs for the specified pipeline will be found
+# job_types: required, array of job types that should be returned, defaults to all job types
+
+module Security
+ class SecurityJobsFinder < JobsFinder
+ def self.allowed_job_types
+ [:sast, :dast, :dependency_scanning, :container_scanning, :secret_detection, :coverage_fuzzing, :api_fuzzing]
+ end
+ end
+end
diff --git a/app/finders/user_groups_counter.rb b/app/finders/user_groups_counter.rb
new file mode 100644
index 00000000000..7dbc8502be2
--- /dev/null
+++ b/app/finders/user_groups_counter.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class UserGroupsCounter
+ def initialize(user_ids)
+ @user_ids = user_ids
+ end
+
+ def execute
+ Namespace.unscoped do
+ Namespace.from_union([
+ groups,
+ project_groups
+ ]).group(:user_id).count # rubocop: disable CodeReuse/ActiveRecord
+ end
+ end
+
+ private
+
+ attr_reader :user_ids
+
+ def groups
+ Group.for_authorized_group_members(user_ids)
+ .select('namespaces.*, members.user_id as user_id')
+ end
+
+ def project_groups
+ Group.for_authorized_project_members(user_ids)
+ .select('namespaces.*, project_authorizations.user_id as user_id')
+ end
+end
diff --git a/app/graphql/gitlab_schema.rb b/app/graphql/gitlab_schema.rb
index 2f5043f9ffa..d66a2333d11 100644
--- a/app/graphql/gitlab_schema.rb
+++ b/app/graphql/gitlab_schema.rb
@@ -30,6 +30,8 @@ class GitlabSchema < GraphQL::Schema
default_max_page_size 100
+ lazy_resolve ::Gitlab::Graphql::Lazy, :force
+
class << self
def multiplex(queries, **kwargs)
kwargs[:max_complexity] ||= max_query_complexity(kwargs[:context])
@@ -76,6 +78,13 @@ class GitlabSchema < GraphQL::Schema
find_by_gid(gid)
end
+ def resolve_type(type, object, ctx = :__undefined__)
+ tc = type.metadata[:type_class]
+ return if tc.respond_to?(:assignable?) && !tc.assignable?(object)
+
+ super
+ end
+
# Find an object by looking it up from its 'GlobalID'.
#
# * For `ApplicationRecord`s, this is equivalent to
diff --git a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
index a3a421f8938..17f9b5b5637 100644
--- a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
+++ b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
@@ -33,9 +33,9 @@ module Mutations
super
end
- def resolve(args)
+ def resolve(queue_name:, **args)
{
- result: Gitlab::SidekiqQueue.new(args[:queue_name]).drop_jobs!(args, timeout: 30),
+ result: Gitlab::SidekiqQueue.new(queue_name).drop_jobs!(args, timeout: 30),
errors: []
}
rescue Gitlab::SidekiqQueue::NoMetadataError
@@ -44,7 +44,7 @@ module Mutations
errors: ['No metadata provided']
}
rescue Gitlab::SidekiqQueue::InvalidQueueError
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, "Queue #{args[:queue_name]} not found"
+ raise Gitlab::Graphql::Errors::ResourceNotAvailable, "Queue #{queue_name} not found"
end
end
end
diff --git a/app/graphql/mutations/alert_management/base.rb b/app/graphql/mutations/alert_management/base.rb
index 0ccfcf34180..81d5ee95f06 100644
--- a/app/graphql/mutations/alert_management/base.rb
+++ b/app/graphql/mutations/alert_management/base.rb
@@ -4,7 +4,6 @@ module Mutations
module AlertManagement
class Base < BaseMutation
include Gitlab::Utils::UsageData
- include ResolvesProject
argument :project_path, GraphQL::ID_TYPE,
required: true,
@@ -33,13 +32,12 @@ module Mutations
private
- def find_object(project_path:, iid:)
- project = resolve_project(full_path: project_path)
+ def find_object(project_path:, **args)
+ project = Project.find_by_full_path(project_path)
return unless project
- resolver = Resolvers::AlertManagement::AlertResolver.single.new(object: project, context: context, field: nil)
- resolver.resolve(iid: iid)
+ ::AlertManagement::AlertsFinder.new(current_user, project, args).execute.first
end
end
end
diff --git a/app/graphql/mutations/alert_management/http_integration/create.rb b/app/graphql/mutations/alert_management/http_integration/create.rb
new file mode 100644
index 00000000000..ddb75e66bb4
--- /dev/null
+++ b/app/graphql/mutations/alert_management/http_integration/create.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module HttpIntegration
+ class Create < HttpIntegrationBase
+ include ResolvesProject
+
+ graphql_name 'HttpIntegrationCreate'
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: 'The project to create the integration in'
+
+ argument :name, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'The name of the integration'
+
+ argument :active, GraphQL::BOOLEAN_TYPE,
+ required: true,
+ description: 'Whether the integration is receiving alerts'
+
+ def resolve(args)
+ project = authorized_find!(full_path: args[:project_path])
+
+ response ::AlertManagement::HttpIntegrations::CreateService.new(
+ project,
+ current_user,
+ args.slice(:name, :active)
+ ).execute
+ end
+
+ private
+
+ def find_object(full_path:)
+ resolve_project(full_path: full_path)
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/http_integration/destroy.rb b/app/graphql/mutations/alert_management/http_integration/destroy.rb
new file mode 100644
index 00000000000..0f478760aab
--- /dev/null
+++ b/app/graphql/mutations/alert_management/http_integration/destroy.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module HttpIntegration
+ class Destroy < HttpIntegrationBase
+ graphql_name 'HttpIntegrationDestroy'
+
+ argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
+ required: true,
+ description: "The id of the integration to remove"
+
+ def resolve(id:)
+ integration = authorized_find!(id: id)
+
+ response ::AlertManagement::HttpIntegrations::DestroyService.new(
+ integration,
+ current_user
+ ).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb b/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb
new file mode 100644
index 00000000000..d328eabf244
--- /dev/null
+++ b/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module HttpIntegration
+ class HttpIntegrationBase < BaseMutation
+ field :integration,
+ Types::AlertManagement::HttpIntegrationType,
+ null: true,
+ description: "The HTTP integration"
+
+ authorize :admin_operations
+
+ private
+
+ def find_object(id:)
+ GitlabSchema.object_from_id(id, expected_class: ::AlertManagement::HttpIntegration)
+ end
+
+ def response(result)
+ {
+ integration: result.payload[:integration],
+ errors: result.errors
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/http_integration/reset_token.rb b/app/graphql/mutations/alert_management/http_integration/reset_token.rb
new file mode 100644
index 00000000000..eefab156825
--- /dev/null
+++ b/app/graphql/mutations/alert_management/http_integration/reset_token.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module HttpIntegration
+ class ResetToken < HttpIntegrationBase
+ graphql_name 'HttpIntegrationResetToken'
+
+ argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
+ required: true,
+ description: "The id of the integration to mutate"
+
+ def resolve(id:)
+ integration = authorized_find!(id: id)
+
+ response ::AlertManagement::HttpIntegrations::UpdateService.new(
+ integration,
+ current_user,
+ regenerate_token: true
+ ).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/http_integration/update.rb b/app/graphql/mutations/alert_management/http_integration/update.rb
new file mode 100644
index 00000000000..309c45b04ac
--- /dev/null
+++ b/app/graphql/mutations/alert_management/http_integration/update.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module HttpIntegration
+ class Update < HttpIntegrationBase
+ graphql_name 'HttpIntegrationUpdate'
+
+ argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
+ required: true,
+ description: "The id of the integration to mutate"
+
+ argument :name, GraphQL::STRING_TYPE,
+ required: false,
+ description: "The name of the integration"
+
+ argument :active, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: "Whether the integration is receiving alerts"
+
+ def resolve(args)
+ integration = authorized_find!(id: args[:id])
+
+ response ::AlertManagement::HttpIntegrations::UpdateService.new(
+ integration,
+ current_user,
+ args.slice(:name, :active)
+ ).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/create.rb b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
new file mode 100644
index 00000000000..935ec53795c
--- /dev/null
+++ b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module PrometheusIntegration
+ class Create < PrometheusIntegrationBase
+ include ResolvesProject
+
+ graphql_name 'PrometheusIntegrationCreate'
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: 'The project to create the integration in'
+
+ argument :active, GraphQL::BOOLEAN_TYPE,
+ required: true,
+ description: 'Whether the integration is receiving alerts'
+
+ argument :api_url, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Endpoint at which prometheus can be queried'
+
+ def resolve(args)
+ project = authorized_find!(full_path: args[:project_path])
+
+ return integration_exists if project.prometheus_service
+
+ result = ::Projects::Operations::UpdateService.new(
+ project,
+ current_user,
+ **integration_attributes(args),
+ **token_attributes
+ ).execute
+
+ response(project.prometheus_service, result)
+ end
+
+ private
+
+ def find_object(full_path:)
+ resolve_project(full_path: full_path)
+ end
+
+ def integration_exists
+ response(nil, message: _('Multiple Prometheus integrations are not supported'))
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb b/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb
new file mode 100644
index 00000000000..6b690ac239a
--- /dev/null
+++ b/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module PrometheusIntegration
+ class PrometheusIntegrationBase < BaseMutation
+ field :integration,
+ Types::AlertManagement::PrometheusIntegrationType,
+ null: true,
+ description: "The newly created integration"
+
+ authorize :admin_project
+
+ private
+
+ def find_object(id:)
+ GitlabSchema.object_from_id(id, expected_class: ::PrometheusService)
+ end
+
+ def response(integration, result)
+ {
+ integration: integration,
+ errors: Array(result[:message])
+ }
+ end
+
+ def integration_attributes(args)
+ {
+ prometheus_integration_attributes: {
+ manual_configuration: args[:active],
+ api_url: args[:api_url]
+ }.compact
+ }
+ end
+
+ def token_attributes
+ { alerting_setting_attributes: { regenerate_token: true } }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb b/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb
new file mode 100644
index 00000000000..745ac51f6e3
--- /dev/null
+++ b/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module PrometheusIntegration
+ class ResetToken < PrometheusIntegrationBase
+ graphql_name 'PrometheusIntegrationResetToken'
+
+ argument :id, Types::GlobalIDType[::PrometheusService],
+ required: true,
+ description: "The id of the integration to mutate"
+
+ def resolve(id:)
+ integration = authorized_find!(id: id)
+
+ result = ::Projects::Operations::UpdateService.new(
+ integration.project,
+ current_user,
+ token_attributes
+ ).execute
+
+ response integration, result
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/update.rb b/app/graphql/mutations/alert_management/prometheus_integration/update.rb
new file mode 100644
index 00000000000..1f0dea119c5
--- /dev/null
+++ b/app/graphql/mutations/alert_management/prometheus_integration/update.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module PrometheusIntegration
+ class Update < PrometheusIntegrationBase
+ graphql_name 'PrometheusIntegrationUpdate'
+
+ argument :id, Types::GlobalIDType[::PrometheusService],
+ required: true,
+ description: "The id of the integration to mutate"
+
+ argument :active, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: "Whether the integration is receiving alerts"
+
+ argument :api_url, GraphQL::STRING_TYPE,
+ required: false,
+ description: "Endpoint at which prometheus can be queried"
+
+ def resolve(args)
+ integration = authorized_find!(id: args[:id])
+
+ result = ::Projects::Operations::UpdateService.new(
+ integration.project,
+ current_user,
+ integration_attributes(args)
+ ).execute
+
+ response integration.reset, result
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/update_alert_status.rb b/app/graphql/mutations/alert_management/update_alert_status.rb
index 1e14bae048a..74185dca529 100644
--- a/app/graphql/mutations/alert_management/update_alert_status.rb
+++ b/app/graphql/mutations/alert_management/update_alert_status.rb
@@ -9,9 +9,9 @@ module Mutations
required: true,
description: 'The status to set the alert'
- def resolve(args)
- alert = authorized_find!(project_path: args[:project_path], iid: args[:iid])
- result = update_status(alert, args[:status])
+ def resolve(project_path:, iid:, status:)
+ alert = authorized_find!(project_path: project_path, iid: iid)
+ result = update_status(alert, status)
track_usage_event(:incident_management_alert_status_changed, current_user.id)
diff --git a/app/graphql/mutations/boards/create.rb b/app/graphql/mutations/boards/create.rb
index e381205242e..ebbd19930ec 100644
--- a/app/graphql/mutations/boards/create.rb
+++ b/app/graphql/mutations/boards/create.rb
@@ -3,8 +3,7 @@
module Mutations
module Boards
class Create < ::Mutations::BaseMutation
- include Mutations::ResolvesGroup
- include ResolvesProject
+ include Mutations::ResolvesResourceParent
graphql_name 'CreateBoard'
@@ -13,12 +12,6 @@ module Mutations
null: true,
description: 'The board after mutation.'
- argument :project_path, GraphQL::ID_TYPE,
- required: false,
- description: 'The project full path the board is associated with.'
- argument :group_path, GraphQL::ID_TYPE,
- required: false,
- description: 'The group full path the board is associated with.'
argument :name,
GraphQL::STRING_TYPE,
required: false,
@@ -28,7 +21,7 @@ module Mutations
required: false,
description: 'The ID of the user to be assigned to the board.'
argument :milestone_id,
- GraphQL::ID_TYPE,
+ Types::GlobalIDType[Milestone],
required: false,
description: 'The ID of the milestone to be assigned to the board.'
argument :weight,
@@ -36,17 +29,14 @@ module Mutations
required: false,
description: 'The weight of the board.'
argument :label_ids,
- [GraphQL::ID_TYPE],
+ [Types::GlobalIDType[Label]],
required: false,
description: 'The IDs of labels to be added to the board.'
authorize :admin_board
def resolve(args)
- group_path = args.delete(:group_path)
- project_path = args.delete(:project_path)
-
- board_parent = authorized_find!(group_path: group_path, project_path: project_path)
+ board_parent = authorized_resource_parent_find!(args)
response = ::Boards::CreateService.new(board_parent, current_user, args).execute
{
@@ -54,25 +44,6 @@ module Mutations
errors: response.errors
}
end
-
- def ready?(**args)
- if args.values_at(:project_path, :group_path).compact.blank?
- raise Gitlab::Graphql::Errors::ArgumentError,
- 'group_path or project_path arguments are required'
- end
-
- super
- end
-
- private
-
- def find_object(group_path: nil, project_path: nil)
- if group_path
- resolve_group(full_path: group_path)
- else
- resolve_project(full_path: project_path)
- end
- end
end
end
end
diff --git a/app/graphql/mutations/boards/lists/update.rb b/app/graphql/mutations/boards/lists/update.rb
index 7efed3058b3..14502b5174f 100644
--- a/app/graphql/mutations/boards/lists/update.rb
+++ b/app/graphql/mutations/boards/lists/update.rb
@@ -6,7 +6,7 @@ module Mutations
class Update < BaseMutation
graphql_name 'UpdateBoardList'
- argument :list_id, GraphQL::ID_TYPE,
+ argument :list_id, Types::GlobalIDType[List],
required: true,
loads: Types::BoardListType,
description: 'Global ID of the list.'
diff --git a/app/graphql/mutations/commits/create.rb b/app/graphql/mutations/commits/create.rb
index 9ed1bb819c8..2b9107350fd 100644
--- a/app/graphql/mutations/commits/create.rb
+++ b/app/graphql/mutations/commits/create.rb
@@ -13,7 +13,11 @@ module Mutations
argument :branch, GraphQL::STRING_TYPE,
required: true,
- description: 'Name of the branch'
+ description: 'Name of the branch to commit into, it can be a new branch'
+
+ argument :start_branch, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'If on a new branch, name of the original branch'
argument :message,
GraphQL::STRING_TYPE,
@@ -32,13 +36,13 @@ module Mutations
authorize :push_code
- def resolve(project_path:, branch:, message:, actions:)
+ def resolve(project_path:, branch:, message:, actions:, **args)
project = authorized_find!(full_path: project_path)
attributes = {
commit_message: message,
branch_name: branch,
- start_branch: branch,
+ start_branch: args[:start_branch] || branch,
actions: actions.map { |action| action.to_h }
}
diff --git a/app/graphql/mutations/concerns/mutations/package_eventable.rb b/app/graphql/mutations/concerns/mutations/package_eventable.rb
new file mode 100644
index 00000000000..86fd7b9a88a
--- /dev/null
+++ b/app/graphql/mutations/concerns/mutations/package_eventable.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Mutations
+ module PackageEventable
+ extend ActiveSupport::Concern
+
+ private
+
+ def track_event(event, scope)
+ ::Packages::CreateEventService.new(nil, current_user, event_name: event, scope: scope).execute
+ ::Gitlab::Tracking.event(event.to_s, scope.to_s)
+ end
+ end
+end
diff --git a/app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb b/app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb
new file mode 100644
index 00000000000..04a9abf9529
--- /dev/null
+++ b/app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Mutations
+ module ResolvesResourceParent
+ extend ActiveSupport::Concern
+ include Mutations::ResolvesGroup
+ include ResolvesProject
+
+ included do
+ argument :project_path, GraphQL::ID_TYPE,
+ required: false,
+ description: 'The project full path the resource is associated with'
+
+ argument :group_path, GraphQL::ID_TYPE,
+ required: false,
+ description: 'The group full path the resource is associated with'
+ end
+
+ def ready?(**args)
+ unless args[:project_path].present? ^ args[:group_path].present?
+ raise Gitlab::Graphql::Errors::ArgumentError,
+ 'Exactly one of group_path or project_path arguments is required'
+ end
+
+ super
+ end
+
+ private
+
+ def authorized_resource_parent_find!(args)
+ authorized_find!(project_path: args.delete(:project_path),
+ group_path: args.delete(:group_path))
+ end
+
+ def find_object(project_path: nil, group_path: nil)
+ if group_path.present?
+ resolve_group(full_path: group_path)
+ else
+ resolve_project(full_path: project_path)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/container_repositories/destroy.rb b/app/graphql/mutations/container_repositories/destroy.rb
new file mode 100644
index 00000000000..8312193147f
--- /dev/null
+++ b/app/graphql/mutations/container_repositories/destroy.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Mutations
+ module ContainerRepositories
+ class Destroy < Mutations::BaseMutation
+ include ::Mutations::PackageEventable
+
+ graphql_name 'DestroyContainerRepository'
+
+ authorize :destroy_container_image
+
+ argument :id,
+ ::Types::GlobalIDType[::ContainerRepository],
+ required: true,
+ description: 'ID of the container repository.'
+
+ field :container_repository,
+ Types::ContainerRepositoryType,
+ null: false,
+ description: 'The container repository policy after scheduling the deletion.'
+
+ def resolve(id:)
+ container_repository = authorized_find!(id: id)
+
+ container_repository.delete_scheduled!
+ DeleteContainerRepositoryWorker.perform_async(current_user.id, container_repository.id)
+ track_event(:delete_repository, :container)
+
+ {
+ container_repository: container_repository,
+ errors: []
+ }
+ end
+
+ private
+
+ def find_object(id:)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = ::Types::GlobalIDType[::ContainerRepository].coerce_isolated_input(id)
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/custom_emoji/create.rb b/app/graphql/mutations/custom_emoji/create.rb
new file mode 100644
index 00000000000..d912a29d12e
--- /dev/null
+++ b/app/graphql/mutations/custom_emoji/create.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Mutations
+ module CustomEmoji
+ class Create < BaseMutation
+ include Mutations::ResolvesGroup
+
+ graphql_name 'CreateCustomEmoji'
+
+ authorize :create_custom_emoji
+
+ field :custom_emoji,
+ Types::CustomEmojiType,
+ null: true,
+ description: 'The new custom emoji'
+
+ argument :group_path, GraphQL::ID_TYPE,
+ required: true,
+ description: 'Namespace full path the emoji is associated with'
+
+ argument :name, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Name of the emoji'
+
+ argument :url, GraphQL::STRING_TYPE,
+ required: true,
+ as: :file,
+ description: 'Location of the emoji file'
+
+ def resolve(group_path:, **args)
+ group = authorized_find!(group_path: group_path)
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37911#note_444682238
+ args[:external] = true
+
+ custom_emoji = group.custom_emoji.create(args)
+
+ {
+ custom_emoji: custom_emoji.valid? ? custom_emoji : nil,
+ errors: errors_on_object(custom_emoji)
+ }
+ end
+
+ private
+
+ def find_object(group_path:)
+ resolve_group(full_path: group_path)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/labels/create.rb b/app/graphql/mutations/labels/create.rb
new file mode 100644
index 00000000000..cb03651618e
--- /dev/null
+++ b/app/graphql/mutations/labels/create.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Labels
+ class Create < BaseMutation
+ include Mutations::ResolvesResourceParent
+
+ graphql_name 'LabelCreate'
+
+ field :label,
+ Types::LabelType,
+ null: true,
+ description: 'The label after mutation'
+
+ argument :title, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Title of the label'
+
+ argument :description, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Description of the label'
+
+ argument :color, GraphQL::STRING_TYPE,
+ required: false,
+ default_value: Label::DEFAULT_COLOR,
+ description: "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the CSS color names in https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords"
+
+ authorize :admin_label
+
+ def resolve(args)
+ parent = authorized_resource_parent_find!(args)
+ parent_key = parent.is_a?(Project) ? :project : :group
+
+ label = ::Labels::CreateService.new(args).execute(parent_key => parent)
+
+ {
+ label: label.persisted? ? label : nil,
+ errors: errors_on_object(label)
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/merge_requests/set_labels.rb b/app/graphql/mutations/merge_requests/set_labels.rb
index c1e45808593..712c68c9425 100644
--- a/app/graphql/mutations/merge_requests/set_labels.rb
+++ b/app/graphql/mutations/merge_requests/set_labels.rb
@@ -6,7 +6,7 @@ module Mutations
graphql_name 'MergeRequestSetLabels'
argument :label_ids,
- [GraphQL::ID_TYPE],
+ [::Types::GlobalIDType[Label]],
required: true,
description: <<~DESC
The Label IDs to set. Replaces existing labels by default.
@@ -23,10 +23,11 @@ module Mutations
merge_request = authorized_find!(project_path: project_path, iid: iid)
project = merge_request.project
- label_ids = label_ids
- .map { |gid| GlobalID.parse(gid) }
- .select(&method(:label_descendant?))
- .map(&:model_id) # MergeRequests::UpdateService expects integers
+ # TODO: remove this line when the compatibility layer is removed:
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ label_ids = label_ids.map { |id| ::Types::GlobalIDType[::Label].coerce_isolated_input(id) }
+ # MergeRequests::UpdateService expects integers
+ label_ids = label_ids.compact.map(&:model_id)
attribute_name = case operation_mode
when Types::MutationOperationModeEnum.enum[:append]
@@ -45,10 +46,6 @@ module Mutations
errors: errors_on_object(merge_request)
}
end
-
- def label_descendant?(gid)
- gid&.model_class&.ancestors&.include?(Label)
- end
end
end
end
diff --git a/app/graphql/mutations/metrics/dashboard/annotations/delete.rb b/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
index 6e183e78d9b..d6731dfcafd 100644
--- a/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
+++ b/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
@@ -9,8 +9,7 @@ module Mutations
authorize :delete_metrics_dashboard_annotation
- argument :id,
- GraphQL::ID_TYPE,
+ argument :id, ::Types::GlobalIDType[::Metrics::Dashboard::Annotation],
required: true,
description: 'The global ID of the annotation to delete'
diff --git a/app/graphql/mutations/notes/reposition_image_diff_note.rb b/app/graphql/mutations/notes/reposition_image_diff_note.rb
new file mode 100644
index 00000000000..0d88bcd9a30
--- /dev/null
+++ b/app/graphql/mutations/notes/reposition_image_diff_note.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Notes
+ # This mutation differs from the update note mutations as it checks the
+ # `reposition_note` permission, and doesn't allow updating a note's `body`.
+ class RepositionImageDiffNote < Mutations::Notes::Base
+ graphql_name 'RepositionImageDiffNote'
+
+ description 'Repositions a DiffNote on an image (a `Note` where the `position.positionType` is `"image"`)'
+
+ authorize :reposition_note
+
+ argument :id,
+ Types::GlobalIDType[DiffNote],
+ loads: Types::Notes::NoteType,
+ as: :note,
+ required: true,
+ description: 'The global id of the DiffNote to update'
+
+ argument :position,
+ Types::Notes::UpdateDiffImagePositionInputType,
+ required: true,
+ description: copy_field_description(Types::Notes::NoteType, :position)
+
+ def resolve(note:, position:)
+ authorize!(note)
+
+ pre_update_checks!(note, position)
+
+ updated_note = ::Notes::UpdateService.new(
+ note.project,
+ current_user,
+ note_params(note.position, position)
+ ).execute(note)
+
+ {
+ note: updated_note.reset,
+ errors: errors_on_object(updated_note)
+ }
+ end
+
+ private
+
+ # An ImageDiffNote does not exist as a class itself, but is instead
+ # just a `DiffNote` with a particular kind of `Gitlab::Diff::Position`.
+ # In addition to accepting a `DiffNote` Global ID we also need to
+ # perform this check.
+ def pre_update_checks!(note, position)
+ unless note.position&.on_image?
+ raise Gitlab::Graphql::Errors::ResourceNotAvailable,
+ 'Resource is not an ImageDiffNote'
+ end
+ end
+
+ def note_params(old_position, new_position)
+ position = old_position.to_h.merge(new_position)
+
+ {
+ position: Gitlab::Diff::Position.new(position)
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/notes/update/image_diff_note.rb b/app/graphql/mutations/notes/update/image_diff_note.rb
index ef70a8d2bf4..f4533cd9edb 100644
--- a/app/graphql/mutations/notes/update/image_diff_note.rb
+++ b/app/graphql/mutations/notes/update/image_diff_note.rb
@@ -47,12 +47,11 @@ module Mutations
end
def position_params(note, args)
- new_position = args[:position]&.to_h&.compact
- return unless new_position
+ return unless args[:position]
original_position = note.position.to_h
- Gitlab::Diff::Position.new(original_position.merge(new_position))
+ Gitlab::Diff::Position.new(original_position.merge(args[:position]))
end
end
end
diff --git a/app/graphql/mutations/releases/base.rb b/app/graphql/mutations/releases/base.rb
new file mode 100644
index 00000000000..d53cfbe6a11
--- /dev/null
+++ b/app/graphql/mutations/releases/base.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Releases
+ class Base < BaseMutation
+ include ResolvesProject
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: 'Full path of the project the release is associated with'
+
+ private
+
+ def find_object(full_path:)
+ resolve_project(full_path: full_path)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/releases/create.rb b/app/graphql/mutations/releases/create.rb
new file mode 100644
index 00000000000..57c1541c368
--- /dev/null
+++ b/app/graphql/mutations/releases/create.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Releases
+ class Create < Base
+ graphql_name 'ReleaseCreate'
+
+ field :release,
+ Types::ReleaseType,
+ null: true,
+ description: 'The release after mutation'
+
+ argument :tag_name, GraphQL::STRING_TYPE,
+ required: true, as: :tag,
+ description: 'Name of the tag to associate with the release'
+
+ argument :ref, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'The commit SHA or branch name to use if creating a new tag'
+
+ argument :name, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Name of the release'
+
+ argument :description, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Description (also known as "release notes") of the release'
+
+ argument :released_at, Types::TimeType,
+ required: false,
+ description: 'The date when the release will be/was ready. Defaults to the current time.'
+
+ argument :milestones, [GraphQL::STRING_TYPE],
+ required: false,
+ description: 'The title of each milestone the release is associated with. GitLab Premium customers can specify group milestones.'
+
+ argument :assets, Types::ReleaseAssetsInputType,
+ required: false,
+ description: 'Assets associated to the release'
+
+ authorize :create_release
+
+ def resolve(project_path:, milestones: nil, assets: nil, **scalars)
+ project = authorized_find!(full_path: project_path)
+
+ params = {
+ **scalars,
+ milestones: milestones.presence || [],
+ assets: assets.to_h
+ }.with_indifferent_access
+
+ result = ::Releases::CreateService.new(project, current_user, params).execute
+
+ if result[:status] == :success
+ {
+ release: result[:release],
+ errors: []
+ }
+ else
+ {
+ release: nil,
+ errors: [result[:message]]
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/snippets/destroy.rb b/app/graphql/mutations/snippets/destroy.rb
index dc9a1e82575..4915d7dd77a 100644
--- a/app/graphql/mutations/snippets/destroy.rb
+++ b/app/graphql/mutations/snippets/destroy.rb
@@ -7,8 +7,7 @@ module Mutations
ERROR_MSG = 'Error deleting the snippet'
- argument :id,
- GraphQL::ID_TYPE,
+ argument :id, ::Types::GlobalIDType[::Snippet],
required: true,
description: 'The global id of the snippet to destroy'
diff --git a/app/graphql/mutations/snippets/mark_as_spam.rb b/app/graphql/mutations/snippets/mark_as_spam.rb
index 8cfbbae7c08..d6b96c699c0 100644
--- a/app/graphql/mutations/snippets/mark_as_spam.rb
+++ b/app/graphql/mutations/snippets/mark_as_spam.rb
@@ -5,8 +5,7 @@ module Mutations
class MarkAsSpam < Base
graphql_name 'MarkAsSpamSnippet'
- argument :id,
- GraphQL::ID_TYPE,
+ argument :id, ::Types::GlobalIDType[::Snippet],
required: true,
description: 'The global id of the snippet to update'
diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb
index 74266880806..bcaa807e4c1 100644
--- a/app/graphql/mutations/snippets/update.rb
+++ b/app/graphql/mutations/snippets/update.rb
@@ -7,8 +7,7 @@ module Mutations
graphql_name 'UpdateSnippet'
- argument :id,
- GraphQL::ID_TYPE,
+ argument :id, ::Types::GlobalIDType[::Snippet],
required: true,
description: 'The global id of the snippet to update'
diff --git a/app/graphql/mutations/terraform/state/base.rb b/app/graphql/mutations/terraform/state/base.rb
new file mode 100644
index 00000000000..b1721c784b1
--- /dev/null
+++ b/app/graphql/mutations/terraform/state/base.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Terraform
+ module State
+ class Base < BaseMutation
+ authorize :admin_terraform_state
+
+ argument :id,
+ Types::GlobalIDType[::Terraform::State],
+ required: true,
+ description: 'Global ID of the Terraform state'
+
+ private
+
+ def find_object(id:)
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/terraform/state/delete.rb b/app/graphql/mutations/terraform/state/delete.rb
new file mode 100644
index 00000000000..f08219cb395
--- /dev/null
+++ b/app/graphql/mutations/terraform/state/delete.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Terraform
+ module State
+ class Delete < Base
+ graphql_name 'TerraformStateDelete'
+
+ def resolve(id:)
+ state = authorized_find!(id: id)
+ state.destroy
+
+ { errors: errors_on_object(state) }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/terraform/state/lock.rb b/app/graphql/mutations/terraform/state/lock.rb
new file mode 100644
index 00000000000..d22c8de2560
--- /dev/null
+++ b/app/graphql/mutations/terraform/state/lock.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Terraform
+ module State
+ class Lock < Base
+ graphql_name 'TerraformStateLock'
+
+ def resolve(id:)
+ state = authorized_find!(id: id)
+
+ if state.locked?
+ state.errors.add(:base, 'state is already locked')
+ else
+ state.update(lock_xid: lock_xid, locked_by_user: current_user, locked_at: Time.current)
+ end
+
+ { errors: errors_on_object(state) }
+ end
+
+ private
+
+ def lock_xid
+ SecureRandom.uuid
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/terraform/state/unlock.rb b/app/graphql/mutations/terraform/state/unlock.rb
new file mode 100644
index 00000000000..0818dbd7fb3
--- /dev/null
+++ b/app/graphql/mutations/terraform/state/unlock.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Terraform
+ module State
+ class Unlock < Base
+ graphql_name 'TerraformStateUnlock'
+
+ def resolve(id:)
+ state = authorized_find!(id: id)
+ state.update(lock_xid: nil, locked_by_user: nil, locked_at: nil)
+
+ { errors: errors_on_object(state) }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/todos/base.rb b/app/graphql/mutations/todos/base.rb
index 6db863796bc..4dab3bbc3f4 100644
--- a/app/graphql/mutations/todos/base.rb
+++ b/app/graphql/mutations/todos/base.rb
@@ -11,16 +11,6 @@ module Mutations
id = ::Types::GlobalIDType[::Todo].coerce_isolated_input(id)
GitlabSchema.find_by_gid(id)
end
-
- def map_to_global_ids(ids)
- return [] if ids.blank?
-
- ids.map { |id| to_global_id(id) }
- end
-
- def to_global_id(id)
- Gitlab::GlobalId.as_global_id(id, model_name: Todo.name).to_s
- end
end
end
end
diff --git a/app/graphql/mutations/todos/create.rb b/app/graphql/mutations/todos/create.rb
new file mode 100644
index 00000000000..53c88696fdd
--- /dev/null
+++ b/app/graphql/mutations/todos/create.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Todos
+ class Create < ::Mutations::Todos::Base
+ graphql_name 'TodoCreate'
+
+ authorize :create_todo
+
+ argument :target_id,
+ Types::GlobalIDType[Todoable],
+ required: true,
+ description: "The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported"
+
+ field :todo, Types::TodoType,
+ null: true,
+ description: 'The to-do created'
+
+ def resolve(target_id:)
+ id = ::Types::GlobalIDType[Todoable].coerce_isolated_input(target_id)
+ target = authorized_find!(id)
+
+ todo = TodoService.new.mark_todo(target, current_user)&.first
+ errors = errors_on_object(todo) if todo
+
+ {
+ todo: todo,
+ errors: errors
+ }
+ end
+
+ private
+
+ def find_object(id)
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/todos/mark_all_done.rb b/app/graphql/mutations/todos/mark_all_done.rb
index 8b53658ddd5..97bbbeeaa2f 100644
--- a/app/graphql/mutations/todos/mark_all_done.rb
+++ b/app/graphql/mutations/todos/mark_all_done.rb
@@ -8,7 +8,7 @@ module Mutations
authorize :update_user
field :updated_ids,
- [GraphQL::ID_TYPE],
+ [::Types::GlobalIDType[::Todo]],
null: false,
deprecated: { reason: 'Use todos', milestone: '13.2' },
description: 'Ids of the updated todos'
@@ -23,7 +23,7 @@ module Mutations
updated_ids = mark_all_todos_done
{
- updated_ids: map_to_global_ids(updated_ids),
+ updated_ids: updated_ids,
todos: Todo.id_in(updated_ids),
errors: []
}
diff --git a/app/graphql/mutations/todos/restore_many.rb b/app/graphql/mutations/todos/restore_many.rb
index ea5f5414134..9e0a95c48ec 100644
--- a/app/graphql/mutations/todos/restore_many.rb
+++ b/app/graphql/mutations/todos/restore_many.rb
@@ -12,7 +12,7 @@ module Mutations
required: true,
description: 'The global ids of the todos to restore (a maximum of 50 is supported at once)'
- field :updated_ids, [GraphQL::ID_TYPE],
+ field :updated_ids, [::Types::GlobalIDType[Todo]],
null: false,
description: 'The ids of the updated todo items',
deprecated: { reason: 'Use todos', milestone: '13.2' }
@@ -28,7 +28,7 @@ module Mutations
updated_ids = restore(todos)
{
- updated_ids: gids_of(updated_ids),
+ updated_ids: updated_ids,
todos: Todo.id_in(updated_ids),
errors: errors_on_objects(todos)
}
@@ -36,10 +36,6 @@ module Mutations
private
- def gids_of(ids)
- ids.map { |id| Gitlab::GlobalId.as_global_id(id, model_name: Todo.name).to_s }
- end
-
def model_ids_of(ids)
ids.map do |gid|
# TODO: remove this line when the compatibility layer is removed
diff --git a/app/graphql/queries/design_management/design_permissions.query.graphql b/app/graphql/queries/design_management/design_permissions.query.graphql
new file mode 100644
index 00000000000..55dfa35129c
--- /dev/null
+++ b/app/graphql/queries/design_management/design_permissions.query.graphql
@@ -0,0 +1,13 @@
+query permissions($fullPath: ID!, $iid: String!) {
+ project(fullPath: $fullPath) {
+ __typename
+ id
+ issue(iid: $iid) {
+ __typename
+ userPermissions {
+ __typename
+ createDesign
+ }
+ }
+ }
+}
diff --git a/app/graphql/queries/design_management/get_design_list.query.graphql b/app/graphql/queries/design_management/get_design_list.query.graphql
new file mode 100644
index 00000000000..ade03d99797
--- /dev/null
+++ b/app/graphql/queries/design_management/get_design_list.query.graphql
@@ -0,0 +1,40 @@
+query getDesignList($fullPath: ID!, $iid: String!, $atVersion: ID) {
+ project(fullPath: $fullPath) {
+ __typename
+ id
+ issue(iid: $iid) {
+ __typename
+ designCollection {
+ __typename
+ copyState
+ designs(atVersion: $atVersion) {
+ __typename
+ nodes {
+ __typename
+ id
+ event
+ filename
+ notesCount
+ image
+ imageV432x230
+ currentUserTodos(state: pending) {
+ __typename
+ nodes {
+ __typename
+ id
+ }
+ }
+ }
+ }
+ versions {
+ __typename
+ nodes {
+ __typename
+ id
+ sha
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/graphql/queries/repository/files.query.graphql b/app/graphql/queries/repository/files.query.graphql
new file mode 100644
index 00000000000..232d98a932c
--- /dev/null
+++ b/app/graphql/queries/repository/files.query.graphql
@@ -0,0 +1,76 @@
+fragment PageInfo on PageInfo {
+ __typename
+ hasNextPage
+ hasPreviousPage
+ startCursor
+ endCursor
+}
+
+fragment TreeEntry on Entry {
+ __typename
+ id
+ sha
+ name
+ flatPath
+ type
+}
+
+query getFiles(
+ $projectPath: ID!
+ $path: String
+ $ref: String!
+ $pageSize: Int!
+ $nextPageCursor: String
+) {
+ project(fullPath: $projectPath) {
+ __typename
+ repository {
+ __typename
+ tree(path: $path, ref: $ref) {
+ __typename
+ trees(first: $pageSize, after: $nextPageCursor) {
+ __typename
+ edges {
+ __typename
+ node {
+ ...TreeEntry
+ webPath
+ }
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ submodules(first: $pageSize, after: $nextPageCursor) {
+ __typename
+ edges {
+ __typename
+ node {
+ ...TreeEntry
+ webUrl
+ treeUrl
+ }
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ blobs(first: $pageSize, after: $nextPageCursor) {
+ __typename
+ edges {
+ __typename
+ node {
+ ...TreeEntry
+ mode
+ webPath
+ lfsOid
+ }
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/graphql/queries/repository/permissions.query.graphql b/app/graphql/queries/repository/permissions.query.graphql
new file mode 100644
index 00000000000..c0262a882cd
--- /dev/null
+++ b/app/graphql/queries/repository/permissions.query.graphql
@@ -0,0 +1,11 @@
+query getPermissions($projectPath: ID!) {
+ project(fullPath: $projectPath) {
+ __typename
+ userPermissions {
+ __typename
+ pushCode
+ forkProject
+ createMergeRequestIn
+ }
+ }
+}
diff --git a/app/graphql/queries/snippet/project_permissions.query.graphql b/app/graphql/queries/snippet/project_permissions.query.graphql
new file mode 100644
index 00000000000..0c38e4f8a07
--- /dev/null
+++ b/app/graphql/queries/snippet/project_permissions.query.graphql
@@ -0,0 +1,9 @@
+query CanCreateProjectSnippet($fullPath: ID!) {
+ project(fullPath: $fullPath) {
+ __typename
+ userPermissions {
+ __typename
+ createSnippet
+ }
+ }
+}
diff --git a/app/graphql/queries/snippet/snippet.query.graphql b/app/graphql/queries/snippet/snippet.query.graphql
new file mode 100644
index 00000000000..2205dc26642
--- /dev/null
+++ b/app/graphql/queries/snippet/snippet.query.graphql
@@ -0,0 +1,65 @@
+query GetSnippetQuery($ids: [SnippetID!]) {
+ snippets(ids: $ids) {
+ __typename
+ nodes {
+ __typename
+ id
+ title
+ description
+ descriptionHtml
+ createdAt
+ updatedAt
+ visibilityLevel
+ webUrl
+ httpUrlToRepo
+ sshUrlToRepo
+ blobs {
+ __typename
+ nodes {
+ __typename
+ binary
+ name
+ path
+ rawPath
+ size
+ externalStorage
+ renderedAsText
+ simpleViewer {
+ __typename
+ collapsed
+ renderError
+ tooLarge
+ type
+ fileType
+ }
+ richViewer {
+ __typename
+ collapsed
+ renderError
+ tooLarge
+ type
+ fileType
+ }
+ }
+ }
+ userPermissions {
+ __typename
+ adminSnippet
+ updateSnippet
+ }
+ project {
+ __typename
+ fullPath
+ webUrl
+ }
+ author {
+ __typename
+ id
+ avatarUrl
+ name
+ username
+ webUrl
+ }
+ }
+ }
+}
diff --git a/app/graphql/queries/snippet/snippet_blob_content.query.graphql b/app/graphql/queries/snippet/snippet_blob_content.query.graphql
new file mode 100644
index 00000000000..005f42ff726
--- /dev/null
+++ b/app/graphql/queries/snippet/snippet_blob_content.query.graphql
@@ -0,0 +1,18 @@
+query SnippetBlobContent($ids: [ID!], $rich: Boolean!, $paths: [String!]) {
+ snippets(ids: $ids) {
+ __typename
+ nodes {
+ __typename
+ id
+ blobs(paths: $paths) {
+ __typename
+ nodes {
+ __typename
+ path
+ richData @include(if: $rich)
+ plainData @skip(if: $rich)
+ }
+ }
+ }
+ }
+}
diff --git a/app/graphql/queries/snippet/user_permissions.query.graphql b/app/graphql/queries/snippet/user_permissions.query.graphql
new file mode 100644
index 00000000000..a4914189807
--- /dev/null
+++ b/app/graphql/queries/snippet/user_permissions.query.graphql
@@ -0,0 +1,9 @@
+query CanCreatePersonalSnippet {
+ currentUser {
+ __typename
+ userPermissions {
+ __typename
+ createSnippet
+ }
+ }
+}
diff --git a/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb b/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb
index aea3afa8ec5..9bac9f222ab 100644
--- a/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb
+++ b/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb
@@ -13,10 +13,20 @@ module Resolvers
required: true,
description: 'The type of measurement/statistics to retrieve'
- def resolve(identifier:)
+ argument :recorded_after, Types::TimeType,
+ required: false,
+ description: 'Measurement recorded after this date'
+
+ argument :recorded_before, Types::TimeType,
+ required: false,
+ description: 'Measurement recorded before this date'
+
+ def resolve(identifier:, recorded_before: nil, recorded_after: nil)
authorize!
::Analytics::InstanceStatistics::Measurement
+ .recorded_after(recorded_after)
+ .recorded_before(recorded_before)
.with_identifier(identifier)
.order_by_latest
end
diff --git a/app/graphql/resolvers/alert_management/alert_resolver.rb b/app/graphql/resolvers/alert_management/alert_resolver.rb
index dc9b1dbb5f4..c3219d9cdc3 100644
--- a/app/graphql/resolvers/alert_management/alert_resolver.rb
+++ b/app/graphql/resolvers/alert_management/alert_resolver.rb
@@ -19,7 +19,7 @@ module Resolvers
required: false
argument :search, GraphQL::STRING_TYPE,
- description: 'Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.',
+ description: 'Search query for title, description, service, or monitoring_tool.',
required: false
argument :assignee_username, GraphQL::STRING_TYPE,
diff --git a/app/graphql/resolvers/alert_management/alert_status_counts_resolver.rb b/app/graphql/resolvers/alert_management/alert_status_counts_resolver.rb
index 96ea4610aff..8fc0f9fd1ff 100644
--- a/app/graphql/resolvers/alert_management/alert_status_counts_resolver.rb
+++ b/app/graphql/resolvers/alert_management/alert_status_counts_resolver.rb
@@ -6,7 +6,7 @@ module Resolvers
type Types::AlertManagement::AlertStatusCountsType, null: true
argument :search, GraphQL::STRING_TYPE,
- description: 'Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.',
+ description: 'Search query for title, description, service, or monitoring_tool.',
required: false
argument :assignee_username, GraphQL::STRING_TYPE,
diff --git a/app/graphql/resolvers/alert_management/integrations_resolver.rb b/app/graphql/resolvers/alert_management/integrations_resolver.rb
new file mode 100644
index 00000000000..4d1fe367277
--- /dev/null
+++ b/app/graphql/resolvers/alert_management/integrations_resolver.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module AlertManagement
+ class IntegrationsResolver < BaseResolver
+ alias_method :project, :synchronized_object
+
+ type Types::AlertManagement::IntegrationType.connection_type, null: true
+
+ def resolve(**args)
+ http_integrations + prometheus_integrations
+ end
+
+ private
+
+ def prometheus_integrations
+ return [] unless Ability.allowed?(current_user, :admin_project, project)
+
+ Array(project.prometheus_service)
+ end
+
+ def http_integrations
+ return [] unless Ability.allowed?(current_user, :admin_operations, project)
+
+ ::AlertManagement::HttpIntegrationsFinder.new(project, {}).execute
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/assigned_merge_requests_resolver.rb b/app/graphql/resolvers/assigned_merge_requests_resolver.rb
index 172a8e298ad..30415ef5d2d 100644
--- a/app/graphql/resolvers/assigned_merge_requests_resolver.rb
+++ b/app/graphql/resolvers/assigned_merge_requests_resolver.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module Resolvers
- class AssignedMergeRequestsResolver < UserMergeRequestsResolver
+ class AssignedMergeRequestsResolver < UserMergeRequestsResolverBase
+ type ::Types::MergeRequestType.connection_type, null: true
accept_author
def user_role
diff --git a/app/graphql/resolvers/authored_merge_requests_resolver.rb b/app/graphql/resolvers/authored_merge_requests_resolver.rb
index bc796f8685a..1426ca83c06 100644
--- a/app/graphql/resolvers/authored_merge_requests_resolver.rb
+++ b/app/graphql/resolvers/authored_merge_requests_resolver.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module Resolvers
- class AuthoredMergeRequestsResolver < UserMergeRequestsResolver
+ class AuthoredMergeRequestsResolver < UserMergeRequestsResolverBase
+ type ::Types::MergeRequestType.connection_type, null: true
accept_assignee
def user_role
diff --git a/app/graphql/resolvers/base_resolver.rb b/app/graphql/resolvers/base_resolver.rb
index 2b8854fb4d0..87a63231b22 100644
--- a/app/graphql/resolvers/base_resolver.rb
+++ b/app/graphql/resolvers/base_resolver.rb
@@ -8,32 +8,81 @@ module Resolvers
argument_class ::Types::BaseArgument
- def self.single
- @single ||= Class.new(self) do
- def ready?(**args)
- ready, early_return = super
- [ready, select_result(early_return)]
- end
+ def self.singular_type
+ return unless type
- def resolve(**args)
- select_result(super)
- end
+ unwrapped = type.unwrap
+
+ %i[node_type relay_node_type of_type itself].reduce(nil) do |t, m|
+ t || unwrapped.try(m)
+ end
+ end
- def single?
- true
+ def self.when_single(&block)
+ as_single << block
+
+ # Have we been called after defining the single version of this resolver?
+ if @single.present?
+ @single.instance_exec(&block)
+ end
+ end
+
+ def self.as_single
+ @as_single ||= []
+ end
+
+ def self.single_definition_blocks
+ ancestors.flat_map { |klass| klass.try(:as_single) || [] }
+ end
+
+ def self.single
+ @single ||= begin
+ parent = self
+ klass = Class.new(self) do
+ type parent.singular_type, null: true
+
+ def ready?(**args)
+ ready, early_return = super
+ [ready, select_result(early_return)]
+ end
+
+ def resolve(**args)
+ select_result(super)
+ end
+
+ def single?
+ true
+ end
+
+ def select_result(results)
+ results&.first
+ end
+
+ define_singleton_method :to_s do
+ "#{parent}.single"
+ end
end
- def select_result(results)
- results&.first
+ single_definition_blocks.each do |definition|
+ klass.instance_exec(&definition)
end
+
+ klass
end
end
def self.last
+ parent = self
@last ||= Class.new(self.single) do
+ type parent.singular_type, null: true
+
def select_result(results)
results&.last
end
+
+ define_singleton_method :to_s do
+ "#{parent}.last"
+ end
end
end
@@ -68,14 +117,13 @@ module Resolvers
end
end
+ # TODO: remove! This should never be necessary
+ # Remove as part of https://gitlab.com/gitlab-org/gitlab/-/issues/13984,
+ # since once we use that authorization approach, the object is guaranteed to
+ # be synchronized before any field.
def synchronized_object
strong_memoize(:synchronized_object) do
- case object
- when BatchLoader::GraphQL
- object.sync
- else
- object
- end
+ ::Gitlab::Graphql::Lazy.force(object)
end
end
diff --git a/app/graphql/resolvers/board_lists_resolver.rb b/app/graphql/resolvers/board_lists_resolver.rb
index 3384b37e2ce..ef12dfa19ff 100644
--- a/app/graphql/resolvers/board_lists_resolver.rb
+++ b/app/graphql/resolvers/board_lists_resolver.rb
@@ -7,7 +7,7 @@ module Resolvers
type Types::BoardListType, null: true
- argument :id, GraphQL::ID_TYPE,
+ argument :id, Types::GlobalIDType[List],
required: false,
description: 'Find a list by its global ID'
diff --git a/app/graphql/resolvers/boards_resolver.rb b/app/graphql/resolvers/boards_resolver.rb
index 82efd92d33f..42b6ce03118 100644
--- a/app/graphql/resolvers/boards_resolver.rb
+++ b/app/graphql/resolvers/boards_resolver.rb
@@ -4,7 +4,7 @@ module Resolvers
class BoardsResolver < BaseResolver
type Types::BoardType, null: true
- argument :id, GraphQL::ID_TYPE,
+ argument :id, ::Types::GlobalIDType[::Board],
required: false,
description: 'Find a board by its ID'
@@ -23,10 +23,13 @@ module Resolvers
private
- def extract_board_id(gid)
- return unless gid.present?
+ def extract_board_id(id)
+ return unless id.present?
- GitlabSchema.parse_gid(gid, expected_type: ::Board).model_id
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = Types::GlobalIDType[Board].coerce_isolated_input(id)
+ id.model_id
end
end
end
diff --git a/app/graphql/resolvers/ci/jobs_resolver.rb b/app/graphql/resolvers/ci/jobs_resolver.rb
new file mode 100644
index 00000000000..8a9ae42b375
--- /dev/null
+++ b/app/graphql/resolvers/ci/jobs_resolver.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Ci
+ class JobsResolver < BaseResolver
+ alias_method :pipeline, :object
+
+ argument :security_report_types, [Types::Security::ReportTypeEnum],
+ required: false,
+ description: 'Filter jobs by the type of security report they produce'
+
+ def resolve(security_report_types: [])
+ if security_report_types.present?
+ ::Security::SecurityJobsFinder.new(
+ pipeline: pipeline,
+ job_types: security_report_types
+ ).execute
+ else
+ pipeline.statuses
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/ci/runner_setup_resolver.rb b/app/graphql/resolvers/ci/runner_setup_resolver.rb
new file mode 100644
index 00000000000..241cd57f74b
--- /dev/null
+++ b/app/graphql/resolvers/ci/runner_setup_resolver.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Ci
+ class RunnerSetupResolver < BaseResolver
+ type Types::Ci::RunnerSetupType, null: true
+
+ argument :platform, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Platform to generate the instructions for'
+
+ argument :architecture, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Architecture to generate the instructions for'
+
+ argument :project_id, ::Types::GlobalIDType[::Project],
+ required: false,
+ description: 'Project to register the runner for'
+
+ argument :group_id, ::Types::GlobalIDType[::Group],
+ required: false,
+ description: 'Group to register the runner for'
+
+ def resolve(platform:, architecture:, **args)
+ instructions = Gitlab::Ci::RunnerInstructions.new(
+ { current_user: current_user, os: platform, arch: architecture }.merge(target_param(args))
+ )
+
+ {
+ install_instructions: instructions.install_script || other_install_instructions(platform),
+ register_instructions: instructions.register_command
+ }
+ ensure
+ raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'User is not authorized to register a runner for the specified resource!' if instructions.errors.include?('Gitlab::Access::AccessDeniedError')
+ end
+
+ private
+
+ def other_install_instructions(platform)
+ Gitlab::Ci::RunnerInstructions::OTHER_ENVIRONMENTS[platform.to_sym][:installation_instructions_url]
+ end
+
+ def target_param(args)
+ project_param(args[:project_id]) || group_param(args[:group_id]) || {}
+ end
+
+ def project_param(project_id)
+ return unless project_id
+
+ { project: find_object(project_id) }
+ end
+
+ def group_param(group_id)
+ return unless group_id
+
+ { group: find_object(group_id) }
+ end
+
+ def find_object(gid)
+ GlobalID::Locator.locate(gid)
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/commit_pipelines_resolver.rb b/app/graphql/resolvers/commit_pipelines_resolver.rb
index 92a83523593..40af392200c 100644
--- a/app/graphql/resolvers/commit_pipelines_resolver.rb
+++ b/app/graphql/resolvers/commit_pipelines_resolver.rb
@@ -1,7 +1,9 @@
# frozen_string_literal: true
+# rubocop: disable Graphql/ResolverType
module Resolvers
class CommitPipelinesResolver < BaseResolver
+ # The GraphQL type here gets defined in this include
include ::ResolvesPipelines
alias_method :commit, :object
@@ -11,3 +13,4 @@ module Resolvers
end
end
end
+# rubocop: enable Graphql/ResolverType
diff --git a/app/graphql/resolvers/concerns/caching_array_resolver.rb b/app/graphql/resolvers/concerns/caching_array_resolver.rb
new file mode 100644
index 00000000000..4f2c8b98928
--- /dev/null
+++ b/app/graphql/resolvers/concerns/caching_array_resolver.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+# Concern that will eliminate N+1 queries for size-constrained
+# collections of items.
+#
+# **note**: The resolver will never load more items than
+# `@field.max_page_size` if defined, falling back to
+# `context.schema.default_max_page_size`.
+#
+# provided that:
+#
+# - the query can be uniquely determined by the object and the arguments
+# - the model class includes FromUnion
+# - the model class defines a scalar primary key
+#
+# This comes at the cost of returning arrays, not relations, so we don't get
+# any keyset pagination goodness. Consequently, this is only suitable for small-ish
+# result sets, as the full result set will be loaded into memory.
+#
+# To enforce this, the resolver limits the size of result sets to
+# `@field.max_page_size || context.schema.default_max_page_size`.
+#
+# **important**: If the cardinality of your collection is likely to be greater than 100,
+# then you will want to pass `max_page_size:` as part of the field definition
+# or (ideally) as part of the resolver `field_options`.
+#
+# How to implement:
+# --------------------
+#
+# Each including class operates on two generic parameters, A and R:
+# - A is any Object that can be used as a Hash key. Instances of A
+# are returned by `query_input` and then passed to `query_for`.
+# - R is any subclass of ApplicationRecord that includes FromUnion.
+# R must have a single scalar primary_key
+#
+# Classes must implement:
+# - #model_class -> Class[R]. (Must respond to :primary_key, and :from_union)
+# - #query_input(**kwargs) -> A (Must be hashable)
+# - #query_for(A) -> ActiveRecord::Relation[R]
+#
+# Note the relationship between query_input and query_for, one of which
+# consumes the input of the other
+# (i.e. `resolve(**args).sync == query_for(query_input(**args)).to_a`).
+#
+# Classes may implement:
+# - #item_found(A, R) (return value is ignored)
+# - max_union_size Integer (the maximum number of queries to run in any one union)
+module CachingArrayResolver
+ MAX_UNION_SIZE = 50
+
+ def resolve(**args)
+ key = query_input(**args)
+
+ BatchLoader::GraphQL.for(key).batch(**batch) do |keys, loader|
+ if keys.size == 1
+ # We can avoid the union entirely.
+ k = keys.first
+ limit(query_for(k)).each { |item| found(loader, k, item) }
+ else
+ queries = keys.map { |key| query_for(key) }
+
+ queries.in_groups_of(max_union_size, false).each do |group|
+ by_id = model_class
+ .from_union(tag(group), remove_duplicates: false)
+ .group_by { |r| r[primary_key] }
+
+ by_id.values.each do |item_group|
+ item = item_group.first
+ item_group.map(&:union_member_idx).each do |i|
+ found(loader, keys[i], item)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ # Override this to intercept the items once they are found
+ def item_found(query_input, item)
+ end
+
+ def max_union_size
+ MAX_UNION_SIZE
+ end
+
+ private
+
+ def primary_key
+ @primary_key ||= (model_class.primary_key || raise("No primary key for #{model_class}"))
+ end
+
+ def batch
+ { key: self.class, default_value: [] }
+ end
+
+ def found(loader, key, value)
+ loader.call(key) do |vs|
+ item_found(key, value)
+ vs << value
+ end
+ end
+
+ # Tag each row returned from each query with a the index of which query in
+ # the union it comes from. This lets us map the results back to the cache key.
+ def tag(queries)
+ queries.each_with_index.map do |q, i|
+ limit(q.select(all_fields, member_idx(i)))
+ end
+ end
+
+ def limit(query)
+ query.limit(query_limit) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ def all_fields
+ model_class.arel_table[Arel.star]
+ end
+
+ # rubocop: disable Graphql/Descriptions (false positive!)
+ def query_limit
+ field&.max_page_size.presence || context.schema.default_max_page_size
+ end
+ # rubocop: enable Graphql/Descriptions
+
+ def member_idx(idx)
+ ::Arel::Nodes::SqlLiteral.new(idx.to_s).as('union_member_idx')
+ end
+end
diff --git a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
index fe6fa0bb262..4715b867ecb 100644
--- a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
+++ b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
@@ -29,7 +29,7 @@ module IssueResolverArguments
description: 'Usernames of users assigned to the issue'
argument :assignee_id, GraphQL::STRING_TYPE,
required: false,
- description: 'ID of a user assigned to the issues, "none" and "any" values supported'
+ description: 'ID of a user assigned to the issues, "none" and "any" values are supported'
argument :created_before, Types::TimeType,
required: false,
description: 'Issues created before this date'
diff --git a/app/graphql/resolvers/concerns/looks_ahead.rb b/app/graphql/resolvers/concerns/looks_ahead.rb
index 61f23920ebb..d468047b539 100644
--- a/app/graphql/resolvers/concerns/looks_ahead.rb
+++ b/app/graphql/resolvers/concerns/looks_ahead.rb
@@ -4,6 +4,7 @@ module LooksAhead
extend ActiveSupport::Concern
included do
+ extras [:lookahead]
attr_accessor :lookahead
end
diff --git a/app/graphql/resolvers/concerns/resolves_pipelines.rb b/app/graphql/resolvers/concerns/resolves_pipelines.rb
index 46d9e174deb..f061f5f1606 100644
--- a/app/graphql/resolvers/concerns/resolves_pipelines.rb
+++ b/app/graphql/resolvers/concerns/resolves_pipelines.rb
@@ -4,7 +4,7 @@ module ResolvesPipelines
extend ActiveSupport::Concern
included do
- type [Types::Ci::PipelineType], null: false
+ type Types::Ci::PipelineType.connection_type, null: false
argument :status,
Types::Ci::PipelineStatusEnum,
required: false,
diff --git a/app/graphql/resolvers/concerns/resolves_project.rb b/app/graphql/resolvers/concerns/resolves_project.rb
index 3c5ce3dab01..b2ee7d7e850 100644
--- a/app/graphql/resolvers/concerns/resolves_project.rb
+++ b/app/graphql/resolvers/concerns/resolves_project.rb
@@ -1,6 +1,9 @@
# frozen_string_literal: true
module ResolvesProject
+ # Accepts EITHER one of
+ # - full_path: String (see Project#full_path)
+ # - project_id: GlobalID. Arguments should be typed as: `::Types::GlobalIDType[Project]`
def resolve_project(full_path: nil, project_id: nil)
unless full_path.present? ^ project_id.present?
raise ::Gitlab::Graphql::Errors::ArgumentError, 'Incompatible arguments: projectId, projectPath.'
diff --git a/app/graphql/resolvers/concerns/resolves_snippets.rb b/app/graphql/resolvers/concerns/resolves_snippets.rb
index 483372bbf63..790ff4f774f 100644
--- a/app/graphql/resolvers/concerns/resolves_snippets.rb
+++ b/app/graphql/resolvers/concerns/resolves_snippets.rb
@@ -4,9 +4,9 @@ module ResolvesSnippets
extend ActiveSupport::Concern
included do
- type Types::SnippetType, null: false
+ type Types::SnippetType.connection_type, null: false
- argument :ids, [GraphQL::ID_TYPE],
+ argument :ids, [::Types::GlobalIDType[::Snippet]],
required: false,
description: 'Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1"'
@@ -32,16 +32,15 @@ module ResolvesSnippets
}.merge(options_by_type(args[:type]))
end
- def resolve_ids(ids)
- Array.wrap(ids).map { |id| resolve_gid(id, :id) }
- end
-
- def resolve_gid(gid, argument)
- return unless gid.present?
+ def resolve_ids(ids, type = ::Types::GlobalIDType[::Snippet])
+ Array.wrap(ids).map do |id|
+ next unless id.present?
- GlobalID.parse(gid)&.model_id.tap do |id|
- raise Gitlab::Graphql::Errors::ArgumentError, "Invalid global id format for param #{argument}" if id.nil?
- end
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = type.coerce_isolated_input(id)
+ id.model_id
+ end.compact
end
def options_by_type(type)
diff --git a/app/graphql/resolvers/container_repositories_resolver.rb b/app/graphql/resolvers/container_repositories_resolver.rb
new file mode 100644
index 00000000000..b4b2893a3b8
--- /dev/null
+++ b/app/graphql/resolvers/container_repositories_resolver.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class ContainerRepositoriesResolver < BaseResolver
+ include ::Mutations::PackageEventable
+
+ type Types::ContainerRepositoryType, null: true
+
+ argument :name, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Filter the container repositories by their name'
+
+ def resolve(name: nil)
+ ContainerRepositoriesFinder.new(user: current_user, subject: object, params: { name: name })
+ .execute
+ .tap { track_event(:list_repositories, :container) }
+ end
+ end
+end
diff --git a/app/graphql/resolvers/design_management/design_at_version_resolver.rb b/app/graphql/resolvers/design_management/design_at_version_resolver.rb
index fd9b349f974..1b69efebe4e 100644
--- a/app/graphql/resolvers/design_management/design_at_version_resolver.rb
+++ b/app/graphql/resolvers/design_management/design_at_version_resolver.rb
@@ -9,7 +9,7 @@ module Resolvers
authorize :read_design
- argument :id, GraphQL::ID_TYPE,
+ argument :id, ::Types::GlobalIDType[::DesignManagement::DesignAtVersion],
required: true,
description: 'The Global ID of the design at this version'
@@ -18,7 +18,10 @@ module Resolvers
end
def find_object(id:)
- dav = GitlabSchema.object_from_id(id, expected_type: ::DesignManagement::DesignAtVersion)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = ::Types::GlobalIDType[::DesignManagement::DesignAtVersion].coerce_isolated_input(id)
+ dav = GitlabSchema.find_by_gid(id)
return unless consistent?(dav)
dav
@@ -35,7 +38,7 @@ module Resolvers
# that the DesignAtVersion as found by its ID does in fact belong
# to this issue.
def consistent?(dav)
- issue.nil? || (dav&.design&.issue_id == issue.id)
+ issue.nil? || (dav.present? && dav.design&.issue_id == issue.id)
end
def issue
diff --git a/app/graphql/resolvers/design_management/design_resolver.rb b/app/graphql/resolvers/design_management/design_resolver.rb
index 05bdbbbe407..e0a68bae397 100644
--- a/app/graphql/resolvers/design_management/design_resolver.rb
+++ b/app/graphql/resolvers/design_management/design_resolver.rb
@@ -3,7 +3,9 @@
module Resolvers
module DesignManagement
class DesignResolver < BaseResolver
- argument :id, GraphQL::ID_TYPE,
+ type ::Types::DesignManagement::DesignType, null: true
+
+ argument :id, ::Types::GlobalIDType[::DesignManagement::Design],
required: false,
description: 'Find a design by its ID'
@@ -50,7 +52,11 @@ module Resolvers
end
def parse_gid(gid)
- GitlabSchema.parse_gid(gid, expected_type: ::DesignManagement::Design).model_id
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ gid = ::Types::GlobalIDType[::DesignManagement::Design].coerce_isolated_input(gid)
+
+ gid.model_id
end
end
end
diff --git a/app/graphql/resolvers/design_management/designs_resolver.rb b/app/graphql/resolvers/design_management/designs_resolver.rb
index 955ea6304e0..c588142ea6b 100644
--- a/app/graphql/resolvers/design_management/designs_resolver.rb
+++ b/app/graphql/resolvers/design_management/designs_resolver.rb
@@ -3,16 +3,18 @@
module Resolvers
module DesignManagement
class DesignsResolver < BaseResolver
- argument :ids,
- [GraphQL::ID_TYPE],
+ DesignID = ::Types::GlobalIDType[::DesignManagement::Design]
+ VersionID = ::Types::GlobalIDType[::DesignManagement::Version]
+
+ type ::Types::DesignManagement::DesignType.connection_type, null: true
+
+ argument :ids, [DesignID],
required: false,
description: 'Filters designs by their ID'
- argument :filenames,
- [GraphQL::STRING_TYPE],
+ argument :filenames, [GraphQL::STRING_TYPE],
required: false,
description: 'Filters designs by their filename'
- argument :at_version,
- GraphQL::ID_TYPE,
+ argument :at_version, VersionID,
required: false,
description: 'Filters designs to only those that existed at the version. ' \
'If argument is omitted or nil then all designs will reflect the latest version'
@@ -36,11 +38,20 @@ module Resolvers
def version(at_version)
return unless at_version
- GitlabSchema.object_from_id(at_version, expected_type: ::DesignManagement::Version)&.sync
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ at_version = VersionID.coerce_isolated_input(at_version)
+ # TODO: when we get promises use this to make resolve lazy
+ Gitlab::Graphql::Lazy.force(GitlabSchema.find_by_gid(at_version))
end
- def design_ids(ids)
- ids&.map { |id| GlobalID.parse(id, expected_type: ::DesignManagement::Design).model_id }
+ def design_ids(gids)
+ return if gids.nil?
+
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ gids = gids.map { |id| DesignID.coerce_isolated_input(id) }
+ gids.map(&:model_id)
end
def issue
diff --git a/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb b/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb
index 03f7908780c..70021057f71 100644
--- a/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb
+++ b/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb
@@ -5,17 +5,20 @@ module Resolvers
module Version
# Resolver for a DesignAtVersion object given an implicit version context
class DesignAtVersionResolver < BaseResolver
+ DesignAtVersionID = ::Types::GlobalIDType[::DesignManagement::DesignAtVersion]
+ DesignID = ::Types::GlobalIDType[::DesignManagement::Design]
+
include Gitlab::Graphql::Authorize::AuthorizeResource
type Types::DesignManagement::DesignAtVersionType, null: true
authorize :read_design
- argument :id, GraphQL::ID_TYPE,
+ argument :id, DesignAtVersionID,
required: false,
as: :design_at_version_id,
description: 'The ID of the DesignAtVersion'
- argument :design_id, GraphQL::ID_TYPE,
+ argument :design_id, DesignID,
required: false,
description: 'The ID of a specific design'
argument :filename, GraphQL::STRING_TYPE,
@@ -29,6 +32,11 @@ module Resolvers
def resolve(design_id: nil, filename: nil, design_at_version_id: nil)
validate_arguments(design_id, filename, design_at_version_id)
+ # TODO: remove this when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ design_id &&= DesignID.coerce_isolated_input(design_id)
+ design_at_version_id &&= DesignAtVersionID.coerce_isolated_input(design_at_version_id)
+
return unless Ability.allowed?(current_user, :read_design, issue)
return specific_design_at_version(design_at_version_id) if design_at_version_id
@@ -49,7 +57,7 @@ module Resolvers
end
def specific_design_at_version(id)
- dav = GitlabSchema.object_from_id(id, expected_type: ::DesignManagement::DesignAtVersion)
+ dav = GitlabSchema.find_by_gid(id)
return unless consistent?(dav)
dav
@@ -65,8 +73,8 @@ module Resolvers
dav.design.visible_in?(version)
end
- def find(id, filename)
- ids = [parse_design_id(id).model_id] if id
+ def find(gid, filename)
+ ids = [gid.model_id] if gid
filenames = [filename] if filename
::DesignManagement::DesignsFinder
@@ -74,10 +82,6 @@ module Resolvers
.execute
end
- def parse_design_id(id)
- GitlabSchema.parse_gid(id, expected_type: ::DesignManagement::Design)
- end
-
def issue
version.issue
end
diff --git a/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb b/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb
index 5ccb2f3e311..a129d8620d4 100644
--- a/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb
+++ b/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb
@@ -11,8 +11,9 @@ module Resolvers
authorize :read_design
- argument :ids,
- [GraphQL::ID_TYPE],
+ DesignID = ::Types::GlobalIDType[::DesignManagement::Design]
+
+ argument :ids, [DesignID],
required: false,
description: 'Filters designs by their ID'
argument :filenames,
@@ -31,16 +32,19 @@ module Resolvers
private
def find(ids, filenames)
- ids = ids&.map { |id| parse_design_id(id).model_id }
-
::DesignManagement::DesignsFinder.new(issue, current_user,
- ids: ids,
+ ids: design_ids(ids),
filenames: filenames,
visible_at_version: version)
end
- def parse_design_id(id)
- GitlabSchema.parse_gid(id, expected_type: ::DesignManagement::Design)
+ def design_ids(gids)
+ return if gids.nil?
+
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ gids = gids.map { |id| DesignID.coerce_isolated_input(id) }
+ gids.map(&:model_id)
end
def issue
diff --git a/app/graphql/resolvers/design_management/version_in_collection_resolver.rb b/app/graphql/resolvers/design_management/version_in_collection_resolver.rb
index 9e729172881..ecd7ab3ee45 100644
--- a/app/graphql/resolvers/design_management/version_in_collection_resolver.rb
+++ b/app/graphql/resolvers/design_management/version_in_collection_resolver.rb
@@ -11,20 +11,25 @@ module Resolvers
alias_method :collection, :object
+ VersionID = ::Types::GlobalIDType[::DesignManagement::Version]
+
argument :sha, GraphQL::STRING_TYPE,
required: false,
description: "The SHA256 of a specific version"
- argument :id, GraphQL::ID_TYPE,
+ argument :id, VersionID,
+ as: :version_id,
required: false,
description: 'The Global ID of the version'
- def resolve(id: nil, sha: nil)
- check_args(id, sha)
+ def resolve(version_id: nil, sha: nil)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ version_id &&= VersionID.coerce_isolated_input(version_id)
- gid = GitlabSchema.parse_gid(id, expected_type: ::DesignManagement::Version) if id
+ check_args(version_id, sha)
::DesignManagement::VersionsFinder
- .new(collection, current_user, sha: sha, version_id: gid&.model_id)
+ .new(collection, current_user, sha: sha, version_id: version_id&.model_id)
.execute
.first
end
diff --git a/app/graphql/resolvers/design_management/version_resolver.rb b/app/graphql/resolvers/design_management/version_resolver.rb
index b0e0843e6c8..1bc9c1a7cd6 100644
--- a/app/graphql/resolvers/design_management/version_resolver.rb
+++ b/app/graphql/resolvers/design_management/version_resolver.rb
@@ -9,7 +9,7 @@ module Resolvers
authorize :read_design
- argument :id, GraphQL::ID_TYPE,
+ argument :id, ::Types::GlobalIDType[::DesignManagement::Version],
required: true,
description: 'The Global ID of the version'
@@ -18,7 +18,11 @@ module Resolvers
end
def find_object(id:)
- GitlabSchema.object_from_id(id, expected_type: ::DesignManagement::Version)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = ::Types::GlobalIDType[::DesignManagement::Version].coerce_isolated_input(id)
+
+ GitlabSchema.find_by_gid(id)
end
end
end
diff --git a/app/graphql/resolvers/design_management/versions_resolver.rb b/app/graphql/resolvers/design_management/versions_resolver.rb
index a62258dad5c..23858c8e991 100644
--- a/app/graphql/resolvers/design_management/versions_resolver.rb
+++ b/app/graphql/resolvers/design_management/versions_resolver.rb
@@ -7,12 +7,14 @@ module Resolvers
alias_method :design_or_collection, :object
+ VersionID = ::Types::GlobalIDType[::DesignManagement::Version]
+
argument :earlier_or_equal_to_sha, GraphQL::STRING_TYPE,
as: :sha,
required: false,
description: 'The SHA256 of the most recent acceptable version'
- argument :earlier_or_equal_to_id, GraphQL::ID_TYPE,
+ argument :earlier_or_equal_to_id, VersionID,
as: :id,
required: false,
description: 'The Global ID of the most recent acceptable version'
@@ -23,6 +25,9 @@ module Resolvers
end
def resolve(parent: nil, id: nil, sha: nil)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id &&= VersionID.coerce_isolated_input(id)
version = cutoff(parent, id, sha)
raise ::Gitlab::Graphql::Errors::ResourceNotAvailable, 'cutoff not found' unless version.present?
@@ -47,8 +52,7 @@ module Resolvers
end
end
- def specific_version(id, sha)
- gid = GitlabSchema.parse_gid(id, expected_type: ::DesignManagement::Version) if id
+ def specific_version(gid, sha)
find(sha: sha, version_id: gid&.model_id).first
end
@@ -58,8 +62,8 @@ module Resolvers
.execute
end
- def by_id(id)
- GitlabSchema.object_from_id(id, expected_type: ::DesignManagement::Version).sync
+ def by_id(gid)
+ ::Gitlab::Graphql::Lazy.force(GitlabSchema.find_by_gid(gid))
end
# Find an `at_version` argument passed to a parent node.
@@ -69,7 +73,11 @@ module Resolvers
# for consistency we should only present versions up to the given
# version here.
def at_version_arg(parent)
- ::Gitlab::Graphql::FindArgumentInParent.find(parent, :at_version, limit_depth: 4)
+ # TODO: remove coercion when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ version_id = ::Gitlab::Graphql::FindArgumentInParent.find(parent, :at_version, limit_depth: 4)
+ version_id &&= VersionID.coerce_isolated_input(version_id)
+ version_id
end
end
end
diff --git a/app/graphql/resolvers/echo_resolver.rb b/app/graphql/resolvers/echo_resolver.rb
index fe0b1893a23..6b85b700712 100644
--- a/app/graphql/resolvers/echo_resolver.rb
+++ b/app/graphql/resolvers/echo_resolver.rb
@@ -2,15 +2,16 @@
module Resolvers
class EchoResolver < BaseResolver
+ type ::GraphQL::STRING_TYPE, null: false
description 'Testing endpoint to validate the API with'
argument :text, GraphQL::STRING_TYPE, required: true,
description: 'Text to echo back'
- def resolve(**args)
- username = context[:current_user]&.username
+ def resolve(text:)
+ username = current_user&.username
- "#{username.inspect} says: #{args[:text]}"
+ "#{username.inspect} says: #{text}"
end
end
end
diff --git a/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb
index 5027403e95c..09e76dba645 100644
--- a/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb
+++ b/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb
@@ -3,19 +3,22 @@
module Resolvers
module ErrorTracking
class SentryDetailedErrorResolver < BaseResolver
- argument :id, GraphQL::ID_TYPE,
+ type Types::ErrorTracking::SentryDetailedErrorType, null: true
+
+ argument :id, ::Types::GlobalIDType[::Gitlab::ErrorTracking::DetailedError],
required: true,
description: 'ID of the Sentry issue'
- def resolve(**args)
- current_user = context[:current_user]
- issue_id = GlobalID.parse(args[:id])&.model_id
+ def resolve(id:)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = ::Types::GlobalIDType[::Gitlab::ErrorTracking::DetailedError].coerce_isolated_input(id)
# Get data from Sentry
response = ::ErrorTracking::IssueDetailsService.new(
project,
current_user,
- { issue_id: issue_id }
+ { issue_id: id.model_id }
).execute
issue = response[:issue]
issue.gitlab_project = project if issue
diff --git a/app/graphql/resolvers/error_tracking/sentry_error_collection_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_error_collection_resolver.rb
index e4b4854c273..d47cc2bae56 100644
--- a/app/graphql/resolvers/error_tracking/sentry_error_collection_resolver.rb
+++ b/app/graphql/resolvers/error_tracking/sentry_error_collection_resolver.rb
@@ -3,6 +3,8 @@
module Resolvers
module ErrorTracking
class SentryErrorCollectionResolver < BaseResolver
+ type Types::ErrorTracking::SentryErrorCollectionType, null: true
+
def resolve(**args)
project = object
diff --git a/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb
index c365baaf475..669b487db10 100644
--- a/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb
+++ b/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb
@@ -3,18 +3,20 @@
module Resolvers
module ErrorTracking
class SentryErrorStackTraceResolver < BaseResolver
- argument :id, GraphQL::ID_TYPE,
+ argument :id, ::Types::GlobalIDType[::Gitlab::ErrorTracking::DetailedError],
required: true,
description: 'ID of the Sentry issue'
- def resolve(**args)
- issue_id = GlobalID.parse(args[:id])&.model_id
+ def resolve(id:)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = ::Types::GlobalIDType[::Gitlab::ErrorTracking::DetailedError].coerce_isolated_input(id)
# Get data from Sentry
response = ::ErrorTracking::IssueLatestEventService.new(
project,
current_user,
- { issue_id: issue_id }
+ { issue_id: id.model_id }
).execute
event = response[:latest_event]
diff --git a/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb
index 79f99709505..c5cf924ce7f 100644
--- a/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb
+++ b/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb
@@ -3,6 +3,8 @@
module Resolvers
module ErrorTracking
class SentryErrorsResolver < BaseResolver
+ type Types::ErrorTracking::SentryErrorType.connection_type, null: true
+
def resolve(**args)
args[:cursor] = args.delete(:after)
project = object.project
diff --git a/app/graphql/resolvers/group_issues_resolver.rb b/app/graphql/resolvers/group_issues_resolver.rb
index 1fa6c78e730..1db0ab08e31 100644
--- a/app/graphql/resolvers/group_issues_resolver.rb
+++ b/app/graphql/resolvers/group_issues_resolver.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# rubocop:disable Graphql/ResolverType (inherited from IssuesResolver)
module Resolvers
class GroupIssuesResolver < IssuesResolver
diff --git a/app/graphql/resolvers/group_members_resolver.rb b/app/graphql/resolvers/group_members_resolver.rb
index f34c873a8a9..d3aa376c29c 100644
--- a/app/graphql/resolvers/group_members_resolver.rb
+++ b/app/graphql/resolvers/group_members_resolver.rb
@@ -2,6 +2,8 @@
module Resolvers
class GroupMembersResolver < MembersResolver
+ type Types::GroupMemberType.connection_type, null: true
+
authorize :read_group_member
private
diff --git a/app/graphql/resolvers/group_merge_requests_resolver.rb b/app/graphql/resolvers/group_merge_requests_resolver.rb
index 5ee72e3f781..2bad974daf7 100644
--- a/app/graphql/resolvers/group_merge_requests_resolver.rb
+++ b/app/graphql/resolvers/group_merge_requests_resolver.rb
@@ -6,6 +6,8 @@ module Resolvers
alias_method :group, :synchronized_object
+ type Types::MergeRequestType.connection_type, null: true
+
include_subgroups 'merge requests'
accept_assignee
accept_author
diff --git a/app/graphql/resolvers/group_milestones_resolver.rb b/app/graphql/resolvers/group_milestones_resolver.rb
index 8d34cea4fa1..83b82e2720b 100644
--- a/app/graphql/resolvers/group_milestones_resolver.rb
+++ b/app/graphql/resolvers/group_milestones_resolver.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# rubocop:disable Graphql/ResolverType (inherited from MilestonesResolver)
module Resolvers
class GroupMilestonesResolver < MilestonesResolver
@@ -6,6 +7,8 @@ module Resolvers
required: false,
description: 'Also return milestones in all subgroups and subprojects'
+ type Types::MilestoneType.connection_type, null: true
+
private
def parent_id_parameters(args)
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
index 396ae02ae13..dd35219454f 100644
--- a/app/graphql/resolvers/issues_resolver.rb
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -12,7 +12,7 @@ module Resolvers
required: false,
default_value: 'created_desc'
- type Types::IssueType, null: true
+ type Types::IssueType.connection_type, null: true
NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc
label_priority_asc label_priority_desc
diff --git a/app/graphql/resolvers/members_resolver.rb b/app/graphql/resolvers/members_resolver.rb
index 88a1ab71c45..523642e912f 100644
--- a/app/graphql/resolvers/members_resolver.rb
+++ b/app/graphql/resolvers/members_resolver.rb
@@ -5,6 +5,8 @@ module Resolvers
include Gitlab::Graphql::Authorize::AuthorizeResource
include LooksAhead
+ type Types::MemberInterface.connection_type, null: true
+
argument :search, GraphQL::STRING_TYPE,
required: false,
description: 'Search query'
diff --git a/app/graphql/resolvers/merge_request_pipelines_resolver.rb b/app/graphql/resolvers/merge_request_pipelines_resolver.rb
index b95e46d9cff..6590dfdc78c 100644
--- a/app/graphql/resolvers/merge_request_pipelines_resolver.rb
+++ b/app/graphql/resolvers/merge_request_pipelines_resolver.rb
@@ -1,7 +1,9 @@
# frozen_string_literal: true
+# rubocop: disable Graphql/ResolverType
module Resolvers
class MergeRequestPipelinesResolver < BaseResolver
+ # The GraphQL type here gets defined in this include
include ::ResolvesPipelines
alias_method :merge_request, :object
@@ -18,3 +20,4 @@ module Resolvers
end
end
end
+# rubocop: enable Graphql/ResolverType
diff --git a/app/graphql/resolvers/merge_request_resolver.rb b/app/graphql/resolvers/merge_request_resolver.rb
index a47a128ea32..4cad65fa697 100644
--- a/app/graphql/resolvers/merge_request_resolver.rb
+++ b/app/graphql/resolvers/merge_request_resolver.rb
@@ -6,6 +6,8 @@ module Resolvers
alias_method :project, :synchronized_object
+ type ::Types::MergeRequestType, null: true
+
argument :iid, GraphQL::STRING_TYPE,
required: true,
as: :iids,
diff --git a/app/graphql/resolvers/metadata_resolver.rb b/app/graphql/resolvers/metadata_resolver.rb
index 3a79e6434fb..26bfa81038c 100644
--- a/app/graphql/resolvers/metadata_resolver.rb
+++ b/app/graphql/resolvers/metadata_resolver.rb
@@ -5,7 +5,7 @@ module Resolvers
type Types::MetadataType, null: false
def resolve(**args)
- { version: Gitlab::VERSION, revision: Gitlab.revision }
+ ::InstanceMetadata.new
end
end
end
diff --git a/app/graphql/resolvers/milestones_resolver.rb b/app/graphql/resolvers/milestones_resolver.rb
index 84712b674db..564e388d571 100644
--- a/app/graphql/resolvers/milestones_resolver.rb
+++ b/app/graphql/resolvers/milestones_resolver.rb
@@ -25,7 +25,7 @@ module Resolvers
required: false,
description: 'A date that the milestone contains'
- type Types::MilestoneType, null: true
+ type Types::MilestoneType.connection_type, null: true
def resolve(**args)
validate_timeframe_params!(args)
diff --git a/app/graphql/resolvers/namespace_projects_resolver.rb b/app/graphql/resolvers/namespace_projects_resolver.rb
index c221cb9aed6..9f57c8f3405 100644
--- a/app/graphql/resolvers/namespace_projects_resolver.rb
+++ b/app/graphql/resolvers/namespace_projects_resolver.rb
@@ -23,7 +23,6 @@ module Resolvers
# 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?
query = include_subgroups ? namespace.all_projects.with_route : namespace.projects.with_route
@@ -41,6 +40,14 @@ module Resolvers
complexity = super
complexity + 10
end
+
+ private
+
+ def namespace
+ strong_memoize(:namespace) do
+ object.respond_to?(:sync) ? object.sync : object
+ end
+ end
end
end
diff --git a/app/graphql/resolvers/project_members_resolver.rb b/app/graphql/resolvers/project_members_resolver.rb
index 1ca4e81f397..e64e8b845a5 100644
--- a/app/graphql/resolvers/project_members_resolver.rb
+++ b/app/graphql/resolvers/project_members_resolver.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
+# rubocop:disable Graphql/ResolverType (inherited from MembersResolver)
module Resolvers
class ProjectMembersResolver < MembersResolver
- type Types::MemberInterface, null: true
-
authorize :read_project_member
private
diff --git a/app/graphql/resolvers/project_merge_requests_resolver.rb b/app/graphql/resolvers/project_merge_requests_resolver.rb
index ba13cb6e52c..bf082c0b182 100644
--- a/app/graphql/resolvers/project_merge_requests_resolver.rb
+++ b/app/graphql/resolvers/project_merge_requests_resolver.rb
@@ -2,6 +2,7 @@
module Resolvers
class ProjectMergeRequestsResolver < MergeRequestsResolver
+ type ::Types::MergeRequestType.connection_type, null: true
accept_assignee
accept_author
end
diff --git a/app/graphql/resolvers/project_milestones_resolver.rb b/app/graphql/resolvers/project_milestones_resolver.rb
index 976fc300b87..c88c9ce7219 100644
--- a/app/graphql/resolvers/project_milestones_resolver.rb
+++ b/app/graphql/resolvers/project_milestones_resolver.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# rubocop:disable Graphql/ResolverType (inherited from MilestonesResolver)
module Resolvers
class ProjectMilestonesResolver < MilestonesResolver
@@ -6,6 +7,8 @@ module Resolvers
required: false,
description: "Also return milestones in the project's parent group and its ancestors"
+ type Types::MilestoneType.connection_type, null: true
+
private
def parent_id_parameters(args)
diff --git a/app/graphql/resolvers/project_pipeline_resolver.rb b/app/graphql/resolvers/project_pipeline_resolver.rb
index 181c1e77109..4cf47dbdc60 100644
--- a/app/graphql/resolvers/project_pipeline_resolver.rb
+++ b/app/graphql/resolvers/project_pipeline_resolver.rb
@@ -2,6 +2,8 @@
module Resolvers
class ProjectPipelineResolver < BaseResolver
+ type ::Types::Ci::PipelineType, null: true
+
alias_method :project, :object
argument :iid, GraphQL::ID_TYPE,
diff --git a/app/graphql/resolvers/project_pipelines_resolver.rb b/app/graphql/resolvers/project_pipelines_resolver.rb
index 86094c46c2a..0171473a77f 100644
--- a/app/graphql/resolvers/project_pipelines_resolver.rb
+++ b/app/graphql/resolvers/project_pipelines_resolver.rb
@@ -1,13 +1,28 @@
# frozen_string_literal: true
+# The GraphQL type here gets defined in
+# https://gitlab.com/gitlab-org/gitlab/blob/master/app/graphql/resolvers/concerns/resolves_pipelines.rb#L7
+# rubocop: disable Graphql/ResolverType
module Resolvers
class ProjectPipelinesResolver < BaseResolver
+ include LooksAhead
include ResolvesPipelines
alias_method :project, :object
- def resolve(**args)
- resolve_pipelines(project, args)
+ def resolve_with_lookahead(**args)
+ apply_lookahead(resolve_pipelines(project, args))
+ end
+
+ private
+
+ def preloads
+ {
+ jobs: [:statuses],
+ upstream: [:triggered_by_pipeline],
+ downstream: [:triggered_pipelines]
+ }
end
end
end
+# rubocop: enable Graphql/ResolverType
diff --git a/app/graphql/resolvers/projects/jira_imports_resolver.rb b/app/graphql/resolvers/projects/jira_imports_resolver.rb
index aa9b7139f38..efd45c2c465 100644
--- a/app/graphql/resolvers/projects/jira_imports_resolver.rb
+++ b/app/graphql/resolvers/projects/jira_imports_resolver.rb
@@ -3,6 +3,8 @@
module Resolvers
module Projects
class JiraImportsResolver < BaseResolver
+ type Types::JiraImportType.connection_type, null: true
+
include Gitlab::Graphql::Authorize::AuthorizeResource
alias_method :project, :object
diff --git a/app/graphql/resolvers/projects/jira_projects_resolver.rb b/app/graphql/resolvers/projects/jira_projects_resolver.rb
index d017f973e17..31f42d305b0 100644
--- a/app/graphql/resolvers/projects/jira_projects_resolver.rb
+++ b/app/graphql/resolvers/projects/jira_projects_resolver.rb
@@ -5,6 +5,8 @@ module Resolvers
class JiraProjectsResolver < BaseResolver
include Gitlab::Graphql::Authorize::AuthorizeResource
+ type Types::Projects::Services::JiraProjectType.connection_type, null: true
+
argument :name,
GraphQL::STRING_TYPE,
required: false,
diff --git a/app/graphql/resolvers/projects/services_resolver.rb b/app/graphql/resolvers/projects/services_resolver.rb
index 40c64c24513..17d81e21c28 100644
--- a/app/graphql/resolvers/projects/services_resolver.rb
+++ b/app/graphql/resolvers/projects/services_resolver.rb
@@ -5,6 +5,8 @@ module Resolvers
class ServicesResolver < BaseResolver
include Gitlab::Graphql::Authorize::AuthorizeResource
+ type Types::Projects::ServiceType.connection_type, null: true
+
argument :active,
GraphQL::BOOLEAN_TYPE,
required: false,
diff --git a/app/graphql/resolvers/projects/snippets_resolver.rb b/app/graphql/resolvers/projects/snippets_resolver.rb
index 22895a24054..448918be2f5 100644
--- a/app/graphql/resolvers/projects/snippets_resolver.rb
+++ b/app/graphql/resolvers/projects/snippets_resolver.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# rubocop:disable Graphql/ResolverType (inherited from ResolvesSnippets)
module Resolvers
module Projects
diff --git a/app/graphql/resolvers/releases_resolver.rb b/app/graphql/resolvers/releases_resolver.rb
index 85892c2abeb..8e8127cf279 100644
--- a/app/graphql/resolvers/releases_resolver.rb
+++ b/app/graphql/resolvers/releases_resolver.rb
@@ -4,6 +4,10 @@ module Resolvers
class ReleasesResolver < BaseResolver
type Types::ReleaseType.connection_type, null: true
+ argument :sort, Types::ReleaseSortEnum,
+ required: false, default_value: :released_at_desc,
+ description: 'Sort releases by this criteria'
+
alias_method :project, :object
# This resolver has a custom singular resolver
@@ -11,12 +15,20 @@ module Resolvers
Resolvers::ReleaseResolver
end
- def resolve(**args)
+ SORT_TO_PARAMS_MAP = {
+ released_at_desc: { order_by: 'released_at', sort: 'desc' },
+ released_at_asc: { order_by: 'released_at', sort: 'asc' },
+ created_desc: { order_by: 'created_at', sort: 'desc' },
+ created_asc: { order_by: 'created_at', sort: 'asc' }
+ }.freeze
+
+ def resolve(sort:)
return unless Feature.enabled?(:graphql_release_data, project, default_enabled: true)
ReleasesFinder.new(
project,
- current_user
+ current_user,
+ SORT_TO_PARAMS_MAP[sort]
).execute
end
end
diff --git a/app/graphql/resolvers/snippets/blobs_resolver.rb b/app/graphql/resolvers/snippets/blobs_resolver.rb
index dc28358cab6..3a0dcb50faf 100644
--- a/app/graphql/resolvers/snippets/blobs_resolver.rb
+++ b/app/graphql/resolvers/snippets/blobs_resolver.rb
@@ -5,6 +5,8 @@ module Resolvers
class BlobsResolver < BaseResolver
include Gitlab::Graphql::Authorize::AuthorizeResource
+ type Types::Snippets::BlobType.connection_type, null: true
+
alias_method :snippet, :object
argument :paths, [GraphQL::STRING_TYPE],
diff --git a/app/graphql/resolvers/snippets_resolver.rb b/app/graphql/resolvers/snippets_resolver.rb
index 530a288a25b..77099565df0 100644
--- a/app/graphql/resolvers/snippets_resolver.rb
+++ b/app/graphql/resolvers/snippets_resolver.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# rubocop:disable Graphql/ResolverType (inherited from ResolvesSnippets)
module Resolvers
class SnippetsResolver < BaseResolver
@@ -8,11 +9,11 @@ module Resolvers
alias_method :user, :object
- argument :author_id, GraphQL::ID_TYPE,
+ argument :author_id, ::Types::GlobalIDType[::User],
required: false,
description: 'The ID of an author'
- argument :project_id, GraphQL::ID_TYPE,
+ argument :project_id, ::Types::GlobalIDType[::Project],
required: false,
description: 'The ID of a project'
@@ -36,9 +37,11 @@ module Resolvers
private
def snippet_finder_params(args)
+ # TODO: remove the type arguments when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
super
- .merge(author: resolve_gid(args[:author_id], :author),
- project: resolve_gid(args[:project_id], :project),
+ .merge(author: resolve_ids(args[:author_id], ::Types::GlobalIDType[::User]),
+ project: resolve_ids(args[:project_id], ::Types::GlobalIDType[::Project]),
explore: args[:explore])
end
end
diff --git a/app/graphql/resolvers/todo_resolver.rb b/app/graphql/resolvers/todo_resolver.rb
index bd5f8f274cd..9a8f7a71154 100644
--- a/app/graphql/resolvers/todo_resolver.rb
+++ b/app/graphql/resolvers/todo_resolver.rb
@@ -2,7 +2,7 @@
module Resolvers
class TodoResolver < BaseResolver
- type Types::TodoType, null: true
+ type Types::TodoType.connection_type, null: true
alias_method :target, :object
diff --git a/app/graphql/resolvers/tree_resolver.rb b/app/graphql/resolvers/tree_resolver.rb
index 5aad1c71b40..075a1929c47 100644
--- a/app/graphql/resolvers/tree_resolver.rb
+++ b/app/graphql/resolvers/tree_resolver.rb
@@ -2,6 +2,8 @@
module Resolvers
class TreeResolver < BaseResolver
+ type Types::Tree::TreeType, null: true
+
argument :path, GraphQL::STRING_TYPE,
required: false,
default_value: '',
diff --git a/app/graphql/resolvers/user_merge_requests_resolver.rb b/app/graphql/resolvers/user_merge_requests_resolver.rb
deleted file mode 100644
index b0d6e159f73..00000000000
--- a/app/graphql/resolvers/user_merge_requests_resolver.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-
-module Resolvers
- class UserMergeRequestsResolver < MergeRequestsResolver
- include ResolvesProject
-
- argument :project_path, GraphQL::STRING_TYPE,
- required: false,
- description: 'The full-path of the project the authored merge requests should be in. Incompatible with projectId.'
-
- argument :project_id, GraphQL::ID_TYPE,
- required: false,
- description: 'The global ID of the project the authored merge requests should be in. Incompatible with projectPath.'
-
- attr_reader :project
- alias_method :user, :synchronized_object
-
- def ready?(project_id: nil, project_path: nil, **args)
- return early_return unless can_read_profile?
-
- if project_id || project_path
- load_project(project_path, project_id)
- return early_return unless can_read_project?
- elsif args[:iids].present?
- raise ::Gitlab::Graphql::Errors::ArgumentError,
- 'iids requires projectPath or projectId'
- end
-
- super(**args)
- end
-
- def resolve(**args)
- prepare_args(args)
- key = :"#{user_role}_id"
- super(key => user.id, **args)
- end
-
- def user_role
- raise NotImplementedError
- end
-
- private
-
- def can_read_profile?
- Ability.allowed?(current_user, :read_user_profile, user)
- end
-
- def can_read_project?
- Ability.allowed?(current_user, :read_merge_request, project)
- end
-
- def load_project(project_path, project_id)
- @project = resolve_project(full_path: project_path, project_id: project_id)
- @project = @project.sync if @project.respond_to?(:sync)
- end
-
- def no_results_possible?(args)
- some_argument_is_empty?(args)
- end
-
- # These arguments are handled in load_project, and should not be passed to
- # the finder directly.
- def prepare_args(args)
- args.delete(:project_id)
- args.delete(:project_path)
- end
- end
-end
diff --git a/app/graphql/resolvers/user_merge_requests_resolver_base.rb b/app/graphql/resolvers/user_merge_requests_resolver_base.rb
new file mode 100644
index 00000000000..47967fe69f9
--- /dev/null
+++ b/app/graphql/resolvers/user_merge_requests_resolver_base.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class UserMergeRequestsResolverBase < MergeRequestsResolver
+ include ResolvesProject
+
+ argument :project_path, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'The full-path of the project the authored merge requests should be in. Incompatible with projectId.'
+
+ argument :project_id, ::Types::GlobalIDType[::Project],
+ required: false,
+ description: 'The global ID of the project the authored merge requests should be in. Incompatible with projectPath.'
+
+ attr_reader :project
+ alias_method :user, :synchronized_object
+
+ def ready?(project_id: nil, project_path: nil, **args)
+ return early_return unless can_read_profile?
+
+ if project_id || project_path
+ load_project(project_path, project_id)
+ return early_return unless can_read_project?
+ elsif args[:iids].present?
+ raise ::Gitlab::Graphql::Errors::ArgumentError,
+ 'iids requires projectPath or projectId'
+ end
+
+ super(**args)
+ end
+
+ def resolve(**args)
+ prepare_args(args)
+ key = :"#{user_role}_id"
+ super(key => user.id, **args)
+ end
+
+ def user_role
+ raise NotImplementedError
+ end
+
+ private
+
+ def can_read_profile?
+ Ability.allowed?(current_user, :read_user_profile, user)
+ end
+
+ def can_read_project?
+ Ability.allowed?(current_user, :read_merge_request, project)
+ end
+
+ def load_project(project_path, project_id)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ project_id &&= ::Types::GlobalIDType[::Project].coerce_isolated_input(project_id)
+ @project = ::Gitlab::Graphql::Lazy.force(resolve_project(full_path: project_path, project_id: project_id))
+ end
+
+ def no_results_possible?(args)
+ some_argument_is_empty?(args)
+ end
+
+ # These arguments are handled in load_project, and should not be passed to
+ # the finder directly.
+ def prepare_args(args)
+ args.delete(:project_id)
+ args.delete(:project_path)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/user_resolver.rb b/app/graphql/resolvers/user_resolver.rb
index a34cecba491..06c1f0cb42d 100644
--- a/app/graphql/resolvers/user_resolver.rb
+++ b/app/graphql/resolvers/user_resolver.rb
@@ -6,7 +6,7 @@ module Resolvers
type Types::UserType, null: true
- argument :id, GraphQL::ID_TYPE,
+ argument :id, Types::GlobalIDType[User],
required: false,
description: 'ID of the User'
diff --git a/app/graphql/resolvers/users/group_count_resolver.rb b/app/graphql/resolvers/users/group_count_resolver.rb
new file mode 100644
index 00000000000..5033c26554a
--- /dev/null
+++ b/app/graphql/resolvers/users/group_count_resolver.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Users
+ class GroupCountResolver < BaseResolver
+ alias_method :user, :object
+
+ def resolve(**args)
+ return unless can_read_group_count?
+
+ BatchLoader::GraphQL.for(user.id).batch do |user_ids, loader|
+ results = UserGroupsCounter.new(user_ids).execute
+
+ results.each do |user_id, count|
+ loader.call(user_id, count)
+ end
+ end
+ end
+
+ def can_read_group_count?
+ current_user&.can?(:read_group_count, user)
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/users/snippets_resolver.rb b/app/graphql/resolvers/users/snippets_resolver.rb
index d757640b5ff..c2d42437ffd 100644
--- a/app/graphql/resolvers/users/snippets_resolver.rb
+++ b/app/graphql/resolvers/users/snippets_resolver.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# rubocop:disable Graphql/ResolverType (inherited from ResolvesSnippets)
module Resolvers
module Users
diff --git a/app/graphql/resolvers/users_resolver.rb b/app/graphql/resolvers/users_resolver.rb
index 110a283b42e..f5838642141 100644
--- a/app/graphql/resolvers/users_resolver.rb
+++ b/app/graphql/resolvers/users_resolver.rb
@@ -4,6 +4,7 @@ module Resolvers
class UsersResolver < BaseResolver
include Gitlab::Graphql::Authorize::AuthorizeResource
+ type Types::UserType.connection_type, null: true
description 'Find Users'
argument :ids, [GraphQL::ID_TYPE],
@@ -18,10 +19,14 @@ module Resolvers
required: false,
default_value: 'created_desc'
- def resolve(ids: nil, usernames: nil, sort: nil)
+ argument :search, GraphQL::STRING_TYPE,
+ required: false,
+ description: "Query to search users by name, username, or primary email."
+
+ def resolve(ids: nil, usernames: nil, sort: nil, search: nil)
authorize!
- ::UsersFinder.new(context[:current_user], finder_params(ids, usernames, sort)).execute
+ ::UsersFinder.new(context[:current_user], finder_params(ids, usernames, sort, search)).execute
end
def ready?(**args)
@@ -42,11 +47,12 @@ module Resolvers
private
- def finder_params(ids, usernames, sort)
+ def finder_params(ids, usernames, sort, search)
params = {}
params[:sort] = sort if sort
params[:username] = usernames if usernames
params[:id] = parse_gids(ids) if ids
+ params[:search] = search if search
params
end
diff --git a/app/graphql/types/alert_management/http_integration_type.rb b/app/graphql/types/alert_management/http_integration_type.rb
new file mode 100644
index 00000000000..88782050b94
--- /dev/null
+++ b/app/graphql/types/alert_management/http_integration_type.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Types
+ module AlertManagement
+ class HttpIntegrationType < BaseObject
+ graphql_name 'AlertManagementHttpIntegration'
+ description 'An endpoint and credentials used to accept alerts for a project'
+
+ implements(Types::AlertManagement::IntegrationType)
+
+ authorize :admin_operations
+
+ def type
+ :http
+ end
+
+ def api_url
+ nil
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/alert_management/integration_type.rb b/app/graphql/types/alert_management/integration_type.rb
new file mode 100644
index 00000000000..bf599885584
--- /dev/null
+++ b/app/graphql/types/alert_management/integration_type.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Types
+ module AlertManagement
+ module IntegrationType
+ include Types::BaseInterface
+ graphql_name 'AlertManagementIntegration'
+
+ field :id,
+ GraphQL::ID_TYPE,
+ null: false,
+ description: 'ID of the integration'
+
+ field :type,
+ AlertManagement::IntegrationTypeEnum,
+ null: false,
+ description: 'Type of integration'
+
+ field :name,
+ GraphQL::STRING_TYPE,
+ null: true,
+ description: 'Name of the integration'
+
+ field :active,
+ GraphQL::BOOLEAN_TYPE,
+ null: true,
+ description: 'Whether the endpoint is currently accepting alerts'
+
+ field :token,
+ GraphQL::STRING_TYPE,
+ null: true,
+ description: 'Token used to authenticate alert notification requests'
+
+ field :url,
+ GraphQL::STRING_TYPE,
+ null: true,
+ description: 'Endpoint which accepts alert notifications'
+
+ field :api_url,
+ GraphQL::STRING_TYPE,
+ null: true,
+ description: 'URL at which Prometheus metrics can be queried to populate the metrics dashboard'
+
+ definition_methods do
+ def resolve_type(object, context)
+ if object.is_a?(::PrometheusService)
+ Types::AlertManagement::PrometheusIntegrationType
+ else
+ Types::AlertManagement::HttpIntegrationType
+ end
+ end
+ end
+
+ orphan_types Types::AlertManagement::PrometheusIntegrationType,
+ Types::AlertManagement::HttpIntegrationType
+ end
+ end
+end
diff --git a/app/graphql/types/alert_management/integration_type_enum.rb b/app/graphql/types/alert_management/integration_type_enum.rb
new file mode 100644
index 00000000000..2f9be549e58
--- /dev/null
+++ b/app/graphql/types/alert_management/integration_type_enum.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Types
+ module AlertManagement
+ class IntegrationTypeEnum < BaseEnum
+ graphql_name 'AlertManagementIntegrationType'
+ description 'Values of types of integrations'
+
+ value 'PROMETHEUS', 'Prometheus integration', value: :prometheus
+ value 'HTTP', 'Integration with any monitoring tool', value: :http
+ end
+ end
+end
diff --git a/app/graphql/types/alert_management/prometheus_integration_type.rb b/app/graphql/types/alert_management/prometheus_integration_type.rb
new file mode 100644
index 00000000000..f605e325b8b
--- /dev/null
+++ b/app/graphql/types/alert_management/prometheus_integration_type.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Types
+ module AlertManagement
+ class PrometheusIntegrationType < BaseObject
+ include ::Gitlab::Routing
+
+ graphql_name 'AlertManagementPrometheusIntegration'
+ description 'An endpoint and credentials used to accept Prometheus alerts for a project'
+
+ implements(Types::AlertManagement::IntegrationType)
+
+ authorize :admin_project
+
+ alias_method :prometheus_service, :object
+
+ def name
+ prometheus_service.title
+ end
+
+ def type
+ :prometheus
+ end
+
+ def token
+ prometheus_service.project&.alerting_setting&.token
+ end
+
+ def url
+ prometheus_service.project && notify_project_prometheus_alerts_url(prometheus_service.project, format: :json)
+ end
+
+ def active
+ prometheus_service.manual_configuration?
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/availability_enum.rb b/app/graphql/types/availability_enum.rb
new file mode 100644
index 00000000000..61686b9359f
--- /dev/null
+++ b/app/graphql/types/availability_enum.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Types
+ class AvailabilityEnum < BaseEnum
+ graphql_name 'AvailabilityEnum'
+ description 'User availability status'
+
+ ::UserStatus.availabilities.keys.each do |availability_value|
+ value availability_value.upcase, value: availability_value, description: availability_value.titleize
+ end
+ end
+end
diff --git a/app/graphql/types/base_object.rb b/app/graphql/types/base_object.rb
index 70e665f8fc3..9c36c83d4a3 100644
--- a/app/graphql/types/base_object.rb
+++ b/app/graphql/types/base_object.rb
@@ -8,6 +8,12 @@ module Types
field_class Types::BaseField
+ def self.accepts(*types)
+ @accepts ||= []
+ @accepts += types
+ @accepts
+ end
+
# All graphql fields exposing an id, should expose a global id.
def id
GitlabSchema.id_from_object(object)
@@ -16,5 +22,13 @@ module Types
def current_user
context[:current_user]
end
+
+ def self.assignable?(object)
+ assignable = accepts
+
+ return true if assignable.blank?
+
+ assignable.any? { |cls| object.is_a?(cls) }
+ end
end
end
diff --git a/app/graphql/types/board_type.rb b/app/graphql/types/board_type.rb
index f5dc9e08427..2a7b318e283 100644
--- a/app/graphql/types/board_type.rb
+++ b/app/graphql/types/board_type.rb
@@ -4,7 +4,7 @@ module Types
class BoardType < BaseObject
graphql_name 'Board'
description 'Represents a project or group board'
-
+ accepts ::Board
authorize :read_board
field :id, type: GraphQL::ID_TYPE, null: false,
diff --git a/app/graphql/types/ci/detailed_status_type.rb b/app/graphql/types/ci/detailed_status_type.rb
index f4a50115ee6..6d8af400ac4 100644
--- a/app/graphql/types/ci/detailed_status_type.rb
+++ b/app/graphql/types/ci/detailed_status_type.rb
@@ -30,7 +30,7 @@ module Types
if obj.has_action?
{
button_title: obj.action_button_title,
- icon: obj.icon,
+ icon: obj.action_icon,
method: obj.action_method,
path: obj.action_path,
title: obj.action_title
diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb
index 0ee1ad47b62..feaff4e81d8 100644
--- a/app/graphql/types/ci/job_type.rb
+++ b/app/graphql/types/ci/job_type.rb
@@ -6,6 +6,9 @@ module Types
class JobType < BaseObject
graphql_name 'CiJob'
+ field :pipeline, Types::Ci::PipelineType, null: false,
+ description: 'Pipeline the job belongs to',
+ resolve: -> (build, _, _) { Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Pipeline, build.pipeline_id).find }
field :name, GraphQL::STRING_TYPE, null: true,
description: 'Name of the job'
field :needs, JobType.connection_type, null: true,
diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb
index c508b746317..c25db39f600 100644
--- a/app/graphql/types/ci/pipeline_type.rb
+++ b/app/graphql/types/ci/pipeline_type.rb
@@ -13,49 +13,89 @@ module Types
field :id, GraphQL::ID_TYPE, null: false,
description: 'ID of the pipeline'
+
field :iid, GraphQL::STRING_TYPE, null: false,
description: 'Internal ID of the pipeline'
field :sha, GraphQL::STRING_TYPE, null: false,
description: "SHA of the pipeline's commit"
+
field :before_sha, GraphQL::STRING_TYPE, null: true,
description: 'Base SHA of the source branch'
+
field :status, PipelineStatusEnum, null: false,
description: "Status of the pipeline (#{::Ci::Pipeline.all_state_names.compact.join(', ').upcase})"
+
field :detailed_status, Types::Ci::DetailedStatusType, null: false,
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 (#{::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,
description: 'Coverage percentage'
+
field :created_at, Types::TimeType, null: false,
description: "Timestamp of the pipeline's creation"
+
field :updated_at, Types::TimeType, null: false,
description: "Timestamp of the pipeline's last activity"
+
field :started_at, Types::TimeType, null: true,
description: 'Timestamp when the pipeline was started'
+
field :finished_at, Types::TimeType, null: true,
description: "Timestamp of the pipeline's completion"
+
field :committed_at, Types::TimeType, null: true,
description: "Timestamp of the pipeline's commit"
+
field :stages, Types::Ci::StageType.connection_type, null: true,
description: 'Stages of the pipeline',
extras: [:lookahead],
resolver: Resolvers::Ci::PipelineStagesResolver
+
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
+
+ field :jobs,
+ ::Types::Ci::JobType.connection_type,
+ null: true,
+ description: 'Jobs belonging to the pipeline',
+ resolver: ::Resolvers::Ci::JobsResolver
+
+ field :source_job, Types::Ci::JobType, null: true,
+ description: 'Job where pipeline was triggered from'
+
+ field :downstream, Types::Ci::PipelineType.connection_type, null: true,
+ description: 'Pipelines this pipeline will trigger',
+ method: :triggered_pipelines_with_preloads
+
+ field :upstream, Types::Ci::PipelineType, null: true,
+ description: 'Pipeline that triggered the pipeline',
+ method: :triggered_by_pipeline
+
+ field :path, GraphQL::STRING_TYPE, null: true,
+ description: "Relative path to the pipeline's page",
+ resolve: -> (obj, _args, _ctx) { ::Gitlab::Routing.url_helpers.project_pipeline_path(obj.project, obj) }
+
+ field :project, Types::ProjectType, null: true,
+ description: 'Project the pipeline belongs to'
end
end
end
diff --git a/app/graphql/types/ci/runner_setup_type.rb b/app/graphql/types/ci/runner_setup_type.rb
new file mode 100644
index 00000000000..66abcf65adf
--- /dev/null
+++ b/app/graphql/types/ci/runner_setup_type.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class RunnerSetupType < BaseObject
+ graphql_name 'RunnerSetup'
+
+ field :install_instructions, GraphQL::STRING_TYPE, null: false,
+ description: 'Instructions for installing the runner on the specified architecture'
+ field :register_instructions, GraphQL::STRING_TYPE, null: true,
+ description: 'Instructions for registering the runner'
+ end
+ end
+end
diff --git a/app/graphql/types/commit_type.rb b/app/graphql/types/commit_type.rb
index dd4b4c3b114..c24b47f08ef 100644
--- a/app/graphql/types/commit_type.rb
+++ b/app/graphql/types/commit_type.rb
@@ -40,16 +40,9 @@ module Types
field :author, type: Types::UserType, null: true,
description: 'Author of the commit'
- field :pipelines, Types::Ci::PipelineType.connection_type,
+ field :pipelines,
null: true,
description: 'Pipelines of the commit ordered latest first',
resolver: Resolvers::CommitPipelinesResolver
-
- field :latest_pipeline,
- type: Types::Ci::PipelineType,
- null: true,
- deprecated: { reason: 'Use `pipelines`', milestone: '12.5' },
- description: 'Latest pipeline of the commit',
- resolver: Resolvers::CommitPipelinesResolver.last
end
end
diff --git a/app/graphql/types/container_repository_cleanup_status_enum.rb b/app/graphql/types/container_repository_cleanup_status_enum.rb
new file mode 100644
index 00000000000..6e654e65360
--- /dev/null
+++ b/app/graphql/types/container_repository_cleanup_status_enum.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Types
+ class ContainerRepositoryCleanupStatusEnum < BaseEnum
+ graphql_name 'ContainerRepositoryCleanupStatus'
+ description 'Status of the tags cleanup of a container repository'
+
+ value 'UNSCHEDULED', value: 'cleanup_unscheduled', description: 'The tags cleanup is not scheduled. This is the default state.'
+ value 'SCHEDULED', value: 'cleanup_scheduled', description: 'The tags cleanup is scheduled and is going to be executed shortly.'
+ value 'UNFINISHED', value: 'cleanup_unfinished', description: 'The tags cleanup has been partially executed. There are still remaining tags to delete.'
+ value 'ONGOING', value: 'cleanup_ongoing', description: 'The tags cleanup is ongoing.'
+ end
+end
diff --git a/app/graphql/types/container_repository_details_type.rb b/app/graphql/types/container_repository_details_type.rb
new file mode 100644
index 00000000000..34523f3ea4a
--- /dev/null
+++ b/app/graphql/types/container_repository_details_type.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Types
+ class ContainerRepositoryDetailsType < Types::ContainerRepositoryType
+ graphql_name 'ContainerRepositoryDetails'
+
+ description 'Details of a container repository'
+
+ authorize :read_container_image
+
+ field :tags,
+ Types::ContainerRepositoryTagType.connection_type,
+ null: true,
+ description: 'Tags of the container repository',
+ max_page_size: 20
+
+ def can_delete
+ Ability.allowed?(current_user, :destroy_container_image, object)
+ end
+ end
+end
diff --git a/app/graphql/types/container_repository_status_enum.rb b/app/graphql/types/container_repository_status_enum.rb
new file mode 100644
index 00000000000..8f3ba8f1083
--- /dev/null
+++ b/app/graphql/types/container_repository_status_enum.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Types
+ class ContainerRepositoryStatusEnum < BaseEnum
+ graphql_name 'ContainerRepositoryStatus'
+ description 'Status of a container repository'
+
+ ::ContainerRepository.statuses.keys.each do |status|
+ value status.upcase, value: status, description: "#{status.titleize} status."
+ end
+ end
+end
diff --git a/app/graphql/types/container_repository_tag_type.rb b/app/graphql/types/container_repository_tag_type.rb
new file mode 100644
index 00000000000..25e605b689d
--- /dev/null
+++ b/app/graphql/types/container_repository_tag_type.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Types
+ class ContainerRepositoryTagType < BaseObject
+ graphql_name 'ContainerRepositoryTag'
+
+ description 'A tag from a container repository'
+
+ authorize :read_container_image
+
+ field :name, GraphQL::STRING_TYPE, null: false, description: 'Name of the tag.'
+ field :path, GraphQL::STRING_TYPE, null: false, description: 'Path of the tag.'
+ field :location, GraphQL::STRING_TYPE, null: false, description: 'URL of the tag.'
+ field :digest, GraphQL::STRING_TYPE, null: false, description: 'Digest of the tag.'
+ field :revision, GraphQL::STRING_TYPE, null: false, description: 'Revision of the tag.'
+ field :short_revision, GraphQL::STRING_TYPE, null: false, description: 'Short revision of the tag.'
+ field :total_size, GraphQL::INT_TYPE, null: false, description: 'The size of the tag.'
+ field :created_at, Types::TimeType, null: false, description: 'Timestamp when the tag was created.'
+ field :can_delete, GraphQL::BOOLEAN_TYPE, null: false, description: 'Can the current user delete this tag.'
+
+ def can_delete
+ Ability.allowed?(current_user, :destroy_container_image, object)
+ end
+ end
+end
diff --git a/app/graphql/types/container_repository_type.rb b/app/graphql/types/container_repository_type.rb
new file mode 100644
index 00000000000..45d19fdbc50
--- /dev/null
+++ b/app/graphql/types/container_repository_type.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Types
+ class ContainerRepositoryType < BaseObject
+ graphql_name 'ContainerRepository'
+
+ description 'A container repository'
+
+ authorize :read_container_image
+
+ field :id, GraphQL::ID_TYPE, null: false, description: 'ID of the container repository.'
+ field :name, GraphQL::STRING_TYPE, null: false, description: 'Name of the container repository.'
+ field :path, GraphQL::STRING_TYPE, null: false, description: 'Path of the container repository.'
+ field :location, GraphQL::STRING_TYPE, null: false, description: 'URL of the container repository.'
+ field :created_at, Types::TimeType, null: false, description: 'Timestamp when the container repository was created.'
+ field :updated_at, Types::TimeType, null: false, description: 'Timestamp when the container repository was updated.'
+ field :expiration_policy_started_at, Types::TimeType, null: true, description: 'Timestamp when the cleanup done by the expiration policy was started on the container repository.'
+ field :expiration_policy_cleanup_status, Types::ContainerRepositoryCleanupStatusEnum, null: true, description: 'The tags cleanup status for the container repository.'
+ field :status, Types::ContainerRepositoryStatusEnum, null: true, description: 'Status of the container repository.'
+ field :tags_count, GraphQL::INT_TYPE, null: false, description: 'Number of tags associated with this image.'
+ field :can_delete, GraphQL::BOOLEAN_TYPE, null: false, description: 'Can the current user delete the container repository.'
+
+ def can_delete
+ Ability.allowed?(current_user, :update_container_image, object)
+ end
+ end
+end
diff --git a/app/graphql/types/countable_connection_type.rb b/app/graphql/types/countable_connection_type.rb
index 2538366b786..f67194d99b3 100644
--- a/app/graphql/types/countable_connection_type.rb
+++ b/app/graphql/types/countable_connection_type.rb
@@ -3,7 +3,7 @@
module Types
# rubocop: disable Graphql/AuthorizeTypes
class CountableConnectionType < GraphQL::Types::Relay::BaseConnection
- field :count, Integer, null: false,
+ field :count, GraphQL::INT_TYPE, null: false,
description: 'Total count of collection'
def count
diff --git a/app/graphql/types/custom_emoji_type.rb b/app/graphql/types/custom_emoji_type.rb
new file mode 100644
index 00000000000..f7d1a7800bc
--- /dev/null
+++ b/app/graphql/types/custom_emoji_type.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Types
+ class CustomEmojiType < BaseObject
+ graphql_name 'CustomEmoji'
+ description 'A custom emoji uploaded by user'
+
+ authorize :read_custom_emoji
+
+ field :id, ::Types::GlobalIDType[::CustomEmoji],
+ null: false,
+ description: 'The ID of the emoji'
+
+ field :name, GraphQL::STRING_TYPE,
+ null: false,
+ description: 'The name of the emoji'
+
+ field :url, GraphQL::STRING_TYPE,
+ null: false,
+ method: :file,
+ description: 'The link to file of the emoji'
+
+ field :external, GraphQL::BOOLEAN_TYPE,
+ null: false,
+ description: 'Whether the emoji is an external link'
+ end
+end
diff --git a/app/graphql/types/environment_type.rb b/app/graphql/types/environment_type.rb
index e4631a4a903..e3885668643 100644
--- a/app/graphql/types/environment_type.rb
+++ b/app/graphql/types/environment_type.rb
@@ -18,9 +18,8 @@ module Types
field :state, GraphQL::STRING_TYPE, null: false,
description: 'State of the environment, for example: available/stopped'
- field :path, GraphQL::STRING_TYPE, null: true,
- description: 'The path to the environment. Will always return null ' \
- 'if `expose_environment_path_in_alert_details` feature flag is disabled'
+ field :path, GraphQL::STRING_TYPE, null: false,
+ description: 'The path to the environment.'
field :metrics_dashboard, Types::Metrics::DashboardType, null: true,
description: 'Metrics dashboard schema for the environment',
diff --git a/app/graphql/types/global_id_type.rb b/app/graphql/types/global_id_type.rb
index 9ae9ba32c13..4c51d4248dd 100644
--- a/app/graphql/types/global_id_type.rb
+++ b/app/graphql/types/global_id_type.rb
@@ -30,6 +30,8 @@ module Types
# @param value [String]
# @return [GID]
def self.coerce_input(value, _ctx)
+ return if value.nil?
+
gid = GlobalID.parse(value)
raise GraphQL::CoercionError, "#{value.inspect} is not a valid Global ID" if gid.nil?
raise GraphQL::CoercionError, "#{value.inspect} is not a Gitlab Global ID" unless gid.app == GlobalID.app
diff --git a/app/graphql/types/grafana_integration_type.rb b/app/graphql/types/grafana_integration_type.rb
index 7db733fc62a..6625af36f82 100644
--- a/app/graphql/types/grafana_integration_type.rb
+++ b/app/graphql/types/grafana_integration_type.rb
@@ -16,13 +16,5 @@ module Types
description: 'Timestamp of the issue\'s creation'
field :updated_at, Types::TimeType, null: false,
description: 'Timestamp of the issue\'s last activity'
-
- field :token, GraphQL::STRING_TYPE, null: false,
- deprecated: { reason: 'Plain text token has been masked for security reasons', milestone: '12.7' },
- description: 'API token for the Grafana integration'
-
- def token
- object.masked_token
- end
end
end
diff --git a/app/graphql/types/group_invitation_type.rb b/app/graphql/types/group_invitation_type.rb
new file mode 100644
index 00000000000..0372ce178ff
--- /dev/null
+++ b/app/graphql/types/group_invitation_type.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ class GroupInvitationType < BaseObject
+ expose_permissions Types::PermissionTypes::Group
+ authorize :read_group
+
+ implements InvitationInterface
+
+ graphql_name 'GroupInvitation'
+ description 'Represents a Group Invitation'
+
+ field :group, Types::GroupType, null: true,
+ description: 'Group that a User is invited to',
+ resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Group, obj.source_id).find }
+ end
+end
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index 199cc0308c5..fb028184488 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -17,6 +17,10 @@ module Types
group.avatar_url(only_path: false)
end
+ field :custom_emoji, Types::CustomEmojiType.connection_type, null: true,
+ description: 'Custom emoji within this namespace',
+ feature_flag: :custom_emoji
+
field :share_with_group_lock, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if sharing a project with another group within this group is prevented'
@@ -82,11 +86,16 @@ module Types
end
field :group_members,
- Types::GroupMemberType.connection_type,
description: 'A membership of a user within this group',
- extras: [:lookahead],
resolver: Resolvers::GroupMembersResolver
+ field :container_repositories,
+ Types::ContainerRepositoryType.connection_type,
+ null: true,
+ description: 'Container repositories of the project',
+ resolver: Resolvers::ContainerRepositoriesResolver,
+ authorize: :read_container_image
+
def label(title:)
BatchLoader::GraphQL.for(title).batch(key: group) do |titles, loader, args|
LabelsFinder
diff --git a/app/graphql/types/invitation_interface.rb b/app/graphql/types/invitation_interface.rb
new file mode 100644
index 00000000000..a29716c292e
--- /dev/null
+++ b/app/graphql/types/invitation_interface.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Types
+ module InvitationInterface
+ include BaseInterface
+
+ field :email, GraphQL::STRING_TYPE, null: false,
+ description: 'Email of the member to invite'
+
+ field :access_level, Types::AccessLevelType, null: true,
+ description: 'GitLab::Access level'
+
+ field :created_by, Types::UserType, null: true,
+ description: 'User that authorized membership'
+
+ field :created_at, Types::TimeType, null: true,
+ description: 'Date and time the membership was created'
+
+ field :updated_at, Types::TimeType, null: true,
+ description: 'Date and time the membership was last updated'
+
+ field :expires_at, Types::TimeType, null: true,
+ description: 'Date and time the membership expires'
+
+ field :user, Types::UserType, null: true,
+ description: 'User that is associated with the member object'
+
+ definition_methods do
+ def resolve_type(object, context)
+ case object
+ when GroupMember
+ Types::GroupInvitationType
+ when ProjectMember
+ Types::ProjectInvitationType
+ else
+ raise ::Gitlab::Graphql::Errors::BaseError, "Unknown member type #{object.class.name}"
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/issue_connection_type.rb b/app/graphql/types/issue_connection_type.rb
new file mode 100644
index 00000000000..2e0f05f741e
--- /dev/null
+++ b/app/graphql/types/issue_connection_type.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Types
+ # rubocop: disable Graphql/AuthorizeTypes
+ class IssueConnectionType < CountableConnectionType
+ end
+end
+
+Types::IssueConnectionType.prepend_if_ee('::EE::Types::IssueConnectionType')
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index 487508f448f..49c84f75e1a 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -4,7 +4,7 @@ module Types
class IssueType < BaseObject
graphql_name 'Issue'
- connection_type_class(Types::CountableConnectionType)
+ connection_type_class(Types::IssueConnectionType)
implements(Types::Notes::NoteableType)
implements(Types::CurrentUserTodos)
@@ -41,6 +41,9 @@ module Types
field :assignees, Types::UserType.connection_type, null: true,
description: 'Assignees of the issue'
+ field :updated_by, Types::UserType, null: true,
+ description: 'User that last updated the issue'
+
field :labels, Types::LabelType.connection_type, null: true,
description: 'Labels of the issue'
field :milestone, Types::MilestoneType, null: true,
@@ -59,6 +62,8 @@ module Types
description: 'Number of downvotes the issue has received'
field :user_notes_count, GraphQL::INT_TYPE, null: false,
description: 'Number of user notes of the issue'
+ field :user_discussions_count, GraphQL::INT_TYPE, null: false,
+ description: 'Number of user discussions in the issue'
field :web_path, GraphQL::STRING_TYPE, null: false, method: :issue_path,
description: 'Web path of the issue'
field :web_url, GraphQL::STRING_TYPE, null: false,
@@ -68,12 +73,19 @@ module Types
field :participants, Types::UserType.connection_type, null: true, complexity: 5,
description: 'List of participants in the issue'
+ field :emails_disabled, GraphQL::BOOLEAN_TYPE, null: false,
+ method: :project_emails_disabled?,
+ description: 'Indicates if a project has email notifications disabled: `true` if email notifications are disabled'
field :subscribed, GraphQL::BOOLEAN_TYPE, method: :subscribed?, null: false, complexity: 5,
description: 'Indicates the currently logged in user is subscribed to the issue'
field :time_estimate, GraphQL::INT_TYPE, null: false,
description: 'Time estimate of the issue'
field :total_time_spent, GraphQL::INT_TYPE, null: false,
description: 'Total time reported as spent on the issue'
+ field :human_time_estimate, GraphQL::STRING_TYPE, null: true,
+ description: 'Human-readable time estimate of the issue'
+ field :human_total_time_spent, GraphQL::STRING_TYPE, null: true,
+ description: 'Human-readable total time reported as spent on the issue'
field :closed_at, Types::TimeType, null: true,
description: 'Timestamp of when the issue was closed'
@@ -86,11 +98,6 @@ module Types
field :task_completion_status, Types::TaskCompletionStatus, null: false,
description: 'Task completion status of the issue'
- field :designs, Types::DesignManagement::DesignCollectionType, null: true,
- method: :design_collection,
- deprecated: { reason: 'Use `designCollection`', milestone: '12.2' },
- description: 'The designs associated with this issue'
-
field :design_collection, Types::DesignManagement::DesignCollectionType, null: true,
description: 'Collection of design images associated with this issue'
@@ -106,14 +113,48 @@ module Types
field :severity, Types::IssuableSeverityEnum, null: true,
description: 'Severity level of the incident'
+ field :moved, GraphQL::BOOLEAN_TYPE, method: :moved?, null: true,
+ description: 'Indicates if issue got moved from other project'
+
+ field :moved_to, Types::IssueType, null: true,
+ description: 'Updated Issue after it got moved to another project'
+
+ def user_notes_count
+ BatchLoader::GraphQL.for(object.id).batch(key: :issue_user_notes_count) do |ids, loader, args|
+ counts = Note.count_for_collection(ids, 'Issue').index_by(&:noteable_id)
+
+ ids.each do |id|
+ loader.call(id, counts[id]&.count || 0)
+ end
+ end
+ end
+
+ def user_discussions_count
+ BatchLoader::GraphQL.for(object.id).batch(key: :issue_user_discussions_count) do |ids, loader, args|
+ counts = Note.count_for_collection(ids, 'Issue', 'COUNT(DISTINCT discussion_id) as count').index_by(&:noteable_id)
+
+ ids.each do |id|
+ loader.call(id, counts[id]&.count || 0)
+ end
+ end
+ end
+
def author
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.author_id).find
end
+ def updated_by
+ Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.updated_by_id).find
+ end
+
def milestone
Gitlab::Graphql::Loaders::BatchModelLoader.new(Milestone, object.milestone_id).find
end
+ def moved_to
+ Gitlab::Graphql::Loaders::BatchModelLoader.new(Issue, object.moved_to_id).find
+ end
+
def discussion_locked
!!object.discussion_locked
end
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 372aeac055b..e68d6706c43 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -68,6 +68,8 @@ module Types
description: 'SHA of the merge request commit (set once merged)'
field :user_notes_count, GraphQL::INT_TYPE, null: true,
description: 'User notes count of the merge request'
+ field :user_discussions_count, GraphQL::INT_TYPE, null: true,
+ description: 'Number of user discussions in the merge request'
field :should_remove_source_branch, GraphQL::BOOLEAN_TYPE, method: :should_remove_source_branch?, null: true,
description: 'Indicates if the source branch of the merge request will be deleted after merge'
field :force_remove_source_branch, GraphQL::BOOLEAN_TYPE, method: :force_remove_source_branch?, null: true,
@@ -86,9 +88,6 @@ module Types
description: 'Rebase commit SHA of the merge request'
field :rebase_in_progress, GraphQL::BOOLEAN_TYPE, method: :rebase_in_progress?, null: false, calls_gitaly: true,
description: 'Indicates if there is a rebase currently in progress for the merge request'
- field :merge_commit_message, GraphQL::STRING_TYPE, method: :default_merge_commit_message, null: true,
- deprecated: { reason: 'Use `defaultMergeCommitMessage`', milestone: '11.8' },
- description: 'Default merge commit message of the merge request'
field :default_merge_commit_message, GraphQL::STRING_TYPE, null: true,
description: 'Default merge commit message of the merge request'
field :merge_ongoing, GraphQL::BOOLEAN_TYPE, method: :merge_ongoing?, null: false,
@@ -112,14 +111,13 @@ 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,
+ field :pipelines,
null: true,
description: 'Pipelines for the merge request',
resolver: Resolvers::MergeRequestPipelinesResolver
field :milestone, Types::MilestoneType, null: true,
- description: 'The milestone of the merge request',
- resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Milestone, obj.milestone_id).find }
+ description: 'The milestone of the merge request'
field :assignees, Types::UserType.connection_type, null: true, complexity: 5,
description: 'Assignees of the merge request'
field :author, Types::UserType, null: true,
@@ -159,17 +157,25 @@ module Types
object.approved_by_users
end
- # rubocop: disable CodeReuse/ActiveRecord
def user_notes_count
BatchLoader::GraphQL.for(object.id).batch(key: :merge_request_user_notes_count) do |ids, loader, args|
- counts = Note.where(noteable_type: 'MergeRequest', noteable_id: ids).user.group(:noteable_id).count
+ counts = Note.count_for_collection(ids, 'MergeRequest').index_by(&:noteable_id)
+
+ ids.each do |id|
+ loader.call(id, counts[id]&.count || 0)
+ end
+ end
+ end
+
+ def user_discussions_count
+ BatchLoader::GraphQL.for(object.id).batch(key: :merge_request_user_discussions_count) do |ids, loader, args|
+ counts = Note.count_for_collection(ids, 'MergeRequest', 'COUNT(DISTINCT discussion_id) as count').index_by(&:noteable_id)
ids.each do |id|
- loader.call(id, counts[id] || 0)
+ loader.call(id, counts[id]&.count || 0)
end
end
end
- # rubocop: enable CodeReuse/ActiveRecord
def diff_stats(path: nil)
stats = Array.wrap(object.diff_stats&.to_a)
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 3f48e7b4a16..75ccac6d590 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -11,6 +11,13 @@ module Types
mount_mutation Mutations::AlertManagement::UpdateAlertStatus
mount_mutation Mutations::AlertManagement::Alerts::SetAssignees
mount_mutation Mutations::AlertManagement::Alerts::Todo::Create
+ mount_mutation Mutations::AlertManagement::HttpIntegration::Create
+ mount_mutation Mutations::AlertManagement::HttpIntegration::Update
+ mount_mutation Mutations::AlertManagement::HttpIntegration::ResetToken
+ mount_mutation Mutations::AlertManagement::HttpIntegration::Destroy
+ mount_mutation Mutations::AlertManagement::PrometheusIntegration::Create
+ mount_mutation Mutations::AlertManagement::PrometheusIntegration::Update
+ mount_mutation Mutations::AlertManagement::PrometheusIntegration::ResetToken
mount_mutation Mutations::AwardEmojis::Add
mount_mutation Mutations::AwardEmojis::Remove
mount_mutation Mutations::AwardEmojis::Toggle
@@ -22,6 +29,7 @@ module Types
mount_mutation Mutations::Boards::Lists::Destroy
mount_mutation Mutations::Branches::Create, calls_gitaly: true
mount_mutation Mutations::Commits::Create, calls_gitaly: true
+ mount_mutation Mutations::CustomEmoji::Create, feature_flag: :custom_emoji
mount_mutation Mutations::Discussions::ToggleResolve
mount_mutation Mutations::Issues::Create
mount_mutation Mutations::Issues::SetAssignees
@@ -32,6 +40,7 @@ module Types
mount_mutation Mutations::Issues::SetSubscription
mount_mutation Mutations::Issues::Update
mount_mutation Mutations::Issues::Move
+ mount_mutation Mutations::Labels::Create
mount_mutation Mutations::MergeRequests::Create
mount_mutation Mutations::MergeRequests::Update
mount_mutation Mutations::MergeRequests::SetLabels
@@ -53,7 +62,13 @@ module Types
description: 'Updates a DiffNote on an image (a `Note` where the `position.positionType` is `"image"`). ' \
'If the body of the Note contains only quick actions, the Note will be ' \
'destroyed during the update, and no Note will be returned'
+ mount_mutation Mutations::Notes::RepositionImageDiffNote
mount_mutation Mutations::Notes::Destroy
+ mount_mutation Mutations::Releases::Create
+ mount_mutation Mutations::Terraform::State::Delete
+ mount_mutation Mutations::Terraform::State::Lock
+ mount_mutation Mutations::Terraform::State::Unlock
+ mount_mutation Mutations::Todos::Create
mount_mutation Mutations::Todos::MarkDone
mount_mutation Mutations::Todos::Restore
mount_mutation Mutations::Todos::MarkAllDone
@@ -68,6 +83,7 @@ module Types
mount_mutation Mutations::DesignManagement::Delete, calls_gitaly: true
mount_mutation Mutations::DesignManagement::Move
mount_mutation Mutations::ContainerExpirationPolicies::Update
+ mount_mutation Mutations::ContainerRepositories::Destroy
mount_mutation Mutations::Ci::PipelineCancel
mount_mutation Mutations::Ci::PipelineDestroy
mount_mutation Mutations::Ci::PipelineRetry
diff --git a/app/graphql/types/notes/update_diff_image_position_input_type.rb b/app/graphql/types/notes/update_diff_image_position_input_type.rb
index af99764f9f2..1b915b65ae9 100644
--- a/app/graphql/types/notes/update_diff_image_position_input_type.rb
+++ b/app/graphql/types/notes/update_diff_image_position_input_type.rb
@@ -23,6 +23,14 @@ module Types
argument :height, GraphQL::INT_TYPE,
required: false,
description: copy_field_description(Types::Notes::DiffPositionType, :height)
+
+ def prepare
+ to_h.compact.tap do |properties|
+ if properties.empty?
+ raise GraphQL::ExecutionError, "At least one property of `#{self.class.graphql_name}` must be set"
+ end
+ end
+ end
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/permission_types/custom_emoji.rb b/app/graphql/types/permission_types/custom_emoji.rb
new file mode 100644
index 00000000000..0b2e7da44f5
--- /dev/null
+++ b/app/graphql/types/permission_types/custom_emoji.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Types
+ module PermissionTypes
+ class CustomEmoji < BasePermissionType
+ graphql_name 'CustomEmojiPermissions'
+
+ abilities :create_custom_emoji, :read_custom_emoji
+ end
+ end
+end
diff --git a/app/graphql/types/permission_types/note.rb b/app/graphql/types/permission_types/note.rb
index a585d3daaa8..923f2b660fe 100644
--- a/app/graphql/types/permission_types/note.rb
+++ b/app/graphql/types/permission_types/note.rb
@@ -5,7 +5,7 @@ module Types
class Note < BasePermissionType
graphql_name 'NotePermissions'
- abilities :read_note, :create_note, :admin_note, :resolve_note, :award_emoji
+ abilities :read_note, :create_note, :admin_note, :resolve_note, :reposition_note, :award_emoji
end
end
end
diff --git a/app/graphql/types/project_invitation_type.rb b/app/graphql/types/project_invitation_type.rb
new file mode 100644
index 00000000000..a5367a4f204
--- /dev/null
+++ b/app/graphql/types/project_invitation_type.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Types
+ class ProjectInvitationType < BaseObject
+ graphql_name 'ProjectInvitation'
+ description 'Represents a Project Membership Invitation'
+
+ expose_permissions Types::PermissionTypes::Project
+
+ implements InvitationInterface
+
+ authorize :read_project
+
+ field :project, Types::ProjectType, null: true,
+ description: 'Project ID for the project of the invitation'
+
+ def project
+ Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.source_id).find
+ end
+ end
+end
diff --git a/app/graphql/types/project_statistics_type.rb b/app/graphql/types/project_statistics_type.rb
index b3916e42e92..26cb5ab59b5 100644
--- a/app/graphql/types/project_statistics_type.rb
+++ b/app/graphql/types/project_statistics_type.rb
@@ -10,18 +10,20 @@ module Types
description: 'Commit count of the project'
field :storage_size, GraphQL::FLOAT_TYPE, null: false,
- description: 'Storage size of the project'
+ description: 'Storage size of the project in bytes'
field :repository_size, GraphQL::FLOAT_TYPE, null: false,
- description: 'Repository size of the project'
+ description: 'Repository size of the project in bytes'
field :lfs_objects_size, GraphQL::FLOAT_TYPE, null: false,
- description: 'Large File Storage (LFS) object size of the project'
+ description: 'Large File Storage (LFS) object size of the project in bytes'
field :build_artifacts_size, GraphQL::FLOAT_TYPE, null: false,
- description: 'Build artifacts size of the project'
+ description: 'Build artifacts size of the project in bytes'
field :packages_size, GraphQL::FLOAT_TYPE, null: false,
- description: 'Packages size of the project'
+ description: 'Packages size of the project in bytes'
field :wiki_size, GraphQL::FLOAT_TYPE, null: true,
- description: 'Wiki size of the project'
+ description: 'Wiki size of the project in bytes'
field :snippets_size, GraphQL::FLOAT_TYPE, null: true,
- description: 'Snippets size of the project'
+ description: 'Snippets size of the project in bytes'
+ field :uploads_size, GraphQL::FLOAT_TYPE, null: true,
+ description: 'Uploads size of the project in bytes'
end
end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index c7fc193abe8..5a436886117 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -161,7 +161,6 @@ module Types
resolver: Resolvers::ProjectMilestonesResolver
field :project_members,
- Types::MemberInterface.connection_type,
description: 'Members of the project',
resolver: Resolvers::ProjectMembersResolver
@@ -188,9 +187,9 @@ module Types
resolver: Resolvers::PackagesResolver
field :pipelines,
- Types::Ci::PipelineType.connection_type,
null: true,
description: 'Build pipelines of the project',
+ extras: [:lookahead],
resolver: Resolvers::ProjectPipelinesResolver
field :pipeline,
@@ -267,6 +266,12 @@ module Types
description: 'Counts of alerts by status for the project',
resolver: Resolvers::AlertManagement::AlertStatusCountsResolver
+ field :alert_management_integrations,
+ Types::AlertManagement::IntegrationType.connection_type,
+ null: true,
+ description: 'Integrations which can receive alerts for the project',
+ resolver: Resolvers::AlertManagement::IntegrationsResolver
+
field :releases,
Types::ReleaseType.connection_type,
null: true,
@@ -285,6 +290,12 @@ module Types
null: true,
description: 'The container expiration policy of the project'
+ field :container_repositories,
+ Types::ContainerRepositoryType.connection_type,
+ null: true,
+ description: 'Container repositories of the project',
+ resolver: Resolvers::ContainerRepositoriesResolver
+
field :label,
Types::LabelType,
null: true,
diff --git a/app/graphql/types/projects/namespace_project_sort_enum.rb b/app/graphql/types/projects/namespace_project_sort_enum.rb
index 1e13deb6508..ede29748beb 100644
--- a/app/graphql/types/projects/namespace_project_sort_enum.rb
+++ b/app/graphql/types/projects/namespace_project_sort_enum.rb
@@ -7,6 +7,7 @@ module Types
description 'Values for sorting projects'
value 'SIMILARITY', 'Most similar to the search query', value: :similarity
+ value 'STORAGE', 'Sort by storage size', value: :storage
end
end
end
diff --git a/app/graphql/types/projects/service_type_enum.rb b/app/graphql/types/projects/service_type_enum.rb
index 340fdff6b86..34e06c67be6 100644
--- a/app/graphql/types/projects/service_type_enum.rb
+++ b/app/graphql/types/projects/service_type_enum.rb
@@ -5,7 +5,7 @@ module Types
class ServiceTypeEnum < BaseEnum
graphql_name 'ServiceType'
- ::Service.services_types.each do |service_type|
+ ::Service.available_services_types(include_dev: false).each do |service_type|
value service_type.underscore.upcase, value: service_type
end
end
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index bd4b53bdaa7..d194b0979b3 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -50,10 +50,14 @@ module Types
field :milestone, ::Types::MilestoneType,
null: true,
description: 'Find a milestone' do
- argument :id, ::Types::GlobalIDType[Milestone],
- required: true,
- description: 'Find a milestone by its ID'
- end
+ argument :id, ::Types::GlobalIDType[Milestone], required: true, description: 'Find a milestone by its ID'
+ end
+
+ field :container_repository, Types::ContainerRepositoryDetailsType,
+ null: true,
+ description: 'Find a container repository' do
+ argument :id, ::Types::GlobalIDType[::ContainerRepository], required: true, description: 'The global ID of the container repository'
+ end
field :user, Types::UserType,
null: true,
@@ -84,6 +88,10 @@ module Types
null: true, description: 'Supported runner platforms',
resolver: Resolvers::Ci::RunnerPlatformsResolver
+ field :runner_setup, Types::Ci::RunnerSetupType, null: true,
+ description: 'Get runner setup instructions',
+ resolver: Resolvers::Ci::RunnerSetupResolver
+
def design_management
DesignManagementObject.new(nil)
end
@@ -101,6 +109,13 @@ module Types
id = ::Types::GlobalIDType[Milestone].coerce_isolated_input(id)
GitlabSchema.find_by_gid(id)
end
+
+ def container_repository(id:)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = ::Types::GlobalIDType[::ContainerRepository].coerce_isolated_input(id)
+ GitlabSchema.find_by_gid(id)
+ end
end
end
diff --git a/app/graphql/types/release_asset_link_input_type.rb b/app/graphql/types/release_asset_link_input_type.rb
new file mode 100644
index 00000000000..d13861fad8f
--- /dev/null
+++ b/app/graphql/types/release_asset_link_input_type.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Types
+ # rubocop: disable Graphql/AuthorizeTypes
+ class ReleaseAssetLinkInputType < BaseInputObject
+ graphql_name 'ReleaseAssetLinkInput'
+ description 'Fields that are available when modifying a release asset link'
+
+ argument :name, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Name of the asset link'
+
+ argument :url, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'URL of the asset link'
+
+ argument :direct_asset_path, GraphQL::STRING_TYPE,
+ required: false, as: :filepath,
+ description: 'Relative path for a direct asset link'
+
+ argument :link_type, Types::ReleaseAssetLinkTypeEnum,
+ required: false, default_value: 'other',
+ description: 'The type of the asset link'
+ end
+end
diff --git a/app/graphql/types/release_asset_link_type.rb b/app/graphql/types/release_asset_link_type.rb
index 0e519ece791..8fb051f5627 100644
--- a/app/graphql/types/release_asset_link_type.rb
+++ b/app/graphql/types/release_asset_link_type.rb
@@ -24,10 +24,8 @@ module Types
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
+ release = object.release.present
+ release.download_url(object.filepath)
end
end
end
diff --git a/app/graphql/types/release_asset_link_type_enum.rb b/app/graphql/types/release_asset_link_type_enum.rb
index 01862ada56d..70601b9f8da 100644
--- a/app/graphql/types/release_asset_link_type_enum.rb
+++ b/app/graphql/types/release_asset_link_type_enum.rb
@@ -3,7 +3,7 @@
module Types
class ReleaseAssetLinkTypeEnum < BaseEnum
graphql_name 'ReleaseAssetLinkType'
- description 'Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`'
+ description 'Type of the link: `other`, `runbook`, `image`, `package`'
::Releases::Link.link_types.keys.each do |link_type|
value link_type.upcase, value: link_type, description: "#{link_type.titleize} link type"
diff --git a/app/graphql/types/release_assets_input_type.rb b/app/graphql/types/release_assets_input_type.rb
new file mode 100644
index 00000000000..3fcb517e044
--- /dev/null
+++ b/app/graphql/types/release_assets_input_type.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Types
+ # rubocop: disable Graphql/AuthorizeTypes
+ class ReleaseAssetsInputType < BaseInputObject
+ graphql_name 'ReleaseAssetsInput'
+ description 'Fields that are available when modifying release assets'
+
+ argument :links, [Types::ReleaseAssetLinkInputType],
+ required: false,
+ description: 'A list of asset links to associate to the release'
+ end
+end
diff --git a/app/graphql/types/release_links_type.rb b/app/graphql/types/release_links_type.rb
index f61a16f5b67..619bb1e6c3a 100644
--- a/app/graphql/types/release_links_type.rb
+++ b/app/graphql/types/release_links_type.rb
@@ -12,12 +12,18 @@ module Types
field :self_url, GraphQL::STRING_TYPE, null: true,
description: 'HTTP URL of the release'
- field :merge_requests_url, GraphQL::STRING_TYPE, null: true,
- description: 'HTTP URL of the merge request page filtered by this release'
- field :issues_url, GraphQL::STRING_TYPE, null: true,
- description: 'HTTP URL of the issues page filtered by this release'
field :edit_url, GraphQL::STRING_TYPE, null: true,
description: "HTTP URL of the release's edit page",
authorize: :update_release
+ field :opened_merge_requests_url, GraphQL::STRING_TYPE, null: true,
+ description: 'HTTP URL of the merge request page, filtered by this release and `state=open`'
+ field :merged_merge_requests_url, GraphQL::STRING_TYPE, null: true,
+ description: 'HTTP URL of the merge request page , filtered by this release and `state=merged`'
+ field :closed_merge_requests_url, GraphQL::STRING_TYPE, null: true,
+ description: 'HTTP URL of the merge request page , filtered by this release and `state=closed`'
+ field :opened_issues_url, GraphQL::STRING_TYPE, null: true,
+ description: 'HTTP URL of the issues page, filtered by this release and `state=open`'
+ field :closed_issues_url, GraphQL::STRING_TYPE, null: true,
+ description: 'HTTP URL of the issues page, filtered by this release and `state=closed`'
end
end
diff --git a/app/graphql/types/release_sort_enum.rb b/app/graphql/types/release_sort_enum.rb
new file mode 100644
index 00000000000..2f9af1bced9
--- /dev/null
+++ b/app/graphql/types/release_sort_enum.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Types
+ # Not inheriting from Types::SortEnum since we only want
+ # to implement a subset of the sort values it defines.
+ class ReleaseSortEnum < BaseEnum
+ graphql_name 'ReleaseSort'
+ description 'Values for sorting releases'
+
+ # Borrowed from Types::SortEnum
+ # These values/descriptions should stay in-sync as much as possible.
+ value 'CREATED_DESC', 'Created at descending order', value: :created_desc
+ value 'CREATED_ASC', 'Created at ascending order', value: :created_asc
+
+ value 'RELEASED_AT_DESC', 'Released at by descending order', value: :released_at_desc
+ value 'RELEASED_AT_ASC', 'Released at by ascending order', value: :released_at_asc
+ end
+end
diff --git a/app/graphql/types/root_storage_statistics_type.rb b/app/graphql/types/root_storage_statistics_type.rb
index 224e8c7ee03..21448b33bb5 100644
--- a/app/graphql/types/root_storage_statistics_type.rb
+++ b/app/graphql/types/root_storage_statistics_type.rb
@@ -14,5 +14,6 @@ module Types
field :wiki_size, GraphQL::FLOAT_TYPE, null: false, description: 'The wiki size in bytes'
field :snippets_size, GraphQL::FLOAT_TYPE, null: false, description: 'The snippets size in bytes'
field :pipeline_artifacts_size, GraphQL::FLOAT_TYPE, null: false, description: 'The CI pipeline artifacts size in bytes'
+ field :uploads_size, GraphQL::FLOAT_TYPE, null: false, description: 'The uploads size in bytes'
end
end
diff --git a/app/graphql/types/security/report_type_enum.rb b/app/graphql/types/security/report_type_enum.rb
new file mode 100644
index 00000000000..ee67f68b27b
--- /dev/null
+++ b/app/graphql/types/security/report_type_enum.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Types
+ module Security
+ class ReportTypeEnum < BaseEnum
+ graphql_name 'SecurityReportTypeEnum'
+
+ ::Security::SecurityJobsFinder.allowed_job_types.each do |report_type|
+ value report_type.upcase,
+ value: report_type,
+ description: "#{report_type.upcase.to_s.tr('_', ' ')} scan report"
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/snippet_type.rb b/app/graphql/types/snippet_type.rb
index 495c25c1776..f587adf207f 100644
--- a/app/graphql/types/snippet_type.rb
+++ b/app/graphql/types/snippet_type.rb
@@ -13,7 +13,7 @@ module Types
expose_permissions Types::PermissionTypes::Snippet
- field :id, GraphQL::ID_TYPE,
+ field :id, Types::GlobalIDType[::Snippet],
description: 'ID of the snippet',
null: false
diff --git a/app/graphql/types/terraform/state_type.rb b/app/graphql/types/terraform/state_type.rb
index f25f3a7789b..05b6d130f19 100644
--- a/app/graphql/types/terraform/state_type.rb
+++ b/app/graphql/types/terraform/state_type.rb
@@ -7,6 +7,8 @@ module Types
authorize :read_terraform_state
+ connection_type_class(Types::CountableConnectionType)
+
field :id, GraphQL::ID_TYPE,
null: false,
description: 'ID of the Terraform state'
@@ -25,6 +27,11 @@ module Types
null: true,
description: 'Timestamp the Terraform state was locked'
+ field :latest_version, Types::Terraform::StateVersionType,
+ complexity: 3,
+ null: true,
+ description: 'The latest version of the Terraform state'
+
field :created_at, Types::TimeType,
null: false,
description: 'Timestamp the Terraform state was created'
diff --git a/app/graphql/types/terraform/state_version_type.rb b/app/graphql/types/terraform/state_version_type.rb
new file mode 100644
index 00000000000..b1fbe42ecaf
--- /dev/null
+++ b/app/graphql/types/terraform/state_version_type.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Types
+ module Terraform
+ class StateVersionType < BaseObject
+ graphql_name 'TerraformStateVersion'
+
+ authorize :read_terraform_state
+
+ field :id, GraphQL::ID_TYPE,
+ null: false,
+ description: 'ID of the Terraform state version'
+
+ field :created_by_user, Types::UserType,
+ null: true,
+ authorize: :read_user,
+ description: 'The user that created this version',
+ resolve: -> (version, _, _) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, version.created_by_user_id).find }
+
+ field :job, Types::Ci::JobType,
+ null: true,
+ authorize: :read_build,
+ description: 'The job that created this version',
+ resolve: -> (version, _, _) { Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Build, version.ci_build_id).find }
+
+ field :created_at, Types::TimeType,
+ null: false,
+ description: 'Timestamp the version was created'
+
+ field :updated_at, Types::TimeType,
+ null: false,
+ description: 'Timestamp the version was updated'
+ end
+ end
+end
diff --git a/app/graphql/types/user_status_type.rb b/app/graphql/types/user_status_type.rb
index ff277c1f8e8..9cf6c862d3d 100644
--- a/app/graphql/types/user_status_type.rb
+++ b/app/graphql/types/user_status_type.rb
@@ -11,5 +11,7 @@ module Types
description: 'User status message'
field :emoji, GraphQL::STRING_TYPE, null: true,
description: 'String representation of emoji'
+ field :availability, Types::AvailabilityEnum, null: false,
+ description: 'User availability status'
end
end
diff --git a/app/graphql/types/user_type.rb b/app/graphql/types/user_type.rb
index 8047708776d..11c5369f726 100644
--- a/app/graphql/types/user_type.rb
+++ b/app/graphql/types/user_type.rb
@@ -32,6 +32,10 @@ module Types
field :group_memberships, Types::GroupMemberType.connection_type, null: true,
description: 'Group memberships of the user',
method: :group_members
+ field :group_count, GraphQL::INT_TYPE, null: true,
+ resolver: Resolvers::Users::GroupCountResolver,
+ description: 'Group count for the user',
+ feature_flag: :user_group_counts
field :status, Types::UserStatusType, null: true,
description: 'User status'
field :project_memberships, Types::ProjectMemberType.connection_type, null: true,
@@ -42,10 +46,10 @@ module Types
resolver: Resolvers::UserStarredProjectsResolver
# Merge request field: MRs can be either authored or assigned:
- field :authored_merge_requests, Types::MergeRequestType.connection_type, null: true,
+ field :authored_merge_requests,
resolver: Resolvers::AuthoredMergeRequestsResolver,
description: 'Merge Requests authored by the user'
- field :assigned_merge_requests, Types::MergeRequestType.connection_type, null: true,
+ field :assigned_merge_requests,
resolver: Resolvers::AssignedMergeRequestsResolver,
description: 'Merge Requests assigned to the user'
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 9c408efe8cd..512649b3008 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -199,14 +199,14 @@ module ApplicationSettingsHelper
:default_projects_limit,
:default_snippet_visibility,
:disabled_oauth_sign_in_sources,
- :domain_blacklist,
- :domain_blacklist_enabled,
- # TODO Remove domain_blacklist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204)
- :domain_blacklist_raw,
- :domain_whitelist,
- # TODO Remove domain_whitelist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204)
- :domain_whitelist_raw,
- :outbound_local_requests_whitelist_raw,
+ :domain_denylist,
+ :domain_denylist_enabled,
+ # TODO Remove domain_denylist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204)
+ :domain_denylist_raw,
+ :domain_allowlist,
+ # TODO Remove domain_allowlist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204)
+ :domain_allowlist_raw,
+ :outbound_local_requests_allowlist_raw,
:dsa_key_restriction,
:ecdsa_key_restriction,
:ed25519_key_restriction,
@@ -394,6 +394,10 @@ module ApplicationSettingsHelper
def show_documentation_base_url_field?
Feature.enabled?(:help_page_documentation_redirect)
end
+
+ def signup_enabled?
+ !!Gitlab::CurrentSettings.signup_enabled
+ end
end
ApplicationSettingsHelper.prepend_if_ee('EE::ApplicationSettingsHelper')
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index 7f8cb66a84f..cc43ea85a11 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -151,6 +151,13 @@ module AuthHelper
current_user.allow_password_authentication_for_web? && !current_user.password_automatically_set?
end
+ def google_tag_manager_enabled?
+ Gitlab.com? &&
+ extra_config.has_key?('google_tag_manager_id') &&
+ extra_config.google_tag_manager_id.present? &&
+ !current_user
+ end
+
extend self
end
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 806fea3ab44..981b5e4d92b 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -26,6 +26,25 @@ module BlobHelper
File.join(segments)
end
+ def ide_merge_request_path(merge_request, path = '')
+ target_project = merge_request.target_project
+ source_project = merge_request.source_project
+
+ if merge_request.merged?
+ branch = merge_request.target_branch_exists? ? merge_request.target_branch : target_project.default_branch
+
+ return ide_edit_path(target_project, branch, path)
+ end
+
+ if target_project != source_project
+ params = { target_project: target_project.full_path }
+ end
+
+ result = File.join(ide_path, 'project', source_project.full_path, 'merge_requests', merge_request.to_param)
+ result += "?#{params.to_query}" unless params.nil?
+ result
+ end
+
def ide_fork_and_edit_path(project = @project, ref = @ref, path = @path, options = {})
fork_path_for_current_user(project, ide_edit_path(project, ref, path))
end
@@ -49,7 +68,7 @@ module BlobHelper
def edit_blob_button(project = @project, ref = @ref, path = @path, options = {})
return unless blob = readable_blob(options, path, project, ref)
- common_classes = "btn btn-primary js-edit-blob ml-2 #{options[:extra_class]}"
+ common_classes = "btn btn-primary js-edit-blob gl-mr-3 #{options[:extra_class]}"
data = { track_event: 'click_edit', track_label: 'Edit' }
if Feature.enabled?(:web_ide_primary_edit, project.group)
@@ -69,7 +88,7 @@ module BlobHelper
def ide_edit_button(project = @project, ref = @ref, path = @path, blob:)
return unless blob
- common_classes = 'btn btn-primary ide-edit-button ml-2'
+ common_classes = 'btn btn-primary ide-edit-button gl-mr-3'
data = { track_event: 'click_edit_ide', track_label: 'Web IDE' }
unless Feature.enabled?(:web_ide_primary_edit, project.group)
@@ -363,7 +382,7 @@ module BlobHelper
end
def show_suggest_pipeline_creation_celebration?
- experiment_enabled?(:suggest_pipeline) &&
+ Feature.enabled?(:suggest_pipeline, default_enabled: true) &&
@blob.path == Gitlab::FileDetector::PATTERNS[:gitlab_ci] &&
@blob.auxiliary_viewer&.valid?(project: @project, sha: @commit.sha, user: current_user) &&
@project.uses_default_ci_config? &&
diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb
index 2a0242fe2fa..8f87cd5bfe0 100644
--- a/app/helpers/branches_helper.rb
+++ b/app/helpers/branches_helper.rb
@@ -13,7 +13,11 @@ module BranchesHelper
return [] unless access_levels
access_levels.map do |level|
- { id: level.id, type: :role, access_level: level.access_level }
+ if level.type == :deploy_key
+ { id: level.id, type: level.type, deploy_key_id: level.deploy_key_id }
+ else
+ { id: level.id, type: :role, access_level: level.access_level }
+ end
end
end
end
diff --git a/app/helpers/breadcrumbs_helper.rb b/app/helpers/breadcrumbs_helper.rb
index b067376cea0..ade7c48b03f 100644
--- a/app/helpers/breadcrumbs_helper.rb
+++ b/app/helpers/breadcrumbs_helper.rb
@@ -32,4 +32,53 @@ module BreadcrumbsHelper
@breadcrumb_dropdown_links[location] ||= []
@breadcrumb_dropdown_links[location] << link
end
+
+ def push_to_schema_breadcrumb(text, link)
+ list_item = schema_list_item(text, link, schema_breadcrumb_list.size + 1)
+
+ schema_breadcrumb_list.push(list_item)
+ end
+
+ def schema_breadcrumb_json
+ {
+ '@context': 'https://schema.org',
+ '@type': 'BreadcrumbList',
+ 'itemListElement': build_item_list_elements
+ }.to_json
+ end
+
+ private
+
+ def schema_breadcrumb_list
+ @schema_breadcrumb_list ||= []
+ end
+
+ def build_item_list_elements
+ return @schema_breadcrumb_list unless @breadcrumbs_extra_links&.any?
+
+ last_element = schema_breadcrumb_list.pop
+
+ @breadcrumbs_extra_links.each do |el|
+ push_to_schema_breadcrumb(el[:text], el[:link])
+ end
+
+ last_element['position'] = schema_breadcrumb_list.last['position'] + 1
+ schema_breadcrumb_list.push(last_element)
+ end
+
+ def schema_list_item(text, link, position)
+ {
+ '@type' => 'ListItem',
+ 'position' => position,
+ 'name' => text,
+ 'item' => ensure_absolute_link(link)
+ }
+ end
+
+ def ensure_absolute_link(link)
+ url = URI.parse(link)
+ url.absolute? ? link : URI.join(request.base_url, link).to_s
+ rescue URI::InvalidURIError
+ "#{request.base_url}#{request.path}"
+ end
end
diff --git a/app/helpers/ci/jobs_helper.rb b/app/helpers/ci/jobs_helper.rb
index e876eb64029..d47f6195c61 100644
--- a/app/helpers/ci/jobs_helper.rb
+++ b/app/helpers/ci/jobs_helper.rb
@@ -15,7 +15,8 @@ module Ci
"build_status" => @build.status,
"build_stage" => @build.stage,
"log_state" => '',
- "build_options" => javascript_build_options
+ "build_options" => javascript_build_options,
+ "retry_outdated_job_docs_url" => help_page_path('ci/pipelines/settings', anchor: 'retry-outdated-jobs')
}
end
end
diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb
new file mode 100644
index 00000000000..3f48b2687b9
--- /dev/null
+++ b/app/helpers/ci/pipeline_editor_helper.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineEditorHelper
+ include ChecksCollaboration
+
+ def can_view_pipeline_editor?(project)
+ can_collaborate_with_project?(project) &&
+ Gitlab::Ci::Features.ci_pipeline_editor_page_enabled?(project)
+ end
+ end
+end
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
index 552acf61f47..432aad663e4 100644
--- a/app/helpers/ci/runners_helper.rb
+++ b/app/helpers/ci/runners_helper.rb
@@ -2,13 +2,15 @@
module Ci
module RunnersHelper
+ include IconsHelper
+
def runner_status_icon(runner)
status = runner.status
case status
when :not_connected
- content_tag :i, nil,
- class: "fa fa-warning",
- title: "New runner. Has not connected yet"
+ content_tag(:span, title: "New runner. Has not connected yet") do
+ sprite_icon("warning-solid", size: 24, css_class: "gl-vertical-align-bottom!")
+ end
when :online, :offline, :paused
content_tag :i, nil,
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index f8490d79427..02d48386e31 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -196,7 +196,7 @@ module CommitsHelper
return unless external_url
link_to(external_url, class: 'btn btn-file-option has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: "View on #{environment.formatted_external_url}", data: { container: 'body' }) do
- icon('external-link')
+ sprite_icon('external-link')
end
end
diff --git a/app/helpers/defer_script_tag_helper.rb b/app/helpers/defer_script_tag_helper.rb
index d91c6d52683..be927c67aaa 100644
--- a/app/helpers/defer_script_tag_helper.rb
+++ b/app/helpers/defer_script_tag_helper.rb
@@ -1,7 +1,9 @@
# frozen_string_literal: true
module DeferScriptTagHelper
- # Override the default ActionView `javascript_include_tag` helper to support page specific deferred loading
+ # Override the default ActionView `javascript_include_tag` helper to support page specific deferred loading.
+ # PLEASE NOTE: `defer` is also critical so that we don't run JavaScript entrypoints before the DOM is ready.
+ # Please see https://gitlab.com/groups/gitlab-org/-/epics/4538#note_432159769.
def javascript_include_tag(*sources)
super(*sources, defer: true)
end
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index 7c254e069f6..d6d06434590 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -64,15 +64,17 @@ module DiffHelper
else
# `sub` and substring-ing would destroy HTML-safeness of `line`
if line.start_with?('+', '-', ' ')
- line.dup.tap do |line|
- line[0] = ''
- end
+ line[1, line.length]
else
line
end
end
end
+ def diff_link_number(line_type, match, text)
+ line_type == match ? " " : text
+ end
+
def parallel_diff_discussions(left, right, diff_file)
return unless @grouped_diff_discussions
@@ -201,6 +203,14 @@ module DiffHelper
set_secure_cookie(:diff_view, params.delete(:view), type: CookiesHelper::COOKIE_TYPE_PERMANENT) if params[:view].present?
end
+ def unified_diff_lines_view_type(project)
+ if Feature.enabled?(:unified_diff_lines, project, default_enabled: true)
+ 'inline'
+ else
+ diff_view
+ end
+ end
+
private
def diff_btn(title, name, selected)
@@ -250,4 +260,18 @@ module DiffHelper
"...#{path[-(max - 3)..-1]}"
end
+
+ def code_navigation_path(diffs)
+ Gitlab::CodeNavigationPath.new(merge_request.project, diffs.diff_refs&.head_sha)
+ end
+
+ def conflicts
+ return unless options[:merge_ref_head_diff]
+
+ conflicts_service = MergeRequests::Conflicts::ListService.new(merge_request) # rubocop:disable CodeReuse/ServiceClass
+
+ return unless conflicts_service.can_be_resolved_in_ui?
+
+ conflicts_service.conflicts.files.index_by(&:our_path)
+ end
end
diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index e1378e485e4..e10e9a83b05 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -129,8 +129,7 @@ module DropdownsHelper
end
def dropdown_loading
- content_tag :div, class: "dropdown-loading" do
- icon('spinner spin')
- end
+ spinner = loading_icon(container: true, size: "md", css_class: "gl-mt-7")
+ content_tag(:div, spinner, class: "dropdown-loading")
end
end
diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb
index 0a0dc77e5e2..017981c8c8e 100644
--- a/app/helpers/emails_helper.rb
+++ b/app/helpers/emails_helper.rb
@@ -214,6 +214,24 @@ module EmailsHelper
end
end
+ def instance_access_request_text(user, format: nil)
+ gitlab_host = Gitlab.config.gitlab.host
+
+ _('%{username} has asked for a GitLab account on your instance %{host}:') % { username: sanitize_name(user.name), host: gitlab_host }
+ end
+
+ def instance_access_request_link(user, format: nil)
+ url = admin_user_url(user)
+
+ case format
+ when :html
+ user_page = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: url }
+ _("Click %{link_start}here%{link_end} to view the request.").html_safe % { link_start: user_page, link_end: '</a>'.html_safe }
+ else
+ _('Click %{link_to} to view the request.') % { link_to: url }
+ end
+ end
+
def contact_your_administrator_text
_('Please contact your administrator with any questions.')
end
diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb
index 7df6bef7914..7ae00a70671 100644
--- a/app/helpers/gitlab_routing_helper.rb
+++ b/app/helpers/gitlab_routing_helper.rb
@@ -70,6 +70,10 @@ module GitlabRoutingHelper
project_commit_url(entity.project, entity.sha, *args)
end
+ def release_url(entity, *args)
+ project_release_url(entity.project, entity, *args)
+ end
+
def preview_markdown_path(parent, *args)
return group_preview_markdown_path(parent, *args) if parent.is_a?(Group)
@@ -343,18 +347,6 @@ module GitlabRoutingHelper
Gitlab::UrlBuilder.wiki_page_url(wiki, page, only_path: true, **options)
end
- def gitlab_ide_merge_request_path(merge_request)
- target_project = merge_request.target_project
- source_project = merge_request.source_project
- params = {}
-
- if target_project != source_project
- params = { target_project: target_project.full_path }
- end
-
- ide_merge_request_path(source_project.namespace, source_project, merge_request, params)
- end
-
private
def snippet_query_params(snippet, *args)
diff --git a/app/helpers/gitpod_helper.rb b/app/helpers/gitpod_helper.rb
index 7edf7dc218d..875a44c51bb 100644
--- a/app/helpers/gitpod_helper.rb
+++ b/app/helpers/gitpod_helper.rb
@@ -2,9 +2,6 @@
module GitpodHelper
def gitpod_enable_description
- link_start = '<a href="https://gitpod.io/" target="_blank" rel="noopener noreferrer">'.html_safe
- link_end = "#{sprite_icon('external-link', size: 12, css_class: 'ml-1 vertical-align-center')}</a>".html_safe
-
- s_('Enable %{link_start}Gitpod%{link_end} integration to launch a development environment in your browser directly from GitLab.').html_safe % { link_start: link_start, link_end: link_end }
+ s_('Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab.')
end
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 06a52457fd6..29ead76a607 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -94,12 +94,19 @@ module GroupsHelper
else
full_title << breadcrumb_list_item(group_title_link(parent, hidable: false))
end
+
+ push_to_schema_breadcrumb(simple_sanitize(parent.name), group_path(parent))
end
full_title << render("layouts/nav/breadcrumbs/collapsed_dropdown", location: :before, title: _("Show parent subgroups"))
full_title << breadcrumb_list_item(group_title_link(group))
- full_title << ' &middot; '.html_safe + link_to(simple_sanitize(name), url, class: 'group-path breadcrumb-item-text js-breadcrumb-item-text') if name
+ push_to_schema_breadcrumb(simple_sanitize(group.name), group_path(group))
+
+ if name
+ full_title << ' &middot; '.html_safe + link_to(simple_sanitize(name), url, class: 'group-path breadcrumb-item-text js-breadcrumb-item-text')
+ push_to_schema_breadcrumb(simple_sanitize(name), url)
+ end
full_title.join.html_safe
end
@@ -163,6 +170,10 @@ module GroupsHelper
group_container_registry_nav?
end
+ def group_dependency_proxy_nav?
+ @group.dependency_proxy_feature_available?
+ end
+
def group_packages_list_nav?
@group.packages_feature_enabled?
end
@@ -174,6 +185,10 @@ module GroupsHelper
!multiple_members?(group)
end
+ def show_thanks_for_purchase_banner?
+ params.key?(:purchased_quantity) && params[:purchased_quantity].to_i > 0
+ end
+
private
def just_created?
diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb
index 1d0001fde72..dc6164ee898 100644
--- a/app/helpers/icons_helper.rb
+++ b/app/helpers/icons_helper.rb
@@ -24,9 +24,11 @@ module IconsHelper
end
def custom_icon(icon_name, size: DEFAULT_ICON_SIZE)
- # We can't simply do the below, because there are some .erb SVGs.
- # File.read(Rails.root.join("app/views/shared/icons/_#{icon_name}.svg")).html_safe
- render "shared/icons/#{icon_name}.svg", size: size
+ memoized_icon("#{icon_name}_#{size}") do
+ # We can't simply do the below, because there are some .erb SVGs.
+ # File.read(Rails.root.join("app/views/shared/icons/_#{icon_name}.svg")).html_safe
+ render "shared/icons/#{icon_name}.svg", size: size
+ end
end
def sprite_icon_path
@@ -46,21 +48,23 @@ module IconsHelper
end
def sprite_icon(icon_name, size: DEFAULT_ICON_SIZE, css_class: nil)
- if known_sprites&.exclude?(icon_name)
- exception = ArgumentError.new("#{icon_name} is not a known icon in @gitlab-org/gitlab-svg")
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(exception)
- end
+ memoized_icon("#{icon_name}_#{size}_#{css_class}") do
+ if known_sprites&.exclude?(icon_name)
+ exception = ArgumentError.new("#{icon_name} is not a known icon in @gitlab-org/gitlab-svg")
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(exception)
+ end
- css_classes = []
- css_classes << "s#{size}" if size
- css_classes << "#{css_class}" unless css_class.blank?
+ css_classes = []
+ css_classes << "s#{size}" if size
+ css_classes << "#{css_class}" unless css_class.blank?
- content_tag(
- :svg,
- content_tag(:use, '', { 'xlink:href' => "#{sprite_icon_path}##{icon_name}" } ),
- class: css_classes.empty? ? nil : css_classes.join(' '),
- data: { testid: "#{icon_name}-icon" }
- )
+ content_tag(
+ :svg,
+ content_tag(:use, '', { 'xlink:href' => "#{sprite_icon_path}##{icon_name}" } ),
+ class: css_classes.empty? ? nil : css_classes.join(' '),
+ data: { testid: "#{icon_name}-icon" }
+ )
+ end
end
def loading_icon(container: false, color: 'orange', size: 'sm', css_class: nil)
@@ -76,26 +80,17 @@ module IconsHelper
content_tag(:span, "", class: "gl-snippet-icon gl-snippet-icon-#{name}")
end
- def audit_icon(names, options = {})
- case names
+ def audit_icon(name, css_class: nil)
+ case name
when "standard"
- names = "key"
+ name = "key"
when "two-factor"
- names = "key"
+ name = "key"
when "google_oauth2"
- names = "google"
+ name = "google"
end
- options.include?(:base) ? fa_stacked_icon(names, options) : fa_icon(names, options)
- end
-
- def spinner(text = nil, visible = false)
- css_class = ['loading']
- css_class << 'hide' unless visible
-
- content_tag :div, class: css_class.join(' ') do
- icon('spinner spin') + text
- end
+ sprite_icon(name, css_class: css_class)
end
def boolean_to_icon(value)
@@ -178,4 +173,12 @@ module IconsHelper
@known_sprites ||= Gitlab::Json.parse(File.read(Rails.root.join('node_modules/@gitlab/svgs/dist/icons.json')))['icons']
end
+
+ def memoized_icon(key)
+ @rendered_icons ||= {}
+
+ @rendered_icons[key] || (
+ @rendered_icons[key] = yield
+ )
+ end
end
diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb
index ac6ac9979b3..cea28fd4611 100644
--- a/app/helpers/invite_members_helper.rb
+++ b/app/helpers/invite_members_helper.rb
@@ -18,4 +18,8 @@ module InviteMembersHelper
experiment_enabled?(:invite_members_version_b) && !can_import_members?
end
end
+
+ def invite_group_members?(group)
+ experiment_enabled?(:invite_members_empty_group_version_a) && Ability.allowed?(current_user, :admin_group_member, group)
+ end
end
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index f8e7711959a..77ced17bc22 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -76,7 +76,6 @@ module IssuablesHelper
when Issue
IssueSerializer
when MergeRequest
- opts[:experiment_enabled] = :suggest_pipeline if experiment_enabled?(:suggest_pipeline) && opts[:serializer] == 'widget'
MergeRequestSerializer
end
@@ -211,7 +210,7 @@ module IssuablesHelper
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")
+ output << content_tag(:span, (issuable.task_status if issuable.tasks?), id: "task_status", class: "d-none d-md-inline-block gl-ml-3")
output << content_tag(:span, (issuable.task_status_short if issuable.tasks?), id: "task_status_short", class: "d-md-none")
output.join.html_safe
@@ -275,7 +274,6 @@ module IssuablesHelper
canUpdate: can?(current_user, :"update_#{issuable.to_ability_name}", issuable),
canDestroy: can?(current_user, :"destroy_#{issuable.to_ability_name}", issuable),
issuableRef: issuable.to_reference,
- issuableStatus: issuable.state,
markdownPreviewPath: preview_markdown_path(parent),
markdownDocsPath: help_page_path('user/markdown'),
lockVersion: issuable.lock_version,
@@ -379,7 +377,12 @@ module IssuablesHelper
end
def issuable_display_type(issuable)
- issuable.model_name.human.downcase
+ case issuable
+ when Issue
+ issuable.issue_type.downcase
+ when MergeRequest
+ issuable.model_name.human.downcase
+ end
end
def has_filter_bar_param?
@@ -489,6 +492,21 @@ module IssuablesHelper
}
end
+ def sidebar_labels_data(issuable_sidebar, project)
+ {
+ 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: issuable_sidebar.dig(:current_user, :can_edit).to_s,
+ iid: issuable_sidebar[:iid],
+ issuable_type: issuable_sidebar[:type],
+ labels_fetch_path: issuable_sidebar[:project_labels_path],
+ labels_manage_path: project_labels_path(project),
+ project_issues_path: issuable_sidebar[:project_issuables_path],
+ project_path: project.full_path,
+ selected_labels: issuable_sidebar[:labels].to_json
+ }
+ end
+
def parent
@project || @group
end
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index dbf284e70e4..dee009cd3ab 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -152,6 +152,29 @@ module IssuesHelper
sort: 'desc'
}
end
+
+ def issue_header_actions_data(project, issuable, current_user)
+ new_issuable_params = ({ issuable_template: 'incident', issue: { issue_type: 'incident' } } if issuable.incident?)
+
+ {
+ can_create_issue: show_new_issue_link?(project).to_s,
+ can_reopen_issue: can?(current_user, :reopen_issue, issuable).to_s,
+ can_report_spam: issuable.submittable_as_spam_by?(current_user).to_s,
+ can_update_issue: can?(current_user, :update_issue, issuable).to_s,
+ iid: issuable.iid,
+ is_issue_author: (issuable.author == current_user).to_s,
+ issue_type: issuable_display_type(issuable),
+ new_issue_path: new_project_issue_path(project, new_issuable_params),
+ project_path: project.full_path,
+ report_abuse_path: new_abuse_report_path(user_id: issuable.author.id, ref_url: issue_url(issuable)),
+ submit_as_spam_path: mark_as_spam_project_issue_path(project, issuable)
+ }
+ end
+
+ # Overridden in EE
+ def scoped_labels_available?(parent)
+ false
+ end
end
IssuesHelper.prepend_if_ee('EE::IssuesHelper')
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index c02adfcf4c6..871d19c6a8c 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -159,6 +159,7 @@ module NotesHelper
members: autocomplete,
issues: autocomplete,
mergeRequests: autocomplete,
+ vulnerabilities: autocomplete,
epics: autocomplete,
milestones: autocomplete,
labels: autocomplete
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index 542a9ad2a70..61fcda6a504 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -67,6 +67,7 @@ module NotificationsHelper
when :custom
_('You will only receive notifications for the events you choose')
when :owner_disabled
+ # Any change must be reflected in board_sidebar_subscription.vue
_('Notifications have been disabled by the project or group owner')
end
end
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
index 9965a705a01..8105fce10cf 100644
--- a/app/helpers/operations_helper.rb
+++ b/app/helpers/operations_helper.rb
@@ -29,7 +29,9 @@ module OperationsHelper
'url' => alerts_service.url,
'alerts_setup_url' => help_page_path('operations/incident_management/alert_integrations.md', anchor: 'generic-http-endpoint'),
'alerts_usage_url' => project_alert_management_index_path(@project),
- 'disabled' => disabled.to_s
+ 'disabled' => disabled.to_s,
+ 'project_path' => @project.full_path,
+ 'multi_integrations' => 'false'
}
end
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index 6808ffc3e27..e3d82e7a091 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
module PageLayoutHelper
+ include Gitlab::Utils::StrongMemoize
+
def page_title(*titles)
@page_title ||= []
@@ -44,7 +46,7 @@ module PageLayoutHelper
if link
@page_canonical_link = link
else
- @page_canonical_link
+ @page_canonical_link ||= generic_canonical_url
end
end
@@ -57,7 +59,7 @@ module PageLayoutHelper
subject = @project || @user || @group
- image = subject.avatar_url if subject.present?
+ image = subject.avatar_url(only_path: false) if subject.present?
image || default
end
@@ -147,4 +149,49 @@ module PageLayoutHelper
css_class.join(' ')
end
+
+ def page_itemtype(itemtype = nil)
+ if itemtype
+ @page_itemtype = { itemscope: true, itemtype: itemtype }
+ else
+ @page_itemtype || {}
+ end
+ end
+
+ def user_status_properties(user)
+ default_properties = { current_emoji: '', current_message: '', can_set_user_availability: Feature.enabled?(:set_user_availability_status, user), default_emoji: UserStatus::DEFAULT_EMOJI }
+ return default_properties unless user&.status
+
+ default_properties.merge({
+ current_emoji: user.status.emoji.to_s,
+ current_message: user.status.message.to_s,
+ current_availability: user.status.availability.to_s
+ })
+ end
+
+ private
+
+ def generic_canonical_url
+ strong_memoize(:generic_canonical_url) do
+ next unless request.get? || request.head?
+ next unless generate_generic_canonical_url?
+
+ # Request#url builds the url without the trailing slash
+ request.url
+ end
+ end
+
+ def generate_generic_canonical_url?
+ # For the main domain it doesn't matter whether there is
+ # a trailing slash or not, they're not considered different
+ # pages
+ return false if request.path == '/'
+
+ # We only need to generate the canonical url when the request has a trailing
+ # slash. In the request object, only the `original_fullpath` and
+ # `original_url` keep the slash if it's present. Both `path` and
+ # `fullpath` would return the path without the slash.
+ # Therefore, we need to process `original_fullpath`
+ request.original_fullpath.sub(request.path, '')[0] == '/'
+ end
end
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index 9bf819febb0..5310aef5bad 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -82,8 +82,8 @@ module PreferencesHelper
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
+ views << { name: 'gitpod', message: gitpod_enable_description, message_url: 'https://gitpod.io/', help_link: help_page_path('integration/gitpod.md') } if Gitlab::Gitpod.feature_and_settings_enabled?
+ views << { name: 'sourcegraph', message: sourcegraph_url_message, message_url: Gitlab::CurrentSettings.sourcegraph_url, help_link: help_page_path('user/profile/preferences.md', anchor: 'sourcegraph') } if Gitlab::Sourcegraph.feature_available? && Gitlab::CurrentSettings.sourcegraph_enabled
end
end
diff --git a/app/helpers/profiles_helper.rb b/app/helpers/profiles_helper.rb
index 5a42e581867..04a3b915493 100644
--- a/app/helpers/profiles_helper.rb
+++ b/app/helpers/profiles_helper.rb
@@ -29,4 +29,18 @@ module ProfilesHelper
def user_profile?
params[:controller] == 'users'
end
+
+ def availability_values
+ Types::AvailabilityEnum.enum
+ end
+
+ def user_status_set_to_busy?(status)
+ status&.availability == availability_values[:busy]
+ end
+
+ def show_status_emoji?(status)
+ return false unless status
+
+ status.message.present? || status.emoji != UserStatus::DEFAULT_EMOJI
+ end
end
diff --git a/app/helpers/projects/terraform_helper.rb b/app/helpers/projects/terraform_helper.rb
new file mode 100644
index 00000000000..b286bc4d7a5
--- /dev/null
+++ b/app/helpers/projects/terraform_helper.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Projects::TerraformHelper
+ def js_terraform_list_data(project)
+ {
+ empty_state_image: image_path('illustrations/empty-state/empty-serverless-lg.svg'),
+ project_path: project.full_path
+ }
+ end
+end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index ae46135e890..f25b229d198 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -84,18 +84,8 @@ module ProjectsHelper
end
def project_title(project)
- namespace_link =
- if project.group
- group_title(project.group, nil, nil)
- else
- owner = project.namespace.owner
- link_to(simple_sanitize(owner.name), user_path(owner))
- end
-
- project_link = link_to project_path(project) do
- icon = project_icon(project, alt: project.name, class: 'avatar-tile', width: 15, height: 15) if project.avatar_url && !Rails.env.test?
- [icon, content_tag("span", simple_sanitize(project.name), class: "breadcrumb-item-text js-breadcrumb-item-text")].join.html_safe
- end
+ namespace_link = build_namespace_breadcrumb_link(project)
+ project_link = build_project_breadcrumb_link(project)
namespace_link = breadcrumb_list_item(namespace_link) unless project.group
project_link = breadcrumb_list_item project_link
@@ -302,7 +292,7 @@ module ProjectsHelper
end
def settings_operations_available?
- can?(current_user, :read_environment, @project)
+ !@project.archived? && can?(current_user, :admin_operations, @project)
end
def error_tracking_setting_project_json
@@ -465,6 +455,7 @@ module ProjectsHelper
builds: :read_build,
clusters: :read_cluster,
serverless: :read_cluster,
+ terraform: :read_terraform_state,
error_tracking: :read_sentry_issue,
alert_management: :read_alert_management_alert,
incidents: :read_issue,
@@ -484,7 +475,8 @@ module ProjectsHelper
:read_issue,
:read_sentry_issue,
:read_cluster,
- :read_feature_flag
+ :read_feature_flag,
+ :read_terraform_state
].any? do |ability|
can?(current_user, ability, project)
end
@@ -762,6 +754,7 @@ module ProjectsHelper
metrics_dashboard
feature_flags
tracings
+ terraform
]
end
@@ -784,6 +777,30 @@ module ProjectsHelper
def project_access_token_available?(project)
can?(current_user, :admin_resource_access_tokens, project)
end
+
+ def build_project_breadcrumb_link(project)
+ project_name = simple_sanitize(project.name)
+
+ push_to_schema_breadcrumb(project_name, project_path(project))
+
+ link_to project_path(project) do
+ icon = project_icon(project, alt: project_name, class: 'avatar-tile', width: 15, height: 15) if project.avatar_url && !Rails.env.test?
+ [icon, content_tag("span", project_name, class: "breadcrumb-item-text js-breadcrumb-item-text")].join.html_safe
+ end
+ end
+
+ def build_namespace_breadcrumb_link(project)
+ if project.group
+ group_title(project.group, nil, nil)
+ else
+ owner = project.namespace.owner
+ name = simple_sanitize(owner.name)
+ url = user_path(owner)
+
+ push_to_schema_breadcrumb(name, url)
+ link_to(name, url)
+ end
+ end
end
ProjectsHelper.prepend_if_ee('EE::ProjectsHelper')
diff --git a/app/helpers/recaptcha_experiment_helper.rb b/app/helpers/recaptcha_experiment_helper.rb
deleted file mode 100644
index f15e92c0e99..00000000000
--- a/app/helpers/recaptcha_experiment_helper.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-module RecaptchaExperimentHelper
- def show_recaptcha_sign_up?
- !!Gitlab::Recaptcha.enabled?
- end
-end
-
-RecaptchaExperimentHelper.prepend_if_ee('EE::RecaptchaExperimentHelper')
diff --git a/app/helpers/recaptcha_helper.rb b/app/helpers/recaptcha_helper.rb
new file mode 100644
index 00000000000..4ebac1d5b7f
--- /dev/null
+++ b/app/helpers/recaptcha_helper.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module RecaptchaHelper
+ def show_recaptcha_sign_up?
+ !!Gitlab::Recaptcha.enabled?
+ end
+end
diff --git a/app/helpers/releases_helper.rb b/app/helpers/releases_helper.rb
index 050b27840a0..d9851564585 100644
--- a/app/helpers/releases_helper.rb
+++ b/app/helpers/releases_helper.rb
@@ -51,18 +51,25 @@ module ReleasesHelper
)
end
+ def group_milestone_project_releases_available?(project)
+ false
+ end
+
private
def new_edit_pages_shared_data
{
project_id: @project.id,
+ group_id: @project.group&.id,
+ group_milestones_available: group_milestone_project_releases_available?(@project),
project_path: @project.full_path,
markdown_preview_path: preview_markdown_path(@project),
markdown_docs_path: help_page_path('user/markdown'),
- update_release_api_docs_path: help_page_path('api/releases/index.md', anchor: 'update-a-release'),
release_assets_docs_path: help_page(anchor: 'release-assets'),
manage_milestones_path: project_milestones_path(@project),
new_milestone_path: new_project_milestone_path(@project)
}
end
end
+
+ReleasesHelper.prepend_if_ee('EE::ReleasesHelper')
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 3467f6e9a44..de1e0e4e05e 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -1,7 +1,16 @@
# frozen_string_literal: true
module SearchHelper
- SEARCH_PERMITTED_PARAMS = [:search, :scope, :project_id, :group_id, :repository_ref, :snippets, :sort, :state, :confidential].freeze
+ SEARCH_GENERIC_PARAMS = [
+ :search,
+ :scope,
+ :project_id,
+ :group_id,
+ :repository_ref,
+ :snippets,
+ :sort,
+ :force_search_results
+ ].freeze
def search_autocomplete_opts(term)
return unless current_user
@@ -9,7 +18,8 @@ module SearchHelper
resources_results = [
recent_items_autocomplete(term),
groups_autocomplete(term),
- projects_autocomplete(term)
+ projects_autocomplete(term),
+ issue_autocomplete(term)
].flatten
search_pattern = Regexp.new(Regexp.escape(term), "i")
@@ -82,11 +92,27 @@ module SearchHelper
end
end
- def search_entries_empty_message(scope, term)
- (s_("SearchResults|We couldn't find any %{scope} matching %{term}") % {
+ def search_entries_empty_message(scope, term, group, project)
+ options = {
scope: search_entries_scope_label(scope, 0),
- term: "<code>#{h(term)}</code>"
- }).html_safe
+ term: "<code>#{h(term)}</code>".html_safe
+ }
+
+ # We check project first because we have 3 possible combinations here:
+ # - group && project
+ # - group
+ # - group: nil, project: nil
+ if project
+ html_escape(_("We couldn't find any %{scope} matching %{term} in project %{project}")) % options.merge(
+ project: link_to(project.full_name, project_path(project), target: '_blank', rel: 'noopener noreferrer').html_safe
+ )
+ elsif group
+ html_escape(_("We couldn't find any %{scope} matching %{term} in group %{group}")) % options.merge(
+ group: link_to(group.full_name, group_path(group), target: '_blank', rel: 'noopener noreferrer').html_safe
+ )
+ else
+ html_escape(_("We couldn't find any %{scope} matching %{term}")) % options
+ end
end
def repository_ref(project)
@@ -140,7 +166,7 @@ module SearchHelper
if @project && @project.repository.root_ref
ref = @ref || @project.repository.root_ref
- [
+ result = [
{ category: "In this project", label: _("Files"), url: project_tree_path(@project, ref) },
{ category: "In this project", label: _("Commits"), url: project_commits_path(@project, ref) },
{ category: "In this project", label: _("Network"), url: project_network_path(@project, ref) },
@@ -152,6 +178,12 @@ module SearchHelper
{ category: "In this project", label: _("Members"), url: project_project_members_path(@project) },
{ category: "In this project", label: _("Wiki"), url: project_wikis_path(@project) }
]
+
+ if can?(current_user, :read_feature_flag, @project)
+ result << { category: "In this project", label: _("Feature Flags"), url: project_feature_flags_path(@project) }
+ end
+
+ result
else
[]
end
@@ -172,6 +204,24 @@ module SearchHelper
end
# rubocop: enable CodeReuse/ActiveRecord
+ def issue_autocomplete(term)
+ return [] unless @project.present? && current_user && term =~ /\A#{Issue.reference_prefix}\d+\z/
+
+ iid = term.sub(Issue.reference_prefix, '').to_i
+ issue = @project.issues.find_by_iid(iid)
+ return [] unless issue && Ability.allowed?(current_user, :read_issue, issue)
+
+ [
+ {
+ category: 'In this project',
+ id: issue.id,
+ label: search_result_sanitize("#{issue.title} (#{issue.to_reference})"),
+ url: issue_path(issue),
+ avatar_url: issue.project.avatar_url || ''
+ }
+ ]
+ end
+
# Autocomplete results for the current user's projects
# rubocop: disable CodeReuse/ActiveRecord
def projects_autocomplete(term, limit = 5)
@@ -225,7 +275,7 @@ module SearchHelper
search_params = params
.merge(search)
.merge({ scope: scope })
- .permit(SEARCH_PERMITTED_PARAMS)
+ .permit(SEARCH_GENERIC_PARAMS)
if @scope == scope
li_class = 'active'
@@ -317,10 +367,10 @@ module SearchHelper
end
# _search_highlight is used in EE override
- def highlight_and_truncate_issue(issue, search_term, _search_highlight)
- return unless issue.description.present?
+ def highlight_and_truncate_issuable(issuable, search_term, _search_highlight)
+ return unless issuable.description.present?
- simple_search_highlight_and_truncate(issue.description, search_term, highlighter: '<span class="gl-text-black-normal gl-font-weight-bold">\1</span>')
+ simple_search_highlight_and_truncate(issuable.description, search_term, highlighter: '<span class="gl-text-black-normal gl-font-weight-bold">\1</span>')
end
def show_user_search_tab?
@@ -330,6 +380,36 @@ module SearchHelper
can?(current_user, :read_users_list)
end
end
+
+ def issuable_state_to_badge_class(issuable)
+ # Closed is considered "danger" for MR so we need to handle separately
+ if issuable.is_a?(::MergeRequest)
+ if issuable.merged?
+ :primary
+ elsif issuable.closed?
+ :danger
+ else
+ :success
+ end
+ else
+ if issuable.closed?
+ :info
+ else
+ :success
+ end
+ end
+ end
+
+ def issuable_state_text(issuable)
+ case issuable.state
+ when 'merged'
+ _("Merged")
+ when 'closed'
+ _("Closed")
+ else
+ _("Open")
+ end
+ end
end
SearchHelper.prepend_if_ee('EE::SearchHelper')
diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb
index 114bbf59ae1..96eb14be4b4 100644
--- a/app/helpers/services_helper.rb
+++ b/app/helpers/services_helper.rb
@@ -35,13 +35,6 @@ module ServicesHelper
"#{event}_events"
end
- def service_save_button(disabled: false)
- button_tag(class: 'btn btn-success', type: 'submit', disabled: disabled, data: { qa_selector: 'save_changes_button' }) do
- icon('spinner spin', class: 'hidden js-btn-spinner') +
- content_tag(:span, 'Save changes', class: 'js-btn-label')
- end
- end
-
def scoped_integrations_path
if @project.present?
project_settings_integrations_path(@project)
@@ -100,7 +93,8 @@ module ServicesHelper
editable: integration.editable?.to_s,
cancel_path: scoped_integrations_path,
can_test: integration.can_test?.to_s,
- test_path: scoped_test_integration_path(integration)
+ test_path: scoped_test_integration_path(integration),
+ reset_path: ''
}
end
@@ -121,7 +115,7 @@ module ServicesHelper
end
def group_level_integrations?
- @group.present? && Feature.enabled?(:group_level_integrations, @group)
+ @group.present? && Feature.enabled?(:group_level_integrations, @group, default_enabled: true)
end
def instance_level_integrations?
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index de6990041a6..10174e5d719 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -28,7 +28,8 @@ module SortingHelper
sort_value_contacted_date => sort_title_contacted_date,
sort_value_relative_position => sort_title_relative_position,
sort_value_size => sort_title_size,
- sort_value_expire_date => sort_title_expire_date
+ sort_value_expire_date => sort_title_expire_date,
+ sort_value_relevant => sort_title_relevant
}
end
@@ -81,6 +82,13 @@ module SortingHelper
}
end
+ def search_reverse_sort_options_hash
+ {
+ sort_value_recently_created => sort_value_oldest_created,
+ sort_value_oldest_created => sort_value_recently_created
+ }
+ end
+
def groups_sort_options_hash
{
sort_value_name => sort_title_name,
@@ -218,6 +226,10 @@ module SortingHelper
sort_options_hash[sort_value]
end
+ def search_sort_option_title(sort_value)
+ sort_options_hash[sort_value]
+ end
+
def sort_direction_icon(sort_value)
case sort_value
when sort_value_milestone, sort_value_due_date, /_asc\z/
@@ -256,6 +268,13 @@ module SortingHelper
sort_direction_button(url, reverse_sort, sort_value)
end
+ def search_sort_direction_button(sort_value)
+ reverse_sort = search_reverse_sort_options_hash[sort_value]
+ url = page_filter_path(sort: reverse_sort)
+
+ sort_direction_button(url, reverse_sort, sort_value)
+ end
+
# Titles.
def sort_title_access_level_asc
s_('SortOptions|Access level, ascending')
@@ -421,6 +440,10 @@ module SortingHelper
s_('SortOptions|Expired date')
end
+ def sort_title_relevant
+ s_('SortOptions|Relevant')
+ end
+
# Values.
def sort_value_access_level_asc
'access_level_asc'
@@ -582,6 +605,10 @@ module SortingHelper
'expired_asc'
end
+ def sort_value_relevant
+ 'relevant'
+ end
+
def packages_sort_options_hash
{
sort_value_recently_created => sort_title_created_date,
diff --git a/app/helpers/sourcegraph_helper.rb b/app/helpers/sourcegraph_helper.rb
index cc5a5c77e9a..25d7b209b45 100644
--- a/app/helpers/sourcegraph_helper.rb
+++ b/app/helpers/sourcegraph_helper.rb
@@ -2,26 +2,22 @@
module SourcegraphHelper
def sourcegraph_url_message
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: Gitlab::CurrentSettings.sourcegraph_url }
- link_end = "#{sprite_icon('external-link', size: 12, css_class: 'ml-1 vertical-align-center')}</a>".html_safe
-
message =
if Gitlab::CurrentSettings.sourcegraph_url_is_com?
- s_('SourcegraphPreferences|Uses %{link_start}Sourcegraph.com%{link_end}.').html_safe
+ s_('SourcegraphPreferences|Uses %{linkStart}Sourcegraph.com%{linkEnd}.').html_safe
else
- s_('SourcegraphPreferences|Uses a custom %{link_start}Sourcegraph instance%{link_end}.').html_safe
+ s_('SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{linkEnd}.').html_safe
end
- message % { link_start: link_start, link_end: link_end }
- end
+ experimental_message =
+ if Gitlab::Sourcegraph.feature_conditional?
+ s_("SourcegraphPreferences|This feature is experimental and currently limited to certain projects.")
+ elsif Gitlab::CurrentSettings.sourcegraph_public_only
+ s_("SourcegraphPreferences|This feature is experimental and limited to public projects.")
+ else
+ s_("SourcegraphPreferences|This feature is experimental.")
+ end
- def sourcegraph_experimental_message
- if Gitlab::Sourcegraph.feature_conditional?
- s_("SourcegraphPreferences|This feature is experimental and currently limited to certain projects.")
- elsif Gitlab::CurrentSettings.sourcegraph_public_only
- s_("SourcegraphPreferences|This feature is experimental and limited to public projects.")
- else
- s_("SourcegraphPreferences|This feature is experimental.")
- end
+ "#{message} #{experimental_message}"
end
end
diff --git a/app/helpers/stat_anchors_helper.rb b/app/helpers/stat_anchors_helper.rb
new file mode 100644
index 00000000000..76e58b45912
--- /dev/null
+++ b/app/helpers/stat_anchors_helper.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module StatAnchorsHelper
+ def stat_anchor_attrs(anchor)
+ {}.tap do |attrs|
+ attrs[:class] = %w(nav-link gl-display-flex gl-align-items-center) << extra_classes(anchor)
+ attrs[:itemprop] = anchor.itemprop if anchor.itemprop
+ end
+ end
+
+ private
+
+ def button_attribute(anchor)
+ "btn-#{anchor.class_modifier || 'missing'}"
+ end
+
+ def extra_classes(anchor)
+ if anchor.is_link
+ 'stat-link'
+ else
+ "btn #{button_attribute(anchor)}"
+ end
+ end
+end
diff --git a/app/helpers/suggest_pipeline_helper.rb b/app/helpers/suggest_pipeline_helper.rb
index d64e8d6f2cd..3151b792344 100644
--- a/app/helpers/suggest_pipeline_helper.rb
+++ b/app/helpers/suggest_pipeline_helper.rb
@@ -2,7 +2,7 @@
module SuggestPipelineHelper
def should_suggest_gitlab_ci_yml?
- experiment_enabled?(:suggest_pipeline) &&
+ Feature.enabled?(:suggest_pipeline, default_enabled: true) &&
current_user &&
params[:suggest_gitlab_ci_yml] == 'true'
end
diff --git a/app/helpers/time_helper.rb b/app/helpers/time_helper.rb
index 719c351242c..ecedbfb2a4f 100644
--- a/app/helpers/time_helper.rb
+++ b/app/helpers/time_helper.rb
@@ -32,4 +32,8 @@ module TimeHelper
"%02d:%02d:%02d" % [hours, minutes, seconds]
end
end
+
+ def time_in_milliseconds
+ (Time.now.to_f * 1000).to_i
+ end
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 563450159b5..692971f4627 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -75,11 +75,27 @@ module TreeHelper
if user_access(project).can_push_to_branch?(ref)
ref
else
- project = tree_edit_project(project)
- project.repository.next_branch('patch')
+ patch_branch_name(ref)
end
end
+ # Generate a patch branch name that should look like:
+ # `username-branchname-patch-epoch`
+ # where `epoch` is the last 5 digits of the time since epoch (in
+ # milliseconds)
+ #
+ # Note: this correlates with how the WebIDE formats the branch name
+ # and if this implementation changes, so should the `placeholderBranchName`
+ # definition in app/assets/javascripts/ide/stores/modules/commit/getters.js
+ def patch_branch_name(ref)
+ return unless current_user
+
+ username = current_user.username
+ epoch = time_in_milliseconds.to_s.last(5)
+
+ "#{username}-#{ref}-patch-#{epoch}"
+ end
+
def tree_edit_project(project = @project)
if can?(current_user, :push_code, project)
project
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
index 0cdf53d6174..e93c1b82cd7 100644
--- a/app/helpers/user_callouts_helper.rb
+++ b/app/helpers/user_callouts_helper.rb
@@ -10,6 +10,7 @@ module UserCalloutsHelper
WEBHOOKS_MOVED = 'webhooks_moved'
CUSTOMIZE_HOMEPAGE = 'customize_homepage'
FEATURE_FLAGS_NEW_VERSION = 'feature_flags_new_version'
+ REGISTRATION_ENABLED_CALLOUT = 'registration_enabled_callout'
def show_admin_integrations_moved?
!user_dismissed?(ADMIN_INTEGRATIONS_MOVED)
@@ -55,6 +56,10 @@ module UserCalloutsHelper
!user_dismissed?(FEATURE_FLAGS_NEW_VERSION)
end
+ def show_registration_enabled_user_callout?
+ current_user&.admin? && signup_enabled? && !user_dismissed?(REGISTRATION_ENABLED_CALLOUT)
+ end
+
private
def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil)
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index f47937e6d57..7d4ab192f2f 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -91,18 +91,18 @@ module UsersHelper
end
end
- def work_information(user)
+ def work_information(user, with_schema_markup: false)
return unless user
organization = user.organization
job_title = user.job_title
if organization.present? && job_title.present?
- s_('Profile|%{job_title} at %{organization}') % { job_title: job_title, organization: organization }
+ render_job_title_and_organization(job_title, organization, with_schema_markup: with_schema_markup)
elsif job_title.present?
- job_title
+ render_job_title(job_title, with_schema_markup: with_schema_markup)
elsif organization.present?
- organization
+ render_organization(organization, with_schema_markup: with_schema_markup)
end
end
@@ -110,6 +110,32 @@ module UsersHelper
!user.confirmed?
end
+ def user_block_data(user, message)
+ {
+ path: block_admin_user_path(user),
+ method: 'put',
+ modal_attributes: {
+ title: s_('AdminUsers|Block user %{username}?') % { username: sanitize_name(user.name) },
+ messageHtml: message,
+ okVariant: 'warning',
+ okTitle: s_('AdminUsers|Block')
+ }.to_json
+ }
+ end
+
+ def user_block_effects
+ header = tag.p s_('AdminUsers|Blocking user has the following effects:')
+
+ list = tag.ul do
+ concat tag.li s_('AdminUsers|User will not be able to login')
+ concat tag.li s_('AdminUsers|User will not be able to access git repositories')
+ concat tag.li s_('AdminUsers|Personal projects will be left')
+ concat tag.li s_('AdminUsers|Owned groups will be left')
+ end
+
+ header + list
+ end
+
private
def blocked_user_badge(user)
@@ -151,6 +177,35 @@ module UsersHelper
items
end
+
+ def render_job_title(job_title, with_schema_markup: false)
+ if with_schema_markup
+ content_tag :span, itemprop: 'jobTitle' do
+ job_title
+ end
+ else
+ job_title
+ end
+ end
+
+ def render_organization(organization, with_schema_markup: false)
+ if with_schema_markup
+ content_tag :span, itemprop: 'worksFor' do
+ organization
+ end
+ else
+ organization
+ end
+ end
+
+ def render_job_title_and_organization(job_title, organization, with_schema_markup: false)
+ if with_schema_markup
+ job_title = '<span itemprop="jobTitle">'.html_safe + job_title + "</span>".html_safe
+ organization = '<span itemprop="worksFor">'.html_safe + organization + "</span>".html_safe
+ end
+
+ html_escape(s_('Profile|%{job_title} at %{organization}')) % { job_title: job_title, organization: organization }
+ end
end
UsersHelper.prepend_if_ee('EE::UsersHelper')
diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb
index a7b9e17c898..896dcdd2caf 100644
--- a/app/helpers/visibility_level_helper.rb
+++ b/app/helpers/visibility_level_helper.rb
@@ -31,7 +31,7 @@ module VisibilityLevelHelper
when Gitlab::VisibilityLevel::PRIVATE
_("Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group.")
when Gitlab::VisibilityLevel::INTERNAL
- _("The project can be accessed by any logged in user.")
+ _("The project can be accessed by any logged in user except external users.")
when Gitlab::VisibilityLevel::PUBLIC
_("The project can be accessed without any authentication.")
end
@@ -42,7 +42,7 @@ module VisibilityLevelHelper
when Gitlab::VisibilityLevel::PRIVATE
_("The group and its projects can only be viewed by members.")
when Gitlab::VisibilityLevel::INTERNAL
- _("The group and any internal projects can be viewed by any logged in user.")
+ _("The group and any internal projects can be viewed by any logged in user except external users.")
when Gitlab::VisibilityLevel::PUBLIC
_("The group and any public projects can be viewed without any authentication.")
end
diff --git a/app/helpers/whats_new_helper.rb b/app/helpers/whats_new_helper.rb
index c183ed7f12a..283d443f51b 100644
--- a/app/helpers/whats_new_helper.rb
+++ b/app/helpers/whats_new_helper.rb
@@ -5,7 +5,7 @@ module WhatsNewHelper
def whats_new_most_recent_release_items_count
Gitlab::ProcessMemoryCache.cache_backend.fetch('whats_new:release_items_count', expires_in: CACHE_DURATION) do
- whats_new_most_recent_release_items&.count
+ whats_new_release_items&.count
end
end
@@ -19,9 +19,7 @@ module WhatsNewHelper
def whats_new_most_recent_version
Gitlab::ProcessMemoryCache.cache_backend.fetch('whats_new:release_version', expires_in: CACHE_DURATION) do
- if whats_new_most_recent_release_items
- whats_new_most_recent_release_items.first.try(:[], 'release')
- end
+ whats_new_release_items&.first&.[]('release')
end
end
end
diff --git a/app/mailers/devise_mailer.rb b/app/mailers/devise_mailer.rb
index a02670aed90..61a23520d54 100644
--- a/app/mailers/devise_mailer.rb
+++ b/app/mailers/devise_mailer.rb
@@ -13,6 +13,10 @@ class DeviseMailer < Devise::Mailer
devise_mail(record, :password_change_by_admin, opts)
end
+ def user_admin_approval(record, opts = {})
+ devise_mail(record, :user_admin_approval, opts)
+ end
+
protected
def subject_for(key)
diff --git a/app/mailers/emails/members.rb b/app/mailers/emails/members.rb
index 57e4c7df440..0b5a8dfdc24 100644
--- a/app/mailers/emails/members.rb
+++ b/app/mailers/emails/members.rb
@@ -51,34 +51,20 @@ module Emails
return unless member_exists?
- 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')
+ subject_line =
+ if member.created_by
+ subject(s_("MemberInviteEmail|%{member_name} invited you to join GitLab") % { member_name: member.created_by.name })
+ else
+ subject(s_("MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}") % { project_or_group: member_source.human_name, project_or_group_name: member_source.model_name.singular })
end
- end
- if member.invite_to_unknown_user? && Gitlab::Experimentation.enabled?(:invitation_reminders)
+ member_email_with_layout(
+ to: member.invite_email,
+ subject: subject_line,
+ layout: 'unknown_user_mailer'
+ )
+
+ if Gitlab::Experimentation.enabled?(:invitation_reminders)
Gitlab::Tracking.event(
Gitlab::Experimentation.experiment(:invitation_reminders).tracking_category,
'sent',
@@ -105,7 +91,7 @@ module Emails
subject_line = subjects[reminder_index] % { inviter: member.created_by.name }
member_email_with_layout(
- layout: 'experiment_mailer',
+ layout: 'unknown_user_mailer',
to: member.invite_email,
subject: subject(subject_line)
)
@@ -162,15 +148,10 @@ module Emails
@member_source_type.classify.constantize
end
- def member_email_with_layout(to:, subject:, template: nil, layout: 'mailer')
+ def member_email_with_layout(to:, subject:, layout: 'mailer')
mail(to: to, subject: subject) do |format|
- 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
+ format.html { render layout: layout }
+ format.text { render layout: layout }
end
end
end
diff --git a/app/mailers/emails/profile.rb b/app/mailers/emails/profile.rb
index 96cf3571968..6f44b63f8d0 100644
--- a/app/mailers/emails/profile.rb
+++ b/app/mailers/emails/profile.rb
@@ -9,6 +9,15 @@ module Emails
mail(to: @user.notification_email, subject: subject("Account was created for you"))
end
+ def instance_access_request_email(user, recipient)
+ @user = user
+ @recipient = recipient
+
+ profile_email_with_layout(
+ to: recipient.notification_email,
+ subject: subject(_("GitLab Account Request")))
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def new_ssh_key_email(key_id)
@key = Key.find_by(id: key_id)
@@ -63,13 +72,9 @@ module Emails
@target_url = edit_profile_password_url
Gitlab::I18n.with_locale(@user.preferred_language) do
- mail(
+ profile_email_with_layout(
to: @user.notification_email,
- subject: subject(_("%{host} sign-in from new location") % { host: Gitlab.config.gitlab.host })
- ) do |format|
- format.html { render layout: 'mailer' }
- format.text { render layout: 'mailer' }
- end
+ subject: subject(_("%{host} sign-in from new location") % { host: Gitlab.config.gitlab.host }))
end
end
@@ -82,6 +87,15 @@ module Emails
mail(to: @user.notification_email, subject: subject(_("Two-factor authentication disabled")))
end
end
+
+ private
+
+ def profile_email_with_layout(to:, subject:, layout: 'mailer')
+ mail(to: to, subject: subject) do |format|
+ format.html { render layout: layout }
+ format.text { render layout: layout }
+ end
+ end
end
end
diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb
index 17ef8b41e79..a4b7b140169 100644
--- a/app/mailers/emails/projects.rb
+++ b/app/mailers/emails/projects.rb
@@ -56,12 +56,9 @@ module Emails
subject: @message.subject)
end
- def prometheus_alert_fired_email(project_id, user_id, alert_attributes)
- @project = ::Project.find(project_id)
- user = ::User.find(user_id)
-
- @alert = AlertManagement::Alert.new(alert_attributes.with_indifferent_access).present
- return unless @alert.parsed_payload.has_required_attributes?
+ def prometheus_alert_fired_email(project, user, alert)
+ @project = project
+ @alert = alert.present
subject_text = "Alert: #{@alert.email_title}"
mail(to: user.notification_email_for(@project.group), subject: subject(subject_text))
diff --git a/app/mailers/emails/service_desk.rb b/app/mailers/emails/service_desk.rb
index 29fe608472d..fa646487819 100644
--- a/app/mailers/emails/service_desk.rb
+++ b/app/mailers/emails/service_desk.rb
@@ -58,10 +58,12 @@ module Emails
def template_content(email_type)
template = Gitlab::Template::ServiceDeskTemplate.find(email_type, @project)
-
text = substitute_template_replacements(template.content)
- markdown(text, project: @project)
+ context = { project: @project, pipeline: :email }
+ context[:author] = @note.author if email_type == 'new_note'
+
+ markdown(text, context)
rescue Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError
nil
end
diff --git a/app/mailers/previews/devise_mailer_preview.rb b/app/mailers/previews/devise_mailer_preview.rb
index 3b9ef0d3ac0..68f281f825e 100644
--- a/app/mailers/previews/devise_mailer_preview.rb
+++ b/app/mailers/previews/devise_mailer_preview.rb
@@ -24,6 +24,10 @@ class DeviseMailerPreview < ActionMailer::Preview
DeviseMailer.password_change(unsaved_user, {})
end
+ def user_admin_approval
+ DeviseMailer.user_admin_approval(unsaved_user, {})
+ end
+
private
def unsaved_user
diff --git a/app/models/alert_management/alert.rb b/app/models/alert_management/alert.rb
index 61cc15a522e..7ce7f40b6a8 100644
--- a/app/models/alert_management/alert.rb
+++ b/app/models/alert_management/alert.rb
@@ -34,7 +34,7 @@ module AlertManagement
has_many :ordered_notes, -> { fresh }, as: :noteable, class_name: 'Note'
has_many :user_mentions, class_name: 'AlertManagement::AlertUserMention', foreign_key: :alert_management_alert_id
- has_internal_id :iid, scope: :project, init: ->(s) { s.project.alert_management_alerts.maximum(:iid) }
+ has_internal_id :iid, scope: :project
sha_attribute :fingerprint
diff --git a/app/models/alert_management/http_integration.rb b/app/models/alert_management/http_integration.rb
index 7f954e1d384..ae5170867c3 100644
--- a/app/models/alert_management/http_integration.rb
+++ b/app/models/alert_management/http_integration.rb
@@ -2,6 +2,10 @@
module AlertManagement
class HttpIntegration < ApplicationRecord
+ include ::Gitlab::Routing
+ LEGACY_IDENTIFIER = 'legacy'
+ DEFAULT_NAME_SLUG = 'http-endpoint'
+
belongs_to :project, inverse_of: :alert_management_http_integrations
attr_encrypted :token,
@@ -9,19 +13,45 @@ module AlertManagement
key: Settings.attr_encrypted_db_key_base_truncated,
algorithm: 'aes-256-gcm'
+ default_value_for(:endpoint_identifier, allows_nil: false) { SecureRandom.hex(8) }
+ default_value_for(:token) { generate_token }
+
validates :project, presence: true
validates :active, inclusion: { in: [true, false] }
-
- validates :token, presence: true
+ validates :token, presence: true, format: { with: /\A\h{32}\z/ }
validates :name, presence: true, length: { maximum: 255 }
- validates :endpoint_identifier, presence: true, length: { maximum: 255 }
+ validates :endpoint_identifier, presence: true, length: { maximum: 255 }, format: { with: /\A[A-Za-z0-9]+\z/ }
validates :endpoint_identifier, uniqueness: { scope: [:project_id, :active] }, if: :active?
before_validation :prevent_token_assignment
+ before_validation :prevent_endpoint_identifier_assignment
before_validation :ensure_token
+ scope :for_endpoint_identifier, -> (endpoint_identifier) { where(endpoint_identifier: endpoint_identifier) }
+ scope :active, -> { where(active: true) }
+ scope :ordered_by_id, -> { order(:id) }
+
+ def url
+ return project_alerts_notify_url(project, format: :json) if legacy?
+
+ project_alert_http_integration_url(project, name_slug, endpoint_identifier, format: :json)
+ end
+
private
+ def self.generate_token
+ SecureRandom.hex
+ end
+
+ def name_slug
+ (name && Gitlab::Utils.slugify(name)) || DEFAULT_NAME_SLUG
+ end
+
+ def legacy?
+ endpoint_identifier == LEGACY_IDENTIFIER
+ end
+
+ # Blank token assignment triggers token reset
def prevent_token_assignment
if token.present? && token_changed?
self.token = nil
@@ -31,11 +61,13 @@ module AlertManagement
end
def ensure_token
- self.token = generate_token if token.blank?
+ self.token = self.class.generate_token if token.blank?
end
- def generate_token
- SecureRandom.hex
+ def prevent_endpoint_identifier_assignment
+ if endpoint_identifier_changed? && endpoint_identifier_was.present?
+ self.endpoint_identifier = endpoint_identifier_was
+ end
end
end
end
diff --git a/app/models/analytics/devops_adoption.rb b/app/models/analytics/devops_adoption.rb
new file mode 100644
index 00000000000..ed5a5b16a6e
--- /dev/null
+++ b/app/models/analytics/devops_adoption.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+module Analytics::DevopsAdoption
+ def self.table_name_prefix
+ 'analytics_devops_adoption_'
+ end
+end
diff --git a/app/models/analytics/devops_adoption/segment.rb b/app/models/analytics/devops_adoption/segment.rb
new file mode 100644
index 00000000000..71d4a312627
--- /dev/null
+++ b/app/models/analytics/devops_adoption/segment.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class Analytics::DevopsAdoption::Segment < ApplicationRecord
+ ALLOWED_SEGMENT_COUNT = 20
+
+ has_many :segment_selections
+ has_many :groups, through: :segment_selections
+
+ validates :name, presence: true, uniqueness: true, length: { maximum: 255 }
+ validate :validate_segment_count
+
+ accepts_nested_attributes_for :segment_selections, allow_destroy: true
+
+ scope :ordered_by_name, -> { order(:name) }
+ scope :with_groups, -> { preload(:groups) }
+
+ private
+
+ def validate_segment_count
+ if self.class.count >= ALLOWED_SEGMENT_COUNT
+ errors.add(:name, s_('DevopsAdoptionSegment|The maximum number of segments has been reached'))
+ end
+ end
+end
diff --git a/app/models/analytics/devops_adoption/segment_selection.rb b/app/models/analytics/devops_adoption/segment_selection.rb
new file mode 100644
index 00000000000..6b70c13a773
--- /dev/null
+++ b/app/models/analytics/devops_adoption/segment_selection.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+class Analytics::DevopsAdoption::SegmentSelection < ApplicationRecord
+ ALLOWED_SELECTIONS_PER_SEGMENT = 20
+
+ belongs_to :segment
+ belongs_to :project
+ belongs_to :group
+
+ validates :segment, presence: true
+ validates :project, presence: { unless: :group }
+ validates :project_id, uniqueness: { scope: :segment_id, if: :project }
+ validates :group, presence: { unless: :project }
+ validates :group_id, uniqueness: { scope: :segment_id, if: :group }
+
+ validate :exclusive_project_or_group
+ validate :validate_selection_count
+
+ private
+
+ def exclusive_project_or_group
+ if project.present? && group.present?
+ errors.add(:group, s_('DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time'))
+ end
+ end
+
+ def validate_selection_count
+ return unless segment
+
+ selection_count_for_segment = self.class.where(segment: segment).count
+
+ if selection_count_for_segment >= ALLOWED_SELECTIONS_PER_SEGMENT
+ errors.add(:segment, s_('DevopsAdoptionSegmentSelection|The maximum number of selections has been reached'))
+ end
+ end
+end
diff --git a/app/models/analytics/instance_statistics/measurement.rb b/app/models/analytics/instance_statistics/measurement.rb
index 76cc1111e90..c8b76e005ef 100644
--- a/app/models/analytics/instance_statistics/measurement.rb
+++ b/app/models/analytics/instance_statistics/measurement.rb
@@ -15,35 +15,47 @@ module Analytics
pipelines_succeeded: 7,
pipelines_failed: 8,
pipelines_canceled: 9,
- pipelines_skipped: 10
+ pipelines_skipped: 10,
+ billable_users: 11
}
- IDENTIFIER_QUERY_MAPPING = {
- identifiers[:projects] => -> { Project },
- identifiers[:users] => -> { User },
- identifiers[:issues] => -> { Issue },
- identifiers[:merge_requests] => -> { MergeRequest },
- identifiers[:groups] => -> { Group },
- identifiers[:pipelines] => -> { Ci::Pipeline },
- identifiers[:pipelines_succeeded] => -> { Ci::Pipeline.success },
- identifiers[:pipelines_failed] => -> { Ci::Pipeline.failed },
- identifiers[:pipelines_canceled] => -> { Ci::Pipeline.canceled },
- identifiers[:pipelines_skipped] => -> { Ci::Pipeline.skipped }
- }.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) }
+ scope :recorded_after, -> (date) { where(self.model.arel_table[:recorded_at].gteq(date)) if date.present? }
+ scope :recorded_before, -> (date) { where(self.model.arel_table[:recorded_at].lteq(date)) if date.present? }
+
+ def self.identifier_query_mapping
+ {
+ identifiers[:projects] => -> { Project },
+ identifiers[:users] => -> { User },
+ identifiers[:issues] => -> { Issue },
+ identifiers[:merge_requests] => -> { MergeRequest },
+ identifiers[:groups] => -> { Group },
+ identifiers[:pipelines] => -> { Ci::Pipeline },
+ identifiers[:pipelines_succeeded] => -> { Ci::Pipeline.success },
+ identifiers[:pipelines_failed] => -> { Ci::Pipeline.failed },
+ identifiers[:pipelines_canceled] => -> { Ci::Pipeline.canceled },
+ identifiers[:pipelines_skipped] => -> { Ci::Pipeline.skipped }
+ }
+ end
+
+ # Customized min and max calculation, in some cases using the original scope is too slow.
+ def self.identifier_min_max_queries
+ {}
+ end
def self.measurement_identifier_values
- if Feature.enabled?(:store_ci_pipeline_counts_by_status, default_enabled: true)
- identifiers.values
- else
- identifiers.values - EXPERIMENTAL_IDENTIFIERS.map { |identifier| identifiers[identifier] }
- end
+ identifiers.values
+ end
+
+ def self.find_latest_or_fallback(identifier)
+ with_identifier(identifier).order_by_latest.first || identifier_query_mapping[identifiers[identifier]].call
end
end
end
end
+
+Analytics::InstanceStatistics::Measurement.prepend_if_ee('EE::Analytics::InstanceStatistics::Measurement')
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index 3542bb90dc0..71235ed1002 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -48,6 +48,8 @@ class ApplicationRecord < ActiveRecord::Base
def self.safe_find_or_create_by!(*args, &block)
safe_find_or_create_by(*args, &block).tap do |record|
+ raise ActiveRecord::RecordNotFound unless record.present?
+
record.validate! unless record.persisted?
end
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index d034630a085..7bfa5fb4cb8 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -8,8 +8,6 @@ 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'
INSTANCE_REVIEW_MIN_USERS = 50
GRAFANA_URL_ERROR_MESSAGE = 'Please check your Grafana URL setting in ' \
@@ -42,8 +40,8 @@ class ApplicationSetting < ApplicationRecord
serialize :restricted_visibility_levels # rubocop:disable Cop/ActiveRecordSerialize
serialize :import_sources # rubocop:disable Cop/ActiveRecordSerialize
serialize :disabled_oauth_sign_in_sources, Array # rubocop:disable Cop/ActiveRecordSerialize
- serialize :domain_whitelist, Array # rubocop:disable Cop/ActiveRecordSerialize
- serialize :domain_blacklist, Array # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :domain_allowlist, Array # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :domain_denylist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :repository_storages # rubocop:disable Cop/ActiveRecordSerialize
serialize :asset_proxy_whitelist, Array # rubocop:disable Cop/ActiveRecordSerialize
@@ -186,9 +184,9 @@ class ApplicationSetting < ApplicationRecord
validates :enabled_git_access_protocol,
inclusion: { in: %w(ssh http), allow_blank: true }
- validates :domain_blacklist,
- presence: { message: 'Domain blacklist cannot be empty if Blacklist is enabled.' },
- if: :domain_blacklist_enabled?
+ validates :domain_denylist,
+ presence: { message: 'Domain denylist cannot be empty if denylist is enabled.' },
+ if: :domain_denylist_enabled?
validates :housekeeping_incremental_repack_period,
presence: true,
@@ -294,6 +292,9 @@ class ApplicationSetting < ApplicationRecord
validates :container_registry_delete_tags_service_timeout,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+ validates :container_registry_expiration_policies_worker_capacity,
+ numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+
SUPPORTED_KEY_TYPES.each do |type|
validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type }
end
@@ -385,6 +386,9 @@ class ApplicationSetting < ApplicationRecord
validates :raw_blob_request_limit,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+ validates :ci_jwt_signing_key,
+ rsa_key: true, allow_nil: true
+
attr_encrypted :asset_proxy_secret_key,
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_truncated,
@@ -410,6 +414,9 @@ class ApplicationSetting < ApplicationRecord
attr_encrypted :recaptcha_site_key, encryption_options_base_truncated_aes_256_gcm
attr_encrypted :slack_app_secret, encryption_options_base_truncated_aes_256_gcm
attr_encrypted :slack_app_verification_token, encryption_options_base_truncated_aes_256_gcm
+ attr_encrypted :ci_jwt_signing_key, encryption_options_base_truncated_aes_256_gcm
+ attr_encrypted :secret_detection_token_revocation_token, encryption_options_base_truncated_aes_256_gcm
+ attr_encrypted :cloud_license_auth_token, encryption_options_base_truncated_aes_256_gcm
before_validation :ensure_uuid!
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index 8a7bd5a7ad9..5c7abbccd63 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -60,7 +60,7 @@ module ApplicationSettingImplementation
diff_max_patch_bytes: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES,
disabled_oauth_sign_in_sources: [],
dns_rebinding_protection_enabled: true,
- domain_whitelist: Settings.gitlab['domain_whitelist'],
+ domain_allowlist: Settings.gitlab['domain_allowlist'],
dsa_key_restriction: 0,
ecdsa_key_restriction: 0,
ed25519_key_restriction: 0,
@@ -120,7 +120,7 @@ module ApplicationSettingImplementation
repository_checks_enabled: true,
repository_storages_weighted: { default: 100 },
repository_storages: ['default'],
- require_admin_approval_after_user_signup: false,
+ require_admin_approval_after_user_signup: true,
require_two_factor_authentication: false,
restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'],
rsa_key_restriction: 0,
@@ -167,7 +167,8 @@ module ApplicationSettingImplementation
user_default_internal_regex: nil,
user_show_add_ssh_key_message: true,
wiki_page_max_content_bytes: 50.megabytes,
- container_registry_delete_tags_service_timeout: 100
+ container_registry_delete_tags_service_timeout: 250,
+ container_registry_expiration_policies_worker_capacity: 0
}
end
@@ -201,38 +202,38 @@ module ApplicationSettingImplementation
super(sources)
end
- def domain_whitelist_raw
- array_to_string(self.domain_whitelist)
+ def domain_allowlist_raw
+ array_to_string(self.domain_allowlist)
end
- def domain_blacklist_raw
- array_to_string(self.domain_blacklist)
+ def domain_denylist_raw
+ array_to_string(self.domain_denylist)
end
- def domain_whitelist_raw=(values)
- self.domain_whitelist = strings_to_array(values)
+ def domain_allowlist_raw=(values)
+ self.domain_allowlist = strings_to_array(values)
end
- def domain_blacklist_raw=(values)
- self.domain_blacklist = strings_to_array(values)
+ def domain_denylist_raw=(values)
+ self.domain_denylist = strings_to_array(values)
end
- def domain_blacklist_file=(file)
- self.domain_blacklist_raw = file.read
+ def domain_denylist_file=(file)
+ self.domain_denylist_raw = file.read
end
- def outbound_local_requests_whitelist_raw
+ def outbound_local_requests_allowlist_raw
array_to_string(self.outbound_local_requests_whitelist)
end
- def outbound_local_requests_whitelist_raw=(values)
- clear_memoization(:outbound_local_requests_whitelist_arrays)
+ def outbound_local_requests_allowlist_raw=(values)
+ clear_memoization(:outbound_local_requests_allowlist_arrays)
self.outbound_local_requests_whitelist = strings_to_array(values)
end
def add_to_outbound_local_requests_whitelist(values_array)
- clear_memoization(:outbound_local_requests_whitelist_arrays)
+ clear_memoization(:outbound_local_requests_allowlist_arrays)
self.outbound_local_requests_whitelist ||= []
self.outbound_local_requests_whitelist += values_array
@@ -244,13 +245,13 @@ module ApplicationSettingImplementation
# application_setting.outbound_local_requests_whitelist array into 2 arrays;
# an array of IPAddr objects (`[IPAddr.new('127.0.0.1')]`), and an array of
# domain strings (`['www.example.com']`).
- def outbound_local_requests_whitelist_arrays
- strong_memoize(:outbound_local_requests_whitelist_arrays) do
+ def outbound_local_requests_allowlist_arrays
+ strong_memoize(:outbound_local_requests_allowlist_arrays) do
next [[], []] unless self.outbound_local_requests_whitelist
- ip_whitelist, domain_whitelist = separate_whitelists(self.outbound_local_requests_whitelist)
+ ip_allowlist, domain_allowlist = separate_allowlists(self.outbound_local_requests_whitelist)
- [ip_whitelist, domain_whitelist]
+ [ip_allowlist, domain_allowlist]
end
end
@@ -395,19 +396,19 @@ module ApplicationSettingImplementation
private
- def separate_whitelists(string_array)
- string_array.reduce([[], []]) do |(ip_whitelist, domain_whitelist), string|
+ def separate_allowlists(string_array)
+ string_array.reduce([[], []]) do |(ip_allowlist, domain_allowlist), string|
address, port = parse_addr_and_port(string)
ip_obj = Gitlab::Utils.string_to_ip_object(address)
if ip_obj
- ip_whitelist << Gitlab::UrlBlockers::IpWhitelistEntry.new(ip_obj, port: port)
+ ip_allowlist << Gitlab::UrlBlockers::IpAllowlistEntry.new(ip_obj, port: port)
else
- domain_whitelist << Gitlab::UrlBlockers::DomainWhitelistEntry.new(address, port: port)
+ domain_allowlist << Gitlab::UrlBlockers::DomainAllowlistEntry.new(address, port: port)
end
- [ip_whitelist, domain_whitelist]
+ [ip_allowlist, domain_allowlist]
end
end
diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb
index 34f03e769a0..55e8a5d4535 100644
--- a/app/models/audit_event.rb
+++ b/app/models/audit_event.rb
@@ -2,7 +2,6 @@
class AuditEvent < ApplicationRecord
include CreatedAtFilterable
- include IgnorableColumns
include BulkInsertSafe
include EachBatch
@@ -14,8 +13,6 @@ class AuditEvent < ApplicationRecord
:target_id
].freeze
- ignore_column :type, remove_with: '13.6', remove_after: '2020-11-22'
-
serialize :details, Hash # rubocop:disable Cop/ActiveRecordSerialize
belongs_to :user, foreign_key: :author_id
@@ -37,14 +34,6 @@ 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
index ac6e08caf50..9d191e6ae4d 100644
--- a/app/models/authentication_event.rb
+++ b/app/models/authentication_event.rb
@@ -3,6 +3,12 @@
class AuthenticationEvent < ApplicationRecord
include UsageStatistics
+ TWO_FACTOR = 'two-factor'.freeze
+ TWO_FACTOR_U2F = 'two-factor-via-u2f-device'.freeze
+ TWO_FACTOR_WEBAUTHN = 'two-factor-via-webauthn-device'.freeze
+ STANDARD = 'standard'.freeze
+ STATIC_PROVIDERS = [TWO_FACTOR, TWO_FACTOR_U2F, TWO_FACTOR_WEBAUTHN, STANDARD].freeze
+
belongs_to :user, optional: true
validates :provider, :user_name, :result, presence: true
@@ -17,6 +23,6 @@ class AuthenticationEvent < ApplicationRecord
scope :ldap, -> { where('provider LIKE ?', 'ldap%')}
def self.providers
- distinct.pluck(:provider)
+ STATIC_PROVIDERS | Devise.omniauth_providers.map(&:to_s)
end
end
diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb
index 856f86201ec..a8325e98095 100644
--- a/app/models/broadcast_message.rb
+++ b/app/models/broadcast_message.rb
@@ -103,6 +103,7 @@ class BroadcastMessage < ApplicationRecord
end
def matches_current_path(current_path)
+ return false if current_path.blank? && target_path.present?
return true if current_path.blank? || target_path.blank?
escaped = Regexp.escape(target_path).gsub('\\*', '.*')
diff --git a/app/models/bulk_import.rb b/app/models/bulk_import.rb
index cabff86a9f9..5d646313423 100644
--- a/app/models/bulk_import.rb
+++ b/app/models/bulk_import.rb
@@ -1,5 +1,8 @@
# frozen_string_literal: true
+# The BulkImport model links all models required for a bulk import of groups and
+# projects to a GitLab instance. It associates the import with the responsible
+# user.
class BulkImport < ApplicationRecord
belongs_to :user, optional: false
@@ -12,5 +15,20 @@ class BulkImport < ApplicationRecord
state_machine :status, initial: :created do
state :created, value: 0
+ state :started, value: 1
+ state :finished, value: 2
+ state :failed, value: -1
+
+ event :start do
+ transition created: :started
+ end
+
+ event :finish do
+ transition started: :finished
+ end
+
+ event :fail_op do
+ transition any => :failed
+ end
end
end
diff --git a/app/models/bulk_imports/configuration.rb b/app/models/bulk_imports/configuration.rb
index 8c3aff6f749..4c6f745c268 100644
--- a/app/models/bulk_imports/configuration.rb
+++ b/app/models/bulk_imports/configuration.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+# Stores the authentication data required to access another GitLab instance on
+# behalf of a user, to import Groups and Projects directly from that instance.
class BulkImports::Configuration < ApplicationRecord
self.table_name = 'bulk_import_configurations'
diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb
index 2d0bba7bccc..34030e079c7 100644
--- a/app/models/bulk_imports/entity.rb
+++ b/app/models/bulk_imports/entity.rb
@@ -1,5 +1,22 @@
# frozen_string_literal: true
+# The BulkImport::Entity represents a Group or Project to be imported during the
+# bulk import process. An entity is nested under the parent group when it is not
+# a top level group.
+#
+# A full bulk import entity structure might look like this, where the links are
+# parents:
+#
+# **Before Import** **After Import**
+#
+# GroupEntity Group
+# | | | |
+# GroupEntity ProjectEntity Group Project
+# | |
+# ProjectEntity Project
+#
+# The tree structure of the entities results in the same structure for imported
+# Groups and Projects.
class BulkImports::Entity < ApplicationRecord
self.table_name = 'bulk_import_entities'
@@ -9,6 +26,10 @@ class BulkImports::Entity < ApplicationRecord
belongs_to :project, optional: true
belongs_to :group, foreign_key: :namespace_id, optional: true
+ has_many :trackers,
+ class_name: 'BulkImports::Tracker',
+ foreign_key: :bulk_import_entity_id
+
validates :project, absence: true, if: :group
validates :group, absence: true, if: :project
validates :source_type, :source_full_path, :destination_name,
@@ -21,6 +42,21 @@ class BulkImports::Entity < ApplicationRecord
state_machine :status, initial: :created do
state :created, value: 0
+ state :started, value: 1
+ state :finished, value: 2
+ state :failed, value: -1
+
+ event :start do
+ transition created: :started
+ end
+
+ event :finish do
+ transition started: :finished
+ end
+
+ event :fail_op do
+ transition any => :failed
+ end
end
private
@@ -33,11 +69,17 @@ class BulkImports::Entity < ApplicationRecord
def validate_imported_entity_type
if group.present? && project_entity?
- errors.add(:group, s_('BulkImport|expected an associated Project but has an associated Group'))
+ errors.add(
+ :group,
+ s_('BulkImport|expected an associated Project but has an associated Group')
+ )
end
if project.present? && group_entity?
- errors.add(:project, s_('BulkImport|expected an associated Group but has an associated Project'))
+ errors.add(
+ :project,
+ s_('BulkImport|expected an associated Group but has an associated Project')
+ )
end
end
end
diff --git a/app/models/bulk_imports/tracker.rb b/app/models/bulk_imports/tracker.rb
new file mode 100644
index 00000000000..02e0904e1af
--- /dev/null
+++ b/app/models/bulk_imports/tracker.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# This model is responsible for keeping track of the requests/pagination
+# happening during a Group Migration (BulkImport).
+class BulkImports::Tracker < ApplicationRecord
+ self.table_name = 'bulk_import_trackers'
+
+ belongs_to :entity,
+ class_name: 'BulkImports::Entity',
+ foreign_key: :bulk_import_entity_id,
+ optional: false
+
+ validates :relation,
+ presence: true,
+ uniqueness: { scope: :bulk_import_entity_id }
+
+ validates :next_page, presence: { if: :has_next_page? }
+end
diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb
index 2e725e0baff..5b23cf46fdb 100644
--- a/app/models/ci/bridge.rb
+++ b/app/models/ci/bridge.rb
@@ -7,6 +7,7 @@ module Ci
include Importable
include AfterCommitQueue
include Ci::HasRef
+ extend ::Gitlab::Utils::Override
InvalidBridgeTypeError = Class.new(StandardError)
InvalidTransitionError = Class.new(StandardError)
@@ -203,8 +204,11 @@ module Ci
end
end
+ override :dependency_variables
def dependency_variables
- []
+ return [] unless ::Feature.enabled?(:ci_bridge_dependency_variables, project)
+
+ super
end
def target_revision_ref
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 9ff70ece947..84abd01786d 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -103,6 +103,10 @@ module Ci
)
end
+ scope :in_pipelines, ->(pipelines) do
+ where(pipeline: pipelines)
+ end
+
scope :with_existing_job_artifacts, ->(query) do
where('EXISTS (?)', ::Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').merge(query))
end
@@ -571,14 +575,6 @@ module Ci
end
end
- def dependency_variables
- return [] if all_dependencies.empty?
-
- Gitlab::Ci::Variables::Collection.new.concat(
- Ci::JobVariable.where(job: all_dependencies).dotenv_source
- )
- end
-
def features
{ trace_sections: true }
end
@@ -828,10 +824,6 @@ module Ci
Gitlab::Ci::Build::Credentials::Factory.new(self).create!
end
- def all_dependencies
- dependencies.all
- end
-
def has_valid_build_dependencies?
dependencies.valid?
end
@@ -994,12 +986,6 @@ module Ci
end
end
- def dependencies
- strong_memoize(:dependencies) do
- Ci::BuildDependencies.new(self)
- end
- end
-
def build_data
@build_data ||= Gitlab::DataBuilder::Build.build(self)
end
@@ -1059,7 +1045,7 @@ module Ci
jwt = Gitlab::Ci::Jwt.for_build(self)
variables.append(key: 'CI_JOB_JWT', value: jwt, public: false, masked: true)
- rescue OpenSSL::PKey::RSAError => e
+ rescue OpenSSL::PKey::RSAError, Gitlab::Ci::Jwt::NoSigningKeyError => e
Gitlab::ErrorTracking.track_exception(e)
end
end
diff --git a/app/models/ci/build_trace_chunk.rb b/app/models/ci/build_trace_chunk.rb
index cf6eb159f52..ceefb6a8b8a 100644
--- a/app/models/ci/build_trace_chunk.rb
+++ b/app/models/ci/build_trace_chunk.rb
@@ -22,20 +22,26 @@ module Ci
FailedToPersistDataError = Class.new(StandardError)
- # Note: The ordering of this enum is related to the precedence of persist store.
+ # Note: The ordering of this hash is related to the precedence of persist store.
# The bottom item takes the highest precedence, and the top item takes the lowest precedence.
- enum data_store: {
+ DATA_STORES = {
redis: 1,
database: 2,
fog: 3
- }
+ }.freeze
+
+ STORE_TYPES = DATA_STORES.keys.map do |store|
+ [store, "Ci::BuildTraceChunks::#{store.capitalize}".constantize]
+ end.to_h.freeze
+
+ enum data_store: DATA_STORES
scope :live, -> { redis }
scope :persisted, -> { not_redis.order(:chunk_index) }
class << self
def all_stores
- @all_stores ||= self.data_stores.keys
+ STORE_TYPES.keys
end
def persistable_store
@@ -44,12 +50,11 @@ module Ci
end
def get_store_class(store)
- @stores ||= {}
+ store = store.to_sym
- # Can't memoize this because the feature flag may alter this
- return fog_store_class.new if store.to_sym == :fog
+ raise "Unknown store type: #{store}" unless STORE_TYPES.key?(store)
- @stores[store] ||= "Ci::BuildTraceChunks::#{store.capitalize}".constantize.new
+ STORE_TYPES[store].new
end
##
@@ -78,14 +83,6 @@ module Ci
def metadata_attributes
attribute_names - %w[raw_data]
end
-
- def fog_store_class
- if Feature.enabled?(:ci_trace_new_fog_store, default_enabled: true)
- Ci::BuildTraceChunks::Fog
- else
- Ci::BuildTraceChunks::LegacyFog
- end
- end
end
def data
@@ -108,7 +105,7 @@ module Ci
raise ArgumentError, 'Offset is out of range' if offset < 0 || offset > size
raise ArgumentError, 'Chunk size overflow' if CHUNK_SIZE < (offset + new_data.bytesize)
- in_lock(*lock_params) { unsafe_append_data!(new_data, offset) }
+ in_lock(lock_key, **lock_params) { unsafe_append_data!(new_data, offset) }
schedule_to_persist! if full?
end
@@ -148,12 +145,13 @@ module Ci
# We are using optimistic locking combined with Redis locking to ensure
# that a chunk gets migrated properly.
#
- # We are catching an exception related to an exclusive lock not being
- # acquired because it is creating a lot of noise, and is a result of
- # duplicated workers running in parallel for the same build trace chunk.
+ # We are using until_executed deduplication strategy for workers,
+ # which should prevent duplicated workers running in parallel for the same build trace,
+ # and causing an exception related to an exclusive lock not being
+ # acquired
#
def persist_data!
- in_lock(*lock_params) do # exclusive Redis lock is acquired first
+ in_lock(lock_key, **lock_params) do # exclusive Redis lock is acquired first
raise FailedToPersistDataError, 'Modifed build trace chunk detected' if has_changes_to_save?
self.reset.then do |chunk| # we ensure having latest lock_version
@@ -162,6 +160,8 @@ module Ci
end
rescue FailedToObtainLockError
metrics.increment_trace_operation(operation: :stalled)
+
+ raise FailedToPersistDataError, 'Data migration failed due to a worker duplication'
rescue ActiveRecord::StaleObjectError
raise FailedToPersistDataError, <<~MSG
Data migration race condition detected
@@ -289,11 +289,16 @@ module Ci
build.trace_chunks.maximum(:chunk_index).to_i
end
+ def lock_key
+ "trace_write:#{build_id}:chunks:#{chunk_index}"
+ end
+
def lock_params
- ["trace_write:#{build_id}:chunks:#{chunk_index}",
- { ttl: WRITE_LOCK_TTL,
- retries: WRITE_LOCK_RETRY,
- sleep_sec: WRITE_LOCK_SLEEP }]
+ {
+ ttl: WRITE_LOCK_TTL,
+ retries: WRITE_LOCK_RETRY,
+ sleep_sec: WRITE_LOCK_SLEEP
+ }
end
def metrics
diff --git a/app/models/ci/build_trace_chunks/legacy_fog.rb b/app/models/ci/build_trace_chunks/legacy_fog.rb
deleted file mode 100644
index b710ed2890b..00000000000
--- a/app/models/ci/build_trace_chunks/legacy_fog.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- module BuildTraceChunks
- class LegacyFog
- def available?
- object_store.enabled
- end
-
- def data(model)
- connection.get_object(bucket_name, key(model))[:body]
- rescue Excon::Error::NotFound
- # If the object does not exist in the object storage, this method returns nil.
- end
-
- def set_data(model, new_data)
- connection.put_object(bucket_name, key(model), new_data)
- end
-
- def append_data(model, new_data, offset)
- if offset > 0
- truncated_data = data(model).to_s.byteslice(0, offset)
- new_data = truncated_data + new_data
- end
-
- set_data(model, new_data)
- new_data.bytesize
- end
-
- def size(model)
- data(model).to_s.bytesize
- end
-
- def delete_data(model)
- delete_keys([[model.build_id, model.chunk_index]])
- end
-
- def keys(relation)
- return [] unless available?
-
- relation.pluck(:build_id, :chunk_index)
- end
-
- def delete_keys(keys)
- keys.each do |key|
- connection.delete_object(bucket_name, key_raw(*key))
- end
- end
-
- private
-
- def key(model)
- key_raw(model.build_id, model.chunk_index)
- end
-
- def key_raw(build_id, chunk_index)
- "tmp/builds/#{build_id.to_i}/chunks/#{chunk_index.to_i}.log"
- end
-
- def bucket_name
- return unless available?
-
- object_store.remote_directory
- end
-
- def connection
- return unless available?
-
- @connection ||= ::Fog::Storage.new(object_store.connection.to_hash.deep_symbolize_keys)
- end
-
- def object_store
- Gitlab.config.artifacts.object_store
- end
- end
- 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 e6f02f2e4f3..e9f3366b939 100644
--- a/app/models/ci/daily_build_group_report_result.rb
+++ b/app/models/ci/daily_build_group_report_result.rb
@@ -4,6 +4,7 @@ module Ci
class DailyBuildGroupReportResult < ApplicationRecord
extend Gitlab::Ci::Model
+ REPORT_WINDOW = 90.days
PARAM_TYPES = %w[coverage].freeze
belongs_to :last_pipeline, class_name: 'Ci::Pipeline', foreign_key: :last_pipeline_id
@@ -12,13 +13,30 @@ module Ci
validates :data, json_schema: { filename: "daily_build_group_report_result_data" }
scope :with_included_projects, -> { includes(:project) }
+ scope :by_projects, -> (ids) { where(project_id: ids) }
+ scope :with_coverage, -> { where("(data->'coverage') IS NOT NULL") }
+ scope :with_default_branch, -> { where(default_branch: true) }
+ scope :by_date, -> (start_date) { where(date: report_window(start_date)..Date.current) }
- def self.upsert_reports(data)
- upsert_all(data, unique_by: :index_daily_build_group_report_results_unique_columns) if data.any?
- end
+ store_accessor :data, :coverage
+
+ class << self
+ def upsert_reports(data)
+ upsert_all(data, unique_by: :index_daily_build_group_report_results_unique_columns) if data.any?
+ end
+
+ def recent_results(attrs, limit: nil)
+ where(attrs).order(date: :desc, group_name: :asc).limit(limit)
+ end
- def self.recent_results(attrs, limit: nil)
- where(attrs).order(date: :desc, group_name: :asc).limit(limit)
+ def report_window(start_date)
+ default_date = REPORT_WINDOW.ago.to_date
+ date = Date.parse(start_date) rescue default_date
+
+ [date, default_date].max
+ end
end
end
end
+
+Ci::DailyBuildGroupReportResult.prepend_if_ee('EE::Ci::DailyBuildGroupReportResult')
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index 02e17afdab0..7cedd13b407 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -169,6 +169,7 @@ module Ci
scope :downloadable, -> { where(file_type: DOWNLOADABLE_TYPES) }
scope :unlocked, -> { joins(job: :pipeline).merge(::Ci::Pipeline.unlocked).order(expire_at: :desc) }
+ scope :with_destroy_preloads, -> { includes(project: [:route, :statistics]) }
scope :scoped_project, -> { where('ci_job_artifacts.project_id = projects.id') }
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 684b6387ab1..8707d635e03 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -42,9 +42,16 @@ module Ci
belongs_to :external_pull_request
belongs_to :ci_ref, class_name: 'Ci::Ref', foreign_key: :ci_ref_id, inverse_of: :pipelines
- has_internal_id :iid, scope: :project, presence: false, track_if: -> { !importing? }, ensure_if: -> { !importing? }, init: ->(s) do
- s&.project&.all_pipelines&.maximum(:iid) || s&.project&.all_pipelines&.count
- end
+ has_internal_id :iid, scope: :project, presence: false,
+ track_if: -> { !importing? },
+ ensure_if: -> { !importing? },
+ init: ->(pipeline, scope) do
+ if pipeline
+ pipeline.project&.all_pipelines&.maximum(:iid) || pipeline.project&.all_pipelines&.count
+ elsif scope
+ ::Ci::Pipeline.where(**scope).maximum(:iid)
+ end
+ end
has_many :stages, -> { order(position: :asc) }, inverse_of: :pipeline
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
@@ -270,6 +277,7 @@ module Ci
scope :internal, -> { where(source: internal_sources) }
scope :no_child, -> { where.not(source: :parent_pipeline) }
scope :ci_sources, -> { where(source: Enums::Ci::Pipeline.ci_sources.values) }
+ scope :ci_and_parent_sources, -> { where(source: Enums::Ci::Pipeline.ci_and_parent_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) }
@@ -347,6 +355,14 @@ module Ci
end
end
+ def self.latest_running_for_ref(ref)
+ newest_first(ref: ref).running.take
+ end
+
+ def self.latest_failed_for_ref(ref)
+ newest_first(ref: ref).failed.take
+ end
+
# Returns a Hash containing the latest pipeline for every given
# commit.
#
@@ -926,7 +942,7 @@ module Ci
def accessibility_reports
Gitlab::Ci::Reports::AccessibilityReports.new.tap do |accessibility_reports|
- builds.latest.with_reports(Ci::JobArtifact.accessibility_reports).each do |build|
+ latest_report_builds(Ci::JobArtifact.accessibility_reports).each do |build|
build.collect_accessibility_reports!(accessibility_reports)
end
end
diff --git a/app/models/ci/processable.rb b/app/models/ci/processable.rb
index ac5785d9c91..6aaf6ac530b 100644
--- a/app/models/ci/processable.rb
+++ b/app/models/ci/processable.rb
@@ -103,5 +103,25 @@ module Ci
pipeline.ensure_scheduling_type!
reset
end
+
+ def dependency_variables
+ return [] if all_dependencies.empty?
+
+ Gitlab::Ci::Variables::Collection.new.concat(
+ Ci::JobVariable.where(job: all_dependencies).dotenv_source
+ )
+ end
+
+ def all_dependencies
+ dependencies.all
+ end
+
+ private
+
+ def dependencies
+ strong_memoize(:dependencies) do
+ Ci::BuildDependencies.new(self)
+ end
+ end
end
end
diff --git a/app/models/ci/test_case.rb b/app/models/ci/test_case.rb
new file mode 100644
index 00000000000..19ecc177436
--- /dev/null
+++ b/app/models/ci/test_case.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Ci
+ class TestCase < ApplicationRecord
+ extend Gitlab::Ci::Model
+
+ validates :project, :key_hash, presence: true
+
+ has_many :test_case_failures, class_name: 'Ci::TestCaseFailure'
+
+ belongs_to :project
+
+ scope :by_project_and_keys, -> (project, keys) { where(project_id: project.id, key_hash: keys) }
+
+ class << self
+ def find_or_create_by_batch(project, test_case_keys)
+ # Insert records first. Existing ones will be skipped.
+ insert_all(test_case_attrs(project, test_case_keys))
+
+ # Find all matching records now that we are sure they all are persisted.
+ by_project_and_keys(project, test_case_keys)
+ end
+
+ private
+
+ def test_case_attrs(project, test_case_keys)
+ # NOTE: Rails 6.1 will add support for insert_all on relation so that
+ # we will be able to do project.test_cases.insert_all.
+ test_case_keys.map do |hashed_key|
+ { project_id: project.id, key_hash: hashed_key }
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/ci/test_case_failure.rb b/app/models/ci/test_case_failure.rb
new file mode 100644
index 00000000000..8867b954240
--- /dev/null
+++ b/app/models/ci/test_case_failure.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Ci
+ class TestCaseFailure < ApplicationRecord
+ extend Gitlab::Ci::Model
+
+ REPORT_WINDOW = 14.days
+
+ validates :test_case, :build, :failed_at, presence: true
+
+ belongs_to :test_case, class_name: "Ci::TestCase", foreign_key: :test_case_id
+ belongs_to :build, class_name: "Ci::Build", foreign_key: :build_id
+
+ def self.recent_failures_count(project:, test_case_keys:, date_range: REPORT_WINDOW.ago..Time.current)
+ joins(:test_case)
+ .where(
+ ci_test_cases: {
+ project_id: project.id,
+ key_hash: test_case_keys
+ },
+ ci_test_case_failures: {
+ failed_at: date_range
+ }
+ )
+ .group(:key_hash)
+ .count('ci_test_case_failures.id')
+ end
+ end
+end
diff --git a/app/models/clusters/agent_token.rb b/app/models/clusters/agent_token.rb
index e9f1ee4e033..5c9561ffa98 100644
--- a/app/models/clusters/agent_token.rb
+++ b/app/models/clusters/agent_token.rb
@@ -3,7 +3,7 @@
module Clusters
class AgentToken < ApplicationRecord
include TokenAuthenticatable
- add_authentication_token_field :token, encrypted: :required
+ add_authentication_token_field :token, encrypted: :required, token_generator: -> { Devise.friendly_token(50) }
self.table_name = 'cluster_agent_tokens'
diff --git a/app/models/clusters/applications/cert_manager.rb b/app/models/clusters/applications/cert_manager.rb
index 1efa44c39c5..d32fff14590 100644
--- a/app/models/clusters/applications/cert_manager.rb
+++ b/app/models/clusters/applications/cert_manager.rb
@@ -30,7 +30,7 @@ module Clusters
end
def install_command
- Gitlab::Kubernetes::Helm::InstallCommand.new(
+ helm_command_module::InstallCommand.new(
name: 'certmanager',
repository: repository,
version: VERSION,
@@ -43,7 +43,7 @@ module Clusters
end
def uninstall_command
- Gitlab::Kubernetes::Helm::DeleteCommand.new(
+ helm_command_module::DeleteCommand.new(
name: 'certmanager',
rbac: cluster.platform_kubernetes_rbac?,
files: files,
diff --git a/app/models/clusters/applications/crossplane.rb b/app/models/clusters/applications/crossplane.rb
index 420e56c1742..2b1a86706a4 100644
--- a/app/models/clusters/applications/crossplane.rb
+++ b/app/models/clusters/applications/crossplane.rb
@@ -29,7 +29,7 @@ module Clusters
end
def install_command
- Gitlab::Kubernetes::Helm::InstallCommand.new(
+ helm_command_module::InstallCommand.new(
name: 'crossplane',
repository: repository,
version: VERSION,
diff --git a/app/models/clusters/applications/elastic_stack.rb b/app/models/clusters/applications/elastic_stack.rb
index 77996748b81..db18a29ec84 100644
--- a/app/models/clusters/applications/elastic_stack.rb
+++ b/app/models/clusters/applications/elastic_stack.rb
@@ -26,7 +26,7 @@ module Clusters
end
def install_command
- Gitlab::Kubernetes::Helm::InstallCommand.new(
+ helm_command_module::InstallCommand.new(
name: 'elastic-stack',
version: VERSION,
rbac: cluster.platform_kubernetes_rbac?,
@@ -39,7 +39,7 @@ module Clusters
end
def uninstall_command
- Gitlab::Kubernetes::Helm::DeleteCommand.new(
+ helm_command_module::DeleteCommand.new(
name: 'elastic-stack',
rbac: cluster.platform_kubernetes_rbac?,
files: files,
@@ -96,7 +96,7 @@ module Clusters
def post_install_script
[
- "timeout -t60 sh /data/helm/elastic-stack/config/wait-for-elasticsearch.sh http://elastic-stack-elasticsearch-master:9200"
+ "timeout 60 sh /data/helm/elastic-stack/config/wait-for-elasticsearch.sh http://elastic-stack-elasticsearch-master:9200"
]
end
@@ -116,7 +116,7 @@ module Clusters
# Chart version 3.0.0 moves to our own chart at https://gitlab.com/gitlab-org/charts/elastic-stack
# and is not compatible with pre-existing resources. We first remove them.
[
- Gitlab::Kubernetes::Helm::DeleteCommand.new(
+ helm_command_module::DeleteCommand.new(
name: 'elastic-stack',
rbac: cluster.platform_kubernetes_rbac?,
files: files
diff --git a/app/models/clusters/applications/fluentd.rb b/app/models/clusters/applications/fluentd.rb
index c608d37be77..91aa422b859 100644
--- a/app/models/clusters/applications/fluentd.rb
+++ b/app/models/clusters/applications/fluentd.rb
@@ -30,7 +30,7 @@ module Clusters
end
def install_command
- Gitlab::Kubernetes::Helm::InstallCommand.new(
+ helm_command_module::InstallCommand.new(
name: 'fluentd',
repository: repository,
version: VERSION,
diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb
index 4a1bcac4bb7..d1d6defb713 100644
--- a/app/models/clusters/applications/helm.rb
+++ b/app/models/clusters/applications/helm.rb
@@ -4,6 +4,8 @@ require 'openssl'
module Clusters
module Applications
+ # DEPRECATED: This model represents the Helm 2 Tiller server, and is no longer being actively used.
+ # It is being kept around for a potential cleanup of the unused Tiller server.
class Helm < ApplicationRecord
self.table_name = 'clusters_applications_helm'
@@ -49,7 +51,7 @@ module Clusters
end
def install_command
- Gitlab::Kubernetes::Helm::InitCommand.new(
+ Gitlab::Kubernetes::Helm::V2::InitCommand.new(
name: name,
files: files,
rbac: cluster.platform_kubernetes_rbac?
@@ -57,7 +59,7 @@ module Clusters
end
def uninstall_command
- Gitlab::Kubernetes::Helm::ResetCommand.new(
+ Gitlab::Kubernetes::Helm::V2::ResetCommand.new(
name: name,
files: files,
rbac: cluster.platform_kubernetes_rbac?
@@ -86,19 +88,19 @@ module Clusters
end
def create_keys_and_certs
- ca_cert = Gitlab::Kubernetes::Helm::Certificate.generate_root
+ ca_cert = Gitlab::Kubernetes::Helm::V2::Certificate.generate_root
self.ca_key = ca_cert.key_string
self.ca_cert = ca_cert.cert_string
end
def tiller_cert
- @tiller_cert ||= ca_cert_obj.issue(expires_in: Gitlab::Kubernetes::Helm::Certificate::INFINITE_EXPIRY)
+ @tiller_cert ||= ca_cert_obj.issue(expires_in: Gitlab::Kubernetes::Helm::V2::Certificate::INFINITE_EXPIRY)
end
def ca_cert_obj
return unless has_ssl?
- Gitlab::Kubernetes::Helm::Certificate
+ Gitlab::Kubernetes::Helm::V2::Certificate
.from_strings(ca_key, ca_cert)
end
end
diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb
index d5412714858..36324e7f3e0 100644
--- a/app/models/clusters/applications/ingress.rb
+++ b/app/models/clusters/applications/ingress.rb
@@ -62,7 +62,7 @@ module Clusters
end
def install_command
- Gitlab::Kubernetes::Helm::InstallCommand.new(
+ helm_command_module::InstallCommand.new(
name: name,
repository: repository,
version: VERSION,
diff --git a/app/models/clusters/applications/jupyter.rb b/app/models/clusters/applications/jupyter.rb
index 056ea355de6..ff907c6847f 100644
--- a/app/models/clusters/applications/jupyter.rb
+++ b/app/models/clusters/applications/jupyter.rb
@@ -39,7 +39,7 @@ module Clusters
end
def install_command
- Gitlab::Kubernetes::Helm::InstallCommand.new(
+ helm_command_module::InstallCommand.new(
name: name,
version: VERSION,
rbac: cluster.platform_kubernetes_rbac?,
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index 3047da12dd9..b1c3116d77c 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -70,7 +70,7 @@ module Clusters
end
def install_command
- Gitlab::Kubernetes::Helm::InstallCommand.new(
+ helm_command_module::InstallCommand.new(
name: name,
version: VERSION,
rbac: cluster.platform_kubernetes_rbac?,
@@ -94,7 +94,7 @@ module Clusters
end
def uninstall_command
- Gitlab::Kubernetes::Helm::DeleteCommand.new(
+ helm_command_module::DeleteCommand.new(
name: name,
rbac: cluster.platform_kubernetes_rbac?,
files: files,
diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb
index 7679296699f..55a9a0ccb81 100644
--- a/app/models/clusters/applications/prometheus.rb
+++ b/app/models/clusters/applications/prometheus.rb
@@ -67,7 +67,7 @@ module Clusters
end
def install_command
- Gitlab::Kubernetes::Helm::InstallCommand.new(
+ helm_command_module::InstallCommand.new(
name: name,
repository: repository,
version: VERSION,
@@ -79,7 +79,7 @@ module Clusters
end
def patch_command(values)
- ::Gitlab::Kubernetes::Helm::PatchCommand.new(
+ helm_command_module::PatchCommand.new(
name: name,
repository: repository,
version: version,
@@ -90,7 +90,7 @@ module Clusters
end
def uninstall_command
- Gitlab::Kubernetes::Helm::DeleteCommand.new(
+ helm_command_module::DeleteCommand.new(
name: name,
rbac: cluster.platform_kubernetes_rbac?,
files: files,
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index d07ea7b71dc..03f4caccccd 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.21.1'
+ VERSION = '0.22.0'
self.table_name = 'clusters_applications_runners'
@@ -30,7 +30,7 @@ module Clusters
end
def install_command
- Gitlab::Kubernetes::Helm::InstallCommand.new(
+ helm_command_module::InstallCommand.new(
name: name,
version: VERSION,
rbac: cluster.platform_kubernetes_rbac?,
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index b94ec3c6dea..3cf5542ae76 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -79,6 +79,9 @@ module Clusters
validates :cluster_type, presence: true
validates :domain, allow_blank: true, hostname: { allow_numeric_hostname: true }
validates :namespace_per_environment, inclusion: { in: [true, false] }
+ validates :helm_major_version, inclusion: { in: [2, 3] }
+
+ default_value_for :helm_major_version, 3
validate :restrict_modification, on: :update
validate :no_groups, unless: :group_type?
diff --git a/app/models/clusters/concerns/application_core.rb b/app/models/clusters/concerns/application_core.rb
index 760576ea1eb..b82b1887308 100644
--- a/app/models/clusters/concerns/application_core.rb
+++ b/app/models/clusters/concerns/application_core.rb
@@ -12,6 +12,17 @@ module Clusters
after_initialize :set_initial_status
+ def helm_command_module
+ case cluster.helm_major_version
+ when 3
+ Gitlab::Kubernetes::Helm::V3
+ when 2
+ Gitlab::Kubernetes::Helm::V2
+ else
+ raise "Invalid Helm major version"
+ end
+ end
+
def set_initial_status
return unless not_installable?
diff --git a/app/models/clusters/concerns/application_data.rb b/app/models/clusters/concerns/application_data.rb
index 22e597e9747..00aeb7669ad 100644
--- a/app/models/clusters/concerns/application_data.rb
+++ b/app/models/clusters/concerns/application_data.rb
@@ -4,7 +4,7 @@ module Clusters
module Concerns
module ApplicationData
def uninstall_command
- Gitlab::Kubernetes::Helm::DeleteCommand.new(
+ helm_command_module::DeleteCommand.new(
name: name,
rbac: cluster.platform_kubernetes_rbac?,
files: files
diff --git a/app/models/clusters/providers/aws.rb b/app/models/clusters/providers/aws.rb
index 35e8b751b3d..bfd01775620 100644
--- a/app/models/clusters/providers/aws.rb
+++ b/app/models/clusters/providers/aws.rb
@@ -5,9 +5,6 @@ module Clusters
class Aws < ApplicationRecord
include Gitlab::Utils::StrongMemoize
include Clusters::Concerns::ProviderStatus
- include IgnorableColumns
-
- ignore_column :created_by_user_id, remove_with: '13.4', remove_after: '2020-08-22'
self.table_name = 'cluster_providers_aws'
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 83400c9e533..80dd02981c1 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -335,7 +335,11 @@ class Commit
strong_memoize(:raw_signature_type) do
next unless @raw.instance_of?(Gitlab::Git::Commit)
- @raw.raw_commit.signature_type if defined? @raw.raw_commit.signature_type
+ if raw_commit_from_rugged? && gpg_commit.signature_text.present?
+ :PGP
+ elsif defined? @raw.raw_commit.signature_type
+ @raw.raw_commit.signature_type
+ end
end
end
@@ -347,7 +351,7 @@ class Commit
strong_memoize(:signature) do
case signature_type
when :PGP
- Gitlab::Gpg::Commit.new(self).signature
+ gpg_commit.signature
when :X509
Gitlab::X509::Commit.new(self).signature
else
@@ -356,6 +360,14 @@ class Commit
end
end
+ def raw_commit_from_rugged?
+ @raw.raw_commit.is_a?(Rugged::Commit)
+ end
+
+ def gpg_commit
+ @gpg_commit ||= Gitlab::Gpg::Commit.new(self)
+ end
+
def revert_branch_name
"revert-#{short_id}"
end
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 4498e08d754..ee9c2501bfc 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -205,13 +205,8 @@ class CommitStatus < ApplicationRecord
# 'rspec:linux: 1/10' => 'rspec:linux'
common_name = name.to_s.gsub(%r{\d+[\s:\/\\]+\d+\s*}, '')
- if ::Gitlab::Ci::Features.one_dimensional_matrix_enabled?
- # 'rspec:linux: [aws, max memory]' => 'rspec:linux', 'rspec:linux: [aws]' => 'rspec:linux'
- common_name.gsub!(%r{: \[.*\]\s*\z}, '')
- else
- # 'rspec:linux: [aws, max memory]' => 'rspec:linux', 'rspec:linux: [aws]' => 'rspec:linux: [aws]'
- common_name.gsub!(%r{: \[.*, .*\]\s*\z}, '')
- end
+ # 'rspec:linux: [aws, max memory]' => 'rspec:linux', 'rspec:linux: [aws]' => 'rspec:linux'
+ common_name.gsub!(%r{: \[.*\]\s*\z}, '')
common_name.strip!
common_name
diff --git a/app/models/concerns/atomic_internal_id.rb b/app/models/concerns/atomic_internal_id.rb
index 4a632e8cd0c..baa99fa5a7f 100644
--- a/app/models/concerns/atomic_internal_id.rb
+++ b/app/models/concerns/atomic_internal_id.rb
@@ -27,16 +27,42 @@ module AtomicInternalId
extend ActiveSupport::Concern
class_methods do
- def has_internal_id(column, scope:, init:, ensure_if: nil, track_if: nil, presence: true, backfill: false) # rubocop:disable Naming/PredicateName
- # We require init here to retain the ability to recalculate in the absence of a
- # InternalId record (we may delete records in `internal_ids` for example).
- raise "has_internal_id requires a init block, none given." unless init
+ def has_internal_id( # rubocop:disable Naming/PredicateName
+ column, scope:, init: :not_given, ensure_if: nil, track_if: nil,
+ presence: true, backfill: false, hook_names: :create)
+ raise "has_internal_id init must not be nil if given." if init.nil?
raise "has_internal_id needs to be defined on association." unless self.reflect_on_association(scope)
- before_validation :"track_#{scope}_#{column}!", on: :create, if: track_if
- before_validation :"ensure_#{scope}_#{column}!", on: :create, if: ensure_if
+ init = infer_init(scope) if init == :not_given
+ before_validation :"track_#{scope}_#{column}!", on: hook_names, if: track_if
+ before_validation :"ensure_#{scope}_#{column}!", on: hook_names, if: ensure_if
validates column, presence: presence
+ define_singleton_internal_id_methods(scope, column, init)
+ define_instance_internal_id_methods(scope, column, init, backfill)
+ end
+
+ private
+
+ def infer_init(scope)
+ case scope
+ when :project
+ AtomicInternalId.project_init(self)
+ when :group
+ AtomicInternalId.group_init(self)
+ else
+ # We require init here to retain the ability to recalculate in the absence of a
+ # InternalId record (we may delete records in `internal_ids` for example).
+ raise "has_internal_id - cannot infer init for scope: #{scope}"
+ end
+ end
+
+ # Defines instance methods:
+ # - ensure_{scope}_{column}!
+ # - track_{scope}_{column}!
+ # - reset_{scope}_{column}
+ # - {column}=
+ def define_instance_internal_id_methods(scope, column, init, backfill)
define_method("ensure_#{scope}_#{column}!") do
return if backfill && self.class.where(column => nil).exists?
@@ -103,19 +129,95 @@ module AtomicInternalId
read_attribute(column)
end
end
+
+ # Defines class methods:
+ #
+ # - with_{scope}_{column}_supply
+ # This method can be used to allocate a block of IID values during
+ # bulk operations (importing/copying, etc). This can be more efficient
+ # than creating instances one-by-one.
+ #
+ # Pass in a block that receives a `Supply` instance. To allocate a new
+ # IID value, call `Supply#next_value`.
+ #
+ # Example:
+ #
+ # MyClass.with_project_iid_supply(project) do |supply|
+ # attributes = MyClass.where(project: project).find_each do |record|
+ # record.attributes.merge(iid: supply.next_value)
+ # end
+ #
+ # bulk_insert(attributes)
+ # end
+ def define_singleton_internal_id_methods(scope, column, init)
+ define_singleton_method("with_#{scope}_#{column}_supply") do |scope_value, &block|
+ subject = find_by(scope => scope_value) || self
+ scope_attrs = ::AtomicInternalId.scope_attrs(scope_value)
+ usage = ::AtomicInternalId.scope_usage(self)
+
+ generator = InternalId::InternalIdGenerator.new(subject, scope_attrs, usage, init)
+
+ generator.with_lock do
+ supply = Supply.new(generator.record.last_value)
+ block.call(supply)
+ ensure
+ generator.track_greatest(supply.current_value) if supply
+ end
+ end
+ end
+ end
+
+ def self.scope_attrs(scope_value)
+ { scope_value.class.table_name.singularize.to_sym => scope_value } if scope_value
end
def internal_id_scope_attrs(scope)
scope_value = internal_id_read_scope(scope)
- { scope_value.class.table_name.singularize.to_sym => scope_value } if scope_value
+ ::AtomicInternalId.scope_attrs(scope_value)
end
def internal_id_scope_usage
- self.class.table_name.to_sym
+ ::AtomicInternalId.scope_usage(self.class)
+ end
+
+ def self.scope_usage(including_class)
+ including_class.table_name.to_sym
+ end
+
+ def self.project_init(klass, column_name = :iid)
+ ->(instance, scope) do
+ if instance
+ klass.where(project_id: instance.project_id).maximum(column_name)
+ elsif scope.present?
+ klass.where(**scope).maximum(column_name)
+ end
+ end
+ end
+
+ def self.group_init(klass, column_name = :iid)
+ ->(instance, scope) do
+ if instance
+ klass.where(group_id: instance.group_id).maximum(column_name)
+ elsif scope.present?
+ klass.where(group: scope[:namespace]).maximum(column_name)
+ end
+ end
end
def internal_id_read_scope(scope)
association(scope).reader
end
+
+ class Supply
+ attr_reader :current_value
+
+ def initialize(start_value)
+ @current_value = start_value
+ end
+
+ def next_value
+ @current_value += 1
+ end
+ end
end
diff --git a/app/models/concerns/enums/ci/pipeline.rb b/app/models/concerns/enums/ci/pipeline.rb
index f1bc43a12d8..bb8df37f649 100644
--- a/app/models/concerns/enums/ci/pipeline.rb
+++ b/app/models/concerns/enums/ci/pipeline.rb
@@ -53,6 +53,10 @@ module Enums
sources.except(*dangling_sources.keys)
end
+ def self.ci_and_parent_sources
+ ci_sources.merge(sources.slice(:parent_pipeline))
+ end
+
# Returns the `Hash` to use for creating the `config_sources` enum for
# `Ci::Pipeline`.
def self.config_sources
diff --git a/app/models/concerns/enums/internal_id.rb b/app/models/concerns/enums/internal_id.rb
index 2d51d232e93..f01bd60ef16 100644
--- a/app/models/concerns/enums/internal_id.rb
+++ b/app/models/concerns/enums/internal_id.rb
@@ -14,7 +14,8 @@ module Enums
operations_feature_flags: 6,
operations_user_lists: 7,
alert_management_alerts: 8,
- sprints: 9 # iterations
+ sprints: 9, # iterations
+ design_management_designs: 10
}
end
end
diff --git a/app/models/concerns/featurable.rb b/app/models/concerns/featurable.rb
index 60aa46ce04c..20b72957ec2 100644
--- a/app/models/concerns/featurable.rb
+++ b/app/models/concerns/featurable.rb
@@ -37,7 +37,8 @@ module Featurable
class_methods do
def set_available_features(available_features = [])
- @available_features = available_features
+ @available_features ||= []
+ @available_features += available_features
class_eval do
available_features.each do |feature|
diff --git a/app/models/concerns/from_union.rb b/app/models/concerns/from_union.rb
index e25d603b802..be6744f1b2a 100644
--- a/app/models/concerns/from_union.rb
+++ b/app/models/concerns/from_union.rb
@@ -37,27 +37,6 @@ module FromUnion
# 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_repository.rb b/app/models/concerns/has_repository.rb
index 978a54bdee7..3dea4a9f5fb 100644
--- a/app/models/concerns/has_repository.rb
+++ b/app/models/concerns/has_repository.rb
@@ -109,6 +109,11 @@ module HasRepository
Gitlab::RepositoryUrlBuilder.build(repository.full_path, protocol: :http)
end
+ # Is overridden in EE::Project for Geo support
+ def lfs_http_url_to_repo(_operation = nil)
+ http_url_to_repo
+ end
+
def web_url(only_path: nil)
Gitlab::UrlBuilder.build(self, only_path: only_path)
end
diff --git a/app/models/concerns/issue_available_features.rb b/app/models/concerns/issue_available_features.rb
index 6efb8103b7b..886db133a94 100644
--- a/app/models/concerns/issue_available_features.rb
+++ b/app/models/concerns/issue_available_features.rb
@@ -6,18 +6,25 @@
module IssueAvailableFeatures
extend ActiveSupport::Concern
- # EE only features are listed on EE::IssueAvailableFeatures
- def available_features_for_issue_types
- {}.with_indifferent_access
+ class_methods do
+ # EE only features are listed on EE::IssueAvailableFeatures
+ def available_features_for_issue_types
+ {}.with_indifferent_access
+ end
+ end
+
+ included do
+ scope :with_feature, ->(feature) { where(issue_type: available_features_for_issue_types[feature]) }
end
def issue_type_supports?(feature)
- unless available_features_for_issue_types.has_key?(feature)
+ unless self.class.available_features_for_issue_types.has_key?(feature)
raise ArgumentError, 'invalid feature'
end
- available_features_for_issue_types[feature].include?(issue_type)
+ self.class.available_features_for_issue_types[feature].include?(issue_type)
end
end
IssueAvailableFeatures.prepend_if_ee('EE::IssueAvailableFeatures')
+IssueAvailableFeatures::ClassMethods.prepend_if_ee('EE::IssueAvailableFeatures::ClassMethods')
diff --git a/app/models/concerns/mentionable/reference_regexes.rb b/app/models/concerns/mentionable/reference_regexes.rb
index 307d58a3a3c..5a5ce1809d0 100644
--- a/app/models/concerns/mentionable/reference_regexes.rb
+++ b/app/models/concerns/mentionable/reference_regexes.rb
@@ -22,7 +22,7 @@ module Mentionable
def self.default_pattern
strong_memoize(:default_pattern) do
issue_pattern = Issue.reference_pattern
- link_patterns = Regexp.union([Issue, Commit, MergeRequest, Epic].map(&:link_reference_pattern).compact)
+ link_patterns = Regexp.union([Issue, Commit, MergeRequest, Epic, Vulnerability].map(&:link_reference_pattern).compact)
reference_pattern(link_patterns, issue_pattern)
end
end
diff --git a/app/models/concerns/project_features_compatibility.rb b/app/models/concerns/project_features_compatibility.rb
index cedcf164a49..b69fb2931c3 100644
--- a/app/models/concerns/project_features_compatibility.rb
+++ b/app/models/concerns/project_features_compatibility.rb
@@ -88,3 +88,5 @@ module ProjectFeaturesCompatibility
project_feature.__send__(:write_attribute, field, value) # rubocop:disable GitlabSecurity/PublicSend
end
end
+
+ProjectFeaturesCompatibility.prepend_if_ee('EE::ProjectFeaturesCompatibility')
diff --git a/app/models/concerns/project_services_loggable.rb b/app/models/concerns/project_services_loggable.rb
index fecd77cdc98..e5385435138 100644
--- a/app/models/concerns/project_services_loggable.rb
+++ b/app/models/concerns/project_services_loggable.rb
@@ -16,8 +16,8 @@ module ProjectServicesLoggable
def build_message(message, params = {})
{
service_class: self.class.name,
- project_id: project.id,
- project_path: project.full_path,
+ project_id: project&.id,
+ project_path: project&.full_path,
message: message
}.merge(params)
end
diff --git a/app/models/concerns/protected_ref_access.rb b/app/models/concerns/protected_ref_access.rb
index d1e3d9b2aff..28dc3366e51 100644
--- a/app/models/concerns/protected_ref_access.rb
+++ b/app/models/concerns/protected_ref_access.rb
@@ -36,10 +36,12 @@ module ProtectedRefAccess
HUMAN_ACCESS_LEVELS[self.access_level]
end
- # CE access levels are always role-based,
- # where as EE allows groups and users too
+ def type
+ :role
+ end
+
def role?
- true
+ type == :role
end
def check_access(user)
diff --git a/app/models/concerns/storage/legacy_namespace.rb b/app/models/concerns/storage/legacy_namespace.rb
index 71b976c6f11..a82cf338039 100644
--- a/app/models/concerns/storage/legacy_namespace.rb
+++ b/app/models/concerns/storage/legacy_namespace.rb
@@ -90,7 +90,7 @@ module Storage
end
def old_repository_storages
- @old_repository_storage_paths ||= repository_storages
+ @old_repository_storage_paths ||= repository_storages(legacy_only: true)
end
def repository_storages(legacy_only: false)
diff --git a/app/models/concerns/todoable.rb b/app/models/concerns/todoable.rb
new file mode 100644
index 00000000000..d93ab463251
--- /dev/null
+++ b/app/models/concerns/todoable.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+# == Todoable concern
+#
+# Specify object types that supports todos.
+#
+# Used by Issue, MergeRequest, Design and Epic.
+#
+module Todoable
+end
diff --git a/app/models/concerns/triggerable_hooks.rb b/app/models/concerns/triggerable_hooks.rb
index b64a9e4f70b..325a5531926 100644
--- a/app/models/concerns/triggerable_hooks.rb
+++ b/app/models/concerns/triggerable_hooks.rb
@@ -13,7 +13,9 @@ module TriggerableHooks
job_hooks: :job_events,
pipeline_hooks: :pipeline_events,
wiki_page_hooks: :wiki_page_events,
- deployment_hooks: :deployment_events
+ deployment_hooks: :deployment_events,
+ feature_flag_hooks: :feature_flag_events,
+ release_hooks: :releases_events
}.freeze
extend ActiveSupport::Concern
diff --git a/app/models/container_expiration_policy.rb b/app/models/container_expiration_policy.rb
index 641d244b665..0441a5f0f5b 100644
--- a/app/models/container_expiration_policy.rb
+++ b/app/models/container_expiration_policy.rb
@@ -5,6 +5,13 @@ class ContainerExpirationPolicy < ApplicationRecord
include UsageStatistics
include EachBatch
+ POLICY_PARAMS = %w[
+ older_than
+ keep_n
+ name_regex
+ name_regex_keep
+ ].freeze
+
belongs_to :project, inverse_of: :container_expiration_policy
delegate :container_repositories, to: :project
@@ -14,14 +21,15 @@ class ContainerExpirationPolicy < ApplicationRecord
validates :cadence, presence: true, inclusion: { in: ->(_) { self.cadence_options.stringify_keys } }
validates :older_than, inclusion: { in: ->(_) { self.older_than_options.stringify_keys } }, allow_nil: true
validates :keep_n, inclusion: { in: ->(_) { self.keep_n_options.keys } }, allow_nil: true
+ validates :name_regex, presence: true, if: :enabled?
validates :name_regex, untrusted_regexp: true, if: :enabled?
validates :name_regex_keep, untrusted_regexp: true, if: :enabled?
scope :active, -> { where(enabled: true) }
scope :preloaded, -> { preload(project: [:route]) }
- def self.executable
- runnable_schedules.where(
+ def self.with_container_repositories
+ where(
'EXISTS (?)',
ContainerRepository.select(1)
.where(
@@ -67,4 +75,8 @@ class ContainerExpirationPolicy < ApplicationRecord
def disable!
update_attribute(:enabled, false)
end
+
+ def policy_params
+ attributes.slice(*POLICY_PARAMS)
+ end
end
diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb
index d97b8776085..4adbd37608f 100644
--- a/app/models/container_repository.rb
+++ b/app/models/container_repository.rb
@@ -3,6 +3,9 @@
class ContainerRepository < ApplicationRecord
include Gitlab::Utils::StrongMemoize
include Gitlab::SQL::Pattern
+ include EachBatch
+
+ WAITING_CLEANUP_STATUSES = %i[cleanup_scheduled cleanup_unfinished].freeze
belongs_to :project
@@ -10,6 +13,7 @@ class ContainerRepository < ApplicationRecord
validates :name, uniqueness: { scope: :project_id }
enum status: { delete_scheduled: 0, delete_failed: 1 }
+ enum expiration_policy_cleanup_status: { cleanup_unscheduled: 0, cleanup_scheduled: 1, cleanup_unfinished: 2, cleanup_ongoing: 3 }
delegate :client, to: :registry
@@ -24,7 +28,9 @@ class ContainerRepository < ApplicationRecord
ContainerRepository
.joins("INNER JOIN (#{project_scope.to_sql}) projects on projects.id=container_repositories.project_id")
end
+ scope :for_project_id, ->(project_id) { where(project_id: project_id) }
scope :search_by_name, ->(query) { fuzzy_search(query, [:name], use_minimum_char_limit: false) }
+ scope :waiting_for_cleanup, -> { where(expiration_policy_cleanup_status: WAITING_CLEANUP_STATUSES) }
def self.exists_by_path?(path)
where(
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index 643b4060ad6..ed22d4ba231 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -3,14 +3,21 @@
class CustomEmoji < ApplicationRecord
belongs_to :namespace, inverse_of: :custom_emoji
+ belongs_to :group, -> { where(type: 'Group') }, foreign_key: 'namespace_id'
+
+ # For now only external emoji are supported. See https://gitlab.com/gitlab-org/gitlab/-/issues/230467
+ validates :external, inclusion: { in: [true] }
+
+ validates :file, public_url: true, if: :external
+
validate :valid_emoji_name
- validates :namespace, presence: true
+ validates :group, presence: true
validates :name,
uniqueness: { scope: [:namespace_id, :name] },
presence: true,
length: { maximum: 36 },
- format: { with: /\A\w+\z/ }
+ format: { with: /\A([a-z0-9]+[-_]?)+[a-z0-9]+\z/ }
private
diff --git a/app/models/dependency_proxy.rb b/app/models/dependency_proxy.rb
new file mode 100644
index 00000000000..510a304ff17
--- /dev/null
+++ b/app/models/dependency_proxy.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+module DependencyProxy
+ def self.table_name_prefix
+ 'dependency_proxy_'
+ end
+end
diff --git a/app/models/dependency_proxy/blob.rb b/app/models/dependency_proxy/blob.rb
new file mode 100644
index 00000000000..3a81112340a
--- /dev/null
+++ b/app/models/dependency_proxy/blob.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class DependencyProxy::Blob < ApplicationRecord
+ include FileStoreMounter
+
+ belongs_to :group
+
+ validates :group, presence: true
+ validates :file, presence: true
+ validates :file_name, presence: true
+
+ mount_file_store_uploader DependencyProxy::FileUploader
+
+ def self.total_size
+ sum(:size)
+ end
+
+ def self.find_or_build(file_name)
+ find_or_initialize_by(file_name: file_name)
+ end
+end
diff --git a/app/models/dependency_proxy/group_setting.rb b/app/models/dependency_proxy/group_setting.rb
new file mode 100644
index 00000000000..bcf09b27129
--- /dev/null
+++ b/app/models/dependency_proxy/group_setting.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class DependencyProxy::GroupSetting < ApplicationRecord
+ belongs_to :group
+
+ validates :group, presence: true
+
+ default_value_for :enabled, true
+end
diff --git a/app/models/dependency_proxy/registry.rb b/app/models/dependency_proxy/registry.rb
new file mode 100644
index 00000000000..471d5be2600
--- /dev/null
+++ b/app/models/dependency_proxy/registry.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class DependencyProxy::Registry
+ AUTH_URL = 'https://auth.docker.io'.freeze
+ LIBRARY_URL = 'https://registry-1.docker.io/v2'.freeze
+
+ class << self
+ def auth_url(image)
+ "#{AUTH_URL}/token?service=registry.docker.io&scope=repository:#{image_path(image)}:pull"
+ end
+
+ def manifest_url(image, tag)
+ "#{LIBRARY_URL}/#{image_path(image)}/manifests/#{tag}"
+ end
+
+ def blob_url(image, blob_sha)
+ "#{LIBRARY_URL}/#{image_path(image)}/blobs/#{blob_sha}"
+ end
+
+ private
+
+ def image_path(image)
+ if image.include?('/')
+ image
+ else
+ "library/#{image}"
+ end
+ end
+ end
+end
diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb
index 793ea3c29c3..db5fd167781 100644
--- a/app/models/deploy_key.rb
+++ b/app/models/deploy_key.rb
@@ -6,9 +6,11 @@ class DeployKey < Key
has_many :deploy_keys_projects, inverse_of: :deploy_key, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :projects, through: :deploy_keys_projects
+ has_many :protected_branch_push_access_levels, class_name: '::ProtectedBranch::PushAccessLevel'
- scope :in_projects, ->(projects) { joins(:deploy_keys_projects).where('deploy_keys_projects.project_id in (?)', projects) }
- scope :are_public, -> { where(public: true) }
+ scope :in_projects, ->(projects) { joins(:deploy_keys_projects).where(deploy_keys_projects: { project_id: projects }) }
+ scope :with_write_access, -> { joins(:deploy_keys_projects).merge(DeployKeysProject.with_write_access) }
+ scope :are_public, -> { where(public: true) }
scope :with_projects, -> { includes(deploy_keys_projects: { project: [:route, namespace: :route] }) }
ignore_column :can_push, remove_after: '2019-12-15', remove_with: '12.6'
@@ -54,4 +56,11 @@ class DeployKey < Key
def projects_with_write_access
Project.with_route.where(id: deploy_keys_projects.with_write_access.select(:project_id))
end
+
+ def self.with_write_access_for_project(project, deploy_key: nil)
+ query = in_projects(project).with_write_access
+ query = query.where(id: deploy_key) if deploy_key
+
+ query
+ end
end
diff --git a/app/models/deploy_keys_project.rb b/app/models/deploy_keys_project.rb
index a9cc56a7246..40c66d5bc4c 100644
--- a/app/models/deploy_keys_project.rb
+++ b/app/models/deploy_keys_project.rb
@@ -6,7 +6,6 @@ class DeployKeysProject < ApplicationRecord
scope :without_project_deleted, -> { joins(:project).where(projects: { pending_delete: false }) }
scope :in_project, ->(project) { where(project: project) }
scope :with_write_access, -> { where(can_push: true) }
- scope :with_deploy_keys, -> { includes(:deploy_key) }
accepts_nested_attributes_for :deploy_key
diff --git a/app/models/deploy_token.rb b/app/models/deploy_token.rb
index 9355d73fae9..5fa9f2ef9f9 100644
--- a/app/models/deploy_token.rb
+++ b/app/models/deploy_token.rb
@@ -54,6 +54,10 @@ class DeployToken < ApplicationRecord
!revoked && !expired?
end
+ def deactivated?
+ !active?
+ end
+
def scopes
AVAILABLE_SCOPES.select { |token_scope| read_attribute(token_scope) }
end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 2d0d98136ec..36ac1bdb236 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -21,9 +21,7 @@ class Deployment < ApplicationRecord
has_one :deployment_cluster
- has_internal_id :iid, scope: :project, track_if: -> { !importing? }, init: ->(s) do
- Deployment.where(project: s.project).maximum(:iid) if s&.project
- end
+ has_internal_id :iid, scope: :project, track_if: -> { !importing? }
validates :sha, presence: true
validates :ref, presence: true
@@ -79,8 +77,6 @@ class Deployment < ApplicationRecord
after_transition any => :running do |deployment|
deployment.run_after_commit do
- next unless Feature.enabled?(:ci_send_deployment_hook_when_start, deployment.project)
-
Deployments::ExecuteHooksWorker.perform_async(id)
end
end
diff --git a/app/models/deployment_merge_request.rb b/app/models/deployment_merge_request.rb
index b67f96906f5..64a578e16bf 100644
--- a/app/models/deployment_merge_request.rb
+++ b/app/models/deployment_merge_request.rb
@@ -14,7 +14,12 @@ class DeploymentMergeRequest < ApplicationRecord
end
def self.deployed_to(name)
+ # We filter by project ID again so the query uses the index on
+ # (project_id, name), instead of using the index on
+ # (name varchar_pattern_ops). This results in better performance on
+ # GitLab.com.
where('environments.name = ?', name)
+ .where('environments.project_id = merge_requests.target_project_id')
end
def self.deployed_after(time)
diff --git a/app/models/design_management/design.rb b/app/models/design_management/design.rb
index 62e4bd6cebc..f5e52c04944 100644
--- a/app/models/design_management/design.rb
+++ b/app/models/design_management/design.rb
@@ -2,6 +2,7 @@
module DesignManagement
class Design < ApplicationRecord
+ include AtomicInternalId
include Importable
include Noteable
include Gitlab::FileTypeDetection
@@ -10,12 +11,15 @@ module DesignManagement
include Mentionable
include WhereComposite
include RelativePositioning
+ include Todoable
+ include Participable
belongs_to :project, inverse_of: :designs
belongs_to :issue
has_many :actions
has_many :versions, through: :actions, class_name: 'DesignManagement::Version', inverse_of: :designs
+ has_many :authors, -> { distinct }, through: :versions, class_name: 'User'
# This is a polymorphic association, so we can't count on FK's to delete the
# data
has_many :notes, as: :noteable, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
@@ -23,6 +27,10 @@ module DesignManagement
has_many :events, as: :target, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
+ has_internal_id :iid, scope: :project, presence: true,
+ hook_names: %i[create update], # Deal with old records
+ track_if: -> { !importing? }
+
validates :project, :filename, presence: true
validates :issue, presence: true, unless: :importing?
validates :filename, uniqueness: { scope: :issue_id }, length: { maximum: 255 }
@@ -30,6 +38,9 @@ module DesignManagement
alias_attribute :title, :filename
+ participant :authors
+ participant :notes_with_associations
+
# Pre-fetching scope to include the data necessary to construct a
# reference using `to_reference`.
scope :for_reference, -> { includes(issue: [{ project: [:route, :namespace] }]) }
diff --git a/app/models/design_management/version.rb b/app/models/design_management/version.rb
index 55c9084caf2..49aec8b9720 100644
--- a/app/models/design_management/version.rb
+++ b/app/models/design_management/version.rb
@@ -43,10 +43,7 @@ module DesignManagement
validates :sha, presence: true
validates :sha, uniqueness: { case_sensitive: false, scope: :issue_id }
validates :author, presence: true
- # We are not validating the issue object as it incurs an extra query to fetch
- # the record from the DB. Instead, we rely on the foreign key constraint to
- # ensure referential integrity.
- validates :issue_id, presence: true, unless: :importing?
+ validates :issue, presence: true, unless: :importing?
sha_attribute :sha
diff --git a/app/models/diff_viewer/image.rb b/app/models/diff_viewer/image.rb
index 62a3446a7b6..fca6c664196 100644
--- a/app/models/diff_viewer/image.rb
+++ b/app/models/diff_viewer/image.rb
@@ -10,5 +10,13 @@ module DiffViewer
self.binary = true
self.switcher_icon = 'doc-image'
self.switcher_title = _('image diff')
+
+ def self.can_render?(diff_file, verify_binary: true)
+ # When both blobs are missing, we often still have a textual diff that can
+ # be displayed
+ return false if diff_file.old_blob.nil? && diff_file.new_blob.nil?
+
+ super
+ end
end
end
diff --git a/app/models/discussion.rb b/app/models/discussion.rb
index 793cdb5dece..70aa02063cc 100644
--- a/app/models/discussion.rb
+++ b/app/models/discussion.rb
@@ -16,6 +16,7 @@ class Discussion
:commit_id,
:confidential?,
:for_commit?,
+ :for_design?,
:for_merge_request?,
:noteable_ability_name,
:to_ability_name,
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 66613869915..deded3eeae0 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -305,6 +305,10 @@ class Environment < ApplicationRecord
latest_opened_most_severe_alert.present?
end
+ def has_running_deployments?
+ all_deployments.running.exists?
+ end
+
def metrics
prometheus_adapter.query(:environment, self) if has_metrics_and_can_query?
end
@@ -395,7 +399,7 @@ class Environment < ApplicationRecord
# Overrides ReactiveCaching default to activate limit checking behind a FF
def reactive_cache_limit_enabled?
- Feature.enabled?(:reactive_caching_limit_environment, project)
+ Feature.enabled?(:reactive_caching_limit_environment, project, default_enabled: true)
end
end
diff --git a/app/models/experiment.rb b/app/models/experiment.rb
index 25640385536..f179a1fc6ce 100644
--- a/app/models/experiment.rb
+++ b/app/models/experiment.rb
@@ -2,26 +2,17 @@
class Experiment < ApplicationRecord
has_many :experiment_users
- has_many :users, through: :experiment_users
- has_many :control_group_users, -> { merge(ExperimentUser.control) }, through: :experiment_users, source: :user
- has_many :experimental_group_users, -> { merge(ExperimentUser.experimental) }, through: :experiment_users, source: :user
validates :name, presence: true, uniqueness: true, length: { maximum: 255 }
def self.add_user(name, group_type, user)
- experiment = find_or_create_by(name: name)
+ return unless experiment = find_or_create_by(name: name)
- return unless experiment
- return if experiment.experiment_users.where(user: user).exists?
-
- group_type == ::Gitlab::Experimentation::GROUP_CONTROL ? experiment.add_control_user(user) : experiment.add_experimental_user(user)
- end
-
- def add_control_user(user)
- control_group_users << user
+ experiment.record_user_and_group(user, group_type)
end
- def add_experimental_user(user)
- experimental_group_users << user
+ # Create or update the recorded experiment_user row for the user in this experiment.
+ def record_user_and_group(user, group_type)
+ experiment_users.find_or_initialize_by(user: user).update!(group_type: group_type)
end
end
diff --git a/app/models/experiment_user.rb b/app/models/experiment_user.rb
index 1571b0c3439..e447becc1bd 100644
--- a/app/models/experiment_user.rb
+++ b/app/models/experiment_user.rb
@@ -1,10 +1,14 @@
# frozen_string_literal: true
class ExperimentUser < ApplicationRecord
+ include ::Gitlab::Experimentation::GroupTypes
+
belongs_to :experiment
belongs_to :user
- enum group_type: { control: 0, experimental: 1 }
+ enum group_type: { GROUP_CONTROL => 0, GROUP_EXPERIMENTAL => 1 }
+ validates :experiment_id, presence: true
+ validates :user_id, presence: true
validates :group_type, presence: true
end
diff --git a/app/models/group.rb b/app/models/group.rb
index 74f7efd253d..3509299a579 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -71,6 +71,9 @@ class Group < Namespace
has_many :group_deploy_tokens
has_many :deploy_tokens, through: :group_deploy_tokens
+ has_one :dependency_proxy_setting, class_name: 'DependencyProxy::GroupSetting'
+ has_many :dependency_proxy_blobs, class_name: 'DependencyProxy::Blob'
+
accepts_nested_attributes_for :variables, allow_destroy: true
validate :visibility_level_allowed_by_projects
@@ -98,6 +101,19 @@ class Group < Namespace
scope :by_id, ->(groups) { where(id: groups) }
+ scope :for_authorized_group_members, -> (user_ids) do
+ joins(:group_members)
+ .where("members.user_id IN (?)", user_ids)
+ .where("access_level >= ?", Gitlab::Access::GUEST)
+ end
+
+ scope :for_authorized_project_members, -> (user_ids) do
+ joins(projects: :project_authorizations)
+ .where("project_authorizations.user_id IN (?)", user_ids)
+ end
+
+ delegate :default_branch_name, to: :namespace_settings
+
class << self
def sort_by_attribute(method)
if method == 'storage_size_desc'
@@ -190,6 +206,10 @@ class Group < Namespace
::Gitlab.config.packages.enabled
end
+ def dependency_proxy_feature_available?
+ ::Gitlab.config.dependency_proxy.enabled
+ end
+
def notification_email_for(user)
# Finds the closest notification_setting with a `notification_email`
notification_settings = notification_settings_for(user, hierarchy_order: :asc)
@@ -571,12 +591,16 @@ class Group < Namespace
ancestor_settings.allow_mfa_for_subgroups
end
+ def has_project_with_service_desk_enabled?
+ Gitlab::ServiceDesk.supported? && all_projects.service_desk_enabled.exists?
+ end
+
private
def update_two_factor_requirement
return unless saved_change_to_require_two_factor_authentication? || saved_change_to_two_factor_grace_period?
- members_with_descendants.find_each(&:update_two_factor_requirement)
+ direct_and_indirect_members.find_each(&:update_two_factor_requirement)
end
def path_changed_hook
diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb
index 2d1bdecc770..b625a70b444 100644
--- a/app/models/hooks/project_hook.rb
+++ b/app/models/hooks/project_hook.rb
@@ -18,7 +18,9 @@ class ProjectHook < WebHook
:job_hooks,
:pipeline_hooks,
:wiki_page_hooks,
- :deployment_hooks
+ :deployment_hooks,
+ :feature_flag_hooks,
+ :release_hooks
]
belongs_to :project
diff --git a/app/models/instance_metadata.rb b/app/models/instance_metadata.rb
new file mode 100644
index 00000000000..96622d0b1b3
--- /dev/null
+++ b/app/models/instance_metadata.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class InstanceMetadata
+ attr_reader :version, :revision
+
+ def initialize(version: Gitlab::VERSION, revision: Gitlab.revision)
+ @version = version
+ @revision = revision
+ end
+end
diff --git a/app/models/internal_id.rb b/app/models/internal_id.rb
index 4c0469d849a..c735e593da7 100644
--- a/app/models/internal_id.rb
+++ b/app/models/internal_id.rb
@@ -61,13 +61,13 @@ class InternalId < ApplicationRecord
class << self
def track_greatest(subject, scope, usage, new_value, init)
- InternalIdGenerator.new(subject, scope, usage)
- .track_greatest(init, new_value)
+ InternalIdGenerator.new(subject, scope, usage, init)
+ .track_greatest(new_value)
end
def generate_next(subject, scope, usage, init)
- InternalIdGenerator.new(subject, scope, usage)
- .generate(init)
+ InternalIdGenerator.new(subject, scope, usage, init)
+ .generate
end
def reset(subject, scope, usage, value)
@@ -99,15 +99,18 @@ class InternalId < ApplicationRecord
# 4) In the absence of a record in the internal_ids table, one will be created
# and last_value will be calculated on the fly.
#
- # subject: The instance we're generating an internal id for. Gets passed to init if called.
+ # subject: The instance or class we're generating an internal id for.
# scope: Attributes that define the scope for id generation.
+ # Valid keys are `project/project_id` and `namespace/namespace_id`.
# usage: Symbol to define the usage of the internal id, see InternalId.usages
- attr_reader :subject, :scope, :scope_attrs, :usage
+ # init: Proc that accepts the subject and the scope and returns Integer|NilClass
+ attr_reader :subject, :scope, :scope_attrs, :usage, :init
- def initialize(subject, scope, usage)
+ def initialize(subject, scope, usage, init = nil)
@subject = subject
@scope = scope
@usage = usage
+ @init = init
raise ArgumentError, 'Scope is not well-defined, need at least one column for scope (given: 0)' if scope.empty?
@@ -119,13 +122,13 @@ class InternalId < ApplicationRecord
# Generates next internal id and returns it
# init: Block that gets called to initialize InternalId record if not present
# Make sure to not throw exceptions in the absence of records (if this is expected).
- def generate(init)
+ def generate
subject.transaction do
# Create a record in internal_ids if one does not yet exist
# and increment its last value
#
# Note this will acquire a ROW SHARE lock on the InternalId record
- (lookup || create_record(init)).increment_and_save!
+ record.increment_and_save!
end
end
@@ -148,12 +151,20 @@ class InternalId < ApplicationRecord
# and set its new_value if it is higher than the current last_value
#
# Note this will acquire a ROW SHARE lock on the InternalId record
- def track_greatest(init, new_value)
+ def track_greatest(new_value)
subject.transaction do
- (lookup || create_record(init)).track_greatest_and_save!(new_value)
+ record.track_greatest_and_save!(new_value)
end
end
+ def record
+ @record ||= (lookup || create_record)
+ end
+
+ def with_lock(&block)
+ record.with_lock(&block)
+ end
+
private
# Retrieve InternalId record for (project, usage) combination, if it exists
@@ -171,12 +182,16 @@ class InternalId < ApplicationRecord
# was faster in doing this, we'll realize once we hit the unique key constraint
# violation. We can safely roll-back the nested transaction and perform
# a lookup instead to retrieve the record.
- def create_record(init)
+ def create_record
+ raise ArgumentError, 'Cannot initialize without init!' unless init
+
+ instance = subject.is_a?(::Class) ? nil : subject
+
subject.transaction(requires_new: true) do
InternalId.create!(
**scope,
usage: usage_value,
- last_value: init.call(subject) || 0
+ last_value: init.call(instance, scope) || 0
)
end
rescue ActiveRecord::RecordNotUnique
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 5291b7890b6..7dc18cacd7c 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -21,6 +21,7 @@ class Issue < ApplicationRecord
include IdInOrdered
include Presentable
include IssueAvailableFeatures
+ include Todoable
DueDateStruct = Struct.new(:title, :name).freeze
NoDueDate = DueDateStruct.new('No Due Date', '0').freeze
@@ -47,7 +48,7 @@ class Issue < ApplicationRecord
belongs_to :moved_to, class_name: 'Issue'
has_one :moved_from, class_name: 'Issue', foreign_key: :moved_to_id
- has_internal_id :iid, scope: :project, track_if: -> { !importing? }, init: ->(s) { s&.project&.issues&.maximum(:iid) }
+ has_internal_id :iid, scope: :project, track_if: -> { !importing? }
has_many :events, as: :target, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
diff --git a/app/models/issue_link.rb b/app/models/issue_link.rb
index 9740b009396..5448ebdf50b 100644
--- a/app/models/issue_link.rb
+++ b/app/models/issue_link.rb
@@ -10,6 +10,7 @@ class IssueLink < ApplicationRecord
validates :target, presence: true
validates :source, uniqueness: { scope: :target_id, message: 'is already related' }
validate :check_self_relation
+ validate :check_opposite_relation
scope :for_source_issue, ->(issue) { where(source_id: issue.id) }
scope :for_target_issue, ->(issue) { where(target_id: issue.id) }
@@ -33,6 +34,14 @@ class IssueLink < ApplicationRecord
errors.add(:source, 'cannot be related to itself')
end
end
+
+ def check_opposite_relation
+ return unless source && target
+
+ if IssueLink.find_by(source: target, target: source)
+ errors.add(:source, 'is already related to this issue')
+ end
+ end
end
IssueLink.prepend_if_ee('EE::IssueLink')
diff --git a/app/models/issues/csv_import.rb b/app/models/issues/csv_import.rb
new file mode 100644
index 00000000000..d141f126ec9
--- /dev/null
+++ b/app/models/issues/csv_import.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+class Issues::CsvImport < ApplicationRecord
+ self.table_name = 'csv_issue_imports'
+
+ belongs_to :project, optional: false
+ belongs_to :user, optional: false
+end
diff --git a/app/models/iteration.rb b/app/models/iteration.rb
index bd245de411c..ba7cd973e9d 100644
--- a/app/models/iteration.rb
+++ b/app/models/iteration.rb
@@ -17,8 +17,8 @@ class Iteration < ApplicationRecord
belongs_to :project
belongs_to :group
- has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.iterations&.maximum(:iid) }
- has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.iterations&.maximum(:iid) }
+ has_internal_id :iid, scope: :project
+ has_internal_id :iid, scope: :group
validates :start_date, presence: true
validates :due_date, presence: true
diff --git a/app/models/member.rb b/app/models/member.rb
index 498e03b2c1a..687830f5267 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -96,6 +96,8 @@ class Member < ApplicationRecord
scope :owners, -> { active.where(access_level: OWNER) }
scope :owners_and_maintainers, -> { active.where(access_level: [OWNER, MAINTAINER]) }
scope :with_user, -> (user) { where(user: user) }
+ scope :with_user_by_email, -> (email) { left_join_users.where(users: { email: email } ) }
+
scope :preload_user_and_notification_settings, -> { preload(user: :notification_settings) }
scope :with_source_id, ->(source_id) { where(source_id: source_id) }
@@ -417,6 +419,10 @@ class Member < ApplicationRecord
invite? && user_id.nil?
end
+ def created_by_name
+ created_by&.name
+ end
+
private
def send_invite
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 34958936c9f..2bbcdbbe5ce 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -21,6 +21,7 @@ class GroupMember < Member
scope :of_groups, ->(groups) { where(source_id: groups.select(:id)) }
scope :of_ldap_type, -> { where(ldap: true) }
scope :count_users_by_group_id, -> { group(:source_id).count }
+ scope :with_user, -> (user) { where(user: user) }
after_create :update_two_factor_requirement, unless: :invite?
after_destroy :update_two_factor_requirement, unless: :invite?
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 24541ba3218..d379f85bc15 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -22,6 +22,7 @@ class MergeRequest < ApplicationRecord
include StateEventable
include ApprovableBase
include IdInOrdered
+ include Todoable
extend ::Gitlab::Utils::Override
@@ -40,7 +41,14 @@ class MergeRequest < ApplicationRecord
belongs_to :merge_user, class_name: "User"
belongs_to :iteration, foreign_key: 'sprint_id'
- has_internal_id :iid, scope: :target_project, track_if: -> { !importing? }, init: ->(s) { s&.target_project&.merge_requests&.maximum(:iid) }
+ has_internal_id :iid, scope: :target_project, track_if: -> { !importing? },
+ init: ->(mr, scope) do
+ if mr
+ mr.target_project&.merge_requests&.maximum(:iid)
+ elsif scope[:project]
+ where(target_project: scope[:project]).maximum(:iid)
+ end
+ end
has_many :merge_request_diffs
has_many :merge_request_context_commits, inverse_of: :merge_request
@@ -48,6 +56,7 @@ class MergeRequest < ApplicationRecord
has_one :merge_request_diff,
-> { order('merge_request_diffs.id DESC') }, inverse_of: :merge_request
+ has_one :cleanup_schedule, inverse_of: :merge_request
belongs_to :latest_merge_request_diff, class_name: 'MergeRequestDiff'
manual_inverse_association :latest_merge_request_diff, :merge_request
@@ -293,6 +302,7 @@ class MergeRequest < ApplicationRecord
scope :preload_author, -> { preload(:author) }
scope :preload_approved_by_users, -> { preload(:approved_by_users) }
scope :preload_metrics, -> (relation) { preload(metrics: relation) }
+ scope :with_web_entity_associations, -> { preload(:author, :target_project) }
scope :with_auto_merge_enabled, -> do
with_state(:opened).where(auto_merge_enabled: true)
@@ -302,6 +312,8 @@ class MergeRequest < ApplicationRecord
includes(:metrics)
end
+ scope :with_jira_issue_keys, -> { where('title ~ :regex OR merge_requests.description ~ :regex', regex: Gitlab::Regex.jira_issue_key_regex.source) }
+
after_save :keep_around_commit, unless: :importing?
alias_attribute :project, :target_project
diff --git a/app/models/merge_request/cleanup_schedule.rb b/app/models/merge_request/cleanup_schedule.rb
new file mode 100644
index 00000000000..79817269be2
--- /dev/null
+++ b/app/models/merge_request/cleanup_schedule.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class MergeRequest::CleanupSchedule < ApplicationRecord
+ belongs_to :merge_request, inverse_of: :cleanup_schedule
+
+ validates :scheduled_at, presence: true
+
+ def self.scheduled_merge_request_ids(limit)
+ where('completed_at IS NULL AND scheduled_at <= NOW()')
+ .order('scheduled_at DESC')
+ .limit(limit)
+ .pluck(:merge_request_id)
+ end
+end
diff --git a/app/models/merge_request_diff_file.rb b/app/models/merge_request_diff_file.rb
index 55ff4250c2d..817e77bf12f 100644
--- a/app/models/merge_request_diff_file.rb
+++ b/app/models/merge_request_diff_file.rb
@@ -8,6 +8,10 @@ class MergeRequestDiffFile < ApplicationRecord
belongs_to :merge_request_diff, inverse_of: :merge_request_diff_files
alias_attribute :index, :relative_order
+ scope :by_paths, ->(paths) do
+ where("new_path in (?) OR old_path in (?)", paths, paths)
+ end
+
def utf8_diff
return '' if diff.blank?
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 0a315ba8db2..c8776be5e4a 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -12,8 +12,8 @@ class Milestone < ApplicationRecord
has_many :milestone_releases
has_many :releases, through: :milestone_releases
- has_internal_id :iid, scope: :project, track_if: -> { !importing? }, init: ->(s) { s&.project&.milestones&.maximum(:iid) }
- has_internal_id :iid, scope: :group, track_if: -> { !importing? }, init: ->(s) { s&.group&.milestones&.maximum(:iid) }
+ has_internal_id :iid, scope: :project, track_if: -> { !importing? }
+ has_internal_id :iid, scope: :group, track_if: -> { !importing? }
has_many :events, as: :target, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index fd31042c2f6..232d0a6b05d 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -96,7 +96,8 @@ class Namespace < ApplicationRecord
'COALESCE(SUM(ps.snippets_size), 0) AS snippets_size',
'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.packages_size), 0) AS packages_size',
+ 'COALESCE(SUM(ps.uploads_size), 0) AS uploads_size'
)
end
@@ -117,8 +118,12 @@ class Namespace < ApplicationRecord
# query - The search query as a String.
#
# Returns an ActiveRecord::Relation.
- def search(query)
- fuzzy_search(query, [:name, :path])
+ def search(query, include_parents: false)
+ if include_parents
+ where(id: Route.for_routable_type(Namespace.name).fuzzy_search(query, [Route.arel_table[:path], Route.arel_table[:name]]).select(:source_id))
+ else
+ fuzzy_search(query, [:path, :name])
+ end
end
def clean_path(path)
@@ -284,7 +289,8 @@ class Namespace < ApplicationRecord
# that belongs to this namespace
def all_projects
if Feature.enabled?(:recursive_approach_for_all_projects)
- Project.where(namespace: self_and_descendants)
+ namespace = user? ? self : self_and_descendants
+ Project.where(namespace: namespace)
else
Project.inside_path(full_path)
end
@@ -357,7 +363,7 @@ class Namespace < ApplicationRecord
def pages_virtual_domain
Pages::VirtualDomain.new(
- all_projects_with_pages.includes(:route, :project_feature),
+ all_projects_with_pages.includes(:route, :project_feature, pages_metadatum: :pages_deployment),
trim_prefix: full_path
)
end
@@ -388,7 +394,6 @@ class Namespace < ApplicationRecord
end
def changing_shared_runners_enabled_is_allowed
- return unless Feature.enabled?(:disable_shared_runners_on_group, default_enabled: true)
return unless new_record? || changes.has_key?(:shared_runners_enabled)
if shared_runners_enabled && has_parent? && parent.shared_runners_setting == 'disabled_and_unoverridable'
@@ -397,7 +402,6 @@ class Namespace < ApplicationRecord
end
def changing_allow_descendants_override_disabled_shared_runners_is_allowed
- return unless Feature.enabled?(:disable_shared_runners_on_group, default_enabled: true)
return unless new_record? || changes.has_key?(:allow_descendants_override_disabled_shared_runners)
if shared_runners_enabled && !new_record?
diff --git a/app/models/namespace/root_storage_statistics.rb b/app/models/namespace/root_storage_statistics.rb
index 5723a823e98..a3df82998c4 100644
--- a/app/models/namespace/root_storage_statistics.rb
+++ b/app/models/namespace/root_storage_statistics.rb
@@ -11,6 +11,7 @@ class Namespace::RootStorageStatistics < ApplicationRecord
packages_size
#{SNIPPETS_SIZE_STAT_NAME}
pipeline_artifacts_size
+ uploads_size
).freeze
self.primary_key = :namespace_id
@@ -50,7 +51,8 @@ class Namespace::RootStorageStatistics < ApplicationRecord
'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.pipeline_artifacts_size), 0) AS pipeline_artifacts_size'
+ 'COALESCE(SUM(ps.pipeline_artifacts_size), 0) AS pipeline_artifacts_size',
+ 'COALESCE(SUM(ps.uploads_size), 0) AS uploads_size'
)
end
diff --git a/app/models/namespace_setting.rb b/app/models/namespace_setting.rb
index 6f31208f28b..50844403d7f 100644
--- a/app/models/namespace_setting.rb
+++ b/app/models/namespace_setting.rb
@@ -6,10 +6,18 @@ class NamespaceSetting < ApplicationRecord
validate :default_branch_name_content
validate :allow_mfa_for_group
+ before_validation :normalize_default_branch_name
+
NAMESPACE_SETTINGS_PARAMS = [:default_branch_name].freeze
self.primary_key = :namespace_id
+ private
+
+ def normalize_default_branch_name
+ self.default_branch_name = nil if default_branch_name.blank?
+ end
+
def default_branch_name_content
return if default_branch_name.nil?
diff --git a/app/models/note.rb b/app/models/note.rb
index 954843505d4..cfdac6c432f 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -197,8 +197,8 @@ class Note < ApplicationRecord
.map(&:position)
end
- def count_for_collection(ids, type)
- user.select('noteable_id', 'COUNT(*) as count')
+ def count_for_collection(ids, type, count_column = 'COUNT(*) as count')
+ user.select(:noteable_id, count_column)
.group(:noteable_id)
.where(noteable_type: type, noteable_id: ids)
end
diff --git a/app/models/operations/feature_flag.rb b/app/models/operations/feature_flag.rb
index 104338b80d1..442f9d36c43 100644
--- a/app/models/operations/feature_flag.rb
+++ b/app/models/operations/feature_flag.rb
@@ -2,6 +2,7 @@
module Operations
class FeatureFlag < ApplicationRecord
+ include AfterCommitQueue
include AtomicInternalId
include IidRoutes
include Limitable
@@ -12,7 +13,7 @@ module Operations
belongs_to :project
- has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.operations_feature_flags&.maximum(:iid) }
+ has_internal_id :iid, scope: :project
default_value_for :active, true
@@ -77,6 +78,22 @@ module Operations
Ability.issues_readable_by_user(issues, current_user)
end
+ def execute_hooks(current_user)
+ run_after_commit do
+ feature_flag_data = Gitlab::DataBuilder::FeatureFlag.build(self, current_user)
+ project.execute_hooks(feature_flag_data, :feature_flag_hooks)
+ end
+ end
+
+ def hook_attrs
+ {
+ id: id,
+ name: name,
+ description: description,
+ active: active
+ }
+ end
+
private
def version_associations
diff --git a/app/models/operations/feature_flags/user_list.rb b/app/models/operations/feature_flags/user_list.rb
index b9bdcb59d5f..3e492eaa892 100644
--- a/app/models/operations/feature_flags/user_list.rb
+++ b/app/models/operations/feature_flags/user_list.rb
@@ -5,6 +5,7 @@ module Operations
class UserList < ApplicationRecord
include AtomicInternalId
include IidRoutes
+ include ::Gitlab::SQL::Pattern
self.table_name = 'operations_user_lists'
@@ -12,7 +13,7 @@ module Operations
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
+ has_internal_id :iid, scope: :project, presence: true
validates :project, presence: true
validates :name,
@@ -23,6 +24,10 @@ module Operations
before_destroy :ensure_no_associated_strategies
+ scope :for_name_like, -> (query) do
+ fuzzy_search(query, [:name], use_minimum_char_limit: false)
+ end
+
private
def ensure_no_associated_strategies
diff --git a/app/models/packages/build_info.rb b/app/models/packages/build_info.rb
index df8cf68490e..1b0f0ed8ffd 100644
--- a/app/models/packages/build_info.rb
+++ b/app/models/packages/build_info.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
class Packages::BuildInfo < ApplicationRecord
- belongs_to :package, inverse_of: :build_info
+ belongs_to :package, inverse_of: :build_infos
belongs_to :pipeline, class_name: 'Ci::Pipeline'
end
diff --git a/app/models/packages/event.rb b/app/models/packages/event.rb
index f1d0af64ccd..959c94931ec 100644
--- a/app/models/packages/event.rb
+++ b/app/models/packages/event.rb
@@ -3,6 +3,7 @@
class Packages::Event < ApplicationRecord
belongs_to :package, optional: true
+ UNIQUE_EVENTS_ALLOWED = %i[push_package delete_package pull_package].freeze
EVENT_SCOPES = ::Packages::Package.package_types.merge(container: 1000, tag: 1001).freeze
enum event_scope: EVENT_SCOPES
@@ -22,4 +23,20 @@ class Packages::Event < ApplicationRecord
}
enum originator_type: { user: 0, deploy_token: 1, guest: 2 }
+
+ def self.allowed_event_name(event_scope, event_type, originator)
+ return unless event_allowed?(event_scope, event_type, originator)
+
+ # remove `package` from the event name to avoid issues with HLLRedisCounter class parsing
+ "i_package_#{event_scope}_#{originator}_#{event_type.gsub(/_packages?/, "")}"
+ end
+
+ # Remove some of the events, for now, so we don't hammer Redis too hard.
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/280770
+ def self.event_allowed?(event_scope, event_type, originator)
+ return false if originator.to_sym == :guest
+ return true if UNIQUE_EVENTS_ALLOWED.include?(event_type.to_sym)
+
+ false
+ end
end
diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb
index b8f8d45ff62..60aab0a7222 100644
--- a/app/models/packages/package.rb
+++ b/app/models/packages/package.rb
@@ -3,6 +3,7 @@ class Packages::Package < ApplicationRecord
include Sortable
include Gitlab::SQL::Pattern
include UsageStatistics
+ include Gitlab::Utils::StrongMemoize
belongs_to :project
belongs_to :creator, class_name: 'User'
@@ -16,7 +17,8 @@ class Packages::Package < ApplicationRecord
has_one :maven_metadatum, inverse_of: :package, class_name: 'Packages::Maven::Metadatum'
has_one :nuget_metadatum, inverse_of: :package, class_name: 'Packages::Nuget::Metadatum'
has_one :composer_metadatum, inverse_of: :package, class_name: 'Packages::Composer::Metadatum'
- has_one :build_info, inverse_of: :package
+ has_many :build_infos, inverse_of: :package
+ has_many :pipelines, through: :build_infos
accepts_nested_attributes_for :conan_metadatum
accepts_nested_attributes_for :maven_metadatum
@@ -38,12 +40,13 @@ class Packages::Package < ApplicationRecord
validates :name, format: { with: Gitlab::Regex.conan_recipe_component_regex }, if: :conan?
validates :name, format: { with: Gitlab::Regex.generic_package_name_regex }, if: :generic?
validates :name, format: { with: Gitlab::Regex.nuget_package_name_regex }, if: :nuget?
- validates :version, format: { with: Gitlab::Regex.semver_regex }, if: :npm?
validates :version, format: { with: Gitlab::Regex.nuget_version_regex }, if: :nuget?
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, format: { with: Gitlab::Regex.prefixed_semver_regex }, if: :golang?
+ validates :version, format: { with: Gitlab::Regex.semver_regex }, if: -> { composer_tag_version? || npm? }
+
validates :version,
presence: true,
format: { with: Gitlab::Regex.generic_package_version_regex },
@@ -58,7 +61,7 @@ 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_build_info, -> { includes(pipelines: :user) }
scope :including_project_route, -> { includes(project: { namespace: :route }) }
scope :including_tags, -> { includes(:tags) }
@@ -165,8 +168,16 @@ class Packages::Package < ApplicationRecord
.order(:version)
end
+ # Technical debt: to be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/281937
+ def original_build_info
+ strong_memoize(:original_build_info) do
+ build_infos.first
+ end
+ end
+
+ # Technical debt: to be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/281937
def pipeline
- build_info&.pipeline
+ original_build_info&.pipeline
end
def tag_names
@@ -175,6 +186,10 @@ class Packages::Package < ApplicationRecord
private
+ def composer_tag_version?
+ composer? && !Gitlab::Regex.composer_dev_version_regex.match(version.to_s)
+ end
+
def valid_conan_package_recipe
recipe_exists = project.packages
.conan
diff --git a/app/models/packages/package_file.rb b/app/models/packages/package_file.rb
index 4ebd96797db..d68f75140ac 100644
--- a/app/models/packages/package_file.rb
+++ b/app/models/packages/package_file.rb
@@ -8,6 +8,8 @@ class Packages::PackageFile < ApplicationRecord
belongs_to :package
has_one :conan_file_metadatum, inverse_of: :package_file, class_name: 'Packages::Conan::FileMetadatum'
+ has_many :package_file_build_infos, inverse_of: :package_file, class_name: 'Packages::PackageFileBuildInfo'
+ has_many :pipelines, through: :package_file_build_infos
accepts_nested_attributes_for :conan_file_metadatum
diff --git a/app/models/packages/package_file_build_info.rb b/app/models/packages/package_file_build_info.rb
new file mode 100644
index 00000000000..5cabed446aa
--- /dev/null
+++ b/app/models/packages/package_file_build_info.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class Packages::PackageFileBuildInfo < ApplicationRecord
+ belongs_to :package_file, inverse_of: :package_file_build_infos
+ belongs_to :pipeline, class_name: 'Ci::Pipeline'
+end
diff --git a/app/models/pages/lookup_path.rb b/app/models/pages/lookup_path.rb
index 84d820e539c..9855731778f 100644
--- a/app/models/pages/lookup_path.rb
+++ b/app/models/pages/lookup_path.rb
@@ -22,11 +22,7 @@ module Pages
end
def source
- if artifacts_archive && !artifacts_archive.file_storage?
- zip_source
- else
- file_source
- end
+ zip_source || file_source
end
def prefix
@@ -42,18 +38,36 @@ module Pages
attr_reader :project, :trim_prefix, :domain
def artifacts_archive
- return unless Feature.enabled?(:pages_artifacts_archive, project)
+ return unless Feature.enabled?(:pages_serve_from_artifacts_archive, project)
+
+ project.pages_metadatum.artifacts_archive
+ end
+
+ def deployment
+ return unless Feature.enabled?(:pages_serve_from_deployments, 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
+ project.pages_metadatum.pages_deployment
end
def zip_source
+ source = deployment || artifacts_archive
+
+ return unless source&.file
+
+ return if source.file.file_storage? && !Feature.enabled?(:pages_serve_with_zip_file_protocol, project)
+
+ # artifacts archive doesn't support this
+ file_count = source.file_count if source.respond_to?(:file_count)
+
+ global_id = ::Gitlab::GlobalId.build(source, id: source.id).to_s
+
{
type: 'zip',
- path: artifacts_archive.url(expire_at: 1.day.from_now)
+ path: source.file.url_or_file_path(expire_at: 1.day.from_now),
+ global_id: global_id,
+ sha256: source.file_sha256,
+ file_size: source.size,
+ file_count: file_count
}
end
diff --git a/app/models/pages_deployment.rb b/app/models/pages_deployment.rb
index cd952c32046..61818a63764 100644
--- a/app/models/pages_deployment.rb
+++ b/app/models/pages_deployment.rb
@@ -4,19 +4,27 @@
class PagesDeployment < ApplicationRecord
include FileStoreMounter
+ attribute :file_store, :integer, default: -> { ::Pages::DeploymentUploader.default_store }
+
belongs_to :project, optional: false
belongs_to :ci_build, class_name: 'Ci::Build', optional: true
+ scope :older_than, -> (id) { where('id < ?', id) }
+
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 }
+ validates :file_count, presence: true, numericality: { greater_than_or_equal_to: 0, only_integer: true }
+ validates :file_sha256, presence: true
before_validation :set_size, if: :file_changed?
- default_value_for(:file_store) { ::Pages::DeploymentUploader.default_store }
-
mount_file_store_uploader ::Pages::DeploymentUploader
+ def log_geo_deleted_event
+ # this is to be adressed in https://gitlab.com/groups/gitlab-org/-/epics/589
+ end
+
private
def set_size
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index 98db47deaa3..8192310ddfb 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -286,7 +286,7 @@ class PagesDomain < ApplicationRecord
return unless domain
if domain.downcase.ends_with?(Settings.pages.host.downcase)
- self.errors.add(:domain, "*.#{Settings.pages.host} is restricted")
+ self.errors.add(:domain, "*.#{Settings.pages.host} is restricted. Please compare our documentation at https://docs.gitlab.com/ee/administration/pages/#advanced-configuration against your configuration.")
end
end
diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb
index e01cb0530a5..5aa5f2c842b 100644
--- a/app/models/personal_access_token.rb
+++ b/app/models/personal_access_token.rb
@@ -26,6 +26,7 @@ class PersonalAccessToken < ApplicationRecord
scope :revoked, -> { where(revoked: true) }
scope :not_revoked, -> { where(revoked: [false, nil]) }
scope :for_user, -> (user) { where(user: user) }
+ scope :for_users, -> (users) { where(user: users) }
scope :preload_users, -> { preload(:user) }
scope :order_expires_at_asc, -> { reorder(expires_at: :asc) }
scope :order_expires_at_desc, -> { reorder(expires_at: :desc) }
diff --git a/app/models/project.rb b/app/models/project.rb
index dbedd6d120c..ebd8e56246d 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -346,7 +346,8 @@ class Project < ApplicationRecord
# GitLab Pages
has_many :pages_domains
has_one :pages_metadatum, class_name: 'ProjectPagesMetadatum', inverse_of: :project
- has_many :pages_deployments
+ # we need to clean up files, not only remove records
+ has_many :pages_deployments, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
# Can be too many records. We need to implement delete_all in batches.
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/228637
@@ -378,7 +379,7 @@ class Project < ApplicationRecord
delegate :feature_available?, :builds_enabled?, :wiki_enabled?,
:merge_requests_enabled?, :forking_enabled?, :issues_enabled?,
- :pages_enabled?, :public_pages?, :private_pages?,
+ :pages_enabled?, :snippets_enabled?, :public_pages?, :private_pages?,
:merge_requests_access_level, :forking_access_level, :issues_access_level,
:wiki_access_level, :snippets_access_level, :builds_access_level,
:repository_access_level, :pages_access_level, :metrics_dashboard_access_level,
@@ -570,6 +571,7 @@ class Project < ApplicationRecord
scope :imported_from, -> (type) { where(import_type: type) }
scope :with_tracing_enabled, -> { joins(:tracing_setting) }
+ scope :with_enabled_error_tracking, -> { joins(:error_tracking_setting).where(project_error_tracking_settings: { enabled: true }) }
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
@@ -600,7 +602,7 @@ class Project < ApplicationRecord
# Returns a collection of projects that is either public or visible to the
# logged in user.
def self.public_or_visible_to_user(user = nil, min_access_level = nil)
- min_access_level = nil if user&.admin?
+ min_access_level = nil if user&.can_read_all_resources?
return public_to_user unless user
@@ -626,7 +628,7 @@ class Project < ApplicationRecord
def self.with_feature_available_for_user(feature, user)
visible = [ProjectFeature::ENABLED, ProjectFeature::PUBLIC]
- if user&.admin?
+ if user&.can_read_all_resources?
with_feature_enabled(feature)
elsif user
min_access_level = ProjectFeature.required_minimum_access_level(feature)
@@ -1193,7 +1195,6 @@ class Project < ApplicationRecord
end
def changing_shared_runners_enabled_is_allowed
- return unless Feature.enabled?(:disable_shared_runners_on_group, default_enabled: true)
return unless new_record? || changes.has_key?(:shared_runners_enabled)
if shared_runners_enabled && group && group.shared_runners_setting == 'disabled_and_unoverridable'
@@ -1340,8 +1341,7 @@ class Project < ApplicationRecord
end
def find_or_initialize_services
- available_services_names =
- Service.available_services_names + Service.project_specific_services_names - disabled_services
+ available_services_names = Service.available_services_names - disabled_services
available_services_names.map do |service_name|
find_or_initialize_service(service_name)
@@ -1468,11 +1468,6 @@ class Project < ApplicationRecord
services.public_send(hooks_scope).any? # rubocop:disable GitlabSecurity/PublicSend
end
- # Is overridden in EE
- def lfs_http_url_to_repo(_)
- http_url_to_repo
- end
-
def feature_usage
super.presence || build_feature_usage
end
@@ -1801,6 +1796,8 @@ class Project < ApplicationRecord
mark_pages_as_not_deployed unless destroyed?
+ DestroyPagesDeploymentsWorker.perform_async(id)
+
# 1. We rename pages to temporary directory
# 2. We wait 5 minutes, due to NFS caching
# 3. We asynchronously remove pages with force
@@ -1817,7 +1814,11 @@ class Project < ApplicationRecord
end
def mark_pages_as_not_deployed
- ensure_pages_metadatum.update!(deployed: false, artifacts_archive: nil)
+ ensure_pages_metadatum.update!(deployed: false, artifacts_archive: nil, pages_deployment: nil)
+ end
+
+ def update_pages_deployment!(deployment)
+ ensure_pages_metadatum.update!(pages_deployment: deployment)
end
def write_repository_config(gl_full_path: full_path)
@@ -2090,21 +2091,36 @@ class Project < ApplicationRecord
(auto_devops || build_auto_devops)&.predefined_variables
end
- # Tries to set repository as read_only, checking for existing Git transfers in progress beforehand
+ RepositoryReadOnlyError = Class.new(StandardError)
+
+ # Tries to set repository as read_only, checking for existing Git transfers in
+ # progress beforehand. Setting a repository read-only will fail if it is
+ # already in that state.
#
- # @return [Boolean] true when set to read_only or false when an existing git transfer is in progress
+ # @return nil. Failures will raise an exception
def set_repository_read_only!
with_lock do
- break false if git_transfer_in_progress?
+ raise RepositoryReadOnlyError, _('Git transfer in progress') if
+ git_transfer_in_progress?
- update_column(:repository_read_only, true)
+ raise RepositoryReadOnlyError, _('Repository already read-only') if
+ self.class.where(id: id).pick(:repository_read_only)
+
+ raise ActiveRecord::RecordNotSaved, _('Database update failed') unless
+ update_column(:repository_read_only, true)
+
+ nil
end
end
- # Set repository as writable again
+ # Set repository as writable again. Unlike setting it read-only, this will
+ # succeed if the repository is already writable.
def set_repository_writable!
with_lock do
- update_column(:repository_read_only, false)
+ raise ActiveRecord::RecordNotSaved, _('Database update failed') unless
+ update_column(:repository_read_only, false)
+
+ nil
end
end
diff --git a/app/models/project_repository_storage_move.rb b/app/models/project_repository_storage_move.rb
index 76f428fe925..3429dbe3a85 100644
--- a/app/models/project_repository_storage_move.rb
+++ b/app/models/project_repository_storage_move.rb
@@ -46,8 +46,15 @@ class ProjectRepositoryStorageMove < ApplicationRecord
transition replicated: :cleanup_failed
end
- after_transition initial: :scheduled do |storage_move|
- storage_move.project.update_column(:repository_read_only, true)
+ around_transition initial: :scheduled do |storage_move, block|
+ block.call
+
+ begin
+ storage_move.project.set_repository_read_only!
+ rescue => err
+ errors.add(:project, err.message)
+ next false
+ end
storage_move.run_after_commit do
ProjectUpdateRepositoryStorageWorker.perform_async(
@@ -56,17 +63,18 @@ class ProjectRepositoryStorageMove < ApplicationRecord
storage_move.id
)
end
+
+ true
end
- after_transition started: :replicated do |storage_move|
- storage_move.project.update_columns(
- repository_read_only: false,
- repository_storage: storage_move.destination_storage_name
- )
+ before_transition started: :replicated do |storage_move|
+ storage_move.project.set_repository_writable!
+
+ storage_move.project.update_column(:repository_storage, storage_move.destination_storage_name)
end
- after_transition started: :failed do |storage_move|
- storage_move.project.update_column(:repository_read_only, false)
+ before_transition started: :failed do |storage_move|
+ storage_move.project.set_repository_writable!
end
state :initial, value: 1
diff --git a/app/models/project_services/alerts_service.rb b/app/models/project_services/alerts_service.rb
index 28902114f3c..5b7d149ace1 100644
--- a/app/models/project_services/alerts_service.rb
+++ b/app/models/project_services/alerts_service.rb
@@ -14,6 +14,8 @@ class AlertsService < Service
before_validation :prevent_token_assignment
before_validation :ensure_token, if: :activated?
+ after_save :update_http_integration
+
def url
return if instance? || template?
@@ -77,6 +79,14 @@ class AlertsService < Service
def url_helpers
Gitlab::Routing.url_helpers
end
+
+ def update_http_integration
+ return unless project_id && type == 'AlertsService'
+
+ AlertManagement::SyncAlertServiceDataService # rubocop: disable CodeReuse/ServiceClass
+ .new(self)
+ .execute
+ end
end
AlertsService.prepend_if_ee('EE::AlertsService')
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index 732da62863f..7814bdb7106 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -30,7 +30,7 @@ class JiraService < IssueTrackerService
# TODO: we can probably just delegate as part of
# https://gitlab.com/gitlab-org/gitlab/issues/29404
- data_field :username, :password, :url, :api_url, :jira_issue_transition_id, :project_key, :issues_enabled
+ data_field :username, :password, :url, :api_url, :jira_issue_transition_id, :project_key, :issues_enabled, :vulnerabilities_enabled, :vulnerabilities_issuetype
before_update :reset_password
after_commit :update_deployment_type, on: [:create, :update], if: :update_deployment_type?
diff --git a/app/models/project_statistics.rb b/app/models/project_statistics.rb
index 0d2f89fb18d..c11a7fea1c6 100644
--- a/app/models/project_statistics.rb
+++ b/app/models/project_statistics.rb
@@ -19,14 +19,14 @@ class ProjectStatistics < ApplicationRecord
before_save :update_storage_size
- COLUMNS_TO_REFRESH = [:repository_size, :wiki_size, :lfs_objects_size, :commit_count, :snippets_size].freeze
+ COLUMNS_TO_REFRESH = [:repository_size, :wiki_size, :lfs_objects_size, :commit_count, :snippets_size, :uploads_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
+ NAMESPACE_RELATABLE_COLUMNS = [:repository_size, :wiki_size, :lfs_objects_size, :uploads_size].freeze
scope :for_project_ids, ->(project_ids) { where(project_id: project_ids) }
@@ -72,6 +72,12 @@ class ProjectStatistics < ApplicationRecord
self.lfs_objects_size = project.lfs_objects.sum(:size)
end
+ def update_uploads_size
+ return uploads_size unless Feature.enabled?(:count_uploads_size_in_storage_stats, project)
+
+ self.uploads_size = project.uploads.sum(:size)
+ end
+
# `wiki_size` and `snippets_size` have no default value in the database
# and the column can be nil.
# This means that, when the columns were added, all rows had nil
@@ -98,6 +104,10 @@ class ProjectStatistics < ApplicationRecord
# might try to update project statistics before the `pipeline_artifacts_size` column has been created.
storage_size += pipeline_artifacts_size if self.class.column_names.include?('pipeline_artifacts_size')
+ # The `uploads_size` column was added on 20201105021637 but db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb
+ # might try to update project statistics before the `uploads_size` column has been created.
+ storage_size += uploads_size if self.class.column_names.include?('uploads_size')
+
self.storage_size = storage_size
end
diff --git a/app/models/protected_branch/push_access_level.rb b/app/models/protected_branch/push_access_level.rb
index bde1d29ad7f..63d577a4866 100644
--- a/app/models/protected_branch/push_access_level.rb
+++ b/app/models/protected_branch/push_access_level.rb
@@ -2,4 +2,29 @@
class ProtectedBranch::PushAccessLevel < ApplicationRecord
include ProtectedBranchAccess
+
+ belongs_to :deploy_key
+
+ validates :access_level, uniqueness: { scope: :protected_branch_id, if: :role?,
+ conditions: -> { where(user_id: nil, group_id: nil, deploy_key_id: nil) } }
+ validates :deploy_key_id, uniqueness: { scope: :protected_branch_id, allow_nil: true }
+ validate :validate_deploy_key_membership
+
+ def type
+ if self.deploy_key.present?
+ :deploy_key
+ else
+ super
+ end
+ end
+
+ private
+
+ def validate_deploy_key_membership
+ return unless deploy_key
+
+ unless project.deploy_keys_projects.where(deploy_key: deploy_key).exists?
+ self.errors.add(:deploy_key, 'is not enabled for this project')
+ end
+ end
end
diff --git a/app/models/release.rb b/app/models/release.rb
index f2162a0f674..c56df0a6aa3 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -83,6 +83,15 @@ class Release < ApplicationRecord
self.milestones.map {|m| m.title }.sort.join(", ")
end
+ def to_hook_data(action)
+ Gitlab::HookData::ReleaseBuilder.new(self).build(action)
+ end
+
+ def execute_hooks(action)
+ hook_data = to_hook_data(action)
+ project.execute_hooks(hook_data, :release_hooks)
+ end
+
private
def actual_sha
diff --git a/app/models/releases/link.rb b/app/models/releases/link.rb
index 82272f4857a..fc2fa639f56 100644
--- a/app/models/releases/link.rb
+++ b/app/models/releases/link.rb
@@ -30,5 +30,15 @@ module Releases
def external?
!internal?
end
+
+ def hook_attrs
+ {
+ id: id,
+ external: external?,
+ link_type: link_type,
+ name: name,
+ url: url
+ }
+ end
end
end
diff --git a/app/models/releases/source.rb b/app/models/releases/source.rb
index 2f00d25d768..44760541290 100644
--- a/app/models/releases/source.rb
+++ b/app/models/releases/source.rb
@@ -24,6 +24,13 @@ module Releases
format: format)
end
+ def hook_attrs
+ {
+ format: format,
+ url: url
+ }
+ end
+
private
def archive_prefix
diff --git a/app/models/resource_timebox_event.rb b/app/models/resource_timebox_event.rb
index dbb2b428c7b..ac164783945 100644
--- a/app/models/resource_timebox_event.rb
+++ b/app/models/resource_timebox_event.rb
@@ -29,10 +29,10 @@ class ResourceTimeboxEvent < ResourceEvent
case self
when ResourceMilestoneEvent
Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_milestone_changed_action(author: user)
- when ResourceIterationEvent
- Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_iteration_changed_action(author: user)
else
# no-op
end
end
end
+
+ResourceTimeboxEvent.prepend_if_ee('EE::ResourceTimeboxEvent')
diff --git a/app/models/route.rb b/app/models/route.rb
index 706589e79b8..fe4846b3be5 100644
--- a/app/models/route.rb
+++ b/app/models/route.rb
@@ -20,6 +20,7 @@ class Route < ApplicationRecord
scope :inside_path, -> (path) { where('routes.path LIKE ?', "#{sanitize_sql_like(path)}/%") }
scope :for_routable, -> (routable) { where(source: routable) }
+ scope :for_routable_type, -> (routable_type) { where(source_type: routable_type) }
scope :sort_by_path_length, -> { order('LENGTH(routes.path)', :path) }
def rename_descendants
diff --git a/app/models/service.rb b/app/models/service.rb
index 764f417362f..2b6971954e3 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -8,6 +8,7 @@ class Service < ApplicationRecord
include ProjectServicesLoggable
include DataFields
include FromUnion
+ include EachBatch
SERVICE_NAMES = %w[
alerts asana assembla bamboo bugzilla buildkite campfire confluence custom_issue_tracker discord
@@ -16,6 +17,7 @@ class Service < ApplicationRecord
pivotaltracker prometheus pushover redmine slack slack_slash_commands teamcity unify_circuit webex_teams youtrack
].freeze
+ # Fake services to help with local development.
DEV_SERVICE_NAMES = %w[
mock_ci mock_deployment mock_monitoring
].freeze
@@ -64,9 +66,9 @@ class Service < ApplicationRecord
scope :by_type, -> (type) { where(type: type) }
scope :by_active_flag, -> (flag) { where(active: flag) }
scope :inherit_from_id, -> (id) { where(inherit_from_id: id) }
- 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 :for_group, -> (group) { where(group_id: group, type: available_services_types(include_project_specific: false)) }
+ scope :for_template, -> { where(template: true, type: available_services_types(include_project_specific: false)) }
+ scope :for_instance, -> { where(instance: true, type: available_services_types(include_project_specific: false)) }
scope :push_hooks, -> { where(push_events: true, active: true) }
scope :tag_push_hooks, -> { where(tag_push_events: true, active: true) }
@@ -167,13 +169,13 @@ class Service < ApplicationRecord
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)
+ def self.find_or_initialize_non_project_specific_integration(name, instance: false, group_id: nil)
+ if name.in?(available_services_names(include_project_specific: false))
"#{name}_service".camelize.constantize.find_or_initialize_by(instance: instance, group_id: group_id)
end
end
- def self.find_or_initialize_all(scope)
+ def self.find_or_initialize_all_non_project_specific(scope)
scope + build_nonexistent_services_for(scope)
end
@@ -187,13 +189,14 @@ class Service < ApplicationRecord
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)
+ available_services_types(include_project_specific: false) - scope.map(&:type)
end
private_class_method :list_nonexistent_services_for
- def self.available_services_names
+ def self.available_services_names(include_project_specific: true, include_dev: true)
service_names = services_names
- service_names += dev_services_names
+ service_names += project_specific_services_names if include_project_specific
+ service_names += dev_services_names if include_dev
service_names.sort_by(&:downcase)
end
@@ -212,12 +215,10 @@ class Service < ApplicationRecord
[]
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 }
+ def self.available_services_types(include_project_specific: true, include_dev: true)
+ available_services_names(include_project_specific: include_project_specific, include_dev: include_dev).map do |service_name|
+ "#{service_name}_service".camelize
+ end
end
def self.build_from_integration(integration, project_id: nil, group_id: nil)
@@ -273,6 +274,17 @@ class Service < ApplicationRecord
end
end
+ def self.inherited_descendants_from_self_or_ancestors_from(integration)
+ inherit_from_ids =
+ where(type: integration.type, group: integration.group.self_and_ancestors)
+ .or(where(type: integration.type, instance: true)).select(:id)
+
+ from_union([
+ where(type: integration.type, inherit_from_id: inherit_from_ids, group: integration.group.descendants),
+ where(type: integration.type, inherit_from_id: inherit_from_ids, project: Project.in_namespace(integration.group.self_and_descendants))
+ ])
+ end
+
def activated?
active
end
@@ -294,7 +306,7 @@ class Service < ApplicationRecord
end
def initialize_properties
- self.properties = {} if properties.nil?
+ self.properties = {} if has_attribute?(:properties) && properties.nil?
end
def title
@@ -410,8 +422,12 @@ class Service < ApplicationRecord
ProjectServiceWorker.perform_async(id, data)
end
- def issue_tracker?
- self.category == :issue_tracker
+ def external_issue_tracker?
+ category == :issue_tracker && active?
+ end
+
+ def external_wiki?
+ type == 'ExternalWikiService' && active?
end
# override if needed
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index d71853e11cf..dc370b46bda 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -293,9 +293,7 @@ class Snippet < ApplicationRecord
@storage ||= Storage::Hashed.new(self, prefix: Storage::Hashed::SNIPPET_REPOSITORY_PATH_PREFIX)
end
- # This is the full_path used to identify the
- # the snippet repository. It will be used mostly
- # for logging purposes.
+ # This is the full_path used to identify the the snippet repository.
override :full_path
def full_path
return unless persisted?
@@ -303,7 +301,7 @@ class Snippet < ApplicationRecord
@full_path ||= begin
components = []
components << project.full_path if project_id?
- components << '@snippets'
+ components << 'snippets'
components << self.id
components.join('/')
end
diff --git a/app/models/terraform/state.rb b/app/models/terraform/state.rb
index 9d88db27449..d329b429c9d 100644
--- a/app/models/terraform/state.rb
+++ b/app/models/terraform/state.rb
@@ -17,8 +17,15 @@ module Terraform
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
+ has_many :versions,
+ class_name: 'Terraform::StateVersion',
+ foreign_key: :terraform_state_id,
+ inverse_of: :terraform_state
+
+ has_one :latest_version, -> { ordered_by_version_desc },
+ class_name: 'Terraform::StateVersion',
+ foreign_key: :terraform_state_id,
+ inverse_of: :terraform_state
scope :versioning_not_enabled, -> { where(versioning_enabled: false) }
scope :ordered_by_name, -> { order(:name) }
@@ -48,11 +55,11 @@ module Terraform
self.lock_xid.present?
end
- def update_file!(data, version:)
+ def update_file!(data, version:, build:)
if versioning_enabled?
- create_new_version!(data: data, version: version)
+ create_new_version!(data: data, version: version, build: build)
elsif latest_version.present?
- migrate_legacy_version!(data: data, version: version)
+ migrate_legacy_version!(data: data, version: version, build: build)
else
self.file = data
save!
@@ -81,18 +88,18 @@ module Terraform
# The code can be removed in the next major version (14.0), after
# which any states that haven't been migrated will need to be
# recreated: https://gitlab.com/gitlab-org/gitlab/-/issues/258960
- def migrate_legacy_version!(data:, version:)
+ def migrate_legacy_version!(data:, version:, build:)
current_file = latest_version.file.read
current_version = parse_serial(current_file) || version - 1
update!(versioning_enabled: true)
reload_latest_version.update!(version: current_version, file: CarrierWaveStringFile.new(current_file))
- create_new_version!(data: data, version: version)
+ create_new_version!(data: data, version: version, build: build)
end
- def create_new_version!(data:, version:)
- new_version = versions.build(version: version, created_by_user: locked_by_user)
+ def create_new_version!(data:, version:, build:)
+ new_version = versions.build(version: version, created_by_user: locked_by_user, build: build)
new_version.assign_attributes(file: data)
new_version.save!
end
diff --git a/app/models/terraform/state_version.rb b/app/models/terraform/state_version.rb
index eff44485401..cc5d94b8e09 100644
--- a/app/models/terraform/state_version.rb
+++ b/app/models/terraform/state_version.rb
@@ -6,6 +6,7 @@ module Terraform
belongs_to :terraform_state, class_name: 'Terraform::State', optional: false
belongs_to :created_by_user, class_name: 'User', optional: true
+ belongs_to :build, class_name: 'Ci::Build', optional: true, foreign_key: :ci_build_id
scope :ordered_by_version_desc, -> { order(version: :desc) }
diff --git a/app/models/user.rb b/app/models/user.rb
index ef77e207215..be64e057d59 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -28,6 +28,8 @@ class User < ApplicationRecord
DEFAULT_NOTIFICATION_LEVEL = :participating
+ INSTANCE_ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10
+
add_authentication_token_field :incoming_email_token, token_generator: -> { SecureRandom.hex.to_i(16).to_s(36) }
add_authentication_token_field :feed_token
add_authentication_token_field :static_object_token
@@ -341,6 +343,7 @@ class User < ApplicationRecord
# Scopes
scope :admins, -> { where(admin: true) }
+ scope :instance_access_request_approvers_to_be_notified, -> { admins.active.order_recent_sign_in.limit(INSTANCE_ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT) }
scope :blocked, -> { with_states(:blocked, :ldap_blocked) }
scope :blocked_pending_approval, -> { with_states(:blocked_pending_approval) }
scope :external, -> { where(external: true) }
@@ -350,6 +353,9 @@ class User < ApplicationRecord
scope :deactivated, -> { with_state(:deactivated).non_internal }
scope :without_projects, -> { joins('LEFT JOIN project_authorizations ON users.id = project_authorizations.user_id').where(project_authorizations: { user_id: nil }) }
scope :by_username, -> (usernames) { iwhere(username: Array(usernames).map(&:to_s)) }
+ scope :by_name, -> (names) { iwhere(name: Array(names)) }
+ scope :by_user_email, -> (emails) { iwhere(email: Array(emails)) }
+ scope :by_emails, -> (emails) { joins(:emails).where(emails: { email: Array(emails).map(&:downcase) }) }
scope :for_todos, -> (todos) { where(id: todos.select(:user_id)) }
scope :with_emails, -> { preload(:emails) }
scope :with_dashboard, -> (dashboard) { where(dashboard: dashboard) }
@@ -514,17 +520,15 @@ class User < ApplicationRecord
# @param emails [String, Array<String>] email addresses to check
# @param confirmed [Boolean] Only return users where the email is confirmed
def by_any_email(emails, confirmed: false)
- emails = Array(emails).map(&:downcase)
-
- from_users = where(email: emails)
+ from_users = by_user_email(emails)
from_users = from_users.confirmed if confirmed
- from_emails = joins(:emails).where(emails: { email: emails })
+ from_emails = by_emails(emails)
from_emails = from_emails.confirmed.merge(Email.confirmed) if confirmed
items = [from_users, from_emails]
- user_ids = Gitlab::PrivateCommitEmail.user_ids_for_emails(emails)
+ user_ids = Gitlab::PrivateCommitEmail.user_ids_for_emails(Array(emails).map(&:downcase))
items << where(id: user_ids) if user_ids.present?
from_union(items)
@@ -909,10 +913,11 @@ class User < ApplicationRecord
# Returns the groups a user has access to, either through a membership or a project authorization
def authorized_groups
Group.unscoped do
- Group.from_union([
- groups,
- authorized_projects.joins(:namespace).select('namespaces.*')
- ])
+ if Feature.enabled?(:shared_group_membership_auth, self)
+ authorized_groups_with_shared_membership
+ else
+ authorized_groups_without_shared_membership
+ end
end
end
@@ -1807,6 +1812,26 @@ class User < ApplicationRecord
private
+ def authorized_groups_without_shared_membership
+ Group.from_union([
+ groups,
+ authorized_projects.joins(:namespace).select('namespaces.*')
+ ])
+ end
+
+ def authorized_groups_with_shared_membership
+ cte = Gitlab::SQL::CTE.new(:direct_groups, authorized_groups_without_shared_membership)
+ cte_alias = cte.table.alias(Group.table_name)
+
+ Group
+ .with(cte.to_arel)
+ .from_union([
+ Group.from(cte_alias),
+ Group.joins(:shared_with_group_links)
+ .where(group_group_links: { shared_with_group_id: Group.from(cte_alias) })
+ ])
+ end
+
def default_private_profile_to_false
return unless private_profile_changed? && private_profile.nil?
@@ -1843,15 +1868,15 @@ class User < ApplicationRecord
valid = true
error = nil
- if Gitlab::CurrentSettings.domain_blacklist_enabled?
- blocked_domains = Gitlab::CurrentSettings.domain_blacklist
+ if Gitlab::CurrentSettings.domain_denylist_enabled?
+ blocked_domains = Gitlab::CurrentSettings.domain_denylist
if domain_matches?(blocked_domains, email)
error = 'is not from an allowed domain.'
valid = false
end
end
- allowed_domains = Gitlab::CurrentSettings.domain_whitelist
+ allowed_domains = Gitlab::CurrentSettings.domain_allowlist
unless allowed_domains.blank?
if domain_matches?(allowed_domains, email)
valid = true
diff --git a/app/models/user_callout.rb b/app/models/user_callout.rb
index e39ff8712fc..cfad58fc0db 100644
--- a/app/models/user_callout.rb
+++ b/app/models/user_callout.rb
@@ -25,7 +25,8 @@ class UserCallout < ApplicationRecord
personal_access_token_expiry: 21, # EE-only
suggest_pipeline: 22,
customize_homepage: 23,
- feature_flags_new_version: 24
+ feature_flags_new_version: 24,
+ registration_enabled_callout: 25
}
validates :user, presence: true
diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb
index c05bc80415a..b49a7eb72dc 100644
--- a/app/models/user_preference.rb
+++ b/app/models/user_preference.rb
@@ -1,11 +1,15 @@
# frozen_string_literal: true
class UserPreference < ApplicationRecord
+ include IgnorableColumns
+
# We could use enums, but Rails 4 doesn't support multiple
# enum options with same name for multiple fields, also it creates
# extra methods that aren't really needed here.
NOTES_FILTERS = { all_notes: 0, only_comments: 1, only_activity: 2 }.freeze
+ ignore_column :feature_filter_type, remove_with: '13.8', remove_after: '2021-01-22'
+
belongs_to :user
scope :with_user, -> { joins(:user) }
diff --git a/app/models/user_status.rb b/app/models/user_status.rb
index 016b89bae81..0e1ae0b7338 100644
--- a/app/models/user_status.rb
+++ b/app/models/user_status.rb
@@ -9,6 +9,8 @@ class UserStatus < ApplicationRecord
belongs_to :user
+ enum availability: { not_set: 0, busy: 1 }
+
validates :user, presence: true
validates :emoji, inclusion: { in: Gitlab::Emoji.emojis_names }
validates :message, length: { maximum: 100 }, allow_blank: true
diff --git a/app/models/vulnerability.rb b/app/models/vulnerability.rb
index a4338c4e2bd..ab29afd0d08 100644
--- a/app/models/vulnerability.rb
+++ b/app/models/vulnerability.rb
@@ -2,6 +2,27 @@
# Placeholder class for model that is implemented in EE
class Vulnerability < ApplicationRecord
+ include IgnorableColumns
+
+ def self.link_reference_pattern
+ nil
+ end
+
+ def self.reference_prefix
+ '[vulnerability:'
+ end
+
+ def self.reference_prefix_escaped
+ '[vulnerability&lbrack;'
+ end
+
+ def self.reference_postfix
+ ']'
+ end
+
+ def self.reference_postfix_escaped
+ '&rbrack;'
+ end
end
Vulnerability.prepend_if_ee('EE::Vulnerability')
diff --git a/app/policies/alert_management/http_integration_policy.rb b/app/policies/alert_management/http_integration_policy.rb
new file mode 100644
index 00000000000..77c936b9e0b
--- /dev/null
+++ b/app/policies/alert_management/http_integration_policy.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module AlertManagement
+ class HttpIntegrationPolicy < ::BasePolicy
+ delegate { @subject.project }
+ end
+end
diff --git a/app/policies/base_policy.rb b/app/policies/base_policy.rb
index 1c93073025d..580a348b408 100644
--- a/app/policies/base_policy.rb
+++ b/app/policies/base_policy.rb
@@ -57,6 +57,8 @@ class BasePolicy < DeclarativePolicy::Base
rule { default }.enable :read_cross_project
condition(:is_gitlab_com) { ::Gitlab.dev_env_or_com? }
+
+ rule { admin }.enable :change_repository_storage
end
BasePolicy.prepend_if_ee('EE::BasePolicy')
diff --git a/app/policies/concerns/policy_actor.rb b/app/policies/concerns/policy_actor.rb
index 3073a2e5d10..7eca6f4c6c8 100644
--- a/app/policies/concerns/policy_actor.rb
+++ b/app/policies/concerns/policy_actor.rb
@@ -72,6 +72,10 @@ module PolicyActor
def try_obtain_ldap_lease
nil
end
+
+ def can_read_all_resources?
+ false
+ end
end
PolicyActor.prepend_if_ee('EE::PolicyActor')
diff --git a/app/policies/container_registry/tag_policy.rb b/app/policies/container_registry/tag_policy.rb
new file mode 100644
index 00000000000..8c75f2a6f20
--- /dev/null
+++ b/app/policies/container_registry/tag_policy.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+module ContainerRegistry
+ class TagPolicy < BasePolicy
+ delegate { @subject.repository }
+ end
+end
diff --git a/app/policies/custom_emoji_policy.rb b/app/policies/custom_emoji_policy.rb
new file mode 100644
index 00000000000..ba73b9a3782
--- /dev/null
+++ b/app/policies/custom_emoji_policy.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class CustomEmojiPolicy < BasePolicy
+ delegate { @subject.group }
+end
diff --git a/app/policies/group_member_policy.rb b/app/policies/group_member_policy.rb
index f6e52def270..78a2be7a9f8 100644
--- a/app/policies/group_member_policy.rb
+++ b/app/policies/group_member_policy.rb
@@ -11,7 +11,10 @@ class GroupMemberPolicy < BasePolicy
condition(:is_target_user) { @user && @subject.user_id == @user.id }
rule { anonymous }.prevent_all
- rule { last_owner }.prevent_all
+ rule { last_owner }.policy do
+ prevent :update_group_member
+ prevent :destroy_group_member
+ end
rule { can?(:admin_group_member) }.policy do
enable :update_group_member
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index f9ec026a6d2..231843c5f23 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -46,6 +46,10 @@ class GroupPolicy < BasePolicy
group_projects_for(user: @user, group: @subject, only_owned: false).any? { |p| p.design_management_enabled? }
end
+ condition(:dependency_proxy_available) do
+ @subject.dependency_proxy_feature_available?
+ end
+
desc "Deploy token with read_package_registry scope"
condition(:read_package_registry_deploy_token) do
@user.is_a?(DeployToken) && @user.groups.include?(@subject) && @user.read_package_registry
@@ -59,6 +63,9 @@ class GroupPolicy < BasePolicy
with_scope :subject
condition(:resource_access_token_available) { resource_access_token_available? }
+ with_scope :subject
+ condition(:has_project_with_service_desk_enabled) { @subject.has_project_with_service_desk_enabled? }
+
rule { design_management_enabled }.policy do
enable :read_design_activity
end
@@ -94,6 +101,7 @@ class GroupPolicy < BasePolicy
enable :read_label
enable :read_board
enable :read_group_member
+ enable :read_custom_emoji
end
rule { ~can?(:read_group) }.policy do
@@ -107,6 +115,7 @@ class GroupPolicy < BasePolicy
enable :create_metrics_dashboard_annotation
enable :delete_metrics_dashboard_annotation
enable :update_metrics_dashboard_annotation
+ enable :create_custom_emoji
end
rule { reporter }.policy do
@@ -187,13 +196,24 @@ class GroupPolicy < BasePolicy
rule { write_package_registry_deploy_token }.policy do
enable :create_package
+ enable :read_package
enable :read_group
end
+ rule { can?(:read_group) & dependency_proxy_available }
+ .enable :read_dependency_proxy
+
+ rule { developer & dependency_proxy_available }
+ .enable :admin_dependency_proxy
+
rule { resource_access_token_available & can?(:admin_group) }.policy do
enable :admin_resource_access_tokens
end
+ rule { support_bot & has_project_with_service_desk_enabled }.policy do
+ enable :read_label
+ end
+
def access_level
return GroupMember::NO_ACCESS if @user.nil?
return GroupMember::NO_ACCESS unless user_is_user?
diff --git a/app/policies/instance_metadata_policy.rb b/app/policies/instance_metadata_policy.rb
new file mode 100644
index 00000000000..3386217044d
--- /dev/null
+++ b/app/policies/instance_metadata_policy.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class InstanceMetadataPolicy < BasePolicy
+ delegate { :global }
+end
diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb
index 44c448eb601..183f4d8f919 100644
--- a/app/policies/issue_policy.rb
+++ b/app/policies/issue_policy.rb
@@ -35,6 +35,10 @@ class IssuePolicy < IssuablePolicy
rule { ~can?(:read_design) }.policy do
prevent :move_design
end
+
+ rule { ~anonymous & can?(:read_issue) }.policy do
+ enable :create_todo
+ end
end
IssuePolicy.prepend_if_ee('EE::IssuePolicy')
diff --git a/app/policies/merge_request_policy.rb b/app/policies/merge_request_policy.rb
index e5ac228b0ee..d5ba42d750c 100644
--- a/app/policies/merge_request_policy.rb
+++ b/app/policies/merge_request_policy.rb
@@ -14,6 +14,10 @@ class MergeRequestPolicy < IssuablePolicy
rule { can?(:update_merge_request) }.policy do
enable :approve_merge_request
end
+
+ rule { ~anonymous & can?(:read_merge_request) }.policy do
+ enable :create_todo
+ end
end
MergeRequestPolicy.prepend_if_ee('EE::MergeRequestPolicy')
diff --git a/app/policies/note_policy.rb b/app/policies/note_policy.rb
index 2217aa1326c..2bf6b6c3161 100644
--- a/app/policies/note_policy.rb
+++ b/app/policies/note_policy.rb
@@ -7,13 +7,15 @@ class NotePolicy < BasePolicy
delegate { @subject.noteable if DeclarativePolicy.has_policy?(@subject.noteable) }
condition(:is_author) { @user && @subject.author == @user }
- condition(:is_noteable_author) { @user && @subject.noteable.author_id == @user.id }
+ condition(:is_noteable_author) { @user && @subject.noteable.try(:author_id) == @user.id }
condition(:editable, scope: :subject) { @subject.editable? }
condition(:can_read_noteable) { can?(:"read_#{@subject.noteable_ability_name}") }
condition(:commit_is_deleted) { @subject.for_commit? && @subject.noteable.blank? }
+ condition(:for_design) { @subject.for_design? }
+
condition(:is_visible) { @subject.system_note_with_references_visible_for?(@user) }
condition(:confidential, scope: :subject) { @subject.confidential? }
@@ -28,6 +30,7 @@ class NotePolicy < BasePolicy
rule { ~can_read_noteable }.policy do
prevent :admin_note
prevent :resolve_note
+ prevent :reposition_note
prevent :award_emoji
end
@@ -46,6 +49,7 @@ class NotePolicy < BasePolicy
prevent :read_note
prevent :admin_note
prevent :resolve_note
+ prevent :reposition_note
prevent :award_emoji
end
@@ -57,9 +61,14 @@ class NotePolicy < BasePolicy
prevent :read_note
prevent :admin_note
prevent :resolve_note
+ prevent :reposition_note
prevent :award_emoji
end
+ rule { can?(:admin_note) | (for_design & can?(:create_note)) }.policy do
+ enable :reposition_note
+ end
+
def parent_namespace
strong_memoize(:parent_namespace) do
next if @subject.is_a?(PersonalSnippet)
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 59e2d617bf7..13073ed68a1 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -546,8 +546,6 @@ class ProjectPolicy < BasePolicy
prevent :create_pipeline
end
- rule { admin }.enable :change_repository_storage
-
rule { can?(:read_issue) }.policy do
enable :read_design
enable :read_design_activity
@@ -570,6 +568,7 @@ class ProjectPolicy < BasePolicy
rule { write_package_registry_deploy_token }.policy do
enable :create_package
+ enable :read_package
enable :read_project
end
diff --git a/app/policies/service_policy.rb b/app/policies/service_policy.rb
new file mode 100644
index 00000000000..61aff444620
--- /dev/null
+++ b/app/policies/service_policy.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class ServicePolicy < BasePolicy
+ delegate(:project)
+end
diff --git a/app/policies/terraform/state_version_policy.rb b/app/policies/terraform/state_version_policy.rb
new file mode 100644
index 00000000000..ad0b2f6d594
--- /dev/null
+++ b/app/policies/terraform/state_version_policy.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Terraform
+ class StateVersionPolicy < BasePolicy
+ alias_method :terraform_state_version, :subject
+
+ delegate { terraform_state_version.terraform_state }
+ end
+end
diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb
index c9dfa98b285..70e8fb32064 100644
--- a/app/policies/user_policy.rb
+++ b/app/policies/user_policy.rb
@@ -21,11 +21,13 @@ class UserPolicy < BasePolicy
enable :update_user
enable :update_user_status
enable :read_user_personal_access_tokens
+ enable :read_group_count
end
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
+ rule { (user_is_self | admin) & ~blocked }.enable :create_user_personal_access_token
end
UserPolicy.prepend_if_ee('EE::UserPolicy')
diff --git a/app/presenters/environment_presenter.rb b/app/presenters/environment_presenter.rb
index 3fa31eb69a2..6f67bbe2a5a 100644
--- a/app/presenters/environment_presenter.rb
+++ b/app/presenters/environment_presenter.rb
@@ -6,8 +6,6 @@ class EnvironmentPresenter < Gitlab::View::Presenter::Delegated
presents :environment
def path
- if Feature.enabled?(:expose_environment_path_in_alert_details, project)
- project_environment_path(project, self)
- end
+ project_environment_path(project, self)
end
end
diff --git a/app/presenters/invitation_presenter.rb b/app/presenters/invitation_presenter.rb
new file mode 100644
index 00000000000..d8c07f327dd
--- /dev/null
+++ b/app/presenters/invitation_presenter.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class InvitationPresenter < Gitlab::View::Presenter::Delegated
+ presents :invitation
+end
diff --git a/app/presenters/issue_presenter.rb b/app/presenters/issue_presenter.rb
index 0b498ce97d8..76bf3bf4577 100644
--- a/app/presenters/issue_presenter.rb
+++ b/app/presenters/issue_presenter.rb
@@ -10,6 +10,10 @@ class IssuePresenter < Gitlab::View::Presenter::Delegated
def subscribed?
issue.subscribed?(current_user, issue.project)
end
+
+ def project_emails_disabled?
+ issue.project.emails_disabled?
+ end
end
IssuePresenter.prepend_if_ee('EE::IssuePresenter')
diff --git a/app/presenters/packages/detail/package_presenter.rb b/app/presenters/packages/detail/package_presenter.rb
index e8223d6498b..dbfcfcb67f3 100644
--- a/app/presenters/packages/detail/package_presenter.rb
+++ b/app/presenters/packages/detail/package_presenter.rb
@@ -29,7 +29,8 @@ module Packages
package_detail[:composer_metadatum] = @package.composer_metadatum if @package.composer_metadatum
package_detail[:conan_metadatum] = @package.conan_metadatum if @package.conan_metadatum
package_detail[:dependency_links] = @package.dependency_links.map(&method(:build_dependency_links))
- package_detail[:pipeline] = build_pipeline_info(@package.build_info.pipeline) if @package.build_info
+ package_detail[:pipeline] = build_pipeline_info(@package.pipeline) if @package.pipeline
+ package_detail[:pipelines] = build_pipeline_infos(@package.pipelines) if @package.pipelines.present?
package_detail
end
@@ -37,12 +38,20 @@ module Packages
private
def build_package_file_view(package_file)
- {
+ file_view = {
created_at: package_file.created_at,
download_path: package_file.download_path,
file_name: package_file.file_name,
size: package_file.size
}
+
+ file_view[:pipelines] = build_pipeline_infos(package_file.pipelines) if package_file.pipelines.present?
+
+ file_view
+ end
+
+ def build_pipeline_infos(pipeline_infos)
+ pipeline_infos.map { |pipeline_info| build_pipeline_info(pipeline_info) }
end
def build_pipeline_info(pipeline_info)
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 392eeafb2b4..0f5b601f2b0 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -13,7 +13,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
presents :project
- AnchorData = Struct.new(:is_link, :label, :link, :class_modifier, :icon)
+ AnchorData = Struct.new(:is_link, :label, :link, :class_modifier, :icon, :itemprop)
MAX_TOPICS_TO_SHOW = 3
def statistic_icon(icon_name = 'plus-square-o')
@@ -277,7 +277,9 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
AnchorData.new(false,
icon + content_tag(:span, license_short_name, class: 'project-stat-value'),
license_path,
- 'default')
+ 'default',
+ nil,
+ 'license')
else
if current_user && can_current_user_push_to_default_branch?
AnchorData.new(false,
diff --git a/app/presenters/release_presenter.rb b/app/presenters/release_presenter.rb
index c27059c6d63..b11585d0d1c 100644
--- a/app/presenters/release_presenter.rb
+++ b/app/presenters/release_presenter.rb
@@ -23,18 +23,36 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated
project_release_url(project, release)
end
- def merge_requests_url
+ def opened_merge_requests_url
return unless release_mr_issue_urls_available?
project_merge_requests_url(project, params_for_issues_and_mrs)
end
- def issues_url
+ def merged_merge_requests_url
+ return unless release_mr_issue_urls_available?
+
+ project_merge_requests_url(project, params_for_issues_and_mrs(state: 'merged'))
+ end
+
+ def closed_merge_requests_url
+ return unless release_mr_issue_urls_available?
+
+ project_merge_requests_url(project, params_for_issues_and_mrs(state: 'closed'))
+ end
+
+ def opened_issues_url
return unless release_mr_issue_urls_available?
project_issues_url(project, params_for_issues_and_mrs)
end
+ def closed_issues_url
+ return unless release_mr_issue_urls_available?
+
+ project_issues_url(project, params_for_issues_and_mrs(state: 'closed'))
+ end
+
def edit_url
return unless release_edit_page_available?
@@ -53,18 +71,24 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated
can_download_code? ? release.name : "Release-#{release.id}"
end
+ def download_url(filepath)
+ filepath = filepath.sub(%r{^/}, '') if filepath.start_with?('/')
+
+ downloads_project_release_url(project, release, filepath)
+ end
+
private
def can_download_code?
can?(current_user, :download_code, project)
end
- def params_for_issues_and_mrs
- { scope: 'all', state: 'opened', release_tag: release.tag }
+ def params_for_issues_and_mrs(state: 'opened')
+ { scope: 'all', state: state, release_tag: release.tag }
end
def release_mr_issue_urls_available?
- ::Feature.enabled?(:release_mr_issue_urls, project)
+ ::Feature.enabled?(:release_mr_issue_urls, project, default_enabled: true)
end
def release_edit_page_available?
diff --git a/app/serializers/base_discussion_entity.rb b/app/serializers/base_discussion_entity.rb
new file mode 100644
index 00000000000..5ca4d1d6cc9
--- /dev/null
+++ b/app/serializers/base_discussion_entity.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+class BaseDiscussionEntity < Grape::Entity
+ include RequestAwareEntity
+ include NotesHelper
+
+ expose :id
+ expose :reply_id
+ expose :project_id
+ expose :commit_id
+
+ expose :confidential?, as: :confidential
+ expose :diff_discussion?, as: :diff_discussion
+ expose :expanded?, as: :expanded
+ expose :for_commit?, as: :for_commit
+ expose :individual_note?, as: :individual_note
+ expose :resolvable?, as: :resolvable
+
+ expose :truncated_diff_lines, using: DiffLineEntity, if: -> (d, _) { d.diff_discussion? && d.on_text? && (d.expanded? || render_truncated_diff_lines?) }
+
+ with_options if: -> (d, _) { d.diff_discussion? } do
+ expose :active?, as: :active
+ expose :line_code
+ expose :diff_file, using: DiscussionDiffFileEntity
+ end
+
+ with_options if: -> (d, _) { d.diff_discussion? && !d.legacy_diff_discussion? } do
+ expose :position
+ expose :original_position
+ end
+
+ expose :discussion_path do |discussion|
+ discussion_path(discussion)
+ end
+
+ with_options if: -> (d, _) { d.resolvable? } do
+ expose :resolve_path do |discussion|
+ resolve_project_merge_request_discussion_path(discussion.project, discussion.noteable, discussion.id)
+ end
+
+ expose :resolve_with_issue_path do |discussion|
+ new_project_issue_path(discussion.project, merge_request_to_resolve_discussions_of: discussion.noteable.iid, discussion_to_resolve: discussion.id)
+ end
+ end
+
+ expose :truncated_diff_lines_path, if: -> (d, _) { !d.expanded? && !render_truncated_diff_lines? } do |discussion|
+ project_merge_request_discussion_path(discussion.project, discussion.noteable, discussion)
+ end
+
+ private
+
+ def render_truncated_diff_lines?
+ options.fetch(:render_truncated_diff_lines, false)
+ end
+end
diff --git a/app/serializers/diff_file_base_entity.rb b/app/serializers/diff_file_base_entity.rb
index 596f5d686da..5036f28184c 100644
--- a/app/serializers/diff_file_base_entity.rb
+++ b/app/serializers/diff_file_base_entity.rb
@@ -48,7 +48,7 @@ class DiffFileBaseEntity < Grape::Entity
next unless has_edit_path?(merge_request)
- gitlab_ide_merge_request_path(merge_request)
+ ide_merge_request_path(merge_request, diff_file.new_path)
end
expose :old_path_html do |diff_file|
diff --git a/app/serializers/diff_file_entity.rb b/app/serializers/diff_file_entity.rb
index e3fefbb46b6..9865af1e116 100644
--- a/app/serializers/diff_file_entity.rb
+++ b/app/serializers/diff_file_entity.rb
@@ -3,6 +3,7 @@
class DiffFileEntity < DiffFileBaseEntity
include CommitsHelper
include IconsHelper
+ include Gitlab::Utils::StrongMemoize
expose :added_lines
expose :removed_lines
@@ -54,11 +55,16 @@ class DiffFileEntity < DiffFileBaseEntity
# Used for inline diffs
expose :highlighted_diff_lines, using: DiffLineEntity, if: -> (diff_file, options) { inline_diff_view?(options, diff_file) && diff_file.text? } do |diff_file|
- diff_file.diff_lines_for_serializer
+ file = conflict_file(options, diff_file) || diff_file
+ file.diff_lines_for_serializer
end
expose :is_fully_expanded do |diff_file|
- diff_file.fully_expanded?
+ if conflict_file(options, diff_file)
+ false
+ else
+ diff_file.fully_expanded?
+ end
end
# Used for parallel diffs
@@ -79,4 +85,10 @@ class DiffFileEntity < DiffFileBaseEntity
# If nothing is present, inline will be the default.
options.fetch(:diff_view, :inline).to_sym == :inline
end
+
+ def conflict_file(options, diff_file)
+ strong_memoize(:conflict_file) do
+ options[:conflicts] && options[:conflicts][diff_file.new_path]
+ end
+ end
end
diff --git a/app/serializers/diffs_entity.rb b/app/serializers/diffs_entity.rb
index 0b4f21c55f4..f573bbe8385 100644
--- a/app/serializers/diffs_entity.rb
+++ b/app/serializers/diffs_entity.rb
@@ -71,7 +71,7 @@ class DiffsEntity < Grape::Entity
submodule_links = Gitlab::SubmoduleLinks.new(merge_request.project.repository)
DiffFileEntity.represent(diffs.diff_files,
- options.merge(submodule_links: submodule_links, code_navigation_path: code_navigation_path(diffs)))
+ options.merge(submodule_links: submodule_links, code_navigation_path: code_navigation_path(diffs), conflicts: conflicts))
end
expose :merge_request_diffs, using: MergeRequestDiffEntity, if: -> (_, options) { options[:merge_request_diffs]&.any? } do |diffs|
@@ -88,10 +88,6 @@ class DiffsEntity < Grape::Entity
private
- def code_navigation_path(diffs)
- Gitlab::CodeNavigationPath.new(merge_request.project, diffs.diff_refs&.head_sha)
- end
-
def commit_ids
@commit_ids ||= merge_request.recent_commits.map(&:id)
end
diff --git a/app/serializers/discussion_entity.rb b/app/serializers/discussion_entity.rb
index 497471699b2..bcf6b331192 100644
--- a/app/serializers/discussion_entity.rb
+++ b/app/serializers/discussion_entity.rb
@@ -1,23 +1,8 @@
# frozen_string_literal: true
-class DiscussionEntity < Grape::Entity
- include RequestAwareEntity
- include NotesHelper
-
- expose :id, :reply_id
- expose :position, if: -> (d, _) { d.diff_discussion? && !d.legacy_diff_discussion? }
- expose :original_position, if: -> (d, _) { d.diff_discussion? && !d.legacy_diff_discussion? }
- expose :line_code, if: -> (d, _) { d.diff_discussion? }
- expose :expanded?, as: :expanded
- expose :active?, as: :active, if: -> (d, _) { d.diff_discussion? }
- expose :project_id
-
+class DiscussionEntity < BaseDiscussionEntity
expose :notes do |discussion, opts|
- request.note_entity.represent(discussion.notes, opts)
- end
-
- expose :discussion_path do |discussion|
- discussion_path(discussion)
+ request.note_entity.represent(discussion.notes, opts.merge(with_base_discussion: false))
end
expose :positions, if: -> (d, _) { display_merge_ref_discussions?(d) } do |discussion|
@@ -28,42 +13,13 @@ class DiscussionEntity < Grape::Entity
discussion.diff_note_positions.map(&:line_code)
end
- expose :individual_note?, as: :individual_note
- expose :resolvable do |discussion|
- discussion.resolvable?
- end
-
expose :resolved?, as: :resolved
expose :resolved_by_push?, as: :resolved_by_push
expose :resolved_by, using: NoteUserEntity
expose :resolved_at
- expose :resolve_path, if: -> (d, _) { d.resolvable? } do |discussion|
- resolve_project_merge_request_discussion_path(discussion.project, discussion.noteable, discussion.id)
- end
- expose :resolve_with_issue_path, if: -> (d, _) { d.resolvable? } do |discussion|
- new_project_issue_path(discussion.project, merge_request_to_resolve_discussions_of: discussion.noteable.iid, discussion_to_resolve: discussion.id)
- end
-
- expose :diff_file, using: DiscussionDiffFileEntity, if: -> (d, _) { d.diff_discussion? }
-
- expose :diff_discussion?, as: :diff_discussion
-
- expose :truncated_diff_lines_path, if: -> (d, _) { !d.expanded? && !render_truncated_diff_lines? } do |discussion|
- project_merge_request_discussion_path(discussion.project, discussion.noteable, discussion)
- end
-
- expose :truncated_diff_lines, using: DiffLineEntity, if: -> (d, _) { d.diff_discussion? && d.on_text? && (d.expanded? || render_truncated_diff_lines?) }
-
- expose :for_commit?, as: :for_commit
- expose :commit_id
- expose :confidential?, as: :confidential
private
- def render_truncated_diff_lines?
- options[:render_truncated_diff_lines]
- end
-
def current_user
request.current_user
end
diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb
index 7da5910a75b..0bd9c602bf5 100644
--- a/app/serializers/environment_entity.rb
+++ b/app/serializers/environment_entity.rb
@@ -4,6 +4,11 @@ class EnvironmentEntity < Grape::Entity
include RequestAwareEntity
expose :id
+
+ expose :global_id do |environment|
+ environment.to_global_id.to_s
+ end
+
expose :name
expose :state
expose :external_url
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index 44cbcfc5044..e46b269ea35 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -67,15 +67,15 @@ class MergeRequestWidgetEntity < Grape::Entity
)
end
- expose :user_callouts_path, if: -> (_, opts) { opts[:experiment_enabled] == :suggest_pipeline } do |_merge_request|
+ expose :user_callouts_path, if: -> (*) { Feature.enabled?(:suggest_pipeline, default_enabled: true) } do |_merge_request|
user_callouts_path
end
- expose :suggest_pipeline_feature_id, if: -> (_, opts) { opts[:experiment_enabled] == :suggest_pipeline } do |_merge_request|
+ expose :suggest_pipeline_feature_id, if: -> (*) { Feature.enabled?(:suggest_pipeline, default_enabled: true) } do |_merge_request|
SUGGEST_PIPELINE
end
- expose :is_dismissed_suggest_pipeline, if: -> (_, opts) { opts[:experiment_enabled] == :suggest_pipeline } do |_merge_request|
+ expose :is_dismissed_suggest_pipeline, if: -> (*) { Feature.enabled?(:suggest_pipeline, default_enabled: true) } do |_merge_request|
current_user && current_user.dismissed_callout?(feature_name: SUGGEST_PIPELINE)
end
@@ -129,7 +129,7 @@ class MergeRequestWidgetEntity < Grape::Entity
end
expose :security_reports_docs_path do |merge_request|
- help_page_path('user/application_security/sast/index.md', anchor: 'reports-json-format')
+ help_page_path('user/application_security/index.md', anchor: 'viewing-security-scan-information-in-merge-requests')
end
private
@@ -151,6 +151,10 @@ class MergeRequestWidgetEntity < Grape::Entity
can?(current_user, :create_pipeline, merge_request.source_project)
end
+ def use_merge_base_with_merged_results?
+ object.actual_head_pipeline&.merge_request_event_type == :merged_result
+ end
+
def head_pipeline_downloadable_path_for_report_type(file_type)
object.head_pipeline&.present(current_user: current_user)
&.downloadable_path_for_report_type(file_type)
@@ -161,11 +165,6 @@ class MergeRequestWidgetEntity < Grape::Entity
&.downloadable_path_for_report_type(file_type)
end
- def use_merge_base_with_merged_results?
- Feature.enabled?(:merge_base_pipelines, object.target_project) &&
- object.actual_head_pipeline&.merge_request_event_type == :merged_result
- end
-
def merge_base_pipeline_downloadable_path_for_report_type(file_type)
object.merge_base_pipeline&.present(current_user: current_user)
&.downloadable_path_for_report_type(file_type)
diff --git a/app/serializers/move_to_project_entity.rb b/app/serializers/move_to_project_entity.rb
index dac1124b0b3..fb1d1a64abd 100644
--- a/app/serializers/move_to_project_entity.rb
+++ b/app/serializers/move_to_project_entity.rb
@@ -3,4 +3,5 @@
class MoveToProjectEntity < Grape::Entity
expose :id
expose :name_with_namespace
+ expose :full_path
end
diff --git a/app/serializers/note_entity.rb b/app/serializers/note_entity.rb
index ef305195e22..9a96778786b 100644
--- a/app/serializers/note_entity.rb
+++ b/app/serializers/note_entity.rb
@@ -34,6 +34,10 @@ class NoteEntity < API::Entities::Note
expose :can_resolve do |note|
note.resolvable? && can?(current_user, :resolve_note, note)
end
+
+ expose :can_resolve_discussion do |note|
+ note.discussion.resolvable? && note.discussion.can_resolve?(current_user)
+ end
end
expose :suggestions, using: SuggestionEntity
@@ -77,11 +81,25 @@ class NoteEntity < API::Entities::Note
expose :cached_markdown_version
+ # Correctly rendering a note requires some background information about any
+ # discussion it is part of. This is essential for the notes endpoint, but
+ # optional for the discussions endpoint, which will include the discussion
+ # along with the note
+ expose :discussion, as: :base_discussion, using: BaseDiscussionEntity, if: -> (_, _) { with_base_discussion? }
+
private
+ def discussion
+ @discussion ||= object.to_discussion(request.noteable)
+ end
+
def current_user
request.current_user
end
+
+ def with_base_discussion?
+ options.fetch(:with_base_discussion, true)
+ end
end
NoteEntity.prepend_if_ee('EE::NoteEntity')
diff --git a/app/serializers/paginated_diff_entity.rb b/app/serializers/paginated_diff_entity.rb
index f24571f7d7d..fe59686278c 100644
--- a/app/serializers/paginated_diff_entity.rb
+++ b/app/serializers/paginated_diff_entity.rb
@@ -7,12 +7,19 @@
#
class PaginatedDiffEntity < Grape::Entity
include RequestAwareEntity
+ include DiffHelper
expose :diff_files do |diffs, options|
submodule_links = Gitlab::SubmoduleLinks.new(merge_request.project.repository)
- DiffFileEntity.represent(diffs.diff_files,
- options.merge(submodule_links: submodule_links, code_navigation_path: code_navigation_path(diffs)))
+ DiffFileEntity.represent(
+ diffs.diff_files,
+ options.merge(
+ submodule_links: submodule_links,
+ code_navigation_path: code_navigation_path(diffs),
+ conflicts: conflicts
+ )
+ )
end
expose :pagination do
@@ -36,10 +43,6 @@ class PaginatedDiffEntity < Grape::Entity
private
- def code_navigation_path(diffs)
- Gitlab::CodeNavigationPath.new(merge_request.project, diffs.diff_refs&.head_sha)
- end
-
%i[current_page next_page total_pages].each do |method|
define_method method do
pagination_data[method]
diff --git a/app/serializers/test_case_entity.rb b/app/serializers/test_case_entity.rb
index b44aa62ad73..299160cd1bf 100644
--- a/app/serializers/test_case_entity.rb
+++ b/app/serializers/test_case_entity.rb
@@ -10,6 +10,7 @@ class TestCaseEntity < Grape::Entity
expose :execution_time
expose :system_output
expose :stack_trace
+ expose :recent_failures
expose :attachment_url, if: -> (*) { can_read_screenshots? } do |test_case|
expose_url(test_case.attachment_url)
end
diff --git a/app/serializers/test_suite_comparer_entity.rb b/app/serializers/test_suite_comparer_entity.rb
index a9f19564b60..aab805f9598 100644
--- a/app/serializers/test_suite_comparer_entity.rb
+++ b/app/serializers/test_suite_comparer_entity.rb
@@ -1,9 +1,6 @@
# frozen_string_literal: true
class TestSuiteComparerEntity < Grape::Entity
- DEFAULT_MAX_TESTS = 100
- DEFAULT_MIN_TESTS = 10
-
expose :name
expose :total_status, as: :status
@@ -14,39 +11,27 @@ class TestSuiteComparerEntity < Grape::Entity
expose :error_count, as: :errored
end
- # rubocop: disable CodeReuse/ActiveRecord
expose :new_failures, using: TestCaseEntity do |suite|
- suite.new_failures.take(max_tests)
+ suite.limited_tests.new_failures
end
expose :existing_failures, using: TestCaseEntity do |suite|
- suite.existing_failures.take(
- max_tests(suite.new_failures))
+ suite.limited_tests.existing_failures
end
expose :resolved_failures, using: TestCaseEntity do |suite|
- suite.resolved_failures.take(
- max_tests(suite.new_failures, suite.existing_failures))
+ suite.limited_tests.resolved_failures
end
expose :new_errors, using: TestCaseEntity do |suite|
- suite.new_errors.take(max_tests)
+ suite.limited_tests.new_errors
end
expose :existing_errors, using: TestCaseEntity do |suite|
- suite.existing_errors.take(
- max_tests(suite.new_errors))
+ suite.limited_tests.existing_errors
end
expose :resolved_errors, using: TestCaseEntity do |suite|
- suite.resolved_errors.take(
- max_tests(suite.new_errors, suite.existing_errors))
- end
-
- private
-
- def max_tests(*used)
- [DEFAULT_MAX_TESTS - used.map(&:count).sum, DEFAULT_MIN_TESTS].max
+ suite.limited_tests.resolved_errors
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/services/admin/propagate_integration_service.rb b/app/services/admin/propagate_integration_service.rb
index 96a6d861e47..ddd5add42bd 100644
--- a/app/services/admin/propagate_integration_service.rb
+++ b/app/services/admin/propagate_integration_service.rb
@@ -5,12 +5,12 @@ module Admin
include PropagateService
def propagate
- update_inherited_integrations
-
if integration.instance?
- create_integration_for_groups_without_integration if Feature.enabled?(:group_level_integrations)
+ update_inherited_integrations
+ create_integration_for_groups_without_integration if Feature.enabled?(:group_level_integrations, default_enabled: true)
create_integration_for_projects_without_integration
else
+ update_inherited_descendant_integrations
create_integration_for_groups_without_integration_belonging_to_group
create_integration_for_projects_without_integration_belonging_to_group
end
@@ -18,34 +18,39 @@ module Admin
private
- # rubocop: disable Cop/InBatches
def update_inherited_integrations
- Service.by_type(integration.type).inherit_from_id(integration.id).in_batches(of: BATCH_SIZE) do |services|
- min_id, max_id = services.pick("MIN(services.id), MAX(services.id)")
- PropagateIntegrationInheritWorker.perform_async(integration.id, min_id, max_id)
- end
+ propagate_integrations(
+ Service.by_type(integration.type).inherit_from_id(integration.id),
+ PropagateIntegrationInheritWorker
+ )
+ end
+
+ def update_inherited_descendant_integrations
+ propagate_integrations(
+ Service.inherited_descendants_from_self_or_ancestors_from(integration),
+ PropagateIntegrationInheritDescendantWorker
+ )
end
- # rubocop: enable Cop/InBatches
def create_integration_for_groups_without_integration
- Group.without_integration(integration).each_batch(of: BATCH_SIZE) do |groups|
- min_id, max_id = groups.pick("MIN(namespaces.id), MAX(namespaces.id)")
- PropagateIntegrationGroupWorker.perform_async(integration.id, min_id, max_id)
- end
+ propagate_integrations(
+ Group.without_integration(integration),
+ PropagateIntegrationGroupWorker
+ )
end
def create_integration_for_groups_without_integration_belonging_to_group
- integration.group.descendants.without_integration(integration).each_batch(of: BATCH_SIZE) do |groups|
- min_id, max_id = groups.pick("MIN(namespaces.id), MAX(namespaces.id)")
- PropagateIntegrationGroupWorker.perform_async(integration.id, min_id, max_id)
- end
+ propagate_integrations(
+ integration.group.descendants.without_integration(integration),
+ PropagateIntegrationGroupWorker
+ )
end
def create_integration_for_projects_without_integration_belonging_to_group
- Project.without_integration(integration).in_namespace(integration.group.self_and_descendants).each_batch(of: BATCH_SIZE) do |projects|
- min_id, max_id = projects.pick("MIN(projects.id), MAX(projects.id)")
- PropagateIntegrationProjectWorker.perform_async(integration.id, min_id, max_id)
- end
+ propagate_integrations(
+ Project.without_integration(integration).in_namespace(integration.group.self_and_descendants),
+ PropagateIntegrationProjectWorker
+ )
end
end
end
diff --git a/app/services/alert_management/http_integrations/create_service.rb b/app/services/alert_management/http_integrations/create_service.rb
new file mode 100644
index 00000000000..576e38c23aa
--- /dev/null
+++ b/app/services/alert_management/http_integrations/create_service.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module AlertManagement
+ module HttpIntegrations
+ class CreateService
+ # @param project [Project]
+ # @param current_user [User]
+ # @param params [Hash]
+ def initialize(project, current_user, params)
+ @project = project
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute
+ return error_no_permissions unless allowed?
+ return error_multiple_integrations unless creation_allowed?
+
+ integration = project.alert_management_http_integrations.create(params)
+ return error_in_create(integration) unless integration.valid?
+
+ success(integration)
+ end
+
+ private
+
+ attr_reader :project, :current_user, :params
+
+ def allowed?
+ current_user&.can?(:admin_operations, project)
+ end
+
+ def creation_allowed?
+ project.alert_management_http_integrations.empty?
+ end
+
+ def error(message)
+ ServiceResponse.error(message: message)
+ end
+
+ def success(integration)
+ ServiceResponse.success(payload: { integration: integration })
+ end
+
+ def error_no_permissions
+ error(_('You have insufficient permissions to create an HTTP integration for this project'))
+ end
+
+ def error_multiple_integrations
+ error(_('Multiple HTTP integrations are not supported for this project'))
+ end
+
+ def error_in_create(integration)
+ error(integration.errors.full_messages.to_sentence)
+ end
+ end
+ end
+end
+
+::AlertManagement::HttpIntegrations::CreateService.prepend_if_ee('::EE::AlertManagement::HttpIntegrations::CreateService')
diff --git a/app/services/alert_management/http_integrations/destroy_service.rb b/app/services/alert_management/http_integrations/destroy_service.rb
new file mode 100644
index 00000000000..aeb3f6cb807
--- /dev/null
+++ b/app/services/alert_management/http_integrations/destroy_service.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module AlertManagement
+ module HttpIntegrations
+ class DestroyService
+ # @param integration [AlertManagement::HttpIntegration]
+ # @param current_user [User]
+ def initialize(integration, current_user)
+ @integration = integration
+ @current_user = current_user
+ end
+
+ def execute
+ return error_no_permissions unless allowed?
+
+ if integration.destroy
+ success
+ else
+ error(integration.errors.full_messages.to_sentence)
+ end
+ end
+
+ private
+
+ attr_reader :integration, :current_user
+
+ def allowed?
+ current_user&.can?(:admin_operations, integration)
+ end
+
+ def error(message)
+ ServiceResponse.error(message: message)
+ end
+
+ def success
+ ServiceResponse.success(payload: { integration: integration })
+ end
+
+ def error_no_permissions
+ error(_('You have insufficient permissions to remove this HTTP integration'))
+ end
+ end
+ end
+end
diff --git a/app/services/alert_management/http_integrations/update_service.rb b/app/services/alert_management/http_integrations/update_service.rb
new file mode 100644
index 00000000000..220c4e759f0
--- /dev/null
+++ b/app/services/alert_management/http_integrations/update_service.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module AlertManagement
+ module HttpIntegrations
+ class UpdateService
+ # @param integration [AlertManagement::HttpIntegration]
+ # @param current_user [User]
+ # @param params [Hash]
+ def initialize(integration, current_user, params)
+ @integration = integration
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute
+ return error_no_permissions unless allowed?
+
+ params[:token] = nil if params.delete(:regenerate_token)
+
+ if integration.update(params)
+ success
+ else
+ error(integration.errors.full_messages.to_sentence)
+ end
+ end
+
+ private
+
+ attr_reader :integration, :current_user, :params
+
+ def allowed?
+ current_user&.can?(:admin_operations, integration)
+ end
+
+ def error(message)
+ ServiceResponse.error(message: message)
+ end
+
+ def success
+ ServiceResponse.success(payload: { integration: integration.reset })
+ end
+
+ def error_no_permissions
+ error(_('You have insufficient permissions to update this HTTP integration'))
+ end
+ end
+ end
+end
diff --git a/app/services/alert_management/process_prometheus_alert_service.rb b/app/services/alert_management/process_prometheus_alert_service.rb
index 5c7698f724a..28ce5401a6c 100644
--- a/app/services/alert_management/process_prometheus_alert_service.rb
+++ b/app/services/alert_management/process_prometheus_alert_service.rb
@@ -9,6 +9,10 @@ module AlertManagement
return bad_request unless incoming_payload.has_required_attributes?
process_alert_management_alert
+ return bad_request unless alert.persisted?
+
+ process_incident_issues if process_issues?
+ send_alert_email if send_email?
ServiceResponse.success
end
@@ -30,8 +34,6 @@ module AlertManagement
else
create_alert_management_alert
end
-
- process_incident_issues if process_issues?
end
def reset_alert_management_alert_status
@@ -85,12 +87,17 @@ module AlertManagement
end
def process_incident_issues
- return unless alert.persisted?
- return if alert.issue
+ return if alert.issue || alert.resolved?
IncidentManagement::ProcessAlertWorker.perform_async(nil, nil, alert.id)
end
+ def send_alert_email
+ notification_service
+ .async
+ .prometheus_alerts_fired(project, [alert])
+ end
+
def logger
@logger ||= Gitlab::AppLogger
end
diff --git a/app/services/alert_management/sync_alert_service_data_service.rb b/app/services/alert_management/sync_alert_service_data_service.rb
new file mode 100644
index 00000000000..1ba197065c5
--- /dev/null
+++ b/app/services/alert_management/sync_alert_service_data_service.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module AlertManagement
+ class SyncAlertServiceDataService
+ # @param alert_service [AlertsService]
+ def initialize(alert_service)
+ @alert_service = alert_service
+ end
+
+ def execute
+ http_integration = find_http_integration
+
+ result = if http_integration
+ update_integration_data(http_integration)
+ else
+ create_integration
+ end
+
+ result ? ServiceResponse.success : ServiceResponse.error(message: 'Update failed')
+ end
+
+ private
+
+ attr_reader :alert_service
+
+ def find_http_integration
+ AlertManagement::HttpIntegrationsFinder.new(
+ alert_service.project,
+ endpoint_identifier: ::AlertManagement::HttpIntegration::LEGACY_IDENTIFIER
+ )
+ .execute
+ .first
+ end
+
+ def create_integration
+ new_integration = AlertManagement::HttpIntegration.create(
+ project_id: alert_service.project_id,
+ name: 'HTTP endpoint',
+ endpoint_identifier: AlertManagement::HttpIntegration::LEGACY_IDENTIFIER,
+ active: alert_service.active,
+ encrypted_token: alert_service.data.encrypted_token,
+ encrypted_token_iv: alert_service.data.encrypted_token_iv
+ )
+
+ new_integration.persisted?
+ end
+
+ def update_integration_data(http_integration)
+ http_integration.update(
+ active: alert_service.active,
+ encrypted_token: alert_service.data.encrypted_token,
+ encrypted_token_iv: alert_service.data.encrypted_token_iv
+ )
+ end
+ end
+end
diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb
index 3c21844ec62..d1558c60c3d 100644
--- a/app/services/audit_event_service.rb
+++ b/app/services/audit_event_service.rb
@@ -16,7 +16,7 @@ class AuditEventService
@author = build_author(author)
@entity = entity
@details = details
- @ip_address = (@details[:ip_address].presence || @author.current_sign_in_ip)
+ @ip_address = resolve_ip_address(@details, @author)
end
# Builds the @details attribute for authentication
@@ -64,6 +64,12 @@ class AuditEventService
end
end
+ def resolve_ip_address(details, author)
+ details[:ip_address].presence ||
+ Gitlab::RequestContext.instance.client_ip ||
+ author.current_sign_in_ip
+ end
+
def base_payload
{
author_id: @author.id,
diff --git a/app/services/bulk_create_integration_service.rb b/app/services/bulk_create_integration_service.rb
index 23b89b0d8a9..61c5565db60 100644
--- a/app/services/bulk_create_integration_service.rb
+++ b/app/services/bulk_create_integration_service.rb
@@ -11,6 +11,8 @@ class BulkCreateIntegrationService
service_list = ServiceList.new(batch, service_hash, association).to_array
Service.transaction do
+ run_callbacks(batch) if association == 'project'
+
results = bulk_insert(*service_list)
if integration.data_fields_present?
@@ -18,8 +20,6 @@ class BulkCreateIntegrationService
bulk_insert(*data_list)
end
-
- run_callbacks(batch) if association == 'project'
end
end
@@ -35,11 +35,11 @@ class BulkCreateIntegrationService
# rubocop: disable CodeReuse/ActiveRecord
def run_callbacks(batch)
- if integration.issue_tracker?
+ if integration.external_issue_tracker?
Project.where(id: batch.select(:id)).update_all(has_external_issue_tracker: true)
end
- if integration.type == 'ExternalWikiService'
+ if integration.external_wiki?
Project.where(id: batch.select(:id)).update_all(has_external_wiki: true)
end
end
@@ -49,7 +49,7 @@ class BulkCreateIntegrationService
if integration.template?
integration.to_service_hash
else
- integration.to_service_hash.tap { |json| json['inherit_from_id'] = integration.id }
+ integration.to_service_hash.tap { |json| json['inherit_from_id'] = integration.inherit_from_id || integration.id }
end
end
diff --git a/app/services/bulk_import_service.rb b/app/services/bulk_import_service.rb
new file mode 100644
index 00000000000..bebf9153ce7
--- /dev/null
+++ b/app/services/bulk_import_service.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+# Entry point of the BulkImport feature.
+# This service receives a Gitlab Instance connection params
+# and a list of groups to be imported.
+#
+# Process topography:
+#
+# sync | async
+# |
+# User +--> P1 +----> Pn +---+
+# | ^ | Enqueue new job
+# | +-----+
+#
+# P1 (sync)
+#
+# - Create a BulkImport record
+# - Create a BulkImport::Entity for each group to be imported
+# - Enqueue a BulkImportWorker job (P2) to import the given groups (entities)
+#
+# Pn (async)
+#
+# - For each group to be imported (BulkImport::Entity.with_status(:created))
+# - Import the group data
+# - Create entities for each subgroup of the imported group
+# - Enqueue a BulkImportService job (Pn) to import the new entities (subgroups)
+#
+class BulkImportService
+ attr_reader :current_user, :params, :credentials
+
+ def initialize(current_user, params, credentials)
+ @current_user = current_user
+ @params = params
+ @credentials = credentials
+ end
+
+ def execute
+ bulk_import = create_bulk_import
+
+ BulkImportWorker.perform_async(bulk_import.id)
+ end
+
+ private
+
+ def create_bulk_import
+ BulkImport.transaction do
+ bulk_import = BulkImport.create!(user: current_user, source_type: 'gitlab')
+ bulk_import.create_configuration!(credentials.slice(:url, :access_token))
+
+ params.each do |entity|
+ BulkImports::Entity.create!(
+ bulk_import: bulk_import,
+ source_type: entity[:source_type],
+ source_full_path: entity[:source_full_path],
+ destination_name: entity[:destination_name],
+ destination_namespace: entity[:destination_namespace]
+ )
+ end
+
+ bulk_import
+ end
+ end
+end
diff --git a/app/services/bulk_update_integration_service.rb b/app/services/bulk_update_integration_service.rb
index 74d77618f2c..5ddfdd359c2 100644
--- a/app/services/bulk_update_integration_service.rb
+++ b/app/services/bulk_update_integration_service.rb
@@ -9,7 +9,7 @@ class BulkUpdateIntegrationService
# rubocop: disable CodeReuse/ActiveRecord
def execute
Service.transaction do
- batch.update_all(service_hash)
+ Service.where(id: batch.select(:id)).update_all(service_hash)
if integration.data_fields_present?
integration.data_fields.class.where(service_id: batch.select(:id)).update_all(data_fields_hash)
@@ -23,7 +23,7 @@ class BulkUpdateIntegrationService
attr_reader :integration, :batch
def service_hash
- integration.to_service_hash.tap { |json| json['inherit_from_id'] = integration.id }
+ integration.to_service_hash.tap { |json| json['inherit_from_id'] = integration.inherit_from_id || integration.id }
end
def data_fields_hash
diff --git a/app/services/ci/append_build_trace_service.rb b/app/services/ci/append_build_trace_service.rb
new file mode 100644
index 00000000000..602f8c5030d
--- /dev/null
+++ b/app/services/ci/append_build_trace_service.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module Ci
+ class AppendBuildTraceService
+ Result = Struct.new(:status, :stream_size, keyword_init: true)
+ TraceRangeError = Class.new(StandardError)
+
+ attr_reader :build, :params
+
+ def initialize(build, params)
+ @build = build
+ @params = params
+ end
+
+ def execute(body_data)
+ # TODO:
+ # it seems that `Content-Range` as formatted by runner is wrong,
+ # the `byte_end` should point to final byte, but it points byte+1
+ # that means that we have to calculate end of body,
+ # as we cannot use `content_length[1]`
+ # Issue: https://gitlab.com/gitlab-org/gitlab-runner/issues/3275
+
+ content_range = stream_range.split('-')
+ body_start = content_range[0].to_i
+ body_end = body_start + body_data.bytesize
+
+ stream_size = build.trace.append(body_data, body_start)
+
+ unless stream_size == body_end
+ log_range_error(stream_size, body_end)
+
+ return Result.new(status: 416, stream_size: stream_size)
+ end
+
+ Result.new(status: 202, stream_size: stream_size)
+ end
+
+ private
+
+ def stream_range
+ params.fetch(:content_range)
+ end
+
+ def log_range_error(stream_size, body_end)
+ extra = {
+ build_id: build.id,
+ body_end: body_end,
+ stream_size: stream_size,
+ stream_class: stream_size.class,
+ stream_range: stream_range
+ }
+
+ build.trace_chunks.last.try do |chunk|
+ extra.merge!(
+ chunk_index: chunk.chunk_index,
+ chunk_store: chunk.data_store,
+ chunks_count: build.trace_chunks.count
+ )
+ end
+
+ ::Gitlab::ErrorTracking
+ .log_exception(TraceRangeError.new, extra)
+ end
+ end
+end
diff --git a/app/services/ci/build_report_result_service.rb b/app/services/ci/build_report_result_service.rb
index 76ecf428f11..f138aa91236 100644
--- a/app/services/ci/build_report_result_service.rb
+++ b/app/services/ci/build_report_result_service.rb
@@ -39,8 +39,6 @@ module Ci
end
def track_test_cases(build, test_suite)
- return if Feature.disabled?(:track_unique_test_cases_parsed, build.project)
-
track_usage_event(EVENT_NAME, test_case_hashes(build, test_suite))
end
diff --git a/app/services/ci/compare_reports_base_service.rb b/app/services/ci/compare_reports_base_service.rb
index 2e84f914db3..9aba3a50ec1 100644
--- a/app/services/ci/compare_reports_base_service.rb
+++ b/app/services/ci/compare_reports_base_service.rb
@@ -8,7 +8,9 @@ module Ci
# issue: https://gitlab.com/gitlab-org/gitlab/issues/34224
class CompareReportsBaseService < ::BaseService
def execute(base_pipeline, head_pipeline)
- comparer = build_comparer(base_pipeline, head_pipeline)
+ base_report = get_report(base_pipeline)
+ head_report = get_report(head_pipeline)
+ comparer = build_comparer(base_report, head_report)
{
status: :parsed,
@@ -31,8 +33,8 @@ module Ci
protected
- def build_comparer(base_pipeline, head_pipeline)
- comparer_class.new(get_report(base_pipeline), get_report(head_pipeline))
+ def build_comparer(base_report, head_report)
+ comparer_class.new(base_report, head_report)
end
private
diff --git a/app/services/ci/compare_test_reports_service.rb b/app/services/ci/compare_test_reports_service.rb
index 382d5b8995f..ed85ca8274c 100644
--- a/app/services/ci/compare_test_reports_service.rb
+++ b/app/services/ci/compare_test_reports_service.rb
@@ -13,5 +13,19 @@ module Ci
def get_report(pipeline)
pipeline&.test_reports
end
+
+ def build_comparer(base_report, head_report)
+ # We need to load the test failure history on the test comparer because we display
+ # this on the MR widget
+ super.tap do |test_reports_comparer|
+ ::Gitlab::Ci::Reports::TestFailureHistory.new(failed_test_cases(test_reports_comparer), project).load!
+ end
+ end
+
+ def failed_test_cases(test_reports_comparer)
+ test_reports_comparer.suite_comparers.flat_map do |suite_comparer|
+ suite_comparer.limited_tests.new_failures + suite_comparer.limited_tests.existing_failures
+ end
+ end
end
end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index e7ede98fea4..e3bab2de44e 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -14,6 +14,7 @@ module Ci
Gitlab::Ci::Pipeline::Chain::Config::Process,
Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs,
Gitlab::Ci::Pipeline::Chain::Skip,
+ Gitlab::Ci::Pipeline::Chain::SeedBlock,
Gitlab::Ci::Pipeline::Chain::EvaluateWorkflowRules,
Gitlab::Ci::Pipeline::Chain::Seed,
Gitlab::Ci::Pipeline::Chain::Limit::Size,
diff --git a/app/services/ci/daily_build_group_report_result_service.rb b/app/services/ci/daily_build_group_report_result_service.rb
index c32fc27c274..bc966fb9634 100644
--- a/app/services/ci/daily_build_group_report_result_service.rb
+++ b/app/services/ci/daily_build_group_report_result_service.rb
@@ -13,7 +13,8 @@ module Ci
project_id: pipeline.project_id,
ref_path: pipeline.source_ref_path,
date: pipeline.created_at.to_date,
- last_pipeline_id: pipeline.id
+ last_pipeline_id: pipeline.id,
+ default_branch: pipeline.default_branch?
}
aggregate(pipeline.builds.with_coverage).map do |group_name, group|
diff --git a/app/services/ci/destroy_expired_job_artifacts_service.rb b/app/services/ci/destroy_expired_job_artifacts_service.rb
index 438b5c7496d..6e7caba8545 100644
--- a/app/services/ci/destroy_expired_job_artifacts_service.rb
+++ b/app/services/ci/destroy_expired_job_artifacts_service.rb
@@ -4,47 +4,90 @@ module Ci
class DestroyExpiredJobArtifactsService
include ::Gitlab::ExclusiveLeaseHelpers
include ::Gitlab::LoopHelpers
+ include ::Gitlab::Utils::StrongMemoize
BATCH_SIZE = 100
- LOOP_TIMEOUT = 45.minutes
+ LOOP_TIMEOUT = 5.minutes
LOOP_LIMIT = 1000
EXCLUSIVE_LOCK_KEY = 'expired_job_artifacts:destroy:lock'
- LOCK_TIMEOUT = 50.minutes
+ LOCK_TIMEOUT = 6.minutes
##
# Destroy expired job artifacts on GitLab instance
#
- # This destroy process cannot run for more than 45 minutes. This is for
+ # This destroy process cannot run for more than 6 minutes. This is for
# preventing multiple `ExpireBuildArtifactsWorker` CRON jobs run concurrently,
- # which is scheduled at every hour.
+ # which is scheduled every 7 minutes.
def execute
in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
- destroy_batch(Ci::JobArtifact) || destroy_batch(Ci::PipelineArtifact)
+ destroy_artifacts_batch
end
end
end
private
- def destroy_batch(klass)
- artifact_batch = if klass == Ci::JobArtifact
- klass.expired(BATCH_SIZE).unlocked
- else
- klass.expired(BATCH_SIZE)
- end
+ def destroy_artifacts_batch
+ destroy_job_artifacts_batch || destroy_pipeline_artifacts_batch
+ end
+
+ def destroy_job_artifacts_batch
+ artifacts = Ci::JobArtifact
+ .expired(BATCH_SIZE)
+ .unlocked
+ .with_destroy_preloads
+ .to_a
+
+ return false if artifacts.empty?
- artifacts = artifact_batch.to_a
+ parallel_destroy_batch(artifacts)
+ true
+ end
+ # TODO: Make sure this can also be parallelized
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/270973
+ def destroy_pipeline_artifacts_batch
+ artifacts = Ci::PipelineArtifact.expired(BATCH_SIZE).to_a
return false if artifacts.empty?
artifacts.each(&:destroy!)
- run_after_destroy(artifacts)
- true # This is required because of the design of `loop_until` method.
+ true
+ end
+
+ def parallel_destroy_batch(job_artifacts)
+ Ci::DeletedObject.transaction do
+ Ci::DeletedObject.bulk_import(job_artifacts)
+ Ci::JobArtifact.id_in(job_artifacts.map(&:id)).delete_all
+ destroy_related_records_for(job_artifacts)
+ end
+
+ # This is executed outside of the transaction because it depends on Redis
+ update_statistics_for(job_artifacts)
+ destroyed_artifacts_counter.increment({}, job_artifacts.size)
+ end
+
+ # This method is implemented in EE and it must do only database work
+ def destroy_related_records_for(job_artifacts); end
+
+ def update_statistics_for(job_artifacts)
+ artifacts_by_project = job_artifacts.group_by(&:project)
+ artifacts_by_project.each do |project, artifacts|
+ delta = -artifacts.sum { |artifact| artifact.size.to_i }
+ ProjectStatistics.increment_statistic(
+ project, Ci::JobArtifact.project_statistics_name, delta)
+ end
end
- def run_after_destroy(artifacts); end
+ def destroyed_artifacts_counter
+ strong_memoize(:destroyed_artifacts_counter) do
+ name = :destroyed_job_artifacts_count_total
+ comment = 'Counter of destroyed expired job artifacts'
+
+ ::Gitlab::Metrics.counter(name, comment)
+ end
+ end
end
end
diff --git a/app/services/ci/list_config_variables_service.rb b/app/services/ci/list_config_variables_service.rb
index b5dc192b512..4a5b3a92a2c 100644
--- a/app/services/ci/list_config_variables_service.rb
+++ b/app/services/ci/list_config_variables_service.rb
@@ -6,7 +6,10 @@ module Ci
config = project.ci_config_for(sha)
return {} unless config
- result = Gitlab::Ci::YamlProcessor.new(config).execute
+ result = Gitlab::Ci::YamlProcessor.new(config, project: project,
+ user: current_user,
+ sha: sha).execute
+
result.valid? ? result.variables_with_data : {}
end
end
diff --git a/app/services/ci/parse_dotenv_artifact_service.rb b/app/services/ci/parse_dotenv_artifact_service.rb
index 71b306864b2..2ee9be476bb 100644
--- a/app/services/ci/parse_dotenv_artifact_service.rb
+++ b/app/services/ci/parse_dotenv_artifact_service.rb
@@ -3,7 +3,7 @@
module Ci
class ParseDotenvArtifactService < ::BaseService
MAX_ACCEPTABLE_DOTENV_SIZE = 5.kilobytes
- MAX_ACCEPTABLE_VARIABLES_COUNT = 10
+ MAX_ACCEPTABLE_VARIABLES_COUNT = 20
SizeLimitError = Class.new(StandardError)
ParserError = Class.new(StandardError)
diff --git a/app/services/ci/test_cases_service.rb b/app/services/ci/test_cases_service.rb
new file mode 100644
index 00000000000..3139b567571
--- /dev/null
+++ b/app/services/ci/test_cases_service.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Ci
+ class TestCasesService
+ MAX_TRACKABLE_FAILURES = 200
+
+ def execute(build)
+ return unless Feature.enabled?(:test_failure_history, build.project)
+ return unless build.has_test_reports?
+ return unless build.project.default_branch_or_master == build.ref
+
+ test_suite = generate_test_suite_report(build)
+
+ track_failures(build, test_suite)
+ end
+
+ private
+
+ def generate_test_suite_report(build)
+ build.collect_test_reports!(Gitlab::Ci::Reports::TestReports.new)
+ end
+
+ def track_failures(build, test_suite)
+ return if test_suite.failed_count > MAX_TRACKABLE_FAILURES
+
+ test_suite.failed.keys.each_slice(100) do |keys|
+ Ci::TestCase.transaction do
+ test_cases = Ci::TestCase.find_or_create_by_batch(build.project, keys)
+ Ci::TestCaseFailure.insert_all(test_case_failures(test_cases, build))
+ end
+ end
+ end
+
+ def test_case_failures(test_cases, build)
+ test_cases.map do |test_case|
+ {
+ test_case_id: test_case.id,
+ build_id: build.id,
+ failed_at: build.finished_at
+ }
+ end
+ end
+ end
+end
diff --git a/app/services/ci/update_build_state_service.rb b/app/services/ci/update_build_state_service.rb
index 22a27906700..fb67b0d2355 100644
--- a/app/services/ci/update_build_state_service.rb
+++ b/app/services/ci/update_build_state_service.rb
@@ -163,16 +163,18 @@ module Ci
end
def ensure_pending_state
- Ci::BuildPendingState.create_or_find_by!(
+ build_state = Ci::BuildPendingState.safe_find_or_create_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
+ unless build_state.present?
+ metrics.increment_trace_operation(operation: :conflict)
+ end
+
+ build_state || build.pending_state
end
##
diff --git a/app/services/clusters/aws/authorize_role_service.rb b/app/services/clusters/aws/authorize_role_service.rb
index 2712a4b05bb..188c4aebc5f 100644
--- a/app/services/clusters/aws/authorize_role_service.rb
+++ b/app/services/clusters/aws/authorize_role_service.rb
@@ -17,7 +17,8 @@ module Clusters
def initialize(user, params:)
@user = user
- @params = params
+ @role_arn = params[:role_arn]
+ @region = params[:region]
end
def execute
@@ -33,14 +34,14 @@ module Clusters
private
- attr_reader :role, :params
+ attr_reader :role, :role_arn, :region
def ensure_role_exists!
@role = ::Aws::Role.find_by_user_id!(user.id)
end
def update_role_arn!
- role.update!(params)
+ role.update!(role_arn: role_arn, region: region)
end
def credentials
diff --git a/app/services/clusters/aws/fetch_credentials_service.rb b/app/services/clusters/aws/fetch_credentials_service.rb
index 33efc4cc120..96abbb43969 100644
--- a/app/services/clusters/aws/fetch_credentials_service.rb
+++ b/app/services/clusters/aws/fetch_credentials_service.rb
@@ -10,6 +10,7 @@ module Clusters
def initialize(provision_role, provider: nil)
@provision_role = provision_role
@provider = provider
+ @region = provider&.region || provision_role&.region || Clusters::Providers::Aws::DEFAULT_REGION
end
def execute
@@ -26,7 +27,7 @@ module Clusters
private
- attr_reader :provider
+ attr_reader :provider, :region
def client
::Aws::STS::Client.new(credentials: gitlab_credentials, region: region)
@@ -44,10 +45,6 @@ module Clusters
Gitlab::CurrentSettings.eks_secret_access_key
end
- def region
- provider&.region || Clusters::Providers::Aws::DEFAULT_REGION
- end
-
##
# If we haven't created a provider record yet,
# we restrict ourselves to read only access so
diff --git a/app/services/clusters/kubernetes.rb b/app/services/clusters/kubernetes.rb
index aafea64c820..819ac4c8464 100644
--- a/app/services/clusters/kubernetes.rb
+++ b/app/services/clusters/kubernetes.rb
@@ -7,7 +7,7 @@ module Clusters
GITLAB_ADMIN_TOKEN_NAME = 'gitlab-token'
GITLAB_CLUSTER_ROLE_BINDING_NAME = 'gitlab-admin'
GITLAB_CLUSTER_ROLE_NAME = 'cluster-admin'
- PROJECT_CLUSTER_ROLE_NAME = 'edit'
+ PROJECT_CLUSTER_ROLE_NAME = 'admin'
GITLAB_KNATIVE_SERVING_ROLE_NAME = 'gitlab-knative-serving-role'
GITLAB_KNATIVE_SERVING_ROLE_BINDING_NAME = 'gitlab-knative-serving-rolebinding'
GITLAB_CROSSPLANE_DATABASE_ROLE_NAME = 'gitlab-crossplane-database-role'
diff --git a/app/services/clusters/kubernetes/create_or_update_service_account_service.rb b/app/services/clusters/kubernetes/create_or_update_service_account_service.rb
index 2725a3aeaa5..eabc428d0d2 100644
--- a/app/services/clusters/kubernetes/create_or_update_service_account_service.rb
+++ b/app/services/clusters/kubernetes/create_or_update_service_account_service.rb
@@ -69,7 +69,13 @@ module Clusters
def create_role_or_cluster_role_binding
if namespace_creator
- kubeclient.create_or_update_role_binding(role_binding_resource)
+ begin
+ kubeclient.delete_role_binding(role_binding_name, service_account_namespace)
+ rescue Kubeclient::ResourceNotFoundError
+ # Do nothing as we will create new role binding below
+ end
+
+ kubeclient.update_role_binding(role_binding_resource)
else
kubeclient.create_or_update_cluster_role_binding(cluster_role_binding_resource)
end
@@ -117,11 +123,9 @@ module Clusters
end
def role_binding_resource
- role_name = Feature.enabled?(:kubernetes_cluster_namespace_role_admin) ? 'admin' : Clusters::Kubernetes::PROJECT_CLUSTER_ROLE_NAME
-
Gitlab::Kubernetes::RoleBinding.new(
name: role_binding_name,
- role_name: role_name,
+ role_name: Clusters::Kubernetes::PROJECT_CLUSTER_ROLE_NAME,
role_kind: :ClusterRole,
namespace: service_account_namespace,
service_account_name: service_account_name
diff --git a/app/services/concerns/admin/propagate_service.rb b/app/services/concerns/admin/propagate_service.rb
index 065ab6f7ff9..03e422aec54 100644
--- a/app/services/concerns/admin/propagate_service.rb
+++ b/app/services/concerns/admin/propagate_service.rb
@@ -21,9 +21,16 @@ module Admin
attr_reader :integration
def create_integration_for_projects_without_integration
- Project.without_integration(integration).each_batch(of: BATCH_SIZE) do |projects|
- min_id, max_id = projects.pick("MIN(projects.id), MAX(projects.id)")
- PropagateIntegrationProjectWorker.perform_async(integration.id, min_id, max_id)
+ propagate_integrations(
+ Project.without_integration(integration),
+ PropagateIntegrationProjectWorker
+ )
+ end
+
+ def propagate_integrations(relation, worker_class)
+ relation.each_batch(of: BATCH_SIZE) do |records|
+ min_id, max_id = records.pick("MIN(#{relation.table_name}.id), MAX(#{relation.table_name}.id)")
+ worker_class.perform_async(integration.id, min_id, max_id)
end
end
end
diff --git a/app/services/concerns/integrations/project_test_data.rb b/app/services/concerns/integrations/project_test_data.rb
index 4d551430315..72c12cfb394 100644
--- a/app/services/concerns/integrations/project_test_data.rb
+++ b/app/services/concerns/integrations/project_test_data.rb
@@ -58,5 +58,12 @@ module Integrations
Gitlab::DataBuilder::Deployment.build(deployment)
end
+
+ def releases_events_data
+ release = project.releases.first
+ return { error: s_('TestHooks|Ensure the project has releases.') } unless release.present?
+
+ release.to_hook_data('create')
+ end
end
end
diff --git a/app/services/concerns/users/participable_service.rb b/app/services/concerns/users/participable_service.rb
index 6fde9abfdb0..fac8e91d216 100644
--- a/app/services/concerns/users/participable_service.rb
+++ b/app/services/concerns/users/participable_service.rb
@@ -45,7 +45,8 @@ module Users
type: user.class.name,
username: user.username,
name: user.name,
- avatar_url: user.avatar_url
+ avatar_url: user.avatar_url,
+ availability: user&.status&.availability
}
end
diff --git a/app/services/container_expiration_policies/cleanup_service.rb b/app/services/container_expiration_policies/cleanup_service.rb
new file mode 100644
index 00000000000..f2bc2beab63
--- /dev/null
+++ b/app/services/container_expiration_policies/cleanup_service.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module ContainerExpirationPolicies
+ class CleanupService
+ attr_reader :repository
+
+ def initialize(repository)
+ @repository = repository
+ end
+
+ def execute
+ return ServiceResponse.error(message: 'no repository') unless repository
+
+ repository.start_expiration_policy!
+
+ result = Projects::ContainerRepository::CleanupTagsService
+ .new(project, nil, policy_params.merge('container_expiration_policy' => true))
+ .execute(repository)
+
+ if result[:status] == :success
+ repository.update!(
+ expiration_policy_cleanup_status: :cleanup_unscheduled,
+ expiration_policy_started_at: nil
+ )
+ success(:finished)
+ else
+ repository.cleanup_unfinished!
+
+ success(:unfinished)
+ end
+ end
+
+ private
+
+ def success(cleanup_status)
+ ServiceResponse.success(message: "cleanup #{cleanup_status}", payload: { cleanup_status: cleanup_status, container_repository_id: repository.id })
+ end
+
+ def policy_params
+ return {} unless policy
+
+ policy.policy_params
+ end
+
+ def policy
+ project.container_expiration_policy
+ end
+
+ def project
+ repository&.project
+ end
+ end
+end
diff --git a/app/services/container_expiration_policy_service.rb b/app/services/container_expiration_policy_service.rb
index 80f32298323..cf5d702a9ef 100644
--- a/app/services/container_expiration_policy_service.rb
+++ b/app/services/container_expiration_policy_service.rb
@@ -4,20 +4,14 @@ class ContainerExpirationPolicyService < BaseService
InvalidPolicyError = Class.new(StandardError)
def execute(container_expiration_policy)
- unless container_expiration_policy.valid?
- container_expiration_policy.disable!
- raise InvalidPolicyError
- end
-
container_expiration_policy.schedule_next_run!
container_expiration_policy.container_repositories.find_each do |container_repository|
CleanupContainerRepositoryWorker.perform_async(
nil,
container_repository.id,
- container_expiration_policy.attributes
- .except('created_at', 'updated_at')
- .merge(container_expiration_policy: true)
+ container_expiration_policy.policy_params
+ .merge(container_expiration_policy: true)
)
end
end
diff --git a/app/services/dependency_proxy/base_service.rb b/app/services/dependency_proxy/base_service.rb
new file mode 100644
index 00000000000..1b2d4b14a27
--- /dev/null
+++ b/app/services/dependency_proxy/base_service.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module DependencyProxy
+ class BaseService < ::BaseService
+ private
+
+ def registry
+ DependencyProxy::Registry
+ end
+
+ def auth_headers
+ {
+ Authorization: "Bearer #{@token}"
+ }
+ end
+ end
+end
diff --git a/app/services/dependency_proxy/download_blob_service.rb b/app/services/dependency_proxy/download_blob_service.rb
new file mode 100644
index 00000000000..3c690683bf6
--- /dev/null
+++ b/app/services/dependency_proxy/download_blob_service.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module DependencyProxy
+ class DownloadBlobService < DependencyProxy::BaseService
+ class DownloadError < StandardError
+ attr_reader :http_status
+
+ def initialize(message, http_status)
+ @http_status = http_status
+
+ super(message)
+ end
+ end
+
+ def initialize(image, blob_sha, token)
+ @image = image
+ @blob_sha = blob_sha
+ @token = token
+ @temp_file = Tempfile.new
+ end
+
+ def execute
+ File.open(@temp_file.path, "wb") do |file|
+ Gitlab::HTTP.get(blob_url, headers: auth_headers, stream_body: true) do |fragment|
+ if [301, 302, 307].include?(fragment.code)
+ # do nothing
+ elsif fragment.code == 200
+ file.write(fragment)
+ else
+ raise DownloadError.new('Non-success response code on downloading blob fragment', fragment.code)
+ end
+ end
+ end
+
+ success(file: @temp_file)
+ rescue DownloadError => exception
+ error(exception.message, exception.http_status)
+ rescue Timeout::Error => exception
+ error(exception.message, 599)
+ end
+
+ private
+
+ def blob_url
+ registry.blob_url(@image, @blob_sha)
+ end
+ end
+end
diff --git a/app/services/dependency_proxy/find_or_create_blob_service.rb b/app/services/dependency_proxy/find_or_create_blob_service.rb
new file mode 100644
index 00000000000..bd06f9d7628
--- /dev/null
+++ b/app/services/dependency_proxy/find_or_create_blob_service.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module DependencyProxy
+ class FindOrCreateBlobService < DependencyProxy::BaseService
+ def initialize(group, image, token, blob_sha)
+ @group = group
+ @image = image
+ @token = token
+ @blob_sha = blob_sha
+ end
+
+ def execute
+ file_name = @blob_sha.sub('sha256:', '') + '.gz'
+ blob = @group.dependency_proxy_blobs.find_or_build(file_name)
+
+ unless blob.persisted?
+ result = DependencyProxy::DownloadBlobService
+ .new(@image, @blob_sha, @token).execute
+
+ if result[:status] == :error
+ log_failure(result)
+
+ return error('Failed to download the blob', result[:http_status])
+ end
+
+ blob.file = result[:file]
+ blob.size = result[:file].size
+ blob.save!
+ end
+
+ success(blob: blob)
+ end
+
+ private
+
+ def log_failure(result)
+ log_error(
+ "Dependency proxy: Failed to download the blob." \
+ "Blob sha: #{@blob_sha}." \
+ "Error message: #{result[:message][0, 100]}" \
+ "HTTP status: #{result[:http_status]}"
+ )
+ end
+ end
+end
diff --git a/app/services/dependency_proxy/pull_manifest_service.rb b/app/services/dependency_proxy/pull_manifest_service.rb
new file mode 100644
index 00000000000..fc54ef85c96
--- /dev/null
+++ b/app/services/dependency_proxy/pull_manifest_service.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module DependencyProxy
+ class PullManifestService < DependencyProxy::BaseService
+ def initialize(image, tag, token)
+ @image = image
+ @tag = tag
+ @token = token
+ end
+
+ def execute
+ response = Gitlab::HTTP.get(manifest_url, headers: auth_headers)
+
+ if response.success?
+ success(manifest: response.body)
+ else
+ error(response.body, response.code)
+ end
+ rescue Timeout::Error => exception
+ error(exception.message, 599)
+ end
+
+ private
+
+ def manifest_url
+ registry.manifest_url(@image, @tag)
+ end
+ end
+end
diff --git a/app/services/dependency_proxy/request_token_service.rb b/app/services/dependency_proxy/request_token_service.rb
new file mode 100644
index 00000000000..4ca7239b9f6
--- /dev/null
+++ b/app/services/dependency_proxy/request_token_service.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module DependencyProxy
+ class RequestTokenService < DependencyProxy::BaseService
+ def initialize(image)
+ @image = image
+ end
+
+ def execute
+ response = Gitlab::HTTP.get(auth_url)
+
+ if response.success?
+ success(token: Gitlab::Json.parse(response.body)['token'])
+ else
+ error('Expected 200 response code for an access token', response.code)
+ end
+ rescue Timeout::Error => exception
+ error(exception.message, 599)
+ rescue JSON::ParserError
+ error('Failed to parse a response body for an access token', 500)
+ end
+
+ private
+
+ def auth_url
+ registry.auth_url(@image)
+ end
+ end
+end
diff --git a/app/services/deploy_keys/collect_keys_service.rb b/app/services/deploy_keys/collect_keys_service.rb
deleted file mode 100644
index 2ef49bf0f30..00000000000
--- a/app/services/deploy_keys/collect_keys_service.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-module DeployKeys
- class CollectKeysService
- def initialize(project, current_user)
- @project = project
- @current_user = current_user
- end
-
- def execute
- return [] unless current_user && project && user_can_read_project
-
- project.deploy_keys_projects
- .with_deploy_keys
- .with_write_access
- .map(&:deploy_key)
- end
-
- private
-
- def user_can_read_project
- Ability.allowed?(current_user, :read_project, project)
- end
-
- attr_reader :project, :current_user
- end
-end
diff --git a/app/services/design_management/copy_design_collection/copy_service.rb b/app/services/design_management/copy_design_collection/copy_service.rb
index 5099c2c5704..c0b32e1e9ae 100644
--- a/app/services/design_management/copy_design_collection/copy_service.rb
+++ b/app/services/design_management/copy_design_collection/copy_service.rb
@@ -172,20 +172,26 @@ module DesignManagement
def copy_designs!
design_attributes = attributes_config[:design_attributes]
- new_rows = designs.map do |design|
- design.attributes.slice(*design_attributes).merge(
- issue_id: target_issue.id,
- project_id: target_project.id
+ ::DesignManagement::Design.with_project_iid_supply(target_project) do |supply|
+ new_rows = designs.each_with_index.map do |design, i|
+ design.attributes.slice(*design_attributes).merge(
+ issue_id: target_issue.id,
+ project_id: target_project.id,
+ iid: supply.next_value
+ )
+ end
+
+ # TODO Replace `Gitlab::Database.bulk_insert` with `BulkInsertSafe`
+ # once https://gitlab.com/gitlab-org/gitlab/-/issues/247718 is fixed.
+ # When this is fixed, we can remove the call to
+ # `with_project_iid_supply` above, since the objects will be instantiated
+ # and callbacks (including `ensure_project_iid!`) will fire.
+ ::Gitlab::Database.bulk_insert( # rubocop:disable Gitlab/BulkInsert
+ DesignManagement::Design.table_name,
+ new_rows,
+ return_ids: true
)
end
-
- # TODO Replace `Gitlab::Database.bulk_insert` with `BulkInsertSafe`
- # once https://gitlab.com/gitlab-org/gitlab/-/issues/247718 is fixed.
- ::Gitlab::Database.bulk_insert( # rubocop:disable Gitlab/BulkInsert
- DesignManagement::Design.table_name,
- new_rows,
- return_ids: true
- )
end
def copy_versions!
diff --git a/app/services/discussions/capture_diff_note_position_service.rb b/app/services/discussions/capture_diff_note_position_service.rb
index 87aa27e455f..a95e149a6c9 100644
--- a/app/services/discussions/capture_diff_note_position_service.rb
+++ b/app/services/discussions/capture_diff_note_position_service.rb
@@ -9,8 +9,7 @@ module Discussions
def execute(discussion)
# The service has been implemented for text only
- # The impact of image notes on this service is being investigated in
- # https://gitlab.com/gitlab-org/gitlab/-/issues/213989
+ # We don't need to capture positions for images
return unless discussion.on_text?
result = tracer&.trace(discussion.position)
diff --git a/app/services/feature_flags/update_service.rb b/app/services/feature_flags/update_service.rb
index c837e50b104..ed5e2e794b4 100644
--- a/app/services/feature_flags/update_service.rb
+++ b/app/services/feature_flags/update_service.rb
@@ -22,6 +22,10 @@ module FeatureFlags
audit_event = audit_event(feature_flag)
+ if feature_flag.active_changed?
+ feature_flag.execute_hooks(current_user)
+ end
+
if feature_flag.save
save_audit_event(audit_event)
diff --git a/app/services/git/branch_hooks_service.rb b/app/services/git/branch_hooks_service.rb
index 93a0d139001..d00ca83441a 100644
--- a/app/services/git/branch_hooks_service.rb
+++ b/app/services/git/branch_hooks_service.rb
@@ -84,7 +84,6 @@ module Git
end
def enqueue_metrics_dashboard_sync
- return unless Feature.enabled?(:sync_metrics_dashboards, project)
return unless default_branch?
::Metrics::Dashboard::SyncDashboardsWorker.perform_async(project.id)
diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb
index cf843d92862..016c31cbccc 100644
--- a/app/services/groups/create_service.rb
+++ b/app/services/groups/create_service.rb
@@ -34,7 +34,7 @@ module Groups
if @group.save
@group.add_owner(current_user)
@group.create_namespace_settings
- Service.create_from_active_default_integrations(@group, :group_id) if Feature.enabled?(:group_level_integrations)
+ Service.create_from_active_default_integrations(@group, :group_id) if Feature.enabled?(:group_level_integrations, default_enabled: true)
end
end
diff --git a/app/services/import/github_service.rb b/app/services/import/github_service.rb
index a2923b1e4f9..948dba2d206 100644
--- a/app/services/import/github_service.rb
+++ b/app/services/import/github_service.rb
@@ -6,6 +6,10 @@ module Import
attr_reader :params, :current_user
def execute(access_params, provider)
+ if blocked_url?
+ return log_and_return_error("Invalid URL: #{url}", :bad_request)
+ end
+
unless authorized?
return error(_('This namespace has already been taken! Please choose another one.'), :unprocessable_entity)
end
@@ -56,6 +60,25 @@ module Import
can?(current_user, :create_projects, target_namespace)
end
+ def url
+ @url ||= params[:github_hostname]
+ end
+
+ def allow_local_requests?
+ Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services?
+ end
+
+ def blocked_url?
+ Gitlab::UrlBlocker.blocked_url?(
+ url,
+ {
+ allow_localhost: allow_local_requests?,
+ allow_local_network: allow_local_requests?,
+ schemes: %w(http https)
+ }
+ )
+ end
+
private
def log_error(exception)
diff --git a/app/services/integrations/test/project_service.rb b/app/services/integrations/test/project_service.rb
index 941d70c2cc4..39471d373f9 100644
--- a/app/services/integrations/test/project_service.rb
+++ b/app/services/integrations/test/project_service.rb
@@ -35,6 +35,8 @@ module Integrations
wiki_page_events_data
when 'deployment'
deployment_events_data
+ when 'release'
+ releases_events_data
else
push_events_data
end
diff --git a/app/services/issuable/common_system_notes_service.rb b/app/services/issuable/common_system_notes_service.rb
index fbc72dc867a..fd2dc3787c2 100644
--- a/app/services/issuable/common_system_notes_service.rb
+++ b/app/services/issuable/common_system_notes_service.rb
@@ -51,11 +51,11 @@ module Issuable
end
end
- def create_wip_note(old_title)
+ def create_draft_note(old_title)
return unless issuable.is_a?(MergeRequest)
if MergeRequest.work_in_progress?(old_title) != issuable.work_in_progress?
- SystemNoteService.handle_merge_request_wip(issuable, issuable.project, current_user)
+ SystemNoteService.handle_merge_request_draft(issuable, issuable.project, current_user)
end
end
@@ -69,7 +69,7 @@ module Issuable
end
def create_title_change_note(old_title)
- create_wip_note(old_title)
+ create_draft_note(old_title)
if issuable.wipless_title_changed(old_title)
SystemNoteService.change_title(issuable, issuable.project, current_user, old_title)
diff --git a/app/services/issuable/import_csv/base_service.rb b/app/services/issuable/import_csv/base_service.rb
new file mode 100644
index 00000000000..bf5f643a51b
--- /dev/null
+++ b/app/services/issuable/import_csv/base_service.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+module Issuable
+ module ImportCsv
+ class BaseService
+ def initialize(user, project, csv_io)
+ @user = user
+ @project = project
+ @csv_io = csv_io
+ @results = { success: 0, error_lines: [], parse_error: false }
+ end
+
+ def execute
+ process_csv
+ email_results_to_user
+
+ @results
+ end
+
+ private
+
+ def process_csv
+ with_csv_lines.each do |row, line_no|
+ issuable_attributes = {
+ title: row[:title],
+ description: row[:description]
+ }
+
+ if create_issuable(issuable_attributes).persisted?
+ @results[:success] += 1
+ else
+ @results[:error_lines].push(line_no)
+ end
+ end
+ rescue ArgumentError, CSV::MalformedCSVError
+ @results[:parse_error] = true
+ end
+
+ def with_csv_lines
+ csv_data = @csv_io.open(&:read).force_encoding(Encoding::UTF_8)
+ verify_headers!(csv_data)
+
+ csv_parsing_params = {
+ col_sep: detect_col_sep(csv_data.lines.first),
+ headers: true,
+ header_converters: :symbol
+ }
+
+ CSV.new(csv_data, csv_parsing_params).each.with_index(2)
+ end
+
+ def verify_headers!(data)
+ headers = data.lines.first.downcase
+ return if headers.include?('title') && headers.include?('description')
+
+ raise CSV::MalformedCSVError
+ end
+
+ def detect_col_sep(header)
+ if header.include?(",")
+ ","
+ elsif header.include?(";")
+ ";"
+ elsif header.include?("\t")
+ "\t"
+ else
+ raise CSV::MalformedCSVError
+ end
+ end
+
+ def create_issuable(attributes)
+ create_issuable_class.new(@project, @user, attributes).execute
+ end
+
+ def email_results_to_user
+ # defined in ImportCsvService
+ end
+
+ def create_issuable_class
+ # defined in ImportCsvService
+ end
+ end
+ end
+end
diff --git a/app/services/issues/import_csv_service.rb b/app/services/issues/import_csv_service.rb
index 60790ba3547..bce3ecc8bef 100644
--- a/app/services/issues/import_csv_service.rb
+++ b/app/services/issues/import_csv_service.rb
@@ -1,64 +1,25 @@
# frozen_string_literal: true
module Issues
- class ImportCsvService
- def initialize(user, project, csv_io)
- @user = user
- @project = project
- @csv_io = csv_io
- @results = { success: 0, error_lines: [], parse_error: false }
- end
-
+ class ImportCsvService < Issuable::ImportCsv::BaseService
def execute
- process_csv
- email_results_to_user
-
- @results
- end
-
- private
-
- def process_csv
- csv_data = @csv_io.open(&:read).force_encoding(Encoding::UTF_8)
+ record_import_attempt
- csv_parsing_params = {
- col_sep: detect_col_sep(csv_data.lines.first),
- headers: true,
- header_converters: :symbol
- }
-
- CSV.new(csv_data, csv_parsing_params).each.with_index(2) do |row, line_no|
- issue_attributes = {
- title: row[:title],
- description: row[:description]
- }
-
- issue = Issues::CreateService.new(@project, @user, issue_attributes).execute
-
- if issue.persisted?
- @results[:success] += 1
- else
- @results[:error_lines].push(line_no)
- end
- end
- rescue ArgumentError, CSV::MalformedCSVError
- @results[:parse_error] = true
+ super
end
def email_results_to_user
Notify.import_issues_csv_email(@user.id, @project.id, @results).deliver_later
end
- def detect_col_sep(header)
- if header.include?(",")
- ","
- elsif header.include?(";")
- ";"
- elsif header.include?("\t")
- "\t"
- else
- raise CSV::MalformedCSVError
- end
+ private
+
+ def create_issuable_class
+ Issues::CreateService
+ end
+
+ def record_import_attempt
+ Issues::CsvImport.create!(user: @user, project: @project)
end
end
end
diff --git a/app/services/issues/reopen_service.rb b/app/services/issues/reopen_service.rb
index 12dbff57ec5..e2b1b5400c7 100644
--- a/app/services/issues/reopen_service.rb
+++ b/app/services/issues/reopen_service.rb
@@ -5,8 +5,6 @@ module Issues
def execute(issue)
return issue unless can?(current_user, :reopen_issue, issue)
- before_reopen(issue)
-
if issue.reopen
event_service.reopen_issue(issue, current_user)
create_note(issue, 'reopened')
@@ -23,14 +21,8 @@ module Issues
private
- def before_reopen(issue)
- # Overriden in EE
- end
-
def create_note(issue, state = issue.state)
SystemNoteService.change_status(issue, issue.project, current_user, state, nil)
end
end
end
-
-Issues::ReopenService.prepend_if_ee('EE::Issues::ReopenService')
diff --git a/app/services/jira_connect/sync_service.rb b/app/services/jira_connect/sync_service.rb
index 07a648bb8c9..f8855fb6deb 100644
--- a/app/services/jira_connect/sync_service.rb
+++ b/app/services/jira_connect/sync_service.rb
@@ -6,11 +6,11 @@ module JiraConnect
self.project = project
end
- def execute(commits: nil, branches: nil, merge_requests: nil)
+ def execute(commits: nil, branches: nil, merge_requests: nil, update_sequence_id: 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)
+ response = client.store_dev_info(project: project, commits: commits, branches: branches, merge_requests: merge_requests, update_sequence_id: update_sequence_id)
log_response(response)
end
diff --git a/app/services/jira_connect_subscriptions/create_service.rb b/app/services/jira_connect_subscriptions/create_service.rb
index 8e794d3acf7..b169d97615d 100644
--- a/app/services/jira_connect_subscriptions/create_service.rb
+++ b/app/services/jira_connect_subscriptions/create_service.rb
@@ -3,6 +3,8 @@
module JiraConnectSubscriptions
class CreateService < ::JiraConnectSubscriptions::BaseService
include Gitlab::Utils::StrongMemoize
+ MERGE_REQUEST_SYNC_BATCH_SIZE = 20
+ MERGE_REQUEST_SYNC_BATCH_DELAY = 1.minute.freeze
def execute
unless namespace && can?(current_user, :create_jira_connect_subscription, namespace)
@@ -18,6 +20,8 @@ module JiraConnectSubscriptions
subscription = JiraConnectSubscription.new(installation: jira_connect_installation, namespace: namespace)
if subscription.save
+ schedule_sync_project_jobs
+
success
else
error(subscription.errors.full_messages.join(', '), 422)
@@ -29,5 +33,18 @@ module JiraConnectSubscriptions
Namespace.find_by_full_path(params[:namespace_path])
end
end
+
+ def schedule_sync_project_jobs
+ return unless Feature.enabled?(:jira_connect_full_namespace_sync)
+
+ namespace.all_projects.each_batch(of: MERGE_REQUEST_SYNC_BATCH_SIZE) do |projects, index|
+ JiraConnect::SyncProjectWorker.bulk_perform_in_with_contexts(
+ index * MERGE_REQUEST_SYNC_BATCH_DELAY,
+ projects,
+ arguments_proc: -> (project) { [project.id, Atlassian::JiraConnect::Client.generate_update_sequence_id] },
+ context_proc: -> (project) { { project: project } }
+ )
+ end
+ end
end
end
diff --git a/app/services/jira_import/users_importer.rb b/app/services/jira_import/users_importer.rb
index 9babd468d56..438a74343a5 100644
--- a/app/services/jira_import/users_importer.rb
+++ b/app/services/jira_import/users_importer.rb
@@ -2,8 +2,6 @@
module JiraImport
class UsersImporter
- attr_reader :user, :project, :start_at
-
def initialize(user, project, start_at)
@project = project
@start_at = start_at
@@ -23,6 +21,8 @@ module JiraImport
private
+ attr_reader :user, :project, :start_at
+
def mapped_users
users_mapper_service.execute
end
@@ -44,9 +44,9 @@ module JiraImport
# TODO: use deployment_type enum from jira service when https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37003 is merged
case deployment_type.upcase
when JiraService::DEPLOYMENT_TYPES[:server]
- ServerUsersMapperService.new(project.jira_service, start_at)
+ ServerUsersMapperService.new(user, project, start_at)
when JiraService::DEPLOYMENT_TYPES[:cloud]
- CloudUsersMapperService.new(project.jira_service, start_at)
+ CloudUsersMapperService.new(user, project, start_at)
else
raise ArgumentError
end
diff --git a/app/services/jira_import/users_mapper_service.rb b/app/services/jira_import/users_mapper_service.rb
index 480c034f952..6c8610bfbf3 100644
--- a/app/services/jira_import/users_mapper_service.rb
+++ b/app/services/jira_import/users_mapper_service.rb
@@ -2,30 +2,37 @@
module JiraImport
class UsersMapperService
+ include Gitlab::Utils::StrongMemoize
+
# MAX_USERS must match the pageSize value in app/assets/javascripts/jira_import/utils/constants.js
MAX_USERS = 50
- attr_reader :jira_service, :start_at
-
- def initialize(jira_service, start_at)
- @jira_service = jira_service
+ # The class is called from UsersImporter and small batches of users are expected
+ # In case the mapping of a big batch of users is expected to be passed here
+ # the implementation needs to change here and handles the matching in batches
+ def initialize(current_user, project, start_at)
+ @current_user = current_user
+ @project = project
+ @jira_service = project.jira_service
@start_at = start_at
end
def execute
- users.to_a.map do |jira_user|
+ jira_users.to_a.map do |jira_user|
{
jira_account_id: jira_user_id(jira_user),
jira_display_name: jira_user_name(jira_user),
jira_email: jira_user['emailAddress']
- }.merge(match_user(jira_user))
+ }.merge(gitlab_id: find_gitlab_id(jira_user))
end
end
private
- def users
- @users ||= client.get(url)
+ attr_reader :current_user, :project, :jira_service, :start_at
+
+ def jira_users
+ @jira_users ||= client.get(url)
end
def client
@@ -44,10 +51,33 @@ module JiraImport
raise NotImplementedError
end
- # TODO: Matching user by email and displayName will be done as the part
- # of follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/219023
- def match_user(jira_user)
- { gitlab_id: nil, gitlab_username: nil, gitlab_name: nil }
+ def matched_users
+ strong_memoize(:matched_users) do
+ jira_emails = jira_users.map { |u| u['emailAddress']&.downcase }.compact
+ jira_names = jira_users.map { |u| jira_user_name(u)&.downcase }.compact
+
+ relations = []
+ relations << User.by_username(jira_names).select("users.id, users.name, users.username, users.email as user_email")
+ relations << User.by_name(jira_names).select("users.id, users.name, users.username, users.email as user_email")
+ relations << User.by_user_email(jira_emails).select("users.id, users.name, users.username, users.email as user_email")
+ relations << User.by_emails(jira_emails).select("users.id, users.name, users.username, emails.email as user_email")
+
+ User.from_union(relations).id_in(project_member_ids).select("users.id as user_id, users.name as name, users.username as username, user_email")
+ end
+ end
+
+ def find_gitlab_id(jira_user)
+ user = matched_users.find do |matched_user|
+ matched_user.user_email&.downcase == jira_user['emailAddress']&.downcase ||
+ matched_user.name&.downcase == jira_user_name(jira_user)&.downcase ||
+ matched_user.username&.downcase == jira_user_name(jira_user)&.downcase
+ end
+
+ user&.user_id
+ end
+
+ def project_member_ids
+ @project_member_ids ||= MembersFinder.new(project, current_user).execute.select(:user_id)
end
end
end
diff --git a/app/services/labels/promote_service.rb b/app/services/labels/promote_service.rb
index 9ed10f6a11b..fdf2cf13f92 100644
--- a/app/services/labels/promote_service.rb
+++ b/app/services/labels/promote_service.rb
@@ -10,81 +10,79 @@ module Labels
label.is_a?(ProjectLabel)
Label.transaction do
- new_label = clone_label_to_group_label(label)
+ # use the existing group label if it exists
+ group_label = find_or_create_group_label(label)
- label_ids_for_merge(new_label).find_in_batches(batch_size: BATCH_SIZE) do |batched_ids|
- update_old_label_relations(new_label, batched_ids)
+ label_ids_for_merge(group_label).find_in_batches(batch_size: BATCH_SIZE) do |batched_ids|
+ update_old_label_relations(group_label, batched_ids)
destroy_project_labels(batched_ids)
end
- # We skipped validations during creation. Let's run them now, after deleting conflicting labels
- raise ActiveRecord::RecordInvalid.new(new_label) unless new_label.valid?
-
- new_label
+ group_label
end
end
# rubocop: enable CodeReuse/ActiveRecord
private
- def update_old_label_relations(new_label, old_label_ids)
- update_issuables(new_label, old_label_ids)
- update_resource_label_events(new_label, old_label_ids)
- update_issue_board_lists(new_label, old_label_ids)
- update_priorities(new_label, old_label_ids)
- subscribe_users(new_label, old_label_ids)
+ def update_old_label_relations(group_label, old_label_ids)
+ update_issuables(group_label, old_label_ids)
+ update_resource_label_events(group_label, old_label_ids)
+ update_issue_board_lists(group_label, old_label_ids)
+ update_priorities(group_label, old_label_ids)
+ subscribe_users(group_label, old_label_ids)
end
# rubocop: disable CodeReuse/ActiveRecord
- def subscribe_users(new_label, label_ids)
+ def subscribe_users(group_label, label_ids)
# users can be subscribed to multiple labels that will be merged into the group one
# we want to keep only one subscription / user
ids_to_update = Subscription.where(subscribable_id: label_ids, subscribable_type: 'Label')
.group(:user_id)
.pluck('MAX(id)')
- Subscription.where(id: ids_to_update).update_all(subscribable_id: new_label.id)
+ Subscription.where(id: ids_to_update).update_all(subscribable_id: group_label.id)
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
- def label_ids_for_merge(new_label)
+ def label_ids_for_merge(group_label)
LabelsFinder
- .new(current_user, title: new_label.title, group_id: project.group.id)
+ .new(current_user, title: group_label.title, group_id: project.group.id)
.execute(skip_authorization: true)
- .where.not(id: new_label)
+ .where.not(id: group_label)
.select(:id) # Can't use pluck() to avoid object-creation because of the batching
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
- def update_issuables(new_label, label_ids)
+ def update_issuables(group_label, label_ids)
LabelLink
.where(label: label_ids)
- .update_all(label_id: new_label.id)
+ .update_all(label_id: group_label.id)
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
- def update_resource_label_events(new_label, label_ids)
+ def update_resource_label_events(group_label, label_ids)
ResourceLabelEvent
.where(label: label_ids)
- .update_all(label_id: new_label.id)
+ .update_all(label_id: group_label.id)
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
- def update_issue_board_lists(new_label, label_ids)
+ def update_issue_board_lists(group_label, label_ids)
List
.where(label: label_ids)
- .update_all(label_id: new_label.id)
+ .update_all(label_id: group_label.id)
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
- def update_priorities(new_label, label_ids)
+ def update_priorities(group_label, label_ids)
LabelPriority
.where(label: label_ids)
- .update_all(label_id: new_label.id)
+ .update_all(label_id: group_label.id)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -92,18 +90,12 @@ module Labels
def destroy_project_labels(label_ids)
Label.where(id: label_ids).destroy_all # rubocop: disable Cop/DestroyAll
end
- # rubocop: enable CodeReuse/ActiveRecord
- def clone_label_to_group_label(label)
+ def find_or_create_group_label(label)
params = label.attributes.slice('title', 'description', 'color')
- # Since the title of the new label has to be the same as the previous labels
- # and we're merging old labels in batches we'll skip validation to omit 2-step
- # merge process and do it in one batch
- # We'll be forcing validation at the end of the transaction to ensure everything
- # was merged correctly
- new_label = GroupLabel.new(params.merge(group: project.group))
- new_label.save(validate: false)
+ new_label = GroupLabel.create_with(params).find_or_initialize_by(group_id: project.group.id, title: label.title)
+ new_label.save! unless new_label.persisted?
new_label
end
end
diff --git a/app/services/members/invite_service.rb b/app/services/members/invite_service.rb
new file mode 100644
index 00000000000..cfab5c3ef9d
--- /dev/null
+++ b/app/services/members/invite_service.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+module Members
+ class InviteService < Members::BaseService
+ DEFAULT_LIMIT = 100
+
+ attr_reader :errors
+
+ def initialize(current_user, params)
+ @current_user, @params = current_user, params.dup
+ @errors = {}
+ end
+
+ def execute(source)
+ return error(s_('Email cannot be blank')) if params[:email].blank?
+
+ emails = params[:email].split(',').uniq.flatten
+ return error(s_("Too many users specified (limit is %{user_limit})") % { user_limit: user_limit }) if
+ user_limit && emails.size > user_limit
+
+ emails.each do |email|
+ next if existing_member?(source, email)
+
+ next if existing_invite?(source, email)
+
+ if existing_user?(email)
+ add_existing_user_as_member(current_user, source, params, email)
+ next
+ end
+
+ invite_new_member_and_user(current_user, source, params, email)
+ end
+
+ return success unless errors.any?
+
+ error(errors)
+ end
+
+ private
+
+ def invite_new_member_and_user(current_user, source, params, email)
+ new_member = (source.class.name + 'Member').constantize.create(source_id: source.id,
+ user_id: nil,
+ access_level: params[:access_level],
+ invite_email: email,
+ created_by_id: current_user.id,
+ expires_at: params[:expires_at],
+ requested_at: Time.current.utc)
+
+ unless new_member.valid? && new_member.persisted?
+ errors[params[:email]] = new_member.errors.full_messages.to_sentence
+ end
+ end
+
+ def add_existing_user_as_member(current_user, source, params, email)
+ new_member = create_member(current_user, existing_user(email), source, params.merge({ invite_email: email }))
+
+ unless new_member.valid? && new_member.persisted?
+ errors[email] = new_member.errors.full_messages.to_sentence
+ end
+ end
+
+ def create_member(current_user, user, source, params)
+ source.add_user(user, params[:access_level], current_user: current_user, expires_at: params[:expires_at])
+ end
+
+ def user_limit
+ limit = params.fetch(:limit, DEFAULT_LIMIT)
+
+ limit && limit < 0 ? nil : limit
+ end
+
+ def existing_member?(source, email)
+ existing_member = source.members.with_user_by_email(email).exists?
+
+ if existing_member
+ errors[email] = "Already a member of #{source.name}"
+ return true
+ end
+
+ false
+ end
+
+ def existing_invite?(source, email)
+ existing_invite = source.members.search_invite_email(email).exists?
+
+ if existing_invite
+ errors[email] = "Member already invited to #{source.name}"
+ return true
+ end
+
+ false
+ end
+
+ def existing_user(email)
+ User.find_by_email(email)
+ end
+
+ def existing_user?(email)
+ existing_user(email).present?
+ end
+ end
+end
diff --git a/app/services/merge_requests/cleanup_refs_service.rb b/app/services/merge_requests/cleanup_refs_service.rb
index d003124a112..23ac8e393f4 100644
--- a/app/services/merge_requests/cleanup_refs_service.rb
+++ b/app/services/merge_requests/cleanup_refs_service.rb
@@ -9,7 +9,7 @@ module MergeRequests
attr_reader :merge_request
def self.schedule(merge_request)
- MergeRequestCleanupRefsWorker.perform_in(TIME_THRESHOLD, merge_request.id)
+ merge_request.create_cleanup_schedule(scheduled_at: TIME_THRESHOLD.from_now)
end
def initialize(merge_request)
@@ -22,6 +22,7 @@ module MergeRequests
end
def execute
+ return error("Merge request is not scheduled to be cleaned up yet.") unless scheduled?
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.
@@ -30,7 +31,10 @@ module MergeRequests
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
+ delete_refs if repository.exists?
+
+ return error('Failed to update schedule.') unless update_schedule
+
success
end
@@ -38,6 +42,10 @@ module MergeRequests
attr_reader :repository, :ref_path, :merge_ref_path, :ref_head_sha, :merge_ref_sha
+ def scheduled?
+ merge_request.cleanup_schedule.present? && merge_request.cleanup_schedule.scheduled_at <= Time.current
+ end
+
def eligible?
return met_time_threshold?(merge_request.metrics&.latest_closed_at) if merge_request.closed?
@@ -71,5 +79,9 @@ module MergeRequests
def delete_refs
repository.delete_refs(ref_path, merge_ref_path)
end
+
+ def update_schedule
+ merge_request.cleanup_schedule.update(completed_at: Time.current)
+ end
end
end
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index e5d0b216d6c..ed977a5a872 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -42,7 +42,7 @@ module MergeRequests
end
notify_about_push(mr)
- mark_mr_as_wip_from_commits(mr)
+ mark_mr_as_draft_from_commits(mr)
execute_mr_web_hooks(mr)
end
@@ -246,7 +246,7 @@ module MergeRequests
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(merge_request)
+ def mark_mr_as_draft_from_commits(merge_request)
return unless @commits.present?
commit_shas = merge_request.commit_shas
@@ -257,7 +257,7 @@ module MergeRequests
if wip_commit && !merge_request.work_in_progress?
merge_request.update(title: merge_request.wip_title)
- SystemNoteService.add_merge_request_wip_from_commit(
+ SystemNoteService.add_merge_request_draft_from_commit(
merge_request,
merge_request.project,
@current_user,
diff --git a/app/services/merge_requests/reopen_service.rb b/app/services/merge_requests/reopen_service.rb
index f87005bcb6c..bcedbc61c65 100644
--- a/app/services/merge_requests/reopen_service.rb
+++ b/app/services/merge_requests/reopen_service.rb
@@ -15,6 +15,8 @@ module MergeRequests
invalidate_cache_counts(merge_request, users: merge_request.assignees)
merge_request.update_project_counter_caches
merge_request.cache_merge_request_closes_issues!(current_user)
+ merge_request.cleanup_schedule&.destroy
+ merge_request.update_column(:merge_ref_sha, nil)
end
merge_request
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 48f44affb23..b2826b5c905 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -73,6 +73,8 @@ module Notes
if note.for_merge_request? && note.diff_note? && note.start_of_discussion?
Discussions::CaptureDiffNotePositionService.new(note.noteable, note.diff_file&.paths).execute(note.discussion)
end
+
+ track_note_creation_usage_for_issues(note) if note.for_issue?
end
def do_commands(note, update_params, message, only_commands)
@@ -113,5 +115,9 @@ module Notes
track_usage_event(:incident_management_incident_comment, user.id)
end
+
+ def track_note_creation_usage_for_issues(note)
+ Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_added_action(author: note.author)
+ end
end
end
diff --git a/app/services/notes/destroy_service.rb b/app/services/notes/destroy_service.rb
index ee8a680fcb4..2b6ec47eaef 100644
--- a/app/services/notes/destroy_service.rb
+++ b/app/services/notes/destroy_service.rb
@@ -8,6 +8,13 @@ module Notes
end
clear_noteable_diffs_cache(note)
+ track_note_removal_usage_for_issues(note) if note.for_issue?
+ end
+
+ private
+
+ def track_note_removal_usage_for_issues(note)
+ Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_removed_action(author: note.author)
end
end
end
diff --git a/app/services/notes/update_service.rb b/app/services/notes/update_service.rb
index 193d3080078..37872f7fbdb 100644
--- a/app/services/notes/update_service.rb
+++ b/app/services/notes/update_service.rb
@@ -14,6 +14,8 @@ module Notes
note.save
end
+ track_note_edit_usage_for_issues(note) if note.for_issue?
+
only_commands = false
quick_actions_service = QuickActionsService.new(project, current_user)
@@ -89,6 +91,10 @@ module Notes
Note.id_in(note.discussion.notes.map(&:id)).update_all(confidential: params[:confidential])
end
+
+ def track_note_edit_usage_for_issues(note)
+ Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_edited_action(author: note.author)
+ end
end
end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 7853ad11c64..85113d3ca22 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -370,6 +370,16 @@ class NotificationService
end
end
+ def new_instance_access_request(user)
+ recipients = User.instance_access_request_approvers_to_be_notified # https://gitlab.com/gitlab-org/gitlab/-/issues/277016 will change this
+
+ return true if recipients.empty?
+
+ recipients.each do |recipient|
+ mailer.instance_access_request_email(user, recipient).deliver_later
+ end
+ end
+
# Members
def new_access_request(member)
return true unless member.notifiable?(:subscription)
@@ -601,7 +611,7 @@ class NotificationService
return if project.emails_disabled?
owners_and_maintainers_without_invites(project).to_a.product(alerts).each do |recipient, alert|
- mailer.prometheus_alert_fired_email(project.id, recipient.user.id, alert).deliver_later
+ mailer.prometheus_alert_fired_email(project, recipient.user, alert).deliver_later
end
end
diff --git a/app/services/packages/composer/create_package_service.rb b/app/services/packages/composer/create_package_service.rb
index 7e16fc78599..2d2f1568187 100644
--- a/app/services/packages/composer/create_package_service.rb
+++ b/app/services/packages/composer/create_package_service.rb
@@ -10,11 +10,11 @@ module Packages
composer_json
::Packages::Package.transaction do
- ::Packages::Composer::Metadatum.upsert(
+ ::Packages::Composer::Metadatum.upsert({
package_id: created_package.id,
target_sha: target,
composer_json: composer_json
- )
+ })
end
end
diff --git a/app/services/packages/composer/version_parser_service.rb b/app/services/packages/composer/version_parser_service.rb
index 76dfd7a14bd..811cac0b3b7 100644
--- a/app/services/packages/composer/version_parser_service.rb
+++ b/app/services/packages/composer/version_parser_service.rb
@@ -9,7 +9,7 @@ module Packages
def execute
if @tag_name.present?
- @tag_name.match(Gitlab::Regex.composer_package_version_regex).captures[0]
+ @tag_name.delete_prefix('v')
elsif @branch_name.present?
branch_sufix_or_prefix(@branch_name.match(Gitlab::Regex.composer_package_version_regex))
end
diff --git a/app/services/packages/create_event_service.rb b/app/services/packages/create_event_service.rb
index d009cba2812..8350ff993bf 100644
--- a/app/services/packages/create_event_service.rb
+++ b/app/services/packages/create_event_service.rb
@@ -3,18 +3,30 @@
module Packages
class CreateEventService < BaseService
def execute
- event_scope = scope.is_a?(::Packages::Package) ? scope.package_type : scope
-
- ::Packages::Event.create!(
- event_type: event_name,
- originator: current_user&.id,
- originator_type: originator_type,
- event_scope: event_scope
- )
+ if Feature.enabled?(:collect_package_events_redis) && redis_event_name
+ ::Gitlab::UsageDataCounters::HLLRedisCounter.track_event(current_user.id, redis_event_name)
+ end
+
+ if Feature.enabled?(:collect_package_events)
+ ::Packages::Event.create!(
+ event_type: event_name,
+ originator: current_user&.id,
+ originator_type: originator_type,
+ event_scope: event_scope
+ )
+ end
end
private
+ def redis_event_name
+ @redis_event_name ||= ::Packages::Event.allowed_event_name(event_scope, event_name, originator_type)
+ end
+
+ def event_scope
+ @event_scope ||= scope.is_a?(::Packages::Package) ? scope.package_type : scope
+ end
+
def scope
params[:scope]
end
diff --git a/app/services/packages/create_package_file_service.rb b/app/services/packages/create_package_file_service.rb
index 0ebceeee779..5723b0b4717 100644
--- a/app/services/packages/create_package_file_service.rb
+++ b/app/services/packages/create_package_file_service.rb
@@ -9,7 +9,7 @@ module Packages
end
def execute
- package.package_files.create!(
+ package_file = package.package_files.build(
file: params[:file],
size: params[:size],
file_name: params[:file_name],
@@ -17,6 +17,13 @@ module Packages
file_sha256: params[:file_sha256],
file_md5: params[:file_md5]
)
+
+ if params[:build].present?
+ package_file.package_file_build_infos << package_file.package_file_build_infos.build(pipeline: params[:build].pipeline)
+ end
+
+ package_file.save!
+ package_file
end
end
end
diff --git a/app/services/packages/debian/extract_deb_metadata_service.rb b/app/services/packages/debian/extract_deb_metadata_service.rb
new file mode 100644
index 00000000000..eb106f4cd30
--- /dev/null
+++ b/app/services/packages/debian/extract_deb_metadata_service.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ # Returns .deb file metadata
+ class ExtractDebMetadataService
+ CommandFailedError = Class.new(StandardError)
+
+ def initialize(file_path)
+ @file_path = file_path
+ end
+
+ def execute
+ unless success?
+ raise CommandFailedError, "The `#{cmd}` command failed (status: #{result.status}) with the following error:\n#{result.stderr}"
+ end
+
+ sections = ParseDebian822Service.new(result.stdout).execute
+
+ sections.each_value.first
+ end
+
+ private
+
+ def cmd
+ @cmd ||= begin
+ dpkg_deb_path = Gitlab.config.packages.dpkg_deb_path
+ [dpkg_deb_path, '--field', @file_path]
+ end
+ end
+
+ def result
+ @result ||= Gitlab::Popen.popen_with_detail(cmd)
+ end
+
+ def success?
+ result.status&.exitstatus == 0
+ end
+ end
+ end
+end
diff --git a/app/services/packages/debian/parse_debian822_service.rb b/app/services/packages/debian/parse_debian822_service.rb
new file mode 100644
index 00000000000..665929d2324
--- /dev/null
+++ b/app/services/packages/debian/parse_debian822_service.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ # Parse String as Debian RFC822 control data format
+ # https://manpages.debian.org/unstable/dpkg-dev/deb822.5
+ class ParseDebian822Service
+ InvalidDebian822Error = Class.new(StandardError)
+
+ def initialize(input)
+ @input = input
+ end
+
+ def execute
+ output = {}
+ @input.each_line('', chomp: true) do |block|
+ section = {}
+ section_name, field = nil
+ block.each_line(chomp: true) do |line|
+ next if comment_line?(line)
+
+ if continuation_line?(line)
+ raise InvalidDebian822Error, "Parse error. Unexpected continuation line" if field.nil?
+
+ section[field] += "\n"
+ section[field] += line[1..] unless paragraph_separator?(line)
+ elsif match = match_section_line(line)
+ section_name = match[:name] if section_name.nil?
+ field = match[:field].to_sym
+
+ raise InvalidDebian822Error, "Duplicate field '#{field}' in section '#{section_name}'" if section.include?(field)
+
+ section[field] = match[:value]
+ else
+ raise InvalidDebian822Error, "Parse error on line #{line}"
+ end
+ end
+
+ raise InvalidDebian822Error, "Duplicate section '#{section_name}'" if output[section_name]
+
+ output[section_name] = section
+ end
+
+ output
+ end
+
+ private
+
+ def comment_line?(line)
+ line.match?(/^#/)
+ end
+
+ def continuation_line?(line)
+ line.match?(/^ /)
+ end
+
+ def paragraph_separator?(line)
+ line == ' .'
+ end
+
+ def match_section_line(line)
+ line.match(/(?<name>(?<field>^\S+):\s*(?<value>.*))/)
+ end
+ end
+ end
+end
diff --git a/app/services/packages/generic/create_package_file_service.rb b/app/services/packages/generic/create_package_file_service.rb
index 4d49c63799f..f25e8b0ae56 100644
--- a/app/services/packages/generic/create_package_file_service.rb
+++ b/app/services/packages/generic/create_package_file_service.rb
@@ -28,7 +28,8 @@ module Packages
file: params[:file],
size: params[:file].size,
file_sha256: params[:file].sha256,
- file_name: params[:file_name]
+ file_name: params[:file_name],
+ build: params[:build]
}
::Packages::CreatePackageFileService.new(package, file_params).execute
diff --git a/app/services/packages/generic/find_or_create_package_service.rb b/app/services/packages/generic/find_or_create_package_service.rb
index 8a8459d167e..97f774a836b 100644
--- a/app/services/packages/generic/find_or_create_package_service.rb
+++ b/app/services/packages/generic/find_or_create_package_service.rb
@@ -6,7 +6,7 @@ module Packages
def execute
find_or_create_package!(::Packages::Package.package_types['generic']) do |package|
if params[:build].present?
- package.build_info = Packages::BuildInfo.new(pipeline: params[:build].pipeline)
+ package.build_infos.new(pipeline: params[:build].pipeline)
end
end
end
diff --git a/app/services/packages/maven/create_package_service.rb b/app/services/packages/maven/create_package_service.rb
index 3df17021499..540c7b1d4da 100644
--- a/app/services/packages/maven/create_package_service.rb
+++ b/app/services/packages/maven/create_package_service.rb
@@ -6,7 +6,7 @@ module Packages
app_group, _, app_name = params[:name].rpartition('/')
app_group.tr!('/', '.')
- package = create_package!(:maven,
+ create_package!(:maven,
maven_metadatum_attributes: {
path: params[:path],
app_group: app_group,
@@ -14,11 +14,6 @@ module Packages
app_version: params[:version]
}
)
-
- build = params[:build]
- package.create_build_info!(pipeline: build.pipeline) if build.present?
-
- package
end
end
end
diff --git a/app/services/packages/maven/find_or_create_package_service.rb b/app/services/packages/maven/find_or_create_package_service.rb
index 505f45a7b21..a2a61ff8d93 100644
--- a/app/services/packages/maven/find_or_create_package_service.rb
+++ b/app/services/packages/maven/find_or_create_package_service.rb
@@ -38,8 +38,7 @@ module Packages
package_params = {
name: package_name,
path: params[:path],
- version: version,
- build: params[:build]
+ version: version
}
package =
@@ -47,6 +46,8 @@ module Packages
.execute
end
+ package.build_infos.create!(pipeline: params[:build].pipeline) if params[:build].present?
+
package
end
end
diff --git a/app/services/packages/npm/create_package_service.rb b/app/services/packages/npm/create_package_service.rb
index 7f868b71734..c4b75348bba 100644
--- a/app/services/packages/npm/create_package_service.rb
+++ b/app/services/packages/npm/create_package_service.rb
@@ -18,7 +18,7 @@ module Packages
package = create_package!(:npm, name: name, version: version)
if build.present?
- package.create_build_info!(pipeline: build.pipeline)
+ package.build_infos.create!(pipeline: build.pipeline)
end
::Packages::CreatePackageFileService.new(package, file_params).execute
@@ -75,7 +75,8 @@ module Packages
file: CarrierWaveStringFile.new(Base64.decode64(attachment['data'])),
size: attachment['length'],
file_sha1: version_data[:dist][:shasum],
- file_name: package_file_name
+ file_name: package_file_name,
+ build: params[:build]
}
end
diff --git a/app/services/pages/destroy_deployments_service.rb b/app/services/pages/destroy_deployments_service.rb
new file mode 100644
index 00000000000..45d906bec7a
--- /dev/null
+++ b/app/services/pages/destroy_deployments_service.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Pages
+ class DestroyDeploymentsService
+ def initialize(project, last_deployment_id = nil)
+ @project = project
+ @last_deployment_id = last_deployment_id
+ end
+
+ def execute
+ deployments_to_destroy = @project.pages_deployments
+ deployments_to_destroy = deployments_to_destroy.older_than(@last_deployment_id) if @last_deployment_id
+ deployments_to_destroy.find_each(&:destroy) # rubocop: disable CodeReuse/ActiveRecord
+ end
+ end
+end
diff --git a/app/services/personal_access_tokens/create_service.rb b/app/services/personal_access_tokens/create_service.rb
index ff9bb7d6802..93a0135669f 100644
--- a/app/services/personal_access_tokens/create_service.rb
+++ b/app/services/personal_access_tokens/create_service.rb
@@ -2,23 +2,30 @@
module PersonalAccessTokens
class CreateService < BaseService
- def initialize(current_user, params = {})
+ def initialize(current_user:, target_user:, params: {})
@current_user = current_user
+ @target_user = target_user
@params = params.dup
+ @ip_address = @params.delete(:ip_address)
end
def execute
- personal_access_token = current_user.personal_access_tokens.create(params.slice(*allowed_params))
+ return ServiceResponse.error(message: 'Not permitted to create') unless creation_permitted?
- if personal_access_token.persisted?
- ServiceResponse.success(payload: { personal_access_token: personal_access_token })
+ token = target_user.personal_access_tokens.create(params.slice(*allowed_params))
+
+ if token.persisted?
+ log_event(token)
+ ServiceResponse.success(payload: { personal_access_token: token })
else
- ServiceResponse.error(message: personal_access_token.errors.full_messages.to_sentence)
+ ServiceResponse.error(message: token.errors.full_messages.to_sentence, payload: { personal_access_token: token })
end
end
private
+ attr_reader :target_user, :ip_address
+
def allowed_params
[
:name,
@@ -27,5 +34,15 @@ module PersonalAccessTokens
:expires_at
]
end
+
+ def creation_permitted?
+ Ability.allowed?(current_user, :create_user_personal_access_token, target_user)
+ end
+
+ def log_event(token)
+ log_info("PAT CREATION: created_by: '#{current_user.username}', created_for: '#{token.user.username}', token_id: '#{token.id}'")
+ end
end
end
+
+PersonalAccessTokens::CreateService.prepend_if_ee('EE::PersonalAccessTokens::CreateService')
diff --git a/app/services/personal_access_tokens/revoke_service.rb b/app/services/personal_access_tokens/revoke_service.rb
index 17405002d8d..34d542acab1 100644
--- a/app/services/personal_access_tokens/revoke_service.rb
+++ b/app/services/personal_access_tokens/revoke_service.rb
@@ -4,16 +4,17 @@ module PersonalAccessTokens
class RevokeService
attr_reader :token, :current_user, :group
- def initialize(current_user = nil, params = { token: nil, group: nil })
+ def initialize(current_user = nil, token: nil, group: nil )
@current_user = current_user
- @token = params[:token]
- @group = params[:group]
+ @token = token
+ @group = group
end
def execute
return ServiceResponse.error(message: 'Not permitted to revoke') unless revocation_permitted?
if token.revoke!
+ log_event
ServiceResponse.success(message: success_message)
else
ServiceResponse.error(message: error_message)
@@ -33,6 +34,10 @@ module PersonalAccessTokens
def revocation_permitted?
Ability.allowed?(current_user, :revoke_token, token)
end
+
+ def log_event
+ Gitlab::AppLogger.info("PAT REVOCATION: revoked_by: '#{current_user.username}', revoked_for: '#{token.user.username}', token_id: '#{token.id}'")
+ end
end
end
diff --git a/app/services/post_receive_service.rb b/app/services/post_receive_service.rb
index 69c9868c75c..79b613f6a88 100644
--- a/app/services/post_receive_service.rb
+++ b/app/services/post_receive_service.rb
@@ -29,9 +29,7 @@ class PostReceiveService
response.add_alert_message(message)
end
- broadcast_message = BroadcastMessage.current_banner_messages&.last&.message
response.add_alert_message(broadcast_message)
-
response.add_merge_request_urls(merge_request_urls)
# Neither User nor Project are guaranteed to be returned; an orphaned write deploy
@@ -74,6 +72,24 @@ class PostReceiveService
::MergeRequests::GetUrlsService.new(project).execute(params[:changes])
end
+
+ private
+
+ def broadcast_message
+ banner = nil
+
+ if project
+ scoped_messages = BroadcastMessage.current_banner_messages(project.full_path).select do |message|
+ message.target_path.present? && message.matches_current_path(project.full_path)
+ end
+
+ banner = scoped_messages.last
+ end
+
+ banner ||= BroadcastMessage.current_banner_messages.last
+
+ banner&.message
+ end
end
PostReceiveService.prepend_if_ee('EE::PostReceiveService')
diff --git a/app/services/projects/alerting/notify_service.rb b/app/services/projects/alerting/notify_service.rb
index affac45fc3d..ab8f53a3757 100644
--- a/app/services/projects/alerting/notify_service.rb
+++ b/app/services/projects/alerting/notify_service.rb
@@ -6,9 +6,11 @@ module Projects
include Gitlab::Utils::StrongMemoize
include ::IncidentManagement::Settings
- def execute(token)
+ def execute(token, integration = nil)
+ @integration = integration
+
return bad_request unless valid_payload_size?
- return forbidden unless alerts_service_activated?
+ return forbidden unless active_integration?
return unauthorized unless valid_token?(token)
process_alert
@@ -22,7 +24,7 @@ module Projects
private
- delegate :alerts_service, :alerts_service_activated?, to: :project
+ attr_reader :integration
def process_alert
if alert.persisted?
@@ -66,14 +68,11 @@ module Projects
return unless alert.save
alert.execute_services
- SystemNoteService.create_new_alert(
- alert,
- alert.monitoring_tool || 'Generic Alert Endpoint'
- )
+ SystemNoteService.create_new_alert(alert, notification_source)
end
def process_incident_issues
- return if alert.issue
+ return if alert.issue || alert.resolved?
::IncidentManagement::ProcessAlertWorker.perform_async(nil, nil, alert.id)
end
@@ -81,7 +80,7 @@ module Projects
def send_alert_email
notification_service
.async
- .prometheus_alerts_fired(project, [alert.attributes])
+ .prometheus_alerts_fired(project, [alert])
end
def alert
@@ -106,12 +105,20 @@ module Projects
end
end
+ def notification_source
+ alert.monitoring_tool || integration&.name || 'Generic Alert Endpoint'
+ end
+
def valid_payload_size?
Gitlab::Utils::DeepSize.new(params).valid?
end
+ def active_integration?
+ integration&.active?
+ end
+
def valid_token?(token)
- token == alerts_service.token
+ token == integration.token
end
def bad_request
diff --git a/app/services/projects/cleanup_service.rb b/app/services/projects/cleanup_service.rb
index 4ced9feff00..6e3b320afbe 100644
--- a/app/services/projects/cleanup_service.rb
+++ b/app/services/projects/cleanup_service.rb
@@ -11,6 +11,24 @@ module Projects
include Gitlab::Utils::StrongMemoize
+ class << self
+ def enqueue(project, current_user, bfg_object_map)
+ Projects::UpdateService.new(project, current_user, bfg_object_map: bfg_object_map).execute.tap do |result|
+ next unless result[:status] == :success
+
+ project.set_repository_read_only!
+ RepositoryCleanupWorker.perform_async(project.id, current_user.id)
+ end
+ rescue Project::RepositoryReadOnlyError => err
+ { status: :error, message: (_('Failed to make repository read-only. %{reason}') % { reason: err.message }) }
+ end
+
+ def cleanup_after(project)
+ project.bfg_object_map.remove!
+ project.set_repository_writable!
+ end
+ end
+
# Attempt to clean up the project following the push. Warning: this is
# destructive!
#
@@ -22,14 +40,14 @@ module Projects
apply_bfg_object_map!
# Remove older objects that are no longer referenced
- GitGarbageCollectWorker.new.perform(project.id, :gc, "project_cleanup:gc:#{project.id}")
+ GitGarbageCollectWorker.new.perform(project.id, :prune, "project_cleanup:gc:#{project.id}")
# The cache may now be inaccurate, and holding onto it could prevent
# bugs assuming the presence of some object from manifesting for some
# time. Better to feel the pain immediately.
project.repository.expire_all_method_caches
- project.bfg_object_map.remove!
+ self.class.cleanup_after(project)
end
private
diff --git a/app/services/projects/container_repository/delete_tags_service.rb b/app/services/projects/container_repository/delete_tags_service.rb
index 9fc3ec0aafb..505ddaf50e3 100644
--- a/app/services/projects/container_repository/delete_tags_service.rb
+++ b/app/services/projects/container_repository/delete_tags_service.rb
@@ -36,11 +36,11 @@ module Projects
def log_response(response)
log_data = LOG_DATA_BASE.merge(
container_repository_id: @container_repository.id,
- message: 'deleted tags'
- )
+ message: 'deleted tags',
+ deleted_tags_count: response[:deleted]&.size
+ ).compact
if response[:status] == :success
- log_data[:deleted_tags_count] = response[:deleted].size
log_info(log_data)
else
log_data[:message] = response[:message]
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 cee94b994a3..e4e22dd9543 100644
--- a/app/services/projects/container_repository/gitlab/delete_tags_service.rb
+++ b/app/services/projects/container_repository/gitlab/delete_tags_service.rb
@@ -14,6 +14,7 @@ module Projects
def initialize(container_repository, tag_names)
@container_repository = container_repository
@tag_names = tag_names
+ @deleted_tags = []
end
# Delete tags by name with a single DELETE request. This is only supported
@@ -25,7 +26,7 @@ module Projects
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')
+ error('timeout while deleting tags', nil, pass_back: { deleted: @deleted_tags })
end
private
@@ -33,13 +34,15 @@ module Projects
def delete_tags
start_time = Time.zone.now
- deleted_tags = @tag_names.select do |name|
+ @tag_names.each do |name|
raise TimeoutError if timeout?(start_time)
- @container_repository.delete_tag_by_name(name)
+ if @container_repository.delete_tag_by_name(name)
+ @deleted_tags.append(name)
+ end
end
- deleted_tags.any? ? success(deleted: deleted_tags) : error('could not delete tags')
+ @deleted_tags.any? ? success(deleted: @deleted_tags) : error('could not delete tags')
end
def timeout?(start_time)
diff --git a/app/services/projects/hashed_storage/base_repository_service.rb b/app/services/projects/hashed_storage/base_repository_service.rb
index 065bf8725be..349d4d367be 100644
--- a/app/services/projects/hashed_storage/base_repository_service.rb
+++ b/app/services/projects/hashed_storage/base_repository_service.rb
@@ -79,13 +79,12 @@ module Projects
end
def try_to_set_repository_read_only!
- # Mitigate any push operation to start during migration
- unless project.set_repository_read_only!
- migration_error = "Target repository '#{old_disk_path}' cannot be made read-only as there is a git transfer in progress"
- logger.error migration_error
+ project.set_repository_read_only!
+ rescue Project::RepositoryReadOnlyError => err
+ migration_error = "Target repository '#{old_disk_path}' cannot be made read-only: #{err.message}"
+ logger.error migration_error
- raise RepositoryInUseError, migration_error
- end
+ raise RepositoryInUseError, migration_error
end
def wiki_path_suffix
diff --git a/app/services/projects/lfs_pointers/lfs_download_service.rb b/app/services/projects/lfs_pointers/lfs_download_service.rb
index d6e5b825e13..525f8a25d04 100644
--- a/app/services/projects/lfs_pointers/lfs_download_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_download_service.rb
@@ -22,7 +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
+ return link_existing_lfs_object! if lfs_size > LARGE_FILE_SIZE && lfs_object
wrap_download_errors do
download_lfs_file!
diff --git a/app/services/projects/prometheus/alerts/notify_service.rb b/app/services/projects/prometheus/alerts/notify_service.rb
index c002aca32db..8ad4f59373d 100644
--- a/app/services/projects/prometheus/alerts/notify_service.rb
+++ b/app/services/projects/prometheus/alerts/notify_service.rb
@@ -17,13 +17,12 @@ module Projects
SUPPORTED_VERSION = '4'
- def execute(token)
+ def execute(token, _integration = nil)
return bad_request unless valid_payload_size?
return unprocessable_entity unless self.class.processable?(params)
return unauthorized unless valid_alert_manager_token?(token)
process_prometheus_alerts
- send_alert_email if send_email?
ServiceResponse.success
end
@@ -120,14 +119,6 @@ module Projects
ActiveSupport::SecurityUtils.secure_compare(expected, actual)
end
- def send_alert_email
- return unless firings.any?
-
- notification_service
- .async
- .prometheus_alerts_fired(project, alerts_attributes)
- end
-
def process_prometheus_alerts
alerts.each do |alert|
AlertManagement::ProcessPrometheusAlertService
@@ -136,18 +127,6 @@ module Projects
end
end
- def alerts_attributes
- firings.map do |payload|
- alert_params = Gitlab::AlertManagement::Payload.parse(
- project,
- payload,
- monitoring_tool: Gitlab::AlertManagement::Payload::MONITORING_TOOLS[:prometheus]
- ).alert_params
-
- AlertManagement::Alert.new(alert_params).attributes
- end
- end
-
def bad_request
ServiceResponse.error(message: 'Bad Request', http_status: :bad_request)
end
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index 64b9eca9014..b9c579a130f 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -12,6 +12,11 @@ module Projects
# as it shares the namespace with groups
TMP_EXTRACT_PATH = '@pages.tmp'
+ # old deployment can be cached by pages daemon
+ # so we need to give pages daemon some time update cache
+ # 10 minutes is enough, but 30 feels safer
+ OLD_DEPLOYMENTS_DESTRUCTION_DELAY = 30.minutes.freeze
+
attr_reader :build
def initialize(project, build)
@@ -97,7 +102,7 @@ module Projects
build.artifacts_file.use_file do |artifacts_path|
SafeZip::Extract.new(artifacts_path)
.extract(directories: [PUBLIC_DIR], to: temp_path)
- create_pages_deployment(artifacts_path)
+ create_pages_deployment(artifacts_path, build)
end
rescue SafeZip::Extract::Error => e
raise FailedToExtractError, e.message
@@ -119,19 +124,28 @@ module Projects
FileUtils.rm_r(previous_public_path, force: true)
end
- def create_pages_deployment(artifacts_path)
- return unless Feature.enabled?(:zip_pages_deployments, project)
+ def create_pages_deployment(artifacts_path, build)
+ return unless Feature.enabled?(:zip_pages_deployments, project, default_enabled: true)
+
+ # we're using the full archive and pages daemon needs to read it
+ # so we want the total count from entries, not only "public/" directory
+ # because it better approximates work we need to do before we can serve the site
+ entries_count = build.artifacts_metadata_entry("", recursive: true).entries.count
+ sha256 = build.job_artifacts_archive.file_sha256
+ deployment = nil
File.open(artifacts_path) do |file|
- deployment = project.pages_deployments.create!(file: file)
- project.pages_metadatum.update!(pages_deployment: deployment)
+ deployment = project.pages_deployments.create!(file: file,
+ file_count: entries_count,
+ file_sha256: sha256)
+ project.update_pages_deployment!(deployment)
end
- # TODO: schedule old deployment removal https://gitlab.com/gitlab-org/gitlab/-/issues/235730
- rescue => e
- # we don't want to break current pages deployment process if something goes wrong
- # TODO: remove this rescue as part of https://gitlab.com/gitlab-org/gitlab/-/issues/245308
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
+ DestroyPagesDeploymentsWorker.perform_in(
+ OLD_DEPLOYMENTS_DESTRUCTION_DELAY,
+ project.id,
+ deployment.id
+ )
end
def latest?
diff --git a/app/services/projects/update_repository_storage_service.rb b/app/services/projects/update_repository_storage_service.rb
index a479d53a43a..e0d2398bc66 100644
--- a/app/services/projects/update_repository_storage_service.rb
+++ b/app/services/projects/update_repository_storage_service.rb
@@ -54,7 +54,7 @@ module Projects
end
def mirror_repositories
- mirror_repository
+ mirror_repository if project.repository_exists?
if project.wiki.repository_exists?
mirror_repository(type: Gitlab::GlRepository::WIKI)
@@ -92,12 +92,14 @@ module Projects
end
def remove_old_paths
- Gitlab::Git::Repository.new(
- source_storage_name,
- "#{project.disk_path}.git",
- nil,
- nil
- ).remove
+ if project.repository_exists?
+ Gitlab::Git::Repository.new(
+ source_storage_name,
+ "#{project.disk_path}.git",
+ nil,
+ nil
+ ).remove
+ end
if project.wiki.repository_exists?
Gitlab::Git::Repository.new(
diff --git a/app/services/releases/base_service.rb b/app/services/releases/base_service.rb
index 15d040287a3..38ef80ced56 100644
--- a/app/services/releases/base_service.rb
+++ b/app/services/releases/base_service.rb
@@ -81,6 +81,10 @@ module Releases
params.key?(:milestones)
end
+ def execute_hooks(release, action = 'create')
+ release.execute_hooks(action)
+ end
+
# overridden in EE
def project_group_id; end
end
diff --git a/app/services/releases/create_service.rb b/app/services/releases/create_service.rb
index 887c2d355ee..deefe559d5d 100644
--- a/app/services/releases/create_service.rb
+++ b/app/services/releases/create_service.rb
@@ -52,6 +52,8 @@ module Releases
notify_create_release(release)
+ execute_hooks(release, 'create')
+
create_evidence!(release, evidence_pipeline)
success(tag: tag, release: release)
diff --git a/app/services/releases/update_service.rb b/app/services/releases/update_service.rb
index 4786d35f31e..4e78120ac05 100644
--- a/app/services/releases/update_service.rb
+++ b/app/services/releases/update_service.rb
@@ -3,11 +3,9 @@
module Releases
class UpdateService < Releases::BaseService
def execute
- return error('Tag does not exist', 404) unless existing_tag
- return error('Release does not exist', 404) unless release
- return error('Access Denied', 403) unless allowed?
- return error('params is empty', 400) if empty_params?
- return error("Milestone(s) not found: #{inexistent_milestones.join(', ')}", 400) if inexistent_milestones.any?
+ if error = validate
+ return error
+ end
if param_for_milestone_titles_provided?
previous_milestones = release.milestones.map(&:title)
@@ -20,6 +18,7 @@ module Releases
# see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43385
ActiveRecord::Base.transaction do
if release.update(params)
+ execute_hooks(release, 'update')
success(tag: existing_tag, release: release, milestones_updated: milestones_updated?(previous_milestones))
else
error(release.errors.messages || '400 Bad request', 400)
@@ -31,6 +30,14 @@ module Releases
private
+ def validate
+ return error('Tag does not exist', 404) unless existing_tag
+ return error('Release does not exist', 404) unless release
+ return error('Access Denied', 403) unless allowed?
+ return error('params is empty', 400) if empty_params?
+ return error("Milestone(s) not found: #{inexistent_milestones.join(', ')}", 400) if inexistent_milestones.any?
+ end
+
def allowed?
Ability.allowed?(current_user, :update_release, release)
end
diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb
index cdeb57627a8..70e09be9407 100644
--- a/app/services/resource_access_tokens/create_service.rb
+++ b/app/services/resource_access_tokens/create_service.rb
@@ -15,13 +15,20 @@ module ResourceAccessTokens
user = create_user
return error(user.errors.full_messages.to_sentence) unless user.persisted?
- return error("Failed to provide maintainer access") unless provision_access(resource, user)
+
+ member = create_membership(resource, user)
+
+ unless member.persisted?
+ delete_failed_user(user)
+ return error("Could not provision maintainer access to project access token")
+ end
token_response = create_personal_access_token(user)
if token_response.success?
success(token_response.payload[:personal_access_token])
else
+ delete_failed_user(user)
error(token_response.message)
end
end
@@ -43,6 +50,10 @@ module ResourceAccessTokens
Users::CreateService.new(current_user, default_user_params).execute(skip_authorization: true)
end
+ def delete_failed_user(user)
+ DeleteUserWorker.perform_async(current_user.id, user.id, hard_delete: true, skip_authorization: true)
+ end
+
def default_user_params
{
name: params[:name] || "#{resource.name.to_s.humanize} bot",
@@ -72,7 +83,9 @@ module ResourceAccessTokens
end
def create_personal_access_token(user)
- PersonalAccessTokens::CreateService.new(user, personal_access_token_params).execute
+ PersonalAccessTokens::CreateService.new(
+ current_user: user, target_user: user, params: personal_access_token_params
+ ).execute
end
def personal_access_token_params
@@ -88,7 +101,7 @@ module ResourceAccessTokens
Gitlab::Auth.resource_bot_scopes
end
- def provision_access(resource, user)
+ def create_membership(resource, user)
resource.add_user(user, :maintainer, expires_at: params[:expires_at])
end
diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb
index 5f80b07aa59..9038650adb7 100644
--- a/app/services/search/global_service.rb
+++ b/app/services/search/global_service.rb
@@ -16,6 +16,7 @@ module Search
Gitlab::SearchResults.new(current_user,
params[:search],
projects,
+ order_by: params[:order_by],
sort: params[:sort],
filters: { state: params[:state], confidential: params[:confidential] })
end
diff --git a/app/services/search/group_service.rb b/app/services/search/group_service.rb
index e17522dcd68..4b2d8499582 100644
--- a/app/services/search/group_service.rb
+++ b/app/services/search/group_service.rb
@@ -16,6 +16,7 @@ module Search
params[:search],
projects,
group: group,
+ order_by: params[:order_by],
sort: params[:sort],
filters: { state: params[:state], confidential: params[:confidential] }
)
diff --git a/app/services/search/project_service.rb b/app/services/search/project_service.rb
index d32534303be..e5fc5a7a438 100644
--- a/app/services/search/project_service.rb
+++ b/app/services/search/project_service.rb
@@ -17,6 +17,7 @@ module Search
params[:search],
project: project,
repository_ref: params[:repository_ref],
+ order_by: params[:order_by],
sort: params[:sort],
filters: { confidential: params[:confidential], state: params[:state] }
)
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index 3ccd67c8d30..84d7e33c3d0 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -62,7 +62,9 @@ class SearchService
end
def search_objects(preload_method = nil)
- @search_objects ||= redact_unauthorized_results(search_results.objects(scope, page: params[:page], per_page: per_page, preload_method: preload_method))
+ @search_objects ||= redact_unauthorized_results(
+ search_results.objects(scope, page: page, per_page: per_page, preload_method: preload_method)
+ )
end
def search_highlight
@@ -71,6 +73,10 @@ class SearchService
private
+ def page
+ [1, params[:page].to_i].max
+ end
+
def per_page
per_page_param = params[:per_page].to_i
diff --git a/app/services/snippets/create_service.rb b/app/services/snippets/create_service.rb
index d7181883c39..0881be73eaf 100644
--- a/app/services/snippets/create_service.rb
+++ b/app/services/snippets/create_service.rb
@@ -56,7 +56,7 @@ module Snippets
snippet_saved
rescue => e # Rescuing all because we can receive Creation exceptions, GRPC exceptions, Git exceptions, ...
- log_error(e.message)
+ Gitlab::ErrorTracking.log_exception(e, service: 'Snippets::CreateService')
# If the commit action failed we need to remove the repository if exists
delete_repository(@snippet) if @snippet.repository_exists?
diff --git a/app/services/snippets/update_service.rb b/app/services/snippets/update_service.rb
index 0115cd19287..b982ff98747 100644
--- a/app/services/snippets/update_service.rb
+++ b/app/services/snippets/update_service.rb
@@ -74,7 +74,7 @@ module Snippets
add_snippet_repository_error(snippet: snippet, error: e)
- log_error(e.message)
+ Gitlab::ErrorTracking.log_exception(e, service: 'Snippets::UpdateService')
# If the commit action failed we remove it because
# we don't want to leave empty repositories
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 1a4374f2e94..eacc88f98a3 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -130,12 +130,12 @@ module SystemNoteService
::SystemNotes::MergeRequestsService.new(noteable: noteable, project: project, author: author).abort_merge_when_pipeline_succeeds(reason)
end
- def handle_merge_request_wip(noteable, project, author)
- ::SystemNotes::MergeRequestsService.new(noteable: noteable, project: project, author: author).handle_merge_request_wip
+ def handle_merge_request_draft(noteable, project, author)
+ ::SystemNotes::MergeRequestsService.new(noteable: noteable, project: project, author: author).handle_merge_request_draft
end
- def add_merge_request_wip_from_commit(noteable, project, author, commit)
- ::SystemNotes::MergeRequestsService.new(noteable: noteable, project: project, author: author).add_merge_request_wip_from_commit(commit)
+ def add_merge_request_draft_from_commit(noteable, project, author, commit)
+ ::SystemNotes::MergeRequestsService.new(noteable: noteable, project: project, author: author).add_merge_request_draft_from_commit(commit)
end
def resolve_all_discussions(merge_request, project, author)
diff --git a/app/services/system_notes/merge_requests_service.rb b/app/services/system_notes/merge_requests_service.rb
index 9b5c9ba20b2..a51e2053394 100644
--- a/app/services/system_notes/merge_requests_service.rb
+++ b/app/services/system_notes/merge_requests_service.rb
@@ -26,16 +26,16 @@ module SystemNotes
create_note(NoteSummary.new(noteable, project, author, body, action: 'merge'))
end
- def handle_merge_request_wip
- prefix = noteable.work_in_progress? ? "marked" : "unmarked"
+ def handle_merge_request_draft
+ action = noteable.work_in_progress? ? "draft" : "ready"
- body = "#{prefix} as a **Work In Progress**"
+ body = "marked this merge request as **#{action}**"
create_note(NoteSummary.new(noteable, project, author, body, action: 'title'))
end
- def add_merge_request_wip_from_commit(commit)
- body = "marked as a **Work In Progress** from #{commit.to_reference(project)}"
+ def add_merge_request_draft_from_commit(commit)
+ body = "marked this merge request as **draft** from #{commit.to_reference(project)}"
create_note(NoteSummary.new(noteable, project, author, body, action: 'title'))
end
diff --git a/app/services/test_hooks/project_service.rb b/app/services/test_hooks/project_service.rb
index 4e554dce357..dcd92ac2b8c 100644
--- a/app/services/test_hooks/project_service.rb
+++ b/app/services/test_hooks/project_service.rb
@@ -30,6 +30,8 @@ module TestHooks
pipeline_events_data
when 'wiki_page_events'
wiki_page_events_data
+ when 'releases_events'
+ releases_events_data
end
end
end
diff --git a/app/services/users/approve_service.rb b/app/services/users/approve_service.rb
index 228cfbd6947..27668e9430e 100644
--- a/app/services/users/approve_service.rb
+++ b/app/services/users/approve_service.rb
@@ -15,7 +15,9 @@ module Users
# Please see Devise's implementation of `resend_confirmation_instructions` for detail.
user.resend_confirmation_instructions
user.accept_pending_invitations! if user.active_for_authentication?
+ DeviseMailer.user_admin_approval(user).deliver_later
+ after_approve_hook(user)
success
else
error(user.errors.full_messages.uniq.join('. '))
@@ -26,6 +28,10 @@ module Users
attr_reader :current_user
+ def after_approve_hook(user)
+ # overridden by EE module
+ end
+
def allowed?
can?(current_user, :approve_user)
end
@@ -35,3 +41,5 @@ module Users
end
end
end
+
+Users::ApproveService.prepend_if_ee('EE::Users::ApproveService')
diff --git a/app/services/users/set_status_service.rb b/app/services/users/set_status_service.rb
index 89008368d5f..356c8782af1 100644
--- a/app/services/users/set_status_service.rb
+++ b/app/services/users/set_status_service.rb
@@ -14,7 +14,7 @@ module Users
def execute
return false unless can?(current_user, :update_user_status, target_user)
- if params[:emoji].present? || params[:message].present?
+ if params[:emoji].present? || params[:message].present? || params[:availability].present?
set_status
else
remove_status
@@ -25,6 +25,9 @@ module Users
def set_status
params[:emoji] = UserStatus::DEFAULT_EMOJI if params[:emoji].blank?
+ params.delete(:availability) if params[:availability].blank?
+ return false if params[:availability].present? && UserStatus.availabilities.keys.exclude?(params[:availability])
+
user_status.update(params)
end
diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb
index d6cb0729d6f..aef07b13cae 100644
--- a/app/services/web_hook_service.rb
+++ b/app/services/web_hook_service.rb
@@ -120,6 +120,7 @@ class WebHookService
@headers ||= begin
{
'Content-Type' => 'application/json',
+ 'User-Agent' => "GitLab/#{Gitlab::VERSION}",
GITLAB_EVENT_HEADER => self.class.hook_to_event(hook_name)
}.tap do |hash|
hash['X-Gitlab-Token'] = Gitlab::Utils.remove_line_breaks(hook.token) if hook.token.present?
diff --git a/app/uploaders/dependency_proxy/file_uploader.rb b/app/uploaders/dependency_proxy/file_uploader.rb
new file mode 100644
index 00000000000..b67a22bae4d
--- /dev/null
+++ b/app/uploaders/dependency_proxy/file_uploader.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class DependencyProxy::FileUploader < GitlabUploader
+ include ObjectStorage::Concern
+
+ storage_options Gitlab.config.dependency_proxy
+
+ alias_method :upload, :model
+
+ def filename
+ model.file_name
+ end
+
+ def store_dir
+ dynamic_segment
+ end
+
+ private
+
+ def dynamic_segment
+ Gitlab::HashedPath.new('dependency_proxy', model.group_id, 'files', model.id, root_hash: model.group_id)
+ end
+end
diff --git a/app/uploaders/gitlab_uploader.rb b/app/uploaders/gitlab_uploader.rb
index 411d8b2614f..9758d3c87aa 100644
--- a/app/uploaders/gitlab_uploader.rb
+++ b/app/uploaders/gitlab_uploader.rb
@@ -118,6 +118,14 @@ class GitlabUploader < CarrierWave::Uploader::Base
storage.store!(file)
end
+ def url_or_file_path(url_options = {})
+ if file_storage?
+ 'file://' + path
+ else
+ url(url_options)
+ end
+ end
+
private
# Designed to be overridden by child uploaders that have a dynamic path
diff --git a/app/validators/rsa_key_validator.rb b/app/validators/rsa_key_validator.rb
new file mode 100644
index 00000000000..64595454a8c
--- /dev/null
+++ b/app/validators/rsa_key_validator.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+# RsaKeyValidator
+#
+# Custom validator for RSA private keys.
+#
+# class Project < ActiveRecord::Base
+# validates :signing_key, rsa_key: true
+# end
+#
+class RsaKeyValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ unless valid_rsa_key?(value)
+ record.errors.add(attribute, "is not a valid RSA key")
+ end
+ end
+
+ private
+
+ def valid_rsa_key?(value)
+ return false unless value
+
+ OpenSSL::PKey::RSA.new(value)
+ rescue OpenSSL::PKey::RSAError
+ false
+ end
+end
diff --git a/app/views/admin/application_settings/_eks.html.haml b/app/views/admin/application_settings/_eks.html.haml
index 68324425ef9..5c0e544eaad 100644
--- a/app/views/admin/application_settings/_eks.html.haml
+++ b/app/views/admin/application_settings/_eks.html.haml
@@ -3,7 +3,7 @@
.settings-header
%h4
= _('Amazon EKS')
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
= _('Amazon EKS integration allows you to provision EKS clusters from GitLab.')
diff --git a/app/views/admin/application_settings/_gitpod.html.haml b/app/views/admin/application_settings/_gitpod.html.haml
index f0a1fd5e763..1baec07fa25 100644
--- a/app/views/admin/application_settings/_gitpod.html.haml
+++ b/app/views/admin/application_settings/_gitpod.html.haml
@@ -5,10 +5,10 @@
.settings-header
%h4
= _('Gitpod')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- = gitpod_enable_description
+ %integration-help-text{ "id" => "js-gitpod-settings-help-text", "message" => gitpod_enable_description, "message-url" => "https://gitpod.io/" }
= link_to sprite_icon('question-o'), help_page_path('integration/gitpod.md'), target: '_blank', class: 'has-tooltip', title: _('More information')
diff --git a/app/views/admin/application_settings/_outbound.html.haml b/app/views/admin/application_settings/_outbound.html.haml
index 4f38ab3ab7a..db0a87c366e 100644
--- a/app/views/admin/application_settings/_outbound.html.haml
+++ b/app/views/admin/application_settings/_outbound.html.haml
@@ -13,9 +13,9 @@
= _('Allow requests to the local network from system hooks')
.form-group
- = f.label :outbound_local_requests_whitelist_raw, class: 'label-bold' do
+ = f.label :outbound_local_requests_allowlist_raw, class: 'label-bold' do
= _('Local IP addresses and domain names that hooks and services may access.')
- = f.text_area :outbound_local_requests_whitelist_raw, placeholder: "example.com, 192.168.1.1", class: 'form-control', rows: 8
+ = f.text_area :outbound_local_requests_allowlist_raw, placeholder: "example.com, 192.168.1.1", class: 'form-control', rows: 8
%span.form-text.text-muted
= _('Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com.')
diff --git a/app/views/admin/application_settings/_package_registry.html.haml b/app/views/admin/application_settings/_package_registry.html.haml
index 257a90252cc..8c956a43e22 100644
--- a/app/views/admin/application_settings/_package_registry.html.haml
+++ b/app/views/admin/application_settings/_package_registry.html.haml
@@ -3,7 +3,7 @@
.settings-header
%h4
= _('Package Registry')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _("Settings related to the use and experience of using GitLab's Package Registry.")
diff --git a/app/views/admin/application_settings/_plantuml.html.haml b/app/views/admin/application_settings/_plantuml.html.haml
index 324f544a108..30acb773424 100644
--- a/app/views/admin/application_settings/_plantuml.html.haml
+++ b/app/views/admin/application_settings/_plantuml.html.haml
@@ -3,7 +3,7 @@
.settings-header
%h4
= _('PlantUML')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
= _('Allow rendering of PlantUML diagrams in Asciidoc documents.')
diff --git a/app/views/admin/application_settings/_signin.html.haml b/app/views/admin/application_settings/_signin.html.haml
index 4a8616beff6..66fd0087c3e 100644
--- a/app/views/admin/application_settings/_signin.html.haml
+++ b/app/views/admin/application_settings/_signin.html.haml
@@ -50,11 +50,11 @@
= f.text_field :home_page_url, class: 'form-control', placeholder: 'http://company.example.com', :'aria-describedby' => 'home_help_block'
%span.form-text.text-muted#home_help_block We will redirect non-logged in users to this page
.form-group
- = f.label :after_sign_out_path, class: 'label-bold'
+ = f.label :after_sign_out_path, _('After sign-out path'), class: 'label-bold'
= f.text_field :after_sign_out_path, class: 'form-control', placeholder: 'http://company.example.com', :'aria-describedby' => 'after_sign_out_path_help_block'
%span.form-text.text-muted#after_sign_out_path_help_block We will redirect users to this page after they sign out
.form-group
- = f.label :sign_in_text, class: 'label-bold'
+ = f.label :sign_in_text, _('Sign-in text'), class: 'label-bold'
= f.text_area :sign_in_text, class: 'form-control', rows: 4
.form-text.text-muted Markdown enabled
= f.submit 'Save changes', class: "gl-button btn btn-success"
diff --git a/app/views/admin/application_settings/_signup.html.haml b/app/views/admin/application_settings/_signup.html.haml
index 98b49a236a3..c3deb8af99e 100644
--- a/app/views/admin/application_settings/_signup.html.haml
+++ b/app/views/admin/application_settings/_signup.html.haml
@@ -9,19 +9,21 @@
Sign-up enabled
.form-text.text-muted
= _("When enabled, any user visiting %{host} will be able to create an account.") % { host: "#{new_user_session_url(host: Gitlab.config.gitlab.host)}" }
- - if Feature.enabled?(:admin_approval_for_new_user_signups, default_enabled: true)
- .form-group
- .form-check
- = f.check_box :require_admin_approval_after_user_signup, class: 'form-check-input'
- = f.label :require_admin_approval_after_user_signup, class: 'form-check-label' do
- = _('Require admin approval for new sign-ups')
- .form-text.text-muted
- = _("When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled.") % { host: "#{new_user_session_url(host: Gitlab.config.gitlab.host)}" }
+ .form-group
+ .form-check
+ = f.check_box :require_admin_approval_after_user_signup, class: 'form-check-input'
+ = f.label :require_admin_approval_after_user_signup, class: 'form-check-label' do
+ = _('Require admin approval for new sign-ups')
+ .form-text.text-muted
+ = _("When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled.") % { host: "#{new_user_session_url(host: Gitlab.config.gitlab.host)}" }
.form-group
.form-check
= f.check_box :send_user_confirmation_email, class: 'form-check-input'
= f.label :send_user_confirmation_email, class: 'form-check-label' do
Send confirmation email on sign-up
+
+ = render_if_exists 'admin/application_settings/new_user_signups_cap', form: f
+
.form-group
= f.label :minimum_password_length, _('Minimum password length (number of characters)'), class: 'label-bold'
= f.number_field :minimum_password_length, class: 'form-control', rows: 4, min: ApplicationSetting::DEFAULT_MINIMUM_PASSWORD_LENGTH, max: Devise.password_length.max
@@ -29,33 +31,33 @@
.form-text.text-muted
= _("See GitLab's %{password_policy_guidelines}").html_safe % { password_policy_guidelines: password_policy_guidelines_link }
.form-group
- = f.label :domain_whitelist, 'Whitelisted domains for sign-ups', class: 'label-bold'
- = f.text_area :domain_whitelist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
+ = f.label :domain_allowlist, _('Allowed domains for sign-ups'), class: 'label-bold'
+ = f.text_area :domain_allowlist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
.form-text.text-muted ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com
.form-group
- = f.label :domain_blacklist_enabled, 'Domain Blacklist', class: 'label-bold'
+ = f.label :domain_denylist_enabled, _('Domain denylist'), class: 'label-bold'
.form-check
- = f.check_box :domain_blacklist_enabled, class: 'form-check-input'
- = f.label :domain_blacklist_enabled, class: 'form-check-label' do
- Enable domain blacklist for sign ups
+ = f.check_box :domain_denylist_enabled, class: 'form-check-input'
+ = f.label :domain_denylist_enabled, class: 'form-check-label' do
+ Enable domain denylist for sign ups
.form-group
.form-check
- = radio_button_tag :blacklist_type, :file, false, class: 'form-check-input'
- = label_tag :blacklist_type_file, class: 'form-check-label' do
+ = radio_button_tag :denylist_type, :file, false, class: 'form-check-input'
+ = label_tag :denylist_type_file, class: 'form-check-label' do
.option-title
- Upload blacklist file
+ Upload denylist file
.form-check
- = radio_button_tag :blacklist_type, :raw, @application_setting.domain_blacklist.present? || @application_setting.domain_blacklist.blank?, class: 'form-check-input'
- = label_tag :blacklist_type_raw, class: 'form-check-label' do
+ = radio_button_tag :denylist_type, :raw, @application_setting.domain_denylist.present? || @application_setting.domain_denylist.blank?, class: 'form-check-input'
+ = label_tag :denylist_type_raw, class: 'form-check-label' do
.option-title
- Enter blacklist manually
- .form-group.blacklist-file
- = f.label :domain_blacklist_file, 'Blacklist file', class: 'label-bold'
- = f.file_field :domain_blacklist_file, class: 'form-control', accept: '.txt,.conf'
+ Enter denylist manually
+ .form-group.js-denylist-file
+ = f.label :domain_denylist_file, _('Denylist file'), class: 'label-bold'
+ = f.file_field :domain_denylist_file, class: 'form-control', accept: '.txt,.conf'
.form-text.text-muted Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines or commas for multiple entries.
- .form-group.blacklist-raw
- = f.label :domain_blacklist, 'Blacklisted domains for sign-ups', class: 'label-bold'
- = f.text_area :domain_blacklist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
+ .form-group.js-denylist-raw
+ = f.label :domain_denylist, _('Denied domains for sign-ups'), class: 'label-bold'
+ = f.text_area :domain_denylist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
.form-text.text-muted Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com
.form-group
= f.label :email_restrictions_enabled, _('Email restrictions'), class: 'label-bold'
diff --git a/app/views/admin/application_settings/_snowplow.html.haml b/app/views/admin/application_settings/_snowplow.html.haml
index 7c2c5e0b3dc..c1edaf9ff29 100644
--- a/app/views/admin/application_settings/_snowplow.html.haml
+++ b/app/views/admin/application_settings/_snowplow.html.haml
@@ -3,7 +3,7 @@
.settings-header
%h4
= _('Snowplow')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
= _('Configure the %{link} integration.').html_safe % { link: link_to('Snowplow', 'https://snowplowanalytics.com/', target: '_blank') }
diff --git a/app/views/admin/application_settings/_third_party_offers.html.haml b/app/views/admin/application_settings/_third_party_offers.html.haml
index 7e3e063118e..32023b11993 100644
--- a/app/views/admin/application_settings/_third_party_offers.html.haml
+++ b/app/views/admin/application_settings/_third_party_offers.html.haml
@@ -3,7 +3,7 @@
.settings-header
%h4
= _('Third party offers')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
= _('Control the display of third party offers.')
diff --git a/app/views/admin/application_settings/ci/_header.html.haml b/app/views/admin/application_settings/ci/_header.html.haml
index 6ff35a42efd..0a0f8aaf032 100644
--- a/app/views/admin/application_settings/ci/_header.html.haml
+++ b/app/views/admin/application_settings/ci/_header.html.haml
@@ -4,7 +4,7 @@
= _('Variables')
= link_to sprite_icon('question-o', css_class: 'gl-vertical-align-baseline!'), help_page_path('ci/variables/README', anchor: 'custom-environment-variables'), target: '_blank', rel: 'noopener noreferrer'
-%button.btn.btn-default.js-settings-toggle{ type: 'button' }
+%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
diff --git a/app/views/admin/application_settings/ci_cd.html.haml b/app/views/admin/application_settings/ci_cd.html.haml
index cdb69d33b12..b05e8621d07 100644
--- a/app/views/admin/application_settings/ci_cd.html.haml
+++ b/app/views/admin/application_settings/ci_cd.html.haml
@@ -17,7 +17,7 @@
.settings-header
%h4
= _('Continuous Integration and Deployment')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Auto DevOps, runners and job artifacts')
@@ -33,7 +33,7 @@
.settings-header
%h4
= _('Container Registry')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Various container registry settings.')
diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml
index 2d336bebc8d..5c3f68843a2 100644
--- a/app/views/admin/application_settings/general.html.haml
+++ b/app/views/admin/application_settings/general.html.haml
@@ -6,7 +6,7 @@
.settings-header
%h4
= _('Visibility and access controls')
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Set default and restrict visibility levels. Configure import sources and git access protocol.')
@@ -17,7 +17,7 @@
.settings-header
%h4
= _('Account and limit')
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan.')
@@ -28,7 +28,7 @@
.settings-header
%h4
= _('Diff limits')
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Diff content limits')
@@ -39,7 +39,7 @@
.settings-header
%h4
= _('Sign-up restrictions')
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Configure the way a user creates a new account.')
@@ -50,7 +50,7 @@
.settings-header
%h4
= _('Sign-in restrictions')
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Set requirements for a user to sign-in. Enable mandatory two-factor authentication.')
@@ -61,7 +61,7 @@
.settings-header
%h4
= _('Terms of Service and Privacy Policy')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Include a Terms of Service agreement and Privacy Policy that all users must accept.')
@@ -74,7 +74,7 @@
.settings-header
%h4
= _('Web terminal')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Set max session time for web terminal.')
@@ -85,7 +85,7 @@
.settings-header
%h4
= _('Web IDE')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Manage Web IDE features')
@@ -108,7 +108,7 @@
.settings-header
%h4
= _('Maintenance mode')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Prevent users from performing write operations on GitLab while performing maintenance.')
diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml
index 40fa86d8ea3..f977a8c93fa 100644
--- a/app/views/admin/application_settings/network.html.haml
+++ b/app/views/admin/application_settings/network.html.haml
@@ -6,7 +6,7 @@
.settings-header
%h4
= _('Performance optimization')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Various settings that affect GitLab performance.')
@@ -17,7 +17,7 @@
.settings-header
%h4
= _('User and IP Rate Limits')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Configure limits for web and API requests.')
@@ -28,7 +28,7 @@
.settings-header
%h4
= _('Outbound requests')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Allow requests to the local network from hooks and services.')
@@ -39,10 +39,14 @@
.settings-header
%h4
= _('Protected Paths')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Configure paths to be protected by Rack Attack.')
+ .help-block
+ = _('These paths are protected for POST requests.')
+ = link_to _('More information'), help_page_path('security/rack_attack', anchor: 'protected-paths-throttle'), target: '_blank'
+
.settings-content
= render 'protected_paths'
@@ -50,7 +54,7 @@
.settings-header
%h4
= _('Issues Rate Limits')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Configure limit for issues created per minute by web and API requests.')
@@ -61,7 +65,7 @@
.settings-header
%h4
= _('Import/Export Rate Limits')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Configure limits for Project/Group Import/Export.')
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index b0d4a3fd8f5..220a211cca6 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -1,5 +1,7 @@
- breadcrumb_title _("Dashboard")
- page_title _("Dashboard")
+- billable_users_url = help_page_path('subscriptions/self_managed/index', anchor: 'billable-users')
+- billable_users_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer nofollow">'.html_safe % { url: billable_users_url }
- if @notices
- @notices.each do |notice|
@@ -8,7 +10,9 @@
= notice[:message].html_safe
- if @license.present? && show_license_breakdown?
- = render_if_exists 'admin/licenses/breakdown'
+ .license-panel.gl-mt-5
+ = render_if_exists 'admin/licenses/summary'
+ = render_if_exists 'admin/licenses/breakdown'
.admin-dashboard.gl-mt-3
.row
@@ -22,10 +26,20 @@
= link_to(s_('AdminArea|New project'), new_project_path, class: "btn gl-button btn-success gl-w-full")
.col-sm-4
.info-well.dark-well
- .well-segment.well-centered
+ .well-segment.well-centered.gl-text-center
= link_to admin_users_path do
- %h3.text-center
+ %h3.gl-display-inline-block.gl-mb-0
= s_('AdminArea|Users: %{number_of_users}') % { number_of_users: approximate_count_with_delimiters(@counts, User) }
+
+ %span.gl-outline-0.gl-ml-2{ href: "#", tabindex: "0", data: { container: "body",
+ toggle: "popover",
+ placement: "top",
+ html: "true",
+ trigger: "focus",
+ content: s_("AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}.").html_safe % { billable_users_link_start: billable_users_link_start, billable_users_link_end: '</a>'.html_safe },
+ } }
+ = sprite_icon('question', size: 16, css_class: 'gl-text-gray-700 gl-mb-1')
+
%hr
.btn-group.d-flex{ role: 'group' }
= link_to s_('AdminArea|New user'), new_admin_user_path, class: "btn gl-button btn-success gl-w-full"
@@ -126,6 +140,10 @@
%span.float-right
= Gitlab::Database.version
%p
+ = _('Redis')
+ %span.float-right
+ = @redis_versions&.join(", ")
+ %p
= link_to _("Gitaly Servers"), admin_gitaly_servers_path
.row
.col-md-4
diff --git a/app/views/admin/dev_ops_report/_report.html.haml b/app/views/admin/dev_ops_report/_report.html.haml
new file mode 100644
index 00000000000..24c805d273a
--- /dev/null
+++ b/app/views/admin/dev_ops_report/_report.html.haml
@@ -0,0 +1,30 @@
+- usage_ping_enabled = Gitlab::CurrentSettings.usage_ping_enabled
+
+- if usage_ping_enabled && show_callout?('dev_ops_report_intro_callout_dismissed')
+ = render 'callout'
+
+- if !usage_ping_enabled
+ #js-devops-empty-state{ data: { is_admin: current_user&.admin.to_s, empty_state_svg_path: image_path('illustrations/convdev/convdev_no_index.svg'), enable_usage_ping_link: metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings'), docs_link: help_page_path('development/product_analytics/usage_ping') } }
+- 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
+ = s_('DevopsReport|DevOps')
+ %br
+ = s_('DevopsReport|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
+ - @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/dev_ops_report/show.html.haml b/app/views/admin/dev_ops_report/show.html.haml
index 88105be70fb..dc3bda3a994 100644
--- a/app/views/admin/dev_ops_report/show.html.haml
+++ b/app/views/admin/dev_ops_report/show.html.haml
@@ -1,34 +1,10 @@
- page_title _('DevOps Report')
-- usage_ping_enabled = Gitlab::CurrentSettings.usage_ping_enabled
- add_page_specific_style 'page_bundles/dev_ops_report'
.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/product_analytics/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
+ - if Gitlab.ee? && Feature.enabled?(:devops_adoption_feature) && License.feature_available?(:devops_adoption)
+ = render_if_exists 'admin/dev_ops_report/devops_tabs'
+ - else
+ = render 'report'
- .devops-steps.d-none.d-lg-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/show.html.haml b/app/views/admin/groups/show.html.haml
index 424251f543e..386df99717b 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -1,6 +1,7 @@
- add_to_breadcrumbs _("Groups"), admin_groups_path
- breadcrumb_title @group.name
- page_title @group.name, _("Groups")
+- current_user_is_group_owner = @group && @group.has_owner?(current_user)
.js-remove-member-modal
%h3.page-title
@@ -116,7 +117,7 @@
= select_tag :access_level, options_for_select(@group.access_level_roles), class: "project-access-select select2"
%hr
= button_tag _('Add users to group'), class: "gl-button btn btn-success"
- = render 'shared/members/requests', membership_source: @group, requesters: @requesters, force_mobile_view: true
+ = render 'shared/members/requests', membership_source: @group, group: @group, requesters: @requesters, force_mobile_view: true
.card
.card-header
@@ -127,6 +128,11 @@
= sprite_icon('pencil-square', css_class: 'gl-icon')
= _('Manage access')
%ul.content-list.group-users-list.content-list.members-list
- = render partial: 'shared/members/member', collection: @members, as: :member, locals: { show_controls: false }
+ = render partial: 'shared/members/member',
+ collection: @members, as: :member,
+ locals: { membership_source: @group,
+ group: @group,
+ show_controls: false,
+ current_user_is_group_owner: current_user_is_group_owner }
.card-footer
= paginate @members, param_name: 'members_page', theme: 'gitlab'
diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
index 76e4fa971a3..78f0fd325fb 100644
--- a/app/views/admin/health_check/show.html.haml
+++ b/app/views/admin/health_check/show.html.haml
@@ -30,7 +30,7 @@
= sprite_icon('check', css_class: 'cgreen')
#{ s_('HealthCheck|Healthy') }
- else
- = icon('warning', class: 'cred')
+ = sprite_icon('warning-solid', css_class: 'cred')
#{ s_('HealthCheck|Unhealthy') }
.card-body
- if no_errors
diff --git a/app/views/admin/identities/_identity.html.haml b/app/views/admin/identities/_identity.html.haml
index d8facbb780a..d852e4a2463 100644
--- a/app/views/admin/identities/_identity.html.haml
+++ b/app/views/admin/identities/_identity.html.haml
@@ -1,6 +1,6 @@
%tr
%td
- #{Gitlab::Auth::OAuth::Provider.label_for(identity.provider)} (#{identity.provider})
+ #{Gitlab::Auth::OAuth::Provider.label_for(identity.provider)} (#{identity.provider}) #{identity.saml_provider_id.present? ? "for #{link_to identity.saml_provider.group.path, identity.saml_provider.group} ID: #{identity.saml_provider_id}".html_safe : ""}
%td
= identity.extern_uid
%td
diff --git a/app/views/admin/jobs/index.html.haml b/app/views/admin/jobs/index.html.haml
index d482ae04c08..8eaf84c8df9 100644
--- a/app/views/admin/jobs/index.html.haml
+++ b/app/views/admin/jobs/index.html.haml
@@ -6,11 +6,9 @@
= render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope
- if @all_builds.running_or_pending.any?
- #stop-jobs-modal
+ #js-stop-jobs-modal
.nav-controls
- %button#stop-jobs-button.btn.gl-button.btn-danger{ data: { toggle: 'modal',
- target: '#stop-jobs-modal',
- url: cancel_all_admin_jobs_path } }
+ %button#js-stop-jobs-button.btn.gl-button.btn-danger{ data: { url: cancel_all_admin_jobs_path } }
= s_('AdminArea|Stop all jobs')
.row-content-block.second-block
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 417fd1d60eb..aae1d5b6a4e 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -2,6 +2,7 @@
- breadcrumb_title @project.full_name
- page_title @project.full_name, _("Projects")
- @content_class = "admin-projects"
+- current_user_is_group_owner = @group && @group.has_owner?(current_user)
.js-remove-member-modal
%h3.page-title
@@ -13,7 +14,7 @@
- if @project.last_repository_check_failed?
.row
.col-md-12
- .gl-alert.gl-alert-danger.gl-mb-5
+ .gl-alert.gl-alert-danger.gl-mb-5{ data: { testid: 'last-repository-check-failed-alert' } }
= sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
- last_check_message = _("Last repository check (%{last_check_timestamp}) failed. See the 'repocheck.log' file for error messages.")
@@ -183,11 +184,16 @@
= sprite_icon('pencil-square', css_class: 'gl-icon')
= _('Manage access')
%ul.content-list.members-list
- = render partial: 'shared/members/member', collection: @group_members, as: :member, locals: { show_controls: false }
+ = render partial: 'shared/members/member',
+ collection: @group_members, as: :member,
+ locals: { membership_source: @project,
+ group: @group,
+ show_controls: false,
+ current_user_is_group_owner: current_user_is_group_owner }
.card-footer
= paginate @group_members, param_name: 'group_members_page', theme: 'gitlab'
- = render 'shared/members/requests', membership_source: @project, requesters: @requesters, force_mobile_view: true
+ = render 'shared/members/requests', membership_source: @project, group: @group, requesters: @requesters, force_mobile_view: true
.card
.card-header
@@ -199,6 +205,11 @@
= sprite_icon('pencil-square', css_class: 'gl-icon')
= _('Manage access')
%ul.content-list.project_members.members-list
- = render partial: 'shared/members/member', collection: @project_members, as: :member, locals: { show_controls: false }
+ = render partial: 'shared/members/member',
+ collection: @project_members, as: :member,
+ locals: { membership_source: @project,
+ group: @group,
+ show_controls: false,
+ current_user_is_group_owner: current_user_is_group_owner }
.card-footer
= paginate @project_members, param_name: 'project_members_page', theme: 'gitlab'
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index 3d3b8c28a17..c2d7b63f1f9 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -39,7 +39,9 @@
= render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: Gitlab::CurrentSettings.runners_registration_token,
type: 'shared',
- reset_token_url: reset_registration_token_admin_application_settings_path }
+ reset_token_url: reset_registration_token_admin_application_settings_path,
+ project_path: '',
+ group_path: '' }
.row
.col-sm-9
diff --git a/app/views/admin/serverless/domains/_form.html.haml b/app/views/admin/serverless/domains/_form.html.haml
index 8f0dd0cab8e..e4b054c7480 100644
--- a/app/views/admin/serverless/domains/_form.html.haml
+++ b/app/views/admin/serverless/domains/_form.html.haml
@@ -36,7 +36,7 @@
= clipboard_button(target: '#serverless_domain_verification', class: 'btn-default d-none d-sm-block')
%p.form-text.text-muted
- link_to_help = link_to(_('verify ownership'), help_page_path('user/project/pages/custom_domains_ssl_tls_certification/index.md', anchor: '4-verify-the-domains-ownership'))
- = _("To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration.").html_safe % { link_to_help: link_to_help }
+ = _("To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration.").html_safe % { link_to_help: link_to_help }
- else
.form-group
diff --git a/app/views/admin/system_info/show.html.haml b/app/views/admin/system_info/show.html.haml
index 312ca62cfdf..ca6efe9b095 100644
--- a/app/views/admin/system_info/show.html.haml
+++ b/app/views/admin/system_info/show.html.haml
@@ -9,7 +9,7 @@
- if @cpus
%h2= _('%{cores} cores') % { cores: @cpus.length }
- else
- = icon('warning', class: 'text-warning')
+ = sprite_icon('warning-solid', css_class: 'text-warning')
= _('Unable to collect CPU info')
.bg-light.light-well.gl-mt-3
%h4= _('Memory Usage')
@@ -17,7 +17,7 @@
- if @memory
%h2 #{number_to_human_size(@memory.active_bytes)} / #{number_to_human_size(@memory.total_bytes)}
- else
- = icon('warning', class: 'text-warning')
+ = sprite_icon('warning-solid', css_class: 'text-warning')
= _('Unable to collect memory info')
.bg-light.light-well.gl-mt-3
%h4= _('Uptime')
diff --git a/app/views/admin/users/_block_user.html.haml b/app/views/admin/users/_block_user.html.haml
index b07a72c3e28..29029986345 100644
--- a/app/views/admin/users/_block_user.html.haml
+++ b/app/views/admin/users/_block_user.html.haml
@@ -2,10 +2,7 @@
.card-header.bg-warning.text-white
= s_('AdminUsers|Block this user')
.card-body
- = render partial: 'admin/users/user_block_effects'
+ = user_block_effects
%br
- %button.btn.gl-button.btn-warning{ data: { 'gl-modal-action': 'block',
- content: s_('AdminUsers|You can always unblock their account, their data will remain intact.'),
- url: block_admin_user_path(user),
- username: sanitize_name(user.name) } }
+ %button.btn.gl-button.btn-warning.js-confirm-modal-button{ data: user_block_data(user, s_('AdminUsers|You can always unblock their account, their data will remain intact.')) }
= s_('AdminUsers|Block user')
diff --git a/app/views/admin/users/_modals.html.haml b/app/views/admin/users/_modals.html.haml
index a8e5d962e5b..e56bbd06575 100644
--- a/app/views/admin/users/_modals.html.haml
+++ b/app/views/admin/users/_modals.html.haml
@@ -5,11 +5,6 @@
action: s_("AdminUsers|Deactivate") } }
= render partial: 'admin/users/user_deactivation_effects'
- %div{ data: { modal: "block",
- title: s_("AdminUsers|Block user %{username}?"),
- action: s_("AdminUsers|Block") } }
- = render partial: 'admin/users/user_block_effects'
-
%div{ data: { modal: "delete",
title: s_("AdminUsers|Delete User %{username}?"),
action: s_('AdminUsers|Delete user'),
diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml
index 70ab95bfa61..679c4805280 100644
--- a/app/views/admin/users/_user.html.haml
+++ b/app/views/admin/users/_user.html.haml
@@ -24,10 +24,10 @@
.table-action-buttons
= 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.gl-button.btn-default{ type: 'button', data: { toggle: 'dropdown' } }
+ %button.dropdown-new.btn.gl-button.btn-default{ type: 'button', data: { testid: "user-action-button-#{user.id}", toggle: 'dropdown' } }
= sprite_icon('settings')
= sprite_icon('chevron-down')
- %ul.dropdown-menu.dropdown-menu-right
+ %ul.dropdown-menu.dropdown-menu-right{ data: { testid: "user-action-dropdown-#{user.id}" } }
%li.dropdown-header
= _('Settings')
%li
@@ -37,16 +37,12 @@
- elsif user.blocked?
- if user.blocked_pending_approval?
= link_to s_('AdminUsers|Approve'), approve_admin_user_path(user), method: :put
- %button.btn.btn-default-tertiary{ data: { 'gl-modal-action': 'block',
- url: block_admin_user_path(user),
- username: sanitize_name(user.name) } }
+ %button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_block_data(user, user_block_effects) }
= s_('AdminUsers|Block')
- else
= link_to _('Unblock'), unblock_admin_user_path(user), method: :put
- else
- %button.btn.btn-default-tertiary{ data: { 'gl-modal-action': 'block',
- url: block_admin_user_path(user),
- username: sanitize_name(user.name) } }
+ %button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_block_data(user, user_block_effects) }
= s_('AdminUsers|Block')
- if user.can_be_deactivated?
%li
diff --git a/app/views/admin/users/_user_block_effects.html.haml b/app/views/admin/users/_user_block_effects.html.haml
deleted file mode 100644
index 8ffbe145169..00000000000
--- a/app/views/admin/users/_user_block_effects.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-%p
- = s_('AdminUsers|Blocking user has the following effects:')
-%ul
- %li
- = s_('AdminUsers|User will not be able to login')
- %li
- = s_('AdminUsers|User will not be able to access git repositories')
- %li
- = s_('AdminUsers|Personal projects will be left')
- %li
- = s_('AdminUsers|Owned groups will be left')
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index 33faef92646..2e179d2d845 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -30,11 +30,10 @@
= link_to admin_users_path(filter: "blocked") do
= s_('AdminUsers|Blocked')
%small.badge.badge-pill= limited_counter_with_delimiter(User.blocked)
- - if Feature.enabled?(:admin_approval_for_new_user_signups, default_enabled: true)
- = nav_link(html_options: { class: "#{active_when(params[:filter] == 'blocked_pending_approval')} filter-blocked-pending-approval" }) do
- = link_to admin_users_path(filter: "blocked_pending_approval") do
- = s_('AdminUsers|Pending approval')
- %small.badge.badge-pill= limited_counter_with_delimiter(User.blocked_pending_approval)
+ = nav_link(html_options: { class: "#{active_when(params[:filter] == 'blocked_pending_approval')} filter-blocked-pending-approval" }) do
+ = link_to admin_users_path(filter: "blocked_pending_approval") do
+ = s_('AdminUsers|Pending approval')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.blocked_pending_approval)
= nav_link(html_options: { class: active_when(params[:filter] == 'deactivated') }) do
= link_to admin_users_path(filter: "deactivated") do
= s_('AdminUsers|Deactivated')
diff --git a/app/views/ci/runner/_how_to_setup_runner.html.haml b/app/views/ci/runner/_how_to_setup_runner.html.haml
index 6c2bd2a5d2f..0ff6fdc6354 100644
--- a/app/views/ci/runner/_how_to_setup_runner.html.haml
+++ b/app/views/ci/runner/_how_to_setup_runner.html.haml
@@ -15,7 +15,9 @@
= clipboard_button(target: '#registration_token', title: _("Copy token"), class: "btn-transparent btn-clipboard")
.gl-mt-3.gl-mb-3
= button_to _("Reset runners registration token"), reset_token_url,
- method: :put, class: 'btn btn-default',
+ method: :put, class: 'gl-button btn btn-default',
data: { confirm: _("Are you sure you want to reset registration token?") }
%li
= _("Start the Runner!")
+
+#js-install-runner{ data: { project_path: project_path, group_path: group_path } }
diff --git a/app/views/ci/runner/_how_to_setup_runner_automatically.html.haml b/app/views/ci/runner/_how_to_setup_runner_automatically.html.haml
index 42710039757..343abf6099e 100644
--- a/app/views/ci/runner/_how_to_setup_runner_automatically.html.haml
+++ b/app/views/ci/runner/_how_to_setup_runner_automatically.html.haml
@@ -19,4 +19,4 @@
= link_to _('Install Runner on Kubernetes'),
clusters_path,
- class: 'btn btn-info'
+ class: 'gl-button btn btn-info'
diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml
index b90e672cca9..660fd1a48a7 100644
--- a/app/views/ci/variables/_index.html.haml
+++ b/app/views/ci/variables/_index.html.haml
@@ -5,42 +5,20 @@
- link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/README', anchor: 'protect-a-custom-variable') }
= s_('Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
-- if Feature.enabled?(:new_variables_ui, @project || @group, default_enabled: true)
- - is_group = !@group.nil?
+- is_group = !@group.nil?
- #js-ci-project-variables{ data: { endpoint: save_endpoint,
- project_id: @project&.id || '',
- group: is_group.to_s,
- maskable_regex: ci_variable_maskable_regex,
- protected_by_default: ci_variable_protected_by_default?.to_s,
- aws_logo_svg_path: image_path('aws_logo.svg'),
- aws_tip_deploy_link: help_page_path('ci/cloud_deployment/index.md', anchor: 'deploy-your-application-to-the-aws-elastic-container-service-ecs'),
- aws_tip_commands_link: help_page_path('ci/cloud_deployment/index.md', anchor: 'run-aws-commands-from-gitlab-cicd'),
- aws_tip_learn_link: help_page_path('ci/cloud_deployment/index.md', anchor: 'aws'),
- protected_environment_variables_link: help_page_path('ci/variables/README', anchor: 'protect-a-custom-variable'),
- masked_environment_variables_link: help_page_path('ci/variables/README', anchor: 'mask-a-custom-variable'),
- } }
-
-- else
- .row
- .col-lg-12.js-ci-variable-list-section{ data: { save_endpoint: save_endpoint, maskable_regex: ci_variable_maskable_regex } }
- .hide.gl-alert.gl-alert-danger.js-ci-variable-error-box
-
- %ul.ci-variable-list
- = render 'ci/variables/variable_header'
- - @variables.each.each do |variable|
- = render 'ci/variables/variable_row', form_field: 'variables', variable: variable
- = render 'ci/variables/variable_row', form_field: 'variables'
- .prepend-top-20
- %button.btn.btn-success.js-ci-variables-save-button{ type: 'button' }
- %span.hide.js-ci-variables-save-loading-icon
- .spinner.spinner-light.mr-1
- = _('Save variables')
- %button.btn.btn-info.btn-inverted.gl-ml-3.js-secret-value-reveal-button{ type: 'button', data: { secret_reveal_status: "#{@variables.size == 0}" } }
- - if @variables.size == 0
- = n_('Hide value', 'Hide values', @variables.size)
- - else
- = n_('Reveal value', 'Reveal values', @variables.size)
+#js-ci-project-variables{ data: { endpoint: save_endpoint,
+ project_id: @project&.id || '',
+ group: is_group.to_s,
+ maskable_regex: ci_variable_maskable_regex,
+ protected_by_default: ci_variable_protected_by_default?.to_s,
+ aws_logo_svg_path: image_path('aws_logo.svg'),
+ aws_tip_deploy_link: help_page_path('ci/cloud_deployment/index.md', anchor: 'deploy-your-application-to-the-aws-elastic-container-service-ecs'),
+ aws_tip_commands_link: help_page_path('ci/cloud_deployment/index.md', anchor: 'run-aws-commands-from-gitlab-cicd'),
+ aws_tip_learn_link: help_page_path('ci/cloud_deployment/index.md', anchor: 'aws'),
+ protected_environment_variables_link: help_page_path('ci/variables/README', anchor: 'protect-a-custom-variable'),
+ masked_environment_variables_link: help_page_path('ci/variables/README', anchor: 'mask-a-custom-variable'),
+} }
- if !@group && @project.group
.settings-header.border-top.prepend-top-20
diff --git a/app/views/clusters/clusters/_details.html.haml b/app/views/clusters/clusters/_details.html.haml
index fb0a1aaebc4..3079e024369 100644
--- a/app/views/clusters/clusters/_details.html.haml
+++ b/app/views/clusters/clusters/_details.html.haml
@@ -4,7 +4,7 @@
%section.settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4= s_('ClusterIntegration|Provider details')
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p= s_('ClusterIntegration|See and edit the details for your Kubernetes cluster')
.settings-content
diff --git a/app/views/clusters/clusters/_empty_state.html.haml b/app/views/clusters/clusters/_empty_state.html.haml
index 1798ba81075..676a8a8111a 100644
--- a/app/views/clusters/clusters/_empty_state.html.haml
+++ b/app/views/clusters/clusters/_empty_state.html.haml
@@ -11,4 +11,4 @@
- if clusterable.can_add_cluster?
.gl-text-center
- = link_to s_('ClusterIntegration|Integrate with a cluster certificate'), clusterable.new_path, class: 'btn btn-success'
+ = link_to s_('ClusterIntegration|Integrate with a cluster certificate'), clusterable.new_path, class: 'gl-button btn btn-success'
diff --git a/app/views/clusters/clusters/_provider_details_form.html.haml b/app/views/clusters/clusters/_provider_details_form.html.haml
index 16891c7fc21..7fc803e9579 100644
--- a/app/views/clusters/clusters/_provider_details_form.html.haml
+++ b/app/views/clusters/clusters/_provider_details_form.html.haml
@@ -55,4 +55,4 @@
= render('clusters/clusters/namespace', platform_field: platform_field, field: field)
.form-group
- = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
+ = field.submit s_('ClusterIntegration|Save changes'), class: 'gl-button btn btn-success'
diff --git a/app/views/clusters/clusters/aws/_new.html.haml b/app/views/clusters/clusters/aws/_new.html.haml
index b1a277faae9..4407b27df1e 100644
--- a/app/views/clusters/clusters/aws/_new.html.haml
+++ b/app/views/clusters/clusters/aws/_new.html.haml
@@ -14,4 +14,4 @@
'kubernetes-integration-help-path' => help_page_path('user/project/clusters/index'),
'account-and-external-ids-help-path' => help_page_path('user/project/clusters/add_remove_clusters.md', anchor: 'new-eks-cluster'),
'create-role-arn-help-path' => help_page_path('user/project/clusters/add_remove_clusters.md', anchor: 'new-eks-cluster'),
- 'external-link-icon' => icon('external-link') } }
+ 'external-link-icon' => sprite_icon('external-link') } }
diff --git a/app/views/clusters/clusters/gcp/_form.html.haml b/app/views/clusters/clusters/gcp/_form.html.haml
index ceb6e1d46b0..d1ea7fec49d 100644
--- a/app/views/clusters/clusters/gcp/_form.html.haml
+++ b/app/views/clusters/clusters/gcp/_form.html.haml
@@ -1,5 +1,5 @@
= javascript_include_tag 'https://apis.google.com/js/api.js'
-- external_link_icon = icon('external-link')
+- external_link_icon = sprite_icon('external-link')
- zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones'
- machine_type_link_url = 'https://cloud.google.com/compute/docs/machine-types'
- pricing_link_url = 'https://cloud.google.com/compute/pricing#machinetype'
@@ -86,4 +86,4 @@
.form-group.js-gke-cluster-creation-submit-container
= field.submit s_('ClusterIntegration|Create Kubernetes cluster'),
- class: 'js-gke-cluster-creation-submit btn btn-success', disabled: true
+ class: 'js-gke-cluster-creation-submit gl-button btn btn-success', disabled: true
diff --git a/app/views/clusters/clusters/user/_form.html.haml b/app/views/clusters/clusters/user/_form.html.haml
index a6097038b2e..e2779d1b683 100644
--- a/app/views/clusters/clusters/user/_form.html.haml
+++ b/app/views/clusters/clusters/user/_form.html.haml
@@ -60,4 +60,4 @@
= render('clusters/clusters/namespace', platform_field: platform_kubernetes_field)
.form-group
- = field.submit s_('ClusterIntegration|Add Kubernetes cluster'), class: 'btn btn-success', data: { qa_selector: 'add_kubernetes_cluster_button' }
+ = field.submit s_('ClusterIntegration|Add Kubernetes cluster'), class: 'gl-button btn btn-success', data: { qa_selector: 'add_kubernetes_cluster_button' }
diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml
index b2fadb77418..c24fe5c6307 100644
--- a/app/views/dashboard/_groups_head.html.haml
+++ b/app/views/dashboard/_groups_head.html.haml
@@ -3,7 +3,7 @@
- if current_user.can_create_group?
.page-title-controls
- = link_to _("New group"), new_group_path, class: "btn btn-success"
+ = link_to _("New group"), new_group_path, class: "gl-button btn btn-success"
.top-area
%ul.nav-links.mobile-separator.nav.nav-tabs
diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml
index fe91f9859f9..6c994f3b230 100644
--- a/app/views/dashboard/_projects_head.html.haml
+++ b/app/views/dashboard/_projects_head.html.haml
@@ -9,7 +9,7 @@
- if current_user.can_create_project?
.page-title-controls
- = link_to _("New project"), new_project_path, class: "btn btn-success"
+ = link_to _("New project"), new_project_path, class: "gl-button btn btn-success"
.top-area.scrolling-tabs-container.inner-page-scroll-tabs
.fade-left= sprite_icon('chevron-lg-left', size: 12)
diff --git a/app/views/dashboard/_snippets_head.html.haml b/app/views/dashboard/_snippets_head.html.haml
index d2fb4a3cd43..2640d483615 100644
--- a/app/views/dashboard/_snippets_head.html.haml
+++ b/app/views/dashboard/_snippets_head.html.haml
@@ -4,7 +4,7 @@
- if current_user && current_user.snippets.any? || @snippets.any?
.page-title-controls
- if can?(current_user, :create_snippet)
- = link_to _("New snippet"), new_snippet_path, class: "btn btn-success", title: _("New snippet")
+ = link_to _("New snippet"), new_snippet_path, class: "gl-button btn btn-success", title: _("New snippet")
.top-area
%ul.nav-links.nav.nav-tabs
diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml
index 9536ff940f5..afe4f1b84c2 100644
--- a/app/views/dashboard/groups/index.html.haml
+++ b/app/views/dashboard/groups/index.html.haml
@@ -6,6 +6,7 @@
= render 'dashboard/groups_head'
- if params[:filter].blank? && @groups.empty?
- = render 'shared/groups/empty_state'
+ .empty-state
+ = render 'shared/groups/empty_state'
- else
= render 'groups'
diff --git a/app/views/dashboard/todos/_todo.html.haml b/app/views/dashboard/todos/_todo.html.haml
index 6fb387ecca3..8e038baf14d 100644
--- a/app/views/dashboard/todos/_todo.html.haml
+++ b/app/views/dashboard/todos/_todo.html.haml
@@ -48,14 +48,14 @@
- if todo.pending?
.todo-actions
- = link_to dashboard_todo_path(todo), method: :delete, class: 'btn btn-loading d-flex align-items-center js-done-todo', data: { href: dashboard_todo_path(todo) } do
+ = link_to dashboard_todo_path(todo), method: :delete, class: 'gl-button btn btn-loading d-flex align-items-center js-done-todo', data: { href: dashboard_todo_path(todo) } do
Done
%span.spinner.ml-1
- = link_to restore_dashboard_todo_path(todo), method: :patch, class: 'btn btn-loading d-flex align-items-center js-undo-todo hidden', data: { href: restore_dashboard_todo_path(todo) } do
+ = link_to restore_dashboard_todo_path(todo), method: :patch, class: 'gl-button btn btn-loading d-flex align-items-center js-undo-todo hidden', data: { href: restore_dashboard_todo_path(todo) } do
Undo
%span.spinner.ml-1
- else
.todo-actions
- = link_to restore_dashboard_todo_path(todo), method: :patch, class: 'btn btn-loading d-flex align-items-center js-add-todo', data: { href: restore_dashboard_todo_path(todo) } do
+ = link_to restore_dashboard_todo_path(todo), method: :patch, class: 'gl-button btn btn-loading d-flex align-items-center js-add-todo', data: { href: restore_dashboard_todo_path(todo) } do
Add a to do
%span.spinner.ml-1
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index 56506370ee0..9a9fbfc1ee8 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -27,10 +27,10 @@
.nav-controls
- if @todos.any?(&:pending?)
.gl-mr-3
- = link_to destroy_all_dashboard_todos_path(todos_filter_params), class: 'btn btn-loading align-items-center js-todos-mark-all', method: :delete, data: { href: destroy_all_dashboard_todos_path(todos_filter_params) } do
+ = link_to destroy_all_dashboard_todos_path(todos_filter_params), class: 'gl-button btn btn-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 align-items-center js-todos-undo-all hidden', method: :patch , data: { href: bulk_restore_dashboard_todos_path(todos_filter_params) } do
+ = link_to bulk_restore_dashboard_todos_path, class: 'gl-button btn btn-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
@@ -114,7 +114,7 @@
.todos-empty
.todos-empty-hero.svg-content
= image_tag 'illustrations/todos_empty.svg'
- .todos-empty-content
+ .todos-empty-content.gl-mx-5
%h4
Your To-Do List shows what to work on next
%p
diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml
index f8aa3cf98dc..49112ed6cd5 100644
--- a/app/views/devise/confirmations/new.html.haml
+++ b/app/views/devise/confirmations/new.html.haml
@@ -8,7 +8,7 @@
= f.label :email
= f.email_field :email, class: "form-control", required: true, title: 'Please provide a valid email address.'
.clearfix
- = f.submit "Resend", class: 'btn btn-success'
+ = f.submit "Resend", class: 'gl-button btn btn-success'
.clearfix.prepend-top-20
= render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/mailer/user_admin_approval.html.haml b/app/views/devise/mailer/user_admin_approval.html.haml
new file mode 100644
index 00000000000..199a143ba63
--- /dev/null
+++ b/app/views/devise/mailer/user_admin_approval.html.haml
@@ -0,0 +1,8 @@
+= email_default_heading(say_hi(@resource))
+
+%p
+ = _('Your GitLab account request has been approved!')
+%p
+ = _('Your username is %{username}.') % { username: @resource.username }
+%p
+ = _('Your sign-in page is %{url}.').html_safe % { url: link_to(Gitlab.config.gitlab.url, Gitlab.config.gitlab.url) }
diff --git a/app/views/devise/mailer/user_admin_approval.text.erb b/app/views/devise/mailer/user_admin_approval.text.erb
new file mode 100644
index 00000000000..5242981e514
--- /dev/null
+++ b/app/views/devise/mailer/user_admin_approval.text.erb
@@ -0,0 +1,7 @@
+<%= say_hi(@resource) %>
+
+<%= _('Your GitLab account request has been approved!') %>
+
+<%= _('Your username is %{username}.' % { username: @resource.username }) %>
+
+<%= _('Your sign-in page is %{url}.' % { url: Gitlab.config.gitlab.url }) %>
diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml
index fee87c6324c..42e301d88ae 100644
--- a/app/views/devise/passwords/edit.html.haml
+++ b/app/views/devise/passwords/edit.html.haml
@@ -12,7 +12,7 @@
= f.label 'Confirm new password', for: "user_password_confirmation"
= f.password_field :password_confirmation, class: "form-control bottom", title: 'This field is required', data: { qa_selector: 'password_confirmation_field' }, required: true
.clearfix
- = f.submit "Change your password", class: "btn btn-primary", data: { qa_selector: 'change_password_button' }
+ = f.submit "Change your password", class: "gl-button btn btn-primary", data: { qa_selector: 'change_password_button' }
.clearfix.prepend-top-20
%p
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index 2f75203ac62..00429f1acbc 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -1,16 +1,13 @@
- page_title _("Sign up")
-- if experiment_enabled?(:signup_flow)
- .row
- .col-lg-7
- %h1.mb-3.font-weight-bold.text-6.mt-0
- = html_escape(_("Speed up your DevOps%{br_tag}with GitLab")) % { br_tag: '<br/>'.html_safe }
- %p.text-3
- = _("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= _('Register for GitLab')
- = render 'devise/shared/experimental_separate_sign_up_flow_box'
- = render 'devise/shared/sign_in_link'
-- else
- = render 'devise/shared/signup_box'
+- add_page_specific_style 'page_bundles/signup'
+- content_for :page_specific_javascripts do
+ = render "layouts/google_tag_manager_head"
+= render "layouts/google_tag_manager_body"
+
+.signup-page
+ = render 'devise/shared/signup_box',
+ url: registration_path(resource_name),
+ button_text: _('Register'),
+ show_omniauth_providers: omniauth_enabled? && button_based_providers_enabled?,
+ suggestion_path: nil
= render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml
index 8c0ca6d4345..a1a1a767847 100644
--- a/app/views/devise/sessions/_new_base.html.haml
+++ b/app/views/devise/sessions/_new_base.html.haml
@@ -20,4 +20,4 @@
= recaptcha_tags
.submit-container.move-submit-down
- = f.submit _('Sign in'), class: 'btn btn-success', data: { qa_selector: 'sign_in_button' }
+ = f.submit _('Sign in'), class: 'gl-button btn btn-success', data: { qa_selector: 'sign_in_button' }
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index c466d2ce936..cce0a3b926e 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -1,24 +1,25 @@
- page_title _("Sign in")
+- content_for :page_specific_javascripts do
+ = render "layouts/google_tag_manager_head"
+= render "layouts/google_tag_manager_body"
#signin-container
- if any_form_based_providers_enabled?
- = render 'devise/shared/tabs_ldap'
- - else
- - unless experiment_enabled?(:signup_flow)
- = render 'devise/shared/tabs_normal'
+ = render 'devise/shared/tabs_ldap', render_signup_link: false
.tab-content
- if password_authentication_enabled_for_web? || ldap_sign_in_enabled? || crowd_enabled?
= render 'devise/shared/signin_box'
- -# Signup only makes sense if you can also sign-in
- - if allow_signup?
- = render 'devise/shared/signup_box'
-
-# Show a message if none of the mechanisms above are enabled
- if !password_authentication_enabled_for_web? && !ldap_sign_in_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?)
%div
No authentication methods configured.
+ - if allow_signup?
+ %p.gl-mt-3
+ = _("Don't have an account yet?")
+ = link_to _("Register now"), new_registration_path(:user, invite_email: @invite_email), data: { qa_selector: 'register_link' }
+
- if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled?
.clearfix
= render 'devise/shared/omniauth_box'
diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml
index 8e05488c091..f5f76eb92b1 100644
--- a/app/views/devise/sessions/two_factor.html.haml
+++ b/app/views/devise/sessions/two_factor.html.haml
@@ -11,6 +11,6 @@
= f.text_field :otp_attempt, class: 'form-control', required: true, autofocus: true, autocomplete: 'off', title: 'This field is required.', data: { qa_selector: 'two_fa_code_field' }
%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' }
+ = f.submit "Verify code", class: "gl-button btn btn-success", data: { qa_selector: 'verify_code_button' }
- 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/_experimental_separate_sign_up_flow_box.html.haml b/app/views/devise/shared/_experimental_separate_sign_up_flow_box.html.haml
deleted file mode 100644
index 621bbb32a13..00000000000
--- a/app/views/devise/shared/_experimental_separate_sign_up_flow_box.html.haml
+++ /dev/null
@@ -1,39 +0,0 @@
-- max_first_name_length = max_last_name_length = 127
-- max_username_length = 255
-- min_username_length = 2
-.signup-box.p-3.mb-2
- .signup-body
- = form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user gl-show-field-errors", "aria-live" => "assertive" }) do |f|
- .devise-errors.mt-0
- = render "devise/shared/error_messages", resource: resource
- - if Feature.enabled?(:invisible_captcha)
- = invisible_captcha
- .name.form-row
- .col.form-group
- = f.label :first_name, _('First name'), for: 'new_user_first_name', class: 'label-bold'
- = f.text_field :first_name, class: 'form-control top js-block-emoji js-validate-length', :data => { :max_length => max_first_name_length, :max_length_message => _("First name is too long (maximum is %{max_length} characters).") % { max_length: max_first_name_length }, :qa_selector => 'new_user_firstname_field' }, required: true, title: _("This field is required.")
- .col.form-group
- = f.label :last_name, _('Last name'), for: 'new_user_last_name', class: 'label-bold'
- = f.text_field :last_name, class: "form-control top js-block-emoji js-validate-length", :data => { :max_length => max_last_name_length, :max_length_message => _("Last name is too long (maximum is %{max_length} characters).") % { max_length: max_last_name_length }, :qa_selector => 'new_user_lastname_field' }, required: true, title: _("This field is required.")
- .username.form-group
- = f.label :username, class: 'label-bold'
- = f.text_field :username, class: "form-control middle js-block-emoji js-validate-length js-validate-username", :data => { :min_length => min_username_length, :min_length_message => s_("SignUp|Username is too short (minimum is %{min_length} characters).") % { min_length: min_username_length }, :max_length => max_username_length, :max_length_message => _("Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.")
- %p.validation-error.gl-field-error-ignore.field-validation.mt-1.hide.cred= _('Username is already taken.')
- %p.validation-success.gl-field-error-ignore.field-validation.mt-1.hide.cgreen= _('Username is available.')
- %p.validation-pending.gl-field-error-ignore.field-validation.mt-1.hide= _('Checking username availability...')
- .form-group
- = f.label :email, class: 'label-bold'
- = f.email_field :email, class: "form-control middle", data: { qa_selector: 'new_user_email_field' }, required: true, title: _("Please provide a valid 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 }
- %p.gl-field-hint.text-secondary= _('Minimum length is %{minimum_password_length} characters') % { minimum_password_length: @minimum_password_length }
- = render_if_exists 'devise/shared/email_opted_in', f: f
- %div
- - if show_recaptcha_sign_up?
- = recaptcha_tags
- .submit-container.mt-3
- = f.submit _("Register"), class: "btn-register btn btn-block btn-success mb-0 p-2", data: { qa_selector: 'new_user_register_button' }
- = render 'devise/shared/terms_of_service_notice'
- - if omniauth_enabled? && button_based_providers_enabled?
- = render 'devise/shared/experimental_separate_sign_up_flow_omniauth_box'
diff --git a/app/views/devise/shared/_experimental_separate_sign_up_flow_omniauth_box.haml b/app/views/devise/shared/_experimental_separate_sign_up_flow_omniauth_box.haml
deleted file mode 100644
index d9143d90430..00000000000
--- a/app/views/devise/shared/_experimental_separate_sign_up_flow_omniauth_box.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-.omniauth-divider.d-flex.align-items-center.text-center
- = _("or")
-%label.label-bold.d-block
- = _("Create an account using:")
-- providers = enabled_button_based_providers
-.d-flex.justify-content-between.flex-wrap
- - providers.each do |provider|
- - has_icon = provider_has_icon?(provider)
- = link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn d-flex align-items-center omniauth-btn text-left oauth-login mb-2 p-2 #{qa_class_for_provider(provider)}", id: "oauth-login-#{provider}" do
- - if has_icon
- = provider_image_tag(provider)
- %span.ml-2
- = label_for_provider(provider)
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 6cf48f89876..67e6e510923 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -7,7 +7,7 @@
.d-flex.justify-content-between.flex-wrap
- providers.each do |provider|
- has_icon = provider_has_icon?(provider)
- = button_to omniauth_authorize_path(:user, provider), id: "oauth-login-#{provider}", class: "btn d-flex align-items-center omniauth-btn text-left oauth-login #{qa_class_for_provider(provider)}" do
+ = button_to omniauth_authorize_path(:user, provider), id: "oauth-login-#{provider}", class: "gl-button btn d-flex align-items-center omniauth-btn text-left oauth-login #{qa_class_for_provider(provider)}" do
- if has_icon
= provider_image_tag(provider)
%span
diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml
index d217b47527a..ff93449194a 100644
--- a/app/views/devise/shared/_signin_box.html.haml
+++ b/app/views/devise/shared/_signin_box.html.haml
@@ -22,8 +22,3 @@
.login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' }
.login-body
= render 'devise/sessions/new_base'
-
-- if experiment_enabled?(:signup_flow)
- %p.light.mt-2
- = _("Don't have an account yet?")
- = link_to _("Register now"), new_registration_path(:user)
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index f4ac9ad696b..0dc98001881 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -1,37 +1,37 @@
- max_first_name_length = max_last_name_length = 127
- max_username_length = 255
- min_username_length = 2
-#register-pane.tab-pane.login-box{ role: 'tabpanel' }
- .login-body
- = form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user gl-show-field-errors", "aria-live" => "assertive" }) do |f|
- .devise-errors
- = render "devise/shared/error_messages", resource: resource
- - if Feature.enabled?(:invisible_captcha)
- = invisible_captcha
- .name.form-row
- .col.form-group
- = f.label :first_name, _('First name'), for: 'new_user_first_name', class: 'label-bold'
- = f.text_field :first_name, class: 'form-control top js-block-emoji js-validate-length', :data => { :max_length => max_first_name_length, :max_length_message => _("First name is too long (maximum is %{max_length} characters).") % { max_length: max_first_name_length }, :qa_selector => 'new_user_first_name_field' }, required: true, title: _("This field is required.")
- .col.form-group
- = f.label :last_name, _('Last name'), for: 'new_user_last_name', class: 'label-bold'
- = f.text_field :last_name, class: "form-control top js-block-emoji js-validate-length", :data => { :max_length => max_last_name_length, :max_length_message => _("Last name is too long (maximum is %{max_length} characters).") % { max_length: max_last_name_length }, :qa_selector => 'new_user_last_name_field' }, required: true, title: _("This field is required.")
- .username.form-group
- = f.label :username, class: 'label-bold'
- = f.text_field :username, class: "form-control middle js-block-emoji js-validate-length js-validate-username", :data => { :min_length => min_username_length, :min_length_message => s_("SignUp|Username is too short (minimum is %{min_length} characters).") % { min_length: min_username_length }, :max_length => max_username_length, :max_length_message => s_("SignUp|Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.")
- %p.validation-error.gl-field-error-ignore.field-validation.hide= _('Username is already taken.')
- %p.validation-success.gl-field-error-ignore.field-validation.hide= _('Username is available.')
- %p.validation-pending.gl-field-error-ignore.field-validation.hide= _('Checking username availability...')
- .form-group
- = f.label :email, class: 'label-bold'
- = f.email_field :email, value: @invite_email, class: "form-control middle", data: { qa_selector: 'new_user_email_field' }, required: true, title: _("Please provide a valid email address.")
- .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 }
- %p.gl-field-hint.text-secondary= _('Minimum length is %{minimum_password_length} characters') % { minimum_password_length: @minimum_password_length }
- = render_if_exists 'devise/shared/email_opted_in', f: f
- %div
- - if show_recaptcha_sign_up?
- = recaptcha_tags
- .submit-container
- = f.submit _("Register"), class: "btn-register btn", data: { qa_selector: 'new_user_register_button' }
- = render 'devise/shared/terms_of_service_notice'
+.gl-mb-3.gl-p-4.gl-border-gray-100.gl-border-1.gl-border-solid.gl-rounded-base
+ = form_for(resource, as: "new_#{resource_name}", url: url, html: { class: 'new_user gl-show-field-errors', 'aria-live' => 'assertive' }) do |f|
+ .devise-errors
+ = render 'devise/shared/error_messages', resource: resource
+ - if Feature.enabled?(:invisible_captcha)
+ = invisible_captcha
+ .name.form-row
+ .col.form-group
+ = f.label :first_name, _('First name'), for: 'new_user_first_name', class: 'label-bold'
+ = f.text_field :first_name, class: 'form-control top js-block-emoji js-validate-length', :data => { :max_length => max_first_name_length, :max_length_message => s_('SignUp|First name is too long (maximum is %{max_length} characters).') % { max_length: max_first_name_length }, :qa_selector => 'new_user_first_name_field' }, required: true, title: _('This field is required.')
+ .col.form-group
+ = f.label :last_name, _('Last name'), for: 'new_user_last_name', class: 'label-bold'
+ = f.text_field :last_name, class: 'form-control top js-block-emoji js-validate-length', :data => { :max_length => max_last_name_length, :max_length_message => s_('SignUp|Last name is too long (maximum is %{max_length} characters).') % { max_length: max_last_name_length }, :qa_selector => 'new_user_last_name_field' }, required: true, title: _('This field is required.')
+ .username.form-group
+ = f.label :username, class: 'label-bold'
+ = f.text_field :username, class: 'form-control middle js-block-emoji js-validate-length js-validate-username', :data => { :api_path => suggestion_path, :min_length => min_username_length, :min_length_message => s_('SignUp|Username is too short (minimum is %{min_length} characters).') % { min_length: min_username_length }, :max_length => max_username_length, :max_length_message => s_('SignUp|Username is too long (maximum is %{max_length} characters).') % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _('Please create a username with only alphanumeric characters.')
+ %p.validation-error.gl-text-red-500.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is already taken.')
+ %p.validation-success.gl-text-green-600.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is available.')
+ %p.validation-pending.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Checking username availability...')
+ .form-group
+ = f.label :email, class: 'label-bold'
+ = f.email_field :email, value: @invite_email, class: 'form-control middle', data: { qa_selector: 'new_user_email_field' }, required: true, title: _('Please provide a valid email address.')
+ .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: s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
+ %p.gl-field-hint.text-secondary= s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
+ %div
+ - if show_recaptcha_sign_up?
+ = recaptcha_tags
+ .submit-container
+ = f.submit button_text, class: 'btn gl-button btn-success', data: { qa_selector: 'new_user_register_button' }
+ = render 'devise/shared/terms_of_service_notice'
+ - if show_omniauth_providers
+ = render 'devise/shared/signup_omniauth_providers'
diff --git a/app/views/devise/shared/_signup_omniauth_providers.haml b/app/views/devise/shared/_signup_omniauth_providers.haml
new file mode 100644
index 00000000000..68098f1865b
--- /dev/null
+++ b/app/views/devise/shared/_signup_omniauth_providers.haml
@@ -0,0 +1,13 @@
+.omniauth-divider.d-flex.align-items-center.text-center
+ = _("or")
+%label.label-bold.d-block
+ = _("Create an account using:")
+- providers = enabled_button_based_providers
+.d-flex.justify-content-between.flex-wrap
+ - providers.each do |provider|
+ - has_icon = provider_has_icon?(provider)
+ = link_to omniauth_authorize_path(:user, provider), method: :post, class: "gl-button btn d-flex align-items-center omniauth-btn text-left oauth-login mb-2 p-2 #{qa_class_for_provider(provider)}", id: "oauth-login-#{provider}" do
+ - if has_icon
+ = provider_image_tag(provider)
+ %span.ml-2
+ = label_for_provider(provider)
diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml
index acd41fb011a..27057d023b1 100644
--- a/app/views/devise/shared/_tabs_ldap.html.haml
+++ b/app/views/devise/shared/_tabs_ldap.html.haml
@@ -4,17 +4,17 @@
%ul.nav-links.new-session-tabs.nav-tabs.nav{ class: ('custom-provider-tabs' if any_form_based_providers_enabled?) }
- if crowd_enabled?
%li.nav-item
- = link_to "Crowd", "#crowd", class: "nav-link #{active_when(form_based_auth_provider_has_active_class?(:crowd))}", 'data-toggle' => 'tab'
+ = link_to "Crowd", "#crowd", class: "nav-link #{active_when(form_based_auth_provider_has_active_class?(:crowd))}", 'data-toggle' => 'tab', role: 'tab'
= render_if_exists "devise/shared/kerberos_tab"
- ldap_servers.each_with_index do |server, i|
%li.nav-item
- = link_to server['label'], "##{server['provider_name']}", class: "nav-link #{active_when(i == 0 && form_based_auth_provider_has_active_class?(:ldapmain))}", data: { toggle: 'tab', qa_selector: 'ldap_tab' }
+ = link_to server['label'], "##{server['provider_name']}", class: "nav-link #{active_when(i == 0 && form_based_auth_provider_has_active_class?(:ldapmain))}", data: { toggle: 'tab', qa_selector: 'ldap_tab' }, role: 'tab'
= render_if_exists 'devise/shared/tab_smartcard'
- if show_password_form
%li.nav-item
- = link_to _('Standard'), '#login-pane', class: 'nav-link', data: { toggle: 'tab', qa_selector: 'standard_tab' }
+ = link_to _('Standard'), '#login-pane', class: 'nav-link', data: { toggle: 'tab', qa_selector: 'standard_tab' }, role: 'tab'
- if render_signup_link && allow_signup?
%li.nav-item
- = link_to 'Register', '#register-pane', class: 'nav-link', data: { toggle: 'tab', qa_selector: 'register_tab' }
+ = link_to 'Register', '#register-pane', class: 'nav-link', data: { toggle: 'tab', qa_selector: 'register_tab' }, role: 'tab'
diff --git a/app/views/devise/unlocks/new.html.haml b/app/views/devise/unlocks/new.html.haml
index 1167f1718d6..96f4f07176e 100644
--- a/app/views/devise/unlocks/new.html.haml
+++ b/app/views/devise/unlocks/new.html.haml
@@ -8,7 +8,7 @@
= f.label :email
= f.email_field :email, class: 'form-control', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off', title: 'Please provide a valid email address.'
.clearfix
- = f.submit 'Resend unlock instructions', class: 'btn btn-success'
+ = f.submit 'Resend unlock instructions', class: 'gl-button btn btn-success'
.clearfix.prepend-top-20
= render 'devise/shared/sign_in_link'
diff --git a/app/views/discussions/_discussion.html.haml b/app/views/discussions/_discussion.html.haml
index 4a27284cbae..075eb99fc36 100644
--- a/app/views/discussions/_discussion.html.haml
+++ b/app/views/discussions/_discussion.html.haml
@@ -2,17 +2,15 @@
%li.note.note-discussion.timeline-entry.unstyled-comments
.timeline-entry-inner
.timeline-content
- .discussion.js-toggle-container{ data: { discussion_id: discussion.id } }
+ .discussion.js-toggle-container{ data: { discussion_id: discussion.id, is_expanded: expanded.to_s } }
.discussion-header
.timeline-icon
= link_to user_path(discussion.author) do
= image_tag avatar_icon_for_user(discussion.author), class: "avatar s40"
.discussion-actions
%button.note-action-button.discussion-toggle-button.js-toggle-button{ type: "button", class: ("js-toggle-lazy-diff" unless expanded) }
- - if expanded
- = icon("chevron-up")
- - else
- = icon("chevron-down")
+ = sprite_icon('chevron-up', css_class: "js-sidebar-collapse #{'hidden' unless expanded}")
+ = sprite_icon('chevron-down', css_class: "js-sidebar-expand #{'hidden' if expanded}")
= _('Toggle thread')
= link_to_member(@project, discussion.author, avatar: false)
diff --git a/app/views/doorkeeper/applications/_delete_form.html.haml b/app/views/doorkeeper/applications/_delete_form.html.haml
index 64b872b5610..3d6361a90ca 100644
--- a/app/views/doorkeeper/applications/_delete_form.html.haml
+++ b/app/views/doorkeeper/applications/_delete_form.html.haml
@@ -2,7 +2,7 @@
= form_tag oauth_application_path(application) do
%input{ :name => "_method", :type => "hidden", :value => "delete" }/
- if defined? small
- = button_tag type: "submit", class: "btn btn-transparent", data: { confirm: _("Are you sure?") } do
+ = button_tag type: "submit", class: "gl-button btn btn-transparent", data: { confirm: _("Are you sure?") } do
%span.sr-only
= _('Destroy')
= sprite_icon('remove')
diff --git a/app/views/doorkeeper/applications/_form.html.haml b/app/views/doorkeeper/applications/_form.html.haml
index f99db696fd6..fbae24410bb 100644
--- a/app/views/doorkeeper/applications/_form.html.haml
+++ b/app/views/doorkeeper/applications/_form.html.haml
@@ -23,4 +23,4 @@
= render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes
.gl-mt-3
- = f.submit _('Save application'), class: "btn btn-success"
+ = f.submit _('Save application'), class: "gl-button btn btn-success"
diff --git a/app/views/doorkeeper/applications/index.html.haml b/app/views/doorkeeper/applications/index.html.haml
index 6f781a635ba..2daba4586e1 100644
--- a/app/views/doorkeeper/applications/index.html.haml
+++ b/app/views/doorkeeper/applications/index.html.haml
@@ -41,7 +41,7 @@
%div= uri
%td= application.access_tokens.count
%td
- = link_to edit_oauth_application_path(application), class: "btn btn-transparent gl-mr-2" do
+ = link_to edit_oauth_application_path(application), class: "gl-button btn btn-transparent gl-mr-2" do
%span.sr-only
= _('Edit')
= sprite_icon('pencil')
diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml
index 280b5d90793..0a091aa7586 100644
--- a/app/views/doorkeeper/applications/show.html.haml
+++ b/app/views/doorkeeper/applications/show.html.haml
@@ -16,7 +16,7 @@
.input-group
%input.label.label-monospace.monospace{ id: "application_id", type: "text", autocomplete: 'off', value: @application.uid, readonly: true }
.input-group-append
- = clipboard_button(target: '#application_id', title: _("Copy ID"), class: "btn btn btn-default")
+ = clipboard_button(target: '#application_id', title: _("Copy ID"), class: "gl-button btn btn-default")
%tr
%td
= _('Secret')
@@ -25,7 +25,7 @@
.input-group
%input.label.label-monospace.monospace{ id: "secret", type: "text", autocomplete: 'off', value: @application.secret, readonly: true }
.input-group-append
- = clipboard_button(target: '#secret', title: _("Copy secret"), class: "btn btn btn-default")
+ = clipboard_button(target: '#secret', title: _("Copy secret"), class: "gl-button btn btn-default")
%tr
%td
= _('Callback URL')
@@ -43,5 +43,5 @@
= render "shared/tokens/scopes_list", token: @application
.form-actions
- = link_to _('Edit'), edit_oauth_application_path(@application), class: 'btn btn-primary wide float-left'
+ = link_to _('Edit'), edit_oauth_application_path(@application), class: 'gl-button btn btn-primary wide float-left'
= render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger gl-ml-3'
diff --git a/app/views/doorkeeper/authorizations/new.html.haml b/app/views/doorkeeper/authorizations/new.html.haml
index 62e66486a3e..bf17eb4fe3e 100644
--- a/app/views/doorkeeper/authorizations/new.html.haml
+++ b/app/views/doorkeeper/authorizations/new.html.haml
@@ -38,7 +38,7 @@
= hidden_field_tag :response_type, @pre_auth.response_type
= hidden_field_tag :scope, @pre_auth.scope
= hidden_field_tag :nonce, @pre_auth.nonce
- = submit_tag _("Deny"), class: "btn btn-danger"
+ = submit_tag _("Deny"), class: "gl-button btn btn-danger"
= form_tag oauth_authorization_path, method: :post, class: 'inline' do
= hidden_field_tag :client_id, @pre_auth.client.uid
= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
@@ -46,4 +46,4 @@
= hidden_field_tag :response_type, @pre_auth.response_type
= hidden_field_tag :scope, @pre_auth.scope
= hidden_field_tag :nonce, @pre_auth.nonce
- = submit_tag _("Authorize"), class: "btn btn-success gl-ml-3", data: { qa_selector: 'authorization_button' }
+ = submit_tag _("Authorize"), class: "gl-button btn btn-success gl-ml-3", data: { qa_selector: 'authorization_button' }
diff --git a/app/views/errors/access_denied.html.haml b/app/views/errors/access_denied.html.haml
index 1ed7b56db1d..ce921060cab 100644
--- a/app/views/errors/access_denied.html.haml
+++ b/app/views/errors/access_denied.html.haml
@@ -11,6 +11,6 @@
%p
= s_('403|Please contact your GitLab administrator to get permission.')
.action-container.js-go-back{ hidden: true }
- %button{ type: 'button', class: 'btn btn-success' }
+ %button{ type: 'button', class: 'gl-button btn btn-success' }
= s_('Go Back')
= render "errors/footer"
diff --git a/app/views/errors/not_found.html.haml b/app/views/errors/not_found.html.haml
index 13f07e2f5d5..291adbc0ae8 100644
--- a/app/views/errors/not_found.html.haml
+++ b/app/views/errors/not_found.html.haml
@@ -11,5 +11,5 @@
= form_tag search_path, method: :get, class: 'form-inline-flex' do |f|
.field
= search_field_tag :search, '', placeholder: _('Search for projects, issues, etc.'), class: 'form-control'
- = button_tag _('Search'), class: 'btn btn-sm btn-success', name: nil, type: 'submit'
+ = button_tag _('Search'), class: 'gl-button btn btn-sm btn-success', name: nil, type: 'submit'
= render 'errors/footer'
diff --git a/app/views/errors/omniauth_error.html.haml b/app/views/errors/omniauth_error.html.haml
index a2a4c75daad..0e9041d07ea 100644
--- a/app/views/errors/omniauth_error.html.haml
+++ b/app/views/errors/omniauth_error.html.haml
@@ -8,8 +8,8 @@
%p Try logging in using your username or email. If you have forgotten your password, try recovering it
- = link_to "Sign in", new_session_path(:user), class: 'btn primary'
- = link_to "Recover password", new_password_path(:user), class: 'btn secondary'
+ = link_to "Sign in", new_session_path(:user), class: 'gl-button btn primary'
+ = link_to "Recover password", new_password_path(:user), class: 'gl-button btn secondary'
%hr
%p.light If none of the options work, try contacting a GitLab administrator.
diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml
index 4e936025c74..2fa595503e5 100644
--- a/app/views/events/event/_note.html.haml
+++ b/app/views/events/event/_note.html.haml
@@ -25,5 +25,5 @@
= image_tag note.attachment.url, class: 'note-image-attach'
- else
= link_to note.attachment.url, target: '_blank', class: 'note-file-attach' do
- %i.fa.fa-paperclip
+ = sprite_icon("paperclip")
= note.attachment_identifier
diff --git a/app/views/explore/projects/_projects.html.haml b/app/views/explore/projects/_projects.html.haml
index d819c4ea554..4275f76c046 100644
--- a/app/views/explore/projects/_projects.html.haml
+++ b/app/views/explore/projects/_projects.html.haml
@@ -1,2 +1 @@
-- is_explore_page = defined?(explore_page) && explore_page
-= render 'shared/projects/list', projects: projects, user: current_user, explore_page: is_explore_page, pipeline_status: Feature.enabled?(:dashboard_pipeline_status, default_enabled: true)
+= render 'shared/projects/list', projects: projects, user: current_user, explore_page: true, pipeline_status: Feature.enabled?(:dashboard_pipeline_status, default_enabled: true)
diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml
index 341ad681c7c..44456b6c015 100644
--- a/app/views/explore/projects/index.html.haml
+++ b/app/views/explore/projects/index.html.haml
@@ -1,6 +1,7 @@
- @hide_top_links = true
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
+- page_canonical_link explore_projects_url
= render_dashboard_gold_trial(current_user)
diff --git a/app/views/explore/projects/page_out_of_bounds.html.haml b/app/views/explore/projects/page_out_of_bounds.html.haml
index 57114dd0752..0ee77ffd7d7 100644
--- a/app/views/explore/projects/page_out_of_bounds.html.haml
+++ b/app/views/explore/projects/page_out_of_bounds.html.haml
@@ -18,4 +18,4 @@
%h5= _("Maximum page reached")
%p= _("Sorry, you have exceeded the maximum browsable page number. Please use the API to explore further.")
- = link_to _("Back to page %{number}") % { number: @max_page_number }, request.params.merge(page: @max_page_number), class: 'btn btn-inverted'
+ = link_to _("Back to page %{number}") % { number: @max_page_number }, request.params.merge(page: @max_page_number), class: 'gl-button btn btn-inverted'
diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml
index 153c90e534e..ed508fa2506 100644
--- a/app/views/explore/projects/trending.html.haml
+++ b/app/views/explore/projects/trending.html.haml
@@ -10,4 +10,4 @@
= render 'explore/head'
= render 'explore/projects/nav' unless Feature.enabled?(:project_list_filter_bar) && current_user
-= render 'projects', projects: @projects, explore_page: true
+= render 'projects', projects: @projects
diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml
index 97e48cdec8c..ee08829d990 100644
--- a/app/views/groups/_home_panel.html.haml
+++ b/app/views/groups/_home_panel.html.haml
@@ -20,37 +20,16 @@
%span.access-request-links.gl-ml-3
= render 'shared/members/access_request_links', source: @group
- .home-panel-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end
+ .home-panel-buttons.col-md-12.col-lg-6
- if current_user
- .group-buttons
- = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn', emails_disabled: emails_disabled
- - new_project_label = _("New project")
- - new_subgroup_label = _("New subgroup")
- - if can_create_projects and can_create_subgroups
- .btn-group.new-project-subgroup.droplab-dropdown.home-panel-action-button.gl-mt-3.js-new-project-subgroup.qa-new-project-or-subgroup-dropdown{ data: { project_path: new_project_path(namespace_id: @group.id), subgroup_path: new_group_path(parent_id: @group.id) } }
- %input.btn.btn-success.dropdown-primary.js-new-group-child.qa-new-in-group-button{ type: "button", value: new_project_label, data: { action: "new-project" } }
- %button.btn.btn-success.dropdown-toggle.js-dropdown-toggle.qa-new-project-or-subgroup-dropdown-toggle{ type: "button", data: { "dropdown-trigger" => "#new-project-or-subgroup-dropdown", 'display' => 'static' } }
- = sprite_icon("chevron-down", css_class: "icon dropdown-btn-icon")
- %ul#new-project-or-subgroup-dropdown.dropdown-menu.dropdown-menu-right{ data: { dropdown: true } }
- %li.droplab-item-selected.qa-new-project-option{ role: "button", data: { value: "new-project", text: new_project_label } }
- .menu-item
- .icon-container
- = icon("check", class: "list-item-checkmark")
- .description
- %strong= new_project_label
- %span= s_("GroupsTree|Create a project in this group.")
- %li.divider.droplap-item-ignore
- %li.qa-new-subgroup-option{ role: "button", data: { value: "new-subgroup", text: new_subgroup_label } }
- .menu-item
- .icon-container
- = icon("check", class: "list-item-checkmark")
- .description
- %strong= new_subgroup_label
- %span= s_("GroupsTree|Create a subgroup in this group.")
- - elsif can_create_projects
- = link_to new_project_label, new_project_path(namespace_id: @group.id), class: "btn btn-success gl-mt-3"
- - elsif can_create_subgroups
- = link_to new_subgroup_label, new_group_path(parent_id: @group.id), class: "btn btn-success gl-mt-3"
+ .gl-display-flex.gl-flex-wrap.gl-lg-justify-content-end.gl-mx-n2{ data: { testid: 'group-buttons' } }
+ = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn gl-button gl-sm-w-auto gl-w-full', dropdown_container_class: 'gl-mr-0 gl-px-2 gl-sm-w-auto gl-w-full', emails_disabled: emails_disabled
+ - if can_create_subgroups
+ .gl-px-2.gl-sm-w-auto.gl-w-full
+ = link_to _("New subgroup"), new_group_path(parent_id: @group.id), class: "btn btn-success btn-md gl-button btn-success-secondary gl-mt-3 gl-sm-w-auto gl-w-full", data: { qa_selector: 'new_subgroup_button' }
+ - if can_create_projects
+ .gl-px-2.gl-sm-w-auto.gl-w-full
+ = link_to _("New project"), new_project_path(namespace_id: @group.id), class: "btn btn-success btn-md gl-button gl-mt-3 gl-sm-w-auto gl-w-full", data: { qa_selector: 'new_project_button' }
- if @group.description.present?
.group-home-desc.mt-1
diff --git a/app/views/groups/_invite_members_modal.html.haml b/app/views/groups/_invite_members_modal.html.haml
index 51f41d58029..3aae81cef8d 100644
--- a/app/views/groups/_invite_members_modal.html.haml
+++ b/app/views/groups/_invite_members_modal.html.haml
@@ -1,6 +1,7 @@
- if invite_members_allowed?(group)
- .js-invite-members-modal{ data: { group_id: group.id,
- group_name: group.name,
+ .js-invite-members-modal{ data: { id: group.id,
+ name: group.name,
+ is_project: false,
access_levels: GroupMember.access_level_roles.to_json,
default_access_level: Gitlab::Access::GUEST,
help_link: help_page_url('user/permissions') } }
diff --git a/app/views/groups/_invite_members_side_nav_link.html.haml b/app/views/groups/_invite_members_side_nav_link.html.haml
index 1c90eaee992..4f1c06d9fe3 100644
--- a/app/views/groups/_invite_members_side_nav_link.html.haml
+++ b/app/views/groups/_invite_members_side_nav_link.html.haml
@@ -1,3 +1,3 @@
- if invite_members_allowed?(group) && body_data_page == 'groups:show'
%li
- .js-invite-members-trigger{ data: { icon: 'plus', display_text: 'Invite team members' } }
+ .js-invite-members-trigger{ data: { icon: 'plus', display_text: _('Invite team members') } }
diff --git a/app/views/groups/dependency_proxies/_url.html.haml b/app/views/groups/dependency_proxies/_url.html.haml
new file mode 100644
index 00000000000..9242954b684
--- /dev/null
+++ b/app/views/groups/dependency_proxies/_url.html.haml
@@ -0,0 +1,12 @@
+- proxy_url = "#{group_url(@group)}/dependency_proxy/containers"
+
+%h5.prepend-top-20= _('Dependency proxy URL')
+
+.row
+ .col-lg-8.col-md-12.input-group
+ = text_field_tag :url, "#{proxy_url}", class: 'js-dependency-proxy-url form-control', readonly: true
+ = clipboard_button(text: "#{proxy_url}", title: _("Copy %{proxy_url}") % { proxy_url: proxy_url })
+
+.row
+ .col-12.help-block.gl-mt-3
+ = _('Contains %{count} blobs of images (%{size})') % { count: @blobs_count, size: number_to_human_size(@blobs_total_size) }
diff --git a/app/views/groups/dependency_proxies/show.html.haml b/app/views/groups/dependency_proxies/show.html.haml
new file mode 100644
index 00000000000..ff1312eb763
--- /dev/null
+++ b/app/views/groups/dependency_proxies/show.html.haml
@@ -0,0 +1,28 @@
+- page_title _("Dependency Proxy")
+
+.settings-header
+ %h4= _('Dependency proxy')
+
+ %p
+ - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('user/packages/dependency_proxy/index') }
+ = _('Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+
+- if @group.public?
+ - if can?(current_user, :admin_dependency_proxy, @group)
+ = form_for(@dependency_proxy, method: :put, url: group_dependency_proxy_path(@group)) do |f|
+ .form-group
+ %h5.prepend-top-20= _('Enable proxy')
+ .js-dependency-proxy-toggle-area
+ = render "shared/buttons/project_feature_toggle", is_checked: @dependency_proxy.enabled?, label: s_("DependencyProxy|Toggle Dependency Proxy") do
+ = f.hidden_field :enabled, { class: 'js-project-feature-toggle-input'}
+
+ - if @dependency_proxy.enabled
+ = render 'groups/dependency_proxies/url'
+
+ - else
+ - if @dependency_proxy.enabled
+ = render 'groups/dependency_proxies/url'
+- else
+ .gl-alert.gl-alert-info
+ = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ = _('Dependency proxy feature is limited to public groups for now.')
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index d999f20ef91..2a87b42ef13 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -3,7 +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)
+- vue_members_list_enabled = Feature.enabled?(:vue_group_members_list, @group, default_enabled: true)
+- current_user_is_group_owner = @group && @group.has_owner?(current_user)
- form_item_label_css_class = 'label-bold gl-mr-2 gl-mb-0 gl-py-2 align-self-md-center'
@@ -69,9 +70,15 @@
= render 'shared/members/sort_dropdown'
- if vue_members_list_enabled
.js-group-members-list{ data: group_members_list_data_attributes(@group, @members) }
+ .loading
+ .spinner.spinner-md
- else
%ul.content-list.members-list{ data: { qa_selector: 'members_list' } }
- = render partial: 'shared/members/member', collection: @members, as: :member
+ = render partial: 'shared/members/member',
+ collection: @members, as: :member,
+ locals: { membership_source: @group,
+ group: @group,
+ current_user_is_group_owner: current_user_is_group_owner }
= paginate @members, theme: 'gitlab', params: { invited_members_page: nil, search_invited: nil }
- if @group.shared_with_group_links.any?
#tab-groups.tab-pane
@@ -81,6 +88,8 @@
= html_escape(_('Groups with access to %{strong_start}%{group_name}%{strong_end}')) % { group_name: @group.name, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
- if vue_members_list_enabled
.js-group-linked-list{ data: linked_groups_list_data_attributes(@group) }
+ .loading
+ .spinner.spinner-md
- else
%ul.content-list.members-list{ data: { qa_selector: 'groups_list' } }
- @group.shared_with_group_links.each do |group_link|
@@ -95,9 +104,15 @@
= render 'shared/members/search_field', name: 'search_invited'
- if vue_members_list_enabled
.js-group-invited-members-list{ data: group_members_list_data_attributes(@group, @invited_members) }
+ .loading
+ .spinner.spinner-md
- else
%ul.content-list.members-list
- = render partial: 'shared/members/member', collection: @invited_members, as: :member
+ = render partial: 'shared/members/member',
+ collection: @invited_members, as: :member,
+ locals: { membership_source: @group,
+ group: @group,
+ current_user_is_group_owner: current_user_is_group_owner }
= paginate @invited_members, param_name: 'invited_members_page', theme: 'gitlab', params: { page: nil }
- if show_access_requests
#tab-access-requests.tab-pane
@@ -107,6 +122,12 @@
= html_escape(_('Users requesting access to %{strong_start}%{group_name}%{strong_end}')) % { group_name: @group.name, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
- if vue_members_list_enabled
.js-group-access-requests-list{ data: group_members_list_data_attributes(@group, @requesters) }
+ .loading
+ .spinner.spinner-md
- else
%ul.content-list.members-list
- = render partial: 'shared/members/member', collection: @requesters, as: :member
+ = render partial: 'shared/members/member',
+ collection: @requesters, as: :member,
+ locals: { membership_source: @group,
+ group: @group,
+ current_user_is_group_owner: current_user_is_group_owner }
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index 33a9f423da6..ef7e3efdc68 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -30,6 +30,7 @@
'can-bulk-edit': @can_bulk_update.to_json,
'empty-state-meta': { svg_path: image_path('illustrations/issues.svg') },
'sort-key': @sort,
- type: 'issues' } }
+ type: 'issues',
+ 'scoped-labels-available': scoped_labels_available?(@group).to_json } }
- else
= render 'shared/issues'
diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml
index debbe95d2aa..804d2da2c4b 100644
--- a/app/views/groups/labels/index.html.haml
+++ b/app/views/groups/labels/index.html.haml
@@ -5,7 +5,7 @@
- labels_or_filters = @labels.exists? || search.present? || subscribed.present?
- if labels_or_filters
- #promote-label-modal
+ #js-promote-label-modal
= render 'shared/labels/nav', labels_or_filters: labels_or_filters, can_admin_label: can_admin_label
.labels-container.gl-mt-2
diff --git a/app/views/groups/milestones/_form.html.haml b/app/views/groups/milestones/_form.html.haml
index df82b264f9a..ffb0ade4f73 100644
--- a/app/views/groups/milestones/_form.html.haml
+++ b/app/views/groups/milestones/_form.html.haml
@@ -19,8 +19,8 @@
.form-actions
- if @milestone.new_record?
- = f.submit 'Create milestone', class: "btn-success btn", data: { qa_selector: "create_milestone_button" }
- = link_to "Cancel", group_milestones_path(@group), class: "btn btn-cancel"
+ = f.submit 'Create milestone', class: "btn-success gl-button btn", data: { qa_selector: "create_milestone_button" }
+ = link_to "Cancel", group_milestones_path(@group), class: "btn gl-button btn-cancel"
- else
- = f.submit 'Update milestone', class: "btn-success btn"
- = link_to "Cancel", group_milestone_path(@group, @milestone), class: "btn btn-cancel"
+ = f.submit 'Update milestone', class: "btn-success gl-button btn"
+ = link_to "Cancel", group_milestone_path(@group, @milestone), class: "btn gl-button btn-cancel"
diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml
index d20fa938a68..c93b24d14f0 100644
--- a/app/views/groups/milestones/index.html.haml
+++ b/app/views/groups/milestones/index.html.haml
@@ -8,7 +8,7 @@
= render 'shared/milestones/search_form'
= render 'shared/milestones_sort_dropdown'
- if can?(current_user, :admin_milestone, @group)
- = link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-success", data: { qa_selector: "new_group_milestone_link" }
+ = link_to "New milestone", new_group_milestone_path(@group), class: "btn gl-button btn-success", data: { qa_selector: "new_group_milestone_link" }
.milestones
%ul.content-list
diff --git a/app/views/groups/runners/_group_runners.html.haml b/app/views/groups/runners/_group_runners.html.haml
index 554240b7aef..087c38c7b86 100644
--- a/app/views/groups/runners/_group_runners.html.haml
+++ b/app/views/groups/runners/_group_runners.html.haml
@@ -17,4 +17,6 @@
= render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: @group.runners_token,
type: 'group',
- reset_token_url: reset_registration_token_group_settings_ci_cd_path }
+ reset_token_url: reset_registration_token_group_settings_ci_cd_path,
+ project_path: '',
+ group_path: @group.path }
diff --git a/app/views/groups/settings/repository/_initial_branch_name.html.haml b/app/views/groups/settings/repository/_initial_branch_name.html.haml
new file mode 100644
index 00000000000..3ef8dccae08
--- /dev/null
+++ b/app/views/groups/settings/repository/_initial_branch_name.html.haml
@@ -0,0 +1,22 @@
+%section.settings.as-default-branch-name.no-animate#js-default-branch-name{ class: ('expanded' if expanded_by_default?) }
+ .settings-header
+ %h4
+ = _('Default initial branch name')
+ %button.gl-button.js-settings-toggle{ type: 'button' }
+ = expanded_by_default? ? _('Collapse') : _('Expand')
+ %p
+ = _('Set the default name of the initial branch when creating new repositories through the user interface.')
+ .settings-content
+ = form_for @group, url: group_path(@group, anchor: 'js-default-branch-name'), html: { class: 'fieldset-form' } do |f|
+ = form_errors(@group)
+ - fallback_branch_name = '<code>master</code>'
+
+ %fieldset
+ .form-group
+ = f.label :default_branch_name, _('Default initial branch name'), class: 'label-light'
+ = f.text_field :default_branch_name, value: group.namespace_settings&.default_branch_name, placeholder: 'master', class: 'form-control'
+ %span.form-text.text-muted
+ = (_("Changes affect new repositories only. If not specified, either the configured application-wide default or Git's default name %{branch_name_default} will be used.") % { branch_name_default: fallback_branch_name }).html_safe
+
+ = f.hidden_field :redirect_target, value: "repository_settings"
+ = f.submit _('Save changes'), class: 'gl-button btn-success'
diff --git a/app/views/groups/settings/repository/show.html.haml b/app/views/groups/settings/repository/show.html.haml
index ff0c9de4fef..a5819320405 100644
--- a/app/views/groups/settings/repository/show.html.haml
+++ b/app/views/groups/settings/repository/show.html.haml
@@ -4,3 +4,4 @@
- deploy_token_description = s_('DeployTokens|Group deploy tokens allow access to the packages, repositories, and registry images within the group.')
= render "shared/deploy_tokens/index", group_or_project: @group, description: deploy_token_description
+= render "initial_branch_name", group: @group
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index fa560942c5d..9d5ec5008dc 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -1,7 +1,9 @@
- breadcrumb_title _("Details")
-- page_title _("Groups")
- @content_class = "limit-container-width" unless fluid_layout
+- if show_thanks_for_purchase_banner?
+ = render_if_exists 'shared/thanks_for_purchase_banner', plan_title: plan_title, quantity: params[:purchased_quantity].to_i
+
- 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}" }
diff --git a/app/views/groups/sidebar/_packages.html.haml b/app/views/groups/sidebar/_packages.html.haml
index 54510d5df0c..7e0ee032aeb 100644
--- a/app/views/groups/sidebar/_packages.html.haml
+++ b/app/views/groups/sidebar/_packages.html.haml
@@ -1,7 +1,7 @@
- packages_link = group_packages_list_nav? ? group_packages_path(@group) : group_container_registries_path(@group)
- if group_packages_nav?
- = nav_link(controller: ['groups/packages', 'groups/registry/repositories']) do
+ = nav_link(controller: ['groups/packages', 'groups/registry/repositories', 'groups/dependency_proxies']) do
= link_to packages_link, title: _('Packages') do
.nav-icon-container
= sprite_icon('package')
@@ -21,3 +21,7 @@
= nav_link(controller: 'groups/registry/repositories') do
= link_to group_container_registries_path(@group), title: _('Container Registry') do
%span= _('Container Registry')
+ - if group_dependency_proxy_nav?
+ = nav_link(controller: 'groups/dependency_proxies') do
+ = link_to group_dependency_proxy_path(@group), title: _('Dependency Proxy') do
+ %span= _('Dependency Proxy')
diff --git a/app/views/ide/_show.html.haml b/app/views/ide/_show.html.haml
index 79cba2a54b0..70ac532e69f 100644
--- a/app/views/ide/_show.html.haml
+++ b/app/views/ide/_show.html.haml
@@ -1,6 +1,7 @@
- @body_class = 'ide-layout'
- page_title _('IDE')
+- add_page_specific_style 'page_bundles/build'
- add_page_specific_style 'page_bundles/ide'
#ide.ide-loading{ data: ide_data }
diff --git a/app/views/import/_project_status.html.haml b/app/views/import/_project_status.html.haml
deleted file mode 100644
index b968db58d38..00000000000
--- a/app/views/import/_project_status.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-- case project.import_status
-- when 'finished'
- = icon('check')
- = _('Done')
-- when 'started'
- = loading_icon
- = _('Started')
-- when 'failed'
- = _('Failed')
-- else
- = project.human_import_status_name
diff --git a/app/views/import/google_code/status.html.haml b/app/views/import/google_code/status.html.haml
index 72112c128cb..0004f0de69f 100644
--- a/app/views/import/google_code/status.html.haml
+++ b/app/views/import/google_code/status.html.haml
@@ -43,7 +43,7 @@
- case project.import_status
- when 'finished'
%span
- %i.fa.fa-check
+ = sprite_icon('check')
= _("done")
- when 'started'
= loading_icon
diff --git a/app/views/import/shared/_new_project_form.html.haml b/app/views/import/shared/_new_project_form.html.haml
index a558b21b461..b053d14a851 100644
--- a/app/views/import/shared/_new_project_form.html.haml
+++ b/app/views/import/shared/_new_project_form.html.haml
@@ -10,7 +10,7 @@
.input-group-prepend.flex-shrink-0.has-tooltip{ title: root_url }
.input-group-text
= root_url
- = select_tag :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), class: 'select2 js-select-namespace block-truncated', tabindex: 1
+ = select_tag :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), class: 'select2 js-select-namespace block-truncated'
- else
.input-group-prepend.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' }
.input-group-text.border-0
@@ -18,4 +18,4 @@
= hidden_field_tag :namespace_id, current_user.namespace_id
.form-group.col-12.col-sm-6.project-path
= label_tag :path, _('Project slug'), class: 'label-bold'
- = text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, required: true
+ = text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control", required: true
diff --git a/app/views/invites/show.html.haml b/app/views/invites/show.html.haml
index 37143799132..1492fea7fb2 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, new_user_invite: params[:new_user_invite]), method: :post, class: "btn gl-button btn-success"
+ = link_to _("Accept invitation"), accept_invite_url(@token), method: :post, class: "btn gl-button btn-success"
= link_to _("Decline"), decline_invite_url(@token), method: :post, class: "btn gl-button 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
index 655c413f2a6..355ffabd7ec 100644
--- a/app/views/jira_connect/subscriptions/index.html.haml
+++ b/app/views/jira_connect/subscriptions/index.html.haml
@@ -21,6 +21,8 @@
.gl-mt-5
%p Note: this integration only works with accounts on GitLab.com (SaaS).
- else
+ .js-jira-connect-app
+
%form#add-subscription-form.subscription-form{ action: jira_connect_subscriptions_path }
.ak-field-group
%label
@@ -50,12 +52,15 @@
%p.browser-limitations-notice
%strong Browser limitations:
- Adding a namespace currently works only in browsers that allow cross site cookies. Please make sure to use
+ Adding a namespace currently works only in browsers that allow cross‑site cookies. Please make sure to use
%a{ href: 'https://www.mozilla.org/en-US/firefox/', target: '_blank', rel: 'noopener noreferrer' } Firefox
or
%a{ href: 'https://www.google.com/chrome/index.html', target: '_blank', rel: 'noopener noreferrer' } Google Chrome
- or enable cross-site cookies in your browser when adding a namespace.
+ or enable cross‑site cookies in your browser when adding a namespace.
%a{ href: 'https://gitlab.com/gitlab-org/gitlab/-/issues/263509', target: '_blank', rel: 'noopener noreferrer' } Learn more
+= webpack_bundle_tag 'performance_bar' if performance_bar_enabled?
+= webpack_bundle_tag 'jira_connect_app'
+
= page_specific_javascript_tag('jira_connect.js')
- add_page_specific_style 'page_bundles/jira_connect'
diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml
index a0b57f8dd52..35fefe40d39 100644
--- a/app/views/layouts/_flash.html.haml
+++ b/app/views/layouts/_flash.html.haml
@@ -1,6 +1,6 @@
-# We currently only support `alert`, `notice`, `success`, 'toast'
- icons = {'alert' => 'error', 'notice' => 'information-o', 'success' => 'check-circle'};
-.flash-container.flash-container-page.sticky
+.flash-container.flash-container-page.sticky{ data: { qa_selector: 'flash_container' } }
- flash.each do |key, value|
- if key == 'toast' && value
.js-toast-message{ data: { message: value } }
diff --git a/app/views/layouts/_google_tag_manager_body.html.haml b/app/views/layouts/_google_tag_manager_body.html.haml
new file mode 100644
index 00000000000..d62e52dc91b
--- /dev/null
+++ b/app/views/layouts/_google_tag_manager_body.html.haml
@@ -0,0 +1,4 @@
+- return unless google_tag_manager_enabled?
+
+<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=#{extra_config.google_tag_manager_id}"
+height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
diff --git a/app/views/layouts/_google_tag_manager_head.html.haml b/app/views/layouts/_google_tag_manager_head.html.haml
new file mode 100644
index 00000000000..ab03f1e7670
--- /dev/null
+++ b/app/views/layouts/_google_tag_manager_head.html.haml
@@ -0,0 +1,8 @@
+- if google_tag_manager_enabled?
+ = javascript_tag nonce: true do
+ :plain
+ (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
+ new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
+ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
+ 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
+ })(window,document,'script','dataLayer','#{extra_config.google_tag_manager_id}');
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index 9d0c3ad5787..1d12b30c58c 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -1,17 +1,4 @@
- page_description brand_title unless page_description
-
--# 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
--# https://gitlab.com/gitlab-org/growth/engineering/issues/64
-- if experiment_enabled?(:signup_flow) && current_path?("sessions#new")
- = javascript_tag nonce: true do
- :plain
- if (window.location.hash === '#register-pane') {
- window.location.replace("/users/sign_up")
- }
-
- site_name = "GitLab"
%head{ prefix: "og: http://ogp.me/ns#" }
%meta{ charset: "utf-8" }
diff --git a/app/views/layouts/_mailer.html.haml b/app/views/layouts/_mailer.html.haml
index 24b8138078d..74d05be7f95 100644
--- a/app/views/layouts/_mailer.html.haml
+++ b/app/views/layouts/_mailer.html.haml
@@ -34,13 +34,7 @@
= render_if_exists 'layouts/mailer/additional_text'
- %tr.footer
- %td
- %img{ alt: "GitLab", height: "33", width: "90", src: image_url('mailers/gitlab_footer_logo.gif') }
- %div
- - manage_notifications_link = link_to(_("Manage all notifications"), profile_notifications_url, class: 'mng-notif-link')
- - help_link = link_to(_("Help"), help_url, class: 'help-link')
- = _("You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}").html_safe % { host: Gitlab.config.gitlab.host, manage_notifications_link: manage_notifications_link, help_link: help_link }
+ = yield :footer
= yield :additional_footer
%tr
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 9b925369660..f6fc49393d8 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -4,12 +4,13 @@
.content-wrapper{ class: "#{@content_wrapper_class}" }
.mobile-overlay
= yield :group_invite_members_banner
- .alert-wrapper
+ .alert-wrapper.gl-force-block-formatting-context
= render 'shared/outdated_browser'
= render_if_exists "layouts/header/licensed_user_count_threshold"
= render_if_exists "layouts/header/token_expiry_notification"
= render "layouts/broadcast"
= render "layouts/header/read_only_banner"
+ = render "layouts/header/registration_enabled_callout"
= render "layouts/nav/classification_level_banner"
= yield :flash_message
= render "shared/ping_consent"
@@ -20,6 +21,6 @@
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
- .content{ id: "content-body" }
+ .content{ id: "content-body", **page_itemtype }
= render "layouts/flash", extra_flash_class: 'limit-container-width'
= yield
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
index 0c6932e59a9..c902c687378 100644
--- a/app/views/layouts/_search.html.haml
+++ b/app/views/layouts/_search.html.haml
@@ -6,14 +6,13 @@
= search_field_tag 'search', nil, placeholder: _('Search or jump to…'),
class: 'search-input dropdown-menu-toggle no-outline js-search-dashboard-options',
spellcheck: false,
- tabindex: '1',
autocomplete: 'off',
data: { issues_path: issues_dashboard_path,
mr_path: merge_requests_dashboard_path,
qa_selector: 'search_term_field' },
aria: { label: _('Search or jump to…') }
%button.hidden.js-dropdown-search-toggle{ type: 'button', data: { toggle: 'dropdown' } }
- .dropdown-menu.dropdown-select.js-dashboard-search-options
+ .dropdown-menu.dropdown-select{ data: { testid: 'dashboard-search-options' } }
= dropdown_content do
%ul
%li.dropdown-menu-empty-item
diff --git a/app/views/layouts/_startup_js.html.haml b/app/views/layouts/_startup_js.html.haml
index f312e00c394..9c488e4f40d 100644
--- a/app/views/layouts/_startup_js.html.haml
+++ b/app/views/layouts/_startup_js.html.haml
@@ -25,7 +25,7 @@
};
gl.startup_graphql_calls = gl.startup_graphql_calls.map(call => ({
- operationName: call.query.match(/^query (.+)\(/)[1],
+ ...call,
fetchCall: fetch(url, {
...opts,
credentials: 'same-origin',
diff --git a/app/views/layouts/devise_experimental_onboarding_issues.html.haml b/app/views/layouts/devise_experimental_onboarding_issues.html.haml
index ec9867f9e1f..f768fba84ca 100644
--- a/app/views/layouts/devise_experimental_onboarding_issues.html.haml
+++ b/app/views/layouts/devise_experimental_onboarding_issues.html.haml
@@ -1,6 +1,6 @@
!!! 5
%html.devise-layout-html.navless{ class: system_message_class }
- - add_page_specific_style 'page_bundles/experimental_separate_sign_up'
+ - add_page_specific_style 'page_bundles/signup'
= render "layouts/head"
%body.ui-indigo.signup-page{ class: "#{client_class_list}", data: { page: body_data_page, qa_selector: 'signup_page' } }
= render "layouts/header/logo_with_title"
diff --git a/app/views/layouts/devise_experimental_separate_sign_up_flow.html.haml b/app/views/layouts/devise_experimental_separate_sign_up_flow.html.haml
deleted file mode 100644
index 6be62645768..00000000000
--- a/app/views/layouts/devise_experimental_separate_sign_up_flow.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-!!! 5
-%html.devise-layout-html.navless{ class: system_message_class }
- - add_page_specific_style 'page_bundles/experimental_separate_sign_up'
- = render "layouts/head"
- %body.ui-indigo.signup-page{ class: "#{client_class_list}", data: { page: body_data_page, qa_selector: 'signup_page' } }
- = render "layouts/header/logo_with_title"
- = render "layouts/init_client_detection_flags"
- .page-wrap
- .container.signup-box-container.navless-container
- = render "layouts/broadcast"
- .content
- = render "layouts/flash"
- = yield
- %hr.footer-fixed
- .footer-container
- .container
- .footer-links
- = link_to _("Help"), help_path
- = link_to _("About GitLab"), "https://about.gitlab.com/"
- = footer_message
diff --git a/app/views/layouts/experiment_mailer.html.haml b/app/views/layouts/experiment_mailer.html.haml
deleted file mode 100644
index 5a342c400d6..00000000000
--- a/app/views/layouts/experiment_mailer.html.haml
+++ /dev/null
@@ -1,48 +0,0 @@
-<!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 4c6bfc0b33c..addf2375222 100644
--- a/app/views/layouts/header/_current_user_dropdown.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown.html.haml
@@ -2,13 +2,16 @@
%ul
%li.current-user
- .user-name.bold
+ .user-name.gl-font-weight-bold
= current_user.name
+ - if current_user&.status && user_status_set_to_busy?(current_user.status)
+ %span.gl-font-weight-normal.gl-text-gray-500= s_("UserProfile|(Busy)")
= current_user.to_reference
- if current_user.status
.user-status.d-flex.align-items-center.gl-mt-2.has-tooltip{ title: current_user.status.message_html, data: { html: 'true', placement: 'bottom' } }
- %span.user-status-emoji.d-flex.align-items-center
- = emoji_icon current_user.status.emoji
+ - if show_status_emoji?(current_user.status)
+ .user-status-emoji.d-flex.align-items-center
+ = emoji_icon current_user.status.emoji
%span.user-status-message.str-truncated
= current_user.status.message_html.html_safe
%li.divider
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index f6dc808aa55..794d1589172 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -1,4 +1,5 @@
- has_impersonation_link = header_link?(:admin_impersonation)
+- user_status_data = user_status_properties(current_user)
%header.navbar.navbar-gitlab.navbar-expand-sm.js-navbar{ data: { qa_selector: 'navbar' } }
%a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
@@ -103,4 +104,4 @@
#whats-new-app{ data: { storage_key: whats_new_storage_key } }
- 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 : '' } }
+ .js-set-status-modal-wrapper{ data: user_status_data }
diff --git a/app/views/layouts/header/_registration_enabled_callout.html.haml b/app/views/layouts/header/_registration_enabled_callout.html.haml
new file mode 100644
index 00000000000..1b1804edcc7
--- /dev/null
+++ b/app/views/layouts/header/_registration_enabled_callout.html.haml
@@ -0,0 +1,15 @@
+- return unless show_registration_enabled_user_callout?
+
+%div{ class: [container_class, @content_class, 'gl-pt-5!'] }
+ .gl-alert.gl-alert-warning.js-registration-enabled-callout{ role: 'alert', data: { feature_id: UserCalloutsHelper::REGISTRATION_ENABLED_CALLOUT, dismiss_endpoint: user_callouts_path } }
+ = sprite_icon('warning', size: 16, css_class: 'gl-alert-icon')
+ %button.gl-alert-dismiss.js-close{ type: 'button', aria: { label: _('Close') }, data: { testid: 'close-registration-enabled-callout' } }
+ = sprite_icon('close', size: 16)
+ .gl-alert-title
+ = _('Open registration is enabled on your instance.')
+ .gl-alert-body
+ = html_escape(_('%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance.')) % { anchorOpen: "<a href=\"#{help_page_path('user/admin_area/settings/sign_up_restrictions')}\">".html_safe, anchorClose: '</a>'.html_safe }
+ .gl-alert-actions
+ = link_to general_admin_application_settings_path(anchor: 'js-signup-settings'), class: 'btn gl-alert-action btn-info btn-md gl-button' do
+ %span.gl-button-text
+ = _('View setting')
diff --git a/app/views/layouts/mailer.html.haml b/app/views/layouts/mailer.html.haml
index 28dcbce7183..c2eb6b68024 100644
--- a/app/views/layouts/mailer.html.haml
+++ b/app/views/layouts/mailer.html.haml
@@ -1 +1,10 @@
+= content_for :footer do
+ %tr.footer
+ %td
+ %img.footer-logo{ alt: "GitLab", src: image_url('mailers/gitlab_footer_logo.gif') }
+ %div
+ - manage_notifications_link = link_to(_("Manage all notifications"), profile_notifications_url, class: 'mng-notif-link')
+ - help_link = link_to(_("Help"), help_url, class: 'help-link')
+ = _("You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}").html_safe % { host: Gitlab.config.gitlab.host, manage_notifications_link: manage_notifications_link, help_link: help_link }
+
= render 'layouts/mailer'
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
index 547d005a93e..f0cdb3d1a51 100644
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ b/app/views/layouts/nav/_breadcrumbs.html.haml
@@ -1,5 +1,6 @@
- container = @no_breadcrumb_container ? 'container-fluid' : container_class
- hide_top_links = @hide_top_links || false
+- push_to_schema_breadcrumb(@breadcrumb_title, breadcrumb_title_link)
%nav.breadcrumbs{ role: "navigation", class: [container, @content_class] }
.breadcrumbs-container{ class: ("border-bottom-0" if @no_breadcrumb_border) }
@@ -17,4 +18,7 @@
= render "layouts/nav/breadcrumbs/collapsed_dropdown", location: :after
%li
%h2.breadcrumbs-sub-title= link_to @breadcrumb_title, breadcrumb_title_link
+ %script{ type:'application/ld+json' }
+ :plain
+ #{schema_breadcrumb_json}
= yield :header_content
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index abaadc89a9e..7cbef6b00b1 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -2,7 +2,7 @@
-# https://gitlab.com/gitlab-org/gitlab-foss/issues/49713 for more information.
%ul.list-unstyled.navbar-sub-nav
- if dashboard_nav_link?(:projects)
- = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects qa-projects-dropdown", data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_value: "" } }) do
+ = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects qa-projects-dropdown", data: { track_label: "projects_dropdown", track_event: "click_dropdown" } }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Projects')
= sprite_icon('chevron-down', css_class: 'caret-down')
@@ -10,7 +10,7 @@
= render "layouts/nav/projects_dropdown/show"
- if dashboard_nav_link?(:groups)
- = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "d-none d-md-block home dropdown header-groups qa-groups-dropdown", data: { track_label: "groups_dropdown", track_event: "click_dropdown", track_value: "" } }) do
+ = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "d-none d-md-block home dropdown header-groups qa-groups-dropdown", data: { track_label: "groups_dropdown", track_event: "click_dropdown" } }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Groups')
= sprite_icon('chevron-down', css_class: 'caret-down')
@@ -18,7 +18,7 @@
= render "layouts/nav/groups_dropdown/show"
- if any_dashboard_nav_link?([:groups, :milestones, :activity, :snippets])
- %li.header-more.dropdown{ **tracking_attrs('main_navigation', 'click_more_link', 'navigation') }
+ = nav_link(html_options: { id: 'nav-more-dropdown', class: "header-more dropdown", data: { track_label: "more_dropdown", track_event: "click_more_link" } }) do
%a{ href: "#", data: { toggle: "dropdown", qa_selector: 'more_dropdown' } }
= _('More')
= sprite_icon('chevron-down', css_class: 'caret-down')
@@ -71,11 +71,11 @@
- if Feature.enabled?(:user_mode_in_session)
- if header_link?(:admin_mode)
- = nav_link(controller: 'admin/sessions', html_options: { class: "d-none d-lg-block d-xl-block"}) do
+ = nav_link(controller: 'admin/sessions', html_options: { class: "d-none d-lg-block"}) do
= link_to destroy_admin_session_path, method: :post, title: _('Leave Admin Mode'), aria: { label: _('Leave Admin Mode') }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= sprite_icon('lock-open', size: 18)
- elsif current_user.admin?
- = nav_link(controller: 'admin/sessions', html_options: { class: "d-none d-lg-block d-xl-block"}) do
+ = nav_link(controller: 'admin/sessions', html_options: { class: "d-none d-lg-block"}) do
= link_to new_admin_session_path, title: _('Enter Admin Mode'), aria: { label: _('Enter Admin Mode') }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= sprite_icon('lock', size: 18)
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 0da4d4f7ddd..1e0e9628c89 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -69,7 +69,7 @@
= link_to admin_cohorts_path, title: _('Cohorts') do
%span
= _('Cohorts')
- - if Feature.enabled?(:instance_statistics)
+ - if Feature.enabled?(:instance_statistics, default_enabled: true)
= nav_link(controller: :instance_statistics) do
= link_to admin_instance_statistics_path, title: _('Instance Statistics') do
%span
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index d3d71f91176..5ff774d5d9c 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, :test_cases], unless: -> { current_path?('projects/pipelines#charts') }) do
+ = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts, :test_cases, :pipeline_editor], 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, :test_cases], html_options: { class: "fly-out-top-item" }) do
+ = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts, :test_cases, :pipeline_editor], html_options: { class: "fly-out-top-item" }) do
= link_to project_pipelines_path(@project) do
%strong.fly-out-top-item-name
= _('CI / CD')
@@ -186,6 +186,12 @@
%span
= _('Pipelines')
+ - if can_view_pipeline_editor?(@project)
+ = nav_link(controller: :pipeline_editor, action: :show) do
+ = link_to project_ci_pipeline_editor_path(@project), title: s_('Pipelines|Editor') do
+ %span
+ = s_('Pipelines|Editor')
+
- if project_nav_tab? :builds
= nav_link(controller: :jobs) do
= link_to project_jobs_path(@project), title: _('Jobs'), class: 'shortcuts-builds' do
@@ -262,6 +268,12 @@
%span
= _('Serverless')
+ - if project_nav_tab? :terraform
+ = nav_link(controller: :terraform) do
+ = link_to project_terraform_index_path(@project), title: _('Terraform') do
+ %span
+ = _('Terraform')
+
- if project_nav_tab? :clusters
- show_cluster_hint = show_gke_cluster_integration_callout?(@project)
= nav_link(controller: [:clusters, :user, :gcp]) do
@@ -272,7 +284,6 @@
.feature-highlight.js-feature-highlight{ disabled: true,
data: { trigger: 'manual',
container: 'body',
- toggle: 'popover',
placement: 'right',
highlight: UserCalloutsHelper::GKE_CLUSTER_INTEGRATION,
highlight_priority: UserCallout.feature_names[:GKE_CLUSTER_INTEGRATION],
@@ -369,6 +380,8 @@
%strong.fly-out-top-item-name
= _('Members')
+ = render_if_exists 'projects/invite_members_side_nav_link', project: @project
+
- if project_nav_tab? :settings
= nav_link(path: sidebar_settings_paths) do
= link_to edit_project_path(@project) do
@@ -412,7 +425,7 @@
= link_to project_settings_ci_cd_path(@project), title: _('CI / CD') do
%span
= _('CI / CD')
- - if !@project.archived? && settings_operations_available?
+ - if settings_operations_available?
= nav_link(controller: [:operations]) do
= link_to project_settings_operations_path(@project), title: _('Operations'), data: { qa_selector: 'operations_settings_link' } do
= _('Operations')
diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml
index a0c82380023..62e5431e290 100644
--- a/app/views/layouts/project.html.haml
+++ b/app/views/layouts/project.html.haml
@@ -2,6 +2,7 @@
- page_description @project.description_html unless page_description
- header_title project_title(@project) unless header_title
- nav "project"
+- page_itemtype 'http://schema.org/SoftwareSourceCode'
- display_subscription_banner!
- display_namespace_storage_limit_alert!
- @left_sidebar = true
diff --git a/app/views/layouts/unknown_user_mailer.html.haml b/app/views/layouts/unknown_user_mailer.html.haml
new file mode 100644
index 00000000000..2eb7b400604
--- /dev/null
+++ b/app/views/layouts/unknown_user_mailer.html.haml
@@ -0,0 +1,8 @@
+= content_for :footer do
+ %tr.footer
+ %td.gitlab-info
+ %img.footer-logo{ alt: "GitLab", src: image_url('mailers/gitlab_footer_logo.gif') }
+ %p.gitlab-info-text
+ = html_escape(_("GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate")) % { br_tag: '<br/>'.html_safe }
+
+= render 'layouts/mailer'
diff --git a/app/views/layouts/unknown_user_mailer.text.erb b/app/views/layouts/unknown_user_mailer.text.erb
new file mode 100644
index 00000000000..f3d8f13b7bf
--- /dev/null
+++ b/app/views/layouts/unknown_user_mailer.text.erb
@@ -0,0 +1,9 @@
+<%= text_header_message %>
+
+<%= yield -%>
+
+-- <%# signature marker %>
+<%= _("GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate") %>
+<%= render_if_exists 'layouts/mailer/additional_text' %>
+
+<%= text_footer_message %>
diff --git a/app/views/layouts/welcome.html.haml b/app/views/layouts/welcome.html.haml
new file mode 100644
index 00000000000..48921e9ff89
--- /dev/null
+++ b/app/views/layouts/welcome.html.haml
@@ -0,0 +1,8 @@
+!!! 5
+%html.subscriptions-layout-html{ lang: 'en' }
+ = render 'layouts/head'
+ %body.ui-indigo.d-flex.vh-100.gl-bg-gray-10
+ = render "layouts/header/logo_with_title"
+ = render "layouts/broadcast"
+ .container.d-flex.flex-grow-1.m-0
+ = yield
diff --git a/app/views/notify/_issuable_csv_export.html.haml b/app/views/notify/_issuable_csv_export.html.haml
index 239b5b14966..5a581811179 100644
--- a/app/views/notify/_issuable_csv_export.html.haml
+++ b/app/views/notify/_issuable_csv_export.html.haml
@@ -1,6 +1,6 @@
%p{ style: 'font-size:18px; text-align:center; line-height:30px;' }
- project_link = link_to(@project.full_name, project_url(@project), style: "color:#3777b0; text-decoration:none; display:block;")
- = _('Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment.').html_safe % { count: pluralize(@written_count, type.to_s), project_link: project_link }
+ = _('Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment.').html_safe % { count: pluralize(@written_count, type.to_s.titleize.downcase), project_link: project_link }
- if @truncated
%p
= _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues.') % { written_count: @written_count, count: @count }
diff --git a/app/views/notify/_note_email.html.haml b/app/views/notify/_note_email.html.haml
index c558358725c..2cef6f97d48 100644
--- a/app/views/notify/_note_email.html.haml
+++ b/app/views/notify/_note_email.html.haml
@@ -9,7 +9,7 @@
= succeed ':' do
= link_to note.author_name, user_url(note.author)
- if discussion.nil?
- commented
+ = link_to 'commented', target_url
- else
- if note.start_of_discussion?
started a new
diff --git a/app/views/notify/instance_access_request_email.html.haml b/app/views/notify/instance_access_request_email.html.haml
new file mode 100644
index 00000000000..87bc655164b
--- /dev/null
+++ b/app/views/notify/instance_access_request_email.html.haml
@@ -0,0 +1,10 @@
+#content
+ = email_default_heading(say_hello(@recipient))
+ %p
+ = instance_access_request_text(@user, format: :html)
+ %p
+ = _("Username: %{username}") % { username: @user.username }
+ %p
+ = _("Email: %{email}") % { email: @user.email }
+ %p
+ = instance_access_request_link(@user, format: :html)
diff --git a/app/views/notify/instance_access_request_email.text.erb b/app/views/notify/instance_access_request_email.text.erb
new file mode 100644
index 00000000000..317f962a29c
--- /dev/null
+++ b/app/views/notify/instance_access_request_email.text.erb
@@ -0,0 +1,8 @@
+<%= say_hello(@recipient) %>
+
+<%= instance_access_request_text(@user) %>
+
+<%= _("Username: %{username}") % { username: @user.username } %>
+<%= _("Email: %{email}") % { email: @user.email } %>
+
+<%= instance_access_request_link(@user) %>
diff --git a/app/views/notify/member_invited_email.html.haml b/app/views/notify/member_invited_email.html.haml
index 4fcd2936d25..5ff1e2393c9 100644
--- a/app/views/notify/member_invited_email.html.haml
+++ b/app/views/notify/member_invited_email.html.haml
@@ -1,16 +1,12 @@
+- placeholders = { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe, project_or_group_name: member_source.human_name, project_or_group: member_source.model_name.singular, br_tag: '<br/>'.html_safe, role: member.human_access.downcase }
%tr
%td.text-content
+ %h2.invite-header
+ = s_('InviteEmail|You are invited!')
%p
- You have been invited
- if member.created_by
- by
- = link_to member.created_by.name, user_url(member.created_by)
- to join the
- = link_to member_source.human_name, member_source.public? ? member_source.web_url : invite_url(@token), class: :highlight
- #{member_source.model_name.singular} as #{content_tag :span, member.human_access, class: :highlight}.
-
- %p
- = link_to 'Accept invitation', invite_url(@token, @invite_url_params)
- or
- = link_to 'decline', decline_invite_url(@token)
-
+ = html_escape(s_("InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders.merge({ inviter: (link_to member.created_by.name, user_url(member.created_by)).html_safe })
+ - else
+ = html_escape(s_("InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders
+ %p.invite-actions
+ = link_to s_('InviteEmail|Join now'), invite_url(@token), class: 'invite-btn-join'
diff --git a/app/views/notify/member_invited_email.text.erb b/app/views/notify/member_invited_email.text.erb
index e6e6a685f92..e58dfc10810 100644
--- a/app/views/notify/member_invited_email.text.erb
+++ b/app/views/notify/member_invited_email.text.erb
@@ -1,4 +1,9 @@
-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 %>.
+<% placeholders = { project_or_group_name: member_source.human_name, project_or_group: member_source.model_name.singular, role: member.human_access.downcase } %>
-Accept invitation: <%= invite_url(@token, @invite_url_params) %>
-Decline invitation: <%= decline_invite_url(@token) %>
+<% if member.created_by %>
+<%= s_('InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}') % placeholders.merge({ inviter: sanitize_name(member.created_by.name) }) %>
+<% else %>
+<%= s_('InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}') % placeholders %>
+<% end %>
+
+<%= s_('InviteEmail|Join now') %>: <%= 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
deleted file mode 100644
index 5cfb6acee05..00000000000
--- a/app/views/notify/member_invited_email_experiment.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-%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
deleted file mode 100644
index 6843cea4df7..00000000000
--- a/app/views/notify/member_invited_email_experiment.text.erb
+++ /dev/null
@@ -1,10 +0,0 @@
-<% 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/prometheus_alert_fired_email.html.haml b/app/views/notify/prometheus_alert_fired_email.html.haml
index 75ba66b44f9..cdc97d583df 100644
--- a/app/views/notify/prometheus_alert_fired_email.html.haml
+++ b/app/views/notify/prometheus_alert_fired_email.html.haml
@@ -1,5 +1,9 @@
+- body = @alert.resolved? ? _('An alert has been resolved in %{project_path}.') : _('An alert has been triggered in %{project_path}.')
+
+%p
+ = body % { project_path: @alert.project.full_path }
%p
- = _('An alert has been triggered in %{project_path}.') % { project_path: @alert.project.full_path }
+ = link_to(_('View alert details.'), @alert.details_url)
- if description = @alert.description
%p
diff --git a/app/views/notify/prometheus_alert_fired_email.text.erb b/app/views/notify/prometheus_alert_fired_email.text.erb
index 8853f2a317b..b23cd8b6ccc 100644
--- a/app/views/notify/prometheus_alert_fired_email.text.erb
+++ b/app/views/notify/prometheus_alert_fired_email.text.erb
@@ -1,4 +1,7 @@
-<%= _('An alert has been triggered in %{project_path}.') % { project_path: @alert.project.full_path } %>.
+<% body = @alert.resolved? ? _('An alert has been resolved in %{project_path}.') : _('An alert has been triggered in %{project_path}.') %>
+
+<%= body % { project_path: @alert.project.full_path } %>
+<%= _('View alert details at') %> <%= @alert.details_url %>
<% if description = @alert.description %>
<%= _('Description:') %> <%= description %>
diff --git a/app/views/profiles/_event_table.html.haml b/app/views/profiles/_event_table.html.haml
index b952868e4e3..f74902a3c3b 100644
--- a/app/views/profiles/_event_table.html.haml
+++ b/app/views/profiles/_event_table.html.haml
@@ -5,7 +5,7 @@
- events.each do |event|
%li
%span.description
- = audit_icon(event.details[:with], class: "gl-mr-2")
+ = audit_icon(event.details[:with], css_class: 'gl-mr-2')
= _('Signed in with %{authentication} authentication') % { authentication: event.details[:with]}
%span.float-right= time_ago_with_tooltip(event.created_at)
diff --git a/app/views/profiles/preferences/_gitpod.html.haml b/app/views/profiles/preferences/_gitpod.html.haml
deleted file mode 100644
index 589c3a27c18..00000000000
--- a/app/views/profiles/preferences/_gitpod.html.haml
+++ /dev/null
@@ -1,9 +0,0 @@
-%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
- = gitpod_enable_description
diff --git a/app/views/profiles/preferences/_integrations.html.haml b/app/views/profiles/preferences/_integrations.html.haml
deleted file mode 100644
index 037fe5df263..00000000000
--- a/app/views/profiles/preferences/_integrations.html.haml
+++ /dev/null
@@ -1,18 +0,0 @@
-- 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
deleted file mode 100644
index fdd0be22664..00000000000
--- a/app/views/profiles/preferences/_sourcegraph.html.haml
+++ /dev/null
@@ -1,10 +0,0 @@
-%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 b8d7e1af005..ca5972f1b46 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -1,146 +1,151 @@
- page_title _('Preferences')
- @content_class = "limit-container-width" unless fluid_layout
+- user_fields = { gitpod_enabled: @user.gitpod_enabled, sourcegraph_enabled: @user.sourcegraph_enabled }
+- user_theme_id = Gitlab::Themes.for_user(@user).id
+- data_attributes = { integration_views: integration_views.to_json, user_fields: user_fields.to_json }
- Gitlab::Themes.each do |theme|
= stylesheet_link_tag "themes/#{theme.css_filename}" if theme.css_filename
-= form_for @user, url: profile_preferences_path, remote: true, method: :put, html: { class: 'row gl-mt-3 js-preferences-form' } do |f|
- .col-lg-4.application-theme#navigation-theme
- %h4.gl-mt-0
- = s_('Preferences|Navigation theme')
- %p
- = s_('Preferences|Customize the appearance of the application header and navigation sidebar.')
- .col-lg-8.application-theme
- .row
- - Gitlab::Themes.each do |theme|
- %label.col-6.col-sm-4.col-md-3.gl-mb-5.gl-text-center
- .preview{ class: theme.css_class }
- = f.radio_button :theme_id, theme.id, checked: Gitlab::Themes.for_user(@user).id == theme.id
- = theme.name
+= form_for @user, url: profile_preferences_path, remote: true, method: :put do |f|
+ .row.gl-mt-3.js-preferences-form
+ .col-lg-4.application-theme#navigation-theme
+ %h4.gl-mt-0
+ = s_('Preferences|Navigation theme')
+ %p
+ = s_('Preferences|Customize the appearance of the application header and navigation sidebar.')
+ .col-lg-8.application-theme
+ .row
+ - Gitlab::Themes.each do |theme|
+ %label.col-6.col-sm-4.col-md-3.gl-mb-5.gl-text-center
+ .preview{ class: theme.css_class }
+ = f.radio_button :theme_id, theme.id, checked: user_theme_id == theme.id
+ = theme.name
- .col-sm-12
- %hr
+ .col-sm-12
+ %hr
- .col-lg-4.profile-settings-sidebar#syntax-highlighting-theme
- %h4.gl-mt-0
- = s_('Preferences|Syntax highlighting theme')
- %p
- = s_('Preferences|This setting allows you to customize the appearance of the syntax.')
- = succeed '.' do
- = link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'syntax-highlighting-theme'), target: '_blank'
- .col-lg-8.syntax-theme
- - Gitlab::ColorSchemes.each do |scheme|
- = label_tag do
- .preview= image_tag "#{scheme.css_class}-scheme-preview.png"
- = f.radio_button :color_scheme_id, scheme.id
- = scheme.name
+ .col-lg-4.profile-settings-sidebar#syntax-highlighting-theme
+ %h4.gl-mt-0
+ = s_('Preferences|Syntax highlighting theme')
+ %p
+ = s_('Preferences|This setting allows you to customize the appearance of the syntax.')
+ = succeed '.' do
+ = link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'syntax-highlighting-theme'), target: '_blank'
+ .col-lg-8.syntax-theme
+ - Gitlab::ColorSchemes.each do |scheme|
+ = label_tag do
+ .preview= image_tag "#{scheme.css_class}-scheme-preview.png"
+ = f.radio_button :color_scheme_id, scheme.id
+ = scheme.name
- .col-sm-12
- %hr
+ .col-sm-12
+ %hr
- .col-lg-4.profile-settings-sidebar#behavior
- %h4.gl-mt-0
- = s_('Preferences|Behavior')
- %p
- = s_('Preferences|This setting allows you to customize the behavior of the system layout and default views.')
- = succeed '.' do
- = link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'behavior'), target: '_blank'
- .col-lg-8
- .form-group
- = f.label :layout, class: 'label-bold' do
- = s_('Preferences|Layout width')
- = f.select :layout, layout_choices, {}, class: 'select2'
- .form-text.text-muted
- = s_('Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage}) application layout.').html_safe % { percentage: '100%' }
- .form-group
- = f.label :dashboard, class: 'label-bold' do
- = s_('Preferences|Homepage content')
- = f.select :dashboard, dashboard_choices, {}, class: 'select2'
- .form-text.text-muted
- = s_('Preferences|Choose what content you want to see on your homepage.')
+ .col-lg-4.profile-settings-sidebar#behavior
+ %h4.gl-mt-0
+ = s_('Preferences|Behavior')
+ %p
+ = s_('Preferences|This setting allows you to customize the behavior of the system layout and default views.')
+ = succeed '.' do
+ = link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'behavior'), target: '_blank'
+ .col-lg-8
+ .form-group
+ = f.label :layout, class: 'label-bold' do
+ = s_('Preferences|Layout width')
+ = f.select :layout, layout_choices, {}, class: 'select2'
+ .form-text.text-muted
+ = s_('Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage}) application layout.').html_safe % { percentage: '100%' }
+ .form-group
+ = f.label :dashboard, class: 'label-bold' do
+ = s_('Preferences|Homepage content')
+ = f.select :dashboard, dashboard_choices, {}, class: 'select2'
+ .form-text.text-muted
+ = s_('Preferences|Choose what content you want to see on your homepage.')
- = render_if_exists 'profiles/preferences/group_overview_selector', f: f # EE-specific
+ = render_if_exists 'profiles/preferences/group_overview_selector', f: f # EE-specific
- .form-group
- = f.label :project_view, class: 'label-bold' do
- = s_('Preferences|Project overview content')
- = f.select :project_view, project_view_choices, {}, class: 'select2'
- .form-text.text-muted
- = s_('Preferences|Choose what content you want to see on a project’s overview page.')
- .form-group.form-check
- = f.check_box :render_whitespace_in_code, class: 'form-check-input'
- = f.label :render_whitespace_in_code, class: 'form-check-label' do
- = s_('Preferences|Render whitespace characters in the Web IDE')
- .form-group.form-check
- = f.check_box :show_whitespace_in_diffs, class: 'form-check-input'
- = f.label :show_whitespace_in_diffs, class: 'form-check-label' do
- = s_('Preferences|Show whitespace changes in diffs')
- - if Feature.enabled?(:view_diffs_file_by_file, default_enabled: true)
+ .form-group
+ = f.label :project_view, class: 'label-bold' do
+ = s_('Preferences|Project overview content')
+ = f.select :project_view, project_view_choices, {}, class: 'select2'
+ .form-text.text-muted
+ = s_('Preferences|Choose what content you want to see on a project’s overview page.')
+ .form-group.form-check
+ = f.check_box :render_whitespace_in_code, class: 'form-check-input'
+ = f.label :render_whitespace_in_code, class: 'form-check-label' do
+ = s_('Preferences|Render whitespace characters in the Web IDE')
.form-group.form-check
- = f.check_box :view_diffs_file_by_file, class: 'form-check-input'
- = f.label :view_diffs_file_by_file, class: 'form-check-label' do
- = s_("Preferences|Show one file at a time on merge request's Changes tab")
+ = f.check_box :show_whitespace_in_diffs, class: 'form-check-input'
+ = f.label :show_whitespace_in_diffs, class: 'form-check-label' do
+ = s_('Preferences|Show whitespace changes in diffs')
+ - if Feature.enabled?(:view_diffs_file_by_file, default_enabled: true)
+ .form-group.form-check
+ = f.check_box :view_diffs_file_by_file, class: 'form-check-input'
+ = f.label :view_diffs_file_by_file, class: 'form-check-label' do
+ = s_("Preferences|Show one file at a time on merge request's Changes tab")
+ .form-text.text-muted
+ = s_("Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser.")
+ .form-group
+ = f.label :tab_width, s_('Preferences|Tab width'), class: 'label-bold'
+ = f.number_field :tab_width,
+ class: 'form-control',
+ min: Gitlab::TabWidth::MIN,
+ max: Gitlab::TabWidth::MAX,
+ required: true
.form-text.text-muted
- = s_("Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser.")
- .form-group
- = f.label :tab_width, s_('Preferences|Tab width'), class: 'label-bold'
- = f.number_field :tab_width,
- class: 'form-control',
- min: Gitlab::TabWidth::MIN,
- max: Gitlab::TabWidth::MAX,
- required: true
- .form-text.text-muted
- = s_('Preferences|Must be a number between %{min} and %{max}') % { min: Gitlab::TabWidth::MIN, max: Gitlab::TabWidth::MAX }
-
- .col-sm-12
- %hr
+ = s_('Preferences|Must be a number between %{min} and %{max}') % { min: Gitlab::TabWidth::MIN, max: Gitlab::TabWidth::MAX }
- .col-lg-4.profile-settings-sidebar#localization
- %h4.gl-mt-0
- = _('Localization')
- %p
- = _('Customize language and region related settings.')
- = succeed '.' do
- = link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'localization'), target: '_blank'
- .col-lg-8
- .form-group
- = f.label :preferred_language, class: 'label-bold' do
- = _('Language')
- = f.select :preferred_language, language_choices, {}, class: 'select2'
- .form-text.text-muted
- = s_('Preferences|This feature is experimental and translations are not complete yet')
- .form-group
- = f.label :first_day_of_week, class: 'label-bold' do
- = _('First day of the week')
- = f.select :first_day_of_week, first_day_of_week_choices_with_default, {}, class: 'select2'
- - if Feature.enabled?(:user_time_settings)
.col-sm-12
%hr
- .col-lg-4.profile-settings-sidebar
- %h4.gl-mt-0= s_('Preferences|Time preferences')
- %p= s_('Preferences|These settings will update how dates and times are displayed for you.')
+
+ .col-lg-4.profile-settings-sidebar#localization
+ %h4.gl-mt-0
+ = _('Localization')
+ %p
+ = _('Customize language and region related settings.')
+ = succeed '.' do
+ = link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'localization'), target: '_blank'
.col-lg-8
.form-group
- %h5= s_('Preferences|Time format')
- .checkbox-icon-inline-wrapper
- - time_format_label = capture do
- = s_('Preferences|Display time in 24-hour format')
- = f.check_box :time_format_in_24h
- = f.label :time_format_in_24h do
- = time_format_label
- %h5= s_('Preferences|Time display')
- .checkbox-icon-inline-wrapper
- - time_display_label = capture do
- = s_('Preferences|Use relative times')
- = f.check_box :time_display_relative
- = f.label :time_display_relative do
- = time_display_label
- .form-text.text-muted
- = s_('Preferences|For example: 30 mins ago.')
+ = f.label :preferred_language, class: 'label-bold' do
+ = _('Language')
+ = f.select :preferred_language, language_choices, {}, class: 'select2'
+ .form-text.text-muted
+ = s_('Preferences|This feature is experimental and translations are not complete yet')
+ .form-group
+ = f.label :first_day_of_week, class: 'label-bold' do
+ = _('First day of the week')
+ = f.select :first_day_of_week, first_day_of_week_choices_with_default, {}, class: 'select2'
+ - if Feature.enabled?(:user_time_settings)
+ .col-sm-12
+ %hr
+ .col-lg-4.profile-settings-sidebar
+ %h4.gl-mt-0= s_('Preferences|Time preferences')
+ %p= s_('Preferences|These settings will update how dates and times are displayed for you.')
+ .col-lg-8
+ .form-group
+ %h5= s_('Preferences|Time format')
+ .checkbox-icon-inline-wrapper
+ - time_format_label = capture do
+ = s_('Preferences|Display time in 24-hour format')
+ = f.check_box :time_format_in_24h
+ = f.label :time_format_in_24h do
+ = time_format_label
+ %h5= s_('Preferences|Time display')
+ .checkbox-icon-inline-wrapper
+ - time_display_label = capture do
+ = s_('Preferences|Use relative times')
+ = f.check_box :time_display_relative
+ = f.label :time_display_relative do
+ = time_display_label
+ .form-text.text-muted
+ = s_('Preferences|For example: 30 mins ago.')
- = render 'integrations', f: f
+ #js-profile-preferences-app{ data: data_attributes, user_fields: user_fields.to_json }
- .col-lg-4.profile-settings-sidebar
- .col-lg-8
- .form-group
- = f.submit _('Save changes'), class: 'gl-button btn btn-success'
+ .row.gl-mt-3.js-preferences-form
+ .col-lg-4.profile-settings-sidebar
+ .col-lg-8
+ .form-group
+ = f.submit _('Save changes'), class: 'gl-button btn btn-success'
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index f5fab727a57..bf9f1336a4f 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -2,6 +2,8 @@
- page_title s_("Profiles|Edit Profile")
- @content_class = "limit-container-width" unless fluid_layout
- gravatar_link = link_to Gitlab.config.gravatar.host, 'https://' + Gitlab.config.gravatar.host
+- availability = availability_values
+- custom_emoji = show_status_emoji?(@user.status)
= bootstrap_form_for @user, url: profile_path, method: :put, html: { multipart: true, class: 'edit-user gl-mt-3 js-quick-submit gl-show-field-errors' }, authenticity_token: true do |f|
= form_errors(@user)
@@ -48,9 +50,9 @@
- emoji_button = button_tag type: :button,
class: 'js-toggle-emoji-menu emoji-menu-toggle-button gl-button btn has-tooltip',
title: s_("Profiles|Add status emoji") do
- - if @user.status
+ - if custom_emoji
= emoji_icon @user.status.emoji
- %span#js-no-emoji-placeholder.no-emoji-placeholder{ class: ('hidden' if @user.status) }
+ %span#js-no-emoji-placeholder.no-emoji-placeholder{ class: ('hidden' if custom_emoji) }
= sprite_icon('slight-smile', css_class: 'award-control-icon-neutral')
= sprite_icon('smiley', css_class: 'award-control-icon-positive')
= sprite_icon('smile', css_class: 'award-control-icon-super-positive')
@@ -68,6 +70,10 @@
prepend: emoji_button,
append: reset_message_button,
placeholder: s_("Profiles|What's your status?")
+ - if Feature.enabled?(:set_user_availability_status, @user)
+ .checkbox-icon-inline-wrapper
+ = status_form.check_box :availability, { data: { testid: "user-availability-checkbox" }, label: s_("Profiles|Busy"), wrapper_class: 'gl-mr-0 gl-font-weight-bold' }, availability["busy"], availability["not_set"]
+ .gl-text-gray-600.gl-ml-5= s_('Profiles|"Busy" will be shown next to your name')
- if Feature.enabled?(:user_time_settings)
%hr
.row.user-time-preferences
diff --git a/app/views/projects/_find_file_link.html.haml b/app/views/projects/_find_file_link.html.haml
index 74cdb0f7409..c3b4a61c28a 100644
--- a/app/views/projects/_find_file_link.html.haml
+++ b/app/views/projects/_find_file_link.html.haml
@@ -1,2 +1,2 @@
-= link_to project_find_file_path(@project, @ref), class: 'btn shortcuts-find-file', rel: 'nofollow' do
+= link_to project_find_file_path(@project, @ref), class: 'gl-button btn shortcuts-find-file', rel: 'nofollow' do
= _('Find file')
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 9f4496e7a13..569255ec2e5 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -3,21 +3,23 @@
- max_project_topic_length = 15
- emails_disabled = @project.emails_disabled?
+= render_if_exists 'projects/invite_members_modal', project: @project
+
.project-home-panel.js-show-on-project-root.gl-my-5{ class: [("empty-project" if empty_repo)] }
.row.gl-mb-3
.home-panel-title-row.col-md-12.col-lg-6.d-flex
.avatar-container.rect-avatar.s64.home-panel-avatar.gl-flex-shrink-0.gl-w-11.gl-h-11.gl-mr-3.float-none
- = project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s64', width: 64, height: 64)
+ = project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s64', width: 64, height: 64, itemprop: 'image')
.d-flex.flex-column.flex-wrap.align-items-baseline
.d-inline-flex.align-items-baseline
- %h1.home-panel-title.gl-mt-3.gl-mb-2.gl-font-size-h1.gl-line-height-24.gl-font-weight-bold{ data: { qa_selector: 'project_name_content' } }
+ %h1.home-panel-title.gl-mt-3.gl-mb-2.gl-font-size-h1.gl-line-height-24.gl-font-weight-bold{ data: { qa_selector: 'project_name_content' }, itemprop: 'name' }
= @project.name
%span.visibility-icon.text-secondary.gl-ml-2.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@project) }
= visibility_level_icon(@project.visibility_level, options: { class: 'icon' })
= render_if_exists 'compliance_management/compliance_framework/compliance_framework_badge', project: @project
.home-panel-metadata.d-flex.flex-wrap.text-secondary.gl-font-base.gl-font-weight-normal.gl-line-height-normal
- if can?(current_user, :read_project, @project)
- %span.text-secondary
+ %span.text-secondary{ itemprop: 'identifier' }
= s_('ProjectPage|Project ID: %{project_id}') % { project_id: @project.id }
- if current_user
%span.access-request-links.gl-ml-3
@@ -30,10 +32,10 @@
- project_topics_classes = "badge badge-pill badge-secondary gl-mr-2"
- explore_project_topic_path = explore_projects_path(tag: topic)
- if topic.length > max_project_topic_length
- %a{ class: "#{ project_topics_classes } str-truncated-30 has-tooltip", data: { container: "body" }, title: topic, href: explore_project_topic_path }
+ %a{ class: "#{ project_topics_classes } str-truncated-30 has-tooltip", data: { container: "body" }, title: topic, href: explore_project_topic_path, itemprop: 'keywords' }
= topic.titleize
- else
- %a{ class: project_topics_classes, href: explore_project_topic_path }
+ %a{ class: project_topics_classes, href: explore_project_topic_path, itemprop: 'keywords' }
= topic.titleize
- if @project.has_extra_topics?
@@ -44,7 +46,7 @@
.project-repo-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end
- if current_user
.d-inline-flex
- = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn-xs', emails_disabled: emails_disabled
+ = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn-xs', dropdown_container_class: 'gl-mr-3', emails_disabled: emails_disabled
.count-buttons.d-inline-flex
= render 'projects/buttons/star'
@@ -61,7 +63,7 @@
.home-panel-home-desc.mt-1
- if @project.description.present?
.home-panel-description.text-break
- .home-panel-description-markdown.read-more-container
+ .home-panel-description-markdown.read-more-container{ itemprop: 'abstract' }
= markdown_field(@project, :description)
%button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
= _("Read more")
diff --git a/app/views/projects/_invite_members_modal.html.haml b/app/views/projects/_invite_members_modal.html.haml
new file mode 100644
index 00000000000..ad95f39bbfa
--- /dev/null
+++ b/app/views/projects/_invite_members_modal.html.haml
@@ -0,0 +1,7 @@
+- if invite_members_allowed?(project.group)
+ .js-invite-members-modal{ data: { id: project.id,
+ name: project.name,
+ is_project: true,
+ access_levels: GroupMember.access_level_roles.to_json,
+ default_access_level: Gitlab::Access::GUEST,
+ help_link: help_page_url('user/permissions') } }
diff --git a/app/views/projects/_invite_members_side_nav_link.html.haml b/app/views/projects/_invite_members_side_nav_link.html.haml
new file mode 100644
index 00000000000..15e0b75cf57
--- /dev/null
+++ b/app/views/projects/_invite_members_side_nav_link.html.haml
@@ -0,0 +1,3 @@
+- if invite_members_allowed?(project.group) && body_data_page == 'projects:show'
+ %li
+ .js-invite-members-trigger{ data: { icon: 'plus', display_text: _('Invite team members') } }
diff --git a/app/views/projects/_merge_request_merge_options_settings.html.haml b/app/views/projects/_merge_request_merge_options_settings.html.haml
index 047b4dafbfc..8951f2ed22f 100644
--- a/app/views/projects/_merge_request_merge_options_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_options_settings.html.haml
@@ -4,6 +4,7 @@
%b= s_('ProjectSettings|Merge options')
%p.text-secondary= s_('ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed')
= render_if_exists 'projects/merge_pipelines_settings', form: form
+ = render_if_exists 'projects/merge_trains_settings', form: form
.form-check.mb-2
= form.check_box :resolve_outdated_diff_discussions, class: 'form-check-input'
= form.label :resolve_outdated_diff_discussions, class: 'form-check-label' do
diff --git a/app/views/projects/_remove.html.haml b/app/views/projects/_remove.html.haml
index 05eab3b3245..c246c45d0f7 100644
--- a/app/views/projects/_remove.html.haml
+++ b/app/views/projects/_remove.html.haml
@@ -1,5 +1,4 @@
- return unless can?(current_user, :remove_project, project)
-- confirm_phrase = s_('DeleteProject|Delete %{name}') % { name: project.full_name }
.sub-section
%h4.danger-title= _('Delete project')
@@ -7,4 +6,4 @@
%strong= _('Deleting the project will delete its repository and all related resources including issues, merge requests etc.')
%p
%strong= _('Deleted projects cannot be restored!')
- #js-project-delete-button{ data: { form_path: project_path(project), confirm_phrase: confirm_phrase } }
+ #js-project-delete-button{ data: { form_path: project_path(project), confirm_phrase: project.path } }
diff --git a/app/views/projects/_remove_fork.html.haml b/app/views/projects/_remove_fork.html.haml
new file mode 100644
index 00000000000..2a7453902a8
--- /dev/null
+++ b/app/views/projects/_remove_fork.html.haml
@@ -0,0 +1,10 @@
+- return unless @project.forked? && can?(current_user, :remove_fork_project, @project)
+
+.sub-section
+ %h4.danger-title= _('Remove fork relationship')
+ %p= remove_fork_project_description_message(@project)
+
+ = form_for @project, url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' } do |f|
+ %p
+ %strong= _('Once removed, the fork relationship cannot be restored. This project will no longer be able to receive or send merge requests to the source project or other forks.')
+ = button_to _('Remove fork relationship'), '#', class: "gl-button btn btn-danger js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_warning_message(@project) }
diff --git a/app/views/projects/_service_desk_settings.html.haml b/app/views/projects/_service_desk_settings.html.haml
index fceef0624d7..7c08955983a 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_address if @project.service_desk_enabled),
+ incoming_email: (@project.service_desk_incoming_address if @project.service_desk_enabled),
custom_email: (@project.service_desk_custom_address if @project.service_desk_enabled),
selected_template: "#{@project.service_desk_setting&.issue_template_key}",
outgoing_name: "#{@project.service_desk_setting&.outgoing_name}",
diff --git a/app/views/projects/_stat_anchor_list.html.haml b/app/views/projects/_stat_anchor_list.html.haml
index 516790fb6d9..8a93d93a538 100644
--- a/app/views/projects/_stat_anchor_list.html.haml
+++ b/app/views/projects/_stat_anchor_list.html.haml
@@ -5,5 +5,5 @@
%ul.nav
- anchors.each do |anchor|
%li.nav-item
- = link_to_if anchor.link, anchor.label, anchor.link, class: anchor.is_link ? 'nav-link stat-link d-flex align-items-center' : "nav-link btn btn-#{anchor.class_modifier || 'missing'} d-flex align-items-center" do
+ = link_to_if(anchor.link, anchor.label, anchor.link, stat_anchor_attrs(anchor)) do
.stat-text.d-flex.align-items-center{ class: ('btn btn-default disabled' if project_buttons) }= anchor.label
diff --git a/app/views/projects/_transfer.html.haml b/app/views/projects/_transfer.html.haml
new file mode 100644
index 00000000000..eb7feb7bd3b
--- /dev/null
+++ b/app/views/projects/_transfer.html.haml
@@ -0,0 +1,16 @@
+- return unless can?(current_user, :change_namespace, @project)
+
+.sub-section
+ %h4.danger-title= _('Transfer project')
+ = form_for @project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } do |f|
+ .form-group
+ = label_tag :new_namespace_id, nil, class: 'label-bold' do
+ %span= _('Select a new namespace')
+ .form-group
+ = select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2'
+ %ul
+ %li= _("Be careful. Changing the project's namespace can have unintended side effects.")
+ %li= _('You can only transfer the project to namespaces you manage.')
+ %li= _('You will need to update your local repositories to point to the new location.')
+ %li= _('Project visibility level will be changed to match namespace rules when transferring to a group.')
+ = f.submit 'Transfer project', class: "gl-button btn btn-danger js-confirm-danger qa-transfer-button", data: { "confirm-danger-message" => transfer_project_message(@project) }
diff --git a/app/views/projects/alert_management/details.html.haml b/app/views/projects/alert_management/details.html.haml
index 5230d5e3476..b1d680e4f3d 100644
--- a/app/views/projects/alert_management/details.html.haml
+++ b/app/views/projects/alert_management/details.html.haml
@@ -1,4 +1,5 @@
- add_to_breadcrumbs s_('AlertManagement|Alerts'), project_alert_management_index_path(@project)
- page_title s_('AlertManagement|Alert detail')
+- add_page_specific_style 'page_bundles/alert_management_details'
#js-alert_details{ data: alert_management_detail_data(@project, @alert_id) }
diff --git a/app/views/projects/artifacts/_artifact.html.haml b/app/views/projects/artifacts/_artifact.html.haml
index 30f30fe922f..233a41a37b5 100644
--- a/app/views/projects/artifacts/_artifact.html.haml
+++ b/app/views/projects/artifacts/_artifact.html.haml
@@ -50,10 +50,10 @@
.table-action-buttons
.btn-group
- if can?(current_user, :read_build, @project)
- = link_to download_project_job_artifacts_path(@project, artifact.job), rel: 'nofollow', download: '', title: _('Download artifacts'), data: { placement: 'top', container: 'body' }, ref: 'tooltip', aria: { label: _('Download artifacts') }, class: 'btn btn-build has-tooltip ml-0' do
+ = link_to download_project_job_artifacts_path(@project, artifact.job), rel: 'nofollow', download: '', title: _('Download artifacts'), data: { placement: 'top', container: 'body' }, ref: 'tooltip', aria: { label: _('Download artifacts') }, class: 'gl-button btn btn-build has-tooltip ml-0' do
= sprite_icon('download')
- = link_to browse_project_job_artifacts_path(@project, artifact.job), rel: 'nofollow', title: _('Browse artifacts'), data: { placement: 'top', container: 'body' }, ref: 'tooltip', aria: { label: _('Browse artifacts') }, class: 'btn btn-build has-tooltip' do
+ = link_to browse_project_job_artifacts_path(@project, artifact.job), rel: 'nofollow', title: _('Browse artifacts'), data: { placement: 'top', container: 'body' }, ref: 'tooltip', aria: { label: _('Browse artifacts') }, class: 'gl-button btn btn-build has-tooltip' do
= sprite_icon('folder-open')
- if can?(current_user, :destroy_artifacts, @project)
diff --git a/app/views/projects/artifacts/_tree_file.html.haml b/app/views/projects/artifacts/_tree_file.html.haml
index f42d5128715..03d35c1c989 100644
--- a/app/views/projects/artifacts/_tree_file.html.haml
+++ b/app/views/projects/artifacts/_tree_file.html.haml
@@ -9,7 +9,7 @@
= link_to path_to_file, class: 'tree-item-file-external-link js-artifact-tree-tooltip str-truncated',
target: '_blank', rel: 'noopener noreferrer', title: _('Opens in a new window') do
%span>= blob.name
- = icon('external-link', class: 'js-artifact-tree-external-icon')
+ = sprite_icon('external-link', css_class: 'js-artifact-tree-external-icon')
- else
= link_to path_to_file, class: 'str-truncated' do
%span= blob.name
diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml
index ff56cb53720..b363f0d4325 100644
--- a/app/views/projects/artifacts/browse.html.haml
+++ b/app/views/projects/artifacts/browse.html.haml
@@ -17,7 +17,7 @@
.tree-controls<
= link_to download_project_job_artifacts_path(@project, @build),
- rel: 'nofollow', download: '', class: 'btn btn-default download' do
+ rel: 'nofollow', download: '', class: 'gl-button btn btn-default download' do
= sprite_icon('download')
Download artifacts archive
diff --git a/app/views/projects/blob/_breadcrumb.html.haml b/app/views/projects/blob/_breadcrumb.html.haml
index 810c8b9082f..710417f90e3 100644
--- a/app/views/projects/blob/_breadcrumb.html.haml
+++ b/app/views/projects/blob/_breadcrumb.html.haml
@@ -23,13 +23,13 @@
- if blob.readable_text?
- if blame
= link_to 'Normal view', project_blob_path(@project, @id),
- class: 'btn'
+ class: 'gl-button btn'
- else
= link_to 'Blame', project_blame_path(@project, @id),
- class: 'btn js-blob-blame-link' unless blob.empty?
+ class: 'gl-button btn js-blob-blame-link' unless blob.empty?
= link_to 'History', project_commits_path(@project, @id),
- class: 'btn'
+ class: 'gl-button btn'
= link_to 'Permalink', project_blob_path(@project,
- tree_join(@commit.sha, @path)), class: 'btn js-data-file-blob-permalink-url'
+ tree_join(@commit.sha, @path)), class: 'gl-button btn js-data-file-blob-permalink-url'
diff --git a/app/views/projects/blob/_header.html.haml b/app/views/projects/blob/_header.html.haml
index 55ae9cded1c..6d01206a128 100644
--- a/app/views/projects/blob/_header.html.haml
+++ b/app/views/projects/blob/_header.html.haml
@@ -2,9 +2,9 @@
.js-file-title.file-title-flex-parent
= render 'projects/blob/header_content', blob: blob
- .file-actions<
+ .file-actions.gl-display-flex.gl-flex-fill-1.gl-align-self-start.gl-md-justify-content-end<
= render 'projects/blob/viewer_switcher', blob: blob unless blame
- - if Feature.enabled?(:consolidated_edit_button)
+ - if Feature.enabled?(:consolidated_edit_button, @project)
= render 'shared/web_ide_button', blob: blob
- else
= edit_blob_button(@project, @ref, @path, blob: blob)
diff --git a/app/views/projects/blob/_header_content.html.haml b/app/views/projects/blob/_header_content.html.haml
index 30356348941..b310939c5a3 100644
--- a/app/views/projects/blob/_header_content.html.haml
+++ b/app/views/projects/blob/_header_content.html.haml
@@ -1,7 +1,7 @@
.file-header-content
= blob_icon blob.mode, blob.name
- %strong.file-title-name
+ %strong.file-title-name.gl-word-break-all{ data: { qa_selector: 'file_name_content' } }
= blob.name
= copy_file_path_button(blob.path)
diff --git a/app/views/projects/blob/_pipeline_tour_success.html.haml b/app/views/projects/blob/_pipeline_tour_success.html.haml
index 3ea2defb2b3..ef1fe25ba1b 100644
--- a/app/views/projects/blob/_pipeline_tour_success.html.haml
+++ b/app/views/projects/blob/_pipeline_tour_success.html.haml
@@ -1,4 +1,6 @@
.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),
+ 'example-link': help_page_path('ci/examples/README.md', anchor: 'gitlab-cicd-examples'),
+ 'code-quality-link': help_page_path('user/project/merge_requests/code_quality'),
'human-access': @project.team.human_max_access(current_user&.id) } }
diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml
index 4dbfa2b1e3c..f400c7de5eb 100644
--- a/app/views/projects/blob/_upload.html.haml
+++ b/app/views/projects/blob/_upload.html.haml
@@ -21,7 +21,7 @@
.form-actions
= button_tag class: 'btn gl-button btn-success btn-upload-file', id: 'submit-all', type: 'button' do
- = icon('spin spinner', class: 'js-loading-icon hidden' )
+ .spinner.spinner-sm.gl-mr-2.js-loading-icon.hidden
= button_title
= link_to _("Cancel"), '#', class: "btn gl-button btn-cancel", "data-dismiss" => "modal"
diff --git a/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml b/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
index 61d67a88a5a..3326cded42a 100644
--- a/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
+++ b/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
@@ -1,8 +1,8 @@
- if viewer.valid?(project: @project, sha: @commit.sha, user: @current_user)
- = icon('check fw')
+ = sprite_icon('check')
This GitLab CI configuration is valid.
- else
- = icon('warning fw')
+ = sprite_icon('warning-solid')
This GitLab CI configuration is invalid:
= viewer.validation_message(project: @project, sha: @commit.sha, user: @current_user)
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 de9c6c5320f..9c3f9b6c9fd 100644
--- a/app/views/projects/blob/viewers/_metrics_dashboard_yml.html.haml
+++ b/app/views/projects/blob/viewers/_metrics_dashboard_yml.html.haml
@@ -1,8 +1,8 @@
- if viewer.valid?
- = icon('check fw')
+ = sprite_icon('check')
= _('Metrics Dashboard YAML definition is valid.')
- else
- = icon('warning fw')
+ = sprite_icon('warning-solid')
= _('Metrics Dashboard YAML definition is invalid:')
%ul
- viewer.errors.each do |error|
diff --git a/app/views/projects/blob/viewers/_route_map.html.haml b/app/views/projects/blob/viewers/_route_map.html.haml
index 024e9b4ddb2..068cf400cd5 100644
--- a/app/views/projects/blob/viewers/_route_map.html.haml
+++ b/app/views/projects/blob/viewers/_route_map.html.haml
@@ -1,8 +1,8 @@
- if viewer.valid?
- = icon('check fw')
+ = sprite_icon('check')
This Route Map is valid.
- else
- = icon('warning fw')
+ = sprite_icon('warning-solid')
This Route Map is invalid:
= viewer.validation_message
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 30e710ead7f..8f5fac1a40b 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -36,12 +36,12 @@
%svg.s24
- if merge_project && create_mr_button?(@repository.root_ref, branch.name)
- = link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-default' do
+ = link_to create_mr_path(@repository.root_ref, branch.name), class: 'gl-button btn btn-default' do
= _('Merge request')
- if branch.name != @repository.root_ref
= link_to project_compare_index_path(@project, from: @repository.root_ref, to: branch.name),
- class: "btn btn-default js-onboarding-compare-branches #{'gl-ml-3' unless merge_project}",
+ class: "gl-button btn btn-default js-onboarding-compare-branches #{'gl-ml-3' unless merge_project}",
method: :post,
title: s_('Branches|Compare') do
= s_('Branches|Compare')
diff --git a/app/views/projects/branches/_delete_protected_modal.html.haml b/app/views/projects/branches/_delete_protected_modal.html.haml
index 8aa79d2d464..24beeeb0ae1 100644
--- a/app/views/projects/branches/_delete_protected_modal.html.haml
+++ b/app/views/projects/branches/_delete_protected_modal.html.haml
@@ -36,7 +36,7 @@
.modal-footer
%button.btn{ data: { dismiss: 'modal' } } Cancel
= link_to s_('Branches|Delete protected branch'), '',
- class: "btn btn-danger js-delete-branch",
+ class: "gl-button btn btn-danger js-delete-branch",
title: s_('Branches|Delete branch'),
method: :delete,
'aria-label' => s_('Branches|Delete branch')
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index f3561ed5078..46cce59f67a 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -24,7 +24,7 @@
%button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
%span.light
= branches_sort_options_hash[@sort]
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable
%li.dropdown-header
= s_('Branches|Sort by')
@@ -40,7 +40,7 @@
data: { confirm: s_('Branches|Deleting the merged branches cannot be undone. Are you sure?'),
container: 'body' } do
= s_('Branches|Delete merged branches')
- = link_to new_project_branch_path(@project), class: 'btn btn-success' do
+ = link_to new_project_branch_path(@project), class: 'gl-button btn btn-success' do
= s_('Branches|New branch')
= render_if_exists 'projects/commits/mirror_status'
diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml
index 7a8bc45a272..24dfb59dc85 100644
--- a/app/views/projects/branches/new.html.haml
+++ b/app/views/projects/branches/new.html.haml
@@ -22,10 +22,10 @@
= hidden_field_tag :ref, default_ref
= button_tag type: 'button', title: default_ref, class: 'dropdown-menu-toggle wide js-branch-select monospace', required: true, data: { toggle: 'dropdown', selected: default_ref, field_name: 'ref' } do
.text-left.dropdown-toggle-text= default_ref
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
= render 'shared/ref_dropdown', dropdown_class: 'wide'
.form-text.text-muted Existing branch name, tag, or commit SHA
.form-actions
- = button_tag 'Create branch', class: 'btn btn-success', tabindex: 3
- = link_to 'Cancel', project_branches_path(@project), class: 'btn btn-cancel'
+ = button_tag 'Create branch', class: 'gl-button btn btn-success'
+ = link_to 'Cancel', project_branches_path(@project), class: 'gl-button btn btn-cancel'
%script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe
diff --git a/app/views/projects/buttons/_clone.html.haml b/app/views/projects/buttons/_clone.html.haml
index 7ce143a86b3..cf58cff7445 100644
--- a/app/views/projects/buttons/_clone.html.haml
+++ b/app/views/projects/buttons/_clone.html.haml
@@ -2,7 +2,7 @@
- dropdown_class = local_assigns.fetch(:dropdown_class, '')
.git-clone-holder.js-git-clone-holder
- %a#clone-dropdown.btn.btn-primary.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
+ %a#clone-dropdown.gl-button.btn.btn-primary.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
%span.gl-mr-2.js-clone-dropdown-label
= _('Clone')
= sprite_icon("chevron-down", css_class: "icon")
diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml
index c04687bd846..0fcbf2ca1eb 100644
--- a/app/views/projects/buttons/_download.html.haml
+++ b/app/views/projects/buttons/_download.html.haml
@@ -3,7 +3,7 @@
- if !project.empty_repo? && can?(current_user, :download_code, project)
- archive_prefix = "#{project.path}-#{ref.tr('/', '-')}"
.project-action-button.dropdown.inline>
- %button.btn.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download'), 'data-display' => 'static', data: { qa_selector: 'download_source_code_button' } }
+ %button.gl-button.btn.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download'), 'data-display' => 'static', data: { qa_selector: 'download_source_code_button' } }
= sprite_icon('download')
%span.sr-only= _('Select Archive Format')
= sprite_icon("chevron-down")
diff --git a/app/views/projects/buttons/_download_links.html.haml b/app/views/projects/buttons/_download_links.html.haml
index 990f3ff526b..c997df578c0 100644
--- a/app/views/projects/buttons/_download_links.html.haml
+++ b/app/views/projects/buttons/_download_links.html.haml
@@ -1,4 +1,4 @@
.btn-group.ml-0.w-100
- Gitlab::Workhorse::ARCHIVE_FORMATS.each_with_index do |fmt, index|
- archive_path = project_archive_path(project, id: tree_join(ref, archive_prefix), path: path, format: fmt)
- = link_to fmt, external_storage_url_or_path(archive_path), rel: 'nofollow', download: '', class: "btn btn-xs #{"btn-primary" if index == 0}"
+ = link_to fmt, external_storage_url_or_path(archive_path), rel: 'nofollow', download: '', class: "gl-button btn btn-xs #{"btn-primary" if index == 0}"
diff --git a/app/views/projects/buttons/_xcode_link.html.haml b/app/views/projects/buttons/_xcode_link.html.haml
index a8b32fb0ef5..e0f47f1ca3d 100644
--- a/app/views/projects/buttons/_xcode_link.html.haml
+++ b/app/views/projects/buttons/_xcode_link.html.haml
@@ -1,2 +1,2 @@
-%a.btn.btn-default{ href: xcode_uri_to_repo(@project) }
+%a.gl-button.btn.btn-default{ href: xcode_uri_to_repo(@project) }
= _("Open in Xcode")
diff --git a/app/views/projects/ci/lints/_create.html.haml b/app/views/projects/ci/lints/_create.html.haml
deleted file mode 100644
index 4b7cda0ef57..00000000000
--- a/app/views/projects/ci/lints/_create.html.haml
+++ /dev/null
@@ -1,51 +0,0 @@
-- if @result.valid?
- .bs-callout.bs-callout-success
- %p
- %b= _("Status:")
- = _("syntax is correct")
-
- = render "projects/ci/lints/lint_warnings", warnings: @result.warnings
-
- .table-holder
- %table.table.table-bordered
- %thead
- %tr
- %th= _("Parameter")
- %th= _("Value")
- %tbody
- - @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
- %p
- %b= _("Status:")
- = _("syntax is incorrect")
- %pre
- - @result.errors.each do |message|
- %p= message
-
- = 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
deleted file mode 100644
index 90db65e6c27..00000000000
--- a/app/views/projects/ci/lints/_lint_warnings.html.haml
+++ /dev/null
@@ -1,10 +0,0 @@
-- if warnings
- - total_warnings = warnings.length
- - message = warning_header(total_warnings)
-
- - if warnings.any?
- .bs-callout.bs-callout-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 64f250bd607..feccea6cfc0 100644
--- a/app/views/projects/ci/lints/show.html.haml
+++ b/app/views/projects/ci/lints/show.html.haml
@@ -3,32 +3,4 @@
%h2.pt-3.pb-3= _("Validate your GitLab CI configuration")
-- if Feature.enabled?(:ci_lint_vue, @project)
- #js-ci-lint{ data: { endpoint: project_ci_lint_path(@project), help_page_path: help_page_path('ci/lint', anchor: 'pipeline-simulation') } }
-
-- 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")
- .file-editor.code
- .js-edit-mode-pane.qa-editor#editor{ data: { 'editor-loading': true } }<
- %pre.editor-loading-content= params[: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)
+#js-ci-lint{ data: { endpoint: project_ci_lint_path(@project), pipeline_simulation_help_page_path: help_page_path('ci/lint', anchor: 'pipeline-simulation') , lint_help_page_path: help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax') } }
diff --git a/app/views/projects/ci/pipeline_editor/show.html.haml b/app/views/projects/ci/pipeline_editor/show.html.haml
new file mode 100644
index 00000000000..0e032f2575e
--- /dev/null
+++ b/app/views/projects/ci/pipeline_editor/show.html.haml
@@ -0,0 +1,6 @@
+- page_title s_('Pipelines|Pipeline Editor')
+
+#js-pipeline-editor{ data: { "ci-config-path": @project.ci_config_path_or_default,
+ "project-path" => @project.full_path,
+ "default-branch" => @project.default_branch,
+} }
diff --git a/app/views/projects/cleanup/_show.html.haml b/app/views/projects/cleanup/_show.html.haml
index 02d35e690ca..37ec63cc871 100644
--- a/app/views/projects/cleanup/_show.html.haml
+++ b/app/views/projects/cleanup/_show.html.haml
@@ -26,4 +26,4 @@
.form-text.text-muted
= _("The maximum file size allowed is %{size}.") % { size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes) }
- = f.submit _('Start cleanup'), class: 'btn btn-success'
+ = f.submit _('Start cleanup'), class: 'gl-button btn btn-success'
diff --git a/app/views/projects/commit/_change.html.haml b/app/views/projects/commit/_change.html.haml
index 4f5d69c614c..11adc7fd64a 100644
--- a/app/views/projects/commit/_change.html.haml
+++ b/app/views/projects/commit/_change.html.haml
@@ -33,7 +33,7 @@
- else
= hidden_field_tag 'create_merge_request', 1, id: nil
.form-actions
- = submit_tag label, class: 'btn btn-success'
- = link_to _("Cancel"), '#', class: "btn btn-cancel", "data-dismiss" => "modal"
+ = submit_tag label, class: 'gl-button btn btn-success'
+ = link_to _("Cancel"), '#', class: "gl-button btn btn-cancel", "data-dismiss" => "modal"
= render 'shared/projects/edit_information'
diff --git a/app/views/projects/commit/diff_files.html.haml b/app/views/projects/commit/diff_files.html.haml
index 3a473be3840..0c52c1a15a4 100644
--- a/app/views/projects/commit/diff_files.html.haml
+++ b/app/views/projects/commit/diff_files.html.haml
@@ -1,3 +1 @@
-- diff_files = diffs.diff_files
-
-= render partial: 'projects/diffs/file', collection: diff_files, as: :diff_file, locals: { project: diffs.project, environment: environment, diff_page_context: 'is-commit' }
+= render partial: 'projects/diffs/file', collection: diffs.diff_files, as: :diff_file, locals: { project: diffs.project, environment: environment, diff_page_context: 'is-commit' }
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index cd61576a96a..179b0c5efbd 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -23,7 +23,7 @@
= author_avatar(commit, size: 40, has_tooltip: false)
.commit-detail.flex-list
- .commit-content.qa-commit-content
+ .commit-content{ data: { qa_selector: 'commit_content' } }
- 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
@@ -57,8 +57,8 @@
.js-commit-pipeline-status{ data: { endpoint: pipelines_project_commit_path(project, commit.id, ref: ref) } }
- .commit-sha-group.d-none.d-sm-flex
+ .commit-sha-group.btn-group.d-none.d-sm-flex
.label.label-monospace.monospace
= commit.short_id
- = clipboard_button(text: commit.id, title: _("Copy commit SHA"), class: "btn btn-default", container: "body")
+ = clipboard_button(text: commit.id, title: _("Copy commit SHA"), class: "gl-button btn btn-default", container: "body")
= link_to_browse_code(project, commit)
diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml
index 40dd3a685d4..94bdab53cd0 100644
--- a/app/views/projects/commits/show.html.haml
+++ b/app/views/projects/commits/show.html.haml
@@ -34,4 +34,5 @@
%div{ id: dom_id(@project) }
%ol#commits-list.list-unstyled.content_list
= render 'commits', project: @project, ref: @ref
- = spinner
+ .loading.hide
+ = loading_icon(size: "lg")
diff --git a/app/views/projects/confluences/show.html.haml b/app/views/projects/confluences/show.html.haml
index 5814b7a00f5..1eeafac5f1e 100644
--- a/app/views/projects/confluences/show.html.haml
+++ b/app/views/projects/confluences/show.html.haml
@@ -8,7 +8,7 @@
- wiki_confluence_epic_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/3629'
- wiki_confluence_epic_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: wiki_confluence_epic_link_url }
= s_("WikiEmpty|You've enabled the Confluence Workspace integration. Your wiki will be viewable directly within Confluence. We are hard at work integrating Confluence more seamlessly into GitLab. If you'd like to stay up to date, follow our %{wiki_confluence_epic_link_start}Confluence epic%{wiki_confluence_epic_link_end}.").html_safe % { wiki_confluence_epic_link_start: wiki_confluence_epic_link_start, wiki_confluence_epic_link_end: '</a>'.html_safe }
- = link_to @project.confluence_service.confluence_url, target: '_blank', rel: 'noopener noreferrer', class: 'btn btn-success external-url', title: s_('WikiEmpty|Go to Confluence') do
+ = link_to @project.confluence_service.confluence_url, target: '_blank', rel: 'noopener noreferrer', class: 'gl-button btn btn-success external-url', title: s_('WikiEmpty|Go to Confluence') do
= sprite_icon('external-link')
= s_('WikiEmpty|Go to Confluence')
diff --git a/app/views/projects/cycle_analytics/show.html.haml b/app/views/projects/cycle_analytics/show.html.haml
index d99579c25c0..b98ab9757fa 100644
--- a/app/views/projects/cycle_analytics/show.html.haml
+++ b/app/views/projects/cycle_analytics/show.html.haml
@@ -22,7 +22,7 @@
.dropdown.inline.js-ca-dropdown
%button.dropdown-menu-toggle{ "data-toggle" => "dropdown", :type => "button" }
%span.dropdown-label {{ n__('Last %d day', 'Last %d days', 30) }}
- %i.fa.fa-chevron-down
+ = sprite_icon("chevron-down", css_class: "dropdown-menu-toggle-icon gl-top-3")
%ul.dropdown-menu.dropdown-menu-right
%li
%a{ "href" => "#", "data-value" => "7" }
diff --git a/app/views/projects/default_branch/_show.html.haml b/app/views/projects/default_branch/_show.html.haml
index 2ba12601c79..a1c7f5027c5 100644
--- a/app/views/projects/default_branch/_show.html.haml
+++ b/app/views/projects/default_branch/_show.html.haml
@@ -28,4 +28,4 @@
= _("Issues referenced by merge requests and commits within the default branch will be closed automatically")
= link_to sprite_icon('question-o'), help_page_path('user/project/issues/managing_issues.md', anchor: 'disabling-automatic-issue-closing'), target: '_blank'
- = f.submit _('Save changes'), class: "btn btn-success"
+ = f.submit _('Save changes'), class: "gl-button btn btn-success"
diff --git a/app/views/projects/deploy_keys/edit.html.haml b/app/views/projects/deploy_keys/edit.html.haml
index 805d4983002..780ec128d63 100644
--- a/app/views/projects/deploy_keys/edit.html.haml
+++ b/app/views/projects/deploy_keys/edit.html.haml
@@ -7,4 +7,4 @@
= render partial: 'shared/deploy_keys/form', locals: { form: f, deploy_key: @deploy_key }
.form-actions
= f.submit 'Save changes', class: 'btn-success btn'
- = link_to 'Cancel', project_settings_repository_path(@project), class: 'btn btn-cancel'
+ = link_to 'Cancel', project_settings_repository_path(@project), class: 'gl-button btn btn-cancel'
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index 43aaa7cb405..8364311796f 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -9,7 +9,7 @@
.files-changed-inner
.inline-parallel-buttons.d-none.d-md-block
- if !diffs_expanded? && diff_files.any? { |diff_file| diff_file.collapsed? }
- = link_to _('Expand all'), url_for(safe_params.merge(expanded: 1, format: nil)), class: 'btn btn-default'
+ = link_to _('Expand all'), url_for(safe_params.merge(expanded: 1, format: nil)), class: 'gl-button btn btn-default'
- if show_whitespace_toggle
- if current_controller?(:commit)
= commit_diff_whitespace_link(diffs.project, @commit, class: 'd-none d-sm-inline-block')
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index 187ebcb739c..18da238d445 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -14,16 +14,15 @@
= submodule_diff_compare_link(diff_file)
- unless diff_file.submodule?
- - blob = diff_file.blob
.file-actions.d-none.d-sm-block
- - if blob&.readable_text?
- = link_to '#', class: 'js-toggle-diff-comments btn active has-tooltip', title: _("Toggle comments for this file"), disabled: @diff_notes_disabled do
+ - if diff_file.blob&.readable_text?
+ = link_to '#', class: 'js-toggle-diff-comments gl-button btn active has-tooltip', title: _("Toggle comments for this file"), disabled: @diff_notes_disabled do
= sprite_icon('comment')
\
- if editable_diff?(diff_file)
- link_opts = @merge_request.persisted? ? { from_merge_request_iid: @merge_request.iid } : {}
= edit_blob_button(@merge_request.source_project, @merge_request.source_branch, diff_file.new_path,
- blob: blob, link_opts: link_opts)
+ blob: diff_file.blob, link_opts: link_opts)
- if image_diff && image_replaced
= view_file_button(diff_file.old_content_sha, diff_file.old_path, project, replaced: true)
diff --git a/app/views/projects/diffs/_file_header.html.haml b/app/views/projects/diffs/_file_header.html.haml
index e9dfda4e927..cb43527def1 100644
--- a/app/views/projects/diffs/_file_header.html.haml
+++ b/app/views/projects/diffs/_file_header.html.haml
@@ -1,30 +1,27 @@
-- show_toggle = local_assigns.fetch(:show_toggle, true)
-
-- if show_toggle
+- if local_assigns.fetch(:show_toggle, true)
%i.fa.diff-toggle-caret.fa-fw
- if diff_file.submodule?
- - blob = diff_file.blob
%span
= sprite_icon('archive')
%strong.file-title-name
- = submodule_link(blob, diff_file.content_sha, diff_file.repository)
+ = submodule_link(diff_file.blob, diff_file.content_sha, diff_file.repository)
- = copy_file_path_button(blob.path)
+ = copy_file_path_button(diff_file.blob.path)
- else
= conditional_link_to url.present?, url do
= blob_icon diff_file.b_mode, diff_file.file_path
- if diff_file.renamed_file?
- old_path, new_path = mark_inline_diffs(diff_file.old_path, diff_file.new_path)
- %strong.file-title-name.has-tooltip{ data: { title: diff_file.old_path, container: 'body' } }
+ %strong.file-title-name.has-tooltip.gl-word-break-all{ data: { title: diff_file.old_path, container: 'body' } }
= old_path
&rarr;
- %strong.file-title-name.has-tooltip{ data: { title: diff_file.new_path, container: 'body' } }
+ %strong.file-title-name.has-tooltip.gl-word-break-all{ data: { title: diff_file.new_path, container: 'body' } }
= new_path
- else
- %strong.file-title-name.has-tooltip{ data: { title: diff_file.file_path, container: 'body' } }
+ %strong.file-title-name.has-tooltip.gl-word-break-all{ data: { title: diff_file.file_path, container: 'body' } }
= diff_file.file_path
- if diff_file.deleted_file?
@@ -33,7 +30,7 @@
= copy_file_path_button(diff_file.file_path)
- if diff_file.mode_changed?
- %small
+ %small.gl-mr-2
#{diff_file.a_mode} → #{diff_file.b_mode}
- if diff_file.stored_externally? && diff_file.external_storage == :lfs
diff --git a/app/views/projects/diffs/_line.html.haml b/app/views/projects/diffs/_line.html.haml
index 4d40071e07c..de7f9eba158 100644
--- a/app/views/projects/diffs/_line.html.haml
+++ b/app/views/projects/diffs/_line.html.haml
@@ -1,12 +1,11 @@
-- email = local_assigns.fetch(:email, false)
- plain = local_assigns.fetch(:plain, false)
- discussions = local_assigns.fetch(:discussions, nil)
-- type = line.type
- line_code = diff_file.line_code(line)
- if discussions && line.discussable?
- line_discussions = discussions[line_code]
-%tr.line_holder{ class: type, id: (line_code unless plain) }
- - case type
+
+%tr.line_holder{ class: line.type, id: (line_code unless plain) }
+ - case line.type
- when 'match'
= diff_match_line line.old_pos, line.new_pos, text: line.text
- when 'old-nonewline', 'new-nonewline'
@@ -14,21 +13,21 @@
%td.new_line.diff-line-num
%td.line_content.match= line.text
- else
- %td.old_line.diff-line-num{ class: [type, ("js-avatar-container" if !plain)], data: { linenumber: line.old_pos } }
- - link_text = type == "new" ? " " : line.old_pos
+ %td.old_line.diff-line-num{ class: [line.type, ("js-avatar-container" if !plain)], data: { linenumber: line.old_pos } }
- if plain
- = link_text
+ = diff_link_number(line.type, "new", line.old_pos)
- else
- = add_diff_note_button(line_code, diff_file.position(line), type)
- %a{ href: "##{line_code}", data: { linenumber: link_text } }
- %td.new_line.diff-line-num{ class: type, data: { linenumber: line.new_pos } }
- - link_text = type == "old" ? " " : line.new_pos
+ = add_diff_note_button(line_code, diff_file.position(line), line.type)
+ %a{ href: "##{line_code}", data: { linenumber: diff_link_number(line.type, "new", line.old_pos) } }
+
+ %td.new_line.diff-line-num{ class: line.type, data: { linenumber: line.new_pos } }
- if plain
- = link_text
+ = diff_link_number(line.type, "old", line.new_pos)
- else
- %a{ href: "##{line_code}", data: { linenumber: link_text } }
- %td.line_content{ class: type }<
- - if email
+ %a{ href: "##{line_code}", data: { linenumber: diff_link_number(line.type, "old", line.new_pos) } }
+
+ %td.line_content{ class: line.type }<
+ - if local_assigns.fetch(:email, false)
%pre= line.rich_text
- else
= diff_line_content(line.rich_text)
diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml
index cee479aab0a..6429cf31bc3 100644
--- a/app/views/projects/diffs/_stats.html.haml
+++ b/app/views/projects/diffs/_stats.html.haml
@@ -10,7 +10,7 @@
%strong.cgreen= pluralize(sum_added_lines, 'addition')
and
%strong.cred= pluralize(sum_removed_lines, 'deletion')
- .diff-stats-additions-deletions-collapsed.float-right.d-none.d-sm-none{ "aria-hidden": "true", "aria-describedby": "diff-stats" }
+ .diff-stats-additions-deletions-collapsed.float-right.d-none{ "aria-hidden": "true", "aria-describedby": "diff-stats" }
%strong.cgreen<
+#{sum_added_lines}
%strong.cred<
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 63d571e718e..10dd80501e0 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -93,31 +93,9 @@
%li= _('Your deployment services will be broken, you will need to manually fix the services after renaming.')
= f.submit _('Change path'), class: "btn btn-warning qa-change-path-button"
- - if can?(current_user, :change_namespace, @project)
- .sub-section
- %h4.danger-title= _('Transfer project')
- = form_for @project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } do |f|
- .form-group
- = label_tag :new_namespace_id, nil, class: 'label-bold' do
- %span= _('Select a new namespace')
- .form-group
- = select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2'
- %ul
- %li= _("Be careful. Changing the project's namespace can have unintended side effects.")
- %li= _('You can only transfer the project to namespaces you manage.')
- %li= _('You will need to update your local repositories to point to the new location.')
- %li= _('Project visibility level will be changed to match namespace rules when transferring to a group.')
- = f.submit 'Transfer project', class: "gl-button btn btn-danger js-confirm-danger qa-transfer-button", data: { "confirm-danger-message" => transfer_project_message(@project) }
-
- - if @project.forked? && can?(current_user, :remove_fork_project, @project)
- .sub-section
- %h4.danger-title= _('Remove fork relationship')
- %p= remove_fork_project_description_message(@project)
-
- = form_for @project, url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' } do |f|
- %p
- %strong= _('Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source.')
- = button_to _('Remove fork relationship'), '#', class: "gl-button btn btn-danger js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_warning_message(@project) }
+ = render 'transfer', project: @project
+
+ = render 'remove_fork', project: @project
= render 'remove', project: @project
diff --git a/app/views/projects/environments/_external_url.html.haml b/app/views/projects/environments/_external_url.html.haml
index 82567f88ccc..b9208969fb3 100644
--- a/app/views/projects/environments/_external_url.html.haml
+++ b/app/views/projects/environments/_external_url.html.haml
@@ -1,4 +1,4 @@
- if environment.external_url && can?(current_user, :read_environment, environment)
- = link_to environment.external_url, target: '_blank', rel: 'noopener noreferrer', class: 'btn external-url has-tooltip qa-view-deployment', title: s_('Environments|Open live environment') do
+ = link_to environment.external_url, target: '_blank', rel: 'noopener noreferrer', class: 'gl-button btn external-url has-tooltip qa-view-deployment', title: s_('Environments|Open live environment') do
= sprite_icon('external-link')
= _("View deployment")
diff --git a/app/views/projects/environments/_form.html.haml b/app/views/projects/environments/_form.html.haml
index 0b8f9fe220d..10890bf1921 100644
--- a/app/views/projects/environments/_form.html.haml
+++ b/app/views/projects/environments/_form.html.haml
@@ -17,5 +17,5 @@
= f.url_field :external_url, class: 'form-control'
.form-actions
- = f.submit _('Save'), class: 'btn btn-success'
- = link_to _('Cancel'), project_environments_path(@project), class: 'btn btn-cancel'
+ = f.submit _('Save'), class: 'gl-button btn btn-success'
+ = link_to _('Cancel'), project_environments_path(@project), class: 'gl-button btn btn-cancel'
diff --git a/app/views/projects/environments/_metrics_button.html.haml b/app/views/projects/environments/_metrics_button.html.haml
index c4f19ea79e7..5a691676a68 100644
--- a/app/views/projects/environments/_metrics_button.html.haml
+++ b/app/views/projects/environments/_metrics_button.html.haml
@@ -2,6 +2,6 @@
- return unless can?(current_user, :read_environment, environment)
-= link_to environment_metrics_path(environment), title: _('See metrics'), class: 'btn metrics-button' do
+= link_to environment_metrics_path(environment), title: _('See metrics'), class: 'gl-button btn metrics-button' do
= sprite_icon('chart')
= _("Monitoring")
diff --git a/app/views/projects/environments/_pin_button.html.haml b/app/views/projects/environments/_pin_button.html.haml
index 5c7bfc2b17b..ec3e7e20365 100644
--- a/app/views/projects/environments/_pin_button.html.haml
+++ b/app/views/projects/environments/_pin_button.html.haml
@@ -1,3 +1,3 @@
- if environment.auto_stop_at? && environment.available?
- = button_to cancel_auto_stop_project_environment_path(environment.project, environment), class: 'btn btn-secondary has-tooltip', title: _('Prevent environment from auto-stopping') do
+ = button_to cancel_auto_stop_project_environment_path(environment.project, environment), class: 'gl-button btn btn-secondary has-tooltip', title: _('Prevent environment from auto-stopping') do
= sprite_icon('thumbtack')
diff --git a/app/views/projects/environments/_terminal_button.html.haml b/app/views/projects/environments/_terminal_button.html.haml
index 38bc087664b..ab3363bbb07 100644
--- a/app/views/projects/environments/_terminal_button.html.haml
+++ b/app/views/projects/environments/_terminal_button.html.haml
@@ -1,3 +1,3 @@
- if environment.has_terminals? && can?(current_user, :admin_environment, @project)
- = link_to terminal_project_environment_path(@project, environment), class: 'btn terminal-button' do
+ = link_to terminal_project_environment_path(@project, environment), class: 'gl-button btn terminal-button' do
= sprite_icon('terminal')
diff --git a/app/views/projects/environments/empty_metrics.html.haml b/app/views/projects/environments/empty_metrics.html.haml
index 5642fb34da9..3ee51a318c6 100644
--- a/app/views/projects/environments/empty_metrics.html.haml
+++ b/app/views/projects/environments/empty_metrics.html.haml
@@ -11,4 +11,4 @@
%p.state-description
= s_('Metrics|Check out the CI/CD documentation on deploying to an environment')
.text-center
- = link_to s_("Environments|Learn about environments"), help_page_path('ci/environments/index.md'), class: 'btn btn-success'
+ = link_to s_("Environments|Learn about environments"), help_page_path('ci/environments/index.md'), class: 'gl-button btn btn-success'
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index 5b1556c9f52..0cb44bd03fb 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -3,6 +3,7 @@
- page_title _("Environments")
- add_page_specific_style 'page_bundles/xterm'
- add_page_specific_style 'page_bundles/environments'
+- add_page_specific_style 'page_bundles/ci_status'
#environments-detail-view{ data: { name: @environment.name, id: @environment.id, delete_path: environment_delete_path(@environment)} }
- if @environment.available? && can?(current_user, :stop_environment, @environment)
@@ -27,8 +28,8 @@
rel: 'noopener noreferrer' }
= s_('Environments|Learn more about stopping environments')
.modal-footer
- = button_tag _('Cancel'), type: 'button', class: 'btn btn-cancel', data: { dismiss: 'modal' }
- = button_to stop_project_environment_path(@project, @environment), class: 'btn btn-danger has-tooltip', method: :post do
+ = button_tag _('Cancel'), type: 'button', class: 'gl-button btn btn-cancel', data: { dismiss: 'modal' }
+ = button_to stop_project_environment_path(@project, @environment), class: 'gl-button btn btn-danger has-tooltip', method: :post do
= s_('Environments|Stop environment')
- if can_destroy_environment?(@environment)
@@ -48,12 +49,12 @@
- if can?(current_user, :update_environment, @environment)
= link_to _('Edit'), edit_project_environment_path(@project, @environment), class: 'btn'
- if @environment.available? && can?(current_user, :stop_environment, @environment)
- = button_tag class: 'btn btn-danger', type: 'button', data: { toggle: 'modal',
+ = button_tag class: 'gl-button btn btn-danger', type: 'button', data: { toggle: 'modal',
target: '#stop-environment-modal' } do
= sprite_icon('stop')
= s_('Environments|Stop')
- if can_destroy_environment?(@environment)
- = button_tag class: 'btn btn-danger', type: 'button', data: { toggle: 'modal',
+ = button_tag class: 'gl-button btn btn-danger', type: 'button', data: { toggle: 'modal',
target: '#delete-environment-modal' } do
= s_('Environments|Delete')
@@ -66,7 +67,7 @@
%p.blank-state-text
= html_escape(_("Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here.")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
.text-center
- = link_to _("Read more"), help_page_path("ci/environments/index.md"), class: "btn btn-success"
+ = link_to _("Read more"), help_page_path("ci/environments/index.md"), class: "gl-button btn btn-success"
- else
.table-holder.gl-overflow-visible
.ci-table.environments{ role: 'grid' }
diff --git a/app/views/projects/environments/terminal.html.haml b/app/views/projects/environments/terminal.html.haml
index ed0bc0680d7..ee31985eaf0 100644
--- a/app/views/projects/environments/terminal.html.haml
+++ b/app/views/projects/environments/terminal.html.haml
@@ -13,7 +13,7 @@
.col-sm-6
.nav-controls
- if @environment.external_url.present?
- = link_to @environment.external_url, class: 'btn btn-default', target: '_blank', rel: 'noopener noreferrer nofollow' do
+ = link_to @environment.external_url, class: 'gl-button btn btn-default', target: '_blank', rel: 'noopener noreferrer nofollow' do
= sprite_icon('external-link')
= render 'projects/deployments/actions', deployment: @environment.last_deployment
diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
index e341831e17d..2627552058b 100644
--- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
+++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
@@ -19,7 +19,7 @@
- if ref
- if generic_commit_status.ref
.icon-container
- = generic_commit_status.tags.any? ? icon('tag') : sprite_icon('fork', size: 10)
+ = generic_commit_status.tags.any? ? sprite_icon('tag', size: 10) : sprite_icon('fork', size: 10)
= link_to generic_commit_status.ref, project_commits_path(generic_commit_status.project, generic_commit_status.ref)
- else
.light none
@@ -30,7 +30,8 @@
= link_to generic_commit_status.short_sha, project_commit_path(generic_commit_status.project, generic_commit_status.sha), class: "commit-sha"
- if retried
- = icon('warning', class: 'text-warning has-tooltip', title: 'Status was retried.')
+ %span.has-tooltip{ title: _('Status was retried.') }
+ = sprite_icon('warning-solid', css_class: 'text-warning')
.label-container
- if generic_commit_status.tags.any?
diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml
index e40c36da29d..03ea623f4c6 100644
--- a/app/views/projects/hooks/index.html.haml
+++ b/app/views/projects/hooks/index.html.haml
@@ -9,6 +9,6 @@
.col-lg-8.gl-mb-3
= form_for @hook, as: :hook, url: polymorphic_path([@project, :hooks]) do |f|
= render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook }
- = f.submit 'Add webhook', class: 'btn btn-success'
+ = f.submit 'Add webhook', class: 'gl-button btn btn-success'
= render 'shared/web_hooks/index', hooks: @hooks, hook_class: @hook.class
diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml
index 58981ca1556..3064b8bf873 100644
--- a/app/views/projects/imports/new.html.haml
+++ b/app/views/projects/imports/new.html.haml
@@ -16,4 +16,4 @@
= render "shared/import_form", f: f
.form-actions
- = f.submit 'Start import', class: "btn btn-success", tabindex: 4
+ = f.submit 'Start import', class: "gl-button btn btn-success"
diff --git a/app/views/projects/incidents/show.html.haml b/app/views/projects/incidents/show.html.haml
index b0ddc85df5d..4d4607e8e36 100644
--- a/app/views/projects/incidents/show.html.haml
+++ b/app/views/projects/incidents/show.html.haml
@@ -1 +1,6 @@
-= render template: 'projects/issues/show'
+- @content_class = "limit-container-width" unless fluid_layout
+- add_to_breadcrumbs _("Incidents"), project_incidents_path(@project)
+- breadcrumb_title @issue.to_reference
+- page_title "#{@issue.title} (#{@issue.to_reference})", _("Incidents")
+
+= render 'projects/issuable/show', issuable: @issue
diff --git a/app/views/projects/issuable/_show.html.haml b/app/views/projects/issuable/_show.html.haml
new file mode 100644
index 00000000000..48920c4e342
--- /dev/null
+++ b/app/views/projects/issuable/_show.html.haml
@@ -0,0 +1,10 @@
+- page_description issuable.description_html
+- page_card_attributes issuable.card_attributes
+- if issuable.relocation_target
+ - page_canonical_link issuable.relocation_target.present(current_user: current_user).web_url
+
+= render_if_exists "projects/issues/alert_blocked", issue: issuable, current_user: current_user
+= render "projects/issues/alert_moved_from_service_desk", issue: issuable
+
+= render 'shared/issue_type/details_header', issuable: issuable
+= render 'shared/issue_type/details_content', issuable: issuable
diff --git a/app/views/projects/issues/_design_management.html.haml b/app/views/projects/issues/_design_management.html.haml
index 6fc2f41b122..ad0605b10a8 100644
--- a/app/views/projects/issues/_design_management.html.haml
+++ b/app/views/projects/issues/_design_management.html.haml
@@ -6,6 +6,8 @@
- 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?
+ - add_page_startup_graphql_call('design_management/get_design_list', { fullPath: @project.full_path, iid: @issue.iid.to_s, atVersion: nil })
+ - add_page_startup_graphql_call('design_management/design_permissions', { fullPath: @project.full_path, iid: @issue.iid.to_s })
.js-design-management{ data: { project_path: @project.full_path, issue_iid: @issue.iid, issue_path: project_issue_path(@project, @issue) } }
- else
.gl-border-solid.gl-border-1.gl-border-gray-100.gl-rounded-base.gl-mt-5.gl-p-3.gl-text-center
diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml
index e1f1d8bb8f7..51130ae666c 100644
--- a/app/views/projects/issues/_discussion.html.haml
+++ b/app/views/projects/issues/_discussion.html.haml
@@ -5,8 +5,8 @@
- content_for :note_actions do
- if can?(current_user, :update_issue, @issue)
- = link_to 'Reopen issue', issue_path(@issue, issue: {state_event: :reopen}, format: 'json'), data: {original_text: "Reopen issue", alternative_text: "Comment & reopen issue"}, class: "btn btn-nr btn-reopen btn-comment js-note-target-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue'
- = link_to 'Close issue', issue_path(@issue, issue: {state_event: :close}, format: 'json'), data: {original_text: "Close issue", alternative_text: "Comment & close issue"}, class: "btn btn-nr btn-close btn-comment js-note-target-close #{issue_button_visibility(@issue, true)}", title: 'Close issue'
+ = link_to 'Reopen issue', issue_path(@issue, issue: {state_event: :reopen}, format: 'json'), data: {original_text: "Reopen issue", alternative_text: "Comment & reopen issue"}, class: "gl-button btn btn-nr btn-reopen btn-comment js-note-target-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue'
+ = link_to 'Close issue', issue_path(@issue, issue: {state_event: :close}, format: 'json'), data: {original_text: "Close issue", alternative_text: "Comment & close issue"}, class: "gl-button btn btn-nr btn-close btn-comment js-note-target-close #{issue_button_visibility(@issue, true)}", title: 'Close issue'
%section.issuable-discussion.js-vue-notes-event
#js-vue-notes{ data: { notes_data: notes_data(@issue).to_json,
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index 4f188ae273c..d9ad171a6cc 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -37,12 +37,15 @@
&nbsp;
= sprite_icon('calendar')
= issue.due_date.to_s(:medium)
+
+ = render_if_exists "projects/issues/issue_weight", issue: issue
+ = render_if_exists "projects/issues/health_status", issue: issue
+
- if issue.labels.any?
&nbsp;
- presented_labels_sorted_by_title(issue.labels, issue.project).each do |label|
= link_to_label(label, small: true)
- = render_if_exists "projects/issues/issue_weight", issue: issue
= render "projects/issues/issue_estimate", issue: issue
.issuable-meta
diff --git a/app/views/projects/issues/_issues.html.haml b/app/views/projects/issues/_issues.html.haml
index fa08c39e407..ef602da72e5 100644
--- a/app/views/projects/issues/_issues.html.haml
+++ b/app/views/projects/issues/_issues.html.haml
@@ -11,7 +11,8 @@
'empty-state-meta': data_empty_state_meta.to_json,
'can-bulk-edit': @can_bulk_update.to_json,
'sort-key': @sort,
- type: type } }
+ type: type,
+ 'scoped-labels-available': scoped_labels_available?(@project).to_json } }
- else
- empty_state_path = local_assigns.fetch(:empty_state_path, 'shared/empty_states/issues')
%ul.content-list.issues-list.issuable-list{ class: ("manual-ordering" if @sort == 'relative_position') }
diff --git a/app/views/projects/issues/_nav_btns.html.haml b/app/views/projects/issues/_nav_btns.html.haml
index cc6ca4aca4a..dbf6a1f1b94 100644
--- a/app/views/projects/issues/_nav_btns.html.haml
+++ b/app/views/projects/issues/_nav_btns.html.haml
@@ -8,22 +8,22 @@
.btn-group
- if show_export_button
- = render 'projects/issues/export_csv/button'
+ = render 'shared/issuable/csv_export/button', issuable_type: 'issues'
- if show_import_button
= render 'projects/issues/import_csv/button'
- if @can_bulk_update
- = button_tag _("Edit issues"), class: "btn btn-default gl-mr-3 js-bulk-update-toggle"
+ = button_tag _("Edit issues"), class: "gl-button btn btn-default gl-mr-3 js-bulk-update-toggle"
- if show_new_issue_link?(@project)
= link_to _("New issue"), new_project_issue_path(@project,
issue: { assignee_id: finder.assignee.try(:id),
milestone_id: finder.milestones.first.try(:id) }),
- class: "btn btn-success",
+ class: "gl-button btn btn-success",
id: "new_issue_link"
- if show_export_button
- = render 'projects/issues/export_csv/modal'
+ = render 'shared/issuable/csv_export/modal', issuable_type: 'issues'
- if show_import_button
= render 'projects/issues/import_csv/modal'
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index aa95cecb5fe..34260899d94 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -29,7 +29,7 @@
- if can_create_merge_request
%li.droplab-item-selected{ role: 'button', data: { value: 'create-mr', text: create_mr_text } }
.menu-item.text-nowrap
- = icon('check', class: 'icon')
+ = sprite_icon('check', css_class: 'icon')
- if can_create_confidential_merge_request?
= _('Create confidential merge request and branch')
- else
@@ -37,7 +37,7 @@
%li{ class: [!can_create_merge_request && 'droplab-item-selected'], role: 'button', data: { value: 'create-branch', text: _('Create branch') } }
.menu-item
- = icon('check', class: 'icon')
+ = sprite_icon('check', css_class: 'icon')
= _('Create branch')
%li.divider.droplab-item-ignore
diff --git a/app/views/projects/issues/_service_desk_empty_state.html.haml b/app/views/projects/issues/_service_desk_empty_state.html.haml
index 4f004439f45..40abedea9d4 100644
--- a/app/views/projects/issues/_service_desk_empty_state.html.haml
+++ b/app/views/projects/issues/_service_desk_empty_state.html.haml
@@ -21,7 +21,7 @@
- if can_edit_project_settings && !service_desk_enabled
.text-center
- = link_to _("Turn on Service Desk"), edit_project_path(@project), class: 'btn btn-success'
+ = link_to _("Turn on Service Desk"), edit_project_path(@project), class: 'gl-button btn btn-success'
- else
.empty-state
.svg-content
diff --git a/app/views/projects/issues/_service_desk_info_content.html.haml b/app/views/projects/issues/_service_desk_info_content.html.haml
index 7fa2f3fab00..1eb427f4f7c 100644
--- a/app/views/projects/issues/_service_desk_info_content.html.haml
+++ b/app/views/projects/issues/_service_desk_info_content.html.haml
@@ -20,4 +20,4 @@
- if can_edit_project_settings && !service_desk_enabled
.gl-mt-3
- = link_to _("Turn on Service Desk"), edit_project_path(@project), class: 'btn btn-success'
+ = link_to _("Turn on Service Desk"), edit_project_path(@project), class: 'gl-button btn btn-success'
diff --git a/app/views/projects/issues/export_csv/_button.html.haml b/app/views/projects/issues/export_csv/_button.html.haml
deleted file mode 100644
index e5710fcdb60..00000000000
--- a/app/views/projects/issues/export_csv/_button.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- if current_user
- %button.csv_download_link.btn.gl-button.has-tooltip{ title: _('Export as CSV'),
- data: { toggle: 'modal', target: '.issues-export-modal', qa_selector: 'export_as_csv_button' } }
- = sprite_icon('export')
diff --git a/app/views/projects/issues/export_csv/_modal.html.haml b/app/views/projects/issues/export_csv/_modal.html.haml
deleted file mode 100644
index 6610af63445..00000000000
--- a/app/views/projects/issues/export_csv/_modal.html.haml
+++ /dev/null
@@ -1,22 +0,0 @@
-- if current_user
- .issues-export-modal.modal
- .modal-dialog
- .modal-content{ data: { qa_selector: 'export_issues_modal' } }
- .modal-header
- %h3
- = _('Export issues')
- .svg-content.import-export-svg-container
- = image_tag 'illustrations/export-import.svg', alt: _('Import/Export illustration'), class: 'illustration'
- %a.close{ href: '#', 'data-dismiss' => 'modal' }
- = sprite_icon('close', css_class: 'gl-icon')
- .modal-body
- - issues_count = issuables_count_for_state(:issues, params[:state])
- - unless issues_count == -1 # The count timed out
- .modal-subheader
- = icon('check', { class: 'checkmark' })
- %strong.gl-ml-3
- = n_('%d issue selected', '%d issues selected', issues_count) % issues_count
- .modal-text
- = html_escape(_('The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment.')) % { email: @current_user.notification_email, strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
- .modal-footer
- = link_to _('Export issues'), export_csv_project_issues_path(@project, request.query_parameters), method: :post, class: 'btn gl-button btn-success float-left', title: _('Export issues'), data: { track_label: "export_issues_csv", track_event: "click_button", track_value: "", qa_selector: "export_issues_button" }
diff --git a/app/views/projects/issues/import_csv/_modal.html.haml b/app/views/projects/issues/import_csv/_modal.html.haml
index fe4a4236896..e928a71b940 100644
--- a/app/views/projects/issues/import_csv/_modal.html.haml
+++ b/app/views/projects/issues/import_csv/_modal.html.haml
@@ -20,5 +20,5 @@
= _('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.')
= _('The maximum file size allowed is %{size}.') % { size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes) }
.modal-footer
- %button{ type: 'submit', class: 'btn btn-success', title: _('Import issues'), data: { track_label: "export_issues_csv", track_event: "click_button", track_value: ""} }
+ %button{ type: 'submit', class: 'gl-button btn btn-success', title: _('Import issues'), data: { track_label: "export_issues_csv", track_event: "click_button", track_value: ""} }
= _('Import issues')
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index 7785093466b..c3949a83e3f 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -1,103 +1,6 @@
- @content_class = "limit-container-width" unless fluid_layout
- add_to_breadcrumbs _("Issues"), project_issues_path(@project)
- breadcrumb_title @issue.to_reference
-- page_title "#{@issue.title} (#{@issue.to_reference})", _("Issues")
-- page_description @issue.description_html
-- page_card_attributes @issue.card_attributes
-- if @issue.relocation_target
- - page_canonical_link @issue.relocation_target.present(current_user: current_user).web_url
-- if @issue.sentry_issue.present?
- - add_page_specific_style 'page_bundles/error_tracking_details'
+- page_title "#{@issue.title} (#{@issue.to_reference})", _("Issues")
-- can_update_issue = can?(current_user, :update_issue, @issue)
-- can_reopen_issue = can?(current_user, :reopen_issue, @issue)
-- can_report_spam = @issue.submittable_as_spam_by?(current_user)
-- can_create_issue = show_new_issue_link?(@project)
-- related_branches_path = related_branches_project_issue_path(@project, @issue)
-
-= render_if_exists "projects/issues/alert_blocked", issue: @issue, current_user: current_user
-= render "projects/issues/alert_moved_from_service_desk", issue: @issue
-
-.detail-page-header
- .detail-page-header-body
- .issuable-status-box.status-box.status-box-issue-closed{ class: issue_status_visibility(@issue, status_box: :closed) }
- = sprite_icon('mobile-issue-close', css_class: 'd-block d-sm-none')
- .d-none.d-sm-block
- = issue_closed_text(@issue, current_user)
- .issuable-status-box.status-box.status-box-open{ class: issue_status_visibility(@issue, status_box: :open) }
- = sprite_icon('issue-open-m', css_class: 'd-block d-sm-none')
- %span.d-none.d-sm-block Open
-
- .issuable-meta
- #js-issuable-header-warnings
- = issuable_meta(@issue, @project, "Issue")
-
- %a.btn.btn-default.float-right.d-block.d-sm-none.gutter-toggle.issuable-gutter-toggle.js-sidebar-toggle{ href: "#" }
- = sprite_icon('chevron-double-lg-left')
-
- .detail-page-header-actions.js-issuable-actions.js-issuable-buttons{ data: { "action": "close-reopen" } }
- .clearfix.issue-btn-group.dropdown
- %button.btn.btn-default.float-left.d-md-none.d-lg-none.d-xl-none{ type: "button", data: { toggle: "dropdown" } }
- Options
- = icon('caret-down')
- .dropdown-menu.dropdown-menu-right.d-lg-none.d-xl-none
- %ul
- - unless current_user == @issue.author
- %li= link_to 'Report abuse', new_abuse_report_path(user_id: @issue.author.id, ref_url: issue_url(@issue))
- - if can_update_issue
- %li= link_to 'Close issue', issue_path(@issue, issue: { state_event: :close }, format: 'json'), class: "btn-close js-btn-issue-action #{issue_button_visibility(@issue, true)}", title: 'Close issue'
- - if can_reopen_issue
- %li= link_to 'Reopen issue', issue_path(@issue, issue: { state_event: :reopen }, format: 'json'), class: "btn-reopen js-btn-issue-action #{issue_button_visibility(@issue, false)}", title: 'Reopen issue'
- - if can_report_spam
- %li= link_to 'Submit as spam', mark_as_spam_project_issue_path(@project, @issue), method: :post, class: 'btn-spam', title: 'Submit as spam'
- - if can_create_issue
- - if can_update_issue || can_report_spam
- %li.divider
- %li= link_to 'New issue', new_project_issue_path(@project), id: 'new_issue_link'
-
- = render 'shared/issuable/close_reopen_button', issuable: @issue, can_update: can_update_issue, can_reopen: can_reopen_issue, warn_before_close: defined?(@issue.blocked?) && @issue.blocked?
-
- - if can_report_spam
- = link_to 'Submit as spam', mark_as_spam_project_issue_path(@project, @issue), method: :post, class: 'd-none d-sm-none d-md-block btn btn-grouped btn-spam', title: 'Submit as spam'
- - if can_create_issue
- = link_to new_project_issue_path(@project), class: 'd-none d-sm-none d-md-block btn btn-grouped btn-success btn-inverted', title: 'New issue', id: 'new_issue_link' do
- New issue
-
-.issue-details.issuable-details
- .detail-page-description.content-block
- #js-issuable-app{ data: { initial: issuable_initial_data(@issue).to_json} }
- .title-container
- %h2.title= markdown_field(@issue, :title)
- - if @issue.description.present?
- .description
- .md= markdown_field(@issue, :description)
-
- = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue-edited-ago js-issue-edited-ago')
-
- - if @issue.sentry_issue.present?
- #js-sentry-error-stack-trace{ data: error_details_data(@project, @issue.sentry_issue.sentry_issue_identifier) }
-
- = render 'projects/issues/design_management'
-
- = render_if_exists 'projects/issues/related_issues'
-
- #js-related-merge-requests{ data: { endpoint: expose_path(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid)), project_namespace: @project.namespace.path, project_path: @project.path } }
-
- - if can?(current_user, :download_code, @project)
- - add_page_startup_api_call related_branches_path
- #related-branches{ data: { url: related_branches_path } }
- -# This element is filled in using JavaScript.
-
- .content-block.emoji-block.emoji-block-sticky
- .row.gl-m-0.gl-justify-content-space-between
- .js-noteable-awards
- = render 'award_emoji/awards_block', awardable: @issue, inline: true
- .new-branch-col
- = render_if_exists "projects/issues/timeline_toggle", issue: @issue
- #js-vue-sort-issue-discussions
- #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?
-
- = render 'projects/issues/discussion'
-
-= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @issue.assignees
+= render 'projects/issuable/show', issuable: @issue
diff --git a/app/views/projects/jobs/index.html.haml b/app/views/projects/jobs/index.html.haml
index 0b4b4aafeee..a1960fc99cf 100644
--- a/app/views/projects/jobs/index.html.haml
+++ b/app/views/projects/jobs/index.html.haml
@@ -1,4 +1,5 @@
- page_title _("Jobs")
+- add_page_specific_style 'page_bundles/ci_status'
.top-area
- build_path_proc = ->(scope) { project_jobs_path(@project, scope: scope) }
diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml
index d7a778088ee..44336b95e0f 100644
--- a/app/views/projects/jobs/show.html.haml
+++ b/app/views/projects/jobs/show.html.haml
@@ -1,7 +1,9 @@
- add_to_breadcrumbs _("Jobs"), project_jobs_path(@project)
- breadcrumb_title "##{@build.id}"
- page_title "#{@build.name} (##{@build.id})", _("Jobs")
+- add_page_specific_style 'page_bundles/build'
- add_page_specific_style 'page_bundles/xterm'
+- add_page_specific_style 'page_bundles/ci_status'
= render_if_exists "shared/shared_runners_minutes_limit_flash_message"
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index 2699192adc9..357d4d193df 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -5,7 +5,7 @@
- labels_or_filters = @labels.exists? || @prioritized_labels.exists? || search.present? || subscribed.present?
- if labels_or_filters
- #promote-label-modal
+ #js-promote-label-modal
= render 'shared/labels/nav', labels_or_filters: labels_or_filters, can_admin_label: can_admin_label
.labels-container.gl-mt-3
@@ -17,7 +17,7 @@
-# Only show it in the first page
- hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1')
- .prioritized-labels{ class: [('hide' if hide), ('is-not-draggable' unless can_admin_label)] }
+ .prioritized-labels.gl-mb-7{ class: [('hide' if hide), ('is-not-draggable' unless can_admin_label)] }
%h5.gl-mt-3= _('Prioritized Labels')
.content-list.manage-labels-list.js-prioritized-labels{ data: { url: set_priorities_project_labels_path(@project), sortable: can_admin_label } }
#js-priority-labels-empty-state.priority-labels-empty-state{ class: "#{'hidden' unless @prioritized_labels.empty? && search.blank?}" }
diff --git a/app/views/projects/logs/empty_logs.html.haml b/app/views/projects/logs/empty_logs.html.haml
index afae2d30f6e..5e3db401d79 100644
--- a/app/views/projects/logs/empty_logs.html.haml
+++ b/app/views/projects/logs/empty_logs.html.haml
@@ -11,4 +11,4 @@
%p.state-description.text-center
= s_('Logs|To see the logs, deploy your code to an environment.')
.text-center
- = link_to s_('Environments|Learn about environments'), help_page_path('ci/environments/index.md'), class: 'btn btn-success'
+ = link_to s_('Environments|Learn about environments'), help_page_path('ci/environments/index.md'), class: 'gl-button btn btn-success'
diff --git a/app/views/projects/mattermosts/_no_teams.html.haml b/app/views/projects/mattermosts/_no_teams.html.haml
index 0377cd6586e..00efea81f8f 100644
--- a/app/views/projects/mattermosts/_no_teams.html.haml
+++ b/app/views/projects/mattermosts/_no_teams.html.haml
@@ -9,8 +9,8 @@
To install this service,
= link_to "#{Gitlab.config.mattermost.host}/select_team", target: '__blank' do
join a team
- = icon('external-link')
+ = sprite_icon('external-link')
and try again.
%hr
.clearfix
- = link_to 'Go back', edit_project_service_path(@project, @service), class: 'btn btn-lg float-right'
+ = link_to 'Go back', edit_project_service_path(@project, @service), class: 'gl-button btn btn-lg float-right'
diff --git a/app/views/projects/mattermosts/_team_selection.html.haml b/app/views/projects/mattermosts/_team_selection.html.haml
index d0a7f89df31..ea04a55a77c 100644
--- a/app/views/projects/mattermosts/_team_selection.html.haml
+++ b/app/views/projects/mattermosts/_team_selection.html.haml
@@ -19,7 +19,7 @@
To create a team,
= link_to "#{Gitlab.config.mattermost.host}/create_team" do
use Mattermost's interface
- = icon('external-link')
+ = sprite_icon('external-link')
or ask your Mattermost system administrator.
%hr
%h4 Command trigger word
@@ -38,9 +38,9 @@
Reserved:
= link_to 'https://docs.mattermost.com/help/messaging/executing-commands.html#built-in-commands', target: '__blank' do
see list of built-in slash commands
- = icon('external-link')
+ = sprite_icon('external-link')
%hr
.clearfix
.float-right
- = link_to 'Cancel', edit_project_service_path(@project, @service), class: 'btn btn-lg'
- = f.submit 'Install', class: 'btn btn-success btn-lg'
+ = link_to 'Cancel', edit_project_service_path(@project, @service), class: 'gl-button btn btn-lg'
+ = f.submit 'Install', class: 'gl-button btn btn-success btn-lg'
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index b56e2c3f985..cd4ffa8602e 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -25,10 +25,10 @@
.detail-page-header-actions.js-issuable-actions
.clearfix.issue-btn-group.dropdown
- %button.btn.btn-default.float-left.d-md-none.d-lg-none.d-xl-none{ type: "button", data: { toggle: "dropdown" } }
+ %button.btn.btn-default.float-left.d-md-none{ type: "button", data: { toggle: "dropdown" } }
Options
= icon('caret-down')
- .dropdown-menu.dropdown-menu-right.d-lg-none.d-xl-none
+ .dropdown-menu.dropdown-menu-right
%ul
- if can_update_merge_request
%li= link_to 'Edit', edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)
@@ -41,10 +41,10 @@
- if can_reopen_merge_request
%li{ class: merge_request_button_visibility(@merge_request, false) }
= link_to 'Reopen', merge_request_path(@merge_request, merge_request: { state_event: :reopen }), method: :put, class: 'reopen-mr-link', title: 'Reopen merge request'
- - unless current_user == @merge_request.author
+ - unless @merge_request.merged? || current_user == @merge_request.author
%li= link_to 'Report abuse', new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request))
- if can_update_merge_request
- = link_to 'Edit', edit_project_merge_request_path(@project, @merge_request), class: "d-none d-sm-none d-md-block btn gl-button btn-grouped js-issuable-edit qa-edit-button"
+ = link_to 'Edit', edit_project_merge_request_path(@project, @merge_request), class: "d-none d-md-block btn gl-button btn-grouped js-issuable-edit qa-edit-button"
= render 'shared/issuable/close_reopen_button', issuable: @merge_request, can_update: can_update_merge_request, can_reopen: can_reopen_merge_request
diff --git a/app/views/projects/merge_requests/_nav_btns.html.haml b/app/views/projects/merge_requests/_nav_btns.html.haml
index 2ef10365c18..473490c6c35 100644
--- a/app/views/projects/merge_requests/_nav_btns.html.haml
+++ b/app/views/projects/merge_requests/_nav_btns.html.haml
@@ -1,5 +1,10 @@
+.btn-group
+ = render 'shared/issuable/csv_export/button', issuable_type: 'merge-requests'
+
- if @can_bulk_update
- = button_tag "Edit merge requests", class: "btn gl-mr-3 js-bulk-update-toggle"
+ = button_tag "Edit merge requests", class: "gl-button btn gl-mr-3 js-bulk-update-toggle"
- if merge_project
- = link_to new_merge_request_path, class: "btn btn-success", title: "New merge request" do
+ = link_to new_merge_request_path, class: "gl-button btn btn-success", title: "New merge request" do
New merge request
+
+ = render 'shared/issuable/csv_export/modal', issuable_type: 'merge_requests'
diff --git a/app/views/projects/merge_requests/conflicts/_submit_form.html.haml b/app/views/projects/merge_requests/conflicts/_submit_form.html.haml
index 55c89f137c5..94c262d300e 100644
--- a/app/views/projects/merge_requests/conflicts/_submit_form.html.haml
+++ b/app/views/projects/merge_requests/conflicts/_submit_form.html.haml
@@ -21,4 +21,4 @@
%button.btn.btn-success.js-submit-button{ type: "button", "@click" => "commit()", ":disabled" => "!readyToCommit" }
%span {{commitButtonText}}
.col-6.text-right
- = link_to "Cancel", project_merge_request_path(@merge_request.project, @merge_request), class: "btn btn-cancel"
+ = link_to "Cancel", project_merge_request_path(@merge_request.project, @merge_request), class: "gl-button btn btn-cancel"
diff --git a/app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml b/app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml
index 3ca82adccf1..7294c5d321a 100644
--- a/app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml
+++ b/app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml
@@ -7,7 +7,4 @@
%button.btn.btn-sm.btn-close{ "@click" => "acceptDiscardConfirmation(file)" } Discard changes
%button.btn.btn-sm{ "@click" => "cancelDiscardConfirmation(file)" } Cancel
.editor-wrap{ ":class" => "classObject" }
- .loading
- .spinner.spinner-md
- .editor
- %pre{ "style" => "height: 350px" }
+ .editor{ "style" => "height: 350px", data: { 'editor-loading': true } }
diff --git a/app/views/projects/merge_requests/conflicts/show.html.haml b/app/views/projects/merge_requests/conflicts/show.html.haml
index a7ffe825139..decdbce3fa7 100644
--- a/app/views/projects/merge_requests/conflicts/show.html.haml
+++ b/app/views/projects/merge_requests/conflicts/show.html.haml
@@ -1,7 +1,5 @@
- page_title _("Merge Conflicts"), "#{@merge_request.title} (#{@merge_request.to_reference}", _("Merge Requests")
- add_page_specific_style 'page_bundles/merge_conflicts'
-- content_for :page_specific_javascripts do
- = page_specific_javascript_tag('lib/ace.js')
= render "projects/merge_requests/mr_title"
.merge-request-details.issuable-details
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 f0a68512326..2cb75d43d4b 100644
--- a/app/views/projects/merge_requests/creations/_new_compare.html.haml
+++ b/app/views/projects/merge_requests/creations/_new_compare.html.haml
@@ -4,7 +4,6 @@
= form_for [@project, @merge_request], url: project_new_merge_request_path(@project), method: :get, html: { class: "merge-request-form js-requires-input" } do |f|
- if params[:nav_source].present?
= hidden_field_tag(:nav_source, params[:nav_source])
- .hide.alert.alert-danger.mr-compare-errors
.js-merge-request-new-compare.row{ 'data-source-branch-url': project_new_merge_request_branch_from_path(@source_project), 'data-target-branch-url': project_new_merge_request_branch_to_path(@source_project) }
.col-lg-6
.card.card-new-merge-request
@@ -65,4 +64,4 @@
- if @merge_request.errors.any?
= form_errors(@merge_request)
- = f.submit 'Compare branches and continue', class: "btn btn-success mr-compare-btn"
+ = f.submit 'Compare branches and continue', class: "gl-button btn btn-success mr-compare-btn"
diff --git a/app/views/projects/merge_requests/creations/new.html.haml b/app/views/projects/merge_requests/creations/new.html.haml
index 4c968c8e8eb..0741b24a5a1 100644
--- a/app/views/projects/merge_requests/creations/new.html.haml
+++ b/app/views/projects/merge_requests/creations/new.html.haml
@@ -2,6 +2,7 @@
- breadcrumb_title _("New")
- page_title _("New Merge Request")
- add_page_specific_style 'page_bundles/pipelines'
+- add_page_specific_style 'page_bundles/ci_status'
- if @merge_request.can_be_created && !params[:change_branches]
= render 'new_submit'
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index 1dbcd613ceb..6b506c38795 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -11,6 +11,7 @@
- add_page_specific_style 'page_bundles/merge_requests'
- add_page_specific_style 'page_bundles/pipelines'
- add_page_specific_style 'page_bundles/reports'
+- add_page_specific_style 'page_bundles/ci_status'
.merge-request{ data: { mr_action: mr_action, url: merge_request_path(@merge_request, format: :json), project_path: project_path(@merge_request.project), lock_version: @merge_request.lock_version } }
= render "projects/merge_requests/mr_title"
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index 907af326ec5..a21f519da0e 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -22,7 +22,7 @@
.form-actions
- if @milestone.new_record?
= f.submit _('Create milestone'), class: 'btn-success btn', data: { qa_selector: 'create_milestone_button' }
- = link_to _('Cancel'), project_milestones_path(@project), class: 'btn btn-cancel'
+ = link_to _('Cancel'), project_milestones_path(@project), class: 'gl-button btn btn-cancel'
- else
= f.submit _('Save changes'), class: 'btn-success btn'
- = link_to _('Cancel'), project_milestone_path(@project, @milestone), class: 'btn btn-cancel'
+ = link_to _('Cancel'), project_milestone_path(@project, @milestone), class: 'gl-button btn btn-cancel'
diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml
index 2c52d2a5fbc..b964c8b1a93 100644
--- a/app/views/projects/milestones/index.html.haml
+++ b/app/views/projects/milestones/index.html.haml
@@ -8,7 +8,7 @@
= render 'shared/milestones/search_form'
= render 'shared/milestones_sort_dropdown'
- if can?(current_user, :admin_milestone, @project)
- = link_to new_project_milestone_path(@project), class: 'btn btn-success', data: { qa_selector: "new_project_milestone_link" }, title: _('New milestone') do
+ = link_to new_project_milestone_path(@project), class: 'gl-button btn btn-success', data: { qa_selector: "new_project_milestone_link" }, title: _('New milestone') do
= _('New milestone')
.milestones
diff --git a/app/views/projects/mirrors/_authentication_method.html.haml b/app/views/projects/mirrors/_authentication_method.html.haml
index dae0fa958ba..88bd7da7fef 100644
--- a/app/views/projects/mirrors/_authentication_method.html.haml
+++ b/app/views/projects/mirrors/_authentication_method.html.haml
@@ -7,7 +7,7 @@
= f.select :auth_method,
options_for_select(auth_options, mirror.auth_method),
{}, { class: "form-control select-control js-mirror-auth-type qa-authentication-method" }
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
= f.hidden_field :auth_method, value: "password", class: "js-hidden-mirror-auth-type"
.form-group
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index d2847de6ece..5b074ff8a28 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -33,7 +33,7 @@
= link_to sprite_icon('question-o'), help_page_path('user/project/protected_branches'), target: '_blank'
.panel-footer
- = f.submit _('Mirror repository'), class: 'btn btn-success js-mirror-submit qa-mirror-repository-button', name: :update_remote_mirror
+ = f.submit _('Mirror repository'), class: 'gl-button btn btn-success js-mirror-submit qa-mirror-repository-button', name: :update_remote_mirror
- else
.gl-alert.gl-alert-info{ role: 'alert' }
= sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
@@ -72,6 +72,6 @@
- if mirror_settings_enabled
.btn-group.mirror-actions-group.float-right{ role: 'group' }
- 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')
+ = clipboard_button(text: mirror.ssh_public_key, class: 'gl-button 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.gl-button.btn-danger{ type: 'button', data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' }, title: _('Remove') }= sprite_icon('remove')
+ %button.js-delete-mirror.qa-delete-mirror.rspec-delete-mirror.btn.btn-icon.gl-button.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_form.html.haml b/app/views/projects/mirrors/_mirror_repos_form.html.haml
index dd794e03f48..215d0a59d1b 100644
--- a/app/views/projects/mirrors/_mirror_repos_form.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos_form.html.haml
@@ -2,6 +2,6 @@
= label_tag :mirror_direction, _('Mirror direction'), class: 'label-light'
.select-wrapper
= select_tag :mirror_direction, options_for_select([[_('Push'), 'push']]), class: 'form-control select-control js-mirror-direction qa-mirror-direction', disabled: true
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
= render partial: "projects/mirrors/mirror_repos_push", locals: { f: f }
diff --git a/app/views/projects/mirrors/_ssh_host_keys.html.haml b/app/views/projects/mirrors/_ssh_host_keys.html.haml
index 1690188f07a..4e3cd609d75 100644
--- a/app/views/projects/mirrors/_ssh_host_keys.html.haml
+++ b/app/views/projects/mirrors/_ssh_host_keys.html.haml
@@ -14,7 +14,7 @@
%code= fp.fingerprint
- if verified_at
.form-text.text-muted.js-fingerprint-verification
- %i.fa.fa-check.fingerprint-verified
+ = sprite_icon('check', css_class: 'gl-text-green-500')
Verified by
- if verified_by
= link_to verified_by.name, user_path(verified_by)
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index d5099f80ea4..f2972a9617b 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -4,7 +4,7 @@
- header_title _("Projects"), dashboard_projects_path
- active_tab = local_assigns.fetch(:active_tab, 'blank')
-.project-edit-container.gl-mt-3
+.project-edit-container.gl-mt-5
.project-edit-errors
= render 'projects/errors'
diff --git a/app/views/projects/no_repo.html.haml b/app/views/projects/no_repo.html.haml
index c44d3da23bb..65c4232b240 100644
--- a/app/views/projects/no_repo.html.haml
+++ b/app/views/projects/no_repo.html.haml
@@ -1,9 +1,10 @@
- breadcrumb_title _("Details")
- page_title _("Details")
-%h2
- %i.fa.fa-warning
- #{ _('No repository') }
+%h2.gl-display-flex
+ .gl-display-flex.gl-align-items-center.gl-justify-content-center
+ = sprite_icon('warning-solid', size: 24, css_class: 'gl-mr-2')
+ = _('No repository')
%p.slead
#{ _('The repository for this project does not exist.') }
@@ -11,6 +12,8 @@
#{ _('This means you can not push code until you create an empty repository or import existing one.') }
%hr
+= render_if_exists 'projects/invite_members_modal', project: @project
+
.no-repo-actions
= link_to project_repository_path(@project), method: :post, class: 'btn btn-primary' do
#{ _('Create empty repository') }
diff --git a/app/views/projects/pages/_ssl_limitations_warning.html.haml b/app/views/projects/pages/_ssl_limitations_warning.html.haml
index 7188e169824..1f2907d183e 100644
--- a/app/views/projects/pages/_ssl_limitations_warning.html.haml
+++ b/app/views/projects/pages/_ssl_limitations_warning.html.haml
@@ -1,5 +1,5 @@
.bs-callout.bs-callout-warning
- %i.fa.fa-warning
+ = sprite_icon("warning-solid", css_class: "gl-text-orange-600")
%strong= _("Warning:")
- pages_host = Gitlab.config.pages.host
= s_("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.").html_safe % { pages_host: pages_host }
diff --git a/app/views/projects/pages_domains/_dns.html.haml b/app/views/projects/pages_domains/_dns.html.haml
index 8e2a9c3bab4..dc8127ab068 100644
--- a/app/views/projects/pages_domains/_dns.html.haml
+++ b/app/views/projects/pages_domains/_dns.html.haml
@@ -30,4 +30,4 @@
= clipboard_button(target: '#domain_verification', class: 'btn-default d-none d-sm-block')
%p.form-text.text-muted
- link_to_help = link_to(_('verify ownership'), help_page_path('user/project/pages/custom_domains_ssl_tls_certification/index.md', anchor: '4-verify-the-domains-ownership'))
- = _("To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration.").html_safe % { link_to_help: link_to_help }
+ = _("To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration.").html_safe % { link_to_help: link_to_help }
diff --git a/app/views/projects/pages_domains/_lets_encrypt_callout.html.haml b/app/views/projects/pages_domains/_lets_encrypt_callout.html.haml
index a86637c36b3..9072312c100 100644
--- a/app/views/projects/pages_domains/_lets_encrypt_callout.html.haml
+++ b/app/views/projects/pages_domains/_lets_encrypt_callout.html.haml
@@ -6,7 +6,7 @@
.col-sm-10.offset-sm-2
.bs-callout.bs-callout-warning.mt-0
.row.align-items-center.mx-2
- = icon('warning', class: 'mr-2')
+ = sprite_icon('warning-solid', css_class: ' mr-2 gl-text-orange-600')
= _("Something went wrong while obtaining the Let's Encrypt certificate.")
.row.mx-0.mt-3
= link_to s_('GitLabPagesDomains|Retry'), retry_auto_ssl_project_pages_domain_path(@project, domain_presenter), class: "btn btn-sm btn-grouped btn-warning", method: :post
diff --git a/app/views/projects/pages_domains/show.html.haml b/app/views/projects/pages_domains/show.html.haml
index 20ecf948447..54522a70f4a 100644
--- a/app/views/projects/pages_domains/show.html.haml
+++ b/app/views/projects/pages_domains/show.html.haml
@@ -6,7 +6,7 @@
- if verification_enabled && domain_presenter.unverified?
= content_for :flash_message do
- .alert.alert-warning
+ .gl-alert.gl-alert-warning
.container-fluid.container-limited
= _("This domain is not verified. You will need to verify ownership before access is enabled.")
diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml
index 1a8229350d9..ee0fe43e79c 100644
--- a/app/views/projects/pipeline_schedules/_form.html.haml
+++ b/app/views/projects/pipeline_schedules/_form.html.haml
@@ -39,5 +39,5 @@
= f.check_box :active, required: false, value: @schedule.active?
= f.label :active, _('Active'), class: 'gl-font-weight-normal'
.footer-block.row-content-block
- = f.submit _('Save pipeline schedule'), class: 'btn btn-success', tabindex: 3
+ = f.submit _('Save pipeline schedule'), class: 'btn btn-success'
= link_to _('Cancel'), pipeline_schedules_path(@project), class: 'btn btn-cancel'
diff --git a/app/views/projects/pipeline_schedules/edit.html.haml b/app/views/projects/pipeline_schedules/edit.html.haml
index d95fa6da903..29896500ea1 100644
--- a/app/views/projects/pipeline_schedules/edit.html.haml
+++ b/app/views/projects/pipeline_schedules/edit.html.haml
@@ -1,6 +1,7 @@
- add_to_breadcrumbs _("Schedules"), pipeline_schedules_path(@project)
- breadcrumb_title "##{@schedule.id}"
- page_title _("Edit"), @schedule.description, _("Pipeline Schedule")
+- add_page_specific_style 'page_bundles/pipeline_schedules'
%h3.page-title
= _("Edit Pipeline Schedule %{id}") % { id: @schedule.id }
diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml
index 91083cc0768..a52a6138402 100644
--- a/app/views/projects/pipeline_schedules/index.html.haml
+++ b/app/views/projects/pipeline_schedules/index.html.haml
@@ -1,8 +1,8 @@
- breadcrumb_title _("Schedules")
-
- page_title _("Pipeline Schedules")
+- add_page_specific_style 'page_bundles/pipeline_schedules'
-#pipeline-schedules-callout{ data: { docs_url: help_page_path('ci/pipelines/schedules'), image_url: image_path('illustrations/pipeline_schedule_callout.svg') } }
+#pipeline-schedules-callout{ data: { docs_url: help_page_path('ci/pipelines/schedules'), illustration_url: image_path('illustrations/pipeline_schedule_callout.svg') } }
.top-area
- schedule_path_proc = ->(scope) { pipeline_schedules_path(@project, scope: scope) }
= render "tabs", schedule_path_proc: schedule_path_proc, all_schedules: @all_schedules, scope: @scope
diff --git a/app/views/projects/pipeline_schedules/new.html.haml b/app/views/projects/pipeline_schedules/new.html.haml
index cfdaf6d43bb..a2652304768 100644
--- a/app/views/projects/pipeline_schedules/new.html.haml
+++ b/app/views/projects/pipeline_schedules/new.html.haml
@@ -1,6 +1,7 @@
- breadcrumb_title "Schedules"
- @breadcrumb_link = namespace_project_pipeline_schedules_path(@project.namespace, @project)
- page_title _("New Pipeline Schedule")
+- add_page_specific_style 'page_bundles/pipeline_schedules'
- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index 6d3b3f815e4..f77f22cc555 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -42,7 +42,7 @@
toggle: "popover",
placement: "top",
html: "true",
- trigger: "focus",
+ triggers: "focus",
title: "<div class='gl-font-weight-normal gl-line-height-normal'>#{popover_title_text}</div>",
content: "<a href='#{popover_content_url}' target='_blank' rel='noopener noreferrer nofollow'>#{popover_content_text}</a>",
} }
@@ -57,12 +57,7 @@
.well-segment.branch-info
.icon-container.commit-icon
= custom_icon("icon_commit")
- = link_to commit.short_id, project_commit_path(@project, @pipeline.sha), class: "commit-sha js-details-short"
- = link_to("#", class: "js-details-expand d-none d-md-inline") do
- %span.text-expander
- = sprite_icon('ellipsis_h', size: 12)
- %span.js-details-content.hide
- = link_to @pipeline.sha, project_commit_path(@project, @pipeline.sha), class: "commit-sha commit-hash-full"
+ = link_to commit.short_id, project_commit_path(@project, @pipeline.sha), class: "commit-sha"
= clipboard_button(text: @pipeline.sha, title: _("Copy commit SHA"))
.well-segment.related-merge-request-info
diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml
index 40a52f76641..8955b568741 100644
--- a/app/views/projects/pipelines/_with_tabs.html.haml
+++ b/app/views/projects/pipelines/_with_tabs.html.haml
@@ -9,7 +9,7 @@
- if dag_pipeline_tab_enabled
%li.js-dag-tab-link
= link_to dag_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-dag', action: 'dag', toggle: 'tab' }, class: 'dag-tab' do
- = _('DAG')
+ = _('Needs')
%li.js-builds-tab-link
= link_to builds_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-builds', action: 'builds', toggle: 'tab' }, class: 'builds-tab' do
= _('Jobs')
@@ -81,7 +81,7 @@
- if dag_pipeline_tab_enabled
#js-tab-dag.tab-pane
- #js-pipeline-dag-vue{ data: { pipeline_project_path: @project.full_path, pipeline_iid: @pipeline.iid, empty_svg_path: image_path('illustrations/empty-state/empty-dag-md.svg'), dag_doc_path: help_page_path('ci/yaml/README.md', anchor: 'needs')} }
+ #js-pipeline-dag-vue{ data: { pipeline_project_path: @project.full_path, pipeline_iid: @pipeline.iid, empty_svg_path: image_path('illustrations/empty-state/empty-dag-md.svg'), about_dag_doc_path: help_page_path('ci/directed_acyclic_graph/index.md'), dag_doc_path: help_page_path('ci/yaml/README.md', anchor: 'needs')} }
#js-tab-tests.tab-pane
#js-pipeline-tests-detail{ data: { summary_endpoint: summary_project_pipeline_tests_path(@project, @pipeline, format: :json),
diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml
index ca07f33136b..6aa1a564499 100644
--- a/app/views/projects/pipelines/index.html.haml
+++ b/app/views/projects/pipelines/index.html.haml
@@ -1,5 +1,6 @@
- page_title _('Pipelines')
- add_page_specific_style 'page_bundles/pipelines'
+- add_page_specific_style 'page_bundles/ci_status'
= render_if_exists "shared/shared_runners_minutes_limit_flash_message"
diff --git a/app/views/projects/pipelines/new.html.haml b/app/views/projects/pipelines/new.html.haml
index cb5401cd329..bc8e6a6d9cc 100644
--- a/app/views/projects/pipelines/new.html.haml
+++ b/app/views/projects/pipelines/new.html.haml
@@ -6,7 +6,7 @@
= s_('Pipeline|Run Pipeline')
%hr
-- if Feature.enabled?(:new_pipeline_form, @project)
+- if Feature.enabled?(:new_pipeline_form, @project, default_enabled: true)
#js-new-pipeline{ data: { project_id: @project.id,
pipelines_path: project_pipelines_path(@project),
config_variables_path: config_variables_namespace_project_pipelines_path(@project.namespace, @project),
@@ -48,7 +48,7 @@
= (s_("Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default.") % {settings_link: settings_link}).html_safe
.form-actions
- = f.submit s_('Pipeline|Run Pipeline'), class: 'btn btn-success js-variables-save-button', tabindex: 3
+ = f.submit s_('Pipeline|Run Pipeline'), class: 'btn btn-success js-variables-save-button'
= link_to _('Cancel'), project_pipelines_path(@project), class: 'btn btn-default float-right'
%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 34f7744f825..0b07fe9921e 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -4,9 +4,10 @@
- pipeline_has_errors = @pipeline.builds.empty? && @pipeline.yaml_errors.present?
- add_page_specific_style 'page_bundles/pipeline'
- add_page_specific_style 'page_bundles/reports'
+- add_page_specific_style 'page_bundles/ci_status'
.js-pipeline-container{ data: { controller_action: "#{controller.action_name}" } }
- #js-pipeline-header-vue.pipeline-header-container{ data: {full_path: @project.full_path, retry_path: retry_project_pipeline_path(@pipeline.project, @pipeline), cancel_path: cancel_project_pipeline_path(@pipeline.project, @pipeline), delete_path: project_pipeline_path(@pipeline.project, @pipeline), pipeline_iid: @pipeline.iid, pipeline_id: @pipeline.id} }
+ #js-pipeline-header-vue.pipeline-header-container{ data: { full_path: @project.full_path, pipeline_iid: @pipeline.iid, pipeline_id: @pipeline.id, pipelines_path: project_pipelines_path(@project) } }
- if @pipeline.commit.present?
= render "projects/pipelines/info", commit: @pipeline.commit
diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml
index 4d4705c4ed5..171212b6a96 100644
--- a/app/views/projects/project_members/_team.html.haml
+++ b/app/views/projects/project_members/_team.html.haml
@@ -1,5 +1,7 @@
- project = local_assigns.fetch(:project)
- members = local_assigns.fetch(:members)
+- group = local_assigns.fetch(:group)
+- current_user_is_group_owner = group && group.has_owner?(current_user)
.card
.card-header.flex-project-members-panel
@@ -14,5 +16,9 @@
= sprite_icon('search', css_class: 'gl-vertical-align-middle!')
= label_tag :sort_by, _('Sort by'), class: 'col-form-label label-bold px-2'
= render 'shared/members/sort_dropdown'
- %ul.content-list.members-list{ data: { qa_selector: 'members_list' } }
- = render partial: 'shared/members/member', collection: members, as: :member
+ %ul.content-list.members-list{ data: { qa_selector: 'members_list', testid: 'members-table' } }
+ = render partial: 'shared/members/member',
+ collection: members, as: :member,
+ locals: { membership_source: project,
+ group: group,
+ current_user_is_group_owner: current_user_is_group_owner }
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index 9a1e997fce7..cad76d7aeac 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -1,5 +1,6 @@
- page_title _("Members")
- can_admin_project_members = can?(current_user, :admin_project_member, @project)
+- group = @project.group
.js-remove-member-modal
.row.gl-mt-3
@@ -32,12 +33,12 @@
- elsif @project.allowed_to_share_with_group?
.invite-group= render 'shared/members/invite_group', access_levels: ProjectGroupLink.access_options, default_access_level: ProjectGroupLink.default_access, submit_url: project_group_links_path(@project), group_link_field: 'link_group_id', group_access_field: 'link_group_access'
- = render 'shared/members/requests', membership_source: @project, requesters: @requesters
+ = render 'shared/members/requests', membership_source: @project, group: group, requesters: @requesters
.clearfix
%h5.member.existing-title
= _("Existing members and groups")
- if @group_links.any?
= render 'projects/project_members/groups', group_links: @group_links
- = render 'projects/project_members/team', project: @project, members: @project_members
+ = render 'projects/project_members/team', project: @project, group: group, members: @project_members
= paginate @project_members, theme: "gitlab"
diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml
index 74b6e981c00..1a3ba690184 100644
--- a/app/views/projects/runners/_runner.html.haml
+++ b/app/views/projects/runners/_runner.html.haml
@@ -37,8 +37,8 @@
- if runner.description.present?
%p.runner-description
= runner.description
- - if runner.tag_list.present?
+ - if runner.tags.present?
%p
- - runner.tag_list.sort.each do |tag|
+ - runner.tags.map(&:name).sort.each do |tag|
%span.badge.badge-primary
= tag
diff --git a/app/views/projects/runners/_specific_runners.html.haml b/app/views/projects/runners/_specific_runners.html.haml
index 4cc67a8f5d8..e02e2cc784a 100644
--- a/app/views/projects/runners/_specific_runners.html.haml
+++ b/app/views/projects/runners/_specific_runners.html.haml
@@ -9,15 +9,18 @@
= render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: @project.runners_token,
type: 'specific',
- reset_token_url: reset_registration_token_namespace_project_settings_ci_cd_path }
+ reset_token_url: reset_registration_token_namespace_project_settings_ci_cd_path,
+ project_path: @project.path_with_namespace,
+ group_path: '' }
- if @project_runners.any?
%h4.underlined-title= _('Runners activated for this project')
%ul.bordered-list.activated-specific-runners
= render partial: 'projects/runners/runner', collection: @project_runners, as: :runner
+ = paginate @project_runners, theme: "gitlab", param_name: "project_page", params: { expand_runners: true, anchor: 'js-runners-settings' }
- if @assignable_runners.any?
%h4.underlined-title= _('Available specific runners')
%ul.bordered-list.available-specific-runners
= render partial: 'projects/runners/runner', collection: @assignable_runners, as: :runner
- = paginate @assignable_runners, theme: "gitlab", :params => { :anchor => '#js-runners-settings' }
+ = paginate @assignable_runners, theme: "gitlab", param_name: "specific_page", :params => { :anchor => 'js-runners-settings'}
diff --git a/app/views/projects/services/prometheus/_metrics.html.haml b/app/views/projects/services/prometheus/_metrics.html.haml
index 732a084d476..4bafd4d06e0 100644
--- a/app/views/projects/services/prometheus/_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_metrics.html.haml
@@ -25,7 +25,8 @@
.card.hidden.js-panel-missing-env-vars
.card-header
- = icon('caret-right lg fw', class: 'panel-toggle js-panel-toggle', 'aria-label' => 'Toggle panel')
+ = sprite_icon('chevron-lg-right', css_class: 'panel-toggle js-panel-toggle-right' )
+ = sprite_icon('chevron-lg-down', css_class: 'panel-toggle js-panel-toggle-down hidden' )
= s_('PrometheusService|Missing environment variable')
%span.badge.badge-pill.js-env-var-count 0
.card-body.hidden
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index 4793e685163..d247e73a5b4 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -72,7 +72,7 @@
%li
= _("For public projects, anyone can view pipelines and access job details (output logs and artifacts)")
%li
- = _("For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)")
+ = _("For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)")
%li
= _("For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)")
%p
@@ -120,6 +120,9 @@
pytest-cov (Python) -
%code ^TOTAL.+?(\d+\%)$
%li
+ Scoverage (Scala) -
+ %code Statement coverage[A-Za-z\.*]\s*:\s*([^%]+)
+ %li
phpunit --coverage-text --colors=never (PHP) -
%code ^\s*Lines:\s*\d+.\d+\%
%li
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index 8e3be5fa086..f6ecb923100 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -33,7 +33,7 @@
= render_if_exists 'projects/settings/ci_cd/protected_environments', expanded: expanded
-%section.settings.no-animate#js-runners-settings{ class: ('expanded' if expanded), data: { qa_selector: 'runners_settings_content' } }
+%section.settings.no-animate#js-runners-settings{ class: ('expanded' if expanded || params[:expand_runners]), data: { qa_selector: 'runners_settings_content' } }
.settings-header
%h4
= _("Runners")
@@ -75,6 +75,8 @@
.settings-content
= render 'projects/registry/settings/index'
+= render_if_exists 'projects/settings/ci_cd/auto_rollback', expanded: expanded
+
- if can?(current_user, :create_freeze_period, @project)
%section.settings.no-animate#js-deploy-freeze-settings{ class: ('expanded' if expanded) }
.settings-header
diff --git a/app/views/projects/settings/operations/_alert_management.html.haml b/app/views/projects/settings/operations/_alert_management.html.haml
index 5c16a5e2758..9e76ad52ecb 100644
--- a/app/views/projects/settings/operations/_alert_management.html.haml
+++ b/app/views/projects/settings/operations/_alert_management.html.haml
@@ -1,5 +1,6 @@
- return unless can?(current_user, :admin_operations, @project)
- expanded = expanded_by_default?
+- add_page_specific_style 'page_bundles/alert_management_settings'
%section.settings.no-animate#js-alert-management-settings{ class: ('expanded' if expanded) }
.settings-header
diff --git a/app/views/projects/settings/operations/_error_tracking.html.haml b/app/views/projects/settings/operations/_error_tracking.html.haml
index 62b344b38f1..6ab8beff99f 100644
--- a/app/views/projects/settings/operations/_error_tracking.html.haml
+++ b/app/views/projects/settings/operations/_error_tracking.html.haml
@@ -1,4 +1,4 @@
-- return unless can?(current_user, :read_environment, @project)
+- return unless can?(current_user, :admin_operations, @project)
- setting = error_tracking_setting
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 67bdcd0d9d6..f7c51e9ada9 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -1,5 +1,4 @@
- breadcrumb_title _("Details")
-- page_title _("Projects")
- @content_class = "limit-container-width" unless fluid_layout
= content_for :meta_tags do
diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml
index d7231e758c7..7679e0714fe 100644
--- a/app/views/projects/tags/_tag.html.haml
+++ b/app/views/projects/tags/_tag.html.haml
@@ -1,5 +1,6 @@
- commit = @repository.commit(tag.dereferenced_target)
- release = @releases.find { |release| release.tag == tag.name }
+- commit_status = @tag_pipeline_statuses[tag.name] unless @tag_pipeline_statuses.nil?
%li.flex-row.allow-wrap.js-tag-list
.row-main-content
@@ -34,6 +35,12 @@
- if tag.has_signature?
= render partial: 'projects/commit/signature', object: tag.signature
+ - if commit_status
+ = render 'ci/status/icon', size: 24, status: commit_status, option_css_classes: 'gl-display-inline-flex gl-vertical-align-middle gl-mr-5'
+ - elsif @tag_pipeline_statuses && @tag_pipeline_statuses.any?
+ .gl-display-inline-flex.gl-vertical-align-middle.gl-mr-5
+ %svg.s24
+
= render 'projects/buttons/download', project: @project, ref: tag.name, pipeline: @tags_pipelines[tag.name]
- if can?(current_user, :admin_tag, @project)
diff --git a/app/views/projects/terraform/index.html.haml b/app/views/projects/terraform/index.html.haml
new file mode 100644
index 00000000000..136e7ded224
--- /dev/null
+++ b/app/views/projects/terraform/index.html.haml
@@ -0,0 +1,4 @@
+- breadcrumb_title _('Terraform')
+- page_title _('Terraform')
+
+#js-terraform-list{ data: js_terraform_list_data(@project) }
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index dc9fb9e7792..cd6e85d60ed 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -13,7 +13,7 @@
= render 'shared/web_ide_button', blob: nil
- if show_xcode_link?(@project)
- .project-action-button.project-xcode.inline<
+ .project-action-button.project-xcode<
= render "projects/buttons/xcode_link"
= render 'projects/buttons/download', project: @project, ref: @ref
diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml
index 4d8c357cee1..355277b7d41 100644
--- a/app/views/projects/tree/show.html.haml
+++ b/app/views/projects/tree/show.html.haml
@@ -1,5 +1,7 @@
- current_route_path = request.fullpath.match(/-\/tree\/[^\/]+\/(.+$)/).to_a[1]
-- add_page_startup_graphql_call('repository/path_last_commit', { projectPath: @project.full_path, ref: current_ref, path: current_route_path })
+- add_page_startup_graphql_call('repository/path_last_commit', { projectPath: @project.full_path, ref: current_ref, path: current_route_path || "" })
+- add_page_startup_graphql_call('repository/permissions', { projectPath: @project.full_path })
+- add_page_startup_graphql_call('repository/files', { nextPageCursor: "", pageSize: 100, projectPath: @project.full_path, ref: current_ref, path: current_route_path || "/"})
- breadcrumb_title _("Repository")
- @content_class = "limit-container-width" unless fluid_layout
diff --git a/app/views/registrations/welcome.html.haml b/app/views/registrations/welcome.html.haml
deleted file mode 100644
index bebcc2152af..00000000000
--- a/app/views/registrations/welcome.html.haml
+++ /dev/null
@@ -1,25 +0,0 @@
-- 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 gl-button btn btn-block gl-mb-0 gl-p-3', data: { qa_selector: 'get_started_button' }
diff --git a/app/views/registrations/welcome/show.html.haml b/app/views/registrations/welcome/show.html.haml
new file mode 100644
index 00000000000..278c0ff7739
--- /dev/null
+++ b/app/views/registrations/welcome/show.html.haml
@@ -0,0 +1,25 @@
+- page_title _('Your profile')
+
+.row.gl-flex-grow-1
+ .d-flex.gl-flex-direction-column.gl-align-items-center.gl-w-full.gl-p-5
+ .edit-profile.login-page.d-flex.flex-column.gl-align-items-center.pt-lg-3
+ = render_if_exists "registrations/welcome/progress_bar"
+ %h2.gl-text-center= html_escape(_('Welcome to GitLab%{br_tag}%{name}!')) % { name: html_escape(current_user.first_name), br_tag: '<br/>'.html_safe }
+ %p
+ .gl-text-center= html_escape(_('In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you.')) % { br_tag: '<br/>'.html_safe }
+
+ = form_for(current_user, url: users_sign_up_welcome_path, html: { class: 'card gl-w-full! gl-p-5', 'aria-live' => 'assertive' }) do |f|
+ .devise-errors
+ = render 'devise/shared/error_messages', resource: current_user
+ .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 gl-button btn btn-block gl-mb-0 gl-p-3', data: { qa_selector: 'get_started_button' }
diff --git a/app/views/search/_filter.html.haml b/app/views/search/_filter.html.haml
index e7febd4638b..964a2a2772a 100644
--- a/app/views/search/_filter.html.haml
+++ b/app/views/search/_filter.html.haml
@@ -2,25 +2,14 @@
= hidden_field_tag :group_id, params[:group_id]
- if params[:project_id].present?
= hidden_field_tag :project_id, params[:project_id]
-.dropdown.form-group.mb-lg-0.mx-lg-1{ data: { testid: "group-filter" } }
+.dropdown.form-group.mb-lg-0.mx-lg-1.gl-p-0{ data: { testid: "group-filter" } }
%label.d-block{ for: "dashboard_search_group" }
= _("Group")
- %button.dropdown-menu-toggle.gl-display-inline-flex.js-search-group-dropdown.gl-mt-0{ type: "button", id: "dashboard_search_group", data: { toggle: "dropdown", group_id: params[:group_id] } }
- %span.dropdown-toggle-text.gl-flex-grow-1.str-truncated-100
- = @group&.name || _("Any")
- - if @group.present?
- = link_to sprite_icon("clear"), url_for(safe_params.except(:project_id, :group_id)), class: 'search-clear js-search-clear has-tooltip', title: _('Clear')
- = icon("chevron-down")
- .dropdown-menu.dropdown-select.dropdown-menu-selectable.dropdown-menu-right
- = dropdown_title(_("Filter results by group"))
- = dropdown_filter(_("Search groups"))
- = dropdown_content
- = dropdown_loading
-
-.dropdown.project-filter.form-group.mb-lg-0.mx-lg-1
+ %input#js-search-group-dropdown.dropdown-menu-toggle{ value: "Loading...", data: { "initial-group-data": @group.to_json } }
+.dropdown.form-group.mb-lg-0.mx-lg-1{ data: { testid: "project-filter" } }
%label.d-block{ for: "dashboard_search_project" }
= _("Project")
- %button.dropdown-menu-toggle.gl-display-inline-flex.js-search-project-dropdown.gl-mt-0{ type: "button", id: "dashboard_search_project", data: { toggle: "dropdown", target: '.project-filter' } }
+ %button.dropdown-menu-toggle.gl-display-inline-flex.js-search-project-dropdown.gl-mt-0{ type: "button", id: "dashboard_search_project", data: { toggle: "dropdown" } }
%span.dropdown-toggle-text.gl-flex-grow-1.str-truncated-100
= @project&.full_name || _("Any")
- if @project.present?
diff --git a/app/views/search/_form.html.haml b/app/views/search/_form.html.haml
index c8fa016662f..80973c2b273 100644
--- a/app/views/search/_form.html.haml
+++ b/app/views/search/_form.html.haml
@@ -17,4 +17,4 @@
- unless params[:snippets].eql? 'true'
= render 'filter'
.d-flex-center.flex-column.flex-lg-row
- = button_tag _("Search"), class: "btn btn-success btn-search form-control mt-lg-0 ml-lg-1 align-self-end"
+ = button_tag _("Search"), class: "gl-button btn btn-success btn-search form-control mt-lg-0 ml-lg-1 align-self-end"
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index 95c378bff7c..855112bdba2 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -1,38 +1,47 @@
- if @search_objects.to_a.empty?
- = render partial: "search/results/filters"
- = render partial: "search/results/empty"
- = render_if_exists 'shared/promotions/promote_advanced_search'
+ .gl-display-md-flex
+ - if %w(issues merge_requests).include?(@scope)
+ #js-search-sidebar.gl-display-flex.gl-flex-direction-column.col-md-3.gl-mr-4{ }
+ .gl-w-full
+ = render partial: "search/results/empty"
+ = render_if_exists 'shared/promotions/promote_advanced_search'
- else
- .row-content-block.d-md-flex.text-left.align-items-center
- - unless @search_objects.is_a?(Kaminari::PaginatableWithoutCount)
- = search_entries_info(@search_objects, @scope, @search_term)
- - unless @show_snippets
- - if @project
- - link_to_project = link_to(@project.full_name, @project, class: 'ml-md-1')
- - if @scope == 'blobs'
- = s_("SearchCodeResults|in")
- .mx-md-1
- = render partial: "shared/ref_switcher", locals: { ref: repository_ref(@project), form_path: request.fullpath, field_name: 'repository_ref' }
- = s_('SearchCodeResults|of %{link_to_project}').html_safe % { link_to_project: link_to_project }
- - else
- = _("in project %{link_to_project}").html_safe % { link_to_project: link_to_project }
- - elsif @group
- - link_to_group = link_to(@group.name, @group, class: 'ml-md-1')
- = _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group }
+ .search-results-status
+ .row-content-block.gl-display-flex
+ .gl-display-md-flex.gl-text-left.gl-align-items-center.gl-flex-grow-1
+ - unless @search_objects.is_a?(Kaminari::PaginatableWithoutCount)
+ = search_entries_info(@search_objects, @scope, @search_term)
+ - unless @show_snippets
+ - if @project
+ - link_to_project = link_to(@project.full_name, @project, class: 'ml-md-1')
+ - if @scope == 'blobs'
+ = s_("SearchCodeResults|in")
+ .mx-md-1
+ = render partial: "shared/ref_switcher", locals: { ref: repository_ref(@project), form_path: request.fullpath, field_name: 'repository_ref' }
+ = s_('SearchCodeResults|of %{link_to_project}').html_safe % { link_to_project: link_to_project }
+ - else
+ = _("in project %{link_to_project}").html_safe % { link_to_project: link_to_project }
+ - elsif @group
+ - link_to_group = link_to(@group.name, @group, class: 'ml-md-1')
+ = _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group }
+ .gl-display-md-flex.gl-flex-direction-column
+ = render partial: 'search/sort_dropdown'
= render_if_exists 'shared/promotions/promote_advanced_search'
- = render partial: "search/results/filters"
- .results.gl-mt-3
- - if @scope == 'commits'
- %ul.content-list.commit-list
- = render partial: "search/results/commit", collection: @search_objects
- - else
- .search-results
- - if @scope == 'projects'
- .term
- = render 'shared/projects/list', projects: @search_objects, pipeline_status: false
- - else
- = render_if_exists partial: "search/results/#{@scope.singularize}", collection: @search_objects
+ .results.gl-display-md-flex.gl-mt-3
+ - if %w(issues merge_requests).include?(@scope)
+ #js-search-sidebar.gl-display-flex.gl-flex-direction-column.col-md-3.gl-mr-4{ }
+ .gl-w-full
+ - if @scope == 'commits'
+ %ul.content-list.commit-list
+ = render partial: "search/results/commit", collection: @search_objects
+ - else
+ .search-results
+ - if @scope == 'projects'
+ .term
+ = render 'shared/projects/list', projects: @search_objects, pipeline_status: false
+ - else
+ = render_if_exists partial: "search/results/#{@scope.singularize}", collection: @search_objects
- - if @scope != 'projects'
- = paginate_collection(@search_objects)
+ - if @scope != 'projects'
+ = paginate_collection(@search_objects)
diff --git a/app/views/search/_sort_dropdown.html.haml b/app/views/search/_sort_dropdown.html.haml
new file mode 100644
index 00000000000..085e2f348f7
--- /dev/null
+++ b/app/views/search/_sort_dropdown.html.haml
@@ -0,0 +1,16 @@
+- return unless ['issues', 'merge_requests'].include?(@scope)
+
+- sort_value = @sort
+- sort_title = search_sort_option_title(sort_value)
+
+.dropdown.gl-display-inline-block.gl-ml-3.filter-dropdown-container
+ .btn-group{ role: 'group' }
+ .btn-group{ role: 'group' }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' }, class: 'btn btn-default' }
+ = sort_title
+ = icon('chevron-down')
+ %ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort
+ %li
+ = render_if_exists('search/sort_by_relevancy', sort_title: sort_title)
+ = sortable_item(sort_title_recently_created, page_filter_path(sort: sort_value_recently_created), sort_title)
+ = search_sort_direction_button(sort_value)
diff --git a/app/views/search/results/_blob_data.html.haml b/app/views/search/results/_blob_data.html.haml
index d873a15d051..16d640273b0 100644
--- a/app/views/search/results/_blob_data.html.haml
+++ b/app/views/search/results/_blob_data.html.haml
@@ -7,4 +7,4 @@
= search_blob_title(project, path)
- if blob.data
.file-content.code.term{ data: { qa_selector: 'file_text_content' } }
- = render 'shared/file_highlight', blob: blob, first_line_number: blob.startline, blob_link: blob_link
+ = render 'shared/file_highlight', blob: blob, first_line_number: blob.startline, blob_link: blob_link, highlight_line: blob.highlight_line
diff --git a/app/views/search/results/_empty.html.haml b/app/views/search/results/_empty.html.haml
index 3cd1c901f8e..0462c29f5c1 100644
--- a/app/views/search/results/_empty.html.haml
+++ b/app/views/search/results/_empty.html.haml
@@ -1,5 +1,5 @@
-.search_box
+.search_box.gl-my-8
.search_glyph
%h4
= sprite_icon('search', size: 24, css_class: 'gl-vertical-align-text-bottom')
- = search_entries_empty_message(@scope, @search_term)
+ = search_entries_empty_message(@scope, @search_term, @group, @project)
diff --git a/app/views/search/results/_filters.html.haml b/app/views/search/results/_filters.html.haml
deleted file mode 100644
index 632d3dfd58c..00000000000
--- a/app/views/search/results/_filters.html.haml
+++ /dev/null
@@ -1,7 +0,0 @@
-.d-lg-flex.align-items-end
- #js-search-filter-by-state{ 'v-cloak': true }
- - if Feature.enabled?(:search_filter_by_confidential, @group)
- #js-search-filter-by-confidential{ 'v-cloak': true }
-
- - if %w(issues merge_requests).include?(@scope)
- %hr.gl-mt-4.gl-mb-4
diff --git a/app/views/search/results/_issuable.html.haml b/app/views/search/results/_issuable.html.haml
new file mode 100644
index 00000000000..288ac53a954
--- /dev/null
+++ b/app/views/search/results/_issuable.html.haml
@@ -0,0 +1,10 @@
+%div{ class: 'search-result-row gl-pb-3! gl-mt-5 gl-mb-0!' }
+ %span.gl-display-flex.gl-align-items-center
+ %span.badge.badge-pill.gl-badge.sm{ class: "badge-#{issuable_state_to_badge_class(issuable)}" }= issuable_state_text(issuable)
+ = sprite_icon('eye-slash', css_class: 'gl-text-gray-500 gl-ml-2') if issuable.respond_to?(:confidential?) && issuable.confidential?
+ = link_to issuable_path(issuable), data: { track_event: 'click_text', track_label: "#{issuable.class.name.downcase}_title", track_property: 'search_result' }, class: 'gl-w-full' do
+ %span.term.str-truncated.gl-font-weight-bold.gl-ml-2= issuable.title
+ .gl-text-gray-500.gl-my-3
+ = sprintf(s_(' %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}'), { project_name: issuable.project.full_name, issuable_iid: issuable.iid, issuable_created: time_ago_with_tooltip(issuable.created_at, placement: 'bottom'), author: link_to_member(@project, issuable.author, avatar: false) }).html_safe
+ .description.term.col-sm-10.gl-px-0
+ = highlight_and_truncate_issuable(issuable, @search_term, @search_highlight)
diff --git a/app/views/search/results/_issue.html.haml b/app/views/search/results/_issue.html.haml
index a101e60f297..6fb463b75fc 100644
--- a/app/views/search/results/_issue.html.haml
+++ b/app/views/search/results/_issue.html.haml
@@ -1,13 +1 @@
-%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-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
- .description.term.col-sm-10.gl-px-0
- = highlight_and_truncate_issue(issue, @search_term, @search_highlight)
+= render partial: 'search/results/issuable', object: issue
diff --git a/app/views/search/results/_merge_request.html.haml b/app/views/search/results/_merge_request.html.haml
index 3135ab9a17e..b2b067bcf68 100644
--- a/app/views/search/results/_merge_request.html.haml
+++ b/app/views/search/results/_merge_request.html.haml
@@ -1,14 +1 @@
-.search-result-row
- %h4
- = 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")
- - elsif merge_request.closed?
- %span.badge.badge-danger.gl-ml-2= _("Closed")
- .float-right= merge_request.to_reference
- - if merge_request.description.present?
- .description.term
- = search_md_sanitize(merge_request.description)
- %span.light
- #{merge_request.project.full_name}
+= render partial: 'search/results/issuable', object: merge_request
diff --git a/app/views/search/results/_wiki_blob.html.haml b/app/views/search/results/_wiki_blob.html.haml
index 3040917dd6e..55161ce333b 100644
--- a/app/views/search/results/_wiki_blob.html.haml
+++ b/app/views/search/results/_wiki_blob.html.haml
@@ -1,4 +1,9 @@
- project = wiki_blob.project
- wiki_blob_link = project_wiki_path(project, wiki_blob.basename)
-= render partial: 'search/results/blob_data', locals: { blob: wiki_blob, project: project, path: wiki_blob.path, blob_link: wiki_blob_link }
+%div{ class: 'search-result-row gl-pb-3! gl-mt-5 gl-mb-0!' }
+ %span.gl-display-flex.gl-align-items-center
+ = link_to wiki_blob_link, data: { track_event: 'click_text', track_label: "wiki_title", track_property: 'search_result' }, class: 'gl-w-full' do
+ %span.term.str-truncated.gl-font-weight-bold= ::Gitlab::Git::Wiki::GollumSlug.canonicalize_filename(wiki_blob.path)
+ .description.term.col-sm-10.gl-px-0
+ = simple_search_highlight_and_truncate(wiki_blob.data, @search_term)
diff --git a/app/views/sent_notifications/unsubscribe.html.haml b/app/views/sent_notifications/unsubscribe.html.haml
index 2ad29707c9f..a286693e2b6 100644
--- a/app/views/sent_notifications/unsubscribe.html.haml
+++ b/app/views/sent_notifications/unsubscribe.html.haml
@@ -15,5 +15,5 @@
%p
= link_to _('Unsubscribe'), unsubscribe_sent_notification_path(@sent_notification, force: true),
- class: 'btn btn-primary gl-mr-3'
- = link_to _('Cancel'), new_user_session_path, class: 'btn gl-mr-3'
+ class: 'gl-button btn btn-primary gl-mr-3'
+ = link_to _('Cancel'), new_user_session_path, class: 'gl-button btn gl-mr-3'
diff --git a/app/views/shared/_broadcast_message.html.haml b/app/views/shared/_broadcast_message.html.haml
index 7be11b0fb81..7aaae3a88f3 100644
--- a/app/views/shared/_broadcast_message.html.haml
+++ b/app/views/shared/_broadcast_message.html.haml
@@ -8,5 +8,5 @@
= render_broadcast_message(message)
.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.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!')
+ %button.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-mx-3! #{is_banner ? 'gl-text-white' : 'gl-text-gray-700'}")
diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml
index 7d328728332..b1f53e4d0f6 100644
--- a/app/views/shared/_file_highlight.html.haml
+++ b/app/views/shared/_file_highlight.html.haml
@@ -1,16 +1,17 @@
#blob-content.file-content.code.js-syntax-highlight
+ - offset = defined?(first_line_number) ? first_line_number : 1
.line-numbers
- if blob.data.present?
- link_icon = sprite_icon('link', size: 12)
- link = blob_link if defined?(blob_link)
- blob.data.each_line.each_with_index do |_, index|
- - offset = defined?(first_line_number) ? first_line_number : 1
- i = index + offset
-# We're not using `link_to` because it is too slow once we get to thousands of lines.
%a.diff-line-num{ href: "#{link}#L#{i}", id: "L#{i}", 'data-line-number' => i }
= link_icon
= i
- .blob-content{ data: { blob_id: blob.id, path: blob.path } }
+ - highlight = defined?(highlight_line) && highlight_line ? highlight_line - offset : nil
+ .blob-content{ data: { blob_id: blob.id, path: blob.path, highlight_line: highlight, qa_selector: 'file_content' } }
%pre.code.highlight
%code
= blob.present.highlight
diff --git a/app/views/shared/_issuable_meta_data.html.haml b/app/views/shared/_issuable_meta_data.html.haml
index f21ec45eefb..352d51dbb8e 100644
--- a/app/views/shared/_issuable_meta_data.html.haml
+++ b/app/views/shared/_issuable_meta_data.html.haml
@@ -6,7 +6,7 @@
- if issuable_mr > 0
%li.issuable-mr.gl-display-none.gl-display-sm-block.has-tooltip{ title: _('Related merge requests') }
- = image_tag('icon-merge-request-unmerged.svg', class: 'icon-merge-request-unmerged')
+ = sprite_icon('merge-request', css_class: "gl-vertical-align-middle")
= issuable_mr
- if upvotes > 0
diff --git a/app/views/shared/_label.html.haml b/app/views/shared/_label.html.haml
index 1dadb4384b9..4b09e8de896 100644
--- a/app/views/shared/_label.html.haml
+++ b/app/views/shared/_label.html.haml
@@ -34,10 +34,7 @@
label_title: label.title,
label_color: label.color,
label_text_color: label.text_color,
- group_name: label.project.group.name,
- target: '#promote-label-modal',
- container: 'body',
- toggle: 'modal' } }
+ group_name: label.project.group.name } }
= _('Promote to group label')
- if can?(current_user, :admin_label, label)
%li
diff --git a/app/views/shared/_label_row.html.haml b/app/views/shared/_label_row.html.haml
index 9c9ac5f7b2c..252f9c26f06 100644
--- a/app/views/shared/_label_row.html.haml
+++ b/app/views/shared/_label_row.html.haml
@@ -5,9 +5,9 @@
.label-name.gl-flex-shrink-0.gl-mt-2.gl-mr-3
= render_label(label, tooltip: false)
-.label-description.gl-flex-grow-1.gl-overflow-hidden
- .gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-mt-2
- .description-text.gl-flex-grow-1.gl-overflow-hidden
+.label-description.gl-overflow-hidden.gl-w-full
+ .gl-display-flex.gl-align-items-stretch.gl-flex-wrap.gl-mt-2
+ .gl-flex-basis-half.gl-flex-grow-1.gl-overflow-hidden.gl-mr-2
- if label.description.present?
= markdown_field(label, :description)
- elsif show_labels_full_path?(@project, @group)
diff --git a/app/views/shared/_ping_consent.html.haml b/app/views/shared/_ping_consent.html.haml
index ded9b55056a..d0f1e4d7221 100644
--- a/app/views/shared/_ping_consent.html.haml
+++ b/app/views/shared/_ping_consent.html.haml
@@ -1,12 +1,14 @@
- if session[:ask_for_usage_stats_consent]
- .ping-consent-message.alert.alert-warning.flex-alert
- - settings_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="alert-link">'.html_safe % { url: metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings') }
- - info_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="alert-link">'.html_safe % { url: help_page_path('user/admin_area/settings/usage_statistics.md') }
- .alert-message
- = s_('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}').html_safe % { settings_link_start: settings_link_start, info_link_start: info_link_start, link_end: '</a>'.html_safe }
- .alert-link-group
+ .ping-consent-message.gl-alert.gl-alert-info
+ = sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
+ = sprite_icon('close', css_class: 'gl-icon')
+ .gl-alert-body
+ - docs_link = link_to _('collect usage information'), help_page_path('user/admin_area/settings/usage_statistics.md'), class: 'gl-link'
+ - settings_link = link_to _('your settings'), metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings'), class: 'gl-link'
+ = s_('To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}.').html_safe % { docs_link: docs_link, settings_link: settings_link }
+ .gl-alert-actions.gl-mt-3
- send_usage_data_path = admin_application_settings_path(application_setting: { version_check_enabled: 1, usage_ping_enabled: 1 })
- not_now_path = admin_application_settings_path(application_setting: { version_check_enabled: 0, usage_ping_enabled: 0 })
- = link_to _("Send usage data"), send_usage_data_path, 'data-url' => admin_application_settings_path, method: :put, 'data-check-enabled': true, 'data-ping-enabled': true, class: 'alert-link js-usage-consent-action'
- |
- = link_to _('Not now'), not_now_path, 'data-url' => admin_application_settings_path, method: :put, 'data-check-enabled': false, 'data-ping-enabled': false, class: 'hide-ping-consent-message alert-link js-usage-consent-action'
+ = link_to _("Send usage data"), send_usage_data_path, 'data-url' => admin_application_settings_path, method: :put, 'data-check-enabled': true, 'data-ping-enabled': true, class: 'js-usage-consent-action alert-link btn gl-button btn-info'
+ = link_to _("Don't send usage data"), not_now_path, 'data-url' => admin_application_settings_path, method: :put, 'data-check-enabled': false, 'data-ping-enabled': false, class: 'js-usage-consent-action alert-link btn gl-button btn-default gl-ml-2'
diff --git a/app/views/shared/_remote_mirror_update_button.html.haml b/app/views/shared/_remote_mirror_update_button.html.haml
index 54bd4ba04a0..70b72f74ab3 100644
--- a/app/views/shared/_remote_mirror_update_button.html.haml
+++ b/app/views/shared/_remote_mirror_update_button.html.haml
@@ -1,6 +1,6 @@
- if remote_mirror.update_in_progress?
- %button.btn.disabled{ type: 'button', data: { toggle: 'tooltip', container: 'body', qa_selector: 'updating_button' }, title: _('Updating') }
- = icon("refresh spin")
+ %button.btn.btn-icon.gl-button.disabled{ type: 'button', data: { toggle: 'tooltip', container: 'body', qa_selector: 'updating_button' }, title: _('Updating') }
+ = sprite_icon("retry", css_class: "spin")
- elsif remote_mirror.enabled?
- = link_to update_now_project_mirror_path(@project, sync_remote: true), method: :post, class: "btn qa-update-now-button rspec-update-now-button", data: { toggle: 'tooltip', container: 'body' }, title: _('Update now') do
- = icon("refresh")
+ = link_to update_now_project_mirror_path(@project, sync_remote: true), method: :post, class: "btn btn-icon gl-button qa-update-now-button rspec-update-now-button", data: { toggle: 'tooltip', container: 'body' }, title: _('Update now') do
+ = sprite_icon("retry")
diff --git a/app/views/shared/access_tokens/_form.html.haml b/app/views/shared/access_tokens/_form.html.haml
index 820a6cbd15d..f206a2152c2 100644
--- a/app/views/shared/access_tokens/_form.html.haml
+++ b/app/views/shared/access_tokens/_form.html.haml
@@ -13,7 +13,7 @@
.row
.form-group.col-md-6
= f.label :name, _('Name'), class: 'label-bold'
- = f.text_field :name, class: 'form-control', required: true, data: { qa_selector: 'access_token_name_field' }
+ = f.text_field :name, class: 'form-control gl-form-input', required: true, data: { qa_selector: 'access_token_name_field' }
.row
.form-group.col-md-6
@@ -23,8 +23,7 @@
= render_if_exists 'personal_access_tokens/callout_max_personal_access_token_lifetime'
.js-access-tokens-expires-at
- %expires-at-field
- = f.text_field :expires_at, class: 'datepicker form-control gl-datepicker-input', placeholder: 'YYYY-MM-DD', autocomplete: 'off', inputmode: 'none', data: { qa_selector: 'expiry_date_field' }
+ = f.text_field :expires_at, class: 'datepicker gl-datepicker-input form-control gl-form-input', placeholder: 'YYYY-MM-DD', autocomplete: 'off'
.form-group
= f.label :scopes, _('Scopes'), class: 'label-bold'
diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml
index c3137120034..ce48691166b 100644
--- a/app/views/shared/boards/_show.html.haml
+++ b/app/views/shared/boards/_show.html.haml
@@ -15,10 +15,9 @@
%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"
+= render 'shared/issuable/search_bar', type: :boards, board: 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) || Feature.enabled?(:graphql_board_lists, current_board_parent)
+ - if Feature.enabled?(:boards_with_swimlanes, current_board_parent, default_enabled: true) || Feature.enabled?(:graphql_board_lists, current_board_parent)
%board-content{ "v-cloak" => "true",
"ref" => "board_content",
":lists" => "state.lists",
diff --git a/app/views/shared/boards/components/sidebar/_assignee.html.haml b/app/views/shared/boards/components/sidebar/_assignee.html.haml
index af6a519a967..e22a7807b3b 100644
--- a/app/views/shared/boards/components/sidebar/_assignee.html.haml
+++ b/app/views/shared/boards/components/sidebar/_assignee.html.haml
@@ -23,7 +23,7 @@
%button.dropdown-menu-toggle.js-user-search.js-author-search.js-multiselect.js-save-user-data.js-issue-board-sidebar{ type: 'button', ref: 'assigneeDropdown', data: board_sidebar_user_data,
":data-issuable-id" => "issue.iid" }
= dropdown_options[:title]
- = icon("chevron-down")
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-user.dropdown-menu-selectable.dropdown-menu-author
= dropdown_title("Assign to")
= dropdown_filter("Search users")
diff --git a/app/views/shared/boards/components/sidebar/_due_date.html.haml b/app/views/shared/boards/components/sidebar/_due_date.html.haml
index d8ed3b13bf1..ab4d22ac03d 100644
--- a/app/views/shared/boards/components/sidebar/_due_date.html.haml
+++ b/app/views/shared/boards/components/sidebar/_due_date.html.haml
@@ -24,7 +24,7 @@
%button.dropdown-menu-toggle.js-due-date-select.js-issue-boards-due-date{ type: 'button',
data: { toggle: 'dropdown', field_name: "issue[due_date]", ability_name: "issue" } }
%span.dropdown-toggle-text= _("Due date")
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-menu-due-date
= dropdown_title(_('Due date'))
= dropdown_content do
diff --git a/app/views/shared/boards/components/sidebar/_labels.html.haml b/app/views/shared/boards/components/sidebar/_labels.html.haml
index 61f3ebcdba4..5af52d4de23 100644
--- a/app/views/shared/boards/components/sidebar/_labels.html.haml
+++ b/app/views/shared/boards/components/sidebar/_labels.html.haml
@@ -27,7 +27,7 @@
data: label_dropdown_data(@project, namespace_path: @namespace_path, field_name: "issue[label_names][]") }
%span.dropdown-toggle-text
{{ labelDropdownTitle }}
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable.dropdown-extended-height
= render partial: "shared/issuable/label_page_default"
- if can?(current_user, :admin_label, current_board_parent)
diff --git a/app/views/shared/boards/components/sidebar/_milestone.html.haml b/app/views/shared/boards/components/sidebar/_milestone.html.haml
index 2c894e9b1b3..6143f1d5afe 100644
--- a/app/views/shared/boards/components/sidebar/_milestone.html.haml
+++ b/app/views/shared/boards/components/sidebar/_milestone.html.haml
@@ -21,7 +21,7 @@
":data-issuable-id" => "issue.iid",
":data-project-id" => "issue.project_id" }
= _("Milestone")
- = icon("chevron-down")
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-selectable
= dropdown_title(_("Assign milestone"))
= dropdown_filter(_("Search milestones"))
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 b1edfba6df4..73be0c741dc 100644
--- a/app/views/shared/form_elements/_apply_template_warning.html.haml
+++ b/app/views/shared/form_elements/_apply_template_warning.html.haml
@@ -1,6 +1,5 @@
-.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
-
+.form-group.row.js-template-warning.hidden.js-issuable-template-warning
+ .col-sm-12
.warning_message.mb-0{ role: 'alert' }
%btn.js-close-btn.js-dismiss-btn.close{ type: "button", "aria-hidden": true, "aria-label": _("Close") }
= sprite_icon("close")
diff --git a/app/views/shared/form_elements/_description.html.haml b/app/views/shared/form_elements/_description.html.haml
index 413df29da77..7f4aed5d1f7 100644
--- a/app/views/shared/form_elements/_description.html.haml
+++ b/app/views/shared/form_elements/_description.html.haml
@@ -14,6 +14,9 @@
- if model.is_a?(Issuable)
= render 'shared/issuable/form/template_selector', issuable: model
+
+ = render 'shared/form_elements/apply_template_warning', issuable: model
+
= render layout: 'shared/md_preview', locals: { url: preview_url, referenced_users: true } do
= render 'shared/zen', f: form, attr: :description,
classes: 'note-textarea qa-issuable-form-description rspec-issuable-form-description',
diff --git a/app/views/shared/groups/_empty_state.html.haml b/app/views/shared/groups/_empty_state.html.haml
index f6b3a49eacb..1d3bc1d6959 100644
--- a/app/views/shared/groups/_empty_state.html.haml
+++ b/app/views/shared/groups/_empty_state.html.haml
@@ -1,8 +1,13 @@
-.group-empty-state.row.align-items-center.justify-content-center
- .icon.text-center.order-md-2
+.row.gl-align-items-center.gl-justify-content-center
+ .order-md-2
= custom_icon("icon_empty_groups")
- .text-content.m-0.order-md-1
+ .text-content.order-md-1{ class: 'gl-m-0!' }
%h4= s_("GroupsEmptyState|A group is a collection of several projects.")
%p= s_("GroupsEmptyState|If you organize your projects under a group, it works like a folder.")
%p= s_("GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group.")
+ - if invite_group_members?(@group)
+ = link_to _('Invite your team'),
+ group_group_members_path(@group),
+ class: 'gl-button btn btn-success-secondary',
+ data: { track_event: 'click_invite_team_group_empty_state', track_label: 'invite_team_group_empty_state' }
diff --git a/app/views/shared/groups/_search_form.html.haml b/app/views/shared/groups/_search_form.html.haml
index 49b812baefc..a574394694d 100644
--- a/app/views/shared/groups/_search_form.html.haml
+++ b/app/views/shared/groups/_search_form.html.haml
@@ -1,2 +1,2 @@
= form_tag request.path, method: :get, class: "group-filter-form js-group-filter-form", id: 'group-filter-form' do |f|
- = search_field_tag :filter, params[:filter], placeholder: s_('GroupsTree|Search by name'), class: 'group-filter-form-field form-control js-groups-list-filter qa-groups-filter', spellcheck: false, id: 'group-filter-form-field', tabindex: "2"
+ = search_field_tag :filter, params[:filter], placeholder: s_('GroupsTree|Search by name'), class: 'group-filter-form-field form-control js-groups-list-filter qa-groups-filter', spellcheck: false, id: 'group-filter-form-field'
diff --git a/app/views/shared/issuable/_close_reopen_button.html.haml b/app/views/shared/issuable/_close_reopen_button.html.haml
index 8365bc6f863..3453db9f209 100644
--- a/app/views/shared/issuable/_close_reopen_button.html.haml
+++ b/app/views/shared/issuable/_close_reopen_button.html.haml
@@ -21,5 +21,6 @@
- else
= render 'shared/issuable/close_reopen_report_toggle', issuable: issuable, warn_before_close: add_blocked_class
- else
- = link_to _('Report abuse'), new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)),
- class: 'd-none d-md-block btn btn-grouped btn-close-color', title: _('Report abuse')
+ - unless issuable.is_a?(MergeRequest) && issuable.merged?
+ = link_to _('Report abuse'), new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)),
+ class: 'd-none d-md-block btn btn-grouped btn-close-color', title: _('Report abuse')
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 df441e6d0af..48d1e146629 100644
--- a/app/views/shared/issuable/_close_reopen_report_toggle.html.haml
+++ b/app/views/shared/issuable/_close_reopen_report_toggle.html.haml
@@ -21,7 +21,7 @@
data: { text: _("Close %{display_issuable_type}") % { display_issuable_type: display_issuable_type }, url: close_issuable_path(issuable),
button_class: "#{button_class} btn-close", toggle_class: "#{toggle_class} btn-close-color" } }
%button.btn.btn-transparent
- = icon('check', class: 'icon')
+ = sprite_icon('check', css_class: 'icon')
.description
%strong.title
= _('Close')
@@ -31,7 +31,7 @@
data: { text: _("Reopen %{display_issuable_type}") % { display_issuable_type: display_issuable_type }, url: reopen_issuable_path(issuable),
button_class: "#{button_class} btn-reopen", toggle_class: "#{toggle_class} btn-reopen-color" } }
%button.btn.btn-transparent
- = icon('check', class: 'icon')
+ = sprite_icon('check', css_class: 'icon')
.description
%strong.title
= _('Reopen')
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 728b527f499..c0aba0eef7f 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -20,8 +20,6 @@
= 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', issuable: issuable
-
= render 'shared/issuable/form/type_selector', issuable: issuable, form: form
= render 'shared/form_elements/description', model: issuable, form: form, project: project
diff --git a/app/views/shared/issuable/_label_dropdown.html.haml b/app/views/shared/issuable/_label_dropdown.html.haml
index 535af522c1a..08883bb3372 100644
--- a/app/views/shared/issuable/_label_dropdown.html.haml
+++ b/app/views/shared/issuable/_label_dropdown.html.haml
@@ -26,7 +26,7 @@
- apply_is_default_styles = (selected.nil? || selected.empty?) && !no_default_styles
%span.dropdown-toggle-text{ class: ("is-default" if apply_is_default_styles) }
= multi_label_name(selected, label_name)
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable.dropdown-extended-height
= render partial: "shared/issuable/label_page_default", locals: { title: dropdown_title, show_footer: show_footer, show_create: show_create }
- if show_create && project && can?(current_user, :admin_label, project)
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index ae79d5e3c3e..00b235809ed 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -96,6 +96,7 @@
%li.filter-dropdown-item
%button.btn.btn-link.js-data-value{ type: 'button' }
{{title}}
+ = render_if_exists 'shared/issuable/filter_iteration', type: type
#js-dropdown-release.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'None' } }
@@ -181,7 +182,7 @@
= render 'shared/issuable/board_create_list_dropdown', board: board
- if @project
#js-add-issues-btn.gl-ml-3{ data: { can_admin_list: can?(current_user, :admin_list, @project) } }
- - if current_user && Feature.enabled?(:boards_with_swimlanes, @group)
+ - if current_user && Feature.enabled?(:boards_with_swimlanes, @group, default_enabled: true)
#js-board-epics-swimlanes-toggle
#js-toggle-focus-btn
- elsif is_not_boards_modal_or_productivity_analytics && show_sorting_dropdown
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 458703ebc5f..1f20c1a30aa 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -96,24 +96,14 @@
%button.dropdown-menu-toggle.js-due-date-select{ type: 'button', data: { toggle: 'dropdown', field_name: "#{issuable_type}[due_date]", ability_name: issuable_type, issue_update: issuable_sidebar[:issuable_json_path], display: 'static' } }
%span.dropdown-toggle-text
= _('Due date')
- = icon('chevron-down', 'aria-hidden': 'true')
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-menu-due-date
= dropdown_title(_('Due date'))
= dropdown_content do
.js-due-date-calendar
- .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 } }
+ .js-sidebar-labels{ data: sidebar_labels_data(issuable_sidebar, @project) }
= render_if_exists 'shared/issuable/sidebar_weight', issuable_sidebar: issuable_sidebar
diff --git a/app/views/shared/issuable/_sort_dropdown.html.haml b/app/views/shared/issuable/_sort_dropdown.html.haml
index 81dbecb430b..f60be3f3e4a 100644
--- a/app/views/shared/issuable/_sort_dropdown.html.haml
+++ b/app/views/shared/issuable/_sort_dropdown.html.haml
@@ -7,7 +7,7 @@
.btn-group{ role: 'group' }
%button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' }, class: 'btn btn-default' }
= sort_title
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort
%li
= sortable_item(sort_title_priority, page_filter_path(sort: sort_value_priority), sort_title)
diff --git a/app/views/shared/issuable/csv_export/_button.html.haml b/app/views/shared/issuable/csv_export/_button.html.haml
new file mode 100644
index 00000000000..3584c9c1ed5
--- /dev/null
+++ b/app/views/shared/issuable/csv_export/_button.html.haml
@@ -0,0 +1,4 @@
+- if current_user
+ %button.csv_download_link.btn.gl-button.has-tooltip{ title: _('Export as CSV'),
+ data: { toggle: 'modal', target: ".#{issuable_type}-export-modal", qa_selector: 'export_as_csv_button' } }
+ = sprite_icon('export')
diff --git a/app/views/shared/issuable/csv_export/_modal.html.haml b/app/views/shared/issuable/csv_export/_modal.html.haml
new file mode 100644
index 00000000000..4a4c6b90cd9
--- /dev/null
+++ b/app/views/shared/issuable/csv_export/_modal.html.haml
@@ -0,0 +1,29 @@
+- class_name = "#{issuable_type.dasherize}-export-modal"
+- if current_user
+ .modal.issuable-export-modal{ class: class_name }
+ .modal-dialog
+ .modal-content{ data: { qa_selector: "export_issuable_modal" } }
+ .modal-header
+ %h3
+ = _("Export %{issuable_type}" % { issuable_type: issuable_type.humanize(capitalize: false) })
+ .svg-content.import-export-svg-container
+ = image_tag 'illustrations/export-import.svg', role: "presentation", class: 'illustration'
+ %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
+ = sprite_icon('close', css_class: 'gl-icon')
+ .modal-body
+ - issuable_count = issuables_count_for_state(issuable_type.to_sym, params[:state])
+ - unless issuable_count == -1 # The count timed out
+ .modal-subheader
+ = sprite_icon('check', css_class: 'gl-icon gl-color-green-400')
+ %strong.gl-ml-3
+ - if issuable_type.eql?('merge_requests')
+ = n_("%{count} merge request selected", "%{count} merge requests selected", issuable_count) % { count: issuable_count }
+ - else
+ = n_("%{count} issue selected", "%{count} issues selected", issuable_count) % { count: issuable_count }
+ .modal-text
+ = html_escape(_('The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment.')) % { email: @current_user.notification_email, strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
+ .modal-footer
+ - if issuable_type.eql?('merge_requests')
+ = link_to _("Export merge requests"), export_csv_project_merge_requests_path(@project, request.query_parameters), method: :post, class: 'btn gl-button btn-success', data: { track_label: "export_merge_requests_csv", track_event: "click_button", track_value: "" }
+ - else
+ = link_to _('Export issues'), export_csv_project_issues_path(@project, request.query_parameters), method: :post, class: 'btn gl-button btn-success', data: { track_label: "export_issues_csv", track_event: "click_button", track_value: "", qa_selector: "export_issues_button" }
diff --git a/app/views/shared/issuable/form/_type_selector.html.haml b/app/views/shared/issuable/form/_type_selector.html.haml
index 3347966f39a..5d64c15d9f9 100644
--- a/app/views/shared/issuable/form/_type_selector.html.haml
+++ b/app/views/shared/issuable/form/_type_selector.html.haml
@@ -8,7 +8,7 @@
%button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
%span.dropdown-toggle-text.is-default
= issuable.issue_type.capitalize || _("Select type")
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-menu-selectable.dropdown-select
.dropdown-title.gl-display-flex
%span.gl-ml-auto
diff --git a/app/views/shared/issue_type/_details_content.html.haml b/app/views/shared/issue_type/_details_content.html.haml
new file mode 100644
index 00000000000..7c1ec332ba4
--- /dev/null
+++ b/app/views/shared/issue_type/_details_content.html.haml
@@ -0,0 +1,31 @@
+- related_branches_path = related_branches_project_issue_path(@project, issuable)
+
+.issue-details.issuable-details
+ .detail-page-description.content-block
+ #js-issuable-app{ data: { initial: issuable_initial_data(issuable).to_json} }
+ .title-container
+ %h2.title= markdown_field(issuable, :title)
+ - if issuable.description.present?
+ .description
+ .md= markdown_field(issuable, :description)
+
+ = edited_time_ago_with_tooltip(issuable, placement: 'bottom', html_class: 'issue-edited-ago js-issue-edited-ago')
+
+ = render 'shared/issue_type/sentry_stack_trace', issuable: issuable
+
+ = render 'projects/issues/design_management'
+
+ = render_if_exists 'projects/issues/related_issues'
+
+ #js-related-merge-requests{ data: { endpoint: expose_path(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: issuable.iid)), project_namespace: @project.namespace.path, project_path: @project.path } }
+
+ - if can?(current_user, :download_code, @project)
+ - add_page_startup_api_call related_branches_path
+ #related-branches{ data: { url: related_branches_path } }
+ -# This element is filled in using JavaScript.
+
+ = render 'shared/issue_type/emoji_block', issuable: issuable
+
+ = render 'projects/issues/discussion'
+
+= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @issue.assignees
diff --git a/app/views/shared/issue_type/_details_header.html.haml b/app/views/shared/issue_type/_details_header.html.haml
new file mode 100644
index 00000000000..ea4df288839
--- /dev/null
+++ b/app/views/shared/issue_type/_details_header.html.haml
@@ -0,0 +1,55 @@
+- can_update_issue = can?(current_user, :update_issue, issuable)
+- can_reopen_issue = can?(current_user, :reopen_issue, issuable)
+- can_report_spam = issuable.submittable_as_spam_by?(current_user)
+- can_create_issue = show_new_issue_link?(@project)
+- display_issuable_type = issuable_display_type(issuable)
+- new_issuable_params = ({ issuable_template: 'incident', issue: { issue_type: 'incident' } } if issuable.incident?)
+
+.detail-page-header
+ .detail-page-header-body
+ .issuable-status-box.status-box.status-box-issue-closed{ class: issue_status_visibility(issuable, status_box: :closed) }
+ = sprite_icon('mobile-issue-close', css_class: 'gl-display-block gl-display-sm-none!')
+ .gl-display-none.gl-display-sm-block!
+ = issue_closed_text(issuable, current_user)
+ .issuable-status-box.status-box.status-box-open{ class: issue_status_visibility(issuable, status_box: :open) }
+ = sprite_icon('issue-open-m', css_class: 'gl-display-block gl-display-sm-none!')
+ %span.gl-display-none.gl-display-sm-block!
+ = _('Open')
+
+ .issuable-meta
+ #js-issuable-header-warnings
+ = issuable_meta(issuable, @project, display_issuable_type)
+
+ %a.btn.gl-button.btn-default.float-right.gl-display-block.d-sm-none.gutter-toggle.issuable-gutter-toggle.js-sidebar-toggle{ href: "#" }
+ = sprite_icon('chevron-double-lg-left')
+
+ - if Feature.enabled?(:vue_issue_header, @project, default_enabled: true)
+ .js-issue-header-actions{ data: issue_header_actions_data(@project, issuable, current_user) }
+ - else
+ .detail-page-header-actions.js-issuable-actions.js-issuable-buttons{ data: { "action": "close-reopen" } }
+ .clearfix.issue-btn-group.dropdown
+ %button.btn.gl-button.btn-default.float-left.gl-display-md-none{ type: "button", data: { toggle: "dropdown" } }
+ = _('Options')
+ = icon('caret-down')
+ .dropdown-menu.dropdown-menu-right
+ %ul
+ - unless current_user == issuable.author
+ %li= link_to _('Report abuse'), new_abuse_report_path(user_id: issuable.author.id, ref_url: issue_url(issuable))
+ - if can_update_issue
+ %li= link_to _('Close %{display_issuable_type}') % { display_issuable_type: display_issuable_type }, issue_path(issuable, issue: { state_event: :close }, format: 'json'), class: "btn-close js-btn-issue-action #{issue_button_visibility(issuable, true)}", title: _('Close %{display_issuable_type}') % { display_issuable_type: display_issuable_type }, data: { endpoint: close_reopen_issuable_path(issuable) }
+ - if can_reopen_issue
+ %li= link_to _('Reopen %{display_issuable_type}') % { display_issuable_type: display_issuable_type }, issue_path(issuable, issue: { state_event: :reopen }, format: 'json'), class: "btn-reopen js-btn-issue-action #{issue_button_visibility(issuable, false)}", title: _('Reopen %{display_issuable_type}') % { display_issuable_type: display_issuable_type }, data: { endpoint: close_reopen_issuable_path(issuable) }
+ - if can_report_spam
+ %li= link_to _('Submit as spam'), mark_as_spam_project_issue_path(@project, issuable), method: :post, class: 'btn-spam', title: 'Submit as spam'
+ - if can_create_issue
+ - if can_update_issue || can_report_spam
+ %li.divider
+ %li= link_to _('New %{display_issuable_type}') % { display_issuable_type: display_issuable_type }, new_project_issue_path(@project, new_issuable_params), id: 'new_%{display_issuable_type}_link' % { display_issuable_type: display_issuable_type }
+
+ = render 'shared/issuable/close_reopen_button', issuable: issuable, can_update: can_update_issue, can_reopen: can_reopen_issue, warn_before_close: defined?(issuable.blocked?) && issuable.blocked?
+
+ - if can_report_spam
+ = link_to _('Submit as spam'), mark_as_spam_project_issue_path(@project, issuable), method: :post, class: 'gl-display-none gl-display-md-block gl-button btn btn-grouped btn-spam', title: 'Submit as spam'
+ - if can_create_issue
+ = link_to new_project_issue_path(@project, new_issuable_params), class: 'gl-display-none gl-display-md-block gl-button btn btn-grouped btn-success btn-inverted', title: _('New %{display_issuable_type}') % { display_issuable_type: display_issuable_type }, id: 'new_%{display_issuable_type}_link' % { display_issuable_type: display_issuable_type } do
+ = _('New %{display_issuable_type}') % { display_issuable_type: display_issuable_type }
diff --git a/app/views/shared/issue_type/_emoji_block.html.haml b/app/views/shared/issue_type/_emoji_block.html.haml
new file mode 100644
index 00000000000..42d149b2ab3
--- /dev/null
+++ b/app/views/shared/issue_type/_emoji_block.html.haml
@@ -0,0 +1,9 @@
+.content-block.emoji-block.emoji-block-sticky
+ .row.gl-m-0.gl-justify-content-space-between
+ .js-noteable-awards
+ = render 'award_emoji/awards_block', awardable: issuable, inline: true
+ .new-branch-col
+ = render_if_exists "projects/issues/timeline_toggle", issuable: issuable
+ #js-vue-sort-issue-discussions
+ #js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(issuable), notes_filters: UserPreference.notes_filters.to_json } }
+ = render 'new_branch' if show_new_branch_button?
diff --git a/app/views/shared/issue_type/_sentry_stack_trace.html.haml b/app/views/shared/issue_type/_sentry_stack_trace.html.haml
new file mode 100644
index 00000000000..40b29a74b53
--- /dev/null
+++ b/app/views/shared/issue_type/_sentry_stack_trace.html.haml
@@ -0,0 +1,4 @@
+- return unless issuable.sentry_issue.present?
+- add_page_specific_style 'page_bundles/error_tracking_details'
+
+#js-sentry-error-stack-trace{ data: error_details_data(@project, issuable.sentry_issue.sentry_issue_identifier) }
diff --git a/app/views/shared/members/_filter_2fa_dropdown.html.haml b/app/views/shared/members/_filter_2fa_dropdown.html.haml
index a2bc5e9ecdf..8187a9bde15 100644
--- a/app/views/shared/members/_filter_2fa_dropdown.html.haml
+++ b/app/views/shared/members/_filter_2fa_dropdown.html.haml
@@ -1,7 +1,7 @@
- filter = params[:two_factor] || 'everyone'
- filter_options = { 'everyone' => _('Everyone'), 'enabled' => _('Enabled'), 'disabled' => _('Disabled') }
-.dropdown.inline.member-filter-2fa-dropdown
- = dropdown_toggle(filter_options[filter], { toggle: 'dropdown' })
+.dropdown.inline.member-filter-2fa-dropdown{ data: { testid: 'member-filter-2fa-dropdown' } }
+ = dropdown_toggle(filter_options[filter], { toggle: 'dropdown', testid: 'dropdown-toggle' })
%ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable
%li.dropdown-header
= _("Filter by two-factor authentication")
diff --git a/app/views/shared/members/_invite_group.html.haml b/app/views/shared/members/_invite_group.html.haml
index a87a4c6a45c..5e3a6918ab2 100644
--- a/app/views/shared/members/_invite_group.html.haml
+++ b/app/views/shared/members/_invite_group.html.haml
@@ -13,7 +13,7 @@
= label_tag group_access_field, _("Max access level"), class: "label-bold"
.select-wrapper
= select_tag group_access_field, options_for_select(access_levels, default_access_level), data: { qa_selector: 'group_access_field' }, class: "form-control select-control"
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
.form-text.text-muted.gl-mb-3
- permissions_docs_path = help_page_path('user/permissions')
- link_start = %q{<a href="%{url}">}.html_safe % { url: permissions_docs_path }
diff --git a/app/views/shared/members/_invite_member.html.haml b/app/views/shared/members/_invite_member.html.haml
index 5f9046b3dcb..59b0600e2dd 100644
--- a/app/views/shared/members/_invite_member.html.haml
+++ b/app/views/shared/members/_invite_member.html.haml
@@ -5,7 +5,7 @@
- import_path = local_assigns[:import_path]
.row
.col-sm-12
- = form_tag submit_url, class: 'invite-users-form', method: :post do
+ = form_tag submit_url, class: 'invite-users-form', data: { testid: 'invite-users-form' }, method: :post do
.form-group
= label_tag :user_ids, _("GitLab member or Email address"), class: "label-bold"
= users_select_tag(:user_ids, multiple: true, class: 'input-clamp qa-member-select-field', scope: :all, email_user: true, placeholder: 'Search for members to update or invite')
@@ -13,7 +13,7 @@
= label_tag :access_level, _("Choose a role permission"), class: "label-bold"
.select-wrapper
= select_tag :access_level, options_for_select(access_levels, default_access_level), class: "form-control project-access-select select-control"
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
.form-text.text-muted.gl-mb-3
- permissions_docs_path = help_page_path('user/permissions')
- link_start = %q{<a href="%{url}">}.html_safe % { url: permissions_docs_path }
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index 164d38986ec..e294936f82c 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -2,6 +2,9 @@
- show_controls = local_assigns.fetch(:show_controls, true)
- force_mobile_view = local_assigns.fetch(:force_mobile_view, false)
- member = local_assigns.fetch(:member)
+- current_user_is_group_owner = local_assigns.fetch(:current_user_is_group_owner, false)
+- membership_source = local_assigns.fetch(:membership_source)
+- group = local_assigns.fetch(:group)
- user = local_assigns.fetch(:user, member.user)
- source = member.source
- override = member.try(:override)
@@ -25,13 +28,13 @@
= render 'shared/members/its_you_badge', user: user, current_user: current_user
- = render_if_exists 'shared/members/ee/license_badge', user: user, group: @group
+ = render_if_exists 'shared/members/ee/license_badge', user: user, group: group, current_user_is_group_owner: current_user_is_group_owner
= render 'shared/members/blocked_badge', user: user
= render 'shared/members/two_factor_auth_badge', user: user
- - if source.instance_of?(Group) && source != @group
+ - if source.instance_of?(Group) && source != membership_source
&middot;
= link_to source.full_name, source, class: "gl-display-inline-block inline-link"
@@ -57,10 +60,9 @@
= link_to member.created_by.name, user_path(member.created_by)
= time_ago_with_tooltip(member.created_at)
- if show_roles
- - current_resource = @project || @group
.controls.member-controls.align-items-center
= render_if_exists 'shared/members/ee/ldap_tag', can_override: member.can_override?
- - if show_controls && member.source == current_resource
+ - if show_controls && member.source == membership_source
- if member.can_resend_invite?
= link_to sprite_icon('paper-airplane'), polymorphic_path([:resend_invite, member]),
@@ -88,7 +90,7 @@
class: ("is-active" if member.access_level == role_id),
data: { id: role_id, el_id: dom_id(member), qa_selector: "#{role.downcase}_access_level_link" }
= render_if_exists 'shared/members/ee/revert_ldap_group_sync_option',
- group: @group,
+ group: group,
member: member,
can_override: member.can_override?
.clearable-input.member-form-control{ class: [("d-sm-inline-block" unless force_mobile_view)] }
@@ -105,12 +107,12 @@
- if member.can_approve?
= link_to polymorphic_path([:approve_access_request, member]),
method: :post,
- class: "btn btn-success align-self-center m-0 mb-2 #{'mb-sm-0 ml-sm-2' unless force_mobile_view}",
+ class: "btn btn-success btn-icon gl-button align-self-center m-0 mb-2 #{'mb-sm-0 ml-sm-2' unless force_mobile_view}",
title: _('Grant access') do
%span{ class: ('d-block d-sm-none' unless force_mobile_view) }
= _('Grant access')
- unless force_mobile_view
- = icon('check inverse', class: 'd-none d-sm-block')
+ = sprite_icon('check', css_class: 'd-none d-sm-block')
- if member.can_remove?
- if current_user == user
@@ -125,8 +127,8 @@
= _("Delete")
- unless force_mobile_view
= sprite_icon('remove', css_class: 'd-none d-sm-block gl-icon')
- = render_if_exists 'shared/members/ee/override_member_buttons', group: @group, member: member, user: user, action: :edit, can_override: member.can_override?
+ = render_if_exists 'shared/members/ee/override_member_buttons', group: group, member: member, user: user, action: :edit, can_override: member.can_override?
- else
%span.member-access-text.user-access-role= member.human_access
-= render_if_exists 'shared/members/ee/override_member_buttons', group: @group, member: member, user: user, action: :confirm, can_override: member.can_override?
+= render_if_exists 'shared/members/ee/override_member_buttons', group: group, member: member, user: user, action: :confirm, can_override: member.can_override?
diff --git a/app/views/shared/members/_requests.html.haml b/app/views/shared/members/_requests.html.haml
index e1e7aa36a78..3aa43ed1922 100644
--- a/app/views/shared/members/_requests.html.haml
+++ b/app/views/shared/members/_requests.html.haml
@@ -1,6 +1,8 @@
- membership_source = local_assigns.fetch(:membership_source)
- requesters = local_assigns.fetch(:requesters)
- force_mobile_view = local_assigns.fetch(:force_mobile_view, false)
+- group = local_assigns.fetch(:group)
+- current_user_is_group_owner = group && group.has_owner?(current_user)
- return if requesters.empty?
@@ -10,4 +12,9 @@
%strong= membership_source.name
%span.badge.badge-pill= requesters.size
%ul.content-list.members-list
- = render partial: 'shared/members/member', collection: requesters, as: :member, locals: { force_mobile_view: force_mobile_view }
+ = render partial: 'shared/members/member',
+ collection: requesters, as: :member,
+ locals: { membership_source: membership_source,
+ group: group,
+ force_mobile_view: force_mobile_view,
+ current_user_is_group_owner: current_user_is_group_owner }
diff --git a/app/views/shared/members/_search_field.html.haml b/app/views/shared/members/_search_field.html.haml
index e70cb063324..b1e3134f7aa 100644
--- a/app/views/shared/members/_search_field.html.haml
+++ b/app/views/shared/members/_search_field.html.haml
@@ -2,5 +2,5 @@
.search-control-wrap.gl-relative
= search_field_tag name, params[name], { placeholder: _('Search'), class: 'form-control', spellcheck: false }
- %button.user-search-btn.border-left.gl-display-flex.gl-align-items-center.gl-justify-content-center{ type: 'submit', 'aria': { label: _('Submit search') } }
+ %button.user-search-btn.border-left.gl-display-flex.gl-align-items-center.gl-justify-content-center{ type: 'submit', 'aria': { label: _('Submit search') }, data: { testid: 'user-search-submit' } }
= sprite_icon('search')
diff --git a/app/views/shared/members/_sort_dropdown.html.haml b/app/views/shared/members/_sort_dropdown.html.haml
index 606d3bcdfa8..682e3a0433b 100644
--- a/app/views/shared/members/_sort_dropdown.html.haml
+++ b/app/views/shared/members/_sort_dropdown.html.haml
@@ -1,5 +1,5 @@
-.dropdown.inline.qa-user-sort-dropdown
- = dropdown_toggle(member_sort_options_hash[@sort], { toggle: 'dropdown' })
+.dropdown.inline.qa-user-sort-dropdown{ data: { testid: 'user-sort-dropdown' } }
+ = dropdown_toggle(member_sort_options_hash[@sort], { toggle: 'dropdown', testid: 'dropdown-toggle' })
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable
%li.dropdown-header
= _("Sort by")
@@ -8,12 +8,12 @@
= link_to filter_group_project_member_path(sort: value), class: ("is-active" if @sort == value) do
= title
%li.divider
- %li{ data: { 'qa-selector': 'filter-members-with-inherited-permissions' } }
+ %li{ data: { testid: 'filter-members-with-inherited-permissions' } }
= link_to filter_group_project_member_path(with_inherited_permissions: nil), class: ("is-active" unless params[:with_inherited_permissions].present?) do
= _("Show all members")
- %li{ data: { 'qa-selector': 'filter-members-with-inherited-permissions' } }
+ %li{ data: { testid: 'filter-members-with-inherited-permissions' } }
= link_to filter_group_project_member_path(with_inherited_permissions: 'exclude'), class: ("is-active" if params[:with_inherited_permissions] == 'exclude') do
= _("Show only direct members")
- %li{ data: { 'qa-selector': 'filter-members-with-inherited-permissions' } }
+ %li{ data: { testid: 'filter-members-with-inherited-permissions' } }
= link_to filter_group_project_member_path(with_inherited_permissions: 'only'), class: ("is-active" if params[:with_inherited_permissions] == 'only') do
= _("Show only inherited members")
diff --git a/app/views/shared/milestones/_delete_button.html.haml b/app/views/shared/milestones/_delete_button.html.haml
index 7a813e110c4..09c783a0b24 100644
--- a/app/views/shared/milestones/_delete_button.html.haml
+++ b/app/views/shared/milestones/_delete_button.html.haml
@@ -1,6 +1,6 @@
- milestone_url = @milestone.project_milestone? ? project_milestone_path(@project, @milestone) : group_milestone_path(@group, @milestone)
-%button.js-delete-milestone-button.btn.btn-grouped.btn-danger{ data: { milestone_id: @milestone.id,
+%button.js-delete-milestone-button.btn.gl-button.btn-grouped.btn-danger{ data: { milestone_id: @milestone.id,
milestone_title: markdown_field(@milestone, :title),
milestone_url: milestone_url,
milestone_issue_count: @milestone.issues.count,
diff --git a/app/views/shared/milestones/_header.html.haml b/app/views/shared/milestones/_header.html.haml
index ea90b674b34..93da319fce7 100644
--- a/app/views/shared/milestones/_header.html.haml
+++ b/app/views/shared/milestones/_header.html.haml
@@ -11,10 +11,10 @@
.milestone-buttons
- if can?(current_user, :admin_milestone, @group || @project)
- = link_to _('Edit'), edit_milestone_path(milestone), class: 'btn btn-grouped'
+ = link_to _('Edit'), edit_milestone_path(milestone), class: 'btn gl-button btn-grouped'
- if milestone.project_milestone? && milestone.project.group
- %button.js-promote-project-milestone-button.btn.btn-grouped{ data: { toggle: 'modal',
+ %button.js-promote-project-milestone-button.btn.gl-button.btn-grouped{ data: { toggle: 'modal',
target: '#promote-milestone-modal',
milestone_title: milestone.title,
group_name: milestone.project.group.name,
@@ -26,11 +26,11 @@
#promote-milestone-modal
- if milestone.active?
- = link_to _('Close milestone'), update_milestone_path(milestone, { state_event: :close }), method: :put, class: 'btn btn-grouped btn-close'
+ = link_to _('Close milestone'), update_milestone_path(milestone, { state_event: :close }), method: :put, class: 'btn gl-button btn-grouped btn-close'
- else
- = link_to _('Reopen milestone'), update_milestone_path(milestone, { state_event: :activate }), method: :put, class: 'btn btn-grouped btn-reopen'
+ = link_to _('Reopen milestone'), update_milestone_path(milestone, { state_event: :activate }), method: :put, class: 'btn gl-button btn-grouped btn-reopen'
= render 'shared/milestones/delete_button'
- %button.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ type: 'button' }
= sprite_icon('chevron-double-lg-left')
diff --git a/app/views/shared/milestones/_labels_tab.html.haml b/app/views/shared/milestones/_labels_tab.html.haml
index 3b4d29ca7b0..a419e749f35 100644
--- a/app/views/shared/milestones/_labels_tab.html.haml
+++ b/app/views/shared/milestones/_labels_tab.html.haml
@@ -7,8 +7,8 @@
%span.prepend-description-left
= markdown_field(label, :description)
- .float-right.d-none.d-lg-block.d-xl-block
- = link_to milestones_issues_path(options.merge(state: 'opened')), class: 'btn btn-transparent btn-action' do
+ .float-right.d-none.d-lg-block
+ = link_to milestones_issues_path(options.merge(state: 'opened')), class: 'btn gl-button btn-default-tertiary btn-action' do
- pluralize milestone_issues_by_label_count(@milestone, label, state: :opened), _('open issue')
- = link_to milestones_issues_path(options.merge(state: 'closed')), class: 'btn btn-transparent btn-action' do
+ = link_to milestones_issues_path(options.merge(state: 'closed')), class: 'btn gl-button btn-default-tertiary btn-action' do
- pluralize milestone_issues_by_label_count(@milestone, label, state: :closed), _('closed issue')
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index f28aa406784..1597a011a45 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -46,7 +46,7 @@
.milestone-actions.d-flex.justify-content-sm-start.justify-content-md-end
- if @project # if in milestones list on project level
- if can_admin_group_milestones?
- %button.js-promote-project-milestone-button.btn.btn-blank.btn-sm.btn-grouped.has-tooltip{ title: s_('Milestones|Promote to Group Milestone'),
+ %button.js-promote-project-milestone-button.btn.gl-button.btn-default-tertiary.btn-sm.btn-grouped.has-tooltip{ title: s_('Milestones|Promote to Group Milestone'),
disabled: true,
type: 'button',
data: { url: promote_project_milestone_path(milestone.project, milestone),
@@ -59,6 +59,6 @@
- if can?(current_user, :admin_milestone, milestone)
- if milestone.closed?
- = link_to s_('Milestones|Reopen Milestone'), milestone_path(milestone, milestone: { state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen"
+ = link_to s_('Milestones|Reopen Milestone'), milestone_path(milestone, milestone: { state_event: :activate }), method: :put, class: "btn gl-button 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"
+ = link_to s_('Milestones|Close Milestone'), milestone_path(milestone, milestone: { state_event: :close }), method: :put, class: "btn gl-button btn-warning-secondary btn-sm btn-grouped btn-close"
diff --git a/app/views/shared/notes/_comment_button.html.haml b/app/views/shared/notes/_comment_button.html.haml
index e151e55d0d2..45af4b51b27 100644
--- a/app/views/shared/notes/_comment_button.html.haml
+++ b/app/views/shared/notes/_comment_button.html.haml
@@ -10,7 +10,7 @@
%ul#resolvable-comment-menu.dropdown-menu.dropdown-open-top{ data: { dropdown: true } }
%li#comment.droplab-item-selected{ data: { value: '', 'submit-text' => _('Comment'), 'close-text' => _("Comment & close %{noteable_name}") % { noteable_name: noteable_name }, 'reopen-text' => _("Comment & reopen %{noteable_name}") % { noteable_name: noteable_name } } }
%button.btn.btn-transparent
- = icon('check', class: 'icon')
+ = sprite_icon('check', css_class: 'icon')
.description
%strong= _("Comment")
%p
@@ -20,7 +20,7 @@
%li#discussion{ data: { value: 'DiscussionNote', 'submit-text' => _('Start thread'), 'close-text' => _("Start thread & close %{noteable_name}") % { noteable_name: noteable_name }, 'reopen-text' => _("Start thread & reopen %{noteable_name}") % { noteable_name: noteable_name } } }
%button.btn.btn-transparent
- = icon('check', class: 'icon')
+ = sprite_icon('check', css_class: 'icon')
.description
%strong= _("Start thread")
%p
diff --git a/app/views/shared/notes/_hints.html.haml b/app/views/shared/notes/_hints.html.haml
index 3703cca2290..a03e8446f5d 100644
--- a/app/views/shared/notes/_hints.html.haml
+++ b/app/views/shared/notes/_hints.html.haml
@@ -23,13 +23,20 @@
= sprite_icon('media', css_class: 'gl-icon gl-vertical-align-text-bottom')
%span.uploading-error-message
-# Populated by app/assets/javascripts/dropzone_input.js
- %button.retry-uploading-link{ type: 'button' }= _("Try again")
- or
- %button.attach-new-file.markdown-selector{ type: 'button' }= _("attach a new file")
+ %button.btn.gl-button.btn-link.gl-vertical-align-baseline.retry-uploading-link
+ %span.gl-button-text
+ = _("Try again")
+ = _("or")
+ %button.btn.gl-button.btn-link.attach-new-file.markdown-selector.gl-vertical-align-baseline
+ %span.gl-button-text
+ = _("attach a new file")
+ = _(".")
- %button.btn.markdown-selector.button-attach-file.btn-link{ type: 'button' }
+ %button.btn.gl-button.btn-link.button-attach-file.markdown-selector.button-attach-file.gl-vertical-align-text-bottom
= sprite_icon('media')
- %span.text-attach-file<>
+ %span.gl-button-text
= _("Attach a file")
- %button.btn.btn-default.btn-sm.hide.button-cancel-uploading-files{ type: 'button' }= _("Cancel")
+ %button.btn.gl-button.btn-link.button-cancel-uploading-files.gl-vertical-align-baseline.hide
+ %span.gl-button-text
+ = _("Cancel")
diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml
index 97ed2852871..f1352be28e3 100644
--- a/app/views/shared/notes/_note.html.haml
+++ b/app/views/shared/notes/_note.html.haml
@@ -72,7 +72,7 @@
= image_tag note.attachment.url, class: 'note-image-attach'
.attachment
= link_to note.attachment.url, target: '_blank' do
- = icon('paperclip')
+ = sprite_icon('paperclip')
= 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
diff --git a/app/views/shared/notes/_notes_with_form.html.haml b/app/views/shared/notes/_notes_with_form.html.haml
index 9baa340376b..1b03225d48d 100644
--- a/app/views/shared/notes/_notes_with_form.html.haml
+++ b/app/views/shared/notes/_notes_with_form.html.haml
@@ -19,7 +19,7 @@
= render "shared/notes/form", view: diff_view, supports_autocomplete: autocomplete
- elsif !current_user
.disabled-comment.text-center.gl-mt-3
- - link_to_register = link_to(_("register"), new_session_path(:user, redirect_to_referer: 'yes', anchor: 'register-pane'), class: 'js-register-link')
+ - link_to_register = link_to(_("register"), new_user_registration_path(redirect_to_referer: 'yes'), class: 'js-register-link')
- link_to_sign_in = link_to(_("sign in"), new_session_path(:user, redirect_to_referer: 'yes'), class: 'js-sign-in-link')
= _("Please %{link_to_register} or %{link_to_sign_in} to comment").html_safe % { link_to_register: link_to_register, link_to_sign_in: link_to_sign_in }
- elsif discussion_locked
diff --git a/app/views/shared/notifications/_custom_notifications.html.haml b/app/views/shared/notifications/_custom_notifications.html.haml
index 51b7da7dee8..946e3c67dcf 100644
--- a/app/views/shared/notifications/_custom_notifications.html.haml
+++ b/app/views/shared/notifications/_custom_notifications.html.haml
@@ -30,4 +30,5 @@
%label.form-check-label{ for: field_id }
%strong
= notification_event_name(event)
- .fa.custom-notification-event-loading.spinner
+ %span.spinner.is-loading.gl-vertical-align-middle.gl-display-none
+ = sprite_icon('check', css_class: 'is-done gl-display-none gl-vertical-align-middle gl-text-green-600')
diff --git a/app/views/shared/notifications/_new_button.html.haml b/app/views/shared/notifications/_new_button.html.haml
index fbcfec5fd96..14f4b04ef78 100644
--- a/app/views/shared/notifications/_new_button.html.haml
+++ b/app/views/shared/notifications/_new_button.html.haml
@@ -1,4 +1,5 @@
- btn_class = local_assigns.fetch(:btn_class, '')
+- dropdown_container_class = local_assigns.fetch(:dropdown_container_class, '')
- emails_disabled = local_assigns.fetch(:emails_disabled, false)
- if notification_setting
@@ -8,8 +9,8 @@
- else
- button_title = _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }
- .js-notification-dropdown.notification-dropdown.home-panel-action-button.gl-mt-3.gl-mr-3.dropdown.inline
- = form_for notification_setting, remote: true, html: { class: "inline notification-form no-label" } do |f|
+ .js-notification-dropdown.notification-dropdown.home-panel-action-button.gl-mt-3.dropdown.inline{ class: dropdown_container_class }
+ = form_for notification_setting, remote: true, html: { class: "notification-form no-label" } do |f|
= hidden_setting_source_input(notification_setting)
= hidden_field_tag "hide_label", true
= f.hidden_field :level, class: "notification_setting_level"
diff --git a/app/views/shared/projects/_search_form.html.haml b/app/views/shared/projects/_search_form.html.haml
index 7b76d6d789b..e96a9152c80 100644
--- a/app/views/shared/projects/_search_form.html.haml
+++ b/app/views/shared/projects/_search_form.html.haml
@@ -7,7 +7,6 @@
class: "project-filter-form-field form-control #{form_field_classes}",
spellcheck: false,
id: 'project-filter-form-field',
- tabindex: "2",
autofocus: local_assigns[:autofocus]
- if local_assigns[:icon]
diff --git a/app/views/shared/web_hooks/_form.html.haml b/app/views/shared/web_hooks/_form.html.haml
index 9c60201412c..c5234f14090 100644
--- a/app/views/shared/web_hooks/_form.html.haml
+++ b/app/views/shared/web_hooks/_form.html.haml
@@ -78,6 +78,18 @@
%strong= s_('Webhooks|Deployment events')
%p.text-muted.ml-1
= s_('Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled')
+ %li
+ = form.check_box :feature_flag_events, class: 'form-check-input'
+ = form.label :feature_flag_events, class: 'list-label form-check-label ml-1' do
+ %strong= s_('Webhooks|Feature Flag events')
+ %p.text-muted.ml-1
+ = s_('Webhooks|This URL is triggered when a feature flag is turned on or off')
+ %li
+ = form.check_box :releases_events, class: 'form-check-input'
+ = form.label :releases_events, class: 'list-label form-check-label ml-1' do
+ %strong= s_('Webhooks|Releases events')
+ %p.text-muted.ml-1
+ = s_('Webhooks|This URL is triggered when a release is created/updated')
.form-group
= form.label :enable_ssl_verification, s_('Webhooks|SSL verification'), class: 'label-bold checkbox'
.form-check
diff --git a/app/views/shared/wikis/_sidebar.html.haml b/app/views/shared/wikis/_sidebar.html.haml
index 893661755ab..c0ed7b4c6f2 100644
--- a/app/views/shared/wikis/_sidebar.html.haml
+++ b/app/views/shared/wikis/_sidebar.html.haml
@@ -1,7 +1,7 @@
%aside.right-sidebar.right-sidebar-expanded.wiki-sidebar.js-wiki-sidebar.js-right-sidebar{ data: { "offset-top" => "50", "spy" => "affix" } }
.sidebar-container
.block.wiki-sidebar-header.gl-mb-3.w-100
- %a.gutter-toggle.float-right.d-block.d-sm-block.d-md-none.js-sidebar-wiki-toggle{ href: "#" }
+ %a.gutter-toggle.float-right.d-block.d-md-none.js-sidebar-wiki-toggle{ href: "#" }
= sprite_icon('chevron-double-lg-right', css_class: 'gl-icon')
- if @wiki.container.is_a?(Project)
diff --git a/app/views/sherlock/transactions/_file_samples.html.haml b/app/views/sherlock/transactions/_file_samples.html.haml
index 5b3448605f2..110eb42f9ea 100644
--- a/app/views/sherlock/transactions/_file_samples.html.haml
+++ b/app/views/sherlock/transactions/_file_samples.html.haml
@@ -21,4 +21,4 @@
%td
= link_to(t('sherlock.view'),
sherlock_transaction_file_sample_path(@transaction, sample),
- class: 'btn btn-sm')
+ class: 'gl-button btn btn-sm')
diff --git a/app/views/sherlock/transactions/_queries.html.haml b/app/views/sherlock/transactions/_queries.html.haml
index 5e224f3aa0e..afe23d61bcd 100644
--- a/app/views/sherlock/transactions/_queries.html.haml
+++ b/app/views/sherlock/transactions/_queries.html.haml
@@ -21,4 +21,4 @@
%td
= link_to(t('sherlock.view'),
sherlock_transaction_query_path(@transaction, query),
- class: 'btn btn-sm')
+ class: 'gl-button btn btn-sm')
diff --git a/app/views/sherlock/transactions/index.html.haml b/app/views/sherlock/transactions/index.html.haml
index 1e16c88571e..a2be6cae1e0 100644
--- a/app/views/sherlock/transactions/index.html.haml
+++ b/app/views/sherlock/transactions/index.html.haml
@@ -4,7 +4,7 @@
.row-content-block
.float-right
= link_to(destroy_all_sherlock_transactions_path,
- class: 'btn btn-danger',
+ class: 'gl-button btn btn-danger',
method: :delete) do
= sprite_icon('remove')
= t('sherlock.delete_all_transactions')
@@ -37,5 +37,5 @@
%td
= time_ago_with_tooltip trans.finished_at
%td
- = link_to(sherlock_transaction_path(trans), class: 'btn btn-sm') do
+ = link_to(sherlock_transaction_path(trans), class: 'gl-button btn btn-sm') do
= t('sherlock.view')
diff --git a/app/views/snippets/notes/_actions.html.haml b/app/views/snippets/notes/_actions.html.haml
index 310d9946663..2e94bbe4baf 100644
--- a/app/views/snippets/notes/_actions.html.haml
+++ b/app/views/snippets/notes/_actions.html.haml
@@ -8,7 +8,7 @@
- if note_editable
.note-actions-item
- = button_tag title: _('Edit comment'), class: 'note-action-button js-note-edit has-tooltip btn btn-transparent', data: { container: 'body', qa_selector: 'edit_comment_button' } do
+ = button_tag title: _('Edit comment'), class: 'note-action-button js-note-edit has-tooltip gl-button btn btn-transparent', data: { container: 'body', qa_selector: 'edit_comment_button' } do
%span.link-highlight
= custom_icon('icon_pencil')
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index 77a6ff5455e..beb4cf4a6aa 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -1,3 +1,9 @@
+- add_page_startup_graphql_call('snippet/snippet', { ids: [@snippet.to_global_id.uri] })
+- add_page_startup_graphql_call('snippet/snippet_blob_content', { ids: [@snippet.to_global_id.uri], rich: false, paths: [@snippet.file_name] })
+- if @snippet.project_id?
+ - add_page_startup_graphql_call('snippet/project_permissions', { fullPath: @snippet.project_id })
+- else
+ - add_page_startup_graphql_call('snippet/user_permissions')
- @hide_top_links = true
- @content_class = "limit-container-width limited-inner-width-container" unless fluid_layout
- add_to_breadcrumbs _("Snippets"), dashboard_snippets_path
diff --git a/app/views/users/_groups.html.haml b/app/views/users/_groups.html.haml
deleted file mode 100644
index 6d7a52c7688..00000000000
--- a/app/views/users/_groups.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-.clearfix
- - groups.each do |group|
- = link_to group, class: 'profile-groups-avatars inline', title: group.name do
- .avatar-container.rect-avatar.s40
- = group_icon(group, class: 'avatar group-avatar s40')
diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml
index 294af53e35b..1367d80cf54 100644
--- a/app/views/users/_overview.html.haml
+++ b/app/views/users/_overview.html.haml
@@ -1,12 +1,14 @@
- activity_pane_class = Feature.enabled?(:security_auto_fix) && @user.bot? ? "col-12" : "col-md-12 col-lg-6"
-.row
- .col-12
- .calendar-block.gl-mt-3.gl-mb-3
- .user-calendar.d-none.d-sm-block{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
- %h4.center.light
- .spinner.spinner-md
- .user-calendar-activities.d-none.d-sm-block
+.row.d-none.d-sm-flex
+ .col-12.calendar-block.gl-my-3
+ .user-calendar.light{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
+ .spinner.spinner-md.gl-my-8
+ .user-calendar-error.invisible
+ = _('There was an error loading users activity calendar.')
+ %a.js-retry-load{ href: '#' }
+ = s_('UserProfile|Retry')
+ .user-calendar-activities
.row
%div{ class: activity_pane_class }
- if can?(current_user, :read_cross_project)
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 2746a139dd0..ee037a7d66a 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -4,6 +4,7 @@
- page_title @user.blocked? ? s_('UserProfile|Blocked user') : @user.name
- page_description @user.bio_html
- header_title @user.name, user_path(@user)
+- page_itemtype 'http://schema.org/Person'
- link_classes = "flex-grow-1 mx-1 "
= content_for :meta_tags do
@@ -35,7 +36,7 @@
.profile-header{ class: [('with-no-profile-tabs' if profile_tabs.empty?)] }
.avatar-holder
= link_to avatar_icon_for_user(@user, 400), target: '_blank', rel: 'noopener noreferrer' do
- = image_tag avatar_icon_for_user(@user, 90), class: "avatar s90", alt: ''
+ = image_tag avatar_icon_for_user(@user, 90), class: "avatar s90", alt: '', itemprop: 'image'
- if @user.blocked?
.user-info
@@ -44,25 +45,27 @@
= render "users/profile_basic_info"
- else
.user-info
- .cover-title
+ .cover-title{ itemprop: 'name' }
= @user.name
+ - if @user&.status && user_status_set_to_busy?(@user.status)
+ %span.gl-font-base.gl-text-gray-500.gl-vertical-align-middle= s_("UserProfile|(Busy)")
- - if @user.status
+ - if show_status_emoji?(@user.status)
.cover-status
= emoji_icon(@user.status.emoji)
= markdown_field(@user.status, :message)
= render "users/profile_basic_info"
.cover-desc.cgray.mb-1.mb-sm-2
- unless @user.location.blank?
- .profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mb-1.mb-sm-0
+ .profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mb-1.mb-sm-0{ itemprop: 'address', itemscope: true, itemtype: 'https://schema.org/PostalAddress' }
= sprite_icon('location', css_class: 'vertical-align-sub fgray')
- %span.vertical-align-middle
+ %span.vertical-align-middle{ itemprop: 'addressLocality' }
= @user.location
- unless work_information(@user).blank?
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline
= sprite_icon('work', css_class: 'vertical-align-middle fgray')
%span.vertical-align-middle
- = work_information(@user)
+ = work_information(@user, with_schema_markup: true)
.cover-desc.cgray.mb-1.mb-sm-2
- unless @user.skype.blank?
.profile-link-holder.middle-dot-divider
@@ -80,10 +83,10 @@
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mt-1.mt-sm-0
- if Feature.enabled?(:security_auto_fix) && @user.bot?
= sprite_icon('question', css_class: 'gl-text-blue-600')
- = link_to @user.short_website_url, @user.full_website_url, class: 'text-link', target: '_blank', rel: 'me noopener noreferrer nofollow'
+ = link_to @user.short_website_url, @user.full_website_url, class: 'text-link', target: '_blank', rel: 'me noopener noreferrer nofollow', itemprop: 'url'
- unless @user.public_email.blank?
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mt-1.mt-sm-0
- = link_to @user.public_email, "mailto:#{@user.public_email}", class: 'text-link'
+ = link_to @user.public_email, "mailto:#{@user.public_email}", class: 'text-link', itemprop: 'email'
- if @user.bio.present?
.cover-desc.cgray
.profile-user-bio
diff --git a/app/views/users/terms/index.html.haml b/app/views/users/terms/index.html.haml
index 175fde1c862..da8b73fd4fd 100644
--- a/app/views/users/terms/index.html.haml
+++ b/app/views/users/terms/index.html.haml
@@ -6,13 +6,13 @@
.card-footer.footer-block.clearfix
- if can?(current_user, :accept_terms, @term)
.float-right
- = button_to accept_term_path(@term, redirect_params), class: 'btn btn-success gl-ml-3', data: { qa_selector: 'accept_terms_button' } do
+ = button_to accept_term_path(@term, redirect_params), class: 'gl-button btn btn-success gl-ml-3', data: { qa_selector: 'accept_terms_button' } do
= _('Accept terms')
- else
.float-right
- = link_to root_path, class: 'btn btn-success gl-ml-3' do
+ = link_to root_path, class: 'gl-button btn btn-success gl-ml-3' do
= _('Continue')
- if can?(current_user, :decline_terms, @term)
.float-right
- = button_to decline_term_path(@term, redirect_params), class: 'btn btn-default gl-ml-3' do
+ = button_to decline_term_path(@term, redirect_params), class: 'gl-button btn btn-default gl-ml-3' do
= _('Decline and sign out')
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 30b89f37562..6f080a97f7a 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -97,7 +97,15 @@
:urgency: :low
:resource_boundary: :unknown
:weight: 1
- :idempotent:
+ :idempotent: true
+ :tags: []
+- :name: container_repository:container_expiration_policies_cleanup_container_repository
+ :feature_category: :container_registry
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
:tags: []
- :name: container_repository:delete_container_repository
:feature_category: :container_registry
@@ -371,6 +379,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: cronjob:schedule_merge_request_cleanup_refs
+ :feature_category: :source_code_management
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: cronjob:schedule_migrate_external_diffs
:feature_category: :source_code_management
:has_external_dependencies:
@@ -435,6 +451,14 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: dependency_proxy:purge_dependency_proxy_cache
+ :feature_category: :dependency_proxy
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: deployment:deployments_drop_older_deployments
:feature_category: :continuous_delivery
:has_external_dependencies:
@@ -819,6 +843,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: jira_connect:jira_connect_sync_project
+ :feature_category: :integrations
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: jira_importer:jira_import_advance_stage
:feature_category: :importers
:has_external_dependencies:
@@ -1312,6 +1344,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: bulk_import
+ :feature_category: :importers
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent:
+ :tags: []
- :name: chat_notification
:feature_category: :chatops
:has_external_dependencies: true
@@ -1409,6 +1449,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: destroy_pages_deployments
+ :feature_category: :pages
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: detect_repository_languages
:feature_category: :source_code_management
:has_external_dependencies:
@@ -1839,6 +1887,14 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: propagate_integration_inherit_descendant
+ :feature_category: :integrations
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: propagate_integration_project
:feature_category: :integrations
:has_external_dependencies:
diff --git a/app/workers/analytics/instance_statistics/counter_job_worker.rb b/app/workers/analytics/instance_statistics/counter_job_worker.rb
index 062b5ccc207..7fc715419b8 100644
--- a/app/workers/analytics/instance_statistics/counter_job_worker.rb
+++ b/app/workers/analytics/instance_statistics/counter_job_worker.rb
@@ -11,18 +11,24 @@ module Analytics
idempotent!
def perform(measurement_identifier, min_id, max_id, recorded_at)
- query_scope = ::Analytics::InstanceStatistics::Measurement::IDENTIFIER_QUERY_MAPPING[measurement_identifier].call
+ 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)
+ counter(query_scope, min_id, max_id)
end
return if count == Gitlab::Database::BatchCounter::FALLBACK
InstanceStatistics::Measurement.insert_all([{ recorded_at: recorded_at, count: count, identifier: measurement_identifier }])
end
+
+ private
+
+ def counter(query_scope, min_id, max_id)
+ Gitlab::Database::BatchCount.batch_count(query_scope, start: min_id, finish: max_id)
+ end
end
end
end
diff --git a/app/workers/background_migration_worker.rb b/app/workers/background_migration_worker.rb
index 74a12dbff77..70c4ad53726 100644
--- a/app/workers/background_migration_worker.rb
+++ b/app/workers/background_migration_worker.rb
@@ -24,10 +24,14 @@ class BackgroundMigrationWorker # rubocop:disable Scalability/IdempotentWorker
# class_name - The class name of the background migration to run.
# arguments - The arguments to pass to the migration class.
# lease_attempts - The number of times we will try to obtain an exclusive
- # lease on the class before running anyway. Pass 0 to always run.
+ # lease on the class before giving up. See MR for more discussion.
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45298#note_434304956
def perform(class_name, arguments = [], lease_attempts = 5)
with_context(caller_id: class_name.to_s) do
- should_perform, ttl = perform_and_ttl(class_name)
+ attempts_left = lease_attempts - 1
+ should_perform, ttl = perform_and_ttl(class_name, attempts_left)
+
+ break if should_perform.nil?
if should_perform
Gitlab::BackgroundMigration.perform(class_name, arguments)
@@ -37,32 +41,41 @@ class BackgroundMigrationWorker # rubocop:disable Scalability/IdempotentWorker
# we'll reschedule the job in such a way that it is picked up again around
# the time the lease expires.
self.class
- .perform_in(ttl || self.class.minimum_interval, class_name, arguments)
+ .perform_in(ttl || self.class.minimum_interval, class_name, arguments, attempts_left)
end
end
end
- def perform_and_ttl(class_name)
- if always_perform?
- # In test environments `perform_in` will run right away. This can then
- # lead to stack level errors in the above `#perform`. To work around this
- # we'll just perform the migration right away in the test environment.
- [true, nil]
- else
- lease = lease_for(class_name)
- perform = !!lease.try_obtain
-
- # If we managed to acquire the lease but the DB is not healthy, then we
- # want to simply reschedule our job and try again _after_ the lease
- # expires.
- if perform && !healthy_database?
- database_unhealthy_counter.increment
-
- perform = false
- end
+ def perform_and_ttl(class_name, attempts_left)
+ # In test environments `perform_in` will run right away. This can then
+ # lead to stack level errors in the above `#perform`. To work around this
+ # we'll just perform the migration right away in the test environment.
+ return [true, nil] if always_perform?
+
+ lease = lease_for(class_name)
+ lease_obtained = !!lease.try_obtain
+ healthy_db = healthy_database?
+ perform = lease_obtained && healthy_db
+
+ database_unhealthy_counter.increment if lease_obtained && !healthy_db
- [perform, lease.ttl]
+ # When the DB is unhealthy or the lease can't be obtained after several tries,
+ # then give up on the job and log a warning. Otherwise we could end up in
+ # an infinite rescheduling loop. Jobs can be tracked in the database with the
+ # use of Gitlab::Database::BackgroundMigrationJob
+ if !perform && attempts_left < 0
+ msg = if !lease_obtained
+ 'Job could not get an exclusive lease after several tries. Giving up.'
+ else
+ 'Database was unhealthy after several tries. Giving up.'
+ end
+
+ Sidekiq.logger.warn(class: class_name, message: msg, job_id: jid)
+
+ return [nil, nil]
end
+
+ [perform, lease.ttl]
end
def lease_for(class_name)
diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb
index d7a5fcf4f18..af2305528ce 100644
--- a/app/workers/build_finished_worker.rb
+++ b/app/workers/build_finished_worker.rb
@@ -33,6 +33,11 @@ class BuildFinishedWorker # rubocop:disable Scalability/IdempotentWorker
BuildCoverageWorker.new.perform(build.id)
Ci::BuildReportResultWorker.new.perform(build.id)
+ # TODO: As per https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/194, it may be
+ # best to avoid creating more workers that we have no intention of calling async.
+ # Change the previous worker calls on top to also just call the service directly.
+ Ci::TestCasesService.new.execute(build)
+
# We execute these async as these are independent operations.
BuildHooksWorker.perform_async(build.id)
ExpirePipelineCacheWorker.perform_async(build.pipeline_id) if build.pipeline.cacheable?
diff --git a/app/workers/bulk_import_worker.rb b/app/workers/bulk_import_worker.rb
new file mode 100644
index 00000000000..7828d046036
--- /dev/null
+++ b/app/workers/bulk_import_worker.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class BulkImportWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+
+ feature_category :importers
+
+ sidekiq_options retry: false, dead: false
+
+ worker_has_external_dependencies!
+
+ def perform(bulk_import_id)
+ BulkImports::Importers::GroupsImporter.new(bulk_import_id).execute
+ 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 89400247a7b..a63b12c0d03 100644
--- a/app/workers/ci/build_trace_chunk_flush_worker.rb
+++ b/app/workers/ci/build_trace_chunk_flush_worker.rb
@@ -5,6 +5,8 @@ module Ci
include ApplicationWorker
include PipelineBackgroundQueue
+ deduplicate :until_executed
+
idempotent!
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/workers/ci/delete_objects_worker.rb b/app/workers/ci/delete_objects_worker.rb
index e34be33b438..d845ad61358 100644
--- a/app/workers/ci/delete_objects_worker.rb
+++ b/app/workers/ci/delete_objects_worker.rb
@@ -14,18 +14,16 @@ module Ci
def remaining_work_count(*args)
@remaining_work_count ||= service
- .remaining_batches_count(max_batch_count: remaining_capacity)
+ .remaining_batches_count(max_batch_count: max_running_jobs)
end
def max_running_jobs
- if ::Feature.enabled?(:ci_delete_objects_low_concurrency)
- 2
- elsif ::Feature.enabled?(:ci_delete_objects_medium_concurrency)
+ if ::Feature.enabled?(:ci_delete_objects_medium_concurrency)
20
elsif ::Feature.enabled?(:ci_delete_objects_high_concurrency)
50
else
- 0
+ 2
end
end
diff --git a/app/workers/cleanup_container_repository_worker.rb b/app/workers/cleanup_container_repository_worker.rb
index 80cc296fff5..1cac2858156 100644
--- a/app/workers/cleanup_container_repository_worker.rb
+++ b/app/workers/cleanup_container_repository_worker.rb
@@ -1,10 +1,13 @@
# frozen_string_literal: true
-class CleanupContainerRepositoryWorker # rubocop:disable Scalability/IdempotentWorker
+class CleanupContainerRepositoryWorker
include ApplicationWorker
queue_namespace :container_repository
feature_category :container_registry
+ urgency :low
+ worker_resource_boundary :unknown
+ idempotent!
loggable_arguments 2
attr_reader :container_repository, :current_user
diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb
index 30dec5159a2..d101ef100d8 100644
--- a/app/workers/concerns/application_worker.rb
+++ b/app/workers/concerns/application_worker.rb
@@ -19,7 +19,7 @@ module ApplicationWorker
def structured_payload(payload = {})
context = Labkit::Context.current.to_h.merge(
- 'class' => self.class,
+ 'class' => self.class.name,
'job_status' => 'running',
'queue' => self.class.queue,
'jid' => jid
diff --git a/app/workers/concerns/limited_capacity/worker.rb b/app/workers/concerns/limited_capacity/worker.rb
index c0d6bfff2f5..b5a97e49300 100644
--- a/app/workers/concerns/limited_capacity/worker.rb
+++ b/app/workers/concerns/limited_capacity/worker.rb
@@ -67,6 +67,7 @@ module LimitedCapacity
return unless has_capacity?
job_tracker.register(jid)
+ report_running_jobs_metrics
perform_work(*args)
rescue => exception
raise
@@ -108,11 +109,15 @@ module LimitedCapacity
end
def report_prometheus_metrics(*args)
- running_jobs_gauge.set(prometheus_labels, running_jobs_count)
+ report_running_jobs_metrics
remaining_work_gauge.set(prometheus_labels, remaining_work_count(*args))
max_running_jobs_gauge.set(prometheus_labels, max_running_jobs)
end
+ def report_running_jobs_metrics
+ running_jobs_gauge.set(prometheus_labels, running_jobs_count)
+ end
+
def required_jobs_count(*args)
[
remaining_work_count(*args),
diff --git a/app/workers/concerns/reenqueuer.rb b/app/workers/concerns/reenqueuer.rb
index bf6f6546c03..6f399b6d90b 100644
--- a/app/workers/concerns/reenqueuer.rb
+++ b/app/workers/concerns/reenqueuer.rb
@@ -13,7 +13,7 @@
# - `#lease_timeout`
#
# The worker spec should include `it_behaves_like 'reenqueuer'` and
-# `it_behaves_like 'it is rate limited to 1 call per'`.
+# `it_behaves_like '#perform is rate limited to 1 call per'`.
#
# Optionally override `#minimum_duration` to adjust the rate limit.
#
diff --git a/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb b/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
new file mode 100644
index 00000000000..8c3c2e9e103
--- /dev/null
+++ b/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+module ContainerExpirationPolicies
+ class CleanupContainerRepositoryWorker
+ include ApplicationWorker
+ include LimitedCapacity::Worker
+ include Gitlab::Utils::StrongMemoize
+
+ queue_namespace :container_repository
+ feature_category :container_registry
+ urgency :low
+ worker_resource_boundary :unknown
+ idempotent!
+
+ def perform_work
+ return unless throttling_enabled?
+ return unless container_repository
+
+ log_extra_metadata_on_done(:container_repository_id, container_repository.id)
+
+ unless allowed_to_run?(container_repository)
+ container_repository.cleanup_unscheduled!
+ log_extra_metadata_on_done(:cleanup_status, :skipped)
+ return
+ end
+
+ result = ContainerExpirationPolicies::CleanupService.new(container_repository)
+ .execute
+ log_extra_metadata_on_done(:cleanup_status, result.payload[:cleanup_status])
+ end
+
+ def remaining_work_count
+ cleanup_scheduled_count = ContainerRepository.cleanup_scheduled.count
+ cleanup_unfinished_count = ContainerRepository.cleanup_unfinished.count
+ total_count = cleanup_scheduled_count + cleanup_unfinished_count
+
+ log_info(
+ cleanup_scheduled_count: cleanup_scheduled_count,
+ cleanup_unfinished_count: cleanup_unfinished_count,
+ cleanup_total_count: total_count
+ )
+
+ total_count
+ end
+
+ def max_running_jobs
+ return 0 unless throttling_enabled?
+
+ ::Gitlab::CurrentSettings.current_application_settings.container_registry_expiration_policies_worker_capacity
+ end
+
+ private
+
+ def allowed_to_run?(container_repository)
+ return false unless policy&.enabled && policy&.next_run_at
+
+ Time.zone.now + max_cleanup_execution_time.seconds < policy.next_run_at
+ end
+
+ def throttling_enabled?
+ Feature.enabled?(:container_registry_expiration_policies_throttling)
+ end
+
+ def max_cleanup_execution_time
+ ::Gitlab::CurrentSettings.current_application_settings.container_registry_delete_tags_service_timeout
+ end
+
+ def policy
+ project.container_expiration_policy
+ end
+
+ def project
+ container_repository&.project
+ end
+
+ def container_repository
+ strong_memoize(:container_repository) do
+ ContainerRepository.transaction do
+ # rubocop: disable CodeReuse/ActiveRecord
+ # We need a lock to prevent two workers from picking up the same row
+ container_repository = ContainerRepository.waiting_for_cleanup
+ .order(:expiration_policy_cleanup_status, :expiration_policy_started_at)
+ .limit(1)
+ .lock('FOR UPDATE SKIP LOCKED')
+ .first
+ # rubocop: enable CodeReuse/ActiveRecord
+ container_repository&.tap(&:cleanup_ongoing!)
+ end
+ end
+ end
+
+ def log_info(extra_structure)
+ logger.info(structured_payload(extra_structure))
+ end
+ end
+end
diff --git a/app/workers/container_expiration_policy_worker.rb b/app/workers/container_expiration_policy_worker.rb
index 61ba27f00d2..43dbea027f2 100644
--- a/app/workers/container_expiration_policy_worker.rb
+++ b/app/workers/container_expiration_policy_worker.rb
@@ -3,20 +3,79 @@
class ContainerExpirationPolicyWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
include CronjobQueue
+ include ExclusiveLeaseGuard
feature_category :container_registry
+ InvalidPolicyError = Class.new(StandardError)
+
+ BATCH_SIZE = 1000.freeze
+
def perform
- ContainerExpirationPolicy.executable.preloaded.each_batch do |relation|
- relation.each do |container_expiration_policy|
- with_context(project: container_expiration_policy.project,
- user: container_expiration_policy.project.owner) do |project:, user:|
- ContainerExpirationPolicyService.new(project, user)
- .execute(container_expiration_policy)
- rescue ContainerExpirationPolicyService::InvalidPolicyError => e
- Gitlab::ErrorTracking.log_exception(e, container_expiration_policy_id: container_expiration_policy.id)
+ throttling_enabled? ? perform_throttled : perform_unthrottled
+ end
+
+ private
+
+ def perform_unthrottled
+ with_runnable_policy(preloaded: true) do |policy|
+ with_context(project: policy.project,
+ user: policy.project.owner) do |project:, user:|
+ ContainerExpirationPolicyService.new(project, user)
+ .execute(policy)
+ end
+ end
+ end
+
+ def perform_throttled
+ try_obtain_lease do
+ with_runnable_policy do |policy|
+ ContainerExpirationPolicy.transaction do
+ policy.schedule_next_run!
+ ContainerRepository.for_project_id(policy.id)
+ .each_batch do |relation|
+ relation.update_all(expiration_policy_cleanup_status: :cleanup_scheduled)
+ end
end
end
+
+ ContainerExpirationPolicies::CleanupContainerRepositoryWorker.perform_with_capacity
end
end
+
+ # TODO : remove the preload option when cleaning FF container_registry_expiration_policies_throttling
+ def with_runnable_policy(preloaded: false)
+ ContainerExpirationPolicy.runnable_schedules.each_batch(of: BATCH_SIZE) do |policies|
+ # rubocop: disable CodeReuse/ActiveRecord
+ cte = Gitlab::SQL::CTE.new(:batched_policies, policies.limit(BATCH_SIZE))
+ # rubocop: enable CodeReuse/ActiveRecord
+ scope = cte.apply_to(ContainerExpirationPolicy.all).with_container_repositories
+
+ scope = scope.preloaded if preloaded
+
+ scope.each do |policy|
+ if policy.valid?
+ yield policy
+ else
+ disable_invalid_policy!(policy)
+ end
+ end
+ end
+ end
+
+ def disable_invalid_policy!(policy)
+ policy.disable!
+ Gitlab::ErrorTracking.log_exception(
+ ::ContainerExpirationPolicyWorker::InvalidPolicyError.new,
+ container_expiration_policy_id: policy.id
+ )
+ end
+
+ def throttling_enabled?
+ Feature.enabled?(:container_registry_expiration_policies_throttling)
+ end
+
+ def lease_timeout
+ 5.hours
+ end
end
diff --git a/app/workers/destroy_pages_deployments_worker.rb b/app/workers/destroy_pages_deployments_worker.rb
new file mode 100644
index 00000000000..32b539325c9
--- /dev/null
+++ b/app/workers/destroy_pages_deployments_worker.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class DestroyPagesDeploymentsWorker
+ include ApplicationWorker
+
+ idempotent!
+
+ loggable_arguments 0, 1
+ sidekiq_options retry: 3
+ feature_category :pages
+
+ def perform(project_id, last_deployment_id = nil)
+ project = Project.find_by_id(project_id)
+
+ return unless project
+
+ ::Pages::DestroyDeploymentsService.new(project, last_deployment_id).execute
+ end
+end
diff --git a/app/workers/git_garbage_collect_worker.rb b/app/workers/git_garbage_collect_worker.rb
index 9071e4b8a1b..e1dcb16bafb 100644
--- a/app/workers/git_garbage_collect_worker.rb
+++ b/app/workers/git_garbage_collect_worker.rb
@@ -27,15 +27,15 @@ class GitGarbageCollectWorker # rubocop:disable Scalability/IdempotentWorker
task = task.to_sym
- if task == :gc
+ if gc?(task)
::Projects::GitDeduplicationService.new(project).execute
cleanup_orphan_lfs_file_references(project)
end
- gitaly_call(task, project.repository.raw_repository)
+ gitaly_call(task, project)
# Refresh the branch cache in case garbage collection caused a ref lookup to fail
- flush_ref_caches(project) if task == :gc
+ flush_ref_caches(project) if gc?(task)
update_repository_statistics(project) if task != :pack_refs
@@ -48,6 +48,10 @@ class GitGarbageCollectWorker # rubocop:disable Scalability/IdempotentWorker
private
+ def gc?(task)
+ task == :gc || task == :prune
+ end
+
def try_obtain_lease(key)
::Gitlab::ExclusiveLease.new(key, timeout: LEASE_TIMEOUT).try_obtain
end
@@ -64,8 +68,9 @@ class GitGarbageCollectWorker # rubocop:disable Scalability/IdempotentWorker
::Gitlab::ExclusiveLease.get_uuid(key)
end
- ## `repository` has to be a Gitlab::Git::Repository
- def gitaly_call(task, repository)
+ def gitaly_call(task, project)
+ repository = project.repository.raw_repository
+
client = if task == :pack_refs
Gitlab::GitalyClient::RefService.new(repository)
else
@@ -73,8 +78,8 @@ class GitGarbageCollectWorker # rubocop:disable Scalability/IdempotentWorker
end
case task
- when :gc
- client.garbage_collect(bitmaps_enabled?)
+ when :prune, :gc
+ client.garbage_collect(bitmaps_enabled?, prune: task == :prune)
when :full_repack
client.repack_full(bitmaps_enabled?)
when :incremental_repack
diff --git a/app/workers/jira_connect/sync_branch_worker.rb b/app/workers/jira_connect/sync_branch_worker.rb
index 8c3416478fd..4c1c987353d 100644
--- a/app/workers/jira_connect/sync_branch_worker.rb
+++ b/app/workers/jira_connect/sync_branch_worker.rb
@@ -8,7 +8,7 @@ module JiraConnect
feature_category :integrations
loggable_arguments 1, 2
- def perform(project_id, branch_name, commit_shas)
+ def perform(project_id, branch_name, commit_shas, update_sequence_id = nil)
project = Project.find_by_id(project_id)
return unless project
@@ -16,7 +16,7 @@ module JiraConnect
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)
+ JiraConnect::SyncService.new(project).execute(commits: commits, branches: branches, update_sequence_id: update_sequence_id)
end
end
end
diff --git a/app/workers/jira_connect/sync_merge_request_worker.rb b/app/workers/jira_connect/sync_merge_request_worker.rb
index b78bb8dfe16..f45ab38f35d 100644
--- a/app/workers/jira_connect/sync_merge_request_worker.rb
+++ b/app/workers/jira_connect/sync_merge_request_worker.rb
@@ -7,12 +7,12 @@ module JiraConnect
queue_namespace :jira_connect
feature_category :integrations
- def perform(merge_request_id)
+ def perform(merge_request_id, update_sequence_id = nil)
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])
+ JiraConnect::SyncService.new(merge_request.project).execute(merge_requests: [merge_request], update_sequence_id: update_sequence_id)
end
end
end
diff --git a/app/workers/jira_connect/sync_project_worker.rb b/app/workers/jira_connect/sync_project_worker.rb
new file mode 100644
index 00000000000..4d52705f207
--- /dev/null
+++ b/app/workers/jira_connect/sync_project_worker.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module JiraConnect
+ class SyncProjectWorker
+ include ApplicationWorker
+
+ queue_namespace :jira_connect
+ feature_category :integrations
+ idempotent!
+ worker_has_external_dependencies!
+
+ MERGE_REQUEST_LIMIT = 400
+
+ def perform(project_id, update_sequence_id)
+ project = Project.find_by_id(project_id)
+
+ return if project.nil?
+
+ JiraConnect::SyncService.new(project).execute(merge_requests: merge_requests_to_sync(project), update_sequence_id: update_sequence_id)
+ end
+
+ private
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def merge_requests_to_sync(project)
+ project.merge_requests.with_jira_issue_keys.preload(:author).limit(MERGE_REQUEST_LIMIT).order(id: :desc)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 0b224b88e4d..9fe7dd31e68 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -20,7 +20,7 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker
changes = Base64.decode64(changes) unless changes.include?(' ')
# Use Sidekiq.logger so arguments can be correlated with execution
# time and thread ID's.
- Sidekiq.logger.info "changes: #{changes.inspect}" if ENV['SIDEKIQ_LOG_ARGUMENTS']
+ Sidekiq.logger.info "changes: #{changes.inspect}" if SidekiqLogArguments.enabled?
post_received = Gitlab::GitPostReceive.new(container, identifier, changes, push_options)
if repo_type.wiki?
diff --git a/app/workers/propagate_integration_inherit_descendant_worker.rb b/app/workers/propagate_integration_inherit_descendant_worker.rb
new file mode 100644
index 00000000000..d589619818c
--- /dev/null
+++ b/app/workers/propagate_integration_inherit_descendant_worker.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class PropagateIntegrationInheritDescendantWorker
+ include ApplicationWorker
+
+ feature_category :integrations
+ idempotent!
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def perform(integration_id, min_id, max_id)
+ integration = Service.find_by_id(integration_id)
+ return unless integration
+
+ batch = Service.inherited_descendants_from_self_or_ancestors_from(integration).where(id: min_id..max_id)
+
+ BulkUpdateIntegrationService.new(integration, batch).execute
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+end
diff --git a/app/workers/propagate_integration_inherit_worker.rb b/app/workers/propagate_integration_inherit_worker.rb
index ef3132202f6..40d67c6d3bf 100644
--- a/app/workers/propagate_integration_inherit_worker.rb
+++ b/app/workers/propagate_integration_inherit_worker.rb
@@ -11,9 +11,9 @@ class PropagateIntegrationInheritWorker
integration = Service.find_by_id(integration_id)
return unless integration
- services = Service.where(id: min_id..max_id).by_type(integration.type).inherit_from_id(integration.id)
+ batch = Service.where(id: min_id..max_id).by_type(integration.type).inherit_from_id(integration.id)
- BulkUpdateIntegrationService.new(integration, services).execute
+ BulkUpdateIntegrationService.new(integration, batch).execute
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/purge_dependency_proxy_cache_worker.rb b/app/workers/purge_dependency_proxy_cache_worker.rb
new file mode 100644
index 00000000000..594cdd3ed11
--- /dev/null
+++ b/app/workers/purge_dependency_proxy_cache_worker.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class PurgeDependencyProxyCacheWorker
+ include ApplicationWorker
+ include Gitlab::Allowable
+ idempotent!
+
+ queue_namespace :dependency_proxy
+ feature_category :dependency_proxy
+
+ def perform(current_user_id, group_id)
+ @current_user = User.find_by_id(current_user_id)
+ @group = Group.find_by_id(group_id)
+
+ return unless valid?
+
+ @group.dependency_proxy_blobs.destroy_all # rubocop:disable Cop/DestroyAll
+ end
+
+ private
+
+ def valid?
+ return unless @group
+
+ can?(@current_user, :admin_group, @group) && @group.dependency_proxy_feature_available?
+ end
+end
diff --git a/app/workers/remove_expired_members_worker.rb b/app/workers/remove_expired_members_worker.rb
index f56a6cd9fa2..35844fdf297 100644
--- a/app/workers/remove_expired_members_worker.rb
+++ b/app/workers/remove_expired_members_worker.rb
@@ -7,11 +7,19 @@ class RemoveExpiredMembersWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :authentication_and_authorization
worker_resource_boundary :cpu
+ # rubocop: disable CodeReuse/ActiveRecord
def perform
- Member.expired.find_each do |member|
+ Member.expired.preload(:user).find_each do |member|
Members::DestroyService.new.execute(member, skip_authorization: true)
+
+ expired_user = member.user
+
+ if expired_user.project_bot?
+ Users::DestroyService.new(nil).execute(expired_user, skip_authorization: true)
+ end
rescue => ex
logger.error("Expired Member ID=#{member.id} cannot be removed - #{ex}")
end
end
+ # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/repository_cleanup_worker.rb b/app/workers/repository_cleanup_worker.rb
index 33b7223dd95..03c9add6afb 100644
--- a/app/workers/repository_cleanup_worker.rb
+++ b/app/workers/repository_cleanup_worker.rb
@@ -27,8 +27,9 @@ class RepositoryCleanupWorker # rubocop:disable Scalability/IdempotentWorker
project = Project.find(project_id)
user = User.find(user_id)
- # Ensure the file is removed
- project.bfg_object_map.remove!
+ # Ensure the file is removed and the repository is made read-write again
+ Projects::CleanupService.cleanup_after(project)
+
notification_service.repository_cleanup_failure(project, user, error)
end
diff --git a/app/workers/schedule_merge_request_cleanup_refs_worker.rb b/app/workers/schedule_merge_request_cleanup_refs_worker.rb
new file mode 100644
index 00000000000..17cabba4278
--- /dev/null
+++ b/app/workers/schedule_merge_request_cleanup_refs_worker.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class ScheduleMergeRequestCleanupRefsWorker
+ include ApplicationWorker
+ include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
+
+ feature_category :source_code_management
+ idempotent!
+
+ # Based on existing data, MergeRequestCleanupRefsWorker can run 3 jobs per
+ # second. This means that 180 jobs can be performed but since there are some
+ # spikes from time time, it's better to give it some allowance.
+ LIMIT = 180
+ DELAY = 10.seconds
+ BATCH_SIZE = 30
+
+ def perform
+ return if Gitlab::Database.read_only?
+
+ ids = MergeRequest::CleanupSchedule.scheduled_merge_request_ids(LIMIT).map { |id| [id] }
+
+ MergeRequestCleanupRefsWorker.bulk_perform_in(DELAY, ids, batch_size: BATCH_SIZE) # rubocop:disable Scalability/BulkPerformWithContext
+
+ log_extra_metadata_on_done(:merge_requests_count, ids.size)
+ end
+end
diff --git a/bin/background_jobs b/bin/background_jobs
index 866f5c39cd6..cbc501094c4 100755
--- a/bin/background_jobs
+++ b/bin/background_jobs
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-cd $(dirname $0)/..
+cd $(dirname $0)/.. || exit 1
if [ -n "$SIDEKIQ_WORKERS" ] ; then
exec bin/background_jobs_sk_cluster "$@"
diff --git a/bin/feature-flag b/bin/feature-flag
index b5e7889be1d..613ddc1d8cb 100755
--- a/bin/feature-flag
+++ b/bin/feature-flag
@@ -35,6 +35,7 @@ class FeatureFlagOptionParser
:name,
:type,
:group,
+ :milestone,
:ee,
:amend,
:dry_run,
@@ -64,6 +65,10 @@ class FeatureFlagOptionParser
options.introduced_by_url = value
end
+ opts.on('-M', '--milestone [string]', String, 'Milestone in which the Feature Flag was introduced') do |value|
+ options.milestone = value
+ end
+
opts.on('-i', '--rollout-issue-url [string]', String, 'URL of Issue rolling out the Feature Flag') do |value|
options.rollout_issue_url = value
end
@@ -99,7 +104,7 @@ class FeatureFlagOptionParser
end
# Name is a first name
- options.name = argv.first
+ options.name = argv.first.downcase.gsub(/-/, '_')
options
end
@@ -126,6 +131,8 @@ class FeatureFlagOptionParser
$stdout.puts ">> Specify the feature flag type:"
$stdout.puts
TYPES.each do |type, data|
+ next if data[:deprecated]
+
$stdout.puts "#{type.to_s.rjust(15)}#{' '*6}#{data[:description]}"
end
@@ -133,7 +140,7 @@ class FeatureFlagOptionParser
$stdout.print "?> "
type = $stdin.gets.strip.to_sym
- return type if TYPES[type]
+ return type if TYPES[type] && !TYPES[type][:deprecated]
$stderr.puts "Invalid type specified '#{type}'"
end
@@ -186,6 +193,11 @@ class FeatureFlagOptionParser
end
end
+ def read_milestone
+ milestone = File.read('VERSION')
+ milestone.gsub(/^(\d+\.\d+).*$/, '\1').chomp
+ end
+
def read_default_enabled(options)
TYPES.dig(options.type, :default_enabled)
end
@@ -212,6 +224,7 @@ class FeatureFlagCreator
options.group ||= FeatureFlagOptionParser.read_group
options.introduced_by_url ||= FeatureFlagOptionParser.read_introduced_by_url
options.rollout_issue_url ||= FeatureFlagOptionParser.read_rollout_issue_url(options)
+ options.milestone ||= FeatureFlagOptionParser.read_milestone
$stdout.puts "\e[32mcreate\e[0m #{file_path}"
$stdout.puts contents
@@ -241,6 +254,7 @@ class FeatureFlagCreator
'name' => options.name,
'introduced_by_url' => options.introduced_by_url,
'rollout_issue_url' => options.rollout_issue_url,
+ 'milestone' => options.milestone,
'group' => options.group,
'type' => options.type.to_s,
'default_enabled' => FeatureFlagOptionParser.read_default_enabled(options)
diff --git a/bin/mail_room b/bin/mail_room
index 2539e3d388e..cf9d422909e 100755
--- a/bin/mail_room
+++ b/bin/mail_room
@@ -1,6 +1,6 @@
#!/bin/sh
-cd $(dirname $0)/..
+cd $(dirname $0)/.. || exit 1
app_root=$(pwd)
mail_room_pidfile="$app_root/tmp/pids/mail_room.pid"
@@ -9,7 +9,8 @@ mail_room_config="$app_root/config/mail_room.yml"
get_mail_room_pid()
{
- local pid=$(cat $mail_room_pidfile)
+ local pid
+ pid=$(cat $mail_room_pidfile)
if [ -z "$pid" ] ; then
echo "Could not find a PID in $mail_room_pidfile"
exit 1
diff --git a/bin/spring b/bin/spring
index e0d140fe0c7..497ab099954 100755
--- a/bin/spring
+++ b/bin/spring
@@ -1,15 +1,17 @@
#!/usr/bin/env ruby
-# This file loads spring without using Bundler, in order to be fast.
+# This file loads Spring without using Bundler, in order to be fast.
# It gets overwritten when you run the `spring binstub` command.
unless (defined?(Spring) || ENV['ENABLE_SPRING'] != '1') && File.basename($0) != 'spring'
require 'rubygems'
require 'bundler'
- if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m))
- Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq.join(Gem.path_separator) }
- gem 'spring', match[1]
+ lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read)
+ spring = lockfile.specs.detect { |spec| spec.name == 'spring' }
+ if spring
+ Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
+ gem 'spring', spring.version
require 'spring/binstub'
end
end
diff --git a/bin/web_unicorn b/bin/web_unicorn
index ecd0bbd10b0..5fa15a8324b 100755
--- a/bin/web_unicorn
+++ b/bin/web_unicorn
@@ -1,6 +1,6 @@
#!/bin/sh
-cd $(dirname $0)/..
+cd $(dirname $0)/.. || exit 1
app_root=$(pwd)
unicorn_pidfile="$app_root/tmp/pids/unicorn.pid"
@@ -9,7 +9,8 @@ unicorn_cmd="bundle exec unicorn_rails -c $unicorn_config -E $RAILS_ENV"
get_unicorn_pid()
{
- local pid=$(cat $unicorn_pidfile)
+ local pid
+ pid=$(cat $unicorn_pidfile)
if [ -z "$pid" ] ; then
echo "Could not find a PID in $unicorn_pidfile"
exit 1
diff --git a/changelogs/unreleased/10io-add-cleanup-status-to-container-repository-details-graphql.yml b/changelogs/unreleased/10io-add-cleanup-status-to-container-repository-details-graphql.yml
new file mode 100644
index 00000000000..ebe84b20539
--- /dev/null
+++ b/changelogs/unreleased/10io-add-cleanup-status-to-container-repository-details-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add cleanup status field to graphQL ContainerRepositoryType
+merge_request: 47544
+author:
+type: added
diff --git a/changelogs/unreleased/10io-graphql-container-repository-details-api.yml b/changelogs/unreleased/10io-graphql-container-repository-details-api.yml
new file mode 100644
index 00000000000..4a0f48ff23f
--- /dev/null
+++ b/changelogs/unreleased/10io-graphql-container-repository-details-api.yml
@@ -0,0 +1,5 @@
+---
+title: Container repository details GraphQL API
+merge_request: 46560
+author:
+type: added
diff --git a/changelogs/unreleased/10io-graphql-destroy-mutation-for-container-repositories.yml b/changelogs/unreleased/10io-graphql-destroy-mutation-for-container-repositories.yml
new file mode 100644
index 00000000000..2d9bda79eec
--- /dev/null
+++ b/changelogs/unreleased/10io-graphql-destroy-mutation-for-container-repositories.yml
@@ -0,0 +1,5 @@
+---
+title: Add container repository destroy GraphQL mutation
+merge_request: 47175
+author:
+type: added
diff --git a/changelogs/unreleased/10io-graphql-query-container-repositories.yml b/changelogs/unreleased/10io-graphql-query-container-repositories.yml
new file mode 100644
index 00000000000..e065c5aadf7
--- /dev/null
+++ b/changelogs/unreleased/10io-graphql-query-container-repositories.yml
@@ -0,0 +1,5 @@
+---
+title: GraphQL API for listing container repositories
+merge_request: 44926
+author:
+type: added
diff --git a/changelogs/unreleased/11752-improve-active-users-count-license-query.yml b/changelogs/unreleased/11752-improve-active-users-count-license-query.yml
new file mode 100644
index 00000000000..72ea685f3ea
--- /dev/null
+++ b/changelogs/unreleased/11752-improve-active-users-count-license-query.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve admin/license timeout on large instances
+merge_request: 46336
+author:
+type: performance
diff --git a/changelogs/unreleased/17652-trademark-and-copyright-symbols-converted-to-smiley.yml b/changelogs/unreleased/17652-trademark-and-copyright-symbols-converted-to-smiley.yml
new file mode 100644
index 00000000000..86ca914838c
--- /dev/null
+++ b/changelogs/unreleased/17652-trademark-and-copyright-symbols-converted-to-smiley.yml
@@ -0,0 +1,6 @@
+---
+title: Do not convert unicode versions of trademark, copyright,
+ and registered trademark to emoji
+merge_request: 45457
+author:
+type: fixed
diff --git a/changelogs/unreleased/198610-remove-ace.yml b/changelogs/unreleased/198610-remove-ace.yml
new file mode 100644
index 00000000000..462d77d158a
--- /dev/null
+++ b/changelogs/unreleased/198610-remove-ace.yml
@@ -0,0 +1,5 @@
+---
+title: Removed ACE editor from the codebase
+merge_request: 46420
+author:
+type: removed
diff --git a/changelogs/unreleased/20099-markdown-with-yaml-rendering-doesn-t-handle-utf8-bom.yml b/changelogs/unreleased/20099-markdown-with-yaml-rendering-doesn-t-handle-utf8-bom.yml
new file mode 100644
index 00000000000..d6dec816abb
--- /dev/null
+++ b/changelogs/unreleased/20099-markdown-with-yaml-rendering-doesn-t-handle-utf8-bom.yml
@@ -0,0 +1,5 @@
+---
+title: Tolerate UTF8 BOM character during frontmatter rendering
+merge_request: 46062
+author:
+type: fixed
diff --git a/changelogs/unreleased/202279-migrate-fa-spinner-to-spinner-for-app-assets-javascripts-vue_merge.yml b/changelogs/unreleased/202279-migrate-fa-spinner-to-spinner-for-app-assets-javascripts-vue_merge.yml
new file mode 100644
index 00000000000..daec1de387b
--- /dev/null
+++ b/changelogs/unreleased/202279-migrate-fa-spinner-to-spinner-for-app-assets-javascripts-vue_merge.yml
@@ -0,0 +1,5 @@
+---
+title: Update loading icon for buttons used in MR's set to merge automatically
+merge_request: 45693
+author:
+type: changed
diff --git a/changelogs/unreleased/205578-feature-flag-pkg-events.yml b/changelogs/unreleased/205578-feature-flag-pkg-events.yml
new file mode 100644
index 00000000000..ce42a88d2b5
--- /dev/null
+++ b/changelogs/unreleased/205578-feature-flag-pkg-events.yml
@@ -0,0 +1,5 @@
+---
+title: Adds feature flag to disable package events
+merge_request: 45802
+author:
+type: changed
diff --git a/changelogs/unreleased/205578-generate-pkg-events-file.yml b/changelogs/unreleased/205578-generate-pkg-events-file.yml
new file mode 100644
index 00000000000..1f7ab455b73
--- /dev/null
+++ b/changelogs/unreleased/205578-generate-pkg-events-file.yml
@@ -0,0 +1,5 @@
+---
+title: Adds rake task to generate package events file
+merge_request: 47118
+author:
+type: added
diff --git a/changelogs/unreleased/207334-design-view-relax-permissions-for-updateimagediffnote-mutation.yml b/changelogs/unreleased/207334-design-view-relax-permissions-for-updateimagediffnote-mutation.yml
new file mode 100644
index 00000000000..31a23da9708
--- /dev/null
+++ b/changelogs/unreleased/207334-design-view-relax-permissions-for-updateimagediffnote-mutation.yml
@@ -0,0 +1,5 @@
+---
+title: Change the mutation and permissions for image note reposition
+merge_request: 47161
+author:
+type: changed
diff --git a/changelogs/unreleased/207334-reposition_note_graphql.yml b/changelogs/unreleased/207334-reposition_note_graphql.yml
new file mode 100644
index 00000000000..23b0b4380c1
--- /dev/null
+++ b/changelogs/unreleased/207334-reposition_note_graphql.yml
@@ -0,0 +1,6 @@
+---
+title: Add repositionImageDiffNote GraphQL mutation to specifically reposition DiffNotes
+ on images
+merge_request: 45958
+author:
+type: added
diff --git a/changelogs/unreleased/207869-lfs-enabled-checks.yml b/changelogs/unreleased/207869-lfs-enabled-checks.yml
new file mode 100644
index 00000000000..30a4a44a3b1
--- /dev/null
+++ b/changelogs/unreleased/207869-lfs-enabled-checks.yml
@@ -0,0 +1,5 @@
+---
+title: Block LFS requests on snippets
+merge_request: 45874
+author:
+type: fixed
diff --git a/changelogs/unreleased/208193-throttle-container-expiration-policy-worker-execution.yml b/changelogs/unreleased/208193-throttle-container-expiration-policy-worker-execution.yml
new file mode 100644
index 00000000000..395a1cdd671
--- /dev/null
+++ b/changelogs/unreleased/208193-throttle-container-expiration-policy-worker-execution.yml
@@ -0,0 +1,5 @@
+---
+title: Throttle container cleanup policies execution by using a limited capacity worker
+merge_request: 40740
+author:
+type: changed
diff --git a/changelogs/unreleased/209784-notes-etag-only-for-empty-response.yml b/changelogs/unreleased/209784-notes-etag-only-for-empty-response.yml
new file mode 100644
index 00000000000..19e3948a592
--- /dev/null
+++ b/changelogs/unreleased/209784-notes-etag-only-for-empty-response.yml
@@ -0,0 +1,5 @@
+---
+title: Only set an ETag for the notes endpoint after all notes have been sent
+merge_request: 46810
+author:
+type: performance
diff --git a/changelogs/unreleased/209916-container-repository-api.yml b/changelogs/unreleased/209916-container-repository-api.yml
new file mode 100644
index 00000000000..892639c535f
--- /dev/null
+++ b/changelogs/unreleased/209916-container-repository-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add container repositories API
+merge_request: 46495
+author:
+type: added
diff --git a/changelogs/unreleased/210327-fix-pipeline-security-tab-filters.yml b/changelogs/unreleased/210327-fix-pipeline-security-tab-filters.yml
new file mode 100644
index 00000000000..bfea6c28f74
--- /dev/null
+++ b/changelogs/unreleased/210327-fix-pipeline-security-tab-filters.yml
@@ -0,0 +1,5 @@
+---
+title: Fix pipeline security tab filters not showing
+merge_request: 47294
+author:
+type: fixed
diff --git a/changelogs/unreleased/211339-forward-deployment-warn-users-on-retry_followup.yml b/changelogs/unreleased/211339-forward-deployment-warn-users-on-retry_followup.yml
new file mode 100644
index 00000000000..3f72e0b8cb2
--- /dev/null
+++ b/changelogs/unreleased/211339-forward-deployment-warn-users-on-retry_followup.yml
@@ -0,0 +1,5 @@
+---
+title: Forward deployment, add modal to warn users on Retry action
+merge_request: 46416
+author:
+type: added
diff --git a/changelogs/unreleased/211357-api-endpoint-to-get-the-gpg-signature-of-a-commit-always-returns-4.yml b/changelogs/unreleased/211357-api-endpoint-to-get-the-gpg-signature-of-a-commit-always-returns-4.yml
new file mode 100644
index 00000000000..93c121701ca
--- /dev/null
+++ b/changelogs/unreleased/211357-api-endpoint-to-get-the-gpg-signature-of-a-commit-always-returns-4.yml
@@ -0,0 +1,5 @@
+---
+title: Fix 404 error from Commit Signature API when using Rugged
+merge_request: 46736
+author:
+type: fixed
diff --git a/changelogs/unreleased/214607-ci-jwt-signing-key-jwks-take-3.yml b/changelogs/unreleased/214607-ci-jwt-signing-key-jwks-take-3.yml
new file mode 100644
index 00000000000..4900c4fa566
--- /dev/null
+++ b/changelogs/unreleased/214607-ci-jwt-signing-key-jwks-take-3.yml
@@ -0,0 +1,5 @@
+---
+title: Add CI JWT signing key to application_setings
+merge_request: 43950
+author:
+type: added
diff --git a/changelogs/unreleased/216008-ec2-for-auto-deploy.yml b/changelogs/unreleased/216008-ec2-for-auto-deploy.yml
new file mode 100644
index 00000000000..3e82961daf7
--- /dev/null
+++ b/changelogs/unreleased/216008-ec2-for-auto-deploy.yml
@@ -0,0 +1,5 @@
+---
+title: Add EC2 to AutoDevOps template
+merge_request: 45651
+author:
+type: changed
diff --git a/changelogs/unreleased/216571-terraform-state-mutations.yml b/changelogs/unreleased/216571-terraform-state-mutations.yml
new file mode 100644
index 00000000000..fdb29c74f72
--- /dev/null
+++ b/changelogs/unreleased/216571-terraform-state-mutations.yml
@@ -0,0 +1,5 @@
+---
+title: Add GraphQL endpoints to lock, unlock and delete Terraform states
+merge_request: 43955
+author:
+type: added
diff --git a/changelogs/unreleased/216974-optional-input-field.yml b/changelogs/unreleased/216974-optional-input-field.yml
new file mode 100644
index 00000000000..1816b6202bf
--- /dev/null
+++ b/changelogs/unreleased/216974-optional-input-field.yml
@@ -0,0 +1,5 @@
+---
+title: Remove default EKS Region dropdown in cluster create form
+merge_request: 43017
+author:
+type: fixed
diff --git a/changelogs/unreleased/217095-design-notifications.yml b/changelogs/unreleased/217095-design-notifications.yml
new file mode 100644
index 00000000000..7396777b5ff
--- /dev/null
+++ b/changelogs/unreleased/217095-design-notifications.yml
@@ -0,0 +1,5 @@
+---
+title: Bugfix email notification recipients for comments on Designs
+merge_request: 46642
+author:
+type: fixed
diff --git a/changelogs/unreleased/217553-permanent-links-to-release-assets-not-found-404.yml b/changelogs/unreleased/217553-permanent-links-to-release-assets-not-found-404.yml
new file mode 100644
index 00000000000..95fc65e5779
--- /dev/null
+++ b/changelogs/unreleased/217553-permanent-links-to-release-assets-not-found-404.yml
@@ -0,0 +1,5 @@
+---
+title: Fix release assets link redirection
+merge_request: 35381
+author:
+type: fixed
diff --git a/changelogs/unreleased/218167-stop-review-for-ecs.yml b/changelogs/unreleased/218167-stop-review-for-ecs.yml
new file mode 100644
index 00000000000..95d49113d84
--- /dev/null
+++ b/changelogs/unreleased/218167-stop-review-for-ecs.yml
@@ -0,0 +1,5 @@
+---
+title: Add a stop review job for ECS
+merge_request: 44717
+author:
+type: added
diff --git a/changelogs/unreleased/218529-change-image-upload-path.yml b/changelogs/unreleased/218529-change-image-upload-path.yml
new file mode 100644
index 00000000000..4e9a3f9c822
--- /dev/null
+++ b/changelogs/unreleased/218529-change-image-upload-path.yml
@@ -0,0 +1,5 @@
+---
+title: Update image upload path (SSE)
+merge_request: 46967
+author:
+type: changed
diff --git a/changelogs/unreleased/218529-display-uploaded-images.yml b/changelogs/unreleased/218529-display-uploaded-images.yml
new file mode 100644
index 00000000000..15c39519b4c
--- /dev/null
+++ b/changelogs/unreleased/218529-display-uploaded-images.yml
@@ -0,0 +1,5 @@
+---
+title: Enable the ability to upload images via the SSE
+merge_request: 36299
+author:
+type: added
diff --git a/changelogs/unreleased/218531-determine-image-relative-paths.yml b/changelogs/unreleased/218531-determine-image-relative-paths.yml
new file mode 100644
index 00000000000..7265f2e6e16
--- /dev/null
+++ b/changelogs/unreleased/218531-determine-image-relative-paths.yml
@@ -0,0 +1,5 @@
+---
+title: Determine image relative paths
+merge_request: 46208
+author:
+type: added
diff --git a/changelogs/unreleased/218666-show-lsf-for-long-name.yml b/changelogs/unreleased/218666-show-lsf-for-long-name.yml
new file mode 100644
index 00000000000..dff85fca6c5
--- /dev/null
+++ b/changelogs/unreleased/218666-show-lsf-for-long-name.yml
@@ -0,0 +1,5 @@
+---
+title: Make files header responsive and remove truncate name
+merge_request: 46406
+author:
+type: changed
diff --git a/changelogs/unreleased/219023-jira-users-mapping.yml b/changelogs/unreleased/219023-jira-users-mapping.yml
new file mode 100644
index 00000000000..c33a8d80448
--- /dev/null
+++ b/changelogs/unreleased/219023-jira-users-mapping.yml
@@ -0,0 +1,5 @@
+---
+title: Match Jira users by email, username or name on jira issues import
+merge_request: 33883
+author:
+type: changed
diff --git a/changelogs/unreleased/220104-fix-race-in-read-only-repository-logic.yml b/changelogs/unreleased/220104-fix-race-in-read-only-repository-logic.yml
new file mode 100644
index 00000000000..41a78821860
--- /dev/null
+++ b/changelogs/unreleased/220104-fix-race-in-read-only-repository-logic.yml
@@ -0,0 +1,5 @@
+---
+title: Fix a race condition checking whether a project is read-only
+merge_request: 45160
+author:
+type: fixed
diff --git a/changelogs/unreleased/220104-git-gc-should-prune-objects.yml b/changelogs/unreleased/220104-git-gc-should-prune-objects.yml
new file mode 100644
index 00000000000..fb2ae03cadd
--- /dev/null
+++ b/changelogs/unreleased/220104-git-gc-should-prune-objects.yml
@@ -0,0 +1,5 @@
+---
+title: Prune loose objects during git garbage collection
+merge_request: 39592
+author:
+type: changed
diff --git a/changelogs/unreleased/220104-read-only-repository-cleanup.yml b/changelogs/unreleased/220104-read-only-repository-cleanup.yml
new file mode 100644
index 00000000000..b9770f253f2
--- /dev/null
+++ b/changelogs/unreleased/220104-read-only-repository-cleanup.yml
@@ -0,0 +1,5 @@
+---
+title: Make the repository read-only while running cleanup
+merge_request: 45058
+author:
+type: changed
diff --git a/changelogs/unreleased/220433-user-stuck-in-2fa-setup-page-even-if-group-disable-2fa-enforce.yml b/changelogs/unreleased/220433-user-stuck-in-2fa-setup-page-even-if-group-disable-2fa-enforce.yml
new file mode 100644
index 00000000000..2ae8f3293b4
--- /dev/null
+++ b/changelogs/unreleased/220433-user-stuck-in-2fa-setup-page-even-if-group-disable-2fa-enforce.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve User stuck in 2FA setup page even if group disable 2FA enforce
+merge_request: 46432
+author:
+type: fixed
diff --git a/changelogs/unreleased/220985-add-npm-project-level-manager-api.yml b/changelogs/unreleased/220985-add-npm-project-level-manager-api.yml
new file mode 100644
index 00000000000..9aedb1cde29
--- /dev/null
+++ b/changelogs/unreleased/220985-add-npm-project-level-manager-api.yml
@@ -0,0 +1,5 @@
+---
+title: NPM project level API
+merge_request: 46867
+author:
+type: added
diff --git a/changelogs/unreleased/221035-ide-solarized-light.yml b/changelogs/unreleased/221035-ide-solarized-light.yml
new file mode 100644
index 00000000000..5ae6f4120f2
--- /dev/null
+++ b/changelogs/unreleased/221035-ide-solarized-light.yml
@@ -0,0 +1,5 @@
+---
+title: Add Web IDE Solarized Light theme support
+merge_request: 46999
+author:
+type: added
diff --git a/changelogs/unreleased/221101-implement-gitlab-ui-component-for-sorting-releases.yml b/changelogs/unreleased/221101-implement-gitlab-ui-component-for-sorting-releases.yml
new file mode 100644
index 00000000000..5cc590dca35
--- /dev/null
+++ b/changelogs/unreleased/221101-implement-gitlab-ui-component-for-sorting-releases.yml
@@ -0,0 +1,5 @@
+---
+title: Add ability to sort releases on Releases page
+merge_request: 43963
+author:
+type: added
diff --git a/changelogs/unreleased/222507-ide-move-file-editor-props.yml b/changelogs/unreleased/222507-ide-move-file-editor-props.yml
new file mode 100644
index 00000000000..4f1395ecd6d
--- /dev/null
+++ b/changelogs/unreleased/222507-ide-move-file-editor-props.yml
@@ -0,0 +1,5 @@
+---
+title: Fix aria label on IDE tab close button
+merge_request: 45709
+author:
+type: fixed
diff --git a/changelogs/unreleased/223768-add-google-analytics-tracking-to-sign-in-pages.yml b/changelogs/unreleased/223768-add-google-analytics-tracking-to-sign-in-pages.yml
new file mode 100644
index 00000000000..29b98310b86
--- /dev/null
+++ b/changelogs/unreleased/223768-add-google-analytics-tracking-to-sign-in-pages.yml
@@ -0,0 +1,5 @@
+---
+title: Add Google Tag Manger to sign in/up and trial pages
+merge_request: 38395
+author:
+type: changed
diff --git a/changelogs/unreleased/224509-chevron-down-svg-issuable.yml b/changelogs/unreleased/224509-chevron-down-svg-issuable.yml
new file mode 100644
index 00000000000..accc855aac4
--- /dev/null
+++ b/changelogs/unreleased/224509-chevron-down-svg-issuable.yml
@@ -0,0 +1,5 @@
+---
+title: Update icons to svg for issuable pages
+merge_request: 47596
+author:
+type: other
diff --git a/changelogs/unreleased/224509-chevron-down-svg-mirror.yml b/changelogs/unreleased/224509-chevron-down-svg-mirror.yml
new file mode 100644
index 00000000000..b48dad58431
--- /dev/null
+++ b/changelogs/unreleased/224509-chevron-down-svg-mirror.yml
@@ -0,0 +1,5 @@
+---
+title: Replace mirror chevron down icon with svg
+merge_request: 47459
+author:
+type: other
diff --git a/changelogs/unreleased/224509-chevron-down-svg-project-branch.yml b/changelogs/unreleased/224509-chevron-down-svg-project-branch.yml
new file mode 100644
index 00000000000..32e9ff0bf53
--- /dev/null
+++ b/changelogs/unreleased/224509-chevron-down-svg-project-branch.yml
@@ -0,0 +1,5 @@
+---
+title: Update chevron-down icon on project branch page
+merge_request: 47460
+author:
+type: other
diff --git a/changelogs/unreleased/224509-replace-add-group-member-chevron.yml b/changelogs/unreleased/224509-replace-add-group-member-chevron.yml
new file mode 100644
index 00000000000..5d95c78726c
--- /dev/null
+++ b/changelogs/unreleased/224509-replace-add-group-member-chevron.yml
@@ -0,0 +1,5 @@
+---
+title: Replace down chevron on invite member/group
+merge_request: 46076
+author:
+type: other
diff --git a/changelogs/unreleased/224509-replace-board-sidebar-chevron.yml b/changelogs/unreleased/224509-replace-board-sidebar-chevron.yml
new file mode 100644
index 00000000000..395d0499abf
--- /dev/null
+++ b/changelogs/unreleased/224509-replace-board-sidebar-chevron.yml
@@ -0,0 +1,5 @@
+---
+title: Replace chevron-down fa-icon in board sidebar
+merge_request: 46075
+author:
+type: other
diff --git a/changelogs/unreleased/224510-replace-fa-chevron-up-with-gitlab-svg-chevron-up-icon.yml b/changelogs/unreleased/224510-replace-fa-chevron-up-with-gitlab-svg-chevron-up-icon.yml
new file mode 100644
index 00000000000..dff2e19b1ff
--- /dev/null
+++ b/changelogs/unreleased/224510-replace-fa-chevron-up-with-gitlab-svg-chevron-up-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-chevron-up with GitLab SVG icon
+merge_request: 46118
+author:
+type: changed
diff --git a/changelogs/unreleased/224587-hide-apply-suggestion-button-for-certain-users.yml b/changelogs/unreleased/224587-hide-apply-suggestion-button-for-certain-users.yml
new file mode 100644
index 00000000000..91c64a53abb
--- /dev/null
+++ b/changelogs/unreleased/224587-hide-apply-suggestion-button-for-certain-users.yml
@@ -0,0 +1,5 @@
+---
+title: Hide apply suggestion button for anonymous users
+merge_request: 47071
+author:
+type: changed
diff --git a/changelogs/unreleased/225180-replace-fa-warning-icons-with-gitlab-svg-warning-solid-icon.yml b/changelogs/unreleased/225180-replace-fa-warning-icons-with-gitlab-svg-warning-solid-icon.yml
new file mode 100644
index 00000000000..67ecca873d8
--- /dev/null
+++ b/changelogs/unreleased/225180-replace-fa-warning-icons-with-gitlab-svg-warning-solid-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-warning icons with GitLab SVG warning-solid icon
+merge_request: 46214
+author:
+type: changed
diff --git a/changelogs/unreleased/225953-replace-fa-external-link-icons-with-gitlab-svg-external-link-icon.yml b/changelogs/unreleased/225953-replace-fa-external-link-icons-with-gitlab-svg-external-link-icon.yml
new file mode 100644
index 00000000000..0d73de87143
--- /dev/null
+++ b/changelogs/unreleased/225953-replace-fa-external-link-icons-with-gitlab-svg-external-link-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace external-link icons with GitLab SVG
+merge_request: 45685
+author:
+type: changed
diff --git a/changelogs/unreleased/225956-replace-fa-check-icons-with-gitlab-svg-check-icon.yml b/changelogs/unreleased/225956-replace-fa-check-icons-with-gitlab-svg-check-icon.yml
new file mode 100644
index 00000000000..da46c724a2c
--- /dev/null
+++ b/changelogs/unreleased/225956-replace-fa-check-icons-with-gitlab-svg-check-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-check icons with GitLab SVG check icon
+merge_request: 43353
+author:
+type: changed
diff --git a/changelogs/unreleased/227415-rename-or-add-a-new-draft-alias-to-the-wip-quick-action.yml b/changelogs/unreleased/227415-rename-or-add-a-new-draft-alias-to-the-wip-quick-action.yml
new file mode 100644
index 00000000000..b71e5d31067
--- /dev/null
+++ b/changelogs/unreleased/227415-rename-or-add-a-new-draft-alias-to-the-wip-quick-action.yml
@@ -0,0 +1,5 @@
+---
+title: Add a /draft alias to the /wip quick action
+merge_request: 46277
+author:
+type: added
diff --git a/changelogs/unreleased/227808-improve-container-registry-client-supports-tag-delete.yml b/changelogs/unreleased/227808-improve-container-registry-client-supports-tag-delete.yml
new file mode 100644
index 00000000000..8d4d28d8b23
--- /dev/null
+++ b/changelogs/unreleased/227808-improve-container-registry-client-supports-tag-delete.yml
@@ -0,0 +1,5 @@
+---
+title: Improve the container registry client tags delete method
+merge_request: 46989
+author:
+type: changed
diff --git a/changelogs/unreleased/229003-migrate-notifications-tooltip.yml b/changelogs/unreleased/229003-migrate-notifications-tooltip.yml
new file mode 100644
index 00000000000..71ca7ce9674
--- /dev/null
+++ b/changelogs/unreleased/229003-migrate-notifications-tooltip.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate collapsed notification tooltip
+merge_request: 45453
+author: artychan
+type: other
diff --git a/changelogs/unreleased/229300-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml b/changelogs/unreleased/229300-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml
new file mode 100644
index 00000000000..675c90449a9
--- /dev/null
+++ b/changelogs/unreleased/229300-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate Bootstrap buttons to GitLab UI buttons for attach a file form actions
+merge_request: 46041
+author:
+type: other
diff --git a/changelogs/unreleased/229308-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml b/changelogs/unreleased/229308-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml
new file mode 100644
index 00000000000..769cf8dc3f9
--- /dev/null
+++ b/changelogs/unreleased/229308-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml
@@ -0,0 +1,5 @@
+---
+title: Replace close button in Scheduling Pipelines user notice with GlButton
+merge_request: 46264
+author:
+type: other
diff --git a/changelogs/unreleased/229674-update-change-username-modal.yml b/changelogs/unreleased/229674-update-change-username-modal.yml
new file mode 100644
index 00000000000..ab2171c6918
--- /dev/null
+++ b/changelogs/unreleased/229674-update-change-username-modal.yml
@@ -0,0 +1,5 @@
+---
+title: Update change username modal
+merge_request: 44325
+author:
+type: changed
diff --git a/changelogs/unreleased/229685-update-leave-group-modal.yml b/changelogs/unreleased/229685-update-leave-group-modal.yml
new file mode 100644
index 00000000000..a1155f452fb
--- /dev/null
+++ b/changelogs/unreleased/229685-update-leave-group-modal.yml
@@ -0,0 +1,5 @@
+---
+title: Update leave group modal to gl-modal
+merge_request: 41817
+author:
+type: changed
diff --git a/changelogs/unreleased/229701-aqualls-stop-jobs-modal.yml b/changelogs/unreleased/229701-aqualls-stop-jobs-modal.yml
new file mode 100644
index 00000000000..f8c8582e833
--- /dev/null
+++ b/changelogs/unreleased/229701-aqualls-stop-jobs-modal.yml
@@ -0,0 +1,5 @@
+---
+title: Update stop all jobs modal to latest modal
+merge_request: 46157
+author:
+type: changed
diff --git a/changelogs/unreleased/229703-aqualls-promote-label-modal.yml b/changelogs/unreleased/229703-aqualls-promote-label-modal.yml
new file mode 100644
index 00000000000..8d3557fa553
--- /dev/null
+++ b/changelogs/unreleased/229703-aqualls-promote-label-modal.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate DeprecatedModal to GitLab UI Modal for promoted labels
+merge_request: 46047
+author:
+type: changed
diff --git a/changelogs/unreleased/229704-aqualls-metrics-modal.yml b/changelogs/unreleased/229704-aqualls-metrics-modal.yml
new file mode 100644
index 00000000000..04377daf53b
--- /dev/null
+++ b/changelogs/unreleased/229704-aqualls-metrics-modal.yml
@@ -0,0 +1,5 @@
+---
+title: Update detailed_metric.vue modal to match Pajamas guidelines
+merge_request: 46183
+author:
+type: changed
diff --git a/changelogs/unreleased/229918-issuedata-comments.yml b/changelogs/unreleased/229918-issuedata-comments.yml
new file mode 100644
index 00000000000..90250d977ca
--- /dev/null
+++ b/changelogs/unreleased/229918-issuedata-comments.yml
@@ -0,0 +1,5 @@
+---
+title: UsageData for issues added/removed/edited
+merge_request: 45609
+author:
+type: added
diff --git a/changelogs/unreleased/230724-matej-tabs-migration-ide-pipelines-list.yml b/changelogs/unreleased/230724-matej-tabs-migration-ide-pipelines-list.yml
new file mode 100644
index 00000000000..0663865afcc
--- /dev/null
+++ b/changelogs/unreleased/230724-matej-tabs-migration-ide-pipelines-list.yml
@@ -0,0 +1,5 @@
+---
+title: Update Web IDE pipelines panel to use our design system component
+merge_request: 45007
+author: matejlatin
+type: other
diff --git a/changelogs/unreleased/231234-remove-unstaged-icon.yml b/changelogs/unreleased/231234-remove-unstaged-icon.yml
new file mode 100644
index 00000000000..5d0b676ca5e
--- /dev/null
+++ b/changelogs/unreleased/231234-remove-unstaged-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Removes the hamburger icon in the Changes tab in Web IDE
+merge_request: 45717
+author:
+type: fixed
diff --git a/changelogs/unreleased/231494-draft-system-notes.yml b/changelogs/unreleased/231494-draft-system-notes.yml
new file mode 100644
index 00000000000..adabce0f707
--- /dev/null
+++ b/changelogs/unreleased/231494-draft-system-notes.yml
@@ -0,0 +1,5 @@
+---
+title: Update system note when marking merge request as draft or ready
+merge_request: 45644
+author:
+type: changed
diff --git a/changelogs/unreleased/231777-switching-branches-in-repo-tree-view-navigates-backwards.yml b/changelogs/unreleased/231777-switching-branches-in-repo-tree-view-navigates-backwards.yml
new file mode 100644
index 00000000000..9212cb18331
--- /dev/null
+++ b/changelogs/unreleased/231777-switching-branches-in-repo-tree-view-navigates-backwards.yml
@@ -0,0 +1,5 @@
+---
+title: Fix loading current directory when changing branches
+merge_request: 46479
+author:
+type: fixed
diff --git a/changelogs/unreleased/232569-update-the-milestone-dropdown-combobox-to-display-separated-sectio.yml b/changelogs/unreleased/232569-update-the-milestone-dropdown-combobox-to-display-separated-sectio.yml
new file mode 100644
index 00000000000..238ce2c9cc0
--- /dev/null
+++ b/changelogs/unreleased/232569-update-the-milestone-dropdown-combobox-to-display-separated-sectio.yml
@@ -0,0 +1,6 @@
+---
+title: Update the milestone dropdown combobox to display separated sections
+ and badge counters
+merge_request: 43427
+author:
+type: added
diff --git a/changelogs/unreleased/232817-display-mr-submodules-icon.yml b/changelogs/unreleased/232817-display-mr-submodules-icon.yml
new file mode 100644
index 00000000000..204f9867988
--- /dev/null
+++ b/changelogs/unreleased/232817-display-mr-submodules-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Display submodules in MR tree and file header
+merge_request: 46840
+author:
+type: fixed
diff --git a/changelogs/unreleased/233278-in-global-search-if-there-is-only-one-result-redirect-to-that-page.yml b/changelogs/unreleased/233278-in-global-search-if-there-is-only-one-result-redirect-to-that-page.yml
new file mode 100644
index 00000000000..4610a56a4c9
--- /dev/null
+++ b/changelogs/unreleased/233278-in-global-search-if-there-is-only-one-result-redirect-to-that-page.yml
@@ -0,0 +1,5 @@
+---
+title: Search Autocomplete add GFM support for issues
+merge_request: 44930
+author:
+type: changed
diff --git a/changelogs/unreleased/233387-remove-lc-temp-index.yml b/changelogs/unreleased/233387-remove-lc-temp-index.yml
new file mode 100644
index 00000000000..ef28429f6fc
--- /dev/null
+++ b/changelogs/unreleased/233387-remove-lc-temp-index.yml
@@ -0,0 +1,5 @@
+---
+title: Remove temp index on job artifacts
+merge_request: 45565
+author:
+type: changed
diff --git a/changelogs/unreleased/233479-add-test-case-move-support.yml b/changelogs/unreleased/233479-add-test-case-move-support.yml
new file mode 100644
index 00000000000..b989124a64f
--- /dev/null
+++ b/changelogs/unreleased/233479-add-test-case-move-support.yml
@@ -0,0 +1,5 @@
+---
+title: Expose moved and movedTo attributes in Issues query
+merge_request: 46447
+author:
+type: added
diff --git a/changelogs/unreleased/233669-remove-bootstrap-ping.yml b/changelogs/unreleased/233669-remove-bootstrap-ping.yml
new file mode 100644
index 00000000000..8306ec9862b
--- /dev/null
+++ b/changelogs/unreleased/233669-remove-bootstrap-ping.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap classes for alerts in ping consent
+merge_request: 45723
+author:
+type: other
diff --git a/changelogs/unreleased/233965-suggest-pipeline-flow-second-step-should-open-on-page-load.yml b/changelogs/unreleased/233965-suggest-pipeline-flow-second-step-should-open-on-page-load.yml
new file mode 100644
index 00000000000..e00875bf91e
--- /dev/null
+++ b/changelogs/unreleased/233965-suggest-pipeline-flow-second-step-should-open-on-page-load.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Suggest Pipeline flow second step not loading
+merge_request: 47419
+author:
+type: fixed
diff --git a/changelogs/unreleased/235385-ide-monokai-theme.yml b/changelogs/unreleased/235385-ide-monokai-theme.yml
new file mode 100644
index 00000000000..a63c27bdd4c
--- /dev/null
+++ b/changelogs/unreleased/235385-ide-monokai-theme.yml
@@ -0,0 +1,5 @@
+---
+title: Monokai theme for the Web IDE
+merge_request: 46901
+author:
+type: added
diff --git a/changelogs/unreleased/235436-add-header-fuzzing-docs.yml b/changelogs/unreleased/235436-add-header-fuzzing-docs.yml
new file mode 100644
index 00000000000..bef6992fb6a
--- /dev/null
+++ b/changelogs/unreleased/235436-add-header-fuzzing-docs.yml
@@ -0,0 +1,5 @@
+---
+title: Support fuzzing HTTP headers with API Fuzzing
+merge_request: 47727
+author:
+type: added
diff --git a/changelogs/unreleased/235460_remove_sse_erb_support_feature_flag.yml b/changelogs/unreleased/235460_remove_sse_erb_support_feature_flag.yml
new file mode 100644
index 00000000000..12a42066a4f
--- /dev/null
+++ b/changelogs/unreleased/235460_remove_sse_erb_support_feature_flag.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for .md.erb files in Static Site Editor
+merge_request: 42353
+author:
+type: added
diff --git a/changelogs/unreleased/235758-track-ci-secrets-management-vault-usage.yml b/changelogs/unreleased/235758-track-ci-secrets-management-vault-usage.yml
new file mode 100644
index 00000000000..1fe85b3ef81
--- /dev/null
+++ b/changelogs/unreleased/235758-track-ci-secrets-management-vault-usage.yml
@@ -0,0 +1,5 @@
+---
+title: Track usage of CI Secrets Management (Vault secrets)
+merge_request: 46515
+author:
+type: added
diff --git a/changelogs/unreleased/236465-search-results-sort-ui.yml b/changelogs/unreleased/236465-search-results-sort-ui.yml
new file mode 100644
index 00000000000..7d1a1e62067
--- /dev/null
+++ b/changelogs/unreleased/236465-search-results-sort-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Add ability to sort search results for issues and merge requests
+merge_request: 45003
+author:
+type: added
diff --git a/changelogs/unreleased/237843-typos-when-deleting-a-project-repository.yml b/changelogs/unreleased/237843-typos-when-deleting-a-project-repository.yml
new file mode 100644
index 00000000000..f592e62477e
--- /dev/null
+++ b/changelogs/unreleased/237843-typos-when-deleting-a-project-repository.yml
@@ -0,0 +1,5 @@
+---
+title: Fix typos when deleting a project repository
+merge_request: 46204
+author: Edstub207
+type: fixed
diff --git a/changelogs/unreleased/237905-add-signup-enabled-alert.yml b/changelogs/unreleased/237905-add-signup-enabled-alert.yml
new file mode 100644
index 00000000000..0e76ad97930
--- /dev/null
+++ b/changelogs/unreleased/237905-add-signup-enabled-alert.yml
@@ -0,0 +1,5 @@
+---
+title: Add user callout to alert admins that registration is open by default
+merge_request: 47425
+author:
+type: added
diff --git a/changelogs/unreleased/238156_remove_old_security_findings_from_database.yml b/changelogs/unreleased/238156_remove_old_security_findings_from_database.yml
new file mode 100644
index 00000000000..c104e8c8e6b
--- /dev/null
+++ b/changelogs/unreleased/238156_remove_old_security_findings_from_database.yml
@@ -0,0 +1,5 @@
+---
+title: Remove all records from `security_findings` table
+merge_request: 44312
+author:
+type: fixed
diff --git a/changelogs/unreleased/238594-package-detail-on-mobile-view-is-impossible-to-see-multiple-tags.yml b/changelogs/unreleased/238594-package-detail-on-mobile-view-is-impossible-to-see-multiple-tags.yml
new file mode 100644
index 00000000000..2775c2ee9a7
--- /dev/null
+++ b/changelogs/unreleased/238594-package-detail-on-mobile-view-is-impossible-to-see-multiple-tags.yml
@@ -0,0 +1,5 @@
+---
+title: 'Package details: on mobile show all the tags'
+merge_request: 46679
+author:
+type: changed
diff --git a/changelogs/unreleased/239305-resolve-ip-address-for-audit.yml b/changelogs/unreleased/239305-resolve-ip-address-for-audit.yml
new file mode 100644
index 00000000000..b6d1f32866d
--- /dev/null
+++ b/changelogs/unreleased/239305-resolve-ip-address-for-audit.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve request IP address on audit event
+merge_request: 46114
+author:
+type: changed
diff --git a/changelogs/unreleased/239518-package-multiple-build-infos.yml b/changelogs/unreleased/239518-package-multiple-build-infos.yml
new file mode 100644
index 00000000000..1cf35cb311b
--- /dev/null
+++ b/changelogs/unreleased/239518-package-multiple-build-infos.yml
@@ -0,0 +1,5 @@
+---
+title: Associate multiple pipelines with packages and package files
+merge_request: 44348
+author:
+type: added
diff --git a/changelogs/unreleased/240887-packages-composer-semver-not-fully-supported.yml b/changelogs/unreleased/240887-packages-composer-semver-not-fully-supported.yml
new file mode 100644
index 00000000000..fa4d4e283f6
--- /dev/null
+++ b/changelogs/unreleased/240887-packages-composer-semver-not-fully-supported.yml
@@ -0,0 +1,5 @@
+---
+title: Allow semver versions in composer packages
+merge_request: 46301
+author:
+type: fixed
diff --git a/changelogs/unreleased/241194-enable-vue_group_members_list-ff-by-default.yml b/changelogs/unreleased/241194-enable-vue_group_members_list-ff-by-default.yml
new file mode 100644
index 00000000000..e5b490c0cca
--- /dev/null
+++ b/changelogs/unreleased/241194-enable-vue_group_members_list-ff-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Enable `vue_group_members_list` feature flag by default
+merge_request: 47427
+author:
+type: changed
diff --git a/changelogs/unreleased/241267-add-partitioned-table-model.yml b/changelogs/unreleased/241267-add-partitioned-table-model.yml
new file mode 100644
index 00000000000..aabf39530d8
--- /dev/null
+++ b/changelogs/unreleased/241267-add-partitioned-table-model.yml
@@ -0,0 +1,5 @@
+---
+title: Add database view for partitioned tables
+merge_request: 45591
+author:
+type: other
diff --git a/changelogs/unreleased/241267-add-postgres-partition-model.yml b/changelogs/unreleased/241267-add-postgres-partition-model.yml
new file mode 100644
index 00000000000..b11bbdb4849
--- /dev/null
+++ b/changelogs/unreleased/241267-add-postgres-partition-model.yml
@@ -0,0 +1,5 @@
+---
+title: Add database view for partitions
+merge_request: 45592
+author:
+type: other
diff --git a/changelogs/unreleased/241378_until_executed_deduplication_strategy.yml b/changelogs/unreleased/241378_until_executed_deduplication_strategy.yml
new file mode 100644
index 00000000000..b9f202273e5
--- /dev/null
+++ b/changelogs/unreleased/241378_until_executed_deduplication_strategy.yml
@@ -0,0 +1,5 @@
+---
+title: Add until_executed deduplication strategy
+merge_request: 42223
+author:
+type: added
diff --git a/changelogs/unreleased/241534-test-report-modal.yml b/changelogs/unreleased/241534-test-report-modal.yml
new file mode 100644
index 00000000000..c11110bf54f
--- /dev/null
+++ b/changelogs/unreleased/241534-test-report-modal.yml
@@ -0,0 +1,5 @@
+---
+title: Move test report system output to modal
+merge_request: 45575
+author:
+type: changed
diff --git a/changelogs/unreleased/241957-remove-v-html-from-app-assets-javascripts-notes-components-discuss.yml b/changelogs/unreleased/241957-remove-v-html-from-app-assets-javascripts-notes-components-discuss.yml
new file mode 100644
index 00000000000..ee781be5134
--- /dev/null
+++ b/changelogs/unreleased/241957-remove-v-html-from-app-assets-javascripts-notes-components-discuss.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with GlSprintf in notes/.../discussion_filter_note.vue
+merge_request: 41482
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/241980-uploads-count-as-used-storage.yml b/changelogs/unreleased/241980-uploads-count-as-used-storage.yml
new file mode 100644
index 00000000000..cfb14145757
--- /dev/null
+++ b/changelogs/unreleased/241980-uploads-count-as-used-storage.yml
@@ -0,0 +1,5 @@
+---
+title: Account for uploads as part of used repository storage
+merge_request: 46941
+author:
+type: added
diff --git a/changelogs/unreleased/241980-uploalds-on-storage-graphql.yml b/changelogs/unreleased/241980-uploalds-on-storage-graphql.yml
new file mode 100644
index 00000000000..cb64f2e9208
--- /dev/null
+++ b/changelogs/unreleased/241980-uploalds-on-storage-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: 'GraphQL: Expose uploads_size for project_statistics and root_storage_statistics'
+merge_request: 47820
+author:
+type: added
diff --git a/changelogs/unreleased/241990-improve-project-labels-page-consistency.yml b/changelogs/unreleased/241990-improve-project-labels-page-consistency.yml
new file mode 100644
index 00000000000..ca87bab003c
--- /dev/null
+++ b/changelogs/unreleased/241990-improve-project-labels-page-consistency.yml
@@ -0,0 +1,5 @@
+---
+title: Improve project labels page card layout consistency
+merge_request: 45311
+author:
+type: fixed
diff --git a/changelogs/unreleased/243555-update-whitelist-blacklist-to-allowlist-denylist-in-signup-restric.yml b/changelogs/unreleased/243555-update-whitelist-blacklist-to-allowlist-denylist-in-signup-restric.yml
new file mode 100644
index 00000000000..f6844bf1cb7
--- /dev/null
+++ b/changelogs/unreleased/243555-update-whitelist-blacklist-to-allowlist-denylist-in-signup-restric.yml
@@ -0,0 +1,5 @@
+---
+title: Update whitelist/blacklist to allowlist/denylist in Signup restrictions window
+merge_request: 46168
+author:
+type: changed
diff --git a/changelogs/unreleased/243607-background-migration-for-setting-jira-tracker-data-deployment-type.yml b/changelogs/unreleased/243607-background-migration-for-setting-jira-tracker-data-deployment-type.yml
new file mode 100644
index 00000000000..12f9de6cfb3
--- /dev/null
+++ b/changelogs/unreleased/243607-background-migration-for-setting-jira-tracker-data-deployment-type.yml
@@ -0,0 +1,5 @@
+---
+title: Background migration for setting Jira tracker data deployment type
+merge_request: 46368
+author:
+type: changed
diff --git a/changelogs/unreleased/244289-quickaction-with-codeblocks.yml b/changelogs/unreleased/244289-quickaction-with-codeblocks.yml
new file mode 100644
index 00000000000..6dc0df9e009
--- /dev/null
+++ b/changelogs/unreleased/244289-quickaction-with-codeblocks.yml
@@ -0,0 +1,5 @@
+---
+title: Fix QuickActions not working if written before a codeblock
+merge_request: 46401
+author:
+type: fixed
diff --git a/changelogs/unreleased/244380_populate_has_vulnerabilities_values.yml b/changelogs/unreleased/244380_populate_has_vulnerabilities_values.yml
new file mode 100644
index 00000000000..96ef13081f4
--- /dev/null
+++ b/changelogs/unreleased/244380_populate_has_vulnerabilities_values.yml
@@ -0,0 +1,5 @@
+---
+title: Populate values for `has_vulnerabilities` column of `project_settings` table
+merge_request: 46890
+author:
+type: fixed
diff --git a/changelogs/unreleased/244831-split-pipelines-for-merged-results-and-merge-train-check-boxes.yml b/changelogs/unreleased/244831-split-pipelines-for-merged-results-and-merge-train-check-boxes.yml
new file mode 100644
index 00000000000..2aac8e603aa
--- /dev/null
+++ b/changelogs/unreleased/244831-split-pipelines-for-merged-results-and-merge-train-check-boxes.yml
@@ -0,0 +1,5 @@
+---
+title: Add merge trains enabled setting to project ci cd settings
+merge_request: 45834
+author:
+type: other
diff --git a/changelogs/unreleased/244868-add-search-filters-to-metadata.yml b/changelogs/unreleased/244868-add-search-filters-to-metadata.yml
new file mode 100644
index 00000000000..40bf04100e8
--- /dev/null
+++ b/changelogs/unreleased/244868-add-search-filters-to-metadata.yml
@@ -0,0 +1,5 @@
+---
+title: Add new search params to metadata
+merge_request: 45896
+author:
+type: changed
diff --git a/changelogs/unreleased/244923-feature-flag-rollout-of-search_filter_by_confidential.yml b/changelogs/unreleased/244923-feature-flag-rollout-of-search_filter_by_confidential.yml
new file mode 100644
index 00000000000..806a15dc992
--- /dev/null
+++ b/changelogs/unreleased/244923-feature-flag-rollout-of-search_filter_by_confidential.yml
@@ -0,0 +1,5 @@
+---
+title: Remove search_filter_by_confidential Feature Flag
+merge_request: 45819
+author:
+type: changed
diff --git a/changelogs/unreleased/245263-fix-cleanup-service-no-repository.yml b/changelogs/unreleased/245263-fix-cleanup-service-no-repository.yml
new file mode 100644
index 00000000000..7bb7f8366f9
--- /dev/null
+++ b/changelogs/unreleased/245263-fix-cleanup-service-no-repository.yml
@@ -0,0 +1,5 @@
+---
+title: Do not fail when cleaning up MR with no repository
+merge_request: 47744
+author:
+type: fixed
diff --git a/changelogs/unreleased/245263-mr-refs-cleanup-old-mrs.yml b/changelogs/unreleased/245263-mr-refs-cleanup-old-mrs.yml
new file mode 100644
index 00000000000..6e105559cfb
--- /dev/null
+++ b/changelogs/unreleased/245263-mr-refs-cleanup-old-mrs.yml
@@ -0,0 +1,5 @@
+---
+title: Backfill cleanup schedules for old closed/merged MRs
+merge_request: 46782
+author:
+type: other
diff --git a/changelogs/unreleased/245263-mr-refs-cleanup-scheduler.yml b/changelogs/unreleased/245263-mr-refs-cleanup-scheduler.yml
new file mode 100644
index 00000000000..f20f2f99233
--- /dev/null
+++ b/changelogs/unreleased/245263-mr-refs-cleanup-scheduler.yml
@@ -0,0 +1,5 @@
+---
+title: Schedule clean up of merge request refs efficiently
+merge_request: 46758
+author:
+type: performance
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..0ba6226744c
--- /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: 45718
+author:
+type: fixed
diff --git a/changelogs/unreleased/249145-update-blank-dag.yml b/changelogs/unreleased/249145-update-blank-dag.yml
new file mode 100644
index 00000000000..73a77fd2620
--- /dev/null
+++ b/changelogs/unreleased/249145-update-blank-dag.yml
@@ -0,0 +1,5 @@
+---
+title: Add new text and tab name for DAG
+merge_request: 47415
+author:
+type: changed
diff --git a/changelogs/unreleased/249661-ci_lint_vue-default-true.yml b/changelogs/unreleased/249661-ci_lint_vue-default-true.yml
new file mode 100644
index 00000000000..6c3fdd4c93c
--- /dev/null
+++ b/changelogs/unreleased/249661-ci_lint_vue-default-true.yml
@@ -0,0 +1,5 @@
+---
+title: Load CI lint checks without refreshing the page
+merge_request: 46801
+author:
+type: changed
diff --git a/changelogs/unreleased/250323-move-projects_with_error_tracking_enabled-to-core.yml b/changelogs/unreleased/250323-move-projects_with_error_tracking_enabled-to-core.yml
new file mode 100644
index 00000000000..8a602a858bd
--- /dev/null
+++ b/changelogs/unreleased/250323-move-projects_with_error_tracking_enabled-to-core.yml
@@ -0,0 +1,5 @@
+---
+title: Moves projects_with_error_tracking_enabled ping usage to Core
+merge_request: 46556
+author:
+type: changed
diff --git a/changelogs/unreleased/250484-add-locked-and-confidential-badge-to-issue-sticky-header.yml b/changelogs/unreleased/250484-add-locked-and-confidential-badge-to-issue-sticky-header.yml
new file mode 100644
index 00000000000..514a7b5b3c0
--- /dev/null
+++ b/changelogs/unreleased/250484-add-locked-and-confidential-badge-to-issue-sticky-header.yml
@@ -0,0 +1,5 @@
+---
+title: Add locked and confidential badge to issue sticky header
+merge_request: 46996
+author:
+type: added
diff --git a/changelogs/unreleased/251011-add-count_all-count_7d-count_28d-top-level-keys-to-usage-data.yml b/changelogs/unreleased/251011-add-count_all-count_7d-count_28d-top-level-keys-to-usage-data.yml
new file mode 100644
index 00000000000..114752547b4
--- /dev/null
+++ b/changelogs/unreleased/251011-add-count_all-count_7d-count_28d-top-level-keys-to-usage-data.yml
@@ -0,0 +1,5 @@
+---
+title: Add basic top level keys license, settings, and counts_weekly for usage data payload
+merge_request: 45540
+author:
+type: added
diff --git a/changelogs/unreleased/251015-add-jobs-to-pipeline-type.yml b/changelogs/unreleased/251015-add-jobs-to-pipeline-type.yml
new file mode 100644
index 00000000000..17cf141ebd9
--- /dev/null
+++ b/changelogs/unreleased/251015-add-jobs-to-pipeline-type.yml
@@ -0,0 +1,5 @@
+---
+title: Add jobs field with secureReportTypes argument to Ci::PipelineType
+merge_request: 45837
+author:
+type: added
diff --git a/changelogs/unreleased/251136-delete-selected-button-in-container-registry-is-not-visible-on-nar.yml b/changelogs/unreleased/251136-delete-selected-button-in-container-registry-is-not-visible-on-nar.yml
new file mode 100644
index 00000000000..ccf44a02ca9
--- /dev/null
+++ b/changelogs/unreleased/251136-delete-selected-button-in-container-registry-is-not-visible-on-nar.yml
@@ -0,0 +1,5 @@
+---
+title: 'container registry: show delete selected button on medium viewports'
+merge_request: 46699
+author:
+type: fixed
diff --git a/changelogs/unreleased/251211-add-sorting-to-search-api.yml b/changelogs/unreleased/251211-add-sorting-to-search-api.yml
new file mode 100644
index 00000000000..3f0764bda69
--- /dev/null
+++ b/changelogs/unreleased/251211-add-sorting-to-search-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add ability to sort to search API
+merge_request: 46646
+author:
+type: added
diff --git a/changelogs/unreleased/25145-remove-expand-sha-button-pipeline.yml b/changelogs/unreleased/25145-remove-expand-sha-button-pipeline.yml
new file mode 100644
index 00000000000..d95d4916a1f
--- /dev/null
+++ b/changelogs/unreleased/25145-remove-expand-sha-button-pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unnecessary expand sha button in pipelines page
+merge_request: 47012
+author:
+type: fixed
diff --git a/changelogs/unreleased/252137-sync-sticky-header-issue-status.yml b/changelogs/unreleased/252137-sync-sticky-header-issue-status.yml
new file mode 100644
index 00000000000..c077a67c2a9
--- /dev/null
+++ b/changelogs/unreleased/252137-sync-sticky-header-issue-status.yml
@@ -0,0 +1,5 @@
+---
+title: Fix sticky header issue status not syncing
+merge_request: 45895
+author:
+type: fixed
diff --git a/changelogs/unreleased/2529-code-quality-severity-rating.yml b/changelogs/unreleased/2529-code-quality-severity-rating.yml
new file mode 100644
index 00000000000..032adb8bf1c
--- /dev/null
+++ b/changelogs/unreleased/2529-code-quality-severity-rating.yml
@@ -0,0 +1,5 @@
+---
+title: Show code quality severity rating in the merge request details page
+merge_request: 46829
+author:
+type: changed
diff --git a/changelogs/unreleased/254228-background-migration-for-pipeline-id.yml b/changelogs/unreleased/254228-background-migration-for-pipeline-id.yml
new file mode 100644
index 00000000000..85a75633ad3
--- /dev/null
+++ b/changelogs/unreleased/254228-background-migration-for-pipeline-id.yml
@@ -0,0 +1,5 @@
+---
+title: Add migration to populate pipeline_id in Vulnerability Feedback
+merge_request: 46266
+author:
+type: added
diff --git a/changelogs/unreleased/254627-include-diff-note-details-in-notes-json.yml b/changelogs/unreleased/254627-include-diff-note-details-in-notes-json.yml
new file mode 100644
index 00000000000..0dd43b83846
--- /dev/null
+++ b/changelogs/unreleased/254627-include-diff-note-details-in-notes-json.yml
@@ -0,0 +1,5 @@
+---
+title: Don't refresh all discussions for a new diff note on a merge request
+merge_request: 43015
+author:
+type: performance
diff --git a/changelogs/unreleased/255519-migrate-existing-generic-alert-endpoints-to-http-integrations-form.yml b/changelogs/unreleased/255519-migrate-existing-generic-alert-endpoints-to-http-integrations-form.yml
new file mode 100644
index 00000000000..7b431783ed9
--- /dev/null
+++ b/changelogs/unreleased/255519-migrate-existing-generic-alert-endpoints-to-http-integrations-form.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate Alert Service to HTTP Integrations model
+merge_request: 46188
+author:
+type: added
diff --git a/changelogs/unreleased/255889-remove-feedback-alert-ondemand-scans.yml b/changelogs/unreleased/255889-remove-feedback-alert-ondemand-scans.yml
new file mode 100644
index 00000000000..c0294ce4af7
--- /dev/null
+++ b/changelogs/unreleased/255889-remove-feedback-alert-ondemand-scans.yml
@@ -0,0 +1,5 @@
+---
+title: Remove feedback alert from on-demand scans form
+merge_request: 45217
+author:
+type: changed
diff --git a/changelogs/unreleased/255970-confirmation-panels-for-significant-actions-are-inconsistent-in-te.yml b/changelogs/unreleased/255970-confirmation-panels-for-significant-actions-are-inconsistent-in-te.yml
new file mode 100644
index 00000000000..2b829c521e4
--- /dev/null
+++ b/changelogs/unreleased/255970-confirmation-panels-for-significant-actions-are-inconsistent-in-te.yml
@@ -0,0 +1,5 @@
+---
+title: Make delete repo prompts consistent
+merge_request: 47117
+author:
+type: fixed
diff --git a/changelogs/unreleased/257822-null-byes-in-url.yml b/changelogs/unreleased/257822-null-byes-in-url.yml
new file mode 100644
index 00000000000..6d9ef42929a
--- /dev/null
+++ b/changelogs/unreleased/257822-null-byes-in-url.yml
@@ -0,0 +1,5 @@
+---
+title: Handle malformed strings in URL
+merge_request: 45701
+author:
+type: fixed
diff --git a/changelogs/unreleased/257879-user-admin-approval-admin-email-notification.yml b/changelogs/unreleased/257879-user-admin-approval-admin-email-notification.yml
new file mode 100644
index 00000000000..0b60c90ed8a
--- /dev/null
+++ b/changelogs/unreleased/257879-user-admin-approval-admin-email-notification.yml
@@ -0,0 +1,5 @@
+---
+title: Send email notifications to admins about users pending approval
+merge_request: 46895
+author:
+type: added
diff --git a/changelogs/unreleased/257880-user-admin-approval-email-when-approved.yml b/changelogs/unreleased/257880-user-admin-approval-email-when-approved.yml
new file mode 100644
index 00000000000..325cf994442
--- /dev/null
+++ b/changelogs/unreleased/257880-user-admin-approval-email-when-approved.yml
@@ -0,0 +1,5 @@
+---
+title: Email user on admin account approval
+merge_request: 45947
+author:
+type: added
diff --git a/changelogs/unreleased/258209-filters-params-remain-when-switching-tabs.yml b/changelogs/unreleased/258209-filters-params-remain-when-switching-tabs.yml
new file mode 100644
index 00000000000..1fbbda31760
--- /dev/null
+++ b/changelogs/unreleased/258209-filters-params-remain-when-switching-tabs.yml
@@ -0,0 +1,5 @@
+---
+title: Reset search results filters whenever a user changes scope.
+merge_request: 45808
+author:
+type: fixed
diff --git a/changelogs/unreleased/258215-add-fuzzy-search-on-full-path-in-groups.yml b/changelogs/unreleased/258215-add-fuzzy-search-on-full-path-in-groups.yml
new file mode 100644
index 00000000000..6e2b0c817f7
--- /dev/null
+++ b/changelogs/unreleased/258215-add-fuzzy-search-on-full-path-in-groups.yml
@@ -0,0 +1,5 @@
+---
+title: Add fuzzy-search on full path in Groups API
+merge_request: 45729
+author:
+type: changed
diff --git a/changelogs/unreleased/258215-improve-fuzzy-search-on-full-path-in-groups.yml b/changelogs/unreleased/258215-improve-fuzzy-search-on-full-path-in-groups.yml
new file mode 100644
index 00000000000..f2fd36bb68e
--- /dev/null
+++ b/changelogs/unreleased/258215-improve-fuzzy-search-on-full-path-in-groups.yml
@@ -0,0 +1,5 @@
+---
+title: Fix problems with Groups API search query parameter
+merge_request: 46394
+author:
+type: fixed
diff --git a/changelogs/unreleased/258638-feature-flag-rollout-of-enable_environment_path_in_alert_details.yml b/changelogs/unreleased/258638-feature-flag-rollout-of-enable_environment_path_in_alert_details.yml
new file mode 100644
index 00000000000..7fe8b2860ba
--- /dev/null
+++ b/changelogs/unreleased/258638-feature-flag-rollout-of-enable_environment_path_in_alert_details.yml
@@ -0,0 +1,5 @@
+---
+title: Show the environment link on alert details page
+merge_request: 44130
+author:
+type: added
diff --git a/changelogs/unreleased/258980-feature-flag-rollout-of-admin-approval-for-new-user-signups.yml b/changelogs/unreleased/258980-feature-flag-rollout-of-admin-approval-for-new-user-signups.yml
new file mode 100644
index 00000000000..e1fa6567219
--- /dev/null
+++ b/changelogs/unreleased/258980-feature-flag-rollout-of-admin-approval-for-new-user-signups.yml
@@ -0,0 +1,5 @@
+---
+title: Remove admin_approval_for_new_user_signups feature flag
+merge_request: 46051
+author:
+type: changed
diff --git a/changelogs/unreleased/258993-render-404-to-bots.yml b/changelogs/unreleased/258993-render-404-to-bots.yml
new file mode 100644
index 00000000000..d07c93ee321
--- /dev/null
+++ b/changelogs/unreleased/258993-render-404-to-bots.yml
@@ -0,0 +1,5 @@
+---
+title: Render 404 to search engine crawlers instead of redirecting to login
+merge_request: 45552
+author:
+type: changed
diff --git a/changelogs/unreleased/259024-labels-api-search-support.yml b/changelogs/unreleased/259024-labels-api-search-support.yml
new file mode 100644
index 00000000000..a5ceacb4e20
--- /dev/null
+++ b/changelogs/unreleased/259024-labels-api-search-support.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for search and inclusion of project labels within Group Labels API
+merge_request: 44415
+author:
+type: changed
diff --git a/changelogs/unreleased/260340-wiki-render-like-issues.yml b/changelogs/unreleased/260340-wiki-render-like-issues.yml
new file mode 100644
index 00000000000..60be57b65d7
--- /dev/null
+++ b/changelogs/unreleased/260340-wiki-render-like-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Improve the look of wikis in search results
+merge_request: 47470
+author:
+type: changed
diff --git a/changelogs/unreleased/262096-change-graphql-id-types-for-global-ids.yml b/changelogs/unreleased/262096-change-graphql-id-types-for-global-ids.yml
new file mode 100644
index 00000000000..d2b8dadfe97
--- /dev/null
+++ b/changelogs/unreleased/262096-change-graphql-id-types-for-global-ids.yml
@@ -0,0 +1,5 @@
+---
+title: Update GraphQL input ids for Board Lists and Issues to be more type specific
+merge_request: 45398
+author:
+type: changed
diff --git a/changelogs/unreleased/262112_populate_missing_dismissal_information_for_vulnerabilities.yml b/changelogs/unreleased/262112_populate_missing_dismissal_information_for_vulnerabilities.yml
new file mode 100644
index 00000000000..44a62049cfd
--- /dev/null
+++ b/changelogs/unreleased/262112_populate_missing_dismissal_information_for_vulnerabilities.yml
@@ -0,0 +1,5 @@
+---
+title: Populate missing `dismissed_at` and `dismissed_by_id` attributes of vulnerabilities
+merge_request: 46370
+author:
+type: fixed
diff --git a/changelogs/unreleased/262395-models-for-devops-adoption-segments.yml b/changelogs/unreleased/262395-models-for-devops-adoption-segments.yml
new file mode 100644
index 00000000000..d806dc9591a
--- /dev/null
+++ b/changelogs/unreleased/262395-models-for-devops-adoption-segments.yml
@@ -0,0 +1,5 @@
+---
+title: Add `analytics_devops_adoption_segment_selections` and `analytics_devops_adoption_segments` database tables.
+merge_request: 45748
+author:
+type: other
diff --git a/changelogs/unreleased/262640-search-results-return-no-results-when-the-pagination-window-is-out.yml b/changelogs/unreleased/262640-search-results-return-no-results-when-the-pagination-window-is-out.yml
new file mode 100644
index 00000000000..cbaa74c9363
--- /dev/null
+++ b/changelogs/unreleased/262640-search-results-return-no-results-when-the-pagination-window-is-out.yml
@@ -0,0 +1,5 @@
+---
+title: Reset the pagination cursor when a search result filter changes.
+merge_request: 45708
+author:
+type: fixed
diff --git a/changelogs/unreleased/263106-user-admin-approval-enable-disable-toggle-require_admin_approval_a.yml b/changelogs/unreleased/263106-user-admin-approval-enable-disable-toggle-require_admin_approval_a.yml
new file mode 100644
index 00000000000..1532833cfed
--- /dev/null
+++ b/changelogs/unreleased/263106-user-admin-approval-enable-disable-toggle-require_admin_approval_a.yml
@@ -0,0 +1,6 @@
+---
+title: Allow setting the value of 'require_admin_approval_after_user_signup' via Settings
+ API
+merge_request: 46851
+author:
+type: added
diff --git a/changelogs/unreleased/263109-implement-graphql-startup-js-for-design-management-app.yml b/changelogs/unreleased/263109-implement-graphql-startup-js-for-design-management-app.yml
new file mode 100644
index 00000000000..fa857465acc
--- /dev/null
+++ b/changelogs/unreleased/263109-implement-graphql-startup-js-for-design-management-app.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Implement GraphQL Startup.js for Design Management app
+merge_request: 46660
+author:
+type: other
diff --git a/changelogs/unreleased/263144-commit-to-new-branch.yml b/changelogs/unreleased/263144-commit-to-new-branch.yml
new file mode 100644
index 00000000000..3248b635630
--- /dev/null
+++ b/changelogs/unreleased/263144-commit-to-new-branch.yml
@@ -0,0 +1,5 @@
+---
+title: Extend GraphQL API to commit to a new branch in a single operation
+merge_request: 47203
+author:
+type: changed
diff --git a/changelogs/unreleased/263222-remove-soft-fail-count-by-state-ff.yml b/changelogs/unreleased/263222-remove-soft-fail-count-by-state-ff.yml
new file mode 100644
index 00000000000..b158462bff5
--- /dev/null
+++ b/changelogs/unreleased/263222-remove-soft-fail-count-by-state-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Gracefully degrade when counting takes too long for a filtered search
+merge_request: 46350
+author:
+type: performance
diff --git a/changelogs/unreleased/263252-mr-template-api.yml b/changelogs/unreleased/263252-mr-template-api.yml
new file mode 100644
index 00000000000..7120c15ce44
--- /dev/null
+++ b/changelogs/unreleased/263252-mr-template-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add merge request description templates to Static Site Editor
+merge_request: 46488
+author:
+type: added
diff --git a/changelogs/unreleased/263482-container-scanning-version-3.yml b/changelogs/unreleased/263482-container-scanning-version-3.yml
new file mode 100644
index 00000000000..cd3412b3c10
--- /dev/null
+++ b/changelogs/unreleased/263482-container-scanning-version-3.yml
@@ -0,0 +1,5 @@
+---
+title: Update container_scanning to version 3 to support FIPS
+merge_request: 47099
+author:
+type: added
diff --git a/changelogs/unreleased/263521-add-projects_with_enabled_alert_integrations-usage-ping.yml b/changelogs/unreleased/263521-add-projects_with_enabled_alert_integrations-usage-ping.yml
new file mode 100644
index 00000000000..3c2a0285a41
--- /dev/null
+++ b/changelogs/unreleased/263521-add-projects_with_enabled_alert_integrations-usage-ping.yml
@@ -0,0 +1,5 @@
+---
+title: Add projects_with_enabled_alert_integrations usage ping
+merge_request: 46693
+author:
+type: added
diff --git a/changelogs/unreleased/263552-number-of-projects-active-alerts.yml b/changelogs/unreleased/263552-number-of-projects-active-alerts.yml
new file mode 100644
index 00000000000..6d9ffd9947a
--- /dev/null
+++ b/changelogs/unreleased/263552-number-of-projects-active-alerts.yml
@@ -0,0 +1,5 @@
+---
+title: Add metric count for projects with alerts created
+merge_request: 46636
+author:
+type: added
diff --git a/changelogs/unreleased/266946-minimal-access-members-are-not-listed-in-saml.yml b/changelogs/unreleased/266946-minimal-access-members-are-not-listed-in-saml.yml
new file mode 100644
index 00000000000..d5a18be688c
--- /dev/null
+++ b/changelogs/unreleased/266946-minimal-access-members-are-not-listed-in-saml.yml
@@ -0,0 +1,5 @@
+---
+title: Add minimal access users to group members api endpoints
+merge_request: 46238
+author:
+type: changed
diff --git a/changelogs/unreleased/266986-update-img-resizing-ffs.yml b/changelogs/unreleased/266986-update-img-resizing-ffs.yml
new file mode 100644
index 00000000000..0d1e5f81a93
--- /dev/null
+++ b/changelogs/unreleased/266986-update-img-resizing-ffs.yml
@@ -0,0 +1,5 @@
+---
+title: Replace existing Image Resizing FFs with a single of `ops` type enabled by default
+merge_request: 45050
+author:
+type: other
diff --git a/changelogs/unreleased/267010-improve-group-packages-finder.yml b/changelogs/unreleased/267010-improve-group-packages-finder.yml
new file mode 100644
index 00000000000..97cfdb86a7a
--- /dev/null
+++ b/changelogs/unreleased/267010-improve-group-packages-finder.yml
@@ -0,0 +1,5 @@
+---
+title: Fix an N+1 issue in Packages::GroupPackagesFinder
+merge_request: 45875
+author:
+type: fixed
diff --git a/changelogs/unreleased/267113-separate-new-group-project-creation-button.yml b/changelogs/unreleased/267113-separate-new-group-project-creation-button.yml
new file mode 100644
index 00000000000..c4d46ad74c4
--- /dev/null
+++ b/changelogs/unreleased/267113-separate-new-group-project-creation-button.yml
@@ -0,0 +1,5 @@
+---
+title: Move "New subgroup" and "New project" out of the dropdown into individual buttons
+merge_request: 46907
+author:
+type: changed
diff --git a/changelogs/unreleased/267147-graphql-total-count.yml b/changelogs/unreleased/267147-graphql-total-count.yml
new file mode 100644
index 00000000000..7c86664560c
--- /dev/null
+++ b/changelogs/unreleased/267147-graphql-total-count.yml
@@ -0,0 +1,5 @@
+---
+title: Add total count to Terraform state GraphQL API
+merge_request: 45798
+author:
+type: changed
diff --git a/changelogs/unreleased/267147-terraform-list.yml b/changelogs/unreleased/267147-terraform-list.yml
new file mode 100644
index 00000000000..22db29c8bb0
--- /dev/null
+++ b/changelogs/unreleased/267147-terraform-list.yml
@@ -0,0 +1,5 @@
+---
+title: Add new Terraform state list page
+merge_request: 45700
+author:
+type: added
diff --git a/changelogs/unreleased/267147-terraform-state-versions-graphql.yml b/changelogs/unreleased/267147-terraform-state-versions-graphql.yml
new file mode 100644
index 00000000000..0eb03990dd1
--- /dev/null
+++ b/changelogs/unreleased/267147-terraform-state-versions-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add latest version field to Terraform state GraphQL type
+merge_request: 45848
+author:
+type: added
diff --git a/changelogs/unreleased/267168-add-ci-build-to-terraform-state-version-graphql-type.yml b/changelogs/unreleased/267168-add-ci-build-to-terraform-state-version-graphql-type.yml
new file mode 100644
index 00000000000..1dee669f006
--- /dev/null
+++ b/changelogs/unreleased/267168-add-ci-build-to-terraform-state-version-graphql-type.yml
@@ -0,0 +1,5 @@
+---
+title: Add CI job to Terraform state version GraphQL type
+merge_request: 47339
+author:
+type: added
diff --git a/changelogs/unreleased/267168-add-pipeline-to-ci-job-type.yml b/changelogs/unreleased/267168-add-pipeline-to-ci-job-type.yml
new file mode 100644
index 00000000000..2f71c1c409c
--- /dev/null
+++ b/changelogs/unreleased/267168-add-pipeline-to-ci-job-type.yml
@@ -0,0 +1,5 @@
+---
+title: Add pipeline to CI job GraphQL type
+merge_request: 47347
+author:
+type: added
diff --git a/changelogs/unreleased/267168-set-build-on-terraform-state-version-creation.yml b/changelogs/unreleased/267168-set-build-on-terraform-state-version-creation.yml
new file mode 100644
index 00000000000..a58cab0a6f8
--- /dev/null
+++ b/changelogs/unreleased/267168-set-build-on-terraform-state-version-creation.yml
@@ -0,0 +1,5 @@
+---
+title: Associate Terraform state versions with the CI job that created them
+merge_request: 45347
+author:
+type: added
diff --git a/changelogs/unreleased/267191-project-access-tokens-delete-project-bot-after-it-s-removed-from-p.yml b/changelogs/unreleased/267191-project-access-tokens-delete-project-bot-after-it-s-removed-from-p.yml
new file mode 100644
index 00000000000..b6cec22bc92
--- /dev/null
+++ b/changelogs/unreleased/267191-project-access-tokens-delete-project-bot-after-it-s-removed-from-p.yml
@@ -0,0 +1,5 @@
+---
+title: Project Access Tokens - Delete project bot after token expires
+merge_request: 45828
+author:
+type: fixed
diff --git a/changelogs/unreleased/267394-improve-search-empty-message.yml b/changelogs/unreleased/267394-improve-search-empty-message.yml
new file mode 100644
index 00000000000..7d035d6a79a
--- /dev/null
+++ b/changelogs/unreleased/267394-improve-search-empty-message.yml
@@ -0,0 +1,5 @@
+---
+title: Improve empty search results message for group and project scopes
+merge_request: 46237
+author:
+type: changed
diff --git a/changelogs/unreleased/267492-change-to-enabled-sp-ff.yml b/changelogs/unreleased/267492-change-to-enabled-sp-ff.yml
new file mode 100644
index 00000000000..28eda7d4183
--- /dev/null
+++ b/changelogs/unreleased/267492-change-to-enabled-sp-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Add suggest pipeline for viable merge requests without pipelines
+merge_request: 45926
+author:
+type: changed
diff --git a/changelogs/unreleased/267495-add-sha256-of-pages-contents-to-pages_deployments.yml b/changelogs/unreleased/267495-add-sha256-of-pages-contents-to-pages_deployments.yml
new file mode 100644
index 00000000000..e108232b0f4
--- /dev/null
+++ b/changelogs/unreleased/267495-add-sha256-of-pages-contents-to-pages_deployments.yml
@@ -0,0 +1,5 @@
+---
+title: Add sha256 and file count to pages_deployments
+merge_request: 45522
+author:
+type: added
diff --git a/changelogs/unreleased/267568-user-admin-approval-default-for-new-instances.yml b/changelogs/unreleased/267568-user-admin-approval-default-for-new-instances.yml
new file mode 100644
index 00000000000..b6512ee661f
--- /dev/null
+++ b/changelogs/unreleased/267568-user-admin-approval-default-for-new-instances.yml
@@ -0,0 +1,5 @@
+---
+title: Admin approval required on user registration by default
+merge_request: 46937
+author:
+type: changed
diff --git a/changelogs/unreleased/267828-remove-minimum_interval-from-backgroundmigrationworker.yml b/changelogs/unreleased/267828-remove-minimum_interval-from-backgroundmigrationworker.yml
new file mode 100644
index 00000000000..09fc66a511c
--- /dev/null
+++ b/changelogs/unreleased/267828-remove-minimum_interval-from-backgroundmigrationworker.yml
@@ -0,0 +1,5 @@
+---
+title: Limit number of times a background migration is rescheduled
+merge_request: 45298
+author:
+type: fixed
diff --git a/changelogs/unreleased/267963-related-merge-requests-icon-in-issues-list-is-rendered-incorrectly.yml b/changelogs/unreleased/267963-related-merge-requests-icon-in-issues-list-is-rendered-incorrectly.yml
new file mode 100644
index 00000000000..4cc67bfbcb7
--- /dev/null
+++ b/changelogs/unreleased/267963-related-merge-requests-icon-in-issues-list-is-rendered-incorrectly.yml
@@ -0,0 +1,5 @@
+---
+title: Updated list view MR icon
+merge_request: 46059
+author:
+type: fixed
diff --git a/changelogs/unreleased/268000-extend-graphql-measurements-api.yml b/changelogs/unreleased/268000-extend-graphql-measurements-api.yml
new file mode 100644
index 00000000000..9fde7fa8f3e
--- /dev/null
+++ b/changelogs/unreleased/268000-extend-graphql-measurements-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add filtering by recorded date to instance statistics measurements GraphQL API
+merge_request: 46344
+author:
+type: changed
diff --git a/changelogs/unreleased/268133-fix-propagate-integrations-for-project-callback.yml b/changelogs/unreleased/268133-fix-propagate-integrations-for-project-callback.yml
new file mode 100644
index 00000000000..6af3e240d16
--- /dev/null
+++ b/changelogs/unreleased/268133-fix-propagate-integrations-for-project-callback.yml
@@ -0,0 +1,5 @@
+---
+title: Fix project callbacks when propagating integrations
+merge_request: 45781
+author:
+type: fixed
diff --git a/changelogs/unreleased/268248-remove-index-service-for-usage-data.yml b/changelogs/unreleased/268248-remove-index-service-for-usage-data.yml
new file mode 100644
index 00000000000..528318f4656
--- /dev/null
+++ b/changelogs/unreleased/268248-remove-index-service-for-usage-data.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unnecessary index on services for usage data
+merge_request: 45655
+author:
+type: other
diff --git a/changelogs/unreleased/268301-mr-ide-button.yml b/changelogs/unreleased/268301-mr-ide-button.yml
new file mode 100644
index 00000000000..5528d05d6d4
--- /dev/null
+++ b/changelogs/unreleased/268301-mr-ide-button.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Merge Request "Edit in Web IDE" dropdown link on MR diffs page
+merge_request: 45653
+author:
+type: fixed
diff --git a/changelogs/unreleased/268315-restructure-project-page-title-to-show-project-name-first.yml b/changelogs/unreleased/268315-restructure-project-page-title-to-show-project-name-first.yml
new file mode 100644
index 00000000000..80e45708196
--- /dev/null
+++ b/changelogs/unreleased/268315-restructure-project-page-title-to-show-project-name-first.yml
@@ -0,0 +1,5 @@
+---
+title: Remove page_title from single project and group pages
+merge_request: 46223
+author:
+type: fixed
diff --git a/changelogs/unreleased/26873-add-webhooks-for-releases.yml b/changelogs/unreleased/26873-add-webhooks-for-releases.yml
new file mode 100644
index 00000000000..9ccb93b66bc
--- /dev/null
+++ b/changelogs/unreleased/26873-add-webhooks-for-releases.yml
@@ -0,0 +1,5 @@
+---
+title: Add webhooks for creating and updating a release
+merge_request: 44881
+author: David Barr @davebarr
+type: added
diff --git a/changelogs/unreleased/26952-fix-viewing-legacy-diff-notes-in-discussion.yml b/changelogs/unreleased/26952-fix-viewing-legacy-diff-notes-in-discussion.yml
new file mode 100644
index 00000000000..f6ec87f1332
--- /dev/null
+++ b/changelogs/unreleased/26952-fix-viewing-legacy-diff-notes-in-discussion.yml
@@ -0,0 +1,5 @@
+---
+title: Fix viewing GitHub-imported diff notes in discussions
+merge_request: 45920
+author:
+type: fixed
diff --git a/changelogs/unreleased/26963-fix-empty-state-in-explore-projects-pages.yml b/changelogs/unreleased/26963-fix-empty-state-in-explore-projects-pages.yml
new file mode 100644
index 00000000000..b6e421f7844
--- /dev/null
+++ b/changelogs/unreleased/26963-fix-empty-state-in-explore-projects-pages.yml
@@ -0,0 +1,5 @@
+---
+title: Fix empty state message in explore projects page
+merge_request: 46860
+author:
+type: fixed
diff --git a/changelogs/unreleased/270051-fj-generate-sitmap-dot-com.yml b/changelogs/unreleased/270051-fj-generate-sitmap-dot-com.yml
new file mode 100644
index 00000000000..c5715db77c3
--- /dev/null
+++ b/changelogs/unreleased/270051-fj-generate-sitmap-dot-com.yml
@@ -0,0 +1,5 @@
+---
+title: Add default sitemap generator for gitlab-org group
+merge_request: 45645
+author:
+type: added
diff --git a/changelogs/unreleased/270065-bs4-optimization-diffs.yml b/changelogs/unreleased/270065-bs4-optimization-diffs.yml
new file mode 100644
index 00000000000..8d8e2a011b6
--- /dev/null
+++ b/changelogs/unreleased/270065-bs4-optimization-diffs.yml
@@ -0,0 +1,5 @@
+---
+title: Remove duplicated BS display properties from various Diffs
+merge_request: 47125
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/270065-bs4-optimization-issue.yml b/changelogs/unreleased/270065-bs4-optimization-issue.yml
new file mode 100644
index 00000000000..7a26ab73fdc
--- /dev/null
+++ b/changelogs/unreleased/270065-bs4-optimization-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Remove duplicated BS display properties from Issue
+merge_request: 45628
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/270065-bs4-optimization-mr.yml b/changelogs/unreleased/270065-bs4-optimization-mr.yml
new file mode 100644
index 00000000000..6b02e496665
--- /dev/null
+++ b/changelogs/unreleased/270065-bs4-optimization-mr.yml
@@ -0,0 +1,5 @@
+---
+title: Remove duplicated BS display properties from Merge Request title
+merge_request: 47124
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/270106_enable_csp_for_sse.yml b/changelogs/unreleased/270106_enable_csp_for_sse.yml
new file mode 100644
index 00000000000..e31fe2e3738
--- /dev/null
+++ b/changelogs/unreleased/270106_enable_csp_for_sse.yml
@@ -0,0 +1,5 @@
+---
+title: Configure CSP for displaying Youtube videos in the Static Site Editor
+merge_request: 45767
+author:
+type: fixed
diff --git a/changelogs/unreleased/270116-region-field.yml b/changelogs/unreleased/270116-region-field.yml
new file mode 100644
index 00000000000..9cf35ae4a18
--- /dev/null
+++ b/changelogs/unreleased/270116-region-field.yml
@@ -0,0 +1,5 @@
+---
+title: Add region field to AWS Role
+merge_request: 47209
+author:
+type: changed
diff --git a/changelogs/unreleased/270200-downtier-pat-apis.yml b/changelogs/unreleased/270200-downtier-pat-apis.yml
new file mode 100644
index 00000000000..48a37c8e19e
--- /dev/null
+++ b/changelogs/unreleased/270200-downtier-pat-apis.yml
@@ -0,0 +1,5 @@
+---
+title: Move Personal Access Token API to Core
+merge_request: 46145
+author:
+type: changed
diff --git a/changelogs/unreleased/270208-add-application-settings-columns.yml b/changelogs/unreleased/270208-add-application-settings-columns.yml
new file mode 100644
index 00000000000..6cbac13d766
--- /dev/null
+++ b/changelogs/unreleased/270208-add-application-settings-columns.yml
@@ -0,0 +1,5 @@
+---
+title: Add secret detection token revocation columns
+merge_request: 45912
+author:
+type: added
diff --git a/changelogs/unreleased/270409-experiment-cleanup-discover-security.yml b/changelogs/unreleased/270409-experiment-cleanup-discover-security.yml
new file mode 100644
index 00000000000..909ad33e7b9
--- /dev/null
+++ b/changelogs/unreleased/270409-experiment-cleanup-discover-security.yml
@@ -0,0 +1,6 @@
+---
+title: Enable dashboard security discover button and ignore feature_filter_type column
+ cleanup
+merge_request: 45636
+author:
+type: added
diff --git a/changelogs/unreleased/270412-license-error-in-template.yml b/changelogs/unreleased/270412-license-error-in-template.yml
new file mode 100644
index 00000000000..e3a7b9daa36
--- /dev/null
+++ b/changelogs/unreleased/270412-license-error-in-template.yml
@@ -0,0 +1,5 @@
+---
+title: Show error in pipeline when API Fuzzing not licensed
+merge_request: 46064
+author:
+type: changed
diff --git a/changelogs/unreleased/270420-fj-add-explore-canonical-link.yml b/changelogs/unreleased/270420-fj-add-explore-canonical-link.yml
new file mode 100644
index 00000000000..5cc14ec254a
--- /dev/null
+++ b/changelogs/unreleased/270420-fj-add-explore-canonical-link.yml
@@ -0,0 +1,5 @@
+---
+title: Add canonical link for default explore route
+merge_request: 45746
+author:
+type: changed
diff --git a/changelogs/unreleased/270439-enable-ci_seed_block_run_before_workflow_rules.yml b/changelogs/unreleased/270439-enable-ci_seed_block_run_before_workflow_rules.yml
new file mode 100644
index 00000000000..cc59ed2c619
--- /dev/null
+++ b/changelogs/unreleased/270439-enable-ci_seed_block_run_before_workflow_rules.yml
@@ -0,0 +1,5 @@
+---
+title: Fix workflow:rules not accessing passed-upstream and trigger variables
+merge_request: 47399
+author:
+type: fixed
diff --git a/changelogs/unreleased/270470-no-query-new-snippet.yml b/changelogs/unreleased/270470-no-query-new-snippet.yml
new file mode 100644
index 00000000000..a2b7b54d8bc
--- /dev/null
+++ b/changelogs/unreleased/270470-no-query-new-snippet.yml
@@ -0,0 +1,5 @@
+---
+title: Do not query snippet infromation on the new snippet's creation
+merge_request: 46355
+author:
+type: fixed
diff --git a/changelogs/unreleased/27142-divider-in-readme-is-overlaying-with-image-anchor-solution.yml b/changelogs/unreleased/27142-divider-in-readme-is-overlaying-with-image-anchor-solution.yml
new file mode 100644
index 00000000000..ce61b1e8d62
--- /dev/null
+++ b/changelogs/unreleased/27142-divider-in-readme-is-overlaying-with-image-anchor-solution.yml
@@ -0,0 +1,5 @@
+---
+title: Fix rendering of markdown headings and floated images
+merge_request: 25442
+author: Gwen_
+type: fixed
diff --git a/changelogs/unreleased/271459-fix-remove-label-inconsistency.yml b/changelogs/unreleased/271459-fix-remove-label-inconsistency.yml
new file mode 100644
index 00000000000..05ddb2b4682
--- /dev/null
+++ b/changelogs/unreleased/271459-fix-remove-label-inconsistency.yml
@@ -0,0 +1,5 @@
+---
+title: Fix remove label inconsistency
+merge_request: 46805
+author:
+type: fixed
diff --git a/changelogs/unreleased/271528-todo-css-on-mobile.yml b/changelogs/unreleased/271528-todo-css-on-mobile.yml
new file mode 100644
index 00000000000..d863180dc7c
--- /dev/null
+++ b/changelogs/unreleased/271528-todo-css-on-mobile.yml
@@ -0,0 +1,5 @@
+---
+title: Fix CSS for To-Do List on mobile
+merge_request: 45969
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/271542-prefetch-requests-link.yml b/changelogs/unreleased/271542-prefetch-requests-link.yml
new file mode 100644
index 00000000000..c0fdf7eaa6c
--- /dev/null
+++ b/changelogs/unreleased/271542-prefetch-requests-link.yml
@@ -0,0 +1,5 @@
+---
+title: Pre-fetched GraphQL queries for snippet view
+merge_request: 46130
+author:
+type: changed
diff --git a/changelogs/unreleased/271550-fj-forbid-realtime_changes-in-robots.yml b/changelogs/unreleased/271550-fj-forbid-realtime_changes-in-robots.yml
new file mode 100644
index 00000000000..b90a85fa043
--- /dev/null
+++ b/changelogs/unreleased/271550-fj-forbid-realtime_changes-in-robots.yml
@@ -0,0 +1,5 @@
+---
+title: Disallow realtime_changes route in robots.txt
+merge_request: 45986
+author:
+type: changed
diff --git a/changelogs/unreleased/271560-enable-ci_include_multiple_files_from_project.yml b/changelogs/unreleased/271560-enable-ci_include_multiple_files_from_project.yml
new file mode 100644
index 00000000000..0945f7aa3ec
--- /dev/null
+++ b/changelogs/unreleased/271560-enable-ci_include_multiple_files_from_project.yml
@@ -0,0 +1,5 @@
+---
+title: Implement including multiple files from a project
+merge_request: 47609
+author:
+type: added
diff --git a/changelogs/unreleased/271589-report-abuse-on-merged-mr.yml b/changelogs/unreleased/271589-report-abuse-on-merged-mr.yml
new file mode 100644
index 00000000000..aef591da54a
--- /dev/null
+++ b/changelogs/unreleased/271589-report-abuse-on-merged-mr.yml
@@ -0,0 +1,5 @@
+---
+title: Remove "Report abuse" button from a merged Merge Request
+merge_request: 46031
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/271635-new-project-access-tokens-do-not-show-in-active-project-access-tok.yml b/changelogs/unreleased/271635-new-project-access-tokens-do-not-show-in-active-project-access-tok.yml
new file mode 100644
index 00000000000..d84fe3e5df0
--- /dev/null
+++ b/changelogs/unreleased/271635-new-project-access-tokens-do-not-show-in-active-project-access-tok.yml
@@ -0,0 +1,5 @@
+---
+title: Skip GMA and SSO validation when creating project access tokens for project bots
+merge_request: 46257
+author:
+type: fixed
diff --git a/changelogs/unreleased/272984-fj-forbid-autocomplete-projects.yml b/changelogs/unreleased/272984-fj-forbid-autocomplete-projects.yml
new file mode 100644
index 00000000000..f0da305ecc2
--- /dev/null
+++ b/changelogs/unreleased/272984-fj-forbid-autocomplete-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Disallow /autocomplete/projects route in robots.txt
+merge_request: 46115
+author:
+type: changed
diff --git a/changelogs/unreleased/272986-fj-disallow-webide-route-in-robots.yml b/changelogs/unreleased/272986-fj-disallow-webide-route-in-robots.yml
new file mode 100644
index 00000000000..29f2cfb1111
--- /dev/null
+++ b/changelogs/unreleased/272986-fj-disallow-webide-route-in-robots.yml
@@ -0,0 +1,5 @@
+---
+title: Disallow WebIDE route in robots.txt
+merge_request: 46117
+author:
+type: changed
diff --git a/changelogs/unreleased/273001-terraform-list-update.yml b/changelogs/unreleased/273001-terraform-list-update.yml
new file mode 100644
index 00000000000..6ecbe68a2e2
--- /dev/null
+++ b/changelogs/unreleased/273001-terraform-list-update.yml
@@ -0,0 +1,5 @@
+---
+title: Add user info to Terraform State List
+merge_request: 46984
+author:
+type: changed
diff --git a/changelogs/unreleased/273002-full-project-issue-boards-api-on-ce.yml b/changelogs/unreleased/273002-full-project-issue-boards-api-on-ce.yml
new file mode 100644
index 00000000000..82856ee39c1
--- /dev/null
+++ b/changelogs/unreleased/273002-full-project-issue-boards-api-on-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Make all Project Issue Boards API available even in CE
+merge_request: 46137
+author: Takuya Noguchi
+type: changed
diff --git a/changelogs/unreleased/273016-replace-ace-merge-conflicts.yml b/changelogs/unreleased/273016-replace-ace-merge-conflicts.yml
new file mode 100644
index 00000000000..4d21070cfd4
--- /dev/null
+++ b/changelogs/unreleased/273016-replace-ace-merge-conflicts.yml
@@ -0,0 +1,5 @@
+---
+title: Replace ACE with Editor Lite
+merge_request: 46250
+author:
+type: changed
diff --git a/changelogs/unreleased/273134-add_web_usage_data_for_geo_secondaries.yml b/changelogs/unreleased/273134-add_web_usage_data_for_geo_secondaries.yml
new file mode 100644
index 00000000000..b986895f882
--- /dev/null
+++ b/changelogs/unreleased/273134-add_web_usage_data_for_geo_secondaries.yml
@@ -0,0 +1,5 @@
+---
+title: Add usage ping for web users of geo secondaries
+merge_request: 46278
+author:
+type: added
diff --git a/changelogs/unreleased/273140-fix-transaction-issue-in-container-expiration-policy-worker.yml b/changelogs/unreleased/273140-fix-transaction-issue-in-container-expiration-policy-worker.yml
new file mode 100644
index 00000000000..7d6aa23038c
--- /dev/null
+++ b/changelogs/unreleased/273140-fix-transaction-issue-in-container-expiration-policy-worker.yml
@@ -0,0 +1,5 @@
+---
+title: Fix transaction usage in ContainerExpirationPolicyWorker
+merge_request: 46217
+author:
+type: fixed
diff --git a/changelogs/unreleased/273142-fj-enable-avatar-with-full-url.yml b/changelogs/unreleased/273142-fj-enable-avatar-with-full-url.yml
new file mode 100644
index 00000000000..9ff31327461
--- /dev/null
+++ b/changelogs/unreleased/273142-fj-enable-avatar-with-full-url.yml
@@ -0,0 +1,5 @@
+---
+title: Enable rendering avatars with full url
+merge_request: 46206
+author:
+type: fixed
diff --git a/changelogs/unreleased/273148-fj-disallow-some-project-routes.yml b/changelogs/unreleased/273148-fj-disallow-some-project-routes.yml
new file mode 100644
index 00000000000..e3e3dec961b
--- /dev/null
+++ b/changelogs/unreleased/273148-fj-disallow-some-project-routes.yml
@@ -0,0 +1,5 @@
+---
+title: Disallow some project routes in robots.txt
+merge_request: 46218
+author:
+type: changed
diff --git a/changelogs/unreleased/273261-not-able-to-set-comment-settings-for-jira.yml b/changelogs/unreleased/273261-not-able-to-set-comment-settings-for-jira.yml
new file mode 100644
index 00000000000..1aecd98c60a
--- /dev/null
+++ b/changelogs/unreleased/273261-not-able-to-set-comment-settings-for-jira.yml
@@ -0,0 +1,5 @@
+---
+title: Fix setting Comment detail for Jira and modal for groups
+merge_request: 46945
+author:
+type: fixed
diff --git a/changelogs/unreleased/273356-remove-sql_set_operators-feature-flag.yml b/changelogs/unreleased/273356-remove-sql_set_operators-feature-flag.yml
new file mode 100644
index 00000000000..9df49692ee5
--- /dev/null
+++ b/changelogs/unreleased/273356-remove-sql_set_operators-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Enable refactored union set operator
+merge_request: 46295
+author:
+type: added
diff --git a/changelogs/unreleased/273434-add-message-in-ci-linter-that-it-was-validated-with-all-the-includ.yml b/changelogs/unreleased/273434-add-message-in-ci-linter-that-it-was-validated-with-all-the-includ.yml
new file mode 100644
index 00000000000..7e61e0973bf
--- /dev/null
+++ b/changelogs/unreleased/273434-add-message-in-ci-linter-that-it-was-validated-with-all-the-includ.yml
@@ -0,0 +1,5 @@
+---
+title: Add message in CI linter that it was validated with all the includes
+merge_request: 46713
+author:
+type: changed
diff --git a/changelogs/unreleased/273541-issue-template-warning-appears-above-type-field.yml b/changelogs/unreleased/273541-issue-template-warning-appears-above-type-field.yml
new file mode 100644
index 00000000000..993f5d79efe
--- /dev/null
+++ b/changelogs/unreleased/273541-issue-template-warning-appears-above-type-field.yml
@@ -0,0 +1,5 @@
+---
+title: Moved template warning below type
+merge_request: 47103
+author:
+type: fixed
diff --git a/changelogs/unreleased/273623-replace-sign-in-text-with-sign-in-text.yml b/changelogs/unreleased/273623-replace-sign-in-text-with-sign-in-text.yml
new file mode 100644
index 00000000000..4d8c12bbf05
--- /dev/null
+++ b/changelogs/unreleased/273623-replace-sign-in-text-with-sign-in-text.yml
@@ -0,0 +1,5 @@
+---
+title: Corrected grammar in Sign-in restrictions text
+merge_request: 46500
+author:
+type: other
diff --git a/changelogs/unreleased/273655-dependency-proxy-to-core.yml b/changelogs/unreleased/273655-dependency-proxy-to-core.yml
new file mode 100644
index 00000000000..ef29e62e344
--- /dev/null
+++ b/changelogs/unreleased/273655-dependency-proxy-to-core.yml
@@ -0,0 +1,5 @@
+---
+title: Dependency proxy feature is moved to GitLab core
+merge_request: 47471
+author:
+type: changed
diff --git a/changelogs/unreleased/273739-pipeline-tooltips-cover-the-entire-element.yml b/changelogs/unreleased/273739-pipeline-tooltips-cover-the-entire-element.yml
new file mode 100644
index 00000000000..4fb470d9010
--- /dev/null
+++ b/changelogs/unreleased/273739-pipeline-tooltips-cover-the-entire-element.yml
@@ -0,0 +1,5 @@
+---
+title: Better-behaved tooltips in pipeline dropdown
+merge_request: 46866
+author:
+type: fixed
diff --git a/changelogs/unreleased/273750-fj-structured-data-for-users.yml b/changelogs/unreleased/273750-fj-structured-data-for-users.yml
new file mode 100644
index 00000000000..26f421e806a
--- /dev/null
+++ b/changelogs/unreleased/273750-fj-structured-data-for-users.yml
@@ -0,0 +1,5 @@
+---
+title: Add structured markup for users
+merge_request: 46553
+author:
+type: added
diff --git a/changelogs/unreleased/273801-graphql-fuzzy-search-users.yml b/changelogs/unreleased/273801-graphql-fuzzy-search-users.yml
new file mode 100644
index 00000000000..9ff646eac06
--- /dev/null
+++ b/changelogs/unreleased/273801-graphql-fuzzy-search-users.yml
@@ -0,0 +1,5 @@
+---
+title: Add search param to Users GraphQL type
+merge_request: 46609
+author:
+type: added
diff --git a/changelogs/unreleased/273813-rename-cycle-analytics-with-value-stream-analytics-in-strings-unde.yml b/changelogs/unreleased/273813-rename-cycle-analytics-with-value-stream-analytics-in-strings-unde.yml
new file mode 100644
index 00000000000..b35d7b7618b
--- /dev/null
+++ b/changelogs/unreleased/273813-rename-cycle-analytics-with-value-stream-analytics-in-strings-unde.yml
@@ -0,0 +1,5 @@
+---
+title: Rename "cycle analytics" with "value stream analytics" under /spec
+merge_request: 46613
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/275899-share-view-code-for-mr-issue-search-results.yml b/changelogs/unreleased/275899-share-view-code-for-mr-issue-search-results.yml
new file mode 100644
index 00000000000..c9e6a0a97fe
--- /dev/null
+++ b/changelogs/unreleased/275899-share-view-code-for-mr-issue-search-results.yml
@@ -0,0 +1,5 @@
+---
+title: Update merge request search results design
+merge_request: 46944
+author:
+type: changed
diff --git a/changelogs/unreleased/276185_alerts_integrations_list_tracking.yml b/changelogs/unreleased/276185_alerts_integrations_list_tracking.yml
new file mode 100644
index 00000000000..e96f3ef6998
--- /dev/null
+++ b/changelogs/unreleased/276185_alerts_integrations_list_tracking.yml
@@ -0,0 +1,5 @@
+---
+title: Fix alerts integration list Snowplow tracking event
+merge_request: 47413
+author:
+type: fixed
diff --git a/changelogs/unreleased/276440-check-all-pipeline-jobs-for-security-artifacts-in-basic-security-m.yml b/changelogs/unreleased/276440-check-all-pipeline-jobs-for-security-artifacts-in-basic-security-m.yml
new file mode 100644
index 00000000000..52958c3b648
--- /dev/null
+++ b/changelogs/unreleased/276440-check-all-pipeline-jobs-for-security-artifacts-in-basic-security-m.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure security report is displayed correctly in merge requests with a lot of CI jobs
+merge_request: 46870
+author:
+type: fixed
diff --git a/changelogs/unreleased/276444-default-vue_issue_header-feature-flag-to-on.yml b/changelogs/unreleased/276444-default-vue_issue_header-feature-flag-to-on.yml
new file mode 100644
index 00000000000..c1d35062d43
--- /dev/null
+++ b/changelogs/unreleased/276444-default-vue_issue_header-feature-flag-to-on.yml
@@ -0,0 +1,5 @@
+---
+title: Convert issue header actions to an ellipsis dropdown menu
+merge_request: 47690
+author:
+type: added
diff --git a/changelogs/unreleased/276911-fix-ruby-lexer-rouge-bug.yml b/changelogs/unreleased/276911-fix-ruby-lexer-rouge-bug.yml
new file mode 100644
index 00000000000..075eae9a2b3
--- /dev/null
+++ b/changelogs/unreleased/276911-fix-ruby-lexer-rouge-bug.yml
@@ -0,0 +1,5 @@
+---
+title: Fix syntax highlight issue with regular expressions
+merge_request: 47469
+author:
+type: fixed
diff --git a/changelogs/unreleased/277369-typeerror-can-t-quote-activesupport-hashwithindifferentaccess.yml b/changelogs/unreleased/277369-typeerror-can-t-quote-activesupport-hashwithindifferentaccess.yml
new file mode 100644
index 00000000000..73136ed5769
--- /dev/null
+++ b/changelogs/unreleased/277369-typeerror-can-t-quote-activesupport-hashwithindifferentaccess.yml
@@ -0,0 +1,5 @@
+---
+title: Fix milestones param validation for releases API PUT method
+merge_request: 47169
+author:
+type: fixed
diff --git a/changelogs/unreleased/277457-saml-admin.yml b/changelogs/unreleased/277457-saml-admin.yml
new file mode 100644
index 00000000000..701c522482a
--- /dev/null
+++ b/changelogs/unreleased/277457-saml-admin.yml
@@ -0,0 +1,5 @@
+---
+title: Add group name and link in admin identities
+merge_request: 47563
+author:
+type: added
diff --git a/changelogs/unreleased/280553-cache-raw-endpoint.yml b/changelogs/unreleased/280553-cache-raw-endpoint.yml
new file mode 100644
index 00000000000..7e4baf7475e
--- /dev/null
+++ b/changelogs/unreleased/280553-cache-raw-endpoint.yml
@@ -0,0 +1,5 @@
+---
+title: Cache repository raw endpoint
+merge_request: 47225
+author:
+type: changed
diff --git a/changelogs/unreleased/280795-stop-finding-commit-empty-ref.yml b/changelogs/unreleased/280795-stop-finding-commit-empty-ref.yml
new file mode 100644
index 00000000000..a4f7e20daa8
--- /dev/null
+++ b/changelogs/unreleased/280795-stop-finding-commit-empty-ref.yml
@@ -0,0 +1,5 @@
+---
+title: Stop finding commit with empty ref
+merge_request: 47497
+author:
+type: fixed
diff --git a/changelogs/unreleased/280811-mr-analytics-chart-tooltip-overlays-filter-dropdown.yml b/changelogs/unreleased/280811-mr-analytics-chart-tooltip-overlays-filter-dropdown.yml
new file mode 100644
index 00000000000..87236ab3e2b
--- /dev/null
+++ b/changelogs/unreleased/280811-mr-analytics-chart-tooltip-overlays-filter-dropdown.yml
@@ -0,0 +1,5 @@
+---
+title: 'MR Analytics: Fix chart tooltip covering filter dropdown'
+merge_request: 47274
+author:
+type: changed
diff --git a/changelogs/unreleased/281020-dark-mode-isn-t-compabile-with-secure-mr-widget.yml b/changelogs/unreleased/281020-dark-mode-isn-t-compabile-with-secure-mr-widget.yml
new file mode 100644
index 00000000000..6551737af26
--- /dev/null
+++ b/changelogs/unreleased/281020-dark-mode-isn-t-compabile-with-secure-mr-widget.yml
@@ -0,0 +1,5 @@
+---
+title: Fix secure MR widget colors in dark mode
+merge_request: 47352
+author:
+type: fixed
diff --git a/changelogs/unreleased/281378-fj-add-absolute-urls-to-schema-breadcrumb.yml b/changelogs/unreleased/281378-fj-add-absolute-urls-to-schema-breadcrumb.yml
new file mode 100644
index 00000000000..3922d3f66b8
--- /dev/null
+++ b/changelogs/unreleased/281378-fj-add-absolute-urls-to-schema-breadcrumb.yml
@@ -0,0 +1,5 @@
+---
+title: Make schema breadcrumb urls absolute
+merge_request: 47523
+author:
+type: changed
diff --git a/changelogs/unreleased/281571-fix-blob-header-button-styles.yml b/changelogs/unreleased/281571-fix-blob-header-button-styles.yml
new file mode 100644
index 00000000000..3b65985a33d
--- /dev/null
+++ b/changelogs/unreleased/281571-fix-blob-header-button-styles.yml
@@ -0,0 +1,5 @@
+---
+title: Update button styles in blob header
+merge_request: 47571
+author:
+type: other
diff --git a/changelogs/unreleased/281697-fj-fix-snippet-resolvers.yml b/changelogs/unreleased/281697-fj-fix-snippet-resolvers.yml
new file mode 100644
index 00000000000..50b3a4eb6db
--- /dev/null
+++ b/changelogs/unreleased/281697-fj-fix-snippet-resolvers.yml
@@ -0,0 +1,5 @@
+---
+title: Add type annotation for snippet resolvers
+merge_request: 47548
+author:
+type: changed
diff --git a/changelogs/unreleased/282499-deploy-token-read-package.yml b/changelogs/unreleased/282499-deploy-token-read-package.yml
new file mode 100644
index 00000000000..da869cff69e
--- /dev/null
+++ b/changelogs/unreleased/282499-deploy-token-read-package.yml
@@ -0,0 +1,5 @@
+---
+title: Fix deploy token permissions for write_package_registry
+merge_request: 47675
+author:
+type: fixed
diff --git a/changelogs/unreleased/283924-user-profile.yml b/changelogs/unreleased/283924-user-profile.yml
new file mode 100644
index 00000000000..e674944c43a
--- /dev/null
+++ b/changelogs/unreleased/283924-user-profile.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor and UI-polish around activity calendar on user profile
+merge_request: 47797
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/30101-fix-includes.yml b/changelogs/unreleased/30101-fix-includes.yml
new file mode 100644
index 00000000000..c39672015dd
--- /dev/null
+++ b/changelogs/unreleased/30101-fix-includes.yml
@@ -0,0 +1,5 @@
+---
+title: Fix config variables when having includes
+merge_request: 47189
+author:
+type: fixed
diff --git a/changelogs/unreleased/31528-fix-pipelines-charts-timeout.yml b/changelogs/unreleased/31528-fix-pipelines-charts-timeout.yml
new file mode 100644
index 00000000000..11e01b79155
--- /dev/null
+++ b/changelogs/unreleased/31528-fix-pipelines-charts-timeout.yml
@@ -0,0 +1,5 @@
+---
+title: Fix pipelines chart query timeout
+merge_request: 47069
+author:
+type: performance
diff --git a/changelogs/unreleased/35404-automatic-rollback-in-case-of-failure.yml b/changelogs/unreleased/35404-automatic-rollback-in-case-of-failure.yml
new file mode 100644
index 00000000000..f91e410da43
--- /dev/null
+++ b/changelogs/unreleased/35404-automatic-rollback-in-case-of-failure.yml
@@ -0,0 +1,5 @@
+---
+title: Add auto_rollback_enabled column to project_ci_cd_settings table
+merge_request: 45816
+author:
+type: other
diff --git a/changelogs/unreleased/36820-fj-add-generic-canonical-url.yml b/changelogs/unreleased/36820-fj-add-generic-canonical-url.yml
new file mode 100644
index 00000000000..f647b6594ad
--- /dev/null
+++ b/changelogs/unreleased/36820-fj-add-generic-canonical-url.yml
@@ -0,0 +1,5 @@
+---
+title: Generate canonical url and remove trailing slash
+merge_request: 46435
+author:
+type: changed
diff --git a/changelogs/unreleased/36836-fj-allow-indexing-snippets-in-robots.yml b/changelogs/unreleased/36836-fj-allow-indexing-snippets-in-robots.yml
new file mode 100644
index 00000000000..00006844f49
--- /dev/null
+++ b/changelogs/unreleased/36836-fj-allow-indexing-snippets-in-robots.yml
@@ -0,0 +1,5 @@
+---
+title: Allow user snippets to be indexed by search crawlers
+merge_request: 45793
+author:
+type: changed
diff --git a/changelogs/unreleased/36837-fj-fix-bug-robots-git-suffix.yml b/changelogs/unreleased/36837-fj-fix-bug-robots-git-suffix.yml
new file mode 100644
index 00000000000..5b6db6de862
--- /dev/null
+++ b/changelogs/unreleased/36837-fj-fix-bug-robots-git-suffix.yml
@@ -0,0 +1,5 @@
+---
+title: Fix bug with robots and .git suffix
+merge_request: 45866
+author:
+type: fixed
diff --git a/changelogs/unreleased/36844-fj-add-schema-to-breadcrumb-json.yml b/changelogs/unreleased/36844-fj-add-schema-to-breadcrumb-json.yml
new file mode 100644
index 00000000000..d45374e22a8
--- /dev/null
+++ b/changelogs/unreleased/36844-fj-add-schema-to-breadcrumb-json.yml
@@ -0,0 +1,5 @@
+---
+title: Add SEO schema markup to breadcrumbs
+merge_request: 46991
+author:
+type: added
diff --git a/changelogs/unreleased/36846-fj-add-structured-data-for-projects.yml b/changelogs/unreleased/36846-fj-add-structured-data-for-projects.yml
new file mode 100644
index 00000000000..a71a9757324
--- /dev/null
+++ b/changelogs/unreleased/36846-fj-add-structured-data-for-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Add structured data for projects
+merge_request: 46858
+author:
+type: added
diff --git a/changelogs/unreleased/37102-expose-human-readable-time-estimate-via-graphql.yml b/changelogs/unreleased/37102-expose-human-readable-time-estimate-via-graphql.yml
new file mode 100644
index 00000000000..a05278e94fc
--- /dev/null
+++ b/changelogs/unreleased/37102-expose-human-readable-time-estimate-via-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Expose humanTimeEstimate and humanTotalTimeSpent via graphql
+merge_request: 45508
+author:
+type: changed
diff --git a/changelogs/unreleased/46087.yml b/changelogs/unreleased/46087.yml
new file mode 100644
index 00000000000..3cec8195d6a
--- /dev/null
+++ b/changelogs/unreleased/46087.yml
@@ -0,0 +1,5 @@
+---
+title: Clarify that external users cannot access all internal projects, groups, and snippets
+merge_request: 46087
+author: Ben Bodenmiller (@bbodenmiller)
+type: other
diff --git a/changelogs/unreleased/47531-fix-secure-bin-tmpl.yml b/changelogs/unreleased/47531-fix-secure-bin-tmpl.yml
new file mode 100644
index 00000000000..86558a81028
--- /dev/null
+++ b/changelogs/unreleased/47531-fix-secure-bin-tmpl.yml
@@ -0,0 +1,5 @@
+---
+title: Bump versions of secrets and klar in the Secure-Binaries template
+merge_request: 47531
+author:
+type: fixed
diff --git a/changelogs/unreleased/7314-backup-files-noncritical-warnings.yml b/changelogs/unreleased/7314-backup-files-noncritical-warnings.yml
new file mode 100644
index 00000000000..e0da6d651d8
--- /dev/null
+++ b/changelogs/unreleased/7314-backup-files-noncritical-warnings.yml
@@ -0,0 +1,6 @@
+---
+title: Show tar warning message when file/folder changed during backup instead of
+ failing whole backup operation
+merge_request: 42197
+author:
+type: fixed
diff --git a/changelogs/unreleased/Add-Caching-To-BitBucket-Server-Importer.yml b/changelogs/unreleased/Add-Caching-To-BitBucket-Server-Importer.yml
new file mode 100644
index 00000000000..eb4c64fe8b9
--- /dev/null
+++ b/changelogs/unreleased/Add-Caching-To-BitBucket-Server-Importer.yml
@@ -0,0 +1,5 @@
+---
+title: Add Caching to BitBucket Server Import for pull requests
+merge_request: 45790
+author: Simon Schrottner
+type: performance
diff --git a/changelogs/unreleased/Change-BitBucket-Pull-Request-Import-to-a-Batched-Process.yml b/changelogs/unreleased/Change-BitBucket-Pull-Request-Import-to-a-Batched-Process.yml
new file mode 100644
index 00000000000..3e63f116778
--- /dev/null
+++ b/changelogs/unreleased/Change-BitBucket-Pull-Request-Import-to-a-Batched-Process.yml
@@ -0,0 +1,5 @@
+---
+title: Add Batch Support for Importing Pull Requests from Bitbucket
+merge_request: 46696
+author: Simon Schrottner
+type: performance
diff --git a/changelogs/unreleased/Fix-bad-escape-in-empty_state-vue.yml b/changelogs/unreleased/Fix-bad-escape-in-empty_state-vue.yml
new file mode 100644
index 00000000000..68b65df96d9
--- /dev/null
+++ b/changelogs/unreleased/Fix-bad-escape-in-empty_state-vue.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Bad Escape in Issue Board Empty State
+merge_request: 45465
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/ImproveShellScriptsChangeDirException.yml b/changelogs/unreleased/ImproveShellScriptsChangeDirException.yml
new file mode 100644
index 00000000000..8d14907e88d
--- /dev/null
+++ b/changelogs/unreleased/ImproveShellScriptsChangeDirException.yml
@@ -0,0 +1,5 @@
+---
+title: Execute `exit 1` when shell script `cd` fails
+merge_request: 46122
+author: Peter Dave Hello
+type: other
diff --git a/changelogs/unreleased/ImproveShellScriptsVariable.yml b/changelogs/unreleased/ImproveShellScriptsVariable.yml
new file mode 100644
index 00000000000..d95f93b6f7d
--- /dev/null
+++ b/changelogs/unreleased/ImproveShellScriptsVariable.yml
@@ -0,0 +1,5 @@
+---
+title: Declare and assign variable separately in Shell Script
+merge_request: 46121
+author: Peter Dave Hello @PeterDaveHello
+type: other
diff --git a/changelogs/unreleased/Migrate-Bootstrap-dropdown-to-GitLab-UI-GlDropdown-in-app-assets-javascri.yml b/changelogs/unreleased/Migrate-Bootstrap-dropdown-to-GitLab-UI-GlDropdown-in-app-assets-javascri.yml
new file mode 100644
index 00000000000..4329e48355a
--- /dev/null
+++ b/changelogs/unreleased/Migrate-Bootstrap-dropdown-to-GitLab-UI-GlDropdown-in-app-assets-javascri.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate-Bootstrap-dropdown-to-GitLab-UI-GlDropdown-in-app/assets/javascripts/jobs/components/stages_dropdown.vue
+merge_request: 41452
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-er.yml b/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-er.yml
new file mode 100644
index 00000000000..e3a6921742a
--- /dev/null
+++ b/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-er.yml
@@ -0,0 +1,5 @@
+---
+title: Replace-GlDeprecatedDropdown-with-GlDropdown-in-app/assets/javascripts/error_tracking
+merge_request: 41420
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-mo.yml b/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-mo.yml
new file mode 100644
index 00000000000..4705aa39c0b
--- /dev/null
+++ b/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-mo.yml
@@ -0,0 +1,5 @@
+---
+title: Replace-GlDeprecatedDropdown-with-GlDropdown-in-app/assets/javascripts/monitoring
+merge_request: 41422
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-re.yml b/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-re.yml
new file mode 100644
index 00000000000..31b8452a758
--- /dev/null
+++ b/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-re.yml
@@ -0,0 +1,5 @@
+---
+title: Replace Deprecated Dropdown in Container Registry Explorer Page
+merge_request: 41425
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-sn.yml b/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-sn.yml
new file mode 100644
index 00000000000..30935278591
--- /dev/null
+++ b/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-sn.yml
@@ -0,0 +1,5 @@
+---
+title: Replace-GlDeprecatedDropdown-with-GlDropdown-in-app/assets/javascripts/snippets/components/snippet_header.vue
+merge_request: 41428
+author: nuwe1
+type: other
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..db712295b7b
--- /dev/null
+++ b/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-vu.yml
@@ -0,0 +1,5 @@
+---
+title: Replace-GlDeprecatedDropdown-with-GlDropdown-in-app/assets/javascripts/vue_merge_request_widget
+merge_request: 41429
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Resolve-Migrate--fa-spinner-app-helpers.yml b/changelogs/unreleased/Resolve-Migrate--fa-spinner-app-helpers.yml
new file mode 100644
index 00000000000..252a36b8328
--- /dev/null
+++ b/changelogs/unreleased/Resolve-Migrate--fa-spinner-app-helpers.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate .fa-spinner to .spinner for app/helpers
+merge_request: 25033
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/ab-add-missing-expression-indexes.yml b/changelogs/unreleased/ab-add-missing-expression-indexes.yml
new file mode 100644
index 00000000000..6e6d6b8f5c4
--- /dev/null
+++ b/changelogs/unreleased/ab-add-missing-expression-indexes.yml
@@ -0,0 +1,5 @@
+---
+title: Add missing expression indexes
+merge_request: 47424
+author:
+type: performance
diff --git a/changelogs/unreleased/ab-primary-keys.yml b/changelogs/unreleased/ab-primary-keys.yml
new file mode 100644
index 00000000000..ff1ca7aa794
--- /dev/null
+++ b/changelogs/unreleased/ab-primary-keys.yml
@@ -0,0 +1,5 @@
+---
+title: Specify primary key for tables without
+merge_request: 45198
+author:
+type: other
diff --git a/changelogs/unreleased/ab-reindex-functional.yml b/changelogs/unreleased/ab-reindex-functional.yml
new file mode 100644
index 00000000000..b3da969ba1f
--- /dev/null
+++ b/changelogs/unreleased/ab-reindex-functional.yml
@@ -0,0 +1,5 @@
+---
+title: Expand postgres_indexes view
+merge_request: 47304
+author:
+type: other
diff --git a/changelogs/unreleased/add-ci-status-css-to-environments.yml b/changelogs/unreleased/add-ci-status-css-to-environments.yml
new file mode 100644
index 00000000000..2ea47f432e1
--- /dev/null
+++ b/changelogs/unreleased/add-ci-status-css-to-environments.yml
@@ -0,0 +1,5 @@
+---
+title: Add CI Status CSS to the Environments Page
+merge_request: 46382
+author:
+type: fixed
diff --git a/changelogs/unreleased/add-emails-disabled-field-to-project-type.yml b/changelogs/unreleased/add-emails-disabled-field-to-project-type.yml
new file mode 100644
index 00000000000..decbfda2f52
--- /dev/null
+++ b/changelogs/unreleased/add-emails-disabled-field-to-project-type.yml
@@ -0,0 +1,5 @@
+---
+title: Add emailsDisabled field for issue type
+merge_request: 46947
+author:
+type: changed
diff --git a/changelogs/unreleased/add-get-invitations-for-group-and-project.yml b/changelogs/unreleased/add-get-invitations-for-group-and-project.yml
new file mode 100644
index 00000000000..6a8d3939d69
--- /dev/null
+++ b/changelogs/unreleased/add-get-invitations-for-group-and-project.yml
@@ -0,0 +1,5 @@
+---
+title: Add API get /invitations for project and group
+merge_request: 46046
+author:
+type: added
diff --git a/changelogs/unreleased/add-github-host-to-api.yml b/changelogs/unreleased/add-github-host-to-api.yml
new file mode 100644
index 00000000000..9c31457db04
--- /dev/null
+++ b/changelogs/unreleased/add-github-host-to-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add hostname to GitHub import API
+merge_request: 45188
+author:
+type: added
diff --git a/changelogs/unreleased/add-helm3-support-for-cluster-apps.yml b/changelogs/unreleased/add-helm3-support-for-cluster-apps.yml
new file mode 100644
index 00000000000..334f5e0ee36
--- /dev/null
+++ b/changelogs/unreleased/add-helm3-support-for-cluster-apps.yml
@@ -0,0 +1,5 @@
+---
+title: Use Helm 3 by default for GitLab-managed apps in new clusters
+merge_request: 46267
+author:
+type: changed
diff --git a/changelogs/unreleased/add-nulls-last-to-db-index.yml b/changelogs/unreleased/add-nulls-last-to-db-index.yml
new file mode 100644
index 00000000000..f1fc7b04785
--- /dev/null
+++ b/changelogs/unreleased/add-nulls-last-to-db-index.yml
@@ -0,0 +1,5 @@
+---
+title: Add NULLS LAST to index on merge request metrics
+merge_request: 47300
+author:
+type: performance
diff --git a/changelogs/unreleased/add-post-invitations-with-email.yml b/changelogs/unreleased/add-post-invitations-with-email.yml
new file mode 100644
index 00000000000..be96a0da598
--- /dev/null
+++ b/changelogs/unreleased/add-post-invitations-with-email.yml
@@ -0,0 +1,5 @@
+---
+title: Add API post /invitations by email
+merge_request: 45950
+author:
+type: added
diff --git a/changelogs/unreleased/add-total-duration-to-cicd-analytics-page.yml b/changelogs/unreleased/add-total-duration-to-cicd-analytics-page.yml
new file mode 100644
index 00000000000..528ed67af24
--- /dev/null
+++ b/changelogs/unreleased/add-total-duration-to-cicd-analytics-page.yml
@@ -0,0 +1,5 @@
+---
+title: Add Total Duration to CI/CD Analytics Page
+merge_request: 44863
+author: Kev @KevSlashNull
+type: added
diff --git a/changelogs/unreleased/add-user-discussions-count-to-issues-and-merge-requests.yml b/changelogs/unreleased/add-user-discussions-count-to-issues-and-merge-requests.yml
new file mode 100644
index 00000000000..1c8dc95d6fe
--- /dev/null
+++ b/changelogs/unreleased/add-user-discussions-count-to-issues-and-merge-requests.yml
@@ -0,0 +1,5 @@
+---
+title: Add userDiscussionsCount to issues and merge requests GraphQL
+merge_request: 46311
+author:
+type: added
diff --git a/changelogs/unreleased/add_existing_column_check_to_46532.yml b/changelogs/unreleased/add_existing_column_check_to_46532.yml
new file mode 100644
index 00000000000..18ef10c0063
--- /dev/null
+++ b/changelogs/unreleased/add_existing_column_check_to_46532.yml
@@ -0,0 +1,5 @@
+---
+title: Guard against existence of project_features.requirement_access_level in migration
+merge_request: 47458
+author: Lee Tickett
+type: other
diff --git a/changelogs/unreleased/add_msg_for_missing_license_covfuzz.yml b/changelogs/unreleased/add_msg_for_missing_license_covfuzz.yml
new file mode 100644
index 00000000000..c486e479f5d
--- /dev/null
+++ b/changelogs/unreleased/add_msg_for_missing_license_covfuzz.yml
@@ -0,0 +1,5 @@
+---
+title: Show error in pipeline when Coverage Fuzzing not licensed
+merge_request: 46652
+author:
+type: changed
diff --git a/changelogs/unreleased/add_tooltips_to_design_buttons.yml b/changelogs/unreleased/add_tooltips_to_design_buttons.yml
new file mode 100644
index 00000000000..b5e5826eae8
--- /dev/null
+++ b/changelogs/unreleased/add_tooltips_to_design_buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Add tooltips to design buttons
+merge_request: 46922
+author: Lee Tickett
+type: added
diff --git a/changelogs/unreleased/ajk-214978-designs-iids.yml b/changelogs/unreleased/ajk-214978-designs-iids.yml
new file mode 100644
index 00000000000..5f397c6dcd1
--- /dev/null
+++ b/changelogs/unreleased/ajk-214978-designs-iids.yml
@@ -0,0 +1,5 @@
+---
+title: Add iid column to design_management_designs
+merge_request: 46596
+author:
+type: added
diff --git a/changelogs/unreleased/ajk-globalid-error-tracking.yml b/changelogs/unreleased/ajk-globalid-error-tracking.yml
new file mode 100644
index 00000000000..12567b785ab
--- /dev/null
+++ b/changelogs/unreleased/ajk-globalid-error-tracking.yml
@@ -0,0 +1,5 @@
+---
+title: Use global IDs for GraphQL arguments accepting sentry IDs
+merge_request: 36098
+author:
+type: changed
diff --git a/changelogs/unreleased/ajk-globalid-snippets.yml b/changelogs/unreleased/ajk-globalid-snippets.yml
new file mode 100644
index 00000000000..157dea91f2d
--- /dev/null
+++ b/changelogs/unreleased/ajk-globalid-snippets.yml
@@ -0,0 +1,5 @@
+---
+title: 'GraphQL Snippets: use Global-ID scalar'
+merge_request: 36117
+author:
+type: changed
diff --git a/changelogs/unreleased/ajk-group-member-policy.yml b/changelogs/unreleased/ajk-group-member-policy.yml
new file mode 100644
index 00000000000..5824a8c6db0
--- /dev/null
+++ b/changelogs/unreleased/ajk-group-member-policy.yml
@@ -0,0 +1,5 @@
+---
+title: Fix overly aggressive prevent call
+merge_request: 47455
+author:
+type: fixed
diff --git a/changelogs/unreleased/ak-fix-chatbot-replies.yml b/changelogs/unreleased/ak-fix-chatbot-replies.yml
new file mode 100644
index 00000000000..30b961d9a3b
--- /dev/null
+++ b/changelogs/unreleased/ak-fix-chatbot-replies.yml
@@ -0,0 +1,5 @@
+---
+title: Fix chatbot replies not including job log
+merge_request: 42010
+author:
+type: fixed
diff --git a/changelogs/unreleased/ak-fix-loading-file.yml b/changelogs/unreleased/ak-fix-loading-file.yml
new file mode 100644
index 00000000000..16396855b37
--- /dev/null
+++ b/changelogs/unreleased/ak-fix-loading-file.yml
@@ -0,0 +1,5 @@
+---
+title: Fix relative path not found on production web server
+merge_request: 47090
+author:
+type: fixed
diff --git a/changelogs/unreleased/alexives-258262-remove_columns_for_tf_state_validation.yml b/changelogs/unreleased/alexives-258262-remove_columns_for_tf_state_validation.yml
new file mode 100644
index 00000000000..8cdbade6547
--- /dev/null
+++ b/changelogs/unreleased/alexives-258262-remove_columns_for_tf_state_validation.yml
@@ -0,0 +1,5 @@
+---
+title: Remove columns no longer used for replicating terraform state
+merge_request: 46742
+author:
+type: other
diff --git a/changelogs/unreleased/alipniagov-update-workhorse-to-8-54.yml b/changelogs/unreleased/alipniagov-update-workhorse-to-8-54.yml
new file mode 100644
index 00000000000..c57e1e5ef7d
--- /dev/null
+++ b/changelogs/unreleased/alipniagov-update-workhorse-to-8-54.yml
@@ -0,0 +1,5 @@
+---
+title: Update Workhorse version to 8.54.0
+merge_request: 47625
+author:
+type: other
diff --git a/changelogs/unreleased/allow_repo_storage_moves_without_repo.yml b/changelogs/unreleased/allow_repo_storage_moves_without_repo.yml
new file mode 100644
index 00000000000..4975480e349
--- /dev/null
+++ b/changelogs/unreleased/allow_repo_storage_moves_without_repo.yml
@@ -0,0 +1,5 @@
+---
+title: Allow project storage to be updated when no repositories exist
+merge_request: 46385
+author:
+type: fixed
diff --git a/changelogs/unreleased/arty-admin-idpid.yml b/changelogs/unreleased/arty-admin-idpid.yml
new file mode 100644
index 00000000000..13bf180dfce
--- /dev/null
+++ b/changelogs/unreleased/arty-admin-idpid.yml
@@ -0,0 +1,5 @@
+---
+title: Display Group SAML provider ID in admin
+merge_request: 47034
+author:
+type: added
diff --git a/changelogs/unreleased/ashmckenzie-gitlab-shell-release-13-13-0.yml b/changelogs/unreleased/ashmckenzie-gitlab-shell-release-13-13-0.yml
new file mode 100644
index 00000000000..17985531638
--- /dev/null
+++ b/changelogs/unreleased/ashmckenzie-gitlab-shell-release-13-13-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Shell to v13.13.0
+merge_request: 47875
+author:
+type: other
diff --git a/changelogs/unreleased/bjk-http_requests_total_status_matrix.yml b/changelogs/unreleased/bjk-http_requests_total_status_matrix.yml
new file mode 100644
index 00000000000..979e6f507a0
--- /dev/null
+++ b/changelogs/unreleased/bjk-http_requests_total_status_matrix.yml
@@ -0,0 +1,5 @@
+---
+title: Make sure the http_requests_total and http_request_duration_seconds metrics are not empty on application start
+merge_request: 45755
+author:
+type: fixed
diff --git a/changelogs/unreleased/boards-css-clean-up.yml b/changelogs/unreleased/boards-css-clean-up.yml
new file mode 100644
index 00000000000..d4b5319741f
--- /dev/null
+++ b/changelogs/unreleased/boards-css-clean-up.yml
@@ -0,0 +1,5 @@
+---
+title: Boards - Fix Milestone icon alignment in header
+merge_request: 45965
+author:
+type: fixed
diff --git a/changelogs/unreleased/bvl-handle-invalid-headers.yml b/changelogs/unreleased/bvl-handle-invalid-headers.yml
new file mode 100644
index 00000000000..94a2f5b46aa
--- /dev/null
+++ b/changelogs/unreleased/bvl-handle-invalid-headers.yml
@@ -0,0 +1,5 @@
+---
+title: Handle nullbytes in auth headers
+merge_request: 47206
+author:
+type: fixed
diff --git a/changelogs/unreleased/bvl-reject-more-invalid-utf8.yml b/changelogs/unreleased/bvl-reject-more-invalid-utf8.yml
new file mode 100644
index 00000000000..9e857943cb6
--- /dev/null
+++ b/changelogs/unreleased/bvl-reject-more-invalid-utf8.yml
@@ -0,0 +1,5 @@
+---
+title: Reject incomplete multibyte chars in UTF8 params
+merge_request: 47658
+author:
+type: fixed
diff --git a/changelogs/unreleased/cablett-231472-group-labels.yml b/changelogs/unreleased/cablett-231472-group-labels.yml
new file mode 100644
index 00000000000..9173e6a70fc
--- /dev/null
+++ b/changelogs/unreleased/cablett-231472-group-labels.yml
@@ -0,0 +1,5 @@
+---
+title: Use existing group label when promoting project label
+merge_request: 45122
+author:
+type: changed
diff --git a/changelogs/unreleased/cache-raw-endpoints-for-logged-in-users.yml b/changelogs/unreleased/cache-raw-endpoints-for-logged-in-users.yml
new file mode 100644
index 00000000000..2c3b7863b7b
--- /dev/null
+++ b/changelogs/unreleased/cache-raw-endpoints-for-logged-in-users.yml
@@ -0,0 +1,5 @@
+---
+title: Enable HTTP caching of repository raw, archive, and avatar endpoints
+merge_request: 47430
+author:
+type: performance
diff --git a/changelogs/unreleased/cat-fix-sprite-failed-builds.yml b/changelogs/unreleased/cat-fix-sprite-failed-builds.yml
new file mode 100644
index 00000000000..b88e09b5877
--- /dev/null
+++ b/changelogs/unreleased/cat-fix-sprite-failed-builds.yml
@@ -0,0 +1,5 @@
+---
+title: Fix retried builds icon sprite to use css_class
+merge_request: 46955
+author:
+type: fixed
diff --git a/changelogs/unreleased/cat-readd-logging-for-ints-273663.yml b/changelogs/unreleased/cat-readd-logging-for-ints-273663.yml
new file mode 100644
index 00000000000..4bc04d600de
--- /dev/null
+++ b/changelogs/unreleased/cat-readd-logging-for-ints-273663.yml
@@ -0,0 +1,5 @@
+---
+title: Fix logging handling for API integer params
+merge_request: 46551
+author:
+type: fixed
diff --git a/changelogs/unreleased/chore-disable-admin-mode-in-services.yml b/changelogs/unreleased/chore-disable-admin-mode-in-services.yml
new file mode 100644
index 00000000000..868d2b43a9a
--- /dev/null
+++ b/changelogs/unreleased/chore-disable-admin-mode-in-services.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate services specs to consider admin mode
+merge_request: 45988
+author: Diego Louzán
+type: other
diff --git a/changelogs/unreleased/ci-enable-variable-expansion-in-rules-changes.yml b/changelogs/unreleased/ci-enable-variable-expansion-in-rules-changes.yml
new file mode 100644
index 00000000000..6a5fbff68cf
--- /dev/null
+++ b/changelogs/unreleased/ci-enable-variable-expansion-in-rules-changes.yml
@@ -0,0 +1,5 @@
+---
+title: Add variable expansion to rules:changes
+merge_request: 47783
+author:
+type: added
diff --git a/changelogs/unreleased/ci-jwt-signing-key-enable-by-default.yml b/changelogs/unreleased/ci-jwt-signing-key-enable-by-default.yml
new file mode 100644
index 00000000000..4f063762bfa
--- /dev/null
+++ b/changelogs/unreleased/ci-jwt-signing-key-enable-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Use dedicated signing key for CI_JOB_JWT by default
+merge_request: 47336
+author:
+type: changed
diff --git a/changelogs/unreleased/cleanup_policy_regex_defaults.yml b/changelogs/unreleased/cleanup_policy_regex_defaults.yml
new file mode 100644
index 00000000000..1d0ed26e273
--- /dev/null
+++ b/changelogs/unreleased/cleanup_policy_regex_defaults.yml
@@ -0,0 +1,5 @@
+---
+title: Add default regexes and prevent blank regexes for container cleanup policies
+merge_request: 44757
+author:
+type: changed
diff --git a/changelogs/unreleased/cngo-remove-positive-tabindexes.yml b/changelogs/unreleased/cngo-remove-positive-tabindexes.yml
new file mode 100644
index 00000000000..7461c3cfa89
--- /dev/null
+++ b/changelogs/unreleased/cngo-remove-positive-tabindexes.yml
@@ -0,0 +1,5 @@
+---
+title: Remove positive tabindexes
+merge_request: 46003
+author:
+type: fixed
diff --git a/changelogs/unreleased/dast-site-validation-create-mutation-233020.yml b/changelogs/unreleased/dast-site-validation-create-mutation-233020.yml
new file mode 100644
index 00000000000..4c2759b5f2b
--- /dev/null
+++ b/changelogs/unreleased/dast-site-validation-create-mutation-233020.yml
@@ -0,0 +1,5 @@
+---
+title: Add db index for DastSiteValidation#state
+merge_request: 45019
+author:
+type: added
diff --git a/changelogs/unreleased/dblessing_auth_events_usage_ping_fix.yml b/changelogs/unreleased/dblessing_auth_events_usage_ping_fix.yml
new file mode 100644
index 00000000000..0c275f10965
--- /dev/null
+++ b/changelogs/unreleased/dblessing_auth_events_usage_ping_fix.yml
@@ -0,0 +1,5 @@
+---
+title: Replace poorly performing auth event providers query in usage ping
+merge_request: 47710
+author:
+type: fixed
diff --git a/changelogs/unreleased/debian_parsers.yml b/changelogs/unreleased/debian_parsers.yml
new file mode 100644
index 00000000000..c85f0b394e1
--- /dev/null
+++ b/changelogs/unreleased/debian_parsers.yml
@@ -0,0 +1,5 @@
+---
+title: Debian RFC822 and .deb metadata extractor
+merge_request: 44029
+author: Mathieu Parent
+type: added
diff --git a/changelogs/unreleased/defect-collapsed-files-expand-renamed-files.yml b/changelogs/unreleased/defect-collapsed-files-expand-renamed-files.yml
new file mode 100644
index 00000000000..e52a4a01fb3
--- /dev/null
+++ b/changelogs/unreleased/defect-collapsed-files-expand-renamed-files.yml
@@ -0,0 +1,5 @@
+---
+title: Assign new incoming diff lines for renamed files to the correct view type
+merge_request: 46823
+author:
+type: fixed
diff --git a/changelogs/unreleased/defect-fork-general-settings-copy.yml b/changelogs/unreleased/defect-fork-general-settings-copy.yml
new file mode 100644
index 00000000000..02b38b5955d
--- /dev/null
+++ b/changelogs/unreleased/defect-fork-general-settings-copy.yml
@@ -0,0 +1,5 @@
+---
+title: Change wording on the project remove fork page
+merge_request: 47878
+author:
+type: other
diff --git a/changelogs/unreleased/delete_tags_service_logging_enhancement.yml b/changelogs/unreleased/delete_tags_service_logging_enhancement.yml
new file mode 100644
index 00000000000..c248634ae42
--- /dev/null
+++ b/changelogs/unreleased/delete_tags_service_logging_enhancement.yml
@@ -0,0 +1,6 @@
+---
+title: Improving Container Registry Delete Tags Service to log number of successfully
+ deleted tags even if deletion process was interrupted by a timeout
+merge_request: 46079
+author: Maksim Stankevic, @maksimstankevic
+type: changed
diff --git a/changelogs/unreleased/deprecate-support-for-es6.yml b/changelogs/unreleased/deprecate-support-for-es6.yml
new file mode 100644
index 00000000000..cf766d09527
--- /dev/null
+++ b/changelogs/unreleased/deprecate-support-for-es6.yml
@@ -0,0 +1,5 @@
+---
+title: Deprecate support for Elasticsearch 6.x
+merge_request: 45619
+author:
+type: deprecated
diff --git a/changelogs/unreleased/design-upload-button-loading-prop.yml b/changelogs/unreleased/design-upload-button-loading-prop.yml
new file mode 100644
index 00000000000..ab8b53d7922
--- /dev/null
+++ b/changelogs/unreleased/design-upload-button-loading-prop.yml
@@ -0,0 +1,5 @@
+---
+title: Use standard loading state for Design Upload button
+merge_request: 46292
+author:
+type: changed
diff --git a/changelogs/unreleased/dj-fix-anchor-linebreak-issue.yml b/changelogs/unreleased/dj-fix-anchor-linebreak-issue.yml
new file mode 100644
index 00000000000..edda0422046
--- /dev/null
+++ b/changelogs/unreleased/dj-fix-anchor-linebreak-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Fix linebreak issue in last commit anchor
+merge_request: 46643
+author:
+type: fixed
diff --git a/changelogs/unreleased/dmishunov-276913-snippet-copy-content.yml b/changelogs/unreleased/dmishunov-276913-snippet-copy-content.yml
new file mode 100644
index 00000000000..78b586942bb
--- /dev/null
+++ b/changelogs/unreleased/dmishunov-276913-snippet-copy-content.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed copy contents functionality for snippets
+merge_request: 47646
+author:
+type: fixed
diff --git a/changelogs/unreleased/docs-api-boards.yml b/changelogs/unreleased/docs-api-boards.yml
new file mode 100644
index 00000000000..91967443f49
--- /dev/null
+++ b/changelogs/unreleased/docs-api-boards.yml
@@ -0,0 +1,5 @@
+---
+title: Copyedit Project Issue Boards API docs
+merge_request: 46110
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/docs-for-canary-ingress-weight-change.yml b/changelogs/unreleased/docs-for-canary-ingress-weight-change.yml
new file mode 100644
index 00000000000..17f452434b9
--- /dev/null
+++ b/changelogs/unreleased/docs-for-canary-ingress-weight-change.yml
@@ -0,0 +1,5 @@
+---
+title: Add Support for Canary-Weight ingress annotation via API
+merge_request: 45637
+author:
+type: added
diff --git a/changelogs/unreleased/dstull-update-whitelist-blacklist-to-allowlist-denylist-in-signup-restric.yml b/changelogs/unreleased/dstull-update-whitelist-blacklist-to-allowlist-denylist-in-signup-restric.yml
new file mode 100644
index 00000000000..a213f1e4585
--- /dev/null
+++ b/changelogs/unreleased/dstull-update-whitelist-blacklist-to-allowlist-denylist-in-signup-restric.yml
@@ -0,0 +1,5 @@
+---
+title: Use allowlist/denylist in application settings backend
+merge_request: 46170
+author:
+type: changed
diff --git a/changelogs/unreleased/eb-remove-tracking-test-cases-feature-flag.yml b/changelogs/unreleased/eb-remove-tracking-test-cases-feature-flag.yml
new file mode 100644
index 00000000000..2e7c604116d
--- /dev/null
+++ b/changelogs/unreleased/eb-remove-tracking-test-cases-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove feature flag to enable tracking unique test cases parsed globally.
+merge_request: 47662
+author:
+type: changed
diff --git a/changelogs/unreleased/eb-test-failure-history-mvc.yml b/changelogs/unreleased/eb-test-failure-history-mvc.yml
new file mode 100644
index 00000000000..f05684787f8
--- /dev/null
+++ b/changelogs/unreleased/eb-test-failure-history-mvc.yml
@@ -0,0 +1,5 @@
+---
+title: Store test failure data when build finishes
+merge_request: 45027
+author:
+type: added
diff --git a/changelogs/unreleased/ek-fix-set-status-modal-tooltip-trigger.yml b/changelogs/unreleased/ek-fix-set-status-modal-tooltip-trigger.yml
new file mode 100644
index 00000000000..e923e4b0f63
--- /dev/null
+++ b/changelogs/unreleased/ek-fix-set-status-modal-tooltip-trigger.yml
@@ -0,0 +1,5 @@
+---
+title: Fix status emoji tooltip trigger
+merge_request: 47378
+author:
+type: fixed
diff --git a/changelogs/unreleased/emilyring-state-pagination.yml b/changelogs/unreleased/emilyring-state-pagination.yml
new file mode 100644
index 00000000000..290d6fb7afd
--- /dev/null
+++ b/changelogs/unreleased/emilyring-state-pagination.yml
@@ -0,0 +1,5 @@
+---
+title: Add pagination to Terraform list view
+merge_request: 47412
+author:
+type: changed
diff --git a/changelogs/unreleased/emilyring-terraform-fixes.yml b/changelogs/unreleased/emilyring-terraform-fixes.yml
new file mode 100644
index 00000000000..a733340936b
--- /dev/null
+++ b/changelogs/unreleased/emilyring-terraform-fixes.yml
@@ -0,0 +1,5 @@
+---
+title: Fix for missing user info for Terraform State
+merge_request: 47814
+author:
+type: fixed
diff --git a/changelogs/unreleased/enable-ci-deleted-objects-ff.yml b/changelogs/unreleased/enable-ci-deleted-objects-ff.yml
new file mode 100644
index 00000000000..f7c76c1ed8e
--- /dev/null
+++ b/changelogs/unreleased/enable-ci-deleted-objects-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Parallelize the removal of expired job artifacts
+merge_request: 46971
+author:
+type: performance
diff --git a/changelogs/unreleased/enable-deployments-filters.yml b/changelogs/unreleased/enable-deployments-filters.yml
new file mode 100644
index 00000000000..2c77a562179
--- /dev/null
+++ b/changelogs/unreleased/enable-deployments-filters.yml
@@ -0,0 +1,5 @@
+---
+title: Add merge requests filters for filtering by environments and deployment dates
+merge_request: 46683
+author:
+type: added
diff --git a/changelogs/unreleased/enable_instance_statistics_ff_by_default.yml b/changelogs/unreleased/enable_instance_statistics_ff_by_default.yml
new file mode 100644
index 00000000000..0d56d5fd765
--- /dev/null
+++ b/changelogs/unreleased/enable_instance_statistics_ff_by_default.yml
@@ -0,0 +1,5 @@
+---
+title: Enable 'instance_statistics' feature flag by default
+merge_request: 46962
+author:
+type: changed
diff --git a/changelogs/unreleased/feat-scoverage-ci-regex.yml b/changelogs/unreleased/feat-scoverage-ci-regex.yml
new file mode 100644
index 00000000000..12c611d43c6
--- /dev/null
+++ b/changelogs/unreleased/feat-scoverage-ci-regex.yml
@@ -0,0 +1,5 @@
+---
+title: Added code coverage regex for Scala Scoverage
+merge_request: 46638
+author: opensorceror
+type: changed
diff --git a/changelogs/unreleased/feature-change-reactive-caching-limit-environment-default-to-true.yml b/changelogs/unreleased/feature-change-reactive-caching-limit-environment-default-to-true.yml
new file mode 100644
index 00000000000..4ec0062f6ec
--- /dev/null
+++ b/changelogs/unreleased/feature-change-reactive-caching-limit-environment-default-to-true.yml
@@ -0,0 +1,6 @@
+---
+title: Limits the Deploy Boards data to 10 MB. This change is enabled by default behind
+ a feature flag
+merge_request: 46043
+author:
+type: changed
diff --git a/changelogs/unreleased/feature-collapsed-diff-files-larger-ui.yml b/changelogs/unreleased/feature-collapsed-diff-files-larger-ui.yml
new file mode 100644
index 00000000000..1057c18522b
--- /dev/null
+++ b/changelogs/unreleased/feature-collapsed-diff-files-larger-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Expand Diff File collapsed UI to be significantly more obvious
+merge_request: 46286
+author:
+type: changed
diff --git a/changelogs/unreleased/feature-collapsed-diff-files-user-collapsed-flag.yml b/changelogs/unreleased/feature-collapsed-diff-files-user-collapsed-flag.yml
new file mode 100644
index 00000000000..5c38a1eb469
--- /dev/null
+++ b/changelogs/unreleased/feature-collapsed-diff-files-user-collapsed-flag.yml
@@ -0,0 +1,6 @@
+---
+title: Manually collapsed diff files are now significantly shorter and less visually
+ intrusive
+merge_request: 43911
+author:
+type: changed
diff --git a/changelogs/unreleased/feature-flags-edit-increase-loading-icon-size.yml b/changelogs/unreleased/feature-flags-edit-increase-loading-icon-size.yml
new file mode 100644
index 00000000000..89b3fe093ba
--- /dev/null
+++ b/changelogs/unreleased/feature-flags-edit-increase-loading-icon-size.yml
@@ -0,0 +1,5 @@
+---
+title: Make loading icon on feature flag edit page larger
+merge_request: 46268
+author:
+type: fixed
diff --git a/changelogs/unreleased/feature-flags-user-lists-search.yml b/changelogs/unreleased/feature-flags-user-lists-search.yml
new file mode 100644
index 00000000000..a9797438464
--- /dev/null
+++ b/changelogs/unreleased/feature-flags-user-lists-search.yml
@@ -0,0 +1,5 @@
+---
+title: Add Search for User Lists in Strategy
+merge_request: 45820
+author:
+type: added
diff --git a/changelogs/unreleased/feature-group-default-initial-branch-name.yml b/changelogs/unreleased/feature-group-default-initial-branch-name.yml
new file mode 100644
index 00000000000..b3059a2c0b2
--- /dev/null
+++ b/changelogs/unreleased/feature-group-default-initial-branch-name.yml
@@ -0,0 +1,5 @@
+---
+title: Add Default Initial Branch Name for Repositories Group Setting
+merge_request: 43290
+author:
+type: added
diff --git a/changelogs/unreleased/feature-mr-diffs-performance-marks.yml b/changelogs/unreleased/feature-mr-diffs-performance-marks.yml
new file mode 100644
index 00000000000..914991b2a91
--- /dev/null
+++ b/changelogs/unreleased/feature-mr-diffs-performance-marks.yml
@@ -0,0 +1,5 @@
+---
+title: Add performance marks and measures to the MR Diffs app at critical moments
+merge_request: 46434
+author:
+type: other
diff --git a/changelogs/unreleased/ff-export_merge_requests_as_csv-default-on.yml b/changelogs/unreleased/ff-export_merge_requests_as_csv-default-on.yml
new file mode 100644
index 00000000000..33381f0723f
--- /dev/null
+++ b/changelogs/unreleased/ff-export_merge_requests_as_csv-default-on.yml
@@ -0,0 +1,5 @@
+---
+title: Enable MR CSV export
+merge_request: 46662
+author:
+type: added
diff --git a/changelogs/unreleased/fix-api-boards-docs-ee.yml b/changelogs/unreleased/fix-api-boards-docs-ee.yml
new file mode 100644
index 00000000000..e342e9bc378
--- /dev/null
+++ b/changelogs/unreleased/fix-api-boards-docs-ee.yml
@@ -0,0 +1,5 @@
+---
+title: Fix example responses for Group Issue Board creation API in the docs
+merge_request: 46760
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/fix-api-boards-docs.yml b/changelogs/unreleased/fix-api-boards-docs.yml
new file mode 100644
index 00000000000..0f2a9fcd8e5
--- /dev/null
+++ b/changelogs/unreleased/fix-api-boards-docs.yml
@@ -0,0 +1,5 @@
+---
+title: Fix example responses for Project Issue Board creation API in the docs
+merge_request: 46749
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/fix-broken-paperclip.yml b/changelogs/unreleased/fix-broken-paperclip.yml
new file mode 100644
index 00000000000..4f8b15386f9
--- /dev/null
+++ b/changelogs/unreleased/fix-broken-paperclip.yml
@@ -0,0 +1,5 @@
+---
+title: Fix dropzone paperclip and loading icons
+merge_request: 46093
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-ci-lint-newlines.yml b/changelogs/unreleased/fix-ci-lint-newlines.yml
new file mode 100644
index 00000000000..f137ab50033
--- /dev/null
+++ b/changelogs/unreleased/fix-ci-lint-newlines.yml
@@ -0,0 +1,5 @@
+---
+title: 'Render script newlines in CI Lint view'
+merge_request: 45087
+author: Nejc Habjan
+type: fixed
diff --git a/changelogs/unreleased/fix-deprecated-stable-repository-error.yml b/changelogs/unreleased/fix-deprecated-stable-repository-error.yml
new file mode 100644
index 00000000000..58ba8810a8d
--- /dev/null
+++ b/changelogs/unreleased/fix-deprecated-stable-repository-error.yml
@@ -0,0 +1,5 @@
+---
+title: Fix auto-deploy-image fetches deprecated stable repository and causes an error
+merge_request: 45984
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-empty-user-list-dropdown-text.yml b/changelogs/unreleased/fix-empty-user-list-dropdown-text.yml
new file mode 100644
index 00000000000..e26d83ca7f3
--- /dev/null
+++ b/changelogs/unreleased/fix-empty-user-list-dropdown-text.yml
@@ -0,0 +1,5 @@
+---
+title: Show "No user list selected" in feature flags
+merge_request: 46790
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-issues-list-with-invalid-due-date.yml b/changelogs/unreleased/fix-issues-list-with-invalid-due-date.yml
new file mode 100644
index 00000000000..69dac74cb0f
--- /dev/null
+++ b/changelogs/unreleased/fix-issues-list-with-invalid-due-date.yml
@@ -0,0 +1,5 @@
+---
+title: Fix issues list when due date parameter is invalid
+merge_request: 47524
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-modal-margins.yml b/changelogs/unreleased/fix-modal-margins.yml
new file mode 100644
index 00000000000..7023b795432
--- /dev/null
+++ b/changelogs/unreleased/fix-modal-margins.yml
@@ -0,0 +1,5 @@
+---
+title: Remove the native styles for modal-dialog - Currently off center
+merge_request: 45789
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-padding-on-failed-job-tab.yml b/changelogs/unreleased/fix-padding-on-failed-job-tab.yml
new file mode 100644
index 00000000000..5dcbbdcdc01
--- /dev/null
+++ b/changelogs/unreleased/fix-padding-on-failed-job-tab.yml
@@ -0,0 +1,5 @@
+---
+title: Fix code lines being cut-off on failed job tab
+merge_request: 46885
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-search-bar-feature-flags.yml b/changelogs/unreleased/fix-search-bar-feature-flags.yml
new file mode 100644
index 00000000000..97dd01cb498
--- /dev/null
+++ b/changelogs/unreleased/fix-search-bar-feature-flags.yml
@@ -0,0 +1,5 @@
+---
+title: Fix when Feature Flags link is shown in search bar results
+merge_request: 45803
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix_sdesk_links.yml b/changelogs/unreleased/fix_sdesk_links.yml
new file mode 100644
index 00000000000..6c3140cc998
--- /dev/null
+++ b/changelogs/unreleased/fix_sdesk_links.yml
@@ -0,0 +1,6 @@
+---
+title: Render correct URLs for uploads in service desk issues when custom template
+ is used.
+merge_request: 45772
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-change-routable-redirect-to-301.yml b/changelogs/unreleased/fj-change-routable-redirect-to-301.yml
new file mode 100644
index 00000000000..63d52404fa7
--- /dev/null
+++ b/changelogs/unreleased/fj-change-routable-redirect-to-301.yml
@@ -0,0 +1,5 @@
+---
+title: Change permanent routable redirect to 301
+merge_request: 45980
+author:
+type: changed
diff --git a/changelogs/unreleased/fj-fix-bug-when-user-anonymous-and-import.yml b/changelogs/unreleased/fj-fix-bug-when-user-anonymous-and-import.yml
new file mode 100644
index 00000000000..1e6a5bd2efc
--- /dev/null
+++ b/changelogs/unreleased/fj-fix-bug-when-user-anonymous-and-import.yml
@@ -0,0 +1,5 @@
+---
+title: Fix bug accessing import route with no user
+merge_request: 46215
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-forbid-snippet-route.yml b/changelogs/unreleased/fj-forbid-snippet-route.yml
new file mode 100644
index 00000000000..5802bbc4ecc
--- /dev/null
+++ b/changelogs/unreleased/fj-forbid-snippet-route.yml
@@ -0,0 +1,5 @@
+---
+title: Forbid top-level route sitemap.xml
+merge_request: 45359
+author:
+type: changed
diff --git a/changelogs/unreleased/fj-forbid-top-level-route-sitemap.yml b/changelogs/unreleased/fj-forbid-top-level-route-sitemap.yml
new file mode 100644
index 00000000000..8baad160fb4
--- /dev/null
+++ b/changelogs/unreleased/fj-forbid-top-level-route-sitemap.yml
@@ -0,0 +1,5 @@
+---
+title: Forbid top level route sitemap
+merge_request: 46677
+author:
+type: changed
diff --git a/changelogs/unreleased/georgekoltsov-add-usage-ping-total-projects-imported.yml b/changelogs/unreleased/georgekoltsov-add-usage-ping-total-projects-imported.yml
new file mode 100644
index 00000000000..c52cbc338b7
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-add-usage-ping-total-projects-imported.yml
@@ -0,0 +1,5 @@
+---
+title: Add total projects imported usage ping
+merge_request: 46541
+author:
+type: added
diff --git a/changelogs/unreleased/georgekoltsov-ignore-failed-to-download-project-export-uploads.yml b/changelogs/unreleased/georgekoltsov-ignore-failed-to-download-project-export-uploads.yml
new file mode 100644
index 00000000000..9e51c3d9272
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-ignore-failed-to-download-project-export-uploads.yml
@@ -0,0 +1,6 @@
+---
+title: Fix 'File name too long' error happening during Project Export when exporting
+ project uploads
+merge_request: 46674
+author:
+type: fixed
diff --git a/changelogs/unreleased/georgekoltsov-use-github-api-for-filtering.yml b/changelogs/unreleased/georgekoltsov-use-github-api-for-filtering.yml
new file mode 100644
index 00000000000..6145846c6fb
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-use-github-api-for-filtering.yml
@@ -0,0 +1,5 @@
+---
+title: Filter GitHub projects to import using GitHub Search API
+merge_request: 47002
+author:
+type: changed
diff --git a/changelogs/unreleased/gl-tooltip-for-quick-submit.yml b/changelogs/unreleased/gl-tooltip-for-quick-submit.yml
new file mode 100644
index 00000000000..550035f26c7
--- /dev/null
+++ b/changelogs/unreleased/gl-tooltip-for-quick-submit.yml
@@ -0,0 +1,5 @@
+---
+title: Replace quick_submit BSTooltip with GlTooltip
+merge_request: 45638
+author: Kristin Brooks @kristinbrooks
+type: other
diff --git a/changelogs/unreleased/graphql_create_label.yml b/changelogs/unreleased/graphql_create_label.yml
new file mode 100644
index 00000000000..2ae2b950c83
--- /dev/null
+++ b/changelogs/unreleased/graphql_create_label.yml
@@ -0,0 +1,5 @@
+---
+title: Added GraphQL mutation for creating project and group labels
+merge_request: 46534
+author:
+type: added
diff --git a/changelogs/unreleased/gregmyers-webhook-useragent.yml b/changelogs/unreleased/gregmyers-webhook-useragent.yml
new file mode 100644
index 00000000000..22b4885dbdc
--- /dev/null
+++ b/changelogs/unreleased/gregmyers-webhook-useragent.yml
@@ -0,0 +1,5 @@
+---
+title: Add User-Agent to web hook service
+merge_request: 46070
+author:
+type: added
diff --git a/changelogs/unreleased/group-level-integration-feature-flag-default-enable.yml b/changelogs/unreleased/group-level-integration-feature-flag-default-enable.yml
new file mode 100644
index 00000000000..914ce4a0854
--- /dev/null
+++ b/changelogs/unreleased/group-level-integration-feature-flag-default-enable.yml
@@ -0,0 +1,5 @@
+---
+title: Add group-level integration management for external services.
+merge_request: 47391
+author:
+type: added
diff --git a/changelogs/unreleased/gy-fix-load-perf-docs.yml b/changelogs/unreleased/gy-fix-load-perf-docs.yml
new file mode 100644
index 00000000000..0c3c32d3b26
--- /dev/null
+++ b/changelogs/unreleased/gy-fix-load-perf-docs.yml
@@ -0,0 +1,5 @@
+---
+title: Fix incorrect code in Load Performance Testing docs
+merge_request: 45877
+author:
+type: other
diff --git a/changelogs/unreleased/himkp-fix-ide-discard.yml b/changelogs/unreleased/himkp-fix-ide-discard.yml
new file mode 100644
index 00000000000..ead221539eb
--- /dev/null
+++ b/changelogs/unreleased/himkp-fix-ide-discard.yml
@@ -0,0 +1,5 @@
+---
+title: Fix danger-secondary button in the Web IDE dark theme
+merge_request: 45714
+author:
+type: fixed
diff --git a/changelogs/unreleased/id-change-default-for-ci-max-artifact-size-lsif.yml b/changelogs/unreleased/id-change-default-for-ci-max-artifact-size-lsif.yml
new file mode 100644
index 00000000000..aaeb7deff00
--- /dev/null
+++ b/changelogs/unreleased/id-change-default-for-ci-max-artifact-size-lsif.yml
@@ -0,0 +1,5 @@
+---
+title: Changes limit for lsif artifacts to 100MB
+merge_request: 46980
+author:
+type: changed
diff --git a/changelogs/unreleased/id-track-git-write-operations.yml b/changelogs/unreleased/id-track-git-write-operations.yml
new file mode 100644
index 00000000000..66e863412e3
--- /dev/null
+++ b/changelogs/unreleased/id-track-git-write-operations.yml
@@ -0,0 +1,5 @@
+---
+title: Include aggregated git-write usage counts
+merge_request: 47511
+author:
+type: added
diff --git a/changelogs/unreleased/improve_performance_of_has_vulnerabilities_scope.yml b/changelogs/unreleased/improve_performance_of_has_vulnerabilities_scope.yml
new file mode 100644
index 00000000000..22fcd18d1f9
--- /dev/null
+++ b/changelogs/unreleased/improve_performance_of_has_vulnerabilities_scope.yml
@@ -0,0 +1,5 @@
+---
+title: Add `has_vulnerabilities` column into project_settings table
+merge_request: 45944
+author:
+type: added
diff --git a/changelogs/unreleased/increase-dotenv-variable-count.yml b/changelogs/unreleased/increase-dotenv-variable-count.yml
new file mode 100644
index 00000000000..7cbb24c057f
--- /dev/null
+++ b/changelogs/unreleased/increase-dotenv-variable-count.yml
@@ -0,0 +1,5 @@
+---
+title: increase allowed dotenv variables from 10 to 20
+merge_request: 45815
+author: jrreid
+type: changed
diff --git a/changelogs/unreleased/issue-277354.yml b/changelogs/unreleased/issue-277354.yml
new file mode 100644
index 00000000000..ba303be24f7
--- /dev/null
+++ b/changelogs/unreleased/issue-277354.yml
@@ -0,0 +1,5 @@
+---
+title: Fix duplicate epic iids and add uniqueness constraint
+merge_request: 47081
+author:
+type: fixed
diff --git a/changelogs/unreleased/issue_233479-add-graphql-create-todo-mutation.yml b/changelogs/unreleased/issue_233479-add-graphql-create-todo-mutation.yml
new file mode 100644
index 00000000000..a623b13d17c
--- /dev/null
+++ b/changelogs/unreleased/issue_233479-add-graphql-create-todo-mutation.yml
@@ -0,0 +1,5 @@
+---
+title: Allow to create todo on GraphQL
+merge_request: 46029
+author:
+type: added
diff --git a/changelogs/unreleased/issue_233479-add_updated_by_for_issue_type.yml b/changelogs/unreleased/issue_233479-add_updated_by_for_issue_type.yml
new file mode 100644
index 00000000000..1c77d28b4f3
--- /dev/null
+++ b/changelogs/unreleased/issue_233479-add_updated_by_for_issue_type.yml
@@ -0,0 +1,5 @@
+---
+title: Expose issue updated by on GraphQL
+merge_request: 46015
+author:
+type: added
diff --git a/changelogs/unreleased/issue_243790.yml b/changelogs/unreleased/issue_243790.yml
new file mode 100644
index 00000000000..e3be3f7eadf
--- /dev/null
+++ b/changelogs/unreleased/issue_243790.yml
@@ -0,0 +1,5 @@
+---
+title: Allow to apply group labels with service desk templates
+merge_request: 46492
+author:
+type: fixed
diff --git a/changelogs/unreleased/jdb-fix-comment-cell-inline.yml b/changelogs/unreleased/jdb-fix-comment-cell-inline.yml
new file mode 100644
index 00000000000..6fc5dafe528
--- /dev/null
+++ b/changelogs/unreleased/jdb-fix-comment-cell-inline.yml
@@ -0,0 +1,5 @@
+---
+title: Fix comment cells not rendering in unified component inline view
+merge_request: 47693
+author:
+type: fixed
diff --git a/changelogs/unreleased/jdb-fix-unified-diffs-inline.yml b/changelogs/unreleased/jdb-fix-unified-diffs-inline.yml
new file mode 100644
index 00000000000..19d60428347
--- /dev/null
+++ b/changelogs/unreleased/jdb-fix-unified-diffs-inline.yml
@@ -0,0 +1,5 @@
+---
+title: Fix unified component inline display
+merge_request: 47345
+author:
+type: fixed
diff --git a/changelogs/unreleased/jduplessis_issue_comment_link.yml b/changelogs/unreleased/jduplessis_issue_comment_link.yml
new file mode 100644
index 00000000000..2d896dfd57b
--- /dev/null
+++ b/changelogs/unreleased/jduplessis_issue_comment_link.yml
@@ -0,0 +1,5 @@
+---
+title: Add link to the note on the email sent after adding a comment on an issue
+merge_request: 45511
+author:
+type: changed
diff --git a/changelogs/unreleased/jh-235732_csv_import_gmau.yml b/changelogs/unreleased/jh-235732_csv_import_gmau.yml
new file mode 100644
index 00000000000..692649522a6
--- /dev/null
+++ b/changelogs/unreleased/jh-235732_csv_import_gmau.yml
@@ -0,0 +1,5 @@
+---
+title: Add usage ping for unique users importing issues via CSV
+merge_request: 44742
+author:
+type: changed
diff --git a/changelogs/unreleased/jh-github_search.yml b/changelogs/unreleased/jh-github_search.yml
new file mode 100644
index 00000000000..796b9b22a44
--- /dev/null
+++ b/changelogs/unreleased/jh-github_search.yml
@@ -0,0 +1,5 @@
+---
+title: Fix project import search box and make it case insensitive
+merge_request: 45783
+author:
+type: fixed
diff --git a/changelogs/unreleased/jh-migration_mvc_gmau.yml b/changelogs/unreleased/jh-migration_mvc_gmau.yml
new file mode 100644
index 00000000000..5d3e2b95749
--- /dev/null
+++ b/changelogs/unreleased/jh-migration_mvc_gmau.yml
@@ -0,0 +1,6 @@
+---
+title: Add usage ping for unique users importing groups and projects via the group
+ migration tool
+merge_request: 45536
+author:
+type: changed
diff --git a/changelogs/unreleased/jira_connect_sync_namespace_worker.yml b/changelogs/unreleased/jira_connect_sync_namespace_worker.yml
new file mode 100644
index 00000000000..ac57e060afc
--- /dev/null
+++ b/changelogs/unreleased/jira_connect_sync_namespace_worker.yml
@@ -0,0 +1,5 @@
+---
+title: Jira Connect automatically synchronizes up to 400 existing merge requests per project when a namespace is connected.
+merge_request: 43880
+author:
+type: added
diff --git a/changelogs/unreleased/jivanvl-add-pagination-specific-runners.yml b/changelogs/unreleased/jivanvl-add-pagination-specific-runners.yml
new file mode 100644
index 00000000000..4f5a60c7ff6
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-add-pagination-specific-runners.yml
@@ -0,0 +1,5 @@
+---
+title: Paginate project_runners in ci_cd settings
+merge_request: 45830
+author:
+type: fixed
diff --git a/changelogs/unreleased/jivanvl-remove-ci-variables-table-feature-flag.yml b/changelogs/unreleased/jivanvl-remove-ci-variables-table-feature-flag.yml
new file mode 100644
index 00000000000..67182bcfc1f
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-remove-ci-variables-table-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove new_variables_ui feature flag
+merge_request: 41412
+author:
+type: other
diff --git a/changelogs/unreleased/jivanvl-runner-guided-install-frontend.yml b/changelogs/unreleased/jivanvl-runner-guided-install-frontend.yml
new file mode 100644
index 00000000000..d103c4015d4
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-runner-guided-install-frontend.yml
@@ -0,0 +1,5 @@
+---
+title: Add install GitLab runner popup
+merge_request: 42877
+author:
+type: added
diff --git a/changelogs/unreleased/jivanvl-update-prometheus-metrics-icons.yml b/changelogs/unreleased/jivanvl-update-prometheus-metrics-icons.yml
new file mode 100644
index 00000000000..ffc2cfb3beb
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-update-prometheus-metrics-icons.yml
@@ -0,0 +1,5 @@
+---
+title: Replace font-awesome icons in prometheus config
+merge_request: 47713
+author:
+type: changed
diff --git a/changelogs/unreleased/job-dropdown-click.yml b/changelogs/unreleased/job-dropdown-click.yml
new file mode 100644
index 00000000000..14e44273d5e
--- /dev/null
+++ b/changelogs/unreleased/job-dropdown-click.yml
@@ -0,0 +1,5 @@
+---
+title: 'Job dropdown: Hide tooltip explicitly on click'
+merge_request: 46465
+author:
+type: fixed
diff --git a/changelogs/unreleased/jv-add-rate-limit-bypass.yml b/changelogs/unreleased/jv-add-rate-limit-bypass.yml
new file mode 100644
index 00000000000..88f9b9726b1
--- /dev/null
+++ b/changelogs/unreleased/jv-add-rate-limit-bypass.yml
@@ -0,0 +1,5 @@
+---
+title: Add rate limit bypass
+merge_request: 46259
+author:
+type: changed
diff --git a/changelogs/unreleased/kassio-bulkimport-entity-trackers.yml b/changelogs/unreleased/kassio-bulkimport-entity-trackers.yml
new file mode 100644
index 00000000000..152f9c5c5b9
--- /dev/null
+++ b/changelogs/unreleased/kassio-bulkimport-entity-trackers.yml
@@ -0,0 +1,6 @@
+---
+title: Add BulkImport::Tracker to store the pagination information of the Group Migration
+ (BulkImport) requests
+merge_request: 47009
+author:
+type: changed
diff --git a/changelogs/unreleased/kassio-fix-bitbucket-server-importer-lfs.yml b/changelogs/unreleased/kassio-fix-bitbucket-server-importer-lfs.yml
new file mode 100644
index 00000000000..3c9050120d7
--- /dev/null
+++ b/changelogs/unreleased/kassio-fix-bitbucket-server-importer-lfs.yml
@@ -0,0 +1,5 @@
+---
+title: Download LFS files when importing from Bitbucket Server
+merge_request: 45908
+author:
+type: fixed
diff --git a/changelogs/unreleased/kerrizor-increase-default-diff_max_patch_bytes.yml b/changelogs/unreleased/kerrizor-increase-default-diff_max_patch_bytes.yml
new file mode 100644
index 00000000000..0eeaf26ba1e
--- /dev/null
+++ b/changelogs/unreleased/kerrizor-increase-default-diff_max_patch_bytes.yml
@@ -0,0 +1,5 @@
+---
+title: Update diff_max_patch_bytes from 100kb -> 200kb
+merge_request: 46276
+author:
+type: changed
diff --git a/changelogs/unreleased/kp-fix-labels-dropdown-search-autofocus.yml b/changelogs/unreleased/kp-fix-labels-dropdown-search-autofocus.yml
new file mode 100644
index 00000000000..76981893244
--- /dev/null
+++ b/changelogs/unreleased/kp-fix-labels-dropdown-search-autofocus.yml
@@ -0,0 +1,5 @@
+---
+title: Autofocus on search input within labels dropdown after labels are loaded
+merge_request: 46750
+author:
+type: fixed
diff --git a/changelogs/unreleased/kubernetes_cluster_namespace_role_admin_role_ref.yml b/changelogs/unreleased/kubernetes_cluster_namespace_role_admin_role_ref.yml
new file mode 100644
index 00000000000..36091853321
--- /dev/null
+++ b/changelogs/unreleased/kubernetes_cluster_namespace_role_admin_role_ref.yml
@@ -0,0 +1,6 @@
+---
+title: Switch to admin clusterRole for GitLab created environment Kubernetes service
+ account
+merge_request: 46417
+author:
+type: changed
diff --git a/changelogs/unreleased/labkit-bump.yml b/changelogs/unreleased/labkit-bump.yml
new file mode 100644
index 00000000000..58bb22da6e8
--- /dev/null
+++ b/changelogs/unreleased/labkit-bump.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade labkit to 0.13.1
+merge_request: 45788
+author:
+type: performance
diff --git a/changelogs/unreleased/lfs-ssh-authentication.yml b/changelogs/unreleased/lfs-ssh-authentication.yml
new file mode 100644
index 00000000000..14309c4927b
--- /dev/null
+++ b/changelogs/unreleased/lfs-ssh-authentication.yml
@@ -0,0 +1,5 @@
+---
+title: Fix internal lfs_authenticate API for non-project repositories
+merge_request: 47404
+author:
+type: fixed
diff --git a/changelogs/unreleased/lm-add-ci-lint-warnings.yml b/changelogs/unreleased/lm-add-ci-lint-warnings.yml
new file mode 100644
index 00000000000..d595e3c2433
--- /dev/null
+++ b/changelogs/unreleased/lm-add-ci-lint-warnings.yml
@@ -0,0 +1,5 @@
+---
+title: Adds warnings to API response for /lint
+merge_request: 47037
+author:
+type: added
diff --git a/changelogs/unreleased/lm-upstream-downstream-pipeline.yml b/changelogs/unreleased/lm-upstream-downstream-pipeline.yml
new file mode 100644
index 00000000000..88fdeb7a198
--- /dev/null
+++ b/changelogs/unreleased/lm-upstream-downstream-pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: 'GraphQL: Adds downstream, upstream, source job, path, and project to PipelineType'
+merge_request: 45212
+author:
+type: added
diff --git a/changelogs/unreleased/mb_rails_save_bang_fix5.yml b/changelogs/unreleased/mb_rails_save_bang_fix5.yml
new file mode 100644
index 00000000000..6c5cf6f09c5
--- /dev/null
+++ b/changelogs/unreleased/mb_rails_save_bang_fix5.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for spec/services/* and spec/sidekiq/*
+merge_request: 45391
+author: matthewbried
+type: other
diff --git a/changelogs/unreleased/mc-bug-fix-k8s-docker-runner-setup.yml b/changelogs/unreleased/mc-bug-fix-k8s-docker-runner-setup.yml
new file mode 100644
index 00000000000..0cfd5f8b0de
--- /dev/null
+++ b/changelogs/unreleased/mc-bug-fix-k8s-docker-runner-setup.yml
@@ -0,0 +1,5 @@
+---
+title: Make register_instructions optional for RunnerSetup.
+merge_request: 47123
+author:
+type: fixed
diff --git a/changelogs/unreleased/mc-feature-add-ci-yaml-parmeter-to-project-lint.yml b/changelogs/unreleased/mc-feature-add-ci-yaml-parmeter-to-project-lint.yml
new file mode 100644
index 00000000000..fbf25c33c97
--- /dev/null
+++ b/changelogs/unreleased/mc-feature-add-ci-yaml-parmeter-to-project-lint.yml
@@ -0,0 +1,5 @@
+---
+title: Add POST project CI lint API endpoint.
+merge_request: 47026
+author:
+type: added
diff --git a/changelogs/unreleased/migrate-feature-flags-config-to-gitlab-ui.yml b/changelogs/unreleased/migrate-feature-flags-config-to-gitlab-ui.yml
new file mode 100644
index 00000000000..d49b24d8706
--- /dev/null
+++ b/changelogs/unreleased/migrate-feature-flags-config-to-gitlab-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate Configure Feature Flags Modal to GitLab UI
+merge_request: 46055
+author:
+type: added
diff --git a/changelogs/unreleased/migrate-terminal-alert.yml b/changelogs/unreleased/migrate-terminal-alert.yml
new file mode 100644
index 00000000000..31f8f1f2f7e
--- /dev/null
+++ b/changelogs/unreleased/migrate-terminal-alert.yml
@@ -0,0 +1,5 @@
+---
+title: Update terminal empty state alert to gl component
+merge_request: 47340
+author:
+type: other
diff --git a/changelogs/unreleased/mk-console-ruby-version.yml b/changelogs/unreleased/mk-console-ruby-version.yml
new file mode 100644
index 00000000000..39848ebffdc
--- /dev/null
+++ b/changelogs/unreleased/mk-console-ruby-version.yml
@@ -0,0 +1,5 @@
+---
+title: Print Ruby version in console greeting
+merge_request: 45370
+author:
+type: other
diff --git a/changelogs/unreleased/mk-workhorse-8-53-0.yml b/changelogs/unreleased/mk-workhorse-8-53-0.yml
new file mode 100644
index 00000000000..8b5611bb133
--- /dev/null
+++ b/changelogs/unreleased/mk-workhorse-8-53-0.yml
@@ -0,0 +1,5 @@
+---
+title: Bump workhorse to 8.53.0
+merge_request: 46666
+author:
+type: other
diff --git a/changelogs/unreleased/mo-add-default-branch-to-daily-build.yml b/changelogs/unreleased/mo-add-default-branch-to-daily-build.yml
new file mode 100644
index 00000000000..811f771b92b
--- /dev/null
+++ b/changelogs/unreleased/mo-add-default-branch-to-daily-build.yml
@@ -0,0 +1,5 @@
+---
+title: Add default_branch to ci_daily_build_group_report_result
+merge_request: 45702
+author:
+type: performance
diff --git a/changelogs/unreleased/mo-bump-codequality.yml b/changelogs/unreleased/mo-bump-codequality.yml
new file mode 100644
index 00000000000..6956b22a0e9
--- /dev/null
+++ b/changelogs/unreleased/mo-bump-codequality.yml
@@ -0,0 +1,5 @@
+---
+title: Use CodeQuality 0.85.18 in the CI template
+merge_request: 46253
+author:
+type: changed
diff --git a/changelogs/unreleased/more-coverage-badges.yml b/changelogs/unreleased/more-coverage-badges.yml
new file mode 100644
index 00000000000..1a7a212d204
--- /dev/null
+++ b/changelogs/unreleased/more-coverage-badges.yml
@@ -0,0 +1,5 @@
+---
+title: Expand scope of coverage badge query to all successful builds
+merge_request: 45321
+author:
+type: changed
diff --git a/changelogs/unreleased/move-security-jobs-finder-out-of-ee.yml b/changelogs/unreleased/move-security-jobs-finder-out-of-ee.yml
new file mode 100644
index 00000000000..e0ed0d8598e
--- /dev/null
+++ b/changelogs/unreleased/move-security-jobs-finder-out-of-ee.yml
@@ -0,0 +1,5 @@
+---
+title: Filter jobs by security report type in GraphQL
+merge_request: 47095
+author:
+type: added
diff --git a/changelogs/unreleased/move-timebox-reports-graphql.yml b/changelogs/unreleased/move-timebox-reports-graphql.yml
new file mode 100644
index 00000000000..32fb2c59894
--- /dev/null
+++ b/changelogs/unreleased/move-timebox-reports-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add GraphQL burnup endpoint under milestone and iteration reports
+merge_request: 45121
+author:
+type: added
diff --git a/changelogs/unreleased/msj-migrate-toggle-replies-widget.yml b/changelogs/unreleased/msj-migrate-toggle-replies-widget.yml
new file mode 100644
index 00000000000..2df31bb1ef6
--- /dev/null
+++ b/changelogs/unreleased/msj-migrate-toggle-replies-widget.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate toggle replies widget from Bootstrap to GlButton
+merge_request: 45780
+author:
+type: other
diff --git a/changelogs/unreleased/mvrachni-OKR-button-migration.yml b/changelogs/unreleased/mvrachni-OKR-button-migration.yml
new file mode 100644
index 00000000000..cd070c603f0
--- /dev/null
+++ b/changelogs/unreleased/mvrachni-OKR-button-migration.yml
@@ -0,0 +1,5 @@
+---
+title: Update Tooltip in Groups to use gl-tooltip
+merge_request: 45305
+author:
+type: other
diff --git a/changelogs/unreleased/mw-replace-fa-check-in-importer-status.yml b/changelogs/unreleased/mw-replace-fa-check-in-importer-status.yml
new file mode 100644
index 00000000000..4c149ee41a7
--- /dev/null
+++ b/changelogs/unreleased/mw-replace-fa-check-in-importer-status.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-check icon in importer status
+merge_request: 47373
+author:
+type: changed
diff --git a/changelogs/unreleased/mw-replace-fa-chevron-down-dropdown-button.yml b/changelogs/unreleased/mw-replace-fa-chevron-down-dropdown-button.yml
new file mode 100644
index 00000000000..f46d24e66d9
--- /dev/null
+++ b/changelogs/unreleased/mw-replace-fa-chevron-down-dropdown-button.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-chevron-down in dropdown button
+merge_request: 47758
+author:
+type: changed
diff --git a/changelogs/unreleased/mw-replace-fa-chevron-duown-in-project-level-vsa.yml b/changelogs/unreleased/mw-replace-fa-chevron-duown-in-project-level-vsa.yml
new file mode 100644
index 00000000000..9055a181995
--- /dev/null
+++ b/changelogs/unreleased/mw-replace-fa-chevron-duown-in-project-level-vsa.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-chevron-down in project level VSA
+merge_request: 47885
+author:
+type: changed
diff --git a/changelogs/unreleased/mw-replace-fa-exclamation-triangle-markdown.yml b/changelogs/unreleased/mw-replace-fa-exclamation-triangle-markdown.yml
new file mode 100644
index 00000000000..f1ba024beb7
--- /dev/null
+++ b/changelogs/unreleased/mw-replace-fa-exclamation-triangle-markdown.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-exclamation-triangle in markdown field MERGE_REQUEST_ID
+merge_request: 47786
+author:
+type: changed
diff --git a/changelogs/unreleased/mw-replace-fa-icons-custom-notifications.yml b/changelogs/unreleased/mw-replace-fa-icons-custom-notifications.yml
new file mode 100644
index 00000000000..573a72950fb
--- /dev/null
+++ b/changelogs/unreleased/mw-replace-fa-icons-custom-notifications.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-check icon in custom notifications
+merge_request: 47288
+author:
+type: changed
diff --git a/changelogs/unreleased/mw-replace-fa-icons-in-pipeline-action-button.yml b/changelogs/unreleased/mw-replace-fa-icons-in-pipeline-action-button.yml
new file mode 100644
index 00000000000..c91e0e20632
--- /dev/null
+++ b/changelogs/unreleased/mw-replace-fa-icons-in-pipeline-action-button.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-caret-down with chevron-down SVG in pipeline action buttons
+merge_request: 45881
+author:
+type: changed
diff --git a/changelogs/unreleased/mw-replace-fa-refresh-icons.yml b/changelogs/unreleased/mw-replace-fa-refresh-icons.yml
new file mode 100644
index 00000000000..3d4593cc223
--- /dev/null
+++ b/changelogs/unreleased/mw-replace-fa-refresh-icons.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-refresh icon with GitLab SVG
+merge_request: 45777
+author:
+type: changed
diff --git a/changelogs/unreleased/mw-use-sprite-icon-in-audit-icon-helper.yml b/changelogs/unreleased/mw-use-sprite-icon-in-audit-icon-helper.yml
new file mode 100644
index 00000000000..465bde06937
--- /dev/null
+++ b/changelogs/unreleased/mw-use-sprite-icon-in-audit-icon-helper.yml
@@ -0,0 +1,5 @@
+---
+title: Use GitLab SVGs in audit_icon helper
+merge_request: 45562
+author:
+type: changed
diff --git a/changelogs/unreleased/new-pipeline-form-default-true.yml b/changelogs/unreleased/new-pipeline-form-default-true.yml
new file mode 100644
index 00000000000..dd12ef458ec
--- /dev/null
+++ b/changelogs/unreleased/new-pipeline-form-default-true.yml
@@ -0,0 +1,5 @@
+---
+title: Default enable new_pipeline_form
+merge_request: 46915
+author:
+type: added
diff --git a/changelogs/unreleased/nfriend-add-graphql-release-sorting.yml b/changelogs/unreleased/nfriend-add-graphql-release-sorting.yml
new file mode 100644
index 00000000000..9da63f36e05
--- /dev/null
+++ b/changelogs/unreleased/nfriend-add-graphql-release-sorting.yml
@@ -0,0 +1,5 @@
+---
+title: Allow sorting of releases from GraphQL
+merge_request: 45577
+author:
+type: added
diff --git a/changelogs/unreleased/nfriend-add-release-create-mutation.yml b/changelogs/unreleased/nfriend-add-release-create-mutation.yml
new file mode 100644
index 00000000000..46881bbd109
--- /dev/null
+++ b/changelogs/unreleased/nfriend-add-release-create-mutation.yml
@@ -0,0 +1,5 @@
+---
+title: Add releaseCreate mutation to GraphQL endpoint
+merge_request: 46263
+author:
+type: added
diff --git a/changelogs/unreleased/nfriend-add-release-progress-link-paths.yml b/changelogs/unreleased/nfriend-add-release-progress-link-paths.yml
new file mode 100644
index 00000000000..1b7532c554a
--- /dev/null
+++ b/changelogs/unreleased/nfriend-add-release-progress-link-paths.yml
@@ -0,0 +1,6 @@
+---
+title: Add links to GraphQL release object for searching related issues and merge
+ requests
+merge_request: 46161
+author:
+type: added
diff --git a/changelogs/unreleased/nfriend-fix-milestone-array-payload.yml b/changelogs/unreleased/nfriend-fix-milestone-array-payload.yml
new file mode 100644
index 00000000000..20fff394ae5
--- /dev/null
+++ b/changelogs/unreleased/nfriend-fix-milestone-array-payload.yml
@@ -0,0 +1,5 @@
+---
+title: Fix error when updating releases with milestone associations through the UI
+merge_request: 47222
+author:
+type: fixed
diff --git a/changelogs/unreleased/nfriend-make-release_mr_issue_urls-enabled-by-default.yml b/changelogs/unreleased/nfriend-make-release_mr_issue_urls-enabled-by-default.yml
new file mode 100644
index 00000000000..820cc5a7af0
--- /dev/null
+++ b/changelogs/unreleased/nfriend-make-release_mr_issue_urls-enabled-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Enable issue and MR stat links on release progress review
+merge_request: 46910
+author:
+type: added
diff --git a/changelogs/unreleased/nfriend-move-copy-branch-shortcut.yml b/changelogs/unreleased/nfriend-move-copy-branch-shortcut.yml
new file mode 100644
index 00000000000..e486019c904
--- /dev/null
+++ b/changelogs/unreleased/nfriend-move-copy-branch-shortcut.yml
@@ -0,0 +1,5 @@
+---
+title: Update copy branch keyboard shortcut to click sidebar button
+merge_request: 45436
+author:
+type: changed
diff --git a/changelogs/unreleased/nfriend-update-tag-name-placeholder.yml b/changelogs/unreleased/nfriend-update-tag-name-placeholder.yml
new file mode 100644
index 00000000000..c2081edbecf
--- /dev/null
+++ b/changelogs/unreleased/nfriend-update-tag-name-placeholder.yml
@@ -0,0 +1,5 @@
+---
+title: Update the tag name field helper text on the Edit Release page
+merge_request: 47234
+author:
+type: changed
diff --git a/changelogs/unreleased/nicolasdular-fix-bm-close-icon.yml b/changelogs/unreleased/nicolasdular-fix-bm-close-icon.yml
new file mode 100644
index 00000000000..e36c32fbeaf
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-fix-bm-close-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Fix broadcast notification close icon appearance
+merge_request: 46804
+author:
+type: fixed
diff --git a/changelogs/unreleased/nicolasdular-new-invite-mail-design.yml b/changelogs/unreleased/nicolasdular-new-invite-mail-design.yml
new file mode 100644
index 00000000000..d4d8b4fbabd
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-new-invite-mail-design.yml
@@ -0,0 +1,5 @@
+---
+title: New group and project invite mail design
+merge_request: 44940
+author:
+type: changed
diff --git a/changelogs/unreleased/nicolasdular-remove-storage-size-limit-column.yml b/changelogs/unreleased/nicolasdular-remove-storage-size-limit-column.yml
new file mode 100644
index 00000000000..55997a4d0ed
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-remove-storage-size-limit-column.yml
@@ -0,0 +1,5 @@
+---
+title: Remove storage limit column from application settings
+merge_request: 46676
+author:
+type: removed
diff --git a/changelogs/unreleased/nicolasdular-split-signin-and-signup.yml b/changelogs/unreleased/nicolasdular-split-signin-and-signup.yml
new file mode 100644
index 00000000000..f4fdf10acad
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-split-signin-and-signup.yml
@@ -0,0 +1,5 @@
+---
+title: Split sign in and sign up pages
+merge_request: 42592
+author:
+type: changed
diff --git a/changelogs/unreleased/nmezzopera-refactor-details-fetch-2.yml b/changelogs/unreleased/nmezzopera-refactor-details-fetch-2.yml
new file mode 100644
index 00000000000..2e1324f15d5
--- /dev/null
+++ b/changelogs/unreleased/nmezzopera-refactor-details-fetch-2.yml
@@ -0,0 +1,5 @@
+---
+title: Use new image details API in container registry details
+merge_request: 47054
+author:
+type: changed
diff --git a/changelogs/unreleased/okr-components-tooltip-ide-commit-sidebar.yml b/changelogs/unreleased/okr-components-tooltip-ide-commit-sidebar.yml
new file mode 100644
index 00000000000..0eb0b404fbf
--- /dev/null
+++ b/changelogs/unreleased/okr-components-tooltip-ide-commit-sidebar.yml
@@ -0,0 +1,5 @@
+---
+title: "Migrate tooltip in app/assets/javascripts/ide/components/commit_sidebar/list.vue"
+merge_request: 46148
+author:
+type: other
diff --git a/changelogs/unreleased/okr-compontent-tooltip-awards-list.yml b/changelogs/unreleased/okr-compontent-tooltip-awards-list.yml
new file mode 100644
index 00000000000..668287f9dde
--- /dev/null
+++ b/changelogs/unreleased/okr-compontent-tooltip-awards-list.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate tooltip in app/assets/javascripts/vue_shared/components/awards_list.vue
+merge_request: 46171
+author:
+type: other
diff --git a/changelogs/unreleased/okr-tooltip-merge-button-sidebar-ide.yml b/changelogs/unreleased/okr-tooltip-merge-button-sidebar-ide.yml
new file mode 100644
index 00000000000..67146ba77e5
--- /dev/null
+++ b/changelogs/unreleased/okr-tooltip-merge-button-sidebar-ide.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate tooltip in app/assets/javascripts/vue_merge_request_widget/components/mr_file_icon.vue
+merge_request: 46156
+author: 46156
+type: other
diff --git a/changelogs/unreleased/okr-tooltip-mr-widget-author-vue.yml b/changelogs/unreleased/okr-tooltip-mr-widget-author-vue.yml
new file mode 100644
index 00000000000..f2e357986df
--- /dev/null
+++ b/changelogs/unreleased/okr-tooltip-mr-widget-author-vue.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate tooltip in app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue
+merge_request: 46034
+author:
+type: other
diff --git a/changelogs/unreleased/pb-clear-merge-ref-sha-reopen.yml b/changelogs/unreleased/pb-clear-merge-ref-sha-reopen.yml
new file mode 100644
index 00000000000..78b1e723294
--- /dev/null
+++ b/changelogs/unreleased/pb-clear-merge-ref-sha-reopen.yml
@@ -0,0 +1,5 @@
+---
+title: Clear cached merge_ref_sha on reopen
+merge_request: 47747
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-225303-fixCreateBranchButtonSpinner.yml b/changelogs/unreleased/ph-225303-fixCreateBranchButtonSpinner.yml
new file mode 100644
index 00000000000..5d906cff257
--- /dev/null
+++ b/changelogs/unreleased/ph-225303-fixCreateBranchButtonSpinner.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed create branch button not hiding when issue is closed
+merge_request: 47187
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-227159-fixMultiLineCommentsOptionsInParallelView.yml b/changelogs/unreleased/ph-227159-fixMultiLineCommentsOptionsInParallelView.yml
new file mode 100644
index 00000000000..676d72ce749
--- /dev/null
+++ b/changelogs/unreleased/ph-227159-fixMultiLineCommentsOptionsInParallelView.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed multi line comment options in parallel mode
+merge_request: 45557
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-233486-removeDraftIsNotFilter.yml b/changelogs/unreleased/ph-233486-removeDraftIsNotFilter.yml
new file mode 100644
index 00000000000..bba397eea82
--- /dev/null
+++ b/changelogs/unreleased/ph-233486-removeDraftIsNotFilter.yml
@@ -0,0 +1,5 @@
+---
+title: Removed not equal filter option for drafts on merge requests
+merge_request: 45649
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-235185-fixCreateMRDropdownReopen.yml b/changelogs/unreleased/ph-235185-fixCreateMRDropdownReopen.yml
new file mode 100644
index 00000000000..f7ff48ba8ad
--- /dev/null
+++ b/changelogs/unreleased/ph-235185-fixCreateMRDropdownReopen.yml
@@ -0,0 +1,6 @@
+---
+title: Fixed create merge request dropdown not re-opening after typing invalid source
+ branch
+merge_request: 46802
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-25973-mergeRequestSidebarLongPathTruncating.yml b/changelogs/unreleased/ph-25973-mergeRequestSidebarLongPathTruncating.yml
new file mode 100644
index 00000000000..ae42f17a5b2
--- /dev/null
+++ b/changelogs/unreleased/ph-25973-mergeRequestSidebarLongPathTruncating.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed long paths truncating in merge request sidebar incorrectly
+merge_request: 45994
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-280579-fixDiffMetadataStartupJS.yml b/changelogs/unreleased/ph-280579-fixDiffMetadataStartupJS.yml
new file mode 100644
index 00000000000..ee1faca8310
--- /dev/null
+++ b/changelogs/unreleased/ph-280579-fixDiffMetadataStartupJS.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed diff metadata endpoint being called twice
+merge_request: 47265
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-28750-removeResolveCommentButton.yml b/changelogs/unreleased/ph-28750-removeResolveCommentButton.yml
new file mode 100644
index 00000000000..04cdefeb91a
--- /dev/null
+++ b/changelogs/unreleased/ph-28750-removeResolveCommentButton.yml
@@ -0,0 +1,5 @@
+---
+title: Remove resolve comment functionality
+merge_request: 45549
+author:
+type: changed
diff --git a/changelogs/unreleased/ph-filterTargetBranchByNotEquals.yml b/changelogs/unreleased/ph-filterTargetBranchByNotEquals.yml
new file mode 100644
index 00000000000..169bf356289
--- /dev/null
+++ b/changelogs/unreleased/ph-filterTargetBranchByNotEquals.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed target branch not filtering
+merge_request: 45652
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-removeResolveNoteDefaultEnabled.yml b/changelogs/unreleased/ph-removeResolveNoteDefaultEnabled.yml
new file mode 100644
index 00000000000..56381151451
--- /dev/null
+++ b/changelogs/unreleased/ph-removeResolveNoteDefaultEnabled.yml
@@ -0,0 +1,5 @@
+---
+title: Remove the ability to resole individual notes
+merge_request: 46775
+author:
+type: removed
diff --git a/changelogs/unreleased/pks-require-git-v2-29-0.yml b/changelogs/unreleased/pks-require-git-v2-29-0.yml
new file mode 100644
index 00000000000..498cceca925
--- /dev/null
+++ b/changelogs/unreleased/pks-require-git-v2-29-0.yml
@@ -0,0 +1,5 @@
+---
+title: Require Git v2.29.0
+merge_request: 46433
+author:
+type: changed
diff --git a/changelogs/unreleased/pl-fix-operations-settings-wo-pipelines.yml b/changelogs/unreleased/pl-fix-operations-settings-wo-pipelines.yml
new file mode 100644
index 00000000000..06af146b1a0
--- /dev/null
+++ b/changelogs/unreleased/pl-fix-operations-settings-wo-pipelines.yml
@@ -0,0 +1,5 @@
+---
+title: Fix operations settings when Pipelines are disabled
+merge_request: 47062
+author:
+type: fixed
diff --git a/changelogs/unreleased/ps-fix-new-project-margin.yml b/changelogs/unreleased/ps-fix-new-project-margin.yml
new file mode 100644
index 00000000000..b495edff812
--- /dev/null
+++ b/changelogs/unreleased/ps-fix-new-project-margin.yml
@@ -0,0 +1,5 @@
+---
+title: Fix top margin in new project page
+merge_request: 47109
+author:
+type: fixed
diff --git a/changelogs/unreleased/ps-fix-repo-tree-header-button-styles.yml b/changelogs/unreleased/ps-fix-repo-tree-header-button-styles.yml
new file mode 100644
index 00000000000..222884a7960
--- /dev/null
+++ b/changelogs/unreleased/ps-fix-repo-tree-header-button-styles.yml
@@ -0,0 +1,5 @@
+---
+title: Update button styles in project tree header
+merge_request: 47562
+author:
+type: other
diff --git a/changelogs/unreleased/ps-move-haml-vue-access-tokens.yml b/changelogs/unreleased/ps-move-haml-vue-access-tokens.yml
new file mode 100644
index 00000000000..aa97182743b
--- /dev/null
+++ b/changelogs/unreleased/ps-move-haml-vue-access-tokens.yml
@@ -0,0 +1,5 @@
+---
+title: Update access token fields to new input style
+merge_request: 46569
+author:
+type: other
diff --git a/changelogs/unreleased/psi-mr-space.yml b/changelogs/unreleased/psi-mr-space.yml
new file mode 100644
index 00000000000..1be56eb7665
--- /dev/null
+++ b/changelogs/unreleased/psi-mr-space.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce whitespace on MR page header
+merge_request: 45966
+author:
+type: fixed
diff --git a/changelogs/unreleased/queue-selector-not-experimental.yml b/changelogs/unreleased/queue-selector-not-experimental.yml
new file mode 100644
index 00000000000..bf0a9dd3571
--- /dev/null
+++ b/changelogs/unreleased/queue-selector-not-experimental.yml
@@ -0,0 +1,5 @@
+---
+title: Mark Sidekiq queue selector as no longer experimental
+merge_request: 46562
+author:
+type: changed
diff --git a/changelogs/unreleased/rc-remove_sync_metrics_dashboard_ff.yml b/changelogs/unreleased/rc-remove_sync_metrics_dashboard_ff.yml
new file mode 100644
index 00000000000..d23fc9c5a3b
--- /dev/null
+++ b/changelogs/unreleased/rc-remove_sync_metrics_dashboard_ff.yml
@@ -0,0 +1,5 @@
+---
+title: Add alerting support for custom dashboards
+merge_request: 47704
+author:
+type: added
diff --git a/changelogs/unreleased/refactor-secondary_navigation_elements.yml b/changelogs/unreleased/refactor-secondary_navigation_elements.yml
new file mode 100644
index 00000000000..3fa55295d5c
--- /dev/null
+++ b/changelogs/unreleased/refactor-secondary_navigation_elements.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor secondary_navigation_elements.scss
+merge_request: 45763
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/remove-ci_always_refresh_merge_requests_from_beginning-flag.yml b/changelogs/unreleased/remove-ci_always_refresh_merge_requests_from_beginning-flag.yml
new file mode 100644
index 00000000000..54879f5fc4f
--- /dev/null
+++ b/changelogs/unreleased/remove-ci_always_refresh_merge_requests_from_beginning-flag.yml
@@ -0,0 +1,6 @@
+---
+title: Make the Merge Train process flow more resilient by always refreshing merge
+ requests from beginning
+merge_request: 46768
+author:
+type: fixed
diff --git a/changelogs/unreleased/remove-cycle-analytics-from-en.yml b/changelogs/unreleased/remove-cycle-analytics-from-en.yml
new file mode 100644
index 00000000000..a9bb98cd2a0
--- /dev/null
+++ b/changelogs/unreleased/remove-cycle-analytics-from-en.yml
@@ -0,0 +1,5 @@
+---
+title: Remove Cycle Analytics message from en i18n message
+merge_request: 45178
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/remove-graphql_lazy_authorization-ff.yml b/changelogs/unreleased/remove-graphql_lazy_authorization-ff.yml
new file mode 100644
index 00000000000..d16a8b8ced4
--- /dev/null
+++ b/changelogs/unreleased/remove-graphql_lazy_authorization-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove graphql_lazy_authorization feature flag
+merge_request: 46819
+author:
+type: added
diff --git a/changelogs/unreleased/remove-merge-base-pipelines-feature-flag.yml b/changelogs/unreleased/remove-merge-base-pipelines-feature-flag.yml
new file mode 100644
index 00000000000..1f39fe81000
--- /dev/null
+++ b/changelogs/unreleased/remove-merge-base-pipelines-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Use updated base report for CodeQuality MergeRequest widdget
+merge_request: 46384
+author:
+type: changed
diff --git a/changelogs/unreleased/remove_scanned_resources_count_from_security_scan_229773.yml b/changelogs/unreleased/remove_scanned_resources_count_from_security_scan_229773.yml
new file mode 100644
index 00000000000..47c7fff58fb
--- /dev/null
+++ b/changelogs/unreleased/remove_scanned_resources_count_from_security_scan_229773.yml
@@ -0,0 +1,5 @@
+---
+title: Remove scanned_resources_count column from security scan
+merge_request: 46108
+author:
+type: changed
diff --git a/changelogs/unreleased/replace-GLDeprecatedBadge-in-clusters-vue.yml b/changelogs/unreleased/replace-GLDeprecatedBadge-in-clusters-vue.yml
new file mode 100644
index 00000000000..02bfae2b7a9
--- /dev/null
+++ b/changelogs/unreleased/replace-GLDeprecatedBadge-in-clusters-vue.yml
@@ -0,0 +1,5 @@
+---
+title: Replaced GlDeprecated Badge in clusters.vue
+merge_request: 46165
+author:
+type: changed
diff --git a/changelogs/unreleased/replace-GlDepractedBadge-in-environment_header.yml b/changelogs/unreleased/replace-GlDepractedBadge-in-environment_header.yml
new file mode 100644
index 00000000000..6ef000bf0c2
--- /dev/null
+++ b/changelogs/unreleased/replace-GlDepractedBadge-in-environment_header.yml
@@ -0,0 +1,5 @@
+---
+title: Replaced GlDeprecatedBadge for GlBadge in environment header
+merge_request: 45768
+author:
+type: changed
diff --git a/changelogs/unreleased/replace-GlDeprecated-Badge-for-GlBadge-in-requirements-tabs.yml b/changelogs/unreleased/replace-GlDeprecated-Badge-for-GlBadge-in-requirements-tabs.yml
new file mode 100644
index 00000000000..1f4e709ac9b
--- /dev/null
+++ b/changelogs/unreleased/replace-GlDeprecated-Badge-for-GlBadge-in-requirements-tabs.yml
@@ -0,0 +1,5 @@
+---
+title: Replaced GlDeprecatedBadge for GlBadge in requirements tabs
+merge_request: 45647
+author:
+type: changed
diff --git a/changelogs/unreleased/reschedule_blocked_by.yml b/changelogs/unreleased/reschedule_blocked_by.yml
new file mode 100644
index 00000000000..a5fffbc1946
--- /dev/null
+++ b/changelogs/unreleased/reschedule_blocked_by.yml
@@ -0,0 +1,6 @@
+---
+title: Reschedule again background migration which convers 'blocked_by' issue links
+ to 'block'
+merge_request: 46770
+author:
+type: changed
diff --git a/changelogs/unreleased/restore-spacing-mr-list-for-mobile.yml b/changelogs/unreleased/restore-spacing-mr-list-for-mobile.yml
new file mode 100644
index 00000000000..69b2420fb63
--- /dev/null
+++ b/changelogs/unreleased/restore-spacing-mr-list-for-mobile.yml
@@ -0,0 +1,5 @@
+---
+title: Simplify CSS for Merge Requests (list)
+merge_request: 45785
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/revert-15df30d0.yml b/changelogs/unreleased/revert-15df30d0.yml
new file mode 100644
index 00000000000..984b11fc239
--- /dev/null
+++ b/changelogs/unreleased/revert-15df30d0.yml
@@ -0,0 +1,5 @@
+---
+title: Global Search - Left Sidebar
+merge_request: 47561
+author:
+type: added
diff --git a/changelogs/unreleased/revert-tz-defer-frequent-item-init.yml b/changelogs/unreleased/revert-tz-defer-frequent-item-init.yml
new file mode 100644
index 00000000000..b25ee863ec7
--- /dev/null
+++ b/changelogs/unreleased/revert-tz-defer-frequent-item-init.yml
@@ -0,0 +1,5 @@
+---
+title: Fix tracking of frequently visited projects / groups
+merge_request: 46348
+author:
+type: fixed
diff --git a/changelogs/unreleased/rmay-216344-2.yml b/changelogs/unreleased/rmay-216344-2.yml
new file mode 100644
index 00000000000..8def899032f
--- /dev/null
+++ b/changelogs/unreleased/rmay-216344-2.yml
@@ -0,0 +1,5 @@
+---
+title: Allow for return of scoped broadcast messages on shell
+merge_request: 46333
+author:
+type: changed
diff --git a/changelogs/unreleased/rmay-216344.yml b/changelogs/unreleased/rmay-216344.yml
new file mode 100644
index 00000000000..d69abcf35e2
--- /dev/null
+++ b/changelogs/unreleased/rmay-216344.yml
@@ -0,0 +1,5 @@
+---
+title: Don't return target-specific broadcasts without a current path supplied
+merge_request: 46322
+author:
+type: fixed
diff --git a/changelogs/unreleased/set-user-availability-be.yml b/changelogs/unreleased/set-user-availability-be.yml
new file mode 100644
index 00000000000..39b821831c6
--- /dev/null
+++ b/changelogs/unreleased/set-user-availability-be.yml
@@ -0,0 +1,5 @@
+---
+title: Add availability to user status
+merge_request: 45888
+author:
+type: added
diff --git a/changelogs/unreleased/sh-add-redis-version-to-admin-page.yml b/changelogs/unreleased/sh-add-redis-version-to-admin-page.yml
new file mode 100644
index 00000000000..233257f0e85
--- /dev/null
+++ b/changelogs/unreleased/sh-add-redis-version-to-admin-page.yml
@@ -0,0 +1,5 @@
+---
+title: Add Redis version to admin page
+merge_request: 47242
+author:
+type: added
diff --git a/changelogs/unreleased/sh-build-trace-chunk-store-thread-safety.yml b/changelogs/unreleased/sh-build-trace-chunk-store-thread-safety.yml
new file mode 100644
index 00000000000..daa86063eff
--- /dev/null
+++ b/changelogs/unreleased/sh-build-trace-chunk-store-thread-safety.yml
@@ -0,0 +1,5 @@
+---
+title: Improve thread safety of Ci::BuildTraceChunk data stores
+merge_request: 46717
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-bump-gitlab-shell-13-12.yml b/changelogs/unreleased/sh-bump-gitlab-shell-13-12.yml
new file mode 100644
index 00000000000..c393bdba59d
--- /dev/null
+++ b/changelogs/unreleased/sh-bump-gitlab-shell-13-12.yml
@@ -0,0 +1,5 @@
+---
+title: Bump gitlab-shell version to 13.12.0
+merge_request: 47084
+author:
+type: other
diff --git a/changelogs/unreleased/sh-enable-sidekiq-arg-logging-default.yml b/changelogs/unreleased/sh-enable-sidekiq-arg-logging-default.yml
new file mode 100644
index 00000000000..913e890d5ba
--- /dev/null
+++ b/changelogs/unreleased/sh-enable-sidekiq-arg-logging-default.yml
@@ -0,0 +1,5 @@
+---
+title: Enable Sidekiq argument logging by default
+merge_request: 44853
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-fix-artifacts-not-working-with-no-nginx.yml b/changelogs/unreleased/sh-fix-artifacts-not-working-with-no-nginx.yml
new file mode 100644
index 00000000000..3ebc5e7737c
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-artifacts-not-working-with-no-nginx.yml
@@ -0,0 +1,5 @@
+---
+title: Fix CI artifacts not uploading with tracing enabled and without NGINX
+merge_request: 46513
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-hashed-storage-no-destroy-namespace-dir.yml b/changelogs/unreleased/sh-hashed-storage-no-destroy-namespace-dir.yml
new file mode 100644
index 00000000000..e16785e8021
--- /dev/null
+++ b/changelogs/unreleased/sh-hashed-storage-no-destroy-namespace-dir.yml
@@ -0,0 +1,5 @@
+---
+title: Fix group destroy not working with Gitaly Cluster
+merge_request: 46934
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-lfs-replace-deleted-file.yml b/changelogs/unreleased/sh-lfs-replace-deleted-file.yml
new file mode 100644
index 00000000000..98e60cd8802
--- /dev/null
+++ b/changelogs/unreleased/sh-lfs-replace-deleted-file.yml
@@ -0,0 +1,5 @@
+---
+title: Gracefully recover from deleted LFS file
+merge_request: 45459
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-remove-legacy-fog-ff.yml b/changelogs/unreleased/sh-remove-legacy-fog-ff.yml
new file mode 100644
index 00000000000..9d8aaa321b2
--- /dev/null
+++ b/changelogs/unreleased/sh-remove-legacy-fog-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove ci_trace_new_fog_store feature flag
+merge_request: 47522
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-update-rack-2-2-3.yml b/changelogs/unreleased/sh-update-rack-2-2-3.yml
new file mode 100644
index 00000000000..e4d44b1c72f
--- /dev/null
+++ b/changelogs/unreleased/sh-update-rack-2-2-3.yml
@@ -0,0 +1,5 @@
+---
+title: Update Rack to v2.2.3
+merge_request: 45183
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-upgrade-fog-google.yml b/changelogs/unreleased/sh-upgrade-fog-google.yml
new file mode 100644
index 00000000000..1956c2b5a46
--- /dev/null
+++ b/changelogs/unreleased/sh-upgrade-fog-google.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade fog-google to v1.11.0
+merge_request: 46648
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-upgrade-ruby-2-7-2-ci.yml b/changelogs/unreleased/sh-upgrade-ruby-2-7-2-ci.yml
new file mode 100644
index 00000000000..ad9bb48dcf2
--- /dev/null
+++ b/changelogs/unreleased/sh-upgrade-ruby-2-7-2-ci.yml
@@ -0,0 +1,5 @@
+---
+title: Update to Ruby v2.7.2
+merge_request: 44223
+author:
+type: other
diff --git a/changelogs/unreleased/sh-upgrade-workhorse-8-52-0.yml b/changelogs/unreleased/sh-upgrade-workhorse-8-52-0.yml
new file mode 100644
index 00000000000..0d5081113ad
--- /dev/null
+++ b/changelogs/unreleased/sh-upgrade-workhorse-8-52-0.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade Workhorse to v8.52.0
+merge_request: 45778
+author:
+type: fixed
diff --git a/changelogs/unreleased/show_build_status_in_tag_list.yml b/changelogs/unreleased/show_build_status_in_tag_list.yml
new file mode 100644
index 00000000000..318655b046a
--- /dev/null
+++ b/changelogs/unreleased/show_build_status_in_tag_list.yml
@@ -0,0 +1,5 @@
+---
+title: Show build status in tag list
+merge_request: 34307
+author: Lee Tickett
+type: added
diff --git a/changelogs/unreleased/sk-220898-feature-flag-webhook.yml b/changelogs/unreleased/sk-220898-feature-flag-webhook.yml
new file mode 100644
index 00000000000..0146fd60e2b
--- /dev/null
+++ b/changelogs/unreleased/sk-220898-feature-flag-webhook.yml
@@ -0,0 +1,5 @@
+---
+title: Add webhooks for feature flag
+merge_request: 41863
+author: Sashi
+type: added
diff --git a/changelogs/unreleased/skip-importing-features-disabled-in-gitea.yml b/changelogs/unreleased/skip-importing-features-disabled-in-gitea.yml
new file mode 100644
index 00000000000..7444f83adae
--- /dev/null
+++ b/changelogs/unreleased/skip-importing-features-disabled-in-gitea.yml
@@ -0,0 +1,5 @@
+---
+title: Skip disabled features when importing a project from Gitea
+merge_request: 46800
+author: John Kristensen (@jerrykan)
+type: fixed
diff --git a/changelogs/unreleased/ss-add-assignee-dropdown.yml b/changelogs/unreleased/ss-add-assignee-dropdown.yml
new file mode 100644
index 00000000000..76deb9cf0fd
--- /dev/null
+++ b/changelogs/unreleased/ss-add-assignee-dropdown.yml
@@ -0,0 +1,5 @@
+---
+title: Add assignee dropdown to group issue boards
+merge_request: 44830
+author:
+type: added
diff --git a/changelogs/unreleased/ss-add-multiselect-wrapper.yml b/changelogs/unreleased/ss-add-multiselect-wrapper.yml
new file mode 100644
index 00000000000..c1dc864102d
--- /dev/null
+++ b/changelogs/unreleased/ss-add-multiselect-wrapper.yml
@@ -0,0 +1,5 @@
+---
+title: Add assignees multiselect wrapper
+merge_request: 44087
+author:
+type: added
diff --git a/changelogs/unreleased/ss-add-wip-limits-license-check.yml b/changelogs/unreleased/ss-add-wip-limits-license-check.yml
new file mode 100644
index 00000000000..47d4b414bf4
--- /dev/null
+++ b/changelogs/unreleased/ss-add-wip-limits-license-check.yml
@@ -0,0 +1,5 @@
+---
+title: Add licensed check for wip limits
+merge_request: 46387
+author:
+type: fixed
diff --git a/changelogs/unreleased/ss-assignee-dropdown-search.yml b/changelogs/unreleased/ss-assignee-dropdown-search.yml
new file mode 100644
index 00000000000..9cc9fc78c1f
--- /dev/null
+++ b/changelogs/unreleased/ss-assignee-dropdown-search.yml
@@ -0,0 +1,5 @@
+---
+title: Add search assignees to group issue boards
+merge_request: 47241
+author:
+type: added
diff --git a/changelogs/unreleased/sy-add-new-incidents-to-usage-ping.yml b/changelogs/unreleased/sy-add-new-incidents-to-usage-ping.yml
new file mode 100644
index 00000000000..7b8f1af281c
--- /dev/null
+++ b/changelogs/unreleased/sy-add-new-incidents-to-usage-ping.yml
@@ -0,0 +1,5 @@
+---
+title: Add new incident counts to usage ping
+merge_request: 46602
+author:
+type: changed
diff --git a/changelogs/unreleased/sy-ff-removal-multiple-http-endpoints.yml b/changelogs/unreleased/sy-ff-removal-multiple-http-endpoints.yml
new file mode 100644
index 00000000000..837ae024b7e
--- /dev/null
+++ b/changelogs/unreleased/sy-ff-removal-multiple-http-endpoints.yml
@@ -0,0 +1,5 @@
+---
+title: Expose GraphQL API for managing HTTP alerting intergations
+merge_request: 47687
+author:
+type: added
diff --git a/changelogs/unreleased/sy-swap-alert-email-api.yml b/changelogs/unreleased/sy-swap-alert-email-api.yml
new file mode 100644
index 00000000000..00d3c75d542
--- /dev/null
+++ b/changelogs/unreleased/sy-swap-alert-email-api.yml
@@ -0,0 +1,5 @@
+---
+title: Improve messaging for emails from alerts
+merge_request: 43054
+author:
+type: changed
diff --git a/changelogs/unreleased/tancnle-fix-jupyter-notebook-overflow.yml b/changelogs/unreleased/tancnle-fix-jupyter-notebook-overflow.yml
new file mode 100644
index 00000000000..bdb2f45a9a5
--- /dev/null
+++ b/changelogs/unreleased/tancnle-fix-jupyter-notebook-overflow.yml
@@ -0,0 +1,5 @@
+---
+title: Fix wide content overflow on Notebook output
+merge_request: 45971
+author:
+type: fixed
diff --git a/changelogs/unreleased/terraform-base-avoid-before-script.yml b/changelogs/unreleased/terraform-base-avoid-before-script.yml
new file mode 100644
index 00000000000..cd257866aab
--- /dev/null
+++ b/changelogs/unreleased/terraform-base-avoid-before-script.yml
@@ -0,0 +1,5 @@
+---
+title: Make Terraform/Base.latest.gitlab-ci.yml template safer to use in projects that have non-terraform jobs
+merge_request: 47254
+author:
+type: changed
diff --git a/changelogs/unreleased/token-revocation.yml b/changelogs/unreleased/token-revocation.yml
new file mode 100644
index 00000000000..ea3df0ade6f
--- /dev/null
+++ b/changelogs/unreleased/token-revocation.yml
@@ -0,0 +1,5 @@
+---
+title: Add a service for token revocation
+merge_request: 46356
+author:
+type: added
diff --git a/changelogs/unreleased/update-cluster-applications-0-34-1.yml b/changelogs/unreleased/update-cluster-applications-0-34-1.yml
new file mode 100644
index 00000000000..5083de747df
--- /dev/null
+++ b/changelogs/unreleased/update-cluster-applications-0-34-1.yml
@@ -0,0 +1,5 @@
+---
+title: Update cluster applications CI template to 0.34.1
+merge_request: 45487
+author:
+type: fixed
diff --git a/changelogs/unreleased/update-design-scaler-component.yml b/changelogs/unreleased/update-design-scaler-component.yml
new file mode 100644
index 00000000000..24584e510fe
--- /dev/null
+++ b/changelogs/unreleased/update-design-scaler-component.yml
@@ -0,0 +1,5 @@
+---
+title: Refresh design zooming buttons
+merge_request: 46205
+author:
+type: changed
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-22-0.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-22-0.yml
new file mode 100644
index 00000000000..0b65485c463
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-22-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Runner Helm Chart to 0.22.0
+merge_request: 45664
+author:
+type: other
diff --git a/changelogs/unreleased/update-haml_lint-to-0-36-0.yml b/changelogs/unreleased/update-haml_lint-to-0-36-0.yml
new file mode 100644
index 00000000000..74ed2b5226b
--- /dev/null
+++ b/changelogs/unreleased/update-haml_lint-to-0-36-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update haml_lint from 0.34.0 to 0.36.0
+merge_request: 44914
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/upgrade-pages-1-29-0.yml b/changelogs/unreleased/upgrade-pages-1-29-0.yml
new file mode 100644
index 00000000000..06a630f87f7
--- /dev/null
+++ b/changelogs/unreleased/upgrade-pages-1-29-0.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade GitLab Pages to 1.29.0
+merge_request: 46665
+author:
+type: added
diff --git a/changelogs/unreleased/upgrade-pages-1-30.yml b/changelogs/unreleased/upgrade-pages-1-30.yml
new file mode 100644
index 00000000000..1a349d630d6
--- /dev/null
+++ b/changelogs/unreleased/upgrade-pages-1-30.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade GitLab Pages to 1.30.0
+merge_request: 47780
+author:
+type: added
diff --git a/changelogs/unreleased/use-longer-agentk-token.yml b/changelogs/unreleased/use-longer-agentk-token.yml
new file mode 100644
index 00000000000..49da99c88fa
--- /dev/null
+++ b/changelogs/unreleased/use-longer-agentk-token.yml
@@ -0,0 +1,5 @@
+---
+title: Generate a longer Kuberntes Agent Token by default (was 20 characters, now 50)
+merge_request: 45620
+author:
+type: changed
diff --git a/changelogs/unreleased/vfazio-update-rack-oauth2.yml b/changelogs/unreleased/vfazio-update-rack-oauth2.yml
new file mode 100644
index 00000000000..1f7612b573f
--- /dev/null
+++ b/changelogs/unreleased/vfazio-update-rack-oauth2.yml
@@ -0,0 +1,5 @@
+---
+title: Update rack-oauth2 to v1.16.0
+merge_request: 47839
+author: Vincent Fazio @vfazio
+type: changed
diff --git a/changelogs/unreleased/vij-add-cloud-license-token.yml b/changelogs/unreleased/vij-add-cloud-license-token.yml
new file mode 100644
index 00000000000..6ecea1b8e0d
--- /dev/null
+++ b/changelogs/unreleased/vij-add-cloud-license-token.yml
@@ -0,0 +1,5 @@
+---
+title: Add cloud_license_auth_token column to application_settings
+merge_request: 47396
+author:
+type: added
diff --git a/changelogs/unreleased/vij-add-snippet-repo-readonly.yml b/changelogs/unreleased/vij-add-snippet-repo-readonly.yml
new file mode 100644
index 00000000000..bda2fdb09ad
--- /dev/null
+++ b/changelogs/unreleased/vij-add-snippet-repo-readonly.yml
@@ -0,0 +1,5 @@
+---
+title: Add repository_read_only column to Snippets
+merge_request: 45868
+author:
+type: added
diff --git a/changelogs/unreleased/vij-add-storage-move-table.yml b/changelogs/unreleased/vij-add-storage-move-table.yml
new file mode 100644
index 00000000000..b6af0e53535
--- /dev/null
+++ b/changelogs/unreleased/vij-add-storage-move-table.yml
@@ -0,0 +1,5 @@
+---
+title: Create snippet_repository_storage_moves database table
+merge_request: 45990
+author:
+type: added
diff --git a/changelogs/unreleased/vij-fix-inconsistent-branch-names.yml b/changelogs/unreleased/vij-fix-inconsistent-branch-names.yml
new file mode 100644
index 00000000000..b15a11d8c77
--- /dev/null
+++ b/changelogs/unreleased/vij-fix-inconsistent-branch-names.yml
@@ -0,0 +1,5 @@
+---
+title: Fix single file editor patch branch name
+merge_request: 46044
+author:
+type: fixed
diff --git a/changelogs/unreleased/vs-admin-new-user-signups.yml b/changelogs/unreleased/vs-admin-new-user-signups.yml
new file mode 100644
index 00000000000..10dacdefe7b
--- /dev/null
+++ b/changelogs/unreleased/vs-admin-new-user-signups.yml
@@ -0,0 +1,5 @@
+---
+title: Add migration to add a new configuration option for setting the new user signups count
+merge_request: 45643
+author:
+type: other
diff --git a/changelogs/unreleased/whole-number-to-integer.yml b/changelogs/unreleased/whole-number-to-integer.yml
new file mode 100644
index 00000000000..f475649ea0c
--- /dev/null
+++ b/changelogs/unreleased/whole-number-to-integer.yml
@@ -0,0 +1,5 @@
+---
+title: Rename "a whole number" to "an integer number" in feature flags strategies
+merge_request: 45444
+author:
+type: changed
diff --git a/changelogs/unreleased/wiki-delete.yml b/changelogs/unreleased/wiki-delete.yml
new file mode 100644
index 00000000000..28e1aa64313
--- /dev/null
+++ b/changelogs/unreleased/wiki-delete.yml
@@ -0,0 +1,5 @@
+---
+title: Minor UI improvements to Wiki Delete Page button and modal
+merge_request: 45740
+author:
+type: changed
diff --git a/changelogs/unreleased/wiki-toast.yml b/changelogs/unreleased/wiki-toast.yml
new file mode 100644
index 00000000000..ef84e3f6111
--- /dev/null
+++ b/changelogs/unreleased/wiki-toast.yml
@@ -0,0 +1,5 @@
+---
+title: Use toasts for wiki notifications
+merge_request: 46201
+author:
+type: changed
diff --git a/changelogs/unreleased/workaround_for_non_unique_project_fingerprints.yml b/changelogs/unreleased/workaround_for_non_unique_project_fingerprints.yml
new file mode 100644
index 00000000000..4011fdad1ff
--- /dev/null
+++ b/changelogs/unreleased/workaround_for_non_unique_project_fingerprints.yml
@@ -0,0 +1,5 @@
+---
+title: Add `position` column into security_findings table
+merge_request: 44815
+author:
+type: fixed
diff --git a/changelogs/unreleased/zip_pages_deployments_true.yml b/changelogs/unreleased/zip_pages_deployments_true.yml
new file mode 100644
index 00000000000..01c27bc35fc
--- /dev/null
+++ b/changelogs/unreleased/zip_pages_deployments_true.yml
@@ -0,0 +1,5 @@
+---
+title: Store pages content in zip format
+merge_request: 47763
+author:
+type: added
diff --git a/config/application.rb b/config/application.rb
index 75befc8a248..e8aebec086b 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -28,7 +28,7 @@ module Gitlab
require_dependency Rails.root.join('lib/gitlab/middleware/basic_health_check')
require_dependency Rails.root.join('lib/gitlab/middleware/same_site_cookies')
require_dependency Rails.root.join('lib/gitlab/middleware/handle_ip_spoof_attack_error')
- require_dependency Rails.root.join('lib/gitlab/middleware/handle_null_bytes')
+ require_dependency Rails.root.join('lib/gitlab/middleware/handle_malformed_strings')
require_dependency Rails.root.join('lib/gitlab/runtime')
# Settings in config/environments/* take precedence over those specified here.
@@ -174,13 +174,17 @@ module Gitlab
config.assets.precompile << "notify.css"
config.assets.precompile << "mailers/*.css"
config.assets.precompile << "page_bundles/_mixins_and_variables_and_functions.css"
+ config.assets.precompile << "page_bundles/alert_management_details.css"
config.assets.precompile << "page_bundles/boards.css"
+ config.assets.precompile << "page_bundles/build.css"
+ config.assets.precompile << "page_bundles/ci_status.css"
config.assets.precompile << "page_bundles/cycle_analytics.css"
config.assets.precompile << "page_bundles/dev_ops_report.css"
config.assets.precompile << "page_bundles/environments.css"
+ config.assets.precompile << "page_bundles/epics.css"
config.assets.precompile << "page_bundles/error_tracking_details.css"
config.assets.precompile << "page_bundles/error_tracking_index.css"
- config.assets.precompile << "page_bundles/experimental_separate_sign_up.css"
+ config.assets.precompile << "page_bundles/signup.css"
config.assets.precompile << "page_bundles/ide.css"
config.assets.precompile << "page_bundles/issues_list.css"
config.assets.precompile << "page_bundles/jira_connect.css"
@@ -190,15 +194,18 @@ module Gitlab
config.assets.precompile << "page_bundles/milestone.css"
config.assets.precompile << "page_bundles/pipeline.css"
config.assets.precompile << "page_bundles/pipelines.css"
+ config.assets.precompile << "page_bundles/pipeline_schedules.css"
config.assets.precompile << "page_bundles/productivity_analytics.css"
config.assets.precompile << "page_bundles/terminal.css"
config.assets.precompile << "page_bundles/todos.css"
config.assets.precompile << "page_bundles/reports.css"
- config.assets.precompile << "page_bundles/xterm.css"
+ config.assets.precompile << "page_bundles/roadmap.css"
config.assets.precompile << "page_bundles/wiki.css"
+ config.assets.precompile << "page_bundles/xterm.css"
+ config.assets.precompile << "page_bundles/alert_management_settings.css"
config.assets.precompile << "lazy_bundles/cropper.css"
+ config.assets.precompile << "lazy_bundles/select2.css"
config.assets.precompile << "performance_bar.css"
- config.assets.precompile << "lib/ace.js"
config.assets.precompile << "disable_animations.css"
config.assets.precompile << "snippets.css"
config.assets.precompile << "locale/**/app.js"
@@ -254,7 +261,7 @@ module Gitlab
config.middleware.insert_before ActionDispatch::RemoteIp, ::Gitlab::Middleware::HandleIpSpoofAttackError
- config.middleware.use ::Gitlab::Middleware::HandleNullBytes
+ config.middleware.insert_after ActionDispatch::ActionableExceptions, ::Gitlab::Middleware::HandleMalformedStrings
# Allow access to GitLab API from other domains
config.middleware.insert_before Warden::Manager, Rack::Cors do
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 9d4fc6ba5e9..31a3af77ba1 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -4,7 +4,7 @@ Rails.application.configure do
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
- config.cache_classes = false
+ config.cache_classes = Gitlab::Utils.to_boolean(ENV['CACHE_CLASSES'], default: false)
# Show full error reports and disable caching
config.active_record.verbose_query_logs = true
diff --git a/config/environments/test.rb b/config/environments/test.rb
index f3a7f894b73..4e359cd308c 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -17,9 +17,7 @@ Rails.application.configure do
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
-
- # Code doesn't change in CI so we don't need code-reloading
- config.cache_classes = !!ENV['CI']
+ config.cache_classes = Gitlab::Utils.to_boolean(ENV['CACHE_CLASSES'], default: false)
# Configure static asset server for tests with Cache-Control for performance
config.assets.compile = false if ENV['CI']
diff --git a/config/feature_categories.yml b/config/feature_categories.yml
index edf7bba27a3..fb261377532 100644
--- a/config/feature_categories.yml
+++ b/config/feature_categories.yml
@@ -18,7 +18,6 @@
- authentication_and_authorization
- auto_devops
- backup_restore
-- behavior_analytics
- boards
- chatops
- cloud_native_installation
@@ -56,7 +55,6 @@
- gitaly
- gitlab_docs
- gitlab_handbook
-- gitter
- global_search
- helm_chart_registry
- importers
@@ -101,6 +99,8 @@
- secret_detection
- secrets_management
- security_benchmarking
+- security_orchestration
+- self_monitoring
- serverless
- service_desk
- snippets
@@ -108,12 +108,13 @@
- static_application_security_testing
- static_site_editor
- subgroups
+- synthetic_monitoring
- templates
- time_tracking
- tracing
- usability_testing
- users
-- value_stream_management
+- value_stream_analytics
- vulnerability_database
- vulnerability_management
- web_firewall
diff --git a/config/feature_flags/development/additional_snowplow_tracking.yml b/config/feature_flags/development/additional_snowplow_tracking.yml
index 3e2b542b1a8..c5726975b37 100644
--- a/config/feature_flags/development/additional_snowplow_tracking.yml
+++ b/config/feature_flags/development/additional_snowplow_tracking.yml
@@ -1,6 +1,8 @@
+---
name: additional_snowplow_tracking
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/12088
-rollout_issue_url:
-group: group::product analytics
+rollout_issue_url:
+milestone: '11.11'
type: development
+group: group::product analytics
default_enabled: false
diff --git a/config/feature_flags/development/admin_approval_for_new_user_signups.yml b/config/feature_flags/development/admin_approval_for_new_user_signups.yml
deleted file mode 100644
index 0cde210e6a0..00000000000
--- a/config/feature_flags/development/admin_approval_for_new_user_signups.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: admin_approval_for_new_user_signups
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43827
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258980
-type: development
-group: group::access
-default_enabled: true
diff --git a/config/feature_flags/development/ajax_new_deploy_token.yml b/config/feature_flags/development/ajax_new_deploy_token.yml
index 336e3004d52..9a6826e6993 100644
--- a/config/feature_flags/development/ajax_new_deploy_token.yml
+++ b/config/feature_flags/development/ajax_new_deploy_token.yml
@@ -2,6 +2,7 @@
name: ajax_new_deploy_token
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27141
rollout_issue_url:
-group: group::progressive delivery
+milestone: '12.10'
type: development
+group: group::progressive delivery
default_enabled: false
diff --git a/config/feature_flags/development/allow_group_deploy_token.yml b/config/feature_flags/development/allow_group_deploy_token.yml
index 06a8659292d..91437352ad8 100644
--- a/config/feature_flags/development/allow_group_deploy_token.yml
+++ b/config/feature_flags/development/allow_group_deploy_token.yml
@@ -2,6 +2,7 @@
name: allow_group_deploy_token
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23460
rollout_issue_url:
-group: group::progressive delivery
+milestone: '12.8'
type: development
+group: group::progressive delivery
default_enabled: true
diff --git a/config/feature_flags/development/allow_possible_spam.yml b/config/feature_flags/development/allow_possible_spam.yml
index 2e121519628..696ab3ba214 100644
--- a/config/feature_flags/development/allow_possible_spam.yml
+++ b/config/feature_flags/development/allow_possible_spam.yml
@@ -2,6 +2,7 @@
name: allow_possible_spam
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17604
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/29830
-group: group::portfolio management
+milestone: '12.4'
type: development
+group: group::portfolio management
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
index 272e9f5ffa2..39ffa51cf9c 100644
--- a/config/feature_flags/development/allow_unsafe_ruby_regexp.yml
+++ b/config/feature_flags/development/allow_unsafe_ruby_regexp.yml
@@ -1,7 +1,8 @@
---
name: allow_unsafe_ruby_regexp
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10566
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257849
+milestone: '11.10'
type: development
group: group::continuous integration
default_enabled: false
diff --git a/config/feature_flags/development/api_json_content_type.yml b/config/feature_flags/development/api_json_content_type.yml
new file mode 100644
index 00000000000..5653a834e62
--- /dev/null
+++ b/config/feature_flags/development/api_json_content_type.yml
@@ -0,0 +1,8 @@
+---
+name: api_json_content_type
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42229
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/270067
+milestone: '13.6'
+type: development
+group: group::ecosystem
+default_enabled: false
diff --git a/config/feature_flags/development/application_settings_tokens_optional_encryption.yml b/config/feature_flags/development/application_settings_tokens_optional_encryption.yml
index b9a5b6420d1..08814f31159 100644
--- a/config/feature_flags/development/application_settings_tokens_optional_encryption.yml
+++ b/config/feature_flags/development/application_settings_tokens_optional_encryption.yml
@@ -2,6 +2,7 @@
name: application_settings_tokens_optional_encryption
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/approval_suggestions.yml b/config/feature_flags/development/approval_suggestions.yml
index ff66e9fa80c..14961d2e248 100644
--- a/config/feature_flags/development/approval_suggestions.yml
+++ b/config/feature_flags/development/approval_suggestions.yml
@@ -1,7 +1,8 @@
---
name: approval_suggestions
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38992
rollout_issue_url:
-group:
+milestone: '13.3'
type: development
+group: group::composition analysis
default_enabled: true
diff --git a/config/feature_flags/development/approvals_commented_by.yml b/config/feature_flags/development/approvals_commented_by.yml
index cc34b1d165e..55619b0e2db 100644
--- a/config/feature_flags/development/approvals_commented_by.yml
+++ b/config/feature_flags/development/approvals_commented_by.yml
@@ -1,7 +1,8 @@
---
name: approvals_commented_by
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38136
rollout_issue_url:
-group:
+milestone: '13.3'
type: development
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/archive_rate_limit.yml b/config/feature_flags/development/archive_rate_limit.yml
index 56e9fcd3f8d..ee4af4d2835 100644
--- a/config/feature_flags/development/archive_rate_limit.yml
+++ b/config/feature_flags/development/archive_rate_limit.yml
@@ -2,6 +2,7 @@
name: archive_rate_limit
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/artifacts_management_page.yml b/config/feature_flags/development/artifacts_management_page.yml
index 78659422a39..f2c7f54d8d8 100644
--- a/config/feature_flags/development/artifacts_management_page.yml
+++ b/config/feature_flags/development/artifacts_management_page.yml
@@ -2,6 +2,7 @@
name: artifacts_management_page
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16654
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/254938
-group: group::continuous integration
+milestone: '12.4'
type: development
+group: group::continuous integration
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
index 90aed05e12a..a4519835fa1 100644
--- a/config/feature_flags/development/async_commit_diff_files.yml
+++ b/config/feature_flags/development/async_commit_diff_files.yml
@@ -1,7 +1,8 @@
---
name: async_commit_diff_files
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38450
rollout_issue_url:
-group:
+milestone: '13.3'
type: development
+group: group::source code
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
index d3b88f056ec..ea7bf349e1e 100644
--- a/config/feature_flags/development/auto_create_cluster_management_project.yml
+++ b/config/feature_flags/development/auto_create_cluster_management_project.yml
@@ -2,6 +2,7 @@
name: auto_create_cluster_management_project
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23946
rollout_issue_url:
-group: group::configure
+milestone: '12.10'
type: development
+group: group::configure
default_enabled: false
diff --git a/config/feature_flags/development/auto_devops_banner_disabled.yml b/config/feature_flags/development/auto_devops_banner_disabled.yml
index b74d3c723ee..cb9566c3de3 100644
--- a/config/feature_flags/development/auto_devops_banner_disabled.yml
+++ b/config/feature_flags/development/auto_devops_banner_disabled.yml
@@ -1,7 +1,8 @@
---
name: auto_devops_banner_disabled
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14218
rollout_issue_url:
-group:
+milestone: '10.0'
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/batch_suggestions.yml b/config/feature_flags/development/batch_suggestions.yml
index 0ef3c7df01e..f2bb0a8f9cb 100644
--- a/config/feature_flags/development/batch_suggestions.yml
+++ b/config/feature_flags/development/batch_suggestions.yml
@@ -2,6 +2,7 @@
name: batch_suggestions
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
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
index 3875cce4d28..c672eb1e64e 100644
--- a/config/feature_flags/development/bitbucket_server_user_mapping_by_username.yml
+++ b/config/feature_flags/development/bitbucket_server_user_mapping_by_username.yml
@@ -1,7 +1,8 @@
---
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
+rollout_issue_url:
+milestone: '13.4'
type: development
+group: group::import
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
index 527e99ad8a8..ee72f1ac60a 100644
--- a/config/feature_flags/development/block_anonymous_global_searches.yml
+++ b/config/feature_flags/development/block_anonymous_global_searches.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
-default_enabled: false \ No newline at end of file
+group: group::global search
+default_enabled: false
diff --git a/config/feature_flags/development/boards_with_swimlanes.yml b/config/feature_flags/development/boards_with_swimlanes.yml
index 19e5ab24206..7080bceb777 100644
--- a/config/feature_flags/development/boards_with_swimlanes.yml
+++ b/config/feature_flags/development/boards_with_swimlanes.yml
@@ -1,7 +1,8 @@
---
name: boards_with_swimlanes
-introduced_by_url:
-rollout_issue_url:
-group: group::project management
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/218040
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/238222
+milestone: 13.6
+group: group::product planning
type: development
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/branch_list_keyset_pagination.yml b/config/feature_flags/development/branch_list_keyset_pagination.yml
index 11975c67561..5397282aecc 100644
--- a/config/feature_flags/development/branch_list_keyset_pagination.yml
+++ b/config/feature_flags/development/branch_list_keyset_pagination.yml
@@ -1,7 +1,8 @@
---
name: branch_list_keyset_pagination
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35819
rollout_issue_url:
-group:
+milestone: '13.2'
type: development
+group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/broadcast_issue_updates.yml b/config/feature_flags/development/broadcast_issue_updates.yml
index 435678f869d..b7c6ccf2353 100644
--- a/config/feature_flags/development/broadcast_issue_updates.yml
+++ b/config/feature_flags/development/broadcast_issue_updates.yml
@@ -2,6 +2,7 @@
name: broadcast_issue_updates
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30732
rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/1210
-group: group::project management
+milestone: '13.0'
type: development
+group: group::project management
default_enabled: false
diff --git a/config/feature_flags/development/build_service_proxy.yml b/config/feature_flags/development/build_service_proxy.yml
index 0c0aaa8aca9..8032a39e959 100644
--- a/config/feature_flags/development/build_service_proxy.yml
+++ b/config/feature_flags/development/build_service_proxy.yml
@@ -1,7 +1,8 @@
---
name: build_service_proxy
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9723
-rollout_issue_url:
-group: group::editor
+rollout_issue_url:
+milestone: '11.11'
type: development
+group: group::editor
default_enabled: false
diff --git a/config/feature_flags/development/builds.yml b/config/feature_flags/development/builds.yml
index 6c17f2eb962..9787c2b1e20 100644
--- a/config/feature_flags/development/builds.yml
+++ b/config/feature_flags/development/builds.yml
@@ -2,6 +2,7 @@
name: builds
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/bulk_import.yml b/config/feature_flags/development/bulk_import.yml
index 0a5a1e5654e..10885093adf 100644
--- a/config/feature_flags/development/bulk_import.yml
+++ b/config/feature_flags/development/bulk_import.yml
@@ -2,6 +2,7 @@
name: bulk_import
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42704
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/255310
-group: group::import
+milestone: '13.5'
type: development
+group: group::import
default_enabled: false
diff --git a/config/feature_flags/development/bulk_update_health_status.yml b/config/feature_flags/development/bulk_update_health_status.yml
index fa06adfd60a..29841ba584c 100644
--- a/config/feature_flags/development/bulk_update_health_status.yml
+++ b/config/feature_flags/development/bulk_update_health_status.yml
@@ -1,7 +1,8 @@
---
name: bulk_update_health_status
-introduced_by_url:
-rollout_issue_url:
-group: group::portfolio management
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33065
+rollout_issue_url:
+milestone: '13.2'
type: development
+group: group::portfolio management
default_enabled: true
diff --git a/config/feature_flags/development/burnup_charts.yml b/config/feature_flags/development/burnup_charts.yml
index 5ead8362d90..3fcc0b33b3f 100644
--- a/config/feature_flags/development/burnup_charts.yml
+++ b/config/feature_flags/development/burnup_charts.yml
@@ -1,7 +1,8 @@
---
name: burnup_charts
-introduced_by_url:
-rollout_issue_url:
-group: group::project management
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268350
+milestone: '13.6'
type: development
-default_enabled: false
+group: group::project management
+default_enabled: true
diff --git a/config/feature_flags/development/cached_markdown_blob.yml b/config/feature_flags/development/cached_markdown_blob.yml
index de7a7c52b66..fcca7f89537 100644
--- a/config/feature_flags/development/cached_markdown_blob.yml
+++ b/config/feature_flags/development/cached_markdown_blob.yml
@@ -2,6 +2,7 @@
name: cached_markdown_blob
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44300
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/263406
+milestone: '13.5'
type: development
group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/canary_ingress_weight_control.yml b/config/feature_flags/development/canary_ingress_weight_control.yml
index 681ffc98cb5..b2b5a3e5dfa 100644
--- a/config/feature_flags/development/canary_ingress_weight_control.yml
+++ b/config/feature_flags/development/canary_ingress_weight_control.yml
@@ -2,6 +2,7 @@
name: canary_ingress_weight_control
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43816
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/260295
+milestone: '13.5'
type: development
group: group::progressive delivery
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/cd_auto_rollback.yml b/config/feature_flags/development/cd_auto_rollback.yml
new file mode 100644
index 00000000000..0878fac7d26
--- /dev/null
+++ b/config/feature_flags/development/cd_auto_rollback.yml
@@ -0,0 +1,8 @@
+---
+name: cd_auto_rollback
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45816
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/35404
+milestone: '13.6'
+type: development
+group: group::progressive delivery
+default_enabled: false
diff --git a/config/feature_flags/development/chatops.yml b/config/feature_flags/development/chatops.yml
index c548af50aa5..2ce01c26cb8 100644
--- a/config/feature_flags/development/chatops.yml
+++ b/config/feature_flags/development/chatops.yml
@@ -2,6 +2,7 @@
name: chatops
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/ci_always_refresh_merge_requests_from_beginning.yml b/config/feature_flags/development/ci_always_refresh_merge_requests_from_beginning.yml
deleted file mode 100644
index 9e5cae4e4a0..00000000000
--- a/config/feature_flags/development/ci_always_refresh_merge_requests_from_beginning.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: ci_always_refresh_merge_requests_from_beginning
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45232
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268215
-type: development
-group: group::continuous integration
-default_enabled: false
diff --git a/config/feature_flags/development/ci_artifacts_exclude.yml b/config/feature_flags/development/ci_artifacts_exclude.yml
index 86398f085d8..f1a7031b4e9 100644
--- a/config/feature_flags/development/ci_artifacts_exclude.yml
+++ b/config/feature_flags/development/ci_artifacts_exclude.yml
@@ -1,7 +1,8 @@
---
name: ci_artifacts_exclude
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30708
-rollout_issue_url:
-group: group::continuous integration
+rollout_issue_url:
+milestone: '13.0'
type: development
+group: group::continuous integration
default_enabled: true
diff --git a/config/feature_flags/development/ci_auto_cancel_all_pipelines.yml b/config/feature_flags/development/ci_auto_cancel_all_pipelines.yml
new file mode 100644
index 00000000000..e20baf93500
--- /dev/null
+++ b/config/feature_flags/development/ci_auto_cancel_all_pipelines.yml
@@ -0,0 +1,8 @@
+---
+name: ci_auto_cancel_all_pipelines
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46686
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/275997
+milestone: '13.6'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/ci_bridge_dependency_variables.yml b/config/feature_flags/development/ci_bridge_dependency_variables.yml
new file mode 100644
index 00000000000..db23a30d2cb
--- /dev/null
+++ b/config/feature_flags/development/ci_bridge_dependency_variables.yml
@@ -0,0 +1,7 @@
+---
+name: ci_bridge_dependency_variables
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46530
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/273734
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/ci_build_metadata_config.yml b/config/feature_flags/development/ci_build_metadata_config.yml
index 176abbfd387..07803e3f1da 100644
--- a/config/feature_flags/development/ci_build_metadata_config.yml
+++ b/config/feature_flags/development/ci_build_metadata_config.yml
@@ -1,7 +1,8 @@
---
name: ci_build_metadata_config
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7238
-rollout_issue_url:
-group: group::continuous integration
+rollout_issue_url:
+milestone: '11.7'
type: development
+group: group::continuous integration
default_enabled: false
diff --git a/config/feature_flags/development/ci_delete_objects_high_concurrency.yml b/config/feature_flags/development/ci_delete_objects_high_concurrency.yml
index c2b391f8b8f..bcc58b2c985 100644
--- a/config/feature_flags/development/ci_delete_objects_high_concurrency.yml
+++ b/config/feature_flags/development/ci_delete_objects_high_concurrency.yml
@@ -2,6 +2,7 @@
name: ci_delete_objects_high_concurrency
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39464
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247103
-group: group::continuous integration
+milestone: '13.5'
type: development
-default_enabled: false \ No newline at end of file
+group: group::continuous integration
+default_enabled: false
diff --git a/config/feature_flags/development/ci_delete_objects_low_concurrency.yml b/config/feature_flags/development/ci_delete_objects_low_concurrency.yml
deleted file mode 100644
index cc59e0e3f6f..00000000000
--- a/config/feature_flags/development/ci_delete_objects_low_concurrency.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: ci_delete_objects_low_concurrency
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39464
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247103
-group: group::continuous integration
-type: development
-default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/ci_delete_objects_medium_concurrency.yml b/config/feature_flags/development/ci_delete_objects_medium_concurrency.yml
index 4b72980945c..911462e88ae 100644
--- a/config/feature_flags/development/ci_delete_objects_medium_concurrency.yml
+++ b/config/feature_flags/development/ci_delete_objects_medium_concurrency.yml
@@ -2,6 +2,7 @@
name: ci_delete_objects_medium_concurrency
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39464
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247103
-group: group::continuous integration
+milestone: '13.5'
type: development
-default_enabled: false \ No newline at end of file
+group: group::continuous integration
+default_enabled: false
diff --git a/config/feature_flags/development/ci_disable_validates_dependencies.yml b/config/feature_flags/development/ci_disable_validates_dependencies.yml
index ccd529d0a09..fd5b3d41eef 100644
--- a/config/feature_flags/development/ci_disable_validates_dependencies.yml
+++ b/config/feature_flags/development/ci_disable_validates_dependencies.yml
@@ -2,6 +2,7 @@
name: ci_disable_validates_dependencies
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14009
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257847
-group: group::continuous integration
+milestone: '10.3'
type: development
+group: group::continuous integration
default_enabled: false
diff --git a/config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml b/config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml
index 81a0d014b12..4b134457a20 100644
--- a/config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml
+++ b/config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
+group: group::progressive delivery
default_enabled: false
diff --git a/config/feature_flags/development/ci_dynamic_child_pipeline.yml b/config/feature_flags/development/ci_dynamic_child_pipeline.yml
index c568e9392b2..c9d5212267e 100644
--- a/config/feature_flags/development/ci_dynamic_child_pipeline.yml
+++ b/config/feature_flags/development/ci_dynamic_child_pipeline.yml
@@ -1,7 +1,8 @@
---
name: ci_dynamic_child_pipeline
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23790
-rollout_issue_url:
-group: group::continuous integration
+rollout_issue_url:
+milestone: '12.9'
type: development
+group: group::continuous integration
default_enabled: true
diff --git a/config/feature_flags/development/ci_enable_live_trace.yml b/config/feature_flags/development/ci_enable_live_trace.yml
index 7ae59946330..d56107e43eb 100644
--- a/config/feature_flags/development/ci_enable_live_trace.yml
+++ b/config/feature_flags/development/ci_enable_live_trace.yml
@@ -1,7 +1,8 @@
---
name: ci_enable_live_trace
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5255
-rollout_issue_url:
-group: group::continuous integration
+rollout_issue_url:
+milestone: '10.8'
type: development
+group: group::continuous integration
default_enabled: false
diff --git a/config/feature_flags/development/ci_include_multiple_files_from_project.yml b/config/feature_flags/development/ci_include_multiple_files_from_project.yml
new file mode 100644
index 00000000000..a291287bd4f
--- /dev/null
+++ b/config/feature_flags/development/ci_include_multiple_files_from_project.yml
@@ -0,0 +1,8 @@
+---
+name: ci_include_multiple_files_from_project
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45991
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/271560
+milestone: '13.6'
+type: development
+group: group::pipeline authoring
+default_enabled: true
diff --git a/config/feature_flags/development/ci_instance_variables_ui.yml b/config/feature_flags/development/ci_instance_variables_ui.yml
index 481e0150600..f5cd2d21bd1 100644
--- a/config/feature_flags/development/ci_instance_variables_ui.yml
+++ b/config/feature_flags/development/ci_instance_variables_ui.yml
@@ -1,7 +1,8 @@
---
name: ci_instance_variables_ui
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33510
-rollout_issue_url:
-group: group::continuous integration
+rollout_issue_url:
+milestone: '13.1'
type: development
+group: group::continuous integration
default_enabled: true
diff --git a/config/feature_flags/development/ci_job_jwt.yml b/config/feature_flags/development/ci_job_jwt.yml
index b0ad0790ebc..cba278c9103 100644
--- a/config/feature_flags/development/ci_job_jwt.yml
+++ b/config/feature_flags/development/ci_job_jwt.yml
@@ -1,7 +1,8 @@
---
name: ci_job_jwt
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/207125
-rollout_issue_url:
-group: group::release management
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28063
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/207125
+milestone: '12.10'
type: development
+group: group::release management
default_enabled: true
diff --git a/config/feature_flags/development/ci_job_line_links.yml b/config/feature_flags/development/ci_job_line_links.yml
new file mode 100644
index 00000000000..458c0afb6d2
--- /dev/null
+++ b/config/feature_flags/development/ci_job_line_links.yml
@@ -0,0 +1,8 @@
+---
+name: ci_job_line_links
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47532
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/281727
+milestone: '13.6'
+type: development
+group: group::continuous integration
+default_enabled: false
diff --git a/config/feature_flags/development/ci_jobs_finder_refactor.yml b/config/feature_flags/development/ci_jobs_finder_refactor.yml
deleted file mode 100644
index f43db747e0a..00000000000
--- a/config/feature_flags/development/ci_jobs_finder_refactor.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-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: true
diff --git a/config/feature_flags/development/ci_jwt_signing_key.yml b/config/feature_flags/development/ci_jwt_signing_key.yml
new file mode 100644
index 00000000000..4f37b49d797
--- /dev/null
+++ b/config/feature_flags/development/ci_jwt_signing_key.yml
@@ -0,0 +1,8 @@
+---
+name: ci_jwt_signing_key
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34249
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258546
+milestone: '13.6'
+type: development
+group: group::release management
+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
deleted file mode 100644
index 5f23d038998..00000000000
--- a/config/feature_flags/development/ci_lint_creates_pipeline_with_dry_run.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: ci_lint_creates_pipeline_with_dry_run
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37828
-rollout_issue_url:
-group: group::continuous integration
-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
deleted file mode 100644
index a72e97909be..00000000000
--- a/config/feature_flags/development/ci_lint_vue.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-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 integration
-type: development
-default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/ci_manual_bridges.yml b/config/feature_flags/development/ci_manual_bridges.yml
index fa3f323722d..6bda63e71ae 100644
--- a/config/feature_flags/development/ci_manual_bridges.yml
+++ b/config/feature_flags/development/ci_manual_bridges.yml
@@ -2,6 +2,7 @@
name: ci_manual_bridges
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44011
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/263412
+milestone: '13.5'
type: development
group: group::pipeline authoring
default_enabled: true
diff --git a/config/feature_flags/development/ci_pipeline_editor_page.yml b/config/feature_flags/development/ci_pipeline_editor_page.yml
new file mode 100644
index 00000000000..9870f419842
--- /dev/null
+++ b/config/feature_flags/development/ci_pipeline_editor_page.yml
@@ -0,0 +1,8 @@
+---
+name: ci_pipeline_editor_page
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46580
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/270059
+milestone: '13.6'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/ci_pipeline_latest.yml b/config/feature_flags/development/ci_pipeline_latest.yml
index 87b064043a3..6857c80565e 100644
--- a/config/feature_flags/development/ci_pipeline_latest.yml
+++ b/config/feature_flags/development/ci_pipeline_latest.yml
@@ -1,7 +1,8 @@
---
name: ci_pipeline_latest
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34160
-rollout_issue_url:
-group: group::continuous integration
+rollout_issue_url:
+milestone: '13.2'
type: development
+group: group::continuous integration
default_enabled: true
diff --git a/config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml b/config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml
index 911eab84b28..82a28884f75 100644
--- a/config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml
+++ b/config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml
@@ -2,6 +2,7 @@
name: ci_pipeline_status_omit_commit_sha_in_cache_key
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33712
rollout_issue_url:
-group: group::continuous integration
+milestone: '13.2'
type: development
+group: group::continuous integration
default_enabled: true
diff --git a/config/feature_flags/development/ci_pipeline_triggers_settings_vue_ui.yml b/config/feature_flags/development/ci_pipeline_triggers_settings_vue_ui.yml
index 0a5c214308a..31840bb494e 100644
--- a/config/feature_flags/development/ci_pipeline_triggers_settings_vue_ui.yml
+++ b/config/feature_flags/development/ci_pipeline_triggers_settings_vue_ui.yml
@@ -2,6 +2,7 @@
name: ci_pipeline_triggers_settings_vue_ui
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41864
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247486
-group: group::continuous integration
+milestone: '13.5'
type: development
+group: group::continuous integration
default_enabled: false
diff --git a/config/feature_flags/development/ci_raise_job_rules_without_workflow_rules_warning.yml b/config/feature_flags/development/ci_raise_job_rules_without_workflow_rules_warning.yml
index c2cd1d62734..e0919dff0e0 100644
--- 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
@@ -1,7 +1,8 @@
---
name: ci_raise_job_rules_without_workflow_rules_warning
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38387
-rollout_issue_url:
-group: group::continuous integration
+rollout_issue_url:
+milestone: '13.3'
type: development
+group: group::continuous integration
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
index 52aed3378ff..d67bd6c591c 100644
--- a/config/feature_flags/development/ci_runners_tokens_optional_encryption.yml
+++ b/config/feature_flags/development/ci_runners_tokens_optional_encryption.yml
@@ -1,7 +1,8 @@
---
name: ci_runners_tokens_optional_encryption
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/cbba8fe02b0ea3adabcfe18685c9af6be3859e2d
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8638
rollout_issue_url:
-group: group::continuous integration
+milestone: '11.6'
type: development
+group: group::continuous integration
default_enabled: true
diff --git a/config/feature_flags/development/ci_seed_block_run_before_workflow_rules.yml b/config/feature_flags/development/ci_seed_block_run_before_workflow_rules.yml
new file mode 100644
index 00000000000..6e030c3685a
--- /dev/null
+++ b/config/feature_flags/development/ci_seed_block_run_before_workflow_rules.yml
@@ -0,0 +1,8 @@
+---
+name: ci_seed_block_run_before_workflow_rules
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45674
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/270439
+milestone: '13.6'
+type: development
+group: group::pipeline authoring
+default_enabled: true
diff --git a/config/feature_flags/development/ci_send_deployment_hook_when_start.yml b/config/feature_flags/development/ci_send_deployment_hook_when_start.yml
deleted file mode 100644
index 41f8e719b63..00000000000
--- a/config/feature_flags/development/ci_send_deployment_hook_when_start.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: ci_send_deployment_hook_when_start
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41214
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247137
-group: group::progressive delivery
-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
index 60c626295ab..9356ac9cfda 100644
--- a/config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml
+++ b/config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml
@@ -2,6 +2,7 @@
name: ci_skip_persistent_ref_existence_check
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32391
rollout_issue_url:
-group: group::continuous integration
+milestone: '13.1'
type: development
+group: group::continuous integration
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
index 35cbfad0efa..ae20b11f79c 100644
--- a/config/feature_flags/development/ci_store_pipeline_messages.yml
+++ b/config/feature_flags/development/ci_store_pipeline_messages.yml
@@ -1,7 +1,8 @@
---
name: ci_store_pipeline_messages
-introduced_by_url:
-rollout_issue_url:
-group: group::continuous integration
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33762
+rollout_issue_url:
+milestone: '13.2'
type: development
+group: group::continuous integration
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
index 795ac08c7e9..a5cf148559f 100644
--- a/config/feature_flags/development/ci_synchronous_artifact_parsing.yml
+++ b/config/feature_flags/development/ci_synchronous_artifact_parsing.yml
@@ -2,6 +2,7 @@
name: ci_synchronous_artifact_parsing
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26247
rollout_issue_url:
-group: group::progressive delivery
+milestone: '12.9'
type: development
+group: group::progressive delivery
default_enabled: true
diff --git a/config/feature_flags/development/ci_trace_new_fog_store.yml b/config/feature_flags/development/ci_trace_new_fog_store.yml
deleted file mode 100644
index 04d2a43100a..00000000000
--- a/config/feature_flags/development/ci_trace_new_fog_store.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: ci_trace_new_fog_store
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46209
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/273405
-type: development
-group: group::testing
-default_enabled: true
diff --git a/config/feature_flags/development/ci_variable_expansion_in_rules_changes.yml b/config/feature_flags/development/ci_variable_expansion_in_rules_changes.yml
new file mode 100644
index 00000000000..a3a66295896
--- /dev/null
+++ b/config/feature_flags/development/ci_variable_expansion_in_rules_changes.yml
@@ -0,0 +1,7 @@
+---
+name: ci_variable_expansion_in_rules_changes
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45037
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/267192
+type: development
+group: group::pipeline authoring
+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
index 0ebd29d0ba5..be013bfe864 100644
--- a/config/feature_flags/development/ci_yaml_limit_size.yml
+++ b/config/feature_flags/development/ci_yaml_limit_size.yml
@@ -1,7 +1,8 @@
---
name: ci_yaml_limit_size
-introduced_by_url:
-rollout_issue_url:
-group: group::continuous integration
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab-foss/-/issues/56018
+milestone: '12.0'
type: development
+group: group::continuous integration
default_enabled: true
diff --git a/config/feature_flags/development/cluster_agent_list.yml b/config/feature_flags/development/cluster_agent_list.yml
index a4468b662ae..2c49950620d 100644
--- a/config/feature_flags/development/cluster_agent_list.yml
+++ b/config/feature_flags/development/cluster_agent_list.yml
@@ -1,7 +1,8 @@
---
name: cluster_agent_list
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/228845
-rollout_issue_url: https://gitlab.com/groups/gitlab-org/-/epics/3834
-group: group::configure
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42115
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/249596
+milestone: '13.5'
type: development
+group: group::configure
default_enabled: true
diff --git a/config/feature_flags/development/cluster_management_project.yml b/config/feature_flags/development/cluster_management_project.yml
index 922b7e6cad3..bcce2e027ff 100644
--- a/config/feature_flags/development/cluster_management_project.yml
+++ b/config/feature_flags/development/cluster_management_project.yml
@@ -2,6 +2,7 @@
name: cluster_management_project
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17866
rollout_issue_url:
-group: group::configure
+milestone: '12.4'
type: development
+group: group::configure
default_enabled: true
diff --git a/config/feature_flags/development/codequality_mr_diff.yml b/config/feature_flags/development/codequality_mr_diff.yml
new file mode 100644
index 00000000000..ca6846b9390
--- /dev/null
+++ b/config/feature_flags/development/codequality_mr_diff.yml
@@ -0,0 +1,8 @@
+---
+name: codequality_mr_diff
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47938
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/284140
+milestone: '13.7'
+type: development
+group: group::testing
+default_enabled: false
diff --git a/config/feature_flags/development/collect_package_events.yml b/config/feature_flags/development/collect_package_events.yml
new file mode 100644
index 00000000000..488dce6a724
--- /dev/null
+++ b/config/feature_flags/development/collect_package_events.yml
@@ -0,0 +1,8 @@
+---
+name: collect_package_events
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45802
+rollout_issue_url:
+milestone: '13.6'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/collect_package_events_redis.yml b/config/feature_flags/development/collect_package_events_redis.yml
new file mode 100644
index 00000000000..bc440a44f84
--- /dev/null
+++ b/config/feature_flags/development/collect_package_events_redis.yml
@@ -0,0 +1,7 @@
+---
+name: collect_package_events_redis
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46846
+rollout_issue_url:
+group: group::package
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/consolidated_edit_button.yml b/config/feature_flags/development/consolidated_edit_button.yml
index eecb426c1aa..c618f70555b 100644
--- a/config/feature_flags/development/consolidated_edit_button.yml
+++ b/config/feature_flags/development/consolidated_edit_button.yml
@@ -1,7 +1,8 @@
---
name: consolidated_edit_button
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44311
-rollout_issue_url:
-group: group::editor
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/270433
+milestone: '13.5'
type: development
+group: group::editor
default_enabled: false
diff --git a/config/feature_flags/development/container_expiration_policies_historic_entry.yml b/config/feature_flags/development/container_expiration_policies_historic_entry.yml
index 0525f77eacf..ab2111b3159 100644
--- a/config/feature_flags/development/container_expiration_policies_historic_entry.yml
+++ b/config/feature_flags/development/container_expiration_policies_historic_entry.yml
@@ -2,6 +2,7 @@
name: container_expiration_policies_historic_entry
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44444
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/262639
+milestone: '13.5'
type: development
group: group::package
default_enabled: false
diff --git a/config/feature_flags/development/container_registry_expiration_policies_throttling.yml b/config/feature_flags/development/container_registry_expiration_policies_throttling.yml
index 5169bcdfa28..f9aa6bde700 100644
--- a/config/feature_flags/development/container_registry_expiration_policies_throttling.yml
+++ b/config/feature_flags/development/container_registry_expiration_policies_throttling.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
+group: group::package
default_enabled: false
diff --git a/config/feature_flags/development/context_commits.yml b/config/feature_flags/development/context_commits.yml
index f615846f6c0..270a058558b 100644
--- a/config/feature_flags/development/context_commits.yml
+++ b/config/feature_flags/development/context_commits.yml
@@ -2,6 +2,7 @@
name: context_commits
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/core_security_mr_widget.yml b/config/feature_flags/development/core_security_mr_widget.yml
index 343bd238ae8..dfeb30cd83a 100644
--- a/config/feature_flags/development/core_security_mr_widget.yml
+++ b/config/feature_flags/development/core_security_mr_widget.yml
@@ -2,6 +2,7 @@
name: core_security_mr_widget
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44639
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/249543
+milestone: '13.5'
type: development
group: group::static analysis
default_enabled: true
diff --git a/config/feature_flags/development/count_uploads_size_in_storage_stats.yml b/config/feature_flags/development/count_uploads_size_in_storage_stats.yml
new file mode 100644
index 00000000000..524e4f4abd8
--- /dev/null
+++ b/config/feature_flags/development/count_uploads_size_in_storage_stats.yml
@@ -0,0 +1,8 @@
+---
+name: count_uploads_size_in_storage_stats
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46941
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/281950
+milestone: '13.6'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/coverage_fuzzing_mr_widget.yml b/config/feature_flags/development/coverage_fuzzing_mr_widget.yml
new file mode 100644
index 00000000000..589b7073b22
--- /dev/null
+++ b/config/feature_flags/development/coverage_fuzzing_mr_widget.yml
@@ -0,0 +1,8 @@
+---
+name: coverage_fuzzing_mr_widget
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43545
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257839
+milestone: '13.6'
+type: development
+group: group::fuzz testing
+default_enabled: true
diff --git a/config/feature_flags/development/create_cloud_run_clusters.yml b/config/feature_flags/development/create_cloud_run_clusters.yml
index 6c479a3dd6c..8352d6290e0 100644
--- a/config/feature_flags/development/create_cloud_run_clusters.yml
+++ b/config/feature_flags/development/create_cloud_run_clusters.yml
@@ -1,7 +1,8 @@
---
name: create_cloud_run_clusters
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19063
-rollout_issue_url:
-group: group::configure
+rollout_issue_url:
+milestone: '12.5'
type: development
+group: group::configure
default_enabled: true
diff --git a/config/feature_flags/development/custom_emoji.yml b/config/feature_flags/development/custom_emoji.yml
new file mode 100644
index 00000000000..64c53c29fdb
--- /dev/null
+++ b/config/feature_flags/development/custom_emoji.yml
@@ -0,0 +1,8 @@
+---
+name: custom_emoji
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37911
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/231317
+milestone: '13.6'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/dag_pipeline_tab.yml b/config/feature_flags/development/dag_pipeline_tab.yml
index f4261b51e05..f2ae897df8e 100644
--- a/config/feature_flags/development/dag_pipeline_tab.yml
+++ b/config/feature_flags/development/dag_pipeline_tab.yml
@@ -1,7 +1,8 @@
---
name: dag_pipeline_tab
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30310
-rollout_issue_url:
-group: group::pipeline authoring
+rollout_issue_url:
+milestone: '13.0'
type: development
+group: group::pipeline authoring
default_enabled: true
diff --git a/config/feature_flags/development/dashboard_pipeline_status.yml b/config/feature_flags/development/dashboard_pipeline_status.yml
index 8034177ee1e..f24ba5983a8 100644
--- a/config/feature_flags/development/dashboard_pipeline_status.yml
+++ b/config/feature_flags/development/dashboard_pipeline_status.yml
@@ -2,6 +2,7 @@
name: dashboard_pipeline_status
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22029
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/209061
-group: group::continuous integration
+milestone: '12.7'
type: development
+group: group::continuous integration
default_enabled: true
diff --git a/config/feature_flags/development/debian_packages.yml b/config/feature_flags/development/debian_packages.yml
index 8f706e81b6a..df4c155bba9 100644
--- a/config/feature_flags/development/debian_packages.yml
+++ b/config/feature_flags/development/debian_packages.yml
@@ -2,6 +2,7 @@
name: debian_packages
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42670
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/5835
-group: group::package
+milestone: '13.5'
type: development
+group: group::package
default_enabled: false
diff --git a/config/feature_flags/development/default_merge_ref_for_diffs.yml b/config/feature_flags/development/default_merge_ref_for_diffs.yml
index b982185c1fd..8442240e442 100644
--- a/config/feature_flags/development/default_merge_ref_for_diffs.yml
+++ b/config/feature_flags/development/default_merge_ref_for_diffs.yml
@@ -1,7 +1,8 @@
---
name: default_merge_ref_for_diffs
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34472
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276917
+milestone: '13.4'
type: development
group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/deploy_boards_dedupe_instances.yml b/config/feature_flags/development/deploy_boards_dedupe_instances.yml
deleted file mode 100644
index d407e11babd..00000000000
--- a/config/feature_flags/development/deploy_boards_dedupe_instances.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: deploy_boards_dedupe_instances
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40768
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258214
-type: development
-group: group::progressive delivery
-default_enabled: false
diff --git a/config/feature_flags/development/deploy_keys_on_protected_branches.yml b/config/feature_flags/development/deploy_keys_on_protected_branches.yml
index ec5c13082ec..438726c0315 100644
--- a/config/feature_flags/development/deploy_keys_on_protected_branches.yml
+++ b/config/feature_flags/development/deploy_keys_on_protected_branches.yml
@@ -2,6 +2,7 @@
name: deploy_keys_on_protected_branches
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35638
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247866
-group: group::progressive delivery
+milestone: '13.5'
type: development
+group: group::progressive delivery
default_enabled: false
diff --git a/config/feature_flags/development/deploy_tokens_api.yml b/config/feature_flags/development/deploy_tokens_api.yml
index 27c583e760b..b9741e05d7e 100644
--- a/config/feature_flags/development/deploy_tokens_api.yml
+++ b/config/feature_flags/development/deploy_tokens_api.yml
@@ -1,7 +1,8 @@
---
name: deploy_tokens_api
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25219
-rollout_issue_url:
-group: group::package
+rollout_issue_url:
+milestone: '12.9'
type: development
+group: group::package
default_enabled: true
diff --git a/config/feature_flags/development/deployment_filters.yml b/config/feature_flags/development/deployment_filters.yml
deleted file mode 100644
index 8c265f253fc..00000000000
--- a/config/feature_flags/development/deployment_filters.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: deployment_filters
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44041
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/267561
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/design_management_allow_dangerous_images.yml b/config/feature_flags/development/design_management_allow_dangerous_images.yml
index 73c348a69ca..1973755f7d3 100644
--- a/config/feature_flags/development/design_management_allow_dangerous_images.yml
+++ b/config/feature_flags/development/design_management_allow_dangerous_images.yml
@@ -2,6 +2,7 @@
name: design_management_allow_dangerous_images
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16160
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/34279
-group: group::knowledge
+milestone: '12.4'
type: development
+group: group::knowledge
default_enabled: false
diff --git a/config/feature_flags/development/devops_adoption_feature.yml b/config/feature_flags/development/devops_adoption_feature.yml
new file mode 100644
index 00000000000..7032c52c390
--- /dev/null
+++ b/config/feature_flags/development/devops_adoption_feature.yml
@@ -0,0 +1,8 @@
+---
+name: devops_adoption_feature
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46005
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/271568
+milestone: '13.6'
+type: development
+group: group::analytics
+default_enabled: false
diff --git a/config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml b/config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml
index d0e549a465d..354dfebbf6d 100644
--- a/config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml
+++ b/config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml
@@ -1,7 +1,8 @@
---
name: disable_metric_dashboard_refresh_rate
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229831
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37195
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229841
-group: group::health
+milestone: '13.2'
type: development
+group: group::health
default_enabled: false
diff --git a/config/feature_flags/development/disable_shared_runners_on_group.yml b/config/feature_flags/development/disable_shared_runners_on_group.yml
deleted file mode 100644
index 86ccf59c8a0..00000000000
--- a/config/feature_flags/development/disable_shared_runners_on_group.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: disable_shared_runners_on_group
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36080
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258991
-type: development
-group: group::runner
-default_enabled: true
diff --git a/config/feature_flags/development/display_merge_conflicts_in_diff.yml b/config/feature_flags/development/display_merge_conflicts_in_diff.yml
index 678037fa366..d460e491480 100644
--- a/config/feature_flags/development/display_merge_conflicts_in_diff.yml
+++ b/config/feature_flags/development/display_merge_conflicts_in_diff.yml
@@ -1,7 +1,8 @@
---
name: display_merge_conflicts_in_diff
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45008
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/277097
+milestone: '13.5'
type: development
group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/drop_license_management_artifact.yml b/config/feature_flags/development/drop_license_management_artifact.yml
index 34e10fa7ae6..1be40187b43 100644
--- a/config/feature_flags/development/drop_license_management_artifact.yml
+++ b/config/feature_flags/development/drop_license_management_artifact.yml
@@ -1,7 +1,8 @@
---
name: drop_license_management_artifact
-introduced_by_url:
-rollout_issue_url:
-group: group::composition analysis
+introduced_by_url:
+rollout_issue_url:
+milestone:
type: development
+group: group::composition analysis
default_enabled: true
diff --git a/config/feature_flags/development/dynamic_image_resizing_owner.yml b/config/feature_flags/development/dynamic_image_resizing_owner.yml
deleted file mode 100644
index fd9881fba31..00000000000
--- a/config/feature_flags/development/dynamic_image_resizing_owner.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-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
deleted file mode 100644
index e491b14d27d..00000000000
--- a/config/feature_flags/development/dynamic_image_resizing_requester.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-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
index 1b12c166c53..98c2b1ce314 100644
--- a/config/feature_flags/development/efficient_counter_attribute.yml
+++ b/config/feature_flags/development/efficient_counter_attribute.yml
@@ -2,6 +2,7 @@
name: efficient_counter_attribute
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35878
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/238535
-group: group::continuous integration
+milestone: '13.3'
type: development
+group: group::continuous integration
default_enabled: false
diff --git a/config/feature_flags/development/environment_auto_stop_start_on_create.yml b/config/feature_flags/development/environment_auto_stop_start_on_create.yml
new file mode 100644
index 00000000000..4950449ad9c
--- /dev/null
+++ b/config/feature_flags/development/environment_auto_stop_start_on_create.yml
@@ -0,0 +1,8 @@
+---
+name: environment_auto_stop_start_on_create
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47239
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/281449
+milestone: '13.6'
+type: development
+group: group::release
+default_enabled: false
diff --git a/config/feature_flags/development/export_reduce_relation_batch_size.yml b/config/feature_flags/development/export_reduce_relation_batch_size.yml
index d077079b586..70b19dfe594 100644
--- a/config/feature_flags/development/export_reduce_relation_batch_size.yml
+++ b/config/feature_flags/development/export_reduce_relation_batch_size.yml
@@ -1,7 +1,8 @@
---
name: export_reduce_relation_batch_size
-introduced_by_url:
-rollout_issue_url:
-group: group::import
+introduced_by_url:
+rollout_issue_url:
+milestone:
type: development
+group: group::import
default_enabled: false
diff --git a/config/feature_flags/development/expose_environment_path_in_alert_details.yml b/config/feature_flags/development/expose_environment_path_in_alert_details.yml
deleted file mode 100644
index f1e35cffbe0..00000000000
--- a/config/feature_flags/development/expose_environment_path_in_alert_details.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: expose_environment_path_in_alert_details
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43414
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258638
-type: development
-group: group::progressive delivery
-default_enabled: false
diff --git a/config/feature_flags/development/feature_flag_api.yml b/config/feature_flags/development/feature_flag_api.yml
index 326cfa83433..3dc1d87d741 100644
--- a/config/feature_flags/development/feature_flag_api.yml
+++ b/config/feature_flags/development/feature_flag_api.yml
@@ -2,6 +2,7 @@
name: feature_flag_api
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18198
rollout_issue_url:
-group: group::progressive delivery
+milestone: '12.4'
type: development
+group: group::progressive delivery
default_enabled: false
diff --git a/config/feature_flags/development/feature_flag_permissions.yml b/config/feature_flags/development/feature_flag_permissions.yml
index 2eb5b513743..b7a4e8cb1bb 100644
--- a/config/feature_flags/development/feature_flag_permissions.yml
+++ b/config/feature_flags/development/feature_flag_permissions.yml
@@ -2,6 +2,7 @@
name: feature_flag_permissions
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10096
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/254981
-group: group::progressive delivery
+milestone: '11.10'
type: development
+group: group::progressive delivery
default_enabled: false
diff --git a/config/feature_flags/development/feature_flags_legacy_read_only.yml b/config/feature_flags/development/feature_flags_legacy_read_only.yml
index b790e466093..b960d2df1fa 100644
--- a/config/feature_flags/development/feature_flags_legacy_read_only.yml
+++ b/config/feature_flags/development/feature_flags_legacy_read_only.yml
@@ -1,7 +1,8 @@
---
name: feature_flags_legacy_read_only
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38353
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/240985
-group: group::progressive delivery
+milestone: '13.3'
type: development
+group: group::progressive delivery
default_enabled: true
diff --git a/config/feature_flags/development/feature_flags_legacy_read_only_override.yml b/config/feature_flags/development/feature_flags_legacy_read_only_override.yml
index 14acde1b8fc..28438a130f4 100644
--- a/config/feature_flags/development/feature_flags_legacy_read_only_override.yml
+++ b/config/feature_flags/development/feature_flags_legacy_read_only_override.yml
@@ -2,6 +2,7 @@
name: feature_flags_legacy_read_only_override
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40431
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/240985
-group: group::progressive delivery
+milestone: '13.4'
type: development
+group: group::progressive delivery
default_enabled: false
diff --git a/config/feature_flags/development/feature_flags_new_version.yml b/config/feature_flags/development/feature_flags_new_version.yml
index 3a89816c482..f42054ce3ef 100644
--- a/config/feature_flags/development/feature_flags_new_version.yml
+++ b/config/feature_flags/development/feature_flags_new_version.yml
@@ -2,6 +2,7 @@
name: feature_flags_new_version
introduced_by_url:
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258831
-group: group::progressive delivery
+milestone: '13.7'
type: development
+group: group::progressive delivery
default_enabled: true
diff --git a/config/feature_flags/development/file_identifier_hash.yml b/config/feature_flags/development/file_identifier_hash.yml
index 681054cf7fa..d5dc2b03eb6 100644
--- a/config/feature_flags/development/file_identifier_hash.yml
+++ b/config/feature_flags/development/file_identifier_hash.yml
@@ -2,6 +2,7 @@
name: file_identifier_hash
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/filter_pipelines_search.yml b/config/feature_flags/development/filter_pipelines_search.yml
deleted file mode 100644
index 57bf61552d8..00000000000
--- a/config/feature_flags/development/filter_pipelines_search.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-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
index 352a6d40bd1..a2430dc1c27 100644
--- a/config/feature_flags/development/force_autodevops_on_by_default.yml
+++ b/config/feature_flags/development/force_autodevops_on_by_default.yml
@@ -1,7 +1,8 @@
---
name: force_autodevops_on_by_default
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21136
rollout_issue_url:
-group:
+milestone: '11.3'
type: development
+group: group::configure
default_enabled: false
diff --git a/config/feature_flags/development/forking.yml b/config/feature_flags/development/forking.yml
index d7d0cb79562..77e223d6268 100644
--- a/config/feature_flags/development/forking.yml
+++ b/config/feature_flags/development/forking.yml
@@ -2,6 +2,7 @@
name: forking
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/forti_authenticator.yml b/config/feature_flags/development/forti_authenticator.yml
index 31f5256753f..f3360d136ec 100644
--- a/config/feature_flags/development/forti_authenticator.yml
+++ b/config/feature_flags/development/forti_authenticator.yml
@@ -1,7 +1,8 @@
---
name: forti_authenticator
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45055
-rollout_issue_url:
+rollout_issue_url:
+milestone: '13.5'
type: development
group: group::access
default_enabled: false
diff --git a/config/feature_flags/development/forward_deployment_enabled.yml b/config/feature_flags/development/forward_deployment_enabled.yml
index f9aed1a0568..b4ad2e75561 100644
--- a/config/feature_flags/development/forward_deployment_enabled.yml
+++ b/config/feature_flags/development/forward_deployment_enabled.yml
@@ -2,6 +2,7 @@
name: forward_deployment_enabled
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24412
rollout_issue_url:
-group: group::progressive delivery
+milestone: '12.8'
type: development
+group: group::progressive delivery
default_enabled: true
diff --git a/config/feature_flags/development/generic_packages.yml b/config/feature_flags/development/generic_packages.yml
index 7b80e50d372..aa41fb58a56 100644
--- a/config/feature_flags/development/generic_packages.yml
+++ b/config/feature_flags/development/generic_packages.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
+group: group::release management
default_enabled: true
diff --git a/config/feature_flags/development/geo_snippet_repository_replication.yml b/config/feature_flags/development/geo_snippet_repository_replication.yml
index 7d121191d6c..69aa7beef55 100644
--- a/config/feature_flags/development/geo_snippet_repository_replication.yml
+++ b/config/feature_flags/development/geo_snippet_repository_replication.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
-default_enabled: false \ No newline at end of file
+group: group::geo
+default_enabled: false
diff --git a/config/feature_flags/development/git_push_create_all_pipelines.yml b/config/feature_flags/development/git_push_create_all_pipelines.yml
index a205307d5fa..3f651fab8ec 100644
--- a/config/feature_flags/development/git_push_create_all_pipelines.yml
+++ b/config/feature_flags/development/git_push_create_all_pipelines.yml
@@ -1,7 +1,8 @@
---
name: git_push_create_all_pipelines
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27205
-rollout_issue_url:
-group: group::continuous integration
+rollout_issue_url:
+milestone: '11.10'
type: development
+group: group::continuous integration
default_enabled: false
diff --git a/config/feature_flags/development/gitaly_catfile-cache.yml b/config/feature_flags/development/gitaly_catfile-cache.yml
index 1fdfacfb4d2..14268e328f0 100644
--- a/config/feature_flags/development/gitaly_catfile-cache.yml
+++ b/config/feature_flags/development/gitaly_catfile-cache.yml
@@ -2,6 +2,7 @@
name: gitaly_catfile-cache
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/gitaly_deny_disk_access.yml b/config/feature_flags/development/gitaly_deny_disk_access.yml
index faf9bc6d71f..b9c401e90d4 100644
--- a/config/feature_flags/development/gitaly_deny_disk_access.yml
+++ b/config/feature_flags/development/gitaly_deny_disk_access.yml
@@ -2,6 +2,7 @@
name: gitaly_deny_disk_access
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
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
index 2e4aa4ab794..cacfd87f203 100644
--- a/config/feature_flags/development/gitaly_enforce_requests_limits.yml
+++ b/config/feature_flags/development/gitaly_enforce_requests_limits.yml
@@ -2,6 +2,7 @@
name: gitaly_enforce_requests_limits
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/gitaly_mep_mep.yml b/config/feature_flags/development/gitaly_mep_mep.yml
index b657449a436..75cac13fe83 100644
--- a/config/feature_flags/development/gitaly_mep_mep.yml
+++ b/config/feature_flags/development/gitaly_mep_mep.yml
@@ -2,6 +2,7 @@
name: gitaly_mep_mep
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
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
index ea03b25874c..5b5453c0f08 100644
--- a/config/feature_flags/development/gitlab_ci_yml_preview.yml
+++ b/config/feature_flags/development/gitlab_ci_yml_preview.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
+group: group::ci
default_enabled: false
diff --git a/config/feature_flags/development/gitlab_org_sitemap.yml b/config/feature_flags/development/gitlab_org_sitemap.yml
new file mode 100644
index 00000000000..e0f10124d58
--- /dev/null
+++ b/config/feature_flags/development/gitlab_org_sitemap.yml
@@ -0,0 +1,8 @@
+---
+name: gitlab_org_sitemap
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46661
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276915
+milestone: '13.6'
+type: development
+group: group::editor
+default_enabled: false
diff --git a/config/feature_flags/development/gitpod.yml b/config/feature_flags/development/gitpod.yml
index d1d9f35d4d4..616aae4be45 100644
--- a/config/feature_flags/development/gitpod.yml
+++ b/config/feature_flags/development/gitpod.yml
@@ -2,6 +2,7 @@
name: gitpod
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37985
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258206
-group: group::editor
+milestone: '13.4'
type: development
+group: group::editor
default_enabled: true
diff --git a/config/feature_flags/development/global_default_branch_name.yml b/config/feature_flags/development/global_default_branch_name.yml
index 2954ed74062..488c9fb47c8 100644
--- a/config/feature_flags/development/global_default_branch_name.yml
+++ b/config/feature_flags/development/global_default_branch_name.yml
@@ -1,7 +1,8 @@
---
name: global_default_branch_name
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35269
-rollout_issue_url:
-group: group::source code
+rollout_issue_url:
+milestone: '13.2'
type: development
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/go_proxy.yml b/config/feature_flags/development/go_proxy.yml
index bd0c58faee5..4ec5dc786fd 100644
--- a/config/feature_flags/development/go_proxy.yml
+++ b/config/feature_flags/development/go_proxy.yml
@@ -1,7 +1,8 @@
---
name: go_proxy
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27746
-rollout_issue_url:
-group: group::package
+rollout_issue_url:
+milestone: '13.1'
type: development
+group: group::package
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
index 336a88bb7ff..f361d3392ec 100644
--- a/config/feature_flags/development/go_proxy_disable_gomod_validation.yml
+++ b/config/feature_flags/development/go_proxy_disable_gomod_validation.yml
@@ -1,7 +1,8 @@
---
name: go_proxy_disable_gomod_validation
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34338
-rollout_issue_url:
-group: group::package
+rollout_issue_url:
+milestone: '13.1'
type: development
+group: group::package
default_enabled: false
diff --git a/config/feature_flags/development/grape_gitlab_json.yml b/config/feature_flags/development/grape_gitlab_json.yml
index ab98ed981c9..e29496c917d 100644
--- a/config/feature_flags/development/grape_gitlab_json.yml
+++ b/config/feature_flags/development/grape_gitlab_json.yml
@@ -1,7 +1,8 @@
---
name: grape_gitlab_json
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36472
rollout_issue_url:
-group:
+milestone: '13.2'
type: development
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/graphql_board_lists.yml b/config/feature_flags/development/graphql_board_lists.yml
index 7e2696a06c8..19785015f1b 100644
--- a/config/feature_flags/development/graphql_board_lists.yml
+++ b/config/feature_flags/development/graphql_board_lists.yml
@@ -1,7 +1,8 @@
---
name: graphql_board_lists
-introduced_by_url:
-rollout_issue_url:
-group: group::project management
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37905
+rollout_issue_url:
+milestone: '13.4'
type: development
+group: group::project management
default_enabled: false
diff --git a/config/feature_flags/development/graphql_individual_release_page.yml b/config/feature_flags/development/graphql_individual_release_page.yml
index 29c9692eaec..07eac51d380 100644
--- a/config/feature_flags/development/graphql_individual_release_page.yml
+++ b/config/feature_flags/development/graphql_individual_release_page.yml
@@ -2,6 +2,7 @@
name: graphql_individual_release_page
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44779
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/263522
+milestone: '13.5'
type: development
group: group::release management
default_enabled: true
diff --git a/config/feature_flags/development/graphql_logging.yml b/config/feature_flags/development/graphql_logging.yml
index cd2a5b109e8..30f03a60a06 100644
--- a/config/feature_flags/development/graphql_logging.yml
+++ b/config/feature_flags/development/graphql_logging.yml
@@ -1,7 +1,8 @@
---
name: graphql_logging
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27885
rollout_issue_url:
-group:
+milestone: '12.0'
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/graphql_milestone_stats.yml b/config/feature_flags/development/graphql_milestone_stats.yml
index a3ff14d3245..f6873e1c9e9 100644
--- a/config/feature_flags/development/graphql_milestone_stats.yml
+++ b/config/feature_flags/development/graphql_milestone_stats.yml
@@ -1,7 +1,8 @@
---
name: graphql_milestone_stats
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35066
-rollout_issue_url:
-group: group::release management
+rollout_issue_url:
+milestone: '13.2'
type: development
+group: group::release management
default_enabled: true
diff --git a/config/feature_flags/development/graphql_pipeline_details.yml b/config/feature_flags/development/graphql_pipeline_details.yml
new file mode 100644
index 00000000000..c6d03850f0e
--- /dev/null
+++ b/config/feature_flags/development/graphql_pipeline_details.yml
@@ -0,0 +1,7 @@
+---
+name: graphql_pipeline_details
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46380
+rollout_issue_url:
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/graphql_pipeline_header.yml b/config/feature_flags/development/graphql_pipeline_header.yml
index 99019d4c849..1d400c17452 100644
--- a/config/feature_flags/development/graphql_pipeline_header.yml
+++ b/config/feature_flags/development/graphql_pipeline_header.yml
@@ -2,6 +2,7 @@
name: graphql_pipeline_header
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39494
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/254235
-group: group::pipeline authoring
+milestone: '13.5'
type: development
+group: group::pipeline authoring
default_enabled: false
diff --git a/config/feature_flags/development/graphql_release_data.yml b/config/feature_flags/development/graphql_release_data.yml
index 609c0dc634a..ef1f3dbba4c 100644
--- a/config/feature_flags/development/graphql_release_data.yml
+++ b/config/feature_flags/development/graphql_release_data.yml
@@ -1,7 +1,8 @@
---
name: graphql_release_data
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30753
-rollout_issue_url:
-group: group::release management
+rollout_issue_url:
+milestone: '13.0'
type: development
+group: group::release management
default_enabled: true
diff --git a/config/feature_flags/development/graphql_releases_page.yml b/config/feature_flags/development/graphql_releases_page.yml
index 607fc7027b5..541cf04bd79 100644
--- a/config/feature_flags/development/graphql_releases_page.yml
+++ b/config/feature_flags/development/graphql_releases_page.yml
@@ -1,7 +1,8 @@
---
name: graphql_releases_page
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33095
-rollout_issue_url:
-group: group::release management
+rollout_issue_url:
+milestone: '13.4'
type: development
+group: group::release management
default_enabled: true
diff --git a/config/feature_flags/development/group_export_ndjson.yml b/config/feature_flags/development/group_export_ndjson.yml
index 3f7f61672f4..0f6cc863022 100644
--- a/config/feature_flags/development/group_export_ndjson.yml
+++ b/config/feature_flags/development/group_export_ndjson.yml
@@ -1,7 +1,8 @@
---
name: group_export_ndjson
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29590
-rollout_issue_url:
-group: group::import
+rollout_issue_url:
+milestone: '13.0'
type: development
+group: group::import
default_enabled: true
diff --git a/config/feature_flags/development/group_import_export.yml b/config/feature_flags/development/group_import_export.yml
index 0e88c45684f..59204f2d16e 100644
--- a/config/feature_flags/development/group_import_export.yml
+++ b/config/feature_flags/development/group_import_export.yml
@@ -1,7 +1,8 @@
---
name: group_import_export
-introduced_by_url:
-rollout_issue_url:
-group: group::import
+introduced_by_url:
+rollout_issue_url:
+milestone:
type: development
+group: group::import
default_enabled: true
diff --git a/config/feature_flags/development/group_import_ndjson.yml b/config/feature_flags/development/group_import_ndjson.yml
index 98f0d4722e4..a84df7e0074 100644
--- a/config/feature_flags/development/group_import_ndjson.yml
+++ b/config/feature_flags/development/group_import_ndjson.yml
@@ -1,7 +1,8 @@
---
name: group_import_ndjson
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29716
-rollout_issue_url:
-group: group::import
+rollout_issue_url:
+milestone: '13.0'
type: development
+group: group::import
default_enabled: true
diff --git a/config/feature_flags/development/group_level_integrations.yml b/config/feature_flags/development/group_level_integrations.yml
index c089333f72a..2be5207e099 100644
--- a/config/feature_flags/development/group_level_integrations.yml
+++ b/config/feature_flags/development/group_level_integrations.yml
@@ -2,6 +2,7 @@
name: group_level_integrations
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27557
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/238575
-group: group::ecosystem
+milestone: '12.10'
type: development
-default_enabled: false
+group: group::ecosystem
+default_enabled: true
diff --git a/config/feature_flags/development/groups_tokens_optional_encryption.yml b/config/feature_flags/development/groups_tokens_optional_encryption.yml
index 2c081e72e52..2b36b0d7c10 100644
--- a/config/feature_flags/development/groups_tokens_optional_encryption.yml
+++ b/config/feature_flags/development/groups_tokens_optional_encryption.yml
@@ -2,6 +2,7 @@
name: groups_tokens_optional_encryption
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/help_page_documentation_redirect.yml b/config/feature_flags/development/help_page_documentation_redirect.yml
index bf30101a199..8871160e42d 100644
--- a/config/feature_flags/development/help_page_documentation_redirect.yml
+++ b/config/feature_flags/development/help_page_documentation_redirect.yml
@@ -2,6 +2,7 @@
name: help_page_documentation_redirect
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42702
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/255328
-group: group::static site editor
+milestone: '13.5'
type: development
+group: group::static site editor
default_enabled: false
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
index 075f3e135ed..6337f6154d9 100644
--- 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
@@ -1,7 +1,8 @@
---
name: hide_jump_to_next_unresolved_in_threads
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37873
rollout_issue_url:
-group:
+milestone: '13.3'
type: development
+group: group::source code
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
index 1133680c173..fc872ea47fc 100644
--- a/config/feature_flags/development/highlight_current_diff_row.yml
+++ b/config/feature_flags/development/highlight_current_diff_row.yml
@@ -1,7 +1,8 @@
---
name: highlight_current_diff_row
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27937
rollout_issue_url:
-group:
+milestone: '13.4'
type: development
+group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/http_integrations_list.yml b/config/feature_flags/development/http_integrations_list.yml
new file mode 100644
index 00000000000..3567f7b446d
--- /dev/null
+++ b/config/feature_flags/development/http_integrations_list.yml
@@ -0,0 +1,8 @@
+---
+name: http_integrations_list
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45993
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/255502
+milestone: '13.6'
+type: development
+group: group::health
+default_enabled: false
diff --git a/config/feature_flags/development/include_lfs_blobs_in_archive.yml b/config/feature_flags/development/include_lfs_blobs_in_archive.yml
index fcbefa3d072..c2908fb28da 100644
--- a/config/feature_flags/development/include_lfs_blobs_in_archive.yml
+++ b/config/feature_flags/development/include_lfs_blobs_in_archive.yml
@@ -1,7 +1,8 @@
---
name: include_lfs_blobs_in_archive
-introduced_by_url: '44116'
-rollout_issue_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44116
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268409
+milestone: '13.5'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/increased_diff_limits.yml b/config/feature_flags/development/increased_diff_limits.yml
index 351e6926161..ee811c221dc 100644
--- a/config/feature_flags/development/increased_diff_limits.yml
+++ b/config/feature_flags/development/increased_diff_limits.yml
@@ -2,6 +2,7 @@
name: increased_diff_limits
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40357
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241185
-group: group::source code
+milestone: '13.5'
type: development
+group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/ingress_modsecurity.yml b/config/feature_flags/development/ingress_modsecurity.yml
index 7ed1d089476..1dc7a1d6a52 100644
--- a/config/feature_flags/development/ingress_modsecurity.yml
+++ b/config/feature_flags/development/ingress_modsecurity.yml
@@ -2,6 +2,7 @@
name: ingress_modsecurity
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20194
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258554
-group: group::container security
+milestone: '12.5'
type: development
+group: group::container security
default_enabled: false
diff --git a/config/feature_flags/development/instance_statistics.yml b/config/feature_flags/development/instance_statistics.yml
index 212b7b39615..b5354561d03 100644
--- a/config/feature_flags/development/instance_statistics.yml
+++ b/config/feature_flags/development/instance_statistics.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
-default_enabled: false \ No newline at end of file
+group: group::analytics
+default_enabled: true
diff --git a/config/feature_flags/development/invisible_captcha.yml b/config/feature_flags/development/invisible_captcha.yml
index e44e5a47947..bfe118c1826 100644
--- a/config/feature_flags/development/invisible_captcha.yml
+++ b/config/feature_flags/development/invisible_captcha.yml
@@ -1,7 +1,8 @@
---
name: invisible_captcha
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31625
-rollout_issue_url:
-group: group::acquisition
+rollout_issue_url:
+milestone: '12.2'
type: development
+group: group::acquisition
default_enabled: false
diff --git a/config/feature_flags/development/invite_email_experiment.yml b/config/feature_flags/development/invite_email_experiment.yml
deleted file mode 100644
index 496f096f7c7..00000000000
--- a/config/feature_flags/development/invite_email_experiment.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: invite_email_experiment
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39628
-rollout_issue_url:
-group: group::acquisition
-type: development
-default_enabled: false
diff --git a/config/feature_flags/development/invite_members_group_modal.yml b/config/feature_flags/development/invite_members_group_modal.yml
index faa905f6557..444cc79ff57 100644
--- a/config/feature_flags/development/invite_members_group_modal.yml
+++ b/config/feature_flags/development/invite_members_group_modal.yml
@@ -2,6 +2,7 @@
name: invite_members_group_modal
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37906
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247208
-group: group::expansion
+milestone: '13.5'
type: development
+group: group::expansion
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
index 07aec532e16..c7b16357c68 100644
--- a/config/feature_flags/development/invite_your_teammates_banner_a.yml
+++ b/config/feature_flags/development/invite_your_teammates_banner_a.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
-default_enabled: false \ No newline at end of file
+group: group::expansion
+default_enabled: false
diff --git a/config/feature_flags/development/issues.yml b/config/feature_flags/development/issues.yml
index 6274767d4e1..a6ff572da52 100644
--- a/config/feature_flags/development/issues.yml
+++ b/config/feature_flags/development/issues.yml
@@ -2,6 +2,7 @@
name: issues
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/jira_connect_full_namespace_sync.yml b/config/feature_flags/development/jira_connect_full_namespace_sync.yml
new file mode 100644
index 00000000000..90fe97be409
--- /dev/null
+++ b/config/feature_flags/development/jira_connect_full_namespace_sync.yml
@@ -0,0 +1,7 @@
+---
+name: jira_connect_full_namespace_sync
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43880
+rollout_issue_url:
+type: development
+group: group::ecosystem
+default_enabled: false
diff --git a/config/feature_flags/development/jira_for_vulnerabilities.yml b/config/feature_flags/development/jira_for_vulnerabilities.yml
new file mode 100644
index 00000000000..32500c48da8
--- /dev/null
+++ b/config/feature_flags/development/jira_for_vulnerabilities.yml
@@ -0,0 +1,7 @@
+---
+name: jira_for_vulnerabilities
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46982
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276893
+type: development
+group: group::threat insights
+default_enabled: false
diff --git a/config/feature_flags/development/jira_issues_list.yml b/config/feature_flags/development/jira_issues_list.yml
new file mode 100644
index 00000000000..081daf0281e
--- /dev/null
+++ b/config/feature_flags/development/jira_issues_list.yml
@@ -0,0 +1,8 @@
+---
+name: jira_issues_list
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45678
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/273726
+milestone: '13.6'
+type: development
+group: group::ecosystem
+default_enabled: false
diff --git a/config/feature_flags/development/json_limited_encoder.yml b/config/feature_flags/development/json_limited_encoder.yml
index d20b5412233..409bae16b90 100644
--- a/config/feature_flags/development/json_limited_encoder.yml
+++ b/config/feature_flags/development/json_limited_encoder.yml
@@ -1,7 +1,8 @@
---
name: json_limited_encoder
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38687
-rollout_issue_url:
-group: group::source code
+rollout_issue_url:
+milestone: '13.3'
type: development
+group: group::source code
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
index dc3da1867e9..d255bf35889 100644
--- a/config/feature_flags/development/json_wrapper_legacy_mode.yml
+++ b/config/feature_flags/development/json_wrapper_legacy_mode.yml
@@ -2,6 +2,7 @@
name: json_wrapper_legacy_mode
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
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
index 273e0ed450e..eae38966064 100644
--- a/config/feature_flags/development/junit_pipeline_screenshots_view.yml
+++ b/config/feature_flags/development/junit_pipeline_screenshots_view.yml
@@ -1,7 +1,8 @@
---
name: junit_pipeline_screenshots_view
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/202114
-rollout_issue_url:
-group: group::verify testing
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31029
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/202114
+milestone: '13.0'
type: development
+group: group::verify testing
default_enabled: false
diff --git a/config/feature_flags/development/kubernetes_cluster_namespace_role_admin.yml b/config/feature_flags/development/kubernetes_cluster_namespace_role_admin.yml
deleted file mode 100644
index 7fb9a3d6921..00000000000
--- a/config/feature_flags/development/kubernetes_cluster_namespace_role_admin.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: kubernetes_cluster_namespace_role_admin
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45479
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/270030
-type: development
-group: group::configure
-default_enabled: false
diff --git a/config/feature_flags/development/lfs_check.yml b/config/feature_flags/development/lfs_check.yml
index 39e7d9ba6e9..1a6413bd016 100644
--- a/config/feature_flags/development/lfs_check.yml
+++ b/config/feature_flags/development/lfs_check.yml
@@ -1,7 +1,8 @@
---
name: lfs_check
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27451
rollout_issue_url:
-group:
+milestone: '11.11'
type: development
+group:
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
deleted file mode 100644
index f38bb4525ec..00000000000
--- a/config/feature_flags/development/lfs_link_existing_object.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-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
index efa763944ec..b2046ce2c29 100644
--- a/config/feature_flags/development/limit_projects_in_groups_api.yml
+++ b/config/feature_flags/development/limit_projects_in_groups_api.yml
@@ -2,6 +2,7 @@
name: limit_projects_in_groups_api
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20023
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257829
-group: group::access
+milestone: '12.6'
type: development
+group: group::access
default_enabled: true
diff --git a/config/feature_flags/development/log_import_export_relation_creation.yml b/config/feature_flags/development/log_import_export_relation_creation.yml
index 4ab84c2193c..ca7223c52b0 100644
--- a/config/feature_flags/development/log_import_export_relation_creation.yml
+++ b/config/feature_flags/development/log_import_export_relation_creation.yml
@@ -1,7 +1,8 @@
---
name: log_import_export_relation_creation
-introduced_by_url:
-rollout_issue_url:
-group: group::import
+introduced_by_url:
+rollout_issue_url:
+milestone:
type: development
+group: group::import
default_enabled: false
diff --git a/config/feature_flags/development/maintenance_mode.yml b/config/feature_flags/development/maintenance_mode.yml
index 429e70b64a2..53ecea7ba2b 100644
--- a/config/feature_flags/development/maintenance_mode.yml
+++ b/config/feature_flags/development/maintenance_mode.yml
@@ -2,6 +2,7 @@
name: maintenance_mode
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28158
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/217895
-group: group::geo
+milestone: '12.10'
type: development
+group: group::geo
default_enabled: false
diff --git a/config/feature_flags/development/merge_base_pipelines.yml b/config/feature_flags/development/merge_base_pipelines.yml
deleted file mode 100644
index 4f57ca556f1..00000000000
--- a/config/feature_flags/development/merge_base_pipelines.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: merge_base_pipelines
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44648
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/263724
-type: development
-group: group::testing
-default_enabled: false
diff --git a/config/feature_flags/development/merge_orchestration_service.yml b/config/feature_flags/development/merge_orchestration_service.yml
index 2bdfe9b52a4..52de3b6e733 100644
--- a/config/feature_flags/development/merge_orchestration_service.yml
+++ b/config/feature_flags/development/merge_orchestration_service.yml
@@ -2,6 +2,7 @@
name: merge_orchestration_service
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28532
rollout_issue_url:
-group: group::continuous integration
+milestone: '12.10'
type: development
+group: group::continuous integration
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
deleted file mode 100644
index 5effc83b53e..00000000000
--- a/config/feature_flags/development/merge_red_head_comments_position_on_demand.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-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
index cc5ea34eb0e..f22a18940c7 100644
--- a/config/feature_flags/development/merge_ref_auto_sync.yml
+++ b/config/feature_flags/development/merge_ref_auto_sync.yml
@@ -1,7 +1,8 @@
---
name: merge_ref_auto_sync
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29569
rollout_issue_url:
-group:
+milestone: '12.1'
type: development
+group: group::source code
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
index d9724712869..e26c5ed5050 100644
--- a/config/feature_flags/development/merge_ref_auto_sync_lock.yml
+++ b/config/feature_flags/development/merge_ref_auto_sync_lock.yml
@@ -1,7 +1,8 @@
---
name: merge_ref_auto_sync_lock
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31082
rollout_issue_url:
-group:
+milestone: '12.2'
type: development
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/merge_request_cached_pipeline_serializer.yml b/config/feature_flags/development/merge_request_cached_pipeline_serializer.yml
index 1141d1f82a4..60db901d801 100644
--- a/config/feature_flags/development/merge_request_cached_pipeline_serializer.yml
+++ b/config/feature_flags/development/merge_request_cached_pipeline_serializer.yml
@@ -1,7 +1,8 @@
---
name: merge_request_cached_pipeline_serializer
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38273
-rollout_issue_url:
+rollout_issue_url:
+milestone: '13.5'
type: development
group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/merge_request_draft_filter.yml b/config/feature_flags/development/merge_request_draft_filter.yml
index 6bf3e12d817..ee719f52b7c 100644
--- a/config/feature_flags/development/merge_request_draft_filter.yml
+++ b/config/feature_flags/development/merge_request_draft_filter.yml
@@ -1,7 +1,8 @@
---
name: merge_request_draft_filter
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35942
-rollout_issue_url:
-group: group::source code
+rollout_issue_url:
+milestone: '13.3'
type: development
+group: group::source code
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
index 06cbcd3da07..3ea69762c1d 100644
--- a/config/feature_flags/development/merge_request_rebase_nowait_lock.yml
+++ b/config/feature_flags/development/merge_request_rebase_nowait_lock.yml
@@ -2,6 +2,7 @@
name: merge_request_rebase_nowait_lock
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/merge_request_reviewers.yml b/config/feature_flags/development/merge_request_reviewers.yml
index 2180662b9df..ca9de4af264 100644
--- a/config/feature_flags/development/merge_request_reviewers.yml
+++ b/config/feature_flags/development/merge_request_reviewers.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
+group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/merge_request_widget_graphql.yml b/config/feature_flags/development/merge_request_widget_graphql.yml
index cbe76a61fa5..2969b91039a 100644
--- a/config/feature_flags/development/merge_request_widget_graphql.yml
+++ b/config/feature_flags/development/merge_request_widget_graphql.yml
@@ -1,7 +1,8 @@
---
name: merge_request_widget_graphql
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38311
-rollout_issue_url:
-group: group::source code
+rollout_issue_url:
+milestone: '13.3'
type: development
+group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/merge_requests.yml b/config/feature_flags/development/merge_requests.yml
index 05e8a301786..27f5f8b1085 100644
--- a/config/feature_flags/development/merge_requests.yml
+++ b/config/feature_flags/development/merge_requests.yml
@@ -2,6 +2,7 @@
name: merge_requests
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/metrics_dashboard.yml b/config/feature_flags/development/metrics_dashboard.yml
index 04a64b632ba..81eafa74ab4 100644
--- a/config/feature_flags/development/metrics_dashboard.yml
+++ b/config/feature_flags/development/metrics_dashboard.yml
@@ -2,6 +2,7 @@
name: metrics_dashboard
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29634
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257902
-group: group::health
+milestone: '13.0'
type: development
+group: group::health
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
index 3e3a5b9de9a..1fe4c51b6ec 100644
--- a/config/feature_flags/development/metrics_dashboard_exhaustive_validations.yml
+++ b/config/feature_flags/development/metrics_dashboard_exhaustive_validations.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
-default_enabled: false \ No newline at end of file
+group: group::apm
+default_enabled: false
diff --git a/config/feature_flags/development/migrate_user_mentions.yml b/config/feature_flags/development/migrate_user_mentions.yml
index 5dd5667dfae..df9e5477590 100644
--- a/config/feature_flags/development/migrate_user_mentions.yml
+++ b/config/feature_flags/development/migrate_user_mentions.yml
@@ -2,6 +2,7 @@
name: migrate_user_mentions
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34378
rollout_issue_url:
-group: group::project management
+milestone: '13.3'
type: development
+group: group::project management
default_enabled: true
diff --git a/config/feature_flags/development/mr_commit_neighbor_nav.yml b/config/feature_flags/development/mr_commit_neighbor_nav.yml
index 7b540e14464..d49dc656858 100644
--- a/config/feature_flags/development/mr_commit_neighbor_nav.yml
+++ b/config/feature_flags/development/mr_commit_neighbor_nav.yml
@@ -1,7 +1,8 @@
---
name: mr_commit_neighbor_nav
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28596
-rollout_issue_url:
-group: group::source code
+rollout_issue_url:
+milestone: '13.0'
type: development
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/mrc_api_use_raw_diffs_from_gitaly.yml b/config/feature_flags/development/mrc_api_use_raw_diffs_from_gitaly.yml
new file mode 100644
index 00000000000..c44d14a6dfc
--- /dev/null
+++ b/config/feature_flags/development/mrc_api_use_raw_diffs_from_gitaly.yml
@@ -0,0 +1,7 @@
+---
+name: mrc_api_use_raw_diffs_from_gitaly
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46190
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/225322
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/multi_select_board.yml b/config/feature_flags/development/multi_select_board.yml
deleted file mode 100644
index 3849fb0e12b..00000000000
--- a/config/feature_flags/development/multi_select_board.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: multi_select_board
-introduced_by_url:
-rollout_issue_url:
-group: group::project management
-type: development
-default_enabled: true
diff --git a/config/feature_flags/development/multiline_comments.yml b/config/feature_flags/development/multiline_comments.yml
index 135e5be1dc5..dad02bf80fd 100644
--- a/config/feature_flags/development/multiline_comments.yml
+++ b/config/feature_flags/development/multiline_comments.yml
@@ -1,7 +1,8 @@
---
name: multiline_comments
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/211255
-rollout_issue_url:
-group: group::source code
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37114
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/211255
+milestone: '13.2'
type: development
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/multiple_http_integrations_custom_mapping.yml b/config/feature_flags/development/multiple_http_integrations_custom_mapping.yml
new file mode 100644
index 00000000000..efc18603fdc
--- /dev/null
+++ b/config/feature_flags/development/multiple_http_integrations_custom_mapping.yml
@@ -0,0 +1,8 @@
+---
+name: multiple_http_integrations_custom_mapping
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46437
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/273573
+milestone: '13.6'
+type: development
+group: group::health
+default_enabled: false
diff --git a/config/feature_flags/development/new_pipeline_form.yml b/config/feature_flags/development/new_pipeline_form.yml
index 3c1079a5f5c..3a4b30f4bd9 100644
--- a/config/feature_flags/development/new_pipeline_form.yml
+++ b/config/feature_flags/development/new_pipeline_form.yml
@@ -2,6 +2,7 @@
name: new_pipeline_form
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35674
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229632
-group: group::continuous integration
+milestone: '13.2'
type: development
-default_enabled: false
+group: group::continuous integration
+default_enabled: true
diff --git a/config/feature_flags/development/new_pipeline_form_prefilled_vars.yml b/config/feature_flags/development/new_pipeline_form_prefilled_vars.yml
index 6b821e7fd9e..3f79783d805 100644
--- a/config/feature_flags/development/new_pipeline_form_prefilled_vars.yml
+++ b/config/feature_flags/development/new_pipeline_form_prefilled_vars.yml
@@ -2,6 +2,7 @@
name: new_pipeline_form_prefilled_vars
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44120
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/263276
+milestone: '13.5'
type: development
group: group::continuous integration
default_enabled: false
diff --git a/config/feature_flags/development/new_release_page.yml b/config/feature_flags/development/new_release_page.yml
index b2890b9ebf9..c3f757bfc41 100644
--- a/config/feature_flags/development/new_release_page.yml
+++ b/config/feature_flags/development/new_release_page.yml
@@ -1,7 +1,8 @@
---
name: new_release_page
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35367
-rollout_issue_url:
-group: group::release management
+rollout_issue_url:
+milestone: '13.2'
type: development
+group: group::release management
default_enabled: true
diff --git a/config/feature_flags/development/new_variables_ui.yml b/config/feature_flags/development/new_variables_ui.yml
deleted file mode 100644
index 091c6e51013..00000000000
--- a/config/feature_flags/development/new_variables_ui.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: new_variables_ui
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25260
-rollout_issue_url:
-group: group::continuous integration
-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
index a5cfba7980d..80aba0fef0f 100644
--- a/config/feature_flags/development/not_issuable_queries.yml
+++ b/config/feature_flags/development/not_issuable_queries.yml
@@ -1,7 +1,8 @@
---
name: not_issuable_queries
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27639
-rollout_issue_url:
-group: group::project management
+rollout_issue_url:
+milestone: '13.0'
type: development
+group: group::project management
default_enabled: true
diff --git a/config/feature_flags/development/notes_create_service_tracking.yml b/config/feature_flags/development/notes_create_service_tracking.yml
index 38636b7ee53..ae9d4ce09c5 100644
--- a/config/feature_flags/development/notes_create_service_tracking.yml
+++ b/config/feature_flags/development/notes_create_service_tracking.yml
@@ -2,6 +2,7 @@
name: notes_create_service_tracking
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/oj_json.yml b/config/feature_flags/development/oj_json.yml
deleted file mode 100644
index b7e112ae544..00000000000
--- a/config/feature_flags/development/oj_json.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: oj_json
-introduced_by_url:
-rollout_issue_url:
-group:
-type: development
-default_enabled: true
diff --git a/config/feature_flags/development/one_dimensional_matrix.yml b/config/feature_flags/development/one_dimensional_matrix.yml
deleted file mode 100644
index 1db16474d38..00000000000
--- a/config/feature_flags/development/one_dimensional_matrix.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: one_dimensional_matrix
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42170
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/256062
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/optimized_issuable_label_filter.yml b/config/feature_flags/development/optimized_issuable_label_filter.yml
index 12db63b03fb..4712cdaf230 100644
--- a/config/feature_flags/development/optimized_issuable_label_filter.yml
+++ b/config/feature_flags/development/optimized_issuable_label_filter.yml
@@ -2,6 +2,7 @@
name: optimized_issuable_label_filter
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34503
rollout_issue_url:
-group: group::analytics
+milestone: '13.4'
type: development
+group: group::analytics
default_enabled: false
diff --git a/config/feature_flags/development/optimized_timebox_queries.yml b/config/feature_flags/development/optimized_timebox_queries.yml
index d5301e20f3e..215242046c5 100644
--- a/config/feature_flags/development/optimized_timebox_queries.yml
+++ b/config/feature_flags/development/optimized_timebox_queries.yml
@@ -2,6 +2,7 @@
name: optimized_timebox_queries
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/pages.yml b/config/feature_flags/development/pages.yml
index 0afdc891e51..b32ab9af770 100644
--- a/config/feature_flags/development/pages.yml
+++ b/config/feature_flags/development/pages.yml
@@ -2,6 +2,7 @@
name: pages
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/pages_artifacts_archive.yml b/config/feature_flags/development/pages_artifacts_archive.yml
deleted file mode 100644
index 5cd4f4bd62b..00000000000
--- a/config/feature_flags/development/pages_artifacts_archive.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-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/pages_serve_from_artifacts_archive.yml b/config/feature_flags/development/pages_serve_from_artifacts_archive.yml
new file mode 100644
index 00000000000..4cc29601e48
--- /dev/null
+++ b/config/feature_flags/development/pages_serve_from_artifacts_archive.yml
@@ -0,0 +1,8 @@
+---
+name: pages_serve_from_artifacts_archive
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46320
+rollout_issue_url:
+group: group::release management
+milestone: '13.4'
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/pages_serve_from_deployments.yml b/config/feature_flags/development/pages_serve_from_deployments.yml
new file mode 100644
index 00000000000..ab75ec16952
--- /dev/null
+++ b/config/feature_flags/development/pages_serve_from_deployments.yml
@@ -0,0 +1,8 @@
+---
+name: pages_serve_from_deployments
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46320
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/2932
+milestone: '13.6'
+type: development
+group: group::Release Management
+default_enabled: false
diff --git a/config/feature_flags/development/pages_serve_with_zip_file_protocol.yml b/config/feature_flags/development/pages_serve_with_zip_file_protocol.yml
new file mode 100644
index 00000000000..7700cf7fae5
--- /dev/null
+++ b/config/feature_flags/development/pages_serve_with_zip_file_protocol.yml
@@ -0,0 +1,8 @@
+---
+name: pages_serve_with_zip_file_protocol
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46320
+rollout_issue_url:
+milestone: '13.6'
+type: development
+group: group::Release Management
+default_enabled: false
diff --git a/config/feature_flags/development/paginated_notes.yml b/config/feature_flags/development/paginated_notes.yml
index a9209fbe4ae..67036d693e3 100644
--- a/config/feature_flags/development/paginated_notes.yml
+++ b/config/feature_flags/development/paginated_notes.yml
@@ -2,6 +2,7 @@
name: paginated_notes
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34628
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/254987
-group: group::source code
+milestone: '13.2'
type: development
+group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/pat_creation_api_for_admin.yml b/config/feature_flags/development/pat_creation_api_for_admin.yml
new file mode 100644
index 00000000000..246f7623cc9
--- /dev/null
+++ b/config/feature_flags/development/pat_creation_api_for_admin.yml
@@ -0,0 +1,7 @@
+---
+name: pat_creation_api_for_admin
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45152
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/267553
+type: development
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/development/personal_snippet_reference_filters.yml b/config/feature_flags/development/personal_snippet_reference_filters.yml
index 44b9ac2f862..eb97a2caf0d 100644
--- a/config/feature_flags/development/personal_snippet_reference_filters.yml
+++ b/config/feature_flags/development/personal_snippet_reference_filters.yml
@@ -2,6 +2,7 @@
name: personal_snippet_reference_filters
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
+milestone: '13.3'
type: development
+group: group::editor
default_enabled: false
diff --git a/config/feature_flags/development/pg_hint_plan_for_issuables.yml b/config/feature_flags/development/pg_hint_plan_for_issuables.yml
new file mode 100644
index 00000000000..06d20c404c5
--- /dev/null
+++ b/config/feature_flags/development/pg_hint_plan_for_issuables.yml
@@ -0,0 +1,8 @@
+---
+name: pg_hint_plan_for_issuables
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46289
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/273528
+milestone: '13.6'
+type: development
+group: group::project planning
+default_enabled: false
diff --git a/config/feature_flags/development/phabricator_import.yml b/config/feature_flags/development/phabricator_import.yml
index 1bce39b65f6..264988e8006 100644
--- a/config/feature_flags/development/phabricator_import.yml
+++ b/config/feature_flags/development/phabricator_import.yml
@@ -2,6 +2,7 @@
name: phabricator_import
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/13569
rollout_issue_url: https://gitlab.com/groups/gitlab-org/-/epics/1197
-group: group::import
+milestone: '12.0'
type: development
+group: group::import
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
index b9e83bc0795..7b67212269c 100644
--- a/config/feature_flags/development/pipelines_security_report_summary.yml
+++ b/config/feature_flags/development/pipelines_security_report_summary.yml
@@ -2,6 +2,7 @@
name: pipelines_security_report_summary
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31136
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/235943
-group: group::dynamic analysis
+milestone: '13.0'
type: development
+group: group::dynamic analysis
default_enabled: false
diff --git a/config/feature_flags/development/product_analytics.yml b/config/feature_flags/development/product_analytics.yml
index 02840f3212b..faed7b5a5d8 100644
--- a/config/feature_flags/development/product_analytics.yml
+++ b/config/feature_flags/development/product_analytics.yml
@@ -1,7 +1,8 @@
---
name: product_analytics
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36443
-rollout_issue_url:
-group: group::product analytics
+rollout_issue_url:
+milestone: '13.2'
type: development
+group: group::product analytics
default_enabled: false
diff --git a/config/feature_flags/development/product_analytics_aggregated_metrics.yml b/config/feature_flags/development/product_analytics_aggregated_metrics.yml
new file mode 100644
index 00000000000..7f13b4c68a4
--- /dev/null
+++ b/config/feature_flags/development/product_analytics_aggregated_metrics.yml
@@ -0,0 +1,8 @@
+---
+name: product_analytics_aggregated_metrics
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44624
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/267550
+milestone: '13.6'
+type: development
+group: group::product analytics
+default_enabled: false
diff --git a/config/feature_flags/development/prohibit_hexadecimal_branch_names.yml b/config/feature_flags/development/prohibit_hexadecimal_branch_names.yml
index d1977765b81..cf90ccd0f69 100644
--- a/config/feature_flags/development/prohibit_hexadecimal_branch_names.yml
+++ b/config/feature_flags/development/prohibit_hexadecimal_branch_names.yml
@@ -2,6 +2,7 @@
name: prohibit_hexadecimal_branch_names
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
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
index f39b892f18a..f77c1979e55 100644
--- a/config/feature_flags/development/project_export_as_ndjson.yml
+++ b/config/feature_flags/development/project_export_as_ndjson.yml
@@ -1,7 +1,8 @@
---
name: project_export_as_ndjson
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26995
-rollout_issue_url:
-group: group::import
+rollout_issue_url:
+milestone: '12.10'
type: development
+group: group::import
default_enabled: true
diff --git a/config/feature_flags/development/project_finder_similarity_sort.yml b/config/feature_flags/development/project_finder_similarity_sort.yml
index 2d29bed82c4..4dadee97fd5 100644
--- a/config/feature_flags/development/project_finder_similarity_sort.yml
+++ b/config/feature_flags/development/project_finder_similarity_sort.yml
@@ -2,6 +2,7 @@
name: project_finder_similarity_sort
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43136
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/263249
+milestone: '13.5'
type: development
group: group::threat insights
default_enabled: false
diff --git a/config/feature_flags/development/project_import_ndjson.yml b/config/feature_flags/development/project_import_ndjson.yml
index 8dc924a97c2..756c6c1aaa5 100644
--- a/config/feature_flags/development/project_import_ndjson.yml
+++ b/config/feature_flags/development/project_import_ndjson.yml
@@ -1,7 +1,8 @@
---
name: project_import_ndjson
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27206
-rollout_issue_url:
-group: group::import
+rollout_issue_url:
+milestone: '12.10'
type: development
+group: group::import
default_enabled: true
diff --git a/config/feature_flags/development/project_list_filter_bar.yml b/config/feature_flags/development/project_list_filter_bar.yml
index 6040fe9edf5..7f8ea867990 100644
--- a/config/feature_flags/development/project_list_filter_bar.yml
+++ b/config/feature_flags/development/project_list_filter_bar.yml
@@ -2,6 +2,7 @@
name: project_list_filter_bar
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/project_statistics_sync.yml b/config/feature_flags/development/project_statistics_sync.yml
index ece3f1e49df..188e953f780 100644
--- a/config/feature_flags/development/project_statistics_sync.yml
+++ b/config/feature_flags/development/project_statistics_sync.yml
@@ -2,6 +2,7 @@
name: project_statistics_sync
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/project_transactionless_destroy.yml b/config/feature_flags/development/project_transactionless_destroy.yml
index 726875655e9..d51db437356 100644
--- a/config/feature_flags/development/project_transactionless_destroy.yml
+++ b/config/feature_flags/development/project_transactionless_destroy.yml
@@ -2,6 +2,7 @@
name: project_transactionless_destroy
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39367
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/255972
-group: group::continuous integration
+milestone: '13.4'
type: development
+group: group::continuous integration
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
index 76d76bca923..3d6f7905ef9 100644
--- a/config/feature_flags/development/projects_tokens_optional_encryption.yml
+++ b/config/feature_flags/development/projects_tokens_optional_encryption.yml
@@ -2,6 +2,7 @@
name: projects_tokens_optional_encryption
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/prometheus_computed_alerts.yml b/config/feature_flags/development/prometheus_computed_alerts.yml
index 576894df589..428a99c1c1e 100644
--- a/config/feature_flags/development/prometheus_computed_alerts.yml
+++ b/config/feature_flags/development/prometheus_computed_alerts.yml
@@ -2,6 +2,7 @@
name: prometheus_computed_alerts
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/13443
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/255304
-group: group::health
+milestone: '12.0'
type: development
+group: group::health
default_enabled: false
diff --git a/config/feature_flags/development/push_rules_supersede_code_owners.yml b/config/feature_flags/development/push_rules_supersede_code_owners.yml
new file mode 100644
index 00000000000..7226e443640
--- /dev/null
+++ b/config/feature_flags/development/push_rules_supersede_code_owners.yml
@@ -0,0 +1,7 @@
+---
+name: push_rules_supersede_code_owners
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44126
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/262019
+type: development
+group: group::source code
+default_enabled: true
diff --git a/config/feature_flags/development/reactive_caching_limit_environment.yml b/config/feature_flags/development/reactive_caching_limit_environment.yml
index 8aa66c9d293..2569f51eaad 100644
--- a/config/feature_flags/development/reactive_caching_limit_environment.yml
+++ b/config/feature_flags/development/reactive_caching_limit_environment.yml
@@ -2,6 +2,7 @@
name: reactive_caching_limit_environment
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34202
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/202633
-group: group::configure
+milestone: '13.2'
type: development
-default_enabled: false
+group: group::configure
+default_enabled: true
diff --git a/config/feature_flags/development/real_time_issue_sidebar.yml b/config/feature_flags/development/real_time_issue_sidebar.yml
index 37284b2642c..4fe8e19213a 100644
--- a/config/feature_flags/development/real_time_issue_sidebar.yml
+++ b/config/feature_flags/development/real_time_issue_sidebar.yml
@@ -2,6 +2,7 @@
name: real_time_issue_sidebar
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30239
rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/1210
-group: group::project management
+milestone: '13.0'
type: development
+group: group::project management
default_enabled: false
diff --git a/config/feature_flags/development/rebalance_issues.yml b/config/feature_flags/development/rebalance_issues.yml
index df04da8c8d3..5b2a4c2437b 100644
--- a/config/feature_flags/development/rebalance_issues.yml
+++ b/config/feature_flags/development/rebalance_issues.yml
@@ -1,7 +1,8 @@
---
name: rebalance_issues
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40124
+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
+milestone: '13.4'
type: development
+group: group::project management
default_enabled: false
diff --git a/config/feature_flags/development/recursive_approach_for_all_projects.yml b/config/feature_flags/development/recursive_approach_for_all_projects.yml
index 10c51419d6a..1d3b7e70919 100644
--- a/config/feature_flags/development/recursive_approach_for_all_projects.yml
+++ b/config/feature_flags/development/recursive_approach_for_all_projects.yml
@@ -2,6 +2,7 @@
name: recursive_approach_for_all_projects
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44740
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/263442
+milestone: '13.5'
type: development
group: group::fulfillment
default_enabled: false
diff --git a/config/feature_flags/development/release_evidence.yml b/config/feature_flags/development/release_evidence.yml
index c2f7ab16332..87648e6a261 100644
--- a/config/feature_flags/development/release_evidence.yml
+++ b/config/feature_flags/development/release_evidence.yml
@@ -2,6 +2,7 @@
name: release_evidence
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26509
rollout_issue_url:
-group: group::release management
+milestone: '12.10'
type: development
+group: group::release management
default_enabled: true
diff --git a/config/feature_flags/development/release_mr_issue_urls.yml b/config/feature_flags/development/release_mr_issue_urls.yml
index 3f9c81b8fe9..b017a716b51 100644
--- a/config/feature_flags/development/release_mr_issue_urls.yml
+++ b/config/feature_flags/development/release_mr_issue_urls.yml
@@ -1,7 +1,8 @@
---
name: release_mr_issue_urls
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18727
-rollout_issue_url:
-group: group::release management
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276619
+milestone: '12.4'
type: development
-default_enabled: false
+group: group::release management
+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
index ecb8e103949..1469a99ab2f 100644
--- a/config/feature_flags/development/remove_legacy_github_client.yml
+++ b/config/feature_flags/development/remove_legacy_github_client.yml
@@ -1,7 +1,8 @@
---
name: remove_legacy_github_client
-introduced_by_url:
-rollout_issue_url:
-group: group::import
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37555
+rollout_issue_url:
+milestone: '13.3'
type: development
+group: group::import
default_enabled: false
diff --git a/config/feature_flags/development/remove_resolve_note.yml b/config/feature_flags/development/remove_resolve_note.yml
new file mode 100644
index 00000000000..f5ec26f7580
--- /dev/null
+++ b/config/feature_flags/development/remove_resolve_note.yml
@@ -0,0 +1,8 @@
+---
+name: remove_resolve_note
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45549
+rollout_issue_url:
+milestone: '13.6'
+type: development
+group: group::source code
+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
index 18663a4e7af..15b7a3e67b0 100644
--- a/config/feature_flags/development/repack_after_shard_migration.yml
+++ b/config/feature_flags/development/repack_after_shard_migration.yml
@@ -2,6 +2,7 @@
name: repack_after_shard_migration
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21502
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/195597
-group: group::source code
+milestone: '12.6'
type: development
+group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/repository.yml b/config/feature_flags/development/repository.yml
index 2ae4abc42bc..a9dd6cbdcb5 100644
--- a/config/feature_flags/development/repository.yml
+++ b/config/feature_flags/development/repository.yml
@@ -2,6 +2,7 @@
name: repository
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/repository_archive_hotlinking_interception.yml b/config/feature_flags/development/repository_archive_hotlinking_interception.yml
index bc9efb2e4bc..6b684e5a8c7 100644
--- a/config/feature_flags/development/repository_archive_hotlinking_interception.yml
+++ b/config/feature_flags/development/repository_archive_hotlinking_interception.yml
@@ -2,6 +2,7 @@
name: repository_archive_hotlinking_interception
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/resource_access_token_feature.yml b/config/feature_flags/development/resource_access_token_feature.yml
new file mode 100644
index 00000000000..536502b7ca0
--- /dev/null
+++ b/config/feature_flags/development/resource_access_token_feature.yml
@@ -0,0 +1,8 @@
+---
+name: resource_access_token_feature
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29622
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/235765
+milestone: '13.0'
+type: development
+group: group::access
+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
index 06f894b79b3..bf909974f7c 100644
--- a/config/feature_flags/development/rugged_commit_is_ancestor.yml
+++ b/config/feature_flags/development/rugged_commit_is_ancestor.yml
@@ -2,6 +2,7 @@
name: rugged_commit_is_ancestor
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
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
index a0cb28e6ca9..c0ba656f7a6 100644
--- a/config/feature_flags/development/rugged_commit_tree_entry.yml
+++ b/config/feature_flags/development/rugged_commit_tree_entry.yml
@@ -1,7 +1,8 @@
---
name: rugged_commit_tree_entry
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25896
rollout_issue_url:
-group:
+milestone: '11.9'
type: development
+group: group::gitaly
default_enabled: false
diff --git a/config/feature_flags/development/rugged_find_commit.yml b/config/feature_flags/development/rugged_find_commit.yml
index b84e056d9f5..723cad3f88a 100644
--- a/config/feature_flags/development/rugged_find_commit.yml
+++ b/config/feature_flags/development/rugged_find_commit.yml
@@ -2,6 +2,7 @@
name: rugged_find_commit
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
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
index 10093f2977f..e41c717a5fe 100644
--- a/config/feature_flags/development/rugged_list_commits_by_oid.yml
+++ b/config/feature_flags/development/rugged_list_commits_by_oid.yml
@@ -1,7 +1,8 @@
---
name: rugged_list_commits_by_oid
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27441
rollout_issue_url:
-group:
+milestone: '11.10'
type: development
+group: group::gitaly
default_enabled: false
diff --git a/config/feature_flags/development/rugged_tree_entries.yml b/config/feature_flags/development/rugged_tree_entries.yml
index 6ef296c43a6..b00f8bed00f 100644
--- a/config/feature_flags/development/rugged_tree_entries.yml
+++ b/config/feature_flags/development/rugged_tree_entries.yml
@@ -2,6 +2,7 @@
name: rugged_tree_entries
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/rugged_tree_entry.yml b/config/feature_flags/development/rugged_tree_entry.yml
index 8ae0a71960b..a78d6ffd21f 100644
--- a/config/feature_flags/development/rugged_tree_entry.yml
+++ b/config/feature_flags/development/rugged_tree_entry.yml
@@ -2,6 +2,7 @@
name: rugged_tree_entry
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/saml_group_links.yml b/config/feature_flags/development/saml_group_links.yml
new file mode 100644
index 00000000000..cb02b426b29
--- /dev/null
+++ b/config/feature_flags/development/saml_group_links.yml
@@ -0,0 +1,8 @@
+---
+name: saml_group_links
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45080
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/267020
+milestone: '13.6'
+type: development
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/development/save_raw_usage_data.yml b/config/feature_flags/development/save_raw_usage_data.yml
index b3c65c12e2d..44820fe2f53 100644
--- a/config/feature_flags/development/save_raw_usage_data.yml
+++ b/config/feature_flags/development/save_raw_usage_data.yml
@@ -1,7 +1,8 @@
---
name: save_raw_usage_data
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38457
-rollout_issue_url:
-group: group::product analytics
+rollout_issue_url:
+milestone: '13.3'
type: development
+group: group::product analytics
default_enabled: false
diff --git a/config/feature_flags/development/schema_linting.yml b/config/feature_flags/development/schema_linting.yml
index 3722f1dd97f..6c1cbdb5248 100644
--- a/config/feature_flags/development/schema_linting.yml
+++ b/config/feature_flags/development/schema_linting.yml
@@ -2,6 +2,7 @@
name: schema_linting
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35838
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/255919
-group: group::editor
+milestone: '13.2'
type: development
+group: group::editor
default_enabled: false
diff --git a/config/feature_flags/development/search_filter_by_confidential.yml b/config/feature_flags/development/search_filter_by_confidential.yml
deleted file mode 100644
index 0a952a4d25e..00000000000
--- a/config/feature_flags/development/search_filter_by_confidential.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: search_filter_by_confidential
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40793
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/244923
-group: group::global search
-type: development
-default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/search_track_unique_users.yml b/config/feature_flags/development/search_track_unique_users.yml
index a5d4940c96a..641636fd955 100644
--- a/config/feature_flags/development/search_track_unique_users.yml
+++ b/config/feature_flags/development/search_track_unique_users.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
+group: group::global search
default_enabled: true
diff --git a/config/feature_flags/development/security_auto_fix.yml b/config/feature_flags/development/security_auto_fix.yml
index b97220a1059..8cbb227728c 100644
--- a/config/feature_flags/development/security_auto_fix.yml
+++ b/config/feature_flags/development/security_auto_fix.yml
@@ -1,7 +1,8 @@
---
name: security_auto_fix
-introduced_by_url:
-rollout_issue_url:
-group: group::composition analysis
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30530
+rollout_issue_url:
+milestone: '13.0'
type: development
+group: group::composition analysis
default_enabled: false
diff --git a/config/feature_flags/development/security_on_demand_scans_http_header_validation.yml b/config/feature_flags/development/security_on_demand_scans_http_header_validation.yml
new file mode 100644
index 00000000000..475cbfa4d9a
--- /dev/null
+++ b/config/feature_flags/development/security_on_demand_scans_http_header_validation.yml
@@ -0,0 +1,8 @@
+---
+name: security_on_demand_scans_http_header_validation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42812
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276403
+milestone: '13.6'
+type: development
+group: group::dynamic analysis
+default_enabled: false
diff --git a/config/feature_flags/development/security_on_demand_scans_site_validation.yml b/config/feature_flags/development/security_on_demand_scans_site_validation.yml
index 27ec926d9ac..9085c22b773 100644
--- a/config/feature_flags/development/security_on_demand_scans_site_validation.yml
+++ b/config/feature_flags/development/security_on_demand_scans_site_validation.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
+group: group::dynamic analysis
default_enabled: false
diff --git a/config/feature_flags/development/serverless_domain.yml b/config/feature_flags/development/serverless_domain.yml
index f4821e5a14c..67b2c6b8e1a 100644
--- a/config/feature_flags/development/serverless_domain.yml
+++ b/config/feature_flags/development/serverless_domain.yml
@@ -2,6 +2,7 @@
name: serverless_domain
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21222
rollout_issue_url:
-group: group::configure
+milestone: '12.8'
type: development
+group: group::configure
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
index 13a9ef6f37a..8b248da00cd 100644
--- a/config/feature_flags/development/service_desk_custom_address.yml
+++ b/config/feature_flags/development/service_desk_custom_address.yml
@@ -2,6 +2,7 @@
name: service_desk_custom_address
introduced_by_url:
rollout_issue_url:
-group: group::certify
+milestone:
type: development
+group: group::certify
default_enabled: false
diff --git a/config/feature_flags/development/set_user_availability_status.yml b/config/feature_flags/development/set_user_availability_status.yml
new file mode 100644
index 00000000000..be3ff522ccc
--- /dev/null
+++ b/config/feature_flags/development/set_user_availability_status.yml
@@ -0,0 +1,8 @@
+---
+name: set_user_availability_status
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46844
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/281073
+milestone: '13.6'
+type: development
+group: group::optimize
+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
index 1a4815a3fb9..3b2fea80a2d 100644
--- a/config/feature_flags/development/settings_operations_prometheus_service.yml
+++ b/config/feature_flags/development/settings_operations_prometheus_service.yml
@@ -2,6 +2,7 @@
name: settings_operations_prometheus_service
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24296
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258560
-group: group::health
+milestone: '12.8'
type: development
+group: group::health
default_enabled: false
diff --git a/config/feature_flags/development/shared_group_membership_auth.yml b/config/feature_flags/development/shared_group_membership_auth.yml
new file mode 100644
index 00000000000..e6aaad9bbd6
--- /dev/null
+++ b/config/feature_flags/development/shared_group_membership_auth.yml
@@ -0,0 +1,8 @@
+---
+name: shared_group_membership_auth
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46412
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/224771
+milestone: '13.6'
+type: development
+group: group::access
+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
index 1f67392a306..7775bf5f27f 100644
--- a/config/feature_flags/development/show_author_on_note.yml
+++ b/config/feature_flags/development/show_author_on_note.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
-default_enabled: false \ No newline at end of file
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/show_inherited_labels.yml b/config/feature_flags/development/show_inherited_labels.yml
index 73ceb07002c..1ee1daaf0af 100644
--- a/config/feature_flags/development/show_inherited_labels.yml
+++ b/config/feature_flags/development/show_inherited_labels.yml
@@ -2,6 +2,7 @@
name: show_inherited_labels
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42960
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/267547
-group: group::project management
+milestone: '13.5'
type: development
+group: group::project management
default_enabled: true
diff --git a/config/feature_flags/development/similarity_search.yml b/config/feature_flags/development/similarity_search.yml
index f99e80b5cc7..312ab767eb0 100644
--- a/config/feature_flags/development/similarity_search.yml
+++ b/config/feature_flags/development/similarity_search.yml
@@ -2,6 +2,7 @@
name: similarity_search
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37300/
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38675
-group: group::analytics
+milestone: '13.3'
type: development
+group: group::analytics
default_enabled: true
diff --git a/config/feature_flags/development/snippet_spam.yml b/config/feature_flags/development/snippet_spam.yml
index 8215766fd3f..299a69fd68d 100644
--- a/config/feature_flags/development/snippet_spam.yml
+++ b/config/feature_flags/development/snippet_spam.yml
@@ -2,6 +2,7 @@
name: snippet_spam
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44010
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/262013
+milestone: '13.5'
type: development
group: group::editor
default_enabled: false
diff --git a/config/feature_flags/development/snippets.yml b/config/feature_flags/development/snippets.yml
index 14f37feaa3f..ee06c54e237 100644
--- a/config/feature_flags/development/snippets.yml
+++ b/config/feature_flags/development/snippets.yml
@@ -2,6 +2,7 @@
name: snippets
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/snippets_binary_blob.yml b/config/feature_flags/development/snippets_binary_blob.yml
index 6ab05b096ba..72a959858d9 100644
--- a/config/feature_flags/development/snippets_binary_blob.yml
+++ b/config/feature_flags/development/snippets_binary_blob.yml
@@ -1,7 +1,8 @@
---
name: snippets_binary_blob
-introduced_by_url:
-rollout_issue_url:
-group: group::editor
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37419
+rollout_issue_url:
+milestone: '13.3'
type: development
+group: group::editor
default_enabled: false
diff --git a/config/feature_flags/development/soft_email_confirmation.yml b/config/feature_flags/development/soft_email_confirmation.yml
index ee951d84ed8..60ebcf1ee50 100644
--- a/config/feature_flags/development/soft_email_confirmation.yml
+++ b/config/feature_flags/development/soft_email_confirmation.yml
@@ -1,7 +1,8 @@
---
name: soft_email_confirmation
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31245
-rollout_issue_url:
-group: group::acquisition
+rollout_issue_url:
+milestone: '12.2'
type: development
+group: group::acquisition
default_enabled: false
diff --git a/config/feature_flags/development/soft_fail_count_by_state.yml b/config/feature_flags/development/soft_fail_count_by_state.yml
deleted file mode 100644
index a8cd1a35e44..00000000000
--- a/config/feature_flags/development/soft_fail_count_by_state.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: soft_fail_count_by_state
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44184
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/263222
-type: development
-group: group::source code
-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
index 951ea4b315f..95ec7eff713 100644
--- a/config/feature_flags/development/specialized_project_authorization_project_share_worker.yml
+++ b/config/feature_flags/development/specialized_project_authorization_project_share_worker.yml
@@ -1,7 +1,8 @@
---
name: specialized_project_authorization_project_share_worker
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32864
-rollout_issue_url:
-group: group::access
+rollout_issue_url:
+milestone: '13.2'
type: development
+group: group::access
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
index 48372cac765..f3dbf09af14 100644
--- a/config/feature_flags/development/specialized_project_authorization_workers.yml
+++ b/config/feature_flags/development/specialized_project_authorization_workers.yml
@@ -1,7 +1,8 @@
---
name: specialized_project_authorization_workers
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31377
-rollout_issue_url:
-group: group::access
+rollout_issue_url:
+milestone: '13.0'
type: development
+group: group::access
default_enabled: false
diff --git a/config/feature_flags/development/sql_set_operators.yml b/config/feature_flags/development/sql_set_operators.yml
deleted file mode 100644
index 2098a19a24a..00000000000
--- a/config/feature_flags/development/sql_set_operators.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: sql_set_operators
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39786
-rollout_issue_url:
-group: group::access
-type: development
-default_enabled: false
diff --git a/config/feature_flags/development/squash_options.yml b/config/feature_flags/development/squash_options.yml
index 9ba5129b9a3..70114cfa252 100644
--- a/config/feature_flags/development/squash_options.yml
+++ b/config/feature_flags/development/squash_options.yml
@@ -1,7 +1,8 @@
---
name: squash_options
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33930
rollout_issue_url:
-group:
+milestone: '13.2'
type: development
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/sse_erb_support.yml b/config/feature_flags/development/sse_erb_support.yml
deleted file mode 100644
index 21a3ad2104b..00000000000
--- a/config/feature_flags/development/sse_erb_support.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: sse_erb_support
-introduced_by_url:
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/235460
-group: group::static site editor
-type: development
-default_enabled: false
diff --git a/config/feature_flags/development/sse_image_uploads.yml b/config/feature_flags/development/sse_image_uploads.yml
deleted file mode 100644
index 469af524c87..00000000000
--- a/config/feature_flags/development/sse_image_uploads.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: sse_image_uploads
-introduced_by_url:
-rollout_issue_url:
-group:
-type: development
-default_enabled: false
diff --git a/config/feature_flags/development/startup_css.yml b/config/feature_flags/development/startup_css.yml
index c87b2abc9a5..88a1cd77c95 100644
--- a/config/feature_flags/development/startup_css.yml
+++ b/config/feature_flags/development/startup_css.yml
@@ -2,6 +2,7 @@
name: startup_css
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39713
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/238718
-group: group::editor
+milestone: '13.3'
type: development
+group: group::editor
default_enabled: false
diff --git a/config/feature_flags/development/store_ci_pipeline_counts_by_status.yml b/config/feature_flags/development/store_ci_pipeline_counts_by_status.yml
deleted file mode 100644
index 62044bf855a..00000000000
--- a/config/feature_flags/development/store_ci_pipeline_counts_by_status.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: store_ci_pipeline_counts_by_status
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43027
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/254721
-type: development
-group: group::analytics
-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..69c14e24303
--- /dev/null
+++ b/config/feature_flags/development/suggest_pipeline.yml
@@ -0,0 +1,8 @@
+---
+name: suggest_pipeline
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45926
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/267492
+milestone: '13.6'
+type: development
+group: group::expansion
+default_enabled: true
diff --git a/config/feature_flags/development/sync_metrics_dashboards.yml b/config/feature_flags/development/sync_metrics_dashboards.yml
deleted file mode 100644
index 2dd8964121a..00000000000
--- a/config/feature_flags/development/sync_metrics_dashboards.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: sync_metrics_dashboards
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39658
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241793
-group: group::apm
-type: development
-default_enabled: false
diff --git a/config/feature_flags/development/test_failure_history.yml b/config/feature_flags/development/test_failure_history.yml
new file mode 100644
index 00000000000..4a0424aae9e
--- /dev/null
+++ b/config/feature_flags/development/test_failure_history.yml
@@ -0,0 +1,8 @@
+---
+name: test_failure_history
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45027
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268249
+milestone: '13.6'
+type: development
+group: group::testing
+default_enabled: false
diff --git a/config/feature_flags/development/track_editor_edit_actions.yml b/config/feature_flags/development/track_editor_edit_actions.yml
index a0a1a3ea873..d73307231a2 100644
--- a/config/feature_flags/development/track_editor_edit_actions.yml
+++ b/config/feature_flags/development/track_editor_edit_actions.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
+group: group::editor
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
index f80831e1b35..c755dac8e75 100644
--- a/config/feature_flags/development/track_issue_activity_actions.yml
+++ b/config/feature_flags/development/track_issue_activity_actions.yml
@@ -1,7 +1,8 @@
---
name: track_issue_activity_actions
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40904
-rollout_issue_url:
-group: group::project management
+rollout_issue_url:
+milestone: '13.4'
type: development
+group: group::project management
default_enabled: true
diff --git a/config/feature_flags/development/track_unique_test_cases_parsed.yml b/config/feature_flags/development/track_unique_test_cases_parsed.yml
deleted file mode 100644
index 98ae38e1cb0..00000000000
--- a/config/feature_flags/development/track_unique_test_cases_parsed.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: track_unique_test_cases_parsed
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41918
-rollout_issue_url:
-group: group::testing
-type: development
-default_enabled: false
diff --git a/config/feature_flags/development/track_unique_visits.yml b/config/feature_flags/development/track_unique_visits.yml
index 10f78a32492..80d969cc65b 100644
--- a/config/feature_flags/development/track_unique_visits.yml
+++ b/config/feature_flags/development/track_unique_visits.yml
@@ -2,6 +2,7 @@
name: track_unique_visits
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33146
rollout_issue_url:
-group: group::analytics
+milestone: '13.2'
type: development
+group: group::analytics
default_enabled: true
diff --git a/config/feature_flags/development/track_unique_wiki_page_views.yml b/config/feature_flags/development/track_unique_wiki_page_views.yml
index 0e8120635ab..eb2bf1304d9 100644
--- a/config/feature_flags/development/track_unique_wiki_page_views.yml
+++ b/config/feature_flags/development/track_unique_wiki_page_views.yml
@@ -2,6 +2,7 @@
name: track_unique_wiki_page_views
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44622
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/267162
+milestone: '13.5'
type: development
group: group::knowledge
default_enabled: true
diff --git a/config/feature_flags/development/tribute_autocomplete.yml b/config/feature_flags/development/tribute_autocomplete.yml
index 94cfc00c467..47fbd11f844 100644
--- a/config/feature_flags/development/tribute_autocomplete.yml
+++ b/config/feature_flags/development/tribute_autocomplete.yml
@@ -1,7 +1,8 @@
---
name: tribute_autocomplete
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32671
-rollout_issue_url:
-group: group::project management
+rollout_issue_url:
+milestone: '13.2'
type: development
+group: group::project management
default_enabled: false
diff --git a/config/feature_flags/development/two_factor_for_cli.yml b/config/feature_flags/development/two_factor_for_cli.yml
index f75264451e0..e442bb035cf 100644
--- a/config/feature_flags/development/two_factor_for_cli.yml
+++ b/config/feature_flags/development/two_factor_for_cli.yml
@@ -2,6 +2,7 @@
name: two_factor_for_cli
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39703
rollout_issue_url:
+milestone: '13.5'
type: development
group: group::access
default_enabled: false
diff --git a/config/feature_flags/development/unified_diff_components.yml b/config/feature_flags/development/unified_diff_components.yml
new file mode 100644
index 00000000000..63470c2a28d
--- /dev/null
+++ b/config/feature_flags/development/unified_diff_components.yml
@@ -0,0 +1,7 @@
+---
+name: unified_diff_components
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44974
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268039
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/unified_diff_lines.yml b/config/feature_flags/development/unified_diff_lines.yml
index d580ef65104..e295893acc4 100644
--- a/config/feature_flags/development/unified_diff_lines.yml
+++ b/config/feature_flags/development/unified_diff_lines.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml b/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml
index bfe3356cb8e..986f002aa1d 100644
--- a/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml
+++ b/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml
@@ -2,6 +2,7 @@
name: unlink_fork_network_upon_visibility_decrease
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
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
index 1c3545cb728..60a68005235 100644
--- a/config/feature_flags/development/upload_middleware_jwt_params_handler.yml
+++ b/config/feature_flags/development/upload_middleware_jwt_params_handler.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
+group: group::package
default_enabled: true
diff --git a/config/feature_flags/development/usage_data_a_compliance_audit_events_api.yml b/config/feature_flags/development/usage_data_a_compliance_audit_events_api.yml
index 8b2e8063164..1daf82b4b8a 100644
--- a/config/feature_flags/development/usage_data_a_compliance_audit_events_api.yml
+++ b/config/feature_flags/development/usage_data_a_compliance_audit_events_api.yml
@@ -2,6 +2,7 @@
name: usage_data_a_compliance_audit_events_api
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41689
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/233786
-group: group::compliance
+milestone: '13.4'
type: development
+group: group::compliance
default_enabled: false
diff --git a/config/feature_flags/development/usage_data_api.yml b/config/feature_flags/development/usage_data_api.yml
index 5c8e918521d..9ba8180eb5a 100644
--- a/config/feature_flags/development/usage_data_api.yml
+++ b/config/feature_flags/development/usage_data_api.yml
@@ -2,6 +2,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/267114
-group: group::product analytics
+milestone: '13.4'
type: development
+group: group::product analytics
default_enabled: true
diff --git a/config/feature_flags/development/usage_data_g_compliance_dashboard.yml b/config/feature_flags/development/usage_data_g_compliance_dashboard.yml
index 24d6f81740b..fcef95c2b01 100644
--- a/config/feature_flags/development/usage_data_g_compliance_dashboard.yml
+++ b/config/feature_flags/development/usage_data_g_compliance_dashboard.yml
@@ -1,7 +1,8 @@
---
name: usage_data_g_compliance_dashboard
-introduced_by_url:
-rollout_issue_url:
-group: group::compliance
+introduced_by_url:
+rollout_issue_url:
+milestone:
type: development
+group: group::compliance
default_enabled: false
diff --git a/config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml b/config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml
new file mode 100644
index 00000000000..58a28139a35
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_ci_secrets_management_vault_build_created
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46515
+rollout_issue_url:
+milestone: '13.6'
+type: development
+group: group::release management
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_source_code_code_intelligence.yml b/config/feature_flags/development/usage_data_i_source_code_code_intelligence.yml
index 15ce7194264..5e4eb0d61af 100644
--- a/config/feature_flags/development/usage_data_i_source_code_code_intelligence.yml
+++ b/config/feature_flags/development/usage_data_i_source_code_code_intelligence.yml
@@ -1,7 +1,8 @@
---
name: usage_data_i_source_code_code_intelligence
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41881
-rollout_issue_url:
-group: group::source code
+rollout_issue_url:
+milestone: '13.4'
type: development
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_testing_test_case_parsed.yml b/config/feature_flags/development/usage_data_i_testing_test_case_parsed.yml
index 095010da56b..e6e3cd09c28 100644
--- a/config/feature_flags/development/usage_data_i_testing_test_case_parsed.yml
+++ b/config/feature_flags/development/usage_data_i_testing_test_case_parsed.yml
@@ -1,7 +1,8 @@
---
name: usage_data_i_testing_test_case_parsed
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41918
-rollout_issue_url:
-group: group::testing
+rollout_issue_url:
+milestone: '13.5'
type: development
+group: group::testing
default_enabled: true
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
index a50a3eafa1a..c3e59a0c323 100644
--- a/config/feature_flags/development/usage_data_incident_management_alert_assigned.yml
+++ b/config/feature_flags/development/usage_data_incident_management_alert_assigned.yml
@@ -2,6 +2,7 @@
name: usage_data_incident_management_alert_assigned
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
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
index 957e316e153..c858de35d56 100644
--- 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
@@ -2,6 +2,7 @@
name: usage_data_incident_management_alert_status_changed
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
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
index 5e64899978a..198289db02d 100644
--- a/config/feature_flags/development/usage_data_incident_management_alert_todo.yml
+++ b/config/feature_flags/development/usage_data_incident_management_alert_todo.yml
@@ -2,6 +2,7 @@
name: usage_data_incident_management_alert_todo
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
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
index a582a44a3e2..1b5b2d1f8a0 100644
--- a/config/feature_flags/development/usage_data_incident_management_incident_assigned.yml
+++ b/config/feature_flags/development/usage_data_incident_management_incident_assigned.yml
@@ -2,6 +2,7 @@
name: usage_data_incident_management_incident_assigned
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
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
index ad482676132..9eff79d3d4a 100644
--- 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
@@ -2,6 +2,7 @@
name: usage_data_incident_management_incident_change_confidential
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
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
index 943b7a83e5e..1e857525d06 100644
--- a/config/feature_flags/development/usage_data_incident_management_incident_closed.yml
+++ b/config/feature_flags/development/usage_data_incident_management_incident_closed.yml
@@ -2,6 +2,7 @@
name: usage_data_incident_management_incident_closed
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
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
index 5d173e1e869..c562501fdad 100644
--- a/config/feature_flags/development/usage_data_incident_management_incident_comment.yml
+++ b/config/feature_flags/development/usage_data_incident_management_incident_comment.yml
@@ -2,6 +2,7 @@
name: usage_data_incident_management_incident_comment
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
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
index 86e47d54d18..d6c4a082714 100644
--- a/config/feature_flags/development/usage_data_incident_management_incident_created.yml
+++ b/config/feature_flags/development/usage_data_incident_management_incident_created.yml
@@ -2,6 +2,7 @@
name: usage_data_incident_management_incident_created
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
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
index 84ba0d34cc7..d9a9f9f5e5e 100644
--- a/config/feature_flags/development/usage_data_incident_management_incident_relate.yml
+++ b/config/feature_flags/development/usage_data_incident_management_incident_relate.yml
@@ -2,6 +2,7 @@
name: usage_data_incident_management_incident_relate
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
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
index ed71d353cfe..1cc30a4683e 100644
--- a/config/feature_flags/development/usage_data_incident_management_incident_reopened.yml
+++ b/config/feature_flags/development/usage_data_incident_management_incident_reopened.yml
@@ -2,6 +2,7 @@
name: usage_data_incident_management_incident_reopened
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
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
index aa400fb4455..414f47e1137 100644
--- a/config/feature_flags/development/usage_data_incident_management_incident_todo.yml
+++ b/config/feature_flags/development/usage_data_incident_management_incident_todo.yml
@@ -2,6 +2,7 @@
name: usage_data_incident_management_incident_todo
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
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
index 5798331175e..a09b8bf2f3f 100644
--- a/config/feature_flags/development/usage_data_incident_management_incident_unrelate.yml
+++ b/config/feature_flags/development/usage_data_incident_management_incident_unrelate.yml
@@ -2,6 +2,7 @@
name: usage_data_incident_management_incident_unrelate
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
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
index 921c466a167..7d3a9bbff39 100644
--- 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
@@ -2,6 +2,7 @@
name: usage_data_incident_management_incident_zoom_meeting
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40475
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: group::health
+milestone: '13.4'
type: development
+group: group::health
default_enabled: true
diff --git a/config/feature_flags/development/use_workhorse_s3_client.yml b/config/feature_flags/development/use_workhorse_s3_client.yml
index dd152996c0c..7f14d51a66c 100644
--- a/config/feature_flags/development/use_workhorse_s3_client.yml
+++ b/config/feature_flags/development/use_workhorse_s3_client.yml
@@ -1,7 +1,8 @@
---
name: use_workhorse_s3_client
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35480
rollout_issue_url:
-group:
+milestone: '13.2'
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/user_group_counts.yml b/config/feature_flags/development/user_group_counts.yml
new file mode 100644
index 00000000000..98798ea3ead
--- /dev/null
+++ b/config/feature_flags/development/user_group_counts.yml
@@ -0,0 +1,8 @@
+---
+name: user_group_counts
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44069/
+rollout_issue_url:
+milestone: '13.6'
+type: development
+group: group::compliance
+default_enabled: false
diff --git a/config/feature_flags/development/user_mode_in_session.yml b/config/feature_flags/development/user_mode_in_session.yml
index 2a373ece4f4..a3c4d44e4ce 100644
--- a/config/feature_flags/development/user_mode_in_session.yml
+++ b/config/feature_flags/development/user_mode_in_session.yml
@@ -2,6 +2,7 @@
name: user_mode_in_session
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/user_time_settings.yml b/config/feature_flags/development/user_time_settings.yml
index a63f229f903..eaeb7f17794 100644
--- a/config/feature_flags/development/user_time_settings.yml
+++ b/config/feature_flags/development/user_time_settings.yml
@@ -2,6 +2,7 @@
name: user_time_settings
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/validate_import_decompressed_archive_size.yml b/config/feature_flags/development/validate_import_decompressed_archive_size.yml
index 3e575657a78..644a936a67c 100644
--- a/config/feature_flags/development/validate_import_decompressed_archive_size.yml
+++ b/config/feature_flags/development/validate_import_decompressed_archive_size.yml
@@ -1,7 +1,8 @@
---
name: validate_import_decompressed_archive_size
-introduced_by_url:
-rollout_issue_url:
-group: group::import
+introduced_by_url:
+rollout_issue_url:
+milestone:
type: development
+group: group::import
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
index 2ac8a7c3087..1af945bf30b 100644
--- a/config/feature_flags/development/view_diffs_file_by_file.yml
+++ b/config/feature_flags/development/view_diffs_file_by_file.yml
@@ -2,6 +2,7 @@
name: view_diffs_file_by_file
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35223
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229848
-group: group::source code
+milestone: '13.2'
type: development
+group: group::source code
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
index c5a5ad638e4..d864f904992 100644
--- a/config/feature_flags/development/vue_group_members_list.yml
+++ b/config/feature_flags/development/vue_group_members_list.yml
@@ -2,6 +2,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
+milestone: '13.4'
type: development
-default_enabled: false \ No newline at end of file
+group: group::access
+default_enabled: true
diff --git a/config/feature_flags/development/vue_issuable_sidebar.yml b/config/feature_flags/development/vue_issuable_sidebar.yml
index 01c8bc3460b..47c17db1206 100644
--- a/config/feature_flags/development/vue_issuable_sidebar.yml
+++ b/config/feature_flags/development/vue_issuable_sidebar.yml
@@ -1,7 +1,8 @@
---
name: vue_issuable_sidebar
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18199
-rollout_issue_url:
-group: group::project management
+rollout_issue_url:
+milestone: '12.4'
type: development
+group: group::project management
default_enabled: false
diff --git a/config/feature_flags/development/vue_issuables_list.yml b/config/feature_flags/development/vue_issuables_list.yml
index 5fe5c7e3e9f..75ef82999ca 100644
--- a/config/feature_flags/development/vue_issuables_list.yml
+++ b/config/feature_flags/development/vue_issuables_list.yml
@@ -2,6 +2,7 @@
name: vue_issuables_list
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15091
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/208093
-group: group::project management
+milestone: '12.5'
type: development
+group: group::project management
default_enabled: false
diff --git a/config/feature_flags/development/vue_issue_header.yml b/config/feature_flags/development/vue_issue_header.yml
new file mode 100644
index 00000000000..6e9de057b82
--- /dev/null
+++ b/config/feature_flags/development/vue_issue_header.yml
@@ -0,0 +1,8 @@
+---
+name: vue_issue_header
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44440
+rollout_issue_url:
+milestone: '13.6'
+type: development
+group: group::project management
+default_enabled: true
diff --git a/config/feature_flags/development/web_ide_primary_edit.yml b/config/feature_flags/development/web_ide_primary_edit.yml
index 33e3db0322b..5a609ae1d88 100644
--- a/config/feature_flags/development/web_ide_primary_edit.yml
+++ b/config/feature_flags/development/web_ide_primary_edit.yml
@@ -2,6 +2,7 @@
name: web_ide_primary_edit
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35957
rollout_issue_url:
-group: group::editor
+milestone: '13.3'
type: development
+group: group::editor
default_enabled: false
diff --git a/config/feature_flags/development/webauthn.yml b/config/feature_flags/development/webauthn.yml
index 7b360e884ae..5339074e84a 100644
--- a/config/feature_flags/development/webauthn.yml
+++ b/config/feature_flags/development/webauthn.yml
@@ -1,7 +1,8 @@
---
name: webauthn
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26692
rollout_issue_url:
-group:
+milestone: '13.4'
type: development
+group: group::access
default_enabled: false
diff --git a/config/feature_flags/development/webperf_experiment.yml b/config/feature_flags/development/webperf_experiment.yml
index 16f1f0ac773..50408df0555 100644
--- a/config/feature_flags/development/webperf_experiment.yml
+++ b/config/feature_flags/development/webperf_experiment.yml
@@ -1,7 +1,8 @@
---
name: webperf_experiment
-introduced_by_url:
-rollout_issue_url:
-group: group::editor
+introduced_by_url:
+rollout_issue_url:
+milestone:
type: development
+group: group::editor
default_enabled: false
diff --git a/config/feature_flags/development/whats_new_drawer.yml b/config/feature_flags/development/whats_new_drawer.yml
index d6b7ffbbb57..c06dfbe1fe6 100644
--- a/config/feature_flags/development/whats_new_drawer.yml
+++ b/config/feature_flags/development/whats_new_drawer.yml
@@ -2,6 +2,7 @@
name: whats_new_drawer
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38975
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/254186
-group: group::retention
+milestone: '13.3'
type: development
+group: group::retention
default_enabled: false
diff --git a/config/feature_flags/development/widget_visibility_polling.yml b/config/feature_flags/development/widget_visibility_polling.yml
index 711d4be2fd1..4cab4a73f8b 100644
--- a/config/feature_flags/development/widget_visibility_polling.yml
+++ b/config/feature_flags/development/widget_visibility_polling.yml
@@ -1,7 +1,8 @@
---
name: widget_visibility_polling
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29318
-rollout_issue_url:
-group: group::source code
+rollout_issue_url:
+milestone: '12.10'
type: development
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/wiki.yml b/config/feature_flags/development/wiki.yml
index 9f36fd7c6aa..5904e6838f3 100644
--- a/config/feature_flags/development/wiki.yml
+++ b/config/feature_flags/development/wiki.yml
@@ -2,6 +2,7 @@
name: wiki
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: true
diff --git a/config/feature_flags/development/wiki_front_matter.yml b/config/feature_flags/development/wiki_front_matter.yml
index 6b388aaa5d2..66add349c44 100644
--- a/config/feature_flags/development/wiki_front_matter.yml
+++ b/config/feature_flags/development/wiki_front_matter.yml
@@ -2,6 +2,7 @@
name: wiki_front_matter
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
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
index b708d21ad89..e7871d9062b 100644
--- a/config/feature_flags/development/workhorse_archive_cache_disabled.yml
+++ b/config/feature_flags/development/workhorse_archive_cache_disabled.yml
@@ -2,6 +2,7 @@
name: workhorse_archive_cache_disabled
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: development
+group:
default_enabled: false
diff --git a/config/feature_flags/development/zip_pages_deployments.yml b/config/feature_flags/development/zip_pages_deployments.yml
index 3bafc2aae14..34aa5c03fdc 100644
--- a/config/feature_flags/development/zip_pages_deployments.yml
+++ b/config/feature_flags/development/zip_pages_deployments.yml
@@ -2,6 +2,7 @@
name: zip_pages_deployments
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42834
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/245308
-group: group::release management
+milestone: '13.5'
type: development
-default_enabled: false \ No newline at end of file
+group: group::release management
+default_enabled: true
diff --git a/config/feature_flags/licensed/incident_sla.yml b/config/feature_flags/licensed/incident_sla.yml
deleted file mode 100644
index e59251dd82f..00000000000
--- a/config/feature_flags/licensed/incident_sla.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: incident_sla
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43648
-rollout_issue_url:
-group: group::health
-type: licensed
-default_enabled: true
diff --git a/config/feature_flags/licensed/minimal_access_role.yml b/config/feature_flags/licensed/minimal_access_role.yml
deleted file mode 100644
index ca27b86d35f..00000000000
--- a/config/feature_flags/licensed/minimal_access_role.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: minimal_access_role
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40942
-rollout_issue_url:
-group: group::access
-type: licensed
-default_enabled: true
diff --git a/config/feature_flags/licensed/resource_access_token.yml b/config/feature_flags/licensed/resource_access_token.yml
deleted file mode 100644
index c236851881d..00000000000
--- a/config/feature_flags/licensed/resource_access_token.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: resource_access_token
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29622
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/235765
-group: group::access
-type: licensed
-default_enabled: true
diff --git a/config/feature_flags/ops/api_kaminari_count_with_limit.yml b/config/feature_flags/ops/api_kaminari_count_with_limit.yml
index 1fdeaa53b83..a987d5c65b1 100644
--- a/config/feature_flags/ops/api_kaminari_count_with_limit.yml
+++ b/config/feature_flags/ops/api_kaminari_count_with_limit.yml
@@ -1,7 +1,8 @@
---
name: api_kaminari_count_with_limit
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23931
-rollout_issue_url:
-group: group::ecosystem
+rollout_issue_url:
+milestone: '11.8'
type: ops
+group: group::ecosystem
default_enabled: false
diff --git a/config/feature_flags/ops/ci_accept_trace.yml b/config/feature_flags/ops/ci_accept_trace.yml
index 8671f42c3c1..2574e12f4f2 100644
--- a/config/feature_flags/ops/ci_accept_trace.yml
+++ b/config/feature_flags/ops/ci_accept_trace.yml
@@ -1,7 +1,8 @@
---
name: ci_accept_trace
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41304
-rollout_issue_url:
-group: group::continuous integration
+rollout_issue_url:
+milestone: '13.4'
type: ops
+group: group::continuous integration
default_enabled: true
diff --git a/config/feature_flags/ops/ci_trace_log_invalid_chunks.yml b/config/feature_flags/ops/ci_trace_log_invalid_chunks.yml
index f5e8bbae258..2deb3f42995 100644
--- a/config/feature_flags/ops/ci_trace_log_invalid_chunks.yml
+++ b/config/feature_flags/ops/ci_trace_log_invalid_chunks.yml
@@ -1,7 +1,8 @@
---
name: ci_trace_log_invalid_chunks
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44409
-rollout_issue_url:
+rollout_issue_url:
+milestone: '13.5'
type: ops
group: group::continuous integration
default_enabled: false
diff --git a/config/feature_flags/ops/ci_trace_overwrite.yml b/config/feature_flags/ops/ci_trace_overwrite.yml
index 7996b957262..36caa9f6134 100644
--- a/config/feature_flags/ops/ci_trace_overwrite.yml
+++ b/config/feature_flags/ops/ci_trace_overwrite.yml
@@ -2,6 +2,7 @@
name: ci_trace_overwrite
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41304
rollout_issue_url:
-group: group::continuous integration
+milestone: '13.4'
type: ops
-default_enabled: false \ No newline at end of file
+group: group::continuous integration
+default_enabled: false
diff --git a/config/feature_flags/ops/database_reindexing.yml b/config/feature_flags/ops/database_reindexing.yml
index ea000a052db..fb0c29393f5 100644
--- a/config/feature_flags/ops/database_reindexing.yml
+++ b/config/feature_flags/ops/database_reindexing.yml
@@ -1,7 +1,8 @@
---
name: database_reindexing
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42705
-rollout_issue_url:
-group: group::database
+rollout_issue_url:
+milestone: '13.5'
type: ops
-default_enabled: false \ No newline at end of file
+group: group::database
+default_enabled: false
diff --git a/config/feature_flags/ops/dynamic_image_resizing.yml b/config/feature_flags/ops/dynamic_image_resizing.yml
new file mode 100644
index 00000000000..f456fa8bf1e
--- /dev/null
+++ b/config/feature_flags/ops/dynamic_image_resizing.yml
@@ -0,0 +1,8 @@
+---
+name: dynamic_image_resizing
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45050
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/266986
+milestone: '13.6'
+type: ops
+group: group::memory
+default_enabled: true
diff --git a/config/feature_flags/ops/gitlab_sidekiq_enable_semi_reliable_fetcher.yml b/config/feature_flags/ops/gitlab_sidekiq_enable_semi_reliable_fetcher.yml
index 680f8201d27..4d6eedb840a 100644
--- a/config/feature_flags/ops/gitlab_sidekiq_enable_semi_reliable_fetcher.yml
+++ b/config/feature_flags/ops/gitlab_sidekiq_enable_semi_reliable_fetcher.yml
@@ -1,7 +1,8 @@
---
name: gitlab_sidekiq_enable_semi_reliable_fetcher
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23854
rollout_issue_url:
-group:
+milestone: '11.6'
type: ops
+group: group::geo
default_enabled: true
diff --git a/config/feature_flags/ops/gitlab_sidekiq_reliable_fetcher.yml b/config/feature_flags/ops/gitlab_sidekiq_reliable_fetcher.yml
index ae395e19384..d7db6a38775 100644
--- a/config/feature_flags/ops/gitlab_sidekiq_reliable_fetcher.yml
+++ b/config/feature_flags/ops/gitlab_sidekiq_reliable_fetcher.yml
@@ -2,6 +2,7 @@
name: gitlab_sidekiq_reliable_fetcher
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: ops
+group:
default_enabled: true
diff --git a/config/feature_flags/ops/kubernetes_agent_internal_api.yml b/config/feature_flags/ops/kubernetes_agent_internal_api.yml
index f1dfdbb3950..34731aaeb52 100644
--- a/config/feature_flags/ops/kubernetes_agent_internal_api.yml
+++ b/config/feature_flags/ops/kubernetes_agent_internal_api.yml
@@ -1,7 +1,8 @@
---
name: kubernetes_agent_internal_api
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41045
-rollout_issue_url:
-group: group::configure
+rollout_issue_url:
+milestone: '13.4'
type: ops
+group: group::configure
default_enabled: true
diff --git a/config/feature_flags/ops/marginalia.yml b/config/feature_flags/ops/marginalia.yml
index a5d64c48b27..fb82f274eb2 100644
--- a/config/feature_flags/ops/marginalia.yml
+++ b/config/feature_flags/ops/marginalia.yml
@@ -2,6 +2,7 @@
name: marginalia
introduced_by_url:
rollout_issue_url:
-group:
+milestone:
type: ops
+group:
default_enabled: false
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index de389514cce..ae9475aa60d 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -317,6 +317,7 @@ production: &base
## Packages (maven repository, npm registry, etc...)
packages:
enabled: true
+ dpkg_deb_path: /usr/bin/dpkg-deb
# The location where build packages are stored (default: shared/packages).
# storage_path: shared/packages
object_store:
@@ -434,7 +435,7 @@ production: &base
cron: "19 * * * *"
# Remove expired build artifacts
expire_build_artifacts_worker:
- cron: "50 * * * *"
+ cron: "*/7 * * * *"
# Remove files from object storage
ci_schedule_delete_objects_worker:
cron: "*/16 * * * *"
@@ -1212,6 +1213,9 @@ production: &base
## Google analytics. Uncomment if you want it
# google_analytics_id: '_your_tracking_id'
+ ## Google tag manager
+ # google_tag_manager_id: '_your_tracking_id'
+
## Piwik analytics.
# piwik_url: '_your_piwik_url'
# piwik_site_id: '_your_piwik_site_id'
diff --git a/config/initializers/0_inject_feature_flags.rb b/config/initializers/0_inject_feature_flags.rb
index 5b33b3bb4ea..74470a6cbfc 100644
--- a/config/initializers/0_inject_feature_flags.rb
+++ b/config/initializers/0_inject_feature_flags.rb
@@ -4,3 +4,42 @@
Feature.register_feature_groups
Feature.register_definitions
Feature.register_hot_reloader unless Rails.configuration.cache_classes
+
+# This disallows usage of licensed feature names with the same name
+# as feature flags. This naming collision creates confusion and it was
+# decided to be removed in favor of explicit check.
+# https://gitlab.com/gitlab-org/gitlab/-/issues/259611
+if Gitlab.ee? && Gitlab.dev_or_test_env?
+ # These are the names of feature flags that do violate the constraint of
+ # being unique to licensed names. These feature flags should be reworked to
+ # be "development" with explicit check
+ IGNORED_FEATURE_FLAGS = %i[
+ swimlanes
+ ].to_set
+
+ # First, we validate a list of overrides to ensure that these overrides
+ # are removed if feature flag is gone
+ missing_feature_flags = IGNORED_FEATURE_FLAGS.reject do |feature_flag|
+ Feature::Definition.definitions[feature_flag]
+ end
+
+ if missing_feature_flags.any?
+ raise "The following feature flags were added as an override for discovering licensed features. " \
+ "Since these feature flags seems to be gone, ensure to remove them from \`IGNORED_FEATURE_FLAGS\` " \
+ "in \`#{__FILE__}'`: #{missing_feature_flags.join(", ")}"
+ end
+
+ # Second, we validate that there's no feature flag under the name as licensed feature
+ # flag, to ensure that the name used, is unique
+ licensed_features = License::PLANS_BY_FEATURE.keys.select do |licensed_feature_name|
+ IGNORED_FEATURE_FLAGS.exclude?(licensed_feature_name) &&
+ Feature::Definition.definitions[licensed_feature_name]
+ end
+
+ if licensed_features.any?
+ raise "The following feature flags do use a licensed feature. " \
+ "To avoid the confusion between their usage it is disallowed to use feature flag " \
+ "with exact the same name as licensed feature name. Use a different name to create " \
+ "a distinction: #{licensed_features.join(", ")}"
+ end
+end
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index affbc85d5a9..022f372a608 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -198,7 +198,7 @@ Settings.gitlab.default_projects_features['snippets'] = true if Settin
Settings.gitlab.default_projects_features['builds'] = true if Settings.gitlab.default_projects_features['builds'].nil?
Settings.gitlab.default_projects_features['container_registry'] = true if Settings.gitlab.default_projects_features['container_registry'].nil?
Settings.gitlab.default_projects_features['visibility_level'] = Settings.__send__(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE)
-Settings.gitlab['domain_whitelist'] ||= []
+Settings.gitlab['domain_allowlist'] ||= []
Settings.gitlab['import_sources'] ||= Gitlab::ImportSources.values
Settings.gitlab['trusted_proxies'] ||= []
Settings.gitlab['content_security_policy'] ||= Gitlab::ContentSecurityPolicy::ConfigLoader.default_settings_hash
@@ -354,25 +354,24 @@ Settings.uploads['object_store']['remote_directory'] ||= 'uploads'
# Packages
#
Settings['packages'] ||= Settingslogic.new({})
-Settings.packages['enabled'] = true if Settings.packages['enabled'].nil?
-Settings.packages['storage_path'] = Settings.absolute(Settings.packages['storage_path'] || File.join(Settings.shared['path'], "packages"))
-Settings.packages['object_store'] = ObjectStoreSettings.legacy_parse(Settings.packages['object_store'])
+Settings.packages['enabled'] = true if Settings.packages['enabled'].nil?
+Settings.packages['dpkg_deb_path'] = '/usr/bin/dpkg-deb' if Settings.packages['dpkg_deb_path'].nil?
+Settings.packages['storage_path'] = Settings.absolute(Settings.packages['storage_path'] || File.join(Settings.shared['path'], "packages"))
+Settings.packages['object_store'] = ObjectStoreSettings.legacy_parse(Settings.packages['object_store'])
#
# Dependency Proxy
#
-Gitlab.ee do
- Settings['dependency_proxy'] ||= Settingslogic.new({})
- Settings.dependency_proxy['enabled'] = true if Settings.dependency_proxy['enabled'].nil?
- Settings.dependency_proxy['storage_path'] = Settings.absolute(Settings.dependency_proxy['storage_path'] || File.join(Settings.shared['path'], "dependency_proxy"))
- Settings.dependency_proxy['object_store'] = ObjectStoreSettings.legacy_parse(Settings.dependency_proxy['object_store'])
-
- # For first iteration dependency proxy uses Rails server to download blobs.
- # To ensure acceptable performance we only allow feature to be used with
- # multithreaded web-server Puma. This will be removed once download logic is moved
- # to GitLab workhorse
- Settings.dependency_proxy['enabled'] = false unless Gitlab::Runtime.puma?
-end
+Settings['dependency_proxy'] ||= Settingslogic.new({})
+Settings.dependency_proxy['enabled'] = true if Settings.dependency_proxy['enabled'].nil?
+Settings.dependency_proxy['storage_path'] = Settings.absolute(Settings.dependency_proxy['storage_path'] || File.join(Settings.shared['path'], "dependency_proxy"))
+Settings.dependency_proxy['object_store'] = ObjectStoreSettings.legacy_parse(Settings.dependency_proxy['object_store'])
+
+# For first iteration dependency proxy uses Rails server to download blobs.
+# To ensure acceptable performance we only allow feature to be used with
+# multithreaded web-server Puma. This will be removed once download logic is moved
+# to GitLab workhorse
+Settings.dependency_proxy['enabled'] = false unless Gitlab::Runtime.puma?
#
# Terraform state
@@ -414,7 +413,7 @@ Settings.cron_jobs['pipeline_schedule_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['pipeline_schedule_worker']['cron'] ||= '19 * * * *'
Settings.cron_jobs['pipeline_schedule_worker']['job_class'] = 'PipelineScheduleWorker'
Settings.cron_jobs['expire_build_artifacts_worker'] ||= Settingslogic.new({})
-Settings.cron_jobs['expire_build_artifacts_worker']['cron'] ||= '50 * * * *'
+Settings.cron_jobs['expire_build_artifacts_worker']['cron'] ||= '*/7 * * * *'
Settings.cron_jobs['expire_build_artifacts_worker']['job_class'] = 'ExpireBuildArtifactsWorker'
Settings.cron_jobs['ci_schedule_delete_objects_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['ci_schedule_delete_objects_worker']['cron'] ||= '*/16 * * * *'
@@ -530,6 +529,9 @@ Settings.cron_jobs['analytics_instance_statistics_count_job_trigger_worker']['jo
Settings.cron_jobs['member_invitation_reminder_emails_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['member_invitation_reminder_emails_worker']['cron'] ||= '0 0 * * *'
Settings.cron_jobs['member_invitation_reminder_emails_worker']['job_class'] = 'MemberInvitationReminderEmailsWorker'
+Settings.cron_jobs['schedule_merge_request_cleanup_refs_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['schedule_merge_request_cleanup_refs_worker']['cron'] ||= '* * * * *'
+Settings.cron_jobs['schedule_merge_request_cleanup_refs_worker']['job_class'] = 'ScheduleMergeRequestCleanupRefsWorker'
Gitlab.ee do
Settings.cron_jobs['active_user_count_threshold_worker'] ||= Settingslogic.new({})
@@ -604,6 +606,9 @@ Gitlab.ee do
Settings.cron_jobs['elastic_remove_expired_namespace_subscriptions_from_index_cron_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['elastic_remove_expired_namespace_subscriptions_from_index_cron_worker']['cron'] ||= '10 3 * * *'
Settings.cron_jobs['elastic_remove_expired_namespace_subscriptions_from_index_cron_worker']['job_class'] ||= 'ElasticRemoveExpiredNamespaceSubscriptionsFromIndexCronWorker'
+ Settings.cron_jobs['elastic_migration_worker'] ||= Settingslogic.new({})
+ Settings.cron_jobs['elastic_migration_worker']['cron'] ||= '*/30 * * * *'
+ Settings.cron_jobs['elastic_migration_worker']['job_class'] ||= 'Elastic::MigrationWorker'
Settings.cron_jobs['sync_seat_link_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['sync_seat_link_worker']['cron'] ||= "#{rand(60)} 0 * * *"
Settings.cron_jobs['sync_seat_link_worker']['job_class'] = 'SyncSeatLinkWorker'
diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb
index dbaebc83658..65ff6b656b9 100644
--- a/config/initializers/7_prometheus_metrics.rb
+++ b/config/initializers/7_prometheus_metrics.rb
@@ -70,7 +70,7 @@ if !Rails.env.test? && Gitlab::Metrics.prometheus_metrics_enabled?
Gitlab::Metrics.gauge(:deployments, 'GitLab Version', {}, :max).set({ version: Gitlab::VERSION }, 1)
unless Gitlab::Runtime.sidekiq?
- Gitlab::Metrics::RequestsRackMiddleware.initialize_http_request_duration_seconds
+ Gitlab::Metrics::RequestsRackMiddleware.initialize_metrics
end
rescue IOError => e
Gitlab::ErrorTracking.track_exception(e)
diff --git a/config/initializers/console_message.rb b/config/initializers/console_message.rb
index 523a3898043..fe47195062b 100644
--- a/config/initializers/console_message.rb
+++ b/config/initializers/console_message.rb
@@ -4,6 +4,7 @@ if Gitlab::Runtime.console?
justify = 15
puts '-' * 80
+ puts " Ruby:".ljust(justify) + RUBY_DESCRIPTION
puts " GitLab:".ljust(justify) + "#{Gitlab::VERSION} (#{Gitlab.revision}) #{Gitlab.ee? ? 'EE' : 'FOSS'}"
puts " GitLab Shell:".ljust(justify) + "#{Gitlab::VersionInfo.parse(Gitlab::Shell.version)}"
@@ -19,4 +20,15 @@ if Gitlab::Runtime.console?
end
puts '-' * 80
+
+ # Stop irb from writing a history file by default.
+ module IrbNoHistory
+ def init_config(*)
+ super
+
+ IRB.conf[:SAVE_HISTORY] = false
+ end
+ end
+
+ IRB.singleton_class.prepend(IrbNoHistory)
end
diff --git a/config/initializers/grape_validators.rb b/config/initializers/grape_validators.rb
index 22f2c9ecf92..715949a276f 100644
--- a/config/initializers/grape_validators.rb
+++ b/config/initializers/grape_validators.rb
@@ -8,3 +8,4 @@ Grape::Validations.register_validator(:integer_none_any, ::API::Validations::Val
Grape::Validations.register_validator(:array_none_any, ::API::Validations::Validators::ArrayNoneAny)
Grape::Validations.register_validator(:check_assignees_count, ::API::Validations::Validators::CheckAssigneesCount)
Grape::Validations.register_validator(:untrusted_regexp, ::API::Validations::Validators::UntrustedRegexp)
+Grape::Validations.register_validator(:email_or_email_list, ::API::Validations::Validators::EmailOrEmailList)
diff --git a/config/initializers/labkit_middleware.rb b/config/initializers/labkit_middleware.rb
index ea4103f052f..748666b6cd7 100644
--- a/config/initializers/labkit_middleware.rb
+++ b/config/initializers/labkit_middleware.rb
@@ -1,3 +1,36 @@
# frozen_string_literal: true
-Rails.application.config.middleware.use(Labkit::Middleware::Rack)
+# partial backport of https://github.com/rails/rails/pull/38169
+# this is in order to be able to re-order rack middlewares.
+
+if ActionDispatch::MiddlewareStack.method_defined?(:move)
+ warn "`move` is now defined in in ActionDispatch itself: https://github.com/rails/rails/pull/38169, please remove this patch from #{__FILE__}"
+else
+ module ActionDispatch
+ class MiddlewareStack
+ def move(target, source)
+ source_index = assert_index(source, :before)
+ source_middleware = middlewares.delete_at(source_index)
+
+ target_index = assert_index(target, :before)
+ middlewares.insert(target_index, source_middleware)
+ end
+ end
+ end
+end
+
+unless Rails::Configuration::MiddlewareStackProxy.method_defined?(:move)
+ module Rails
+ module Configuration
+ class MiddlewareStackProxy
+ def move(*args, &block)
+ @operations << ->(middleware) { middleware.send(__method__, *args, &block) }
+ end
+ ruby2_keywords(:move) if respond_to?(:ruby2_keywords, true)
+ end
+ end
+ end
+end
+
+Rails.application.config.middleware.move(1, ActionDispatch::RequestId)
+Rails.application.config.middleware.insert_after(ActionDispatch::RequestId, Labkit::Middleware::Rack)
diff --git a/config/initializers/rack_attack.rb b/config/initializers/rack_attack.rb
index b0778633199..58bf3f6013c 100644
--- a/config/initializers/rack_attack.rb
+++ b/config/initializers/rack_attack.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Specs for this file can be found on:
# * spec/lib/gitlab/throttle_spec.rb
# * spec/requests/rack_attack_global_spec.rb
@@ -15,6 +17,13 @@ module Gitlab::Throttle
Rack::Attack.throttles.key?('protected paths')
end
+ def self.bypass_header
+ env_value = ENV['GITLAB_THROTTLE_BYPASS_HEADER']
+ return unless env_value.present?
+
+ "HTTP_#{env_value.upcase.tr('-', '_')}"
+ end
+
def self.unauthenticated_options
limit_proc = proc { |req| settings.throttle_unauthenticated_requests_per_period }
period_proc = proc { |req| settings.throttle_unauthenticated_period_in_seconds.seconds }
@@ -112,6 +121,11 @@ class Rack::Attack
end
end
+ safelist('throttle_bypass_header') do |req|
+ Gitlab::Throttle.bypass_header.present? &&
+ req.get_header(Gitlab::Throttle.bypass_header) == '1'
+ end
+
class Request
def unauthenticated?
!(authenticated_user_id([:api, :rss, :ics]) || authenticated_runner_id)
diff --git a/config/initializers/rack_attack_logging.rb b/config/initializers/rack_attack_logging.rb
index a95cb09755b..e89c6b1b794 100644
--- a/config/initializers/rack_attack_logging.rb
+++ b/config/initializers/rack_attack_logging.rb
@@ -5,13 +5,15 @@
ActiveSupport::Notifications.subscribe(/rack_attack/) do |name, start, finish, request_id, payload|
req = payload[:request]
- if [:throttle, :blocklist].include? req.env['rack.attack.match_type']
+ case req.env['rack.attack.match_type']
+ when :throttle, :blocklist
rack_attack_info = {
message: 'Rack_Attack',
env: req.env['rack.attack.match_type'],
remote_ip: req.ip,
request_method: req.request_method,
- path: req.fullpath
+ path: req.fullpath,
+ matched: req.env['rack.attack.matched']
}
throttles_with_user_information = [
@@ -25,11 +27,12 @@ ActiveSupport::Notifications.subscribe(/rack_attack/) do |name, start, finish, r
user_id = req.env['rack.attack.match_discriminator']
user = User.find_by(id: user_id)
- rack_attack_info[:throttle_type] = req.env['rack.attack.matched']
rack_attack_info[:user_id] = user_id
- rack_attack_info[:username] = user.username unless user.nil?
+ rack_attack_info['meta.user'] = user.username unless user.nil?
end
Gitlab::AuthLogger.error(rack_attack_info)
+ when :safelist
+ Gitlab::Instrumentation::Throttle.safelist = req.env['rack.attack.matched']
end
end
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 72e2b94fe07..8e3241a2e4c 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -1,4 +1,9 @@
# frozen_string_literal: true
+module SidekiqLogArguments
+ def self.enabled?
+ Gitlab::Utils.to_boolean(ENV['SIDEKIQ_LOG_ARGUMENTS'], default: true)
+ end
+end
def enable_reliable_fetch?
return true unless Feature::FlipperFeature.table_exists?
@@ -35,7 +40,7 @@ Sidekiq.configure_server do |config|
config.server_middleware(&Gitlab::SidekiqMiddleware.server_configurator({
metrics: Settings.monitoring.sidekiq_exporter,
- arguments_logger: ENV['SIDEKIQ_LOG_ARGUMENTS'] && !enable_json_logs,
+ arguments_logger: SidekiqLogArguments.enabled? && !enable_json_logs,
memory_killer: enable_sidekiq_memory_killer && use_sidekiq_legacy_memory_killer
}))
diff --git a/config/initializers/tracing.rb b/config/initializers/tracing.rb
index f26fb18f3ea..3058bdeb84e 100644
--- a/config/initializers/tracing.rb
+++ b/config/initializers/tracing.rb
@@ -2,7 +2,8 @@
if Labkit::Tracing.enabled?
Rails.application.configure do |config|
- config.middleware.insert_after Labkit::Middleware::Rack, ::Labkit::Tracing::RackMiddleware
+ # Rack needs to parse multipart messages before ActionDispatch can filter parameters
+ config.middleware.insert_after Rack::MethodOverride, ::Labkit::Tracing::RackMiddleware
end
# Instrument Redis
diff --git a/config/initializers/oj.rb b/config/initializers_before_autoloader/oj.rb
index 3fa26259fc6..3fa26259fc6 100644
--- a/config/initializers/oj.rb
+++ b/config/initializers_before_autoloader/oj.rb
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
index 6c6a5f7b1a1..06dece58173 100644
--- a/config/locales/devise.en.yml
+++ b/config/locales/devise.en.yml
@@ -30,6 +30,8 @@ en:
subject: "Password Changed"
password_change_by_admin:
subject: "Password changed by administrator"
+ user_admin_approval:
+ subject: "Welcome to GitLab!"
omniauth_callbacks:
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
success: "Successfully authenticated from %{kind} account."
diff --git a/config/routes.rb b/config/routes.rb
index 87d32e3d89a..867e5c2ec46 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -45,8 +45,7 @@ Rails.application.routes.draw do
# Sign up
scope path: '/users/sign_up', module: :registrations, as: :users_sign_up do
- get :welcome
- patch :update_registration
+ resource :welcome, only: [:show, :update], controller: 'welcome'
resource :experience_level, only: [:show, :update]
Gitlab.ee do
@@ -122,7 +121,6 @@ Rails.application.routes.draw do
get 'ide' => 'ide#index'
get 'ide/*vueroute' => 'ide#index', format: false
- get 'ide/project/:namespace/:project/merge_requests/:id' => 'ide#index', format: false, as: :ide_merge_request
draw :operations
draw :jira_connect
@@ -175,11 +173,11 @@ Rails.application.routes.draw do
resources :abuse_reports, only: [:new, :create]
# JWKS (JSON Web Key Set) endpoint
- # Used by third parties to verify CI_JOB_JWT, placeholder route
- # in case we decide to move away from doorkeeper-openid_connect
- get 'jwks' => 'doorkeeper/openid_connect/discovery#keys'
+ # Used by third parties to verify CI_JOB_JWT
+ get 'jwks' => 'jwks#index'
draw :snippets
+ draw :profile
# Product analytics collector
match '/collector/i', to: ProductAnalytics::CollectorApp.new, via: :all
@@ -266,7 +264,6 @@ Rails.application.routes.draw do
draw :uploads
draw :explore
draw :admin
- draw :profile
draw :dashboard
draw :user
draw :project
@@ -274,14 +271,11 @@ Rails.application.routes.draw do
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/210024
scope as: 'deprecated' do
draw :snippets
+ draw :profile
end
- # Serve profile routes under /-/ scope.
- # To ensure an old unscoped routing is used for the UI we need to
- # add prefix 'as' to the scope routing and place it below original routing.
- # Issue https://gitlab.com/gitlab-org/gitlab/-/issues/210024
- scope '-', as: :scoped do
- draw :profile
+ Gitlab.ee do
+ get '/sitemap' => 'sitemap#show', format: :xml
end
root to: "root#index"
diff --git a/config/routes/group.rb b/config/routes/group.rb
index 33464cf3b55..e90be482bbd 100644
--- a/config/routes/group.rb
+++ b/config/routes/group.rb
@@ -107,6 +107,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
end
resources :container_registries, only: [:index, :show], controller: 'registry/repositories'
+ resource :dependency_proxy, only: [:show, :update]
end
scope(path: '*id',
@@ -119,3 +120,14 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
delete '/', action: :destroy
end
end
+
+# Dependency proxy for containers
+# Because docker adds v2 prefix to URI this need to be outside of usual group routes
+scope format: false do
+ get 'v2', to: proc { [200, {}, ['']] } # rubocop:disable Cop/PutGroupRoutesUnderScope
+
+ constraints image: Gitlab::PathRegex.container_image_regex, sha: Gitlab::PathRegex.container_image_blob_sha_regex do
+ get 'v2/*group_id/dependency_proxy/containers/*image/manifests/*tag' => 'groups/dependency_proxy_for_containers#manifest' # rubocop:todo Cop/PutGroupRoutesUnderScope
+ get 'v2/*group_id/dependency_proxy/containers/*image/blobs/:sha' => 'groups/dependency_proxy_for_containers#blob' # rubocop:todo Cop/PutGroupRoutesUnderScope
+ end
+end
diff --git a/config/routes/import.rb b/config/routes/import.rb
index 3ee44aa8659..557d7fe7143 100644
--- a/config/routes/import.rb
+++ b/config/routes/import.rb
@@ -69,7 +69,7 @@ namespace :import do
post :authorize
end
- resource :bulk_import, only: [:create] do
+ resource :bulk_imports, only: [:create] do
post :configure
get :status
end
diff --git a/config/routes/merge_requests.rb b/config/routes/merge_requests.rb
index b2635a7fa74..c11e5a5c3d9 100644
--- a/config/routes/merge_requests.rb
+++ b/config/routes/merge_requests.rb
@@ -47,6 +47,7 @@ resources :merge_requests, concerns: :awardable, except: [:new, :create, :show],
collection do
get :diff_for_path
post :bulk_update
+ post :export_csv
end
resources :discussions, only: [:show], constraints: { id: /\h{40}/ } do
diff --git a/config/routes/project.rb b/config/routes/project.rb
index eae217de1ac..2e61bc8175e 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -85,6 +85,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
namespace :ci do
resource :lint, only: [:show, :create]
+ resource :pipeline_editor, only: [:show], controller: :pipeline_editor, path: 'editor'
resources :daily_build_group_report_results, only: [:index], constraints: { format: /(csv|json)/ }
end
@@ -264,6 +265,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :functions, only: [:index]
end
+ resources :terraform, only: [:index]
+
resources :environments, except: [:destroy] do
member do
post :stop
@@ -400,6 +403,11 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
#
# Templates
#
+ get '/templates/:template_type' => 'templates#index', # rubocop:todo Cop/PutProjectRoutesUnderScope
+ as: :templates,
+ defaults: { format: 'json' },
+ constraints: { template_type: %r{issue|merge_request}, format: 'json' }
+
get '/templates/:template_type/:key' => 'templates#show', # rubocop:todo Cop/PutProjectRoutesUnderScope
as: :template,
defaults: { format: 'json' },
@@ -436,6 +444,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
post 'alerts/notify', to: 'alerting/notifications#create' # rubocop:todo Cop/PutProjectRoutesUnderScope
+ post 'alerts/notify/:name/:endpoint_identifier', # rubocop:todo Cop/PutProjectRoutesUnderScope
+ to: 'alerting/notifications#create',
+ as: :alert_http_integration,
+ constraints: { endpoint_identifier: /[A-Za-z0-9]+/ }
draw :legacy_builds
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index f061efeb427..2c1bb3c75e1 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -44,6 +44,8 @@
- 3
- - background_migration
- 1
+- - bulk_import
+ - 1
- - chaos
- 2
- - chat_notification
@@ -84,6 +86,8 @@
- 1
- - design_management_new_version
- 1
+- - destroy_pages_deployments
+ - 1
- - detect_repository_languages
- 1
- - disallow_two_factor_for_group
@@ -108,6 +112,8 @@
- 2
- - emails_on_push
- 2
+- - environments_canary_ingress_update
+ - 1
- - epics
- 2
- - error_tracking_issue_link
@@ -140,6 +146,8 @@
- 1
- - group_import
- 1
+- - group_saml_group_sync
+ - 1
- - hashed_storage
- 1
- - import_issues_csv
@@ -252,6 +260,8 @@
- 1
- - propagate_integration_inherit
- 1
+- - propagate_integration_inherit_descendant
+ - 1
- - propagate_integration_project
- 1
- - propagate_service_template
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 821ddc84e1a..190d97da1b4 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -18,6 +18,7 @@ const IS_DEV_SERVER = process.env.WEBPACK_DEV_SERVER === 'true';
const IS_EE = require('./helpers/is_ee_env');
const DEV_SERVER_HOST = process.env.DEV_SERVER_HOST || 'localhost';
const DEV_SERVER_PORT = parseInt(process.env.DEV_SERVER_PORT, 10) || 3808;
+const DEV_SERVER_PUBLIC_ADDR = process.env.DEV_SERVER_PUBLIC_ADDR;
const DEV_SERVER_HTTPS = process.env.DEV_SERVER_HTTPS && process.env.DEV_SERVER_HTTPS !== 'false';
const DEV_SERVER_LIVERELOAD = IS_DEV_SERVER && process.env.DEV_SERVER_LIVERELOAD !== 'false';
const WEBPACK_REPORT = process.env.WEBPACK_REPORT && process.env.WEBPACK_REPORT !== 'false';
@@ -82,6 +83,7 @@ function generateEntries() {
// sentry: './sentry/index.js', Temporarily commented out to investigate performance: https://gitlab.com/gitlab-org/gitlab/-/issues/251179
performance_bar: './performance_bar/index.js',
chrome_84_icon_fix: './lib/chrome_84_icon_fix.js',
+ jira_connect_app: './jira_connect/index.js',
};
return Object.assign(manualEntries, autoEntries);
@@ -553,12 +555,8 @@ module.exports = {
devServer: {
host: DEV_SERVER_HOST,
port: DEV_SERVER_PORT,
+ public: DEV_SERVER_PUBLIC_ADDR,
https: DEV_SERVER_HTTPS,
- disableHostCheck: true,
- headers: {
- 'Access-Control-Allow-Origin': '*',
- 'Access-Control-Allow-Headers': '*',
- },
contentBase: false,
stats: 'errors-only',
hot: DEV_SERVER_LIVERELOAD,
diff --git a/danger/commit_messages/Dangerfile b/danger/commit_messages/Dangerfile
index 174fc10eef3..4e17db60471 100644
--- a/danger/commit_messages/Dangerfile
+++ b/danger/commit_messages/Dangerfile
@@ -37,7 +37,8 @@ def build_message(commit, message, more_info: true)
end
def squash_mr?
- gitlab_danger.ci? ? gitlab.mr_json['squash'] : false
+ # Locally, we assume the MR is set to be squashed so that the user only sees warnings instead of errors.
+ gitlab_danger.ci? ? gitlab.mr_json['squash'] : true
end
def wip_mr?
@@ -100,25 +101,27 @@ end
def lint_commits(commits)
commit_linters = commits.map { |commit| lint_commit(commit) }
- failed_commit_linters = commit_linters.select { |commit_linter| commit_linter.failed? }
- warn_or_fail_commits(failed_commit_linters, default_to_fail: !squash_mr?)
-
- if count_non_fixup_commits(commit_linters) > MAX_COMMITS_COUNT
- self.warn(format(MAX_COMMITS_COUNT_EXCEEDED_MESSAGE, max_commits_count: MAX_COMMITS_COUNT))
- end
if squash_mr?
multi_line_commit_linter = commit_linters.detect { |commit_linter| !commit_linter.merge? && commit_linter.multi_line? }
if multi_line_commit_linter && multi_line_commit_linter.failed?
warn_or_fail_commits(multi_line_commit_linter)
- else
+ commit_linters.delete(multi_line_commit_linter) # Don't show an error (here) and a warning (below)
+ elsif gitlab_danger.ci? # We don't have access to the MR title locally
title_linter = lint_mr_title(gitlab.mr_json['title'])
if title_linter.failed?
warn_or_fail_commits(title_linter)
end
end
+ else
+ if count_non_fixup_commits(commit_linters) > MAX_COMMITS_COUNT
+ self.warn(format(MAX_COMMITS_COUNT_EXCEEDED_MESSAGE, max_commits_count: MAX_COMMITS_COUNT))
+ end
end
+
+ failed_commit_linters = commit_linters.select { |commit_linter| commit_linter.failed? }
+ warn_or_fail_commits(failed_commit_linters, default_to_fail: !squash_mr?)
end
def warn_or_fail_commits(failed_linters, default_to_fail: true)
@@ -127,7 +130,7 @@ def warn_or_fail_commits(failed_linters, default_to_fail: true)
Array(failed_linters).each do |linter|
linter.problems.each do |problem_key, problem_desc|
case problem_key
- when :subject_above_warning
+ when :subject_too_short, :subject_above_warning
warn_commit(linter.commit, problem_desc)
else
self.__send__("#{level}_commit", linter.commit, problem_desc) # rubocop:disable GitlabSecurity/PublicSend
diff --git a/danger/documentation/Dangerfile b/danger/documentation/Dangerfile
index dc43e9d1843..240c374435c 100644
--- a/danger/documentation/Dangerfile
+++ b/danger/documentation/Dangerfile
@@ -4,9 +4,29 @@ def gitlab_danger
@gitlab_danger ||= GitlabDanger.new(helper.gitlab_helper)
end
+def feature_mr?
+ return false unless helper.gitlab_helper&.mr_labels
+
+ (helper.gitlab_helper.mr_labels & %w[feature::addition feature::enhancement]).any?
+end
+
+DOCUMENTATION_UPDATE_MISSING = <<~MSG
+~"feature::addition" and ~"feature::enhancement" merge requests normally have a documentation change. Consider adding a documentation update or confirming the documentation plan with the [Technical Writer counterpart](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers).
+
+For more information, see:
+
+- The Handbook page on [throughput implementation](https://about.gitlab.com/handbook/engineering/management/throughput/#implementation).
+- The [definition of done](https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html#definition-of-done) documentation.
+MSG
+
docs_paths_to_review = helper.changes_by_category[:docs]
-return if docs_paths_to_review.empty?
+# Documentation should be updated for feature::addition and feature::enhancement
+if docs_paths_to_review.empty?
+ warn(DOCUMENTATION_UPDATE_MISSING) if feature_mr?
+
+ return
+end
message 'This merge request adds or changes documentation files. A review from the Technical Writing team before you merge is **recommended**. Reviews can happen after you merge.'
diff --git a/danger/product_analytics/Dangerfile b/danger/product_analytics/Dangerfile
index fb441d6e467..b2144e7f034 100644
--- a/danger/product_analytics/Dangerfile
+++ b/danger/product_analytics/Dangerfile
@@ -2,7 +2,7 @@
PRODUCT_ANALYTICS_CHANGED_FILES_MESSAGE = <<~MSG
For the following files, a review from the [Data team and Product Analytics team](https://gitlab.com/groups/gitlab-org/growth/product_analytics/engineers/-/group_members?with_inherited_permissions=exclude) is recommended
-Please check the ~"product analytics(telemetry)" [guide](https://docs.gitlab.com/ee/development/product_analytics/usage_ping.html) and reach out to %<product_analytics_engineers_group>s group for a review.
+Please check the ~"product analytics" [guide](https://docs.gitlab.com/ee/development/product_analytics/usage_ping.html) and reach out to %<product_analytics_engineers_group>s group for a review.
%<changed_files>s
@@ -10,7 +10,7 @@ Please check the ~"product analytics(telemetry)" [guide](https://docs.gitlab.com
MSG
UPDATE_METRICS_DEFINITIONS_MESSAGE = <<~MSG
- When adding, changing, or updating metrics, please update the [Event dictionary Usage Ping table](https://docs.gitlab.com/ee/development/product_analytics/event_dictionary.html#usage-ping).
+ When adding, changing, or updating metrics, please update the [Event dictionary Usage Ping table](https://about.gitlab.com/handbook/product/product-analytics-guide#event-dictionary).
MSG
@@ -41,8 +41,8 @@ if changed_files.any?
warn format(PRODUCT_ANALYTICS_CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(changed_files), product_analytics_engineers_group: mention)
warn format(UPDATE_METRICS_DEFINITIONS_MESSAGE) unless helper.changed_files(/usage_ping\.md/).any?
- product_analytics_labels = ['product analytics(telemetry)']
- product_analytics_labels << 'product analytics(telemetry)::review pending' unless helper.mr_has_labels?('product analytics(telemetry)::reviewed')
+ product_analytics_labels = ['product analytics']
+ product_analytics_labels << 'product analytics::review pending' unless helper.mr_has_labels?('product analytics::reviewed')
markdown(helper.prepare_labels_for_mr(product_analytics_labels))
end
diff --git a/data/whats_new/202008210001_13_02.yml b/data/whats_new/202008210001_13_02.yml
index 64ee0b0174a..77bde327f9c 100644
--- a/data/whats_new/202008210001_13_02.yml
+++ b/data/whats_new/202008210001_13_02.yml
@@ -6,7 +6,7 @@
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
+ image_url: https://img.youtube.com/vi/31pNKjenlJY/hqdefault.jpg
published_at: 2020-07-22
release: 13.2
- title: Container Host Monitoring and Blocking
@@ -16,7 +16,7 @@
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
+ image_url: https://img.youtube.com/vi/WxBzBz76FxU/hqdefault.jpg
published_at: 2020-07-22
release: 13.2
- title: Official GitLab-Figma Plugin
diff --git a/data/whats_new/202009150001_13_03.yml b/data/whats_new/202009150001_13_03.yml
index 73c3dae5136..ae22a9826b3 100644
--- a/data/whats_new/202009150001_13_03.yml
+++ b/data/whats_new/202009150001_13_03.yml
@@ -6,7 +6,7 @@
gitlab-com: true
packages: [Ultimate]
url: https://www.youtube.com/watch?v=3wdWMDRLdp4
- image_url: http://i3.ytimg.com/vi/3wdWMDRLdp4/hqdefault.jpg
+ image_url: https://img.youtube.com/vi/3wdWMDRLdp4/hqdefault.jpg
published_at: 2020-08-22
release: 13.3
- title: Create a matrix of jobs using a simple syntax
diff --git a/data/whats_new/202009300001_13_04.yml b/data/whats_new/202009300001_13_04.yml
index cda0cf15170..0e54a137bae 100644
--- a/data/whats_new/202009300001_13_04.yml
+++ b/data/whats_new/202009300001_13_04.yml
@@ -46,7 +46,7 @@
gitlab-com: true
packages: [starter, premium, ultimate]
url: https://www.youtube.com/embed/1FBRaBQTQZk
- image_url: http://i3.ytimg.com/vi/1FBRaBQTQZk/maxresdefault.jpg
+ image_url: https://img.youtube.com/vi/1FBRaBQTQZk/hqdefault.jpg
published_at: 2020-09-22
release: 13.4
- title: Quick navigation using the Search bar
diff --git a/data/whats_new/202010230001_13_05.yml b/data/whats_new/202010230001_13_05.yml
new file mode 100644
index 00000000000..1c6249ae477
--- /dev/null
+++ b/data/whats_new/202010230001_13_05.yml
@@ -0,0 +1,61 @@
+---
+- title: Group wikis
+ body: For many teams, using GitLab wikis for planning and documentation is a critical part of their workflow. Wikis are so popular that they get over a million views each month on GitLab.com. Despite this popularity, teams have struggled with the limitation that wikis were only available at the project level. Teams working on multiple projects needed to create separate wikis for each repository, leading to a fragmented experience. In Gitlab 13.5, we are so excited to bring you group wikis! This was the most upvoted feature in the entire GitLab backlog. While highly requested, making a large project-only feature like wikis available at the group level has been a non-trivial operation. We’ve worked tirelessly over the past year to make it happen and now we can't wait to get it in your hands and hear your feedback.
+ stage: Create
+ self-managed: true
+ gitlab-com: true
+ packages: [Premium, Ultimate]
+ url: https://docs.gitlab.com/ee/user/group/index.html#group-wikis
+ image_url: https://about.gitlab.com/images/13_5/cdybenko-group-wiki.png
+ published_at: 2020-10-22
+ release: 13.5
+- title: Install the GitLab Kubernetes Agent with Omnibus GitLab
+ body: "Last month we introduced the GitLab Kubernetes Agent for self-managed GitLab instances installed with Helm. This release adds support for the official Linux package. In this new Kubernetes integration, the Agent orchestrates deployments by pulling new changes from GitLab, rather than GitLab pushing updates to your cluster."
+ stage: Configure
+ self-managed: true
+ gitlab-com: false
+ packages: [Premium, Ultimate]
+ url: https://docs.gitlab.com/ee/user/clusters/agent/
+ image_url: https://about.gitlab.com/images/13_5/gitops-header.png
+ published_at: 2020-10-22
+ release: 13.5
+- title: Snippets with multiple files
+ body: Engineers often use Snippets to share examples of code, reusable components, logs, and other items. These valuable pieces of information often require additional context and may require more than one file. Sharing a link to multiple files or multiple Snippets makes it challenging for users to piece this context together and understand the scope of what is being presented. GitLab now supports multiple files inside of a single Snippet, so you can create Snippets composed of multiple parts. It broadens its use to endless possibilities!
+ stage: Create
+ self-managed: true
+ gitlab-com: true
+ packages: [Core, Starter, Premium, Ultimate]
+ url: https://docs.gitlab.com/ee/user/snippets.html#multiple-files-by-snippet
+ image_url: https://about.gitlab.com/images/13_5/phikai-snippets-multiple-files.png
+ published_at: 2020-10-22
+ release: 13.5
+- title: Enable instance-level shared runners when viewing groups
+ body: GitLab SaaS includes Linux and Windows runners, which are easy to use agents that run your GitLab CI/CD pipeline jobs. These runners, visible in the GitLab.com UI as "shared runners," are enabled by default and can be disabled for each project. However, some organizations require their CI/CD jobs to run only on self-managed runners, and so disabling the use of instance-level shared runners on each project resulted in unnecessary administrative overhead. Now administrators can enable or disable shared runners at the group level. Administrators can also allow groups to override the global setting and use shared runners on a project-by-project basis.
+ stage: Verify
+ self-managed: true
+ gitlab-com: true
+ packages: [Core, Starter, Premium, Ultimate]
+ url: https://docs.gitlab.com/ee/ci/runners/README.html#disable-shared-runners
+ image_url: https://about.gitlab.com/images/13_5/enable_shared_runners_v2.png
+ published_at: 2020-10-22
+ release: 13.5
+- title: Feature Flags flexible rollout strategy
+ body: When you use the percent rollout strategy today, the stickiness, or the experience consistency, is determined only by the user ID. This can be limiting; as an example, anonymous users cannot be affected by this strategy. We have improved this rollout strategy by enabling you to define the stickiness based on session ID, user ID, or at random (no stickiness). This gives you more control over the rollout and allows you to support stickiness for anonymous users.
+ stage: Release
+ self-managed: true
+ gitlab-com: true
+ packages: [core, starter, premium, ultimate]
+ url: https://docs.gitlab.com/ee/operations/feature_flags.html#percent-rollout
+ image_url: https://about.gitlab.com/images/13_5/percent-rollout.png
+ published_at: 2020-10-22
+ release: 13.5
+- title: SAST support for iOS and Android mobile apps
+ body: GitLab SAST now supports mobile applications including iOS apps written in Objective-C and Swift as well as Android apps written in Java and Kotlin powered by the Mobile Security Framework (MobSF). Initially this analyzer supports source code analysis but we intend to expand support for binary scanning of .ipa and .apk files in the near future. This feature was a generous contribution by the H-E-B Digital team.
+ stage: Secure
+ self-managed: true
+ gitlab-com: true
+ packages: [core, starter, premium, ultimate]
+ url: https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks
+ image_url: https://about.gitlab.com/images/13_5/sast-gitlab-mobile.png
+ published_at: 2020-10-22
+ release: 13.5
diff --git a/db/fixtures/development/02_application_settings.rb b/db/fixtures/development/02_application_settings.rb
index 67486d2ab5f..46da3205d8f 100644
--- a/db/fixtures/development/02_application_settings.rb
+++ b/db/fixtures/development/02_application_settings.rb
@@ -7,4 +7,7 @@ ApplicationSetting.create_from_defaults
puts "Enable hashed storage for every new projects.".color(:green)
ApplicationSetting.current_without_cache.update!(hashed_storage_enabled: true)
+puts "Generate CI JWT signing key".color(:green)
+ApplicationSetting.current_without_cache.update!(ci_jwt_signing_key: OpenSSL::PKey::RSA.new(2048).to_pem)
+
print '.'
diff --git a/db/fixtures/development/12_snippets.rb b/db/fixtures/development/12_snippets.rb
index 8ceabcdcd9b..6d31007b320 100644
--- a/db/fixtures/development/12_snippets.rb
+++ b/db/fixtures/development/12_snippets.rb
@@ -1,6 +1,28 @@
require './spec/support/sidekiq_middleware'
SNIPPET_REPO_URL = "https://gitlab.com/gitlab-org/gitlab-snippet-test.git"
+BUNDLE_PATH = File.join(Rails.root, 'db/fixtures/development/gitlab-snippet-test.bundle')
+
+class Gitlab::Seeder::SnippetRepository
+ def initialize(snippet)
+ @snippet = snippet
+ end
+
+ def import
+ if File.exists?(BUNDLE_PATH)
+ @snippet.repository.create_from_bundle(BUNDLE_PATH)
+ else
+ @snippet.repository.import_repository(SNIPPET_REPO_URL)
+ @snippet.repository.bundle_to_disk(BUNDLE_PATH)
+ end
+ end
+
+ def self.cleanup
+ File.delete(BUNDLE_PATH) if File.exists?(BUNDLE_PATH)
+ rescue => e
+ warn "\nError cleaning up snippet bundle: #{e}"
+ end
+end
Gitlab::Seeder.quiet do
20.times do |i|
@@ -14,7 +36,7 @@ Gitlab::Seeder.quiet do
content: 'foo'
}).tap do |snippet|
unless snippet.repository_exists?
- snippet.repository.import_repository(SNIPPET_REPO_URL)
+ Gitlab::Seeder::SnippetRepository.new(snippet).import
end
snippet.track_snippet_repository(snippet.repository.storage)
@@ -23,5 +45,7 @@ Gitlab::Seeder.quiet do
print('.')
end
+
+ Gitlab::Seeder::SnippetRepository.cleanup
end
diff --git a/db/fixtures/production/010_settings.rb b/db/fixtures/production/010_settings.rb
index 7626cdb0b9c..65f70a9e715 100644
--- a/db/fixtures/production/010_settings.rb
+++ b/db/fixtures/production/010_settings.rb
@@ -24,3 +24,7 @@ if ENV['GITLAB_PROMETHEUS_METRICS_ENABLED'].present?
settings.prometheus_metrics_enabled = value
save(settings, 'Prometheus metrics enabled flag')
end
+
+settings = Gitlab::CurrentSettings.current_application_settings
+settings.ci_jwt_signing_key = OpenSSL::PKey::RSA.new(2048).to_pem
+save(settings, 'CI JWT signing key')
diff --git a/db/migrate/20200908212414_add_feature_flag_events_to_web_hooks.rb b/db/migrate/20200908212414_add_feature_flag_events_to_web_hooks.rb
new file mode 100644
index 00000000000..40e2b37b390
--- /dev/null
+++ b/db/migrate/20200908212414_add_feature_flag_events_to_web_hooks.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddFeatureFlagEventsToWebHooks < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :web_hooks, :feature_flag_events, :boolean, null: false, default: false
+ end
+end
diff --git a/db/migrate/20200920130356_add_container_expiration_policy_worker_settings_to_application_settings.rb b/db/migrate/20200920130356_add_container_expiration_policy_worker_settings_to_application_settings.rb
new file mode 100644
index 00000000000..7501f150283
--- /dev/null
+++ b/db/migrate/20200920130356_add_container_expiration_policy_worker_settings_to_application_settings.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddContainerExpirationPolicyWorkerSettingsToApplicationSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ unless column_exists?(:application_settings, :container_registry_expiration_policies_worker_capacity)
+ add_column(:application_settings, :container_registry_expiration_policies_worker_capacity, :integer, default: 0, null: false)
+ end
+ end
+
+ def down
+ if column_exists?(:application_settings, :container_registry_expiration_policies_worker_capacity)
+ remove_column(:application_settings, :container_registry_expiration_policies_worker_capacity)
+ end
+ end
+end
diff --git a/db/migrate/20200928123510_add_expiration_policy_cleanup_status_to_container_repositories.rb b/db/migrate/20200928123510_add_expiration_policy_cleanup_status_to_container_repositories.rb
new file mode 100644
index 00000000000..4d611a56e9c
--- /dev/null
+++ b/db/migrate/20200928123510_add_expiration_policy_cleanup_status_to_container_repositories.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class AddExpirationPolicyCleanupStatusToContainerRepositories < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'idx_container_repositories_on_exp_cleanup_status_and_start_date'
+
+ disable_ddl_transaction!
+
+ def up
+ unless column_exists?(:container_repositories, :expiration_policy_cleanup_status)
+ add_column(:container_repositories, :expiration_policy_cleanup_status, :integer, limit: 2, default: 0, null: false)
+ end
+
+ add_concurrent_index(:container_repositories, [:expiration_policy_cleanup_status, :expiration_policy_started_at], name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index(:container_repositories, [:expiration_policy_cleanup_status, :expiration_policy_started_at], name: INDEX_NAME)
+
+ if column_exists?(:container_repositories, :expiration_policy_cleanup_status)
+ remove_column(:container_repositories, :expiration_policy_cleanup_status)
+ end
+ end
+end
diff --git a/db/migrate/20201008011523_add_ci_jwt_signing_key_to_application_settings.rb b/db/migrate/20201008011523_add_ci_jwt_signing_key_to_application_settings.rb
new file mode 100644
index 00000000000..c51f7e8b706
--- /dev/null
+++ b/db/migrate/20201008011523_add_ci_jwt_signing_key_to_application_settings.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddCiJwtSigningKeyToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20201001011937_add_text_limit_to_application_settings_encrypted_ci_jwt_signing_key_iv
+ def change
+ add_column :application_settings, :encrypted_ci_jwt_signing_key, :text
+ add_column :application_settings, :encrypted_ci_jwt_signing_key_iv, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20201008011937_add_text_limit_to_application_settings_encrypted_ci_jwt_signing_key_iv.rb b/db/migrate/20201008011937_add_text_limit_to_application_settings_encrypted_ci_jwt_signing_key_iv.rb
new file mode 100644
index 00000000000..39f6eb2106a
--- /dev/null
+++ b/db/migrate/20201008011937_add_text_limit_to_application_settings_encrypted_ci_jwt_signing_key_iv.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddTextLimitToApplicationSettingsEncryptedCiJwtSigningKeyIv < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :application_settings, :encrypted_ci_jwt_signing_key_iv, 255
+ end
+
+ def down
+ remove_text_limit :application_settings, :encrypted_ci_jwt_signing_key_iv
+ end
+end
diff --git a/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb b/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb
new file mode 100644
index 00000000000..7983a56f439
--- /dev/null
+++ b/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class GenerateCiJwtSigningKey < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ class ApplicationSetting < ActiveRecord::Base
+ self.table_name = 'application_settings'
+
+ attr_encrypted :ci_jwt_signing_key, {
+ mode: :per_attribute_iv,
+ key: Rails.application.secrets.db_key_base[0..31],
+ algorithm: 'aes-256-gcm',
+ encode: true
+ }
+ end
+
+ def up
+ ApplicationSetting.reset_column_information
+
+ ApplicationSetting.find_each do |application_setting|
+ application_setting.update(ci_jwt_signing_key: OpenSSL::PKey::RSA.new(2048).to_pem)
+ end
+ end
+
+ def down
+ ApplicationSetting.reset_column_information
+
+ ApplicationSetting.find_each do |application_setting|
+ application_setting.update_columns(encrypted_ci_jwt_signing_key: nil, encrypted_ci_jwt_signing_key_iv: nil)
+ end
+ end
+end
diff --git a/db/migrate/20201008075620_add_releases_events_to_web_hooks.rb b/db/migrate/20201008075620_add_releases_events_to_web_hooks.rb
new file mode 100644
index 00000000000..f6df213f162
--- /dev/null
+++ b/db/migrate/20201008075620_add_releases_events_to_web_hooks.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddReleasesEventsToWebHooks < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :web_hooks, :releases_events, :boolean, null: false, default: false
+ end
+end
diff --git a/db/migrate/20201008125643_create_csv_issue_imports.rb b/db/migrate/20201008125643_create_csv_issue_imports.rb
new file mode 100644
index 00000000000..be3206af6d8
--- /dev/null
+++ b/db/migrate/20201008125643_create_csv_issue_imports.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class CreateCsvIssueImports < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ create_table :csv_issue_imports do |t|
+ t.bigint :project_id, null: false, index: true
+ t.bigint :user_id, null: false, index: true
+
+ t.timestamps_with_timezone
+ end
+ end
+
+ def down
+ drop_table :csv_issue_imports
+ end
+end
diff --git a/db/migrate/20201008144854_set_regex_defaults_on_container_expiration_policies.rb b/db/migrate/20201008144854_set_regex_defaults_on_container_expiration_policies.rb
new file mode 100644
index 00000000000..45c411fc238
--- /dev/null
+++ b/db/migrate/20201008144854_set_regex_defaults_on_container_expiration_policies.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class SetRegexDefaultsOnContainerExpirationPolicies < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ change_column_default :container_expiration_policies, :name_regex, '.*'
+ change_column_default :container_expiration_policies, :enabled, false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ change_column_default :container_expiration_policies, :name_regex, nil
+ change_column_default :container_expiration_policies, :enabled, true
+ end
+ end
+end
diff --git a/db/migrate/20201008224441_add_position_into_security_findings.rb b/db/migrate/20201008224441_add_position_into_security_findings.rb
new file mode 100644
index 00000000000..ee6d5370f83
--- /dev/null
+++ b/db/migrate/20201008224441_add_position_into_security_findings.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddPositionIntoSecurityFindings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :security_findings, :position, :integer
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :security_findings, :position
+ end
+ end
+end
diff --git a/db/migrate/20201012073022_remove_not_null_constraint_on_framework.rb b/db/migrate/20201012073022_remove_not_null_constraint_on_framework.rb
new file mode 100644
index 00000000000..b8cc8984575
--- /dev/null
+++ b/db/migrate/20201012073022_remove_not_null_constraint_on_framework.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class RemoveNotNullConstraintOnFramework < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ GDPR_FRAMEWORK_ID = 1
+
+ disable_ddl_transaction!
+
+ class TmpComplianceProjectFrameworkSetting < ActiveRecord::Base
+ self.table_name = 'project_compliance_framework_settings'
+ self.primary_key = :project_id
+
+ include EachBatch
+ end
+
+ def up
+ change_column_null :project_compliance_framework_settings, :framework, true
+ end
+
+ def down
+ # Custom frameworks cannot be rolled back easily since we don't have enum for them.
+ # To make the database consistent, we mark them as GDPR framework.
+ # Note: framework customization will be implemented in the next 1-3 releases so data
+ # corruption due to the rollback is unlikely.
+ TmpComplianceProjectFrameworkSetting.each_batch(of: 100) do |query|
+ query.where(framework: nil).update_all(framework: GDPR_FRAMEWORK_ID)
+ end
+
+ change_column_null :project_compliance_framework_settings, :framework, false
+ end
+end
diff --git a/db/migrate/20201012122428_add_container_registry_expiration_policies_worker_capacity_constraint.rb b/db/migrate/20201012122428_add_container_registry_expiration_policies_worker_capacity_constraint.rb
new file mode 100644
index 00000000000..e4f7d1309a3
--- /dev/null
+++ b/db/migrate/20201012122428_add_container_registry_expiration_policies_worker_capacity_constraint.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 AddContainerRegistryExpirationPoliciesWorkerCapacityConstraint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ CONSTRAINT_NAME = 'app_settings_registry_exp_policies_worker_capacity_positive'
+
+ disable_ddl_transaction!
+
+ def up
+ add_check_constraint :application_settings, 'container_registry_expiration_policies_worker_capacity >= 0', CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint :application_settings, CONSTRAINT_NAME
+ end
+end
diff --git a/db/migrate/20201012134230_create_ci_test_cases.rb b/db/migrate/20201012134230_create_ci_test_cases.rb
new file mode 100644
index 00000000000..fd1bcaf1093
--- /dev/null
+++ b/db/migrate/20201012134230_create_ci_test_cases.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class CreateCiTestCases < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:ci_test_cases)
+ create_table :ci_test_cases do |t|
+ t.bigint :project_id, null: false
+ t.text :key_hash, null: false
+
+ t.index [:project_id, :key_hash], unique: true
+ # NOTE: FK for projects will be added on a separate migration as per guidelines
+ end
+ end
+
+ add_text_limit :ci_test_cases, :key_hash, 64
+ end
+
+ def down
+ drop_table :ci_test_cases
+ end
+end
diff --git a/db/migrate/20201012135330_create_ci_test_case_failures.rb b/db/migrate/20201012135330_create_ci_test_case_failures.rb
new file mode 100644
index 00000000000..7eaf7b5256d
--- /dev/null
+++ b/db/migrate/20201012135330_create_ci_test_case_failures.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class CreateCiTestCaseFailures < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ create_table :ci_test_case_failures do |t|
+ t.datetime_with_timezone :failed_at
+ t.bigint :test_case_id, null: false
+ t.bigint :build_id, null: false
+
+ t.index [:test_case_id, :failed_at, :build_id], name: 'index_test_case_failures_unique_columns', unique: true, order: { failed_at: :desc }
+ t.index :build_id
+ t.foreign_key :ci_test_cases, column: :test_case_id, on_delete: :cascade
+ # NOTE: FK for ci_builds will be added on a separate migration as per guidelines
+ end
+ end
+
+ def down
+ drop_table :ci_test_case_failures
+ end
+end
diff --git a/db/migrate/20201012140110_add_projects_fk_to_ci_test_cases.rb b/db/migrate/20201012140110_add_projects_fk_to_ci_test_cases.rb
new file mode 100644
index 00000000000..d30b332e41a
--- /dev/null
+++ b/db/migrate/20201012140110_add_projects_fk_to_ci_test_cases.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddProjectsFkToCiTestCases < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :ci_test_cases, :projects, column: :project_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :ci_test_cases, column: :project_id
+ end
+ end
+end
diff --git a/db/migrate/20201012140452_add_ci_builds_fk_to_ci_test_case_failures.rb b/db/migrate/20201012140452_add_ci_builds_fk_to_ci_test_case_failures.rb
new file mode 100644
index 00000000000..0f2fdf071fa
--- /dev/null
+++ b/db/migrate/20201012140452_add_ci_builds_fk_to_ci_test_case_failures.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddCiBuildsFkToCiTestCaseFailures < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :ci_test_case_failures, :ci_builds, column: :build_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :ci_test_case_failures, column: :build_id
+ end
+ end
+end
diff --git a/db/migrate/20201014163633_specify_primary_key_where_missing.rb b/db/migrate/20201014163633_specify_primary_key_where_missing.rb
new file mode 100644
index 00000000000..bca111dacf2
--- /dev/null
+++ b/db/migrate/20201014163633_specify_primary_key_where_missing.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+class SpecifyPrimaryKeyWhereMissing < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ TABLES = {
+ project_authorizations: [:index_project_authorizations_on_user_id_project_id_access_level, %i(user_id project_id access_level)],
+ analytics_language_trend_repository_languages: [:analytics_repository_languages_unique_index, %i(programming_language_id project_id snapshot_date)],
+ approval_project_rules_protected_branches: [:index_approval_project_rules_protected_branches_unique, %i(approval_project_rule_id protected_branch_id)],
+ ci_build_trace_sections: [:index_ci_build_trace_sections_on_build_id_and_section_name_id, %i(build_id section_name_id)],
+ deployment_merge_requests: [:idx_deployment_merge_requests_unique_index, %i(deployment_id merge_request_id)],
+ issue_assignees: [:index_issue_assignees_on_issue_id_and_user_id, %i(issue_id user_id)],
+ issues_prometheus_alert_events: [:issue_id_prometheus_alert_event_id_index, %i(issue_id prometheus_alert_event_id)],
+ issues_self_managed_prometheus_alert_events: [:issue_id_self_managed_prometheus_alert_event_id_index, %i(issue_id self_managed_prometheus_alert_event_id)],
+ merge_request_diff_commits: [:index_merge_request_diff_commits_on_mr_diff_id_and_order, %i(merge_request_diff_id relative_order)],
+ merge_request_diff_files: [:index_merge_request_diff_files_on_mr_diff_id_and_order, %i(merge_request_diff_id relative_order)],
+ milestone_releases: [:index_miletone_releases_on_milestone_and_release, %i(milestone_id release_id)],
+ project_pages_metadata: [:index_project_pages_metadata_on_project_id, %i(project_id)],
+ push_event_payloads: [:index_push_event_payloads_on_event_id, %i(event_id)],
+ repository_languages: [:index_repository_languages_on_project_and_languages_id, %i(project_id programming_language_id)],
+ user_interacted_projects: [:index_user_interacted_projects_on_project_id_and_user_id, %i(project_id user_id)],
+ users_security_dashboard_projects: [:users_security_dashboard_projects_unique_index, %i(project_id user_id)]
+ }.freeze
+
+ def up
+ TABLES.each do |table, (unique_index, _)|
+ with_lock_retries do
+ execute "ALTER TABLE #{table} ADD CONSTRAINT #{table}_pkey PRIMARY KEY USING INDEX #{unique_index}" if index_exists_by_name?(table, unique_index)
+ end
+ end
+ end
+
+ def down
+ TABLES.each do |table, (unique_index, columns)|
+ add_concurrent_index table, columns, name: unique_index, unique: true
+
+ with_lock_retries do
+ execute "ALTER TABLE #{table} DROP CONSTRAINT #{table}_pkey"
+ end
+ end
+ end
+end
diff --git a/db/migrate/20201015121805_add_project_foreign_key_to_csv_issue_imports.rb b/db/migrate/20201015121805_add_project_foreign_key_to_csv_issue_imports.rb
new file mode 100644
index 00000000000..9476d2d55bd
--- /dev/null
+++ b/db/migrate/20201015121805_add_project_foreign_key_to_csv_issue_imports.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddProjectForeignKeyToCsvIssueImports < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :csv_issue_imports, :projects, column: :project_id
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :csv_issue_imports, column: :project_id
+ end
+ end
+end
diff --git a/db/migrate/20201015121825_add_user_foreign_key_to_csv_issue_imports.rb b/db/migrate/20201015121825_add_user_foreign_key_to_csv_issue_imports.rb
new file mode 100644
index 00000000000..ae91695bff4
--- /dev/null
+++ b/db/migrate/20201015121825_add_user_foreign_key_to_csv_issue_imports.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddUserForeignKeyToCsvIssueImports < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :csv_issue_imports, :users, column: :user_id
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :csv_issue_imports, column: :user_id
+ end
+ end
+end
diff --git a/db/migrate/20201015194852_add_index_on_state_for_dast_site_validations.rb b/db/migrate/20201015194852_add_index_on_state_for_dast_site_validations.rb
new file mode 100644
index 00000000000..785d7c8829c
--- /dev/null
+++ b/db/migrate/20201015194852_add_index_on_state_for_dast_site_validations.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class AddIndexOnStateForDastSiteValidations < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ OLD_INDEX_NAME = 'index_dast_site_validations_on_url_base'
+ NEW_INDEX_NAME = 'index_dast_site_validations_on_url_base_and_state'
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :dast_site_validations, [:url_base, :state], name: NEW_INDEX_NAME
+ remove_concurrent_index_by_name :dast_site_validations, OLD_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :dast_site_validations, :url_base, name: OLD_INDEX_NAME
+ remove_concurrent_index_by_name :dast_site_validations, NEW_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20201015231049_add_ci_build_id_to_terraform_state_versions.rb b/db/migrate/20201015231049_add_ci_build_id_to_terraform_state_versions.rb
new file mode 100644
index 00000000000..539b2af5fc4
--- /dev/null
+++ b/db/migrate/20201015231049_add_ci_build_id_to_terraform_state_versions.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class AddCiBuildIdToTerraformStateVersions < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_terraform_state_versions_on_ci_build_id'
+
+ disable_ddl_transaction!
+
+ def up
+ unless column_exists?(:terraform_state_versions, :ci_build_id)
+ add_column :terraform_state_versions, :ci_build_id, :bigint
+ end
+
+ add_concurrent_index :terraform_state_versions, :ci_build_id, name: INDEX_NAME
+ add_concurrent_foreign_key :terraform_state_versions, :ci_builds, column: :ci_build_id, on_delete: :nullify
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists :terraform_state_versions, :ci_builds, column: :ci_build_id
+ end
+
+ remove_concurrent_index_by_name :terraform_state_versions, INDEX_NAME
+ remove_column :terraform_state_versions, :ci_build_id
+ end
+end
diff --git a/db/migrate/20201016074302_add_index_project_id_and_id_to_container_repositories.rb b/db/migrate/20201016074302_add_index_project_id_and_id_to_container_repositories.rb
new file mode 100644
index 00000000000..b2e7c62ba0c
--- /dev/null
+++ b/db/migrate/20201016074302_add_index_project_id_and_id_to_container_repositories.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexProjectIdAndIdToContainerRepositories < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_container_repositories_on_project_id_and_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(:container_repositories, [:project_id, :id], name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index(:container_repositories, [:project_id, :id], name: INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20201019091307_add_unique_index_on_scan_id_and_position_of_security_findings.rb b/db/migrate/20201019091307_add_unique_index_on_scan_id_and_position_of_security_findings.rb
new file mode 100644
index 00000000000..3303e41d8a1
--- /dev/null
+++ b/db/migrate/20201019091307_add_unique_index_on_scan_id_and_position_of_security_findings.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddUniqueIndexOnScanIdAndPositionOfSecurityFindings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_security_findings_on_scan_id_and_position'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :security_findings, [:scan_id, :position], unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :security_findings, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20201019101549_add_es_custom_analyzers_settings.rb b/db/migrate/20201019101549_add_es_custom_analyzers_settings.rb
new file mode 100644
index 00000000000..47fd9ebbb8e
--- /dev/null
+++ b/db/migrate/20201019101549_add_es_custom_analyzers_settings.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class AddEsCustomAnalyzersSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :elasticsearch_analyzers_smartcn_enabled, :bool, null: false, default: false
+ add_column :application_settings, :elasticsearch_analyzers_smartcn_search, :bool, null: false, default: false
+ add_column :application_settings, :elasticsearch_analyzers_kuromoji_enabled, :bool, null: false, default: false
+ add_column :application_settings, :elasticsearch_analyzers_kuromoji_search, :bool, null: false, default: false
+ end
+end
diff --git a/db/migrate/20201019111952_add_sha256_and_filecount_to_pages_deployments.rb b/db/migrate/20201019111952_add_sha256_and_filecount_to_pages_deployments.rb
new file mode 100644
index 00000000000..1921701626d
--- /dev/null
+++ b/db/migrate/20201019111952_add_sha256_and_filecount_to_pages_deployments.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class AddSha256AndFilecountToPagesDeployments < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ # pages_deployments were never enabled on any production/staging
+ # environments, so we safely delete them for people who enabled
+ # them locally
+ execute "DELETE FROM pages_deployments"
+
+ # rubocop:disable Rails/NotNullColumn
+ add_column :pages_deployments, :file_count, :integer, null: false
+ add_column :pages_deployments, :file_sha256, :binary, null: false
+ # rubocop:enable Rails/NotNullColumn
+ end
+
+ def down
+ remove_column :pages_deployments, :file_sha256
+ remove_column :pages_deployments, :file_count
+ end
+end
diff --git a/db/migrate/20201019113009_add_new_user_signups_cap_to_application_settings.rb b/db/migrate/20201019113009_add_new_user_signups_cap_to_application_settings.rb
new file mode 100644
index 00000000000..8754b0d481e
--- /dev/null
+++ b/db/migrate/20201019113009_add_new_user_signups_cap_to_application_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddNewUserSignupsCapToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :new_user_signups_cap, :integer
+ end
+end
diff --git a/db/migrate/20201019130244_remove_license_compliance_temp_index.rb b/db/migrate/20201019130244_remove_license_compliance_temp_index.rb
new file mode 100644
index 00000000000..d0383d999ed
--- /dev/null
+++ b/db/migrate/20201019130244_remove_license_compliance_temp_index.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class RemoveLicenseComplianceTempIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_ci_job_artifacts_on_license_compliance_file_types'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :ci_job_artifacts, name: INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :ci_job_artifacts, [:job_id, :file_type], where: 'file_type = 10 OR file_type = 101', name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20201019152046_add_default_branch_to_daily_build_group_report_result.rb b/db/migrate/20201019152046_add_default_branch_to_daily_build_group_report_result.rb
new file mode 100644
index 00000000000..8a0051b8106
--- /dev/null
+++ b/db/migrate/20201019152046_add_default_branch_to_daily_build_group_report_result.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddDefaultBranchToDailyBuildGroupReportResult < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :ci_daily_build_group_report_results, :default_branch, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20201019161924_add_partitioned_table_view.rb b/db/migrate/20201019161924_add_partitioned_table_view.rb
new file mode 100644
index 00000000000..45bbfda40ff
--- /dev/null
+++ b/db/migrate/20201019161924_add_partitioned_table_view.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class AddPartitionedTableView < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ execute(<<~SQL)
+ CREATE OR REPLACE VIEW postgres_partitioned_tables AS
+ SELECT
+ pg_namespace.nspname::text || '.'::text || pg_class.relname::text AS identifier,
+ pg_class.oid AS oid,
+ pg_namespace.nspname AS schema,
+ pg_class.relname AS name,
+ CASE partitioned_tables.partstrat
+ WHEN 'l' THEN 'list'
+ WHEN 'r' THEN 'range'
+ WHEN 'h' THEN 'hash'
+ END as strategy,
+ array_agg(pg_attribute.attname) as key_columns
+ FROM (
+ SELECT
+ partrelid,
+ partstrat,
+ unnest(partattrs) as column_position
+ FROM pg_partitioned_table
+ ) partitioned_tables
+ INNER JOIN pg_class
+ ON partitioned_tables.partrelid = pg_class.oid
+ INNER JOIN pg_namespace
+ ON pg_class.relnamespace = pg_namespace.oid
+ INNER JOIN pg_attribute
+ ON pg_attribute.attrelid = pg_class.oid
+ AND pg_attribute.attnum = partitioned_tables.column_position
+ WHERE pg_namespace.nspname = current_schema()
+ GROUP BY identifier, pg_class.oid, schema, name, strategy;
+ SQL
+ end
+
+ def down
+ execute(<<~SQL)
+ DROP VIEW IF EXISTS postgres_partitioned_tables
+ SQL
+ end
+end
diff --git a/db/migrate/20201019172704_add_partitions_view.rb b/db/migrate/20201019172704_add_partitions_view.rb
new file mode 100644
index 00000000000..991d137faf3
--- /dev/null
+++ b/db/migrate/20201019172704_add_partitions_view.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+class AddPartitionsView < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ execute(<<~SQL)
+ CREATE OR REPLACE VIEW postgres_partitions AS
+ SELECT
+ pg_namespace.nspname::text || '.'::text || pg_class.relname::text AS identifier,
+ pg_class.oid AS oid,
+ pg_namespace.nspname AS schema,
+ pg_class.relname AS name,
+ parent_namespace.nspname::text || '.'::text || parent_class.relname::text AS parent_identifier,
+ pg_get_expr(pg_class.relpartbound, pg_inherits.inhrelid) AS condition
+ FROM pg_class
+ INNER JOIN pg_namespace
+ ON pg_namespace.oid = pg_class.relnamespace
+ INNER JOIN pg_inherits
+ ON pg_class.oid = pg_inherits.inhrelid
+ INNER JOIN pg_class parent_class
+ ON pg_inherits.inhparent = parent_class.oid
+ INNER JOIN pg_namespace parent_namespace
+ ON parent_class.relnamespace = parent_namespace.oid
+ WHERE pg_class.relispartition
+ AND pg_namespace.nspname IN (
+ current_schema(),
+ 'gitlab_partitions_dynamic',
+ 'gitlab_partitions_static'
+ )
+ SQL
+ end
+
+ def down
+ execute(<<~SQL)
+ DROP VIEW IF EXISTS postgres_partitions
+ SQL
+ end
+end
diff --git a/db/migrate/20201021085007_create_analytics_devops_adoption_segments.rb b/db/migrate/20201021085007_create_analytics_devops_adoption_segments.rb
new file mode 100644
index 00000000000..3e322675ba6
--- /dev/null
+++ b/db/migrate/20201021085007_create_analytics_devops_adoption_segments.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class CreateAnalyticsDevopsAdoptionSegments < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ create_table :analytics_devops_adoption_segments, if_not_exists: true do |t|
+ t.text :name, null: false, index: { unique: true }
+ t.datetime_with_timezone :last_recorded_at
+
+ t.timestamps_with_timezone
+ end
+
+ add_text_limit :analytics_devops_adoption_segments, :name, 255
+ end
+
+ def down
+ drop_table :analytics_devops_adoption_segments
+ end
+end
diff --git a/db/migrate/20201021101956_add_index_route_on_name_trigram_to_route.rb b/db/migrate/20201021101956_add_index_route_on_name_trigram_to_route.rb
new file mode 100644
index 00000000000..cf65c7500c5
--- /dev/null
+++ b/db/migrate/20201021101956_add_index_route_on_name_trigram_to_route.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexRouteOnNameTrigramToRoute < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_route_on_name_trigram'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :routes, :name, name: INDEX_NAME, using: :gin, opclass: { name: :gin_trgm_ops }
+ end
+
+ def down
+ remove_concurrent_index_by_name(:routes, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20201021102554_create_analytics_devops_adoption_segment_selections.rb b/db/migrate/20201021102554_create_analytics_devops_adoption_segment_selections.rb
new file mode 100644
index 00000000000..c5aac7a82a5
--- /dev/null
+++ b/db/migrate/20201021102554_create_analytics_devops_adoption_segment_selections.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class CreateAnalyticsDevopsAdoptionSegmentSelections < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ create_table :analytics_devops_adoption_segment_selections do |t|
+ t.references :segment, index: { name: 'index_on_segment_selections_segment_id' }, null: false, foreign_key: { to_table: :analytics_devops_adoption_segments, on_delete: :cascade }
+ t.bigint :group_id
+ t.bigint :project_id
+ t.index [:group_id, :segment_id], unique: true, name: 'index_on_segment_selections_group_id_segment_id'
+ t.index [:project_id, :segment_id], unique: true, name: 'index_on_segment_selections_project_id_segment_id'
+
+ t.timestamps_with_timezone
+ end
+ end
+end
diff --git a/db/migrate/20201021105347_add_foreign_key_project_id_to_segment_selection.rb b/db/migrate/20201021105347_add_foreign_key_project_id_to_segment_selection.rb
new file mode 100644
index 00000000000..651770e059c
--- /dev/null
+++ b/db/migrate/20201021105347_add_foreign_key_project_id_to_segment_selection.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddForeignKeyProjectIdToSegmentSelection < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key(:analytics_devops_adoption_segment_selections, :projects, column: :project_id, on_delete: :cascade)
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :analytics_devops_adoption_segment_selections, column: :project_id
+ end
+ end
+end
diff --git a/db/migrate/20201021105600_add_foreign_key_group_id_to_segment_selection.rb b/db/migrate/20201021105600_add_foreign_key_group_id_to_segment_selection.rb
new file mode 100644
index 00000000000..3ee73ee3a64
--- /dev/null
+++ b/db/migrate/20201021105600_add_foreign_key_group_id_to_segment_selection.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddForeignKeyGroupIdToSegmentSelection < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key(:analytics_devops_adoption_segment_selections, :namespaces, column: :group_id, on_delete: :cascade)
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :analytics_devops_adoption_segment_selections, column: :group_id
+ end
+ end
+end
diff --git a/db/migrate/20201021105959_add_check_constraint_to_segment_selection.rb b/db/migrate/20201021105959_add_check_constraint_to_segment_selection.rb
new file mode 100644
index 00000000000..68fec36aa8a
--- /dev/null
+++ b/db/migrate/20201021105959_add_check_constraint_to_segment_selection.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddCheckConstraintToSegmentSelection < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ CONSTRAINT_NAME = 'segment_selection_project_id_or_group_id_required'
+
+ def up
+ add_check_constraint :analytics_devops_adoption_segment_selections, '(project_id != NULL AND group_id IS NULL) OR (group_id != NULL AND project_id IS NULL)', CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint :analytics_devops_adoption_segment_selections, CONSTRAINT_NAME
+ end
+end
diff --git a/db/migrate/20201021142812_add_index_to_ci_daily_build_group_report_results.rb b/db/migrate/20201021142812_add_index_to_ci_daily_build_group_report_results.rb
new file mode 100644
index 00000000000..c811e3deeda
--- /dev/null
+++ b/db/migrate/20201021142812_add_index_to_ci_daily_build_group_report_results.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class AddIndexToCiDailyBuildGroupReportResults < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_ci_daily_build_group_report_results_on_project_and_date'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(
+ :ci_daily_build_group_report_results,
+ [:project_id, :date],
+ order: { date: :desc },
+ where: "default_branch = TRUE AND (data -> 'coverage') IS NOT NULL",
+ name: INDEX_NAME
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name(:ci_daily_build_group_report_results, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20201021152210_add_secret_detection_token_revocation_application_settings.rb b/db/migrate/20201021152210_add_secret_detection_token_revocation_application_settings.rb
new file mode 100644
index 00000000000..6334dcd8c1a
--- /dev/null
+++ b/db/migrate/20201021152210_add_secret_detection_token_revocation_application_settings.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddSecretDetectionTokenRevocationApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ add_column :application_settings, :secret_detection_token_revocation_enabled, :boolean, default: false, null: false
+ add_column :application_settings, :secret_detection_token_revocation_url, :text, null: true # rubocop:disable Migration/AddLimitToTextColumns
+
+ add_column :application_settings, :encrypted_secret_detection_token_revocation_token, :text
+ add_column :application_settings, :encrypted_secret_detection_token_revocation_token_iv, :text
+ end
+
+ def down
+ remove_column :application_settings, :secret_detection_token_revocation_enabled
+ remove_column :application_settings, :secret_detection_token_revocation_url
+
+ remove_column :application_settings, :encrypted_secret_detection_token_revocation_token
+ remove_column :application_settings, :encrypted_secret_detection_token_revocation_token_iv
+ end
+end
diff --git a/db/migrate/20201021190539_add_text_limit_to_secret_detection_token_revocation_application_settings.rb b/db/migrate/20201021190539_add_text_limit_to_secret_detection_token_revocation_application_settings.rb
new file mode 100644
index 00000000000..ea5e12322d0
--- /dev/null
+++ b/db/migrate/20201021190539_add_text_limit_to_secret_detection_token_revocation_application_settings.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddTextLimitToSecretDetectionTokenRevocationApplicationSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :application_settings, :secret_detection_token_revocation_url, 255
+ end
+
+ def down
+ remove_text_limit :application_settings, :secret_detection_token_revocation_url
+ end
+end
diff --git a/db/migrate/20201021220101_add_merge_trains_enabled.rb b/db/migrate/20201021220101_add_merge_trains_enabled.rb
new file mode 100644
index 00000000000..88a71897435
--- /dev/null
+++ b/db/migrate/20201021220101_add_merge_trains_enabled.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddMergeTrainsEnabled < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :project_ci_cd_settings, :merge_trains_enabled, :boolean, default: false, allow_null: false
+ end
+end
diff --git a/db/migrate/20201022080802_add_repository_read_only_to_snippets.rb b/db/migrate/20201022080802_add_repository_read_only_to_snippets.rb
new file mode 100644
index 00000000000..d0cb329fb02
--- /dev/null
+++ b/db/migrate/20201022080802_add_repository_read_only_to_snippets.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddRepositoryReadOnlyToSnippets < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :snippets, :repository_read_only, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20201022094845_add_historical_data_recorded_at.rb b/db/migrate/20201022094845_add_historical_data_recorded_at.rb
new file mode 100644
index 00000000000..c90889e2d38
--- /dev/null
+++ b/db/migrate/20201022094845_add_historical_data_recorded_at.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddHistoricalDataRecordedAt < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ add_column(:historical_data, :recorded_at, :timestamptz)
+ end
+
+ def down
+ remove_column(:historical_data, :recorded_at)
+ end
+end
diff --git a/db/migrate/20201022094846_update_historical_data_recorded_at.rb b/db/migrate/20201022094846_update_historical_data_recorded_at.rb
new file mode 100644
index 00000000000..bd1889149bb
--- /dev/null
+++ b/db/migrate/20201022094846_update_historical_data_recorded_at.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class UpdateHistoricalDataRecordedAt < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ update_value = Arel.sql("COALESCE(created_at, date + '12:00'::time AT TIME ZONE '#{Time.zone&.tzinfo&.name || "Etc/UTC"}')")
+
+ update_column_in_batches(:historical_data, :recorded_at, update_value) do |table, query|
+ query.where(table[:recorded_at].eq(nil))
+ end
+
+ add_not_null_constraint :historical_data, :recorded_at
+
+ change_column_null :historical_data, :date, true
+ end
+
+ def down
+ change_column_null :historical_data, :date, false
+
+ remove_not_null_constraint :historical_data, :recorded_at
+
+ update_column_in_batches(:historical_data, :recorded_at, nil) do |table, query|
+ query.where(table[:recorded_at].not_eq(nil))
+ end
+ end
+end
diff --git a/db/migrate/20201022103304_add_availability_to_user_statuses.rb b/db/migrate/20201022103304_add_availability_to_user_statuses.rb
new file mode 100644
index 00000000000..9144c81fcfb
--- /dev/null
+++ b/db/migrate/20201022103304_add_availability_to_user_statuses.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddAvailabilityToUserStatuses < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :user_statuses, :availability, :integer, limit: 2, default: 0, null: false
+ end
+end
diff --git a/db/migrate/20201022144501_create_snippet_repository_storage_move.rb b/db/migrate/20201022144501_create_snippet_repository_storage_move.rb
new file mode 100644
index 00000000000..7db38191942
--- /dev/null
+++ b/db/migrate/20201022144501_create_snippet_repository_storage_move.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class CreateSnippetRepositoryStorageMove < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:snippet_repository_storage_moves)
+ with_lock_retries do
+ create_table :snippet_repository_storage_moves do |t|
+ t.timestamps_with_timezone
+ t.references :snippet, index: true, null: false, foreign_key: { on_delete: :cascade }
+ t.integer :state, limit: 2, default: 1, null: false
+ t.text :source_storage_name, null: false
+ t.text :destination_storage_name, null: false
+ end
+ end
+ end
+
+ add_text_limit(:snippet_repository_storage_moves, :source_storage_name, 255, constraint_name: 'snippet_repository_storage_moves_source_storage_name')
+ add_text_limit(:snippet_repository_storage_moves, :destination_storage_name, 255, constraint_name: 'snippet_repository_storage_moves_destination_storage_name')
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :snippet_repository_storage_moves
+ end
+ end
+end
diff --git a/db/migrate/20201022191817_add_has_vulnerabilities_into_project_settings.rb b/db/migrate/20201022191817_add_has_vulnerabilities_into_project_settings.rb
new file mode 100644
index 00000000000..bb2d683c4e2
--- /dev/null
+++ b/db/migrate/20201022191817_add_has_vulnerabilities_into_project_settings.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddHasVulnerabilitiesIntoProjectSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :project_settings, :has_vulnerabilities, :boolean, default: false, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :project_settings, :has_vulnerabilities
+ end
+ end
+end
diff --git a/db/migrate/20201022192254_index_project_settings_on_project_id_partially.rb b/db/migrate/20201022192254_index_project_settings_on_project_id_partially.rb
new file mode 100644
index 00000000000..57247bd0f22
--- /dev/null
+++ b/db/migrate/20201022192254_index_project_settings_on_project_id_partially.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class IndexProjectSettingsOnProjectIdPartially < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_project_settings_on_project_id_partially'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :project_settings, :project_id, name: INDEX_NAME, where: 'has_vulnerabilities IS TRUE'
+ end
+
+ def down
+ remove_concurrent_index_by_name :project_settings, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20201023114628_create_merge_request_cleanup_schedules.rb b/db/migrate/20201023114628_create_merge_request_cleanup_schedules.rb
new file mode 100644
index 00000000000..f63738682b1
--- /dev/null
+++ b/db/migrate/20201023114628_create_merge_request_cleanup_schedules.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class CreateMergeRequestCleanupSchedules < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ create_table :merge_request_cleanup_schedules, id: false do |t|
+ t.references :merge_request, primary_key: true, index: { unique: true }, null: false, foreign_key: { on_delete: :cascade }
+ t.datetime_with_timezone :scheduled_at, null: false
+ t.datetime_with_timezone :completed_at, null: true
+
+ t.timestamps_with_timezone
+
+ t.index :scheduled_at, where: 'completed_at IS NULL', name: 'index_mr_cleanup_schedules_timestamps'
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :merge_request_cleanup_schedules
+ end
+ end
+end
diff --git a/db/migrate/20201026200736_seed_merge_trains_enabled.rb b/db/migrate/20201026200736_seed_merge_trains_enabled.rb
new file mode 100644
index 00000000000..c22c2a408bc
--- /dev/null
+++ b/db/migrate/20201026200736_seed_merge_trains_enabled.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class SeedMergeTrainsEnabled < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ update_column_in_batches(:project_ci_cd_settings, :merge_trains_enabled, true) do |table, query|
+ query.where(table[:merge_pipelines_enabled].eq(true))
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20201027002551_migrate_services_to_http_integrations.rb b/db/migrate/20201027002551_migrate_services_to_http_integrations.rb
new file mode 100644
index 00000000000..5fe05320862
--- /dev/null
+++ b/db/migrate/20201027002551_migrate_services_to_http_integrations.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+class MigrateServicesToHttpIntegrations < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ ALERT_SERVICE_TYPE = 'AlertsService'
+ SERVICE_NAMES_IDENTIFIER = {
+ name: 'HTTP endpoint',
+ identifier: 'legacy'
+ }
+
+ class HttpIntegration < ActiveRecord::Base
+ self.table_name = 'alert_management_http_integrations'
+ end
+
+ # For each Alerts service,
+ # Create the matching HttpIntegration
+ def up
+ HttpIntegration.reset_column_information
+
+ sql = <<~SQL
+ SELECT * FROM services
+ JOIN alerts_service_data
+ ON (services.id = alerts_service_data.service_id)
+ WHERE type = '#{ALERT_SERVICE_TYPE}'
+ AND active = TRUE
+ SQL
+
+ current_time = Time.current
+
+ values = select_all(sql).map do |alerts_service|
+ {
+ project_id: alerts_service['project_id'],
+ name: SERVICE_NAMES_IDENTIFIER[:name],
+ endpoint_identifier: SERVICE_NAMES_IDENTIFIER[:identifier],
+ encrypted_token: alerts_service['encrypted_token'],
+ encrypted_token_iv: alerts_service['encrypted_token_iv'],
+ active: alerts_service['active'],
+ updated_at: current_time,
+ created_at: current_time
+ }
+ end
+
+ HttpIntegration.insert_all(values) if values.present?
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20201027135651_add_auto_rollback_setting.rb b/db/migrate/20201027135651_add_auto_rollback_setting.rb
new file mode 100644
index 00000000000..8e916ac9d36
--- /dev/null
+++ b/db/migrate/20201027135651_add_auto_rollback_setting.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddAutoRollbackSetting < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :project_ci_cd_settings, :auto_rollback_enabled, :boolean, default: false, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :project_ci_cd_settings, :auto_rollback_enabled
+ end
+ end
+end
diff --git a/db/migrate/20201027210127_add_index_to_oauth_access_grants_resource_owner_id.rb b/db/migrate/20201027210127_add_index_to_oauth_access_grants_resource_owner_id.rb
new file mode 100644
index 00000000000..035d2fb4386
--- /dev/null
+++ b/db/migrate/20201027210127_add_index_to_oauth_access_grants_resource_owner_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexToOauthAccessGrantsResourceOwnerId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_oauth_access_grants_on_resource_owner_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :oauth_access_grants, %i[resource_owner_id application_id created_at], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :oauth_access_grants, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20201027211138_increase_default_diff_max_patch_bytes.rb b/db/migrate/20201027211138_increase_default_diff_max_patch_bytes.rb
new file mode 100644
index 00000000000..92d9025706f
--- /dev/null
+++ b/db/migrate/20201027211138_increase_default_diff_max_patch_bytes.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class IncreaseDefaultDiffMaxPatchBytes < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ change_column_default(:application_settings, :diff_max_patch_bytes, from: 102400, to: 204800)
+ end
+end
diff --git a/db/migrate/20201028160831_add_temporary_index_to_vulnerabilities_table.rb b/db/migrate/20201028160831_add_temporary_index_to_vulnerabilities_table.rb
new file mode 100644
index 00000000000..05bb75be75a
--- /dev/null
+++ b/db/migrate/20201028160831_add_temporary_index_to_vulnerabilities_table.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddTemporaryIndexToVulnerabilitiesTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'temporary_index_vulnerabilities_on_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerabilities, :id, where: "state = 2 AND (dismissed_at IS NULL OR dismissed_by_id IS NULL)", name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20201028184640_add_helm_major_version_to_clusters.rb b/db/migrate/20201028184640_add_helm_major_version_to_clusters.rb
new file mode 100644
index 00000000000..2169fd41826
--- /dev/null
+++ b/db/migrate/20201028184640_add_helm_major_version_to_clusters.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 AddHelmMajorVersionToClusters < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column(:clusters, :helm_major_version, :integer, default: 2, null: false)
+ end
+end
diff --git a/db/migrate/20201028204306_migrate_default_diff_max_patch_bytes_to_minimum_200kb.rb b/db/migrate/20201028204306_migrate_default_diff_max_patch_bytes_to_minimum_200kb.rb
new file mode 100644
index 00000000000..11d47904e67
--- /dev/null
+++ b/db/migrate/20201028204306_migrate_default_diff_max_patch_bytes_to_minimum_200kb.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class MigrateDefaultDiffMaxPatchBytesToMinimum200kb < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+ MAX_SIZE = 200.kilobytes
+
+ class ApplicationSetting < ActiveRecord::Base
+ self.table_name = 'application_settings'
+ end
+
+ def up
+ table = ApplicationSetting.arel_table
+ ApplicationSetting.where(table[:diff_max_patch_bytes].lt(MAX_SIZE)).update_all(diff_max_patch_bytes: MAX_SIZE)
+ end
+
+ def down
+ table = ApplicationSetting.arel_table
+ ApplicationSetting.where(table[:diff_max_patch_bytes].eq(MAX_SIZE)).update_all(diff_max_patch_bytes: 100.kilobytes)
+ end
+end
diff --git a/db/migrate/20201029143650_rename_application_settings_to_allow_deny_names.rb b/db/migrate/20201029143650_rename_application_settings_to_allow_deny_names.rb
new file mode 100644
index 00000000000..2d96da91069
--- /dev/null
+++ b/db/migrate/20201029143650_rename_application_settings_to_allow_deny_names.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class RenameApplicationSettingsToAllowDenyNames < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ rename_column_concurrently :application_settings, :domain_blacklist_enabled, :domain_denylist_enabled
+ rename_column_concurrently :application_settings, :domain_blacklist, :domain_denylist
+ rename_column_concurrently :application_settings, :domain_whitelist, :domain_allowlist
+ end
+
+ def down
+ undo_rename_column_concurrently :application_settings, :domain_blacklist_enabled, :domain_denylist_enabled
+ undo_rename_column_concurrently :application_settings, :domain_blacklist, :domain_denylist
+ undo_rename_column_concurrently :application_settings, :domain_whitelist, :domain_allowlist
+ end
+end
diff --git a/db/migrate/20201029144444_create_vulnerability_finding_links.rb b/db/migrate/20201029144444_create_vulnerability_finding_links.rb
new file mode 100644
index 00000000000..80f93b9a0af
--- /dev/null
+++ b/db/migrate/20201029144444_create_vulnerability_finding_links.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class CreateVulnerabilityFindingLinks < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ create_table :vulnerability_finding_links, if_not_exists: true do |t|
+ t.timestamps_with_timezone null: false
+ t.references :vulnerability_occurrence, index: { name: 'finding_links_on_vulnerability_occurrence_id' }, null: false, foreign_key: { on_delete: :cascade }
+ t.text :name, limit: 255
+ t.text :url, limit: 2048, null: false
+ end
+
+ add_text_limit :vulnerability_finding_links, :name, 255
+ add_text_limit :vulnerability_finding_links, :url, 2048
+ end
+
+ def down
+ drop_table :vulnerability_finding_links
+ end
+end
diff --git a/db/migrate/20201030092151_add_requirements_access_level_to_project_features.rb b/db/migrate/20201030092151_add_requirements_access_level_to_project_features.rb
new file mode 100644
index 00000000000..e4ba7b2adb9
--- /dev/null
+++ b/db/migrate/20201030092151_add_requirements_access_level_to_project_features.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddRequirementsAccessLevelToProjectFeatures < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ unless column_exists?(:project_features, :requirements_access_level)
+ with_lock_retries { add_column :project_features, :requirements_access_level, :integer, default: 20, null: false }
+ end
+ end
+
+ def down
+ if column_exists?(:project_features, :requirements_access_level)
+ with_lock_retries { remove_column :project_features, :requirements_access_level }
+ end
+ end
+end
diff --git a/db/migrate/20201030200115_add_iid_to_design_management_design.rb b/db/migrate/20201030200115_add_iid_to_design_management_design.rb
new file mode 100644
index 00000000000..c31cd86d5e2
--- /dev/null
+++ b/db/migrate/20201030200115_add_iid_to_design_management_design.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddIidToDesignManagementDesign < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :design_management_designs, :iid, :integer
+ end
+end
diff --git a/db/migrate/20201030200539_add_index_on_design_management_designs_iid_project_id.rb b/db/migrate/20201030200539_add_index_on_design_management_designs_iid_project_id.rb
new file mode 100644
index 00000000000..3ff50c299cb
--- /dev/null
+++ b/db/migrate/20201030200539_add_index_on_design_management_designs_iid_project_id.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddIndexOnDesignManagementDesignsIidProjectId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_design_management_designs_on_iid_and_project_id'
+
+ def up
+ add_concurrent_index :design_management_designs, [:project_id, :iid],
+ name: INDEX_NAME,
+ unique: true
+ end
+
+ def down
+ remove_concurrent_index_by_name :design_management_designs, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20201102184743_add_index_to_incident_issues_on_project_and_created_at.rb b/db/migrate/20201102184743_add_index_to_incident_issues_on_project_and_created_at.rb
new file mode 100644
index 00000000000..1fd900002c3
--- /dev/null
+++ b/db/migrate/20201102184743_add_index_to_incident_issues_on_project_and_created_at.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class AddIndexToIncidentIssuesOnProjectAndCreatedAt < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ INCIDENT_TYPE = 1
+ OLD_INDEX_NAME = 'index_issues_project_id_issue_type_incident'
+ NEW_INDEX_NAME = 'index_issues_on_project_id_and_created_at_issue_type_incident'
+
+ DOWNTIME = false
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :issues,
+ [:project_id, :created_at],
+ where: "issue_type = #{INCIDENT_TYPE}",
+ name: NEW_INDEX_NAME
+
+ remove_concurrent_index_by_name :issues, OLD_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :issues,
+ :project_id,
+ where: "issue_type = #{INCIDENT_TYPE}",
+ name: OLD_INDEX_NAME
+
+ remove_concurrent_index_by_name :issues, NEW_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20201103095752_add_issues_closed_at_index.rb b/db/migrate/20201103095752_add_issues_closed_at_index.rb
new file mode 100644
index 00000000000..7a8ee4e8d67
--- /dev/null
+++ b/db/migrate/20201103095752_add_issues_closed_at_index.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIssuesClosedAtIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(:issues, [:project_id, :closed_at])
+ end
+
+ def down
+ remove_concurrent_index_by_name(:issues, 'index_issues_on_project_id_and_closed_at')
+ end
+end
diff --git a/db/migrate/20201103171537_add_index_active_billable_users_to_user.rb b/db/migrate/20201103171537_add_index_active_billable_users_to_user.rb
new file mode 100644
index 00000000000..3ad7a3f4ca3
--- /dev/null
+++ b/db/migrate/20201103171537_add_index_active_billable_users_to_user.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddIndexActiveBillableUsersToUser < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'active_billable_users'
+ HUMAN_TYPE = 'NULL'
+ HUMAN_SVC_BOT_TYPES = "#{HUMAN_TYPE}, 6, 4"
+ BOT_TYPES = '2,6,1,3,7,8'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :users, :id, name: INDEX_NAME, where: "(state = 'active' AND (user_type is #{HUMAN_TYPE} or user_type in (#{HUMAN_SVC_BOT_TYPES}))) and ((users.user_type IS #{HUMAN_TYPE}) OR (users.user_type <> ALL ('{#{BOT_TYPES}}')))"
+ end
+
+ def down
+ remove_concurrent_index_by_name(:users, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20201103184333_create_packages_package_file_build_infos.rb b/db/migrate/20201103184333_create_packages_package_file_build_infos.rb
new file mode 100644
index 00000000000..9cb6869cae4
--- /dev/null
+++ b/db/migrate/20201103184333_create_packages_package_file_build_infos.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class CreatePackagesPackageFileBuildInfos < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ unless table_exists?(:packages_package_file_build_infos)
+ with_lock_retries do
+ create_table :packages_package_file_build_infos do |t|
+ t.references :package_file, index: true,
+ null: false,
+ foreign_key: { to_table: :packages_package_files, on_delete: :cascade },
+ type: :bigint
+ t.references :pipeline, index: true,
+ null: true,
+ foreign_key: { to_table: :ci_pipelines, on_delete: :nullify },
+ type: :bigint
+ end
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :packages_package_file_build_infos
+ end
+ end
+end
diff --git a/db/migrate/20201103202213_update_packages_build_infos_index.rb b/db/migrate/20201103202213_update_packages_build_infos_index.rb
new file mode 100644
index 00000000000..d737517045b
--- /dev/null
+++ b/db/migrate/20201103202213_update_packages_build_infos_index.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class UpdatePackagesBuildInfosIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ NEW_INDEX_NAME = 'idx_packages_build_infos_on_package_id'
+ OLD_INDEX_NAME = 'index_packages_build_infos_on_package_id'
+
+ def up
+ add_concurrent_index :packages_build_infos, :package_id, name: NEW_INDEX_NAME
+ remove_concurrent_index_by_name :packages_build_infos, OLD_INDEX_NAME
+ end
+
+ def down
+ # No op. It is possible records would validate the UNIQUE constraint, so it
+ # cannot be added back to the index.
+ end
+end
diff --git a/db/migrate/20201104204739_create_bulk_import_trackers.rb b/db/migrate/20201104204739_create_bulk_import_trackers.rb
new file mode 100644
index 00000000000..906bd06248d
--- /dev/null
+++ b/db/migrate/20201104204739_create_bulk_import_trackers.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+class CreateBulkImportTrackers < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ unless table_exists?(:bulk_import_trackers)
+ create_table :bulk_import_trackers do |t|
+ t.references :bulk_import_entity,
+ null: false,
+ index: false,
+ foreign_key: { on_delete: :cascade }
+
+ t.text :relation, null: false
+ t.text :next_page
+ t.boolean :has_next_page, default: false, null: false
+
+ t.index %w(bulk_import_entity_id relation),
+ unique: true,
+ name: :bulk_import_trackers_uniq_relation_by_entity
+ end
+ end
+ end
+
+ add_check_constraint :bulk_import_trackers,
+ '(has_next_page IS FALSE or next_page IS NOT NULL)',
+ 'check_next_page_requirement'
+ add_text_limit :bulk_import_trackers, :relation, 255
+ add_text_limit :bulk_import_trackers, :next_page, 255
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :bulk_import_trackers
+ end
+ end
+end
diff --git a/db/migrate/20201105021637_add_uploads_size_to_project_statistics.rb b/db/migrate/20201105021637_add_uploads_size_to_project_statistics.rb
new file mode 100644
index 00000000000..1d2251f6c37
--- /dev/null
+++ b/db/migrate/20201105021637_add_uploads_size_to_project_statistics.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddUploadsSizeToProjectStatistics < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ add_column :project_statistics, :uploads_size, :bigint, default: 0, null: false
+ end
+
+ def down
+ remove_column :project_statistics, :uploads_size
+ end
+end
diff --git a/db/migrate/20201105024127_add_uploads_size_to_namespace_root_storage_statistics.rb b/db/migrate/20201105024127_add_uploads_size_to_namespace_root_storage_statistics.rb
new file mode 100644
index 00000000000..c3cccc7d5f2
--- /dev/null
+++ b/db/migrate/20201105024127_add_uploads_size_to_namespace_root_storage_statistics.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddUploadsSizeToNamespaceRootStorageStatistics < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ add_column :namespace_root_storage_statistics, :uploads_size, :bigint, default: 0, null: false
+ end
+
+ def down
+ remove_column :namespace_root_storage_statistics, :uploads_size
+ end
+end
diff --git a/db/migrate/20201105135051_change_default_value_of_ci_max_artifact_size_lsif_of_plan_limits_from20_to100.rb b/db/migrate/20201105135051_change_default_value_of_ci_max_artifact_size_lsif_of_plan_limits_from20_to100.rb
new file mode 100644
index 00000000000..d53f81ecabb
--- /dev/null
+++ b/db/migrate/20201105135051_change_default_value_of_ci_max_artifact_size_lsif_of_plan_limits_from20_to100.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class ChangeDefaultValueOfCiMaxArtifactSizeLsifOfPlanLimitsFrom20To100 < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ change_column_default :plan_limits, :ci_max_artifact_size_lsif, 100
+ execute('UPDATE plan_limits SET ci_max_artifact_size_lsif = 100 WHERE ci_max_artifact_size_lsif = 20')
+ end
+ end
+
+ def down
+ with_lock_retries do
+ change_column_default :plan_limits, :ci_max_artifact_size_lsif, 20
+ execute('UPDATE plan_limits SET ci_max_artifact_size_lsif = 20 WHERE ci_max_artifact_size_lsif = 100')
+ end
+ end
+end
diff --git a/db/migrate/20201105143211_add_vulnerabilities_enabled_and_issuetype_to_jira_tracker_data.rb b/db/migrate/20201105143211_add_vulnerabilities_enabled_and_issuetype_to_jira_tracker_data.rb
new file mode 100644
index 00000000000..27269de611c
--- /dev/null
+++ b/db/migrate/20201105143211_add_vulnerabilities_enabled_and_issuetype_to_jira_tracker_data.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddVulnerabilitiesEnabledAndIssuetypeToJiraTrackerData < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20201105143312_add_text_limit_to_jira_tracker_data_issuetype.rb
+ def change
+ add_column :jira_tracker_data, :vulnerabilities_issuetype, :text
+ add_column :jira_tracker_data, :vulnerabilities_enabled, :boolean, default: false, null: false
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20201105143312_add_text_limit_to_jira_tracker_data_issuetype.rb b/db/migrate/20201105143312_add_text_limit_to_jira_tracker_data_issuetype.rb
new file mode 100644
index 00000000000..4a81b0ce7af
--- /dev/null
+++ b/db/migrate/20201105143312_add_text_limit_to_jira_tracker_data_issuetype.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddTextLimitToJiraTrackerDataIssuetype < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :jira_tracker_data, :vulnerabilities_issuetype, 255
+ end
+
+ def down
+ remove_text_limit :jira_tracker_data, :vulnerabilities_issuetype
+ end
+end
diff --git a/db/migrate/20201106134139_add_pipelines_created_index.rb b/db/migrate/20201106134139_add_pipelines_created_index.rb
new file mode 100644
index 00000000000..aaf6643cf0b
--- /dev/null
+++ b/db/migrate/20201106134139_add_pipelines_created_index.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddPipelinesCreatedIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_NAME = :index_ci_pipelines_on_project_id_and_status_and_created_at
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_pipelines, [:project_id, :status, :created_at], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_pipelines, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20201107032257_add_default_true_require_admin_approval_after_user_signup_to_application_settings.rb b/db/migrate/20201107032257_add_default_true_require_admin_approval_after_user_signup_to_application_settings.rb
new file mode 100644
index 00000000000..196f7bd8359
--- /dev/null
+++ b/db/migrate/20201107032257_add_default_true_require_admin_approval_after_user_signup_to_application_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddDefaultTrueRequireAdminApprovalAfterUserSignupToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ change_column_default :application_settings, :require_admin_approval_after_user_signup, from: false, to: true
+ end
+end
diff --git a/db/migrate/20201109144634_add_region_field_to_aws_role.rb b/db/migrate/20201109144634_add_region_field_to_aws_role.rb
new file mode 100644
index 00000000000..ced75f24552
--- /dev/null
+++ b/db/migrate/20201109144634_add_region_field_to_aws_role.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddRegionFieldToAwsRole < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless column_exists?(:aws_roles, :region)
+ add_column :aws_roles, :region, :text
+ end
+
+ add_text_limit :aws_roles, :region, 255
+ end
+
+ def down
+ remove_column :aws_roles, :region
+ end
+end
diff --git a/db/migrate/20201109180311_add_secret_detection_revocation_token_types_application_settings.rb b/db/migrate/20201109180311_add_secret_detection_revocation_token_types_application_settings.rb
new file mode 100644
index 00000000000..0823655f92f
--- /dev/null
+++ b/db/migrate/20201109180311_add_secret_detection_revocation_token_types_application_settings.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddSecretDetectionRevocationTokenTypesApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ add_column :application_settings, :secret_detection_revocation_token_types_url, :text, null: true # rubocop:disable Migration/AddLimitToTextColumns
+ end
+
+ def down
+ remove_column :application_settings, :secret_detection_revocation_token_types_url
+ end
+end
diff --git a/db/migrate/20201109184023_add_text_limit_to_secret_detection_revocation_token_types_application_settings.rb b/db/migrate/20201109184023_add_text_limit_to_secret_detection_revocation_token_types_application_settings.rb
new file mode 100644
index 00000000000..9e0329aafcc
--- /dev/null
+++ b/db/migrate/20201109184023_add_text_limit_to_secret_detection_revocation_token_types_application_settings.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddTextLimitToSecretDetectionRevocationTokenTypesApplicationSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :application_settings, :secret_detection_revocation_token_types_url, 255
+ end
+
+ def down
+ remove_text_limit :application_settings, :secret_detection_revocation_token_types_url
+ end
+end
diff --git a/db/migrate/20201110035029_created_index_for_vulnerability_occurrences_on_project_fingerprint.rb b/db/migrate/20201110035029_created_index_for_vulnerability_occurrences_on_project_fingerprint.rb
new file mode 100644
index 00000000000..fed117d5f08
--- /dev/null
+++ b/db/migrate/20201110035029_created_index_for_vulnerability_occurrences_on_project_fingerprint.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class CreatedIndexForVulnerabilityOccurrencesOnProjectFingerprint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_vulnerability_occurrences_on_project_fingerprint'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerability_occurrences, :project_fingerprint, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerability_occurrences, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20201110110454_extend_postgres_indexes_view.rb b/db/migrate/20201110110454_extend_postgres_indexes_view.rb
new file mode 100644
index 00000000000..4e9172024d3
--- /dev/null
+++ b/db/migrate/20201110110454_extend_postgres_indexes_view.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+class ExtendPostgresIndexesView < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ execute(<<~SQL)
+ DROP VIEW postgres_indexes;
+
+ CREATE VIEW postgres_indexes AS
+ SELECT (pg_namespace.nspname::text || '.'::text) || pg_class.relname::text AS identifier,
+ pg_index.indexrelid,
+ pg_namespace.nspname AS schema,
+ pg_class.relname AS name,
+ pg_index.indisunique AS "unique",
+ pg_index.indisvalid AS valid_index,
+ pg_class.relispartition AS partitioned,
+ pg_index.indisexclusion AS exclusion,
+ pg_index.indexprs IS NOT NULL as expression,
+ pg_index.indpred IS NOT NULL as partial,
+ pg_indexes.indexdef AS definition,
+ pg_relation_size(pg_class.oid::regclass) AS ondisk_size_bytes
+ FROM pg_index
+ JOIN pg_class ON pg_class.oid = pg_index.indexrelid
+ JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
+ JOIN pg_indexes ON pg_class.relname = pg_indexes.indexname
+ WHERE pg_namespace.nspname <> 'pg_catalog'::name
+ AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name]));
+ SQL
+ end
+
+ def down
+ execute(<<~SQL)
+ DROP VIEW postgres_indexes;
+
+ CREATE VIEW postgres_indexes AS
+ SELECT (pg_namespace.nspname::text || '.'::text) || pg_class.relname::text AS identifier,
+ pg_index.indexrelid,
+ pg_namespace.nspname AS schema,
+ pg_class.relname AS name,
+ pg_index.indisunique AS "unique",
+ pg_index.indisvalid AS valid_index,
+ pg_class.relispartition AS partitioned,
+ pg_index.indisexclusion AS exclusion,
+ pg_indexes.indexdef AS definition,
+ pg_relation_size(pg_class.oid::regclass) AS ondisk_size_bytes
+ FROM pg_index
+ JOIN pg_class ON pg_class.oid = pg_index.indexrelid
+ JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
+ JOIN pg_indexes ON pg_class.relname = pg_indexes.indexname
+ WHERE pg_namespace.nspname <> 'pg_catalog'::name
+ AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name]));
+ SQL
+ end
+end
diff --git a/db/migrate/20201110133629_change_index_mr_metrics_target_project_id.rb b/db/migrate/20201110133629_change_index_mr_metrics_target_project_id.rb
new file mode 100644
index 00000000000..5bd810207d8
--- /dev/null
+++ b/db/migrate/20201110133629_change_index_mr_metrics_target_project_id.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class ChangeIndexMrMetricsTargetProjectId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_merge_request_metrics_on_target_project_id_merged_at'
+ NULLS_LAST_INDEX_NAME = 'index_mr_metrics_on_target_project_id_merged_at_nulls_last'
+
+ def up
+ add_concurrent_index :merge_request_metrics, [:target_project_id, :merged_at, :id], order: { merged_at: 'DESC NULLS LAST', id: 'DESC' }, name: NULLS_LAST_INDEX_NAME
+ remove_concurrent_index_by_name(:merge_request_metrics, INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index :merge_request_metrics, [:target_project_id, :merged_at], name: INDEX_NAME
+ remove_concurrent_index_by_name(:merge_request_metrics, NULLS_LAST_INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20201111110318_add_cloud_license_auth_token_to_settings.rb b/db/migrate/20201111110318_add_cloud_license_auth_token_to_settings.rb
new file mode 100644
index 00000000000..e2069835597
--- /dev/null
+++ b/db/migrate/20201111110318_add_cloud_license_auth_token_to_settings.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddCloudLicenseAuthTokenToSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20201111110918_add_cloud_license_auth_token_application_settings_text_limit
+ def change
+ add_column :application_settings, :encrypted_cloud_license_auth_token, :text
+ add_column :application_settings, :encrypted_cloud_license_auth_token_iv, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20201111110918_add_cloud_license_auth_token_application_settings_text_limit.rb b/db/migrate/20201111110918_add_cloud_license_auth_token_application_settings_text_limit.rb
new file mode 100644
index 00000000000..fd1ee5e07bf
--- /dev/null
+++ b/db/migrate/20201111110918_add_cloud_license_auth_token_application_settings_text_limit.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddCloudLicenseAuthTokenApplicationSettingsTextLimit < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :application_settings, :encrypted_cloud_license_auth_token_iv, 255
+ end
+
+ def down
+ remove_text_limit :application_settings, :encrypted_cloud_license_auth_token_iv
+ end
+end
diff --git a/db/migrate/20201111152859_add_missing_expression_indexes.rb b/db/migrate/20201111152859_add_missing_expression_indexes.rb
new file mode 100644
index 00000000000..e2742f7f3bc
--- /dev/null
+++ b/db/migrate/20201111152859_add_missing_expression_indexes.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+class AddMissingExpressionIndexes < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEXES = [
+ [:namespaces, :index_on_namespaces_lower_name, 'LOWER(name)'],
+ [:namespaces, :index_on_namespaces_lower_path, 'LOWER(path)'],
+ [:projects, :index_on_projects_lower_path, 'LOWER(path)'],
+ [:routes, :index_on_routes_lower_path, 'LOWER(path)'],
+ [:users, :index_on_users_lower_username, 'LOWER(username)'],
+ [:users, :index_on_users_lower_email, 'LOWER(email)']
+ ]
+
+ def up
+ # Those indexes had been introduced before, but they haven't been
+ # captured in structure.sql. For installations that already have it,
+ # this is a no-op - others will get it retroactively with
+ # this migration.
+
+ tables = Set.new
+
+ INDEXES.each do |(table, name, expression)|
+ unless index_name_exists?(table, name)
+ add_concurrent_index table, expression, name: name
+ tables.add(table)
+ end
+ end
+
+ # Rebuild statistics on affected tables only
+ tables.each do |table|
+ execute("ANALYZE #{table}")
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20201112195322_reseed_merge_trains_enabled.rb b/db/migrate/20201112195322_reseed_merge_trains_enabled.rb
new file mode 100644
index 00000000000..777c59d16b1
--- /dev/null
+++ b/db/migrate/20201112195322_reseed_merge_trains_enabled.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class ReseedMergeTrainsEnabled < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ update_column_in_batches(:project_ci_cd_settings, :merge_trains_enabled, true) do |table, query|
+ query.where(table[:merge_pipelines_enabled].eq(true))
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20201015073808_schedule_blocked_by_links_replacement.rb b/db/post_migrate/20201015073808_schedule_blocked_by_links_replacement.rb
index 7833d7c4c04..dd8cbb57136 100644
--- a/db/post_migrate/20201015073808_schedule_blocked_by_links_replacement.rb
+++ b/db/post_migrate/20201015073808_schedule_blocked_by_links_replacement.rb
@@ -19,10 +19,8 @@ class ScheduleBlockedByLinksReplacement < ActiveRecord::Migration[6.0]
end
def up
- relation = IssueLink.where(link_type: 2)
-
- queue_background_migration_jobs_by_range_at_intervals(
- relation, MIGRATION, INTERVAL, batch_size: BATCH_SIZE)
+ # no-op
+ # superseded by db/post_migrate/20201102073808_schedule_blocked_by_links_replacement_second_try.rb
end
def down
diff --git a/db/post_migrate/20201019094741_rename_sitemap_root_namespaces.rb b/db/post_migrate/20201019094741_rename_sitemap_root_namespaces.rb
new file mode 100644
index 00000000000..20812a53bfb
--- /dev/null
+++ b/db/post_migrate/20201019094741_rename_sitemap_root_namespaces.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class RenameSitemapRootNamespaces < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+ include Gitlab::Database::RenameReservedPathsMigration::V1
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ # We're taking over the /sitemap.xml and /sitemap.xml.gz namespaces
+ # since they're necessary for the default behavior of Sitemaps
+ def up
+ disable_statement_timeout do
+ rename_root_paths(['sitemap.xml', 'sitemap.xml.gz'])
+ end
+ end
+
+ def down
+ disable_statement_timeout do
+ revert_renames
+ end
+ end
+end
diff --git a/db/post_migrate/20201020102551_remove_index_service_for_usage_data.rb b/db/post_migrate/20201020102551_remove_index_service_for_usage_data.rb
new file mode 100644
index 00000000000..a0d39ecd2c1
--- /dev/null
+++ b/db/post_migrate/20201020102551_remove_index_service_for_usage_data.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class RemoveIndexServiceForUsageData < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_services_on_type_id_when_active_not_instance_not_template'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :services, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :services, [:type, :id], where: 'active = TRUE AND instance = FALSE AND template = FALSE', name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20201026051643_remove_scanned_resources_count_from_security_scans.rb b/db/post_migrate/20201026051643_remove_scanned_resources_count_from_security_scans.rb
new file mode 100644
index 00000000000..208448e2278
--- /dev/null
+++ b/db/post_migrate/20201026051643_remove_scanned_resources_count_from_security_scans.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class RemoveScannedResourcesCountFromSecurityScans < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ remove_column :security_scans, :scanned_resources_count
+ end
+
+ def down
+ add_column :security_scans, :scanned_resources_count, :integer
+ end
+end
diff --git a/db/post_migrate/20201026182253_schedule_populate_vulnerability_feedback_pipeline_id.rb b/db/post_migrate/20201026182253_schedule_populate_vulnerability_feedback_pipeline_id.rb
new file mode 100644
index 00000000000..2df475ab2a8
--- /dev/null
+++ b/db/post_migrate/20201026182253_schedule_populate_vulnerability_feedback_pipeline_id.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class SchedulePopulateVulnerabilityFeedbackPipelineId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INTERVAL = 2.minutes.to_i
+ BATCH_SIZE = 100
+ MIGRATION = 'PopulateVulnerabilityFeedbackPipelineId'
+
+ disable_ddl_transaction!
+
+ def up
+ return unless Gitlab.ee?
+
+ vulnerability_feedback = exec_query <<~SQL
+ SELECT DISTINCT "vulnerability_feedback"."project_id"
+ FROM "vulnerability_feedback"
+ WHERE "vulnerability_feedback"."pipeline_id" IS NULL
+ ORDER BY "vulnerability_feedback"."project_id" ASC
+ SQL
+
+ return if vulnerability_feedback.rows.blank?
+
+ vulnerability_feedback.rows.flatten.in_groups_of(BATCH_SIZE, false).each_with_index do |project_ids, index|
+ migrate_in(index * INTERVAL, MIGRATION, [project_ids])
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20201028160832_schedule_populate_missing_dismissal_information_for_vulnerabilities.rb b/db/post_migrate/20201028160832_schedule_populate_missing_dismissal_information_for_vulnerabilities.rb
new file mode 100644
index 00000000000..f358ea863db
--- /dev/null
+++ b/db/post_migrate/20201028160832_schedule_populate_missing_dismissal_information_for_vulnerabilities.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class SchedulePopulateMissingDismissalInformationForVulnerabilities < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ BATCH_SIZE = 1_000
+ DELAY_INTERVAL = 3.minutes.to_i
+ MIGRATION_CLASS = 'PopulateMissingVulnerabilityDismissalInformation'
+
+ disable_ddl_transaction!
+
+ def up
+ ::Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation::Vulnerability.broken.each_batch(of: BATCH_SIZE) do |batch, index|
+ vulnerability_ids = batch.pluck(:id)
+ migrate_in(index * DELAY_INTERVAL, MIGRATION_CLASS, vulnerability_ids)
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20201028182809_backfill_jira_tracker_deployment_type2.rb b/db/post_migrate/20201028182809_backfill_jira_tracker_deployment_type2.rb
new file mode 100644
index 00000000000..63a0554433c
--- /dev/null
+++ b/db/post_migrate/20201028182809_backfill_jira_tracker_deployment_type2.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class BackfillJiraTrackerDeploymentType2 < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ MIGRATION = 'BackfillJiraTrackerDeploymentType2'
+ DELAY_INTERVAL = 2.minutes
+ BATCH_SIZE = 1000
+
+ disable_ddl_transaction!
+
+ class JiraTrackerData < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'jira_tracker_data'
+ end
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ JiraTrackerData.where(deployment_type: 0),
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ track_jobs: true)
+ end
+
+ def down
+ # NOOP
+ end
+end
diff --git a/db/post_migrate/20201029052241_migrate_geo_blob_verification_primary_worker_sidekiq_queue.rb b/db/post_migrate/20201029052241_migrate_geo_blob_verification_primary_worker_sidekiq_queue.rb
new file mode 100644
index 00000000000..64d22863389
--- /dev/null
+++ b/db/post_migrate/20201029052241_migrate_geo_blob_verification_primary_worker_sidekiq_queue.rb
@@ -0,0 +1,18 @@
+# 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 MigrateGeoBlobVerificationPrimaryWorkerSidekiqQueue < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ sidekiq_queue_migrate 'geo:geo_blob_verification_primary', to: 'geo:geo_verification'
+ end
+
+ def down
+ sidekiq_queue_migrate 'geo:geo_verification', to: 'geo:geo_blob_verification_primary'
+ end
+end
diff --git a/db/post_migrate/20201029144157_cleanup_application_settings_to_allow_deny_rename.rb b/db/post_migrate/20201029144157_cleanup_application_settings_to_allow_deny_rename.rb
new file mode 100644
index 00000000000..bb6fe4258c5
--- /dev/null
+++ b/db/post_migrate/20201029144157_cleanup_application_settings_to_allow_deny_rename.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class CleanupApplicationSettingsToAllowDenyRename < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_rename :application_settings, :domain_blacklist_enabled, :domain_denylist_enabled
+ cleanup_concurrent_column_rename :application_settings, :domain_blacklist, :domain_denylist
+ cleanup_concurrent_column_rename :application_settings, :domain_whitelist, :domain_allowlist
+ end
+
+ def down
+ undo_cleanup_concurrent_column_rename :application_settings, :domain_blacklist_enabled, :domain_denylist_enabled
+ undo_cleanup_concurrent_column_rename :application_settings, :domain_blacklist, :domain_denylist
+ undo_cleanup_concurrent_column_rename :application_settings, :domain_whitelist, :domain_allowlist
+ end
+end
diff --git a/db/post_migrate/20201030203854_backfill_design_iids.rb b/db/post_migrate/20201030203854_backfill_design_iids.rb
new file mode 100644
index 00000000000..7acca6ad93d
--- /dev/null
+++ b/db/post_migrate/20201030203854_backfill_design_iids.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class BackfillDesignIids < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class Designs < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'design_management_designs'
+ end
+
+ def up
+ backfill = ::Gitlab::BackgroundMigration::BackfillDesignInternalIds.new(Designs)
+
+ Designs.select(:project_id).distinct.each_batch(of: 100, column: :project_id) do |relation|
+ backfill.perform(relation)
+ end
+ end
+
+ def down
+ # NOOP
+ end
+end
diff --git a/db/post_migrate/20201102073808_schedule_blocked_by_links_replacement_second_try.rb b/db/post_migrate/20201102073808_schedule_blocked_by_links_replacement_second_try.rb
new file mode 100644
index 00000000000..217d4f81d26
--- /dev/null
+++ b/db/post_migrate/20201102073808_schedule_blocked_by_links_replacement_second_try.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class ScheduleBlockedByLinksReplacementSecondTry < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INTERVAL = 2.minutes
+ # at the time of writing there were 12931 blocked_by issues:
+ # estimated time is 13 batches * 2 minutes -> 26 minutes
+ BATCH_SIZE = 1000
+ MIGRATION = 'ReplaceBlockedByLinks'
+
+ disable_ddl_transaction!
+
+ class IssueLink < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'issue_links'
+ end
+
+ def up
+ relation = IssueLink.where(link_type: 2)
+
+ queue_background_migration_jobs_by_range_at_intervals(
+ relation, MIGRATION, INTERVAL, batch_size: BATCH_SIZE)
+ end
+
+ def down
+ end
+end
diff --git a/db/post_migrate/20201102112206_rename_sitemap_namespace.rb b/db/post_migrate/20201102112206_rename_sitemap_namespace.rb
new file mode 100644
index 00000000000..b2e610d68db
--- /dev/null
+++ b/db/post_migrate/20201102112206_rename_sitemap_namespace.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class RenameSitemapNamespace < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+ include Gitlab::Database::RenameReservedPathsMigration::V1
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ # We're taking over the /sitemap namespace
+ # since it's necessary for the default behavior of Sitemaps
+ def up
+ disable_statement_timeout do
+ rename_root_paths(['sitemap'])
+ end
+ end
+
+ def down
+ disable_statement_timeout do
+ revert_renames
+ end
+ end
+end
diff --git a/db/post_migrate/20201102114018_remove_storage_size_limit_from_application_settings.rb b/db/post_migrate/20201102114018_remove_storage_size_limit_from_application_settings.rb
new file mode 100644
index 00000000000..6646cf2ad0c
--- /dev/null
+++ b/db/post_migrate/20201102114018_remove_storage_size_limit_from_application_settings.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class RemoveStorageSizeLimitFromApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ remove_column :application_settings, :namespace_storage_size_limit
+ end
+
+ def down
+ add_column :application_settings, :namespace_storage_size_limit, :bigint, default: 0
+ end
+end
diff --git a/db/post_migrate/20201102152554_add_not_null_check_on_iid_on_design_manangement_designs.rb b/db/post_migrate/20201102152554_add_not_null_check_on_iid_on_design_manangement_designs.rb
new file mode 100644
index 00000000000..861a0c3c27a
--- /dev/null
+++ b/db/post_migrate/20201102152554_add_not_null_check_on_iid_on_design_manangement_designs.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddNotNullCheckOnIidOnDesignManangementDesigns < ActiveRecord::Migration[6.0]
+ include ::Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_not_null_constraint(:design_management_designs, :iid)
+ end
+
+ def down
+ remove_not_null_constraint(:design_management_designs, :iid)
+ end
+end
diff --git a/db/post_migrate/20201102152945_truncate_security_findings_table.rb b/db/post_migrate/20201102152945_truncate_security_findings_table.rb
new file mode 100644
index 00000000000..8bfaa31f0de
--- /dev/null
+++ b/db/post_migrate/20201102152945_truncate_security_findings_table.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class TruncateSecurityFindingsTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ return unless Gitlab.dev_env_or_com?
+
+ with_lock_retries do
+ connection.execute('TRUNCATE security_findings RESTART IDENTITY')
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20201103013242_remove_terraform_state_verification_columns.rb b/db/post_migrate/20201103013242_remove_terraform_state_verification_columns.rb
new file mode 100644
index 00000000000..b1cd9790ead
--- /dev/null
+++ b/db/post_migrate/20201103013242_remove_terraform_state_verification_columns.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class RemoveTerraformStateVerificationColumns < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ transaction do
+ remove_column :terraform_states, :verification_retry_at, :datetime_with_timezone
+ remove_column :terraform_states, :verified_at, :datetime_with_timezone
+ remove_column :terraform_states, :verification_retry_count, :integer, limit: 2
+ remove_column :terraform_states, :verification_checksum, :binary, using: 'verification_checksum::bytea'
+ remove_column :terraform_states, :verification_failure, :text
+ end
+ end
+
+ def down
+ add_column(:terraform_states, :verification_retry_at, :datetime_with_timezone) unless column_exists?(:terraform_states, :verification_retry_at)
+ add_column(:terraform_states, :verified_at, :datetime_with_timezone) unless column_exists?(:terraform_states, :verified_at)
+ add_column(:terraform_states, :verification_retry_count, :integer, limit: 2) unless column_exists?(:terraform_states, :verification_retry_count)
+ add_column(:terraform_states, :verification_checksum, :binary, using: 'verification_checksum::bytea') unless column_exists?(:terraform_states, :verification_checksum)
+ add_column(:terraform_states, :verification_failure, :text) unless column_exists?(:terraform_states, :verification_failure)
+
+ add_text_limit :terraform_states, :verification_failure, 255
+ end
+end
diff --git a/db/post_migrate/20201103110018_schedule_merge_request_cleanup_schedules_backfill.rb b/db/post_migrate/20201103110018_schedule_merge_request_cleanup_schedules_backfill.rb
new file mode 100644
index 00000000000..77057205b09
--- /dev/null
+++ b/db/post_migrate/20201103110018_schedule_merge_request_cleanup_schedules_backfill.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class ScheduleMergeRequestCleanupSchedulesBackfill < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ MIGRATION = 'BackfillMergeRequestCleanupSchedules'
+ DELAY_INTERVAL = 2.minutes
+ BATCH_SIZE = 10_000
+ TEMP_INDEX_NAME = 'merge_requests_state_id_temp_index'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :merge_requests, :id, name: TEMP_INDEX_NAME, where: "state_id IN (2, 3)"
+
+ eligible_mrs = Gitlab::BackgroundMigration::BackfillMergeRequestCleanupSchedules::MergeRequest.eligible
+
+ queue_background_migration_jobs_by_range_at_intervals(
+ eligible_mrs,
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name :merge_requests, TEMP_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20201103192526_schedule_populate_has_vulnerabilities.rb b/db/post_migrate/20201103192526_schedule_populate_has_vulnerabilities.rb
new file mode 100644
index 00000000000..bed90af09dc
--- /dev/null
+++ b/db/post_migrate/20201103192526_schedule_populate_has_vulnerabilities.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class SchedulePopulateHasVulnerabilities < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ BATCH_SIZE = 1_000
+ DELAY_INTERVAL = 2.minutes
+ MIGRATION_CLASS = 'PopulateHasVulnerabilities'
+
+ disable_ddl_transaction!
+
+ def up
+ Gitlab::BackgroundMigration::PopulateHasVulnerabilities::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
+ end
+end
diff --git a/db/post_migrate/20201106082723_add_merge_request_jira_reference_indexes.rb b/db/post_migrate/20201106082723_add_merge_request_jira_reference_indexes.rb
new file mode 100644
index 00000000000..d69f57c6088
--- /dev/null
+++ b/db/post_migrate/20201106082723_add_merge_request_jira_reference_indexes.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class AddMergeRequestJiraReferenceIndexes < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ DESCRIPTION_INDEX_NAME = 'index_merge_requests_on_target_project_id_iid_jira_description'
+ TITLE_INDEX_NAME = 'index_merge_requests_on_target_project_id_and_iid_jira_title'
+
+ JIRA_KEY_REGEX = '[A-Z][A-Z_0-9]+-\d+'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(
+ :merge_requests,
+ [:target_project_id, :iid],
+ name: TITLE_INDEX_NAME,
+ using: :btree,
+ where: "(merge_requests.title)::text ~ '#{JIRA_KEY_REGEX}'::text"
+ )
+
+ add_concurrent_index(
+ :merge_requests,
+ [:target_project_id, :iid],
+ name: DESCRIPTION_INDEX_NAME,
+ using: :btree,
+ where: "(merge_requests.description)::text ~ '#{JIRA_KEY_REGEX}'::text"
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name(
+ :merge_requests,
+ TITLE_INDEX_NAME
+ )
+
+ remove_concurrent_index_by_name(
+ :merge_requests,
+ DESCRIPTION_INDEX_NAME
+ )
+ end
+end
diff --git a/db/post_migrate/20201106134950_deduplicate_epic_iids.rb b/db/post_migrate/20201106134950_deduplicate_epic_iids.rb
new file mode 100644
index 00000000000..bc7daf9329d
--- /dev/null
+++ b/db/post_migrate/20201106134950_deduplicate_epic_iids.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+class DeduplicateEpicIids < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_epics_on_group_id_and_iid'
+
+ disable_ddl_transaction!
+
+ class Epic < ActiveRecord::Base
+ end
+
+ class InternalId < ActiveRecord::Base
+ class << self
+ def generate_next(subject, scope, usage, init)
+ InternalIdGenerator.new(subject, scope, usage, init).generate
+ end
+ end
+
+ # Increments #last_value and saves the record
+ #
+ # The operation locks the record and gathers a `ROW SHARE` lock (in PostgreSQL).
+ # As such, the increment is atomic and safe to be called concurrently.
+ def increment_and_save!
+ update_and_save { self.last_value = (last_value || 0) + 1 }
+ end
+
+ private
+
+ def update_and_save(&block)
+ lock!
+ yield
+ save!
+ last_value
+ end
+ end
+
+ # See app/models/internal_id
+ class InternalIdGenerator
+ attr_reader :subject, :scope, :scope_attrs, :usage, :init
+
+ def initialize(subject, scope, usage, init = nil)
+ @subject = subject
+ @scope = scope
+ @usage = usage
+ @init = init
+
+ raise ArgumentError, 'Scope is not well-defined, need at least one column for scope (given: 0)' if scope.empty? || usage.to_s != 'epics'
+ end
+
+ # Generates next internal id and returns it
+ # init: Block that gets called to initialize InternalId record if not present
+ # Make sure to not throw exceptions in the absence of records (if this is expected).
+ def generate
+ subject.transaction do
+ # Create a record in internal_ids if one does not yet exist
+ # and increment its last value
+ #
+ # Note this will acquire a ROW SHARE lock on the InternalId record
+ record.increment_and_save!
+ end
+ end
+
+ def record
+ @record ||= (lookup || create_record)
+ end
+
+ def lookup
+ InternalId.find_by(**scope, usage: usage_value)
+ end
+
+ def usage_value
+ 4 # see Enums::InternalId - this is the value for epics
+ end
+
+ # Create InternalId record for (scope, usage) combination, if it doesn't exist
+ #
+ # We blindly insert without synchronization. If another process
+ # was faster in doing this, we'll realize once we hit the unique key constraint
+ # violation. We can safely roll-back the nested transaction and perform
+ # a lookup instead to retrieve the record.
+ def create_record
+ raise ArgumentError, 'Cannot initialize without init!' unless init
+
+ instance = subject.is_a?(::Class) ? nil : subject
+
+ subject.transaction(requires_new: true) do
+ InternalId.create!(
+ **scope,
+ usage: usage_value,
+ last_value: init.call(instance, scope) || 0
+ )
+ end
+ rescue ActiveRecord::RecordNotUnique
+ lookup
+ end
+ end
+
+ def up
+ duplicate_epic_ids = ApplicationRecord.connection.execute('SELECT iid, group_id, COUNT(*) FROM epics GROUP BY iid, group_id HAVING COUNT(*) > 1;')
+
+ duplicate_epic_ids.each do |dup|
+ Epic.where(iid: dup['iid'], group_id: dup['group_id']).last(dup['count'] - 1).each do |epic|
+ new_iid = InternalId.generate_next(epic,
+ { namespace_id: epic.group_id },
+ :epics, ->(instance, _) { instance.class.where(group_id: epic.group_id).maximum(:iid) }
+ )
+
+ epic.update!(iid: new_iid)
+ end
+ end
+
+ add_concurrent_index :epics, [:group_id, :iid], unique: true, name: INDEX_NAME
+ end
+
+ def down
+ # only remove the index, as we do not want to create the duplicates back
+ remove_concurrent_index :epics, [:group_id, :iid], name: INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20200908212414 b/db/schema_migrations/20200908212414
new file mode 100644
index 00000000000..208f9affc91
--- /dev/null
+++ b/db/schema_migrations/20200908212414
@@ -0,0 +1 @@
+a9605126178d887bbf526a4a33b7060b072eff7a8d6712e3552099f7e615f88b \ No newline at end of file
diff --git a/db/schema_migrations/20200920130356 b/db/schema_migrations/20200920130356
new file mode 100644
index 00000000000..ab0575958ec
--- /dev/null
+++ b/db/schema_migrations/20200920130356
@@ -0,0 +1 @@
+80d2beb7a1c5f60a4bf3462054fa5bcd0488152b6754f8a7164046201fcb08ed \ No newline at end of file
diff --git a/db/schema_migrations/20200928123510 b/db/schema_migrations/20200928123510
new file mode 100644
index 00000000000..db9d2889739
--- /dev/null
+++ b/db/schema_migrations/20200928123510
@@ -0,0 +1 @@
+1e274e744ed9e225e2ee09afc15871a1af63857f95c5d787e8efd9943fce1bed \ No newline at end of file
diff --git a/db/schema_migrations/20201008011523 b/db/schema_migrations/20201008011523
new file mode 100644
index 00000000000..845ee2f5b96
--- /dev/null
+++ b/db/schema_migrations/20201008011523
@@ -0,0 +1 @@
+b7b49ca4c021b7caa9f8612ad9b69d4ec6d79894db2e43266bfe26f2e0bffe08 \ No newline at end of file
diff --git a/db/schema_migrations/20201008011937 b/db/schema_migrations/20201008011937
new file mode 100644
index 00000000000..258daf9a836
--- /dev/null
+++ b/db/schema_migrations/20201008011937
@@ -0,0 +1 @@
+8af89bb3e63bfca24cee8fdf6f0dd587fae7d81bfeaf6d427f84c7b37c9664ba \ No newline at end of file
diff --git a/db/schema_migrations/20201008013434 b/db/schema_migrations/20201008013434
new file mode 100644
index 00000000000..9ec9dd8277c
--- /dev/null
+++ b/db/schema_migrations/20201008013434
@@ -0,0 +1 @@
+966f6e95189b551cba0ef548cb410911c0beee30d0a265ae21d90321ecbb2a00 \ No newline at end of file
diff --git a/db/schema_migrations/20201008075620 b/db/schema_migrations/20201008075620
new file mode 100644
index 00000000000..a0a5d6a7314
--- /dev/null
+++ b/db/schema_migrations/20201008075620
@@ -0,0 +1 @@
+f9bc943b61460b1a9a6db8189ab5b21eba46e14650c68658175299b14d48a030 \ No newline at end of file
diff --git a/db/schema_migrations/20201008125643 b/db/schema_migrations/20201008125643
new file mode 100644
index 00000000000..121dcbc0281
--- /dev/null
+++ b/db/schema_migrations/20201008125643
@@ -0,0 +1 @@
+b7b15717435e06ea386c941c5a021b73f986ad3f41f2bd6f890738a79b710207 \ No newline at end of file
diff --git a/db/schema_migrations/20201008144854 b/db/schema_migrations/20201008144854
new file mode 100644
index 00000000000..f4b71f06acd
--- /dev/null
+++ b/db/schema_migrations/20201008144854
@@ -0,0 +1 @@
+250785e18682cc10afb4f04546e5ff6dff9ab6c6673df84692c8221d6fe820ac \ No newline at end of file
diff --git a/db/schema_migrations/20201008224441 b/db/schema_migrations/20201008224441
new file mode 100644
index 00000000000..1f27662d754
--- /dev/null
+++ b/db/schema_migrations/20201008224441
@@ -0,0 +1 @@
+d0ca8f0dbe0cf0fbbdd715867f3ae20862683433d919ee5cd942086d21f3b44d \ No newline at end of file
diff --git a/db/schema_migrations/20201012073022 b/db/schema_migrations/20201012073022
new file mode 100644
index 00000000000..b7ce136a7e3
--- /dev/null
+++ b/db/schema_migrations/20201012073022
@@ -0,0 +1 @@
+234711b96d3869fe826dfd71ae29e0f75e50302bc29a4e60f436ec76b4be3efb \ No newline at end of file
diff --git a/db/schema_migrations/20201012122428 b/db/schema_migrations/20201012122428
new file mode 100644
index 00000000000..13e7e9c2cd6
--- /dev/null
+++ b/db/schema_migrations/20201012122428
@@ -0,0 +1 @@
+d43764a44f6578548d8b7838dc011b7693da0b7d65cbcc1fff96a212d655024e \ No newline at end of file
diff --git a/db/schema_migrations/20201012134230 b/db/schema_migrations/20201012134230
new file mode 100644
index 00000000000..2bf2175ef60
--- /dev/null
+++ b/db/schema_migrations/20201012134230
@@ -0,0 +1 @@
+1673018885366e92eb47f5fc705ea8251c2db49b5c14b788e84b10d8db91af48 \ No newline at end of file
diff --git a/db/schema_migrations/20201012135330 b/db/schema_migrations/20201012135330
new file mode 100644
index 00000000000..8ecce197faa
--- /dev/null
+++ b/db/schema_migrations/20201012135330
@@ -0,0 +1 @@
+18ccd2059d9a19a51ea0162c46a1293e280759daffa54ba58ba5e431ee7aba93 \ No newline at end of file
diff --git a/db/schema_migrations/20201012140110 b/db/schema_migrations/20201012140110
new file mode 100644
index 00000000000..1bbfe820a5d
--- /dev/null
+++ b/db/schema_migrations/20201012140110
@@ -0,0 +1 @@
+e266655483655e1ecbb4f65594ef5b985c3f0449231755f589f3e293e28c9f6b \ No newline at end of file
diff --git a/db/schema_migrations/20201012140452 b/db/schema_migrations/20201012140452
new file mode 100644
index 00000000000..11bc272341d
--- /dev/null
+++ b/db/schema_migrations/20201012140452
@@ -0,0 +1 @@
+d62928276708c26656070f803ea6271be74a1fe9802877258d4a8cf19df32d09 \ No newline at end of file
diff --git a/db/schema_migrations/20201014163633 b/db/schema_migrations/20201014163633
new file mode 100644
index 00000000000..6025edca343
--- /dev/null
+++ b/db/schema_migrations/20201014163633
@@ -0,0 +1 @@
+591bb8d685c686cced324825e7bec01711aee328176c1c5396a9e61847cb6fab \ No newline at end of file
diff --git a/db/schema_migrations/20201015121805 b/db/schema_migrations/20201015121805
new file mode 100644
index 00000000000..50c3cd1285c
--- /dev/null
+++ b/db/schema_migrations/20201015121805
@@ -0,0 +1 @@
+b8d5890fe5569127e794eea831fc18f8e5708b326e8037963fe2f6ae7f120e27 \ No newline at end of file
diff --git a/db/schema_migrations/20201015121825 b/db/schema_migrations/20201015121825
new file mode 100644
index 00000000000..b853c405ba0
--- /dev/null
+++ b/db/schema_migrations/20201015121825
@@ -0,0 +1 @@
+76e5a5bb535019da28041d1c7dddd8a18d3b04f688b38edc0c4214d3a4d6e357 \ No newline at end of file
diff --git a/db/schema_migrations/20201015194852 b/db/schema_migrations/20201015194852
new file mode 100644
index 00000000000..665135a7e3e
--- /dev/null
+++ b/db/schema_migrations/20201015194852
@@ -0,0 +1 @@
+1b12f68f7d8c56ecdd7d6d7551d81f5d95d1b4dc5f8d4c67eb239b8640128531 \ No newline at end of file
diff --git a/db/schema_migrations/20201015231049 b/db/schema_migrations/20201015231049
new file mode 100644
index 00000000000..17a4147993a
--- /dev/null
+++ b/db/schema_migrations/20201015231049
@@ -0,0 +1 @@
+cae3c41e344f15fa5a9cf71546a0bf209ead964fd3efefba39aba79afd60e0be \ No newline at end of file
diff --git a/db/schema_migrations/20201016074302 b/db/schema_migrations/20201016074302
new file mode 100644
index 00000000000..e0ed03f0ac3
--- /dev/null
+++ b/db/schema_migrations/20201016074302
@@ -0,0 +1 @@
+de07bcc8166421d01382038d930cabb6a4749b314f05ca148e8d13cff947447c \ No newline at end of file
diff --git a/db/schema_migrations/20201019091307 b/db/schema_migrations/20201019091307
new file mode 100644
index 00000000000..6b74c804ed8
--- /dev/null
+++ b/db/schema_migrations/20201019091307
@@ -0,0 +1 @@
+f19ab0de07415e728849ef4e56804909a3a4a57ad8f55fe71a27bc43c535ac66 \ No newline at end of file
diff --git a/db/schema_migrations/20201019094741 b/db/schema_migrations/20201019094741
new file mode 100644
index 00000000000..5e53ab91e9b
--- /dev/null
+++ b/db/schema_migrations/20201019094741
@@ -0,0 +1 @@
+16ef5ba153f1145dcd2578bb8c860d4e1a975d5df3a1b1d9315946e632a95999 \ No newline at end of file
diff --git a/db/schema_migrations/20201019101549 b/db/schema_migrations/20201019101549
new file mode 100644
index 00000000000..9b22cf277fb
--- /dev/null
+++ b/db/schema_migrations/20201019101549
@@ -0,0 +1 @@
+1bd99d7d6b972ea66495f21358e3b8731532219fcf75731bf643c312eb56820d \ No newline at end of file
diff --git a/db/schema_migrations/20201019111952 b/db/schema_migrations/20201019111952
new file mode 100644
index 00000000000..7fe9fcf3b2f
--- /dev/null
+++ b/db/schema_migrations/20201019111952
@@ -0,0 +1 @@
+82d6ed3e066c15352abdb58d58d195f48aa7b1d17bbb28f58f42c19ae67fab54 \ No newline at end of file
diff --git a/db/schema_migrations/20201019113009 b/db/schema_migrations/20201019113009
new file mode 100644
index 00000000000..88d91b79607
--- /dev/null
+++ b/db/schema_migrations/20201019113009
@@ -0,0 +1 @@
+fe57e8e74ebbe0e9567c1487e6e4f8b499afa6404c73424157c43ae79c005f08 \ No newline at end of file
diff --git a/db/schema_migrations/20201019130244 b/db/schema_migrations/20201019130244
new file mode 100644
index 00000000000..b37e6eeae70
--- /dev/null
+++ b/db/schema_migrations/20201019130244
@@ -0,0 +1 @@
+fcd2cc46dae4f4da96ac5a2100a9de9bd360defee82a9c9d6cfbda0e1507ee66 \ No newline at end of file
diff --git a/db/schema_migrations/20201019152046 b/db/schema_migrations/20201019152046
new file mode 100644
index 00000000000..bc364a38a46
--- /dev/null
+++ b/db/schema_migrations/20201019152046
@@ -0,0 +1 @@
+e5b3bcac7150df4443879db05b18b6aeb01271d99965b2468278954dedf8413b \ No newline at end of file
diff --git a/db/schema_migrations/20201019161924 b/db/schema_migrations/20201019161924
new file mode 100644
index 00000000000..3857a5cb5a1
--- /dev/null
+++ b/db/schema_migrations/20201019161924
@@ -0,0 +1 @@
+47aba29a35e24113c9f198c731ba95597a2a6cd5d16b01a958644ce3e1a96170 \ No newline at end of file
diff --git a/db/schema_migrations/20201019172704 b/db/schema_migrations/20201019172704
new file mode 100644
index 00000000000..0bf2d30205f
--- /dev/null
+++ b/db/schema_migrations/20201019172704
@@ -0,0 +1 @@
+2a426e1a7cc6283e777667a1b4a6987f011c6cfd189ec702abc55d13a8499eca \ No newline at end of file
diff --git a/db/schema_migrations/20201020102551 b/db/schema_migrations/20201020102551
new file mode 100644
index 00000000000..f658f1fdc0a
--- /dev/null
+++ b/db/schema_migrations/20201020102551
@@ -0,0 +1 @@
+ba16ad5a51494f436dc47ffb924f94ce7795bfd3b9061ca58d1c8dda238245e9 \ No newline at end of file
diff --git a/db/schema_migrations/20201021085007 b/db/schema_migrations/20201021085007
new file mode 100644
index 00000000000..59567962e80
--- /dev/null
+++ b/db/schema_migrations/20201021085007
@@ -0,0 +1 @@
+552f8a042bdecb7511d63e129438faff3fde8e1086cc88f7a79269b2b7098a65 \ No newline at end of file
diff --git a/db/schema_migrations/20201021101956 b/db/schema_migrations/20201021101956
new file mode 100644
index 00000000000..bf3e1092fd1
--- /dev/null
+++ b/db/schema_migrations/20201021101956
@@ -0,0 +1 @@
+47158d21bd1a800e5a9da1bfea25870f14cc0b094e5f3e9a4b7608b8a9eca180 \ No newline at end of file
diff --git a/db/schema_migrations/20201021102554 b/db/schema_migrations/20201021102554
new file mode 100644
index 00000000000..c2bd788943b
--- /dev/null
+++ b/db/schema_migrations/20201021102554
@@ -0,0 +1 @@
+90936786a9c2a9d035d13be87021b2f8278342cd11992d58753ca5a5413ed9d7 \ No newline at end of file
diff --git a/db/schema_migrations/20201021105347 b/db/schema_migrations/20201021105347
new file mode 100644
index 00000000000..86117fd6538
--- /dev/null
+++ b/db/schema_migrations/20201021105347
@@ -0,0 +1 @@
+d7683f7a2db6aa27606756c158fa029c932230713b165917bc05a491f10e7adf \ No newline at end of file
diff --git a/db/schema_migrations/20201021105600 b/db/schema_migrations/20201021105600
new file mode 100644
index 00000000000..14d2edb23a6
--- /dev/null
+++ b/db/schema_migrations/20201021105600
@@ -0,0 +1 @@
+9b90dd436cc1c315eacc60acbc5f6b3b94029b82b4fcb27a41abc4941ad9a4ad \ No newline at end of file
diff --git a/db/schema_migrations/20201021105959 b/db/schema_migrations/20201021105959
new file mode 100644
index 00000000000..2ddfcb102c9
--- /dev/null
+++ b/db/schema_migrations/20201021105959
@@ -0,0 +1 @@
+d924e4ad9ff67d01d660db3b3a1b9e5d74cecb1a127d598d1d1193cbfa499030 \ No newline at end of file
diff --git a/db/schema_migrations/20201021142812 b/db/schema_migrations/20201021142812
new file mode 100644
index 00000000000..d4ddf2a3595
--- /dev/null
+++ b/db/schema_migrations/20201021142812
@@ -0,0 +1 @@
+81b9b79f2ca8830b9d9e9315d93421875dfe44cfa0da6f4e9166567452a2363b \ No newline at end of file
diff --git a/db/schema_migrations/20201021152210 b/db/schema_migrations/20201021152210
new file mode 100644
index 00000000000..78358b24bad
--- /dev/null
+++ b/db/schema_migrations/20201021152210
@@ -0,0 +1 @@
+853dbc604fc8ce4d82e6040aa7a7970ae194f09bafb2749077cd9f48d2708eac \ No newline at end of file
diff --git a/db/schema_migrations/20201021190539 b/db/schema_migrations/20201021190539
new file mode 100644
index 00000000000..902213f9029
--- /dev/null
+++ b/db/schema_migrations/20201021190539
@@ -0,0 +1 @@
+1d0689b5182ac391473075aeabb0e341fb8634dbf0aa87dbb6d48cc0e61d2ada \ No newline at end of file
diff --git a/db/schema_migrations/20201021220101 b/db/schema_migrations/20201021220101
new file mode 100644
index 00000000000..cda2e4076a5
--- /dev/null
+++ b/db/schema_migrations/20201021220101
@@ -0,0 +1 @@
+72580665fcb0fca332ede450690902c0a7afb6159feff41df1bc10a3cf6607f2 \ No newline at end of file
diff --git a/db/schema_migrations/20201022080802 b/db/schema_migrations/20201022080802
new file mode 100644
index 00000000000..c84c8c6ffbe
--- /dev/null
+++ b/db/schema_migrations/20201022080802
@@ -0,0 +1 @@
+809d93d367ff9310063904ee3c266914311ef54e8c7f9d6d7fd924d25890bf19 \ No newline at end of file
diff --git a/db/schema_migrations/20201022094845 b/db/schema_migrations/20201022094845
new file mode 100644
index 00000000000..3bc0b95b711
--- /dev/null
+++ b/db/schema_migrations/20201022094845
@@ -0,0 +1 @@
+16b402740c6b1dd21908265085e516f63f8858424724ba97f46658e7bd5f7bf2 \ No newline at end of file
diff --git a/db/schema_migrations/20201022094846 b/db/schema_migrations/20201022094846
new file mode 100644
index 00000000000..40ef0760dc8
--- /dev/null
+++ b/db/schema_migrations/20201022094846
@@ -0,0 +1 @@
+588c5f99d34652bbd5bde86351cbdb8c0455af0c31a440bfb63df02f12fd588f \ No newline at end of file
diff --git a/db/schema_migrations/20201022103304 b/db/schema_migrations/20201022103304
new file mode 100644
index 00000000000..e54cb431bd4
--- /dev/null
+++ b/db/schema_migrations/20201022103304
@@ -0,0 +1 @@
+aa15aad0b51f313f3cd59e1065023146fe53c6bd50319656ae992f8f43e1525e \ No newline at end of file
diff --git a/db/schema_migrations/20201022144501 b/db/schema_migrations/20201022144501
new file mode 100644
index 00000000000..4e82b2785d0
--- /dev/null
+++ b/db/schema_migrations/20201022144501
@@ -0,0 +1 @@
+f9a573d50f8b4aeb3d8d2cc2f0223ab9970776d663e49e0f022e96158593d929 \ No newline at end of file
diff --git a/db/schema_migrations/20201022191817 b/db/schema_migrations/20201022191817
new file mode 100644
index 00000000000..619ae381a72
--- /dev/null
+++ b/db/schema_migrations/20201022191817
@@ -0,0 +1 @@
+205cb628e9637bcd1acb90c5211b71b51015fa5f50aadcacd5fbafc4f09c00d0 \ No newline at end of file
diff --git a/db/schema_migrations/20201022192254 b/db/schema_migrations/20201022192254
new file mode 100644
index 00000000000..c09518b0e6c
--- /dev/null
+++ b/db/schema_migrations/20201022192254
@@ -0,0 +1 @@
+9f942de6f83629a144e9d460b4bed7a246afe95275b5913745109fc0ab9dacc1 \ No newline at end of file
diff --git a/db/schema_migrations/20201023114628 b/db/schema_migrations/20201023114628
new file mode 100644
index 00000000000..458392082ca
--- /dev/null
+++ b/db/schema_migrations/20201023114628
@@ -0,0 +1 @@
+f4fb466c74e1366d5980a54d6e5fc42fe78237cae33d8cdaf5573d2fe75f8a5a \ No newline at end of file
diff --git a/db/schema_migrations/20201026051643 b/db/schema_migrations/20201026051643
new file mode 100644
index 00000000000..f3290df0d23
--- /dev/null
+++ b/db/schema_migrations/20201026051643
@@ -0,0 +1 @@
+bb20b72c7fa65735f37d896cc098d27edd4cc07c3083fdb567e4b421309703a7 \ No newline at end of file
diff --git a/db/schema_migrations/20201026182253 b/db/schema_migrations/20201026182253
new file mode 100644
index 00000000000..a8da92aa906
--- /dev/null
+++ b/db/schema_migrations/20201026182253
@@ -0,0 +1 @@
+ab2b8af98a8a29658f92c302d45668c7b9f8f5234ef35f4311a0f0ebbd954ec8 \ No newline at end of file
diff --git a/db/schema_migrations/20201026200736 b/db/schema_migrations/20201026200736
new file mode 100644
index 00000000000..7ed57505c3e
--- /dev/null
+++ b/db/schema_migrations/20201026200736
@@ -0,0 +1 @@
+691fe3335de3e072bc5612705c4d16744ff17e334025ddd78eb37309f87441e3 \ No newline at end of file
diff --git a/db/schema_migrations/20201027002551 b/db/schema_migrations/20201027002551
new file mode 100644
index 00000000000..f4a5527fac7
--- /dev/null
+++ b/db/schema_migrations/20201027002551
@@ -0,0 +1 @@
+34e357b739235d627e543e1bc7202e0cf26f5b1ca8021bb25357e29e883f785b \ No newline at end of file
diff --git a/db/schema_migrations/20201027135651 b/db/schema_migrations/20201027135651
new file mode 100644
index 00000000000..eb3a5080c0f
--- /dev/null
+++ b/db/schema_migrations/20201027135651
@@ -0,0 +1 @@
+3f24bfc2d18ffa5f171e027d4e7aaf9994b255e5806e2de57fd36b4a193db122 \ No newline at end of file
diff --git a/db/schema_migrations/20201027210127 b/db/schema_migrations/20201027210127
new file mode 100644
index 00000000000..ab0ba73f588
--- /dev/null
+++ b/db/schema_migrations/20201027210127
@@ -0,0 +1 @@
+c269a999cabce99d26f3be303656bbb27f2b843b639755b112ad350d4cb5b5c6 \ No newline at end of file
diff --git a/db/schema_migrations/20201027211138 b/db/schema_migrations/20201027211138
new file mode 100644
index 00000000000..5e36445702b
--- /dev/null
+++ b/db/schema_migrations/20201027211138
@@ -0,0 +1 @@
+402e9a6e92802888ba01ee216850ab5b0fe9997a84415c9ffe8d5d37a9823220 \ No newline at end of file
diff --git a/db/schema_migrations/20201028160831 b/db/schema_migrations/20201028160831
new file mode 100644
index 00000000000..de94901dcc5
--- /dev/null
+++ b/db/schema_migrations/20201028160831
@@ -0,0 +1 @@
+4b0c70d8cd2648149011adab4f302922483436406f361c3037f26efb12b19042 \ No newline at end of file
diff --git a/db/schema_migrations/20201028160832 b/db/schema_migrations/20201028160832
new file mode 100644
index 00000000000..4b0da32b638
--- /dev/null
+++ b/db/schema_migrations/20201028160832
@@ -0,0 +1 @@
+9ea8e8f1234d6291ea00e725d380bfe33d804853b90da1221be8781b3dd9bb77 \ No newline at end of file
diff --git a/db/schema_migrations/20201028182809 b/db/schema_migrations/20201028182809
new file mode 100644
index 00000000000..6747bd58d72
--- /dev/null
+++ b/db/schema_migrations/20201028182809
@@ -0,0 +1 @@
+c51bf825045ef80714f3903f25321785883da3d612725f6fa67ec3ddd12d5808 \ No newline at end of file
diff --git a/db/schema_migrations/20201028184640 b/db/schema_migrations/20201028184640
new file mode 100644
index 00000000000..4cac95e4e7b
--- /dev/null
+++ b/db/schema_migrations/20201028184640
@@ -0,0 +1 @@
+5520cca016af07fb2e009c0e3254362f106a9cc808cbb61e280221be82be1b25 \ No newline at end of file
diff --git a/db/schema_migrations/20201028204306 b/db/schema_migrations/20201028204306
new file mode 100644
index 00000000000..03b68c9a0d1
--- /dev/null
+++ b/db/schema_migrations/20201028204306
@@ -0,0 +1 @@
+ec5bab20a1b591b77b48b85dc0b871e88a41891d256201b7d8eb86195ef1c4ad \ No newline at end of file
diff --git a/db/schema_migrations/20201029052241 b/db/schema_migrations/20201029052241
new file mode 100644
index 00000000000..8257e4d3681
--- /dev/null
+++ b/db/schema_migrations/20201029052241
@@ -0,0 +1 @@
+87e330bc15accb10733825b079cf89e78d905a7c4080075489857085f014bfe7 \ No newline at end of file
diff --git a/db/schema_migrations/20201029143650 b/db/schema_migrations/20201029143650
new file mode 100644
index 00000000000..c6f00890f4f
--- /dev/null
+++ b/db/schema_migrations/20201029143650
@@ -0,0 +1 @@
+c718bc731f7dc3e1f0104dfdb79a3dc46c46849153ec9b228600eeb5a92465e7 \ No newline at end of file
diff --git a/db/schema_migrations/20201029144157 b/db/schema_migrations/20201029144157
new file mode 100644
index 00000000000..7fdac19230f
--- /dev/null
+++ b/db/schema_migrations/20201029144157
@@ -0,0 +1 @@
+a61310c95a1302871ea18881d45bc0c7357baa8f24daa31b7e2174318dab5707 \ No newline at end of file
diff --git a/db/schema_migrations/20201029144444 b/db/schema_migrations/20201029144444
new file mode 100644
index 00000000000..1ab20b33da5
--- /dev/null
+++ b/db/schema_migrations/20201029144444
@@ -0,0 +1 @@
+50e4e42c804d3abdcfe9ab2bbb890262d4b2ddd93bff1b2af1da1e55a0300cf5 \ No newline at end of file
diff --git a/db/schema_migrations/20201030092151 b/db/schema_migrations/20201030092151
new file mode 100644
index 00000000000..7b39a8e0dca
--- /dev/null
+++ b/db/schema_migrations/20201030092151
@@ -0,0 +1 @@
+ced03562d300f99abf687c258a25bf280a6c4f1798a893ee8a79189c09f19e6e \ No newline at end of file
diff --git a/db/schema_migrations/20201030200115 b/db/schema_migrations/20201030200115
new file mode 100644
index 00000000000..ed9c743f538
--- /dev/null
+++ b/db/schema_migrations/20201030200115
@@ -0,0 +1 @@
+bef50f2417b9676c89aea838f7b9c85fb88af9f52c197d8eb4613a9c91bc7741 \ No newline at end of file
diff --git a/db/schema_migrations/20201030200539 b/db/schema_migrations/20201030200539
new file mode 100644
index 00000000000..f8e7642befb
--- /dev/null
+++ b/db/schema_migrations/20201030200539
@@ -0,0 +1 @@
+2f6c7efc1716d02dd40adb08bd09b9f1e63e4248619678c0562f4b8d581e6065 \ No newline at end of file
diff --git a/db/schema_migrations/20201030203854 b/db/schema_migrations/20201030203854
new file mode 100644
index 00000000000..6a337c366aa
--- /dev/null
+++ b/db/schema_migrations/20201030203854
@@ -0,0 +1 @@
+3937235469c8fb1f2b0af9cdf38933db5ae61552d1a9050755cec5f7c16ebb66 \ No newline at end of file
diff --git a/db/schema_migrations/20201102073808 b/db/schema_migrations/20201102073808
new file mode 100644
index 00000000000..9e77ee028a5
--- /dev/null
+++ b/db/schema_migrations/20201102073808
@@ -0,0 +1 @@
+153b437ac481f4d79cd5bdee45dd3932f3cb58bf5dce793573c4b651a3b9314f \ No newline at end of file
diff --git a/db/schema_migrations/20201102112206 b/db/schema_migrations/20201102112206
new file mode 100644
index 00000000000..5bbba26e110
--- /dev/null
+++ b/db/schema_migrations/20201102112206
@@ -0,0 +1 @@
+a861c91ebc7f7892020ba10a151df761b38bf69d5e02bcdf72a965eb266e6aff \ No newline at end of file
diff --git a/db/schema_migrations/20201102114018 b/db/schema_migrations/20201102114018
new file mode 100644
index 00000000000..33615073453
--- /dev/null
+++ b/db/schema_migrations/20201102114018
@@ -0,0 +1 @@
+dc1c372f4976e3747d7201406123a54e3852d9ea9516089043a93698a09e2f9f \ No newline at end of file
diff --git a/db/schema_migrations/20201102152554 b/db/schema_migrations/20201102152554
new file mode 100644
index 00000000000..f52694965c6
--- /dev/null
+++ b/db/schema_migrations/20201102152554
@@ -0,0 +1 @@
+7ec73c06ccc4c9f618e0455d0a7aae3b591bf52b5ddb1b3f1678d2fd50b9fd5e \ No newline at end of file
diff --git a/db/schema_migrations/20201102152945 b/db/schema_migrations/20201102152945
new file mode 100644
index 00000000000..cb4ae9c2598
--- /dev/null
+++ b/db/schema_migrations/20201102152945
@@ -0,0 +1 @@
+55ffd18d5f55ee0fd51a31d50cf2d51595740c72ca23d5134d93e2da3fc186ff \ No newline at end of file
diff --git a/db/schema_migrations/20201102184743 b/db/schema_migrations/20201102184743
new file mode 100644
index 00000000000..da002122e5d
--- /dev/null
+++ b/db/schema_migrations/20201102184743
@@ -0,0 +1 @@
+040e73d690cb315627fe16c931273aa1f86dfabb481dc2086f787d067b87642f \ No newline at end of file
diff --git a/db/schema_migrations/20201103013242 b/db/schema_migrations/20201103013242
new file mode 100644
index 00000000000..1f592b4a619
--- /dev/null
+++ b/db/schema_migrations/20201103013242
@@ -0,0 +1 @@
+8a30cf20f71e0cb198caf6f77a19e4da55b83eb38bdb5888cd2674373d94cede \ No newline at end of file
diff --git a/db/schema_migrations/20201103095752 b/db/schema_migrations/20201103095752
new file mode 100644
index 00000000000..4888f7c5dfb
--- /dev/null
+++ b/db/schema_migrations/20201103095752
@@ -0,0 +1 @@
+3427cf92dc785f399329b00a3dded01dd2a6386cafbd0ef4b732bfcf522ce615 \ No newline at end of file
diff --git a/db/schema_migrations/20201103110018 b/db/schema_migrations/20201103110018
new file mode 100644
index 00000000000..82ab2fda543
--- /dev/null
+++ b/db/schema_migrations/20201103110018
@@ -0,0 +1 @@
+8a45a6186d7e18f1dea43593dc0226860fc2e8d3ae386f50a022958b758c7c75 \ No newline at end of file
diff --git a/db/schema_migrations/20201103171537 b/db/schema_migrations/20201103171537
new file mode 100644
index 00000000000..4621c0e4802
--- /dev/null
+++ b/db/schema_migrations/20201103171537
@@ -0,0 +1 @@
+3120428427e3c0c94799501b1d31f384c98899f2ef9bda6f95066c94afd5ecf8 \ No newline at end of file
diff --git a/db/schema_migrations/20201103184333 b/db/schema_migrations/20201103184333
new file mode 100644
index 00000000000..0475ea2b466
--- /dev/null
+++ b/db/schema_migrations/20201103184333
@@ -0,0 +1 @@
+a3117169b472fffd6302a4da17850a11474c196fd06ebeb3f6b28705d59c74ba \ No newline at end of file
diff --git a/db/schema_migrations/20201103192526 b/db/schema_migrations/20201103192526
new file mode 100644
index 00000000000..8fe11ed16d6
--- /dev/null
+++ b/db/schema_migrations/20201103192526
@@ -0,0 +1 @@
+bb137c3a41a40e740f8ae65b43d7f9218f52d6d5eaf53c8a64b3336a8f16141b \ No newline at end of file
diff --git a/db/schema_migrations/20201103202213 b/db/schema_migrations/20201103202213
new file mode 100644
index 00000000000..74b0b1888d2
--- /dev/null
+++ b/db/schema_migrations/20201103202213
@@ -0,0 +1 @@
+af006a3c01620c258a253b5c9ccca6faa4cb46a97dddbfeecc0ecc4454eb46e6 \ No newline at end of file
diff --git a/db/schema_migrations/20201104204739 b/db/schema_migrations/20201104204739
new file mode 100644
index 00000000000..83794fd569f
--- /dev/null
+++ b/db/schema_migrations/20201104204739
@@ -0,0 +1 @@
+9431c771b14d61851e8e69b3a789f222463bbe460078a35c8ad3cbcf8df8b077 \ No newline at end of file
diff --git a/db/schema_migrations/20201105021637 b/db/schema_migrations/20201105021637
new file mode 100644
index 00000000000..05a76d22568
--- /dev/null
+++ b/db/schema_migrations/20201105021637
@@ -0,0 +1 @@
+b04e37c8713a333afbff4c7034d9f3ffca4a4490d0b563b73d9e6bffd45f3f6a \ No newline at end of file
diff --git a/db/schema_migrations/20201105024127 b/db/schema_migrations/20201105024127
new file mode 100644
index 00000000000..fecda19cb2f
--- /dev/null
+++ b/db/schema_migrations/20201105024127
@@ -0,0 +1 @@
+afeff8d6bf5ca14f955f5d387e8d219e852e9617b80fe07ed2e1b57af19fd4fa \ No newline at end of file
diff --git a/db/schema_migrations/20201105135051 b/db/schema_migrations/20201105135051
new file mode 100644
index 00000000000..26ebc47fd3a
--- /dev/null
+++ b/db/schema_migrations/20201105135051
@@ -0,0 +1 @@
+41cc59ebfeed647b2525191befa43c1faeb1c133a687a5c93124f4b4c745117a \ No newline at end of file
diff --git a/db/schema_migrations/20201105143211 b/db/schema_migrations/20201105143211
new file mode 100644
index 00000000000..6ddf20c1d68
--- /dev/null
+++ b/db/schema_migrations/20201105143211
@@ -0,0 +1 @@
+b614435cdb654ebbd11bcc5ac0ed69352219e51b368d8f10c0b2998c5258caf9 \ No newline at end of file
diff --git a/db/schema_migrations/20201105143312 b/db/schema_migrations/20201105143312
new file mode 100644
index 00000000000..fe616c85dc9
--- /dev/null
+++ b/db/schema_migrations/20201105143312
@@ -0,0 +1 @@
+decdc314dbcf6b8ac2ce140f81f9d342efca0d98bbeff10c7a041568a67b63f3 \ No newline at end of file
diff --git a/db/schema_migrations/20201106082723 b/db/schema_migrations/20201106082723
new file mode 100644
index 00000000000..0bb6a3b85b8
--- /dev/null
+++ b/db/schema_migrations/20201106082723
@@ -0,0 +1 @@
+a2dc0d31af6834adf6634f6051d7d451fc48d31492d96efe57547c3e9d61a64d \ No newline at end of file
diff --git a/db/schema_migrations/20201106134139 b/db/schema_migrations/20201106134139
new file mode 100644
index 00000000000..245cbbf712e
--- /dev/null
+++ b/db/schema_migrations/20201106134139
@@ -0,0 +1 @@
+9b1008df64741ad313ddf51969c18d609cd01a7255563fe0395d2bbf4d288e30 \ No newline at end of file
diff --git a/db/schema_migrations/20201106134950 b/db/schema_migrations/20201106134950
new file mode 100644
index 00000000000..b36cccd4c40
--- /dev/null
+++ b/db/schema_migrations/20201106134950
@@ -0,0 +1 @@
+f6e4e62dbd992fc8283f3d7872bb33f1b6bea1b366806caf8f7a65140584c0c1 \ No newline at end of file
diff --git a/db/schema_migrations/20201107032257 b/db/schema_migrations/20201107032257
new file mode 100644
index 00000000000..4ea5f763dc0
--- /dev/null
+++ b/db/schema_migrations/20201107032257
@@ -0,0 +1 @@
+07160ee3c92e68273042df979640c3927abbb187f79e1a4645471e28061e1c2c \ No newline at end of file
diff --git a/db/schema_migrations/20201109144634 b/db/schema_migrations/20201109144634
new file mode 100644
index 00000000000..8f47a75dfb8
--- /dev/null
+++ b/db/schema_migrations/20201109144634
@@ -0,0 +1 @@
+cbb2a2027fb6083771e97510a00c07a4ded0576e89fafd6cff4faba4e21c82c0 \ No newline at end of file
diff --git a/db/schema_migrations/20201109180311 b/db/schema_migrations/20201109180311
new file mode 100644
index 00000000000..0752e2dabb3
--- /dev/null
+++ b/db/schema_migrations/20201109180311
@@ -0,0 +1 @@
+49143d2a7dd0a53c051151b0cdc93745a0fa1b01e6d54bb663e147c2064d9290 \ No newline at end of file
diff --git a/db/schema_migrations/20201109184023 b/db/schema_migrations/20201109184023
new file mode 100644
index 00000000000..7a66c0f0f4c
--- /dev/null
+++ b/db/schema_migrations/20201109184023
@@ -0,0 +1 @@
+698bcedf387fc01fbb7f1899f0f7660ba86a197fa72cf71d998cc90e3d1da9f3 \ No newline at end of file
diff --git a/db/schema_migrations/20201110035029 b/db/schema_migrations/20201110035029
new file mode 100644
index 00000000000..9631f17bce0
--- /dev/null
+++ b/db/schema_migrations/20201110035029
@@ -0,0 +1 @@
+21245809e056dfefedc4d2c6a8e2bf642bfcee480a863f8707ba6fa6b748a2e0 \ No newline at end of file
diff --git a/db/schema_migrations/20201110110454 b/db/schema_migrations/20201110110454
new file mode 100644
index 00000000000..5b721550325
--- /dev/null
+++ b/db/schema_migrations/20201110110454
@@ -0,0 +1 @@
+f008d77d2a0aef463a924923d5a338030758d6b9c194756a0490b51a95681127 \ No newline at end of file
diff --git a/db/schema_migrations/20201110133629 b/db/schema_migrations/20201110133629
new file mode 100644
index 00000000000..487b5eab7c1
--- /dev/null
+++ b/db/schema_migrations/20201110133629
@@ -0,0 +1 @@
+83773b825db9b2671fd4ffb2c0d6733036737385ce7a933040011026b34ba1e1 \ No newline at end of file
diff --git a/db/schema_migrations/20201111110318 b/db/schema_migrations/20201111110318
new file mode 100644
index 00000000000..0a88f8f09df
--- /dev/null
+++ b/db/schema_migrations/20201111110318
@@ -0,0 +1 @@
+4168c39fe93b1c11d8080e07167f79c8234c74a7b274332174d9e861f2084ada \ No newline at end of file
diff --git a/db/schema_migrations/20201111110918 b/db/schema_migrations/20201111110918
new file mode 100644
index 00000000000..cfc30e2bcfc
--- /dev/null
+++ b/db/schema_migrations/20201111110918
@@ -0,0 +1 @@
+f5705da7bce46d98ca798c85f08d8a6a0577839aabacd0ba9b50e0b7351a4e96 \ No newline at end of file
diff --git a/db/schema_migrations/20201111152859 b/db/schema_migrations/20201111152859
new file mode 100644
index 00000000000..2d5b337b857
--- /dev/null
+++ b/db/schema_migrations/20201111152859
@@ -0,0 +1 @@
+4c5baa6a09a339fac544f830d5ef822b1e7e4eae8431bd91df5113125accbc77 \ No newline at end of file
diff --git a/db/schema_migrations/20201112195322 b/db/schema_migrations/20201112195322
new file mode 100644
index 00000000000..ba4c7e9d50f
--- /dev/null
+++ b/db/schema_migrations/20201112195322
@@ -0,0 +1 @@
+644bf793b3b62330bfb1f4dc406e6dd01cbcf4651ebfd2873fb551c757c8a3b4 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 4e6fc7e9260..f29f9178a26 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -8953,6 +8953,43 @@ CREATE SEQUENCE analytics_cycle_analytics_project_stages_id_seq
ALTER SEQUENCE analytics_cycle_analytics_project_stages_id_seq OWNED BY analytics_cycle_analytics_project_stages.id;
+CREATE TABLE analytics_devops_adoption_segment_selections (
+ id bigint NOT NULL,
+ segment_id bigint NOT NULL,
+ group_id bigint,
+ project_id bigint,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ CONSTRAINT segment_selection_project_id_or_group_id_required CHECK ((((project_id <> NULL::bigint) AND (group_id IS NULL)) OR ((group_id <> NULL::bigint) AND (project_id IS NULL))))
+);
+
+CREATE SEQUENCE analytics_devops_adoption_segment_selections_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE analytics_devops_adoption_segment_selections_id_seq OWNED BY analytics_devops_adoption_segment_selections.id;
+
+CREATE TABLE analytics_devops_adoption_segments (
+ id bigint NOT NULL,
+ name text NOT NULL,
+ last_recorded_at timestamp with time zone,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ CONSTRAINT check_4be7a006fd CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE analytics_devops_adoption_segments_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE analytics_devops_adoption_segments_id_seq OWNED BY analytics_devops_adoption_segments.id;
+
CREATE TABLE analytics_instance_statistics_measurements (
id bigint NOT NULL,
count bigint NOT NULL,
@@ -9046,7 +9083,6 @@ CREATE TABLE application_settings (
max_attachment_size integer DEFAULT 10 NOT NULL,
default_project_visibility integer DEFAULT 0 NOT NULL,
default_snippet_visibility integer DEFAULT 0 NOT NULL,
- domain_whitelist text,
user_oauth_applications boolean DEFAULT true,
after_sign_out_path character varying,
session_expire_delay integer DEFAULT 10080 NOT NULL,
@@ -9082,8 +9118,6 @@ CREATE TABLE application_settings (
elasticsearch_search boolean DEFAULT false NOT NULL,
repository_storages character varying DEFAULT 'default'::character varying,
enabled_git_access_protocol character varying,
- domain_blacklist_enabled boolean DEFAULT false,
- domain_blacklist text,
usage_ping_enabled boolean DEFAULT true NOT NULL,
sign_in_text_html text,
help_page_text_html text,
@@ -9171,7 +9205,7 @@ CREATE TABLE application_settings (
custom_project_templates_group_id integer,
usage_stats_set_by_user_id integer,
receive_max_input_size integer,
- diff_max_patch_bytes integer DEFAULT 102400 NOT NULL,
+ diff_max_patch_bytes integer DEFAULT 204800 NOT NULL,
archive_builds_in_seconds integer,
commit_email_hostname character varying,
protected_ci_variables boolean DEFAULT true NOT NULL,
@@ -9257,7 +9291,6 @@ CREATE TABLE application_settings (
email_restrictions_enabled boolean DEFAULT false NOT NULL,
email_restrictions text,
npm_package_requests_forwarding boolean DEFAULT true NOT NULL,
- namespace_storage_size_limit bigint DEFAULT 0 NOT NULL,
seat_link_enabled boolean DEFAULT true NOT NULL,
container_expiration_policies_enable_historic_entries boolean DEFAULT false NOT NULL,
issues_create_limit integer DEFAULT 0 NOT NULL,
@@ -9291,16 +9324,39 @@ CREATE TABLE application_settings (
gitpod_enabled boolean DEFAULT false NOT NULL,
gitpod_url text DEFAULT 'https://gitpod.io/'::text,
abuse_notification_email character varying,
- require_admin_approval_after_user_signup boolean DEFAULT false NOT NULL,
+ require_admin_approval_after_user_signup boolean DEFAULT true NOT NULL,
help_page_documentation_base_url text,
automatic_purchased_storage_allocation boolean DEFAULT false NOT NULL,
+ encrypted_ci_jwt_signing_key text,
+ encrypted_ci_jwt_signing_key_iv text,
+ container_registry_expiration_policies_worker_capacity integer DEFAULT 0 NOT NULL,
+ elasticsearch_analyzers_smartcn_enabled boolean DEFAULT false NOT NULL,
+ elasticsearch_analyzers_smartcn_search boolean DEFAULT false NOT NULL,
+ elasticsearch_analyzers_kuromoji_enabled boolean DEFAULT false NOT NULL,
+ elasticsearch_analyzers_kuromoji_search boolean DEFAULT false NOT NULL,
+ secret_detection_token_revocation_enabled boolean DEFAULT false NOT NULL,
+ secret_detection_token_revocation_url text,
+ encrypted_secret_detection_token_revocation_token text,
+ encrypted_secret_detection_token_revocation_token_iv text,
+ domain_denylist_enabled boolean DEFAULT false,
+ domain_denylist text,
+ domain_allowlist text,
+ new_user_signups_cap integer,
+ encrypted_cloud_license_auth_token text,
+ encrypted_cloud_license_auth_token_iv text,
+ secret_detection_revocation_token_types_url text,
+ CONSTRAINT app_settings_registry_exp_policies_worker_capacity_positive CHECK ((container_registry_expiration_policies_worker_capacity >= 0)),
CONSTRAINT check_2dba05b802 CHECK ((char_length(gitpod_url) <= 255)),
CONSTRAINT check_51700b31b5 CHECK ((char_length(default_branch_name) <= 255)),
CONSTRAINT check_57123c9593 CHECK ((char_length(help_page_documentation_base_url) <= 255)),
+ CONSTRAINT check_85a39b68ff CHECK ((char_length(encrypted_ci_jwt_signing_key_iv) <= 255)),
+ CONSTRAINT check_9a719834eb CHECK ((char_length(secret_detection_token_revocation_url) <= 255)),
CONSTRAINT check_9c6c447a13 CHECK ((char_length(maintenance_mode_message) <= 255)),
+ CONSTRAINT check_a5704163cc CHECK ((char_length(secret_detection_revocation_token_types_url) <= 255)),
CONSTRAINT check_d03919528d CHECK ((char_length(container_registry_vendor) <= 255)),
CONSTRAINT check_d820146492 CHECK ((char_length(spam_check_endpoint_url) <= 255)),
- CONSTRAINT check_e5aba18f02 CHECK ((char_length(container_registry_version) <= 255))
+ CONSTRAINT check_e5aba18f02 CHECK ((char_length(container_registry_version) <= 255)),
+ CONSTRAINT check_ef6176834f CHECK ((char_length(encrypted_cloud_license_auth_token_iv) <= 255))
);
CREATE SEQUENCE application_settings_id_seq
@@ -9608,7 +9664,9 @@ CREATE TABLE aws_roles (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
role_arn character varying(2048),
- role_external_id character varying(64) NOT NULL
+ role_external_id character varying(64) NOT NULL,
+ region text,
+ CONSTRAINT check_57adedab55 CHECK ((char_length(region) <= 255))
);
CREATE TABLE background_migration_jobs (
@@ -9865,6 +9923,26 @@ CREATE SEQUENCE bulk_import_entities_id_seq
ALTER SEQUENCE bulk_import_entities_id_seq OWNED BY bulk_import_entities.id;
+CREATE TABLE bulk_import_trackers (
+ id bigint NOT NULL,
+ bulk_import_entity_id bigint NOT NULL,
+ relation text NOT NULL,
+ next_page text,
+ has_next_page boolean DEFAULT false NOT NULL,
+ CONSTRAINT check_2d45cae629 CHECK ((char_length(relation) <= 255)),
+ CONSTRAINT check_40aeaa600b CHECK ((char_length(next_page) <= 255)),
+ CONSTRAINT check_next_page_requirement CHECK (((has_next_page IS FALSE) OR (next_page IS NOT NULL)))
+);
+
+CREATE SEQUENCE bulk_import_trackers_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE bulk_import_trackers_id_seq OWNED BY bulk_import_trackers.id;
+
CREATE TABLE bulk_imports (
id bigint NOT NULL,
user_id integer NOT NULL,
@@ -10129,7 +10207,8 @@ CREATE TABLE ci_daily_build_group_report_results (
last_pipeline_id bigint NOT NULL,
ref_path text NOT NULL,
group_name text NOT NULL,
- data jsonb NOT NULL
+ data jsonb NOT NULL,
+ default_branch boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE ci_daily_build_group_report_results_id_seq
@@ -10653,6 +10732,38 @@ CREATE SEQUENCE ci_subscriptions_projects_id_seq
ALTER SEQUENCE ci_subscriptions_projects_id_seq OWNED BY ci_subscriptions_projects.id;
+CREATE TABLE ci_test_case_failures (
+ id bigint NOT NULL,
+ failed_at timestamp with time zone,
+ test_case_id bigint NOT NULL,
+ build_id bigint NOT NULL
+);
+
+CREATE SEQUENCE ci_test_case_failures_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_test_case_failures_id_seq OWNED BY ci_test_case_failures.id;
+
+CREATE TABLE ci_test_cases (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ key_hash text NOT NULL,
+ CONSTRAINT check_dd3c5d1c15 CHECK ((char_length(key_hash) <= 64))
+);
+
+CREATE SEQUENCE ci_test_cases_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_test_cases_id_seq OWNED BY ci_test_cases.id;
+
CREATE TABLE ci_trigger_requests (
id integer NOT NULL,
trigger_id integer NOT NULL,
@@ -10883,7 +10994,8 @@ CREATE TABLE clusters (
namespace_per_environment boolean DEFAULT true NOT NULL,
management_project_id integer,
cleanup_status smallint DEFAULT 1 NOT NULL,
- cleanup_status_reason text
+ cleanup_status_reason text,
+ helm_major_version integer DEFAULT 2 NOT NULL
);
CREATE TABLE clusters_applications_cert_managers (
@@ -11197,11 +11309,11 @@ CREATE TABLE container_expiration_policies (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
next_run_at timestamp with time zone,
- name_regex character varying(255),
+ name_regex character varying(255) DEFAULT '.*'::character varying,
cadence character varying(12) DEFAULT '1d'::character varying NOT NULL,
older_than character varying(12) DEFAULT '90d'::character varying,
keep_n integer DEFAULT 10,
- enabled boolean DEFAULT true NOT NULL,
+ enabled boolean DEFAULT false NOT NULL,
name_regex_keep text,
CONSTRAINT container_expiration_policies_name_regex_keep CHECK ((char_length(name_regex_keep) <= 255))
);
@@ -11213,7 +11325,8 @@ CREATE TABLE container_repositories (
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
status smallint,
- expiration_policy_started_at timestamp with time zone
+ expiration_policy_started_at timestamp with time zone,
+ expiration_policy_cleanup_status smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE container_repositories_id_seq
@@ -11270,6 +11383,23 @@ CREATE SEQUENCE conversational_development_index_metrics_id_seq
ALTER SEQUENCE conversational_development_index_metrics_id_seq OWNED BY conversational_development_index_metrics.id;
+CREATE TABLE csv_issue_imports (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE csv_issue_imports_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE csv_issue_imports_id_seq OWNED BY csv_issue_imports.id;
+
CREATE TABLE custom_emoji (
id bigint NOT NULL,
namespace_id bigint NOT NULL,
@@ -11547,7 +11677,9 @@ CREATE TABLE design_management_designs (
issue_id integer,
filename character varying NOT NULL,
relative_position integer,
- CONSTRAINT check_07155e2715 CHECK ((char_length((filename)::text) <= 255))
+ iid integer,
+ CONSTRAINT check_07155e2715 CHECK ((char_length((filename)::text) <= 255)),
+ CONSTRAINT check_cfb92df01a CHECK ((iid IS NOT NULL))
);
CREATE SEQUENCE design_management_designs_id_seq
@@ -12647,10 +12779,12 @@ CREATE TABLE group_wiki_repositories (
CREATE TABLE historical_data (
id integer NOT NULL,
- date date NOT NULL,
+ date date,
active_user_count integer,
created_at timestamp without time zone,
- updated_at timestamp without time zone
+ updated_at timestamp without time zone,
+ recorded_at timestamp with time zone,
+ CONSTRAINT check_640e8cf66c CHECK ((recorded_at IS NOT NULL))
);
CREATE SEQUENCE historical_data_id_seq
@@ -13063,6 +13197,9 @@ CREATE TABLE jira_tracker_data (
project_key text,
issues_enabled boolean DEFAULT false NOT NULL,
deployment_type smallint DEFAULT 0 NOT NULL,
+ vulnerabilities_issuetype text,
+ vulnerabilities_enabled boolean DEFAULT false NOT NULL,
+ CONSTRAINT check_0bf84b76e9 CHECK ((char_length(vulnerabilities_issuetype) <= 255)),
CONSTRAINT check_214cf6a48b CHECK ((char_length(project_key) <= 255))
);
@@ -13354,6 +13491,23 @@ CREATE SEQUENCE merge_request_blocks_id_seq
ALTER SEQUENCE merge_request_blocks_id_seq OWNED BY merge_request_blocks.id;
+CREATE TABLE merge_request_cleanup_schedules (
+ merge_request_id bigint NOT NULL,
+ scheduled_at timestamp with time zone NOT NULL,
+ completed_at timestamp with time zone,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE merge_request_cleanup_schedules_merge_request_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE merge_request_cleanup_schedules_merge_request_id_seq OWNED BY merge_request_cleanup_schedules.merge_request_id;
+
CREATE TABLE merge_request_context_commit_diff_files (
sha bytea NOT NULL,
relative_order integer NOT NULL,
@@ -13724,7 +13878,8 @@ CREATE TABLE namespace_root_storage_statistics (
storage_size bigint DEFAULT 0 NOT NULL,
packages_size bigint DEFAULT 0 NOT NULL,
snippets_size bigint DEFAULT 0 NOT NULL,
- pipeline_artifacts_size bigint DEFAULT 0 NOT NULL
+ pipeline_artifacts_size bigint DEFAULT 0 NOT NULL,
+ uploads_size bigint DEFAULT 0 NOT NULL
);
CREATE TABLE namespace_settings (
@@ -14298,6 +14453,21 @@ CREATE TABLE packages_nuget_metadata (
CONSTRAINT packages_nuget_metadata_project_url_constraint CHECK ((char_length(project_url) <= 255))
);
+CREATE TABLE packages_package_file_build_infos (
+ id bigint NOT NULL,
+ package_file_id bigint NOT NULL,
+ pipeline_id bigint
+);
+
+CREATE SEQUENCE packages_package_file_build_infos_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_package_file_build_infos_id_seq OWNED BY packages_package_file_build_infos.id;
+
CREATE TABLE packages_package_files (
id bigint NOT NULL,
package_id bigint NOT NULL,
@@ -14380,6 +14550,8 @@ CREATE TABLE pages_deployments (
file_store smallint NOT NULL,
size integer NOT NULL,
file text NOT NULL,
+ file_count integer NOT NULL,
+ file_sha256 bytea NOT NULL,
CONSTRAINT check_f0fe8032dd CHECK ((char_length(file) <= 255))
);
@@ -14524,7 +14696,7 @@ CREATE TABLE plan_limits (
offset_pagination_limit integer DEFAULT 50000 NOT NULL,
ci_instance_level_variables integer DEFAULT 25 NOT NULL,
storage_size_limit integer DEFAULT 0 NOT NULL,
- ci_max_artifact_size_lsif integer DEFAULT 20 NOT NULL,
+ ci_max_artifact_size_lsif integer DEFAULT 100 NOT NULL,
ci_max_artifact_size_archive integer DEFAULT 0 NOT NULL,
ci_max_artifact_size_metadata integer DEFAULT 0 NOT NULL,
ci_max_artifact_size_trace integer DEFAULT 0 NOT NULL,
@@ -14615,6 +14787,8 @@ CREATE VIEW postgres_indexes AS
pg_index.indisvalid AS valid_index,
pg_class.relispartition AS partitioned,
pg_index.indisexclusion AS exclusion,
+ (pg_index.indexprs IS NOT NULL) AS expression,
+ (pg_index.indpred IS NOT NULL) AS partial,
pg_indexes.indexdef AS definition,
pg_relation_size((pg_class.oid)::regclass) AS ondisk_size_bytes
FROM (((pg_index
@@ -14623,6 +14797,48 @@ CREATE VIEW postgres_indexes AS
JOIN pg_indexes ON ((pg_class.relname = pg_indexes.indexname)))
WHERE ((pg_namespace.nspname <> 'pg_catalog'::name) AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name])));
+CREATE VIEW postgres_partitioned_tables AS
+ SELECT (((pg_namespace.nspname)::text || '.'::text) || (pg_class.relname)::text) AS identifier,
+ pg_class.oid,
+ pg_namespace.nspname AS schema,
+ pg_class.relname AS name,
+ CASE partitioned_tables.partstrat
+ WHEN 'l'::"char" THEN 'list'::text
+ WHEN 'r'::"char" THEN 'range'::text
+ WHEN 'h'::"char" THEN 'hash'::text
+ ELSE NULL::text
+ END AS strategy,
+ array_agg(pg_attribute.attname) AS key_columns
+ FROM (((( SELECT pg_partitioned_table.partrelid,
+ pg_partitioned_table.partstrat,
+ unnest(pg_partitioned_table.partattrs) AS column_position
+ FROM pg_partitioned_table) partitioned_tables
+ JOIN pg_class ON ((partitioned_tables.partrelid = pg_class.oid)))
+ JOIN pg_namespace ON ((pg_class.relnamespace = pg_namespace.oid)))
+ JOIN pg_attribute ON (((pg_attribute.attrelid = pg_class.oid) AND (pg_attribute.attnum = partitioned_tables.column_position))))
+ WHERE (pg_namespace.nspname = "current_schema"())
+ GROUP BY (((pg_namespace.nspname)::text || '.'::text) || (pg_class.relname)::text), pg_class.oid, pg_namespace.nspname, pg_class.relname,
+ CASE partitioned_tables.partstrat
+ WHEN 'l'::"char" THEN 'list'::text
+ WHEN 'r'::"char" THEN 'range'::text
+ WHEN 'h'::"char" THEN 'hash'::text
+ ELSE NULL::text
+ END;
+
+CREATE VIEW postgres_partitions AS
+ SELECT (((pg_namespace.nspname)::text || '.'::text) || (pg_class.relname)::text) AS identifier,
+ pg_class.oid,
+ pg_namespace.nspname AS schema,
+ pg_class.relname AS name,
+ (((parent_namespace.nspname)::text || '.'::text) || (parent_class.relname)::text) AS parent_identifier,
+ pg_get_expr(pg_class.relpartbound, pg_inherits.inhrelid) AS condition
+ FROM ((((pg_class
+ JOIN pg_namespace ON ((pg_namespace.oid = pg_class.relnamespace)))
+ JOIN pg_inherits ON ((pg_class.oid = pg_inherits.inhrelid)))
+ JOIN pg_class parent_class ON ((pg_inherits.inhparent = parent_class.oid)))
+ JOIN pg_namespace parent_namespace ON ((parent_class.relnamespace = parent_namespace.oid)))
+ WHERE (pg_class.relispartition AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name])));
+
CREATE TABLE postgres_reindex_actions (
id bigint NOT NULL,
action_start timestamp with time zone NOT NULL,
@@ -14717,7 +14933,9 @@ CREATE TABLE project_ci_cd_settings (
group_runners_enabled boolean DEFAULT true NOT NULL,
merge_pipelines_enabled boolean,
default_git_depth integer,
- forward_deployment_enabled boolean
+ forward_deployment_enabled boolean,
+ merge_trains_enabled boolean DEFAULT false,
+ auto_rollback_enabled boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE project_ci_cd_settings_id_seq
@@ -14731,7 +14949,7 @@ ALTER SEQUENCE project_ci_cd_settings_id_seq OWNED BY project_ci_cd_settings.id;
CREATE TABLE project_compliance_framework_settings (
project_id bigint NOT NULL,
- framework smallint NOT NULL,
+ framework smallint,
framework_id bigint,
CONSTRAINT check_d348de9e2d CHECK ((framework_id IS NOT NULL))
);
@@ -14842,7 +15060,8 @@ CREATE TABLE project_features (
repository_access_level integer DEFAULT 20 NOT NULL,
pages_access_level integer NOT NULL,
forking_access_level integer,
- metrics_dashboard_access_level integer
+ metrics_dashboard_access_level integer,
+ requirements_access_level integer DEFAULT 20 NOT NULL
);
CREATE SEQUENCE project_features_id_seq
@@ -15041,6 +15260,7 @@ CREATE TABLE project_settings (
allow_merge_on_skipped_pipeline boolean,
squash_option smallint DEFAULT 3,
has_confluence boolean DEFAULT false NOT NULL,
+ has_vulnerabilities boolean DEFAULT false NOT NULL,
CONSTRAINT check_bde223416c CHECK ((show_default_award_emojis IS NOT NULL))
);
@@ -15058,7 +15278,8 @@ CREATE TABLE project_statistics (
packages_size bigint DEFAULT 0 NOT NULL,
wiki_size bigint,
snippets_size bigint,
- pipeline_artifacts_size bigint DEFAULT 0 NOT NULL
+ pipeline_artifacts_size bigint DEFAULT 0 NOT NULL,
+ uploads_size bigint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE project_statistics_id_seq
@@ -15840,6 +16061,7 @@ CREATE TABLE security_findings (
confidence smallint NOT NULL,
project_fingerprint text NOT NULL,
deduplicated boolean DEFAULT false NOT NULL,
+ "position" integer,
CONSTRAINT check_b9508c6df8 CHECK ((char_length(project_fingerprint) <= 40))
);
@@ -15857,8 +16079,7 @@ CREATE TABLE security_scans (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
build_id bigint NOT NULL,
- scan_type smallint NOT NULL,
- scanned_resources_count integer
+ scan_type smallint NOT NULL
);
CREATE SEQUENCE security_scans_id_seq
@@ -16049,6 +16270,27 @@ CREATE TABLE snippet_repositories (
CONSTRAINT snippet_repositories_verification_failure_text_limit CHECK ((char_length(verification_failure) <= 255))
);
+CREATE TABLE snippet_repository_storage_moves (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ snippet_id bigint NOT NULL,
+ state smallint DEFAULT 1 NOT NULL,
+ source_storage_name text NOT NULL,
+ destination_storage_name text NOT NULL,
+ CONSTRAINT snippet_repository_storage_moves_destination_storage_name CHECK ((char_length(destination_storage_name) <= 255)),
+ CONSTRAINT snippet_repository_storage_moves_source_storage_name CHECK ((char_length(source_storage_name) <= 255))
+);
+
+CREATE SEQUENCE snippet_repository_storage_moves_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE snippet_repository_storage_moves_id_seq OWNED BY snippet_repository_storage_moves.id;
+
CREATE TABLE snippet_statistics (
snippet_id bigint NOT NULL,
repository_size bigint DEFAULT 0 NOT NULL,
@@ -16092,7 +16334,8 @@ CREATE TABLE snippets (
description_html text,
encrypted_secret_token character varying(255),
encrypted_secret_token_iv character varying(255),
- secret boolean DEFAULT false NOT NULL
+ secret boolean DEFAULT false NOT NULL,
+ repository_read_only boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE snippets_id_seq
@@ -16356,6 +16599,7 @@ CREATE TABLE terraform_state_versions (
verified_at timestamp with time zone,
verification_checksum bytea,
verification_failure text,
+ ci_build_id bigint,
CONSTRAINT check_0824bb7bbd CHECK ((char_length(file) <= 255)),
CONSTRAINT tf_state_versions_verification_failure_text_limit CHECK ((char_length(verification_failure) <= 255))
);
@@ -16381,13 +16625,7 @@ CREATE TABLE terraform_states (
locked_by_user_id bigint,
uuid character varying(32) NOT NULL,
name character varying(255),
- verification_retry_at timestamp with time zone,
- verified_at timestamp with time zone,
- 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))
+ versioning_enabled boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE terraform_states_id_seq
@@ -16649,7 +16887,8 @@ CREATE TABLE user_statuses (
cached_markdown_version integer,
emoji character varying DEFAULT 'speech_balloon'::character varying NOT NULL,
message character varying(100),
- message_html character varying
+ message_html character varying,
+ availability smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE user_statuses_user_id_seq
@@ -16929,6 +17168,26 @@ CREATE SEQUENCE vulnerability_feedback_id_seq
ALTER SEQUENCE vulnerability_feedback_id_seq OWNED BY vulnerability_feedback.id;
+CREATE TABLE vulnerability_finding_links (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ vulnerability_occurrence_id bigint NOT NULL,
+ name text,
+ url text NOT NULL,
+ CONSTRAINT check_55f0a95439 CHECK ((char_length(name) <= 255)),
+ CONSTRAINT check_b7fe886df6 CHECK ((char_length(url) <= 2048))
+);
+
+CREATE SEQUENCE vulnerability_finding_links_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_finding_links_id_seq OWNED BY vulnerability_finding_links.id;
+
CREATE TABLE vulnerability_historical_statistics (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -17166,7 +17425,9 @@ CREATE TABLE web_hooks (
encrypted_token_iv character varying,
encrypted_url character varying,
encrypted_url_iv character varying,
- deployment_events boolean DEFAULT false NOT NULL
+ deployment_events boolean DEFAULT false NOT NULL,
+ releases_events boolean DEFAULT false NOT NULL,
+ feature_flag_events boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE web_hooks_id_seq
@@ -17333,6 +17594,10 @@ ALTER TABLE ONLY analytics_cycle_analytics_group_value_streams ALTER COLUMN id S
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 analytics_devops_adoption_segment_selections ALTER COLUMN id SET DEFAULT nextval('analytics_devops_adoption_segment_selections_id_seq'::regclass);
+
+ALTER TABLE ONLY analytics_devops_adoption_segments ALTER COLUMN id SET DEFAULT nextval('analytics_devops_adoption_segments_id_seq'::regclass);
+
ALTER TABLE ONLY analytics_instance_statistics_measurements ALTER COLUMN id SET DEFAULT nextval('analytics_instance_statistics_measurements_id_seq'::regclass);
ALTER TABLE ONLY appearances ALTER COLUMN id SET DEFAULT nextval('appearances_id_seq'::regclass);
@@ -17395,6 +17660,8 @@ ALTER TABLE ONLY bulk_import_configurations ALTER COLUMN id SET DEFAULT nextval(
ALTER TABLE ONLY bulk_import_entities ALTER COLUMN id SET DEFAULT nextval('bulk_import_entities_id_seq'::regclass);
+ALTER TABLE ONLY bulk_import_trackers ALTER COLUMN id SET DEFAULT nextval('bulk_import_trackers_id_seq'::regclass);
+
ALTER TABLE ONLY bulk_imports ALTER COLUMN id SET DEFAULT nextval('bulk_imports_id_seq'::regclass);
ALTER TABLE ONLY chat_names ALTER COLUMN id SET DEFAULT nextval('chat_names_id_seq'::regclass);
@@ -17469,6 +17736,10 @@ ALTER TABLE ONLY ci_stages ALTER COLUMN id SET DEFAULT nextval('ci_stages_id_seq
ALTER TABLE ONLY ci_subscriptions_projects ALTER COLUMN id SET DEFAULT nextval('ci_subscriptions_projects_id_seq'::regclass);
+ALTER TABLE ONLY ci_test_case_failures ALTER COLUMN id SET DEFAULT nextval('ci_test_case_failures_id_seq'::regclass);
+
+ALTER TABLE ONLY ci_test_cases ALTER COLUMN id SET DEFAULT nextval('ci_test_cases_id_seq'::regclass);
+
ALTER TABLE ONLY ci_trigger_requests ALTER COLUMN id SET DEFAULT nextval('ci_trigger_requests_id_seq'::regclass);
ALTER TABLE ONLY ci_triggers ALTER COLUMN id SET DEFAULT nextval('ci_triggers_id_seq'::regclass);
@@ -17523,6 +17794,8 @@ ALTER TABLE ONLY container_repositories ALTER COLUMN id SET DEFAULT nextval('con
ALTER TABLE ONLY conversational_development_index_metrics ALTER COLUMN id SET DEFAULT nextval('conversational_development_index_metrics_id_seq'::regclass);
+ALTER TABLE ONLY csv_issue_imports ALTER COLUMN id SET DEFAULT nextval('csv_issue_imports_id_seq'::regclass);
+
ALTER TABLE ONLY custom_emoji ALTER COLUMN id SET DEFAULT nextval('custom_emoji_id_seq'::regclass);
ALTER TABLE ONLY dast_scanner_profiles ALTER COLUMN id SET DEFAULT nextval('dast_scanner_profiles_id_seq'::regclass);
@@ -17719,6 +17992,8 @@ ALTER TABLE ONLY merge_request_assignees ALTER COLUMN id SET DEFAULT nextval('me
ALTER TABLE ONLY merge_request_blocks ALTER COLUMN id SET DEFAULT nextval('merge_request_blocks_id_seq'::regclass);
+ALTER TABLE ONLY merge_request_cleanup_schedules ALTER COLUMN merge_request_id SET DEFAULT nextval('merge_request_cleanup_schedules_merge_request_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 merge_request_diff_details ALTER COLUMN merge_request_diff_id SET DEFAULT nextval('merge_request_diff_details_merge_request_diff_id_seq'::regclass);
@@ -17793,6 +18068,8 @@ ALTER TABLE ONLY packages_events ALTER COLUMN id SET DEFAULT nextval('packages_e
ALTER TABLE ONLY packages_maven_metadata ALTER COLUMN id SET DEFAULT nextval('packages_maven_metadata_id_seq'::regclass);
+ALTER TABLE ONLY packages_package_file_build_infos ALTER COLUMN id SET DEFAULT nextval('packages_package_file_build_infos_id_seq'::regclass);
+
ALTER TABLE ONLY packages_package_files ALTER COLUMN id SET DEFAULT nextval('packages_package_files_id_seq'::regclass);
ALTER TABLE ONLY packages_packages ALTER COLUMN id SET DEFAULT nextval('packages_packages_id_seq'::regclass);
@@ -17943,6 +18220,8 @@ ALTER TABLE ONLY slack_integrations ALTER COLUMN id SET DEFAULT nextval('slack_i
ALTER TABLE ONLY smartcard_identities ALTER COLUMN id SET DEFAULT nextval('smartcard_identities_id_seq'::regclass);
+ALTER TABLE ONLY snippet_repository_storage_moves ALTER COLUMN id SET DEFAULT nextval('snippet_repository_storage_moves_id_seq'::regclass);
+
ALTER TABLE ONLY snippet_user_mentions ALTER COLUMN id SET DEFAULT nextval('snippet_user_mentions_id_seq'::regclass);
ALTER TABLE ONLY snippets ALTER COLUMN id SET DEFAULT nextval('snippets_id_seq'::regclass);
@@ -18015,6 +18294,8 @@ ALTER TABLE ONLY vulnerability_exports ALTER COLUMN id SET DEFAULT nextval('vuln
ALTER TABLE ONLY vulnerability_feedback ALTER COLUMN id SET DEFAULT nextval('vulnerability_feedback_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_finding_links ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_links_id_seq'::regclass);
+
ALTER TABLE ONLY vulnerability_historical_statistics ALTER COLUMN id SET DEFAULT nextval('vulnerability_historical_statistics_id_seq'::regclass);
ALTER TABLE ONLY vulnerability_identifiers ALTER COLUMN id SET DEFAULT nextval('vulnerability_identifiers_id_seq'::regclass);
@@ -18276,9 +18557,18 @@ ALTER TABLE ONLY analytics_cycle_analytics_group_value_streams
ALTER TABLE ONLY analytics_cycle_analytics_project_stages
ADD CONSTRAINT analytics_cycle_analytics_project_stages_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY analytics_devops_adoption_segment_selections
+ ADD CONSTRAINT analytics_devops_adoption_segment_selections_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY analytics_devops_adoption_segments
+ ADD CONSTRAINT analytics_devops_adoption_segments_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY analytics_instance_statistics_measurements
ADD CONSTRAINT analytics_instance_statistics_measurements_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY analytics_language_trend_repository_languages
+ ADD CONSTRAINT analytics_language_trend_repository_languages_pkey PRIMARY KEY (programming_language_id, project_id, snapshot_date);
+
ALTER TABLE ONLY appearances
ADD CONSTRAINT appearances_pkey PRIMARY KEY (id);
@@ -18309,6 +18599,9 @@ ALTER TABLE ONLY approval_project_rules_groups
ALTER TABLE ONLY approval_project_rules
ADD CONSTRAINT approval_project_rules_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY approval_project_rules_protected_branches
+ ADD CONSTRAINT approval_project_rules_protected_branches_pkey PRIMARY KEY (approval_project_rule_id, protected_branch_id);
+
ALTER TABLE ONLY approval_project_rules_users
ADD CONSTRAINT approval_project_rules_users_pkey PRIMARY KEY (id);
@@ -18381,6 +18674,9 @@ ALTER TABLE ONLY bulk_import_configurations
ALTER TABLE ONLY bulk_import_entities
ADD CONSTRAINT bulk_import_entities_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY bulk_import_trackers
+ ADD CONSTRAINT bulk_import_trackers_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY bulk_imports
ADD CONSTRAINT bulk_imports_pkey PRIMARY KEY (id);
@@ -18411,6 +18707,9 @@ ALTER TABLE ONLY ci_build_trace_chunks
ALTER TABLE ONLY ci_build_trace_section_names
ADD CONSTRAINT ci_build_trace_section_names_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_build_trace_sections
+ ADD CONSTRAINT ci_build_trace_sections_pkey PRIMARY KEY (build_id, section_name_id);
+
ALTER TABLE ONLY ci_builds_metadata
ADD CONSTRAINT ci_builds_metadata_pkey PRIMARY KEY (id);
@@ -18498,6 +18797,12 @@ ALTER TABLE ONLY ci_stages
ALTER TABLE ONLY ci_subscriptions_projects
ADD CONSTRAINT ci_subscriptions_projects_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_test_case_failures
+ ADD CONSTRAINT ci_test_case_failures_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY ci_test_cases
+ ADD CONSTRAINT ci_test_cases_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_trigger_requests
ADD CONSTRAINT ci_trigger_requests_pkey PRIMARY KEY (id);
@@ -18582,6 +18887,9 @@ ALTER TABLE ONLY container_repositories
ALTER TABLE ONLY conversational_development_index_metrics
ADD CONSTRAINT conversational_development_index_metrics_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY csv_issue_imports
+ ADD CONSTRAINT csv_issue_imports_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY custom_emoji
ADD CONSTRAINT custom_emoji_pkey PRIMARY KEY (id);
@@ -18615,6 +18923,9 @@ ALTER TABLE ONLY deploy_tokens
ALTER TABLE ONLY deployment_clusters
ADD CONSTRAINT deployment_clusters_pkey PRIMARY KEY (deployment_id);
+ALTER TABLE ONLY deployment_merge_requests
+ ADD CONSTRAINT deployment_merge_requests_pkey PRIMARY KEY (deployment_id, merge_request_id);
+
ALTER TABLE ONLY deployments
ADD CONSTRAINT deployments_pkey PRIMARY KEY (id);
@@ -18813,6 +19124,9 @@ ALTER TABLE ONLY issuable_severities
ALTER TABLE ONLY issuable_slas
ADD CONSTRAINT issuable_slas_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY issue_assignees
+ ADD CONSTRAINT issue_assignees_pkey PRIMARY KEY (issue_id, user_id);
+
ALTER TABLE ONLY issue_email_participants
ADD CONSTRAINT issue_email_participants_pkey PRIMARY KEY (id);
@@ -18831,6 +19145,12 @@ ALTER TABLE ONLY issue_user_mentions
ALTER TABLE ONLY issues
ADD CONSTRAINT issues_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY issues_prometheus_alert_events
+ ADD CONSTRAINT issues_prometheus_alert_events_pkey PRIMARY KEY (issue_id, prometheus_alert_event_id);
+
+ALTER TABLE ONLY issues_self_managed_prometheus_alert_events
+ ADD CONSTRAINT issues_self_managed_prometheus_alert_events_pkey PRIMARY KEY (issue_id, self_managed_prometheus_alert_event_id);
+
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));
@@ -18891,12 +19211,21 @@ ALTER TABLE ONLY merge_request_assignees
ALTER TABLE ONLY merge_request_blocks
ADD CONSTRAINT merge_request_blocks_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY merge_request_cleanup_schedules
+ ADD CONSTRAINT merge_request_cleanup_schedules_pkey PRIMARY KEY (merge_request_id);
+
ALTER TABLE ONLY merge_request_context_commits
ADD CONSTRAINT merge_request_context_commits_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY merge_request_diff_commits
+ ADD CONSTRAINT merge_request_diff_commits_pkey PRIMARY KEY (merge_request_diff_id, relative_order);
+
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_diff_files
+ ADD CONSTRAINT merge_request_diff_files_pkey PRIMARY KEY (merge_request_diff_id, relative_order);
+
ALTER TABLE ONLY merge_request_diffs
ADD CONSTRAINT merge_request_diffs_pkey PRIMARY KEY (id);
@@ -18924,6 +19253,9 @@ ALTER TABLE ONLY metrics_dashboard_annotations
ALTER TABLE ONLY metrics_users_starred_dashboards
ADD CONSTRAINT metrics_users_starred_dashboards_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY milestone_releases
+ ADD CONSTRAINT milestone_releases_pkey PRIMARY KEY (milestone_id, release_id);
+
ALTER TABLE ONLY milestones
ADD CONSTRAINT milestones_pkey PRIMARY KEY (id);
@@ -19023,6 +19355,9 @@ ALTER TABLE ONLY packages_nuget_dependency_link_metadata
ALTER TABLE ONLY packages_nuget_metadata
ADD CONSTRAINT packages_nuget_metadata_pkey PRIMARY KEY (package_id);
+ALTER TABLE ONLY packages_package_file_build_infos
+ ADD CONSTRAINT packages_package_file_build_infos_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_package_files
ADD CONSTRAINT packages_package_files_pkey PRIMARY KEY (id);
@@ -19077,6 +19412,9 @@ ALTER TABLE ONLY project_alerting_settings
ALTER TABLE ONLY project_aliases
ADD CONSTRAINT project_aliases_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY project_authorizations
+ ADD CONSTRAINT project_authorizations_pkey PRIMARY KEY (user_id, project_id, access_level);
+
ALTER TABLE ONLY project_auto_devops
ADD CONSTRAINT project_auto_devops_pkey PRIMARY KEY (id);
@@ -19122,6 +19460,9 @@ ALTER TABLE ONLY project_metrics_settings
ALTER TABLE ONLY project_mirror_data
ADD CONSTRAINT project_mirror_data_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY project_pages_metadata
+ ADD CONSTRAINT project_pages_metadata_pkey PRIMARY KEY (project_id);
+
ALTER TABLE ONLY project_repositories
ADD CONSTRAINT project_repositories_pkey PRIMARY KEY (id);
@@ -19179,6 +19520,9 @@ ALTER TABLE ONLY protected_tag_create_access_levels
ALTER TABLE ONLY protected_tags
ADD CONSTRAINT protected_tags_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY push_event_payloads
+ ADD CONSTRAINT push_event_payloads_pkey PRIMARY KEY (event_id);
+
ALTER TABLE ONLY push_rules
ADD CONSTRAINT push_rules_pkey PRIMARY KEY (id);
@@ -19197,6 +19541,9 @@ ALTER TABLE ONLY releases
ALTER TABLE ONLY remote_mirrors
ADD CONSTRAINT remote_mirrors_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY repository_languages
+ ADD CONSTRAINT repository_languages_pkey PRIMARY KEY (project_id, programming_language_id);
+
ALTER TABLE ONLY required_code_owners_sections
ADD CONSTRAINT required_code_owners_sections_pkey PRIMARY KEY (id);
@@ -19278,6 +19625,9 @@ ALTER TABLE ONLY smartcard_identities
ALTER TABLE ONLY snippet_repositories
ADD CONSTRAINT snippet_repositories_pkey PRIMARY KEY (snippet_id);
+ALTER TABLE ONLY snippet_repository_storage_moves
+ ADD CONSTRAINT snippet_repository_storage_moves_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY snippet_statistics
ADD CONSTRAINT snippet_statistics_pkey PRIMARY KEY (snippet_id);
@@ -19362,6 +19712,9 @@ ALTER TABLE ONLY user_details
ALTER TABLE ONLY user_highest_roles
ADD CONSTRAINT user_highest_roles_pkey PRIMARY KEY (user_id);
+ALTER TABLE ONLY user_interacted_projects
+ ADD CONSTRAINT user_interacted_projects_pkey PRIMARY KEY (project_id, user_id);
+
ALTER TABLE ONLY user_preferences
ADD CONSTRAINT user_preferences_pkey PRIMARY KEY (id);
@@ -19377,6 +19730,9 @@ ALTER TABLE ONLY users_ops_dashboard_projects
ALTER TABLE ONLY users
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY users_security_dashboard_projects
+ ADD CONSTRAINT users_security_dashboard_projects_pkey PRIMARY KEY (project_id, user_id);
+
ALTER TABLE ONLY users_star_projects
ADD CONSTRAINT users_star_projects_pkey PRIMARY KEY (id);
@@ -19392,6 +19748,9 @@ ALTER TABLE ONLY vulnerability_exports
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT vulnerability_feedback_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY vulnerability_finding_links
+ ADD CONSTRAINT vulnerability_finding_links_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY vulnerability_historical_statistics
ADD CONSTRAINT vulnerability_historical_statistics_pkey PRIMARY KEY (id);
@@ -19576,14 +19935,14 @@ 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 active_billable_users ON users USING btree (id) WHERE (((state)::text = 'active'::text) AND ((user_type IS NULL) OR (user_type = ANY (ARRAY[NULL::integer, 6, 4]))) AND ((user_type IS NULL) OR (user_type <> ALL ('{2,6,1,3,7,8}'::smallint[]))));
+
CREATE INDEX analytics_index_audit_events_on_created_at_and_author_id ON audit_events USING btree (created_at, author_id);
CREATE INDEX analytics_index_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);
@@ -19604,6 +19963,8 @@ 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 UNIQUE INDEX bulk_import_trackers_uniq_relation_by_entity ON bulk_import_trackers USING btree (bulk_import_entity_id, relation);
+
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);
@@ -19618,15 +19979,17 @@ CREATE UNIQUE INDEX epic_user_mentions_on_epic_id_and_note_id_index ON epic_user
CREATE UNIQUE INDEX epic_user_mentions_on_epic_id_index ON epic_user_mentions USING btree (epic_id) WHERE (note_id IS NULL);
+CREATE INDEX finding_links_on_vulnerability_occurrence_id ON vulnerability_finding_links USING btree (vulnerability_occurrence_id);
+
CREATE INDEX idx_audit_events_on_entity_id_desc_author_id_created_at ON audit_events USING btree (entity_id, entity_type, id DESC, author_id, created_at);
CREATE INDEX idx_ci_pipelines_artifacts_locked ON ci_pipelines USING btree (ci_ref_id, id) WHERE (locked = 1);
CREATE INDEX idx_container_exp_policies_on_project_id_next_run_at_enabled ON container_expiration_policies USING btree (project_id, next_run_at, enabled);
-CREATE INDEX idx_deployment_clusters_on_cluster_id_and_kubernetes_namespace ON deployment_clusters USING btree (cluster_id, kubernetes_namespace);
+CREATE INDEX idx_container_repositories_on_exp_cleanup_status_and_start_date ON container_repositories USING btree (expiration_policy_cleanup_status, expiration_policy_started_at);
-CREATE UNIQUE INDEX idx_deployment_merge_requests_unique_index ON deployment_merge_requests USING btree (deployment_id, merge_request_id);
+CREATE INDEX idx_deployment_clusters_on_cluster_id_and_kubernetes_namespace ON deployment_clusters USING btree (cluster_id, kubernetes_namespace);
CREATE UNIQUE INDEX idx_environment_merge_requests_unique_index ON deployment_merge_requests USING btree (environment_id, merge_request_id);
@@ -19668,6 +20031,8 @@ CREATE INDEX idx_mr_cc_diff_files_on_mr_cc_id_and_sha ON merge_request_context_c
CREATE UNIQUE INDEX idx_on_compliance_management_frameworks_namespace_id_name ON compliance_management_frameworks USING btree (namespace_id, name);
+CREATE INDEX idx_packages_build_infos_on_package_id ON packages_build_infos USING btree (package_id);
+
CREATE INDEX idx_packages_packages_on_project_id_name_version_package_type ON packages_packages USING btree (project_id, name, version, package_type);
CREATE 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);
@@ -19756,6 +20121,8 @@ CREATE INDEX index_analytics_ca_project_stages_on_start_event_label_id ON analyt
CREATE INDEX index_analytics_cycle_analytics_group_stages_custom_only ON analytics_cycle_analytics_group_stages USING btree (id) WHERE (custom = true);
+CREATE UNIQUE INDEX index_analytics_devops_adoption_segments_on_name ON analytics_devops_adoption_segments USING btree (name);
+
CREATE INDEX index_application_settings_on_custom_project_templates_group_id ON application_settings USING btree (custom_project_templates_group_id);
CREATE INDEX index_application_settings_on_file_template_project_id ON application_settings USING btree (file_template_project_id);
@@ -19796,8 +20163,6 @@ CREATE INDEX index_approval_project_rules_on_rule_type ON approval_project_rules
CREATE INDEX index_approval_project_rules_protected_branches_pb_id ON approval_project_rules_protected_branches USING btree (protected_branch_id);
-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 UNIQUE INDEX index_approval_project_rules_users_1 ON approval_project_rules_users USING btree (approval_project_rule_id, user_id);
CREATE INDEX index_approval_project_rules_users_2 ON approval_project_rules_users USING btree (user_id);
@@ -19922,8 +20287,6 @@ CREATE UNIQUE INDEX index_ci_build_trace_chunks_on_build_id_and_chunk_index ON c
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 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 INDEX index_ci_build_trace_sections_on_project_id ON ci_build_trace_sections USING btree (project_id);
CREATE INDEX index_ci_build_trace_sections_on_section_name_id ON ci_build_trace_sections USING btree (section_name_id);
@@ -19984,6 +20347,8 @@ CREATE UNIQUE INDEX index_ci_builds_runner_session_on_build_id ON ci_builds_runn
CREATE INDEX index_ci_daily_build_group_report_results_on_last_pipeline_id ON ci_daily_build_group_report_results USING btree (last_pipeline_id);
+CREATE INDEX index_ci_daily_build_group_report_results_on_project_and_date ON ci_daily_build_group_report_results USING btree (project_id, date DESC) WHERE ((default_branch = true) AND ((data -> 'coverage'::text) IS NOT NULL));
+
CREATE INDEX index_ci_deleted_objects_on_pick_up_at ON ci_deleted_objects USING btree (pick_up_at);
CREATE INDEX index_ci_freeze_periods_on_project_id ON ci_freeze_periods USING btree (project_id);
@@ -20002,8 +20367,6 @@ CREATE INDEX index_ci_job_artifacts_on_file_store ON ci_job_artifacts USING btre
CREATE UNIQUE INDEX index_ci_job_artifacts_on_job_id_and_file_type ON ci_job_artifacts USING btree (job_id, file_type);
-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_ci_job_artifacts_on_project_id ON ci_job_artifacts USING btree (project_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]));
@@ -20064,6 +20427,8 @@ CREATE INDEX index_ci_pipelines_on_project_id_and_source ON ci_pipelines USING b
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_pipelines_on_project_id_and_status_and_created_at ON ci_pipelines USING btree (project_id, status, created_at);
+
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_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);
@@ -20130,6 +20495,10 @@ CREATE INDEX index_ci_subscriptions_projects_on_upstream_project_id ON ci_subscr
CREATE UNIQUE INDEX index_ci_subscriptions_projects_unique_subscription ON ci_subscriptions_projects USING btree (downstream_project_id, upstream_project_id);
+CREATE INDEX index_ci_test_case_failures_on_build_id ON ci_test_case_failures USING btree (build_id);
+
+CREATE UNIQUE INDEX index_ci_test_cases_on_project_id_and_key_hash ON ci_test_cases USING btree (project_id, key_hash);
+
CREATE INDEX index_ci_trigger_requests_on_commit_id ON ci_trigger_requests USING btree (commit_id);
CREATE INDEX index_ci_trigger_requests_on_trigger_id_and_id ON ci_trigger_requests USING btree (trigger_id, id DESC);
@@ -20216,12 +20585,18 @@ CREATE INDEX index_container_expiration_policies_on_next_run_at_and_enabled ON c
CREATE INDEX index_container_repositories_on_project_id ON container_repositories USING btree (project_id);
+CREATE INDEX index_container_repositories_on_project_id_and_id ON container_repositories USING btree (project_id, id);
+
CREATE UNIQUE INDEX index_container_repositories_on_project_id_and_name ON container_repositories USING btree (project_id, name);
CREATE INDEX index_container_repository_on_name_trigram ON container_repositories USING gin (name gin_trgm_ops);
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_csv_issue_imports_on_project_id ON csv_issue_imports USING btree (project_id);
+
+CREATE INDEX index_csv_issue_imports_on_user_id ON csv_issue_imports USING btree (user_id);
+
CREATE UNIQUE INDEX index_custom_emoji_on_namespace_id_and_name ON custom_emoji USING btree (namespace_id, name);
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);
@@ -20236,7 +20611,7 @@ CREATE INDEX index_dast_site_tokens_on_project_id ON dast_site_tokens USING btre
CREATE INDEX index_dast_site_validations_on_dast_site_token_id ON dast_site_validations USING btree (dast_site_token_id);
-CREATE INDEX index_dast_site_validations_on_url_base ON dast_site_validations USING btree (url_base);
+CREATE INDEX index_dast_site_validations_on_url_base_and_state ON dast_site_validations USING btree (url_base, state);
CREATE INDEX index_dast_sites_on_dast_site_validation_id ON dast_sites USING btree (dast_site_validation_id);
@@ -20302,6 +20677,8 @@ CREATE INDEX index_description_versions_on_merge_request_id ON description_versi
CREATE INDEX index_design_management_designs_issue_id_relative_position_id ON design_management_designs USING btree (issue_id, relative_position, id);
+CREATE UNIQUE INDEX index_design_management_designs_on_iid_and_project_id ON design_management_designs USING btree (project_id, iid);
+
CREATE UNIQUE INDEX index_design_management_designs_on_issue_id_and_filename ON design_management_designs USING btree (issue_id, filename);
CREATE INDEX index_design_management_designs_on_project_id ON design_management_designs USING btree (project_id);
@@ -20384,6 +20761,8 @@ CREATE INDEX index_epics_on_group_id ON epics USING btree (group_id);
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 UNIQUE INDEX index_epics_on_group_id_and_iid ON epics USING btree (group_id, iid);
+
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_epics_on_iid ON epics USING btree (iid);
@@ -20628,8 +21007,6 @@ CREATE UNIQUE INDEX index_issuable_severities_on_issue_id ON issuable_severities
CREATE UNIQUE INDEX index_issuable_slas_on_issue_id ON issuable_slas USING btree (issue_id);
-CREATE UNIQUE INDEX index_issue_assignees_on_issue_id_and_user_id ON issue_assignees USING btree (issue_id, user_id);
-
CREATE INDEX index_issue_assignees_on_user_id ON issue_assignees USING btree (user_id);
CREATE UNIQUE INDEX index_issue_email_participants_on_issue_id_and_email ON issue_email_participants USING btree (issue_id, email);
@@ -20670,6 +21047,10 @@ CREATE INDEX index_issues_on_milestone_id ON issues USING btree (milestone_id);
CREATE INDEX index_issues_on_moved_to_id ON issues USING btree (moved_to_id) WHERE (moved_to_id IS NOT NULL);
+CREATE INDEX index_issues_on_project_id_and_closed_at ON issues USING btree (project_id, closed_at);
+
+CREATE INDEX index_issues_on_project_id_and_created_at_issue_type_incident ON issues USING btree (project_id, created_at) WHERE (issue_type = 1);
+
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 UNIQUE INDEX index_issues_on_project_id_and_iid ON issues USING btree (project_id, iid);
@@ -20684,8 +21065,6 @@ CREATE INDEX index_issues_on_updated_at ON issues USING btree (updated_at);
CREATE INDEX index_issues_on_updated_by_id ON issues USING btree (updated_by_id) WHERE (updated_by_id IS NOT NULL);
-CREATE INDEX index_issues_project_id_issue_type_incident ON issues USING btree (project_id) WHERE (issue_type = 1);
-
CREATE UNIQUE INDEX index_jira_connect_installations_on_client_key ON jira_connect_installations USING btree (client_key);
CREATE INDEX index_jira_connect_subscriptions_on_namespace_id ON jira_connect_subscriptions USING btree (namespace_id);
@@ -20786,14 +21165,12 @@ CREATE INDEX index_merge_request_assignees_on_user_id ON merge_request_assignees
CREATE INDEX index_merge_request_blocks_on_blocked_merge_request_id ON merge_request_blocks USING btree (blocked_merge_request_id);
-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 UNIQUE INDEX index_merge_request_cleanup_schedules_on_merge_request_id ON merge_request_cleanup_schedules USING btree (merge_request_id);
CREATE INDEX index_merge_request_diff_commits_on_sha ON merge_request_diff_commits USING btree (sha);
CREATE INDEX index_merge_request_diff_details_on_merge_request_diff_id ON merge_request_diff_details USING btree (merge_request_diff_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 INDEX index_merge_request_diffs_by_id_partial ON merge_request_diffs USING btree (id) WHERE ((files_count > 0) AND ((NOT stored_externally) OR (stored_externally IS NULL)));
CREATE INDEX index_merge_request_diffs_on_external_diff_store ON merge_request_diffs USING btree (external_diff_store);
@@ -20816,8 +21193,6 @@ CREATE INDEX index_merge_request_metrics_on_pipeline_id ON merge_request_metrics
CREATE INDEX index_merge_request_metrics_on_target_project_id ON merge_request_metrics USING btree (target_project_id);
-CREATE INDEX index_merge_request_metrics_on_target_project_id_merged_at ON merge_request_metrics USING btree (target_project_id, merged_at);
-
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 INDEX index_merge_request_reviewers_on_user_id ON merge_request_reviewers USING btree (user_id);
@@ -20858,8 +21233,12 @@ CREATE UNIQUE INDEX index_merge_requests_on_target_project_id_and_iid ON merge_r
CREATE INDEX index_merge_requests_on_target_project_id_and_iid_and_state_id ON merge_requests USING btree (target_project_id, iid, state_id);
+CREATE INDEX index_merge_requests_on_target_project_id_and_iid_jira_title ON merge_requests USING btree (target_project_id, iid) WHERE ((title)::text ~ '[A-Z][A-Z_0-9]+-\d+'::text);
+
CREATE INDEX index_merge_requests_on_target_project_id_and_target_branch ON merge_requests USING btree (target_project_id, target_branch) WHERE ((state_id = 1) AND (merge_when_pipeline_succeeds = true));
+CREATE INDEX index_merge_requests_on_target_project_id_iid_jira_description ON merge_requests USING btree (target_project_id, iid) WHERE (description ~ '[A-Z][A-Z_0-9]+-\d+'::text);
+
CREATE INDEX index_merge_requests_on_title ON merge_requests USING btree (title);
CREATE INDEX index_merge_requests_on_title_trigram ON merge_requests USING gin (title gin_trgm_ops);
@@ -20896,14 +21275,16 @@ CREATE INDEX index_milestones_on_title ON milestones USING btree (title);
CREATE INDEX index_milestones_on_title_trigram ON milestones USING gin (title gin_trgm_ops);
-CREATE UNIQUE INDEX index_miletone_releases_on_milestone_and_release ON milestone_releases USING btree (milestone_id, release_id);
-
CREATE INDEX index_mirror_data_on_next_execution_and_retry_count ON project_mirror_data USING btree (next_execution_timestamp, retry_count);
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_mr_cleanup_schedules_timestamps ON merge_request_cleanup_schedules USING btree (scheduled_at) WHERE (completed_at IS NULL);
+
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_mr_metrics_on_target_project_id_merged_at_nulls_last ON merge_request_metrics USING btree (target_project_id, merged_at DESC NULLS LAST, id DESC);
+
CREATE UNIQUE INDEX index_namespace_aggregation_schedules_on_namespace_id ON namespace_aggregation_schedules USING btree (namespace_id);
CREATE UNIQUE INDEX index_namespace_root_storage_statistics_on_namespace_id ON namespace_root_storage_statistics USING btree (namespace_id);
@@ -20974,6 +21355,8 @@ CREATE INDEX index_notification_settings_on_user_id ON notification_settings USI
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_oauth_access_grants_on_resource_owner_id ON oauth_access_grants USING btree (resource_owner_id, application_id, created_at);
+
CREATE UNIQUE INDEX index_oauth_access_grants_on_token ON oauth_access_grants USING btree (token);
CREATE INDEX index_oauth_access_tokens_on_application_id ON oauth_access_tokens USING btree (application_id);
@@ -21000,6 +21383,24 @@ CREATE UNIQUE INDEX index_on_instance_statistics_recorded_at_and_identifier ON a
CREATE INDEX index_on_label_links_all_columns ON label_links USING btree (target_id, label_id, target_type);
+CREATE INDEX index_on_namespaces_lower_name ON namespaces USING btree (lower((name)::text));
+
+CREATE INDEX index_on_namespaces_lower_path ON namespaces USING btree (lower((path)::text));
+
+CREATE INDEX index_on_projects_lower_path ON projects USING btree (lower((path)::text));
+
+CREATE INDEX index_on_routes_lower_path ON routes USING btree (lower((path)::text));
+
+CREATE UNIQUE INDEX index_on_segment_selections_group_id_segment_id ON analytics_devops_adoption_segment_selections USING btree (group_id, segment_id);
+
+CREATE UNIQUE INDEX index_on_segment_selections_project_id_segment_id ON analytics_devops_adoption_segment_selections USING btree (project_id, segment_id);
+
+CREATE INDEX index_on_segment_selections_segment_id ON analytics_devops_adoption_segment_selections USING btree (segment_id);
+
+CREATE INDEX index_on_users_lower_email ON users USING btree (lower((email)::text));
+
+CREATE INDEX index_on_users_lower_username ON users USING btree (lower((username)::text));
+
CREATE INDEX index_on_users_name_lower ON users USING btree (lower((name)::text));
CREATE INDEX index_open_project_tracker_data_on_service_id ON open_project_tracker_data USING btree (service_id);
@@ -21024,8 +21425,6 @@ CREATE UNIQUE INDEX index_ops_feature_flags_issues_on_feature_flag_id_and_issue_
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 UNIQUE INDEX index_packages_build_infos_on_package_id ON packages_build_infos USING btree (package_id);
-
CREATE INDEX index_packages_build_infos_on_pipeline_id ON packages_build_infos USING btree (pipeline_id);
CREATE UNIQUE INDEX index_packages_composer_metadata_on_package_id_and_target_sha ON packages_composer_metadata USING btree (package_id, target_sha);
@@ -21046,6 +21445,10 @@ CREATE INDEX index_packages_nuget_dl_metadata_on_dependency_link_id ON packages_
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_packages_package_file_build_infos_on_package_file_id ON packages_package_file_build_infos USING btree (package_file_id);
+
+CREATE INDEX index_packages_package_file_build_infos_on_pipeline_id ON packages_package_file_build_infos USING btree (pipeline_id);
+
CREATE INDEX index_packages_package_files_on_file_store ON packages_package_files USING btree (file_store);
CREATE INDEX index_packages_package_files_on_package_id_and_file_name ON packages_package_files USING btree (package_id, file_name);
@@ -21140,8 +21543,6 @@ CREATE INDEX index_project_aliases_on_project_id ON project_aliases USING btree
CREATE INDEX index_project_authorizations_on_project_id ON project_authorizations USING btree (project_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 UNIQUE INDEX index_project_auto_devops_on_project_id ON project_auto_devops USING btree (project_id);
CREATE UNIQUE INDEX index_project_ci_cd_settings_on_project_id ON project_ci_cd_settings USING btree (project_id);
@@ -21194,8 +21595,6 @@ CREATE INDEX index_project_pages_metadata_on_artifacts_archive_id ON project_pag
CREATE INDEX index_project_pages_metadata_on_pages_deployment_id ON project_pages_metadata USING btree (pages_deployment_id);
-CREATE UNIQUE INDEX index_project_pages_metadata_on_project_id ON project_pages_metadata USING btree (project_id);
-
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 UNIQUE INDEX index_project_repositories_on_disk_path ON project_repositories USING btree (disk_path);
@@ -21208,6 +21607,8 @@ CREATE UNIQUE INDEX index_project_repository_states_on_project_id ON project_rep
CREATE INDEX index_project_repository_storage_moves_on_project_id ON project_repository_storage_moves USING btree (project_id);
+CREATE INDEX index_project_settings_on_project_id_partially ON project_settings USING btree (project_id) WHERE (has_vulnerabilities IS TRUE);
+
CREATE UNIQUE INDEX index_project_settings_on_push_rule_id ON project_settings USING btree (push_rule_id);
CREATE INDEX index_project_statistics_on_namespace_id ON project_statistics USING btree (namespace_id);
@@ -21368,8 +21769,6 @@ CREATE INDEX index_protected_tags_on_project_id ON protected_tags USING btree (p
CREATE UNIQUE INDEX index_protected_tags_on_project_id_and_name ON protected_tags USING btree (project_id, name);
-CREATE UNIQUE INDEX index_push_event_payloads_on_event_id ON push_event_payloads USING btree (event_id);
-
CREATE INDEX index_push_rules_on_is_sample ON push_rules USING btree (is_sample) WHERE is_sample;
CREATE INDEX index_push_rules_on_project_id ON push_rules USING btree (project_id);
@@ -21394,8 +21793,6 @@ CREATE INDEX index_remote_mirrors_on_last_successful_update_at ON remote_mirrors
CREATE INDEX index_remote_mirrors_on_project_id ON remote_mirrors USING btree (project_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_required_code_owners_sections_on_protected_branch_id ON required_code_owners_sections USING btree (protected_branch_id);
CREATE INDEX index_requirements_management_test_reports_on_author_id ON requirements_management_test_reports USING btree (author_id);
@@ -21472,6 +21869,8 @@ CREATE INDEX index_reviews_on_merge_request_id ON reviews USING btree (merge_req
CREATE INDEX index_reviews_on_project_id ON reviews USING btree (project_id);
+CREATE INDEX index_route_on_name_trigram ON routes USING gin (name gin_trgm_ops);
+
CREATE UNIQUE INDEX index_routes_on_path ON routes USING btree (path);
CREATE INDEX index_routes_on_path_text_pattern_ops ON routes USING btree (path varchar_pattern_ops);
@@ -21502,6 +21901,8 @@ CREATE INDEX index_security_findings_on_project_fingerprint ON security_findings
CREATE INDEX index_security_findings_on_scan_id_and_deduplicated ON security_findings USING btree (scan_id, deduplicated);
+CREATE UNIQUE INDEX index_security_findings_on_scan_id_and_position ON security_findings USING btree (scan_id, "position");
+
CREATE INDEX index_security_findings_on_scanner_id ON security_findings USING btree (scanner_id);
CREATE INDEX index_security_findings_on_severity ON security_findings USING btree (severity);
@@ -21536,8 +21937,6 @@ CREATE UNIQUE INDEX index_services_on_type_and_template_partial ON services USIN
CREATE INDEX index_services_on_type_id_when_active_and_project_id_not_null ON services USING btree (type, id) WHERE ((active = true) AND (project_id IS NOT NULL));
-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 UNIQUE INDEX index_services_on_unique_group_id_and_type ON services USING btree (group_id, type);
CREATE UNIQUE INDEX index_shards_on_name ON shards USING btree (name);
@@ -21554,6 +21953,8 @@ CREATE UNIQUE INDEX index_snippet_repositories_on_disk_path ON snippet_repositor
CREATE INDEX index_snippet_repositories_on_shard_id ON snippet_repositories USING btree (shard_id);
+CREATE INDEX index_snippet_repository_storage_moves_on_snippet_id ON snippet_repository_storage_moves USING btree (snippet_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 INDEX index_snippets_on_author_id ON snippets USING btree (author_id);
@@ -21632,6 +22033,8 @@ CREATE INDEX index_term_agreements_on_term_id ON term_agreements USING btree (te
CREATE INDEX index_term_agreements_on_user_id ON term_agreements USING btree (user_id);
+CREATE INDEX index_terraform_state_versions_on_ci_build_id ON terraform_state_versions USING btree (ci_build_id);
+
CREATE INDEX index_terraform_state_versions_on_created_by_user_id ON terraform_state_versions USING btree (created_by_user_id);
CREATE UNIQUE INDEX index_terraform_state_versions_on_state_id_and_version ON terraform_state_versions USING btree (terraform_state_id, version);
@@ -21644,6 +22047,8 @@ CREATE UNIQUE INDEX index_terraform_states_on_project_id_and_name ON terraform_s
CREATE UNIQUE INDEX index_terraform_states_on_uuid ON terraform_states USING btree (uuid);
+CREATE UNIQUE INDEX index_test_case_failures_unique_columns ON ci_test_case_failures USING btree (test_case_id, failed_at DESC, build_id);
+
CREATE INDEX index_timelogs_on_issue_id ON timelogs USING btree (issue_id);
CREATE INDEX index_timelogs_on_merge_request_id ON timelogs USING btree (merge_request_id);
@@ -21708,8 +22113,6 @@ CREATE UNIQUE INDEX index_user_details_on_user_id ON user_details USING btree (u
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 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_user_interacted_projects_on_user_id ON user_interacted_projects USING btree (user_id);
CREATE INDEX index_user_preferences_on_gitpod_enabled ON user_preferences USING btree (gitpod_enabled);
@@ -21838,6 +22241,8 @@ CREATE INDEX index_vulnerability_occurrences_for_issue_links_migration ON vulner
CREATE INDEX index_vulnerability_occurrences_on_primary_identifier_id ON vulnerability_occurrences USING btree (primary_identifier_id);
+CREATE INDEX index_vulnerability_occurrences_on_project_fingerprint ON vulnerability_occurrences USING btree (project_fingerprint);
+
CREATE INDEX index_vulnerability_occurrences_on_scanner_id ON vulnerability_occurrences USING btree (scanner_id);
CREATE UNIQUE INDEX index_vulnerability_occurrences_on_unique_keys ON vulnerability_occurrences USING btree (project_id, primary_identifier_id, location_fingerprint, scanner_id);
@@ -21904,10 +22309,6 @@ CREATE INDEX issue_id_issues_prometheus_alert_events_index ON issues_prometheus_
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 issue_id_prometheus_alert_event_id_index ON issues_prometheus_alert_events USING btree (issue_id, prometheus_alert_event_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 UNIQUE INDEX issue_user_mentions_on_issue_id_and_note_id_index ON issue_user_mentions USING btree (issue_id, note_id);
CREATE UNIQUE INDEX issue_user_mentions_on_issue_id_index ON issue_user_mentions USING btree (issue_id) WHERE (note_id IS NULL);
@@ -21920,6 +22321,8 @@ CREATE UNIQUE INDEX merge_request_user_mentions_on_mr_id_and_note_id_index ON me
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 merge_requests_state_id_temp_index ON merge_requests USING btree (id) WHERE (state_id = ANY (ARRAY[2, 3]));
+
CREATE INDEX note_mentions_temp_index ON notes USING btree (id, noteable_type) WHERE (note ~~ '%@%'::text);
CREATE UNIQUE INDEX one_canonical_wiki_page_slug_per_metadata ON wiki_page_slugs USING btree (wiki_page_meta_id) WHERE (canonical = true);
@@ -21946,6 +22349,8 @@ CREATE UNIQUE INDEX snippet_user_mentions_on_snippet_id_index ON snippet_user_me
CREATE UNIQUE INDEX taggings_idx ON taggings USING btree (tag_id, taggable_id, taggable_type, context, tagger_id, tagger_type);
+CREATE INDEX temporary_index_vulnerabilities_on_id ON vulnerabilities USING btree (id) WHERE ((state = 2) AND ((dismissed_at IS NULL) OR (dismissed_by_id IS NULL)));
+
CREATE UNIQUE INDEX term_agreements_unique_index ON term_agreements USING btree (user_id, term_id);
CREATE INDEX terraform_state_versions_verification_checksum_partial ON terraform_state_versions USING btree (verification_checksum) WHERE (verification_checksum IS NOT NULL);
@@ -21964,8 +22369,6 @@ CREATE INDEX tmp_index_for_email_unconfirmation_migration ON emails USING btree
CREATE UNIQUE INDEX unique_merge_request_metrics_by_merge_request_id ON merge_request_metrics USING btree (merge_request_id);
-CREATE UNIQUE INDEX users_security_dashboard_projects_unique_index ON users_security_dashboard_projects USING btree (project_id, user_id);
-
CREATE UNIQUE INDEX vulnerability_feedback_unique_idx ON vulnerability_feedback USING btree (project_id, category, feedback_type, project_fingerprint);
CREATE UNIQUE INDEX vulnerability_occurrence_pipelines_on_unique_keys ON vulnerability_occurrence_pipelines USING btree (occurrence_id, pipeline_id);
@@ -22240,6 +22643,12 @@ ALTER TABLE ONLY clusters_applications_runners
ALTER TABLE ONLY design_management_designs_versions
ADD CONSTRAINT fk_03c671965c FOREIGN KEY (design_id) REFERENCES design_management_designs(id) ON DELETE CASCADE;
+ALTER TABLE ONLY terraform_state_versions
+ ADD CONSTRAINT fk_04b91e4a9f FOREIGN KEY (ci_build_id) REFERENCES ci_builds(id) ON DELETE SET NULL;
+
+ALTER TABLE ONLY ci_test_cases
+ ADD CONSTRAINT fk_0526c30ded FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issues
ADD CONSTRAINT fk_05f1e72feb FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -22423,6 +22832,9 @@ ALTER TABLE ONLY deploy_keys_projects
ALTER TABLE ONLY issue_assignees
ADD CONSTRAINT fk_5e0c8d9154 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY csv_issue_imports
+ ADD CONSTRAINT fk_5e1572387c FOREIGN KEY (user_id) REFERENCES users(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;
@@ -22750,6 +23162,9 @@ ALTER TABLE ONLY ci_sources_pipelines
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 ci_test_case_failures
+ ADD CONSTRAINT fk_d69404d827 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY lists
ADD CONSTRAINT fk_d6cf4279f7 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -22774,6 +23189,9 @@ ALTER TABLE ONLY project_group_links
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_dccd3f98fc FOREIGN KEY (assignee_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY analytics_devops_adoption_segment_selections
+ ADD CONSTRAINT fk_ded7fe0344 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issues
ADD CONSTRAINT fk_df75a7c8b8 FOREIGN KEY (promoted_to_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
@@ -22795,6 +23213,9 @@ ALTER TABLE ONLY merge_requests
ALTER TABLE ONLY issue_links
ADD CONSTRAINT fk_e71bb44f1f FOREIGN KEY (target_id) REFERENCES issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY csv_issue_imports
+ ADD CONSTRAINT fk_e71c0ae362 FOREIGN KEY (project_id) REFERENCES projects(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;
@@ -22834,6 +23255,9 @@ ALTER TABLE ONLY clusters
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_f081aa4489 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY analytics_devops_adoption_segment_selections
+ ADD CONSTRAINT fk_f1472b95f3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY boards
ADD CONSTRAINT fk_f15266b5f9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -22903,6 +23327,9 @@ ALTER TABLE ONLY ip_restrictions
ALTER TABLE ONLY terraform_state_versions
ADD CONSTRAINT fk_rails_04f176e239 FOREIGN KEY (terraform_state_id) REFERENCES terraform_states(id) ON DELETE CASCADE;
+ALTER TABLE ONLY analytics_devops_adoption_segment_selections
+ ADD CONSTRAINT fk_rails_053f00a9da FOREIGN KEY (segment_id) REFERENCES analytics_devops_adoption_segments(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_build_report_results
ADD CONSTRAINT fk_rails_056d298d48 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -23182,6 +23609,9 @@ ALTER TABLE ONLY snippet_user_mentions
ALTER TABLE ONLY clusters_applications_helm
ADD CONSTRAINT fk_rails_3e2b1c06bc FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_package_file_build_infos
+ ADD CONSTRAINT fk_rails_3e3f630188 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY epic_user_mentions
ADD CONSTRAINT fk_rails_3eaf4d88cc FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
@@ -23251,6 +23681,9 @@ ALTER TABLE ONLY ci_pipeline_artifacts
ALTER TABLE ONLY group_deletion_schedules
ADD CONSTRAINT fk_rails_4b8c694a6c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY snippet_repository_storage_moves
+ ADD CONSTRAINT fk_rails_4b950f5b94 FOREIGN KEY (snippet_id) REFERENCES snippets(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;
@@ -23563,6 +23996,9 @@ ALTER TABLE ONLY merge_request_diff_details
ALTER TABLE ONLY clusters_applications_crossplane
ADD CONSTRAINT fk_rails_87186702df FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_package_file_build_infos
+ ADD CONSTRAINT fk_rails_871ca3ae21 FOREIGN KEY (package_file_id) REFERENCES packages_package_files(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;
@@ -23632,6 +24068,9 @@ ALTER TABLE ONLY project_error_tracking_settings
ALTER TABLE ONLY list_user_preferences
ADD CONSTRAINT fk_rails_916d72cafd FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_cleanup_schedules
+ ADD CONSTRAINT fk_rails_92dd0e705c FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY board_labels
ADD CONSTRAINT fk_rails_9374a16edd FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
@@ -23764,6 +24203,9 @@ ALTER TABLE ONLY analytics_cycle_analytics_group_stages
ALTER TABLE ONLY metrics_dashboard_annotations
ADD CONSTRAINT fk_rails_aeb11a7643 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
+ALTER TABLE ONLY bulk_import_trackers
+ ADD CONSTRAINT fk_rails_aed566d3f3 FOREIGN KEY (bulk_import_entity_id) REFERENCES bulk_import_entities(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY pool_repositories
ADD CONSTRAINT fk_rails_af3f8c5d62 FOREIGN KEY (shard_id) REFERENCES shards(id) ON DELETE RESTRICT;
@@ -23914,6 +24356,9 @@ ALTER TABLE ONLY gpg_signatures
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 vulnerability_finding_links
+ ADD CONSTRAINT fk_rails_cbdfde27ce FOREIGN KEY (vulnerability_occurrence_id) REFERENCES vulnerability_occurrences(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;
@@ -24040,6 +24485,9 @@ ALTER TABLE ONLY merge_request_blocks
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 ci_test_case_failures
+ ADD CONSTRAINT fk_rails_eab6349715 FOREIGN KEY (test_case_id) REFERENCES ci_test_cases(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;
diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml
index 53690138300..494b1e42d2f 100644
--- a/doc/.vale/gitlab/Acronyms.yml
+++ b/doc/.vale/gitlab/Acronyms.yml
@@ -16,18 +16,24 @@ second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)'
exceptions:
- ANSI
- API
+ - ARM
- ARN
- ASCII
- AWS
+ - BSD
- CLI
- CNAME
- CORE
- CPU
- CSS
- CSV
+ - DAG
- DAST
+ - DHCP
- DNS
+ - DVCS
- EKS
+ - EOL
- FAQ
- FOSS
- GCP
@@ -41,6 +47,7 @@ exceptions:
- HTTP
- HTTPS
- IAM
+ - IANA
- IBM
- IDE
- IID
@@ -48,13 +55,17 @@ exceptions:
- IRC
- ISO
- JSON
+ - LAN
- LDAP
- LDAPS
- LESS
- LFS
- LRU
+ - LTS
- MIME
+ - MIT
- MVC
+ - NAT
- NFS
- NGINX
- NOTE
@@ -67,7 +78,9 @@ exceptions:
- PUT
- RAM
- REST
+ - RHEL
- RPC
+ - RPM
- RSA
- RSS
- RVM
@@ -81,6 +94,7 @@ exceptions:
- SLA
- SMTP
- SQL
+ - SSD
- SSH
- SSL
- SSO
@@ -88,6 +102,7 @@ exceptions:
- SVN
- TCP
- TIP
+ - TLD
- TLS
- TODO
- TOML
@@ -95,6 +110,7 @@ exceptions:
- URI
- URL
- USB
+ - UTC
- UUID
- VPC
- WIP
diff --git a/doc/.vale/gitlab/Admin.yml b/doc/.vale/gitlab/Admin.yml
index 27a703c30c3..6d01882138a 100644
--- a/doc/.vale/gitlab/Admin.yml
+++ b/doc/.vale/gitlab/Admin.yml
@@ -10,4 +10,4 @@ link: https://docs.gitlab.com/ee/development/documentation/styleguide.html
level: warning
ignorecase: true
swap:
- 'admin ?\w*': '(?:Admin Area|[Aa]dminist(ration|rator|er))'
+ 'admin ?\w*': '(?:Admin Area|[Aa]dminist(ration|rator|er|rative))'
diff --git a/doc/.vale/gitlab/AlertBoxCaution.yml b/doc/.vale/gitlab/AlertBoxCaution.yml
new file mode 100644
index 00000000000..49d4dc62ab5
--- /dev/null
+++ b/doc/.vale/gitlab/AlertBoxCaution.yml
@@ -0,0 +1,14 @@
+---
+# Error: gitlab.AlertBoxCaution
+#
+# Makes sure CAUTION: alert boxes follow standard formatting.
+#
+# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
+extends: substitution
+message: "CAUTION: alert boxes must be of the format 'CAUTION: **Caution:**'. 'Caution' can be replaced with 'Warning' or 'Important'."
+link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#alert-boxes
+level: warning
+nonword: true
+scope: raw
+swap:
+ 'CAUTION: *?\*\*.*\*\*': 'CAUTION: \*\*(?:Caution|Warning|Important):\*\*'
diff --git a/doc/.vale/gitlab/AlertBoxDanger.yml b/doc/.vale/gitlab/AlertBoxDanger.yml
new file mode 100644
index 00000000000..2589d34614c
--- /dev/null
+++ b/doc/.vale/gitlab/AlertBoxDanger.yml
@@ -0,0 +1,14 @@
+---
+# Error: gitlab.AlertBoxDanger
+#
+# Makes sure DANGER: alert boxes follow standard formatting.
+#
+# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
+extends: substitution
+message: "DANGER: alert boxes must be of the format 'DANGER: **Warning:**'. 'Warning' can be replaced with 'Important', 'Deprecated', or 'Required'."
+link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#alert-boxes
+level: error
+nonword: true
+scope: raw
+swap:
+ 'DANGER: *?\*\*.*\*\*': 'DANGER: \*\*(?:Warning|Important|Deprecated|Required):\*\*'
diff --git a/doc/.vale/gitlab/AlertBoxNoteTip.yml b/doc/.vale/gitlab/AlertBoxNoteTip.yml
new file mode 100644
index 00000000000..0b480794476
--- /dev/null
+++ b/doc/.vale/gitlab/AlertBoxNoteTip.yml
@@ -0,0 +1,15 @@
+---
+# Error: gitlab.AlertBoxNoteTip
+#
+# Makes sure NOTE: and TIP: alert boxes follow standard formatting.
+#
+# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
+extends: substitution
+message: "NOTE: and TIP: alert boxes must be of the format 'NOTE: **Note:**' or 'TIP: **Tip:**"
+link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#alert-boxes
+level: warning
+nonword: true
+scope: raw
+swap:
+ 'NOTE: *?\*\*.*\*\*': 'NOTE: \*\*Note:\*\*'
+ 'TIP: *?\*\*.*\*\*': 'TIP: \*\*Tip:\*\*'
diff --git a/doc/.vale/gitlab/AlertBoxStyle.yml b/doc/.vale/gitlab/AlertBoxStyle.yml
index 06743d95ea9..d15757d38fc 100644
--- a/doc/.vale/gitlab/AlertBoxStyle.yml
+++ b/doc/.vale/gitlab/AlertBoxStyle.yml
@@ -3,9 +3,7 @@
#
# 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
+# Checks for 2 formatting issues:
# - Alert boxes with the note text on the same line
# - Alert boxes using blockquote formatting, like "> **Note:**"
#
@@ -16,7 +14,5 @@ link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#alert
level: error
scope: raw
raw:
- - '((NOTE|TIP|CAUTION|DANGER): \*\*[^:]*\*\*)|'
- - '((NOTE: \*\*(NOTE|note):\*\*)|(TIP: \*\*(TIP|tip):\*\*)|(CAUTION: \*\*(CAUTION|caution):\*\*)|(DANGER: \*\*(DANGER|danger):\*\*))|'
- - '((NOTE|TIP|CAUTION|DANGER): \*\*.*\*\*.+)|'
+ - '(\n(NOTE|TIP|CAUTION|DANGER): \*\*.*\*\*.+)|'
- '((\n[> ]*(\*){1,2}(NOTE|Note|note|TIP|Tip|tip|CAUTION|Caution|caution|DANGER|Danger|danger):(\*){1,2}))'
diff --git a/doc/.vale/gitlab/CurlStringsQuoted.yml b/doc/.vale/gitlab/CurlStringsQuoted.yml
index 39ee9372947..a09c3fbfb51 100644
--- a/doc/.vale/gitlab/CurlStringsQuoted.yml
+++ b/doc/.vale/gitlab/CurlStringsQuoted.yml
@@ -1,12 +1,12 @@
---
# Warning: gitlab.CurlStringsQuoted
#
-# Ensures all codeblocks using curl quote any URL strings.
+# Ensures all code blocks using curl quote any URL strings.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
-message: 'Curl commands must wrap URLs in double quotes ("): %s'
-link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#curl-commands
+message: 'For consistency across all cURL examples, always wrap the URL in double quotes ("): %s'
+link: https://docs.gitlab.com/ee/development/documentation/restful_api_styleguide.html#curl-commands
level: warning
scope: code
raw:
diff --git a/doc/.vale/gitlab/CurrentStatus.yml b/doc/.vale/gitlab/CurrentStatus.yml
index 7368310eee8..584ac73aa17 100644
--- a/doc/.vale/gitlab/CurrentStatus.yml
+++ b/doc/.vale/gitlab/CurrentStatus.yml
@@ -5,7 +5,7 @@
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
-message: 'Avoid words like "%s" that promise future changes.'
+message: 'Avoid words like "%s" that promise future changes, because documentation is about the current state of the product.'
level: suggestion
ignorecase: true
link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#language-to-avoid
diff --git a/doc/.vale/gitlab/FutureTense.yml b/doc/.vale/gitlab/FutureTense.yml
index 4a74ee87331..bba60dc9657 100644
--- a/doc/.vale/gitlab/FutureTense.yml
+++ b/doc/.vale/gitlab/FutureTense.yml
@@ -6,7 +6,7 @@
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
-message: 'Avoid using future tense: "%s"'
+message: 'Avoid using future tense: "%s". Use present tense instead.'
ignorecase: true
level: warning
link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#language-to-avoid
diff --git a/doc/.vale/gitlab/InternalLinkExtension.yml b/doc/.vale/gitlab/InternalLinkExtension.yml
index 61a08e4a86c..9b5a3499815 100644
--- a/doc/.vale/gitlab/InternalLinkExtension.yml
+++ b/doc/.vale/gitlab/InternalLinkExtension.yml
@@ -10,4 +10,4 @@ link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#links
level: error
scope: raw
raw:
- - '\[.+\]\((https?:){0}[\w\/\.-]+(\.html).*\)'
+ - '\[.+\]\((https?:){0}[\w\/\.-]+(\.html).*?\)'
diff --git a/doc/.vale/gitlab/InternalLinkFormat.yml b/doc/.vale/gitlab/InternalLinkFormat.yml
new file mode 100644
index 00000000000..9a72778140e
--- /dev/null
+++ b/doc/.vale/gitlab/InternalLinkFormat.yml
@@ -0,0 +1,13 @@
+---
+# Error: gitlab.InternalLinkFormat
+#
+# Checks that internal link paths don't start with "./", which is not needed.
+#
+# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
+extends: existence
+message: 'Link "%s" must not start with "./".'
+link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#links-to-internal-documentation
+level: error
+scope: raw
+raw:
+ - '\[.+\]\(\.\/.+?\)'
diff --git a/doc/.vale/gitlab/RelativeLinks.yml b/doc/.vale/gitlab/RelativeLinks.yml
index 7af20d8226f..1ae73472f8a 100644
--- a/doc/.vale/gitlab/RelativeLinks.yml
+++ b/doc/.vale/gitlab/RelativeLinks.yml
@@ -5,7 +5,7 @@
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
-message: 'Link "%s" must be relative.'
+message: 'Link "%s" must be a relative link with a .md extension.'
link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#links-to-internal-documentation
level: error
scope: raw
diff --git a/doc/.vale/gitlab/Simplicity.yml b/doc/.vale/gitlab/Simplicity.yml
new file mode 100644
index 00000000000..fa7a07c3e81
--- /dev/null
+++ b/doc/.vale/gitlab/Simplicity.yml
@@ -0,0 +1,18 @@
+---
+# Suggestion: gitlab.Simplicity
+#
+# Checks for words implying ease of use, to avoid cognitive dissonance for frustrated users.
+#
+# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
+extends: existence
+message: 'Avoid words like "%s" that imply ease of use, because the user may find this action hard.'
+level: suggestion
+ignorecase: true
+link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#language-to-avoid
+tokens:
+ - easy
+ - easily
+ - handy
+ - simple
+ - simply
+ - useful
diff --git a/doc/.vale/gitlab/SubstitutionSuggestions.yml b/doc/.vale/gitlab/SubstitutionSuggestions.yml
new file mode 100644
index 00000000000..df68961b1ce
--- /dev/null
+++ b/doc/.vale/gitlab/SubstitutionSuggestions.yml
@@ -0,0 +1,17 @@
+---
+# Suggestion: gitlab.SubstitutionSuggestions
+#
+# Suggests better options for frequently misused terms at GitLab that are
+# often - but not always - incorrect.
+#
+# For a list of all options, see https://errata-ai.github.io/vale/styles/
+extends: substitution
+message: 'Consider "%s" instead of "%s".'
+link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#language
+level: suggestion
+ignorecase: true
+swap:
+ since: because
+ once that: after that
+ once the: after the
+ once you: after you
diff --git a/doc/.vale/gitlab/SubstitutionWarning.yml b/doc/.vale/gitlab/SubstitutionWarning.yml
index 68313a37e7d..ed0f8b498fe 100644
--- a/doc/.vale/gitlab/SubstitutionWarning.yml
+++ b/doc/.vale/gitlab/SubstitutionWarning.yml
@@ -18,3 +18,4 @@ swap:
filesystem: file system
info: information
repo: repository
+ utilize: use
diff --git a/doc/.vale/gitlab/Substitutions.yml b/doc/.vale/gitlab/Substitutions.yml
index 704c64f1fbd..3d1cf8057eb 100644
--- a/doc/.vale/gitlab/Substitutions.yml
+++ b/doc/.vale/gitlab/Substitutions.yml
@@ -25,5 +25,13 @@ swap:
self hosted: self-managed
self-hosted: self-managed
styleguide: style guide
+ to login: to log in
+ can login: can log in
+ to log-in: to log in
+ can log-in: can log in
+ to signin: to sign in
+ can signin: can sign in
+ to sign-in: to sign in
+ can sign-in: can sign in
x509: X.509
yaml: YAML
diff --git a/doc/.vale/gitlab/ToDo.yml b/doc/.vale/gitlab/ToDo.yml
new file mode 100644
index 00000000000..b3c5f6077b1
--- /dev/null
+++ b/doc/.vale/gitlab/ToDo.yml
@@ -0,0 +1,14 @@
+---
+# Warning: gitlab.ToDo
+#
+# You should not use "To Do", unless it refers to the UI element.
+#
+# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
+extends: substitution
+message: 'Use "to-do item" in most cases, or "Add a to do" if referring to the UI button.'
+link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#feature-names
+level: warning
+ignorecase: false
+swap:
+ '[Tt]o [Dd]o [Ii]tems?': to-do item
+ '\w* [Aa] [Tt]o [Dd]o': Add a to do
diff --git a/doc/.vale/gitlab/VersionText.yml b/doc/.vale/gitlab/VersionText.yml
index 3723170b169..e59b936ae3f 100644
--- a/doc/.vale/gitlab/VersionText.yml
+++ b/doc/.vale/gitlab/VersionText.yml
@@ -15,9 +15,9 @@
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
-message: '"%s" is not formatted correctly.'
+message: 'This introduced-in line is not formatted correctly.'
link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#text-for-documentation-requiring-version-text
level: error
scope: raw
raw:
- - '> (- ){0}\[?Introduced.+\n.+'
+ - '> (- ){0}\[?Introduced.+\n[^\n`]'
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index c0a85fc6b70..bbb5c892298 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -232,6 +232,7 @@ Laravel
LDAP
ldapsearch
Leiningen
+Lefthook
Libravatar
liveness
Lograge
@@ -347,6 +348,7 @@ proxied
proxies
proxyable
proxying
+pseudocode
pseudonymized
pseudonymizer
Puma
diff --git a/doc/.vale/vale.tmpl b/doc/.vale/vale.tmpl
new file mode 100644
index 00000000000..36dfbd6b778
--- /dev/null
+++ b/doc/.vale/vale.tmpl
@@ -0,0 +1,51 @@
+{{- /* Modify Vale's output https://docs.errata.ai/vale/cli#--output */ -}}
+
+{{- /* Keep track of our various counts */ -}}
+
+{{- $e := 0 -}}
+{{- $w := 0 -}}
+{{- $s := 0 -}}
+{{- $f := 0 -}}
+
+{{- /* Range over the linted files */ -}}
+
+{{- range .Files}}
+
+{{- $f = add1 $f -}}
+{{- $path := .Path | underline -}}
+
+{{- /* Range over the file's alerts */ -}}
+
+{{- range .Alerts -}}
+
+{{- $error := "" -}}
+{{- if eq .Severity "error" -}}
+ {{- $error = .Severity | red -}}
+ {{- $e = add1 $e -}}
+{{- else if eq .Severity "warning" -}}
+ {{- $error = .Severity | yellow -}}
+ {{- $w = add1 $w -}}
+{{- else -}}
+ {{- $error = .Severity | blue -}}
+ {{- $s = add1 $s -}}
+{{- end}}
+
+{{- /* Variables setup */ -}}
+
+{{- $path = $path -}}
+{{- $loc := printf "Line %d, position %d" .Line (index .Span 0) -}}
+{{- $check := printf "%s" .Check -}}
+{{- $message := printf "%s" .Message -}}
+{{- $link := printf "%s" .Link -}}
+
+{{- /* Output */ -}}
+
+{{ $path }}:
+ {{ $loc }} (rule {{ $check }})
+ {{ $error }}: {{ $message }}
+ More information: {{ $link }}
+
+{{end -}}
+{{end -}}
+
+{{- $e}} {{"errors" | red}}, {{$w}} {{"warnings" | yellow}}, and {{$s}} {{"suggestions" | blue}} found in {{$f}} {{$f | int | plural "file" "files"}}.
diff --git a/doc/README.md b/doc/README.md
index 09638bb4ce8..759b5dda32b 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -1,9 +1,12 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
description: 'Learn how to use and administer GitLab, the most scalable Git-based fully integrated platform for software development.'
---
-<div class="display-none">
+<div class="d-none">
<em>Visit <a href="https://docs.gitlab.com/ee/">docs.gitlab.com</a> for optimized
navigation, discoverability, and readability.</em>
</div>
@@ -20,14 +23,14 @@ Here you can access the complete documentation for GitLab, the single applicatio
No matter how you use GitLab, we have documentation for you.
-| Essential documentation | Essential documentation |
-|:-------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------|
-| [**User Documentation**](user/index.md)<br/>Discover features and concepts for GitLab users. | [**Administrator documentation**](administration/index.md)<br/>Everything GitLab self-managed administrators need to know. |
-| [**Contributing to GitLab**](#contributing-to-gitlab)<br/>At GitLab, everyone can contribute! | [**New to Git and GitLab?**](#new-to-git-and-gitlab)<br/>We have the resources to get you started. |
-| [**Build an integration with GitLab?**](#build-an-integration-with-gitlab)<br/>Consult our automation and integration documentation. | [**Coming to GitLab from another platform?**](#coming-to-gitlab-from-another-platform)<br/>Consult our handy guides. |
-| [**Install GitLab**](https://about.gitlab.com/install/)<br/>Installation options for different platforms. | [**Customers**](subscriptions/index.md)<br/>Information for new and existing customers. |
-| [**Update GitLab**](update/README.md)<br/>Update your GitLab self-managed instance to the latest version. | [**Reference Architectures**](administration/reference_architectures/index.md)<br/>GitLab's reference architectures |
-| [**GitLab Releases**](https://about.gitlab.com/releases/)<br/>What's new in GitLab. | |
+| Essential documentation | Essential documentation |
+|:------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------|
+| [**User documentation**](user/index.md)<br>Discover features and concepts for GitLab users. | [**Administrator documentation**](administration/index.md)<br/>Everything GitLab self-managed administrators need to know. |
+| [**Contributing to GitLab**](#contributing-to-gitlab)<br/>At GitLab, everyone can contribute! | [**New to Git and GitLab?**](#new-to-git-and-gitlab)<br/>We have the resources to get you started. |
+| [**Build an integration with GitLab**](#build-an-integration-with-gitlab)<br/>Consult our automation and integration documentation. | [**Coming to GitLab from another platform?**](#coming-to-gitlab-from-another-platform)<br/>Consult our guides. |
+| [**Install GitLab**](https://about.gitlab.com/install/)<br/>Installation options for different platforms. | [**Customers**](subscriptions/index.md)<br/>Information for new and existing customers. |
+| [**Update GitLab**](update/README.md)<br/>Update your GitLab self-managed instance to the latest version. | [**Reference Architectures**](administration/reference_architectures/index.md)<br/>GitLab's reference architectures |
+| [**GitLab releases**](https://about.gitlab.com/releases/)<br/>What's new in GitLab. | |
## Popular topics
@@ -47,7 +50,7 @@ Have a look at some of our most popular topics:
| [Omnibus GitLab SSL configuration](https://docs.gitlab.com/omnibus/settings/ssl.html) **(CORE ONLY)** | SSL settings for Omnibus GitLab self-managed instances. |
| [GitLab.com settings](user/gitlab_com/index.md) | Settings used for GitLab.com. |
-## The entire DevOps Lifecycle
+## The entire DevOps lifecycle
GitLab is the first single application for software development, security,
and operations that enables [Concurrent DevOps](https://about.gitlab.com/topics/concurrent-devops/),
@@ -89,11 +92,11 @@ GitLab provides statistics and insights into ways you can maximize the value of
The following documentation relates to the DevOps **Manage** stage:
-| Manage topics | Description |
-|:--------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [Authentication and<br/>Authorization](administration/auth/README.md) **(CORE ONLY)** | Supported authentication and authorization providers. |
-| [GitLab Value Stream Analytics](user/analytics/value_stream_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-level Analytics](user/admin_area/analytics/index.md) | Discover statistics on how many GitLab features you use and user activity. |
+| Manage topics | Description |
+|:--------------------------------------------------------------------------------------|:---------------------------------------------------------------------------|
+| [Authentication and<br/>Authorization](administration/auth/README.md) **(CORE ONLY)** | Supported authentication and authorization providers. |
+| [GitLab Value Stream Analytics](user/analytics/value_stream_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-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">
@@ -110,23 +113,23 @@ management tools.
The following documentation relates to the DevOps **Plan** stage:
-| Plan topics | Description |
-|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------|
-| [Burndown Charts](user/project/milestones/burndown_charts.md) **(STARTER)** | Watch your project's progress throughout a specific milestone. |
-| [Discussions](user/discussions/index.md) | Threads, comments, and resolvable threads in issues, commits, and merge requests. |
-| [Due Dates](user/project/issues/due_dates.md) | Keep track of issue deadlines. |
-| [Epics](user/group/epics/index.md) **(ULTIMATE)** | Tracking groups of issues that share a theme. |
+| Plan topics | Description |
+|:-----------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------|
+| [Burndown charts](user/project/milestones/burndown_charts.md) **(STARTER)** | Watch your project's progress throughout a specific milestone. |
+| [Discussions](user/discussions/index.md) | Threads, comments, and resolvable threads in issues, commits, and merge requests. |
+| [Due dates](user/project/issues/due_dates.md) | Keep track of issue deadlines. |
+| [Epics](user/group/epics/index.md) **(ULTIMATE)** | Tracking groups of issues that share a theme. |
| [Issues](user/project/issues/index.md), including [confidential issues](user/project/issues/confidential_issues.md),<br/>[issue and merge request templates](user/project/description_templates.md),<br/>and [moving issues](user/project/issues/managing_issues.md#moving-issues) | Project issues and restricting access to issues as well as creating templates for submitting new issues and merge requests. Also, moving issues between projects. |
-| [Labels](user/project/labels.md) | Categorize issues or merge requests with descriptive labels. |
-| [Milestones](user/project/milestones/index.md) | Set milestones for delivery of issues and merge requests, with optional due date. |
-| [Project Issue Board](user/project/issue_board.md) | Display issues on a Scrum or Kanban board. |
-| [Quick Actions](user/project/quick_actions.md) | Shortcuts for common actions on issues or merge requests, replacing the need to click buttons or use dropdowns in GitLab's UI. |
-| [Related Issues](user/project/issues/related_issues.md) | Create a relationship between issues. |
-| [Requirements Management](user/project/requirements/index.md) **(ULTIMATE)** | Check your products against a set of criteria. |
-| [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. |
-| [To-Do List](user/todos.md) | Keep track of work requiring attention with a chronological list displayed on a simple dashboard. |
+| [Labels](user/project/labels.md) | Categorize issues or merge requests with descriptive labels. |
+| [Milestones](user/project/milestones/index.md) | Set milestones for delivery of issues and merge requests, with optional due date. |
+| [Project Issue Board](user/project/issue_board.md) | Display issues on a Scrum or Kanban board. |
+| [Quick Actions](user/project/quick_actions.md) | Shortcuts for common actions on issues or merge requests, replacing the need to click buttons or use dropdowns in GitLab's UI. |
+| [Related issues](user/project/issues/related_issues.md) | Create a relationship between issues. |
+| [Requirements Management](user/project/requirements/index.md) **(ULTIMATE)** | Check your products against a set of criteria. |
+| [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. |
+| [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">
@@ -145,25 +148,25 @@ on projects and code.
The following documentation relates to the DevOps **Create** stage:
-#### Projects and Groups
-
-| Create topics - Projects and Groups | Description |
-|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------|
-| [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. |
-| [File locking](user/project/file_lock.md) **(PREMIUM)** | Lock files to avoid merge conflicts. |
-| [GitLab Pages](user/project/pages/index.md) | Build, test, and deploy your static website with GitLab Pages. |
-| [Groups](user/group/index.md) and [Subgroups](user/group/subgroups/index.md) | Organize your projects in groups. |
-| [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 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. |
-| [Wikis](user/project/wiki/index.md) | Enhance your repository documentation with built-in wikis. |
+#### Projects and groups
+
+| Create topics - Projects and Groups | Description |
+|:-----------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------|
+| [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. |
+| [File locking](user/project/file_lock.md) **(PREMIUM)** | Lock files to avoid merge conflicts. |
+| [GitLab Pages](user/project/pages/index.md) | Build, test, and deploy your static website with GitLab Pages. |
+| [Groups](user/group/index.md) and [Subgroups](user/group/subgroups/index.md) | Organize your projects in groups. |
+| [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 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. |
+| [Wikis](user/project/wiki/index.md) | Enhance your repository documentation with built-in wikis. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -173,20 +176,20 @@ The following documentation relates to the DevOps **Create** stage:
#### Repositories
-| Create topics - Repositories | Description |
-|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------|
-| [Branches](user/project/repository/branches/index.md) and the [default branch](user/project/repository/branches/index.md#default-branch) | How to use branches in GitLab. |
-| [Commits](user/project/repository/index.md#commits) and [signing commits](user/project/repository/gpg_signed_commits/index.md) | Work with commits, and use GPG to sign your commits. |
+| Create topics - Repositories | Description |
+|:-----------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------|
+| [Branches](user/project/repository/branches/index.md) and the [default branch](user/project/repository/branches/index.md#default-branch) | How to use branches in GitLab. |
+| [Commits](user/project/repository/index.md#commits) and [signing commits](user/project/repository/gpg_signed_commits/index.md) | Work with commits, and use GPG to sign your commits. |
| [Create branches](user/project/repository/web_editor.md#create-a-new-branch), [create](user/project/repository/web_editor.md#create-a-file)<br/>and [upload](user/project/repository/web_editor.md#upload-a-file) files, and [create directories](user/project/repository/web_editor.md#create-a-directory) | Create branches, create and upload files, and create directories within GitLab. |
-| [Delete merged branches](user/project/repository/branches/index.md#delete-merged-branches) | Bulk delete branches after their changes are merged. |
-| [File templates](user/project/repository/web_editor.md#template-dropdowns) | File templates for common files. |
-| [Files](user/project/repository/index.md#files) | Files management. |
-| [Jupyter Notebook files](user/project/repository/jupyter_notebooks/index.md#jupyter-notebook-files) | GitLab's support for `.ipynb` files. |
-| [Protected branches](user/project/protected_branches.md) | Use protected branches. |
-| [Push rules](push_rules/push_rules.md) **(STARTER)** | Additional control over pushes to your projects. |
-| [Repositories](user/project/repository/index.md) | Manage source code repositories in GitLab's user interface. |
-| [Repository mirroring](user/project/repository/repository_mirroring.md) **(STARTER)** | Push to or pull from repositories outside of GitLab |
-| [Start a merge request](user/project/repository/web_editor.md#tips) | Start merge request when committing via GitLab's user interface. |
+| [Delete merged branches](user/project/repository/branches/index.md#delete-merged-branches) | Bulk delete branches after their changes are merged. |
+| [File templates](user/project/repository/web_editor.md#template-dropdowns) | File templates for common files. |
+| [Files](user/project/repository/index.md#files) | Files management. |
+| [Jupyter Notebook files](user/project/repository/jupyter_notebooks/index.md#jupyter-notebook-files) | GitLab's support for `.ipynb` files. |
+| [Protected branches](user/project/protected_branches.md) | Use protected branches. |
+| [Push rules](push_rules/push_rules.md) **(STARTER)** | Additional control over pushes to your projects. |
+| [Repositories](user/project/repository/index.md) | Manage source code repositories in GitLab's user interface. |
+| [Repository mirroring](user/project/repository/repository_mirroring.md) **(STARTER)** | Push to or pull from repositories outside of GitLab |
+| [Start a merge request](user/project/repository/web_editor.md#tips) | Start merge request when committing via GitLab's user interface. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -194,15 +197,15 @@ The following documentation relates to the DevOps **Create** stage:
</a>
</div>
-#### Merge Requests
+#### Merge requests
-| Create topics - Merge Requests | Description |
-|:--------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------|
-| [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. |
-| [**Draft** merge requests](user/project/merge_requests/work_in_progress_merge_requests.md) | Prevent merges of draft merge requests. |
+| Create topics - Merge Requests | Description |
+|:---------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------|
+| [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. |
+| [Draft merge requests](user/project/merge_requests/work_in_progress_merge_requests.md) | Prevent merges of draft merge requests. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -212,15 +215,15 @@ The following documentation relates to the DevOps **Create** stage:
#### Integration and Automation
-| Create topics - Integration and Automation | Description |
-|:------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------|
-| [GitLab REST API](api/README.md) | Integrate with GitLab using our REST API. |
-| [GitLab GraphQL API](api/graphql/index.md) | Integrate with GitLab using our GraphQL API. |
-| [GitLab Integration](integration/README.md) | Integrate with multiple third-party services with GitLab to allow external issue trackers and external authentication. |
-| [GitLab Webhooks](user/project/integrations/webhooks.md) | Let GitLab notify you when new code has been pushed to your project. |
+| Create topics - Integration and Automation | Description |
+|:----------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------|
+| [GitLab REST API](api/README.md) | Integrate with GitLab using our REST API. |
+| [GitLab GraphQL API](api/graphql/index.md) | Integrate with GitLab using our GraphQL API. |
+| [GitLab integrations](integration/README.md) | Integrate with multiple third-party services with GitLab to allow external issue trackers and external authentication. |
+| [GitLab Webhooks](user/project/integrations/webhooks.md) | Let GitLab notify you when new code has been pushed to your project. |
| [Jira Development Panel](integration/jira_development_panel.md) | See GitLab information in the Jira Development Panel. |
-| [Integrations](user/project/integrations/overview.md) | Integrate a project with external services, such as CI and chat. |
-| [Trello Power-Up](integration/trello_power_up.md) | Integrate with GitLab's Trello Power-Up. |
+| [Integrations](user/project/integrations/overview.md) | Integrate a project with external services, such as CI and chat. |
+| [Trello Power-Up](integration/trello_power_up.md) | Integrate with GitLab's Trello Power-Up. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -240,14 +243,14 @@ scales to run your tests faster.
The following documentation relates to the DevOps **Verify** stage:
-| Verify topics | Description |
-|:----------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------|
-| [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. |
-| [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. |
+| Verify topics | Description |
+|:-----------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------|
+| [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. |
+| [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. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -257,17 +260,17 @@ The following documentation relates to the DevOps **Verify** stage:
### Package
-GitLab Packages allows organizations to utilize GitLab as a private repository
+GitLab Packages allows organizations to use GitLab as a private repository
for a variety of common package managers. Users are able to build and publish
-packages, which can be easily consumed as a dependency in downstream projects.
+packages, which can be consumed as a dependency in downstream projects.
The following documentation relates to the DevOps **Package** stage:
-| Package topics | Description |
-|:----------------------------------------------------------------|:-------------------------------------------------------|
-| [Container Registry](user/packages/container_registry/index.md) | The GitLab Container Registry enables every project in GitLab to have its own space to store [Docker](https://www.docker.com/) images. |
-| [Dependency Proxy](user/packages/dependency_proxy/index.md) **(PREMIUM)** | The GitLab Dependency Proxy sets up a local proxy for frequently used upstream images/packages. |
-| [Package Registry](user/packages/package_registry/index.md) | Use GitLab as a private or public registry for a variety of common package managers, including [NPM](user/packages/npm_registry/index.md), [Maven](user/packages/maven_repository/index.md), [PyPI](user/packages/pypi_repository/index.md), and others. You can also store generic files. |
+| Package topics | Description |
+|:----------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------|
+| [Container Registry](user/packages/container_registry/index.md) | The GitLab Container Registry enables every project in GitLab to have its own space to store [Docker](https://www.docker.com/) images. |
+| [Dependency Proxy](user/packages/dependency_proxy/index.md) | The GitLab Dependency Proxy sets up a local proxy for frequently used upstream images/packages. |
+| [Package Registry](user/packages/package_registry/index.md) | Use GitLab as a private or public registry for a variety of common package managers, including [NPM](user/packages/npm_registry/index.md), [Maven](user/packages/maven_repository/index.md), [PyPI](user/packages/pypi_repository/index.md), and others. You can also store generic files. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -285,19 +288,19 @@ remediation processes when needed.
The following documentation relates to the DevOps **Secure** stage:
-| Secure topics | Description |
-|:------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------|
-| [Compliance Dashboard](user/compliance/compliance_dashboard/index.md) **(ULTIMATE)** | View the most recent Merge Request activity in a group. |
-| [Container Scanning](user/application_security/container_scanning/index.md) **(ULTIMATE)** | Use Clair to scan Docker images for known vulnerabilities. |
-| [Dependency List](user/application_security/dependency_list/index.md) **(ULTIMATE)** | View your project's dependencies and their known vulnerabilities. |
-| [Dependency Scanning](user/application_security/dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. |
-| [Dynamic Application Security Testing (DAST)](user/application_security/dast/index.md) **(ULTIMATE)** | Analyze running web applications for known vulnerabilities. |
-| [Group Security Dashboard](user/application_security/security_dashboard/index.md#group-security-dashboard) **(ULTIMATE)** | View vulnerabilities in all the projects in a group and its subgroups. |
-| [Instance Security Center](user/application_security/security_dashboard/index.md#instance-security-center) **(ULTIMATE)** | View vulnerabilities in all the projects you're interested in. |
-| [License Compliance](user/compliance/license_compliance/index.md) **(ULTIMATE)** | Search your project's dependencies for their licenses. |
-| [Pipeline Security](user/application_security/security_dashboard/index.md#pipeline-security) **(ULTIMATE)** | View the security reports for your project's pipelines. |
-| [Project Security Dashboard](user/application_security/security_dashboard/index.md#project-security-dashboard) **(ULTIMATE)** | View the latest security reports for your project. |
-| [Static Application Security Testing (SAST)](user/application_security/sast/index.md) **(ULTIMATE)** | Analyze source code for known vulnerabilities. |
+| Secure topics | Description |
+|:------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------|
+| [Compliance Dashboard](user/compliance/compliance_dashboard/index.md) **(ULTIMATE)** | View the most recent Merge Request activity in a group. |
+| [Container Scanning](user/application_security/container_scanning/index.md) **(ULTIMATE)** | Use Clair to scan Docker images for known vulnerabilities. |
+| [Dependency List](user/application_security/dependency_list/index.md) **(ULTIMATE)** | View your project's dependencies and their known vulnerabilities. |
+| [Dependency Scanning](user/application_security/dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. |
+| [Dynamic Application Security Testing (DAST)](user/application_security/dast/index.md) **(ULTIMATE)** | Analyze running web applications for known vulnerabilities. |
+| [Group Security Dashboard](user/application_security/security_dashboard/index.md#group-security-dashboard) **(ULTIMATE)** | View vulnerabilities in all the projects in a group and its subgroups. |
+| [Instance Security Center](user/application_security/security_dashboard/index.md#instance-security-center) **(ULTIMATE)** | View vulnerabilities in all the projects you're interested in. |
+| [License Compliance](user/compliance/license_compliance/index.md) **(ULTIMATE)** | Search your project's dependencies for their licenses. |
+| [Pipeline Security](user/application_security/security_dashboard/index.md#pipeline-security) **(ULTIMATE)** | View the security reports for your project's pipelines. |
+| [Project Security Dashboard](user/application_security/security_dashboard/index.md#project-security-dashboard) **(ULTIMATE)** | View the latest security reports for your project. |
+| [Static Application Security Testing (SAST)](user/application_security/sast/index.md) **(ULTIMATE)** | Analyze source code for known vulnerabilities. |
### Release
@@ -307,17 +310,17 @@ confidently and securely with GitLab’s built-in Continuous Delivery and Deploy
The following documentation relates to the DevOps **Release** stage:
-| Release topics | Description |
-|:------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------|
-| [Auto Deploy](topics/autodevops/stages.md#auto-deploy) | Configure GitLab for the deployment of your application. |
-| [Canary Deployments](user/project/canary_deployments.md) **(PREMIUM)** | Employ a popular CI strategy where a small portion of the fleet is updated to the new version first. |
-| [Deploy Boards](user/project/deploy_boards.md) **(PREMIUM)** | View the current health and status of each CI environment running on Kubernetes, displaying the status of the pods in the deployment. |
-| [Environments and deployments](ci/environments/index.md) | With environments, you can control the continuous deployment of your software within GitLab. |
-| [Environment-specific variables](ci/variables/README.md#limit-the-environment-scopes-of-environment-variables) | Limit the scope of variables to specific environments. |
-| [GitLab CI/CD](ci/README.md) | Explore the features and capabilities of Continuous Deployment and Delivery with GitLab. |
-| [GitLab Pages](user/project/pages/index.md) | Build, test, and deploy a static site directly from GitLab. |
-| [Protected Runners](ci/runners/README.md#prevent-runners-from-revealing-sensitive-information) | Select Runners to only pick jobs for protected branches and tags. |
-| [Scheduled Pipelines](ci/pipelines/schedules.md) | Execute pipelines on a schedule. |
+| Release topics | Description |
+|:---------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------|
+| [Auto Deploy](topics/autodevops/stages.md#auto-deploy) | Configure GitLab for the deployment of your application. |
+| [Canary Deployments](user/project/canary_deployments.md) **(PREMIUM)** | Employ a popular CI strategy where a small portion of the fleet is updated to the new version first. |
+| [Deploy Boards](user/project/deploy_boards.md) **(PREMIUM)** | View the current health and status of each CI environment running on Kubernetes, displaying the status of the pods in the deployment. |
+| [Environments and deployments](ci/environments/index.md) | With environments, you can control the continuous deployment of your software within GitLab. |
+| [Environment-specific variables](ci/variables/README.md#limit-the-environment-scopes-of-environment-variables) | Limit the scope of variables to specific environments. |
+| [GitLab CI/CD](ci/README.md) | Explore the features and capabilities of Continuous Deployment and Delivery with GitLab. |
+| [GitLab Pages](user/project/pages/index.md) | Build, test, and deploy a static site directly from GitLab. |
+| [Protected runners](ci/runners/README.md#prevent-runners-from-revealing-sensitive-information) | Select Runners to only pick jobs for protected branches and tags. |
+| [Schedule pipelines](ci/pipelines/schedules.md) | Execute pipelines on a schedule. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -333,19 +336,19 @@ configuration. Then customize everything from buildpacks to CI/CD.
The following documentation relates to the DevOps **Configure** stage:
-| Configure topics | Description |
-|:-----------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------|
-| [Auto DevOps](topics/autodevops/index.md) | Automatically employ a complete DevOps lifecycle. |
-| [Create Kubernetes clusters](user/project/clusters/add_remove_clusters.md#create-new-cluster) | Use Kubernetes and GitLab. |
-| [Executable Runbooks](user/project/clusters/runbooks/index.md) | Documented procedures that explain how to carry out particular processes. |
-| [GitLab ChatOps](ci/chatops/README.md) | Interact with CI/CD jobs through chat services. |
-| [Installing Applications](user/project/clusters/index.md#installing-applications) | Install Helm charts such as Ingress and Prometheus on Kubernetes. |
-| [Mattermost slash commands](user/project/integrations/mattermost_slash_commands.md) | Enable and use slash commands from within Mattermost. |
-| [Multiple Kubernetes Clusters](user/project/clusters/index.md#multiple-kubernetes-clusters) | Associate more than one Kubernetes clusters to your project. |
-| [Protected variables](ci/variables/README.md#protect-a-custom-variable) | Restrict variables to protected branches and tags. |
-| [Serverless](user/project/clusters/serverless/index.md) | Run serverless workloads on Kubernetes. |
-| [Slack slash commands](user/project/integrations/slack_slash_commands.md) | Enable and use slash commands from within Slack. |
-| [Manage your infrastructure with Terraform](user/infrastructure/index.md) | Manage your infrastructure as you run your CI/CD pipeline. |
+| Configure topics | Description |
+|:----------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------|
+| [Auto DevOps](topics/autodevops/index.md) | Automatically employ a complete DevOps lifecycle. |
+| [Create Kubernetes clusters](user/project/clusters/add_remove_clusters.md#create-new-cluster) | Use Kubernetes and GitLab. |
+| [Executable Runbooks](user/project/clusters/runbooks/index.md) | Documented procedures that explain how to carry out particular processes. |
+| [GitLab ChatOps](ci/chatops/README.md) | Interact with CI/CD jobs through chat services. |
+| [Installing applications](user/project/clusters/index.md#installing-applications) | Install Helm charts such as Ingress and Prometheus on Kubernetes. |
+| [Mattermost slash commands](user/project/integrations/mattermost_slash_commands.md) | Enable and use slash commands from within Mattermost. |
+| [Multiple Kubernetes clusters](user/project/clusters/index.md#multiple-kubernetes-clusters) | Associate more than one Kubernetes clusters to your project. |
+| [Protected variables](ci/variables/README.md#protect-a-custom-variable) | Restrict variables to protected branches and tags. |
+| [Serverless](user/project/clusters/serverless/index.md) | Run serverless workloads on Kubernetes. |
+| [Slack slash commands](user/project/integrations/slack_slash_commands.md) | Enable and use slash commands from within Slack. |
+| [Manage your infrastructure with Terraform](user/infrastructure/index.md) | Manage your infrastructure as you run your CI/CD pipeline. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -364,12 +367,12 @@ The following documentation relates to the DevOps **Monitor** stage:
| Monitor topics | Description |
|:------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------|
-| [GitLab Performance Monitoring](administration/monitoring/performance/index.md) **(CORE ONLY)** | Use Prometheus and Grafana to monitor the performance of your GitLab instance. |
+| [GitLab Performance Monitoring](administration/monitoring/performance/index.md) **(CORE ONLY)** | Use Prometheus and Grafana to monitor the performance of your GitLab instance. |
| [GitLab Prometheus](administration/monitoring/prometheus/index.md) **(CORE ONLY)** | Configure the bundled Prometheus to collect various metrics from your GitLab instance. |
| [Health check](user/admin_area/monitoring/health_check.md) | GitLab provides liveness and readiness probes to indicate service health and reachability to required services. |
| [Prometheus project integration](user/project/integrations/prometheus.md) | Configure the Prometheus integration per project and monitor your CI/CD environments. |
| [Prometheus metrics](user/project/integrations/prometheus_library/index.md) | Let Prometheus collect metrics from various services, like Kubernetes, NGINX, NGINX Ingress controller, HAProxy, and Amazon Cloud Watch. |
-| [Incident management](operations/incident_management/index.md) | Use GitLab to help you better respond to incidents that may occur in your systems. |
+| [Incident management](operations/incident_management/index.md) | Use GitLab to help you better respond to incidents that may occur in your systems. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -388,11 +391,11 @@ your applications that are deployed in production.
The following documentation relates to the DevOps **Defend** stage:
-| Defend topics | Description |
-|:------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------|
-| [Web Application Firewall with ModSecurity](user/compliance/compliance_dashboard/index.md) | Filter, monitor, and block HTTP traffic to and from a web application. |
-| [Container Host Security](user/clusters/applications.md#install-falco-using-gitlab-cicd) | Detect and respond to security threats at the Kubernetes, network, and host level. |
-| [Container Network Security](user/clusters/applications.md#install-cilium-using-gitlab-cicd) | Detect and block unauthorized network traffic between pods and to/from the internet.|
+| Defend topics | Description |
+|:---------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------|
+| [Web Application Firewall with ModSecurity](user/compliance/compliance_dashboard/index.md) | Filter, monitor, and block HTTP traffic to and from a web application. |
+| [Container host security](user/clusters/applications.md#install-falco-using-gitlab-cicd) | Detect and respond to security threats at the Kubernetes, network, and host level. |
+| [Container network security](user/clusters/applications.md#install-cilium-using-gitlab-cicd) | Detect and block unauthorized network traffic between pods and to/from the internet. |
## New to Git and GitLab?
@@ -400,13 +403,13 @@ Working with new systems can be daunting.
We have the following documentation to rapidly uplift your GitLab knowledge:
-| Topic | Description |
-|:-----------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------|
-| [GitLab basics guides](gitlab-basics/README.md) | Start working on the command line and with GitLab. |
-| [GitLab workflow overview](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/) | Enhance your workflow with the best of GitLab Workflow. |
-| [Get started with GitLab CI/CD](ci/quick_start/README.md) | Quickly implement GitLab CI/CD. |
-| [Auto DevOps](topics/autodevops/index.md) | Learn more about GitLab's Auto DevOps. |
-| [GitLab Markdown](user/markdown.md) | GitLab's advanced formatting system (GitLab Flavored Markdown) |
+| Topic | Description |
+|:--------------------------------------------------------------------------------------------------|:---------------------------------------------------------------|
+| [GitLab basics guides](gitlab-basics/README.md) | Start working on the command line and with GitLab. |
+| [GitLab workflow overview](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/) | Enhance your workflow with the best of GitLab Workflow. |
+| [Get started with GitLab CI/CD](ci/quick_start/README.md) | Quickly implement GitLab CI/CD. |
+| [Auto DevOps](topics/autodevops/index.md) | Learn more about GitLab's Auto DevOps. |
+| [GitLab Markdown](user/markdown.md) | GitLab's advanced formatting system (GitLab Flavored Markdown) |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -435,11 +438,11 @@ Learn more about GitLab account management:
Learn more about using Git, and using Git with GitLab:
-| Topic | Description |
-|:----------------------------------------------------------------------------|:---------------------------------------------------------------------------|
-| [Git](topics/git/index.md) | Getting started with Git, branching strategies, Git LFS, and advanced use. |
+| Topic | Description |
+|:-----------------------------------------------------------------------------|:---------------------------------------------------------------------------|
+| [Git](topics/git/index.md) | Getting started with Git, branching strategies, Git LFS, and advanced use. |
| [Git cheat sheet](https://about.gitlab.com/images/press/git-cheat-sheet.pdf) | Download a PDF describing the most used Git operations. |
-| [GitLab Flow](topics/gitlab_flow.md) | Explore the best of Git with the GitLab Flow strategy. |
+| [GitLab Flow](topics/gitlab_flow.md) | Explore the best of Git with the GitLab Flow strategy. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -449,12 +452,12 @@ Learn more about using Git, and using Git with GitLab:
## Coming to GitLab from another platform
-If you are coming to GitLab from another platform, you'll find the following information useful:
+If you are coming to GitLab from another platform, the following information is useful:
-| Topic | Description |
-|:---------------------------------------------------------------|:---------------------------------------------------------------------------------------|
-| [Importing to GitLab](user/project/import/index.md) | Import your projects from GitHub, Bitbucket, GitLab.com, FogBugz, and SVN into GitLab. |
-| [Migrating from SVN](user/project/import/svn.md) | Convert a SVN repository to Git and GitLab. |
+| Topic | Description |
+|:----------------------------------------------------|:---------------------------------------------------------------------------------------|
+| [Importing to GitLab](user/project/import/index.md) | Import your projects from GitHub, Bitbucket, GitLab.com, FogBugz, and SVN into GitLab. |
+| [Migrating from SVN](user/project/import/svn.md) | Convert a SVN repository to Git and GitLab. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -466,11 +469,11 @@ If you are coming to GitLab from another platform, you'll find the following inf
There are many ways to integrate with GitLab, including:
-| Topic | Description |
-|:-----------------------------------------------------------|:------------------------------------------------|
-| [GitLab REST API](api/README.md) | Integrate with GitLab using our REST API. |
-| [GitLab GraphQL API](api/graphql/index.md) | Integrate with GitLab using our GraphQL API. |
-| [Integrations and automation](#integration-and-automation) | All GitLab integration and automation options. |
+| Topic | Description |
+|:-----------------------------------------------------------|:-----------------------------------------------|
+| [GitLab REST API](api/README.md) | Integrate with GitLab using our REST API. |
+| [GitLab GraphQL API](api/graphql/index.md) | Integrate with GitLab using our GraphQL API. |
+| [Integrations and automation](#integration-and-automation) | All GitLab integration and automation options. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index ac972e2e33e..67a3a3c1539 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -11,6 +11,8 @@ GitLab offers a way to view the changes made within the GitLab server for owners
GitLab system administrators can also take advantage of the logs located on the
file system. See [the logs system documentation](logs.md) for more details.
+You can generate an [Audit report](audit_reports.md) of audit events.
+
## Overview
**Audit Events** is a tool for GitLab owners and administrators
@@ -96,9 +98,10 @@ 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 CI/CD variable added, removed, or protected status changed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30857) in GitLab 13.4)
+- User was approved via Admin Area ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276250) in GitLab 13.6)
-Project events can also be accessed via the [Project Audit Events API](../api/audit_events.md#project-audit-events)
+Project events can also be accessed via the [Project Audit Events API](../api/audit_events.md#project-audit-events).
### Instance events **(PREMIUM ONLY)**
@@ -113,8 +116,8 @@ To view the server-wide administrator log, visit **Admin Area > Monitoring > Aud
In addition to the group and project events, the following user actions are also
recorded:
-- Failed Logins
- Sign-in events and the authentication type (such as standard, LDAP, or OmniAuth)
+- Failed sign-ins
- Added SSH key
- Added or removed email
- Changed password
@@ -127,6 +130,8 @@ recorded:
- User was blocked via Admin Area ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/251) in GitLab 12.8)
- User was blocked via API ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25872) in GitLab 12.9)
- Failed second-factor authentication attempt ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16826) in GitLab 13.5)
+- A user's personal access token was successfully created or revoked ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276921) in GitLab 13.6)
+- A failed attempt to create or revoke a user's personal access token ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276921) in GitLab 13.6)
It's possible to filter particular actions by choosing an audit data type from
the filter dropdown box. You can further filter by specific group, project, or user
@@ -134,7 +139,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)
+Instance events can also be accessed via the [Instance Audit Events API](../api/audit_events.md#instance-audit-events).
### Missing events
@@ -175,6 +180,12 @@ the steps bellow.
Feature.enable(:repository_push_audit_event)
```
+## Retention policy
+
+On GitLab.com, Audit Event records become subject to deletion after 400 days, or when your license is downgraded to a tier that does not include access to Audit Events. Data that is subject to deletion will be deleted at GitLab's discretion, possibly without additional notice.
+
+If you require a longer retention period, you should independently archive your Audit Event data, which you can retrieve through the [Audit Events API](../api/audit_events.md).
+
## Export to CSV **(PREMIUM ONLY)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1449) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
@@ -228,7 +239,7 @@ The first row contains the headers, which are listed in the following table alon
### Limitation
-The Audit Log CSV file size is limited to a maximum of `15 MB`.
+The Audit Log CSV file size is limited to a maximum of `100,000` events.
The remaining records are truncated when this limit is reached.
### Enable or disable Audit Log Export to CSV
diff --git a/doc/administration/audit_reports.md b/doc/administration/audit_reports.md
index 83fbeda26aa..9c772302375 100644
--- a/doc/administration/audit_reports.md
+++ b/doc/administration/audit_reports.md
@@ -18,12 +18,12 @@ needs.
## APIs
-- `https://docs.gitlab.com/ee/api/audit_events.html`
-- `https://docs.gitlab.com/ee/api/graphql/reference/#user`
-- `https://docs.gitlab.com/ee/api/graphql/reference/#groupmember`
-- `https://docs.gitlab.com/ee/api/graphql/reference/#projectmember`
+- [Audit events](../api/audit_events.md)
+- [GraphQL - User](../api/graphql/reference/index.md#user)
+- [GraphQL - GroupMember](../api/graphql/reference/index.md#groupmember)
+- [GraphQL - ProjectMember](../api/graphql/reference/index.md#projectmember)
## Features
-- `https://docs.gitlab.com/ee/administration/audit_events.html`
-- `https://docs.gitlab.com/ee/administration/logs.html`
+- [Audit events](audit_events.md)
+- [Log system](logs.md)
diff --git a/doc/administration/auth/crowd.md b/doc/administration/auth/crowd.md
index 254bd259344..6e3dbcb68b3 100644
--- a/doc/administration/auth/crowd.md
+++ b/doc/administration/auth/crowd.md
@@ -82,6 +82,8 @@ If you see an error message like the one below when you sign in after Crowd auth
could not authorize you from Crowd because invalid credentials
```
-Please make sure the Crowd users who need to login to GitLab are authorized to [the application](#configure-a-new-crowd-application) in the step of **Authorisation**. This could be verified by try "Authentication test" for Crowd as of 2.11.
+Ensure the Crowd users who need to sign in to GitLab are authorized to the
+[application](#configure-a-new-crowd-application) in the **Authorisation** step.
+This could be verified by trying "Authentication test" for Crowd (as of 2.11).
![Example Crowd application authorisation configuration](img/crowd_application_authorisation.png)
diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index 3df85babc94..9d88d66bf46 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -17,7 +17,7 @@ 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).
+Users added through LDAP take a [licensed seat](../../../subscriptions/self_managed/index.md#billable-users).
GitLab Enterprise Editions (EE) include enhanced integration,
including group membership syncing as well as multiple LDAP servers support.
@@ -97,7 +97,8 @@ library. `start_tls` corresponds to StartTLS, not to be confused with regular TL
Normally, if you specify `simple_tls` it will be on port 636, while `start_tls` (StartTLS)
would be on port 389. `plain` also operates on port 389. Removed values: `tls` was replaced with `start_tls` and `ssl` was replaced with `simple_tls`.
-LDAP users must have an email address set, regardless of whether it is used to sign-in.
+LDAP users must have a set email address, regardless of whether or not it's used
+to sign in.
### Example Configurations **(CORE ONLY)**
@@ -444,10 +445,10 @@ account control attribute (`userAccountControl:1.2.840.113556.1.4.803`)
has bit 2 set.
For more information, see <https://ctovswild.com/2009/09/03/bitmask-searches-in-ldap/>
-The user will be set to `ldap_blocked` state in GitLab if the above conditions
-fail. This means the user will not be able to sign-in or push/pull code.
+The user is set to an `ldap_blocked` state in GitLab if the previous conditions
+fail. This means the user won't be able to sign in or push/pull code.
-The process will also update the following user information:
+The process also updates the following user information:
- Email address.
- If `sync_ssh_keys` is set, SSH public keys.
@@ -460,16 +461,12 @@ The LDAP sync process:
### Adjusting LDAP user sync schedule **(STARTER ONLY)**
-NOTE: **Note:**
-These are cron formatted values. You can use a crontab generator to create
-these values, for example <http://www.crontabgenerator.com/>.
-
By default, GitLab runs a worker once per day at 01:30 a.m. server time to
check and update GitLab users against LDAP.
You can manually configure LDAP user sync times by setting the
following configuration values, in cron format. If needed, you can
-use a [crontab generator](http://crontabgenerator.com).
+use a [crontab generator](http://www.crontabgenerator.com).
The example below shows how to set LDAP user
sync to run once every 12 hours at the top of the hour.
diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md
index c6558bf1791..8920479949d 100644
--- a/doc/administration/auth/ldap/ldap-troubleshooting.md
+++ b/doc/administration/auth/ldap/ldap-troubleshooting.md
@@ -13,10 +13,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
#### Connection refused
-If you are getting `Connection Refused` errors when trying to connect to the
-LDAP server please double-check the LDAP `port` and `encryption` settings used by
-GitLab. Common combinations are `encryption: 'plain'` and `port: 389`, OR
-`encryption: 'simple_tls'` and `port: 636`.
+If you're getting `Connection Refused` error messages when attempting to
+connect to the LDAP server, review the LDAP `port` and `encryption` settings
+used by GitLab. Common combinations are `encryption: 'plain'` and `port: 389`,
+or `encryption: 'simple_tls'` and `port: 636`.
#### Connection times out
@@ -69,10 +69,10 @@ options = {
# :filter is optional
# 'cn' looks for all "cn"s under :base
# '*' is the search string - here, it's a wildcard
- filter: Net::Ldap::Filter.eq('cn', '*'),
+ filter: Net::LDAP::Filter.eq('cn', '*'),
# :attributes is optional
- # the attributes we want to get returned
+ # the attributes we want to get returnedk
attributes: %w(dn cn memberuid member submember uniquemember memberof)
}
adapter.ldap_search(options)
@@ -103,16 +103,16 @@ 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) in
- LDAP? The user must fall under this `base` to sign-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)?
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.
+ 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).
If the above are both okay, the next place to look for the problem is
the logs themselves while reproducing the issue.
-- Ask the user to sign-in and let it fail.
+- Ask the user to sign in and let it fail.
- [Look through the output](#gitlab-logs) for any errors or other
messages about the sign-in. You may see one of the other error messages on
this page, in which case that section can help resolve the issue.
@@ -159,7 +159,7 @@ 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,
+A user tries to sign in with the correct LDAP credentials, is denied access,
and the [production.log](../../logs.md#productionlog) shows an error that looks like this:
```plaintext
@@ -649,8 +649,7 @@ ldapsearch -D "cn=admin,dc=ldap-testing,dc=example,dc=com" \
Note that the `bind_dn`, `password`, `port`, `host`, and `base` are all
identical to what's configured in the `gitlab.rb`.
-Please see [the official
-`ldapsearch` documentation](https://linux.die.net/man/1/ldapsearch) for more.
+For more information, see the [official `ldapsearch` documentation](https://linux.die.net/man/1/ldapsearch).
### Using **AdFind** (Windows)
@@ -675,15 +674,15 @@ adfind -h ad.example.org:636 -ssl -u "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -u
### Rails console
CAUTION: **Caution:**
-Please note that it is very easy to create, read, modify, and destroy data on the
-rails console, so please be sure to run commands exactly as listed.
+It is very easy to create, read, modify, and destroy data with the rails
+console. Be sure to run commands exactly as listed.
The rails console is a valuable tool to help debug LDAP problems. It allows you to
directly interact with the application by running commands and seeing how GitLab
responds to them.
-Please refer to [this guide](../../operations/rails_console.md#starting-a-rails-console-session)
-for instructions on how to use the rails console.
+For instructions about how to use the rails console, refer to this
+[guide](../../operations/rails_console.md#starting-a-rails-console-session).
#### Enable debug output
diff --git a/doc/administration/auth/okta.md b/doc/administration/auth/okta.md
index 7a55e127733..06b50be2647 100644
--- a/doc/administration/auth/okta.md
+++ b/doc/administration/auth/okta.md
@@ -14,7 +14,9 @@ The following documentation enables Okta as a SAML provider.
## Configure the Okta application
-1. On Okta go to the admin section and choose to **Add an App**.
+The following guidance is based on this Okta article, on adding a [SAML Application with an Okta Developer account](https://support.okta.com/help/s/article/Why-can-t-I-add-a-SAML-Application-with-an-Okta-Developer-account?language=en_US):
+
+1. On Okta admin section, make sure to select Classic UI view in the top left corner. From there, choose to **Add an App**.
1. When the app screen comes up you see another button to **Create an App** and
choose SAML 2.0 on the next screen.
1. Now, very important, add a logo
diff --git a/doc/administration/auth/smartcard.md b/doc/administration/auth/smartcard.md
index a696d0499a4..d2937d36a35 100644
--- a/doc/administration/auth/smartcard.md
+++ b/doc/administration/auth/smartcard.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Manage
+group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index 44270283308..4cb2c002015 100644
--- a/doc/administration/compliance.md
+++ b/doc/administration/compliance.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Manage
+group: Compliance
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
diff --git a/doc/administration/consul.md b/doc/administration/consul.md
index 4eed020c284..491251bc842 100644
--- a/doc/administration/consul.md
+++ b/doc/administration/consul.md
@@ -17,12 +17,9 @@ a service networking solution that you can manage by using `/etc/gitlab/gitlab.r
## Configure the Consul nodes
-NOTE: **Important:**
-Before proceeding, refer to the
-[available reference architectures](reference_architectures/index.md#available-reference-architectures)
-to find out how many Consul server nodes you should have.
-
-On **each** Consul server node perform the following:
+After you review the [reference architecture](reference_architectures/index.md#available-reference-architectures)
+documentation to determine the number of Consul server nodes you should have,
+on _each_ Consul server node:
1. Follow the instructions to [install](https://about.gitlab.com/install/)
GitLab by choosing your preferred platform, but do not supply the
@@ -87,16 +84,15 @@ Consul nodes communicate using the raft protocol. If the current leader goes
offline, there needs to be a leader election. A leader node must exist to facilitate
synchronization across the cluster. If too many nodes go offline at the same time,
the cluster will lose quorum and not elect a leader due to
-[broken consensus](https://www.consul.io/docs/internals/consensus.html).
+[broken consensus](https://www.consul.io/docs/architecture/consensus).
Consult the [troubleshooting section](#troubleshooting-consul) if the cluster is not
able to recover after the upgrade. The [outage recovery](#outage-recovery) may
be of particular interest.
-NOTE: **Note:**
-GitLab uses Consul to store only transient data that is easily regenerated. If
-the bundled Consul was not used by any process other than GitLab itself, then
-[rebuilding the cluster from scratch](#recreate-from-scratch) is fine.
+GitLab uses Consul to store only easily regenerated, transient data. If the
+bundled Consul wasn't used by any process other than GitLab itself, you can
+[rebuild the cluster from scratch](#recreate-from-scratch).
## Troubleshooting Consul
diff --git a/doc/administration/database_load_balancing.md b/doc/administration/database_load_balancing.md
index e88f88a0427..2b25ee4bab8 100644
--- a/doc/administration/database_load_balancing.md
+++ b/doc/administration/database_load_balancing.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Enablement
+group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
diff --git a/doc/administration/feature_flags.md b/doc/administration/feature_flags.md
index 4129677f134..2a5260a1342 100644
--- a/doc/administration/feature_flags.md
+++ b/doc/administration/feature_flags.md
@@ -36,8 +36,8 @@ error, it's very important that you [**provide feedback**](https://gitlab.com/gi
as possible so we can improve or fix it while behind a flag. When you upgrade
GitLab to an earlier version, the feature flag status may change.
-NOTE: **Note:**
-Mind that features deployed behind feature flags may not be ready for
+CAUTION: **Caution:**
+Features deployed behind feature flags may not be ready for
production use. However, disabling features behind flags that were deployed
enabled by default may also present a risk. If they're enabled, we recommend
you leave them as-is.
diff --git a/doc/administration/geo/disaster_recovery/bring_primary_back.md b/doc/administration/geo/disaster_recovery/bring_primary_back.md
index 83081e2cef6..b73d3ba52a2 100644
--- a/doc/administration/geo/disaster_recovery/bring_primary_back.md
+++ b/doc/administration/geo/disaster_recovery/bring_primary_back.md
@@ -45,9 +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](../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.
+1. [Set up database replication](../setup/database.md). In this case, the **secondary** node
+ refers to the former **primary** node.
+ 1. If [PgBouncer](../../postgresql/pgbouncer.md) was enabled on the **current secondary** node
+ (when it was a primary node) disable it by editing `/etc/gitlab/gitlab.rb`
+ and running `sudo gitlab-ctl reconfigure`.
+ 1. You can then set up database replication on the **secondary** node.
If you have lost your original **primary** node, follow the
[setup instructions](../setup/index.md) to set up a new **secondary** node.
diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md
index 5876a8c36e6..1e9b430834c 100644
--- a/doc/administration/geo/disaster_recovery/index.md
+++ b/doc/administration/geo/disaster_recovery/index.md
@@ -133,6 +133,12 @@ Note the following when promoting a secondary:
```
1. Promote the **secondary** node to the **primary** node.
+ DANGER: **Warning:**
+ In GitLab 13.2 and 13.3, promoting a secondary node to a primary while the
+ secondary is paused fails. Do not pause replication before promoting a
+ secondary. If the node is paused, be sure to resume before promoting. This
+ issue has been fixed in GitLab 13.4 and later.
+
CAUTION: **Caution:**
If the secondary node [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs
a point-in-time recovery to the last known state.
@@ -167,8 +173,14 @@ conjunction with multiple servers, as it can only
perform changes on a **secondary** with only a single machine. Instead, you must
do this manually.
+DANGER: **Warning:**
+In GitLab 13.2 and 13.3, promoting a secondary node to a primary while the
+secondary is paused fails. Do not pause replication before promoting a
+secondary. If the node is paused, be sure to resume before promoting. This
+issue has been fixed in GitLab 13.4 and later.
+
CAUTION: **Caution:**
-If the secondary node [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs
+ If the secondary node [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs
a point-in-time recovery to the last known state.
Data that was created on the primary while the secondary was paused will be lost.
diff --git a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md
index c89b7929b13..3864445bbf4 100644
--- a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md
+++ b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md
@@ -227,6 +227,12 @@ conjunction with multiple servers, as it can only
perform changes on a **secondary** with only a single machine. Instead, you must
do this manually.
+DANGER: **Warning:**
+In GitLab 13.2 and 13.3, promoting a secondary node to a primary while the
+secondary is paused fails. Do not pause replication before promoting a
+secondary. If the node is paused, be sure to resume before promoting. This
+issue has been fixed in GitLab 13.4 and later.
+
CAUTION: **Caution:**
If the secondary node [has been paused](../../../geo/index.md#pausing-and-resuming-replication), this performs
a point-in-time recovery to the last known state.
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
index 0bfdf1d2d65..02b907ae237 100644
--- a/doc/administration/geo/index.md
+++ b/doc/administration/geo/index.md
@@ -49,7 +49,7 @@ 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.
+- An intuitive UI: **Secondary** nodes use 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
@@ -116,6 +116,7 @@ The following are required to run Geo:
- [Ubuntu](https://ubuntu.com) 16.04+
- PostgreSQL 11+ with [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
- Git 2.9+
+- Git-lfs 2.4.2+ on the user side when using LFS
- All nodes must run the same GitLab version.
Additionally, check GitLab's [minimum requirements](../../install/requirements.md),
@@ -195,6 +196,12 @@ For information on how to update your Geo nodes to the latest GitLab version, se
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35913) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
+DANGER: **Warning:**
+In GitLab 13.2 and 13.3, promoting a secondary node to a primary while the
+secondary is paused fails. Do not pause replication before promoting a
+secondary. If the node is paused, be sure to resume before promoting. This
+issue has been fixed in GitLab 13.4 and later.
+
CAUTION: **Caution:**
Pausing and resuming of replication is currently only supported for Geo installations using an
Omnibus GitLab-managed database. External databases are currently not supported.
diff --git a/doc/administration/geo/replication/configuration.md b/doc/administration/geo/replication/configuration.md
index 8c818bcfbe2..43a422c4bc3 100644
--- a/doc/administration/geo/replication/configuration.md
+++ b/doc/administration/geo/replication/configuration.md
@@ -229,19 +229,10 @@ replicating missing data from the **primary** node in a process known as **backf
Meanwhile, the **primary** node will start to notify each **secondary** node of any changes, so
that the **secondary** node can act on those notifications immediately.
-Make sure the **secondary** node is running and accessible.
-You can login to the **secondary** node with the same credentials as used for the **primary** node.
+Be sure the _secondary_ node is running and accessible. You can sign in to the
+_secondary_ node with the same credentials as were used with the _primary_ node.
-### Step 4. Enabling Hashed Storage
-
-Using Hashed Storage significantly improves Geo replication. Project and group
-renames no longer require synchronization between nodes.
-
-1. Visit the **primary** node's **Admin Area > Settings > Repository**
- (`/admin/application_settings/repository`) in your browser.
-1. In the **Repository storage** section, check **Use hashed storage paths for newly created and renamed projects**.
-
-### Step 5. (Optional) Configuring the **secondary** node to trust the **primary** node
+### Step 4. (Optional) Configuring the **secondary** node to trust the **primary** node
You can safely skip this step if your **primary** node uses a CA-issued HTTPS certificate.
@@ -251,21 +242,23 @@ certificate from the **primary** node and follow
[these instructions](https://docs.gitlab.com/omnibus/settings/ssl.html)
on the **secondary** node.
-### Step 6. Enable Git access over HTTP/HTTPS
+### Step 5. Enable Git access over HTTP/HTTPS
Geo synchronizes repositories over HTTP/HTTPS, and therefore requires this clone
-method to be enabled. Navigate to **Admin Area > Settings**
-(`/admin/application_settings/general`) on the **primary** node, and set
-`Enabled Git access protocols` to `Both SSH and HTTP(S)` or `Only HTTP(S)`.
+method to be enabled. This is enabled by default, but if converting an existing node to Geo it should be checked:
+
+1. Navigate to **Admin Area > Settings** (`/admin/application_settings/general`) on the **primary** node.
+1. Expand "Visibility and access controls".
+1. Ensure "Enabled Git access protocols" is set to either "Both SSH and HTTP(S)" or "Only HTTP(S)".
-### Step 7. Verify proper functioning of the **secondary** node
+### Step 6. Verify proper functioning of the **secondary** node
Your **secondary** node is now configured!
-You can login to the **secondary** node with the same credentials you used for the
-**primary** node. Visit the **secondary** node's **Admin Area > Geo**
-(`/admin/geo/nodes`) in your browser to check if it's correctly identified as a
-**secondary** Geo node and if Geo is enabled.
+You can sign in to the _secondary_ node with the same credentials you used with
+the _primary_ node. Visit the _secondary_ node's **Admin Area > Geo**
+(`/admin/geo/nodes`) in your browser to determine if it's correctly identified
+as a _secondary_ Geo node, and if Geo is enabled.
The initial replication, or 'backfill', will probably still be in progress. You
can monitor the synchronization process on each Geo node from the **primary**
diff --git a/doc/administration/geo/replication/datatypes.md b/doc/administration/geo/replication/datatypes.md
index d1fa2d503be..9e896f2c07c 100644
--- a/doc/administration/geo/replication/datatypes.md
+++ b/doc/administration/geo/replication/datatypes.md
@@ -127,8 +127,11 @@ and verification status on a **secondary** node.
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)
+- [Geo: Build a scalable, self-service Geo replication and verification framework](https://gitlab.com/groups/gitlab-org/-/epics/2161)
+- [Geo: Improve the self-service Geo replication framework](https://gitlab.com/groups/gitlab-org/-/epics/3761)
+- [Geo: Move existing blobs to framework](https://gitlab.com/groups/gitlab-org/-/epics/3588)
+- [Geo: Add unreplicated data types](https://gitlab.com/groups/gitlab-org/-/epics/893)
+- [Geo: Support GitLab Pages](https://gitlab.com/groups/gitlab-org/-/epics/589)
### Replicated data types behind a feature flag
@@ -157,18 +160,19 @@ To enable, such as for package file replication:
Feature.enable(:geo_package_file_replication)
```
-DANGER: **Danger:**
+DANGER: **Warning:**
Features not on this list, or with **No** in the **Replicated** column,
are not replicated on the **secondary** node. Failing over without manually
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) | Object Storage replication (please see [Geo with Object Storage](object_storage.md)) | Notes |
+| Feature | Replicated (added in GitLab version) | Verified (added in GitLab version) | Object Storage replication (see [Geo with Object Storage](object_storage.md)) | Notes |
|:---------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------|:----------------------------------------------------------|:-------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Application data in PostgreSQL](../../postgresql/index.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
| [Project repository](../../..//user/project/repository/) | **Yes** (10.2) | **Yes** (10.7) | No | |
-| [Project wiki repository](../../../user/project/wiki/) | **Yes** (10.2) | **Yes** (10.7) | No | |
+| [Project wiki repository](../../../user/project/wiki/) | **Yes** (10.2) | **Yes** (10.7) | No |
+| [Group wiki repository](../../../user/group/index.md#group-wikis) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | No | |
| [Uploads](../../uploads.md) | **Yes** (10.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | No | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both nodes and comparing the output between them. |
| [LFS objects](../../lfs/index.md) | **Yes** (10.2) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8922) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both nodes and comparing the output between them. GitLab versions 11.11.x and 12.0.x are affected by [a bug that prevents any new LFS objects from replicating](https://gitlab.com/gitlab-org/gitlab/-/issues/32696). |
| [Personal snippets](../../../user/snippets.md#personal-snippets) | **Yes** (10.2) | **Yes** (10.2) | No | |
@@ -176,7 +180,7 @@ successfully, you must replicate their data using some other means.
| [CI job artifacts (other than Job Logs)](../../../ci/pipelines/job_artifacts.md) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Via Object Storage provider if supported. Native Geo support (Beta) . | Verified only manually using [Integrity Check Rake Task](../../raketasks/check.md) on both nodes and comparing the output between them |
| [Job logs](../../job_logs.md) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both nodes and comparing the output between them |
| [Object pools for forked project deduplication](../../../development/git_object_deduplication.md) | **Yes** | No | No | |
-| [Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | No | Disabled by default. See [instructions](./docker_registry.md) to enable. |
+| [Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | No | Disabled by default. See [instructions](docker_registry.md) to enable. |
| [Content in object storage (beta)](object_storage.md) | **Yes** (12.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/13845) | No | |
| [Project designs repository](../../../user/project/issues/design_management.md) | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) | Via Object Storage provider if supported. Native Geo support (Beta). | |
| [NPM Registry](../../../user/packages/npm_registry/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
@@ -187,7 +191,7 @@ successfully, you must replicate their data using some other means.
| [Composer Repository](../../../user/packages/composer_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
| [Generic packages](../../../user/packages/generic_packages/index.md) | **Yes** (13.5) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
| [Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_terraform_state_version_replication`, enabled by default |
-| [External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | No | Behind feature flag `geo_merge_request_diff_replication`, enabled by default | |
+| [External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_merge_request_diff_replication`, enabled by default |
| [Versioned snippets](../../../user/snippets.md#versioned-snippets) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2810) | No | |
| [Server-side Git hooks](../../server_hooks.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1867) | No | No | |
| [Elasticsearch integration](../../../integration/elasticsearch.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | No | |
diff --git a/doc/administration/geo/replication/disable_geo.md b/doc/administration/geo/replication/disable_geo.md
index 14a11d9c1e3..dabf4499f9d 100644
--- a/doc/administration/geo/replication/disable_geo.md
+++ b/doc/administration/geo/replication/disable_geo.md
@@ -25,7 +25,7 @@ To disable Geo, follow these steps:
## Remove all secondary Geo nodes
To disable Geo, you need to first remove all your secondary Geo nodes, which means replication will not happen
-anymore on these nodes. You can follow our docs to [remove your secondary Geo nodes](./remove_geo_node.md).
+anymore on these nodes. You can follow our docs to [remove your secondary Geo nodes](remove_geo_node.md).
If the current node that you want to keep using is a secondary node, you need to first promote it to primary.
You can use our steps on [how to promote a secondary node](../disaster_recovery/#step-3-promoting-a-secondary-node)
diff --git a/doc/administration/geo/replication/location_aware_git_url.md b/doc/administration/geo/replication/location_aware_git_url.md
index ddcdea736e7..82fda8b0fc2 100644
--- a/doc/administration/geo/replication/location_aware_git_url.md
+++ b/doc/administration/geo/replication/location_aware_git_url.md
@@ -43,8 +43,8 @@ In any case, you require:
- A working GitLab **secondary** node.
- 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).
+If you haven't yet set up a Geo _primary_ node and _secondary_ node, see the
+[Geo setup instructions](../index.md#setup-instructions).
## Create a traffic policy
diff --git a/doc/administration/geo/replication/object_storage.md b/doc/administration/geo/replication/object_storage.md
index 642d31f6298..3f5ba1939b8 100644
--- a/doc/administration/geo/replication/object_storage.md
+++ b/doc/administration/geo/replication/object_storage.md
@@ -72,7 +72,7 @@ If you are using Google Cloud Storage, consider using
Or you can use the [Storage Transfer Service](https://cloud.google.com/storage-transfer/docs/),
although this only supports daily synchronization.
-For manual synchronization, or scheduled by `cron`, please have a look at:
+For manual synchronization, or scheduled by `cron`, see:
- [`s3cmd sync`](https://s3tools.org/s3cmd-sync)
- [`gsutil rsync`](https://cloud.google.com/storage/docs/gsutil/commands/rsync)
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index b62c5c6f460..15e3d3ff0a8 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -720,7 +720,8 @@ GitLab cannot find or doesn't have permission to access the `database_geo.yml` c
In an Omnibus GitLab installation, the file should be in `/var/opt/gitlab/gitlab-rails/etc`.
If it doesn't exist or inadvertent changes have been made to it, run `sudo gitlab-ctl reconfigure` to restore it to its correct state.
-If this path is mounted on a remote volume, please check your volume configuration and that it has correct permissions.
+If this path is mounted on a remote volume, ensure your volume configuration
+has the correct permissions.
### An existing tracking database cannot be reused
@@ -782,3 +783,13 @@ To resolve this issue:
using IPv6 to send its status to the **primary** node. If it is, add an entry to
the **primary** node using IPv4 in the `/etc/hosts` file. Alternatively, you should
[enable IPv6 on the **primary** node](https://docs.gitlab.com/omnibus/settings/nginx.html#setting-the-nginx-listen-address-or-addresses).
+
+## Fixing client errors
+
+### Authorization errors from LFS HTTP(s) client requests
+
+You may have problems if you're running a version of [Git LFS](https://git-lfs.github.com/) before 2.4.2.
+As noted in [this authentication issue](https://github.com/git-lfs/git-lfs/issues/3025),
+requests redirected from the secondary to the primary node do not properly send the
+Authorization header. This may result in either an infinite `Authorization <-> Redirect`
+loop, or Authorization errors.
diff --git a/doc/administration/geo/replication/updating_the_geo_nodes.md b/doc/administration/geo/replication/updating_the_geo_nodes.md
index 55ddccb1d98..af59e45250c 100644
--- a/doc/administration/geo/replication/updating_the_geo_nodes.md
+++ b/doc/administration/geo/replication/updating_the_geo_nodes.md
@@ -8,7 +8,9 @@ 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.
+Read these sections carefully before updating your Geo nodes. Not following
+version-specific update steps may result in unexpected downtime. If you have
+any specific questions, [contact Support](https://about.gitlab.com/support/#contact-support).
Updating Geo nodes involves performing:
@@ -47,4 +49,4 @@ everything is working correctly:
1. Test the data replication by pushing code to the **primary** node and see if it
is received by **secondary** nodes.
-If you encounter any issues, please consult the [Geo troubleshooting guide](troubleshooting.md).
+If you encounter any issues, see the [Geo troubleshooting guide](troubleshooting.md).
diff --git a/doc/administration/geo/replication/version_specific_updates.md b/doc/administration/geo/replication/version_specific_updates.md
index 85c869eff92..9ea5283812e 100644
--- a/doc/administration/geo/replication/version_specific_updates.md
+++ b/doc/administration/geo/replication/version_specific_updates.md
@@ -24,34 +24,41 @@ DROP SERVER gitlab_secondary CASCADE;
DROP EXTENSION IF EXISTS postgres_fdw;
```
+DANGER: **Warning:**
+In GitLab 13.3, promoting a secondary node to a primary while the secondary is
+paused fails. Do not pause replication before promoting a secondary. If the
+node is paused, be sure to resume before promoting. To avoid this issue,
+upgrade to GitLab 13.4 or later.
+
+## Updating to GitLab 13.2
+
+In GitLab 13.2, promoting a secondary node to a primary while the secondary is paused fails. **Do not pause replication before promoting a secondary.** If the node is paused, please resume before promoting. To avoid this issue, upgrade to GitLab 13.4 or later.
+
## Updating to GitLab 13.0
Upgrading to GitLab 13.0 requires GitLab 12.10 to already be using PostgreSQL
-version 11. Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for the recommended procedure.
+version 11. For the recommended procedure, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
## Updating to GitLab 12.10
-GitLab 12.10 does not attempt to automatically update the embedded PostgreSQL
-server when using Geo, because the PostgreSQL upgrade requires downtime on
-secondaries while reinitializing streaming replication. It must be upgraded
-manually. Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for the recommended procedure.
+GitLab 12.10 doesn't attempt to update the embedded PostgreSQL server when
+using Geo, because the PostgreSQL upgrade requires downtime for secondaries
+while reinitializing streaming replication. It must be upgraded manually. For
+the recommended procedure, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
## Updating to GitLab 12.9
CAUTION: **Warning:**
GitLab 12.9.0 through GitLab 12.9.3 are affected by [a bug that stops
repository verification](https://gitlab.com/gitlab-org/gitlab/-/issues/213523).
-The issue is fixed in GitLab 12.9.4. Please upgrade to GitLab 12.9.4 or later.
+The issue is fixed in GitLab 12.9.4. Upgrade to GitLab 12.9.4 or later.
By default, GitLab 12.9 will attempt to automatically update the embedded
PostgreSQL server to 10.12 from 9.6, which requires downtime on secondaries
-while reinitializing streaming replication. Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for the recommended procedure.
+while reinitializing streaming replication. For the recommended procedure, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
This can be temporarily disabled by running the following before updating:
@@ -63,9 +70,8 @@ sudo touch /etc/gitlab/disable-postgresql-upgrade
By default, GitLab 12.8 will attempt to automatically update the embedded
PostgreSQL server to 10.12 from 9.6, which requires downtime on secondaries
-while reinitializing streaming replication. Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for the recommended procedure.
+while reinitializing streaming replication. For the recommended procedure, see
+the [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
This can be temporarily disabled by running the following before updating:
@@ -75,7 +81,7 @@ sudo touch /etc/gitlab/disable-postgresql-upgrade
## Updating to GitLab 12.7
-DANGER: **Danger:**
+DANGER: **Warning:**
Only upgrade to GitLab 12.7.5 or later. Do not upgrade to versions 12.7.0
through 12.7.4 because there is [an initialization order
bug](https://gitlab.com/gitlab-org/gitlab/-/issues/199672) that causes Geo
@@ -84,10 +90,9 @@ fix](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24021) was
shipped in 12.7.5.
By default, GitLab 12.7 will attempt to automatically update the embedded
-PostgreSQL server to 10.9 from 9.6, which requires downtime on secondaries while
-reinitializing streaming replication. Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for the recommended procedure.
+PostgreSQL server to 10.9 from 9.6, which requires downtime on secondaries
+while reinitializing streaming replication. For the recommended procedure, see
+the [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
This can be temporarily disabled by running the following before updating:
@@ -98,10 +103,9 @@ sudo touch /etc/gitlab/disable-postgresql-upgrade
## Updating to GitLab 12.6
By default, GitLab 12.6 will attempt to automatically update the embedded
-PostgreSQL server to 10.9 from 9.6, which requires downtime on secondaries while
-reinitializing streaming replication. Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for the recommended procedure.
+PostgreSQL server to 10.9 from 9.6, which requires downtime on secondaries
+while reinitializing streaming replication. For the recommended procedure, see
+the [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
This can be temporarily disabled by running the following before updating:
@@ -112,10 +116,9 @@ sudo touch /etc/gitlab/disable-postgresql-upgrade
## Updating to GitLab 12.5
By default, GitLab 12.5 will attempt to automatically update the embedded
-PostgreSQL server to 10.9 from 9.6, which requires downtime on secondaries while
-reinitializing streaming replication. Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for the recommended procedure.
+PostgreSQL server to 10.9 from 9.6, which requires downtime on secondaries
+while reinitializing streaming replication. For the recommended procedure, see
+the [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
This can be temporarily disabled by running the following before updating:
@@ -126,10 +129,9 @@ sudo touch /etc/gitlab/disable-postgresql-upgrade
## Updating to GitLab 12.4
By default, GitLab 12.4 will attempt to automatically update the embedded
-PostgreSQL server to 10.9 from 9.6, which requires downtime on secondaries while
-reinitializing streaming replication. Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for the recommended procedure.
+PostgreSQL server to 10.9 from 9.6, which requires downtime on secondaries
+while reinitializing streaming replication. For the recommended procedure, see
+the [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
This can be temporarily disabled by running the following before updating:
@@ -139,35 +141,31 @@ sudo touch /etc/gitlab/disable-postgresql-upgrade
## Updating to GitLab 12.3
-DANGER: **Danger:**
+DANGER: **Warning:**
If the existing PostgreSQL server version is 9.6.x, it is recommended to
-upgrade to GitLab 12.4 or newer. By default, GitLab 12.3 will attempt to
-automatically update the embedded PostgreSQL server to 10.9 from 9.6. In
-certain circumstances, it will fail. Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for more information.
+upgrade to GitLab 12.4 or later. By default, GitLab 12.3 attempts to update the
+embedded PostgreSQL server from 9.6 to 10.9. In certain circumstances, it will
+fail. For more information, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
-Additionally, if the PostgreSQL upgrade does not fail, a successful upgrade
-requires downtime on secondaries while reinitializing streaming replication.
-Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for the recommended procedure.
+Additionally, if the PostgreSQL upgrade doesn't fail, a successful upgrade
+requires downtime for secondaries while reinitializing streaming replication.
+For the recommended procedure, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
## Updating to GitLab 12.2
-DANGER: **Danger:**
+DANGER: **Warning:**
If the existing PostgreSQL server version is 9.6.x, it is recommended to
-upgrade to GitLab 12.4 or newer. By default, GitLab 12.2 will attempt to
-automatically update the embedded PostgreSQL server to 10.9 from 9.6. In
-certain circumstances, it will fail. Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for more information.
+upgrade to GitLab 12.4 or later. By default, GitLab 12.2 attempts to update the
+embedded PostgreSQL server from 9.6 to 10.9. In certain circumstances, it will
+fail. For more information, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
Additionally, if the PostgreSQL upgrade does not fail, a successful upgrade
-requires downtime on secondaries while reinitializing streaming replication.
-Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for the recommended procedure.
+requires downtime for secondaries while reinitializing streaming replication.
+For the recommended procedure, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
GitLab 12.2 includes the following minor PostgreSQL updates:
@@ -187,33 +185,31 @@ The restart avoids a version mismatch when PostgreSQL tries to load the FDW exte
## Updating to GitLab 12.1
-DANGER: **Danger:**
+DANGER: **Warning:**
If the existing PostgreSQL server version is 9.6.x, it is recommended to
-upgrade to GitLab 12.4 or newer. By default, GitLab 12.1 will attempt to
-automatically update the embedded PostgreSQL server to 10.9 from 9.6. In
-certain circumstances, it will fail. Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for more information.
+upgrade to GitLab 12.4 or later. By default, GitLab 12.1 attempts to update the
+embedded PostgreSQL server from 9.6 to 10.9. In certain circumstances, it will
+fail. For more information, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
-Additionally, if the PostgreSQL upgrade does not fail, a successful upgrade
-requires downtime on secondaries while reinitializing streaming replication.
-Please see
-[the Omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance)
-for the recommended procedure.
+Additionally, if the PostgreSQL upgrade doesn't fail, a successful upgrade
+requires downtime for secondaries while reinitializing streaming replication.
+For the recommended procedure, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
## Updating to GitLab 12.0
CAUTION: **Warning:**
-This version is affected by [a bug that results in new LFS objects not being replicated to
-Geo secondary nodes](https://gitlab.com/gitlab-org/gitlab/-/issues/32696). The issue is fixed
-in GitLab 12.1. Please upgrade to GitLab 12.1 or later.
+This version is affected by a [bug that results in new LFS objects not being
+replicated to Geo secondary nodes](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).
+The issue is fixed in GitLab 12.1; be sure to upgrade to GitLab 12.1 or later.
## Updating to GitLab 11.11
CAUTION: **Warning:**
-This version is affected by [a bug that results in new LFS objects not being replicated to
-Geo secondary nodes](https://gitlab.com/gitlab-org/gitlab/-/issues/32696). The issue is fixed
-in GitLab 12.1. Please upgrade to GitLab 12.1 or later.
+This version is affected by a [bug that results in new LFS objects not being
+replicated to Geo secondary nodes](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).
+The issue is fixed in GitLab 12.1; be sure to upgrade to GitLab 12.1 or later.
## Updating to GitLab 10.8
@@ -329,7 +325,7 @@ In GitLab 10.2, synchronizing secondaries over SSH was deprecated. In 10.3,
support is removed entirely. All installations will switch to the HTTP/HTTPS
cloning method instead. Before updating, ensure that all your Geo nodes are
configured to use this method and that it works for your installation. In
-particular, ensure that [Git access over HTTP/HTTPS is enabled](configuration.md#step-6-enable-git-access-over-httphttps).
+particular, ensure that [Git access over HTTP/HTTPS is enabled](configuration.md#step-5-enable-git-access-over-httphttps).
Synchronizing repositories over the public Internet using HTTP is insecure, so
you should ensure that you have HTTPS configured before updating. Note that
@@ -433,7 +429,7 @@ required because replication slots are used by default. However, if you
started with GitLab 9.3 and updated later, you should still follow the
instructions below.
-When in doubt, it does not hurt to do a resync. The easiest way to do this in
+When in doubt, it doesn't hurt to do a resync. The easiest way to do this in
Omnibus is the following:
1. Make sure you have Omnibus GitLab on the **primary** server.
diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md
index 09b9c71aeb7..24e55d26997 100644
--- a/doc/administration/geo/setup/database.md
+++ b/doc/administration/geo/setup/database.md
@@ -474,6 +474,81 @@ 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).
+## Patroni support
+
+Support for Patroni is intended to replace `repmgr` as a
+[highly availabile PostgreSQL solution](../../postgresql/replication_and_failover.md)
+on the primary node, but it can also be used for PostgreSQL HA on a secondary
+node.
+
+Starting with GitLab 13.5, Patroni is available for _experimental_ use with Geo
+primary and secondary nodes. Due to its experimental nature, Patroni support is
+subject to change without notice.
+
+This experimental implementation has the following limitations:
+
+- Whenever a new Leader is elected, the PgBouncer instance must be reconfigured
+ to point to the new Leader.
+- Whenever a new Leader is elected on the primary node, the Standby Leader on
+ the secondary needs to be reconfigured to point to the new Leader.
+- Whenever `gitlab-ctl reconfigure` runs on a Patroni Leader instance, there's a
+ chance the node will be demoted due to the required short-time restart. To
+ avoid this, you can pause auto-failover by running `gitlab-ctl patroni pause`.
+ After a reconfigure, it unpauses on its own.
+
+For instructions about how to set up Patroni on the primary node, see the
+[PostgreSQL replication and failover with Omnibus GitLab](../../postgresql/replication_and_failover.md#patroni) page.
+
+A production-ready and secure setup requires at least three Patroni instances on
+the primary, and a similar configuration on the secondary nodes. Be sure to use
+password credentials and other database best practices.
+
+Similar to `repmgr`, using Patroni on a secondary node is optional.
+
+To set up database replication with Patroni on a secondary node, configure a
+_permanent replication slot_ on the primary node's Patroni cluster, and ensure
+password authentication is used.
+
+On Patroni instances for the primary node, add the following to the
+`/etc/gitlab/gitlab.rb` file:
+
+```ruby
+# You need one entry for each secondary, with a unique name following PostgreSQL slot_name constraints:
+#
+# Configuration syntax will be: 'unique_slotname' => { 'type' => 'physical' },
+# We don't support setting a permanent replication slot for logical replication type
+patroni['replication_slots'] = {
+ 'geo_secondary' => { 'type' => 'physical' }
+}
+
+postgresql['md5_auth_cidr_addresses'] = [
+ 'PATRONI_PRIMARY1_IP/32', 'PATRONI_PRIMARY2_IP/32', 'PATRONI_PRIMARY3_IP/32', 'PATRONI_PRIMARY_PGBOUNCER/32',
+ 'PATRONI_SECONDARY1_IP/32', 'PATRONI_SECONDARY2_IP/32', 'PATRONI_SECONDARY3_IP/32' # we list all secondary instances as they can all become a Standby Leader
+ # any other instance that needs access to the database as per documentation
+]
+
+postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
+postgresql['sql_replication_password'] = 'POSTGRESQL_REPLICATION_PASSWORD_HASH'
+postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
+```
+
+On Patroni instances for the secondary node, add the following to the
+`/etc/gitlab/gitlab.rb` file:
+
+```ruby
+postgresql['md5_auth_cidr_addresses'] = [
+ 'PATRONI_SECONDARY1_IP/32', 'PATRONI_SECONDARY2_IP/32', 'PATRONI_SECONDARY3_IP/32', 'PATRONI_SECONDARY_PGBOUNCER/32',
+ # any other instance that needs access to the database as per documentation
+]
+
+patroni['enable'] = true
+patroni['standby_cluster']['enable'] = true
+patroni['standby_cluster']['host'] = 'PATRONI_PRIMARY_LEADER_IP' # this needs to be changed anytime the primary Leader changes
+patroni['standby_cluster']['port'] = 5432
+patroni['standby_cluster']['primary_slot_name'] = 'geo_secondary' # or the unique replication slot name you setup before
+patroni['replication_password'] = 'PLAIN_TEXT_POSTGRESQL_REPLICATION_PASSWORD'
+```
+
## Troubleshooting
Read the [troubleshooting document](../replication/troubleshooting.md).
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 59a6f2596da..0d9c761e078 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -121,7 +121,7 @@ The following list depicts the network architecture of Gitaly:
- Authentication is done through a static token which is shared among the Gitaly and GitLab Rails
nodes.
-DANGER: **Danger:**
+DANGER: **Warning:**
Gitaly servers must not be exposed to the public internet as Gitaly's network traffic is unencrypted
by default. The use of firewall is highly recommended to restrict access to the Gitaly server.
Another option is to [use TLS](#enable-tls-support).
@@ -373,7 +373,7 @@ As the final step, you must update Gitaly clients to switch from using local Git
the Gitaly servers you just configured.
This can be risky because anything that prevents your Gitaly clients from reaching the Gitaly
-servers will cause all Gitaly requests to fail. For example, any sort of network, firewall, or name
+servers causes all Gitaly requests to fail. For example, any sort of network, firewall, or name
resolution problems.
Additionally, you must [disable Rugged](../nfs.md#improving-nfs-performance-with-gitlab)
@@ -450,7 +450,7 @@ server (with `gitaly_address`) unless you setup with special
When you tail the Gitaly logs on your Gitaly server, you should see requests coming in. One sure way
to trigger a Gitaly request is to clone a repository from GitLab over HTTP or HTTPS.
-DANGER: **Danger:**
+DANGER: **Warning:**
If you have [server hooks](../server_hooks.md) configured, either per repository or globally, you
must move these to the Gitaly servers. If you have multiple Gitaly servers, copy your server hooks
to all Gitaly servers.
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index bd075e86a15..20dce6d68df 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -42,6 +42,8 @@ a mail server feature where any email to `user+arbitrary_tag@example.com` will e
in the mailbox for `user@example.com` . It is supported by providers such as
Gmail, Google Apps, Yahoo! Mail, Outlook.com, and iCloud, as well as the
[Postfix mail server](reply_by_email_postfix_setup.md), which you can run on-premises.
+Microsoft Exchange Server [does not support sub-addressing](#microsoft-exchange-server),
+and Microsoft Office 365 [does not support sub-addressing by default](#microsoft-office-365)
TIP: **Tip:**
If your provider or server supports email sub-addressing, we recommend using it.
@@ -326,11 +328,11 @@ incoming_email:
#### Microsoft Exchange Server
-Example configurations for Microsoft Exchange Server with IMAP enabled. Since
+Example configurations for Microsoft Exchange Server with IMAP enabled. Because
Exchange does not support sub-addressing, only two options exist:
-- Catch-all mailbox (recommended for Exchange-only)
-- Dedicated email address (supports Reply by Email only)
+- [Catch-all mailbox](#catch-all-mailbox) (recommended for Exchange-only)
+- [Dedicated email address](#dedicated-email-address) (supports Reply by Email only)
##### Catch-all mailbox
@@ -417,7 +419,8 @@ Example for source installs:
incoming_email:
enabled: true
- # Exchange does not support sub-addressing, and we're not using a catch-all mailbox so %{key} is not used here
+ # Exchange does not support sub-addressing,
+ # and we're not using a catch-all mailbox so %{key} is not used here
address: "incoming@exchange.example.com"
# Email account username
@@ -433,3 +436,180 @@ incoming_email:
# Whether the IMAP server uses SSL
ssl: true
```
+
+#### Microsoft Office 365
+
+Example configurations for Microsoft Office 365 with IMAP enabled.
+
+##### Sub-addressing mailbox
+
+NOTE: **Note:**
+As of September 2020 sub-addressing support
+[has been added to Office 365](https://office365.uservoice.com/forums/273493-office-365-admin/suggestions/18612754-support-for-dynamic-email-aliases-in-office-36). This feature is not
+enabled by default, and must be enabled through PowerShell.
+
+This series of PowerShell commands enables [sub-addressing](#email-sub-addressing)
+at the organization level in Office 365. This allows all mailboxes in the organization
+to receive sub-addressed mail:
+
+NOTE: **Note:**
+This series of commands will enable sub-addressing at the organization
+level in Office 365. This will allow all mailboxes in the organization
+to receive sub-addressed mail.
+
+```powershell
+Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
+
+$UserCredential = Get-Credential
+
+$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
+
+Import-PSSession $Session -DisableNameChecking
+
+Set-OrganizationConfig -AllowPlusAddressInRecipients $true
+```
+
+This example for Omnibus GitLab assumes the mailbox `incoming@office365.example.com`:
+
+```ruby
+gitlab_rails['incoming_email_enabled'] = true
+
+# The email address including the `%{key}` placeholder that will be replaced
+# to reference the item being replied to. The placeholder can be omitted, but if
+# present, it must appear in the "user" part of the address (before the `@`).
+gitlab_rails['incoming_email_address'] = "incoming+%{key}@office365.example.com"
+
+# Email account username
+# Typically this is the userPrincipalName (UPN)
+gitlab_rails['incoming_email_email'] = "incoming@office365.example.com"
+# Email account password
+gitlab_rails['incoming_email_password'] = "[REDACTED]"
+
+# IMAP server host
+gitlab_rails['incoming_email_host'] = "outlook.office365.com"
+# IMAP server port
+gitlab_rails['incoming_email_port'] = 993
+# Whether the IMAP server uses SSL
+gitlab_rails['incoming_email_ssl'] = true
+```
+
+This example for source installs assumes the mailbox `incoming@office365.example.com`:
+
+```yaml
+incoming_email:
+ enabled: true
+
+ # The email address including the `%{key}` placeholder that will be replaced
+ # to reference the item being replied to. The placeholder can be omitted, but
+ # if present, it must appear in the "user" part of the address (before the `@`).
+ address: "incoming+%{key}@office365.example.comm"
+
+ # Email account username
+ # Typically this is the userPrincipalName (UPN)
+ user: "incoming@office365.example.comm"
+ # Email account password
+ password: "[REDACTED]"
+
+ # IMAP server host
+ host: "outlook.office365.com"
+ # IMAP server port
+ port: 993
+ # Whether the IMAP server uses SSL
+ ssl: true
+```
+
+##### Catch-all mailbox
+
+This example for Omnibus installs assumes the catch-all mailbox `incoming@office365.example.com`:
+
+```ruby
+gitlab_rails['incoming_email_enabled'] = true
+
+# The email address including the `%{key}` placeholder that will be replaced to
+# reference the item being replied to. The placeholder can be omitted, but if present,
+# it must appear in the "user" part of the address (before the `@`).
+gitlab_rails['incoming_email_address'] = "incoming-%{key}@office365.example.com"
+
+# Email account username
+# Typically this is the userPrincipalName (UPN)
+gitlab_rails['incoming_email_email'] = "incoming@office365.example.com"
+# Email account password
+gitlab_rails['incoming_email_password'] = "[REDACTED]"
+
+# IMAP server host
+gitlab_rails['incoming_email_host'] = "outlook.office365.com"
+# IMAP server port
+gitlab_rails['incoming_email_port'] = 993
+# Whether the IMAP server uses SSL
+gitlab_rails['incoming_email_ssl'] = true
+```
+
+This example for source installs assumes the catch-all mailbox `incoming@office365.example.com`:
+
+```yaml
+incoming_email:
+ enabled: true
+
+ # The email address including the `%{key}` placeholder that will be replaced
+ # to reference the item being replied to. The placeholder can be omitted, but
+ # if present, it must appear in the "user" part of the address (before the `@`).
+ address: "incoming-%{key}@office365.example.com"
+
+ # Email account username
+ # Typically this is the userPrincipalName (UPN)
+ user: "incoming@ad-domain.example.com"
+ # Email account password
+ password: "[REDACTED]"
+
+ # IMAP server host
+ host: "outlook.office365.com"
+ # IMAP server port
+ port: 993
+ # Whether the IMAP server uses SSL
+ ssl: true
+```
+
+##### Dedicated email address
+
+This example for Omnibus installs assumes the dedicated email address `incoming@office365.example.com`:
+
+```ruby
+gitlab_rails['incoming_email_enabled'] = true
+
+gitlab_rails['incoming_email_address'] = "incoming@office365.example.com"
+
+# Email account username
+# Typically this is the userPrincipalName (UPN)
+gitlab_rails['incoming_email_email'] = "incoming@office365.example.com"
+# Email account password
+gitlab_rails['incoming_email_password'] = "[REDACTED]"
+
+# IMAP server host
+gitlab_rails['incoming_email_host'] = "outlook.office365.com"
+# IMAP server port
+gitlab_rails['incoming_email_port'] = 993
+# Whether the IMAP server uses SSL
+gitlab_rails['incoming_email_ssl'] = true
+```
+
+This example for source installs assumes the dedicated email address `incoming@office365.example.com`:
+
+```yaml
+incoming_email:
+ enabled: true
+
+ address: "incoming@office365.example.com"
+
+ # Email account username
+ # Typically this is the userPrincipalName (UPN)
+ user: "incoming@office365.example.com"
+ # Email account password
+ password: "[REDACTED]"
+
+ # IMAP server host
+ host: "outlook.office365.com"
+ # IMAP server port
+ port: 993
+ # Whether the IMAP server uses SSL
+ ssl: true
+```
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 07aa3b50bc6..0aa94b86371 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#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"
description: 'Learn how to install, configure, update, and maintain your GitLab instance.'
---
@@ -143,7 +143,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Container Registry](packages/container_registry.md): Configure Container Registry with GitLab.
- [Package Registry](packages/index.md): Enable GitLab to act as an NPM Registry and a Maven Repository.
-- [Dependency Proxy](packages/dependency_proxy.md): Configure the Dependency Proxy, a local proxy for frequently used upstream images/packages. **(PREMIUM ONLY)**
+- [Dependency Proxy](packages/dependency_proxy.md): Configure the Dependency Proxy, a local proxy for frequently used upstream images/packages.
### Repository settings
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index cb37be8d9dd..ec56a59fdc2 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -179,7 +179,6 @@ Plan.default.actual_limits.update!(project_hooks: 100)
Plan.default.actual_limits.update!(group_hooks: 100)
```
-NOTE: **Note:**
Set the limit to `0` to disable it.
## Incoming emails from auto-responders
@@ -217,7 +216,6 @@ Plan.default.actual_limits.update!(offset_pagination_limit: 10000)
- **Default offset pagination limit:** 50000
-NOTE: **Note:**
Set the limit to `0` to disable it.
## CI/CD limits
@@ -250,7 +248,6 @@ To set this limit on a self-managed installation, run the following in the
Plan.default.actual_limits.update!(ci_active_jobs: 500)
```
-NOTE: **Note:**
Set the limit to `0` to disable it.
### Number of CI/CD subscriptions to a project
@@ -273,7 +270,6 @@ To set this limit on a self-managed installation, run the following in the
Plan.default.actual_limits.update!(ci_project_subscriptions: 500)
```
-NOTE: **Note:**
Set the limit to `0` to disable it.
### Number of pipeline schedules
@@ -351,7 +347,7 @@ setting is used:
| `ci_max_artifact_size_license_management` | 0 |
| `ci_max_artifact_size_license_scanning` | 0 |
| `ci_max_artifact_size_load_performance` | 0 |
-| `ci_max_artifact_size_lsif` | 20 MB ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37226) in GitLab 13.3) |
+| `ci_max_artifact_size_lsif` | 100 MB ([Introduced at 20 MB](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37226) in GitLab 13.3 and [raised to 100 MB](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46980) in GitLab 13.6.) |
| `ci_max_artifact_size_metadata` | 0 |
| `ci_max_artifact_size_metrics_referee` | 0 |
| `ci_max_artifact_size_metrics` | 0 |
@@ -462,11 +458,10 @@ Setting a limit helps reduce the memory usage of the indexing processes as well
as the overall index size. This value defaults to `1024 KiB` (1 MiB) as any
text files larger than this likely aren't meant to be read by humans.
-NOTE: **Note:**
-You must set a limit, as an unlimited file size is not supported. Setting this
-value to be greater than the amount of memory on GitLab's Sidekiq nodes will
-lead to GitLab's Sidekiq nodes running out of memory as they will pre-allocate
-this amount of memory during indexing.
+You must set a limit, as unlimited file sizes aren't supported. Setting this
+value to be greater than the amount of memory on GitLab's Sidekiq nodes causes
+GitLab's Sidekiq nodes to run out of memory, as they will pre-allocate this
+amount of memory during indexing.
### Maximum field length
@@ -486,7 +481,6 @@ indexed](#maximum-file-size-indexed)).
This limit can be configured for self-managed installations when [enabling
Elasticsearch](../integration/elasticsearch.md#enabling-advanced-search).
-NOTE: **Note:**
Set the limit to `0` to disable it.
## Wiki limits
diff --git a/doc/administration/instance_review.md b/doc/administration/instance_review.md
index 7eadb54804b..b00586b281b 100644
--- a/doc/administration/instance_review.md
+++ b/doc/administration/instance_review.md
@@ -4,15 +4,15 @@ group: Conversion
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Instance Review **(CORE ONLY)**
+# Instance Review
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6995) in [GitLab Core](https://about.gitlab.com/pricing/) 11.3.
-If you are running a medium size instance (50+ users) of
-[GitLab Core](https://about.gitlab.com/pricing/) edition, you are qualified for a
-free Instance Review.
+If you run a medium-sized self-managed instance (50+ users) of a free version of GitLab,
+[either Community Edition or unlicensed Enterprise Edition](https://about.gitlab.com/install/ce-or-ee/),
+you qualify for a free Instance Review.
-1. Sign in as a user with Admin [permissions](../user/permissions.md).
+1. Sign in as a user with administrator [permissions](../user/permissions.md).
1. In the top menu, click your user icon, and select
**Get a free instance review**:
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 8069b12e0b9..a010903013e 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -103,7 +103,7 @@ If you configure GitLab to store artifacts on object storage, you may also want
[eliminate local disk usage for job logs](job_logs.md#prevent-local-disk-usage).
In both cases, job logs are archived and moved to object storage when the job completes.
-DANGER: **Danger:**
+DANGER: **Warning:**
In a multi-server setup you must use one of the options to
[eliminate local disk usage for job logs](job_logs.md#prevent-local-disk-usage), or job logs could be lost.
diff --git a/doc/administration/job_logs.md b/doc/administration/job_logs.md
index c89ffb8da8b..23343d309de 100644
--- a/doc/administration/job_logs.md
+++ b/doc/administration/job_logs.md
@@ -43,6 +43,45 @@ To change the location where the job logs will be stored, follow the steps below
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the
changes to take effect.
+Alternatively, if you have existing job logs you can follow
+these steps to move the logs to a new location without losing any data.
+
+1. Pause continuous integration data processing by updating this setting in `/etc/gitlab/gitlab.rb`.
+ Jobs in progress are not affected, based on how [data flow](#data-flow) works.
+
+ ```ruby
+ sidekiq['experimental_queue_selector'] = true
+ sidekiq['queue_groups'] = [
+ "feature_category!=continuous_integration"
+ ]
+ ```
+
+1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the
+ changes to take effect.
+1. Set the new storage location in `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_ci['builds_directory'] = '/mnt/to/gitlab-ci/builds'
+ ```
+
+1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the
+ changes to take effect.
+1. Use `rsync` to move job logs from the current location to the new location:
+
+ ```shell
+ sudo rsync -avzh --remove-source-files --ignore-existing --progress /var/opt/gitlab/gitlab-ci/builds/ /mnt/to/gitlab-ci/builds`
+ ```
+
+ Use `--ignore-existing` so you don't override new job logs with older versions of the same log.
+1. Unpause continuous integration data processing by editing `/etc/gitlab/gitlab.rb` and removing the `sidekiq` setting you updated earlier.
+1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the
+ changes to take effect.
+1. Remove the old job logs storage location:
+
+ ```shell
+ sudo rm -rf /var/opt/gitlab/gitlab-ci/builds`
+ ```
+
**In installations from source:**
1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
@@ -82,7 +121,7 @@ job output in the UI will be empty.
For example, to delete all job logs older than 60 days, run the following from a shell in your GitLab instance:
-DANGER: **Danger:**
+DANGER: **Warning:**
This command will permanently delete the log files and is irreversible.
```shell
@@ -104,7 +143,7 @@ The data flow is the same as described in the [data flow section](#data-flow)
with one change: _the stored path of the first two phases is different_. This incremental
log architecture stores chunks of logs in Redis and a persistent store (object storage or database) instead of
file storage. Redis is used as first-class storage, and it stores up-to 128KB
-of data. Once the full chunk is sent, it is flushed to a persistent store, either object storage (temporary directory) or database.
+of data. After the full chunk is sent, it is flushed to a persistent store, either object storage (temporary directory) or database.
After a while, the data in Redis and a persistent store will be archived to [object storage](#uploading-logs-to-object-storage).
The data are stored in the following Redis namespace: `Gitlab::Redis::SharedState`.
@@ -114,9 +153,9 @@ Here is the detailed data flow:
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. After the data in Redis reaches 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.
-1. Once the job is finished, GitLab schedules a Sidekiq worker to archive the log.
+1. After the job is finished, GitLab schedules a Sidekiq worker to archive the log.
1. The Sidekiq worker archives the log to object storage and cleans up the log
in Redis and a persistent store (object storage or the database).
diff --git a/doc/administration/load_balancer.md b/doc/administration/load_balancer.md
index ae4fa83662a..410381ff2b0 100644
--- a/doc/administration/load_balancer.md
+++ b/doc/administration/load_balancer.md
@@ -114,7 +114,7 @@ Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`.
## Readiness check
-It is strongly recommend that multi-node deployments configure load balancers to utilize the [readiness check](../user/admin_area/monitoring/health_check.md#readiness) to ensure a node is ready to accept traffic, before routing traffic to it. This is especially important when utilizing Puma, as there is a brief period during a restart where Puma will not accept requests.
+It is strongly recommend that multi-node deployments configure load balancers to use the [readiness check](../user/admin_area/monitoring/health_check.md#readiness) to ensure a node is ready to accept traffic, before routing traffic to it. This is especially important when utilizing Puma, as there is a brief period during a restart where Puma will not accept requests.
<!-- ## Troubleshooting
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index c9e0cca807e..e5523ba67aa 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -14,8 +14,8 @@ Find more about them [in Audit Events documentation](audit_events.md).
System log files are typically plain text in a standard log file format.
This guide talks about how to read and use these system log files.
-[Read more about how to customise logging on Omnibus GitLab
-installations](https://docs.gitlab.com/omnibus/settings/logs.html)
+Read more about how to
+[customize logging on Omnibus GitLab installations](https://docs.gitlab.com/omnibus/settings/logs.html)
including adjusting log retention, log forwarding,
switching logs from JSON to plain text logging, and more.
@@ -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 Search](../user/search/advanced_global_search.md). These will
+[Advanced Search](../user/search/advanced_global_search.md). These
additionally log `elasticsearch_calls` and `elasticsearch_call_duration_s`,
which correspond to:
@@ -367,9 +367,9 @@ After GitLab version 12.2, this file was renamed from `githost.log` to
`git_json.log` and stored in JSON format.
GitLab has to interact with Git repositories, but in some rare cases
-something can go wrong, and in this case you may need know what exactly
+something can go wrong. If this happens, you need to know exactly what
happened. This log file contains all failed requests from GitLab to Git
-repositories. In the majority of cases this file will be useful for developers
+repositories. In the majority of cases this file is useful for developers
only. For example:
```json
@@ -482,7 +482,7 @@ This file contains logging information about jobs before Sidekiq starts
processing them, such as before being enqueued.
This log file follows the same structure as
-[`sidekiq.log`](#sidekiqlog), so it will be structured as JSON if
+[`sidekiq.log`](#sidekiqlog), so it is structured as JSON if
you've configured this for Sidekiq as mentioned above.
## `gitlab-shell.log`
@@ -582,6 +582,12 @@ This file lives in `/var/log/gitlab/gitaly/current` and is produced by [runit](h
This file lives in `/var/log/gitlab/gitlab-rails/grpc.log` for Omnibus GitLab packages. Native [gRPC](https://grpc.io/) logging used by Gitaly.
+### `gitaly_ruby_json.log`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/2678) in GitLab 13.6.
+
+This file lives in `/var/log/gitlab/gitaly/gitaly_ruby_json.log` and is produced by [`gitaly-ruby`](gitaly/reference.md#gitaly-ruby). It contains an access log of gRPC calls made by Gitaly to `gitaly-ruby`.
+
## Puma Logs
### `puma_stdout.log`
@@ -599,7 +605,7 @@ installations from source.
## Unicorn Logs
Starting with GitLab 13.0, Puma is the default web server used in GitLab
-all-in-one package based installations as well as GitLab Helm chart deployments.
+all-in-one package based installations, and GitLab Helm chart deployments.
### `unicorn_stdout.log`
@@ -720,21 +726,26 @@ 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:
+starts 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
+be enabled:
+
+- For Omnibus GitLab installations, using the `sidekiq['exporter_log_enabled'] = true`
+ option in `/etc/gitlab/gitlab.rb`.
+- For installations from source, using the `sidekiq_exporter.log_enabled` option
+ in `gitlab.yml`.
+
+When enabled, access logs are 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
-start a Web server and listen to the defined port (default: `8083`). Access logs
-will be generated in `/var/log/gitlab/gitlab-rails/web_exporter.log` for
-Omnibus GitLab packages or in `/home/git/gitlab/log/web_exporter.log` for
-installations from source.
+If Prometheus metrics and the Web Exporter are both enabled, Puma/Unicorn
+starts a Web server and listen to the defined port (default: `8083`), and access logs
+are generated:
+
+- For Omnibus GitLab packages, in `/var/log/gitlab/gitlab-rails/web_exporter.log`.
+- For installations from source, in `/home/git/gitlab/log/web_exporter.log`.
## `database_load_balancing.log` **(PREMIUM ONLY)**
@@ -750,13 +761,11 @@ It's stored at:
> Introduced in GitLab 12.6.
-This file lives in
-`/var/log/gitlab/gitlab-rails/elasticsearch.log` for Omnibus GitLab
-packages or in `/home/git/gitlab/log/elasticsearch.log` for installations
-from source.
+This file logs information related to the Elasticsearch Integration, including
+errors during indexing or searching Elasticsearch. It's stored at:
-It logs information related to the Elasticsearch Integration including
-errors during indexing or searching Elasticsearch.
+- `/var/log/gitlab/gitlab-rails/elasticsearch.log` for Omnibus GitLab packages.
+- `/home/git/gitlab/log/elasticsearch.log` for installations from source.
Each line contains a JSON line that can be ingested by services like Elasticsearch and Splunk.
Line breaks have been added to the following example line for clarity:
@@ -779,12 +788,12 @@ Line breaks have been added to the following example line for clarity:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17819) in GitLab 12.6.
-This file lives in
-`/var/log/gitlab/gitlab-rails/exceptions_json.log` for Omnibus GitLab
-packages or in `/home/git/gitlab/log/exceptions_json.log` for installations
-from source.
+This file logs the information about exceptions being tracked by
+`Gitlab::ErrorTracking`, which provides a standard and consistent way of
+[processing rescued exceptions](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/logging.md#exception-handling). This file is stored in:
-It logs the information about exceptions being tracked by `Gitlab::ErrorTracking` which provides a standard and consistent way of [processing rescued exceptions](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/logging.md#exception-handling).
+- `/var/log/gitlab/gitlab-rails/exceptions_json.log` for Omnibus GitLab packages.
+- `/home/git/gitlab/log/exceptions_json.log` for installations from source.
Each line contains a JSON line that can be ingested by Elasticsearch. For example:
@@ -814,7 +823,7 @@ Omnibus GitLab packages or in `/home/git/gitlab/log/service_measurement.log` for
installations from source.
It contains only a single structured log with measurements for each service execution.
-It will contain measurements such as the number of SQL calls, `execution_time`, `gc_stats`, and `memory usage`.
+It contains measurements such as the number of SQL calls, `execution_time`, `gc_stats`, and `memory usage`.
For example:
@@ -847,7 +856,9 @@ This file is stored in:
- `/var/log/gitlab/gitlab-rails/update_mirror_service_json.log` for Omnibus GitLab installations.
- `/home/git/gitlab/log/update_mirror_service_json.log` for installations from source.
-This file contains information about any errors that occurred during project mirroring.
+This file contains information about LFS errors that occurred during project mirroring.
+While we work to move other project mirroring errors into this log, the [general log](#productionlog)
+can be used.
```json
{
@@ -939,7 +950,7 @@ For Omnibus GitLab installations, Alertmanager logs reside in `/var/log/gitlab/a
## Crond Logs
-For Omnibus GitLab installations, crond logs reside in `/var/log/gitlab/crond/`.
+For Omnibus GitLab installations, `crond` logs reside in `/var/log/gitlab/crond/`.
## Grafana Logs
@@ -957,6 +968,11 @@ For Omnibus GitLab installations, GitLab Monitor logs reside in `/var/log/gitlab
For Omnibus GitLab installations, GitLab Exporter logs reside in `/var/log/gitlab/gitlab-exporter/`.
+## GitLab Kubernetes Agent Server
+
+For Omnibus GitLab installations, GitLab Kubernetes Agent Server logs reside
+in `/var/log/gitlab/gitlab-kas/`.
+
## Gathering logs
When [troubleshooting](troubleshooting/index.md) issues that aren't localized to one of the
@@ -967,7 +983,7 @@ from a GitLab instance.
If the bug or error is readily reproducible, save the main GitLab logs
[to a file](troubleshooting/linux_cheat_sheet.md#files--dirs) while reproducing the
-problem once or more times:
+problem a few times:
```shell
sudo gitlab-ctl tail | tee /tmp/<case-ID-and-keywords>.log
@@ -980,7 +996,7 @@ Conclude the log gathering with <kbd>Ctrl</kbd> + <kbd>C</kbd>.
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).
+to run it, read [the GitLabSOS documentation](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos/#gitlabsos).
NOTE: **Note:**
GitLab Support likes to use this custom-made tool.
@@ -989,5 +1005,5 @@ GitLab Support likes to use this custom-made tool.
[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).
+For more details and instructions to run it, read the
+[documentation for fast-stats](https://gitlab.com/gitlab-com/support/toolbox/fast-stats#usage).
diff --git a/doc/administration/monitoring/github_imports.md b/doc/administration/monitoring/github_imports.md
index 64f45001438..da7796c05f0 100644
--- a/doc/administration/monitoring/github_imports.md
+++ b/doc/administration/monitoring/github_imports.md
@@ -17,11 +17,10 @@ monitor the health and progress of the importer.
|------------------------------------------|-----------|
| `github_importer_total_duration_seconds` | histogram |
-This metric tracks the total time spent (in seconds) importing a project (from
+This metric tracks the total time, in seconds, spent importing a project (from
project creation until the import process finishes), for every imported project.
-
The name of the project is stored in the `project` label in the format
-`namespace/name` (e.g. `gitlab-org/gitlab`).
+`namespace/name` (such as `gitlab-org/gitlab`).
## Number of imported projects
@@ -59,7 +58,7 @@ projects. This metric does not expose any labels.
This metric tracks the number of imported issues across all projects.
The name of the project is stored in the `project` label in the format
-`namespace/name` (e.g. `gitlab-org/gitlab`).
+`namespace/name` (such as `gitlab-org/gitlab`).
## Number of imported pull requests
@@ -70,7 +69,7 @@ The name of the project is stored in the `project` label in the format
This metric tracks the number of imported pull requests across all projects.
The name of the project is stored in the `project` label in the format
-`namespace/name` (e.g. `gitlab-org/gitlab`).
+`namespace/name` (such as `gitlab-org/gitlab`).
## Number of imported comments
@@ -81,7 +80,7 @@ The name of the project is stored in the `project` label in the format
This metric tracks the number of imported comments across all projects.
The name of the project is stored in the `project` label in the format
-`namespace/name` (e.g. `gitlab-org/gitlab`).
+`namespace/name` (such as `gitlab-org/gitlab`).
## Number of imported pull request review comments
@@ -92,7 +91,7 @@ The name of the project is stored in the `project` label in the format
This metric tracks the number of imported comments across all projects.
The name of the project is stored in the `project` label in the format
-`namespace/name` (e.g. `gitlab-org/gitlab`).
+`namespace/name` (such as `gitlab-org/gitlab`).
## Number of imported repositories
diff --git a/doc/administration/monitoring/performance/gitlab_configuration.md b/doc/administration/monitoring/performance/gitlab_configuration.md
index 6677eb73664..eb9dab1af59 100644
--- a/doc/administration/monitoring/performance/gitlab_configuration.md
+++ b/doc/administration/monitoring/performance/gitlab_configuration.md
@@ -7,21 +7,17 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Configuration
GitLab Performance Monitoring is disabled by default. To enable it and change any of its
-settings, navigate to **Admin Area > Settings > Metrics and profiling**
-(`/admin/application_settings/metrics_and_profiling`).
+settings:
-![GitLab Performance Monitoring Admin Settings](img/metrics_gitlab_configuration_settings.png)
+1. Navigate to **Admin Area > Settings > Metrics and profiling**
+ (`/admin/application_settings/metrics_and_profiling`):
-Finally, a restart of all GitLab processes is required for the changes to take
-effect:
+ ![GitLab Performance Monitoring Administration Settings](img/metrics_gitlab_configuration_settings.png)
-```shell
-# For Omnibus installations
-sudo gitlab-ctl restart
+1. You must restart all GitLab processes for the changes to take effect:
-# For installations from source
-sudo service gitlab restart
-```
+ - For Omnibus GitLab installations: `sudo gitlab-ctl restart`
+ - For installations from source: `sudo service gitlab restart`
## Pending Migrations
diff --git a/doc/administration/monitoring/performance/grafana_configuration.md b/doc/administration/monitoring/performance/grafana_configuration.md
index 77ed5d442e6..dc77a35e44b 100644
--- a/doc/administration/monitoring/performance/grafana_configuration.md
+++ b/doc/administration/monitoring/performance/grafana_configuration.md
@@ -113,7 +113,7 @@ If you require access to your old Grafana data but don't meet one of these crite
1. [Exporting the dashboards](https://grafana.com/docs/grafana/latest/reference/export_import/#exporting-a-dashboard) you need.
1. Refreshing the data and [re-importing your dashboards](https://grafana.com/docs/grafana/latest/reference/export_import/#importing-a-dashboard).
-DANGER: **Danger:**
+DANGER: **Warning:**
These actions pose a temporary vulnerability while your old Grafana data is in use.
Deciding to take any of these actions should be weighed carefully with your need to access
existing data and dashboards.
diff --git a/doc/administration/monitoring/performance/index.md b/doc/administration/monitoring/performance/index.md
index 68b89b837ac..6ea756619f5 100644
--- a/doc/administration/monitoring/performance/index.md
+++ b/doc/administration/monitoring/performance/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Performance Monitoring
GitLab comes with its own application performance measuring system as of GitLab
-8.4, simply called "GitLab Performance Monitoring". GitLab Performance Monitoring is available in both the
+8.4, called "GitLab Performance Monitoring". GitLab Performance Monitoring is available in both the
Community and Enterprise editions.
Apart from this introduction, you are advised to read through the following
@@ -42,7 +42,7 @@ Two types of metrics are collected:
Transaction metrics are metrics that can be associated with a single
transaction. This includes statistics such as the transaction duration, timings
-of any executed SQL queries, time spent rendering HAML views, etc. These metrics
+of any executed SQL queries, time spent rendering HAML views, and so on. These metrics
are collected for every Rack request and Sidekiq job processed.
### Sampled Metrics
@@ -59,5 +59,5 @@ parts:
The actual interval can be anywhere between a half of the defined interval and a
half above the interval. For example, for a user defined interval of 15 seconds
the actual interval can be anywhere between 7.5 and 22.5. The interval is
-re-generated for every sampling run instead of being generated once and re-used
+re-generated for every sampling run instead of being generated one time and reused
for the duration of the process' lifetime.
diff --git a/doc/administration/monitoring/prometheus/gitlab_exporter.md b/doc/administration/monitoring/prometheus/gitlab_exporter.md
index 971dafb4ba2..aa2eb9f3415 100644
--- a/doc/administration/monitoring/prometheus/gitlab_exporter.md
+++ b/doc/administration/monitoring/prometheus/gitlab_exporter.md
@@ -13,7 +13,6 @@ The [GitLab exporter](https://gitlab.com/gitlab-org/gitlab-exporter) enables you
measure various GitLab metrics pulled from Redis and the database in Omnibus GitLab
instances.
-NOTE: **Note:**
For installations from source you must install and configure it yourself.
To enable the GitLab exporter in an Omnibus GitLab instance:
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index adb1f719f3c..5c9268b54e1 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -13,7 +13,6 @@ To enable the GitLab Prometheus metrics:
1. Find the **Metrics - Prometheus** section, and click **Enable Prometheus Metrics**.
1. [Restart GitLab](../../restart_gitlab.md#omnibus-gitlab-restart) for the changes to take effect.
-NOTE: **Note:**
For installations from source you must configure it yourself.
## Collecting the metrics
@@ -124,8 +123,6 @@ The following metrics can be controlled by feature flags:
|:---------------------------------------------------------------|:-------------------------------------------------------------------|
| `gitlab_method_call_duration_seconds` | `prometheus_metrics_method_instrumentation` |
| `gitlab_view_rendering_duration_seconds` | `prometheus_metrics_view_instrumentation` |
-| `gitlab_issuable_fast_count_by_state_total` | `soft_fail_count_by_state` |
-| `gitlab_issuable_fast_count_by_state_failures_total` | `soft_fail_count_by_state` |
## Sidekiq metrics
@@ -211,6 +208,7 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `limited_capacity_worker_running_jobs` | Gauge | 13.5 | Number of running jobs | `worker` |
| `limited_capacity_worker_max_running_jobs` | Gauge | 13.5 | Maximum number of running jobs | `worker` |
| `limited_capacity_worker_remaining_work_count` | Gauge | 13.5 | Number of jobs waiting to be enqueued | `worker` |
+| `destroyed_job_artifacts_count_total` | Counter | 13.6 | Number of destroyed expired job artifacts | |
## Database load balancing metrics **(PREMIUM ONLY)**
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
index 63231996dcc..91f810dc681 100644
--- a/doc/administration/monitoring/prometheus/index.md
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -26,12 +26,11 @@ access to high quality time-series monitoring of GitLab services.
Prometheus works by periodically connecting to data sources and collecting their
performance metrics through the [various exporters](#bundled-software-metrics). To view
and work with the monitoring data, you can either
-[connect directly to Prometheus](#viewing-performance-metrics) or utilize a
+[connect directly to Prometheus](#viewing-performance-metrics) or use a
dashboard tool like [Grafana](https://grafana.com).
## Configuring Prometheus
-NOTE: **Note:**
For installations from source, you must install and configure it yourself.
Prometheus and its exporters are on by default, starting with GitLab 9.0.
@@ -54,7 +53,7 @@ To disable Prometheus and all of its exporters, as well as any added in the futu
### Changing the port and address Prometheus listens on
-NOTE: **Note:**
+CAUTION: **Caution:**
The following change was added in [Omnibus GitLab 8.17](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/1261). Although possible,
it's not recommended to change the port Prometheus listens
on, as this might affect or conflict with other services running on the GitLab
@@ -178,7 +177,6 @@ The next step is to tell all the other nodes where the monitoring node is:
1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to
take effect.
-NOTE: **Note:**
After monitoring using Service Discovery is enabled with `consul['monitoring_service_discovery'] = true`,
ensure that `prometheus['scrape_configs']` is not set in `/etc/gitlab/gitlab.rb`. Setting both
`consul['monitoring_service_discovery'] = true` and `prometheus['scrape_configs']` in `/etc/gitlab/gitlab.rb`
@@ -186,7 +184,7 @@ will result in errors.
### Using an external Prometheus server
-NOTE: **Note:**
+CAUTION: **Caution:**
Prometheus and most exporters don't support authentication. We don't recommend exposing them outside the local network.
A few configuration changes are required to allow GitLab to be monitored by an external Prometheus server. External servers are recommended for [GitLab deployments with multiple nodes](../../reference_architectures/index.md).
diff --git a/doc/administration/monitoring/prometheus/node_exporter.md b/doc/administration/monitoring/prometheus/node_exporter.md
index dae1f02b196..fea78a3685c 100644
--- a/doc/administration/monitoring/prometheus/node_exporter.md
+++ b/doc/administration/monitoring/prometheus/node_exporter.md
@@ -9,7 +9,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
The [node exporter](https://github.com/prometheus/node_exporter) enables you to measure
various machine resources such as memory, disk and CPU utilization.
-NOTE: **Note:**
For installations from source you must install and configure it yourself.
To enable the node exporter:
diff --git a/doc/administration/monitoring/prometheus/pgbouncer_exporter.md b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
index 4554bc06401..ff0cfc65e10 100644
--- a/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
+++ b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
@@ -11,7 +11,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
The [PgBouncer exporter](https://github.com/prometheus-community/pgbouncer_exporter) enables
you to measure various [PgBouncer](https://www.pgbouncer.org/) metrics.
-NOTE: **Note:**
For installations from source you must install and configure it yourself.
To enable the PgBouncer exporter:
diff --git a/doc/administration/monitoring/prometheus/postgres_exporter.md b/doc/administration/monitoring/prometheus/postgres_exporter.md
index 9eb9ba3c59f..f7368556235 100644
--- a/doc/administration/monitoring/prometheus/postgres_exporter.md
+++ b/doc/administration/monitoring/prometheus/postgres_exporter.md
@@ -8,7 +8,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
The [PostgreSQL Server Exporter](https://github.com/wrouesnel/postgres_exporter) allows you to export various PostgreSQL metrics.
-NOTE: **Note:**
For installations from source you must install and configure it yourself.
To enable the PostgreSQL Server Exporter:
diff --git a/doc/administration/monitoring/prometheus/redis_exporter.md b/doc/administration/monitoring/prometheus/redis_exporter.md
index 16a758c9804..41a84f1f3ed 100644
--- a/doc/administration/monitoring/prometheus/redis_exporter.md
+++ b/doc/administration/monitoring/prometheus/redis_exporter.md
@@ -10,7 +10,6 @@ The [Redis exporter](https://github.com/oliver006/redis_exporter) enables you to
various [Redis](https://redis.io) metrics. For more information on what is exported,
[read the upstream documentation](https://github.com/oliver006/redis_exporter/blob/master/README.md#whats-exported).
-NOTE: **Note:**
For installations from source you must install and configure it yourself.
To enable the Redis exporter:
diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md
index fabbfb2552e..3e16b173003 100644
--- a/doc/administration/nfs.md
+++ b/doc/administration/nfs.md
@@ -19,11 +19,10 @@ From GitLab 13.0, using NFS for Git repositories is deprecated. In GitLab 14.0,
support for NFS for Git repositories is scheduled to be removed. Upgrade to
[Gitaly Cluster](gitaly/praefect.md) as soon as possible.
-NOTE: **Note:**
-Filesystem performance has a big impact on overall GitLab
-performance, especially for actions that read or write to Git repositories. See
-[Filesystem Performance Benchmarking](operations/filesystem_benchmarking.md)
-for steps to test filesystem performance.
+Filesystem performance can impact overall GitLab performance, especially for
+actions that read or write to Git repositories. For steps you can use to test
+filesystem performance, see
+[Filesystem Performance Benchmarking](operations/filesystem_benchmarking.md).
## Known kernel version incompatibilities
@@ -119,7 +118,7 @@ To disable NFS server delegation, do the following:
1. Restart the NFS server process. For example, on CentOS run `service nfs restart`.
-NOTE: **Important note:**
+NOTE: **Note:**
The kernel bug may be fixed in
[more recent kernels with this commit](https://github.com/torvalds/linux/commit/95da1b3a5aded124dd1bda1e3cdb876184813140).
Red Hat Enterprise 7 [shipped a kernel update](https://access.redhat.com/errata/RHSA-2019:2029)
@@ -250,9 +249,9 @@ gitlab_rails['shared_path'] = '/gitlab-nfs/gitlab-data/shared'
gitlab_ci['builds_directory'] = '/gitlab-nfs/gitlab-data/builds'
```
-Run `sudo gitlab-ctl reconfigure` to start using the central location. Please
-be aware that if you had existing data you will need to manually copy/rsync it
-to these new locations and then restart GitLab.
+Run `sudo gitlab-ctl reconfigure` to start using the central location. Be aware
+that if you had existing data, you'll need to manually copy or rsync it to
+these new locations, and then restart GitLab.
### Bind mounts
@@ -307,8 +306,12 @@ by testing the following commands:
```shell
sudo mkdir /gitlab-nfs/test-dir
sudo chown git /gitlab-nfs/test-dir
-sudo chgrp gitlab-www /gitlab-nfs/test-dir
sudo chgrp root /gitlab-nfs/test-dir
+sudo chmod 0700 /gitlab-nfs/test-dir
+sudo chgrp gitlab-www /gitlab-nfs/test-dir
+sudo chmod 0751 /gitlab-nfs/test-dir
+sudo chgrp git /gitlab-nfs/test-dir
+sudo chmod 2770 /gitlab-nfs/test-dir
sudo chmod 2755 /gitlab-nfs/test-dir
sudo -u git mkdir /gitlab-nfs/test-dir/test2
sudo -u git chmod 2755 /gitlab-nfs/test-dir/test2
@@ -323,7 +326,7 @@ Any `Operation not permitted` errors means you should investigate your NFS serve
If the traffic between your NFS server and NFS client(s) is subject to port filtering
by a firewall, then you will need to reconfigure that firewall to allow NFS communication.
-[This guide from TDLP](http://tldp.org/HOWTO/NFS-HOWTO/security.html#FIREWALLS)
+[This guide from TDLP](https://tldp.org/HOWTO/NFS-HOWTO/security.html#FIREWALLS)
covers the basics of using NFS in a firewalled environment. Additionally, we encourage you to
search for and review the specific documentation for your operating system or distribution and your firewall software.
@@ -396,8 +399,8 @@ Additionally, this configuration is specifically warned against in the
>system semantics, this can cause reliability problems. Specifically, delayed (asynchronous) writes
>to the NFS server can cause data corruption problems.
-For supported database architecture, please see our documentation on
-[Configuring a Database for GitLab HA](postgresql/replication_and_failover.md).
+For supported database architecture, see our documentation about
+[configuring a database for replication and failover](postgresql/replication_and_failover.md).
<!-- ## Troubleshooting
diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md
index 0ce1ff447ec..2b714c36d93 100644
--- a/doc/administration/object_storage.md
+++ b/doc/administration/object_storage.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Enablement
+group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
@@ -61,18 +61,17 @@ must be enabled, only the following providers can be used:
- [Google Cloud Storage](#google-cloud-storage-gcs)
- [Azure Blob storage](#azure-blob-storage)
-Background upload 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
+Background upload isn't supported with the consolidated object storage
+configuration. We recommend enabling direct upload mode because it doesn't
+require a shared folder, and [this setting may become the
default](https://gitlab.com/gitlab-org/gitlab/-/issues/27331).
-NOTE: **Note:**
-Consolidated object storage configuration cannot be used for
-backups or Mattermost. See [the full table for a complete list](#storage-specific-configuration).
+Consolidated object storage configuration can't be used for backups or
+Mattermost. See the [full table for a complete list](#storage-specific-configuration).
-NOTE: **Note:**
-Enabling consolidated object storage will enable object storage for all object types.
-If you wish to use local storage for specific object types, you can [selectively disable object storages](#selectively-disabling-object-storage).
+Enabling consolidated object storage enables object storage for all object
+types. If you want to use local storage for specific object types, you can
+[selectively disable object storages](#selectively-disabling-object-storage).
Most types of objects, such as CI artifacts, LFS files, upload
attachments, and so on can be saved in object storage by specifying a single
@@ -117,7 +116,7 @@ See the section on [ETag mismatch errors](#etag-mismatch) for more details.
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = '<terraform-state>'
```
- NOTE: For GitLab 9.4 or later, if you're using AWS IAM profiles, be sure to omit the
+ For GitLab 9.4 or later, if you're using AWS IAM profiles, be sure to omit the
AWS access key and secret access key/value pairs. For example:
```ruby
@@ -262,10 +261,11 @@ Here are the valid connection parameters for GCS:
| `google_project` | GCP project name | `gcp-project-12345` |
| `google_client_email` | The email address of the service account | `foo@gcp-project-12345.iam.gserviceaccount.com` |
| `google_json_key_location` | The JSON key path | `/path/to/gcp-project-12345-abcde.json` |
+| `google_application_default` | Set to `true` to use [Google Cloud Application Default Credentials](https://cloud.google.com/docs/authentication/production#automatically) to locate service account credentials. |
-NOTE: **Note:**
-The service account must have permission to access the bucket.
-[See more](https://cloud.google.com/storage/docs/authentication)
+The service account must have permission to access the bucket. Learn more
+in Google's
+[Cloud Storage authentication documentation](https://cloud.google.com/storage/docs/authentication).
##### Google example (consolidated form)
@@ -280,6 +280,33 @@ gitlab_rails['object_store']['connection'] = {
}
```
+##### Google example with ADC (consolidated form)
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275979) in GitLab 13.6.
+
+Google Cloud Application Default Credentials (ADC) are typically
+used with GitLab to use the default service account. This eliminates the
+need to supply credentials for the instance. For example:
+
+```ruby
+gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<GOOGLE PROJECT>',
+ 'google_application_default' => true
+}
+```
+
+If you use ADC, be sure that:
+
+- The service account that you use has the
+[`iam.serviceAccounts.signBlob` permission](https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob).
+ Typically this is done by granting the `Service Account Token Creator` role to the service account.
+- Your virtual machines have the [correct access scopes to access Google Cloud APIs](https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances#changeserviceaccountandscopes). If the machines do not have the right scope, the error logs may show:
+
+ ```markdown
+ Google::Apis::ClientError (insufficientPermissions: Request had insufficient authentication scopes.)
+ ```
+
#### Azure Blob storage
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25877) in GitLab 13.4.
@@ -288,6 +315,11 @@ 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.
+Azure Blob storage can only be used with the [consolidated form](#consolidated-object-storage-configuration)
+because a single set of credentials are used to access multiple
+containers. The [storage-specific form](#storage-specific-configuration)
+is not supported. For more details, see [how to transition to consolidated form](#transition-to-consolidated-form).
+
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.
@@ -314,10 +346,9 @@ gitlab_rails['object_store']['connection'] = {
###### 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.
+For source installations, Workhorse also needs to be configured with Azure
+credentials. This isn't needed in Omnibus installs, because the Workhorse
+settings are populated from the previous settings.
1. Edit `/home/git/gitlab-workhorse/config.toml` and add or amend the following lines:
@@ -337,14 +368,14 @@ GitLab Rails and Workhorse.
#### OpenStack-compatible connection settings
-NOTE: **Note:**
-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.
+Although 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).
+
+This isn't compatible with the consolidated object storage form. OpenStack Swift
+is supported only with the storage-specific form. If you want to use the
+consolidated form, see the [S3 settings](#s3-compatible-connection-settings).
-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
+Here are the valid connection settings for the Swift API, provided by
[fog-openstack](https://github.com/fog/fog-openstack):
| Setting | Description | Default |
@@ -359,12 +390,11 @@ Here are the valid connection settings below for the Swift API, provided by
#### Rackspace Cloud Files
-NOTE: **Note:**
-This is not compatible with the consolidated object
-storage form. Rackspace Cloud is only supported with the storage-specific form.
+The following table describes the valid connection parameters for
+Rackspace Cloud, provided by [fog-rackspace](https://github.com/fog/fog-rackspace/).
-Here are the valid connection parameters for Rackspace Cloud, provided by
-[fog-rackspace](https://github.com/fog/fog-rackspace/):
+This isn't compatible with the consolidated object storage form.
+Rackspace Cloud is supported only with the storage-specific form.
| Setting | Description | example |
|---------|-------------|---------|
@@ -374,13 +404,13 @@ Here are the valid connection parameters for Rackspace Cloud, provided by
| `rackspace_region` | The Rackspace storage region to use, a three letter code from the [list of service access endpoints](https://developer.rackspace.com/docs/cloud-files/v1/general-api-info/service-access/) | `iad` |
| `rackspace_temp_url_key` | The private key you have set in the Rackspace API for [temporary URLs](https://developer.rackspace.com/docs/cloud-files/v1/use-cases/public-access-to-your-cloud-files-account/#tempurl). | `ABC123DEF456ABC123DEF456ABC123DE` |
-NOTE: **Note:**
-Regardless of whether the container has public access enabled or disabled, Fog will
-use the TempURL method to grant access to LFS objects. If you see errors in logs referencing
-instantiating storage with a `temp-url-key`, ensure that you have set the key properly
-on the Rackspace API and in `gitlab.rb`. You can verify the value of the key Rackspace
-has set by sending a GET request with token header to the service access endpoint URL
-and comparing the output of the returned headers.
+Regardless of whether the container has public access enabled or disabled, Fog
+uses the TempURL method to grant access to LFS objects. If you see error
+messages in logs that refer to instantiating storage with a `temp-url-key`,
+be sure you have set the key properly both in the Rackspace API and in
+`gitlab.rb`. You can verify the value of the key Rackspace has set by sending a
+GET request with token header to the service access endpoint URL and comparing
+the output of the returned headers.
### Object-specific configuration
@@ -488,15 +518,16 @@ gitlab_rails['uploads_object_store_remote_directory'] = 'uploads'
gitlab_rails['uploads_object_store_connection'] = { 'provider' => 'AWS', 'aws_access_key_id' => 'access_key', 'aws_secret_access_key' => 'secret' }
```
-While this provides flexibility in that it makes it possible for GitLab
+Although this provides flexibility in that it makes it possible for GitLab
to store objects across different cloud providers, it also creates
additional complexity and unnecessary redundancy. Since both GitLab
Rails and Workhorse components need access to object storage, the
consolidated form avoids excessive duplication of credentials.
-NOTE: **Note:**
-The consolidated object storage configuration is **only** used if all
-lines from the original form is omitted. To move to the consolidated form, remove the original configuration (for example, `artifacts_object_store_enabled`, `uploads_object_store_connection`, and so on.)
+The consolidated object storage configuration is used _only_ if all lines from
+the original form is omitted. To move to the consolidated form, remove the
+original configuration (for example, `artifacts_object_store_enabled`, or
+`uploads_object_store_connection`)
## Storage-specific configuration
diff --git a/doc/administration/operations/cleaning_up_redis_sessions.md b/doc/administration/operations/cleaning_up_redis_sessions.md
index a94f88439f2..8f90231a713 100644
--- a/doc/administration/operations/cleaning_up_redis_sessions.md
+++ b/doc/administration/operations/cleaning_up_redis_sessions.md
@@ -34,7 +34,7 @@ rcli() {
# This example works for Omnibus installations of GitLab 7.3 or newer. For an
# installation from source you will have to change the socket path and the
# path to redis-cli.
- sudo /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.shared_state.socket "$@"
+ sudo /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.socket "$@"
}
# test the new shell function; the response should be PONG
diff --git a/doc/administration/operations/extra_sidekiq_processes.md b/doc/administration/operations/extra_sidekiq_processes.md
index 76dc9bf5510..5de79882083 100644
--- a/doc/administration/operations/extra_sidekiq_processes.md
+++ b/doc/administration/operations/extra_sidekiq_processes.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Enablement
+group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
@@ -38,7 +38,7 @@ To start multiple processes:
process, and values in each item determine the queues it works on.
For example, the following setting creates three Sidekiq processes, one to run on
- `elastic_indexer`, one to run on `mailers`, and one process running all on queues:
+ `elastic_indexer`, one to run on `mailers`, and one process running on all queues:
```ruby
sidekiq['queue_groups'] = [
@@ -110,34 +110,29 @@ you list:
sudo gitlab-ctl reconfigure
```
-## Queue selector (experimental)
+## Queue selector
-> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/45) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.8.
+> - [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/45) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.8.
+> - [Sidekiq cluster including queue selector moved](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) to GitLab [Core](https://about.gitlab.com/pricing/#self-managed) in GitLab 12.10.
+> - [Marked as supported](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/147) in GitLab [Core](https://about.gitlab.com/pricing/#self-managed) in GitLab 13.6. Renamed from `experimental_queue_selector` to `queue_selector`.
-CAUTION: **Caution:**
-As this is marked as **experimental**, it is subject to change at any
-time, including **breaking backwards compatibility**. This is so that we
-can react to changes we need for our GitLab.com deployment. We have a
-tracking issue open to [remove the experimental
-designation](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/147)
-from this feature; please comment there if you are interested in using
-this in your own deployment.
-
-In addition to selecting queues by name, as above, the
-`experimental_queue_selector` option allows queue groups to be selected
-in a more general way using the following components:
+In addition to selecting queues by name, as above, the `queue_selector`
+option allows queue groups to be selected in a more general way using
+the following components:
- Attributes that can be selected.
- Operators used to construct a query.
+When `queue_selector` is set, all `queue_groups` must be in the queue
+selector syntax.
+
### Available attributes
- [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/261) in GitLab 13.1, `tags`.
From the [list of all available
attributes](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml),
-`experimental_queue_selector` allows selecting of queues by the
-following attributes:
+`queue_selector` allows selecting of queues by the following attributes:
- `feature_category` - the [GitLab feature
category](https://about.gitlab.com/direction/maturity/#category-maturity) the
@@ -169,8 +164,8 @@ neither of those tags.
### Available operators
-`experimental_queue_selector` supports the following operators, listed
-from highest to lowest precedence:
+`queue_selector` supports the following operators, listed from highest
+to lowest precedence:
- `|` - the logical OR operator. For example, `query_a|query_b` (where `query_a`
and `query_b` are queries made up of the other operators here) will include
@@ -201,7 +196,7 @@ In `/etc/gitlab/gitlab.rb`:
```ruby
sidekiq['enable'] = true
-sidekiq['experimental_queue_selector'] = true
+sidekiq['queue_selector'] = true
sidekiq['queue_groups'] = [
# Run all non-CPU-bound queues that are high urgency
'resource_boundary!=cpu&urgency=high',
@@ -230,7 +225,7 @@ All of the aforementioned configuration options for `sidekiq`
are available. By default, they will be configured as follows:
```ruby
-sidekiq['experimental_queue_selector'] = false
+sidekiq['queue_selector'] = false
sidekiq['interval'] = nil
sidekiq['max_concurrency'] = 50
sidekiq['min_concurrency'] = nil
@@ -327,9 +322,9 @@ Running Sidekiq cluster is the default in GitLab 13.0 and later.
```
`min_concurrency` and `max_concurrency` are independent; one can be set without
-the other. Setting `min_concurrency` to 0 will disable the limit.
+the other. Setting `min_concurrency` to `0` will disable the limit.
-For each queue group, let N be one more than the number of queues. The
+For each queue group, let `N` be one more than the number of queues. The
concurrency factor will be set to:
1. `N`, if it's between `min_concurrency` and `max_concurrency`.
diff --git a/doc/administration/operations/fast_ssh_key_lookup.md b/doc/administration/operations/fast_ssh_key_lookup.md
index 88ef69b29f2..c8830a45fb2 100644
--- a/doc/administration/operations/fast_ssh_key_lookup.md
+++ b/doc/administration/operations/fast_ssh_key_lookup.md
@@ -196,7 +196,8 @@ the database. The following instructions can be used to build OpenSSH 7.5:
yes | cp pam-ssh-conf-$timestamp /etc/pam.d/sshd
```
-1. Verify the installed version. In another window, attempt to login to the server:
+1. Verify the installed version. In another window, attempt to sign in to the
+ server:
```shell
ssh -v <your-centos-machine>
@@ -204,7 +205,7 @@ the database. The following instructions can be used to build OpenSSH 7.5:
You should see a line that reads: "debug1: Remote protocol version 2.0, remote software version OpenSSH_7.5"
- If not, you may need to restart `sshd` (e.g. `systemctl restart sshd.service`).
+ If not, you may need to restart `sshd` (for example, `systemctl restart sshd.service`).
1. *IMPORTANT!* Open a new SSH session to your server before exiting to make
sure everything is working! If you need to downgrade, simple install the
diff --git a/doc/administration/operations/index.md b/doc/administration/operations/index.md
index aaeb8c723d0..864bbb3233e 100644
--- a/doc/administration/operations/index.md
+++ b/doc/administration/operations/index.md
@@ -13,6 +13,9 @@ Keep your GitLab instance up and running smoothly.
you have been running a large GitLab server (thousands of users) since before
GitLab 7.3 we recommend cleaning up stale sessions to compact the Redis
database after you upgrade to GitLab 7.3.
+- [Rake tasks](../../raketasks/README.md): Tasks for common administration and operational processes such as
+ [cleaning up unneeded items from GitLab instance](../../raketasks/cleanup.md), integrity checks,
+ and more.
- [Moving repositories](moving_repositories.md): Moving all repositories managed
by GitLab to another file system or another server.
- [Sidekiq MemoryKiller](sidekiq_memory_killer.md): Configure Sidekiq MemoryKiller
@@ -28,6 +31,8 @@ Keep your GitLab instance up and running smoothly.
performance can have a big impact on GitLab performance, especially for actions
that read or write Git repositories. This information will help benchmark
filesystem performance against known good and bad real-world systems.
+- [The Rails Console](rails_console.md): Provides a way to interact with your GitLab instance from the command line.
+ Used for troubleshooting a problem or retrieving some data that can only be done through direct access to GitLab.
- [ChatOps Scripts](https://gitlab.com/gitlab-com/chatops): The GitLab.com Infrastructure team uses this repository to house
common ChatOps scripts they use to troubleshoot and maintain the production instance of GitLab.com.
These scripts are likely useful to administrators of GitLab instances of all sizes.
diff --git a/doc/administration/operations/moving_repositories.md b/doc/administration/operations/moving_repositories.md
index 94eea1e25b8..b311bee1a5b 100644
--- a/doc/administration/operations/moving_repositories.md
+++ b/doc/administration/operations/moving_repositories.md
@@ -1,26 +1,69 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Gitaly
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+type: reference
---
-# Moving repositories managed by GitLab
+# Moving repositories managed by GitLab **(CORE ONLY)**
Sometimes you need to move all repositories managed by GitLab to
-another filesystem or another server. In this document we will look
+another file system or another server.
+
+## Moving data within a GitLab instance
+
+The GitLab API is the recommended way to move Git repositories:
+
+- Between servers.
+- Between different storage.
+- From single-node Gitaly to Gitaly Cluster.
+
+For more information, see:
+
+- [Configuring additional storage for Gitaly](../gitaly/index.md#network-architecture). Within this
+ example, additional storage called `storage1` and `storage2` is configured.
+- [The API documentation](../../api/project_repository_storage_moves.md) details the endpoints for
+ querying and scheduling repository moves.
+- [Migrate existing repositories to Gitaly Cluster](../gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster).
+
+### Limitations
+
+Read more in the [API documentation](../../api/project_repository_storage_moves.md#limitations).
+
+## Migrating to another GitLab instance
+
+[Using the API](#moving-data-within-a-gitlab-instance) isn't an option if you are migrating to a new
+GitLab environment, for example:
+
+- From a single-node GitLab to a scaled-out architecture.
+- From a GitLab instance in your private datacenter to a cloud provider.
+
+The rest of the document looks
at some of the ways you can copy all your repositories from
`/var/opt/gitlab/git-data/repositories` to `/mnt/gitlab/repositories`.
-We will look at three scenarios: the target directory is empty, the
-target directory contains an outdated copy of the repositories, and
-how to deal with thousands of repositories.
+We look at three scenarios:
+
+- The target directory is empty.
+- The target directory contains an outdated copy of the repositories.
+- How to deal with thousands of repositories.
+
+DANGER: **Warning:**
+Each of the approaches we list can or does overwrite data in the target directory
+`/mnt/gitlab/repositories`. Do not mix up the source and the target.
+
+### Recommended approach in all cases
+
+GitLab's [backup and restore capability](../../raketasks/backup_restore.md) should be used. Git
+repositories are accessed, managed, and stored on GitLab servers by Gitaly as a database. Data loss
+can result from directly accessing and copying Gitaly's files using tools like `rsync`.
-DANGER: **Danger:**
-Each of the approaches we list can/will overwrite data in the
-target directory `/mnt/gitlab/repositories`. Do not mix up the
-source and the target.
+- From GitLab 13.3, backup performance can be improved by
+ [processing multiple repositories concurrently](../../raketasks/backup_restore.md#back-up-git-repositories-concurrently).
+- Backups can be created of just the repositories using the
+ [skip feature](../../raketasks/backup_restore.md#excluding-specific-directories-from-the-backup).
-## Target directory is empty: use a `tar` pipe
+### Target directory is empty: use a `tar` pipe
If the target directory `/mnt/gitlab/repositories` is empty the
simplest thing to do is to use a `tar` pipe. This method has low
@@ -35,7 +78,7 @@ sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
If you want to see progress, replace `-xf` with `-xvf`.
-### `tar` pipe to another server
+#### `tar` pipe to another server
You can also use a `tar` pipe to copy data to another server. If your
`git` user has SSH access to the new server as `git@newserver`, you
@@ -47,15 +90,19 @@ sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
```
If you want to compress the data before it goes over the network
-(which will cost you CPU cycles) you can replace `ssh` with `ssh -C`.
+(which costs you CPU cycles) you can replace `ssh` with `ssh -C`.
-## The target directory contains an outdated copy of the repositories: use `rsync`
+### The target directory contains an outdated copy of the repositories: use `rsync`
+
+DANGER: **Warning:**
+Using `rsync` to migrate Git data can cause data loss and repository corruption.
+[These instructions are being reviewed](https://gitlab.com/gitlab-org/gitlab/-/issues/270422).
If the target directory already contains a partial / outdated copy
of the repositories it may be wasteful to copy all the data again
with `tar`. In this scenario it is better to use `rsync`. This utility
is either already installed on your system or easily installable
-via `apt`, `yum`, etc.
+via `apt`, `yum`, and so on.
```shell
sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
@@ -66,7 +113,11 @@ The `/.` in the command above is very important, without it you can
easily get the wrong directory structure in the target directory.
If you want to see progress, replace `-a` with `-av`.
-### Single `rsync` to another server
+#### Single `rsync` to another server
+
+DANGER: **Warning:**
+Using `rsync` to migrate Git data can cause data loss and repository corruption.
+[These instructions are being reviewed](https://gitlab.com/gitlab-org/gitlab/-/issues/270422).
If the `git` user on your source system has SSH access to the target
server you can send the repositories over the network with `rsync`.
@@ -76,7 +127,11 @@ sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
git@newserver:/mnt/gitlab/repositories'
```
-## Thousands of Git repositories: use one `rsync` per repository
+### Thousands of Git repositories: use one `rsync` per repository
+
+DANGER: **Warning:**
+Using `rsync` to migrate Git data can cause data loss and repository corruption.
+[These instructions are being reviewed](https://gitlab.com/gitlab-org/gitlab/-/issues/270422).
Every time you start an `rsync` job it has to inspect all files in
the source directory, all files in the target directory, and then
@@ -86,20 +141,20 @@ for your GitLab server. In cases like this you can make `rsync`'s
life easier by dividing its work in smaller pieces, and sync one
repository at a time.
-In addition to `rsync` we will use [GNU
-Parallel](http://www.gnu.org/software/parallel/). This utility is
-not included in GitLab so you need to install it yourself with `apt`
-or `yum`. Also note that the GitLab scripts we used below were added
-in GitLab 8.1.
+In addition to `rsync` we use [GNU Parallel](http://www.gnu.org/software/parallel/).
+This utility is not included in GitLab so you need to install it yourself with `apt`
+or `yum`. Also note that the GitLab scripts we used below were added in GitLab 8.1.
**This process does not clean up repositories at the target location that no
-longer exist at the source.** If you start using your GitLab instance with
-`/mnt/gitlab/repositories`, you need to run `gitlab-rake gitlab:cleanup:repos`
-after switching to the new repository storage directory.
+longer exist at the source.**
-### Parallel `rsync` for all repositories known to GitLab
+#### Parallel `rsync` for all repositories known to GitLab
-This will sync repositories with 10 `rsync` processes at a time. We keep
+DANGER: **Warning:**
+Using `rsync` to migrate Git data can cause data loss and repository corruption.
+[These instructions are being reviewed](https://gitlab.com/gitlab-org/gitlab/-/issues/270422).
+
+This syncs repositories with 10 `rsync` processes at a time. We keep
track of progress so that the transfer can be restarted if necessary.
First we create a new directory, owned by `git`, to hold transfer
@@ -154,7 +209,11 @@ cat /home/git/transfer-logs/* | sort | uniq -u |\
`
```
-### Parallel `rsync` only for repositories with recent activity
+#### Parallel `rsync` only for repositories with recent activity
+
+DANGER: **Warning:**
+Using `rsync` to migrate Git data can cause data loss and repository corruption.
+[These instructions are being reviewed](https://gitlab.com/gitlab-org/gitlab/-/issues/270422).
Suppose you have already done one sync that started after 2015-10-1 12:00 UTC.
Then you might only want to sync repositories that were changed via GitLab
diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md
index 2d53a790428..5104b65c86d 100644
--- a/doc/administration/operations/puma.md
+++ b/doc/administration/operations/puma.md
@@ -33,7 +33,7 @@ will _not_ carry over automatically, due to differences between the two applicat
deployments, see [Configuring Puma Settings](https://docs.gitlab.com/omnibus/settings/puma.html#configuring-puma-settings).
For Helm based deployments, see the [Webservice Chart documentation](https://docs.gitlab.com/charts/charts/gitlab/webservice/index.html).
-Additionally we strongly recommend that multi-node deployments [configure their load balancers to utilize the readiness check](../load_balancer.md#readiness-check) due to a difference between Unicorn and Puma in how they handle connections during a restart of the service.
+Additionally we strongly recommend that multi-node deployments [configure their load balancers to use the readiness check](../load_balancer.md#readiness-check) due to a difference between Unicorn and Puma in how they handle connections during a restart of the service.
## Performance caveat when using Puma with Rugged
diff --git a/doc/administration/operations/rails_console.md b/doc/administration/operations/rails_console.md
index 9db9a885baf..dac36135a8e 100644
--- a/doc/administration/operations/rails_console.md
+++ b/doc/administration/operations/rails_console.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# The Rails Console
The [Rails console](https://guides.rubyonrails.org/command_line.html#rails-console).
diff --git a/doc/administration/operations/sidekiq_memory_killer.md b/doc/administration/operations/sidekiq_memory_killer.md
index d99468411e3..0de8b681dd8 100644
--- a/doc/administration/operations/sidekiq_memory_killer.md
+++ b/doc/administration/operations/sidekiq_memory_killer.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Enablement
+group: Memory
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 56b7f01e1ad..541bd99084c 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -170,7 +170,7 @@ If your certificate provider provides the CA Bundle certificates, append them to
1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
1. Make the relevant changes in NGINX as well (domain, port, TLS certificates path).
-Users should now be able to login to the Container Registry with their GitLab
+Users should now be able to sign in to the Container Registry with their GitLab
credentials using:
```shell
@@ -234,7 +234,7 @@ registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/certificate.key"
1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
1. Make the relevant changes in NGINX as well (domain, port, TLS certificates path).
-Users should now be able to login to the Container Registry using their GitLab
+Users should now be able to sign in to the Container Registry using their GitLab
credentials:
```shell
@@ -397,6 +397,20 @@ To configure the `s3` storage driver in Omnibus:
}
```
+ To avoid using static credentials, use an
+ [IAM role](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)
+ and omit `accesskey` and `secretkey`. Make sure that your IAM profile follows
+ [the permissions documented by Docker](https://docs.docker.com/registry/storage-drivers/s3/#s3-permission-scopes).
+
+ ```ruby
+ registry['storage'] = {
+ 's3' => {
+ 'bucket' => 'your-s3-bucket',
+ 'region' => 'your-s3-region'
+ }
+ }
+ ```
+
- `regionendpoint` is only required when configuring an S3 compatible service such as MinIO. It takes a URL such as `http://127.0.0.1:9000`.
- `your-s3-bucket` should be the name of a bucket that exists, and can't include subdirectories.
@@ -412,8 +426,8 @@ when you [deployed your Docker registry](https://docs.docker.com/registry/deploy
```yaml
storage:
s3:
- accesskey: 's3-access-key'
- secretkey: 's3-secret-key-for-access-key'
+ accesskey: 's3-access-key' # Not needed if IAM role used
+ secretkey: 's3-secret-key-for-access-key' # Not needed if IAM role used
bucket: 'your-s3-bucket'
region: 'your-s3-region'
regionendpoint: 'your-s3-regionendpoint'
@@ -471,7 +485,7 @@ you can pull from the Container Registry, but you cannot push.
[`--dryrun`](https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html)
flag and run the command.
- DANGER: **Danger:**
+ DANGER: **Warning:**
The [`--delete`](https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html)
flag deletes files that exist in the destination but not in the source.
If you swap the source and destination, all data in the Registry is deleted.
@@ -584,7 +598,7 @@ on how to achieve that.
## Use an external container registry with GitLab as an auth endpoint
If you use an external container registry, some features associated with the
-container registry may be unavailable or have [inherent risks](./../../user/packages/container_registry/index.md#use-with-external-container-registries).
+container registry may be unavailable or have [inherent risks](../../user/packages/container_registry/index.md#use-with-external-container-registries).
**Omnibus GitLab**
@@ -815,23 +829,23 @@ If you changed the location of the Container Registry `config.yml`:
sudo gitlab-ctl registry-garbage-collect /path/to/config.yml
```
-You may also [remove all unreferenced manifests](#removing-unused-layers-not-referenced-by-manifests),
+You may also [remove all untagged manifests and unreferenced layers](#removing-untagged-manifests-and-unreferenced-layers),
although this is a way more destructive operation, and you should first
understand the implications.
-### Removing unused layers not referenced by manifests
+### Removing untagged manifests and unreferenced layers
> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/3097) in Omnibus GitLab 11.10.
-DANGER: **Danger:**
+DANGER: **Warning:**
This is a destructive operation.
The GitLab Container Registry follows the same default workflow as Docker Distribution:
-retain all layers, even ones that are unreferenced directly to allow all content
-to be accessed using context addressable identifiers.
+retain untagged manifests and all layers, even ones that are not referenced directly. All content
+can be accessed by using context addressable identifiers.
-However, in most workflows, you don't care about old layers if they are not directly
-referenced by the registry tag. The `registry-garbage-collect` command supports the
+However, in most workflows, you don't care about untagged manifests and old layers if they are not directly
+referenced by a tagged manifest. The `registry-garbage-collect` command supports the
`-m` switch to allow you to remove all unreferenced manifests and layers that are
not directly accessible via `tag`:
@@ -839,6 +853,8 @@ not directly accessible via `tag`:
sudo gitlab-ctl registry-garbage-collect -m
```
+Without the `-m` flag, the Container Registry only removes layers that are not referenced by any manifest, tagged or not.
+
Since this is a way more destructive operation, this behavior is disabled by default.
You are likely expecting this way of operation, but before doing that, ensure
that you have backed up all registry data.
@@ -932,6 +948,8 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
5 4 * * 0 root gitlab-ctl registry-garbage-collect
```
+You may want to add the `-m` flag to [remove untagged manifests and unreferenced layers](#removing-untagged-manifests-and-unreferenced-layers).
+
## Troubleshooting
Before diving in to the following sections, here's some basic troubleshooting:
@@ -1234,8 +1252,8 @@ This will launch the Docker daemon and proxy all connections through mitmproxy.
#### Running the Docker client
-Now that we have mitmproxy and Docker running, we can attempt to login and push
-a container image. You may need to run as root to do this. For example:
+Now that we have mitmproxy and Docker running, we can attempt to sign in and
+push a container image. You may need to run as root to do this. For example:
```shell
docker login s3-testing.myregistry.com:5050
diff --git a/doc/administration/packages/dependency_proxy.md b/doc/administration/packages/dependency_proxy.md
index fba3d51f741..56b39658dc2 100644
--- a/doc/administration/packages/dependency_proxy.md
+++ b/doc/administration/packages/dependency_proxy.md
@@ -4,11 +4,12 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# GitLab Dependency Proxy administration **(PREMIUM ONLY)**
+# GitLab Dependency Proxy administration
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.11.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.11.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/273655) to [GitLab Core](https://about.gitlab.com/pricing/) in GitLab 13.6.
-GitLab can be utilized as a dependency proxy for a variety of common package managers.
+GitLab can be used as a dependency proxy for a variety of common package managers.
This is the administration documentation. If you want to learn how to use the
dependency proxies, see the [user guide](../../user/packages/dependency_proxy/index.md).
diff --git a/doc/administration/packages/index.md b/doc/administration/packages/index.md
index 0b3a7ae9fa5..4af0de864ca 100644
--- a/doc/administration/packages/index.md
+++ b/doc/administration/packages/index.md
@@ -6,26 +6,50 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Package Registry administration
-GitLab Packages allows organizations to utilize GitLab as a private repository
+GitLab Packages allows organizations to use GitLab as a private repository
for a variety of common package managers. Users are able to build and publish
packages, which can be easily consumed as a dependency in downstream projects.
The Packages feature allows GitLab to act as a repository for the following:
-| Software repository | Description | Available in GitLab version |
-| ------------------- | ----------- | --------------------------- |
-| [PyPI Repository](../../user/packages/pypi_repository/index.md) | The GitLab PyPI Repository enables every project in GitLab to have its own space to store [PyPI](https://pypi.org/) packages. | 12.10+ |
-| [Composer Repository](../../user/packages/composer_repository/index.md) | The GitLab Composer Repository enables every project in GitLab to have its own space to store [Composer](https://getcomposer.org/) packages. | 13.1+ |
-| [NuGet Repository](../../user/packages/nuget_repository/index.md) | The GitLab NuGet Repository enables every project in GitLab to have its own space to store [NuGet](https://www.nuget.org/) packages. | 12.8+ |
-| [Conan Repository](../../user/packages/conan_repository/index.md) | The GitLab Conan Repository enables every project in GitLab to have its own space to store [Conan](https://conan.io/) packages. | 12.4+ |
-| [Maven Repository](../../user/packages/maven_repository/index.md) | The GitLab Maven Repository enables every project in GitLab to have its own space to store [Maven](https://maven.apache.org/) packages. | 11.3+ |
-| [NPM Registry](../../user/packages/npm_registry/index.md) | The GitLab NPM Registry enables every project in GitLab to have its own space to store [NPM](https://www.npmjs.com/) packages. | 11.7+ |
-| [Go Proxy](../../user/packages/go_proxy/index.md) | The Go proxy for GitLab enables every project in GitLab to be fetched with the [Go proxy protocol](https://proxy.golang.org/). | 13.1+ |
-| [Generic packages](../../user/packages/generic_packages/index.md) | Store arbitrary files, like release binaries. | 13.5+ |
-
-Don't you see your package management system supported yet?
-Please consider contributing
-to GitLab. This [development documentation](../../development/packages.md) will guide you through the process.
+The Package Registry supports the following formats:
+
+<div class="row">
+<div class="col-md-9">
+<table align="left" style="width:50%">
+<tr style="background:#dfdfdf"><th>Package type</th><th>GitLab version</th></tr>
+<tr><td><a href="https://docs.gitlab.com/ee/user/packages/composer_repository/index.html">Composer</a></td><td>13.2+</td></tr>
+<tr><td><a href="https://docs.gitlab.com/ee/user/packages/conan_repository/index.html">Conan</a></td><td>12.6+</td></tr>
+<tr><td><a href="https://docs.gitlab.com/ee/user/packages/go_proxy/index.html">Go</a></td><td>13.1+</td></tr>
+<tr><td><a href="https://docs.gitlab.com/ee/user/packages/maven_repository/index.html">Maven</a></td><td>11.3+</td></tr>
+<tr><td><a href="https://docs.gitlab.com/ee/user/packages/npm_registry/index.html">NPM</a></td><td>11.7+</td></tr>
+<tr><td><a href="https://docs.gitlab.com/ee/user/packages/nuget_repository/index.html">NuGet</a></td><td>12.8+</td></tr>
+<tr><td><a href="https://docs.gitlab.com/ee/user/packages/pypi_repository/index.html">PyPI</a></td><td>12.10+</td></tr>
+<tr><td><a href="https://docs.gitlab.com/ee/user/packages/generic_packages/index.html">Generic packages</a></td><td>13.5+</td></tr>
+</table>
+</div>
+</div>
+
+## Accepting contributions
+
+The below table lists formats that are not supported, but are accepting Community contributions for. Consider contributing to GitLab. This [development documentation](../../development/packages.md) will
+guide you through the process.
+
+| Format | Status |
+| ------ | ------ |
+| Chef | [#36889](https://gitlab.com/gitlab-org/gitlab/-/issues/36889) |
+| CocoaPods | [#36890](https://gitlab.com/gitlab-org/gitlab/-/issues/36890) |
+| Conda | [#36891](https://gitlab.com/gitlab-org/gitlab/-/issues/36891) |
+| CRAN | [#36892](https://gitlab.com/gitlab-org/gitlab/-/issues/36892) |
+| Debian | [WIP: Merge Request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44746) |
+| Opkg | [#36894](https://gitlab.com/gitlab-org/gitlab/-/issues/36894) |
+| P2 | [#36895](https://gitlab.com/gitlab-org/gitlab/-/issues/36895) |
+| Puppet | [#36897](https://gitlab.com/gitlab-org/gitlab/-/issues/36897) |
+| RPM | [#5932](https://gitlab.com/gitlab-org/gitlab/-/issues/5932) |
+| RubyGems | [#803](https://gitlab.com/gitlab-org/gitlab/-/issues/803) |
+| SBT | [#36898](https://gitlab.com/gitlab-org/gitlab/-/issues/36898) |
+| Terraform | [WIP: Merge Request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834) |
+| Vagrant | [#36899](https://gitlab.com/gitlab-org/gitlab/-/issues/36899) |
## Enabling the Packages feature
@@ -58,6 +82,18 @@ To enable the Packages feature:
1. [Restart GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab") for the changes to take effect.
+**Helm Chart installations**
+
+1. After the installation is complete, you will have to configure the `packages`
+ section in `global.appConfig.packages`. Set to `true` to enable it:
+
+ ```yaml
+ packages:
+ enabled: true
+ ```
+
+1. [Restart GitLab](../restart_gitlab.md#helm-chart-installations "How to reconfigure Helm GitLab") for the changes to take effect.
+
## Changing the storage path
By default, the packages are stored locally, but you can change the default
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 9f72293a730..0ebeb96d247 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -415,9 +415,6 @@ internet connectivity is gated by a proxy. To use a proxy for GitLab Pages:
### Using a custom Certificate Authority (CA)
-NOTE: **Note:**
-[Before 13.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4411), when using Omnibus, a [workaround was required](https://docs.gitlab.com/13.1/ee/administration/pages/index.html#using-a-custom-certificate-authority-ca).
-
When using certificates issued by a custom CA, [Access Control](../../user/project/pages/pages_access_control.md#gitlab-pages-access-control) and
the [online view of HTML job artifacts](../../ci/pipelines/job_artifacts.md#browsing-artifacts)
will fail to work if the custom CA is not recognized.
@@ -462,6 +459,34 @@ are stored.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+Alternatively, if you have existing Pages deployed you can follow
+the below steps to do a no downtime transfer to a new storage location.
+
+1. Pause Pages deployments by setting the following in `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ sidekiq['experimental_queue_selector'] = true
+ sidekiq['queue_groups'] = [
+ "feature_category!=pages"
+ ]
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. `rsync` contents from the current storage location to the new storage location: `sudo rsync -avzh --progress /var/opt/gitlab/gitlab-rails/shared/pages/ /mnt/storage/pages`
+1. Set the new storage location in `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['pages_path'] = "/mnt/storage/pages"
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Verify Pages are still being served up as expected.
+1. Unpause Pages deployments by removing from `/etc/gitlab/gitlab.rb` the `sidekiq` setting set above.
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Trigger a new Pages deployment and verify it's working as expected.
+1. Remove the old Pages storage location: `sudo rm -rf /var/opt/gitlab/gitlab-rails/shared/pages`
+1. Verify Pages are still being served up as expected.
+
## Configure listener for reverse proxy requests
Follow the steps below to configure the proxy listener of GitLab Pages. [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2533) in
@@ -514,7 +539,7 @@ your main application server.
To configure GitLab Pages on a separate server:
-DANGER: **Danger:**
+DANGER: **Warning:**
The following procedure includes steps to back up and edit the
`gitlab-secrets.json` file. This file contains secrets that control
database encryption. Proceed with caution.
@@ -528,7 +553,6 @@ database encryption. Proceed with caution.
1. On the **GitLab server**, to enable Pages, add the following to `/etc/gitlab/gitlab.rb`:
```ruby
- gitlab_pages['enable'] = true
pages_external_url "http://<pages_server_URL>"
```
@@ -559,18 +583,11 @@ database encryption. Proceed with caution.
to include:
```ruby
- external_url 'http://<gitlab_server_IP_or_URL>'
+ roles ['pages_role']
+
pages_external_url "http://<pages_server_URL>"
- postgresql['enable'] = false
- redis['enable'] = false
- prometheus['enable'] = false
- puma['enable'] = false
- sidekiq['enable'] = false
- gitlab_workhorse['enable'] = false
- gitaly['enable'] = false
- alertmanager['enable'] = false
- node_exporter['enable'] = false
- gitlab_rails['auto_migrate'] = false
+
+ gitlab_pages['gitlab_server'] = 'http://<gitlab_server_IP_or_URL>'
```
1. Create a backup of the secrets file on the **Pages server**:
diff --git a/doc/administration/polling.md b/doc/administration/polling.md
index a1077614677..17b8045b51f 100644
--- a/doc/administration/polling.md
+++ b/doc/administration/polling.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Polling configuration
The GitLab UI polls for updates for different resources (issue notes, issue
diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md
index 0a40b61fd3c..a29815672e5 100644
--- a/doc/administration/postgresql/replication_and_failover.md
+++ b/doc/administration/postgresql/replication_and_failover.md
@@ -579,18 +579,19 @@ in the Troubleshooting section before proceeding.
### Ensure GitLab is running
-At this point, your GitLab instance should be up and running. Verify you are
-able to login, and create issues and merge requests. If you have troubles check
+At this point, your GitLab instance should be up and running. Verify you're able
+to sign in, and create issues and merge requests. If you encounter issues, see
the [Troubleshooting section](#troubleshooting).
## Example configuration
-Here we'll show you some fully expanded example configurations.
+This section describes several fully expanded example configurations.
### Example recommended setup
-This example uses 3 Consul servers, 3 PgBouncer servers (with associated internal load balancer),
-3 PostgreSQL servers, and 1 application node.
+This example uses three Consul servers, three PgBouncer servers (with an
+associated internal load balancer), three PostgreSQL servers, and one
+application node.
We start with all servers on the same 10.6.0.0/16 private network range, they
can connect to each freely other on those addresses.
diff --git a/doc/administration/pseudonymizer.md b/doc/administration/pseudonymizer.md
index 22543a5c743..41a7ec087ac 100644
--- a/doc/administration/pseudonymizer.md
+++ b/doc/administration/pseudonymizer.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Pseudonymizer **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5532) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.1.
@@ -44,7 +50,6 @@ To configure the pseudonymizer, you need to:
}
```
- NOTE: **Note:**
If you are using AWS IAM profiles, be sure to omit the AWS access key and secret access key/value pairs.
```ruby
diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md
index bdccd6d5fe9..f61a3107b3d 100644
--- a/doc/administration/raketasks/check.md
+++ b/doc/administration/raketasks/check.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Integrity check Rake task **(CORE ONLY)**
GitLab provides Rake tasks to check the integrity of various components.
diff --git a/doc/administration/raketasks/doctor.md b/doc/administration/raketasks/doctor.md
index c97aa5a4de1..e6a6751f199 100644
--- a/doc/administration/raketasks/doctor.md
+++ b/doc/administration/raketasks/doctor.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Doctor Rake tasks **(CORE ONLY)**
This is a collection of tasks to help investigate and repair
@@ -15,7 +21,6 @@ Automatic resolution is not yet implemented. If you have values that
cannot be decrypted, you can follow steps to reset them, see our
docs on what to do [when the secrets file is lost](../../raketasks/backup_restore.md#when-the-secrets-file-is-lost).
-NOTE: **Note:**
This can take a very long time, depending on the size of your
database, as it checks all rows in all tables.
diff --git a/doc/administration/raketasks/geo.md b/doc/administration/raketasks/geo.md
index 885d19903ed..0ee6fd8fc75 100644
--- a/doc/administration/raketasks/geo.md
+++ b/doc/administration/raketasks/geo.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Geo Rake Tasks **(PREMIUM ONLY)**
The following Rake tasks are for [Geo installations](../geo/index.md).
diff --git a/doc/administration/raketasks/github_import.md b/doc/administration/raketasks/github_import.md
index 7f673a2c850..d549110c32f 100644
--- a/doc/administration/raketasks/github_import.md
+++ b/doc/administration/raketasks/github_import.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitHub import **(CORE ONLY)**
> [Introduced]( https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10308) in GitLab 9.1.
diff --git a/doc/administration/raketasks/ldap.md b/doc/administration/raketasks/ldap.md
index 6d04a786d3a..821a72291fd 100644
--- a/doc/administration/raketasks/ldap.md
+++ b/doc/administration/raketasks/ldap.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# LDAP Rake tasks **(CORE ONLY)**
The following are LDAP-related Rake tasks.
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
index 553afba78e3..b93442be0a1 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Maintenance Rake tasks **(CORE ONLY)**
GitLab provides Rake tasks for general maintenance.
@@ -124,7 +130,6 @@ sudo gitlab-rake gitlab:check
bundle exec rake gitlab:check RAILS_ENV=production
```
-NOTE: **Note:**
Use `SANITIZE=true` for `gitlab:check` if you want to omit project names from the output.
Example output:
@@ -267,7 +272,7 @@ clear it.
To clear all exclusive leases:
-DANGER: **Danger:**
+DANGER: **Warning:**
Don't run it while GitLab or Sidekiq is running
```shell
diff --git a/doc/administration/raketasks/project_import_export.md b/doc/administration/raketasks/project_import_export.md
index 51e0e2e46b6..d83ab6e5cee 100644
--- a/doc/administration/raketasks/project_import_export.md
+++ b/doc/administration/raketasks/project_import_export.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Project import/export administration **(CORE ONLY)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3050) in GitLab 8.9.
diff --git a/doc/administration/raketasks/storage.md b/doc/administration/raketasks/storage.md
index 896eafeb5f3..9b15f5ed4de 100644
--- a/doc/administration/raketasks/storage.md
+++ b/doc/administration/raketasks/storage.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Repository storage Rake tasks **(CORE ONLY)**
This is a collection of Rake tasks to help you list and migrate
@@ -68,7 +74,7 @@ To have a summary and then a list of projects and their attachments using hashed
## Migrate to hashed storage
-NOTE: **Note:**
+DANGER: **Deprecated:**
In GitLab 13.0, [hashed storage](../repository_storage_types.md#hashed-storage)
is enabled by default and the legacy storage is deprecated.
Support for legacy storage will be removed in GitLab 14.0. If you're on GitLab
@@ -109,7 +115,6 @@ If you find it necessary, you can run this migration script again to schedule mi
Any error or warning will be logged in Sidekiq's log file.
-NOTE: **Note:**
If [Geo](../geo/index.md) is enabled, each project that is successfully migrated
generates an event to replicate the changes on any **secondary** nodes.
@@ -118,7 +123,7 @@ commands below that helps you inspect projects and attachments in both legacy an
## Rollback from hashed storage to legacy storage
-NOTE: **Deprecated:**
+DANGER: **Deprecated:**
In GitLab 13.0, [hashed storage](../repository_storage_types.md#hashed-storage)
is enabled by default and the legacy storage is deprecated.
Support for legacy storage will be removed in GitLab 14.0. If you're on GitLab
diff --git a/doc/administration/raketasks/uploads/migrate.md b/doc/administration/raketasks/uploads/migrate.md
index 8d61beea597..075b27fb70d 100644
--- a/doc/administration/raketasks/uploads/migrate.md
+++ b/doc/administration/raketasks/uploads/migrate.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Uploads migrate Rake tasks **(CORE ONLY)**
There is a Rake task for migrating uploads between different storage types.
@@ -10,11 +16,10 @@ There is a Rake task for migrating uploads between different storage types.
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).
-
-NOTE: **Note:**
All of the processing will be done in a background worker and requires **no downtime**.
+Read more about using [object storage with GitLab](../../object_storage.md).
+
### All-in-one Rake task
GitLab provides a wrapper Rake task that migrates all uploaded files (for example avatars, logos,
@@ -93,7 +98,6 @@ gitlab-rake "gitlab:uploads:migrate[DesignManagement::DesignV432x230Uploader, De
**Source Installation**
-NOTE: **Note:**
Use `RAILS_ENV=production` for every task.
```shell
diff --git a/doc/administration/raketasks/uploads/sanitize.md b/doc/administration/raketasks/uploads/sanitize.md
index 54aa62059cf..4f7c99babd8 100644
--- a/doc/administration/raketasks/uploads/sanitize.md
+++ b/doc/administration/raketasks/uploads/sanitize.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Uploads sanitize Rake tasks **(CORE ONLY)**
In GitLab 11.9 and later, EXIF data is automatically stripped from JPG or TIFF image uploads.
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index 7910905ce54..9f522e0d599 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -836,6 +836,12 @@ a node and change its status from primary to replica (and vice versa).
# Set up password authentication for Redis (use the same password in all nodes).
redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER'
+ # Set the Redis Cache instance as an LRU
+ # 90% of available RAM in MB
+ redis['maxmemory'] = '13500mb'
+ redis['maxmemory_policy'] = "allkeys-lru"
+ redis['maxmemory_samples'] = 5
+
## Enable service discovery for Prometheus
consul['enable'] = true
consul['monitoring_service_discovery'] = true
@@ -897,6 +903,12 @@ You can specify multiple roles, like sentinel and Redis, as:
# to `6379`.
#redis['master_port'] = 6379
+ # Set the Redis Cache instance as an LRU
+ # 90% of available RAM in MB
+ redis['maxmemory'] = '13500mb'
+ redis['maxmemory_policy'] = "allkeys-lru"
+ redis['maxmemory_samples'] = 5
+
## Enable service discovery for Prometheus
consul['enable'] = true
consul['monitoring_service_discovery'] = true
@@ -1335,6 +1347,13 @@ To configure the Sentinel Queues server:
## Configure Gitaly
+NOTE: **Note:**
+[Gitaly Cluster](../gitaly/praefect.md) support
+for the Reference Architectures is being
+worked on as a [collaborative effort](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/1) between the Quality Engineering and Gitaly teams. When this component has been verified
+some Architecture specs will likely change as a result to support the new
+and improved designed.
+
[Gitaly](../gitaly/index.md) server node requirements are dependent on data,
specifically the number of projects and those projects' sizes. It's recommended
that a Gitaly server node stores no more than 5 TB of data. Although this
@@ -1988,7 +2007,7 @@ on what features you intend to use:
| [Merge request diffs](../merge_request_diffs.md#using-object-storage) | Yes |
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
-| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM ONLY)** | Yes |
+| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | 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) | Yes |
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index bb6e2eb4376..b106f7bced1 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -836,6 +836,12 @@ a node and change its status from primary to replica (and vice versa).
# Set up password authentication for Redis (use the same password in all nodes).
redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER'
+ # Set the Redis Cache instance as an LRU
+ # 90% of available RAM in MB
+ redis['maxmemory'] = '13500mb'
+ redis['maxmemory_policy'] = "allkeys-lru"
+ redis['maxmemory_samples'] = 5
+
## Enable service discovery for Prometheus
consul['enable'] = true
consul['monitoring_service_discovery'] = true
@@ -897,6 +903,12 @@ You can specify multiple roles, like sentinel and Redis, as:
# to `6379`.
#redis['master_port'] = 6379
+ # Set the Redis Cache instance as an LRU
+ # 90% of available RAM in MB
+ redis['maxmemory'] = '13500mb'
+ redis['maxmemory_policy'] = "allkeys-lru"
+ redis['maxmemory_samples'] = 5
+
## Enable service discovery for Prometheus
consul['enable'] = true
consul['monitoring_service_discovery'] = true
@@ -1225,7 +1237,7 @@ To configure the Sentinel Queues server:
1. SSH in to the server that will host Sentinel.
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to both follow _only_ installation steps 1 and 2
- on the page, and to select the correct Omnibus package, with the same version
+ on the page, and to select the correct Omnibus GitLab package, with the same version
and type (Community or Enterprise editions) as your current install.
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
@@ -1335,6 +1347,13 @@ To configure the Sentinel Queues server:
## Configure Gitaly
+NOTE: **Note:**
+[Gitaly Cluster](../gitaly/praefect.md) support
+for the Reference Architectures is being
+worked on as a [collaborative effort](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/1) between the Quality Engineering and Gitaly teams. When this component has been verified
+some Architecture specs will likely change as a result to support the new
+and improved designed.
+
[Gitaly](../gitaly/index.md) server node requirements are dependent on data,
specifically the number of projects and those projects' sizes. It's recommended
that a Gitaly server node stores no more than 5 TB of data. Although this
@@ -1988,7 +2007,7 @@ on what features you intend to use:
| [Merge request diffs](../merge_request_diffs.md#using-object-storage) | Yes |
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
-| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM ONLY)** | Yes |
+| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | 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) | Yes |
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index 4863329b695..f4842a8568b 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -356,6 +356,13 @@ are supported and can be added if needed.
## Configure Gitaly
+NOTE: **Note:**
+[Gitaly Cluster](../gitaly/praefect.md) support
+for the Reference Architectures is being
+worked on as a [collaborative effort](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/1) between the Quality Engineering and Gitaly teams. When this component has been verified
+some Architecture specs will likely change as a result to support the new
+and improved designed.
+
[Gitaly](../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
@@ -859,7 +866,7 @@ on what features you intend to use:
| [Merge request diffs](../merge_request_diffs.md#using-object-storage) | Yes |
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
-| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM ONLY)** | Yes |
+| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | 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) | Yes |
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index 70d0cae6dfd..b5b3e4e0300 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -1058,6 +1058,13 @@ Refer to your preferred Load Balancer's documentation for further guidance.
## Configure Gitaly
+NOTE: **Note:**
+[Gitaly Cluster](../gitaly/praefect.md) support
+for the Reference Architectures is being
+worked on as a [collaborative effort](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/1) between the Quality Engineering and Gitaly teams. When this component has been verified
+some Architecture specs will likely change as a result to support the new
+and improved designed.
+
[Gitaly](../gitaly/index.md) server node requirements are dependent on data,
specifically the number of projects and those projects' sizes. It's recommended
that a Gitaly server node stores no more than 5 TB of data. Although this
@@ -1735,7 +1742,7 @@ on what features you intend to use:
| [Merge request diffs](../merge_request_diffs.md#using-object-storage) | Yes |
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
-| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM ONLY)** | Yes |
+| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | 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) | Yes |
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index 44fbe2db504..152eb9cb90d 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -836,6 +836,12 @@ a node and change its status from primary to replica (and vice versa).
# Set up password authentication for Redis (use the same password in all nodes).
redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER'
+ # Set the Redis Cache instance as an LRU
+ # 90% of available RAM in MB
+ redis['maxmemory'] = '13500mb'
+ redis['maxmemory_policy'] = "allkeys-lru"
+ redis['maxmemory_samples'] = 5
+
## Enable service discovery for Prometheus
consul['enable'] = true
consul['monitoring_service_discovery'] = true
@@ -897,6 +903,12 @@ You can specify multiple roles, like sentinel and Redis, as:
# to `6379`.
#redis['master_port'] = 6379
+ # Set the Redis Cache instance as an LRU
+ # 90% of available RAM in MB
+ redis['maxmemory'] = '13500mb'
+ redis['maxmemory_policy'] = "allkeys-lru"
+ redis['maxmemory_samples'] = 5
+
## Enable service discovery for Prometheus
consul['enable'] = true
consul['monitoring_service_discovery'] = true
@@ -1335,6 +1347,13 @@ To configure the Sentinel Queues server:
## Configure Gitaly
+NOTE: **Note:**
+[Gitaly Cluster](../gitaly/praefect.md) support
+for the Reference Architectures is being
+worked on as a [collaborative effort](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/1) between the Quality Engineering and Gitaly teams. When this component has been verified
+some Architecture specs will likely change as a result to support the new
+and improved designed.
+
[Gitaly](../gitaly/index.md) server node requirements are dependent on data,
specifically the number of projects and those projects' sizes. It's recommended
that a Gitaly server node stores no more than 5 TB of data. Although this
@@ -1988,7 +2007,7 @@ on what features you intend to use:
| [Merge request diffs](../merge_request_diffs.md#using-object-storage) | Yes |
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
-| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM ONLY)** | Yes |
+| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | 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) | Yes |
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index 9f83950a927..f023971bdc0 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -1057,6 +1057,13 @@ Refer to your preferred Load Balancer's documentation for further guidance.
## Configure Gitaly
+NOTE: **Note:**
+[Gitaly Cluster](../gitaly/praefect.md) support
+for the Reference Architectures is being
+worked on as a [collaborative effort](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/1) between the Quality Engineering and Gitaly teams. When this component has been verified
+some Architecture specs will likely change as a result to support the new
+and improved designed.
+
[Gitaly](../gitaly/index.md) server node requirements are dependent on data,
specifically the number of projects and those projects' sizes. It's recommended
that a Gitaly server node stores no more than 5 TB of data. Although this
@@ -1734,7 +1741,7 @@ on what features you intend to use:
| [Merge request diffs](../merge_request_diffs.md#using-object-storage) | Yes |
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
-| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM ONLY)** | Yes |
+| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | 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) | Yes |
diff --git a/doc/administration/reply_by_email.md b/doc/administration/reply_by_email.md
index 62645ad17a1..4108635ba2c 100644
--- a/doc/administration/reply_by_email.md
+++ b/doc/administration/reply_by_email.md
@@ -46,4 +46,4 @@ If it finds a reply key, it will be able to leave your reply as a comment on
the entity the notification was about (issue, merge request, commit...).
For more details about the `Message-ID`, `In-Reply-To`, and `References headers`,
-please consult [RFC 5322](https://tools.ietf.org/html/rfc5322#section-3.6.4).
+see [RFC 5322](https://tools.ietf.org/html/rfc5322#section-3.6.4).
diff --git a/doc/administration/reply_by_email_postfix_setup.md b/doc/administration/reply_by_email_postfix_setup.md
index f4fcbefa403..aaadeef8bf5 100644
--- a/doc/administration/reply_by_email_postfix_setup.md
+++ b/doc/administration/reply_by_email_postfix_setup.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Set up Postfix for incoming email
This document will take you through the steps of setting up a basic Postfix mail
@@ -85,9 +91,10 @@ The instructions make the assumption that you will be using the email address `i
quit
```
- _**Note:** The `.` is a literal period on its own line._
+ NOTE: **Note:**
+ The `.` is a literal period on its own line.
- _**Note:** If you receive an error after entering `rcpt to: incoming@localhost`
+ If you receive an error after entering `rcpt to: incoming@localhost`
then your Postfix `my_network` configuration is not correct. The error will
say 'Temporary lookup failure'. See
[Configure Postfix to receive email from the Internet](#configure-postfix-to-receive-email-from-the-internet)._
@@ -158,11 +165,11 @@ Courier, which we will install later to add IMAP authentication, requires mailbo
q
```
- _**Note:** If `mail` returns an error `Maildir: Is a directory` then your
+ If `mail` returns an error `Maildir: Is a directory` then your
version of `mail` doesn't support Maildir style mailboxes. Install
`heirloom-mailx` by running `sudo apt-get install heirloom-mailx`. Then,
try the above steps again, substituting `heirloom-mailx` for the `mail`
- command._
+ command.
1. Sign out of the `incoming` account, and go back to being `root`:
@@ -265,7 +272,8 @@ Courier, which we will install later to add IMAP authentication, requires mailbo
quit
```
- (Note: The `.` is a literal period on its own line)
+ NOTE: **Note:**
+ The `.` is a literal period on its own line.
1. Check if the `incoming` user received the email:
diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md
index b272c4b463e..d2d492c8f1a 100644
--- a/doc/administration/repository_storage_types.md
+++ b/doc/administration/repository_storage_types.md
@@ -117,7 +117,7 @@ The output includes the project ID and the project name:
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/1606) in GitLab 12.1.
-DANGER: **Danger:**
+DANGER: **Warning:**
Do not run `git prune` or `git gc` in pool repositories! This can
cause data loss in "real" repositories that depend on the pool in
question.
diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md
index 57f53fd6cc4..f6a4a39ad60 100644
--- a/doc/administration/restart_gitlab.md
+++ b/doc/administration/restart_gitlab.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# How to restart GitLab
Depending on how you installed GitLab, there are different methods to restart
diff --git a/doc/administration/sidekiq.md b/doc/administration/sidekiq.md
index 23e870dbb82..2cc6acc8c87 100644
--- a/doc/administration/sidekiq.md
+++ b/doc/administration/sidekiq.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
@@ -92,7 +95,6 @@ you want using steps 1 and 2 from the GitLab downloads page.
1. Run `gitlab-ctl reconfigure`.
-NOTE: **Note:**
You will need to restart the Sidekiq nodes after an update has occurred and database
migrations performed.
@@ -111,7 +113,6 @@ prometheus['enable'] = false
gitlab_rails['auto_migrate'] = false
alertmanager['enable'] = false
gitaly['enable'] = false
-gitlab_monitor['enable'] = false
gitlab_workhorse['enable'] = false
nginx['enable'] = false
postgres_exporter['enable'] = false
diff --git a/doc/administration/smime_signing_email.md b/doc/administration/smime_signing_email.md
index 6ded7fdd7d0..f5b40210e62 100644
--- a/doc/administration/smime_signing_email.md
+++ b/doc/administration/smime_signing_email.md
@@ -1,10 +1,15 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Signing outgoing email with S/MIME
Notification emails sent by GitLab can be signed with S/MIME for improved
security.
-NOTE: **Note:**
-Please be aware that S/MIME certificates and TLS/SSL certificates are not the
+Be aware that S/MIME certificates and TLS/SSL certificates are not the
same and are used for different purposes: TLS creates a secure channel, whereas
S/MIME signs and/or encrypts the message itself
@@ -21,7 +26,7 @@ files must be provided:
Optionally, you can also provide a bundle of CA certs (PEM-encoded) to be
included on each signature. This will typically be an intermediate CA.
-NOTE: **Note:**
+CAUTION: **Caution:**
Be mindful of the access levels for your private keys and visibility to
third parties.
@@ -39,7 +44,6 @@ third parties.
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-NOTE: **Note:**
The key needs to be readable by the GitLab system user (`git` by default).
**For installations from source:**
@@ -63,7 +67,6 @@ The key needs to be readable by the GitLab system user (`git` by default).
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
-NOTE: **Note:**
The key needs to be readable by the GitLab system user (`git` by default).
### How to convert S/MIME PKCS#12 / PFX format to PEM encoding
diff --git a/doc/administration/timezone.md b/doc/administration/timezone.md
index 3cfee8630b7..bec82f66948 100644
--- a/doc/administration/timezone.md
+++ b/doc/administration/timezone.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Changing your time zone
The global time zone configuration parameter can be changed in `config/gitlab.yml`:
@@ -15,7 +21,7 @@ To see all available time zones, run `bundle exec rake time:zones:all`.
For Omnibus installations, run `gitlab-rake time:zones:all`.
NOTE: **Note:**
-Currently, this Rake task does not list timezones in TZInfo format required by Omnibus GitLab during a reconfigure: [#27209](https://gitlab.com/gitlab-org/gitlab/-/issues/27209).
+This Rake task does not list timezones in TZInfo format required by Omnibus GitLab during a reconfigure: [#27209](https://gitlab.com/gitlab-org/gitlab/-/issues/27209).
## Changing time zone in Omnibus installations
diff --git a/doc/administration/troubleshooting/debug.md b/doc/administration/troubleshooting/debug.md
index ef95bdc8602..d67c9963092 100644
--- a/doc/administration/troubleshooting/debug.md
+++ b/doc/administration/troubleshooting/debug.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Debugging Tips
Sometimes things don't work the way they should. Here are some tips on debugging issues out
diff --git a/doc/administration/troubleshooting/diagnostics_tools.md b/doc/administration/troubleshooting/diagnostics_tools.md
index 5912981ba6e..132f8524ca1 100644
--- a/doc/administration/troubleshooting/diagnostics_tools.md
+++ b/doc/administration/troubleshooting/diagnostics_tools.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/administration/troubleshooting/elasticsearch.md b/doc/administration/troubleshooting/elasticsearch.md
index 6de5bb71d75..12aa91e6f14 100644
--- a/doc/administration/troubleshooting/elasticsearch.md
+++ b/doc/administration/troubleshooting/elasticsearch.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Troubleshooting Elasticsearch
To install and configure Elasticsearch, and for common and known issues,
@@ -165,7 +171,7 @@ The first step is to confirm GitLab is using Elasticsearch for the search functi
To do this:
1. Confirm the integration is enabled in **Admin Area > Settings > General**.
-1. Confirm searches utilize Elasticsearch by accessing the rails console
+1. Confirm searches use Elasticsearch by accessing the rails console
(`sudo gitlab-rails console`) and running the following commands:
```rails
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index dbda889d370..cae4aa96f75 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -1,8 +1,11 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
-# GitLab Rails Console Cheat Sheet
+# GitLab Rails Console Cheat Sheet **(CORE ONLY)**
This is the GitLab Support Team's collection of information regarding the GitLab Rails
console, for use while troubleshooting. It is listed here for transparency,
@@ -43,6 +46,40 @@ instance_of_object.method(:foo).source_location
project.method(:private?).source_location
```
+## Attributes
+
+View available attributes, formatted using pretty print (`pp`).
+
+For example, determine what attributes contain users' names and email addresses:
+
+```ruby
+u = User.find_by_username('someuser')
+pp u.attributes
+```
+
+Partial output:
+
+```plaintext
+{"id"=>1234,
+ "email"=>"someuser@example.com",
+ "sign_in_count"=>99,
+ "name"=>"S User",
+ "username"=>"someuser",
+ "first_name"=>nil,
+ "last_name"=>nil,
+ "bot_type"=>nil}
+```
+
+Then make use of the attributes, [testing SMTP, for example](https://docs.gitlab.com/omnibus/settings/smtp.html#testing-the-smtp-configuration):
+
+```ruby
+e = u.email
+n = u.name
+Notify.test_email(e, "Test email for #{n}", 'Test email').deliver_now
+#
+Notify.test_email(u.email, "Test email for #{u.name}", 'Test email').deliver_now
+```
+
## Query the database using an ActiveRecord Model
```ruby
@@ -145,7 +182,7 @@ project.repository.expire_exists_cache
Project.update_all(visibility_level: 0)
```
-### Find & remove projects that are pending deletion
+### Find projects that are pending deletion
```ruby
#
@@ -174,8 +211,6 @@ project = Project.find_by_full_path('group-changeme/project-changeme')
::Projects::DestroyService.new(project, user, {}).execute
```
-Next, run `sudo gitlab-rake gitlab:cleanup:repos` on the command line to finish.
-
### Destroy a project
```ruby
@@ -273,11 +308,11 @@ pp p.statistics # compare with earlier values
### Recreate
-A Projects Wiki can be recreated by
-
-NOTE: **Note:**
+CAUTION: **Caution:**
This is a destructive operation, the Wiki will be empty.
+A Projects Wiki can be recreated by this command:
+
```ruby
p = Project.find_by_full_path('<username-or-group>/<project-name>') ### enter your projects path
@@ -423,7 +458,7 @@ user.skip_reconfirmation!
User.active.count
# Users taking a seat on the instance
-License.current.current_active_users_count
+User.billable.count
# The historical max on the instance as of the past year
::HistoricalData.max_historical_user_count
@@ -484,6 +519,16 @@ user.max_member_access_for_group group.id
## Groups
+### Transfer group to another location
+
+```ruby
+user = User.find_by_username('<username>')
+group = Group.find_by_name("<group_name>")
+parent_group = Group.find_by(id: "") # empty string amounts to root as parent
+service = ::Groups::TransferService.new(group, user)
+service.execute(parent_group)
+```
+
### Count unique users in a group and sub-groups
```ruby
@@ -813,7 +858,7 @@ Find this content in the [Container Registry troubleshooting docs](../packages/c
## Sidekiq
-This content has been moved to the [Troubleshooting Sidekiq docs](./sidekiq.md).
+This content has been moved to the [Troubleshooting Sidekiq docs](sidekiq.md).
## Redis
@@ -954,3 +999,19 @@ project = Project.find_by_full_path('<group/project>')
Geo::RepositorySyncService.new(project).execute
```
+
+### Generate usage ping
+
+#### Generate or get the cached usage ping
+
+```ruby
+Gitlab::UsageData.to_json
+```
+
+#### Generate a fresh new usage ping
+
+This will also refresh the cached usage ping displayed in the admin area
+
+```ruby
+Gitlab::UsageData.to_json(force_refresh: true)
+```
diff --git a/doc/administration/troubleshooting/group_saml_scim.md b/doc/administration/troubleshooting/group_saml_scim.md
index 7492688ded0..efc8eaab198 100644
--- a/doc/administration/troubleshooting/group_saml_scim.md
+++ b/doc/administration/troubleshooting/group_saml_scim.md
@@ -1,4 +1,7 @@
---
+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
type: reference
---
diff --git a/doc/administration/troubleshooting/img/ADFS-determine-token-signing-certificate-fingerprint.png b/doc/administration/troubleshooting/img/ADFS-determine-token-signing-certificate-fingerprint.png
index cd1b9db31d9..e24c994e996 100644
--- a/doc/administration/troubleshooting/img/ADFS-determine-token-signing-certificate-fingerprint.png
+++ b/doc/administration/troubleshooting/img/ADFS-determine-token-signing-certificate-fingerprint.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/OneLogin-encryption.png b/doc/administration/troubleshooting/img/OneLogin-encryption.png
deleted file mode 100644
index 2b811409bd0..00000000000
--- a/doc/administration/troubleshooting/img/OneLogin-encryption.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/troubleshooting/img/network_monitor_xid.png b/doc/administration/troubleshooting/img/network_monitor_xid.png
index 5392f77327f..7fc2cf47ea0 100644
--- a/doc/administration/troubleshooting/img/network_monitor_xid.png
+++ b/doc/administration/troubleshooting/img/network_monitor_xid.png
Binary files differ
diff --git a/doc/administration/troubleshooting/index.md b/doc/administration/troubleshooting/index.md
index 50f192b1983..8a4a0a4caac 100644
--- a/doc/administration/troubleshooting/index.md
+++ b/doc/administration/troubleshooting/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Troubleshooting a GitLab installation
Below are some resources to help you troubleshoot a GitLab installation
diff --git a/doc/administration/troubleshooting/kubernetes_cheat_sheet.md b/doc/administration/troubleshooting/kubernetes_cheat_sheet.md
index 7c5a9e0d79f..21fd183dfd0 100644
--- a/doc/administration/troubleshooting/kubernetes_cheat_sheet.md
+++ b/doc/administration/troubleshooting/kubernetes_cheat_sheet.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
@@ -67,8 +70,7 @@ and they will assist you with any issues you are having.
kubectl logs <pod-name> --previous
```
- NOTE: **Note:**
- No logs are kept in the containers/pods themselves, everything is written to stdout.
+ No logs are kept in the containers/pods themselves. Everything is written to stdout.
This is the principle of Kubernetes, read [Twelve-factor app](https://12factor.net/)
for details.
diff --git a/doc/administration/troubleshooting/linux_cheat_sheet.md b/doc/administration/troubleshooting/linux_cheat_sheet.md
index f24234e1aff..b1042a9402b 100644
--- a/doc/administration/troubleshooting/linux_cheat_sheet.md
+++ b/doc/administration/troubleshooting/linux_cheat_sheet.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
@@ -15,7 +18,6 @@ If you are administering GitLab you are expected to know these commands for your
of choice. If you are a GitLab Support Engineer, consider this a cross-reference to
translate `yum` -> `apt-get` and the like.
-Note: **Note:**
Most of the commands below have not been labeled as to which distribution they work
on. Contributions are welcome to help add them.
diff --git a/doc/administration/troubleshooting/log_parsing.md b/doc/administration/troubleshooting/log_parsing.md
index 7914628a756..4e9e8cd591f 100644
--- a/doc/administration/troubleshooting/log_parsing.md
+++ b/doc/administration/troubleshooting/log_parsing.md
@@ -1,8 +1,14 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Parsing GitLab logs with `jq`
We recommend using log aggregation and search tools like Kibana and Splunk whenever possible,
but if they are not available you can still quickly parse
-[GitLab logs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26311) in JSON format
+[GitLab logs](../logs.md) in JSON format
(the default in GitLab 12.0 and later) using [`jq`](https://stedolan.github.io/jq/).
## What is JQ?
diff --git a/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md b/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md
index a1485249b0e..475f3d56836 100644
--- a/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md
+++ b/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Navigating GitLab via Rails console
At the heart of GitLab is a web application [built using the Ruby on Rails
@@ -379,7 +385,7 @@ User.find_by(username: 'root')
User.find_by_any_email('user@example.com')
```
-Note: `find_by_any_email` is a custom method added by GitLab developers rather
+The `find_by_any_email` method is a custom method added by GitLab developers rather
than a Rails-provided default method.
**Get a collection of admin users:**
@@ -388,7 +394,7 @@ than a Rails-provided default method.
User.admins
```
-Note: `admins` is a [scope convenience method](https://guides.rubyonrails.org/active_record_querying.html#scopes)
+`admins` is a [scope convenience method](https://guides.rubyonrails.org/active_record_querying.html#scopes)
which does `where(admin: true)` under the hood.
**Get a project by its path:**
@@ -397,7 +403,7 @@ which does `where(admin: true)` under the hood.
Project.find_by_full_path('group/subgroup/project')
```
-Note: `find_by_full_path` is a custom method added by GitLab developers rather
+`find_by_full_path` is a custom method added by GitLab developers rather
than a Rails-provided default method.
**Get a project's issue or merge request by its numeric ID:**
@@ -408,7 +414,7 @@ project.issues.find_by(iid: 42)
project.merge_requests.find_by(iid: 42)
```
-Note: `iid` means "internal ID" and is how we keep issue and merge request IDs
+`iid` means "internal ID" and is how we keep issue and merge request IDs
scoped to each GitLab project.
**Get a group by its path:**
@@ -448,7 +454,7 @@ Ci::Pipeline.find(4151)
Ci::Build.find(66124)
```
-Note: The pipeline and job #ID numbers increment globally across your GitLab
+The pipeline and job ID numbers increment globally across your GitLab
instance, so there's no need to use an internal ID attribute to look them up,
unlike with issues or merge requests.
diff --git a/doc/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md
index 91ff6f6524a..d22e76a505a 100644
--- a/doc/administration/troubleshooting/postgresql.md
+++ b/doc/administration/troubleshooting/postgresql.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
@@ -145,4 +148,4 @@ It may take a little while to respond.
```
NOTE: **Note:**
-These are Omnibus settings. If an external database, such as a customer's PostgreSQL installation or Amazon RDS is being used, these values don't get set, and would have to be set externally.
+These are Omnibus GitLab settings. If an external database, such as a customer's PostgreSQL installation or Amazon RDS is being used, these values don't get set, and would have to be set externally.
diff --git a/doc/administration/troubleshooting/sidekiq.md b/doc/administration/troubleshooting/sidekiq.md
index b7762f8ac3e..d415aa0d980 100644
--- a/doc/administration/troubleshooting/sidekiq.md
+++ b/doc/administration/troubleshooting/sidekiq.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Troubleshooting Sidekiq
Sidekiq is the background job processor GitLab uses to asynchronously run
@@ -7,12 +13,10 @@ may be filling up. Users will notice when this happens because new branches
may not show up and merge requests may not be updated. The following are some
troubleshooting steps that will help you diagnose the bottleneck.
-NOTE: **Note:**
GitLab administrators/users should consider working through these
debug steps with GitLab Support so the backtraces can be analyzed by our team.
It may reveal a bug or necessary improvement in GitLab.
-NOTE: **Note:**
In any of the backtraces, be wary of suspecting cases where every
thread appears to be waiting in the database, Redis, or waiting to acquire
a mutex. This **may** mean there's contention in the database, for example,
@@ -22,19 +26,11 @@ preventing other threads from continuing.
## Log arguments to Sidekiq jobs
-If you want to see what arguments are being passed to Sidekiq jobs you can set
-the `SIDEKIQ_LOG_ARGUMENTS` [environment variable](https://docs.gitlab.com/omnibus/settings/environment-variables.html) to `1` (true).
-
-Example:
-
-```ruby
-gitlab_rails['env'] = {"SIDEKIQ_LOG_ARGUMENTS" => "1"}
-```
-
-This does not log all job arguments. To avoid logging sensitive
-information (for instance, password reset tokens), it logs numeric
-arguments for all workers, with overrides for some specific workers
-where their arguments are not sensitive.
+[In GitLab 13.6 and later](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44853)
+some arguments passed to Sidekiq jobs are logged by default.
+To avoid logging sensitive information (for instance, password reset tokens),
+GitLab logs numeric arguments for all workers, with overrides for some specific
+workers where their arguments are not sensitive.
Example log output:
@@ -49,6 +45,17 @@ arguments logs are limited to a maximum size of 10 kilobytes of text;
any arguments after this limit will be discarded and replaced with a
single argument containing the string `"..."`.
+You can set `SIDEKIQ_LOG_ARGUMENTS` [environment variable](https://docs.gitlab.com/omnibus/settings/environment-variables.html)
+to `0` (false) to disable argument logging.
+
+Example:
+
+```ruby
+gitlab_rails['env'] = {"SIDEKIQ_LOG_ARGUMENTS" => "0"}
+```
+
+In GitLab 13.5 and earlier, set `SIDEKIQ_LOG_ARGUMENTS` to `1` to start logging arguments passed to Sidekiq.
+
## Thread dump
Send the Sidekiq process ID the `TTIN` signal and it will output thread
@@ -127,7 +134,6 @@ corresponding Ruby code where this is happening.
`gdb` can be another effective tool for debugging Sidekiq. It gives you a little
more interactive way to look at each thread and see what's causing problems.
-NOTE: **Note:**
Attaching to a process with `gdb` will suspends the normal operation
of the process (Sidekiq will not process jobs while `gdb` is attached).
@@ -278,15 +284,15 @@ end
### Remove Sidekiq jobs for given parameters (destructive)
-The general method to kill jobs conditionally is the following:
+The general method to kill jobs conditionally is the following command, which
+will remove jobs that are queued but not started. Running jobs will not be killed.
```ruby
queue = Sidekiq::Queue.new('<queue name>')
queue.each { |job| job.delete if <condition>}
```
-NOTE: **Note:**
-This will remove jobs that are queued but not started, running jobs will not be killed. Have a look at the section below for cancelling running jobs.
+Have a look at the section below for cancelling running jobs.
In the method above, `<queue-name>` is the name of the queue that contains the job(s) you want to delete and `<condition>` will decide which jobs get deleted.
@@ -294,7 +300,6 @@ Commonly, `<condition>` references the job arguments, which depend on the type o
For example, `repository_import` has `project_id` as the job argument, while `update_merge_requests` has `project_id, user_id, oldrev, newrev, ref`.
-NOTE: **Note:**
Arguments need to be referenced by their sequence ID using `job.args[<id>]` because `job.args` is a list of all arguments provided to the Sidekiq job.
Here are some examples:
diff --git a/doc/administration/troubleshooting/ssl.md b/doc/administration/troubleshooting/ssl.md
index 4d4b9755fa9..996856521b7 100644
--- a/doc/administration/troubleshooting/ssl.md
+++ b/doc/administration/troubleshooting/ssl.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/administration/troubleshooting/test_environments.md b/doc/administration/troubleshooting/test_environments.md
index 80ccd15aa22..9855a27ca30 100644
--- a/doc/administration/troubleshooting/test_environments.md
+++ b/doc/administration/troubleshooting/test_environments.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/administration/troubleshooting/tracing_correlation_id.md b/doc/administration/troubleshooting/tracing_correlation_id.md
index ae9ebd90951..8840c2706d6 100644
--- a/doc/administration/troubleshooting/tracing_correlation_id.md
+++ b/doc/administration/troubleshooting/tracing_correlation_id.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/administration/uploads.md b/doc/administration/uploads.md
index 91de089c45e..cd15301edf6 100644
--- a/doc/administration/uploads.md
+++ b/doc/administration/uploads.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# 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.
@@ -16,7 +22,7 @@ were before.
This change is deployed behind a feature flag that is **enabled by default**.
If you experience any issues with upload,
-[GitLab administrators with access to the GitLab Rails console](./feature_flags.md)
+[GitLab administrators with access to the GitLab Rails console](feature_flags.md)
can opt to disable it.
To enable it:
@@ -33,16 +39,15 @@ Feature.disable(:upload_middleware_jwt_params_handler)
## Using local storage
-NOTE: **Note:**
-This is the default configuration
+This is the default configuration. To change the location where the uploads are
+stored locally, use the steps in this section based on your installation method:
-To change the location where the uploads are stored locally, follow the steps
-below.
-
-**In Omnibus installations:**
+**In Omnibus GitLab installations:**
NOTE: **Note:**
-For historical reasons, uploads are stored into a base directory, which by default is `uploads/-/system`. It is strongly discouraged to change this configuration option on an existing GitLab installation.
+For historical reasons, uploads are stored into a base directory, which by
+default is `uploads/-/system`. It's strongly discouraged to change this
+configuration option for an existing GitLab installation.
_The uploads are stored by default in `/var/opt/gitlab/gitlab-rails/uploads`._
@@ -86,7 +91,6 @@ This configuration relies on valid AWS credentials to be configured already.
[Read more about using object storage with GitLab](object_storage.md).
-NOTE: **Note:**
We recommend using the [consolidated object storage settings](object_storage.md#consolidated-object-storage-configuration). The following instructions apply to the original configuration format.
## Object Storage Settings
@@ -125,7 +129,6 @@ _The uploads are stored by default in
}
```
- NOTE: **Note:**
If you are using AWS IAM profiles, be sure to omit the AWS access key and secret access key/value pairs.
```ruby
diff --git a/doc/administration/user_settings.md b/doc/administration/user_settings.md
index 7a3e1d86712..94ce1debfea 100644
--- a/doc/administration/user_settings.md
+++ b/doc/administration/user_settings.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Modifying global user settings
GitLab administrators can modify user settings for the entire GitLab instance.
diff --git a/doc/api/README.md b/doc/api/README.md
index 3f7dae055e2..3933431407c 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -1,10 +1,20 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# API Docs
-Automate GitLab via a simple and powerful API.
+Automate GitLab by using 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.
+The main GitLab API is a [REST](http://spec.openapis.org/oas/v3.0.3)
+API. Because of this, the documentation in this section assumes that you're
+familiar with 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.
+There's 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
@@ -13,21 +23,22 @@ For a list of the available resources and their endpoints, see
## SCIM **(SILVER ONLY)**
-[GitLab.com Silver and above](https://about.gitlab.com/pricing/) provides an [SCIM API](scim.md) that implements [the RFC7644 protocol](https://tools.ietf.org/html/rfc7644) and provides
-the `/Users` endpoint. The base URL is: `/api/scim/v2/groups/:group_path/Users/`.
+[GitLab.com Silver and higher](https://about.gitlab.com/pricing/) provides an
+[SCIM API](scim.md) that both implements [the RFC7644 protocol](https://tools.ietf.org/html/rfc7644)
+and provides the `/Users` endpoint. The base URL is: `/api/scim/v2/groups/:group_path/Users/`.
## Road to GraphQL
-[GraphQL](graphql/index.md) is available in GitLab, which will
-allow deprecation of controller-specific endpoints.
+[GraphQL](graphql/index.md) is available in GitLab, which allows for the
+deprecation of controller-specific endpoints.
-GraphQL has a number of benefits:
+GraphQL has several benefits, including:
-1. We avoid having to maintain two different APIs.
-1. Callers of the API can request only what they need.
-1. It is versioned by default.
+- We avoid having to maintain two different APIs.
+- Callers of the API can request only what they need.
+- It's versioned by default.
-It will co-exist with the current v4 REST API. If we have a v5 API, this should
+GraphQL co-exists with the current v4 REST API. If we have a v5 API, this should
be a compatibility layer on top of GraphQL.
Although there were some patenting and licensing concerns with GraphQL, these
@@ -37,33 +48,35 @@ specification.
## Compatibility guidelines
-The HTTP API is versioned using a single number, the current one being 4. This
-number symbolizes the same as the major version number as described by
-[SemVer](https://semver.org/). This mean that backward incompatible changes
-will require this version number to change. However, the minor version is
-not explicit. This allows for a stable API endpoint, but also means new
-features can be added to the API in the same version number.
+The HTTP API is versioned using a single number, (currently _4_). This number
+symbolizes the major version number, as described by [SemVer](https://semver.org/).
+Because of this, backwards-incompatible changes require this version number to
+change. However, the minor version isn't explicit, allowing for a stable API
+endpoint. This also means that new features can be added to the API in the same
+version number.
New features and bug fixes are released in tandem with a new GitLab, and apart
from incidental patch and security releases, are released on the 22nd of each
-month. Backward incompatible changes (e.g. endpoints removal, parameters
-removal etc.), as well as removal of entire API versions are done in tandem
-with a major point release of GitLab itself. All deprecations and changes
-between two versions should be listed in the documentation. For the changes
-between v3 and v4; please read the [v3 to v4 documentation](v3_to_v4.md)
+month. Backward incompatible changes (for example, endpoints removal and
+parameters removal), and removal of entire API versions are done in tandem with
+a major point release of GitLab itself. All deprecations and changes between two
+versions should be listed in the documentation. For the changes between v3 and
+v4, see the [v3 to v4 documentation](v3_to_v4.md).
### Current status
-Currently only API version v4 is available. Version v3 was removed in
+Only API version v4 is available. Version v3 was removed in
[GitLab 11.0](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36819).
## Basic usage
-API requests should be prefixed with `api` and the API version. The API version
-is defined in [`lib/api.rb`](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/api/api.rb). For example, the root of the v4 API
-is at `/api/v4`.
+API requests should be prefixed with both `api` and the API version. The API
+version is defined in [`lib/api.rb`](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/api/api.rb).
+For example, the root of the v4 API is at `/api/v4`. The following sections illustrate different uses:
+
+### Valid API request
-Example of a valid API request using cURL:
+If you have a GitLab instance at `gitlab.example.com`:
```shell
curl "https://gitlab.example.com/api/v4/projects"
@@ -72,32 +85,56 @@ curl "https://gitlab.example.com/api/v4/projects"
The API uses JSON to serialize data. You don't need to specify `.json` at the
end of an API URL.
+### API request to expose HTTP response headers
+
+If you want to expose HTTP response headers, use the `--include` option:
+
+```shell
+curl --include "https://gitlab.example.com/api/v4/projects"
+HTTP/2 200
+...
+```
+
+This can help you investigate an unexpected response.
+
+### API Request that includes the exit code
+
+If you want to expose the HTTP exit code, include the `--fail` option:
+
+```shell script
+curl --fail "https://gitlab.example.com/api/v4/does-not-exist"
+curl: (22) The requested URL returned error: 404
+```
+
+The HTTP exit code can help you diagnose the success or failure of your REST call.
+
## Authentication
-Most API requests require authentication, or will only return public data when
-authentication is not provided. For
-those cases where it is not required, this will be mentioned in the documentation
-for each individual endpoint. For example, the [`/projects/:id` endpoint](projects.md#get-single-project).
+Most API requests require authentication, or will return public data only when
+authentication isn't provided. For cases where it isn't required, this will be
+mentioned in the documentation for each individual endpoint (for example, the
+[`/projects/:id` endpoint](projects.md#get-single-project)).
-There are several ways to authenticate with the GitLab API:
+There are several methods you can use to authenticate with the GitLab API:
-1. [OAuth2 tokens](#oauth2-tokens)
-1. [Personal access tokens](../user/profile/personal_access_tokens.md)
-1. [Project access tokens](../user/project/settings/project_access_tokens.md)
+- [OAuth2 tokens](#oauth2-tokens)
+- [Personal access tokens](../user/profile/personal_access_tokens.md)
+- [Project access tokens](../user/project/settings/project_access_tokens.md)
+- [Session cookie](#session-cookie)
+- [GitLab CI/CD job token](#gitlab-ci-job-token) **(Specific endpoints only)**
NOTE: **Note:**
-Project access tokens are supported for self-managed instances on Core and above. They are also supported on GitLab.com Bronze and above.
+Project access tokens are supported for self-managed instances on Core and
+higher. They're also supported on GitLab.com Bronze and higher.
-1. [Session cookie](#session-cookie)
-1. [GitLab CI/CD job token](#gitlab-ci-job-token) **(Specific endpoints only)**
+For administrators who want to authenticate with the API as a specific user, or who want
+to build applications or scripts that do so, the following options are available:
-For admins who want to authenticate with the API as a specific user, or who want to build applications or scripts that do so, two options are available:
+- [Impersonation tokens](#impersonation-tokens)
+- [Sudo](#sudo)
-1. [Impersonation tokens](#impersonation-tokens)
-1. [Sudo](#sudo)
-
-If authentication information is invalid or omitted, an error message will be
-returned with status code `401`:
+If authentication information is invalid or omitted, GitLab will return an error
+message with a status code of `401`:
```json
{
@@ -107,8 +144,8 @@ returned with status code `401`:
### OAuth2 tokens
-You can use an [OAuth2 token](oauth2.md) to authenticate with the API by passing it in either the
-`access_token` parameter or the `Authorization` header.
+You can use an [OAuth2 token](oauth2.md) to authenticate with the API by passing
+it in either the `access_token` parameter or the `Authorization` header.
Example of using the OAuth2 token in a parameter:
@@ -126,22 +163,22 @@ 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.
+You can use access tokens to authenticate with the API by passing it in either
+the `private_token` parameter or the `PRIVATE-TOKEN` header.
-Example of using the personal/project access token in a parameter:
+Example of using the personal or project access token in a parameter:
```shell
curl "https://gitlab.example.com/api/v4/projects?private_token=<your_access_token>"
```
-Example of using the personal/project access token in a header:
+Example of using the personal or project access token in a header:
```shell
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:
+You can also use personal or project access tokens with OAuth-compliant headers:
```shell
curl --header "Authorization: Bearer <your_access_token>" "https://gitlab.example.com/api/v4/projects"
@@ -150,12 +187,12 @@ curl --header "Authorization: Bearer <your_access_token>" "https://gitlab.exampl
### Session cookie
When signing in to the main GitLab application, a `_gitlab_session` cookie is
-set. The API will use this cookie for authentication if it is present, but using
-the API to generate a new session cookie is currently not supported.
+set. The API uses this cookie for authentication if it's present. Using the
+API to generate a new session cookie isn't supported.
-The primary user of this authentication method is the web frontend of GitLab itself,
-which can use the API as the authenticated user to get a list of their projects,
-for example, without needing to explicitly pass an access token.
+The primary user of this authentication method is the web frontend of GitLab
+itself, which can, for example, use the API as the authenticated user to get a
+list of their projects without needing to explicitly pass an access token.
### GitLab CI job token
@@ -165,15 +202,17 @@ to authenticate with the API:
- Packages:
- [Composer Repository](../user/packages/composer_repository/index.md)
- [Conan Repository](../user/packages/conan_repository/index.md)
- - [Container Registry](../user/packages/container_registry/index.md) (`$CI_REGISTRY_PASSWORD` is actually `$CI_JOB_TOKEN`, but this may change in the future)
+ - [Container Registry](../user/packages/container_registry/index.md)
+ (`$CI_REGISTRY_PASSWORD` is actually `$CI_JOB_TOKEN`, but this may change in
+ the future)
- [Go Proxy](../user/packages/go_proxy/index.md)
- - [Maven Repository](../user/packages/maven_repository/index.md#authenticate-with-a-ci-job-token)
- - [NPM Repository](../user/packages/npm_registry/index.md#authenticating-with-a-ci-job-token)
+ - [Maven Repository](../user/packages/maven_repository/index.md#authenticate-with-a-ci-job-token-in-maven)
+ - [NPM Repository](../user/packages/npm_registry/index.md#authenticate-with-a-ci-job-token)
- [Nuget Repository](../user/packages/nuget_repository/index.md)
- - [PyPI Repository](../user/packages/pypi_repository/index.md#using-gitlab-ci-with-pypi-packages)
+ - [PyPI Repository](../user/packages/pypi_repository/index.md#authenticate-with-a-ci-job-token)
- [Generic packages](../user/packages/generic_packages/index.md#publish-a-generic-package-by-using-cicd)
- [Get job artifacts](job_artifacts.md#get-job-artifacts)
-- [Pipeline triggers](pipeline_triggers.md) (via `token=` parameter)
+- [Pipeline triggers](pipeline_triggers.md) (using the `token=` parameter)
- [Release creation](releases/index.md#create-a-release)
- [Terraform plan](../user/infrastructure/index.md)
@@ -181,21 +220,22 @@ The token is valid as long as the job is running.
### Impersonation tokens
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9099) in GitLab 9.0. Needs admin permissions.
-
Impersonation tokens are a type of [personal access token](../user/profile/personal_access_tokens.md)
that can only be created by an admin for a specific user. They are a great fit
-if you want to build applications or scripts that authenticate with the API as a specific user.
+if you want to build applications or scripts that authenticate with the API as a
+specific user.
-They are an alternative to directly using the user's password or one of their
-personal access tokens, and to using the [Sudo](#sudo) feature, since the user's (or admin's, in the case of Sudo)
-password/token may not be known or may change over time.
+They're an alternative to directly using the user's password or one of their
+personal access tokens, and to using the [Sudo](#sudo) feature, as the user's
+(or admin's, in the case of Sudo) password or token may not be known, or may
+change over time.
-For more information, refer to the
-[users API](users.md#create-an-impersonation-token) docs.
+For more information, see the [users API](users.md#create-an-impersonation-token)
+documentation.
-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.
+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.
#### Disable impersonation
@@ -214,7 +254,8 @@ By default, impersonation is enabled. To disable impersonation:
1. Save the file and [reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
GitLab for the changes to take effect.
-To re-enable impersonation, remove this configuration and reconfigure GitLab.
+To re-enable impersonation, remove this configuration, and then reconfigure
+GitLab.
**For installations from source**
@@ -228,26 +269,22 @@ To re-enable impersonation, remove this configuration and reconfigure GitLab.
1. Save the file and [restart](../administration/restart_gitlab.md#installations-from-source)
GitLab for the changes to take effect.
-To re-enable impersonation, remove this configuration and restart GitLab.
+To re-enable impersonation, remove this configuration, and then restart GitLab.
### Sudo
-NOTE: **Note:**
-Only available to [administrators](../user/permissions.md).
-
All API requests support performing an API call as if you were another user,
-provided you are authenticated as an administrator with an OAuth or Personal Access Token that has the `sudo` scope.
-The API requests are executed with the permissions of the impersonated user.
+provided you're authenticated as an administrator with an OAuth or personal
+access token that has the `sudo` scope. The API requests are executed with the
+permissions of the impersonated user.
-You need to pass the `sudo` parameter either via query string or a header with an ID/username of
-the user you want to perform the operation as. If passed as a header, the
-header name must be `Sudo`.
+As an [administrator](../user/permissions.md), pass the `sudo` parameter either
+by using query string or a header with an ID or username (case insensitive) of
+the user you want to perform the operation as. If passed as a header, the header
+name must be `Sudo`.
-NOTE: **Note:**
-Usernames are case insensitive.
-
-If a non administrative access token is provided, an error message will
-be returned with status code `403`:
+If a non administrative access token is provided, GitLab returns an error
+message with a status code of `403`:
```json
{
@@ -256,7 +293,7 @@ be returned with status code `403`:
```
If an access token without the `sudo` scope is provided, an error message will
-be returned with status code `403`:
+be returned with a status code of `403`:
```json
{
@@ -267,7 +304,7 @@ be returned with status code `403`:
```
If the sudo user ID or username cannot be found, an error message will be
-returned with status code `404`:
+returned with a status code of `404`:
```json
{
@@ -305,27 +342,27 @@ insight into what went wrong.
The following table gives an overview of how the API functions generally behave.
-| Request type | Description |
-| ------------ | ----------- |
-| `GET` | Access one or more resources and return the result as JSON. |
-| `POST` | Return `201 Created` if the resource is successfully created and return the newly created resource as JSON. |
+| Request type | Description |
+|---------------|-------------|
+| `GET` | Access one or more resources and return the result as JSON. |
+| `POST` | Return `201 Created` if the resource is successfully created and return the newly created resource as JSON. |
| `GET` / `PUT` | Return `200 OK` if the resource is accessed or modified successfully. The (modified) result is returned as JSON. |
-| `DELETE` | Returns `204 No Content` if the resource was deleted successfully. |
+| `DELETE` | Returns `204 No Content` if the resource was deleted successfully. |
The following table shows the possible return codes for API requests.
| Return values | Description |
-| ------------------------ | ----------- |
+|--------------------------|-------------|
| `200 OK` | The `GET`, `PUT` or `DELETE` request was successful, the resource(s) itself is returned as JSON. |
| `204 No Content` | The server has successfully fulfilled the request and that there is no additional content to send in the response payload body. |
| `201 Created` | The `POST` request was successful and the resource is returned as JSON. |
| `304 Not Modified` | Indicates that the resource has not been modified since the last request. |
| `400 Bad Request` | A required attribute of the API request is missing, e.g., the title of an issue is not given. |
| `401 Unauthorized` | The user is not authenticated, a valid [user token](#authentication) is necessary. |
-| `403 Forbidden` | The request is not allowed, e.g., the user is not allowed to delete a project. |
-| `404 Not Found` | A resource could not be accessed, e.g., an ID for a resource could not be found. |
+| `403 Forbidden` | The request is not allowed. For example, the user is not allowed to delete a project. |
+| `404 Not Found` | A resource could not be accessed. For example, an ID for a resource could not be found. |
| `405 Method Not Allowed` | The request is not supported. |
-| `409 Conflict` | A conflicting resource already exists, e.g., creating a project with a name that already exists. |
+| `409 Conflict` | A conflicting resource already exists. For example, creating a project with a name that already exists. |
| `412` | Indicates the request was denied. May happen if the `If-Unmodified-Since` header is provided when trying to delete a resource, which was modified in between. |
| `422 Unprocessable` | The entity could not be processed. |
| `429 Too Many Requests` | The user exceeded the [application rate limits](../administration/instance_limits.md#rate-limits). |
@@ -333,26 +370,26 @@ The following table shows the possible return codes for API requests.
## Pagination
-We support two kinds of pagination methods:
+GitLab supports the following pagination methods:
- Offset-based pagination. This is the default method and available on all endpoints.
- Keyset-based pagination. Added to selected endpoints but being
[progressively rolled out](https://gitlab.com/groups/gitlab-org/-/epics/2039).
-For large collections, we recommend keyset pagination (when available) over offset
-pagination for performance reasons.
+For large collections, we recommend keyset pagination (when available) instead
+of offset pagination for performance reasons.
### Offset-based pagination
-Sometimes the returned result will span across many pages. When listing
-resources you can pass the following parameters:
+Sometimes, the returned result spans many pages. When listing resources, you can
+pass the following parameters:
| Parameter | Description |
-| --------- | ----------- |
-| `page` | Page number (default: `1`) |
-| `per_page`| Number of items to list per page (default: `20`, max: `100`) |
+|-----------|-------------|
+| `page` | Page number (default: `1`). |
+| `per_page`| Number of items to list per page (default: `20`, max: `100`). |
-In the example below, we list 50 [namespaces](namespaces.md) per page.
+In the following example, we list 50 [namespaces](namespaces.md) per page:
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/namespaces?per_page=50"
@@ -361,15 +398,14 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
#### Pagination `Link` header
[`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.
+response. They have `rel` set to `prev`, `next`, `first`, or `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 `9`:
+In the following cURL example, we limit the output to three 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 `9`:
```shell
curl --head --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/9/issues/8/notes?per_page=3&page=2"
@@ -400,31 +436,32 @@ x-total-pages: 3
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 |
-| `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 |
+| Header | Description |
+|-----------------|-------------|
+| `x-next-page` | The index of the next page. |
+| `x-page` | The index of the current page (starting at 1). |
+| `x-per-page` | The number of items per page. |
+| `X-prev-page` | The index of the previous page. |
+| `x-total` | The total number of items. |
+| `x-total-pages` | The total number of pages. |
-NOTE: **Note:**
For GitLab.com users, [some pagination headers may not be returned](../user/gitlab_com/index.md#pagination-response-headers).
### Keyset-based pagination
-Keyset-pagination allows for more efficient retrieval of pages and - in contrast to offset-based pagination - runtime
-is independent of the size of the collection.
+Keyset-pagination allows for more efficient retrieval of pages and - in contrast
+to offset-based pagination - runtime is independent of the size of the
+collection.
This method is controlled by the following parameters:
-| Parameter | Description |
-| ------------ | -------------------------------------- |
-| `pagination` | `keyset` (to enable keyset pagination) |
-| `per_page` | Number of items to list per page (default: `20`, max: `100`) |
+| Parameter | Description |
+|--------------| ------------|
+| `pagination` | `keyset` (to enable keyset pagination). |
+| `per_page` | Number of items to list per page (default: `20`, max: `100`). |
-In the example below, we list 50 [projects](projects.md) per page, ordered by `id` ascending.
+In the following example, we list 50 [projects](projects.md) per page, ordered
+by `id` ascending.
```shell
curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects?pagination=keyset&per_page=50&order_by=id&sort=asc"
@@ -442,27 +479,34 @@ Status: 200 OK
```
CAUTION: **Deprecation:**
-The `Links` header will be removed in GitLab 14.0 to be aligned with the [W3C `Link` specification](https://www.w3.org/wiki/LinkHeader).
-The `Link` header was [added in GitLab 13.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33714)
+The `Links` header will be removed in GitLab 14.0 to be aligned with the
+[W3C `Link` specification](https://www.w3.org/wiki/LinkHeader). The `Link`
+header was [added in GitLab 13.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33714)
and should be used instead.
-The link to the next page contains an additional filter `id_after=42` which excludes records we have retrieved already.
-Note the type of filter depends on the `order_by` option used and we may have more than one additional filter.
+The link to the next page contains an additional filter `id_after=42` that
+excludes already-retrieved records. Note the type of filter depends on the
+`order_by` option used, and we may have more than one additional filter.
-When the end of the collection has been reached and there are no additional records to retrieve, the `Link` header is absent and the resulting array is empty.
+When the end of the collection has been reached and there are no additional
+records to retrieve, the `Link` header is absent and the resulting array is
+empty.
-We recommend using only the given link to retrieve the next page instead of building your own URL. Apart from the headers shown,
-we don't expose additional pagination headers.
+We recommend using only the given link to retrieve the next page instead of
+building your own URL. Apart from the headers shown, we don't expose additional
+pagination headers.
-Keyset-based pagination is only supported for selected resources and ordering options:
+Keyset-based pagination is supported only for selected resources and ordering
+options:
-| Resource | Order |
-| ------------------------- | -------------------------- |
-| [Projects](projects.md) | `order_by=id` only |
+| Resource | Order |
+|-------------------------|-------|
+| [Projects](projects.md) | `order_by=id` only. |
## Path parameters
-If an endpoint has path parameters, the documentation shows them with a preceding colon.
+If an endpoint has path parameters, the documentation displays them with a
+preceding colon.
For example:
@@ -470,7 +514,9 @@ For example:
DELETE /projects/:id/share/:group_id
```
-The `:id` path parameter needs to be replaced with the project ID, and the `:group_id` needs to be replaced with the ID of the group. The colons `:` should not be included.
+The `:id` path parameter needs to be replaced with the project ID, and the
+`:group_id` needs to be replaced with the ID of the group. The colons `:`
+shouldn't be included.
The resulting cURL call for a project with ID `5` and a group ID of `17` is then:
@@ -478,11 +524,10 @@ The resulting cURL call for a project with ID `5` and a group ID of `17` is then
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/share/17"
```
-NOTE: **Note:**
Path parameters that are required to be URL-encoded must be followed. If not,
-it will not match an API endpoint and respond with a 404. If there's something
-in front of the API (for example, Apache), ensure that it won't decode the URL-encoded
-path parameters.
+it won't match an API endpoint, and will respond with a 404. If there's
+something in front of the API (for example, Apache), ensure that it won't decode
+the URL-encoded path parameters.
## Namespaced path encoding
@@ -495,10 +540,9 @@ For example, `/` is represented by `%2F`:
GET /api/v4/projects/diaspora%2Fdiaspora
```
-NOTE: **Note:**
-A project's **path** is not necessarily the same as its **name**. A
-project's path can be found in the project's URL or in the project's settings
-under **General > Advanced > Change path**.
+A project's _path_ isn't necessarily the same as its _name_. A project's path is
+found in the project's URL or in the project's settings, under
+**General > Advanced > Change path**.
## File path, branches, and tags name encoding
@@ -516,7 +560,8 @@ GET /api/v4/projects/1/repository/tags/my%2Ftag
API Requests can use parameters sent as [query strings](https://en.wikipedia.org/wiki/Query_string)
or as a [payload body](https://tools.ietf.org/html/draft-ietf-httpbis-p3-payload-14#section-3.2).
-GET requests usually send a query string, while PUT/POST requests usually send the payload body:
+GET requests usually send a query string, while PUT or POST requests usually
+send the payload body:
- Query string:
@@ -530,13 +575,13 @@ GET requests usually send a query string, while PUT/POST requests usually send t
curl --request POST --header "Content-Type: application/json" --data '{"name":"<example-name>", "description":"<example-description"}' "https://gitlab/api/v4/projects"
```
-URL encoded query strings have a length limitation. Requests that are too large will
-result in a `414 Request-URI Too Large` error message. This can be resolved by using
-a payload body instead.
+URL encoded query strings have a length limitation. Requests that are too large
+result in a `414 Request-URI Too Large` error message. This can be resolved by
+using a payload body instead.
## Encoding API parameters of `array` and `hash` types
-We can call the API with `array` and `hash` types parameters as shown below:
+We can call the API with `array` and `hash` types parameters as follows:
### `array`
@@ -565,7 +610,8 @@ https://gitlab.example.com/api/v4/projects/import
### Array of hashes
-`variables` is a parameter of type `array` containing hash key/value pairs `[{ 'key': 'UPLOAD_TO_S3', 'value': 'true' }]`:
+`variables` is a parameter of type `array` containing hash key/value pairs
+`[{ 'key': 'UPLOAD_TO_S3', 'value': 'true' }]`:
```shell
curl --globoff --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
@@ -579,34 +625,37 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
## `id` vs `iid`
- Some resources have two similarly-named fields. For example, [issues](issues.md), [merge requests](merge_requests.md), and [project milestones](merge_requests.md). The fields are:
+Some resources have two similarly-named fields. For example, [issues](issues.md),
+[merge requests](merge_requests.md), and [project milestones](merge_requests.md).
+The fields are:
- `id`: ID that is unique across all projects.
-- `iid`: additional, internal ID that is unique in the scope of a single project.
+- `iid`: Additional, internal ID (displayed in the web UI) that's unique in the
+ scope of a single project.
-NOTE: **Note:**
-The `iid` is displayed in the web UI.
-
-If a resource has the `iid` field and the `id` field, the `iid` field is usually used instead of `id` to fetch the resource.
+If a resource has both the `iid` field and the `id` field, the `iid` field is
+usually used instead of `id` to fetch the resource.
-For example, suppose a project with `id: 42` has an issue with `id: 46` and `iid: 5`. In this case:
+For example, suppose a project with `id: 42` has an issue with `id: 46` and
+`iid: 5`. In this case:
-- A valid API call to retrieve the issue is `GET /projects/42/issues/5`
+- A valid API call to retrieve the issue is `GET /projects/42/issues/5`.
- An invalid API call to retrieve the issue is `GET /projects/42/issues/46`.
-NOTE: **Note:**
-Not all resources with the `iid` field are fetched by `iid`. For guidance on which field to use, see the documentation for the specific resource.
+Not all resources with the `iid` field are fetched by `iid`. For guidance
+regarding which field to use, see the documentation for the specific resource.
## Data validation and error reporting
When working with the API you may encounter validation errors, in which case
-the API will answer with an HTTP `400` status.
+the API returns an HTTP `400` error.
-Such errors appear in two cases:
+Such errors appear in the following cases:
-- A required attribute of the API request is missing, e.g., the title of an
- issue is not given
-- An attribute did not pass the validation, e.g., the user bio is too long
+- A required attribute of the API request is missing (for example, the title of
+ an issue isn't given).
+- An attribute did not pass the validation (for example, the user bio is too
+ long).
When an attribute is missing, you will get something like:
@@ -618,8 +667,8 @@ Content-Type: application/json
}
```
-When a validation error occurs, error messages will be different. They will
-hold all details of validation errors:
+When a validation error occurs, error messages will be different. They will hold
+all details of validation errors:
```http
HTTP/1.1 400 Bad Request
@@ -657,7 +706,8 @@ follows:
## Unknown route
-When you try to access an API URL that does not exist, you will receive 404 Not Found.
+When you attempt to access an API URL that doesn't exist, you will receive
+404 Not Found message.
```http
HTTP/1.1 404 Not Found
@@ -669,10 +719,10 @@ Content-Type: application/json
## Encoding `+` in ISO 8601 dates
-If you need to include a `+` in a query parameter, you may need to use `%2B` instead due
-to a [W3 recommendation](http://www.w3.org/Addressing/URL/4_URI_Recommentations.html) that
-causes a `+` to be interpreted as a space. For example, in an ISO 8601 date, you may want to pass
-a time in Mountain Standard Time, such as:
+If you need to include a `+` in a query parameter, you may need to use `%2B`
+instead, due to a [W3 recommendation](http://www.w3.org/Addressing/URL/4_URI_Recommentations.html)
+that causes a `+` to be interpreted as a space. For example, in an ISO 8601 date,
+you may want to include a specific time in ISO 8601 format, such as:
```plaintext
2017-10-17T23:11:13.000+05:30
@@ -686,8 +736,8 @@ The correct encoding for the query parameter would be:
## Clients
-There are many unofficial GitLab API Clients for most of the popular
-programming languages. Visit the [GitLab website](https://about.gitlab.com/partners/#api-clients) for a complete list.
+There are many unofficial GitLab API Clients for most of the popular programming
+languages. For a complete list, visit the [GitLab website](https://about.gitlab.com/partners/#api-clients).
## Rate limits
diff --git a/doc/api/admin_sidekiq_queues.md b/doc/api/admin_sidekiq_queues.md
index 22488d053b4..8e1f7260208 100644
--- a/doc/api/admin_sidekiq_queues.md
+++ b/doc/api/admin_sidekiq_queues.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Sidekiq queues administration API **(CORE ONLY)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25998) in GitLab 12.9
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index 199b244b2c3..7ef3b5fcbb6 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# API resources
Available resources for the [GitLab API](README.md) can be grouped in the following contexts:
@@ -34,6 +40,7 @@ The following API resources are available in the project context:
| [Events](events.md) | `/projects/:id/events` (also available for users and standalone) |
| [Feature Flags](feature_flags.md) | `/projects/:id/feature_flags` |
| [Feature Flag User Lists](feature_flag_user_lists.md) | `/projects/:id/feature_flags_user_lists` |
+| [Invitations](invitations.md) | `/projects/:id/invitations` (also available for groups) |
| [Issues](issues.md) | `/projects/:id/issues` (also available for groups and standalone) |
| [Issues Statistics](issues_statistics.md) | `/projects/:id/issues_statistics` (also available for groups and standalone) |
| [Issue boards](boards.md) | `/projects/:id/boards` |
@@ -102,6 +109,7 @@ The following API resources are available in the group context:
| [Group labels](group_labels.md) | `/groups/:id/labels` |
| [Group-level variables](group_level_variables.md) | `/groups/:id/variables` |
| [Group milestones](group_milestones.md) | `/groups/:id/milestones` |
+| [Invitations](invitations.md) | `/groups/:id/invitations` (also available for projects) |
| [Issues](issues.md) | `/groups/:id/issues` (also available for projects and standalone) |
| [Issues Statistics](issues_statistics.md) | `/groups/:id/issues_statistics` (also available for projects and standalone) |
| [Members](members.md) | `/groups/:id/members` (also available for projects) |
diff --git a/doc/api/appearance.md b/doc/api/appearance.md
index 47a9d48a4ae..07d26b1a643 100644
--- a/doc/api/appearance.md
+++ b/doc/api/appearance.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Appearance API **(CORE ONLY)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16647) in GitLab 12.7.
diff --git a/doc/api/applications.md b/doc/api/applications.md
index 379f346c019..a3216bdddde 100644
--- a/doc/api/applications.md
+++ b/doc/api/applications.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Applications API
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8160) in GitLab 10.5.
diff --git a/doc/api/audit_events.md b/doc/api/audit_events.md
index 5f31919c52b..5fdf0c20f1a 100644
--- a/doc/api/audit_events.md
+++ b/doc/api/audit_events.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Audit Events API
## Instance Audit Events **(PREMIUM ONLY)**
diff --git a/doc/api/avatar.md b/doc/api/avatar.md
index 223704d3e6c..aec1ba67d45 100644
--- a/doc/api/avatar.md
+++ b/doc/api/avatar.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Avatar API
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19121) in GitLab 11.0.
diff --git a/doc/api/boards.md b/doc/api/boards.md
index 12ebbcf916a..228c0ca322b 100644
--- a/doc/api/boards.md
+++ b/doc/api/boards.md
@@ -4,16 +4,16 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Issue Boards API
+# Project Issue Boards API
Every API call to boards must be authenticated.
If a user is not a member of a project and the project is private, a `GET`
request on that project will result to a `404` status code.
-## Project Board
+## List project issue boards
-Lists Issue Boards in the given project.
+Lists project issue boards in the given project.
```plaintext
GET /projects/:id/boards
@@ -33,6 +33,7 @@ Example response:
[
{
"id" : 1,
+ "name": "board1",
"project": {
"id": 5,
"name": "Diaspora Project Site",
@@ -88,9 +89,15 @@ Example response:
]
```
-## Single board
+Another example response when no board has been activated or exist in the project:
-Get a single board.
+```json
+[]
+```
+
+## Show a single issue board
+
+Get a single project issue board.
```plaintext
GET /projects/:id/boards/:board_id
@@ -165,9 +172,9 @@ Example response:
}
```
-## Create a board **(STARTER)**
+## Create an issue board
-Creates a board.
+Creates a project issue board.
```plaintext
POST /projects/:id/boards
@@ -197,70 +204,34 @@ Example response:
"web_url": "http://example.com/diaspora/diaspora-project-site"
},
"name": "newboard",
- "milestone": {
- "id": 12
- "title": "10.0"
- },
- "lists" : [
- {
- "id" : 1,
- "label" : {
- "name" : "Testing",
- "color" : "#F0AD4E",
- "description" : null
- },
- "position" : 1,
- "max_issue_count": 0,
- "max_issue_weight": 0,
- "limit_metric": null
- },
- {
- "id" : 2,
- "label" : {
- "name" : "Ready",
- "color" : "#FF0000",
- "description" : null
- },
- "position" : 2,
- "max_issue_count": 0,
- "max_issue_weight": 0,
- "limit_metric": null
- },
- {
- "id" : 3,
- "label" : {
- "name" : "Production",
- "color" : "#FF5F00",
- "description" : null
- },
- "position" : 3,
- "max_issue_count": 0,
- "max_issue_weight": 0,
- "limit_metric": null
- }
- ]
+ "lists" : [],
+ "group": null,
+ "milestone": null,
+ "assignee" : null,
+ "labels" : [],
+ "weight" : null
}
```
-## Update a board **(STARTER)**
+## Update an issue board
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5954) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.1.
-Updates a board.
+Updates a project issue board.
```plaintext
PUT /projects/:id/boards/:board_id
```
-| Attribute | Type | Required | Description |
-| ------------------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `board_id` | integer | yes | The ID of a board |
-| `name` | string | no | The new name of the board |
-| `assignee_id` | integer | no | The assignee the board should be scoped to |
-| `milestone_id` | integer | no | The milestone the board should be scoped to |
-| `labels` | string | no | Comma-separated list of label names which the board should be scoped to |
-| `weight` | integer | no | The weight range from 0 to 9, to which the board should be scoped to |
+| Attribute | Type | Required | Description |
+| ---------------------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `board_id` | integer | yes | The ID of a board |
+| `name` | string | no | The new name of the board |
+| `assignee_id` **(STARTER)** | integer | no | The assignee the board should be scoped to |
+| `milestone_id` **(STARTER)** | integer | no | The milestone the board should be scoped to |
+| `labels` **(STARTER)** | string | no | Comma-separated list of label names which the board should be scoped to |
+| `weight` **(STARTER)** | integer | no | The weight range from 0 to 9, to which the board should be scoped to |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/boards/1?name=new_name&milestone_id=43&assignee_id=1&labels=Doing&weight=4"
@@ -323,9 +294,9 @@ Example response:
}
```
-## Delete a board **(STARTER)**
+## Delete an issue board
-Deletes a board.
+Deletes a project issue board.
```plaintext
DELETE /projects/:id/boards/:board_id
@@ -340,10 +311,10 @@ DELETE /projects/:id/boards/:board_id
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/boards/1"
```
-## List board lists
+## List board lists in a project issue board
Get a list of the board's lists.
-Does not include `open` and `closed` lists
+Does not include `open` and `closed` lists.
```plaintext
GET /projects/:id/boards/:board_id/lists
@@ -401,7 +372,7 @@ Example response:
]
```
-## Single board list
+## Show a single board list
Get a single board list.
@@ -436,9 +407,9 @@ Example response:
}
```
-## New board list
+## Create a board list
-Creates a new Issue Board list.
+Creates a new issue board list.
```plaintext
POST /projects/:id/boards/:board_id/lists
@@ -479,9 +450,9 @@ Example response:
}
```
-## Edit board list
+## Reorder a list in a board
-Updates an existing Issue Board list. This call is used to change list position.
+Updates an existing issue board list. This call is used to change list position.
```plaintext
PUT /projects/:id/boards/:board_id/lists/:list_id
@@ -515,7 +486,7 @@ Example response:
}
```
-## Delete a board list
+## Delete a board list from a board
Only for admins and project owners. Deletes the board list in question.
diff --git a/doc/api/broadcast_messages.md b/doc/api/broadcast_messages.md
index 37156186d03..f7253da297d 100644
--- a/doc/api/broadcast_messages.md
+++ b/doc/api/broadcast_messages.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Broadcast Messages API
> Introduced in GitLab 8.12.
@@ -92,8 +98,8 @@ Parameters:
| Attribute | Type | Required | Description |
|:----------------|:---------|:---------|:------------------------------------------------------|
| `message` | string | yes | Message to display. |
-| `starts_at` | datetime | no | Starting time (defaults to current time). |
-| `ends_at` | datetime | no | Ending time (defaults to one hour from current time). |
+| `starts_at` | datetime | no | Starting time (defaults to current time). Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `ends_at` | datetime | no | Ending time (defaults to one hour from current time). Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `color` | string | no | Background color hex code. |
| `font` | string | no | Foreground color hex code. |
| `target_path` | string | no | Target path of the broadcast message. |
@@ -137,8 +143,8 @@ Parameters:
|:----------------|:---------|:---------|:--------------------------------------|
| `id` | integer | yes | ID of broadcast message to update. |
| `message` | string | no | Message to display. |
-| `starts_at` | datetime | no | Starting time. |
-| `ends_at` | datetime | no | Ending time. |
+| `starts_at` | datetime | no | Starting time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `ends_at` | datetime | no | Ending time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `color` | string | no | Background color hex code. |
| `font` | string | no | Foreground color hex code. |
| `target_path` | string | no | Target path of the broadcast message. |
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 66b34d4bc75..d60acaad94d 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -631,7 +631,7 @@ GET /projects/:id/repository/commits/:sha/statuses
| `sha` | string | yes | The commit SHA
| `ref` | string | no | The name of a repository branch or tag or, if not given, the default branch
| `stage` | string | no | Filter by [build stage](../ci/yaml/README.md#stages), e.g., `test`
-| `name` | string | no | Filter by [job name](../ci/yaml/README.md#introduction), e.g., `bundler:audit`
+| `name` | string | no | Filter by [job name](../ci/yaml/README.md#job-keywords), e.g., `bundler:audit`
| `all` | boolean | no | Return all statuses, not only the latest ones
```shell
@@ -842,7 +842,8 @@ Example response if commit is GPG signed:
"gpg_key_primary_keyid": "8254AAB3FBD54AC9",
"gpg_key_user_name": "John Doe",
"gpg_key_user_email": "johndoe@example.com",
- "gpg_key_subkey_id": null
+ "gpg_key_subkey_id": null,
+ "commit_source": "gitaly"
}
```
@@ -865,7 +866,8 @@ Example response if commit is X.509 signed:
"subject_key_identifier": "AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB",
"crl_url": "http://example.com/pki.crl"
}
- }
+ },
+ "commit_source": "gitaly"
}
```
diff --git a/doc/api/container_registry.md b/doc/api/container_registry.md
index 3a7ebf9a2aa..ddfe5d3f238 100644
--- a/doc/api/container_registry.md
+++ b/doc/api/container_registry.md
@@ -124,6 +124,48 @@ Example response:
]
```
+## Get details of a single repository
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/209916) in GitLab 13.6.
+
+Get details of a registry repository.
+
+```plaintext
+GET /registry/repositories/:id
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID of the registry repository accessible by the authenticated user. |
+| `tags` | boolean | no | If the parameter is included as `true`, the response includes an array of `"tags"`. |
+| `tags_count` | boolean | no | If the parameter is included as `true`, the response includes `"tags_count"`. |
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/registry/repositories/2?tags=true&tags_count=true"
+```
+
+Example response:
+
+```json
+{
+ "id": 2,
+ "name": "",
+ "path": "group/project",
+ "project_id": 9,
+ "location": "gitlab.example.com:5000/group/project",
+ "created_at": "2019-01-10T13:38:57.391Z",
+ "cleanup_policy_started_at": "2020-08-17T03:12:35.489Z",
+ "tags_count": 1,
+ "tags": [
+ {
+ "name": "0.0.1",
+ "path": "group/project:0.0.1",
+ "location": "gitlab.example.com:5000/group/project:0.0.1"
+ }
+ ]
+}
+```
+
## Delete registry repository
Delete a repository in registry.
@@ -238,7 +280,7 @@ This action doesn't delete blobs. To delete them and recycle disk space,
Delete registry repository tags in bulk based on given criteria.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview, see [Utilize the Container Registry API to delete all tags except *](https://youtu.be/Hi19bKe_xsg).
+For an overview, see [Use the Container Registry API to delete all tags except *](https://youtu.be/Hi19bKe_xsg).
```plaintext
DELETE /projects/:id/registry/repositories/:repository_id/tags
diff --git a/doc/api/custom_attributes.md b/doc/api/custom_attributes.md
index 07ece99f9b1..76c8474ee95 100644
--- a/doc/api/custom_attributes.md
+++ b/doc/api/custom_attributes.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Custom Attributes API
Every API call to custom attributes must be authenticated as administrator.
diff --git a/doc/api/dependencies.md b/doc/api/dependencies.md
index 56d33bf151a..2f65ff7b8d9 100644
--- a/doc/api/dependencies.md
+++ b/doc/api/dependencies.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Dependencies API **(ULTIMATE)**
CAUTION: **Caution:**
diff --git a/doc/api/dependency_proxy.md b/doc/api/dependency_proxy.md
index a379f1481c1..4d937027dec 100644
--- a/doc/api/dependency_proxy.md
+++ b/doc/api/dependency_proxy.md
@@ -1,11 +1,21 @@
-# Dependency Proxy API **(PREMIUM)**
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# Dependency Proxy API
## Purge the dependency proxy for a group
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11631) in GitLab 12.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11631) in GitLab 12.10.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/273655) to [GitLab Core](https://about.gitlab.com/pricing/) in GitLab 13.6.
Deletes the cached blobs for a group. This endpoint requires group admin access.
+CAUTION: **Warning:**
+[A bug exists](https://gitlab.com/gitlab-org/gitlab/-/issues/277161) for this API.
+
```plaintext
DELETE /groups/:id/dependency_proxy/cache
```
diff --git a/doc/api/deploy_tokens.md b/doc/api/deploy_tokens.md
index f11f88ab5c9..ce55657ce27 100644
--- a/doc/api/deploy_tokens.md
+++ b/doc/api/deploy_tokens.md
@@ -96,7 +96,7 @@ POST /projects/:id/deploy_tokens
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | New deploy token's name |
-| `expires_at` | datetime | no | Expiration date for the deploy token. Does not expire if no value is provided. |
+| `expires_at` | datetime | no | Expiration date for the deploy token. Does not expire if no value is provided. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `username` | string | no | Username for deploy token. Default is `gitlab+deploy-token-{n}` |
| `scopes` | array of strings | yes | Indicates the deploy token scopes. Must be at least one of `read_repository`, `read_registry`, `write_registry`, `read_package_registry`, or `write_package_registry`. |
@@ -198,7 +198,7 @@ POST /groups/:id/deploy_tokens
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | New deploy token's name |
-| `expires_at` | datetime | no | Expiration date for the deploy token. Does not expire if no value is provided. |
+| `expires_at` | datetime | no | Expiration date for the deploy token. Does not expire if no value is provided. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `username` | string | no | Username for deploy token. Default is `gitlab+deploy-token-{n}` |
| `scopes` | array of strings | yes | Indicates the deploy token scopes. Must be at least one of `read_repository`, `read_registry`, `write_registry`, `read_package_registry`, or `write_package_registry`. |
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index b0de972160b..0bc72c93be7 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -20,8 +20,8 @@ GET /projects/:id/deployments
| `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 |
+| `updated_after` | datetime | no | Return deployments updated after the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_before` | datetime | no | Return deployments updated before the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `environment` | string | no | The [name of the environment](../ci/environments/index.md#defining-environments) to filter deployments by |
| `status` | string | no | The status to filter deployments by |
@@ -379,7 +379,7 @@ This API retrieves the list of merge requests shipped with a given deployment:
GET /projects/:id/deployments/:deployment_id/merge_requests
```
-It supports the same parameters as the [Merge Requests API](./merge_requests.md#list-merge-requests) and will return a response using the same format:
+It supports the same parameters as the [Merge Requests API](merge_requests.md#list-merge-requests) and will return a response using the same format:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/42"
diff --git a/doc/api/epic_issues.md b/doc/api/epic_issues.md
index 4ab505f3627..21ba75d37a5 100644
--- a/doc/api/epic_issues.md
+++ b/doc/api/epic_issues.md
@@ -1,6 +1,6 @@
---
stage: Plan
-group: Portfolio Management
+group: Product Planning
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
diff --git a/doc/api/epic_links.md b/doc/api/epic_links.md
index 19c8dc78aed..a368b806f75 100644
--- a/doc/api/epic_links.md
+++ b/doc/api/epic_links.md
@@ -1,3 +1,9 @@
+---
+stage: Plan
+group: Product Planning
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Epic Links API **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9188) in GitLab 11.8.
diff --git a/doc/api/epics.md b/doc/api/epics.md
index 5c7366c8457..74cde87bb91 100644
--- a/doc/api/epics.md
+++ b/doc/api/epics.md
@@ -1,6 +1,6 @@
---
stage: Plan
-group: Portfolio Management
+group: Product Planning
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
@@ -67,10 +67,10 @@ GET /groups/:id/epics?state=opened
| `sort` | string | no | Return epics sorted in `asc` or `desc` order. Default is `desc` |
| `search` | string | no | Search epics against their `title` and `description` |
| `state` | string | no | Search epics against their `state`, possible filters: `opened`, `closed` and `all`, default: `all` |
-| `created_after` | datetime | no | Return epics created on or after the given time |
-| `created_before` | datetime | no | Return epics created on or before the given time |
-| `updated_after` | datetime | no | Return epics updated on or after the given time |
-| `updated_before` | datetime | no | Return epics updated on or before the given time |
+| `created_after` | datetime | no | Return epics created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `created_before` | datetime | no | Return epics created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_after` | datetime | no | Return epics updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_before` | datetime | no | Return epics updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `include_ancestor_groups` | boolean | no | Include epics from the requested group's ancestors. Default is `false` |
| `include_descendant_groups` | boolean | no | Include epics from the requested group's descendants. Default is `true` |
| `my_reaction_emoji` | string | no | Return epics reacted by the authenticated user by the given emoji. `None` returns epics not given a reaction. `Any` returns epics given at least one reaction. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31479)|
@@ -349,7 +349,9 @@ PUT /groups/:id/epics/:epic_iid
| `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 |
-| `labels` | string | no | The comma separated list of labels |
+| `labels` | string | no | Comma-separated label names for an issue. Set to an empty string to unassign all labels. |
+| `add_labels` | string | no | Comma-separated label names to add to an issue. |
+| `remove_labels` | string | no | Comma-separated label names to remove from an issue. |
| `updated_at` | string | no | When the epic was updated. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` . Requires administrator or project/group owner privileges ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255309) in GitLab 13.5) |
| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (since 11.3) |
| `start_date_fixed` | string | no | The fixed start date of an epic (since 11.3) |
@@ -424,10 +426,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 to do
+## Create a to-do item
-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
+Manually creates a to-do item for the current user on an epic. If
+there already exists a to-do item for the user on that epic, status code `304` is
returned.
```plaintext
diff --git a/doc/api/events.md b/doc/api/events.md
index 3f4f11b9786..e59630d1358 100644
--- a/doc/api/events.md
+++ b/doc/api/events.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Events
## Filter parameters
@@ -6,6 +12,7 @@
Available action types for the `action` parameter are:
+- `approved`
- `created`
- `updated`
- `closed`
diff --git a/doc/api/experiments.md b/doc/api/experiments.md
index 66c444e54ce..7e2cad1070b 100644
--- a/doc/api/experiments.md
+++ b/doc/api/experiments.md
@@ -8,13 +8,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/262725) in GitLab 13.5.
-This API is for listing Experiments [experiment use in development of GitLab](../development/experiment_guide/index.md).
+This API is for listing A/B experiments [defined in GitLab](../development/experiment_guide/index.md).
-All methods require user be a [GitLab team member](https://gitlab.com/groups/gitlab-com/-/group_members) for authorization.
+The user must be a [GitLab team member](https://gitlab.com/groups/gitlab-com/-/group_members) to access the API.
## List all experiments
-Get a list of all experiments, with its enabled status.
+Get a list of all experiments. Each experiment has an `enabled` status that indicates whether the experiment is enabled globally, or only in specific contexts.
```plaintext
GET /experiments
diff --git a/doc/api/feature_flag_user_lists.md b/doc/api/feature_flag_user_lists.md
index b44cb1fb9f2..7cdfcb8d074 100644
--- a/doc/api/feature_flag_user_lists.md
+++ b/doc/api/feature_flag_user_lists.md
@@ -25,9 +25,10 @@ Gets all feature flag user lists for the requested project.
GET /projects/:id/feature_flags_user_lists
```
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| Attribute | Type | Required | Description |
+| --------- | -------------- | -------- | -------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `search` | string | no | Return user lists matching the search criteria. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists"
diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md
index 064bd26ee72..c9b86320a9f 100644
--- a/doc/api/geo_nodes.md
+++ b/doc/api/geo_nodes.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Geo Nodes API **(PREMIUM ONLY)**
To interact with Geo node endpoints, you need to authenticate yourself as an
diff --git a/doc/api/graphql/audit_report.md b/doc/api/graphql/audit_report.md
index 36c3f44ff89..12663654026 100644
--- a/doc/api/graphql/audit_report.md
+++ b/doc/api/graphql/audit_report.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Set up an Audit Report with GraphQL
This page describes how you can use the GraphiQL explorer to set up an audit report
diff --git a/doc/api/graphql/getting_started.md b/doc/api/graphql/getting_started.md
index c2220403461..8501e76b5aa 100644
--- a/doc/api/graphql/getting_started.md
+++ b/doc/api/graphql/getting_started.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Getting started with GitLab GraphQL API
This guide demonstrates basic usage of GitLab's GraphQL API.
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index bda24a7e90a..91917ea47a4 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GraphQL API
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19008) in GitLab 11.0 (enabled by feature flag `graphql`).
@@ -76,6 +82,10 @@ The process is as follows:
release post (at or prior to X.11 and X.5 releases).
1. Fields meeting criteria are removed in X.0 or X.6.
+### List of removed items
+
+View the [fields, enums, and other items we removed](removed_items.md) from the GraphQL API.
+
## Available queries
The GraphQL API includes the following queries at the root level:
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index a44f8f70311..58f7d8ecdcf 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -591,6 +591,178 @@ type AlertManagementAlertStatusCountsType {
}
"""
+An endpoint and credentials used to accept alerts for a project
+"""
+type AlertManagementHttpIntegration implements AlertManagementIntegration {
+ """
+ Whether the endpoint is currently accepting alerts
+ """
+ active: Boolean
+
+ """
+ URL at which Prometheus metrics can be queried to populate the metrics dashboard
+ """
+ apiUrl: String
+
+ """
+ ID of the integration
+ """
+ id: ID!
+
+ """
+ Name of the integration
+ """
+ name: String
+
+ """
+ Token used to authenticate alert notification requests
+ """
+ token: String
+
+ """
+ Type of integration
+ """
+ type: AlertManagementIntegrationType!
+
+ """
+ Endpoint which accepts alert notifications
+ """
+ url: String
+}
+
+"""
+Identifier of AlertManagement::HttpIntegration
+"""
+scalar AlertManagementHttpIntegrationID
+
+interface AlertManagementIntegration {
+ """
+ Whether the endpoint is currently accepting alerts
+ """
+ active: Boolean
+
+ """
+ URL at which Prometheus metrics can be queried to populate the metrics dashboard
+ """
+ apiUrl: String
+
+ """
+ ID of the integration
+ """
+ id: ID!
+
+ """
+ Name of the integration
+ """
+ name: String
+
+ """
+ Token used to authenticate alert notification requests
+ """
+ token: String
+
+ """
+ Type of integration
+ """
+ type: AlertManagementIntegrationType!
+
+ """
+ Endpoint which accepts alert notifications
+ """
+ url: String
+}
+
+"""
+The connection type for AlertManagementIntegration.
+"""
+type AlertManagementIntegrationConnection {
+ """
+ A list of edges.
+ """
+ edges: [AlertManagementIntegrationEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [AlertManagementIntegration]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type AlertManagementIntegrationEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: AlertManagementIntegration
+}
+
+"""
+Values of types of integrations
+"""
+enum AlertManagementIntegrationType {
+ """
+ Integration with any monitoring tool
+ """
+ HTTP
+
+ """
+ Prometheus integration
+ """
+ PROMETHEUS
+}
+
+"""
+An endpoint and credentials used to accept Prometheus alerts for a project
+"""
+type AlertManagementPrometheusIntegration implements AlertManagementIntegration {
+ """
+ Whether the endpoint is currently accepting alerts
+ """
+ active: Boolean
+
+ """
+ URL at which Prometheus metrics can be queried to populate the metrics dashboard
+ """
+ apiUrl: String
+
+ """
+ ID of the integration
+ """
+ id: ID!
+
+ """
+ Name of the integration
+ """
+ name: String
+
+ """
+ Token used to authenticate alert notification requests
+ """
+ token: String
+
+ """
+ Type of integration
+ """
+ type: AlertManagementIntegrationType!
+
+ """
+ Endpoint which accepts alert notifications
+ """
+ url: String
+}
+
+"""
Alert severity values
"""
enum AlertManagementSeverity {
@@ -761,6 +933,21 @@ type AlertTodoCreatePayload {
}
"""
+User availability status
+"""
+enum AvailabilityEnum {
+ """
+ Busy
+ """
+ BUSY
+
+ """
+ Not Set
+ """
+ NOT_SET
+}
+
+"""
An emoji awarded by a user
"""
type AwardEmoji {
@@ -1134,7 +1321,7 @@ type Board {
"""
Find a list by its global ID
"""
- id: ID
+ id: ListID
"""
Filters applied when getting issue metadata in the board list
@@ -1253,6 +1440,11 @@ type BoardEpic implements CurrentUserTodos & Noteable {
iids: [ID!]
"""
+ Include epics from descendant groups
+ """
+ includeDescendantGroups: Boolean = true
+
+ """
Filter epics by labels
"""
labelName: [String!]
@@ -1611,6 +1803,16 @@ type BoardEpic implements CurrentUserTodos & Noteable {
upvotes: Int!
"""
+ Number of user discussions in the epic
+ """
+ userDiscussionsCount: Int!
+
+ """
+ Number of user notes of the epic
+ """
+ userNotesCount: Int!
+
+ """
Permissions for the current user on the resource
"""
userPermissions: EpicPermissions!
@@ -1695,7 +1897,7 @@ input BoardIssueInput {
"""
Filter by epic ID. Incompatible with epicWildcardId
"""
- epicId: ID
+ epicId: EpicID
"""
Filter by epic ID wildcard. Incompatible with epicId
@@ -1703,6 +1905,16 @@ input BoardIssueInput {
epicWildcardId: EpicWildcardId
"""
+ Filter by iteration title
+ """
+ iterationTitle: String
+
+ """
+ Filter by iteration ID wildcard
+ """
+ iterationWildcardId: IterationWildcardId
+
+ """
Filter by label name
"""
labelName: [String]
@@ -2134,6 +2346,11 @@ type CiJob {
): CiJobConnection
"""
+ Pipeline the job belongs to
+ """
+ pipeline: Pipeline!
+
+ """
Schedule for the build
"""
scheduledAt: Time
@@ -2308,6 +2525,11 @@ The connection type for ClusterAgent.
"""
type ClusterAgentConnection {
"""
+ Total count of collection
+ """
+ count: Int!
+
+ """
A list of edges.
"""
edges: [ClusterAgentEdge]
@@ -2390,6 +2612,11 @@ The connection type for ClusterAgentToken.
"""
type ClusterAgentTokenConnection {
"""
+ Total count of collection
+ """
+ count: Int!
+
+ """
A list of edges.
"""
edges: [ClusterAgentTokenEdge]
@@ -2505,6 +2732,86 @@ Identifier of Clusters::Cluster
"""
scalar ClustersClusterID
+"""
+Represents the code coverage activity for a group
+"""
+type CodeCoverageActivity {
+ """
+ Average percentage of the different code coverage results available for the group.
+ """
+ averageCoverage: Float
+
+ """
+ Number of different code coverage results available for the group.
+ """
+ coverageCount: Int
+
+ """
+ Date when the code coverage was created.
+ """
+ date: Date!
+
+ """
+ Number of projects with code coverage results for the group.
+ """
+ projectCount: Int
+}
+
+"""
+The connection type for CodeCoverageActivity.
+"""
+type CodeCoverageActivityConnection {
+ """
+ A list of edges.
+ """
+ edges: [CodeCoverageActivityEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [CodeCoverageActivity]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type CodeCoverageActivityEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: CodeCoverageActivity
+}
+
+"""
+Represents the code coverage summary for a project
+"""
+type CodeCoverageSummary {
+ """
+ Average percentage of the different code coverage results available for the project.
+ """
+ averageCoverage: Float
+
+ """
+ Number of different code coverage results available.
+ """
+ coverageCount: Int
+
+ """
+ Latest date when the code coverage was created for the project.
+ """
+ lastUpdatedOn: Date
+}
+
type Commit {
"""
Author of the commit
@@ -2542,26 +2849,6 @@ type Commit {
id: ID!
"""
- Latest pipeline of the commit. Deprecated in 12.5: Use `pipelines`
- """
- latestPipeline(
- """
- Filter pipelines by the ref they are run for
- """
- ref: String
-
- """
- Filter pipelines by the sha of the commit they are run for
- """
- sha: String
-
- """
- Filter pipelines by their status
- """
- status: PipelineStatusEnum
- ): Pipeline @deprecated(reason: "Use `pipelines`. Deprecated in 12.5")
-
- """
Raw commit message
"""
message: String
@@ -2714,7 +3001,7 @@ input CommitCreateInput {
actions: [CommitAction!]!
"""
- Name of the branch
+ Name of the branch to commit into, it can be a new branch
"""
branch: String!
@@ -2732,6 +3019,11 @@ input CommitCreateInput {
Project full path the branch is associated with
"""
projectPath: ID!
+
+ """
+ If on a new branch, name of the original branch
+ """
+ startBranch: String
}
"""
@@ -2773,7 +3065,7 @@ type ComplianceFramework {
"""
Name of the compliance framework
"""
- name: ProjectSettingEnum!
+ name: String!
}
"""
@@ -2988,6 +3280,316 @@ enum ContainerExpirationPolicyOlderThanEnum {
}
"""
+A container repository
+"""
+type ContainerRepository {
+ """
+ Can the current user delete the container repository.
+ """
+ canDelete: Boolean!
+
+ """
+ Timestamp when the container repository was created.
+ """
+ createdAt: Time!
+
+ """
+ The tags cleanup status for the container repository.
+ """
+ expirationPolicyCleanupStatus: ContainerRepositoryCleanupStatus
+
+ """
+ Timestamp when the cleanup done by the expiration policy was started on the container repository.
+ """
+ expirationPolicyStartedAt: Time
+
+ """
+ ID of the container repository.
+ """
+ id: ID!
+
+ """
+ URL of the container repository.
+ """
+ location: String!
+
+ """
+ Name of the container repository.
+ """
+ name: String!
+
+ """
+ Path of the container repository.
+ """
+ path: String!
+
+ """
+ Status of the container repository.
+ """
+ status: ContainerRepositoryStatus
+
+ """
+ Number of tags associated with this image.
+ """
+ tagsCount: Int!
+
+ """
+ Timestamp when the container repository was updated.
+ """
+ updatedAt: Time!
+}
+
+"""
+Status of the tags cleanup of a container repository
+"""
+enum ContainerRepositoryCleanupStatus {
+ """
+ The tags cleanup is ongoing.
+ """
+ ONGOING
+
+ """
+ The tags cleanup is scheduled and is going to be executed shortly.
+ """
+ SCHEDULED
+
+ """
+ The tags cleanup has been partially executed. There are still remaining tags to delete.
+ """
+ UNFINISHED
+
+ """
+ The tags cleanup is not scheduled. This is the default state.
+ """
+ UNSCHEDULED
+}
+
+"""
+The connection type for ContainerRepository.
+"""
+type ContainerRepositoryConnection {
+ """
+ A list of edges.
+ """
+ edges: [ContainerRepositoryEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [ContainerRepository]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+Details of a container repository
+"""
+type ContainerRepositoryDetails {
+ """
+ Can the current user delete the container repository.
+ """
+ canDelete: Boolean!
+
+ """
+ Timestamp when the container repository was created.
+ """
+ createdAt: Time!
+
+ """
+ The tags cleanup status for the container repository.
+ """
+ expirationPolicyCleanupStatus: ContainerRepositoryCleanupStatus
+
+ """
+ Timestamp when the cleanup done by the expiration policy was started on the container repository.
+ """
+ expirationPolicyStartedAt: Time
+
+ """
+ ID of the container repository.
+ """
+ id: ID!
+
+ """
+ URL of the container repository.
+ """
+ location: String!
+
+ """
+ Name of the container repository.
+ """
+ name: String!
+
+ """
+ Path of the container repository.
+ """
+ path: String!
+
+ """
+ Status of the container repository.
+ """
+ status: ContainerRepositoryStatus
+
+ """
+ Tags of the container repository
+ """
+ tags(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): ContainerRepositoryTagConnection
+
+ """
+ Number of tags associated with this image.
+ """
+ tagsCount: Int!
+
+ """
+ Timestamp when the container repository was updated.
+ """
+ updatedAt: Time!
+}
+
+"""
+An edge in a connection.
+"""
+type ContainerRepositoryEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: ContainerRepository
+}
+
+"""
+Identifier of ContainerRepository
+"""
+scalar ContainerRepositoryID
+
+"""
+Status of a container repository
+"""
+enum ContainerRepositoryStatus {
+ """
+ Delete Failed status.
+ """
+ DELETE_FAILED
+
+ """
+ Delete Scheduled status.
+ """
+ DELETE_SCHEDULED
+}
+
+"""
+A tag from a container repository
+"""
+type ContainerRepositoryTag {
+ """
+ Can the current user delete this tag.
+ """
+ canDelete: Boolean!
+
+ """
+ Timestamp when the tag was created.
+ """
+ createdAt: Time!
+
+ """
+ Digest of the tag.
+ """
+ digest: String!
+
+ """
+ URL of the tag.
+ """
+ location: String!
+
+ """
+ Name of the tag.
+ """
+ name: String!
+
+ """
+ Path of the tag.
+ """
+ path: String!
+
+ """
+ Revision of the tag.
+ """
+ revision: String!
+
+ """
+ Short revision of the tag.
+ """
+ shortRevision: String!
+
+ """
+ The size of the tag.
+ """
+ totalSize: Int!
+}
+
+"""
+The connection type for ContainerRepositoryTag.
+"""
+type ContainerRepositoryTagConnection {
+ """
+ A list of edges.
+ """
+ edges: [ContainerRepositoryTagEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [ContainerRepositoryTag]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type ContainerRepositoryTagEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: ContainerRepositoryTag
+}
+
+"""
Autogenerated input type of CreateAlertIssue
"""
input CreateAlertIssueInput {
@@ -3112,19 +3714,19 @@ input CreateBoardInput {
clientMutationId: String
"""
- The group full path the board is associated with.
+ The group full path the resource is associated with
"""
groupPath: ID
"""
The IDs of labels to be added to the board.
"""
- labelIds: [ID!]
+ labelIds: [LabelID!]
"""
The ID of the milestone to be assigned to the board.
"""
- milestoneId: ID
+ milestoneId: MilestoneID
"""
The board name.
@@ -3132,7 +3734,7 @@ input CreateBoardInput {
name: String
"""
- The project full path the board is associated with.
+ The project full path the resource is associated with
"""
projectPath: ID
@@ -3248,6 +3850,51 @@ type CreateClusterAgentPayload {
}
"""
+Autogenerated input type of CreateCustomEmoji
+"""
+input CreateCustomEmojiInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Namespace full path the emoji is associated with
+ """
+ groupPath: ID!
+
+ """
+ Name of the emoji
+ """
+ name: String!
+
+ """
+ Location of the emoji file
+ """
+ url: String!
+}
+
+"""
+Autogenerated return type of CreateCustomEmoji
+"""
+type CreateCustomEmojiPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The new custom emoji
+ """
+ customEmoji: CustomEmoji
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+"""
Autogenerated input type of CreateDiffNote
"""
input CreateDiffNoteInput {
@@ -3845,6 +4492,71 @@ interface CurrentUserTodos {
}
"""
+A custom emoji uploaded by user
+"""
+type CustomEmoji {
+ """
+ Whether the emoji is an external link
+ """
+ external: Boolean!
+
+ """
+ The ID of the emoji
+ """
+ id: CustomEmojiID!
+
+ """
+ The name of the emoji
+ """
+ name: String!
+
+ """
+ The link to file of the emoji
+ """
+ url: String!
+}
+
+"""
+The connection type for CustomEmoji.
+"""
+type CustomEmojiConnection {
+ """
+ A list of edges.
+ """
+ edges: [CustomEmojiEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [CustomEmoji]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type CustomEmojiEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: CustomEmoji
+}
+
+"""
+Identifier of CustomEmoji
+"""
+scalar CustomEmojiID
+
+"""
Autogenerated input type of DastOnDemandScanCreate
"""
input DastOnDemandScanCreateInput {
@@ -3911,14 +4623,14 @@ type DastScannerProfile {
editPath: String
"""
- ID of the DAST scanner profile
+ ID of the DAST scanner profile. Deprecated in 13.6: Use `id`
"""
- globalId: DastScannerProfileID!
+ globalId: DastScannerProfileID! @deprecated(reason: "Use `id`. Deprecated in 13.6")
"""
- ID of the DAST scanner profile. Deprecated in 13.4: Use `global_id`
+ ID of the DAST scanner profile
"""
- id: ID! @deprecated(reason: "Use `global_id`. Deprecated in 13.4")
+ id: DastScannerProfileID!
"""
Name of the DAST scanner profile
@@ -4035,14 +4747,14 @@ type DastScannerProfileCreatePayload {
errors: [String!]!
"""
- ID of the scanner profile.
+ ID of the scanner profile.. Deprecated in 13.6: Use `id`
"""
- globalId: DastScannerProfileID
+ globalId: DastScannerProfileID @deprecated(reason: "Use `id`. Deprecated in 13.6")
"""
- ID of the scanner profile.. Deprecated in 13.4: Use `global_id`
+ ID of the scanner profile.
"""
- id: ID @deprecated(reason: "Use `global_id`. Deprecated in 13.4")
+ id: DastScannerProfileID
}
"""
@@ -4465,6 +5177,93 @@ Identifier of DastSiteToken
scalar DastSiteTokenID
"""
+Represents a DAST Site Validation
+"""
+type DastSiteValidation {
+ """
+ ID of the site validation
+ """
+ id: DastSiteValidationID!
+
+ """
+ The status of the validation
+ """
+ status: DastSiteProfileValidationStatusEnum!
+}
+
+"""
+Autogenerated input type of DastSiteValidationCreate
+"""
+input DastSiteValidationCreateInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ ID of the site token.
+ """
+ dastSiteTokenId: DastSiteTokenID!
+
+ """
+ The project the site profile belongs to.
+ """
+ fullPath: ID!
+
+ """
+ The validation strategy to be used.
+ """
+ strategy: DastSiteValidationStrategyEnum
+
+ """
+ The path to be requested during validation.
+ """
+ validationPath: String!
+}
+
+"""
+Autogenerated return type of DastSiteValidationCreate
+"""
+type DastSiteValidationCreatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ ID of the site validation.
+ """
+ id: DastSiteValidationID
+
+ """
+ The current validation status.
+ """
+ status: DastSiteProfileValidationStatusEnum
+}
+
+"""
+Identifier of DastSiteValidation
+"""
+scalar DastSiteValidationID
+
+enum DastSiteValidationStrategyEnum {
+ """
+ Header validation
+ """
+ HEADER
+
+ """
+ Text file validation
+ """
+ TEXT_FILE
+}
+
+"""
Date represented in ISO 8601
"""
scalar Date
@@ -4481,7 +5280,7 @@ input DeleteAnnotationInput {
"""
The global ID of the annotation to delete
"""
- id: ID!
+ id: MetricsDashboardAnnotationID!
}
"""
@@ -4670,7 +5469,7 @@ type Design implements CurrentUserTodos & DesignFields & Noteable {
"""
The Global ID of the most recent acceptable version
"""
- earlierOrEqualToId: ID
+ earlierOrEqualToId: DesignManagementVersionID
"""
The SHA256 of the most recent acceptable version
@@ -4810,7 +5609,7 @@ type DesignCollection {
"""
Find a design by its ID
"""
- id: ID
+ id: DesignManagementDesignID
): Design
"""
@@ -4820,7 +5619,7 @@ type DesignCollection {
"""
The Global ID of the design at this version
"""
- id: ID!
+ id: DesignManagementDesignAtVersionID!
): DesignAtVersion
"""
@@ -4836,7 +5635,7 @@ type DesignCollection {
Filters designs to only those that existed at the version. If argument is
omitted or nil then all designs will reflect the latest version
"""
- atVersion: ID
+ atVersion: DesignManagementVersionID
"""
Returns the elements in the list that come before the specified cursor.
@@ -4856,7 +5655,7 @@ type DesignCollection {
"""
Filters designs by their ID
"""
- ids: [ID!]
+ ids: [DesignManagementDesignID!]
"""
Returns the last _n_ elements from the list.
@@ -4881,7 +5680,7 @@ type DesignCollection {
"""
The Global ID of the version
"""
- id: ID
+ id: DesignManagementVersionID
"""
The SHA256 of a specific version
@@ -4906,7 +5705,7 @@ type DesignCollection {
"""
The Global ID of the most recent acceptable version
"""
- earlierOrEqualToId: ID
+ earlierOrEqualToId: DesignManagementVersionID
"""
The SHA256 of the most recent acceptable version
@@ -5040,7 +5839,7 @@ type DesignManagement {
"""
The Global ID of the design at this version
"""
- id: ID!
+ id: DesignManagementDesignAtVersionID!
): DesignAtVersion
"""
@@ -5050,7 +5849,7 @@ type DesignManagement {
"""
The Global ID of the version
"""
- id: ID!
+ id: DesignManagementVersionID!
): DesignVersion
}
@@ -5100,6 +5899,11 @@ type DesignManagementDeletePayload {
}
"""
+Identifier of DesignManagement::DesignAtVersion
+"""
+scalar DesignManagementDesignAtVersionID
+
+"""
Identifier of DesignManagement::Design
"""
scalar DesignManagementDesignID
@@ -5200,6 +6004,11 @@ type DesignManagementUploadPayload {
}
"""
+Identifier of DesignManagement::Version
+"""
+scalar DesignManagementVersionID
+
+"""
A specific version in which designs were added, modified or deleted
"""
type DesignVersion {
@@ -5210,7 +6019,7 @@ type DesignVersion {
"""
The ID of a specific design
"""
- designId: ID
+ designId: DesignManagementDesignID
"""
The filename of a specific design
@@ -5220,7 +6029,7 @@ type DesignVersion {
"""
The ID of the DesignAtVersion
"""
- id: ID
+ id: DesignManagementDesignAtVersionID
): DesignAtVersion!
"""
@@ -5275,7 +6084,7 @@ type DesignVersion {
"""
Filters designs by their ID
"""
- ids: [ID!]
+ ids: [DesignManagementDesignID!]
"""
Returns the last _n_ elements from the list.
@@ -5425,6 +6234,41 @@ type DestroyBoardPayload {
}
"""
+Autogenerated input type of DestroyContainerRepository
+"""
+input DestroyContainerRepositoryInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ ID of the container repository.
+ """
+ id: ContainerRepositoryID!
+}
+
+"""
+Autogenerated return type of DestroyContainerRepository
+"""
+type DestroyContainerRepositoryPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The container repository policy after scheduling the deletion.
+ """
+ containerRepository: ContainerRepository!
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+"""
Autogenerated input type of DestroyNote
"""
input DestroyNoteInput {
@@ -5471,7 +6315,7 @@ input DestroySnippetInput {
"""
The global id of the snippet to destroy
"""
- id: ID!
+ id: SnippetID!
}
"""
@@ -5541,6 +6385,81 @@ type DetailedStatus {
tooltip: String
}
+"""
+Segment
+"""
+type DevopsAdoptionSegment {
+ """
+ Assigned groups
+ """
+ groups(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): GroupConnection
+
+ """
+ ID of the segment
+ """
+ id: ID!
+
+ """
+ Name of the segment
+ """
+ name: String!
+}
+
+"""
+The connection type for DevopsAdoptionSegment.
+"""
+type DevopsAdoptionSegmentConnection {
+ """
+ A list of edges.
+ """
+ edges: [DevopsAdoptionSegmentEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [DevopsAdoptionSegment]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type DevopsAdoptionSegmentEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: DevopsAdoptionSegment
+}
+
input DiffImagePositionInput {
"""
Merge base of the branch the comment was made on
@@ -5584,6 +6503,11 @@ input DiffImagePositionInput {
y: Int!
}
+"""
+Identifier of DiffNote
+"""
+scalar DiffNoteID
+
input DiffPathsInput {
"""
The path of the file on the head sha
@@ -6009,10 +6933,9 @@ type Environment {
name: String!
"""
- The path to the environment. Will always return null if
- `expose_environment_path_in_alert_details` feature flag is disabled
+ The path to the environment.
"""
- path: String
+ path: String!
"""
State of the environment, for example: available/stopped
@@ -6061,6 +6984,41 @@ Identifier of Environment
scalar EnvironmentID
"""
+Autogenerated input type of EnvironmentsCanaryIngressUpdate
+"""
+input EnvironmentsCanaryIngressUpdateInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The global ID of the environment to update
+ """
+ id: EnvironmentID!
+
+ """
+ The weight of the Canary Ingress
+ """
+ weight: Int!
+}
+
+"""
+Autogenerated return type of EnvironmentsCanaryIngressUpdate
+"""
+type EnvironmentsCanaryIngressUpdatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+"""
Represents an epic
"""
type Epic implements CurrentUserTodos & Noteable {
@@ -6115,6 +7073,11 @@ type Epic implements CurrentUserTodos & Noteable {
iids: [ID!]
"""
+ Include epics from descendant groups
+ """
+ includeDescendantGroups: Boolean = true
+
+ """
Filter epics by labels
"""
labelName: [String!]
@@ -6473,6 +7436,16 @@ type Epic implements CurrentUserTodos & Noteable {
upvotes: Int!
"""
+ Number of user discussions in the epic
+ """
+ userDiscussionsCount: Int!
+
+ """
+ Number of user notes of the epic
+ """
+ userNotesCount: Int!
+
+ """
Permissions for the current user on the resource
"""
userPermissions: EpicPermissions!
@@ -6688,6 +7661,11 @@ type EpicIssue implements CurrentUserTodos & Noteable {
blocked: Boolean!
"""
+ Count of issues blocking this issue
+ """
+ blockedByCount: Int
+
+ """
Timestamp of when the issue was closed
"""
closedAt: Time
@@ -6748,11 +7726,6 @@ type EpicIssue implements CurrentUserTodos & Noteable {
designCollection: DesignCollection
"""
- The designs associated with this issue. Deprecated in 12.2: Use `designCollection`
- """
- designs: DesignCollection @deprecated(reason: "Use `designCollection`. Deprecated in 12.2")
-
- """
Indicates discussion is locked on the issue
"""
discussionLocked: Boolean!
@@ -6793,6 +7766,11 @@ type EpicIssue implements CurrentUserTodos & Noteable {
dueDate: Time
"""
+ Indicates if a project has email notifications disabled: `true` if email notifications are disabled
+ """
+ emailsDisabled: Boolean!
+
+ """
Epic to which this issue belongs
"""
epic: Epic
@@ -6808,6 +7786,16 @@ type EpicIssue implements CurrentUserTodos & Noteable {
healthStatus: HealthStatus
"""
+ Human-readable time estimate of the issue
+ """
+ humanTimeEstimate: String
+
+ """
+ Human-readable total time reported as spent on the issue
+ """
+ humanTotalTimeSpent: String
+
+ """
Global ID of the epic-issue relation
"""
id: ID
@@ -6853,6 +7841,16 @@ type EpicIssue implements CurrentUserTodos & Noteable {
milestone: Milestone
"""
+ Indicates if issue got moved from other project
+ """
+ moved: Boolean
+
+ """
+ Updated Issue after it got moved to another project
+ """
+ movedTo: Issue
+
+ """
All notes on this noteable
"""
notes(
@@ -6983,11 +7981,21 @@ type EpicIssue implements CurrentUserTodos & Noteable {
updatedAt: Time!
"""
+ User that last updated the issue
+ """
+ updatedBy: User
+
+ """
Number of upvotes the issue has received
"""
upvotes: Int!
"""
+ Number of user discussions in the issue
+ """
+ userDiscussionsCount: Int!
+
+ """
Number of user notes of the issue
"""
userNotesCount: Int!
@@ -7036,6 +8044,11 @@ type EpicIssueConnection {
Information to aid in pagination.
"""
pageInfo: PageInfo!
+
+ """
+ Total weight of issues collection
+ """
+ weight: Int!
}
"""
@@ -7414,6 +8427,37 @@ type GeoNode {
selectiveSyncType: String
"""
+ Find snippet repository registries on this Geo node. Available only when
+ feature flag `geo_snippet_repository_replication` is enabled
+ """
+ snippetRepositoryRegistries(
+ """
+ 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
+ ): SnippetRepositoryRegistryConnection
+
+ """
Indicates if this secondary node will replicate blobs in Object Storage
"""
syncObjectStorage: Boolean
@@ -7459,6 +8503,11 @@ type GeoNode {
verificationMaxCapacity: Int
}
+"""
+Identifier of Gitlab::ErrorTracking::DetailedError
+"""
+scalar GitlabErrorTrackingDetailedErrorID
+
type GrafanaIntegration {
"""
Timestamp of the issue's creation
@@ -7481,11 +8530,6 @@ type GrafanaIntegration {
id: ID!
"""
- API token for the Grafana integration. Deprecated in 12.7: Plain text token has been masked for security reasons
- """
- token: String! @deprecated(reason: "Plain text token has been masked for security reasons. Deprecated in 12.7")
-
- """
Timestamp of the issue's last activity
"""
updatedAt: Time!
@@ -7544,7 +8588,7 @@ type Group {
"""
Find a board by its ID
"""
- id: ID
+ id: BoardID
"""
Returns the last _n_ elements from the list.
@@ -7553,11 +8597,97 @@ type Group {
): BoardConnection
"""
+ Represents the code coverage activity for this group. Available only when
+ feature flag `group_coverage_data_report_graph` is enabled
+ """
+ codeCoverageActivities(
+ """
+ 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
+
+ """
+ First day for which to fetch code coverage activity (maximum time window is set to 90 days)
+ """
+ startDate: Date!
+ ): CodeCoverageActivityConnection
+
+ """
+ Container repositories of the project
+ """
+ containerRepositories(
+ """
+ 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
+
+ """
+ Filter the container repositories by their name
+ """
+ name: String
+ ): ContainerRepositoryConnection
+
+ """
Includes at least one project where the repository size exceeds the limit
"""
containsLockedProjects: Boolean!
"""
+ Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled
+ """
+ customEmoji(
+ """
+ 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
+ ): CustomEmojiConnection
+
+ """
Description of the namespace
"""
description: String
@@ -7603,6 +8733,11 @@ type Group {
iids: [ID!]
"""
+ Include epics from descendant groups
+ """
+ includeDescendantGroups: Boolean = true
+
+ """
Filter epics by labels
"""
labelName: [String!]
@@ -7686,6 +8821,11 @@ type Group {
iids: [ID!]
"""
+ Include epics from descendant groups
+ """
+ includeDescendantGroups: Boolean = true
+
+ """
Filter epics by labels
"""
labelName: [String!]
@@ -7798,7 +8938,7 @@ type Group {
after: String
"""
- ID of a user assigned to the issues, "none" and "any" values supported
+ ID of a user assigned to the issues, "none" and "any" values are supported
"""
assigneeId: String
@@ -7843,6 +8983,11 @@ type Group {
createdBefore: Time
"""
+ ID of an epic associated with the issues, "none" and "any" values are supported
+ """
+ epicId: String
+
+ """
Returns the first _n_ elements from the list.
"""
first: Int
@@ -8280,6 +9425,11 @@ type Group {
shareWithGroupLock: Boolean
"""
+ Group statistics
+ """
+ stats: GroupStats
+
+ """
Total storage limit of the root namespace in bytes
"""
storageSizeLimit: Float
@@ -8503,7 +9653,12 @@ type Group {
"""
Represents vulnerable project counts for each grade
"""
- vulnerabilityGrades: [VulnerableProjectsByGrade!]!
+ vulnerabilityGrades(
+ """
+ Include grades belonging to subgroups
+ """
+ includeSubgroups: Boolean = false
+ ): [VulnerableProjectsByGrade!]!
"""
Vulnerability scanners reported on the project vulnerabilties of the group and its subgroups
@@ -8567,6 +9722,46 @@ type Group {
}
"""
+The connection type for Group.
+"""
+type GroupConnection {
+ """
+ A list of edges.
+ """
+ edges: [GroupEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [Group]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type GroupEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: Group
+}
+
+"""
+Identifier of Group
+"""
+scalar GroupID
+
+"""
Represents a Group Membership
"""
type GroupMember implements MemberInterface {
@@ -8659,6 +9854,33 @@ type GroupPermissions {
}
"""
+Contains release-related statistics about a group
+"""
+type GroupReleaseStats {
+ """
+ Total number of releases in all descendant projects of the group. Will always
+ return `null` if `group_level_release_statistics` feature flag is disabled
+ """
+ releasesCount: Int
+
+ """
+ Percentage of the group's descendant projects that have at least one release.
+ Will always return `null` if `group_level_release_statistics` feature flag is disabled
+ """
+ releasesPercentage: Int
+}
+
+"""
+Contains statistics about a group
+"""
+type GroupStats {
+ """
+ Statistics related to releases within the group
+ """
+ releaseStats: GroupReleaseStats
+}
+
+"""
Health status of an issue or epic
"""
enum HealthStatus {
@@ -8668,6 +9890,166 @@ enum HealthStatus {
}
"""
+Autogenerated input type of HttpIntegrationCreate
+"""
+input HttpIntegrationCreateInput {
+ """
+ Whether the integration is receiving alerts
+ """
+ active: Boolean!
+
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The name of the integration
+ """
+ name: String!
+
+ """
+ The project to create the integration in
+ """
+ projectPath: ID!
+}
+
+"""
+Autogenerated return type of HttpIntegrationCreate
+"""
+type HttpIntegrationCreatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The HTTP integration
+ """
+ integration: AlertManagementHttpIntegration
+}
+
+"""
+Autogenerated input type of HttpIntegrationDestroy
+"""
+input HttpIntegrationDestroyInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The id of the integration to remove
+ """
+ id: AlertManagementHttpIntegrationID!
+}
+
+"""
+Autogenerated return type of HttpIntegrationDestroy
+"""
+type HttpIntegrationDestroyPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The HTTP integration
+ """
+ integration: AlertManagementHttpIntegration
+}
+
+"""
+Autogenerated input type of HttpIntegrationResetToken
+"""
+input HttpIntegrationResetTokenInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The id of the integration to mutate
+ """
+ id: AlertManagementHttpIntegrationID!
+}
+
+"""
+Autogenerated return type of HttpIntegrationResetToken
+"""
+type HttpIntegrationResetTokenPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The HTTP integration
+ """
+ integration: AlertManagementHttpIntegration
+}
+
+"""
+Autogenerated input type of HttpIntegrationUpdate
+"""
+input HttpIntegrationUpdateInput {
+ """
+ Whether the integration is receiving alerts
+ """
+ active: Boolean
+
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The id of the integration to mutate
+ """
+ id: AlertManagementHttpIntegrationID!
+
+ """
+ The name of the integration
+ """
+ name: String
+}
+
+"""
+Autogenerated return type of HttpIntegrationUpdate
+"""
+type HttpIntegrationUpdatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The HTTP integration
+ """
+ integration: AlertManagementHttpIntegration
+}
+
+"""
An ISO 8601-encoded date
"""
scalar ISO8601Date
@@ -8896,6 +10278,11 @@ type Issue implements CurrentUserTodos & Noteable {
blocked: Boolean!
"""
+ Count of issues blocking this issue
+ """
+ blockedByCount: Int
+
+ """
Timestamp of when the issue was closed
"""
closedAt: Time
@@ -8956,11 +10343,6 @@ type Issue implements CurrentUserTodos & Noteable {
designCollection: DesignCollection
"""
- The designs associated with this issue. Deprecated in 12.2: Use `designCollection`
- """
- designs: DesignCollection @deprecated(reason: "Use `designCollection`. Deprecated in 12.2")
-
- """
Indicates discussion is locked on the issue
"""
discussionLocked: Boolean!
@@ -9001,6 +10383,11 @@ type Issue implements CurrentUserTodos & Noteable {
dueDate: Time
"""
+ Indicates if a project has email notifications disabled: `true` if email notifications are disabled
+ """
+ emailsDisabled: Boolean!
+
+ """
Epic to which this issue belongs
"""
epic: Epic
@@ -9011,6 +10398,16 @@ type Issue implements CurrentUserTodos & Noteable {
healthStatus: HealthStatus
"""
+ Human-readable time estimate of the issue
+ """
+ humanTimeEstimate: String
+
+ """
+ Human-readable total time reported as spent on the issue
+ """
+ humanTotalTimeSpent: String
+
+ """
ID of the issue
"""
id: ID!
@@ -9056,6 +10453,16 @@ type Issue implements CurrentUserTodos & Noteable {
milestone: Milestone
"""
+ Indicates if issue got moved from other project
+ """
+ moved: Boolean
+
+ """
+ Updated Issue after it got moved to another project
+ """
+ movedTo: Issue
+
+ """
All notes on this noteable
"""
notes(
@@ -9181,11 +10588,21 @@ type Issue implements CurrentUserTodos & Noteable {
updatedAt: Time!
"""
+ User that last updated the issue
+ """
+ updatedBy: User
+
+ """
Number of upvotes the issue has received
"""
upvotes: Int!
"""
+ Number of user discussions in the issue
+ """
+ userDiscussionsCount: Int!
+
+ """
Number of user notes of the issue
"""
userNotesCount: Int!
@@ -9234,6 +10651,11 @@ type IssueConnection {
Information to aid in pagination.
"""
pageInfo: PageInfo!
+
+ """
+ Total weight of issues collection
+ """
+ weight: Int!
}
"""
@@ -9568,7 +10990,7 @@ input IssueSetEpicInput {
"""
Global ID of the epic to be assigned to the issue, epic will be removed if absent or set to null
"""
- epicId: ID
+ epicId: EpicID
"""
The IID of the issue to mutate
@@ -9906,6 +11328,16 @@ enum IssueSort {
SEVERITY_DESC
"""
+ Issues with earliest SLA due time shown first
+ """
+ SLA_DUE_AT_ASC
+
+ """
+ Issues with latest SLA due time shown first
+ """
+ SLA_DUE_AT_DESC
+
+ """
Updated at ascending order
"""
UPDATED_ASC
@@ -10014,12 +11446,7 @@ enum IssueType {
"""
Represents an iteration object
"""
-type Iteration implements TimeboxBurnupTimeSeriesInterface {
- """
- Daily scope and completed totals for burnup charts
- """
- burnupTimeSeries: [BurnupChartDailyTotals!]
-
+type Iteration implements TimeboxReportInterface {
"""
Timestamp of iteration creation
"""
@@ -10051,6 +11478,11 @@ type Iteration implements TimeboxBurnupTimeSeriesInterface {
iid: ID!
"""
+ Historically accurate report about the timebox
+ """
+ report: TimeboxReport
+
+ """
Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts
"""
scopedPath: String
@@ -10143,6 +11575,21 @@ enum IterationState {
}
"""
+Iteration ID wildcard values
+"""
+enum IterationWildcardId {
+ """
+ An iteration is assigned
+ """
+ ANY
+
+ """
+ No iteration is assigned
+ """
+ NONE
+}
+
+"""
Represents untyped JSON
"""
scalar JSON
@@ -10505,6 +11952,63 @@ type LabelConnection {
}
"""
+Autogenerated input type of LabelCreate
+"""
+input LabelCreateInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The color of the label given in 6-digit hex notation with leading '#' sign
+ (e.g. #FFAABB) or one of the CSS color names in
+ https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords
+ """
+ color: String = "#428BCA"
+
+ """
+ Description of the label
+ """
+ description: String
+
+ """
+ The group full path the resource is associated with
+ """
+ groupPath: ID
+
+ """
+ The project full path the resource is associated with
+ """
+ projectPath: ID
+
+ """
+ Title of the label
+ """
+ title: String!
+}
+
+"""
+Autogenerated return type of LabelCreate
+"""
+type LabelCreatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The label after mutation
+ """
+ label: Label
+}
+
+"""
An edge in a connection.
"""
type LabelEdge {
@@ -10550,7 +12054,7 @@ input MarkAsSpamSnippetInput {
"""
The global id of the snippet to update
"""
- id: ID!
+ id: SnippetID!
}
"""
@@ -10952,11 +12456,6 @@ type MergeRequest implements CurrentUserTodos & Noteable {
): LabelConnection
"""
- Default merge commit message of the merge request. Deprecated in 11.8: Use `defaultMergeCommitMessage`
- """
- mergeCommitMessage: String @deprecated(reason: "Use `defaultMergeCommitMessage`. Deprecated in 11.8")
-
- """
SHA of the merge request commit (set once merged)
"""
mergeCommitSha: String
@@ -11212,6 +12711,11 @@ type MergeRequest implements CurrentUserTodos & Noteable {
upvotes: Int!
"""
+ Number of user discussions in the merge request
+ """
+ userDiscussionsCount: Int
+
+ """
User notes count of the merge request
"""
userNotesCount: Int
@@ -11534,7 +13038,7 @@ input MergeRequestSetLabelsInput {
"""
The Label IDs to set. Replaces existing labels by default.
"""
- labelIds: [ID!]!
+ labelIds: [LabelID!]!
"""
Changes the operation mode. Defaults to REPLACE.
@@ -12020,14 +13524,14 @@ type MetricsDashboardAnnotationEdge {
}
"""
-Represents a milestone
+Identifier of Metrics::Dashboard::Annotation
"""
-type Milestone implements TimeboxBurnupTimeSeriesInterface {
- """
- Daily scope and completed totals for burnup charts
- """
- burnupTimeSeries: [BurnupChartDailyTotals!]
+scalar MetricsDashboardAnnotationID
+"""
+Represents a milestone
+"""
+type Milestone implements TimeboxReportInterface {
"""
Timestamp of milestone creation
"""
@@ -12059,6 +13563,11 @@ type Milestone implements TimeboxBurnupTimeSeriesInterface {
projectMilestone: Boolean!
"""
+ Historically accurate report about the timebox
+ """
+ report: TimeboxReport
+
+ """
Timestamp of the milestone start date
"""
startDate: Time
@@ -12190,6 +13699,11 @@ type Mutation {
createBoard(input: CreateBoardInput!): CreateBoardPayload
createBranch(input: CreateBranchInput!): CreateBranchPayload
createClusterAgent(input: CreateClusterAgentInput!): CreateClusterAgentPayload
+
+ """
+ . Available only when feature flag `custom_emoji` is enabled
+ """
+ createCustomEmoji(input: CreateCustomEmojiInput!): CreateCustomEmojiPayload
createDiffNote(input: CreateDiffNoteInput!): CreateDiffNotePayload
createEpic(input: CreateEpicInput!): CreateEpicPayload
createImageDiffNote(input: CreateImageDiffNoteInput!): CreateImageDiffNotePayload
@@ -12207,12 +13721,14 @@ type Mutation {
dastSiteProfileDelete(input: DastSiteProfileDeleteInput!): DastSiteProfileDeletePayload
dastSiteProfileUpdate(input: DastSiteProfileUpdateInput!): DastSiteProfileUpdatePayload
dastSiteTokenCreate(input: DastSiteTokenCreateInput!): DastSiteTokenCreatePayload
+ dastSiteValidationCreate(input: DastSiteValidationCreateInput!): DastSiteValidationCreatePayload
deleteAnnotation(input: DeleteAnnotationInput!): DeleteAnnotationPayload
designManagementDelete(input: DesignManagementDeleteInput!): DesignManagementDeletePayload
designManagementMove(input: DesignManagementMoveInput!): DesignManagementMovePayload
designManagementUpload(input: DesignManagementUploadInput!): DesignManagementUploadPayload
destroyBoard(input: DestroyBoardInput!): DestroyBoardPayload
destroyBoardList(input: DestroyBoardListInput!): DestroyBoardListPayload
+ destroyContainerRepository(input: DestroyContainerRepositoryInput!): DestroyContainerRepositoryPayload
destroyNote(input: DestroyNoteInput!): DestroyNotePayload
destroySnippet(input: DestroySnippetInput!): DestroySnippetPayload
@@ -12221,9 +13737,14 @@ type Mutation {
"""
discussionToggleResolve(input: DiscussionToggleResolveInput!): DiscussionToggleResolvePayload
dismissVulnerability(input: DismissVulnerabilityInput!): DismissVulnerabilityPayload @deprecated(reason: "Use vulnerabilityDismiss. Deprecated in 13.5")
+ environmentsCanaryIngressUpdate(input: EnvironmentsCanaryIngressUpdateInput!): EnvironmentsCanaryIngressUpdatePayload
epicAddIssue(input: EpicAddIssueInput!): EpicAddIssuePayload
epicSetSubscription(input: EpicSetSubscriptionInput!): EpicSetSubscriptionPayload
epicTreeReorder(input: EpicTreeReorderInput!): EpicTreeReorderPayload
+ httpIntegrationCreate(input: HttpIntegrationCreateInput!): HttpIntegrationCreatePayload
+ httpIntegrationDestroy(input: HttpIntegrationDestroyInput!): HttpIntegrationDestroyPayload
+ httpIntegrationResetToken(input: HttpIntegrationResetTokenInput!): HttpIntegrationResetTokenPayload
+ httpIntegrationUpdate(input: HttpIntegrationUpdateInput!): HttpIntegrationUpdatePayload
issueMove(input: IssueMoveInput!): IssueMovePayload
issueMoveList(input: IssueMoveListInput!): IssueMoveListPayload
issueSetAssignees(input: IssueSetAssigneesInput!): IssueSetAssigneesPayload
@@ -12237,6 +13758,7 @@ type Mutation {
issueSetWeight(input: IssueSetWeightInput!): IssueSetWeightPayload
jiraImportStart(input: JiraImportStartInput!): JiraImportStartPayload
jiraImportUsers(input: JiraImportUsersInput!): JiraImportUsersPayload
+ labelCreate(input: LabelCreateInput!): LabelCreatePayload
markAsSpamSnippet(input: MarkAsSpamSnippetInput!): MarkAsSpamSnippetPayload
mergeRequestCreate(input: MergeRequestCreateInput!): MergeRequestCreatePayload
mergeRequestSetAssignees(input: MergeRequestSetAssigneesInput!): MergeRequestSetAssigneesPayload
@@ -12254,10 +13776,24 @@ type Mutation {
pipelineCancel(input: PipelineCancelInput!): PipelineCancelPayload
pipelineDestroy(input: PipelineDestroyInput!): PipelineDestroyPayload
pipelineRetry(input: PipelineRetryInput!): PipelineRetryPayload
+ prometheusIntegrationCreate(input: PrometheusIntegrationCreateInput!): PrometheusIntegrationCreatePayload
+ prometheusIntegrationResetToken(input: PrometheusIntegrationResetTokenInput!): PrometheusIntegrationResetTokenPayload
+ prometheusIntegrationUpdate(input: PrometheusIntegrationUpdateInput!): PrometheusIntegrationUpdatePayload
+ promoteToEpic(input: PromoteToEpicInput!): PromoteToEpicPayload
+ releaseCreate(input: ReleaseCreateInput!): ReleaseCreatePayload
removeAwardEmoji(input: RemoveAwardEmojiInput!): RemoveAwardEmojiPayload @deprecated(reason: "Use awardEmojiRemove. Deprecated in 13.2")
removeProjectFromSecurityDashboard(input: RemoveProjectFromSecurityDashboardInput!): RemoveProjectFromSecurityDashboardPayload
+
+ """
+ Repositions a DiffNote on an image (a `Note` where the `position.positionType` is `"image"`)
+ """
+ repositionImageDiffNote(input: RepositionImageDiffNoteInput!): RepositionImageDiffNotePayload
revertVulnerabilityToDetected(input: RevertVulnerabilityToDetectedInput!): RevertVulnerabilityToDetectedPayload @deprecated(reason: "Use vulnerabilityRevertToDetected. Deprecated in 13.5")
runDastScan(input: RunDASTScanInput!): RunDASTScanPayload @deprecated(reason: "Use DastOnDemandScanCreate. Deprecated in 13.4")
+ terraformStateDelete(input: TerraformStateDeleteInput!): TerraformStateDeletePayload
+ terraformStateLock(input: TerraformStateLockInput!): TerraformStateLockPayload
+ terraformStateUnlock(input: TerraformStateUnlockInput!): TerraformStateUnlockPayload
+ todoCreate(input: TodoCreateInput!): TodoCreatePayload
todoMarkDone(input: TodoMarkDoneInput!): TodoMarkDonePayload
todoRestore(input: TodoRestoreInput!): TodoRestorePayload
todoRestoreMany(input: TodoRestoreManyInput!): TodoRestoreManyPayload
@@ -12542,6 +14078,11 @@ enum NamespaceProjectSort {
Most similar to the search query
"""
SIMILARITY
+
+ """
+ Sort by storage size
+ """
+ STORAGE
}
input NegatedBoardIssueInput {
@@ -12558,7 +14099,12 @@ input NegatedBoardIssueInput {
"""
Filter by epic ID. Incompatible with epicWildcardId
"""
- epicId: ID
+ epicId: EpicID
+
+ """
+ Filter by iteration title
+ """
+ iterationTitle: String
"""
Filter by label name
@@ -12735,6 +14281,11 @@ type NotePermissions {
readNote: Boolean!
"""
+ Indicates the user can perform `reposition_note` on this resource
+ """
+ repositionNote: Boolean!
+
+ """
Indicates the user can perform `resolve_note` on this resource
"""
resolveNote: Boolean!
@@ -13058,6 +14609,31 @@ type Pipeline {
detailedStatus: DetailedStatus!
"""
+ Pipelines this pipeline will trigger
+ """
+ downstream(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): PipelineConnection
+
+ """
Duration of the pipeline in seconds
"""
duration: Int
@@ -13078,6 +14654,46 @@ type Pipeline {
iid: String!
"""
+ Jobs belonging to the pipeline
+ """
+ jobs(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+
+ """
+ Filter jobs by the type of security report they produce
+ """
+ securityReportTypes: [SecurityReportTypeEnum!]
+ ): CiJobConnection
+
+ """
+ Relative path to the pipeline's page
+ """
+ path: String
+
+ """
+ Project the pipeline belongs to
+ """
+ project: Project
+
+ """
Specifies if a pipeline can be retried
"""
retryable: Boolean!
@@ -13093,6 +14709,11 @@ type Pipeline {
sha: String!
"""
+ Job where pipeline was triggered from
+ """
+ sourceJob: CiJob
+
+ """
Stages of the pipeline
"""
stages(
@@ -13134,6 +14755,11 @@ type Pipeline {
updatedAt: Time!
"""
+ Pipeline that triggered the pipeline
+ """
+ upstream: Pipeline
+
+ """
Pipeline user
"""
user: User
@@ -13342,7 +14968,7 @@ type Project {
iid: String
"""
- Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.
+ Search query for title, description, service, or monitoring_tool.
"""
search: String
@@ -13367,7 +14993,7 @@ type Project {
assigneeUsername: String
"""
- Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.
+ Search query for title, description, service, or monitoring_tool.
"""
search: String
): AlertManagementAlertStatusCountsType
@@ -13407,7 +15033,7 @@ type Project {
last: Int
"""
- Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.
+ Search query for title, description, service, or monitoring_tool.
"""
search: String
@@ -13423,6 +15049,31 @@ type Project {
): AlertManagementAlertConnection
"""
+ Integrations which can receive alerts for the project
+ """
+ alertManagementIntegrations(
+ """
+ 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
+ ): AlertManagementIntegrationConnection
+
+ """
If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge
requests of the project can also be merged with skipped jobs
"""
@@ -13475,7 +15126,7 @@ type Project {
"""
Find a board by its ID
"""
- id: ID
+ id: BoardID
"""
Returns the last _n_ elements from the list.
@@ -13519,6 +15170,11 @@ type Project {
): ClusterAgentConnection
"""
+ Code coverage summary associated with the project
+ """
+ codeCoverageSummary: CodeCoverageSummary
+
+ """
Compliance frameworks associated with the project
"""
complianceFrameworks(
@@ -13554,6 +15210,36 @@ type Project {
containerRegistryEnabled: Boolean
"""
+ Container repositories of the project
+ """
+ containerRepositories(
+ """
+ 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
+
+ """
+ Filter the container repositories by their name
+ """
+ name: String
+ ): ContainerRepositoryConnection
+
+ """
Timestamp of the project creation
"""
createdAt: Time
@@ -13619,6 +15305,16 @@ type Project {
): DastSiteProfileConnection
"""
+ DAST Site Validation associated with the project
+ """
+ dastSiteValidation(
+ """
+ target URL of the DAST Site Validation
+ """
+ targetUrl: String!
+ ): DastSiteValidation
+
+ """
Short description of the project
"""
description: String
@@ -13728,7 +15424,7 @@ type Project {
"""
issue(
"""
- ID of a user assigned to the issues, "none" and "any" values supported
+ ID of a user assigned to the issues, "none" and "any" values are supported
"""
assigneeId: String
@@ -13768,6 +15464,11 @@ type Project {
createdBefore: Time
"""
+ ID of an epic associated with the issues, "none" and "any" values are supported
+ """
+ epicId: String
+
+ """
IID of the issue. For example, "1"
"""
iid: String
@@ -13828,7 +15529,7 @@ type Project {
"""
issueStatusCounts(
"""
- ID of a user assigned to the issues, "none" and "any" values supported
+ ID of a user assigned to the issues, "none" and "any" values are supported
"""
assigneeId: String
@@ -13918,7 +15619,7 @@ type Project {
after: String
"""
- ID of a user assigned to the issues, "none" and "any" values supported
+ ID of a user assigned to the issues, "none" and "any" values are supported
"""
assigneeId: String
@@ -13963,6 +15664,11 @@ type Project {
createdBefore: Time
"""
+ ID of an epic associated with the issues, "none" and "any" values are supported
+ """
+ epicId: String
+
+ """
Returns the first _n_ elements from the list.
"""
first: Int
@@ -14545,6 +16251,11 @@ type Project {
Returns the last _n_ elements from the list.
"""
last: Int
+
+ """
+ Sort releases by this criteria
+ """
+ sort: ReleaseSort = RELEASED_AT_DESC
): ReleaseConnection
"""
@@ -14684,7 +16395,7 @@ type Project {
"""
ID of the Sentry issue
"""
- id: ID!
+ id: GitlabErrorTrackingDetailedErrorID!
): SentryDetailedError
"""
@@ -14764,7 +16475,7 @@ type Project {
"""
Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1"
"""
- ids: [ID!]
+ ids: [SnippetID!]
"""
Returns the last _n_ elements from the list.
@@ -15345,20 +17056,9 @@ type ProjectPermissions {
uploadFile: Boolean!
}
-"""
-Names of compliance frameworks that can be assigned to a Project
-"""
-enum ProjectSettingEnum {
- gdpr
- hipaa
- pci_dss
- soc_2
- sox
-}
-
type ProjectStatistics {
"""
- Build artifacts size of the project
+ Build artifacts size of the project in bytes
"""
buildArtifactsSize: Float!
@@ -15368,32 +17068,37 @@ type ProjectStatistics {
commitCount: Float!
"""
- Large File Storage (LFS) object size of the project
+ Large File Storage (LFS) object size of the project in bytes
"""
lfsObjectsSize: Float!
"""
- Packages size of the project
+ Packages size of the project in bytes
"""
packagesSize: Float!
"""
- Repository size of the project
+ Repository size of the project in bytes
"""
repositorySize: Float!
"""
- Snippets size of the project
+ Snippets size of the project in bytes
"""
snippetsSize: Float
"""
- Storage size of the project
+ Storage size of the project in bytes
"""
storageSize: Float!
"""
- Wiki size of the project
+ Uploads size of the project in bytes
+ """
+ uploadsSize: Float
+
+ """
+ Wiki size of the project in bytes
"""
wikiSize: Float
}
@@ -15413,8 +17118,198 @@ type PrometheusAlert {
id: ID!
}
+"""
+Autogenerated input type of PrometheusIntegrationCreate
+"""
+input PrometheusIntegrationCreateInput {
+ """
+ Whether the integration is receiving alerts
+ """
+ active: Boolean!
+
+ """
+ Endpoint at which prometheus can be queried
+ """
+ apiUrl: String!
+
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The project to create the integration in
+ """
+ projectPath: ID!
+}
+
+"""
+Autogenerated return type of PrometheusIntegrationCreate
+"""
+type PrometheusIntegrationCreatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The newly created integration
+ """
+ integration: AlertManagementPrometheusIntegration
+}
+
+"""
+Autogenerated input type of PrometheusIntegrationResetToken
+"""
+input PrometheusIntegrationResetTokenInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The id of the integration to mutate
+ """
+ id: PrometheusServiceID!
+}
+
+"""
+Autogenerated return type of PrometheusIntegrationResetToken
+"""
+type PrometheusIntegrationResetTokenPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The newly created integration
+ """
+ integration: AlertManagementPrometheusIntegration
+}
+
+"""
+Autogenerated input type of PrometheusIntegrationUpdate
+"""
+input PrometheusIntegrationUpdateInput {
+ """
+ Whether the integration is receiving alerts
+ """
+ active: Boolean
+
+ """
+ Endpoint at which prometheus can be queried
+ """
+ apiUrl: String
+
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The id of the integration to mutate
+ """
+ id: PrometheusServiceID!
+}
+
+"""
+Autogenerated return type of PrometheusIntegrationUpdate
+"""
+type PrometheusIntegrationUpdatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The newly created integration
+ """
+ integration: AlertManagementPrometheusIntegration
+}
+
+"""
+Identifier of PrometheusService
+"""
+scalar PrometheusServiceID
+
+"""
+Autogenerated input type of PromoteToEpic
+"""
+input PromoteToEpicInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The group the promoted epic will belong to
+ """
+ groupPath: ID
+
+ """
+ The IID of the issue to mutate
+ """
+ iid: String!
+
+ """
+ The project the issue to mutate is in
+ """
+ projectPath: ID!
+}
+
+"""
+Autogenerated return type of PromoteToEpic
+"""
+type PromoteToEpicPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The epic after issue promotion
+ """
+ epic: Epic
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The issue after mutation
+ """
+ issue: Issue
+}
+
type Query {
"""
+ Find a container repository
+ """
+ containerRepository(
+ """
+ The global ID of the container repository
+ """
+ id: ContainerRepositoryID!
+ ): ContainerRepositoryDetails
+
+ """
Get information about current user
"""
currentUser: User
@@ -15425,6 +17320,31 @@ type Query {
designManagement: DesignManagement!
"""
+ Get configured DevOps adoption segments on the instance
+ """
+ devopsAdoptionSegments(
+ """
+ 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
+ ): DevopsAdoptionSegmentConnection
+
+ """
Text to echo back
"""
echo(
@@ -15487,6 +17407,16 @@ type Query {
Returns the last _n_ elements from the list.
"""
last: Int
+
+ """
+ Measurement recorded after this date
+ """
+ recordedAfter: Time
+
+ """
+ Measurement recorded before this date
+ """
+ recordedBefore: Time
): InstanceStatisticsMeasurementConnection
"""
@@ -15620,6 +17550,31 @@ type Query {
): RunnerPlatformConnection
"""
+ Get runner setup instructions
+ """
+ runnerSetup(
+ """
+ Architecture to generate the instructions for
+ """
+ architecture: String!
+
+ """
+ Group to register the runner for
+ """
+ groupId: GroupID
+
+ """
+ Platform to generate the instructions for
+ """
+ platform: String!
+
+ """
+ Project to register the runner for
+ """
+ projectId: ProjectID
+ ): RunnerSetup
+
+ """
Find Snippets visible to the current user
"""
snippets(
@@ -15631,7 +17586,7 @@ type Query {
"""
The ID of an author
"""
- authorId: ID
+ authorId: UserID
"""
Returns the elements in the list that come before the specified cursor.
@@ -15651,7 +17606,7 @@ type Query {
"""
Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1"
"""
- ids: [ID!]
+ ids: [SnippetID!]
"""
Returns the last _n_ elements from the list.
@@ -15661,7 +17616,7 @@ type Query {
"""
The ID of a project
"""
- projectId: ID
+ projectId: ProjectID
"""
The type of snippet
@@ -15681,7 +17636,7 @@ type Query {
"""
ID of the User
"""
- id: ID
+ id: UserID
"""
Username of the User
@@ -15719,6 +17674,11 @@ type Query {
last: Int
"""
+ Query to search users by name, username, or primary email.
+ """
+ search: String
+
+ """
Sort users by this criteria
"""
sort: Sort = created_desc
@@ -16088,7 +18048,32 @@ type ReleaseAssetLinkEdge {
}
"""
-Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`
+Fields that are available when modifying a release asset link
+"""
+input ReleaseAssetLinkInput {
+ """
+ Relative path for a direct asset link
+ """
+ directAssetPath: String
+
+ """
+ The type of the asset link
+ """
+ linkType: ReleaseAssetLinkType = OTHER
+
+ """
+ Name of the asset link
+ """
+ name: String!
+
+ """
+ URL of the asset link
+ """
+ url: String!
+}
+
+"""
+Type of the link: `other`, `runbook`, `image`, `package`
"""
enum ReleaseAssetLinkType {
"""
@@ -16173,6 +18158,16 @@ type ReleaseAssets {
}
"""
+Fields that are available when modifying release assets
+"""
+input ReleaseAssetsInput {
+ """
+ A list of asset links to associate to the release
+ """
+ links: [ReleaseAssetLinkInput!]
+}
+
+"""
The connection type for Release.
"""
type ReleaseConnection {
@@ -16198,6 +18193,76 @@ type ReleaseConnection {
}
"""
+Autogenerated input type of ReleaseCreate
+"""
+input ReleaseCreateInput {
+ """
+ Assets associated to the release
+ """
+ assets: ReleaseAssetsInput
+
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Description (also known as "release notes") of the release
+ """
+ description: String
+
+ """
+ The title of each milestone the release is associated with. GitLab Premium customers can specify group milestones.
+ """
+ milestones: [String!]
+
+ """
+ Name of the release
+ """
+ name: String
+
+ """
+ Full path of the project the release is associated with
+ """
+ projectPath: ID!
+
+ """
+ The commit SHA or branch name to use if creating a new tag
+ """
+ ref: String
+
+ """
+ The date when the release will be/was ready. Defaults to the current time.
+ """
+ releasedAt: Time
+
+ """
+ Name of the tag to associate with the release
+ """
+ tagName: String!
+}
+
+"""
+Autogenerated return type of ReleaseCreate
+"""
+type ReleaseCreatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The release after mutation
+ """
+ release: Release
+}
+
+"""
An edge in a connection.
"""
type ReleaseEdge {
@@ -16274,19 +18339,34 @@ type ReleaseEvidenceEdge {
type ReleaseLinks {
"""
+ HTTP URL of the issues page, filtered by this release and `state=closed`
+ """
+ closedIssuesUrl: String
+
+ """
+ HTTP URL of the merge request page , filtered by this release and `state=closed`
+ """
+ closedMergeRequestsUrl: String
+
+ """
HTTP URL of the release's edit page
"""
editUrl: String
"""
- HTTP URL of the issues page filtered by this release
+ HTTP URL of the merge request page , filtered by this release and `state=merged`
+ """
+ mergedMergeRequestsUrl: String
+
+ """
+ HTTP URL of the issues page, filtered by this release and `state=open`
"""
- issuesUrl: String
+ openedIssuesUrl: String
"""
- HTTP URL of the merge request page filtered by this release
+ HTTP URL of the merge request page, filtered by this release and `state=open`
"""
- mergeRequestsUrl: String
+ openedMergeRequestsUrl: String
"""
HTTP URL of the release
@@ -16295,6 +18375,31 @@ type ReleaseLinks {
}
"""
+Values for sorting releases
+"""
+enum ReleaseSort {
+ """
+ Created at ascending order
+ """
+ CREATED_ASC
+
+ """
+ Created at descending order
+ """
+ CREATED_DESC
+
+ """
+ Released at by ascending order
+ """
+ RELEASED_AT_ASC
+
+ """
+ Released at by descending order
+ """
+ RELEASED_AT_DESC
+}
+
+"""
Represents the source code attached to a release in a particular format
"""
type ReleaseSource {
@@ -16414,6 +18519,46 @@ type RemoveProjectFromSecurityDashboardPayload {
errors: [String!]!
}
+"""
+Autogenerated input type of RepositionImageDiffNote
+"""
+input RepositionImageDiffNoteInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The global id of the DiffNote to update
+ """
+ id: DiffNoteID!
+
+ """
+ The position of this note on a diff
+ """
+ position: UpdateDiffImagePositionInput!
+}
+
+"""
+Autogenerated return type of RepositionImageDiffNote
+"""
+type RepositionImageDiffNotePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The note after mutation
+ """
+ note: Note
+}
+
type Repository {
"""
Indicates repository has no visible content
@@ -16738,6 +18883,11 @@ type RootStorageStatistics {
storageSize: Float!
"""
+ The uploads size in bytes
+ """
+ uploadsSize: Float!
+
+ """
The wiki size in bytes
"""
wikiSize: Float!
@@ -16912,6 +19062,18 @@ type RunnerPlatformEdge {
node: RunnerPlatform
}
+type RunnerSetup {
+ """
+ Instructions for installing the runner on the specified architecture
+ """
+ installInstructions: String!
+
+ """
+ Instructions for registering the runner
+ """
+ registerInstructions: String
+}
+
"""
Represents a CI configuration of SAST
"""
@@ -17431,6 +19593,43 @@ type SecurityReportSummarySection {
vulnerabilitiesCount: Int
}
+enum SecurityReportTypeEnum {
+ """
+ API FUZZING scan report
+ """
+ API_FUZZING
+
+ """
+ CONTAINER SCANNING scan report
+ """
+ CONTAINER_SCANNING
+
+ """
+ COVERAGE FUZZING scan report
+ """
+ COVERAGE_FUZZING
+
+ """
+ DAST scan report
+ """
+ DAST
+
+ """
+ DEPENDENCY SCANNING scan report
+ """
+ DEPENDENCY_SCANNING
+
+ """
+ SAST scan report
+ """
+ SAST
+
+ """
+ SECRET DETECTION scan report
+ """
+ SECRET_DETECTION
+}
+
"""
The type of the security scanner
"""
@@ -17710,7 +19909,7 @@ type SentryErrorCollection {
"""
ID of the Sentry issue
"""
- id: ID!
+ id: GitlabErrorTrackingDetailedErrorID!
): SentryDetailedError
"""
@@ -17720,7 +19919,7 @@ type SentryErrorCollection {
"""
ID of the Sentry issue
"""
- id: ID!
+ id: GitlabErrorTrackingDetailedErrorID!
): SentryErrorStackTrace
"""
@@ -18099,7 +20298,7 @@ type Snippet implements Noteable {
"""
ID of the snippet
"""
- id: ID!
+ id: SnippetID!
"""
All notes on this noteable
@@ -18377,6 +20576,11 @@ type SnippetEdge {
node: Snippet
}
+"""
+Identifier of Snippet
+"""
+scalar SnippetID
+
type SnippetPermissions {
"""
Indicates the user can perform `admin_snippet` on this resource
@@ -18410,6 +20614,86 @@ type SnippetPermissions {
}
"""
+Represents the Geo sync and verification state of a snippet repository
+"""
+type SnippetRepositoryRegistry {
+ """
+ Timestamp when the SnippetRepositoryRegistry was created
+ """
+ createdAt: Time
+
+ """
+ ID of the SnippetRepositoryRegistry
+ """
+ id: ID!
+
+ """
+ Error message during sync of the SnippetRepositoryRegistry
+ """
+ lastSyncFailure: String
+
+ """
+ Timestamp of the most recent successful sync of the SnippetRepositoryRegistry
+ """
+ lastSyncedAt: Time
+
+ """
+ Timestamp after which the SnippetRepositoryRegistry should be resynced
+ """
+ retryAt: Time
+
+ """
+ Number of consecutive failed sync attempts of the SnippetRepositoryRegistry
+ """
+ retryCount: Int
+
+ """
+ ID of the Snippet Repository
+ """
+ snippetRepositoryId: ID!
+
+ """
+ Sync state of the SnippetRepositoryRegistry
+ """
+ state: RegistryState
+}
+
+"""
+The connection type for SnippetRepositoryRegistry.
+"""
+type SnippetRepositoryRegistryConnection {
+ """
+ A list of edges.
+ """
+ edges: [SnippetRepositoryRegistryEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [SnippetRepositoryRegistry]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type SnippetRepositoryRegistryEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: SnippetRepositoryRegistry
+}
+
+"""
Common sort values
"""
enum Sort {
@@ -18585,6 +20869,11 @@ type TerraformState {
id: ID!
"""
+ The latest version of the Terraform state
+ """
+ latestVersion: TerraformStateVersion
+
+ """
Timestamp the Terraform state was locked
"""
lockedAt: Time
@@ -18610,6 +20899,11 @@ The connection type for TerraformState.
"""
type TerraformStateConnection {
"""
+ Total count of collection
+ """
+ count: Int!
+
+ """
A list of edges.
"""
edges: [TerraformStateEdge]
@@ -18626,6 +20920,36 @@ type TerraformStateConnection {
}
"""
+Autogenerated input type of TerraformStateDelete
+"""
+input TerraformStateDeleteInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Global ID of the Terraform state
+ """
+ id: TerraformStateID!
+}
+
+"""
+Autogenerated return type of TerraformStateDelete
+"""
+type TerraformStateDeletePayload {
+ """
+ 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 TerraformStateEdge {
@@ -18641,6 +20965,98 @@ type TerraformStateEdge {
}
"""
+Identifier of Terraform::State
+"""
+scalar TerraformStateID
+
+"""
+Autogenerated input type of TerraformStateLock
+"""
+input TerraformStateLockInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Global ID of the Terraform state
+ """
+ id: TerraformStateID!
+}
+
+"""
+Autogenerated return type of TerraformStateLock
+"""
+type TerraformStateLockPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+"""
+Autogenerated input type of TerraformStateUnlock
+"""
+input TerraformStateUnlockInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Global ID of the Terraform state
+ """
+ id: TerraformStateID!
+}
+
+"""
+Autogenerated return type of TerraformStateUnlock
+"""
+type TerraformStateUnlockPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+type TerraformStateVersion {
+ """
+ Timestamp the version was created
+ """
+ createdAt: Time!
+
+ """
+ The user that created this version
+ """
+ createdByUser: User
+
+ """
+ ID of the Terraform state version
+ """
+ id: ID!
+
+ """
+ The job that created this version
+ """
+ job: CiJob
+
+ """
+ Timestamp the version was updated
+ """
+ updatedAt: Time!
+}
+
+"""
Represents the Geo sync and verification state of a terraform state version
"""
type TerraformStateVersionRegistry {
@@ -18793,11 +21209,61 @@ Time represented in ISO 8601
"""
scalar Time
-interface TimeboxBurnupTimeSeriesInterface {
+"""
+Represents the time report stats for timeboxes
+"""
+type TimeReportStats {
+ """
+ Completed issues metrics
+ """
+ complete: TimeboxMetrics
+
+ """
+ Incomplete issues metrics
+ """
+ incomplete: TimeboxMetrics
+
+ """
+ Total issues metrics
+ """
+ total: TimeboxMetrics
+}
+
+"""
+Represents measured stats metrics for timeboxes
+"""
+type TimeboxMetrics {
+ """
+ The count metric
+ """
+ count: Int!
+
+ """
+ The weight metric
+ """
+ weight: Int!
+}
+
+"""
+Represents a historically accurate report about the timebox
+"""
+type TimeboxReport {
"""
Daily scope and completed totals for burnup charts
"""
burnupTimeSeries: [BurnupChartDailyTotals!]
+
+ """
+ Represents the time report stats for the timebox
+ """
+ stats: TimeReportStats
+}
+
+interface TimeboxReportInterface {
+ """
+ Historically accurate report about the timebox
+ """
+ report: TimeboxReport
}
"""
@@ -18817,11 +21283,6 @@ input Timeframe {
type Timelog {
"""
- Timestamp of when the time tracked was spent at. Deprecated in 12.10: Use `spentAt`
- """
- date: Time! @deprecated(reason: "Use `spentAt`. Deprecated in 12.10")
-
- """
The issue that logged time was added to
"""
issue: Issue
@@ -18963,6 +21424,41 @@ type TodoConnection {
}
"""
+Autogenerated input type of TodoCreate
+"""
+input TodoCreateInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported
+ """
+ targetId: TodoableID!
+}
+
+"""
+Autogenerated return type of TodoCreate
+"""
+type TodoCreatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The to-do created
+ """
+ todo: Todo
+}
+
+"""
An edge in a connection.
"""
type TodoEdge {
@@ -19069,7 +21565,7 @@ type TodoRestoreManyPayload {
"""
The ids of the updated todo items. Deprecated in 13.2: Use todos
"""
- updatedIds: [ID!]! @deprecated(reason: "Use todos. Deprecated in 13.2")
+ updatedIds: [TodoID!]! @deprecated(reason: "Use todos. Deprecated in 13.2")
}
"""
@@ -19130,6 +21626,11 @@ enum TodoTargetEnum {
}
"""
+Identifier of Todoable
+"""
+scalar TodoableID
+
+"""
Autogenerated input type of TodosMarkAllDone
"""
input TodosMarkAllDoneInput {
@@ -19161,7 +21662,7 @@ type TodosMarkAllDonePayload {
"""
Ids of the updated todos. Deprecated in 13.2: Use todos
"""
- updatedIds: [ID!]! @deprecated(reason: "Use todos. Deprecated in 13.2")
+ updatedIds: [TodoID!]! @deprecated(reason: "Use todos. Deprecated in 13.2")
}
"""
@@ -19553,7 +22054,7 @@ input UpdateBoardListInput {
"""
Global ID of the list.
"""
- listId: ID!
+ listId: ListID!
"""
Position of list within the board
@@ -19855,7 +22356,7 @@ input UpdateIssueInput {
"""
The ID of the parent epic. NULL when removing the association
"""
- epicId: ID
+ epicId: EpicID
"""
The desired health status
@@ -20110,7 +22611,7 @@ input UpdateSnippetInput {
"""
The global id of the snippet to update
"""
- id: ID!
+ id: SnippetID!
"""
Title of the snippet
@@ -20208,7 +22709,7 @@ type User {
"""
The global ID of the project the authored merge requests should be in. Incompatible with projectPath.
"""
- projectId: ID
+ projectId: ProjectID
"""
The full-path of the project the authored merge requests should be in. Incompatible with projectId.
@@ -20293,7 +22794,7 @@ type User {
"""
The global ID of the project the authored merge requests should be in. Incompatible with projectPath.
"""
- projectId: ID
+ projectId: ProjectID
"""
The full-path of the project the authored merge requests should be in. Incompatible with projectId.
@@ -20332,6 +22833,11 @@ type User {
email: String
"""
+ Group count for the user. Available only when feature flag `user_group_counts` is enabled
+ """
+ groupCount: Int
+
+ """
Group memberships of the user
"""
groupMemberships(
@@ -20413,7 +22919,7 @@ type User {
"""
Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1"
"""
- ids: [ID!]
+ ids: [SnippetID!]
"""
Returns the last _n_ elements from the list.
@@ -20616,6 +23122,11 @@ enum UserState {
type UserStatus {
"""
+ User availability status
+ """
+ availability: AvailabilityEnum!
+
+ """
String representation of emoji
"""
emoji: String
@@ -20644,7 +23155,7 @@ enum VisibilityScopesEnum {
}
"""
-Represents the count of vulnerabilities by severity on a particular day
+Represents the count of vulnerabilities by severity on a particular day. This data is retained for 365 days
"""
type VulnerabilitiesCountByDay {
"""
@@ -20689,7 +23200,7 @@ type VulnerabilitiesCountByDay {
}
"""
-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. This data is retained for 365 days
"""
type VulnerabilitiesCountByDayAndSeverity {
"""
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 6914ba29c57..de3f9c2665f 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -1481,6 +1481,525 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "AlertManagementHttpIntegration",
+ "description": "An endpoint and credentials used to accept alerts for a project",
+ "fields": [
+ {
+ "name": "active",
+ "description": "Whether the endpoint is currently accepting alerts",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "apiUrl",
+ "description": "URL at which Prometheus metrics can be queried to populate the metrics dashboard",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "token",
+ "description": "Token used to authenticate alert notification requests",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "type",
+ "description": "Type of integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "AlertManagementIntegrationType",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "url",
+ "description": "Endpoint which accepts alert notifications",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+ {
+ "kind": "INTERFACE",
+ "name": "AlertManagementIntegration",
+ "ofType": null
+ }
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
+ "name": "AlertManagementHttpIntegrationID",
+ "description": "Identifier of AlertManagement::HttpIntegration",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INTERFACE",
+ "name": "AlertManagementIntegration",
+ "description": null,
+ "fields": [
+ {
+ "name": "active",
+ "description": "Whether the endpoint is currently accepting alerts",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "apiUrl",
+ "description": "URL at which Prometheus metrics can be queried to populate the metrics dashboard",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "token",
+ "description": "Token used to authenticate alert notification requests",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "type",
+ "description": "Type of integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "AlertManagementIntegrationType",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "url",
+ "description": "Endpoint which accepts alert notifications",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": [
+ {
+ "kind": "OBJECT",
+ "name": "AlertManagementHttpIntegration",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "AlertManagementPrometheusIntegration",
+ "ofType": null
+ }
+ ]
+ },
+ {
+ "kind": "OBJECT",
+ "name": "AlertManagementIntegrationConnection",
+ "description": "The connection type for AlertManagementIntegration.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "AlertManagementIntegrationEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "INTERFACE",
+ "name": "AlertManagementIntegration",
+ "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": "AlertManagementIntegrationEdge",
+ "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": "AlertManagementIntegration",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
+ "name": "AlertManagementIntegrationType",
+ "description": "Values of types of integrations",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "PROMETHEUS",
+ "description": "Prometheus integration",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "HTTP",
+ "description": "Integration with any monitoring tool",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "AlertManagementPrometheusIntegration",
+ "description": "An endpoint and credentials used to accept Prometheus alerts for a project",
+ "fields": [
+ {
+ "name": "active",
+ "description": "Whether the endpoint is currently accepting alerts",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "apiUrl",
+ "description": "URL at which Prometheus metrics can be queried to populate the metrics dashboard",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "token",
+ "description": "Token used to authenticate alert notification requests",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "type",
+ "description": "Type of integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "AlertManagementIntegrationType",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "url",
+ "description": "Endpoint which accepts alert notifications",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+ {
+ "kind": "INTERFACE",
+ "name": "AlertManagementIntegration",
+ "ofType": null
+ }
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "ENUM",
"name": "AlertManagementSeverity",
"description": "Alert severity values",
@@ -1883,6 +2402,29 @@
"possibleTypes": null
},
{
+ "kind": "ENUM",
+ "name": "AvailabilityEnum",
+ "description": "User availability status",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "NOT_SET",
+ "description": "Not Set",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "BUSY",
+ "description": "Busy",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "AwardEmoji",
"description": "An emoji awarded by a user",
@@ -2936,7 +3478,7 @@
"description": "Find a list by its global ID",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "ListID",
"ofType": null
},
"defaultValue": null
@@ -3326,6 +3868,16 @@
"defaultValue": null
},
{
+ "name": "includeDescendantGroups",
+ "description": "Include epics from descendant groups",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": "true"
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -4202,6 +4754,42 @@
"deprecationReason": null
},
{
+ "name": "userDiscussionsCount",
+ "description": "Number of user discussions in the epic",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "userNotesCount",
+ "description": "Number of user notes of the epic",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "userPermissions",
"description": "Permissions for the current user on the resource",
"args": [
@@ -4518,7 +5106,17 @@
"description": "Filter by epic ID. Incompatible with epicWildcardId",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "EpicID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "iterationTitle",
+ "description": "Filter by iteration title",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
"ofType": null
},
"defaultValue": null
@@ -4562,6 +5160,16 @@
"ofType": null
},
"defaultValue": null
+ },
+ {
+ "name": "iterationWildcardId",
+ "description": "Filter by iteration ID wildcard",
+ "type": {
+ "kind": "ENUM",
+ "name": "IterationWildcardId",
+ "ofType": null
+ },
+ "defaultValue": null
}
],
"interfaces": null,
@@ -5689,6 +6297,24 @@
"deprecationReason": null
},
{
+ "name": "pipeline",
+ "description": "Pipeline the job belongs to",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "Pipeline",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "scheduledAt",
"description": "Schedule for the build",
"args": [
@@ -6184,6 +6810,24 @@
"description": "The connection type for ClusterAgent.",
"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": [
@@ -6443,6 +7087,24 @@
"description": "The connection type for ClusterAgentToken.",
"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": [
@@ -6785,6 +7447,246 @@
},
{
"kind": "OBJECT",
+ "name": "CodeCoverageActivity",
+ "description": "Represents the code coverage activity for a group",
+ "fields": [
+ {
+ "name": "averageCoverage",
+ "description": "Average percentage of the different code coverage results available for the group.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Float",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "coverageCount",
+ "description": "Number of different code coverage results available for the group.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "date",
+ "description": "Date when the code coverage was created.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Date",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "projectCount",
+ "description": "Number of projects with code coverage results for the group.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "CodeCoverageActivityConnection",
+ "description": "The connection type for CodeCoverageActivity.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CodeCoverageActivityEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CodeCoverageActivity",
+ "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": "CodeCoverageActivityEdge",
+ "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": "CodeCoverageActivity",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "CodeCoverageSummary",
+ "description": "Represents the code coverage summary for a project",
+ "fields": [
+ {
+ "name": "averageCoverage",
+ "description": "Average percentage of the different code coverage results available for the project.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Float",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "coverageCount",
+ "description": "Number of different code coverage results available.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lastUpdatedOn",
+ "description": "Latest date when the code coverage was created for the project.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Date",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "Commit",
"description": null,
"fields": [
@@ -6891,49 +7793,6 @@
"deprecationReason": null
},
{
- "name": "latestPipeline",
- "description": "Latest pipeline of the commit. Deprecated in 12.5: Use `pipelines`",
- "args": [
- {
- "name": "status",
- "description": "Filter pipelines by their status",
- "type": {
- "kind": "ENUM",
- "name": "PipelineStatusEnum",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "ref",
- "description": "Filter pipelines by the ref they are run for",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "sha",
- "description": "Filter pipelines by the sha of the commit they are run for",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- }
- ],
- "type": {
- "kind": "OBJECT",
- "name": "Pipeline",
- "ofType": null
- },
- "isDeprecated": true,
- "deprecationReason": "Use `pipelines`. Deprecated in 12.5"
- },
- {
"name": "message",
"description": "Raw commit message",
"args": [
@@ -7286,7 +8145,7 @@
},
{
"name": "branch",
- "description": "Name of the branch",
+ "description": "Name of the branch to commit into, it can be a new branch",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -7299,6 +8158,16 @@
"defaultValue": null
},
{
+ "name": "startBranch",
+ "description": "If on a new branch, name of the original branch",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "message",
"description": "Raw commit message",
"type": {
@@ -7454,8 +8323,8 @@
"kind": "NON_NULL",
"name": null,
"ofType": {
- "kind": "ENUM",
- "name": "ProjectSettingEnum",
+ "kind": "SCALAR",
+ "name": "String",
"ofType": null
}
},
@@ -7995,6 +8864,924 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "ContainerRepository",
+ "description": "A container repository",
+ "fields": [
+ {
+ "name": "canDelete",
+ "description": "Can the current user delete the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "createdAt",
+ "description": "Timestamp when the container repository was created.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "expirationPolicyCleanupStatus",
+ "description": "The tags cleanup status for the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "ContainerRepositoryCleanupStatus",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "expirationPolicyStartedAt",
+ "description": "Timestamp when the cleanup done by the expiration policy was started on the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "location",
+ "description": "URL of the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "path",
+ "description": "Path of the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "status",
+ "description": "Status of the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "ContainerRepositoryStatus",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "tagsCount",
+ "description": "Number of tags associated with this image.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "updatedAt",
+ "description": "Timestamp when the container repository was updated.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
+ "name": "ContainerRepositoryCleanupStatus",
+ "description": "Status of the tags cleanup of a container repository",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "UNSCHEDULED",
+ "description": "The tags cleanup is not scheduled. This is the default state.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "SCHEDULED",
+ "description": "The tags cleanup is scheduled and is going to be executed shortly.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "UNFINISHED",
+ "description": "The tags cleanup has been partially executed. There are still remaining tags to delete.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "ONGOING",
+ "description": "The tags cleanup is ongoing.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "ContainerRepositoryConnection",
+ "description": "The connection type for ContainerRepository.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "ContainerRepositoryEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "ContainerRepository",
+ "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": "ContainerRepositoryDetails",
+ "description": "Details of a container repository",
+ "fields": [
+ {
+ "name": "canDelete",
+ "description": "Can the current user delete the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "createdAt",
+ "description": "Timestamp when the container repository was created.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "expirationPolicyCleanupStatus",
+ "description": "The tags cleanup status for the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "ContainerRepositoryCleanupStatus",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "expirationPolicyStartedAt",
+ "description": "Timestamp when the cleanup done by the expiration policy was started on the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "location",
+ "description": "URL of the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "path",
+ "description": "Path of the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "status",
+ "description": "Status of the container repository.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "ContainerRepositoryStatus",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "tags",
+ "description": "Tags of the container repository",
+ "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": "ContainerRepositoryTagConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "tagsCount",
+ "description": "Number of tags associated with this image.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "updatedAt",
+ "description": "Timestamp when the container repository was updated.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "ContainerRepositoryEdge",
+ "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": "ContainerRepository",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
+ "name": "ContainerRepositoryID",
+ "description": "Identifier of ContainerRepository",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
+ "name": "ContainerRepositoryStatus",
+ "description": "Status of a container repository",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "DELETE_SCHEDULED",
+ "description": "Delete Scheduled status.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "DELETE_FAILED",
+ "description": "Delete Failed status.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "ContainerRepositoryTag",
+ "description": "A tag from a container repository",
+ "fields": [
+ {
+ "name": "canDelete",
+ "description": "Can the current user delete this tag.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "createdAt",
+ "description": "Timestamp when the tag was created.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "digest",
+ "description": "Digest of the tag.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "location",
+ "description": "URL of the tag.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the tag.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "path",
+ "description": "Path of the tag.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "revision",
+ "description": "Revision of the tag.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "shortRevision",
+ "description": "Short revision of the tag.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "totalSize",
+ "description": "The size of the tag.",
+ "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": "ContainerRepositoryTagConnection",
+ "description": "The connection type for ContainerRepositoryTag.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "ContainerRepositoryTagEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "ContainerRepositoryTag",
+ "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": "ContainerRepositoryTagEdge",
+ "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": "ContainerRepositoryTag",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
"name": "CreateAlertIssueInput",
"description": "Autogenerated input type of CreateAlertIssue",
@@ -8306,7 +10093,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project full path the board is associated with.",
+ "description": "The project full path the resource is associated with",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -8316,7 +10103,7 @@
},
{
"name": "groupPath",
- "description": "The group full path the board is associated with.",
+ "description": "The group full path the resource is associated with",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -8349,7 +10136,7 @@
"description": "The ID of the milestone to be assigned to the board.",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "MilestoneID",
"ofType": null
},
"defaultValue": null
@@ -8375,7 +10162,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "LabelID",
"ofType": null
}
}
@@ -8712,6 +10499,136 @@
},
{
"kind": "INPUT_OBJECT",
+ "name": "CreateCustomEmojiInput",
+ "description": "Autogenerated input type of CreateCustomEmoji",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "groupPath",
+ "description": "Namespace full path the emoji is associated with",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the emoji",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "url",
+ "description": "Location of the emoji file",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "CreateCustomEmojiPayload",
+ "description": "Autogenerated return type of CreateCustomEmoji",
+ "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": "customEmoji",
+ "description": "The new custom emoji",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "CustomEmoji",
+ "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": "CreateDiffNoteInput",
"description": "Autogenerated input type of CreateDiffNote",
"fields": null,
@@ -10334,6 +12251,213 @@
]
},
{
+ "kind": "OBJECT",
+ "name": "CustomEmoji",
+ "description": "A custom emoji uploaded by user",
+ "fields": [
+ {
+ "name": "external",
+ "description": "Whether the emoji is an external link",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "The ID of the emoji",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "CustomEmojiID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "The name of the emoji",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "url",
+ "description": "The link to file of the emoji",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "CustomEmojiConnection",
+ "description": "The connection type for CustomEmoji.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CustomEmojiEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CustomEmoji",
+ "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": "CustomEmojiEdge",
+ "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": "CustomEmoji",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
+ "name": "CustomEmojiID",
+ "description": "Identifier of CustomEmoji",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
"name": "DastOnDemandScanCreateInput",
"description": "Autogenerated input type of DastOnDemandScanCreate",
@@ -10503,7 +12627,7 @@
},
{
"name": "globalId",
- "description": "ID of the DAST scanner profile",
+ "description": "ID of the DAST scanner profile. Deprecated in 13.6: Use `id`",
"args": [
],
@@ -10516,12 +12640,12 @@
"ofType": null
}
},
- "isDeprecated": false,
- "deprecationReason": null
+ "isDeprecated": true,
+ "deprecationReason": "Use `id`. Deprecated in 13.6"
},
{
"name": "id",
- "description": "ID of the DAST scanner profile. Deprecated in 13.4: Use `global_id`",
+ "description": "ID of the DAST scanner profile",
"args": [
],
@@ -10530,12 +12654,12 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DastScannerProfileID",
"ofType": null
}
},
- "isDeprecated": true,
- "deprecationReason": "Use `global_id`. Deprecated in 13.4"
+ "isDeprecated": false,
+ "deprecationReason": null
},
{
"name": "profileName",
@@ -10850,7 +12974,7 @@
},
{
"name": "globalId",
- "description": "ID of the scanner profile.",
+ "description": "ID of the scanner profile.. Deprecated in 13.6: Use `id`",
"args": [
],
@@ -10859,22 +12983,22 @@
"name": "DastScannerProfileID",
"ofType": null
},
- "isDeprecated": false,
- "deprecationReason": null
+ "isDeprecated": true,
+ "deprecationReason": "Use `id`. Deprecated in 13.6"
},
{
"name": "id",
- "description": "ID of the scanner profile.. Deprecated in 13.4: Use `global_id`",
+ "description": "ID of the scanner profile.",
"args": [
],
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DastScannerProfileID",
"ofType": null
},
- "isDeprecated": true,
- "deprecationReason": "Use `global_id`. Deprecated in 13.4"
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -12041,6 +14165,242 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "DastSiteValidation",
+ "description": "Represents a DAST Site Validation",
+ "fields": [
+ {
+ "name": "id",
+ "description": "ID of the site validation",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DastSiteValidationID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "status",
+ "description": "The status of the validation",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "DastSiteProfileValidationStatusEnum",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "DastSiteValidationCreateInput",
+ "description": "Autogenerated input type of DastSiteValidationCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "fullPath",
+ "description": "The project the site profile belongs to.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "dastSiteTokenId",
+ "description": "ID of the site token.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DastSiteTokenID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "validationPath",
+ "description": "The path to be requested during validation.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "strategy",
+ "description": "The validation strategy to be used.",
+ "type": {
+ "kind": "ENUM",
+ "name": "DastSiteValidationStrategyEnum",
+ "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": "DastSiteValidationCreatePayload",
+ "description": "Autogenerated return type of DastSiteValidationCreate",
+ "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 site validation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "DastSiteValidationID",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "status",
+ "description": "The current validation status.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "DastSiteProfileValidationStatusEnum",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
+ "name": "DastSiteValidationID",
+ "description": "Identifier of DastSiteValidation",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
+ "name": "DastSiteValidationStrategyEnum",
+ "description": null,
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "TEXT_FILE",
+ "description": "Text file validation",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "HEADER",
+ "description": "Header validation",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "SCALAR",
"name": "Date",
"description": "Date represented in ISO 8601",
@@ -12064,7 +14424,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "MetricsDashboardAnnotationID",
"ofType": null
}
},
@@ -12574,7 +14934,7 @@
"description": "The Global ID of the most recent acceptable version",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DesignManagementVersionID",
"ofType": null
},
"defaultValue": null
@@ -13023,7 +15383,7 @@
"description": "Find a design by its ID",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DesignManagementDesignID",
"ofType": null
},
"defaultValue": null
@@ -13059,7 +15419,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DesignManagementDesignAtVersionID",
"ofType": null
}
},
@@ -13089,7 +15449,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DesignManagementDesignID",
"ofType": null
}
}
@@ -13119,7 +15479,7 @@
"description": "Filters designs to only those that existed at the version. If argument is omitted or nil then all designs will reflect the latest version",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DesignManagementVersionID",
"ofType": null
},
"defaultValue": null
@@ -13232,7 +15592,7 @@
"description": "The Global ID of the version",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DesignManagementVersionID",
"ofType": null
},
"defaultValue": null
@@ -13265,7 +15625,7 @@
"description": "The Global ID of the most recent acceptable version",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DesignManagementVersionID",
"ofType": null
},
"defaultValue": null
@@ -13687,7 +16047,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DesignManagementDesignAtVersionID",
"ofType": null
}
},
@@ -13714,7 +16074,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DesignManagementVersionID",
"ofType": null
}
},
@@ -13877,6 +16237,16 @@
},
{
"kind": "SCALAR",
+ "name": "DesignManagementDesignAtVersionID",
+ "description": "Identifier of DesignManagement::DesignAtVersion",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
"name": "DesignManagementDesignID",
"description": "Identifier of DesignManagement::Design",
"fields": null,
@@ -14184,6 +16554,16 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "DesignManagementVersionID",
+ "description": "Identifier of DesignManagement::Version",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "DesignVersion",
"description": "A specific version in which designs were added, modified or deleted",
@@ -14197,7 +16577,7 @@
"description": "The ID of the DesignAtVersion",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DesignManagementDesignAtVersionID",
"ofType": null
},
"defaultValue": null
@@ -14207,7 +16587,7 @@
"description": "The ID of a specific design",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DesignManagementDesignID",
"ofType": null
},
"defaultValue": null
@@ -14307,7 +16687,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DesignManagementDesignID",
"ofType": null
}
}
@@ -14782,6 +17162,112 @@
},
{
"kind": "INPUT_OBJECT",
+ "name": "DestroyContainerRepositoryInput",
+ "description": "Autogenerated input type of DestroyContainerRepository",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "ID of the container repository.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ContainerRepositoryID",
+ "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": "DestroyContainerRepositoryPayload",
+ "description": "Autogenerated return type of DestroyContainerRepository",
+ "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": "containerRepository",
+ "description": "The container repository policy after scheduling the deletion.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "ContainerRepository",
+ "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,
@@ -14896,7 +17382,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "SnippetID",
"ofType": null
}
},
@@ -15124,6 +17610,220 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "DevopsAdoptionSegment",
+ "description": "Segment",
+ "fields": [
+ {
+ "name": "groups",
+ "description": "Assigned groups",
+ "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": "GroupConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the segment",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the segment",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "DevopsAdoptionSegmentConnection",
+ "description": "The connection type for DevopsAdoptionSegment.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "DevopsAdoptionSegmentEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "DevopsAdoptionSegment",
+ "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": "DevopsAdoptionSegmentEdge",
+ "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": "DevopsAdoptionSegment",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
"name": "DiffImagePositionInput",
"description": null,
@@ -15243,6 +17943,16 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "DiffNoteID",
+ "description": "Identifier of DiffNote",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
"name": "DiffPathsInput",
"description": null,
@@ -16567,14 +19277,18 @@
},
{
"name": "path",
- "description": "The path to the environment. Will always return null if `expose_environment_path_in_alert_details` feature flag is disabled",
+ "description": "The path to the environment.",
"args": [
],
"type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
},
"isDeprecated": false,
"deprecationReason": null
@@ -16728,6 +19442,108 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "EnvironmentsCanaryIngressUpdateInput",
+ "description": "Autogenerated input type of EnvironmentsCanaryIngressUpdate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "The global ID of the environment to update",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "EnvironmentID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "weight",
+ "description": "The weight of the Canary Ingress",
+ "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": "EnvironmentsCanaryIngressUpdatePayload",
+ "description": "Autogenerated return type of EnvironmentsCanaryIngressUpdate",
+ "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": "Epic",
"description": "Represents an epic",
@@ -16891,6 +19707,16 @@
"defaultValue": null
},
{
+ "name": "includeDescendantGroups",
+ "description": "Include epics from descendant groups",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": "true"
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -17767,6 +20593,42 @@
"deprecationReason": null
},
{
+ "name": "userDiscussionsCount",
+ "description": "Number of user discussions in the epic",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "userNotesCount",
+ "description": "Number of user notes of the epic",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "userPermissions",
"description": "Permissions for the current user on the resource",
"args": [
@@ -18391,6 +21253,20 @@
"deprecationReason": null
},
{
+ "name": "blockedByCount",
+ "description": "Count of issues blocking this issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "closedAt",
"description": "Timestamp of when the issue was closed",
"args": [
@@ -18550,20 +21426,6 @@
"deprecationReason": null
},
{
- "name": "designs",
- "description": "The designs associated with this issue. Deprecated in 12.2: Use `designCollection`",
- "args": [
-
- ],
- "type": {
- "kind": "OBJECT",
- "name": "DesignCollection",
- "ofType": null
- },
- "isDeprecated": true,
- "deprecationReason": "Use `designCollection`. Deprecated in 12.2"
- },
- {
"name": "discussionLocked",
"description": "Indicates discussion is locked on the issue",
"args": [
@@ -18671,6 +21533,24 @@
"deprecationReason": null
},
{
+ "name": "emailsDisabled",
+ "description": "Indicates if a project has email notifications disabled: `true` if email notifications are disabled",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "epic",
"description": "Epic to which this issue belongs",
"args": [
@@ -18717,6 +21597,34 @@
"deprecationReason": null
},
{
+ "name": "humanTimeEstimate",
+ "description": "Human-readable time estimate of the issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "humanTotalTimeSpent",
+ "description": "Human-readable total time reported as spent on the issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "id",
"description": "Global ID of the epic-issue relation",
"args": [
@@ -18830,6 +21738,34 @@
"deprecationReason": null
},
{
+ "name": "moved",
+ "description": "Indicates if issue got moved from other project",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "movedTo",
+ "description": "Updated Issue after it got moved to another project",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Issue",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "notes",
"description": "All notes on this noteable",
"args": [
@@ -19191,6 +22127,20 @@
"deprecationReason": null
},
{
+ "name": "updatedBy",
+ "description": "User that last updated the issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "upvotes",
"description": "Number of upvotes the issue has received",
"args": [
@@ -19209,6 +22159,24 @@
"deprecationReason": null
},
{
+ "name": "userDiscussionsCount",
+ "description": "Number of user discussions in the issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "userNotesCount",
"description": "Number of user notes of the issue",
"args": [
@@ -19387,6 +22355,24 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "weight",
+ "description": "Total weight of issues collection",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -20382,6 +23368,77 @@
"deprecationReason": null
},
{
+ "name": "snippetRepositoryRegistries",
+ "description": "Find snippet repository registries on this Geo node. Available only when feature flag `geo_snippet_repository_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": "SnippetRepositoryRegistryConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "syncObjectStorage",
"description": "Indicates if this secondary node will replicate blobs in Object Storage",
"args": [
@@ -20503,6 +23560,16 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "GitlabErrorTrackingDetailedErrorID",
+ "description": "Identifier of Gitlab::ErrorTracking::DetailedError",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "GrafanaIntegration",
"description": null,
@@ -20580,24 +23647,6 @@
"deprecationReason": null
},
{
- "name": "token",
- "description": "API token for the Grafana integration. Deprecated in 12.7: Plain text token has been masked for security reasons",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- }
- },
- "isDeprecated": true,
- "deprecationReason": "Plain text token has been masked for security reasons. Deprecated in 12.7"
- },
- {
"name": "updatedAt",
"description": "Timestamp of the issue's last activity",
"args": [
@@ -20720,7 +23769,7 @@
"description": "Find a board by its ID",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "BoardID",
"ofType": null
},
"defaultValue": null
@@ -20775,6 +23824,136 @@
"deprecationReason": null
},
{
+ "name": "codeCoverageActivities",
+ "description": "Represents the code coverage activity for this group. Available only when feature flag `group_coverage_data_report_graph` is enabled",
+ "args": [
+ {
+ "name": "startDate",
+ "description": "First day for which to fetch code coverage activity (maximum time window is set to 90 days)",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Date",
+ "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": "CodeCoverageActivityConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "containerRepositories",
+ "description": "Container repositories of the project",
+ "args": [
+ {
+ "name": "name",
+ "description": "Filter the container repositories by their name",
+ "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": "ContainerRepositoryConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "containsLockedProjects",
"description": "Includes at least one project where the repository size exceeds the limit",
"args": [
@@ -20793,6 +23972,59 @@
"deprecationReason": null
},
{
+ "name": "customEmoji",
+ "description": "Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled",
+ "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": "CustomEmojiConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "description",
"description": "Description of the namespace",
"args": [
@@ -20973,6 +24205,16 @@
"ofType": null
},
"defaultValue": null
+ },
+ {
+ "name": "includeDescendantGroups",
+ "description": "Include epics from descendant groups",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": "true"
}
],
"type": {
@@ -21124,6 +24366,16 @@
"defaultValue": null
},
{
+ "name": "includeDescendantGroups",
+ "description": "Include epics from descendant groups",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": "true"
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -21435,7 +24687,7 @@
},
{
"name": "assigneeId",
- "description": "ID of a user assigned to the issues, \"none\" and \"any\" values supported",
+ "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -21566,6 +24818,16 @@
"defaultValue": null
},
{
+ "name": "epicId",
+ "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "includeSubgroups",
"description": "Include issues belonging to subgroups",
"type": {
@@ -22467,6 +25729,20 @@
"deprecationReason": null
},
{
+ "name": "stats",
+ "description": "Group statistics",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "GroupStats",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "storageSizeLimit",
"description": "Total storage limit of the root namespace in bytes",
"args": [
@@ -23018,7 +26294,16 @@
"name": "vulnerabilityGrades",
"description": "Represents vulnerable project counts for each grade",
"args": [
-
+ {
+ "name": "includeSubgroups",
+ "description": "Include grades belonging to subgroups",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": "false"
+ }
],
"type": {
"kind": "NON_NULL",
@@ -23224,6 +26509,128 @@
},
{
"kind": "OBJECT",
+ "name": "GroupConnection",
+ "description": "The connection type for Group.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "GroupEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "Group",
+ "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": "GroupEdge",
+ "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": "Group",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
+ "name": "GroupID",
+ "description": "Identifier of Group",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "GroupMember",
"description": "Represents a Group Membership",
"fields": [
@@ -23521,6 +26928,74 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "GroupReleaseStats",
+ "description": "Contains release-related statistics about a group",
+ "fields": [
+ {
+ "name": "releasesCount",
+ "description": "Total number of releases in all descendant projects of the group. Will always return `null` if `group_level_release_statistics` feature flag is disabled",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "releasesPercentage",
+ "description": "Percentage of the group's descendant projects that have at least one release. Will always return `null` if `group_level_release_statistics` feature flag is disabled",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "GroupStats",
+ "description": "Contains statistics about a group",
+ "fields": [
+ {
+ "name": "releaseStats",
+ "description": "Statistics related to releases within the group",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "GroupReleaseStats",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "ENUM",
"name": "HealthStatus",
"description": "Health status of an issue or epic",
@@ -23550,6 +27025,462 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "HttpIntegrationCreateInput",
+ "description": "Autogenerated input type of HttpIntegrationCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "projectPath",
+ "description": "The project to create the integration in",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "name",
+ "description": "The name of the integration",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "active",
+ "description": "Whether the integration is receiving alerts",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "HttpIntegrationCreatePayload",
+ "description": "Autogenerated return type of HttpIntegrationCreate",
+ "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": "integration",
+ "description": "The HTTP integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "AlertManagementHttpIntegration",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "HttpIntegrationDestroyInput",
+ "description": "Autogenerated input type of HttpIntegrationDestroy",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "The id of the integration to remove",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "AlertManagementHttpIntegrationID",
+ "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": "HttpIntegrationDestroyPayload",
+ "description": "Autogenerated return type of HttpIntegrationDestroy",
+ "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": "integration",
+ "description": "The HTTP integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "AlertManagementHttpIntegration",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "HttpIntegrationResetTokenInput",
+ "description": "Autogenerated input type of HttpIntegrationResetToken",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "The id of the integration to mutate",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "AlertManagementHttpIntegrationID",
+ "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": "HttpIntegrationResetTokenPayload",
+ "description": "Autogenerated return type of HttpIntegrationResetToken",
+ "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": "integration",
+ "description": "The HTTP integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "AlertManagementHttpIntegration",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "HttpIntegrationUpdateInput",
+ "description": "Autogenerated input type of HttpIntegrationUpdate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "The id of the integration to mutate",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "AlertManagementHttpIntegrationID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "name",
+ "description": "The name of the integration",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "active",
+ "description": "Whether the integration is receiving alerts",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "HttpIntegrationUpdatePayload",
+ "description": "Autogenerated return type of HttpIntegrationUpdate",
+ "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": "integration",
+ "description": "The HTTP integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "AlertManagementHttpIntegration",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "SCALAR",
"name": "ID",
"description": "Represents a unique identifier that is Base64 obfuscated. It is often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"VXNlci0xMA==\"`) or integer (such as `4`) input value will be accepted as an ID.",
@@ -24191,6 +28122,20 @@
"deprecationReason": null
},
{
+ "name": "blockedByCount",
+ "description": "Count of issues blocking this issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "closedAt",
"description": "Timestamp of when the issue was closed",
"args": [
@@ -24350,20 +28295,6 @@
"deprecationReason": null
},
{
- "name": "designs",
- "description": "The designs associated with this issue. Deprecated in 12.2: Use `designCollection`",
- "args": [
-
- ],
- "type": {
- "kind": "OBJECT",
- "name": "DesignCollection",
- "ofType": null
- },
- "isDeprecated": true,
- "deprecationReason": "Use `designCollection`. Deprecated in 12.2"
- },
- {
"name": "discussionLocked",
"description": "Indicates discussion is locked on the issue",
"args": [
@@ -24471,6 +28402,24 @@
"deprecationReason": null
},
{
+ "name": "emailsDisabled",
+ "description": "Indicates if a project has email notifications disabled: `true` if email notifications are disabled",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "epic",
"description": "Epic to which this issue belongs",
"args": [
@@ -24499,6 +28448,34 @@
"deprecationReason": null
},
{
+ "name": "humanTimeEstimate",
+ "description": "Human-readable time estimate of the issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "humanTotalTimeSpent",
+ "description": "Human-readable total time reported as spent on the issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "id",
"description": "ID of the issue",
"args": [
@@ -24616,6 +28593,34 @@
"deprecationReason": null
},
{
+ "name": "moved",
+ "description": "Indicates if issue got moved from other project",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "movedTo",
+ "description": "Updated Issue after it got moved to another project",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Issue",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "notes",
"description": "All notes on this noteable",
"args": [
@@ -24963,6 +28968,20 @@
"deprecationReason": null
},
{
+ "name": "updatedBy",
+ "description": "User that last updated the issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "upvotes",
"description": "Number of upvotes the issue has received",
"args": [
@@ -24981,6 +29000,24 @@
"deprecationReason": null
},
{
+ "name": "userDiscussionsCount",
+ "description": "Number of user discussions in the issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "userNotesCount",
"description": "Number of user notes of the issue",
"args": [
@@ -25159,6 +29196,24 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "weight",
+ "description": "Total weight of issues collection",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -26137,7 +30192,7 @@
"description": "Global ID of the epic to be assigned to the issue, epic will be removed if absent or set to null",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "EpicID",
"ofType": null
},
"defaultValue": null
@@ -27015,6 +31070,18 @@
"description": "Published issues shown first",
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "SLA_DUE_AT_ASC",
+ "description": "Issues with earliest SLA due time shown first",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "SLA_DUE_AT_DESC",
+ "description": "Issues with latest SLA due time shown first",
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"possibleTypes": null
@@ -27167,28 +31234,6 @@
"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": [
@@ -27285,6 +31330,20 @@
"deprecationReason": null
},
{
+ "name": "report",
+ "description": "Historically accurate report about the timebox",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TimeboxReport",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "scopedPath",
"description": "Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts",
"args": [
@@ -27421,7 +31480,7 @@
"interfaces": [
{
"kind": "INTERFACE",
- "name": "TimeboxBurnupTimeSeriesInterface",
+ "name": "TimeboxReportInterface",
"ofType": null
}
],
@@ -27592,6 +31651,29 @@
"possibleTypes": null
},
{
+ "kind": "ENUM",
+ "name": "IterationWildcardId",
+ "description": "Iteration ID wildcard values",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "NONE",
+ "description": "No iteration is assigned",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "ANY",
+ "description": "An iteration is assigned",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "SCALAR",
"name": "JSON",
"description": "Represents untyped JSON",
@@ -28726,6 +32808,148 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "LabelCreateInput",
+ "description": "Autogenerated input type of LabelCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "projectPath",
+ "description": "The project full path the resource is associated with",
+ "type": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "groupPath",
+ "description": "The group full path the resource is associated with",
+ "type": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "title",
+ "description": "Title of the label",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "description",
+ "description": "Description of the label",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "color",
+ "description": "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the CSS color names in https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": "\"#428BCA\""
+ },
+ {
+ "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": "LabelCreatePayload",
+ "description": "Autogenerated return type of LabelCreate",
+ "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": "label",
+ "description": "The label after mutation",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Label",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "LabelEdge",
"description": "An edge in a connection.",
@@ -28833,7 +33057,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "SnippetID",
"ofType": null
}
},
@@ -29892,20 +34116,6 @@
"deprecationReason": null
},
{
- "name": "mergeCommitMessage",
- "description": "Default merge commit message of the merge request. Deprecated in 11.8: Use `defaultMergeCommitMessage`",
- "args": [
-
- ],
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "isDeprecated": true,
- "deprecationReason": "Use `defaultMergeCommitMessage`. Deprecated in 11.8"
- },
- {
"name": "mergeCommitSha",
"description": "SHA of the merge request commit (set once merged)",
"args": [
@@ -30636,6 +34846,20 @@
"deprecationReason": null
},
{
+ "name": "userDiscussionsCount",
+ "description": "Number of user discussions in the merge request",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "userNotesCount",
"description": "User notes count of the merge request",
"args": [
@@ -31644,7 +35868,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "LabelID",
"ofType": null
}
}
@@ -32929,33 +37153,21 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "MetricsDashboardAnnotationID",
+ "description": "Identifier of Metrics::Dashboard::Annotation",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "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": [
@@ -33056,6 +37268,20 @@
"deprecationReason": null
},
{
+ "name": "report",
+ "description": "Historically accurate report about the timebox",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TimeboxReport",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "startDate",
"description": "Timestamp of the milestone start date",
"args": [
@@ -33178,7 +37404,7 @@
"interfaces": [
{
"kind": "INTERFACE",
- "name": "TimeboxBurnupTimeSeriesInterface",
+ "name": "TimeboxReportInterface",
"ofType": null
}
],
@@ -33940,6 +38166,33 @@
"deprecationReason": null
},
{
+ "name": "createCustomEmoji",
+ "description": ". Available only when feature flag `custom_emoji` is enabled",
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "CreateCustomEmojiInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "CreateCustomEmojiPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "createDiffNote",
"description": null,
"args": [
@@ -34399,6 +38652,33 @@
"deprecationReason": null
},
{
+ "name": "dastSiteValidationCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "DastSiteValidationCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastSiteValidationCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "deleteAnnotation",
"description": null,
"args": [
@@ -34561,6 +38841,33 @@
"deprecationReason": null
},
{
+ "name": "destroyContainerRepository",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "DestroyContainerRepositoryInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DestroyContainerRepositoryPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "destroyNote",
"description": null,
"args": [
@@ -34669,6 +38976,33 @@
"deprecationReason": "Use vulnerabilityDismiss. Deprecated in 13.5"
},
{
+ "name": "environmentsCanaryIngressUpdate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "EnvironmentsCanaryIngressUpdateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "EnvironmentsCanaryIngressUpdatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "epicAddIssue",
"description": null,
"args": [
@@ -34750,6 +39084,114 @@
"deprecationReason": null
},
{
+ "name": "httpIntegrationCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "HttpIntegrationCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "HttpIntegrationCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "httpIntegrationDestroy",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "HttpIntegrationDestroyInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "HttpIntegrationDestroyPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "httpIntegrationResetToken",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "HttpIntegrationResetTokenInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "HttpIntegrationResetTokenPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "httpIntegrationUpdate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "HttpIntegrationUpdateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "HttpIntegrationUpdatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "issueMove",
"description": null,
"args": [
@@ -35101,6 +39543,33 @@
"deprecationReason": null
},
{
+ "name": "labelCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "LabelCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "LabelCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "markAsSpamSnippet",
"description": null,
"args": [
@@ -35452,6 +39921,141 @@
"deprecationReason": null
},
{
+ "name": "prometheusIntegrationCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "PrometheusIntegrationCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PrometheusIntegrationCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "prometheusIntegrationResetToken",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "PrometheusIntegrationResetTokenInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PrometheusIntegrationResetTokenPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "prometheusIntegrationUpdate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "PrometheusIntegrationUpdateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PrometheusIntegrationUpdatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "promoteToEpic",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "PromoteToEpicInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PromoteToEpicPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "releaseCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "ReleaseCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "ReleaseCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "removeAwardEmoji",
"description": null,
"args": [
@@ -35506,6 +40110,33 @@
"deprecationReason": null
},
{
+ "name": "repositionImageDiffNote",
+ "description": "Repositions a DiffNote on an image (a `Note` where the `position.positionType` is `\"image\"`)",
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "RepositionImageDiffNoteInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "RepositionImageDiffNotePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "revertVulnerabilityToDetected",
"description": null,
"args": [
@@ -35560,6 +40191,114 @@
"deprecationReason": "Use DastOnDemandScanCreate. Deprecated in 13.4"
},
{
+ "name": "terraformStateDelete",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "TerraformStateDeleteInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TerraformStateDeletePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "terraformStateLock",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "TerraformStateLockInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TerraformStateLockPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "terraformStateUnlock",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "TerraformStateUnlockInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TerraformStateUnlockPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "todoCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "TodoCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TodoCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "todoMarkDone",
"description": null,
"args": [
@@ -36822,6 +41561,12 @@
"description": "Most similar to the search query",
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "STORAGE",
+ "description": "Sort by storage size",
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"possibleTypes": null
@@ -36905,7 +41650,17 @@
"description": "Filter by epic ID. Incompatible with epicWildcardId",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "EpicID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "iterationTitle",
+ "description": "Filter by iteration title",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
"ofType": null
},
"defaultValue": null
@@ -37416,6 +42171,24 @@
"deprecationReason": null
},
{
+ "name": "repositionNote",
+ "description": "Indicates the user can perform `reposition_note` on this resource",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "resolveNote",
"description": "Indicates the user can perform `resolve_note` on this resource",
"args": [
@@ -38354,6 +43127,59 @@
"deprecationReason": null
},
{
+ "name": "downstream",
+ "description": "Pipelines this pipeline will trigger",
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PipelineConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "duration",
"description": "Duration of the pipeline in seconds",
"args": [
@@ -38418,6 +43244,105 @@
"deprecationReason": null
},
{
+ "name": "jobs",
+ "description": "Jobs belonging to the pipeline",
+ "args": [
+ {
+ "name": "securityReportTypes",
+ "description": "Filter jobs by the type of security report they produce",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "SecurityReportTypeEnum",
+ "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": "CiJobConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "path",
+ "description": "Relative path to the pipeline's page",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "project",
+ "description": "Project the pipeline belongs to",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Project",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "retryable",
"description": "Specifies if a pipeline can be retried",
"args": [
@@ -38468,6 +43393,20 @@
"deprecationReason": null
},
{
+ "name": "sourceJob",
+ "description": "Job where pipeline was triggered from",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "CiJob",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "stages",
"description": "Stages of the pipeline",
"args": [
@@ -38571,6 +43510,20 @@
"deprecationReason": null
},
{
+ "name": "upstream",
+ "description": "Pipeline that triggered the pipeline",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Pipeline",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "user",
"description": "Pipeline user",
"args": [
@@ -39284,7 +44237,7 @@
},
{
"name": "search",
- "description": "Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.",
+ "description": "Search query for title, description, service, or monitoring_tool.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -39317,7 +44270,7 @@
"args": [
{
"name": "search",
- "description": "Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.",
+ "description": "Search query for title, description, service, or monitoring_tool.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -39388,7 +44341,7 @@
},
{
"name": "search",
- "description": "Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.",
+ "description": "Search query for title, description, service, or monitoring_tool.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -39456,6 +44409,59 @@
"deprecationReason": null
},
{
+ "name": "alertManagementIntegrations",
+ "description": "Integrations which can receive alerts for 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": "AlertManagementIntegrationConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "allowMergeOnSkippedPipeline",
"description": "If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs",
"args": [
@@ -39547,7 +44553,7 @@
"description": "Find a board by its ID",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "BoardID",
"ofType": null
},
"defaultValue": null
@@ -39682,6 +44688,20 @@
"deprecationReason": null
},
{
+ "name": "codeCoverageSummary",
+ "description": "Code coverage summary associated with the project",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "CodeCoverageSummary",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "complianceFrameworks",
"description": "Compliance frameworks associated with the project",
"args": [
@@ -39763,6 +44783,69 @@
"deprecationReason": null
},
{
+ "name": "containerRepositories",
+ "description": "Container repositories of the project",
+ "args": [
+ {
+ "name": "name",
+ "description": "Filter the container repositories by their name",
+ "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": "ContainerRepositoryConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "createdAt",
"description": "Timestamp of the project creation",
"args": [
@@ -39910,6 +44993,33 @@
"deprecationReason": null
},
{
+ "name": "dastSiteValidation",
+ "description": "DAST Site Validation associated with the project",
+ "args": [
+ {
+ "name": "targetUrl",
+ "description": "target URL of the DAST Site Validation",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastSiteValidation",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "description",
"description": "Short description of the project",
"args": [
@@ -40289,7 +45399,7 @@
},
{
"name": "assigneeId",
- "description": "ID of a user assigned to the issues, \"none\" and \"any\" values supported",
+ "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -40418,6 +45528,16 @@
}
},
"defaultValue": null
+ },
+ {
+ "name": "epicId",
+ "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
}
],
"type": {
@@ -40528,7 +45648,7 @@
},
{
"name": "assigneeId",
- "description": "ID of a user assigned to the issues, \"none\" and \"any\" values supported",
+ "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -40733,7 +45853,7 @@
},
{
"name": "assigneeId",
- "description": "ID of a user assigned to the issues, \"none\" and \"any\" values supported",
+ "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -40864,6 +45984,16 @@
"defaultValue": null
},
{
+ "name": "epicId",
+ "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported",
+ "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": {
@@ -42055,6 +47185,16 @@
"description": "Releases of the project",
"args": [
{
+ "name": "sort",
+ "description": "Sort releases by this criteria",
+ "type": {
+ "kind": "ENUM",
+ "name": "ReleaseSort",
+ "ofType": null
+ },
+ "defaultValue": "RELEASED_AT_DESC"
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -42445,7 +47585,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "GitlabErrorTrackingDetailedErrorID",
"ofType": null
}
},
@@ -42604,7 +47744,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "SnippetID",
"ofType": null
}
}
@@ -44448,54 +49588,13 @@
"possibleTypes": null
},
{
- "kind": "ENUM",
- "name": "ProjectSettingEnum",
- "description": "Names of compliance frameworks that can be assigned to a Project",
- "fields": null,
- "inputFields": null,
- "interfaces": null,
- "enumValues": [
- {
- "name": "gdpr",
- "description": null,
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "hipaa",
- "description": null,
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "pci_dss",
- "description": null,
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "soc_2",
- "description": null,
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "sox",
- "description": null,
- "isDeprecated": false,
- "deprecationReason": null
- }
- ],
- "possibleTypes": null
- },
- {
"kind": "OBJECT",
"name": "ProjectStatistics",
"description": null,
"fields": [
{
"name": "buildArtifactsSize",
- "description": "Build artifacts size of the project",
+ "description": "Build artifacts size of the project in bytes",
"args": [
],
@@ -44531,7 +49630,7 @@
},
{
"name": "lfsObjectsSize",
- "description": "Large File Storage (LFS) object size of the project",
+ "description": "Large File Storage (LFS) object size of the project in bytes",
"args": [
],
@@ -44549,7 +49648,7 @@
},
{
"name": "packagesSize",
- "description": "Packages size of the project",
+ "description": "Packages size of the project in bytes",
"args": [
],
@@ -44567,7 +49666,7 @@
},
{
"name": "repositorySize",
- "description": "Repository size of the project",
+ "description": "Repository size of the project in bytes",
"args": [
],
@@ -44585,7 +49684,7 @@
},
{
"name": "snippetsSize",
- "description": "Snippets size of the project",
+ "description": "Snippets size of the project in bytes",
"args": [
],
@@ -44599,7 +49698,7 @@
},
{
"name": "storageSize",
- "description": "Storage size of the project",
+ "description": "Storage size of the project in bytes",
"args": [
],
@@ -44616,8 +49715,22 @@
"deprecationReason": null
},
{
+ "name": "uploadsSize",
+ "description": "Uploads size of the project in bytes",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Float",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "wikiSize",
- "description": "Wiki size of the project",
+ "description": "Wiki size of the project in bytes",
"args": [
],
@@ -44687,11 +49800,542 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "PrometheusIntegrationCreateInput",
+ "description": "Autogenerated input type of PrometheusIntegrationCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "projectPath",
+ "description": "The project to create the integration in",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "active",
+ "description": "Whether the integration is receiving alerts",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "apiUrl",
+ "description": "Endpoint at which prometheus can be queried",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "PrometheusIntegrationCreatePayload",
+ "description": "Autogenerated return type of PrometheusIntegrationCreate",
+ "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": "integration",
+ "description": "The newly created integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "AlertManagementPrometheusIntegration",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "PrometheusIntegrationResetTokenInput",
+ "description": "Autogenerated input type of PrometheusIntegrationResetToken",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "The id of the integration to mutate",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "PrometheusServiceID",
+ "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": "PrometheusIntegrationResetTokenPayload",
+ "description": "Autogenerated return type of PrometheusIntegrationResetToken",
+ "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": "integration",
+ "description": "The newly created integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "AlertManagementPrometheusIntegration",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "PrometheusIntegrationUpdateInput",
+ "description": "Autogenerated input type of PrometheusIntegrationUpdate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "The id of the integration to mutate",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "PrometheusServiceID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "active",
+ "description": "Whether the integration is receiving alerts",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "apiUrl",
+ "description": "Endpoint at which prometheus can be queried",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "PrometheusIntegrationUpdatePayload",
+ "description": "Autogenerated return type of PrometheusIntegrationUpdate",
+ "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": "integration",
+ "description": "The newly created integration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "AlertManagementPrometheusIntegration",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
+ "name": "PrometheusServiceID",
+ "description": "Identifier of PrometheusService",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "PromoteToEpicInput",
+ "description": "Autogenerated input type of PromoteToEpic",
+ "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": "groupPath",
+ "description": "The group the promoted epic will belong to",
+ "type": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "PromoteToEpicPayload",
+ "description": "Autogenerated return type of PromoteToEpic",
+ "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": "epic",
+ "description": "The epic after issue promotion",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Epic",
+ "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": "OBJECT",
"name": "Query",
"description": null,
"fields": [
{
+ "name": "containerRepository",
+ "description": "Find a container repository",
+ "args": [
+ {
+ "name": "id",
+ "description": "The global ID of the container repository",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ContainerRepositoryID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "ContainerRepositoryDetails",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "currentUser",
"description": "Get information about current user",
"args": [
@@ -44724,6 +50368,59 @@
"deprecationReason": null
},
{
+ "name": "devopsAdoptionSegments",
+ "description": "Get configured DevOps adoption segments on the instance",
+ "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": "DevopsAdoptionSegmentConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "echo",
"description": "Text to echo back",
"args": [
@@ -44837,6 +50534,26 @@
"defaultValue": null
},
{
+ "name": "recordedAfter",
+ "description": "Measurement recorded after this date",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "recordedBefore",
+ "description": "Measurement recorded before this date",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -45199,6 +50916,67 @@
"deprecationReason": null
},
{
+ "name": "runnerSetup",
+ "description": "Get runner setup instructions",
+ "args": [
+ {
+ "name": "platform",
+ "description": "Platform to generate the instructions for",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "architecture",
+ "description": "Architecture to generate the instructions for",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "projectId",
+ "description": "Project to register the runner for",
+ "type": {
+ "kind": "SCALAR",
+ "name": "ProjectID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "groupId",
+ "description": "Group to register the runner for",
+ "type": {
+ "kind": "SCALAR",
+ "name": "GroupID",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "RunnerSetup",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "snippets",
"description": "Find Snippets visible to the current user",
"args": [
@@ -45213,7 +50991,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "SnippetID",
"ofType": null
}
}
@@ -45235,7 +51013,7 @@
"description": "The ID of an author",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "UserID",
"ofType": null
},
"defaultValue": null
@@ -45245,7 +51023,7 @@
"description": "The ID of a project",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "ProjectID",
"ofType": null
},
"defaultValue": null
@@ -45328,7 +51106,7 @@
"description": "ID of the User",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "UserID",
"ofType": null
},
"defaultValue": null
@@ -45403,6 +51181,16 @@
"defaultValue": "created_desc"
},
{
+ "name": "search",
+ "description": "Query to search users by name, username, or primary email.",
+ "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": {
@@ -46357,9 +52145,68 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "ReleaseAssetLinkInput",
+ "description": "Fields that are available when modifying a release asset link",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "name",
+ "description": "Name of the asset link",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "url",
+ "description": "URL of the asset link",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "directAssetPath",
+ "description": "Relative path for a direct asset link",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "linkType",
+ "description": "The type of the asset link",
+ "type": {
+ "kind": "ENUM",
+ "name": "ReleaseAssetLinkType",
+ "ofType": null
+ },
+ "defaultValue": "OTHER"
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "ENUM",
"name": "ReleaseAssetLinkType",
- "description": "Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`",
+ "description": "Type of the link: `other`, `runbook`, `image`, `package`",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -46525,6 +52372,35 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "ReleaseAssetsInput",
+ "description": "Fields that are available when modifying release assets",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "links",
+ "description": "A list of asset links to associate to the release",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "ReleaseAssetLinkInput",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "ReleaseConnection",
"description": "The connection type for Release.",
@@ -46610,6 +52486,190 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "ReleaseCreateInput",
+ "description": "Autogenerated input type of ReleaseCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "projectPath",
+ "description": "Full path of the project the release is associated with",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "tagName",
+ "description": "Name of the tag to associate with the release",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "ref",
+ "description": "The commit SHA or branch name to use if creating a new tag",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the release",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "description",
+ "description": "Description (also known as \"release notes\") of the release",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "releasedAt",
+ "description": "The date when the release will be/was ready. Defaults to the current time.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "milestones",
+ "description": "The title of each milestone the release is associated with. GitLab Premium customers can specify group milestones.",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "assets",
+ "description": "Assets associated to the release",
+ "type": {
+ "kind": "INPUT_OBJECT",
+ "name": "ReleaseAssetsInput",
+ "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": "ReleaseCreatePayload",
+ "description": "Autogenerated return type of ReleaseCreate",
+ "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": "release",
+ "description": "The release after mutation",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Release",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "ReleaseEdge",
"description": "An edge in a connection.",
@@ -46845,6 +52905,34 @@
"description": null,
"fields": [
{
+ "name": "closedIssuesUrl",
+ "description": "HTTP URL of the issues page, filtered by this release and `state=closed`",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "closedMergeRequestsUrl",
+ "description": "HTTP URL of the merge request page , filtered by this release and `state=closed`",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "editUrl",
"description": "HTTP URL of the release's edit page",
"args": [
@@ -46859,8 +52947,22 @@
"deprecationReason": null
},
{
- "name": "issuesUrl",
- "description": "HTTP URL of the issues page filtered by this release",
+ "name": "mergedMergeRequestsUrl",
+ "description": "HTTP URL of the merge request page , filtered by this release and `state=merged`",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "openedIssuesUrl",
+ "description": "HTTP URL of the issues page, filtered by this release and `state=open`",
"args": [
],
@@ -46873,8 +52975,8 @@
"deprecationReason": null
},
{
- "name": "mergeRequestsUrl",
- "description": "HTTP URL of the merge request page filtered by this release",
+ "name": "openedMergeRequestsUrl",
+ "description": "HTTP URL of the merge request page, filtered by this release and `state=open`",
"args": [
],
@@ -46909,6 +53011,41 @@
"possibleTypes": null
},
{
+ "kind": "ENUM",
+ "name": "ReleaseSort",
+ "description": "Values for sorting releases",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "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": "RELEASED_AT_DESC",
+ "description": "Released at by descending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "RELEASED_AT_ASC",
+ "description": "Released at by ascending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "ReleaseSource",
"description": "Represents the source code attached to a release in a particular format",
@@ -47266,6 +53403,122 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "RepositionImageDiffNoteInput",
+ "description": "Autogenerated input type of RepositionImageDiffNote",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "The global id of the DiffNote to update",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DiffNoteID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "position",
+ "description": "The position of this note on a diff",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "UpdateDiffImagePositionInput",
+ "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": "RepositionImageDiffNotePayload",
+ "description": "Autogenerated return type of RepositionImageDiffNote",
+ "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": "note",
+ "description": "The note after mutation",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Note",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "Repository",
"description": null,
@@ -48274,6 +54527,24 @@
"deprecationReason": null
},
{
+ "name": "uploadsSize",
+ "description": "The uploads size in bytes",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Float",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "wikiSize",
"description": "The wiki size in bytes",
"args": [
@@ -48820,6 +55091,51 @@
},
{
"kind": "OBJECT",
+ "name": "RunnerSetup",
+ "description": null,
+ "fields": [
+ {
+ "name": "installInstructions",
+ "description": "Instructions for installing the runner on the specified architecture",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "registerInstructions",
+ "description": "Instructions for registering the runner",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "SastCiConfiguration",
"description": "Represents a CI configuration of SAST",
"fields": [
@@ -50231,6 +56547,59 @@
},
{
"kind": "ENUM",
+ "name": "SecurityReportTypeEnum",
+ "description": null,
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "SAST",
+ "description": "SAST scan report",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "DAST",
+ "description": "DAST scan report",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "DEPENDENCY_SCANNING",
+ "description": "DEPENDENCY SCANNING scan report",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "CONTAINER_SCANNING",
+ "description": "CONTAINER SCANNING scan report",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "SECRET_DETECTION",
+ "description": "SECRET DETECTION scan report",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "COVERAGE_FUZZING",
+ "description": "COVERAGE FUZZING scan report",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "API_FUZZING",
+ "description": "API FUZZING scan report",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
"name": "SecurityScannerType",
"description": "The type of the security scanner",
"fields": null,
@@ -51186,7 +57555,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "GitlabErrorTrackingDetailedErrorID",
"ofType": null
}
},
@@ -51213,7 +57582,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "GitlabErrorTrackingDetailedErrorID",
"ofType": null
}
},
@@ -52036,6 +58405,12 @@
"deprecationReason": null
},
{
+ "name": "GITHUB_SERVICE",
+ "description": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "HANGOUTS_CHAT_SERVICE",
"description": null,
"isDeprecated": false,
@@ -52054,6 +58429,12 @@
"deprecationReason": null
},
{
+ "name": "JENKINS_SERVICE",
+ "description": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "JIRA_SERVICE",
"description": null,
"isDeprecated": false,
@@ -52148,18 +58529,6 @@
"description": null,
"isDeprecated": false,
"deprecationReason": null
- },
- {
- "name": "GITHUB_SERVICE",
- "description": null,
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "JENKINS_SERVICE",
- "description": null,
- "isDeprecated": false,
- "deprecationReason": null
}
],
"possibleTypes": null
@@ -52414,7 +58783,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "SnippetID",
"ofType": null
}
},
@@ -53281,6 +59650,16 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "SnippetID",
+ "description": "Identifier of Snippet",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "SnippetPermissions",
"description": null,
@@ -53402,6 +59781,251 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "SnippetRepositoryRegistry",
+ "description": "Represents the Geo sync and verification state of a snippet repository",
+ "fields": [
+ {
+ "name": "createdAt",
+ "description": "Timestamp when the SnippetRepositoryRegistry was created",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the SnippetRepositoryRegistry",
+ "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 SnippetRepositoryRegistry",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lastSyncedAt",
+ "description": "Timestamp of the most recent successful sync of the SnippetRepositoryRegistry",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "retryAt",
+ "description": "Timestamp after which the SnippetRepositoryRegistry 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 SnippetRepositoryRegistry",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "snippetRepositoryId",
+ "description": "ID of the Snippet Repository",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "state",
+ "description": "Sync state of the SnippetRepositoryRegistry",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "RegistryState",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "SnippetRepositoryRegistryConnection",
+ "description": "The connection type for SnippetRepositoryRegistry.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "SnippetRepositoryRegistryEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "SnippetRepositoryRegistry",
+ "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": "SnippetRepositoryRegistryEdge",
+ "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": "SnippetRepositoryRegistry",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "ENUM",
"name": "Sort",
"description": "Common sort values",
@@ -53909,6 +60533,20 @@
"deprecationReason": null
},
{
+ "name": "latestVersion",
+ "description": "The latest version of the Terraform state",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TerraformStateVersion",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "lockedAt",
"description": "Timestamp the Terraform state was locked",
"args": [
@@ -53986,6 +60624,24 @@
"description": "The connection type for TerraformState.",
"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": [
@@ -54048,6 +60704,94 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "TerraformStateDeleteInput",
+ "description": "Autogenerated input type of TerraformStateDelete",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "Global ID of the Terraform state",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "TerraformStateID",
+ "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": "TerraformStateDeletePayload",
+ "description": "Autogenerated return type of TerraformStateDelete",
+ "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": "TerraformStateEdge",
"description": "An edge in a connection.",
@@ -54093,6 +60837,287 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "TerraformStateID",
+ "description": "Identifier of Terraform::State",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "TerraformStateLockInput",
+ "description": "Autogenerated input type of TerraformStateLock",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "Global ID of the Terraform state",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "TerraformStateID",
+ "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": "TerraformStateLockPayload",
+ "description": "Autogenerated return type of TerraformStateLock",
+ "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": "INPUT_OBJECT",
+ "name": "TerraformStateUnlockInput",
+ "description": "Autogenerated input type of TerraformStateUnlock",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "Global ID of the Terraform state",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "TerraformStateID",
+ "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": "TerraformStateUnlockPayload",
+ "description": "Autogenerated return type of TerraformStateUnlock",
+ "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": "TerraformStateVersion",
+ "description": null,
+ "fields": [
+ {
+ "name": "createdAt",
+ "description": "Timestamp the version was created",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "createdByUser",
+ "description": "The user that created this version",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the Terraform state version",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "job",
+ "description": "The job that created this version",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "CiJob",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "updatedAt",
+ "description": "Timestamp the version was updated",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "TerraformStateVersionRegistry",
"description": "Represents the Geo sync and verification state of a terraform state version",
@@ -54564,9 +61589,113 @@
"possibleTypes": null
},
{
- "kind": "INTERFACE",
- "name": "TimeboxBurnupTimeSeriesInterface",
- "description": null,
+ "kind": "OBJECT",
+ "name": "TimeReportStats",
+ "description": "Represents the time report stats for timeboxes",
+ "fields": [
+ {
+ "name": "complete",
+ "description": "Completed issues metrics",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TimeboxMetrics",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "incomplete",
+ "description": "Incomplete issues metrics",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TimeboxMetrics",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "total",
+ "description": "Total issues metrics",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TimeboxMetrics",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "TimeboxMetrics",
+ "description": "Represents measured stats metrics for timeboxes",
+ "fields": [
+ {
+ "name": "count",
+ "description": "The count metric",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "weight",
+ "description": "The weight metric",
+ "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": "TimeboxReport",
+ "description": "Represents a historically accurate report about the timebox",
"fields": [
{
"name": "burnupTimeSeries",
@@ -54589,6 +61718,47 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "stats",
+ "description": "Represents the time report stats for the timebox",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TimeReportStats",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INTERFACE",
+ "name": "TimeboxReportInterface",
+ "description": null,
+ "fields": [
+ {
+ "name": "report",
+ "description": "Historically accurate report about the timebox",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TimeboxReport",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -54652,24 +61822,6 @@
"description": null,
"fields": [
{
- "name": "date",
- "description": "Timestamp of when the time tracked was spent at. Deprecated in 12.10: Use `spentAt`",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "Time",
- "ofType": null
- }
- },
- "isDeprecated": true,
- "deprecationReason": "Use `spentAt`. Deprecated in 12.10"
- },
- {
"name": "issue",
"description": "The issue that logged time was added to",
"args": [
@@ -55155,6 +62307,108 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "TodoCreateInput",
+ "description": "Autogenerated input type of TodoCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "targetId",
+ "description": "The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "TodoableID",
+ "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": "TodoCreatePayload",
+ "description": "Autogenerated return type of TodoCreate",
+ "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": "todo",
+ "description": "The to-do created",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Todo",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "TodoEdge",
"description": "An edge in a connection.",
@@ -55481,7 +62735,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "TodoID",
"ofType": null
}
}
@@ -55640,6 +62894,16 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "TodoableID",
+ "description": "Identifier of Todoable",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
"name": "TodosMarkAllDoneInput",
"description": "Autogenerated input type of TodosMarkAllDone",
@@ -55748,7 +63012,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "TodoID",
"ofType": null
}
}
@@ -56828,7 +64092,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "ListID",
"ofType": null
}
},
@@ -57735,7 +64999,7 @@
"description": "The ID of the parent epic. NULL when removing the association",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "EpicID",
"ofType": null
},
"defaultValue": null
@@ -58270,7 +65534,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "SnippetID",
"ofType": null
}
},
@@ -58576,7 +65840,7 @@
"description": "The global ID of the project the authored merge requests should be in. Incompatible with projectPath.",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "ProjectID",
"ofType": null
},
"defaultValue": null
@@ -58781,7 +66045,7 @@
"description": "The global ID of the project the authored merge requests should be in. Incompatible with projectPath.",
"type": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "ProjectID",
"ofType": null
},
"defaultValue": null
@@ -58874,6 +66138,20 @@
"deprecationReason": null
},
{
+ "name": "groupCount",
+ "description": "Group count for the user. Available only when feature flag `user_group_counts` is enabled",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "groupMemberships",
"description": "Group memberships of the user",
"args": [
@@ -59030,7 +66308,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "SnippetID",
"ofType": null
}
}
@@ -59634,6 +66912,24 @@
"description": null,
"fields": [
{
+ "name": "availability",
+ "description": "User availability status",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "AvailabilityEnum",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "emoji",
"description": "String representation of emoji",
"args": [
@@ -59744,7 +67040,7 @@
{
"kind": "OBJECT",
"name": "VulnerabilitiesCountByDay",
- "description": "Represents the count of vulnerabilities by severity on a particular day",
+ "description": "Represents the count of vulnerabilities by severity on a particular day. This data is retained for 365 days",
"fields": [
{
"name": "critical",
@@ -59901,7 +67197,7 @@
{
"kind": "OBJECT",
"name": "VulnerabilitiesCountByDayAndSeverity",
- "description": "Represents the number of vulnerabilities for a particular severity on a particular day",
+ "description": "Represents the number of vulnerabilities for a particular severity on a particular day. This data is retained for 365 days",
"fields": [
{
"name": "count",
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index dca00fc1286..c46f12bcdcd 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -15,6 +15,8 @@ fields and methods on a model are available via GraphQL.
CAUTION: **Caution:**
Fields that are deprecated are marked with **{warning-solid}**.
+Items (fields, enums, etc) that have been removed according to our [deprecation process](../index.md#deprecation-process) can be found
+in [Removed Items](../removed_items.md).
## Object types
@@ -72,10 +74,12 @@ Describes an alert from the project's Alert Management.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `assignees` | UserConnection | Assignees of the alert |
| `createdAt` | Time | Timestamp the alert was created |
| `description` | String | Description of the alert |
| `details` | JSON | Alert details |
| `detailsUrl` | String! | The URL of the alert detail page |
+| `discussions` | DiscussionConnection! | All discussions on this noteable |
| `endedAt` | Time | Timestamp the alert ended |
| `environment` | Environment | Environment for the alert |
| `eventCount` | Int | Number of events of this alert |
@@ -84,6 +88,7 @@ Describes an alert from the project's Alert Management.
| `issueIid` | ID | Internal ID of the GitLab issue attached to the alert |
| `metricsDashboardUrl` | String | URL for metrics embed for the alert |
| `monitoringTool` | String | Monitoring tool the alert came from |
+| `notes` | NoteConnection! | All notes on this noteable |
| `prometheusAlert` | PrometheusAlert | The alert condition for Prometheus |
| `runbook` | String | Runbook for the alert as defined in alert details |
| `service` | String | Service the alert came from |
@@ -91,6 +96,7 @@ Describes an alert from the project's Alert Management.
| `startedAt` | Time | Timestamp the alert was raised |
| `status` | AlertManagementStatus | Status of the alert |
| `title` | String | Title of the alert |
+| `todos` | TodoConnection | Todos of the current user for the alert |
| `updatedAt` | Time | Timestamp the alert was last updated |
### AlertManagementAlertStatusCountsType
@@ -106,6 +112,34 @@ 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 |
+### AlertManagementHttpIntegration
+
+An endpoint and credentials used to accept alerts for a project.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `active` | Boolean | Whether the endpoint is currently accepting alerts |
+| `apiUrl` | String | URL at which Prometheus metrics can be queried to populate the metrics dashboard |
+| `id` | ID! | ID of the integration |
+| `name` | String | Name of the integration |
+| `token` | String | Token used to authenticate alert notification requests |
+| `type` | AlertManagementIntegrationType! | Type of integration |
+| `url` | String | Endpoint which accepts alert notifications |
+
+### AlertManagementPrometheusIntegration
+
+An endpoint and credentials used to accept Prometheus alerts for a project.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `active` | Boolean | Whether the endpoint is currently accepting alerts |
+| `apiUrl` | String | URL at which Prometheus metrics can be queried to populate the metrics dashboard |
+| `id` | ID! | ID of the integration |
+| `name` | String | Name of the integration |
+| `token` | String | Token used to authenticate alert notification requests |
+| `type` | AlertManagementIntegrationType! | Type of integration |
+| `url` | String | Endpoint which accepts alert notifications |
+
### AlertSetAssigneesPayload
Autogenerated return type of AlertSetAssignees.
@@ -203,9 +237,12 @@ Represents a project or group board.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `assignee` | User | The board assignee. |
+| `epics` | BoardEpicConnection | Epics associated with board issues. |
| `hideBacklogList` | Boolean | Whether or not backlog list is hidden. |
| `hideClosedList` | Boolean | Whether or not closed list is hidden. |
| `id` | ID! | ID (global ID) of the board |
+| `labels` | LabelConnection | Labels of the board |
+| `lists` | BoardListConnection | Lists of the board |
| `milestone` | Milestone | The board milestone. |
| `name` | String | Name of the board |
| `weight` | Int | Weight of the board. |
@@ -217,12 +254,15 @@ Represents an epic on an issue board.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `author` | User! | Author of the epic |
+| `children` | EpicConnection | Children (sub-epics) of the epic |
| `closedAt` | Time | Timestamp of when the epic was closed |
| `confidential` | Boolean | Indicates if the epic is confidential |
| `createdAt` | Time | Timestamp of when the epic was created |
+| `currentUserTodos` | TodoConnection! | Todos for the current user |
| `descendantCounts` | EpicDescendantCount | Number of open and closed descendant epics and issues |
| `descendantWeightSum` | EpicDescendantWeights | Total weight of open and closed issues in the epic and its descendants |
| `description` | String | Description of the epic |
+| `discussions` | DiscussionConnection! | All discussions on this noteable |
| `downvotes` | Int! | Number of downvotes the epic has received |
| `dueDate` | Time | Due date of the epic |
| `dueDateFixed` | Time | Fixed due date of the epic |
@@ -235,7 +275,11 @@ Represents an epic on an issue board.
| `healthStatus` | EpicHealthStatus | Current health status of the epic |
| `id` | ID! | ID of the epic |
| `iid` | ID! | Internal ID of the epic |
+| `issues` | EpicIssueConnection | A list of issues associated with the epic |
+| `labels` | LabelConnection | Labels assigned to the epic |
+| `notes` | NoteConnection! | All notes on this noteable |
| `parent` | Epic | Parent epic of the epic |
+| `participants` | UserConnection | List of participants for the epic |
| `reference` | String! | Internal reference of the epic. Returned in shortened format by default |
| `relationPath` | String | URI path of the epic-issue relationship |
| `relativePosition` | Int | The relative position of the epic in the epic tree |
@@ -248,6 +292,8 @@ Represents an epic on an issue board.
| `title` | String | Title of the epic |
| `updatedAt` | Time | Timestamp of when the epic was updated |
| `upvotes` | Int! | Number of upvotes the epic has received |
+| `userDiscussionsCount` | Int! | Number of user discussions in the epic |
+| `userNotesCount` | Int! | Number of user notes of the epic |
| `userPermissions` | EpicPermissions! | Permissions for the current user on the resource |
| `userPreferences` | BoardEpicUserPreferences | User preferences for the epic on the issue board |
| `webPath` | String! | Web path of the epic |
@@ -270,6 +316,7 @@ Represents a list for an issue board.
| `assignee` | User | Assignee in the list |
| `collapsed` | Boolean | Indicates if list is collapsed for this user |
| `id` | ID! | ID (global ID) of the list |
+| `issues` | IssueConnection | Board issues |
| `issuesCount` | Int | Count of issues in the list |
| `label` | Label | Label of the list |
| `limitMetric` | ListLimitMetric | The current limit metric for the list |
@@ -325,6 +372,7 @@ Represents the total number of issues and their weights for a particular day.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `detailedStatus` | DetailedStatus | Detailed status of the group |
+| `jobs` | CiJobConnection | Jobs in group |
| `name` | String | Name of the job group |
| `size` | Int | Size of the group |
@@ -334,6 +382,8 @@ Represents the total number of issues and their weights for a particular day.
| ----- | ---- | ----------- |
| `detailedStatus` | DetailedStatus | Detailed status of the job |
| `name` | String | Name of the job |
+| `needs` | CiJobConnection | Builds that must complete before the jobs run |
+| `pipeline` | Pipeline! | Pipeline the job belongs to |
| `scheduledAt` | Time | Schedule for the build |
### CiStage
@@ -341,6 +391,7 @@ Represents the total number of issues and their weights for a particular day.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `detailedStatus` | DetailedStatus | Detailed status of the stage |
+| `groups` | CiGroupConnection | Group of jobs for the stage |
| `name` | String | Name of the stage |
### ClusterAgent
@@ -351,6 +402,7 @@ Represents the total number of issues and their weights for a particular day.
| `id` | ID! | ID of the cluster agent |
| `name` | String | Name of the cluster agent |
| `project` | Project | The project this cluster agent is associated with |
+| `tokens` | ClusterAgentTokenConnection | Tokens associated with the cluster agent |
| `updatedAt` | Time | Timestamp the cluster agent was updated |
### ClusterAgentDeletePayload
@@ -390,6 +442,27 @@ Autogenerated return type of ClusterAgentTokenDelete.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+### CodeCoverageActivity
+
+Represents the code coverage activity for a group.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `averageCoverage` | Float | Average percentage of the different code coverage results available for the group. |
+| `coverageCount` | Int | Number of different code coverage results available for the group. |
+| `date` | Date! | Date when the code coverage was created. |
+| `projectCount` | Int | Number of projects with code coverage results for the group. |
+
+### CodeCoverageSummary
+
+Represents the code coverage summary for a project.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `averageCoverage` | Float | Average percentage of the different code coverage results available for the project. |
+| `coverageCount` | Int | Number of different code coverage results available. |
+| `lastUpdatedOn` | Date | Latest date when the code coverage was created for the project. |
+
### Commit
| Field | Type | Description |
@@ -401,8 +474,8 @@ Autogenerated return type of ClusterAgentTokenDelete.
| `description` | String | Description of the commit message |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `id` | ID! | ID (global ID) of the commit |
-| `latestPipeline` **{warning-solid}** | Pipeline | **Deprecated:** Use `pipelines`. Deprecated in 12.5 |
| `message` | String | Raw commit message |
+| `pipelines` | PipelineConnection | Pipelines of the commit ordered latest first |
| `sha` | String! | SHA1 ID of the commit |
| `signatureHtml` | String | Rendered HTML of the commit signature |
| `title` | String | Title of the commit message |
@@ -426,7 +499,7 @@ Represents a ComplianceFramework associated with a Project.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `name` | ProjectSettingEnum! | Name of the compliance framework |
+| `name` | String! | Name of the compliance framework |
### ConfigureSastPayload
@@ -455,6 +528,59 @@ 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 |
+### ContainerRepository
+
+A container repository.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `canDelete` | Boolean! | Can the current user delete the container repository. |
+| `createdAt` | Time! | Timestamp when the container repository was created. |
+| `expirationPolicyCleanupStatus` | ContainerRepositoryCleanupStatus | The tags cleanup status for the container repository. |
+| `expirationPolicyStartedAt` | Time | Timestamp when the cleanup done by the expiration policy was started on the container repository. |
+| `id` | ID! | ID of the container repository. |
+| `location` | String! | URL of the container repository. |
+| `name` | String! | Name of the container repository. |
+| `path` | String! | Path of the container repository. |
+| `status` | ContainerRepositoryStatus | Status of the container repository. |
+| `tagsCount` | Int! | Number of tags associated with this image. |
+| `updatedAt` | Time! | Timestamp when the container repository was updated. |
+
+### ContainerRepositoryDetails
+
+Details of a container repository.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `canDelete` | Boolean! | Can the current user delete the container repository. |
+| `createdAt` | Time! | Timestamp when the container repository was created. |
+| `expirationPolicyCleanupStatus` | ContainerRepositoryCleanupStatus | The tags cleanup status for the container repository. |
+| `expirationPolicyStartedAt` | Time | Timestamp when the cleanup done by the expiration policy was started on the container repository. |
+| `id` | ID! | ID of the container repository. |
+| `location` | String! | URL of the container repository. |
+| `name` | String! | Name of the container repository. |
+| `path` | String! | Path of the container repository. |
+| `status` | ContainerRepositoryStatus | Status of the container repository. |
+| `tags` | ContainerRepositoryTagConnection | Tags of the container repository |
+| `tagsCount` | Int! | Number of tags associated with this image. |
+| `updatedAt` | Time! | Timestamp when the container repository was updated. |
+
+### ContainerRepositoryTag
+
+A tag from a container repository.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `canDelete` | Boolean! | Can the current user delete this tag. |
+| `createdAt` | Time! | Timestamp when the tag was created. |
+| `digest` | String! | Digest of the tag. |
+| `location` | String! | URL of the tag. |
+| `name` | String! | Name of the tag. |
+| `path` | String! | Path of the tag. |
+| `revision` | String! | Revision of the tag. |
+| `shortRevision` | String! | Short revision of the tag. |
+| `totalSize` | Int! | The size of the tag. |
+
### CreateAlertIssuePayload
Autogenerated return type of CreateAlertIssue.
@@ -507,6 +633,16 @@ Autogenerated return type of CreateClusterAgent.
| `clusterAgent` | ClusterAgent | Cluster agent created after mutation |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+### CreateCustomEmojiPayload
+
+Autogenerated return type of CreateCustomEmoji.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `customEmoji` | CustomEmoji | The new custom emoji |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
### CreateDiffNotePayload
Autogenerated return type of CreateDiffNote.
@@ -598,6 +734,17 @@ Autogenerated return type of CreateTestCase.
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `testCase` | Issue | The test case created |
+### CustomEmoji
+
+A custom emoji uploaded by user.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `external` | Boolean! | Whether the emoji is an external link |
+| `id` | CustomEmojiID! | The ID of the emoji |
+| `name` | String! | The name of the emoji |
+| `url` | String! | The link to file of the emoji |
+
### DastOnDemandScanCreatePayload
Autogenerated return type of DastOnDemandScanCreate.
@@ -615,8 +762,8 @@ Represents a 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 |
+| `globalId` **{warning-solid}** | DastScannerProfileID! | **Deprecated:** Use `id`. Deprecated in 13.6 |
+| `id` | DastScannerProfileID! | ID of the DAST scanner profile |
| `profileName` | String | Name of the DAST scanner profile |
| `scanType` | DastScanTypeEnum | Indicates the type of DAST scan that will run. Either a Passive Scan or an Active Scan. |
| `showDebugMessages` | Boolean! | Indicates if debug messages should be included in DAST console output. True to include the debug messages. |
@@ -632,8 +779,8 @@ Autogenerated return type of DastScannerProfileCreate.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `globalId` | DastScannerProfileID | ID of the scanner profile. |
-| `id` **{warning-solid}** | ID | **Deprecated:** Use `global_id`. Deprecated in 13.4 |
+| `globalId` **{warning-solid}** | DastScannerProfileID | **Deprecated:** Use `id`. Deprecated in 13.6 |
+| `id` | DastScannerProfileID | ID of the scanner profile. |
### DastScannerProfileDeletePayload
@@ -716,6 +863,26 @@ Autogenerated return type of DastSiteTokenCreate.
| `status` | DastSiteProfileValidationStatusEnum | The current validation status of the target. |
| `token` | String | Token string. |
+### DastSiteValidation
+
+Represents a DAST Site Validation.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `id` | DastSiteValidationID! | ID of the site validation |
+| `status` | DastSiteProfileValidationStatusEnum! | The status of the validation |
+
+### DastSiteValidationCreatePayload
+
+Autogenerated return type of DastSiteValidationCreate.
+
+| 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` | DastSiteValidationID | ID of the site validation. |
+| `status` | DastSiteProfileValidationStatusEnum | The current validation status. |
+
### DeleteAnnotationPayload
Autogenerated return type of DeleteAnnotation.
@@ -741,7 +908,9 @@ A single design.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `currentUserTodos` | TodoConnection! | Todos for the current user |
| `diffRefs` | DiffRefs! | The diff refs for this design |
+| `discussions` | DiscussionConnection! | All discussions on this noteable |
| `event` | DesignVersionEvent! | How this design was changed in the current version |
| `filename` | String! | The filename of the design |
| `fullPath` | String! | The full path to the design file |
@@ -749,8 +918,10 @@ A single design.
| `image` | String! | The URL of the full-sized image |
| `imageV432x230` | String | The URL of the design resized to fit within the bounds of 432x230. This will be `null` if the image has not been generated |
| `issue` | Issue! | The issue the design belongs to |
+| `notes` | NoteConnection! | All notes on this noteable |
| `notesCount` | Int! | The total count of user-created notes for this design |
| `project` | Project! | The project the design belongs to |
+| `versions` | DesignVersionConnection! | All versions related to this design ordered newest first |
### DesignAtVersion
@@ -780,9 +951,11 @@ A collection of designs.
| `copyState` | DesignCollectionCopyState | Copy state of the design collection |
| `design` | Design | Find a specific design |
| `designAtVersion` | DesignAtVersion | Find a design as of a version |
+| `designs` | DesignConnection! | All designs for the design collection |
| `issue` | Issue! | Issue associated with the design collection |
| `project` | Project! | Project associated with the design collection |
| `version` | DesignVersion | A specific version |
+| `versions` | DesignVersionConnection! | All versions related to all designs, ordered newest first |
### DesignManagement
@@ -829,6 +1002,8 @@ A specific version in which designs were added, modified or deleted.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `designAtVersion` | DesignAtVersion! | A particular design as of this version, provided it is visible at this version |
+| `designs` | DesignConnection! | All designs that were changed in the version |
+| `designsAtVersion` | DesignAtVersionConnection! | All designs that are visible at this version, as of this version |
| `id` | ID! | ID of the design version |
| `sha` | ID! | SHA of the design version |
@@ -852,6 +1027,16 @@ Autogenerated return type of DestroyBoard.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+### DestroyContainerRepositoryPayload
+
+Autogenerated return type of DestroyContainerRepository.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `containerRepository` | ContainerRepository! | The container repository policy after scheduling the deletion. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
### DestroyNotePayload
Autogenerated return type of DestroyNote.
@@ -886,6 +1071,16 @@ Autogenerated return type of DestroySnippet.
| `text` | String | Text of the status |
| `tooltip` | String | Tooltip associated with the status |
+### DevopsAdoptionSegment
+
+Segment.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `groups` | GroupConnection | Assigned groups |
+| `id` | ID! | ID of the segment |
+| `name` | String! | Name of the segment |
+
### DiffPosition
| Field | Type | Description |
@@ -937,6 +1132,7 @@ Aggregated summary of changes.
| ----- | ---- | ----------- |
| `createdAt` | Time! | Timestamp of the discussion's creation |
| `id` | ID! | ID of this discussion |
+| `notes` | NoteConnection! | All notes in the discussion |
| `replyId` | ID! | ID used to reply to this discussion |
| `resolvable` | Boolean! | Indicates if the object can be resolved |
| `resolved` | Boolean! | Indicates if the object is resolved |
@@ -973,9 +1169,18 @@ Describes where code is deployed for a project.
| `latestOpenedMostSevereAlert` | AlertManagementAlert | The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned |
| `metricsDashboard` | MetricsDashboard | Metrics dashboard schema for the environment |
| `name` | String! | Human-readable name of the environment |
-| `path` | String | The path to the environment. Will always return null if `expose_environment_path_in_alert_details` feature flag is disabled |
+| `path` | String! | The path to the environment. |
| `state` | String! | State of the environment, for example: available/stopped |
+### EnvironmentsCanaryIngressUpdatePayload
+
+Autogenerated return type of EnvironmentsCanaryIngressUpdate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
### Epic
Represents an epic.
@@ -983,12 +1188,15 @@ Represents an epic.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `author` | User! | Author of the epic |
+| `children` | EpicConnection | Children (sub-epics) of the epic |
| `closedAt` | Time | Timestamp of when the epic was closed |
| `confidential` | Boolean | Indicates if the epic is confidential |
| `createdAt` | Time | Timestamp of when the epic was created |
+| `currentUserTodos` | TodoConnection! | Todos for the current user |
| `descendantCounts` | EpicDescendantCount | Number of open and closed descendant epics and issues |
| `descendantWeightSum` | EpicDescendantWeights | Total weight of open and closed issues in the epic and its descendants |
| `description` | String | Description of the epic |
+| `discussions` | DiscussionConnection! | All discussions on this noteable |
| `downvotes` | Int! | Number of downvotes the epic has received |
| `dueDate` | Time | Due date of the epic |
| `dueDateFixed` | Time | Fixed due date of the epic |
@@ -1001,7 +1209,11 @@ Represents an epic.
| `healthStatus` | EpicHealthStatus | Current health status of the epic |
| `id` | ID! | ID of the epic |
| `iid` | ID! | Internal ID of the epic |
+| `issues` | EpicIssueConnection | A list of issues associated with the epic |
+| `labels` | LabelConnection | Labels assigned to the epic |
+| `notes` | NoteConnection! | All notes on this noteable |
| `parent` | Epic | Parent epic of the epic |
+| `participants` | UserConnection | List of participants for the epic |
| `reference` | String! | Internal reference of the epic. Returned in shortened format by default |
| `relationPath` | String | URI path of the epic-issue relationship |
| `relativePosition` | Int | The relative position of the epic in the epic tree |
@@ -1014,6 +1226,8 @@ Represents an epic.
| `title` | String | Title of the epic |
| `updatedAt` | Time | Timestamp of when the epic was updated |
| `upvotes` | Int! | Number of upvotes the epic has received |
+| `userDiscussionsCount` | Int! | Number of user discussions in the epic |
+| `userNotesCount` | Int! | Number of user notes of the epic |
| `userPermissions` | EpicPermissions! | Permissions for the current user on the resource |
| `webPath` | String! | Web path of the epic |
| `webUrl` | String! | Web URL of the epic |
@@ -1066,25 +1280,36 @@ Relationship between an epic and an issue.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `alertManagementAlert` | AlertManagementAlert | Alert associated to this issue |
+| `assignees` | UserConnection | Assignees of the issue |
| `author` | User! | User that created the issue |
| `blocked` | Boolean! | Indicates the issue is blocked |
+| `blockedByCount` | Int | Count of issues blocking this issue |
| `closedAt` | Time | Timestamp of when the issue was closed |
| `confidential` | Boolean! | Indicates the issue is confidential |
| `createdAt` | Time! | Timestamp of when the issue was created |
+| `currentUserTodos` | TodoConnection! | Todos for the current user |
| `description` | String | Description of the issue |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `designCollection` | DesignCollection | Collection of design images associated with this issue |
-| `designs` **{warning-solid}** | DesignCollection | **Deprecated:** Use `designCollection`. Deprecated in 12.2 |
| `discussionLocked` | Boolean! | Indicates discussion is locked on the issue |
+| `discussions` | DiscussionConnection! | All discussions on this noteable |
| `downvotes` | Int! | Number of downvotes the issue has received |
| `dueDate` | Time | Due date of the issue |
+| `emailsDisabled` | Boolean! | Indicates if a project has email notifications disabled: `true` if email notifications are disabled |
| `epic` | Epic | Epic to which this issue belongs |
| `epicIssueId` | ID! | ID of the epic-issue relation |
| `healthStatus` | HealthStatus | Current health status. Returns null if `save_issuable_health_status` feature flag is disabled. |
+| `humanTimeEstimate` | String | Human-readable time estimate of the issue |
+| `humanTotalTimeSpent` | String | Human-readable total time reported as spent on the issue |
| `id` | ID | Global ID of the epic-issue relation |
| `iid` | ID! | Internal ID of the issue |
| `iteration` | Iteration | Iteration of the issue |
+| `labels` | LabelConnection | Labels of the issue |
| `milestone` | Milestone | Milestone of the issue |
+| `moved` | Boolean | Indicates if issue got moved from other project |
+| `movedTo` | Issue | Updated Issue after it got moved to another project |
+| `notes` | NoteConnection! | All notes on this noteable |
+| `participants` | UserConnection | List of participants in the issue |
| `reference` | String! | Internal reference of the issue. Returned in shortened format by default |
| `relationPath` | String | URI path of the epic-issue relation |
| `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards) |
@@ -1100,7 +1325,9 @@ Relationship between an epic and an issue.
| `totalTimeSpent` | Int! | Total time reported as spent on the issue |
| `type` | IssueType | Type of the issue |
| `updatedAt` | Time! | Timestamp of when the issue was last updated |
+| `updatedBy` | User | User that last updated the issue |
| `upvotes` | Int! | Number of upvotes the issue has received |
+| `userDiscussionsCount` | Int! | Number of user discussions in the issue |
| `userNotesCount` | Int! | Number of user notes of the issue |
| `userPermissions` | IssuePermissions! | Permissions for the current user on the resource |
| `webPath` | String! | Web path of the issue |
@@ -1150,13 +1377,18 @@ Autogenerated return type of EpicTreeReorder.
| `filesMaxCapacity` | Int | The maximum concurrency of LFS/attachment backfill for this secondary node |
| `id` | ID! | ID of this GeoNode |
| `internalUrl` | String | The URL defined on the primary node that secondary nodes should use to contact it |
+| `mergeRequestDiffRegistries` | MergeRequestDiffRegistryConnection | Find merge request diff registries on this Geo node |
| `minimumReverificationInterval` | Int | The interval (in days) in which the repository verification is valid. Once expired, it will be reverified |
| `name` | String | The unique identifier for this Geo node |
+| `packageFileRegistries` | PackageFileRegistryConnection | Package file registries of the GeoNode |
| `primary` | Boolean | Indicates whether this Geo node is the primary |
| `reposMaxCapacity` | Int | The maximum concurrency of repository backfill for this secondary node |
+| `selectiveSyncNamespaces` | NamespaceConnection | The namespaces that should be synced, if `selective_sync_type` == `namespaces` |
| `selectiveSyncShards` | String! => Array | The repository storages whose projects should be synced, if `selective_sync_type` == `shards` |
| `selectiveSyncType` | String | Indicates if syncing is limited to only specific groups, or shards |
+| `snippetRepositoryRegistries` | SnippetRepositoryRegistryConnection | Find snippet repository registries on this Geo node. Available only when feature flag `geo_snippet_repository_replication` is enabled |
| `syncObjectStorage` | Boolean | Indicates if this secondary node will replicate blobs in Object Storage |
+| `terraformStateVersionRegistries` | TerraformStateVersionRegistryConnection | Find terraform state version registries on this Geo node |
| `url` | String | The user-facing URL for this Geo node |
| `verificationMaxCapacity` | Int | The maximum concurrency of repository verification for this secondary node |
@@ -1168,7 +1400,6 @@ Autogenerated return type of EpicTreeReorder.
| `enabled` | Boolean! | Indicates whether Grafana integration is enabled |
| `grafanaUrl` | String! | URL for the Grafana host for the Grafana integration |
| `id` | ID! | Internal ID of the Grafana integration |
-| `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
@@ -1180,38 +1411,56 @@ Autogenerated return type of EpicTreeReorder.
| `autoDevopsEnabled` | Boolean | Indicates whether Auto DevOps is enabled for all projects within this group |
| `avatarUrl` | String | Avatar URL of the group |
| `board` | Board | A single board of the group |
+| `boards` | BoardConnection | Boards of the group |
+| `codeCoverageActivities` | CodeCoverageActivityConnection | Represents the code coverage activity for this group. Available only when feature flag `group_coverage_data_report_graph` is enabled |
+| `containerRepositories` | ContainerRepositoryConnection | Container repositories of the project |
| `containsLockedProjects` | Boolean! | Includes at least one project where the repository size exceeds the limit |
+| `customEmoji` | CustomEmojiConnection | Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled |
| `description` | String | Description of the namespace |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `emailsDisabled` | Boolean | Indicates if a group has email notifications disabled |
| `epic` | Epic | Find a single epic |
+| `epics` | EpicConnection | Find epics |
| `epicsEnabled` | Boolean | Indicates if Epics are enabled for namespace |
| `fullName` | String! | Full name of the namespace |
| `fullPath` | ID! | Full path of the namespace |
+| `groupMembers` | GroupMemberConnection | A membership of a user within this group |
| `groupTimelogsEnabled` | Boolean | Indicates if Group timelogs are enabled for namespace |
| `id` | ID! | ID of the namespace |
| `isTemporaryStorageIncreaseEnabled` | Boolean! | Status of the temporary storage increase |
+| `issues` | IssueConnection | Issues for projects in this group |
+| `iterations` | IterationConnection | Find iterations |
| `label` | Label | A label available on this group |
+| `labels` | LabelConnection | Labels available on this group |
| `lfsEnabled` | Boolean | Indicates if Large File Storage (LFS) is enabled for namespace |
| `mentionsDisabled` | Boolean | Indicates if a group is disabled from getting mentioned |
+| `mergeRequests` | MergeRequestConnection | Merge requests for projects in this group |
+| `milestones` | MilestoneConnection | Milestones of the group |
| `name` | String! | Name of the namespace |
| `parent` | Group | Parent group |
| `path` | String! | Path of the namespace |
| `projectCreationLevel` | String | The permission level required to create projects in the group |
+| `projects` | ProjectConnection! | Projects within this namespace |
| `repositorySizeExcessProjectCount` | Int! | Number of projects in the root namespace where the repository size exceeds the limit |
| `requestAccessEnabled` | Boolean | Indicates if users can request access to namespace |
| `requireTwoFactorAuthentication` | Boolean | Indicates if all users in this group are required to set up two-factor authentication |
| `rootStorageStatistics` | RootStorageStatistics | Aggregated storage statistics of the namespace. Only available for root namespaces |
| `shareWithGroupLock` | Boolean | Indicates if sharing a project with another group within this group is prevented |
+| `stats` | GroupStats | Group statistics |
| `storageSizeLimit` | Float | Total storage limit of the root namespace in bytes |
| `subgroupCreationLevel` | String | The permission level required to create subgroups within the group |
| `temporaryStorageIncreaseEndsOn` | Time | Date until the temporary storage increase is active |
+| `timelogs` | TimelogConnection! | Time logged in issues by group members |
| `totalRepositorySize` | Float | Total repository size of all projects in the root namespace in bytes |
| `totalRepositorySizeExcess` | Float | Total excess repository size of all projects in the root namespace in bytes |
| `twoFactorGracePeriod` | Int | Time before two-factor authentication is enforced |
| `userPermissions` | GroupPermissions! | Permissions for the current user on the resource |
| `visibility` | String | Visibility of the namespace |
+| `vulnerabilities` | VulnerabilityConnection | Vulnerabilities reported on the projects in the group and its subgroups |
+| `vulnerabilitiesCountByDay` | VulnerabilitiesCountByDayConnection | Number of vulnerabilities per day for the projects in the group and its subgroups |
+| `vulnerabilitiesCountByDayAndSeverity` **{warning-solid}** | VulnerabilitiesCountByDayAndSeverityConnection | **Deprecated:** Use `vulnerabilitiesCountByDay`. Deprecated in 13.3 |
| `vulnerabilityGrades` | VulnerableProjectsByGrade! => Array | Represents vulnerable project counts for each grade |
+| `vulnerabilityScanners` | VulnerabilityScannerConnection | Vulnerability scanners reported on the project vulnerabilties of the group and its subgroups |
| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each vulnerability severity in the group and its subgroups |
| `webUrl` | String! | Web URL of the group |
@@ -1237,11 +1486,70 @@ Represents a Group Membership.
| ----- | ---- | ----------- |
| `readGroup` | Boolean! | Indicates the user can perform `read_group` on this resource |
+### GroupReleaseStats
+
+Contains release-related statistics about a group.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `releasesCount` | Int | Total number of releases in all descendant projects of the group. Will always return `null` if `group_level_release_statistics` feature flag is disabled |
+| `releasesPercentage` | Int | Percentage of the group's descendant projects that have at least one release. Will always return `null` if `group_level_release_statistics` feature flag is disabled |
+
+### GroupStats
+
+Contains statistics about a group.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `releaseStats` | GroupReleaseStats | Statistics related to releases within the group |
+
+### HttpIntegrationCreatePayload
+
+Autogenerated return type of HttpIntegrationCreate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `integration` | AlertManagementHttpIntegration | The HTTP integration |
+
+### HttpIntegrationDestroyPayload
+
+Autogenerated return type of HttpIntegrationDestroy.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `integration` | AlertManagementHttpIntegration | The HTTP integration |
+
+### HttpIntegrationResetTokenPayload
+
+Autogenerated return type of HttpIntegrationResetToken.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `integration` | AlertManagementHttpIntegration | The HTTP integration |
+
+### HttpIntegrationUpdatePayload
+
+Autogenerated return type of HttpIntegrationUpdate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `integration` | AlertManagementHttpIntegration | The HTTP integration |
+
### InstanceSecurityDashboard
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `projects` | ProjectConnection! | Projects selected in Instance Security Dashboard |
| `vulnerabilityGrades` | VulnerableProjectsByGrade! => Array | Represents vulnerable project counts for each grade |
+| `vulnerabilityScanners` | VulnerabilityScannerConnection | Vulnerability scanners reported on the vulnerabilties from projects selected in Instance Security Dashboard |
| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each vulnerability severity from projects selected in Instance Security Dashboard |
### InstanceStatisticsMeasurement
@@ -1259,24 +1567,35 @@ Represents a recorded measurement (object count) for the Admins.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `alertManagementAlert` | AlertManagementAlert | Alert associated to this issue |
+| `assignees` | UserConnection | Assignees of the issue |
| `author` | User! | User that created the issue |
| `blocked` | Boolean! | Indicates the issue is blocked |
+| `blockedByCount` | Int | Count of issues blocking this issue |
| `closedAt` | Time | Timestamp of when the issue was closed |
| `confidential` | Boolean! | Indicates the issue is confidential |
| `createdAt` | Time! | Timestamp of when the issue was created |
+| `currentUserTodos` | TodoConnection! | Todos for the current user |
| `description` | String | Description of the issue |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `designCollection` | DesignCollection | Collection of design images associated with this issue |
-| `designs` **{warning-solid}** | DesignCollection | **Deprecated:** Use `designCollection`. Deprecated in 12.2 |
| `discussionLocked` | Boolean! | Indicates discussion is locked on the issue |
+| `discussions` | DiscussionConnection! | All discussions on this noteable |
| `downvotes` | Int! | Number of downvotes the issue has received |
| `dueDate` | Time | Due date of the issue |
+| `emailsDisabled` | Boolean! | Indicates if a project has email notifications disabled: `true` if email notifications are disabled |
| `epic` | Epic | Epic to which this issue belongs |
| `healthStatus` | HealthStatus | Current health status. Returns null if `save_issuable_health_status` feature flag is disabled. |
+| `humanTimeEstimate` | String | Human-readable time estimate of the issue |
+| `humanTotalTimeSpent` | String | Human-readable total time reported as spent on the issue |
| `id` | ID! | ID of the issue |
| `iid` | ID! | Internal ID of the issue |
| `iteration` | Iteration | Iteration of the issue |
+| `labels` | LabelConnection | Labels of the issue |
| `milestone` | Milestone | Milestone of the issue |
+| `moved` | Boolean | Indicates if issue got moved from other project |
+| `movedTo` | Issue | Updated Issue after it got moved to another project |
+| `notes` | NoteConnection! | All notes on this noteable |
+| `participants` | UserConnection | List of participants in the issue |
| `reference` | String! | Internal reference of the issue. Returned in shortened format by default |
| `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards) |
| `severity` | IssuableSeverity | Severity level of the incident |
@@ -1291,7 +1610,9 @@ Represents a recorded measurement (object count) for the Admins.
| `totalTimeSpent` | Int! | Total time reported as spent on the issue |
| `type` | IssueType | Type of the issue |
| `updatedAt` | Time! | Timestamp of when the issue was last updated |
+| `updatedBy` | User | User that last updated the issue |
| `upvotes` | Int! | Number of upvotes the issue has received |
+| `userDiscussionsCount` | Int! | Number of user discussions in the issue |
| `userNotesCount` | Int! | Number of user notes of the issue |
| `userPermissions` | IssuePermissions! | Permissions for the current user on the resource |
| `webPath` | String! | Web path of the issue |
@@ -1439,13 +1760,13 @@ Represents an iteration object.
| 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` |
| `dueDate` | Time | Timestamp of the iteration due date |
| `id` | ID! | ID of the iteration |
| `iid` | ID! | Internal ID of the iteration |
+| `report` | TimeboxReport | Historically accurate report about the timebox |
| `scopedPath` | String | Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts |
| `scopedUrl` | String | Web URL of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts |
| `startDate` | Time | Timestamp of the iteration start date |
@@ -1500,6 +1821,7 @@ Autogenerated return type of JiraImportUsers.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `active` | Boolean | Indicates if the service is active |
+| `projects` | JiraProjectConnection | List of all Jira projects fetched through Jira REST API |
| `type` | String | Class name of the service |
### JiraUser
@@ -1524,6 +1846,16 @@ Autogenerated return type of JiraImportUsers.
| `textColor` | String! | Text color of the label |
| `title` | String! | Content of the label |
+### LabelCreatePayload
+
+Autogenerated return type of LabelCreate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `label` | Label | The label after mutation |
+
### MarkAsSpamSnippetPayload
Autogenerated return type of MarkAsSpamSnippet.
@@ -1542,11 +1874,14 @@ Autogenerated return type of MarkAsSpamSnippet.
| `approvalsLeft` | Int | Number of approvals left |
| `approvalsRequired` | Int | Number of approvals required |
| `approved` | Boolean! | Indicates if the merge request has all the required approvals. Returns true if no required approvals are configured. |
+| `approvedBy` | UserConnection | Users who approved the merge request |
+| `assignees` | UserConnection | Assignees of the merge request |
| `author` | User | User who created this merge request |
| `autoMergeEnabled` | Boolean! | Indicates if auto merge is enabled for the merge request |
| `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 |
+| `currentUserTodos` | TodoConnection! | Todos for the current user |
| `defaultMergeCommitMessage` | String | Default merge commit message of the merge request |
| `description` | String | Description of the merge request (Markdown rendered as HTML for caching) |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
@@ -1555,13 +1890,14 @@ Autogenerated return type of MarkAsSpamSnippet.
| `diffStats` | DiffStats! => Array | Details about which files were changed in this merge request |
| `diffStatsSummary` | DiffStatsSummary | Summary of which files were changed in this merge request |
| `discussionLocked` | Boolean! | Indicates if comments on the merge request are locked to members only |
+| `discussions` | DiscussionConnection! | All discussions on this noteable |
| `downvotes` | Int! | Number of downvotes for the merge request |
| `forceRemoveSourceBranch` | Boolean | Indicates if the project settings will lead to source branch deletion after merge |
| `headPipeline` | Pipeline | The pipeline running on the branch HEAD of the merge request |
| `id` | ID! | ID of the merge request |
| `iid` | String! | Internal ID of the merge request |
| `inProgressMergeCommitSha` | String | Commit SHA of the merge request if merge is in progress |
-| `mergeCommitMessage` **{warning-solid}** | String | **Deprecated:** Use `defaultMergeCommitMessage`. Deprecated in 11.8 |
+| `labels` | LabelConnection | Labels of the merge request |
| `mergeCommitSha` | String | SHA of the merge request commit (set once merged) |
| `mergeError` | String | Error message due to a merge error |
| `mergeOngoing` | Boolean! | Indicates if a merge is currently occurring |
@@ -1570,6 +1906,9 @@ Autogenerated return type of MarkAsSpamSnippet.
| `mergeableDiscussionsState` | Boolean | Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged |
| `mergedAt` | Time | Timestamp of when the merge request was merged, null if not merged |
| `milestone` | Milestone | The milestone of the merge request |
+| `notes` | NoteConnection! | All notes on this noteable |
+| `participants` | UserConnection | Participants in the merge request |
+| `pipelines` | PipelineConnection | Pipelines for the merge request |
| `project` | Project! | Alias for target_project |
| `projectId` | Int! | ID of the merge request project |
| `rebaseCommitSha` | String | Rebase commit SHA of the merge request |
@@ -1594,6 +1933,7 @@ Autogenerated return type of MarkAsSpamSnippet.
| `totalTimeSpent` | Int! | Total time reported as spent on the merge request |
| `updatedAt` | Time! | Timestamp of when the merge request was last updated |
| `upvotes` | Int! | Number of upvotes for the merge request |
+| `userDiscussionsCount` | Int | Number of user discussions in the merge request |
| `userNotesCount` | Int | User notes count of the merge request |
| `userPermissions` | MergeRequestPermissions! | Permissions for the current user on the resource |
| `webUrl` | String | Web URL of the merge request |
@@ -1721,6 +2061,7 @@ Autogenerated return type of MergeRequestUpdate.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `annotations` | MetricsDashboardAnnotationConnection | Annotations added to the dashboard |
| `path` | String | Path to a file with the dashboard definition |
| `schemaValidationWarnings` | String! => Array | Dashboard schema validation warnings |
@@ -1740,13 +2081,13 @@ Represents a milestone.
| 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 |
| `groupMilestone` | Boolean! | Indicates if milestone is at group level |
| `id` | ID! | ID of the milestone |
| `projectMilestone` | Boolean! | Indicates if milestone is at project level |
+| `report` | TimeboxReport | Historically accurate report about the timebox |
| `startDate` | Time | Timestamp of the milestone start date |
| `state` | MilestoneStateEnum! | State of the milestone |
| `stats` | MilestoneStats | Milestone statistics |
@@ -1780,6 +2121,7 @@ Contains statistics about a milestone.
| `lfsEnabled` | Boolean | Indicates if Large File Storage (LFS) is enabled for namespace |
| `name` | String! | Name of the namespace |
| `path` | String! | Path of the namespace |
+| `projects` | ProjectConnection! | Projects within this namespace |
| `repositorySizeExcessProjectCount` | Int! | Number of projects in the root namespace where the repository size exceeds the limit |
| `requestAccessEnabled` | Boolean | Indicates if users can request access to namespace |
| `rootStorageStatistics` | RootStorageStatistics | Aggregated storage statistics of the namespace. Only available for root namespaces |
@@ -1829,6 +2171,7 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily.
| `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 |
+| `repositionNote` | Boolean! | Indicates the user can perform `reposition_note` on this resource |
| `resolveNote` | Boolean! | Indicates the user can perform `resolve_note` on this resource |
### Package
@@ -1881,16 +2224,23 @@ Information about pagination in a connection..
| `coverage` | Float | Coverage percentage |
| `createdAt` | Time! | Timestamp of the pipeline's creation |
| `detailedStatus` | DetailedStatus! | Detailed status of the pipeline |
+| `downstream` | PipelineConnection | Pipelines this pipeline will trigger |
| `duration` | Int | Duration of the pipeline in seconds |
| `finishedAt` | Time | Timestamp of the pipeline's completion |
| `id` | ID! | ID of the pipeline |
| `iid` | String! | Internal ID of the pipeline |
+| `jobs` | CiJobConnection | Jobs belonging to the pipeline |
+| `path` | String | Relative path to the pipeline's page |
+| `project` | Project | Project the pipeline belongs to |
| `retryable` | Boolean! | Specifies if a pipeline can be retried |
| `securityReportSummary` | SecurityReportSummary | Vulnerability and scanned resource counts for each security scanner of the pipeline |
| `sha` | String! | SHA of the pipeline's commit |
+| `sourceJob` | CiJob | Job where pipeline was triggered from |
+| `stages` | CiStageConnection | Stages of the pipeline |
| `startedAt` | Time | Timestamp when the pipeline was started |
| `status` | PipelineStatusEnum! | Status of the pipeline (CREATED, WAITING_FOR_RESOURCE, PREPARING, PENDING, RUNNING, FAILED, SUCCESS, CANCELED, SKIPPED, MANUAL, SCHEDULED) |
| `updatedAt` | Time! | Timestamp of the pipeline's last activity |
+| `upstream` | Pipeline | Pipeline that triggered the pipeline |
| `user` | User | Pipeline user |
| `userPermissions` | PipelinePermissions! | Permissions for the current user on the resource |
@@ -1937,19 +2287,30 @@ Autogenerated return type of PipelineRetry.
| `actualRepositorySizeLimit` | Float | Size limit for the repository in bytes |
| `alertManagementAlert` | AlertManagementAlert | A single Alert Management alert of the project |
| `alertManagementAlertStatusCounts` | AlertManagementAlertStatusCountsType | Counts of alerts by status for the project |
+| `alertManagementAlerts` | AlertManagementAlertConnection | Alert Management alerts of the project |
+| `alertManagementIntegrations` | AlertManagementIntegrationConnection | Integrations which can receive alerts for the project |
| `allowMergeOnSkippedPipeline` | Boolean | If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs |
| `archived` | Boolean | Indicates the archived status of the project |
| `autocloseReferencedIssues` | Boolean | Indicates if issues referenced by merge requests and commits within the default branch are closed automatically |
| `avatarUrl` | String | URL to avatar image file of the project |
| `board` | Board | A single board of the project |
+| `boards` | BoardConnection | Boards of the project |
| `clusterAgent` | ClusterAgent | Find a single cluster agent by name |
+| `clusterAgents` | ClusterAgentConnection | Cluster agents associated with the project |
+| `codeCoverageSummary` | CodeCoverageSummary | Code coverage summary associated with the project |
+| `complianceFrameworks` | ComplianceFrameworkConnection | Compliance frameworks associated with the project |
| `containerExpirationPolicy` | ContainerExpirationPolicy | The container expiration policy of the project |
| `containerRegistryEnabled` | Boolean | Indicates if the project stores Docker container images in a container registry |
+| `containerRepositories` | ContainerRepositoryConnection | Container repositories of the project |
| `createdAt` | Time | Timestamp of the project creation |
+| `dastScannerProfiles` | DastScannerProfileConnection | The DAST scanner profiles associated with the project |
| `dastSiteProfile` | DastSiteProfile | DAST Site Profile associated with the project |
+| `dastSiteProfiles` | DastSiteProfileConnection | DAST Site Profiles associated with the project |
+| `dastSiteValidation` | DastSiteValidation | DAST Site Validation 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 |
+| `environments` | EnvironmentConnection | Environments of the project |
| `forksCount` | Int! | Number of times the project has been forked |
| `fullPath` | ID! | Full path of the project |
| `grafanaIntegration` | GrafanaIntegration | Grafana integration details for the project |
@@ -1959,32 +2320,43 @@ Autogenerated return type of PipelineRetry.
| `importStatus` | String | Status of import background job of the project |
| `issue` | Issue | A single issue of the project |
| `issueStatusCounts` | IssueStatusCountsType | Counts of issues by status for the project |
+| `issues` | IssueConnection | Issues of the project |
| `issuesEnabled` | Boolean | Indicates if Issues are enabled for the current user |
+| `iterations` | IterationConnection | Find iterations |
| `jiraImportStatus` | String | Status of Jira import background job of the project |
+| `jiraImports` | JiraImportConnection | Jira imports into the project |
| `jobsEnabled` | Boolean | Indicates if CI/CD pipeline jobs are enabled for the current user |
| `label` | Label | A label available on this project |
+| `labels` | LabelConnection | Labels available on this project |
| `lastActivityAt` | Time | Timestamp of the project last activity |
| `lfsEnabled` | Boolean | Indicates if the project has Large File Storage (LFS) enabled |
| `mergeRequest` | MergeRequest | A single merge request of the project |
+| `mergeRequests` | MergeRequestConnection | Merge requests of the project |
| `mergeRequestsEnabled` | Boolean | Indicates if Merge Requests are enabled for the current user |
| `mergeRequestsFfOnlyEnabled` | Boolean | Indicates if no merge commits should be created and all merges should instead be fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. |
+| `milestones` | MilestoneConnection | Milestones of the project |
| `name` | String! | Name of the project (without namespace) |
| `nameWithNamespace` | String! | Full name of the project with its namespace |
| `namespace` | Namespace | Namespace of the project |
| `onlyAllowMergeIfAllDiscussionsAreResolved` | Boolean | Indicates if merge requests of the project can only be merged when all the discussions are resolved |
| `onlyAllowMergeIfPipelineSucceeds` | Boolean | Indicates if merge requests of the project can only be merged with successful jobs |
| `openIssuesCount` | Int | Number of open issues for the project |
+| `packages` | PackageConnection | Packages of the project |
| `path` | String! | Path of the project |
| `pipeline` | Pipeline | Build pipeline of the project |
+| `pipelines` | PipelineConnection | Build pipelines of the project |
| `printingMergeRequestLinkEnabled` | Boolean | Indicates if a link to create or view a merge request should display after a push to Git repositories of the project from the command line |
+| `projectMembers` | MemberInterfaceConnection | Members of the project |
| `publicJobs` | Boolean | Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts |
| `release` | Release | A single release of the project |
+| `releases` | ReleaseConnection | Releases of the project |
| `removeSourceBranchAfterMerge` | Boolean | Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project |
| `repository` | Repository | Git repository of the project |
| `repositorySizeExcess` | Float | Size of repository that exceeds the limit in bytes |
| `requestAccessEnabled` | Boolean | Indicates if users can request member access to the project |
| `requirement` | Requirement | Find a single requirement |
| `requirementStatesCount` | RequirementStatesCount | Number of requirements for the project by their state |
+| `requirements` | RequirementConnection | Find requirements |
| `sastCiConfiguration` | SastCiConfiguration | SAST CI configuration for the project |
| `securityDashboardPath` | String | Path to project's security dashboard |
| `securityScanners` | SecurityScanners | Information about security analyzers used in the project |
@@ -1992,15 +2364,21 @@ Autogenerated return type of PipelineRetry.
| `sentryErrors` | SentryErrorCollection | Paginated collection of Sentry errors on the project |
| `serviceDeskAddress` | String | E-mail address of the service desk. |
| `serviceDeskEnabled` | Boolean | Indicates if the project has service desk enabled. |
+| `services` | ServiceConnection | Project services |
| `sharedRunnersEnabled` | Boolean | Indicates if shared runners are enabled for the project |
+| `snippets` | SnippetConnection | Snippets of the project |
| `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 |
| `statistics` | ProjectStatistics | Statistics of the project |
| `suggestionCommitMessage` | String | The commit message used to apply merge request suggestions |
| `tagList` | String | List of project topics (not Git tags) |
+| `terraformStates` | TerraformStateConnection | Terraform states associated with the project |
| `userPermissions` | ProjectPermissions! | Permissions for the current user on the resource |
| `visibility` | String | Visibility of the project |
+| `vulnerabilities` | VulnerabilityConnection | Vulnerabilities reported on the project |
+| `vulnerabilitiesCountByDay` | VulnerabilitiesCountByDayConnection | Number of vulnerabilities per day for the project |
+| `vulnerabilityScanners` | VulnerabilityScannerConnection | Vulnerability scanners reported on the project vulnerabilties |
| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each vulnerability severity in the project |
| `webUrl` | String | Web URL of the project |
| `wikiEnabled` | Boolean | Indicates if Wikis are enabled for the current user |
@@ -2072,14 +2450,15 @@ Represents a Project Membership.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `buildArtifactsSize` | Float! | Build artifacts size of the project |
+| `buildArtifactsSize` | Float! | Build artifacts size of the project in bytes |
| `commitCount` | Float! | Commit count of the project |
-| `lfsObjectsSize` | Float! | Large File Storage (LFS) object size of the project |
-| `packagesSize` | Float! | Packages size of the project |
-| `repositorySize` | Float! | Repository size of the project |
-| `snippetsSize` | Float | Snippets size of the project |
-| `storageSize` | Float! | Storage size of the project |
-| `wikiSize` | Float | Wiki size of the project |
+| `lfsObjectsSize` | Float! | Large File Storage (LFS) object size of the project in bytes |
+| `packagesSize` | Float! | Packages size of the project in bytes |
+| `repositorySize` | Float! | Repository size of the project in bytes |
+| `snippetsSize` | Float | Snippets size of the project in bytes |
+| `storageSize` | Float! | Storage size of the project in bytes |
+| `uploadsSize` | Float | Uploads size of the project in bytes |
+| `wikiSize` | Float | Wiki size of the project in bytes |
### PrometheusAlert
@@ -2090,6 +2469,47 @@ The alert condition for Prometheus.
| `humanizedText` | String! | The human-readable text of the alert condition |
| `id` | ID! | ID of the alert condition |
+### PrometheusIntegrationCreatePayload
+
+Autogenerated return type of PrometheusIntegrationCreate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `integration` | AlertManagementPrometheusIntegration | The newly created integration |
+
+### PrometheusIntegrationResetTokenPayload
+
+Autogenerated return type of PrometheusIntegrationResetToken.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `integration` | AlertManagementPrometheusIntegration | The newly created integration |
+
+### PrometheusIntegrationUpdatePayload
+
+Autogenerated return type of PrometheusIntegrationUpdate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `integration` | AlertManagementPrometheusIntegration | The newly created integration |
+
+### PromoteToEpicPayload
+
+Autogenerated return type of PromoteToEpic.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `epic` | Epic | The epic after issue promotion |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `issue` | Issue | The issue after mutation |
+
### Release
Represents a release.
@@ -2102,7 +2522,9 @@ Represents a release.
| `createdAt` | Time | Timestamp of when the release was created |
| `description` | String | Description (also known as "release notes") of the release |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
+| `evidences` | ReleaseEvidenceConnection | Evidence for the release |
| `links` | ReleaseLinks | Links of the release |
+| `milestones` | MilestoneConnection | Milestones associated to the release |
| `name` | String | Name of the release |
| `releasedAt` | Time | Timestamp of when the release was released |
| `tagName` | String | Name of the tag associated with the release |
@@ -2129,6 +2551,18 @@ A container for all assets associated with a release.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `count` | Int | Number of assets of the release |
+| `links` | ReleaseAssetLinkConnection | Asset links of the release |
+| `sources` | ReleaseSourceConnection | Sources of the release |
+
+### ReleaseCreatePayload
+
+Autogenerated return type of ReleaseCreate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `release` | Release | The release after mutation |
### ReleaseEvidence
@@ -2145,9 +2579,12 @@ Evidence for a release.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `closedIssuesUrl` | String | HTTP URL of the issues page, filtered by this release and `state=closed` |
+| `closedMergeRequestsUrl` | String | HTTP URL of the merge request page , filtered by this release and `state=closed` |
| `editUrl` | String | HTTP URL of the release's edit page |
-| `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 |
+| `mergedMergeRequestsUrl` | String | HTTP URL of the merge request page , filtered by this release and `state=merged` |
+| `openedIssuesUrl` | String | HTTP URL of the issues page, filtered by this release and `state=open` |
+| `openedMergeRequestsUrl` | String | HTTP URL of the merge request page, filtered by this release and `state=open` |
| `selfUrl` | String | HTTP URL of the release |
### ReleaseSource
@@ -2178,6 +2615,16 @@ Autogenerated return type of RemoveProjectFromSecurityDashboard.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+### RepositionImageDiffNotePayload
+
+Autogenerated return type of RepositionImageDiffNote.
+
+| 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 |
+
### Repository
| Field | Type | Description |
@@ -2203,6 +2650,7 @@ Represents a requirement.
| `lastTestReportState` | TestReportState | Latest requirement test report state |
| `project` | Project! | Project to which the requirement belongs |
| `state` | RequirementState! | State of the requirement |
+| `testReports` | TestReportConnection | Test reports of the requirement |
| `title` | String | Title of the requirement |
| `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` |
| `updatedAt` | Time! | Timestamp of when the requirement was last updated |
@@ -2250,6 +2698,7 @@ Autogenerated return type of RevertVulnerabilityToDetected.
| `repositorySize` | Float! | The Git repository size in bytes |
| `snippetsSize` | Float! | The snippets size in bytes |
| `storageSize` | Float! | The total storage in bytes |
+| `uploadsSize` | Float! | The uploads size in bytes |
| `wikiSize` | Float! | The wiki size in bytes |
### RunDASTScanPayload
@@ -2273,9 +2722,27 @@ Autogenerated return type of RunDASTScan.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `architectures` | RunnerArchitectureConnection | Runner architectures supported for the platform |
| `humanReadableName` | String! | Human readable name of the runner platform |
| `name` | String! | Name slug of the runner platform |
+### RunnerSetup
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `installInstructions` | String! | Instructions for installing the runner on the specified architecture |
+| `registerInstructions` | String | Instructions for registering the runner |
+
+### SastCiConfiguration
+
+Represents a CI configuration of SAST.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `analyzers` | SastCiConfigurationAnalyzersEntityConnection | List of analyzers entities attached to SAST configuration. |
+| `global` | SastCiConfigurationEntityConnection | List of global entities related to SAST configuration. |
+| `pipeline` | SastCiConfigurationEntityConnection | List of pipeline entities related to SAST configuration. |
+
### SastCiConfigurationAnalyzersEntity
Represents an analyzer entity in SAST CI configuration.
@@ -2286,6 +2753,7 @@ Represents an analyzer entity in SAST CI configuration.
| `enabled` | Boolean | Indicates whether an analyzer is enabled |
| `label` | String | Analyzer label used in the config UI |
| `name` | String | Name of the analyzer |
+| `variables` | SastCiConfigurationEntityConnection | List of supported variables |
### SastCiConfigurationEntity
@@ -2297,6 +2765,7 @@ Represents an entity in SAST CI configuration.
| `description` | String | Entity description that is displayed on the form. |
| `field` | String | CI keyword of entity. |
| `label` | String | Label for entity used in the form. |
+| `options` | SastCiConfigurationOptionsEntityConnection | Different possible values of the field. |
| `size` | SastUiComponentSize | Size of the UI component. |
| `type` | String | Type of the field value. |
| `value` | String | Current value of the entity. |
@@ -2339,6 +2808,7 @@ Represents a section of a summary of a security report.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `scannedResources` | ScannedResourceConnection | A list of the first 20 scanned resources |
| `scannedResourcesCount` | Int | Total number of scanned resources |
| `scannedResourcesCsvPath` | String | Path to download all the scanned resources in CSV format |
| `vulnerabilitiesCount` | Int | Total number of vulnerabilities |
@@ -2478,12 +2948,15 @@ Represents a snippet entry.
| ----- | ---- | ----------- |
| `author` | User | The owner of the snippet |
| `blob` **{warning-solid}** | SnippetBlob! | **Deprecated:** Use `blobs`. Deprecated in 13.3 |
+| `blobs` | SnippetBlobConnection | Snippet blobs |
| `createdAt` | Time! | Timestamp this snippet was created |
| `description` | String | Description of the snippet |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
+| `discussions` | DiscussionConnection! | All discussions on this noteable |
| `fileName` | String | File Name of the snippet |
| `httpUrlToRepo` | String | HTTP URL to the snippet repository |
-| `id` | ID! | ID of the snippet |
+| `id` | SnippetID! | ID of the snippet |
+| `notes` | NoteConnection! | All notes on this noteable |
| `project` | Project | The project the snippet is associated with |
| `rawUrl` | String! | Raw URL of the snippet |
| `sshUrlToRepo` | String | SSH URL to the snippet repository |
@@ -2537,6 +3010,21 @@ 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 |
+### SnippetRepositoryRegistry
+
+Represents the Geo sync and verification state of a snippet repository.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | Time | Timestamp when the SnippetRepositoryRegistry was created |
+| `id` | ID! | ID of the SnippetRepositoryRegistry |
+| `lastSyncFailure` | String | Error message during sync of the SnippetRepositoryRegistry |
+| `lastSyncedAt` | Time | Timestamp of the most recent successful sync of the SnippetRepositoryRegistry |
+| `retryAt` | Time | Timestamp after which the SnippetRepositoryRegistry should be resynced |
+| `retryCount` | Int | Number of consecutive failed sync attempts of the SnippetRepositoryRegistry |
+| `snippetRepositoryId` | ID! | ID of the Snippet Repository |
+| `state` | RegistryState | Sync state of the SnippetRepositoryRegistry |
+
### StatusAction
| Field | Type | Description |
@@ -2575,11 +3063,49 @@ Completion status of tasks.
| ----- | ---- | ----------- |
| `createdAt` | Time! | Timestamp the Terraform state was created |
| `id` | ID! | ID of the Terraform state |
+| `latestVersion` | TerraformStateVersion | The latest version of the Terraform state |
| `lockedAt` | Time | Timestamp the Terraform state was locked |
| `lockedByUser` | User | The user currently holding a lock on the Terraform state |
| `name` | String! | Name of the Terraform state |
| `updatedAt` | Time! | Timestamp the Terraform state was updated |
+### TerraformStateDeletePayload
+
+Autogenerated return type of TerraformStateDelete.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
+### TerraformStateLockPayload
+
+Autogenerated return type of TerraformStateLock.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
+### TerraformStateUnlockPayload
+
+Autogenerated return type of TerraformStateUnlock.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
+### TerraformStateVersion
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | Time! | Timestamp the version was created |
+| `createdByUser` | User | The user that created this version |
+| `id` | ID! | ID of the Terraform state version |
+| `job` | CiJob | The job that created this version |
+| `updatedAt` | Time! | Timestamp the version was updated |
+
### TerraformStateVersionRegistry
Represents the Geo sync and verification state of a terraform state version.
@@ -2606,11 +3132,38 @@ Represents a requirement test report.
| `id` | ID! | ID of the test report |
| `state` | TestReportState! | State of the test report |
+### TimeReportStats
+
+Represents the time report stats for timeboxes.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `complete` | TimeboxMetrics | Completed issues metrics |
+| `incomplete` | TimeboxMetrics | Incomplete issues metrics |
+| `total` | TimeboxMetrics | Total issues metrics |
+
+### TimeboxMetrics
+
+Represents measured stats metrics for timeboxes.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `count` | Int! | The count metric |
+| `weight` | Int! | The weight metric |
+
+### TimeboxReport
+
+Represents a historically accurate report about the timebox.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `burnupTimeSeries` | BurnupChartDailyTotals! => Array | Daily scope and completed totals for burnup charts |
+| `stats` | TimeReportStats | Represents the time report stats for the timebox |
+
### Timelog
| 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 |
@@ -2633,6 +3186,16 @@ Representing a todo entry.
| `state` | TodoStateEnum! | State of the todo |
| `targetType` | TodoTargetEnum! | Target type of the todo |
+### TodoCreatePayload
+
+Autogenerated return type of TodoCreate.
+
+| 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 to-do created |
+
### TodoMarkDonePayload
Autogenerated return type of TodoMarkDone.
@@ -2652,7 +3215,7 @@ Autogenerated return type of TodoRestoreMany.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `todos` | Todo! => Array | Updated todos |
-| `updatedIds` **{warning-solid}** | ID! => Array | **Deprecated:** Use todos. Deprecated in 13.2 |
+| `updatedIds` **{warning-solid}** | TodoID! => Array | **Deprecated:** Use todos. Deprecated in 13.2 |
### TodoRestorePayload
@@ -2673,7 +3236,7 @@ Autogenerated return type of TodosMarkAllDone.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `todos` | Todo! => Array | Updated todos |
-| `updatedIds` **{warning-solid}** | ID! => Array | **Deprecated:** Use todos. Deprecated in 13.2 |
+| `updatedIds` **{warning-solid}** | TodoID! => Array | **Deprecated:** Use todos. Deprecated in 13.2 |
### ToggleAwardEmojiPayload
@@ -2690,7 +3253,10 @@ Autogenerated return type of ToggleAwardEmoji.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `blobs` | BlobConnection! | Blobs of the tree |
| `lastCommit` | Commit | Last commit for the tree |
+| `submodules` | SubmoduleConnection! | Sub-modules of the tree |
+| `trees` | TreeEntryConnection! | Trees of the tree |
### TreeEntry
@@ -2834,12 +3400,20 @@ Autogenerated return type of UpdateSnippet.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `assignedMergeRequests` | MergeRequestConnection | Merge Requests assigned to the user |
+| `authoredMergeRequests` | MergeRequestConnection | Merge Requests authored by the user |
| `avatarUrl` | String | URL of the user's avatar |
| `email` | String | User email |
+| `groupCount` | Int | Group count for the user. Available only when feature flag `user_group_counts` is enabled |
+| `groupMemberships` | GroupMemberConnection | Group memberships of the user |
| `id` | ID! | ID of the user |
| `name` | String! | Human-readable name of the user |
+| `projectMemberships` | ProjectMemberConnection | Project memberships of the user |
+| `snippets` | SnippetConnection | Snippets authored by the user |
+| `starredProjects` | ProjectConnection | Projects starred by the user |
| `state` | UserState! | State of the user |
| `status` | UserStatus | User status |
+| `todos` | TodoConnection! | Todos of the user |
| `userPermissions` | UserPermissions! | Permissions for the current user on the resource |
| `username` | String! | Username of the user. Unique within this instance of GitLab |
| `webPath` | String! | Web path of the user |
@@ -2855,13 +3429,14 @@ Autogenerated return type of UpdateSnippet.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `availability` | AvailabilityEnum! | User availability status |
| `emoji` | String | String representation of emoji |
| `message` | String | User status message |
| `messageHtml` | String | HTML of the user status message |
### VulnerabilitiesCountByDay
-Represents the count of vulnerabilities by severity on a particular day.
+Represents the count of vulnerabilities by severity on a particular day. This data is retained for 365 days.
| Field | Type | Description |
| ----- | ---- | ----------- |
@@ -2876,7 +3451,7 @@ Represents the count of vulnerabilities by severity on a particular day.
### 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. This data is retained for 365 days.
| Field | Type | Description |
| ----- | ---- | ----------- |
@@ -2892,9 +3467,12 @@ Represents a vulnerability.
| ----- | ---- | ----------- |
| `description` | String | Description of the vulnerability |
| `detectedAt` | Time! | Timestamp of when the vulnerability was first detected |
+| `discussions` | DiscussionConnection! | All discussions on this noteable |
| `id` | ID! | GraphQL ID of the vulnerability |
| `identifiers` | VulnerabilityIdentifier! => Array | Identifiers of the vulnerability. |
+| `issueLinks` | VulnerabilityIssueLinkConnection! | List of issue links related to the vulnerability |
| `location` | VulnerabilityLocation | Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability |
+| `notes` | NoteConnection! | All notes on this noteable |
| `primaryIdentifier` | VulnerabilityIdentifier | Primary identifier of the vulnerability. |
| `project` | Project | The project on which the vulnerability was found |
| `reportType` | VulnerabilityReportType | Type of the security report that found the vulnerability (SAST, DEPENDENCY_SCANNING, CONTAINER_SCANNING, DAST, SECRET_DETECTION, COVERAGE_FUZZING, API_FUZZING) |
@@ -3098,6 +3676,7 @@ Represents vulnerability letter grades with associated projects.
| ----- | ---- | ----------- |
| `count` | Int! | Number of projects within this grade |
| `grade` | VulnerabilityGrade! | Grade based on the highest severity vulnerability present |
+| `projects` | ProjectConnection! | Projects within this grade |
## Enumeration types
@@ -3150,6 +3729,15 @@ Values for sorting alerts.
| `updated_asc` **{warning-solid}** | **Deprecated:** Use UPDATED_ASC. Deprecated in 13.5 |
| `updated_desc` **{warning-solid}** | **Deprecated:** Use UPDATED_DESC. Deprecated in 13.5 |
+### AlertManagementIntegrationType
+
+Values of types of integrations.
+
+| Value | Description |
+| ----- | ----------- |
+| `HTTP` | Integration with any monitoring tool |
+| `PROMETHEUS` | Prometheus integration |
+
### AlertManagementSeverity
Alert severity values.
@@ -3174,6 +3762,15 @@ Alert status values.
| `RESOLVED` | Resolved status |
| `TRIGGERED` | Triggered status |
+### AvailabilityEnum
+
+User availability status.
+
+| Value | Description |
+| ----- | ----------- |
+| `BUSY` | Busy |
+| `NOT_SET` | Not Set |
+
### BlobViewersType
Types of blob viewers.
@@ -3233,6 +3830,26 @@ Mode of a commit action.
| `SEVEN_DAYS` | 7 days until tags are automatically removed |
| `THIRTY_DAYS` | 30 days until tags are automatically removed |
+### ContainerRepositoryCleanupStatus
+
+Status of the tags cleanup of a container repository.
+
+| Value | Description |
+| ----- | ----------- |
+| `ONGOING` | The tags cleanup is ongoing. |
+| `SCHEDULED` | The tags cleanup is scheduled and is going to be executed shortly. |
+| `UNFINISHED` | The tags cleanup has been partially executed. There are still remaining tags to delete. |
+| `UNSCHEDULED` | The tags cleanup is not scheduled. This is the default state. |
+
+### ContainerRepositoryStatus
+
+Status of a container repository.
+
+| Value | Description |
+| ----- | ----------- |
+| `DELETE_FAILED` | Delete Failed status. |
+| `DELETE_SCHEDULED` | Delete Scheduled status. |
+
### DastScanTypeEnum
| Value | Description |
@@ -3249,6 +3866,13 @@ Mode of a commit action.
| `PASSED_VALIDATION` | Site validation process finished successfully |
| `PENDING_VALIDATION` | Site validation process has not started |
+### DastSiteValidationStrategyEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `HEADER` | Header validation |
+| `TEXT_FILE` | Text file validation |
+
### DesignCollectionCopyState
Copy state of a DesignCollection.
@@ -3382,6 +4006,8 @@ Values for sorting issues.
| `RELATIVE_POSITION_ASC` | Relative position by ascending order |
| `SEVERITY_ASC` | Severity from less critical to more critical |
| `SEVERITY_DESC` | Severity from more critical to less critical |
+| `SLA_DUE_AT_ASC` | Issues with earliest SLA due time shown first |
+| `SLA_DUE_AT_DESC` | Issues with latest SLA due time shown first |
| `UPDATED_ASC` | Updated at ascending order |
| `UPDATED_DESC` | Updated at descending order |
| `WEIGHT_ASC` | Weight by ascending order |
@@ -3433,6 +4059,15 @@ State of a GitLab iteration.
| `started` | |
| `upcoming` | |
+### IterationWildcardId
+
+Iteration ID wildcard values.
+
+| Value | Description |
+| ----- | ----------- |
+| `ANY` | An iteration is assigned |
+| `NONE` | No iteration is assigned |
+
### ListLimitMetric
List limit metric setting.
@@ -3528,6 +4163,7 @@ Values for sorting projects.
| Value | Description |
| ----- | ----------- |
| `SIMILARITY` | Most similar to the search query |
+| `STORAGE` | Sort by storage size |
### PackageTypeEnum
@@ -3572,18 +4208,6 @@ Values for sorting projects.
| `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.
@@ -3597,7 +4221,7 @@ State of a Geo registry.
### ReleaseAssetLinkType
-Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`.
+Type of the link: `other`, `runbook`, `image`, `package`.
| Value | Description |
| ----- | ----------- |
@@ -3606,6 +4230,17 @@ Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`.
| `PACKAGE` | Package link type |
| `RUNBOOK` | Runbook link type |
+### ReleaseSort
+
+Values for sorting releases.
+
+| Value | Description |
+| ----- | ----------- |
+| `CREATED_ASC` | Created at ascending order |
+| `CREATED_DESC` | Created at descending order |
+| `RELEASED_AT_ASC` | Released at by ascending order |
+| `RELEASED_AT_DESC` | Released at by descending order |
+
### RequirementState
State of a requirement.
@@ -3625,6 +4260,18 @@ Size of UI component in SAST configuration page.
| `MEDIUM` | |
| `SMALL` | |
+### SecurityReportTypeEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `API_FUZZING` | API FUZZING scan report |
+| `CONTAINER_SCANNING` | CONTAINER SCANNING scan report |
+| `COVERAGE_FUZZING` | COVERAGE FUZZING scan report |
+| `DAST` | DAST scan report |
+| `DEPENDENCY_SCANNING` | DEPENDENCY SCANNING scan report |
+| `SAST` | SAST scan report |
+| `SECRET_DETECTION` | SECRET DETECTION scan report |
+
### SecurityScannerType
The type of the security scanner.
diff --git a/doc/api/graphql/removed_items.md b/doc/api/graphql/removed_items.md
new file mode 100644
index 00000000000..f05b23495bb
--- /dev/null
+++ b/doc/api/graphql/removed_items.md
@@ -0,0 +1,17 @@
+# GraphQL API removed items
+
+GraphQL is a versionless API, unlike the REST API.
+Occasionally, items have to be updated or removed from the GraphQL API.
+According to our [process for removing items](index.md#deprecation-process), here are the items that have been removed.
+
+## GitLab 13.6
+
+Fields removed in [GitLab 13.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44866):
+
+| Field name | GraphQL type | Deprecated in | Use instead |
+| -------------------- | -------------------- | ------------- | -------------------------- |
+| `date` | `Timelog` **(STARTER)** | 12.10 | `spentAt` |
+| `designs` | `Issue`, `EpicIssue` | 12.2 | `designCollection` |
+| `latestPipeline` | `Commit` | 12.5 | `pipelines` |
+| `mergeCommitMessage` | `MergeRequest` | 11.8 | `latestMergeCommitMessage` |
+| `token` | `GrafanaIntegration` | 12.7 | None. Plaintext tokens no longer supported for security reasons. |
diff --git a/doc/api/graphql/sample_issue_boards.md b/doc/api/graphql/sample_issue_boards.md
index 4ac9317b01a..27fd1f48aec 100644
--- a/doc/api/graphql/sample_issue_boards.md
+++ b/doc/api/graphql/sample_issue_boards.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Identify issue boards with GraphQL
This page describes how you can use the GraphiQL explorer to identify
diff --git a/doc/api/group_activity_analytics.md b/doc/api/group_activity_analytics.md
index 90920d1b25c..ea2527e6c4a 100644
--- a/doc/api/group_activity_analytics.md
+++ b/doc/api/group_activity_analytics.md
@@ -1,3 +1,9 @@
+---
+stage: Manage
+group: Optimize
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Group Activity Analytics API
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26460) in GitLab 12.9.
diff --git a/doc/api/group_badges.md b/doc/api/group_badges.md
index 43e1944226d..e13b9633da9 100644
--- a/doc/api/group_badges.md
+++ b/doc/api/group_badges.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Group badges API
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17082) in GitLab 10.6.
diff --git a/doc/api/group_boards.md b/doc/api/group_boards.md
index 4ff373ce583..6158400f882 100644
--- a/doc/api/group_boards.md
+++ b/doc/api/group_boards.md
@@ -265,44 +265,17 @@ Example response:
{
"id": 1,
"name": "newboard",
+ "project": null,
+ "lists" : [],
"group": {
"id": 5,
"name": "Documentcloud",
"web_url": "http://example.com/groups/documentcloud"
},
- "milestone": {
- "id": 12
- "title": "10.0"
- },
- "lists" : [
- {
- "id" : 1,
- "label" : {
- "name" : "Testing",
- "color" : "#F0AD4E",
- "description" : null
- },
- "position" : 1
- },
- {
- "id" : 2,
- "label" : {
- "name" : "Ready",
- "color" : "#FF0000",
- "description" : null
- },
- "position" : 2
- },
- {
- "id" : 3,
- "label" : {
- "name" : "Production",
- "color" : "#FF5F00",
- "description" : null
- },
- "position" : 3
- }
- ]
+ "milestone": null,
+ "assignee" : null,
+ "labels" : [],
+ "weight" : null
}
```
diff --git a/doc/api/group_import_export.md b/doc/api/group_import_export.md
index 01d81eb62ac..5677cb51c37 100644
--- a/doc/api/group_import_export.md
+++ b/doc/api/group_import_export.md
@@ -1,3 +1,9 @@
+---
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Group Import/Export API
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20353) in GitLab 12.8.
diff --git a/doc/api/group_iterations.md b/doc/api/group_iterations.md
index 62431244d78..eb6a99a430e 100644
--- a/doc/api/group_iterations.md
+++ b/doc/api/group_iterations.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.5.
This page describes the group iterations API.
-There's a separate [project iterations API](./iterations.md) page.
+There's a separate [project iterations API](iterations.md) page.
## List group iterations
diff --git a/doc/api/group_labels.md b/doc/api/group_labels.md
index 260ee669e08..f11a4d8ccc9 100644
--- a/doc/api/group_labels.md
+++ b/doc/api/group_labels.md
@@ -26,6 +26,9 @@ GET /groups/:id/labels
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user. |
| `with_counts` | boolean | no | Whether or not to include issue and merge request counts. Defaults to `false`. _([Introduced in GitLab 12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31543))_ |
| `include_ancestor_groups` | boolean | no | Include ancestor groups. Defaults to `true`. |
+| `include_descendant_groups` | boolean | no | Include descendant groups. Defaults to `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259024) in GitLab 13.6 |
+| `only_group_labels` | boolean | no | Toggle to include only group labels or also project labels. Defaults to `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259024) in GitLab 13.6 |
+| `search` | string | no | Keyword to filter labels by. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259024) in GitLab 13.6 |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/labels?with_counts=true"
@@ -75,6 +78,8 @@ GET /groups/:id/labels/:label_id
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user. |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
| `include_ancestor_groups` | boolean | no | Include ancestor groups. Defaults to `true`. |
+| `include_descendant_groups` | boolean | no | Include descendant groups. Defaults to `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259024) in GitLab 13.6 |
+| `only_group_labels` | boolean | no | Toggle to include only group labels or also project labels. Defaults to `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259024) in GitLab 13.6 |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/labels/bug"
diff --git a/doc/api/group_level_variables.md b/doc/api/group_level_variables.md
index aa5f0b3db72..6997ebdede4 100644
--- a/doc/api/group_level_variables.md
+++ b/doc/api/group_level_variables.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Group-level Variables API
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34519) in GitLab 9.5
diff --git a/doc/api/group_milestones.md b/doc/api/group_milestones.md
index 3220707e9e3..a2acf2c8fb1 100644
--- a/doc/api/group_milestones.md
+++ b/doc/api/group_milestones.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12819) in GitLab 9.5.
This page describes the group milestones API.
-There's a separate [project milestones API](./milestones.md) page.
+There's a separate [project milestones API](milestones.md) page.
## List group milestones
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 53c92cf85ec..0a584795d21 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Groups API
## List groups
@@ -89,7 +95,7 @@ GET /groups?statistics=true
"parent_id": null,
"created_at": "2020-01-15T12:36:29.590Z",
"statistics": {
- "storage_size" : 212,
+ "storage_size" : 363,
"repository_size" : 33,
"wiki_size" : 100,
"lfs_objects_size" : 123,
@@ -1037,6 +1043,7 @@ GET /groups/:id/hooks/:hook_id
"pipeline_events": true,
"wiki_page_events": true,
"deployment_events": true,
+ "releases_events": true,
"enable_ssl_verification": true,
"created_at": "2012-10-12T17:04:47Z"
}
@@ -1065,6 +1072,7 @@ POST /groups/:id/hooks
| `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 |
+| `releases_events` | boolean | no | Trigger hook on release 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 |
@@ -1092,6 +1100,7 @@ PUT /groups/:id/hooks/:hook_id
| `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 |
+| `releases_events` | boolean | no | Trigger hook on release 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 |
@@ -1113,7 +1122,7 @@ DELETE /groups/:id/hooks/:hook_id
Group audit events can be accessed via the [Group Audit Events API](audit_events.md#group-audit-events)
-## Sync group with LDAP **(STARTER)**
+## Sync group with LDAP **(STARTER ONLY)**
Syncs the group with its linked LDAP group. Only available to group owners and administrators.
@@ -1133,7 +1142,7 @@ Please consult the [Group Members](members.md) documentation.
List, add, and delete LDAP group links.
-### List LDAP group links **(STARTER)**
+### List LDAP group links **(STARTER ONLY)**
Lists LDAP group links.
@@ -1145,7 +1154,7 @@ GET /groups/:id/ldap_group_links
| --------- | -------------- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
-### Add LDAP group link with CN or filter **(STARTER)**
+### Add LDAP group link with CN or filter **(STARTER ONLY)**
Adds an LDAP group link using a CN or filter. Adding a group link by filter is only supported in the Premium tier and above.
@@ -1164,7 +1173,7 @@ POST /groups/:id/ldap_group_links
NOTE: **Note:**
To define the LDAP group link, provide either a `cn` or a `filter`, but not both.
-### Delete LDAP group link **(STARTER)**
+### Delete LDAP group link **(STARTER ONLY)**
Deletes an LDAP group link. Deprecated. Will be removed in a future release.
@@ -1189,7 +1198,7 @@ DELETE /groups/:id/ldap_group_links/:provider/:cn
| `cn` | string | yes | The CN of an LDAP group |
| `provider` | string | yes | LDAP provider for the LDAP group link |
-### Delete LDAP group link with CN or filter **(STARTER)**
+### Delete LDAP group link with CN or filter **(STARTER ONLY)**
Deletes an LDAP group link using a CN or filter. Deleting by filter is only supported in the Premium tier and above.
diff --git a/doc/api/import.md b/doc/api/import.md
index e377853ade0..27f5915b206 100644
--- a/doc/api/import.md
+++ b/doc/api/import.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Import API
## Import repository from GitHub
@@ -13,10 +19,20 @@ POST /import/github
| `personal_access_token` | string | yes | GitHub personal access token |
| `repo_id` | integer | yes | GitHub repository ID |
| `new_name` | string | no | New repository name |
-| `target_namespace` | string | yes | Namespace to import repository into |
+| `target_namespace` | string | yes | Namespace to import repository into. Supports subgroups like `/namespace/subgroup`. |
+| `github_hostname` | string | no | Custom GitHub enterprise hostname. Defaults to GitHub.com if `github_hostname` is not set. |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "personal_access_token=abc123&repo_id=12345&target_namespace=root" "https://gitlab.example.com/api/v4/import/github"
+curl --request POST \
+ --url "https://gitlab.example.com/api/v4/import/github" \
+ --header "content-type: application/json" \
+ --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data '{
+ "personal_access_token": "aBc123abC12aBc123abC12abC123+_A/c123",
+ "repo_id": "12345",
+ "target_namespace": "group/subgroup",
+ "new_name": "NEW-NAME"
+}'
```
Example response:
@@ -51,7 +67,7 @@ POST /import/bitbucket_server
| `bitbucket_server_project` | string | yes | Bitbucket Project Key |
| `bitbucket_server_repo` | string | yes | Bitbucket Repository Name |
| `new_name` | string | no | New repository name |
-| `target_namespace` | string | no | Namespace to import repository into |
+| `target_namespace` | string | no | Namespace to import repository into. Supports subgroups like `/namespace/subgroup` |
```shell
curl --request POST \
diff --git a/doc/api/instance_clusters.md b/doc/api/instance_clusters.md
index 1108550eee7..bc4eca5abfd 100644
--- a/doc/api/instance_clusters.md
+++ b/doc/api/instance_clusters.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Instance clusters API
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36001) in GitLab 13.2.
diff --git a/doc/api/invitations.md b/doc/api/invitations.md
new file mode 100644
index 00000000000..6fd2b26d80f
--- /dev/null
+++ b/doc/api/invitations.md
@@ -0,0 +1,107 @@
+---
+stage: Growth
+group: Expansion
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# Invitations API
+
+Use the Invitations API to send email to users you want to join a group or project, and to list pending
+invitations.
+
+## Valid access levels
+
+To send an invitation, you must have access to the project or group you are sending email for. Valid access
+levels are defined in the `Gitlab::Access` module. Currently, these levels are valid:
+
+- No access (`0`)
+- Guest (`10`)
+- Reporter (`20`)
+- Developer (`30`)
+- Maintainer (`40`)
+- Owner (`50`) - Only valid to set for groups
+
+CAUTION: **Caution:**
+Due to [an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/219299),
+projects in personal namespaces will not show owner (`50`) permission.
+
+## Invite by email to group or project
+
+Invites a new user by email to join a group or project.
+
+```plaintext
+POST /groups/:id/invitations
+POST /projects/:id/invitations
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `email` | integer/string | yes | The email of the new member or multiple emails separated by commas |
+| `access_level` | integer | yes | A valid access level |
+| `expires_at` | string | no | A date string in the format YEAR-MONTH-DAY |
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "email=test@example.com&access_level=30" "https://gitlab.example.com/api/v4/groups/:id/invitations"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "email=test@example.com&access_level=30" "https://gitlab.example.com/api/v4/projects/:id/invitations"
+```
+
+Example responses:
+
+When all emails were successfully sent:
+
+```json
+{ "status": "success" }
+```
+
+When there was any error sending the email:
+
+```json
+{
+ "status": "error",
+ "message": {
+ "test@example.com": "Already invited",
+ "test2@example.com": "Member already exsists"
+ }
+}
+```
+
+## List all invitations pending for a group or project
+
+Gets a list of invited group or project members viewable by the authenticated user.
+Returns invitations to direct members only, and not through inherited ancestors' groups.
+
+This function takes pagination parameters `page` and `per_page` to restrict the list of users.
+
+```plaintext
+GET /groups/:id/invitations
+GET /projects/:id/invitations
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `page` | integer | no | Page to retrieve |
+| `per_page`| integer | no | Number of member invitations to return per page |
+| `query` | string | no | A query string to search for invited members by invite email. Query text must match email address exactly. When empty, returns all invitations. |
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/invitations?query=member@example.org"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/invitations?query=member@example.org"
+```
+
+Example response:
+
+```json
+ [
+ {
+ "id": 1,
+ "invite_email": "member@example.org",
+ "invited_at": "2020-10-22T14:13:35Z",
+ "access_level": 30,
+ "expires_at": "2020-11-22T14:13:35Z",
+ "user_name": "Raymond Smith",
+ "created_by_name": "Administrator"
+ },
+]
+```
diff --git a/doc/api/issue_links.md b/doc/api/issue_links.md
index 757910d0946..41e2dd7c147 100644
--- a/doc/api/issue_links.md
+++ b/doc/api/issue_links.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Issue links API **(CORE)**
> The simple "relates to" relationship [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212329) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.4.
diff --git a/doc/api/issues.md b/doc/api/issues.md
index b50ea7b42be..ad5990f4a37 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -55,11 +55,14 @@ GET /issues?state=opened
| `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 |
+| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `due_date` | string | no | Return issues that have no due date (`0`) or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _(Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ |
| `iids[]` | integer array | no | Return only the issues having the given `iid` |
| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
+| `iteration_id` **(STARTER)** | integer | no | Return issues assigned to the given iteration ID. `None` returns issues that do not belong to an iteration. `Any` returns issues that belong to an iteration. Mutually exclusive with `iteration_title`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6)_ |
+| `iteration_title` **(STARTER)** | string | no | Return issues assigned to the iteration with the given title. Similar to `iteration_id` and mutually exclusive with `iteration_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6)_ |
+| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0)_ |
@@ -70,8 +73,8 @@ GET /issues?state=opened
| `search` | string | no | Search issues against their `title` and `description` |
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
| `state` | string | no | Return `all` issues or just those that are `opened` or `closed` |
-| `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 |
+| `updated_after` | datetime | no | Return issues updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_before` | datetime | no | Return issues updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `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)|
@@ -234,8 +237,8 @@ GET /groups/:id/issues?state=opened
| `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 |
+| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `due_date` | string | no | Return issues that have no due date (`0`) or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _(Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `iids[]` | integer array | no | Return only the issues having the given `iid` |
@@ -249,8 +252,8 @@ GET /groups/:id/issues?state=opened
| `search` | string | no | Search group issues against their `title` and `description` |
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
-| `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 |
+| `updated_after` | datetime | no | Return issues updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_before` | datetime | no | Return issues updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `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) |
@@ -411,8 +414,8 @@ GET /projects/:id/issues?state=opened
| `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 |
+| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `due_date` | string | no | Return issues that have no due date (`0`) or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _(Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ |
| `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` |
@@ -425,8 +428,8 @@ GET /projects/:id/issues?state=opened
| `search` | string | no | Search project issues against their `title` and `description` |
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
-| `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 |
+| `updated_after` | datetime | no | Return issues updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_before` | datetime | no | Return issues updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `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) |
@@ -1507,10 +1510,10 @@ Example response:
}
```
-## Create a to do
+## Create a to-do item
-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
+Manually creates a to-do item for the current user on an issue. If
+there already exists a to-do item for the user on that issue, status code `304` is
returned.
```plaintext
@@ -1941,7 +1944,7 @@ GET /projects/:id/issues/:issue_iid/closed_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 |
+| `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
@@ -2081,4 +2084,4 @@ Example response:
## List issue state events
To track which state was set, who did it, and when it happened, check out
-[Resource state events API](./resource_state_events.md#issues).
+[Resource state events API](resource_state_events.md#issues).
diff --git a/doc/api/issues_statistics.md b/doc/api/issues_statistics.md
index 8e2dcc07af8..3f0b22cca4c 100644
--- a/doc/api/issues_statistics.md
+++ b/doc/api/issues_statistics.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Issues Statistics API
Every API call to issues_statistics must be authenticated.
@@ -39,10 +45,10 @@ GET /issues_statistics?confidential=true
| `iids[]` | integer array | no | Return only the issues having the given `iid` |
| `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 |
-| `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 |
+| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_after` | datetime | no | Return issues updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_before` | datetime | no | Return issues updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `confidential` | boolean | no | Filter confidential or public issues. |
```shell
@@ -95,10 +101,10 @@ GET /groups/:id/issues_statistics?confidential=true
| `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. |
| `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 |
-| `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 |
+| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_after` | datetime | no | Return issues updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_before` | datetime | no | Return issues updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `confidential` | boolean | no | Filter confidential or public issues. |
```shell
@@ -151,10 +157,10 @@ GET /projects/:id/issues_statistics?confidential=true
| `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. |
| `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 |
-| `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 |
+| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_after` | datetime | no | Return issues updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_before` | datetime | no | Return issues updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `confidential` | boolean | no | Filter confidential or public issues. |
```shell
diff --git a/doc/api/iterations.md b/doc/api/iterations.md
index 53a6bb00f23..9f1585eed79 100644
--- a/doc/api/iterations.md
+++ b/doc/api/iterations.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.5.
This page describes the project iterations API.
-There's a separate [group iterations API](./group_iterations.md) page.
+There's a separate [group iterations API](group_iterations.md) page.
As of GitLab 13.5, we don't have project-level iterations, but you can use this endpoint to fetch the iterations of the project's ancestor groups.
diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md
index f5510f6ee91..54085e6f508 100644
--- a/doc/api/job_artifacts.md
+++ b/doc/api/job_artifacts.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Job Artifacts API
## Get job artifacts
diff --git a/doc/api/labels.md b/doc/api/labels.md
index 30290f18653..acc80badd11 100644
--- a/doc/api/labels.md
+++ b/doc/api/labels.md
@@ -24,6 +24,7 @@ GET /projects/:id/labels
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `with_counts` | boolean | no | Whether or not to include issue and merge request counts. Defaults to `false`. _([Introduced in GitLab 12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31543))_ |
| `include_ancestor_groups` | boolean | no | Include ancestor groups. Defaults to `true`. |
+| `search` | string | no | Keyword to filter labels by. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259024) in GitLab 13.6 |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels?with_counts=true"
@@ -248,9 +249,12 @@ An older endpoint `PUT /projects/:id/labels` with `name` or `label_id` in the pa
## Promote a project label to a group label
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25218) in GitLab 12.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25218) in GitLab 12.3.
+> - In [GitLab 13.6 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/231472), promoting a
+> project label keeps that label's ID and changes it into a group label. Previously, promoting a
+> project label created a new group label with a new ID and deleted the old label.
-Promotes a project label to a group label.
+Promotes a project label to a group label. The label keeps its ID.
```plaintext
PUT /projects/:id/labels/:label_id/promote
diff --git a/doc/api/license.md b/doc/api/license.md
index dcdf019059b..8c92a46a975 100644
--- a/doc/api/license.md
+++ b/doc/api/license.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# License **(CORE ONLY)**
To interact with license endpoints, you need to authenticate yourself as an
diff --git a/doc/api/lint.md b/doc/api/lint.md
index c82e0845f99..24de4a24ff1 100644
--- a/doc/api/lint.md
+++ b/doc/api/lint.md
@@ -36,7 +36,20 @@ Example responses:
```json
{
"status": "valid",
- "errors": []
+ "errors": [],
+ "warnings": []
+ }
+ ```
+
+- Valid content with warnings:
+
+ ```json
+ {
+ "status": "valid",
+ "errors": [],
+ "warnings": ["jobs:job 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"]
}
```
@@ -47,7 +60,8 @@ Example responses:
"status": "invalid",
"errors": [
"variables config should be a hash of key value pairs"
- ]
+ ],
+ "warnings": []
}
```
@@ -99,6 +113,54 @@ Example response:
}
```
+## Validate a CI YAML configuration with a namespace
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/231352) in GitLab 13.6.
+
+Checks if CI/CD YAML configuration is valid. This endpoint has namespace
+specific context.
+
+```plaintext
+POST /projects/:id/ci/lint
+```
+
+| Attribute | Type | Required | Description |
+| ---------- | ------- | -------- | -------- |
+| `content` | string | yes | The CI/CD configuration content. |
+| `dry_run` | boolean | no | Run [pipeline creation simulation](../ci/lint.md#pipeline-simulation), or only do static check. This is false by default. |
+
+Example request:
+
+```shell
+curl --header "Content-Type: application/json" "https://gitlab.example.com/api/v4/projects/:id/ci/lint" --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
+```
+
+Example responses:
+
+- Valid configuration:
+
+ ```json
+ {
+ "valid": true,
+ "merged_yaml": "---\n:test_job:\n :script: echo 1\n",
+ "errors": [],
+ "warnings": []
+ }
+ ```
+
+- Invalid configuration:
+
+ ```json
+ {
+ "valid": false,
+ "merged_yaml": "---\n:test_job:\n :script: echo 1\n",
+ "errors": [
+ "jobs config should contain at least one visible job"
+ ],
+ "warnings": []
+ }
+ ```
+
## Validate a project's CI configuration
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/231352) in GitLab 13.5.
diff --git a/doc/api/managed_licenses.md b/doc/api/managed_licenses.md
index 984cfa92d3a..f7f6fbfbc47 100644
--- a/doc/api/managed_licenses.md
+++ b/doc/api/managed_licenses.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Managed Licenses API **(ULTIMATE)**
## List managed licenses
diff --git a/doc/api/members.md b/doc/api/members.md
index 4440b70c512..d616dfdd85c 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Group and project members API
## Valid access levels
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 194f48c6e84..44c59fd497b 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -55,10 +55,10 @@ Parameters:
| `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) |
| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) |
-| `created_after` | datetime | no | Return merge requests created on or after the given time |
-| `created_before` | datetime | no | Return merge requests created on or before the given time |
-| `updated_after` | datetime | no | Return merge requests updated on or after the given time |
-| `updated_before` | datetime | no | Return merge requests updated on or before the given time |
+| `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `created_before` | datetime | no | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_after` | datetime | no | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_before` | datetime | no | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead. |
| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`
| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10)_ | |
@@ -72,9 +72,9 @@ Parameters:
| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests |
| `not` | Hash | no | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `my_reaction_emoji` |
-| `environment` | string | no | Returns merge requests deployed to the given environment
-| `deployed_before` | datetime | no | Return merge requests deployed before the given date/time
-| `deployed_after` | datetime | no | Return merge requests deployed after the given date/time
+| `environment` | string | no | Returns merge requests deployed to the given environment. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `deployed_before` | datetime | no | Return merge requests deployed before the given date/time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `deployed_after` | datetime | no | Return merge requests deployed after the given date/time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
NOTE: **Note:**
[Starting in GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890),
@@ -246,10 +246,10 @@ Parameters:
| `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) |
| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) |
-| `created_after` | datetime | no | Return merge requests created on or after the given time |
-| `created_before` | datetime | no | Return merge requests created on or before the given time |
-| `updated_after` | datetime | no | Return merge requests updated on or after the given time |
-| `updated_before` | datetime | no | Return merge requests updated on or before the given time |
+| `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `created_before` | datetime | no | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_after` | datetime | no | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_before` | datetime | no | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5. [Changed to snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) in GitLab 11.0)_ |
| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5)_
| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10)_ | |
@@ -410,10 +410,10 @@ Parameters:
| `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)|
| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) |
-| `created_after` | datetime | no | Return merge requests created on or after the given time |
-| `created_before` | datetime | no | Return merge requests created on or before the given time |
-| `updated_after` | datetime | no | Return merge requests updated on or after the given time |
-| `updated_before` | datetime | no | Return merge requests updated on or before the given time |
+| `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `created_before` | datetime | no | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_after` | datetime | no | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_before` | datetime | no | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> |
| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5)_
| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10)_ | |
@@ -787,10 +787,17 @@ Shows information about the merge request including its files and changes.
GET /projects/:id/merge_requests/:merge_request_iid/changes
```
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46190) in GitLab 13.6,
+diffs associated with the set of changes will have the same size limitations applied as other diffs
+returned by the API or viewed via the UI. When these limits impact the results, the `overflow`
+field will contain a value of `true`. Diff data without these limits applied can be retrieved by
+adding the `access_raw_diffs` parameter, however, it will be slower and more resource-intensive.
+
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - The internal ID of the merge request
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user.
+- `merge_request_iid` (required) - The internal ID of the merge request.
+- `access_raw_diffs` (optional) - Retrieve change diffs without size limitations.
```json
{
@@ -884,7 +891,8 @@ Parameters:
"renamed_file": false,
"deleted_file": false
}
- ]
+ ],
+ "overflow": false
}
```
@@ -2089,10 +2097,10 @@ the `approvals_before_merge` parameter:
}
```
-## Create a to do
+## Create a to-do item
-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,
+Manually creates a to-do item for the current user on a merge request.
+If there already exists a to-do item for the user on that merge request,
status code `304` is returned.
```plaintext
@@ -2464,4 +2472,4 @@ For approvals, please see [Merge Request Approvals](merge_request_approvals.md)
## List merge request state events
To track which state was set, who did it, and when it happened, check out
-[Resource state events API](./resource_state_events.md#merge-requests).
+[Resource state events API](resource_state_events.md#merge-requests).
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index 7b26dbadad4..161b3b81499 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Project milestones API
This page describes the project milestones API.
-There's a separate [group milestones API](./group_milestones.md) page.
+There's a separate [group milestones API](group_milestones.md) page.
## List project milestones
diff --git a/doc/api/namespaces.md b/doc/api/namespaces.md
index 0792c6d4a3b..f61400dfddb 100644
--- a/doc/api/namespaces.md
+++ b/doc/api/namespaces.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Namespaces API
Usernames and groupnames fall under a special category called namespaces.
diff --git a/doc/api/notes.md b/doc/api/notes.md
index aaff28757bb..70aa4923b97 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Notes API
Notes are comments on:
diff --git a/doc/api/notification_settings.md b/doc/api/notification_settings.md
index 8442e371a56..cbe5aa46a5d 100644
--- a/doc/api/notification_settings.md
+++ b/doc/api/notification_settings.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Notification settings API
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5632) in GitLab 8.12.
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index 5fbb7913ff4..b1c81ff20b6 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -1,3 +1,10 @@
+---
+type: reference, howto
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technica l-writing/#designated-technical-writers
+---
+
# GitLab as an OAuth2 provider
This document covers using the [OAuth2](https://oauth.net/2/) protocol to allow
@@ -28,12 +35,24 @@ During registration, by enabling proper scopes, you can limit the range of
resources which the `application` can access. Upon creation, you'll obtain the
`application` credentials: _Application ID_ and _Client Secret_ - **keep them secure**.
-CAUTION: **Important:**
-OAuth specification advises sending the `state` parameter with each request to
-`/oauth/authorize`. We highly recommended sending a unique value with each request
-and validate it against the one in the redirect request. This is important in
-order to prevent [CSRF attacks](https://wiki.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)).
-The `state` parameter really should have been a requirement in the standard!
+### Prevent CSRF attacks
+
+To [protect redirect-based flows](https://tools.ietf.org/id/draft-ietf-oauth-security-topics-13.html#rec_redirect),
+the OAuth specification recommends the use of "One-time use CSRF tokens carried in the state
+parameter, which are securely bound to the user agent", with each request to the
+`/oauth/authorize` endpoint. This can prevent
+[CSRF attacks](https://wiki.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)).
+
+### Use HTTPS in production
+
+For production, please use HTTPS for your `redirect_uri`.
+For development, GitLab allows insecure HTTP redirect URIs.
+
+As OAuth2 bases its security entirely on the transport layer, you should not use unprotected
+URIs. For more information, see the [OAuth 2.0 RFC](https://tools.ietf.org/html/rfc6749#section-3.1.2.1)
+and the [OAuth 2.0 Threat Model RFC](https://tools.ietf.org/html/rfc6819#section-4.4.2.1).
+These factors are particularly important when using the
+[Implicit grant flow](#implicit-grant-flow), where actual credentials are included in the `redirect_uri`.
In the following sections you will find detailed instructions on how to obtain
authorization with each flow.
diff --git a/doc/api/packages.md b/doc/api/packages.md
index d4e69b9bc66..8124b081506 100644
--- a/doc/api/packages.md
+++ b/doc/api/packages.md
@@ -93,9 +93,10 @@ GET /groups/:id/packages
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/packages?exclude_subgroups=true"
```
-CAUTION: **Deprecation:**
-> The `build_info` attribute in the response is deprecated in favour of `pipeline`.
-> Introduced [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040).
+> **Deprecation:**
+>
+> The `pipeline` attribute in the response is deprecated in favor of `pipelines`, which was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44348) in GitLab 13.6. Both are available until 13.7.
+> The `build_info` attribute in the response is deprecated in favor of `pipeline`, which was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040) in GitLab 12.10.
Example response:
@@ -111,19 +112,21 @@ Example response:
"delete_api_path": "/namespace1/project1/-/packages/1"
},
"created_at": "2019-11-27T03:37:38.711Z",
- "pipeline": {
- "id": 123,
- "status": "pending",
- "ref": "new-pipeline",
- "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "web_url": "https://example.com/foo/bar/pipelines/47",
- "created_at": "2016-08-11T11:28:34.085Z",
- "updated_at": "2016-08-11T11:32:35.169Z",
- "user": {
- "name": "Administrator",
- "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
+ "pipelines": [
+ {
+ "id": 123,
+ "status": "pending",
+ "ref": "new-pipeline",
+ "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
+ "web_url": "https://example.com/foo/bar/pipelines/47",
+ "created_at": "2016-08-11T11:28:34.085Z",
+ "updated_at": "2016-08-11T11:32:35.169Z",
+ "user": {
+ "name": "Administrator",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
+ }
}
- }
+ ]
},
{
"id": 2,
@@ -135,19 +138,21 @@ Example response:
"delete_api_path": "/namespace1/project1/-/packages/1"
},
"created_at": "2019-11-27T03:37:38.711Z",
- "pipeline": {
- "id": 123,
- "status": "pending",
- "ref": "new-pipeline",
- "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "web_url": "https://example.com/foo/bar/pipelines/47",
- "created_at": "2016-08-11T11:28:34.085Z",
- "updated_at": "2016-08-11T11:32:35.169Z",
- "user": {
- "name": "Administrator",
- "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
+ "pipelines": [
+ {
+ "id": 123,
+ "status": "pending",
+ "ref": "new-pipeline",
+ "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
+ "web_url": "https://example.com/foo/bar/pipelines/47",
+ "created_at": "2016-08-11T11:28:34.085Z",
+ "updated_at": "2016-08-11T11:32:35.169Z",
+ "user": {
+ "name": "Administrator",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
+ }
}
- }
+ ]
}
]
```
@@ -178,9 +183,10 @@ GET /projects/:id/packages/:package_id
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/packages/:package_id"
```
-CAUTION: **Deprecation:**
-> The `build_info` attribute in the response is deprecated in favour of `pipeline`.
-> Introduced [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040).
+> **Deprecation:**
+>
+> The `pipeline` attribute in the response is deprecated in favor of `pipelines`, which was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44348) in GitLab 13.6. Both are available until 13.7.
+> The `build_info` attribute in the response is deprecated in favor of `pipeline`, which was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040) in GitLab 12.10.
Example response:
@@ -195,37 +201,41 @@ Example response:
"delete_api_path": "/namespace1/project1/-/packages/1"
},
"created_at": "2019-11-27T03:37:38.711Z",
- "pipeline": {
- "id": 123,
- "status": "pending",
- "ref": "new-pipeline",
- "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "web_url": "https://example.com/foo/bar/pipelines/47",
- "created_at": "2016-08-11T11:28:34.085Z",
- "updated_at": "2016-08-11T11:32:35.169Z",
- "user": {
- "name": "Administrator",
- "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
+ "pipelines": [
+ {
+ "id": 123,
+ "status": "pending",
+ "ref": "new-pipeline",
+ "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
+ "web_url": "https://example.com/foo/bar/pipelines/47",
+ "created_at": "2016-08-11T11:28:34.085Z",
+ "updated_at": "2016-08-11T11:32:35.169Z",
+ "user": {
+ "name": "Administrator",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
+ }
}
- },
+ ],
"versions": [
{
"id":2,
"version":"2.0-SNAPSHOT",
"created_at":"2020-04-28T04:42:11.573Z",
- "pipeline": {
- "id": 234,
- "status": "pending",
- "ref": "new-pipeline",
- "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "web_url": "https://example.com/foo/bar/pipelines/58",
- "created_at": "2016-08-11T11:28:34.085Z",
- "updated_at": "2016-08-11T11:32:35.169Z",
- "user": {
- "name": "Administrator",
- "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
+ "pipelines": [
+ {
+ "id": 234,
+ "status": "pending",
+ "ref": "new-pipeline",
+ "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
+ "web_url": "https://example.com/foo/bar/pipelines/58",
+ "created_at": "2016-08-11T11:28:34.085Z",
+ "updated_at": "2016-08-11T11:32:35.169Z",
+ "user": {
+ "name": "Administrator",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
+ }
}
- }
+ ]
}
]
}
@@ -266,7 +276,22 @@ Example response:
"file_name": "my-app-1.5-20181107.152550-1.jar",
"size": 2421,
"file_md5": "58e6a45a629910c6ff99145a688971ac",
- "file_sha1": "ebd193463d3915d7e22219f52740056dfd26cbfe"
+ "file_sha1": "ebd193463d3915d7e22219f52740056dfd26cbfe",
+ "pipelines": [
+ {
+ "id": 123,
+ "status": "pending",
+ "ref": "new-pipeline",
+ "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
+ "web_url": "https://example.com/foo/bar/pipelines/47",
+ "created_at": "2016-08-11T11:28:34.085Z",
+ "updated_at": "2016-08-11T11:32:35.169Z",
+ "user": {
+ "name": "Administrator",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
+ }
+ }
+ ]
},
{
"id": 26,
diff --git a/doc/api/personal_access_tokens.md b/doc/api/personal_access_tokens.md
index 43310570fe8..f7cbaeba438 100644
--- a/doc/api/personal_access_tokens.md
+++ b/doc/api/personal_access_tokens.md
@@ -1,10 +1,17 @@
-# Personal access tokens API **(ULTIMATE)**
+---
+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
+---
+
+# Personal access tokens API
You can read more about [personal access tokens](../user/profile/personal_access_tokens.md#personal-access-tokens).
## List personal access tokens
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227264) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227264) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/270200) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.6.
Get a list of personal access tokens.
@@ -86,3 +93,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
- `204: No Content` if successfully revoked.
- `400 Bad Request` if not revoked successfully.
+
+## Create a personal access token (admin only)
+
+See the [Users API documentation](users.md#create-a-personal-access-token-admin-only) for information on creating a personal access token.
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index 95a7787e029..145a0a5ab7e 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -39,8 +39,8 @@ GET /projects/:id/pipelines
| `yaml_errors`| boolean | no | Returns pipelines with invalid configurations |
| `name`| string | no | The name of the user who triggered pipelines |
| `username`| string | no | The username of the user who triggered pipelines |
-| `updated_after` | datetime | no | Return pipelines updated after the specified date. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
-| `updated_before` | datetime | no | Return pipelines updated before the specified date. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
+| `updated_after` | datetime | no | Return pipelines updated after the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
+| `updated_before` | datetime | no | Return pipelines updated before the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
| `order_by`| string | no | Order pipelines by `id`, `status`, `ref`, `updated_at` or `user_id` (default: `id`) |
| `sort` | string | no | Sort pipelines in `asc` or `desc` order (default: `desc`) |
diff --git a/doc/api/project_repository_storage_moves.md b/doc/api/project_repository_storage_moves.md
index b490b6235b1..c1ba421e73e 100644
--- a/doc/api/project_repository_storage_moves.md
+++ b/doc/api/project_repository_storage_moves.md
@@ -9,7 +9,7 @@ type: reference
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31285) in GitLab 13.0.
-Project repositories can be moved between storages. This can be useful when
+Project repositories including wiki and design 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.
@@ -22,10 +22,19 @@ of `state` are:
- `finished`
- `failed`
- `replicated`
-- `cleanup_failed`
+- `cleanup failed`
+
+To ensure data integrity, projects are put in a temporary read-only state for the
+duration of the move. During this time, users receive a `The repository is temporarily
+read-only. Please try again later.` message if they try to push new commits.
This API requires you to [authenticate yourself](README.md#authentication) as an administrator.
+## Limitations
+
+- The repositories associated with snippets [can't be moved with the API](https://gitlab.com/groups/gitlab-org/-/epics/3393).
+- Group-level wikis [can't be moved with the API](https://gitlab.com/gitlab-org/gitlab/-/issues/219003).
+
## Retrieve all project repository storage moves
```plaintext
@@ -185,6 +194,14 @@ Example response:
## Schedule a repository storage move for a project
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34119) in GitLab 13.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/2618) in GitLab 13.3, original repository is automatically removed after successful move and integrity check.
+
+CAUTION: **Caution:**
+Before GitLab 13.3, a repository move worked more like a repository copy as the
+original repository was not deleted from the original storage disk location and
+had to be manually cleaned up.
+
```plaintext
POST /projects/:project_id/repository_storage_moves
```
@@ -194,12 +211,12 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `project_id` | integer | yes | ID of the project |
-| `destination_storage_name` | string | no | Name of the destination storage shard. If not provided the storage will be selected automatically. |
+| `destination_storage_name` | string | no | Name of the destination storage shard. In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitaly/-/issues/3209), the storage is selected automatically if not provided |
Example request:
```shell
-curl --request POST --header "PRIVATE_TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
--data '{"destination_storage_name":"storage2"}' "https://gitlab.example.com/api/v4/projects/1/repository_storage_moves"
```
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index cc8bb20b003..7955050e716 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -17,7 +17,7 @@ Constants for snippet visibility levels are:
| visibility | Description |
| ---------- | ----------- |
| `private` | The snippet is visible only the snippet creator |
-| `internal` | The snippet is visible for any logged in user |
+| `internal` | The snippet is visible for any logged in user except [external users](../user/permissions.md#external-users) |
| `public` | The snippet can be accessed without any authentication |
NOTE: **Note:**
diff --git a/doc/api/projects.md b/doc/api/projects.md
index f6ed905cda1..1c162e0bbd3 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -13,62 +13,61 @@ This is determined by the `visibility` field in the project.
Values for the project visibility level are:
-- `private`:
- Project access must be granted explicitly for each user.
-- `internal`:
- The project can be cloned by any logged in user.
-- `public`:
- The project can be accessed without any authentication.
+- `private`: project access must be granted explicitly for each user.
+- `internal`: the project can be cloned by any signed-in user except [external users](../user/permissions.md#external-users).
+- `public`: the project can be accessed without any authentication.
## Project merge method
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.
-- `rebase_merge`:
- A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible.
- This way you could make sure that if this merge request would build, after merging to target branch it would also build.
-- `ff`:
- No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.
+- `merge`: a merge commit is created for every merge, and merging is allowed if
+ there are no conflicts.
+- `rebase_merge`: a merge commit is created for every merge, but merging is only
+ allowed if fast-forward merge is possible. This way you could make sure that
+ if this merge request would build, after merging to target branch it would
+ also build.
+- `ff`: no merge commits are created and all merges are fast-forwarded, which
+ means that merging is only allowed if the branch could be fast-forwarded.
## List all projects
Get a list of all visible projects across GitLab for the authenticated user.
-When accessed without authentication, only public projects with "simple" fields are returned.
+When accessed without authentication, only public projects with _simple_ fields
+are returned.
```plaintext
GET /projects
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `archived` | boolean | no | Limit by archived status |
-| `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` |
-| `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. |
-| `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 |
-
-NOTE: **Note:**
-This endpoint supports [keyset pagination](README.md#keyset-based-pagination) for selected `order_by` options.
+| Attribute | Type | Required | Description |
+|--------------------------------------------|----------|------------------------|-------------|
+| `archived` | boolean | **{dotted-circle}** No | Limit by archived status. |
+| `id_after` | integer | **{dotted-circle}** No | Limit results to projects with IDs greater than the specified ID. |
+| `id_before` | integer | **{dotted-circle}** No | Limit results to projects with IDs less than the specified ID. |
+| `last_activity_after` | datetime | **{dotted-circle}** No | Limit results to projects with last_activity after specified time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
+| `last_activity_before` | datetime | **{dotted-circle}** No | Limit results to projects with last_activity before specified time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
+| `membership` | boolean | **{dotted-circle}** No | Limit by projects that the current user is a member of. |
+| `min_access_level` | integer | **{dotted-circle}** No | Limit by current user minimal [access level](members.md#valid-access-levels). |
+| `order_by` | string | **{dotted-circle}** No | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. `repository_size`, `storage_size`, or `wiki_size` fields are only allowed for admins. Default is `created_at`. |
+| `owned` | boolean | **{dotted-circle}** No | Limit by projects explicitly owned by the current user. |
+| `repository_checksum_failed` **(PREMIUM)** | boolean | **{dotted-circle}** No | Limit projects where the repository checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2). |
+| `repository_storage` | string | **{dotted-circle}** No | Limit results to projects stored on `repository_storage`. _(admins only)_ |
+| `search_namespaces` | boolean | **{dotted-circle}** No | Include ancestor namespaces when matching search criteria. Default is `false`. |
+| `search` | string | **{dotted-circle}** No | Return list of projects matching the search criteria. |
+| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
+| `sort` | string | **{dotted-circle}** No | Return projects sorted in `asc` or `desc` order. Default is `desc`. |
+| `starred` | boolean | **{dotted-circle}** No | Limit by projects starred by the current user. |
+| `statistics` | boolean | **{dotted-circle}** No | Include project statistics. |
+| `visibility` | string | **{dotted-circle}** No | Limit by visibility `public`, `internal`, or `private`. |
+| `wiki_checksum_failed` **(PREMIUM)** | boolean | **{dotted-circle}** No | Limit projects where the wiki checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2). |
+| `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(admins only)_ |
+| `with_issues_enabled` | boolean | **{dotted-circle}** No | Limit by enabled issues feature. |
+| `with_merge_requests_enabled` | boolean | **{dotted-circle}** No | Limit by enabled merge requests feature. |
+| `with_programming_language` | string | **{dotted-circle}** No | Limit by projects which use the given programming language. |
+
+This endpoint supports [keyset pagination](README.md#keyset-based-pagination)
+for selected `order_by` options.
When `simple=true` or the user is unauthenticated this returns something like:
@@ -297,11 +296,12 @@ 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 of 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/) can also see
-the `approvals_before_merge` parameter:
+Users of GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/)
+can also see the `approvals_before_merge` parameter:
```json
[
@@ -322,44 +322,45 @@ GET /projects?custom_attributes[key]=value&custom_attributes[other_key]=other_va
### Pagination limits
-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) is required to retrieve projects
-beyond this limit.
+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) is required to retrieve
+projects beyond this limit.
-Note that keyset pagination only supports `order_by=id`. Other sorting options are not available.
+Keyset pagination supports only `order_by=id`. Other sorting options aren't available.
## List user projects
-Get a list of visible projects owned by the given user. When accessed without authentication, only public projects are returned.
+Get a list of visible projects owned by the given user. When accessed without
+authentication, only public projects are returned.
+
+This endpoint supports [keyset pagination](README.md#keyset-based-pagination)
+for selected `order_by` options.
```plaintext
GET /users/:user_id/projects
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `user_id` | string | yes | The ID or username of the user |
-| `archived` | boolean | no | Limit by archived status |
-| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
-| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. 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 |
-| `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 |
-| `starred` | boolean | no | Limit by projects starred by the current user |
-| `statistics` | boolean | no | Include project statistics |
-| `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 |
-| `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 |
-
-NOTE: **Note:**
-This endpoint supports [keyset pagination](README.md#keyset-based-pagination) for selected `order_by` options.
+| Attribute | Type | Required | Description |
+|-------------------------------|---------|------------------------|-------------|
+| `archived` | boolean | **{dotted-circle}** No | Limit by archived status. |
+| `id_after` | integer | **{dotted-circle}** No | Limit results to projects with IDs greater than the specified ID. |
+| `id_before` | integer | **{dotted-circle}** No | Limit results to projects with IDs less than the specified ID. |
+| `membership` | boolean | **{dotted-circle}** No | Limit by projects that the current user is a member of. |
+| `min_access_level` | integer | **{dotted-circle}** No | Limit by current user minimal [access level](members.md#valid-access-levels). |
+| `order_by` | string | **{dotted-circle}** No | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at`. |
+| `owned` | boolean | **{dotted-circle}** No | Limit by projects explicitly owned by the current user. |
+| `search` | string | **{dotted-circle}** No | Return list of projects matching the search criteria. |
+| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
+| `sort` | string | **{dotted-circle}** No | Return projects sorted in `asc` or `desc` order. Default is `desc`. |
+| `starred` | boolean | **{dotted-circle}** No | Limit by projects starred by the current user. |
+| `statistics` | boolean | **{dotted-circle}** No | Include project statistics. |
+| `user_id` | string | **{check-circle}** Yes | The ID or username of the user. |
+| `visibility` | string | **{dotted-circle}** No | Limit by visibility `public`, `internal`, or `private`. |
+| `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(admins only)_ |
+| `with_issues_enabled` | boolean | **{dotted-circle}** No | Limit by enabled issues feature. |
+| `with_merge_requests_enabled` | boolean | **{dotted-circle}** No | Limit by enabled merge requests feature. |
+| `with_programming_language` | string | **{dotted-circle}** No | Limit by projects which use the given programming language. |
```json
[
@@ -554,29 +555,30 @@ This endpoint supports [keyset pagination](README.md#keyset-based-pagination) fo
## List projects starred by a user
-Get a list of visible projects owned by the given user. When accessed without authentication, only public projects are returned.
+Get a list of visible projects owned by the given user. When accessed without
+authentication, only public projects are returned.
```plaintext
GET /users/:user_id/starred_projects
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `user_id` | string | yes | The ID or username of the user. |
-| `archived` | boolean | no | Limit by archived status. |
-| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private`. |
-| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. 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. |
-| `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. |
-| `starred` | boolean | no | Limit by projects starred by the current user. |
-| `statistics` | boolean | no | Include project statistics. |
-| `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. |
-| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md#valid-access-levels). |
+| Attribute | Type | Required | Description |
+|-------------------------------|---------|------------------------|-------------|
+| `archived` | boolean | **{dotted-circle}** No | Limit by archived status. |
+| `membership` | boolean | **{dotted-circle}** No | Limit by projects that the current user is a member of. |
+| `min_access_level` | integer | **{dotted-circle}** No | Limit by current user minimal [access level](members.md#valid-access-levels). |
+| `order_by` | string | **{dotted-circle}** No | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at`. |
+| `owned` | boolean | **{dotted-circle}** No | Limit by projects explicitly owned by the current user. |
+| `search` | string | **{dotted-circle}** No | Return list of projects matching the search criteria. |
+| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned.. |
+| `sort` | string | **{dotted-circle}** No | Return projects sorted in `asc` or `desc` order. Default is `desc`. |
+| `starred` | boolean | **{dotted-circle}** No | Limit by projects starred by the current user. |
+| `statistics` | boolean | **{dotted-circle}** No | Include project statistics. |
+| `user_id` | string | **{check-circle}** Yes | The ID or username of the user. |
+| `visibility` | string | **{dotted-circle}** No | Limit by visibility `public`, `internal`, or `private`. |
+| `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(admins only)_ |
+| `with_issues_enabled` | boolean | **{dotted-circle}** No | Limit by enabled issues feature. |
+| `with_merge_requests_enabled` | boolean | **{dotted-circle}** No | Limit by enabled merge requests feature. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/users/5/starred_projects"
@@ -772,12 +774,12 @@ the project is publicly accessible.
GET /projects/:id
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `statistics` | boolean | no | Include project statistics |
-| `license` | boolean | no | Include project license data |
-| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
+| Attribute | Type | Required | Description |
+|--------------------------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `license` | boolean | **{dotted-circle}** No | Include project license data. |
+| `statistics` | boolean | **{dotted-circle}** No | Include project statistics. |
+| `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(admins only)_ |
```json
{
@@ -924,8 +926,8 @@ GET /projects/:id
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
-the `approvals_before_merge` parameter:
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/)
+can also see the `approvals_before_merge` parameter:
```json
{
@@ -936,7 +938,9 @@ 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.
+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 appears in the response.
@@ -995,11 +999,11 @@ Get the users list of a project.
GET /projects/:id/users
```
-| Attribute | Type | Required | Description |
-| ------------ | ------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `search` | string | no | Search for specific users |
-| `skip_users` | integer array | no | Filter out users with the specified IDs |
+| Attribute | Type | Required | Description |
+|--------------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `search` | string | **{dotted-circle}** No | Search for specific users. |
+| `skip_users` | integer array | **{dotted-circle}** No | Filter out users with the specified IDs. |
```json
[
@@ -1024,223 +1028,223 @@ GET /projects/:id/users
## Get project events
-Please refer to the [Events API documentation](events.md#list-a-projects-visible-events).
+Refer to the [Events API documentation](events.md#list-a-projects-visible-events).
## Create project
Creates a new project owned by the authenticated user.
+If your HTTP repository isn't publicly accessible, add authentication information
+to the URL `https://username:password@gitlab.company.com/group/project.git`,
+where `password` is a public access key with the `api` scope enabled.
+
```plaintext
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 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 |
-| `issues_enabled` | boolean | no | (deprecated) Enable issues for this project. Use `issues_access_level` instead |
-| `merge_requests_enabled` | boolean | no | (deprecated) Enable merge requests for this project. Use `merge_requests_access_level` instead |
-| `jobs_enabled` | boolean | no | (deprecated) Enable jobs for this project. Use `builds_access_level` instead |
-| `wiki_enabled` | boolean | no | (deprecated) Enable wiki for this project. Use `wiki_access_level` instead |
-| `snippets_enabled` | boolean | no | (deprecated) Enable snippets for this project. Use `snippets_access_level` instead |
-| `issues_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `repository_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `merge_requests_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `forking_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `builds_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `wiki_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `snippets_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `pages_access_level` | string | no | One of `disabled`, `private`, `enabled` or `public` |
-| `emails_disabled` | boolean | no | Disable email notifications |
-| `show_default_award_emojis` | boolean | no | Show default award emojis |
-| `resolve_outdated_diff_discussions` | boolean | no | Automatically resolve merge request diffs discussions on lines changed with a push |
-| `container_registry_enabled` | boolean | no | Enable container registry for this project |
-| `container_expiration_policy_attributes` | hash | no | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (string), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean) |
-| `shared_runners_enabled` | boolean | no | Enable shared runners for this project |
-| `visibility` | string | no | See [project visibility level](#project-visibility-level) |
-| `import_url` | string | no | URL to import repository from |
-| `public_builds` | boolean | no | If `true`, jobs can be viewed by non-project-members |
-| `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs |
-| `allow_merge_on_skipped_pipeline` | boolean | no | Set whether or not merge requests can be merged with skipped jobs |
-| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved |
-| `merge_method` | string | no | Set the [merge method](#project-merge-method) used |
-| `autoclose_referenced_issues` | boolean | no | Set whether auto-closing referenced issues on default branch |
-| `remove_source_branch_after_merge` | boolean | no | Enable `Delete source branch` option by default for all new merge requests |
-| `lfs_enabled` | boolean | no | Enable LFS |
-| `request_access_enabled` | boolean | no | Allow users to request member access |
-| `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project |
-| `avatar` | mixed | no | Image file for avatar of the project |
-| `printing_merge_request_link_enabled` | boolean | no | Show link to create/view merge request when pushing from the command line |
-| `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` |
-| `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 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 |
-| `approvals_before_merge` | integer | no | **(STARTER)** How many approvers should approve merge requests by default |
-| `external_authorization_classification_label` | string | no | **(PREMIUM)** The classification label for the project |
-| `mirror` | boolean | no | **(STARTER)** Enables pull mirroring in a project |
-| `mirror_trigger_builds` | boolean | no | **(STARTER)** Pull mirroring triggers builds |
-| `initialize_with_readme` | boolean | no | `false` by default |
-| `template_name` | string | no | When used without `use_custom_template`, name of a [built-in project template](../gitlab-basics/create-project.md#built-in-templates). When used with `use_custom_template`, name of a custom project template |
-| `template_project_id` | integer | no | **(PREMIUM)** When used with `use_custom_template`, project ID of a custom project template. This is preferable to using `template_name` since `template_name` may be ambiguous. |
-| `use_custom_template` | boolean | no | **(PREMIUM)** Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template |
-| `group_with_project_templates_id` | integer | no | **(PREMIUM)** For group-level custom templates, specifies ID of group from which all the custom project templates are sourced. Leave empty for instance-level templates. Requires `use_custom_template` to be true |
-| `packages_enabled` | boolean | no | Enable or disable packages repository feature |
-
-NOTE: **Note:**
-If your HTTP repository is not publicly accessible,
-add authentication information to the URL: `https://username:password@gitlab.company.com/group/project.git`
-where `password` is a public access key with the `api` scope enabled.
+| Attribute | Type | Required | Description |
+|-------------------------------------------------------------|---------|------------------------|-------------|
+| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
+| `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
+| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
+| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). |
+| `auto_devops_enabled` | boolean | **{dotted-circle}** No | Enable Auto DevOps for this project. |
+| `autoclose_referenced_issues` | boolean | **{dotted-circle}** No | Set whether auto-closing referenced issues on default branch. |
+| `avatar` | mixed | **{dotted-circle}** No | Image file for avatar of the project. |
+| `build_coverage_regex` | string | **{dotted-circle}** No | Test coverage parsing. |
+| `build_git_strategy` | string | **{dotted-circle}** No | The Git strategy. Defaults to `fetch`. |
+| `build_timeout` | integer | **{dotted-circle}** No | The maximum amount of time in minutes that a job is able run (in seconds). |
+| `builds_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
+| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (string), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). |
+| `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. |
+| `default_branch` | string | **{dotted-circle}** No | `master` by default. |
+| `description` | string | **{dotted-circle}** No | Short project description. |
+| `emails_disabled` | boolean | **{dotted-circle}** No | Disable email notifications. |
+| `external_authorization_classification_label` **(PREMIUM)** | string | **{dotted-circle}** No | The classification label for the project. |
+| `forking_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `group_with_project_templates_id` **(PREMIUM)** | integer | **{dotted-circle}** No | For group-level custom templates, specifies ID of group from which all the custom project templates are sourced. Leave empty for instance-level templates. Requires `use_custom_template` to be true. |
+| `import_url` | string | **{dotted-circle}** No | URL to import repository from. |
+| `initialize_with_readme` | boolean | **{dotted-circle}** No | `false` by default. |
+| `issues_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `issues_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable issues for this project. Use `issues_access_level` instead. |
+| `jobs_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable jobs for this project. Use `builds_access_level` instead. |
+| `lfs_enabled` | boolean | **{dotted-circle}** No | Enable LFS. |
+| `merge_method` | string | **{dotted-circle}** No | Set the [merge method](#project-merge-method) used. |
+| `merge_requests_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `merge_requests_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable merge requests for this project. Use `merge_requests_access_level` instead. |
+| `mirror_trigger_builds` **(STARTER)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
+| `mirror` **(STARTER)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a project. |
+| `name` | string | **{check-circle}** Yes (if path isn't provided) | The name of the new project. Equals path if not provided. |
+| `namespace_id` | integer | **{dotted-circle}** No | Namespace for the new project (defaults to the current user's namespace). |
+| `only_allow_merge_if_all_discussions_are_resolved` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged when all the discussions are resolved. |
+| `only_allow_merge_if_pipeline_succeeds` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged with successful jobs. |
+| `packages_enabled` | boolean | **{dotted-circle}** No | Enable or disable packages repository feature. |
+| `pages_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled`, or `public`. |
+| `requirements_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled` or `public` |
+| `path` | string | **{check-circle}** Yes (if name isn't provided) | Repository name for new project. Generated based on name if not provided (generated as lowercase with dashes). |
+| `printing_merge_request_link_enabled` | boolean | **{dotted-circle}** No | Show link to create/view merge request when pushing from the command line. |
+| `public_builds` | boolean | **{dotted-circle}** No | If `true`, jobs can be viewed by non-project members. |
+| `remove_source_branch_after_merge` | boolean | **{dotted-circle}** No | Enable `Delete source branch` option by default for all new merge requests. |
+| `repository_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `repository_storage` | string | **{dotted-circle}** No | Which storage shard the repository is on. _(admins only)_ |
+| `request_access_enabled` | boolean | **{dotted-circle}** No | Allow users to request member access. |
+| `resolve_outdated_diff_discussions` | boolean | **{dotted-circle}** No | Automatically resolve merge request diffs discussions on lines changed with a push. |
+| `shared_runners_enabled` | boolean | **{dotted-circle}** No | Enable shared runners for this project. |
+| `show_default_award_emojis` | boolean | **{dotted-circle}** No | Show default award emojis. |
+| `snippets_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
+| `tag_list` | array | **{dotted-circle}** No | The list of tags for a project; put array of tags, that should be finally assigned to a project. |
+| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../gitlab-basics/create-project.md#built-in-templates). When used with `use_custom_template`, name of a custom project template. |
+| `template_project_id` **(PREMIUM)** | integer | **{dotted-circle}** No | When used with `use_custom_template`, project ID of a custom project template. This is preferable to using `template_name` since `template_name` may be ambiguous. |
+| `use_custom_template` **(PREMIUM)** | boolean | **{dotted-circle}** No | Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template. |
+| `visibility` | string | **{dotted-circle}** No | See [project visibility level](#project-visibility-level). |
+| `wiki_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `wiki_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable wiki for this project. Use `wiki_access_level` instead. |
## Create project for user
Creates a new project owned by the specified user. Available only for admins.
+If your HTTP repository isn't publicly accessible, add authentication information
+to the URL `https://username:password@gitlab.company.com/group/project.git`,
+where `password` is a public access key with the `api` scope enabled.
+
```plaintext
POST /projects/user/:user_id
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `user_id` | integer | yes | The user ID of the project owner |
-| `name` | string | yes | The name of the new project |
-| `path` | string | no | Custom repository name for new project. By default generated based on name |
-| `namespace_id` | integer | no | Namespace for the new project (defaults to the current user's namespace) |
-| `description` | string | no | Short project description |
-| `issues_enabled` | boolean | no | (deprecated) Enable issues for this project. Use `issues_access_level` instead |
-| `merge_requests_enabled` | boolean | no | (deprecated) Enable merge requests for this project. Use `merge_requests_access_level` instead |
-| `jobs_enabled` | boolean | no | (deprecated) Enable jobs for this project. Use `builds_access_level` instead |
-| `wiki_enabled` | boolean | no | (deprecated) Enable wiki for this project. Use `wiki_access_level` instead |
-| `snippets_enabled` | boolean | no | (deprecated) Enable snippets for this project. Use `snippets_access_level` instead |
-| `issues_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `repository_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `merge_requests_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `forking_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `builds_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `wiki_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `snippets_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `pages_access_level` | string | no | One of `disabled`, `private`, `enabled` or `public` |
-| `emails_disabled` | boolean | no | Disable email notifications |
-| `show_default_award_emojis` | boolean | no | Show default award emojis |
-| `resolve_outdated_diff_discussions` | boolean | no | Automatically resolve merge request diffs discussions on lines changed with a push |
-| `container_registry_enabled` | boolean | no | Enable container registry for this project |
-| `shared_runners_enabled` | boolean | no | Enable shared runners for this project |
-| `visibility` | string | no | See [project visibility level](#project-visibility-level) |
-| `import_url` | string | no | URL to import repository from |
-| `public_builds` | boolean | no | If `true`, jobs can be viewed by non-project-members |
-| `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs |
-| `allow_merge_on_skipped_pipeline` | boolean | no | Set whether or not merge requests can be merged with skipped jobs |
-| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved |
-| `merge_method` | string | no | Set the [merge method](#project-merge-method) used |
-| `autoclose_referenced_issues` | boolean | no | Set whether auto-closing referenced issues on default branch |
-| `suggestion_commit_message` | string | no | The commit message used to apply merge request suggestions |
-| `remove_source_branch_after_merge` | boolean | no | Enable `Delete source branch` option by default for all new merge requests |
-| `lfs_enabled` | boolean | no | Enable LFS |
-| `request_access_enabled` | boolean | no | Allow users to request member access |
-| `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project |
-| `avatar` | mixed | no | Image file for avatar of the project |
-| `printing_merge_request_link_enabled` | boolean | no | Show link to create/view merge request when pushing from the command line |
-| `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` |
-| `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 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 |
-| `approvals_before_merge` | integer | no | **(STARTER)** How many approvers should approve merge requests by default |
-| `external_authorization_classification_label` | string | no | **(PREMIUM)** The classification label for the project |
-| `mirror` | boolean | no | **(STARTER)** Enables pull mirroring in a project |
-| `mirror_trigger_builds` | boolean | no | **(STARTER)** Pull mirroring triggers builds |
-| `initialize_with_readme` | boolean | no | `false` by default |
-| `template_name` | string | no | When used without `use_custom_template`, name of a [built-in project template](../gitlab-basics/create-project.md#built-in-templates). When used with `use_custom_template`, name of a custom project template |
-| `use_custom_template` | boolean | no | **(PREMIUM)** Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template |
-| `group_with_project_templates_id` | integer | no | **(PREMIUM)** For group-level custom templates, specifies ID of group from which all the custom project templates are sourced. Leave empty for instance-level templates. Requires `use_custom_template` to be true |
-| `packages_enabled` | boolean | no | Enable or disable packages repository feature |
-
-NOTE: **Note:**
-If your HTTP repository is not publicly accessible,
-add authentication information to the URL: `https://username:password@gitlab.company.com/group/project.git`
-where `password` is a public access key with the `api` scope enabled.
+| Attribute | Type | Required | Description |
+|-------------------------------------------------------------|---------|------------------------|-------------|
+| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
+| `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
+| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
+| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). |
+| `auto_devops_enabled` | boolean | **{dotted-circle}** No | Enable Auto DevOps for this project. |
+| `autoclose_referenced_issues` | boolean | **{dotted-circle}** No | Set whether auto-closing referenced issues on default branch. |
+| `avatar` | mixed | **{dotted-circle}** No | Image file for avatar of the project. |
+| `build_coverage_regex` | string | **{dotted-circle}** No | Test coverage parsing. |
+| `build_git_strategy` | string | **{dotted-circle}** No | The Git strategy. Defaults to `fetch`. |
+| `build_timeout` | integer | **{dotted-circle}** No | The maximum amount of time in minutes that a job is able run (in seconds). |
+| `builds_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
+| `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. |
+| `description` | string | **{dotted-circle}** No | Short project description. |
+| `emails_disabled` | boolean | **{dotted-circle}** No | Disable email notifications. |
+| `external_authorization_classification_label` **(PREMIUM)** | string | **{dotted-circle}** No | The classification label for the project. |
+| `forking_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `group_with_project_templates_id` **(PREMIUM)** | integer | **{dotted-circle}** No | For group-level custom templates, specifies ID of group from which all the custom project templates are sourced. Leave empty for instance-level templates. Requires `use_custom_template` to be true. |
+| `import_url` | string | **{dotted-circle}** No | URL to import repository from. |
+| `initialize_with_readme` | boolean | **{dotted-circle}** No | `false` by default. |
+| `issues_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `issues_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable issues for this project. Use `issues_access_level` instead. |
+| `jobs_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable jobs for this project. Use `builds_access_level` instead. |
+| `lfs_enabled` | boolean | **{dotted-circle}** No | Enable LFS. |
+| `merge_method` | string | **{dotted-circle}** No | Set the [merge method](#project-merge-method) used. |
+| `merge_requests_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `merge_requests_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable merge requests for this project. Use `merge_requests_access_level` instead. |
+| `mirror_trigger_builds` **(STARTER)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
+| `mirror` **(STARTER)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a project. |
+| `name` | string | **{check-circle}** Yes | The name of the new project. |
+| `namespace_id` | integer | **{dotted-circle}** No | Namespace for the new project (defaults to the current user's namespace). |
+| `only_allow_merge_if_all_discussions_are_resolved` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged when all the discussions are resolved. |
+| `only_allow_merge_if_pipeline_succeeds` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged with successful jobs. |
+| `packages_enabled` | boolean | **{dotted-circle}** No | Enable or disable packages repository feature. |
+| `pages_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled`, or `public`. |
+| `requirements_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled` or `public` |
+| `path` | string | **{dotted-circle}** No | Custom repository name for new project. By default generated based on name. |
+| `printing_merge_request_link_enabled` | boolean | **{dotted-circle}** No | Show link to create/view merge request when pushing from the command line. |
+| `public_builds` | boolean | **{dotted-circle}** No | If `true`, jobs can be viewed by non-project-members. |
+| `remove_source_branch_after_merge` | boolean | **{dotted-circle}** No | Enable `Delete source branch` option by default for all new merge requests. |
+| `repository_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `repository_storage` | string | **{dotted-circle}** No | Which storage shard the repository is on. _(admins only)_ |
+| `request_access_enabled` | boolean | **{dotted-circle}** No | Allow users to request member access. |
+| `resolve_outdated_diff_discussions` | boolean | **{dotted-circle}** No | Automatically resolve merge request diffs discussions on lines changed with a push. |
+| `shared_runners_enabled` | boolean | **{dotted-circle}** No | Enable shared runners for this project. |
+| `show_default_award_emojis` | boolean | **{dotted-circle}** No | Show default award emojis. |
+| `snippets_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
+| `suggestion_commit_message` | string | **{dotted-circle}** No | The commit message used to apply merge request suggestions. |
+| `tag_list` | array | **{dotted-circle}** No | The list of tags for a project; put array of tags, that should be finally assigned to a project. |
+| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../gitlab-basics/create-project.md#built-in-templates). When used with `use_custom_template`, name of a custom project template. |
+| `use_custom_template` **(PREMIUM)** | boolean | **{dotted-circle}** No | Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template. |
+| `user_id` | integer | **{check-circle}** Yes | The user ID of the project owner. |
+| `visibility` | string | **{dotted-circle}** No | See [project visibility level](#project-visibility-level). |
+| `wiki_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `wiki_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable wiki for this project. Use `wiki_access_level` instead. |
## Edit project
Updates an existing project.
+If your HTTP repository isn't publicly accessible, add authentication information
+to the URL `https://username:password@gitlab.company.com/group/project.git`,
+where `password` is a public access key with the `api` scope enabled.
+
```plaintext
PUT /projects/:id
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `name` | string | no | The name of the project |
-| `path` | string | no | Custom repository name for the project. By default generated based on name |
-| `default_branch` | string | no | `master` by default |
-| `description` | string | no | Short project description |
-| `issues_enabled` | boolean | no | (deprecated) Enable issues for this project. Use `issues_access_level` instead |
-| `merge_requests_enabled` | boolean | no | (deprecated) Enable merge requests for this project. Use `merge_requests_access_level` instead |
-| `jobs_enabled` | boolean | no | (deprecated) Enable jobs for this project. Use `builds_access_level` instead |
-| `wiki_enabled` | boolean | no | (deprecated) Enable wiki for this project. Use `wiki_access_level` instead |
-| `snippets_enabled` | boolean | no | (deprecated) Enable snippets for this project. Use `snippets_access_level` instead |
-| `issues_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `repository_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `merge_requests_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `forking_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `builds_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `wiki_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `snippets_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `pages_access_level` | string | no | One of `disabled`, `private`, `enabled` or `public` |
-| `emails_disabled` | boolean | no | Disable email notifications |
-| `show_default_award_emojis` | boolean | no | Show default award emojis |
-| `resolve_outdated_diff_discussions` | boolean | no | Automatically resolve merge request diffs discussions on lines changed with a push |
-| `container_registry_enabled` | boolean | no | Enable container registry for this project |
-| `container_expiration_policy_attributes` | hash | no | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (string), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean) |
-| `shared_runners_enabled` | boolean | no | Enable shared runners for this project |
-| `visibility` | string | no | See [project visibility level](#project-visibility-level) |
-| `import_url` | string | no | URL to import repository from |
-| `public_builds` | boolean | no | If `true`, jobs can be viewed by non-project-members |
-| `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs |
-| `allow_merge_on_skipped_pipeline` | boolean | no | Set whether or not merge requests can be merged with skipped jobs |
-| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved |
-| `merge_method` | string | no | Set the [merge method](#project-merge-method) used |
-| `autoclose_referenced_issues` | boolean | no | Set whether auto-closing referenced issues on default branch |
-| `suggestion_commit_message` | string | no | The commit message used to apply merge request suggestions |
-| `remove_source_branch_after_merge` | boolean | no | Enable `Delete source branch` option by default for all new merge requests |
-| `lfs_enabled` | boolean | no | Enable LFS |
-| `request_access_enabled` | boolean | no | Allow users to request member access |
-| `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project |
-| `avatar` | mixed | no | Image file for avatar of the project |
-| `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` |
-| `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 configuration file |
-| `ci_default_git_depth` | integer | no | Default number of revisions for [shallow cloning](../ci/pipelines/settings.md#git-shallow-clone) |
-| `ci_forward_deployment_enabled` | boolean | no | When a new deployment job starts, [skip older deployment jobs](../ci/pipelines/settings.md#skip-outdated-deployment-jobs) that are still pending |
-| `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 |
-| `approvals_before_merge` | integer | no | **(STARTER)** How many approvers should approve merge request by default |
-| `external_authorization_classification_label` | string | no | **(PREMIUM)** The classification label for the project |
-| `mirror` | boolean | no | **(STARTER)** Enables pull mirroring in a project |
-| `mirror_user_id` | integer | no | **(STARTER)** User responsible for all the activity surrounding a pull mirror event. Can only be set by admins. |
-| `mirror_trigger_builds` | boolean | no | **(STARTER)** Pull mirroring triggers builds |
-| `only_mirror_protected_branches` | boolean | no | **(STARTER)** Only mirror protected branches |
-| `mirror_overwrites_diverged_branches` | boolean | no | **(STARTER)** Pull mirror overwrites diverged branches |
-| `packages_enabled` | boolean | no | Enable or disable packages repository feature |
-| `service_desk_enabled` | boolean | no | Enable or disable Service Desk feature |
-
-NOTE: **Note:**
-If your HTTP repository is not publicly accessible,
-add authentication information to the URL: `https://username:password@gitlab.company.com/group/project.git`
-where `password` is a public access key with the `api` scope enabled.
+| Attribute | Type | Required | Description |
+|-------------------------------------------------------------|----------------|------------------------|-------------|
+| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
+| `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge request by default. |
+| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
+| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual`, or `timed_incremental`). |
+| `auto_devops_enabled` | boolean | **{dotted-circle}** No | Enable Auto DevOps for this project. |
+| `autoclose_referenced_issues` | boolean | **{dotted-circle}** No | Set whether auto-closing referenced issues on default branch. |
+| `avatar` | mixed | **{dotted-circle}** No | Image file for avatar of the project. |
+| `build_coverage_regex` | string | **{dotted-circle}** No | Test coverage parsing. |
+| `build_git_strategy` | string | **{dotted-circle}** No | The Git strategy. Defaults to `fetch`. |
+| `build_timeout` | integer | **{dotted-circle}** No | The maximum amount of time in minutes that a job is able run (in seconds). |
+| `builds_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
+| `ci_default_git_depth` | integer | **{dotted-circle}** No | Default number of revisions for [shallow cloning](../ci/pipelines/settings.md#git-shallow-clone). |
+| `ci_forward_deployment_enabled` | boolean | **{dotted-circle}** No | When a new deployment job starts, [skip older deployment jobs](../ci/pipelines/settings.md#skip-outdated-deployment-jobs) that are still pending |
+| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (string), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). |
+| `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. |
+| `default_branch` | string | **{dotted-circle}** No | `master` by default. |
+| `description` | string | **{dotted-circle}** No | Short project description. |
+| `emails_disabled` | boolean | **{dotted-circle}** No | Disable email notifications. |
+| `external_authorization_classification_label` **(PREMIUM)** | string | **{dotted-circle}** No | The classification label for the project. |
+| `forking_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `import_url` | string | **{dotted-circle}** No | URL to import repository from. |
+| `issues_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `issues_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable issues for this project. Use `issues_access_level` instead. |
+| `jobs_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable jobs for this project. Use `builds_access_level` instead. |
+| `lfs_enabled` | boolean | **{dotted-circle}** No | Enable LFS. |
+| `merge_method` | string | **{dotted-circle}** No | Set the [merge method](#project-merge-method) used. |
+| `merge_requests_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `merge_requests_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable merge requests for this project. Use `merge_requests_access_level` instead. |
+| `mirror_overwrites_diverged_branches` **(STARTER)** | boolean | **{dotted-circle}** No | Pull mirror overwrites diverged branches. |
+| `mirror_trigger_builds` **(STARTER)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
+| `mirror_user_id` **(STARTER)** | integer | **{dotted-circle}** No | User responsible for all the activity surrounding a pull mirror event. _(admins only)_ |
+| `mirror` **(STARTER)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a project. |
+| `name` | string | **{dotted-circle}** No | The name of the project. |
+| `only_allow_merge_if_all_discussions_are_resolved` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged when all the discussions are resolved. |
+| `only_allow_merge_if_pipeline_succeeds` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged with successful jobs. |
+| `only_mirror_protected_branches` **(STARTER)** | boolean | **{dotted-circle}** No | Only mirror protected branches. |
+| `packages_enabled` | boolean | **{dotted-circle}** No | Enable or disable packages repository feature. |
+| `pages_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled`, or `public`. |
+| `requirements_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled` or `public` |
+| `path` | string | **{dotted-circle}** No | Custom repository name for the project. By default generated based on name. |
+| `public_builds` | boolean | **{dotted-circle}** No | If `true`, jobs can be viewed by non-project members. |
+| `remove_source_branch_after_merge` | boolean | **{dotted-circle}** No | Enable `Delete source branch` option by default for all new merge requests. |
+| `repository_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `repository_storage` | string | **{dotted-circle}** No | Which storage shard the repository is on. _(admins only)_ |
+| `request_access_enabled` | boolean | **{dotted-circle}** No | Allow users to request member access. |
+| `resolve_outdated_diff_discussions` | boolean | **{dotted-circle}** No | Automatically resolve merge request diffs discussions on lines changed with a push. |
+| `service_desk_enabled` | boolean | **{dotted-circle}** No | Enable or disable Service Desk feature. |
+| `shared_runners_enabled` | boolean | **{dotted-circle}** No | Enable shared runners for this project. |
+| `show_default_award_emojis` | boolean | **{dotted-circle}** No | Show default award emojis. |
+| `snippets_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
+| `suggestion_commit_message` | string | **{dotted-circle}** No | The commit message used to apply merge request suggestions. |
+| `tag_list` | array | **{dotted-circle}** No | The list of tags for a project; put array of tags, that should be finally assigned to a project. |
+| `visibility` | string | **{dotted-circle}** No | See [project visibility level](#project-visibility-level). |
+| `wiki_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
+| `wiki_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable wiki for this project. Use `wiki_access_level` instead. |
## Fork project
@@ -1254,42 +1258,43 @@ fork of the project has completed, query the `import_status` for the new project
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 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 |
+| Attribute | Type | Required | Description |
+|------------------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `name` | string | **{dotted-circle}** No | The name assigned to the resultant project after forking. |
+| `namespace_id` | integer | **{dotted-circle}** No | The ID of the namespace that the project is forked to. |
+| `namespace_path` | string | **{dotted-circle}** No | The path of the namespace that the project is forked to. |
+| `namespace` | integer/string | **{dotted-circle}** No | _(Deprecated)_ The ID or path of the namespace that the project is forked to. |
+| `path` | string | **{dotted-circle}** No | The path assigned to the resultant project after forking. |
## List Forks of a project
> Introduced in GitLab 10.1.
-List the projects accessible to the calling user that have an established, forked relationship with the specified project
+List the projects accessible to the calling user that have an established,
+forked relationship with the specified project
```plaintext
GET /projects/:id/forks
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `archived` | boolean | no | Limit by archived status |
-| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
-| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. 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 |
-| `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 |
-| `starred` | boolean | no | Limit by projects starred by the current user |
-| `statistics` | boolean | no | Include project statistics |
-| `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 |
-| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md#valid-access-levels) |
+| Attribute | Type | Required | Description |
+|-------------------------------|----------------|------------------------|-------------|
+| `archived` | boolean | **{dotted-circle}** No | Limit by archived status. |
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `membership` | boolean | **{dotted-circle}** No | Limit by projects that the current user is a member of. |
+| `min_access_level` | integer | **{dotted-circle}** No | Limit by current user minimal [access level](members.md#valid-access-levels). |
+| `order_by` | string | **{dotted-circle}** No | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at`. |
+| `owned` | boolean | **{dotted-circle}** No | Limit by projects explicitly owned by the current user. |
+| `search` | string | **{dotted-circle}** No | Return list of projects matching the search criteria. |
+| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
+| `sort` | string | **{dotted-circle}** No | Return projects sorted in `asc` or `desc` order. Default is `desc`. |
+| `starred` | boolean | **{dotted-circle}** No | Limit by projects starred by the current user. |
+| `statistics` | boolean | **{dotted-circle}** No | Include project statistics. |
+| `visibility` | string | **{dotted-circle}** No | Limit by visibility `public`, `internal`, or `private`. |
+| `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(admins only)_ |
+| `with_issues_enabled` | boolean | **{dotted-circle}** No | Limit by enabled issues feature. |
+| `with_merge_requests_enabled` | boolean | **{dotted-circle}** No | Limit by enabled merge requests feature. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/forks"
@@ -1366,15 +1371,16 @@ Example responses:
## Star a project
-Stars a given project. Returns status code `304` if the project is already starred.
+Stars a given project. Returns status code `304` if the project is already
+starred.
```plaintext
POST /projects/:id/star
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/star"
@@ -1463,9 +1469,9 @@ Unstars a given project. Returns status code `304` if the project is not starred
POST /projects/:id/unstar
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/unstar"
@@ -1554,10 +1560,10 @@ List the users who starred the specified project.
GET /projects/:id/starrers
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `search` | string | no | Search for specific users. |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `search` | string | **{dotted-circle}** No | Search for specific users. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/starrers"
@@ -1600,9 +1606,9 @@ Get languages used in a project with percentage value.
GET /projects/:id/languages
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/languages"
@@ -1621,16 +1627,17 @@ Example response:
## Archive a 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.
+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
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/archive"
@@ -1732,16 +1739,17 @@ Example response:
## Unarchive a 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.
+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
+doesn't change the project.
```plaintext
POST /projects/:id/unarchive
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/unarchive"
@@ -1845,25 +1853,27 @@ Example response:
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) 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).
+- Deletes a project including all associated resources (including issues and
+ merge requests).
+- From [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) on
+ [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers, group
+ 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).
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)
+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).
```plaintext
DELETE /projects/:id
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
## Restore project marked for deletion **(PREMIUM)**
@@ -1875,27 +1885,28 @@ Restores project marked for deletion.
POST /projects/:id/restore
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
## Upload a file
-Uploads a file to the specified project to be used in an issue or merge request description, or a comment.
+Uploads a file to the specified project to be used in an issue or merge request
+description, or a comment.
```plaintext
POST /projects/:id/uploads
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `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) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `file` | string | **{check-circle}** Yes | The file to be uploaded. |
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
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 file system and be preceded
-by `@`. For example:
+cURL to post data using the header `Content-Type: multipart/form-data`. The
+`file=` parameter must point to a file on your file system and be preceded by
+`@`. For example:
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "file=@dk.png" "https://gitlab.example.com/api/v4/projects/5/uploads"
@@ -1912,9 +1923,41 @@ Returned object:
}
```
->**Note**: The returned `url` is relative to the project path. The returned `full_path` is the absolute path to the file.
-In Markdown contexts, the link is automatically expanded when the format in
-`markdown` is used.
+The returned `url` is relative to the project path. The returned `full_path` is
+the absolute path to the file. In Markdown contexts, the link is expanded when
+the format in `markdown` is used.
+
+## Upload a project avatar
+
+Uploads an avatar to the specified project.
+
+```plaintext
+PUT /projects/:id
+```
+
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `avatar` | string | **{check-circle}** Yes | The file to be uploaded. |
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+
+To upload an avatar from your file system, use the `--form` argument. This causes
+cURL to post data using the header `Content-Type: multipart/form-data`. The
+`file=` parameter must point to an image file on your file system and be
+preceded by `@`. For example:
+
+Example request:
+
+```shell
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "avatar=@dk.png" "https://gitlab.example.com/api/v4/projects/5"
+```
+
+Returned object:
+
+```json
+{
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/project/avatar/2/dk.png"
+}
+```
## Share project with group
@@ -1924,12 +1967,12 @@ Allow to share project with group.
POST /projects/:id/share
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `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) |
+| Attribute | Type | Required | Description |
+|----------------|----------------|------------------------|-------------|
+| `expires_at` | string | **{dotted-circle}** No | Share expiration date in ISO 8601 format: 2016-09-26 |
+| `group_access` | integer | **{check-circle}** Yes | The [access level](members.md#valid-access-levels) to grant the group. |
+| `group_id` | integer | **{check-circle}** Yes | The ID of the group to share with. |
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
## Delete a shared project link within a group
@@ -1939,10 +1982,10 @@ Unshare the project from the group. Returns `204` and no content on success.
DELETE /projects/:id/share/:group_id
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `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) |
+| Attribute | Type | Required | Description |
+|------------|----------------|------------------------|-------------|
+| `group_id` | integer | **{check-circle}** Yes | The ID of the group. |
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/share/17"
@@ -1950,8 +1993,8 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
## Hooks
-Also called Project Hooks and Webhooks.
-These are different for [System Hooks](system_hooks.md) that are system wide.
+Also called Project Hooks and Webhooks. These are different for [System Hooks](system_hooks.md)
+that are system-wide.
### List project hooks
@@ -1961,9 +2004,9 @@ Get a list of project hooks.
GET /projects/:id/hooks
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
### Get project hook
@@ -1973,10 +2016,10 @@ Get a specific hook for a project.
GET /projects/:id/hooks/:hook_id
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `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) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|---------------------------|
+| `hook_id` | integer | **{check-circle}** Yes | The ID of a project hook. |
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```json
{
@@ -1995,6 +2038,7 @@ GET /projects/:id/hooks/:hook_id
"pipeline_events": true,
"wiki_page_events": true,
"deployment_events": true,
+ "releases_events": true,
"enable_ssl_verification": true,
"created_at": "2012-10-12T17:04:47Z"
}
@@ -2008,24 +2052,24 @@ Adds a hook to a specified project.
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) |
-| `issues_events` | boolean | no | Trigger hook on issues events |
-| `job_events` | boolean | no | Trigger hook on job events |
-| `merge_requests_events` | boolean | no | Trigger hook on merge requests events |
-| `note_events` | boolean | no | Trigger hook on note 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 |
+| Attribute | Type | Required | Description |
+|------------------------------|----------------|------------------------|-------------|
+| `confidential_issues_events` | boolean | **{dotted-circle}** No | Trigger hook on confidential issues events. |
+| `confidential_note_events` | boolean | **{dotted-circle}** No | Trigger hook on confidential note events. |
+| `deployment_events` | boolean | **{dotted-circle}** No | Trigger hook on deployment events. |
+| `enable_ssl_verification` | boolean | **{dotted-circle}** No | Do SSL verification when triggering the hook. |
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `issues_events` | boolean | **{dotted-circle}** No | Trigger hook on issues events. |
+| `job_events` | boolean | **{dotted-circle}** No | Trigger hook on job events. |
+| `merge_requests_events` | boolean | **{dotted-circle}** No | Trigger hook on merge requests events. |
+| `note_events` | boolean | **{dotted-circle}** No | Trigger hook on note events. |
+| `pipeline_events` | boolean | **{dotted-circle}** No | Trigger hook on pipeline events. |
+| `push_events_branch_filter` | string | **{dotted-circle}** No | Trigger hook on push events for matching branches only. |
+| `push_events` | boolean | **{dotted-circle}** No | Trigger hook on push events. |
+| `tag_push_events` | boolean | **{dotted-circle}** No | Trigger hook on tag push events. |
+| `token` | string | **{dotted-circle}** No | Secret token to validate received payloads; this isn't returned in the response. |
+| `url` | string | **{check-circle}** Yes | The hook URL. |
+| `wiki_page_events` | boolean | **{dotted-circle}** No | Trigger hook on wiki events. |
### Edit project hook
@@ -2035,46 +2079,49 @@ Edits a hook for a specified project.
PUT /projects/:id/hooks/:hook_id
```
-| 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 |
-| `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) |
-| `issues_events` | boolean | no | Trigger hook on issues events |
-| `job_events` | boolean | no | Trigger hook on job events |
-| `merge_requests_events` | boolean | no | Trigger hook on merge requests events |
-| `note_events` | boolean | no | Trigger hook on note 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 |
+| Attribute | Type | Required | Description |
+|------------------------------|----------------|------------------------|-------------|
+| `confidential_issues_events` | boolean | **{dotted-circle}** No | Trigger hook on confidential issues events. |
+| `confidential_note_events` | boolean | **{dotted-circle}** No | Trigger hook on confidential note events. |
+| `deployment_events` | boolean | **{dotted-circle}** No | Trigger hook on deployment events. |
+| `enable_ssl_verification` | boolean | **{dotted-circle}** No | Do SSL verification when triggering the hook. |
+| `hook_id` | integer | **{check-circle}** Yes | The ID of the project hook. |
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `issues_events` | boolean | **{dotted-circle}** No | Trigger hook on issues events. |
+| `job_events` | boolean | **{dotted-circle}** No | Trigger hook on job events. |
+| `merge_requests_events` | boolean | **{dotted-circle}** No | Trigger hook on merge requests events. |
+| `note_events` | boolean | **{dotted-circle}** No | Trigger hook on note events. |
+| `pipeline_events` | boolean | **{dotted-circle}** No | Trigger hook on pipeline events. |
+| `push_events_branch_filter` | string | **{dotted-circle}** No | Trigger hook on push events for matching branches only. |
+| `push_events` | boolean | **{dotted-circle}** No | Trigger hook on push events. |
+| `tag_push_events` | boolean | **{dotted-circle}** No | Trigger hook on tag push events. |
+| `token` | string | **{dotted-circle}** No | Secret token to validate received payloads; this isn't returned in the response. |
+| `url` | string | **{check-circle}** Yes | The hook URL. |
+| `wiki_events` | boolean | **{dotted-circle}** No | Trigger hook on wiki events. |
+| `releases_events` | boolean | **{dotted-circle}** No | Trigger hook on release events. |
### Delete project hook
-Removes a hook from a project. This is an idempotent method and can be called multiple times.
-Either the hook is available or not.
+Removes a hook from a project. This is an idempotent method and can be called
+multiple times. Either the hook is available or not.
```plaintext
DELETE /projects/:id/hooks/:hook_id
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `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) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `hook_id` | integer | **{check-circle}** Yes | The ID of the project hook. |
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
-Note the JSON response differs if the hook is available or not. If the project hook
-is available before it's returned in the JSON response or an empty response is returned.
+Note the JSON response differs if the hook is available or not. If the project
+hook is available before it's returned in the JSON response or an empty response
+is returned.
## Fork relationship
-Allows modification of the forked relationship between existing projects. Available only for project owners and admins.
+Allows modification of the forked relationship between existing projects.
+Available only for project owners and admins.
### Create a forked from/to relation between existing projects
@@ -2082,10 +2129,10 @@ Allows modification of the forked relationship between existing projects. Availa
POST /projects/:id/fork/:forked_from_id
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `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) |
+| Attribute | Type | Required | Description |
+|------------------|----------------|------------------------|-------------|
+| `forked_from_id` | ID | **{check-circle}** Yes | The ID of the project that was forked from. |
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
### Delete an existing forked from relationship
@@ -2093,9 +2140,9 @@ POST /projects/:id/fork/:forked_from_id
DELETE /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) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
## Search for projects by name
@@ -2107,11 +2154,11 @@ accessible.
GET /projects
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `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 |
+| Attribute | Type | Required | Description |
+|------------|--------|------------------------|-------------|
+| `order_by` | string | **{dotted-circle}** No | Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields. |
+| `search` | string | **{check-circle}** Yes | A string contained in the project name. |
+| `sort` | string | **{dotted-circle}** 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"
@@ -2125,23 +2172,24 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
POST /projects/:id/housekeeping
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
## Push Rules **(STARTER)**
### Get project push rules
-Get the [push rules](../push_rules/push_rules.md#enabling-push-rules) of a project.
+Get the [push rules](../push_rules/push_rules.md#enabling-push-rules) of a
+project.
```plaintext
GET /projects/:id/push_rule
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
```json
{
@@ -2162,8 +2210,9 @@ GET /projects/:id/push_rule
}
```
-Users on GitLab [Premium, Silver, or higher](https://about.gitlab.com/pricing/) can also see
-the `commit_committer_check` and `reject_unsigned_commits` parameters:
+Users of GitLab [Premium, Silver, or higher](https://about.gitlab.com/pricing/)
+can also see the `commit_committer_check` and `reject_unsigned_commits`
+parameters:
```json
{
@@ -2183,20 +2232,20 @@ Adds a push rule to a specified project.
POST /projects/:id/push_rule
```
-| Attribute | Type | Required | Description |
-| --------------------------------------------- | -------------- | -------- | ----------- |
-| `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 |
-| `reject_unsigned_commits` **(PREMIUM)** | boolean | no | Reject commit when it's not signed through GPG. |
+| Attribute | Type | Required | Description |
+|-----------------------------------------------|----------------|------------------------|-------------|
+| `author_email_regex` **(STARTER)** | string | **{dotted-circle}** No | All commit author emails must match this, for example `@my-company.com$`. |
+| `branch_name_regex` **(STARTER)** | string | **{dotted-circle}** No | All branch names must match this, for example `(feature|hotfix)\/*`. |
+| `commit_committer_check` **(PREMIUM)** | boolean | **{dotted-circle}** No | Users can only push commits to this repository that were committed with one of their own verified emails. |
+| `commit_message_negative_regex` **(STARTER)** | string | **{dotted-circle}** No | No commit message is allowed to match this, for example `ssh\:\/\/`. |
+| `commit_message_regex` **(STARTER)** | string | **{dotted-circle}** No | All commit messages must match this, for example `Fixed \d+\..*`. |
+| `deny_delete_tag` **(STARTER)** | boolean | **{dotted-circle}** No | Deny deleting a tag. |
+| `file_name_regex` **(STARTER)** | string | **{dotted-circle}** No | All committed filenames must **not** match this, for example `(jar|exe)$`. |
+| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
+| `max_file_size` **(STARTER)** | integer | **{dotted-circle}** No | Maximum file size (MB). |
+| `member_check` **(STARTER)** | boolean | **{dotted-circle}** No | Restrict commits by author (email) to existing GitLab users. |
+| `prevent_secrets` **(STARTER)** | boolean | **{dotted-circle}** No | GitLab will reject any files that are likely to contain secrets. |
+| `reject_unsigned_commits` **(PREMIUM)** | boolean | **{dotted-circle}** No | Reject commit when it's not signed through GPG. |
### Edit project push rule
@@ -2206,35 +2255,35 @@ Edits a push rule for a specified project.
PUT /projects/:id/push_rule
```
-| Attribute | Type | Required | Description |
-| --------------------------------------------- | -------------- | -------- | ----------- |
-| `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 |
-| `reject_unsigned_commits` **(PREMIUM)** | boolean | no | Reject commits when they are not GPG signed. |
+| Attribute | Type | Required | Description |
+|-----------------------------------------------|----------------|------------------------|-------------|
+| `author_email_regex` **(STARTER)** | string | **{dotted-circle}** No | All commit author emails must match this, for example `@my-company.com$`. |
+| `branch_name_regex` **(STARTER)** | string | **{dotted-circle}** No | All branch names must match this, for example `(feature|hotfix)\/*`. |
+| `commit_committer_check` **(PREMIUM)** | boolean | **{dotted-circle}** No | Users can only push commits to this repository that were committed with one of their own verified emails. |
+| `commit_message_negative_regex` **(STARTER)** | string | **{dotted-circle}** No | No commit message is allowed to match this, for example `ssh\:\/\/`. |
+| `commit_message_regex` **(STARTER)** | string | **{dotted-circle}** No | All commit messages must match this, for example `Fixed \d+\..*`. |
+| `deny_delete_tag` **(STARTER)** | boolean | **{dotted-circle}** No | Deny deleting a tag. |
+| `file_name_regex` **(STARTER)** | string | **{dotted-circle}** No | All committed filenames must **not** match this, for example `(jar|exe)$`. |
+| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
+| `max_file_size` **(STARTER)** | integer | **{dotted-circle}** No | Maximum file size (MB). |
+| `member_check` **(STARTER)** | boolean | **{dotted-circle}** No | Restrict commits by author (email) to existing GitLab users. |
+| `prevent_secrets` **(STARTER)** | boolean | **{dotted-circle}** No | GitLab will reject any files that are likely to contain secrets. |
+| `reject_unsigned_commits` **(PREMIUM)** | boolean | **{dotted-circle}** No | Reject commits when they are not GPG signed. |
### Delete project push rule
> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 9.0.
-Removes a push rule from a project. This is an idempotent method and can be called multiple times.
-Either the push rule is available or not.
+Removes a push rule from a project. This is an idempotent method and can be
+called multiple times. Either the push rule is available or not.
```plaintext
DELETE /projects/:id/push_rule
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
## Transfer a project to a new namespace
@@ -2244,10 +2293,10 @@ DELETE /projects/:id/push_rule
PUT /projects/:id/transfer
```
-| 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 | yes | The ID or path of the namespace to transfer to project to |
+| Attribute | Type | Required | Description |
+|-------------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `namespace` | integer/string | **{check-circle}** Yes | The ID or path of the namespace to transfer to project to. |
Example request:
@@ -2376,9 +2425,9 @@ Read more in the [Project members](members.md) documentation.
POST /projects/:id/mirror/pull
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/mirror/pull"
@@ -2390,7 +2439,9 @@ Read more in the [Project Badges](project_badges.md) documentation.
## Issue and merge request description templates
-The non-default [issue and merge request description templates](../user/project/description_templates.md) are managed inside the project's repository. So you can manage them via the API through the [Repositories API](repositories.md) and the [Repository Files API](repository_files.md).
+The non-default [issue and merge request description templates](../user/project/description_templates.md)
+are managed inside the project's repository. So you can manage them with the API
+through the [Repositories API](repositories.md) and the [Repository Files API](repository_files.md).
## Download snapshot of a Git repository
@@ -2402,14 +2453,14 @@ Download a snapshot of the project (or wiki, if requested) Git repository. This
snapshot is always in uncompressed [tar](https://en.wikipedia.org/wiki/Tar_(computing))
format.
-If a repository is corrupted to the point where `git clone` does not work, the
+If a repository is corrupted to the point where `git clone` doesn't work, the
snapshot may allow some of the data to be retrieved.
```plaintext
GET /projects/:id/snapshot
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `wiki` | boolean | no | Whether to download the wiki, rather than project, repository |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `wiki` | boolean | **{dotted-circle}** No | Whether to download the wiki, rather than project, repository. |
diff --git a/doc/api/protected_environments.md b/doc/api/protected_environments.md
index 56b399cec9b..c42d6776341 100644
--- a/doc/api/protected_environments.md
+++ b/doc/api/protected_environments.md
@@ -96,7 +96,7 @@ POST /projects/:id/protected_environments
```
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/protected_environments?name=staging&deploy_access_levels%5B%5D%5Buser_id%5D=1"
+curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/22034114/protected_environments"
```
| Attribute | Type | Required | Description |
@@ -105,21 +105,22 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
| `name` | string | yes | The name of the environment. |
| `deploy_access_levels` | array | yes | Array of access levels allowed to deploy, with each described by a hash. |
-Elements in the `deploy_access_levels` array should take the
-form `{user_id: integer}`, `{group_id: integer}` or `{access_level: integer}`.
+Elements in the `deploy_access_levels` array should be one of `user_id`, `group_id` or
+`access_level`, and 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).
Example response:
```json
{
- "name":"staging",
+ "name":"production",
"deploy_access_levels":[
{
- "access_level":null,
- "access_level_description":"Administrator",
- "user_id":1,
- "group_id":null
+ "access_level":40,
+ "access_level_description":"protected-access-group",
+ "user_id":null,
+ "group_id":9899826
}
]
}
diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md
index 4dac9f61469..7c65e9da74b 100644
--- a/doc/api/releases/index.md
+++ b/doc/api/releases/index.md
@@ -228,7 +228,7 @@ GET /projects/:id/releases/:tag_name
| Attribute | Type | Required | Description |
| ------------- | -------------- | -------- | ----------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
-| `tag_name` | string | yes | The tag where the release will be created from. |
+| `tag_name` | string | yes | The Git tag the release is associated with. |
Example request:
@@ -367,7 +367,7 @@ POST /projects/:id/releases
| `assets:links` | array of hash | no | An array of assets links. |
| `assets:links:name`| string | required by: `assets:links` | The name of the link. |
| `assets:links:url` | string | required by: `assets:links` | The URL of the link. |
-| `assets:links:filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases/index.md).
+| `assets:links:filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases/index.md#permanent-links-to-release-assets).
| `assets:links:link_type` | string | no | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`.
| `released_at` | datetime | no | The date when the release will be/was ready. Defaults to the current time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
@@ -508,7 +508,7 @@ POST /projects/:id/releases/:tag_name/evidence
| Attribute | Type | Required | Description |
| ------------- | -------------- | -------- | ----------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
-| `tag_name` | string | yes | The tag where the release will be created from. |
+| `tag_name` | string | yes | The Git tag the release is associated with. |
Example request:
@@ -533,7 +533,7 @@ PUT /projects/:id/releases/:tag_name
| Attribute | Type | Required | Description |
| ------------- | --------------- | -------- | ----------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
-| `tag_name` | string | yes | The tag where the release will be created from. |
+| `tag_name` | string | yes | The Git tag the release is associated with. |
| `name` | string | no | The release name. |
| `description` | string | no | The description of the release. You can use [Markdown](../../user/markdown.md). |
| `milestones` | array of string | no | The title of each milestone to associate with the release. [GitLab Premium](https://about.gitlab.com/pricing/) customers can specify group milestones. To remove all milestones from the release, specify `[]`. |
@@ -584,7 +584,7 @@ Example response:
"id":53,
"iid":3,
"project_id":24,
- "title":"v1.0",
+ "title":"v1.2",
"description":"Voluptate fugiat possimus quis quod aliquam expedita.",
"state":"active",
"created_at":"2019-09-01T13:00:00.256Z",
@@ -640,7 +640,7 @@ DELETE /projects/:id/releases/:tag_name
| Attribute | Type | Required | Description |
| ------------- | -------------- | -------- | ----------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
-| `tag_name` | string | yes | The tag where the release will be created from. |
+| `tag_name` | string | yes | The Git tag the release is associated with. |
Example request:
diff --git a/doc/api/releases/links.md b/doc/api/releases/links.md
index 242b5eb41f5..2b33f6a4dc7 100644
--- a/doc/api/releases/links.md
+++ b/doc/api/releases/links.md
@@ -97,26 +97,29 @@ POST /projects/:id/releases/:tag_name/assets/links
| `tag_name` | string | yes | The tag associated with the Release. |
| `name` | string | yes | The name of the link. |
| `url` | string | yes | The URL of the link. |
+| `filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases/index.md#permanent-links-to-release-assets).
| `link_type` | string | no | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`. |
Example request:
```shell
curl --request POST \
- --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" \
- --data name="awesome-v0.2.dmg" \
- --data url="http://192.168.10.15:3000" \
- "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links"
+ --header "PRIVATE-TOKEN: tkhfG7HgG-LiZd3zfdDC" \
+ --data name="hellodarwin-amd64" \
+ --data url="https://gitlab.example.com/mynamespace/hello/-/jobs/688/artifacts/raw/bin/hello-darwin-amd64" \
+ --data filepath="/bin/hellodarwin-amd64" \
+ "https://gitlab.example.com/api/v4/projects/20/releases/v1.7.0/assets/links"
```
Example response:
```json
{
- "id":1,
- "name":"awesome-v0.2.dmg",
- "url":"http://192.168.10.15:3000",
- "external":true,
+ "id":2,
+ "name":"hellodarwin-amd64",
+ "url":"https://gitlab.example.com/mynamespace/hello/-/jobs/688/artifacts/raw/bin/hello-darwin-amd64",
+ "direct_asset_url":"https://gitlab.example.com/mynamespace/hello/-/releases/v1.7.0/downloads/bin/hellodarwin-amd64",
+ "external":false,
"link_type":"other"
}
```
@@ -136,6 +139,7 @@ PUT /projects/:id/releases/:tag_name/assets/links/:link_id
| `link_id` | integer | yes | The ID of the link. |
| `name` | string | no | The name of the link. |
| `url` | string | no | The URL of the link. |
+| `filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases/index.md#permanent-links-to-release-assets).
| `link_type` | string | no | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`. |
NOTE: **Note:**
diff --git a/doc/api/resource_label_events.md b/doc/api/resource_label_events.md
index 275614a1449..b088c06b342 100644
--- a/doc/api/resource_label_events.md
+++ b/doc/api/resource_label_events.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Resource label events API
Resource label events keep track about who, when, and which label was added to, or removed from, an issuable.
diff --git a/doc/api/scim.md b/doc/api/scim.md
index 350f992779e..653d56f3e06 100644
--- a/doc/api/scim.md
+++ b/doc/api/scim.md
@@ -1,19 +1,23 @@
-# SCIM API **(SILVER ONLY)**
+---
+type: reference, howto
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in [GitLab Silver](https://about.gitlab.com/pricing/) 11.10.
+# SCIM API (SYSTEM ONLY) **(SILVER ONLY)**
-The SCIM API implements the [RFC7644 protocol](https://tools.ietf.org/html/rfc7644).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in [GitLab.com Silver](https://about.gitlab.com/pricing/) 11.10.
-CAUTION: **Caution:**
-This API is for internal system use for connecting with a SCIM provider. While it can be used directly, it is subject to change without notice.
+The SCIM API implements the [RFC7644 protocol](https://tools.ietf.org/html/rfc7644). As this API is for
+**system** use for SCIM provider integration, it is subject to change without notice.
-NOTE: **Note:**
-[Group SSO](../user/group/saml_sso/index.md) must be enabled for the group. For more information, see [SCIM setup documentation](../user/group/saml_sso/scim_setup.md#requirements).
+To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group.
+This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities.
## Get a list of SAML users
-NOTE: **Note:**
-This endpoint is used as part of the SCIM syncing mechanism and it only returns
+This endpoint is used as part of the SCIM syncing mechanism. It only returns
a single user based on a unique ID which should match the `extern_uid` of the user.
```plaintext
diff --git a/doc/api/search.md b/doc/api/search.md
index bdf5bdd4924..8de93ce0d32 100644
--- a/doc/api/search.md
+++ b/doc/api/search.md
@@ -7,7 +7,8 @@ type: reference, api
# Search API
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41763) in GitLab 10.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41763) in GitLab 10.5.
+> - [Feature flag `search_filter_by_confidential` removed](https://gitlab.com/gitlab-org/gitlab/-/issues/244923) in GitLab 13.6.
Every API call to search must be authenticated.
@@ -24,7 +25,9 @@ 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. |
-| `confidential` | boolean | no | Filter by confidentiality. Issues scope is supported; it is ignored for other scopes. This parameter is behind a [feature flag (`search_filter_by_confidential`)](../administration/feature_flags.md). |
+| `confidential` | boolean | no | Filter by confidentiality. Issues scope is supported; it is ignored for other scopes. |
+| `order_by` | string | no | Allowed values are `created_at` only. If this is not set, the results will either be sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
+| `sort` | string | no | Allowed values are `asc` or `desc` only. If this is not set, the results will either be sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, snippet_titles, users.
@@ -434,7 +437,9 @@ GET /groups/:id/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. |
-| `confidential` | boolean | no | Filter by confidentiality. Issues scope is supported; it is ignored for other scopes. This parameter is behind a [feature flag (`search_filter_by_confidential`)](../administration/feature_flags.md). |
+| `confidential` | boolean | no | Filter by confidentiality. Issues scope is supported; it is ignored for other scopes. |
+| `order_by` | string | no | Allowed values are `created_at` only. If this is not set, the results will either be sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
+| `sort` | string | no | Allowed values are `asc` or `desc` only. If this is not set, the results will either be sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, users.
@@ -814,7 +819,9 @@ GET /projects/:id/search
| `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. |
-| `confidential` | boolean | no | Filter by confidentiality. Issues scope is supported; it is ignored for other scopes. This parameter is behind a [feature flag (`search_filter_by_confidential`)](../administration/feature_flags.md). |
+| `confidential` | boolean | no | Filter by confidentiality. Issues scope is supported; it is ignored for other scopes. |
+| `order_by` | string | no | Allowed values are `created_at` only. If this is not set, the results will either be sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
+| `sort` | string | no | Allowed values are `asc` or `desc` only. If this is not set, the results will either be sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
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 7c01e43a4d8..a60eacef1d8 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Services API
NOTE: **Note:**
@@ -305,7 +311,7 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `webhook` | string | true | The Unify Circuit webhook. For example, `https://circuit.com/rest/v2/webhooks/incoming/...`. |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
-| `branches_to_be_notified` | string | all | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected" |
+| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected". The default value is "default" |
| `push_events` | boolean | false | Enable notifications for push events |
| `issues_events` | boolean | false | Enable notifications for issue events |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
@@ -350,7 +356,7 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `webhook` | string | true | The Webex Teams webhook. For example, `https://api.ciscospark.com/v1/webhooks/incoming/...`. |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
-| `branches_to_be_notified` | string | all | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected" |
+| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected". The default value is "default" |
| `push_events` | boolean | false | Enable notifications for push events |
| `issues_events` | boolean | false | Enable notifications for issue events |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
@@ -476,7 +482,7 @@ Parameters:
| `send_from_committer_email` | boolean | false | Send from committer |
| `push_events` | boolean | false | Enable notifications for push events |
| `tag_push_events` | boolean | false | Enable notifications for tag push events |
-| `branches_to_be_notified` | string | all | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected". Notifications will be always fired for tag pushes. |
+| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected". Notifications will be always fired for tag pushes. The default value is "all" |
### Delete Emails on push service
@@ -659,7 +665,7 @@ Parameters:
| `webhook` | string | true | The Hangouts Chat webhook. For example, `https://chat.googleapis.com/v1/spaces...`. |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
| `notify_only_default_branch` | boolean | false | DEPRECATED: This parameter has been replaced with `branches_to_be_notified` |
-| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected" |
+| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected". The default value is "default" |
| `push_events` | boolean | false | Enable notifications for push events |
| `issues_events` | boolean | false | Enable notifications for issue events |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
@@ -972,7 +978,7 @@ Parameters:
| `recipients` | string | yes | Comma-separated list of recipient email addresses |
| `add_pusher` | boolean | no | Add pusher to recipients list |
| `notify_only_broken_pipelines` | boolean | no | Notify only broken pipelines |
-| `branches_to_be_notified` | string | all | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected" |
+| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected. The default value is "default" |
| `notify_only_default_branch` | boolean | no | Send notifications only for the default branch ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28271)) |
| `pipeline_events` | boolean | false | Enable notifications for pipeline events |
@@ -1165,7 +1171,7 @@ Parameters:
| `channel` | string | false | Default channel to use if others are not configured |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
| `notify_only_default_branch` | boolean | false | DEPRECATED: This parameter has been replaced with `branches_to_be_notified` |
-| `branches_to_be_notified` | string | all | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected" |
+| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected". The default value is "default" |
| `commit_events` | boolean | false | Enable notifications for commit events |
| `confidential_issue_channel` | string | false | The name of the channel to receive confidential issues events notifications |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
@@ -1224,7 +1230,7 @@ Parameters:
| `webhook` | string | true | The Microsoft Teams webhook. For example, `https://outlook.office.com/webhook/...` |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
| `notify_only_default_branch` | boolean | false | DEPRECATED: This parameter has been replaced with `branches_to_be_notified` |
-| `branches_to_be_notified` | string | all | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected" |
+| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected". The default value is "default" |
| `push_events` | boolean | false | Enable notifications for push events |
| `issues_events` | boolean | false | Enable notifications for issue events |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
@@ -1275,7 +1281,7 @@ Parameters:
| `channel` | string | false | Default channel to use if others are not configured |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
| `notify_only_default_branch` | boolean | false | DEPRECATED: This parameter has been replaced with `branches_to_be_notified` |
-| `branches_to_be_notified` | string | all | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected" |
+| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected". The default value is "default" |
| `push_events` | boolean | false | Enable notifications for push events |
| `issues_events` | boolean | false | Enable notifications for issue events |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 236cd10a30e..5b04ee9d368 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Application settings API **(CORE ONLY)**
These API calls allow you to read and modify GitLab instance
@@ -37,9 +43,9 @@ Example response:
"home_page_url" : null,
"default_snippet_visibility" : "private",
"outbound_local_requests_whitelist": [],
- "domain_whitelist" : [],
- "domain_blacklist_enabled" : false,
- "domain_blacklist" : [],
+ "domain_allowlist" : [],
+ "domain_denylist_enabled" : false,
+ "domain_denylist" : [],
"created_at" : "2016-01-04T15:44:55.176Z",
"default_ci_config_path" : null,
"default_project_visibility" : "private",
@@ -73,7 +79,8 @@ Example response:
"snippet_size_limit": 52428800,
"issues_create_limit": 300,
"raw_blob_request_limit": 300,
- "wiki_page_max_content_bytes": 52428800
+ "wiki_page_max_content_bytes": 52428800,
+ "require_admin_approval_after_user_signup": false
}
```
@@ -127,9 +134,9 @@ Example response:
"default_snippet_visibility": "private",
"default_group_visibility": "private",
"outbound_local_requests_whitelist": [],
- "domain_whitelist": [],
- "domain_blacklist_enabled" : false,
- "domain_blacklist" : [],
+ "domain_allowlist": [],
+ "domain_denylist_enabled" : false,
+ "domain_denylist" : [],
"external_authorization_service_enabled": true,
"external_authorization_service_url": "https://authorize.me",
"external_authorization_service_default_label": "default",
@@ -164,7 +171,8 @@ Example response:
"snippet_size_limit": 52428800,
"issues_create_limit": 300,
"raw_blob_request_limit": 300,
- "wiki_page_max_content_bytes": 52428800
+ "wiki_page_max_content_bytes": 52428800,
+ "require_admin_approval_after_user_signup": false
}
```
@@ -225,9 +233,9 @@ listed in the descriptions of the relevant settings.
| `diff_max_patch_bytes` | integer | no | Maximum diff patch size (Bytes). |
| `disabled_oauth_sign_in_sources` | array of strings | no | Disabled OAuth sign-in sources. |
| `dns_rebinding_protection_enabled` | boolean | no | Enforce DNS rebinding attack protection. |
-| `domain_blacklist_enabled` | boolean | no | (**If enabled, requires:** `domain_blacklist`) Allows blocking sign-ups from emails from specific domains. |
-| `domain_blacklist` | array of strings | no | Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: `domain.com`, `*.domain.com`. |
-| `domain_whitelist` | array of strings | no | Force people to use only corporate emails for sign-up. Default is `null`, meaning there is no restriction. |
+| `domain_denylist_enabled` | boolean | no | (**If enabled, requires:** `domain_denylist`) Allows blocking sign-ups from emails from specific domains. |
+| `domain_denylist` | array of strings | no | Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: `domain.com`, `*.domain.com`. |
+| `domain_allowlist` | array of strings | no | Force people to use only corporate emails for sign-up. Default is `null`, meaning there is no restriction. |
| `dsa_key_restriction` | integer | no | The minimum allowed bit length of an uploaded DSA key. Default is `0` (no restriction). `-1` disables DSA keys. |
| `ecdsa_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ECDSA key. Default is `0` (no restriction). `-1` disables ECDSA keys. |
| `ed25519_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ED25519 key. Default is `0` (no restriction). `-1` disables ED25519 keys. |
@@ -325,6 +333,7 @@ listed in the descriptions of the relevant settings.
| `repository_size_limit` | integer | no | **(PREMIUM)** Size limit per repository (MB) |
| `repository_storages_weighted` | hash of strings to integers | no | (GitLab 13.1 and later) Hash of names of taken from `gitlab.yml` to [weights](../administration/repository_storage_paths.md#choose-where-new-repositories-will-be-stored). New projects are created in one of these stores, chosen by a weighted random selection. |
| `repository_storages` | array of strings | no | (GitLab 13.0 and earlier) List of names of enabled storage paths, taken from `gitlab.yml`. New projects are created in one of these stores, chosen at random. |
+| `require_admin_approval_after_user_signup` | boolean | no | When enabled, any user that signs up for an account using the registration form is placed under a **Pending approval** state and has to be explicitly [approved](../user/admin_area/approving_users.md) by an administrator. |
| `require_two_factor_authentication` | boolean | no | (**If enabled, requires:** `two_factor_grace_period`) Require all users to set up Two-factor authentication. |
| `restricted_visibility_levels` | array of strings | no | Selected levels cannot be used by non-admin users for groups, projects or snippets. Can take `private`, `internal` and `public` as a parameter. Default is `null` which means there is no restriction. |
| `rsa_key_restriction` | integer | no | The minimum allowed bit length of an uploaded RSA key. Default is `0` (no restriction). `-1` disables RSA keys. |
diff --git a/doc/api/sidekiq_metrics.md b/doc/api/sidekiq_metrics.md
index caa02412a28..914f5fbf42a 100644
--- a/doc/api/sidekiq_metrics.md
+++ b/doc/api/sidekiq_metrics.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Sidekiq Metrics API **(CORE ONLY)**
> Introduced in GitLab 8.9.
diff --git a/doc/api/snippets.md b/doc/api/snippets.md
index 431d745ac84..c2812de5dd7 100644
--- a/doc/api/snippets.md
+++ b/doc/api/snippets.md
@@ -21,7 +21,7 @@ Valid values for snippet visibility levels are:
| Visibility | Description |
|:-----------|:----------------------------------------------------|
| `private` | Snippet is visible only to the snippet creator. |
-| `internal` | Snippet is visible for any logged in user. |
+| `internal` | Snippet is visible for any logged in user except [external users](../user/permissions.md#external-users). |
| `public` | Snippet can be accessed without any authentication. |
## List all snippets for a user
diff --git a/doc/api/statistics.md b/doc/api/statistics.md
index 890c6f68898..6a41a960eba 100644
--- a/doc/api/statistics.md
+++ b/doc/api/statistics.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Application statistics API
## Get current application statistics
diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md
index 3e0d2151428..00cd88c88dd 100644
--- a/doc/api/system_hooks.md
+++ b/doc/api/system_hooks.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# System hooks API
All methods require administrator authorization.
diff --git a/doc/api/templates/dockerfiles.md b/doc/api/templates/dockerfiles.md
index e579300a2fd..fd0edfce8e5 100644
--- a/doc/api/templates/dockerfiles.md
+++ b/doc/api/templates/dockerfiles.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/api/templates/gitignores.md b/doc/api/templates/gitignores.md
index 3acd666ad66..b957c582755 100644
--- a/doc/api/templates/gitignores.md
+++ b/doc/api/templates/gitignores.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/api/templates/licenses.md b/doc/api/templates/licenses.md
index 4eb3c0f6111..d1044b23306 100644
--- a/doc/api/templates/licenses.md
+++ b/doc/api/templates/licenses.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/api/todos.md b/doc/api/todos.md
index ab36021d694..06b99ab8c53 100644
--- a/doc/api/todos.md
+++ b/doc/api/todos.md
@@ -26,7 +26,7 @@ Parameters:
| `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 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` |
+| `type` | string | no | The type of to-do item. 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,7 +187,7 @@ Example Response:
]
```
-## Mark a to do as done
+## Mark a to-do item as done
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.
@@ -200,7 +200,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a to do |
+| `id` | integer | yes | The ID of to-do item |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/todos/130/mark_as_done"
diff --git a/doc/api/users.md b/doc/api/users.md
index beaea689fb7..e1fa97765df 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Users API
## List users
@@ -1435,7 +1441,54 @@ Parameters:
| `user_id` | integer | yes | The ID of the user |
| `impersonation_token_id` | integer | yes | The ID of the impersonation token |
-### Get user activities (admin only)
+## Create a personal access token (admin only)
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17176) in GitLab 13.6.
+> - It's [deployed behind a feature flag](../user/feature_flags.md), disabled by default.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-an-administrators-ability-to-use-the-api-to-create-personal-access-tokens). **(CORE)**
+
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+> Requires admin permissions.
+> Token values are returned once. Make sure you save it - you won't be able to access it again.
+
+It creates a new personal access token.
+
+```plaintext
+POST /users/:user_id/personal_access_tokens
+```
+
+| Attribute | Type | Required | Description |
+| ------------ | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
+| `user_id` | integer | yes | The ID of the user |
+| `name` | string | yes | The name of the personal access token |
+| `expires_at` | date | no | The expiration date of the personal access token in ISO format (`YYYY-MM-DD`) |
+| `scopes` | array | yes | The array of scopes of the personal access token (`api`, `read_user`, `read_api`, `read_repository`, `write_repository`) |
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "name=mytoken" --data "expires_at=2017-04-04" --data "scopes[]=api" "https://gitlab.example.com/api/v4/users/42/personal_access_tokens"
+```
+
+Example response:
+
+```json
+{
+ "id": 3,
+ "name": "mytoken",
+ "revoked": false,
+ "created_at": "2020-10-14T11:58:53.526Z",
+ "scopes": [
+ "api"
+ ],
+ "user_id": 42,
+ "active": true,
+ "expires_at": "2020-12-31",
+ "token": "ggbfKkC4n-Lujy8jwCR2"
+}
+```
+
+## Get user activities (admin only)
NOTE: **Note:**
This API endpoint is only available on 8.15 (EE) and 9.1 (CE) and above.
@@ -1540,3 +1593,22 @@ Example response:
},
]
```
+
+## Enable or disable an administrator's ability to use the API to create personal access tokens **(CORE)**
+
+An administrator's ability to create personal access tokens through the API is
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:pat_creation_api_for_admin)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:pat_creation_api_for_admin)
+```
diff --git a/doc/api/v3_to_v4.md b/doc/api/v3_to_v4.md
index c351c14e24c..2dd4376413b 100644
--- a/doc/api/v3_to_v4.md
+++ b/doc/api/v3_to_v4.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# API V3 to API V4
In GitLab 9.0 and later, API V4 is the preferred version to be used.
diff --git a/doc/api/version.md b/doc/api/version.md
index 3c6feaae071..d1582cf63cd 100644
--- a/doc/api/version.md
+++ b/doc/api/version.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Version API
> Introduced in GitLab 8.13.
diff --git a/doc/architecture/blueprints/cloud_native_build_logs/index.md b/doc/architecture/blueprints/cloud_native_build_logs/index.md
index 25abfe36e88..f901a724653 100644
--- a/doc/architecture/blueprints/cloud_native_build_logs/index.md
+++ b/doc/architecture/blueprints/cloud_native_build_logs/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
description: 'Next iteration of build logs architecture at GitLab'
---
diff --git a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
index 37e69d46ae1..27d2f1362e5 100644
--- a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
+++ b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
description: 'Making GitLab Pages a Cloud Native application - architecture blueprint.'
---
diff --git a/doc/architecture/blueprints/feature_flags_development/index.md b/doc/architecture/blueprints/feature_flags_development/index.md
index 0aeb2b51b39..76fb5f5c7db 100644
--- a/doc/architecture/blueprints/feature_flags_development/index.md
+++ b/doc/architecture/blueprints/feature_flags_development/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
description: 'Internal usage of Feature Flags for GitLab development'
---
diff --git a/doc/architecture/blueprints/image_resizing/index.md b/doc/architecture/blueprints/image_resizing/index.md
new file mode 100644
index 00000000000..47e2ad24960
--- /dev/null
+++ b/doc/architecture/blueprints/image_resizing/index.md
@@ -0,0 +1,76 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+comments: false
+description: 'Image Resizing'
+---
+
+# Image resizing for avatars and content images
+
+Currently, we are showing all uploaded images 1:1, which is of course not ideal. To improve performance greatly we will add image resizing to the backend. There are two main areas of image resizing to consider; avatars and content images. The MVC for this implementation will focus on Avatars. Avatars requests consist of approximately 70% of total image requests. There is an identified set of sizes we intend to support which makes the scope of this first MVC very narrow. Content image resizing has many more considerations for size and features. It is entirely possible that we have two separate development efforts with the same goal of increasing performance via image resizing.
+
+## MVC Avatar Resizing
+
+We will implement a dynamic image resizing solution. This means image should be resized and optimized on the fly so that if we define new targeted sizes later we can add them dynamically. This would mean a huge improvement in performance as some of the measurements suggest that we can save up to 95% of our current load size. Our initial investigations indicate that we have uploaded approximately 1.65 million avatars totaling approximately 80GB in size and averaging approximately 48kb each. Early measurements indicate we can reduce the most common avatar dimensions to between 1-3kb in size, netting us a greater than 90% size reduction. For the MVC we will not consider application level caching and rely purely on HTTP based caches as implemented in CDNs and browsers, but might revisit this decision later on. To easily mitigate performance issues with avatar resizing, especially in the case of self managed, an operations feature flag will be implemented to disable dynamic image resizing.
+
+```mermaid
+sequenceDiagram
+ autonumber
+ Requester->>Workhorse: Incoming request
+ Workhorse->>RailsApp: Incoming request
+ alt All is true: 1.Avatar is requested, 2.Requested Width is allowed, 3.Feature is enabled
+ Note right of RailsApp: Width Allowlist: https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/concerns/avatarable.rb#L10
+ RailsApp->>Workhorse: `send-scaled-img:` request
+ Note right of RailsApp: Set `send-scaled-img:` Header
+ Workhorse->>Workhorse: Image resizing using Go lib
+ Workhorse->>Requester: Serve the resized image
+ else All other cases
+ RailsApp->>Workhorse: Usual request scenario
+ Workhorse->>Requester: Usual request scenario
+ end
+```
+
+## Content Image Resizing
+
+Content image resizing is a more complex problem to tackle. There are no set size restrictions and there are additional features or requirements to consider.
+
+- Dynamic WebP support - the WebP format typically achieves an average of 30% more compression than JPEG without the loss of image quality. More details [here](https://developers.google.com/speed/webp/docs/c_study)
+- Extract first image of GIF's so we can prevent from loading 10MB pixels
+- Check Device Pixel Ratio to deliver nice images on High DPI screens
+- Progressive image loading, similar to what is described [here](https://www.sitepoint.com/how-to-build-your-own-progressive-image-loader/)
+- Resizing recommendations (size, clarity, etc.)
+- Storage
+
+The MVC Avatar resizing implementation is integrated into Workhorse. With the extra requirements for content image resizing, this may require further use of GraphicsMagik (GM) or a similar library and breaking it out of Workhorse.
+
+## Iterations
+
+1. ✓ POC on different image resizing solutions
+1. ✓ Review solutions with security team
+1. ✓ Implement avatar resizing MVC
+1. Deploy, measure, monitor
+1. Clarify features for content image resizing
+1. Weigh options between using current implementation of image resizing vs new solution
+1. Implement content image resizing MVC
+1. Deploy, measure, monitor
+
+## Who
+
+Proposal:
+
+| Role | Who
+|------------------------------|-------------------------|
+| Author | Craig Gomes |
+| Architecture Evolution Coach | Kamil Trzciński |
+| Engineering Leader | Tim Zallmann |
+| Domain Expert | Matthias Kaeppler |
+| Domain Expert | Aleksei Lipniagov |
+
+DRIs:
+
+| Role | Who
+|------------------------------|------------------------|
+| Product | Josh Lambert |
+| Leadership | Craig Gomes |
+| Engineering | Matthias Kaeppler |
diff --git a/doc/architecture/index.md b/doc/architecture/index.md
index 0a2ade6b7b0..0cac646ea83 100644
--- a/doc/architecture/index.md
+++ b/doc/architecture/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
description: 'Architecture Practice at GitLab'
---
diff --git a/doc/ci/README.md b/doc/ci/README.md
index dca6d8baa79..45cf56df894 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -77,7 +77,7 @@ While building your `.gitlab-ci.yml`, you can use the [CI/CD configuration visua
For a broader overview, see the [CI/CD getting started](quick_start/README.md) guide.
-Once you're familiar with how GitLab CI/CD works, see the
+After you're familiar with how GitLab CI/CD works, see the
[`.gitlab-ci.yml` full reference](yaml/README.md)
for all the attributes you can set and use.
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index df41f7da2d9..dfa92d469bc 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -411,6 +411,8 @@ job B:
- cat vendor/hello.txt
cache:
key: build-cache
+ paths:
+ - vendor/
```
Here's what happens behind the scenes:
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 7ee9f98bd39..b6f885ff220 100644
--- a/doc/ci/ci_cd_for_external_repos/github_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/github_integration.md
@@ -22,7 +22,7 @@ cannot be used to authenticate with GitHub as an external CI/CD repository.
## Connect with Personal Access Token
Personal access tokens can only be used to connect GitHub.com
-repositories to GitLab, and the GitHub user must have the [owner role](https://docs.github.com/en/github/getting-started-with-github/access-permissions-on-github).
+repositories to GitLab, and the GitHub user must have the [owner role](https://docs.github.com/en/free-pro-team@latest/github/getting-started-with-github/access-permissions-on-github).
To perform a one-off authorization with GitHub to grant GitLab access your
repositories:
diff --git a/doc/ci/ci_cd_for_external_repos/img/github_omniauth.png b/doc/ci/ci_cd_for_external_repos/img/github_omniauth.png
deleted file mode 100644
index 71a3a057a41..00000000000
--- a/doc/ci/ci_cd_for_external_repos/img/github_omniauth.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/ci_cd_for_external_repos/img/github_push_webhook.png b/doc/ci/ci_cd_for_external_repos/img/github_push_webhook.png
deleted file mode 100644
index e8c17d664e1..00000000000
--- a/doc/ci/ci_cd_for_external_repos/img/github_push_webhook.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/ci_cd_for_external_repos/index.md b/doc/ci/ci_cd_for_external_repos/index.md
index c6590599849..ae6cb759d23 100644
--- a/doc/ci/ci_cd_for_external_repos/index.md
+++ b/doc/ci/ci_cd_for_external_repos/index.md
@@ -77,7 +77,7 @@ created.
GitLab CI/CD will create 2 pipelines in this case. One for the
branch push and one for the external pull request.
-Once the Pull Request is closed, no pipelines are created for the external pull
+After the Pull Request is closed, no pipelines are created for the external pull
request, even if new changes are pushed to the same branch.
### Additional predefined variables
diff --git a/doc/ci/cloud_deployment/index.md b/doc/ci/cloud_deployment/index.md
index af7df0e1153..cbaebde0b00 100644
--- a/doc/ci/cloud_deployment/index.md
+++ b/doc/ci/cloud_deployment/index.md
@@ -239,7 +239,7 @@ pass three JSON input objects, based on existing templates:
- [Template for the _Deploy to EC2_ step on AWS](https://docs.aws.amazon.com/codedeploy/latest/APIReference/API_CreateDeployment.html).
-1. Once you have completed these three templates based on your requirements, you
+1. After you have completed these three templates based on your requirements, you
have two ways to pass in these JSON objects:
- They can be three actual files located in your project. You must specify their path relative to
@@ -281,3 +281,40 @@ When running your project pipeline at this point:
- Your built application is pushed to your S3 bucket then and deployed to your EC2 instance, based
on the related JSON object's content. The deployment job finishes whenever the deployment to EC2
is done or has failed.
+
+#### Custom build job for Auto DevOps
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216008) in GitLab 13.6.
+
+To leverage [Auto DevOps](../../topics/autodevops/index.md) for your project when deploying to
+AWS EC2, first you must define [your AWS credentials as environment variables](#run-aws-commands-from-gitlab-cicd).
+
+Next, define a job for the `build` stage. To do so, you must reference the
+`Auto-DevOps.gitlab-ci.yml` template and include a job named `build_artifact` in your
+`.gitlab-ci.yml` file. For example:
+
+```yaml
+# .gitlab-ci.yml
+
+include:
+ - template: Auto-DevOps.gitlab-ci.yml
+
+variables:
+ - AUTO_DEVOPS_PLATFORM_TARGET: EC2
+
+build_artifact:
+ stage: build
+ script:
+ - <your build script goes here>
+ artifacts:
+ paths:
+ - <built artifact>
+```
+
+### Deploy to Amazon EKS
+
+- [How to deploy your application to a GitLab-managed Amazon EKS cluster with Auto DevOps](https://about.gitlab.com/blog/2020/05/05/deploying-application-eks/)
+
+## Deploy to Google Cloud
+
+- [Deploying with GitLab on Google Cloud](https://about.gitlab.com/solutions/google-cloud-platform/)
diff --git a/doc/ci/directed_acyclic_graph/index.md b/doc/ci/directed_acyclic_graph/index.md
index 19da0496f8a..04f27c584b7 100644
--- a/doc/ci/directed_acyclic_graph/index.md
+++ b/doc/ci/directed_acyclic_graph/index.md
@@ -79,26 +79,28 @@ are certain use cases that you may need to work around. For more information:
- [`needs` requirements and limitations](../yaml/README.md#requirements-and-limitations).
- Related epic [tracking planned improvements](https://gitlab.com/groups/gitlab-org/-/epics/1716).
-## DAG Visualization
+## Needs Visualization
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215517) in GitLab 13.1 as a [Beta feature](https://about.gitlab.com/handbook/product/#beta).
> - It was deployed behind a feature flag, disabled by default.
> - It became [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36802) in 13.2.
> - It became a [standard feature](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38517) in 13.3.
> - It's enabled on GitLab.com.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-dag-visualization).
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-needs-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.
+The needs 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.
-![DAG visualization example](img/dag_graph_example_v13_1.png)
+To see the needs visualization, click on the **Needs** tab when viewing a pipeline that uses the `needs:` keyword.
+
+![Needs visualization example](img/dag_graph_example_v13_1.png)
Clicking a node will highlight all the job paths it depends on.
-![DAG visualization with path highlight](img/dag_graph_example_clicked_v13_1.png)
+![Needs visualization with path highlight](img/dag_graph_example_clicked_v13_1.png)
-### Enable or disable DAG Visualization **(CORE ONLY)**
+### Enable or disable Needs Visualization **(CORE ONLY)**
-DAG Visualization is deployed behind a feature flag that is **enabled by default**.
+The needs visualization is deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
can opt to disable it for your instance:
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index e3123cde1cd..ebbfde09c67 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -90,7 +90,7 @@ GitLab Runner then executes job scripts as the `gitlab-runner` user.
1. You can now use `docker` command (and **install** `docker-compose` if needed).
By adding `gitlab-runner` to the `docker` group you are effectively granting `gitlab-runner` full root permissions.
-For more information please read [On Docker security: `docker` group considered harmful](https://www.andreas-jung.com/contents/on-docker-security-docker-group-considered-harmful).
+For more information please read [On Docker security: `docker` group considered harmful](https://blog.zopyx.com/on-docker-security-docker-group-considered-harmful/).
### Use Docker-in-Docker workflow with Docker executor
@@ -103,7 +103,7 @@ image in privileged mode.
CI builds, follow the `docker-compose`
[installation instructions](https://docs.docker.com/compose/install/).
-DANGER: **Danger:**
+DANGER: **Warning:**
By enabling `--docker-privileged`, you are effectively disabling all of
the security mechanisms of containers and exposing your host to privilege
escalation which can lead to container breakout. For more information, check
@@ -302,7 +302,149 @@ build:
- docker run my-docker-image /script/to/run/tests
```
-### Use Docker socket binding
+#### Enable registry mirror for `docker:dind` service
+
+When the Docker daemon starts inside of the service container, it uses
+the default configuration. You may want to configure a [registry
+mirror](https://docs.docker.com/registry/recipes/mirror/) for
+performance improvements and ensuring you don't reach DockerHub rate limits.
+
+##### Inside `.gitlab-ci.yml`
+
+You can append extra CLI flags to the `dind` service to set the registry
+mirror:
+
+```yaml
+services:
+ - name: docker:19.03.13-dind
+ command: ["--registry-mirror", "https://registry-mirror.example.com"] # Specify the registry mirror to use.
+```
+
+##### DinD service defined inside of GitLab Runner configuration
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27173) in GitLab Runner 13.6.
+
+If you are an administrator of GitLab Runner and you have the `dind`
+service defined for the [Docker
+executor](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnersdockerservices-section),
+or the [Kubernetes
+executor](https://docs.gitlab.com/runner/executors/kubernetes.html#using-services)
+you can specify the `command` to configure the registry mirror for the
+Docker daemon.
+
+Docker:
+
+```toml
+[[runners]]
+ ...
+ executor = "docker"
+ [runners.docker]
+ ...
+ privileged = true
+ [[runners.docker.services]]
+ name = "docker:19.03.13-dind"
+ command = ["--registry-mirror", "https://registry-mirror.example.com"]
+```
+
+Kubernetes:
+
+```toml
+[[runners]]
+ ...
+ name = "kubernetes"
+ [runners.kubernetes]
+ ...
+ privileged = true
+ [[runners.kubernetes.services]]
+ name = "docker:19.03.13-dind"
+ command = ["--registry-mirror", "https://registry-mirror.example.com"]
+```
+
+##### Docker executor inside GitLab Runner configuration
+
+If you are an administrator of GitLab Runner and you want to use
+the mirror for every `dind` service, update the
+[configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)
+to specify a [volume
+mount](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#volumes-in-the-runnersdocker-section).
+
+For example, if you have a `/opt/docker/daemon.json` file with the following
+content:
+
+```json
+{
+ "registry-mirrors": [
+ "https://registry-mirror.example.com"
+ ]
+}
+```
+
+Update the `config.toml` file to mount the file to
+`/etc/docker/daemon.json`. This would mount the file for **every**
+container that is created by GitLab Runner. The configuration will be
+picked up by the `dind` service.
+
+```toml
+[[runners]]
+ ...
+ executor = "docker"
+ [runners.docker]
+ image = "alpine:3.12"
+ privileged = true
+ volumes = ["/opt/docker/daemon.json:/etc/docker/daemon.json:ro"]
+```
+
+##### Kubernetes executor inside GitLab Runner configuration
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3223) in GitLab Runner 13.6.
+
+If you are an administrator of GitLab Runner and you want to use
+the mirror for every `dind` service, update the
+[configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)
+to specify a [ConfigMap volume
+mount](https://docs.gitlab.com/runner/executors/kubernetes.html#using-volumes).
+
+For example, if you have a `/tmp/daemon.json` file with the following
+content:
+
+```json
+{
+ "registry-mirrors": [
+ "https://registry-mirror.example.com"
+ ]
+}
+```
+
+Create a [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/) with the content
+of this file. You can do this with a command like:
+
+```shell
+kubectl create configmap docker-daemon --namespace gitlab-runner --from-file /tmp/daemon.json
+```
+
+NOTE: **Note:**
+Make sure to use the namespace that GitLab Runner Kubernetes executor uses
+to create job pods in.
+
+After the ConfigMap is created, you can update the `config.toml`
+file to mount the file to `/etc/docker/daemon.json`. This update
+mounts the file for **every** container that is created by GitLab Runner.
+The configuration is picked up by the `dind` service.
+
+```toml
+[[runners]]
+ ...
+ executor = "kubernetes"
+ [runners.kubernetes]
+ image = "alpine:3.12"
+ privileged = true
+ [[runners.kubernetes.volumes.config_map]]
+ name = "docker-daemon"
+ mount_path = "/etc/docker/daemon.json"
+ sub_path = "daemon.json"
+```
+
+#### Use Docker socket binding
The third approach is to bind-mount `/var/run/docker.sock` into the
container so that Docker is available in the context of that image.
@@ -502,7 +644,7 @@ and [using the OverlayFS storage driver](https://docs.docker.com/engine/userguid
## Using the GitLab Container Registry
-Once you've built a Docker image, you can push it up to the built-in
+After you've built a Docker image, you can push it up to the built-in
[GitLab Container Registry](../../user/packages/container_registry/index.md#build-and-push-by-using-gitlab-cicd).
## Troubleshooting
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index f7d54aa7d78..b8563182bd9 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -452,9 +452,9 @@ CI jobs:
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
- [`before_script`](../yaml/README.md#before_script-and-after_script),
+ [`before_script`](../yaml/README.md#before_script),
[`script`](../yaml/README.md#script),
- and [`after_script`](../yaml/README.md#before_script-and-after_script)).
+ and [`after_script`](../yaml/README.md#after_script)).
1. The runner sends the script to the container's shell STDIN and receives the
output.
@@ -561,10 +561,11 @@ See below for examples of each.
#### Determining your `DOCKER_AUTH_CONFIG` data
-As an example, let's assume that you want to use the `registry.example.com:5000/private/image:latest`
-image which is private and requires you to login into a private container registry.
+As an example, let's assume you want to use the `registry.example.com:5000/private/image:latest`
+image, which is private and requires you to sign in to a private container
+registry.
-Let's also assume that these are the login credentials:
+Let's also assume that these are the sign-in credentials:
| Key | Value |
|:---------|:----------------------------|
@@ -572,9 +573,9 @@ Let's also assume that these are the login credentials:
| username | `my_username` |
| password | `my_password` |
-There are two ways to determine the value of `DOCKER_AUTH_CONFIG`:
+Use one of the following methods to determine the value of `DOCKER_AUTH_CONFIG`:
-- **First way -** Do a `docker login` on your local machine:
+- Do a `docker login` on your local machine:
```shell
docker login registry.example.com:5000 --username my_username --password my_password
@@ -589,12 +590,11 @@ There are two ways to determine the value of `DOCKER_AUTH_CONFIG`:
docker logout registry.example.com:5000
```
-- **Second way -** In some setups, it's possible that Docker client
- uses the available system key store to store the result of `docker
- login`. In that case, it's impossible to read `~/.docker/config.json`,
- so you need to prepare the required base64-encoded version of
- `${username}:${password}` and create the Docker configuration JSON manually.
- Open a terminal and execute the following command:
+- In some setups, it's possible that Docker client uses the available system key
+ store to store the result of `docker login`. In that case, it's impossible to
+ read `~/.docker/config.json`, so you need to prepare the required
+ base64-encoded version of `${username}:${password}` and create the Docker
+ configuration JSON manually. Open a terminal and execute the following command:
```shell
# The use of "-n" - prevents encoding a newline in the password.
diff --git a/doc/ci/environments/img/protected_access_group_v13_6.png b/doc/ci/environments/img/protected_access_group_v13_6.png
new file mode 100644
index 00000000000..9c39e4362e8
--- /dev/null
+++ b/doc/ci/environments/img/protected_access_group_v13_6.png
Binary files differ
diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md
index baf2156e64a..361b7217d17 100644
--- a/doc/ci/environments/index.md
+++ b/doc/ci/environments/index.md
@@ -34,8 +34,7 @@ currently being deployed or has been deployed on your servers.
It's important to know that:
- Environments are like tags for your CI jobs, describing where code gets deployed.
-- Deployments are created when [jobs](../yaml/README.md#introduction) deploy versions of code to environments,
- so every environment can have one or more deployments.
+- Deployments are created when [GitLab CI/CD](../yaml/README.md) is used to deploy versions of code to environments.
GitLab:
@@ -219,10 +218,17 @@ You can also specify a static part of the URL at `environment:url:`, such as
The assigned URL for the `review/your-branch-name` environment is [visible in the UI](#using-the-environment-url).
-> **Notes:**
->
-> - `stop_review` doesn't generate a dotenv report artifact, so it won't recognize the `DYNAMIC_ENVIRONMENT_URL` variable. Therefore you should not set `environment:url:` in the `stop_review` job.
-> - If the environment URL is not valid (for example, the URL is malformed), the system doesn't update the environment URL.
+Note the following:
+
+- `stop_review` doesn't generate a dotenv report artifact, so it won't recognize the
+ `DYNAMIC_ENVIRONMENT_URL` variable. Therefore you shouldn't set `environment:url:` in the
+ `stop_review` job.
+- If the environment URL isn't valid (for example, the URL is malformed), the system doesn't update
+ the environment URL.
+- If the script that runs in `stop_review` exists only in your repository and therefore can't use
+ `GIT_STRATEGY: none`, configure [pipelines for merge requests](../../ci/merge_request_pipelines/index.md)
+ for these jobs. This ensures that runners can fetch the repository even after a feature branch is
+ deleted. For more information, see [Ref Specs for Runners](../pipelines/index.md#ref-specs-for-runners).
### Configuring manual deployments
@@ -304,7 +310,7 @@ Dynamic environments are a fundamental part of [Review apps](../review_apps/inde
#### Allowed variables
-The `name` and `url` parameters for dynamic environments can use most available CI/CD variables,
+The `name` and `url` keywords for dynamic environments can use most available CI/CD variables,
including:
- [Predefined environment variables](../variables/README.md#predefined-environment-variables)
@@ -436,7 +442,7 @@ The configuration in this section provides a full development workflow where you
- Tested.
- Built.
- Deployed as a Review App.
-- Deployed to a staging server once the merge request is merged.
+- Deployed to a staging server after the merge request is merged.
- Finally, able to be manually deployed to the production server.
The following combines the previous configuration examples, including:
@@ -675,24 +681,23 @@ deploy_review:
name: review/$CI_COMMIT_REF_NAME
url: https://$CI_ENVIRONMENT_SLUG.example.com
on_stop: stop_review
- only:
- - branches
- except:
- - master
+ rules:
+ - if: $CI_MERGE_REQUEST_ID
stop_review:
stage: deploy
- variables:
- GIT_STRATEGY: none
script:
- echo "Remove review app"
- when: manual
environment:
name: review/$CI_COMMIT_REF_NAME
action: stop
+ rules:
+ - if: $CI_MERGE_REQUEST_ID
+ when: manual
```
-Setting the [`GIT_STRATEGY`](../yaml/README.md#git-strategy) to `none` is necessary in the
+If you can't use [Pipelines for merge requests](../merge_request_pipelines/index.md),
+setting the [`GIT_STRATEGY`](../runners/README.md#git-strategy) to `none` is necessary in the
`stop_review` job so that the [runner](https://docs.gitlab.com/runner/) won't
try to check out the code after the branch is deleted.
@@ -748,13 +753,17 @@ review_app:
name: review/$CI_COMMIT_REF_NAME
on_stop: stop_review_app
auto_stop_in: 1 week
+ rules:
+ - if: $CI_MERGE_REQUEST_ID
stop_review_app:
script: stop-review-app
environment:
name: review/$CI_COMMIT_REF_NAME
action: stop
- when: manual
+ rules:
+ - if: $CI_MERGE_REQUEST_ID
+ when: manual
```
As long as a merge request is active and keeps getting new commits,
@@ -923,11 +932,10 @@ the [Kubernetes integration](../../user/project/clusters/index.md)), GitLab can
a terminal session to your environment.
This is a powerful feature that allows you to debug issues without leaving the comfort
-of your web browser. To enable it, just follow the instructions given in the service integration
+of your web browser. To enable it, follow the instructions given in the service integration
documentation.
-NOTE: **Note:**
-Container-based deployments often lack basic tools (like an editor), and may
+Note that container-based deployments often lack basic tools (like an editor), and may
be stopped or restarted at any time. If this happens, you will lose all your
changes. Treat this as a debugging tool, not a comprehensive online IDE.
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index 87bced29906..eeb95947ba1 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -45,6 +45,61 @@ To protect an environment:
The protected environment will now appear in the list of protected environments.
+### Use the API to protect an environment
+
+Alternatively, you can use the API to protect an environment:
+
+1. Use a project with a CI that creates an environment. For example:
+
+ ```yaml
+ stages:
+ - test
+ - deploy
+
+ test:
+ stage: test
+ script:
+ - 'echo "Testing Application: ${CI_PROJECT_NAME}"'
+
+ production:
+ stage: deploy
+ when: manual
+ script:
+ - 'echo "Deploying to ${CI_ENVIRONMENT_NAME}"'
+ environment:
+ name: ${CI_JOB_NAME}
+ ```
+
+1. Use the UI to [create a new group](../../user/group/index.md#create-a-new-group).
+ For example, this group is called `protected-access-group` and has the group ID `9899826`. Note
+ that the rest of the examples in these steps use this group.
+
+ ![Group Access](img/protected_access_group_v13_6.png)
+
+1. Use the API to add a user to the group as a reporter:
+
+ ```shell
+ $ curl --request POST --header "PRIVATE-TOKEN: xxxxxxxxxxxx" --data "user_id=3222377&access_level=20" "https://gitlab.com/api/v4/groups/9899826/members"
+
+ {"id":3222377,"name":"Sean Carroll","username":"sfcarroll","state":"active","avatar_url":"https://assets.gitlab-static.net/uploads/-/system/user/avatar/3222377/avatar.png","web_url":"https://gitlab.com/sfcarroll","access_level":20,"created_at":"2020-10-26T17:37:50.309Z","expires_at":null}
+ ```
+
+1. Use the API to add the group to the project as a reporter:
+
+ ```shell
+ $ curl --request POST --header "PRIVATE-TOKEN: xxxxxxxxxxxx" --request POST "https://gitlab.com/api/v4/projects/22034114/share?group_id=9899826&group_access=20"
+
+ {"id":1233335,"project_id":22034114,"group_id":9899826,"group_access":20,"expires_at":null}
+ ```
+
+1. Use the API to add the group with protected environment access:
+
+ ```shell
+ curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' --header "PRIVATE-TOKEN: xxxxxxxxxxx" "https://gitlab.com/api/v4/projects/22034114/protected_environments"
+ ```
+
+The group now has access and can be seen in the UI.
+
## Environment access by group membership
A user may be granted access to protected environments as part of
@@ -72,8 +127,7 @@ they have the following privileges:
Users granted access to a protected environment, but not push or merge access
to the branch deployed to it, are only granted access to deploy the environment.
-NOTE: **Note:**
-Deployment-only access is the only possible access level for users with
+Note that deployment-only access is the only possible access level for users with
[Reporter permissions](../../user/permissions.md).
## Modifying and unprotecting environments
@@ -84,7 +138,6 @@ 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.
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index 34e3b276d3e..1abb33005ca 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -15,7 +15,7 @@ Examples are available in several forms. As a collection of:
- `.gitlab-ci.yml` [template files](#cicd-templates) maintained in GitLab, for many
common frameworks and programming languages.
-- Repositories with [example projects](https://gitlab.com/gitlab-examples) for various languages. You can fork and adjust them to your own needs. Projects include demonstrations of [multi-project pipelines](https://gitlab.com/gitlab-examples/multi-project-pipelines) and using [Review Apps with a static site served by NGINX](https://gitlab.com/gitlab-examples/review-apps-nginx/).
+- Repositories with [example projects](https://gitlab.com/gitlab-examples) for various languages. You can fork and adjust them to your own needs. Projects include an example of using [Review Apps with a static site served by NGINX](https://gitlab.com/gitlab-examples/review-apps-nginx/).
- Examples and [other resources](#other-resources) listed below.
## CI/CD examples
@@ -42,6 +42,7 @@ The following table lists examples with step-by-step tutorials that are containe
| Scala on Heroku | [Test and deploy a Scala application to Heroku](test-scala-application.md). |
| Parallel testing Ruby & JS | [GitLab CI/CD parallel jobs testing for Ruby & JavaScript projects](https://docs.knapsackpro.com/2019/how-to-run-parallel-jobs-for-rspec-tests-on-gitlab-ci-pipeline-and-speed-up-ruby-javascript-testing). |
| Secrets management with Vault | [Authenticating and Reading Secrets With Hashicorp Vault](authenticating-with-hashicorp-vault/index.md). |
+| Multi project pipeline | [Build, test deploy using multi project pipeline](https://gitlab.com/gitlab-examples/upstream-project). |
### Contributing examples
diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
index 4a0ff2fa6ac..c0fb94acdf2 100644
--- a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
+++ b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
@@ -22,7 +22,8 @@ This tutorial assumes you are familiar with GitLab CI/CD and Vault.
To follow along, you will need:
- An account on GitLab.
-- A running Vault server and the access required to configure authentication and create roles and policies.
+- A running Vault server and access to it is required to configure authentication and create roles
+ and policies. For HashiCorp Vaults, this can be the Open Source or Enterprise version.
NOTE: **Note:**
You will need to replace the `vault.example.com` URL below with the URL of your Vault server and `gitlab.example.com` with the URL of your GitLab instance.
@@ -55,7 +56,7 @@ The JWT's payload looks like this:
}
```
-The JWT is encoded by using RS256 and signed with your GitLab instance's OpenID Connect private key. The expire time for the token will be set to job's timeout, if specified, or 5 minutes if it is not. The key used to sign this token may change without any notice. In such case retrying the job will generate new JWT using the current signing key.
+The JWT is encoded by using RS256 and signed with a dedicated private key. The expire time for the token will be set to job's timeout, if specified, or 5 minutes if it is not. The key used to sign this token may change without any notice. In such case retrying the job will generate new JWT using the current signing key.
You can use this JWT and your instance's JWKS endpoint (`https://gitlab.example.com/-/jwks`) to authenticate with a Vault server that is configured to allow the JWT Authentication method for authentication.
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 b113b10f2e3..25b866a08ed 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
@@ -103,27 +103,27 @@ Hub](https://hub.docker.com/). We've also added the [`only`
clause](../../yaml/README.md#onlyexcept-basic)
to ensure our deployments only happen when we push to the master branch.
-Now, since the steps defined in `.gitlab-ci.yml` require credentials to login
-to CF, you'll need to add your CF credentials as [environment
-variables](../../variables/README.md#predefined-environment-variables)
-on GitLab CI/CD. To set the environment variables, navigate to your project's
-**Settings > CI/CD** and expand **Variables**. Name the variables
+Because the steps defined in `.gitlab-ci.yml` require credentials to sign in to
+CF, you'll need to add your CF credentials as
+[environment variables](../../variables/README.md#predefined-environment-variables)
+in GitLab CI/CD. To set the environment variables, navigate to your project's
+**Settings > CI/CD**, and then expand **Variables**. Name the variables
`CF_USERNAME` and `CF_PASSWORD` and set them to the correct values.
![Variable Settings in GitLab](img/cloud_foundry_variables.png)
-Once set up, GitLab CI/CD will deploy your app to CF at every push to your
-repository's default branch. To see the build logs or watch your builds running
-live, navigate to **CI/CD > Pipelines**.
+After set up, GitLab CI/CD deploys your app to CF at every push to your
+repository's default branch. To review the build logs or watch your builds
+running live, navigate to **CI/CD > Pipelines**.
CAUTION: **Caution:**
-It is considered best practice for security to create a separate deploy
-user for your application and add its credentials to GitLab instead of using
-a developer's credentials.
+It's considered best practice for security to create a separate deploy user for
+your application and add its credentials to GitLab instead of using a
+developer's credentials.
To start a manual deployment in GitLab go to **CI/CD > Pipelines** then click
-on **Run Pipeline**. Once the app is finished deploying it will display the URL
-of your application in the logs for the `production` job like:
+on **Run Pipeline**. After the app is finished deploying, it will display the
+URL of your application in the logs for the `production` job like:
```shell
requested state: started
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 836141af91e..39cad3a0c93 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
@@ -249,7 +249,7 @@ pipeline to include running the tests along with the existing build job.
## Continuous Integration
-To ensure our changes don't break the build and all tests still pass, we utilize
+To ensure our changes don't break the build and all tests still pass, we use
Continuous Integration (CI) to run these checks automatically for every push.
Read through this article to understand [Continuous Integration, Continuous Delivery, and Continuous Deployment](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/),
and how these methods are leveraged by GitLab.
@@ -261,7 +261,7 @@ Please read through the [documentation on CI/CD configuration](../../../ci/yaml/
### Build your game with GitLab CI/CD
We need to update our build job to ensure tests get run as well. Add `gulp build-test`
-to the end of the `script` array for the existing `build` job. Once these commands run,
+to the end of the `script` array for the existing `build` job. After these commands run,
we know we will need to access everything in the `built` folder, given by GitLab CI/CD's `artifacts`.
We'll also cache `node_modules` to avoid having to do a full re-pull of those dependencies:
just pack them up in the cache. Here is the full `build` job:
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 aa6e6f73a0d..42725e8aef9 100644
--- a/doc/ci/examples/end_to_end_testing_webdriverio/index.md
+++ b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
@@ -14,7 +14,7 @@ environment, reducing the effort to assess the impact of changes. Thus, when we
and it will immediately be clear that the application can still be properly built and deployed. After all, you can _see_ it
running!
-<img src="img/deployed_dependency_update.png" alt="dependencies.io" class="image-noshadow">
+<img src="img/deployed_dependency_update.png" alt="dependencies.io">
However, looking at the freshly deployed code to check whether it still looks and behaves as
expected is repetitive manual work, which means it is a prime candidate for automation. This is
@@ -140,7 +140,7 @@ new browser window interacting with your app as you specified.
Which brings us to the exciting part: how do we run this in GitLab CI/CD? There are two things we
need to do for this:
-1. Set up [CI/CD jobs](../../yaml/README.md#introduction) that actually have a browser available.
+1. Set up [CI/CD jobs](../../yaml/README.md) that actually have a browser available.
1. Update our WebdriverIO configuration to use those browsers to visit the review apps.
For the scope of this article, we've defined an additional [CI/CD stage](../../yaml/README.md#stages)
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 aaa34afeddf..f692a8042f5 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -632,7 +632,7 @@ After our code passed through the pipeline successfully, we can deploy to our pr
![pipelines page deploy button](img/pipelines_page_deploy_button.png)
-Once the deploy pipeline passed successfully, navigate to **Pipelines > Environments**.
+After the deploy pipeline passed successfully, navigate to **Pipelines > Environments**.
![environments page](img/environments_page.png)
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 c62f0dec598..9bc9ac5423e 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
@@ -298,7 +298,7 @@ project.
- mix ecto.migrate
```
- This ensures that [rebar3](https://www.rebar3.org) and [hex](https://hex.pm) are both installed
+ This ensures that [rebar3](https://rebar3.org) and [hex](https://hex.pm) are both installed
before attempting to fetch the dependencies that are required to run the tests. Next, the `postgres` db
is created and migrated with `ecto`, to ensure it's up-to-date.
diff --git a/doc/ci/git_submodules.md b/doc/ci/git_submodules.md
index 5bcfe8fa3f1..c28febd15d7 100644
--- a/doc/ci/git_submodules.md
+++ b/doc/ci/git_submodules.md
@@ -78,7 +78,7 @@ correctly with your CI jobs:
GIT_SUBMODULE_STRATEGY: recursive
```
- See the [`.gitlab-ci.yml` reference](yaml/README.md#git-submodule-strategy)
+ See the [GitLab Runner documentation](runners/README.md#git-submodule-strategy)
for more details about `GIT_SUBMODULE_STRATEGY`.
1. If you are using an older version of `gitlab-runner`, then use
diff --git a/doc/ci/interactive_web_terminal/img/interactive_web_terminal_running_job.png b/doc/ci/interactive_web_terminal/img/interactive_web_terminal_running_job.png
index 3ee5e39afc0..8082d17ae6a 100644
--- a/doc/ci/interactive_web_terminal/img/interactive_web_terminal_running_job.png
+++ b/doc/ci/interactive_web_terminal/img/interactive_web_terminal_running_job.png
Binary files differ
diff --git a/doc/ci/interactive_web_terminal/index.md b/doc/ci/interactive_web_terminal/index.md
index 125e7dabecf..a131d21039d 100644
--- a/doc/ci/interactive_web_terminal/index.md
+++ b/doc/ci/interactive_web_terminal/index.md
@@ -16,7 +16,7 @@ is deployed, some [security precautions](../../administration/integration/termin
taken to protect the users.
NOTE: **Note:**
-[Shared runners on GitLab.com](../quick_start/README.md#shared-runners) do not
+[Shared runners on GitLab.com](../runners/README.md#shared-runners) do not
provide an interactive web terminal. Follow [this
issue](https://gitlab.com/gitlab-org/gitlab/-/issues/24674) for progress on
adding support. For groups and projects hosted on GitLab.com, interactive web
diff --git a/doc/ci/introduction/img/gitlab_workflow_example_11_9.png b/doc/ci/introduction/img/gitlab_workflow_example_11_9.png
index f3fb9444b55..1f11db55f81 100644
--- a/doc/ci/introduction/img/gitlab_workflow_example_11_9.png
+++ b/doc/ci/introduction/img/gitlab_workflow_example_11_9.png
Binary files differ
diff --git a/doc/ci/introduction/img/job_running.png b/doc/ci/introduction/img/job_running.png
index d5f922ceb8c..efd138fd4f8 100644
--- a/doc/ci/introduction/img/job_running.png
+++ b/doc/ci/introduction/img/job_running.png
Binary files differ
diff --git a/doc/ci/introduction/index.md b/doc/ci/introduction/index.md
index d1f3e449e5b..b24ee66fdba 100644
--- a/doc/ci/introduction/index.md
+++ b/doc/ci/introduction/index.md
@@ -17,6 +17,14 @@ Out-of-the-box management systems can decrease hours spent on maintaining toolch
Watch our ["Mastering continuous software development"](https://about.gitlab.com/webcast/mastering-ci-cd/)
webcast to learn about continuous methods and how GitLab’s built-in CI can help you simplify and scale software development.
+> For some additional information about GitLab CI/CD:
+>
+> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Watch the [CI/CD Ease of configuration](https://www.youtube.com/embed/opdLqwz6tcE) video.
+> - Watch the [Making the case for CI/CD in your organization](https://about.gitlab.com/compare/github-actions-alternative/)
+> webcast to learn the benefits of CI/CD and how to measure the results of CI/CD automation.
+> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Learn how [Verizon reduced rebuilds](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/)
+> from 30 days to under 8 hours with GitLab.
+
## Introduction to CI/CD methodologies
The continuous methodologies of software development are based on
@@ -93,7 +101,7 @@ In this file, you can define the scripts you want to run, define include and
cache dependencies, choose commands you want to run in sequence
and those you want to run in parallel, define where you want to
deploy your app, and specify whether you will want to run the scripts automatically
-or trigger any of them manually. Once you're familiar with
+or trigger any of them manually. After you're familiar with
GitLab CI/CD you can add more advanced steps into the configuration file.
To add scripts to that file, you'll need to organize them in a
@@ -102,7 +110,7 @@ the tests you wish to perform. To visualize the process, imagine
that all the scripts you add to the configuration file are the
same as the commands you run on a terminal on your computer.
-Once you've added your `.gitlab-ci.yml` configuration file to your
+After you've added your `.gitlab-ci.yml` configuration file to your
repository, GitLab will detect it and run your scripts with the
tool called [GitLab Runner](https://docs.gitlab.com/runner/), which
works similarly to your terminal.
@@ -149,7 +157,7 @@ Consider the following example for how GitLab CI/CD fits in a
common development workflow.
Assume that you have discussed a code implementation in an issue
-and worked locally on your proposed changes. Once you push your
+and worked locally on your proposed changes. After you push your
commits to a feature branch in a remote repository in GitLab,
the CI/CD pipeline set for your project is triggered. By doing
so, GitLab CI/CD:
@@ -159,7 +167,7 @@ so, GitLab CI/CD:
- Preview the changes per merge request with Review Apps, as you
would see in your `localhost`.
-Once you're happy with your implementation:
+After you're happy with your implementation:
- Get your code reviewed and approved.
- Merge the feature branch into the default branch.
diff --git a/doc/ci/pipelines/img/collapsible_log_v12_6.png b/doc/ci/jobs/img/collapsible_log_v12_6.png
index a1e9aeb244a..a1e9aeb244a 100644
--- a/doc/ci/pipelines/img/collapsible_log_v12_6.png
+++ b/doc/ci/jobs/img/collapsible_log_v12_6.png
Binary files differ
diff --git a/doc/ci/pipelines/img/job_failure_reason.png b/doc/ci/jobs/img/job_failure_reason.png
index d44b8e6d1be..d44b8e6d1be 100644
--- a/doc/ci/pipelines/img/job_failure_reason.png
+++ b/doc/ci/jobs/img/job_failure_reason.png
Binary files differ
diff --git a/doc/ci/pipelines/img/job_group_v12_10.png b/doc/ci/jobs/img/job_group_v12_10.png
index 27e6bfbfc0f..27e6bfbfc0f 100644
--- a/doc/ci/pipelines/img/job_group_v12_10.png
+++ b/doc/ci/jobs/img/job_group_v12_10.png
Binary files differ
diff --git a/doc/ci/jobs/img/manual_job_variables.png b/doc/ci/jobs/img/manual_job_variables.png
new file mode 100644
index 00000000000..63801ade21f
--- /dev/null
+++ b/doc/ci/jobs/img/manual_job_variables.png
Binary files differ
diff --git a/doc/ci/pipelines/img/pipeline_incremental_rollout.png b/doc/ci/jobs/img/pipeline_incremental_rollout.png
index b3498e9a5a5..b3498e9a5a5 100644
--- a/doc/ci/pipelines/img/pipeline_incremental_rollout.png
+++ b/doc/ci/jobs/img/pipeline_incremental_rollout.png
Binary files differ
diff --git a/doc/ci/pipelines/img/pipelines_grouped.png b/doc/ci/jobs/img/pipelines_grouped.png
index 82814754747..82814754747 100644
--- a/doc/ci/pipelines/img/pipelines_grouped.png
+++ b/doc/ci/jobs/img/pipelines_grouped.png
Binary files differ
diff --git a/doc/ci/pipelines/img/pipelines_mini_graph_sorting.png b/doc/ci/jobs/img/pipelines_mini_graph_sorting.png
index 3a4e5453360..3a4e5453360 100644
--- a/doc/ci/pipelines/img/pipelines_mini_graph_sorting.png
+++ b/doc/ci/jobs/img/pipelines_mini_graph_sorting.png
Binary files differ
diff --git a/doc/ci/jobs/index.md b/doc/ci/jobs/index.md
new file mode 100644
index 00000000000..dc306ac7ecb
--- /dev/null
+++ b/doc/ci/jobs/index.md
@@ -0,0 +1,251 @@
+---
+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
+---
+
+# Jobs
+
+Pipeline configuration begins with jobs. Jobs are the most fundamental element of a `.gitlab-ci.yml` file.
+
+Jobs are:
+
+- Defined with constraints stating under what conditions they should be executed.
+- Top-level elements with an arbitrary name and must contain at least the [`script`](../yaml/README.md#script) clause.
+- Not limited in how many can be defined.
+
+For example:
+
+```yaml
+job1:
+ script: "execute-script-for-job1"
+
+job2:
+ script: "execute-script-for-job2"
+```
+
+The above example is the simplest possible CI/CD configuration with two separate
+jobs, where each of the jobs executes a different command.
+Of course a command can execute code directly (`./configure;make;make install`)
+or run a script (`test.sh`) in the repository.
+
+Jobs are picked up by [runners](../runners/README.md) and executed within the
+environment of the runner. What is important is that each job is run
+independently from each other.
+
+## View jobs in a pipeline
+
+When you access a pipeline, you can see the related jobs for that pipeline.
+
+Clicking an individual job shows you its job log, and allows you to:
+
+- Cancel the job.
+- Retry the job.
+- Erase the job log.
+
+## See why a job failed
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17782) in GitLab 10.7.
+
+When a pipeline fails or is allowed to fail, there are several places where you
+can find the reason:
+
+- In the [pipeline graph](../pipelines/index.md#visualize-pipelines), on the pipeline detail view.
+- In the pipeline widgets, in the merge requests and commit pages.
+- In the job views, in the global and detailed views of a job.
+
+In each place, if you hover over the failed job you can see the reason it failed.
+
+![Pipeline detail](img/job_failure_reason.png)
+
+In [GitLab 10.8](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17814) and later,
+you can also see the reason it failed on the Job detail page.
+
+## The order of jobs in a pipeline
+
+The order of jobs in a pipeline depends on the type of pipeline graph.
+
+- For [regular pipeline graphs](../pipelines/index.md#regular-pipeline-graphs), jobs are sorted by name.
+- For [pipeline mini graphs](../pipelines/index.md#pipeline-mini-graphs), jobs are sorted by severity and then by name.
+
+The order of severity is:
+
+- failed
+- warning
+- pending
+- running
+- manual
+- scheduled
+- canceled
+- success
+- skipped
+- created
+
+For example:
+
+![Pipeline mini graph sorting](img/pipelines_mini_graph_sorting.png)
+
+## Group jobs in a pipeline
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6242) in GitLab 8.12.
+
+If you have many similar jobs, your [pipeline graph](../pipelines/index.md#visualize-pipelines) becomes long and hard
+to read.
+
+You can automatically group similar jobs together. If the job names are formatted in a certain way,
+they are collapsed into a single group in regular pipeline graphs (not the mini graphs).
+
+You can recognize when a pipeline has grouped jobs if you don't see the retry or
+cancel button inside them. Hovering over them shows the number of grouped
+jobs. Click to expand them.
+
+![Grouped pipelines](img/pipelines_grouped.png)
+
+To create a group of jobs, in the [CI/CD pipeline configuration file](../yaml/README.md),
+separate each job name with a number and one of the following:
+
+- A slash (`/`), for example, `test 1/3`, `test 2/3`, `test 3/3`.
+- A colon (`:`), for example, `test 1:3`, `test 2:3`, `test 3:3`.
+- A space, for example `test 0 3`, `test 1 3`, `test 2 3`.
+
+You can use these symbols interchangeably.
+
+In the example below, these three jobs are in a group named `build ruby`:
+
+```yaml
+build ruby 1/3:
+ stage: build
+ script:
+ - echo "ruby1"
+
+build ruby 2/3:
+ stage: build
+ script:
+ - echo "ruby2"
+
+build ruby 3/3:
+ stage: build
+ script:
+ - echo "ruby3"
+```
+
+In the pipeline, the result is a group named `build ruby` with three jobs:
+
+![Job group](img/job_group_v12_10.png)
+
+The jobs are be ordered by comparing the numbers from left to right. You
+usually want the first number to be the index and the second number to be the total.
+
+[This regular expression](https://gitlab.com/gitlab-org/gitlab/blob/2f3dc314f42dbd79813e6251792853bc231e69dd/app/models/commit_status.rb#L99)
+evaluates the job names: `\d+[\s:\/\\]+\d+\s*`.
+
+## Specifying variables when running manual jobs
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30485) in GitLab 12.2.
+
+When running manual jobs you can supply additional job specific variables.
+
+You can do this from the job page of the manual job you want to run with
+additional variables. To access this page, click on the **name** of the manual job in
+the pipeline view, *not* the play (**{play}**) button.
+
+This is useful when you want to alter the execution of a job that uses
+[custom environment variables](../variables/README.md#custom-environment-variables).
+Add a variable name (key) and value here to override the value defined in
+[the UI or `.gitlab-ci.yml`](../variables/README.md#custom-environment-variables),
+for a single run of the manual job.
+
+![Manual job variables](img/manual_job_variables.png)
+
+## Delay a job
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21767) in GitLab 11.4.
+
+When you do not want to run a job immediately, you can use the [`when:delayed`](../yaml/README.md#whendelayed) keyword to
+delay a job's execution for a certain period.
+
+This is especially useful for timed incremental rollout where new code is rolled out gradually.
+
+For example, if you start rolling out new code and:
+
+- Users do not experience trouble, GitLab can automatically complete the deployment from 0% to 100%.
+- Users experience trouble with the new code, you can stop the timed incremental rollout by canceling the pipeline
+ and [rolling](../environments/index.md#retrying-and-rolling-back) back to the last stable version.
+
+![Pipelines example](img/pipeline_incremental_rollout.png)
+
+## Expand and collapse job log sections
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14664) in GitLab 12.0.
+
+Job logs are divided into sections that can be collapsed or expanded. Each section displays
+the duration.
+
+In the following example:
+
+- Two sections are collapsed and can be expanded.
+- Three sections are expanded and can be collapsed.
+
+![Collapsible sections](img/collapsible_log_v12_6.png)
+
+### Custom collapsible sections
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14664) in GitLab 12.0.
+
+You can create [collapsible sections in job logs](#expand-and-collapse-job-log-sections)
+by manually outputting special codes
+that GitLab uses to determine what sections to collapse:
+
+- Section start marker: `section_start:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + `TEXT_OF_SECTION_HEADER`
+- Section end marker: `section_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K`
+
+You must add these codes to the script section of the CI configuration. For example,
+using `echo`:
+
+```yaml
+job1:
+ script:
+ - echo -e "section_start:`date +%s`:my_first_section\r\e[0KHeader of the 1st collapsible section"
+ - echo 'this line should be hidden when collapsed'
+ - echo -e "section_end:`date +%s`:my_first_section\r\e[0K"
+```
+
+In the example above:
+
+- `date +%s`: The Unix timestamp (for example `1560896352`).
+- `my_first_section`: The name given to the section.
+- `\r\e[0K`: Prevents the section markers from displaying in the rendered (colored)
+ job log, but they are displayed in the raw job log. To see them, in the top right
+ of the job log, click **{doc-text}** (**Show complete raw**).
+ - `\r`: carriage return.
+ - `\e[0K`: clear line ANSI escape code.
+
+Sample raw job log:
+
+```plaintext
+section_start:1560896352:my_first_section\r\e[0KHeader of the 1st collapsible section
+this line should be hidden when collapsed
+section_end:1560896353:my_first_section\r\e[0K
+```
+
+### Pre-collapse sections
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/198413) in GitLab 13.5.
+
+You can make the job log automatically collapse collapsible sections by adding the `collapsed` option to the section start.
+Add `[collapsed=true]` after the section name and before the `\r`. The section end marker
+remains unchanged:
+
+- Section start marker with `[collapsed=true]`: `section_start:UNIX_TIMESTAMP:SECTION_NAME[collapsed=true]\r\e[0K` + `TEXT_OF_SECTION_HEADER`
+- Section end marker: `section_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K`
+
+Add the updated section start text to the CI configuration. For example,
+using `echo`:
+
+```yaml
+job1:
+ script:
+ - echo -e "section_start:`date +%s`:my_first_section[collapsed=true]\r\e[0KHeader of the 1st collapsible section"
+ - echo 'this line should be hidden automatically after loading the job log'
+ - echo -e "section_end:`date +%s`:my_first_section\r\e[0K"
+```
diff --git a/doc/ci/large_repositories/index.md b/doc/ci/large_repositories/index.md
index 0019eb5f40c..f25ef7c725a 100644
--- a/doc/ci/large_repositories/index.md
+++ b/doc/ci/large_repositories/index.md
@@ -56,29 +56,16 @@ test:
> Introduced in GitLab Runner 8.9.
-By default, GitLab is configured to always prefer the `GIT_STRATEGY: fetch` strategy.
-The `GIT_STRATEGY: fetch` strategy will re-use existing worktrees if found
-on disk. This is different to the `GIT_STRATEGY: clone` strategy
-as in case of clones, if a worktree is found, it is removed before clone.
-
-Usage of `fetch` is preferred because it reduces the amount of data to transfer and
+By default, GitLab is configured to use the [`fetch` Git strategy](../runners/README.md#git-strategy),
+which is recommended for large repositories.
+This strategy reduces the amount of data to transfer and
does not really impact the operations that you might do on a repository from CI.
-However, `fetch` does require access to the previous worktree. This works
-well when using the `shell` or `docker` executor because these
-try to preserve worktrees and try to re-use them by default.
-
-This does not work today for `kubernetes` executor and has limitations when using
-`docker+machine`. `kubernetes` executor today always clones into ephemeral directory.
-
-GitLab also offers the `GIT_STRATEGY: none` strategy. This disables any `fetch` and `checkout` commands
-done by GitLab, requiring you to do them.
-
## Git clone path
> Introduced in GitLab Runner 11.10.
-[`GIT_CLONE_PATH`](../yaml/README.md#custom-build-directories) allows you to
+[`GIT_CLONE_PATH`](../runners/README.md#custom-build-directories) allows you to
control where you clone your sources. This can have implications if you
heavily use big repositories with fork workflow.
@@ -90,7 +77,7 @@ In such cases, ideally you want to make the GitLab Runner executor be used only
for the given project and not shared across different projects to make this
process more efficient.
-The [`GIT_CLONE_PATH`](../yaml/README.md#custom-build-directories) has to be
+The [`GIT_CLONE_PATH`](../runners/README.md#custom-build-directories) has to be
within the `$CI_BUILDS_DIR`. Currently, it is impossible to pick any path
from disk.
@@ -98,12 +85,12 @@ from disk.
> Introduced in GitLab Runner 11.10.
-[`GIT_CLEAN_FLAGS`](../yaml/README.md#git-clean-flags) allows you to control
+[`GIT_CLEAN_FLAGS`](../runners/README.md#git-clean-flags) allows you to control
whether or not you require the `git clean` command to be executed for each CI
job. By default, GitLab ensures that you have your worktree on the given SHA,
and that your repository is clean.
-[`GIT_CLEAN_FLAGS`](../yaml/README.md#git-clean-flags) is disabled when set
+[`GIT_CLEAN_FLAGS`](../runners/README.md#git-clean-flags) is disabled when set
to `none`. On very big repositories, this might be desired because `git
clean` is disk I/O intensive. Controlling that with `GIT_CLEAN_FLAGS: -ffdx
-e .build/` (for example) allows you to control and disable removal of some
@@ -112,7 +99,7 @@ the incremental builds. This has the biggest effect if you re-use existing
machines and have an existing worktree that you can re-use for builds.
For exact parameters accepted by
-[`GIT_CLEAN_FLAGS`](../yaml/README.md#git-clean-flags), see the documentation
+[`GIT_CLEAN_FLAGS`](../runners/README.md#git-clean-flags), see the documentation
for [`git clean`](https://git-scm.com/docs/git-clean). The available parameters
are dependent on Git version.
@@ -120,14 +107,14 @@ are dependent on Git version.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4142) in GitLab Runner 13.1.
-[`GIT_FETCH_EXTRA_FLAGS`](../yaml/README.md#git-fetch-extra-flags) allows you
+[`GIT_FETCH_EXTRA_FLAGS`](../runners/README.md#git-fetch-extra-flags) allows you
to modify `git fetch` behavior by passing extra flags.
For example, if your project contains a large number of tags that your CI jobs don't rely on,
you could add [`--no-tags`](https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt---no-tags)
to the extra flags to make your fetches faster and more compact.
-See the [`GIT_FETCH_EXTRA_FLAGS` documentation](../yaml/README.md#git-fetch-extra-flags)
+See the [`GIT_FETCH_EXTRA_FLAGS` documentation](../runners/README.md#git-fetch-extra-flags)
for more information.
## Fork-based workflow
diff --git a/doc/ci/lint.md b/doc/ci/lint.md
index 716a4218d97..cef71a68d72 100644
--- a/doc/ci/lint.md
+++ b/doc/ci/lint.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# CI Lint
If you want to test the validity of your GitLab CI/CD configuration before committing
@@ -11,7 +17,8 @@ in your project and click **CI lint**.
## Validate basic logic and syntax
By default, the CI lint checks the syntax of your CI YAML configuration and also runs
-some basic logical validations.
+some basic logical validations. Configuration added with the [`includes` keyword](yaml/README.md#include),
+is also validated.
To use the CI lint, paste a complete CI configuration (`.gitlab-ci.yml` for example)
into the text box and click **Validate**:
diff --git a/doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_MR_v12_09.png b/doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_MR_v12_09.png
deleted file mode 100644
index 3e4c72b9279..00000000000
--- a/doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_MR_v12_09.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_branch_v12_09.png b/doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_branch_v12_09.png
deleted file mode 100644
index dd70c3f8c20..00000000000
--- a/doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_branch_v12_09.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md
index cc0b4ac1f86..ac9cda4e46c 100644
--- a/doc/ci/merge_request_pipelines/index.md
+++ b/doc/ci/merge_request_pipelines/index.md
@@ -56,7 +56,7 @@ below.
When you use this method, you have to specify `only: - merge_requests` for each job. In this
example, the pipeline contains a `test` job that is configured to run on merge requests.
-The `build` and `deploy` jobs don't have the `only: - merge_requests` parameter,
+The `build` and `deploy` jobs don't have the `only: - merge_requests` keyword,
so they will not run on merge requests.
```yaml
@@ -81,8 +81,8 @@ deploy:
#### Excluding certain jobs
-The behavior of the `only: [merge_requests]` parameter is such that _only_ jobs with
-that parameter are run in the context of a merge request; no other jobs will be run.
+The behavior of the `only: [merge_requests]` keyword is such that _only_ jobs with
+that keyword are run in the context of a merge request; no other jobs will be run.
However, you can invert this behavior and have all of your jobs run _except_
for one or two.
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline_config.png b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline_config.png
deleted file mode 100644
index 3ee9d8ec93b..00000000000
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline_config.png
+++ /dev/null
Binary files differ
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 2330bdb4c7c..9c6fbba1337 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
@@ -56,7 +56,7 @@ To enable pipelines for merged results for your project:
1. [Configure your CI/CD configuration file](../index.md#configuring-pipelines-for-merge-requests)
so that the pipeline or individual jobs run for merge requests.
1. Visit your project's **Settings > General** and expand **Merge requests**.
-1. Check **Enable merge trains and pipelines for merged results**.
+1. Check **Enable merged results pipelines.**.
1. Click **Save changes**.
CAUTION: **Caution:**
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_config_v12_0.png b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_config_v12_0.png
deleted file mode 100644
index 9da959ad440..00000000000
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_config_v12_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_immediate_merge.png b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_immediate_merge.png
deleted file mode 100644
index 03bc61129ba..00000000000
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_immediate_merge.png
+++ /dev/null
Binary files differ
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 45cae49377f..d4099cdeafd 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
@@ -82,9 +82,13 @@ To enable merge trains for your project:
1. If you are on a self-managed GitLab instance, ensure the [feature flag](#merge-trains-feature-flag) is set correctly.
1. [Configure your CI/CD configuration file](../../index.md#configuring-pipelines-for-merge-requests)
so that the pipeline or individual jobs run for merge requests.
-1. Visit your project's **Settings > General** and expand **Merge requests**.
-1. Check **Enable merge trains and pipelines for merged results**.
-1. Click **Save changes**.
+1. Visit your project's **Settings > General** and expand **Merge requests**
+1. Check **Enable merged results pipelines.** (if not enabled)
+1. Check **Enable merge trains.**
+1. Click **Save changes**
+
+In GitLab 13.5 and earlier, there is only one checkbox, named
+**Enable merge trains and pipelines for merged results**.
CAUTION: **Caution:**
If you select the check box but don't configure your CI/CD to use
@@ -200,17 +204,26 @@ for more information.
### Merge Trains feature flag **(PREMIUM ONLY)**
-To enable and disable the Merge Trains feature, use the `:disable_merge_trains` feature flag.
+In [GitLab 13.6 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/244831),
+you can [enable or disable merge trains in the project settings](#enable-merge-trains).
+
+In GitLab 13.5 and earlier, merge trains are automatically enabled when
+[pipelines for merged results](../index.md#pipelines-for-merged-results) are enabled.
+To use pipelines for merged results without using merge trains, you can enable a
+[feature flag](../../../../user/feature_flags.md) that blocks the merge trains feature.
-To check if the feature flag is enabled on your GitLab instance,
-ask an administrator to execute the following commands:
+[GitLab administrators with access to the GitLab Rails console](../../../../administration/feature_flags.md)
+can enable the feature flag to disable merge trains:
-```shell
-> sudo gitlab-rails console # Login to Rails console of GitLab instance.
-> Feature.enabled?(:disable_merge_trains) # Check if it's disabled or not.
-> Feature.enable(:disable_merge_trains) # Disable Merge Trains.
-> Feature.disable(:disable_merge_trains) # Enable Merge Trains.
+```ruby
+Feature.enable(:disable_merge_trains)
```
-When you disable this feature, all existing merge trains are cancelled and
+After you enable this feature flag, all existing merge trains are cancelled and
the **Start/Add to Merge Train** button no longer appears in merge requests.
+
+To disable the feature flag, and enable merge trains again:
+
+```ruby
+Feature.disable(:disable_merge_trains)
+```
diff --git a/doc/ci/metrics_reports.md b/doc/ci/metrics_reports.md
index 53e097760e6..dbc0397bb0b 100644
--- a/doc/ci/metrics_reports.md
+++ b/doc/ci/metrics_reports.md
@@ -17,7 +17,7 @@ You can configure your job to use custom Metrics Reports, and GitLab will displa
## Use cases
-Consider the following examples of data that can utilize Metrics Reports:
+Consider the following examples of data that can use Metrics Reports:
1. Memory usage
1. Load testing results
diff --git a/doc/ci/migration/circleci.md b/doc/ci/migration/circleci.md
index 6de494bceaf..13190c15cca 100644
--- a/doc/ci/migration/circleci.md
+++ b/doc/ci/migration/circleci.md
@@ -10,7 +10,7 @@ type: index, howto
If you are currently using CircleCI, you can migrate your CI/CD pipelines to [GitLab CI/CD](../introduction/index.md),
and start making use of all its powerful features. Check out our
-[CircleCI vs GitLab](https://about.gitlab.com/devops-tools/circle-ci-vs-gitlab.html)
+[CircleCI vs GitLab](https://about.gitlab.com/devops-tools/circle-ci-vs-gitlab/)
comparison to see what's different.
We have collected several resources that you may find useful before starting to migrate.
@@ -27,7 +27,7 @@ CircleCI's `config.yml` configuration file defines scripts, jobs, and workflows
### Jobs
-In CircleCI, jobs are a collection of steps to perform a specific task. In GitLab, [jobs](../yaml/README.md#introduction) are also a fundamental element in the configuration file. The `checkout` parameter is not necessary in GitLab CI/CD as the repository is automatically fetched.
+In CircleCI, jobs are a collection of steps to perform a specific task. In GitLab, [jobs](../jobs/index.md) are also a fundamental element in the configuration file. The `checkout` keyword is not necessary in GitLab CI/CD as the repository is automatically fetched.
CircleCI example job definition:
diff --git a/doc/ci/migration/jenkins.md b/doc/ci/migration/jenkins.md
index 1130c11f472..afec94ca91c 100644
--- a/doc/ci/migration/jenkins.md
+++ b/doc/ci/migration/jenkins.md
@@ -258,7 +258,7 @@ stages:
```
Setting a step to be performed before and after any job can be done via the
-[`before_script` and `after_script` keywords](../yaml/README.md#before_script-and-after_script):
+[`before_script`](../yaml/README.md#before_script) and [`after_script`](../yaml/README.md#after_script) keywords:
```yaml
default:
diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md
index 378adcd35e9..5837bf6cf6b 100644
--- a/doc/ci/multi_project_pipelines.md
+++ b/doc/ci/multi_project_pipelines.md
@@ -305,7 +305,7 @@ Some features are not implemented yet. For example, support for environments.
- `when` (only with `on_success`, `on_failure`, and `always` values)
- `extends`
-## Trigger a pipeline when an upstream project is rebuilt
+## Trigger a pipeline when an upstream project is rebuilt **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9045) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.8.
@@ -322,6 +322,9 @@ will now trigger a pipeline on the current project's default branch. The maximum
number of upstream pipeline subscriptions is 2 by default, for both the upstream and
downstream projects. This [application limit](../administration/instance_limits.md#number-of-cicd-subscriptions-to-a-project) can be changed on self-managed instances by a GitLab administrator.
+The upstream project needs to be [public](../public_access/public_access.md) for
+pipeline subscription to work.
+
## Downstream private projects confidentiality concern
If you trigger a pipeline in a downstream private project, the name of the project
diff --git a/doc/ci/pipelines/img/manual_job_variables.png b/doc/ci/pipelines/img/manual_job_variables.png
deleted file mode 100644
index a5ed351fdcd..00000000000
--- a/doc/ci/pipelines/img/manual_job_variables.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md
index f7e3698b6d4..f22d2373e5f 100644
--- a/doc/ci/pipelines/index.md
+++ b/doc/ci/pipelines/index.md
@@ -68,7 +68,7 @@ Pipelines can be configured in many different ways:
Pipelines and their component jobs and stages are defined in the CI/CD pipeline configuration file for each project.
-- Jobs are the [basic configuration](../yaml/README.md#introduction) component.
+- [Jobs](../jobs/index.md) are the basic configuration component.
- Stages are defined by using the [`stages`](../yaml/README.md#stages) keyword.
For a list of configuration options in the CI pipeline file, see the [GitLab CI/CD Pipeline Configuration Reference](../yaml/README.md).
@@ -79,6 +79,27 @@ You can also configure specific aspects of your pipelines through the GitLab UI.
- [Pipeline schedules](schedules.md).
- [Custom CI/CD variables](../variables/README.md#custom-environment-variables).
+### Ref Specs for Runners
+
+When a runner picks a pipeline job, GitLab provides that job's metadata. This includes the [Git refspecs](https://git-scm.com/book/en/v2/Git-Internals-The-Refspec),
+which indicate which ref (branch, tag, and so on) and commit (SHA1) are checked out from your
+project repository.
+
+This table lists the refspecs injected for each pipeline type:
+
+| Pipeline type | Refspecs |
+|--------------- |---------------------------------------- |
+| Pipeline for Branches | `+refs/pipelines/<id>:refs/pipelines/<id>` and `+refs/heads/<name>:refs/remotes/origin/<name>` |
+| pipeline for Tags | `+refs/pipelines/<id>:refs/pipelines/<id>` and `+refs/tags/<name>:refs/tags/<name>` |
+| [Pipeline for Merge Requests](../merge_request_pipelines/index.md) | `+refs/pipelines/<id>:refs/pipelines/<id>` |
+
+The refs `refs/heads/<name>` and `refs/tags/<name>` exist in your
+project repository. GitLab generates the special ref `refs/pipelines/<id>` during a
+running pipeline job. This ref can be created even after the associated branch or tag has been
+deleted. It's therefore useful in some features such as [automatically stopping an environment](../environments/index.md#automatically-stopping-an-environment),
+and [merge trains](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md)
+that might run pipelines after branch deletion.
+
### View pipelines
You can find the current and historical pipeline runs under your project's
@@ -157,7 +178,7 @@ For each `var` or `file_var`, a key and value are required.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7931) in GitLab 8.15.
-Manual actions, configured using the [`when:manual`](../yaml/README.md#whenmanual) parameter,
+Manual actions, configured using the [`when:manual`](../yaml/README.md#whenmanual) keyword,
allow you to require manual interaction before moving forward in the pipeline.
You can do this straight from the pipeline graph. Just click the play button
@@ -174,7 +195,7 @@ stage has a job with a manual action.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27188) in GitLab 11.11.
Multiple manual actions in a single stage can be started at the same time using the "Play all manual" button.
-Once you click this button, each individual manual action is triggered and refreshed
+After you click this button, each individual manual action is triggered and refreshed
to an updated status.
This functionality is only available:
@@ -266,223 +287,6 @@ preserving deployment keys and other credentials from being unintentionally
accessed. In order to ensure that jobs intended to be executed on protected
runners do not use regular runners, they must be tagged accordingly.
-## View jobs in a pipeline
-
-When you access a pipeline, you can see the related jobs for that pipeline.
-
-Clicking an individual job shows you its job log, and allows you to:
-
-- Cancel the job.
-- Retry the job.
-- Erase the job log.
-
-### See why a job failed
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17782) in GitLab 10.7.
-
-When a pipeline fails or is allowed to fail, there are several places where you
-can find the reason:
-
-- In the [pipeline graph](#visualize-pipelines), on the pipeline detail view.
-- In the pipeline widgets, in the merge requests and commit pages.
-- In the job views, in the global and detailed views of a job.
-
-In each place, if you hover over the failed job you can see the reason it failed.
-
-![Pipeline detail](img/job_failure_reason.png)
-
-In [GitLab 10.8](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17814) and later,
-you can also see the reason it failed on the Job detail page.
-
-### The order of jobs in a pipeline
-
-The order of jobs in a pipeline depends on the type of pipeline graph.
-
-- For [regular pipeline graphs](#regular-pipeline-graphs), jobs are sorted by name.
-- For [pipeline mini graphs](#pipeline-mini-graphs), jobs are sorted by severity and then by name.
-
-The order of severity is:
-
-- failed
-- warning
-- pending
-- running
-- manual
-- scheduled
-- canceled
-- success
-- skipped
-- created
-
-For example:
-
-![Pipeline mini graph sorting](img/pipelines_mini_graph_sorting.png)
-
-### Group jobs in a pipeline
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6242) in GitLab 8.12.
-
-If you have many similar jobs, your [pipeline graph](#visualize-pipelines) becomes long and hard
-to read.
-
-You can automatically group similar jobs together. If the job names are formatted in a certain way,
-they are collapsed into a single group in regular pipeline graphs (not the mini graphs).
-
-You can recognize when a pipeline has grouped jobs if you don't see the retry or
-cancel button inside them. Hovering over them shows the number of grouped
-jobs. Click to expand them.
-
-![Grouped pipelines](img/pipelines_grouped.png)
-
-To create a group of jobs, in the [CI/CD pipeline configuration file](../yaml/README.md),
-separate each job name with a number and one of the following:
-
-- A slash (`/`), for example, `test 1/3`, `test 2/3`, `test 3/3`.
-- A colon (`:`), for example, `test 1:3`, `test 2:3`, `test 3:3`.
-- A space, for example `test 0 3`, `test 1 3`, `test 2 3`.
-
-You can use these symbols interchangeably.
-
-In the example below, these three jobs are in a group named `build ruby`:
-
-```yaml
-build ruby 1/3:
- stage: build
- script:
- - echo "ruby1"
-
-build ruby 2/3:
- stage: build
- script:
- - echo "ruby2"
-
-build ruby 3/3:
- stage: build
- script:
- - echo "ruby3"
-```
-
-In the pipeline, the result is a group named `build ruby` with three jobs:
-
-![Job group](img/job_group_v12_10.png)
-
-The jobs are be ordered by comparing the numbers from left to right. You
-usually want the first number to be the index and the second number to be the total.
-
-[This regular expression](https://gitlab.com/gitlab-org/gitlab/blob/2f3dc314f42dbd79813e6251792853bc231e69dd/app/models/commit_status.rb#L99)
-evaluates the job names: `\d+[\s:\/\\]+\d+\s*`.
-
-### Specifying variables when running manual jobs
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30485) in GitLab 12.2.
-
-When running manual jobs you can supply additional job specific variables.
-
-You can do this from the job page of the manual job you want to run with
-additional variables. To access this page, click on the **name** of the manual job in
-the pipeline view, *not* the play (**{play}**) button.
-
-This is useful when you want to alter the execution of a job that uses
-[custom environment variables](../variables/README.md#custom-environment-variables).
-Add a variable name (key) and value here to override the value defined in
-[the UI or `.gitlab-ci.yml`](../variables/README.md#custom-environment-variables),
-for a single run of the manual job.
-
-![Manual job variables](img/manual_job_variables.png)
-
-### Delay a job
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21767) in GitLab 11.4.
-
-When you do not want to run a job immediately, you can use the [`when:delayed`](../yaml/README.md#whendelayed) parameter to
-delay a job's execution for a certain period.
-
-This is especially useful for timed incremental rollout where new code is rolled out gradually.
-
-For example, if you start rolling out new code and:
-
-- Users do not experience trouble, GitLab can automatically complete the deployment from 0% to 100%.
-- Users experience trouble with the new code, you can stop the timed incremental rollout by canceling the pipeline
- and [rolling](../environments/index.md#retrying-and-rolling-back) back to the last stable version.
-
-![Pipelines example](img/pipeline_incremental_rollout.png)
-
-### Expand and collapse job log sections
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14664) in GitLab 12.0.
-
-Job logs are divided into sections that can be collapsed or expanded. Each section displays
-the duration.
-
-In the following example:
-
-- Two sections are collapsed and can be expanded.
-- Three sections are expanded and can be collapsed.
-
-![Collapsible sections](img/collapsible_log_v12_6.png)
-
-#### Custom collapsible sections
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14664) in GitLab 12.0.
-
-You can create [collapsible sections in job logs](../pipelines/index.md#expand-and-collapse-job-log-sections)
-by manually outputting special codes
-that GitLab uses to determine what sections to collapse:
-
-- Section start marker: `section_start:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + `TEXT_OF_SECTION_HEADER`
-- Section end marker: `section_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K`
-
-You must add these codes to the script section of the CI configuration. For example,
-using `echo`:
-
-```yaml
-job1:
- script:
- - echo -e "section_start:`date +%s`:my_first_section\r\e[0KHeader of the 1st collapsible section"
- - echo 'this line should be hidden when collapsed'
- - echo -e "section_end:`date +%s`:my_first_section\r\e[0K"
-```
-
-In the example above:
-
-- `date +%s`: The Unix timestamp (for example `1560896352`).
-- `my_first_section`: The name given to the section.
-- `\r\e[0K`: Prevents the section markers from displaying in the rendered (colored)
- job log, but they are displayed in the raw job log. To see them, in the top right
- of the job log, click **{doc-text}** (**Show complete raw**).
- - `\r`: carriage return.
- - `\e[0K`: clear line ANSI escape code.
-
-Sample raw job log:
-
-```plaintext
-section_start:1560896352:my_first_section\r\e[0KHeader of the 1st collapsible section
-this line should be hidden when collapsed
-section_end:1560896353:my_first_section\r\e[0K
-```
-
-#### Pre-collapse sections
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/198413) in GitLab 13.5.
-
-You can make the job log automatically collapse collapsible sections by adding the `collapsed` option to the section start.
-Add `[collapsed=true]` after the section name and before the `\r`. The section end marker
-remains unchanged:
-
-- Section start marker with `[collapsed=true]`: `section_start:UNIX_TIMESTAMP:SECTION_NAME[collapsed=true]\r\e[0K` + `TEXT_OF_SECTION_HEADER`
-- Section end marker: `section_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K`
-
-Add the updated section start text to the CI configuration. For example,
-using `echo`:
-
-```yaml
-job1:
- script:
- - echo -e "section_start:`date +%s`:my_first_section[collapsed=true]\r\e[0KHeader of the 1st collapsible section"
- - echo 'this line should be hidden automatically after loading the job log'
- - echo -e "section_end:`date +%s`:my_first_section\r\e[0K"
-```
-
## Visualize pipelines
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5742) in GitLab 8.11.
diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md
index d904452a011..160399e4bc4 100644
--- a/doc/ci/pipelines/job_artifacts.md
+++ b/doc/ci/pipelines/job_artifacts.md
@@ -44,7 +44,7 @@ are relative to the repository that was cloned during the build.
By default, the artifacts upload when the job succeeds. You can also set artifacts to upload
when the job fails, or always, by using [`artifacts:when`](../yaml/README.md#artifactswhen)
-parameter. GitLab keeps these uploaded artifacts for 1 week, as defined
+keyword. 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).
@@ -114,7 +114,9 @@ There are a couple of exceptions to the [original dotenv rules](https://github.c
- The variable key can contain only letters, digits, and underscores (`_`).
- The maximum size of the `.env` file is 5 KB.
-- The maximum number of variables is 10.
+- In GitLab 13.5 and older, the maximum number of inherited variables is 10.
+- In [GitLab 13.6 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/247913),
+ the maximum number of inherited variables is 20.
- Variable substitution in the `.env` file is not supported.
- The `.env` file can't have empty lines or comments (starting with `#`).
- Key values in the `env` file cannot have spaces or newline characters (`\n`), including when using single or double quotes.
@@ -137,10 +139,10 @@ third party ports for other languages like JavaScript, Python, Ruby, and so on.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207528) in GitLab 13.0.
> - Requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 and above.
-The `terraform` report obtains a Terraform `tfplan.json` file. [JQ processing required to remove credentials](../../user/infrastructure/index.md#output-terraform-plan-information-into-a-merge-request). The collected Terraform
+The `terraform` report obtains a Terraform `tfplan.json` file. [JQ processing required to remove credentials](../../user/infrastructure/mr_integration.md#setup). The collected Terraform
plan report uploads to GitLab as an artifact and displays
in merge requests. For more information, see
-[Output `terraform plan` information into a merge request](../../user/infrastructure/index.md#output-terraform-plan-information-into-a-merge-request).
+[Output `terraform plan` information into a merge request](../../user/infrastructure/mr_integration.md).
#### `artifacts:reports:codequality`
@@ -414,7 +416,7 @@ information in the UI.
## Erasing artifacts
-DANGER: **Danger:**
+DANGER: **Warning:**
This is a destructive action that leads to data loss. Use with caution.
You can erase a single job via the UI, which also removes the job's
diff --git a/doc/ci/pipelines/pipeline_efficiency.md b/doc/ci/pipelines/pipeline_efficiency.md
index c4febba8f44..149c596430c 100644
--- a/doc/ci/pipelines/pipeline_efficiency.md
+++ b/doc/ci/pipelines/pipeline_efficiency.md
@@ -222,6 +222,8 @@ Methods to reduce Docker image size:
- 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.
+- Use [multi-stage builds](https://blog.alexellis.io/mutli-stage-docker-builds/)
+ to merge multiple Dockerfiles that use the builder pattern into one Dockerfile, which can reduce image size.
- 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.
diff --git a/doc/ci/pipelines/schedules.md b/doc/ci/pipelines/schedules.md
index bcdb7c4c8b6..9df73957293 100644
--- a/doc/ci/pipelines/schedules.md
+++ b/doc/ci/pipelines/schedules.md
@@ -85,10 +85,10 @@ job:
### Advanced configuration
-The pipelines won't be executed exactly on schedule because schedules are handled by
+The pipelines are not executed exactly on schedule because schedules are handled by
Sidekiq, which runs according to its interval.
-For example, only two pipelines will be created per day if:
+For example, only two pipelines are created per day if:
- You set a schedule to create a pipeline every minute (`* * * * *`).
- The Sidekiq worker runs on 00:00 and 12:00 every day (`0 */12 * * *`).
@@ -112,8 +112,8 @@ To trigger a pipeline schedule manually, click the "Play" button:
![Play Pipeline Schedule](img/pipeline_schedule_play.png)
-This will schedule a background job to run the pipeline schedule. A flash
-message will provide a link to the CI/CD Pipeline index page.
+This schedules a background job to run the pipeline schedule. A flash
+message provides a link to the CI/CD Pipeline index page.
NOTE: **Note:**
To help avoid abuse, users are rate limited to triggering a pipeline once per
@@ -124,12 +124,12 @@ minute.
Pipelines are executed as a user, who owns a schedule. This influences what projects and other resources the pipeline has access to.
If a user does not own a pipeline, you can take ownership by clicking the **Take ownership** button.
-The next time a pipeline is scheduled, your credentials will be used.
+The next time a pipeline is scheduled, your credentials are used.
![Schedules list](img/pipeline_schedules_ownership.png)
-If the owner of a pipeline schedule doesn't have the ability to create
-pipelines on the target branch, the schedule will stop creating new
+If the owner of a pipeline schedule does not have the ability to create
+pipelines on the target branch, the schedule stops creating new
pipelines.
This can happen if, for example:
diff --git a/doc/ci/pipelines/settings.md b/doc/ci/pipelines/settings.md
index 143a5346e88..d2d2cb26256 100644
--- a/doc/ci/pipelines/settings.md
+++ b/doc/ci/pipelines/settings.md
@@ -26,10 +26,11 @@ There are two options. Using:
- `git clone`, which is slower since it clones the repository from scratch
for every job, ensuring that the local working copy is always pristine.
-- `git fetch`, which is faster as it re-uses the local working copy (falling
+- `git fetch`, which is GitLab's default and faster as it re-uses the local working copy (falling
back to clone if it doesn't exist).
+ This is recommended, especially for [large repositories](../large_repositories/index.md#git-strategy).
-The default Git strategy can be overridden by the [GIT_STRATEGY variable](../yaml/README.md#git-strategy)
+The configured Git strategy can be overridden by the [`GIT_STRATEGY` variable](../runners/README.md#git-strategy)
in `.gitlab-ci.yml`.
## Git shallow clone
@@ -183,7 +184,7 @@ Job logs and artifacts are [not visible for guest users and non-project members]
If **Public pipelines** is enabled (default):
- For **public** projects, anyone can view the pipelines and related features.
-- For **internal** projects, any logged in user can view the pipelines
+- For **internal** projects, any logged in user except [external users](../../user/permissions.md#external-users) can view the pipelines
and related features.
- For **private** projects, any project member (guest or higher) can view the pipelines
and related features.
@@ -192,7 +193,7 @@ If **Public pipelines** is disabled:
- For **public** projects, anyone can view the pipelines, but only members
(reporter or higher) can access the related features.
-- For **internal** projects, any logged in user can view the pipelines.
+- For **internal** projects, any logged in user except [external users](../../user/permissions.md#external-users) can view the pipelines.
However, only members (reporter or higher) can access the job related features.
- For **private** projects, only project members (reporter or higher)
can view the pipelines or access the related features.
@@ -231,6 +232,16 @@ When enabled, any older deployments job are skipped when a new deployment starts
For more information, see [Deployment safety](../environments/deployment_safety.md).
+## Retry outdated jobs
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211339) in GitLab 13.6.
+
+A deployment job can fail because a newer one has run. If you retry the failed deployment job, the
+environment could be overwritten with older source code. If you click **Retry**, a modal warns you
+about this and asks for confirmation.
+
+For more information, see [Deployment safety](../environments/deployment_safety.md).
+
## Pipeline Badges
In the pipelines settings page you can find pipeline status and test coverage
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index 246430a6458..f3e60fae13a 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -5,224 +5,153 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Getting started with GitLab CI/CD
+# Get started with GitLab CI/CD
-GitLab offers a [continuous integration](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/) service. For each commit or push to trigger your CI
-[pipeline](../pipelines/index.md), you must:
+Use this document to get started with
+GitLab [continuous integration](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/).
-- 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).
+Before you start, make sure you have:
-The `.gitlab-ci.yml` file tells the runner what to do. A simple pipeline commonly has
-three [stages](../yaml/README.md#stages):
+- A project in GitLab that you would like to use CI/CD for.
+- Maintainer or owner access for the project.
-- `build`
-- `test`
-- `deploy`
+If you are migrating from another CI/CD tool, view this documentation:
-You do not need to use all three stages; stages with no jobs are ignored.
+- [Migrate from CircleCI](../migration/circleci.md).
+- [Migrate from Jenkins](../migration/jenkins.md).
-The pipeline appears under the project's **CI/CD > Pipelines** page. If everything runs OK (no non-zero
-return values), you get a green check mark associated with the commit. This makes it easy to see
-whether a commit caused any of the tests to fail before you even look at the job (test) log. Many projects use
-GitLab's CI service to run the test suite, so developers get immediate feedback if they broke
-something.
+## CI/CD process overview
-It's also common to use pipelines to automatically deploy
-tested code to staging and production environments.
+To use GitLab CI/CD:
-If you're already familiar with general CI/CD concepts, you can review which
-[pipeline architectures](../pipelines/pipeline_architectures.md) can be used
-in your projects. If you're coming over to GitLab from Jenkins, you can check out
-our [reference](../migration/jenkins.md) for converting your pre-existing pipelines
-over to our format.
+1. [Ensure you have runners available](#ensure-you-have-runners-available) to run your jobs.
+ If you don't have a runner, [install GitLab Runner](https://docs.gitlab.com/runner/install/)
+ and [register a runner](https://docs.gitlab.com/runner/register/) for your instance, project, or group.
+1. [Create a `.gitlab-ci.yml` file](#create-a-gitlab-ciyml-file)
+ at the root of your repository. This file is where you define your CI/CD jobs.
-This guide assumes that you have:
+When you commit the file to your repository, the runner runs your jobs.
+The job results [are displayed in a pipeline](#view-the-status-of-your-pipeline-and-jobs).
-- A working GitLab instance of version 8.0+ or are using
- [GitLab.com](https://gitlab.com).
-- A project in GitLab that you would like to use CI for.
-- Maintainer or owner access to the project
+### Ensure you have runners available
-Let's break it down to pieces and work on solving the GitLab CI/CD puzzle.
+In GitLab, runners are agents that run your CI/CD jobs.
-## Creating a `.gitlab-ci.yml` file
+You might already have runners available for your project, including
+[shared runners](../runners/README.md#shared-runners), which are
+available to all projects in your GitLab instance.
-Before you create `.gitlab-ci.yml` let's first explain in brief what this is
-all about.
+To view available runners:
-### What is `.gitlab-ci.yml`
+- Go to **Settings > CI/CD** and expand **Runners**.
-The `.gitlab-ci.yml` file is where you configure what CI does with your project.
-It lives in the root of your repository.
+As long as you have at least one runner that's active, with a green circle next to it,
+you have a runner available to process your jobs.
-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,
-for that commit.
+If no runners are listed on the **Runners** page in the UI, you or an administrator
+must [install GitLab Runner](https://docs.gitlab.com/runner/install/) and
+[register](https://docs.gitlab.com/runner/register/) at least one runner.
-Because `.gitlab-ci.yml` is in the repository and is version controlled, old
-versions still build successfully, forks can easily make use of CI, branches can
-have different pipelines and jobs, and you have a single source of truth for CI.
-You can read more about the reasons why we are using `.gitlab-ci.yml` [in our
-blog about it](https://about.gitlab.com/blog/2015/05/06/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml/).
+If you are testing CI/CD, you can install GitLab Runner and register runners on your local machine.
+When your CI/CD jobs run, they will run on your local machine.
-### Creating a simple `.gitlab-ci.yml` file
+### Create a `.gitlab-ci.yml` file
-You need to create a file named `.gitlab-ci.yml` in the root directory of your
-repository. This is a [YAML](https://en.wikipedia.org/wiki/YAML) file
-so you have to pay extra attention to indentation. Always use spaces, not tabs.
+The `.gitlab-ci.yml` file is a [YAML](https://en.wikipedia.org/wiki/YAML) file where
+you configure specific instructions for GitLab CI/CD.
-Below is an example for a Ruby on Rails project:
+In this file, you define:
-```yaml
-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[@]}"
+- The structure and order of jobs that the runner should execute.
+- The decisions the runner should make when specific conditions are encountered.
-rspec:
- script:
- - bundle exec rspec
+For example, you might want to run a suite of tests when you commit to
+any branch except `master`. When you commit to `master`, you want
+to run the same suite, but also publish your application.
-rubocop:
- script:
- - bundle exec rubocop
-```
+All of this is defined in the `.gitlab-ci.yml` file.
-This is the simplest possible configuration that will work for most Ruby
-applications:
+To create a `.gitlab-ci.yml` file:
-1. Define two jobs `rspec` and `rubocop` (the names are arbitrary) with
- different commands to be executed.
-1. Before every job, the commands defined by `before_script` are executed.
+1. Go to **Project overview > Details**.
+1. Above the file list, select the branch you want to commit to,
+ click the plus icon, then select **New file**:
-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.
+ ![New file](img/new_file_v13_6.png)
-What is important is that each job is run independently from each other.
+1. For the **File name** type `.gitlab-ci.yml` and in the larger window,
+ paste this sample code:
-If you want to check whether the `.gitlab-ci.yml` of your project is valid, there is a
-[CI Lint tool](../lint.md) available in every project.
+ ```yaml
+ build-job:
+ stage: build
+ script:
+ - echo "Hello, $GITLAB_USER_LOGIN!"
-You can use the [CI/CD configuration visualization](../yaml/visualization.md) to
-see a graphical representation of your `.gitlab-ci.yml`.
+ test-job1:
+ stage: test
+ script:
+ - echo "This job tests something"
-For more information and a complete `.gitlab-ci.yml` syntax, please read
-[the reference documentation on `.gitlab-ci.yml`](../yaml/README.md).
+ test-job2:
+ stage: test
+ script:
+ - echo "This job tests something, but takes more time than test-job1."
+ - echo "After the echo commands complete, it runs the sleep command for 20 seconds"
+ - echo "which simulates a test that runs 20 seconds longer than test-job1"
+ - sleep 20
-TIP: **Tip:**
-A GitLab team member has made an [unofficial visual pipeline editor](https://unofficial.gitlab.tools/visual-pipelines/).
-There is a [plan to make it an official part of GitLab](https://gitlab.com/groups/gitlab-org/-/epics/4069)
-in the future, but it's available for anyone who wants to try it at the above link.
+ deploy-prod:
+ stage: deploy
+ script:
+ - echo "This job deploys something from the $CI_COMMIT_BRANCH branch."
+ ```
-### Push `.gitlab-ci.yml` to GitLab
+ `$GITLAB_USER_LOGIN` and `$CI_COMMIT_BRANCH` are
+ [predefined variables](../variables/predefined_variables.md)
+ that populate when the job runs.
-Once you've created `.gitlab-ci.yml`, you should add it to your Git repository
-and push it to GitLab.
+1. Click **Commit changes**.
-```shell
-git add .gitlab-ci.yml
-git commit -m "Add .gitlab-ci.yml"
-git push origin master
-```
+The pipeline starts when the commit is committed.
-Now if you go to the **Pipelines** page you will see that the pipeline is
-pending.
+#### `.gitlab-ci.yml` tips
-NOTE: **Note:**
-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**.
+- If you want the runner to use a Docker image to run the jobs, edit the `.gitlab-ci.yml` file
+ to include your image name:
-You can also go to the **Commits** page and notice the little pause icon next
-to the commit SHA.
+ ```yaml
+ default:
+ image: ruby:2.7.2
+ ```
-![New commit pending](img/new_commit.png)
+ This command tells the runner to use a Ruby image from Docker Hub.
-Clicking on it you will be directed to the jobs page for that specific commit.
+- To validate your `.gitlab-ci.yml` file, use the
+ [CI Lint tool](../lint.md), which is available in every project.
+- You can also use [CI/CD configuration visualization](../yaml/visualization.md) to
+ view a graphical representation of your `.gitlab-ci.yml` file.
+- For the complete `.gitlab-ci.yml` syntax, see
+ [the `.gitlab-ci.yml` reference topic](../yaml/README.md).
-![Single commit jobs page](img/single_commit_status_pending.png)
+### View the status of your pipeline and jobs
-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
-yet for this job.
+When you committed your changes, a pipeline started.
-The next step is to configure a runner so that it picks the pending jobs.
+To view your pipeline:
-## Configuring a runner
+- Go **CI/CD > Pipelines**.
-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 pipeline with three stages should be displayed:
-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_.
+ ![Three stages](img/three_stages_v13_6.png)
-Find more information about runners in the
-[runner](../runners/README.md) documentation.
+- To view a visual representation of your pipeline, click the pipeline ID.
-The official runner supported by GitLab is written in Go.
-View [the documentation](https://docs.gitlab.com/runner/).
+ ![Pipeline graph](img/pipeline_graph_v13_6.png)
-For a runner to be available in GitLab, you must:
+- To view details of a job, click the job name, for example, `deploy-prod`.
-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/).
+ ![Job details](img/job_details_v13_6.png)
-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
-
-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 shared runners, go to your project's or group's
-**Settings > CI/CD** and click **Enable shared runners**.
-
-[Read more about shared runners](../runners/README.md#shared-runners).
-
-## Viewing the status of your pipeline and jobs
-
-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.
-
-![Commit status](img/pipelines_status.png)
-
-Or you can view all jobs, by going to the **Pipelines âž” Jobs** page.
-
-![Commit status](img/builds_status.png)
-
-By clicking on a job's status, you will be able to see the log of that job.
-This is important to diagnose why a job failed or acted differently than
-you expected.
-
-![Build log](img/build_log.png)
-
-You are also able to view the status of any commit in the various pages in
-GitLab, such as **Commits** and **Merge requests**.
-
-## 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).
+If the job status is `stuck`, check to ensure a runner is probably configured for the project.
diff --git a/doc/ci/quick_start/img/build_log.png b/doc/ci/quick_start/img/build_log.png
deleted file mode 100644
index 16698629edc..00000000000
--- a/doc/ci/quick_start/img/build_log.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/quick_start/img/builds_status.png b/doc/ci/quick_start/img/builds_status.png
deleted file mode 100644
index b4aeeb988d2..00000000000
--- a/doc/ci/quick_start/img/builds_status.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/quick_start/img/job_details_v13_6.png b/doc/ci/quick_start/img/job_details_v13_6.png
new file mode 100644
index 00000000000..e94287f90ba
--- /dev/null
+++ b/doc/ci/quick_start/img/job_details_v13_6.png
Binary files differ
diff --git a/doc/ci/quick_start/img/new_commit.png b/doc/ci/quick_start/img/new_commit.png
deleted file mode 100644
index 507eb93ac0c..00000000000
--- a/doc/ci/quick_start/img/new_commit.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/quick_start/img/new_file_v13_6.png b/doc/ci/quick_start/img/new_file_v13_6.png
new file mode 100644
index 00000000000..c71923f9b90
--- /dev/null
+++ b/doc/ci/quick_start/img/new_file_v13_6.png
Binary files differ
diff --git a/doc/ci/quick_start/img/pipeline_graph_v13_6.png b/doc/ci/quick_start/img/pipeline_graph_v13_6.png
new file mode 100644
index 00000000000..fcf7e02d1f3
--- /dev/null
+++ b/doc/ci/quick_start/img/pipeline_graph_v13_6.png
Binary files differ
diff --git a/doc/ci/quick_start/img/pipelines_status.png b/doc/ci/quick_start/img/pipelines_status.png
deleted file mode 100644
index 39a77a26b25..00000000000
--- a/doc/ci/quick_start/img/pipelines_status.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/quick_start/img/single_commit_status_pending.png b/doc/ci/quick_start/img/single_commit_status_pending.png
deleted file mode 100644
index ffc7054d3b0..00000000000
--- a/doc/ci/quick_start/img/single_commit_status_pending.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/quick_start/img/three_stages_v13_6.png b/doc/ci/quick_start/img/three_stages_v13_6.png
new file mode 100644
index 00000000000..a6c049e3e6c
--- /dev/null
+++ b/doc/ci/quick_start/img/three_stages_v13_6.png
Binary files differ
diff --git a/doc/ci/review_apps/img/view_on_env_mr.png b/doc/ci/review_apps/img/view_on_env_mr.png
index 2c0bd25a4f2..0e61814a65d 100644
--- a/doc/ci/review_apps/img/view_on_env_mr.png
+++ b/doc/ci/review_apps/img/view_on_env_mr.png
Binary files differ
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index 7110117709f..ba23eff0434 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -27,7 +27,7 @@ In the above example:
- A Review App is built every time a commit is pushed to `topic branch`.
- The reviewer fails two reviews before passing the third review.
-- Once the review has passed, `topic branch` is merged into `master` where it is deployed to staging.
+- After the review has passed, `topic branch` is merged into `master` where it is deployed to staging.
- After having been approved in staging, the changes that were merged into `master` are deployed in to production.
## How Review Apps work
@@ -169,7 +169,7 @@ will match `/source\/(.+?\.html).*/` instead of `/source\/(.*)/`,
and will result in a public path of `index.html`, instead of
`index.html.haml`.
-Once you have the route mapping set up, it will take effect in the following locations:
+After you have the route mapping set up, it will take effect in the following locations:
- In the merge request widget. The:
- **View app** button will take you to the environment URL set in `.gitlab-ci.yml`.
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index a3cc46f59bf..4392fa3c78b 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -6,8 +6,6 @@ type: reference
---
# Configuring runners in GitLab
-<!-- This topic contains several commented-out sections that were accidentally added in 13.2.-->
-<!-- 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 runner is a lightweight, highly-scalable agent that picks up a CI job through
@@ -16,6 +14,10 @@ the coordinator API of GitLab CI/CD, runs the job, and sends the result back to
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.
+This documentation is focused on using runners in GitLab.
+If you need to install and configure GitLab Runner, see
+[the GitLab Runner documentation](https://docs.gitlab.com/runner/).
+
## Types of runners
In the GitLab UI there are three types of runners, based on who you want to have access:
@@ -36,7 +38,7 @@ multiple projects.
If you are using a self-managed instance of GitLab:
- Your administrator can install and register shared runners by [following the documentation](https://docs.gitlab.com/runner/install/index.html).
- <!-- going to your project's
+ <!-- going to your project's-->
<!-- **Settings > CI / CD**, expanding the **Runners** section, and clicking **Show runner installation instructions**.-->
<!-- These instructions are also available [in the documentation](https://docs.gitlab.com/runner/install/index.html).-->
- The administrator can also configure a maximum number of shared runner [pipeline minutes for
@@ -390,6 +392,9 @@ You must set up a runner to be able to run all the different types of jobs
that it may encounter on the projects it's shared over. This would be
problematic for large amounts of projects, if it weren't for tags.
+GitLab CI tags are not the same as Git tags. GitLab CI tags are associated with runners.
+Git tags are associated with commits.
+
By tagging a runner for the types of jobs it can handle, you can make sure
shared runners will [only run the jobs they are equipped to run](../yaml/README.md#tags).
@@ -450,6 +455,339 @@ Example 2:
1. A job that has no tags defined is executed and run.
1. A second job that has a `docker` tag defined is stuck.
+## Configure runner behavior with variables
+
+You can use [CI/CD variables](../variables/README.md) to configure runner Git behavior
+globally or for individual jobs:
+
+- [`GIT_STRATEGY`](#git-strategy)
+- [`GIT_SUBMODULE_STRATEGY`](#git-submodule-strategy)
+- [`GIT_CHECKOUT`](#git-checkout)
+- [`GIT_CLEAN_FLAGS`](#git-clean-flags)
+- [`GIT_FETCH_EXTRA_FLAGS`](#git-fetch-extra-flags)
+- [`GIT_DEPTH`](#shallow-cloning) (shallow cloning)
+- [`GIT_CLONE_PATH`](#custom-build-directories) (custom build directories)
+
+You can also use variables to configure how many times a runner
+[attempts certain stages of job execution](#job-stages-attempts).
+
+### Git strategy
+
+> - Introduced in GitLab 8.9 as an experimental feature.
+> - `GIT_STRATEGY=none` requires GitLab Runner v1.7+.
+
+You can set the `GIT_STRATEGY` used to fetch the repository content, either
+globally or per-job in the [`variables`](../yaml/README.md#variables) section:
+
+```yaml
+variables:
+ GIT_STRATEGY: clone
+```
+
+There are three possible values: `clone`, `fetch`, and `none`. If left unspecified,
+jobs use the [project's pipeline setting](../pipelines/settings.md#git-strategy).
+
+`clone` is the slowest option. It clones the repository from scratch for every
+job, ensuring that the local working copy is always pristine.
+If an existing worktree is found, it is removed before cloning.
+
+`fetch` is faster as it re-uses the local working copy (falling back to `clone`
+if it does not exist). `git clean` is used to undo any changes made by the last
+job, and `git fetch` is used to retrieve commits made after the last job ran.
+
+However, `fetch` does require access to the previous worktree. This works
+well when using the `shell` or `docker` executor because these
+try to preserve worktrees and try to re-use them by default.
+
+This has limitations when using the [Docker Machine executor](https://docs.gitlab.com/runner/executors/docker_machine.html).
+
+It does not work for [the `kubernetes` executor](https://docs.gitlab.com/runner/executors/kubernetes.html),
+but a [feature proposal](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3847) exists.
+The `kubernetes` executor always clones into an temporary directory.
+
+A Git strategy of `none` also re-uses the local working copy, but skips all Git
+operations normally done by GitLab. GitLab Runner pre-clone scripts are also skipped,
+if present. This strategy could mean you need to add `fetch` and `checkout` commands
+to [your `.gitlab-ci.yml` script](../yaml/README.md#script).
+
+It can be used for jobs that operate exclusively on artifacts, like a deployment job.
+Git repository data may be present, but it's likely out of date. You should only
+rely on files brought into the local working copy from cache or artifacts.
+
+### Git submodule strategy
+
+> Requires GitLab Runner v1.10+.
+
+The `GIT_SUBMODULE_STRATEGY` variable is used to control if / how Git
+submodules are included when fetching the code before a build. You can set them
+globally or per-job in the [`variables`](../yaml/README.md#variables) section.
+
+There are three possible values: `none`, `normal`, and `recursive`:
+
+- `none` means that submodules are not included when fetching the project
+ code. This is the default, which matches the pre-v1.10 behavior.
+
+- `normal` means that only the top-level submodules are included. It's
+ equivalent to:
+
+ ```shell
+ git submodule sync
+ git submodule update --init
+ ```
+
+- `recursive` means that all submodules (including submodules of submodules)
+ are included. This feature needs Git v1.8.1 and later. When using a
+ GitLab Runner with an executor not based on Docker, make sure the Git version
+ meets that requirement. It's equivalent to:
+
+ ```shell
+ git submodule sync --recursive
+ git submodule update --init --recursive
+ ```
+
+For this feature to work correctly, the submodules must be configured
+(in `.gitmodules`) with either:
+
+- the HTTP(S) URL of a publicly-accessible repository, or
+- a relative path to another repository on the same GitLab server. See the
+ [Git submodules](../git_submodules.md) documentation.
+
+### Git checkout
+
+> Introduced in GitLab Runner 9.3.
+
+The `GIT_CHECKOUT` variable can be used when the `GIT_STRATEGY` is set to either
+`clone` or `fetch` to specify whether a `git checkout` should be run. If not
+specified, it defaults to true. You can set them globally or per-job in the
+[`variables`](../yaml/README.md#variables) section.
+
+If set to `false`, the runner:
+
+- when doing `fetch` - updates the repository and leaves the working copy on
+ the current revision,
+- when doing `clone` - clones the repository and leaves the working copy on the
+ default branch.
+
+If `GIT_CHECKOUT` is set to `true`, both `clone` and `fetch` work the same way.
+The runner checks out the working copy of a revision related
+to the CI pipeline:
+
+```yaml
+variables:
+ GIT_STRATEGY: clone
+ GIT_CHECKOUT: "false"
+script:
+ - git checkout -B master origin/master
+ - git merge $CI_COMMIT_SHA
+```
+
+### Git clean flags
+
+> Introduced in GitLab Runner 11.10
+
+The `GIT_CLEAN_FLAGS` variable is used to control the default behavior of
+`git clean` after checking out the sources. You can set it globally or per-job in the
+[`variables`](../yaml/README.md#variables) section.
+
+`GIT_CLEAN_FLAGS` accepts all possible options of the [`git clean`](https://git-scm.com/docs/git-clean)
+command.
+
+`git clean` is disabled if `GIT_CHECKOUT: "false"` is specified.
+
+If `GIT_CLEAN_FLAGS` is:
+
+- Not specified, `git clean` flags default to `-ffdx`.
+- Given the value `none`, `git clean` is not executed.
+
+For example:
+
+```yaml
+variables:
+ GIT_CLEAN_FLAGS: -ffdx -e cache/
+script:
+ - ls -al cache/
+```
+
+### Git fetch extra flags
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4142) in GitLab Runner 13.1.
+
+The `GIT_FETCH_EXTRA_FLAGS` variable is used to control the behavior of
+`git fetch`. You can set it globally or per-job in the [`variables`](../yaml/README.md#variables) section.
+
+`GIT_FETCH_EXTRA_FLAGS` accepts all options of the [`git fetch`](https://git-scm.com/docs/git-fetch) command. However, `GIT_FETCH_EXTRA_FLAGS` flags are appended after the default flags that can't be modified.
+
+The default flags are:
+
+- [GIT_DEPTH](#shallow-cloning).
+- The list of [refspecs](https://git-scm.com/book/en/v2/Git-Internals-The-Refspec).
+- A remote called `origin`.
+
+If `GIT_FETCH_EXTRA_FLAGS` is:
+
+- Not specified, `git fetch` flags default to `--prune --quiet` along with the default flags.
+- Given the value `none`, `git fetch` is executed only with the default flags.
+
+For example, the default flags are `--prune --quiet`, so you can make `git fetch` more verbose by overriding this with just `--prune`:
+
+```yaml
+variables:
+ GIT_FETCH_EXTRA_FLAGS: --prune
+script:
+ - ls -al cache/
+```
+
+The configuration above results in `git fetch` being called this way:
+
+```shell
+git fetch origin $REFSPECS --depth 50 --prune
+```
+
+Where `$REFSPECS` is a value provided to the runner internally by GitLab.
+
+### Shallow cloning
+
+> Introduced in GitLab 8.9 as an experimental feature.
+
+You can specify the depth of fetching and cloning using `GIT_DEPTH`.
+`GIT_DEPTH` does a shallow clone of the repository and can significantly speed up cloning.
+It can be helpful for repositories with a large number of commits or old, large binaries. The value is
+passed to `git fetch` and `git clone`.
+
+In GitLab 12.0 and later, newly-created projects automatically have a
+[default `git depth` value of `50`](../pipelines/settings.md#git-shallow-clone).
+
+If you use a depth of `1` and have a queue of jobs or retry
+jobs, jobs may fail.
+
+Git fetching and cloning is based on a ref, such as a branch name, so runners
+can't clone a specific commit SHA. If multiple jobs are in the queue, or
+you're retrying an old job, the commit to be tested must be within the
+Git history that is cloned. Setting too small a value for `GIT_DEPTH` can make
+it impossible to run these old commits and `unresolved reference` is displayed in
+job logs. You should then reconsider changing `GIT_DEPTH` to a higher value.
+
+Jobs that rely on `git describe` may not work correctly when `GIT_DEPTH` is
+set since only part of the Git history is present.
+
+To fetch or clone only the last 3 commits:
+
+```yaml
+variables:
+ GIT_DEPTH: "3"
+```
+
+You can set it globally or per-job in the [`variables`](../yaml/README.md#variables) section.
+
+### Custom build directories
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2211) in GitLab Runner 11.10.
+
+By default, GitLab Runner clones the repository in a unique subpath of the
+`$CI_BUILDS_DIR` directory. However, your project might require the code in a
+specific directory (Go projects, for example). In that case, you can specify
+the `GIT_CLONE_PATH` variable to tell the runner the directory to clone the
+repository in:
+
+```yaml
+variables:
+ GIT_CLONE_PATH: $CI_BUILDS_DIR/project-name
+
+test:
+ script:
+ - pwd
+```
+
+The `GIT_CLONE_PATH` has to always be within `$CI_BUILDS_DIR`. The directory set in `$CI_BUILDS_DIR`
+is dependent on executor and configuration of [runners.builds_dir](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
+setting.
+
+This can only be used when `custom_build_dir` is enabled in the
+[runner's configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscustom_build_dir-section).
+This is the default configuration for the `docker` and `kubernetes` executors.
+
+#### Handling concurrency
+
+An executor that uses a concurrency greater than `1` might lead
+to failures. Multiple jobs might be working on the same directory if the `builds_dir`
+is shared between jobs.
+
+The runner does not try to prevent this situation. It's up to the administrator
+and developers to comply with the requirements of runner configuration.
+
+To avoid this scenario, you can use a unique path within `$CI_BUILDS_DIR`, because runner
+exposes two additional variables that provide a unique `ID` of concurrency:
+
+- `$CI_CONCURRENT_ID`: Unique ID for all jobs running within the given executor.
+- `$CI_CONCURRENT_PROJECT_ID`: Unique ID for all jobs running within the given executor and project.
+
+The most stable configuration that should work well in any scenario and on any executor
+is to use `$CI_CONCURRENT_ID` in the `GIT_CLONE_PATH`. For example:
+
+```yaml
+variables:
+ GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/project-name
+
+test:
+ script:
+ - pwd
+```
+
+The `$CI_CONCURRENT_PROJECT_ID` should be used in conjunction with `$CI_PROJECT_PATH`
+as the `$CI_PROJECT_PATH` provides a path of a repository. That is, `group/subgroup/project`. For example:
+
+```yaml
+variables:
+ GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH
+
+test:
+ script:
+ - pwd
+```
+
+#### Nested paths
+
+The value of `GIT_CLONE_PATH` is expanded once and nesting variables
+within is not supported.
+
+For example, you define both the variables below in your
+`.gitlab-ci.yml` file:
+
+```yaml
+variables:
+ GOPATH: $CI_BUILDS_DIR/go
+ GIT_CLONE_PATH: $GOPATH/src/namespace/project
+```
+
+The value of `GIT_CLONE_PATH` is expanded once into
+`$CI_BUILDS_DIR/go/src/namespace/project`, and results in failure
+because `$CI_BUILDS_DIR` is not expanded.
+
+### Job stages attempts
+
+> Introduced in GitLab, it requires GitLab Runner v1.9+.
+
+You can set the number of attempts that the running job tries to execute
+the following stages:
+
+| Variable | Description |
+|---------------------------------|--------------------------------------------------------|
+| `ARTIFACT_DOWNLOAD_ATTEMPTS` | Number of attempts to download artifacts running a job |
+| `EXECUTOR_JOB_SECTION_ATTEMPTS` | [In GitLab 12.10](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450) and later, the number of attempts to run a section in a job after a [`No Such Container`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450) error ([Docker executor](https://docs.gitlab.com/runner/executors/docker.html) only). |
+| `GET_SOURCES_ATTEMPTS` | Number of attempts to fetch sources running a job |
+| `RESTORE_CACHE_ATTEMPTS` | Number of attempts to restore the cache running a job |
+
+The default is one single attempt.
+
+Example:
+
+```yaml
+variables:
+ GET_SOURCES_ATTEMPTS: 3
+```
+
+You can set them globally or per-job in the [`variables`](../yaml/README.md#variables) section.
+
## System calls not available on GitLab.com shared runners
GitLab.com shared runners run on CoreOS. This means that you cannot use some system calls, like `getlogin`, from the C standard library.
diff --git a/doc/ci/runners/img/shared_runners_admin.png b/doc/ci/runners/img/shared_runners_admin.png
deleted file mode 100644
index e049b339b36..00000000000
--- a/doc/ci/runners/img/shared_runners_admin.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md
index 12478000a0a..a329331df08 100644
--- a/doc/ci/ssh_keys/README.md
+++ b/doc/ci/ssh_keys/README.md
@@ -93,7 +93,7 @@ to access it. This is where an SSH key pair comes in handy.
# - git config --global user.name "User name"
```
- The [`before_script`](../yaml/README.md#before_script-and-after_script) can be set globally
+ The [`before_script`](../yaml/README.md#before_script) can be set globally
or per-job.
1. Make sure the private server's [SSH host keys are verified](#verifying-the-ssh-host-keys).
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index bcd19f0de6f..6fca482975c 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -32,7 +32,7 @@ This also applies when using the `pipelines` or `triggers` keywords with the leg
A unique trigger token can be obtained when [adding a new trigger](#adding-a-new-trigger).
-DANGER: **Danger:**
+DANGER: **Warning:**
Passing plain text tokens in public projects is a security issue. Potential
attackers can impersonate the user that exposed their trigger token publicly in
their `.gitlab-ci.yml` file. Use [variables](../variables/README.md#gitlab-cicd-environment-variables)
@@ -50,7 +50,7 @@ with the [GitLab Container Registry](../../user/packages/container_registry/inde
This way of triggering can only be used when invoked inside `.gitlab-ci.yml`,
and it creates a dependent pipeline relation visible on the
-[pipeline graph](../multi_project_pipelines.md#overview). For example:
+[pipeline graph](../multi_project_pipelines.md). For example:
```yaml
build_docs:
diff --git a/doc/ci/troubleshooting.md b/doc/ci/troubleshooting.md
index 992b51b6b3d..5dc1d3663c5 100644
--- a/doc/ci/troubleshooting.md
+++ b/doc/ci/troubleshooting.md
@@ -225,7 +225,7 @@ should disable **Pipelines must succeed** so you can accept merge requests.
Pipeline configuration warnings are shown when you:
-- [Validate configuration with the CI Lint tool](yaml/README.md#validate-the-gitlab-ciyml).
+- [Validate configuration with the CI Lint tool](yaml/README.md).
- [Manually run a pipeline](pipelines/index.md#run-a-pipeline-manually).
### "Job may allow multiple pipelines to run for a single action" warning
diff --git a/doc/ci/unit_test_reports.md b/doc/ci/unit_test_reports.md
index b9c1809bf0d..0a1f0000969 100644
--- a/doc/ci/unit_test_reports.md
+++ b/doc/ci/unit_test_reports.md
@@ -244,6 +244,44 @@ Test:
- ./**/*test-result.xml
```
+### JavaScript example
+
+There are a few tools that can produce JUnit report format XML files in JavaScript.
+
+#### Jest
+
+The [jest-junit](https://github.com/jest-community/jest-junit) npm package can generate test reports for JavaScript applications.
+In the following `.gitlab-ci.yml` example, the `javascript` job uses Jest to generate the test reports:
+
+```yaml
+javascript:
+ stage: test
+ script:
+ - 'jest --ci --reporters=default --reporters=jest-junit'
+ artifacts:
+ when: always
+ reports:
+ junit:
+ - junit.xml
+```
+
+#### Karma
+
+The [Karma-junit-reporter](https://github.com/karma-runner/karma-junit-reporter) npm package can generate test reports for JavaScript applications.
+In the following `.gitlab-ci.yml` example, the `javascript` job uses Karma to generate the test reports:
+
+```yaml
+javascript:
+ stage: test
+ script:
+ - karma start --reporters junit
+ artifacts:
+ when: always
+ reports:
+ junit:
+ - junit.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.
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 9c8fb994bf7..c5eee2ed960 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -70,7 +70,7 @@ When you need a specific custom environment variable, you can
or directly [in the `.gitlab-ci.yml` file](#create-a-custom-variable-in-gitlab-ciyml).
The variables are used by the runner any time the pipeline runs.
-You can also [override variable values manually for a specific pipeline](../pipelines/index.md#specifying-variables-when-running-manual-jobs).
+You can also [override variable values manually for a specific pipeline](../jobs/index.md#specifying-variables-when-running-manual-jobs).
There are two types of variables: **Variable** and **File**. You cannot set types in
the `.gitlab-ci.yml` file, but you can set them in the UI and API.
@@ -423,7 +423,7 @@ Group-level variables can be added by:
1. Inputting variable types, keys, and values in the **Variables** section.
Any variables of [subgroups](../../user/group/subgroups/index.md) are inherited recursively.
-Once you set them, they are available for all subsequent pipelines. Any group-level user defined variables can be viewed in projects by:
+After you set them, they are available for all subsequent pipelines. Any group-level user defined variables can be viewed in projects by:
1. Navigating to the project's **Settings > CI/CD** page.
1. Expanding the **Variables** section.
@@ -841,7 +841,7 @@ Available on GitLab Runner v1.7+, this feature enables the shell's execution log
Before enabling this, you should ensure jobs are visible to
[team members only](../../user/permissions.md#project-features). You should
-also [erase](../pipelines/index.md#view-jobs-in-a-pipeline) all generated job logs
+also [erase](../jobs/index.md#view-jobs-in-a-pipeline) all generated job logs
before making them visible again.
To enable debug logs (traces), set the `CI_DEBUG_TRACE` variable to `true`:
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 08aaacd2620..055cb2f6a61 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -40,7 +40,7 @@ Kubernetes-specific environment variables are detailed in the
| `CI_COMMIT_REF_SLUG` | 9.0 | all | `$CI_COMMIT_REF_NAME` lowercased, shortened to 63 bytes, and with everything except `0-9` and `a-z` replaced with `-`. No leading / trailing `-`. Use in URLs, host names and domain names. |
| `CI_COMMIT_SHA` | 9.0 | all | The commit revision for which project is built |
| `CI_COMMIT_SHORT_SHA` | 11.7 | all | The first eight characters of `CI_COMMIT_SHA` |
-| `CI_COMMIT_BRANCH` | 12.6 | 0.5 | The commit branch name. Present only when building branches. |
+| `CI_COMMIT_BRANCH` | 12.6 | 0.5 | The commit branch name. Present in branch pipelines, including pipelines for the default branch. Not present in merge request pipelines. |
| `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. |
@@ -69,14 +69,14 @@ Kubernetes-specific environment variables are detailed in the
| `CI_JOB_MANUAL` | 8.12 | all | The flag to indicate that job was manually started |
| `CI_JOB_NAME` | 9.0 | 0.5 | The name of the job as defined in `.gitlab-ci.yml` |
| `CI_JOB_STAGE` | 9.0 | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
-| `CI_JOB_STATUS` | all | 13.5 | The state of the job as each runner stage is executed. Use with [`after_script`](../yaml/README.md#before_script-and-after_script) where `CI_JOB_STATUS` can be either: `success`, `failed` or `canceled`. |
+| `CI_JOB_STATUS` | all | 13.5 | The state of the job as each runner stage is executed. Use with [`after_script`](../yaml/README.md#after_script) where `CI_JOB_STATUS` can be either: `success`, `failed` or `canceled`. |
| `CI_JOB_TOKEN` | 9.0 | 1.2 | Token used for authenticating with [a few API endpoints](../../api/README.md#gitlab-ci-job-token) and downloading [dependent repositories](../../user/project/new_ci_build_permissions_model.md#dependent-repositories). The token is valid as long as the job is running. |
| `CI_JOB_JWT` | 12.10 | all | RS256 JSON web token that can be used for authenticating with third party systems that support JWT authentication, for example [HashiCorp's Vault](../secrets/index.md). |
| `CI_JOB_URL` | 11.1 | 0.5 | Job details URL |
| `CI_KUBERNETES_ACTIVE` | 13.0 | all | Included with the value `true` only if the pipeline has a Kubernetes cluster available for deployments. Not included if no cluster is available. Can be used as an alternative to [`only:kubernetes`/`except:kubernetes`](../yaml/README.md#onlykubernetesexceptkubernetes) with [`rules:if`](../yaml/README.md#rulesif) |
| `CI_MERGE_REQUEST_ASSIGNEES` | 11.9 | all | Comma-separated list of username(s) of assignee(s) for the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_ID` | 11.6 | all | The instance-level ID of the merge request. Only available if [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. |
-| `CI_MERGE_REQUEST_IID` | 11.6 | all | The project-level IID (internal ID) of the merge request. Only available If [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. |
+| `CI_MERGE_REQUEST_ID` | 11.6 | all | The instance-level ID of the merge request. Only available if [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. This is a unique ID across all projects on GitLab. |
+| `CI_MERGE_REQUEST_IID` | 11.6 | all | The project-level IID (internal ID) of the merge request. Only available If [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. This ID is unique for the current project. |
| `CI_MERGE_REQUEST_LABELS` | 11.9 | all | Comma-separated label names of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
| `CI_MERGE_REQUEST_MILESTONE` | 11.9 | all | The milestone title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
| `CI_MERGE_REQUEST_PROJECT_ID` | 11.6 | all | The ID of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
@@ -96,8 +96,8 @@ Kubernetes-specific environment variables are detailed in the
| `CI_NODE_TOTAL` | 11.5 | all | Total number of instances of this job running in parallel. If the job is not parallelized, this variable is set to `1`. |
| `CI_PAGES_DOMAIN` | 11.8 | all | The configured domain that hosts GitLab Pages. |
| `CI_PAGES_URL` | 11.8 | all | URL to GitLab Pages-built pages. Always belongs to a subdomain of `CI_PAGES_DOMAIN`. |
-| `CI_PIPELINE_ID` | 8.10 | all | The instance-level ID of the current pipeline. |
-| `CI_PIPELINE_IID` | 11.0 | all | The project-level IID (internal ID) of the current pipeline. |
+| `CI_PIPELINE_ID` | 8.10 | all | The instance-level ID of the current pipeline. This is a unique ID across all projects on GitLab. |
+| `CI_PIPELINE_IID` | 11.0 | all | The project-level IID (internal ID) of the current pipeline. This ID is unique for the current project. |
| `CI_PIPELINE_SOURCE` | 10.0 | all | Indicates how the pipeline was triggered. Possible options are: `push`, `web`, `schedule`, `api`, `external`, `chat`, `webide`, `merge_request_event`, `external_pull_request_event`, `parent_pipeline`, [`trigger`, or `pipeline`](../triggers/README.md#authentication-tokens) (renamed to `cross_project_pipeline` since 13.0). For pipelines created before GitLab 9.5, this is displayed as `unknown`. |
| `CI_PIPELINE_TRIGGERED` | all | all | The flag to indicate that job was [triggered](../triggers/README.md) |
| `CI_PIPELINE_URL` | 11.1 | 0.5 | Pipeline details URL |
diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md
index b4236ca34c2..b914f3db572 100644
--- a/doc/ci/variables/where_variables_can_be_used.md
+++ b/doc/ci/variables/where_variables_can_be_used.md
@@ -99,7 +99,7 @@ In the case of `after_script` scripts, they can:
- Not use variables defined in `before_script` and `script`.
These restrictions are because `after_script` scripts are executed in a
-[separated shell context](../yaml/README.md#before_script-and-after_script).
+[separated shell context](../yaml/README.md#after_script).
## Persisted variables
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 2e4ab68a0e8..1057a1389de 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -7,105 +7,29 @@ type: reference
# GitLab CI/CD pipeline configuration reference
-GitLab CI/CD [pipelines](../pipelines/index.md) are configured using a YAML file called `.gitlab-ci.yml` within each project.
+This document lists the configuration options for your GitLab `.gitlab-ci.yml` file.
-The `.gitlab-ci.yml` file defines the structure and order of the pipelines and determines:
-
-- What to execute using [GitLab Runner](https://docs.gitlab.com/runner/).
-- What decisions to make when specific conditions are encountered. For example, when a process succeeds or fails.
-
-This topic covers CI/CD pipeline configuration. For other CI/CD configuration information, see:
-
-- [GitLab CI/CD Variables](../variables/README.md), for configuring the environment the pipelines run in.
-- [GitLab Runner advanced configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html), for configuring GitLab Runner.
-
-We have complete examples of configuring pipelines:
-
-- For a quick introduction to GitLab CI/CD, follow our [quick start guide](../quick_start/README.md).
+- For a quick introduction to GitLab CI/CD, follow the [quick start guide](../quick_start/README.md).
- For a collection of examples, see [GitLab CI/CD Examples](../examples/README.md).
-- To see a large `.gitlab-ci.yml` file used in an enterprise, see the [`.gitlab-ci.yml` file for `gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml).
-
-> For some additional information about GitLab CI/CD:
->
-> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Watch the [CI/CD Ease of configuration](https://www.youtube.com/embed/opdLqwz6tcE) video.
-> - Watch the [Making the case for CI/CD in your organization](https://about.gitlab.com/compare/github-actions-alternative/)
-> webcast to learn the benefits of CI/CD and how to measure the results of CI/CD automation.
-> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Learn how [Verizon reduced rebuilds](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/)
-> from 30 days to under 8 hours with GitLab.
-
-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**.
+- To view a large `.gitlab-ci.yml` file used in an enterprise, see the [`.gitlab-ci.yml` file for `gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml).
-## Introduction
-
-Pipeline configuration begins with jobs. Jobs are the most fundamental element of a `.gitlab-ci.yml` file.
-
-Jobs are:
-
-- Defined with constraints stating under what conditions they should be executed.
-- Top-level elements with an arbitrary name and must contain at least the [`script`](#script) clause.
-- Not limited in how many can be defined.
-
-For example:
-
-```yaml
-job1:
- script: "execute-script-for-job1"
-
-job2:
- script: "execute-script-for-job2"
-```
-
-The above example is the simplest possible CI/CD configuration with two separate
-jobs, where each of the jobs executes a different command.
-Of course a command can execute code directly (`./configure;make;make install`)
-or run a script (`test.sh`) in the repository.
-
-Jobs are picked up by [runners](../runners/README.md) and executed within the
-environment of the runner. What is important is that each job is run
-independently from each other.
-
-### Validate the `.gitlab-ci.yml`
-
-Each instance of GitLab CI/CD has an embedded debug tool called Lint, which validates the
-content of your `.gitlab-ci.yml` files. You can find the Lint under the page `ci/lint` of your
+While you are authoring your `.gitlab-ci.yml` file, you can validate it
+by using the [CI Lint](../lint.md) tool.
project namespace. For example, `https://gitlab.example.com/gitlab-org/project-123/-/ci/lint`.
-### Unavailable names for jobs
-
-Each job must have a unique name, but there are a few **reserved `keywords` that
-can't be used as job names**:
-
-- `image`
-- `services`
-- `stages`
-- `types`
-- `before_script`
-- `after_script`
-- `variables`
-- `cache`
-- `include`
+## Job keywords
-### Using reserved keywords
+A job is defined as a list of keywords that define the job's behavior.
-If you get validation error when using specific values (for example, `true` or `false`), try to:
-
-- Quote them.
-- Change them to a different form. For example, `/bin/true`.
-
-## Configuration parameters
-
-A job is defined as a list of parameters that define the job's behavior.
-
-The following table lists available parameters for jobs:
+The following table lists available keywords for jobs:
| Keyword | Description |
|:---------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`script`](#script) | Shell script that is executed by a runner. |
-| [`after_script`](#before_script-and-after_script) | Override a set of commands that are executed after job. |
+| [`after_script`](#after_script) | Override a set of commands that are executed after job. |
| [`allow_failure`](#allow_failure) | Allow job to fail. Failed job does not contribute to commit status. |
| [`artifacts`](#artifacts) | List of files and directories to attach to a job on success. Also available: `artifacts:paths`, `artifacts:exclude`, `artifacts:expose_as`, `artifacts:name`, `artifacts:untracked`, `artifacts:when`, `artifacts:expire_in`, and `artifacts:reports`. |
-| [`before_script`](#before_script-and-after_script) | Override a set of commands that are executed before job. |
+| [`before_script`](#before_script) | Override a set of commands that are executed before job. |
| [`cache`](#cache) | List of files that should be cached between subsequent runs. Also available: `cache:paths`, `cache:key`, `cache:untracked`, `cache:when`, and `cache:policy`. |
| [`coverage`](#coverage) | Code coverage settings for a given job. |
| [`dependencies`](#dependencies) | Restrict which artifacts are passed to a specific job by providing a list of jobs to fetch artifacts from. |
@@ -130,22 +54,44 @@ The following table lists available parameters for jobs:
| [`variables`](#variables) | Define job variables on a job level. |
| [`when`](#when) | When to run job. Also available: `when:manual` and `when:delayed`. |
-## Global parameters
+### Unavailable names for jobs
-Some parameters must be defined at a global level, affecting all jobs in the pipeline.
+Each job must have a unique name, but there are a few **reserved `keywords` that
+can't be used as job names**:
+
+- `image`
+- `services`
+- `stages`
+- `types`
+- `before_script`
+- `after_script`
+- `variables`
+- `cache`
+- `include`
+
+## Global keywords
+
+Some keywords must be defined at a global level, affecting all jobs in the pipeline.
+
+### Using reserved keywords
+
+If you get validation error when using specific values (for example, `true` or `false`), try to:
+
+- Quote them.
+- Change them to a different form. For example, `/bin/true`.
### Global defaults
-Some parameters can be set globally as the default for all jobs using the
-`default:` keyword. Default parameters can then be overridden by job-specific
+Some keywords can be set globally as the default for all jobs using the
+`default:` keyword. Default keywords can then be overridden by job-specific
configuration.
-The following job parameters can be defined inside a `default:` block:
+The following job keywords can be defined inside a `default:` block:
- [`image`](#image)
- [`services`](#services)
-- [`before_script`](#before_script-and-after_script)
-- [`after_script`](#before_script-and-after_script)
+- [`before_script`](#before_script)
+- [`after_script`](#after_script)
- [`tags`](#tags)
- [`cache`](#cache)
- [`artifacts`](#artifacts)
@@ -173,20 +119,20 @@ rspec 2.6:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207484) in GitLab 12.9.
You can disable inheritance of globally defined defaults
-and variables with the `inherit:` parameter.
+and variables with the `inherit:` keyword.
-To enable or disable the inheritance of all `variables:` or `default:` parameters, use the following format:
+To enable or disable the inheritance of all `variables:` or `default:` keywords, use the following format:
- `default: true` or `default: false`
- `variables: true` or `variables: false`
-To inherit only a subset of `default:` parameters or `variables:`, specify what
+To inherit only a subset of `default:` keywords or `variables:`, specify what
you wish to inherit. Anything not listed is **not** inherited. Use
one of the following formats:
```yaml
inherit:
- default: [parameter1, parameter2]
+ default: [keyword1, keyword2]
variables: [VARIABLE1, VARIABLE2]
```
@@ -195,8 +141,8 @@ Or:
```yaml
inherit:
default:
- - parameter1
- - parameter2
+ - keyword1
+ - keyword2
variables:
- VARIABLE1
- VARIABLE2
@@ -288,23 +234,23 @@ There are also two edge cases worth mentioning:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29654) in GitLab 12.5
-The top-level `workflow:` key applies to the entirety of a pipeline, and
-determines whether or not a pipeline is created. It accepts a single
-`rules:` key that operates similarly to [`rules:` defined within jobs](#rules),
-enabling dynamic configuration of the pipeline.
+The top-level `workflow:` keyword determines whether or not a pipeline is created.
+It accepts a single `rules:` keyword that is similar to [`rules:` defined within jobs](#rules).
+Use it to define what can trigger a new pipeline.
-If you are new to GitLab CI/CD and `workflow: rules`, you may find the [`workflow:rules` templates](#workflowrules-templates) useful.
+You can use the [`workflow:rules` templates](#workflowrules-templates) to import
+a preconfigured `workflow: rules` entry.
-To define your own `workflow: rules`, the available configuration options are:
+`workflow: rules` accepts these keywords:
-- [`if`](#rulesif): Define a rule.
-- [`when`](#when): May be set to `always` or `never` only. If not provided, the default value is `always`​.
+- [`if`](#rulesif): Check this rule to determine when to run a pipeline.
+- [`when`](#when): Specify what to do when the `if` rule evaluates to true.
+ - To run a pipeline, set to `always`.
+ - To prevent pipelines from running, set to `never`.
-If a pipeline attempts to run but matches no rule, it's dropped and doesn't run.
+When no rules evaluate to true, the pipeline does not run.
-Use the example rules below exactly as written to allow pipelines that match the rule
-to run. Add `when: never` to prevent pipelines that match the rule from running. See
-the [common `if` clauses for `rules`](#common-if-clauses-for-rules) for more examples.
+Some example `if` clauses for `workflow: rules`:
| Example rules | Details |
|------------------------------------------------------|-----------------------------------------------------------|
@@ -313,9 +259,12 @@ the [common `if` clauses for `rules`](#common-if-clauses-for-rules) for more exa
| `if: $CI_COMMIT_TAG` | Control when tag pipelines run. |
| `if: $CI_COMMIT_BRANCH` | Control when branch pipelines run. |
+See the [common `if` clauses for `rules`](#common-if-clauses-for-rules) for more examples.
+
For example, in the following configuration, pipelines run for all `push` events (changes to
-branches and new tags). Only push events with `-wip` in the commit message are excluded. Scheduled
-pipelines and merge request pipelines don't run, as there's no rule allowing them.
+branches and new tags). Pipelines for push events with `-wip` in the commit message
+don't run, because they are set to `when: never`. Pipelines for schedules or merge requests
+don't run either, because no rules evaluate to true for them:
```yaml
workflow:
@@ -325,11 +274,11 @@ workflow:
- if: '$CI_PIPELINE_SOURCE == "push"'
```
-This example has strict rules, and no other pipelines can run.
+This example has strict rules, and pipelines do **not** run in any other case.
-Alternatively, you can have loose rules by using only `when: never` rules, followed
-by a final `when: always` rule. This allows all types of pipelines, except for any
-that match the `when: never` rules:
+Alternatively, all of the rules can be `when: never`, with a final
+`when: always` rule. Pipelines that match the `when: never` rules do not run.
+All other pipeline types run:
```yaml
workflow:
@@ -341,12 +290,13 @@ workflow:
- when: always
```
-This example never allows pipelines for schedules or `push` (branches and tags) pipelines,
-but does allow pipelines in **all** other cases, *including* merge request pipelines.
+This example prevents pipelines for schedules or `push` (branches and tags) pipelines.
+The final `when: always` rule lets all other pipeline types run, **including** merge
+request pipelines.
-Be careful not to use a configuration that might run
-merge request pipelines and branch pipelines at the same time. As with `rules` defined in jobs,
-it can cause [duplicate pipelines](#prevent-duplicate-pipelines).
+Be careful not to have rules that match both branch pipelines
+and merge request pipelines. Similar to `rules` defined in jobs, this can cause
+[duplicate pipelines](#prevent-duplicate-pipelines).
#### `workflow:rules` templates
@@ -405,7 +355,7 @@ of using YAML anchors, you can use the [`extends` keyword](#extends).
`include` supports the following inclusion methods:
-| Method | Description |
+| Keyword | Method |
|:--------------------------------|:------------------------------------------------------------------|
| [`local`](#includelocal) | Include a file from the local project repository. |
| [`file`](#includefile) | Include a file from a different project repository. |
@@ -471,7 +421,7 @@ include:
file: '/templates/.gitlab-ci-template.yml'
```
-You can also specify `ref`, with the default being the `HEAD` of the project:
+You can also specify a `ref`. If not specified, it defaults to the `HEAD` of the project:
```yaml
include:
@@ -492,11 +442,47 @@ All [nested includes](#nested-includes) are executed in the scope of the target
This means you can use local (relative to target project), project, remote,
or template includes.
+##### Multiple files from a project
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26793) in GitLab 13.6.
+> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to disable it. **(CORE ONLY)**
+
+You can include multiple files from the same project:
+
+```yaml
+include:
+ - project: 'my-group/my-project'
+ ref: master
+ file:
+ - '/templates/.builds.yml'
+ - '/templates/.tests.yml'
+```
+
+Including multiple files from the same project is under development but ready for production use. It is
+deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
+can opt to disable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:ci_include_multiple_files_from_project)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:ci_include_multiple_files_from_project)
+```
+
#### `include:remote`
`include:remote` can be used to include a file from a different location,
-using HTTP/HTTPS, referenced by using the full URL. The remote file must be
-publicly accessible through a simple GET request as authentication schemas
+using HTTP/HTTPS, referenced by the full URL. The remote file must be
+publicly accessible by a GET request, because authentication schemas
in the remote URL are not supported. For example:
```yaml
@@ -542,15 +528,15 @@ Nested includes allow you to compose a set of includes.
A total of 100 includes is allowed, but duplicate includes are considered a configuration error.
In [GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/issues/28212) and later, the time limit
-for resolving all files is 30 seconds.
+to resolve all files is 30 seconds.
#### Additional `includes` examples
There is a list of [additional `includes` examples](includes.md) available.
-## Parameter details
+## Keyword details
-The following are detailed explanations for parameters used to configure CI/CD pipelines.
+The following are detailed explanations for keywords used to configure CI/CD pipelines.
### `image`
@@ -558,7 +544,7 @@ Used to specify [a Docker image](../docker/using_docker_images.md#what-is-an-ima
For:
-- Simple definition examples, see [Define `image` and `services` from `.gitlab-ci.yml`](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml).
+- Usage examples, see [Define `image` and `services` from `.gitlab-ci.yml`](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml).
- Detailed usage information, refer to [Docker integration](../docker/README.md) documentation.
#### `image:name`
@@ -579,7 +565,7 @@ Used to specify a [service Docker image](../docker/using_docker_images.md#what-i
For:
-- Simple definition examples, see [Define `image` and `services` from `.gitlab-ci.yml`](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml).
+- Usage examples, see [Define `image` and `services` from `.gitlab-ci.yml`](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml).
- Detailed usage information, refer to [Docker integration](../docker/README.md) documentation.
- For example services, see [GitLab CI/CD Services](../services/README.md).
@@ -617,9 +603,9 @@ job:
script: "bundle exec rspec"
```
-[YAML anchors for scripts](#yaml-anchors-for-script) are available.
+You can use [YAML anchors with `script`](#yaml-anchors-for-scripts).
-This parameter can also contain several commands using an array:
+This keyword can also contain several commands in an array:
```yaml
job:
@@ -635,8 +621,8 @@ a "key: value" pair. Be careful when using special characters:
`:`, `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` ``.
If any of the script commands return an exit code other than zero, the job
-fails and further commands are not executed. You can avoid this behavior by
-storing the exit code in a variable:
+fails and further commands are not executed. Store the exit code in a variable to
+avoid this behavior:
```yaml
job:
@@ -645,191 +631,86 @@ job:
- if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;
```
-#### `before_script` and `after_script`
+#### `before_script`
> Introduced in GitLab 8.7 and requires GitLab Runner v1.2.
-`before_script` is used to define commands that should be run before each
-job, including deploy jobs, but after the restoration of any [artifacts](#artifacts).
-This must be an array.
+`before_script` is used to define commands that should run before each job, including
+deploy jobs, but after the restoration of any [artifacts](#artifacts). This must be an array.
Scripts specified in `before_script` are concatenated with any scripts specified
in the main [`script`](#script), and executed together in a single shell.
-`after_script` is used to define commands that run after each
-job, including failed jobs. This must be an array. If a job times out or is cancelled,
-the `after_script` commands are not executed. Support for executing `after_script`
-commands for timed-out or cancelled jobs
-[is planned](https://gitlab.com/gitlab-org/gitlab/-/issues/15603).
-
-Scripts specified in `after_script` are executed in a new shell, separate from any
-`before_script` or `script` scripts. As a result, they:
-
-- Have a current working directory set back to the default.
-- Have no access to changes done by scripts defined in `before_script` or `script`, including:
- - Command aliases and variables exported in `script` scripts.
- - Changes outside of the working tree (depending on the runner executor), like
- software installed by a `before_script` or `script` script.
-- Have a separate timeout, which is hard coded to 5 minutes. See
- [related issue](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2716) for details.
-- Don't affect the job's exit code. If the `script` section succeeds and the
- `after_script` times out or fails, the job exits with code `0` (`Job Succeeded`).
-
-It's possible to overwrite a globally defined `before_script` or `after_script`
-if you set it per-job:
+It's possible to overwrite a globally defined `before_script` if you define it in a job:
```yaml
default:
before_script:
- - global before script
-
-job:
- before_script:
- - execute this instead of global before script
- script:
- - my command
- after_script:
- - execute this after my script
-```
-
-[YAML anchors for `before_script` and `after_script`](#yaml-anchors-for-before_script-and-after_script) are available.
+ - echo "Execute this in all jobs that don't already have a before_script section."
-#### Coloring script output
-
-Script output can be colored using [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors),
-or by running commands or programs that output ANSI escape codes.
-
-For example, using [Bash with color codes](https://misc.flogisoft.com/bash/tip_colors_and_formatting):
-
-```yaml
-job:
+job1:
script:
- - echo -e "\e[31mThis text is red,\e[0m but this text isn't\e[31m however this text is red again."
-```
+ - echo "This executes after the global before_script."
-You can define the color codes in Shell variables, or even [custom environment variables](../variables/README.md#custom-environment-variables),
-which makes the commands easier to read and reusable.
-
-For example, using the same example as above and variables defined in a `before_script`:
-
-```yaml
job:
before_script:
- - TXT_RED="\e[31m" && TXT_CLEAR="\e[0m"
+ - echo "Execute this instead of the global before_script."
script:
- - echo -e "${TXT_RED}This text is red,${TXT_CLEAR} but this part isn't${TXT_RED} however this part is again."
- - echo "This text is not colored"
+ - echo "This executes after the job's `before_script`"
```
-Or with [PowerShell color codes](https://superuser.com/a/1259916):
+You can use [YAML anchors with `before_script`](#yaml-anchors-for-scripts).
-```yaml
-job:
- before_script:
- - $esc="$([char]27)"; $TXT_RED="$esc[31m"; $TXT_CLEAR="$esc[0m"
- script:
- - Write-Host $TXT_RED"This text is red,"$TXT_CLEAR" but this text isn't"$TXT_RED" however this text is red again."
- - Write-Host "This text is not colored"
-```
-
-#### Multi-line commands
+#### `after_script`
-You can split long commands into multi-line commands to improve readability
-using [`|` (literal) and `>` (folded) YAML multi-line block scalar indicators](https://yaml-multiline.info/).
-
-CAUTION: **Warning:**
-If multiple commands are combined into one command string, only the last command's
-failure or success is reported.
-[Failures from earlier commands are ignored due to a bug](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394).
-To work around this,
-run each command as a separate `script:` item, or add an `exit 1` command
-to each command string.
+Introduced in GitLab 8.7 and requires GitLab Runner v1.2.
-You can use the `|` (literal) YAML multiline block scalar indicator to write
-commands over multiple lines in the `script` section of a job description.
-Each line is treated as a separate command.
-Only the first command is repeated in the job log, but additional
-commands are still executed:
+`after_script` is used to define commands that run after each job, including failed
+jobs. This must be an array.
-```yaml
-job:
- script:
- - |
- echo "First command line."
- echo "Second command line."
- echo "Third command line."
-```
-
-The example above renders in the job log as:
+If a job times out or is cancelled, the `after_script` commands are not executed.
+Support for executing `after_script` commands for timed-out or cancelled jobs
+[is planned](https://gitlab.com/gitlab-org/gitlab/-/issues/15603).
-```shell
-$ echo First command line # collapsed multi-line command
-First command line
-Second command line.
-Third command line.
-```
+Scripts specified in `after_script` are executed in a new shell, separate from any
+`before_script` or `script` scripts. As a result, they:
-The `>` (folded) YAML multiline block scalar indicator treats empty lines between
-sections as the start of a new command:
+- Have a current working directory set back to the default.
+- Have no access to changes done by scripts defined in `before_script` or `script`, including:
+ - Command aliases and variables exported in `script` scripts.
+ - Changes outside of the working tree (depending on the runner executor), like
+ software installed by a `before_script` or `script` script.
+- Have a separate timeout, which is hard coded to 5 minutes. See the
+ [related issue](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2716) for details.
+- Don't affect the job's exit code. If the `script` section succeeds and the
+ `after_script` times out or fails, the job exits with code `0` (`Job Succeeded`).
```yaml
-job:
- script:
- - >
- echo "First command line
- is split over two lines."
-
- echo "Second command line."
-```
-
-This behaves similarly to writing multiline commands without the `>` or `|` block
-scalar indicators:
+default:
+ after_script:
+ - echo "Execute this in all jobs that don't already have an after_script section."
-```yaml
-job:
+job1:
script:
- - echo "First command line
- is split over two lines."
-
- echo "Second command line."
-```
-
-Both examples above render in the job log as:
-
-```shell
-$ echo First command line is split over two lines. # collapsed multi-line command
-First command line is split over two lines.
-Second command line.
-```
-
-When you omit the `>` or `|` block scalar indicators, GitLab forms the command
-by concatenating non-empty lines. Make sure the lines can run when concatenated.
+ - echo "This executes first. When it completes, the global after_script executes."
-Shell [here documents](https://en.wikipedia.org/wiki/Here_document) work with the
-`|` and `>` operators as well. The example below transliterates the lower case letters
-to upper case:
-
-```yaml
job:
script:
- - |
- tr a-z A-Z << END_TEXT
- one two three
- four five six
- END_TEXT
+ - echo "This executes first. When it completes, the job's `after_script` executes."
+ after_script:
+ - echo "Execute this instead of the global after_script."
```
-Results in:
+You can use [YAML anchors with `after_script`](#yaml-anchors-for-scripts).
-```shell
-$ tr a-z A-Z << END_TEXT # collapsed multi-line command
- ONE TWO THREE
- FOUR FIVE SIX
-```
+#### Script syntax
-#### Custom collapsible sections
+You can use special syntax in [`script`](README.md#script) sections to:
-See [custom collapsible sections](../pipelines/index.md#custom-collapsible-sections).
+- [Split long commands](script.md#split-long-commands) into multiline commands.
+- [Use color codes](script.md#add-color-codes-to-script-output) to make job logs easier to review.
+- [Create custom collapsible sections](../jobs/index.md#custom-collapsible-sections)
+ to simplify job log output.
### `stage`
@@ -968,7 +849,7 @@ rspec:
- $RSPEC
```
-If you do want to include the `rake test`, see [`before_script` and `after_script`](#before_script-and-after_script).
+If you do want to include the `rake test`, see [`before_script`](#before_script) or [`after_script`](#after_script).
`.tests` in this example is a [hidden job](#hide-jobs), but it's
possible to inherit from regular jobs as well.
@@ -1422,29 +1303,20 @@ Other commonly used variables for `if` clauses:
#### `rules:changes`
-To determine if jobs should be added to a pipeline, `rules: changes` clauses check
-the files changed by Git push events.
+`rules:changes` determines whether or not to add jobs to a pipeline by checking for
+changes to specific files.
`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'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:
+accepting an array of paths. It's recommended to only use `rules: changes` with branch
+pipelines or merge request pipelines. For example, it's common to use `rules: changes`
+with merge request pipelines:
```yaml
-workflow:
- rules:
- - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
-
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- - changes:
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+ changes:
- Dockerfile
when: manual
allow_failure: true
@@ -1452,14 +1324,77 @@ docker build:
In this example:
-- [`workflow: rules`](#workflowrules) allows only pipelines for merge requests for all jobs.
+- If the pipeline is a merge request pipeline, check `Dockerfile` for changes.
- If `Dockerfile` has changed, add the job to the pipeline as a manual job, and allow the pipeline
to continue running even if the job is not triggered (`allow_failure: true`).
- If `Dockerfile` has not changed, do not add job to any pipeline (same as `when: never`).
-To implement a rule similar to [`except: changes`](#onlychangesexceptchanges),
+To use `rules: changes` with branch pipelines instead of merge request pipelines,
+change the `if:` clause in the example above to:
+
+```yaml
+rules:
+ - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH
+```
+
+To implement a rule similar to [`except:changes`](#onlychangesexceptchanges),
use `when: never`.
+CAUTION: **Caution:**
+You can use `rules: changes` with other pipeline types, but it is not recommended
+because `rules: changes` always evaluates to true when there is no Git `push` event.
+Tag pipelines, scheduled pipelines, and so on do **not** have a Git `push` event
+associated with them. A `rules: changes` job is **always** added to those pipeline
+if there is no `if:` statement that limits the job to branch or merge request pipelines.
+
+##### Variables in `rules:changes`
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34272) in GitLab 13.6.
+> - It was [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/267192) in GitLab 13.6.
+> - 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-variables-support-in-ruleschanges). **(CORE ONLY)**
+
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+Environment variables can be used in `rules:changes` expressions to determine when
+to add jobs to a pipeline:
+
+```yaml
+docker build:
+ variables:
+ DOCKERFILES_DIR: 'path/to/files/'
+ script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
+ rules:
+ - changes:
+ - $DOCKERFILES_DIR/*
+```
+
+The `$` character can be used for both variables and paths. For example, if the
+`$DOCKERFILES_DIR` variable exists, its value is used. If it does not exist, the
+`$` is interpreted as being part of a path.
+
+###### Enable or disable variables support in `rules:changes` **(CORE ONLY)**
+
+Variables support in `rules:changes` is under development, but is ready for production use.
+It is deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
+can opt to disable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:ci_variable_expansion_in_rules_changes)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:ci_variable_expansion_in_rules_changes)
+```
+
#### `rules:exists`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24021) in GitLab 12.4.
@@ -1567,7 +1502,7 @@ The [`rules`](#rules) syntax is an improved, more powerful solution for defining
when jobs should run or not. Consider using `rules` instead of `only/except` to get
the most out of your pipelines.
-`only` and `except` are two parameters that set a job policy to limit when
+`only` and `except` are two keywords that set a job policy to limit when
jobs are created:
1. `only` defines the names of branches and tags the job runs for.
@@ -1695,7 +1630,7 @@ while just `/issue/` would also match a branch called `severe-issues`.
#### Supported `only`/`except` regexp syntax
In GitLab 11.9.4, GitLab began internally converting the regexp used
-in `only` and `except` parameters to [RE2](https://github.com/google/re2/wiki/Syntax).
+in `only` and `except` keywords to [RE2](https://github.com/google/re2/wiki/Syntax).
[RE2](https://github.com/google/re2/wiki/Syntax) limits the set of available features
due to computational complexity, and some features, like negative lookaheads, became unavailable.
@@ -2489,7 +2424,7 @@ deployment to the `production` environment.
> - Before GitLab 8.11, the name of an environment could be defined as a string like
> `environment: production`. The recommended way now is to define it under the
> `name` keyword.
-> - The `name` parameter can use any of the defined CI variables,
+> - The `name` keyword can use any of the defined CI variables,
> including predefined, secure variables and `.gitlab-ci.yml` [`variables`](#variables).
> You however can't use variables defined under `script`.
@@ -2525,7 +2460,7 @@ deploy to production:
> - Introduced in GitLab 8.11.
> - Before GitLab 8.11, the URL could be added only in GitLab's UI. The
> recommended way now is to define it in `.gitlab-ci.yml`.
-> - The `url` parameter can use any of the defined CI variables,
+> - The `url` keyword can use any of the defined CI variables,
> including predefined, secure variables and `.gitlab-ci.yml` [`variables`](#variables).
> You however can't use variables defined under `script`.
@@ -2624,7 +2559,7 @@ In the example above, if the configuration is not identical:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20956) in GitLab 12.8.
-The `auto_stop_in` keyword is for specifying life period of the environment,
+The `auto_stop_in` keyword is for specifying the lifetime of the environment,
that when expired, GitLab automatically stops them.
For example,
@@ -2637,8 +2572,8 @@ review_app:
auto_stop_in: 1 day
```
-When `review_app` job is executed and a review app is created, a life period of
-the environment is set to `1 day`.
+When the environment for `review_app` is created, the environment's lifetime is set to `1 day`.
+Every time the review app is deployed, that lifetime is also reset to `1 day`.
For more information, see
[the environments auto-stop documentation](../environments/index.md#environments-auto-stop)
@@ -2679,7 +2614,7 @@ To follow progress on support for GitLab-managed clusters, see the
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21971) in GitLab 8.12 and GitLab Runner 1.6.
> - The `$CI_ENVIRONMENT_SLUG` was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22864) in GitLab 8.15.
-> - The `name` and `url` parameters can use any of the defined CI variables,
+> - The `name` and `url` keywords can use any of the defined CI variables,
> including predefined, secure variables and `.gitlab-ci.yml` [`variables`](#variables).
> You however can't use variables defined under `script`.
@@ -2774,11 +2709,7 @@ Otherwise cache content can be overwritten.
> Introduced in GitLab Runner v1.0.0.
-The cache is shared between jobs, so 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` parameter defines the affinity of caching between jobs.
+The `key` keyword defines the affinity of caching between jobs.
You can 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,
including caching data between different jobs or even different branches.
@@ -2812,6 +2743,32 @@ URI-encoded `%2F`. A value made only of dots (`.`, `%2E`) is also forbidden.
You can specify a [fallback cache key](#fallback-cache-key) to use if the specified `cache:key` is not found.
+#### Fallback cache key
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/1534) in GitLab Runner 13.4.
+
+You can use the `$CI_COMMIT_REF_SLUG` [variable](#variables) to specify your [`cache:key`](#cachekey).
+For example, if your `$CI_COMMIT_REF_SLUG` is `test` you can set a job
+to download cache that's tagged with `test`.
+
+If a cache with this tag is not found, you can use `CACHE_FALLBACK_KEY` to
+specify a cache to use when none exists.
+
+For example:
+
+```yaml
+variables:
+ CACHE_FALLBACK_KEY: fallback-key
+
+cache:
+ key: "$CI_COMMIT_REF_SLUG"
+ paths:
+ - binaries/
+```
+
+In this example, if the `$CI_COMMIT_REF_SLUG` is not found, the job uses the key defined
+by the `CACHE_FALLBACK_KEY` variable.
+
##### `cache:key:files`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18986) in GitLab v12.5.
@@ -2847,7 +2804,7 @@ use the new cache, instead of rebuilding the dependencies.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18986) in GitLab v12.5.
When you want to combine a prefix with the SHA computed for `cache:key:files`,
-use the `prefix` parameter with `key:files`.
+use the `prefix` keyword with `key:files`.
For example, if you add a `prefix` of `test`, the resulting key is: `test-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5`.
If neither file was changed in any commits, the prefix is added to `default`, so the
key in the example would be `test-default`.
@@ -3307,7 +3264,7 @@ It also exposes these reports in GitLab's UI (merge requests, pipeline views, an
These are the available report types:
-| Parameter | Description |
+| Keyword | Description |
|--------------------------------------------------------------------------------------------------------------------------------------|-------------|
| [`artifacts:reports:cobertura`](../pipelines/job_artifacts.md#artifactsreportscobertura) | The `cobertura` report collects Cobertura coverage XML files. |
| [`artifacts:reports:codequality`](../pipelines/job_artifacts.md#artifactsreportscodequality) | The `codequality` report collects CodeQuality issues. |
@@ -3329,7 +3286,7 @@ These are the available report types:
> Introduced in GitLab 8.6 and GitLab Runner v1.1.1.
By default, all [`artifacts`](#artifacts) from previous [stages](#stages)
-are passed to each job. However, you can use the `dependencies` parameter to
+are passed to each job. However, you can use the `dependencies` keyword to
define a limited list of jobs to fetch artifacts from. You can also set a job to download no artifacts at all.
To use this feature, define `dependencies` in context of the job and pass
@@ -3495,7 +3452,7 @@ Possible values for `when` are:
- `scheduler_failure`: Retry if the scheduler failed to assign the job to a runner.
- `data_integrity_failure`: Retry if there was a structural integrity problem detected.
-You can specify the number of [retry attempts for certain stages of job execution](#job-stages-attempts) using variables.
+You can specify the number of [retry attempts for certain stages of job execution](../runners/README.md#job-stages-attempts) using variables.
### `timeout`
@@ -3522,7 +3479,7 @@ exceed the runner-specific timeout.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21480) in GitLab 11.5.
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.
+parallel. This value can be from 2 to 50.
This creates N instances of the same job that run in parallel. They are named
sequentially from `job_name 1/N` to `job_name N/N`.
@@ -3574,9 +3531,6 @@ There can be from 2 to 50 jobs.
[In GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/26362) and later,
you can have one-dimensional matrices with a single job.
-The ability to have one-dimensional matrices is [deployed behind a feature flag](../../user/feature_flags.md),
-enabled by default. It's enabled on GitLab.com. For self-managed GitLab instances,
-administrators can opt to disable it by [disabling the `one_dimensional_matrix:` feature flag](../../administration/feature_flags.md). **(CORE ONLY)**
Every job gets the same `CI_NODE_TOTAL` [environment variable](../variables/README.md#predefined-environment-variables) value, and a unique `CI_NODE_INDEX` value.
@@ -3624,8 +3578,8 @@ Use `trigger` to define a downstream pipeline trigger. When GitLab starts a job
with a `trigger` definition, a downstream pipeline is created.
Jobs with `trigger` can only use a [limited set of keywords](../multi_project_pipelines.md#limitations).
-For example, you can't run commands with [`script`](#script), [`before_script`](#before_script-and-after_script),
-or [`after_script`](#before_script-and-after_script).
+For example, you can't run commands with [`script`](#script), [`before_script`](#before_script),
+or [`after_script`](#after_script).
You can use this keyword to create two different types of downstream pipelines:
@@ -3784,7 +3738,7 @@ starting, which reduces parallelization.
To force a rebuild of a specific branch, tag, or commit, you can use an API call
with a trigger token.
-The trigger token is different than the [`trigger`](#trigger) parameter.
+The trigger token is different than the [`trigger`](#trigger) keyword.
[Read more in the triggers documentation.](../triggers/README.md)
@@ -3884,8 +3838,8 @@ For more information, see [Deployments Safety](../environments/deployment_safety
These methods are supported:
- [`tag_name`](#releasetag_name)
+- [`description`](#releasedescription)
- [`name`](#releasename) (optional)
-- [`description`](#releasedescription) (optional)
- [`ref`](#releaseref) (optional)
- [`milestones`](#releasemilestones) (optional)
- [`released_at`](#releasereleased_at) (optional)
@@ -3943,7 +3897,7 @@ For example, when creating a Release from a Git tag:
job:
release:
tag_name: $CI_COMMIT_TAG
- description: changelog.txt
+ description: 'Release description'
```
It is also possible to create any unique tag, in which case `only: tags` is not mandatory.
@@ -3953,7 +3907,7 @@ A semantic versioning example:
job:
release:
tag_name: ${MAJOR}_${MINOR}_${REVISION}
- description: changelog.txt
+ description: 'Release description'
```
- The Release is created only if the job's main script succeeds.
@@ -4160,8 +4114,8 @@ Read more on [GitLab Pages user documentation](../../user/project/pages/index.md
> Introduced in GitLab Runner v0.5.0.
-Variables are configurable values that are passed to jobs. They can be set
-globally and per-job.
+[CI/CD variables](../variables/README.md) are configurable values that are passed to jobs.
+They can be set globally and per-job.
There are two types of variables.
@@ -4178,372 +4132,49 @@ Variables are meant for non-sensitive project configuration, for example:
```yaml
variables:
- DATABASE_URL: "postgres://postgres@postgres/my_database"
+ DEPLOY_SITE: "https://example.com/"
+
+deploy_job:
+ stage: deploy
+ script:
+ - deploy-script --url $DEPLOY_SITE --path "/"
+
+deploy_review_job:
+ stage: deploy
+ variables:
+ REVIEW_PATH: "/review"
+ script:
+ - deploy-review-script --url $DEPLOY_SITE --path $REVIEW_PATH
```
-You can use integers and strings for the variable's name and value.
-You cannot use floats.
+You can use only integers and strings for the variable's name and value.
If you define a variable at the top level of the `gitlab-ci.yml` file, it is global,
-meaning it applies to all jobs.
-
-If you define a variable within a job, it's available to that job only.
+meaning it applies to all jobs. If you define a variable within a job, it's available
+to that job only.
If a variable of the same name is defined globally and for a specific job, the
[job-specific variable is used](../variables/README.md#priority-of-environment-variables).
All YAML-defined variables are also set to any linked
-[service containers](../docker/using_docker_images.md#what-is-a-service).
-
-[YAML anchors for variables](#yaml-anchors-for-variables) are available.
-
-Learn more about [variables and their priority](../variables/README.md).
-
-### Git strategy
-
-> - Introduced in GitLab 8.9 as an experimental feature.
-> - `GIT_STRATEGY=none` requires GitLab Runner v1.7+.
-
-You can set the `GIT_STRATEGY` used for getting recent application code, either
-globally or per-job in the [`variables`](#variables) section. If left
-unspecified, the default from the project settings is used.
-
-There are three possible values: `clone`, `fetch`, and `none`.
-
-`clone` is the slowest option. It clones the repository from scratch for every
-job, ensuring that the local working copy is always pristine.
-
-```yaml
-variables:
- GIT_STRATEGY: clone
-```
-
-`fetch` is faster as it re-uses the local working copy (falling back to `clone`
-if it does not exist). `git clean` is used to undo any changes made by the last
-job, and `git fetch` is used to retrieve commits made since the last job ran.
-
-```yaml
-variables:
- GIT_STRATEGY: fetch
-```
-
-`none` also re-uses the local working copy. However, it skips all Git operations,
-including GitLab Runner's pre-clone script, if present.
-
-It's useful for jobs that operate exclusively on artifacts, like a deployment job.
-Git repository data may be present, but it's likely out-of-date. You should only
-rely on files brought into the local working copy from cache or artifacts.
-
-```yaml
-variables:
- GIT_STRATEGY: none
-```
-
-NOTE: **Note:**
-`GIT_STRATEGY` is not supported for
-[Kubernetes executor](https://docs.gitlab.com/runner/executors/kubernetes.html),
-but may be in the future. See the [support Git strategy with Kubernetes executor feature proposal](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3847)
-for updates.
-
-### Git submodule strategy
-
-> Requires GitLab Runner v1.10+.
-
-The `GIT_SUBMODULE_STRATEGY` variable is used to control if / how Git
-submodules are included when fetching the code before a build. You can set them
-globally or per-job in the [`variables`](#variables) section.
-
-There are three possible values: `none`, `normal`, and `recursive`:
-
-- `none` means that submodules are not included when fetching the project
- code. This is the default, which matches the pre-v1.10 behavior.
-
-- `normal` means that only the top-level submodules are included. It's
- equivalent to:
-
- ```shell
- git submodule sync
- git submodule update --init
- ```
-
-- `recursive` means that all submodules (including submodules of submodules)
- are included. This feature needs Git v1.8.1 and later. When using a
- GitLab Runner with an executor not based on Docker, make sure the Git version
- meets that requirement. It's equivalent to:
-
- ```shell
- git submodule sync --recursive
- git submodule update --init --recursive
- ```
-
-For this feature to work correctly, the submodules must be configured
-(in `.gitmodules`) with either:
-
-- the HTTP(S) URL of a publicly-accessible repository, or
-- a relative path to another repository on the same GitLab server. See the
- [Git submodules](../git_submodules.md) documentation.
-
-### Git checkout
-
-> Introduced in GitLab Runner 9.3.
-
-The `GIT_CHECKOUT` variable can be used when the `GIT_STRATEGY` is set to either
-`clone` or `fetch` to specify whether a `git checkout` should be run. If not
-specified, it defaults to true. You can set them globally or per-job in the
-[`variables`](#variables) section.
-
-If set to `false`, the runner:
-
-- when doing `fetch` - updates the repository and leaves the working copy on
- the current revision,
-- when doing `clone` - clones the repository and leaves the working copy on the
- default branch.
-
-If `GIT_CHECKOUT` is set to `true`, both `clone` and `fetch` work the same way.
-The runner checks out the working copy of a revision related
-to the CI pipeline:
-
-```yaml
-variables:
- GIT_STRATEGY: clone
- GIT_CHECKOUT: "false"
-script:
- - git checkout -B master origin/master
- - git merge $CI_COMMIT_SHA
-```
-
-### Git clean flags
-
-> Introduced in GitLab Runner 11.10
-
-The `GIT_CLEAN_FLAGS` variable is used to control the default behavior of
-`git clean` after checking out the sources. You can set it globally or per-job in the
-[`variables`](#variables) section.
-
-`GIT_CLEAN_FLAGS` accepts all possible options of the [`git clean`](https://git-scm.com/docs/git-clean)
-command.
-
-`git clean` is disabled if `GIT_CHECKOUT: "false"` is specified.
-
-If `GIT_CLEAN_FLAGS` is:
-
-- Not specified, `git clean` flags default to `-ffdx`.
-- Given the value `none`, `git clean` is not executed.
-
-For example:
-
-```yaml
-variables:
- GIT_CLEAN_FLAGS: -ffdx -e cache/
-script:
- - ls -al cache/
-```
-
-### Git fetch extra flags
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4142) in GitLab Runner 13.1.
-
-The `GIT_FETCH_EXTRA_FLAGS` variable is used to control the behavior of
-`git fetch`. You can set it globally or per-job in the [`variables`](#variables) section.
-
-`GIT_FETCH_EXTRA_FLAGS` accepts all options of the [`git fetch`](https://git-scm.com/docs/git-fetch) command. However, `GIT_FETCH_EXTRA_FLAGS` flags are appended after the default flags that can't be modified.
-
-The default flags are:
-
-- [GIT_DEPTH](#shallow-cloning).
-- The list of [refspecs](https://git-scm.com/book/en/v2/Git-Internals-The-Refspec).
-- A remote called `origin`.
-
-If `GIT_FETCH_EXTRA_FLAGS` is:
-
-- Not specified, `git fetch` flags default to `--prune --quiet` along with the default flags.
-- Given the value `none`, `git fetch` is executed only with the default flags.
-
-For example, the default flags are `--prune --quiet`, so you can make `git fetch` more verbose by overriding this with just `--prune`:
-
-```yaml
-variables:
- GIT_FETCH_EXTRA_FLAGS: --prune
-script:
- - ls -al cache/
-```
-
-The configuration above results in `git fetch` being called this way:
+[Docker service containers](../docker/using_docker_images.md#what-is-a-service).
-```shell
-git fetch origin $REFSPECS --depth 50 --prune
-```
-
-Where `$REFSPECS` is a value provided to the runner internally by GitLab.
-
-### Job stages attempts
-
-> Introduced in GitLab, it requires GitLab Runner v1.9+.
-
-You can set the number of attempts that the running job tries to execute
-the following stages:
-
-| Variable | Description |
-|-----------------------------------|--------------------------------------------------------|
-| **ARTIFACT_DOWNLOAD_ATTEMPTS** | Number of attempts to download artifacts running a job |
-| **EXECUTOR_JOB_SECTION_ATTEMPTS** | [In GitLab 12.10](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450) and later, the number of attempts to run a section in a job after a [`No Such Container`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450) error ([Docker executor](https://docs.gitlab.com/runner/executors/docker.html) only). |
-| **GET_SOURCES_ATTEMPTS** | Number of attempts to fetch sources running a job |
-| **RESTORE_CACHE_ATTEMPTS** | Number of attempts to restore the cache running a job |
-
-The default is one single attempt.
-
-Example:
-
-```yaml
-variables:
- GET_SOURCES_ATTEMPTS: 3
-```
-
-You can set them globally or per-job in the [`variables`](#variables) section.
-
-### Fallback cache key
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/1534) in GitLab Runner 13.4.
-
-You can use the `$CI_COMMIT_REF_SLUG` variable to specify your [`cache:key`](#cachekey).
-For example, if your `$CI_COMMIT_REF_SLUG` is `test` you can set a job
-to download cache that's tagged with `test`.
-
-If a cache with this tag is not found, you can use `CACHE_FALLBACK_KEY` to
-specify a cache to use when none exists.
-
-For example:
-
-```yaml
-variables:
- CACHE_FALLBACK_KEY: fallback-key
-
-cache:
- key: "$CI_COMMIT_REF_SLUG"
- paths:
- - binaries/
-```
-
-In this example, if the `$CI_COMMIT_REF_SLUG` is not found, the job uses the key defined
-by the `CACHE_FALLBACK_KEY` variable.
-
-### Shallow cloning
-
-> Introduced in GitLab 8.9 as an experimental feature.
-
-You can specify the depth of fetching and cloning using `GIT_DEPTH`.
-`GIT_DEPTH` does a shallow clone of the repository and can significantly speed up cloning.
-It can be helpful for repositories with a large number of commits or old, large binaries. The value is
-passed to `git fetch` and `git clone`.
-
-In GitLab 12.0 and later, newly-created projects automatically have a
-[default `git depth` value of `50`](../pipelines/settings.md#git-shallow-clone).
-
-If you use a depth of `1` and have a queue of jobs or retry
-jobs, jobs may fail.
-
-Git fetching and cloning is based on a ref, such as a branch name, so runners
-can't clone a specific commit SHA. If multiple jobs are in the queue, or
-you're retrying an old job, the commit to be tested must be within the
-Git history that is cloned. Setting too small a value for `GIT_DEPTH` can make
-it impossible to run these old commits and `unresolved reference` is displayed in
-job logs. You should then reconsider changing `GIT_DEPTH` to a higher value.
-
-Jobs that rely on `git describe` may not work correctly when `GIT_DEPTH` is
-set since only part of the Git history is present.
-
-To fetch or clone only the last 3 commits:
-
-```yaml
-variables:
- GIT_DEPTH: "3"
-```
-
-You can set it globally or per-job in the [`variables`](#variables) section.
-
-### Custom build directories
+You can use [YAML anchors for variables](#yaml-anchors-for-variables).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2211) in GitLab Runner 11.10.
+### Configure runner behavior with variables
-By default, GitLab Runner clones the repository in a unique subpath of the
-`$CI_BUILDS_DIR` directory. However, your project might require the code in a
-specific directory (Go projects, for example). In that case, you can specify
-the `GIT_CLONE_PATH` variable to tell the runner the directory to clone the
-repository in:
+You can use [CI/CD variables](../variables/README.md) to configure runner Git behavior:
-```yaml
-variables:
- GIT_CLONE_PATH: $CI_BUILDS_DIR/project-name
-
-test:
- script:
- - pwd
-```
-
-The `GIT_CLONE_PATH` has to always be within `$CI_BUILDS_DIR`. The directory set in `$CI_BUILDS_DIR`
-is dependent on executor and configuration of [runners.builds_dir](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
-setting.
+- [`GIT_STRATEGY`](../runners/README.md#git-strategy)
+- [`GIT_SUBMODULE_STRATEGY`](../runners/README.md#git-submodule-strategy)
+- [`GIT_CHECKOUT`](../runners/README.md#git-checkout)
+- [`GIT_CLEAN_FLAGS`](../runners/README.md#git-clean-flags)
+- [`GIT_FETCH_EXTRA_FLAGS`](../runners/README.md#git-fetch-extra-flags)
+- [`GIT_DEPTH`](../runners/README.md#shallow-cloning) (shallow cloning)
+- [`GIT_CLONE_PATH`](../runners/README.md#custom-build-directories) (custom build directories)
-This can only be used when `custom_build_dir` is enabled in the
-[runner's configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscustom_build_dir-section).
-This is the default configuration for the `docker` and `kubernetes` executors.
-
-#### Handling concurrency
-
-An executor that uses a concurrency greater than `1` might lead
-to failures. Multiple jobs might be working on the same directory if the `builds_dir`
-is shared between jobs.
-
-The runner does not try to prevent this situation. It's up to the administrator
-and developers to comply with the requirements of runner configuration.
-
-To avoid this scenario, you can use a unique path within `$CI_BUILDS_DIR`, because runner
-exposes two additional variables that provide a unique `ID` of concurrency:
-
-- `$CI_CONCURRENT_ID`: Unique ID for all jobs running within the given executor.
-- `$CI_CONCURRENT_PROJECT_ID`: Unique ID for all jobs running within the given executor and project.
-
-The most stable configuration that should work well in any scenario and on any executor
-is to use `$CI_CONCURRENT_ID` in the `GIT_CLONE_PATH`. For example:
-
-```yaml
-variables:
- GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/project-name
-
-test:
- script:
- - pwd
-```
-
-The `$CI_CONCURRENT_PROJECT_ID` should be used in conjunction with `$CI_PROJECT_PATH`
-as the `$CI_PROJECT_PATH` provides a path of a repository. That is, `group/subgroup/project`. For example:
-
-```yaml
-variables:
- GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH
-
-test:
- script:
- - pwd
-```
-
-#### Nested paths
-
-The value of `GIT_CLONE_PATH` is expanded once and nesting variables
-within is not supported.
-
-For example, you define both the variables below in your
-`.gitlab-ci.yml` file:
-
-```yaml
-variables:
- GOPATH: $CI_BUILDS_DIR/go
- GIT_CLONE_PATH: $GOPATH/src/namespace/project
-```
-
-The value of `GIT_CLONE_PATH` is expanded once into
-`$CI_BUILDS_DIR/go/src/namespace/project`, and results in failure
-because `$CI_BUILDS_DIR` is not expanded.
+You can also use variables to configure how many times a runner
+[attempts certain stages of job execution](../runners/README.md#job-stages-attempts).
## Special YAML features
@@ -4573,7 +4204,7 @@ feature. Anchors are only valid within the file they were defined in. Instead
of using YAML anchors, you can use the [`extends` keyword](#extends).
The following example uses anchors and map merging. It creates two jobs,
-`test1` and `test2`, that inherit the parameters of `.job_template`, each
+`test1` and `test2`, that inherit the `.job_template` configuration, each
with their own custom `script` defined:
```yaml
@@ -4696,50 +4327,30 @@ test:mysql:
You can see that the hidden jobs are conveniently used as templates, and
`tags: [dev]` has been overwritten by `tags: [postgres]`.
-#### YAML anchors for `before_script` and `after_script`
+#### YAML anchors for scripts
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23005) in GitLab 12.5.
-You can use [YAML anchors](#anchors) with `before_script` and `after_script`,
-which makes it possible to include a predefined list of commands in multiple
-jobs.
-
-Example:
+You can use [YAML anchors](#anchors) with [script](#script), [`before_script`](#before_script),
+and [`after_script`](#after_script) to use predefined commands in multiple jobs:
```yaml
-.something_before: &something_before
- - echo 'something before'
-
-.something_after: &something_after
- - echo 'something after'
- - echo 'another thing after'
-
-job_name:
- before_script:
- - *something_before
- script:
- - echo 'this is the script'
- after_script:
- - *something_after
-```
-
-#### YAML anchors for `script`
+.some-script: &some-script
+ - echo "Execute this in `before_script` sections"
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23005) in GitLab 12.5.
+.some-script-before: &some-script-before
+ - echo "Execute this in `script` sections"
-You can use [YAML anchors](#anchors) with scripts, which makes it possible to
-include a predefined list of commands in multiple jobs.
-
-For example:
-
-```yaml
-.something: &something
- - echo 'something'
+.some-script-after: &some-script-after
+ - echo "Execute this in `after_script` sections"
job_name:
+ before_script:
+ - *some-script-before
script:
- - *something
- - echo 'this is the script'
+ - *some-script
+ before_script:
+ - *some-script-after
```
#### YAML anchors for variables
@@ -4809,19 +4420,19 @@ This limitation does not affect any of the updated merge request pipelines.
All updated merge requests have a pipeline created when using
[pipelines for merge requests](../merge_request_pipelines/index.md).
-## Deprecated parameters
+## Deprecated keywords
-The following parameters are deprecated.
+The following keywords are deprecated.
### Globally-defined `types`
-CAUTION: **Deprecated:**
+DANGER: **Deprecated:**
`types` is deprecated, and could be removed in a future release.
Use [`stages`](#stages) instead.
### Job-defined `type`
-CAUTION: **Deprecated:**
+DANGER: **Deprecated:**
`type` is deprecated, and could be removed in one of the future releases.
Use [`stage`](#stage) instead.
diff --git a/doc/ci/yaml/script.md b/doc/ci/yaml/script.md
new file mode 100644
index 00000000000..87885c8e548
--- /dev/null
+++ b/doc/ci/yaml/script.md
@@ -0,0 +1,147 @@
+---
+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
+---
+
+# GitLab CI/CD script syntax
+
+You can use special syntax in [`script`](README.md#script) sections to:
+
+- [Split long commands](#split-long-commands) into multiline commands.
+- [Use color codes](#add-color-codes-to-script-output) to make job logs easier to review.
+- [Create custom collapsible sections](../jobs/index.md#custom-collapsible-sections)
+ to simplify job log output.
+
+## Split long commands
+
+You can split long commands into multiline commands to improve readability with
+`|` (literal) and `>` (folded) [YAML multiline block scalar indicators](https://yaml-multiline.info/).
+
+CAUTION: **Warning:**
+If multiple commands are combined into one command string, only the last command's
+failure or success is reported.
+[Failures from earlier commands are ignored due to a bug](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394).
+To work around this, run each command as a separate `script:` item, or add an `exit 1`
+command to each command string.
+
+You can use the `|` (literal) YAML multiline block scalar indicator to write
+commands over multiple lines in the `script` section of a job description.
+Each line is treated as a separate command.
+Only the first command is repeated in the job log, but additional
+commands are still executed:
+
+```yaml
+job:
+ script:
+ - |
+ echo "First command line."
+ echo "Second command line."
+ echo "Third command line."
+```
+
+The example above renders in the job log as:
+
+```shell
+$ echo First command line # collapsed multiline command
+First command line
+Second command line.
+Third command line.
+```
+
+The `>` (folded) YAML multiline block scalar indicator treats empty lines between
+sections as the start of a new command:
+
+```yaml
+job:
+ script:
+ - >
+ echo "First command line
+ is split over two lines."
+
+ echo "Second command line."
+```
+
+This behaves similarly to multiline commands without the `>` or `|` block
+scalar indicators:
+
+```yaml
+job:
+ script:
+ - echo "First command line
+ is split over two lines."
+
+ echo "Second command line."
+```
+
+Both examples above render in the job log as:
+
+```shell
+$ echo First command line is split over two lines. # collapsed multiline command
+First command line is split over two lines.
+Second command line.
+```
+
+When you omit the `>` or `|` block scalar indicators, GitLab concatenates non-empty
+lines to form the command. Make sure the lines can run when concatenated.
+
+[Shell here documents](https://en.wikipedia.org/wiki/Here_document) work with the
+`|` and `>` operators as well. The example below transliterates lower case letters
+to upper case:
+
+```yaml
+job:
+ script:
+ - |
+ tr a-z A-Z << END_TEXT
+ one two three
+ four five six
+ END_TEXT
+```
+
+Results in:
+
+```shell
+$ tr a-z A-Z << END_TEXT # collapsed multiline command
+ ONE TWO THREE
+ FOUR FIVE SIX
+```
+
+## Add color codes to script output
+
+Script output can be colored using [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors),
+or by running commands or programs that output ANSI escape codes.
+
+For example, using [Bash with color codes](https://misc.flogisoft.com/bash/tip_colors_and_formatting):
+
+```yaml
+job:
+ script:
+ - echo -e "\e[31mThis text is red,\e[0m but this text isn't\e[31m however this text is red again."
+```
+
+You can define the color codes in Shell variables, or even [custom environment variables](../variables/README.md#custom-environment-variables),
+which makes the commands easier to read and reusable.
+
+For example, using the same example as above and variables defined in a `before_script`:
+
+```yaml
+job:
+ before_script:
+ - TXT_RED="\e[31m" && TXT_CLEAR="\e[0m"
+ script:
+ - echo -e "${TXT_RED}This text is red,${TXT_CLEAR} but this part isn't${TXT_RED} however this part is again."
+ - echo "This text is not colored"
+```
+
+Or with [PowerShell color codes](https://superuser.com/a/1259916):
+
+```yaml
+job:
+ before_script:
+ - $esc="$([char]27)"; $TXT_RED="$esc[31m"; $TXT_CLEAR="$esc[0m"
+ script:
+ - Write-Host $TXT_RED"This text is red,"$TXT_CLEAR" but this text isn't"$TXT_RED" however this text is red again."
+ - Write-Host "This text is not colored"
+```
diff --git a/doc/ci/yaml/visualization.md b/doc/ci/yaml/visualization.md
index ac5f5c8fd14..391ff9f852a 100644
--- a/doc/ci/yaml/visualization.md
+++ b/doc/ci/yaml/visualization.md
@@ -1,3 +1,9 @@
+---
+stage: Verify
+group: Pipeline Authoring
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Visualize your CI/CD configuration
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241722) in GitLab 13.5.
diff --git a/doc/development/README.md b/doc/development/README.md
index 7b8a5cd5f75..75ea6ae5f3b 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -1,6 +1,10 @@
---
comments: false
-description: 'Learn how to contribute to GitLab.'
+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"
+description: "Development Guidelines: learn how to contribute to GitLab."
---
# Contributor and Development Docs
@@ -60,6 +64,19 @@ Complementary reads:
- [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)
+### Development guidelines review
+
+When you submit a change to GitLab's development guidelines, request a review
+from:
+
+- A member of your team or group, to check for technical accuracy.
+- For **significant** changes or proposals, request review from:
+ - Engineering managers (FE, BE, DB, Security, UX, and others), according to the subject or process you're proposing.
+ - The VP of Development (DRI) ([@clefelhocz1](https://gitlab.com/clefelhocz1)), for
+ final approval of the new or changed guidelines.
+- The [Technical Writer assigned to dev guidelines](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines),
+ to review the content for consistency and adherence to documentation guidelines.
+
## UX and Frontend guides
- [GitLab Design System](https://design.gitlab.com/) for building GitLab with existing CSS styles and elements
@@ -93,7 +110,6 @@ Complementary reads:
- [Working with Merge Request diffs](diffs.md)
- [Kubernetes integration guidelines](kubernetes.md)
- [Permissions](permissions.md)
-- [Prometheus](prometheus.md)
- [Guidelines for reusing abstractions](reusing_abstractions.md)
- [DeclarativePolicy framework](policies.md)
- [How Git object deduplication works in GitLab](git_object_deduplication.md)
@@ -117,17 +133,21 @@ Complementary reads:
- [Approval Rules](approval_rules.md)
- [Feature categorization](feature_categorization/index.md)
- [Wikis development guide](wikis.md)
+- [Newlines style guide](newlines_styleguide.md)
+- [Image scaling guide](image_scaling.md)
## Performance guides
- [Instrumentation](instrumentation.md) for Ruby code running in production
- environments
+ environments.
- [Performance guidelines](performance.md) for writing code, benchmarks, and
- certain patterns to avoid
+ certain patterns to avoid.
- [Merge request performance guidelines](merge_request_performance_guidelines.md)
for ensuring merge requests do not negatively impact GitLab performance
- [Profiling](profiling.md) a URL, measuring performance using Sherlock, or
- tracking down N+1 queries using Bullet
+ tracking down N+1 queries using Bullet.
+- [Cached queries guidelines](cached_queries.md), for tracking down N+1 queries masked by query caching, memory profiling and why should
+ we avoid cached queries.
## Database guides
@@ -156,7 +176,7 @@ See [database guidelines](database/index.md).
## Documentation guides
- [Writing documentation](documentation/index.md)
-- [Documentation style guide](documentation/styleguide.md)
+- [Documentation style guide](documentation/styleguide/index.md)
- [Markdown](../user/markdown.md)
## Internationalization (i18n) guides
@@ -167,7 +187,7 @@ See [database guidelines](database/index.md).
## Product Analytics guides
-- [Product Analytics guide](product_analytics/index.md)
+- [Product Analytics guide](https://about.gitlab.com/handbook/product/product-analytics-guide/)
- [Usage Ping guide](product_analytics/usage_ping.md)
- [Snowplow guide](product_analytics/snowplow.md)
@@ -198,9 +218,9 @@ See [database guidelines](database/index.md).
## Other Development guides
- [Defining relations between files using projections](projections.md)
-- [Reference processing](./reference_processing.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)
+- [Features inside `.gitlab/`](features_inside_dot_gitlab.md)
## Other GitLab Development Kit (GDK) guides
diff --git a/doc/development/adding_service_component.md b/doc/development/adding_service_component.md
index bb5af286c1d..74309a5c616 100644
--- a/doc/development/adding_service_component.md
+++ b/doc/development/adding_service_component.md
@@ -1,10 +1,16 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# 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).
+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)
@@ -53,10 +59,8 @@ TIP: **Tip:**
## 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.
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 3d4c033e676..0e81a332d6c 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GraphQL API style guide
This document outlines the style guide for GitLab's [GraphQL API](../api/graphql/index.md).
@@ -126,8 +132,23 @@ Non-nullable fields should only be used when a field is required, very unlikely
to become optional in the future, and very easy to calculate. An example would
be `id` fields.
+A non-nullable GraphQL schema field is an object type followed by the exclamation point (bang) `!`. Here's an example from the `gitlab_schema.graphql` file:
+
+```graphql
+ id: ProjectID!
+```
+
+Here's an example of a non-nullable GraphQL array:
+
+```graphql
+
+ errors: [String!]!
+```
+
Further reading:
+- [GraphQL Best Practices Guide](https://graphql.org/learn/best-practices/#nullability).
+- GraphQL documentation on [Object types and fields](https://graphql.org/learn/schema/#object-types-and-fields).
- [GraphQL Best Practices Guide](https://graphql.org/learn/best-practices/#nullability)
- [Using nullability in GraphQL](https://www.apollographql.com/blog/using-nullability-in-graphql-2254f84c4ed7)
@@ -376,7 +397,7 @@ field :foo, GraphQL::STRING_TYPE,
'if `my_feature_flag` feature flag is disabled'
def foo
- object.foo unless Feature.enabled?(:my_feature_flag, object)
+ object.foo if Feature.enabled?(:my_feature_flag, object)
end
```
@@ -683,7 +704,7 @@ end
```
Fields can also be authorized against multiple abilities, in which case
-all of ability checks must pass. **Note:** This requires explicitly
+all of ability checks must pass. This requires explicitly
passing a block to `field`:
```ruby
@@ -696,7 +717,6 @@ module Types
end
```
-NOTE: **Note:**
If the field's type already [has a particular
authorization](#type-authorization) then there is no need to add that
same authorization to the field.
@@ -736,7 +756,142 @@ To find objects to display in a field, we can add resolvers to
Arguments can be defined within the resolver in the same way as in a mutation.
See the [Mutation arguments](#object-identifier-arguments) section.
-To limit the amount of queries performed, we can use `BatchLoader`.
+To limit the amount of queries performed, we can use [BatchLoader](graphql_guide/batchloader.md).
+
+### Writing resolvers
+
+Our code should aim to be thin declarative wrappers around finders and services. You can
+repeat lists of arguments, or extract them to concerns. Composition is preferred over
+inheritance in most cases. Treat resolvers like controllers: resolvers should be a DSL
+that compose other application abstractions.
+
+For example:
+
+```ruby
+class PostResolver < BaseResolver
+ type Post.connection_type, null: true
+ authorize :read_blog
+ description 'Blog posts, optionally filtered by name'
+
+ argument :name, [::GraphQL::STRING_TYPE], required: false, as: :slug
+
+ alias_method :blog, :object
+
+ def resolve(**args)
+ PostFinder.new(blog, current_user, args).execute
+ end
+end
+```
+
+You should never re-use resolvers directly. Resolvers have a complex life-cycle, with
+authorization, readiness and resolution orchestrated by the framework, and at
+each stage lazy values can be returned to take advantage of batching
+opportunities. Never instantiate a resolver or a mutation in application code.
+
+Instead, the units of code reuse are much the same as in the rest of the
+application:
+
+- Finders in queries to look up data.
+- Services in mutations to apply operations.
+- Loaders (batch-aware finders) specific to queries.
+
+Note that there is never any reason to use batching in a mutation. Mutations are
+executed in series, so there are no batching opportunities. All values are
+evaluated eagerly as soon as they are requested, so batching is unnecessary
+overhead. If you are writing:
+
+- A `Mutation`, feel free to lookup objects directly.
+- A `Resolver` or methods on a `BaseObject`, then you want to allow for batching.
+
+### Deriving resolvers (`BaseResolver.single` and `BaseResolver.last`)
+
+For some simple use cases, we can derive resolvers from others.
+The main use case for this is one resolver to find all items, and another to
+find one specific one. For this, we supply convenience methods:
+
+- `BaseResolver.single`, which constructs a new resolver that selects the first item.
+- `BaseResolver.last`, with constructs a resolver that selects the last item.
+
+The correct singular type is inferred from the collection type, so we don't have
+to define the `type` here.
+
+Before you make use of these methods, consider if it would be simpler to either:
+
+- Write another resolver that defines its own arguments.
+- Write a concern that abstracts out the query.
+
+Using `BaseResolver.single` too freely is an anti-pattern. It can lead to
+non-sensical fields, such as a `Project.mergeRequest` field that just returns
+the first MR if no arguments are given. Whenever we derive a single resolver
+from a collection resolver, it must have more restrictive arguments.
+
+To make this possible, use the `when_single` block to customize the single
+resolver. Every `when_single` block must:
+
+- Define (or re-define) at least one argument.
+- Make optional filters required.
+
+For example, we can do this by redefining an existing optional argument,
+changing its type and making it required:
+
+```ruby
+class JobsResolver < BaseResolver
+ type JobType.connection_type, null: true
+ authorize :read_pipeline
+
+ argument :name, [::GraphQL::STRING_TYPE], required: false
+
+ when_single do
+ argument :name, ::GraphQL::STRING_TYPE, required: true
+ end
+
+ def resolve(**args)
+ JobsFinder.new(pipeline, current_user, args.compact).execute
+ end
+```
+
+Here we have a simple resolver for getting pipeline jobs. The `name` argument is
+optional when getting a list, but required when getting a single job.
+
+If there are multiple arguments, and neither can be made required, we can use
+the block to add a ready condition:
+
+```ruby
+class JobsResolver < BaseResolver
+ alias_method :pipeline, :object
+
+ type JobType.connection_type, null: true
+ authorize :read_pipeline
+
+ argument :name, [::GraphQL::STRING_TYPE], required: false
+ argument :id, [::Types::GlobalIDType[::Job]],
+ required: false,
+ prepare: ->(ids, ctx) { ids.map(&:model_id) }
+
+ when_single do
+ argument :name, ::GraphQL::STRING_TYPE, required: false
+ argument :id, ::Types::GlobalIDType[::Job],
+ required: false
+ prepare: ->(id, ctx) { id.model_id }
+
+ def ready?(**args)
+ raise ::Gitlab::Graphql::Errors::ArgumentError, 'Only one argument may be provided' unless args.size == 1
+ end
+ end
+
+ def resolve(**args)
+ JobsFinder.new(pipeline, current_user, args.compact).execute
+ end
+```
+
+Then we can use these resolver on fields:
+
+```ruby
+# In PipelineType
+
+field :jobs, resolver: JobsResolver, description: 'All jobs'
+field :job, resolver: JobsResolver.single, description: 'A single job'
+```
### Correct use of `Resolver#ready?`
@@ -835,7 +990,29 @@ To avoid duplicated argument definitions, you can place these arguments in a reu
class, if the arguments are nested). Alternatively, you can consider to add a
[helper resolver method](https://gitlab.com/gitlab-org/gitlab/-/issues/258969).
-## Pass a parent object into a child Presenter
+### Metadata
+
+When using resolvers, they can and should serve as the SSoT for field metadata.
+All field options (apart from the field name) can be declared on the resolver.
+These include:
+
+- `type` (this is particularly important, and will soon be mandatory)
+- `extras`
+- `description`
+
+Example:
+
+```ruby
+module Resolvers
+ MyResolver < BaseResolver
+ type Types::MyType, null: true
+ extras [:lookahead]
+ description 'Retrieve a single MyType'
+ end
+end
+```
+
+### 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`.
@@ -850,7 +1027,7 @@ To find the parent object in your `Presenter` class:
end
```
-1. Declare that your fields require the `parent` field context. For example:
+1. Declare that your resolver or fields require the `parent` field context. For example:
```ruby
# in ChildType
@@ -858,6 +1035,14 @@ To find the parent object in your `Presenter` class:
method: :my_computing_method,
extras: [:parent], # Necessary
description: 'My field description'
+
+ field :resolver_field, resolver: SomeTypeResolver
+
+ # In SomeTypeResolver
+
+ extras [:parent]
+ type SomeType, null: true
+ description 'My field description'
```
1. Declare your field's method in your Presenter class and have it accept the `parent` keyword argument.
@@ -869,6 +1054,12 @@ This argument contains the parent **GraphQL context**, so you have to access the
def my_computing_method(parent:)
# do something with `parent[:parent_object]` here
end
+
+ # In SomeTypeResolver
+
+ def resolve(parent:)
+ # ...
+ 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)
@@ -1273,6 +1464,11 @@ 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.
+#### Deprecating EE mutations
+
+EE mutations should follow the same process. For an example of the merge request
+process, read [merge request !42588](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42588).
+
## Pagination implementation
To learn more, visit [GraphQL pagination](graphql_guide/pagination.md).
@@ -1381,6 +1577,62 @@ it 'returns a successful response' do
end
```
+### Testing tips and tricks
+
+- Avoid false positives:
+
+ Authenticating a user with the `current_user:` argument for `post_graphql`
+ generates more queries on the first request than on subsequent requests on that
+ same user. If you are testing for N+1 queries using
+ [QueryRecorder](query_recorder.md), use a **different** user for each request.
+
+ The below example shows how a test for avoiding N+1 queries should look:
+
+ ```ruby
+ RSpec.describe 'Query.project(fullPath).pipelines' do
+ include GraphqlHelpers
+
+ let(:project) { create(:project) }
+
+ let(:query) do
+ %(
+ {
+ project(fullPath: "#{project.full_path}") {
+ pipelines {
+ nodes {
+ id
+ }
+ }
+ }
+ }
+ )
+ end
+
+ it 'avoids N+1 queries' do
+ first_user = create(:user)
+ second_user = create(:user)
+ create(:ci_pipeline, project: project)
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(query, current_user: first_user)
+ end
+
+ create(:ci_pipeline, project: project)
+
+ expect do
+ post_graphql(query, current_user: second_user) # use a different user to avoid a false positive from authentication queries
+ end.not_to exceed_query_limit(control_count)
+ end
+ end
+ ```
+
+- Mimic the folder structure of `app/graphql/types`:
+
+ For example, tests for fields on `Types::Ci::PipelineType`
+ in `app/graphql/types/ci/pipeline_type.rb` should live in
+ `spec/requests/api/graphql/ci/pipeline_spec.rb` regardless of the query being
+ used to fetch the pipeline data.
+
## Notes about Query flow and GraphQL infrastructure
GitLab's GraphQL infrastructure can be found in `lib/gitlab/graphql`.
@@ -1446,3 +1698,7 @@ For information on generating GraphQL documentation and schema files, see
To help our readers, you should also add a new page to our [GraphQL API](../api/graphql/index.md) documentation.
For guidance, see the [GraphQL API](documentation/graphql_styleguide.md) page.
+
+## Include a changelog entry
+
+All client-facing changes **must** include a [changelog entry](changelog.md).
diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md
index 47c06377d88..d21975a43d2 100644
--- a/doc/development/api_styleguide.md
+++ b/doc/development/api_styleguide.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# API style guide
This style guide recommends best practices for API development.
@@ -201,6 +207,12 @@ guide on how you can add a new custom validator.
checks if the value of the given parameter is either an `Array`, `None`, or `Any`.
It allows only either of these mentioned values to move forward in the request.
+- `EmailOrEmailList`:
+
+ The [`EmailOrEmailList` validator](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators/email_or_email_list.rb)
+ checks if the value of a string or a list of strings contains only valid
+ email addresses. It allows only lists with all valid email addresses to move forward in the request.
+
### Adding a new custom validator
Custom validators are a great way to validate parameters before sending
@@ -228,7 +240,7 @@ it's own file in the [`validators`](https://gitlab.com/gitlab-org/gitlab/-/blob/
## Internal API
-The [internal API](./internal_api.md) is documented for internal use. Please keep it up to date so we know what endpoints
+The [internal API](internal_api.md) is documented for internal use. Please keep it up to date so we know what endpoints
different components are making use of.
## Avoiding N+1 problems
@@ -285,10 +297,15 @@ end
## Testing
-When writing tests for new API endpoints, consider using a schema [fixture](./testing_guide/best_practices.md#fixtures) located in `/spec/fixtures/api/schemas`. You can `expect` a response to match a given schema:
+When writing tests for new API endpoints, consider using a schema [fixture](testing_guide/best_practices.md#fixtures) located in `/spec/fixtures/api/schemas`. You can `expect` a response to match a given schema:
```ruby
expect(response).to match_response_schema('merge_requests')
```
Also see [verifying N+1 performance](#verifying-with-tests) in tests.
+
+## Include a changelog entry
+
+All client-facing changes **must** include a [changelog entry](changelog.md).
+This does not include internal APIs.
diff --git a/doc/development/application_limits.md b/doc/development/application_limits.md
index f96ed2e7f57..41fcf5301ad 100644
--- a/doc/development/application_limits.md
+++ b/doc/development/application_limits.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Application limits development
This document provides a development guide for contributors to add application
@@ -27,7 +33,6 @@ It's recommended to create two separate migration script files.
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.
@@ -58,7 +63,6 @@ It's recommended to create two separate migration script files.
end
```
- NOTE: **Note:**
Some plans exist only on GitLab.com. This will be a no-op for plans
that do not exist.
@@ -97,7 +101,6 @@ can be used to validate that a model does not exceed the limits. It ensures
that the count of the records for the current model does not exceed the defined
limit.
-NOTE: **Note:**
You must specify the limit scope of the object being validated
and the limit name if it's different from the pluralized model name.
@@ -146,5 +149,4 @@ GitLab.com:
- `silver` - Namespaces and projects with a Silver subscription
- `gold` - Namespaces and projects with a Gold subscription
-NOTE: **Note:**
-The test environment doesn't have any plans.
+The `test` environment doesn't have any plans.
diff --git a/doc/development/application_secrets.md b/doc/development/application_secrets.md
index 24755586cf8..abc5ff7b985 100644
--- a/doc/development/application_secrets.md
+++ b/doc/development/application_secrets.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Application secrets
This page is a development guide for application secrets.
diff --git a/doc/development/approval_rules.md b/doc/development/approval_rules.md
index f295c20a36f..d190f2b7c63 100644
--- a/doc/development/approval_rules.md
+++ b/doc/development/approval_rules.md
@@ -1,3 +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
+---
+
# Approval Rules **(STARTER)**
This document explains the backend design and flow of all related functionality
@@ -14,7 +20,7 @@ feature to work.
NOTE: **Note:**
This is a living document and should be updated accordingly when parts
-of the codebase touched in this document changed/removed or when new components
+of the codebase touched in this document are changed or removed, or when new components
are added.
## Data Model
@@ -141,7 +147,7 @@ Whenever an approval is given/revoked, a record is created/deleted.
## Controllers and Services
-The following controllers and services below are being utilized for the approval
+The following controllers and services below are being used for the approval
rules feature to work.
### `API::ProjectApprovalSettings`
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index 513af491576..a1097ad4ed6 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab architecture overview
## Software delivery
@@ -252,6 +258,7 @@ Table description links:
| [NGINX](#nginx) | Routes requests to appropriate components, terminates SSL | ✅ | ✅ | ⚙ | ✅ | ⤓ | ⌠| CE & EE |
| [Node Exporter](#node-exporter) | Prometheus endpoint with system metrics | ✅ | N/A | N/A | ✅ | ⌠| ⌠| CE & EE |
| [Outbound email (SMTP)](#outbound-email) | Send email messages to users | ⤓ | ⚙ | ⤓ | ✅ | ⤓ | ⤓ | CE & EE |
+| [Patroni](#patroni) | Manage PostgreSQL HA cluster leader selection and replication | ⚙ | ⌠| ⌠| ✅ | ⌠| ⌠| EE Only |
| [PgBouncer Exporter](#pgbouncer-exporter) | Prometheus endpoint with PgBouncer metrics | ⚙ | ⌠| ⌠| ✅ | ⌠| ⌠| CE & EE |
| [PgBouncer](#pgbouncer) | Database connection pooling, failover | ⚙ | ⌠| ⌠| ✅ | ⌠| ⌠| EE Only |
| [PostgreSQL Exporter](#postgresql-exporter) | Prometheus endpoint with PostgreSQL metrics | ✅ | ✅ | ✅ | ✅ | ⌠| ⌠| CE & EE |
@@ -539,6 +546,15 @@ NGINX has an Ingress port for all HTTP requests and routes them to the appropria
[Node Exporter](https://github.com/prometheus/node_exporter) is a Prometheus tool that gives us metrics on the underlying machine (think CPU/Disk/Load). It's just a packaged version of the common open source offering from the Prometheus project.
+#### Patroni
+
+- [Project Page](https://github.com/zalando/patroni)
+- Configuration:
+ - [Omnibus](../administration/postgresql/replication_and_failover.md#patroni)
+- Layer: Core Service (Data)
+- Process: `patroni`
+- GitLab.com: [Database Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#database-architecture)
+
#### PgBouncer
- [Project page](https://github.com/pgbouncer/pgbouncer/blob/master/README.md)
@@ -681,7 +697,6 @@ Sidekiq is a Ruby background job processor that pulls jobs from the Redis queue
#### Puma
-NOTE: **Note:**
Starting with GitLab 13.0, Puma is the default web server and Unicorn has been
disabled by default.
@@ -699,7 +714,6 @@ disabled by default.
#### Unicorn
-NOTE: **Note:**
Starting with GitLab 13.0, Puma is the default web server and Unicorn has been
disabled by default.
@@ -931,7 +945,7 @@ processes: `puma master` (1 process), `puma cluster worker`
### Repository access
-Repositories get accessed via HTTP or SSH. HTTP cloning/push/pull utilizes the GitLab API and SSH cloning is handled by GitLab Shell (previously explained).
+Repositories get accessed via HTTP or SSH. HTTP cloning/push/pull uses the GitLab API and SSH cloning is handled by GitLab Shell (previously explained).
## Troubleshooting
@@ -1015,9 +1029,9 @@ PostgreSQL:
GitLab has configuration files located in `/home/git/gitlab/config/*`. Commonly referenced
configuration files include:
-- `gitlab.yml` - GitLab configuration
-- `puma.rb` - Puma web server settings
-- `database.yml` - Database connection settings
+- `gitlab.yml`: GitLab configuration
+- `puma.rb`: Puma web server settings
+- `database.yml`: Database connection settings
GitLab Shell has a configuration file at `/home/git/gitlab-shell/config.yml`.
@@ -1033,9 +1047,12 @@ bundle exec rake gitlab:env:info RAILS_ENV=production
bundle exec rake gitlab:check RAILS_ENV=production
```
-Note: It is recommended to log into the `git` user using `sudo -i -u git` or `sudo su - git`. While
-the `sudo` commands provided by GitLab work in Ubuntu they do not always work in RHEL.
+It's recommended to sign in to the `git` user using either `sudo -i -u git` or
+`sudo su - git`. Although the `sudo` commands provided by GitLab work in Ubuntu,
+they don't always work in RHEL.
## GitLab.com
-We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/) but this is probably over the top unless you have millions of users.
+The [GitLab.com architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/)
+is detailed for your reference, but this architecture is only useful if you have
+millions of users.
diff --git a/doc/development/background_migrations.md b/doc/development/background_migrations.md
index e5cc2ae4d1d..86a2aed5ea1 100644
--- a/doc/development/background_migrations.md
+++ b/doc/development/background_migrations.md
@@ -343,10 +343,32 @@ for more details.
1. Make sure that tests you write are not false positives.
1. Make sure that if the data being migrated is critical and cannot be lost, the
clean-up migration also checks the final state of the data before completing.
-1. Make sure to know how much time it'll take to run all scheduled migrations.
1. When migrating many columns, make sure it won't generate too many
dead tuples in the process (you may need to directly query the number of dead tuples
and adjust the scheduling according to this piece of data).
1. Make sure to discuss the numbers with a database specialist, the migration may add
more pressure on DB than you expect (measure on staging,
or ask someone to measure on production).
+1. Make sure to know how much time it'll take to run all scheduled migrations.
+1. Provide an estimation section in the description, explaining timings from the
+ linked query plans and batches as described in the migration.
+
+ For example, assuming a migration that deletes data, include information similar to
+ the following section:
+
+ ```ruby
+ Background Migration Details:
+
+ 47600 items to delete
+ batch size = 1000
+ 47600 / 1000 = 48 loops
+
+ Estimated times per batch:
+ - 900ms for select statement with 1000 items
+ - 2100ms for delete statement with 1000 items
+ Total: ~3sec per batch
+
+ 2 mins delay per loop (safe for the given total time per batch)
+
+ 48 * ( 120 + 3) = ~98.4 mins to run all the scheduled jobs
+ ```
diff --git a/doc/development/cached_queries.md b/doc/development/cached_queries.md
new file mode 100644
index 00000000000..812e5f88754
--- /dev/null
+++ b/doc/development/cached_queries.md
@@ -0,0 +1,139 @@
+# Cached queries guidelines
+
+Rails provides an [SQL query cache](https://guides.rubyonrails.org/caching_with_rails.html#sql-caching),
+used to cache the results of database queries for the duration of the request.
+
+If Rails encounters the same query again for that request,
+it will use the cached result set as opposed to running the query against the database again.
+
+The query results are only cached for the duration of that single request, it does not persist across multiple requests.
+
+## Why cached queries are considered bad
+
+The cached queries help with reducing DB load, but they still:
+
+- Consume memory.
+- Require as to re-instantiate each `ActiveRecord` object.
+- Require as to re-instantiate each relation of the object.
+- Make us spend additional CPU-cycles to look into a list of cached queries.
+
+The Cached SQL queries are cheaper, but they are not cheap at all from `memory` perspective.
+They could mask [N+1 query problem](https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations),
+so we should threat them the same way we threat regular N+1 queries.
+
+In case of N+1 queries, masked with cached queries, we are executing the same query N times.
+It will not hit the database N times, it will return the cached results instead.
+This is still expensive since we need to re-initialize objects each time, and this is CPU/Memory expensive.
+Instead, we should use the same in-memory objects, if possible.
+
+When we introduce a new feature, we should avoid N+1 problems,
+minimize the [query count](merge_request_performance_guidelines.md#query-counts), and pay special attention that [cached
+queries](merge_request_performance_guidelines.md#cached-queries) are not masking N+1 problems.
+
+## How to detect
+
+### Detect potential offenders by using Kibana
+
+On GitLab.com, we are logging entries with the number of executed cached queries in the
+`pubsub-redis-inf-gprd*` index with the [`db_cached_count`](https://log.gprd.gitlab.net/goto/77d18d80ad84c5df1bf1da5c2cd35b82).
+We can filter endpoints that have a large number of executed cached queries. For example, if we encounter an endpoint
+that has 100+ `db_cached_count`, this could indicate that there is an N+1 problem masked with cached queries.
+We should probably investigate this endpoint further, to check if we are executing duplicated cached queries.
+
+For more cached queries Kibana visualizations see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/259007).
+
+### Inspect suspicious endpoint using Performance Bar
+
+When building features, you could use the [performance bar](../administration/monitoring/performance/performance_bar.md)
+to list database queries, which will include cached queries as well. The performance bar will show a warning
+when threshold of total executed queries (including cached ones) has exceeded 100 queries.
+
+## What to look for
+
+Using [Kibana](cached_queries.md#detect-potential-offenders-by-using-kibana), you can look for a large number
+of executed cached queries. End-points with large number of `db_cached_count` could indicate that there
+are probably a lot of duplicated cached queries, which often indicates a masked N+1 problem.
+
+When you investigate specific endpoint, you could use
+the [performance bar](cached_queries.md#inspect-suspicious-endpoint-using-performance-bar).
+If you see a lot of similar queries, this often indicates an N+1 query issue (or a similar kind of query batching problem).
+If you see same cached query executed multiple times, this often indicates a masked N+1 query problem.
+
+For example, let's say you wanted to debug `GroupMembers` page.
+
+In the left corner of the performance bar you could see **Database queries** showing the total number of database queries
+and the number of executed cached queries:
+
+![Performance Bar Database Queries](img/performance_bar_members_page.png)
+
+We can see that there are 55 cached queries. By clicking on the number, a modal window with more details is shown.
+Cached queries are marked with the `cached` label, so they are easy to spot. We can see that there are multiple duplicated
+cached queries:
+
+![Performance Bar Cached Queries Modal](img/performance_bar_cached_queries.png)
+
+If we click on `...` for one of them, it will expand the actual stack trace:
+
+```shell
+[
+ "app/models/group.rb:305:in `has_owner?'",
+ "ee/app/views/shared/members/ee/_license_badge.html.haml:1",
+ "app/helpers/application_helper.rb:19:in `render_if_exists'",
+ "app/views/shared/members/_member.html.haml:31",
+ "app/views/groups/group_members/index.html.haml:75",
+ "app/controllers/application_controller.rb:134:in `render'",
+ "ee/lib/gitlab/ip_address_state.rb:10:in `with'",
+ "ee/app/controllers/ee/application_controller.rb:44:in `set_current_ip_address'",
+ "app/controllers/application_controller.rb:493:in `set_current_admin'",
+ "lib/gitlab/session.rb:11:in `with_session'",
+ "app/controllers/application_controller.rb:484:in `set_session_storage'",
+ "app/controllers/application_controller.rb:478:in `set_locale'",
+ "lib/gitlab/error_tracking.rb:52:in `with_context'",
+ "app/controllers/application_controller.rb:543:in `sentry_context'",
+ "app/controllers/application_controller.rb:471:in `block in set_current_context'",
+ "lib/gitlab/application_context.rb:54:in `block in use'",
+ "lib/gitlab/application_context.rb:54:in `use'",
+ "lib/gitlab/application_context.rb:21:in `with_context'",
+ "app/controllers/application_controller.rb:463:in `set_current_context'",
+ "lib/gitlab/jira/middleware.rb:19:in `call'"
+]
+```
+
+The stack trace, shows us that we obviously have an N+1 problem, since we are repeatably executing for each group member:
+
+```ruby
+group.has_owner?(current_user)
+```
+
+This is easily solvable by extracting this check, above the loop.
+
+After [the fix](https://gitlab.com/gitlab-org/gitlab/-/issues/231468), we now have:
+
+![Performance Bar Fixed Cached Queries](img/performance_bar_fixed_cached_queries.png)
+
+## How to measure the impact of the change
+
+We can use the [memory profiler](performance.md#using-memory-profiler) to profile our code.
+For the previous example, we could wrap the profiler around the `Groups::GroupMembersController#index` action.
+
+We had:
+
+- Total allocated: 7133601 bytes (84858 objects)
+- Total retained: 757595 bytes (6070 objects)
+- `db_count`: 144
+- `db_cached_count`: 55
+- `db_duration`: 303ms
+
+After the fix, we can see that we have reduced the allocated memory as well as the number of cached queries and improved execution time:
+
+- Total allocated: 5313899 bytes (65290 objects), 1810KB (25%) less
+- Total retained: 685593 bytes (5278 objects), 72KB (9%) less
+- `db_count`: 95 (34% less)
+- `db_cached_count`: 6 (89% less)
+- `db_duration`: 162ms (87% faster)
+
+## See also
+
+- [Metrics that would help us detect the potential N+1 Cached SQL calls](https://gitlab.com/gitlab-org/gitlab/-/issues/259007)
+- [Merge Request performance guidelines for cached queries](merge_request_performance_guidelines.md#cached-queries)
+- [Improvements for biggest offenders](https://gitlab.com/groups/gitlab-org/-/epics/4508)
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index 922c4814d91..b8e879c1826 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Changelog entries
This guide contains instructions for when and how to generate a changelog entry
@@ -38,9 +44,10 @@ the `author` field. GitLab team members **should not**.
- [Security fixes](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md)
**must** have a changelog entry, without `merge_request` value
and with `type` set to `security`.
-- Any user-facing change **should** have a changelog entry. This includes both visual changes (regardless of how minor), and changes to the rendered DOM which impact how a screen reader may announce the content.
+- Any user-facing change **must** have a changelog entry. This includes both visual changes (regardless of how minor), and changes to the rendered DOM which impact how a screen reader may announce the content.
+- Any client-facing change to our REST and GraphQL APIs **must** have a changelog entry.
- Performance improvements **should** have a changelog entry.
-- Changes that need to be documented in the Product Analytics [Event Dictionary](product_analytics/event_dictionary.md)
+- Changes that need to be documented in the Product Analytics [Event Dictionary](https://about.gitlab.com/handbook/product/product-analytics-guide#event-dictionary)
also require a changelog entry.
- _Any_ contribution from a community member, no matter how small, **may** have
a changelog entry regardless of these guidelines if the contributor wants one.
@@ -48,7 +55,8 @@ the `author` field. GitLab team members **should not**.
- Any docs-only changes **should not** have a changelog entry.
- Any change behind a disabled feature flag **should not** have a changelog entry.
- Any change behind an enabled feature flag **should** have a changelog entry.
-- Any change that adds new usage data metrics and changes that needs to be documented in Product Analytics [Event Dictionary](telemetry/event_dictionary.md) **should** have a changelog entry.
+- Any change that adds new usage data metrics and changes that needs to be documented in Product Analytics [Event Dictionary](https://about.gitlab.com/handbook/product/product-analytics-guide#event-dictionary) **should** have a changelog entry.
+- A change that adds snowplow events **should** have a changelog entry -
- A change that [removes a feature flag](feature_flags/development.md) **should** have a changelog entry -
only if the feature flag did not default to true already.
- A fix for a regression introduced and then fixed in the same release (i.e.,
@@ -117,7 +125,6 @@ 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).
diff --git a/doc/development/chaos_endpoints.md b/doc/development/chaos_endpoints.md
index 26ff3d2def7..63218af857d 100644
--- a/doc/development/chaos_endpoints.md
+++ b/doc/development/chaos_endpoints.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Generating chaos in a test GitLab instance
As [Werner Vogels](https://twitter.com/Werner), the CTO at Amazon Web Services, famously put it, **Everything fails, all the time**.
@@ -18,7 +24,7 @@ Currently, there are four endpoints for simulating the following conditions:
For obvious reasons, these endpoints are not enabled by default on `production`.
They are enabled by default on **development** environments.
-DANGER: **Danger:**
+DANGER: **Warning:**
It is required that you secure access to the chaos endpoints using a secret token.
You should not enable them in production unless you absolutely know what you're doing.
@@ -44,8 +50,7 @@ each endpoint can be set to `true`. This will run the chaos process in a Sidekiq
To simulate a memory leak in your application, use the `/-/chaos/leakmem` endpoint.
-NOTE: **Note:**
-The memory is not retained after the request finishes. Once the request has completed, the Ruby garbage collector will attempt to recover the memory.
+The memory is not retained after the request finishes. After the request has completed, the Ruby garbage collector will attempt to recover the memory.
```plaintext
GET /-/chaos/leakmem
@@ -80,7 +85,7 @@ GET /-/chaos/cpu_spin?duration_s=50&async=true
| Attribute | Type | Required | Description |
| ------------ | ------- | -------- | --------------------------------------------------------------------- |
-| `duration_s` | integer | no | Duration, in seconds, that the core will be utilized. Defaults to 30s |
+| `duration_s` | integer | no | Duration, in seconds, that the core will be used. Defaults to 30s |
| `async` | boolean | no | Set to true to consume CPU in a Sidekiq background worker process |
```shell
@@ -105,7 +110,7 @@ GET /-/chaos/db_spin?duration_s=50&async=true
| Attribute | Type | Required | Description |
| ------------ | ------- | -------- | --------------------------------------------------------------------------- |
| `interval_s` | float | no | Interval, in seconds, for every DB request. Defaults to 1s |
-| `duration_s` | integer | no | Duration, in seconds, that the core will be utilized. Defaults to 30s |
+| `duration_s` | integer | no | Duration, in seconds, that the core will be used. Defaults to 30s |
| `async` | boolean | no | Set to true to perform the operation in a Sidekiq background worker process |
```shell
@@ -139,8 +144,8 @@ curl http://localhost:3000/-/chaos/sleep?duration_s=60&token=secret
This endpoint will simulate the unexpected death of a worker process using a `kill` signal.
-NOTE: **Note:**
-Since this endpoint uses the `KILL` signal, the worker is not given a chance to cleanup or shutdown.
+Because this endpoint uses the `KILL` signal, the worker isn't given an
+opportunity to cleanup or shutdown.
```plaintext
GET /-/chaos/kill
diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md
index 7d522a55559..e4c3e622ede 100644
--- a/doc/development/cicd/templates.md
+++ b/doc/development/cicd/templates.md
@@ -174,3 +174,7 @@ is updated in a major version GitLab release.
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.
+
+## Contribute CI/CD Template Merge Requests
+
+After your CI/CD Template MR is created and labeled with `ci::templates`, DangerBot suggests one reviewer and one maintainer that can review your code. When your merge request is ready for review, please `@mention` the reviewer and ask them to review your CI/CD Template changes. See details in the merge request that added [a DangerBot task for CI/CD Template MRs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44688).
diff --git a/doc/development/code_comments.md b/doc/development/code_comments.md
index b0e83b29cb0..d9ab719d18a 100644
--- a/doc/development/code_comments.md
+++ b/doc/development/code_comments.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Code comments
Whenever you add comment to the code that is expected to be addressed at any time
diff --git a/doc/development/code_intelligence/index.md b/doc/development/code_intelligence/index.md
index bd11f0bff79..24abf57e9d6 100644
--- a/doc/development/code_intelligence/index.md
+++ b/doc/development/code_intelligence/index.md
@@ -1,3 +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
+---
+
# Code Intelligence
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/1576) in GitLab 13.1.
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 3ff802d3b23..63a47240435 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Code Review Guidelines
This guide contains advice and best practices for performing code review, and
@@ -91,8 +97,14 @@ with [domain expertise](#domain-experts).
**approved by a [frontend maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_frontend)**.
1. If your merge request includes UX changes (*1*), it must be
**approved by a [UX team member](https://about.gitlab.com/company/team/)**.
-1. If your merge request includes adding a new JavaScript library (*1*), it must be
- **approved by a [frontend lead](https://about.gitlab.com/company/team/)**.
+1. If your merge request includes adding a new JavaScript library (*1*)...
+ - If the library significantly increases the
+ [bundle size](https://gitlab.com/gitlab-org/frontend/playground/webpack-memory-metrics/-/blob/master/doc/report.md), it must
+ be **approved by a [frontend foundations member](https://about.gitlab.com/direction/create/ecosystem/frontend-ux-foundations/)**.
+ - If the license used by the new library hasn't been approved for use in
+ GitLab, the license must be **approved by a [legal department member](https://about.gitlab.com/handbook/legal/)**.
+ More information about license compatiblity can be found in our
+ [GitLab Licensing and Compatibility documentation](licensing.md).
1. If your merge request includes adding a new UI/UX paradigm (*1*), it must be
**approved by a [UX lead](https://about.gitlab.com/company/team/)**.
1. If your merge request includes a new dependency or a filesystem change, it must be
@@ -378,8 +390,7 @@ When ready to merge:
- When you set the MR to "Merge When Pipeline Succeeds", you should take over
subsequent revisions for anything that would be spotted after that.
-NOTE: **Note:**
-Thanks to "Pipeline for Merged Results", authors won't have to rebase their
+Thanks to **Pipeline for Merged Results**, authors won't have to rebase their
branch as frequently anymore (only when there are conflicts) since the Merge
Results Pipeline will already incorporate the latest changes from `master`.
This results in faster review/merge cycles since maintainers don't have to ask
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index 6cbe57bf926..17431195c3d 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -37,7 +37,7 @@ Report suspected security vulnerabilities in private to
`support@gitlab.com`, also see the
[disclosure section on the GitLab.com website](https://about.gitlab.com/security/disclosure/).
-DANGER: **Danger:**
+DANGER: **Warning:**
Do **NOT** create publicly viewable issues for suspected security vulnerabilities.
## Code of conduct
@@ -146,7 +146,7 @@ Keep the following in mind when submitting merge requests:
reviewers.
- If the code quality is found to not meet GitLab’s standards, the merge request reviewer will
provide guidance and refer the author to our:
- - [Documentation](../documentation/styleguide.md) style guide.
+ - [Documentation](../documentation/styleguide/index.md) style guide.
- Code style guides.
- Sometimes style guides will be followed but the code will lack structural integrity, or the
reviewer will have reservations about the code’s overall quality. When there is a reservation,
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index b7c05a369f0..99650c24661 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -90,25 +90,6 @@ explain what falls under each type label.
The GitLab handbook documents [when something is a bug](https://about.gitlab.com/handbook/product/product-processes/#bug-issues) and [when it is a feature request](https://about.gitlab.com/handbook/product/product-processes/#feature-issues).
-### Facet labels
-
-Sometimes it's useful to refine the type of an issue. In those cases, you can
-add facet labels.
-
-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 ~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.
-- ~customer: This relates to an issue that was created by a customer, or that is of interest for a customer.
-- ~"UI text": Issues that add or modify any text within the UI such as user-assistance microcopy, button/menu labels, or error messages.
-
### Stage labels
Stage labels specify which [stage](https://about.gitlab.com/handbook/product/product-categories/#hierarchy) the issue belongs to.
@@ -226,6 +207,13 @@ Examples of feature labels are `~wiki`, `~ldap`, `~api`, `~issues`, `~"merge req
Feature labels are all-lowercase.
+### Facet labels
+
+To track additional information or context about created issues, developers may
+add _facet labels_. Facet labels are also sometimes used for issue prioritization
+or for measurements (such as time to close). An example of a facet label is the
+~customer label, which indicates customer interest.
+
### Department labels
The current department labels are:
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 31f59ad875c..d5ffff7bfc8 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -123,24 +123,37 @@ document from the Kubernetes team also has some great points regarding this.
### Commit messages guidelines
-When writing commit messages, please follow the guidelines below:
+Commit messages should follow the guidelines below, for reasons explained by Chris Beams in [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/):
-- The commit subject must contain at least 3 words.
-- The commit subject must not be longer than 72 characters.
+- The commit subject and body must be separated by a blank line.
- The commit subject must start with a capital letter.
+- The commit subject must not be longer than 72 characters.
- The commit subject must not end with a period.
-- The commit subject and body must be separated by a blank line.
- The commit body must not contain more than 72 characters per line.
- Commits that change 30 or more lines across at least 3 files must
describe these changes in the commit body.
- The commit subject or body must not contain Emojis.
- Use issues and merge requests' full URLs instead of short references,
as they are displayed as plain text outside of GitLab.
-- The merge request must not contain more than 10 commit messages.
+- The merge request should not contain more than 10 commit messages.
+- The commit subject should contain at least 3 words.
+
+**Important notes:**
+
+- If the guidelines are not met, the MR may not pass the [Danger checks](https://gitlab.com/gitlab-org/gitlab/blob/master/danger/commit_messages/Dangerfile).
+- Consider enabling [Squash and merge](../../user/project/merge_requests/squash_and_merge.md#squash-and-merge)
+ if your merge request includes "Applied suggestion to X files" commits, so that Danger can ignore those.
+- The prefixes in the form of `[prefix]` and `prefix:` are allowed (they can be all lowercase, as long
+ as the message itself is capitalized). For instance, `danger: Improve Danger behavior` and
+ `[API] Improve the labels endpoint` are valid commit messages.
+
+#### Why these standards matter
+
+1. Consistent commit messages that follow these guidelines make the history more readable.
+1. Concise standard commit messages helps to identify breaking changes for a deployment or ~"master:broken" quicker when
+ reviewing commits between two points in time.
-If the guidelines are not met, the MR will not pass the
-[Danger checks](https://gitlab.com/gitlab-org/gitlab/blob/master/danger/commit_messages/Dangerfile).
-For more information see [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/).
+#### Commit message template
Example commit message template that can be used on your machine that embodies the above (guide for [how to apply template](https://codeinthehole.com/tips/a-useful-template-for-commit-messages/)):
diff --git a/doc/development/contributing/style_guides.md b/doc/development/contributing/style_guides.md
index 773c1a771cd..fd3fe239110 100644
--- a/doc/development/contributing/style_guides.md
+++ b/doc/development/contributing/style_guides.md
@@ -15,25 +15,49 @@ settings automatically by default. If your editor/IDE does not automatically sup
we suggest investigating to see if a plugin exists. For instance here is the
[plugin for vim](https://github.com/editorconfig/editorconfig-vim).
-## Pre-commit static analysis
+## Pre-push static analysis
-You should install [`overcommit`](https://github.com/sds/overcommit) to automatically check for
-static analysis offenses before committing locally.
+We strongly recommend installing [Lefthook](https://github.com/Arkweid/lefthook) to automatically check
+for static analysis offenses before pushing your changes.
-After installing `overcommit`, run the following in your GitLab source directory:
+To install `lefthook`, run the following in your GitLab source directory:
```shell
-make -C tooling/overcommit
+# 1. Make sure to uninstall Overcommit first
+overcommit --uninstall
+
+# If using rbenv, at this point you may need to do: rbenv rehash
+
+# 2. Install lefthook...
+
+## With Homebrew (macOS)
+brew install Arkweid/lefthook/lefthook
+
+## Or with Go
+go get github.com/Arkweid/lefthook
+
+## Or with Rubygems
+gem install lefthook
+
+# 3. Install the Git hooks
+lefthook install -f
```
-Then before a commit is created, `overcommit` automatically checks for RuboCop (and other checks)
-offenses on every modified file.
+Before you push your changes, Lefthook then automatically run Danger checks, and other checks
+for changed files. This saves you time as you don't have to wait for the same errors to be detected
+by CI/CD.
+
+Lefthook relies on a pre-push hook to prevent commits that violate its ruleset.
+To override this behavior, pass the environment variable `LEFTHOOK=0`. That is,
+`LEFTHOOK=0 git push`.
-This saves you time as you don't have to wait for the same errors to be detected by CI/CD.
+You can also:
-`overcommit` relies on a pre-commit hook to prevent commits that violate its ruleset. To override
-this behavior, pass the `OVERCOMMIT_DISABLE` environment variable. For example,
-`OVERCOMMIT_DISABLE=1 git rebase master` to rebase while disabling the Git hook.
+- Define [local configuration](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#local-config).
+- Skip [checks per tag on the fly](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#skip-some-tags-on-the-fly).
+ For example, `LEFTHOOK_EXCLUDE=frontend git push origin`.
+- Run [hooks manually](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#run-githook-group-directly).
+ For example, `lefthook run pre-push`.
## Ruby, Rails, RSpec
@@ -100,7 +124,7 @@ We're following [Ciro Santilli's Markdown Style Guide](https://cirosantilli.com/
## Documentation
-See the dedicated [Documentation Style Guide](../documentation/styleguide.md).
+See the dedicated [Documentation Style Guide](../documentation/styleguide/index.md).
## Python
diff --git a/doc/development/creating_enums.md b/doc/development/creating_enums.md
index af9bf919b2b..fbf35171ecb 100644
--- a/doc/development/creating_enums.md
+++ b/doc/development/creating_enums.md
@@ -1,3 +1,9 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Creating enums
When creating a new enum, it should use the database type `SMALLINT`.
diff --git a/doc/development/dangerbot.md b/doc/development/dangerbot.md
index 6fda394c10d..4feec5c093a 100644
--- a/doc/development/dangerbot.md
+++ b/doc/development/dangerbot.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Danger bot
The GitLab CI/CD pipeline includes a `danger-review` job that uses [Danger](https://github.com/danger/danger)
diff --git a/doc/development/database/constraint_naming_convention.md b/doc/development/database/constraint_naming_convention.md
new file mode 100644
index 00000000000..63a2d607ac5
--- /dev/null
+++ b/doc/development/database/constraint_naming_convention.md
@@ -0,0 +1,26 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# Constraints naming conventions
+
+The most common option is to let Rails pick the name for database constraints and indexes or let PostgreSQL use the defaults (when applicable). However, when needing to define custom names in Rails or working in Go applications where no ORM is used, it is important to follow strict naming conventions to improve consistency and discoverability.
+
+The table below describes the naming conventions for custom PostgreSQL constraints.
+Please note that the intent is not to retroactively change names in existing databases but rather ensure consistency of future changes.
+
+| Type | Syntax | Notes | Examples |
+|--------------------------|---------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|
+| **Primary Key** | `pk_<table name>` | | `pk_projects` |
+| **Foreign Key** | `fk_<table name>_<column name>[_and_<column name>]*_<foreign table name>` | | `fk_projects_group_id_groups` |
+| **Index** | `index_<table name>_on_<column name>[_and_<column name>]*[_and_<column name in partial clause>]*` | | `index_repositories_on_group_id` |
+| **Unique Constraint** | `unique_<table name>_<column name>[_and_<column name>]*` | | `unique_projects_group_id_and_name` |
+| **Check Constraint** | `check_<table name>_<column name>[_and_<column name>]*[_<suffix>]?` | The optional suffix should denote the type of validation, such as `length` and `enum`. It can also be used to desambiguate multiple `CHECK` constraints on the same column. | `check_projects_name_length`<br />`check_projects_type_enum`<br />`check_projects_admin1_id_and_admin2_id_differ` |
+| **Exclusion Constraint** | `excl_<table name>_<column name>[_and_<column name>]*_[_<suffix>]?` | The optional suffix should denote the type of exclusion being performed. | `excl_reservations_start_at_end_at_no_overlap` |
+
+## Observations
+
+- Prefixes are preferred over suffices because they make it easier to identify the type of a given constraint quickly, as well as group them alphabetically;
+- The `_and_` that joins column names can be omitted to keep the identifiers under the 63 characters' length limit defined by PostgreSQL. Additionally, the notation may be abbreviated to the best of our ability if struggling to keep under this limit.
diff --git a/doc/development/database/index.md b/doc/development/database/index.md
index 4bcefefe7a7..19159c6c0ff 100644
--- a/doc/development/database/index.md
+++ b/doc/development/database/index.md
@@ -57,9 +57,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
- [Query Count Limits](../query_count_limits.md)
- [Creating enums](../creating_enums.md)
- [Client-side connection-pool](client_side_connection_pool.md)
-- [Updating multiple values](./setting_multiple_values.md)
+- [Updating multiple values](setting_multiple_values.md)
+- [Constraints naming conventions](constraint_naming_convention.md)
## Case studies
- [Database case study: Filtering by label](../filtering_by_label.md)
- [Database case study: Namespaces storage statistics](../namespaces_storage_statistics.md)
+
+## Miscellaneous
+
+- [Maintenance operations](maintenance_operations.md)
diff --git a/doc/development/database/maintenance_operations.md b/doc/development/database/maintenance_operations.md
new file mode 100644
index 00000000000..c84ec31471e
--- /dev/null
+++ b/doc/development/database/maintenance_operations.md
@@ -0,0 +1,46 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# Maintenance operations
+
+This page details various database related operations that may relate to development.
+
+## Disabling an index
+
+There are certain situations in which you might want to disable an index before removing it:
+
+- The index is on a large table and rebuilding it in the case of a revert would take a long time.
+- It is uncertain whether or not the index is being used in ways that are not fully visible.
+
+To disable an index before removing it:
+
+1. Open a [production infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/new)
+and use the "Production Change" template.
+1. Inform the database team in the issue `@gl-database` or in Slack `#database`.
+1. Add a step to verify the index is used (this would likely be an `EXPLAIN` command known to use the index).
+1. Add the step to disable the index:
+
+ ```sql
+ UPDATE pg_index SET indisvalid = false WHERE indexrelid = 'index_issues_on_foo'::regclass;
+ ```
+
+1. Add a step to verify the index is invalid (this would likely be the same as used to verify before disabling the index).
+1. Verify the index is invalid on replicas:
+
+ ```sql
+ SELECT indisvalid FROM pg_index WHERE indexrelid = 'index_issues_on_foo'::regclass;
+ ```
+
+1. Add steps for rolling back the invalidation:
+ 1. Rollback the index invalidation
+
+ ```sql
+ UPDATE pg_index SET indisvalid = true WHERE indexrelid = 'index_issues_on_foo'::regclass;
+ ```
+
+ 1. Verify the index is being used again.
+
+See this [example infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/2795) for reference.
diff --git a/doc/development/database/setting_multiple_values.md b/doc/development/database/setting_multiple_values.md
index 5569a0e10b7..c354247a9f8 100644
--- a/doc/development/database/setting_multiple_values.md
+++ b/doc/development/database/setting_multiple_values.md
@@ -1,9 +1,15 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Setting Multiple Values
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32921) in GitLab 13.5.
-Frequently, we will want to update multiple objects with new values for one
-or more columns. The obvious way to do this is using `Relation#update_all`:
+There's often a need to update multiple objects with new values for one
+or more columns. One method of doing this is using `Relation#update_all`:
```ruby
user.issues.open.update_all(due_date: 7.days.from_now) # (1)
@@ -28,11 +34,11 @@ update issues
where id = obj_id
```
-The bad news: There is no way to express this in ActiveRecord or even dropping
-down to ARel - the `UpdateManager` just does not support `update from`, so this
+The bad news: there is no way to express this in ActiveRecord or even dropping
+down to ARel. The `UpdateManager` does not support `update from`, so this
is not expressible.
-The good news: We supply an abstraction to help you generate these kinds of
+The good news: we supply an abstraction to help you generate these kinds of
updates, called `Gitlab::Database::BulkUpdate`. This constructs queries such as the
above, and uses binding parameters to avoid SQL injection.
@@ -44,7 +50,7 @@ To use this, we need:
- a mapping from object/ID to the new values to set for that object
- a way to determine the table for each object
-So for example, we can express the query above as:
+For example, we can express the query above as:
```ruby
issue_a = Issue.find(..)
@@ -87,7 +93,7 @@ objects = Foo.from_union([
])
# At this point, all the objects are instances of Foo, even the ones from the
# Bar table
-mapping = objects.to_h { |obj| [obj, bazzes[obj.id] }
+mapping = objects.to_h { |obj| [obj, bazzes[obj.id]] }
# Issues at most 2 queries
::Gitlab::Database::BulkUpdate.execute(%i[baz], mapping) do |obj|
@@ -100,4 +106,4 @@ end
Note that this is a **very low level** tool, and operates on the raw column
values. Enumerations and state fields must be translated into their underlying
representations, for example, and nested associations are not supported. No
-validations or hooks will be called.
+validations or hooks are called.
diff --git a/doc/development/database_review.md b/doc/development/database_review.md
index 3f5f36b0b6e..d1ec32af464 100644
--- a/doc/development/database_review.md
+++ b/doc/development/database_review.md
@@ -27,7 +27,7 @@ A database review is required for:
database review.
- Changes in usage data metrics that use `count` and `distinct_count`.
These metrics could have complex queries over large tables.
- See the [Product Analytics Guide](product_analytics/usage_ping.md#implementing-usage-ping)
+ See the [Product Analytics Guide](https://about.gitlab.com/handbook/product/product-analytics-guide/)
for implementation details.
A database reviewer is expected to look out for obviously complex
@@ -106,7 +106,8 @@ test its execution using `CREATE INDEX CONCURRENTLY` in the `#database-lab` Slac
- Write the raw SQL in the MR description. Preferably formatted
nicely with [pgFormatter](https://sqlformat.darold.net) or
- [paste.depesz.com](https://paste.depesz.com).
+ [paste.depesz.com](https://paste.depesz.com) and using regular quotes
+ (e.g. `"projects"."id"`) and avoiding smart quotes (e.g. `“projectsâ€.“idâ€`).
- Include the output of `EXPLAIN (ANALYZE, BUFFERS)` of the relevant
queries in the description. If the output is too long, wrap it in
`<details>` blocks, paste it in a GitLab Snippet, or provide the
@@ -201,8 +202,8 @@ estimated to keep migration timing to a minimum.
NOTE: **Note:**
Keep in mind that all runtimes should be measured against GitLab.com.
-| Migration Type | Execution Time Recommended | Notes |
+| Migration Type | Execution Time Recommended | Notes |
|----|----|---|
| Regular migrations on `db/migrate` | `3 minutes` | A valid exception are index creation as this can take a long time. |
-| Post migrations on `db/post_migrate` | `10 minutes` | |
-| Background migrations | --- | Since these are suitable for larger tables, it's not possible to set a precise timing guideline, however, any single query must stay below `1 second` execution time with cold caches. |
+| Post migrations on `db/post_migrate` | `10 minutes` | |
+| Background migrations | --- | Since these are suitable for larger tables, it's not possible to set a precise timing guideline, however, any single query must stay below `1 second` execution time with cold caches. |
diff --git a/doc/development/deleting_migrations.md b/doc/development/deleting_migrations.md
index b8f23019ac2..df36715fa6a 100644
--- a/doc/development/deleting_migrations.md
+++ b/doc/development/deleting_migrations.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Delete existing migrations
When removing existing migrations from the GitLab project, you have to take into account
diff --git a/doc/development/deprecation_guidelines/index.md b/doc/development/deprecation_guidelines/index.md
index 1ee22644bbc..5cc408bb57b 100644
--- a/doc/development/deprecation_guidelines/index.md
+++ b/doc/development/deprecation_guidelines/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Deprecation guidelines
This page includes information about how and when to remove or make breaking
diff --git a/doc/development/diffs.md b/doc/development/diffs.md
index eb070cbf4d7..ece7bb9e9ee 100644
--- a/doc/development/diffs.md
+++ b/doc/development/diffs.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Working with diffs
Currently we rely on different sources to present diffs, these include:
@@ -93,7 +99,6 @@ Gitlab::Git::DiffCollection.collection_limits[:max_bytes] = Gitlab::Git::DiffCol
No more files will be rendered at all if 5 megabytes have already been rendered.
-NOTE: **Note:**
All collection limit parameters are currently sent and applied on Gitaly. That is, once the limit is surpassed,
Gitaly will only return the safe amount of data to be persisted on `merge_request_diff_files`.
@@ -108,7 +113,6 @@ That is, it's equivalent to 10kb if the maximum allowed value is 100kb.
The diff will still be persisted and expandable if the patch size doesn't
surpass `ApplicationSettings#diff_max_patch_bytes`.
-NOTE: **Note:**
Although this nomenclature (Collapsing) is also used on Gitaly, this limit is only used on GitLab (hardcoded - not sent to Gitaly).
Gitaly will only return `Diff.Collapsed` (RPC) when surpassing collection limits.
@@ -123,7 +127,6 @@ Commit::DIFF_SAFE_LINES = Gitlab::Git::DiffCollection::DEFAULT_LIMITS[:max_lines
File diff will be suppressed (technically different from collapsed, but behaves the same, and is expandable) if it has more than 5000 lines.
-NOTE: **Note:**
This limit is currently hardcoded and only applied on GitLab.
## Viewers
@@ -132,3 +135,51 @@ Diff Viewers, which can be found on `models/diff_viewer/*` are classes used to m
whether it's a binary, which partial should be used to render it or which File extensions this class accounts for.
`DiffViewer::Base` validates _blobs_ (old and new versions) content, extension and file type in order to check if it can be rendered.
+
+## Merge request diffs against the `HEAD` of the target branch
+
+Historically, merge request diffs have been calculated by `git diff target...source` which compares the
+`HEAD` of the source branch with the merge base (or a common ancestor) of the target branch and the source's.
+This solution works well until the target branch starts containing some of the
+changes introduced by the source branch: Consider the following case, in which the source branch
+is `feature_a` and the target is `master`:
+
+1. Checkout a new branch `feature_a` from `master` and remove `file_a` and `file_b` in it.
+1. Add a commit that removes `file_a` to `master`.
+
+The merge request diff still contains the `file_a` removal while the actual diff compared to
+`master`'s `HEAD` has only the `file_b` removal. The diff with such redundant
+changes is harder to review.
+
+In order to display an up-to-date diff, in GitLab 12.9 we
+[introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27008) merge request
+diffs compared against `HEAD` of the target branch: the
+target branch is artificially merged into the source branch, then the resulting
+merge ref is compared to the source branch in order to calculate an accurate
+diff.
+
+Until we complete the epics ["use merge refs for diffs"](https://gitlab.com/groups/gitlab-org/-/epics/854)
+and ["merge conflicts in diffs"](https://gitlab.com/groups/gitlab-org/-/epics/4893),
+both options `master (base)` and `master (HEAD)` are available to be displayed in merge requests:
+
+![Merge ref head options](img/merge_ref_head_options_v13_6.png)
+
+The `master (HEAD)` option is meant to replace `master (base)` in the future.
+
+In order to support comments for both options, diff note positions are stored for
+both `master (base)` and `master (HEAD)` versions ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/198457) in 12.10).
+The position for `master (base)` version is stored in `Note#position` and
+`Note#original_position` columns, for `master (HEAD)` version `DiffNotePosition`
+has been introduced.
+
+One of the key challenges to deal with when working on merge ref diffs are merge
+conflicts. If the target and source branch contains a merge conflict, the branches
+cannot be automatically merged. The [recording on
+YouTube](https://www.youtube.com/watch?v=GFXIFA4ZuZw&feature=youtu.be&ab_channel=GitLabUnfiltered)
+is a quick introduction to the problem and the motivation behind the [epic](https://gitlab.com/groups/gitlab-org/-/epics/854).
+
+In 13.5 a solution for both-modified merge
+conflict has been
+[introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232484). However,
+there are more classes of merge conflicts that are to be
+[addressed](https://gitlab.com/groups/gitlab-org/-/epics/4893) in the future.
diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md
index 952435150d6..6d277f9ae99 100644
--- a/doc/development/distributed_tracing.md
+++ b/doc/development/distributed_tracing.md
@@ -178,6 +178,7 @@ This configuration string uses the Jaeger driver `opentracing://jaeger` with the
| `udp_endpoint` | `localhost:6831` | This is the default. Configures Jaeger to send trace information to the UDP listener on port `6831` using compact thrift protocol. Note that we've experienced some issues with the [Jaeger Client for Ruby](https://github.com/salemove/jaeger-client-ruby) when using this protocol. |
| `sampler` | `probabalistic` | Configures Jaeger to use a probabilistic random sampler. The rate of samples is configured by the `sampler_param` value. |
| `sampler_param` | `0.01` | Use a ratio of `0.01` to configure the `probabalistic` sampler to randomly sample _1%_ of traces. |
+| `service_name` | `api` | Override the service name used by the Jaeger backend. This parameter will take precedence over the application-supplied value. |
NOTE: **Note:**
The same `GITLAB_TRACING` value should to be configured in the environment
@@ -185,7 +186,7 @@ variables for all GitLab processes, including Workhorse, Gitaly, Rails, and Side
### 3. Start the GitLab application
-Once the `GITLAB_TRACING` environment variable is exported to all GitLab services, start the
+After the `GITLAB_TRACING` environment variable is exported to all GitLab services, start the
application.
When `GITLAB_TRACING` is configured properly, the application will log this on startup:
diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md
index 0f03ceeb4b5..5bc3e1d59e2 100644
--- a/doc/development/documentation/feature_flags.md
+++ b/doc/development/documentation/feature_flags.md
@@ -30,8 +30,7 @@ See how to document them below, according to the state of the flag:
- [Features that can be enabled or disabled for a single project](#features-enabled-by-project).
- [Features with the feature flag removed](#features-with-flag-removed).
-NOTE: **Note:**
-The [`**(CORE ONLY)**`](styleguide.md#product-badges) badge or equivalent for
+The [`**(CORE ONLY)**`](styleguide/index.md#product-badges) badge or equivalent for
the feature's tier should be added to the line and heading that refers to
enabling/disabling feature flags as Admin access is required to do so,
therefore, it indicates that it cannot be done by regular users of GitLab.com.
diff --git a/doc/development/documentation/graphql_styleguide.md b/doc/development/documentation/graphql_styleguide.md
index 11e6b159359..d658794f7e0 100644
--- a/doc/development/documentation/graphql_styleguide.md
+++ b/doc/development/documentation/graphql_styleguide.md
@@ -67,7 +67,7 @@ Set up the section with the following:
```
- Include a screenshot of the result in the GraphiQL explorer. Follow the naming
- convention described in the [Save the image](styleguide.md#save-the-image) section of the Documentation style guide.
+ convention described in the [Save the image](styleguide/index.md#save-the-image) section of the Documentation style guide.
- 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).
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index e51f966ee6e..69a8ff10878 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -11,7 +11,7 @@ GitLab's documentation is [intended as the single source of truth (SSOT)](https:
In addition to this page, the following resources can help you craft and contribute to documentation:
-- [Style Guide](styleguide.md) - What belongs in the docs, language guidelines, Markdown standards to follow, links, and more.
+- [Style Guide](styleguide/index.md) - What belongs in the docs, language guidelines, Markdown standards to follow, links, and more.
- [Structure and template](structure.md) - Learn the typical parts of a doc page and how to write each one.
- [Documentation process](workflow.md).
- [Markdown Guide](../../user/markdown.md) - A reference for all Markdown syntax supported by GitLab.
@@ -64,11 +64,11 @@ However, anyone can contribute [documentation improvements](workflow.md) that ar
[GitLab docs](https://gitlab.com/gitlab-org/gitlab-docs) uses [GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown)
as its Markdown rendering engine. See the [GitLab Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/) for a complete Kramdown reference.
-Adhere to the [Documentation Style Guide](styleguide.md). If a style standard is missing, you are welcome to suggest one via a merge request.
+Adhere to the [Documentation Style Guide](styleguide/index.md). If a style standard is missing, you are welcome to suggest one via a merge request.
## Folder structure and files
-See the [Structure](styleguide.md#structure) section of the [Documentation Style Guide](styleguide.md).
+See the [Structure](styleguide/index.md#structure) section of the [Documentation Style Guide](styleguide/index.md).
## Metadata
@@ -229,7 +229,7 @@ Things to note:
it in for `workflow/lfs/lfs_administration` and `lfs/lfs_administration`
and will print the file and the line where this file is mentioned.
You may ask why the two greps. Since [we use relative paths to link to
- documentation](styleguide.md#links), sometimes it might be useful to search a path deeper.
+ documentation](styleguide/index.md#links), sometimes it might be useful to search a path deeper.
- The `*.md` extension is not used when a document is linked to GitLab's
built-in help page, which is why we omit it in `git grep`.
- Use the checklist on the "Change documentation location" MR description template.
@@ -472,269 +472,7 @@ The following GitLab features are used among others:
## Testing
-We treat documentation as code, and so use tests in our CI pipeline to maintain the
-standards and quality of the docs. The current tests, which run in CI jobs when a
-merge request with new or changed docs is submitted, are:
-
-- [`docs lint`](https://gitlab.com/gitlab-org/gitlab/-/blob/0b562014f7b71f98540e682c8d662275f0011f2f/.gitlab/ci/docs.gitlab-ci.yml#L41):
- Runs several tests on the content of the docs themselves:
- - [`lint-doc.sh` script](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/lint-doc.sh)
- runs the following checks and linters:
- - All cURL examples use the long flags (ex: `--header`, not `-H`).
- - The `CHANGELOG.md` does not contain duplicate versions.
- - No files in `doc/` are executable.
- - No new `README.md` was added.
- - [markdownlint](#markdownlint).
- - [Vale](#vale).
- - Nanoc tests:
- - [`internal_links`](https://gitlab.com/gitlab-org/gitlab/-/blob/0b562014f7b71f98540e682c8d662275f0011f2f/.gitlab/ci/docs.gitlab-ci.yml#L58)
- checks that all internal links (ex: `[link](../index.md)`) are valid.
- - [`internal_anchors`](https://gitlab.com/gitlab-org/gitlab/-/blob/0b562014f7b71f98540e682c8d662275f0011f2f/.gitlab/ci/docs.gitlab-ci.yml#L60)
- checks that all internal anchors (ex: `[link](../index.md#internal_anchor)`)
- are valid.
- - [`ui-docs-links lint`](https://gitlab.com/gitlab-org/gitlab/-/blob/0b562014f7b71f98540e682c8d662275f0011f2f/.gitlab/ci/docs.gitlab-ci.yml#L62)
- checks that all links to docs from UI elements (`app/views` files, for example)
- are linking to valid docs and anchors.
-
-### Run tests locally
-
-Apart from [previewing your changes locally](#previewing-the-changes-live), you can also run all lint checks
-and Nanoc tests locally.
-
-#### Lint checks
-
-Lint checks are performed by the [`lint-doc.sh`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/lint-doc.sh)
-script and can be executed as follows:
-
-1. Navigate to the `gitlab` directory.
-1. Run:
-
- ```shell
- MD_DOC_PATH=path/to/my_doc.md scripts/lint-doc.sh
- ```
-
-Where `MD_DOC_PATH` points to the file or directory you would like to run lint checks for.
-If you omit it completely, it will default to the `doc/` directory.
-The output should be similar to:
-
-```plaintext
-=> Linting documents at path /path/to/gitlab as <user>...
-=> Checking for cURL short options...
-=> Checking for CHANGELOG.md duplicate entries...
-=> Checking /path/to/gitlab/doc for executable permissions...
-=> Checking for new README.md files...
-=> Linting markdown style...
-=> Linting prose...
-✔ 0 errors, 0 warnings and 0 suggestions in 1 file.
-✔ Linting passed
-```
-
-Note that this requires you to either have the required lint tools installed on your machine,
-or a working Docker installation, in which case an image with these tools pre-installed will be used.
-
-#### Nanoc tests
-
-To execute Nanoc tests locally:
-
-1. Navigate to the [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs) directory.
-1. Run:
-
- ```shell
- # Check for broken internal links
- bundle exec nanoc check internal_links
-
- # Check for broken external links (might take a lot of time to complete).
- # This test is set to be allowed to fail and is run only in the gitlab-docs project CI
- bundle exec nanoc check internal_anchors
- ```
-
-#### `ui-docs-links` test
-
-The `ui-docs-links lint` job uses `haml-lint` to test that all links to docs from
-UI elements (`app/views` files, for example) are linking to valid docs and anchors.
-
-To run the `ui-docs-links` test locally:
-
-1. Open the `gitlab` directory in a terminal window.
-1. Run:
-
- ```shell
- bundle exec haml-lint -i DocumentationLinks
- ```
-
-If you receive an error the first time you run this test, run `bundle install`, which
-installs GitLab's dependencies, and try again.
-
-If you don't want to install all of GitLab's dependencies to test the links, you can:
-
-1. Open the `gitlab` directory in a terminal window.
-1. Install `haml-lint`:
-
- ```shell
- gem install haml_lint
- ```
-
-1. Run:
-
- ```shell
- haml-lint -i DocumentationLinks
- ```
-
-If you manually install `haml-lint` with this process, it will not update automatically
-and you should make sure your version matches the version used by GitLab.
-
-### Local linters
-
-To help adhere to the [documentation style guidelines](styleguide.md), and improve the content
-added to documentation, [install documentation linters](#install-linters) and
-[integrate them with your code editor](#configure-editors).
-
-At GitLab, we mostly use:
-
-- [markdownlint](#markdownlint)
-- [Vale](#vale)
-
-#### markdownlint
-
-[markdownlint](https://github.com/DavidAnson/markdownlint) checks that Markdown syntax follows
-[certain rules](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#rules), and is
-used by the [`docs-lint` test](#testing).
-
-Our [Documentation Style Guide](styleguide.md#markdown) and
-[Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/) elaborate on which choices must
-be made when selecting Markdown syntax for GitLab documentation. This tool helps catch deviations
-from those guidelines.
-
-markdownlint configuration is found in the following projects:
-
-- [`gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/.markdownlint.json)
-- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/.markdownlint.json)
-- [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/.markdownlint.json)
-- [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/.markdownlint.json)
-- [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/.markdownlint.json)
-
-This configuration is also used within build pipelines.
-
-You can use markdownlint:
-
-- [On the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--).
-- [Within a code editor](#configure-editors).
-- [In a `pre-commit` hook](#configure-pre-commit-hooks).
-
-#### Vale
-
-[Vale](https://errata-ai.gitbook.io/vale/) is a grammar, style, and word usage linter for the
-English language. Vale's configuration is stored in the
-[`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/blob/master/.vale.ini) file located in the root
-directory of projects.
-
-Vale supports creating [custom tests](https://errata-ai.github.io/vale/styles/) that extend any of
-several types of checks, which we store in the `.linting/vale/styles/gitlab` directory within the
-documentation directory of projects.
-
-Vale configuration is found in the following projects:
-
-- [`gitlab`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.vale/gitlab)
-- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/master/docs/.vale/gitlab)
-- [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/tree/master/doc/.vale/gitlab)
-- [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/tree/master/doc/.vale/gitlab)
-- [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/master/doc/.vale/gitlab)
-
-This configuration is also used within build pipelines.
-
-You can use Vale:
-
-- [On the command line](https://errata-ai.gitbook.io/vale/getting-started/usage).
-- [Within a code editor](#configure-editors).
-- [In a `pre-commit` hook](#configure-pre-commit-hooks). Vale only reports errors in the
- `pre-commit` hook (the same configuration as the CI/CD pipelines), and does not report suggestions
- or warnings.
-
-#### Install linters
-
-At a minimum, install [markdownlint](#markdownlint) and [Vale](#vale) to match the checks run in
-build pipelines:
-
-1. Install `markdownlint-cli`, using either:
-
- - `npm`:
-
- ```shell
- npm install -g markdownlint-cli
- ```
-
- - `yarn`:
-
- ```shell
- yarn global add markdownlint-cli
- ```
-
- We recommend installing the version of `markdownlint-cli` currently used in the documentation
- linting [Docker image](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/.gitlab-ci.yml#L420).
-
-1. Install [`vale`](https://github.com/errata-ai/vale/releases). For example, to install using
- `brew` for macOS, run:
-
- ```shell
- brew install vale
- ```
-
- We recommend installing the version of Vale currently used in the documentation linting
- [Docker image](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/.gitlab-ci.yml#L419).
-
-In addition to using markdownlint and Vale at the command line, these tools can be
-[integrated with your code editor](#configure-editors).
-
-#### Configure editors
-
-To configure markdownlint within your editor, install one of the following as appropriate:
-
-- [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint)
-- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint)
-- [Atom](https://atom.io/packages/linter-node-markdownlint)
-- [Vim](https://github.com/dense-analysis/ale)
-
-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 [`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).
-
-#### Configure pre-commit hooks
-
-Git [pre-commit hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) allow Git users to
-run tests or other processes before committing to a branch, with the ability to not commit to the branch if
-failures occur with these tests.
-
-[`overcommit`](https://github.com/sds/overcommit) is a Git hooks manager, making configuring,
-installing, and removing Git hooks easy.
-
-Sample configuration for `overcommit` is available in the
-[`.overcommit.yml.example`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.overcommit.yml.example)
-file for the [`gitlab`](https://gitlab.com/gitlab-org/gitlab) project.
-
-To set up `overcommit` for documentation linting, see
-[Pre-commit static analysis](../contributing/style_guides.md#pre-commit-static-analysis).
-
-#### Disable Vale tests
-
-You can disable a specific Vale linting rule or all Vale linting rules for any portion of a
-document:
-
-- To disable a specific rule, add a `<!-- vale gitlab.rulename = NO -->` tag before the text, and a
- `<!-- vale gitlab.rulename = YES -->` tag after the text, replacing `rulename` with the filename
- of a test in the
- [GitLab styles](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.linting/vale/styles/gitlab)
- directory.
-- 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).
-
-For more information, see
-[Vale's documentation](https://errata-ai.gitbook.io/vale/getting-started/markup#markup-based-configuration).
+For more information on documentation testing, see [Documentation testing](testing.md)
## Danger Bot
diff --git a/doc/development/documentation/restful_api_styleguide.md b/doc/development/documentation/restful_api_styleguide.md
index b12578b5d98..13c6140114f 100644
--- a/doc/development/documentation/restful_api_styleguide.md
+++ b/doc/development/documentation/restful_api_styleguide.md
@@ -38,12 +38,16 @@ The following can be used as a template to get started:
````markdown
## Descriptive title
+> Version history note.
+
One or two sentence description of what endpoint does.
```plaintext
METHOD /endpoint
```
+Supported attributes:
+
| Attribute | Type | Required | Description |
|:------------|:---------|:---------|:----------------------|
| `attribute` | datatype | yes/no | Detailed description. |
@@ -65,6 +69,9 @@ Example response:
```
````
+Adjust the [version history note accordingly](styleguide/index.md#version-text-in-the-version-history)
+to describe the GitLab release that introduced the API call.
+
## Method description
Use the following table headers to describe the methods. Attributes should
@@ -105,8 +112,8 @@ you can use in the API documentation.
CAUTION: **Caution:**
Do not use information for real users, URLs, or tokens. For documentation, refer to our
-relevant style guide sections on [Fake user information](styleguide.md#fake-user-information),
-[Fake URLs](styleguide.md#fake-urls), and [Fake tokens](styleguide.md#fake-tokens).
+relevant style guide sections on [Fake user information](styleguide/index.md#fake-user-information),
+[Fake URLs](styleguide/index.md#fake-urls), and [Fake tokens](styleguide/index.md#fake-tokens).
### Simple cURL command
@@ -136,14 +143,26 @@ 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.
+This example creates a new group. Be aware of the use of single (`'`) and double
+(`"`) quotes.
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"path": "my-group", "name": "My group"}' "https://gitlab.example.com/api/v4/groups"
```
+For readability, you can also set up the `--data` by using the following format:
+
+```shell
+curl --request POST \
+--url "https://gitlab.example.com/api/v4/groups" \
+--header "content-type: application/json" \
+--header "PRIVATE-TOKEN: <your_access_token>" \
+--data '{
+ "path": "my-group",
+ "name": "My group"
+}'
+```
+
### Post data using form-data
Instead of using JSON or urlencode you can use multipart/form-data which
diff --git a/doc/development/documentation/site_architecture/deployment_process.md b/doc/development/documentation/site_architecture/deployment_process.md
index 00cdc69d422..f101a669968 100644
--- a/doc/development/documentation/site_architecture/deployment_process.md
+++ b/doc/development/documentation/site_architecture/deployment_process.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Documentation deployment process
The [`dockerfiles` directory](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/)
diff --git a/doc/development/documentation/site_architecture/global_nav.md b/doc/development/documentation/site_architecture/global_nav.md
index 9fce9b4e4b3..21b0c4b6b43 100644
--- a/doc/development/documentation/site_architecture/global_nav.md
+++ b/doc/development/documentation/site_architecture/global_nav.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
description: "Learn how GitLab docs' global navigation works and how to add new items."
---
@@ -67,7 +70,6 @@ With these groups in mind, the following are general rules for where new items s
- Other documentation belongs at the top-level, but care must be taken to not create an enormously
long top-level navigation, which defeats the purpose of it.
-NOTE: **Note:**
Making all documentation and navigation items adhere to these principles is being progressively
rolled out.
@@ -114,7 +116,6 @@ for clarity.
To see the improvements planned, check the
[global nav epic](https://gitlab.com/groups/gitlab-com/-/epics/21).
-NOTE: **Note:**
**Do not** [add items](#adding-new-items) to the global nav without
the consent of one of the technical writers.
diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md
index 5d3af6721d1..3772746e25b 100644
--- a/doc/development/documentation/site_architecture/index.md
+++ b/doc/development/documentation/site_architecture/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
description: "Learn how GitLab's documentation website is architectured."
---
@@ -227,8 +230,9 @@ 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 Team Members:**
-If you’re a GitLab Team Member, find credentials for the Algolia dashboard
+### Algolia notes 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`,
diff --git a/doc/development/documentation/site_architecture/release_process.md b/doc/development/documentation/site_architecture/release_process.md
index d04d34ff786..547adc89a08 100644
--- a/doc/development/documentation/site_architecture/release_process.md
+++ b/doc/development/documentation/site_architecture/release_process.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab Docs monthly release process
When a new GitLab version is released on the 22nd, we need to create the respective
@@ -9,7 +15,6 @@ Since the charts use a different version number than all the other GitLab
products, we need to add a
[version mapping](https://docs.gitlab.com/charts/installation/version_mappings.html):
-NOTE: **Note:**
The charts stable branch is not created automatically like the other products.
There's an [issue to track this](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1442).
It is usually created on the 21st or the 22nd.
@@ -158,7 +163,7 @@ Releasing a new version is a long process that involves many moving parts.
### `test_internal_links_and_anchors` failing on dropdown merge requests
-NOTE: **Note:**
+DANGER: **Deprecated:**
We now pin versions in the `.gitlab-ci.yml` of the respective branch,
so the steps below are deprecated.
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index e454a401a9d..3cc7f49f05e 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -10,7 +10,7 @@ description: What to include in GitLab documentation pages.
Use these standards to contribute content to the GitLab documentation.
Before getting started, familiarize yourself with [GitLab's Documentation guidelines](index.md)
-and the [Documentation Style Guide](styleguide.md).
+and the [Documentation Style Guide](styleguide/index.md).
## Components of a documentation page
@@ -39,7 +39,7 @@ pre-deployment and post-deployment tasks.
## Template for new docs
-Follow the [folder structure and file name guidelines](styleguide.md#folder-structure-overview)
+Follow the [folder structure and file name guidelines](styleguide/index.md#folder-structure-overview)
and create a new topic by using this template:
```markdown
@@ -160,9 +160,9 @@ 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/index.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/index.md#gitlab-versions-and-tiers).
```
## Help and feedback section
@@ -230,7 +230,6 @@ Consider the following guidelines when offering examples:
- 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`.
-NOTE: **Note:**
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 6075124ef40..a12c2740083 100644
--- a/doc/development/documentation/styleguide.md
+++ b/doc/development/documentation/styleguide.md
@@ -1,2063 +1,5 @@
---
-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.'
+redirect_to: 'styleguide/index.md'
---
-# Documentation Style Guide
-
-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 guidelines specific to text in the GitLab interface, see the Pajamas [Content](https://design.gitlab.com/content/error-messages) section.
-
-For information on how to validate styles locally or by using GitLab CI/CD, see [Testing](index.md#testing).
-
-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.
-
-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.
-
-### 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.
-
-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.
-
-- 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/):
-
-- 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.
-
-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 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.
-
-For example, do not create groupings of similar media types. For example:
-
-- Glossaries.
-- FAQs.
-- Sets of all articles or videos.
-
-Such grouping of content by type makes it difficult to browse for the information
-you need and difficult to maintain up-to-date content. Instead, organize content
-by its subject (for example, everything related to CI goes together) and
-cross-link between any related content.
-
-### Docs-first methodology
-
-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
- 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 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 [documentation template](structure.md#template-for-new-docs), if present.
-
-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 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 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 [`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).
-
-### 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:
-
-- There's no equivalent markup in Markdown.
-- Advanced tables are necessary.
-- Special styling is required.
-- Reviewed and approved by a technical writer.
-
-### 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).
-
-#### 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.
-
-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:
-
-- MinIO (needs capital `IO`)
-- NGINX (needs all capitals)
-- runit (needs lowercase `r`)
-
-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.
-- "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.
-
-## Structure
-
-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.
-
-Beyond that, we primarily follow the structure of the GitLab user interface or
-API.
-
-Our goal is to have a clear hierarchical structure with meaningful URLs like
-`docs.gitlab.com/user/project/merge_requests/`. With this pattern, you can
-immediately tell that you are navigating to user-related documentation about
-Project features; specifically about Merge Requests. Our site's paths match
-those of our repository, so the clear structure also makes documentation easier to update.
-
-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 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 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 or renaming a file or directory and it has more than one word
- in its name, use underscores (`_`) instead of spaces or dashes. For example,
- proper naming would be `import_project/import_from_github.md`. This applies
- to both image files and Markdown files.
-1. For image files, do not exceed 100KB.
-1. Do not upload video files to the product repositories.
- [Link or embed videos](#videos) instead.
-1. There are four main directories: `user`, `administration`, `api`, and
- `development`.
-1. The `doc/user/` directory has five main subdirectories: `project/`, `group/`,
- `profile/`, `dashboard/` and `admin_area/`.
- 1. `doc/user/project/` should contain all project related documentation.
- 1. `doc/user/group/` should contain all group related documentation.
- 1. `doc/user/profile/` should contain all profile related documentation.
- Every page you would navigate under `/profile` should have its own document,
- for example, `account.md`, `applications.md`, or `emails.md`.
- 1. `doc/user/dashboard/` should contain all dashboard related documentation.
- 1. `doc/user/admin_area/` should contain all admin related documentation
- describing what can be achieved by accessing GitLab's admin interface
- (_not to be confused with `doc/administration` where server access is
- required_).
- 1. Every category under `/admin/application_settings/` should have its
- own document located at `doc/user/admin_area/settings/`. For example,
- the **Visibility and Access Controls** category should have a document
- located at `doc/user/admin_area/settings/visibility_and_access_controls.md`.
-1. The `doc/topics/` directory holds topic-related technical content. Create
- `doc/topics/topic_name/subtopic_name/index.md` when subtopics become necessary.
- General user- and admin- related documentation, should be placed accordingly.
-1. The `/university/` directory is *deprecated* and the majority of its documentation
- has been moved.
-
-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.
-
-### Avoid duplication
-
-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 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's a logical reason not to (for example, when mirroring the user
- interface or an otherwise ordered sequence).
-
-## Language
-
-GitLab documentation should be clear and easy to understand.
-
-- Be clear, concise, and stick to the goal of the documentation.
-- Write in US English with US grammar. (Tested in [`British.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/British.yml).)
-- Use [inclusive language](#inclusive-language).
-
-### 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).)
-
-<!-- How do we harmonize the second person in Pajamas with our first person plural in our doc guide? -->
-
-### Capitalization
-
-#### Headings
-
-Use sentence case. For example:
-
-- `# Use variables to configure pipelines`
-- `## Use the To-Do List`
-
-#### 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 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 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:
- - epics
- - issues
- - issue weights
- - merge requests
- - milestones
- - reorder issues
- - runner, runners, shared runners
- - a to-do item, to dos
-- *Some features are capitalized*, typically nouns naming GitLab-specific
- capabilities or tools. For example:
- - GitLab CI/CD
- - Repository Mirroring
- - Value Stream Analytics
- - the To-Do List
- - the Web IDE
- - 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.
-
-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).)
-
-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 select **Log in**.
-
-### Inclusive language
-
-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).
- (Tested in [`InclusionGender.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionGender.yml).)
-- [Ableist language](#avoid-ableist-language).
- (Tested in [`InclusionAbleism.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionAbleism.yml).)
-- [Cultural sensitivity](#culturally-sensitive-language).
- (Tested in [`InclusionCultural.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionCultural.yml).)
-
-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.
-
-Avoid the use of gender-specific pronouns, unless referring to a specific person.
-
-<!-- vale gitlab.InclusionGender = NO -->
-
-| Use | Avoid |
-|-----------------------------------|---------------------------------|
-| People, humanity | Mankind |
-| GitLab Team Members | Manpower |
-| You can install; They can install | He can install; She can install |
-
-<!-- vale gitlab.InclusionGender = YES -->
-
-If you need to set up [Fake user information](#fake-user-information), use
-diverse or non-gendered names with common surnames.
-
-#### Avoid ableist language
-
-Avoid terms that are also used in negative stereotypes for different groups.
-
-<!-- vale gitlab.InclusionAbleism = NO -->
-
-| Use | Avoid |
-|------------------------|----------------------|
-| Check for completeness | Sanity check |
-| Uncertain outliers | Crazy outliers |
-| Slows the service | Cripples the service |
-| Placeholder variable | Dummy variable |
-| Active/Inactive | Enabled/Disabled |
-| On/Off | Enabled/Disabled |
-
-<!-- vale gitlab.InclusionAbleism = YES -->
-
-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`.
-
-<!-- vale gitlab.InclusionCultural = NO -->
-
-| Use | Avoid |
-|----------------------|-----------------------|
-| Primary / secondary | Master / slave |
-| Allowlist / denylist | Blacklist / whitelist |
-
-<!-- vale gitlab.InclusionCultural = YES -->
-
-For more information see the following [Internet Draft specification](https://tools.ietf.org/html/draft-knodel-terminology-02).
-
-### Fake user information
-
-You may need to include user information in entries such as a REST call or user profile.
-**Do not** use real user information or email addresses in GitLab documentation. For email
-addresses and names, do use:
-
-- **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 `Alex Garcia`.
-
-### Fake URLs
-
-When including sample URLs in the documentation, use:
-
-- `example.com` when the domain name is generic.
-- `gitlab.example.com` when referring to self-managed instances of GitLab.
-
-### 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.
-
-You can use the following fake tokens as examples:
-
-| Token type | Token value |
-|:----------------------|:-------------------------------------------------------------------|
-| Private user token | `<your_access_token>` |
-| Personal access token | `n671WNGecHugsdEDPsyo` |
-| Application ID | `2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6` |
-| Application secret | `04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df` |
-| CI/CD variable | `Li8j-mLUVA3eZYjPfd_H` |
-| Specific runner token | `yrnZW46BrtBFqM7xDzE7dddd` |
-| Shared runner token | `6Vk7ZsosqQyfreAxXTZr` |
-| Trigger token | `be20d8dcc028677c931e04f3871a9b` |
-| Webhook secret token | `6XhDroRcYPM5by_h-HLY` |
-| Health check token | `Tu7BgjR9qeZTEyRzGG2P` |
-| Request profile token | `7VgpS4Ax5utVD2esNstz` |
-
-### Language to avoid
-
-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.
-- 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."
- - When possible, stay user focused by writing in the second person ("you" or
- the imperative).
-- Don't overuse "that". In many cases, you can remove "that" from a sentence
- and improve readability.
-- Avoid use of the future tense:
- - Instead of "after you execute this command, GitLab will display the
- result", use "after you execute this command, GitLab displays the result".
- - Only use the future tense to convey when the action or result will actually
- occur at a future time.
-- Don't use slashes to clump different words together or as a replacement for
- the word "or":
- - Instead of "and/or," consider using "or," or use another sensible
- construction.
- - Other examples include "clone/fetch," author/assignee," and
- "namespace/repository name." Break apart any such instances in an
- appropriate way.
- - Exceptions to this rule include commonly accepted technical terms, such as
- CI/CD and TCP/IP.
-- <!-- vale gitlab.LatinTerms = NO -->
- We discourage use of Latin abbreviations, such as "e.g.," "i.e.," or "etc.,"
- as even native users of English might misunderstand them.
- (Tested in [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml).)
- - Instead of "i.e.," use "that is."
- - 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.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.
-- Avoid the using the word *scalability* with increasing GitLab's performance
- for additional users. Using the words *scale* or *scaling* in other cases is
- acceptable, but references to increasing GitLab's performance for additional
- users should direct readers to the GitLab
- [reference architectures](../../administration/reference_architectures/index.md)
- page.
-- Avoid all forms of the phrases *high availability* and *HA*, and instead
- direct readers to the GitLab [reference architectures](../../administration/reference_architectures/index.md)
- for information about configuring GitLab to have the performance needed for
- additional users over time.
-- Don't use profanity or obscenities. Doing so may negatively affect other
- users and contributors, which is contrary to GitLab's value of
- [Diversity, Inclusion, and Belonging](https://about.gitlab.com/handbook/values/#diversity-inclusion).
-- Avoid the use of [racially-insensitive terminology or phrases](https://www.marketplace.org/2020/06/17/tech-companies-update-language-to-avoid-offensive-terms/). For example:
- - Use *primary* and *secondary* for database and server relationships.
- - Use *allowlist* and *denylist* to describe access control lists.
-- Avoid the word *please*. For details, see [the Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/p/please).
-
-### Word usage clarifications
-
-- Don't use "may" and "might" interchangeably:
- - Use "might" to indicate the probability of something occurring. "If you
- skip this step, the import process might fail."
- - Use "may" to indicate giving permission for someone to do something, or
- consider using "can" instead. "You may select either option on this
- screen." Or, "You can select either option on this screen."
-
-### Contractions
-
-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 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 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. |
-
-- 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. |
-
-## 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.
-- 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:
-
- ```markdown
- ## Header
-
- Paragraph.
-
- - List item 1
- - List item 2
- ```
-
-### Emphasis
-
-- Use double asterisks (`**`) to mark a word or text in bold (`**bold**`).
-- Use underscore (`_`) for text in italics (`_italic_`).
-- Use greater than (`>`) for blockquotes.
-
-### Punctuation
-
-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._ |
-| 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._ |
-
-### Placeholder text
-
-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.
-
-For example:
-
-```shell
-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 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).
-
-### Ordered vs. unordered lists
-
-Only use ordered lists when their items describe a sequence of steps to follow.
-
-Do:
-
-```markdown
-These are the steps to do something:
-
-1. First, do the first step.
-1. Then, do the next step.
-1. Finally, do the last step.
-```
-
-Don't:
-
-```markdown
-This is a list of available features:
-
-1. Feature 1
-1. Feature 2
-1. Feature 3
-```
-
-### 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.
-
-### 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)
- 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.
-- Separate list items from explanatory text with a colon (`:`). For example:
-
- ```markdown
- The list is as follows:
-
- - First item: this explains the first item.
- - Second item: this explains the second item.
- ```
-
-**Examples:**
-
-Do:
-
-- First list item
-- Second list item
-- Third list item
-
-Don't:
-
-- First list item
-- Second list item
-- Third list item.
-
-Do:
-
-- Let's say this is a complete sentence.
-- Let's say this is also a complete sentence.
-- Not a complete sentence.
-
-Don't (vary use of periods; majority rules):
-
-- Let's say this is a complete sentence.
-- Let's say this is also a complete sentence.
-- Not a complete sentence
-
-### Nesting inside a list item
-
-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:
-
-````markdown
-- Unordered list item 1
-
- A line nested using 2 spaces to align with the `U` above.
-
-- Unordered list item 2
-
- > A quote block that will nest
- > inside list item 2.
-
-- Unordered list item 3
-
- ```plaintext
- a codeblock that will next inside list item 3
- ```
-
-- Unordered list item 4
-
- ![an image that will nest inside list item 4](image.png)
-````
-
-For ordered lists, use three spaces for each level of indentation:
-
-````markdown
-1. Ordered list item 1
-
- A line nested using 3 spaces to align with the `O` above.
-
-1. Ordered list item 2
-
- > A quote block that will nest
- > inside list item 2.
-
-1. Ordered list item 3
-
- ```plaintext
- a codeblock that will next inside list item 3
- ```
-
-1. Ordered list item 4
-
- ![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
-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.
-1. Ordered list item two.
- - Nested unordered list item one.
- - Nested unordered list item two.
-1. Ordered list item three.
-
-- Unordered list item one.
-- Unordered list item two.
- 1. Nested ordered list item one.
- 1. Nested ordered list item two.
-- Unordered list item three.
-```
-
-## Tables
-
-Tables should be used to describe complex information in a straightforward
-manner. Note that in many cases, an unordered list is sufficient to describe a
-list of items with a single, simple description per item. But, if you have data
-that is best described by a matrix, tables are the best choice for use.
-
-### Creation guidelines
-
-Due to accessibility and scannability requirements, tables should not have any
-empty cells. If there is no otherwise meaningful value for a cell, consider entering
-*N/A* (for 'not applicable') or *none*.
-
-To help tables be easier to maintain, consider adding additional spaces to the
-column widths to make them consistent. For example:
-
-```markdown
-| App name | Description | Requirements |
-|:---------|:---------------------|:---------------|
-| App 1 | Description text 1. | Requirements 1 |
-| App 2 | Description text 2. | None |
-```
-
-Consider installing a plugin or extension in your editor for formatting tables:
-
-- [Markdown Table Prettifier](https://marketplace.visualstudio.com/items?itemName=darkriszty.markdown-table-prettify) for Visual Studio Code
-- [Markdown Table Formatter](https://packagecontrol.io/packages/Markdown%20Table%20Formatter) for Sublime Text
-- [Markdown Table Formatter](https://atom.io/packages/markdown-table-formatter) for Atom
-
-### Feature tables
-
-When creating tables of lists of features (such as whether or not features are
-available to certain roles on the [Permissions](../../user/permissions.md#project-members-permissions)
-page), use the following phrases (based on the SVG icons):
-
-| Option | Markdown | Displayed result |
-|--------|--------------------------|------------------------|
-| No | `**{dotted-circle}** No` | **{dotted-circle}** No |
-| Yes | `**{check-circle}** Yes` | **{check-circle}** Yes |
-
-## Quotes
-
-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".
-
-For other punctuation rules, please refer to the
-[GitLab UX guide](https://design.gitlab.com/content/punctuation/).
-
-## Headings
-
-- Add **only one H1** in each document, by adding `#` at the beginning of
- it (when using Markdown). The `h1` will be the document `<title>`.
-- Start with an `h2` (`##`), and respect the order `h2` > `h3` > `h4` > `h5` > `h6`.
- Never skip the hierarchy level, such as `h2` > `h4`
-- Avoid putting numbers in headings. Numbers shift, hence documentation anchor
- links shift too, which eventually leads to dead links. If you think it is
- compelling to add numbers in headings, make sure to at least discuss it with
- 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.
-- 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.
-- 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 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.
-
-| 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 |
-
-For guidelines on capitalizing headings, see the section on [capitalization](#capitalization).
-
-NOTE: **Note:**
-If you change an existing title, be careful. These changes might affect not
-only [links](#anchor-links) within the page, but might 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`.
-
-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 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.
-- Do not link to `h1` headings.
-
-Note that, with Kramdown, it is possible to add a custom ID to an HTML element
-with Markdown markup, but they **do not** work in GitLab's `/help`. Therefore,
-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 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.
-- 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).
-- How to [link to specific lines of code](#link-to-specific-lines-of-code)
-
-### 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]`.
-
-- 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)`,
- write `Read more about [GitLab Issue Boards](LINK)`.
-
-### 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 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 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 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:
-
-- Use relative links to Markdown files in the same repository.
-- Do not use absolute URLs or URLs from `docs.gitlab.com`.
-- Use `../` to navigate to higher-level directories.
-- Do not link relative to root. For example, `/ee/user/gitlab_com/index.md`.
-
- Don't:
-
- - `https://docs.gitlab.com/ee/administration/geo/replication/troubleshooting.html`
- - `/ee/administration/geo/replication/troubleshooting.md`
-
- Do: `../../geo/replication/troubleshooting.md`
-
-- Always add the file name `file.md` at the end of the link with the `.md`
- extension, not `.html`.
-
- Don't:
-
- - `../../merge_requests/`
- - `../../issues/tags.html`
- - `../../issues/tags.html#stages`
-
- Do:
-
- - `../../merge_requests/index.md`
- - `../../issues/tags.md`
- - `../../issues/tags.md#stages`
-
-NOTE: **Note:**
-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.
-
-### 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.
-
-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/).
-- Books from an authoritative publisher.
-
-Examples of sources to avoid include:
-
-- Personal blog posts.
-- Wikipedia.
-- Non-trustworthy articles.
-- 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.
-
-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.
-
-### 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.
-
-These will fail for:
-
-- Those without sufficient permissions.
-- Automated link checkers.
-
-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.
-
-Example:
-
-```markdown
-For more information, see the [confidential issue](../../user/project/issues/confidential_issues.md) `https://gitlab.com/gitlab-org/gitlab-foss/-/issues/<issue_number>`.
-```
-
-### 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.
-
-- *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 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
-
-When documenting navigation through the user interface:
-
-- Use the exact wording as shown in the UI, including any capital letters as-is.
-- Use bold text for navigation items and the char "greater than" (`>`) as a
- separator. For example: `Navigate to your project's **Settings > CI/CD**`.
-- 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**`.
-
-### Navigational elements
-
-Use the following terms when referring to the main GitLab user interface
-elements:
-
-- **Top menu**: This is the top menu that spans the width of the user interface.
- It includes the GitLab logo, search field, counters, and the user's avatar.
-- **Left sidebar**: This is the navigation sidebar on the left of the user
- interface, specific to the project or group.
-- **Right sidebar**: This is the navigation sidebar on the right of the user
- interface, specific to the open issue, merge request, or epic.
-
-## 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.
-
-### 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.
-
-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 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
-
-- Save the image with a lowercase file name that is descriptive of the feature
- or concept in the image. If the image is of the GitLab interface, append the
- GitLab version to the file name, based on the following format:
- `image_name_vX_Y.png`. For example, for a screenshot taken from the pipelines
- page of GitLab 11.1, a valid name is `pipelines_v11_1.png`. If you're adding an
- illustration that doesn't include parts of the user interface, add the release
- number corresponding to the release the image was added to; for an MR added to
- 11.1's milestone, a valid name for an illustration is `devops_diagram_v11_1.png`.
-- Place images in a separate directory named `img/` in the same directory where
- the `.md` document that you're working on is located.
-- Consider using PNG images instead of JPEG.
-- [Compress all PNG images](#compress-images).
-- Compress gifs with <https://ezgif.com/optimize> or similar tool.
-- 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
- 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
-documentation site. For accessibility and SEO, use [descriptions](https://webaim.org/techniques/alttext/)
-that:
-
-- Are accurate, succinct, and unique.
-- Don't use *image of …* or *graphic of…* to describe the image.
-
-### Remove image shadow
-
-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">
-```
-
-### Compress images
-
-You should always compress any new images you add to the documentation. One
-known tool is [`pngquant`](https://pngquant.org/), which is cross-platform and
-open source. Install it by visiting the official website and following the
-instructions for your OS.
-
-GitLab has a [Rake task](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/tasks/pngquant.rake)
-that you can use to automate the process. In the root directory of your local
-copy of `https://gitlab.com/gitlab-org/gitlab`, run in a terminal:
-
-- Before compressing, if you want, check that all documentation PNG images have
- been compressed:
-
- ```shell
- bundle exec rake pngquant:lint
- ```
-
-- Compress all documentation PNG images using `pngquant`:
-
- ```shell
- bundle exec rake pngquant:compress
- ```
-
-The only caveat is that the task runs on all images under `doc/`, not only the
-ones you might have included in a merge request. In that case, you can run the
-compress task and only commit the images that are relevant to your merge
-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.
-
-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 scan the page
-for videos before reading:
-
-```markdown
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview, see [Video Title](link-to-video).
-```
-
-You can link any up-to-date video that is useful to the GitLab user.
-
-### Embed videos
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/472) in GitLab 12.1.
-
-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).
-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.
-
-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. 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, select **Share**, and then select **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
- `iframe` tag.
-
-```html
-leave a blank line here
-<div class="video-fallback">
- See the video: <a href="https://www.youtube.com/watch?v=MqL6BMOySIQ">Video title</a>.
-</div>
-<figure class="video-container">
- <iframe src="https://www.youtube.com/embed/MqL6BMOySIQ" frameborder="0" allowfullscreen="true"> </iframe>
-</figure>
-leave a blank line here
-```
-
-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>.
-</div>
-<figure class="video-container">
- <iframe src="https://www.youtube.com/embed/MqL6BMOySIQ" frameborder="0" allowfullscreen="true"> </iframe>
-</figure>
-
-> 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 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 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.
-- HTTP methods (`HTTP POST`) and HTTP status codes, both full (`404 File Not Found`)
- and abbreviated (`404`), should be wrapped in inline code blocks when used in sentences.
- For example: Send a `DELETE` request to delete the runner. Send a `POST` request to create one.
-- 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 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:
-
- ````markdown
- ```ruby
- Ruby code
- ```
-
- ```javascript
- JavaScript code
- ```
-
- ```markdown
- [Markdown code example](example.md)
- ```
-
- ```plaintext
- Code or text for which no specific highlighting class is 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 |
-|-------------------------|------------------------------------------------------------------------------|
-| `asciidoc` | |
-| `dockerfile` | Alias: `docker`. |
-| `elixir` | |
-| `erb` | |
-| `golang` | Alias: `go`. |
-| `graphql` | |
-| `haml` | |
-| `html` | |
-| `ini` | For some simple config files that are not in TOML format. |
-| `javascript` | Alias `js`. |
-| `json` | |
-| `markdown` | Alias: `md`. |
-| `mermaid` | |
-| `nginx` | |
-| `perl` | |
-| `php` | |
-| `plaintext` | Examples with no defined language, such as output from shell commands or API calls. If a codeblock has no language, it defaults to `plaintext`. Alias: `text`. |
-| `prometheus` | Prometheus configuration examples. |
-| `python` | |
-| `ruby` | Alias: `rb`. |
-| `shell` | Aliases: `bash` or `sh`. |
-| `sql` | |
-| `toml` | Runner configuration examples, and other TOML-formatted configuration files. |
-| `typescript` | Alias: `ts`. |
-| `xml` | |
-| `yaml` | Alias: `yml`. |
-
-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.
-
-This way, you can achieve a consistent look when writing about interacting with
-GitLab user interface elements.
-
-Usage examples:
-
-- Icon with default size (16px): `**{icon-name}**`
-
- Example: `**{tanuki}**` renders as: **{tanuki}**.
-- Icon with custom size: `**{icon-name, size}**`
-
- Available sizes (in px): 8, 10, 12, 14, 16, 18, 24, 32, 48, and 72
-
- 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 documentation CSS.
-
- Example with `float-right`, a
- [Bootstrap utility class](https://getbootstrap.com/docs/4.4/utilities/float/):
- `**{tanuki, 32, float-right}**` renders as: **{tanuki, 32, float-right}**
-
-### When to use icons
-
-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:
-
-```markdown
-1. Go to **{home}** **Project overview > Details**
-```
-
-1. Go to **{home}** **Project overview > Details**
-
-However, the following might help the reader connect the text to the user
-interface:
-
-```markdown
-| Section | Description |
-|:-------------------------|:----------------------------------------------------------------------------------------------------------------------------|
-| **{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. |
-| **{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 yourself having to describe an interface element. For
-example:
-
-- Do: Select the Admin Area icon ( **{admin}** ).
-- Don't: Select the Admin Area icon (the wrench icon).
-
-## Alert boxes
-
-When you need to call special attention to particular sentences, use the
-following markup to create highlighted alert boxes.
-
-Alert boxes work for one paragraph only. Multiple paragraphs, lists, and headers
-won't render correctly. For multiple lines, use [blockquotes](#blockquotes)
-instead.
-
-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 indicate additional information that is of special use to the reader.
-Notes are most effective when used _sparingly_.
-
-Try to avoid them. Too many notes can impact the scannability of a topic and
-create an overly busy page.
-
-Instead of adding a note, try one of these alternatives:
-
-- Re-write the sentence as part of the most-relevant paragraph.
-- Put the information into its own standalone paragraph.
-- Put the content under a new subheading that introduces the topic, which makes
- it more visible.
-
-If you must use a note, use the following formatting:
-
-```markdown
-NOTE: **Note:**
-This is something to note.
-```
-
-How it renders on the GitLab documentation site:
-
-NOTE: **Note:**
-This is something to note.
-
-### Tip
-
-```markdown
-TIP: **Tip:**
-This is a tip.
-```
-
-How it renders on the GitLab documentation site:
-
-TIP: **Tip:**
-This is a tip.
-
-### Caution
-
-```markdown
-CAUTION: **Caution:**
-This is something to be cautious about.
-```
-
-How it renders on the GitLab documentation site:
-
-CAUTION: **Caution:**
-This is something to be cautious about.
-
-### Danger
-
-```markdown
-DANGER: **Danger:**
-This is a breaking change, a bug, or something very important to note.
-```
-
-How it renders on the GitLab documentation site:
-
-DANGER: **Danger:**
-This is a breaking change, a bug, or something very important to note.
-
-## Blockquotes
-
-For highlighting a text within a blue blockquote, use this format:
-
-```markdown
-> This is a blockquote.
-```
-
-which renders on the [GitLab documentation site](https://docs.gitlab.com) as:
-
-> This is a blockquote.
-
-If the text spans across multiple lines it's OK to split the line.
-
-For multiple paragraphs, use the symbol `>` before every line:
-
-```markdown
-> This is the first paragraph.
->
-> This is the second paragraph.
->
-> - This is a list item
-> - Second item in the list
-```
-
-Which renders to:
-
-> This is the first paragraph.
->
-> This is the second paragraph.
->
-> - This is a list item
-> - Second item in the list
-
-## 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:
-
-- 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_.
-
-Examples:
-
-- "We prefer GitLab merge requests".
-- "Open a merge request to fix a broken link".
-- "After you open a merge request (MR), submit your MR for review and approval".
-
-### Describe UI elements
-
-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`.
-
-### Verbs for UI elements
-
-The following are recommended verbs for specific uses with user interface
-elements:
-
-| Recommended | Used for | Replaces |
-|:--------------------|:--------------------------------------|:---------------------------|
-| *select* | buttons, links, menu items, dropdowns | "click, "press," "hit" |
-| *select* or *clear* | checkboxes | "enable", "click", "press" |
-| *expand* | expandable sections | "open" |
-
-### Other Verbs
-
-| Recommended | Used for | Replaces |
-|:------------|:--------------------------------|:----------------------|
-| *go to* | making a browser go to location | "navigate to", "open" |
-
-## GitLab versions and tiers
-
-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 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.
-
-### Text for documentation requiring version text
-
-When a feature is new or updated, you can add version information as a bulleted
-item in the **Version history**, or as an inline reference with related text.
-
-#### Version text in the **Version History**
-
-If all content in a section is related, add version text in a bulleted list
-following the heading for the section. To render correctly, it must be on its
-own line and surrounded by blank lines.
-
-- 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:
- - `> [Introduced](<link-to-issue>) in GitLab 11.3.`.
-
-- If the feature is only available in GitLab Enterprise Edition, mention
- the [paid tier](https://about.gitlab.com/handbook/marketing/product-marketing/#tiers)
- 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:
-
- ```markdown
- > - [Introduced](<link-to-issue>) in GitLab 11.3.
- > - Enabled by default in GitLab 11.4.
- ```
-
-- If a feature is moved to another tier:
-
- ```markdown
- > - [Introduced](<link-to-issue>) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.5.
- > - [Moved](<link-to-issue>) to [GitLab Starter](https://about.gitlab.com/pricing/) in 11.8.
- > - [Moved](<link-to-issue>) to GitLab Core in 12.0.
- ```
-
-- If a feature is deprecated, include a link to a replacement (when available):
-
- ```markdown
- > - [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.
-
- If the deprecation is not obvious in existing text, you may want to include a
- warning such as:
-
- ```markdown
- DANGER: **Deprecated:**
- This feature was [deprecated](link-to-issue) in GitLab 12.3
- and replaced by [Feature name](link-to-feature-documentation).
- ```
-
-#### Inline version text
-
-If you're adding content to an existing topic, you can add version information
-inline with the existing text.
-
-In this case, add `([introduced/deprecated](<link-to-issue>) in GitLab X.X)`.
-If applicable, include the paid tier: `([introduced/deprecated](<link-to-issue>) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4)`
-
-Including the issue link is encouraged, but isn't a requirement. For example:
-
-```markdown
-The voting strategy (introduced in GitLab 13.4) requires
-the primary and secondary voters to agree.
-```
-
-### 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*.
-
-For example:
-
-- Available in GitLab 12.3 and earlier.
-- Available in GitLab 12.4 and later.
-- If using GitLab 11.4 or earlier, ...
-- If using GitLab 10.6 or later, ...
-
-### 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.
-
-`[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.
-
-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
-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 documentation.
-
-## Products and features
-
-Refer to the information in this section when describing products and features
-within the GitLab product documentation.
-
-### Avoid line breaks in names
-
-When entering a product or feature name that includes a space (such as
-GitLab Community Edition) or even other companies' products (such as
-Amazon Web Services), be sure to not split the product or feature name across
-lines with an inserted line break. Splitting product or feature names across
-lines makes searching for these items more difficult, and can cause problems if
-names change.
-
-For example, the following Markdown content is *not* formatted correctly:
-
-```markdown
-When entering a product or feature name that includes a space (such as GitLab
-Community Edition), don't split the product or feature name across lines.
-```
-
-Instead, it should appear similar to the following:
-
-```markdown
-When entering a product or feature name that includes a space (such as
-GitLab Community Edition), don't split the product or feature name across lines.
-```
-
-### Product badges
-
-When a feature is available in paid tiers, add the corresponding tier to the
-header or other page element according to the feature's availability:
-
-| Tier in which feature is available | Tier markup |
-|:-----------------------------------------------------------------------|:----------------------|
-| GitLab Core and GitLab.com Free, and their higher tiers | `**(CORE)**` |
-| GitLab Starter and GitLab.com Bronze, and their higher tiers | `**(STARTER)**` |
-| GitLab Premium and GitLab.com Silver, and their higher tiers | `**(PREMIUM)**` |
-| GitLab Ultimate and GitLab.com Gold | `**(ULTIMATE)**` |
-| *Only* GitLab Core and higher tiers (no GitLab.com-based tiers) | `**(CORE ONLY)**` |
-| *Only* GitLab Starter and higher tiers (no GitLab.com-based tiers) | `**(STARTER ONLY)**` |
-| *Only* GitLab Premium and higher tiers (no GitLab.com-based tiers) | `**(PREMIUM ONLY)**` |
-| *Only* GitLab Ultimate (no GitLab.com-based tiers) | `**(ULTIMATE ONLY)**` |
-| *Only* GitLab.com Free and higher tiers (no self-managed instances) | `**(FREE ONLY)**` |
-| *Only* GitLab.com Bronze and higher tiers (no self-managed instances) | `**(BRONZE ONLY)**` |
-| *Only* GitLab.com Silver and higher tiers (no self-managed instances) | `**(SILVER ONLY)**` |
-| *Only* GitLab.com Gold (no self-managed instances) | `**(GOLD ONLY)**` |
-
-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.
-
-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)**
-- `**(SILVER ONLY)**` displays as **(SILVER ONLY)**
-
-#### How it works
-
-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.
-
-## Specific sections
-
-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
-[`doc/administration/restart_gitlab.md`](../../administration/restart_gitlab.md).
-Usually the text will read like:
-
-```markdown
-Save the file and [reconfigure GitLab](../../administration/restart_gitlab.md)
-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/ee/administration/restart_gitlab.html`. Replace
-`reconfigure` with `restart` where appropriate.
-
-### Installation guide
-
-**Ruby:**
-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).
-
-### Configuration documentation for source and Omnibus installations
-
-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 documentation to avoid duplication.
-
-Configuration settings include:
-
-1. Settings that touch configuration files in `config/`.
-1. NGINX settings and settings in `lib/support/` in general.
-
-When there is a list of steps to perform, usually that entails editing the
-configuration file and reconfiguring/restarting GitLab. In such case, follow
-the style below as a guide:
-
-````markdown
-**For Omnibus installations**
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- 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.
-
----
-
-**For installations from source**
-
-1. Edit `config/gitlab.yml`:
-
- ```yaml
- gitlab:
- 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.
-````
-
-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.
-- 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 or reconfigure of GitLab.
-
-### Troubleshooting
-
-For troubleshooting sections, you should provide as much context as possible so
-users can identify the problem they are facing and resolve it on their own. You
-can facilitate this by making sure the troubleshooting content addresses:
-
-1. The problem the user needs to solve.
-1. How the user can confirm they have the problem.
-1. Steps the user can take towards resolution of the problem.
-
-If the contents of each category can be summarized in one line and a list of
-steps aren't required, consider setting up a [table](#tables) 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).
-
-## GraphQL API
-
-GraphQL APIs are different from [RESTful APIs](restful_api_styleguide.md). 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).
-
-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`.
-
-### Start the page with an explanation
-
-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.
-
-### 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:
-
-- Use the following title:
-
- ```markdown
- ## Set up the GraphiQL explorer
- ```
-
-- Include a code block with the query that anyone can include in their
- instance of the GraphiQL explorer:
-
- ````markdown
- ```graphql
- query {
- <insert queries here>
- }
- ```
- ````
-
-- Tell the user what to do:
-
- ```markdown
- 1. Open the GraphiQL explorer tool in the following URL: `https://gitlab.com/-/graphql-explorer`.
- 1. Paste the `query` listed above into the left window of your GraphiQL explorer tool.
- 1. Select Play to get the result shown here:
- ```
-
-- 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.
-- 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 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:
-
-```yaml
-- 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.
-
-And that's all you need!
+This document was moved to [another location](styleguide/index.md).
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
new file mode 100644
index 00000000000..41e38266a58
--- /dev/null
+++ b/doc/development/documentation/styleguide/index.md
@@ -0,0 +1,1999 @@
+---
+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.
+
+For broader information about the documentation, see the [Documentation guidelines](index.md).
+
+For guidelines specific to text in the GitLab interface, see the Pajamas [Content](https://design.gitlab.com/content/error-messages/) section.
+
+For information on how to validate styles locally or by using GitLab CI/CD, see [Testing](../testing.md).
+
+Use this guide for standards on grammar, formatting, word usage, and more.
+
+You can also view a list of [recent updates to this guide](https://gitlab.com/dashboard/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name[]=tw-style&not[label_name][]=docs%3A%3Afix).
+
+If you can't find what you need:
+
+- View the GitLab Handbook for [writing style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines) that apply to all GitLab content.
+- Refer to one of the following:
+
+ - [Microsoft Style Guide](https://docs.microsoft.com/en-us/style-guide/welcome/).
+ - [Google Developer Documentation Style Guide](https://developers.google.com/style).
+
+If you have questions about style, mention `@tw-style` in an issue or merge request, or, if you have access to the GitLab Slack workspace, use `#docs-process`.
+
+## 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.
+
+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.
+
+### 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.
+
+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.
+
+- 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/):
+
+- 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.
+
+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 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 in the
+single-source-of-truth (SSOT) section for the subject matter.
+
+For example, do not create groupings of similar media types. For example:
+
+- Glossaries.
+- FAQs.
+- Sets of all articles or videos.
+
+Such grouping of content by type makes it difficult to browse for the information
+you need and difficult to maintain up-to-date content. Instead, organize content
+by its subject (for example, everything related to CI goes together) and
+cross-link between any related content.
+
+### Docs-first methodology
+
+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
+ 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 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 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 [documentation template](../structure.md#template-for-new-docs), if present.
+
+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 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. Review the
+[Documentation guidelines](index.md) before you begin your first documentation MR.
+
+Having a knowledge base in any form that's 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 [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown) Ruby gem
+will support all [GFM markup](../../../user/markdown.md) in the future, which 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}`) doesn't 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 if:
+
+- There's no equivalent markup in Markdown.
+- Advanced tables are necessary.
+- Special styling is required.
+- Reviewed and approved by a technical writer.
+
+### 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](../testing.md)
+with [markdownlint](../testing.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.
+
+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:
+
+- MinIO (needs capital `IO`)
+- NGINX (needs all capitals)
+- runit (needs lowercase `r`)
+
+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.
+- "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.
+
+## Structure
+
+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.
+
+Beyond that, we primarily follow the structure of the GitLab user interface or
+API.
+
+Our goal is to have a clear hierarchical structure with meaningful URLs like
+`docs.gitlab.com/user/project/merge_requests/`. With this pattern, you can
+immediately tell that you are navigating to user-related documentation about
+Project features; specifically about Merge Requests. Our site's paths match
+those of our repository, so the clear structure also makes documentation easier
+to update.
+
+Put files for a specific product area into the related folder:
+
+| Directory | 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 by using 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 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
+
+Refer to the following items when working with directories and files:
+
+1. When you create a new directory, always start with an `index.md` file.
+ Don't 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. The `doc/user/` directory has five main subdirectories: `project/`, `group/`,
+ `profile/`, `dashboard/` and `admin_area/`.
+ - `doc/user/project/` should contain all project related documentation.
+ - `doc/user/group/` should contain all group related documentation.
+ - `doc/user/profile/` should contain all profile related documentation.
+ Every page you would navigate under `/profile` should have its own document,
+ for example, `account.md`, `applications.md`, or `emails.md`.
+ - `doc/user/dashboard/` should contain all dashboard related documentation.
+ - `doc/user/admin_area/` should contain all admin related documentation
+ describing what can be achieved by accessing GitLab's admin interface
+ (_not to be confused with `doc/administration` where server access is
+ required_).
+ - Every category under `/admin/application_settings/` should have its
+ own document located at `doc/user/admin_area/settings/`. For example,
+ the **Visibility and Access Controls** category should have a document
+ located at `doc/user/admin_area/settings/visibility_and_access_controls.md`.
+1. The `doc/topics/` directory holds topic-related technical content. Create
+ `doc/topics/topic_name/subtopic_name/index.md` when subtopics become necessary.
+ General user- and admin- related documentation, should be placed accordingly.
+1. The `/university/` directory is *deprecated* and the majority of its documentation
+ has been moved.
+
+If you're unsure where to place a document or a content addition, this shouldn't
+stop you from authoring and contributing. Use your best judgment, and then ask
+the reviewer of your MR to confirm your decision, 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 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 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's a logical reason not to (for example, when mirroring the user
+ interface or an otherwise ordered sequence).
+
+## Language
+
+GitLab documentation should be clear and easy to understand.
+
+- Be clear, concise, and stick to the goal of the documentation.
+- Write in US English with US grammar. (Tested in [`British.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/British.yml).)
+- Use [inclusive language](#inclusive-language).
+
+### 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).)
+
+### Capitalization
+
+#### Headings
+
+Use sentence case. For example:
+
+- `# Use variables to configure pipelines`
+- `## Use the To-Do List`
+
+#### UI text
+
+When referring to specific user interface text, like a button label or menu
+item, use the same capitalization that's 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's called for in this Documentation Style Guide.
+
+If you think there's 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:
+ - epics
+ - issues
+ - issue weights
+ - merge requests
+ - milestones
+ - reorder issues
+ - runner, runners, shared runners
+ - a to-do item (tested in [`ToDo.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/ToDo.yml))
+- *Some features are capitalized*, typically nouns naming GitLab-specific
+ capabilities or tools. For example:
+ - GitLab CI/CD
+ - Repository Mirroring
+ - Value Stream Analytics
+ - the To-Do List
+ - the Web IDE
+ - 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.
+
+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).)
+
+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 select **Log in**.
+
+### Inclusive language
+
+We strive to create documentation that's inclusive. This section includes
+guidance and examples for the following categories:
+
+- [Gender-specific wording](#avoid-gender-specific-wording).
+ (Tested in [`InclusionGender.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionGender.yml).)
+- [Ableist language](#avoid-ableist-language).
+ (Tested in [`InclusionAbleism.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionAbleism.yml).)
+- [Cultural sensitivity](#culturally-sensitive-language).
+ (Tested in [`InclusionCultural.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionCultural.yml).)
+
+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.
+
+Avoid the use of gender-specific pronouns, unless referring to a specific person.
+
+<!-- vale gitlab.InclusionGender = NO -->
+
+| Use | Avoid |
+|-----------------------------------|---------------------------------|
+| People, humanity | Mankind |
+| GitLab Team Members | Manpower |
+| You can install; They can install | He can install; She can install |
+
+<!-- vale gitlab.InclusionGender = YES -->
+
+If you need to set up [Fake user information](#fake-user-information), use
+diverse or non-gendered names with common surnames.
+
+#### Avoid ableist language
+
+Avoid terms that are also used in negative stereotypes for different groups.
+
+<!-- vale gitlab.InclusionAbleism = NO -->
+
+| Use | Avoid |
+|------------------------|----------------------|
+| Check for completeness | Sanity check |
+| Uncertain outliers | Crazy outliers |
+| Slows the service | Cripples the service |
+| Placeholder variable | Dummy variable |
+| Active/Inactive | Enabled/Disabled |
+| On/Off | Enabled/Disabled |
+
+<!-- vale gitlab.InclusionAbleism = YES -->
+
+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`.
+
+<!-- vale gitlab.InclusionCultural = NO -->
+
+| Use | Avoid |
+|----------------------|-----------------------|
+| Primary / secondary | Master / slave |
+| Allowlist / denylist | Blacklist / whitelist |
+
+<!-- vale gitlab.InclusionCultural = YES -->
+
+For more information see the following [Internet Draft specification](https://tools.ietf.org/html/draft-knodel-terminology-02).
+
+### Fake user information
+
+You may need to include user information in entries such as a REST call or user profile.
+_Do not_ use real user information or email addresses in GitLab documentation. For email
+addresses and names, do use:
+
+- _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 `Alex Garcia`.
+
+### Fake URLs
+
+When including sample URLs in the documentation, use:
+
+- `example.com` when the domain name is generic.
+- `gitlab.example.com` when referring to self-managed instances of GitLab.
+
+### 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.
+
+You can use the following fake tokens as examples:
+
+| Token type | Token value |
+|:----------------------|:-------------------------------------------------------------------|
+| Private user token | `<your_access_token>` |
+| Personal access token | `n671WNGecHugsdEDPsyo` |
+| Application ID | `2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6` |
+| Application secret | `04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df` |
+| CI/CD variable | `Li8j-mLUVA3eZYjPfd_H` |
+| Specific runner token | `yrnZW46BrtBFqM7xDzE7dddd` |
+| Shared runner token | `6Vk7ZsosqQyfreAxXTZr` |
+| Trigger token | `be20d8dcc028677c931e04f3871a9b` |
+| Webhook secret token | `6XhDroRcYPM5by_h-HLY` |
+| Health check token | `Tu7BgjR9qeZTEyRzGG2P` |
+| Request profile token | `7VgpS4Ax5utVD2esNstz` |
+
+### Language to avoid
+
+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.
+- 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_.
+ - When possible, stay user focused by writing in the second person (_you_ or
+ the imperative).
+- Don't overuse "that". In many cases, you can remove "that" from a sentence
+ and improve readability.
+- Avoid use of the future tense:
+ - Instead of "after you execute this command, GitLab will display the
+ result", use "after you execute this command, GitLab displays the result".
+ - Only use the future tense to convey when the action or result will actually
+ occur at a future time.
+- Don't use slashes to clump different words together or as a replacement for
+ the word "or":
+ - Instead of "and/or," consider using "or," or use another sensible
+ construction.
+ - Other examples include "clone/fetch," author/assignee," and
+ "namespace/repository name." Break apart any such instances in an
+ appropriate way.
+ - Exceptions to this rule include commonly accepted technical terms, such as
+ CI/CD and TCP/IP.
+<!-- vale gitlab.LatinTerms = NO -->
+- We discourage the use of Latin abbreviations and terms, such as _e.g._,
+ _i.e._, _etc._, or _via_, as even native users of English can misunderstand
+ those terms. (Tested in [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml).)
+ - Instead of _i.e._, use _that is_.
+ - Instead of _via_, use _through_.
+ - 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.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.
+- Avoid the using the word *scalability* with increasing GitLab's performance
+ for additional users. Using the words *scale* or *scaling* in other cases is
+ acceptable, but references to increasing GitLab's performance for additional
+ users should direct readers to the GitLab
+ [reference architectures](../../../administration/reference_architectures/index.md)
+ page.
+- Avoid all forms of the phrases *high availability* and *HA*, and instead
+ direct readers to the GitLab [reference architectures](../../../administration/reference_architectures/index.md)
+ for information about configuring GitLab to have the performance needed for
+ additional users over time.
+- Don't use profanity or obscenities. Doing so may negatively affect other
+ users and contributors, which is contrary to GitLab's value of
+ [Diversity, Inclusion, and Belonging](https://about.gitlab.com/handbook/values/#diversity-inclusion).
+- Avoid the use of [racially-insensitive terminology or phrases](https://www.marketplace.org/2020/06/17/tech-companies-update-language-to-avoid-offensive-terms/). For example:
+ - Use *primary* and *secondary* for database and server relationships.
+ - Use *allowlist* and *denylist* to describe access control lists.
+- Avoid the word _please_. For details, see the [Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/p/please).
+- Avoid words like _easily_, _simply_, _handy_, and _useful._ If the user
+ doesn't find the process to be these things, we lose their trust.
+
+### Word usage clarifications
+
+- Don't use "may" and "might" interchangeably:
+ - Use "might" to indicate the probability of something occurring. "If you
+ skip this step, the import process might fail."
+ - Use "may" to indicate giving permission for someone to do something, or
+ consider using "can" instead. "You may select either option on this
+ screen." Or, "You can select either option on this screen."
+
+### Contractions
+
+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 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 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. |
+
+- 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. |
+
+## 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.
+- 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:
+
+ ```markdown
+ ## Header
+
+ Paragraph.
+
+ - List item 1
+ - List item 2
+ ```
+
+### Emphasis
+
+- Use double asterisks (`**`) to mark a word or text in bold (`**bold**`).
+- Use underscore (`_`) for text in italics (`_italic_`).
+- Use greater than (`>`) for blockquotes.
+
+### Punctuation
+
+Follow these guidelines for punctuation:
+
+<!-- vale gitlab.Repetition = NO -->
+
+| 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 _or_ in a list of three or more items. (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._ |
+
+<!-- vale gitlab.Repetition = YES -->
+
+### Placeholder text
+
+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.
+
+For example:
+
+```shell
+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're 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).
+
+### Ordered vs. unordered lists
+
+Only use ordered lists when their items describe a sequence of steps to follow.
+
+Do:
+
+```markdown
+These are the steps to do something:
+
+1. First, do the first step.
+1. Then, do the next step.
+1. Finally, do the last step.
+```
+
+Don't:
+
+```markdown
+This is a list of available features:
+
+1. Feature 1
+1. Feature 2
+1. Feature 3
+```
+
+### 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.
+
+### Punctuation
+
+- Don't add commas (`,`) or semicolons (`;`) to the ends of list items.
+- Only add periods to the end of a list item if the item consists of a complete
+ sentence (with a subject and a verb).
+- 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
+ The list is as follows:
+
+ - First item: this explains the first item.
+ - Second item: this explains the second item.
+ ```
+
+**Examples:**
+
+Do:
+
+- First list item
+- Second list item
+- Third list item
+
+Don't:
+
+- First list item
+- Second list item
+- Third list item.
+
+Do:
+
+- Let's say this is a complete sentence.
+- Let's say this is also a complete sentence.
+- Not a complete sentence.
+
+Don't (vary use of periods; majority rules):
+
+- Let's say this is a complete sentence.
+- Let's say this is also a complete sentence.
+- Not a complete sentence
+
+### Nesting inside a list item
+
+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:
+
+````markdown
+- Unordered list item 1
+
+ A line nested using 2 spaces to align with the `U` above.
+
+- Unordered list item 2
+
+ > A quote block that will nest
+ > inside list item 2.
+
+- Unordered list item 3
+
+ ```plaintext
+ a codeblock that will next inside list item 3
+ ```
+
+- Unordered list item 4
+
+ ![an image that will nest inside list item 4](image.png)
+````
+
+For ordered lists, use three spaces for each level of indentation:
+
+````markdown
+1. Ordered list item 1
+
+ A line nested using 3 spaces to align with the `O` above.
+
+1. Ordered list item 2
+
+ > A quote block that will nest
+ > inside list item 2.
+
+1. Ordered list item 3
+
+ ```plaintext
+ a codeblock that will next inside list item 3
+ ```
+
+1. Ordered list item 4
+
+ ![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
+want to mix types, that's also possible, if you don't mix items at the same
+level:
+
+```markdown
+1. Ordered list item one.
+1. Ordered list item two.
+ - Nested unordered list item one.
+ - Nested unordered list item two.
+1. Ordered list item three.
+
+- Unordered list item one.
+- Unordered list item two.
+ 1. Nested ordered list item one.
+ 1. Nested ordered list item two.
+- Unordered list item three.
+```
+
+## Tables
+
+Tables should be used to describe complex information in a straightforward
+manner. Note that in many cases, an unordered list is sufficient to describe a
+list of items with a single, simple description per item. But, if you have data
+that's best described by a matrix, tables are the best choice.
+
+### Creation guidelines
+
+Due to accessibility and scannability requirements, tables should not have any
+empty cells. If there is no otherwise meaningful value for a cell, consider entering
+*N/A* (for 'not applicable') or *none*.
+
+To help tables be easier to maintain, consider adding additional spaces to the
+column widths to make them consistent. For example:
+
+```markdown
+| App name | Description | Requirements |
+|:---------|:---------------------|:---------------|
+| App 1 | Description text 1. | Requirements 1 |
+| App 2 | Description text 2. | None |
+```
+
+Consider installing a plugin or extension in your editor for formatting tables:
+
+- [Markdown Table Prettifier](https://marketplace.visualstudio.com/items?itemName=darkriszty.markdown-table-prettify) for Visual Studio Code
+- [Markdown Table Formatter](https://packagecontrol.io/packages/Markdown%20Table%20Formatter) for Sublime Text
+- [Markdown Table Formatter](https://atom.io/packages/markdown-table-formatter) for Atom
+
+### Feature tables
+
+When creating tables of lists of features (such as whether or not features are
+available to certain roles on the [Permissions](../../../user/permissions.md#project-members-permissions)
+page), use the following phrases (based on the SVG icons):
+
+| Option | Markdown | Displayed result |
+|--------|--------------------------|------------------------|
+| No | `**{dotted-circle}** No` | **{dotted-circle}** No |
+| Yes | `**{check-circle}** Yes` | **{check-circle}** Yes |
+
+## Quotes
+
+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".
+
+For other punctuation rules, refer to the
+[GitLab UX guide](https://design.gitlab.com/content/punctuation/).
+
+## Headings
+
+- Add _only one H1_ in each document, by adding `#` at the beginning of
+ it (when using Markdown). The `h1` will be the document `<title>`.
+- Start with an `h2` (`##`), and respect the order `h2` > `h3` > `h4` > `h5` > `h6`.
+ Never skip the hierarchy level, such as `h2` > `h4`
+- Avoid putting numbers in headings. Numbers shift, hence documentation anchor
+ links shift too, which eventually leads to dead links. If you think it is
+ compelling to add numbers in headings, make sure to at least discuss it with
+ 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.
+- 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.
+- 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 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.
+
+| 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 |
+
+For guidelines on capitalizing headings, see the section on [capitalization](#capitalization).
+
+NOTE: **Note:**
+If you change an existing title, be careful. These changes might affect not
+only [links](#anchor-links) within the page, but might also affect links to the
+GitLab documentation from both the GitLab application and external sites.
+
+### Anchor links
+
+Headings generate anchor links when rendered. `## This is an example` generates
+the anchor `#this-is-an-example`.
+
+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 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.
+- Do not link to `h1` headings.
+
+Note that, with Kramdown, it is possible to add a custom ID to an HTML element
+with Markdown markup, but they _do not_ work in GitLab's `/help`. Therefore,
+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 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.
+- 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).
+- How to [link to specific lines of code](#link-to-specific-lines-of-code)
+
+### 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]`.
+
+- 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)`,
+ write `Read more about [GitLab Issue Boards](LINK)`.
+
+### 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 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 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 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:
+
+- Use relative links to Markdown files in the same repository.
+- Do not use absolute URLs or URLs from `docs.gitlab.com`.
+- Use `../` to navigate to higher-level directories.
+- Don't prepend `./` to links to files or directories.
+- Don't link relative to root. For example, `/ee/user/gitlab_com/index.md`.
+
+ Don't:
+
+ - `https://docs.gitlab.com/ee/administration/geo/replication/troubleshooting.html`
+ - `/ee/administration/geo/replication/troubleshooting.md`
+ - `./troubleshooting.md`
+
+ Do: `../../geo/replication/troubleshooting.md`
+
+- Always add the file name `file.md` at the end of the link with the `.md`
+ extension, not `.html`.
+
+ Don't:
+
+ - `../../merge_requests/`
+ - `../../issues/tags.html`
+ - `../../issues/tags.html#stages`
+
+ Do:
+
+ - `../../merge_requests/index.md`
+ - `../../issues/tags.md`
+ - `../../issues/tags.md#stages`
+
+NOTE: **Note:**
+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.
+
+### 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.
+
+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/).
+- Books from an authoritative publisher.
+
+Examples of sources to avoid include:
+
+- Personal blog posts.
+- Wikipedia.
+- Non-trustworthy articles.
+- 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.
+
+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.
+
+### 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.
+
+These will fail for:
+
+- Those without sufficient permissions.
+- Automated link checkers.
+
+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 navigate to it.
+
+Example:
+
+```markdown
+For more information, see the [confidential issue](../../../user/project/issues/confidential_issues.md) `https://gitlab.com/gitlab-org/gitlab-foss/-/issues/<issue_number>`.
+```
+
+### 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.
+
+- _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 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
+
+When documenting navigation through the user interface:
+
+- Use the exact wording as shown in the UI, including any capital letters as-is.
+- Use bold text for navigation items and the char "greater than" (`>`) as a
+ separator. For example: `Navigate to your project's **Settings > CI/CD**`.
+- 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**`.
+
+### Navigational elements
+
+Use the following terms when referring to the main GitLab user interface
+elements:
+
+- **Top menu**: This is the top menu that spans the width of the user interface.
+ It includes the GitLab logo, search field, counters, and the user's avatar.
+- **Left sidebar**: This is the navigation sidebar on the left of the user
+ interface, specific to the project or group.
+- **Right sidebar**: This is the navigation sidebar on the right of the user
+ interface, specific to the open issue, merge request, or epic.
+
+## 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.
+
+### 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.
+
+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 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
+
+- Save the image with a lowercase file name that's descriptive of the feature
+ or concept in the image. If the image is of the GitLab interface, append the
+ GitLab version to the file name, based on the following format:
+ `image_name_vX_Y.png`. For example, for a screenshot taken from the pipelines
+ page of GitLab 11.1, a valid name is `pipelines_v11_1.png`. If you're adding an
+ illustration that doesn't include parts of the user interface, add the release
+ number corresponding to the release the image was added to; for an MR added to
+ 11.1's milestone, a valid name for an illustration is `devops_diagram_v11_1.png`.
+- Place images in a separate directory named `img/` in the same directory where
+ the `.md` document that you're working on is located.
+- Consider using PNG images instead of JPEG.
+- [Compress all PNG images](#compress-images).
+- Compress gifs with <https://ezgif.com/optimize> or similar tool.
+- 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
+ 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
+documentation site. For accessibility and SEO, use [descriptions](https://webaim.org/techniques/alttext/)
+that:
+
+- Are accurate, succinct, and unique.
+- Don't use _image of…_ or _graphic of…_ to describe the image.
+
+### Compress images
+
+You should always compress any new images you add to the documentation. One
+known tool is [`pngquant`](https://pngquant.org/), which is cross-platform and
+open source. Install it by visiting the official website and following the
+instructions for your OS.
+
+GitLab has a [Rake task](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/tasks/pngquant.rake)
+that you can use to automate the process. In the root directory of your local
+copy of `https://gitlab.com/gitlab-org/gitlab`, run in a terminal:
+
+- Before compressing, if you want, check that all documentation PNG images have
+ been compressed:
+
+ ```shell
+ bundle exec rake pngquant:lint
+ ```
+
+- Compress all documentation PNG images using `pngquant`:
+
+ ```shell
+ bundle exec rake pngquant:compress
+ ```
+
+The only caveat is that the task runs on all images under `doc/`, not only the
+ones you might have included in a merge request. In that case, you can run the
+compress task and only commit the images that are relevant to your merge
+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.
+
+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 scan the page
+for videos before reading:
+
+```markdown
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For an overview, see [Video Title](link-to-video).
+```
+
+You can link any up-to-date video that's useful to the GitLab user.
+
+### Embed videos
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/472) in GitLab 12.1.
+
+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).
+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.
+
+To embed a video:
+
+1. Copy the code from this procedure 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, select **Share**, and then select **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
+ `iframe` tag.
+
+```html
+leave a blank line here
+<div class="video-fallback">
+ See the video: <a href="https://www.youtube.com/watch?v=MqL6BMOySIQ">Video title</a>.
+</div>
+<figure class="video-container">
+ <iframe src="https://www.youtube.com/embed/MqL6BMOySIQ" frameborder="0" allowfullscreen="true"> </iframe>
+</figure>
+leave a blank line here
+```
+
+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>.
+</div>
+<figure class="video-container">
+ <iframe src="https://www.youtube.com/embed/MqL6BMOySIQ" frameborder="0" allowfullscreen="true"> </iframe>
+</figure>
+
+> 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 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 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 do it
+ with the button on code blocks.
+- HTTP methods (`HTTP POST`) and HTTP status codes, both full (`404 File Not Found`)
+ and abbreviated (`404`), should be wrapped in inline code blocks when used in sentences.
+ For example: Send a `DELETE` request to delete the runner. Send a `POST` request to create one.
+- 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 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:
+
+ ````markdown
+ ```ruby
+ Ruby code
+ ```
+
+ ```javascript
+ JavaScript code
+ ```
+
+ ```markdown
+ [Markdown code example](example.md)
+ ```
+
+ ```plaintext
+ Code or text for which no specific highlighting class is 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 |
+|-------------------------|------------------------------------------------------------------------------|
+| `asciidoc` | |
+| `dockerfile` | Alias: `docker`. |
+| `elixir` | |
+| `erb` | |
+| `golang` | Alias: `go`. |
+| `graphql` | |
+| `haml` | |
+| `html` | |
+| `ini` | For some simple config files that are not in TOML format. |
+| `javascript` | Alias `js`. |
+| `json` | |
+| `markdown` | Alias: `md`. |
+| `mermaid` | |
+| `nginx` | |
+| `perl` | |
+| `php` | |
+| `plaintext` | Examples with no defined language, such as output from shell commands or API calls. If a codeblock has no language, it defaults to `plaintext`. Alias: `text`. |
+| `prometheus` | Prometheus configuration examples. |
+| `python` | |
+| `ruby` | Alias: `rb`. |
+| `shell` | Aliases: `bash` or `sh`. |
+| `sql` | |
+| `toml` | Runner configuration examples, and other TOML-formatted configuration files. |
+| `typescript` | Alias: `ts`. |
+| `xml` | |
+| `yaml` | Alias: `yml`. |
+
+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.
+
+This way, you can achieve a consistent look when writing about interacting with
+GitLab user interface elements.
+
+Usage examples:
+
+- Icon with default size (16px): `**{icon-name}**`
+
+ Example: `**{tanuki}**` renders as: **{tanuki}**.
+- Icon with custom size: `**{icon-name, size}**`
+
+ Available sizes (in px): 8, 10, 12, 14, 16, 18, 24, 32, 48, and 72
+
+ 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 documentation CSS.
+
+ Example with `float-right`, a
+ [Bootstrap utility class](https://getbootstrap.com/docs/4.4/utilities/float/):
+ `**{tanuki, 32, float-right}**` renders as: **{tanuki, 32, float-right}**
+
+### When to use icons
+
+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:
+
+```markdown
+1. Go to **{home}** **Project overview > Details**
+```
+
+1. Go to **{home}** **Project overview > Details**
+
+However, the following might help the reader connect the text to the user
+interface:
+
+```markdown
+| Section | Description |
+|:-------------------------|:----------------------------------------------------------------------------------------------------------------------------|
+| **{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. |
+| **{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 yourself having to describe an interface element. For
+example:
+
+- Do: Select the Admin Area icon ( **{admin}** ).
+- Don't: Select the Admin Area icon (the wrench icon).
+
+## Alert boxes
+
+When you need to call special attention to particular sentences, use the
+following markup to create highlighted alert boxes.
+
+Alert boxes work for one paragraph only. Multiple paragraphs, lists, and headers
+won't render correctly. For multiple lines, use [blockquotes](#blockquotes)
+instead.
+
+Alert boxes render only on the GitLab documentation site (<https://docs.gitlab.com>).
+In the GitLab product help, alert boxes appear as plain Markdown text.
+
+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 indicate additional information that's of special use to the reader.
+Notes are most effective when used _sparingly_.
+
+Try to avoid them. Too many notes can impact the scannability of a topic and
+create an overly busy page.
+
+Instead of adding a note, try one of these alternatives:
+
+- Re-write the sentence as part of the most-relevant paragraph.
+- Put the information into its own standalone paragraph.
+- Put the content under a new subheading that introduces the topic, which makes
+ it more visible.
+
+If you must use a note, use the following formatting:
+
+```markdown
+NOTE: **Note:**
+This is something to note.
+```
+
+How it renders on the GitLab documentation site:
+
+NOTE: **Note:**
+This is something to note.
+
+### Tip
+
+```markdown
+TIP: **Tip:**
+This is a tip.
+```
+
+How it renders on the GitLab documentation site:
+
+TIP: **Tip:**
+This is a tip.
+
+### Caution
+
+```markdown
+CAUTION: **Caution:**
+This is something to be cautious about.
+```
+
+How it renders on the GitLab documentation site:
+
+CAUTION: **Caution:**
+This is something to be cautious about.
+
+### Danger
+
+```markdown
+DANGER: **Warning:**
+This is a breaking change, a bug, or something very important to note.
+```
+
+How it renders on the GitLab documentation site:
+
+DANGER: **Warning:**
+This is a breaking change, a bug, or something very important to note.
+
+## Blockquotes
+
+For highlighting a text within a blue blockquote, use this format:
+
+```markdown
+> This is a blockquote.
+```
+
+which renders on the [GitLab documentation site](https://docs.gitlab.com) as:
+
+> This is a blockquote.
+
+If the text spans across multiple lines it's OK to split the line.
+
+For multiple paragraphs, use the symbol `>` before every line:
+
+```markdown
+> This is the first paragraph.
+>
+> This is the second paragraph.
+>
+> - This is a list item
+> - Second item in the list
+```
+
+Which renders to:
+
+> This is the first paragraph.
+>
+> This is the second paragraph.
+>
+> - This is a list item
+> - Second item in the list
+
+## 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:
+
+- 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_.
+
+Examples:
+
+- "We prefer GitLab merge requests".
+- "Open a merge request to fix a broken link".
+- "After you open a merge request (MR), submit your MR for review and approval".
+
+### Describe UI elements
+
+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`.
+
+### Verbs for UI elements
+
+The following are recommended verbs for specific uses with user interface
+elements:
+
+| Recommended | Used for | Replaces |
+|:--------------------|:--------------------------------------|:---------------------------|
+| _select_ | buttons, links, menu items, dropdowns | "click, "press," "hit" |
+| _select_ or _clear_ | checkboxes | "enable", "click", "press" |
+| _expand_ | expandable sections | "open" |
+
+### Other Verbs
+
+| Recommended | Used for | Replaces |
+|:------------|:--------------------------------|:----------------------|
+| _go to_ | making a browser go to location | "navigate to", "open" |
+
+## GitLab versions and tiers
+
+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 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.
+
+### Text for documentation requiring version text
+
+When a feature is new or updated, you can add version information as a bulleted
+item in the **Version history**, or as an inline reference with related text.
+
+#### Version text in the **Version History**
+
+If all content in a section is related, add version text following the header for
+the section. Each entry should be on a single line. To render correctly, it must be on its
+own line and surrounded by blank lines.
+
+Features should declare the GitLab version that introduced a feature in a blockquote
+following the header:
+
+```markdown
+## Feature name
+
+> Introduced in GitLab 11.3.
+
+This feature does something.
+```
+
+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:
+
+```markdown
+> [Introduced](<link-to-issue>) in GitLab 11.3.
+```
+
+If the feature is only available in GitLab Enterprise Edition, mention
+the [paid tier](https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/)
+the feature is available in:
+
+```markdown
+> [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:
+
+```markdown
+> - [Introduced](<link-to-issue>) in GitLab 11.3.
+> - Enabled by default in GitLab 11.4.
+```
+
+If a feature is moved to another tier:
+
+```markdown
+> - [Introduced](<link-to-issue>) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.5.
+> - [Moved](<link-to-issue>) to [GitLab Starter](https://about.gitlab.com/pricing/) in 11.8.
+> - [Moved](<link-to-issue>) to GitLab Core in 12.0.
+```
+
+If a feature is deprecated, include a link to a replacement (when available):
+
+```markdown
+> - [Deprecated](<link-to-issue>) in GitLab 11.3. Replaced by [meaningful text](<link-to-appropriate-documentation>).
+```
+
+You can also 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:
+
+```markdown
+DANGER: **Deprecated:**
+This feature was [deprecated](link-to-issue) in GitLab 12.3
+and replaced by [Feature name](link-to-feature-documentation).
+```
+
+#### Inline version text
+
+If you're adding content to an existing topic, you can add version information
+inline with the existing text.
+
+In this case, add `([introduced/deprecated](<link-to-issue>) in GitLab X.X)`.
+If applicable, include the paid tier: `([introduced/deprecated](<link-to-issue>) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4)`
+
+Including the issue link is encouraged, but isn't a requirement. For example:
+
+```markdown
+The voting strategy (in GitLab 13.4 and later) requires
+the primary and secondary voters to agree.
+```
+
+#### End-of-life for features or products
+
+Whenever a feature or product enters the end-of-life process, indicate its
+status by using the `Danger` [alert](#alert-boxes) with the `**Important**`
+keyword directly below the feature or product's header (which can include H1
+page titles). Link to the deprecation and removal issues, if possible.
+
+For example:
+
+```markdown
+DANGER: **Important:**
+This feature is in its end-of-life process. It is [deprecated](link-to-issue)
+for use in GitLab X.X, and is planned for [removal](link-to-issue) in GitLab X.X.
+```
+
+### 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_.
+
+For example:
+
+- Available in GitLab 12.3 and earlier.
+- Available in GitLab 12.4 and later.
+- In GitLab 11.4 and earlier, ...
+- In GitLab 10.6 and later, ...
+
+### 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.
+Also, they can know 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.
+
+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
+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 documentation.
+
+## Products and features
+
+Refer to the information in this section when describing products and features
+within the GitLab product documentation.
+
+### Avoid line breaks in names
+
+When entering a product or feature name that includes a space (such as
+GitLab Community Edition) or even other companies' products (such as
+Amazon Web Services), be sure to not split the product or feature name across
+lines with an inserted line break. Splitting product or feature names across
+lines makes searching for these items more difficult, and can cause problems if
+names change.
+
+For example, the following Markdown content is _not_ formatted correctly:
+
+```markdown
+When entering a product or feature name that includes a space (such as GitLab
+Community Edition), don't split the product or feature name across lines.
+```
+
+Instead, it should appear similar to the following:
+
+```markdown
+When entering a product or feature name that includes a space (such as
+GitLab Community Edition), don't split the product or feature name across lines.
+```
+
+### Product badges
+
+When a feature is available in paid tiers, add the corresponding tier to the
+header or other page element according to the feature's availability:
+
+| Tier in which feature is available | Tier markup |
+|:-----------------------------------------------------------------------|:----------------------|
+| GitLab Core and GitLab.com Free, and their higher tiers | `**(CORE)**` |
+| GitLab Starter and GitLab.com Bronze, and their higher tiers | `**(STARTER)**` |
+| GitLab Premium and GitLab.com Silver, and their higher tiers | `**(PREMIUM)**` |
+| GitLab Ultimate and GitLab.com Gold | `**(ULTIMATE)**` |
+| _Only_ GitLab Core and higher tiers (no GitLab.com-based tiers) | `**(CORE ONLY)**` |
+| _Only_ GitLab Starter and higher tiers (no GitLab.com-based tiers) | `**(STARTER ONLY)**` |
+| _Only_ GitLab Premium and higher tiers (no GitLab.com-based tiers) | `**(PREMIUM ONLY)**` |
+| _Only_ GitLab Ultimate (no GitLab.com-based tiers) | `**(ULTIMATE ONLY)**` |
+| _Only_ GitLab.com Free and higher tiers (no self-managed instances) | `**(FREE ONLY)**` |
+| _Only_ GitLab.com Bronze and higher tiers (no self-managed instances) | `**(BRONZE ONLY)**` |
+| _Only_ GitLab.com Silver and higher tiers (no self-managed instances) | `**(SILVER ONLY)**` |
+| _Only_ GitLab.com Gold (no self-managed instances) | `**(GOLD ONLY)**` |
+
+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.
+
+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)**
+- `**(SILVER ONLY)**` displays as **(SILVER ONLY)**
+
+#### How it works
+
+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.
+
+## Specific sections
+
+Certain styles should be applied to specific sections. Styles for specific
+sections are outlined in this section.
+
+### 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
+[`doc/administration/restart_gitlab.md`](../../../administration/restart_gitlab.md).
+Usually the text will read like:
+
+```markdown
+Save the file and [reconfigure GitLab](../../../administration/restart_gitlab.md)
+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/ee/administration/restart_gitlab.html`. Replace
+`reconfigure` with `restart` where appropriate.
+
+### Installation guide
+
+**Ruby:**
+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).
+
+### Configuration documentation for source and Omnibus installations
+
+GitLab currently officially supports two installation methods: installations
+from source and Omnibus packages installations.
+
+Whenever there's a setting that's configurable for both installation methods,
+the preference is to document it in the CE documentation to avoid duplication.
+
+Configuration settings include:
+
+- Settings that touch configuration files in `config/`.
+- NGINX settings and settings in `lib/support/` in general.
+
+When you document a list of steps, it may entail editing the configuration file
+and reconfiguring or restarting GitLab. In that case, use these styles:
+
+````markdown
+**For Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ 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.
+
+---
+
+**For installations from source**
+
+1. Edit `config/gitlab.yml`:
+
+ ```yaml
+ gitlab:
+ 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.
+````
+
+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.
+- 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 or reconfigure of GitLab.
+
+### Troubleshooting
+
+For troubleshooting sections, you should provide as much context as possible so
+users can identify the problem they are facing and resolve it on their own. You
+can facilitate this by making sure the troubleshooting content addresses:
+
+1. The problem the user needs to solve.
+1. How the user can confirm they have the problem.
+1. Steps the user can take towards resolution of the problem.
+
+If the contents of each category can be summarized in one line and a list of
+steps aren't required, consider setting up a [table](#tables) 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).
diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md
new file mode 100644
index 00000000000..043da38d207
--- /dev/null
+++ b/doc/development/documentation/testing.md
@@ -0,0 +1,292 @@
+---
+stage: none
+group: Documentation Guidelines
+info: 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 contribute to GitLab Documentation.
+---
+
+# Documentation testing
+
+We treat documentation as code, and so use tests in our CI pipeline to maintain the
+standards and quality of the docs. The current tests, which run in CI jobs when a
+merge request with new or changed docs is submitted, are:
+
+- [`docs lint`](https://gitlab.com/gitlab-org/gitlab/-/blob/0b562014f7b71f98540e682c8d662275f0011f2f/.gitlab/ci/docs.gitlab-ci.yml#L41):
+ Runs several tests on the content of the docs themselves:
+ - [`lint-doc.sh` script](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/lint-doc.sh)
+ runs the following checks and linters:
+ - All cURL examples use the long flags (ex: `--header`, not `-H`).
+ - The `CHANGELOG.md` does not contain duplicate versions.
+ - No files in `doc/` are executable.
+ - No new `README.md` was added.
+ - [markdownlint](#markdownlint).
+ - [Vale](#vale).
+ - Nanoc tests:
+ - [`internal_links`](https://gitlab.com/gitlab-org/gitlab/-/blob/0b562014f7b71f98540e682c8d662275f0011f2f/.gitlab/ci/docs.gitlab-ci.yml#L58)
+ checks that all internal links (ex: `[link](../index.md)`) are valid.
+ - [`internal_anchors`](https://gitlab.com/gitlab-org/gitlab/-/blob/0b562014f7b71f98540e682c8d662275f0011f2f/.gitlab/ci/docs.gitlab-ci.yml#L60)
+ checks that all internal anchors (ex: `[link](../index.md#internal_anchor)`)
+ are valid.
+ - [`ui-docs-links lint`](https://gitlab.com/gitlab-org/gitlab/-/blob/0b562014f7b71f98540e682c8d662275f0011f2f/.gitlab/ci/docs.gitlab-ci.yml#L62)
+ checks that all links to docs from UI elements (`app/views` files, for example)
+ are linking to valid docs and anchors.
+
+## Run tests locally
+
+Apart from [previewing your changes locally](index.md#previewing-the-changes-live), you can also run all lint checks
+and Nanoc tests locally.
+
+### Lint checks
+
+Lint checks are performed by the [`lint-doc.sh`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/lint-doc.sh)
+script and can be executed as follows:
+
+1. Navigate to the `gitlab` directory.
+1. Run:
+
+ ```shell
+ MD_DOC_PATH=path/to/my_doc.md scripts/lint-doc.sh
+ ```
+
+Where `MD_DOC_PATH` points to the file or directory you would like to run lint checks for.
+If you omit it completely, it defaults to the `doc/` directory.
+The output should be similar to:
+
+```plaintext
+=> Linting documents at path /path/to/gitlab as <user>...
+=> Checking for cURL short options...
+=> Checking for CHANGELOG.md duplicate entries...
+=> Checking /path/to/gitlab/doc for executable permissions...
+=> Checking for new README.md files...
+=> Linting markdown style...
+=> Linting prose...
+✔ 0 errors, 0 warnings and 0 suggestions in 1 file.
+✔ Linting passed
+```
+
+This requires you to either:
+
+- Have the required lint tools installed on your machine.
+- A working Docker installation, in which case an image with these tools pre-installed is used.
+
+### Nanoc tests
+
+To execute Nanoc tests locally:
+
+1. Navigate to the [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs) directory.
+1. Run:
+
+ ```shell
+ # Check for broken internal links
+ bundle exec nanoc check internal_links
+
+ # Check for broken external links (might take a lot of time to complete).
+ # This test is set to be allowed to fail and is run only in the gitlab-docs project CI
+ bundle exec nanoc check internal_anchors
+ ```
+
+### `ui-docs-links` test
+
+The `ui-docs-links lint` job uses `haml-lint` to test that all links to docs from
+UI elements (`app/views` files, for example) are linking to valid docs and anchors.
+
+To run the `ui-docs-links` test locally:
+
+1. Open the `gitlab` directory in a terminal window.
+1. Run:
+
+ ```shell
+ bundle exec haml-lint -i DocumentationLinks
+ ```
+
+If you receive an error the first time you run this test, run `bundle install`, which
+installs GitLab's dependencies, and try again.
+
+If you don't want to install all of GitLab's dependencies to test the links, you can:
+
+1. Open the `gitlab` directory in a terminal window.
+1. Install `haml-lint`:
+
+ ```shell
+ gem install haml_lint
+ ```
+
+1. Run:
+
+ ```shell
+ haml-lint -i DocumentationLinks
+ ```
+
+If you manually install `haml-lint` with this process, it does not update automatically
+and you should make sure your version matches the version used by GitLab.
+
+## Local linters
+
+To help adhere to the [documentation style guidelines](styleguide/index.md), and improve the content
+added to documentation, [install documentation linters](#install-linters) and
+[integrate them with your code editor](#configure-editors).
+
+At GitLab, we mostly use:
+
+- [markdownlint](#markdownlint)
+- [Vale](#vale)
+
+### markdownlint
+
+[markdownlint](https://github.com/DavidAnson/markdownlint) checks that Markdown syntax follows
+[certain rules](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#rules), and is
+used by the `docs-lint` test.
+
+Our [Documentation Style Guide](styleguide/index.md#markdown) and
+[Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/) elaborate on which choices must
+be made when selecting Markdown syntax for GitLab documentation. This tool helps catch deviations
+from those guidelines.
+
+markdownlint configuration is found in the following projects:
+
+- [`gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/.markdownlint.json)
+- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/.markdownlint.json)
+- [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/.markdownlint.json)
+- [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/.markdownlint.json)
+- [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/.markdownlint.json)
+
+This configuration is also used within build pipelines.
+
+You can use markdownlint:
+
+- [On the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--).
+- [Within a code editor](#configure-editors).
+- [In a `pre-push` hook](#configure-pre-push-hooks).
+
+### Vale
+
+[Vale](https://errata-ai.gitbook.io/vale/) is a grammar, style, and word usage linter for the
+English language. Vale's configuration is stored in the
+[`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/blob/master/.vale.ini) file located in the root
+directory of projects.
+
+Vale supports creating [custom tests](https://errata-ai.github.io/vale/styles/) that extend any of
+several types of checks, which we store in the `.linting/vale/styles/gitlab` directory within the
+documentation directory of projects.
+
+Vale configuration is found in the following projects:
+
+- [`gitlab`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.vale/gitlab)
+- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/master/docs/.vale/gitlab)
+- [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/tree/master/doc/.vale/gitlab)
+- [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/tree/master/doc/.vale/gitlab)
+- [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/master/doc/.vale/gitlab)
+
+This configuration is also used within build pipelines.
+
+You can use Vale:
+
+- [On the command line](https://errata-ai.gitbook.io/vale/getting-started/usage).
+- [Within a code editor](#configure-editors).
+- [In a Git hook](#configure-pre-push-hooks). Vale only reports errors in the Git hook (the same
+ configuration as the CI/CD pipelines), and does not report suggestions or warnings.
+
+### Install linters
+
+At a minimum, install [markdownlint](#markdownlint) and [Vale](#vale) to match the checks run in
+build pipelines:
+
+1. Install `markdownlint-cli`, using either:
+
+ - `npm`:
+
+ ```shell
+ npm install -g markdownlint-cli
+ ```
+
+ - `yarn`:
+
+ ```shell
+ yarn global add markdownlint-cli
+ ```
+
+ We recommend installing the version of `markdownlint-cli` currently used in the documentation
+ linting [Docker image](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/.gitlab-ci.yml#L420).
+
+1. Install [`vale`](https://github.com/errata-ai/vale/releases). For example, to install using
+ `brew` for macOS, run:
+
+ ```shell
+ brew install vale
+ ```
+
+ We recommend installing the version of Vale currently used in the documentation linting
+ [Docker image](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/.gitlab-ci.yml#L419).
+
+In addition to using markdownlint and Vale at the command line, these tools can be
+[integrated with your code editor](#configure-editors).
+
+### Configure editors
+
+To configure markdownlint within your editor, install one of the following as appropriate:
+
+- [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint)
+- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint)
+- [Atom](https://atom.io/packages/linter-node-markdownlint)
+- [Vim](https://github.com/dense-analysis/ale)
+
+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 [`errata-ai.vale-server` extension](https://marketplace.visualstudio.com/items?itemName=errata-ai.vale-server).
+ You don't need Vale Server to use the plugin. You can configure the plugin to
+ [display only a subset of alerts](#show-subset-of-vale-alerts).
+- [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).
+
+### Configure pre-push hooks
+
+Git [pre-push hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) allow Git users to:
+
+- Run tests or other processes before pushing a branch.
+- Avoid pushing a branch if failures occur with these tests.
+
+[`lefthook`](https://github.com/Arkweid/lefthook) is a Git hooks manager, making configuring,
+installing, and removing Git hooks easy.
+
+Configuration for `lefthook` is available in the [`lefthook.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lefthook.yml)
+file for the [`gitlab`](https://gitlab.com/gitlab-org/gitlab) project.
+
+To set up `lefthook` for documentation linting, see
+[Pre-push static analysis](../contributing/style_guides.md#pre-push-static-analysis).
+
+### Show subset of Vale alerts
+
+You can set Visual Studio Code to display only a subset of Vale alerts when viewing files:
+
+1. Go to **Preferences > Settings > Extensions > Vale**.
+1. In **Vale CLI: Min Alert Level**, select the minimum alert level you want displayed in files.
+
+To display only a subset of Vale alerts when running Vale from the command line, use
+the `--minAlertLevel` flag, which accepts `error`, `warning`, or `suggestion`. Combine it with `--config`
+to point to the configuration file within the project, if needed:
+
+```shell
+vale --config .vale.ini --minAlertLevel error doc/**/*.md
+```
+
+Omit the flag to display all alerts, including `suggestion` level alerts.
+
+### Disable Vale tests
+
+You can disable a specific Vale linting rule or all Vale linting rules for any portion of a
+document:
+
+- To disable a specific rule, add a `<!-- vale gitlab.rulename = NO -->` tag before the text, and a
+ `<!-- vale gitlab.rulename = YES -->` tag after the text, replacing `rulename` with the filename
+ of a test in the
+ [GitLab styles](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.linting/vale/styles/gitlab)
+ directory.
+- 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).
+
+For more information, see
+[Vale's documentation](https://errata-ai.gitbook.io/vale/getting-started/markup#markup-based-configuration).
diff --git a/doc/development/documentation/workflow.md b/doc/development/documentation/workflow.md
index 488c71a6328..9bc80116d25 100644
--- a/doc/development/documentation/workflow.md
+++ b/doc/development/documentation/workflow.md
@@ -1,10 +1,15 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Documentation process
The process for creating and maintaining GitLab product documentation allows
anyone to contribute a merge request or create an issue for GitLab's
documentation.
-NOTE: **Note:**
Documentation updates relating to new features or feature enhancements must
use the [feature workflow process](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#for-a-product-change) described in the GitLab Handbook.
@@ -53,7 +58,7 @@ To update GitLab documentation:
[GitLab Documentation guidelines](index.md) page.
1. Follow the described standards and processes listed on the page, including:
- The [Structure and template](structure.md) page.
- - The [Style Guide](styleguide.md).
+ - The [Style Guide](styleguide/index.md).
- The [Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/).
1. Follow GitLab's [Merge Request Guidelines](../contributing/merge_request_workflow.md#merge-request-guidelines).
@@ -82,7 +87,7 @@ Anyone with Maintainer access to the relevant GitLab project can merge documenta
Maintainers must make a good-faith effort to ensure that the content:
- Is clear and sufficiently easy for the intended audience to navigate and understand.
-- Meets the [Documentation Guidelines](index.md) and [Style Guide](styleguide.md).
+- Meets the [Documentation Guidelines](index.md) and [Style Guide](styleguide/index.md).
If the author or reviewer has any questions, they can mention the writer who is assigned to the relevant
[DevOps stage group](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments).
@@ -149,16 +154,15 @@ Remember:
Ensure the following if skipping an initial Technical Writer review:
-- That [product badges](styleguide.md#product-badges) are applied.
-- That the GitLab [version](styleguide.md#text-for-documentation-requiring-version-text) that
+- That [product badges](styleguide/index.md#product-badges) are applied.
+- That the GitLab [version](styleguide/index.md#text-for-documentation-requiring-version-text) that
introduced the feature has been included.
- That changes to headings don't affect in-app hyperlinks.
- Specific [user permissions](../../user/permissions.md) are documented.
- That new documents are linked from higher-level indexes, for discoverability.
- Style guide is followed:
- - For [directories and files](styleguide.md#work-with-directories-and-files).
- - For [images](styleguide.md#images).
+ - For [directories and files](styleguide/index.md#work-with-directories-and-files).
+ - For [images](styleguide/index.md#images).
-NOTE: **Note:**
Merge requests that change the location of documentation must always be reviewed by a Technical
Writer prior to merging.
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index 01f9d9b16fb..26a1e9ec3aa 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -1,9 +1,15 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Guidelines for implementing Enterprise Edition features
- **Write the code and the tests.**: As with any code, EE features should have
good test coverage to prevent regressions.
- **Write documentation.**: Add documentation to the `doc/` directory. Describe
- the feature and include screenshots, if applicable. Indicate [what editions](documentation/styleguide.md#product-badges)
+ the feature and include screenshots, if applicable. Indicate [what editions](documentation/styleguide/index.md#product-badges)
the feature applies to.
- **Submit a MR to the `www-gitlab-com` project.**: Add the new feature to the
[EE features list](https://about.gitlab.com/features/).
@@ -426,6 +432,38 @@ module EE
end
```
+### Code in `app/graphql/`
+
+EE-specific mutations, resolvers, and types should be added to
+`ee/app/graphql/{mutations,resolvers,types}`.
+
+To override a CE mutation, resolver, or type, create the file in
+`ee/app/graphql/ee/{mutations,resolvers,types}` and add new code to a
+`prepended` block.
+
+For example, if CE has a mutation called `Mutations::Tanukis::Create` and you
+wanted to add a new argument, place the EE override in
+`ee/app/graphql/ee/mutations/tanukis/create.rb`:
+
+```ruby
+module EE
+ module Mutations
+ module Tanukis
+ module Create
+ extend ActiveSupport::Concern
+
+ prepended do
+ argument :name,
+ GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Tanuki name'
+ end
+ end
+ end
+ end
+end
+```
+
#### Using `render_if_exists`
Instead of using regular `render`, we should use `render_if_exists`, which
@@ -535,7 +573,7 @@ constants.
#### EE parameters
-We can define `params` and utilize `use` in another `params` definition to
+We can define `params` and use `use` in another `params` definition to
include parameters defined in EE. However, we need to define the "interface" first
in CE in order for EE to override it. We don't have to do this in other places
due to `prepend_if_ee`, but Grape is complex internally and we couldn't easily
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
index 639759e5014..cde221aaf16 100644
--- a/doc/development/elasticsearch.md
+++ b/doc/development/elasticsearch.md
@@ -184,6 +184,38 @@ If the current version is `v12p1`, and we need to create a new version for `v12p
1. Change the namespace for files under `v12p1` folder from `Latest` to `V12p1`
1. Make changes to files under the `latest` folder as needed
+## Creating a new Global Search migration
+
+> This functionality was introduced by [#234046](https://gitlab.com/gitlab-org/gitlab/-/issues/234046).
+
+NOTE: **Note:**
+This only supported for indices created with GitLab 13.0 or greater.
+
+Migrations are stored in the [`ee/elastic/migrate/`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/elastic/migrate) folder with `YYYYMMDDHHMMSS_migration_name.rb`
+file name format, which is similar to Rails database migrations:
+
+```ruby
+# frozen_string_literal: true
+
+class MigrationName < Elastic::Migration
+ # Important: Any update to the Elastic index mappings should be replicated in Elastic::Latest::Config
+
+ def migrate
+ end
+
+ # Check if the migration has completed
+ # Return true if completed, otherwise return false
+ def completed?
+ end
+end
+```
+
+Applied migrations are stored in `gitlab-#{RAILS_ENV}-migrations` index. All unexecuted migrations
+are applied by the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb)
+cron worker sequentially.
+
+Any update to the Elastic index mappings should be replicated in [`Elastic::Latest::Config`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/elastic/latest/config.rb).
+
## Performance Monitoring
### Prometheus
@@ -234,7 +266,7 @@ which is useful to diagnose why a search might be slow.
### Correlation ID and `X-Opaque-Id`
Our [correlation
-ID](./distributed_tracing.md#developer-guidelines-for-working-with-correlation-ids)
+ID](distributed_tracing.md#developer-guidelines-for-working-with-correlation-ids)
is forwarded by all requests from Rails to Elasticsearch as the
[`X-Opaque-Id`](https://www.elastic.co/guide/en/elasticsearch/reference/current/tasks.html#_identifying_running_tasks)
header which allows us to track any
diff --git a/doc/development/emails.md b/doc/development/emails.md
index de9607fef64..4b43bff0e02 100644
--- a/doc/development/emails.md
+++ b/doc/development/emails.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Dealing with email in development
## Ensuring compatibility with mailer Sidekiq jobs
diff --git a/doc/development/experiment_guide/index.md b/doc/development/experiment_guide/index.md
index 18b606450c2..3b2f1d21463 100644
--- a/doc/development/experiment_guide/index.md
+++ b/doc/development/experiment_guide/index.md
@@ -1,3 +1,9 @@
+---
+stage: Growth
+group: Activation
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Experiment Guide
Experiments can be conducted by any GitLab team, most often the teams from the [Growth Sub-department](https://about.gitlab.com/handbook/engineering/development/growth/). Experiments are not tied to releases because they will primarily target GitLab.com.
@@ -32,7 +38,7 @@ addressed.
## How to create an A/B test
-### Implementation
+### Implement the experiment
1. Add the experiment to the `Gitlab::Experimentation::EXPERIMENTS` hash in [`experimentation.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib%2Fgitlab%2Fexperimentation.rb):
@@ -44,7 +50,7 @@ addressed.
# Add your experiment here:
signup_flow: {
environment: ::Gitlab.dev_env_or_com?, # Target environment, defaults to enabled for development and GitLab.com
- tracking_category: 'Growth::Acquisition::Experiment::SignUpFlow' # Used for providing the category when setting up tracking data
+ tracking_category: 'Growth::Activation::Experiment::SignUpFlow' # Used for providing the category when setting up tracking data
}
}.freeze
```
@@ -105,8 +111,131 @@ addressed.
end
```
-1. Track necessary events. See the [product analytics guide](../product_analytics/index.md) for details.
-1. After the merge request is merged, use [`chatops`](../../ci/chatops/README.md) in the
+### Implement the tracking events
+
+To determine whether the experiment is a success or not, we must implement tracking events
+to acquire data for analyzing. We can send events to Snowplow via either the backend or frontend.
+Read the [product analytics guide](https://about.gitlab.com/handbook/product/product-analytics-guide/) for more details.
+
+#### Track backend events
+
+The framework provides the following helper method that is available in controllers:
+
+```ruby
+before_action do
+ track_experiment_event(:signup_flow, 'action', 'value')
+end
+```
+
+Which can be tested as follows:
+
+```ruby
+context 'when the experiment is active and the user is in the experimental group' do
+ before do
+ stub_experiment(signup_flow: true)
+ stub_experiment_for_user(signup_flow: true)
+ end
+
+ it 'tracks an event', :snowplow do
+ subject
+
+ expect_snowplow_event(
+ category: 'Growth::Activation::Experiment::SignUpFlow',
+ action: 'action',
+ value: 'value',
+ label: 'experimentation_subject_id',
+ property: 'experimental_group'
+ )
+ end
+end
+```
+
+#### Track frontend events
+
+The framework provides the following helper method that is available in controllers:
+
+```ruby
+before_action do
+ push_frontend_experiment(:signup_flow)
+ frontend_experimentation_tracking_data(:signup_flow, 'action', 'value')
+end
+```
+
+This pushes tracking data to `gon.experiments` and `gon.tracking_data`.
+
+```ruby
+expect(Gon.experiments['signupFlow']).to eq(true)
+
+expect(Gon.tracking_data).to eq(
+ {
+ category: 'Growth::Activation::Experiment::SignUpFlow',
+ action: 'action',
+ value: 'value',
+ label: 'experimentation_subject_id',
+ property: 'experimental_group'
+ }
+)
+```
+
+Which can then be used for tracking as follows:
+
+```javascript
+import { isExperimentEnabled } from '~/lib/utils/experimentation';
+import Tracking from '~/tracking';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const signupFlowExperimentEnabled = isExperimentEnabled('signupFlow');
+
+ if (signupFlowExperimentEnabled && gon.tracking_data) {
+ const { category, action, ...data } = gon.tracking_data;
+
+ Tracking.event(category, action, data);
+ }
+}
+```
+
+Which can be tested in Jest as follows:
+
+```javascript
+import { withGonExperiment } from 'helpers/experimentation_helper';
+import Tracking from '~/tracking';
+
+describe('event tracking', () => {
+ describe('with tracking data', () => {
+ withGonExperiment('signupFlow');
+
+ beforeEach(() => {
+ jest.spyOn(Tracking, 'event').mockImplementation(() => {});
+
+ gon.tracking_data = {
+ category: 'Growth::Activation::Experiment::SignUpFlow',
+ action: 'action',
+ value: 'value',
+ label: 'experimentation_subject_id',
+ property: 'experimental_group'
+ };
+ });
+
+ it('should track data', () => {
+ performAction()
+
+ expect(Tracking.event).toHaveBeenCalledWith(
+ 'Growth::Activation::Experiment::SignUpFlow',
+ 'action',
+ {
+ value: 'value',
+ label: 'experimentation_subject_id',
+ property: 'experimental_group'
+ },
+ );
+ });
+ });
+});
+```
+
+### Enable the experiment
+
+After all merge requests have been merged, use [`chatops`](../../ci/chatops/README.md) in the
[appropriate channel](../feature_flags/controls.md#communicate-the-change) to start the experiment for 10% of the users.
The feature flag should have the name of the experiment with the `_experiment_percentage` suffix appended.
For visibility, please also share any commands run against production in the `#s_growth` channel:
@@ -121,9 +250,39 @@ For visibility, please also share any commands run against production in the `#s
/chatops run feature delete signup_flow_experiment_percentage
```
-### Tests and test helpers
+### Testing and test helpers
+
+#### RSpec
+
+Use the following in RSpec to mock the experiment:
+
+```ruby
+context 'when the experiment is active' do
+ before do
+ stub_experiment(signup_flow: true)
+ end
+
+ context 'when the user is in the experimental group' do
+ before do
+ stub_experiment_for_user(signup_flow: true)
+ end
+
+ it { is_expected.to do_experimental_thing }
+ end
+
+ context 'when the user is in the control group' do
+ before do
+ stub_experiment_for_user(signup_flow: false)
+ end
+
+ it { is_expected.to do_control_thing }
+ end
+end
+```
+
+#### Jest
-Use the following in Jest to test the experiment is enabled.
+Use the following in Jest to mock the experiment:
```javascript
import { withGonExperiment } from 'helpers/experimentation_helper';
diff --git a/doc/development/fe_guide/accessibility.md b/doc/development/fe_guide/accessibility.md
index 669c93eb251..8cb61019556 100644
--- a/doc/development/fe_guide/accessibility.md
+++ b/doc/development/fe_guide/accessibility.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Accessibility & Readability
## Resources
diff --git a/doc/development/fe_guide/architecture.md b/doc/development/fe_guide/architecture.md
index c7e1ba59f23..4b45fb97c76 100644
--- a/doc/development/fe_guide/architecture.md
+++ b/doc/development/fe_guide/architecture.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Architecture
When you are developing a new feature that requires architectural design, or if
diff --git a/doc/development/fe_guide/axios.md b/doc/development/fe_guide/axios.md
index 38a8c8f1086..856b03e4b47 100644
--- a/doc/development/fe_guide/axios.md
+++ b/doc/development/fe_guide/axios.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Axios
We use [Axios](https://github.com/axios/axios) to communicate with the server in Vue applications and most new code.
diff --git a/doc/development/fe_guide/dependencies.md b/doc/development/fe_guide/dependencies.md
index ba97e7e39be..bbe4cdc285d 100644
--- a/doc/development/fe_guide/dependencies.md
+++ b/doc/development/fe_guide/dependencies.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Frontend dependencies
## Package manager
diff --git a/doc/development/fe_guide/design_patterns.md b/doc/development/fe_guide/design_patterns.md
index 5b7b16a9a8a..ed4d91f34bd 100644
--- a/doc/development/fe_guide/design_patterns.md
+++ b/doc/development/fe_guide/design_patterns.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Design Patterns
## Singletons
diff --git a/doc/development/fe_guide/development_process.md b/doc/development/fe_guide/development_process.md
index 2b64534e7c9..915dab06ac2 100644
--- a/doc/development/fe_guide/development_process.md
+++ b/doc/development/fe_guide/development_process.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Frontend Development Process
You can find more about the organization of the frontend team in the [handbook](https://about.gitlab.com/handbook/engineering/frontend/).
diff --git a/doc/development/fe_guide/dropdowns.md b/doc/development/fe_guide/dropdowns.md
index 019bd36573d..bd2dae13c5b 100644
--- a/doc/development/fe_guide/dropdowns.md
+++ b/doc/development/fe_guide/dropdowns.md
@@ -1,3 +1,3 @@
---
-redirect_to: 'https://design.gitlab.com/components/dropdowns/'
+redirect_to: 'https://design.gitlab.com/components/dropdown/'
---
diff --git a/doc/development/fe_guide/droplab/droplab.md b/doc/development/fe_guide/droplab/droplab.md
index 83bc4216403..fe0f07b3019 100644
--- a/doc/development/fe_guide/droplab/droplab.md
+++ b/doc/development/fe_guide/droplab/droplab.md
@@ -1,22 +1,29 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# DropLab
A generic dropdown for all of your custom dropdown needs.
## Usage
-DropLab can be used by simply adding a `data-dropdown-trigger` HTML attribute.
-This attribute allows us to find the "trigger" _(toggle)_ for the dropdown,
-whether that is a button, link or input.
+DropLab can be used by adding a `data-dropdown-trigger` HTML attribute. This
+attribute allows us to find the "trigger" _(toggle)_ for the dropdown, whether
+it's a button, link or input.
-The value of the `data-dropdown-trigger` should be a CSS selector that
-DropLab can use to find the trigger's dropdown list.
+The value of the `data-dropdown-trigger` should be a CSS selector that DropLab
+can use to find the trigger's dropdown list.
You should also add the `data-dropdown` attribute to declare the dropdown list.
The value is irrelevant.
-The DropLab class has no side effects, so you must always call `.init` when
-the DOM is ready. `DropLab.prototype.init` takes the same arguments as `DropLab.prototype.addHook`.
-If you do not provide any arguments, it will globally query and instantiate all droplab compatible dropdowns.
+The DropLab class has no side effects, so you must always call `.init` when the
+DOM is ready. `DropLab.prototype.init` takes the same arguments as `DropLab.prototype.addHook`.
+If you don't provide any arguments, it will globally query and instantiate all
+DropLab-compatible dropdowns.
```html
<a href="#" data-dropdown-trigger="#list">Toggle</a>
@@ -31,8 +38,8 @@ const droplab = new DropLab();
droplab.init();
```
-As you can see, we have a "Toggle" link, that is declared as a trigger.
-It provides a selector to find the dropdown list it should control.
+As noted, we have a "Toggle" link that's declared as a trigger. It provides a
+selector to find the dropdown list it should control.
### Static data
@@ -54,8 +61,8 @@ droplab.init();
### Explicit instantiation
-You can pass the trigger and list elements as constructor arguments to return
-a non-global instance of DropLab using the `DropLab.prototype.init` method.
+You can pass the trigger and list elements as constructor arguments to return a
+non-global instance of DropLab using the `DropLab.prototype.init` method.
```html
<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a>
@@ -96,12 +103,13 @@ droplab.addHook(trigger, list);
### Dynamic data
-Adding `data-dynamic` to your dropdown element will enable dynamic list rendering.
+Adding `data-dynamic` to your dropdown element will enable dynamic list
+rendering.
-You can template a list item using the keys of the data object provided.
-Use the handlebars syntax `{{ value }}` to HTML escape the value.
-Use the `<%= value %>` syntax to simply interpolate the value.
-Use the `<%= value %>` syntax to evaluate the value.
+You can template a list item using the keys of the data object provided. Use the
+handlebars syntax `{{ value }}` to HTML escape the value. Use the `<%= value %>`
+syntax to interpolate the value. Use the `<%= value %>` syntax to evaluate the
+value.
Passing an array of objects to `DropLab.prototype.addData` will render that data
for all `data-dynamic` dropdown lists tracked by that DropLab instance.
@@ -126,8 +134,9 @@ droplab.init().addData([{
}]);
```
-Alternatively, you can specify a specific dropdown to add this data to but passing
-the data as the second argument and the `id` of the trigger element as the first argument.
+Alternatively, you can specify a specific dropdown to add this data to by
+passing the data as the second argument and the `id` of the trigger element as
+the first argument.
```html
<a href="#" data-dropdown-trigger="#list" id="trigger">Toggle</a>
@@ -149,7 +158,7 @@ droplab.init().addData('trigger', [{
}]);
```
-This allows you to mix static and dynamic content with ease, even with one trigger.
+This allows you to mix static and dynamic content, even with one trigger.
Note the use of scoping regarding the `data-dropdown` attribute to capture both
dropdown lists, one of which is dynamic.
@@ -185,12 +194,13 @@ DropLab adds some CSS classes to help lower the barrier to integration.
For example:
-- The `droplab-item-selected` CSS class is added to items that have been selected
- either by a mouse click or by enter key selection.
+- The `droplab-item-selected` CSS class is added to items that have been
+ selected either by a mouse click or by enter key selection.
- The `droplab-item-active` CSS class is added to items that have been selected
using arrow key navigation.
-- You can add the `droplab-item-ignore` CSS class to any item that you do not want to be selectable. For example,
- an `<li class="divider"></li>` list divider element that should not be interactive.
+- You can add the `droplab-item-ignore` CSS class to any item that you don't
+ want to be selectable. For example, an `<li class="divider"></li>` list
+ divider element that shouldn't be interactive.
## Internal events
@@ -198,26 +208,33 @@ DropLab uses some custom events to help lower the barrier to integration.
For example:
-- The `click.dl` event is fired when an `li` list item has been clicked. It is also
- fired when a list item has been selected with the keyboard. It is also fired when a
- `HookButton` button is clicked (a registered `button` tag or `a` tag trigger).
-- The `input.dl` event is fired when a `HookInput` (a registered `input` tag trigger) triggers an `input` event.
-- The `mousedown.dl` event is fired when a `HookInput` triggers a `mousedown` event.
+- The `click.dl` event is fired when an `li` list item has been clicked. It's
+ also fired when a list item has been selected with the keyboard. It's also
+ fired when a `HookButton` button is clicked (a registered `button` tag or `a`
+ tag trigger).
+- The `input.dl` event is fired when a `HookInput` (a registered `input` tag
+ trigger) triggers an `input` event.
+- The `mousedown.dl` event is fired when a `HookInput` triggers a `mousedown`
+ event.
- The `keyup.dl` event is fired when a `HookInput` triggers a `keyup` event.
- The `keydown.dl` event is fired when a `HookInput` triggers a `keydown` event.
-These custom events add a `detail` object to the vanilla `Event` object that provides some potentially useful data.
+These custom events add a `detail` object to the vanilla `Event` object that
+provides some potentially useful data.
## Plugins
-Plugins are objects that are registered to be executed when a hook is added (when a droplab trigger and dropdown are instantiated).
+Plugins are objects that are registered to be executed when a hook is added (when
+a DropLab trigger and dropdown are instantiated).
-If no modules API is detected, the library will fall back as it does with `window.DropLab` and will add `window.DropLab.plugins.PluginName`.
+If no modules API is detected, the library will fall back as it does with
+`window.DropLab` and will add `window.DropLab.plugins.PluginName`.
### Usage
-To use plugins, you can pass them in an array as the third argument of `DropLab.prototype.init` or `DropLab.prototype.addHook`.
-Some plugins require configuration values, the config object can be passed as the fourth argument.
+To use plugins, you can pass them in an array as the third argument of
+`DropLab.prototype.init` or `DropLab.prototype.addHook`. Some plugins require
+configuration values; the config object can be passed as the fourth argument.
```html
<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a>
@@ -240,14 +257,13 @@ droplab.init(trigger, list, [droplabAjax], {
### Documentation
-- [Ajax plugin](plugins/ajax.md)
-- [Filter plugin](plugins/filter.md)
-- [InputSetter plugin](plugins/input_setter.md)
+Refer to the list of available [DropLab plugins](plugins/index.md) for
+information about their use.
### Development
-When plugins are initialised for a droplab trigger+dropdown, DropLab will
-call the plugins `init` function, so this must be implemented in the plugin.
+When plugins are initialised for a DropLab trigger+dropdown, DropLab calls the
+plugins' `init` function, so this must be implemented in the plugin.
```javascript
class MyPlugin {
diff --git a/doc/development/fe_guide/droplab/plugins/ajax.md b/doc/development/fe_guide/droplab/plugins/ajax.md
index f22d95064dd..3ac876ad062 100644
--- a/doc/development/fe_guide/droplab/plugins/ajax.md
+++ b/doc/development/fe_guide/droplab/plugins/ajax.md
@@ -1,17 +1,25 @@
-# Ajax
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
-`Ajax` is a droplab plugin that allows for retrieving and rendering list data from a server.
+# Ajax plugin
+
+`Ajax` is a DropLab plugin that allows for retrieving and rendering list data
+from a server.
## Usage
-Add the `Ajax` object to the plugins array of a `DropLab.prototype.init` or `DropLab.prototype.addHook` call.
+Add the `Ajax` object to the plugins array of a `DropLab.prototype.init` or
+`DropLab.prototype.addHook` call.
-`Ajax` requires 2 configuration values, the `endpoint` and `method`.
+`Ajax` requires 2 configuration values: the `endpoint` and `method`.
-- `endpoint` should be a URL to the request endpoint.
-- `method` should be `setData` or `addData`.
-- `setData` completely replaces the dropdown with the response data.
-- `addData` appends the response data to the current dropdown list.
+- `endpoint`: Should be a URL to the request endpoint.
+- `method`: Should be `setData` or `addData`.
+- `setData`: Completely replaces the dropdown with the response data.
+- `addData`: Appends the response data to the current dropdown list.
```html
<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a>
@@ -32,7 +40,7 @@ droplab.addHook(trigger, list, [Ajax], {
});
```
-Optionally you can set `loadingTemplate` to a HTML string. This HTML string will
-replace the dropdown list while the request is pending.
+Optionally, you can set `loadingTemplate` to a HTML string. This HTML string
+replaces the dropdown list while the request is pending.
Additionally, you can set `onError` to a function to catch any XHR errors.
diff --git a/doc/development/fe_guide/droplab/plugins/filter.md b/doc/development/fe_guide/droplab/plugins/filter.md
index e8194e45a41..9ab4946d21d 100644
--- a/doc/development/fe_guide/droplab/plugins/filter.md
+++ b/doc/development/fe_guide/droplab/plugins/filter.md
@@ -1,15 +1,22 @@
-# Filter
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
-`Filter` is a plugin that allows for filtering data that has been added
+# Filter plugin
+
+`Filter` is a DropLab plugin that allows for filtering data that has been added
to the dropdown using a simple fuzzy string search of an input value.
## Usage
-Add the `Filter` object to the plugins array of a `DropLab.prototype.init` or `DropLab.prototype.addHook` call.
+Add the `Filter` object to the plugins array of a `DropLab.prototype.init` or
+`DropLab.prototype.addHook` call.
-- `Filter` requires a configuration value for `template`.
-- `template` should be the key of the objects within your data array that you want to compare
- to the user input string, for filtering.
+- `Filter`: Requires a configuration value for `template`.
+- `template`: Should be the key of the objects within your data array that you
+ want to compare to the user input string, for filtering.
```html
<input href="#" id="trigger" data-dropdown-trigger="#list">
@@ -39,8 +46,10 @@ droplab.addData('trigger', [{
}]);
```
-Above, the input string will be compared against the `test` key of the passed data objects.
+In the previous code, the input string is compared against the `test` key of the
+passed data objects.
-Optionally you can set `filterFunction` to a function. This function will be used instead
-of `Filter`'s built in string search. `filterFunction` is passed 2 arguments, the first
-is one of the data objects, the second is the current input value.
+Optionally you can set `filterFunction` to a function. This function will be
+used instead of `Filter`'s built-in string search. `filterFunction` is passed
+two arguments: the first is one of the data objects, and the second is the
+current input value.
diff --git a/doc/development/fe_guide/droplab/plugins/index.md b/doc/development/fe_guide/droplab/plugins/index.md
new file mode 100644
index 00000000000..d44670bfb3c
--- /dev/null
+++ b/doc/development/fe_guide/droplab/plugins/index.md
@@ -0,0 +1,14 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+description: A list of DropLab plugins.
+---
+
+# DropLab plugins
+
+The following plugins are available for use with [DropLab](../droplab.md):
+
+- [Ajax plugin](ajax.md)
+- [Filter plugin](filter.md)
+- [InputSetter plugin](input_setter.md)
diff --git a/doc/development/fe_guide/droplab/plugins/input_setter.md b/doc/development/fe_guide/droplab/plugins/input_setter.md
index b873b7a14ee..ab8a5cebd08 100644
--- a/doc/development/fe_guide/droplab/plugins/input_setter.md
+++ b/doc/development/fe_guide/droplab/plugins/input_setter.md
@@ -1,17 +1,26 @@
-# InputSetter
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
-`InputSetter` is a plugin that allows for updating DOM out of the scope of droplab when a list item is clicked.
+# InputSetter plugin
+
+`InputSetter` is a DropLab plugin that allows for updating DOM out of the scope
+of DropLab when a list item is clicked.
## Usage
-Add the `InputSetter` object to the plugins array of a `DropLab.prototype.init` or `DropLab.prototype.addHook` call.
+Add the `InputSetter` object to the plugins array of a `DropLab.prototype.init`
+or `DropLab.prototype.addHook` call.
-- `InputSetter` requires a configuration value for `input` and `valueAttribute`.
-- `input` should be the DOM element that you want to manipulate.
-- `valueAttribute` should be a string that is the name of an attribute on your list items that is used to get the value
- to update the `input` element with.
+- `InputSetter`: Requires a configuration value for `input` and `valueAttribute`.
+- `input`: The DOM element that you want to manipulate.
+- `valueAttribute`: A string that's the name of an attribute on your list items
+ that's used to get the value to update the `input` element with.
-You can also set the `InputSetter` configuration to an array of objects, which will allow you to update multiple elements.
+You can also set the `InputSetter` configuration to an array of objects, which
+allows you to update multiple elements.
```html
<input id="input" value="">
@@ -52,9 +61,12 @@ droplab.addData('trigger', [{
}]);
```
-Above, if the second list item was clicked, it would update the `#input` element
-to have a `value` of `1`, it would also update the `#div` element's `data-selected-id` to `1`.
+In the previous code, if the second list item was clicked, it would update the
+`#input` element to have a `value` of `1`, it would also update the `#div`
+element's `data-selected-id` to `1`.
-Optionally you can set `inputAttribute` to a string that is the name of an attribute on your `input` element that you want to update.
-If you do not provide an `inputAttribute`, `InputSetter` will update the `value` of the `input` element if it is an `INPUT` element,
-or the `textContent` of the `input` element if it is not an `INPUT` element.
+Optionally, you can set `inputAttribute` to a string that's the name of an
+attribute on your `input` element that you want to update. If you don't provide
+an `inputAttribute`, `InputSetter` will update the `value` of the `input`
+element if it's an `INPUT` element, or the `textContent` of the `input` element
+if it isn't an `INPUT` element.
diff --git a/doc/development/fe_guide/editor_lite.md b/doc/development/fe_guide/editor_lite.md
new file mode 100644
index 00000000000..eb5852d258d
--- /dev/null
+++ b/doc/development/fe_guide/editor_lite.md
@@ -0,0 +1,224 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# Editor Lite
+
+## Background
+
+**Editor Lite** is a technological product driving [Web Editor](../../user/project/repository/web_editor.md), [Snippets](../../user/snippets.md), [CI Linter](../../ci/lint.md), etc. Editor Lite is the driving technology for any single-file editing experience across the product.
+
+Editor Lite is a thin wrapper around [the Monaco editor](https://microsoft.github.io/monaco-editor/index.html) that provides the necessary helpers and abstractions and extends Monaco using extensions.
+
+## How to use Editor Lite
+
+Editor Lite is framework-agnostic and can be used in any application, whether it's Rails or Vue. For the convenience of integration, we have [the dedicated `<editor-lite>` Vue component](#vue-component), but in general, the integration of Editor Lite is pretty straightforward:
+
+1. Import Editor Lite:
+
+```javascript
+import EditorLite from '~/editor/editor_lite';
+```
+
+1. Initialize global editor for the view:
+
+```javascript
+const editor = new EditorLite({
+ // Editor Options.
+ // The list of all accepted options can be found at
+ // https://microsoft.github.io/monaco-editor/api/enums/monaco.editor.editoroption.html
+});
+```
+
+1. Create an editor's instance:
+
+```javascript
+editor.createInstance({
+ // Editor Lite configuration options.
+})
+```
+
+An instance of Editor Lite accepts the following configuration options:
+
+| Option | Required? | Description |
+| ---- | ---- | ---- |
+| `el` | `true` | `HTML Node`: element on which to render the editor |
+| `blobPath` | `false` | `String`: the name of a file to render in the editor. It is used to identify the correct syntax highlighter to use with that or another file type. Can accept wildcard as in `*.js` when the actual filename isn't known or doesn't play any role |
+| `blobContent` | `false` | `String`: the initial content to be rendered in the editor |
+| `extensions` | `false` | `Array`: extensions to use in this instance |
+| `blobGlobalId` | `false` | `String`: auto-generated property.<br>**Note:** this prop might go away in the future. Do not pass `blobGlobalId` unless you know what you're doing.|
+| [Editor Options](https://microsoft.github.io/monaco-editor/api/enums/monaco.editor.editoroption.html) | `false` | `Object(s)`: any prop outside of the list above is treated as an Editor Option for this particular instance. This way, one can override global Editor Options on the instance level. |
+
+## API
+
+The editor follows the same public API as [provided by Monaco editor](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html) with just a few additional functions on the instance level:
+
+| Function | Arguments | Description
+| ----- | ----- | ----- |
+| `updateModelLanguage` | `path`: String | Updates the instance's syntax highlighting to follow the extension of the passed `path`. Available only on _instance_ level|
+| `use` | Array of objects | Array of **extensions** to apply to the instance. Accepts only the array of _objects_, which means that the extensions' ES6 modules should be fetched and resolved in your views/components before being passed to `use`. This prop is available on _instance_ (applies extension to this particular instance) and _global edtor_ (applies the same extension to all instances) levels. |
+| Monaco Editor options | See [documentation](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html) | Default Monaco editor options |
+
+## Tips
+
+1. Editor's loading state.
+
+Editor Lite comes with the loading state built-in, making spinners and loaders rarely needed in HTML. To benefit the built-in loading state, set the `data-editor-loading` property on the HTML element that is supposed to contain the editor. Editor Lite will show the loader automatically while it's bootstrapping.
+![Editor Lite: loading state](img/editor_lite_loading.png)
+
+1. Update syntax highlighting if the file name changes.
+
+```javascript
+// fileNameEl here is the HTML input element that contains the file name
+fileNameEl.addEventListener('change', () => {
+ this.editor.updateModelLanguage(fileNameEl.value);
+});
+```
+
+1. Get the editor's content.
+
+We might set up listeners on the editor for every change but it rapidly can become an expensive operation. Instead , we can get editor's content when it's needed. For example on a form's submission:
+
+```javascript
+form.addEventListener('submit', () => {
+ my_content_variable = this.editor.getValue();
+});
+```
+
+1. Performance
+
+Even though Editor Lite itself is extremely slim, it still depends on Monaco editor. Monaco is not an easily tree-shakeable module. Hence, every time you add Editor Lite to a view, the JavaScript bundle's size significantly increases, affecting your view's loading performance. To avoid that, it is recommended to import the editor on demand on those views where it is not 100% certain that the editor will be used. Or if the editor is a secondary element of the view. Loading Editor Lite on demand is no different from loading any other module:
+
+```javascript
+someActionFunction() {
+ import(/* webpackChunkName: 'EditorLite' */ '~/editor/editor_lite').
+ then(({ default: EditorLite }) => {
+ const editor = new EditorLite();
+ ...
+ });
+ ...
+}
+```
+
+## Extensions
+
+Editor Lite has been built to provide a universal, extensible editing tool to the whole product, which would not depend on any particular group. Even though the Editor Lite's core is owned by [Create::Editor FE Team](https://about.gitlab.com/handbook/engineering/development/dev/create-editor-fe/), the main functional elements — extensions — can be owned by any group. Editor Lite extensions' main idea is that the core of the editor remains very slim and stable. At the same time, whatever new functionality is needed can be added as an extension to this core, without touching the core itself. It allows any group to build and own any new editing functionality without being afraid of it being broken or overridden with the Editor Lite changes.
+
+Structurally, the complete implementation of Editor Lite could be presented as the following diagram:
+
+```mermaid
+graph TD;
+ B[Extension 1]---A[Editor Lite]
+ C[Extension 2]---A[Editor Lite]
+ D[Extension 3]---A[Editor Lite]
+ E[...]---A[Editor Lite]
+ F[Extension N]---A[Editor Lite]
+ A[Editor Lite]---Z[Monaco]
+```
+
+Technically, an extension is just an ES6 module that exports a JavaScript object:
+
+```javascript
+import { Position } from 'monaco-editor';
+
+export default {
+ navigateFileStart() {
+ this.setPosition(new Position(1, 1));
+ },
+};
+
+```
+
+Important things to note here:
+
+- We can depend on other modules in our extensions. This organization helps keep the size of Editor Lite's core at bay by importing dependencies only when needed.
+- `this` in extension's functions refers to the current Editor Lite instance. Using `this`, you get access to the complete instance's API, such as the `setPosition()` method in this particular case.
+
+### Using an existing extension
+
+Adding an extension to Editor Lite's instance is simple:
+
+```javascript
+import EditorLite from '~/editor/editor_lite';
+import MyExtension from '~/my_extension';
+
+const editor = new EditorLite().createInstance({
+ ...
+});
+editor.use(MyExtension);
+```
+
+### Creating an extension
+
+Let's create our first Editor Lite extension. As aforementioned, extensions are ES6 modules exporting the simple `Object` that is used to extend Editor Lite's functionality. As the most straightforward test, let's create an extension that extends Editor Lite with a new function that, when called, will output editor's content in `alert`.
+
+`~/my_folder/my_fancy_extension.js:`
+
+```javascript
+export default {
+ throwContentAtMe() {
+ alert(this.getValue());
+ },
+};
+```
+
+And that's it with our extension! Note that we're using `this` as a reference to the instance. And through it, we get access to the complete underlying [Monaco editor API](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html) like `getValue()` in this case.
+
+Now let's use our extension:
+
+`~/my_folder/component_bundle.js`:
+
+```javascript
+import EditorLite from '~/editor/editor_lite';
+import MyFancyExtension from './my_fancy_extension';
+
+const editor = new EditorLite().createInstance({
+ ...
+});
+editor.use(MyFancyExtension);
+...
+someButton.addEventListener('click', () => {
+ editor.throwContentAtMe();
+});
+```
+
+First of all, we import Editor Lite and our new extension. Then we create the editor and its instance. By default Editor Lite has no `throwContentAtMe` method. But the `editor.use(MyFancyExtension)` line brings that method to our instance. After that, we can use it any time we need it. In this case, we call it when some theoretical button has been clicked.
+
+This script would result in an alert containing the editor's content when `someButton` is clicked.
+
+![Editor Lite new extension's result](img/editor_lite_create_ext.png)
+
+### Tips
+
+1. Performance
+
+Just like Editor Lite itself, any extension can be loaded on demand to not harm loading performance of the views:
+
+```javascript
+const EditorPromise = import(
+ /* webpackChunkName: 'EditorLite' */ '~/editor/editor_lite'
+);
+const MarkdownExtensionPromise = import('~/editor/editor_markdown_ext');
+
+Promise.all([EditorPromise, MarkdownExtensionPromise])
+ .then(([{ default: EditorLite }, { default: MarkdownExtension }]) => {
+ const editor = new EditorLite().createInstance({
+ ...
+ });
+ editor.use(MarkdownExtension);
+ });
+```
+
+1. Using multiple extensions
+
+Just pass the array of extensions to your `use` method:
+
+```javascript
+editor.use([FileTemplateExtension, MyFancyExtension]);
+```
+
+## <a id="vue-component"></a>`<editor-lite>` Vue component
+
+TBD
diff --git a/doc/development/fe_guide/emojis.md b/doc/development/fe_guide/emojis.md
index 3cd14c0dfd3..9b1abaa14ae 100644
--- a/doc/development/fe_guide/emojis.md
+++ b/doc/development/fe_guide/emojis.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Emojis
GitLab supports native Unicode emojis and falls back to image-based emojis selectively
diff --git a/doc/development/fe_guide/frontend_faq.md b/doc/development/fe_guide/frontend_faq.md
index 0a26fdba934..22a48c8f9f9 100644
--- a/doc/development/fe_guide/frontend_faq.md
+++ b/doc/development/fe_guide/frontend_faq.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Frontend FAQ
## Rules of Frontend FAQ
@@ -63,7 +69,7 @@ banner on top of the component examples indicates that:
> component.
For example, at the time of writing, this type of warning can be observed for
-[all form components](https://design.gitlab.com/components/forms/). It, however,
+[all form components](https://design.gitlab.com/components/form/). It, however,
doesn't imply that the component should not be used.
GitLab always asks to use `<gl-*>` components whenever a suitable component exists.
@@ -174,10 +180,9 @@ which adds the appropriate `core-js` polyfills once for each JavaScript feature
we're using that our target browsers don't support. You don't need to add `core-js`
polyfills manually.
-NOTE: **Note:**
-GitLab still manually adds non-`core-js` polyfills for extending browser features
-(such as GitLab's SVG polyfill) that allow us reference SVGs by using `<use xlink:href>`.
-These polyfills should be added to `app/assets/javascripts/commons/polyfills.js`.
+GitLab adds non-`core-js` polyfills for extending browser features (such as
+GitLab's SVG polyfill), which allow us to reference SVGs by using `<use xlink:href>`.
+Be sure to add these polyfills to `app/assets/javascripts/commons/polyfills.js`.
To see what polyfills are being used:
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index ad3958d4496..cae2435e4ff 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -664,7 +664,9 @@ it('calls mutation on submitting form ', () => {
### Testing with mocked Apollo Client
-To test the logic of Apollo cache updates, we might want to mock an Apollo Client in our unit tests. 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:
+To test the logic of Apollo cache updates, we might want to mock an Apollo Client in our unit tests. We use [`mock-apollo-client`](https://www.npmjs.com/package/mock-apollo-client) library to mock Apollo client and [`createMockApollo` helper](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/frontend/helpers/mock_apollo_helper.js) we created on top of it.
+
+To separate tests with mocked client from 'usual' unit tests, it's recommended to create an additional component factory. This way we only create Apollo Client instance when it's necessary:
```javascript
function createComponent() {...}
@@ -672,12 +674,6 @@ 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
@@ -741,8 +737,8 @@ describe('Some component with Apollo mock', () => {
})
```
-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 mocking resolved values, ensure the structure of the response is the same
+as the actual API response. For example, root property should be `data`.
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:
@@ -830,6 +826,53 @@ it('calls a mutation with correct parameters and reorders designs', async () =>
});
```
+#### Testing `@client` queries
+
+If your application contains `@client` queries, most probably you will have an Apollo Client warning saying that you have a local query but no resolvers are defined. In order to fix it, you need to pass resolvers to the mocked client with a second parameter (bare minimum is an empty object):
+
+```javascript
+import createMockApollo from 'jest/helpers/mock_apollo_helper';
+...
+fakeApollo = createMockApollo(requestHandlers, {});
+```
+
+Sometimes we want to test a `result` hook of the local query. In order to have it triggered, we need to populate a cache with correct data to be fetched with this query:
+
+```javascript
+query fetchLocalUser {
+ fetchLocalUser @client {
+ name
+ }
+}
+```
+
+```javascript
+import fetchLocalUserQuery from '~/design_management/graphql/queries/fetch_local_user.query.graphql';
+
+function createComponentWithApollo() {
+ const requestHandlers = [
+ [getDesignListQuery, jest.fn().mockResolvedValue(designListQueryResponse)],
+ [permissionsQuery, jest.fn().mockResolvedValue(permissionsQueryResponse)],
+ ];
+
+ fakeApollo = createMockApollo(requestHandlers, {});
+ fakeApollo.clients.defaultClient.cache.writeQuery({
+ query: fetchLocalUserQuery,
+ data: {
+ fetchLocalUser: {
+ __typename: 'User',
+ name: 'Test',
+ },
+ },
+ })
+
+ wrapper = shallowMount(Index, {
+ localVue,
+ apolloProvider: fakeApollo,
+ });
+}
+```
+
## Handling errors
GitLab's GraphQL mutations currently have two distinct error modes: [Top-level](#top-level-errors) and [errors-as-data](#errors-as-data).
@@ -910,3 +953,99 @@ const defaultClient = createDefaultClient(
},
);
```
+
+## Making initial queries early with GraphQL startup calls
+
+To improve performance, sometimes we want to make initial GraphQL queries early. In order to do this, we can add them to **startup calls** with the following steps:
+
+- Move all the queries you need initially in your application to `app/graphql/queries`;
+- Add `__typename` property to every nested query level:
+
+ ```javascript
+ query getPermissions($projectPath: ID!) {
+ project(fullPath: $projectPath) {
+ __typename
+ userPermissions {
+ __typename
+ pushCode
+ forkProject
+ createMergeRequestIn
+ }
+ }
+ }
+ ```
+
+- If queries contain fragments, you need to move fragments to the query file directly instead of importing them:
+
+ ```javascript
+ fragment PageInfo on PageInfo {
+ __typename
+ hasNextPage
+ hasPreviousPage
+ startCursor
+ endCursor
+ }
+
+ query getFiles(
+ $projectPath: ID!
+ $path: String
+ $ref: String!
+ ) {
+ project(fullPath: $projectPath) {
+ __typename
+ repository {
+ __typename
+ tree(path: $path, ref: $ref) {
+ __typename
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ }
+ }
+ }
+ }
+ ```
+
+- If the fragment is used only once, we can also remove the fragment altogether:
+
+ ```javascript
+ query getFiles(
+ $projectPath: ID!
+ $path: String
+ $ref: String!
+ ) {
+ project(fullPath: $projectPath) {
+ __typename
+ repository {
+ __typename
+ tree(path: $path, ref: $ref) {
+ __typename
+ pageInfo {
+ __typename
+ hasNextPage
+ hasPreviousPage
+ startCursor
+ endCursor
+ }
+ }
+ }
+ }
+ }
+ }
+ ```
+
+- Add startup call(s) with correct variables to the HAML file that serves as a view
+for your application. To add GraphQL startup calls, we use
+`add_page_startup_graphql_call` helper where the first parameter is a path to the
+query, the second one is an object containing query variables. Path to the query is
+relative to `app/graphql/queries` folder: for example, if we need a
+`app/graphql/queries/repository/files.query.graphql` query, the path will be
+`repository/files`.
+
+ ```yaml
+ - current_route_path = request.fullpath.match(/-\/tree\/[^\/]+\/(.+$)/).to_a[1]
+ - add_page_startup_graphql_call('repository/path_last_commit', { projectPath: @project.full_path, ref: current_ref, path: current_route_path || "" })
+ - add_page_startup_graphql_call('repository/permissions', { projectPath: @project.full_path })
+ - add_page_startup_graphql_call('repository/files', { nextPageCursor: "", pageSize: 100, projectPath: @project.full_path, ref: current_ref, path: current_route_path || "/"})
+ ```
diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md
index 67add5709d9..994a3aa36fc 100644
--- a/doc/development/fe_guide/icons.md
+++ b/doc/development/fe_guide/icons.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Icons and SVG Illustrations
We manage our own icon and illustration library in the [`gitlab-svgs`](https://gitlab.com/gitlab-org/gitlab-svgs)
@@ -84,7 +90,7 @@ Please use the following function inside JS to render an icon:
### Usage in HAML/Rails
-DANGER: **Danger:**
+DANGER: **Warning:**
Do not use the `spinner` or `icon('spinner spin')` rails helpers to insert
loading icons. These helpers rely on the Font Awesome icon library which is
deprecated.
diff --git a/doc/development/fe_guide/img/editor_lite_create_ext.png b/doc/development/fe_guide/img/editor_lite_create_ext.png
new file mode 100644
index 00000000000..73941cf5d62
--- /dev/null
+++ b/doc/development/fe_guide/img/editor_lite_create_ext.png
Binary files differ
diff --git a/doc/development/fe_guide/img/editor_lite_loading.png b/doc/development/fe_guide/img/editor_lite_loading.png
new file mode 100644
index 00000000000..f2c242da155
--- /dev/null
+++ b/doc/development/fe_guide/img/editor_lite_loading.png
Binary files differ
diff --git a/doc/development/fe_guide/img/gl-modal.png b/doc/development/fe_guide/img/gl-modal.png
deleted file mode 100644
index b2d2d637e57..00000000000
--- a/doc/development/fe_guide/img/gl-modal.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md
index f909866d44e..9f98876bc8e 100644
--- a/doc/development/fe_guide/index.md
+++ b/doc/development/fe_guide/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Frontend Development Guidelines
This document describes various guidelines to ensure consistency and quality
diff --git a/doc/development/fe_guide/keyboard_shortcuts.md b/doc/development/fe_guide/keyboard_shortcuts.md
index da9b3702a8d..227b5cfd22c 100644
--- a/doc/development/fe_guide/keyboard_shortcuts.md
+++ b/doc/development/fe_guide/keyboard_shortcuts.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Implementing keyboard shortcuts
We use [Mousetrap](https://craig.is/killing/mice) to implement keyboard
diff --git a/doc/development/fe_guide/performance.md b/doc/development/fe_guide/performance.md
index 5d2b699c40d..de9a9f5cb14 100644
--- a/doc/development/fe_guide/performance.md
+++ b/doc/development/fe_guide/performance.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Performance
## Best Practices
@@ -71,9 +77,8 @@ controller with the `index` action. If a corresponding file exists at
`pages/projects/issues/index/index.js`, it will be compiled into a webpack
bundle and included on the page.
-NOTE: **Note:**
-Previously we had encouraged the use of
-`content_for :page_specific_javascripts` within haml files, along with
+Previously, GitLab encouraged the use of
+`content_for :page_specific_javascripts` within HAML files, along with
manually generated webpack bundles. However under this new system you should
not ever need to manually add an entry point to the `webpack.config.js` file.
@@ -91,17 +96,55 @@ browser's developer console while on any page within GitLab.
modules outside of the entry point script. Just import, read the DOM,
instantiate, and nothing else.
-- **Entry Points May Be Asynchronous:**
- _DO NOT ASSUME_ that the DOM has been fully loaded and available when an
- entry point script is run. If you require that some code be run after the
- DOM has loaded, you should attach an event handler to the `DOMContentLoaded`
- event with:
+- **`DOMContentLoaded` should not be used:**
+ All of GitLab's JavaScript files are added with the `defer` attribute.
+ According to the [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer),
+ this implies that "the script is meant to be executed after the document has
+ been parsed, but before firing `DOMContentLoaded`". Since the document is already
+ parsed, `DOMContentLoaded` is not needed to bootstrap applications because all
+ the DOM nodes are already at our disposal.
+
+- **JavaScript that relies on CSS for calculations should use [`waitForCSSLoaded()`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/helpers/startup_css_helper.js#L34):**
+ GitLab uses [Startup.css](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38052)
+ to improve page performance. This can cause issues if JavaScript relies on CSS
+ for calculations. To fix this the JavaScript can be wrapped in the
+ [`waitForCSSLoaded()`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/helpers/startup_css_helper.js#L34)
+ helper function.
```javascript
import initMyWidget from './my_widget';
+ import { waitForCSSLoaded } from '~/helpers/startup_css_helper';
- document.addEventListener('DOMContentLoaded', () => {
- initMyWidget();
+ waitForCSSLoaded(initMyWidget);
+ ```
+
+ Note that `waitForCSSLoaded()` methods supports receiving the action in different ways:
+
+ - With a callback:
+
+ ```javascript
+ waitForCSSLoaded(action)
+ ```
+
+ - With `then()`:
+
+ ```javascript
+ waitForCSSLoaded().then(action);
+ ```
+
+ - With `await` followed by `action`:
+
+ ```javascript
+ await waitForCSSLoaded;
+ action();
+ ```
+
+ For example, see how we use this in [app/assets/javascripts/pages/projects/graphs/charts/index.js](https://gitlab.com/gitlab-org/gitlab/-/commit/5e90885d6afd4497002df55bf015b338efcfc3c5#02e81de37f5b1716a3ef3222fa7f7edf22c40969_9_8):
+
+ ```javascript
+ waitForCSSLoaded(() => {
+ const languagesContainer = document.getElementById('js-languages-chart');
+ //...
});
```
diff --git a/doc/development/fe_guide/principles.md b/doc/development/fe_guide/principles.md
index 2bef48fddcf..75954a5f988 100644
--- a/doc/development/fe_guide/principles.md
+++ b/doc/development/fe_guide/principles.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Principles
These principles will ensure that your frontend contribution starts off in the right direction.
diff --git a/doc/development/fe_guide/security.md b/doc/development/fe_guide/security.md
index a001dd83ab7..a82c315032f 100644
--- a/doc/development/fe_guide/security.md
+++ b/doc/development/fe_guide/security.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Security
## Resources
@@ -77,3 +83,25 @@ inject scripts into the web app.
Inline styles should be avoided in almost all cases, they should only be used
when no alternatives can be found. This allows reusability of styles as well as
readability.
+
+### Sanitize HTML output
+
+If you need to output raw HTML, you should sanitize it.
+
+If you are using Vue, you can use the[`v-safe-html` directive](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/directives-safe-html-directive--default) from GitLab UI.
+
+For other use cases, wrap a preconfigured version of [`dompurify`](https://www.npmjs.com/package/dompurify)
+that also allows the icons to be rendered:
+
+```javascript
+import { sanitize } from '~/lib/dompurify';
+
+const unsafeHtml = '<some unsafe content ... >';
+
+// ...
+
+element.appendChild(sanitize(unsafeHtml));
+```
+
+This `sanitize` function takes the same configuration as the
+original.
diff --git a/doc/development/fe_guide/style/html.md b/doc/development/fe_guide/style/html.md
index 1445da3f0e1..61a724cf3c7 100644
--- a/doc/development/fe_guide/style/html.md
+++ b/doc/development/fe_guide/style/html.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# HTML style guide
## Buttons
diff --git a/doc/development/fe_guide/style/index.md b/doc/development/fe_guide/style/index.md
index 4ca409664de..0d73b16b5d3 100644
--- a/doc/development/fe_guide/style/index.md
+++ b/doc/development/fe_guide/style/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab development style guides
See below for the relevant style guides, guidelines, linting, and other information for developing GitLab.
diff --git a/doc/development/fe_guide/style/javascript.md b/doc/development/fe_guide/style/javascript.md
index 2a06a473878..b8e7429eb2c 100644
--- a/doc/development/fe_guide/style/javascript.md
+++ b/doc/development/fe_guide/style/javascript.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
disqus_identifier: 'https://docs.gitlab.com/ee/development/fe_guide/style_guide_js.html'
---
@@ -138,7 +141,7 @@ module.exports = SomeClass;
export default SomeClass;
```
-_Note:_ We still use `require` in `scripts/` and `config/` files.
+We still use `require` in `scripts/` and `config/` files.
## Absolute vs relative paths for modules
diff --git a/doc/development/fe_guide/style/scss.md b/doc/development/fe_guide/style/scss.md
index dba39eeb98c..c6ee1e64a80 100644
--- a/doc/development/fe_guide/style/scss.md
+++ b/doc/development/fe_guide/style/scss.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
disqus_identifier: 'https://docs.gitlab.com/ee/development/fe_guide/style_guide_scss.html'
---
@@ -46,11 +49,6 @@ We recommend a "utility-first" approach.
This encourages an organic growth of component classes and prevents the creation of one-off unreusable classes. Also, the kind of classes that emerge from "utility-first" tend to be design-centered (e.g. `.button`, `.alert`, `.card`) rather than domain-centered (e.g. `.security-report-widget`, `.commit-header-icon`).
-Examples of component classes that were created using "utility-first" include:
-
-- [`.circle-icon-container`](https://gitlab.com/gitlab-org/gitlab/blob/579fa8b8ec7eb38d40c96521f517c9dab8c3b97a/app/assets/stylesheets/framework/icons.scss#L85)
-- [`.d-flex-center`](https://gitlab.com/gitlab-org/gitlab/blob/900083d89cd6af391d26ab7922b3f64fa2839bef/app/assets/stylesheets/framework/common.scss#L425)
-
Inspiration:
- <https://tailwindcss.com/docs/utility-first>
diff --git a/doc/development/fe_guide/style/vue.md b/doc/development/fe_guide/style/vue.md
index 1a64db443bc..6b6ca9a6c71 100644
--- a/doc/development/fe_guide/style/vue.md
+++ b/doc/development/fe_guide/style/vue.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Vue.js style guide
## Linting
@@ -51,6 +57,66 @@ Please check this [rules](https://github.com/vuejs/eslint-plugin-vue#bulb-rules)
1. Use `.vue` for Vue templates. Do not use `%template` in HAML.
+1. Explicitly define data being passed into the Vue app
+
+ ```javascript
+ // bad
+ return new Vue({
+ el: '#element',
+ components: {
+ componentName
+ },
+ provide: {
+ ...someDataset
+ },
+ props: {
+ ...anotherDataset
+ },
+ render: createElement => createElement('component-name'),
+ }));
+
+ // good
+ const { foobar, barfoo } = someDataset;
+ const { foo, bar } = anotherDataset;
+
+ return new Vue({
+ el: '#element',
+ components: {
+ componentName
+ },
+ provide: {
+ foobar,
+ barfoo
+ },
+ props: {
+ foo,
+ bar
+ },
+ render: createElement => createElement('component-name'),
+ }));
+ ```
+
+ We discourage the use of the spread operator in this specific case in
+ order to keep our codebase explicit, discoverable, and searchable.
+ This applies in any place where we'll benefit from the above, such as
+ when [initializing Vuex state](../vuex.md#why-not-just-spread-the-initial-state).
+ The pattern above also enables us to easily parse non scalar values during
+ instantiation.
+
+ ```javascript
+ return new Vue({
+ el: '#element',
+ components: {
+ componentName
+ },
+ props: {
+ foo,
+ bar: parseBoolean(bar)
+ },
+ render: createElement => createElement('component-name'),
+ }));
+ ```
+
## Naming
1. **Extensions**: Use `.vue` extension for Vue components. Do not use `.js` as file extension ([#34371](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34371)).
@@ -184,7 +250,7 @@ Please check this [rules](https://github.com/vuejs/eslint-plugin-vue#bulb-rules)
```
1. Default key should be provided if the prop is not required.
- _Note:_ There are some scenarios where we need to check for the existence of the property.
+ There are some scenarios where we need to check for the existence of the property.
On those a default key should not be provided.
```javascript
@@ -400,6 +466,199 @@ Useful links:
$('span').tooltip('_fixTitle');
```
+## Vue testing
+
+Over time, a number of programming patterns and style preferences have emerged in our efforts to effectively test Vue components.
+The following guide describes some of these. **These are not strict guidelines**, but rather a collection of suggestions and
+good practices that aim to provide insight into how we write Vue tests at GitLab.
+
+### Mounting a component
+
+Typically, when testing a Vue component, the component should be "re-mounted" in every test block.
+
+To achieve this:
+
+1. Create a mutable `wrapper` variable inside the top-level `describe` block.
+1. Mount the component using [`mount`](https://vue-test-utils.vuejs.org/api/#mount)/[`shallowMount`](https://vue-test-utils.vuejs.org/api/#shallowMount).
+1. Reassign the resulting [`Wrapper`](https://vue-test-utils.vuejs.org/api/wrapper/#wrapper) instance to our `wrapper` variable.
+
+Creating a global, mutable wrapper provides a number of advantages, including the ability to:
+
+- Define common functions for finding components/DOM elements:
+
+ ```javascript
+ import MyComponent from '~/path/to/my_component.vue';
+ describe('MyComponent', () => {
+ let wrapper;
+
+ // this can now be reused across tests
+ const findMyComponent = wrapper.find(MyComponent);
+ // ...
+ })
+ ```
+
+- Use a `beforeEach` block to mount the component (see [the `createComponent` factory](#the-createcomponent-factory) for more information).
+- Use an `afterEach` block to destroy the component, for example, `wrapper.destroy()`.
+
+#### The `createComponent` factory
+
+To avoid duplicating our mounting logic, it's useful to define a `createComponent` factory function
+that we can reuse in each test block. This is a closure which should reassign our `wrapper` variable
+to the result of [`mount`](https://vue-test-utils.vuejs.org/api/#mount) and [`shallowMount`](https://vue-test-utils.vuejs.org/api/#shallowMount):
+
+```javascript
+import MyComponent from '~/path/to/my_component.vue';
+import { shallowMount } from '@vue/test-utils';
+
+describe('MyComponent', () => {
+ // Initiate the "global" wrapper variable. This will be used throughout our test:
+ let wrapper;
+
+ // Define our `createComponent` factory:
+ function createComponent() {
+ // Mount component and reassign `wrapper`:
+ wrapper = shallowMount(MyComponent);
+ }
+
+ it('mounts', () => {
+ createComponent();
+
+ expect(wrapper.exists()).toBe(true);
+ });
+
+ it('`isLoading` prop defaults to `false`', () => {
+ createComponent();
+
+ expect(wrapper.props('isLoading')).toBe(false);
+ });
+})
+```
+
+Similarly, we could further de-duplicate our test by calling `createComponent` in a `beforeEach` block:
+
+```javascript
+import MyComponent from '~/path/to/my_component.vue';
+import { shallowMount } from '@vue/test-utils';
+
+describe('MyComponent', () => {
+ // Initiate the "global" wrapper variable. This will be used throughout our test
+ let wrapper;
+
+ // define our `createComponent` factory
+ function createComponent() {
+ // mount component and reassign `wrapper`
+ wrapper = shallowMount(MyComponent);
+ }
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('mounts', () => {
+ expect(wrapper.exists()).toBe(true);
+ });
+
+ it('`isLoading` prop defaults to `false`', () => {
+ expect(wrapper.props('isLoading')).toBe(false);
+ });
+})
+```
+
+#### `createComponent` best practices
+
+1. Consider using a single (or a limited number of) object arguments over many arguments.
+ Defining single parameters for common data like `props` is okay,
+ but keep in mind our [JavaScript style guide](javascript.md#limit-number-of-parameters) and stay within the parameter number limit:
+
+ ```javascript
+ // bad
+ function createComponent(data, props, methods, isLoading, mountFn) { }
+
+ // good
+ function createComponent({ data, props, methods, stubs, isLoading } = {}) { }
+
+ // good
+ function createComponent(props = {}, { data, methods, stubs, isLoading } = {}) { }
+ ```
+
+1. If you require both `mount` _and_ `shallowMount` within the same set of tests, it
+can be useful define a `mountFn` parameter for the `createComponent` factory that accepts
+the mounting function (`mount` or `shallowMount`) to be used to mount the component:
+
+ ```javascript
+ import { shallowMount } from '@vue/test-utils';
+
+ function createComponent({ mountFn = shallowMount } = {}) { }
+ ```
+
+### Setting component state
+
+1. Avoid using [`setProps`](https://vue-test-utils.vuejs.org/api/wrapper/#setprops) to set
+component state wherever possible. Instead, set the component's
+[`propsData`](https://vue-test-utils.vuejs.org/api/options.html#propsdata) when mounting the component:
+
+ ```javascript
+ // bad
+ wrapper = shallowMount(MyComponent);
+ wrapper.setProps({
+ myProp: 'my cool prop'
+ });
+
+ // good
+ wrapper = shallowMount({ propsData: { myProp: 'my cool prop' } });
+ ```
+
+ The exception here is when you wish to test component reactivity in some way.
+ For example, you may want to test the output of a component when after a particular watcher has executed.
+ Using `setProps` to test such behavior is okay.
+
+### Accessing component state
+
+1. When accessing props or attributes, prefer the `wrapper.props('myProp')` syntax over `wrapper.props().myProp`:
+
+ ```javascript
+ // good
+ expect(wrapper.props().myProp).toBe(true);
+ expect(wrapper.attributes().myAttr).toBe(true);
+
+ // better
+ expect(wrapper.props('myProp').toBe(true);
+ expect(wrapper.attributes('myAttr')).toBe(true);
+ ```
+
+1. When asserting multiple props, check the deep equality of the `props()` object with [`toEqual`](https://jestjs.io/docs/en/expect#toequalvalue):
+
+ ```javascript
+ // good
+ expect(wrapper.props('propA')).toBe('valueA');
+ expect(wrapper.props('propB')).toBe('valueB');
+ expect(wrapper.props('propC')).toBe('valueC');
+
+ // better
+ expect(wrapper.props()).toEqual({
+ propA: 'valueA',
+ propB: 'valueB',
+ propC: 'valueC',
+ });
+ ```
+
+1. If you are only interested in some of the props, you can use [`toMatchObject`](https://jestjs.io/docs/en/expect#tomatchobjectobject).
+Prefer `toMatchObject` over [`expect.objectContaining`](https://jestjs.io/docs/en/expect#expectobjectcontainingobject):
+
+ ```javascript
+ // good
+ expect(wrapper.props()).toEqual(expect.objectContaining({
+ propA: 'valueA',
+ propB: 'valueB',
+ }));
+
+ // better
+ expect(wrapper.props()).toMatchObject({
+ propA: 'valueA',
+ propB: 'valueB',
+ });
+ ```
+
## The JavaScript/Vue Accord
The goal of this accord is to make sure we are all on the same page.
diff --git a/doc/development/fe_guide/tooling.md b/doc/development/fe_guide/tooling.md
index b93c0a9736b..809e05ea61f 100644
--- a/doc/development/fe_guide/tooling.md
+++ b/doc/development/fe_guide/tooling.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Tooling
## ESLint
@@ -14,7 +20,7 @@ To check all currently staged files (based on `git diff`) with ESLint, run the f
yarn eslint-staged
```
-_A list of problems found will be logged to the console._
+A list of problems found will be logged to the console.
To apply automatic ESLint fixes to all currently staged files (based on `git diff`), run the following script:
@@ -22,7 +28,7 @@ To apply automatic ESLint fixes to all currently staged files (based on `git dif
yarn eslint-staged-fix
```
-_If manual changes are required, a list of changes will be sent to the console._
+If manual changes are required, a list of changes will be sent to the console.
To check **all** files in the repository with ESLint, run the following script:
@@ -30,7 +36,7 @@ To check **all** files in the repository with ESLint, run the following script:
yarn eslint
```
-_A list of problems found will be logged to the console._
+A list of problems found will be logged to the console.
To apply automatic ESLint fixes to **all** files in the repository, run the following script:
@@ -38,7 +44,7 @@ To apply automatic ESLint fixes to **all** files in the repository, run the foll
yarn eslint-fix
```
-_If manual changes are required, a list of changes will be sent to the console._
+If manual changes are required, a list of changes will be sent to the console.
CAUTION: **Caution:**
Limit use to global rule updates. Otherwise, the changes can lead to huge Merge Requests.
@@ -54,9 +60,8 @@ rules only if you are invoking/instantiating existing code modules.
- [`no-new`](https://eslint.org/docs/rules/no-new)
- [`class-method-use-this`](https://eslint.org/docs/rules/class-methods-use-this)
-NOTE: **Note:**
-Disable these rules on a per-line basis. This makes it easier to refactor
-in the future. E.g. use `eslint-disable-next-line` or `eslint-disable-line`.
+Disable these rules on a per-line basis. This makes it easier to refactor in the
+future. For example, use `eslint-disable-next-line` or `eslint-disable-line`.
### Disabling ESLint for a single violation
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 58a8332589d..77bdadfe8da 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Vue
To get started with Vue, read through [their documentation](https://vuejs.org/v2/guide/).
@@ -47,7 +53,7 @@ of the new feature should be.
The Store and the Service should be imported and initialized in this file and
provided as a prop to the main component.
-Be sure to read about [page-specific JavaScript](./performance.md#page-specific-javascript).
+Be sure to read about [page-specific JavaScript](performance.md#page-specific-javascript).
### Bootstrapping Gotchas
@@ -56,33 +62,36 @@ Be sure to read about [page-specific JavaScript](./performance.md#page-specific-
While mounting a Vue application, you might need to provide data from Rails to JavaScript.
To do that, you can use the `data` attributes in the HTML element and query them while mounting the application.
-_Note:_ You should only do this while initializing the application, because the mounted element will be replaced with Vue-generated DOM.
+You should only do this while initializing the application, because the mounted element will be replaced with Vue-generated DOM.
The advantage of providing data from the DOM to the Vue instance through `props` in the `render` function
instead of querying the DOM inside the main Vue component is avoiding the need to create a fixture or an HTML element in the unit test,
-which will make the tests easier. See the following example:
+which will make the tests easier.
+
+See the following example, also, please refer to our [Vue style guide](style/vue.md#basic-rules) for additional
+information on why we explicitly declare the data being passed into the Vue app;
```javascript
// haml
#js-vue-app{ data: { endpoint: 'foo' }}
// index.js
-document.addEventListener('DOMContentLoaded', () => new Vue({
- el: '#js-vue-app',
- data() {
- const dataset = this.$options.el.dataset;
- return {
- endpoint: dataset.endpoint,
- };
- },
+const el = document.getElementById('js-vue-app');
+
+if (!el) return false;
+
+const { endpoint } = el.dataset;
+
+return new Vue({
+ el,
render(createElement) {
return createElement('my-component', {
props: {
- endpoint: this.endpoint,
+ endpoint
},
});
},
-}));
+}
```
> When adding an `id` attribute to mount a Vue application, please make sure this `id` is unique across the codebase
@@ -94,7 +103,7 @@ By following this practice, we can avoid the need to mock the `gl` object, which
It should be done while initializing our Vue instance, and the data should be provided as `props` to the main component:
```javascript
-document.addEventListener('DOMContentLoaded', () => new Vue({
+return new Vue({
el: '.js-vue-app',
render(createElement) {
return createElement('my-component', {
@@ -103,7 +112,7 @@ document.addEventListener('DOMContentLoaded', () => new Vue({
},
});
},
-}));
+});
```
#### Accessing feature flags
@@ -111,7 +120,7 @@ document.addEventListener('DOMContentLoaded', () => new Vue({
Use Vue's [provide/inject](https://vuejs.org/v2/api/#provide-inject) mechanism
to make feature flags available to any descendant components in a Vue
application. The `glFeatures` object is already provided in `commons/vue.js`, so
-only the mixin is required to utilize the flags:
+only the mixin is required to use the flags:
```javascript
// An arbitrary descendant component
@@ -179,13 +188,40 @@ Check this [page](vuex.md) for more details.
- It is acceptable for Vue to listen to existing jQuery events using jQuery event listeners.
- It is not recommended to add new jQuery events for Vue to interact with jQuery.
+### Mixing Vue and JavaScript classes (in the data function)
+
+In the [Vue documentation](https://vuejs.org/v2/api/#Options-Data) the Data function/object is defined as follows:
+
+> The data object for the Vue instance. Vue will recursively convert its properties into getter/setters to make it “reactiveâ€. The object must be plain: native objects such as browser API objects and prototype properties are ignored. A rule of thumb is that data should just be data - it is not recommended to observe objects with their own stateful behavior.
+
+Based on the Vue guidance:
+
+- **Do not** use or create a JavaScript class in your [data function](https://vuejs.org/v2/api/#data), such as `user: new User()`.
+- **Do not** add new JavaScript class implementations.
+- **Do** use [GraphQL](../api_graphql_styleguide.md), [Vuex](vuex.md) or a set of components if cannot use simple primitives or objects.
+- **Do** maintain existing implementations using such approaches.
+- **Do** Migrate components to a pure object model when there are substantial changes to it.
+- **Do** add business logic to helpers or utils, so you can test them separately from your component.
+
+#### Why
+
+There are additional reasons why having a JavaScript class presents maintainability issues on a huge codebase:
+
+- Once a class is created, it is easy to extend it in a way that can infringe Vue reactivity and best practices.
+- A class adds a layer of abstraction, which makes the component API and its inner workings less clear.
+- It makes it harder to test. Since the class is instantiated by the component data function, it is harder to 'manage' component and class separately.
+- Adding OOP to a functional codebase adds yet another way of writing code, reducing consistency and clarity.
+
## Style guide
Please refer to the Vue section of our [style guide](style/vue.md)
-for best practices while writing your Vue components and templates.
+for best practices while writing and testing your Vue components and templates.
## Testing Vue Components
+Please refer to the [Vue testing style guide](style/vue.md#vue-testing)
+for guidelines and best practices for testing your Vue components.
+
Each Vue component has a unique output. This output is always present in the render function.
Although we can test each method of a Vue component individually, our goal must be to test the output
@@ -226,7 +262,7 @@ describe('~/todos/app.vue', () => {
mock.restore();
});
- // NOTE: It is very helpful to separate setting up the component from
+ // It is very helpful to separate setting up the component from
// its collaborators (i.e. Vuex, axios, etc.)
const createWrapper = (props = {}) => {
wrapper = shallowMount(App, {
@@ -236,7 +272,7 @@ describe('~/todos/app.vue', () => {
},
});
};
- // NOTE: Helper methods greatly help test maintainability and readability.
+ // Helper methods greatly help test maintainability and readability.
const findLoader = () => wrapper.find(GlLoadingIcon);
const findAddButton = () => wrapper.find('[data-testid="add-button"]');
const findTextInput = () => wrapper.find('[data-testid="text-input"]');
diff --git a/doc/development/fe_guide/vue3_migration.md b/doc/development/fe_guide/vue3_migration.md
index afdb2690c02..46437f39dbe 100644
--- a/doc/development/fe_guide/vue3_migration.md
+++ b/doc/development/fe_guide/vue3_migration.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Migration to Vue 3
In order to prepare for the eventual migration to Vue 3.x, we should be wary about adding the following features to the codebase:
@@ -76,7 +82,6 @@ const FunctionalComp = (props, slots) => {
}
```
-NOTE: **Note:**
It is not recommended to replace stateful components with functional components unless you absolutely need a performance improvement right now. In Vue 3, performance gains for functional components will be negligible.
## Old slots syntax with `slot` attribute
diff --git a/doc/development/fe_guide/vuex.md b/doc/development/fe_guide/vuex.md
index 528dcb3b7f4..7765ba04d40 100644
--- a/doc/development/fe_guide/vuex.md
+++ b/doc/development/fe_guide/vuex.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Vuex
When there's a clear benefit to separating state management from components (e.g. due to state complexity) we recommend using [Vuex](https://vuex.vuejs.org) over any other Flux pattern. Otherwise, feel free to manage state within the components.
@@ -9,14 +15,14 @@ Vuex should be strongly considered when:
- There are complex interactions with Backend, e.g. multiple API calls
- The app involves interacting with backend via both traditional REST API and GraphQL (especially when moving the REST API over to GraphQL is a pending backend task)
-_Note:_ All of the below is explained in more detail in the official [Vuex documentation](https://vuex.vuejs.org).
+The information included in this page is explained in more detail in the
+official [Vuex documentation](https://vuex.vuejs.org).
## Separation of concerns
Vuex is composed of State, Getters, Mutations, Actions, and Modules.
-When a user clicks on an action, we need to `dispatch` it. This action will `commit` a mutation that will change the state.
-_Note:_ The action itself will not update the state, only a mutation should update the state.
+When a user clicks on an action, we need to `dispatch` it. This action will `commit` a mutation that will change the state. The action itself will not update the state; only a mutation should update the state.
## File structure
@@ -60,7 +66,7 @@ export const createStore = () =>
The first thing you should do before writing any code is to design the state.
-Often we need to provide data from haml to our Vue application. Let's store it in the state for better access.
+Often we need to provide data from HAML to our Vue application. Let's store it in the state for better access.
```javascript
export default () => ({
@@ -354,8 +360,8 @@ export default initialState => ({
```
We've made the conscious decision to avoid this pattern to aid in the
-discoverability and searchability of our frontend codebase. The reasoning for
-this is described in [this
+discoverability and searchability of our frontend codebase. The same applies
+when [providing data to a Vue app](vue.md#providing-data-from-haml-to-javascript). The reasoning for this is described in [this
discussion](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/56#note_302514865):
> Consider a `someStateKey` is being used in the store state. You _may_ not be
diff --git a/doc/development/feature_categorization/index.md b/doc/development/feature_categorization/index.md
index 57e0ad8b772..66ed2952250 100644
--- a/doc/development/feature_categorization/index.md
+++ b/doc/development/feature_categorization/index.md
@@ -1,8 +1,14 @@
+---
+stage: Enablement
+group: Infrastructure
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Feature Categorization
> [Introduced](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/269) in GitLab 13.2.
-Each Sidekiq worker, controller action, or (eventually) API endpoint
+Each Sidekiq worker, controller action, or API endpoint
must declare a `feature_category` attribute. This attribute maps each
of these to a [feature
category](https://about.gitlab.com/handbook/product/product-categories/). This
@@ -112,3 +118,42 @@ assigned to all actions.
The spec also validates if the used feature categories are known. And if
the actions used in configuration still exist as routes.
+
+## API endpoints
+
+Grape API endpoints can use the `feature_category` class method, like
+[Rails controllers](#rails-controllers) do:
+
+```ruby
+module API
+ class Issues < ::API::Base
+ feature_category :issue_tracking
+ end
+end
+```
+
+The second argument can be used to specify feature categories for
+specific routes:
+
+```ruby
+module API
+ class Users < ::API::Base
+ feature_category :users, ['/users/:id/custom_attributes', '/users/:id/custom_attributes/:key']
+ end
+end
+```
+
+Or the feature category can be specified in the action itself:
+
+```ruby
+module API
+ class Users < ::API::Base
+ get ':id', feature_category: :users do
+ end
+ end
+end
+```
+
+As with Rails controllers, an API class must specify the category for
+every single action unless the same category is used for every action
+within that class.
diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md
index ef38a85bec0..df737912c00 100644
--- a/doc/development/feature_flags/controls.md
+++ b/doc/development/feature_flags/controls.md
@@ -92,9 +92,7 @@ Guidelines:
1. If the feature meets the requirements for creating a [Change Management](https://about.gitlab.com/handbook/engineering/infrastructure/change-management/#feature-flags-and-the-change-management-process) issue, create a Change Management issue per [criticality guidelines](https://about.gitlab.com/handbook/engineering/infrastructure/change-management/#change-request-workflows).
1. For simple, low-risk, easily reverted features, proceed and [enable the feature in `#production`](#process).
-1. For features that impact the user experience, consider notifying
- `#support_gitlab-com` first.
- `#support_gitlab-com` beforehand.
+1. For features that impact the user experience, consider notifying `#support_gitlab-com` beforehand.
#### Process
@@ -215,7 +213,6 @@ actors.
Feature.enabled?(:some_feature, group)
```
-NOTE: **Note:**
**Percentage of time** rollout is not a good idea if what you want is to make sure a feature
is always on or off to the users. In that case, **Percentage of actors** rollout is a better method.
diff --git a/doc/development/feature_flags/development.md b/doc/development/feature_flags/development.md
index 067e480f6f8..2855662e1db 100644
--- a/doc/development/feature_flags/development.md
+++ b/doc/development/feature_flags/development.md
@@ -35,7 +35,6 @@ used so that unfinished code can be deployed in production.
A `development` feature flag should have a rollout issue,
ideally created using the [Feature Flag Roll Out template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20Flag%20Roll%20Out.md).
-NOTE: **Note:**
This is the default type used when calling `Feature.enabled?`.
### `ops` type
@@ -61,30 +60,6 @@ Feature.disabled?(:my_ops_flag, project, type: :ops)
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.
@@ -128,7 +103,7 @@ a YAML definition in `config/feature_flags` or `ee/config/feature_flags`.
Only feature flags that have a YAML definition file can be used when running the development or testing environments.
```shell
-$ bin/feature-flag my-feature-flag
+$ bin/feature-flag my_feature_flag
>> Specify the group introducing the feature flag, like `group::apm`:
?> group::memory
@@ -140,9 +115,9 @@ https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue%5Btitle%5D=%5BFeature+fl
>> URL of the rollout issue (enter to skip):
?> https://gitlab.com/gitlab-org/gitlab/-/issues/232533
-create config/feature_flags/development/test-flag.yml
+create config/feature_flags/development/my_feature_flag.yml
---
-name: test-flag
+name: my_feature_flag
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38602
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/232533
group: group::memory
@@ -212,6 +187,30 @@ if Feature.disabled?(:my_feature_flag, project, type: :ops)
end
```
+DANGER: **Warning:**
+Don't use feature flags at application load time. For example, using the `Feature` class in
+`config/initializers/*` or at the class level could cause an unexpected error. This error occurs
+because a database that a feature flag adapter might depend on doesn't exist at load time
+(especially for fresh installations). Checking for the database's existence at the caller isn't
+recommended, as some adapters don't require a database at all (for example, the HTTP adapter). The
+feature flag setup check must be abstracted in the `Feature` namespace. This approach also requires
+application reload when the feature flag changes. You must therefore ask SREs to reload the
+Web/API/Sidekiq fleet on production, which takes time to fully rollout/rollback the changes. For
+these reasons, use environment variables (for example, `ENV['YOUR_FEATURE_NAME']`) or `gitlab.yml`
+instead.
+
+Here's an example of a pattern that you should avoid:
+
+```ruby
+class MyClass
+ if Feature.enabled?(:...)
+ new_process
+ else
+ legacy_process
+ end
+end
+```
+
### Frontend
Use the `push_frontend_feature_flag` method for frontend code, which is
@@ -309,57 +308,16 @@ 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 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.
-
-The [`Project#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/app/models/project_feature.rb#L63-68),
-[`Namespace#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/ee/namespace.rb#L71-85) (EE), and
-[`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.
-
-**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 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
-[alpha or beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga), and
-should not be available by default.
-
-As an example, if you were to ship the frontend half of a feature without the
-backend, you'd want to disable the feature entirely until the backend half is
-also ready to be shipped. To make sure this feature is disabled for both
-GitLab.com and self-managed instances, you should use the
-[`Namespace#alpha_feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/458749872f4a8f27abe8add930dbb958044cb926/ee/app/models/ee/namespace.rb#L113) or
-[`Namespace#beta_feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/458749872f4a8f27abe8add930dbb958044cb926/ee/app/models/ee/namespace.rb#L100-112)
-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).
+You can't use a feature flag with the same name as a licensed feature name, because
+it would cause a naming collision. This was [widely discussed and removed](https://gitlab.com/gitlab-org/gitlab/-/issues/259611)
+because it is confusing.
-The resulting YAML should be similar to:
+To check for licensed features, add a dedicated feature flag under a different name
+and check it explicitly, for example:
-```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]
+```ruby
+Feature.enabled?(:licensed_feature_feature_flag, project) &&
+ project.feature_available?(:licensed_feature)
```
### Feature groups
@@ -397,7 +355,6 @@ Introducing a feature flag into the codebase creates an additional code path tha
It is strongly advised to test all code affected by a feature flag, both when **enabled** and **disabled**
to ensure the feature works properly.
-NOTE: **Note:**
When using the testing environment, all feature flags are enabled by default.
To disable a feature flag in a test, use the `stub_feature_flags`
diff --git a/doc/development/feature_flags/index.md b/doc/development/feature_flags/index.md
index 2643571aec3..a867bcf792a 100644
--- a/doc/development/feature_flags/index.md
+++ b/doc/development/feature_flags/index.md
@@ -1,5 +1,4 @@
---
-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"
diff --git a/doc/development/feature_flags/process.md b/doc/development/feature_flags/process.md
index b327eec58e8..b282424f59a 100644
--- a/doc/development/feature_flags/process.md
+++ b/doc/development/feature_flags/process.md
@@ -80,7 +80,7 @@ In order to build a final release and present the feature for self-managed
users, the feature flag should be at least defaulted to **on**. If the feature
is deemed stable and there is confidence that removing the feature flag is safe,
consider removing the feature flag altogether. It's _strongly_ recommended that
-the feature flag is [enabled **globally** on **production**](./controls.md#enabling-a-feature-for-gitlabcom) for **at least one day**
+the feature flag is [enabled **globally** on **production**](controls.md#enabling-a-feature-for-gitlabcom) for **at least one day**
before making this decision. Unexpected bugs are sometimes discovered during this period.
The process for enabling features that are disabled by default can take 5-6 days
diff --git a/doc/development/features_inside_dot_gitlab.md b/doc/development/features_inside_dot_gitlab.md
index cb883471adf..e8918c76d04 100644
--- a/doc/development/features_inside_dot_gitlab.md
+++ b/doc/development/features_inside_dot_gitlab.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# 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.
diff --git a/doc/development/file_storage.md b/doc/development/file_storage.md
index e8ae5a11d48..aa91e105513 100644
--- a/doc/development/file_storage.md
+++ b/doc/development/file_storage.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# File Storage in GitLab
We use the [CarrierWave](https://github.com/carrierwaveuploader/carrierwave) gem to handle file upload, store and retrieval.
@@ -50,10 +56,10 @@ In the case of Issues/MR/Notes Markdown attachments, there is a different approa
instead of basing the path into a mutable variable `:project_path_with_namespace`, it's possible to use the
hash of the project ID instead, if project migrates to the new approach (introduced in 10.2).
-> Note: We provide an [all-in-one Rake task](../administration/raketasks/uploads/migrate.md) to migrate all uploads to object
-> storage in one go. If a new Uploader class or model type is introduced, make
-> sure you add a Rake task invocation corresponding to it to the
-> [category list](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/tasks/gitlab/uploads/migrate.rake).
+We provide an [all-in-one Rake task](../administration/raketasks/uploads/migrate.md)
+to migrate all uploads to object storage in one go. If a new Uploader class or model
+type is introduced, make sure you add a Rake task invocation corresponding to it to the
+[category list](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/tasks/gitlab/uploads/migrate.rake).
### Path segments
@@ -101,7 +107,7 @@ The `CarrierWave::Uploader#store_dir` is overridden to
### Using `ObjectStorage::Extension::RecordsUploads`
-> Note: this concern will automatically include `RecordsUploads::Concern` if not already included.
+This concern will automatically include `RecordsUploads::Concern` if not already included.
The `ObjectStorage::Concern` uploader will search for the matching `Upload` to select the correct object store. The `Upload` is mapped using `#store_dirs + identifier` for each store (LOCAL/REMOTE).
diff --git a/doc/development/foreign_keys.md b/doc/development/foreign_keys.md
index 8a81dc158a7..ff8c03ce76b 100644
--- a/doc/development/foreign_keys.md
+++ b/doc/development/foreign_keys.md
@@ -1,3 +1,9 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Foreign Keys & Associations
When adding an association to a model you must also add a foreign key. For
diff --git a/doc/development/gemfile.md b/doc/development/gemfile.md
index 8d93c52e7bc..1daa3ad5cba 100644
--- a/doc/development/gemfile.md
+++ b/doc/development/gemfile.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# `Gemfile` guidelines
When adding a new entry to `Gemfile` or upgrading an existing dependency pay
diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md
index 55f4be07bb4..e440e324c4a 100644
--- a/doc/development/geo/framework.md
+++ b/doc/development/geo/framework.md
@@ -4,17 +4,12 @@ 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
---
-# Geo self-service framework (alpha)
+# Geo self-service framework
NOTE: **Note:**
-This document might be subjected to change. It's a
-proposal we're working on and once the implementation is complete this
-documentation will be updated. Follow progress in the
-[epic](https://gitlab.com/groups/gitlab-org/-/epics/2161).
-
-NOTE: **Note:**
-The Geo self-service framework is currently in
-alpha. If you need to replicate a new data type, reach out to the Geo
+This document is subject to change as we continue to implement and iterate on the framework.
+Follow the progress in the [epic](https://gitlab.com/groups/gitlab-org/-/epics/2161).
+If you need to replicate a new data type, reach out to the Geo
team to discuss the options. You can contact them in `#g_geo` on Slack
or mention `@geo-team` in the issue or merge request.
@@ -26,38 +21,40 @@ minimal effort of the engineer who created a data type.
## Nomenclature
Before digging into the API, developers need to know some Geo-specific
-naming conventions.
+naming conventions:
-Model
-: A model is an Active Model, which is how it is known in the entire
+- **Model**:
+ A model is an Active Model, which is how it is known in the entire
Rails codebase. It usually is tied to a database table. From Geo
perspective, a model can have one or more resources.
-Resource
-: A resource is a piece of data that belongs to a model and is
+- **Resource**:
+ A resource is a piece of data that belongs to a model and is
produced by a GitLab feature. It is persisted using a storage
- mechanism. By default, a resource is not a replicable.
+ mechanism. By default, a resource is not a Geo replicable.
-Data type
-: Data type is how a resource is stored. Each resource should
+- **Data type**:
+ Data type is how a resource is stored. Each resource should
fit in one of the data types Geo supports:
-:- Git repository
-:- Blob
-:- Database
-: For more detail, see [Data types](../../administration/geo/replication/datatypes.md).
+ - Git repository
+ - Blob
+ - Database
+
+ For more detail, see [Data types](../../administration/geo/replication/datatypes.md).
-Geo Replicable
-: A Replicable is a resource Geo wants to sync across Geo nodes. There
+- **Geo Replicable**:
+ A Replicable is a resource Geo wants to sync across Geo nodes. There
is a limited set of supported data types of replicables. The effort
required to implement replication of a resource that belongs to one
of the known data types is minimal.
-Geo Replicator
-: A Geo Replicator is the object that knows how to replicate a
+- **Geo Replicator**:
+ A Geo Replicator is the object that knows how to replicate a
replicable. It's responsible for:
-:- Firing events (producer)
-:- Consuming events (consumer)
-: It's tied to the Geo Replicable data type. All replicators have a
+ - Firing events (producer)
+ - Consuming events (consumer)
+
+ It's tied to the Geo Replicable data type. All replicators have a
common interface that can be used to process (that is, produce and
consume) events. It takes care of the communication between the
primary node (where events are produced) and the secondary node
@@ -65,8 +62,8 @@ Geo Replicator
Geo in their feature will use the API of replicators to make this
happen.
-Geo Domain-Specific Language
-: The syntactic sugar that allows engineers to easily specify which
+- **Geo Domain-Specific Language**:
+ The syntactic sugar that allows engineers to easily specify which
resources should be replicated and how.
## Geo Domain-Specific Language
@@ -144,7 +141,7 @@ replicator.model_record
```
The replicator can be used to generate events, for example in
-ActiveRecord hooks:
+`ActiveRecord` hooks:
```ruby
after_create_commit -> { replicator.publish_created_event }
@@ -207,9 +204,12 @@ For example, to add support for files referenced by a `Widget` model with a
end
```
+ If there is a common constraint for records to be available for replication,
+ make sure to also overwrite the `available_replicables` scope.
+
1. Create `ee/app/replicators/geo/widget_replicator.rb`. Implement the
- `#carrierwave_uploader` method which should return a `CarrierWave::Uploader`.
- And implement the class method `.model` to return the `Widget` class.
+ `#carrierwave_uploader` method which should return a `CarrierWave::Uploader`,
+ and implement the class method `.model` to return the `Widget` class:
```ruby
# frozen_string_literal: true
@@ -236,7 +236,7 @@ For example, to add support for files referenced by a `Widget` model with a
```
1. Add this replicator class to the method `replicator_classes` in
-`ee/lib/gitlab/geo.rb`:
+ `ee/lib/gitlab/geo.rb`:
```ruby
REPLICATOR_CLASSES = [
@@ -247,8 +247,8 @@ For example, to add support for files referenced by a `Widget` model with a
```
1. Create `ee/spec/replicators/geo/widget_replicator_spec.rb` and perform
- the setup necessary to define the `model_record` variable for the shared
- examples.
+ the necessary setup to define the `model_record` variable for the shared
+ examples:
```ruby
# frozen_string_literal: true
@@ -319,9 +319,7 @@ For example, to add support for files referenced by a `Widget` model with a
```
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`.
-
1. Create `ee/spec/factories/geo/widget_registry.rb`:
```ruby
@@ -375,17 +373,17 @@ For example, to add support for files referenced by a `Widget` model with a
end
```
-Widgets should now be replicated by Geo!
+Widgets should now be replicated by Geo.
#### Verification
There are two ways to add verification related fields so that the Geo primary
-can track verification state:
+can track verification state.
##### Option 1: Add verification state fields to the existing `widgets` table itself
1. Add a migration to add columns ordered according to [our guidelines](../ordering_table_columns.md)
-for verification state to the widgets table:
+ for verification state to the widgets table:
```ruby
# frozen_string_literal: true
@@ -462,7 +460,7 @@ for verification state to the widgets table:
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):
+ the columns according to [the guidelines](../ordering_table_columns.md):
```ruby
# frozen_string_literal: true
@@ -520,12 +518,12 @@ for verification state to the widgets table:
To do: Add verification on secondaries. This should be done as part of
[Geo: Self Service Framework - First Implementation for Package File verification](https://gitlab.com/groups/gitlab-org/-/epics/1817)
-Widgets should now be verified by Geo!
+Widgets should now be verified by Geo.
#### Metrics
Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in
-`GeoNodeStatus` for display in the UI, and sent to Prometheus.
+`GeoNodeStatus` for display in the UI, and sent to Prometheus:
1. Add fields `widgets_count`, `widgets_checksummed_count`,
`widgets_checksum_failed_count`, `widgets_synced_count`,
@@ -560,8 +558,12 @@ Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in
end
```
+1. Make sure the factory also allows setting a `project` attribute. If the model
+ does not have a direct relation to a project, you can use a `transient`
+ attribute. Check out `spec/factories/merge_request_diffs.rb` for an example.
+
Widget replication and verification metrics should now be available in the API,
-the Admin Area UI, and Prometheus!
+the Admin Area UI, and Prometheus.
#### GraphQL API
@@ -578,7 +580,6 @@ the Admin Area UI, and Prometheus!
1. Add the new `widget_registries` field name to the `expected_fields` array in
`ee/spec/graphql/types/geo/geo_node_type_spec.rb`.
-
1. Create `ee/app/graphql/resolvers/geo/widget_registries_resolver.rb`:
```ruby
@@ -687,14 +688,14 @@ the Admin Area UI, and Prometheus!
```
Individual widget synchronization and verification data should now be available
-via the GraphQL API!
+via the GraphQL API.
-1. Take care of replicating "update" events. Geo Framework does not currently support
- replicating "update" events because all entities added to the framework, by this time,
- are immutable. If this is the case
- for the entity you're going to add, please follow <https://gitlab.com/gitlab-org/gitlab/-/issues/118743>
- and <https://gitlab.com/gitlab-org/gitlab/-/issues/118745> as examples to add the new event type.
- Please also remove this notice when you've added it.
+Make sure to replicate the "update" events. Geo Framework does not currently support
+replicating "update" events because all entities added to the framework, by this time,
+are immutable. If this is the case
+for the entity you're going to add, follow <https://gitlab.com/gitlab-org/gitlab/-/issues/118743>
+and <https://gitlab.com/gitlab-org/gitlab/-/issues/118745> as examples to add the new event type.
+Also, remove this notice when you've added it.
#### Admin UI
@@ -702,7 +703,7 @@ To do: This should be done as part of
[Geo: Implement frontend for Self-Service Framework replicables](https://gitlab.com/groups/gitlab-org/-/epics/2525)
Widget sync and verification data (aggregate and individual) should now be
-available in the Admin UI!
+available in the Admin UI.
#### Releasing the feature
diff --git a/doc/development/git_object_deduplication.md b/doc/development/git_object_deduplication.md
index 06af34d9232..4f1afed24ba 100644
--- a/doc/development/git_object_deduplication.md
+++ b/doc/development/git_object_deduplication.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# How Git object deduplication works in GitLab
When a GitLab user [forks a project](../user/project/repository/forking_workflow.md),
@@ -27,7 +33,7 @@ configuration. Objects in A that are not in B will remain in A. For this
to work, it is of course critical that **no objects ever get deleted from
B** because A might need them.
-DANGER: **Danger:**
+DANGER: **Warning:**
Do not run `git prune` or `git gc` in pool repositories! This can
cause data loss in "real" repositories that depend on the pool in
question.
@@ -156,7 +162,7 @@ repository and a pool.
### Pool existence
-If GitLab thinks a pool repository exists (i.e. it exists according to
+If GitLab thinks a pool repository exists (i.e. it exists according to
SQL), but it does not on the Gitaly server, then it will be created on
the fly by Gitaly.
diff --git a/doc/development/github_importer.md b/doc/development/github_importer.md
index 5a490737f37..9fa55d2662a 100644
--- a/doc/development/github_importer.md
+++ b/doc/development/github_importer.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Working with the GitHub importer
In GitLab 10.2 a new version of the GitHub importer was introduced. This new
diff --git a/doc/development/go_guide/dependencies.md b/doc/development/go_guide/dependencies.md
index b85344635c6..461ee394533 100644
--- a/doc/development/go_guide/dependencies.md
+++ b/doc/development/go_guide/dependencies.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Dependency Management in Go
Go takes an unusual approach to dependency management, in that it is
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index 15d25d2d1ed..4077cf2a2c2 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Go standards and style guidelines
This document describes various guidelines and best practices for GitLab
diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md
index cc3db267d53..691027f385f 100644
--- a/doc/development/gotchas.md
+++ b/doc/development/gotchas.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Gotchas
The purpose of this guide is to document potential "gotchas" that contributors
@@ -157,7 +163,7 @@ allow_next_found_instance_of(Project) do |project|
end
```
-_**Note:** Since Active Record is not calling the `.new` method on model classes to instantiate the objects,
+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
@@ -182,7 +188,7 @@ refresh_service.execute(oldrev, newrev, ref)
See ["Why is it bad style to `rescue Exception => e` in Ruby?"](https://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby).
-_**Note:** This rule is [enforced automatically by
+This rule is [enforced automatically by
RuboCop](https://gitlab.com/gitlab-org/gitlab-foss/blob/8-4-stable/.rubocop.yml#L911-914)._
## Do not use inline JavaScript in views
@@ -190,8 +196,8 @@ RuboCop](https://gitlab.com/gitlab-org/gitlab-foss/blob/8-4-stable/.rubocop.yml#
Using the inline `:javascript` Haml filters comes with a
performance overhead. Using inline JavaScript is not a good way to structure your code and should be avoided.
-_**Note:** We've [removed these two filters](https://gitlab.com/gitlab-org/gitlab/blob/master/config/initializers/hamlit.rb)
-in an initializer._
+We've [removed these two filters](https://gitlab.com/gitlab-org/gitlab/blob/master/config/initializers/hamlit.rb)
+in an initializer.
### Further reading
diff --git a/doc/development/graphql_guide/batchloader.md b/doc/development/graphql_guide/batchloader.md
new file mode 100644
index 00000000000..6d529358499
--- /dev/null
+++ b/doc/development/graphql_guide/batchloader.md
@@ -0,0 +1,121 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# GraphQL BatchLoader
+
+GitLab uses the [batch-loader](https://github.com/exAspArk/batch-loader) Ruby gem to optimize and avoid N+1 SQL queries.
+
+It is the properties of the GraphQL query tree that create opportunities for batching like this - disconnected nodes might need the same data, but cannot know about themselves.
+
+## When should you use it?
+
+We should try to batch DB requests as much as possible during GraphQL **query** execution. There is no need to batch loading during **mutations** because they are executed serially. If you need to make a database query, and it is possible to combine two similar (but not identical) queries, then consider using the batch-loader.
+
+When implementing a new endpoint we should aim to minimise the number of SQL queries. For stability and scalability we must also ensure that our queries do not suffer from N+1 performance issues.
+
+## Implementation
+
+Batch loading is useful when a series of queries for inputs `Qα, Qβ, ... Qω` can be combined to a single query for `Q[α, β, ... ω]`. An example of this is lookups by ID, where we can find two users by usernames as cheaply as one, but real-world examples can be more complex.
+
+Batchloading is not suitable when the result sets have different sort-orders, grouping, aggregation or other non-composable features.
+
+There are two ways to use the batch-loader in your code. For simple ID lookups, use `::Gitlab::Graphql::Loaders::BatchModelLoader.new(model, id).find`. For more complex cases, you can use the batch API directly.
+
+For example, to load a `User` by `username`, we can add batching as follows:
+
+```ruby
+class UserResolver < BaseResolver
+ type UserType, null: true
+ argument :username, ::GraphQL::STRING_TYPE, required: true
+
+ def resolve(**args)
+ BatchLoader::GraphQL.for(username).batch do |usernames, loader|
+ User.by_username(usernames).each do |user|
+ loader.call(user.username, user)
+ end
+ end
+ end
+end
+```
+
+- `project_id` is the `ID` of the current project being queried
+- `loader.call` is used to map the result back to the input key (here a project ID)
+- `BatchLoader::GraphQL` returns a lazy object (suspended promise to fetch the data)
+
+Here an [example MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46549) illustrating how to use our `BatchLoading` mechanism.
+
+## How does it work exactly?
+
+Each lazy object knows which data it needs to load and how to batch the query. When we need to use the lazy objects (which we announce by calling `#sync`), they will be loaded along with all other similar objects in the current batch.
+
+Inside the block we execute a batch query for our items (`User`). After that, all we have to do is to call loader by passing an item which was used in `BatchLoader::GraphQL.for` method (`usernames`) and the loaded object itself (`user`):
+
+```ruby
+BatchLoader::GraphQL.for(username).batch do |usernames, loader|
+ User.by_username(usernames).each do |user|
+ loader.call(user.username, user)
+ end
+end
+```
+
+### What does lazy mean?
+
+It is important to avoid syncing batches too early. In the example below we can see how calling sync too early can eliminate opportunities for batching:
+
+```ruby
+x = find_lazy(1)
+y = find_lazy(2)
+
+# calling .sync will flush the current batch and will inhibit maximum laziness
+x.sync
+
+z = find_lazy(3)
+
+y.sync
+z.sync
+
+# => will run 2 queries
+```
+
+```ruby
+x = find_lazy(1)
+y = find_lazy(2)
+z = find_lazy(3)
+
+x.sync
+y.sync
+z.sync
+
+# => will run 1 query
+```
+
+## Testing
+
+Any GraphQL field that supports `BatchLoading` should be tested using the `batch_sync` method available in [GraphQLHelpers](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/support/helpers/graphql_helpers.rb).
+
+```ruby
+it 'returns data as a batch' do
+ results = batch_sync(max_queries: 1) do
+ [{ id: 1 }, { id: 2 }].map { |args| resolve(args) }
+ end
+
+ expect(results).to eq(expected_results)
+end
+
+def resolve(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: obj, args: args, ctx: context)
+end
+```
+
+We can also use [QueryRecorder](../query_recorder.md) to make sure we are performing only **one SQL query** per call.
+
+```ruby
+it 'executes only 1 SQL query' do
+ query_count = ActiveRecord::QueryRecorder.new { subject }.count
+
+ expect(query_count).to eq(1)
+end
+```
diff --git a/doc/development/graphql_guide/index.md b/doc/development/graphql_guide/index.md
index 9d7fb5ba0a8..12b4f9796c7 100644
--- a/doc/development/graphql_guide/index.md
+++ b/doc/development/graphql_guide/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GraphQL development guidelines
This guide contains all the information to successfully contribute to GitLab's
diff --git a/doc/development/graphql_guide/pagination.md b/doc/development/graphql_guide/pagination.md
index bf9eaa99158..d5140363396 100644
--- a/doc/development/graphql_guide/pagination.md
+++ b/doc/development/graphql_guide/pagination.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GraphQL pagination
## Types of pagination
@@ -59,13 +65,13 @@ 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
+- More data stability for end-users since records are not missing from lists 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.
+ `sort_order`, complicated (or impossible) for [complex sorting scenarios](#limitations-of-query-complexity).
## Implementation
@@ -80,12 +86,171 @@ 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 -->
+### Keyset pagination
+
+The keyset pagination implementation is a subclass of `GraphQL::Pagination::ActiveRecordRelationConnection`,
+which is a part of the `graphql` gem. This is installed as the default for all `ActiveRecord::Relation`.
+However, instead of using a cursor based on an offset (which is the default), GitLab uses a more specialized cursor.
+
+The cursor is created by encoding a JSON object which contains the relevant ordering fields. For example:
+
+```ruby
+ordering = {"id"=>"72410125", "created_at"=>"2020-10-08 18:05:21.953398000 UTC"}
+json = ordering.to_json
+cursor = Base64Bp.urlsafe_encode64(json, padding: false)
+
+"eyJpZCI6IjcyNDEwMTI1IiwiY3JlYXRlZF9hdCI6IjIwMjAtMTAtMDggMTg6MDU6MjEuOTUzMzk4MDAwIFVUQyJ9"
+
+json = Base64Bp.urlsafe_decode64(cursor)
+Gitlab::Json.parse(json)
+
+{"id"=>"72410125", "created_at"=>"2020-10-08 18:05:21.953398000 UTC"}
+```
+
+The benefits of storing the order attribute values in the cursor:
+
+- If only the ID of the object were stored, the object and its attributes could be queried.
+ That would require an additional query, and if the object is no longer there, then the needed
+ attributes are not available.
+- If an attribute is `NULL`, then one SQL query can be used. If it's not `NULL`, then a
+ different SQL query can be used.
+
+Based on whether the main attribute field being sorted on is `NULL` in the cursor, the proper query
+condition is built. The last ordering field is considered to be unique (a primary key), meaning the
+column never contains `NULL` values.
+
+#### Limitations of query complexity
+
+We only support two ordering fields, and one of those fields needs to be the primary key.
+
+Here are two examples of pseudocode for the query:
+
+- **Two-condition query.** `X` represents the values from the cursor. `C` represents
+ the columns in the database, sorted in ascending order, using an `:after` cursor, and with `NULL`
+ values sorted last.
+
+ ```plaintext
+ X1 IS NOT NULL
+ AND
+ (C1 > X1)
+ OR
+ (C1 IS NULL)
+ OR
+ (C1 = X1
+ AND
+ C2 > X2)
+
+ X1 IS NULL
+ AND
+ (C1 IS NULL
+ AND
+ C2 > X2)
+ ```
+
+ Below is an example based on the relation `Issue.order(relative_position: :asc).order(id: :asc)`
+ with an after cursor of `relative_position: 1500, id: 500`:
+
+ ```plaintext
+ when cursor[relative_position] is not NULL
+
+ ("issues"."relative_position" > 1500)
+ OR (
+ "issues"."relative_position" = 1500
+ AND
+ "issues"."id" > 500
+ )
+ OR ("issues"."relative_position" IS NULL)
+
+ when cursor[relative_position] is NULL
+
+ "issues"."relative_position" IS NULL
+ AND
+ "issues"."id" > 500
+ ```
+
+- **Three-condition query.** The example below is not complete, but shows the
+ complexity of adding one more condition. `X` represents the values from the cursor. `C` represents
+ the columns in the database, sorted in ascending order, using an `:after` cursor, and with `NULL`
+ values sorted last.
+
+ ```plaintext
+ X1 IS NOT NULL
+ AND
+ (C1 > X1)
+ OR
+ (C1 IS NULL)
+ OR
+ (C1 = X1 AND C2 > X2)
+ OR
+ (C1 = X1
+ AND
+ X2 IS NOT NULL
+ AND
+ ((C2 > X2)
+ OR
+ (C2 IS NULL)
+ OR
+ (C2 = X2 AND C3 > X3)
+ OR
+ X2 IS NULL.....
+ ```
+
+By using
+[`Gitlab::Graphql::Pagination::Keyset::QueryBuilder`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/graphql/pagination/keyset/query_builder.rb),
+we're able to build the necessary SQL conditions and apply them to the Active Record relation.
+
+Complex queries can be difficult or impossible to use. For example,
+in [`issuable.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/concerns/issuable.rb),
+the `order_due_date_and_labels_priority` method creates a very complex query.
+
+These types of queries are not supported. In these instances, you can use offset pagination.
+
+### Offset pagination
+
+There are times when the [complexity of sorting](#limitations-of-query-complexity)
+is more than our keyset pagination can handle.
+
+For example, in [`IssuesResolver`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/resolvers/issues_resolver.rb),
+when sorting by `priority_asc`, we can't use keyset pagination as the ordering is much
+too complex. For more information, read [`issuable.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/concerns/issuable.rb).
-<!-- ### Offset pagination -->
+In cases like this, we can fall back to regular offset pagination by returning a
+[`Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/graphql/pagination/offset_active_record_relation_connection.rb)
+instead of an `ActiveRecord::Relation`:
+
+```ruby
+ def resolve(parent, finder, **args)
+ 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.
+ # In these cases, we use offset pagination, so we return the correct connection.
+ Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection.new(issues)
+ else
+ issues
+ end
+ end
+```
<!-- ### External pagination -->
+### External pagination
+
+There may be times where you need to return data through the GitLab API that is stored in
+another system. In these cases you may have to paginate a third-party's API.
+
+An example of this is with our [Error Tracking](../../operations/error_tracking.md) implementation,
+where we proxy [Sentry errors](../../operations/error_tracking.md#sentry-error-tracking) through
+the GitLab API. We do this by calling the Sentry API which enforces its own pagination rules.
+This means we cannot access the collection within GitLab to perform our own custom pagination.
+
+For consistency, we manually set the pagination cursors based on values returned by the external API, using `Gitlab::Graphql::ExternallyPaginatedArray.new(previous_cursor, next_cursor, *items)`.
+
+You can see an example implementation in the following files:
+
+- [`types/error__tracking/sentry_error_collection_type.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/types/error_tracking/sentry_error_collection_type.rb) which adds an extension to `field :errors`.
+- [`resolvers/error_tracking/sentry_errors_resolver.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb) which returns the data from the resolver.
+
## Testing
Any GraphQL field that supports pagination and sorting should be tested
diff --git a/doc/development/hash_indexes.md b/doc/development/hash_indexes.md
index 1ed76e35f69..cc0b0b3a736 100644
--- a/doc/development/hash_indexes.md
+++ b/doc/development/hash_indexes.md
@@ -1,3 +1,9 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Hash Indexes
PostgreSQL supports hash indexes besides the regular B-tree
diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md
index 59399e54c3e..65a1d83a8fc 100644
--- a/doc/development/i18n/externalization.md
+++ b/doc/development/i18n/externalization.md
@@ -1,3 +1,9 @@
+---
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Internationalization for GitLab
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10669) in GitLab 9.2.
@@ -15,7 +21,7 @@ All `rake` commands described on this page must be run on a GitLab instance, usu
In order to be able to work on the [GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab-foss)
project you must download and configure it through [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/set-up-gdk.md).
-Once you have the GitLab project ready, you can start working on the translation.
+After you have the GitLab project ready, you can start working on the translation.
## Tools
@@ -98,9 +104,8 @@ Active Record's `:message` option accepts a `Proc`, so we can do this instead:
validates :group_id, uniqueness: { scope: [:project_id], message: -> (object, data) { _("already shared with this group") } }
```
-NOTE: **Note:**
Messages in the API (`lib/api/` or `app/graphql`) do
-not need to be externalised.
+not need to be externalized.
### HAML files
@@ -379,8 +384,8 @@ Namespaces should be PascalCase.
s__('OpenedNDaysAgo|Opened')
```
-Note: The namespace should be removed from the translation. See the [translation
-guidelines for more details](translation.md#namespaced-strings).
+The namespace should be removed from the translation. See the
+[translation guidelines for more details](translation.md#namespaced-strings).
### HTML
@@ -475,6 +480,21 @@ This makes use of [`Intl.DateTimeFormat`](https://developer.mozilla.org/en-US/do
## Best practices
+### Minimize translation updates
+
+Updates can result in the loss of the translations for this string. To minimize risks,
+avoid changes to strings, unless they:
+
+- Add value to the user.
+- Include extra context for translators.
+
+For example, we should avoid changes like this:
+
+```diff
+- _('Number of things: %{count}') % { count: 10 }
++ n_('Number of things: %d', 10)
+```
+
### Keep translations dynamic
There are cases when it makes sense to keep translations together within an array or a hash.
diff --git a/doc/development/i18n/index.md b/doc/development/i18n/index.md
index 2d84fe4536f..13f2b43b788 100644
--- a/doc/development/i18n/index.md
+++ b/doc/development/i18n/index.md
@@ -1,3 +1,9 @@
+---
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Translate GitLab to your language
The text in GitLab's user interface is in American English by default.
diff --git a/doc/development/i18n/merging_translations.md b/doc/development/i18n/merging_translations.md
index 8b3357c41d3..c4a709f84d3 100644
--- a/doc/development/i18n/merging_translations.md
+++ b/doc/development/i18n/merging_translations.md
@@ -1,3 +1,9 @@
+---
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Merging translations from CrowdIn
CrowdIn automatically syncs the `gitlab.pot` file with the CrowdIn service, presenting
diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md
index 1916f96801d..56a4f835b3f 100644
--- a/doc/development/i18n/proofreader.md
+++ b/doc/development/i18n/proofreader.md
@@ -1,3 +1,9 @@
+---
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Proofread Translations
Most translations are contributed, reviewed, and accepted by the community. We
@@ -115,10 +121,8 @@ are very appreciative of the work done by translators and proofreaders!
## Become a proofreader
-NOTE: **Note:**
-Before requesting Proofreader permissions in CrowdIn please make
-sure that you have a history of contributing translations to the GitLab
-project.
+Before requesting Proofreader permissions in CrowdIn, be sure you have a history
+of contributing translations to the GitLab project.
1. Contribute translations to GitLab. See instructions for
[translating GitLab](translation.md).
@@ -140,8 +144,8 @@ project.
- link to your GitLab profile
- link to your CrowdIn profile
- In the merge request description, please include links to any projects you
- have previously translated.
+ In the merge request description, include links to any projects you have
+ previously translated.
1. Your request to become a proofreader will be considered on the merits of
your previous translations by [GitLab team members](https://about.gitlab.com/company/team/)
diff --git a/doc/development/i18n/translation.md b/doc/development/i18n/translation.md
index ed205c20c0d..128bacfda97 100644
--- a/doc/development/i18n/translation.md
+++ b/doc/development/i18n/translation.md
@@ -1,3 +1,9 @@
+---
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Translating GitLab
For managing the translation process we use [CrowdIn](https://crowdin.com).
@@ -94,7 +100,7 @@ To propose additions to the glossary please
### Inclusive language in French
<!-- vale gitlab.Spelling = NO -->
-In French, the "écriture inclusive" is now over (see on [Legifrance](https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000036068906&categorieLien=id)).
+In French, the "écriture inclusive" is now over (see on [Legifrance](https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000036068906&categorieLien=id)).
So, to include both genders, write “Utilisateurs et utilisatrices†instead of “Utilisateur·rice·sâ€.
When space is missing, the male gender should be used alone.
<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/development/image_scaling.md b/doc/development/image_scaling.md
new file mode 100644
index 00000000000..05f44209bc4
--- /dev/null
+++ b/doc/development/image_scaling.md
@@ -0,0 +1,96 @@
+---
+stage: Enablement
+group: Memory
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# Image scaling guide
+
+This section contains a brief overview of GitLab's image scaler and how to work with it.
+
+For a general introduction to the history of image scaling at GitLab, you might be interested in
+[this Unfiltered blog post](https://about.gitlab.com/blog/2020/11/02/scaling-down-how-we-prototyped-an-image-scaler-at-gitlab/).
+
+## Why image scaling?
+
+Since version 13.6, GitLab scales down images on demand in order to reduce the page data footprint.
+This both reduces the amount of data "on the wire", but also helps with rendering performance,
+since the browser has less work to do.
+
+## When do we scale images?
+
+Generally, the image scaler is triggered whenever a client requests an image resource by adding
+the `width` parameter to the query string. However, we only scale images of certain kinds and formats.
+Whether we allow an image to be rescaled or not is decided by combination of hard-coded rules and configuration settings.
+
+The hard-coded rules only permit:
+
+- [Project, group and user avatars](https://gitlab.com/gitlab-org/gitlab/-/blob/fd08748862a5fe5c25b919079858146ea85843ae/app/controllers/concerns/send_file_upload.rb#L65-67)
+- [PNGs or JPEGs](https://gitlab.com/gitlab-org/gitlab/-/blob/5dff8fa3814f2a683d8884f468cba1ec06a60972/lib/gitlab/file_type_detection.rb#L23)
+- [Specific dimensions](https://gitlab.com/gitlab-org/gitlab/-/blob/5dff8fa3814f2a683d8884f468cba1ec06a60972/app/models/concerns/avatarable.rb#L6)
+
+Furthermore, configuration in Workhorse can lead to the image scaler rejecting a request if:
+
+- The image file is too large (controlled by [`max_filesize`](- we only rescale images that do not exceed a configured size in bytes (see [`max_filesize`](https://gitlab.com/gitlab-org/gitlab-workhorse/-/blob/67ab3a2985d2097392f93523ae1cffe0dbf01b31/config.toml.example#L17)))).
+- Too many image scalers are already running (controlled by [`max_scaler_procs`](https://gitlab.com/gitlab-org/gitlab-workhorse/-/blob/67ab3a2985d2097392f93523ae1cffe0dbf01b31/config.toml.example#L16)).
+
+For instance, here are two different URLs that serve the GitLab project avatar both in its
+original size and scaled down to 64 pixels. Only the second request will trigger the image scaler:
+
+- [`/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png`](https://assets.gitlab-static.net/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png)
+- [`/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png?width=64`](https://assets.gitlab-static.net/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png?width=64)
+
+## Where do we scale images?
+
+Rails and Workhorse currently collaborate to rescale images. This is a common implementation and performance
+pattern in GitLab: important business logic such as request authentication and validation
+happens in Rails, whereas the "heavy lifting", scaling and serving the binary data, happens in Workhorse.
+
+The overall request flow is as follows:
+
+```mermaid
+sequenceDiagram
+ Client->>+Workhorse: GET /uploads/-/system/project/avatar/278964/logo-extra-whitespace.png?width=64
+ Workhorse->>+Rails: forward request
+ Rails->>+Rails: validate request
+ Rails->>+Rails: resolve image location
+ Rails-->>-Workhorse: Gitlab-Workhorse-Send-Data: send-scaled-image
+ Workhorse->>+Workhorse: invoke image scaler
+ Workhorse-->>-Client: 200 OK
+```
+
+### Rails
+
+Currently, image scaling is limited to `Upload` entities, specifically avatars as mentioned above.
+Therefore, all image scaling related logic in Rails is currently found in the
+[`send_file_upload`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/controllers/concerns/send_file_upload.rb)
+controller mixin. Upon receiving a request coming from a client through Workhorse, we check whether
+it should trigger the image scaler as per the criteria mentioned above, and if so, render a special response
+header field (`Gitlab-Workhorse-Send-Data`) with the necessary parameters for Workhorse to carry
+out the scaling request. If Rails decides the request does not constitute a valid image scaling request,
+we simply follow the path we take to serve any ordinary upload.
+
+### Workhorse
+
+Assuming Rails decided the request to be valid, Workhorse will take over. Upon receiving the `send-scaled-image`
+instruction through the Rails response, a [special response injecter](https://gitlab.com/gitlab-org/gitlab-workhorse/-/blob/master/internal/imageresizer/image_resizer.go)
+will be invoked that knows how to rescale images. The only inputs it requires are the location of the image
+(a path if the image resides in block storage, or a URL to remote storage otherwise) and the desired width.
+Workhorse will handle the location transparently so Rails does not need to be concerned with where the image
+actually resides.
+
+Additionally, to request validation in Rails, Workhorse will run several pre-condition checks to ensure that
+we can actually rescale the image, such as making sure we wouldn't outgrow our scaler process budget but also
+if the file meets the configured maximum allowed size constraint (to keep memory consumption in check).
+
+To actually scale the image, Workhorse will finally fork into a child process that performs the actual
+scaling work, and stream the result back to the client.
+
+#### Caching rescaled images
+
+We currently do not store rescaled images anywhere; the scaler runs every time a smaller version is requested.
+However, Workhorse implements standard conditional HTTP request strategies that allow us to skip the scaler
+if the image in the client cache is up-to-date.
+To that end we transmit a `Last-Modified` header field carrying the UTC
+timestamp of the original image file and match it against the `If-Modified-Since` header field in client requests.
+Only if the original image has changed and rescaling becomes necessary do we run the scaler again.
diff --git a/doc/development/img/architecture_simplified.png b/doc/development/img/architecture_simplified.png
index 72d00b91129..bd731758ddd 100644
--- a/doc/development/img/architecture_simplified.png
+++ b/doc/development/img/architecture_simplified.png
Binary files differ
diff --git a/doc/development/img/bullet_v13_0.png b/doc/development/img/bullet_v13_0.png
index e185bdef76d..2a3248e380c 100644
--- a/doc/development/img/bullet_v13_0.png
+++ b/doc/development/img/bullet_v13_0.png
Binary files differ
diff --git a/doc/development/img/distributed_tracing_jaeger_ui.png b/doc/development/img/distributed_tracing_jaeger_ui.png
index dcd18b1ec9f..5452294caa3 100644
--- a/doc/development/img/distributed_tracing_jaeger_ui.png
+++ b/doc/development/img/distributed_tracing_jaeger_ui.png
Binary files differ
diff --git a/doc/development/img/memory_ruby_heap_fragmentation.png b/doc/development/img/memory_ruby_heap_fragmentation.png
index 4703da7491d..204130f8d87 100644
--- a/doc/development/img/memory_ruby_heap_fragmentation.png
+++ b/doc/development/img/memory_ruby_heap_fragmentation.png
Binary files differ
diff --git a/doc/development/img/merge_ref_head_options_v13_6.png b/doc/development/img/merge_ref_head_options_v13_6.png
new file mode 100644
index 00000000000..3134092cc92
--- /dev/null
+++ b/doc/development/img/merge_ref_head_options_v13_6.png
Binary files differ
diff --git a/doc/development/img/performance_bar_cached_queries.png b/doc/development/img/performance_bar_cached_queries.png
new file mode 100644
index 00000000000..f5bdc6ffd84
--- /dev/null
+++ b/doc/development/img/performance_bar_cached_queries.png
Binary files differ
diff --git a/doc/development/img/performance_bar_fixed_cached_queries.png b/doc/development/img/performance_bar_fixed_cached_queries.png
new file mode 100644
index 00000000000..3f4232fb88f
--- /dev/null
+++ b/doc/development/img/performance_bar_fixed_cached_queries.png
Binary files differ
diff --git a/doc/development/img/performance_bar_members_page.png b/doc/development/img/performance_bar_members_page.png
new file mode 100644
index 00000000000..bc81cd645e5
--- /dev/null
+++ b/doc/development/img/performance_bar_members_page.png
Binary files differ
diff --git a/doc/development/img/telemetry_system_overview.png b/doc/development/img/telemetry_system_overview.png
deleted file mode 100644
index f2e6b300e94..00000000000
--- a/doc/development/img/telemetry_system_overview.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/import_export.md b/doc/development/import_export.md
index 8d2be1baf24..a73144abce6 100644
--- a/doc/development/import_export.md
+++ b/doc/development/import_export.md
@@ -1,3 +1,9 @@
+---
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Import/Export development documentation
Troubleshooting and general development guidelines and tips for the [Import/Export feature](../user/project/settings/import_export.md).
@@ -354,28 +360,28 @@ The NDJSON tree will look like this:
```shell
tree
├── project
-│   ├── auto_devops.ndjson
-│   ├── boards.ndjson
-│   ├── ci_cd_settings.ndjson
-│   ├── ci_pipelines.ndjson
-│   ├── container_expiration_policy.ndjson
-│   ├── custom_attributes.ndjson
-│   ├── error_tracking_setting.ndjson
-│   ├── external_pull_requests.ndjson
-│   ├── issues.ndjson
-│   ├── labels.ndjson
-│   ├── merge_requests.ndjson
-│   ├── milestones.ndjson
-│   ├── pipeline_schedules.ndjson
-│   ├── project_badges.ndjson
-│   ├── project_feature.ndjson
-│   ├── project_members.ndjson
-│   ├── protected_branches.ndjson
-│   ├── protected_tags.ndjson
-│   ├── releases.ndjson
-│   ├── services.ndjson
-│   ├── snippets.ndjson
-│   └── triggers.ndjson
+│ ├── auto_devops.ndjson
+│ ├── boards.ndjson
+│ ├── ci_cd_settings.ndjson
+│ ├── ci_pipelines.ndjson
+│ ├── container_expiration_policy.ndjson
+│ ├── custom_attributes.ndjson
+│ ├── error_tracking_setting.ndjson
+│ ├── external_pull_requests.ndjson
+│ ├── issues.ndjson
+│ ├── labels.ndjson
+│ ├── merge_requests.ndjson
+│ ├── milestones.ndjson
+│ ├── pipeline_schedules.ndjson
+│ ├── project_badges.ndjson
+│ ├── project_feature.ndjson
+│ ├── project_members.ndjson
+│ ├── protected_branches.ndjson
+│ ├── protected_tags.ndjson
+│ ├── releases.ndjson
+│ ├── services.ndjson
+│ ├── snippets.ndjson
+│ └── triggers.ndjson
└── project.json
```
@@ -389,19 +395,19 @@ The NDJSON tree will look like this:
tree
└── groups
├── 4351
- │   ├── badges.ndjson
- │   ├── boards.ndjson
- │   ├── epics.ndjson
- │   ├── labels.ndjson
- │   ├── members.ndjson
- │   └── milestones.ndjson
+ │ ├── badges.ndjson
+ │ ├── boards.ndjson
+ │ ├── epics.ndjson
+ │ ├── labels.ndjson
+ │ ├── members.ndjson
+ │ └── milestones.ndjson
├── 4352
- │   ├── badges.ndjson
- │   ├── boards.ndjson
- │   ├── epics.ndjson
- │   ├── labels.ndjson
- │   ├── members.ndjson
- │   └── milestones.ndjson
+ │ ├── badges.ndjson
+ │ ├── boards.ndjson
+ │ ├── epics.ndjson
+ │ ├── labels.ndjson
+ │ ├── members.ndjson
+ │ └── milestones.ndjson
├── _all.ndjson
├── 4351.json
└── 4352.json
diff --git a/doc/development/import_project.md b/doc/development/import_project.md
index 9e2f5af6738..8b27b7d28a5 100644
--- a/doc/development/import_project.md
+++ b/doc/development/import_project.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Test Import Project
For testing, we can import our own [GitLab CE](https://gitlab.com/gitlab-org/gitlab-foss/) project (named `gitlabhq` in this case) under a group named `qa-perf-testing`. Project tarballs that can be used for testing can be found over on the [performance-data](https://gitlab.com/gitlab-org/quality/performance-data) project. A different project could be used if required.
@@ -17,7 +23,6 @@ The first option is to simply [import the Project tarball file via the GitLab UI
It should take up to 15 minutes for the project to fully import. You can head to the project's main page for the current status.
-NOTE: **Note:**
This method ignores all the errors silently (including the ones related to `GITALY_DISABLE_REQUEST_LIMITS`) and is used by GitLab's users. For development and testing, check the other methods below.
### Importing via the `import-project` script
diff --git a/doc/development/insert_into_tables_in_batches.md b/doc/development/insert_into_tables_in_batches.md
index f65d2478d2e..5fe37a95b59 100644
--- a/doc/development/insert_into_tables_in_batches.md
+++ b/doc/development/insert_into_tables_in_batches.md
@@ -1,4 +1,7 @@
---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
description: "Sometimes it is necessary to store large amounts of records at once, which can be inefficient
when iterating collections and performing individual `save`s. With the arrival of `insert_all`
in Rails 6, which operates at the row level (that is, using `Hash`es), GitLab has added a set
diff --git a/doc/development/integrations/jenkins.md b/doc/development/integrations/jenkins.md
index 5d3c869d922..d81dee94f17 100644
--- a/doc/development/integrations/jenkins.md
+++ b/doc/development/integrations/jenkins.md
@@ -1,3 +1,9 @@
+---
+stage: Create
+group: Ecosystem
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# How to run Jenkins in development environment (on macOS) **(STARTER)**
This is a step by step guide on how to set up [Jenkins](https://www.jenkins.io/) on your local machine and connect to it from your GitLab instance. GitLab triggers webhooks on Jenkins, and Jenkins connects to GitLab using the API. By running both applications on the same machine, we can make sure they are able to access each other.
diff --git a/doc/development/integrations/jira_connect.md b/doc/development/integrations/jira_connect.md
index 1f9b03075f0..66a93f8c947 100644
--- a/doc/development/integrations/jira_connect.md
+++ b/doc/development/integrations/jira_connect.md
@@ -1,31 +1,37 @@
-# Setting up a development environment
+---
+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
+---
-The following are required to install and test the app:
-
-1. A Jira Cloud instance
+# Set up a development environment
- Atlassian provides free instances for development and testing. [Click here to sign up](https://developer.atlassian.com/platform/marketplace/getting-started/#free-developer-instances-to-build-and-test-your-app).
+The following are required to install and test the app:
-1. A GitLab instance available over the internet
+- A Jira Cloud instance. Atlassian provides [free instances for development and testing](https://developer.atlassian.com/platform/marketplace/getting-started/#free-developer-instances-to-build-and-test-your-app).
+- A GitLab instance available over the internet. For the app to work, Jira Cloud should
+ be able to connect to the GitLab instance through the internet. To easily expose your
+ local development environment, you can use tools like:
+ - [serveo](https://medium.com/automationmaster/how-to-forward-my-local-port-to-public-using-serveo-4979f352a3bf)
+ - [ngrok](https://ngrok.com).
- For the app to work, Jira Cloud should be able to connect to the GitLab instance through the internet.
+ These also take care of SSL for you because Jira requires all connections to the app
+ host to be over SSL.
- To easily expose your local development environment, you can use tools like
- [serveo](https://medium.com/automationmaster/how-to-forward-my-local-port-to-public-using-serveo-4979f352a3bf)
- or [ngrok](https://ngrok.com). These also take care of SSL for you because Jira
- requires all connections to the app host to be over SSL.
+## Install the app in Jira
-## Installing the app in Jira
+To install the app in Jira:
-1. Enable Jira development mode to install apps that are not from the Atlassian Marketplace
+1. Enable Jira development mode to install apps that are not from the Atlassian
+ Marketplace:
- 1. Navigate to **Jira settings** (cog icon) > **Apps** > **Manage apps**.
+ 1. In Jira, navigate to **Jira settings > Apps > Manage apps**.
1. Scroll to the bottom of the **Manage apps** page and click **Settings**.
1. Select **Enable development mode** and click **Apply**.
-1. Install the app
+1. Install the app:
- 1. Navigate to Jira, then choose **Jira settings** (cog icon) > **Apps** > **Manage apps**.
+ 1. In Jira, navigate to **Jira settings > Apps > Manage apps**.
1. Click **Upload app**.
1. In the **From this URL** field, provide a link to the app descriptor. The host and port must point to your GitLab instance.
diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md
index 1094074cab6..9bb92709d54 100644
--- a/doc/development/integrations/secure.md
+++ b/doc/development/integrations/secure.md
@@ -1,7 +1,13 @@
+---
+stage: Protect
+group: Container Security
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Security scanner integration
Integrating a security scanner into GitLab consists of providing end users
-with a [CI job definition](../../ci/yaml/README.md#introduction)
+with a [CI job definition](../../ci/yaml/README.md)
they can add to their CI configuration files to scan their GitLab projects.
This CI job should then output its results in a GitLab-specified format. These results are then
automatically presented in various places in GitLab, such as the Pipeline view, Merge Request
@@ -40,12 +46,12 @@ Because the `script` entry can't be left empty, it must be set to the command th
It is not possible to rely on the predefined `ENTRYPOINT` and `CMD` of the Docker image
to perform the scan automatically, without passing any command.
-The [`before_script`](../../ci/yaml/README.md#before_script-and-after_script)
+The [`before_script`](../../ci/yaml/README.md#before_script)
should not be used in the job definition because users may rely on this to prepare their projects before performing the scan.
For instance, it is common practice to use `before_script` to install system libraries
a particular project needs before performing SAST or Dependency Scanning.
-Similarly, [`after_script`](../../ci/yaml/README.md#before_script-and-after_script)
+Similarly, [`after_script`](../../ci/yaml/README.md#after_script)
should not be used in the job definition, because it may be overridden by users.
### Stage
@@ -175,7 +181,9 @@ SAST and Dependency Scanning scanners must scan the files in the project directo
In order to be consistent with the official Container Scanning for GitLab,
scanners must scan the Docker image whose name and tag are given by
-`CI_APPLICATION_REPOSITORY` and `CI_APPLICATION_TAG`, respectively.
+`CI_APPLICATION_REPOSITORY` and `CI_APPLICATION_TAG`, respectively. If the `DOCKER_IMAGE`
+variable is provided, then the `CI_APPLICATION_REPOSITORY` and `CI_APPLICATION_TAG` variables
+are ignored, and the image specified in the `DOCKER_IMAGE` variable is scanned instead.
If not provided, `CI_APPLICATION_REPOSITORY` should default to
`$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG`, which is a combination of predefined CI variables.
@@ -248,6 +256,11 @@ It is recommended to use the `debug` level for verbose logging that could be
useful when debugging. The default value for `SECURE_LOG_LEVEL` should be set
to `info`.
+When executing command lines, scanners should use the `debug` level to log the command line and its output.
+For instance, the [bundler-audit](https://gitlab.com/gitlab-org/security-products/analyzers/bundler-audit) scanner
+uses the `debug` level to log the command line `bundle audit check --quiet`,
+and what `bundle audit` writes to the standard output.
+
#### common logutil package
If you are using [go](https://golang.org/) and
@@ -278,8 +291,7 @@ You can find the schemas for these scanners here:
### Version
-This field specifies the version of the report schema you are using. Please reference individual scanner
-pages for the specific versions to use.
+This field specifies the version of the [Security Report Schemas](https://gitlab.com/gitlab-org/security-products/security-report-schemas) you are using. Please refer to the [releases](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/releases) of the schemas for the specific versions to use.
### Vulnerabilities
@@ -287,7 +299,7 @@ The `vulnerabilities` field of the report is an array of vulnerability objects.
#### ID
-The `id` field is the unique identifier of the vulnerability.
+The `id` field is the unique identifier of the vulnerability.
It is used to reference a fixed vulnerability from a [remediation objects](#remediations).
We recommend that you generate a UUID and use it as the `id` field's value.
@@ -532,7 +544,7 @@ of the available SAST Analyzers and what data is currently available.
The `remediations` field of the report is an array of remediation objects.
Each remediation describes a patch that can be applied to
-[automatically fix](../../user/application_security/#solutions-for-vulnerabilities-auto-remediation)
+[automatically fix](../../user/application_security/#automatic-remediation-for-vulnerabilities)
a set of vulnerabilities.
Here is an example of a report that contains remediations.
diff --git a/doc/development/integrations/secure_partner_integration.md b/doc/development/integrations/secure_partner_integration.md
index 19fd86f4bf6..52d10f0bd3c 100644
--- a/doc/development/integrations/secure_partner_integration.md
+++ b/doc/development/integrations/secure_partner_integration.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Secure Partner Integration - Onboarding Process
If you want to integrate your product with the [Secure Stage](https://about.gitlab.com/direction/secure/),
@@ -95,7 +101,7 @@ and complete an integration with the Secure stage.
- Users can interact with the findings from your artifact within their workflow. They can dismiss the findings or accept them and create a backlog issue.
- To automatically create issues without user interaction, use the [issue API](../../api/issues.md). This will be replaced by [Standalone Vulnerabilities](https://gitlab.com/groups/gitlab-org/-/epics/634) in the future.
1. Optional: Provide auto-remediation steps:
- - If you specified `remediations` in your artifact, it is proposed through our [auto-remediation](../../user/application_security/index.md#solutions-for-vulnerabilities-auto-remediation)
+ - If you specified `remediations` in your artifact, it is proposed through our [auto-remediation](../../user/application_security/index.md#automatic-remediation-for-vulnerabilities)
interface.
1. Demo the integration to GitLab:
- After you have tested and are ready to demo your integration please
diff --git a/doc/development/interacting_components.md b/doc/development/interacting_components.md
index 697c64986b1..87bbe30d9fd 100644
--- a/doc/development/interacting_components.md
+++ b/doc/development/interacting_components.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Developing against interacting components or features
It's not uncommon that a single code change can reflect and interact with multiple parts of GitLab
diff --git a/doc/development/internal_users.md b/doc/development/internal_users.md
new file mode 100644
index 00000000000..9f1428dce80
--- /dev/null
+++ b/doc/development/internal_users.md
@@ -0,0 +1,44 @@
+---
+description: "Internal users documentation."
+type: concepts, 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"
+---
+
+# Internal users
+
+GitLab uses internal users (sometimes referred to as "bots") to perform
+actions or functions that cannot be attributed to a regular user.
+
+These users are created programatically throughout the codebase itself when
+necessary, and do not count towards a license limit.
+
+They are used when a traditional user account would not be applicable, for
+example when generating alerts or automatic review feedback.
+
+Technically, an internal user is a type of user, but they have reduced access
+and a very specific purpose. They cannot be used for regular user actions,
+such as authentication or API requests.
+
+They have email addresses and names which can be attributed to any actions
+they perform.
+
+For example, when we [migrated](https://gitlab.com/gitlab-org/gitlab/-/issues/216120)
+GitLab Snippets to [Versioned Snippets](../user/snippets.md#versioned-snippets)
+in GitLab 13.0, we used an internal user to attribute the authorship of
+snippets to itself when a snippet's author wasn't available for creating
+repository commits, such as when the user has been disabled, so the Migration
+Bot was used instead.
+
+For this bot:
+
+- The name was set to `GitLab Migration Bot`.
+- The email was set to `noreply+gitlab-migration-bot@{instance host}`.
+
+Other examples of internal users:
+
+- [Alert Bot](../operations/metrics/alerts.md#trigger-actions-from-alerts)
+- [Ghost User](../user/profile/account/delete_account.md#associated-records)
+- [Support Bot](../user/project/service_desk.md#support-bot-user)
+- Visual Review Bot
diff --git a/doc/development/iterating_tables_in_batches.md b/doc/development/iterating_tables_in_batches.md
index 56cbb3a0e9e..062b755de38 100644
--- a/doc/development/iterating_tables_in_batches.md
+++ b/doc/development/iterating_tables_in_batches.md
@@ -1,3 +1,9 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Iterating Tables In Batches
Rails provides a method called `in_batches` that can be used to iterate over
diff --git a/doc/development/lfs.md b/doc/development/lfs.md
index 3ba81e6a140..64bc709ff9a 100644
--- a/doc/development/lfs.md
+++ b/doc/development/lfs.md
@@ -1,3 +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
+---
+
# Git LFS
## Deep Dive
diff --git a/doc/development/licensed_feature_availability.md b/doc/development/licensed_feature_availability.md
index 4350c7fb4d4..f83a57fe1ca 100644
--- a/doc/development/licensed_feature_availability.md
+++ b/doc/development/licensed_feature_availability.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Licensed feature availability **(STARTER)**
As of GitLab 9.4, we've been supporting a simplified version of licensed
diff --git a/doc/development/licensing.md b/doc/development/licensing.md
index 8cda3d5f361..d1808822ba6 100644
--- a/doc/development/licensing.md
+++ b/doc/development/licensing.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab Licensing and Compatibility
[GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab-foss/) (CE) is licensed [under the terms of the MIT License](https://gitlab.com/gitlab-org/gitlab-foss/blob/master/LICENSE). [GitLab Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/) (EE) is licensed under "[The GitLab Enterprise Edition (EE) license](https://gitlab.com/gitlab-org/gitlab/blob/master/LICENSE)" wherein there are more restrictions.
@@ -12,7 +18,8 @@ Some gems may not include their license information in their `gemspec` file, and
### License Finder commands
-> Note: License Finder currently uses GitLab misused terms of `whitelist` and `blacklist`. As a result, the commands below reference those terms. We've created an [issue on their project](https://github.com/pivotal/LicenseFinder/issues/745) to propose that they rename their commands.
+NOTE: **Note:**
+License Finder currently uses GitLab misused terms of `whitelist` and `blacklist`. As a result, the commands below reference those terms. We've created an [issue on their project](https://github.com/pivotal/LicenseFinder/issues/745) to propose that they rename their commands.
There are a few basic commands License Finder provides that you'll need in order to manage license detection.
diff --git a/doc/development/mass_insert.md b/doc/development/mass_insert.md
index c19850ca67e..dfffab564bc 100644
--- a/doc/development/mass_insert.md
+++ b/doc/development/mass_insert.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Mass inserting Rails models
Setting the environment variable [`MASS_INSERT=1`](rake_tasks.md#environment-variables)
diff --git a/doc/development/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md
index 2f084937cc9..a5d9a653472 100644
--- a/doc/development/merge_request_performance_guidelines.md
+++ b/doc/development/merge_request_performance_guidelines.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Merge Request Performance Guidelines
Each new introduced merge request **should be performant by default**.
@@ -119,10 +125,10 @@ read this section on [how to prepare the merge request for a database review](da
## Query Counts
-**Summary:** a merge request **should not** increase the number of executed SQL
+**Summary:** a merge request **should not** increase the total number of executed SQL
queries unless absolutely necessary.
-The number of queries executed by the code modified or added by a merge request
+The total number of queries executed by the code modified or added by a merge request
must not increase unless absolutely necessary. When building features it's
entirely possible you will need some extra queries, but you should try to keep
this at a minimum.
@@ -141,7 +147,7 @@ end
This will end up running one query for every object to update. This code can
easily overload a database given enough rows to update or many instances of this
code running in parallel. This particular problem is known as the
-["N+1 query problem"](https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations). You can write a test with [QueryRecoder](query_recorder.md) to detect this and prevent regressions.
+["N+1 query problem"](https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations). You can write a test with [QueryRecorder](query_recorder.md) to detect this and prevent regressions.
In this particular case the workaround is fairly easy:
@@ -152,6 +158,63 @@ objects_to_update.update_all(some_field: some_value)
This uses ActiveRecord's `update_all` method to update all rows in a single
query. This in turn makes it much harder for this code to overload a database.
+## Cached Queries
+
+**Summary:** a merge request **should not** execute duplicated cached queries.
+
+Rails provides an [SQL Query Cache](cached_queries.md#cached-queries-guidelines),
+used to cache the results of database queries for the duration of the request.
+
+See [why cached queries are considered bad](cached_queries.md#why-cached-queries-are-considered-bad) and
+[how to detect them](cached_queries.md#how-to-detect).
+
+The code introduced by a merge request, should not execute multiple duplicated cached queries.
+
+The total number of the queries (including cached ones) executed by the code modified or added by a merge request
+should not increase unless absolutely necessary.
+The number of executed queries (including cached queries) should not depend on
+collection size.
+You can write a test by passing the `skip_cached` variable to [QueryRecorder](query_recorder.md) to detect this and prevent regressions.
+
+As an example, say you have a CI pipeline. All pipeline builds belong to the same pipeline,
+thus they also belong to the same project (`pipeline.project`):
+
+```ruby
+pipeline_project = pipeline.project
+# Project Load (0.6ms) SELECT "projects".* FROM "projects" WHERE "projects"."id" = $1 LIMIT $2
+build = pipeline.builds.first
+
+build.project == pipeline_project
+# CACHE Project Load (0.0ms) SELECT "projects".* FROM "projects" WHERE "projects"."id" = $1 LIMIT $2
+# => true
+```
+
+When we call `build.project`, it will not hit the database, it will use the cached result, but it will re-instantiate
+same pipeline project object. It turns out that associated objects do not point to the same in-memory object.
+
+If we try to serialize each build:
+
+```ruby
+pipeline.builds.each do |build|
+ build.to_json(only: [:name], include: [project: { only: [:name]}])
+end
+```
+
+It will re-instantiate project object for each build, instead of using the same in-memory object.
+
+In this particular case the workaround is fairly easy:
+
+```ruby
+pipeline.builds.each do |build|
+ build.project = pipeline.project
+ build.to_json(only: [:name], include: [project: { only: [:name]}])
+end
+```
+
+We can assign `pipeline.project` to each `build.project`, since we know it should point to the same project.
+This will allow us that each build point to the same in-memory project,
+avoiding the cached SQL query and re-instantiation of the project object for each build.
+
## Executing Queries in Loops
**Summary:** SQL queries **must not** be executed in a loop unless absolutely
@@ -464,7 +527,7 @@ end
The usage of shared temporary storage is required if your intent
is to persistent file for a disk-based storage, and not Object Storage.
-[Workhorse direct_upload](./uploads.md#direct-upload) when accepting file
+[Workhorse direct_upload](uploads.md#direct-upload) when accepting file
can write it to shared storage, and later GitLab Rails can perform a move operation.
The move operation on the same destination is instantaneous.
The system instead of performing `copy` operation just re-attaches file into a new place.
@@ -488,7 +551,7 @@ that implements a seamless support for Shared and Object Storage-based persisten
#### Data access
Each feature that accepts data uploads or allows to download them needs to use
-[Workhorse direct_upload](./uploads.md#direct-upload). It means that uploads needs to be
+[Workhorse direct_upload](uploads.md#direct-upload). It means that uploads needs to be
saved directly to Object Storage by Workhorse, and all downloads needs to be served
by Workhorse.
@@ -500,5 +563,5 @@ can time out, which is especially problematic for slow clients. If clients take
to upload/download the processing slot might be killed due to request processing
timeout (usually between 30s-60s).
-For the above reasons it is required that [Workhorse direct_upload](./uploads.md#direct-upload) is implemented
+For the above reasons it is required that [Workhorse direct_upload](uploads.md#direct-upload) is implemented
for all file uploads and downloads.
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 71191d1d871..84679a78545 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Migration Style Guide
When writing migrations for GitLab, you have to take into account that
@@ -376,8 +382,7 @@ Example changes:
- `change_column_default`
- `create_table` / `drop_table`
-NOTE: **Note:**
-`with_lock_retries` method **cannot** be used within the `change` method, you must manually define the `up` and `down` methods to make the migration reversible.
+The `with_lock_retries` method **cannot** be used within the `change` method, you must manually define the `up` and `down` methods to make the migration reversible.
### How the helper method works
@@ -437,7 +442,6 @@ the `with_multiple_threads` block, instead of re-using the global connection
pool. This ensures each thread has its own connection object, and won't time
out when trying to obtain one.
-NOTE: **Note:**
PostgreSQL has a maximum amount of connections that it allows. This
limit can vary from installation to installation. As a result, it's recommended
you do not use more than 32 threads in a single migration. Usually, 4-8 threads
@@ -474,6 +478,12 @@ 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,
combining it with other operations that don't require `disable_ddl_transaction!`.
+### Disabling an index
+
+There are certain situations in which you might want to disable an index before removing it.
+See the [maintenance operations guide](database/maintenance_operations.md#disabling-an-index)
+for more details.
+
## Adding indexes
Before adding an index, consider if this one is necessary. There are situations in which an index
@@ -612,7 +622,6 @@ Before PostgreSQL 11, adding a column with a default was problematic as it would
have caused a full table rewrite. The corresponding helper `add_column_with_default`
has been deprecated and will be removed in a later release.
-NOTE: **Note:**
If a backport adding a column with a default value is needed for %12.9 or earlier versions,
it should use `add_column_with_default` helper. If a [large table](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3)
is involved, backporting to %12.9 is contraindicated.
@@ -958,7 +967,6 @@ in a previous migration.
### Example: Add a column `my_column` to the users table
-NOTE: **Note:**
It is important not to leave out the `User.reset_column_information` command, in order to ensure that the old schema is dropped from the cache and ActiveRecord loads the updated schema information.
```ruby
diff --git a/doc/development/module_with_instance_variables.md b/doc/development/module_with_instance_variables.md
index 2229c99c99b..80e926f800c 100644
--- a/doc/development/module_with_instance_variables.md
+++ b/doc/development/module_with_instance_variables.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Modules with instance variables could be considered harmful
## Background
diff --git a/doc/development/multi_version_compatibility.md b/doc/development/multi_version_compatibility.md
index 714be296b40..2501f8a169f 100644
--- a/doc/development/multi_version_compatibility.md
+++ b/doc/development/multi_version_compatibility.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Compatibility with multiple versions of the application running at the same time
When adding or changing features, we must be aware that there may be multiple versions of the application running
diff --git a/doc/development/namespaces_storage_statistics.md b/doc/development/namespaces_storage_statistics.md
index 5207276ba73..b4a7c8c3132 100644
--- a/doc/development/namespaces_storage_statistics.md
+++ b/doc/development/namespaces_storage_statistics.md
@@ -1,17 +1,23 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Database case study: Namespaces storage statistics
-## Introduction
+## Introduction
On [Storage and limits management for groups](https://gitlab.com/groups/gitlab-org/-/epics/886),
we want to facilitate a method for easily viewing the amount of
storage consumed by a group, and allow easy management.
-## Proposal
+## Proposal
1. Create a new ActiveRecord model to hold the namespaces' statistics in an aggregated form (only for root namespaces).
1. Refresh the statistics in this model every time a project belonging to this namespace is changed.
-## Problem
+## Problem
In GitLab, we update the project storage statistics through a
[callback](https://gitlab.com/gitlab-org/gitlab/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/app/models/project.rb#L97)
@@ -36,7 +42,7 @@ alternative method.
## Attempts
-### Attempt A: PostgreSQL materialized view
+### Attempt A: PostgreSQL materialized view
Model can be updated through a refresh strategy based on a project routes SQL and a [materialized view](https://www.postgresql.org/docs/11/rules-materializedviews.html):
@@ -65,7 +71,7 @@ While this implied a single query update (and probably a fast one), it has some
- Materialized views syntax varies from PostgreSQL and MySQL. While this feature was worked on, MySQL was still supported by GitLab.
- Rails does not have native support for materialized views. We'd need to use a specialized gem to take care of the management of the database views, which implies additional work.
-### Attempt B: An update through a CTE
+### Attempt B: An update through a CTE
Similar to Attempt A: Model update done through a refresh strategy with a [Common Table Expression](https://www.postgresql.org/docs/9.1/queries-with.html)
@@ -134,7 +140,7 @@ Even though this approach would make aggregating much easier, it has some major
- We'd have to migrate **all namespaces** by adding and filling a new column. Because of the size of the table, dealing with time/cost will not be great. The background migration will take approximately `153h`, see <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29772>.
- Background migration has to be shipped one release before, delaying the functionality by another milestone.
-### Attempt E (final): Update the namespace storage statistics in async way
+### Attempt E (final): Update the namespace storage statistics in async way
This approach consists of keep using the incremental statistics updates we currently already have,
but we refresh them through Sidekiq jobs and in different transactions:
@@ -164,7 +170,7 @@ The only downside of this approach is that namespaces' statistics are updated up
which means there's a time window in which the statistics are inaccurate. Because we're still not
[enforcing storage limits](https://gitlab.com/gitlab-org/gitlab/-/issues/17664), this is not a major problem.
-## Conclusion
+## Conclusion
Updating the storage statistics asynchronously, was the less problematic and
performant approach of aggregating the root namespaces.
diff --git a/doc/development/new_fe_guide/dependencies.md b/doc/development/new_fe_guide/dependencies.md
index afdf6e27b37..fad004f9df5 100644
--- a/doc/development/new_fe_guide/dependencies.md
+++ b/doc/development/new_fe_guide/dependencies.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Dependencies
## Adding Dependencies
diff --git a/doc/development/new_fe_guide/development/accessibility.md b/doc/development/new_fe_guide/development/accessibility.md
index 9c63ccad6e1..1189dd1137b 100644
--- a/doc/development/new_fe_guide/development/accessibility.md
+++ b/doc/development/new_fe_guide/development/accessibility.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Accessibility
Using semantic HTML plays a key role when it comes to accessibility.
@@ -6,7 +12,7 @@ Using semantic HTML plays a key role when it comes to accessibility.
WAI-ARIA (the Accessible Rich Internet Applications specification) defines a way to make Web content and Web applications more accessible to people with disabilities.
-> Note: It is [recommended](https://www.w3.org/TR/using-aria/#notes2) to use semantic elements as the primary method to achieve accessibility rather than adding aria attributes. Adding aria attributes should be seen as a secondary method for creating accessible elements.
+The W3C recommends [using semantic elements](https://www.w3.org/TR/using-aria/#notes2) as the primary method to achieve accessibility rather than adding aria attributes. Adding aria attributes should be seen as a secondary method for creating accessible elements.
### Role
diff --git a/doc/development/new_fe_guide/development/components.md b/doc/development/new_fe_guide/development/components.md
index b7233f5d7c0..1597d4e62e7 100644
--- a/doc/development/new_fe_guide/development/components.md
+++ b/doc/development/new_fe_guide/development/components.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Components
## Graphs
diff --git a/doc/development/new_fe_guide/development/index.md b/doc/development/new_fe_guide/development/index.md
index 119dbc58012..52435ca719d 100644
--- a/doc/development/new_fe_guide/development/index.md
+++ b/doc/development/new_fe_guide/development/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Development
## [Components](components.md)
diff --git a/doc/development/new_fe_guide/development/performance.md b/doc/development/new_fe_guide/development/performance.md
index ad6fdc0b85c..44f5bccde95 100644
--- a/doc/development/new_fe_guide/development/performance.md
+++ b/doc/development/new_fe_guide/development/performance.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Performance
## Monitoring
diff --git a/doc/development/new_fe_guide/index.md b/doc/development/new_fe_guide/index.md
index 9e9c367807f..c9b655c2274 100644
--- a/doc/development/new_fe_guide/index.md
+++ b/doc/development/new_fe_guide/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Frontend Development Guidelines
This guide contains all the information to successfully contribute to GitLab's frontend.
diff --git a/doc/development/new_fe_guide/modules/dirty_submit.md b/doc/development/new_fe_guide/modules/dirty_submit.md
index dd336ad3a90..17cdab3f240 100644
--- a/doc/development/new_fe_guide/modules/dirty_submit.md
+++ b/doc/development/new_fe_guide/modules/dirty_submit.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Dirty Submit
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21115) in GitLab 11.3.
diff --git a/doc/development/new_fe_guide/modules/index.md b/doc/development/new_fe_guide/modules/index.md
index a7820442df0..18c5b05432c 100644
--- a/doc/development/new_fe_guide/modules/index.md
+++ b/doc/development/new_fe_guide/modules/index.md
@@ -1,5 +1,15 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Modules
- [DirtySubmit](dirty_submit.md)
Disable form submits until there are unsaved changes.
+
+- [Merge Request widget extensions](widget_extensions.md)
+
+ Easily add extensions into the merge request widget
diff --git a/doc/development/new_fe_guide/modules/widget_extensions.md b/doc/development/new_fe_guide/modules/widget_extensions.md
new file mode 100644
index 00000000000..3844fedb126
--- /dev/null
+++ b/doc/development/new_fe_guide/modules/widget_extensions.md
@@ -0,0 +1,56 @@
+---
+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
+---
+
+# Merge request widget extensions
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44616) in GitLab 13.6.
+
+## Summary
+
+Extensions in the merge request widget allow for others team to quickly and easily add new features
+into the widget that will match the existing design and interaction as other extensions.
+
+## Usage
+
+To use extensions you need to first create a new extension object that will be used to fetch the
+data that will be rendered in the extension. See the example file in
+app/assets/javascripts/vue_merge_request_widget/extensions/issues.js for a working example.
+
+The basic object structure is as below:
+
+```javascript
+export default {
+ name: '',
+ props: [],
+ computed: {
+ summary() {},
+ statusIcon() {},
+ },
+ methods: {
+ fetchCollapsedData() {},
+ fetchFullData() {},
+ },
+};
+```
+
+Following the same data structure allows each extension to follow the same registering structure
+but allows for each extension to manage where it gets its own data from.
+
+After creating this structure you need to register it. Registering the extension can happen at any
+point _after_ the widget has been created.
+
+To register a extension the following can be done:
+
+```javascript
+// Import the register method
+import { registerExtension } from '~/vue_merge_request_widget/components/extensions';
+
+// Import the new extension
+import issueExtension from '~/vue_merge_request_widget/extensions/issues';
+
+// Register the imported extension
+registerExtension(issueExtension);
+```
diff --git a/doc/development/new_fe_guide/tips.md b/doc/development/new_fe_guide/tips.md
index c65266a3f25..d7e9c440335 100644
--- a/doc/development/new_fe_guide/tips.md
+++ b/doc/development/new_fe_guide/tips.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: Development
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Tips
## Clearing production compiled assets
diff --git a/doc/development/newlines_styleguide.md b/doc/development/newlines_styleguide.md
index e298ba1d935..f123482fa5a 100644
--- a/doc/development/newlines_styleguide.md
+++ b/doc/development/newlines_styleguide.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Newlines style guide
This style guide recommends best practices for newlines in Ruby code.
diff --git a/doc/development/omnibus.md b/doc/development/omnibus.md
index deaf72d2ecf..84c395e2e57 100644
--- a/doc/development/omnibus.md
+++ b/doc/development/omnibus.md
@@ -1,3 +1,9 @@
+---
+stage: Enablement
+group: Distribution
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# What you should know about Omnibus packages
Most users install GitLab using our Omnibus packages. As a developer it can be
diff --git a/doc/development/ordering_table_columns.md b/doc/development/ordering_table_columns.md
index 18788d0b86e..124f82ac2c8 100644
--- a/doc/development/ordering_table_columns.md
+++ b/doc/development/ordering_table_columns.md
@@ -1,3 +1,9 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Ordering Table Columns in PostgreSQL
For GitLab we require that columns of new tables are ordered to use the
@@ -45,7 +51,6 @@ In these examples, the `id` and `user_id` columns are packed together, which
means we only need 8 bytes to store _both_ of them. This in turn means each row
will require 8 bytes less space.
-Note: **NOTE:**
Since Ruby on Rails 5.1, the default data type for IDs is `bigint`, which uses 8 bytes.
We are using `integer` in the examples to showcase a more realistic reordering scenario.
diff --git a/doc/development/packages.md b/doc/development/packages.md
index 9eae99ff890..de6cac2ce73 100644
--- a/doc/development/packages.md
+++ b/doc/development/packages.md
@@ -13,12 +13,13 @@ See already supported package types in [Packages documentation](../administratio
Since GitLab packages' UI is pretty generic, it is possible to add basic new
package system support with solely backend changes. This guide is superficial and does
not cover the way the code should be written. However, you can find a good example
-by looking at merge requests with Maven and NPM support:
+by looking at the following merge requests:
- [NPM registry support](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8673).
-- [Conan repository](https://gitlab.com/gitlab-org/gitlab/-/issues/8248).
- [Maven repository](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6607).
-- [Instance level endpoint for Maven repository](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8757)
+- [Composer repository for PHP dependencies](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22415).
+- [Terraform modules registry](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834).
+- [Instance-level endpoint for Maven repository](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8757).
## General information
diff --git a/doc/development/performance.md b/doc/development/performance.md
index 3b59393bae6..e20633a05f6 100644
--- a/doc/development/performance.md
+++ b/doc/development/performance.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Performance Guidelines
This document describes various guidelines to follow to ensure good and
@@ -334,15 +340,49 @@ These results can also be placed into a PostgreSQL database by setting the
`RSPEC_PROFILING_POSTGRES_URL` variable. This is used to profile the test suite
when running in the CI environment.
-We store these results also when running CI jobs on the default branch on
-`gitlab.com`. Statistics of these profiling data are [available
-online](https://gitlab-org.gitlab.io/rspec_profiling_stats/). For example,
-you can find which tests take longest to run or which execute the most
+We store these results also when running nightly scheduled CI jobs on the
+default branch on `gitlab.com`. Statistics of these profiling data are
+[available online](https://gitlab-org.gitlab.io/rspec_profiling_stats/). For
+example, you can find which tests take longest to run or which execute the most
queries. This can be handy for optimizing our tests or identifying performance
issues in our code.
## Memory profiling
+We can use two approaches, often in combination, to track down memory issues:
+
+- Leaving the code intact and wrapping a profiler around it.
+- Monitor memory usage of the process while disabling/enabling different parts of the code we suspect could be problematic.
+
+### Using Memory Profiler
+
+We can use `memory_profiler` for profiling.
+
+The [`memory_profiler`](https://github.com/SamSaffron/memory_profiler) gem is already present in GitLab's `Gemfile`,
+you just need to require it:
+
+```ruby
+require 'sidekiq/testing'
+
+report = MemoryProfiler.report do
+ # Code you want to profile
+end
+
+output = File.open('/tmp/profile.txt','w')
+report.pretty_print(output)
+```
+
+The report breaks down 2 key concepts:
+
+- Retained: long lived memory use and object count retained due to the execution of the code block.
+- Allocated: all object allocation and memory allocation during code block.
+
+As a general rule, **retained** will always be smaller than or equal to allocated.
+
+The actual RSS cost will always be slightly higher as MRI heaps are not squashed to size and memory fragments.
+
+### Rbtrace
+
One of the reasons of the increased memory footprint could be Ruby memory fragmentation.
To diagnose it, you can visualize Ruby heap as described in [this post by Aaron Patterson](https://tenderlovemaking.com/2017/09/27/visualizing-your-ruby-heap.html).
diff --git a/doc/development/permissions.md b/doc/development/permissions.md
index e930345caec..859c838280e 100644
--- a/doc/development/permissions.md
+++ b/doc/development/permissions.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# GitLab permissions guide
There are multiple types of permissions across GitLab, and when implementing
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index d12220d8c95..a8ef5701d50 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Pipelines for the GitLab project
Pipelines for <https://gitlab.com/gitlab-org/gitlab> and <https://gitlab.com/gitlab-org/gitlab-foss> (as well as the
@@ -618,7 +624,7 @@ each pipeline includes default variables defined in
Most of the jobs [extend from a few CI definitions](../ci/yaml/README.md#extends)
defined in [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml)
-that are scoped to a single [configuration parameter](../ci/yaml/README.md#configuration-parameters).
+that are scoped to a single [configuration keyword](../ci/yaml/README.md#job-keywords).
| Job definitions | Description |
|------------------|-------------|
diff --git a/doc/development/policies.md b/doc/development/policies.md
index 8dfd4763551..b44367f7075 100644
--- a/doc/development/policies.md
+++ b/doc/development/policies.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# `DeclarativePolicy` framework
The DeclarativePolicy framework is designed to assist in performance of policy checks, and to enable ease of extension for EE. The DSL code in `app/policies` is what `Ability.allowed?` uses to check whether a particular action is allowed on a subject.
diff --git a/doc/development/polling.md b/doc/development/polling.md
index 47cfc32d934..b06507787b0 100644
--- a/doc/development/polling.md
+++ b/doc/development/polling.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Polling with ETag caching
Polling for changes (repeatedly asking server if there are any new changes)
diff --git a/doc/development/polymorphic_associations.md b/doc/development/polymorphic_associations.md
index b6567704d8e..66ea974063a 100644
--- a/doc/development/polymorphic_associations.md
+++ b/doc/development/polymorphic_associations.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Polymorphic Associations
**Summary:** always use separate tables instead of polymorphic associations.
diff --git a/doc/development/post_deployment_migrations.md b/doc/development/post_deployment_migrations.md
index 4d523178a21..2550f9547df 100644
--- a/doc/development/post_deployment_migrations.md
+++ b/doc/development/post_deployment_migrations.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Post Deployment Migrations
Post deployment migrations are regular Rails migrations that can optionally be
diff --git a/doc/development/product_analytics/event_dictionary.md b/doc/development/product_analytics/event_dictionary.md
index b049db21c30..88cb75fdb83 100644
--- a/doc/development/product_analytics/event_dictionary.md
+++ b/doc/development/product_analytics/event_dictionary.md
@@ -1,32 +1,5 @@
---
-stage: Growth
-group: Product Analytics
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+redirect_to: 'https://about.gitlab.com/handbook/product/product-analytics-guide/'
---
-# Event Dictionary
-
-**Note: We've temporarily moved the Event Dictionary to a [Google Sheet](https://docs.google.com/spreadsheets/d/1VzE8R72Px_Y_LlE3Z05LxUlG_dumWe3vl-HeUo70TPw/edit?usp=sharing)**. The previous Markdown table exceeded 600 rows making it difficult to manage. In the future, our intention is to move this back into our docs using a [YAML file](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/823).
-
-The event dictionary is a single source of truth for the metrics and events we collect for product usage data. The Event Dictionary lists all the metrics and events we track, why we're tracking them, and where they are tracked.
-
-This is a living document that is updated any time a new event is planned or implemented. It includes the following information.
-
-- Section, stage, or group
-- Description
-- Implementation status
-- Availability by plan type
-- Code path
-
-We're currently focusing our Event Dictionary on [Usage Ping](usage_ping.md). In the future, we will also include [Snowplow](snowplow.md). We currently have an initiative across the entire product organization to complete the [Event Dictionary for Usage Ping](https://gitlab.com/groups/gitlab-org/-/epics/4174).
-
-## Instructions
-
-1. Open the Event Dictionary and fill in all the **PM to edit** columns highlighted in yellow.
-1. Check that all the metrics and events are assigned to the correct section, stage, or group. If a metric is used across many groups, assign it to the stage. If a metric is used across many stages, assign it to the section. If a metric is incorrectly assigned to another section, stage, or group, let the PM know you have reassigned it. If your group has no assigned metrics and events, check that your metrics and events are not incorrectly assigned to another PM.
-1. Add descriptions of what your metrics and events are tracking. Work with your Engineering team or the Product Analytics team if you need help understanding this.
-1. Add what plans this metric is available on. Work with your Engineering team or the Product Analytics team if you need help understanding this.
-
-## Planned metrics and events
-
-For future metrics and events you plan to track, please add them to the Event Dictionary and note the status as `Planned`, `In Progress`, or `Implemented`. Once you have confirmed the metric has been implemented and have confirmed the metric data is in our data warehouse, change the status to **Data Available**.
+This document was moved to [another location](https://about.gitlab.com/handbook/product/product-analytics-guide/).
diff --git a/doc/development/product_analytics/index.md b/doc/development/product_analytics/index.md
index ab76d6f0561..88cb75fdb83 100644
--- a/doc/development/product_analytics/index.md
+++ b/doc/development/product_analytics/index.md
@@ -1,182 +1,5 @@
---
-stage: Growth
-group: Product Analytics
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+redirect_to: 'https://about.gitlab.com/handbook/product/product-analytics-guide/'
---
-# Product Analytics Guide
-
-At GitLab, we collect product usage data for the purpose of helping us build a better product. Data helps GitLab understand which parts of the product need improvement and which features we should build next. Product usage data also helps our team better understand the reasons why people use GitLab. With this knowledge we are able to make better product decisions.
-
-We encourage users to enable tracking, and we embrace full transparency with our tracking approach so it can be easily understood and trusted.
-
-By enabling tracking, users can:
-
-- Contribute back to the wider community.
-- Help GitLab improve on the product.
-
-## Our tracking tools
-
-We use three methods to gather product usage data:
-
-- [Snowplow](#snowplow)
-- [Usage Ping](#usage-ping)
-- [Database import](#database-import)
-
-### Snowplow
-
-Snowplow is an enterprise-grade marketing and product analytics platform which helps track the way
-users engage with our website and application.
-
-Snowplow consists of two components:
-
-- [Snowplow JS](https://github.com/snowplow/snowplow/wiki/javascript-tracker) tracks client-side
- events.
-- [Snowplow Ruby](https://github.com/snowplow/snowplow/wiki/ruby-tracker) tracks server-side events.
-
-For more details, read the [Snowplow](snowplow.md) guide.
-
-### Usage Ping
-
-Usage Ping is a method for GitLab Inc to collect usage data on a GitLab instance. Usage Ping is primarily composed of row counts for different tables in the instance’s database. By comparing these counts month over month (or week over week), we can get a rough sense for how an instance is using the different features within the product. This high-level data is used to help our product, support, and sales teams.
-
-For more details, read the [Usage Ping](usage_ping.md) guide.
-
-### Database import
-
-Database imports are full imports of data into GitLab's data warehouse. For GitLab.com, the PostgreSQL database is loaded into Snowflake data warehouse every 6 hours. For more details, see the [data team handbook](https://about.gitlab.com/handbook/business-ops/data-team/platform/#extract-and-load).
-
-## What data can be tracked
-
-Our different tracking tools allows us to track different types of events. The event types and examples of what data can be tracked are outlined below.
-
-The availability of event types and their tracking tools varies by segment. For example, on Self-Managed Users, we only have reporting using Database records via Usage Ping.
-
-| Event Types | SaaS Instance | SaaS Plan | SaaS Group | SaaS Session | SaaS User | SM Instance | SM Plan | SM Group | SM Session | SM User |
-|----------------------------------------|---------------|-----------|------------|--------------|-----------|-------------|---------|----------|------------|---------|
-| Snowplow (JS Pageview events) | ✅ | 📅 | 📅 | ✅ | 📅 | 📅 | 📅 | 📅 | 📅 | 📅 |
-| Snowplow (JS UI events) | ✅ | 📅 | 📅 | ✅ | 📅 | 📅 | 📅 | 📅 | 📅 | 📅 |
-| Snowplow (Ruby Pageview events) | ✅ | 📅 | 📅 | ✅ | 📅 | 📅 | 📅 | 📅 | 📅 | 📅 |
-| Snowplow (Ruby CRUD / API events) | ✅ | 📅 | 📅 | ✅ | 📅 | 📅 | 📅 | 📅 | 📅 | 📅 |
-| Usage Ping (Redis UI counters) | 🔄 | 🔄 | 🔄 | âœ–ï¸ | 🔄 | 🔄 | 🔄 | 🔄 | âœ–ï¸ | 🔄 |
-| Usage Ping (Redis Pageview counters) | 🔄 | 🔄 | 🔄 | âœ–ï¸ | 🔄 | 🔄 | 🔄 | 🔄 | âœ–ï¸ | 🔄 |
-| Usage Ping (Redis CRUD / API counters) | 🔄 | 🔄 | 🔄 | âœ–ï¸ | 🔄 | 🔄 | 🔄 | 🔄 | âœ–ï¸ | 🔄 |
-| Usage Ping (Database counters) | ✅ | 🔄 | 📅 | âœ–ï¸ | ✅ | ✅ | ✅ | ✅ | âœ–ï¸ | ✅ |
-| Usage Ping (Instance settings) | ✅ | 🔄 | 📅 | âœ–ï¸ | ✅ | ✅ | ✅ | ✅ | âœ–ï¸ | ✅ |
-| Usage Ping (Integration settings) | ✅ | 🔄 | 📅 | âœ–ï¸ | ✅ | ✅ | ✅ | ✅ | âœ–ï¸ | ✅ |
-| Database import (Database records) | ✅ | ✅ | ✅ | âœ–ï¸ | ✅ | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ |
-
-[Source file](https://docs.google.com/spreadsheets/d/1e8Afo41Ar8x3JxAXJF3nL83UxVZ3hPIyXdt243VnNuE/edit?usp=sharing)
-
-**Legend**
-
-✅ Available, 🔄 In Progress, 📅 Planned, âœ–ï¸ Not Possible
-
-SaaS = GitLab.com. SM = Self-Managed instance
-
-### Pageview events
-
-- Number of sessions that visited the /dashboard/groups page
-
-### UI events
-
-- Number of sessions that clicked on a button or link
-- Number of sessions that closed a modal
-
-UI events are any interface-driven actions from the browser including click data.
-
-### CRUD or API events
-
-- Number of Git pushes
-- Number of GraphQL queries
-- Number of requests to a Rails action or controller
-
-These are backend events that include the creation, read, update, deletion of records, and other events that might be triggered from layers other than those available in the interface.
-
-### Database records
-
-These are raw database records which can be explored using business intelligence tools like Sisense. The full list of available tables can be found in [structure.sql](https://gitlab.com/gitlab-org/gitlab/-/blob/master/db/structure.sql).
-
-### Instance settings
-
-These are settings of your instance such as the instance's Git version and if certain features are enabled such as `container_registry_enabled`.
-
-### Integration settings
-
-These are integrations your GitLab instance interacts with such as an [external storage provider](../../administration/static_objects_external_storage.md) or an [external container registry](../../administration/packages/container_registry.md#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint). These services must be able to send data back into a GitLab instance for data to be tracked.
-
-## Reporting level
-
-Our reporting levels of aggregate or individual reporting varies by segment. For example, on Self-Managed Users, we can report at an aggregate user level using Usage Ping but not on an Individual user level.
-
-| Aggregated Reporting | SaaS Instance | SaaS Plan | SaaS Group | SaaS Session | SaaS User | SM Instance | SM Plan | SM Group | SM Session | SM User |
-|----------------------|---------------|-----------|------------|--------------|-----------|-------------|---------|----------|------------|---------|
-| Snowplow | ✅ | 📅 | 📅 | ✅ | 📅 | ✅ | 📅 | 📅 | ✅ | 📅 |
-| Usage Ping | ✅ | 🔄 | 📅 | 📅 | ✅ | ✅ | ✅ | ✅ | 📅 | ✅ |
-| Database import | ✅ | ✅ | ✅ | âœ–ï¸ | ✅ | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ |
-
-| Identifiable Reporting | SaaS Instance | SaaS Plan | SaaS Group | SaaS Session | SaaS User | SM Instance | SM Plan | SM Group | SM Session | SM User |
-|------------------------|---------------|-----------|------------|--------------|-----------|-------------|---------|----------|------------|---------|
-| Snowplow | ✅ | 📅 | 📅 | ✅ | 📅 | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ |
-| Usage Ping | ✅ | 🔄 | 📅 | âœ–ï¸ | âœ–ï¸ | ✅ | ✅ | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ |
-| Database import | ✅ | ✅ | ✅ | âœ–ï¸ | ✅ | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ | âœ–ï¸ |
-
-**Legend**
-
-✅ Available, 🔄 In Progress, 📅 Planned, âœ–ï¸ Not Possible
-
-SaaS = GitLab.com. SM = Self-Managed instance
-
-## Reporting time period
-
-Our reporting time periods varies by segment. For example, on Self-Managed Users, we can report all time counts and 28 day counts in Usage Ping.
-
-| Reporting Time Period | All Time | 28 Days | 7 Days | Daily |
-|-----------------------|----------|---------|--------|-------|
-| Snowplow | ✅ | ✅ | ✅ | ✅ |
-| Usage Ping | ✅ | ✅ | 📅 | âœ–ï¸ |
-| Database import | ✅ | ✅ | ✅ | ✅ |
-
-**Legend**
-
-✅ Available, 🔄 In Progress, 📅 Planned, âœ–ï¸ Not Possible
-
-## Systems overview
-
-The systems overview is a simplified diagram showing the interactions between GitLab Inc and self-managed instances.
-
-![Product Analytics Overview](../img/telemetry_system_overview.png)
-
-[Source file](https://app.diagrams.net/#G13DVpN-XnhWGz9tqReIj8pp1UE4ehk_EC)
-
-### GitLab Inc
-
-For Product Analytics purposes, GitLab Inc has three major components:
-
-1. [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/): This contains everything managed by our data team including Sisense Dashboards for visualization, Snowflake for Data Warehousing, incoming data sources such as PostgreSQL Pipeline and S3 Bucket, and lastly our data collectors [GitLab.com's Snowplow Collector](https://gitlab.com/gitlab-com/gl-infra/readiness/-/tree/master/library/snowplow/) and GitLab's Versions Application.
-1. GitLab.com: This is the production GitLab application which is made up of a Client and Server. On the Client or browser side, a Snowplow JS Tracker (Frontend) is used to track client-side events. On the Server or application side, a Snowplow Ruby Tracker (Backend) is used to track server-side events. The server also contains Usage Ping which leverages a PostgreSQL database and a Redis in-memory data store to report on usage data. Lastly, the server also contains System Logs which are generated from running the GitLab application.
-1. [Monitoring infrastructure](https://about.gitlab.com/handbook/engineering/monitoring/): This is the infrastructure used to ensure GitLab.com is operating smoothly. System Logs are sent from GitLab.com to our monitoring infrastructure and collected by a FluentD collector. From FluentD, logs are either sent to long term Google Cloud Services cold storage via Stackdriver, or, they are sent to our Elastic Cluster via Cloud Pub/Sub which can be explored in real-time using Kibana.
-
-### Self-managed
-
-For Product Analytics purposes, self-managed instances have two major components:
-
-1. Data infrastructure: Having a data infrastructure setup is optional on self-managed instances. If you'd like to collect Snowplow tracking events for your self-managed instance, you can setup your own self-managed Snowplow collector and configure your Snowplow events to point to your own collector.
-1. GitLab: A self-managed GitLab instance contains all of the same components as GitLab.com mentioned above.
-
-### Differences between GitLab Inc and Self-managed
-
-As shown by the orange lines, on GitLab.com Snowplow JS, Snowplow Ruby, Usage Ping, and PostgreSQL database imports all flow into GitLab Inc's data infrastructure. However, on self-managed, only Usage Ping flows into GitLab Inc's data infrastructure.
-
-As shown by the green lines, on GitLab.com system logs flow into GitLab Inc's monitoring infrastructure. On self-managed, there are no logs sent to GitLab Inc's monitoring infrastructure.
-
-Note (1): Snowplow JS and Snowplow Ruby are available on self-managed, however, the Snowplow Collector endpoint is set to a self-managed Snowplow Collector which GitLab Inc does not have access to.
-
-## Additional information
-
-More useful links:
-
-- [Product Analytics Direction](https://about.gitlab.com/direction/product-analytics/)
-- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/)
-- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/)
-- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/)
+This document was moved to [another location](https://about.gitlab.com/handbook/product/product-analytics-guide/).
diff --git a/doc/development/product_analytics/snowplow.md b/doc/development/product_analytics/snowplow.md
index 21d92566ffd..c5f48994d5c 100644
--- a/doc/development/product_analytics/snowplow.md
+++ b/doc/development/product_analytics/snowplow.md
@@ -10,7 +10,7 @@ This guide provides an overview of how Snowplow works, and implementation detail
For more information about Product Analytics, see:
-- [Product Analytics Guide](index.md)
+- [Product Analytics Guide](https://about.gitlab.com/handbook/product/product-analytics-guide/)
- [Usage Ping Guide](usage_ping.md)
More useful links:
@@ -52,7 +52,7 @@ Tracking can be enabled at:
- The instance level, which enables tracking on both the frontend and backend layers.
- User level, though user tracking can be disabled on a per-user basis. GitLab tracking respects the [Do Not Track](https://www.eff.org/issues/do-not-track) standard, so any user who has enabled the Do Not Track option in their browser is not tracked at a user level.
-We utilize Snowplow for the majority of our tracking strategy and it is enabled on GitLab.com. On a self-managed instance, Snowplow can be enabled by navigating to:
+We use Snowplow for the majority of our tracking strategy and it is enabled on GitLab.com. On a self-managed instance, Snowplow can be enabled by navigating to:
- **Admin Area > Settings > General** in the UI.
- `admin/application_settings/integrations` in your browser.
@@ -112,7 +112,7 @@ The current method provides several attributes that are sent on each click event
## 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 [Structured event taxonomy](#structured-event-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 use tracking, but each generally requires at minimum, a `category` and an `action`. Additional data can be provided that adheres to our [Structured event taxonomy](#structured-event-taxonomy).
| field | type | default value | description |
|:-----------|:-------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -294,7 +294,7 @@ Custom event tracking and instrumentation can be added by directly calling the `
| `action` | string | 'generic' | The action being taken, which can be anything from a controller action like `create` to something like an Active Record callback. |
| `data` | object | {} | Additional data such as `label`, `property`, `value`, and `context` as described in [Structured event taxonomy](#structured-event-taxonomy). These are set as empty strings if you don't provide them. |
-Tracking can be viewed as either tracking user behavior, or can be utilized for instrumentation to monitor and visualize performance over time in an area or aspect of code.
+Tracking can be viewed as either tracking user behavior, or can be used for instrumentation to monitor and visualize performance over time in an area or aspect of code.
For example:
diff --git a/doc/development/product_analytics/usage_ping.md b/doc/development/product_analytics/usage_ping.md
index d482af77d8a..fa785d934cb 100644
--- a/doc/development/product_analytics/usage_ping.md
+++ b/doc/development/product_analytics/usage_ping.md
@@ -15,7 +15,7 @@ This guide describes Usage Ping's purpose and how it's implemented.
For more information about Product Analytics, see:
-- [Product Analytics Guide](index.md)
+- [Product Analytics Guide](https://about.gitlab.com/handbook/product/product-analytics-guide/)
- [Snowplow Guide](snowplow.md)
More useful links:
@@ -270,7 +270,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
##### Adding new events
-1. Define events in [`known_events.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events.yml).
+1. Define events in [`known_events`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/).
Example event:
@@ -312,6 +312,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
- `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.
+ - `feature_flag`: optional. For details, see our [GitLab internal Feature flags](../feature_flags/) documentation.
1. Track event in controller using `RedisTracking` module with `track_redis_hll_event(*controller_actions, name:, feature:, feature_default_enabled: false)`.
@@ -402,7 +403,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
| `event` | string | yes | The event name it should be tracked |
Response
-w
+
Return 200 if tracking failed for any reason.
- `200` if event was tracked or any errors
@@ -412,7 +413,7 @@ w
1. Track events using JavaScript/Vue API helper which calls the API above
- Example usage for an existing event already defined in [known events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events.yml):
+ Example usage for an existing event already defined in [known events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/):
Note that `usage_data_api` and `usage_data_#{event_name}` should be enabled in order to be able to track events
@@ -422,20 +423,46 @@ w
api.trackRedisHllUserEvent('my_already_defined_event_name'),
```
-1. Track event using base module `Gitlab::UsageDataCounters::HLLRedisCounter.track_event(entity_id, event_name)`.
+1. Track event using base module `Gitlab::UsageDataCounters::HLLRedisCounter.track_event(values, event_name)`.
+
+ Arguments:
+
+ - `values`: One value or array of values we count. For example: user_id, visitor_id, user_ids.
+ - `event_name`: event name.
+
+1. Track event on context level using base module `Gitlab::UsageDataCounters::HLLRedisCounter.track_event_in_context(entity_id, event_name, context)`.
Arguments:
- `entity_id`: value we count. For example: user_id, visitor_id.
- `event_name`: event name.
+ - `context`: context value. Allowed values are `default`, `free`, `bronze`, `silver`, `gold`, `starter`, `premium`, `ultimate`
-1. Get event data using `Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names:, start_date:, end_date)`.
+1. Get event data using `Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names:, start_date:, end_date:, context: '')`.
Arguments:
- `event_names`: the list of event names.
- `start_date`: start date of the period for which we want to get event data.
- `end_date`: end date of the period for which we want to get event data.
+ - `context`: context of the event. Allowed values are `default`, `free`, `bronze`, `silver`, `gold`, `starter`, `premium`, `ultimate`.
+
+1. Testing tracking and getting unique events
+
+Trigger events in rails console by using `track_event` method
+
+ ```ruby
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(1, 'g_compliance_audit_events')
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(2, 'g_compliance_audit_events')
+ ```
+
+Next, get the unique events for the current week.
+
+ ```ruby
+ # Get unique events for metric for current_week
+ Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'g_compliance_audit_events',
+ start_date: Date.current.beginning_of_week, end_date: Date.current.end_of_week)
+ ```
Recommendations:
@@ -445,9 +472,23 @@ Recommendations:
- Use a [feature flag](../../operations/feature_flags.md) to have a control over the impact when
adding new metrics.
+##### Enable/Disable Redis HLL tracking
+
+Events are tracked behind [feature flags](../feature_flags/index.md) due to concerns for Redis performance and scalability.
+
+For a full list of events and coresponding feature flags see, [known_events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/) files.
+
+To enable or disable tracking for specific event within <https://gitlab.com> or <https://staging.gitlab.com>, run commands such as the following to
+[enable or disable the corresponding feature](../feature_flags/index.md).
+
+```shell
+/chatops run feature set <feature_name> true
+/chatops run feature set <feature_name> false
+```
+
##### Known events in usage data payload
-All events added in [`known_events.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).
+All events added in [`known_events/common.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml) are automatically added to usage data generation under the `redis_hll_counters` key. This column is stored in [version-app as a JSON](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L209).
For each event we add metrics for the weekly and monthly time frames, and totals for each where applicable:
- `#{event_name}_weekly`: Data for 7 days for daily [aggregation](#adding-new-events) events and data for the last complete week for weekly [aggregation](#adding-new-events) events.
@@ -493,7 +534,7 @@ Example usage:
redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter)
redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] }
-# Define events in known_events.yml https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events.yml
+# Define events in common.yml https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml
# Tracking events
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(visitor_id, 'expand_vulnerabilities')
@@ -548,7 +589,17 @@ for how to use its API to query for data.
## Developing and testing Usage Ping
-### 1. Use your Rails console to manually test counters
+### 1. Naming and placing the metrics
+
+Add the metric in one of the top level keys
+
+- `license`: for license related metrics.
+- `settings`: for settings related metrics.
+- `counts_weekly`: for counters that have data for the most recent 7 days.
+- `counts_monthly`: for counters that have data for the most recent 28 days.
+- `counts`: for counters that have data for all time.
+
+### 2. Use your Rails console to manually test counters
```ruby
# count
@@ -560,7 +611,7 @@ Gitlab::UsageData.distinct_count(::Project, :creator_id)
Gitlab::UsageData.distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id))
```
-### 2. Generate the SQL query
+### 3. Generate the SQL query
Your Rails console will return the generated SQL queries.
@@ -574,7 +625,7 @@ pry(main)> Gitlab::UsageData.count(User.active)
(1.9ms) SELECT COUNT("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) AND "users"."id" BETWEEN 1 AND 100000
```
-### 3. Optimize queries with #database-lab
+### 4. Optimize queries with #database-lab
Paste the SQL query into `#database-lab` to see how the query performs at scale.
@@ -601,27 +652,27 @@ We also use `#database-lab` and [explain.depesz.com](https://explain.depesz.com/
- Avoid joins and write the queries as simply as possible, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36316).
- Set a custom `batch_size` for `distinct_count`, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38000).
-### 4. Add the metric definition
+### 5. Add the metric definition
-When adding, changing, or updating metrics, please update the [Event Dictionary's **Usage Ping** table](event_dictionary.md).
+When adding, changing, or updating metrics, please update the [Event Dictionary's **Usage Ping** table](https://about.gitlab.com/handbook/product/product-analytics-guide#event-dictionary).
-### 5. Add new metric to Versions Application
+### 6. Add new metric to Versions Application
Check if new metrics need to be added to the Versions Application. See `usage_data` [schema](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L147) and usage data [parameters accepted](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/app/services/usage_ping.rb). Any metrics added under the `counts` key are saved in the `stats` column.
-### 6. Add the feature label
+### 7. Add the feature label
Add the `feature` label to the Merge Request for new Usage Ping metrics. These are user-facing changes and are part of expanding the Usage Ping feature.
-### 7. Add a changelog file
+### 8. Add a changelog file
Ensure you comply with the [Changelog entries guide](../changelog.md).
-### 8. Ask for a Product Analytics Review
+### 9. Ask for a Product Analytics Review
On GitLab.com, we have DangerBot setup to monitor Product Analytics related files and DangerBot will recommend a Product Analytics review. Mention `@gitlab-org/growth/product_analytics/engineers` in your MR for a review.
-### 9. Verify your metric
+### 10. Verify your metric
On GitLab.com, the Product Analytics team regularly monitors Usage Ping. They may alert you that your metrics need further optimization to run quicker and with greater success. You may also use the [Usage Ping QA dashboard](https://app.periscopedata.com/app/gitlab/632033/Usage-Ping-QA) to check how well your metric performs. The dashboard allows filtering by GitLab version, by "Self-managed" & "Saas" and shows you how many failures have occurred for each metric. Whenever you notice a high failure rate, you may re-optimize your metric.
@@ -671,6 +722,59 @@ with any of the other services that are running. That is not how node metrics ar
always runs as a process alongside other GitLab components on any given node. From Usage Ping's perspective none of the node data would therefore
appear to be associated to any of the services running, since they all appear to be running on different hosts. To alleviate this problem, the `node_exporter` in GCK was arbitrarily "assigned" to the `web` service, meaning only for this service `node_*` metrics will appear in Usage Ping.
+## Aggregated metrics
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45979) in GitLab 13.6.
+> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - It's enabled on GitLab.com.
+
+CAUTION: **Warning:**
+This feature is intended solely for internal GitLab use.
+
+In order to add data for aggregated metrics into Usage Ping payload you should add corresponding definition into [`aggregated_metrics.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics.yml) file. Each aggregate definition includes following parts:
+
+- name: unique name under which aggregate metric will be added to Usage Ping payload
+- operator: operator that defines how aggregated metric data will be counted. Available operators are:
+ - `OR`: removes duplicates and counts all entries that triggered any of listed events
+ - `AND`: removes duplicates and counts all elements that were observed triggering all of following events
+- events: list of events names (from [`known_events.yml`](#known-events-in-usage-data-payload)) to aggregate into metric. All events in this list must have the same `redis_slot` and `aggregation` attributes.
+- feature_flag: name of [development feature flag](../feature_flags/development.md#development-type) that will be checked before
+metrics aggregation is performed. Corresponding feature flag should have `default_enabled` attribute set to `false`.
+`feature_flag` attribute is **OPTIONAL** and can be omitted, when `feature_flag` is missing no feature flag will be checked.
+
+Example aggregated metric entries:
+
+```yaml
+- name: product_analytics_test_metrics_union
+ operator: OR
+ events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
+- name: product_analytics_test_metrics_intersection_with_feautre_flag
+ operator: AND
+ events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
+ feature_flag: example_aggregated_metric
+```
+
+Aggregated metrics will be added under `aggregated_metrics` key in both `counts_weekly` and `counts_monthly` top level keys in Usage Ping payload.
+
+```ruby
+{
+ :counts_monthly => {
+ :deployments => 1003,
+ :successful_deployments => 78,
+ :failed_deployments => 275,
+ :packages => 155,
+ :personal_snippets => 2106,
+ :project_snippets => 407,
+ :promoted_issues => 719,
+ :aggregated_metrics => {
+ :product_analytics_test_metrics_union => 7,
+ :product_analytics_test_metrics_intersection_with_feautre_flag => 2
+ },
+ :snippets => 2513
+ }
+}
+```
+
## Example Usage Ping payload
The following is example content of the Usage Ping payload.
@@ -935,3 +1039,7 @@ bin/rake gitlab:usage_data:dump_sql_in_json
# You may pipe the output into a file
bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02.yaml
```
+
+## Generating and troubleshooting usage ping
+
+To get a usage ping, or to troubleshoot caching issues on your GitLab instance, please follow [instructions to generate usage ping](../../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping).
diff --git a/doc/development/profiling.md b/doc/development/profiling.md
index f5a4d1edb92..6e1b81e659d 100644
--- a/doc/development/profiling.md
+++ b/doc/development/profiling.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Profiling
To make it easier to track down performance problems GitLab comes with a set of
@@ -10,7 +16,6 @@ There is a `Gitlab::Profiler.profile` method, and corresponding
`bin/profile-url` script, that enable profiling a GET or POST request to a
specific URL, either as an anonymous user (the default) or as a specific user.
-NOTE: **Note:**
The first argument to the profiler is either a full URL
(including the instance hostname) or an absolute path, including the
leading slash.
diff --git a/doc/development/projections.md b/doc/development/projections.md
index 9d5702da530..b8f476c53e9 100644
--- a/doc/development/projections.md
+++ b/doc/development/projections.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Projections
Projections are a way to define relations between files. Every file can have a
diff --git a/doc/development/prometheus.md b/doc/development/prometheus.md
index 3e7acaf6d94..fc1f2303d0a 100644
--- a/doc/development/prometheus.md
+++ b/doc/development/prometheus.md
@@ -1,59 +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: '../user/project/integrations/prometheus.md'
---
-# Working with Prometheus
-
-For more information on working with [Prometheus metrics](prometheus_metrics.md), see
-the documentation.
-
-## Access the UI of a Prometheus managed application in Kubernetes
-
-You can connect directly to Prometheus, and view the Prometheus user interface, when
-using a Prometheus managed application in Kubernetes:
-
-1. Find the name of the Prometheus pod in the user interface of your Kubernetes
- provider, such as GKE, or by running the following `kubectl` command in your
- terminal:
-
- ```shell
- kubectl get pods -n gitlab-managed-apps | grep 'prometheus-prometheus-server'
- ```
-
- The command should return a result like the following example, where
- `prometheus-prometheus-server-55b4bd64c9-dpc6b` is the name of the Prometheus pod:
-
- ```plaintext
- gitlab-managed-apps prometheus-prometheus-server-55b4bd64c9-dpc6b 2/2 Running 0 71d
- ```
-
-1. Run a `kubectl port-forward` command. In the following example, `9090` is the
- Prometheus server's listening port:
-
- ```shell
- kubectl port-forward prometheus-prometheus-server-55b4bd64c9-dpc6b 9090:9090 -n gitlab-managed-apps
- ```
-
- The `port-forward` command forwards all requests sent to your system's `9090` port
- to the `9090` port of the Prometheus pod. If the `9090` port on your system is used
- by another application, you can change the port number before the colon to your
- desired port. For example, to forward port `8080` of your local system, change the
- command to:
-
- ```shell
- kubectl port-forward prometheus-prometheus-server-55b4bd64c9-dpc6b 8080:9090 -n gitlab-managed-apps
- ```
-
-1. Open `localhost:9090` in your browser to display the Prometheus user interface.
-
-## Script access to Prometheus
-
-You can script the access to Prometheus, extracting the name of the pod automatically like this:
-
-```shell
-POD_INFORMATION=$(kubectl get pods -n gitlab-managed-apps | grep 'prometheus-prometheus-server')
-POD_NAME=$(echo $POD_INFORMATION | awk '{print $1;}')
-kubectl port-forward $POD_NAME 9090:9090 -n gitlab-managed-apps
-```
+This document was moved to [another location](../user/project/integrations/prometheus.md).
diff --git a/doc/development/pry_debugging.md b/doc/development/pry_debugging.md
index 0558a0a515a..7f9a49d4d50 100644
--- a/doc/development/pry_debugging.md
+++ b/doc/development/pry_debugging.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Pry debugging
## Invoking pry debugging
diff --git a/doc/development/python_guide/index.md b/doc/development/python_guide/index.md
index fae2e495417..22a01c3b877 100644
--- a/doc/development/python_guide/index.md
+++ b/doc/development/python_guide/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Python Development Guidelines
GitLab requires Python as a dependency for [reStructuredText](https://docutils.sourceforge.io/rst.html)
diff --git a/doc/development/query_count_limits.md b/doc/development/query_count_limits.md
index b3ecaf30d8a..07dcb6c7d90 100644
--- a/doc/development/query_count_limits.md
+++ b/doc/development/query_count_limits.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Query Count Limits
Each controller or API endpoint is allowed to execute up to 100 SQL queries and
diff --git a/doc/development/query_recorder.md b/doc/development/query_recorder.md
index ef9a3c657aa..4a02af3348c 100644
--- a/doc/development/query_recorder.md
+++ b/doc/development/query_recorder.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# QueryRecorder
QueryRecorder is a tool for detecting the [N+1 queries problem](https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations) from tests.
@@ -20,17 +26,17 @@ end
As an example you might create 5 issues in between counts, which would cause the query count to increase by 5 if an N+1 problem exists.
-NOTE: **Note:**
In some cases the query count might change slightly between runs for unrelated reasons. In this case you might need to test `exceed_query_limit(control_count + acceptable_change)`, but this should be avoided if possible.
## Cached queries
-By default, QueryRecorder will ignore cached queries in the count. However, it may be better to count
-all queries to avoid introducing an N+1 query that may be masked by the statement cache. To do this,
-pass the `skip_cached` variable to `QueryRecorder` and use the `exceed_all_query_limit` matcher:
+By default, QueryRecorder will ignore [cached queries](merge_request_performance_guidelines.md#cached-queries) in the count. However, it may be better to count
+all queries to avoid introducing an N+1 query that may be masked by the statement cache.
+To do this, this requires the `:use_sql_query_cache` flag to be set.
+You should pass the `skip_cached` variable to `QueryRecorder` and use the `exceed_all_query_limit` matcher:
```ruby
-it "avoids N+1 database queries" do
+it "avoids N+1 database queries", :use_sql_query_cache do
control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { visit_some_page }.count
create_list(:issue, 5)
expect { visit_some_page }.not_to exceed_all_query_limit(control_count)
@@ -118,4 +124,5 @@ There are multiple ways to find the source of queries.
- [Bullet](profiling.md#bullet) For finding `N+1` query problems
- [Performance guidelines](performance.md)
-- [Merge request performance guidelines](merge_request_performance_guidelines.md#query-counts)
+- [Merge request performance guidelines - Query counts](merge_request_performance_guidelines.md#query-counts)
+- [Merge request performance guidelines - Cached queries](merge_request_performance_guidelines.md#cached-queries)
diff --git a/doc/development/rails_initializers.md b/doc/development/rails_initializers.md
index 6473baf58d4..bc0ac963f3f 100644
--- a/doc/development/rails_initializers.md
+++ b/doc/development/rails_initializers.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Rails initializers
By default, Rails loads Zeitwerk after the initializers in `config/initializers` are loaded.
diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md
index fd5dee69fc3..2dca747425c 100644
--- a/doc/development/rake_tasks.md
+++ b/doc/development/rake_tasks.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Rake tasks for developers
Rake tasks are available for developers and others contributing to GitLab.
@@ -12,7 +18,7 @@ bundle exec rake setup
The `setup` task is an alias for `gitlab:setup`.
This tasks calls `db:reset` to create the database, and calls `db:seed_fu` to seed the database.
-Note: `db:setup` calls `db:seed` but this does nothing.
+`db:setup` calls `db:seed` but this does nothing.
### Environment variables
diff --git a/doc/development/reactive_caching.md b/doc/development/reactive_caching.md
index cf125c46565..106a9b5de31 100644
--- a/doc/development/reactive_caching.md
+++ b/doc/development/reactive_caching.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# `ReactiveCaching`
> This doc refers to <https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/concerns/reactive_caching.rb>.
diff --git a/doc/development/redis.md b/doc/development/redis.md
index a0ae84beb8d..7ee8afda36a 100644
--- a/doc/development/redis.md
+++ b/doc/development/redis.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Redis guidelines
GitLab uses [Redis](https://redis.io) for the following distinct purposes:
diff --git a/doc/development/refactoring_guide/index.md b/doc/development/refactoring_guide/index.md
index a9ff9556aed..17deffb4cb2 100644
--- a/doc/development/refactoring_guide/index.md
+++ b/doc/development/refactoring_guide/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Refactoring guide
This document is a collection of techniques and best practices to consider while performing a refactor.
diff --git a/doc/development/reference_processing.md b/doc/development/reference_processing.md
index cf587043cae..07833c0d302 100644
--- a/doc/development/reference_processing.md
+++ b/doc/development/reference_processing.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
description: 'An introduction to reference parsers and reference filters, and a guide to their implementation.'
---
@@ -10,7 +13,6 @@ abstractions in the `Banzai` pipeline: `ReferenceFilter` and `ReferenceParser`.
This page explains what these are, how they are used, and how you would
implement a new filter/parser pair.
-NOTE: **Note:**
Each `ReferenceFilter` must have a corresponding `ReferenceParser`.
It is possible to share reference parsers between filters - if two filters find
@@ -39,7 +41,7 @@ For example, the class
is responsible for handling references to issues, such as
`gitlab-org/gitlab#123` and `https://gitlab.com/gitlab-org/gitlab/-/issues/200048`.
-All reference filters are instances of [`HTML::Pipeline::Filter`](https://www.rubydoc.info/github/jch/html-pipeline/v1.11.0/HTML/Pipeline/Filter),
+All reference filters are instances of [`HTML::Pipeline::Filter`](https://www.rubydoc.info/github/jch/html-pipeline/HTML/Pipeline/Filter),
and inherit (often indirectly) from [`Banzai::Filter::ReferenceFilter`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/banzai/filter/reference_filter.rb).
`HTML::Pipeline::Filter` has a simple interface consisting of `#call`, a void
@@ -196,6 +198,5 @@ In practice, all reference parsers inherit from [`BaseParser`](https://gitlab.co
- `#references_relation` an active record relation for objects by ID.
- `#nodes_user_can_reference(user, nodes)` to filter nodes directly.
-NOTE: **Note:**
A failure to implement this class for each reference type means that the
application will raise exceptions during Markdown processing.
diff --git a/doc/development/renaming_features.md b/doc/development/renaming_features.md
index daf437027db..02d1851dbfe 100644
--- a/doc/development/renaming_features.md
+++ b/doc/development/renaming_features.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Renaming features
Sometimes the business asks to change the name of a feature. Broadly speaking, there are 2 approaches to that task. They basically trade between immediate effort and future complexity/bug risk:
diff --git a/doc/development/repository_mirroring.md b/doc/development/repository_mirroring.md
index fe6db987471..02d1499ca35 100644
--- a/doc/development/repository_mirroring.md
+++ b/doc/development/repository_mirroring.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Repository mirroring
## Deep Dive
diff --git a/doc/development/reusing_abstractions.md b/doc/development/reusing_abstractions.md
index 8711bac69e0..77534eea076 100644
--- a/doc/development/reusing_abstractions.md
+++ b/doc/development/reusing_abstractions.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Guidelines for reusing abstractions
As GitLab has grown, different patterns emerged across the codebase. Service
diff --git a/doc/development/rolling_out_changes_using_feature_flags.md b/doc/development/rolling_out_changes_using_feature_flags.md
index 6bad91d6287..cff88388ba0 100644
--- a/doc/development/rolling_out_changes_using_feature_flags.md
+++ b/doc/development/rolling_out_changes_using_feature_flags.md
@@ -1 +1,5 @@
+---
+redirect_to: 'feature_flags/index.md'
+---
+
This document was moved to [another location](feature_flags/index.md).
diff --git a/doc/development/routing.md b/doc/development/routing.md
index e164431853f..cbae2b38427 100644
--- a/doc/development/routing.md
+++ b/doc/development/routing.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Routing
The GitLab backend is written primarily with Rails so it uses [Rails
diff --git a/doc/development/scalability.md b/doc/development/scalability.md
index 0fb54d89913..73f7c5e0915 100644
--- a/doc/development/scalability.md
+++ b/doc/development/scalability.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab scalability
This section describes the current architecture of GitLab as it relates to
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index e35bda82aaa..ebab0e59cc3 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -219,11 +219,11 @@ the mitigations for a new feature.
- [More details](https://dev.gitlab.org/gitlab/gitlabhq/-/merge_requests/2530/diffs)
-#### Feature-specific Mitigations
+#### Feature-specific mitigations
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.
+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.
- Block connections to all localhost addresses
- `127.0.0.1/8` (IPv4 - note the subnet mask)
@@ -269,7 +269,7 @@ When user submitted data is included in responses to end users, which is just ab
### Mitigation
-In most situations, a two-step solution can be utilized: input validation and output encoding in the appropriate context.
+In most situations, a two-step solution can be used: input validation and output encoding in the appropriate context.
#### Input validation
@@ -311,6 +311,7 @@ Specifically, the following options are dangerous because they mark strings as t
|----------------------|-------------------------------|
| HAML templates | `html_safe`, `raw`, `!=` |
| Embedded Ruby (ERB) | `html_safe`, `raw`, `<%== %>` |
+
In case you want to sanitize user-controlled values against XSS vulnerabilities, you can use
[`ActionView::Helpers::SanitizeHelper`](https://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html).
Calling `link_to` and `redirect_to` with user-controlled parameters can also lead to cross-site scripting.
@@ -328,6 +329,7 @@ References:
- When updating the content of an HTML element using JavaScript, mark user-controlled values as `textContent` or `nodeValue` instead of `innerHTML`.
- Avoid using `v-html` with user-controlled data, use [`v-safe-html`](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/directives-safe-html-directive--default) instead.
+- Render unsafe or unsanitized content using [`dompurify`](fe_guide/security.md#sanitize-html-output).
- Consider using [`gl-sprintf`](../../ee/development/i18n/externalization.md#interpolation) to interpolate translated strings securely.
- Avoid `__()` with translations that contain user-controlled values.
- When working with `postMessage`, ensure the `origin` of the message is allowlisted.
@@ -428,6 +430,132 @@ The Path Traversal check can also be used to forbid any absolute path:
requires :file_path, type: String, file_path: true
```
-NOTE: **Note:**
Absolute paths are not allowed by default. If allowing an absolute path is required, you
-need to provide an array of paths to the parameter `allowlist`.
+need to provide an array of paths to the parameter `allowlist`.
+
+## OS command injection guidelines
+
+Command injection is an issue in which an attacker is able to execute arbitrary commands on the host
+operating system through a vulnerable application. Such attacks don't always provide feedback to a
+user, but the attacker can use simple commands like `curl` to obtain an answer.
+
+### Impact
+
+The impact of command injection greatly depends on the user context running the commands, as well as
+how data is validated and sanitized. It can vary from low impact because the user running the
+injected commands has limited rights, to critical impact if running as the root user.
+
+Potential impacts include:
+
+- Execution of arbitrary commands on the host machine.
+- Unauthorized access to sensitive data, including passwords and tokens in secrets or configuration
+ files.
+- Exposure of sensitive system files on the host machine, such as `/etc/passwd/` or `/etc/shadow`.
+- Compromise of related systems and services gained through access to the host machine.
+
+You should be aware of and take steps to prevent command injection when working with user-controlled
+data that are used to run OS commands.
+
+### Mitigation and prevention
+
+To prevent OS command injections, user-supplied data shouldn't be used within OS commands. In cases
+where you can't avoid this:
+
+- Validate user-supplied data against an allowlist.
+- Ensure that user-supplied data only contains alphanumeric characters (and no syntax or whitespace
+ characters, for example).
+- Always use `--` to separate options from arguments.
+
+### Ruby
+
+Consider using `system("command", "arg0", "arg1", ...)` whenever you can. This prevents an attacker
+from concatenating commands.
+
+For more examples on how to use shell commands securely, consult
+[Guidelines for shell commands in the GitLab codebase](shell_commands.md).
+It contains various examples on how to securely call OS commands.
+
+### Go
+
+Go has built-in protections that usually prevent an attacker from successfully injecting OS commands.
+
+Consider the following example:
+
+```golang
+package main
+
+import (
+ "fmt"
+ "os/exec"
+)
+
+func main() {
+ cmd := exec.Command("echo", "1; cat /etc/passwd")
+ out, _ := cmd.Output()
+ fmt.Printf("%s", out)
+}
+```
+
+This echoes `"1; cat /etc/passwd"`.
+
+**Do not** use `sh`, as it bypasses internal protections:
+
+```golang
+out, _ = exec.Command("sh", "-c", "echo 1 | cat /etc/passwd").Output()
+```
+
+This outputs `1` followed by the content of `/etc/passwd`.
+
+## GitLab Internal Authorization
+
+### Introduction
+
+There are some cases where `users` passed in the code is actually referring to a `DeployToken`/`DeployKey` entity instead of a real `User`, because of the code below in **`/lib/api/api_guard.rb`**
+
+```ruby
+ def find_user_from_sources
+ strong_memoize(:find_user_from_sources) do
+ deploy_token_from_request ||
+ find_user_from_bearer_token ||
+ find_user_from_job_token ||
+ user_from_warden
+ end
+ end
+```
+
+### Past Vulnerable Code
+
+In some scenarios such as [this one](https://gitlab.com/gitlab-org/gitlab/-/issues/237795), user impersonation is possible because a `DeployToken` ID can be used in place of a `User` ID. This happened because there was no check on the line with `Gitlab::Auth::CurrentUserMode.bypass_session!(user.id)`. In this case, the `id` is actually a `DeployToken` ID instead of a `User` ID.
+
+```ruby
+ def find_current_user!
+ user = find_user_from_sources
+ return unless user
+
+ # Sessions are enforced to be unavailable for API calls, so ignore them for admin mode
+ Gitlab::Auth::CurrentUserMode.bypass_session!(user.id) if Feature.enabled?(:user_mode_in_session)
+
+ unless api_access_allowed?(user)
+ forbidden!(api_access_denied_message(user))
+ end
+```
+
+### Best Practices
+
+In order to prevent this from happening, it is recommended to use the method `user.is_a?(User)` to make sure it returns `true` when we are expecting to deal with a `User` object. This could prevent the ID confusion from the method `find_user_from_sources` mentioned above. Below code snippet shows the fixed code after applying the best practice to the vulnerable code above.
+
+```ruby
+ def find_current_user!
+ user = find_user_from_sources
+ return unless user
+
+ if user.is_a?(User) && Feature.enabled?(:user_mode_in_session)
+ # Sessions are enforced to be unavailable for API calls, so ignore them for admin mode
+ Gitlab::Auth::CurrentUserMode.bypass_session!(user.id)
+ end
+
+ unless api_access_allowed?(user)
+ forbidden!(api_access_denied_message(user))
+ end
+```
+ \ No newline at end of file
diff --git a/doc/development/serializing_data.md b/doc/development/serializing_data.md
index af791f5a4e0..83a75eef556 100644
--- a/doc/development/serializing_data.md
+++ b/doc/development/serializing_data.md
@@ -1,3 +1,9 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Serializing Data
**Summary:** don't store serialized data in the database, use separate columns
diff --git a/doc/development/service_measurement.md b/doc/development/service_measurement.md
index 24b16aac95b..571bbddb494 100644
--- a/doc/development/service_measurement.md
+++ b/doc/development/service_measurement.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab Developers Guide to service measurement
You can enable service measurement in order to debug any slow service's execution time, number of SQL calls, garbage collection stats, memory usage, etc.
@@ -16,7 +22,6 @@ The measuring module is a tool that allows to measure a service's execution, and
The measuring module will log these measurements into a structured log called [`service_measurement.log`](../administration/logs.md#service_measurementlog),
as a single entry for each service execution.
-NOTE: **Note:**
For GitLab.com, `service_measurement.log` is ingested in Elasticsearch and Kibana as part of our monitoring solution.
## How to use it
@@ -64,9 +69,8 @@ def extra_attributes_for_measurement
end
```
-NOTE: **Note:**
-Once the measurement module is injected in the service, it will be behind generic feature flag.
-In order to actually use it, you need to enable measuring for the desired service by enabling the feature flag.
+After the measurement module is injected in the service, it will be behind a generic feature flag.
+To actually use it, you need to enable measuring for the desired service by enabling the feature flag.
### Enabling measurement using feature flags
diff --git a/doc/development/session.md b/doc/development/session.md
index 971795d8816..a7f69f570c3 100644
--- a/doc/development/session.md
+++ b/doc/development/session.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Accessing session data
Session data in GitLab is stored in Redis and can be accessed in a variety of ways.
diff --git a/doc/development/sha1_as_binary.md b/doc/development/sha1_as_binary.md
index 6c4252ec634..e69ba149cde 100644
--- a/doc/development/sha1_as_binary.md
+++ b/doc/development/sha1_as_binary.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Storing SHA1 Hashes As Binary
Storing SHA1 hashes as strings is not very space efficient. A SHA1 as a string
diff --git a/doc/development/shared_files.md b/doc/development/shared_files.md
index fcd905b54a4..2c6b1222cfb 100644
--- a/doc/development/shared_files.md
+++ b/doc/development/shared_files.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Shared files
Historically, GitLab has been storing shared files in many different
diff --git a/doc/development/shell_commands.md b/doc/development/shell_commands.md
index b71fcbdc2ab..25113b4ac29 100644
--- a/doc/development/shell_commands.md
+++ b/doc/development/shell_commands.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Guidelines for shell commands in the GitLab codebase
This document contains guidelines for working with processes and files in the GitLab codebase.
diff --git a/doc/development/shell_scripting_guide/index.md b/doc/development/shell_scripting_guide/index.md
index 704b46c7efa..f447a0e0e72 100644
--- a/doc/development/shell_scripting_guide/index.md
+++ b/doc/development/shell_scripting_guide/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Shell scripting standards and style guidelines
GitLab consists of many various services and sub-projects. The majority of
diff --git a/doc/development/sidekiq_debugging.md b/doc/development/sidekiq_debugging.md
index b6a11dd813d..e0f74b39c9a 100644
--- a/doc/development/sidekiq_debugging.md
+++ b/doc/development/sidekiq_debugging.md
@@ -1,6 +1,5 @@
-# Sidekiq debugging
+---
+redirect_to: '../administration/troubleshooting/sidekiq.md'
+---
-## Log arguments to Sidekiq jobs
-
-This content has been moved to the
-[Troubleshooting Sidekiq docs](../administration/troubleshooting/sidekiq.md).
+This document was moved to [another location](../administration/troubleshooting/sidekiq.md).
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index 24570cfc07b..13ae39997bc 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Sidekiq Style Guide
This document outlines various guidelines that should be followed when adding or
@@ -21,7 +27,10 @@ After adding a new queue, run `bin/rake
gitlab:sidekiq:all_queues_yml:generate` to regenerate
`app/workers/all_queues.yml` or `ee/app/workers/all_queues.yml` so that
it can be picked up by
-[`sidekiq-cluster`](../administration/operations/extra_sidekiq_processes.md).
+[`sidekiq-cluster`](../administration/operations/extra_sidekiq_processes.md).
+Additionally, run
+`bin/rake gitlab:sidekiq:sidekiq_queues_yml:generate` to regenerate
+`config/sidekiq_queues.yml`.
## Queue Namespaces
@@ -112,7 +121,6 @@ As a general rule, a worker can be considered idempotent if:
A good example of that would be a cache expiration worker.
-NOTE: **Note:**
A job scheduled for an idempotent worker will automatically be
[deduplicated](#deduplication) when an unstarted job with the same
arguments is already in the queue.
@@ -152,7 +160,6 @@ end
It's encouraged to only have the `idempotent!` call in the top-most worker class, even if
the `perform` method is defined in another class or module.
-NOTE: **Note:**
If the worker class is not marked as idempotent, a cop will fail.
Consider skipping the cop if you're not confident your job can safely
run multiple times.
@@ -165,6 +172,22 @@ job. The work is skipped because the same work would be
done by the job that was scheduled first; by the time the second
job executed, the first job would do nothing.
+#### Strategies
+
+GitLab supports two deduplication strategies:
+
+- `until_executing`
+- `until_executed`
+
+More [deduplication strategies have been
+suggested](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/195). If
+you are implementing a worker that could benefit from a different
+strategy, please comment in the issue.
+
+##### Until Executing
+
+This strategy takes a lock when a job is added to the queue, and removes that lock before the job starts.
+
For example, `AuthorizedProjectsWorker` takes a user ID. When the
worker runs, it recalculates a user's authorizations. GitLab schedules
this job each time an action potentially changes a user's
@@ -173,10 +196,47 @@ same time, the second job can be skipped if the first job hasn't
begun, because when the first job runs, it creates the
authorizations for both projects.
+```ruby
+module AuthorizedProjectUpdate
+ class UserRefreshOverUserRangeWorker
+ include ApplicationWorker
+
+ deduplicate :until_executing
+ idempotent!
+
+ # ...
+ end
+end
+```
+
+##### Until Executed
+
+This strategy takes a lock when a job is added to the queue, and removes that lock after the job finishes.
+It can be used to prevent jobs from running simultaneously multiple times.
+
+```ruby
+module Ci
+ class BuildTraceChunkFlushWorker
+ include ApplicationWorker
+
+ deduplicate :until_executed
+ idempotent!
+
+ # ...
+ end
+end
+```
+
+#### Scheduling jobs in the future
+
GitLab doesn't skip jobs scheduled in the future, as we assume that
the state will have changed by the time the job is scheduled to
-execute. If you do want to deduplicate jobs scheduled in the future
-this can be specified on the worker as follows:
+execute. Deduplication of jobs scheduled in the feature is possible
+for both `until_executed` and `until_executing` strategies.
+
+If you do want to deduplicate jobs scheduled in the future,
+this can be specified on the worker by passing `including_scheduled: true` argument
+when defining deduplication strategy:
```ruby
module AuthorizedProjectUpdate
@@ -191,11 +251,7 @@ module AuthorizedProjectUpdate
end
```
-This strategy is called `until_executing`. More [deduplication
-strategies have been
-suggested](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/195). If
-you are implementing a worker that could benefit from a different
-strategy, please comment in the issue.
+#### Troubleshooting
If the automatic deduplication were to cause issues in certain
queues. This can be temporarily disabled by enabling a feature flag
@@ -429,9 +485,7 @@ class ExternalDependencyWorker
end
```
-NOTE: **Note:**
-Note that a job cannot be both high urgency and have
-external dependencies.
+A job cannot be both high urgency and have external dependencies.
## CPU-bound and Memory-bound Workers
@@ -645,8 +699,8 @@ blocks:
## Arguments logging
-When [`SIDEKIQ_LOG_ARGUMENTS`](../administration/troubleshooting/sidekiq.md#log-arguments-to-sidekiq-jobs)
-is enabled, Sidekiq job arguments will be logged.
+As of GitLab 13.6, Sidekiq job arguments will be logged by default, unless [`SIDEKIQ_LOG_ARGUMENTS`](../administration/troubleshooting/sidekiq.md#log-arguments-to-sidekiq-jobs)
+is disabled.
By default, the only arguments logged are numeric arguments, because
arguments of other types could contain sensitive information. To
@@ -767,7 +821,7 @@ This approach requires multiple releases.
##### Parameter hash
This approach will not require multiple releases if an existing worker already
-utilizes a parameter hash.
+uses a parameter hash.
1. Use a parameter hash in the worker to allow future flexibility.
diff --git a/doc/development/single_table_inheritance.md b/doc/development/single_table_inheritance.md
index 27c3c4f3199..51268092225 100644
--- a/doc/development/single_table_inheritance.md
+++ b/doc/development/single_table_inheritance.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Single Table Inheritance
**Summary:** don't use Single Table Inheritance (STI), use separate tables
diff --git a/doc/development/sql.md b/doc/development/sql.md
index 55a8192578b..bf405eab688 100644
--- a/doc/development/sql.md
+++ b/doc/development/sql.md
@@ -1,3 +1,9 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# SQL Query Guidelines
This document describes various guidelines to follow when writing SQL queries,
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index 2c1d70a005e..dabb18c1f75 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -361,7 +361,7 @@ Finished in 34.51 seconds (files took 0.76702 seconds to load)
1 example, 0 failures
```
-Note: `live_debug` only works on JavaScript enabled specs.
+`live_debug` only works on JavaScript enabled specs.
#### Run `:js` spec in a visible browser
@@ -584,9 +584,9 @@ this trait should be either fixed to not rely on Sidekiq processing jobs, or the
`:sidekiq_might_not_need_inline` trait should be updated to `:sidekiq_inline` if
the processing of background jobs is needed/expected.
-NOTE: **Note:**
-The usage of `perform_enqueued_jobs` is only useful for testing delayed mail
-deliveries since our Sidekiq workers aren't inheriting from `ApplicationJob` / `ActiveJob::Base`.
+The usage of `perform_enqueued_jobs` is useful only for testing delayed mail
+deliveries, because our Sidekiq workers aren't inheriting from `ApplicationJob`
+/ `ActiveJob::Base`.
#### DNS
diff --git a/doc/development/testing_guide/ci.md b/doc/development/testing_guide/ci.md
index 8091142410c..618f9010b4d 100644
--- a/doc/development/testing_guide/ci.md
+++ b/doc/development/testing_guide/ci.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab tests in the Continuous Integration (CI) context
## Test suite parallelization on the CI
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 a1883f44170..ef0bd9902e1 100644
--- a/doc/development/testing_guide/end_to_end/beginners_guide.md
+++ b/doc/development/testing_guide/end_to_end/beginners_guide.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Beginner's guide to writing end-to-end tests
In this tutorial, you will learn about the creation of end-to-end (_e2e_) tests
@@ -52,7 +58,6 @@ Check both [GitLab Community Edition](https://gitlab-org.gitlab.io/gitlab-foss/c
for previously-written tests for this feature. For analyzing the code coverage,
you must understand which application files implement specific features.
-NOTE: **Note:**
In this tutorial we're writing a login end-to-end test, even though it has been
sufficiently covered by lower-level testing, because it's the first step for most
end-to-end flows, and is easiest to understand.
@@ -68,7 +73,6 @@ under the stage.
![DevOps lifecycle by stages](img/gl-devops-lifecycle-by-stage-numbers_V12_10.png)
-NOTE: **Note:**
If the test is Enterprise Edition only, the test will be created in the `features/ee`
directory, but follow the same DevOps lifecycle format.
@@ -204,7 +208,6 @@ end
1. Check if the user avatar appears in the top navigation.
1. Check if the user avatar *does not* appear in the top navigation.
-NOTE: **Note:**
Behind the scenes, `be_signed_in` is a
[predicate matcher](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/built-in-matchers/predicate-matchers)
that [implements checking the user avatar](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/page/main/menu.rb#L74).
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 58bae749dc5..4d12a0f79cb 100644
--- a/doc/development/testing_guide/end_to_end/best_practices.md
+++ b/doc/development/testing_guide/end_to_end/best_practices.md
@@ -1,6 +1,11 @@
+---
+stage: none
+group: Development
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# End-to-end testing Best Practices
-NOTE: **Note:**
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
@@ -263,7 +268,7 @@ We don't run tests that require Administrator access against our Production envi
When you add a new test that requires Administrator access, apply the RSpec metadata `:requires_admin` so that the test will not be included in the test suites executed against Production and other environments on which we don't want to run those tests.
-Note: When running tests locally or configuring a pipeline, the environment variable `QA_CAN_TEST_ADMIN_FEATURES` can be set to `false` to skip tests that have the `:requires_admin` tag.
+When running tests locally or configuring a pipeline, the environment variable `QA_CAN_TEST_ADMIN_FEATURES` can be set to `false` to skip tests that have the `:requires_admin` tag.
## Prefer `Commit` resource over `ProjectPush`
@@ -288,7 +293,6 @@ Resource::Repository::ProjectPush.fabricate! do |push|
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.
@@ -321,39 +325,69 @@ In general, we use an `expect` statement to check that something _is_ as we expe
```ruby
Page::Project::Pipeline::Show.perform do |pipeline|
- expect(pipeline).to have_job("a_job")
+ expect(pipeline).to have_job('a_job')
end
```
-### Ensure `expect` checks for negation efficiently
+### Create negatable matchers to speed `expect` checks
However, sometimes we want to check that something is _not_ as we _don't_ want it to be. In other
-words, we want to make sure something is absent. In such a case we should use an appropriate
-predicate method that returns quickly, rather than waiting for a state that won't appear.
+words, we want to make sure something is absent. For unit tests and feature specs,
+we commonly use `not_to`
+because RSpec's built-in matchers are negatable, as are Capybara's, which means the following two statements are
+equivalent.
+
+```ruby
+except(page).not_to have_text('hidden')
+except(page).to have_no_text('hidden')
+```
+
+Unfortunately, that's not automatically the case for the predicate methods that we add to our
+[page objects](page_objects.md). We need to [create our own negatable matchers](https://relishapp.com/rspec/rspec-expectations/v/3-9/docs/custom-matchers/define-a-custom-matcher#matcher-with-separate-logic-for-expect().to-and-expect().not-to).
+
+The initial example uses the `have_job` matcher which is derived from the [`has_job?` predicate
+method of the `Page::Project::Pipeline::Show` page object](https://gitlab.com/gitlab-org/gitlab/-/blob/87864b3047c23b4308f59c27a3757045944af447/qa/qa/page/project/pipeline/show.rb#L53).
+To create a negatable matcher, we use `has_no_job?` for the negative case:
+
+```ruby
+RSpec::Matchers.define :have_job do |job_name|
+ match do |page_object|
+ page_object.has_job?(job_name)
+ end
+
+ match_when_negated do |page_object|
+ page_object.has_no_job?(job_name)
+ end
+end
+```
-It's most efficient to use a predicate method that returns immediately when there is no job, or waits
-until it disappears:
+And then the two `expect` statements in the following example are equivalent:
```ruby
-# Good
Page::Project::Pipeline::Show.perform do |pipeline|
- expect(pipeline).to have_no_job("a_job")
+ expect(pipeline).not_to have_job('a_job')
+ expect(pipeline).to have_no_job('a_job')
end
```
-### Problematic alternatives
+[See this merge request for a real example of adding a custom matcher](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46302).
-Alternatively, if we want to check that a job doesn't exist it might be tempting to use `not_to`:
+NOTE: **Note:**
+We need to create custom negatable matchers only for the predicate methods we've added to the test framework, and only if we're using `not_to`. If we use `to have_no_*` a negatable matcher is not necessary.
+
+### Why we need negatable matchers
+
+Consider the following code, but assume that we _don't_ have a custom negatable matcher for `have_job`.
```ruby
# Bad
Page::Project::Pipeline::Show.perform do |pipeline|
- expect(pipeline).not_to have_job("a_job")
+ expect(pipeline).not_to have_job('a_job')
end
```
-For this statement to pass, `have_job("a_job")` has to return `false` so that `not_to` can negate it.
-The problem is that `have_job("a_job")` waits up to ten seconds for `"a job"` to appear before
+For this statement to pass, `have_job('a_job')` has to return `false` so that `not_to` can negate it.
+The problem is that `have_job('a_job')` waits up to ten seconds for `'a job'` to appear before
returning `false`. Under the expected condition this test will take ten seconds longer than it needs to.
Instead, we could force no wait:
@@ -361,9 +395,13 @@ Instead, we could force no wait:
```ruby
# Not as bad but potentially flaky
Page::Project::Pipeline::Show.perform do |pipeline|
- expect(pipeline).not_to have_job("a_job", wait: 0)
+ expect(pipeline).not_to have_job('a_job', wait: 0)
end
```
-The problem is that if `"a_job"` is present and we're waiting for it to disappear, this statement
-will fail.
+The problem is that if `'a_job'` is present and we're waiting for it to disappear, this statement will fail.
+
+Neither problem is present if we create a custom negatable matcher because the `has_no_job?` predicate method
+would be used, which would wait only as long as necessary for the job to disappear.
+
+Lastly, negatable matchers are preferred over using matchers of the form `have_no_*` because it's a common and familiar practice to negate matchers using `not_to`. If we facilitate that practice by adding negatable matchers, we make it easier for subsequent test authors to write efficient tests.
diff --git a/doc/development/testing_guide/end_to_end/dynamic_element_validation.md b/doc/development/testing_guide/end_to_end/dynamic_element_validation.md
index 32b1c304a9a..871b3f80c18 100644
--- a/doc/development/testing_guide/end_to_end/dynamic_element_validation.md
+++ b/doc/development/testing_guide/end_to_end/dynamic_element_validation.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Dynamic Element Validation
We devised a solution to solve common test automation problems such as the dreaded `NoSuchElementException`.
diff --git a/doc/development/testing_guide/end_to_end/environment_selection.md b/doc/development/testing_guide/end_to_end/environment_selection.md
index 325f251b280..f5e3e99b79e 100644
--- a/doc/development/testing_guide/end_to_end/environment_selection.md
+++ b/doc/development/testing_guide/end_to_end/environment_selection.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Environment selection
Some tests are designed to be run against specific environments or [pipelines](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#scheduled-qa-test-pipelines).
@@ -42,14 +48,13 @@ RSpec.describe 'Area' do
it 'runs in dev environment', only: { tld: '.org', domain: 'gitlab', subdomain: 'dev' } do; end
it 'runs in prod and staging environments', only: { subdomain: /(staging.)?/, domain: 'gitlab' } {}
-
+
it 'runs only in nightly pipeline', only: { pipeline: :nightly } do; end
-
+
it 'runs in nightly and canary pipelines', only: { pipeline: [:nightly, :canary] } do; end
end
```
-NOTE: **Note:**
If the test has a `before` or `after`, you must add the `only` metadata
to the outer `RSpec.describe`.
diff --git a/doc/development/testing_guide/end_to_end/feature_flags.md b/doc/development/testing_guide/end_to_end/feature_flags.md
index e571774167d..2ff1c9f6dc3 100644
--- a/doc/development/testing_guide/end_to_end/feature_flags.md
+++ b/doc/development/testing_guide/end_to_end/feature_flags.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Testing with feature flags
To run a specific test with a feature flag enabled you can use the `QA::Runtime::Feature` class to
diff --git a/doc/development/testing_guide/end_to_end/flows.md b/doc/development/testing_guide/end_to_end/flows.md
index fb1d82914aa..291d8bd5319 100644
--- a/doc/development/testing_guide/end_to_end/flows.md
+++ b/doc/development/testing_guide/end_to_end/flows.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Flows in GitLab QA
Flows are frequently used sequences of actions. They are a higher level
diff --git a/doc/development/testing_guide/end_to_end/index.md b/doc/development/testing_guide/end_to_end/index.md
index f61eab5c8f3..1d144359ed8 100644
--- a/doc/development/testing_guide/end_to_end/index.md
+++ b/doc/development/testing_guide/end_to_end/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# End-to-end Testing
## What is end-to-end testing?
diff --git a/doc/development/testing_guide/end_to_end/page_objects.md b/doc/development/testing_guide/end_to_end/page_objects.md
index 6ce44b2d359..7eacaf4b08a 100644
--- a/doc/development/testing_guide/end_to_end/page_objects.md
+++ b/doc/development/testing_guide/end_to_end/page_objects.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Page objects in GitLab QA
In GitLab QA we are using a known pattern, called _Page Objects_.
diff --git a/doc/development/testing_guide/end_to_end/resources.md b/doc/development/testing_guide/end_to_end/resources.md
index b8a093c54c6..d73bae331d5 100644
--- a/doc/development/testing_guide/end_to_end/resources.md
+++ b/doc/development/testing_guide/end_to_end/resources.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Resource class in GitLab QA
Resources are primarily created using Browser UI steps, but can also
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 3a1303d9c0c..8e99cf18ea0 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
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# RSpec metadata for end-to-end tests
This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec-core/docs/metadata/user-defined-metadata)
@@ -10,7 +16,7 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| `: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`.* |
+| `: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 or pipelines. See [Environment selection](environment_selection.md) for more information. |
| `:orchestrated` | The GitLab instance under test may be [configured by `gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#orchestrated-tests) to be different to the default GitLab configuration, or `gitlab-qa` may launch additional services in separate Docker containers, or both. Tests tagged with `:orchestrated` are excluded when testing environments where we can't dynamically modify 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). |
@@ -19,3 +25,20 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| `:runner` | The test depends on and will set up a GitLab Runner instance, typically to run a pipeline. |
| `:skip_live_env` | The test will be excluded when run against live deployed environments such as Staging, Canary, and Production. |
| `:testcase` | The link to the test case issue in the [Quality Testcases project](https://gitlab.com/gitlab-org/quality/testcases/). |
+| `:mattermost` | The test requires a GitLab Mattermost service on the GitLab instance. |
+| `:ldap_no_server` | The test requires a GitLab instance to be configured to use LDAP. To be used with the `:orchestrated` tag. It does not spin up an LDAP server at orchestration time. Instead, it creates the LDAP server at runtime. |
+| `:ldap_no_tls` | The test requires a GitLab instance to be configured to use an external LDAP server with TLS not enabled. |
+| `:ldap_tls` | The test requires a GitLab instance to be configured to use an external LDAP server with TLS enabled. |
+| `:object_storage` | The test requires a GitLab instance to be configured to use multiple [object storage types](../../../administration/object_storage.md). Uses MinIO as the object storage server. |
+| `:smtp` | The test requires a GitLab instance to be configured to use an SMTP server. Tests SMTP notification email delivery from GitLab by using MailHog. |
+| `:group_saml` | The test requires a GitLab instance that has SAML SSO enabled at the group level. Interacts with an external SAML identity provider. Paired with the `:orchestrated` tag. |
+| `:instance_saml` | The test requires a GitLab instance that has SAML SSO enabled at the instance level. Interacts with an external SAML identity provider. Paired with the `:orchestrated` tag. |
+| `:skip_signup_disabled` | The test uses UI to sign up a new user and will be skipped in any environment that does not allow new user registration via the UI. |
+| `:smoke` | The test belongs to the test suite which verifies basic functionality of a GitLab instance.|
+| `:github` | The test requires a GitHub personal access token. |
+| `:repository_storage` | The test requires a GitLab instance to be configured to use multiple [repository storage paths](../../../administration/repository_storage_paths.md). Paired with the `:orchestrated` tag. |
+| `:geo` | The test requires two GitLab Geo instances - a primary and a secondary - to be spun up. |
+| `:relative_url` | The test requires a GitLab instance to be installed under a [relative URL](../../../install/relative_url.md). |
+| `:requires_git_protocol_v2` | The test requires that Git protocol version 2 is enabled on the server. It's assumed to be enabled by default but if not the test can be skipped by setting `QA_CAN_TEST_GIT_PROTOCOL_V2` to `false`. |
+| `:requires_praefect` | The test requires that the GitLab instance uses [Gitaly Cluster](../../../administration/gitaly/praefect.md) (a.k.a. Praefect) as the repository storage . It's assumed to be used by default but if not the test can be skipped by setting `QA_CAN_TEST_PRAEFECT` to `false`. |
+| `:packages` | The test requires a GitLab instance that has the [Package Registry](../../../administration/packages/#gitlab-package-registry-administration) enabled. |
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 658839fcf96..df4b833526c 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
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Running tests that require special setup
## Jenkins spec
@@ -232,7 +238,11 @@ run: ./services/tunnel_gitlab: (pid 2650) 10875s, normally down; run: log: (pid
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:
+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 sign in. Note that the Registry port and GDK port aren't
+the same. When configuring Auto DevOps in GDK, the `gdk reconfigure` command
+outputs the port of the Registry:
```shell
*********************************************
diff --git a/doc/development/testing_guide/end_to_end/style_guide.md b/doc/development/testing_guide/end_to_end/style_guide.md
index 645c2633831..e6c96bca93e 100644
--- a/doc/development/testing_guide/end_to_end/style_guide.md
+++ b/doc/development/testing_guide/end_to_end/style_guide.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Style guide for writing end-to-end tests
This document describes the conventions used at GitLab for writing End-to-end (E2E) tests using the GitLab QA project.
diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md
index 7aed908c4f6..47ed11d76a2 100644
--- a/doc/development/testing_guide/flaky_tests.md
+++ b/doc/development/testing_guide/flaky_tests.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Flaky tests
## What's a flaky test?
@@ -12,7 +18,13 @@ When a test frequently fails in `master`,
should be created.
If the test cannot be fixed in a timely fashion, there is an impact on the
productivity of all the developers, so it should be placed in quarantine by
-assigning the `:quarantine` metadata.
+assigning the `:quarantine` metadata with the issue URL.
+
+```ruby
+it 'should succeed', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/12345' do
+ expect(response).to have_gitlab_http_status(:ok)
+end
+```
This means it will be skipped unless run with `--tag quarantine`:
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index 730f8d5ad7d..28fe63f1fb4 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Frontend testing standards and style guidelines
There are two types of test suites you'll encounter while developing frontend code
@@ -24,7 +30,6 @@ We have started to migrate frontend tests to the [Jest](https://jestjs.io) testi
Jest tests can be found in `/spec/frontend` and `/ee/spec/frontend` in EE.
-NOTE: **Note:**
Most examples have a Jest and Karma example. See the Karma examples only as explanation to what's going on in the code, should you stumble over some use cases during your discovery. The Jest examples are the one you should follow.
## Karma test suite
@@ -110,6 +115,37 @@ describe('Component', () => {
Remember that the performance of each test depends on the environment.
+### Timout error due to async components
+
+If your component is fetching some other components asynchroneously based on some conditions, it might happen so that your Jest suite for this component will become flaky timing out from time to time.
+
+```javascript
+// ide.vue
+export default {
+ components: {
+ 'error-message': () => import('./error_message.vue'),
+ 'gl-button': () => import('@gitlab/ui/src/components/base/button/button.vue'),
+ ...
+};
+```
+
+To address this issue, you can "help" Jest by stubbing the async components so that Jest would not need to fetch those asynchroneously at the run-time.
+
+```javascript
+// ide_spec.js
+import { GlButton } from '@gitlab/ui';
+import ErrorMessage from '~/ide/components/error_message.vue';
+...
+return shallowMount(ide, {
+ ...
+ stubs: {
+ ErrorMessage,
+ GlButton,
+ ...
+ },
+})
+```
+
## What and how to test
Before jumping into more gritty details about Jest-specific workflows like mocks and spies, we should briefly cover what to test with Jest.
@@ -198,47 +234,33 @@ Following you'll find some general common practices you will find as part of our
When it comes to querying DOM elements in your tests, it is best to uniquely and semantically target
the element.
-Preferentially, this is done by targeting text the user actually sees using [DOM Testing Library](https://testing-library.com/docs/dom-testing-library/intro).
+Preferentially, this is done by targeting what the user actually sees using [DOM Testing Library](https://testing-library.com/docs/dom-testing-library/intro).
When selecting by text it is best to use [`getByRole` or `findByRole`](https://testing-library.com/docs/dom-testing-library/api-queries#byrole)
as these enforce accessibility best practices as well. The examples below demonstrate the order of preference.
-Sometimes this cannot be done feasibly. In these cases, adding test attributes to simplify the
-selectors might be the best option.
+When writing Vue component unit tests, it can be wise to query children by component, so that the unit test can focus on comprehensive value coverage
+rather than dealing with the complexity of a child component's behavior.
+
+Sometimes, neither of the above are feasible. In these cases, adding test attributes to simplify the selectors might be the best option. A list of
+possible selectors include:
- A semantic attribute like `name` (also verifies that `name` was setup properly)
- A `data-testid` attribute ([recommended by maintainers of `@vue/test-utils`](https://github.com/vuejs/vue-test-utils/issues/1498#issuecomment-610133465))
- a Vue `ref` (if using `@vue/test-utils`)
```javascript
-import { mount, shallowMount } from '@vue/test-utils'
import { getByRole, getByText } from '@testing-library/dom'
-let wrapper
-let el
-
-const createComponent = (mountFn = shallowMount) => {
- wrapper = mountFn(Component)
- el = wrapper.vm.$el // reference to the container element
-}
-
-beforeEach(() => {
- createComponent()
-})
-
-
+// In this example, `wrapper` is a `@vue/test-utils` wrapper returned from `mount` or `shallowMount`.
it('exists', () => {
- // Best
-
- // NOTE: both mount and shallowMount work as long as a DOM element is available
- // 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"
- getByText(el, 'Click Me')
- // Regex is also available
- getByText(el, /Click Me/i)
-
- // Good
+ // Best (especially for integration tests)
+ getByRole(wrapper.element, 'link', { name: /Click Me/i })
+ getByRole(wrapper.element, 'link', { name: 'Click Me' })
+ getByText(wrapper.element, 'Click Me')
+ getByText(wrapper.element, /Click Me/i)
+
+ // Good (especially for unit tests)
+ wrapper.find(FooComponent);
wrapper.find('input[name=foo]');
wrapper.find('[data-testid="foo"]');
wrapper.find({ ref: 'foo'});
@@ -249,14 +271,6 @@ it('exists', () => {
wrapper.find('.qa-foo-component');
wrapper.find('[data-qa-selector="foo"]');
});
-
-// Good
-it('exists', () => {
- wrapper.find(FooComponent);
- wrapper.find('input[name=foo]');
- wrapper.find('[data-testid="foo"]');
- wrapper.find({ ref: 'foo'});
-});
```
It is not recommended that you add `.js-*` classes just for testing purposes. Only do this if there are no other feasible options available.
@@ -327,7 +341,6 @@ it('tests a promise rejection', async () => {
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.
@@ -777,7 +790,7 @@ While you work on a test suite, you may want to run these specs in watch mode, s
# Watch and rerun all specs matching the name icon
yarn jest --watch icon
-# Watch and rerun one specifc file
+# Watch and rerun one specific file
yarn jest --watch path/to/spec/file.spec.js
```
@@ -917,6 +930,32 @@ it.each([
);
```
+**Note**: only use template literal block if pretty print is **not** needed for spec output. For example, empty strings, nested objects etc.
+
+For example, when testing the difference between an empty search string and a non-empty search string, the use of the array block syntax with the pretty print option would be preferred. That way the differences between an empty string e.g. `''` and a non-empty string e.g. `'search string'` would be visible in the spec output. Whereas with a template literal block, the empty string would be shown as a space, which could lead to a confusing developer experience
+
+```javascript
+// bad
+it.each`
+ searchTerm | expected
+ ${''} | ${{ issue: { users: { nodes: [] } } }}
+ ${'search term'} | ${{ issue: { other: { nested: [] } } }}
+`('when search term is $searchTerm, it returns $expected', ({ searchTerm, expected }) => {
+ expect(search(searchTerm)).toEqual(expected)
+});
+
+// good
+it.each([
+ ['', { issue: { users: { nodes: [] } } }],
+ ['search term', { issue: { other: { nested: [] } } }],
+])('when search term is %p, expect to return %p',
+ (searchTerm, expected) => {
+ expect(search(searchTerm)).toEqual(expected)
+ }
+);
+
+```
+
```javascript
// test suite with tagged template literal block
describe.each`
diff --git a/doc/development/testing_guide/index.md b/doc/development/testing_guide/index.md
index a61a700594c..840c8c9206c 100644
--- a/doc/development/testing_guide/index.md
+++ b/doc/development/testing_guide/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Testing standards and style guidelines
This document describes various guidelines and best practices for automated
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 61d3299cabf..5dcc7e7091e 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Review Apps
Review Apps are automatically deployed by [the
diff --git a/doc/development/testing_guide/smoke.md b/doc/development/testing_guide/smoke.md
index 5a144b43478..76484dd193b 100644
--- a/doc/development/testing_guide/smoke.md
+++ b/doc/development/testing_guide/smoke.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Smoke Tests
It is imperative in any testing suite that we have Smoke Tests. In short, smoke
diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md
index 88d7cf9ca08..d9e7edfa0c8 100644
--- a/doc/development/testing_guide/testing_levels.md
+++ b/doc/development/testing_guide/testing_levels.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Testing levels
![Testing priority triangle](img/testing_triangle.png)
diff --git a/doc/development/testing_guide/testing_migrations_guide.md b/doc/development/testing_guide/testing_migrations_guide.md
index a5bcb651d71..b944c7ed406 100644
--- a/doc/development/testing_guide/testing_migrations_guide.md
+++ b/doc/development/testing_guide/testing_migrations_guide.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
@@ -236,6 +239,5 @@ describe Gitlab::BackgroundMigration::ArchiveLegacyTraces, schema: 2018052915262
end
```
-NOTE: **Note:**
These tests do not run within a database transaction, as we use a deletion database
cleanup strategy. Do not depend on a transaction being present.
diff --git a/doc/development/testing_guide/testing_rake_tasks.md b/doc/development/testing_guide/testing_rake_tasks.md
index db8ca87e9f8..384739d1adb 100644
--- a/doc/development/testing_guide/testing_rake_tasks.md
+++ b/doc/development/testing_guide/testing_rake_tasks.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Testing Rake tasks
To make testing Rake tasks a little easier, there is a helper that can be included
diff --git a/doc/development/understanding_explain_plans.md b/doc/development/understanding_explain_plans.md
index 797dfc676eb..896b34a4ab4 100644
--- a/doc/development/understanding_explain_plans.md
+++ b/doc/development/understanding_explain_plans.md
@@ -1,3 +1,9 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Understanding EXPLAIN plans
PostgreSQL allows you to obtain query plans using the `EXPLAIN` command. This
@@ -428,6 +434,17 @@ If there aren't any, check if you can perhaps slightly change an existing one to
fit both the existing and new queries. Only add a new index if none of the
existing indexes can be used in any way.
+When comparing execution plans, don't take timing as the only important metric.
+Good timing is the main goal of any optimization, but it can be too volatile to
+be used for comparison (for example, it depends a lot on the state of cache).
+When optimizing a query, we usually need to reduce the amount of data we're
+dealing with. Indexes are the way to work with fewer pages (buffers) to get the
+result, so, during optimization, look at the number of buffers used (read and hit),
+and work on reducing these numbers. Reduced timing will be the consequence of reduced
+buffer numbers. [#database-lab](#database-lab) guarantees that the plan is structurally
+identical to production (and overall number of buffers is the same as on production),
+but difference in cache state and I/O speed may lead to different timings.
+
## Queries that can't be optimised
Now that we have seen how to optimise a query, let's look at another query that
diff --git a/doc/development/uploads.md b/doc/development/uploads.md
index ee94553c200..0307ab76cd1 100644
--- a/doc/development/uploads.md
+++ b/doc/development/uploads.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Uploads development documentation
[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) has special rules for handling uploads.
@@ -214,7 +220,6 @@ In this setup, an extra Rails route must be implemented in order to handle autho
and [its routes](https://gitlab.com/gitlab-org/gitlab/blob/cc723071ad337573e0360a879cbf99bc4fb7adb9/config/routes/git_http.rb#L31-32).
- [API endpoints for uploading packages](packages.md#file-uploads).
-Note: **Note:**
This will fallback to _disk buffered upload_ when `direct_upload` is disabled inside the [object storage setting](../administration/uploads.md#object-storage-settings).
The answer to the `/authorize` call will only contain a file system path.
@@ -273,8 +278,10 @@ 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.
+1. GraphQL API: uploads handled by a GraphQL resolve function.
+
+CAUTION: **Warning:**
+GraphQL uploads do not support [direct upload](#direct-upload) yet. Depending on the use case, the feature may not work on installations without NFS (like GitLab.com or Kubernetes installations). Uploading to object storage inside the GraphQL resolve function may result in timeout errors. For more details please follow [issue #280819](https://gitlab.com/gitlab-org/gitlab/-/issues/280819).
### Update Workhorse for the new route
diff --git a/doc/development/utilities.md b/doc/development/utilities.md
index 52151d37038..aca14507fcd 100644
--- a/doc/development/utilities.md
+++ b/doc/development/utilities.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab utilities
We have developed a number of utilities to help ease development:
diff --git a/doc/development/value_stream_analytics.md b/doc/development/value_stream_analytics.md
index 70b16cc1739..4560a115562 100644
--- a/doc/development/value_stream_analytics.md
+++ b/doc/development/value_stream_analytics.md
@@ -1,3 +1,9 @@
+---
+stage: Manage
+group: Optimize
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Value Stream Analytics development guide
Value stream analytics calculates the time between two arbitrary events recorded on domain objects and provides aggregated statistics about the duration.
@@ -53,8 +59,8 @@ def timestamp_projection
end
```
-NOTE: **Note:**
-More complex expressions are also possible (e.g. using `COALESCE`). Look at the existing event classes for examples.
+More complex expressions are also possible (for example, using `COALESCE`).
+Review the existing event classes for examples.
In some cases, defining the `timestamp_projection` method is not enough. The calculation query should know which table contains the timestamp expression. Each `Event` class is responsible for making modifications to the calculation query to make the `timestamp_projection` work. This usually means joining an additional table.
diff --git a/doc/development/verifying_database_capabilities.md b/doc/development/verifying_database_capabilities.md
index f6c78e51299..fe60ec11bce 100644
--- a/doc/development/verifying_database_capabilities.md
+++ b/doc/development/verifying_database_capabilities.md
@@ -1,3 +1,9 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Verifying Database Capabilities
Sometimes certain bits of code may only work on a certain database
diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md
index 9063fb867e2..18a2e17967a 100644
--- a/doc/development/what_requires_downtime.md
+++ b/doc/development/what_requires_downtime.md
@@ -1,3 +1,9 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# What requires downtime?
When working with a database certain operations can be performed without taking
@@ -88,6 +94,8 @@ renaming. For example
class RenameUsersUpdatedAtToUpdatedAtTimestamp < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
+ DOWNTIME = false
+
disable_ddl_transaction!
def up
@@ -100,13 +108,12 @@ class RenameUsersUpdatedAtToUpdatedAtTimestamp < ActiveRecord::Migration[4.2]
end
```
-This will take care of renaming the column, ensuring data stays in sync, copying
-over indexes and foreign keys, etc.
+This will take care of renaming the column, ensuring data stays in sync, and
+copying over indexes and foreign keys.
-NOTE: **Note:**
-If a column contains 1 or more indexes that do not contain the name of
-the original column, the above procedure will fail. In this case you will first
-need to rename these indexes.
+If a column contains one or more indexes that don't contain the name of the
+original column, the previously described procedure will fail. In that case,
+you'll first need to rename these indexes.
### Step 2: Add A Post-Deployment Migration
@@ -131,7 +138,6 @@ class CleanupUsersUpdatedAtRename < ActiveRecord::Migration[4.2]
end
```
-NOTE: **Note:**
If you're renaming a [large table](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3), please carefully consider the state when the first migration has run but the second cleanup migration hasn't been run yet.
With [Canary](https://gitlab.com/gitlab-com/gl-infra/readiness/-/tree/master/library/canary/) it is possible that the system runs in this state for a significant amount of time.
@@ -142,7 +148,7 @@ done without requiring downtime. However, this does require that any application
changes are deployed _first_. Thus, changing the constraints of a column should
happen in a post-deployment migration.
-NOTE: Avoid using `change_column` as it produces an inefficient query because it re-defines
+Avoid using `change_column` as it produces an inefficient query because it re-defines
the whole column type.
You can check the following guides for each specific use case:
diff --git a/doc/development/wikis.md b/doc/development/wikis.md
index 9a436762645..f8bcaac2ec0 100644
--- a/doc/development/wikis.md
+++ b/doc/development/wikis.md
@@ -1,8 +1,8 @@
---
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"
+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
description: "GitLab's development guidelines for Wikis"
---
diff --git a/doc/development/windows.md b/doc/development/windows.md
index 3301e4f7c8f..2ca99508746 100644
--- a/doc/development/windows.md
+++ b/doc/development/windows.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference, howto
---
diff --git a/doc/downgrade_ee_to_ce/README.md b/doc/downgrade_ee_to_ce/README.md
index cba21668816..2561ee875d2 100644
--- a/doc/downgrade_ee_to_ce/README.md
+++ b/doc/downgrade_ee_to_ce/README.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Downgrading from EE to CE
If you ever decide to downgrade your Enterprise Edition back to the Community
diff --git a/doc/gitlab-basics/command-line-commands.md b/doc/gitlab-basics/command-line-commands.md
index e259aeef37b..1933b432138 100644
--- a/doc/gitlab-basics/command-line-commands.md
+++ b/doc/gitlab-basics/command-line-commands.md
@@ -7,14 +7,14 @@ type: howto, reference
# Edit files through the command line
-When [working with Git from the command line](start-using-git.md), you will need to
+When [working with Git from the command line](start-using-git.md), you need to
use more than just the Git commands. There are several basic commands that you should
learn, in order to make full use of the command line.
## Start working on your project
To work on a Git project locally (from your own computer), with the command line,
-first you will need to [clone (copy) it](start-using-git.md#clone-a-repository) to
+first you need to [clone (copy) it](start-using-git.md#clone-a-repository) to
your computer.
## Working with files on the command line
@@ -57,16 +57,16 @@ nano README.md
### Remove a file or directory
-It is easy to delete (remove) a file or directory, but be careful:
+It's easy to delete (remove) a file or directory, but be careful:
-DANGER: **Danger:**
+DANGER: **Warning:**
This will **permanently** delete a file.
```shell
rm NAME-OF-FILE
```
-DANGER: **Danger:**
+DANGER: **Warning:**
This will **permanently** delete a directory and **all** of its contents.
```shell
@@ -96,7 +96,7 @@ for example) . Execute the same full command with:
Not all commands can be executed from a basic user account on a computer, you may
need administrator's rights to execute commands that affect the system, or try to access
protected data, for example. You can use `sudo` to execute these commands, but you
-will likely be asked for an administrator password.
+might be asked for an administrator password.
```shell
sudo RESTRICTED-COMMAND
@@ -108,8 +108,8 @@ damage to your data or system.
## Sample Git taskflow
-If you are completely new to Git, looking through some [sample taskflows](https://rogerdudler.github.io/git-guide/)
-will help you understand the best practices for using these commands as you work.
+If you're completely new to Git, looking through some [sample taskflows](https://rogerdudler.github.io/git-guide/)
+may help you understand the best practices for using these commands as you work.
<!-- ## Troubleshooting
diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md
index 616bb752694..415edce0d7d 100644
--- a/doc/gitlab-basics/create-project.md
+++ b/doc/gitlab-basics/create-project.md
@@ -128,10 +128,10 @@ To use a custom project template on the **New project** page:
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26388) in GitLab 10.5.
-When you create a new repository locally, instead of manually creating a new project in GitLab
+When you create a new repository locally, instead of manually creating a new project in GitLab
and then [cloning the repository](start-using-git.md#clone-a-repository)
locally, you can directly push it to GitLab to create the new project, all without leaving
-your terminal. If you have access rights to the associated namespace, GitLab
+your terminal. If you have access rights to the associated namespace, GitLab
automatically creates a new project under that GitLab namespace with its visibility
set to Private by default (you can later change it in the [project's settings](../public_access/public_access.md#how-to-change-project-visibility)).
diff --git a/doc/gitlab-basics/img/fork_choose_namespace.png b/doc/gitlab-basics/img/fork_choose_namespace.png
deleted file mode 100644
index 4c50276d5ad..00000000000
--- a/doc/gitlab-basics/img/fork_choose_namespace.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/img/fork_new.png b/doc/gitlab-basics/img/fork_new.png
deleted file mode 100644
index 7bbc3d8fbae..00000000000
--- a/doc/gitlab-basics/img/fork_new.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/img/merge_request_page.png b/doc/gitlab-basics/img/merge_request_page.png
deleted file mode 100644
index f6087294e22..00000000000
--- a/doc/gitlab-basics/img/merge_request_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/img/merge_request_select_branch.png b/doc/gitlab-basics/img/merge_request_select_branch.png
deleted file mode 100644
index b1dec975f9b..00000000000
--- a/doc/gitlab-basics/img/merge_request_select_branch.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/img/project_clone_url.png b/doc/gitlab-basics/img/project_clone_url.png
deleted file mode 100644
index bdd7d011db3..00000000000
--- a/doc/gitlab-basics/img/project_clone_url.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
index 93ac17d823b..a1774ddb770 100644
--- a/doc/install/aws/index.md
+++ b/doc/install/aws/index.md
@@ -312,7 +312,7 @@ We need a security group for our database that will allow inbound traffic from t
### Create the database
-DANGER: **Danger:**
+DANGER: **Warning:**
Avoid using burstable instances (t class instances) for the database as this could lead to performance issues due to CPU credits running out during sustained periods of high load.
Now, it's time to create the database:
@@ -349,6 +349,10 @@ Now that the database is created, let's move on to setting up Redis with ElastiC
ElastiCache is an in-memory hosted caching solution. Redis maintains its own
persistence and is used to store session data, temporary cache information, and background job queues for the GitLab application.
+DANGER: **Warning:**
+GitLab recommends you use ElastiCache Redis version 5.0.x, because version 6.x contains
+a bug that [prevents Sidekiq from processing jobs](https://gitlab.com/gitlab-org/gitlab/-/issues/281683).
+
### Create a Redis Security Group
1. Navigate to the EC2 dashboard.
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
index b5e72a9b84a..9dc30ab2476 100644
--- a/doc/install/azure/index.md
+++ b/doc/install/azure/index.md
@@ -347,8 +347,8 @@ connect to it using SSH ([Secure Shell](https://en.wikipedia.org/wiki/Secure_She
If you're running Windows, you'll need to connect using [PuTTY](https://www.putty.org) or an equivalent Windows SSH client.
If you're running Linux or macOS, then you already have an SSH client installed.
-Remember that you will need to login with the username and password you specified
-[when you created](#basics) your Azure VM.
+Remember to sign in with the username and password you specified when you
+[created your Azure VM](#basics).
If you need to reset your VM password, read
[how to reset SSH credentials for a user on an Azure VM](https://docs.microsoft.com/en-us/azure/virtual-machines/troubleshooting/troubleshoot-ssh-connection).
@@ -375,20 +375,20 @@ read on [using PuTTY in Windows](https://mediatemple.net/community/products/dv/2
### Updating GitLab
-Once you've logged in via SSH, enter the following command to update GitLab to the latest
-version:
+After signing in by using SSH, enter the following command to update GitLab to
+the latest version:
```shell
sudo apt-get update && sudo apt-get install gitlab-ce
```
-This command will update GitLab and its associated components to the latest versions, so it will
-take a little time to complete. You'll see various update tasks being completed in your SSH
-terminal window:
+This command updates GitLab and its associated components to the latest versions,
+so it will take a little time to complete. You'll see various update tasks being
+completed in your SSH terminal window:
![GitLab updating](img/gitlab-ssh-update-in-progress.png)
-Once the update process has completed, you'll see a message like this:
+After the update process is complete, you'll see a message like this:
```plaintext
Upgrade complete! If your GitLab server is misbehaving try running
diff --git a/doc/install/digitaloceandocker.md b/doc/install/digitaloceandocker.md
index fe32b37a9ed..deb8a8cc6ca 100644
--- a/doc/install/digitaloceandocker.md
+++ b/doc/install/digitaloceandocker.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: howto
---
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 0adf09595e4..87e3cd1ea06 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -90,6 +90,8 @@ The GitLab installation consists of setting up the following components:
## 1. Packages and dependencies
+### sudo
+
`sudo` is not installed on Debian by default. Make sure your system is
up-to-date and install it.
@@ -110,6 +112,8 @@ sudo apt-get install -y vim
sudo update-alternatives --set editor /usr/bin/vim.basic
```
+### Build dependencies
+
Install the required packages (needed to compile Ruby and native extensions to Ruby gems):
```shell
@@ -129,69 +133,33 @@ If you want to use Kerberos for user authentication, install `libkrb5-dev`
sudo apt-get install libkrb5-dev
```
-Make sure you have the right version of Git installed:
-
-```shell
-# Install Git
-sudo apt-get install -y git-core
+### Git
-# Make sure Git is version 2.24.0 or higher (recommended version is 2.28.0)
-git --version
-```
+From GitLab 13.6, we recommend you use the [Git version provided by
+Gitaly](https://gitlab.com/gitlab-org/gitaly/-/issues/2729)
+that:
-Starting with GitLab 12.0, Git is required to be compiled with `libpcre2`.
-Find out if that's the case:
+- Is always at the version required by GitLab.
+- May contain custom patches required for proper operation.
```shell
-ldd $(command -v git) | grep pcre2
-```
-
-The output should contain `libpcre2-8.so.0`.
+# Install dependencies
+sudo apt-get install -y libcurl4-openssl-dev libexpat1-dev gettext libz-dev libssl-dev libpcre2-dev build-essential
-If the system packaged Git is too old or not compiled with `pcre2`, remove it:
+# Clone the Gitaly repository
+git clone https://gitlab.com/gitlab-org/gitaly.git -b <X-Y-stable> /tmp/gitaly
-```shell
-sudo apt-get remove git-core
+# Compile and install Git
+cd /tmp/gitaly
+sudo make git GIT_PREFIX=/usr/local
```
-On Ubuntu, install Git from [its official PPA](https://git-scm.com/download/linux):
+Replace `<X-Y-stable>` with the stable branch that matches the GitLab version you want to
+install. For example, if you want to install GitLab 13.6, use the branch name `13-6-stable`.
-```shell
-# run as root!
-add-apt-repository ppa:git-core/ppa
-apt update
-apt install git
-# repeat libpcre2 check as above
-```
+When editing `config/gitlab.yml` later, change the `git -> bin_path` to `/usr/local/bin/git`.
-On Debian, use the following compilation instructions:
-
-```shell
-# Install dependencies
-sudo apt-get install -y libcurl4-openssl-dev libexpat1-dev gettext libz-dev libssl-dev build-essential
-
-# Download and compile pcre2 from source
-curl --silent --show-error --location https://ftp.pcre.org/pub/pcre/pcre2-10.33.tar.gz --output pcre2.tar.gz
-tar -xzf pcre2.tar.gz
-cd pcre2-10.33
-chmod +x configure
-./configure --prefix=/usr --enable-jit
-make
-sudo make install
-
-# Download and compile from source
-cd /tmp
-curl --remote-name --location --progress https://www.kernel.org/pub/software/scm/git/git-2.28.0.tar.gz
-echo 'f914c60a874d466c1e18467c864a910dd4ea22281ba6d4d58077cb0c3f115170 git-2.28.0.tar.gz' | shasum -a256 -c - && tar -xzf git-2.28.0.tar.gz
-cd git-2.28.0/
-./configure --with-libpcre
-make prefix=/usr/local all
-
-# Install into /usr/local/bin
-sudo make prefix=/usr/local install
-
-# When editing config/gitlab.yml later, change the git -> bin_path to /usr/local/bin/git
-```
+### GraphicsMagick
For the [Custom Favicon](../user/admin_area/appearance.md#favicon) to work, GraphicsMagick
needs to be installed.
@@ -200,6 +168,8 @@ needs to be installed.
sudo apt-get install -y graphicsmagick
```
+### Mail server
+
In order to receive mail notifications, make sure to install a mail server.
By default, Debian is shipped with `exim4` but this
[has problems](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/12754) while
@@ -212,6 +182,8 @@ sudo apt-get install -y postfix
Then select 'Internet Site' and press enter to confirm the hostname.
+### Exiftool
+
[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse#dependencies)
requires `exiftool` to remove EXIF data from uploaded images.
@@ -243,9 +215,9 @@ Download Ruby and compile it:
```shell
mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.6.tar.gz
-echo '2d78048e293817f38d4ede4ebc7873013e97bb0b ruby-2.6.6.tar.gz' | shasum -c - && tar xzf ruby-2.6.6.tar.gz
-cd ruby-2.6.6
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.2.tar.gz
+echo 'cb9731a17487e0ad84037490a6baf8bfa31a09e8 ruby-2.7.2.tar.gz' | shasum -c - && tar xzf ruby-2.7.2.tar.gz
+cd ruby-2.7.2
./configure --disable-install-rdoc
make
@@ -463,22 +435,22 @@ Clone Community Edition:
```shell
# Clone GitLab repository
-sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-foss.git -b X-Y-stable gitlab
+sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-foss.git -b <X-Y-stable> gitlab
```
Clone Enterprise Edition:
```shell
# Clone GitLab repository
-sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab.git -b X-Y-stable gitlab
+sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab.git -b <X-Y-stable> gitlab
```
-Make sure to replace `X-Y-stable` with the stable branch that matches the
+Make sure to replace `<X-Y-stable>` with the stable branch that matches the
version you want to install. For example, if you want to install 11.8 you would
use the branch name `11-8-stable`.
CAUTION: **Caution:**
-You can change `X-Y-stable` to `master` if you want the *bleeding edge* version, but never install `master` on a production server!
+You can change `<X-Y-stable>` to `master` if you want the *bleeding edge* version, but never install `master` on a production server!
### Configure It
diff --git a/doc/install/kubernetes/gitlab_chart.md b/doc/install/kubernetes/gitlab_chart.md
deleted file mode 100644
index d067c341be8..00000000000
--- a/doc/install/kubernetes/gitlab_chart.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com/charts/'
----
-
-This document was moved to [another location](https://docs.gitlab.com/charts/).
diff --git a/doc/install/kubernetes/gitlab_omnibus.md b/doc/install/kubernetes/gitlab_omnibus.md
deleted file mode 100644
index d067c341be8..00000000000
--- a/doc/install/kubernetes/gitlab_omnibus.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com/charts/'
----
-
-This document was moved to [another location](https://docs.gitlab.com/charts/).
diff --git a/doc/install/kubernetes/gitlab_runner_chart.md b/doc/install/kubernetes/gitlab_runner_chart.md
deleted file mode 100644
index be58c957166..00000000000
--- a/doc/install/kubernetes/gitlab_runner_chart.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com/runner/install/kubernetes.html'
----
-
-This document was moved to [another location](https://docs.gitlab.com/runner/install/kubernetes.html).
diff --git a/doc/install/kubernetes/index.md b/doc/install/kubernetes/index.md
deleted file mode 100644
index d067c341be8..00000000000
--- a/doc/install/kubernetes/index.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com/charts/'
----
-
-This document was moved to [another location](https://docs.gitlab.com/charts/).
diff --git a/doc/install/kubernetes/preparation/connect.md b/doc/install/kubernetes/preparation/connect.md
deleted file mode 100644
index 839461c982c..00000000000
--- a/doc/install/kubernetes/preparation/connect.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com/charts/installation/cloud/'
----
-
-This document was moved to [another location](https://docs.gitlab.com/charts/installation/cloud/).
diff --git a/doc/install/kubernetes/preparation/eks.md b/doc/install/kubernetes/preparation/eks.md
deleted file mode 100644
index c3f53c2f580..00000000000
--- a/doc/install/kubernetes/preparation/eks.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com/charts/installation/cloud/eks.html'
----
-
-This document was moved to [another location](https://docs.gitlab.com/charts/installation/cloud/eks.html).
diff --git a/doc/install/kubernetes/preparation/networking.md b/doc/install/kubernetes/preparation/networking.md
deleted file mode 100644
index 7e88bbd3cd1..00000000000
--- a/doc/install/kubernetes/preparation/networking.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com/charts/installation/deployment.html#networking-and-dns'
----
-
-This document was moved to [another location](https://docs.gitlab.com/charts/installation/deployment.html#networking-and-dns).
diff --git a/doc/install/kubernetes/preparation/rbac.md b/doc/install/kubernetes/preparation/rbac.md
deleted file mode 100644
index fc18b91641c..00000000000
--- a/doc/install/kubernetes/preparation/rbac.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com/charts/installation/deployment.html#rbac'
----
-
-This document was moved to [another location](https://docs.gitlab.com/charts/installation/deployment.html#rbac).
diff --git a/doc/install/kubernetes/preparation/tiller.md b/doc/install/kubernetes/preparation/tiller.md
deleted file mode 100644
index c1c7910703e..00000000000
--- a/doc/install/kubernetes/preparation/tiller.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com/charts/installation/tools.html'
----
-
-This document was moved to [another location](https://docs.gitlab.com/charts/installation/tools.html).
diff --git a/doc/install/kubernetes/preparation/tools_installation.md b/doc/install/kubernetes/preparation/tools_installation.md
deleted file mode 100644
index c1c7910703e..00000000000
--- a/doc/install/kubernetes/preparation/tools_installation.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com/charts/installation/tools.html'
----
-
-This document was moved to [another location](https://docs.gitlab.com/charts/installation/tools.html).
diff --git a/doc/install/openshift_and_gitlab/index.md b/doc/install/openshift_and_gitlab/index.md
index 7ac5aa6667a..2d7389a48a0 100644
--- a/doc/install/openshift_and_gitlab/index.md
+++ b/doc/install/openshift_and_gitlab/index.md
@@ -183,9 +183,9 @@ Using the all-in-one VM gives you the ability to test OpenShift whenever you
want. That means you get to play with it, shutdown the VM, and pick up where
you left off.
-Sometimes though, you may encounter some issues, like OpenShift not running
-when booting up the VM. The web UI may not responding or you may see issues
-when trying to login with `oc`, like:
+Occasionally, you may encounter issues, like OpenShift not running when booting
+up the VM. The web UI may not respond, or you may see issues when trying to sign
+in with `oc`, like:
```plaintext
The connection to the server 10.2.2.2:8443 was refused - did you specify the right host or port?
@@ -213,8 +213,7 @@ In that case, the OpenShift service might not be running, so in order to fix it:
systemctl status openshift -l
```
-Now you will be able to login using `oc` (like we did before) and visit the web
-console.
+You can now sign in by using `oc` (like we did before) and visit the web console.
## Deploy GitLab
@@ -497,14 +496,13 @@ oc adm policy add-scc-to-user anyuid system:serviceaccount:gitlab:gitlab-ce-user
## Conclusion
-By now, you should have an understanding of the basic OpenShift Origin concepts
-and a sense of how things work using the web console or the CLI.
+You should now have an understanding of the basic OpenShift Origin concepts, and
+a sense of how things work using the web console or the CLI.
-GitLab was hard to install in previous versions of OpenShift,
-but now that belongs to the past. Upload a template, create a project, add an
-application and you are done. You are ready to login to your new GitLab instance.
+Upload a template, create a project, add an application, and you're done. You're
+ready to sign in to your new GitLab instance.
-And remember that in this tutorial we just scratched the surface of what Origin
-is capable of. As always, you can refer to the detailed
-[documentation](https://docs.okd.io) to learn more about deploying your own OpenShift
-PaaS and managing your applications with the ease of containers.
+Remember that this tutorial doesn't address all that Origin is capable of. As
+always, refer to the detailed [documentation](https://docs.okd.io) to learn more
+about deploying your own OpenShift PaaS and managing your applications with
+containers.
diff --git a/doc/install/pivotal/index.md b/doc/install/pivotal/index.md
index 6a4b361c842..41a5ea82ea2 100644
--- a/doc/install/pivotal/index.md
+++ b/doc/install/pivotal/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab Pivotal Tile **(PREMIUM ONLY)**
CAUTION: **Discontinued:**
diff --git a/doc/install/postgresql_extensions.md b/doc/install/postgresql_extensions.md
index 9e5a1e3d627..6355806f067 100644
--- a/doc/install/postgresql_extensions.md
+++ b/doc/install/postgresql_extensions.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# 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 bc320bcd335..4a61831ff86 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -57,6 +57,10 @@ The minimum required Go version is 1.13.
### Git versions
+From GitLab 13.6:
+
+- Git 2.29.x and later is required.
+
From GitLab 13.1:
- Git 2.24.x and later is required.
@@ -144,6 +148,7 @@ GitLab version | Minimum PostgreSQL version
-|-
10.0 | 9.6
13.0 | 11
+13.6 | 12
You must also ensure the `pg_trgm` and `btree_gist` extensions are [loaded into every
GitLab database](postgresql_extensions.html).
diff --git a/doc/integration/README.md b/doc/integration/README.md
index c8ce367e99f..25e8c1a51c1 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/integration/akismet.md b/doc/integration/akismet.md
index 7cb8f8b70ce..d290ffa92b9 100644
--- a/doc/integration/akismet.md
+++ b/doc/integration/akismet.md
@@ -1,11 +1,17 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Akismet
-GitLab leverages [Akismet](https://akismet.com/) to protect against spam. Currently
+GitLab leverages [Akismet](https://akismet.com/) to protect against spam.
GitLab uses Akismet to prevent the creation of spam issues on public projects. Issues
-created via the web UI or the API can be submitted to Akismet for review.
+created through the web UI or the API can be submitted to Akismet for review.
-Detected spam will be rejected, and an entry in the "Spam Log" section in the
-Admin page will be created.
+Detected spam is rejected, and an entry is added in the **Spam Log** section of the
+Admin page.
Privacy note: GitLab submits the user's IP and user agent to Akismet.
@@ -17,11 +23,11 @@ In earlier GitLab versions, this only applied to API and non-project members.
To use Akismet:
-1. Go to the URL: <https://akismet.com/account/>
-1. Sign-in or create a new account.
-1. Click on **Show** to reveal the API key.
+1. Go to the [Akismet sign-in page](https://akismet.com/account/).
+1. Sign in or create a new account.
+1. Click **Show** to reveal the API key.
1. Go to **Admin Area > Settings > Reporting** (`/admin/application_settings/reporting`).
-1. Check the **Enable Akismet** checkbox.
+1. Select the **Enable Akismet** checkbox.
1. Fill in the API key from step 3.
1. Save the configuration.
@@ -29,23 +35,20 @@ To use Akismet:
## Training
-NOTE: **Note:**
-Training the Akismet filter is only available in GitLab 8.11 and later.
-
-As a way to better recognize between spam and ham, you can train the Akismet
+To better differentiate between spam and ham, you can train the Akismet
filter whenever there is a false positive or false negative.
When an entry is recognized as spam, it is rejected and added to the Spam Logs.
-From here you can review if they are really spam. If one of them is not really
+From here you can review if entries are really spam. If one of them is not really
spam, you can use the **Submit as ham** button to tell Akismet that it falsely
recognized an entry as spam.
![Screenshot of Spam Logs](img/spam_log.png)
-If an entry that is actually spam was not recognized as such, you will be able
-to also submit this to Akismet. The **Submit as spam** button will only appear
-to admin users.
+If an entry that is actually spam was not recognized as such, you can also submit
+this information to Akismet. The **Submit as spam** button is only displayed
+to administrator users.
![Screenshot of Issue](img/submit_issue.png)
-Training Akismet will help it to recognize spam more accurately in the future.
+Training Akismet helps it to recognize spam more accurately in the future.
diff --git a/doc/integration/auth0.md b/doc/integration/auth0.md
index d851b9f5dc7..339d97cb00f 100644
--- a/doc/integration/auth0.md
+++ b/doc/integration/auth0.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Auth0 OmniAuth Provider
To enable the Auth0 OmniAuth provider, you must create an Auth0 account, and an
@@ -6,31 +12,30 @@ application.
1. Sign in to the [Auth0 Console](https://auth0.com/auth/login). If you need to
create an account, you can do so at the same link.
-1. Select "New App/API".
+1. Select **New App/API**.
1. Provide the Application Name ('GitLab' works fine).
-1. Once created, you should see the Quick Start options. Disregard them and
- select 'Settings' above the Quick Start options.
+1. After creating, you should see the **Quick Start** options. Disregard them and
+ select **Settings** above the **Quick Start** options.
-1. At the top of the Settings screen, you should see your Domain, Client ID and
- Client Secret. Take note of these as you'll need to put them in the
- configuration file. For example:
+1. At the top of the Settings screen, you should see your **Domain**, **Client ID**, and
+ **Client Secret**. These values are needed in the configuration file. For example:
- Domain: `test1234.auth0.com`
- Client ID: `t6X8L2465bNePWLOvt9yi41i`
- Client Secret: `KbveM3nqfjwCbrhaUy_gDu2dss8TIlHIdzlyf33pB7dEK5u_NyQdp65O_o02hXs2`
-1. Fill in the Allowed Callback URLs:
+1. Fill in the **Allowed Callback URLs**:
- `http://YOUR_GITLAB_URL/users/auth/auth0/callback` (or)
- `https://YOUR_GITLAB_URL/users/auth/auth0/callback`
-1. Fill in the Allowed Origins (CORS):
+1. Fill in the **Allowed Origins (CORS)**:
- `http://YOUR_GITLAB_URL` (or)
- `https://YOUR_GITLAB_URL`
1. On your GitLab server, open the configuration file.
- For Omnibus package:
+ For Omnibus GitLab:
```shell
sudo editor /etc/gitlab/gitlab.rb
@@ -43,12 +48,12 @@ application.
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration)
+1. Read [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration)
for initial settings.
1. Add the provider configuration:
- For Omnibus package:
+ For Omnibus GitLab:
```ruby
gitlab_rails['omniauth_providers'] = [
@@ -81,10 +86,14 @@ application.
1. Change `YOUR_AUTH0_CLIENT_SECRET` to the client secret from the Auth0 Console
page from step 5.
-1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect if you
- installed GitLab via Omnibus or from source respectively.
+1. Reconfigure or restart GitLab, depending on your installation method:
+
+ - *If you installed from Omnibus GitLab,*
+ [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab.
+ - *If you installed from source,*
+ [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
-On the sign in page there should now be an Auth0 icon below the regular sign in
-form. Click the icon to begin the authentication process. Auth0 will ask the
-user to sign in and authorize the GitLab application. If everything goes well
-the user will be returned to GitLab and will be signed in.
+On the sign-in page there should now be an Auth0 icon below the regular sign-in
+form. Click the icon to begin the authentication process. Auth0 asks the
+user to sign in and authorize the GitLab application. If the user authenticates
+successfully, the user is returned to GitLab and signed in.
diff --git a/doc/integration/azure.md b/doc/integration/azure.md
index 2059707e38c..a9660e1d716 100644
--- a/doc/integration/azure.md
+++ b/doc/integration/azure.md
@@ -1,6 +1,12 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Microsoft Azure OAuth2 OmniAuth Provider
-To enable the Microsoft Azure OAuth2 OmniAuth provider you must register your application with Azure. Azure will generate a client ID and secret key for you to use.
+To enable the Microsoft Azure OAuth2 OmniAuth provider, you must register your application with Azure. Azure generates a client ID and secret key for you to use.
Sign in to the [Azure Portal](https://portal.azure.com), and follow the instructions in
the [Microsoft Quickstart documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app).
@@ -9,15 +15,19 @@ As you go through the Microsoft procedure, keep the following in mind:
- If you have multiple instances of Azure Active Directory, you can switch to the desired tenant.
- You're setting up a Web application.
-- For the redirect URI, you'll need the URL of the Azure OAuth callback of your GitLab installation (for example, `https://gitlab.mycompany.com/users/auth/azure_oauth2/callback`). The type dropdown should be set to "Web".
+- The redirect URI requires the URL of the Azure OAuth callback of your GitLab
+ installation. For example, `https://gitlab.mycompany.com/users/auth/azure_oauth2/callback`.
+ The type dropdown should be set to **Web**.
- The `client ID` and `client secret` are terms associated with OAuth 2. In some Microsoft documentation,
the terms may be listed as `Application ID` and `Application Secret`.
-- If you need to generate a new client secret, follow the Microsoft documentation on how to [Create a new application secret](https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal#create-a-new-application-secret).
-- Save the client ID and client secret for your new app. Once you leave the Azure portal, you won't be able to find the client secret again.
+- If you need to generate a new client secret, follow the Microsoft documentation
+ for [creating a new application secret](https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal#create-a-new-application-secret).
+- Save the client ID and client secret for your new app, as the client secret is only
+ displayed one time.
1. On your GitLab server, open the configuration file.
- For Omnibus package:
+ For Omnibus GitLab:
```shell
sudo editor /etc/gitlab/gitlab.rb
@@ -31,11 +41,12 @@ As you go through the Microsoft procedure, keep the following in mind:
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+1. Refer to [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration)
+ for initial settings.
1. Add the provider configuration:
- For Omnibus package:
+ For Omnibus GitLab:
```ruby
gitlab_rails['omniauth_providers'] = [
@@ -60,16 +71,22 @@ As you go through the Microsoft procedure, keep the following in mind:
```
The `base_azure_url` is optional and can be added for different locales;
- e.g. `base_azure_url: "https://login.microsoftonline.de"`.
+ such as `base_azure_url: "https://login.microsoftonline.de"`.
-1. Replace 'CLIENT ID', 'CLIENT SECRET' and 'TENANT ID' with the values you got above.
+1. Replace `CLIENT ID`, `CLIENT SECRET` and `TENANT ID` with the values you got above.
1. Save the configuration file.
-1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect if you
- installed GitLab via Omnibus or from source respectively.
+1. Reconfigure or restart GitLab, depending on your installation method:
+
+ - *If you installed from Omnibus GitLab,*
+ [reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab.
+ - *If you installed from source,*
+ [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
+
+On the sign-in page, you should now see a Microsoft icon below the regular sign-in form.
+Click the icon to begin the authentication process. Microsoft then asks you to
+sign in and authorize the GitLab application. If successful, you are returned to GitLab and signed in.
-On the sign-in page, you should now see a Microsoft icon below the regular sign in form. Click the icon
-to begin the authentication process. Microsoft then asks you to sign in and authorize the GitLab application. If everything goes well, you are returned to GitLab and signed in.
-See [Enable OmniAuth for an Existing User](omniauth.md#enable-omniauth-for-an-existing-user)
+Read [Enable OmniAuth for an Existing User](omniauth.md#enable-omniauth-for-an-existing-user)
for information on how existing GitLab users can connect to their newly-available Azure AD accounts.
diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md
index a151fbf50e7..3dc6983355c 100644
--- a/doc/integration/bitbucket.md
+++ b/doc/integration/bitbucket.md
@@ -1,34 +1,29 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Integrate your GitLab server with Bitbucket Cloud
NOTE: **Note:**
Starting from GitLab 11.4, OmniAuth is enabled by default. If you're using an
-earlier version, you'll need to explicitly enable it.
-
-Import projects from Bitbucket.org and login to your GitLab instance with your
-Bitbucket.org account.
-
-## Overview
+earlier version, you must explicitly enable it.
You can set up Bitbucket.org as an OAuth2 provider so that you can use your
-credentials to authenticate into GitLab or import your projects from
+Bitbucket.org account credentials to sign into GitLab or import your projects from
Bitbucket.org.
-- To use Bitbucket.org as an OmniAuth provider, follow the [Bitbucket OmniAuth
- provider](#bitbucket-omniauth-provider) section.
+- To use Bitbucket.org as an OmniAuth provider, follow the
+ [Bitbucket OmniAuth provider](#bitbucket-omniauth-provider) section.
- To import projects from Bitbucket, follow both the
[Bitbucket OmniAuth provider](#bitbucket-omniauth-provider) and
[Bitbucket project import](#bitbucket-project-import) sections.
## Bitbucket OmniAuth provider
-NOTE: **Note:**
-GitLab 8.15 significantly simplified the way to integrate Bitbucket.org with
-GitLab. You are encouraged to upgrade your GitLab instance if you haven't done so
-already. If you're using GitLab 8.14 or below, [use the previous integration
-docs](https://gitlab.com/gitlab-org/gitlab/blob/8-14-stable-ee/doc/integration/bitbucket.md).
-
To enable the Bitbucket OmniAuth provider you must register your application
-with Bitbucket.org. Bitbucket will generate an application ID and secret key for
+with Bitbucket.org. Bitbucket generates an application ID and secret key for
you to use.
1. Sign in to [Bitbucket.org](https://bitbucket.org).
@@ -36,26 +31,23 @@ you to use.
settings (**Manage team**), depending on how you want the application registered.
It does not matter if the application is registered as an individual or a
team, that is entirely up to you.
-1. Select **OAuth** in the left menu under "Access Management".
+1. In the left menu under **Access Management**, select **OAuth**.
1. Select **Add consumer**.
1. Provide the required details:
- | Item | Description |
- | :--- | :---------- |
- | **Name** | This can be anything. Consider something like `<Organization>'s GitLab` or `<Your Name>'s GitLab` or something else descriptive. |
- | **Application description** | Fill this in if you wish. |
- | **Callback URL** | The URL to your GitLab installation, e.g., `https://gitlab.example.com/users/auth`. |
- | **URL** | The URL to your GitLab installation, e.g., `https://gitlab.example.com`. |
-
- NOTE: Be sure to append `/users/auth` to the end of the callback URL
- to prevent a [OAuth2 convert
- redirect](http://tetraph.com/covert_redirect/) vulnerability.
-
- NOTE: Starting in GitLab 8.15, you MUST specify a callback URL, or you will
- see an "Invalid redirect_uri" message. For more details, see [the
- Bitbucket documentation](https://confluence.atlassian.com/bitbucket/oauth-faq-338365710.html).
+ - **Name:** This can be anything. Consider something like `<Organization>'s GitLab`
+ or `<Your Name>'s GitLab` or something else descriptive.
+ - **Application description:** *(Optional)* Fill this in if you wish.
+ - **Callback URL:** (Required in GitLab versions 8.15 and greater)
+ The URL to your GitLab installation, such as
+ `https://gitlab.example.com/users/auth`. Be sure to append `/users/auth` to
+ the end of the callback URL to prevent an
+ [OAuth2 convert redirect](http://tetraph.com/covert_redirect/) vulnerability.
+ Leaving this field empty
+ [results in an `Invalid redirect_uri` message](https://confluence.atlassian.com/bitbucket/oauth-faq-338365710.html).
+ - **URL:** The URL to your GitLab installation, such as `https://gitlab.example.com`.
- And grant at least the following permissions:
+1. Grant at least the following permissions:
```plaintext
Account: Email, Read
@@ -69,8 +61,8 @@ you to use.
![Bitbucket OAuth settings page](img/bitbucket_oauth_settings_page.png)
1. Select **Save**.
-1. Select your newly created OAuth consumer and you should now see a Key and
- Secret in the list of OAuth consumers. Keep this page open as you continue
+1. Select your newly created OAuth consumer, and you should now see a **Key** and
+ **Secret** in the list of OAuth consumers. Keep this page open as you continue
the configuration.
![Bitbucket OAuth key](img/bitbucket_oauth_keys.png)
@@ -119,16 +111,16 @@ you to use.
1. Save the configuration file.
1. For the changes to take effect, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) if you installed via
- Omnibus, or [restart](../administration/restart_gitlab.md#installations-from-source) if installed from source.
+ Omnibus GitLab, or [restart](../administration/restart_gitlab.md#installations-from-source) if installed from source.
-On the sign in page there should now be a Bitbucket icon below the regular sign
-in form. Click the icon to begin the authentication process. Bitbucket will ask
-the user to sign in and authorize the GitLab application. If everything goes
-well, the user will be returned to GitLab and will be signed in.
+On the sign-in page there should now be a Bitbucket icon below the regular
+sign-in form. Click the icon to begin the authentication process. Bitbucket asks
+the user to sign in and authorize the GitLab application. If successful, the user
+is returned to GitLab and signed in.
## Bitbucket project import
-Once the above configuration is set up, you can use Bitbucket to sign into
+After the above configuration is set up, you can use Bitbucket to sign into
GitLab and [start importing your projects](../user/project/import/bitbucket.md).
If you want to import projects from Bitbucket, but don't want to enable signing in,
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
index eee801350eb..e61988c3301 100644
--- a/doc/integration/cas.md
+++ b/doc/integration/cas.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# CAS OmniAuth Provider
To enable the CAS OmniAuth provider you must register your application with your CAS instance. This requires the service URL GitLab will supply to CAS. It should be something like: `https://gitlab.example.com:443/users/auth/cas3/callback?url`. By default handling for SLO is enabled, you only need to configure CAS for backchannel logout.
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index a88f2db5c26..095c58f17fc 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -23,7 +23,9 @@ and the advantage of the following special searches:
| GitLab version | Elasticsearch version |
|---------------------------------------------|-------------------------------|
-| GitLab Enterprise Edition 12.7 or greater | Elasticsearch 6.x through 7.x |
+| GitLab Enterprise Edition 13.6 or greater | Elasticsearch 7.x (6.4 - 6.x deprecated to be removed in 13.8) |
+| GitLab Enterprise Edition 13.2 through 13.5 | Elasticsearch 6.4 through 7.x |
+| GitLab Enterprise Edition 12.7 through 13.2 | Elasticsearch 6.x through 7.x |
| GitLab Enterprise Edition 11.5 through 12.6 | Elasticsearch 5.6 through 6.x |
| GitLab Enterprise Edition 9.0 through 11.4 | Elasticsearch 5.1 through 5.5 |
| GitLab Enterprise Edition 8.4 through 8.17 | Elasticsearch 2.4 with [Delete By Query Plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/2.4/plugins-delete-by-query.html) installed |
@@ -56,7 +58,7 @@ A few notes on CPU and 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
+Heavily-used Elasticsearch clusters will likely require considerably more
resources.
## Installing Elasticsearch
@@ -244,6 +246,29 @@ for filtering to work correctly. To do this run the Rake tasks `gitlab:elastic:r
`gitlab:elastic:clear_index_status`. Afterwards, removing a namespace or a project from the list will delete the data
from the Elasticsearch index as expected.
+## Enabling custom language analyzers
+
+You can improve the language support for Chinese and Japanese languages by utilizing [smartcn](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html) and/or [kuromoji](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html) analysis plugins from Elastic.
+
+To enable language(s) support:
+
+1. Install the desired plugin(s), please refer to [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/plugins/7.9/installation.html) for plugins installation instructions. The plugin(s) must be installed on every node in the cluster, and each node must be restarted after installation. For a list of plugins, see the table later in this section.
+1. Navigate to the **Admin Area** (wrench icon), then **Settings > General**..
+1. Expand the **Advanced Search** section and locate **Custom analyzers: language support**.
+1. Enable plugin(s) support for **Indexing**.
+1. Click **Save changes** for the changes to take effect.
+1. Trigger [Zero downtime reindexing](#zero-downtime-reindexing) or reindex everything from scratch to create a new index with updated mappings.
+1. Enable plugin(s) support for **Searching** after the previous step is completed.
+
+For guidance on what to install, see the following Elasticsearch language plugin options:
+
+| Parameter | Description |
+|-------------------------------------------------------|-------------|
+| `Enable Chinese (smartcn) custom analyzer: Indexing` | Enables or disables Chinese language support using [smartcn](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html) custom analyzer for newly created indices.|
+| `Enable Chinese (smartcn) custom analyzer: Search` | Enables or disables using [smartcn](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html) fields for Advanced Search. Please only enable this after [installing the plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html), enabling custom analyzer indexing and recreating the index.|
+| `Enable Japanese (kuromoji) custom analyzer: Indexing` | Enables or disables Japanese language support using [kuromoji](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html) custom analyzer for newly created indices.|
+| `Enable Japanese (kuromoji) custom analyzer: Search` | Enables or disables using [kuromoji](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html) fields for Advanced Search. Please only enable this after [installing the plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html), enabling custom analyzer indexing and recreating the index.|
+
## Disabling Advanced Search
To disable the Elasticsearch integration:
diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md
index 96c9b9d7f62..a4fca36b154 100644
--- a/doc/integration/external-issue-tracker.md
+++ b/doc/integration/external-issue-tracker.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# External issue tracker
GitLab has a great [issue tracker](../user/project/issues/index.md) but you can also use an external
diff --git a/doc/integration/facebook.md b/doc/integration/facebook.md
index dbefb560fe7..bb699fa90b7 100644
--- a/doc/integration/facebook.md
+++ b/doc/integration/facebook.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Facebook OAuth2 OmniAuth Provider
To enable the Facebook OmniAuth provider you must register your application with Facebook. Facebook will generate an app ID and secret key for you to use.
diff --git a/doc/integration/github.md b/doc/integration/github.md
index ce2b50acc54..8407920c631 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -1,6 +1,14 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Integrate your GitLab instance with GitHub
-You can integrate your GitLab instance with GitHub.com as well as GitHub Enterprise to enable users to import projects from GitHub and/or to login to your GitLab instance with your GitHub account.
+You can integrate your GitLab instance with GitHub.com and GitHub Enterprise to
+enable users to import projects from GitHub or sign in to your GitLab instance
+with your GitHub account.
## Enabling GitHub OAuth
@@ -18,11 +26,11 @@ See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration)
Once you have configured the GitHub provider, you'll need the following information, which you'll need to substitute in the GitLab configuration file, in the steps shown next.
-| Setting from GitHub | Substitute in the GitLab configuration file | Description |
-|:---------------------|:-----------------------------------------------|:------------|
-| Client ID | `YOUR_APP_ID` | OAuth 2 Client ID |
-| Client Secret | `YOUR_APP_SECRET` | OAuth 2 Client Secret |
-| URL | `https://github.example.com/` | GitHub Deployment URL |
+| Setting from GitHub | Substitute in the GitLab configuration file | Description |
+|:---------------------|:---------------------------------------------|:------------|
+| Client ID | `YOUR_APP_ID` | OAuth 2 Client ID |
+| Client Secret | `YOUR_APP_SECRET` | OAuth 2 Client Secret |
+| URL | `https://github.example.com/` | GitHub Deployment URL |
Follow these steps to incorporate the GitHub OAuth 2 app in your GitLab server:
diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md
index a200f6b6470..c618d226290 100644
--- a/doc/integration/gitlab.md
+++ b/doc/integration/gitlab.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Integrate your server with GitLab.com
Import projects from GitLab.com and login to your GitLab instance with your GitLab.com account.
diff --git a/doc/integration/gmail_action_buttons_for_gitlab.md b/doc/integration/gmail_action_buttons_for_gitlab.md
index 526db8a7338..72196fd0f52 100644
--- a/doc/integration/gmail_action_buttons_for_gitlab.md
+++ b/doc/integration/gmail_action_buttons_for_gitlab.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Gmail actions buttons for GitLab
GitLab supports [Google actions in email](https://developers.google.com/gmail/markup/actions/actions-overview).
diff --git a/doc/integration/google.md b/doc/integration/google.md
index 4cf589c1da8..cd40aaff30a 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Google OAuth2 OmniAuth Provider
To enable the Google OAuth2 OmniAuth provider you must register your application
diff --git a/doc/integration/img/jira_dev_panel_jira_setup_1.png b/doc/integration/img/jira_dev_panel_jira_setup_1.png
deleted file mode 100644
index 5c0f594cc1d..00000000000
--- a/doc/integration/img/jira_dev_panel_jira_setup_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/img/spam_log.png b/doc/integration/img/spam_log.png
index 43e267daff4..693ea2a55cd 100644
--- a/doc/integration/img/spam_log.png
+++ b/doc/integration/img/spam_log.png
Binary files differ
diff --git a/doc/integration/img/submit_issue.png b/doc/integration/img/submit_issue.png
index e794eac189e..c1bb725cc03 100644
--- a/doc/integration/img/submit_issue.png
+++ b/doc/integration/img/submit_issue.png
Binary files differ
diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md
index 8fc638db95a..7eb147c1fe6 100644
--- a/doc/integration/jenkins.md
+++ b/doc/integration/jenkins.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Jenkins CI service **(STARTER)**
NOTE: **Note:**
diff --git a/doc/integration/jenkins_deprecated.md b/doc/integration/jenkins_deprecated.md
index 5fc30bf3305..63d5ac48765 100644
--- a/doc/integration/jenkins_deprecated.md
+++ b/doc/integration/jenkins_deprecated.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Jenkins CI (deprecated) service
NOTE: **Note:**
diff --git a/doc/integration/jira_development_panel.md b/doc/integration/jira_development_panel.md
index b86eb1c38b6..1bd3095edce 100644
--- a/doc/integration/jira_development_panel.md
+++ b/doc/integration/jira_development_panel.md
@@ -9,9 +9,20 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [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)).
+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.
-Depending on your environment, you can enable this integration by configuring the Jira DVCS connector or by using the GitLab for Jira app in the Atlassian Marketplace. See the [Configuration](#configuration) section for details.
+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).
+
+Depending on your environment, you can enable this integration by either:
+
+- Configuring the Jira DVCS connector.
+- Using the GitLab for Jira app in the Atlassian Marketplace.
+
+See the [Configuration](#configuration) section for details.
## Features
@@ -24,10 +35,12 @@ Depending on your environment, you can enable this integration by configuring th
With this integration, you can access related GitLab merge requests, branches, and commits directly from a Jira issue, reflecting your work in GitLab. From the Development panel, you can open a detailed view and take actions including creating a new merge request from a branch. For more information, see [Usage](#usage).
-This integration connects all GitLab projects within a top-level group or a personal namespace to projects in the Jira instance.
-A top-level GitLab group is one that does not have any parent group itself. All the projects of that top-level group,
-as well as projects of the top-level group's subgroups nesting down, are connected. Alternatively, you can specify
-a GitLab personal namespace in the Jira configuration, which will then connect the projects in that personal namespace to Jira.
+This integration connects all GitLab projects to projects in the Jira instance within either:
+
+- A top-level group. A top-level GitLab group is one that does not have any parent group itself. All
+ the projects of that top-level group, as well as projects of the top-level group's subgroups nesting
+ down, are connected.
+- A personal namespace, which then connects the projects in that personal namespace to Jira.
This differs from the [Jira integration](../user/project/integrations/jira.md), where the mapping is between one GitLab project and the entire Jira instance.
@@ -36,17 +49,23 @@ This differs from the [Jira integration](../user/project/integrations/jira.md),
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, see [Agile Management - GitLab-Jira Development Panel Integration](https://www.youtube.com/watch?v=VjVTOmMl85M&feature=youtu.be).
-- If you're using GitLab.com and Jira Cloud, the recommended method to enable this integration is to install the [GitLab for Jira app](#gitlab-for-jira-app) from the Atlassian Marketplace, which offers a real-time sync between GitLab and Jira.
-- If you're using self-managed GitLab, self-managed Jira, or both, configure the integration using [Jira's DVCS Connector](#jira-dvcs-configuration), which syncs data hourly.
+If you're using:
-We recommend that a GitLab group admin
-or instance admin (in the case of self-managed GitLab) set up the integration,
-in order to simplify administration.
+- GitLab.com and Jira Cloud, we recommend you enable this integration by installing the
+ [GitLab for Jira app](#gitlab-for-jira-app) from the Atlassian Marketplace, which offers a real-time
+ sync between GitLab and Jira.
+- Self-managed GitLab, self-managed Jira, or both, configure the integration using
+ [Jira's DVCS Connector](#jira-dvcs-configuration), which syncs data hourly.
+
+We recommend that a GitLab group administrator or instance administrator (in the case of
+self-managed GitLab) set up the integration to simplify administration.
### Jira DVCS configuration
-NOTE: **Note:**
-If you're using GitLab.com and Jira Cloud, we recommend you use the [GitLab for Jira app](#gitlab-for-jira-app), unless you have a specific need for the DVCS Connector.
+If you're using GitLab.com and Jira Cloud, we recommend you use the
+[GitLab for Jira app](#gitlab-for-jira-app), unless you have a specific need for the DVCS Connector.
+
+When configuring Jira DVCS Connector:
- If you are using self-managed GitLab, make sure your GitLab instance is accessible by Jira.
- If you're connecting to Jira Cloud, ensure your instance is accessible through the internet.
@@ -85,8 +104,8 @@ create and use a single-purpose `jira` user in GitLab.
#### Jira DVCS Connector setup
-NOTE: **Note:**
-If you're using GitLab.com and Jira Cloud, we recommend you use the [GitLab for Jira app](#gitlab-for-jira-app), unless you have a specific need for the DVCS Connector.
+If you're using GitLab.com and Jira Cloud, we recommend you use the
+[GitLab for Jira app](#gitlab-for-jira-app), unless you have a specific need for the DVCS Connector.
1. Ensure you have completed the [GitLab configuration](#gitlab-account-configuration-for-dvcs).
1. If you're using Jira Server, go to **Settings (gear) > Applications > DVCS accounts**.
@@ -288,14 +307,6 @@ For more information on using Jira Smart Commits to track time against an issue,
## Limitations
-- This integration is currently not supported on GitLab instances under a [relative URL](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab) (for example, `http://example.com/gitlab`).
-
-## Changelog
-
-### 11.10
-
-- [Instance admins can now setup integration for all namespaces](https://gitlab.com/gitlab-org/gitlab/-/issues/8902)
-
-### 11.1
-
-- [Support GitLab subgroups in Jira development panel](https://gitlab.com/gitlab-org/gitlab/-/issues/3561)
+This integration is currently not supported on GitLab instances under a
+[relative URL](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab).
+For example, `http://example.com/gitlab`.
diff --git a/doc/integration/kerberos.md b/doc/integration/kerberos.md
index 1a193deca18..50468443769 100644
--- a/doc/integration/kerberos.md
+++ b/doc/integration/kerberos.md
@@ -1,6 +1,6 @@
---
-stage: Create
-group: Source Code
+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"
type: reference, how-to
---
@@ -47,7 +47,7 @@ sudo chmod 0600 /etc/http.keytab
### Configure GitLab
-**Installations from source**
+#### Installations from source
NOTE: **Note:**
For source installations, make sure the `kerberos` gem group
@@ -74,7 +74,7 @@ For source installations, make sure the `kerberos` gem group
1. [Restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect.
-**Omnibus package installations**
+#### Omnibus package installations
1. Edit `/etc/gitlab/gitlab.rb`:
@@ -91,23 +91,75 @@ GitLab will now offer the `negotiate` authentication method for signing in and
HTTP Git access, enabling Git clients that support this authentication protocol
to authenticate with Kerberos tokens.
-## Creating and linking Kerberos accounts
+#### Enable single sign-on
-The Administrative user can navigate to **Admin > Users > Example User > Identities**
-and attach a Kerberos account. Existing GitLab users can go to **Profile > Account**
-and attach a Kerberos account. If you want to allow users without a GitLab
-account to login, you should enable the option `allow_single_sign_on` as
-described in the [Configure GitLab](#configure-gitlab) section. Then, the first
-time a user signs in with Kerberos credentials, GitLab will create a new GitLab
-user associated with the email, which is built from the Kerberos username and
-realm. User accounts will be created automatically when authentication was
-successful.
+See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration)
+for initial settings to enable single sign-on and add Kerberos servers
+as an identity provider.
-## Linking Kerberos and LDAP accounts together
+## Create and link Kerberos accounts
-If your users log in with Kerberos, but you also have [LDAP integration](../administration/auth/ldap/index.md)
-enabled, then your users will be automatically linked to their LDAP accounts on
-first login. For this to work, some prerequisites must be met:
+You can either link a Kerberos account to an existing GitLab account, or
+set up GitLab to create a new account when a Kerberos user tries to sign in.
+
+### Link a Kerberos account to an existing GitLab account
+
+If you're an administrator, you can link a Kerberos account to an
+existing GitLab account. To do so:
+
+1. Navigate to **Admin Area > Overview > Users > Example User**.
+1. Select the Identities tab.
+1. Select 'Kerberos Spnego' in the 'Provider' dropdown box.
+1. Make sure the **Identifier** corresponds to the Kerberos username.
+1. Select **Save changes**.
+
+If you're not an administrator:
+
+1. Select your avatar in the upper-right corner, and select **Settings**.
+1. Select Account. In the **Social sign-in** section, select
+ **Connect Kerberos Spnego**.
+ If you don't see a **Social sign-in** Kerberos option, follow the
+ requirements in [Enable single sign-on](#enable-single-sign-on).
+
+In either case, you should now be able to sign in to your GitLab account
+with your Kerberos credentials.
+
+### Create accounts on first sign-in
+
+The first time users sign in to GitLab with their Kerberos accounts,
+GitLab creates a matching account.
+Before you continue, review the [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) options in Omnibus and GitLab source. You must also include `kerberos`.
+
+With that information at hand:
+
+1. Include `'kerberos'` with the `allow_single_sign_on` setting.
+1. For now, accept the default `block_auto_created_users` option, true.
+1. When a user tries to sign in with Kerberos credentials, GitLab
+ creates a new account.
+ 1. If `block_auto_created_users` is true, the Kerberos user may see
+ a message like:
+
+ ```shell
+ Your account has been blocked. Please contact your GitLab
+ administrator if you think this is an error.
+ ```
+
+ 1. As an administrator, you can confirm the new, blocked account.
+ Select **Admin Area > Overview > Users** and review the Blocked tab.
+ 1. You can enable the user.
+ 1. If `block_auto_created_users` is false, the Kerberos user is
+ authenticated and is signed in to GitLab.
+
+CAUTION: **Warning**
+We recommend that you retain the default for `block_auto_created_users`.
+Kerberos users who create accounts on GitLab without administrator
+knowledge can be a security risk.
+
+## Link Kerberos and LDAP accounts together
+
+If your users sign in with Kerberos, but you also have [LDAP integration](../administration/auth/ldap/index.md)
+enabled, your users will be linked to their LDAP accounts on their first sign-in.
+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)
@@ -125,10 +177,10 @@ LDAP Distinguished Names look like `sAMAccountName=foo,dc=ad,dc=example,dc=com`.
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9962) in GitLab 13.5.
-You can configure custom allowed realms when
-the user's Kerberos realm doesn't match the domain from the user's LDAP DN. The
-configuration value must specify all domains that users may be expected to
-have. Any other domains will be ignored and an LDAP identity will not be linked.
+You can configure custom allowed realms when the user's Kerberos realm doesn't
+match the domain from the user's LDAP DN. The configuration value must specify
+all domains that users may be expected to have. Any other domains will be
+ignored and an LDAP identity won't be linked.
**For Omnibus installations**
@@ -164,7 +216,7 @@ GitLab users with a linked Kerberos account can also `git pull` and `git push`
using Kerberos tokens, i.e., without having to send their password with each
operation.
-DANGER: **Danger:**
+DANGER: **Warning:**
There is a [known issue](https://github.com/curl/curl/issues/1261) with `libcurl`
older than version 7.64.1 wherein it won't reuse connections when negotiating.
This leads to authorization issues when push is larger than `http.postBuffer`
diff --git a/doc/integration/oauth2_generic.md b/doc/integration/oauth2_generic.md
index 8566134815a..5957af292ab 100644
--- a/doc/integration/oauth2_generic.md
+++ b/doc/integration/oauth2_generic.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Sign into GitLab with (almost) any OAuth2 provider
The `omniauth-oauth2-generic` gem allows Single Sign On between GitLab and your own OAuth2 provider
diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md
index fd1c21d725d..68d10a3135e 100644
--- a/doc/integration/oauth_provider.md
+++ b/doc/integration/oauth_provider.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab as OAuth2 authentication service provider
This document is about using GitLab as an OAuth authentication service provider
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index cf09c2f2803..eebafab2693 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# OmniAuth
GitLab leverages OmniAuth to allow users to sign in using Twitter, GitHub, and
@@ -82,8 +88,8 @@ To change these settings:
```ruby
# CAUTION!
- # This allows users to login without having a user account first. Define the allowed providers
- # using an array, e.g. ["saml", "twitter"], or as true/false to allow all providers or none.
+ # This allows users to sign in without having a user account first. Define the allowed providers
+ # using an array, for example, ["saml", "twitter"], or as true/false to allow all providers or none.
# User accounts will be created automatically when authentication was successful.
gitlab_rails['omniauth_allow_single_sign_on'] = ['saml', 'twitter']
gitlab_rails['omniauth_auto_link_ldap_user'] = true
@@ -105,13 +111,13 @@ To change these settings:
```yaml
## OmniAuth settings
omniauth:
- # Allow login via Twitter, Google, etc. using OmniAuth providers
+ # Allow sign-in by using Twitter, Google, etc. using OmniAuth providers
# Versions prior to 11.4 require this to be set to true
# enabled: true
# CAUTION!
- # This allows users to login without having a user account first. Define the allowed providers
- # using an array, e.g. ["saml", "twitter"], or as true/false to allow all providers or none.
+ # This allows users to sign in without having a user account first. Define the allowed providers
+ # using an array, for example, ["saml", "twitter"], or as true/false to allow all providers or none.
# User accounts will be created automatically when authentication was successful.
allow_single_sign_on: ["saml", "twitter"]
@@ -171,9 +177,9 @@ like `google_oauth2` for Google. Refer to the examples for the full names of the
supported providers.
NOTE: **Note:**
-If you decide to remove an OmniAuth provider from the external providers list
-you will need to manually update the users that use this method to login, if you
-want their accounts to be upgraded to full internal accounts.
+If you decide to remove an OmniAuth provider from the external providers list,
+you must manually update the users that use this method to sign in if you want
+their accounts to be upgraded to full internal accounts.
**For Omnibus installations**
@@ -296,13 +302,13 @@ omniauth:
## Bypassing two factor authentication
-Starting with GitLab 12.3, this allows users to login with the specified
-providers without two factor authentication.
+In GitLab 12.3 or later, users can sign in with specified providers _without_
+using 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 configuration dose not apply to SAML.
+Define the allowed providers using an array (for example, `["twitter", 'google_oauth2']`),
+or as `true` or `false` to allow all providers (or none). This option should be
+configured only for providers which already have two factor authentication
+(default: false). This configuration doesn't apply to SAML.
```ruby
gitlab_rails['omniauth_allow_bypass_two_factor'] = ['twitter', 'google_oauth2']
@@ -317,13 +323,12 @@ omniauth:
## Automatically sign in with provider
-You can add the `auto_sign_in_with_provider` setting to your
-GitLab configuration to automatically redirect login requests
-to your OmniAuth provider for authentication, thus removing the need to click a button
-before actually signing in.
+You can add the `auto_sign_in_with_provider` setting to your GitLab
+configuration to redirect login requests to your OmniAuth provider for
+authentication, removing the need to click a button before actually signing in.
-For example, when using the Azure integration, you would set the following
-to enable auto sign in.
+For example, when using the Azure integration, set the following to enable auto
+sign-in:
For Omnibus package:
@@ -338,13 +343,15 @@ omniauth:
auto_sign_in_with_provider: azure_oauth2
```
-Please keep in mind that every sign in attempt will be redirected to the OmniAuth provider,
-so you will not be able to sign in using local credentials. Make sure that at least one
-of the OmniAuth users has admin permissions.
+Keep in mind that every sign-in attempt will be redirected to the OmniAuth
+provider; you won't be able to sign in using local credentials. Ensure at least
+one of the OmniAuth users has admin permissions.
-You may also bypass the auto signin feature by browsing to
+You may also bypass the auto sign in feature by browsing to
`https://gitlab.example.com/users/sign_in?auto_sign_in=false`.
## Passwords for users created via OmniAuth
-The [Generated passwords for users created through integrated authentication](../security/passwords_for_integrated_authentication_methods.md) guide provides an overview of how GitLab generates and sets passwords for users created via OmniAuth.
+The [Generated passwords for users created through integrated authentication](../security/passwords_for_integrated_authentication_methods.md)
+guide provides an overview about how GitLab generates and sets passwords for
+users created with OmniAuth.
diff --git a/doc/integration/openid_connect_provider.md b/doc/integration/openid_connect_provider.md
index b66262772da..bf33483f949 100644
--- a/doc/integration/openid_connect_provider.md
+++ b/doc/integration/openid_connect_provider.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab as OpenID Connect identity provider
This document is about using GitLab as an OpenID Connect identity provider
diff --git a/doc/integration/recaptcha.md b/doc/integration/recaptcha.md
index 1868711ca9c..545f60cddbf 100644
--- a/doc/integration/recaptcha.md
+++ b/doc/integration/recaptcha.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# reCAPTCHA
GitLab leverages [Google's reCAPTCHA](https://www.google.com/recaptcha/about/)
diff --git a/doc/integration/salesforce.md b/doc/integration/salesforce.md
index dbd0a03e3cf..3290f18e2cb 100644
--- a/doc/integration/salesforce.md
+++ b/doc/integration/salesforce.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Salesforce OmniAuth Provider
You can integrate your GitLab instance with [Salesforce](https://www.salesforce.com/) to enable users to log in to your GitLab instance with their Salesforce account.
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index ee08a0026cd..16a33a86472 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -369,18 +369,18 @@ omniauth:
auto_sign_in_with_provider: saml
```
-Please keep in mind that every sign in attempt will be redirected to the SAML server,
-so you will not be able to sign in using local credentials. Make sure that at least one
-of the SAML users has admin permissions.
+Keep in mind that every sign in attempt will be redirected to the SAML server;
+you won't be able to sign in using local credentials. Ensure at least one of the
+SAML users has admin permissions.
-You may also bypass the auto signin feature by browsing to
+You may also bypass the auto sign-in feature by browsing to
`https://gitlab.example.com/users/sign_in?auto_sign_in=false`.
### `attribute_statements`
NOTE: **Note:**
-This setting should only be used to map attributes that are part of the
-OmniAuth `info` hash schema.
+This setting should be used only to map attributes that are part of the OmniAuth
+`info` hash schema.
`attribute_statements` is used to map Attribute Names in a SAMLResponse to entries
in the OmniAuth [`info` hash](https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema#schema-10-and-later).
@@ -541,9 +541,14 @@ This integration uses the `certificate` and `private_key` settings for both asse
## Request signing (optional)
-Another optional configuration is to sign SAML authentication requests. GitLab SAML Requests uses the SAML redirect binding so this is not necessary, unlike the SAML POST binding where signing is required to prevent intermediaries tampering with the requests.
+Another optional configuration is to sign SAML authentication requests. GitLab
+SAML Requests use the SAML redirect binding, so this isn't necessary (unlike the
+SAML POST binding, where signing is required to prevent intermediaries from
+tampering with the requests).
-In order to sign, you need to create a private key and public certificate pair for your GitLab instance to use for SAML. The settings related to signing can be set in the `security` section of the configuration.
+To sign, you need to create a private key and public certificate pair for your
+GitLab instance to use for SAML. The settings for signing can be set in the
+`security` section of the configuration.
For example:
@@ -636,7 +641,9 @@ Group SAML on a self-managed instance is limited when compared to the recommende
## Troubleshooting
-You can find the base64-encoded SAML Response in the [`production_json.log`](../administration/logs.md#production_jsonlog).
+### SAML Response
+
+You can find the base64-encoded SAML Response in the [`production_json.log`](../administration/logs.md#production_jsonlog). This response is sent from the IdP, and contains user information that is consumed by GitLab. Many errors in the SAML integration can be solved by decoding this response and comparing it to the SAML settings in the GitLab configuration file.
### GitLab+SAML Testing Environments
@@ -646,13 +653,14 @@ If you only need a SAML provider for testing, a [quick start guide to start a Do
### 500 error after login
-If you see a "500 error" in GitLab when you are redirected back from the SAML sign in page,
-this likely indicates that GitLab could not get the email address for the SAML user.
+If you see a "500 error" in GitLab when you are redirected back from the SAML
+sign-in page, this likely indicates that GitLab couldn't get the email address
+for the SAML user.
-Make sure the IdP provides a claim containing the user's email address, using claim name
-`email` or `mail`.
+Ensure the IdP provides a claim containing the user's email address, using the
+claim name `email` or `mail`.
-### Redirect back to login screen with no evident error
+### Redirect back to the login screen with no evident error
If after signing in into your SAML server you are redirected back to the sign in page and
no error is displayed, check your `production.log` file. It will most likely contain the
@@ -682,7 +690,7 @@ This error means that the IdP doesn't recognize GitLab as a valid sender and
receiver of SAML requests. Make sure to add the GitLab callback URL to the approved
audiences of the IdP server.
-### Missing claims
+### Missing claims, or `Email can't be blank` errors
The IdP server needs to pass certain information in order for GitLab to either
create an account, or match the login information to an existing account. `email`
@@ -710,3 +718,10 @@ For this you need take the following into account:
Make sure that one of the above described scenarios is valid, or the requests will
fail with one of the mentioned errors.
+
+### User is blocked when signing in through SAML
+
+The following are the most likely reasons that a user is blocked when signing in through SAML:
+
+- In the configuration, `gitlab_rails['omniauth_block_auto_created_users'] = true` is set and this is the user's first time signing in.
+- There are [`required_groups`](#required-groups) configured, but the user is not a member of one.
diff --git a/doc/integration/shibboleth.md b/doc/integration/shibboleth.md
index 1b645541cec..59374d8ad6f 100644
--- a/doc/integration/shibboleth.md
+++ b/doc/integration/shibboleth.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Shibboleth OmniAuth Provider
NOTE: **Note:**
diff --git a/doc/integration/slash_commands.md b/doc/integration/slash_commands.md
index c73db32a42a..ea2c4b3e93f 100644
--- a/doc/integration/slash_commands.md
+++ b/doc/integration/slash_commands.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Slash Commands
> The `run` command was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6. [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) to [GitLab Core](https://about.gitlab.com/pricing/) in 11.9.
diff --git a/doc/integration/trello_power_up.md b/doc/integration/trello_power_up.md
index fc55dbb9654..22481e14236 100644
--- a/doc/integration/trello_power_up.md
+++ b/doc/integration/trello_power_up.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Trello Power-Up
GitLab's Trello Power-Up enables you to seamlessly attach
diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md
index e501eac0c5f..bfe18c43e9d 100644
--- a/doc/integration/twitter.md
+++ b/doc/integration/twitter.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Twitter OAuth2 OmniAuth Provider
To enable the Twitter OmniAuth provider you must register your application with Twitter. Twitter will generate a client ID and secret key for you to use.
diff --git a/doc/integration/vault.md b/doc/integration/vault.md
index cead8f7592a..ea63f16c72b 100644
--- a/doc/integration/vault.md
+++ b/doc/integration/vault.md
@@ -106,13 +106,17 @@ The following assumes you already have Vault installed and running.
vault login -method=oidc port=8250 role=demo
```
- Here is a short explanation of what this command does:
+ Here's a short explanation of what this command does:
- 1. In the **Write the OIDC Role Config** (step 4), we created a role called `demo`. We set `role=demo` so Vault knows which configuration we'd like to login in with.
+ 1. In the **Write the OIDC Role Config** (step 4), we created a role called
+ `demo`. We set `role=demo` so Vault knows which configuration we'd like to
+ sign in with.
1. To set Vault to use the `OIDC` sign-in method, we set `-method=oidc`.
- 1. To set the port that GitLab should redirect to, we set `port=8250` or another port number that matches the port given to GitLab when listing [Redirect URIs](https://www.vaultproject.io/docs/auth/jwt#redirect-uris).
+ 1. To set the port that GitLab should redirect to, we set `port=8250` or
+ another port number that matches the port given to GitLab when listing
+ [Redirect URIs](https://www.vaultproject.io/docs/auth/jwt#redirect-uris).
- Once you run the command above, it will present a link in the terminal.
+ After running the command, it will present a link in the terminal.
Click the link in the terminal and a tab will open in the browser confirming you're signed into Vault via OIDC:
![Signed into Vault via OIDC](img/signed_into_vault_via_oidc_v12_6.png)
diff --git a/doc/legal/README.md b/doc/legal/README.md
index 497a477419a..4b3bcac190c 100644
--- a/doc/legal/README.md
+++ b/doc/legal/README.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/legal/corporate_contributor_license_agreement.md b/doc/legal/corporate_contributor_license_agreement.md
index 018c4b575b5..2496c866906 100644
--- a/doc/legal/corporate_contributor_license_agreement.md
+++ b/doc/legal/corporate_contributor_license_agreement.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Corporate contributor license agreement
You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab B.V.. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., You reserve all right, title, and interest in and to Your Contributions.
diff --git a/doc/legal/individual_contributor_license_agreement.md b/doc/legal/individual_contributor_license_agreement.md
index 7a071414629..8e6683d0dc6 100644
--- a/doc/legal/individual_contributor_license_agreement.md
+++ b/doc/legal/individual_contributor_license_agreement.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Individual contributor license agreement
You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab B.V.. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., You reserve all right, title, and interest in and to Your Contributions.
diff --git a/doc/migrate_ci_to_ce/README.md b/doc/migrate_ci_to_ce/README.md
index 3233cfdbaba..17f9db10767 100644
--- a/doc/migrate_ci_to_ce/README.md
+++ b/doc/migrate_ci_to_ce/README.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: howto
---
diff --git a/doc/operations/error_tracking.md b/doc/operations/error_tracking.md
index 150264eddcb..fad2c0e39be 100644
--- a/doc/operations/error_tracking.md
+++ b/doc/operations/error_tracking.md
@@ -16,7 +16,7 @@ Error Tracking allows developers to easily discover and view the errors that the
### Deploying Sentry
-You can sign up to the cloud hosted <https://sentry.io>, deploy your own [on-premise instance](https://github.com/getsentry/onpremise/) or use GitLab to [install Sentry to a Kubernetes cluster](../user/clusters/applications.md#install-sentry-using-gitlab-cicd).
+You can sign up to the cloud hosted [Sentry](https://sentry.io), deploy your own [on-premise instance](https://github.com/getsentry/onpremise/), or use GitLab to [install Sentry to a Kubernetes cluster](../user/clusters/applications.md#install-sentry-using-gitlab-cicd). To make this easier, we are [considering shipping Sentry with GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5343).
### Enabling Sentry
diff --git a/doc/operations/feature_flags.md b/doc/operations/feature_flags.md
index 00ebfe5ccf8..cac243edded 100644
--- a/doc/operations/feature_flags.md
+++ b/doc/operations/feature_flags.md
@@ -135,24 +135,21 @@ Selecting **Random** provides inconsistent application behavior for individual u
### Percent of Users
-Enables the feature for a percentage of authenticated users. It uses the
-[`gradualRolloutUserId`](https://unleash.github.io/docs/activation_strategy#gradualrolloutuserid)
-Unleash activation strategy.
-
-NOTE: **Note:**
-[Percent rollout](#percent-rollout) with a consistency based on **User IDs** has the same
-behavior. It is recommended to use percent rollout instead of percent of users as
-it is more flexible.
+Enables the feature for a percentage of authenticated users. It uses the Unleash activation strategy
+[`gradualRolloutUserId`](https://unleash.github.io/docs/activation_strategy#gradualrolloutuserid).
For example, set a value of 15% to enable the feature for 15% of authenticated users.
The rollout percentage can be from 0% to 100%.
-NOTE: **Note:**
-Stickiness (consistent application behavior for the same user) is guaranteed for logged-in users, but not anonymous users.
+Stickiness (consistent application behavior for the same user) is guaranteed for logged-in users,
+but not anonymous users.
+
+Note that [percent rollout](#percent-rollout) with a consistency based on **User IDs** has the same
+behavior. We recommend using percent rollout because it's more flexible than percent of users
CAUTION: **Caution:**
-If this strategy is selected, then the Unleash client **must** be given a user
+If the percent of users strategy is selected, then the Unleash client **must** be given a user
ID for the feature to be enabled. See the [Ruby example](#ruby-application-example) below.
### User IDs
@@ -164,11 +161,9 @@ Enables the feature for a list of target users. It is implemented
using the Unleash [`userWithId`](https://unleash.github.io/docs/activation_strategy#userwithid)
activation strategy.
-Enter user IDs as a comma-separated list of values. For example,
-`user@example.com, user2@example.com`, or `username1,username2,username3`, and so on.
-
-NOTE: **Note:**
-User IDs are identifiers for your application users. They do not need to be GitLab users.
+Enter user IDs as a comma-separated list of values (for example,
+`user@example.com, user2@example.com`, or `username1,username2,username3`, and so on). Note that
+user IDs are identifiers for your application users. They do not need to be GitLab users.
CAUTION: **Caution:**
The Unleash client **must** be given a user ID for the feature to be enabled for
@@ -306,11 +301,9 @@ To get the access credentials that your application needs to communicate with Gi
For example, if the application runs for a production server, the **Application name**
could be `production` or similar. This value is used for the environment spec evaluation.
-NOTE: **Note:**
-The meaning of these fields might change over time. For example, we are not sure
-if **Instance ID** will be single token or multiple tokens, assigned to the
-**Environment**. Also, **Application name** could describe the version of
-application instead of the running environment.
+Note that the meaning of these fields might change over time. For example, we're not sure if
+**Instance ID** will be single token or multiple tokens, assigned to the **Environment**. Also,
+**Application name** could describe the application version instead of the running environment.
### Choose a client library
diff --git a/doc/operations/incident_management/alert_integrations.md b/doc/operations/incident_management/alert_integrations.md
index 58c1e1eae76..7850841d380 100644
--- a/doc/operations/incident_management/alert_integrations.md
+++ b/doc/operations/incident_management/alert_integrations.md
@@ -9,7 +9,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13203) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.4.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) to [GitLab Core](https://about.gitlab.com/pricing/) in 12.8.
-GitLab can accept alerts from any source via a webhook receiver. This can be configured generically or, in GitLab versions 13.1 and greater, you can configure
+GitLab can accept alerts from any source via a webhook receiver. This can be configured
+generically or, in GitLab versions 13.1 and greater, you can configure
[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances)
to use this endpoint.
@@ -26,16 +27,14 @@ The list displays the integration name, type, and status (enabled or disabled):
## Configuration
-You can either configure alerts to integrate with an [external Prometheus server](#external-prometheus-integration),
-or provide a [generic HTTP endpoint](#generic-http-endpoint) to receive alerts
-from other services.
+GitLab can receive alerts via a [HTTP endpoint](#generic-http-endpoint) that you configure,
+or the [Prometheus integration](#external-prometheus-integration).
-### Generic HTTP Endpoint
+### Generic HTTP Endpoint **CORE**
-Enabling the Generic HTTP Endpoint creates a unique HTTP endpoint that can receive alert payloads in JSON format. You can always
-[customize the payload](#customizing-the-payload) to your liking.
-
-You will need to activate the endpoint and obtain credentials to set up this integration:
+Enabling the Generic HTTP Endpoint activates a unique HTTP endpoint that can
+receive alert payloads in JSON format. You can always
+[customize the payload](#customize-the-alert-payload-outside-of-gitlab) to your liking.
1. Sign in to GitLab as a user with maintainer [permissions](../../user/permissions.md)
for a project.
@@ -44,20 +43,49 @@ You will need to activate the endpoint and obtain credentials to set up this int
1. Toggle the **Active** alert setting to display the **URL** and **Authorization Key**
for the webhook configuration.
+### HTTP Endpoints **PREMIUM**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4442) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
+
+In [GitLab Premium](https://about.gitlab.com/pricing/), you can create multiple
+unique HTTP endpoints to receive alerts from any external source in JSON format,
+and you can [customize the payload](#customize-the-alert-payload-outside-of-gitlab).
+
+1. Sign in to GitLab as a user with maintainer [permissions](../../user/permissions.md)
+ for a project.
+1. Navigate to **Settings > Operations** in your project.
+1. Expand the **Alerts** section.
+1. For each endpoint you want to create:
+
+ 1. In the **Integration** dropdown menu, select **HTTP Endpoint**.
+ 1. Name the integration.
+ 1. Toggle the **Active** alert setting to display the **URL** and **Authorization Key**
+ for the webhook configuration. You will input the URL and Authorization Key
+ in your external service.
+ 1. _(Optional)_ To generate a test alert to test the new integration, enter a
+ sample payload, then click **Save and test alert payload**.Valid JSON is required.
+ 1. Click **Save Integration**.
+
+The new HTTP Endpoint displays in the [integrations list](#integrations-list).
+You can edit the integration by selecting the **{pencil}** pencil icon on the right
+side of the integrations list.
+
### External Prometheus integration
-For GitLab versions 13.1 and greater, please see [External Prometheus Instances](../metrics/alerts.md#external-prometheus-instances) to configure alerts for this integration.
+For GitLab versions 13.1 and greater, please read
+[External Prometheus Instances](../metrics/alerts.md#external-prometheus-instances)
+to configure alerts for this integration.
-## Customizing the payload
+## Customize the alert payload outside of GitLab
-You can customize the payload by sending the following parameters. This applies to all types of integrations. All fields
-other than `title` are optional:
+For all integration types, 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. |
+| `start_time` | DateTime | The time of the incident. If none is provided, a timestamp of the issue is used. |
| `end_time` | DateTime | For existing alerts only. When provided, the alert is resolved and the associated incident is closed. |
| `service` | String | The affected service. |
| `monitoring_tool` | String | The name of the associated monitoring tool. |
@@ -74,8 +102,9 @@ can be a nested JSON object. For example:
{ "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).
+TIP: **Tip:**
+Ensure your requests are smaller than the
+[payload application limits](../../administration/instance_limits.md#generic-alert-json-payloads).
Example request:
@@ -132,15 +161,21 @@ GitLab displays an error or success message, depending on the outcome of your te
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)
+together and displays a counter on the [Alert Management List](incidents.md)
and details pages.
If the existing alert is already `resolved`, GitLab creates a new alert instead.
-![Alert Management List](./img/alert_list_v13_1.png)
+![Alert Management List](img/alert_list_v13_1.png)
## Link to your Opsgenie Alerts
+DANGER: **Deprecated:**
+We are building deeper integration with Opsgenie and other alerting tools through
+[HTTP endpoint integrations](#generic-http-endpoint) so you can see alerts within
+the GitLab interface. As a result, the previous direct link to Opsgenie Alerts from
+the GitLab alerts list will be deprecated following the 13.7 release on December 22, 2020.
+
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
You can monitor alerts using a GitLab integration with [Opsgenie](https://www.atlassian.com/software/opsgenie).
diff --git a/doc/operations/incident_management/alerts.md b/doc/operations/incident_management/alerts.md
index a6168386024..37836f4ab50 100644
--- a/doc/operations/incident_management/alerts.md
+++ b/doc/operations/incident_management/alerts.md
@@ -63,7 +63,7 @@ Alerts contain one of the following icons:
## Alert details page
-Navigate to the Alert details view by visiting the [Alert list](./alerts.md)
+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.
@@ -142,7 +142,7 @@ There are different actions avilable in GitLab to help triage and respond to ale
### 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.
+See [Create and manage alerts in GitLab](alerts.md) for more details.
### Create an incident from an alert
@@ -168,11 +168,11 @@ To assign an alert:
1. To display the list of current alerts, navigate to **Operations > Alerts**:
- ![Alert List View Assignee(s)](./img/alert_list_assignees_v13_1.png)
+ ![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)
+ ![Alert Details View Assignee(s)](img/alert_details_assignees_v13_1.png)
1. If the right sidebar is not expanded, select
**{angle-double-right}** **Expand sidebar** to expand it.
@@ -180,29 +180,29 @@ To assign an alert:
From the dropdown menu, select each user you want to assign to the alert.
GitLab creates a [to-do item](../../user/todos.md) for each user.
- ![Alert Details View Assignee(s)](./img/alert_todo_assignees_v13_1.png)
+ ![Alert Details View Assignee(s)](img/alert_todo_assignees_v13_1.png)
After completing their portion of investigating or fixing the alert, users can
unassign themselves from the alert. To remove an assignee, select **Edit** next to the **Assignee** dropdown menu
and deselect the user from the list of assignees, or select **Unassigned**.
-### Create a to do from an alert
+### Create a to-do item 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:
+add a to-do item:
1. To display the list of current alerts, navigate to **Operations > Alerts**.
1. Select your desired alert to display its **Alert Management Details View**.
1. Select the **Add a To-Do** button in the right sidebar:
- ![Alert Details Add A To Do](./img/alert_detail_add_todo_v13_1.png)
+ ![Alert Details Add a To-Do](img/alert_detail_add_todo_v13_1.png)
Select the **To-Do List** **{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)
+![Alert Details Added to do](img/alert_detail_added_todo_v13_1.png)
## Link runbooks to alerts
@@ -219,46 +219,10 @@ the correct runbook:
## View the environment that generated the alert
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232492) in GitLab 13.5.
-> - 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-environment-link-in-alert-details). **(CORE ONLY)**
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232492) in GitLab 13.5 behind a feature flag, disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/232492) in GitLab 13.6.
CAUTION: **Warning:**
This feature might not be available to you. Check the **version history** note above for details.
The environment information and the link are displayed in the [Alert Details tab](#alert-details-tab).
-
-### Enable or disable Environment Link in Alert Details **(CORE ONLY)**
-
-Viewing the environment 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(:expose_environment_path_in_alert_details)
-```
-
-To enable for just a particular project:
-
-```ruby
-project = Project.find_by_full_path('your-group/your-project')
-Feature.enable(:expose_environment_path_in_alert_details, project)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:expose_environment_path_in_alert_details)
-```
-
-To disable for just a particular project:
-
-```ruby
-project = Project.find_by_full_path('your-group/your-project')
-Feature.disable(:expose_environment_path_in_alert_details, project)
-```
diff --git a/doc/operations/incident_management/generic_alerts.md b/doc/operations/incident_management/generic_alerts.md
index a8f2f9a58a6..29d609f1811 100644
--- a/doc/operations/incident_management/generic_alerts.md
+++ b/doc/operations/incident_management/generic_alerts.md
@@ -1,5 +1,5 @@
---
-redirect_to: alert_notifications.md
+redirect_to: alert_integrations.md
---
-This document was moved to [another location](alert_notifications.md).
+This document was moved to [another location](alert_integrations.md).
diff --git a/doc/operations/incident_management/img/alert_detail_full_v13_1.png b/doc/operations/incident_management/img/alert_detail_full_v13_1.png
deleted file mode 100644
index 18a6f4fb67b..00000000000
--- a/doc/operations/incident_management/img/alert_detail_full_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/incident_management/img/alert_detail_overview_v13_1.png b/doc/operations/incident_management/img/alert_detail_overview_v13_1.png
deleted file mode 100644
index 10c945d3810..00000000000
--- a/doc/operations/incident_management/img/alert_detail_overview_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/incident_management/img/alert_detail_system_notes_v13_1.png b/doc/operations/incident_management/img/alert_detail_system_notes_v13_1.png
deleted file mode 100644
index 2a6d0320a54..00000000000
--- a/doc/operations/incident_management/img/alert_detail_system_notes_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/incident_management/img/alert_list_search_v13_1.png b/doc/operations/incident_management/img/alert_list_search_v13_1.png
deleted file mode 100644
index ba993fe530b..00000000000
--- a/doc/operations/incident_management/img/alert_list_search_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/incident_management/img/alert_list_sort_v13_1.png b/doc/operations/incident_management/img/alert_list_sort_v13_1.png
deleted file mode 100644
index 8e06c3478f7..00000000000
--- a/doc/operations/incident_management/img/alert_list_sort_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/incident_management/img/incident_highlight_bar_v13_5.png b/doc/operations/incident_management/img/incident_highlight_bar_v13_5.png
deleted file mode 100644
index 6a40e97820c..00000000000
--- a/doc/operations/incident_management/img/incident_highlight_bar_v13_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/incident_management/img/incident_list.png b/doc/operations/incident_management/img/incident_list.png
deleted file mode 100644
index 0498fec6c9c..00000000000
--- a/doc/operations/incident_management/img/incident_list.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/incident_management/img/incident_list_search_v13_3.png b/doc/operations/incident_management/img/incident_list_search_v13_3.png
deleted file mode 100644
index 293268986cc..00000000000
--- a/doc/operations/incident_management/img/incident_list_search_v13_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/incident_management/img/incident_sla_settings_v13_5.png b/doc/operations/incident_management/img/incident_sla_settings_v13_5.png
deleted file mode 100644
index 94c8b840210..00000000000
--- a/doc/operations/incident_management/img/incident_sla_settings_v13_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md
index 3d85fa0ebd8..13a755bbb6f 100644
--- a/doc/operations/incident_management/incidents.md
+++ b/doc/operations/incident_management/incidents.md
@@ -6,7 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Incidents
-Incidents are critical entities in incident management workflows. They represent a service disruption or outage that needs to be restored urgently. GitLab provides tools for the triage, response, and remediation of incidents.
+Incidents are critical entities in incident management workflows. They represent
+a service disruption or outage that needs to be restored urgently. GitLab provides
+tools for the triage, response, and remediation of incidents.
## Incident Creation
@@ -14,7 +16,8 @@ You can create an incident manually or automatically.
### Create incidents manually
-If you have at least Guest [permissions](../../user/permissions.md), to create an Incident, you have two options to do this manually.
+If you have at least Guest [permissions](../../user/permissions.md), to create an
+Incident, you have two options to do this manually.
**From the Incidents List:**
@@ -24,7 +27,7 @@ If you have at least Guest [permissions](../../user/permissions.md), to create a
- 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:**
@@ -34,7 +37,7 @@ If you have at least Guest [permissions](../../user/permissions.md), to create a
- 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)
+![Incident List Create](img/new_incident_create_v13_4.png)
### Create incidents automatically
@@ -43,17 +46,17 @@ If you have at least Guest [permissions](../../user/permissions.md), to create a
With Maintainer or higher [permissions](../../user/permissions.md), you can enable
GitLab to create incident automatically whenever an alert is triggered:
-1. Navigate to **Settings > Operations > Incidents** and expand
- **Incidents**:
+1. Navigate to **Settings > 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. Check the **Create an incident**
- checkbox.
-1. To customize the incident, select an [issue templates](../../user/project/description_templates.md#creating-issue-templates).
+1. Check the **Create an incident** checkbox.
+1. To customize the incident, select an
+ [issue template](../../user/project/description_templates.md#creating-issue-templates).
1. To send [an email notification](alert_notifications.md#email-notifications) to users
with [Developer permissions](../../user/permissions.md), select
- **Send a separate email notification to Developers**. Email notifications will also be sent to users with **Maintainer** and **Owner** permissions.
+ **Send a separate email notification to Developers**. Email notifications are
+ also sent to users with **Maintainer** and **Owner** permissions.
1. Click **Save changes**.
### Create incidents via the PagerDuty webhook
@@ -68,7 +71,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.
@@ -167,7 +170,7 @@ tab, the incident must have been created with a linked alert. Incidents
created automatically from alerts have this
field populated.
-![Incident alert details](./img/incident_alert_details_v13_4.png)
+![Incident alert details](img/incident_alert_details_v13_4.png)
### Timeline view
@@ -177,32 +180,47 @@ To quickly see the latest updates on an incident, click
**{comments}** **Turn timeline view on** in the comment bar to display comments
un-threaded and ordered chronologically, newest to oldest:
-![Timeline view toggle](./img/timeline_view_toggle_v13_5.png)
+![Timeline view toggle](img/timeline_view_toggle_v13_5.png)
### Service Level Agreement countdown timer
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241663) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5.
-After enabling **Incident SLA** in the Incident Management configuration, newly-created
-incidents display a SLA (Service Level Agreement) timer showing the time remaining before
-the SLA period expires. If the incident is not closed before the SLA period ends, GitLab
-adds a `missed::SLA` label to the incident.
+You can enable the Service Level Agreement Countdown timer on incidents to track
+the Service Level Agreements (SLAs) you hold with your customers. The timer is
+automatically started when the incident is created, and shows the time
+remaining before the SLA period expires. To configure the timer:
+
+1. Navigate to **Settings > Operations**.
+1. Scroll to **Incidents** and click **Expand**, then select the
+ **Incident settings** tab.
+1. Select **Activate "time to SLA" countdown timer**.
+1. Set a time limit in increments of 15 minutes.
+1. Click **Save changes**.
+
+After you enable the SLA countdown timer, the **Time to SLA** attribute is displayed
+as a column in the Incidents List, and as a field on newly created Incidents. If
+the incident isn't closed before the SLA period ends, GitLab adds a `missed::SLA`
+label to the incident.
## Incident Actions
-There are different actions avilable to help triage and respond to incidents.
+There are different actions available to help triage and respond to incidents.
### Assign incidents
-Assign incidents to users that are actively responding. Select **Edit** in the right-hand side bar to select or deselect assignees.
+Assign incidents to users that are actively responding. Select **Edit** in the
+right-hand side bar to select or deselect assignees.
### Change severity
-See [Incident List](#incident-list) for a full description of the severities available. Select **Edit** in the right-hand side bar to change the severity of an incident.
+See [Incident List](#incident-list) for a full description of the severity levels available.
+Select **Edit** in the right-hand side bar to change the severity of an incident.
-### Add a to do
+### Add a to-do item
-Add a to-do for incidents that you want to track in your to-do list. Clicke the **Add a to do** button at the top of the right-hand side bar to add a to do.
+Add a to-do for incidents that you want to track in your to-do list. Click the
+**Add a to do** button at the top of the right-hand side bar to add a to-do item.
### Manage incidents from Slack
diff --git a/doc/operations/incident_management/status_page.md b/doc/operations/incident_management/status_page.md
index e5d0ae1ddbb..4230091866e 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.
@@ -138,7 +138,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/metrics/dashboards/img/metrics_settings_button_v13_3.png b/doc/operations/metrics/dashboards/img/metrics_settings_button_v13_3.png
deleted file mode 100644
index 9c0eac12a3f..00000000000
--- a/doc/operations/metrics/dashboards/img/metrics_settings_button_v13_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/metrics/dashboards/index.md b/doc/operations/metrics/dashboards/index.md
index 4aa340a9e59..c11da2926bb 100644
--- a/doc/operations/metrics/dashboards/index.md
+++ b/doc/operations/metrics/dashboards/index.md
@@ -14,9 +14,6 @@ includes a few key metrics, but you can also define your own custom dashboards.
You may create a [new dashboard from scratch](#add-a-new-dashboard-to-your-project)
or [duplicate a GitLab-defined Prometheus dashboard](#duplicate-a-gitlab-defined-dashboard).
-The metrics as defined below do not support alerts, unlike
-[custom metrics](../index.md#adding-custom-metrics).
-
## Add a new dashboard to your project
> UI option [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/228856) in GitLab 13.3.
@@ -116,14 +113,9 @@ Your custom dashboard is available at `https://example.com/project/-/metrics/cus
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223204) in GitLab 13.2.
-To manage the settings for your metrics dashboard:
-
-1. Sign in as a user with project Maintainer or Administrator
- [permissions](../../../user/permissions.md#project-members-permissions).
-1. Navigate to your dashboard at **Operations > Metrics**.
-1. In the top-right corner of your dashboard, click **Metrics Settings**:
-
- ![Monitoring Dashboard actions menu with create new item](img/metrics_settings_button_v13_3.png)
+Users with project Maintainer or Administrator
+[permissions](../../../user/permissions.md#project-members-permissions)
+can manage [the settings](settings.md) for your metrics dashboard.
## Chart Context Menu
@@ -226,7 +218,7 @@ links:
## Troubleshooting
When troubleshooting issues with a managed Prometheus app, it is often useful to
-[view the Prometheus UI](../../../development/prometheus.md#access-the-ui-of-a-prometheus-managed-application-in-kubernetes).
+[view the Prometheus UI](../../../user/project/integrations/prometheus.md#access-the-ui-of-a-prometheus-managed-application-in-kubernetes).
### "No data found" error on Metrics dashboard page
diff --git a/doc/operations/metrics/dashboards/settings.md b/doc/operations/metrics/dashboards/settings.md
index aa0b9a81771..6052b0778da 100644
--- a/doc/operations/metrics/dashboards/settings.md
+++ b/doc/operations/metrics/dashboards/settings.md
@@ -21,8 +21,8 @@ time zone, but you can display dates and times in UTC format. To change the
time zone:
1. Sign in as a user with Manage Project Operations [permissions](../../../user/permissions.md).
-1. Navigate to **Settings > Operations**, and scroll to
- **Metrics Dashboard**.
+1. Navigate to **Settings > Operations**.
+1. Scroll to **Metrics Dashboard** and click **Expand**.
1. In the **Dashboard timezone** select box, select *User's local timezone*
or *UTC*:
@@ -37,8 +37,8 @@ You can add a button on your monitoring dashboard that links directly to your
existing external dashboards:
1. Sign in as a user with Manage Project Operations [permissions](../../../user/permissions.md).
-1. Navigate to **Settings > Operations**, and scroll to
- **Metrics Dashboard**.
+1. Navigate to **Settings > Operations**.
+1. Scroll to **Metrics Dashboard** and click **Expand**.
1. In **External dashboard URL**, provide the URL to your external dashboard:
![External Dashboard Setting](img/dashboard_external_link_v13_1.png)
diff --git a/doc/operations/metrics/dashboards/variables.md b/doc/operations/metrics/dashboards/variables.md
index 2103f8e66db..e1f5f0ce6f4 100644
--- a/doc/operations/metrics/dashboards/variables.md
+++ b/doc/operations/metrics/dashboards/variables.md
@@ -50,6 +50,8 @@ For example, if the dashboard time range is set to 8 hours, the value of
[Variables can be defined](../../../operations/metrics/dashboards/yaml.md#templating-templating-properties) in a custom dashboard YAML file.
+Variable names are case-sensitive.
+
## Query variables from URL
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214500) in GitLab 13.0.
diff --git a/doc/operations/metrics/dashboards/yaml.md b/doc/operations/metrics/dashboards/yaml.md
index c3523327c51..13397eb702a 100644
--- a/doc/operations/metrics/dashboards/yaml.md
+++ b/doc/operations/metrics/dashboards/yaml.md
@@ -87,8 +87,8 @@ is no longer used.
| `id` | string | no | Used for associating dashboard metrics with database records. Must be unique across dashboard configuration files. Required for [alerting](../alerts.md) (support not yet enabled, see [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/27980)). |
| `unit` | string | yes | Defines the unit of the query's return data. |
| `label` | string | no, but highly encouraged | Defines the legend-label for the query. Should be unique within the panel's metrics. Can contain time series labels as interpolated variables. |
-| `query` | string/number | yes if `query_range` is not defined | Defines the Prometheus query to be used to populate the chart/panel. If defined, the `query` endpoint of the [Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/) will be utilized. |
-| `query_range` | string/number | yes if `query` is not defined | Defines the Prometheus query to be used to populate the chart/panel. If defined, the `query_range` endpoint of the [Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/) will be utilized. |
+| `query` | string/number | yes if `query_range` is not defined | Defines the Prometheus query to be used to populate the chart/panel. If defined, the `query` endpoint of the [Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/) will be used. |
+| `query_range` | string/number | yes if `query` is not defined | Defines the Prometheus query to be used to populate the chart/panel. If defined, the `query_range` endpoint of the [Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/) will be used. |
| `step` | number | no, value is calculated if not defined | Defines query resolution step width in float number of seconds. Metrics on the same panel should use the same `step` value. |
## Dynamic labels
diff --git a/doc/operations/metrics/index.md b/doc/operations/metrics/index.md
index 39d03ded373..6ce0bd42d3c 100644
--- a/doc/operations/metrics/index.md
+++ b/doc/operations/metrics/index.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Monitor your CI/CD environment's metrics **(CORE)**
+# Monitor your environment's metrics **(CORE)**
GitLab helps your team monitor the health and performance of your applications
and infrastructure by turning statistics and log files into charts and graphs
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index 77b4b22e6a8..9edec660d5f 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -1,4 +1,7 @@
---
+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
type: concepts
---
@@ -54,21 +57,11 @@ one major version. For example, it is safe to:
- `12.7.5` -> `12.10.5`
- `11.3.4` -> `11.11.1`
- - `10.6.6` -> `10.8.3`
- - `11.3.4` -> `11.11.8`
- - `10.6.6` -> `10.8.7`
- - `9.2.3` -> `9.5.5`
- - `8.9.4` -> `8.12.3`
- Upgrade the *patch* version. For example:
- `12.0.4` -> `12.0.12`
- `11.11.1` -> `11.11.8`
- - `10.6.3` -> `10.6.6`
- - `11.11.1` -> `11.11.8`
- - `10.6.3` -> `10.6.6`
- - `9.5.5` -> `9.5.9`
- - `8.9.2` -> `8.9.6`
NOTE: **Note:**
Version specific changes in Omnibus GitLab Linux packages can be found in [the Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/update/README.html#version-specific-changes).
@@ -79,74 +72,9 @@ Instructions are available for downloading an Omnibus GitLab Linux package local
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.
-Backward-incompatible changes and migrations are reserved for major versions.
-We cannot guarantee that upgrading between major versions will be seamless.
-We suggest upgrading to the latest available *minor* version within
-your major version before proceeding to the next major version.
-Doing this will address any backward-incompatible changes or deprecations
-to help ensure a successful upgrade to the next major release.
-
-It's also important to ensure that any background migrations have been fully completed
-before upgrading to a new major version. To see the current size of the `background_migration` queue,
-[Check for background migrations before upgrading](../update/README.md#checking-for-background-migrations-before-upgrading).
-
-If your GitLab instance has any runners associated with it, it is very
-important to upgrade GitLab Runner to match the GitLab minor version that was
-upgraded to. This is to ensure [compatibility with GitLab versions](https://docs.gitlab.com/runner/#compatibility-with-gitlab-versions).
-
-### Version 12 onward: Extra step for major upgrades
-
-From version 12 onward, an additional step is required. More significant migrations
-may occur during major release upgrades.
-
-To ensure these are successful:
-
-1. Increment to the first minor version (`x.0.x`) during the major version jump.
-1. Proceed with upgrading to a newer release.
-
-**For example: `11.5.x` -> `11.11.x` -> `12.0.x` -> `12.10.x` -> `13.0.x`**
-
-### Example upgrade paths
-
-Please see the table below for some examples:
+## Upgrading major versions
-| Target version | Your version | Recommended upgrade path | Note |
-| --------------------- | ------------ | ------------------------ | ---- |
-| `13.4.3` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.4.3` | Two intermediate versions are required: the final `12.10` release, plus `13.0`. |
-| `13.2.10` | `11.5.0` | `11.5.0` -> `11.11.8` -> `12.0.12` -> `12.10.14` -> `13.0.14` -> `13.2.10` | Four intermediate versions are required: the final `11.11`, `12.0`, and `12.10` releases, plus `13.0`. |
-| `12.10.14` | `11.3.4` | `11.3.4` -> `11.11.8` -> `12.0.12` -> `12.10.14` | Two intermediate versions are required: the final `11.11` release and `12.0.12` |
-| `12.9.5` | `10.4.5` | `10.4.5` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.9.5` | Three intermediate versions are required: `10.8`, `11.11`, and `12.0`, then `12.9.5` |
-| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.2.5` | Four intermediate versions are required: `9.5`, `10.8`, `11.11`, `12.0`, then `12.2`. |
-| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version 8, `9.5.10` is the last version in version 9, `10.8.7` is the last version in version 10. |
-
-### Upgrades from versions earlier than 8.12
-
-- `8.11.x` and earlier: you might have to upgrade to `8.12.0` specifically before you can upgrade to `8.17.7`. This was [reported in an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/207259).
-- [CI changes prior to version 8.0](https://docs.gitlab.com/omnibus/update/README.html#updating-gitlab-ci-from-prior-540-to-version-714-via-omnibus-gitlab)
- when it was merged into GitLab.
-
-### Multi-step upgrade paths with GitLab all-in-one Linux package repository
-
-Linux package managers default to installing the latest available version of a package for installation and upgrades.
-Upgrading directly to the latest major version can be problematic for older GitLab versions that require a multi-stage upgrade path.
-
-When following an upgrade path spanning multiple versions, for each upgrade, specify the intended GitLab version number in your package manager's install or upgrade command.
-
-Examples:
-
-```shell
-# apt-get (Ubuntu/Debian)
-sudo apt-get upgrade gitlab-ee=12.0.12-ee.0
-# yum (RHEL/CentOS 6 and 7)
-yum install gitlab-ee-12.0.12-ee.0.el7
-# dnf (RHEL/CentOS 8)
-dnf install gitlab-ee-12.0.12-ee.0.el8
-# zypper (SUSE)
-zypper install gitlab-ee=12.0.12-ee.0
-```
+Backward-incompatible changes and migrations are reserved for major versions. See the [upgrade guide](../update/README.md#upgrading-to-a-new-major-version).
## Patch releases
@@ -221,19 +149,6 @@ This decision is made on a case-by-case basis.
## More information
-Check [our release posts](https://about.gitlab.com/releases/categories/releases/).
-
-Each month, we publish either a major or minor release of GitLab. At the end
-of those release posts, there are three sections to look for: Deprecations, Removals, and Important notes on upgrading. These will include:
-
-- Steps you need to perform as part of an upgrade.
- For example [8.12](https://about.gitlab.com/releases/2016/09/22/gitlab-8-12-released/#upgrade-barometer)
- required the Elasticsearch index to be recreated. Any older version of GitLab upgrading to 8.12 or higher would require this.
-- Changes to the versions of software we support such as
- [ceasing support for IE11 in GitLab 13](https://about.gitlab.com/releases/2020/03/22/gitlab-12-9-released/#ending-support-for-internet-explorer-11).
-
-You should check all the major and minor versions you're passing over.
-
More information about the release procedures can be found in our
[release documentation](https://gitlab.com/gitlab-org/release/docs). You may also want to read our
[Responsible Disclosure Policy](https://about.gitlab.com/security/disclosure/).
diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md
index 848065de001..1f9486dc324 100644
--- a/doc/public_access/public_access.md
+++ b/doc/public_access/public_access.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
@@ -21,12 +24,12 @@ on the repository.
### Internal projects
-Internal projects can be cloned by any logged in user.
+Internal projects can be cloned by any logged in user except [external users](../user/permissions.md#external-users).
They will also be listed in the public access directory (`/public`), but only for logged
in users.
-Any logged in user will have [Guest permissions](../user/permissions.md)
+Any logged in user except [external users](../user/permissions.md#external-users) will have [Guest permissions](../user/permissions.md)
on the repository.
NOTE: **Note:**
diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md
index 7aec74f1243..4d2185c62f2 100644
--- a/doc/raketasks/README.md
+++ b/doc/raketasks/README.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 8a4cc0c8ff2..a06fe00ef0d 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Back up and restore GitLab **(CORE ONLY)**
GitLab provides Rake tasks for backing up and restoring GitLab instances.
@@ -329,7 +335,7 @@ sudo -u git -H GITLAB_ASSUME_YES=1 bundle exec rake gitlab:backup:restore RAILS_
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37158) in GitLab 13.3.
-Repositories can be backed up concurrently to help fully utilize CPU time. The
+Repositories can be backed up concurrently to help fully use CPU time. The
following variables are available to modify the default behavior of the Rake
task:
diff --git a/doc/raketasks/cleanup.md b/doc/raketasks/cleanup.md
index 0b3da39d3d5..00a3e9196e2 100644
--- a/doc/raketasks/cleanup.md
+++ b/doc/raketasks/cleanup.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Clean up **(CORE ONLY)**
GitLab provides Rake tasks for cleaning up GitLab instances.
@@ -6,7 +12,7 @@ GitLab provides Rake tasks for cleaning up GitLab instances.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36628) in GitLab 12.10.
-DANGER: **Danger:**
+DANGER: **Warning:**
Do not run this within 12 hours of a GitLab upgrade. This is to ensure that all background migrations
have finished, which otherwise may lead to data loss.
@@ -201,6 +207,10 @@ sudo gitlab-rake gitlab:cleanup:sessions:active_sessions_lookup_keys
bundle exec rake gitlab:cleanup:sessions:active_sessions_lookup_keys RAILS_ENV=production
```
+## Cleaning up stale Redis sessions
+
+[Clean up stale sessions](../administration/operations/cleaning_up_redis_sessions.md) to compact the Redis database after you upgrade to GitLab 7.3.
+
## Container Registry garbage collection
Container Registry can use considerable amounts of disk space. To clear up
diff --git a/doc/raketasks/features.md b/doc/raketasks/features.md
index 1d68671a545..ecdf6aee069 100644
--- a/doc/raketasks/features.md
+++ b/doc/raketasks/features.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Namespaces **(CORE ONLY)**
This Rake task enables [namespaces](../user/group/index.md#namespaces) for projects.
diff --git a/doc/raketasks/generate_sample_prometheus_data.md b/doc/raketasks/generate_sample_prometheus_data.md
index 902be6862c8..f37aa95c63b 100644
--- a/doc/raketasks/generate_sample_prometheus_data.md
+++ b/doc/raketasks/generate_sample_prometheus_data.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Generate sample Prometheus data **(CORE ONLY)**
This command will run Prometheus queries for each of the metrics of a specific environment
diff --git a/doc/raketasks/import.md b/doc/raketasks/import.md
index b0603a76211..ecd777361a7 100644
--- a/doc/raketasks/import.md
+++ b/doc/raketasks/import.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Import bare repositories **(CORE ONLY)**
Rake tasks are available to import bare repositories into a GitLab instance.
diff --git a/doc/raketasks/list_repos.md b/doc/raketasks/list_repos.md
index 411de52e379..192a65f6a62 100644
--- a/doc/raketasks/list_repos.md
+++ b/doc/raketasks/list_repos.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Listing repository directories **(CORE ONLY)**
You can print a list of all Git repositories on disk managed by GitLab.
@@ -13,7 +19,6 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:list_repos RAILS_ENV=production
```
-NOTE: **Note:**
The results use the default ordering of the GitLab Rails application.
## Limit search results
diff --git a/doc/raketasks/migrate_snippets.md b/doc/raketasks/migrate_snippets.md
index 476615d3926..e36ad5184ad 100644
--- a/doc/raketasks/migrate_snippets.md
+++ b/doc/raketasks/migrate_snippets.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Migration to Versioned Snippets **(CORE ONLY)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215861) in GitLab 13.0.
diff --git a/doc/raketasks/spdx.md b/doc/raketasks/spdx.md
index 23eb27eb059..19ec0397179 100644
--- a/doc/raketasks/spdx.md
+++ b/doc/raketasks/spdx.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# SPDX license list import **(PREMIUM ONLY)**
GitLab provides a Rake task for uploading a fresh copy of the [SPDX license list](https://spdx.org/licenses/)
diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md
index 61e30f9ddb1..a0a880eac51 100644
--- a/doc/raketasks/user_management.md
+++ b/doc/raketasks/user_management.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# User management **(CORE ONLY)**
GitLab provides Rake tasks for user management.
@@ -26,7 +32,6 @@ sudo gitlab-rake gitlab:import:all_users_to_all_projects
bundle exec rake gitlab:import:all_users_to_all_projects RAILS_ENV=production
```
-NOTE: **Note:**
Admin users are added as maintainers.
## Add user as a developer to all groups
@@ -53,7 +58,6 @@ sudo gitlab-rake gitlab:import:all_users_to_all_groups
bundle exec rake gitlab:import:all_users_to_all_groups RAILS_ENV=production
```
-NOTE: **Note:**
Admin users are added as owners so they can add additional users to the group.
## Control the number of active users
diff --git a/doc/raketasks/web_hooks.md b/doc/raketasks/web_hooks.md
index 7bd2ed311d2..769a5ebae3a 100644
--- a/doc/raketasks/web_hooks.md
+++ b/doc/raketasks/web_hooks.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Webhooks administration **(CORE ONLY)**
GitLab provides Rake tasks for webhooks management.
diff --git a/doc/raketasks/x509_signatures.md b/doc/raketasks/x509_signatures.md
index f7c47794690..79770a56808 100644
--- a/doc/raketasks/x509_signatures.md
+++ b/doc/raketasks/x509_signatures.md
@@ -1,3 +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
+---
+
# X.509 signatures **(CORE ONLY)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/122159) in GitLab 12.10.
diff --git a/doc/security/README.md b/doc/security/README.md
index f8b9e423c04..a8947ef3de9 100644
--- a/doc/security/README.md
+++ b/doc/security/README.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
type: index
---
diff --git a/doc/security/asset_proxy.md b/doc/security/asset_proxy.md
index fdceecdf386..7eb6d5067e2 100644
--- a/doc/security/asset_proxy.md
+++ b/doc/security/asset_proxy.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Proxying assets
A possible security concern when managing a public facing GitLab instance is
diff --git a/doc/security/crime_vulnerability.md b/doc/security/crime_vulnerability.md
index 2496029d93e..4571f0051d8 100644
--- a/doc/security/crime_vulnerability.md
+++ b/doc/security/crime_vulnerability.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/security/information_exclusivity.md b/doc/security/information_exclusivity.md
index 7c3d7284f25..a8c4a4e878e 100644
--- a/doc/security/information_exclusivity.md
+++ b/doc/security/information_exclusivity.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: concepts
---
diff --git a/doc/security/password_length_limits.md b/doc/security/password_length_limits.md
index 5354fe30082..b8d329ab342 100644
--- a/doc/security/password_length_limits.md
+++ b/doc/security/password_length_limits.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference, howto
---
@@ -11,11 +14,31 @@ By default, GitLab supports passwords with:
GitLab administrators can modify password lengths:
-- Using configuration file.
-- [From](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20661) GitLab 12.6, using the GitLab UI.
+- Using the GitLab UI. **[From](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20661) GitLab 12.6 this is the only available option.**
+- Using configuration file. **Up to GitLab 12.5**.
+
+Changing the minimum or maximum length does not affect existing user passwords. Existing users are
+not asked to reset their password to adhere to the new limits. The new limit restriction applies
+only during new user sign-ups and when an existing user performs a password reset.
+
+## Modify minimum password length using GitLab UI
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20661) in GitLab 12.6
+
+The user password length is set to a minimum of 8 characters by default.
+
+To change the minimum password length using GitLab UI:
+
+1. Go to **Admin Area > Settings**, then select **Sign-up restrictions**.
+
+ ![Minimum password length settings](../user/admin_area/img/minimum_password_length_settings_v12_6.png)
+
+1. Input a **Minimum password length** value greater than or equal to 8, then select **Save changes**.
## Modify maximum password length using configuration file
+From GitLab 12.6, the minimum password length set in this configuration file is ignored. Minimum password lengths must instead be modified via the [GitLab UI](#modify-minimum-password-length-using-gitlab-ui).
+
The user password length is set to a maximum of 128 characters by default.
To change that for installations from source:
@@ -39,26 +62,6 @@ To change that for installations from source:
1. [Restart GitLab](../administration/restart_gitlab.md#installations-from-source)
for the changes to take effect.
-NOTE: **Note:**
-From GitLab 12.6, the minimum password length set in this configuration file will be ignored. Minimum password lengths will now have to be modified via the [GitLab UI](#modify-minimum-password-length-using-gitlab-ui) instead.
-
-## Modify minimum password length using GitLab UI
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20661) in GitLab 12.6
-
-The user password length is set to a minimum of 8 characters by default.
-To change that using GitLab UI:
-
-In **Admin Area > Settings** (`/admin/application_settings/general`), go to the section **Sign-up restrictions**.
-
-[Minimum password length settings](../user/admin_area/img/minimum_password_length_settings_v12_6.png)
-
-Set the **Minimum password length** to a value greater than or equal to 8 and hit **Save changes** to save the changes.
-
-CAUTION: **Caution:**
-Changing minimum or maximum limit does not affect existing user passwords in any manner. Existing users will not be asked to reset their password to adhere to the new limits.
-The new limit restriction will only apply during new user sign-ups and when an existing user performs a password reset.
-
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/security/password_storage.md b/doc/security/password_storage.md
index 96487a75d8d..ca4d350dc06 100644
--- a/doc/security/password_storage.md
+++ b/doc/security/password_storage.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/security/passwords_for_integrated_authentication_methods.md b/doc/security/passwords_for_integrated_authentication_methods.md
index f2597ef1578..4872f26a0ad 100644
--- a/doc/security/passwords_for_integrated_authentication_methods.md
+++ b/doc/security/passwords_for_integrated_authentication_methods.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/security/project_import_decompressed_archive_size_limits.md b/doc/security/project_import_decompressed_archive_size_limits.md
index 16821e1f192..9e50290afcc 100644
--- a/doc/security/project_import_decompressed_archive_size_limits.md
+++ b/doc/security/project_import_decompressed_archive_size_limits.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference, howto
---
diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md
index b386917f399..a84ecc8e47d 100644
--- a/doc/security/rack_attack.md
+++ b/doc/security/rack_attack.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference, howto
---
diff --git a/doc/security/rate_limits.md b/doc/security/rate_limits.md
index 9e754cf1917..94cc446c804 100644
--- a/doc/security/rate_limits.md
+++ b/doc/security/rate_limits.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference, howto
---
diff --git a/doc/security/reset_user_password.md b/doc/security/reset_user_password.md
index bc8de882afe..66e11587e96 100644
--- a/doc/security/reset_user_password.md
+++ b/doc/security/reset_user_password.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: howto
---
@@ -53,14 +56,15 @@ Don't forget to save the changes.
user.save!
```
-Exit the console and try to login with your new password.
+Exit the console, and then try to sign in with your new password.
NOTE: **Note:**
-Passwords can also be reset via the [Users API](../api/users.md#user-modification)
+You can also reset passwords by using 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:
+The previously described steps can also be used to reset the root password. First,
+identify the root user, with an `id` of `1`. To do so, run the following command:
```shell
user = User.where(id: 1).first
diff --git a/doc/security/two_factor_authentication.md b/doc/security/two_factor_authentication.md
index 995dea7809e..27cc2474b8a 100644
--- a/doc/security/two_factor_authentication.md
+++ b/doc/security/two_factor_authentication.md
@@ -8,22 +8,22 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Enforce Two-factor Authentication (2FA)
Two-factor Authentication (2FA) provides an additional level of security to your
-users' GitLab account. Once enabled, in addition to supplying their username and
-password to login, they'll be prompted for a code generated by an application on
-their phone.
+users' GitLab account. After being enabled, in addition to supplying their
+username and password to sign in, they'll be prompted for a code generated by an
+application on their phone.
You can read more about it here:
[Two-factor Authentication (2FA)](../user/profile/account/two_factor_authentication.md)
## Enforcing 2FA for all users
-Users on GitLab, can enable it without any admin's intervention. If you want to
-enforce everyone to set up 2FA, you can choose from two different ways:
+Users on GitLab can enable it without any administrator's intervention. If you
+want to enforce everyone to set up 2FA, you can choose from two different ways:
- Enforce on next login.
- Suggest on next login, but allow a grace period before enforcing.
-After the configured grace period has elapsed, users will be able to log in but
+After the configured grace period has elapsed, users will be able to sign in but
won't be able to leave the 2FA configuration area at `/profile/two_factor_auth`.
To enable 2FA for all users:
@@ -32,15 +32,17 @@ To enable 2FA for all users:
(`/admin/application_settings/general`).
1. Expand the **Sign-in restrictions** section, where you can configure both.
-If you want 2FA enforcement to take effect on next login, change the grace
-period to `0`.
+If you want 2FA enforcement to take effect during the next sign-in attempt,
+change the grace period to `0`.
## Enforcing 2FA for all users in a group
If you want to enforce 2FA only for certain groups, you can:
-1. Enable it in the group's **Settings > General** page. Navigate to **Permissions, LFS, 2FA > Two-factor authentication**.
-You can then check the **Require all users in this group to setup Two-factor authentication** option.
+1. Enable it in the group's **Settings > General** page. Navigate to
+ **Permissions, LFS, 2FA > Two-factor authentication**. You can then select
+ the **Require all users in this group to setup Two-factor authentication**
+ option.
1. You can also specify a grace period in the **Time before enforced** option.
To change this setting, you need to be administrator or owner of the group.
diff --git a/doc/security/unlock_user.md b/doc/security/unlock_user.md
index bf3bbbb701e..4013bfb7cae 100644
--- a/doc/security/unlock_user.md
+++ b/doc/security/unlock_user.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: howto
---
diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md
index 3d7aa3026ab..2e2fb093916 100644
--- a/doc/security/webhooks.md
+++ b/doc/security/webhooks.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: concepts, reference, howto
---
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
index 128e9d07282..a03c8e758de 100644
--- a/doc/subscriptions/gitlab_com/index.md
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: index, reference
---
@@ -54,7 +57,7 @@ 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).
+ [sign up page](https://gitlab.com/users/sign_up).
1. Visit the [billing page](https://gitlab.com/profile/billings)
under your profile.
1. Select the **Bronze**, **Silver**, or **Gold** GitLab.com plan through the
@@ -67,7 +70,7 @@ To subscribe to GitLab.com:
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).
+ [sign up page](https://gitlab.com/users/sign_up).
1. Create a [group](../../user/group/index.md). GitLab groups help assemble related
projects together allowing you to grant members access to several projects
at once. A group is not required if you plan on having projects inside a personal
diff --git a/doc/subscriptions/img/additional_minutes.png b/doc/subscriptions/img/additional_minutes.png
deleted file mode 100644
index b159b98c9ce..00000000000
--- a/doc/subscriptions/img/additional_minutes.png
+++ /dev/null
Binary files differ
diff --git a/doc/subscriptions/img/buy_btn.png b/doc/subscriptions/img/buy_btn.png
deleted file mode 100644
index 4fd05c0fba7..00000000000
--- a/doc/subscriptions/img/buy_btn.png
+++ /dev/null
Binary files differ
diff --git a/doc/subscriptions/img/buy_minutes_card.png b/doc/subscriptions/img/buy_minutes_card.png
deleted file mode 100644
index cab098300cd..00000000000
--- a/doc/subscriptions/img/buy_minutes_card.png
+++ /dev/null
Binary files differ
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
index bc58c9e899d..df71c6bcf31 100644
--- a/doc/subscriptions/index.md
+++ b/doc/subscriptions/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: index, reference
---
@@ -81,7 +84,7 @@ With the [Customers Portal](https://customers.gitlab.com/) you can:
Your personal details are used on invoices. Your email address is used for the Customers Portal
login and license-related email.
-To change your personal details, including name and billing address:
+To change your personal details, including name, billing address, and email address:
1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
1. Select **My account > Account details**.
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index 5f232bd4ed2..a63c2830909 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: index, reference
---
@@ -6,16 +9,23 @@ type: index, reference
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.
+This page covers the details of your GitLab self-managed subscription.
-## Choose a GitLab tier
+## Subscription
+
+The cost of a GitLab self-managed subscription is determined by the following:
+
+- GitLab tier
+- Subscription seats
+
+## 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
+## Subscription seats
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.
@@ -23,14 +33,17 @@ 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 is counted in the subscription, with the following exceptions:
+### Billable users
+
+A _billable user_ counts against the number of subscription seats. Every user is considered a
+billable user, with the following exceptions:
-- [Deactivated](../../user/admin_area/activating_deactivating_users.md#deactivating-a-user), [pending approval](../../user/admin_area/approving_users.md) 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.
+- [Deactivated users](../../user/admin_area/activating_deactivating_users.md#deactivating-a-user) and
+ [blocked users](../../user/admin_area/blocking_unblocking_users.md) don't count as billable users in the current subscription. When they are either deactivated or blocked they release a _billable user_ seat. However, they may
+ count toward overages in the subscribed seat count.
+- Users who are [pending approval](../../user/admin_area/approving_users.md).
- Members with Guest permissions on an Ultimate subscription.
-- GitLab-created service accounts: `Ghost User` and bots (`Support Bot`, [`Project bot users`](../../user/project/settings/project_access_tokens.md#project-bot-users), etc.).
+- GitLab-created service accounts: `Ghost User` and bots (`Support Bot`, [`Project bot users`](../../user/project/settings/project_access_tokens.md#project-bot-users), and so on).
### Users statistics
@@ -39,8 +52,23 @@ and blocked, go to **Admin Area > Overview > Dashboard** and select **Users stat
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.
+### Tips for managing users and subscription seats
+
+Managing the number of users against the number of subscription seats can be a challenge:
+
+- If LDAP integration is enabled, anyone in the configured domain can sign up for a GitLab account.
+ This can result in an unexpected bill at time of renewal.
+- If sign-up is enabled on your instance, anyone who can access the instance can sign up for an
+ account.
+
+GitLab has several features which can help you manage the number of users:
+
+- Enable the [**Require administrator approval for new sign ups**](../../user/admin_area/settings/sign_up_restrictions.md#require-administrator-approval-for-new-sign-ups)
+ option.
+- Enable the [User cap](../../user/admin_area/settings/sign_up_restrictions.md#user-cap)
+ option. **Available in GitLab 13.6 and later**.
+- [Disable new sign-ups](../../user/admin_area/settings/sign_up_restrictions.md), and instead manage new
+ users manually.
## Obtain a subscription
@@ -96,10 +124,10 @@ It's important to regularly review your user accounts, because:
#### 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
+[Billable users](#billable-users). If the billable user
count exceeds the number included in the subscription, known as the number of
_users over license_, you must pay for the excess number of users either before
-renewal, or at the time of renewal. This is also known the _true up_ process.
+renewal, or at the time of renewal. This is also known as 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
@@ -144,7 +172,7 @@ We recommend following these steps during renewal:
| 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. |
+ | Active users | The daily count of 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. |
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index d2bdf935aa1..9f42c96e31b 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
@@ -28,11 +31,18 @@ Your GitLab instance can perform HTTP POST requests on the following events:
- `user_update_for_group`
- `user_update_for_team`
-The triggers for most of these are self-explanatory, but `project_update` and `project_rename` deserve some clarification: `project_update` is fired any time an attribute of a project is changed (name, description, tags, etc.) *unless* the `path` attribute is also changed. In that case, a `project_rename` is triggered instead (so that, for instance, if all you care about is the repository URL, you can just listen for `project_rename`).
+The triggers for most of these are self-explanatory, but `project_update` and
+`project_rename` deserve some clarification: `project_update` is fired any time
+an attribute of a project is changed (including name, description, and tags)
+_unless_ the `path` attribute is also changed. In that case, a `project_rename`
+is triggered instead (so that, for instance, if all you care about is the
+repository URL, you can just listen for `project_rename`).
-`user_failed_login` is sent whenever a **blocked** user attempts to login and denied access.
+`user_failed_login` is sent whenever a _blocked_ user attempts to sign in and is
+denied access.
-System hooks can be used, e.g. for logging or changing information in a LDAP server.
+System hooks can be used, for example, for logging or changing information in an
+LDAP server.
NOTE: **Note:**
We follow the same structure and deprecations as [Webhooks](../user/project/integrations/webhooks.md)
diff --git a/doc/tools/email.md b/doc/tools/email.md
index 69aca200311..41a78f3a68a 100644
--- a/doc/tools/email.md
+++ b/doc/tools/email.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: howto, reference
---
diff --git a/doc/topics/application_development_platform/index.md b/doc/topics/application_development_platform/index.md
index 85741c4b631..c38b067f1f3 100644
--- a/doc/topics/application_development_platform/index.md
+++ b/doc/topics/application_development_platform/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Application Development Platform
The GitLab Application Development Platform refers to the set of GitLab features used to create, configure, and manage
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index 9e37ebb699b..8a876e07791 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Authentication
This page gathers all the resources for the topic **Authentication** within GitLab.
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index 0026cf4d18a..95b6241583f 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Customizing Auto DevOps
While [Auto DevOps](index.md) provides great defaults to get you started, you can customize
@@ -68,7 +74,6 @@ Docker image based on based on the `ruby:alpine` instead of the default `ruby:la
# ... put your stuff here
```
-NOTE: **Note:**
Use Base64 encoding if you need to pass complex values, such as newlines and
spaces. Left unencoded, complex values like these can cause escaping issues
due to how Auto DevOps uses the arguments.
@@ -117,7 +122,6 @@ to `CI_COMMIT_SHA,CI_ENVIRONMENT_NAME`.
RUN --mount=type=secret,id=auto-devops-build-secrets . /run/secrets/auto-devops-build-secrets && $COMMAND
```
-NOTE: **Note:**
When `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` is set, Auto DevOps
enables the experimental [Docker BuildKit](https://docs.docker.com/develop/develop-images/build_enhancements/)
feature to use the `--secret` flag.
@@ -447,7 +451,6 @@ the updated secrets. To update the secrets, either:
- Manually delete running pods to cause Kubernetes to create new pods with updated
secrets.
-NOTE: **Note:**
Variables with multi-line values are not currently supported due to
limitations with the current Auto DevOps scripting environment.
@@ -514,8 +517,7 @@ on the default branch. However, there are cases where you might want to use a
staging environment, and deploy to production manually. For this scenario, the
`STAGING_ENABLED` environment variable was introduced.
-If you define `STAGING_ENABLED`, such as setting `STAGING_ENABLED` to
-`1` as a CI/CD variable, then GitLab automatically deploys the application
+If you define `STAGING_ENABLED` with a non-empty value, then GitLab automatically deploys the application
to a `staging` environment, and creates a `production_manual` job for
you when you're ready to manually deploy to production.
@@ -526,8 +528,7 @@ you when you're ready to manually deploy to production.
You can use a [canary environment](../../user/project/canary_deployments.md) before
deploying any changes to production.
-If you define `CANARY_ENABLED` in your project, such as setting `CANARY_ENABLED` to
-`1` as a CI/CD variable, then two manual jobs are created:
+If you define `CANARY_ENABLED` with a non-empty value, then two manual jobs are created:
- `canary` - Deploys the application to the canary environment.
- `production_manual` - Manually deploys the application to production.
diff --git a/doc/topics/autodevops/img/autodevops_multiple_clusters.png b/doc/topics/autodevops/img/autodevops_multiple_clusters.png
deleted file mode 100644
index f4d101ca921..00000000000
--- a/doc/topics/autodevops/img/autodevops_multiple_clusters.png
+++ /dev/null
Binary files differ
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 1952fadc076..014690c4cdf 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Auto DevOps
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/37115) in GitLab 10.0.
@@ -160,7 +166,7 @@ a base domain of `example.com`, you'd need a DNS entry like:
```
In this case, the deployed applications are served from `example.com`, and `1.2.3.4`
-is the IP address of your load balancer; generally NGINX ([see requirements](#requirements)).
+is the IP address of your load balancer; generally NGINX ([see requirements](requirements.md)).
Setting up the DNS record is beyond the scope of this document; check with your
DNS provider for information.
@@ -177,7 +183,7 @@ See [Auto DevOps requirements for Amazon ECS](requirements.md#auto-devops-requir
## Enabling/Disabling Auto DevOps
-When first using Auto DevOps, review the [requirements](#requirements) to ensure
+When first using Auto DevOps, review the [requirements](requirements.md) to ensure
all the necessary components to make full use of Auto DevOps are available. First-time
users should follow the [quick start guide](quick_start_guide.md).
@@ -401,7 +407,7 @@ If you receive this error, you can do one of the following actions:
database by setting `AUTO_DEVOPS_POSTGRES_DELETE_V1` to a non-empty value and
redeploying.
- DANGER: **Danger:**
+ DANGER: **Warning:**
Deleting the channel 1 PostgreSQL database permanently deletes the existing
channel 1 database and all its data. See
[Upgrading PostgreSQL](upgrading_postgresql.md)
@@ -415,7 +421,7 @@ If you receive this error, you can do one of the following actions:
and persisted by Helm, regardless of whether or not your chart uses the
variable.
-DANGER: **Danger:**
+DANGER: **Warning:**
Setting `POSTGRES_ENABLED` to `false` permanently deletes any existing
channel 1 database for your environment.
@@ -467,6 +473,104 @@ that works for this problem. Follow these steps to use the tool in Auto DevOps:
1. Continue the deployments as usual.
+### Error: error initializing: Looks like "https://kubernetes-charts.storage.googleapis.com" is not a valid chart repository or cannot be reached
+
+As [announced in the official CNCF blogpost](https://www.cncf.io/blog/2020/10/07/important-reminder-for-all-helm-users-stable-incubator-repos-are-deprecated-and-all-images-are-changing-location/),
+the stable Helm chart repository will be deprecated and removed on November 13th, 2020.
+You may encounter this error after that date.
+
+Some GitLab features had dependencies on the stable chart. To mitigate the impact, we changed them
+to use new official repositories or the [Helm Stable Archive repository maintained by GitLab](https://gitlab.com/gitlab-org/cluster-integration/helm-stable-archive).
+Auto Deploy contains [an example fix](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/merge_requests/127).
+
+In Auto Deploy, `v1.0.6+` of `auto-deploy-image` no longer adds the deprecated stable repository to
+the `helm` command. If you use a custom chart and it relies on the deprecated stable repository,
+specify an older `auto-deploy-image` like this example:
+
+```yaml
+include:
+ - template: Auto-DevOps.gitlab-ci.yml
+
+.auto-deploy:
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v1.0.5"
+```
+
+Keep in mind that this approach will eventually stop working when the stable repository is removed,
+so you must eventually fix your custom chart.
+
+To fix your custom chart:
+
+1. In your chart directory, update the `repository` value in your `requirements.yaml` file from :
+
+ ```yaml
+ repository: "https://kubernetes-charts.storage.googleapis.com/"
+ ```
+
+ to:
+
+ ```yaml
+ repository: "https://charts.helm.sh/stable"
+ ```
+
+1. In your chart directory, run `helm dep update .` using the same Helm major version as Auto DevOps.
+1. Commit the changes for the `requirements.yaml` file.
+1. If you previously had a `requirements.lock` file, commit the changes to the file.
+ If you did not previously have a `requirements.lock` file in your chart,
+ you do not need to commit the new one. This file is optional, but when present,
+ it's used to verify the integrity of the downloaded dependencies.
+
+You can find more information in
+[issue #263778, "Migrate PostgreSQL from stable Helm repo"](https://gitlab.com/gitlab-org/gitlab/-/issues/263778).
+
+### Error: release .... failed: timed out waiting for the condition
+
+When getting started with Auto DevOps, you may encounter this error when first
+deploying your application:
+
+```plaintext
+INSTALL FAILED
+PURGING CHART
+Error: release staging failed: timed out waiting for the condition
+```
+
+This is most likely caused by a failed liveness (or readiness) probe attempted
+during the deployment process. By default, these probes are run against the root
+page of the deployed application on port 5000. If your application isn't configured
+to serve anything at the root page, or is configured to run on a specific port
+*other* than 5000, this check fails.
+
+If it fails, you should see these failures within the events for the relevant
+Kubernetes namespace. These events look like the following example:
+
+```plaintext
+LAST SEEN TYPE REASON OBJECT MESSAGE
+3m20s Warning Unhealthy pod/staging-85db88dcb6-rxd6g Readiness probe failed: Get http://10.192.0.6:5000/: dial tcp 10.192.0.6:5000: connect: connection refused
+3m32s Warning Unhealthy pod/staging-85db88dcb6-rxd6g Liveness probe failed: Get http://10.192.0.6:5000/: dial tcp 10.192.0.6:5000: connect: connection refused
+```
+
+To change the port used for the liveness checks, pass
+[custom values to the Helm chart](customize.md#customize-values-for-helm-chart)
+used by Auto DevOps:
+
+1. Create a directory and file at the root of your repository named `.gitlab/auto-deploy-values.yaml`.
+
+1. Populate the file with the following content, replacing the port values with
+ the actual port number your application is configured to use:
+
+ ```yaml
+ service:
+ internalPort: <port_value>
+ externalPort: <port_value>
+ ```
+
+1. Commit your changes.
+
+After committing your changes, subsequent probes should use the newly-defined ports.
+The page that's probed can also be changed by overriding the `livenessProbe.path`
+and `readinessProbe.path` values (shown in the
+[default `values.yaml`](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/blob/master/assets/auto-deploy-app/values.yaml)
+file) in the same fashion.
+
## Development guides
[Development guide for Auto DevOps](../../development/auto_devops.md)
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index 02d9669a9bc..3531035eb67 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Getting started with Auto DevOps
This step-by-step guide will help you use [Auto DevOps](index.md) to
@@ -108,7 +114,6 @@ In this guide, we will install Ingress and Prometheus:
- Prometheus - An open-source monitoring and alerting system used to supervise the
deployed application.
-NOTE: **Note:**
We won't install GitLab Runner in this quick start guide, as this guide uses the
shared runners provided by GitLab.com.
@@ -155,7 +160,8 @@ The jobs are separated into stages:
- **Build** - The application builds a Docker image and uploads it to your project's
[Container Registry](../../user/packages/container_registry/index.md) ([Auto Build](stages.md#auto-build)).
-- **Test** - GitLab runs various checks on the application:
+- **Test** - GitLab runs various checks on the application, but all jobs except `test`
+ are allowed to fail in the test stage:
- The `test` job runs unit and integration tests by detecting the language and
framework ([Auto Test](stages.md#auto-test))
@@ -173,9 +179,6 @@ The jobs are separated into stages:
licenses and is allowed to fail
([Auto License Compliance](stages.md#auto-license-compliance)) **(ULTIMATE)**
- NOTE: **Note:**
- All jobs except `test` are allowed to fail in the test stage.
-
- **Review** - Pipelines on `master` include this stage with a `dast_environment_deploy` job.
To learn more, see [Dynamic Application Security Testing (DAST)](../../user/application_security/dast/index.md).
diff --git a/doc/topics/autodevops/requirements.md b/doc/topics/autodevops/requirements.md
index af98e0a438b..acec7b79d6b 100644
--- a/doc/topics/autodevops/requirements.md
+++ b/doc/topics/autodevops/requirements.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Requirements for Auto DevOps
You can set up Auto DevOps for [Kubernetes](#auto-devops-requirements-for-kubernetes)
@@ -120,11 +126,9 @@ When you trigger a pipeline, if you have Auto DevOps enabled and if you have cor
[entered AWS credentials as environment variables](../../ci/cloud_deployment/index.md#deploy-your-application-to-the-aws-elastic-container-service-ecs),
your application will be deployed to AWS ECS.
-NOTE: **Note:**
[GitLab Managed Apps](../../user/clusters/applications.md) are not available when deploying to AWS ECS.
You must manually configure your application (such as Ingress or Help) on AWS ECS.
-NOTE: **Note:**
If you have both a valid `AUTO_DEVOPS_PLATFORM_TARGET` variable and a Kubernetes cluster tied to your project,
only the deployment to Kubernetes will run.
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index d3f02889a2e..f2d3b78e2b0 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Stages of Auto DevOps
The following sections describe the stages of [Auto DevOps](index.md).
@@ -161,10 +167,7 @@ see the documentation.
> - [Select functionality made available in all tiers](../../user/application_security/secret_detection/#making-secret-detection-available-to-all-gitlab-tiers) in 13.3
Secret Detection uses the
-[Secret Detection Docker image](https://gitlab.com/gitlab-org/security-products/analyzers/secrets) to run Secret Detection on the current code, and checks for leaked secrets. The
-Auto Secret Detection stage runs only on the
-[Ultimate](https://about.gitlab.com/pricing/) tier, and requires
-[GitLab Runner](https://docs.gitlab.com/runner/) 11.5 or above.
+[Secret Detection Docker image](https://gitlab.com/gitlab-org/security-products/analyzers/secrets) to run Secret Detection on the current code, and checks for leaked secrets. Auto Secret Detection requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 or above.
After creating the report, it's uploaded as an artifact which you can later
download and evaluate. The merge request widget also displays any security
@@ -285,7 +288,7 @@ see the documentation.
To use a custom target instead of the auto-deployed review apps,
set a `DAST_WEBSITE` environment variable to the URL for DAST to scan.
-DANGER: **Danger:**
+DANGER: **Warning:**
If [DAST Full Scan](../../user/application_security/dast/index.md#full-scan) is
enabled, GitLab strongly advises **not**
to set `DAST_WEBSITE` to any staging or production environment. DAST Full Scan
@@ -428,7 +431,7 @@ To use Auto Deploy on a Kubernetes 1.16+ cluster:
1. If you are deploying your application for the first time and are using
GitLab 12.9 or 12.10, set `AUTO_DEVOPS_POSTGRES_CHANNEL` to `2`.
-DANGER: **Danger:**
+DANGER: **Warning:**
On GitLab 12.9 and 12.10, opting into
`AUTO_DEVOPS_POSTGRES_CHANNEL` version `2` deletes the version `1` PostgreSQL
database. Follow the [guide to upgrading PostgreSQL](upgrading_postgresql.md)
@@ -668,4 +671,16 @@ To use Auto Monitoring:
## Auto Code Intelligence
-Code Intelligence is powered by [LSIF](https://lsif.dev/) and available for Go at this stage. We'll support more languages as they become available.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216438) in GitLab 13.5.
+
+[GitLab code intelligence](../../user/project/code_intelligence.md) adds
+code navigation features common to interactive development environments (IDE),
+including type signatures, symbol documentation, and go-to definition. It's powered by
+[LSIF](https://lsif.dev/) and available for Auto DevOps projects using Go language only.
+GitLab plans to add support for more languages as more LSIF indexers become available.
+You can follow the [code intelligence epic](https://gitlab.com/groups/gitlab-org/-/epics/4212)
+for updates.
+
+This stage is enabled by default. You can disable it by adding the
+`CODE_INTELLIGENCE_DISABLED` environment variable. Read more about
+[disabling Auto DevOps jobs](../../topics/autodevops/customize.md#disable-jobs).
diff --git a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
index 1aefb6b34df..16536e5b586 100644
--- a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
+++ b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
@@ -71,6 +71,10 @@ The v2 auto-deploy-image contains multiple dependency and architectural changes.
If your Auto DevOps project has an active environment deployed with the v1 `auto-deploy-image`,
please proceed with the following upgrade guide. Otherwise, you can skip this process.
+#### Kubernetes 1.16+
+
+The v2 auto-deploy-image also drops support for Kubernetes 1.15 and lower.
+
#### Helm 3
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/228609) in GitLab 13.4.
diff --git a/doc/topics/autodevops/upgrading_postgresql.md b/doc/topics/autodevops/upgrading_postgresql.md
index bcbc1d914be..a3c9f562f5e 100644
--- a/doc/topics/autodevops/upgrading_postgresql.md
+++ b/doc/topics/autodevops/upgrading_postgresql.md
@@ -1,3 +1,9 @@
+---
+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
+---
+
# Upgrading PostgreSQL for Auto DevOps
Auto DevOps provides an [in-cluster PostgreSQL database](customize.md#postgresql-database-support)
diff --git a/doc/topics/cron/index.md b/doc/topics/cron/index.md
index 851dd6d3f77..2be579b4e98 100644
--- a/doc/topics/cron/index.md
+++ b/doc/topics/cron/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Cron
Cron syntax is used to schedule when jobs should run.
diff --git a/doc/topics/git/git_rebase.md b/doc/topics/git/git_rebase.md
index 6f50dea26dd..c01080400ac 100644
--- a/doc/topics/git/git_rebase.md
+++ b/doc/topics/git/git_rebase.md
@@ -119,7 +119,7 @@ repository, you can run `git remote -v`.
If there are [merge conflicts](#merge-conflicts), Git will prompt you to fix
them before continuing the rebase.
-To learn more, check Git's documentation on [rebasing](ttps://git-scm.com/book/en/v2/Git-Branching-Rebasing)
+To learn more, check Git's documentation on [rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing)
and [rebasing strategies](https://git-scm.com/book/en/v2/Git-Branching-Rebasing).
### Interactive rebase
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index 7235ba07d0a..80014358230 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -114,8 +114,11 @@ See the documentation on [File Locking](../../../user/project/file_lock.md).
## LFS objects in project archives
> - Support for including Git LFS blobs inside [project source downloads](../../../user/project/repository/index.md) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) in GitLab 13.5.
-> - It's [deployed behind a feature flag](../../../user/feature_flags.md), disabled by default.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-lfs-objects-in-project-archives). **(CORE ONLY)**
+> - It was [deployed behind a feature flag](../../../user/feature_flags.md), disabled by default.
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/268409) on GitLab 13.6.
+> - 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-lfs-objects-in-project-archives).
CAUTION: **Warning:**
This feature might not be available to you. Check the **version history** note above for details.
@@ -139,10 +142,10 @@ Technical details about how this works can be found in the [development document
### Enable or disable LFS objects in project archives
-_LFS objects in project archives_ is under development and not ready for production use. It is
-deployed behind a feature flag that is **disabled by default**.
+_LFS objects in project archives_ is under development but ready for production use.
+It is deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can enable it.
+can opt to disable it.
To enable it:
diff --git a/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md b/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
index c62b7e1cc12..d65d52841aa 100644
--- a/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
+++ b/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
@@ -7,7 +7,7 @@ type: reference, howto
# Migration guide from Git Annex to Git LFS
-NOTE: **Note:**
+DANGER: **Deprecated:**
Git Annex support [has been removed](https://gitlab.com/gitlab-org/gitlab/-/issues/1648) in GitLab Enterprise
Edition 9.0 (2017/03/22).
@@ -37,7 +37,6 @@ ones that GitLab developed.
## Migration steps
-NOTE: **Note:**
Since Git Annex files are stored in a sub-directory of the normal repositories
(`.git/annex/objects`) and LFS files are stored outside of the repositories,
they are not compatible as they are using a different scheme. Therefore, the
diff --git a/doc/topics/git/lfs/migrate_to_git_lfs.md b/doc/topics/git/lfs/migrate_to_git_lfs.md
index f0ad7570d87..596b2cb400f 100644
--- a/doc/topics/git/lfs/migrate_to_git_lfs.md
+++ b/doc/topics/git/lfs/migrate_to_git_lfs.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
description: "How to migrate an existing Git repository to Git LFS with BFG."
---
diff --git a/doc/topics/git/partial_clone.md b/doc/topics/git/partial_clone.md
index c976eda688a..58fa6d2f112 100644
--- a/doc/topics/git/partial_clone.md
+++ b/doc/topics/git/partial_clone.md
@@ -91,7 +91,7 @@ Updating files: 100% (28/28), done.
$ cd www-gitlab-com
-$ git sparse-checkout init --clone
+$ git sparse-checkout init --cone
$ git sparse-checkout add data
remote: Enumerating objects: 301, done.
diff --git a/doc/topics/gitlab_flow.md b/doc/topics/gitlab_flow.md
index 8c5a2092a92..32676658bff 100644
--- a/doc/topics/gitlab_flow.md
+++ b/doc/topics/gitlab_flow.md
@@ -250,7 +250,7 @@ Atlassian has a more thorough explanation of the tradeoffs between merging and r
A good way to prevent creating many merge commits is to not frequently merge `master` into the feature branch.
There are three reasons to merge in `master`: utilizing new code, resolving merge conflicts, and updating long-running branches.
-If you need to utilize some code that was introduced in `master` after you created the feature branch, you can often solve this by just cherry-picking a commit.
+If you need to use some code that was introduced in `master` after you created the feature branch, you can often solve this by just cherry-picking a commit.
If your feature branch has a merge conflict, creating a merge commit is a standard way of solving this.
diff --git a/doc/topics/index.md b/doc/topics/index.md
index 3b92bbb55cb..91b1905f1b6 100644
--- a/doc/topics/index.md
+++ b/doc/topics/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Topics
Welcome to Topics! We have organized our content resources into topics
@@ -16,6 +22,3 @@ tutorials, technical overviews, blog posts) and videos.
- [GitLab Installation](../install/README.md)
- [GitLab Pages](../user/project/pages/index.md)
- [Offline GitLab](offline/index.md)
-
-NOTE: **Note:**
-More topics will be available soon.
diff --git a/doc/topics/offline/index.md b/doc/topics/offline/index.md
index a8366659c22..b40f5e92738 100644
--- a/doc/topics/offline/index.md
+++ b/doc/topics/offline/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Offline GitLab
Computers in an offline environment are isolated from the public internet as a security measure. This
diff --git a/doc/topics/offline/quick_start_guide.md b/doc/topics/offline/quick_start_guide.md
index 8b9996cb66f..92f8f9167b7 100644
--- a/doc/topics/offline/quick_start_guide.md
+++ b/doc/topics/offline/quick_start_guide.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Getting started with an offline GitLab Installation
This is a step-by-step guide that helps you install, configure, and use a self-managed GitLab
@@ -7,9 +13,7 @@ instance entirely offline.
NOTE: **Note:**
This guide assumes the server is Ubuntu 18.04. Instructions for other servers may vary.
-
-NOTE: **Note:**
-This guide assumes the server host resolves as `my-host`, which you should replace with your
+This guide also assumes the server host resolves as `my-host`, which you should replace with your
server's name.
Follow the installation instructions [as outlined in the omnibus install
diff --git a/doc/topics/web_application_firewall/index.md b/doc/topics/web_application_firewall/index.md
index 5ce7c0779bb..83b3bfb1cef 100644
--- a/doc/topics/web_application_firewall/index.md
+++ b/doc/topics/web_application_firewall/index.md
@@ -1,5 +1,5 @@
---
-stage: Defend
+stage: Protect
group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
@@ -15,19 +15,14 @@ much more.
## Overview
-GitLab provides a WAF out of the box after Ingress is deployed.
-All you need to do is deploy your application along with a service
-and Ingress resource.
+GitLab provides a WAF out of the box after Ingress is deployed. All you need to do is deploy your
+application along with a service and Ingress resource. In GitLab's [Ingress](../../user/clusters/applications.md#ingress)
+deployment, the [ModSecurity](https://modsecurity.org/)
+module is loaded into Ingress-NGINX by default and monitors the traffic going to the applications
+which have an Ingress. The ModSecurity module runs with the [OWASP Core Rule Set (CRS)](https://coreruleset.org/)
+by default. The OWASP CRS detects and logs a wide range of common attacks.
-In GitLab's [Ingress](../../user/clusters/applications.md#ingress) deployment, the [ModSecurity](https://modsecurity.org/) module is loaded
-into Ingress-NGINX by default and monitors the traffic going to the
-applications which have an Ingress.
-
-The ModSecurity module runs with the [OWASP Core Rule Set (CRS)](https://coreruleset.org/) by default. The OWASP CRS will detect and log a wide range of common attacks.
-
-NOTE: **Note:**
-The WAF is deployed in "Detection-only mode" by default and will only log attack
-attempts.
+By default, the WAF is deployed in Detection-only mode and only logs attack attempts.
## Requirements
@@ -98,5 +93,5 @@ It is good to have a basic knowledge of the following:
## Roadmap
-More information on the direction of the WAF can be
-found in [Product Vision - Defend](https://about.gitlab.com/direction/defend/#waf)
+You can find more information on the product direction of the WAF in
+[Category Direction - Web Application Firewall](https://about.gitlab.com/direction/protect/web_application_firewall/).
diff --git a/doc/topics/web_application_firewall/quick_start_guide.md b/doc/topics/web_application_firewall/quick_start_guide.md
index 971250cd526..3df22854437 100644
--- a/doc/topics/web_application_firewall/quick_start_guide.md
+++ b/doc/topics/web_application_firewall/quick_start_guide.md
@@ -1,5 +1,5 @@
---
-stage: Defend
+stage: Protect
group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
@@ -17,7 +17,7 @@ These instructions will also work for a self-managed GitLab instance. However, y
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),
+GitLab's Web Application Firewall is deployed with [Ingress](../../user/clusters/applications.md#ingress),
so it will be available to your applications no matter how you deploy them to Kubernetes.
## Configuring your Google account
@@ -107,7 +107,7 @@ the scenes. Make sure to switch the toggle to the enabled position before instal
Both logging and blocking modes are available for WAF. While logging mode is useful for
auditing anomalous traffic, blocking mode ensures the traffic doesn't reach past Ingress.
-![Cluster applications](./img/guide_waf_ingress_installation_v12_10.png)
+![Cluster applications](img/guide_waf_ingress_installation_v12_10.png)
After Ingress is installed, wait a few seconds and copy the IP address that
is displayed in order to add in your base **Domain** at the top of the page. For
@@ -252,7 +252,7 @@ You can now see the benefits of a using a Web Application Firewall.
ModSecurity and the OWASP Core Rule Set, offer many more benefits.
You can explore them in more detail:
-- [GitLab Defend Vision](https://about.gitlab.com/direction/defend/#waf)
+- [Category Direction - Web Application Firewall](https://about.gitlab.com/direction/protect/web_application_firewall/)
- [ModSecurity](https://www.modsecurity.org/)
- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/)
- [AutoDevOps](../autodevops/index.md)
diff --git a/doc/university/README.md b/doc/university/README.md
index 6f063e028b5..1448d150a2c 100644
--- a/doc/university/README.md
+++ b/doc/university/README.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
type: index
---
diff --git a/doc/university/training/gitlab_flow.md b/doc/university/training/gitlab_flow.md
index b80eb031aee..ce6ee7e6561 100644
--- a/doc/university/training/gitlab_flow.md
+++ b/doc/university/training/gitlab_flow.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
type: reference
---
diff --git a/doc/university/training/index.md b/doc/university/training/index.md
index 4c54108b4fa..c8613e834b8 100644
--- a/doc/university/training/index.md
+++ b/doc/university/training/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
type: index
---
diff --git a/doc/university/training/topics/agile_git.md b/doc/university/training/topics/agile_git.md
index c5634bec27b..6cd5051261f 100644
--- a/doc/university/training/topics/agile_git.md
+++ b/doc/university/training/topics/agile_git.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/bisect.md b/doc/university/training/topics/bisect.md
index cb6d6e683a8..09274c1ce11 100644
--- a/doc/university/training/topics/bisect.md
+++ b/doc/university/training/topics/bisect.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/cherry_picking.md b/doc/university/training/topics/cherry_picking.md
index 47734834801..04b8f3b9a47 100644
--- a/doc/university/training/topics/cherry_picking.md
+++ b/doc/university/training/topics/cherry_picking.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/env_setup.md b/doc/university/training/topics/env_setup.md
index be517032a1b..cbe2ce46be4 100644
--- a/doc/university/training/topics/env_setup.md
+++ b/doc/university/training/topics/env_setup.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
@@ -6,22 +9,31 @@ comments: false
## Install
-- **Windows**
- - Install 'Git for Windows' from <https://gitforwindows.org>
-
+- **Windows** - Install 'Git for Windows' from [Git for Windows](https://gitforwindows.org).
- **Mac**
- Type '`git`' in the Terminal application.
- If it's not installed, it will prompt you to install it.
-- **Linux**
-
- ```shell
- sudo yum install git-all
- ```
-
- ```shell
- sudo apt-get install git-all
- ```
+- **GNU/Linux** - Enter `which git` in the Terminal application and press <kbd>Enter</kbd> to
+ determine if Git is installed on your system.
+
+ - If the output of that command gives you the path to the Git executable, similar to
+ `/usr/bin/git`, then Git is already installed on your system.
+ - If the output of the command displays "command not found" error, Git isn't installed on your system.
+
+ GitLab recommends installing Git with the default package manager of your distribution.
+ The following commands install Git on various GNU/Linux distributions using their
+ default package managers. After you run the command corresponding to your distribution
+ and complete the installation process, Git should be available on your system:
+
+ - **Arch Linux and its derivatives** - `sudo pacman -S git`
+ - **Fedora, RHEL, and CentOS** - For the `yum` package manager run `sudo yum install git-all`,
+ and for the `dnf` package manager run `sudo dnf install git`.
+ - **Debian/Ubuntu and their derivatives** - `sudo apt-get install git`
+ - **Gentoo** - `sudo emerge --ask --verbose dev-vcs/git`
+ - **openSUSE** - `sudo zypper install git`
+- **FreeBSD** - `sudo pkg install git`
+- **OpenBSD** - `doas pkg_add git`
## Configure Git
diff --git a/doc/university/training/topics/feature_branching.md b/doc/university/training/topics/feature_branching.md
index e7454dbba75..45fad8f1894 100644
--- a/doc/university/training/topics/feature_branching.md
+++ b/doc/university/training/topics/feature_branching.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/getting_started.md b/doc/university/training/topics/getting_started.md
index fd50c5492f1..531d274249a 100644
--- a/doc/university/training/topics/getting_started.md
+++ b/doc/university/training/topics/getting_started.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/git_add.md b/doc/university/training/topics/git_add.md
index a3389af526d..be66b1a14cc 100644
--- a/doc/university/training/topics/git_add.md
+++ b/doc/university/training/topics/git_add.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/git_intro.md b/doc/university/training/topics/git_intro.md
index c9a1cbb7839..1ff436214b2 100644
--- a/doc/university/training/topics/git_intro.md
+++ b/doc/university/training/topics/git_intro.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/git_log.md b/doc/university/training/topics/git_log.md
index 26b389beea9..c62b5ad5a3c 100644
--- a/doc/university/training/topics/git_log.md
+++ b/doc/university/training/topics/git_log.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/merge_conflicts.md b/doc/university/training/topics/merge_conflicts.md
index e59f9e2bae8..87cb119768f 100644
--- a/doc/university/training/topics/merge_conflicts.md
+++ b/doc/university/training/topics/merge_conflicts.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/merge_requests.md b/doc/university/training/topics/merge_requests.md
index ea679a7d66f..bda14dc342e 100644
--- a/doc/university/training/topics/merge_requests.md
+++ b/doc/university/training/topics/merge_requests.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/rollback_commits.md b/doc/university/training/topics/rollback_commits.md
index 616ed972ab0..47f28f8ef89 100644
--- a/doc/university/training/topics/rollback_commits.md
+++ b/doc/university/training/topics/rollback_commits.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/stash.md b/doc/university/training/topics/stash.md
index 28d28382d62..db4a21da6ba 100644
--- a/doc/university/training/topics/stash.md
+++ b/doc/university/training/topics/stash.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/subtree.md b/doc/university/training/topics/subtree.md
index 5b08832084c..779ebab1441 100644
--- a/doc/university/training/topics/subtree.md
+++ b/doc/university/training/topics/subtree.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/topics/tags.md b/doc/university/training/topics/tags.md
index 01eb1dd9b4c..b2b8a085a77 100644
--- a/doc/university/training/topics/tags.md
+++ b/doc/university/training/topics/tags.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
type: reference
---
diff --git a/doc/university/training/topics/unstage.md b/doc/university/training/topics/unstage.md
index b74cc9b2f0a..77aca3cdab8 100644
--- a/doc/university/training/topics/unstage.md
+++ b/doc/university/training/topics/unstage.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/university/training/user_training.md b/doc/university/training/user_training.md
index 43de90010b1..86f397eba41 100644
--- a/doc/university/training/user_training.md
+++ b/doc/university/training/user_training.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
type: reference
---
diff --git a/doc/update/README.md b/doc/update/README.md
index b5e99671278..774d468cb76 100644
--- a/doc/update/README.md
+++ b/doc/update/README.md
@@ -1,28 +1,51 @@
-# Updating GitLab
+---
+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
+---
-Depending on the installation method and your GitLab version, there are multiple
-update guides.
+# Upgrading GitLab
-There are currently 3 official ways to install GitLab:
+Upgrading GitLab is a relatively straightforward process, but the complexity
+can increase based on the installation method you have used, how old your
+GitLab version is, if you're upgrading to a major version, and so on.
-- [Omnibus packages](#omnibus-packages)
-- [Source installation](#installation-from-source)
-- [Docker installation](#installation-using-docker)
+Make sure to read the whole page as it contains information related to every upgrade method.
-Based on your installation, choose a section below that fits your needs.
+The [maintenance policy documentation](../policy/maintenance.md)
+has additional information about upgrading, including:
-## Omnibus Packages
+- How to interpret GitLab product versioning.
+- Recommendations on the what release to run.
+- How we use patch and security patch releases.
+- When we backport code changes.
+
+## Upgrade based on installation method
+
+Depending on the installation method and your GitLab version, there are multiple
+official ways to update GitLab:
-- The [Omnibus update guide](https://docs.gitlab.com/omnibus/update/README.html)
- contains the steps needed to update an Omnibus GitLab package.
+- [Linux packages (Omnibus GitLab)](#linux-packages-omnibus-gitlab)
+- [Source installations](#installation-from-source)
+- [Docker installations](#installation-using-docker)
+- [Kubernetes (Helm) installations](#installation-using-helm)
-## Installation from source
+### Linux packages (Omnibus GitLab)
+
+The [Omnibus update guide](https://docs.gitlab.com/omnibus/update/)
+contains the steps needed to update a package installed by GitLab's official
+repositories.
+
+There are also instructions when you want to
+[update to a specific version](https://docs.gitlab.com/omnibus/update/#multi-step-upgrade-using-the-official-repositories).
+
+### Installation from source
- [Upgrading Community Edition and Enterprise Edition from
source](upgrading_from_source.md) - The guidelines for upgrading Community
Edition and Enterprise Edition from source.
- [Patch versions](patch_versions.md) guide includes the steps needed for a
- patch version, such as 6.2.0 to 6.2.1, and apply to both Community and Enterprise
+ patch version, such as 13.2.0 to 13.2.1, and apply to both Community and Enterprise
Editions.
In the past we used separate documents for the upgrading instructions, but we
@@ -32,82 +55,20 @@ can still be found in the Git repository:
- [Old upgrading guidelines for Community Edition](https://gitlab.com/gitlab-org/gitlab-foss/tree/11-8-stable/doc/update)
- [Old upgrading guidelines for Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/tree/11-8-stable-ee/doc/update)
-## Installation using Docker
+### Installation using Docker
GitLab provides official Docker images for both Community and Enterprise
editions. They are based on the Omnibus package and instructions on how to
update them are in [a separate document](https://docs.gitlab.com/omnibus/docker/README.html).
-## Upgrading without downtime
-
-Starting with GitLab 9.1.0 it's possible to upgrade to a newer major, minor, or
-patch version of GitLab without having to take your GitLab instance offline.
-However, for this to work there are the following requirements:
-
-- You can only upgrade 1 minor release at a time. So from 9.1 to 9.2, not to
- 9.3.
-- You have to use [post-deployment
- migrations](../development/post_deployment_migrations.md) (included in
- zero downtime update steps below).
-- You are using PostgreSQL. Starting from GitLab 12.1, MySQL is not supported.
-- Multi-node GitLab instance. Single-node instances may experience brief interruptions
- [as services restart (Puma in particular)](https://docs.gitlab.com/omnibus/update/README.html#single-node-deployment).
-
-Most of the time you can safely upgrade from a patch release to the next minor
-release if the patch release is not the latest. For example, upgrading from
-9.1.1 to 9.2.0 should be safe even if 9.1.2 has been released. We do recommend
-you check the release posts of any releases between your current and target
-version just in case they include any migrations that may require you to upgrade
-1 release at a time.
-
-Some releases may also include so called "background migrations". These
-migrations are performed in the background by Sidekiq and are often used for
-migrating data. Background migrations are only added in the monthly releases.
-
-Certain major/minor releases may require a set of background migrations to be
-finished. To guarantee this such a release will process any remaining jobs
-before continuing the upgrading procedure. While this won't require downtime
-(if the above conditions are met) we recommend users to keep at least 1 week
-between upgrading major/minor releases, allowing the background migrations to
-finish. The time necessary to complete these migrations can be reduced by
-increasing the number of Sidekiq workers that can process jobs in the
-`background_migration` queue. To see the size of this queue,
-[Check for background migrations before upgrading](#checking-for-background-migrations-before-upgrading).
-
-As a rule of thumb, any database smaller than 10 GB won't take too much time to
-upgrade; perhaps an hour at most per minor release. Larger databases however may
-require more time, but this is highly dependent on the size of the database and
-the migrations that are being performed.
+### Installation using Helm
-### Examples
-
-To help explain this, let's look at some examples.
+GitLab can be deployed into a Kubernetes cluster using Helm.
+Instructions on how to update a cloud-native deployment are in
+[a separate document](https://docs.gitlab.com/charts/installation/upgrade.html).
-**Example 1:** You are running a large GitLab installation using version 9.4.2,
-which is the latest patch release of 9.4. When GitLab 9.5.0 is released this
-installation can be safely upgraded to 9.5.0 without requiring downtime if the
-requirements mentioned above are met. You can also skip 9.5.0 and upgrade to
-9.5.1 once it's released, but you **can not** upgrade straight to 9.6.0; you
-_have_ to first upgrade to a 9.5.x release.
-
-**Example 2:** You are running a large GitLab installation using version 9.4.2,
-which is the latest patch release of 9.4. GitLab 9.5 includes some background
-migrations, and 10.0 will require these to be completed (processing any
-remaining jobs for you). Skipping 9.5 is not possible without downtime, and due
-to the background migrations would require potentially hours of downtime
-depending on how long it takes for the background migrations to complete. To
-work around this you will have to upgrade to 9.5.x first, then wait at least a
-week before upgrading to 10.0.
-
-**Example 3:** You use MySQL as the database for GitLab. Any upgrade to a new
-major/minor release will require downtime. If a release includes any background
-migrations this could potentially lead to hours of downtime, depending on the
-size of your database. To work around this you will have to use PostgreSQL and
-meet the other online upgrade requirements mentioned above.
-
-### Steps
-
-Steps to [upgrade without downtime](https://docs.gitlab.com/omnibus/update/README.html#zero-downtime-updates).
+Use the [version mapping](https://docs.gitlab.com/charts/installation/version_mappings.html)
+from the chart version to GitLab version to determine the [upgrade path](#upgrade-paths).
## Checking for background migrations before upgrading
@@ -130,8 +91,6 @@ puts Sidekiq::Queue.new("background_migration").size
Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size
```
----
-
**For installations from source**
If using GitLab 12.9 and newer, run:
@@ -153,7 +112,6 @@ Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.
CAUTION: **Warning:**
The following operations can disrupt your GitLab performance.
-NOTE: **Note:**
It is safe to re-execute these commands, especially if you have 1000+ pending jobs which would likely overflow your runtime memory.
**For Omnibus installations**
@@ -180,16 +138,123 @@ pending_job_classes = scheduled_queue.select { |job| job["class"] == "Background
pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) }
```
+## Upgrade paths
+
+Although you can generally upgrade through multiple GitLab versions in one go,
+sometimes this can cause issues.
+
+Find where your version sits in the upgrade path below, and upgrade GitLab
+accordingly, while also consulting the
+[version-specific upgrade instructions](#version-specific-upgrading-instructions):
+
+`8.11.x` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.1.11` - > `13.5.3`
+
+The following table, while not exhaustive, shows some examples of the supported
+upgrade paths.
+
+| Target version | Your version | Supported upgrade path | Note |
+| --------------------- | ------------ | ------------------------ | ---- |
+| `13.4.3` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.4.3` | Two intermediate versions are required: the final `12.10` release, plus `13.0`. |
+| `13.2.10` | `11.5.0` | `11.5.0` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.2.10` | Five intermediate versions are required: the final `11.11`, `12.0`, `12.1` and `12.10` releases, plus `13.0`. |
+| `12.10.14` | `11.3.4` | `11.3.4` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` | Three intermediate versions are required: the final `11.11` and `12.0` releases, plus `12.1` |
+| `12.9.5` | `10.4.5` | `10.4.5` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.9.5` | Four intermediate versions are required: `10.8`, `11.11`, `12.0` and `12.1`, then `12.9.5` |
+| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.2.5` | Five intermediate versions are required: `9.5`, `10.8`, `11.11`, `12.0`, `12.1`, then `12.2`. |
+| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version 8, `9.5.10` is the last version in version 9, `10.8.7` is the last version in version 10. |
+
## Upgrading to a new major version
-Major versions are reserved for backwards incompatible changes. We recommend that
-you first upgrade to the latest available minor version within your major version.
-Please follow the [Upgrade Recommendations](../policy/maintenance.md#upgrade-recommendations)
-to identify a supported upgrade path.
+Upgrading the *major* version requires more attention.
+Backward-incompatible changes and migrations are reserved for major versions.
+We cannot guarantee that upgrading between major versions will be seamless.
+It is suggested to upgrade to the latest available *minor* version within
+your major version before proceeding to the next major version.
+Doing this will address any backward-incompatible changes or deprecations
+to help ensure a successful upgrade to the next major release.
+Identify a [supported upgrade path](#upgrade-paths).
+
+More significant migrations may occur during major release upgrades. To ensure these are successful:
-Before upgrading to a new major version, you should ensure that any background
-migration jobs from previous releases have been completed. To see the current size
-of the `background_migration` queue, [check for background migrations before upgrading](#checking-for-background-migrations-before-upgrading).
+1. Increment to the first minor version (`x.0.x`) during the major version jump.
+1. Proceed with upgrading to a newer release.
+
+It's also important to ensure that any background migrations have been fully completed
+before upgrading to a new major version. To see the current size of the `background_migration` queue,
+[Check for background migrations before upgrading](#checking-for-background-migrations-before-upgrading).
+
+If your GitLab instance has any runners associated with it, it is very
+important to upgrade GitLab Runner to match the GitLab minor version that was
+upgraded to. This is to ensure [compatibility with GitLab versions](https://docs.gitlab.com/runner/#compatibility-with-gitlab-versions).
+
+## Upgrading without downtime
+
+Starting with GitLab 9.1.0 it's possible to upgrade to a newer major, minor, or
+patch version of GitLab without having to take your GitLab instance offline.
+However, for this to work there are the following requirements:
+
+- You can only upgrade 1 minor release at a time. So from 9.1 to 9.2, not to
+ 9.3.
+- You have to use [post-deployment
+ migrations](../development/post_deployment_migrations.md) (included in
+ zero downtime update steps below).
+- You are using PostgreSQL. Starting from GitLab 12.1, MySQL is not supported.
+- Multi-node GitLab instance. Single-node instances may experience brief interruptions
+ [as services restart (Puma in particular)](https://docs.gitlab.com/omnibus/update/README.html#single-node-deployment).
+
+Most of the time you can safely upgrade from a patch release to the next minor
+release if the patch release is not the latest. For example, upgrading from
+9.1.1 to 9.2.0 should be safe even if 9.1.2 has been released. We do recommend
+you check the release posts of any releases between your current and target
+version just in case they include any migrations that may require you to upgrade
+1 release at a time.
+
+Some releases may also include so called "background migrations". These
+migrations are performed in the background by Sidekiq and are often used for
+migrating data. Background migrations are only added in the monthly releases.
+
+Certain major/minor releases may require a set of background migrations to be
+finished. To guarantee this such a release will process any remaining jobs
+before continuing the upgrading procedure. While this won't require downtime
+(if the above conditions are met) we recommend users to keep at least 1 week
+between upgrading major/minor releases, allowing the background migrations to
+finish. The time necessary to complete these migrations can be reduced by
+increasing the number of Sidekiq workers that can process jobs in the
+`background_migration` queue. To see the size of this queue,
+[Check for background migrations before upgrading](#checking-for-background-migrations-before-upgrading).
+
+As a rule of thumb, any database smaller than 10 GB won't take too much time to
+upgrade; perhaps an hour at most per minor release. Larger databases however may
+require more time, but this is highly dependent on the size of the database and
+the migrations that are being performed.
+
+### Examples
+
+To help explain this, let's look at some examples.
+
+**Example 1:** You are running a large GitLab installation using version 9.4.2,
+which is the latest patch release of 9.4. When GitLab 9.5.0 is released this
+installation can be safely upgraded to 9.5.0 without requiring downtime if the
+requirements mentioned above are met. You can also skip 9.5.0 and upgrade to
+9.5.1 after it's released, but you **can not** upgrade straight to 9.6.0; you
+_have_ to first upgrade to a 9.5.x release.
+
+**Example 2:** You are running a large GitLab installation using version 9.4.2,
+which is the latest patch release of 9.4. GitLab 9.5 includes some background
+migrations, and 10.0 will require these to be completed (processing any
+remaining jobs for you). Skipping 9.5 is not possible without downtime, and due
+to the background migrations would require potentially hours of downtime
+depending on how long it takes for the background migrations to complete. To
+work around this you will have to upgrade to 9.5.x first, then wait at least a
+week before upgrading to 10.0.
+
+**Example 3:** You use MySQL as the database for GitLab. Any upgrade to a new
+major/minor release will require downtime. If a release includes any background
+migrations this could potentially lead to hours of downtime, depending on the
+size of your database. To work around this you will have to use PostgreSQL and
+meet the other online upgrade requirements mentioned above.
+
+### Steps
+
+Steps to [upgrade without downtime](https://docs.gitlab.com/omnibus/update/README.html#zero-downtime-updates).
## Upgrading between editions
@@ -197,7 +262,7 @@ GitLab comes in two flavors: [Community Edition](https://about.gitlab.com/featur
and [Enterprise Edition](https://about.gitlab.com/features/#enterprise) which builds on top of the Community Edition and
includes extra features mainly aimed at organizations with more than 100 users.
-Below you can find some guides to help you change editions easily.
+Below you can find some guides to help you change GitLab editions.
### Community to Enterprise Edition
@@ -220,7 +285,34 @@ If you need to downgrade your Enterprise Edition installation back to Community
Edition, you can follow [this guide](../downgrade_ee_to_ce/README.md) to make the process as smooth as
possible.
-## Version specific upgrading instructions
+## Version-specific upgrading instructions
+
+Each month, a major or minor release of GitLab is published along with a
+[release post](https://about.gitlab.com/releases/categories/releases/).
+You should check all the major and minor versions you're passing over.
+At the end of those release posts, there are three sections to look for:
+
+- Deprecations
+- Removals
+- Important notes on upgrading
+
+These will include:
+
+- Steps you need to perform as part of an upgrade.
+ For example [8.12](https://about.gitlab.com/releases/2016/09/22/gitlab-8-12-released/#upgrade-barometer)
+ required the Elasticsearch index to be recreated. Any older version of GitLab upgrading to 8.12 or higher would require this.
+- Changes to the versions of software we support such as
+ [ceasing support for IE11 in GitLab 13](https://about.gitlab.com/releases/2020/03/22/gitlab-12-9-released/#ending-support-for-internet-explorer-11).
+
+Apart from the instructions in this section, you should also check the
+installation-specific upgrade instructions, based on how you installed GitLab:
+
+- [Linux packages (Omnibus GitLab)](https://docs.gitlab.com/omnibus/update/README.html#version-specific-changes)
+- [Helm charts](https://docs.gitlab.com/charts/installation/upgrade.html)
+
+### 13.6.0
+
+The required Git version is Git v2.29 or higher.
### 13.3.0
@@ -263,9 +355,9 @@ with the older Rails version - which could cause non-GET requests to
fail for [multi-node GitLab installations](https://docs.gitlab.com/omnibus/update/#multi-node--ha-deployment).
So, if you are using multiple Rails servers and specifically upgrading from 13.0,
-all servers must first be upgraded to 13.1.0 before upgrading to later versions:
+all servers must first be upgraded to 13.1.X before upgrading to 13.2.0 or later:
-1. Ensure all GitLab web nodes are on GitLab 13.1.0.
+1. Ensure all GitLab web nodes are on GitLab 13.1.X.
1. Optionally, enable the `global_csrf_token` feature flag to enable new
method of CSRF token generation:
@@ -283,10 +375,16 @@ automatically upgraded.
However, session cookie downgrades are not supported. So after upgrading to 12.2.0,
any downgrades would result to all sessions being invalidated and users are logged out.
+### 12.1.0
+
+If you are planning to upgrade from `12.0.x` to `12.10.x`, it is necessary to
+perform an intermediary upgrade to `12.1.x` before upgrading to `12.10.x` to
+avoid issues like [#215141](https://gitlab.com/gitlab-org/gitlab/-/issues/215141).
+
### 12.0.0
In 12.0.0 we made various database related changes. These changes require that
-users first upgrade to the latest 11.11 patch release. Once upgraded to 11.11.x,
+users first upgrade to the latest 11.11 patch release. After upgraded to 11.11.x,
users can upgrade to 12.0.x. Failure to do so may result in database migrations
not being applied, which could lead to application errors.
@@ -298,11 +396,17 @@ release for 11.11.x. You can upgrade as usual to 12.0.x.
Example 2: you are currently using a version of GitLab 10.x. To upgrade, first
upgrade to the last 10.x release (10.8.7) then the last 11.x release (11.11.8).
-Once upgraded to 11.11.8 you can safely upgrade to 12.0.x.
+After upgraded to 11.11.8 you can safely upgrade to 12.0.x.
See our [documentation on upgrade paths](../policy/maintenance.md#upgrade-recommendations)
for more information.
+### Upgrades from versions earlier than 8.12
+
+- `8.11.x` and earlier: you might have to upgrade to `8.12.0` specifically before you can upgrade to `8.17.7`. This was [reported in an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/207259).
+- [CI changes prior to version 8.0](https://docs.gitlab.com/omnibus/update/README.html#updating-gitlab-ci-from-prior-540-to-version-714-via-omnibus-gitlab)
+ when it was merged into GitLab.
+
## Miscellaneous
- [MySQL to PostgreSQL](mysql_to_postgresql.md) guides you through migrating
diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md
index 0759d45147a..10c1a5017b5 100644
--- a/doc/update/mysql_to_postgresql.md
+++ b/doc/update/mysql_to_postgresql.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Migrating from MySQL to PostgreSQL
This guide documents how to take a working GitLab instance that uses MySQL and
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index 0092df7b89d..081df16be81 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/update/restore_after_failure.md b/doc/update/restore_after_failure.md
index 2c70e38d041..e35d7bff562 100644
--- a/doc/update/restore_after_failure.md
+++ b/doc/update/restore_after_failure.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Restoring from backup after a failed upgrade
Upgrades are usually smooth and restoring from backup is a rare occurrence.
diff --git a/doc/update/upgrading_from_ce_to_ee.md b/doc/update/upgrading_from_ce_to_ee.md
index f82f5001c89..71d857ce18f 100644
--- a/doc/update/upgrading_from_ce_to_ee.md
+++ b/doc/update/upgrading_from_ce_to_ee.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index a0f042acab2..d2a3466984e 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
@@ -132,7 +135,7 @@ To check you are running the minimum required Git version, see
In Debian or Ubuntu:
```shell
-# Make sure Git is version 2.24.0 or higher
+# Make sure Git is version 2.29.0 or higher
git --version
# Remove packaged Git
@@ -152,9 +155,9 @@ make install
# Download and compile from source
cd /tmp
-curl --remote-name --location --progress https://www.kernel.org/pub/software/scm/git/git-2.28.0.tar.gz
-echo 'f914c60a874d466c1e18467c864a910dd4ea22281ba6d4d58077cb0c3f115170 git-2.28.0.tar.gz' | shasum -a256 -c - && tar -xzf git-2.28.0.tar.gz
-cd git-2.28.0/
+curl --remote-name --location --progress https://www.kernel.org/pub/software/scm/git/git-2.29.0.tar.gz
+echo 'fa08dc8424ef80c0f9bf307877f9e2e49f1a6049e873530d6747c2be770742ff git-2.29.0.tar.gz' | shasum -a256 -c - && tar -xzf git-2.29.0.tar.gz
+cd git-2.29.0/
./configure --with-libpcre
make prefix=/usr/local all
diff --git a/doc/update/upgrading_postgresql_using_slony.md b/doc/update/upgrading_postgresql_using_slony.md
index 5133e4cf4e5..4d8b58cc3af 100644
--- a/doc/update/upgrading_postgresql_using_slony.md
+++ b/doc/update/upgrading_postgresql_using_slony.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Upgrading PostgreSQL Using Slony
This guide describes the steps one can take to upgrade their PostgreSQL database
diff --git a/doc/user/abuse_reports.md b/doc/user/abuse_reports.md
index e6c86cc8f2e..155f45f087f 100644
--- a/doc/user/abuse_reports.md
+++ b/doc/user/abuse_reports.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Abuse reports
You can report abuse from other GitLab users to GitLab administrators.
diff --git a/doc/user/admin_area/activating_deactivating_users.md b/doc/user/admin_area/activating_deactivating_users.md
index 8b3a7682841..96b39ae7116 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/self_managed/index.md#choose-the-number-of-users).
+A deactivated user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users).
## Activating a user
@@ -62,8 +62,8 @@ To do this:
Users can also be activated using the [GitLab API](../../api/users.md#activate-user).
NOTE: **Note:**
-Activating a user will change the user's state to active and it consumes a
-[seat](../../subscriptions/self_managed/index.md#choose-the-number-of-users).
+Activating a user changes the user's state to active and consumes a
+[seat](../../subscriptions/self_managed/index.md#billable-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/dev_ops_report.md b/doc/user/admin_area/analytics/dev_ops_report.md
index f04bd69b76b..d1f80e63c04 100644
--- a/doc/user/admin_area/analytics/dev_ops_report.md
+++ b/doc/user/admin_area/analytics/dev_ops_report.md
@@ -1,4 +1,10 @@
-# DevOps Report
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# DevOps Report **(CORE)**
> - [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.
@@ -10,6 +16,8 @@ The DevOps Report gives you an overview of your entire instance's adoption of
[Concurrent DevOps](https://about.gitlab.com/topics/concurrent-devops/)
from planning to monitoring.
+To see DevOps Report, go to **Admin Area > Analytics > DevOps Report**.
+
## DevOps Score
DevOps Score displays the usage of GitLab's major features on your instance over
diff --git a/doc/user/admin_area/analytics/img/instance_activity_pipelines_chart_v13_6.png b/doc/user/admin_area/analytics/img/instance_activity_pipelines_chart_v13_6.png
new file mode 100644
index 00000000000..da9e4c64e12
--- /dev/null
+++ b/doc/user/admin_area/analytics/img/instance_activity_pipelines_chart_v13_6.png
Binary files differ
diff --git a/doc/user/admin_area/analytics/index.md b/doc/user/admin_area/analytics/index.md
index f79245c7325..792d0245290 100644
--- a/doc/user/admin_area/analytics/index.md
+++ b/doc/user/admin_area/analytics/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Instance-level analytics
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41416) in GitLab 11.2.
@@ -6,6 +12,6 @@ Administrators have access to instance-wide analytics, as shown in **Admin Area
There are several kinds of statistics:
-- [DevOps Report](dev_ops_report.md): Provides an overview of your entire instance's feature usage.
-- [Instance Statistics](instance_statistics.md): Shows how much data your instance contains, and how that is changing.
-- [User Cohorts](user_cohorts.md): Display the monthly cohorts of new users and their activities over time.
+- [DevOps Report](dev_ops_report.md): Provides an overview of your entire instance's feature usage. **(CORE)**
+- [Instance Statistics](instance_statistics.md): Shows how much data your instance contains, and how that is changing. **(CORE)**
+- [User Cohorts](user_cohorts.md): Display the monthly cohorts of new users and their activities over time. **(CORE)**
diff --git a/doc/user/admin_area/analytics/instance_statistics.md b/doc/user/admin_area/analytics/instance_statistics.md
index bac0e845d2c..0d62d30435d 100644
--- a/doc/user/admin_area/analytics/instance_statistics.md
+++ b/doc/user/admin_area/analytics/instance_statistics.md
@@ -1,9 +1,23 @@
-# Instance Statistics
+---
+stage: Manage
+group: Value Stream 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
+---
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235754) in GitLab 13.4.
+# Instance Statistics **(CORE)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235754) in GitLab 13.5 behind a feature flag, disabled by default.
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46962) in GitLab 13.6.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
Instance Statistics gives you an overview of how much data your instance contains, and how quickly this volume is changing over time.
+To see Instance Statistics, go to **Admin Area > Analytics > Instance Statistics**.
+
## Total counts
At the top of the page, Instance Statistics shows total counts for:
@@ -16,3 +30,31 @@ At the top of the page, Instance Statistics shows total counts for:
- Pipelines
These figures can be useful for understanding how much data your instance contains in total.
+
+## Past year trend charts
+
+Instance Statistics also displays line charts that show total counts per month, over the past 12 months,
+in the categories shown in [Total counts](#total-counts).
+
+These charts help you visualize how rapidly these records are being created on your instance.
+
+![Instance Activity Pipelines chart](img/instance_activity_pipelines_chart_v13_6.png)
+
+### Enable or disable Instance Statistics
+
+In GitLab version 13.5 only, Instance Statistics was under development and not ready for production use.
+It was deployed behind a feature flag that was **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can opt to enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:instance_statistics)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:instance_statistics)
+```
diff --git a/doc/user/admin_area/analytics/user_cohorts.md b/doc/user/admin_area/analytics/user_cohorts.md
index faf8caa7e00..c9b62e258ae 100644
--- a/doc/user/admin_area/analytics/user_cohorts.md
+++ b/doc/user/admin_area/analytics/user_cohorts.md
@@ -1,10 +1,18 @@
-# Cohorts
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# Cohorts **(CORE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/23361) in GitLab 9.1.
As a benefit of having the [usage ping active](../settings/usage_statistics.md),
GitLab lets you analyze the users' activities over time of your GitLab installation.
+To see User Cohorts, go to **Admin Area > Analytics > Cohorts**.
+
## Overview
How do we read the user cohorts table? Let's take an example with the following
diff --git a/doc/user/admin_area/appearance.md b/doc/user/admin_area/appearance.md
index 55dabce7342..23a6de38e17 100644
--- a/doc/user/admin_area/appearance.md
+++ b/doc/user/admin_area/appearance.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: howto
disqus_identifier: 'https://docs.gitlab.com/ee/customization/branded_login_page.html'
---
@@ -76,7 +79,7 @@ to activate it in the GitLab instance. You can also click on the **Sign-in page*
to review the saved appearance settings:
NOTE: **Note:**
-You can add also add a [customized help message](settings/help_page.md) below the sign in message.
+You can add also add a [customized help message](settings/help_page.md) below the sign in message or add [a Sign in text message](settings/sign_in_restrictions.md#sign-in-information).
## New project pages
diff --git a/doc/user/admin_area/approving_users.md b/doc/user/admin_area/approving_users.md
index 486d0b6a25d..430ad4f8899 100644
--- a/doc/user/admin_area/approving_users.md
+++ b/doc/user/admin_area/approving_users.md
@@ -9,7 +9,7 @@ type: howto
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4491) in GitLab 13.5.
-When [Require admin approval for new sign-ups](settings/sign_up_restrictions.md#require-admin-approval-for-new-sign-ups) is enabled, any user that signs up for an account using the registration form is placed under a **Pending approval** state.
+When [Require admin approval for new sign-ups](settings/sign_up_restrictions.md#require-administrator-approval-for-new-sign-ups) is enabled, any user that signs up for an account using the registration form is placed under a **Pending approval** state.
A user pending approval is functionally identical to a [blocked](blocking_unblocking_users.md) user.
@@ -18,7 +18,7 @@ A user pending approval:
- Will not be able to sign in.
- Cannot access Git repositories or the API.
- Will not receive any notifications from GitLab.
-- Does not consume a [seat](../../subscriptions/self_managed/index.md#choose-the-number-of-users).
+- Does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users).
## Approving a user
@@ -33,4 +33,4 @@ Approving a user:
1. Activates their account.
1. Changes the user's state to active and it consumes a
-[seat](../../subscriptions/self_managed/index.md#choose-the-number-of-users).
+[seat](../../subscriptions/self_managed/index.md#billable-users).
diff --git a/doc/user/admin_area/blocking_unblocking_users.md b/doc/user/admin_area/blocking_unblocking_users.md
index d8dde317d38..989182db423 100644
--- a/doc/user/admin_area/blocking_unblocking_users.md
+++ b/doc/user/admin_area/blocking_unblocking_users.md
@@ -23,17 +23,17 @@ or directly from the Admin Area. To do this:
A blocked user:
-- Will not be able to login.
+- Cannot log in.
- Cannot access Git repositories or the API.
-- Will not receive any notifications from GitLab.
-- Will not be able to use [slash commands](../../integration/slash_commands.md).
+- Does not receive any notifications from GitLab.
+- Cannot use [slash commands](../../integration/slash_commands.md).
-Personal projects, and group and user history of the blocked user will be left intact.
+Personal projects, and group and user history of the blocked user are left intact.
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/self_managed/index.md#choose-the-number-of-users).
+A blocked user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users).
## Unblocking a user
@@ -47,5 +47,5 @@ A blocked user can be unblocked from the Admin Area. To do this:
Users can also be unblocked using the [GitLab API](../../api/users.md#unblock-user).
NOTE: **Note:**
-Unblocking a user will change the user's state to active and it consumes a
-[seat](../../subscriptions/self_managed/index.md#choose-the-number-of-users).
+Unblocking a user changes the user's state to active and consumes a
+[seat](../../subscriptions/self_managed/index.md#billable-users).
diff --git a/doc/user/admin_area/broadcast_messages.md b/doc/user/admin_area/broadcast_messages.md
index 7e1a4faee75..0bbdf5bc5e7 100644
--- a/doc/user/admin_area/broadcast_messages.md
+++ b/doc/user/admin_area/broadcast_messages.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference, howto
---
@@ -62,12 +65,17 @@ To add a broadcast message:
1. Navigate to the **Admin Area > Messages** page.
1. Add the text for the message to the **Message** field. Markdown and emoji are supported.
-1. If required, click the **Customize colors** link to edit the background color and font color of the message.
+1. Select one of the suggested background colors, or add the hex code of a different color. The default color is orange.
1. If required, add a **Target Path** to only show the broadcast message on URLs matching that path. You can use the wildcard character `*` to match multiple URLs, for example `/users/*/issues`.
1. Select a date for the message to start and end.
1. Click the **Add broadcast message** button.
NOTE: **Note:**
+The **Background color** field expects the value to be a hexadecimal code because
+the form uses the [color_field](https://api.rubyonrails.org/v6.0.3.4/classes/ActionView/Helpers/FormHelper.html#method-i-color_field)
+helper method, which generates the proper HTML to render.
+
+NOTE: **Note:**
Once a broadcast message has expired, it is no longer displayed in the UI but is still listed in the
list of broadcast messages. User can also dismiss a broadcast message if the option **Dismissable** is set.
diff --git a/doc/user/admin_area/credentials_inventory.md b/doc/user/admin_area/credentials_inventory.md
index b17d0ab3dd5..fc04f9786b6 100644
--- a/doc/user/admin_area/credentials_inventory.md
+++ b/doc/user/admin_area/credentials_inventory.md
@@ -40,10 +40,13 @@ If you see a **Revoke** button, you can revoke that user's PAT. Whether you see
| Revoked | Yes | No | Not applicable; token is already revoked |
| Revoked | No | No | Not applicable; token is already revoked |
+When a PAT is revoked from the credentials inventory, the instance notifies the user by email.
+
## Delete a user's SSH key
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225248) in GitLab 13.5.
You can **Delete** a user's SSH key by navigating to the credentials inventory's SSH Keys tab.
+The instance then notifies the user.
![Credentials inventory page - SSH keys](img/credentials_inventory_ssh_keys_v13_5.png)
diff --git a/doc/user/admin_area/img/appearance_sign_in_preview_v12_3.png b/doc/user/admin_area/img/appearance_sign_in_preview_v12_3.png
index 59c190393d1..d05bda71545 100644
--- a/doc/user/admin_area/img/appearance_sign_in_preview_v12_3.png
+++ b/doc/user/admin_area/img/appearance_sign_in_preview_v12_3.png
Binary files differ
diff --git a/doc/user/admin_area/img/appearance_sign_in_v12_3.png b/doc/user/admin_area/img/appearance_sign_in_v12_3.png
index 7e2337bbae8..0caa29aae2c 100644
--- a/doc/user/admin_area/img/appearance_sign_in_v12_3.png
+++ b/doc/user/admin_area/img/appearance_sign_in_v12_3.png
Binary files differ
diff --git a/doc/user/admin_area/img/mr_approval_settings_compliance_project_v13_1.png b/doc/user/admin_area/img/mr_approval_settings_compliance_project_v13_1.png
deleted file mode 100644
index 04d01f2662f..00000000000
--- a/doc/user/admin_area/img/mr_approval_settings_compliance_project_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/img/scope_mr_approval_settings_v13_1.png b/doc/user/admin_area/img/scope_mr_approval_settings_v13_1.png
deleted file mode 100644
index fe85d567a57..00000000000
--- a/doc/user/admin_area/img/scope_mr_approval_settings_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index 0ddbe17580a..fd8c72ad081 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
@@ -143,22 +146,16 @@ you must provide the complete email address.
#### Users statistics
-The **Users statistics** page provides an overview of user accounts by role, such as _Users with
-highest role Maintainer_.
+The **Users statistics** page provides an overview of user accounts by role. These statistics are
+calculated daily, so user changes made since the last update are not reflected.
The following totals are also included:
-- Active users
+- Billable users
- Blocked users
- Total users
-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/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
-reflected in the statistics.
+GitLab billing is based on the number of [**Billable users**](../../subscriptions/self_managed/index.md#billable-users).
### Administering Groups
diff --git a/doc/user/admin_area/license.md b/doc/user/admin_area/license.md
index c37a61d6748..2b0496b381a 100644
--- a/doc/user/admin_area/license.md
+++ b/doc/user/admin_area/license.md
@@ -8,14 +8,22 @@ type: howto
# Activate GitLab EE with a license **(STARTER ONLY)**
To activate all GitLab Enterprise Edition (EE) functionality, you need to upload
-a license. After you've received your license from GitLab Inc., you can upload it
-by **signing into your GitLab instance as an admin** or adding it at
-installation time.
+a license. It's only possible to activate GitLab Enterprise Edition, so first verify which edition
+you are running. To verify, sign in to GitLab and browse to `/help`. The GitLab edition and version
+are listed at the top of the **Help** page.
+
+If you are running GitLab Community Edition (CE), upgrade your installation to
+GitLab Enterprise Edition (EE). For more details, see [Upgrading between editions](../../update/README.md#upgrading-between-editions).
+If you have questions or need assistance upgrading from GitLab CE to EE please [contact GitLab Support](https://about.gitlab.com/support/#contact-support).
The license is a base64-encoded ASCII text file with a `.gitlab-license`
extension. You can obtain the file by [purchasing a license](https://about.gitlab.com/pricing/)
or by signing up for a [free trial](https://about.gitlab.com/free-trial/).
+After you've received your license from GitLab Inc., you can upload it
+by **signing into your GitLab instance as an admin** or adding it at
+installation time.
+
As of GitLab Enterprise Edition 9.4.0, a newly-installed instance without an
uploaded license only has the Core features active. A trial license
activates all Ultimate features, but after
@@ -108,8 +116,9 @@ To remove a license from a self-managed instance:
## License history
-You can upload and view more than one license,
-but only the latest license is used as the active license.
+You can upload and view more than one license, but only the latest license in the current date
+range is used as the active license. When you upload a future-dated license, it
+doesn't take effect until its applicable date.
## Troubleshooting
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
index 2a38ccb31f0..88c98248435 100644
--- a/doc/user/admin_area/monitoring/health_check.md
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: concepts, howto
---
diff --git a/doc/user/admin_area/settings/account_and_limit_settings.md b/doc/user/admin_area/settings/account_and_limit_settings.md
index 957f84206e9..97c74483cc3 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -18,6 +18,12 @@ If you choose a size larger than what is currently configured for the web server
you will likely get errors. See the [troubleshooting section](#troubleshooting) for more
details.
+## Max push size
+
+You can change the maximum push size for your repository.
+Navigate to **Admin Area (wrench icon) > Settings > General**, then expand **Account and Limit**.
+From here, you can increase or decrease by changing the value in `Maximum push size (MB)`.
+
## Max import size
You can change the maximum file size for imports in GitLab.
@@ -76,12 +82,13 @@ and **will** be rejected if the sum of their sizes exceeds the maximum allowed
repository size.
NOTE: **Note:**
-The repository size limit includes repository files and LFS, and does not include artifacts.
+The repository size limit includes repository files and LFS, but does not include artifacts, uploads,
+wiki, packages, or snippets.
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#account-and-limit-settings).
+For GitLab.com repository size limits, see [accounts and limit settings](../../gitlab_com/index.md#account-and-limit-settings).
## Troubleshooting
diff --git a/doc/user/admin_area/settings/external_authorization.md b/doc/user/admin_area/settings/external_authorization.md
index 0b250e07412..80bca6f5b2c 100644
--- a/doc/user/admin_area/settings/external_authorization.md
+++ b/doc/user/admin_area/settings/external_authorization.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/user/admin_area/settings/help_page.md b/doc/user/admin_area/settings/help_page.md
index ca983edd4fa..c0237c3da73 100644
--- a/doc/user/admin_area/settings/help_page.md
+++ b/doc/user/admin_area/settings/help_page.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: howto
---
diff --git a/doc/user/admin_area/settings/img/custom_sign_in_page_v13_6.png b/doc/user/admin_area/settings/img/custom_sign_in_page_v13_6.png
new file mode 100644
index 00000000000..5eb2134187a
--- /dev/null
+++ b/doc/user/admin_area/settings/img/custom_sign_in_page_v13_6.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/disable_signup_v12_7.png b/doc/user/admin_area/settings/img/disable_signup_v12_7.png
deleted file mode 100644
index be1a070a804..00000000000
--- a/doc/user/admin_area/settings/img/disable_signup_v12_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/settings/img/respond_to_terms.png b/doc/user/admin_area/settings/img/respond_to_terms.png
index d0d086c3498..f91480d1ce7 100644
--- a/doc/user/admin_area/settings/img/respond_to_terms.png
+++ b/doc/user/admin_area/settings/img/respond_to_terms.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/sign_up_restrictions_v13_5.png b/doc/user/admin_area/settings/img/sign_up_restrictions_v13_5.png
deleted file mode 100644
index ebbfad77e69..00000000000
--- a/doc/user/admin_area/settings/img/sign_up_restrictions_v13_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index bc8df63e33f..21d495de5b7 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: index
---
@@ -20,7 +23,7 @@ Access the default page for admin area settings by navigating to **Admin Area >
| [Account and limit](account_and_limit_settings.md) **(STARTER)** | Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan. |
| [Diff limits](../diff_limits.md) | Diff content limits. |
| [Sign-up restrictions](sign_up_restrictions.md) | Configure the way a user creates a new account. |
-| [Sign in restrictions](sign_in_restrictions.md) | Set requirements for a user to sign-in. Enable mandatory two-factor authentication. |
+| [Sign in restrictions](sign_in_restrictions.md) | Set requirements for a user to sign in. Enable mandatory two-factor authentication. |
| [Terms of Service and Privacy Policy](terms.md) | Include a Terms of Service agreement and Privacy Policy that all users must accept. |
| [External Authentication](external_authorization.md#configuration) | External Classification Policy Authorization |
| [Web terminal](../../../administration/integration/terminal.md#limiting-websocket-connection-time) | Set max session time for web terminal. |
diff --git a/doc/user/admin_area/settings/project_integration_management.md b/doc/user/admin_area/settings/project_integration_management.md
index 748d608676d..c09bb6f3c67 100644
--- a/doc/user/admin_area/settings/project_integration_management.md
+++ b/doc/user/admin_area/settings/project_integration_management.md
@@ -8,51 +8,87 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Project integrations can be configured and enabled by project administrators. As a GitLab instance
administrator, you can set default configuration parameters for a given integration that all projects
-can inherit and use. This enables the integration for all projects that are not already using custom
+can inherit and use, enabling the integration for all projects that are not already using custom
settings.
You can update these default settings at any time, changing the settings used for all projects that
-are set to use instance-level defaults. Updating the default settings also enables the integration
+are set to use instance-level or group-level defaults. Updating the default settings also enables the integration
for all projects that didn't have it already enabled.
-Only the complete settings for an integration can be inherited. Per-field inheritance is
-[planned](https://gitlab.com/groups/gitlab-org/-/epics/2137) as is
-[group-level management](https://gitlab.com/groups/gitlab-org/-/epics/2543) of integration settings.
+Only the complete settings for an integration can be inherited. Per-field inheritance is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137).
## Manage instance-level default settings for a project integration **(CORE ONLY)**
-> [Introduced in](https://gitlab.com/groups/gitlab-org/-/epics/2137) GitLab 13.3.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2137) in GitLab 13.3 for project-level integrations.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6 for group-level integrations.
1. Navigate to **Admin Area > Settings > Integrations**.
-1. Select a project integration.
+1. Select an integration.
1. Enter configuration details and click **Save changes**.
CAUTION: **Caution:**
-This may affect all or most of the projects on your GitLab instance. Please review the details
+This may affect all or most of the groups and projects on your GitLab instance. Please review the details
below.
If this is the first time you are setting up instance-level settings for an integration:
-- The integration is enabled for all projects that don't already have this integration configured,
+- The integration is enabled for all groups and projects that don't already have this integration configured,
if you have the **Enable integration** toggle turned on in the instance-level settings.
-- Projects that already have the integration configured are not affected, but can choose to use the
+- Groups and projects that already have the integration configured are not affected, but can choose to use the
inherited settings at any time.
When you make further changes to the instance defaults:
-- They are immediately applied to all projects that have the integration set to use default settings.
-- They are immediately applied to newer projects, created since you last saved defaults for the
+- They are immediately applied to all groups and projects that have the integration set to use default settings.
+- They are immediately applied to newer groups and projects, created since you last saved defaults for the
integration. If your instance-level default setting has the **Enable integration** toggle turned
- on, the integration is automatically enabled for all such projects.
-- Projects with custom settings selected for the integration are not immediately affected and may
+ on, the integration is automatically enabled for all such groups and projects.
+- Groups and projects with custom settings selected for the integration are not immediately affected and may
choose to use the latest defaults at any time.
Only the complete settings for an integration can be inherited. Per-field inheritance
is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137). This would allow
-administrators to update settings inherited by projects without enabling the
-integration on all non-configured projects by default.
+administrators to update settings inherited by groups and projects without enabling the
+integration on all non-configured groups and projects by default.
-## Use instance-level default settings for a project integration
+## Manage group-level default settings for a project integration
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6.
+
+1. Navigate to the group's **Settings > Integrations**.
+1. Select an integration.
+1. Enter configuration details and click **Save changes**.
+
+CAUTION: **Caution:**
+This may affect all or most of the subgroups and projects belonging to the group. Please review the details below.
+
+If this is the first time you are setting up group-level settings for an integration:
+
+- The integration is enabled for all subgroups and projects belonging to the group that don't already have
+ this integration configured, if you have the **Enable integration** toggle turned on in the group-level
+ settings.
+- Subgroups and projects that already have the integration configured are not affected, but can choose to use
+ the inherited settings at any time.
+
+When you make further changes to the group defaults:
+
+- They are immediately applied to all subgroups and projects belonging to the group that have the integration
+ set to use default settings.
+- They are immediately applied to newer subgroups and projects, created since you last saved defaults for the
+ integration. If your group-level default setting has the **Enable integration** toggle turned on,
+ the integration is automatically enabled for all such subgroups and projects.
+
+- Subgroups and projects with custom settings selected for the integration are not immediately affected and
+ may choose to use the latest defaults at any time.
+
+Only the complete settings for an integration can be inherited. Per-field inheritance
+is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137). This would allow
+administrators to update settings inherited by subgroups and projects without enabling the
+integration on all non-configured groups and projects by default.
+
+## Use instance-level or group-level default settings for a project integration
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6 for group-level settings.
1. Navigate to **Project > Settings > Integrations**.
1. Choose the integration you want to enable or update.
@@ -60,9 +96,9 @@ integration on all non-configured projects by default.
1. Ensure the toggle is set to **Enable integration**.
1. Click **Save changes**.
-## Use custom settings for a project integration
+## Use custom settings for a group or project integration
-1. Navigate to project's **Settings > Integrations**.
+1. Navigate to project or group's **Settings > Integrations**.
1. Choose the integration you want to enable or update.
1. From the drop-down, select **Use custom settings**.
1. Ensure the toggle is set to **Enable integration** and enter all required settings.
diff --git a/doc/user/admin_area/settings/protected_paths.md b/doc/user/admin_area/settings/protected_paths.md
index 0cfaf5843d0..bb6fff9650d 100644
--- a/doc/user/admin_area/settings/protected_paths.md
+++ b/doc/user/admin_area/settings/protected_paths.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md b/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
index 45dcc9119ac..96cd71033d0 100644
--- a/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
+++ b/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/user/admin_area/settings/sign_in_restrictions.md b/doc/user/admin_area/settings/sign_in_restrictions.md
index 311b79af7e3..7ab1d396e8b 100644
--- a/doc/user/admin_area/settings/sign_in_restrictions.md
+++ b/doc/user/admin_area/settings/sign_in_restrictions.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
@@ -47,8 +50,21 @@ All users that are not logged-in will be redirected to the page represented by t
All users will be redirect to the page represented by the configured "After sign out path"
after sign out if value is not empty.
-If a "Sign in text" in Markdown format is provided, then every user will be presented with
-this message after logging-in.
+In the Sign-in restrictions section, scroll to the "Sign-in text" text box. You can add a
+custom message for your users in Markdown format.
+
+For example, if you include the following information in the noted text box:
+
+```markdown
+# Custom sign-in text
+
+To access this text box, navigate to Admin Area > Settings > General, and expand the "Sign-in restrictions" section.
+```
+
+Your users will see the "Custom sign-in text" when they navigate to the sign-in screen for your
+GitLab instance:
+
+![Sign-in page](img/custom_sign_in_page_v13_6.png)
<!-- ## Troubleshooting
diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md
index f57cf7c2045..5ea034ff4d2 100644
--- a/doc/user/admin_area/settings/sign_up_restrictions.md
+++ b/doc/user/admin_area/settings/sign_up_restrictions.md
@@ -1,52 +1,75 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
# Sign-up restrictions **(CORE ONLY)**
-You can use sign-up restrictions to:
+You can enforce the following restrictions on sign ups:
-- Disable new sign-ups.
-- Require admin approval for new sign-ups.
+- Disable new sign ups.
+- Require administrator approval for new sign ups.
- Require user email confirmation.
-- Denylist or allowlist email addresses belonging to specific domains.
+- Allow or deny sign ups using specific email domains.
-NOTE: **Note:**
-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 sign ups
-## Disable new signups
+By default, any user visiting your GitLab domain can sign up for an account. 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.
-When this setting is enabled, any user visiting your GitLab domain will be able to sign up for an account.
+To disable sign ups:
-![Disable signups](img/disable_signup_v12_7.png)
+1. Go to **Admin Area > Settings > General** and expand **Sign-up restrictions**.
+1. Clear the **Sign-up enabled** checkbox, then select **Save changes**.
-You can restrict new users from signing up by themselves for an account in your instance by disabling this setting.
+## Require administrator approval for new sign ups
-### Recommendations
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4491) in GitLab 13.5.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/267568) in GitLab 13.6.
-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.
+When this setting is enabled, any user visiting your GitLab domain and signing up for a new account must be explicitly [approved](../approving_users.md#approving-a-user) by an administrator before they can start using their account. This setting is enabled by default for newly created instances. This setting is only applicable if sign ups are enabled.
-Alternatively, you could also consider setting up a
-[allowlist](#allowlist-email-domains) or [denylist](#denylist-email-domains) on
-email domains to prevent malicious users from creating accounts.
+To require administrator approval for new sign ups:
-## Require admin approval for new sign-ups
+1. Go to **Admin Area > Settings > General** and expand **Sign-up restrictions**.
+1. Select the **Require admin approval for new sign-ups** checkbox, then select **Save changes**.
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4491) in GitLab 13.5.
+## Require email confirmation
-When this setting is enabled, any user visiting your GitLab domain and signing up for a new account will have to be explicitly [approved](../approving_users.md#approving-a-user) by an administrator before they can start using their account.
+You can send confirmation emails during sign up and require that users confirm
+their email address before they are allowed to sign in.
-![Require admin approval for new signups](img/sign_up_restrictions_v13_5.png)
+To enforce confirmation of the email address used for new sign ups:
-## Require email confirmation
+1. Go to **Admin Area > Settings > General** and expand **Sign-up restrictions**.
+1. Select the **Enable email restrictions for sign ups** checkbox, then select **Save changes**.
-You can send confirmation emails during sign-up and require that users confirm
-their email address before they are allowed to sign in.
+## User cap **(CORE ONLY)**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4315) in GitLab 13.6.
-![Email confirmation](img/sign_up_restrictions_v13_5.png)
+When the number of users reaches the user cap, any user who is added or requests access must be
+[approved](../approving_users.md#approving-a-user) by an administrator before they can start using
+their account.
+
+## Soft email confirmation
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47003) in GitLab 12.2.
+> - It's [deployed behind a feature flag](../../..//user/feature_flags.md), disabled by default.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-soft-email-confirmation).
+
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+The soft email confirmation improves the signup experience for new users by allowing
+them to sign in without an immediate confirmation when an email confirmation is required.
+GitLab shows the user a reminder to confirm their email address, and the user can't
+create or update pipelines until their email address is confirmed.
## Minimum password length limit
@@ -55,40 +78,61 @@ 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.
-## Allowlist email domains
+## Allow or deny sign ups using specific email domains
+
+You can specify an inclusive or exclusive list of email domains which can be used for user sign up.
+
+These restrictions are only applied during sign up from an external user. An administrator can add a
+user through the admin panel with a disallowed domain. Also, note that the users can change their
+email addresses to disallowed domains after sign up.
+
+### Allowlist email domains
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/598) in GitLab 7.11.0
You can restrict users only to sign up using email addresses matching the given
domains list.
-## Denylist email domains
+### Denylist email domains
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5259) in GitLab 8.10.
-With this feature enabled, you can block email addresses of a specific domain
-from creating an account on your GitLab server. This is particularly useful
-to prevent malicious users from creating spam accounts with disposable email
-addresses.
-
-## Settings
+You can block users from signing up when using an email addresses of specific domains. This can
+reduce the risk of malicious users creating spam accounts with disposable email addresses.
-To access this feature:
+### Create email domain allowlist or denylist
-1. Navigate to the **Admin Area > Settings > General**.
-1. Expand the **Sign-up restrictions** section.
+To create an email domain allowlist or denylist:
-For the denylist, you can enter the list manually or upload a `.txt` file that
-contains list entries.
+1. Go to **Admin Area > Settings > General** and expand **Sign-up restrictions**.
+1. For the allowlist, you must enter the list manually. For the denylist, you can enter the list
+ manually or upload a `.txt` file that contains list entries.
-For the allowlist, you must enter the list manually.
-
-Both the allowlist and denylist 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,
+domains ending in `.io`. Domains must be separated by a whitespace,
semicolon, comma, or a new line.
-![Domain Denylist](img/domain_denylist.png)
+ ![Domain Denylist](img/domain_denylist.png)
+
+### Enable or disable soft email confirmation
+
+Soft email confirmation is under development but ready for production use.
+It is deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can opt to disable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:soft_email_confirmation)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:soft_email_confirmation)
+```
<!-- ## Troubleshooting
diff --git a/doc/user/admin_area/settings/terms.md b/doc/user/admin_area/settings/terms.md
index 77c172aa927..95c32af5716 100644
--- a/doc/user/admin_area/settings/terms.md
+++ b/doc/user/admin_area/settings/terms.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/user/admin_area/settings/third_party_offers.md b/doc/user/admin_area/settings/third_party_offers.md
index 29ca3bf5ab2..f0e53115cb1 100644
--- a/doc/user/admin_area/settings/third_party_offers.md
+++ b/doc/user/admin_area/settings/third_party_offers.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index 140d149555a..d4080b3921a 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
diff --git a/doc/user/admin_area/settings/user_and_ip_rate_limits.md b/doc/user/admin_area/settings/user_and_ip_rate_limits.md
index 5d49d88d254..af3e0c5b63b 100644
--- a/doc/user/admin_area/settings/user_and_ip_rate_limits.md
+++ b/doc/user/admin_area/settings/user_and_ip_rate_limits.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
@@ -19,6 +22,43 @@ These limits are disabled by default.
![user-and-ip-rate-limits](img/user_and_ip_rate_limits.png)
+## Use an HTTP header to bypass rate limiting
+
+> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/622) in GitLab 13.6.
+
+Depending on the needs of your organization, you may want to enable rate limiting
+but have some requests bypass the rate limiter.
+
+You can do this by marking requests that should bypass the rate limiter with a custom
+header. You must do this somewhere in a load balancer or reverse proxy in front of
+GitLab. For example:
+
+1. Pick a name for your bypass header. For example, `Gitlab-Bypass-Rate-Limiting`.
+1. Configure your load balancer to set `Gitlab-Bypass-Rate-Limiting: 1` on requests
+ that should bypass GitLab rate limiting.
+1. Configure your load balancer to either:
+ - Erase `Gitlab-Bypass-Rate-Limiting`.
+ - Set `Gitlab-Bypass-Rate-Limiting` to a value other than `1` on all requests that
+ should be affected by rate limiting.
+1. Set the environment variable `GITLAB_THROTTLE_BYPASS_HEADER`.
+ - For [Omnibus](https://docs.gitlab.com/omnibus/settings/environment-variables.html),
+ set `'GITLAB_THROTTLE_BYPASS_HEADER' => 'Gitlab-Bypass-Rate-Limiting'` in `gitlab_rails['env']`.
+ - For source installations, set `export GITLAB_THROTTLE_BYPASS_HEADER=Gitlab-Bypass-Rate-Limiting`
+ in `/etc/default/gitlab`.
+
+It is important that your load balancer erases or overwrites the bypass
+header on all incoming traffic, because otherwise you must trust your
+users to not set that header and bypass the GitLab rate limiter.
+
+Note that the bypass only works if the header is set to `1`.
+
+Requests that bypassed the rate limiter because of the bypass header
+will be marked with `"throttle_safelist":"throttle_bypass_header"` in
+[`production_json.log`](../../../administration/logs.md#production_jsonlog).
+
+To disable the bypass mechanism, make sure the environment variable
+`GITLAB_THROTTLE_BYPASS_HEADER` is unset or empty.
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
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 95a87378e18..3740dc95c12 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).
+Projects within a group (but not a personal namespace) can be deleted after a delayed period, by [configuring in Group Settings](../../group/index.md#enabling-delayed-project-removal).
The default period is 7 days, and can be changed. Setting this period to 0 will enable immediate removal
of projects or groups.
diff --git a/doc/user/analytics/code_review_analytics.md b/doc/user/analytics/code_review_analytics.md
index 89acb430a9f..dc956765794 100644
--- a/doc/user/analytics/code_review_analytics.md
+++ b/doc/user/analytics/code_review_analytics.md
@@ -1,7 +1,7 @@
---
description: "Learn how long your open merge requests have spent in code review, and what distinguishes the longest-running." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here.
stage: Manage
-group: Analytics
+group: Value Stream 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/analytics/index.md b/doc/user/analytics/index.md
index 54b4c702c5c..29df25d76af 100644
--- a/doc/user/analytics/index.md
+++ b/doc/user/analytics/index.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Analytics
+group: Value Stream 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
---
@@ -26,6 +26,7 @@ The following analytics features are available at the group level:
- [Insights](../group/insights/index.md). **(ULTIMATE)**
- [Issue](../group/issues_analytics/index.md). **(PREMIUM)**
- [Productivity](productivity_analytics.md) **(PREMIUM)**
+- [Repositories](../group/repositories_analytics/index.md) **(PREMIUM)**
- [Value Stream](value_stream_analytics.md). **(PREMIUM)**
## Project-level analytics
@@ -34,7 +35,7 @@ The following analytics features are available at the project level:
- [CI/CD](../../ci/pipelines/index.md#pipeline-success-and-duration-charts). **(STARTER)**
- [Code Review](code_review_analytics.md). **(STARTER)**
-- [Insights](../group/insights/index.md). **(ULTIMATE)**
+- [Insights](../project/insights/index.md). **(ULTIMATE)**
- [Issue](../group/issues_analytics/index.md). **(PREMIUM)**
- [Merge Request](merge_request_analytics.md), enabled with the `project_merge_request_analytics`
[feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-locally-in-development). **(STARTER)**
diff --git a/doc/user/analytics/merge_request_analytics.md b/doc/user/analytics/merge_request_analytics.md
index 04a5fa71e19..5402d9a20a0 100644
--- a/doc/user/analytics/merge_request_analytics.md
+++ b/doc/user/analytics/merge_request_analytics.md
@@ -1,7 +1,7 @@
---
description: "Merge Request Analytics help you understand the efficiency of your code review process, and the productivity of your team." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here.
stage: Manage
-group: Analytics
+group: Value Stream 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
---
@@ -57,9 +57,11 @@ Data table displaying a maximum of the 100 most recent merge requests merged for
You can filter the data that is presented on the page based on the following parameters:
- Author
-- Assignees
-- Labels
-- Milestones
+- Assignee
+- Label
+- Milestone
+- Source branch
+- Target branch
To filter results:
diff --git a/doc/user/analytics/productivity_analytics.md b/doc/user/analytics/productivity_analytics.md
index 951be1c550b..da3fe00a901 100644
--- a/doc/user/analytics/productivity_analytics.md
+++ b/doc/user/analytics/productivity_analytics.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Analytics
+group: Value Stream 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/analytics/repository_analytics.md b/doc/user/analytics/repository_analytics.md
index 6d2de951a55..3fc5478d466 100644
--- a/doc/user/analytics/repository_analytics.md
+++ b/doc/user/analytics/repository_analytics.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Analytics
+group: Value Stream 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/analytics/value_stream_analytics.md b/doc/user/analytics/value_stream_analytics.md
index 86525587b30..244e37ba3ab 100644
--- a/doc/user/analytics/value_stream_analytics.md
+++ b/doc/user/analytics/value_stream_analytics.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Analytics
+group: Value Stream 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
---
@@ -105,7 +105,7 @@ Each stage of Value Stream Analytics is further described in the table below.
| --------- | --------------- |
| Issue | Measures the median time between creating an issue and taking action to solve it, by either labeling it or adding it to a milestone, whatever comes first. The label will be tracked only if it already has an [Issue Board list](../project/issue_board.md) created for it. |
| Plan | Measures the median time between the action you took for the previous stage, and pushing the first commit to the branch. The very first commit of the branch is the one that triggers the separation between **Plan** and **Code**, and at least one of the commits in the branch needs to contain the related issue number (e.g., `#42`). If none of the commits in the branch mention the related issue number, it is not considered to the measurement time of the stage. |
-| Code | Measures the median time between pushing a first commit (previous stage) and creating a merge request (MR) related to that commit. The key to keep the process tracked is to include the [issue closing pattern](../project/issues/managing_issues.md#closing-issues-automatically) to the description of the merge request (for example, `Closes #xxx`, where `xxx` is the number of the issue related to this merge request). If the issue closing pattern is not present in the merge request description, the MR is not considered to the measurement time of the stage. |
+| Code | Measures the median time between pushing a first commit (previous stage) and creating a merge request (MR) related to that commit. The key to keep the process tracked is to include the [issue closing pattern](../project/issues/managing_issues.md#closing-issues-automatically) to the description of the merge request (for example, `Closes #xxx`, where `xxx` is the number of the issue related to this merge request). If the closing pattern is not present, then the calculation takes the creation time of the first commit in the merge request as the start time. |
| Test | Measures the median time to run the entire pipeline for that project. It's related to the time GitLab CI/CD takes to run every job for the commits pushed to that merge request defined in the previous stage. It is basically the start->finish time for all pipelines. |
| 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 a [production environment](#how-the-production-environment-is-identified). If there isn't a production environment, this is not tracked. |
@@ -299,7 +299,7 @@ To recover a default stage that was previously hidden:
A default value stream is readily available for each group. You can create additional value streams based on the different areas of work that you would like to measure.
-Once created, a new value stream includes the [seven stages](#overview) that follow
+Once created, a new value stream includes the [seven stages](#default-stages) that follow
[GitLab workflow](../../topics/gitlab_flow.md)
best practices. You can customize this flow by adding, hiding or re-ordering stages.
@@ -339,12 +339,14 @@ Feature.disable(:value_stream_analytics_create_multiple_value_streams)
> - [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.
+This chart visually depicts the total number of days it takes for cycles to be completed. (Totals are being replaced with averages in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/262070).)
This chart uses the global page filters for displaying data based on the selected
group, projects, and timeframe. In addition, specific stages can be selected
from within the chart itself.
+The chart data is limited to the last 500 items.
+
### Disabling chart
This chart is enabled by default. If you have a self-managed instance, an
@@ -377,7 +379,7 @@ The current permissions on the Project Value Stream Analytics dashboard are:
You can [read more about permissions](../../user/permissions.md) in general.
-For Value Stream Analytics functionality introduced in GitLab 12.3 and later,
+For Value Stream Analytics functionality introduced in GitLab 12.3 and later,
users must have Reporter access or above.
## More resources
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
index 145422f8736..57c5f8bc1fa 100644
--- a/doc/user/application_security/api_fuzzing/index.md
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -8,9 +8,10 @@ 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.
+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),
@@ -23,7 +24,10 @@ you can run fuzz tests as part your CI/CD workflow.
- SOAP
- GraphQL
- Form bodies, JSON, or XML
-- An OpenAPI definition, or HTTP Archive (HAR) of requests to test
+- One of the following assets to provide APIs to test:
+ - OpenAPI v2 API definition
+ - HTTP Archive (HAR) of API requests to test
+ - Postman Collection v2.0 or v2.1
## When fuzzing scans run
@@ -48,15 +52,17 @@ changes, other pipelines, or other scanners) during a scan could cause inaccurat
## Configuration
-There are two ways to perform scans. See the configuration section for the one you wish to use:
+There are three 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)
+- [Postman Collection v2.0 or v2.1](#postman-collection)
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)
+- [Example Postman Collection project](https://gitlab.com/gitlab-org/security-products/demos/api-fuzzing/postman-api-fuzzing-example)
### OpenAPI Specification
@@ -133,7 +139,7 @@ This is a minimal configuration for API Fuzzing. From here you can:
- [Add authentication](#authentication).
- Learn how to [handle false positives](#handling-false-positives).
-DANGER: **Danger:**
+DANGER: **Warning:**
**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.
@@ -224,7 +230,98 @@ This is a minimal configuration for API Fuzzing. From here you can:
- [Add authentication](#authentication).
- Learn how to [handle false positives](#handling-false-positives).
-DANGER: **Danger:**
+DANGER: **Warning:**
+**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.
+
+### Postman Collection
+
+The [Postman API Client](https://www.postman.com/product/api-client/) is a popular tool that
+developers and testers use to call various types of APIs. The API definitions
+[can be exported as a Postman Collection file](https://learning.postman.com/docs/getting-started/importing-and-exporting-data/#exporting-postman-data)
+for use with API Fuzzing. When exporting, make sure to select a supported version of Postman
+Collection: v2.0 or v2.1.
+
+When used with GitLab's API fuzzer, Postman Collections must contain definitions of the web API to
+test with valid data. The API fuzzer extracts all the API definitions and uses them to perform
+testing.
+
+DANGER: **Warning:**
+Postman Collection files may contain sensitive information such as authentication tokens, API keys,
+and session cookies. We recommend that you review the Postman Collection file contents before adding
+them to a repository.
+
+Follow these steps to configure API fuzzing to use a Postman Collection 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_POSTMAN_COLLECTION` variable and set it to the Postman Collection's location:
+
+ ```yaml
+ include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+ variables:
+ FUZZAPI_PROFILE: Quick-10
+ FUZZAPI_POSTMAN_COLLECTION: postman-collection_serviceA.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_POSTMAN_COLLECTION: postman-collection_serviceA.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: **Warning:**
**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.
@@ -398,6 +495,7 @@ increases as the numbers go up. To use a configuration file, add it to your repo
| `FUZZAPI_REPORT` |Scan report filename. Defaults to `gl-api_fuzzing-report.xml`. |
|[`FUZZAPI_OPENAPI`](#openapi-specification)|OpenAPI specification file or URL. |
|[`FUZZAPI_HAR`](#http-archive-har)|HTTP Archive (HAR) file. |
+|[`FUZZAPI_POSTMAN_COLLECTION`](#postman-collection)|Postman Collection file. |
|[`FUZZAPI_OVERRIDES_FILE`](#overrides) |Path to a JSON file containing overrides. |
|[`FUZZAPI_OVERRIDES_ENV`](#overrides) |JSON string containing headers to override. |
|[`FUZZAPI_OVERRIDES_CMD`](#overrides) |Overrides command. |
@@ -540,6 +638,86 @@ variables:
FUZZAPI_OVERRIDES_INTERVAL: 300
```
+### Header Fuzzing
+
+Header fuzzing is disabled by default due to the high number of false positives that occur with many
+technology stacks. When header fuzzing is enabled, you must specify a list of headers to include in
+fuzzing.
+
+Each profile in the default configuration file has an entry for `GeneralFuzzingCheck`. This check
+performs header fuzzing. Under the `Configuration` section, you must change the `HeaderFuzzing` and
+`Headers` settings to enable header fuzzing.
+
+This snippet shows the `Quick-10` profile's default configuration with header fuzzing disabled:
+
+```yaml
+- Name: Quick-10
+ DefaultProfile: Empty
+ Routes:
+ - Route: *Route0
+ Checks:
+ - Name: FormBodyFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ - Name: GeneralFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ HeaderFuzzing: false
+ Headers:
+ - Name: JsonFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ - Name: XmlFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+```
+
+`HeaderFuzzing` is a boolean that turns header fuzzing on and off. The default setting is `false`
+for off. To turn header fuzzing on, change this setting to `true`:
+
+```yaml
+ - Name: GeneralFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ HeaderFuzzing: true
+ Headers:
+```
+
+`Headers` is a list of headers to fuzz. Only headers listed are fuzzed. For example, to fuzz a
+custom header `X-Custom` used by your APIs, add an entry for it using the syntax
+`- Name: HeaderName`, substituting `HeaderName` with the header to fuzz:
+
+```yaml
+ - Name: GeneralFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ HeaderFuzzing: true
+ Headers:
+ - Name: X-Custom
+```
+
+You now have a configuration to fuzz the header `X-Custom`. Use the same notation to list additional
+headers:
+
+```yaml
+ - Name: GeneralFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ HeaderFuzzing: true
+ Headers:
+ - Name: X-Custom
+ - Name: X-AnotherHeader
+```
+
+Repeat this configuration for each profile as needed.
+
## Running your first scan
When configured correctly, a CI/CD pipeline contains a `Fuzz` stage and a `apifuzzer_fuzz` job. The
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index 9e7f98dd4fc..eef15a9c424 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -1,6 +1,6 @@
---
type: reference, howto
-stage: Defend
+stage: Protect
group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
@@ -76,6 +76,7 @@ How you enable container scanning depends on your GitLab version:
that comes with your GitLab installation.
- GitLab versions earlier than 11.9: Copy and use the job from the
[`Container-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml).
+- GitLab 13.6 [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263482) better support for [FIPS](https://csrc.nist.gov/publications/detail/fips/140/2/final) by upgrading the `CS_MAJOR_VERSION` from `2` to `3`.
To include the `Container-Scanning.gitlab-ci.yml` template (GitLab 11.9 and later), add the
following to your `.gitlab-ci.yml` file:
@@ -144,6 +145,26 @@ variables:
CLAIR_OUTPUT: High
```
+Version `3` of the `container_scanning` Docker image uses [`centos:centos8`](https://hub.docker.com/_/centos)
+as the new base. It also removes the use of the [start.sh](https://gitlab.com/gitlab-org/security-products/analyzers/klar/-/merge_requests/77)
+script and instead executes the analyzer by default. Any customizations made to the
+`container_scanning` job's [`before_script`](../../../ci/yaml/README.md#before_script)
+and [`after_script`](../../../ci/yaml/README.md#after_script)
+blocks may not work with the new version. To roll back to the previous [`alpine:3.11.3`](https://hub.docker.com/_/alpine)-based
+Docker image, you can specify the major version through the [`CS_MAJOR_VERSION`](#available-variables)
+variable.
+
+This example [includes](../../../ci/yaml/README.md#include) the container scanning template and
+enables version `2` of the analyzer:
+
+```yaml
+include:
+ - template: Container-Scanning.gitlab-ci.yml
+
+variables:
+ CS_MAJOR_VERSION: '2'
+```
+
<!-- NOTE: The container scanning tool references the following heading in the code, so if you"
make a change to this heading, make sure to update the documentation URLs used in the"
container scanning tool (https://gitlab.com/gitlab-org/security-products/analyzers/klar)" -->
@@ -164,6 +185,8 @@ scanning by using the following environment variables:
| `CLAIR_VULNERABILITIES_DB_URL` | `clair-vulnerabilities-db` | (**DEPRECATED - use `CLAIR_DB_CONNECTION_STRING` instead**) This variable is explicitly set in the [services section](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23) of the `Container-Scanning.gitlab-ci.yml` file and defaults to `clair-vulnerabilities-db`. This value represents the address that the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db) is running on and **shouldn't be changed** unless you're running the image locally as described in the [Running the standalone container scanning tool](#running-the-standalone-container-scanning-tool) section. |
| `CI_APPLICATION_REPOSITORY` | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` | Docker repository URL for the image to be scanned. |
| `CI_APPLICATION_TAG` | `$CI_COMMIT_SHA` | Docker repository tag for the image to be scanned. |
+| `CS_MAJOR_VERSION` | `3` | The major version of the Docker image tag. |
+| `DOCKER_IMAGE` | `$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG` | The Docker image to be scanned. If set, this variable overrides the `$CI_APPLICATION_REPOSITORY` and `$CI_APPLICATION_TAG` variables. |
| `DOCKER_INSECURE` | `"false"` | Allow [Klar](https://github.com/optiopay/klar) to access secure Docker registries using HTTPS with bad (or self-signed) SSL certificates. |
| `DOCKER_PASSWORD` | `$CI_REGISTRY_PASSWORD` | Password for accessing a Docker registry requiring authentication. |
| `DOCKER_USER` | `$CI_REGISTRY_USER` | Username for accessing a Docker registry requiring authentication. |
@@ -415,11 +438,11 @@ automatically generates.
To enable remediation support, the scanning tool _must_ have access to the `Dockerfile` specified by
the [`DOCKERFILE_PATH`](#available-variables) environment variable. To ensure that the scanning tool
has access to this
-file, it's necessary to set [`GIT_STRATEGY: fetch`](../../../ci/yaml/README.md#git-strategy) in
+file, it's necessary to set [`GIT_STRATEGY: fetch`](../../../ci/runners/README.md#git-strategy) in
your `.gitlab-ci.yml` file by following the instructions described in this document's
[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).
+Read more about the [solutions for vulnerabilities](../index.md#automatic-remediation-for-vulnerabilities).
## Troubleshooting
diff --git a/doc/user/application_security/coverage_fuzzing/img/coverage_fuzzing_report_v13_6.png b/doc/user/application_security/coverage_fuzzing/img/coverage_fuzzing_report_v13_6.png
new file mode 100644
index 00000000000..bed3ca4c9df
--- /dev/null
+++ b/doc/user/application_security/coverage_fuzzing/img/coverage_fuzzing_report_v13_6.png
Binary files differ
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index 9508407ccae..4c5afcee3d0 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -30,6 +30,7 @@ Docker image with the fuzz engine to run your app.
| Swift | [libfuzzer](https://github.com/apple/swift/blob/master/docs/libFuzzerIntegration.md) | [swift-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/swift-fuzzing-example) |
| Rust | [cargo-fuzz (libFuzzer support)](https://github.com/rust-fuzz/cargo-fuzz) | [rust-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/rust-fuzzing-example) |
| Java | [JQF](https://github.com/rohanpadhye/JQF) | [java-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/java-fuzzing-example) |
+| Java | [javafuzz](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/javafuzz) (recommended) | [javafuzz-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/javafuzz-fuzzing-example) |
## Configuration
@@ -221,6 +222,34 @@ This essentially creates two steps:
The `covfuzz-ci.yml` is the same as that in the [original synchronous example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example#running-go-fuzz-from-ci).
+## Interacting with the vulnerabilities
+
+After a vulnerability is found, you can [interact with it](../index.md#interacting-with-the-vulnerabilities).
+The merge request widget lists the vulnerability and contains a button for downloading the fuzzing
+artifacts. By clicking one of the detected vulnerabilities, you can see its details.
+
+![Coverage Fuzzing Security Report](img/coverage_fuzzing_report_v13_6.png)
+
+You can also view the vulnerability from the [Security Dashboard](../security_dashboard/index.md),
+which shows an overview of all the security vulnerabilities in your groups, projects, and pipelines.
+
+Clicking the vulnerability opens a modal that provides additional information about the
+vulnerability:
+
+- Status: The vulnerability's status. As with any type of vulnerability, a coverage fuzzing
+ vulnerability can be Detected, Confirmed, Dismissed, or Resolved.
+- Project: The project in which the vulnerability exists.
+- Crash type: The type of crash or weakness in the code. This typically maps to a [CWE](https://cwe.mitre.org/).
+- Crash state: A normalized version of the stacktrace, containing the last three functions of the
+ crash (without random addresses).
+- Stacktrace snippet: The last few lines of the stacktrace, which shows details about the crash.
+- Identifier: The vulnerability's identifier. This maps to either a [CVE](https://cve.mitre.org/)
+ or [CWE](https://cwe.mitre.org/).
+- Severity: The vulnerability's severity. This can be Critical, High, Medium, Low, Info, or Unknown.
+- Scanner: The scanner that detected the vulnerability (for example, Coverage Fuzzing).
+- Scanner Provider: The engine that did the scan. For Coverage Fuzzing, this can be any of the
+ engines listed in [Supported fuzzing engines and languages](#supported-fuzzing-engines-and-languages).
+
### Glossary
- Seed corpus: The set of test cases given as initial input to the fuzz target. This usually speeds
diff --git a/doc/user/application_security/dast/img/dast_on_demand_v13_2.png b/doc/user/application_security/dast/img/dast_on_demand_v13_2.png
deleted file mode 100644
index 045221d713c..00000000000
--- a/doc/user/application_security/dast/img/dast_on_demand_v13_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/dast/img/dast_single_v13_0.png b/doc/user/application_security/dast/img/dast_single_v13_0.png
index 91ed4d916ab..1d528fa0ace 100644
--- a/doc/user/application_security/dast/img/dast_single_v13_0.png
+++ b/doc/user/application_security/dast/img/dast_single_v13_0.png
Binary files differ
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index fffaf4ad26b..2f1ed2faf90 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -161,6 +161,12 @@ headers whose values you want masked. For details on how to mask headers, see
It's also possible to authenticate the user before performing the DAST checks.
+**Important:** It is highly recommended that you configure the scanner to authenticate to the application,
+or it will not be able to check most of the application for security risks, as most
+of your application is likely not accessible without authentication. It is also recommended
+that you periodically confirm the scanner's authentication is still working as this tends to break over
+time due to authentication changes to the application.
+
Create masked variables to pass the credentials that DAST uses.
To create masked variables for the username and password, see [Create a custom variable in the UI](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui).
Note that the key of the username variable must be `DAST_USERNAME`
@@ -185,7 +191,7 @@ The results are saved as a
that you can later download and analyze.
Due to implementation limitations, we always take the latest DAST artifact available.
-DANGER: **Danger:**
+DANGER: **Warning:**
**NEVER** run an authenticated scan against a production server. When an authenticated
scan is run, it may perform *any* function that the authenticated user can. This
includes actions like modifying and deleting data, submitting forms, and following links.
@@ -423,7 +429,51 @@ 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 scan, add a comma-separated list of the paths to the `DAST_PATHS`
+URLs to scan can be specified by either of the following methods:
+
+- Use `DAST_PATHS_FILE` environment variable to specify the name of a file containing the paths.
+- Use `DAST_PATHS` environment variable to list the paths.
+
+##### Use DAST_PATHS_FILE environment variable
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6.
+
+To define the URLs to scan in a file, create a plain text file with one path per line.
+
+```txt
+page1.html
+/page2.html
+category/shoes/page1.html
+```
+
+To scan the URLs in that file, set the environment variable `DAST_PATHS_FILE` to the path of that file.
+
+```yaml
+include:
+ - template: DAST.gitlab-ci.yml
+
+variables:
+ DAST_PATHS_FILE: url_file.txt
+```
+
+By default, DAST scans do not clone the project repository. If the file is checked in to the project, instruct the DAST job to clone the project by setting GIT_STRATEGY to fetch. The file is expected to be in the `/zap/wrk` directory.
+
+```yaml
+dast:
+ script:
+ - mkdir -p /zap/wrk
+ - cp url_file.txt /zap/wrk/url_file.txt
+ - /analyze -t $DAST_WEBSITE
+ variables:
+ GIT_STRATEGY: fetch
+ DAST_PATHS_FILE: url_file.txt
+```
+
+##### Use DAST_PATHS environment variable
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4.
+
+To specify the paths to scan in an environment variable, add a comma-separated list of the paths to the `DAST_PATHS`
environment variable. Note that you can only scan paths of a single host.
```yaml
@@ -434,10 +484,13 @@ variables:
DAST_PATHS=/page1.html,/category1/page1.html,/page3.html
```
-When using `DAST_PATHS`, note the following:
+When using `DAST_PATHS` and `DAST_PATHS_FILE`, note the following:
+- `DAST_WEBSITE` must be defined when using either `DAST_PATHS_FILE` or `DAST_PATHS`. The paths listed in either will use `DAST_WEBSITE` to build the URLs to scan
+- Spidering is disabed when `DAST_PATHS` or `DAST_PATHS_FILE` are defined
+- `DAST_PATHS_FILE` and `DAST_PATHS` can not be used together
- The `DAST_PATHS` environment variable has a limit of about 130kb. If you have a list or paths
- greater than this, you should create multiple DAST jobs and split the paths over each job.
+ greater than this, use `DAST_PATHS_FILE`.
#### Full Scan
@@ -476,6 +529,7 @@ DAST can be [configured](#customizing-the-dast-settings) using environment varia
| `SECURE_ANALYZERS_PREFIX` | URL | Set the Docker registry base address from which to download the analyzer. |
| `DAST_WEBSITE` | URL | The URL of the website to scan. `DAST_API_SPECIFICATION` must be specified if this is omitted. |
| `DAST_API_SPECIFICATION` | URL or string | The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. `DAST_WEBSITE` must be specified if this is omitted. |
+| `DAST_SPIDER_START_AT_HOST` | boolean | Set to `false` to prevent DAST from resetting the target to its host before scanning. When `true`, non-host targets `http://test.site/some_path` will be reset to `http://test.site` before scan. Default: `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258805) in GitLab 13.6. |
| `DAST_AUTH_URL` | URL | The URL of the page containing the sign-in HTML form on the target website. `DAST_USERNAME` and `DAST_PASSWORD` are submitted with the login form to create an authenticated scan. Not supported for API scans. |
| `DAST_USERNAME` | string | The username to authenticate to in the website. |
| `DAST_PASSWORD` | string | The password to authenticate to in the website. |
@@ -489,15 +543,16 @@ DAST can be [configured](#customizing-the-dast-settings) using environment varia
| `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. |
-| `DAST_HTML_REPORT` | string | The filename of the HTML report written at the end of a scan. |
-| `DAST_MARKDOWN_REPORT` | string | The filename of the Markdown report written at the end of a scan. |
-| `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_DEBUG` | boolean | Enable debug message output. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_SPIDER_MINS` | number | The maximum duration of the spider scan in minutes. Set to `0` for unlimited. Default: One minute, or unlimited when the scan is a full scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_HTML_REPORT` | string | The filename of the HTML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_MARKDOWN_REPORT` | string | The filename of the Markdown report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1.|
+| `DAST_XML_REPORT` | string | The filename of the XML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_INCLUDE_ALPHA_VULNERABILITIES` | boolean | Set to `true` to include alpha passive and active scan rules. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_USE_AJAX_SPIDER` | boolean | Set to `true` to use the AJAX spider in addition to the traditional spider, useful for crawling sites that require JavaScript. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_PATHS` | string | Set to a comma-separated list of URLs for DAST to scan. For example, `/page1.html,/category1/page3.html,/page2.html`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4. |
+| `DAST_PATHS_FILE` | string | The file path containing the paths within `DAST_WEBSITE` to scan. The file must be plain text with one path per line and be within `/zap/wrk`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6. |
+| `DAST_ZAP_CLI_OPTIONS` | string | ZAP server command-line options. For example, `-Xmx3072m` would set the Java maximum memory allocation pool size. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_ZAP_LOG_CONFIGURATION` | string | Set to a semicolon-separated list of additional log4j properties for the ZAP Server. For example, `log4j.logger.org.parosproxy.paros.network.HttpSender=DEBUG;log4j.logger.com.crawljax=DEBUG` |
### DAST command-line options
@@ -548,7 +603,7 @@ variables:
### Cloning the project's repository
The DAST job does not require the project's repository to be present when running, so by default
-[`GIT_STRATEGY`](../../../ci/yaml/README.md#git-strategy) is set to `none`.
+[`GIT_STRATEGY`](../../../ci/runners/README.md#git-strategy) is set to `none`.
### Debugging DAST jobs
@@ -713,10 +768,6 @@ To delete a scanner 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).
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.
@@ -747,35 +798,6 @@ To run an on-demand DAST scan, you need:
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.
-
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can disable or enable the feature flags.
-
-To disable On-demand DAST Scans:
-
-```ruby
-# Instance-wide
-Feature.disable(:security_on_demand_scans_feature_flag)
-# or by project
-Feature.disable(:security_on_demand_scans_feature_flag, Project.find(<project id>))
-```
-
-To enable On-demand DAST Scans:
-
-```ruby
-# Instance-wide
-Feature.enable(:security_on_demand_scans_feature_flag)
-# or by project
-Feature.enable(:security_on_demand_scans_feature_flag, Project.find(<project ID>))
-```
-
## Reports
The DAST tool outputs a report file in JSON format by default. However, this tool can also generate reports in
diff --git a/doc/user/application_security/dependency_list/img/dependency_list_v12_3.png b/doc/user/application_security/dependency_list/img/dependency_list_v12_3.png
deleted file mode 100644
index 8eeadb34504..00000000000
--- a/doc/user/application_security/dependency_list/img/dependency_list_v12_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/dependency_list/img/dependency_list_v12_4.png b/doc/user/application_security/dependency_list/img/dependency_list_v12_4.png
deleted file mode 100644
index 4687987b763..00000000000
--- a/doc/user/application_security/dependency_list/img/dependency_list_v12_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/dependency_list/img/yarn_dependency_path_v13_6.png b/doc/user/application_security/dependency_list/img/yarn_dependency_path_v13_6.png
new file mode 100644
index 00000000000..78e324f43c4
--- /dev/null
+++ b/doc/user/application_security/dependency_list/img/yarn_dependency_path_v13_6.png
Binary files differ
diff --git a/doc/user/application_security/dependency_list/index.md b/doc/user/application_security/dependency_list/index.md
index 1f730e5f205..ddd059707d4 100644
--- a/doc/user/application_security/dependency_list/index.md
+++ b/doc/user/application_security/dependency_list/index.md
@@ -32,7 +32,7 @@ Dependencies are displayed with the following information:
| --------- | ----------- |
| Component | The dependency's name and version |
| Packager | The packager used to install the dependency |
-| Location | A link to the packager-specific lock file in your project that declared the dependency |
+| Location | A link to the packager-specific lock file in your project that declared the dependency. It also shows the [dependency path](#dependency-paths) to a top-level dependency, if any, and if supported. |
| License | Links to dependency's software licenses |
Dependencies shown are initially sorted by the severity of their known vulnerabilities, if any. They
@@ -44,6 +44,18 @@ If a dependency has known vulnerabilities, you can view them by clicking the arr
dependency's name or the badge that indicates how many known vulnerabilities exist. For each
vulnerability, its severity and description then appears below it.
+### Dependency Paths
+
+The dependency list shows the path between a dependency and a top-level dependency it's connected
+to, if any. There are many possible paths connecting a transient dependency to top-level
+dependencies, but the UI only shows one of the shortest paths.
+
+![Dependency Path](img/yarn_dependency_path_v13_6.png)
+
+Dependency Paths are supported for the following package managers:
+
+- [NuGet](https://www.nuget.org/)
+
## Licenses
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10536) in GitLab Ultimate 12.3.
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index b90bb37c60f..1b164c9cecd 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -53,7 +53,7 @@ is **not** `19.03.0`. See [troubleshooting information](#error-response-from-dae
## 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.
-The current detection logic limits the maximum search depth to two levels. For example, the `gemnasium-dependency_scanning` job is enabled if a repository contains either a `Gemfile` or `api/Gemfile` file, but not if the only supported dependency file is `api/client/Gemfile`.
+The current detection logic limits the maximum search depth to two levels. For example, the `gemnasium-dependency_scanning` job is enabled if a repository contains either a `Gemfile` or `api/Gemfile` file, but not if the only supported dependency file is `api/client/Gemfile`.
The following languages and dependency managers are supported:
@@ -71,11 +71,11 @@ The following languages and dependency managers are supported:
Plans are underway for supporting the following languages, dependency managers, and dependency files. For details, see the issue link for each.
-| Package Managers | Languages | Supported files | Scan tools |
-| ------------------- | --------- | --------------- | ------------ |
+| Package Managers | Languages | Supported files | Scan tools | Issue |
+| ------------------- | --------- | --------------- | ---------- | ----- |
| [Pipenv](https://pipenv.pypa.io/en/latest/) | Python | `Pipfile.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#11756](https://gitlab.com/gitlab-org/gitlab/-/issues/11756) |
| [Poetry](https://python-poetry.org/) | Python | `poetry.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#7006](https://gitlab.com/gitlab-org/gitlab/-/issues/7006) |
-| [sbt](https://www.scala-sbt.org/) 1.3+ ([Coursier](https://get-coursier.io/))| Scala | `build.sbt` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#249526](https://gitlab.com/gitlab-org/gitlab/-/issues/249526) |
+| [sbt](https://www.scala-sbt.org/) 1.3+ ([Coursier](https://get-coursier.io/))| Scala | `build.sbt` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#271345](https://gitlab.com/gitlab-org/gitlab/-/issues/271345) |
## Contribute your scanner
@@ -201,7 +201,7 @@ Once a vulnerability is found, you can interact with it. Read more on how to
Some vulnerabilities can be fixed by applying the solution that GitLab
automatically generates. Read more about the
-[solutions for vulnerabilities](../index.md#solutions-for-vulnerabilities-auto-remediation).
+[solutions for vulnerabilities](../index.md#automatic-remediation-for-vulnerabilities).
## Security Dashboard
@@ -356,9 +356,11 @@ Here are the requirements for using dependency scanning in an offline environmen
- GitLab Runner with the [`docker` or `kubernetes` executor](#requirements).
- Docker Container Registry with locally available copies of dependency scanning [analyzer](https://gitlab.com/gitlab-org/security-products/analyzers) images.
-- Host an offline Git copy of the [gemnasium-db advisory database](https://gitlab.com/gitlab-org/security-products/gemnasium-db/).
- This is required because, in an offline environment, the Gemnasium analyzer can't fetch the latest
- advisories from the online repository.
+- If you have a limited access environment you will need to allow access, such as using a proxy, to the advisory database: `https://gitlab.com/gitlab-org/security-products/gemnasium-db.git`.
+ If you are unable to permit access to `https://gitlab.com/gitlab-org/security-products/gemnasium-db.git` you must host an offline copy of this `git` repository and set the `GEMNASIUM_DB_REMOTE_URL` variable to the URL of this repository. For more information on configuration variables, see [Dependency Scanning](#configuring-dependency-scanning).
+
+ This advisory database is constantly being updated, so you will need to periodically sync your local copy with GitLab's.
+
- _Only if scanning Ruby projects_: Host an offline Git copy of the [advisory database](https://github.com/rubysec/ruby-advisory-db).
- _Only if scanning npm/yarn projects_: Host an offline copy of the [retire.js](https://github.com/RetireJS/retire.js/) [node](https://github.com/RetireJS/retire.js/blob/master/repository/npmrepository.json) and [js](https://github.com/RetireJS/retire.js/blob/master/repository/jsrepository.json) advisory databases.
diff --git a/doc/user/application_security/img/security_configuration_page_v13_2.png b/doc/user/application_security/img/security_configuration_page_v13_2.png
deleted file mode 100644
index 016328948cc..00000000000
--- a/doc/user/application_security/img/security_configuration_page_v13_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/img/security_widget_v13_6.png b/doc/user/application_security/img/security_widget_v13_6.png
new file mode 100644
index 00000000000..2dd44909dfe
--- /dev/null
+++ b/doc/user/application_security/img/security_widget_v13_6.png
Binary files differ
diff --git a/doc/user/application_security/img/vulnerability_page_merge_request_button_dropdown_v13_1.png b/doc/user/application_security/img/vulnerability_page_merge_request_button_dropdown_v13_1.png
new file mode 100644
index 00000000000..05ca74c3d5c
--- /dev/null
+++ b/doc/user/application_security/img/vulnerability_page_merge_request_button_dropdown_v13_1.png
Binary files differ
diff --git a/doc/user/application_security/img/vulnerability_page_merge_request_button_v13_1.png b/doc/user/application_security/img/vulnerability_page_merge_request_button_v13_1.png
new file mode 100644
index 00000000000..a3034a7db04
--- /dev/null
+++ b/doc/user/application_security/img/vulnerability_page_merge_request_button_v13_1.png
Binary files differ
diff --git a/doc/user/application_security/img/vulnerability_solution.png b/doc/user/application_security/img/vulnerability_solution.png
deleted file mode 100644
index 63e9c1473b6..00000000000
--- a/doc/user/application_security/img/vulnerability_solution.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index 413a9f894e2..30852d1bbcd 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference, howto
---
@@ -18,7 +21,7 @@ For an overview of application security with GitLab, see
## Quick start
Get started quickly with Dependency Scanning, License Scanning, Static Application Security
-Testing (SAST), and Secret Detection by adding the following to your `.gitlab-ci.yml`:
+Testing (SAST), and Secret Detection by adding the following to your [`.gitlab-ci.yml`](../../ci/yaml/README.md):
```yaml
include:
@@ -67,12 +70,26 @@ 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. |
+| [API fuzzing](api_fuzzing/index.md) **(ULTIMATE)** | Find unknown bugs and vulnerabilities in web APIs with fuzzing. |
+| [Secret Detection](secret_detection/index.md) | 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. |
| [Coverage fuzzing](coverage_fuzzing/index.md) **(ULTIMATE)** | Find unknown bugs and vulnerabilities with coverage-guided fuzzing. |
+### Use security scanning tools with Pipelines for Merge Requests
+
+The security scanning tools can all be added to pipelines with [templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Security).
+See each tool for details on how to use include each template in your CI/CD configuration.
+
+By default, the application security jobs are configured to run for branch pipelines only.
+To use them with [pipelines for merge requests](../../ci/merge_request_pipelines/index.md),
+you may need to override the default `rules:` configuration to add:
+
+```yaml
+rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+```
+
## Security Scanning with Auto DevOps
When [Auto DevOps](../../topics/autodevops/) is enabled, all GitLab Security scanning tools will be configured using default settings.
@@ -93,7 +110,7 @@ The scanning tools and vulnerabilities database are updated regularly.
| Secure scanning tool | Vulnerabilities database updates |
|:-------------------------------------------------------------|-------------------------------------------|
| [Container Scanning](container_scanning/index.md) | Uses `clair`. The latest `clair-db` version is used for each job by running the [`latest` Docker image tag](https://gitlab.com/gitlab-org/gitlab/blob/438a0a56dc0882f22bdd82e700554525f552d91b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L37). The `clair-db` database [is updated daily according to the author](https://github.com/arminc/clair-local-scan#clair-server-or-local). |
-| [Dependency Scanning](dependency_scanning/index.md) | Relies on `bundler-audit` (for Ruby gems), `retire.js` (for NPM packages), and `gemnasium` (GitLab's own tool for all libraries). Both `bundler-audit` and `retire.js` fetch their vulnerabilities data from GitHub repositories, so vulnerabilities added to `ruby-advisory-db` and `retire.js` are immediately available. The tools themselves are updated once per month if there's a new version. The [Gemnasium DB](https://gitlab.com/gitlab-org/security-products/gemnasium-db) is updated at least once a week. See our [current measurement of time from CVE being issued to our product being updated](https://about.gitlab.com/handbook/engineering/development/performance-indicators/#cve-issue-to-update). |
+| [Dependency Scanning](dependency_scanning/index.md) | Relies on `bundler-audit` (for Ruby gems), `retire.js` (for NPM packages), and `gemnasium` (GitLab's own tool for all libraries). Both `bundler-audit` and `retire.js` fetch their vulnerabilities data from GitHub repositories, so vulnerabilities added to `ruby-advisory-db` and `retire.js` are immediately available. The tools themselves are updated once per month if there's a new version. The [Gemnasium DB](https://gitlab.com/gitlab-org/security-products/gemnasium-db) is updated at least once a week. See our [current measurement of time from CVE being issued to our product being updated](https://about.gitlab.com/handbook/engineering/development/performance-indicators/#cve-issue-to-update). |
| [Dynamic Application Security Testing (DAST)](dast/index.md) | The scanning engine is updated on a periodic basis. See the [version of the underlying tool `zaproxy`](https://gitlab.com/gitlab-org/security-products/dast/blob/master/Dockerfile#L1). The scanning rules are downloaded at scan runtime. |
| [Static Application Security Testing (SAST)](sast/index.md) | Relies exclusively on [the tools GitLab wraps](sast/index.md#supported-languages-and-frameworks). The underlying analyzers are updated at least once per month if a relevant update is available. The vulnerabilities database is updated by the upstream tools. |
@@ -106,6 +123,24 @@ latest versions of the scanning tools without having to do anything. There are s
with this approach, however, and there is a
[plan to resolve them](https://gitlab.com/gitlab-org/gitlab/-/issues/9725).
+## Viewing security scan information in merge requests **(CORE)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4393) in GitLab Core 13.5.
+> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/273205) in 13.6.
+> - It's [deployed behind a feature flag](../feature_flags.md), enabled by default.
+> - It's enabled on GitLab.com.
+> - It can be enabled or disabled for a single project.
+> - It's recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-the-basic-security-widget). **(CORE ONLY)**
+
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+Merge requests which have run security scans let you know that the generated
+reports are available to download.
+
+![Security widget](img/security_widget_v13_6.png)
+
## Interacting with the vulnerabilities
> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.8.
@@ -119,7 +154,7 @@ information with several options:
- [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](#solutions-for-vulnerabilities-auto-remediation): For some vulnerabilities,
+- [Automatic Remediation](#automatic-remediation-for-vulnerabilities): For some vulnerabilities,
a solution is provided for how to fix the vulnerability.
![Interacting with security reports](img/interacting_with_vulnerability_v13_3.png)
@@ -141,21 +176,21 @@ To view details of DAST vulnerabilities:
1. Click on the vulnerability's description. The following details are provided:
- | Field | Description |
-|:-----------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Description | Description of the vulnerability. |
-| Project | Namespace and project in which the vulnerability was detected. |
-| Method | HTTP method used to detect the vulnerability. |
-| URL | URL at which the vulnerability was detected. |
-| Request Headers | Headers of the request. |
-| Response Status | Response status received from the application. |
-| Response Headers | Headers of the response received from the application. |
+| Field | Description |
+|:-----------------|:------------------------------------------------------------------ |
+| Description | Description of the vulnerability. |
+| Project | Namespace and project in which the vulnerability was detected. |
+| Method | HTTP method used to detect the vulnerability. |
+| URL | URL at which the vulnerability was detected. |
+| Request Headers | Headers of the request. |
+| Response Status | Response status received from the application. |
+| Response Headers | Headers of the response received from the application. |
| Evidence | Evidence of the data found that verified the vulnerability. Often a snippet of the request or response, this can be used to help verify that the finding is a vulnerability. |
-| Identifiers | Identifiers of the vulnerability. |
-| Severity | Severity of the vulnerability. |
-| Scanner Type | Type of vulnerability report. |
-| Links | Links to further details of the detected vulnerability. |
-| Solution | Details of a recommended solution to the vulnerability (optional). |
+| Identifiers | Identifiers of the vulnerability. |
+| Severity | Severity of the vulnerability. |
+| Scanner Type | Type of vulnerability report. |
+| Links | Links to further details of the detected vulnerability. |
+| Solution | Details of a recommended solution to the vulnerability (optional). |
#### Hide sensitive information in headers
@@ -198,38 +233,60 @@ Pressing the "Dismiss Selected" button will dismiss all the selected vulnerabili
![Multiple vulnerability dismissal](img/multi_select_v12_9.png)
-### Solutions for vulnerabilities (auto-remediation)
+### 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.
+
+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)
+
+### Automatic remediation for vulnerabilities
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5656) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.7.
Some vulnerabilities can be fixed by applying the solution that GitLab
-automatically generates. The following scanners are supported:
+automatically generates. Although the feature name is Automatic Remediation, this feature is also commonly called Auto-Remediation, Auto Remediation, or Suggested Solutions. The following scanners are supported:
- [Dependency Scanning](dependency_scanning/index.md):
Automatic Patch creation is only available for Node.js projects managed with
`yarn`.
- [Container Scanning](container_scanning/index.md)
+When an automatic solution is available, the button in the header shows **Resolve with merge request**:
+
+![Resolve with Merge Request button](img/vulnerability_page_merge_request_button_v13_1.png)
+
+Selecting the button creates a merge request with the solution.
+
#### Manually applying the suggested patch
-Some vulnerabilities can be fixed by applying a patch that is automatically
-generated by GitLab. To apply the fix:
+To manually apply the patch that GitLab generated for a vulnerability:
+
+1. Select the **Resolve with merge request** dropdown, then select **Download patch to resolve**:
+
+ ![Resolve with Merge Request button dropdown](img/vulnerability_page_merge_request_button_dropdown_v13_1.png)
-1. Click the vulnerability.
-1. Download and review the patch file `remediation.patch`.
1. Ensure your local project has the same commit checked out that was used to generate the patch.
1. Run `git apply remediation.patch`.
1. Verify and commit the changes to your branch.
-![Apply patch for dependency scanning](img/vulnerability_solution.png)
-
#### Creating a merge request from a vulnerability
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9224) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9.
In certain cases, GitLab allows you to create a merge request that automatically remediates the
vulnerability. Any vulnerability that has a
-[solution](#solutions-for-vulnerabilities-auto-remediation) can have a merge
+[solution](#automatic-remediation-for-vulnerabilities) can have a merge
request created to automatically solve the issue.
If this action is available, the vulnerability page or modal contains a **Create merge request** button.
@@ -237,25 +294,6 @@ Click this button to create a merge request to apply the solution onto the sourc
![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
Issues can be linked to a vulnerability using the related issues block on the vulnerability page.
@@ -320,7 +358,7 @@ 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.
+If at least one security scanner is enabled, you can enable the `Vulnerability-Check` approval rule. If a license scanning job is enabled, you can enable the `License-Check` rule.
![Unconfigured Approval Rules with valid pipeline jobs](img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.png)
@@ -566,3 +604,36 @@ Additionally, we provide a dedicated project containing the versioned legacy tem
This can be useful for offline setups or anyone wishing to use [Auto DevOps](../../topics/autodevops/index.md).
Instructions are available in the [legacy template project](https://gitlab.com/gitlab-org/auto-devops-v12-10).
+
+#### Vulnerabilities are found, but the job succeeds. How can I have a pipeline fail instead?
+
+This is the current default behavior, because the job's status indicates success or failure of the analyzer itself.
+Analyzer results are displayed in the [job logs](../../ci/jobs/index.md#expand-and-collapse-job-log-sections),
+[Merge Request widget](sast/index.md)
+or [Security Dashboard](security_dashboard/index.md).
+There is [an open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/235772) in which changes to this behavior are being discussed.
+
+### Enable or disable the basic security widget **(CORE ONLY)**
+
+The basic security widget is under development but ready for production use.
+It is deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../feature_flags.md)
+can opt to disable it.
+
+To enable it:
+
+```ruby
+# For the instance
+Feature.enable(:core_security_mr_widget)
+# For a single project
+Feature.enable(:core_security_mr_widget, Project.find(<project id>))
+```
+
+To disable it:
+
+```ruby
+# For the instance
+Feature.disable(:core_security_mr_widget)
+# For a single project
+Feature.disable(:core_security_mr_widget, Project.find(<project id>))
+```
diff --git a/doc/user/application_security/offline_deployments/index.md b/doc/user/application_security/offline_deployments/index.md
index 3a7c0148388..35582aa20ed 100644
--- a/doc/user/application_security/offline_deployments/index.md
+++ b/doc/user/application_security/offline_deployments/index.md
@@ -66,8 +66,7 @@ external links exposed in the UI. These links might not be accessible within an
### Automatic remediation for vulnerabilities
-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
+The [automatic remediation for vulnerabilities](../index.md#automatic-remediation-for-vulnerabilities) feature is available for offline Dependency Scanning and Container Scanning, but may not work
depending on your instance's configuration. We can only suggest solutions, which are generally more
current versions that have been patched, when we are able to access up-to-date registry services
hosting the latest versions of that dependency or image.
@@ -214,3 +213,28 @@ do
ssh $GITLAB_HOST "sudo docker push ${registry}/analyzers/${i}:2"
done
```
+
+### Using GitLab Secure with AutoDevOps in an offline environment
+
+You can use GitLab AutoDevOps for Secure scans in an offline environment. However, you must first do
+these steps:
+
+1. Load the container images into the local registry. GitLab Secure leverages analyzer container
+ images to do the various scans. These images must be available as part of running AutoDevOps.
+ Before running AutoDevOps, follow the [above steps](#using-the-official-gitlab-template)
+ to load those container images into the local container registry.
+
+1. Set the pipeline variable to ensure that AutoDevOps looks in the right place for those images.
+ The AutoDevOps templates leverage the `SECURE_ANALYZERS_PREFIX` variable to identify the location
+ of analyzer images. This variable is discussed above in [Using the secure bundle created](#using-the-secure-bundle-created).
+ Ensure that you set this variable to the correct value for where you loaded the analyzer images.
+ You could consider doing this with a pipeline variable or by [modifying](../../../topics/autodevops/customize.md#customizing-gitlab-ciyml)
+ the `.gitlab-ci.yml` file directly.
+
+Once these steps are complete, GitLab has local copies of the Secure analyzers and is set up to use
+them instead of an Internet-hosted container image. This allows you to run Secure in AutoDevOps in
+an offline environment.
+
+Note that these steps are specific to GitLab Secure with AutoDevOps. Using other stages with
+AutoDevOps may require other steps covered in the
+[Auto DevOps documentation](../../../topics/autodevops/).
diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md
index 6167c0445f9..4cbd4496dea 100644
--- a/doc/user/application_security/sast/analyzers.md
+++ b/doc/user/application_security/sast/analyzers.md
@@ -4,7 +4,10 @@ group: Static Analysis
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# SAST Analyzers **(ULTIMATE)**
+# SAST Analyzers **(CORE)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3775) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.3.
+> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) to GitLab Core in 13.3.
SAST relies on underlying third party tools that are wrapped into what we call
"Analyzers". An analyzer is a
@@ -33,7 +36,7 @@ SAST supports the following official analyzers:
- [`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))
-The analyzers are published as Docker images that SAST will use to launch
+The analyzers are published as Docker images that SAST uses to launch
dedicated containers for each analysis.
SAST is pre-configured with a set of **default images** that are maintained by
@@ -77,12 +80,12 @@ variables:
SAST_DEFAULT_ANALYZERS: "bandit,flawfinder"
```
-`bandit` runs first. When merging the reports, SAST will
-remove the duplicates and will keep the `bandit` entries.
+`bandit` runs first. When merging the reports, SAST
+removes the duplicates and keeps the `bandit` entries.
### Disabling default analyzers
-Setting `SAST_DEFAULT_ANALYZERS` to an empty string will disable all the official
+Setting `SAST_DEFAULT_ANALYZERS` to an empty string disables all the official
default analyzers. In `.gitlab-ci.yml` define:
```yaml
@@ -121,7 +124,7 @@ The [Security Scanner Integration](../../../development/integrations/secure.md)
| Property / Tool | Apex | Bandit | Brakeman | ESLint security | SpotBugs | Flawfinder | Gosec | Kubesec Scanner | MobSF | NodeJsScan | PHP CS Security Audit | Security code Scan (.NET) | Sobelow |
| --------------------------------------- | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :---------------------: | :-------------------------: | :----------------: |
-| Severity | ✓ | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ð„‚ | ð„‚ |
+| Severity | ✓ | ✓ | ✓ | ð„‚ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ð„‚ | ð„‚ |
| Title | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Description | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ✓ | ð„‚ | ð„‚ | ✓ |
| File | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
@@ -129,11 +132,11 @@ The [Security Scanner Integration](../../../development/integrations/secure.md)
| End line | ✓ | ✓ | ð„‚ | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
| Start column | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ✓ | ✓ | ð„‚ |
| End column | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
-| External ID (e.g. CVE) | ð„‚ | ð„‚ | âš  | ð„‚ | âš  | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
+| External ID (for example, CVE) | ð„‚ | ð„‚ | âš  | ð„‚ | âš  | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
| URLs | ✓ | ð„‚ | ✓ | ð„‚ | âš  | ð„‚ | âš  | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
| Internal doc/explanation | ✓ | âš  | ✓ | ð„‚ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ✓ |
| Solution | ✓ | ð„‚ | ð„‚ | ð„‚ | âš  | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
-| Affected item (e.g. class or package) | ✓ | ð„‚ | ✓ | ð„‚ | ✓ | ✓ | ð„‚ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
+| Affected item (for example, class or package) | ✓ | ð„‚ | ✓ | ð„‚ | ✓ | ✓ | ð„‚ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
| Confidence | ð„‚ | ✓ | ✓ | ð„‚ | ✓ | x | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ✓ |
| Source code extract | ð„‚ | ✓ | ✓ | ✓ | ð„‚ | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
| Internal ID | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ✓ | ✓ | ✓ |
@@ -143,4 +146,4 @@ The [Security Scanner Integration](../../../development/integrations/secure.md)
- ð„‚ => we don't have that data or it would need to develop specific or inefficient/unreliable logic to obtain it.
The values provided by these tools are heterogeneous so they are sometimes
-normalized into common values (e.g., `severity`, `confidence`, etc).
+normalized into common values (for example, `severity`, `confidence`, and so on).
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index 9e4d4112ae8..49e194a9319 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -32,8 +32,8 @@ The results are sorted by the priority of the vulnerability:
1. Everything else
A pipeline consists of multiple jobs, including SAST and DAST scanning. If any job fails to finish
-for any reason, the security dashboard doesn't show SAST scanner output. For example, if the SAST
-job finishes but the DAST job fails, the security dashboard doesn't show SAST results. On failure,
+for any reason, the security dashboard does not show SAST scanner output. For example, if the SAST
+job finishes but the DAST job fails, the security dashboard does not show SAST results. On failure,
the analyzer outputs an [exit code](../../../development/integrations/secure.md#exit-code).
## Use cases
@@ -71,9 +71,9 @@ You can also [view our language roadmap](https://about.gitlab.com/direction/secu
| C/C++ | [Flawfinder](https://github.com/david-a-wheeler/flawfinder) | 10.7 |
| Elixir (Phoenix) | [Sobelow](https://github.com/nccgroup/sobelow) | 11.1 |
| Go | [Gosec](https://github.com/securego/gosec) | 10.7 |
-| Groovy ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 11.3 (Gradle) & 11.9 (Ant, Maven, SBT) |
+| Groovy ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/), and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 11.3 (Gradle) & 11.9 (Ant, Maven, SBT) |
| Helm Charts | [Kubesec](https://github.com/controlplaneio/kubesec) | 13.1 |
-| Java ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 10.6 (Maven), 10.8 (Gradle) & 11.9 (Ant, SBT) |
+| Java ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/), and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 10.6 (Maven), 10.8 (Gradle) & 11.9 (Ant, SBT) |
| Java (Android) | [MobSF (beta)](https://github.com/MobSF/Mobile-Security-Framework-MobSF) | 13.5 |
| JavaScript | [ESLint security plugin](https://github.com/nodesecurity/eslint-plugin-security) | 11.8 |
| Kotlin (Android) | [MobSF (beta)](https://github.com/MobSF/Mobile-Security-Framework-MobSF) | 13.5 |
@@ -84,7 +84,7 @@ You can also [view our language roadmap](https://about.gitlab.com/direction/secu
| Python ([pip](https://pip.pypa.io/en/stable/)) | [bandit](https://github.com/PyCQA/bandit) | 10.3 |
| React | [ESLint react plugin](https://github.com/yannickcr/eslint-plugin-react) | 12.5 |
| Ruby on Rails | [brakeman](https://brakemanscanner.org) | 10.3 |
-| Scala ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 11.0 (SBT) & 11.9 (Ant, Gradle, Maven) |
+| Scala ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/), and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 11.0 (SBT) & 11.9 (Ant, Gradle, Maven) |
| Swift (iOS) | [MobSF (beta)](https://github.com/MobSF/Mobile-Security-Framework-MobSF) | 13.5 |
| TypeScript | [ESLint security plugin](https://github.com/nodesecurity/eslint-plugin-security) | 11.9, [merged](https://gitlab.com/gitlab-org/gitlab/-/issues/36059) with ESLint in 13.2 |
@@ -107,10 +107,11 @@ as shown in the following table:
| [Configure SAST Scanners](#configuration) | **{check-circle}** | **{check-circle}** |
| [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}** |
+| Presentation of JSON Report in Merge Request | **{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}** |
+| [Customize SAST Rulesets](#customize-rulesets) | **{dotted-circle}** | **{check-circle}** |
## Contribute your scanner
@@ -162,7 +163,7 @@ page:
1. Enter the custom SAST values.
Custom values are stored in the `.gitlab-ci.yml` file. For variables not in the SAST Configuration page, their values are left unchanged. Default values are inherited from the GitLab SAST template.
-1. Optionally, expand the **SAST analyzers** section, select individual [SAST analyzers](./analyzers.md) and enter custom analyzer values.
+1. Optionally, expand the **SAST analyzers** section, select individual [SAST analyzers](analyzers.md) and enter custom analyzer values.
1. Click **Create Merge Request**.
1. Review and merge the merge request.
@@ -205,15 +206,21 @@ spotbugs-sast:
FAIL_NEVER: 1
```
-### Custom rulesets
+### Customize rulesets **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235382) in GitLab 13.5.
-You can customize the default scanning rules provided with SAST's NodeJS-Scan and Gosec analyzers.
-Customization allows you to exclude rules and modify the behavior of existing rules.
+You can customize the default scanning rules provided by our SAST analyzers.
+
+Ruleset customization supports two capabilities:
+
+1. Disabling predefined rules
+1. Modifying the default behavior of a given analyzer
+
+These capabilities can be used simultaneously.
To customize the default scanning rules, create a file containing custom rules. These rules
-are passed through to the analyzer's underlying scanner tool.
+are passed through to the analyzer's underlying scanner tools.
To create a custom ruleset:
@@ -221,6 +228,25 @@ To create a custom ruleset:
1. Create a custom ruleset file named `sast-ruleset.toml` in the `.gitlab` directory.
1. In the `sast-ruleset.toml` file, do one of the following:
+ - Disable predefined rules belonging to SAST analyzers. In this example, the disabled rules
+ belong to `eslint` and `sobelow` and have the corresponding identifiers `type` and `value`:
+
+ ```toml
+ [eslint]
+ [[eslint.ruleset]]
+ disable = true
+ [eslint.ruleset.identifier]
+ type = "eslint_rule_id"
+ value = "security/detect-object-injection"
+
+ [sobelow]
+ [[sobelow.ruleset]]
+ disable = true
+ [sobelow.ruleset.identifier]
+ type = "sobelow_rule_id"
+ value = "sql_injection"
+ ```
+
- Define a custom analyzer configuration. In this example, customized rules are defined for the
`nodejs-scan` scanner:
@@ -285,7 +311,7 @@ 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 Kubesec analyzer
+### Enabling Kubesec analyzer
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12752) in GitLab Ultimate 12.6.
@@ -300,7 +326,7 @@ variables:
SCAN_KUBERNETES_MANIFESTS: "true"
```
-#### Pre-compilation
+### Pre-compilation
If your project requires custom build configurations, it can be preferable to avoid
compilation during your SAST execution and instead pass all job artifacts from an
@@ -398,7 +424,7 @@ Some analyzers can be customized with environment variables.
| Environment variable | Analyzer | Description |
|---------------------------------------|----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `SCAN_KUBERNETES_MANIFESTS` | Kubesec | Set to `"true"` to scan Kubernetes manifests. |
-| `KUBESEC_HELM_CHARTS_PATH` | Kubesec | Optional path to Helm charts that `helm` will use to generate a Kubernetes manifest that `kubesec` will scan. If dependencies are defined, `helm dependency build` should be ran in a `before_script` to fetch the necessary dependencies. |
+| `KUBESEC_HELM_CHARTS_PATH` | Kubesec | Optional path to Helm charts that `helm` uses to generate a Kubernetes manifest that `kubesec` will scan. If dependencies are defined, `helm dependency build` should be ran in a `before_script` to fetch the necessary dependencies. |
| `KUBESEC_HELM_OPTIONS` | Kubesec | Additional arguments for the `helm` executable. |
| `COMPILE` | SpotBugs | Set to `false` to disable project compilation and dependency fetching. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195252) in GitLab 13.1. |
| `ANT_HOME` | SpotBugs | The `ANT_HOME` environment variable. |
@@ -426,7 +452,7 @@ to the underlying SAST analyzer images if
[the SAST vendored template](#configuration) is used.
CAUTION: **Caution:**
-Variables having names starting with these prefixes will **not** be propagated to the SAST Docker container and/or
+Variables having names starting with these prefixes are **not** propagated to the SAST Docker container and/or
analyzer containers: `DOCKER_`, `CI`, `GITLAB_`, `FF_`, `HOME`, `PWD`, `OLDPWD`, `PATH`, `SHLVL`, `HOSTNAME`.
### Experimental features
@@ -642,7 +668,7 @@ security reports without requiring internet access.
### Configure certificate checking of packages
If a SAST job invokes a package manager, you must configure its certificate verification. In an
-offline environment, certificate verification with an external source isn't possible. Either use a
+offline environment, certificate verification with an external source is not possible. Either use a
self-signed certificate or disable certificate verification. Refer to the package manager's
documentation for instructions.
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index bb10e9d7315..025a37f684d 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -5,9 +5,10 @@ group: Static Analysis
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Secret Detection **(ULTIMATE)**
+# Secret Detection
-> [Introduced](https://about.gitlab.com/releases/2019/03/22/gitlab-11-9-released/#detect-secrets-and-credentials-in-the-repository) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9.
+> - [Introduced](https://about.gitlab.com/releases/2019/03/22/gitlab-11-9-released/#detect-secrets-and-credentials-in-the-repository) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9.
+> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/222788) in 13.3.
A recurring problem when developing applications is that developers may unintentionally commit
secrets and credentials to their remote repositories. If other people have access to the source,
@@ -30,6 +31,29 @@ GitLab displays identified secrets visibly in a few places:
- Detecting unintentional commit of secrets like keys, passwords, and API tokens.
- Performing a single or recurring scan of the full history of your repository for secrets.
+## Supported secrets
+
+Secret Detection detects a variety of common secrets by default. You can also customize the secret detection patterns using [custom rulesets](#custom-rulesets).
+
+The [default ruleset provided by Gitleaks](https://gitlab.com/gitlab-org/security-products/analyzers/secrets/-/blob/master/gitleaks/gitleaks.toml) includes the following key types:
+
+- Cloud services:
+ - Amazon Web Services (AWS)
+ - Google Cloud Platform (GCP)
+Encryption keys:
+ - PKCS8
+ - RSA
+ - SSH
+ - PGP
+- Social media platforms:
+ - Facebook API
+ - Twitter API
+- Cloud SaaS vendors:
+ - GitHub API
+ - Slack Token
+ - Stripe API
+ - Generic API key strings starting with `api-`
+
## Requirements
To run Secret Detection jobs, by default, you need GitLab Runner with the
@@ -59,7 +83,7 @@ as shown in the following table:
| [Configure Secret Detection Scanners](#configuration) | **{check-circle}** | **{check-circle}** |
| [Customize Secret Detection Settings](#customizing-settings) | **{check-circle}** | **{check-circle}** |
| View [JSON Report](../sast/index.md#reports-json-format) | **{check-circle}** | **{check-circle}** |
-| [Presentation of JSON Report in Merge Request](#overview) | **{dotted-circle}** | **{check-circle}** |
+| Presentation of JSON Report in Merge Request | **{dotted-circle}** | **{check-circle}** |
| [Interaction with Vulnerabilities](../vulnerabilities/index.md) | **{dotted-circle}** | **{check-circle}** |
| [Access to Security Dashboard](../security_dashboard/index.md) | **{dotted-circle}** | **{check-circle}** |
@@ -102,6 +126,18 @@ The results are saved as a
that you can later download and analyze. Due to implementation limitations, we
always take the latest Secret Detection artifact available.
+### Post-processing
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/46390) in GitLab 13.6.
+
+Upon detection of a secret, GitLab supports post processing hooks. These can be used to take actions like notifying the cloud service who issued the secret. The cloud provider can confirm the credentials and take remediation actions like revoking or reissuing a new secret and notifying the creator of the secret. Post-processing workflows vary by supported cloud providers.
+
+GitLab currently supports post-processing for following service providers:
+
+- Amazon Web Services (AWS)
+
+Third party cloud and SaaS providers can [express integration interest by filling out this form](https://forms.gle/wWpvrtLRK21Q2WJL9). Learn more about the [technical details of post-processing secrets](https://gitlab.com/groups/gitlab-org/-/epics/4639).
+
### Customizing settings
The Secret Detection scan settings can be changed through [environment variables](#available-variables)
@@ -142,7 +178,7 @@ Secret Detection can be customized by defining available variables:
| `SECRET_DETECTION_EXCLUDED_PATHS` | "" | Exclude vulnerabilities from output based on the paths. This is a comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec` ). Parent directories also match patterns. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225273) in GitLab 13.3. |
| `SECRET_DETECTION_HISTORIC_SCAN` | false | Flag to enable a historic Gitleaks scan. |
-### Custom rulesets
+### Custom rulesets **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211387) in GitLab 13.5.
diff --git a/doc/user/application_security/security_dashboard/img/group_security_dashboard_export_csv_v13_1.png b/doc/user/application_security/security_dashboard/img/group_security_dashboard_export_csv_v13_1.png
deleted file mode 100644
index 8fab4e39175..00000000000
--- a/doc/user/application_security/security_dashboard/img/group_security_dashboard_export_csv_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/project_security_dashboard_chart_v13_6.png b/doc/user/application_security/security_dashboard/img/project_security_dashboard_chart_v13_6.png
new file mode 100644
index 00000000000..6ccae80e80e
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/project_security_dashboard_chart_v13_6.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/project_security_dashboard_export_csv_v12_10.png b/doc/user/application_security/security_dashboard/img/project_security_dashboard_export_csv_v12_10.png
deleted file mode 100644
index 07b41b471d4..00000000000
--- a/doc/user/application_security/security_dashboard/img/project_security_dashboard_export_csv_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md
index 5fa8ebb80e0..1b038ef76a0 100644
--- a/doc/user/application_security/security_dashboard/index.md
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -9,15 +9,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w
GitLab provides a comprehensive set of features for viewing and managing vulnerabilities:
-- Security dashboards: An overview of the security status in your instance, groups, and projects.
-- Vulnerability reports: Detailed lists of all vulnerabilities for the instance, group, project, or
+- Security dashboards: An overview of the security status in your instance, [groups](#group-security-dashboard), and
+ [projects](#project-security-dashboard).
+- [Vulnerability reports](#vulnerability-report): Detailed lists of all vulnerabilities for the instance, group, project, or
pipeline. This is where you triage and manage vulnerabilities.
-- Security Center: A dedicated area for vulnerability management at the instance level. This
+- [Security Center](#instance-security-center): A dedicated area for vulnerability management at the instance level. This
includes a security dashboard, vulnerability report, and settings.
-You can also drill down into a vulnerability and get extra information. This includes the project it
-comes from, any related file(s), and metadata that helps you analyze the risk it poses. You can also
-dismiss a vulnerability or create an issue for it.
+You can also drill down into a vulnerability and get extra information on the
+[Vulnerability Page](../vulnerabilities/index.md). This view includes the project it
+comes from, any related file(s), and metadata that helps you analyze the risk it poses.
+You can also confirm, dismiss, or resolve a vulnerability, create an issue for it,
+and in some cases, generate a merge request to fix the vulnerability.
To benefit from these features, you must first configure one of the
[security scanners](../index.md).
@@ -30,7 +33,7 @@ The vulnerability report displays vulnerabilities detected by scanners such as:
- [Dynamic Application Security Testing](../dast/index.md)
- [Dependency Scanning](../dependency_scanning/index.md)
- [Static Application Security Testing](../sast/index.md)
-- And others!
+- And [others](../index.md#security-scanning-tools)!
## Requirements
@@ -60,43 +63,67 @@ job finishes but the DAST job fails, the security dashboard doesn't show SAST re
the analyzer outputs an
[exit code](../../../development/integrations/secure.md#exit-code).
+You can filter the vulnerabilities list by selecting from the **Severity** and **Scanner** dropdowns.
+
## Project Security Dashboard
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235558) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.6.
+
+At the project level, the Security Dashboard displays a chart with the number of vulnerabilities over time.
+Access it by navigating to **Security & Compliance > Security Dashboard**. Currently, we display historical
+data up to 365 days.
+
+![Project Security Dashboard](img/project_security_dashboard_chart_v13_6.png)
+
+Filter the historical data by clicking on the corresponding legend name. The image above, for example, shows
+only the graph for vulnerabilities with **high** severity.
+
+### Vulnerability Report
+
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6165) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.1.
-At the project level, the Security Dashboard displays the vulnerabilities merged into your project's
-[default branch](../../project/repository/branches/index.md#default-branch). Access it by navigating
-to **Security & Compliance > Security Dashboard**. By default, the Security Dashboard displays all
-detected and confirmed vulnerabilities.
+The vulnerabilities that exist in your project's
+[default branch](../../project/repository/branches/index.md#default-branch) are accessed by navigating to
+**Security & Compliance > Vulnerability Report**. By default, the Vulnerability Report is filtered to
+display all detected and confirmed vulnerabilities.
-The Security Dashboard first displays the time at which the last pipeline completed on the project's
-default branch. There's also a link to view this in more detail.
+The Vulnerability Report first displays the time at which the last pipeline completed on the project's
+default branch. There's also a link to view this in more detail. In the case of any pipeline failures,
+you will see the number of failures clearly indicated. The failure notification takes you directly to
+the **Failed jobs** tab of the pipeline page.
-The Security Dashboard next displays the total number of vulnerabilities by severity (for example,
+The Vulnerability Report next displays the total number of vulnerabilities by severity (for example,
Critical, High, Medium, Low, Info, Unknown). Below this, a table shows each vulnerability's status, severity,
and description. Clicking a vulnerability takes you to its [Vulnerability Details](../vulnerabilities)
page to view more information about that vulnerability.
-![Project Security Dashboard](img/project_security_dashboard_v13_5.png)
+![Project Vulnerability Report](img/project_security_dashboard_v13_5.png)
You can filter the vulnerabilities by one or more of the following:
-- Status
-- Severity
-- Scanner
+| Filter | Available Options |
+| --- | --- |
+| Status | Detected, Confirmed, Dismissed, Resolved |
+| Severity | Critical, High, Medium, Low, Info, Unknown |
+| Scanner | [Available Scanners](../index.md#security-scanning-tools) |
+
+You can filter the vulnerabilities list by selecting from the **Status**, **Severity**, and
+**Scanner** dropdowns. In the **Scanner** dropdown, select individual scanners or scanner groups to
+toggle those scanners. The **Scanner** dropdown includes both GitLab scanners, and in GitLab 13.6
+and later, custom scanners.
You can also dismiss vulnerabilities in the table:
1. Select the checkbox for each vulnerability you want to dismiss.
1. In the menu that appears, select the reason for dismissal and click **Dismiss Selected**.
-![Project Security Dashboard](img/project_security_dashboard_dismissal_v13_4.png)
+![Project Vulnerability Report](img/project_security_dashboard_dismissal_v13_4.png)
## Group Security Dashboard
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6709) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5.
-The group Security Dashboard gives an overview of the vulnerabilities in the default branches of the
+The group Security Dashboard gives an overview of the vulnerabilities found in the default branches of the
projects in a group and its subgroups. Access it by navigating to **Security > Security Dashboard**
after selecting your group. By default, the Security Dashboard displays all detected and confirmed
vulnerabilities. If you don't see the vulnerabilities over time graph, the likely cause is that you
@@ -111,20 +138,21 @@ enabled in a group.
There is a timeline chart that shows how many open
vulnerabilities your projects had at various points in time. You can display the vulnerability
trends over a 30, 60, or 90-day time frame (the default is 90 days). Hover over the chart to get
-more details about the open vulnerabilities at a specific time.
+more details about the open vulnerabilities at a specific time. Aggregated data beyond 90 days can be accessed by querying our [VulnerabilitiesCountByDay GraphQL API](../../../api/graphql/reference/index.md#vulnerabilitiescountbyday). This data is retained for 365 days.
Next to the timeline chart is a list of projects, grouped and sorted by the severity of the vulnerability found:
-- F: One or more "critical"
-- D: One or more "high" or "unknown"
-- C: One or more "medium"
-- B: One or more "low"
-- A: Zero vulnerabilities
+| Grade | Description |
+| F | One or more "critical" |
+| D | One or more "high" or "unknown" |
+| C | One or more "medium" |
+| B | One or more "low" |
+| A | Zero vulnerabilities |
Projects with no vulnerability tests configured will not appear in the list. Additionally, dismissed
vulnerabilities are excluded.
-Navigate to the group's [vulnerability report](#vulnerability-report) to view the vulnerabilities found.
+Navigate to the group's [vulnerability report](#vulnerability-report-1) to view the vulnerabilities found.
## Instance Security Center
@@ -232,10 +260,17 @@ into the default branch.
You can filter which vulnerabilities the vulnerability report displays by:
-- Status
-- Severity
-- Scanner
-- Project
+| Filter | Available Options |
+| --- | --- |
+| Status | Detected, Confirmed, Dismissed, Resolved |
+| Severity | Critical, High, Medium, Low, Info, Unknown |
+| Scanner | [Available Scanners](../index.md#security-scanning-tools) |
+| Project | Projects configured in the Security Center settings |
+
+You can filter the vulnerabilities list by selecting from the **Status**, **Severity**, and
+**Scanner**, and **Project** dropdowns. In the **Scanner** dropdown, select individual scanners or
+scanner groups to toggle those scanners. The **Scanner** dropdown includes both GitLab scanners, and
+in GitLab 13.6 and later, custom scanners.
Clicking any vulnerability in the table takes you to its
[Vulnerability Details](../vulnerabilities) page to see more information on that vulnerability.
diff --git a/doc/user/application_security/threat_monitoring/index.md b/doc/user/application_security/threat_monitoring/index.md
index 391666a077e..f85d4f0140c 100644
--- a/doc/user/application_security/threat_monitoring/index.md
+++ b/doc/user/application_security/threat_monitoring/index.md
@@ -1,6 +1,6 @@
---
type: reference, howto
-stage: Defend
+stage: Protect
group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
diff --git a/doc/user/application_security/vulnerabilities/img/vulnerability_page_download_patch_button_v13_1.png b/doc/user/application_security/vulnerabilities/img/vulnerability_page_download_patch_button_v13_1.png
deleted file mode 100644
index b925c342a11..00000000000
--- a/doc/user/application_security/vulnerabilities/img/vulnerability_page_download_patch_button_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 ee3fd6c4dd4..95bb1ff1a67 100644
--- a/doc/user/application_security/vulnerabilities/index.md
+++ b/doc/user/application_security/vulnerabilities/index.md
@@ -11,10 +11,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Each security vulnerability in a project's [Security Dashboard](../security_dashboard/index.md#project-security-dashboard) has an individual page which includes:
-- Details of the vulnerability.
+- Details for the vulnerability.
- The status of the vulnerability within the project.
- Available actions for the vulnerability.
-- Issues related to the vulnerability.
+- Any issues related to the vulnerability.
On the vulnerability page, you can interact with the vulnerability in
several different ways:
@@ -25,22 +25,22 @@ several different ways:
title and description pre-populated with information from the vulnerability report.
By default, such issues are [confidential](../../project/issues/confidential_issues.md).
- [Link issues](#link-issues-to-the-vulnerability) - Link existing issues to vulnerability.
-- [Solution](#automatic-remediation-for-vulnerabilities) - For some vulnerabilities,
- a solution is provided for how to fix the vulnerability.
+- [Automatic remediation](#automatic-remediation-for-vulnerabilities) - For some vulnerabilities,
+ a solution is provided for how to fix the vulnerability automatically.
## Changing vulnerability status
You can switch the status of a vulnerability using the **Status** dropdown to one of
the following values:
-| Status | Description |
-|-----------|-------------------------------------------------------------------|
-| Detected | The default state for a newly discovered vulnerability |
-| Confirmed | A user has seen this vulnerability and confirmed it to be real |
-| Dismissed | A user has seen this vulnerability and dismissed it |
-| Resolved | The vulnerability has been fixed and is no longer in the codebase |
+| Status | Description |
+|-----------|------------------------------------------------------------------------------------------------------------------|
+| Detected | The default state for a newly discovered vulnerability |
+| Confirmed | A user has seen this vulnerability and confirmed it to be accurate |
+| Dismissed | A user has seen this vulnerability and dismissed it because it is not accurate or otherwise will not be resolved |
+| Resolved | The vulnerability has been fixed and is no longer valid |
-A timeline shows you when the vulnerability status has changed,
+A timeline shows you when the vulnerability status has changed
and allows you to comment on a change.
## Creating an issue for a vulnerability
@@ -48,7 +48,7 @@ and allows you to comment on a change.
You can create an issue for a vulnerability by selecting the **Create issue** button.
This creates a [confidential issue](../../project/issues/confidential_issues.md) in the
-project the vulnerability came from, and pre-populates it with useful information from
+project the vulnerability came from and pre-populates it with useful information from
the vulnerability report. After the issue is created, GitLab redirects you to the
issue page so you can edit, assign, or comment on the issue.
@@ -61,4 +61,4 @@ that the resolution of one issue would resolve multiple vulnerabilities.
## Automatic remediation for vulnerabilities
You can fix some vulnerabilities by applying the solution that GitLab automatically
-generates for you. [Read more about the automatic remediation for vulnerabilities feature](../index.md#solutions-for-vulnerabilities-auto-remediation).
+generates for you. [Read more about the automatic remediation for vulnerabilities feature](../index.md#automatic-remediation-for-vulnerabilities).
diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md
index 196c3e9fb43..74c679d9bb9 100644
--- a/doc/user/clusters/agent/index.md
+++ b/doc/user/clusters/agent/index.md
@@ -24,9 +24,11 @@ tasks in a secure and cloud-native way. It enables:
Many more features are planned. Please [review our roadmap](https://gitlab.com/groups/gitlab-org/-/epics/3329).
-## Architecture
+## GitLab Agent GitOps workflow
-### GitLab Agent GitOps workflow
+The GitLab Agent uses multiple GitLab projects to provide a flexible workflow
+that can suit various needs. This diagram shows these repositories and the main
+actors involved in a deployment:
```mermaid
sequenceDiagram
@@ -44,11 +46,6 @@ sequenceDiagram
end
```
-Please refer to our [full architecture documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md#high-level-architecture)
-in the Agent project.
-
-## Get started with GitOps and the GitLab Agent
-
There are several components that work in concert for the Agent to accomplish GitOps deployments:
- A properly-configured Kubernetes cluster.
@@ -57,51 +54,93 @@ There are several components that work in concert for the Agent to accomplish Gi
- A manifest repository that contains a `manifest.yaml`, which is tracked by the
Agent and can be auto-generated. Any changes to `manifest.yaml` are applied to the cluster.
+These repositories might be the same GitLab project or separate projects.
+
+For more details, please refer to our [full architecture documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md#high-level-architecture) in the Agent project.
+
+## Get started with GitOps and the GitLab Agent
+
The setup process involves a few steps to enable GitOps deployments:
-1. Installing the Agent server.
-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`.
+1. [Install the Agent server](#install-the-kubernetes-agent-server).
+1. [Define a configuration repository](#define-a-configuration-repository).
+1. [Create an Agent record in GitLab](#create-an-agent-record-in-gitlab).
+1. [Generate and copy a Secret token used to connect to the Agent](#create-the-kubernetes-secret).
+1. [Install the Agent into the cluster](#install-the-agent-into-the-cluster).
+1. [Create a `manifest.yaml`](#create-a-manifestyaml).
+
+### Upgrades and version compatibility
+
+As the GitLab Kubernetes Agent is a new product, we are constantly adding new features
+to it. As a result, while shipped features are production ready, its internal API is
+neither stable nor versioned yet. For this reason, GitLab only guarantees compatibility
+between corresponding major.minor (X.Y) versions of GitLab and its cluster side
+component, `agentk`.
+
+Upgrade your agent installations together with GitLab upgrades. To decide which version of `agentk`to install follow:
+
+1. Open the [GITLAB_KAS_VERSION](https://gitlab.com/gitlab-org/gitlab/-/blob/master/GITLAB_KAS_VERSION) file from the GitLab Repository, which contains the latest `agentk` version associated with the `master` branch.
+1. Change the `master` branch and select the Git tag associated with your version. For instance, you could change it to GitLab [v13.5.3-ee release](https://gitlab.com/gitlab-org/gitlab/-/blob/v13.5.3-ee/GITLAB_KAS_VERSION)
-### Install the Agent server
+The available `agentk` versions can be found in
+[its container registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/eyJuYW1lIjoiZ2l0bGFiLW9yZy9jbHVzdGVyLWludGVncmF0aW9uL2dpdGxhYi1hZ2VudC9hZ2VudGsiLCJ0YWdzX3BhdGgiOiIvZ2l0bGFiLW9yZy9jbHVzdGVyLWludGVncmF0aW9uL2dpdGxhYi1hZ2VudC9yZWdpc3RyeS9yZXBvc2l0b3J5LzEyMjMyMDUvdGFncz9mb3JtYXQ9anNvbiIsImlkIjoxMjIzMjA1LCJjbGVhbnVwX3BvbGljeV9zdGFydGVkX2F0IjpudWxsfQ==).
-The GitLab Kubernetes Agent can be deployed using [Omnibus
+### Install the Kubernetes Agent Server
+
+The GitLab Kubernetes Agent Server (KAS) can be deployed using [Omnibus
GitLab](https://docs.gitlab.com/omnibus/) or the [GitLab
chart](https://gitlab.com/gitlab-org/charts/gitlab). If you don't already have
GitLab installed, please refer to our [installation
documentation](https://docs.gitlab.com/ee/install/README.html).
NOTE: **Note:**
-GitLab plans to include the Agent on [GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/3834).
+GitLab plans to include the KAS on [GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/3834).
+
+#### Install with Omnibus
When using the [Omnibus GitLab](https://docs.gitlab.com/omnibus/) package:
1. Edit `/etc/gitlab/gitlab.rb`:
-```plaintext
-gitlab_kas['enable'] = true
-```
+ ```plaintext
+ gitlab_kas['enable'] = true
+ ```
1. [Reconfigure GitLab](../../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
-When installing or upgrading the GitLab Helm chart, consider the following Helm 2 example.
-(If you're using Helm 3, you must modify this example.) You must set `global.kas.enabled=true`
-for the Agent to be properly installed and configured:
+To configure any additional options related to GitLab Kubernetes Agent Server,
+refer to the **Enable GitLab KAS** section of the
+[`gitlab.rb.template`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/master/files/gitlab-config-template/gitlab.rb.template).
+
+#### Install with the Helm chart
+
+When installing or upgrading the GitLab Helm chart, consider the following Helm v3 example.
+If you're using Helm v2, you must modify this example. See our [notes regarding deploy with Helm](https://docs.gitlab.com/charts/installation/deployment.html#deploy-using-helm).
+
+You must set `global.kas.enabled=true` for the KAS to be properly installed and configured:
```shell
+helm repo add gitlab https://charts.gitlab.io/
helm repo update
-helm upgrade --force --install gitlab gitlab/gitlab \
- --timeout 600 \
+helm upgrade --install gitlab gitlab/gitlab \
+ --timeout 600s \
--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
```
+To specify other options related to the KAS sub-chart, create a `gitlab.kas` sub-section
+of your `values.yaml` file:
+
+```shell
+gitlab:
+ kas:
+ # put your KAS custom options here
+```
+
+For details, read [Using the GitLab-KAS chart](https://docs.gitlab.com/charts/charts/gitlab/kas/).
+
### Define a configuration repository
Next, you need a GitLab repository to contain your Agent configuration. The minimal
@@ -111,12 +150,33 @@ repository layout looks like this:
.gitlab/agents/<agent-name>/config.yaml
```
-The `config.yaml` file contents should look like this:
+Your `config.yaml` file can specify multiple manifest projects in the
+section `manifest_projects`:
+
+```yaml
+gitops:
+ manifest_projects:
+ - id: "path-to/your-manifest-project-number1"
+ ...
+```
+
+GitLab [versions 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) also
+supports manifest projects containing multiple directories (or subdirectories)
+of YAML files. To use multiple YAML files, specify a `paths` attribute:
```yaml
gitops:
manifest_projects:
- - id: "path-to/your-awesome-project"
+ - id: "path-to/your-manifest-project-number1"
+ paths:
+ # Read all .yaml files from team1/app1 directory.
+ # See https://github.com/bmatcuk/doublestar#about and
+ # https://pkg.go.dev/github.com/bmatcuk/doublestar/v2#Match for globbing rules.
+ - glob: '/team1/app1/*.yaml'
+ # Read all .yaml files from team2/apps and all subdirectories
+ - glob: '/team2/apps/**/*.yaml'
+ # If 'paths' is not specified or is an empty list, the configuration below is used
+ - glob: '/**/*.{yaml,yml,json}'
```
### Create an Agent record in GitLab
@@ -125,20 +185,24 @@ Next, create an GitLab Rails Agent record so the Agent can associate itself with
the configuration repository project. Creating this record also creates a Secret needed to configure
the Agent in subsequent steps. You can create an Agent record either:
-- Through the Rails console, by running `rails c`:
+- Through the Rails console:
```ruby
- project = ::Project.find_by_full_path("path-to/your-awesome-project")
+ project = ::Project.find_by_full_path("path-to/your-configuration-project")
+ # agent-name should be the same as specified above in the config.yaml
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
```
+ For full details, read [Starting a Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session).
+
- Through GraphQL: **(PREMIUM ONLY)**
```graphql
mutation createAgent {
- createClusterAgent(input: { projectPath: "path-to/your-awesome-project", name: "<agent-name>" }) {
+ # agent-name should be the same as specified above in the config.yaml
+ createClusterAgent(input: { projectPath: "path-to/your-configuration-project", name: "<agent-name>" }) {
clusterAgent {
id
name
@@ -160,7 +224,7 @@ the Agent in subsequent steps. You can create an Agent record either:
```
NOTE: **Note:**
- GraphQL only displays the token once, after creating it.
+ GraphQL only displays the token one time after creating it.
If you are new to using the GitLab GraphQL API, refer to the
[Getting started with the GraphQL API page](../../../api/graphql/getting_started.md),
@@ -170,7 +234,7 @@ the Agent in subsequent steps. You can create an Agent record either:
After generating the token, you must apply it to the Kubernetes cluster.
-1. If you haven't previous defined or created a namespace, run the following command:
+1. If you haven't previously defined or created a namespace, run the following command:
```shell
kubectl create namespace <YOUR-DESIRED-NAMESPACE>
@@ -188,43 +252,40 @@ Next, install the in-cluster component of the Agent. This example file contains
Kubernetes resources required for the Agent to be installed. You can modify this
example [`resources.yml` file](#example-resourcesyml-file) in the following ways:
-- You can replace `gitlab-agent` with `<YOUR-DESIRED-NAMESPACE>`.
-- For the `kas-address` (Kubernetes Agent Server), the agent can use the WebSockets
- or gRPC protocols to connect to the Agent Server. Depending on your cluster
- configuration and GitLab architecture, you may need to use one or the other.
- For the `gitlab-kas` Helm chart, an Ingress is created for the Agent Server using
- the `/-/kubernetes-agent` endpoint. This can be used for the WebSockets protocol connection.
- - Specify the `grpc` scheme (such as `grpc://gitlab-kas:5005`) to use gRPC directly.
- Encrypted gRPC is not supported yet. Follow the
+- Replace `namespace: gitlab-agent` with `namespace: <YOUR-DESIRED-NAMESPACE>`.
+- You can configure `kas-address` (Kubernetes Agent Server) in several ways.
+ The agent can use the WebSockets or gRPC protocols to connect to the Agent Server.
+ Select the option appropriate for your cluster configuration and GitLab architecture:
+ - The `wss` scheme (an encrypted WebSockets connection) is specified by default
+ after you install `gitlab-kas` sub-chart or enable `kas` for Omnibus GitLab.
+ In this case, you must set `wss://GitLab.host.tld:443/-/kubernetes-agent` as
+ `kas-address`, where `GitLab.host.tld` is your GitLab hostname.
+ - Specify the `ws` scheme (such as `ws://GitLab.host.tld:80/-/kubernetes-agent`)
+ to use an unencrypted WebSockets connection.
+ - Specify the `grpc` scheme if both Agent and Server are installed in one cluster.
+ In this case, you may specify `kas-address` value as
+ `grpc://gitlab-kas.<your-namespace>:5005`) to use gRPC directly, where `gitlab-kas`
+ is the name of the service created by `gitlab-kas` chart, and `your-namespace`
+ is the namespace where the chart was installed. Encrypted gRPC is not supported yet.
+ Follow the
[Support TLS for gRPC communication issue](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/7)
for progress updates.
- - Specify the `ws` scheme (such as `ws://gitlab-kas-ingress:80/-/kubernetes-agent`)
- to use an unencrypted WebSockets connection.
- - Specify the `wss` scheme (such as `wss://gitlab-kas-ingress:443/-/kubernetes-agent`)
- to use an encrypted WebSockets connection. This is the recommended option if
- installing the Agent into a separate cluster from your Agent Server.
-- If you defined your own secret name, replace `gitlab-agent-token` with your secret name.
+- If you defined your own secret name, replace `gitlab-agent-token` with your
+ secret name in the `secretName:` section.
To apply this file, run the following command:
```shell
-kubectl apply -n gitlab-agent -f ./resources.yml
+kubectl apply -n <YOUR-DESIRED-NAMESPACE> -f ./resources.yml
```
To review your configuration, run the following command:
```shell
-$ kubectl get pods --all-namespaces
+$ kubectl get pods -n <YOUR-DESIRED-NAMESPACE>
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
```
#### Example `resources.yml` file
@@ -256,7 +317,7 @@ spec:
args:
- --token-file=/config/token
- --kas-address
- - grpc://host.docker.internal:5005 # {"$openapi":"kas-address"}
+ - wss://gitlab.host.tld:443/-/kubernetes-agent
volumeMounts:
- name: token-volume
mountPath: /config
@@ -331,7 +392,9 @@ subjects:
In a previous step, you configured a `config.yaml` to point to the GitLab projects
the Agent should synchronize. In each of those projects, you must create a `manifest.yaml`
file for the Agent to monitor. You can auto-generate this `manifest.yaml` with a
-templating engine or other means.
+templating engine or other means. Only public projects are supported as
+manifest projects. Support for private projects is planned in the issue
+[Agent authorization for private manifest projects](https://gitlab.com/gitlab-org/gitlab/-/issues/220912).
Each time you commit and push a change to this file, the Agent logs the change:
@@ -341,7 +404,7 @@ Each time you commit and push a change to this file, the Agent logs the change:
#### Example `manifest.yaml` file
-This file creates a simple NGINX deployment.
+This file creates an NGINX deployment.
```yaml
apiVersion: apps/v1
@@ -368,7 +431,128 @@ spec:
## Example projects
+The following example projects can help you get started with the Kubernetes Agent.
+
+### Simple NGINX deployment
+
This basic GitOps example deploys NGINX:
- [Configuration repository](https://gitlab.com/gitlab-org/configure/examples/kubernetes-agent)
- [Manifest repository](https://gitlab.com/gitlab-org/configure/examples/gitops-project)
+
+### Deploying GitLab Runner with the Agent
+
+These instructions assume that the Agent is already set up as described in the
+[Get started with GitOps](#get-started-with-gitops-and-the-gitlab-agent):
+
+1. Check the possible
+ [Runner chart YAML values](https://gitlab.com/gitlab-org/charts/gitlab-runner/blob/master/values.yaml)
+ on the Runner chart documentation, and create a `runner-chart-values.yaml` file
+ with the configuration that fits your needs, such as:
+
+ ```yaml
+ ## The GitLab Server URL (with protocol) that want to register the runner against
+ ## ref: https://docs.gitlab.com/runner/commands/README.html#gitlab-runner-register
+ ##
+ gitlabUrl: https://gitlab.my.domain.com/
+
+ ## The Registration Token for adding new Runners to the GitLab Server. This must
+ ## be retrieved from your GitLab Instance.
+ ## ref: https://docs.gitlab.com/ce/ci/runners/README.html
+ ##
+ runnerRegistrationToken: "XXXXXXYYYYYYZZZZZZ"
+
+ ## For RBAC support:
+ rbac:
+ create: true
+
+ ## Run all containers with the privileged flag enabled
+ ## This will allow the docker:dind image to run if you need to run Docker
+ ## commands. Please read the docs before turning this on:
+ ## ref: https://docs.gitlab.com/runner/executors/kubernetes.html#using-dockerdind
+ runners:
+ privileged: true
+ ```
+
+1. Create a single manifest file to install the Runner chart with your cluster agent:
+
+ ```shell
+ helm template --namespace gitlab gitlab-runner -f runner-chart-values.yaml gitlab/gitlab-runner > manifest.yaml
+ ```
+
+1. Push your `manifest.yaml` to your manifest repository.
+
+## Troubleshooting
+
+If you face any issues while using GitLab Kubernetes Agent, you can read the
+service logs with the following commands:
+
+- KAS pod logs - Tail these logs with the
+ `kubectl logs -f -l=app=kas -n <YOUR-GITLAB-NAMESPACE>`
+ command. In Omnibus GitLab, the logs reside in `/var/log/gitlab/gitlab-kas/`.
+- Agent pod logs - Tail these logs with the
+ `kubectl logs -f -l=app=gitlab-agent -n <YOUR-DESIRED-NAMESPACE>` command.
+
+### KAS logs - GitOps: failed to get project info
+
+```plaintext
+{"level":"warn","time":"2020-10-30T08:37:26.123Z","msg":"GitOps: failed to get project info","agent_id":4,"project_id":"root/kas-manifest001","error":"error kind: 0; status: 404"}
+```
+
+This error is shown if the specified manifest project `root/kas-manifest001`
+doesn't exist, or if a project is private. To fix it, make sure the project exists
+and its visibility is [set to public](../../../public_access/public_access.md).
+
+### KAS logs - Configuration file not found
+
+```plaintext
+time="2020-10-29T04:44:14Z" level=warning msg="Config: failed to fetch" agent_id=2 error="configuration file not found: \".gitlab/agents/test-agent/config.yaml\
+```
+
+This error is shown if the path to the configuration project was specified incorrectly,
+or if the path to `config.yaml` inside the project is not valid.
+
+### Agent logs - Transport: Error while dialing failed to WebSocket dial
+
+```plaintext
+{"level":"warn","time":"2020-11-04T10:14:39.368Z","msg":"GetConfiguration failed","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing failed to WebSocket dial: failed to send handshake request: Get \\\"https://gitlab-kas:443/-/kubernetes-agent\\\": dial tcp: lookup gitlab-kas on 10.60.0.10:53: no such host\""}
+```
+
+This error is shown if there are some connectivity issues between the address
+specified as `kas-address`, and your Agent pod. To fix it, make sure that you
+specified the `kas-address` correctly.
+
+### Agent logs - ValidationError(Deployment.metadata
+
+```plaintext
+{"level":"info","time":"2020-10-30T08:56:54.329Z","msg":"Synced","project_id":"root/kas-manifest001","resource_key":"apps/Deployment/kas-test001/nginx-deployment","sync_result":"error validating data: [ValidationError(Deployment.metadata): unknown field \"replicas\" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta, ValidationError(Deployment.metadata): unknown field \"selector\" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta, ValidationError(Deployment.metadata): unknown field \"template\" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta]"}
+```
+
+This error is shown if your `manifest.yaml` file is malformed, and Kubernetes can't
+create specified objects. Make sure that your `manifest.yaml` file is valid. You
+may try using it to create objects in Kubernetes directly for more troubleshooting.
+
+### Agent logs - Error while dialing failed to WebSocket dial: failed to send handshake request
+
+```plaintext
+{"level":"warn","time":"2020-10-30T09:50:51.173Z","msg":"GetConfiguration failed","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing failed to WebSocket dial: failed to send handshake request: Get \\\"https://GitLabhost.tld:443/-/kubernetes-agent\\\": net/http: HTTP/1.x transport connection broken: malformed HTTP response \\\"\\\\x00\\\\x00\\\\x06\\\\x04\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x05\\\\x00\\\\x00@\\\\x00\\\"\""}
+```
+
+This error is shown if you configured `wss` as `kas-address` on the agent side,
+but KAS on the server side is not available via `wss`. To fix it, make sure the
+same schemes are configured on both sides.
+
+It's not possible to set the `grpc` scheme due to the issue
+[It is not possible to configure KAS to work with `grpc` without directly editing GitLab KAS deployment](https://gitlab.com/gitlab-org/gitlab/-/issues/276888). To use `grpc` while the
+issue is in progress, directly edit the deployment with the
+`kubectl edit deployment gitlab-kas` command, and change `--listen-websocket=true` to `--listen-websocket=false`. After running that command, you should be able to use
+`grpc://gitlab-kas.<YOUR-NAMESPACE>:5005`.
+
+#### Agent logs - Decompressor is not installed for grpc-encoding
+
+```plaintext
+{"level":"warn","time":"2020-11-05T05:25:46.916Z","msg":"GetConfiguration.Recv failed","error":"rpc error: code = Unimplemented desc = grpc: Decompressor is not installed for grpc-encoding \"gzip\""}
+```
+
+This error is shown if the version of the agent is newer that the version of KAS.
+To fix it, make sure that both `agentk` and KAS use the same versions.
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index 4e0e2991acb..67a53fa773f 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -64,21 +64,35 @@ supported by GitLab before installing any of the applications.
> - Introduced in GitLab 10.2 for project-level clusters.
> - Introduced in GitLab 11.6 for group-level clusters.
> - [Uses a local Tiller](https://gitlab.com/gitlab-org/gitlab/-/issues/209736) in GitLab 13.2 and later.
+> - [Uses Helm 3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46267) for clusters created with GitLab 13.6 and later.
[Helm](https://helm.sh/docs/) is a package manager for Kubernetes and is
used to install the GitLab-managed apps. GitLab runs each `helm` command
in a pod within the `gitlab-managed-apps` namespace inside the cluster.
-GitLab's integration uses Helm 2 with a local
-[Tiller](https://v2.helm.sh/docs/glossary/#tiller) server for managing
-applications. Prior to [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/209736),
-GitLab used an in-cluster Tiller server in the `gitlab-managed-apps`
-namespace. This server can now be safely removed.
+- For clusters created on GitLab 13.6 and newer, GitLab uses Helm 3 to manage
+ applications.
+- For clusters created on versions of GitLab prior to 13.6, GitLab uses
+ Helm 2 with a local [Tiller](https://v2.helm.sh/docs/glossary/#tiller) server.
+ Prior to [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/209736),
+ GitLab used an in-cluster Tiller server in the `gitlab-managed-apps`
+ namespace. You can safely remove this server after upgrading to GitLab 13.2
+ or newer.
GitLab's Helm integration does not support installing applications behind a proxy,
but a [workaround](../../topics/autodevops/index.md#install-applications-behind-a-proxy)
is available.
+#### Upgrade a cluster to Helm 3
+
+GitLab does not currently offer a way to migrate existing application management
+on existing clusters from Helm 2 to Helm 3. To migrate a cluster to Helm 3:
+
+1. Uninstall all applications on your cluster.
+1. [Remove the cluster integration](../project/clusters/add_remove_clusters.md#removing-integration).
+1. [Re-add the cluster](../project/clusters/add_remove_clusters.md#existing-kubernetes-cluster) as
+ an existing cluster.
+
### cert-manager
> Introduced in GitLab 11.6 for project- and group-level clusters.
@@ -93,7 +107,7 @@ The chart used to install this application depends on the version of GitLab used
- GitLab 12.3 and newer, the [`jetstack/cert-manager`](https://github.com/jetstack/cert-manager)
chart is used with a [`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/cert_manager/values.yaml)
file.
-- GitLab 12.2 and older, the [`stable/cert-manager`](https://gi2wthub.com/helm/charts/tree/master/stable/cert-manager)
+- GitLab 12.2 and older, the [`stable/cert-manager`](https://github.com/helm/charts/tree/master/stable/cert-manager)
chart was used.
If you installed cert-manager prior to GitLab 12.3, Let's Encrypt
@@ -625,10 +639,13 @@ To install applications using GitLab CI/CD:
- template: Managed-Cluster-Applications.gitlab-ci.yml
```
- The job provided by this template connects to the cluster using tools provided
+ The job provided by this template connects to the `*` (default) cluster using tools provided
in a custom Docker image. It requires that you have a runner registered with the Docker,
Kubernetes, or Docker Machine executor.
+ To install to a specific cluster, read
+ [Use the template with a custom environment](#use-the-template-with-a-custom-environment).
+
1. Add a `.gitlab/managed-apps/config.yaml` file to define which
applications you would like to install. Define the `installed` key as
`true` to install the application and `false` to uninstall the
@@ -647,6 +664,47 @@ applications you have configured. In case of pipeline failure, the
output of the [Helm Tiller](https://v2.helm.sh/docs/install/#running-tiller-locally) binary
is saved as a [CI job artifact](../../ci/pipelines/job_artifacts.md).
+For GitLab versions 13.5 and below, the Ingress, Fluentd, Prometheus,
+and Sentry apps are fetched from the central Helm [stable
+repository](https://kubernetes-charts.storage.googleapis.com/), which
+will be [deleted](https://github.com/helm/charts#deprecation-timeline)
+on November 13, 2020. This will cause the installation CI/CD pipeline to
+fail. Upgrade to GitLab 13.6, or alternatively, you can
+use the following `.gitlab-ci.yml`, which has been tested on GitLab
+13.5:
+
+```yaml
+include:
+ - template: Managed-Cluster-Applications.gitlab-ci.yml
+
+apply:
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.34.1"
+```
+
+### Use the template with a custom environment
+
+If you only want apps to be installed on a specific cluster, or if your cluster's
+scope does not match `production`, you can override the environment name in your `.gitlab-ci.yml`
+file:
+
+```yaml
+include:
+ - template: Managed-Cluster-Applications.gitlab-ci.yml
+
+apply:
+ except:
+ variables:
+ - '$CI_JOB_NAME == "apply"'
+
+.managed-apps:
+ extends: apply
+
+example-install:
+ extends: .managed-apps
+ environment:
+ name: example/production
+```
+
### Important notes
Note the following:
@@ -717,7 +775,7 @@ certManager:
You can customize the installation of cert-manager by defining a
`.gitlab/managed-apps/cert-manager/values.yaml` file in your cluster
management project. Refer to the
-[chart](https://hub.helm.sh/charts/jetstack/cert-manager) for the
+[chart](https://github.com/jetstack/cert-manager) for the
available configuration options.
Support for installing the Cert Manager managed application is provided by the
@@ -797,7 +855,7 @@ least 2 people from the
### Install PostHog using GitLab CI/CD
-[PostHog](https://www.posthog.com) 🦔 is a developer-friendly, open-source product analytics platform.
+[PostHog](https://posthog.com) 🦔 is a developer-friendly, open-source product analytics platform.
To install PostHog into the `gitlab-managed-apps` namespace of your cluster,
define the `.gitlab/managed-apps/config.yaml` file with:
@@ -954,15 +1012,15 @@ CAUTION: **Caution:**
Installation and removal of the Cilium requires a **manual**
[restart](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-gke/#restart-unmanaged-pods)
of all affected pods in all namespaces to ensure that they are
-[managed](https://docs.cilium.io/en/stable/troubleshooting/#ensure-pod-is-managed-by-cilium)
+[managed](https://docs.cilium.io/en/v1.8/operations/troubleshooting/#ensure-managed-pod)
by the correct networking plugin.
NOTE: **Note:**
Major upgrades might require additional setup steps. For more information, see
-the official [upgrade guide](https://docs.cilium.io/en/stable/install/upgrade/).
+the official [upgrade guide](https://docs.cilium.io/en/v1.8/operations/upgrade/).
By default, Cilium's
-[audit mode](https://docs.cilium.io/en/v1.8/gettingstarted/policy-creation/?highlight=policy-audit#enable-policy-audit-mode)
+[audit mode](https://docs.cilium.io/en/v1.8/gettingstarted/policy-creation/#enable-policy-audit-mode)
is enabled. In audit mode, Cilium doesn't drop disallowed packets. You
can use `policy-verdict` log to observe policy-related decisions. You
can disable audit mode by adding the following to
diff --git a/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_3_1.png b/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_3_1.png
deleted file mode 100644
index 89f4e917567..00000000000
--- a/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_3_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_6.png b/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_6.png
new file mode 100644
index 00000000000..b2ac4f95e0d
--- /dev/null
+++ b/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_6.png
Binary files differ
diff --git a/doc/user/compliance/compliance_dashboard/index.md b/doc/user/compliance/compliance_dashboard/index.md
index 5c05725d95b..151c61b50d8 100644
--- a/doc/user/compliance/compliance_dashboard/index.md
+++ b/doc/user/compliance/compliance_dashboard/index.md
@@ -17,7 +17,7 @@ for merging into production.
To access the Compliance Dashboard for a group, navigate to **{shield}** **Security & Compliance > Compliance** on the group's menu.
-![Compliance Dashboard](img/compliance_dashboard_v13_3_1.png)
+![Compliance Dashboard](img/compliance_dashboard_v13_6.png)
NOTE: **Note:**
The Compliance Dashboard shows only the latest MR on each project.
@@ -63,14 +63,24 @@ This column has four states:
If you do not see the success icon in your Compliance dashboard; please review the above criteria for the Merge Requests
project to make sure it complies with the separation of duties described above.
-## Chain of Custody report
+## Chain of Custody report **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213364) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3.
The Chain of Custody report allows customers to export a list of merge commits within the group.
The data provides a comprehensive view with respect to merge commits. It includes the merge commit SHA,
merge request author, merge request ID, merge user, pipeline ID, group name, project name, and merge request approvers.
+Depending on the merge strategy, the merge commit SHA can either be a merge commit, squash commit or a diff head commit.
To download the Chain of Custody report, navigate to **{shield}** **Security & Compliance > Compliance** on the group's menu and click **List of all merge commits**
+### Commit-specific Chain of Custody Report **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267629) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.6.
+
+You can generate a commit-specific Chain of Custody report for a given commit SHA. To do so, select
+the dropdown next to the **List of all merge commits** button at the top of the Compliance Dashboard.
+
NOTE: **Note:**
The Chain of Custody report download is a CSV file, with a maximum size of 15 MB.
The remaining records are truncated when this limit is reached.
diff --git a/doc/user/compliance/license_compliance/img/license_compliance_add_license_v13_0.png b/doc/user/compliance/license_compliance/img/license_compliance_add_license_v13_0.png
deleted file mode 100644
index 1366c569f17..00000000000
--- a/doc/user/compliance/license_compliance/img/license_compliance_add_license_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/compliance/license_compliance/img/license_compliance_decision_v13_0.png b/doc/user/compliance/license_compliance/img/license_compliance_decision_v13_0.png
deleted file mode 100644
index 42bf8bd1ed5..00000000000
--- a/doc/user/compliance/license_compliance/img/license_compliance_decision_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/compliance/license_compliance/img/license_compliance_pipeline_tab_v13_0.png b/doc/user/compliance/license_compliance/img/license_compliance_pipeline_tab_v13_0.png
deleted file mode 100644
index 49c66832f00..00000000000
--- a/doc/user/compliance/license_compliance/img/license_compliance_pipeline_tab_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/compliance/license_compliance/img/license_compliance_search_v13_0.png b/doc/user/compliance/license_compliance/img/license_compliance_search_v13_0.png
deleted file mode 100644
index 5a4216dd645..00000000000
--- a/doc/user/compliance/license_compliance/img/license_compliance_search_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/compliance/license_compliance/img/license_compliance_settings_v13_0.png b/doc/user/compliance/license_compliance/img/license_compliance_settings_v13_0.png
deleted file mode 100644
index 91f1eec2a23..00000000000
--- a/doc/user/compliance/license_compliance/img/license_compliance_settings_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md
index 894c0e14862..65c009f947f 100644
--- a/doc/user/compliance/license_compliance/index.md
+++ b/doc/user/compliance/license_compliance/index.md
@@ -37,10 +37,7 @@ compliance report will be shown properly.
![License Compliance Widget](img/license_compliance_v13_0.png)
-If you are a project or group Maintainer, you can click on a license to be given
-the choice to allow it or deny it.
-
-![License approval decision](img/license_compliance_decision_v13_0.png)
+You can click on a license to see more information.
When GitLab detects a **Denied** license, you can view it in the [license list](#license-list).
@@ -62,7 +59,6 @@ The following languages and package managers are supported.
| .NET | [Nuget](https://www.nuget.org/) | The .NET Framework is supported via the [mono project](https://www.mono-project.com/). There are, however, some limitations. The scanner doesn't support Windows-specific dependencies and doesn't report dependencies of your project's listed dependencies. Also, the scanner always marks detected licenses for all dependencies as `unknown`. | [License Finder](https://github.com/pivotal/LicenseFinder) |
| Python | [pip](https://pip.pypa.io/en/stable/) | Python is supported through [requirements.txt](https://pip.pypa.io/en/stable/user_guide/#requirements-files) and [Pipfile.lock](https://github.com/pypa/pipfile#pipfilelock). | [License Finder](https://github.com/pivotal/LicenseFinder) |
| Ruby | [gem](https://rubygems.org/) | | [License Finder](https://github.com/pivotal/LicenseFinder)|
-| Objective-C, Swift | [Carthage](https://github.com/Carthage/Carthage) | | [License Finder](https://github.com/pivotal/LicenseFinder) |
NOTE: **Note:**
Java 8 and Gradle 1.x projects are not supported.
@@ -78,6 +74,7 @@ which means that the reported licenses might be incomplete or inaccurate.
| JavaScript | [Yarn](https://yarnpkg.com/)|[License Finder](https://github.com/pivotal/LicenseFinder)|
| Go | go get, gvt, glide, dep, trash, govendor |[License Finder](https://github.com/pivotal/LicenseFinder)|
| Erlang | [Rebar](https://www.rebar3.org/) |[License Finder](https://github.com/pivotal/LicenseFinder)|
+| Objective-C, Swift | [Carthage](https://github.com/Carthage/Carthage) | | [License Finder](https://github.com/pivotal/LicenseFinder) |
| Objective-C, Swift | [CocoaPods](https://cocoapods.org/) v0.39 and below |[License Finder](https://github.com/pivotal/LicenseFinder)|
| Elixir | [Mix](https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html) |[License Finder](https://github.com/pivotal/LicenseFinder)|
| C++/C | [Conan](https://conan.io/) |[License Finder](https://github.com/pivotal/LicenseFinder)|
@@ -144,7 +141,7 @@ License Compliance can be configured using environment variables.
| `ASDF_PYTHON_VERSION` | no | Version of Python to use for the scan. |
| `ASDF_RUBY_VERSION` | no | Version of Ruby to use for the scan. |
| `GRADLE_CLI_OPTS` | no | Additional arguments for the gradle executable. If not supplied, defaults to `--exclude-task=test`. |
-| `LICENSE_FINDER_CLI_OPTS` | no | Additional arguments for the `license_finder` executable. For example, if your project has both Golang and Ruby code stored in different directories and you want to only scan the Ruby code, you can update your `.gitlab-ci-yml` template to specify which project directories to scan, like `LICENSE_FINDER_CLI_OPTS: '--debug --aggregate-paths=. ruby'`. |
+| `LICENSE_FINDER_CLI_OPTS` | no | Additional arguments for the `license_finder` executable. For example, if you have multiple projects in nested directories, you can update your `.gitlab-ci-yml` template to specify a recursive scan, like `LICENSE_FINDER_CLI_OPTS: '--recursive'`. |
| `LM_JAVA_VERSION` | no | Version of Java. If set to `11`, Maven and Gradle use Java 11 instead of Java 8. |
| `LM_PYTHON_VERSION` | no | Version of Python. If set to `3`, dependencies are installed using Python 3 instead of Python 2.7. |
| `MAVEN_CLI_OPTS` | no | Additional arguments for the mvn executable. If not supplied, defaults to `-DskipTests`. |
@@ -444,7 +441,7 @@ documentation for a list of settings that you can apply.
The `license_scanning` job runs in a [Debian 10](https://www.debian.org/releases/buster/) Docker
image. The supplied image ships with some build tools such as [CMake](https://cmake.org/) and [GCC](https://gcc.gnu.org/).
However, not all project types are supported by default. To install additional tools needed to
-compile dependencies, use a [`before_script`](../../../ci/yaml/README.md#before_script-and-after_script)
+compile dependencies, use a [`before_script`](../../../ci/yaml/README.md#before_script)
to install the necessary build tools using the [`apt`](https://wiki.debian.org/PackageManagementTools)
package manager. For a comprehensive list, consult [the Conan documentation](https://docs.conan.io/en/latest/introduction.html#all-platforms-all-build-systems-and-compilers).
@@ -775,11 +772,11 @@ or using the appropriate [`ASDF_<tool>_VERSION`](https://asdf-vm.com/#/core-conf
activate the appropriate version.
For example, the following `.tool-versions` file will activate version `12.16.3` of [Node.js](https://nodejs.org/)
-and version `2.6.6` of [Ruby](https://www.ruby-lang.org/).
+and version `2.7.2` of [Ruby](https://www.ruby-lang.org/).
```plaintext
nodejs 12.16.3
-ruby 2.6.6
+ruby 2.7.2
```
The next example shows how to activate the same versions of the tools mentioned above by using environment variables defined in your
@@ -792,7 +789,7 @@ include:
license_scanning:
variables:
ASDF_NODEJS_VERSION: '12.16.3'
- ASDF_RUBY_VERSION: '2.6.6'
+ ASDF_RUBY_VERSION: '2.7.2'
```
A full list of variables can be found in [environment variables](#available-variables).
diff --git a/doc/user/discussions/img/discussions_resolved.png b/doc/user/discussions/img/discussions_resolved.png
deleted file mode 100644
index 3fd496f6da5..00000000000
--- a/doc/user/discussions/img/discussions_resolved.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_unresolve2.png b/doc/user/discussions/img/mr_review_unresolve2.png
deleted file mode 100644
index 79da61bb556..00000000000
--- a/doc/user/discussions/img/mr_review_unresolve2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/new_issue_for_discussion.png b/doc/user/discussions/img/new_issue_for_discussion.png
deleted file mode 100644
index 819d872a9a2..00000000000
--- a/doc/user/discussions/img/new_issue_for_discussion.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved.png b/doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved.png
deleted file mode 100644
index 928c7d33898..00000000000
--- a/doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved_msg.png b/doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved_msg.png
deleted file mode 100644
index 9044926b0eb..00000000000
--- a/doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved_msg.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/preview_issue_for_discussion.png b/doc/user/discussions/img/preview_issue_for_discussion.png
deleted file mode 100644
index 30c273ca4c5..00000000000
--- a/doc/user/discussions/img/preview_issue_for_discussion.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/preview_issue_for_discussions.png b/doc/user/discussions/img/preview_issue_for_discussions.png
deleted file mode 100644
index 3d906e1b0b0..00000000000
--- a/doc/user/discussions/img/preview_issue_for_discussions.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/resolve_discussion_button.png b/doc/user/discussions/img/resolve_discussion_button.png
deleted file mode 100644
index ab454f661e0..00000000000
--- a/doc/user/discussions/img/resolve_discussion_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/resolve_discussion_issue_notice.png b/doc/user/discussions/img/resolve_discussion_issue_notice.png
deleted file mode 100644
index ed50dc1de91..00000000000
--- a/doc/user/discussions/img/resolve_discussion_issue_notice.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/resolve_discussion_open_issue.png b/doc/user/discussions/img/resolve_discussion_open_issue.png
deleted file mode 100644
index 9d0a14671d6..00000000000
--- a/doc/user/discussions/img/resolve_discussion_open_issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/feature_highlight.md b/doc/user/feature_highlight.md
index 9b52c178493..31eb0e6375d 100644
--- a/doc/user/feature_highlight.md
+++ b/doc/user/feature_highlight.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Feature highlight
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/16379) in GitLab 10.5
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index ec0c207e190..54f14c71c93 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab.com settings
In this page you will find information about the settings that are used on
@@ -85,6 +91,7 @@ which is part of [GitLab CI/CD](#gitlab-cicd).
## GitLab CI/CD
Below are the current settings regarding [GitLab CI/CD](../../ci/README.md).
+Any settings or feature limits not listed here are using the defaults listed in the related documentation.
| Setting | GitLab.com | Default |
| ----------- | ----------------- | ------------- |
@@ -94,7 +101,6 @@ Below are the current settings regarding [GitLab CI/CD](../../ci/README.md).
| [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) | 3 months | Never |
| Max test cases per [unit test report](../../ci/unit_test_reports.md) | `500_000` | Unlimited |
@@ -107,7 +113,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 |
+| [Repository size including LFS](../admin_area/settings/account_and_limit_settings.md) | 10 GB | Unlimited |
| Maximum import size | 5 GB | 50 MB |
NOTE: **Note:**
@@ -146,7 +152,7 @@ Shared runners provided by GitLab are **not** configurable. Consider [installing
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
+to 400 CI minutes per month per group for private projects. More minutes
[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/).
@@ -264,26 +270,23 @@ sentry_dsn = "X"
### Windows shared runners (beta)
-The Windows shared runners are currently in
-[beta](https://about.gitlab.com/handbook/product/#beta) and should not be used
-for production workloads.
+The Windows shared runners are in [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
+and shouldn't be used for production workloads.
-During the beta period, the
-[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).
+During this beta period, the [shared runner pipeline quota](../admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota)
+applies for groups and projects in the same manner as Linux runners. This may
+change when the beta period ends, as discussed in this [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/30834).
-Windows shared runners on GitLab.com 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)
+Windows shared runners on GitLab.com autoscale by launching virtual machines on
+the Google Cloud Platform. This solution uses an
+[autoscaling driver](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md)
developed by GitLab for the [custom executor](https://docs.gitlab.com/runner/executors/custom.html).
-Windows shared runners execute your CI/CD jobs on `n1-standard-2` instances with 2
-vCPUs and 7.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).
+Windows shared runners execute your CI/CD jobs on `n1-standard-2` instances with
+2 vCPUs and 7.5 GB RAM. You can find a full list of available Windows packages in
+the [package documentation](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/master/cookbooks/preinstalled-software/README.md).
We want to keep iterating to get Windows shared runners in a stable state and
-[generally available](https://about.gitlab.com/handbook/product/#generally-available-ga).
+[generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga).
You can follow our work towards this goal in the
[related epic](https://gitlab.com/groups/gitlab-org/-/epics/2162).
@@ -292,7 +295,7 @@ You can follow our work towards this goal in the
The full contents of our `config.toml` are:
NOTE: **Note:**
-Settings that are not public are shown as `X`.
+Settings that aren't public are shown as `X`.
```toml
concurrent = X
@@ -406,7 +409,7 @@ test:
- For the beta release, we have included a set of software packages in
the base VM image. If your CI job requires additional software that's
not included in this list, then you will need to add installation
- commands to [`before_script`](../../ci/yaml/README.md#before_script-and-after_script) or [`script`](../../ci/yaml/README.md#script) to install the required
+ commands to [`before_script`](../../ci/yaml/README.md#before_script) or [`script`](../../ci/yaml/README.md#script) to install the required
software. Note that each job runs on a new VM instance, so the
installation of additional software packages needs to be repeated for
each job in your pipeline.
@@ -429,7 +432,7 @@ and the following environment variables:
| `SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL` | - | `3` |
| `SIDEKIQ_MEMORY_KILLER_GRACE_TIME` | - | `900` |
| `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT` | - | `30` |
-| `SIDEKIQ_LOG_ARGUMENTS` | `1` | - |
+| `SIDEKIQ_LOG_ARGUMENTS` | `1` | `1` |
NOTE: **Note:**
The `SIDEKIQ_MEMORY_KILLER_MAX_RSS` setting is `16000000` on Sidekiq import
@@ -627,6 +630,13 @@ You can view more information in our runbooks such as:
- Our [current log retention policies](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging#retention)
- A [diagram of our logging infrastructure](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging#logging-infrastructure-overview)
+### Job Logs
+
+By default, GitLab does not expire job logs. Job logs are retained indefinitely,
+and can't be configured on GitLab.com to expire. You can erase job logs
+[manually with the Jobs API](../../api/jobs.md#erase-a-job) or by
+[deleting a pipeline](../../ci/pipelines/index.md#delete-a-pipeline).
+
## GitLab.com at scale
In addition to the GitLab Enterprise Edition Omnibus install, GitLab.com uses
diff --git a/doc/user/group/contribution_analytics/index.md b/doc/user/group/contribution_analytics/index.md
index a689b7c380b..cf55a1f688b 100644
--- a/doc/user/group/contribution_analytics/index.md
+++ b/doc/user/group/contribution_analytics/index.md
@@ -1,7 +1,7 @@
---
type: reference
stage: Manage
-group: Analytics
+group: Value Stream 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
---
# Contribution Analytics **(STARTER)**
diff --git a/doc/user/group/dependency_proxy/img/group_dependency_proxy.png b/doc/user/group/dependency_proxy/img/group_dependency_proxy.png
deleted file mode 100644
index 035aff0b6c4..00000000000
--- a/doc/user/group/dependency_proxy/img/group_dependency_proxy.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/epics/img/containing_epic.png b/doc/user/group/epics/img/containing_epic.png
index dc13d55e2bc..1ba5a30708f 100644
--- a/doc/user/group/epics/img/containing_epic.png
+++ b/doc/user/group/epics/img/containing_epic.png
Binary files differ
diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md
index f380b36cc00..e98c4b416fe 100644
--- a/doc/user/group/epics/index.md
+++ b/doc/user/group/epics/index.md
@@ -1,7 +1,7 @@
---
type: reference, howto
stage: Plan
-group: Portfolio Management
+group: Product Planning
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
diff --git a/doc/user/group/epics/manage_epics.md b/doc/user/group/epics/manage_epics.md
index c09032bffb2..5895b611bb3 100644
--- a/doc/user/group/epics/manage_epics.md
+++ b/doc/user/group/epics/manage_epics.md
@@ -1,7 +1,7 @@
---
type: howto
stage: Plan
-group: Portfolio Management
+group: Product Planning
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
@@ -23,9 +23,9 @@ selected group. From your group page:
To create an epic from the epic list, in a group:
1. Go to **{epic}** **Epics**.
-1. Click **New epic**.
+1. Select **New epic**.
1. Enter a descriptive title.
-1. Click **Create epic**.
+1. Select **Create epic**.
### Access the New Epic form
@@ -33,8 +33,8 @@ To create an epic from the epic list, in a group:
There are two ways to get to the New Epic form and create an epic in the group you're in:
-- From an epic in your group, click **New Epic**.
-- From anywhere, in the top menu, click **plus** (**{plus-square}**) **> New epic**.
+- From an epic in your group, select **New Epic**.
+- From anywhere, in the top menu, select **plus** (**{plus-square}**) **> New epic**.
![New epic from an open epic](img/new_epic_from_groups_v13.2.png)
@@ -63,13 +63,13 @@ After you create an epic, you can edit change the following details:
To edit an epic's title or description:
-1. Click the **Edit title and description** **{pencil}** button.
+1. Select the **Edit title and description** **{pencil}** button.
1. Make your changes.
-1. Click **Save changes**.
+1. Select **Save changes**.
To edit an epics' start date, due date, or labels:
-1. Click **Edit** next to each section in the epic sidebar.
+1. Select **Edit** next to each section in the epic sidebar.
1. Select the dates or labels for your epic.
## Bulk-edit epics
@@ -82,7 +82,7 @@ You can edit multiple epics at once. To learn how to do it, visit
NOTE: **Note:**
To delete an epic, you need to be an [Owner](../../permissions.md#group-members-permissions) of a group/subgroup.
-When editing the description of an epic, click the **Delete** button to delete the epic.
+When editing the description of an epic, select the **Delete** button to delete the epic.
A modal appears to confirm your action.
Deleting an epic releases all existing issues from their associated epic in the system.
@@ -92,7 +92,7 @@ Deleting an epic releases all existing issues from their associated epic in the
Whenever you decide that there is no longer need for that epic,
close the epic by:
-- Clicking the **Close epic** button.
+- Selecting the **Close epic** button.
![close epic - button](img/button_close_epic.png)
@@ -129,7 +129,7 @@ that of Issues and Merge Requests) based on following parameters:
![epics search](img/epics_search.png)
-To search, go to the list of epics and click the field **Search or filter results**.
+To search, go to the list of epics and select the field **Search or filter results**.
It will display a dropdown menu, from which you can add an author. You can also enter plain
text to search by epic title or description. When done, press <kbd>Enter</kbd> on your
keyboard to filter the list.
@@ -168,7 +168,7 @@ To make an epic confidential:
### Add a new issue to an epic
-You can add an existing issue to an epic, or, create a new issue that's
+You can add an existing issue to an epic, or create a new issue that's
automatically added to the epic.
#### Add an existing issue to an epic
@@ -183,15 +183,15 @@ current parent.
To add a new issue to an epic:
-1. Click the **Add** dropdown button.
-1. Click **Add a new issue**.
+1. On the epic's page, under **Epics and Issues**, select the **Add** dropdown button.
+1. Select **Add an existing 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
match (introduced in [GitLab 12.5](https://gitlab.com/gitlab-org/gitlab/-/issues/9126)).
If there are multiple issues to be added, press <kbd>Spacebar</kbd> and repeat this step.
-1. Click **Add**.
+1. Select **Add**.
#### Create an issue from an epic
@@ -202,11 +202,11 @@ while dividing work into smaller parts.
To create an issue from an epic:
-1. On the epic's page, under **Epics and Issues**, click the **Add** dropdown button and select
- **Create new issue**.
+1. On the epic's page, under **Epics and Issues**, select the **Add** dropdown button.
+1. Select **Add a new issue**.
1. Under **Title**, enter the title for the new issue.
1. From the **Project** dropdown, select the project in which the issue should be created.
-1. Click **Create issue**.
+1. Select **Create issue**.
### Remove an issue from an epic
@@ -215,9 +215,9 @@ After you remove an issue from an epic, the issue will no longer be associated w
To remove an issue from an epic:
-1. Click the **Remove** (**{close}**) button next to the issue you want to remove.
+1. Select the **Remove** (**{close}**) button next to the issue you want to remove.
The **Remove issue** warning appears.
-1. Click **Remove**.
+1. Select **Remove**.
![List of issues assigned to an epic](img/issue_list_v13_1.png)
@@ -285,15 +285,15 @@ 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 a new epic**.
+1. Select the **Add** dropdown button.
+1. Select **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
match (introduced in [GitLab 12.5](https://gitlab.com/gitlab-org/gitlab/-/issues/9126)).
If there are multiple epics to be added, press <kbd>Spacebar</kbd> and repeat this step.
-1. Click **Add**.
+1. Select **Add**.
### Move child epics between epics
@@ -325,5 +325,5 @@ To reorder child epics assigned to an epic:
To remove a child epic from a parent epic:
-1. Click on the <kbd>x</kbd> button in the parent epic's list of epics.
-1. Click **Remove** in the **Remove epic** warning message.
+1. Select the <kbd>x</kbd> button in the parent epic's list of epics.
+1. Select **Remove** in the **Remove epic** warning message.
diff --git a/doc/user/group/img/add_new_members.png b/doc/user/group/img/add_new_members.png
deleted file mode 100644
index 8bd9e2374bc..00000000000
--- a/doc/user/group/img/add_new_members.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/img/add_new_members_v13_6.png b/doc/user/group/img/add_new_members_v13_6.png
new file mode 100644
index 00000000000..4255eeb72c7
--- /dev/null
+++ b/doc/user/group/img/add_new_members_v13_6.png
Binary files differ
diff --git a/doc/user/group/img/create_new_project_from_group.png b/doc/user/group/img/create_new_project_from_group.png
deleted file mode 100644
index df98091334c..00000000000
--- a/doc/user/group/img/create_new_project_from_group.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/img/create_new_project_from_group_v13_6.png b/doc/user/group/img/create_new_project_from_group_v13_6.png
new file mode 100644
index 00000000000..72d19817686
--- /dev/null
+++ b/doc/user/group/img/create_new_project_from_group_v13_6.png
Binary files differ
diff --git a/doc/user/group/img/manual_permissions_v13_1.png b/doc/user/group/img/manual_permissions_v13_1.png
deleted file mode 100644
index 0ada9a4839c..00000000000
--- a/doc/user/group/img/manual_permissions_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/img/manual_permissions_v13_6.png b/doc/user/group/img/manual_permissions_v13_6.png
new file mode 100644
index 00000000000..6d26061b049
--- /dev/null
+++ b/doc/user/group/img/manual_permissions_v13_6.png
Binary files differ
diff --git a/doc/user/group/img/restrict-by-email.gif b/doc/user/group/img/restrict-by-email.gif
new file mode 100644
index 00000000000..d1ebeb07a0a
--- /dev/null
+++ b/doc/user/group/img/restrict-by-email.gif
Binary files differ
diff --git a/doc/user/group/img/restrict-by-ip.gif b/doc/user/group/img/restrict-by-ip.gif
new file mode 100644
index 00000000000..6292a58e748
--- /dev/null
+++ b/doc/user/group/img/restrict-by-ip.gif
Binary files differ
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 2c838724cb3..e09c685147a 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -130,7 +130,7 @@ give a user access to all projects in the group with one action.
Add members to a group by navigating to the group's dashboard and clicking **Members**.
-![add members to group](img/add_new_members.png)
+![add members to group](img/add_new_members_v13_6.png)
Select the [permission level](../permissions.md#permissions), and add the new member. You can also set the expiring date for that user; this is the date on which they will no longer have access to your group.
@@ -235,7 +235,7 @@ There are two different ways to add a new project to a group:
- Select a group, and then click **New project**. You can then continue [creating your project](../../gitlab-basics/create-project.md).
- ![New project](img/create_new_project_from_group.png)
+ ![New project](img/create_new_project_from_group_v13_6.png)
- While you are creating a project, select a group namespace
you've already created from the dropdown menu.
@@ -375,9 +375,9 @@ In GitLab [8.15](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/822) and
1. Go to your group's **Members** page.
1. Select the pencil icon in the row for the user you are editing.
-1. Select the orange `Change permissions` button.
+1. Select the brown `Edit permissions` button in the modal.
-![Setting manual permissions](img/manual_permissions_v13_1.png)
+![Setting manual permissions](img/manual_permissions_v13_6.png)
Now you will be able to edit the user's permissions from the **Members** page.
@@ -394,13 +394,6 @@ milestones.
## Group wikis **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13195) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5.
-> - 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-group-wikis).
-
-CAUTION: **Warning:**
-This feature might not be available to you. Check the **version history** note above for details.
Group wikis work the same way as [project wikis](../project/wiki/index.md), please refer to those docs for details on usage.
@@ -414,27 +407,13 @@ There are a few limitations compared to project wikis:
- Local Git access is not supported yet.
- Group wikis are not included in global search, group exports, backups, and Geo replication.
- Changes to group wikis don't show up in the group's activity feed.
+- Group wikis [can't be moved](../../api/project_repository_storage_moves.md#limitations) using the project
+ repository moves API.
-You can follow [this epic](https://gitlab.com/groups/gitlab-org/-/epics/2782) for updates.
-
-### Enable or disable group wikis **(CORE ONLY)**
-
-Group wikis are under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can opt to disable it for your instance.
-
-To enable it:
+For updates, you can follow:
-```ruby
-Feature.enable(:group_wikis)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:group_wikis)
-```
+- [The epic tracking feature parity with project wikis](https://gitlab.com/groups/gitlab-org/-/epics/2782).
+- [The issue for adding the ability to move group wikis using the API](https://gitlab.com/gitlab-org/gitlab/-/issues/219003).
## Group Security Dashboard **(ULTIMATE)**
@@ -513,6 +492,23 @@ If you want to retain ownership over the original namespace and
protect the URL redirects, then instead of changing a group's path or renaming a
username, you can create a new group and transfer projects to it.
+### Group repository settings
+
+You can change settings that are specific to repositories in your group.
+
+#### Custom initial branch name **(CORE ONLY)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43290) in GitLab 13.6.
+
+By default, when you create a new project in GitLab, the initial branch is called `master`.
+For groups, a group administrator can customize the initial branch name to something
+else. This way, every new project created under that group from then on will start from the custom branch name rather than `master`. To do so:
+
+1. Go to the **Group page > Settings > Repository** and expand **Default initial
+ branch name**.
+1. Change the default initial branch to a custom name of your choice.
+1. **Save Changes**.
+
### Remove a group
To remove a group and its contents:
@@ -525,7 +521,10 @@ 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).
+- Since [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [Premium or Silver](https://about.gitlab.com/pricing/premium/) or higher tiers, this action adds a background job to mark a group for deletion. By default, the job schedules the deletion 7 days in the future. You can modify this waiting period through the [instance settings](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
+
+Since [GitLab 13.6](https://gitlab.com/gitlab-org/gitlab/-/issues/39504), if the user who sets up the deletion leaves or is otherwise removed from the group before the
+actual deletion happens, the job is cancelled, and the group is no longer scheduled for deletion.
### Restore a group **(PREMIUM)**
@@ -608,6 +607,8 @@ To enable this feature:
1. Expand the **Permissions, LFS, 2FA** section, and enter IP address ranges into **Allow access to the following IP addresses** field.
1. Click **Save changes**.
+![Domain restriction by IP address](img/restrict-by-ip.gif)
+
#### Allowed domain restriction **(PREMIUM)**
>- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7297) in [GitLab Premium and Silver](https://about.gitlab.com/pricing/) 12.2.
@@ -636,6 +637,8 @@ To enable this feature:
1. Expand the **Permissions, LFS, 2FA** section, and enter the domain names into **Restrict membership by email** field.
1. Click **Save changes**.
+![Domain restriction by email](img/restrict-by-email.gif)
+
This will enable the domain-checking for all new users added to the group from this moment on.
#### Group file templates **(PREMIUM)**
@@ -742,6 +745,7 @@ To enable prevent project forking:
- **Audit Events**: View [Audit Events](../../administration/audit_events.md)
for the group. **(STARTER ONLY)**
- **Pipelines quota**: Keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group.
+- **Integrations**: Configure [integrations](../admin_area/settings/project_integration_management.md) for your group.
#### Storage usage quota **(STARTER)**
@@ -794,7 +798,7 @@ With [GitLab Issue Analytics](issues_analytics/index.md), you can see a bar char
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)**
+## Dependency Proxy
Use GitLab as a [dependency proxy](../packages/dependency_proxy/index.md) for upstream Docker images.
diff --git a/doc/user/group/insights/index.md b/doc/user/group/insights/index.md
index dd1f8914392..50dfb0e5ccd 100644
--- a/doc/user/group/insights/index.md
+++ b/doc/user/group/insights/index.md
@@ -1,7 +1,7 @@
---
type: reference, howto
stage: Manage
-group: Analytics
+group: Value Stream 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/group/issues_analytics/index.md b/doc/user/group/issues_analytics/index.md
index 69512f90fca..dea1eaba819 100644
--- a/doc/user/group/issues_analytics/index.md
+++ b/doc/user/group/issues_analytics/index.md
@@ -1,7 +1,7 @@
---
type: reference
stage: Manage
-group: Analytics
+group: Value Stream 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/group/iterations/index.md b/doc/user/group/iterations/index.md
index 2eb50f07de3..90050e217ee 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)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-iterations). **(STARTER 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)
@@ -50,7 +50,7 @@ To create an iteration:
## Edit an iteration
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218277) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218277) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.2.
NOTE: **Note:**
You need Developer [permissions](../../permissions.md) or higher to edit an iteration.
@@ -73,7 +73,23 @@ An iteration report displays a list of all the issues assigned to an iteration a
To view an iteration report, go to the iterations list page and click an iteration's title.
-## Disable Iterations **(CORE ONLY)**
+### Iteration burndown and burnup charts
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222750) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.5.
+> - It was deployed behind a feature flag, disabled by default.
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45492) on GitLab 13.6.
+> - 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-iteration-charts). **(STARTER ONLY)**
+
+The iteration report includes [burndown and burnup charts](../../project/milestones/burndown_and_burnup_charts.md),
+similar to how they appear when viewing a [milestone](../../project/milestones/index.md).
+
+Burndown charts help track completion progress of total scope, and burnup charts track the daily
+total count and weight of issues added to and completed in a given timebox.
+
+## Disable iterations **(STARTER ONLY)**
GitLab Iterations feature is deployed with a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
@@ -97,6 +113,30 @@ Feature.disable(:group_iterations)
Feature.disable(:group_iterations, Group.find(<group ID>))
```
+## Disable iteration charts **(STARTER ONLY)**
+
+GitLab iteration charts feature is deployed with a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can disable it for your instance. `:iteration_charts` can be enabled or disabled per-group.
+
+To enable it:
+
+```ruby
+# Instance-wide
+Feature.enable(:iteration_charts)
+# or by group
+Feature.enable(:iteration_charts, Group.find(<group ID>))
+```
+
+To disable it:
+
+```ruby
+# Instance-wide
+Feature.disable(:iteration_charts)
+# or by group
+Feature.disable(:iteration_charts, Group.find(<group ID>))
+```
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/group/repositories_analytics/index.md b/doc/user/group/repositories_analytics/index.md
index c9a10146440..fe5e7979592 100644
--- a/doc/user/group/repositories_analytics/index.md
+++ b/doc/user/group/repositories_analytics/index.md
@@ -12,6 +12,19 @@ info: To determine the technical writer assigned to the Stage/Group associated w
CAUTION: **Warning:**
This feature might not be available to you. Check the **version history** note above for details.
+## Latest project test coverage list
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267624) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
+
+To see the latest code coverage for each project in your group:
+
+1. Go to **Analytics > Repositories** in the group (not from a project).
+1. In the **Latest test coverage results** section, use the **Select projects** dropdown to choose the projects you want to check.
+
+## Download historic test coverage data
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215104) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
+
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
diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md
index c185055f6b2..f9d49c1236e 100644
--- a/doc/user/group/roadmap/index.md
+++ b/doc/user/group/roadmap/index.md
@@ -1,7 +1,7 @@
---
type: reference
stage: Plan
-group: Portfolio Management
+group: Product Planning
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
diff --git a/doc/user/group/saml_sso/group_managed_accounts.md b/doc/user/group/saml_sso/group_managed_accounts.md
index 7497d036d31..50f062bafa9 100644
--- a/doc/user/group/saml_sso/group_managed_accounts.md
+++ b/doc/user/group/saml_sso/group_managed_accounts.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
CAUTION: **Caution:**
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.
+[identity model](https://gitlab.com/groups/gitlab-org/-/epics/4345) that does not require separate accounts.
We recommend that group administrators who haven't yet implemented this feature wait for
the new solution.
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 3cb566c7f77..94d2c9afb24 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -88,8 +88,6 @@ We intend to add a similar SSO requirement for [Git and API activity](https://gi
When SSO enforcement is enabled for a group, users cannot share a project in the group outside the top-level group, even if the project is forked.
-To disallow users to contribute outside of the top-level group, please see [Group Managed Accounts](group_managed_accounts.md).
-
## Providers
NOTE: **Note:**
@@ -107,7 +105,7 @@ When [configuring your identify provider](#configuring-your-identity-provider),
### Azure setup notes
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For a demo of the Azure SAML setup including SCIM, see [SCIM Provisioning on Azure Using SAML SSO for Groups Demo](https://youtu.be/24-ZxmTeEBU).
+For a demo of the Azure SAML setup including SCIM, see [SCIM Provisioning on Azure Using SAML SSO for Groups Demo](https://youtu.be/24-ZxmTeEBU). Please note that the video is outdated in regards to objectID mapping and the [SCIM documentation should be followed](scim_setup.md#azure-configuration-steps).
| GitLab Setting | Azure Field |
|--------------|----------------|
@@ -136,7 +134,7 @@ For a demo of the Okta SAML setup including SCIM, see [Demo: Okta Group SAML & S
Under Okta's **Single sign-on URL** field, check the option **Use this for Recipient URL and Destination URL**.
-We recommend:
+For NameID, the following settings are recommended; for SCIM, the following settings are required:
- **Application username** (NameID) set to **Custom** `user.getInternalProperty("id")`.
- **Name ID Format** set to **Persistent**.
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index c6444ada165..7c089a289c6 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -121,8 +121,12 @@ Once synchronized, changing the field mapped to `id` and `externalId` may cause
### Okta configuration steps
-The SAML application that was created during [Single sign-on](index.md#okta-setup-notes) setup for [Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/) now needs to be set up for SCIM.
-Before proceeding, be sure to complete the [GitLab configuration](#gitlab-configuration) process.
+Before you start this section, complete the [GitLab configuration](#gitlab-configuration) process.
+Make sure that you've also set up a SAML application for [Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/),
+as described in the [Okta setup notes](index.md#okta-setup-notes)
+
+Make sure that the Okta setup matches our documentation exactly, especially the NameID
+configuration. Otherwise, the Okta SCIM app may not work properly.
1. Sign in to Okta.
1. If you see an **Admin** button in the top right, click the button. This will
@@ -212,39 +216,7 @@ When the user is added back to the SCIM app, GitLab cannot create a new user bec
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?
-
-Review the following:
-
-- Ensure that the SCIM value for `id` matches the SAML value for `NameId`.
-- Ensure that the SCIM value for `externalId` matches the SAML value for `NameId`.
-
-Review the following SCIM parameters for sensible values:
-
-- `userName`
-- `displayName`
-- `emails[type eq "work"].value`
-
-#### Testing Azure connection: invalid credentials
-
-When testing the connection, you may encounter an error: **You appear to have entered invalid credentials. Please confirm you are using the correct information for an administrative account**. If `Tenant URL` and `secret token` are correct, check whether your group path contains characters that may be considered invalid JSON primitives (such as `.`). Removing such characters from the group path typically resolves the error.
-
-#### Azure: (Field) can't be blank sync error
-
-When checking the Audit Logs for the Provisioning, you can sometimes see the
-error `Namespace can't be blank, Name can't be blank, and User can't be blank.`
-
-This is likely caused because not all required fields (such as first name and last name) are present for all users being mapped.
-
-As a workaround, try an alternate mapping:
-
-1. Follow the Azure mapping instructions from above.
-1. Delete the `name.formatted` target attribute entry.
-1. Change the `displayName` source attribute to have `name.formatted` target attribute.
-
-#### How do I diagnose why a user is unable to sign in
+### How do I diagnose why a user is unable to sign in
Ensure that the user has been added to the SCIM app.
@@ -254,9 +226,9 @@ The **Identity** (`extern_uid`) value stored by GitLab is updated by SCIM whenev
This value is also used by SCIM to match users on the `id`, and is updated by SCIM whenever the `id` or `externalId` values change.
-It is important that this SCIM `id` and SCIM `externalId` are configured to the same value as the SAML `NameId`. SAML responses can be traced using [debugging tools](./index.md#saml-debugging-tools), and any errors can be checked against our [SAML troubleshooting docs](./index.md#troubleshooting).
+It is important that this SCIM `id` and SCIM `externalId` are configured to the same value as the SAML `NameId`. SAML responses can be traced using [debugging tools](index.md#saml-debugging-tools), and any errors can be checked against our [SAML troubleshooting docs](index.md#troubleshooting).
-#### How do I verify user's SAML NameId matches the SCIM externalId
+### How do I verify user's SAML NameId matches the SCIM externalId
Group owners can see the list of users and the `externalId` stored for each user in the group SAML SSO Settings page.
@@ -264,7 +236,7 @@ A possible alternative is to use the [SCIM API](../../../api/scim.md#get-a-list-
To see how the `external_uid` compares to the value returned as the SAML NameId, you can have the user use a [SAML Tracer](index.md#saml-debugging-tools).
-#### Update or fix mismatched SCIM externalId and SAML NameId
+### Update or fix mismatched SCIM externalId and SAML NameId
Whether the value was changed or you need to map to a different field, ensure `id`, `externalId`, and `NameId` all map to the same field.
@@ -277,15 +249,47 @@ that provider may create duplicate users.
If the `externalId` for a user is not correct, and also doesn't match the SAML NameID,
you can address the problem in the following ways:
-- You can have users unlink and relink themselves, based on the ["SAML authentication failed: User has already been taken"](./index.md#message-saml-authentication-failed-user-has-already-been-taken) section.
+- You can have users unlink and relink themselves, based on the ["SAML authentication failed: User has already been taken"](index.md#message-saml-authentication-failed-user-has-already-been-taken) section.
- You can unlink all users simultaneously, by removing all users from the SAML app while provisioning is turned on.
- It may be possible to use the [SCIM API](../../../api/scim.md#update-a-single-saml-user) to manually correct the `externalId` stored for users to match the SAML `NameId`.
To look up a user, you'll need to know the desired value that matches the `NameId` as well as the current `externalId`.
It is important not to update these to incorrect values, since this will cause users to be unable to sign in. It is also important not to assign a value to the wrong user, as this would cause users to get signed into the wrong account.
-#### I need to change my SCIM app
+### I need to change my SCIM app
-Individual users can follow the instructions in the ["SAML authentication failed: User has already been taken"](./index.md#i-need-to-change-my-saml-app) section.
+Individual users can follow the instructions in the ["SAML authentication failed: User has already been taken"](index.md#i-need-to-change-my-saml-app) section.
Alternatively, users can be removed from the SCIM app which will delink all removed users. Sync can then be turned on for the new SCIM app to [link existing users](#user-access-and-linking-setup).
+
+### Azure
+
+#### How do I verify my SCIM configuration is correct?
+
+Review the following:
+
+- Ensure that the SCIM value for `id` matches the SAML value for `NameId`.
+- Ensure that the SCIM value for `externalId` matches the SAML value for `NameId`.
+
+Review the following SCIM parameters for sensible values:
+
+- `userName`
+- `displayName`
+- `emails[type eq "work"].value`
+
+#### Testing Azure connection: invalid credentials
+
+When testing the connection, you may encounter an error: **You appear to have entered invalid credentials. Please confirm you are using the correct information for an administrative account**. If `Tenant URL` and `secret token` are correct, check whether your group path contains characters that may be considered invalid JSON primitives (such as `.`). Removing such characters from the group path typically resolves the error.
+
+#### (Field) can't be blank sync error
+
+When checking the Audit Logs for the Provisioning, you can sometimes see the
+error `Namespace can't be blank, Name can't be blank, and User can't be blank.`
+
+This is likely caused because not all required fields (such as first name and last name) are present for all users being mapped.
+
+As a workaround, try an alternate mapping:
+
+1. Follow the Azure mapping instructions from above.
+1. Delete the `name.formatted` target attribute entry.
+1. Change the `displayName` source attribute to have `name.formatted` target attribute.
diff --git a/doc/user/group/settings/img/new_group_navigation_v13_1.png b/doc/user/group/settings/img/new_group_navigation_v13_1.png
index 98d45a694b6..307175727c7 100644
--- a/doc/user/group/settings/img/new_group_navigation_v13_1.png
+++ b/doc/user/group/settings/img/new_group_navigation_v13_1.png
Binary files differ
diff --git a/doc/user/group/subgroups/img/create_subgroup_button.png b/doc/user/group/subgroups/img/create_subgroup_button.png
deleted file mode 100644
index d1355d4b2c3..00000000000
--- a/doc/user/group/subgroups/img/create_subgroup_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/subgroups/img/create_subgroup_button_v13_6.png b/doc/user/group/subgroups/img/create_subgroup_button_v13_6.png
new file mode 100644
index 00000000000..013aee6b0b4
--- /dev/null
+++ b/doc/user/group/subgroups/img/create_subgroup_button_v13_6.png
Binary files differ
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index 6de38354c5e..268014a3cd2 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference, howto, concepts
---
@@ -80,7 +83,10 @@ By default, groups created in:
- GitLab 12.2 or later allow both Owners and Maintainers to create subgroups.
- GitLab 12.1 or earlier only allow Owners to create subgroups.
-This setting can be for any group by an Owner or Administrator.
+The setting can be changed for any group by:
+
+- A group owner. Select the group, and navigate to **Settings > General > Permissions, LFS, 2FA**.
+- An administrator. Navigate to **Admin Area > Overview > Groups**, select the group, and choose **Edit**.
For more information check the
[permissions table](../../permissions.md#group-members-permissions). For a list
@@ -93,10 +99,9 @@ creation is disabled by an administrator in their settings.
To create a subgroup:
-1. In the group's dashboard expand the **New project** split button, select
- **New subgroup** and click the **New subgroup** button.
+1. In the group's dashboard click the **New subgroup** button.
- ![Subgroups page](img/create_subgroup_button.png)
+ ![Subgroups page](img/create_subgroup_button_v13_6.png)
1. Create a new group like you would normally do. Notice that the immediate parent group
namespace is fixed under **Group path**. The visibility level can differ from
diff --git a/doc/user/img/unordered_check_list_render_gfm.png b/doc/user/img/unordered_check_list_render_gfm.png
deleted file mode 100644
index 2ce0fb95645..00000000000
--- a/doc/user/img/unordered_check_list_render_gfm.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/index.md b/doc/user/index.md
index 32a1c235882..8701b5e038b 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference, index
description: 'Read through the GitLab User documentation to learn how to use, configure, and customize GitLab and GitLab.com to your own needs.'
---
@@ -69,6 +72,17 @@ With GitLab Enterprise Edition, you can also:
You can also [integrate](project/integrations/overview.md) GitLab with numerous third-party applications, such as Mattermost, Microsoft Teams, HipChat, Trello, Slack, Bamboo CI, Jira, and a lot more.
+## User types
+
+There are several types of users in GitLab:
+
+- Regular users and GitLab.com users. <!-- Note: further description TBA -->
+- [Groups](group/index.md) of users.
+- GitLab [admin area](admin_area/index.md) user.
+- [GitLab Administrator](../administration/index.md) with full access to
+ self-managed instances' features and settings.
+- [Internal users](../development/internal_users.md).
+
## Projects
In GitLab, you can create [projects](project/index.md) to host
@@ -84,18 +98,6 @@ it all at once, from one single project.
- [Milestones](project/milestones/index.md): Work on multiple issues and merge
requests towards the same target date with Milestones.
-## GitLab CI/CD
-
-Use built-in [GitLab CI/CD](../ci/README.md) to test, build, and deploy your applications
-directly from GitLab. No third-party integrations needed.
-
-- [GitLab Auto Deploy](../topics/autodevops/stages.md#auto-deploy): Deploy your application out-of-the-box with GitLab Auto Deploy.
-- [Review Apps](../ci/review_apps/index.md): Live-preview the changes introduced by a merge request with Review Apps.
-- [GitLab Pages](project/pages/index.md): Publish your static site directly from
- GitLab with GitLab Pages. You can build, test, and deploy any Static Site Generator with Pages.
-- [GitLab Container Registry](packages/container_registry/index.md): Build and deploy Docker
- images with Container Registry.
-
## Account
There is a lot you can customize and configure
@@ -151,6 +153,11 @@ requests you're assigned to.
you have quick access to. You can also gather feedback on them through
[Discussions](#discussions).
+## GitLab CI/CD
+
+Use built-in [GitLab CI/CD](../ci/README.md) to test, build, and deploy your applications
+directly from GitLab. No third-party integrations needed.
+
## Features behind feature flags
Understand what [features behind feature flags](feature_flags.md) mean.
diff --git a/doc/user/infrastructure/img/terraform_list_view_v13_5.png b/doc/user/infrastructure/img/terraform_list_view_v13_5.png
new file mode 100644
index 00000000000..b23dfa6289e
--- /dev/null
+++ b/doc/user/infrastructure/img/terraform_list_view_v13_5.png
Binary files differ
diff --git a/doc/user/infrastructure/img/terraform_plan_widget_v13_0.png b/doc/user/infrastructure/img/terraform_plan_widget_v13_0.png
deleted file mode 100644
index 62bf4b279b2..00000000000
--- a/doc/user/infrastructure/img/terraform_plan_widget_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/infrastructure/index.md b/doc/user/infrastructure/index.md
index cee6e21a5c5..4af18873798 100644
--- a/doc/user/infrastructure/index.md
+++ b/doc/user/infrastructure/index.md
@@ -13,35 +13,7 @@ workflows to tie into GitLab's authentication and authorization. These features
lowering the barrier to entry for teams to adopt Terraform, collaborate effectively within
GitLab, and support Terraform best practices.
-## Quick Start
-
-Use the following `.gitlab-ci.yml` to set up a simple Terraform project integration
-for GitLab versions 13.5 and greater:
-
-```yaml
-include:
- - template: Terraform.latest.gitlab-ci.yml
-
-variables:
- # If not using GitLab's HTTP backend, remove this line and specify TF_HTTP_* variables
- TF_STATE_NAME: default
- TF_CACHE_KEY: default
-```
-
-This template uses `.latest.`, instead of stable, and may include breaking changes.
-This template also includes some opinionated decisions, which you can override:
-
-- Including the latest [GitLab Terraform Image](https://gitlab.com/gitlab-org/terraform-images).
-- Using the [GitLab managed Terraform State](#gitlab-managed-terraform-state) as
- the Terraform state storage backend.
-- Creating [four pipeline stages](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml):
- `init`, `validate`, `build`, and `deploy`. These stages
- [run the Terraform commands](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml)
- `init`, `validate`, `plan`, `plan-json`, and `apply`. The `apply` command only runs on `master`.
-
-## GitLab managed Terraform State
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2673) in GitLab 13.0.
+## GitLab Managed Terraform state
[Terraform remote backends](https://www.terraform.io/docs/backends/index.html)
enable you to store the state file in a remote, shared store. GitLab uses the
@@ -57,507 +29,36 @@ Amazon S3 or Google Cloud Storage. Its features include:
- Locking and unlocking state.
- Remote Terraform plan and apply execution.
-To get started with a GitLab-managed Terraform State, there are two different options:
-
-- [Use a local machine](#get-started-using-local-development).
-- [Use GitLab CI](#get-started-using-gitlab-ci).
-
-## Permissions for using Terraform
-
-In GitLab version 13.1, [Maintainer access](../permissions.md) was required to use a
-GitLab managed Terraform state backend. In GitLab versions 13.2 and greater,
-[Maintainer access](../permissions.md) is required to lock, unlock and write to the state
-(using `terraform apply`), while [Developer access](../permissions.md) is required to read
-the state (using `terraform plan -lock=false`).
-
-## Get started using local development
-
-If you plan to only run `terraform plan` and `terraform apply` commands from your
-local machine, this is a simple way to get started:
-
-1. Create your project on your GitLab instance.
-1. Navigate to **Settings > General** and note your **Project name**
- and **Project ID**.
-1. Define the Terraform backend in your Terraform project to be:
-
- ```hcl
- terraform {
- backend "http" {
- }
- }
- ```
-
-1. Create a [Personal Access Token](../profile/personal_access_tokens.md) with
- the `api` scope.
-
-1. On your local machine, run `terraform init`, passing in the following options,
- replacing `<YOUR-STATE-NAME>`, `<YOUR-PROJECT-ID>`, `<YOUR-USERNAME>` and
- `<YOUR-ACCESS-TOKEN>` with the relevant values. This command initializes your
- Terraform state, and stores that state within your GitLab project. The name of
- your state can contain only uppercase and lowercase letters, decimal digits,
- hyphens, and underscores. This example uses `gitlab.com`:
-
- ```shell
- terraform init \
- -backend-config="address=https://gitlab.com/api/v4/projects/<YOUR-PROJECT-ID>/terraform/state/<YOUR-STATE-NAME>" \
- -backend-config="lock_address=https://gitlab.com/api/v4/projects/<YOUR-PROJECT-ID>/terraform/state/<YOUR-STATE-NAME>/lock" \
- -backend-config="unlock_address=https://gitlab.com/api/v4/projects/<YOUR-PROJECT-ID>/terraform/state/<YOUR-STATE-NAME>/lock" \
- -backend-config="username=<YOUR-USERNAME>" \
- -backend-config="password=<YOUR-ACCESS-TOKEN>" \
- -backend-config="lock_method=POST" \
- -backend-config="unlock_method=DELETE" \
- -backend-config="retry_wait_min=5"
- ```
-
-You can now run `terraform plan` and `terraform apply` as you normally would.
-
-## Get started using GitLab CI
-
-If you don't want to start with local development, you can also use GitLab CI to
-run your `terraform plan` and `terraform apply` commands.
-
-Next, [configure the backend](#configure-the-backend).
-
-## Configure the backend
-
-After executing the `terraform init` command, you must configure the Terraform backend
-and the CI YAML file:
-
-1. In your Terraform project, define the [HTTP backend](https://www.terraform.io/docs/backends/types/http.html)
- by adding the following code block in a `.tf` file (such as `backend.tf`) to
- define the remote backend:
-
- ```hcl
- terraform {
- backend "http" {
- }
- }
- ```
-
-1. In the root directory of your project repository, configure a
- `.gitlab-ci.yaml` file. This example uses a pre-built image which includes a
- `gitlab-terraform` helper. For supported Terraform versions, see the [GitLab
- Terraform Images project](https://gitlab.com/gitlab-org/terraform-images).
-
- ```yaml
- image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest
- ```
-
-1. In the `.gitlab-ci.yaml` file, define some environment variables to ease
- development. In this example, `TF_ROOT` is the directory where the Terraform
- commands must be executed, `TF_ADDRESS` is the URL to the state on the GitLab
- instance where this pipeline runs, and the final path segment in `TF_ADDRESS`
- is the name of the Terraform state. Projects may have multiple states, and
- this name is arbitrary, so in this example we set it to `example-production`
- which corresponds with the directory we're using as our `TF_ROOT`, and we
- ensure that the `.terraform` directory is cached between jobs in the pipeline
- using a cache key based on the state name (`example-production`):
-
- ```yaml
- 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
- ```
-
-1. In a `before_script`, change to your `TF_ROOT`:
-
- ```yaml
- before_script:
- - cd ${TF_ROOT}
-
- stages:
- - prepare
- - validate
- - build
- - deploy
-
- init:
- stage: prepare
- script:
- - gitlab-terraform init
-
- validate:
- stage: validate
- script:
- - gitlab-terraform validate
-
- plan:
- stage: build
- script:
- - gitlab-terraform plan
- - gitlab-terraform plan-json
- artifacts:
- name: plan
- paths:
- - ${TF_ROOT}/plan.cache
- reports:
- terraform: ${TF_ROOT}/plan.json
-
- apply:
- stage: deploy
- environment:
- name: production
- script:
- - gitlab-terraform apply
- dependencies:
- - plan
- when: manual
- only:
- - master
- ```
-
-1. Push your project to GitLab, which triggers a CI job pipeline. This pipeline
- runs the `gitlab-terraform init`, `gitlab-terraform validate`, and
- `gitlab-terraform plan` commands.
-
-The output from the above `terraform` commands should be viewable in the job logs.
-
-CAUTION: **Caution:**
-Like any other job artifact, Terraform plan data is [viewable by anyone with Guest access](../permissions.md) to the repository.
-Neither Terraform nor GitLab encrypts the plan file by default. If your Terraform plan
-includes sensitive data such as passwords, access tokens, or certificates, GitLab strongly
-recommends encrypting plan output or modifying the project visibility settings.
-
-## Example project
-
-See [this reference project](https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-aws) using GitLab and Terraform to deploy a basic AWS EC2 within a custom VPC.
-
-## Copy Terraform state between backends
-
-Terraform supports copying the state when the backend is changed or
-reconfigured. This can be useful if you need to migrate from another backend to
-GitLab managed Terraform state. It's also useful if you need to change the state
-name as in the following example:
-
-```shell
-PROJECT_ID="<gitlab-project-id>"
-TF_USERNAME="<gitlab-username>"
-TF_PASSWORD="<gitlab-personal-access-token>"
-TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/old-state-name"
-
-terraform init \
- -backend-config=address=${TF_ADDRESS} \
- -backend-config=lock_address=${TF_ADDRESS}/lock \
- -backend-config=unlock_address=${TF_ADDRESS}/lock \
- -backend-config=username=${TF_USERNAME} \
- -backend-config=password=${TF_PASSWORD} \
- -backend-config=lock_method=POST \
- -backend-config=unlock_method=DELETE \
- -backend-config=retry_wait_min=5
-```
-
-```plaintext
-Initializing the backend...
-
-Successfully configured the backend "http"! Terraform will automatically
-use this backend unless the backend configuration changes.
-
-Initializing provider plugins...
-
-Terraform has been successfully initialized!
-
-You may now begin working with Terraform. Try running "terraform plan" to see
-any changes that are required for your infrastructure. All Terraform commands
-should now work.
-
-If you ever set or change modules or backend configuration for Terraform,
-rerun this command to reinitialize your working directory. If you forget, other
-commands will detect it and remind you to do so if necessary.
-```
-
-Now that `terraform init` has created a `.terraform/` directory that knows where
-the old state is, you can tell it about the new location:
-
-```shell
-TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/new-state-name"
-
-terraform init \
- -backend-config=address=${TF_ADDRESS} \
- -backend-config=lock_address=${TF_ADDRESS}/lock \
- -backend-config=unlock_address=${TF_ADDRESS}/lock \
- -backend-config=username=${TF_USERNAME} \
- -backend-config=password=${TF_PASSWORD} \
- -backend-config=lock_method=POST \
- -backend-config=unlock_method=DELETE \
- -backend-config=retry_wait_min=5
-```
-
-```plaintext
-Initializing the backend...
-Backend configuration changed!
-
-Terraform has detected that the configuration specified for the backend
-has changed. Terraform will now check for existing state in the backends.
-
-
-Acquiring state lock. This may take a few moments...
-Do you want to copy existing state to the new backend?
- Pre-existing state was found while migrating the previous "http" backend to the
- newly configured "http" backend. No existing state was found in the newly
- configured "http" backend. Do you want to copy this state to the new "http"
- backend? Enter "yes" to copy and "no" to start with an empty state.
-
- Enter a value: yes
-
-
-Successfully configured the backend "http"! Terraform will automatically
-use this backend unless the backend configuration changes.
-
-Initializing provider plugins...
-
-Terraform has been successfully initialized!
-
-You may now begin working with Terraform. Try running "terraform plan" to see
-any changes that are required for your infrastructure. All Terraform commands
-should now work.
-
-If you ever set or change modules or backend configuration for Terraform,
-rerun this command to reinitialize your working directory. If you forget, other
-commands will detect it and remind you to do so if necessary.
-```
-
-If you type `yes`, it copies your state from the old location to the new
-location. You can then go back to running it from within GitLab CI.
-
-## Output Terraform Plan information into a merge request
-
-Using the [GitLab Terraform Report artifact](../../ci/pipelines/job_artifacts.md#artifactsreportsterraform),
-you can expose details from `terraform plan` runs directly into a merge request widget,
-enabling you to see statistics about the resources that Terraform creates,
-modifies, or destroys.
+Read more on setting up and [using GitLab Managed Terraform states](terraform_state.md)
-Let's explore how to configure a GitLab Terraform Report artifact. You can
-either use a pre-built image which includes a `gitlab-terraform` helper as
-above, where `gitlab-terraform plan-json` outputs the required artifact, or you
-can configure this manually as follows:
+## Terraform integration in Merge Requests
-1. For simplicity, let's define a few reusable variables to allow us to
- refer to these files multiple times:
+Collaborating around Infrastructure as Code (IaC) changes requires both code changes and expected infrastructure changes to be checked and approved. GitLab provides a solution to help collaboration around Terraform code changes and their expected effects using the Merge Request pages. This way users don't have to build custom tools or rely on 3rd party solutions to streamline their IaC workflows.
- ```yaml
- variables:
- PLAN: plan.cache
- PLAN_JSON: plan.json
- ```
+Read more on setting up and [using the merge request integrations](mr_integration.md).
-1. Install `jq`, a
- [lightweight and flexible command-line JSON processor](https://stedolan.github.io/jq/).
-1. Create an alias for a specific `jq` command that parses out the information we
- want to extract from the `terraform plan` output:
-
- ```yaml
- before_script:
- - apk --no-cache add jq
- - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'"
- ```
-
- NOTE: **Note:**
- In distributions that use Bash (for example, Ubuntu), `alias` statements are not
- expanded in non-interactive mode. If your pipelines fail with the error
- `convert_report: command not found`, alias expansion can be activated explicitly
- by adding a `shopt` command to your script:
-
- ```yaml
- before_script:
- - shopt -s expand_aliases
- - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'"
- ```
-
-1. Define a `script` that runs `terraform plan` and `terraform show`. These commands
- pipe the output and convert the relevant bits into a store variable `PLAN_JSON`.
- This JSON is used to create a
- [GitLab Terraform Report artifact](../../ci/pipelines/job_artifacts.md#artifactsreportsterraform).
- The Terraform report obtains a Terraform `tfplan.json` file. The collected
- Terraform plan report is uploaded to GitLab as an artifact, and is shown in merge requests.
-
- ```yaml
- plan:
- stage: build
- script:
- - terraform plan -out=$PLAN
- - terraform show --json $PLAN | convert_report > $PLAN_JSON
- artifacts:
- reports:
- terraform: $PLAN_JSON
- ```
-
- For a full example using the pre-built image, see [Example `.gitlab-ci.yaml`
- file](#example-gitlab-ciyaml-file).
-
- For an example displaying multiple reports, see [`.gitlab-ci.yaml` multiple reports file](#multiple-terraform-plan-reports).
-
-1. Running the pipeline displays the widget in the merge request, like this:
-
- ![Merge Request Terraform widget](img/terraform_plan_widget_v13_2.png)
-
-1. Clicking the **View Full Log** button in the widget takes you directly to the
- plan output present in the pipeline logs:
-
- ![Terraform plan logs](img/terraform_plan_log_v13_0.png)
+## Quick Start
-### Example `.gitlab-ci.yaml` file
+Use the following `.gitlab-ci.yml` to set up a simple Terraform project integration
+for GitLab versions 13.5 and greater:
```yaml
-default:
- image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest
-
- cache:
- key: example-production
- paths:
- - ${TF_ROOT}/.terraform
+include:
+ - template: Terraform.latest.gitlab-ci.yml
variables:
- TF_ROOT: ${CI_PROJECT_DIR}/environments/example/production
- TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/example-production
-
-before_script:
- - cd ${TF_ROOT}
-
-stages:
- - prepare
- - validate
- - build
- - deploy
-
-init:
- stage: prepare
- script:
- - gitlab-terraform init
-
-validate:
- stage: validate
- script:
- - gitlab-terraform validate
-
-plan:
- stage: build
- script:
- - gitlab-terraform plan
- - gitlab-terraform plan-json
- artifacts:
- name: plan
- paths:
- - ${TF_ROOT}/plan.cache
- reports:
- terraform: ${TF_ROOT}/plan.json
-
-apply:
- stage: deploy
- environment:
- name: production
- script:
- - gitlab-terraform apply
- dependencies:
- - plan
- when: manual
- only:
- - master
-```
-
-### Multiple Terraform Plan reports
-
-Starting with GitLab version 13.2, you can display multiple reports on the Merge Request
-page. The reports also display the `artifacts: name:`. See example below for a suggested setup.
-
-```yaml
-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
-
-.terraform-plan-generation:
- stage: build
- variables:
- PLAN: plan.tfplan
- JSON_PLAN_FILE: tfplan.json
- before_script:
- - cd ${TERRAFORM_DIRECTORY}
- - terraform --version
- - terraform init
- - apk --no-cache add jq
- script:
- - terraform validate
- - terraform plan -out=${PLAN}
- - terraform show --json ${PLAN} | jq -r '([.resource_changes[]?.change.actions?]|flatten)|{"create":(map(select(.=="create"))|length),"update":(map(select(.=="update"))|length),"delete":(map(select(.=="delete"))|length)}' > ${JSON_PLAN_FILE}
- artifacts:
- reports:
- terraform: ${TERRAFORM_DIRECTORY}/${JSON_PLAN_FILE}
-
-review_plan:
- extends: .terraform-plan-generation
- variables:
- TERRAFORM_DIRECTORY: "review/"
- # Review will not include an artifact name
-
-staging_plan:
- extends: .terraform-plan-generation
- variables:
- TERRAFORM_DIRECTORY: "staging/"
- artifacts:
- name: Staging
-
-production_plan:
- extends: .terraform-plan-generation
- variables:
- TERRAFORM_DIRECTORY: "production/"
- artifacts:
- name: Production
+ # If not using GitLab's HTTP backend, remove this line and specify TF_HTTP_* variables
+ TF_STATE_NAME: default
+ TF_CACHE_KEY: default
```
-## Using a GitLab managed Terraform state backend as a remote data source
-
-You can use a GitLab-managed Terraform state as a
-[Terraform data source](https://www.terraform.io/docs/providers/terraform/d/remote_state.html).
-To use your existing Terraform state backend as a data source, provide the following details
-as [Terraform input variables](https://www.terraform.io/docs/configuration/variables.html):
-
-- **address**: The URL of the remote state backend you want to use as a data source.
- For example, `https://gitlab.com/api/v4/projects/<TARGET-PROJECT-ID>/terraform/state/<TARGET-STATE-NAME>`.
-- **username**: The username to authenticate with the data source. If you are using a [Personal Access Token](../profile/personal_access_tokens.md) for
- authentication, this is your GitLab username. If you are using GitLab CI, this is `'gitlab-ci-token'`.
-- **password**: The password to authenticate with the data source. If you are using a Personal Access Token for
- authentication, this is the token value. If you are using GitLab CI, it is the contents of the `${CI_JOB_TOKEN}` CI variable.
-
-An example setup is shown below:
-
-1. Create a file named `example.auto.tfvars` with the following contents:
-
- ```plaintext
- example_remote_state_address=https://gitlab.com/api/v4/projects/<TARGET-PROJECT-ID>/terraform/state/<TARGET-STATE-NAME>
- example_username=<GitLab username>
- example_access_token=<GitLab Personal Acceess Token>
- ```
-
-1. Define the data source by adding the following code block in a `.tf` file (such as `data.tf`):
-
- ```hcl
- data "terraform_remote_state" "example" {
- backend = "http"
-
- config = {
- address = var.example_remote_state_address
- username = var.example_username
- password = var.example_access_token
- }
- }
- ```
-
-Outputs from the data source can now be referenced within your Terraform resources
-using `data.terraform_remote_state.example.outputs.<OUTPUT-NAME>`.
+This template uses `.latest.`, instead of stable, and may include breaking changes.
+This template also includes some opinionated decisions, which you can override:
-You need at least [developer access](../permissions.md) to the target project
-to read the Terraform state.
+- Including the latest [GitLab Terraform Image](https://gitlab.com/gitlab-org/terraform-images).
+- Using the [GitLab managed Terraform State](#gitlab-managed-terraform-state) as
+ the Terraform state storage backend.
+- Creating [four pipeline stages](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml):
+ `init`, `validate`, `build`, and `deploy`. These stages
+ [run the Terraform commands](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml)
+ `init`, `validate`, `plan`, `plan-json`, and `apply`. The `apply` command only runs on `master`.
diff --git a/doc/user/infrastructure/mr_integration.md b/doc/user/infrastructure/mr_integration.md
new file mode 100644
index 00000000000..7d9a036cac8
--- /dev/null
+++ b/doc/user/infrastructure/mr_integration.md
@@ -0,0 +1,205 @@
+---
+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
+---
+
+# Terraform integration in Merge Requests
+
+Collaborating around Infrastructure as Code (IaC) changes requires both code changes and expected infrastructure changes to be checked and approved. GitLab provides a solution to help collaboration around Terraform code changes and their expected effects using the Merge Request pages. This way users don't have to build custom tools or rely on 3rd party solutions to streamline their IaC workflows.
+
+## Output Terraform Plan information into a merge request
+
+Using the [GitLab Terraform Report artifact](../../ci/pipelines/job_artifacts.md#artifactsreportsterraform),
+you can expose details from `terraform plan` runs directly into a merge request widget,
+enabling you to see statistics about the resources that Terraform creates,
+modifies, or destroys.
+
+## Setup
+
+NOTE: **Note:**
+GitLab ships with a [pre-built CI template](index.md#quick-start) that uses GitLab Managed Terraform state and integrates Terraform changes into merge requests. We recommend customizing the pre-built image and relying on the `gitlab-terraform` helper provided within for a quick setup.
+
+To manually configure a GitLab Terraform Report artifact requires the following steps:
+
+1. For simplicity, let's define a few reusable variables to allow us to
+ refer to these files multiple times:
+
+ ```yaml
+ variables:
+ PLAN: plan.cache
+ PLAN_JSON: plan.json
+ ```
+
+1. Install `jq`, a
+ [lightweight and flexible command-line JSON processor](https://stedolan.github.io/jq/).
+1. Create an alias for a specific `jq` command that parses out the information we
+ want to extract from the `terraform plan` output:
+
+ ```yaml
+ before_script:
+ - apk --no-cache add jq
+ - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'"
+ ```
+
+ NOTE: **Note:**
+ In distributions that use Bash (for example, Ubuntu), `alias` statements are not
+ expanded in non-interactive mode. If your pipelines fail with the error
+ `convert_report: command not found`, alias expansion can be activated explicitly
+ by adding a `shopt` command to your script:
+
+ ```yaml
+ before_script:
+ - shopt -s expand_aliases
+ - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'"
+ ```
+
+1. Define a `script` that runs `terraform plan` and `terraform show`. These commands
+ pipe the output and convert the relevant bits into a store variable `PLAN_JSON`.
+ This JSON is used to create a
+ [GitLab Terraform Report artifact](../../ci/pipelines/job_artifacts.md#artifactsreportsterraform).
+ The Terraform report obtains a Terraform `tfplan.json` file. The collected
+ Terraform plan report is uploaded to GitLab as an artifact, and is shown in merge requests.
+
+ ```yaml
+ plan:
+ stage: build
+ script:
+ - terraform plan -out=$PLAN
+ - terraform show --json $PLAN | convert_report > $PLAN_JSON
+ artifacts:
+ reports:
+ terraform: $PLAN_JSON
+ ```
+
+ For a full example using the pre-built image, see [Example `.gitlab-ci.yaml`
+ file](#example-gitlab-ciyaml-file).
+
+ For an example displaying multiple reports, see [`.gitlab-ci.yaml` multiple reports file](#multiple-terraform-plan-reports).
+
+1. Running the pipeline displays the widget in the merge request, like this:
+
+ ![Merge Request Terraform widget](img/terraform_plan_widget_v13_2.png)
+
+1. Clicking the **View Full Log** button in the widget takes you directly to the
+ plan output present in the pipeline logs:
+
+ ![Terraform plan logs](img/terraform_plan_log_v13_0.png)
+
+### Example `.gitlab-ci.yaml` file
+
+```yaml
+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
+
+before_script:
+ - cd ${TF_ROOT}
+
+stages:
+ - prepare
+ - validate
+ - build
+ - deploy
+
+init:
+ stage: prepare
+ script:
+ - gitlab-terraform init
+
+validate:
+ stage: validate
+ script:
+ - gitlab-terraform validate
+
+plan:
+ stage: build
+ script:
+ - gitlab-terraform plan
+ - gitlab-terraform plan-json
+ artifacts:
+ name: plan
+ paths:
+ - ${TF_ROOT}/plan.cache
+ reports:
+ terraform: ${TF_ROOT}/plan.json
+
+apply:
+ stage: deploy
+ environment:
+ name: production
+ script:
+ - gitlab-terraform apply
+ dependencies:
+ - plan
+ when: manual
+ only:
+ - master
+```
+
+### Multiple Terraform Plan reports
+
+Starting with GitLab version 13.2, you can display multiple reports on the Merge Request
+page. The reports also display the `artifacts: name:`. See example below for a suggested setup.
+
+```yaml
+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
+
+.terraform-plan-generation:
+ stage: build
+ variables:
+ PLAN: plan.tfplan
+ JSON_PLAN_FILE: tfplan.json
+ before_script:
+ - cd ${TERRAFORM_DIRECTORY}
+ - terraform --version
+ - terraform init
+ - apk --no-cache add jq
+ script:
+ - terraform validate
+ - terraform plan -out=${PLAN}
+ - terraform show --json ${PLAN} | jq -r '([.resource_changes[]?.change.actions?]|flatten)|{"create":(map(select(.=="create"))|length),"update":(map(select(.=="update"))|length),"delete":(map(select(.=="delete"))|length)}' > ${JSON_PLAN_FILE}
+ artifacts:
+ reports:
+ terraform: ${TERRAFORM_DIRECTORY}/${JSON_PLAN_FILE}
+
+review_plan:
+ extends: .terraform-plan-generation
+ variables:
+ TERRAFORM_DIRECTORY: "review/"
+ # Review will not include an artifact name
+
+staging_plan:
+ extends: .terraform-plan-generation
+ variables:
+ TERRAFORM_DIRECTORY: "staging/"
+ artifacts:
+ name: Staging
+
+production_plan:
+ extends: .terraform-plan-generation
+ variables:
+ TERRAFORM_DIRECTORY: "production/"
+ artifacts:
+ name: Production
+```
diff --git a/doc/user/infrastructure/terraform_state.md b/doc/user/infrastructure/terraform_state.md
new file mode 100644
index 00000000000..ef36f0217be
--- /dev/null
+++ b/doc/user/infrastructure/terraform_state.md
@@ -0,0 +1,360 @@
+---
+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 managed Terraform State
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2673) in GitLab 13.0.
+
+[Terraform remote backends](https://www.terraform.io/docs/backends/index.html)
+enable you to store the state file in a remote, shared store. GitLab uses the
+[Terraform HTTP backend](https://www.terraform.io/docs/backends/types/http.html)
+to securely store the state files in local storage (the default) or
+[the remote store of your choice](../../administration/terraform_state.md).
+
+The GitLab managed Terraform state backend can store your Terraform state easily and
+securely, and spares you from setting up additional remote resources like
+Amazon S3 or Google Cloud Storage. Its features include:
+
+- Supporting encryption of the state file both in transit and at rest.
+- Locking and unlocking state.
+- Remote Terraform plan and apply execution.
+
+## Permissions for using Terraform
+
+In GitLab version 13.1, [Maintainer access](../permissions.md) was required to use a
+GitLab managed Terraform state backend. In GitLab versions 13.2 and greater,
+[Maintainer access](../permissions.md) is required to lock, unlock and write to the state
+(using `terraform apply`), while [Developer access](../permissions.md) is required to read
+the state (using `terraform plan -lock=false`).
+
+## Set up GitLab-managed Terraform state
+
+To get started with a GitLab-managed Terraform state, there are two different options:
+
+- [Use a local machine](#get-started-using-local-development).
+- [Use GitLab CI](#get-started-using-gitlab-ci).
+
+Terraform States can be found by navigating to a Project's **{cloud-gear}** **Operations > Terraform** page.
+
+### Get started using local development
+
+If you plan to only run `terraform plan` and `terraform apply` commands from your
+local machine, this is a simple way to get started:
+
+1. Create your project on your GitLab instance.
+1. Navigate to **Settings > General** and note your **Project name**
+ and **Project ID**.
+1. Define the Terraform backend in your Terraform project to be:
+
+ ```hcl
+ terraform {
+ backend "http" {
+ }
+ }
+ ```
+
+1. Create a [Personal Access Token](../profile/personal_access_tokens.md) with
+ the `api` scope.
+
+1. On your local machine, run `terraform init`, passing in the following options,
+ replacing `<YOUR-STATE-NAME>`, `<YOUR-PROJECT-ID>`, `<YOUR-USERNAME>` and
+ `<YOUR-ACCESS-TOKEN>` with the relevant values. This command initializes your
+ Terraform state, and stores that state within your GitLab project. The name of
+ your state can contain only uppercase and lowercase letters, decimal digits,
+ hyphens, and underscores. This example uses `gitlab.com`:
+
+ ```shell
+ terraform init \
+ -backend-config="address=https://gitlab.com/api/v4/projects/<YOUR-PROJECT-ID>/terraform/state/<YOUR-STATE-NAME>" \
+ -backend-config="lock_address=https://gitlab.com/api/v4/projects/<YOUR-PROJECT-ID>/terraform/state/<YOUR-STATE-NAME>/lock" \
+ -backend-config="unlock_address=https://gitlab.com/api/v4/projects/<YOUR-PROJECT-ID>/terraform/state/<YOUR-STATE-NAME>/lock" \
+ -backend-config="username=<YOUR-USERNAME>" \
+ -backend-config="password=<YOUR-ACCESS-TOKEN>" \
+ -backend-config="lock_method=POST" \
+ -backend-config="unlock_method=DELETE" \
+ -backend-config="retry_wait_min=5"
+ ```
+
+You can now run `terraform plan` and `terraform apply` as you normally would.
+
+### Get started using GitLab CI
+
+If you don't want to start with local development, you can also use GitLab CI to
+run your `terraform plan` and `terraform apply` commands.
+
+Next, [configure the backend](#configure-the-backend).
+
+#### Configure the backend
+
+After executing the `terraform init` command, you must configure the Terraform backend
+and the CI YAML file:
+
+1. In your Terraform project, define the [HTTP backend](https://www.terraform.io/docs/backends/types/http.html)
+ by adding the following code block in a `.tf` file (such as `backend.tf`) to
+ define the remote backend:
+
+ ```hcl
+ terraform {
+ backend "http" {
+ }
+ }
+ ```
+
+1. In the root directory of your project repository, configure a
+ `.gitlab-ci.yaml` file. This example uses a pre-built image which includes a
+ `gitlab-terraform` helper. For supported Terraform versions, see the [GitLab
+ Terraform Images project](https://gitlab.com/gitlab-org/terraform-images).
+
+ ```yaml
+ image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest
+ ```
+
+1. In the `.gitlab-ci.yaml` file, define some environment variables to ease
+ development. In this example, `TF_ROOT` is the directory where the Terraform
+ commands must be executed, `TF_ADDRESS` is the URL to the state on the GitLab
+ instance where this pipeline runs, and the final path segment in `TF_ADDRESS`
+ is the name of the Terraform state. Projects may have multiple states, and
+ this name is arbitrary, so in this example we set it to `example-production`
+ which corresponds with the directory we're using as our `TF_ROOT`, and we
+ ensure that the `.terraform` directory is cached between jobs in the pipeline
+ using a cache key based on the state name (`example-production`):
+
+ ```yaml
+ 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
+ ```
+
+1. In a `before_script`, change to your `TF_ROOT`:
+
+ ```yaml
+ before_script:
+ - cd ${TF_ROOT}
+
+ stages:
+ - prepare
+ - validate
+ - build
+ - deploy
+
+ init:
+ stage: prepare
+ script:
+ - gitlab-terraform init
+
+ validate:
+ stage: validate
+ script:
+ - gitlab-terraform validate
+
+ plan:
+ stage: build
+ script:
+ - gitlab-terraform plan
+ - gitlab-terraform plan-json
+ artifacts:
+ name: plan
+ paths:
+ - ${TF_ROOT}/plan.cache
+ reports:
+ terraform: ${TF_ROOT}/plan.json
+
+ apply:
+ stage: deploy
+ environment:
+ name: production
+ script:
+ - gitlab-terraform apply
+ dependencies:
+ - plan
+ when: manual
+ only:
+ - master
+ ```
+
+1. Push your project to GitLab, which triggers a CI job pipeline. This pipeline
+ runs the `gitlab-terraform init`, `gitlab-terraform validate`, and
+ `gitlab-terraform plan` commands.
+
+The output from the above `terraform` commands should be viewable in the job logs.
+
+CAUTION: **Caution:**
+Like any other job artifact, Terraform plan data is [viewable by anyone with Guest access](../permissions.md) to the repository.
+Neither Terraform nor GitLab encrypts the plan file by default. If your Terraform plan
+includes sensitive data such as passwords, access tokens, or certificates, GitLab strongly
+recommends encrypting plan output or modifying the project visibility settings.
+
+### Example project
+
+See [this reference project](https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-aws) using GitLab and Terraform to deploy a basic AWS EC2 within a custom VPC.
+
+## Using a GitLab managed Terraform state backend as a remote data source
+
+You can use a GitLab-managed Terraform state as a
+[Terraform data source](https://www.terraform.io/docs/providers/terraform/d/remote_state.html).
+To use your existing Terraform state backend as a data source, provide the following details
+as [Terraform input variables](https://www.terraform.io/docs/configuration/variables.html):
+
+- **address**: The URL of the remote state backend you want to use as a data source.
+ For example, `https://gitlab.com/api/v4/projects/<TARGET-PROJECT-ID>/terraform/state/<TARGET-STATE-NAME>`.
+- **username**: The username to authenticate with the data source. If you are using a [Personal Access Token](../profile/personal_access_tokens.md) for
+ authentication, this is your GitLab username. If you are using GitLab CI, this is `'gitlab-ci-token'`.
+- **password**: The password to authenticate with the data source. If you are using a Personal Access Token for
+ authentication, this is the token value. If you are using GitLab CI, it is the contents of the `${CI_JOB_TOKEN}` CI variable.
+
+An example setup is shown below:
+
+1. Create a file named `example.auto.tfvars` with the following contents:
+
+ ```plaintext
+ example_remote_state_address=https://gitlab.com/api/v4/projects/<TARGET-PROJECT-ID>/terraform/state/<TARGET-STATE-NAME>
+ example_username=<GitLab username>
+ example_access_token=<GitLab Personal Acceess Token>
+ ```
+
+1. Define the data source by adding the following code block in a `.tf` file (such as `data.tf`):
+
+ ```hcl
+ data "terraform_remote_state" "example" {
+ backend = "http"
+
+ config = {
+ address = var.example_remote_state_address
+ username = var.example_username
+ password = var.example_access_token
+ }
+ }
+ ```
+
+Outputs from the data source can now be referenced within your Terraform resources
+using `data.terraform_remote_state.example.outputs.<OUTPUT-NAME>`.
+
+You need at least [developer access](../permissions.md) to the target project
+to read the Terraform state.
+
+## Migrating to GitLab Managed Terraform state
+
+Terraform supports copying the state when the backend is changed or
+reconfigured. This can be useful if you need to migrate from another backend to
+GitLab managed Terraform state. Using a local terminal is recommended to run the commands needed for migrating to GitLab Managed Terraform state.
+
+The following example demonstrates how to change the state name, the same workflow is needed to migrate to GitLab Managed Terraform state from a different state storage backend.
+
+### Setting up the initial backend
+
+```shell
+PROJECT_ID="<gitlab-project-id>"
+TF_USERNAME="<gitlab-username>"
+TF_PASSWORD="<gitlab-personal-access-token>"
+TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/old-state-name"
+
+terraform init \
+ -backend-config=address=${TF_ADDRESS} \
+ -backend-config=lock_address=${TF_ADDRESS}/lock \
+ -backend-config=unlock_address=${TF_ADDRESS}/lock \
+ -backend-config=username=${TF_USERNAME} \
+ -backend-config=password=${TF_PASSWORD} \
+ -backend-config=lock_method=POST \
+ -backend-config=unlock_method=DELETE \
+ -backend-config=retry_wait_min=5
+```
+
+```plaintext
+Initializing the backend...
+
+Successfully configured the backend "http"! Terraform will automatically
+use this backend unless the backend configuration changes.
+
+Initializing provider plugins...
+
+Terraform has been successfully initialized!
+
+You may now begin working with Terraform. Try running "terraform plan" to see
+any changes that are required for your infrastructure. All Terraform commands
+should now work.
+
+If you ever set or change modules or backend configuration for Terraform,
+rerun this command to reinitialize your working directory. If you forget, other
+commands will detect it and remind you to do so if necessary.
+```
+
+### Changing the backend
+
+Now that `terraform init` has created a `.terraform/` directory that knows where
+the old state is, you can tell it about the new location:
+
+```shell
+TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/new-state-name"
+
+terraform init \
+ -backend-config=address=${TF_ADDRESS} \
+ -backend-config=lock_address=${TF_ADDRESS}/lock \
+ -backend-config=unlock_address=${TF_ADDRESS}/lock \
+ -backend-config=username=${TF_USERNAME} \
+ -backend-config=password=${TF_PASSWORD} \
+ -backend-config=lock_method=POST \
+ -backend-config=unlock_method=DELETE \
+ -backend-config=retry_wait_min=5
+```
+
+```plaintext
+Initializing the backend...
+Backend configuration changed!
+
+Terraform has detected that the configuration specified for the backend
+has changed. Terraform will now check for existing state in the backends.
+
+
+Acquiring state lock. This may take a few moments...
+Do you want to copy existing state to the new backend?
+ Pre-existing state was found while migrating the previous "http" backend to the
+ newly configured "http" backend. No existing state was found in the newly
+ configured "http" backend. Do you want to copy this state to the new "http"
+ backend? Enter "yes" to copy and "no" to start with an empty state.
+
+ Enter a value: yes
+
+
+Successfully configured the backend "http"! Terraform will automatically
+use this backend unless the backend configuration changes.
+
+Initializing provider plugins...
+
+Terraform has been successfully initialized!
+
+You may now begin working with Terraform. Try running "terraform plan" to see
+any changes that are required for your infrastructure. All Terraform commands
+should now work.
+
+If you ever set or change modules or backend configuration for Terraform,
+rerun this command to reinitialize your working directory. If you forget, other
+commands will detect it and remind you to do so if necessary.
+```
+
+If you type `yes`, it copies your state from the old location to the new
+location. You can then go back to running it from within GitLab CI.
+
+## Managing state files
+
+NOTE: **Note:**
+We are currently working on [providing a graphical interface for managing state files](https://gitlab.com/groups/gitlab-org/-/epics/4563).
+
+![Terraform state list](img/terraform_list_view_v13_5.png)
+
+The state files attached to a project can be found under Operations / Terraform.
+
+## Removing a State file
+
+You can only remove a state file by making a request to the API, like the following example:
+
+```shell
+curl --header "Private-Token: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/<your_project_id/terraform/state/<your_state_name>"
+```
diff --git a/doc/user/instance/clusters/index.md b/doc/user/instance/clusters/index.md
index c370f9d8725..68af74b69fe 100644
--- a/doc/user/instance/clusters/index.md
+++ b/doc/user/instance/clusters/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Instance-level Kubernetes clusters
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39840) in GitLab 11.11.
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index 8b65da4ab94..4bdf72673a1 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -425,6 +425,7 @@ GFM recognizes the following:
| merge request | `!123` | `namespace/project!123` | `project!123` |
| snippet | `$123` | `namespace/project$123` | `project$123` |
| epic **(ULTIMATE)** | `&123` | `group1/subgroup&123` | |
+| vulnerability **(ULTIMATE)** *(1)* | `[vulnerability:123]` | `[vulnerability:namespace/project/123]` | `[vulnerability:project/123]` |
| label by ID | `~123` | `namespace/project~123` | `project~123` |
| one-word label by name | `~bug` | `namespace/project~bug` | `project~bug` |
| multi-word label by name | `~"feature request"` | `namespace/project~"feature request"` | `project~"feature request"` |
@@ -438,6 +439,26 @@ GFM recognizes the following:
| repository file line references | `[README](doc/README#L13)` | | |
| [alert](../operations/incident_management/alerts.md) | `^alert#123` | `namespace/project^alert#123` | `project^alert#123` |
+1. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/281035) in GitLab 13.6.
+
+ The Vulnerability special references feature is under development but ready for production use.
+ It is deployed behind a feature flag that is **disabled by default**.
+ [GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md)
+ can opt to enable it for your instance.
+ It's disabled on GitLab.com.
+
+ To disable it:
+
+ ```ruby
+ Feature.disable(:vulnerability_special_references)
+ ```
+
+ To enable it:
+
+ ```ruby
+ Feature.enable(:vulnerability_special_references)
+ ```
+
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`.
@@ -532,7 +553,7 @@ If this snippet was placed on a page at `<your_wiki>/documentation/main`,
it would link to `<your_wiki>/documentation/related`:
```markdown
-[Link to Related Page](./related)
+[Link to Related Page](related)
```
If this snippet was placed on a page at `<your_wiki>/documentation/related/content`,
@@ -546,7 +567,7 @@ If this snippet was placed on a page at `<your_wiki>/documentation/main`,
it would link to `<your_wiki>/documentation/related.md`:
```markdown
-[Link to Related Page](./related.md)
+[Link to Related Page](related.md)
```
If this snippet was placed on a page at `<your_wiki>/documentation/related/content`,
diff --git a/doc/user/operations_dashboard/index.md b/doc/user/operations_dashboard/index.md
index 5a2ff410253..9e2dfd9ad96 100644
--- a/doc/user/operations_dashboard/index.md
+++ b/doc/user/operations_dashboard/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Operations Dashboard **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5781) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5. [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/9218) to [GitLab Premium](https://about.gitlab.com/pricing/) in 11.10.
diff --git a/doc/user/packages/composer_repository/img/project_id_v13_5.png b/doc/user/packages/composer_repository/img/project_id_v13_5.png
deleted file mode 100644
index 45861b6ff1b..00000000000
--- a/doc/user/packages/composer_repository/img/project_id_v13_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md
index d4fb662c3a6..6e5563d0d4e 100644
--- a/doc/user/packages/composer_repository/index.md
+++ b/doc/user/packages/composer_repository/index.md
@@ -77,7 +77,7 @@ Prerequisites:
- A [personal access token](../../../user/profile/personal_access_tokens.md) with the scope set to `api`.
NOTE: **Note:**
- [Deploy tokens](./../../project/deploy_tokens/index.md) are
+ [Deploy tokens](../../project/deploy_tokens/index.md) are
[not yet supported](https://gitlab.com/gitlab-org/gitlab/-/issues/240897) for use with Composer.
To publish the package:
@@ -140,7 +140,7 @@ Prerequisites:
- A [personal access token](../../../user/profile/personal_access_tokens.md) with the scope set to, at minimum, `read_api`.
NOTE: **Note:**
- [Deploy tokens](./../../project/deploy_tokens/index.md) are
+ [Deploy tokens](../../project/deploy_tokens/index.md) are
[not yet supported](https://gitlab.com/gitlab-org/gitlab/-/issues/240897) for use with Composer.
To install a package:
diff --git a/doc/user/packages/conan_repository/index.md b/doc/user/packages/conan_repository/index.md
index 10c820a86be..f6f8d6d61b6 100644
--- a/doc/user/packages/conan_repository/index.md
+++ b/doc/user/packages/conan_repository/index.md
@@ -12,23 +12,27 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Publish Conan packages in your project’s Package Registry. Then install the
packages whenever you need to use them as a dependency.
-To publish Conan packages to the Package Registry, add the
-Package Registry as a remote and authenticate with it.
+To publish Conan packages to the Package Registry, add the Package Registry as a
+remote and authenticate with it.
-Then you can run `conan` commands and publish your package to the Package Registry.
+Then you can run `conan` commands and publish your package to the
+Package Registry.
## Build a Conan package
-This section explains how to install Conan and build a package for your C/C++ project.
+This section explains how to install Conan and build a package for your C/C++
+project.
-If you already use Conan and know how to build your own packages, go to the [next section](#add-the-package-registry-as-a-conan-remote).
+If you already use Conan and know how to build your own packages, go to the
+[next section](#add-the-package-registry-as-a-conan-remote).
### Install Conan
-Download the Conan package manager to your local development environment by following
-the instructions at [conan.io](https://conan.io/downloads.html).
+Download the Conan package manager to your local development environment by
+following the instructions at [conan.io](https://conan.io/downloads.html).
-When installation is complete, verify you can use Conan in your terminal by running:
+When installation is complete, verify you can use Conan in your terminal by
+running:
```shell
conan --version
@@ -42,15 +46,16 @@ Conan version 1.20.5
### Install CMake
-When you develop with C++ and Conan, you have a range of compilers to choose from.
-This example uses the CMake compiler.
+When you develop with C++ and Conan, you can select from many available
+compilers. This example uses the CMake compiler.
To install CMake:
- For Mac, use [homebrew](https://brew.sh/) and run `brew install cmake`.
- For other operating systems, follow the instructions at [cmake.org](https://cmake.org/install/).
-When installation is complete, verify you can use CMake in your terminal by running:
+When installation is complete, verify you can use CMake in your terminal by
+running:
```shell
cmake --version
@@ -60,8 +65,8 @@ The CMake version is printed in the output.
### Create a project
-To test the Package Registry, you need a C++ project. If you don't already have one, you can clone the
-Conan [hello world starter project](https://github.com/conan-io/hello).
+To test the Package Registry, you need a C++ project. If you don't already have
+one, you can clone the Conan [hello world starter project](https://github.com/conan-io/hello).
### Build a package
@@ -74,22 +79,26 @@ To build a package:
conan new Hello/0.1 -t
```
-1. Create a package for the recipe by running `conan create` with the Conan user and channel:
+1. Create a package for the recipe by running `conan create` with the Conan user
+ and channel:
```shell
conan create . mycompany/beta
```
NOTE: **Note:**
- If you use an [instance remote](#add-a-remote-for-your-instance), you must follow a specific [naming convention](#package-recipe-naming-convention-for-instance-remotes).
+ If you use an [instance remote](#add-a-remote-for-your-instance), you must
+ follow a specific [naming convention](#package-recipe-naming-convention-for-instance-remotes).
A package with the recipe `Hello/0.1@mycompany/beta` is created.
-For more details on creating and managing Conan packages, see the [Conan docs](https://docs.conan.io/en/latest/creating_packages.html).
+For more details about creating and managing Conan packages, see the
+[Conan documentation](https://docs.conan.io/en/latest/creating_packages.html).
## Add the Package Registry as a Conan remote
-To run `conan` commands, you must add the Package Registry as a Conan remote for your project or instance.
+To run `conan` commands, you must add the Package Registry as a Conan remote for
+your project or instance.
### Add a remote for your project
@@ -143,9 +152,9 @@ To add the remote:
#### Package recipe naming convention for instance remotes
-The standard Conan recipe convention is `package_name/version@user/channel`,
-but if you're using an [instance remote](#add-a-remote-for-your-instance), the recipe
-`user` must be the plus sign (`+`) separated project path.
+The standard Conan recipe convention is `package_name/version@user/channel`, but
+if you're using an [instance remote](#add-a-remote-for-your-instance), the
+recipe `user` must be the plus sign (`+`) separated project path.
Example recipe names:
@@ -156,58 +165,68 @@ Example recipe names:
| `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 |
-[Project remotes](#add-a-remote-for-your-project) have a more flexible naming convention.
+[Project remotes](#add-a-remote-for-your-project) have a more flexible naming
+convention.
## Authenticate to the Package Registry
-To authenticate to the Package Registry, you need either a personal access token or deploy token.
+To authenticate to the Package Registry, you need either a personal access token
+or deploy token.
-- If you use a [personal access token](../../../user/profile/personal_access_tokens.md), set the scope to `api`.
-- If you use a [deploy token](./../../project/deploy_tokens/index.md), set the scope to `read_package_registry`, `write_package_registry`, or both.
+- If you use a [personal access token](../../../user/profile/personal_access_tokens.md),
+ set the scope to `api`.
+- If you use a [deploy token](../../project/deploy_tokens/index.md), set the
+ scope to `read_package_registry`, `write_package_registry`, or both.
### Add your credentials to the GitLab remote
-Associate your token with the GitLab remote, so that you don't have to explicitly
-add a token to every Conan command.
+Associate your token with the GitLab remote, so that you don't have to
+explicitly add a token to every Conan command.
Prerequisites:
- You must have an authentication token.
-- The Conan remote [must be set](#add-the-package-registry-as-a-conan-remote).
+- The Conan remote [must be configured](#add-the-package-registry-as-a-conan-remote).
-In a terminal, run this command. In this example, the remote name is `gitlab`. Use the name of your remote.
+In a terminal, run this command. In this example, the remote name is `gitlab`.
+Use the name of your remote.
```shell
conan user <gitlab_username or deploy_token_username> -r gitlab -p <personal_access_token or deploy_token>
```
-Now when you run commands with `--remote=gitlab`, your username and password are automatically included in the requests.
+Now when you run commands with `--remote=gitlab`, your username and password are
+included in the requests.
-Alternately, you can explicitly include your credentials in any given command. For example:
+Alternatively, you can explicitly include your credentials in any given command.
+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@mycompany/beta --all --remote=gitlab
```
NOTE: **Note:**
-Your authentication with GitLab expires on a regular basis,
-so occasionally you may need to re-enter your personal access token.
+Because your authentication with GitLab expires on a regular basis, you may
+occasionally need to re-enter your personal access token.
### Set a default remote for your project (optional)
-If you want to interact with the GitLab Package Registry without having to specify a remote,
-you can tell Conan to always use the Package Registry for your packages.
+If you want to interact with the GitLab Package Registry without having to
+specify a remote, you can tell Conan to always use the Package Registry for your
+packages.
-In a terminal, run this command.
+In a terminal, run this command:
```shell
conan remote add_ref Hello/0.1@mycompany/beta gitlab
```
NOTE: **Note:**
-The package recipe includes the version, so the default remote for `Hello/0.1@user/channel` does not work for `Hello/0.2@user/channel`.
+The package recipe includes the version, so the default remote for
+`Hello/0.1@user/channel` doesn't work for `Hello/0.2@user/channel`.
-If you do not set a default user or remote, you can still include the user and remote in your commands:
+If you don't set a default user or remote, you can still include the user and
+remote in your commands:
```shell
`CONAN_LOGIN_USERNAME=<gitlab_username or deploy_token_username> CONAN_PASSWORD=<personal_access_token or deploy_token> <conan command> --remote=gitlab
@@ -215,17 +234,18 @@ If you do not set a default user or remote, you can still include the user and r
## Publish a Conan package
-Publish a Conan package to the Package Registry, so that anyone who can access the project can use the package as a dependency.
+Publish a Conan package to the Package Registry, so that anyone who can access
+the project can use the package as a dependency.
Prerequisites:
-To publish a Conan package, you need:
-
-- The Package Registry [set as a remote](#add-the-package-registry-as-a-conan-remote).
-- [Authentication](#authenticate-to-the-package-registry) set up with the Package Registry.
-- A local [Conan package](https://docs.conan.io/en/latest/creating_packages/getting_started.html).
+- The Conan remote [must be configured](#add-the-package-registry-as-a-conan-remote).
+- [Authentication](#authenticate-to-the-package-registry) with the
+ Package Registry must be configured.
+- A local [Conan package](https://docs.conan.io/en/latest/creating_packages/getting_started.html)
+ must exist.
- For an instance remote, the package must meet the [naming convention](#package-recipe-naming-convention-for-instance-remotes).
-- A project ID, which is on the project's homepage.
+- You must have the project ID, which is on the project's homepage.
To publish the package, use the `conan upload` command:
@@ -237,11 +257,11 @@ conan upload Hello/0.1@mycompany/beta --all
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11678) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7.
-To work with Conan commands in [GitLab CI/CD](./../../../ci/README.md), you can use
-`CI_JOB_TOKEN` in place of the personal access token in your commands.
+To work with Conan commands in [GitLab CI/CD](../../../ci/README.md), you can
+use `CI_JOB_TOKEN` in place of the personal access token in your commands.
-You can provide the `CONAN_LOGIN_USERNAME` and `CONAN_PASSWORD` with each
-Conan command in your `.gitlab-ci.yml` file. For example:
+You can provide the `CONAN_LOGIN_USERNAME` and `CONAN_PASSWORD` with each Conan
+command in your `.gitlab-ci.yml` file. For example:
```yaml
image: conanio/gcc7
@@ -255,24 +275,26 @@ create_package:
- CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload <package-name>/0.1@<group-name>+<project-name>/stable --all --remote=gitlab
```
-Additional Conan images to use as the basis of your CI file are available
-in the [Conan docs](https://docs.conan.io/en/latest/howtos/run_conan_in_docker.html#available-docker-images).
+Additional Conan images to use as the basis of your CI file are available in the
+[Conan docs](https://docs.conan.io/en/latest/howtos/run_conan_in_docker.html#available-docker-images).
## Install a Conan package
-Install a Conan package from the Package Registry so you can use it as a dependency.
+Install a Conan package from the Package Registry so you can use it as a
+dependency.
-Conan packages are often installed as dependencies by using the `conanfile.txt` file.
+Conan packages are often installed as dependencies by using the `conanfile.txt`
+file.
Prerequisites:
-To install a Conan package, you need:
-
-- The Package Registry [set as a remote](#add-the-package-registry-as-a-conan-remote).
-- [Authentication](#authenticate-to-the-package-registry) set up with the Package Registry.
+- The Conan remote [must be configured](#add-the-package-registry-as-a-conan-remote).
+- [Authentication](#authenticate-to-the-package-registry) with the
+ Package Registry must be configured.
-1. In the project where you want to install the package as a dependency, open `conanfile.txt`.
- Or, in the root of your project, create a file called `conanfile.txt`.
+1. In the project where you want to install the package as a dependency, open
+ `conanfile.txt`. Or, in the root of your project, create a file called
+ `conanfile.txt`.
1. Add the Conan recipe to the `[requires]` section of the file:
@@ -284,7 +306,8 @@ To install a Conan package, you need:
cmake
```
-1. At the root of your project, create a `build` directory and change to that directory:
+1. At the root of your project, create a `build` directory and change to that
+ directory:
```shell
mkdir build && cd build
@@ -298,7 +321,7 @@ To install a Conan package, you need:
NOTE: **Note:**
If you try to install the package you just created in this tutorial, the package
-already exists on your local machine, so this command has no effect.
+already exists on your local computer, so this command has no effect.
## Remove a Conan package
@@ -310,19 +333,22 @@ There are two ways to remove a Conan package from the GitLab Package Registry.
conan remove Hello/0.2@user/channel --remote=gitlab
```
- You must explicitly include the remote in this command, otherwise the package is only removed from your
- local system cache.
+ You must explicitly include the remote in this command, otherwise the package
+ is removed only from your local system cache.
NOTE: **Note:**
- This command removes all recipe and binary package files from the Package Registry.
+ This command removes all recipe and binary package files from the
+ Package Registry.
- From the GitLab user interface:
- Go to your project's **Packages & Registries > Package Registry**. Remove the package by clicking the red trash icon.
+ Go to your project's **Packages & Registries > Package Registry**. Remove the
+ package by clicking the red trash icon.
## Search for Conan packages in the Package Registry
-To search by full or partial package name, or by exact recipe, run the `conan search` command.
+To search by full or partial package name, or by exact recipe, run the
+`conan search` command.
- To search for all packages with a specific package name:
@@ -336,7 +362,8 @@ To search by full or partial package name, or by exact recipe, run the `conan se
conan search He* --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.
+The scope of your search includes all projects you have permission to access.
+This includes your private projects as well as all public projects.
## Fetch Conan package information from the Package Registry
@@ -351,7 +378,9 @@ conan info Hello/0.1@mycompany/beta
The GitLab Conan repository supports the following Conan CLI commands:
- `conan upload`: Upload your recipe and package files to the Package Registry.
-- `conan install`: Install a Conan package from the Package Registry, this includes using the `conanfile.txt` file.
-- `conan search`: Search the Package Registry for public packages, and private packages you have permission to view.
+- `conan install`: Install a Conan package from the Package Registry, which
+ includes using the `conanfile.txt` file.
+- `conan search`: Search the Package Registry for public packages, and private
+ packages you have permission to view.
- `conan info`: View the information on a given package from the Package Registry.
- `conan remove`: Delete the package from the Package Registry.
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index baadd3c91a7..1cb6c951bd9 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -447,7 +447,7 @@ For the project where it's defined, tags matching the regex pattern are removed.
The underlying layers and images remain.
To delete the underlying layers and images that aren't associated with any tags, administrators can use
-[garbage collection](../../../administration/packages/container_registry.md#removing-unused-layers-not-referenced-by-manifests) with the `-m` switch.
+[garbage collection](../../../administration/packages/container_registry.md#removing-untagged-manifests-and-unreferenced-layers) with the `-m` switch.
### Enable the cleanup policy
@@ -468,7 +468,7 @@ Cleanup policies can be run on all projects, with these exceptions:
```
There are performance risks with enabling it for all projects, especially if you
- are using an [external registry](./index.md#use-with-external-container-registries).
+ are using an [external registry](index.md#use-with-external-container-registries).
- For self-managed GitLab instances, you can enable or disable the cleanup policy for a specific
project.
@@ -522,7 +522,7 @@ To create a cleanup policy in the UI:
| **Expiration interval** | How long tags are exempt from being deleted. |
| **Expiration schedule** | How often the policy should run. |
| **Number of tags to retain** | How many tags to _always_ keep for each image. |
- | **Tags with names matching this regex pattern expire:** | The regex pattern that determines which tags to remove. For all tags, use `.*`. See other [regex pattern examples](#regex-pattern-examples). |
+ | **Tags with names matching this regex pattern expire:** | The regex pattern that determines which tags to remove. This value cannot be blank. For all tags, use `.*`. See other [regex pattern examples](#regex-pattern-examples). |
| **Tags with names matching this regex pattern are preserved:** | The regex pattern that determines which tags to preserve. The `latest` tag is always preserved. For all tags, use `.*`. See other [regex pattern examples](#regex-pattern-examples). |
1. Click **Set cleanup policy**.
@@ -544,6 +544,8 @@ Here are examples of regex patterns you may want to use:
.*
```
+ This is the default value for the expiration regex.
+
- Match tags that start with `v`:
```plaintext
@@ -578,7 +580,7 @@ See the API documentation for further details: [Edit project](../../../api/proje
### Use with external container registries
-When using an [external container registry](./../../../administration/packages/container_registry.md#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint),
+When using an [external container registry](../../../administration/packages/container_registry.md#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint),
running a cleanup policy on a project may have some performance risks.
If a project runs a policy to remove thousands of tags
the GitLab background jobs may get backed up or fail completely.
diff --git a/doc/user/packages/dependency_proxy/index.md b/doc/user/packages/dependency_proxy/index.md
index 3fa21ef486b..e1fae770a5d 100644
--- a/doc/user/packages/dependency_proxy/index.md
+++ b/doc/user/packages/dependency_proxy/index.md
@@ -4,9 +4,10 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Dependency Proxy **(PREMIUM)**
+# Dependency Proxy
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.11.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.11.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/273655) to [GitLab Core](https://about.gitlab.com/pricing/) in GitLab 13.6.
The GitLab Dependency Proxy is a local proxy you can use for your frequently-accessed
upstream images.
@@ -41,6 +42,9 @@ The Dependency Proxy is not available for projects.
## Use the Dependency Proxy for Docker images
+CAUTION: **Important:**
+In some specific storage configurations, an issue occurs and container images are not pulled correctly from the cache. The problem occurs when an image is located in object storage. The proxy looks for it locally and fails to find it. View [issue #208080](https://gitlab.com/gitlab-org/gitlab/-/issues/208080) for details.
+
You can use GitLab as a source for your Docker images.
Prerequisites:
diff --git a/doc/user/packages/generic_packages/index.md b/doc/user/packages/generic_packages/index.md
index 0c961b5c86f..f489c7c800f 100644
--- a/doc/user/packages/generic_packages/index.md
+++ b/doc/user/packages/generic_packages/index.md
@@ -49,7 +49,7 @@ Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" \
--upload-file path/to/file.txt \
- https://gitlab.example.com/api/v4/projects/24/generic/my_package/0.0.1/file.txt
+ https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt
```
Example response:
@@ -85,12 +85,12 @@ Example request that uses a personal access token:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" \
- https://gitlab.example.com/api/v4/projects/24/generic/my_package/0.0.1/file.txt
+ https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt
```
## Publish a generic package by using CI/CD
-To work with generic packages in [GitLab CI/CD](./../../../ci/README.md), you can use
+To work with generic packages in [GitLab CI/CD](../../../ci/README.md), you can use
`CI_JOB_TOKEN` in place of the personal access token in your commands.
For example:
@@ -137,3 +137,9 @@ Feature.disable(:generic_packages)
# For a single project
Feature.disable(:generic_packages, Project.find(<project id>))
```
+
+### Generic package sample project
+
+The [Write CI-CD Variables in Pipeline](https://gitlab.com/guided-explorations/cfg-data/write-ci-cd-variables-in-pipeline) project contains a working example you can use to create, upload, and download generic packages in GitLab CI/CD.
+
+It also demonstrates how to manage a semantic version for the generic package: storing it in a CI/CD variable, retrieving it, incrementing it, and writing it back to the CI/CD variable when tests for the download work correctly.
diff --git a/doc/user/packages/go_proxy/index.md b/doc/user/packages/go_proxy/index.md
index bd3b5b49ebd..81edc3afcfd 100644
--- a/doc/user/packages/go_proxy/index.md
+++ b/doc/user/packages/go_proxy/index.md
@@ -4,11 +4,11 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# GitLab Go Proxy
+# Go proxy for GitLab
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27376) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.1.
> - It's deployed behind a feature flag, disabled by default.
-> - It's disabled on GitLab.com.
+> - It's disabled for GitLab.com.
> - It's not recommended for production use.
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-the-go-proxy).
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
@@ -16,14 +16,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
With the Go proxy for GitLab, every project in GitLab can be fetched with the
[Go proxy protocol](https://proxy.golang.org/).
-## Prerequisites
+## Enable the Go proxy
-### Enable the Go proxy
+The Go proxy for GitLab is under development, and isn't ready for production use
+due to [potential performance issues with large repositories](https://gitlab.com/gitlab-org/gitlab/-/issues/218083).
-The Go proxy for GitLab is under development and not ready for production use, due to
-[potential performance issues with large repositories](https://gitlab.com/gitlab-org/gitlab/-/issues/218083).
-
-It is deployed behind a feature flag that is **disabled by default**.
+It's 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 for your instance.
@@ -47,57 +45,46 @@ Feature.enable(:go_proxy, Project.find(1))
Feature.disable(:go_proxy, Project.find(2))
```
-### Enable the Package Registry
-
-The Package Registry is enabled for new projects by default. If you cannot find
-the **Packages > List** entry under your project's sidebar, verify
-the following:
-
-1. Your GitLab administrator has
- [enabled support for the Package Registry](../../../administration/packages/index.md).
-1. The Package Registry is [enabled for your project](../index.md).
-
NOTE: **Note:**
-GitLab does not currently display Go modules in the **Packages Registry** of a project.
-Follow [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/213770) for details.
+Even if it's enabled, GitLab doesn't display Go modules in the **Package Registry**.
+Follow [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/213770) for
+details.
## Add GitLab as a Go proxy
-NOTE: **Note:**
-To use a Go proxy, you must be using Go 1.13 or later.
-
-The available proxy endpoints are:
+To use GitLab as a Go proxy, you must be using Go 1.13 or later.
-- Project - can fetch modules defined by a project - `/api/v4/projects/:id/packages/go`
+The available proxy endpoint is for fetching modules by project: `/api/v4/projects/:id/packages/go`
-To use the Go proxy for GitLab to fetch Go modules from GitLab, add the
-appropriate proxy endpoint to `GOPROXY`. For details on setting Go environment
-variables, see [Set environment variables](#set-environment-variables). For
-details on configuring `GOPROXY`, see [Dependency Management in Go >
-Proxies](../../../development/go_guide/dependencies.md#proxies).
+To fetch Go modules from GitLab, add the project-specific endpoint to `GOPROXY`.
-For example, adding the project-specific endpoint to `GOPROXY` will tell Go
-to initially query that endpoint and fall back to the default behavior:
+Go queries the endpoint and falls back to the default behavior:
```shell
-go env -w GOPROXY='https://gitlab.com/api/v4/projects/1234/packages/go,https://proxy.golang.org,direct'
+go env -w GOPROXY='https://gitlab.example.com/api/v4/projects/1234/packages/go,https://proxy.golang.org,direct'
```
-With this configuration, Go fetches dependencies as follows:
+With this configuration, Go fetches dependencies in this order:
-1. Attempt to fetch from the project-specific Go proxy.
-1. Attempt to fetch from [proxy.golang.org](https://proxy.golang.org).
-1. Fetch directly with version control system operations (such as `git clone`,
+1. Go attempts to fetch from the project-specific Go proxy.
+1. Go attempts to fetch from [proxy.golang.org](https://proxy.golang.org).
+1. Go fetches directly with version control system operations (like `git clone`,
`svn checkout`, and so on).
-If `GOPROXY` is not specified, Go follows steps 2 and 3, which corresponds to
-setting `GOPROXY` to `https://proxy.golang.org,direct`. If `GOPROXY` only
-contains the project-specific endpoint, Go will only query that endpoint.
+If `GOPROXY` isn't specified, Go follows steps 2 and 3, which corresponds to
+setting `GOPROXY` to `https://proxy.golang.org,direct`. If `GOPROXY`
+contains only the project-specific endpoint, Go queries only that endpoint.
+
+For details about how to set Go environment variables, see
+[Set environment variables](#set-environment-variables).
+
+For details about configuring `GOPROXY`, see
+[Dependency Management in Go > Proxies](../../../development/go_guide/dependencies.md#proxies).
## Fetch modules from private projects
-`go` does not support transmitting credentials over insecure connections. The
-steps below work only if GitLab is configured for HTTPS.
+`go` doesn't support transmitting credentials over insecure connections. The
+following steps work only if GitLab is configured for HTTPS:
1. Configure Go to include HTTP basic authentication credentials when fetching
from the Go proxy for GitLab.
@@ -107,31 +94,38 @@ steps below work only if GitLab is configured for HTTPS.
### Enable request authentication
Create a [personal access token](../../profile/personal_access_tokens.md) with
-the `api` or `read_api` scope and add it to
-[`~/.netrc`](https://ec.haxx.se/usingcurl/usingcurl-netrc):
+the scope set to `api` or `read_api`.
-```netrc
+Open your [`~/.netrc`](https://ec.haxx.se/usingcurl/usingcurl-netrc) file
+and add the following text. Replace the variables in `< >` with your values.
+
+```plaintext
machine <url> login <username> password <token>
```
-`<url>` should be the URL of the GitLab instance, for example `gitlab.com`.
-`<username>` and `<token>` should be your username and the personal access
-token, respectively.
+- `<url>`: The GitLab URL, for example `gitlab.com`.
+- `<username>`: Your username.
+- `<token>`: Your personal access token.
### Disable checksum database queries
-When downloading dependencies, by default Go 1.13 and later validate fetched
-sources against the checksum database `sum.golang.org`. If the checksum of the
-fetched sources does not match the checksum from the database, Go will not build
-the dependency. This causes private modules to fail to build, as
-`sum.golang.org` cannot fetch the source of private modules and thus cannot
-provide a checksum. To resolve this issue, `GONOSUMDB` should be set to a
-comma-separated list of private projects. For details on setting Go environment
-variables, see [Set environment variables](#set-environment-variables). For more
-details on disabling this feature of Go, see [Dependency Management in Go >
-Checksums](../../../development/go_guide/dependencies.md#checksums).
+When downloading dependencies with Go 1.13 and later, fetched sources are
+validated against the checksum database `sum.golang.org`.
+
+If the checksum of the fetched sources doesn't match the checksum from the
+database, Go doesn't build the dependency.
+
+Private modules fail to build because `sum.golang.org` can't fetch the source
+of private modules, and so it cannot provide a checksum.
+
+To resolve this issue, set `GONOSUMDB` to a comma-separated list of private
+projects. For details about setting Go environment variables, see
+[Set environment variables](#set-environment-variables). For more details about
+disabling this feature of Go, see
+[Dependency Management in Go > Checksums](../../../development/go_guide/dependencies.md#checksums).
-For example, to disable checksum queries for `gitlab.com/my/project`, set `GONOSUMDB`:
+For example, to disable checksum queries for `gitlab.com/my/project`, set
+`GONOSUMDB`:
```shell
go env -w GONOSUMDB='gitlab.com/my/project,<previous value>'
@@ -139,32 +133,36 @@ go env -w GONOSUMDB='gitlab.com/my/project,<previous value>'
## Working with Go
-If you are unfamiliar with managing dependencies in Go, or Go in general,
-consider reviewing the following documentation:
+If you're unfamiliar with managing dependencies in Go, or Go in general, review
+the following documentation:
- [Dependency Management in Go](../../../development/go_guide/dependencies.md)
- [Go Modules Reference](https://golang.org/ref/mod)
-- [Documentation (golang.org)](https://golang.org/doc/)
-- [Learn (learn.go.dev)](https://learn.go.dev/)
+- [Documentation (`golang.org`)](https://golang.org/doc/)
+- [Learn (`learn.go.dev`)](https://learn.go.dev/)
### Set environment variables
-Go uses environment variables to control various features. These can be managed
-in all the usual ways, but Go 1.14 will read and write Go environment variables
-from and to a special Go environment file, `~/.go/env` by default. If `GOENV` is
-set to a file, Go will read and write that file instead. If `GOENV` is not set
-but `GOPATH` is set, Go will read and write `$GOPATH/env`.
+Go uses environment variables to control various features. You can manage these
+variables in all the usual ways. However, Go 1.14 reads and writes Go
+environment variables to and from a special Go environment file, `~/.go/env` by
+default.
+
+- If `GOENV` is set to a file, Go reads and writes to and from that file instead.
+- If `GOENV` is not set but `GOPATH` is set, Go reads and writes `$GOPATH/env`.
Go environment variables can be read with `go env <var>` and, in Go 1.14 and
-later, can be written with `go env -w <var>=<value>`. For example, `go env
-GOPATH` or `go env -w GOPATH=/go`.
+later, can be written with `go env -w <var>=<value>`. For example,
+`go env GOPATH` or `go env -w GOPATH=/go`.
### Release a module
Go modules and module versions are defined by source repositories, such as Git,
-SVN, Mercurial, and so on. A module is a repository containing `go.mod` and Go
-files. Module versions are defined by VCS tags. To publish a module, push
-`go.mod` and source files to a VCS repository. To publish a module version, push
-a VCS tag. See [Dependency Management in Go >
-Versioning](../../../development/go_guide/dependencies.md#versioning) for more
-details on what constitutes a valid module or module version.
+SVN, and Mercurial. A module is a repository that contains `go.mod` and Go
+files. Module versions are defined by VCS tags.
+
+To publish a module, push `go.mod` and source files to a VCS repository. To
+publish a module version, push a VCS tag.
+
+See [Dependency Management in Go > Versioning](../../../development/go_guide/dependencies.md#versioning)
+for more details about what constitutes a valid module or module version.
diff --git a/doc/user/packages/index.md b/doc/user/packages/index.md
index 53ba3d01b3e..83d179cbc9c 100644
--- a/doc/user/packages/index.md
+++ b/doc/user/packages/index.md
@@ -30,31 +30,31 @@ The Package Registry supports the following formats:
You can also use the [API](../../api/packages.md) to administer the Package Registry.
-The GitLab [Container Registry](container_registry/index.md) is a secure and private registry for container images.
-It's built on open source software and completely integrated within GitLab.
-Use GitLab CI/CD to create and publish images. Use the GitLab [API](../../api/container_registry.md) to
-manage the registry across groups and projects.
+## Accepting contributions
-The [Dependency Proxy](dependency_proxy/index.md) is a local proxy for frequently-used upstream images and packages.
-
-## Suggested contributions
-
-Consider contributing to GitLab. This [development documentation](../../development/packages.md) will
-guide you through the process. Or check out how other members of the community
-are adding support for [PHP](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17417) or [Terraform](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834).
+The below table lists formats that are not supported, but are accepting Community contributions for. Consider contributing to GitLab. This [development documentation](../../development/packages.md) will
+guide you through the process.
-| Format | Use case |
+| Format | Status |
| ------ | ------ |
-| [Cargo](https://gitlab.com/gitlab-org/gitlab/-/issues/33060) | Cargo is the Rust package manager. Build, publish and share Rust packages |
-| [Chef](https://gitlab.com/gitlab-org/gitlab/-/issues/36889) | Configuration management with Chef using all the benefits of a repository manager. |
-| [CocoaPods](https://gitlab.com/gitlab-org/gitlab/-/issues/36890) | Speed up development with Xcode and CocoaPods. |
-| [Conda](https://gitlab.com/gitlab-org/gitlab/-/issues/36891) | Secure and private local Conda repositories. |
-| [CRAN](https://gitlab.com/gitlab-org/gitlab/-/issues/36892) | Deploy and resolve CRAN packages for the R language. |
-| [Debian](https://gitlab.com/gitlab-org/gitlab/-/issues/5835) | Host and provision Debian packages. |
-| [Opkg](https://gitlab.com/gitlab-org/gitlab/-/issues/36894) | Optimize your work with OpenWrt using Opkg repositories. |
-| [P2](https://gitlab.com/gitlab-org/gitlab/-/issues/36895) | Host all your Eclipse plugins in your own GitLab P2 repository. |
-| [Puppet](https://gitlab.com/gitlab-org/gitlab/-/issues/36897) | Configuration management meets repository management with Puppet repositories. |
-| [RPM](https://gitlab.com/gitlab-org/gitlab/-/issues/5932) | Distribute RPMs directly from GitLab. |
-| [RubyGems](https://gitlab.com/gitlab-org/gitlab/-/issues/803) | Use GitLab to host your own gems. |
-| [SBT](https://gitlab.com/gitlab-org/gitlab/-/issues/36898) | Resolve dependencies from and deploy build output to SBT repositories when running SBT builds. |
-| [Vagrant](https://gitlab.com/gitlab-org/gitlab/-/issues/36899) | Securely host your Vagrant boxes in local repositories. |
+| Chef | [#36889](https://gitlab.com/gitlab-org/gitlab/-/issues/36889) |
+| CocoaPods | [#36890](https://gitlab.com/gitlab-org/gitlab/-/issues/36890) |
+| Conda | [#36891](https://gitlab.com/gitlab-org/gitlab/-/issues/36891) |
+| CRAN | [#36892](https://gitlab.com/gitlab-org/gitlab/-/issues/36892) |
+| Debian | [WIP: Merge Request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44746) |
+| Opkg | [#36894](https://gitlab.com/gitlab-org/gitlab/-/issues/36894) |
+| P2 | [#36895](https://gitlab.com/gitlab-org/gitlab/-/issues/36895) |
+| Puppet | [#36897](https://gitlab.com/gitlab-org/gitlab/-/issues/36897) |
+| RPM | [#5932](https://gitlab.com/gitlab-org/gitlab/-/issues/5932) |
+| RubyGems | [#803](https://gitlab.com/gitlab-org/gitlab/-/issues/803) |
+| SBT | [#36898](https://gitlab.com/gitlab-org/gitlab/-/issues/36898) |
+| Terraform | [WIP: Merge Request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834) |
+| Vagrant | [#36899](https://gitlab.com/gitlab-org/gitlab/-/issues/36899) |
+
+## Container Registry
+
+The GitLab [Container Registry](container_registry/index.md) is a secure and private registry for container images. It's built on open source software and completely integrated within GitLab. Use GitLab CI/CD to create and publish images. Use the GitLab [API](../../api/container_registry.md) to manage the registry across groups and projects.
+
+## Dependency Proxy
+
+The [Dependency Proxy](dependency_proxy/index.md) is a local proxy for frequently-used upstream images and packages.
diff --git a/doc/user/packages/maven_repository/index.md b/doc/user/packages/maven_repository/index.md
index d4a8ff0cdb4..5d0d64b310d 100644
--- a/doc/user/packages/maven_repository/index.md
+++ b/doc/user/packages/maven_repository/index.md
@@ -17,9 +17,9 @@ Then, install the packages whenever you need to use them as a dependency.
This section explains how to install Maven and build a package.
If you already use Maven and know how to build your own packages, go to the
-[next section](#add-the-package-registry-as-a-maven-remote).
+[next section](#authenticate-to-the-package-registry-with-maven).
-Maven repositories work well with Gradle, too. To set up a Gradle project, see [get started with Gradle](#use-gradle-to-create-a-java-project).
+Maven repositories work well with Gradle, too. To set up a Gradle project, see [get started with Gradle](#build-a-java-project-with-gradle).
### Install Maven
@@ -29,14 +29,14 @@ The required minimum versions are:
- Maven 3.6+
Follow the instructions at [maven.apache.org](https://maven.apache.org/install.html)
-to download and install Maven for your local development environment. Once
+to download and install Maven for your local development environment. After
installation is complete, verify you can use Maven in your terminal by running:
```shell
mvn --version
```
-You should see something similar to the below printed in the output:
+The output should be similar to:
```shell
Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-04T20:00:29+01:00)
@@ -48,29 +48,26 @@ OS name: "mac os x", version: "10.15.2", arch: "x86_64", family: "mac"
### Create a project
-Understanding how to create a full Java project is outside the scope of this
-guide but you can follow the steps below to create a new project that can be
+Follow these steps to create a Maven project that can be
published to the GitLab Package Registry.
-Start by opening your terminal and creating a directory where you would like to
-store the project in your environment. From inside the directory, you can run
-the following Maven command to initialize a new package:
+1. Open your terminal and create a directory to store the project.
+1. From the new directory, run this Maven command to initialize a new package:
-```shell
-mvn archetype:generate -DgroupId=com.mycompany.mydepartment -DartifactId=my-project -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
-```
+ ```shell
+ mvn archetype:generate -DgroupId=com.mycompany.mydepartment -DartifactId=my-project -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
+ ```
-The arguments are as follows:
+ The arguments are:
-- `DgroupId`: A unique string that identifies your package. You should follow
-the [Maven naming conventions](https://maven.apache.org/guides/mini/guide-naming-conventions.html).
-- `DartifactId`: The name of the JAR, appended to the end of the `DgroupId`.
-- `DarchetypeArtifactId`: The archetype used to create the initial structure of
-the project.
-- `DinteractiveMode`: Create the project using batch mode (optional).
+ - `DgroupId`: A unique string that identifies your package. Follow
+ the [Maven naming conventions](https://maven.apache.org/guides/mini/guide-naming-conventions.html).
+ - `DartifactId`: The name of the `JAR`, appended to the end of the `DgroupId`.
+ - `DarchetypeArtifactId`: The archetype used to create the initial structure of
+ the project.
+ - `DinteractiveMode`: Create the project using batch mode (optional).
-After running the command, you should see the following message, indicating that
-your project has been set up successfully:
+This message indicates that the project was set up successfully:
```shell
...
@@ -82,33 +79,33 @@ your project has been set up successfully:
[INFO] ------------------------------------------------------------------------
```
-You should see a new directory where you ran this command matching your
-`DartifactId` parameter (in this case it should be `my-project`).
+In the folder where you ran the command, a new directory should be displayed.
+The directory name should match the `DartifactId` parameter, which in this case,
+is `my-project`.
-## Use Gradle to create a Java project
+## Build a Java project with Gradle
This section explains how to install Gradle and initialize a Java project.
If you already use Gradle and know how to build your own packages, go to the
-[next section](#add-the-package-registry-as-a-maven-remote).
+[next section](#authenticate-to-the-package-registry-with-maven).
### Install Gradle
-Installation is needed only if you want to create a new Gradle project. Follow
+If you want to create a new Gradle project, you must install Gradle. Follow
instructions at [gradle.org](https://gradle.org/install/) to download and install
Gradle for your local development environment.
-Verify you can use Gradle in your terminal by running:
+In your terminal, verify you can use Gradle by running:
```shell
gradle -version
```
-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.
+To use an existing Gradle project, in the project directory,
+on Linux execute `gradlew`, or on Windows execute `gradlew.bat`.
-You should see something similar to the below printed in the output:
+The output should be similar to:
```plaintext
------------------------------------------------------------
@@ -127,88 +124,79 @@ OS: Windows 10 10.0 amd64
### Create a Java project
-Understanding how to create a full Java project in Gradle is outside the scope of this
-guide, but you can follow the steps below to create a new project that can be
+Follow these steps to create a Maven project that can be
published to the GitLab Package Registry.
-Start by opening your terminal and creating a directory where you would like to
-store the project in your environment. From inside the directory, you can run
-the following Maven command to initialize a new package:
+1. Open your terminal and create a directory to store the project.
+1. From this new directory, run this Maven command to initialize a new package:
-```shell
-gradle init
-```
+ ```shell
+ gradle init
+ ```
-The output should be
+ The output should be:
-```plaintext
-Select type of project to generate:
- 1: basic
- 2: application
- 3: library
- 4: Gradle plugin
-Enter selection (default: basic) [1..4]
-```
+ ```plaintext
+ Select type of project to generate:
+ 1: basic
+ 2: application
+ 3: library
+ 4: Gradle plugin
+ Enter selection (default: basic) [1..4]
+ ```
-Enter `3` to create a new Library project. The output should be:
+1. Enter `3` to create a new Library project. The output should be:
-```plaintext
-Select implementation language:
- 1: C++
- 2: Groovy
- 3: Java
- 4: Kotlin
- 5: Scala
- 6: Swift
-```
+ ```plaintext
+ Select implementation language:
+ 1: C++
+ 2: Groovy
+ 3: Java
+ 4: Kotlin
+ 5: Scala
+ 6: Swift
+ ```
-Enter `3` to create a new Java Library project. The output should be:
+1. Enter `3` to create a new Java Library project. The output should be:
-```plaintext
-Select build script DSL:
- 1: Groovy
- 2: Kotlin
-Enter selection (default: Groovy) [1..2]
-```
+ ```plaintext
+ Select build script DSL:
+ 1: Groovy
+ 2: Kotlin
+ Enter selection (default: Groovy) [1..2]
+ ```
-Choose `1` to create a new Java Library project which is described in Groovy DSL. The output should be:
+1. Enter `1` to create a new Java Library project that is described in Groovy DSL. The output should be:
-```plaintext
-Select test framework:
- 1: JUnit 4
- 2: TestNG
- 3: Spock
- 4: JUnit Jupiter
-```
+ ```plaintext
+ Select test framework:
+ 1: JUnit 4
+ 2: TestNG
+ 3: Spock
+ 4: JUnit Jupiter
+ ```
-Choose `1` to initialize the project with JUnit 4 testing libraries. The output should be:
+1. Enter `1` to initialize the project with JUnit 4 testing libraries. The output should be:
-```plaintext
-Project name (default: test):
-```
+ ```plaintext
+ Project name (default: test):
+ ```
-Enter a project name or hit enter to use the directory name as project name.
+1. Enter a project name or press Enter to use the directory name as project name.
-## Add the Package Registry as a Maven remote
+## Authenticate to the Package Registry with Maven
-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 must be provided for authorization too. Support is available
-for [personal access tokens](#authenticate-with-a-personal-access-token),
-[CI job tokens](#authenticate-with-a-ci-job-token), and
-[deploy tokens](../../project/deploy_tokens/index.md) only. Regular username/password
-credentials do not work.
+To authenticate to the Package Registry, you need either a personal access token or deploy token.
-### Authenticate with a personal access token
+- If you use a [personal access token](../../../user/profile/personal_access_tokens.md), set the scope to `api`.
+- If you use a [deploy token](../../project/deploy_tokens/index.md), set the scope to `read_package_registry`, `write_package_registry`, or both.
-To authenticate with a [personal access token](../../profile/personal_access_tokens.md),
-set the scope to `api` when creating one, and add it to your Maven or Gradle configuration
-files.
+### Authenticate with a personal access token in Maven
-#### Authenticate with a personal access token in Maven
+To use a personal access token, add this section to your
+[`settings.xml`](https://maven.apache.org/settings.html) file.
-Add a corresponding section to your
-[`settings.xml`](https://maven.apache.org/settings.html) file:
+The `name` must be `Private-Token`.
```xml
<settings>
@@ -228,45 +216,40 @@ Add a corresponding section to your
</settings>
```
-#### Authenticate with a personal access token in Gradle
+### Authenticate with a deploy token in Maven
-Create a file `~/.gradle/gradle.properties` with the following content:
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) deploy token authentication in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
-```groovy
-gitLabPrivateToken=REPLACE_WITH_YOUR_PERSONAL_ACCESS_TOKEN
-```
+To use a deploy token, add this section to your
+[`settings.xml`](https://maven.apache.org/settings.html) file.
-Add a repositories section to your
-[`build.gradle`](https://docs.gradle.org/current/userguide/tutorial_using_tasks.html)
-file:
+The `name` must be `Deploy-Token`.
-```groovy
-repositories {
- maven {
- url "https://<gitlab-url>/api/v4/groups/<group>/-/packages/maven"
- name "GitLab"
- credentials(HttpHeaderCredentials) {
- name = 'Private-Token'
- value = gitLabPrivateToken
- }
- authentication {
- header(HttpHeaderAuthentication)
- }
- }
-}
+```xml
+<settings>
+ <servers>
+ <server>
+ <id>gitlab-maven</id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>Deploy-Token</name>
+ <value>REPLACE_WITH_YOUR_DEPLOY_TOKEN</value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+</settings>
```
-You should now be able to upload Maven artifacts to your project.
-
-### Authenticate with a CI job token
+### Authenticate with a CI job token in Maven
-If you're using GitLab CI/CD, a CI job token can be used instead
-of a personal access token.
+To authenticate with a CI job token, add this section to your
+[`settings.xml`](https://maven.apache.org/settings.html) file.
-#### Authenticate with a CI job token in Maven
-
-To authenticate with a CI job token, add a corresponding section to your
-[`settings.xml`](https://maven.apache.org/settings.html) file:
+The `name` must be `Job-Token`.
```xml
<settings>
@@ -286,23 +269,35 @@ To authenticate with a CI job token, add a corresponding section to your
</settings>
```
-You can read more on
-[how to create Maven packages using GitLab CI/CD](#creating-maven-packages-with-gitlab-cicd).
+Read more about [how to create Maven packages using GitLab CI/CD](#create-maven-packages-with-gitlab-cicd).
+
+## Authenticate to the Package Registry with Gradle
-#### Authenticate with a CI job token in Gradle
+To authenticate to the Package Registry, you need either a personal access token or deploy token.
-To authenticate with a CI job token, add a repositories section to your
+- If you use a [personal access token](../../../user/profile/personal_access_tokens.md), set the scope to `api`.
+- If you use a [deploy token](../../project/deploy_tokens/index.md), set the scope to `read_package_registry`, `write_package_registry`, or both.
+
+### Authenticate with a personal access token in Gradle
+
+Create a file `~/.gradle/gradle.properties` with the following content:
+
+```groovy
+gitLabPrivateToken=REPLACE_WITH_YOUR_PERSONAL_ACCESS_TOKEN
+```
+
+Add a `repositories` section to your
[`build.gradle`](https://docs.gradle.org/current/userguide/tutorial_using_tasks.html)
file:
```groovy
repositories {
maven {
- url "https://<gitlab-url>/api/v4/groups/<group>/-/packages/maven"
+ url "https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven"
name "GitLab"
credentials(HttpHeaderCredentials) {
- name = 'Job-Token'
- value = System.getenv("CI_JOB_TOKEN")
+ name = 'Private-Token'
+ value = gitLabPrivateToken
}
authentication {
header(HttpHeaderAuthentication)
@@ -311,51 +306,42 @@ repositories {
}
```
-### Authenticate with a deploy token
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0.
-
-To authenticate with a [deploy token](./../../project/deploy_tokens/index.md),
-set the scope to `api` when creating one, and add it to your Maven or Gradle configuration
-files.
-
-#### Authenticate with a deploy token in Maven
+### Authenticate with a deploy token in Gradle
-Add a corresponding section to your
-[`settings.xml`](https://maven.apache.org/settings.html) file:
+To authenticate with a deploy token, add a `repositories` section to your
+[`build.gradle`](https://docs.gradle.org/current/userguide/tutorial_using_tasks.html)
+file:
-```xml
-<settings>
- <servers>
- <server>
- <id>gitlab-maven</id>
- <configuration>
- <httpHeaders>
- <property>
- <name>Deploy-Token</name>
- <value>REPLACE_WITH_YOUR_DEPLOY_TOKEN</value>
- </property>
- </httpHeaders>
- </configuration>
- </server>
- </servers>
-</settings>
+```groovy
+repositories {
+ maven {
+ url "https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven"
+ name "GitLab"
+ credentials(HttpHeaderCredentials) {
+ name = 'Deploy-Token'
+ value = '<deploy-token>'
+ }
+ authentication {
+ header(HttpHeaderAuthentication)
+ }
+ }
+}
```
-#### Authenticate with a deploy token in Gradle
+### Authenticate with a CI job token in Gradle
-To authenticate with a deploy token, add a repositories section to your
+To authenticate with a CI job token, add a `repositories` section to your
[`build.gradle`](https://docs.gradle.org/current/userguide/tutorial_using_tasks.html)
file:
```groovy
repositories {
maven {
- url "https://<gitlab-url>/api/v4/groups/<group>/-/packages/maven"
+ url "https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven"
name "GitLab"
credentials(HttpHeaderCredentials) {
- name = 'Deploy-Token'
- value = '<deploy-token>'
+ name = 'Job-Token'
+ value = System.getenv("CI_JOB_TOKEN")
}
authentication {
header(HttpHeaderAuthentication)
@@ -364,177 +350,162 @@ repositories {
}
```
-## Configuring your project to use the GitLab Maven repository URL
-
-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 must add the following information to your
-`my-project/pom.xml` file.
+## Use the GitLab endpoint for Maven packages
-Depending on your workflow and the amount of Maven packages you have, there are
-3 ways you can configure your project to use the GitLab endpoint for Maven packages:
+To use the GitLab endpoint for Maven packages, choose an option:
-- **Project level**: Useful when you have few Maven packages which are not under
+- **Project-level**: Use when you have few Maven packages and they are not in
the same GitLab group.
-- **Group level**: Useful when you have many Maven packages under the same GitLab
+- **Group-level**: Use when you have many Maven packages in the same GitLab
group.
-- **Instance level**: Useful when you have many Maven packages under different
- GitLab groups or on their own namespace.
+- **Instance-level**: Use when you have many Maven packages in different
+ GitLab groups or in their own namespace.
+
+The option you choose determines the settings you'll add to your `pom.xml` file.
-NOTE: **Note:**
-In all cases, you need a project specific URL for uploading a package in
-the `distributionManagement` section.
+In all cases, to publish a package, you need:
-### Project level Maven endpoint
+- A project-specific URL in the `distributionManagement` section.
+- A `repository` and `distributionManagement` section.
-The example below shows how the relevant `repository` section of your `pom.xml`
-would look like in Maven:
+### Project-level Maven endpoint
+
+The relevant `repository` section of your `pom.xml`
+in Maven should look like this:
```xml
<repositories>
<repository>
<id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ <url>https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ <url>https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven</url>
</repository>
<snapshotRepository>
<id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ <url>https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven</url>
</snapshotRepository>
</distributionManagement>
```
-The corresponding section in Gradle would look like this:
+The corresponding section in Gradle would be:
```groovy
repositories {
maven {
- url "https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven"
+ url "https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven"
name "GitLab"
}
}
```
-The `id` must be the same with what you
-[defined in `settings.xml`](#add-the-package-registry-as-a-maven-remote).
-
-Replace `PROJECT_ID` with your project ID which can be found on the home page
-of your project.
+- The `id` is what you [defined in `settings.xml`](#authenticate-to-the-package-registry-with-maven).
+- The `PROJECT_ID` is your project ID, which you can view on your project's home page.
+- Replace `gitlab.example.com` with your domain name.
+- For retrieving artifacts, use either the
+ [URL-encoded](../../../api/README.md#namespaced-path-encoding) path of the project
+ (like `group%2Fproject`) or the project's ID (like `42`). However, only the
+ project's ID can be used for publishing.
-If you have a self-managed GitLab installation, replace `gitlab.com` with your
-domain name.
+### Group-level Maven endpoint
-NOTE: **Note:**
-For retrieving artifacts, you can use either the
-[URL encoded](../../../api/README.md#namespaced-path-encoding) path of the project
-(such as `group%2Fproject`) or the project's ID (such as `42`). However, only the
-project's ID can be used for uploading.
-
-### Group level Maven endpoint
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8798) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8798) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
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
+with a unique URL for each package. Instead, you can use the group-level endpoint for
+all the Maven packages stored within one GitLab group. Only packages you have access to
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 does not guarantee the uniqueness of the package names within
+The group-level endpoint works with any package names, so you
+have more flexibility in naming, compared to the [instance-level endpoint](#instance-level-maven-endpoint).
+However, GitLab does not guarantee the uniqueness of package names within
the group. You can have two projects with the same package name and package
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
+This example shows the relevant `repository` section of your `pom.xml` file.
+You still need a project-specific URL for publishing a package in
the `distributionManagement` section:
```xml
<repositories>
<repository>
<id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/groups/GROUP_ID/-/packages/maven</url>
+ <url>https://gitlab.example.com/api/v4/groups/GROUP_ID/-/packages/maven</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ <url>https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven</url>
</repository>
<snapshotRepository>
<id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ <url>https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven</url>
</snapshotRepository>
</distributionManagement>
```
-For Gradle, the corresponding repositories section would look like:
+For Gradle, the corresponding `repositories` section would look like:
```groovy
repositories {
maven {
- url "https://gitlab.com/api/v4/groups/GROUP_ID/-/packages/maven"
+ url "https://gitlab.example.com/api/v4/groups/GROUP_ID/-/packages/maven"
name "GitLab"
}
}
```
-The `id` must be the same with what you
-[defined in `settings.xml`](#add-the-package-registry-as-a-maven-remote).
-
-Replace `my-group` with your group name and `PROJECT_ID` with your project ID
-which can be found on the home page of your project.
-
-If you have a self-managed GitLab installation, replace `gitlab.com` with your
-domain name.
+- For the `id`, use what you [defined in `settings.xml`](#authenticate-to-the-package-registry-with-maven).
+- For `my-group`, use your group name.
+- For `PROJECT_ID`, use your project ID, which you can view on your project's home page.
+- Replace `gitlab.example.com` with your domain name.
+- For retrieving artifacts, use either the
+ [URL-encoded](../../../api/README.md#namespaced-path-encoding) path of the group
+ (like `group%2Fsubgroup`) or the group's ID (like `12`).
-NOTE: **Note:**
-For retrieving artifacts, you can use either the
-[URL encoded](../../../api/README.md#namespaced-path-encoding) path of the group
-(such as `group%2Fsubgroup`) or the group's ID (such as `12`).
+### Instance-level Maven endpoint
-### Instance level Maven endpoint
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8274) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8274) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
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 are available
+with a unique URL for each package. Instead, you can use the instance-level endpoint for
+all Maven packages stored in GitLab. All packages you have access to are available
for download.
-Note that **only packages that have the same path as the project** are exposed via
-the instance level endpoint.
+**Only packages that have the same path as the project** are exposed by
+the instance-level endpoint.
-| Project | Package | Instance level endpoint available |
+| Project | Package | Instance-level endpoint available |
| ------- | ------- | --------------------------------- |
| `foo/bar` | `foo/bar/1.0-SNAPSHOT` | Yes |
| `gitlab-org/gitlab` | `foo/bar/1.0-SNAPSHOT` | No |
| `gitlab-org/gitlab` | `gitlab-org/gitlab/1.0-SNAPSHOT` | Yes |
-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
-the `distributionManagement` section:
+This example shows how relevant `repository` section of your `pom.xml`.
+You still need a project-specific URL in the `distributionManagement` section.
```xml
<repositories>
<repository>
<id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/packages/maven</url>
+ <url>https://gitlab.example.com/api/v4/packages/maven</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ <url>https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven</url>
</repository>
<snapshotRepository>
<id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ <url>https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven</url>
</snapshotRepository>
</distributionManagement>
```
@@ -544,40 +515,35 @@ The corresponding repositories section in Gradle would look like:
```groovy
repositories {
maven {
- url "https://gitlab.com/api/v4/packages/maven"
+ url "https://gitlab.example.com/api/v4/packages/maven"
name "GitLab"
}
}
```
-The `id` must be the same with what you
-[defined in `settings.xml`](#add-the-package-registry-as-a-maven-remote).
-
-Replace `PROJECT_ID` with your project ID which can be found on the home page
-of your project.
-
-If you have a self-managed GitLab installation, replace `gitlab.com` with your
-domain name.
+- The `id` is what you [defined in `settings.xml`](#authenticate-to-the-package-registry-with-maven).
+- The `PROJECT_ID` is your project ID, which you can view on your project's home page.
+- Replace `gitlab.example.com` with your domain name.
+- For retrieving artifacts, use either the
+ [URL-encoded](../../../api/README.md#namespaced-path-encoding) path of the project
+ (like `group%2Fproject`) or the project's ID (like `42`). However, only the
+ project's ID can be used for publishing.
-NOTE: **Note:**
-For retrieving artifacts, you can use either the
-[URL encoded](../../../api/README.md#namespaced-path-encoding) path of the project
-(such as `group%2Fproject`) or the project's ID (such as `42`). However, only the
-project's ID can be used for uploading.
+## Publish a package
-## Uploading packages
+After you have set up the [remote and authentication](#authenticate-to-the-package-registry-with-maven)
+and [configured your project](#use-the-gitlab-endpoint-for-maven-packages),
+publish a Maven artifact from your project.
-Once you have set up the [remote and authentication](#add-the-package-registry-as-a-maven-remote)
-and [configured your project](#configuring-your-project-to-use-the-gitlab-maven-repository-url),
-test to upload a Maven artifact from a project of yours.
+### Publish by using Maven
-### Upload using Maven
+To publish a package by using Maven:
```shell
mvn deploy
```
-If the deploy is successful, you should see the build success message again:
+If the deploy is successful, the build success message should be displayed:
```shell
...
@@ -585,108 +551,112 @@ If the deploy is successful, you should see the build success message again:
...
```
-You should also see that the upload was uploaded to the correct registry:
+The message should also show that the package was published to the correct location:
```shell
-Uploading to gitlab-maven: https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.jar
+Uploading to gitlab-maven: https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.jar
```
-### Upload using Gradle
+### Publish by using Gradle
-Add the Gradle plugin [`maven-publish`](https://docs.gradle.org/current/userguide/publishing_maven.html) to the plugins section:
+To publish a package by using Gradle:
-```groovy
-plugins {
- id 'java'
- id 'maven-publish'
-}
-```
+1. Add the Gradle plugin [`maven-publish`](https://docs.gradle.org/current/userguide/publishing_maven.html) to the plugins section:
-Add a `publishing` section:
+ ```groovy
+ plugins {
+ id 'java'
+ id 'maven-publish'
+ }
+ ```
-```groovy
-publishing {
- publications {
- library(MavenPublication) {
- from components.java
- }
- }
- repositories {
- maven {
- url "https://gitlab.com/api/v4/projects/<PROJECT_ID>/packages/maven"
- credentials(HttpHeaderCredentials) {
- name = "Private-Token"
- value = gitLabPrivateToken // the variable resides in ~/.gradle/gradle.properties
- }
- authentication {
- header(HttpHeaderAuthentication)
- }
- }
- }
-}
-```
+1. Add a `publishing` section:
+
+ ```groovy
+ publishing {
+ publications {
+ library(MavenPublication) {
+ from components.java
+ }
+ }
+ repositories {
+ maven {
+ url "https://gitlab.example.com/api/v4/projects/<PROJECT_ID>/packages/maven"
+ credentials(HttpHeaderCredentials) {
+ name = "Private-Token"
+ value = gitLabPrivateToken // the variable resides in ~/.gradle/gradle.properties
+ }
+ authentication {
+ header(HttpHeaderAuthentication)
+ }
+ }
+ }
+ }
+ ```
-Replace `PROJECT_ID` with your project ID which can be found on the home page
-of your project.
+1. Replace `PROJECT_ID` with your project ID, which can be found on your project's home page.
-Run the publish task:
+1. Run the publish task:
-```shell
-gradle publish
-```
+ ```shell
+ gradle publish
+ ```
-You can then navigate to your project's **Packages & Registries** page and see the uploaded
-artifacts or even delete them.
+Now navigate to your project's **Packages & Registries** page and view the published artifacts.
-## Installing a package
+## Install a package
-Installing a package from the GitLab Package Registry requires that you set up
-the [remote and authentication](#add-the-package-registry-as-a-maven-remote)
-as above. Once this is completed, there are two ways to install a package.
+To install a package from the GitLab Package Registry, you must configure
+the [remote and authenticate](#authenticate-to-the-package-registry-with-maven).
+When this is completed, there are two ways to install a package.
-### Install using Maven with `mvn install`
+### Use Maven with `mvn install`
-Add the dependency manually to your project `pom.xml` file. To add the example
-created above, the XML would look like:
+To install a package by using `mvn install`:
-```xml
-<dependency>
- <groupId>com.mycompany.mydepartment</groupId>
- <artifactId>my-project</artifactId>
- <version>1.0-SNAPSHOT</version>
-</dependency>
-```
+1. Add the dependency manually to your project `pom.xml` file.
+ To add the example created earlier, the XML would be:
-Then, inside your project, run the following:
+ ```xml
+ <dependency>
+ <groupId>com.mycompany.mydepartment</groupId>
+ <artifactId>my-project</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ ```
-```shell
-mvn install
-```
+1. In your project, run the following:
+
+ ```shell
+ mvn install
+ ```
-Provided everything is set up correctly, you should see the dependency
-downloaded from the GitLab Package Registry:
+The message should show that the package is downloading from the Package Registry:
```shell
-Downloading from gitlab-maven: http://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.pom
+Downloading from gitlab-maven: http://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.pom
```
-### Install using Maven with `mvn dependency:get`
+### Use Maven with `mvn dependency:get`
-The second way to install packages is to use the Maven commands directly.
-Inside your project directory, run:
+You can install packages by using the Maven commands directly.
+
+1. In your project directory, run:
+
+ ```shell
+ mvn dependency:get -Dartifact=com.nickkipling.app:nick-test-app:1.1-SNAPSHOT
+ ```
+
+The message should show that the package is downloading from the Package Registry:
```shell
-mvn dependency:get -Dartifact=com.nickkipling.app:nick-test-app:1.1-SNAPSHOT
+Downloading from gitlab-maven: http://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.pom
```
-You should see the same downloading message confirming that the project was
-retrieved from the GitLab Package Registry.
-
TIP: **Tip:**
-Both the XML block and Maven command are readily copy and pastable from the
-Package details page, allowing for quick and easy installation.
+In the GitLab UI, on the Package Registry page for Maven, you can view and copy these commands.
-### Install using Gradle
+### Use Gradle
Add a [dependency](https://docs.gradle.org/current/userguide/declaring_dependencies.html) to `build.gradle` in the dependencies section:
@@ -696,25 +666,25 @@ dependencies {
}
```
-## Removing a package
+## Remove a package
-In the packages view of your project page, you can delete packages by clicking
-the red trash icons or by clicking the **Delete** button on the package details
-page.
+For your project, go to **Packages & Registries > Package Registry**.
-## Creating Maven packages with GitLab CI/CD
+To remove a package, click the red trash icon or, from the package details, the **Delete** button.
-Once you have your repository configured to use the GitLab Maven Repository,
+## Create Maven packages with GitLab CI/CD
+
+After you have configured your repository to use the Package Repository for Maven,
you can configure GitLab CI/CD to build new packages automatically.
-### Creating Maven packages with GitLab CI/CD using Maven
+### Create Maven packages with GitLab CI/CD by using Maven
-The example below shows how to create a new package each time the `master` branch
-is updated:
+You can create a new package each time the `master` branch is updated.
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`:
+
+1. Add the `server` section with the same ID you defined in your `pom.xml` file.
+ For example, use `gitlab-maven` as the ID:
```xml
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -735,30 +705,29 @@ is updated:
</settings>
```
-1. Make sure your `pom.xml` file includes the following:
+1. Make sure your `pom.xml` file includes the following.
+ You can either let Maven use the CI environment variables, as shown in this example,
+ or you can hard code your project's ID.
```xml
<repositories>
<repository>
<id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ <url>https://gitlab.example.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ <url>https://gitlab.example.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
</repository>
<snapshotRepository>
<id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ <url>https://gitlab.example.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
</snapshotRepository>
</distributionManagement>
```
- TIP: **Tip:**
- You can either let Maven utilize the CI environment variables or hardcode your project's ID.
-
1. Add a `deploy` job to your `.gitlab-ci.yml` file:
```yaml
@@ -773,16 +742,17 @@ is updated:
1. Push those files to your repository.
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 uses the configured CI
-[environment variables](../../../ci/variables/README.md#predefined-environment-variables).
+user's home location. In this example:
+
+- The user is `root`, because the job runs in a Docker container.
+- Maven uses the configured CI [environment variables](../../../ci/variables/README.md#predefined-environment-variables).
-### Creating Maven packages with GitLab CI/CD using Gradle
+### Create Maven packages with GitLab CI/CD by using Gradle
-The example below shows how to create a new package each time the `master` branch
-is updated:
+You can create a package each time the `master` branch
+is updated.
-1. Make sure you use the Job-Token authentication as described in ["Authenticating with a CI job token in Gradle"](#authenticate-with-a-ci-job-token-in-gradle).
+1. Authenticate with [a CI job token in Gradle](#authenticate-with-a-ci-job-token-in-gradle).
1. Add a `deploy` job to your `.gitlab-ci.yml` file:
@@ -795,11 +765,13 @@ is updated:
- master
```
-1. Push those files to your repository.
+1. Commit files to your repository.
+
+When the pipeline is successful, the package is created.
### Version validation
-The version string is validated using the following regex.
+The version string is validated by using the following regex.
```ruby
\A(\.?[\w\+-]+\.?)+\z
@@ -827,7 +799,7 @@ When you set these options, all network requests are logged and a large amount o
### Useful Maven command-line options
There are some [Maven command-line options](https://maven.apache.org/ref/current/maven-embedder/cli.html)
-that may be useful when performing tasks with GitLab CI/CD.
+that you can use when performing tasks with GitLab CI/CD.
- File transfer progress can make the CI logs hard to read.
Option `-ntp,--no-transfer-progress` was added in
@@ -835,7 +807,7 @@ that may be useful when performing tasks with GitLab CI/CD.
Alternatively, look at `-B,--batch-mode`
[or lower level logging changes.](https://stackoverflow.com/questions/21638697/disable-maven-download-progress-indication)
-- Specify where to find the POM file (`-f,--file`):
+- Specify where to find the `pom.xml` file (`-f,--file`):
```yaml
package:
@@ -852,11 +824,10 @@ that may be useful when performing tasks with GitLab CI/CD.
- 'mvn -s settings/ci.xml package'
```
-### Verifying your Maven settings
+### Verify your Maven settings
-If you encounter issues within CI that relate to the `settings.xml` file, it might be useful
-to add an additional script task or job to
-[verify the effective settings](https://maven.apache.org/plugins/maven-help-plugin/effective-settings-mojo.html).
+If you encounter issues within CI/CD that relate to the `settings.xml` file, try adding
+an additional script task or job to [verify the effective settings](https://maven.apache.org/plugins/maven-help-plugin/effective-settings-mojo.html).
The help plugin can also provide
[system properties](https://maven.apache.org/plugins/maven-help-plugin/system-mojo.html), including environment variables:
diff --git a/doc/user/packages/npm_registry/img/npm_package_view_v12_5.png b/doc/user/packages/npm_registry/img/npm_package_view_v12_5.png
deleted file mode 100644
index a6f823011eb..00000000000
--- a/doc/user/packages/npm_registry/img/npm_package_view_v12_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
index f15b31d8b67..feb797240f4 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -4,331 +4,378 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# GitLab NPM Registry
+# NPM packages in the Package Registry
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
-With the GitLab NPM Registry, every
-project can have its own space to store NPM packages.
+Publish NPM packages in your project's Package Registry. Then install the
+packages whenever you need to use them as a dependency.
-![GitLab NPM Registry](img/npm_package_view_v12_5.png)
-
-NOTE: **Note:**
Only [scoped](https://docs.npmjs.com/misc/scope) packages are supported.
-## Enabling the NPM Registry
-
-NOTE: **Note:**
-This option is available only if your GitLab administrator has
-[enabled support for the NPM registry](../../../administration/packages/index.md).
-
-Enabling the NPM registry makes it available for all new projects
-by default. To enable it for existing projects, or if you want to disable it:
-
-1. Navigate to your project's **Settings > General > Visibility, project features, permissions**.
-1. Find the Packages feature and enable or disable it.
-1. Click on **Save changes** for the changes to take effect.
-
-You should then be able to see the **Packages & Registries** section on the left sidebar.
+## Build an NPM package
-Before proceeding to authenticating with the GitLab NPM Registry, you should
-get familiar with the package naming convention.
+This section covers how to install NPM or Yarn and build a package for your
+JavaScript project.
-## Getting started
+If you already use NPM and know how to build your own packages, go to
+the [next section](#authenticate-to-the-package-registry).
-This section covers how to install NPM (or Yarn) and build a package for your
-JavaScript project. This is a quickstart if you are new to NPM packages. If you
-are already using NPM and understand how to build your own packages, move on to
-the [next section](#authenticating-to-the-gitlab-npm-registry).
+### Install NPM
-### Installing NPM
+Install Node.js and NPM in your local development environment by following
+the instructions at [npmjs.com](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).
-Follow the instructions at [npmjs.com](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) to download and install Node.js and
-NPM to your local development environment.
-
-Once installation is complete, verify you can use NPM in your terminal by
+When installation is complete, verify you can use NPM in your terminal by
running:
```shell
npm --version
```
-You should see the NPM version printed in the output:
+The NPM version is shown in the output:
```plaintext
6.10.3
```
-### Installing Yarn
+### Install Yarn
-You may want to install and use Yarn as an alternative to NPM. Follow the
-instructions at [yarnpkg.com](https://classic.yarnpkg.com/en/docs/install) to install on
-your development environment.
+As an alternative to NPM, you can install Yarn in your local environment by following the
+instructions at [yarnpkg.com](https://classic.yarnpkg.com/en/docs/install).
-Once installed, you can verify that Yarn is available with the following command:
+When installation is complete, verify you can use Yarn in your terminal by
+running:
```shell
yarn --version
```
-You should see the version printed like so:
+The Yarn version is shown in the output:
```plaintext
1.19.1
```
-### Creating a project
+### Create a project
-Understanding how to create a full JavaScript project is outside the scope of
-this guide but you can initialize a new empty package by creating and navigating
-to an empty directory and using the following command:
+To create a project:
-```shell
-npm init
-```
+1. Create an empty directory.
+1. Go to the directory and initialize an empty package by running:
-Or if you're using Yarn:
+ ```shell
+ npm init
+ ```
-```shell
-yarn init
-```
+ Or if you're using Yarn:
+
+ ```shell
+ yarn init
+ ```
+
+1. Enter responses to the questions. Ensure the **package name** follows
+ the [naming convention](#package-naming-convention) and is scoped to the
+ project or group where the registry exists.
+
+A `package.json` file is created.
+
+## Use the GitLab endpoint for NPM packages
+
+To use the GitLab endpoint for NPM packages, choose an option:
+
+- **Project-level**: Use when you have few NPM packages and they are not in
+ the same GitLab group.
+- **Instance-level**: Use when you have many NPM packages in different
+ GitLab groups or in their own namespace. Be sure to comply with the [package naming convention](#package-naming-convention).
-This takes you through a series of questions to produce a `package.json`
-file, which is required for all NPM packages. The most important question is the
-package name. NPM packages must [follow the naming convention](#package-naming-convention)
-and be scoped to the project or group where the registry exists.
+Some features such as [publishing](#publish-an-npm-package) a package is only available on the project-level endpoint.
-Once you have completed the setup, you are now ready to upload your package to
-the GitLab registry. To get started, you need to set up authentication and then
-configure GitLab as a remote registry.
+## Authenticate to the Package Registry
-## Authenticating to the GitLab NPM Registry
+To authenticate to the Package Registry, you must use one of the following:
-If a project is private or you want to upload an NPM package to GitLab,
-you need to provide credentials for authentication. [Personal access tokens](../../profile/personal_access_tokens.md)
-and [deploy tokens](../../project/deploy_tokens/index.md)
-are preferred, but support is available for [OAuth tokens](../../../api/oauth2.md#resource-owner-password-credentials-flow).
+- A [personal access token](../../../user/profile/personal_access_tokens.md)
+ (required for two-factor authentication (2FA)), with the scope set to `api`.
+- A [deploy token](../../project/deploy_tokens/index.md), with the scope set to `read_package_registry`, `write_package_registry`, or both.
+- It's not recommended, but you can use [OAuth tokens](../../../api/oauth2.md#resource-owner-password-credentials-flow).
+ Standard OAuth tokens cannot authenticate to the GitLab NPM Registry. You must use a personal access token with OAuth headers.
+- A [CI job token](#authenticate-with-a-ci-job-token).
-CAUTION: **Two-factor authentication (2FA) is only supported with personal access tokens:**
-If you have 2FA enabled, you need to use a [personal access token](../../profile/personal_access_tokens.md) with OAuth headers with the scope set to `api` or a [deploy token](../../project/deploy_tokens/index.md) with `read_package_registry` or `write_package_registry` scopes. Standard OAuth tokens cannot authenticate to the GitLab NPM Registry.
+### Authenticate with a personal access token or deploy token
-### Authenticating with a personal access token or deploy token
+To authenticate with the Package Registry, you will need a [personal access token](../../profile/personal_access_tokens.md) or [deploy token](../../project/deploy_tokens/index.md).
-To authenticate with a [personal access token](../../profile/personal_access_tokens.md) or [deploy token](../../project/deploy_tokens/index.md),
-set your NPM configuration:
+#### Project-level NPM endpoint
+
+To use the [project-level](#use-the-gitlab-endpoint-for-npm-packages) NPM endpoint, set your NPM configuration:
```shell
# Set URL for your scoped packages.
# For example package with name `@foo/bar` will use this URL for download
-npm config set @foo:registry https://gitlab.com/api/v4/packages/npm/
+npm config set @foo:registry https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/
-# Add the token for the scoped packages URL. This will allow you to download
-# `@foo/` packages from private projects.
-npm config set '//gitlab.com/api/v4/packages/npm/:_authToken' "<your_token>"
-
-# Add token for uploading to the registry. Replace <your_project_id>
-# with the project you want your package to be uploaded to.
-npm config set '//gitlab.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken' "<your_token>"
+# Add the token for the scoped packages URL. Replace <your_project_id>
+# with the project where your package is located.
+npm config set '//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken' "<your_token>"
```
-Replace `<your_project_id>` with your project ID which can be found on the home page
-of your project and `<your_token>` with your personal access token or deploy token.
-
-If you have a self-managed GitLab installation, replace `gitlab.com` with your
-domain name.
+- `<your_project_id>` is your project ID, found on the project's home page.
+- `<your_token>` is your personal access token or deploy token.
+- Replace `gitlab.example.com` with your domain name.
-You should now be able to download and upload NPM packages to your project.
+You should now be able to publish and install NPM packages in your project.
-NOTE: **Note:**
-If you encounter an error message with [Yarn](https://classic.yarnpkg.com/en/), see the
-[troubleshooting section](#troubleshooting).
+If you encounter an error with [Yarn](https://classic.yarnpkg.com/en/), view
+[troubleshooting steps](#troubleshooting).
-### Using variables to avoid hard-coding auth token values
+#### Instance-level NPM endpoint
-To avoid hard-coding the `authToken` value, you may use a variables in its place:
+To use the [instance-level](#use-the-gitlab-endpoint-for-npm-packages) NPM endpoint, set your NPM configuration:
```shell
-npm config set '//gitlab.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken' "${NPM_TOKEN}"
-npm config set '//gitlab.com/api/v4/packages/npm/:_authToken' "${NPM_TOKEN}"
-```
+# Set URL for your scoped packages.
+# For example package with name `@foo/bar` will use this URL for download
+npm config set @foo:registry https://gitlab.example.com/api/v4/packages/npm/
-Then, you could run `npm publish` either locally or via GitLab CI/CD:
+# Add the token for the scoped packages URL. This will allow you to download
+# `@foo/` packages from private projects.
+npm config set '//gitlab.example.com/api/v4/packages/npm/:_authToken' "<your_token>"
+```
-- **Locally:** Export `NPM_TOKEN` before publishing:
+- `<your_token>` is your personal access token or deploy token.
+- Replace `gitlab.example.com` with your domain name.
- ```shell
- NPM_TOKEN=<your_token> npm publish
- ```
+You should now be able to publish and install NPM packages in your project.
-- **GitLab CI/CD:** Set an `NPM_TOKEN` [variable](../../../ci/variables/README.md)
- under your project's **Settings > CI/CD > Variables**.
+If you encounter an error with [Yarn](https://classic.yarnpkg.com/en/), view
+[troubleshooting steps](#troubleshooting).
-### Authenticating with a CI job token
+### Authenticate with a CI job token
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9104) in GitLab Premium 12.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9104) in GitLab Premium 12.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
-If you’re using NPM with GitLab CI/CD, a CI job token can be used instead of a personal access token or deploy token.
+If you're using NPM with GitLab CI/CD, a CI job token can be used instead of a personal access token or deploy token.
The token inherits the permissions of the user that generates the pipeline.
-Add a corresponding section to your `.npmrc` file:
+#### Project-level NPM endpoint
+
+To use the [project-level](#use-the-gitlab-endpoint-for-npm-packages) NPM endpoint, add a corresponding section to your `.npmrc` file:
```ini
-@foo:registry=https://gitlab.com/api/v4/packages/npm/
-//gitlab.com/api/v4/packages/npm/:_authToken=${CI_JOB_TOKEN}
-//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}
+@foo:registry=https://gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/
+//gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}
```
-## Uploading packages
+#### Instance-level NPM endpoint
-Before you can upload a package, you need to specify the registry
-for NPM. To do this, add the following section to the bottom of `package.json`:
+To use the [instance-level](#use-the-gitlab-endpoint-for-npm-packages) NPM endpoint, add a corresponding section to your `.npmrc` file:
-```json
-"publishConfig": {
- "@foo:registry":"https://gitlab.com/api/v4/projects/<your_project_id>/packages/npm/"
-}
+```ini
+@foo:registry=https://gitlab.example.com/api/v4/packages/npm/
+//gitlab.example.com/api/v4/packages/npm/:_authToken=${CI_JOB_TOKEN}
```
-Replace `<your_project_id>` with your project ID, which can be found on the home
-page of your project, and replace `@foo` with your own scope.
-
-If you have a self-managed GitLab installation, replace `gitlab.com` with your
-domain name.
+#### Use variables to avoid hard-coding auth token values
-Once you have enabled it and set up [authentication](#authenticating-to-the-gitlab-npm-registry),
-you can upload an NPM package to your project:
+To avoid hard-coding the `authToken` value, you may use a variable in its place:
```shell
-npm publish
+npm config set '//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken' "${NPM_TOKEN}"
+npm config set '//gitlab.example.com/api/v4/packages/npm/:_authToken' "${NPM_TOKEN}"
```
-You can then navigate to your project's **Packages & Registries** page and see the uploaded
-packages or even delete them.
+Then, you can run `npm publish` either locally or by using GitLab CI/CD.
-Attempting to publish a package with a name that already exists within
-a given scope causes a `403 Forbidden!` error.
+- **Locally:** Export `NPM_TOKEN` before publishing:
-## Uploading a package with the same version twice
+ ```shell
+ NPM_TOKEN=<your_token> npm publish
+ ```
-You cannot upload a package with the same name and version twice, unless you
-delete the existing package first. This aligns with npmjs.org's behavior, with
-the exception that npmjs.org does not allow users to ever publish the same version
-more than once, even if it has been deleted.
+- **GitLab CI/CD:** Set an `NPM_TOKEN` [variable](../../../ci/variables/README.md)
+ under your project's **Settings > CI/CD > Variables**.
## Package naming convention
-**Packages must be scoped in the root namespace of the project**. The package
-name may be anything but it is preferred that the project name be used unless
-it is not possible due to a naming collision. For example:
+Your NPM package name must be in the format of `@scope:package-name`.
+
+- The `@scope` is the root namespace of the GitLab project. It must match exactly, including the case.
+- The `package-name` can be whatever you want.
+
+For example, if your project is `https://gitlab.example.com/my-org/engineering-group/team-amazing/analytics`,
+the root namespace is `my-org`. When you publish a package, it must have `my-org` as the scope.
| Project | Package | Supported |
| ---------------------- | ----------------------- | --------- |
-| `foo/bar` | `@foo/bar` | Yes |
-| `foo/bar/baz` | `@foo/baz` | Yes |
-| `foo/bar/buz` | `@foo/anything` | Yes |
+| `my-org/bar` | `@my-org/bar` | Yes |
+| `my-org/bar/baz` | `@my-org/baz` | Yes |
+| `My-org/Bar/baz` | `@My-org/Baz` | Yes |
+| `my-org/bar/buz` | `@my-org/anything` | Yes |
| `gitlab-org/gitlab` | `@gitlab-org/gitlab` | Yes |
| `gitlab-org/gitlab` | `@foo/bar` | No |
-The regex that is used for naming is validating all package names from all package managers:
+In GitLab, this regex validates all package names from all package managers:
```plaintext
/\A\@?(([\w\-\.\+]*)\/)*([\w\-\.]+)@?(([\w\-\.\+]*)\/)*([\w\-\.]*)\z/
```
-It allows for capital letters, while NPM does not, and allows for almost all of the
-characters NPM allows with a few exceptions (`~` is not allowed).
+This regex allows almost all of the characters that NPM allows, with a few exceptions (for example, `~` is not allowed).
+
+The regex also allows for capital letters, while NPM does not. Capital letters are needed because the scope must be
+identical to the root namespace of the project.
-NOTE: **Note:**
-Capital letters are needed because the scope is required to be
-identical to the top level namespace of the project. So, for example, if your
-project path is `My-Group/project-foo`, your package must be named `@My-Group/any-package-name`.
-`@my-group/any-package-name` will not work.
+CAUTION: **Caution:**
+When you update the path of a user or group, or transfer a subgroup or project,
+you must remove any NPM packages first. You cannot update the root namespace
+of a project with NPM packages. Make sure you update your `.npmrc` files to follow
+the naming convention and run `npm publish` if necessary.
-CAUTION: **When updating the path of a user/group or transferring a (sub)group/project:**
-Make sure to remove any NPM packages first. You cannot update the root namespace of a project with NPM packages. Don't forget to update your `.npmrc` files to follow the above naming convention and run `npm publish` if necessary.
+## Publish an NPM package
-Now, you can configure your project to authenticate with the GitLab NPM
-Registry.
+Prerequisites:
-## Installing a package
+- [Authenticate](#authenticate-to-the-package-registry) to the Package Registry.
+- Set a [project-level NPM endpoint](#use-the-gitlab-endpoint-for-npm-packages).
-NPM packages are commonly installed using the `npm` or `yarn` commands
-inside a JavaScript project. If you haven't already, set the
-URL for scoped packages. You can do this with the following command:
+To upload an NPM package to your project, run this command:
```shell
-npm config set @foo:registry https://gitlab.com/api/v4/packages/npm/
+npm publish
```
-Replace `@foo` with your scope.
+To view the package, go to your project's **Packages & Registries**.
-Next, you need to ensure [authentication](#authenticating-to-the-gitlab-npm-registry)
-is setup so you can successfully install the package. Once this has been
-completed, you can run the following command inside your project to install a
-package:
+If you try to publish a package [with a name that already exists](#publishing-packages-with-the-same-name-or-version) within
+a given scope, you get a `403 Forbidden!` error.
-```shell
-npm install @my-project-scope/my-package
-```
+## Publish an NPM package by using CI/CD
-Or if you're using Yarn:
+Prerequisites:
-```shell
-yarn add @my-project-scope/my-package
+- [Authenticate](#authenticate-to-the-package-registry) to the Package Registry.
+- Set a [project-level NPM endpoint](#use-the-gitlab-endpoint-for-npm-packages).
+
+To work with NPM commands within [GitLab CI/CD](../../../ci/README.md), you can use
+`CI_JOB_TOKEN` in place of the personal access token or deploy token in your commands.
+
+An example `.gitlab-ci.yml` file for publishing NPM packages:
+
+```yaml
+image: node:latest
+
+stages:
+ - deploy
+
+deploy:
+ stage: deploy
+ script:
+ - echo "//gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}">.npmrc
+ - npm publish
```
-### Forwarding requests to npmjs.org
+## Publishing packages with the same name or version
+
+You cannot publish a package if a package of the same name and version already exists.
+You must delete the existing package first.
+
+This aligns with npmjs.org's behavior. However, npmjs.org does not ever let you publish
+the same version more than once, even if it has been deleted.
+
+## Install a package
+
+NPM packages are commonly-installed by using the `npm` or `yarn` commands
+in a JavaScript project.
+
+1. Set the URL for scoped packages by running:
+
+ ```shell
+ npm config set @foo:registry https://gitlab.example.com/api/v4/packages/npm/
+ ```
+
+ Replace `@foo` with your scope.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/55344) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.9.
+1. Ensure [authentication](#authenticate-to-the-package-registry) is configured.
-By default, when an NPM package is not found in the GitLab NPM Registry, the request is forwarded to [npmjs.com](https://www.npmjs.com/).
+1. In your project, to install a package, run:
+
+ ```shell
+ npm install @my-project-scope/my-package
+ ```
+
+ Or if you're using Yarn:
+
+ ```shell
+ yarn add @my-project-scope/my-package
+ ```
+
+In [GitLab 12.9 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/55344),
+when an NPM package is not found in the Package Registry, the request is forwarded to [npmjs.com](https://www.npmjs.com/).
Administrators can disable this behavior in the [Continuous Integration settings](../../admin_area/settings/continuous_integration.md).
-### Installing packages from other organizations
+### Install NPM packages from other organizations
You can route package requests to organizations and users outside of GitLab.
-To do this, add lines to your `.npmrc` file, replacing `my-org` with the namespace or group that owns your project's repository. The name is case-sensitive and must match the name of your group or namespace exactly.
+To do this, add lines to your `.npmrc` file. Replace `my-org` with the namespace or group that owns your project's repository,
+and use your organization's URL. The name is case-sensitive and must match the name of your group or namespace exactly.
```shell
@foo:registry=https://gitlab.example.com/api/v4/packages/npm/
-//gitlab.com/api/v4/packages/npm/:_authToken= "<your_token>"
-//gitlab.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken= "<your_token>"
+//gitlab.example.com/api/v4/packages/npm/:_authToken= "<your_token>"
+//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken= "<your_token>"
@my-other-org:registry=https://gitlab.example.com/api/v4/packages/npm/
-//gitlab.com/api/v4/packages/npm/:_authToken= "<your_token>"
-//gitlab.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken= "<your_token>"
+//gitlab.example.com/api/v4/packages/npm/:_authToken= "<your_token>"
+//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken= "<your_token>"
```
-## Removing a package
+### NPM dependencies metadata
-In the packages view of your project page, you can delete packages by clicking
-the red trash icons or by clicking the **Delete** button on the package details
-page.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11867) in GitLab Premium 12.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
-## Publishing a package with CI/CD
+In GitLab 12.6 and later, packages published to the Package Registry expose the following attributes to the NPM client:
-To work with NPM commands within [GitLab CI/CD](./../../../ci/README.md), you can use
-`CI_JOB_TOKEN` in place of the personal access token or deploy token in your commands.
+- name
+- version
+- dist-tags
+- dependencies
+ - dependencies
+ - devDependencies
+ - bundleDependencies
+ - peerDependencies
+ - deprecated
-A simple example `.gitlab-ci.yml` file for publishing NPM packages:
+## Add NPM distribution tags
-```yaml
-image: node:latest
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9425) in GitLab Premium 12.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
-stages:
- - deploy
+You can add [distribution tags](https://docs.npmjs.com/cli/dist-tag) to newly-published packages.
+Tags are optional and can be assigned to only one package at a time.
-deploy:
- stage: deploy
- script:
- - echo "//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}">.npmrc
- - npm publish
+When you publish a package without a tag, the `latest` tag is added by default.
+When you install a package without specifying the tag or version, the `latest` tag is used.
+
+Examples of the supported `dist-tag` commands:
+
+```shell
+npm publish @scope/package --tag # Publish a package with new tag
+npm dist-tag add @scope/package@version my-tag # Add a tag to an existing package
+npm dist-tag ls @scope/package # List all tags under the package
+npm dist-tag rm @scope/package@version my-tag # Delete a tag from the package
+npm install @scope/package@my-tag # Install a specific tag
```
-Learn more about [using `CI_JOB_TOKEN` to authenticate to the GitLab NPM registry](#authenticating-with-a-ci-job-token).
+You cannot use your `CI_JOB_TOKEN` or deploy token with the `npm dist-tag` commands.
+View [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/258835) for details.
+
+Due to a bug in NPM 6.9.0, deleting distribution tags fails. Make sure your NPM version is 6.9.1 or later.
## Troubleshooting
@@ -344,7 +391,7 @@ info No lockfile found.
warning XXX: No license field
[1/4] 🔠Resolving packages...
[2/4] 🚚 Fetching packages...
-error An unexpected error occurred: "https://gitlab.com/api/v4/projects/XXX/packages/npm/XXX/XXX/-/XXX/XXX-X.X.X.tgz: Request failed \"404 Not Found\"".
+error An unexpected error occurred: "https://gitlab.example.com/api/v4/projects/XXX/packages/npm/XXX/XXX/-/XXX/XXX-X.X.X.tgz: Request failed \"404 Not Found\"".
info If you think this is a bug, please open a bug report with the information provided in "/Users/XXX/gitlab-migration/module-util/yarn-error.log".
info Visit https://classic.yarnpkg.com/en/docs/cli/install for documentation about this command
```
@@ -353,14 +400,14 @@ In this case, try adding this to your `.npmrc` file (and replace `<your_token>`
with your personal access token or deploy token):
```plaintext
-//gitlab.com/api/v4/projects/:_authToken=<your_token>
+//gitlab.example.com/api/v4/projects/:_authToken=<your_token>
```
You can also use `yarn config` instead of `npm config` when setting your auth-token dynamically:
```shell
-yarn config set '//gitlab.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken' "<your_token>"
-yarn config set '//gitlab.com/api/v4/packages/npm/:_authToken' "<your_token>"
+yarn config set '//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken' "<your_token>"
+yarn config set '//gitlab.example.com/api/v4/packages/npm/:_authToken' "<your_token>"
```
### `npm publish` targets default NPM registry (`registry.npmjs.org`)
@@ -375,23 +422,20 @@ should look like:
"name": "@foo/my-package",
"version": "1.0.0",
"description": "Example package for GitLab NPM registry",
- "publishConfig": {
- "@foo:registry":"https://gitlab.com/api/v4/projects/<your_project_id>/packages/npm/"
- }
}
```
And the `.npmrc` file should look like:
```ini
-//gitlab.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken=<your_token>
-//gitlab.com/api/v4/packages/npm/:_authToken=<your_token>
-@foo:registry=https://gitlab.com/api/v4/packages/npm/
+//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken=<your_token>
+//gitlab.example.com/api/v4/packages/npm/:_authToken=<your_token>
+@foo:registry=https://gitlab.example.com/api/v4/packages/npm/
```
### `npm install` returns `Error: Failed to replace env in config: ${NPM_TOKEN}`
-You do not need a token to run `npm install` unless your project is private (the token is only required to publish). If the `.npmrc` file was checked in with a reference to `$NPM_TOKEN`, you can remove it. If you prefer to leave the reference in, you need to set a value prior to running `npm install` or set the value using [GitLab environment variables](./../../../ci/variables/README.md):
+You do not need a token to run `npm install` unless your project is private. The token is only required to publish. If the `.npmrc` file was checked in with a reference to `$NPM_TOKEN`, you can remove it. If you prefer to leave the reference in, you must set a value prior to running `npm install` or set the value by using [GitLab environment variables](../../../ci/variables/README.md):
```shell
NPM_TOKEN=<your_token> npm install
@@ -399,50 +443,11 @@ 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/`
- - Incorrect: `//gitlab.com/api/v4/packages/npm`
-
-## NPM dependencies metadata
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11867) in GitLab Premium 12.6.
-
-Starting from GitLab 12.6, new packages published to the GitLab NPM Registry expose the following attributes to the NPM client:
-
-- name
-- version
-- dist-tags
-- dependencies
- - dependencies
- - devDependencies
- - bundleDependencies
- - peerDependencies
- - deprecated
-
-## NPM distribution tags
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9425) in GitLab Premium 12.8.
-
-You can add [distribution tags](https://docs.npmjs.com/cli/dist-tag) for newly published packages.
-They follow NPM's convention where they are optional, and each tag can only be assigned to one
-package at a time. The `latest` tag is added by default when a package is published without a tag.
-The same applies to installing a package without specifying the tag or version.
-
-Examples of the supported `dist-tag` commands and using tags in general:
-
-```shell
-npm publish @scope/package --tag # Publish new package with new tag
-npm dist-tag add @scope/package@version my-tag # Add a tag to an existing package
-npm dist-tag ls @scope/package # List all tags under the package
-npm dist-tag rm @scope/package@version my-tag # Delete a tag from the package
-npm install @scope/package@my-tag # Install a specific tag
-```
-
-NOTE: **Note:**
-You cannot use your `CI_JOB_TOKEN` or deploy token with the `npm dist-tag` commands. View [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/258835) for details.
+If you get this error, ensure that:
-CAUTION: **Warning:**
-Due to a bug in NPM 6.9.0, deleting dist tags fails. Make sure your NPM version is greater than 6.9.1.
+- Your token is not expired and has appropriate permissions.
+- [Your token does not begin with `-`](https://gitlab.com/gitlab-org/gitlab/-/issues/235473).
+- A package with the same name doesn't already exist within the given scope.
+- The scoped packages URL includes a trailing slash:
+ - Correct: `//gitlab.example.com/api/v4/packages/npm/`
+ - Incorrect: `//gitlab.example.com/api/v4/packages/npm`
diff --git a/doc/user/packages/nuget_repository/img/visual_studio_nuget_source_added.png b/doc/user/packages/nuget_repository/img/visual_studio_nuget_source_added.png
index e4f6068f28c..8c14a14e304 100644
--- a/doc/user/packages/nuget_repository/img/visual_studio_nuget_source_added.png
+++ b/doc/user/packages/nuget_repository/img/visual_studio_nuget_source_added.png
Binary files differ
diff --git a/doc/user/packages/nuget_repository/index.md b/doc/user/packages/nuget_repository/index.md
index 22e1a95649d..2b61c4a6c28 100644
--- a/doc/user/packages/nuget_repository/index.md
+++ b/doc/user/packages/nuget_repository/index.md
@@ -4,34 +4,38 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# GitLab NuGet Repository
+# NuGet packages in the Package Registry
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20050) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.8.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
-With the GitLab NuGet Repository, every project can have its own space to store NuGet packages.
+Publish NuGet packages in your project’s Package Registry. Then, install the
+packages whenever you need to use them as a dependency.
-The GitLab NuGet Repository works with:
+The Package Registry works with:
- [NuGet CLI](https://docs.microsoft.com/en-us/nuget/reference/nuget-exe-cli-reference)
- [.NET Core CLI](https://docs.microsoft.com/en-us/dotnet/core/tools/)
- [Visual Studio](https://visualstudio.microsoft.com/vs/)
-## Setting up your development environment
+## Install NuGet
-[NuGet CLI 5.1 or later](https://www.nuget.org/downloads) is required. Earlier versions have not been tested
-against the GitLab NuGet Repository and might not work. If you have [Visual Studio](https://visualstudio.microsoft.com/vs/),
-NuGet CLI is probably already installed.
+The required minimum versions are:
-Alternatively, you can use [.NET SDK 3.0 or later](https://dotnet.microsoft.com/download/dotnet-core/3.0), which installs NuGet CLI.
+- [NuGet CLI 5.1 or later](https://www.nuget.org/downloads). If you have
+ [Visual Studio](https://visualstudio.microsoft.com/vs/), the NuGet CLI is
+ probably already installed.
+- Alternatively, you can use [.NET SDK 3.0 or later](https://dotnet.microsoft.com/download/dotnet-core/3.0),
+ which installs the NuGet CLI.
+- NuGet protocol version 3 or later.
-You can confirm that [NuGet CLI](https://www.nuget.org/) is properly installed with:
+Verify that the [NuGet CLI](https://www.nuget.org/) is installed by running:
```shell
nuget help
```
-You should see something similar to:
+The output should be similar to:
```plaintext
NuGet Version: 5.1.0.6013
@@ -43,103 +47,98 @@ Available commands:
[output truncated]
```
-NOTE: **Note:**
-GitLab currently only supports NuGet's protocol version 3. Earlier versions are not supported.
+### Install NuGet on macOS
-### macOS support
+For macOS, you can use [Mono](https://www.mono-project.com/) to run the
+NuGet CLI.
-For macOS, you can also use [Mono](https://www.mono-project.com/) to run
-the NuGet CLI. For Homebrew users, run `brew install mono` to install
-Mono. Then you should be able to download the Windows C# binary
-`nuget.exe` from the [NuGet CLI page](https://www.nuget.org/downloads)
-and run:
+1. If you use Homebrew, to install Mono, run `brew install mono`.
+1. Download the Windows C# binary `nuget.exe` from the [NuGet CLI page](https://www.nuget.org/downloads).
+1. Run this command:
-```shell
-mono nuget.exe
-```
-
-## Enabling the NuGet Repository
-
-NOTE: **Note:**
-This option is available only if your GitLab administrator has
-[enabled support for the Package Registry](../../../administration/packages/index.md).
-
-When the NuGet Repository is enabled, it is available for all new projects
-by default. To enable it for existing projects, or if you want to disable it:
-
-1. Navigate to your project's **Settings > General > Visibility, project features, permissions**.
-1. Find the Packages feature and enable or disable it.
-1. Click on **Save changes** for the changes to take effect.
+ ```shell
+ mono nuget.exe
+ ```
-You should then be able to see the **Packages & Registries** section on the left sidebar.
+## Add the Package Registry as a source for NuGet packages
-## Adding the GitLab NuGet Repository as a source to NuGet
+To publish and install packages to the Package Registry, you must add the
+Package Registry as a source for your packages.
-You need the following:
+Prerequisites:
- Your GitLab username.
- A personal access token or deploy token. For repository authentication:
- - You can generate a [personal access token](../../../user/profile/personal_access_tokens.md) with the scope set to `api`.
- - You can generate a [deploy token](./../../project/deploy_tokens/index.md) with the scope set to `read_package_registry`, `write_package_registry`, or both.
-- A suitable name for your source.
-- Your project ID which can be found on the home page of your project.
+ - You can generate a [personal access token](../../../user/profile/personal_access_tokens.md)
+ with the scope set to `api`.
+ - You can generate a [deploy token](../../project/deploy_tokens/index.md)
+ with the scope set to `read_package_registry`, `write_package_registry`, or
+ both.
+- A name for your source.
+- Your project ID, which is found on your project's home page.
You can now add a new source to NuGet with:
-- [NuGet CLI](#add-nuget-repository-source-with-nuget-cli)
-- [Visual Studio](#add-nuget-repository-source-with-visual-studio).
-- [.NET CLI](#add-nuget-repository-source-with-net-cli)
+- [NuGet CLI](#add-a-source-with-the-nuget-cli)
+- [Visual Studio](#add-a-source-with-visual-studio)
+- [.NET CLI](#add-a-source-with-the-net-cli)
-### Add NuGet Repository source with NuGet CLI
+### Add a source with the NuGet CLI
-To add the GitLab NuGet Repository as a source with `nuget`:
+To add the Package Registry as a source with `nuget`:
```shell
-nuget source Add -Name <source_name> -Source "https://gitlab-instance.example.com/api/v4/projects/<your_project_id>/packages/nuget/index.json" -UserName <gitlab_username or deploy_token_username> -Password <gitlab_personal_access_token or deploy_token>
+nuget source Add -Name <source_name> -Source "https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/nuget/index.json" -UserName <gitlab_username or deploy_token_username> -Password <gitlab_personal_access_token or deploy_token>
```
-Where:
-
-- `<source_name>` is your desired source name.
+- `<source_name>` is the desired source name.
For example:
```shell
-nuget source Add -Name "GitLab" -Source "https://gitlab.example/api/v4/projects/10/packages/nuget/index.json" -UserName carol -Password 12345678asdf
+nuget source Add -Name "GitLab" -Source "https://gitlab.example.com/api/v4/projects/10/packages/nuget/index.json" -UserName carol -Password 12345678asdf
```
-### Add NuGet Repository source with Visual Studio
+### Add a source with Visual Studio
+
+To add the Package Registry as a source with Visual Studio:
1. Open [Visual Studio](https://visualstudio.microsoft.com/vs/).
-1. Open the **FILE > OPTIONS** (Windows) or **Visual Studio > Preferences** (Mac OS).
-1. In the **NuGet** section, open **Sources** to see a list of all your NuGet sources.
-1. Click **Add**.
-1. Fill the fields with:
- - **Name**: Desired name for the source
- - **Location**: `https://gitlab.com/api/v4/projects/<your_project_id>/packages/nuget/index.json`
- - Replace `<your_project_id>` with your project ID.
- - If you have a self-managed GitLab installation, replace `gitlab.com` with your domain name.
- - **Username**: Your GitLab username or deploy token username
- - **Password**: Your personal access token or deploy token
+1. In Windows, select **File > Options**. On macOS, select **Visual Studio > Preferences**.
+1. In the **NuGet** section, select **Sources** to view a list of all your NuGet sources.
+1. Select **Add**.
+1. Complete the following fields:
+ - **Name**: Name for the source.
+ - **Location**: `https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/nuget/index.json`,
+ where `<your_project_id>` is your project ID, and `gitlab.example.com` is
+ your domain name.
+ - **Username**: Your GitLab username or deploy token username.
+ - **Password**: Your personal access token or deploy token.
![Visual Studio Adding a NuGet source](img/visual_studio_adding_nuget_source.png)
1. Click **Save**.
- ![Visual Studio NuGet source added](img/visual_studio_nuget_source_added.png)
+The source is displayed in your list.
-In case of any warning, please make sure that the **Location**, **Username**, and **Password** are correct.
+![Visual Studio NuGet source added](img/visual_studio_nuget_source_added.png)
-### Add NuGet Repository source with .NET CLI
+If you get a warning, ensure that the **Location**, **Username**, and
+**Password** are correct.
-To add the GitLab NuGet Repository as a source for .NET, create a file named `nuget.config` in the root of your project with the following content:
+### Add a source with the .NET CLI
-```xml
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
+To add the Package Registry as a source for .NET:
+
+1. In the root of your project, create a file named `nuget.config`.
+1. Add this content:
+
+ ```xml
+ <?xml version="1.0" encoding="utf-8"?>
+ <configuration>
<packageSources>
<clear />
- <add key="gitlab" value="https://gitlab-instance.example.com/api/v4/projects/<your_project_id>/packages/nuget/index.json" />
+ <add key="gitlab" value="https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/nuget/index.json" />
</packageSources>
<packageSourceCredentials>
<gitlab>
@@ -147,46 +146,51 @@ To add the GitLab NuGet Repository as a source for .NET, create a file named `nu
<add key="ClearTextPassword" value="<gitlab_personal_access_token or deploy_token>" />
</gitlab>
</packageSourceCredentials>
-</configuration>
-```
+ </configuration>
+ ```
+
+## Publish a NuGet package
-## Uploading packages
+When publishing packages:
-When uploading packages, note that:
+- The Package Registry on GitLab.com can store up to 500 MB of content.
+ This limit is [configurable for self-managed GitLab instances](../../../administration/instance_limits.md#package-registry-limits).
+- If you publish the same package with the same version multiple times, each
+ consecutive upload is saved as a separate file. When installing a package,
+ GitLab serves the most recent file.
+- When publishing packages to GitLab, they aren't displayed in the packages user
+ interface of your project immediately. It can take up to 10 minutes to process
+ a package.
-- The Package Registry on GitLab.com can store up to 500 MB of content. This limit is [configurable for self-managed GitLab instances](../../../administration/instance_limits.md#package-registry-limits).
-- 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.
-- When uploading packages to GitLab, they are not displayed in the packages UI of your project
- immediately. It can take up to 10 minutes to process a package.
+### Publish a package with the NuGet CLI
-### Upload packages with NuGet CLI
+Prerequisite:
-This section assumes that your project is properly built and you already [created a NuGet package with NuGet CLI](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package).
-Upload your package using the following command:
+- [A NuGet package created with NuGet CLI](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package).
+
+Publish a package by running this command:
```shell
nuget push <package_file> -Source <source_name>
```
-Where:
-
- `<package_file>` is your package filename, ending in `.nupkg`.
-- `<source_name>` is the [source name used during setup](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget).
+- `<source_name>` is the [source name used during setup](#add-a-source-with-the-nuget-cli).
+
+### Publish a package with the .NET CLI
+
+Prerequisite:
-### Upload packages with .NET CLI
+[A NuGet package created with .NET CLI](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package-dotnet-cli).
-This section assumes that your project is properly built and you already [created a NuGet package with .NET CLI](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package-dotnet-cli).
-Upload your package using the following command:
+Publish a package by running this command:
```shell
dotnet nuget push <package_file> --source <source_name>
```
-Where:
-
- `<package_file>` is your package filename, ending in `.nupkg`.
-- `<source_name>` is the [source name used during setup](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget).
+- `<source_name>` is the [source name used during setup](#add-a-source-with-the-net-cli).
For example:
@@ -194,16 +198,47 @@ For example:
dotnet nuget push MyPackage.1.0.0.nupkg --source gitlab
```
+### Publish a NuGet package by using CI/CD
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36424) in GitLab 13.3.
+
+If you’re using NuGet with GitLab CI/CD, a CI job token can be used instead of a
+personal access token or deploy token. The token inherits the permissions of the
+user that generates the pipeline.
+
+This example shows how to create a new package each time the `master` branch is
+updated:
+
+1. Add a `deploy` job to your `.gitlab-ci.yml` file:
+
+ ```yaml
+ image: mcr.microsoft.com/dotnet/core/sdk:3.1
+
+ stages:
+ - deploy
+
+ deploy:
+ stage: deploy
+ script:
+ - dotnet pack -c Release
+ - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
+ - dotnet nuget push "bin/Release/*.nupkg" --source gitlab
+ only:
+ - master
+ ```
+
+1. Commit the changes and push it to your GitLab repository to trigger a new CI/CD build.
+
## Install packages
-### Install a package with NuGet CLI
+### Install a package with the NuGet CLI
CAUTION: **Warning:**
-By default, `nuget` checks the official source at `nuget.org` first. If you have a package in the
-GitLab NuGet Repository with the same name as a package at `nuget.org`, you must specify the source
-name to install the correct package.
+By default, `nuget` checks the official source at `nuget.org` first. If you have
+a NuGet package in the Package Registry with the same name as a package at
+`nuget.org`, you must specify the source name to install the correct package.
-Install the latest version of a package using the following command:
+Install the latest version of a package by running this command:
```shell
nuget install <package_id> -OutputDirectory <output_directory> \
@@ -211,60 +246,24 @@ nuget install <package_id> -OutputDirectory <output_directory> \
-Source <source_name>
```
-Where:
-
- `<package_id>` is the package ID.
- `<output_directory>` is the output directory, where the package is installed.
-- `<package_version>` (Optional) is the package version.
-- `<source_name>` (Optional) is the source name.
+- `<package_version>` The package version. Optional.
+- `<source_name>` The source name. Optional.
-### Install a package with .NET CLI
+### Install a package with the .NET CLI
CAUTION: **Warning:**
-If you have a package in the GitLab NuGet Repository with the same name as a package at a different source,
-you should verify the order in which `dotnet` checks sources during install. This is defined in the
-`nuget.config` file.
+If you have a package in the Package Registry with the same name as a package at
+a different source, verify the order in which `dotnet` checks sources during
+install. This is defined in the `nuget.config` file.
-Install the latest version of a package using the following command:
+Install the latest version of a package by running this command:
```shell
dotnet add package <package_id> \
-v <package_version>
```
-Where:
-
- `<package_id>` is the package ID.
-- `<package_version>` (Optional) is the package version.
-
-## Publishing a NuGet package with CI/CD
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36424) in GitLab 13.3.
-
-If you’re using NuGet with GitLab CI/CD, a CI job token can be used instead of a personal access token or deploy token.
-The token inherits the permissions of the user that generates the pipeline.
-
-This example shows how to create a new package each time the `master` branch
-is updated:
-
-1. Add a `deploy` job to your `.gitlab-ci.yml` file:
-
- ```yaml
- image: mcr.microsoft.com/dotnet/core/sdk:3.1
-
- stages:
- - deploy
-
- deploy:
- stage: deploy
- script:
- - dotnet restore -p:Configuration=Release
- - dotnet build -c Release
- - dotnet pack -c Release
- - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
- - dotnet nuget push "bin/Release/*.nupkg" --source gitlab
- only:
- - master
- ```
-
-1. Commit the changes and push it to your GitLab repository to trigger a new CI build.
+- `<package_version>` is the package version. Optional.
diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md
index ae9ca5b2333..56fd4a02ba0 100644
--- a/doc/user/packages/package_registry/index.md
+++ b/doc/user/packages/package_registry/index.md
@@ -31,23 +31,30 @@ 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), [Composer packages](../composer_repository/index.md#publish-a-composer-package-by-using-cicd), [NuGet Packages](../nuget_repository/index.md#publishing-a-nuget-package-with-cicd), [Conan Packages](../conan_repository/index.md#publish-a-conan-package-by-using-cicd), [PyPI packages](../pypi_repository/index.md#using-gitlab-ci-with-pypi-packages), and [generic packages](../generic_packages/index.md#publish-a-generic-package-by-using-cicd).
+Learn more about using CI/CD to build:
-If you use CI/CD to build a package, extended activity
-information is displayed when you view the package details:
+- [Maven packages](../maven_repository/index.md#create-maven-packages-with-gitlab-cicd)
+- [NPM packages](../npm_registry/index.md#publish-an-npm-package-by-using-cicd)
+- [Composer packages](../composer_repository/index.md#publish-a-composer-package-by-using-cicd)
+- [NuGet packages](../nuget_repository/index.md#publish-a-nuget-package-by-using-cicd)
+- [Conan packages](../conan_repository/index.md#publish-a-conan-package-by-using-cicd)
+- [Generic packages](../generic_packages/index.md#publish-a-generic-package-by-using-cicd)
+
+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)
-When using Maven and NPM, you can view which pipeline published the package, as well as the commit and
-user who triggered it.
+When using Maven and NPM, you can view which pipeline published the package, and
+the commit and user who triggered it.
## Download a package
To download a package:
1. Go to **Packages & Registries > Package Registry**.
-1. Click the name of the package you want to download.
-1. In the **Activity** section, click the name of the package you want to download.
+1. Select the name of the package you want to download.
+1. In the **Activity** section, select the name of the package you want to download.
## Delete a package
diff --git a/doc/user/packages/pypi_repository/index.md b/doc/user/packages/pypi_repository/index.md
index 33c37ee6a6c..83b29d5f53a 100644
--- a/doc/user/packages/pypi_repository/index.md
+++ b/doc/user/packages/pypi_repository/index.md
@@ -4,89 +4,83 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# GitLab PyPI Repository
+# PyPI packages in the Package Registry
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208747) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
-With the GitLab PyPI Repository, every project can have its own space to store PyPI packages.
+Publish PyPI packages in your project’s Package Registry. Then install the
+packages whenever you need to use them as a dependency.
-The GitLab PyPI Repository works with:
+The Package Registry works with:
- [pip](https://pypi.org/project/pip/)
- [twine](https://pypi.org/project/twine/)
-## Setting up your development environment
+## Build a PyPI package
-You need a recent version of [pip](https://pypi.org/project/pip/) and [twine](https://pypi.org/project/twine/).
+This section explains how to create a PyPI package.
-## Enabling the PyPI Repository
+If you already use PyPI and know how to build your own packages, go to the
+[next section](#authenticate-with-the-package-registry).
-NOTE: **Note:**
-This option is available only if your GitLab administrator has
-[enabled support for the Package Registry](../../../administration/packages/index.md).
+### Install pip and twine
-After the PyPI Repository is enabled, it is available for all new projects
-by default. To enable it for existing projects, or if you want to disable it:
+Install a recent version of [pip](https://pypi.org/project/pip/) and
+[twine](https://pypi.org/project/twine/).
-1. Navigate to your project's **Settings > General > Visibility, project features, permissions**.
-1. Find the Packages feature and enable or disable it.
-1. Click on **Save changes** for the changes to take effect.
+### Create a project
-You should then be able to see the **Packages & Registries** section on the left sidebar.
+Create a test project.
-## Getting started
+1. Open your terminal.
+1. Create a directory called `MyPyPiPackage`, and then go to that directory:
-This section covers creating a new example PyPI package to upload. This is a
-quickstart to test out the **GitLab PyPI Registry**. If you already understand how
-to build and publish your own packages, move on to the [next section](#adding-the-gitlab-pypi-repository-as-a-source).
+ ```shell
+ mkdir MyPyPiPackage && cd MyPyPiPackage
+ ```
-### Create a project
+1. Create another directory and go to it:
-Understanding how to create a full Python project is outside the scope of this
-guide, but you can create a small package to test out the registry. Start by
-creating a new directory called `MyPyPiPackage`:
+ ```shell
+ mkdir mypypipackage && cd mypypipackage
+ ```
-```shell
-mkdir MyPyPiPackage && cd MyPyPiPackage
-```
+1. Create the required files in this directory:
-After creating this, create another directory inside:
+ ```shell
+ touch __init__.py
+ touch greet.py
+ ```
-```shell
-mkdir mypypipackage && cd mypypipackage
-```
+1. Open the `greet.py` file, and then add:
-Create two new files inside this directory to set up the basic project:
+ ```python
+ def SayHello():
+ print("Hello from MyPyPiPackage")
+ return
+ ```
-```shell
-touch __init__.py
-touch greet.py
-```
+1. Open the `__init__.py` file, and then add:
-Inside `greet.py`, add the following code:
+ ```python
+ from .greet import SayHello
+ ```
-```python
-def SayHello():
- print("Hello from MyPyPiPackage")
- return
-```
+1. To test the code, in your `MyPyPiPackage` directory, start the Python prompt.
-Inside the `__init__.py` file, add the following:
+ ```shell
+ python
+ ```
-```python
-from .greet import SayHello
-```
+1. Run this command:
-Now that the basics of our project is completed, we can test that the code runs.
-Start the Python prompt inside your top `MyPyPiPackage` directory. Then run:
+ ```python
+ >>> from mypypipackage import SayHello
+ >>> SayHello()
+ ```
-```python
->>> from mypypipackage import SayHello
->>> SayHello()
-```
-
-You should see an output similar to the following:
+A message indicates that the project was set up successfully:
```plaintext
Python 3.8.2 (v3.8.2:7b3ab5921f, Feb 24 2020, 17:52:18)
@@ -97,80 +91,81 @@ Type "help", "copyright", "credits" or "license" for more information.
Hello from MyPyPiPackage
```
-Once we've verified that the sample project is working as above, we can next
-work on creating a package.
-
### Create a package
-Inside your `MyPyPiPackage` directory, we need to create a `setup.py` file. Run
-the following:
+After you create a project, you can create a package.
-```shell
-touch setup.py
-```
+1. In your terminal, go to the `MyPyPiPackage` directory.
+1. Create a `setup.py` file:
-This file contains all the information about our package. For more information
-about this file, see [creating setup.py](https://packaging.python.org/tutorials/packaging-projects/#creating-setup-py).
-GitLab identifies packages based on
-[Python normalized names (PEP-503)](https://www.python.org/dev/peps/pep-0503/#normalized-names),
-so ensure your package name meets these requirements.
-See the [installation section](#install-packages) for more details.
-
-For this guide, we don't need to extensively fill out this file, simply add the
-below to your `setup.py`:
-
-```python
-import setuptools
-
-setuptools.setup(
- name="mypypipackage",
- version="0.0.1",
- author="Example Author",
- author_email="author@example.com",
- description="A small example package",
- packages=setuptools.find_packages(),
- classifiers=[
- "Programming Language :: Python :: 3",
- "License :: OSI Approved :: MIT License",
- "Operating System :: OS Independent",
- ],
- python_requires='>=3.6',
-)
-```
+ ```shell
+ touch setup.py
+ ```
-Save the file, then execute the setup like so:
+ This file contains all the information about the package. For more information
+ about this file, see [creating setup.py](https://packaging.python.org/tutorials/packaging-projects/#creating-setup-py).
+ Because GitLab identifies packages based on
+ [Python normalized names (PEP-503)](https://www.python.org/dev/peps/pep-0503/#normalized-names),
+ ensure your package name meets these requirements. See the [installation section](#authenticate-with-a-ci-job-token)
+ for details.
-```shell
-python3 setup.py sdist bdist_wheel
-```
+1. Open the `setup.py` file, and then add basic information:
+
+ ```python
+ import setuptools
-If successful, you should be able to see the output in a newly created `dist`
-folder. Run:
+ setuptools.setup(
+ name="mypypipackage",
+ version="0.0.1",
+ author="Example Author",
+ author_email="author@example.com",
+ description="A small example package",
+ packages=setuptools.find_packages(),
+ classifiers=[
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+ ],
+ python_requires='>=3.6',
+ )
+ ```
+
+1. Save the file.
+1. Execute the setup:
+
+ ```shell
+ python3 setup.py sdist bdist_wheel
+ ```
+
+The output should be visible in a newly-created `dist` folder:
```shell
ls dist
```
-And confirm your output matches the below:
+The output should appear similar to the following:
```plaintext
mypypipackage-0.0.1-py3-none-any.whl mypypipackage-0.0.1.tar.gz
```
-Our package is now all set up and ready to be uploaded to the **GitLab PyPI
-Package Registry**. Before we do so, we next need to set up authentication.
+The package is now ready to be published to the Package Registry.
-## Adding the GitLab PyPI Repository as a source
+## Authenticate with the Package Registry
-### Authenticating with a personal access token
+Before you can publish to the Package Registry, you must authenticate.
-You need the following:
+To do this, you can use:
-- 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 suitable name for your source.
-- Your project ID which can be found on the home page of your project.
+- A [personal access token](../../../user/profile/personal_access_tokens.md)
+ with the scope set to `api`.
+- A [deploy token](../../project/deploy_tokens/index.md) with the scope set to
+ `read_package_registry`, `write_package_registry`, or both.
+- A [CI job token](#authenticate-with-a-ci-job-token).
-Edit your `~/.pypirc` file and add the following:
+### Authenticate with a personal access token
+
+To authenticate with a personal access token, edit the `~/.pypirc` file and add:
```ini
[distutils]
@@ -178,20 +173,17 @@ index-servers =
gitlab
[gitlab]
-repository = https://gitlab.com/api/v4/projects/<project_id>/packages/pypi
+repository = https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi
username = __token__
password = <your personal access token>
```
-### Authenticating with a deploy token
-
-You need the following:
+- `username` must be `__token__` exactly.
+- Your project ID is on your project's home page.
-- A deploy token. You can generate a [deploy token](./../../project/deploy_tokens/index.md) with the `read_package_registry` and/or `write_package_registry` scopes for repository authentication.
-- A suitable name for your source.
-- Your project ID which can be found on the home page of your project.
+### Authenticate with a deploy token
-Edit your `~/.pypirc` file and add the following:
+To authenticate with a deploy token, edit your `~/.pypirc` file and add:
```ini
[distutils]
@@ -199,21 +191,58 @@ index-servers =
gitlab
[gitlab]
-repository = https://gitlab.com/api/v4/projects/<project_id>/packages/pypi
+repository = https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi
username = <deploy token username>
password = <deploy token>
```
-## Uploading packages
+Your project ID is on your project's home page.
-When uploading packages, note that:
+### Authenticate with a CI job token
-- The maximum allowed size is 50 Megabytes.
-- 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`.
+> [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` instead of a personal access token or deploy token.
+
+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.example.com/api/v4/projects/${CI_PROJECT_ID}/packages/pypi dist/*
+```
+
+You can also use `CI_JOB_TOKEN` in a `~/.pypirc` file that you check in to
+GitLab:
+
+```ini
+[distutils]
+index-servers =
+ gitlab
+
+[gitlab]
+repository = https://gitlab.example.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/pypi
+username = gitlab-ci-token
+password = ${env.CI_JOB_TOKEN}
+```
+
+## Publish a PyPI package
+
+When publishing packages, note that:
+
+- The maximum allowed size is 50 MB.
+- You can't upload the same version of a package multiple times. If you try,
+ you'll 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.
+If your version string (for example, `0.0.1`) isn't valid, it will be rejected.
+GitLab uses the following regex to validate the version string.
```ruby
\A(?:
@@ -227,118 +256,86 @@ If your version string (for example, `0.0.1`) is invalid, it will be rejected. G
)\z}xi
```
-You can play around with the regex and try your version strings on [this regular expression editor](https://rubular.com/r/FKM6d07ouoDaFV).
+You can experiment with the regex and try your version strings by using 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))
+For more details about the regex, review this [documentation](https://www.python.org/dev/peps/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions).
-### Upload packages with Twine
+### Publish a PyPI package by using twine
-If you were following the guide above, then the `MyPyPiPackage` package should
-be ready to be uploaded. Run the following command:
+To publish a PyPI package, run a command like:
```shell
python3 -m twine upload --repository gitlab dist/*
```
-If successful, you should see the following:
+This message indicates that the package was published successfully:
```plaintext
-Uploading distributions to https://gitlab.com/api/v4/projects/<your_project_id>/packages/pypi
+Uploading distributions to https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/pypi
Uploading mypypipackage-0.0.1-py3-none-any.whl
100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.58k/4.58k [00:00<00:00, 10.9kB/s]
Uploading mypypipackage-0.0.1.tar.gz
100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.24k/4.24k [00:00<00:00, 11.0kB/s]
```
-This indicates that the package was uploaded successfully. You can then navigate
-to your project's **Packages & Registries** page and see the uploaded packages.
+To view the published package, go to your project's **Packages & Registries**
+page.
-If you would rather not use a `.pypirc` file to define your repository source,
-you can upload to the repository with the authentication inline:
+If you didn't use a `.pypirc` file to define your repository source, you can
+publish 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/*
+TWINE_PASSWORD=<personal_access_token or deploy_token> TWINE_USERNAME=<username or deploy_token_username> python3 -m twine upload --repository-url https://gitlab.example.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/).
+If you didn't follow the steps on this page, ensure your package was properly
+built, and that you [created a PyPI package with `setuptools`](https://packaging.python.org/tutorials/packaging-projects/).
-You can then upload your package using the following command:
+You can then upload your package by using the following command:
```shell
python -m twine upload --repository <source_name> dist/<package_file>
```
-Where:
-
- `<package_file>` is your package filename, ending in `.tar.gz` or `.whl`.
-- `<source_name>` is the [source name used during setup](#adding-the-gitlab-pypi-repository-as-a-source).
+- `<source_name>` is the [source name used during setup](#authenticate-with-the-package-registry).
-## Install packages
+## Install a PyPI package
-Install the latest version of a package using the following command:
+To install the latest version of a package, use the following command:
```shell
-pip install --extra-index-url https://__token__:<personal_access_token>@gitlab.com/api/v4/projects/<project_id>/packages/pypi/simple --no-deps <package_name>
+pip install --extra-index-url https://__token__:<personal_access_token>@gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple --no-deps <package_name>
```
-Where:
-
- `<package_name>` is the package name.
- `<personal_access_token>` is a personal access token with the `read_api` scope.
- `<project_id>` is the project ID.
-If you were following the guide above and want to test installing the
-`MyPyPiPackage` package, you can run the following:
+If you were following the guide and want to install the
+`MyPyPiPackage` package, you can run:
```shell
-pip install mypypipackage --no-deps --extra-index-url https://__token__:<personal_access_token>@gitlab.com/api/v4/projects/<your_project_id>/packages/pypi/simple
+pip install mypypipackage --no-deps --extra-index-url https://__token__:<personal_access_token>@gitlab.example.com/api/v4/projects/<your_project_id>/packages/pypi/simple
```
-This should result in the following:
+This message indicates that the package was installed successfully:
```plaintext
-Looking in indexes: https://__token__:****@gitlab.com/api/v4/projects/<your_project_id>/packages/pypi/simple
+Looking in indexes: https://__token__:****@gitlab.example.com/api/v4/projects/<your_project_id>/packages/pypi/simple
Collecting mypypipackage
- Downloading https://gitlab.com/api/v4/projects/<your_project_id>/packages/pypi/files/d53334205552a355fee8ca35a164512ef7334f33d309e60240d57073ee4386e6/mypypipackage-0.0.1-py3-none-any.whl (1.6 kB)
+ Downloading https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/pypi/files/d53334205552a355fee8ca35a164512ef7334f33d309e60240d57073ee4386e6/mypypipackage-0.0.1-py3-none-any.whl (1.6 kB)
Installing collected packages: mypypipackage
Successfully installed mypypipackage-0.0.1
```
-GitLab looks for packages using
-[Python normalized names (PEP-503)](https://www.python.org/dev/peps/pep-0503/#normalized-names),
-so the characters `-`, `_`, and `.` are all treated the same and repeated characters are removed.
-A `pip install` request for `my.package` looks for packages that match any of
-the three characters, such as `my-package`, `my_package`, and `my....package`.
-
-## Using GitLab CI with PyPI packages
+### Package names
-> [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.
+GitLab looks for packages that use
+[Python normalized names (PEP-503)](https://www.python.org/dev/peps/pep-0503/#normalized-names).
+The characters `-`, `_`, and `.` are all treated the same, and repeated
+characters are removed.
-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}
-```
+A `pip install` request for `my.package` looks for packages that match any of
+the three characters, such as `my-package`, `my_package`, and `my....package`.
diff --git a/doc/user/packages/workflows/monorepo.md b/doc/user/packages/workflows/monorepo.md
index f20f3427ac5..1e375dffe7e 100644
--- a/doc/user/packages/workflows/monorepo.md
+++ b/doc/user/packages/workflows/monorepo.md
@@ -68,7 +68,7 @@ package is to be uploaded to. If you set this to any project that you have
access to and update any other configuration similarly depending on the package type,
your packages are published to that project. This means you can publish
multiple packages to one project, even if their code does not exist in the same
-place. See the [project registry workflow documentation](./project_registry.md)
+place. See the [project registry workflow documentation](project_registry.md)
for more details.
## CI workflows for automating packaging
diff --git a/doc/user/packages/workflows/project_registry.md b/doc/user/packages/workflows/project_registry.md
index 24437e6dfac..a8972f05acd 100644
--- a/doc/user/packages/workflows/project_registry.md
+++ b/doc/user/packages/workflows/project_registry.md
@@ -67,16 +67,16 @@ If you are using NPM, this involves creating an `.npmrc` file and adding the app
to your project using your project ID, then adding a section to your `package.json` file with a similar URL.
Follow
-the instructions in the [GitLab NPM Registry documentation](../npm_registry/index.md#authenticating-to-the-gitlab-npm-registry). After
+the instructions in the [GitLab NPM Registry documentation](../npm_registry/index.md#authenticate-to-the-package-registry). After
you do this, you can push your NPM package to your project using `npm publish`, as described in the
-[uploading packages](../npm_registry/index.md#uploading-packages) section of the docs.
+[publishing packages](../npm_registry/index.md#publish-an-npm-package) section of the docs.
#### Maven
If you are using Maven, this involves updating your `pom.xml` file with distribution sections, including the
appropriate URL for your project, as described in the [GitLab Maven Repository documentation](../maven_repository/index.md#project-level-maven-endpoint).
-Then, you need to add a `settings.xml` file and [include your access token](../maven_repository/index.md#authenticate-with-a-personal-access-token).
-Now you can [deploy Maven packages](../maven_repository/index.md#uploading-packages) to your project.
+Then, you need to add a `settings.xml` file and [include your access token](../maven_repository/index.md#authenticate-with-a-personal-access-token-in-maven).
+Now you can [deploy Maven packages](../maven_repository/index.md#publish-a-package) to your project.
#### Conan
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 2e9f36360c6..f1365ee1cab 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -163,7 +163,7 @@ The following table depicts the various user permission levels in a project.
| Delete wiki pages | | | | ✓ | ✓ |
| View project Audit Events | | | | ✓ | ✓ |
| Manage [push rules](../push_rules/push_rules.md) | | | | ✓ | ✓ |
-| Manage [project access tokens](./project/settings/project_access_tokens.md) **(CORE ONLY)** | | | | ✓ | ✓ |
+| Manage [project access tokens](project/settings/project_access_tokens.md) **(CORE ONLY)** | | | | ✓ | ✓ |
| Switch visibility level | | | | | ✓ |
| Transfer project to another namespace | | | | | ✓ |
| Rename project | | | | | ✓ |
@@ -180,11 +180,11 @@ The following table depicts the various user permission levels in a project.
1. Guest users are able to perform this action on public and internal projects, but not private projects. This doesn't apply to [external users](#external-users) where explicit access must be given even if the project is internal.
1. Guest users can only view the confidential issues they created themselves.
1. If **Public pipelines** is enabled in **Project Settings > CI/CD**.
-1. Not allowed for Guest, Reporter, Developer, Maintainer, or Owner. See [Protected Branches](./project/protected_branches.md).
-1. If the [branch is protected](./project/protected_branches.md#using-the-allowed-to-merge-and-allowed-to-push-settings), this depends on the access Developers and Maintainers are given.
+1. Not allowed for Guest, Reporter, Developer, Maintainer, or Owner. See [Protected Branches](project/protected_branches.md).
+1. If the [branch is protected](project/protected_branches.md#using-the-allowed-to-merge-and-allowed-to-push-settings), this depends on the access Developers and Maintainers are given.
1. Guest users can access GitLab [**Releases**](project/releases/index.md) for downloading assets but are not allowed to download the source code nor see repository information like tags and commits.
1. Actions are limited only to records owned (referenced) by user.
-1. When [Share Group Lock](./group/index.md#share-with-group-lock) is enabled the project can't be shared with other groups. It does not affect group with group sharing.
+1. When [Share Group Lock](group/index.md#share-with-group-lock) is enabled the project can't be shared with other groups. It does not affect group with group sharing.
1. For information on eligible approvers for merge requests, see
[Eligible approvers](project/merge_requests/merge_request_approvals.md#eligible-approvers).
1. Owner permission is only available at the group or personal namespace level (and for instance admins) and is inherited by its projects.
@@ -256,7 +256,7 @@ group.
| Share (invite) groups with groups | | | | | ✓ |
| Create/edit/delete group milestones | | | ✓ | ✓ | ✓ |
| Create/edit/delete iterations | | | ✓ | ✓ | ✓ |
-| Enable/disable a dependency proxy **(PREMIUM)** | | | ✓ | ✓ | ✓ |
+| Enable/disable a dependency proxy | | | ✓ | ✓ | ✓ |
| Create and edit group wiki pages **(PREMIUM)** | | | ✓ | ✓ | ✓ |
| Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
| Create/edit/delete metrics dashboard annotations | | | ✓ | ✓ | ✓ |
@@ -314,6 +314,10 @@ External users:
- Can only access public projects and projects to which they are explicitly granted access,
thus hiding all other internal or private ones from them (like being
logged out).
+- Can only access public groups and groups to which they are explicitly granted access,
+ thus hiding all other internal or private ones from them (like being
+ logged out).
+- Can only access public snippets.
Access can be granted by adding the user as member to the project or group.
Like usual users, they receive a role in the project or group with all
@@ -391,7 +395,7 @@ with the permissions described on the documentation on [auditor users permission
[Read more about Auditor users.](../administration/auditor_users.md)
-## Users with minimal access **(PREMIUM ONLY)**
+## Users with minimal access **(PREMIUM)**
>[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40942) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
@@ -432,7 +436,7 @@ instance and project. In addition, all admins can use the admin interface under
|---------------------------------------|-----------------|-------------|----------|--------|
| See commits and jobs | ✓ | ✓ | ✓ | ✓ |
| Retry or cancel job | | ✓ | ✓ | ✓ |
-| Erase job artifacts and trace | | ✓ (*1*) | ✓ | ✓ |
+| Erase job artifacts and job logs | | ✓ (*1*) | ✓ | ✓ |
| Delete project | | | ✓ | ✓ |
| Create project | | | ✓ | ✓ |
| Change project configuration | | | ✓ | ✓ |
diff --git a/doc/user/profile/account/create_accounts.md b/doc/user/profile/account/create_accounts.md
index 09bfa7afc9e..cf5e4591a50 100644
--- a/doc/user/profile/account/create_accounts.md
+++ b/doc/user/profile/account/create_accounts.md
@@ -14,9 +14,9 @@ You can create users:
## Create users on sign in page
-If you have [sign-up enabled](../../admin_area/settings/sign_up_restrictions.md), users can create their own accounts using the **Register** tab on the sign in page.
+If you have [sign-up enabled](../../admin_area/settings/sign_up_restrictions.md), users can create their own accounts by selecting "Register now" on the sign-in page, or navigate to `https://gitlab.example.com/users/sign_up`.
-![Register Tab](img/register_tab.png)
+![Register Tab](img/register_v13_6.png)
## Create users in Admin Area
diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
index a70d11438f4..637d740ab0f 100644
--- a/doc/user/profile/account/delete_account.md
+++ b/doc/user/profile/account/delete_account.md
@@ -35,7 +35,7 @@ As an administrator, you can delete a user account by:
- **Delete user and contributions** to delete the user and
their associated records.
-DANGER: **Danger:**
+DANGER: **Warning:**
Using the **Delete user and contributions** option may result
in removing more data than intended. Please see [associated records](#associated-records)
below for additional details.
diff --git a/doc/user/profile/account/img/register_tab.png b/doc/user/profile/account/img/register_tab.png
deleted file mode 100644
index 4bbb4e62687..00000000000
--- a/doc/user/profile/account/img/register_tab.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/profile/account/img/register_v13_6.png b/doc/user/profile/account/img/register_v13_6.png
new file mode 100644
index 00000000000..ce4adc0f55b
--- /dev/null
+++ b/doc/user/profile/account/img/register_v13_6.png
Binary files differ
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index 0e645e1b4a3..dacb6c3a5a7 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -8,12 +8,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Two-factor authentication
Two-factor authentication (2FA) provides an additional level of security to your
-GitLab account. Once enabled, in addition to supplying your username and
-password to login, you'll be prompted for a code generated by your one time password
-authenticator. For example, a password manager on one of your devices.
+GitLab account. After being enabled, in addition to supplying your username and
+password to sign in, you'll be prompted for a code generated by your one-time
+password authenticator (for example, a password manager on one of your devices).
-By enabling 2FA, the only way someone other than you can log into your account
-is to know your username and password *and* have access to your one time password secret.
+By enabling 2FA, the only way someone other than you can sign in to your account
+is to know your username and password _and_ have access to your one-time
+password secret.
## Overview
@@ -21,30 +22,30 @@ TIP: **Tip:**
When you enable 2FA, don't forget to back up your [recovery codes](#recovery-codes)!
In addition to time-based one time passwords (TOTP), GitLab supports U2F
-(universal 2nd factor) devices as the second factor of authentication. Once
+(universal 2nd factor) and WebAuthn (experimental) devices as the second factor of authentication. Once
enabled, in addition to supplying your username and password to log in, you'll
-be prompted to activate your U2F device (usually by pressing a button on it),
+be prompted to activate your U2F / WebAuthn device (usually by pressing a button on it),
and it will perform secure authentication on your behalf.
It is highly recommended that you set up 2FA with both a
-[one-time password authenticator](#enable-2fa-via-one-time-password-authenticator)
-and a [U2F device](#enable-2fa-via-u2f-device), so you can still access your account
-if you lose your U2F device.
+[one-time password authenticator](#one-time-password) or use [FortiAuthenticator](#one-time-password-via-fortiauthenticator)
+and a [U2F device](#u2f-device) or a [WebAuthn device](#webauthn-device), so you can still access your account
+if you lose your U2F / WebAuthn device.
## Enabling 2FA
-There are two ways to enable two-factor authentication: via a one time password authenticator
-or a U2F device.
+There are multiple ways to enable two-factor authentication: via a one time password authenticator
+or a U2F / WebAuthn device.
-### Enable 2FA via one time password authenticator
+### One-time password
To enable 2FA:
1. **In GitLab:**
- 1. Log in to your GitLab account.
+ 1. Sign in to your GitLab account.
1. Go to your [**Profile settings**](../index.md#profile-settings).
1. Go to **Account**.
- 1. Click **Enable Two-factor Authentication**.
+ 1. Select **Enable Two-factor Authentication**.
1. **On your device (usually your phone):**
1. Install a compatible application, like:
- [Authenticator](https://mattrubin.me/authenticator/): open source app for iOS devices.
@@ -59,14 +60,88 @@ To enable 2FA:
1. **In GitLab:**
1. Enter the six-digit pin number from the entry on your device into the **Pin
code** field.
- 1. Click **Submit**.
+ 1. Select **Submit**.
If the pin you entered was correct, you'll see a message indicating that
two-factor authentication has been enabled, and you'll be presented with a list
-of [recovery codes](#recovery-codes). Make sure you download them and keep them
+of [recovery codes](#recovery-codes). Be sure to download them and keep them
in a safe place.
-### Enable 2FA via U2F device
+### One-time password via FortiAuthenticator
+
+> - Introduced in [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/212312)
+> - 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](#enable-fortiauthenticator-integration).
+
+You can use FortiAuthenticator as an OTP provider in GitLab. Users must exist in
+both FortiAuthenticator and GitLab with the exact same username, and users must
+have FortiToken configured in FortiAuthenticator.
+
+You'll also need a username and access token for FortiAuthenticator. The
+`access_token` in the code samples shown below is the FortAuthenticator access
+key. To get the token, see the `REST API Solution Guide` at
+[`Fortinet Document Library`](https://docs.fortinet.com/document/fortiauthenticator/6.2.0/rest-api-solution-guide/158294/the-fortiauthenticator-api).
+GitLab 13.5 has been tested with FortAuthenticator version 6.2.0.
+
+First configure FortiAuthenticator in GitLab. On your GitLab server:
+
+1. Open the configuration file.
+
+ For Omnibus GitLab:
+
+ ```shell
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ For installations from source:
+
+ ```shell
+ cd /home/git/gitlab
+ sudo -u git -H editor config/gitlab.yml
+ ```
+
+1. Add the provider configuration:
+
+ For Omnibus package:
+
+ ```ruby
+ gitlab_rails['forti_authenticator_enabled'] = true
+ gitlab_rails['forti_authenticator_host'] = 'forti_authenticator.example.com'
+ gitlab_rails['forti_authenticator_port'] = 443
+ gitlab_rails['forti_authenticator_username'] = '<some_username>'
+ gitlab_rails['forti_authenticator_access_token'] = 's3cr3t'
+ ```
+
+ For installations from source:
+
+ ```yaml
+ forti_authenticator:
+ enabled: true
+ host: forti_authenticator.example.com
+ port: 443
+ username: <some_username>
+ access_token: s3cr3t
+ ```
+
+1. Save the configuration file.
+1. [Reconfigure](../../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
+ or [restart GitLab](../../../administration/restart_gitlab.md#installations-from-source)
+ for the changes to take effect if you installed GitLab via Omnibus or from
+ source respectively.
+
+#### Enable FortiAuthenticator integration
+
+This feature comes with the `:forti_authenticator` 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(:forti_authenticator, User.find(<user ID>))
+```
+
+### U2F device
> Introduced in [GitLab 8.9](https://about.gitlab.com/blog/2016/06/22/gitlab-adds-support-for-u2f/).
@@ -100,10 +175,46 @@ To set up 2FA with a U2F device:
You will see a message indicating that your device was successfully set up.
Click on **Register U2F Device** to complete the process.
+### WebAuthn device
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22506) in GitLab 13.4.
+> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - It's disabled on GitLab.com.
+> - It's not recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-webauthn). **(CORE ONLY)**
+
+The WebAuthn workflow is [supported by](https://caniuse.com/#search=webauthn) the
+following desktop browsers:
+
+- Chrome
+- Edge
+- Firefox
+- Opera
+- Safari
+
+and the following mobile browsers:
+
+- Chrome for Android
+- Firefox for Android
+- iOS Safari (since iOS 13.3)
+
+To set up 2FA with a WebAuthn compatible device:
+
+1. Sign in to your GitLab account.
+1. Go to your [**Profile settings**](../index.md#profile-settings).
+1. Go to **Account**.
+1. Select **Enable Two-Factor Authentication**.
+1. Plug in your WebAuthn device.
+1. Select **Set up New WebAuthn Device**.
+1. Depending on your device, you might need to press a button or touch a sensor.
+
+You will see a message indicating that your device was successfully set up.
+Recovery codes are not generated for WebAuthn devices.
+
## Recovery codes
NOTE: **Note:**
-Recovery codes are not generated for U2F devices.
+Recovery codes are not generated for U2F / WebAuthn devices.
CAUTION: **Caution:**
Each code can be used only once to log in to your account.
@@ -141,6 +252,14 @@ To log in via a U2F device:
You will see a message indicating that your device responded to the authentication
request and you will be automatically logged in.
+### Log in via WebAuthn device
+
+In supported browsers you should be automatically prompted to activate your WebAuthn device
+(e.g. by touching/pressing its button) after entering your credentials.
+
+You will see a message indicating that your device responded to the authentication
+request and you will be automatically logged in.
+
## Disabling 2FA
If you ever need to disable 2FA:
@@ -151,7 +270,7 @@ If you ever need to disable 2FA:
1. Click **Disable**, under **Two-Factor Authentication**.
This will clear all your two-factor authentication registrations, including mobile
-applications and U2F devices.
+applications and U2F / WebAuthn devices.
## Personal access tokens
@@ -257,7 +376,8 @@ Sign in and re-enable two-factor authentication as soon as possible.
you may have cases where authorization always fails because of time differences.
- The GitLab U2F implementation does _not_ work when the GitLab instance is accessed from
multiple hostnames, or FQDNs. Each U2F registration is linked to the _current hostname_ at
- the time of registration, and cannot be used for other hostnames/FQDNs.
+ the time of registration, and cannot be used for other hostnames/FQDNs. The same applies to
+ WebAuthn registrations.
For example, if a user is trying to access a GitLab instance from `first.host.xyz` and `second.host.xyz`:
@@ -268,6 +388,25 @@ Sign in and re-enable two-factor authentication as soon as possible.
- To enforce 2FA at the system or group levels see [Enforce Two-factor Authentication](../../../security/two_factor_authentication.md).
+## Enable or disable WebAuthn **(CORE ONLY)**
+
+Support for WebAuthn 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(:webauthn)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:webauthn)
+```
+
## Troubleshooting
If you are receiving an `invalid pin code` error, this may indicate that there is a time sync issue between the authentication application and the GitLab instance itself.
diff --git a/doc/user/profile/active_sessions.md b/doc/user/profile/active_sessions.md
index a5b15a7880c..4630215eca6 100644
--- a/doc/user/profile/active_sessions.md
+++ b/doc/user/profile/active_sessions.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: howto
---
diff --git a/doc/user/profile/img/busy_status_indicator_v13_6.png b/doc/user/profile/img/busy_status_indicator_v13_6.png
new file mode 100644
index 00000000000..291e0fab971
--- /dev/null
+++ b/doc/user/profile/img/busy_status_indicator_v13_6.png
Binary files differ
diff --git a/doc/user/profile/img/unknown_sign_in_email_v13_0.png b/doc/user/profile/img/unknown_sign_in_email_v13_0.png
deleted file mode 100644
index 51a7c29cdfa..00000000000
--- a/doc/user/profile/img/unknown_sign_in_email_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index 0400d9ca2e5..8ae92a42581 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -86,7 +86,7 @@ From there, you can:
If you don't know your current password, select the 'I forgot my password' link.
-![Change your password](./img/change_password_v13_0.png)
+![Change your password](img/change_password_v13_0.png)
## Changing your username
@@ -188,17 +188,22 @@ To set your current status:
1. Set the desired emoji and/or status message.
1. Click **Set status**. Alternatively, you can click **Remove status** to remove your user status entirely.
+![Busy status indicator](img/busy_status_indicator_v13_6.png)
+
or
1. Click your avatar.
1. Select **Profile**.
1. Click **Edit profile** (pencil icon).
1. Enter your status message in the **Your status** text field.
+ 1. Alternatively, select the **Busy** checkbox ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259649) in GitLab 13.6}.
1. Click **Add status emoji** (smiley face), and select the desired emoji.
1. Click **Update profile settings**.
You can also set your current status [using the API](../../api/users.md#user-status).
+If you previously selected the "Busy" checkbox, remember to deselect it when you become available again.
+
## Commit email
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21598) in GitLab 11.4.
diff --git a/doc/user/profile/notifications.md b/doc/user/profile/notifications.md
index 73a83b08a23..f3d27147557 100644
--- a/doc/user/profile/notifications.md
+++ b/doc/user/profile/notifications.md
@@ -7,13 +7,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Notification Emails
-GitLab Notifications allow you to stay informed about what's happening in GitLab. With notifications enabled, you can receive updates about activity in issues, merge requests, and epics. Notifications are sent via email.
+GitLab Notifications allow you to stay informed about what's happening in GitLab. With notifications
+enabled, you can receive updates about activity in issues, merge requests, epics, and designs.
+Notifications are sent via email.
## Receiving notifications
You will receive notifications for one of the following reasons:
-- You participate in an issue, merge request, or epic. In this context, _participate_ means comment, or edit.
+- You participate in an issue, merge request, epic or design. In this context, _participate_ means comment, or edit.
- You enable notifications in an issue, merge request, or epic. To enable notifications, click the **Notifications** toggle in the sidebar to _on_.
While notifications are enabled, you will receive notification of actions occurring in that issue, merge request, or epic.
@@ -209,6 +211,18 @@ If an open merge request becomes unmergeable due to conflict, its author will be
If a user has also set the merge request to automatically merge once pipeline succeeds,
then that user will also be notified.
+## Design email notifications
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217095) in GitLab 13.6.
+
+Email notifications are sent to the participants when comments are made on a design.
+
+The participants are:
+
+- Authors of the design (can be multiple people if different authors have uploaded different versions of the design).
+- Authors of comments on the design.
+- Anyone that is `@mentioned` in a comment on the design.
+
## Filtering email
Notification email messages include GitLab-specific headers. You can filter the notification emails based on the content of these headers to better manage your notifications. For example, you could filter all emails for a specific project where you are being assigned either a merge request or issue.
diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md
index 61944bb9d0b..168bcb5a42e 100644
--- a/doc/user/profile/preferences.md
+++ b/doc/user/profile/preferences.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: concepts, howto
---
diff --git a/doc/user/profile/unknown_sign_in_notification.md b/doc/user/profile/unknown_sign_in_notification.md
index 6a6820bb2d4..a97af3d6965 100644
--- a/doc/user/profile/unknown_sign_in_notification.md
+++ b/doc/user/profile/unknown_sign_in_notification.md
@@ -30,4 +30,4 @@ for a notification email to be sent.
## Example email
-![Unknown sign in email](./img/unknown_sign_in_email_v13_1.png)
+![Unknown sign in email](img/unknown_sign_in_email_v13_1.png)
diff --git a/doc/user/project/canary_deployments.md b/doc/user/project/canary_deployments.md
index afce3869cbf..e9bb6d0e3ff 100644
--- a/doc/user/project/canary_deployments.md
+++ b/doc/user/project/canary_deployments.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Canary Deployments **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1659) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.1.
@@ -61,3 +67,74 @@ Canary deployments are marked with a yellow dot in the Deploy Board so that you
can easily notice them.
![Canary deployments on Deploy Board](img/deploy_boards_canary_deployments.png)
+
+### Advanced traffic control with Canary Ingress **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215501) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
+
+Canary deployments can be more strategic with [Canary Ingress](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary),
+which is an advanced traffic routing service that controls incoming HTTP
+requests between stable and canary deployments based on factors such as weight, sessions, cookies,
+and others. GitLab uses this service in its [Auto Deploy architecture](../../topics/autodevops/upgrading_auto_deploy_dependencies.md#v2-chart-resource-architecture)
+to let users easily and safely roll out their new deployments.
+
+#### How to set up a Canary Ingress in a canary deployment
+
+A Canary Ingress is installed by default if your Auto DevOps pipeline uses
+[`v2.0.0+` of `auto-deploy-image`](../../topics/autodevops/upgrading_auto_deploy_dependencies.md#verify-dependency-versions).
+A Canary Ingress becomes available when you create a new canary deployment and is destroyed when the
+canary deployment is promoted to production.
+
+Here's an example setup flow from scratch:
+
+1. Prepare an [Auto DevOps-enabled](../../topics/autodevops/index.md) project.
+1. Set up a [Kubernetes Cluster](../../user/project/clusters/index.md) in your project.
+1. Install [Ingress](../../user/clusters/applications.md#ingress) as a GitLab Managed App.
+1. Set up [the base domain](../../user/project/clusters/index.md#base-domain) based on the Ingress
+ Endpoint assigned above.
+1. Check if [`v2.0.0+` of `auto-deploy-image` is used in your Auto DevOps pipelines](../../topics/autodevops/upgrading_auto_deploy_dependencies.md#verify-dependency-versions).
+ If it isn't, follow the documentation to specify the image version.
+1. [Run a new Auto DevOps pipeline](../../ci/pipelines/index.md#run-a-pipeline-manually)
+ and make sure that the `production` job succeeds and creates a production environment.
+1. Configure a [`canary` deployment job for Auto DevOps pipelines](../../topics/autodevops/customize.md#deploy-policy-for-canary-environments).
+1. [Run a new Auto DevOps pipeline](../../ci/pipelines/index.md#run-a-pipeline-manually)
+ and make sure that the `canary` job succeeds and creates a canary deployment with Canary Ingress.
+
+#### How to check the current traffic weight on a Canary Ingress
+
+1. Visit [Deploy Board](../../user/project/deploy_boards.md).
+1. Open your browser's inspection tool and examine a response from the `environments.json` endpoint.
+ You can find the current weight under `rollout_status`.
+
+ ![Rollout Status Canary Ingress](img/rollout_status_canary_ingress.png)
+
+ Note that we have [a plan](https://gitlab.com/gitlab-org/gitlab/-/issues/218139)
+ to visualize this information in a [Deploy Board](../../user/project/deploy_boards.md)
+ without needing a browser's inspection tool.
+
+#### How to change the traffic weight on a Canary Ingress
+
+You can change the traffic weight by using [GraphiQL](../../api/graphql/getting_started.md#graphiql)
+or by sending requests to the [GraphQL API](../../api/graphql/getting_started.md#command-line).
+
+Here's an example using [GraphiQL](../../api/graphql/getting_started.md#graphiql):
+
+1. Visit [GraphiQL Explorer](https://gitlab.com/-/graphql-explorer).
+1. Execute the `environmentsCanaryIngressUpdate` GraphQL mutation:
+
+ ```shell
+ mutation {
+ environmentsCanaryIngressUpdate(input:{
+ id: "gid://gitlab/Environment/29", # Your Environment ID. You can get the ID from the URL of the environment page.
+ weight: 45 # The new traffic weight. e.g. If you set `45`, 45% of traffic goes to a canary deployment and 55% of traffic goes to a stable deployment.
+ }) {
+ errors
+ }
+ }
+ ```
+
+1. If the request succeeds, the `errors` response contains an empty array. GitLab sends a `PATCH`
+ request to your Kubernetes cluster for updating the weight parameter on a Canary Ingress.
+
+Note that there's [a plan](https://gitlab.com/gitlab-org/gitlab/-/issues/218139)
+to control the weight from a [Deploy Board](../../user/project/deploy_boards.md).
diff --git a/doc/user/project/clusters/add_eks_clusters.md b/doc/user/project/clusters/add_eks_clusters.md
index 65416d73f06..c3f2b96ce9f 100644
--- a/doc/user/project/clusters/add_eks_clusters.md
+++ b/doc/user/project/clusters/add_eks_clusters.md
@@ -139,6 +139,7 @@ To create and add a new Kubernetes cluster to your project, group, or instance:
1. Enter a role name and optional description into the fields provided.
1. Click **Create role**, the new role name will appear at the top. Click on its name and copy the `Role ARN` from the newly created role.
1. In GitLab, enter the copied role ARN into the `Role ARN` field.
+1. In the **Cluster Region** field, enter the [region](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html) you plan to use for your new cluster. GitLab will authenticate you have access to this region when authenticating your role.
1. Click **Authenticate with AWS**.
1. Choose your cluster's settings:
- **Kubernetes cluster name** - The name you wish to give the cluster.
@@ -152,9 +153,6 @@ To create and add a new Kubernetes cluster to your project, group, or instance:
the one you created much earlier by following the
[Amazon EKS cluster IAM role](https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html)
guide.
-
- - **Region** - The [region](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html)
- in which the cluster will be created.
- **Key pair name** - Select the [key pair](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)
that you can use to connect to your worker nodes if required.
- **VPC** - Select a [VPC](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html)
@@ -184,9 +182,10 @@ The following errors are commonly encountered when creating a new cluster.
#### Error: Request failed with status code 422
When submitting the initial authentication form, GitLab returns a status code 422
-error when it can't determine the role you've provided. Make sure you've
+error when it can't determine the role or region you've provided. Make sure you've
correctly configured your role with the **Account ID** and **External ID**
provided by GitLab. In GitLab, make sure to enter the correct **Role ARN**.
+Make sure you also have access to the chosen region.
#### Could not load Security Groups for this VPC
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index 094f4bcf6ba..c96e38b1dfc 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.md
@@ -94,7 +94,11 @@ GitLab creates the following resources for RBAC clusters.
| Environment namespace | `Namespace` | Contains all environment-specific resources | Deploying to a cluster |
| Environment namespace | `ServiceAccount` | Uses namespace of environment | Deploying to a cluster |
| Environment namespace | `Secret` | Token for environment ServiceAccount | Deploying to a cluster |
-| Environment namespace | `RoleBinding` | [`edit`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Deploying to a cluster |
+| Environment namespace | `RoleBinding` | [`admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Deploying to a cluster |
+
+The environment namespace `RoleBinding` was
+[updated](https://gitlab.com/gitlab-org/gitlab/-/issues/31113) in GitLab 13.6
+to `admin` roleRef. Previously, the `edit` roleRef was used.
### ABAC cluster resources
@@ -149,6 +153,9 @@ Amazon Elastic Kubernetes Service (EKS) at the project, group, or instance level
- [Amazon EKS](add_eks_clusters.md#new-eks-cluster).
- [Google GKE](add_gke_clusters.md#creating-the-cluster-on-gke).
+After creating a cluster, you can install runners for it as described in
+[GitLab Managed Apps](../../clusters/applications.md).
+
## Add existing cluster
If you have an existing Kubernetes cluster, you can add it to a project, group,
@@ -158,6 +165,9 @@ Kubernetes integration isn't supported for arm64 clusters. See the issue
[Helm Tiller fails to install on arm64 cluster](https://gitlab.com/gitlab-org/gitlab/-/issues/29838)
for details.
+After adding an existing cluster, you can install runners for it as described in
+[GitLab Managed Apps](../../clusters/applications.md).
+
### Existing Kubernetes cluster
To add a Kubernetes cluster to your project, group, or instance:
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index 459ba144186..9273fb7b361 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -22,6 +22,8 @@ Using the GitLab project Kubernetes integration, you can:
- Use [Web terminals](#web-terminals).
- Use [Deploy Boards](#deploy-boards). **(PREMIUM)**
- Use [Canary Deployments](#canary-deployments). **(PREMIUM)**
+- Use [deployment variables](#deployment-variables).
+- Use [role-based or attribute-based access controls](add_remove_clusters.md#access-controls).
- View [Logs](#viewing-pod-logs).
- Run serverless workloads on [Kubernetes with Knative](serverless/index.md).
@@ -40,14 +42,15 @@ of memory and CPU usage.
GitLab is committed to support at least two production-ready Kubernetes minor
versions at any given time. We regularly review the versions we support, and
-provide a four-month deprecation period before we remove support of a specific
+provide a three-month deprecation period before we remove support of a specific
version. The range of supported versions is based on the evaluation of:
- Our own needs.
- The versions supported by major managed Kubernetes providers.
- The versions [supported by the Kubernetes community](https://kubernetes.io/docs/setup/release/version-skew-policy/#supported-versions).
-Currently, GitLab supports the following Kubernetes versions:
+GitLab supports the following Kubernetes versions, and you can upgrade your
+Kubernetes version to any supported version at any time:
- 1.17
- 1.16
@@ -241,9 +244,18 @@ A Kubernetes cluster can be the destination for a deployment job. If
### Deployment variables
+Deployment variables require a valid [Deploy Token](../deploy_tokens/index.md) named
+[`gitlab-deploy-token`](../deploy_tokens/index.md#gitlab-deploy-token), and the
+following command in your deployment job script, for Kubernetes to access the registry:
+
+```plaintext
+kubectl create secret docker-registry gitlab-registry --docker-server="$CI_REGISTRY" --docker-username="$CI_DEPLOY_USER" --docker-password="$CI_DEPLOY_PASSWORD" --docker-email="$GITLAB_USER_EMAIL" -o yaml --dry-run | kubectl apply -f -
+```
+
The Kubernetes cluster integration exposes the following
[deployment variables](../../../ci/variables/README.md#deployment-environment-variables) in the
-GitLab CI/CD build environment.
+GitLab CI/CD build environment to deployment jobs, which are jobs that have
+[defined a target environment](../../../ci/environments/index.md#defining-environments).
| Variable | Description |
| -------- | ----------- |
diff --git a/doc/user/project/clusters/securing.md b/doc/user/project/clusters/securing.md
index bed01ff4d58..2d74f67ba35 100644
--- a/doc/user/project/clusters/securing.md
+++ b/doc/user/project/clusters/securing.md
@@ -1,5 +1,5 @@
---
-stage: Defend
+stage: Protect
group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
@@ -42,7 +42,7 @@ Minimum requirements (depending on the GitLab Manage Application you want to ins
NOTE: **Note:**
These diagrams use the term _Kubernetes_ for simplicity. In practice, Sidekiq connects to a Helm
-Tiller daemon running in a pod in the cluster.
+command runner pod in the cluster.
You install GitLab Managed Apps from the GitLab web interface with a one-click setup process. GitLab
uses Sidekiq (a background processing service) to facilitate this.
diff --git a/doc/user/project/clusters/serverless/aws.md b/doc/user/project/clusters/serverless/aws.md
index db91f78fc20..0de0fd38336 100644
--- a/doc/user/project/clusters/serverless/aws.md
+++ b/doc/user/project/clusters/serverless/aws.md
@@ -335,7 +335,7 @@ Some steps in this documentation use SAM CLI. Follow the instructions for
[installing SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)
to install and configure SAM CLI.
-If you use [AWS Cloud9](https://aws.amazon.com/cloud9/) as your integrated development
+If you use [AWS Cloud9](https://aws.amazon.com/cloud9/) as your integrated development
environment (IDE), the following are installed for you:
- [AWS Command Line Interface](https://docs.aws.amazon.com/en_pv/cli/latest/userguide/cli-chap-install.html)
@@ -357,7 +357,7 @@ To create a new AWS SAM application:
1. `git push` the application back to the GitLab project.
This creates a SAM app named `gitlabpoc` using the default configuration, a single
-Python 3.8 function invoked by an [Amazon API Gateway](https://aws.amazon.com/api-gateway/)
+Python 3.8 function invoked by an [Amazon API Gateway](https://aws.amazon.com/api-gateway/)
endpoint. To see additional runtimes supported by SAM and options for `sam init`, run:
```shell
@@ -367,13 +367,13 @@ sam init -h
### Setting up your AWS credentials with your GitLab account
In order to interact with your AWS account, the GitLab CI/CD pipelines require both
-`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` to be set in the project's CI/CD
+`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` to be set in the project's CI/CD
variables.
To set these:
-1. Navigate to the project's **Settings > CI / CD**.
-1. Expand the **Variables** section and create entries for `AWS_ACCESS_KEY_ID` and
+1. Navigate to the project's **Settings > CI / CD**.
+1. Expand the **Variables** section and create entries for `AWS_ACCESS_KEY_ID` and
`AWS_SECRET_ACCESS_KEY`.
1. Mask the credentials so they do not show in logs using the **Masked** toggle.
@@ -460,7 +460,7 @@ CLI installed locally for you to test locally.
First, test the function.
-SAM provides a default event in `events/event.json` that includes a message body of:
+SAM provides a default event in `events/event.json` that includes a message body of:
```plaintext
{\"message\": \"hello world\"}
@@ -491,7 +491,7 @@ sam local start-api
```
SAM again launches a Docker container, this time with a mocked Amazon API Gateway
-listening on `localhost:3000`.
+listening on `localhost:3000`.
Call the `hello` API by running:
diff --git a/doc/user/project/code_intelligence.md b/doc/user/project/code_intelligence.md
index d0c5a24826a..5f96f65ea06 100644
--- a/doc/user/project/code_intelligence.md
+++ b/doc/user/project/code_intelligence.md
@@ -35,7 +35,9 @@ code_navigation:
lsif: dump.lsif
```
-The generated LSIF file must be less than 170MiB.
+The generated LSIF file size may be limited by
+the [artifact application limits (`ci_max_artifact_size_lsif`)](../../administration/instance_limits.md#maximum-file-size-per-type-of-artifact),
+default to 100MB (configurable by an instance administrator).
After the job succeeds, code intelligence data can be viewed while browsing the code:
diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md
index 4ae3d5ec032..37ebef3a26e 100644
--- a/doc/user/project/code_owners.md
+++ b/doc/user/project/code_owners.md
@@ -27,7 +27,7 @@ who is responsible for each file or path.
Code Owners allows for a version controlled, single source of
truth file outlining the exact GitLab users or groups that
own certain files or paths in a repository. Code Owners can be
-utilized in the merge request approval process which can streamline
+used in the merge request approval process which can streamline
the process of finding the right reviewers and approvers for a given
merge request.
@@ -48,10 +48,14 @@ You can choose to add the `CODEOWNERS` file in three places:
- Inside the `.gitlab/` directory
- Inside the `docs/` directory
-The `CODEOWNERS` file is scoped to a branch, which means that as
-new files are introduced, the user adding the new content can
-specify themselves as a code owner, all before the new changes
-get merged to the target branch.
+The `CODEOWNERS` file is valid for the branch where it lives. For example, if you change the code owners
+in a feature branch, they won't be valid in the main branch until the feature branch is merged.
+
+If you introduce new files to your repository and you want to identify the code owners for that file,
+you have to update `CODEOWNERS` accordingly. If you update the code owners when you are adding the files (in the same
+branch), GitLab will count the owners as soon as the branch is merged. If
+you don't, you can do that later, but your new files will not belong to anyone until you update your
+`CODEOWNERS` file in the TARGET branch.
When a file matches multiple entries in the `CODEOWNERS` file,
the users from last pattern matching the file are displayed on the
diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md
index 3c6494d5f1a..2bf35b48547 100644
--- a/doc/user/project/deploy_boards.md
+++ b/doc/user/project/deploy_boards.md
@@ -41,9 +41,9 @@ knowledge. In particular, you should be familiar with:
- [Kubernetes namespaces](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)
- [Kubernetes canary deployments](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments)
-NOTE: **Note:**
-Apps that consist of multiple deployments are shown as duplicates on the deploy board.
-Follow [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/8463) for details.
+In GitLab 13.5 and earlier, apps that consist of multiple deployments are shown as
+duplicates on the deploy board. This is [fixed](https://gitlab.com/gitlab-org/gitlab/-/issues/8463)
+in GitLab 13.6.
## Use cases
diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md
index 5ca421dda5b..1ac528ca4ae 100644
--- a/doc/user/project/deploy_tokens/index.md
+++ b/doc/user/project/deploy_tokens/index.md
@@ -13,57 +13,61 @@ type: howto
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29280) from **Settings > CI / CD** in GitLab 12.10.1.
> - [Added package registry scopes](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) in GitLab 13.0.
-Deploy tokens allow you to download (`git clone`) or push and pull packages and container registry images of a project without having a user and a password.
+Deploy tokens allow you to download (`git clone`) or push and pull packages and
+container registry images of a project without having a user and a password.
Deploy tokens can be managed by [maintainers only](../../permissions.md).
-If you have a key pair, you might want to use [deploy keys](../../../ssh/README.md#deploy-keys) instead.
+If you have a key pair, you might want to use [deploy keys](../../../ssh/README.md#deploy-keys)
+instead.
## Creating a Deploy Token
-You can create as many deploy tokens as you like from the settings of your project. Alternatively, you can also create [group-scoped deploy tokens](#group-deploy-token).
+You can create as many deploy tokens as you need from the settings of your
+project. Alternatively, you can also create [group-scoped deploy tokens](#group-deploy-token).
-1. Log in to your GitLab account.
+1. Sign in to your GitLab account.
1. Go to the project (or group) you want to create Deploy Tokens for.
1. Go to **Settings > Repository**.
1. Click on "Expand" on **Deploy Tokens** section.
1. Choose a name, expiry date (optional), and username (optional) for the token.
1. Choose the [desired scopes](#limiting-scopes-of-a-deploy-token).
-1. Click on **Create deploy token**.
-1. Save the deploy token somewhere safe. Once you leave or refresh
+1. Select **Create deploy token**.
+1. Save the deploy token somewhere safe. After you leave or refresh
the page, **you won't be able to access it again**.
![Personal access tokens page](img/deploy_tokens.png)
## Deploy token expiration
-Deploy tokens expire on the date you define, at midnight UTC.
+Deploy tokens expire at midnight UTC on the date you define.
## Revoking a deploy token
-At any time, you can revoke any deploy token by just clicking the
-respective **Revoke** button under the 'Active deploy tokens' area.
+At any time, you can revoke any deploy token by just clicking the respective
+**Revoke** button under the 'Active deploy tokens' area.
## Limiting scopes of a deploy token
-Deploy tokens can be created with different scopes that allow various
-actions that a given token can perform. The available scopes are depicted in
-the following table along with GitLab version it was introduced in.
+Deploy tokens can be created with different scopes that allow various actions
+that a given token can perform. The available scopes are depicted in the
+following table along with GitLab version it was introduced in:
-| Scope | Description | Introduced in GitLab Version |
-| ----- | ----------- | ------ |
-| `read_repository` | Allows read-access to the repository through `git clone` | 10.7 |
-| `read_registry` | Allows read-access to [container registry](../../packages/container_registry/index.md) images if a project is private and authorization is required. | 10.7 |
-| `write_registry` | Allows write-access (push) to [container registry](../../packages/container_registry/index.md). | 12.10 |
-| `read_package_registry` | Allows read access to the package registry. | 13.0 |
+| Scope | Description | Introduced in GitLab Version |
+|--------------------------|-------------|------------------------------|
+| `read_repository` | Allows read-access to the repository through `git clone` | 10.7 |
+| `read_registry` | Allows read-access to [container registry](../../packages/container_registry/index.md) images if a project is private and authorization is required. | 10.7 |
+| `write_registry` | Allows write-access (push) to [container registry](../../packages/container_registry/index.md). | 12.10 |
+| `read_package_registry` | Allows read access to the package registry. | 13.0 |
| `write_package_registry` | Allows write access to the package registry. | 13.0 |
## Deploy token custom username
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29639) in GitLab 12.1.
-The default username format is `gitlab+deploy-token-#{n}`. Some tools or platforms may not support this format,
-in such case you can specify custom username to be used when creating the deploy token.
+The default username format is `gitlab+deploy-token-#{n}`. Some tools or
+platforms may not support this format; in this case you can specify a custom
+username to be used when creating the deploy token.
## Usage
@@ -87,13 +91,13 @@ To read the container registry images, you'll need to:
1. Create a Deploy Token with `read_registry` as a scope.
1. Take note of your `username` and `token`.
-1. Log in to GitLab’s Container Registry using the deploy token:
+1. Sign in to GitLab’s Container Registry using the deploy token:
```shell
docker login -u <username> -p <deploy_token> registry.example.com
```
-Just replace `<username>` and `<deploy_token>` with the proper values. Then you can simply
+Replace `<username>` and `<deploy_token>` with the proper values. You can now
pull images from your Container Registry.
### Push Container Registry images
@@ -104,13 +108,13 @@ To push the container registry images, you'll need to:
1. Create a Deploy Token with `write_registry` as a scope.
1. Take note of your `username` and `token`.
-1. Log in to GitLab’s Container Registry using the deploy token:
+1. Sign in to GitLab’s Container Registry using the deploy token:
```shell
docker login -u <username> -p <deploy_token> registry.example.com
```
-Just replace `<username>` and `<deploy_token>` with the proper values. Then you can simply
+Replace `<username>` and `<deploy_token>` with the proper values. You can now
push images to your Container Registry.
### Read or pull packages
@@ -121,7 +125,8 @@ To pull packages in the GitLab package registry, you'll need to:
1. Create a Deploy Token with `read_package_registry` as a scope.
1. Take note of your `username` and `token`.
-1. For the [package type of your choice](./../../packages/index.md), follow the authentication instructions for deploy tokens.
+1. For the [package type of your choice](../../packages/index.md), follow the
+ authentication instructions for deploy tokens.
### Push or upload packages
@@ -131,7 +136,8 @@ To upload packages in the GitLab package registry, you'll need to:
1. Create a Deploy Token with `write_package_registry` as a scope.
1. Take note of your `username` and `token`.
-1. For the [package type of your choice](./../../packages/index.md), follow the authentication instructions for deploy tokens.
+1. For the [package type of your choice](../../packages/index.md), follow the
+ authentication instructions for deploy tokens.
### Group Deploy Token
@@ -158,10 +164,10 @@ apply consistently when cloning the repository of related projects.
There's a special case when it comes to Deploy Tokens. If a user creates one
named `gitlab-deploy-token`, the username and token of the Deploy Token will be
-automatically exposed to the CI/CD jobs as environment variables: `CI_DEPLOY_USER` and
-`CI_DEPLOY_PASSWORD`, respectively.
+automatically exposed to the CI/CD jobs as environment variables: `CI_DEPLOY_USER`
+and `CI_DEPLOY_PASSWORD`, respectively.
-After you create the token, you can login to the Container Registry using
+After you create the token, you can sign in to the Container Registry by using
those variables:
```shell
@@ -169,4 +175,7 @@ docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
```
NOTE: **Note:**
-The special handling for the `gitlab-deploy-token` deploy token is not currently implemented for group deploy tokens. For the deploy token to be available for CI/CD jobs, it must be created at the project level. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/214014) for details.
+The special handling for the `gitlab-deploy-token` deploy token is not currently
+implemented for group deploy tokens. For the deploy token to be available for
+CI/CD jobs, it must be created at the project level. For details, see
+[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/214014).
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index e0c4097d1c5..4c14251cfa5 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -62,7 +62,7 @@ To create the `.gitlab/issue_templates` directory:
1. Click the `+` button next to `master` again and select **New directory**.This time, n
1. Name your directory `issue_templates` and commit to your default branch.
-To check if this has worked correctly, [create a new issue](./issues/managing_issues.md#create-a-new-issue)
+To check if this has worked correctly, [create a new issue](issues/managing_issues.md#create-a-new-issue)
and see if you can choose a description template.
## Creating merge request templates
diff --git a/doc/user/project/img/epics_swimlanes_drag_and_drop.png b/doc/user/project/img/epics_swimlanes_drag_and_drop.png
new file mode 100644
index 00000000000..b2cc4105898
--- /dev/null
+++ b/doc/user/project/img/epics_swimlanes_drag_and_drop.png
Binary files differ
diff --git a/doc/user/project/img/epics_swimlanes_v13.6.png b/doc/user/project/img/epics_swimlanes_v13.6.png
new file mode 100644
index 00000000000..6f787ba8b10
--- /dev/null
+++ b/doc/user/project/img/epics_swimlanes_v13.6.png
Binary files differ
diff --git a/doc/user/project/img/group_issue_board.png b/doc/user/project/img/group_issue_board.png
deleted file mode 100644
index be360d18540..00000000000
--- a/doc/user/project/img/group_issue_board.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_board_add_list.png b/doc/user/project/img/issue_board_add_list.png
deleted file mode 100644
index 91098daa1d1..00000000000
--- a/doc/user/project/img/issue_board_add_list.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_board_add_list_v13_6.png b/doc/user/project/img/issue_board_add_list_v13_6.png
new file mode 100644
index 00000000000..4239ab6e7e4
--- /dev/null
+++ b/doc/user/project/img/issue_board_add_list_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/issue_board_assignee_lists.png b/doc/user/project/img/issue_board_assignee_lists.png
deleted file mode 100644
index f2660cd8f80..00000000000
--- a/doc/user/project/img/issue_board_assignee_lists.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_board_assignee_lists_v13_6.png b/doc/user/project/img/issue_board_assignee_lists_v13_6.png
new file mode 100644
index 00000000000..d0fbb0a2ef0
--- /dev/null
+++ b/doc/user/project/img/issue_board_assignee_lists_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/issue_board_creation.png b/doc/user/project/img/issue_board_creation.png
deleted file mode 100644
index 099fe6eee21..00000000000
--- a/doc/user/project/img/issue_board_creation.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_board_creation_v13_6.png b/doc/user/project/img/issue_board_creation_v13_6.png
new file mode 100644
index 00000000000..e36b53418fd
--- /dev/null
+++ b/doc/user/project/img/issue_board_creation_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/issue_board_edit_button.png b/doc/user/project/img/issue_board_edit_button.png
deleted file mode 100644
index a0dc6f41592..00000000000
--- a/doc/user/project/img/issue_board_edit_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_board_focus_mode.gif b/doc/user/project/img/issue_board_focus_mode.gif
deleted file mode 100644
index 9565bdb0865..00000000000
--- a/doc/user/project/img/issue_board_focus_mode.gif
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_board_milestone_lists.png b/doc/user/project/img/issue_board_milestone_lists.png
deleted file mode 100644
index 91926f58f87..00000000000
--- a/doc/user/project/img/issue_board_milestone_lists.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_board_milestone_lists_v13_6.png b/doc/user/project/img/issue_board_milestone_lists_v13_6.png
new file mode 100644
index 00000000000..a7718ffd66c
--- /dev/null
+++ b/doc/user/project/img/issue_board_milestone_lists_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/issue_board_move_issue_card_list.png b/doc/user/project/img/issue_board_move_issue_card_list.png
deleted file mode 100644
index 13750a63766..00000000000
--- a/doc/user/project/img/issue_board_move_issue_card_list.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_board_move_issue_card_list_v13_6.png b/doc/user/project/img/issue_board_move_issue_card_list_v13_6.png
new file mode 100644
index 00000000000..2b661a63d7d
--- /dev/null
+++ b/doc/user/project/img/issue_board_move_issue_card_list_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/issue_board_summed_weights.png b/doc/user/project/img/issue_board_summed_weights.png
deleted file mode 100644
index 6035d7ca330..00000000000
--- a/doc/user/project/img/issue_board_summed_weights.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_board_summed_weights_v13_6.png b/doc/user/project/img/issue_board_summed_weights_v13_6.png
new file mode 100644
index 00000000000..a6482e73c0a
--- /dev/null
+++ b/doc/user/project/img/issue_board_summed_weights_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/issue_board_system_notes.png b/doc/user/project/img/issue_board_system_notes.png
deleted file mode 100644
index c6ecb498198..00000000000
--- a/doc/user/project/img/issue_board_system_notes.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_board_system_notes_v13_6.png b/doc/user/project/img/issue_board_system_notes_v13_6.png
new file mode 100644
index 00000000000..4958f63541e
--- /dev/null
+++ b/doc/user/project/img/issue_board_system_notes_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/issue_board_view_scope.png b/doc/user/project/img/issue_board_view_scope.png
deleted file mode 100644
index d173679a0e7..00000000000
--- a/doc/user/project/img/issue_board_view_scope.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_boards_add_issues_modal.png b/doc/user/project/img/issue_boards_add_issues_modal.png
deleted file mode 100644
index ecddf6709d0..00000000000
--- a/doc/user/project/img/issue_boards_add_issues_modal.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_boards_add_issues_modal_v13_6.png b/doc/user/project/img/issue_boards_add_issues_modal_v13_6.png
new file mode 100644
index 00000000000..a138efc9c1c
--- /dev/null
+++ b/doc/user/project/img/issue_boards_add_issues_modal_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/issue_boards_blocked_icon_v12_8.png b/doc/user/project/img/issue_boards_blocked_icon_v12_8.png
deleted file mode 100644
index 1055fb48322..00000000000
--- a/doc/user/project/img/issue_boards_blocked_icon_v12_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_boards_blocked_icon_v13_6.png b/doc/user/project/img/issue_boards_blocked_icon_v13_6.png
new file mode 100644
index 00000000000..2dac6bb2ee3
--- /dev/null
+++ b/doc/user/project/img/issue_boards_blocked_icon_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/issue_boards_core.png b/doc/user/project/img/issue_boards_core.png
deleted file mode 100644
index 41ddbb24b14..00000000000
--- a/doc/user/project/img/issue_boards_core.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_boards_core_v13_6.png b/doc/user/project/img/issue_boards_core_v13_6.png
new file mode 100644
index 00000000000..8695b523c12
--- /dev/null
+++ b/doc/user/project/img/issue_boards_core_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/issue_boards_multiple.png b/doc/user/project/img/issue_boards_multiple.png
deleted file mode 100644
index e6183360610..00000000000
--- a/doc/user/project/img/issue_boards_multiple.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_boards_multiple_v13_6.png b/doc/user/project/img/issue_boards_multiple_v13_6.png
new file mode 100644
index 00000000000..18ff5e2bc66
--- /dev/null
+++ b/doc/user/project/img/issue_boards_multiple_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/issue_boards_premium.png b/doc/user/project/img/issue_boards_premium.png
deleted file mode 100644
index ef9f5bbea32..00000000000
--- a/doc/user/project/img/issue_boards_premium.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_boards_premium_v13_6.png b/doc/user/project/img/issue_boards_premium_v13_6.png
new file mode 100644
index 00000000000..8d1c1299d5c
--- /dev/null
+++ b/doc/user/project/img/issue_boards_premium_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/issue_boards_remove_issue.png b/doc/user/project/img/issue_boards_remove_issue.png
deleted file mode 100644
index 7050e6c3ede..00000000000
--- a/doc/user/project/img/issue_boards_remove_issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_boards_remove_issue_v13_6.png b/doc/user/project/img/issue_boards_remove_issue_v13_6.png
new file mode 100644
index 00000000000..c980759ad0c
--- /dev/null
+++ b/doc/user/project/img/issue_boards_remove_issue_v13_6.png
Binary files differ
diff --git a/doc/user/project/img/rollout_status_canary_ingress.png b/doc/user/project/img/rollout_status_canary_ingress.png
new file mode 100644
index 00000000000..fb59ba31615
--- /dev/null
+++ b/doc/user/project/img/rollout_status_canary_ingress.png
Binary files differ
diff --git a/doc/user/project/import/img/gemnasium/connect_github.png b/doc/user/project/import/img/gemnasium/connect_github.png
index 5933f4d5d0a..fae62e8d840 100644
--- a/doc/user/project/import/img/gemnasium/connect_github.png
+++ b/doc/user/project/import/img/gemnasium/connect_github.png
Binary files differ
diff --git a/doc/user/project/import/img/gemnasium/create_project.png b/doc/user/project/import/img/gemnasium/create_project.png
index 6e00bf63405..8edbf711629 100644
--- a/doc/user/project/import/img/gemnasium/create_project.png
+++ b/doc/user/project/import/img/gemnasium/create_project.png
Binary files differ
diff --git a/doc/user/project/import/img/gemnasium/project_connected.png b/doc/user/project/import/img/gemnasium/project_connected.png
index 8e7216c015b..332d2230ef8 100644
--- a/doc/user/project/import/img/gemnasium/project_connected.png
+++ b/doc/user/project/import/img/gemnasium/project_connected.png
Binary files differ
diff --git a/doc/user/project/import/img/jira/import_issues_from_jira_form_v12_10.png b/doc/user/project/import/img/jira/import_issues_from_jira_form_v12_10.png
deleted file mode 100644
index 317a426394c..00000000000
--- a/doc/user/project/import/img/jira/import_issues_from_jira_form_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index a1c28cfa2b7..a113758495a 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -30,6 +30,11 @@ repository is too large the import can timeout.
There is also the option of [connecting your external repository to get CI/CD benefits](../../../ci/ci_cd_for_external_repos/index.md). **(PREMIUM)**
+## LFS authentication
+
+When importing a project that contains LFS objects, if the project has an [`.lfsconfig`](https://github.com/git-lfs/git-lfs/blob/master/docs/man/git-lfs-config.5.ronn)
+file with a URL host (`lfs.url`) different from the repository URL host, LFS files are not downloaded.
+
## Migrating from self-managed GitLab to GitLab.com
If you only need to migrate Git repositories, you can [import each project by URL](repo_by_url.md). Issues and merge requests can't be imported.
diff --git a/doc/user/project/import/tfvc.md b/doc/user/project/import/tfvc.md
index faa2a9b4927..cbc25552873 100644
--- a/doc/user/project/import/tfvc.md
+++ b/doc/user/project/import/tfvc.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: concepts
---
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index a00f93bac9c..333c72a65b1 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -192,17 +192,7 @@ To delete a project, first navigate to the home page for that project.
1. Click **Delete project**
1. Confirm this action by typing in the expected text.
-### Delayed deletion **(PREMIUM)**
-
-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)
+Projects in personal namespaces are deleted immediately on request. For information on delayed deletion of projects within a group, please see [Enabling delayed project removal](../group/index.md#enabling-delayed-project-removal).
## CI/CD for external repositories **(PREMIUM)**
@@ -250,6 +240,14 @@ For users without permissions to view the project's code:
- The wiki homepage is displayed, if any.
- The list of issues within the project is displayed.
+## GitLab Workflow - VS Code extension
+
+To avoid switching from the GitLab UI and VS Code while working in GitLab repositories, you can integrate
+the [VS Code](https://code.visualstudio.com/) editor with GitLab through the
+[GitLab Workflow extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow).
+
+To review or contribute to the extension's code, visit [its codebase in GitLab](https://gitlab.com/gitlab-org/gitlab-vscode-extension/).
+
## Redirects when changing repository paths
When a repository path changes, it is essential to smoothly transition from the
diff --git a/doc/user/project/insights/index.md b/doc/user/project/insights/index.md
index 4d646ee2f79..eaef0b8d69f 100644
--- a/doc/user/project/insights/index.md
+++ b/doc/user/project/insights/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Insights **(ULTIMATE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
diff --git a/doc/user/project/integrations/ewm.md b/doc/user/project/integrations/ewm.md
index be89323a246..822483a1d5b 100644
--- a/doc/user/project/integrations/ewm.md
+++ b/doc/user/project/integrations/ewm.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# 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.
diff --git a/doc/user/project/integrations/img/jira_create_new_group_name.png b/doc/user/project/integrations/img/jira_create_new_group_name.png
deleted file mode 100644
index bfc0dc6b2e9..00000000000
--- a/doc/user/project/integrations/img/jira_create_new_group_name.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/toggle_metrics_user_starred_dashboard_v13_0.png b/doc/user/project/integrations/img/toggle_metrics_user_starred_dashboard_v13_0.png
deleted file mode 100644
index 59dc9ccfd30..00000000000
--- a/doc/user/project/integrations/img/toggle_metrics_user_starred_dashboard_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/webex_teams_configuration.png b/doc/user/project/integrations/img/webex_teams_configuration.png
deleted file mode 100644
index 493b3ea50a0..00000000000
--- a/doc/user/project/integrations/img/webex_teams_configuration.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/project_services.md b/doc/user/project/integrations/project_services.md
index 2c681db1692..90f91fbaa0d 100644
--- a/doc/user/project/integrations/project_services.md
+++ b/doc/user/project/integrations/project_services.md
@@ -1 +1,5 @@
+---
+redirect_to: 'overview.md'
+---
+
This document was moved to [Integrations](overview.md).
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index 28a9afa5bb0..97be16f8dd3 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -95,6 +95,55 @@ spec:
targetPort: ${CONTAINER_PORT}
```
+#### Access the UI of a Prometheus managed application in Kubernetes
+
+You can connect directly to Prometheus, and view the Prometheus user interface, when
+using a Prometheus managed application in Kubernetes:
+
+1. Find the name of the Prometheus pod in the user interface of your Kubernetes
+ provider, such as GKE, or by running the following `kubectl` command in your
+ terminal:
+
+ ```shell
+ kubectl get pods -n gitlab-managed-apps | grep 'prometheus-prometheus-server'
+ ```
+
+ The command should return a result like the following example, where
+ `prometheus-prometheus-server-55b4bd64c9-dpc6b` is the name of the Prometheus pod:
+
+ ```plaintext
+ gitlab-managed-apps prometheus-prometheus-server-55b4bd64c9-dpc6b 2/2 Running 0 71d
+ ```
+
+1. Run a `kubectl port-forward` command. In the following example, `9090` is the
+ Prometheus server's listening port:
+
+ ```shell
+ kubectl port-forward prometheus-prometheus-server-55b4bd64c9-dpc6b 9090:9090 -n gitlab-managed-apps
+ ```
+
+ The `port-forward` command forwards all requests sent to your system's `9090` port
+ to the `9090` port of the Prometheus pod. If the `9090` port on your system is used
+ by another application, you can change the port number before the colon to your
+ desired port. For example, to forward port `8080` of your local system, change the
+ command to:
+
+ ```shell
+ kubectl port-forward prometheus-prometheus-server-55b4bd64c9-dpc6b 8080:9090 -n gitlab-managed-apps
+ ```
+
+1. Open `localhost:9090` in your browser to display the Prometheus user interface.
+
+#### Script access to Prometheus
+
+You can script the access to Prometheus, extracting the name of the pod automatically like this:
+
+```shell
+POD_INFORMATION=$(kubectl get pods -n gitlab-managed-apps | grep 'prometheus-prometheus-server')
+POD_NAME=$(echo $POD_INFORMATION | awk '{print $1;}')
+kubectl port-forward $POD_NAME 9090:9090 -n gitlab-managed-apps
+```
+
### Manual configuration of Prometheus
#### Requirements
diff --git a/doc/user/project/integrations/webex_teams.md b/doc/user/project/integrations/webex_teams.md
index 39daa14407f..7654909b735 100644
--- a/doc/user/project/integrations/webex_teams.md
+++ b/doc/user/project/integrations/webex_teams.md
@@ -10,9 +10,9 @@ You can configure GitLab to send notifications to a Webex Teams space.
## Create a webhook for the space
-1. Go to the [Incoming Webhooks app page](https://apphub.webex.com/teams/applications/incoming-webhooks-cisco-systems).
+1. Go to the [Incoming Webhooks app page](https://apphub.webex.com/teams/applications/incoming-webhooks-cisco-systems-38054).
1. Click **Connect** and log in to Webex Teams, if required.
-1. Enter a name for the webhook and select the space that will receive the notifications.
+1. Enter a name for the webhook and select the space to receive the notifications.
1. Click **ADD**.
1. Copy the **Webhook URL**.
@@ -27,4 +27,4 @@ Once you have a webhook URL for your Webex Teams space, you can configure GitLab
1. Paste the **Webhook** URL for the Webex Teams space.
1. Configure the remaining options and then click **Test settings and save changes**.
-The Webex Teams space will begin to receive all applicable GitLab events.
+The Webex Teams space now begins to receive all applicable GitLab events.
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index 7adea5ebcd6..6a436c5093e 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -1358,6 +1358,140 @@ X-Gitlab-Event: Deployment Hook
Note that `deployable_id` is the ID of the CI job.
+### Feature Flag events
+
+Triggered when a feature flag is turned on or off.
+
+**Request Header**:
+
+```plaintext
+X-Gitlab-Event: Feature Flag Hook
+```
+
+**Request Body**:
+
+```json
+{
+ "object_kind": "feature_flag",
+ "project": {
+ "id": 1,
+ "name":"Gitlab Test",
+ "description":"Aut reprehenderit ut est.",
+ "web_url":"http://example.com/gitlabhq/gitlab-test",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
+ "git_http_url":"http://example.com/gitlabhq/gitlab-test.git",
+ "namespace":"GitlabHQ",
+ "visibility_level":20,
+ "path_with_namespace":"gitlabhq/gitlab-test",
+ "default_branch":"master",
+ "ci_config_path": null,
+ "homepage":"http://example.com/gitlabhq/gitlab-test",
+ "url":"http://example.com/gitlabhq/gitlab-test.git",
+ "ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
+ "http_url":"http://example.com/gitlabhq/gitlab-test.git"
+ },
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "email": "admin@example.com"
+ },
+ "user_url": "http://example.com/root",
+ "object_attributes": {
+ "id": 6,
+ "name": "test-feature-flag",
+ "description": "test-feature-flag-description",
+ "active": true
+ }
+}
+```
+
+### Release events
+
+Triggered when a release is created or updated.
+
+**Request Header**:
+
+```plaintext
+X-Gitlab-Event: Release Hook
+```
+
+**Request Body**:
+
+```json
+{
+ "id": 1,
+ "created_at": "2020-11-02 12:55:12 UTC",
+ "description": "v1.0 has been released",
+ "name": "v1.1",
+ "released_at": "2020-11-02 12:55:12 UTC",
+ "tag": "v1.1",
+ "object_kind": "release",
+ "project": {
+ "id": 2,
+ "name": "release-webhook-example",
+ "description": "",
+ "web_url": "https://example.com/gitlab-org/release-webhook-example",
+ "avatar_url": null,
+ "git_ssh_url": "ssh://git@example.com/gitlab-org/release-webhook-example.git",
+ "git_http_url": "https://example.com/gitlab-org/release-webhook-example.git",
+ "namespace": "Gitlab",
+ "visibility_level": 0,
+ "path_with_namespace": "gitlab-org/release-webhook-example",
+ "default_branch": "master",
+ "ci_config_path": null,
+ "homepage": "https://example.com/gitlab-org/release-webhook-example",
+ "url": "ssh://git@example.com/gitlab-org/release-webhook-example.git",
+ "ssh_url": "ssh://git@example.com/gitlab-org/release-webhook-example.git",
+ "http_url": "https://example.com/gitlab-org/release-webhook-example.git"
+ },
+ "url": "https://example.com/gitlab-org/release-webhook-example/-/releases/v1.1",
+ "action": "create",
+ "assets": {
+ "count": 5,
+ "links": [
+ {
+ "id": 1,
+ "external": true,
+ "link_type": "other",
+ "name": "Changelog",
+ "url": "https://example.net/changelog"
+ }
+ ],
+ "sources": [
+ {
+ "format": "zip",
+ "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.zip"
+ },
+ {
+ "format": "tar.gz",
+ "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar.gz"
+ },
+ {
+ "format": "tar.bz2",
+ "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar.bz2"
+ },
+ {
+ "format": "tar",
+ "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar"
+ }
+ ]
+ },
+ "commit": {
+ "id": "ee0a3fb31ac16e11b9dbb596ad16d4af654d08f8",
+ "message": "Release v1.1",
+ "title": "Release v1.1",
+ "timestamp": "2020-10-31T14:58:32+11:00",
+ "url": "https://example.com/gitlab-org/release-webhook-example/-/commit/ee0a3fb31ac16e11b9dbb596ad16d4af654d08f8",
+ "author": {
+ "name": "Example User",
+ "email": "user@example.com"
+ }
+ }
+}
+```
+
## Image URL rewriting
From GitLab 11.2, simple image references are rewritten to use an absolute URL
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index bce40e9a838..dfe608df18d 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -31,7 +31,7 @@ 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.
-![GitLab issue board - Core](img/issue_boards_core.png)
+![GitLab issue board - Core](img/issue_boards_core_v13_6.png)
Different issue board features are available in different [GitLab tiers](https://about.gitlab.com/pricing/),
as shown in the following table:
@@ -45,7 +45,7 @@ as shown in the following table:
To learn more, visit [GitLab Enterprise features for issue boards](#gitlab-enterprise-features-for-issue-boards) below.
-![GitLab issue board - Premium](img/issue_boards_premium.png)
+![GitLab issue board - Premium](img/issue_boards_premium_v13_6.png)
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
Watch a [video presentation](https://youtu.be/vjccjHI7aGI) of
@@ -69,8 +69,8 @@ For example, let's consider this simplified development workflow:
1. When frontend is complete, the new feature is deployed to a **staging** environment to be tested.
1. When successful, it's deployed to **production**.
-If you have the labels "**backend**", "**frontend**", "**staging**", and
-"**production**", and an issue board with a list for each, you can:
+If you have the labels **Backend**, **Frontend**, **Staging**, and
+**Production**, and an issue board with a list for each, you can:
- Visualize the entire flow of implementations since the beginning of the development life cycle
until deployed to production.
@@ -78,7 +78,7 @@ If you have the labels "**backend**", "**frontend**", "**staging**", and
- Move issues between lists to organize them according to the labels you've set.
- Add multiple issues to lists in the board by selecting one or more existing issues.
-![issue card moving](img/issue_board_move_issue_card_list.png)
+![issue card moving](img/issue_board_move_issue_card_list_v13_6.png)
### Use cases for multiple issue boards
@@ -199,7 +199,7 @@ Using the search box at the top of the menu, you can filter the listed boards.
When you have ten or more boards available, a **Recent** section is also shown in the menu, with
shortcuts to your last four visited boards.
-![Multiple issue boards](img/issue_boards_multiple.png)
+![Multiple issue boards](img/issue_boards_multiple_v13_6.png)
When you're revisiting an issue board in a project or group with multiple boards,
GitLab automatically loads the last board you visited.
@@ -229,20 +229,16 @@ An issue board can be associated with a GitLab [Milestone](milestones/index.md#m
which automatically filter the board issues accordingly.
This allows you to create unique boards according to your team's need.
-![Create scoped board](img/issue_board_creation.png)
+![Create scoped board](img/issue_board_creation_v13_6.png)
-You can define the scope of your board when creating it or by clicking the "Edit board" button.
-Once a milestone, assignee or weight is assigned to an issue board, you can no longer
+You can define the scope of your board when creating it or by clicking the **Edit board** button.
+After a milestone, assignee or weight is assigned to an issue board, you can no longer
filter through these in the search bar. In order to do that, you need to remove the desired scope
(for example, milestone, assignee, or weight) from the issue board.
-![Edit board configuration](img/issue_board_edit_button.png)
-
If you don't have editing permission in a board, you're still able to see the configuration by
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.
@@ -253,12 +249,8 @@ the Configurable Issue Board feature.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28597) to the Free tier of GitLab.com in 12.10.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212331) to GitLab Core in 13.0.
-Click the button at the top right to toggle focus mode on and off. In focus mode, the navigation UI
-is hidden, allowing you to focus on issues in the board.
-
-![Board focus mode](img/issue_board_focus_mode.gif)
-
----
+To enable or disable focus mode, select the **Toggle focus mode** button (**{maximize}**) at the top
+right. In focus mode, the navigation UI is hidden, allowing you to focus on issues in the board.
### Sum of issue weights **(STARTER)**
@@ -266,7 +258,7 @@ 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).
-![issue board summed weights](img/issue_board_summed_weights.png)
+![issue board summed weights](img/issue_board_summed_weights_v13_6.png)
### Group issue boards **(PREMIUM)**
@@ -279,8 +271,6 @@ group and its descendant subgroups. Similarly, you can only filter by group labe
boards. When updating milestones and labels for an issue through the sidebar update mechanism, again only
group-level objects are available.
-![Group issue board](img/group_issue_board.png)
-
### Assignee lists **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5784) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.0.
@@ -290,15 +280,15 @@ an assignee list that shows all issues assigned to a user.
You can have a board with both label lists and assignee lists. To add an
assignee list:
-1. Click **Add list**.
+1. Select the **Add list** dropdown button.
1. Select the **Assignee list** tab.
-1. Search and click the user you want to add as an assignee.
+1. Search and select the user you want to add as an assignee.
Now that the assignee list is added, you can assign or unassign issues to that user
by [dragging issues](#drag-issues-between-lists) to and from an assignee list.
To remove an assignee list, just as with a label list, click the trash icon.
-![Assignee lists](img/issue_board_assignee_lists.png)
+![Assignee lists](img/issue_board_assignee_lists_v13_6.png)
### Milestone lists **(PREMIUM)**
@@ -307,7 +297,7 @@ To remove an assignee list, just as with a label list, click the trash icon.
You're also able to create lists of a milestone. These are lists that filter issues by the assigned
milestone, giving you more freedom and visibility on the issue board. To add a milestone list:
-1. Click **Add list**.
+1. Select the **Add list** dropdown button.
1. Select the **Milestone** tab.
1. Search and click the milestone.
@@ -315,7 +305,31 @@ Like the assignee lists, you're able to [drag issues](#drag-issues-between-lists
to and from a milestone list to manipulate the milestone of the dragged issues.
As in other list types, click the trash icon to remove a list.
-![Milestone lists](img/issue_board_milestone_lists.png)
+![Milestone lists](img/issue_board_milestone_lists_v13_6.png)
+
+### Group issues in swimlanes **(PREMIUM)**
+
+> Grouping by epic [introduced](https://gitlab.com/groups/gitlab-org/-/epics/3352) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
+
+With swimlanes you can visualize issues grouped by epic.
+Your issue board keeps all the other features, but with a different visual organization of issues.
+This feature is available both at the project and group level.
+
+To group issues by epic in an issue board:
+
+1. Select the **Group by** dropdown button.
+1. Select **Epic**.
+
+![Epics Swimlanes](img/epics_swimlanes_v13.6.png)
+
+You can also [drag issues](#drag-issues-between-lists) to change their position and epic assignment:
+
+- To reorder an issue, drag it to the new position within a list.
+- To assign an issue to another epic, drag it to the epic's horizontal lane.
+- To unassign an issue from an epic, drag it to the **Issues with no epic assigned** lane.
+- To move an issue to another epic _and_ another list, at the same time, drag the issue diagonally.
+
+![Drag issues between swimlanes](img/epics_swimlanes_drag_and_drop.png)
## Work In Progress limits **(STARTER)**
@@ -347,7 +361,7 @@ To set a WIP limit for a list:
If an issue is blocked by another issue, an icon appears next to its title to indicate its blocked
status.
-![Blocked issues](img/issue_boards_blocked_icon_v12_8.png)
+![Blocked issues](img/issue_boards_blocked_icon_v13_6.png)
## Actions you can take on an issue board
@@ -381,16 +395,16 @@ have that label.
### Create a new list
-Create a new list by clicking the **Add list** button in the upper right corner of the issue board.
+Create a new list by clicking the **Add list** dropdown button in the upper right corner of the issue board.
-![creating a new list in an issue board](img/issue_board_add_list.png)
+![creating a new list in an issue board](img/issue_board_add_list_v13_6.png)
-Then, choose the label or user to create the list from. The new list is inserted
-at the end of the lists, before **Done**. Moving and reordering lists is as
-easy as dragging them around.
+Then, choose the label or user to base the new list on. The new list is inserted
+at the end of the lists, before **Done**. To move and reorder lists, drag them around.
To create a list for a label that doesn't yet exist, create the label by
-choosing **Create new label**. This creates the label immediately and adds it to the dropdown.
+choosing **Create project label** or **Create group label**.
+This creates the label immediately and adds it to the dropdown.
You can now choose it to create a list.
### Delete a list
@@ -404,14 +418,14 @@ list view that's removed. You can always restore it later if you need.
### Add issues to a list
You can add issues to a list by clicking the **Add issues** button
-present in the upper right corner of the issue board. This opens up a modal
+in the top right corner of the issue board. This opens up a modal
window where you can see all the issues that do not belong to any list.
Select one or more issues by clicking the cards and then click **Add issues**
to add them to the selected list. You can limit the issues you want to add to
the list by filtering by author, assignee, milestone, and label.
-![Bulk adding issues to lists](img/issue_boards_add_issues_modal.png)
+![Bulk adding issues to lists](img/issue_boards_add_issues_modal_v13_6.png)
### Remove an issue from a list
@@ -419,13 +433,13 @@ Removing an issue from a list can be done by clicking the issue card and then
clicking the **Remove from board** button in the sidebar. The
respective label is removed.
-![Remove issue from list](img/issue_boards_remove_issue.png)
+![Remove issue from list](img/issue_boards_remove_issue_v13_6.png)
### Filter issues
You should be able to use the filters on top of your issue board to show only
-the results you want. It's similar to the filtering used in the issue tracker
-since the metadata from the issues and labels are re-used in the issue board.
+the results you want. It's similar to the filtering used in the issue tracker,
+as the metadata from the issues and labels is re-used in the issue board.
You can filter by author, assignee, milestone, and label.
@@ -435,13 +449,13 @@ 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
-the lists as you create them. In addition, this means you can easily move
-something between lists by changing a label.
+the lists as you create them. In addition, this means you can move something between lists by
+changing a label.
A typical workflow of using an issue board would be:
1. You have [created](labels.md#label-management) and [prioritized](labels.md#label-priority)
- labels so that you can easily categorize your issues.
+ labels to categorize your issues.
1. You have a bunch of issues (ideally labeled).
1. You visit the issue board and start [creating lists](#create-a-new-list) to
create a workflow.
@@ -457,15 +471,15 @@ For example, you can create a list based on the label of **Frontend** and one fo
**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
+Then, when they're done, all they have to do is
drag it to the next list, **Backend**. Then, a backend developer can
-eventually pick it up. Once they’re done, they move it to **Done**, to close the
+eventually pick it up. When they’re done, they move it to **Done**, to close the
issue.
This process can be seen clearly when visiting an issue. With every move
to another list, the label changes and a system note is recorded.
-![issue board system notes](img/issue_board_system_notes.png)
+![issue board system notes](img/issue_board_system_notes_v13_6.png)
### Drag issues between lists
@@ -473,16 +487,17 @@ When dragging issues between lists, different behavior occurs depending on the s
| | To Open | To Closed | To label `B` list | To assignee `Bob` list |
|----------------------------|--------------------|--------------|------------------------------|---------------------------------------|
-| From Open | - | Issue closed | `B` added | `Bob` assigned |
-| From Closed | Issue reopened | - | Issue reopened<br/>`B` added | Issue reopened<br/>`Bob` assigned |
-| From label `A` list | `A` removed | Issue closed | `A` removed<br/>`B` added | `Bob` assigned |
-| From assignee `Alice` list | `Alice` unassigned | Issue closed | `B` added | `Alice` unassigned<br/>`Bob` assigned |
+| **From Open** | - | Issue closed | `B` added | `Bob` assigned |
+| **From Closed** | Issue reopened | - | Issue reopened<br/>`B` added | Issue reopened<br/>`Bob` assigned |
+| **From label `A` list** | `A` removed | Issue closed | `A` removed<br/>`B` added | `Bob` assigned |
+| **From assignee `Alice` list** | `Alice` unassigned | Issue closed | `B` added | `Alice` unassigned<br/>`Bob` assigned |
### Multi-select issue cards
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18954) in GitLab 12.4.
-You can select multiple issue cards, then drag the group to another position within the list, or to another list. This makes it faster to reorder many issues at once.
+You can select multiple issue cards, then drag the group to another position within the list, or to
+another list. This makes it faster to reorder many issues at once.
To select and move multiple cards:
diff --git a/doc/user/project/issues/csv_export.md b/doc/user/project/issues/csv_export.md
index af01534a67f..af9a6401474 100644
--- a/doc/user/project/issues/csv_export.md
+++ b/doc/user/project/issues/csv_export.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Export Issues to CSV
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1126) in [GitLab Starter 9.0](https://about.gitlab.com/releases/2017/03/22/gitlab-9-0-released/#export-issues-ees-eep).
diff --git a/doc/user/project/issues/csv_import.md b/doc/user/project/issues/csv_import.md
index 807f4fcffdf..2cac88b1b29 100644
--- a/doc/user/project/issues/csv_import.md
+++ b/doc/user/project/issues/csv_import.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Importing issues from CSV
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23532) in GitLab 11.7.
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index 6f57487fccd..c19c9ca0615 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -228,7 +228,7 @@ available in the **Resolved Comment** area at the bottom of the right sidebar.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/198439) in GitLab 13.4.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/245074) in GitLab 13.5.
-Add a to do for a design by clicking **Add a To Do** on the design sidebar:
+Add a to-do item for a design by clicking **Add a to do** on the design sidebar:
![To-do button](img/design_todo_button_v13_5.png)
diff --git a/doc/user/project/issues/img/adding_note_to_design_1.png b/doc/user/project/issues/img/adding_note_to_design_1.png
index aa50bbb69ce..3c25fcb1241 100644
--- a/doc/user/project/issues/img/adding_note_to_design_1.png
+++ b/doc/user/project/issues/img/adding_note_to_design_1.png
Binary files differ
diff --git a/doc/user/project/issues/img/adding_note_to_design_2.png b/doc/user/project/issues/img/adding_note_to_design_2.png
index 37cefeb1a15..c418a0364c0 100644
--- a/doc/user/project/issues/img/adding_note_to_design_2.png
+++ b/doc/user/project/issues/img/adding_note_to_design_2.png
Binary files differ
diff --git a/doc/user/project/issues/img/button_close_issue.png b/doc/user/project/issues/img/button_close_issue.png
deleted file mode 100644
index 05d257ce9bf..00000000000
--- a/doc/user/project/issues/img/button_close_issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/button_close_issue_v13_6.png b/doc/user/project/issues/img/button_close_issue_v13_6.png
new file mode 100644
index 00000000000..6c7f8da496b
--- /dev/null
+++ b/doc/user/project/issues/img/button_close_issue_v13_6.png
Binary files differ
diff --git a/doc/user/project/issues/img/closing_and_related_issues.png b/doc/user/project/issues/img/closing_and_related_issues.png
deleted file mode 100644
index c6543e85fdb..00000000000
--- a/doc/user/project/issues/img/closing_and_related_issues.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/confirm_design_deletion_v12_4.png b/doc/user/project/issues/img/confirm_design_deletion_v12_4.png
index 447d3907122..5631b6ec98e 100644
--- a/doc/user/project/issues/img/confirm_design_deletion_v12_4.png
+++ b/doc/user/project/issues/img/confirm_design_deletion_v12_4.png
Binary files differ
diff --git a/doc/user/project/issues/img/delete_multiple_designs_v12_4.png b/doc/user/project/issues/img/delete_multiple_designs_v12_4.png
index 75cbdf77c24..40d449d5b39 100644
--- a/doc/user/project/issues/img/delete_multiple_designs_v12_4.png
+++ b/doc/user/project/issues/img/delete_multiple_designs_v12_4.png
Binary files differ
diff --git a/doc/user/project/issues/img/delete_single_design_v12_4.png b/doc/user/project/issues/img/delete_single_design_v12_4.png
deleted file mode 100644
index 158b4949ce4..00000000000
--- a/doc/user/project/issues/img/delete_single_design_v12_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/design_drag_and_drop_uploads_v12_9.png b/doc/user/project/issues/img/design_drag_and_drop_uploads_v12_9.png
deleted file mode 100644
index 6680c792063..00000000000
--- a/doc/user/project/issues/img/design_drag_and_drop_uploads_v12_9.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/design_drag_and_drop_uploads_v13_2.png b/doc/user/project/issues/img/design_drag_and_drop_uploads_v13_2.png
index 25a02eef406..4ab5e184905 100644
--- a/doc/user/project/issues/img/design_drag_and_drop_uploads_v13_2.png
+++ b/doc/user/project/issues/img/design_drag_and_drop_uploads_v13_2.png
Binary files differ
diff --git a/doc/user/project/issues/img/design_management_v12_3.png b/doc/user/project/issues/img/design_management_v12_3.png
deleted file mode 100644
index b3647aa97c1..00000000000
--- a/doc/user/project/issues/img/design_management_v12_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/design_management_v13_2.png b/doc/user/project/issues/img/design_management_v13_2.png
index 6d7e03d6f20..3da11c92514 100644
--- a/doc/user/project/issues/img/design_management_v13_2.png
+++ b/doc/user/project/issues/img/design_management_v13_2.png
Binary files differ
diff --git a/doc/user/project/issues/img/design_zooming_v12_7.png b/doc/user/project/issues/img/design_zooming_v12_7.png
index 4acb4e10913..4966af06e41 100644
--- a/doc/user/project/issues/img/design_zooming_v12_7.png
+++ b/doc/user/project/issues/img/design_zooming_v12_7.png
Binary files differ
diff --git a/doc/user/project/issues/img/epic_tree_health_status_v12_10.png b/doc/user/project/issues/img/epic_tree_health_status_v12_10.png
deleted file mode 100644
index 1a603656fd8..00000000000
--- a/doc/user/project/issues/img/epic_tree_health_status_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/issue_health_status_v12_10.png b/doc/user/project/issues/img/issue_health_status_v12_10.png
deleted file mode 100644
index dd6becbb970..00000000000
--- a/doc/user/project/issues/img/issue_health_status_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/issue_health_status_v12_9.png b/doc/user/project/issues/img/issue_health_status_v12_9.png
deleted file mode 100644
index f8922a74fc1..00000000000
--- a/doc/user/project/issues/img/issue_health_status_v12_9.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue_from_open_issue.png b/doc/user/project/issues/img/new_issue_from_open_issue.png
deleted file mode 100644
index c6f3f0617ab..00000000000
--- a/doc/user/project/issues/img/new_issue_from_open_issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue_from_open_issue_v13_6.png b/doc/user/project/issues/img/new_issue_from_open_issue_v13_6.png
new file mode 100644
index 00000000000..902aa40614a
--- /dev/null
+++ b/doc/user/project/issues/img/new_issue_from_open_issue_v13_6.png
Binary files differ
diff --git a/doc/user/project/issues/img/reopen-issue.png b/doc/user/project/issues/img/reopen-issue.png
deleted file mode 100644
index fc48742afe0..00000000000
--- a/doc/user/project/issues/img/reopen-issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/report-abuse.png b/doc/user/project/issues/img/report-abuse.png
deleted file mode 100644
index f8cef22da03..00000000000
--- a/doc/user/project/issues/img/report-abuse.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/select_designs_v12_4.png b/doc/user/project/issues/img/select_designs_v12_4.png
index 532a79fce65..fe1c55a4ae2 100644
--- a/doc/user/project/issues/img/select_designs_v12_4.png
+++ b/doc/user/project/issues/img/select_designs_v12_4.png
Binary files differ
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index 434af3a4a49..716377f2e45 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -95,12 +95,13 @@ While you can view and manage the full details of an issue on the [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)**.
-Key actions for Issues include:
+Key actions for issues include:
- [Creating issues](managing_issues.md#create-a-new-issue)
- [Moving issues](managing_issues.md#moving-issues)
- [Closing issues](managing_issues.md#closing-issues)
- [Deleting issues](managing_issues.md#deleting-issues)
+- [Promoting issues](managing_issues.md#promote-an-issue-to-an-epic) **(PREMIUM)**
### Issue page
@@ -189,6 +190,8 @@ requires [GraphQL](../../../api/graphql/index.md) to be enabled.
> - [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.
+> - Issue health status visible in issue lists [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45141) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.6.
+
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:
@@ -201,7 +204,7 @@ that's progressing as planned or needs attention to keep on schedule:
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
+You can then see issue statuses in the [issue list](#issues-list) and the
[Epic tree](../../group/epics/index.md#issue-health-status-in-epic-tree).
#### Disable issue health status
diff --git a/doc/user/project/issues/issue_data_and_actions.md b/doc/user/project/issues/issue_data_and_actions.md
index 003444e0ed8..a5f60fbd515 100644
--- a/doc/user/project/issues/issue_data_and_actions.md
+++ b/doc/user/project/issues/issue_data_and_actions.md
@@ -18,7 +18,7 @@ You can find all the information for that issue on one screen.
![Issue view](img/issues_main_view_numbered.png)
-- **1.** [New Issue, close issue (reopen issue, report issue)](#new-issue-close-issue-reopen-issue-report-issue)
+- **1.** [Issue actions](#issue-actions)
- **2.** [To Do](#to-do)
- **3.** [Assignee](#assignee)
- **3.1.** [Multiple Assignees **(STARTER)**](#multiple-assignees)
@@ -55,22 +55,21 @@ Many of the elements of the issue screen refresh automatically, such as the titl
description, when they are changed by another user. Comments and system notes also
update automatically in response to various actions and content updates.
-### New Issue, close issue (reopen issue, report issue)
+### Issue actions
-Clicking on **New issue** will open a new window to create a new issue in the same project.
-Clicking on **Close issue** will close this issue, but it will not be deleted. If the
-issue is already closed, you can still access it and the button will show **Reopen issue**, as shown below,
-which you can click to reopen the issue. A reopened issue is no different from any
-other issue.
+In an open issue, you can close it by selecting the **Close issue** button.
+The issue is marked as closed but is not deleted.
-![Reopen Issue](img/reopen-issue.png)
+To reopen a closed issue, select the **Reopen issue** button.
+A reopened issue is no different from any other open issue.
-If you do not have rights to modify the issue, the **close issue** button will be
-replaced with **report issue**, which you can click to [submit an abuse report](../../abuse_reports.md)
-about the issue. It will also appear if you have rights to modify the issue, but only
-after it is closed.
+To access additional actions, select the vertical ellipsis
+(**{ellipsis_v}**) button:
-![Report Abuse](img/report-abuse.png)
+- To create a new issue in the same project, select **New issue** in the dropdown menu.
+
+- If you are not the issue author, you can [submit an abuse report](../../abuse_reports.md).
+ Select **Report abuse** in the dropdown menu.
### To Do
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index b033dc79dcc..62b388ec137 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -7,9 +7,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Managing issues
[GitLab Issues](index.md) are the fundamental medium for collaborating on ideas and
-planning work in GitLab. [Creating](#create-a-new-issue), [moving](#moving-issues),
-[closing](#closing-issues), and [deleting](#deleting-issues) are key actions that
-you can do with issues.
+planning work in GitLab.
+
+Key actions for issues include:
+
+- [Creating issues](#create-a-new-issue)
+- [Moving issues](#moving-issues)
+- [Closing issues](#closing-issues)
+- [Deleting issues](#deleting-issues)
+- [Promoting issues](#promote-an-issue-to-an-epic) **(PREMIUM)**
## Create a new issue
@@ -28,10 +34,10 @@ There are many ways to get to the New Issue form from within a project:
![New issue from the issue list view](img/new_issue_from_tracker_list.png)
-- From an **opened issue** in your project, click **New Issue** to create a new
- issue in the same project:
+- From an **open issue** in your project, click the vertical ellipsis (**{ellipsis_v}**) button
+ to open a dropdown menu, and then click **New Issue** to create a new issue in the same project:
- ![New issue from an open issue](img/new_issue_from_open_issue.png)
+ ![New issue from an open issue](img/new_issue_from_open_issue_v13_6.png)
- From your **Project's Dashboard**, click the plus sign (**+**) to open a dropdown
menu with a few options. Select **New Issue** to create an issue in that project:
@@ -178,7 +184,7 @@ end; nil
When you decide that an issue is resolved, or no longer needed, you can close the issue
using the close button:
-![close issue - button](img/button_close_issue.png)
+![close issue - button](img/button_close_issue_v13_6.png)
You can also close an issue from the [Issue Boards](../issue_board.md) by dragging an issue card
from its list and dropping it into the **Closed** list.
@@ -280,6 +286,23 @@ editing it and clicking on the delete button.
![delete issue - button](img/delete_issue.png)
+## Promote an issue to an epic **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3777) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) to [GitLab Premium](https://about.gitlab.com/pricing/) in 12.8.
+> - Promoting issues to epics via the UI [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233974) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
+
+You can promote an issue to an epic in the immediate parent group.
+
+To promote an issue to an epic:
+
+1. In an issue, select the vertical ellipsis (**{ellipsis_v}**) button.
+1. Select **Promote to epic**.
+
+Alternatively, you can use the `/promote` [quick action](../quick_actions.md#quick-actions-for-issues-merge-requests-and-epics).
+
+Read more about promoting an issue to an epic on the [Manage epics page](../../group/epics/manage_epics.md#promote-an-issue-to-an-epic).
+
## Add an issue to an iteration **(STARTER)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216158) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.2.
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index 4f0354f86af..c237f46b23a 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -95,6 +95,8 @@ If you delete a label, it is permanently deleted. All references to the label ar
#### Promote a project label to a group label
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/231472) in GitLab 13.6: promoting a project label keeps that label's ID and changes it into a group label. Previously, promoting a project label created a new group label with a new ID and deleted the old label.
+
If you previously created a project label and now want to make it available for other
projects within the same group, you can promote it to a group label.
@@ -105,6 +107,8 @@ also merged.
All issues, merge requests, issue board lists, issue board filters, and label subscriptions
with the old labels are assigned to the new group label.
+The new group label has the same ID as the previous project label.
+
CAUTION: **Caution:**
Promoting a label is a permanent action, and cannot be reversed.
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index d8579c4cd8e..c66103604ed 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Members of a project
You can manage the groups and users and their access levels in all of your
diff --git a/doc/user/project/members/share_project_with_groups.md b/doc/user/project/members/share_project_with_groups.md
index 033d69cbbfa..395f4353f47 100644
--- a/doc/user/project/members/share_project_with_groups.md
+++ b/doc/user/project/members/share_project_with_groups.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Share Projects with other Groups
You can share projects with other [groups](../../group/index.md). This makes it
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
index e03d4e99b86..d50056c9450 100644
--- a/doc/user/project/merge_requests/code_quality.md
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -265,6 +265,40 @@ Once the Code Quality job has completed:
[downloadable artifact](../../../ci/pipelines/job_artifacts.md#downloading-artifacts)
for the `code_quality` job.
+### Generating an HTML report
+
+In [GitLab 13.6 and later](https://gitlab.com/gitlab-org/ci-cd/codequality/-/issues/10),
+it is possible to generate an HTML report file by setting the `REPORT_FORMAT`
+variable to `html`. This is useful if you just want to view the report in a more
+human-readable format or to publish this artifact on GitLab Pages for even
+easier reviewing.
+
+```yaml
+include:
+ - template: Code-Quality.gitlab-ci.yml
+
+code_quality:
+ variables:
+ REPORT_FORMAT: html
+ artifacts:
+ paths: [gl-code-quality-report.html]
+```
+
+It's also possible to generate both JSON and HTML report files by defining
+another job and using `extends: code_quality`:
+
+```yaml
+include:
+ - template: Code-Quality.gitlab-ci.yml
+
+code_quality_html:
+ extends: code_quality
+ variables:
+ REPORT_FORMAT: html
+ artifacts:
+ paths: [gl-code-quality-report.html]
+```
+
## Extending functionality
### Using Analysis Plugins
@@ -314,7 +348,7 @@ This can be due to multiple reasons:
nothing will be displayed.
- The [`artifacts:expire_in`](../../../ci/yaml/README.md#artifactsexpire_in) CI/CD
setting can cause the Code Quality artifact(s) to expire faster than desired.
-- Large `codeclimate.json` files (esp. >10 MB) are [known to prevent the report from being displayed](https://gitlab.com/gitlab-org/gitlab/-/issues/2737).
+- Large `codeclimate.json` files (esp. >10 MB) are [known to prevent the report from being displayed](https://gitlab.com/gitlab-org/gitlab/-/issues/2737).
As a work-around, try removing [properties](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#data-types)
that are [ignored by GitLab](#implementing-a-custom-tool). You can:
- Configure the Code Quality tool to not output those types.
diff --git a/doc/user/project/merge_requests/csv_export.md b/doc/user/project/merge_requests/csv_export.md
new file mode 100644
index 00000000000..52c6f8a8d41
--- /dev/null
+++ b/doc/user/project/merge_requests/csv_export.md
@@ -0,0 +1,45 @@
+---
+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
+---
+
+# Export Merge Requests to CSV **(CORE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3619) in GitLab 13.6.
+
+Exporting Merge Requests CSV enables you and your team to export all the data collected from merge requests into a comma-separated values (CSV) file, which stores tabular data in plain text.
+
+To export Merge Requests to CSV, navigate to your **Merge Requests** from the sidebar of a project and click **Export to CSV**.
+
+## CSV Output
+
+The following table shows what attributes will be present in the CSV.
+
+| Column | Description |
+|--------------------|--------------------------------------------------------------|
+| MR ID | MR iid |
+| URL | A link to the merge request on GitLab |
+| Title | Merge request title |
+| State | Opened, Closed, Locked, or Merged |
+| Description | Merge request description |
+| Source Branch | Source branch |
+| Target Branch | Target branch |
+| Source Project ID | ID of the source project |
+| Target Project ID | ID of the target project |
+| Author | Full name of the merge request author |
+| Author Username | Username of the author, with the @ symbol omitted |
+| Assignees | Full names of the merge request assignees, joined with a `,` |
+| Assignee Usernames | Username of the assignees, with the @ symbol omitted |
+| Approvers | Full names of the approvers, joined with a `,` |
+| Approver Usernames | Username of the approvers, with the @ symbol omitted |
+| Merged User | Full name of the merged user |
+| Merged Username | Username of the merge user, with the @ symbol omitted |
+| Milestone ID | ID of the merge request milestone |
+| Created At (UTC) | Formatted as YYYY-MM-DD HH:MM:SS |
+| Updated At (UTC) | Formatted as YYYY-MM-DD HH:MM:SS |
+
+## Limitations
+
+- Export merge requests to CSV is not available at the Group’s merge request list.
+- As the merge request CSV file is sent as an email attachment, the size is limited to 15MB to ensure successful delivery across a range of email providers. If you need to minimize the size of the file, you can narrow the search before export. For example, you can set up exports of open and closed merge requests in separate files.
diff --git a/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png b/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png
deleted file mode 100644
index ed374b11fbd..00000000000
--- a/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/project_merge_requests_list_view.png b/doc/user/project/merge_requests/img/project_merge_requests_list_view.png
index 457716d811c..2c86a1ad839 100644
--- a/doc/user/project/merge_requests/img/project_merge_requests_list_view.png
+++ b/doc/user/project/merge_requests/img/project_merge_requests_list_view.png
Binary files differ
diff --git a/doc/user/project/merge_requests/load_performance_testing.md b/doc/user/project/merge_requests/load_performance_testing.md
index 2675f509eed..3ee88275aac 100644
--- a/doc/user/project/merge_requests/load_performance_testing.md
+++ b/doc/user/project/merge_requests/load_performance_testing.md
@@ -156,7 +156,7 @@ The best approach is to capture the dynamic URL in a [`.env` file](https://docs.
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`})``.
+such as: ``http.get(`${__ENV.ENVIRONMENT_URL}`)``.
For example:
diff --git a/doc/user/project/merge_requests/test_coverage_visualization.md b/doc/user/project/merge_requests/test_coverage_visualization.md
index bded1839f97..039f0f7d5e1 100644
--- a/doc/user/project/merge_requests/test_coverage_visualization.md
+++ b/doc/user/project/merge_requests/test_coverage_visualization.md
@@ -73,11 +73,11 @@ test:
cobertura: coverage/cobertura-coverage.xml
```
-### Java examples
+### Java and Kotlin examples
#### Maven example
-The following [`gitlab-ci.yml`](../../../ci/yaml/README.md) example for Java uses [Maven](https://maven.apache.org/)
+The following [`gitlab-ci.yml`](../../../ci/yaml/README.md) example for Java or Kotlin uses [Maven](https://maven.apache.org/)
to build the project and [Jacoco](https://www.eclemma.org/jacoco/) coverage-tooling to
generate the coverage artifact.
You can check the [Docker image configuration and scripts](https://gitlab.com/haynes/jacoco2cobertura) if you want to build your own image.
@@ -101,7 +101,7 @@ coverage-jdk11:
# The `visualize` stage does not exist by default.
# Please define it first, or chose an existing stage like `deploy`.
stage: visualize
- image: haynes/jacoco2cobertura:1.0.3
+ image: haynes/jacoco2cobertura:1.0.4
script:
# convert report from jacoco to cobertura
- 'python /opt/cover2cover.py target/site/jacoco/jacoco.xml src/main/java > target/site/cobertura.xml'
@@ -117,7 +117,7 @@ coverage-jdk11:
#### Gradle example
-The following [`gitlab-ci.yml`](../../../ci/yaml/README.md) example for Java uses [Gradle](https://gradle.org/)
+The following [`gitlab-ci.yml`](../../../ci/yaml/README.md) example for Java or Kotlin uses [Gradle](https://gradle.org/)
to build the project and [Jacoco](https://www.eclemma.org/jacoco/) coverage-tooling to
generate the coverage artifact.
You can check the [Docker image configuration and scripts](https://gitlab.com/haynes/jacoco2cobertura) if you want to build your own image.
@@ -141,7 +141,7 @@ coverage-jdk11:
# The `visualize` stage does not exist by default.
# Please define it first, or chose an existing stage like `deploy`.
stage: visualize
- image: haynes/jacoco2cobertura:1.0.3
+ image: haynes/jacoco2cobertura:1.0.4
script:
# convert report from jacoco to cobertura
- 'python /opt/cover2cover.py build/jacoco/jacoco.xml src/main/java > build/cobertura.xml'
diff --git a/doc/user/project/merge_requests/versions.md b/doc/user/project/merge_requests/versions.md
index 9581c974414..0922ffb2943 100644
--- a/doc/user/project/merge_requests/versions.md
+++ b/doc/user/project/merge_requests/versions.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference, concepts
---
diff --git a/doc/user/project/merge_requests/work_in_progress_merge_requests.md b/doc/user/project/merge_requests/work_in_progress_merge_requests.md
index e7abf6e5fb6..2218d38fdad 100644
--- a/doc/user/project/merge_requests/work_in_progress_merge_requests.md
+++ b/doc/user/project/merge_requests/work_in_progress_merge_requests.md
@@ -27,7 +27,7 @@ There are several ways to flag a merge request as a Draft:
description will have the same effect.
- **Deprecated** Add `[WIP]` or `WIP:` to the start of the merge request's title.
**WIP** still works but was deprecated in favor of **Draft**. It will be removed in the next major version (GitLab 14.0).
-- Add the `/wip` [quick action](../quick_actions.md#quick-actions-for-issues-merge-requests-and-epics)
+- Add the `/draft` (or `/wip`) [quick action](../quick_actions.md#quick-actions-for-issues-merge-requests-and-epics)
in a comment in the merge request. This is a toggle, and can be repeated
to change the status back. Note that any other text in the comment will be discarded.
- Add `draft:`, `Draft:`, `fixup!`, or `Fixup!` to the beginning of a commit message targeting the
@@ -43,7 +43,7 @@ Similar to above, when a Merge Request is ready to be merged, you can remove the
- Remove `[Draft]`, `Draft:` or `(Draft)` from the start of the merge request's title. Clicking on
**Remove the Draft: prefix from the title**, under the title box, when editing the merge
request's description, will have the same effect.
-- Add the `/wip` [quick action](../quick_actions.md#quick-actions-for-issues-merge-requests-and-epics)
+- Add the `/draft` (or `/wip`) [quick action](../quick_actions.md#quick-actions-for-issues-merge-requests-and-epics)
in a comment in the merge request. This is a toggle, and can be repeated
to change the status back. Note that any other text in the comment will be discarded.
- Click on the **Resolve Draft status** button near the bottom of the merge request description,
diff --git a/doc/user/project/milestones/burndown_and_burnup_charts.md b/doc/user/project/milestones/burndown_and_burnup_charts.md
index 327a52a05ab..ae03be5fa0f 100644
--- a/doc/user/project/milestones/burndown_and_burnup_charts.md
+++ b/doc/user/project/milestones/burndown_and_burnup_charts.md
@@ -9,18 +9,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w
[Burndown](#burndown-charts) and [burnup](#burnup-charts) charts show the progress of completing a milestone.
-![burndown and burnup chart](img/burndown_and_burnup_charts_v13_5.png)
+![burndown and burnup chart](img/burndown_and_burnup_charts_v13_6.png)
## Burndown charts
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1540) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.1 for project milestones.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5354) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.8 for group milestones.
> - [Added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6495) to [GitLab Starter](https://about.gitlab.com/pricing/) 11.2 for group milestones.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6903) [fixed burndown charts](#fixed-burndown-charts) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6903) [fixed burndown charts](#fixed-burndown-charts) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6.
Burndown charts show the number of issues over the course of a milestone.
-![burndown chart](img/burndown_chart_v13_5.png)
+![burndown chart](img/burndown_chart_v13_6.png)
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
@@ -81,12 +81,12 @@ cumulative value.
### Fixed burndown charts
-For milestones created before GitLab 13.5, burndown charts have an additional toggle to
+For milestones created before GitLab 13.6, burndown charts have an additional toggle to
switch between Legacy and Fixed views.
| Legacy | Fixed |
| ----- | ----- |
-| ![Legacy burndown chart, ](img/burndown_chart_legacy_v13_5.png) | ![Fixed burndown chart, showing a jump when a lot of issues were added to the milestone](img/burndown_chart_fixed_v13_5.png) |
+| ![Legacy burndown chart](img/burndown_chart_legacy_v13_6.png) | ![Fixed burndown chart, showing a jump when a lot of issues were added to the milestone](img/burndown_chart_fixed_v13_6.png) |
**Fixed burndown** charts track the full history of milestone activity, from its creation until the
milestone expires. After the milestone due date passes, issues removed from the milestone no longer
@@ -103,11 +103,18 @@ Reopened issues are considered as having been opened on the day after they were
## Burnup charts
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6903) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6903) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6.
+> - 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-burnup-charts). **(STARTER ONLY)**
+
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
Burnup charts show the assigned and completed work for a milestone.
-![burnup chart](img/burnup_chart_v13_5.png)
+![burnup chart](img/burnup_chart_v13_6.png)
To view a project's burnup chart:
@@ -129,6 +136,25 @@ Burnup charts can show either the total number of issues or total weight for eac
day of the milestone. Use the toggle above the charts to switch between total
and weight.
+### Enable or disable burnup charts **(STARTER ONLY)**
+
+Burnup charts 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(:burnup_charts)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:burnup_charts)
+```
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/project/milestones/burndown_charts.md b/doc/user/project/milestones/burndown_charts.md
index 5aa5534dd37..5d9e6b67bb8 100644
--- a/doc/user/project/milestones/burndown_charts.md
+++ b/doc/user/project/milestones/burndown_charts.md
@@ -2,4 +2,4 @@
redirect_to: './burndown_and_burnup_charts.md'
---
-This document was moved to [another location](./burndown_and_burnup_charts.md).
+This document was moved to [another location](burndown_and_burnup_charts.md).
diff --git a/doc/user/project/milestones/img/burndown_and_burnup_charts_v13_5.png b/doc/user/project/milestones/img/burndown_and_burnup_charts_v13_6.png
index 8d6ba1d4fa7..8d6ba1d4fa7 100644
--- a/doc/user/project/milestones/img/burndown_and_burnup_charts_v13_5.png
+++ b/doc/user/project/milestones/img/burndown_and_burnup_charts_v13_6.png
Binary files differ
diff --git a/doc/user/project/milestones/img/burndown_chart_fixed_v13_5.png b/doc/user/project/milestones/img/burndown_chart_fixed_v13_6.png
index a532bfeeca0..a532bfeeca0 100644
--- a/doc/user/project/milestones/img/burndown_chart_fixed_v13_5.png
+++ b/doc/user/project/milestones/img/burndown_chart_fixed_v13_6.png
Binary files differ
diff --git a/doc/user/project/milestones/img/burndown_chart_legacy_v13_5.png b/doc/user/project/milestones/img/burndown_chart_legacy_v13_6.png
index 5824fc59ce5..5824fc59ce5 100644
--- a/doc/user/project/milestones/img/burndown_chart_legacy_v13_5.png
+++ b/doc/user/project/milestones/img/burndown_chart_legacy_v13_6.png
Binary files differ
diff --git a/doc/user/project/milestones/img/burndown_chart_v13_5.png b/doc/user/project/milestones/img/burndown_chart_v13_6.png
index e06b24f9907..e06b24f9907 100644
--- a/doc/user/project/milestones/img/burndown_chart_v13_5.png
+++ b/doc/user/project/milestones/img/burndown_chart_v13_6.png
Binary files differ
diff --git a/doc/user/project/milestones/img/burnup_chart_v13_5.png b/doc/user/project/milestones/img/burnup_chart_v13_6.png
index a850caba348..a850caba348 100644
--- a/doc/user/project/milestones/img/burnup_chart_v13_5.png
+++ b/doc/user/project/milestones/img/burnup_chart_v13_6.png
Binary files differ
diff --git a/doc/user/project/milestones/img/milestones_new_group_milestone.png b/doc/user/project/milestones/img/milestones_new_group_milestone.png
index a517f0f7537..5bbe8e51f23 100644
--- a/doc/user/project/milestones/img/milestones_new_group_milestone.png
+++ b/doc/user/project/milestones/img/milestones_new_group_milestone.png
Binary files differ
diff --git a/doc/user/project/milestones/img/milestones_new_project_milestone.png b/doc/user/project/milestones/img/milestones_new_project_milestone.png
index 482c73f6568..2d0bdce542d 100644
--- a/doc/user/project/milestones/img/milestones_new_project_milestone.png
+++ b/doc/user/project/milestones/img/milestones_new_project_milestone.png
Binary files differ
diff --git a/doc/user/project/milestones/img/milestones_project_milestone_page.png b/doc/user/project/milestones/img/milestones_project_milestone_page.png
index c17bf350aeb..1faaf0b3979 100644
--- a/doc/user/project/milestones/img/milestones_project_milestone_page.png
+++ b/doc/user/project/milestones/img/milestones_project_milestone_page.png
Binary files differ
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index 8cbed3de1c6..9c47f15cb8f 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -150,7 +150,7 @@ There are also tabs below these that show the following:
For project 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.
-![burndown chart](img/burndown_chart_v13_5.png)
+![burndown chart](img/burndown_chart_v13_6.png)
### Group Burndown Charts **(STARTER)**
diff --git a/doc/user/project/operations/img/alert_issue_v13_1.png b/doc/user/project/operations/img/alert_issue_v13_1.png
deleted file mode 100644
index da79074aa2f..00000000000
--- a/doc/user/project/operations/img/alert_issue_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/operations/img/error_details_v12_5.png b/doc/user/project/operations/img/error_details_v12_5.png
deleted file mode 100644
index f4866141948..00000000000
--- a/doc/user/project/operations/img/error_details_v12_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/operations/img/error_details_v12_6.png b/doc/user/project/operations/img/error_details_v12_6.png
deleted file mode 100644
index 3194d8284d7..00000000000
--- a/doc/user/project/operations/img/error_details_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/operations/img/error_details_with_issue_v12_6.png b/doc/user/project/operations/img/error_details_with_issue_v12_6.png
deleted file mode 100644
index 963b70bd1e4..00000000000
--- a/doc/user/project/operations/img/error_details_with_issue_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/operations/img/error_details_with_issue_v12_7.png b/doc/user/project/operations/img/error_details_with_issue_v12_7.png
deleted file mode 100644
index aa846ee7220..00000000000
--- a/doc/user/project/operations/img/error_details_with_issue_v12_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/operations/img/feature_flags_list_v12_7.png b/doc/user/project/operations/img/feature_flags_list_v12_7.png
deleted file mode 100644
index a28a844b46d..00000000000
--- a/doc/user/project/operations/img/feature_flags_list_v12_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/operations/img/specs_list_v12_6.png b/doc/user/project/operations/img/specs_list_v12_6.png
deleted file mode 100644
index ea429802a40..00000000000
--- a/doc/user/project/operations/img/specs_list_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/packages/img/maven_package_view.png b/doc/user/project/packages/img/maven_package_view.png
deleted file mode 100644
index 2eb4b6f76b4..00000000000
--- a/doc/user/project/packages/img/maven_package_view.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/packages/img/npm_package_view.png b/doc/user/project/packages/img/npm_package_view.png
deleted file mode 100644
index e0634718c02..00000000000
--- a/doc/user/project/packages/img/npm_package_view.png
+++ /dev/null
Binary files differ
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 a7eb4c4019f..e030326ac5f 100644
--- a/doc/user/project/pages/getting_started/pages_from_scratch.md
+++ b/doc/user/project/pages/getting_started/pages_from_scratch.md
@@ -158,9 +158,12 @@ When it succeeds, go to **Settings > Pages** to view the URL where your site
is now available.
If you want to do more advanced tasks, you can update your `.gitlab-ci.yml` file
-with [any of the available settings](../../../../ci/yaml/README.md). See
-[Validate the `.gitlab-ci.yml`](../../../../ci/yaml/README.md#validate-the-gitlab-ciyml)
-for instructions on validating your YAML file with the Lint tool included with GitLab.
+with [any of the available settings](../../../../ci/yaml/README.md). You can validate
+your `.gitlab-ci.yml` file with the [CI Lint](../../../../ci/lint.md) tool that's included with GitLab.
+
+After successful execution of this `pages` job, a special `pages:deploy` job appears in the
+pipeline view. It prepares the content of the website for GitLab Pages daemon. GitLab executes it in
+the background and doesn't use runner.
The following topics show other examples of other options you can add to your CI/CD file.
diff --git a/doc/user/project/pages/img/icons/click.png b/doc/user/project/pages/img/icons/click.png
deleted file mode 100644
index 62a997a7591..00000000000
--- a/doc/user/project/pages/img/icons/click.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/img/icons/cogs.png b/doc/user/project/pages/img/icons/cogs.png
deleted file mode 100644
index f37f8f361d1..00000000000
--- a/doc/user/project/pages/img/icons/cogs.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/img/icons/fork.png b/doc/user/project/pages/img/icons/fork.png
deleted file mode 100644
index 1ae8fa722b7..00000000000
--- a/doc/user/project/pages/img/icons/fork.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/img/icons/free.png b/doc/user/project/pages/img/icons/free.png
deleted file mode 100644
index c74cd90fa1a..00000000000
--- a/doc/user/project/pages/img/icons/free.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/img/icons/monitor.png b/doc/user/project/pages/img/icons/monitor.png
deleted file mode 100644
index ce27b7e177e..00000000000
--- a/doc/user/project/pages/img/icons/monitor.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/img/pages_workflow_v12_5.png b/doc/user/project/pages/img/pages_workflow_v12_5.png
deleted file mode 100644
index ca5190fca79..00000000000
--- a/doc/user/project/pages/img/pages_workflow_v12_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index 4f389716f08..f5cd6991869 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -29,7 +29,7 @@ directly from a repository in GitLab.
</ul>
</p>
</div>
-<div class="col-md-3"><img src="img/ssgs_pages.png" alt="Examples of SSGs supported by Pages" class="image-noshadow middle display-block"></div>
+<div class="col-md-3"><img src="img/ssgs_pages.png" alt="Examples of SSGs supported by Pages" class="middle display-block"></div>
</div>
To publish a website with Pages, you can use any SSG,
@@ -89,7 +89,7 @@ need admin access to your domain's registrar (or control panel) to set it up wit
The following diagrams show the workflows you might follow to get started with Pages.
-<img src="img/new_project_for_pages_v12_5.png" alt="New projects for GitLab Pages" class="image-noshadow">
+<img src="img/new_project_for_pages_v12_5.png" alt="New projects for GitLab Pages">
## Access to your Pages site
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index b97d5328c07..6dbc12cc2ec 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -11,7 +11,7 @@ GitLab Pages offers.
To familiarize yourself with GitLab Pages first:
-- Read an [introduction to GitLab Pages](index.md#overview).
+- Read an [introduction to GitLab Pages](index.md).
- Learn [how to get started with Pages](index.md#getting-started).
- Learn how to enable GitLab Pages
across your GitLab instance on the [administrator documentation](../../../administration/pages/index.md).
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 02d1dd7898a..13ea57939f8 100644
--- a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
+++ b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
@@ -1,4 +1,7 @@
---
+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
description: "How to secure GitLab Pages websites with Let's Encrypt (manual process, deprecated)."
---
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 2f1b05f481e..46db7293711 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -40,6 +40,7 @@ The following quick actions are applicable to descriptions, discussions and thre
| `/copy_metadata <#issue>` | ✓ | ✓ | | Copy labels and milestone from another issue in the project. |
| `/create_merge_request <branch name>` | ✓ | | | Create a new merge request starting from the current issue. |
| `/done` | ✓ | ✓ | ✓ | Mark to do as done. |
+| `/draft` | | ✓ | | Toggle the draft status. |
| `/due <date>` | ✓ | | | Set due date. Examples of valid `<date>` include `in 2 days`, `this Friday` and `December 31st`. |
| `/duplicate <#issue>` | ✓ | | | Close this issue and mark as a duplicate of another issue. **(CORE)** Also, mark both as related. **(STARTER)** |
| `/epic <epic>` | ✓ | | | Add to epic `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic. **(PREMIUM)** |
@@ -74,7 +75,7 @@ The following quick actions are applicable to descriptions, discussions and thre
| `/tableflip <comment>` | ✓ | ✓ | ✓ | Append the comment with `(╯°□°)╯︵ â”»â”â”»`. |
| `/target_branch <local branch name>` | | ✓ | | Set target branch. |
| `/title <new title>` | ✓ | ✓ | ✓ | Change title. |
-| `/todo` | ✓ | ✓ | ✓ | Add a to do. |
+| `/todo` | ✓ | ✓ | ✓ | Add a to-do item. |
| `/unassign @user1 @user2` | ✓ | ✓ | | Remove specific assignees. **(STARTER)** |
| `/unassign` | ✓ | ✓ | | Remove all assignees. |
| `/unlabel ~label1 ~label2` or `/remove_label ~label1 ~label2` | ✓ | ✓ | ✓ | Remove specified labels. |
@@ -82,7 +83,7 @@ The following quick actions are applicable to descriptions, discussions and thre
| `/unlock` | ✓ | ✓ | | Unlock the discussions. |
| `/unsubscribe` | ✓ | ✓ | ✓ | Unsubscribe from notifications. |
| `/weight <value>` | ✓ | | | Set weight. Valid options for `<value>` include `0`, `1`, `2`, and so on. **(STARTER)** |
-| `/wip` | | ✓ | | Toggle the Work In Progress status. |
+| `/wip` | | ✓ | | Toggle the draft status. |
| `/zoom <Zoom URL>` | ✓ | | | Add Zoom meeting to this issue ([introduced in GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16609)). |
## Autocomplete characters
diff --git a/doc/user/project/releases/img/edit_release_page_v12_10.png b/doc/user/project/releases/img/edit_release_page_v12_10.png
deleted file mode 100644
index ebb12a549b7..00000000000
--- a/doc/user/project/releases/img/edit_release_page_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/releases/img/edit_release_page_v12_6.png b/doc/user/project/releases/img/edit_release_page_v12_6.png
deleted file mode 100644
index ae7641ac8a5..00000000000
--- a/doc/user/project/releases/img/edit_release_page_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/releases/img/release_with_milestone_v12_5.png b/doc/user/project/releases/img/release_with_milestone_v12_5.png
deleted file mode 100644
index 2a7a2ee9754..00000000000
--- a/doc/user/project/releases/img/release_with_milestone_v12_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/releases/img/releases.png b/doc/user/project/releases/img/releases.png
deleted file mode 100644
index da5bcd9d913..00000000000
--- a/doc/user/project/releases/img/releases.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/releases/img/releases_count_v12_8.png b/doc/user/project/releases/img/releases_count_v12_8.png
deleted file mode 100644
index e70f623d508..00000000000
--- a/doc/user/project/releases/img/releases_count_v12_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/releases/img/releases_sort_v13_6.png b/doc/user/project/releases/img/releases_sort_v13_6.png
new file mode 100644
index 00000000000..e663e3cc7f3
--- /dev/null
+++ b/doc/user/project/releases/img/releases_sort_v13_6.png
Binary files differ
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index 962d612cac1..674fe8b22b8 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -43,6 +43,13 @@ To view a list of releases:
- On private projects, this number is visible to users with Reporter
[permissions](../../permissions.md#project-members-permissions) or higher.
+### Sort Releases
+
+On the top right of the **Releases** page, you can use the sorting button to order releases by
+**Released date** or **Created date**. You can sort releases in ascending or descending order.
+
+![Sort Releases dropdown button](img/releases_sort_v13_6.png)
+
## Create a release
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32812) in GitLab 12.9. Releases can be created directly in the GitLab UI.
@@ -130,6 +137,8 @@ In the interface, to add release notes to an existing Git tag:
You can associate a release with one or more [project milestones](../milestones/index.md#project-milestones-and-group-milestones).
+[GitLab Premium](https://about.gitlab.com/pricing/) customers can specify [group milestones](../milestones/index.md#project-milestones-and-group-milestones) to associate with a release.
+
You can do this in the user interface, or by including a `milestones` array in your request to
the [Releases API](../../../api/releases/index.md#create-a-release).
@@ -446,17 +455,17 @@ In the API:
- If you do not specify a `released_at` date, release evidence is collected on the
date the release is created.
-## GitLab Releaser
+## Release Command Line
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-releaser/-/merge_requests/6) in GitLab 12.10.
+> [Introduced](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/6) in GitLab 12.10.
-GitLab Releaser is a CLI tool for managing GitLab Releases from the command line or from
+The Release CLI is a command-line tool for managing GitLab Releases from the command line or from
GitLab's CI/CD configuration file, `.gitlab-ci.yml`.
With it, you can create, update, modify, and delete releases right through the
terminal.
-Read the [GitLab Releaser documentation](https://gitlab.com/gitlab-org/gitlab-releaser/-/tree/master/docs/index.md)
+Read the [Release CLI documentation](https://gitlab.com/gitlab-org/release-cli/-/blob/master/docs/index.md)
for details.
<!-- ## Troubleshooting
diff --git a/doc/user/project/repository/branches/img/compare_branches.png b/doc/user/project/repository/branches/img/compare_branches.png
index 52d5c518c45..e6f88da4989 100644
--- a/doc/user/project/repository/branches/img/compare_branches.png
+++ b/doc/user/project/repository/branches/img/compare_branches.png
Binary files differ
diff --git a/doc/user/project/repository/img/file_ext_icons_repo_v12_10.png b/doc/user/project/repository/img/file_ext_icons_repo_v12_10.png
index 346f0e58325..04a8f38871b 100644
--- a/doc/user/project/repository/img/file_ext_icons_repo_v12_10.png
+++ b/doc/user/project/repository/img/file_ext_icons_repo_v12_10.png
Binary files differ
diff --git a/doc/user/project/repository/img/repository_mirroring_push_settings.png b/doc/user/project/repository/img/repository_mirroring_push_settings.png
index 9fc25dd3b25..8916d21d515 100644
--- a/doc/user/project/repository/img/repository_mirroring_push_settings.png
+++ b/doc/user/project/repository/img/repository_mirroring_push_settings.png
Binary files differ
diff --git a/doc/user/project/repository/jupyter_notebooks/index.md b/doc/user/project/repository/jupyter_notebooks/index.md
index fe432e0d553..69a32841981 100644
--- a/doc/user/project/repository/jupyter_notebooks/index.md
+++ b/doc/user/project/repository/jupyter_notebooks/index.md
@@ -22,8 +22,8 @@ GitLab.
## Jupyter Hub as a GitLab Managed App
-You can deploy [Jupyter Hub as a GitLab managed app](./../../../clusters/applications.md#jupyterhub).
+You can deploy [Jupyter Hub as a GitLab managed app](../../../clusters/applications.md#jupyterhub).
## Jupyter Git integration
-Find out how to [leverage JupyterLab’s Git extension on your Kubernetes cluster](./../../../clusters/applications.md#jupyter-git-integration).
+Find out how to [leverage JupyterLab’s Git extension on your Kubernetes cluster](../../../clusters/applications.md#jupyter-git-integration).
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 ad79fd8a8f9..9f4dfe54c47 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
@@ -18,7 +18,7 @@ We **recommend [`git filter-repo`](https://github.com/newren/git-filter-repo/blo
over [`git filter-branch`](https://git-scm.com/docs/git-filter-branch) and
[BFG](https://rtyley.github.io/bfg-repo-cleaner/).
-DANGER: **Danger:**
+DANGER: **Warning:**
Rewriting repository history is a destructive operation. Make sure to back up your repository before
you begin. The best way back up a repository is to
[export the project](../settings/import_export.md#exporting-a-project-and-its-data).
@@ -202,6 +202,12 @@ To purge files from GitLab storage:
## Repository cleanup
+NOTE: **Note:**
+Safely cleaning the repository requires it to be made read-only for the duration
+of the operation. This happens automatically, but submitting the cleanup request
+will fail if any writes are ongoing, so cancel any outstanding `git push`
+operations before continuing.
+
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/19376) in GitLab 11.6.
Repository cleanup allows you to upload a text file of objects and GitLab will remove internal Git
diff --git a/doc/user/project/repository/repository_mirroring.md b/doc/user/project/repository/repository_mirroring.md
index 188699e0c77..1f9835f4f59 100644
--- a/doc/user/project/repository/repository_mirroring.md
+++ b/doc/user/project/repository/repository_mirroring.md
@@ -577,3 +577,7 @@ Should an error occur during a push, GitLab will display an "Error" highlight fo
### 13:Received RST_STREAM with error code 2 with GitHub
If you receive an "13:Received RST_STREAM with error code 2" while mirroring to a GitHub repository, your GitHub settings might be set to block pushes that expose your email address used in commits. Either set your email address on GitHub to be public, or disable the [Block command line pushes that expose my email](https://github.com/settings/emails) setting.
+
+### 4:Deadline Exceeded
+
+When upgrading to GitLab 11.11.8 or newer, a change in how usernames are represented means that you may need to update your mirroring username and password to ensure that `%40` characters are replaced with `@`.
diff --git a/doc/user/project/repository/web_editor.md b/doc/user/project/repository/web_editor.md
index af0daaaeca2..5b82cdbd9e9 100644
--- a/doc/user/project/repository/web_editor.md
+++ b/doc/user/project/repository/web_editor.md
@@ -29,6 +29,11 @@ When you are satisfied with your new file, click **Commit Changes** at the botto
![Create file editor](img/web_editor_new_file_editor.png)
+### Shortcuts
+
+You can use handy shortcuts when editing a file through the Web Editor, which are the same as
+the WEB IDE's. For details, see the documentation for [Command Palette](../web_ide/index.md#command-palette).
+
### Template dropdowns
When starting a new project, there are some common files that the new project
@@ -107,7 +112,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. This project will no longer be able to receive or send merge requests to the source project or other forks.
![Create Button](img/web_editor_new_branch_from_issue_create_button_v12_6.png)
diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md
index 0a1b81a6359..34a075df990 100644
--- a/doc/user/project/service_desk.md
+++ b/doc/user/project/service_desk.md
@@ -76,7 +76,7 @@ Follow these steps to do so:
address's format. The older format is still supported, however, allowing existing aliases or
contacts to continue working.
- DANGER: **Danger:**
+ DANGER: **Warning:**
This email address can be used by anyone to create an issue on this project, whether or not they
have access to your GitLab instance. We recommend **putting this behind an alias** so it can be
changed if needed, and **[enabling Akismet](../../integration/akismet.md)** on your GitLab
@@ -99,7 +99,7 @@ navigation's **Issues** menu.
When a user submits a new issue using Service Desk, or when a new note is created on a Service Desk issue, an email is sent to the author.
-The body of these email messages can customized by using templates. To create a new customized template,
+The body of these email messages can be customized by using templates. To create a new customized template,
create a new Markdown (`.md`) file inside the `.gitlab/service_desk_templates/`
directory in your repository. Commit and push to your default branch.
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 478d9b3b948..3e493f02392 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -1,6 +1,6 @@
---
-stage: Create
-group: Source Code
+stage: Manage
+group: Import
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: reference, howto
---
@@ -32,6 +32,9 @@ To set up a project import/export:
Note the following:
+- Before you can import a project, you need to export the data first.
+ See [Exporting a project and its data](#exporting-a-project-and-its-data)
+ for how you can export a project through the UI.
- Imports from a newer version of GitLab are not supported.
The Importing GitLab version must be greater than or equal to the Exporting GitLab version.
- Imports will fail unless the import and export GitLab instances are
@@ -41,7 +44,7 @@ Note the following:
- Group members are exported as project members, as long as the user has
maintainer or admin access to the group where the exported project lives.
- Project members with owner access will be imported as maintainers.
-- Using an admin account to import will map users by primary email address (self-managed only).
+- Imported users can be mapped by their primary email on self-managed instances, if an administrative user (not an owner) does the import.
Otherwise, a supplementary comment is left to mention that the original author and
the MRs, notes, or issues will be owned by the importer.
- If an imported project contains merge requests originating from forks,
@@ -129,6 +132,11 @@ For more details on the specific data persisted in a project export, see the
## Exporting a project and its data
+Full project export functionality is limited to project maintainers and owners.
+You can configure such functionality through [project settings](index.md):
+
+To export a project and its data, follow these steps:
+
1. Go to your project's homepage.
1. Click **Settings** in the sidebar.
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index 8fdcf58b5aa..4b368fc20d6 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -72,6 +72,7 @@ Use the switches to enable or disable the following features:
| **Snippets** | ✓ | Enables [sharing of code and text](../../snippets.md) |
| **Pages** | ✓ | Allows you to [publish static websites](../pages/) |
| **Metrics Dashboard** | ✓ | Control access to [metrics dashboard](../integrations/prometheus.md)
+| **Requirements** | ✓ | Control access to [Requirements Management](../requirements/index.md)
Some features depend on others:
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index b6ce21ebea6..9f8cf2ff41a 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -54,7 +54,7 @@ Furthermore, the bot user can not be added to any other project.
When the project access token is [revoked](#revoking-a-project-access-token) the bot user is then deleted and all records are moved to a system-wide user with the username "Ghost User". For more information, see [Associated Records](../../profile/account/delete_account.md#associated-records).
-Project bot users are [GitLab-created service accounts](../../../subscriptions/self_managed/index.md#choose-the-number-of-users) and do not count as licensed seats.
+Project bot users are [GitLab-created service accounts](../../../subscriptions/self_managed/index.md#billable-users) and do not count as licensed seats.
## 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 8a2f62ec7a2..e58667c275c 100644
--- a/doc/user/project/static_site_editor/index.md
+++ b/doc/user/project/static_site_editor/index.md
@@ -80,6 +80,7 @@ codebase.
## Edit content
> - Support for modifying the default merge request title and description [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216861) in GitLab 13.5.
+> - Support for selecting a merge request template [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263252) in GitLab 13.6.
After setting up your project, you can start editing content directly from the Static Site Editor.
@@ -91,7 +92,9 @@ To edit a file:
wish to edit the raw Markdown instead, you can toggle the **Markdown** mode
in the bottom-right corner.
1. When you're done, click **Submit changes...**.
-1. (Optional) Adjust the default title and description of the merge request that will be submitted with your changes.
+1. (Optional) Adjust the default title and description of the merge request that will be submitted
+ with your changes. Alternatively, select a [merge request template](../../../user/project/description_templates.md#creating-merge-request-templates)
+ from the dropdown menu and edit it accordingly.
1. Click **Submit changes**.
1. A new merge request is automatically created and you can assign a colleague for review.
@@ -104,13 +107,36 @@ The Static Site Editors supports Markdown files (`.md`, `.md.erb`) for editing t
### Images
> - Support for adding images through the WYSIWYG editor [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216640) in GitLab 13.1.
+> - Support for uploading images via the WYSIWYG editor [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218529) in GitLab 13.6.
-You can add image files on the WYSIWYG mode by clicking the image icon (**{doc-image}**).
-From there, link to a URL, add optional [ALT text](https://moz.com/learn/seo/alt-text),
-and you're done. The link can reference images already hosted in your project, an asset hosted
+#### Upload an image
+
+You can upload image files via the WYSIWYG editor directly to the repository to default upload directory
+`source/images`. To do so:
+
+1. Click the image icon (**{doc-image}**).
+1. Choose the **Upload file** tab.
+1. Click **Choose file** to select a file from your computer.
+1. Optional: add a description to the image for SEO and accessibility ([ALT text](https://moz.com/learn/seo/alt-text)).
+1. Click **Insert image**.
+
+The selected file can be any supported image file (`.png`, `.jpg`, `.jpeg`, `.gif`). The editor renders
+thumbnail previews so you can verify the correct image is included and there aren't any references to
+missing images.
+
+#### Link to an image
+
+You can also link to an image if you'd like:
+
+1. Click the image icon (**{doc-image}**).
+1. Choose the **Link to an image** tab.
+1. Add the link to the image into the **Image URL** field (use the full path; relative paths are not supported yet).
+1. Optional: add a description to the image for SEO and accessibility ([ALT text](https://moz.com/learn/seo/alt-text)).
+1. Click **Insert image**.
+
+The link can reference images already hosted in your project, an asset hosted
externally on a content delivery network, or any other external URL. The editor renders thumbnail previews
so you can verify the correct image is included and there aren't any references to missing images.
-default directory (`source/images/`).
### Videos
diff --git a/doc/user/project/web_ide/img/command_palette_v13_6.png b/doc/user/project/web_ide/img/command_palette_v13_6.png
new file mode 100644
index 00000000000..54580a79ebd
--- /dev/null
+++ b/doc/user/project/web_ide/img/command_palette_v13_6.png
Binary files differ
diff --git a/doc/user/project/web_ide/img/commit_changes_v12_9.png b/doc/user/project/web_ide/img/commit_changes_v12_9.png
index d26c9cc82e1..9a8bb214b3d 100644
--- a/doc/user/project/web_ide/img/commit_changes_v12_9.png
+++ b/doc/user/project/web_ide/img/commit_changes_v12_9.png
Binary files differ
diff --git a/doc/user/project/web_ide/img/dark_theme_v13_0.png b/doc/user/project/web_ide/img/dark_theme_v13_0.png
index f1999363904..020578a9444 100644
--- a/doc/user/project/web_ide/img/dark_theme_v13_0.png
+++ b/doc/user/project/web_ide/img/dark_theme_v13_0.png
Binary files differ
diff --git a/doc/user/project/web_ide/img/solarized_light_theme_v13_0.png b/doc/user/project/web_ide/img/solarized_light_theme_v13_0.png
index adf6d3c6b02..b4b14f1fc7f 100644
--- a/doc/user/project/web_ide/img/solarized_light_theme_v13_0.png
+++ b/doc/user/project/web_ide/img/solarized_light_theme_v13_0.png
Binary files differ
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index 4da9b5f88ff..2b9db1c952d 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, how-to
---
-# Web IDE
+# Web IDE **(CORE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4539) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44157) to GitLab Core in 10.7.
@@ -25,9 +25,25 @@ and from merge requests.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18323) in [GitLab Core](https://about.gitlab.com/pricing/) 10.8.
The file finder allows you to quickly open files in the current branch by
-searching. The file finder is launched using the keyboard shortcut `Command-p`,
-`Control-p`, or `t` (when editor is not in focus). Type the filename or
-file path fragments to start seeing results.
+searching for fragments of the file path. The file finder is launched using the keyboard shortcut
+<kbd>Cmd</kbd>+<kbd>p</kbd>, <kbd>Ctrl</kbd>+<kbd>p</kbd>, or <kbd>t</kbd>
+(when editor is not in focus). Type the filename or file path fragments to
+start seeing results.
+
+## Command palette
+
+You can see all available commands for manipulating editor content by pressing
+the <kbd>F1</kbd> key when the editor is in focus. After that,
+you'll see a complete list of available commands for
+manipulating editor content. The editor supports commands for multi-cursor
+editing, code block folding, commenting, searching and replacing, navigating
+editor warnings and suggestions, and more.
+
+Some commands have a keyboard shortcut assigned to them. The command palette
+displays this shortcut next to each command. You can use this shortcut to invoke
+the command without having to select it in the command palette.
+
+![Command palette](img/command_palette_v13_6.png)
## Syntax highlighting
@@ -244,6 +260,8 @@ quickly share your project with others.
### Enabling Live Preview
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/268288) in GitLab 12.9, third-party assets and libraries required for Live Preview are hosted at `https://sandbox-prod.gitlab-static.net` when it is enabled. However, some libraries are still served from other third-party services which may or may not be desirable in your environment.
+
The Live Preview feature needs to be enabled in the GitLab instances
admin settings. Live Preview is enabled for all projects on
GitLab.com
diff --git a/doc/user/project/wiki/img/wiki_move_page_1.png b/doc/user/project/wiki/img/wiki_move_page_1.png
deleted file mode 100644
index 189fcc9a845..00000000000
--- a/doc/user/project/wiki/img/wiki_move_page_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/wiki/img/wiki_move_page_2.png b/doc/user/project/wiki/img/wiki_move_page_2.png
deleted file mode 100644
index 63e6ddb29c1..00000000000
--- a/doc/user/project/wiki/img/wiki_move_page_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/wiki/img/wiki_sidebar_v13_5.png b/doc/user/project/wiki/img/wiki_sidebar_v13_5.png
index 0f445d61d71..f22424749a5 100644
--- a/doc/user/project/wiki/img/wiki_sidebar_v13_5.png
+++ b/doc/user/project/wiki/img/wiki_sidebar_v13_5.png
Binary files differ
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index 64608b9a915..e082e091dec 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -96,12 +96,12 @@ Please note that:
## Editing a wiki page
-NOTE: **Note:**
-Requires Developer [permissions](../../permissions.md).
+You need Developer [permissions](../../permissions.md) or higher to edit a wiki page.
+To do so:
-To edit a page, simply click on the **Edit** button. From there on, you can
-change its content. When done, click **Save changes** for the changes to take
-effect.
+1. Click the edit icon (**{pencil}**).
+1. Edit the content.
+1. Click **Save changes**.
### Adding a table of contents
@@ -110,23 +110,34 @@ For an example, see [Table of contents](../../markdown.md#table-of-contents).
## Deleting a wiki page
-NOTE: **Note:**
-Requires Maintainer [permissions](../../permissions.md).
+You need Maintainer [permissions](../../permissions.md) or higher to delete a wiki page.
+To do so:
-You can find the **Delete** button only when editing a page. Click on it and
-confirm you want the page to be deleted.
+1. Open the page you want to delete.
+1. Click the **Delete page** button.
+1. Confirm the deletion.
## Moving a wiki page
-You can move a wiki page from one directory to another by specifying the full
-path in the wiki page title in the [edit](#editing-a-wiki-page) form.
+You need Developer [permissions](../../permissions.md) or higher to move a wiki page.
+To do so:
+
+1. Click the edit icon (**{pencil}**).
+1. Add the new path to the **Title** field.
+1. Click **Save changes**.
+
+For example, if you have a wiki page called `about` under `company` and you want to
+move it to the wiki's root:
-![Moving a page](img/wiki_move_page_1.png)
+1. Click the edit icon (**{pencil}**).
+1. Change the **Title** from `about` to `/about`.
+1. Click **Save changes**.
-![After moving a page](img/wiki_move_page_2.png)
+If you want to do the opposite:
-In order to move a wiki page to the root directory, the wiki page title must
-be preceded by the slash (`/`) character.
+1. Click the edit icon (**{pencil}**).
+1. Change the **Title** from `about` to `company/about`.
+1. Click **Save changes**.
## Viewing a list of all created wiki pages
diff --git a/doc/user/reserved_names.md b/doc/user/reserved_names.md
index 28dd4c142f7..ea3ca7a28d7 100644
--- a/doc/user/reserved_names.md
+++ b/doc/user/reserved_names.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Reserved project and group names
Not all project & group names are allowed because they would conflict with
@@ -76,6 +82,9 @@ Currently the following names are reserved as top level groups:
- `s`
- `search`
- `sent_notifications`
+- `sitemap`
+- `sitemap.xml`
+- `sitemap.xml.gz`
- `slash-command-logo.png`
- `snippets`
- `unsubscribes`
diff --git a/doc/user/search/advanced_search_syntax.md b/doc/user/search/advanced_search_syntax.md
index ed5ecc17a8b..c1414fb9ebe 100644
--- a/doc/user/search/advanced_search_syntax.md
+++ b/doc/user/search/advanced_search_syntax.md
@@ -64,8 +64,8 @@ The Advanced Search Syntax also supports the use of filters. The available filte
- extension: Filters by extension in the filename. Please write the extension without a leading dot. Exact match only.
- blob: Filters by Git `object ID`. Exact match only.
-To use them, simply add them to your query in the format `<filter_name>:<value>` without
- any spaces between the colon (`:`) and the value.
+To use them, add them to your keyword in the format `<filter_name>:<value>` without
+any spaces between the colon (`:`) and the value. A keyword or an asterisk (`*`) is required for filter searches and has to be added in front of the filter separated by a space.
Examples:
diff --git a/doc/user/search/img/filtering_merge_requests_by_date_v13_6.png b/doc/user/search/img/filtering_merge_requests_by_date_v13_6.png
new file mode 100644
index 00000000000..8f59534ef1c
--- /dev/null
+++ b/doc/user/search/img/filtering_merge_requests_by_date_v13_6.png
Binary files differ
diff --git a/doc/user/search/img/filtering_merge_requests_by_environment_v13_6.png b/doc/user/search/img/filtering_merge_requests_by_environment_v13_6.png
new file mode 100644
index 00000000000..e73a0995d73
--- /dev/null
+++ b/doc/user/search/img/filtering_merge_requests_by_environment_v13_6.png
Binary files differ
diff --git a/doc/user/search/img/issue_search_filter.png b/doc/user/search/img/issue_search_filter.png
deleted file mode 100644
index d4de3ff7656..00000000000
--- a/doc/user/search/img/issue_search_filter.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/project_search_sha_redirect.png b/doc/user/search/img/project_search_sha_redirect.png
new file mode 100644
index 00000000000..718a859d4af
--- /dev/null
+++ b/doc/user/search/img/project_search_sha_redirect.png
Binary files differ
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 412951f8a3b..79c6cf3b07d 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -44,6 +44,7 @@ groups:
- Author
- Assignee
- [Milestone](../project/milestones/index.md)
+ - [Iteration](../group/iterations/index.md) ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6)
- Release
- [Label](../project/labels.md)
- My-reaction
@@ -117,6 +118,28 @@ the dropdown) **Approved-By** and select the user.
![Filter MRs by approved by](img/filter_approved_by_merge_requests_v13_0.png)
+### Filtering merge requests by environment or deployment date **(CORE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44041) in GitLab 13.6.
+
+To filter merge requests by deployment data, such as the environment or a date,
+you can type (or select from the dropdown) the following:
+
+- Environment
+- Deployed-before
+- Deployed-after
+
+When filtering by an environment, a dropdown presents all environments that
+you can choose from:
+
+![Filter MRs by their environment](img/filtering_merge_requests_by_environment_v13_6.png)
+
+When filtering by a deploy date, you must enter the date manually. Deploy dates
+use the format `YYYY-MM-DD`, and must be quoted if you wish to specify
+both a date and time (`"YYYY-MM-DD HH:MM"`):
+
+![Filter MRs by a deploy date](img/filtering_merge_requests_by_date_v13_6.png)
+
## Filters autocomplete
GitLab provides many filters across many pages (issues, merge requests, epics,
@@ -211,6 +234,7 @@ You can also type in this search bar to see autocomplete suggestions for:
- Recently viewed issues (try and type some word from the title of a recently viewed issue)
- Recently viewed merge requests (try and type some word from the title of a recently viewed merge request)
- Recently viewed epics (try and type some word from the title of a recently viewed epic)
+- [GitLab Flavored Markdown](../markdown.md#special-gitlab-references) (GFM) for issues within a project (try and type a GFM reference for an issue)
## Basic search
@@ -248,6 +272,14 @@ 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)
+### SHA search
+
+You can quickly access a commit from within the project dashboard by entering the SHA
+into the search field on the top right of the screen. If a single result is found, you will be
+redirected to the commit result and given the option to return to the search results page.
+
+![project sha search redirect](img/project_search_sha_redirect.png)
+
## Advanced Search **(STARTER)**
Leverage Elasticsearch for faster, more advanced code search across your entire
diff --git a/doc/user/shortcuts.md b/doc/user/shortcuts.md
index c34d5be5899..6361aa856fe 100644
--- a/doc/user/shortcuts.md
+++ b/doc/user/shortcuts.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/shortcuts.html'
---
diff --git a/doc/user/todos.md b/doc/user/todos.md
index c48d2adfa45..061d81618a1 100644
--- a/doc/user/todos.md
+++ b/doc/user/todos.md
@@ -15,9 +15,9 @@ spend your time. This can include taking an action, or keeping track of things
do your work, being able to get started quickly is important.
Your *To-Do List* offers a chronological list of items waiting for your input
-(known as *to do items*) in a single dashboard.
+(known as *to-do items*) in a single dashboard.
-The To-Do List supports tracking [actions](#what-triggers-a-to-do) related to
+The To-Do List supports tracking [actions](#what-triggers-a-to-do-item) related to
the following:
- Issues
@@ -27,17 +27,17 @@ the following:
![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 To-Do List icon (**{task-done}**)
-next to the search bar in the top navigation. If the to do item count is:
+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.
+- *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 item
-A to do item 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're `@mentioned` in the description or comment of an issue or merge request
@@ -60,19 +60,19 @@ 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 item triggers aren't affected by [GitLab notification email settings](profile/notifications.md).
+To-do item 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 item (such as
+When a user no longer has access to a resource related to a to-do item (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
+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 item
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7926) in GitLab 9.0.
-If you're mentioned at the start of a line, the to do item you receive will be
+If you're mentioned at the start of a line, the to-do item you receive will be
listed as *directly addressed*. For example, in the following comment:
```markdown
@@ -87,11 +87,11 @@ listed as *directly addressed*. For example, in the following 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 item
You can also add the following to your To-Do List by clicking the **Add a to do** button on an:
@@ -100,14 +100,14 @@ You can also add the following to your To-Do List by clicking the **Add a to do*
- [Epic](group/epics/index.md) **(ULTIMATE)**
- [Design](project/issues/design_management.md)
-![Adding a To Do from the issuable sidebar](img/todos_add_todo_sidebar.png)
+![Adding a to-do item from the issuable sidebar](img/todos_add_todo_sidebar.png)
-## Marking a to do as done
+## Marking a to-do item as done
Any action to an issue or merge request (or epic **(ULTIMATE)**) will mark its
-corresponding to do item as done.
+corresponding to-do item as done.
-Actions that dismiss to do items include:
+Actions that dismiss to-do items include:
- Changing the assignee
- Changing the milestone
@@ -115,28 +115,28 @@ Actions that dismiss to do items include:
- Commenting on the issue
Your To-Do List is personal, and items are only marked as done if you take
-action. If you close the issue or merge request, your to do item is marked as
+action. If you close the issue or merge request, your to-do item is marked as
done.
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 item remains pending.
+epic **(ULTIMATE)**), your to-do item remains pending.
-There's just one to do item for each of these, so mentioning a user many times
-in an issue only triggers one to do item.
+There's just one to-do item for each of these, so mentioning a user many times
+in an issue only triggers one to-do item.
-If no action is needed, you can manually mark the to do item as done by
+If no action is needed, you can manually mark the to-do item as done by
clicking its corresponding **Done** button to have GitLab remove the item from
your To-Do List.
![A to do in the To-Do List](img/todos_todo_list_item.png)
-You can also mark a to do item as done by clicking the **Mark as done** button
+You can also mark a to-do item 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
+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
@@ -152,7 +152,7 @@ You can use the following types of filters with your To-Do List:
| 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 previously
-described [triggering actions](#what-triggers-a-to-do) include:
+described [triggering actions](#what-triggers-a-to-do-item) include:
- Any action
- Assigned
diff --git a/doc/user/upgrade_email_bypass.md b/doc/user/upgrade_email_bypass.md
index 35fddc4a1d4..97d4b5e6a0a 100644
--- a/doc/user/upgrade_email_bypass.md
+++ b/doc/user/upgrade_email_bypass.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Updating to GitLab 13.2: Email confirmation issues
In the [GitLab 13.0.1 security release](https://about.gitlab.com/releases/2020/05/27/security-release-13-0-1-released/),
diff --git a/lefthook.yml b/lefthook.yml
new file mode 100644
index 00000000000..5e307f9af30
--- /dev/null
+++ b/lefthook.yml
@@ -0,0 +1,36 @@
+pre-push:
+ parallel: true
+ commands:
+ danger:
+ run: bundle exec danger dry_run
+ eslint:
+ tags: frontend style
+ files: git diff --name-only $(git merge-base origin/master HEAD)..HEAD
+ glob: "*.{js,vue}"
+ run: yarn eslint --cache --max-warnings 0 --report-unused-disable-directives {files}
+ haml-lint:
+ tags: view haml style
+ files: git diff --name-only $(git merge-base origin/master HEAD)..HEAD
+ glob: "*.html.haml"
+ run: bundle exec haml-lint --config .haml-lint.yml {files}
+ markdownlint:
+ tags: documentation style
+ files: git diff --name-only $(git merge-base origin/master HEAD)..HEAD
+ glob: "*.md"
+ run: yarn markdownlint {files}
+ scss-lint:
+ tags: stylesheet css style
+ files: git diff --name-only $(git merge-base origin/master HEAD)..HEAD
+ glob: "*.scss{,.css}"
+ exclude: "app/assets/stylesheets/pages/emojis.scss"
+ run: bundle exec scss-lint --config .scss-lint.yml {files}
+ rubocop:
+ tags: backend style
+ files: git diff --name-only $(git merge-base origin/master HEAD)..HEAD
+ glob: "*.rb"
+ run: bundle exec rubocop --parallel --force-exclusion {files}
+ vale: # Requires Vale: https://docs.gitlab.com/ee/development/documentation/#install-linters
+ tags: documentation style
+ files: git diff --name-only $(git merge-base origin/master HEAD)..HEAD
+ glob: "*.md"
+ run: if command -v vale 2> /dev/null; then vale --config .vale.ini --minAlertLevel error {files}; else echo "Vale not found. Install Vale"; fi
diff --git a/lib/api/access_requests.rb b/lib/api/access_requests.rb
index 7e3d70a210a..e6ce62a1c6e 100644
--- a/lib/api/access_requests.rb
+++ b/lib/api/access_requests.rb
@@ -8,6 +8,8 @@ module API
helpers ::API::Helpers::MembersHelpers
+ feature_category :authentication_and_authorization
+
%w[group project].each do |source_type|
params do
requires :id, type: String, desc: "The #{source_type} ID"
diff --git a/lib/api/admin/ci/variables.rb b/lib/api/admin/ci/variables.rb
index 44c389d6f94..654d3a48162 100644
--- a/lib/api/admin/ci/variables.rb
+++ b/lib/api/admin/ci/variables.rb
@@ -8,6 +8,8 @@ module API
before { authenticated_as_admin! }
+ feature_category :continuous_integration
+
namespace 'admin' do
namespace 'ci' do
namespace 'variables' do
diff --git a/lib/api/admin/instance_clusters.rb b/lib/api/admin/instance_clusters.rb
index ce1bdd65eff..679e231b283 100644
--- a/lib/api/admin/instance_clusters.rb
+++ b/lib/api/admin/instance_clusters.rb
@@ -5,6 +5,8 @@ module API
class InstanceClusters < ::API::Base
include PaginationParams
+ feature_category :kubernetes_management
+
before do
authenticated_as_admin!
end
diff --git a/lib/api/admin/sidekiq.rb b/lib/api/admin/sidekiq.rb
index c2e9de5fb4e..7e561783685 100644
--- a/lib/api/admin/sidekiq.rb
+++ b/lib/api/admin/sidekiq.rb
@@ -5,6 +5,8 @@ module API
class Sidekiq < ::API::Base
before { authenticated_as_admin! }
+ feature_category :not_owned
+
namespace 'admin' do
namespace 'sidekiq' do
namespace 'queues' do
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 84b4d5a5835..ea149f25584 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -25,7 +25,8 @@ module API
Gitlab::GrapeLogging::Loggers::QueueDurationLogger.new,
Gitlab::GrapeLogging::Loggers::PerfLogger.new,
Gitlab::GrapeLogging::Loggers::CorrelationIdLogger.new,
- Gitlab::GrapeLogging::Loggers::ContextLogger.new
+ Gitlab::GrapeLogging::Loggers::ContextLogger.new,
+ Gitlab::GrapeLogging::Loggers::ContentLogger.new
]
allow_access_with_scope :api
@@ -48,11 +49,17 @@ module API
before do
coerce_nil_params_to_array!
+ api_endpoint = env['api.endpoint']
+ feature_category = api_endpoint.options[:for].try(:feature_category_for_app, api_endpoint).to_s
+
+ header[Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER] = feature_category
+
Gitlab::ApplicationContext.push(
user: -> { @current_user },
project: -> { @project },
namespace: -> { @group },
- caller_id: route.origin
+ caller_id: route.origin,
+ feature_category: feature_category
)
end
@@ -115,7 +122,14 @@ module API
format :json
formatter :json, Gitlab::Json::GrapeFormatter
- content_type :txt, "text/plain"
+
+ # There is a small chance some users depend on the old behavior.
+ # We this change under a feature flag to see if affects GitLab.com users.
+ if Gitlab::Database.cached_table_exists?('features') && Feature.enabled?(:api_json_content_type)
+ content_type :json, 'application/json'
+ else
+ content_type :txt, 'text/plain'
+ end
# Ensure the namespace is right, otherwise we might load Grape::API::Helpers
helpers ::API::Helpers
@@ -147,6 +161,8 @@ module API
mount ::API::Commits
mount ::API::CommitStatuses
mount ::API::ContainerRegistryEvent
+ mount ::API::ContainerRepositories
+ mount ::API::DependencyProxy
mount ::API::DeployKeys
mount ::API::DeployTokens
mount ::API::Deployments
@@ -171,6 +187,7 @@ module API
mount ::API::ImportBitbucketServer
mount ::API::ImportGithub
mount ::API::IssueLinks
+ mount ::API::Invitations
mount ::API::Issues
mount ::API::JobArtifacts
mount ::API::Jobs
@@ -202,7 +219,8 @@ module API
mount ::API::DebianGroupPackages
mount ::API::DebianProjectPackages
mount ::API::MavenPackages
- mount ::API::NpmPackages
+ mount ::API::NpmProjectPackages
+ mount ::API::NpmInstancePackages
mount ::API::GenericPackages
mount ::API::GoProxy
mount ::API::Pages
@@ -222,6 +240,7 @@ module API
mount ::API::ProjectTemplates
mount ::API::Terraform::State
mount ::API::Terraform::StateVersion
+ mount ::API::PersonalAccessTokens
mount ::API::ProtectedBranches
mount ::API::ProtectedTags
mount ::API::Releases
@@ -266,7 +285,7 @@ module API
end
end
- route :any, '*path' do
+ route :any, '*path', feature_category: :not_owned do
error!('404 Not Found', 404)
end
end
diff --git a/lib/api/appearance.rb b/lib/api/appearance.rb
index 00b495bbc1e..fe498bf611b 100644
--- a/lib/api/appearance.rb
+++ b/lib/api/appearance.rb
@@ -4,6 +4,8 @@ module API
class Appearance < ::API::Base
before { authenticated_as_admin! }
+ feature_category :navigation
+
helpers do
def current_appearance
@current_appearance ||= (::Appearance.current || ::Appearance.new)
diff --git a/lib/api/applications.rb b/lib/api/applications.rb
index 2afe8763d9d..8b14e16b495 100644
--- a/lib/api/applications.rb
+++ b/lib/api/applications.rb
@@ -5,6 +5,8 @@ module API
class Applications < ::API::Base
before { authenticated_as_admin! }
+ feature_category :authentication_and_authorization
+
resource :applications do
helpers do
def validate_redirect_uri(value)
diff --git a/lib/api/avatar.rb b/lib/api/avatar.rb
index 5a9b9940fcf..a42d89ddf83 100644
--- a/lib/api/avatar.rb
+++ b/lib/api/avatar.rb
@@ -2,6 +2,8 @@
module API
class Avatar < ::API::Base
+ feature_category :users
+
resource :avatar do
desc 'Return avatar url for a user' do
success Entities::Avatar
diff --git a/lib/api/award_emoji.rb b/lib/api/award_emoji.rb
index 6d40ae8f5ff..8ea4f32d3eb 100644
--- a/lib/api/award_emoji.rb
+++ b/lib/api/award_emoji.rb
@@ -6,9 +6,9 @@ module API
before { authenticate! }
AWARDABLES = [
- { type: 'issue', find_by: :iid },
- { type: 'merge_request', find_by: :iid },
- { type: 'snippet', find_by: :id }
+ { type: 'issue', find_by: :iid, feature_category: :issue_tracking },
+ { type: 'merge_request', find_by: :iid, feature_category: :code_review },
+ { type: 'snippet', find_by: :id, feature_category: :snippets }
].freeze
params do
@@ -34,7 +34,7 @@ module API
params do
use :pagination
end
- get endpoint do
+ get endpoint, feature_category: awardable_params[:feature_category] do
if can_read_awardable?
awards = awardable.award_emoji
present paginate(awards), with: Entities::AwardEmoji
@@ -50,7 +50,7 @@ module API
params do
requires :award_id, type: Integer, desc: 'The ID of the award'
end
- get "#{endpoint}/:award_id" do
+ get "#{endpoint}/:award_id", feature_category: awardable_params[:feature_category] do
if can_read_awardable?
present awardable.award_emoji.find(params[:award_id]), with: Entities::AwardEmoji
else
@@ -65,7 +65,7 @@ module API
params do
requires :name, type: String, desc: 'The name of a award_emoji (without colons)'
end
- post endpoint do
+ post endpoint, feature_category: awardable_params[:feature_category] do
not_found!('Award Emoji') unless can_read_awardable? && can_award_awardable?
service = AwardEmojis::AddService.new(awardable, params[:name], current_user).execute
@@ -84,7 +84,7 @@ module API
params do
requires :award_id, type: Integer, desc: 'The ID of an award emoji'
end
- delete "#{endpoint}/:award_id" do
+ delete "#{endpoint}/:award_id", feature_category: awardable_params[:feature_category] do
award = awardable.award_emoji.find(params[:award_id])
unauthorized! unless award.user == current_user || current_user.admin?
diff --git a/lib/api/badges.rb b/lib/api/badges.rb
index fc00594c9ec..04f155be4e1 100644
--- a/lib/api/badges.rb
+++ b/lib/api/badges.rb
@@ -8,6 +8,8 @@ module API
helpers ::API::Helpers::BadgesHelpers
+ feature_category :continuous_integration
+
helpers do
def find_source_if_admin(source_type)
source = find_source(source_type, params[:id])
diff --git a/lib/api/base.rb b/lib/api/base.rb
index e174cef3bad..33e47c18fcd 100644
--- a/lib/api/base.rb
+++ b/lib/api/base.rb
@@ -2,5 +2,30 @@
module API
class Base < Grape::API::Instance # rubocop:disable API/Base
+ include ::Gitlab::WithFeatureCategory
+
+ class << self
+ def feature_category_for_app(app)
+ feature_category_for_action(path_for_app(app))
+ end
+
+ def path_for_app(app)
+ normalize_path(app.namespace, app.options[:path].first)
+ end
+
+ def route(methods, paths = ['/'], route_options = {}, &block)
+ if category = route_options.delete(:feature_category)
+ feature_category(category, Array(paths).map { |path| normalize_path(namespace, path) })
+ end
+
+ super
+ end
+
+ private
+
+ def normalize_path(namespace, path)
+ [namespace.presence, path.to_s.chomp('/').presence].compact.join('/')
+ end
+ end
end
end
diff --git a/lib/api/boards.rb b/lib/api/boards.rb
index d2d1628aff4..f4b23c507f4 100644
--- a/lib/api/boards.rb
+++ b/lib/api/boards.rb
@@ -9,6 +9,8 @@ module API
before { authenticate! }
+ feature_category :boards
+
helpers do
def board_parent
user_project
@@ -40,6 +42,43 @@ module API
authorize!(:read_board, user_project)
present board, with: Entities::Board
end
+
+ desc 'Create a project board' do
+ detail 'This feature was introduced in 10.4'
+ success Entities::Board
+ end
+ params do
+ requires :name, type: String, desc: 'The board name'
+ end
+ post '/' do
+ authorize!(:admin_board, board_parent)
+
+ create_board
+ end
+
+ desc 'Update a project board' do
+ detail 'This feature was introduced in 11.0'
+ success Entities::Board
+ end
+ params do
+ use :update_params
+ end
+ put '/:board_id' do
+ authorize!(:admin_board, board_parent)
+
+ update_board
+ end
+
+ desc 'Delete a project board' do
+ detail 'This feature was introduced in 10.4'
+ success Entities::Board
+ end
+
+ delete '/:board_id' do
+ authorize!(:admin_board, board_parent)
+
+ delete_board
+ end
end
params do
diff --git a/lib/api/boards_responses.rb b/lib/api/boards_responses.rb
index 6a86c02bf4a..2ae82f78e01 100644
--- a/lib/api/boards_responses.rb
+++ b/lib/api/boards_responses.rb
@@ -10,6 +10,35 @@ module API
board_parent.boards.find(params[:board_id])
end
+ def create_board
+ forbidden! unless board_parent.multiple_issue_boards_available?
+
+ response =
+ ::Boards::CreateService.new(board_parent, current_user, { name: params[:name] }).execute
+
+ present response.payload, with: Entities::Board
+ end
+
+ def update_board
+ service = ::Boards::UpdateService.new(board_parent, current_user, declared_params(include_missing: false))
+ service.execute(board)
+
+ if board.valid?
+ present board, with: Entities::Board
+ else
+ bad_request!("Failed to save board #{board.errors.messages}")
+ end
+ end
+
+ def delete_board
+ forbidden! unless board_parent.multiple_issue_boards_available?
+
+ destroy_conditionally!(board) do |board|
+ service = ::Boards::DestroyService.new(board_parent, current_user)
+ service.execute(board)
+ end
+ end
+
def board_lists
board.destroyable_lists
end
@@ -62,6 +91,12 @@ module API
params :list_creation_params do
requires :label_id, type: Integer, desc: 'The ID of an existing label'
end
+
+ params :update_params do
+ # Configurable issue boards are not available in CE/EE Core.
+ # https://docs.gitlab.com/ee/user/project/issue_board.html#configurable-issue-boards
+ optional :name, type: String, desc: 'The board name'
+ end
end
end
end
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 37cce6eafba..6842e93a4de 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -10,6 +10,8 @@ module API
after_validation { content_type "application/json" }
+ feature_category :source_code_management
+
before do
require_repository_enabled!
authorize! :download_code, user_project
diff --git a/lib/api/broadcast_messages.rb b/lib/api/broadcast_messages.rb
index 8ce7694bbfd..0762c276aad 100644
--- a/lib/api/broadcast_messages.rb
+++ b/lib/api/broadcast_messages.rb
@@ -4,6 +4,8 @@ module API
class BroadcastMessages < ::API::Base
include PaginationParams
+ feature_category :navigation
+
resource :broadcast_messages do
helpers do
def find_message
diff --git a/lib/api/ci/pipeline_schedules.rb b/lib/api/ci/pipeline_schedules.rb
index b669acf668c..8a9ba2cbe0f 100644
--- a/lib/api/ci/pipeline_schedules.rb
+++ b/lib/api/ci/pipeline_schedules.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
+ feature_category :continuous_integration
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/ci/pipelines.rb b/lib/api/ci/pipelines.rb
index 61e03ed1a95..1b36e27f6c9 100644
--- a/lib/api/ci/pipelines.rb
+++ b/lib/api/ci/pipelines.rb
@@ -7,6 +7,8 @@ module API
before { authenticate_non_get! }
+ feature_category :continuous_integration
+
params do
requires :id, type: String, desc: 'The project ID'
end
@@ -128,15 +130,9 @@ module API
pipeline = user_project.all_pipelines.find(params[:pipeline_id])
- if Feature.enabled?(:ci_jobs_finder_refactor, default_enabled: true)
- 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 = ::Ci::JobsFinder
+ .new(current_user: current_user, pipeline: pipeline, params: params)
+ .execute
builds = builds.with_preloads
@@ -157,16 +153,9 @@ module API
pipeline = user_project.all_pipelines.find(params[:pipeline_id])
- if Feature.enabled?(:ci_jobs_finder_refactor, default_enabled: true)
- 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 = ::Ci::JobsFinder
+ .new(current_user: current_user, pipeline: pipeline, params: params, type: ::Ci::Bridge)
+ .execute
bridges = bridges.with_preloads
present paginate(bridges), with: Entities::Ci::Bridge
@@ -246,21 +235,6 @@ 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])
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index ef679147c9f..85232b4ae1b 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -5,6 +5,10 @@ module API
class Runner < ::API::Base
helpers ::API::Helpers::Runner
+ content_type :txt, 'text/plain'
+
+ feature_category :continuous_integration
+
resource :runners do
desc 'Registers a new Runner' do
success Entities::RunnerRegistrationDetails
@@ -203,27 +207,18 @@ module API
error!('400 Missing header Content-Range', 400) unless request.headers.key?('Content-Range')
content_range = request.headers['Content-Range']
- content_range = content_range.split('-')
-
- # TODO:
- # it seems that `Content-Range` as formatted by runner is wrong,
- # the `byte_end` should point to final byte, but it points byte+1
- # that means that we have to calculate end of body,
- # as we cannot use `content_length[1]`
- # Issue: https://gitlab.com/gitlab-org/gitlab-runner/issues/3275
-
- body_data = request.body.read
- body_start = content_range[0].to_i
- body_end = body_start + body_data.bytesize
-
- stream_size = job.trace.append(body_data, body_start)
- unless stream_size == body_end
- break error!('416 Range Not Satisfiable', 416, { 'Range' => "0-#{stream_size}" })
+
+ result = ::Ci::AppendBuildTraceService
+ .new(job, content_range: content_range)
+ .execute(request.body.read)
+
+ if result.status == 416
+ break error!('416 Range Not Satisfiable', 416, { 'Range' => "0-#{result.stream_size}" })
end
- status 202
+ status result.status
header 'Job-Status', job.status
- header 'Range', "0-#{stream_size}"
+ header 'Range', "0-#{result.stream_size}"
header 'X-GitLab-Trace-Update-Interval', job.trace.update_interval.to_s
end
diff --git a/lib/api/ci/runners.rb b/lib/api/ci/runners.rb
index d37f10fe631..44ffc941cfa 100644
--- a/lib/api/ci/runners.rb
+++ b/lib/api/ci/runners.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
+ feature_category :continuous_integration
+
resource :runners do
desc 'Get runners available for user' do
success Entities::Runner
diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb
index af103b8c1f8..26af921432c 100644
--- a/lib/api/commit_statuses.rb
+++ b/lib/api/commit_statuses.rb
@@ -4,6 +4,8 @@ require 'mime/types'
module API
class CommitStatuses < ::API::Base
+ feature_category :continuous_integration
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index 582ccd41847..a24848082a9 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -6,6 +6,8 @@ module API
class Commits < ::API::Base
include PaginationParams
+ feature_category :source_code_management
+
before do
require_repository_enabled!
authorize! :download_code, user_project
diff --git a/lib/api/composer_packages.rb b/lib/api/composer_packages.rb
index 1becbd668a3..0ac5cc45ccf 100644
--- a/lib/api/composer_packages.rb
+++ b/lib/api/composer_packages.rb
@@ -9,6 +9,8 @@ module API
include ::API::Helpers::Packages::BasicAuthHelpers::Constants
include ::Gitlab::Utils::StrongMemoize
+ feature_category :package_registry
+
content_type :json, 'application/json'
default_format :json
diff --git a/lib/api/conan_package_endpoints.rb b/lib/api/conan_package_endpoints.rb
index 9b6867a328b..188a42f26f8 100644
--- a/lib/api/conan_package_endpoints.rb
+++ b/lib/api/conan_package_endpoints.rb
@@ -29,6 +29,8 @@ module API
CONAN_FILES = (Gitlab::Regex::Packages::CONAN_RECIPE_FILES + Gitlab::Regex::Packages::CONAN_PACKAGE_FILES).freeze
included do
+ feature_category :package_registry
+
helpers ::API::Helpers::PackagesManagerClientsHelpers
helpers ::API::Helpers::Packages::Conan::ApiHelpers
helpers ::API::Helpers::RelatedResourcesHelpers
diff --git a/lib/api/concerns/packages/npm_endpoints.rb b/lib/api/concerns/packages/npm_endpoints.rb
new file mode 100644
index 00000000000..a91db93b182
--- /dev/null
+++ b/lib/api/concerns/packages/npm_endpoints.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+
+# NPM 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 NPM package manager client when users run commands
+# like `npm install` or `npm publish`. The usage of the GitLab NPM registry is documented here:
+# https://docs.gitlab.com/ee/user/packages/npm_registry/
+#
+# Technical debt: https://gitlab.com/gitlab-org/gitlab/issues/35798
+#
+# Caution: This Concern has to be included at the end of the API class
+# The last route of this Concern has a globbing wildcard that will match all urls.
+# As such, routes declared after the last route of this Concern will not match any url.
+module API
+ module Concerns
+ module Packages
+ module NpmEndpoints
+ extend ActiveSupport::Concern
+
+ included do
+ helpers ::API::Helpers::Packages::DependencyProxyHelpers
+
+ before do
+ require_packages_enabled!
+ authenticate_non_get!
+ end
+
+ params do
+ requires :package_name, type: String, desc: 'Package name'
+ end
+ namespace '-/package/*package_name' do
+ desc 'Get all tags for a given an NPM package' do
+ detail 'This feature was introduced in GitLab 12.7'
+ success ::API::Entities::NpmPackageTag
+ end
+ get 'dist-tags', format: false, requirements: ::API::Helpers::Packages::Npm::NPM_ENDPOINT_REQUIREMENTS do
+ package_name = params[:package_name]
+
+ bad_request!('Package Name') if package_name.blank?
+
+ authorize_read_package!(project)
+
+ packages = ::Packages::Npm::PackageFinder.new(project, package_name)
+ .execute
+
+ not_found! if packages.empty?
+
+ present ::Packages::Npm::PackagePresenter.new(package_name, packages),
+ with: ::API::Entities::NpmPackageTag
+ end
+
+ params do
+ requires :tag, type: String, desc: "Package dist-tag"
+ end
+ namespace 'dist-tags/:tag', requirements: ::API::Helpers::Packages::Npm::NPM_ENDPOINT_REQUIREMENTS do
+ desc 'Create or Update the given tag for the given NPM package and version' do
+ detail 'This feature was introduced in GitLab 12.7'
+ end
+ put format: false do
+ package_name = params[:package_name]
+ version = env['api.request.body']
+ tag = params[:tag]
+
+ bad_request!('Package Name') if package_name.blank?
+ bad_request!('Version') if version.blank?
+ bad_request!('Tag') if tag.blank?
+
+ authorize_create_package!(project)
+
+ package = ::Packages::Npm::PackageFinder
+ .new(project, package_name)
+ .find_by_version(version)
+ not_found!('Package') unless package
+
+ ::Packages::Npm::CreateTagService.new(package, tag).execute
+
+ no_content!
+ end
+
+ desc 'Deletes the given tag' do
+ detail 'This feature was introduced in GitLab 12.7'
+ end
+ delete format: false do
+ package_name = params[:package_name]
+ tag = params[:tag]
+
+ bad_request!('Package Name') if package_name.blank?
+ bad_request!('Tag') if tag.blank?
+
+ authorize_destroy_package!(project)
+
+ package_tag = ::Packages::TagsFinder
+ .new(project, package_name, package_type: :npm)
+ .find_by_name(tag)
+
+ not_found!('Package tag') unless package_tag
+
+ ::Packages::RemoveTagService.new(package_tag).execute
+
+ no_content!
+ end
+ end
+ end
+
+ desc 'NPM registry metadata endpoint' do
+ detail 'This feature was introduced in GitLab 11.8'
+ end
+ params do
+ requires :package_name, type: String, desc: 'Package name'
+ end
+ route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
+ get '*package_name', format: false, requirements: ::API::Helpers::Packages::Npm::NPM_ENDPOINT_REQUIREMENTS do
+ package_name = params[:package_name]
+
+ packages = ::Packages::Npm::PackageFinder.new(project_or_nil, package_name)
+ .execute
+
+ redirect_request = project_or_nil.blank? || packages.empty?
+
+ redirect_registry_request(redirect_request, :npm, package_name: package_name) do
+ authorize_read_package!(project)
+
+ not_found!('Packages') if packages.empty?
+
+ present ::Packages::Npm::PackagePresenter.new(package_name, packages),
+ with: ::API::Entities::NpmPackage
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/container_registry_event.rb b/lib/api/container_registry_event.rb
index 6c4b80b612a..9bad31f6661 100644
--- a/lib/api/container_registry_event.rb
+++ b/lib/api/container_registry_event.rb
@@ -4,6 +4,8 @@ module API
class ContainerRegistryEvent < ::API::Base
DOCKER_DISTRIBUTION_EVENTS_V1_JSON = 'application/vnd.docker.distribution.events.v1+json'
+ feature_category :package_registry
+
before { authenticate_registry_notification! }
resource :container_registry_event do
diff --git a/lib/api/container_repositories.rb b/lib/api/container_repositories.rb
new file mode 100644
index 00000000000..c84527f26e7
--- /dev/null
+++ b/lib/api/container_repositories.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module API
+ class ContainerRepositories < ::API::Base
+ include Gitlab::Utils::StrongMemoize
+ helpers ::API::Helpers::PackagesHelpers
+
+ before { authenticate! }
+
+ feature_category :container_registry
+
+ namespace 'registry' do
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
+ resource :repositories, requirements: { id: /[0-9]*/ } do
+ desc 'Get a container repository' do
+ detail 'This feature was introduced in GitLab 13.6.'
+ success Entities::ContainerRegistry::Repository
+ end
+ params do
+ optional :tags, type: Boolean, default: false, desc: 'Determines if tags should be included'
+ optional :tags_count, type: Boolean, default: false, desc: 'Determines if the tags count should be included'
+ end
+ get ':id' do
+ authorize!(:read_container_image, repository)
+
+ present repository, with: Entities::ContainerRegistry::Repository, tags: params[:tags], tags_count: params[:tags_count], user: current_user
+ end
+ end
+ end
+
+ helpers do
+ def repository
+ strong_memoize(:repository) do
+ ContainerRepository.find(params[:id])
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/debian_package_endpoints.rb b/lib/api/debian_package_endpoints.rb
index 168b3ca7a4f..c95c75b7e5c 100644
--- a/lib/api/debian_package_endpoints.rb
+++ b/lib/api/debian_package_endpoints.rb
@@ -26,6 +26,8 @@ module API
}.freeze
included do
+ feature_category :package_registry
+
helpers ::API::Helpers::PackagesHelpers
helpers ::API::Helpers::Packages::BasicAuthHelpers
diff --git a/lib/api/dependency_proxy.rb b/lib/api/dependency_proxy.rb
new file mode 100644
index 00000000000..3379bb2f029
--- /dev/null
+++ b/lib/api/dependency_proxy.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module API
+ class DependencyProxy < ::API::Base
+ helpers ::API::Helpers::PackagesHelpers
+
+ feature_category :dependency_proxy
+
+ helpers do
+ def obtain_new_purge_cache_lease
+ Gitlab::ExclusiveLease
+ .new("dependency_proxy:delete_group_blobs:#{user_group.id}",
+ timeout: 1.hour)
+ .try_obtain
+ end
+ end
+
+ before do
+ authorize! :admin_group, user_group
+ end
+
+ params do
+ requires :id, type: String, desc: 'The ID of a group'
+ end
+ resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc 'Deletes all dependency_proxy_blobs for a group' do
+ detail 'This feature was introduced in GitLab 12.10'
+ end
+ delete ':id/dependency_proxy/cache' do
+ not_found! unless user_group.dependency_proxy_feature_available?
+
+ message = 'This request has already been made. It may take some time to purge the cache. You can run this at most once an hour for a given group'
+ render_api_error!(message, 409) unless obtain_new_purge_cache_lease
+
+ # rubocop:disable CodeReuse/Worker
+ PurgeDependencyProxyCacheWorker.perform_async(current_user.id, user_group.id)
+ # rubocop:enable CodeReuse/Worker
+ end
+ end
+ end
+end
diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb
index 314f5b6ee1d..0a541620c3a 100644
--- a/lib/api/deploy_keys.rb
+++ b/lib/api/deploy_keys.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :continuous_delivery
+
helpers do
def add_deploy_keys_project(project, attrs = {})
project.deploy_keys_projects.create(attrs)
diff --git a/lib/api/deploy_tokens.rb b/lib/api/deploy_tokens.rb
index 1c156b8b3bb..5fab590eb4e 100644
--- a/lib/api/deploy_tokens.rb
+++ b/lib/api/deploy_tokens.rb
@@ -4,6 +4,8 @@ module API
class DeployTokens < ::API::Base
include PaginationParams
+ feature_category :continuous_delivery
+
helpers do
def scope_params
scopes = params.delete(:scopes)
diff --git a/lib/api/deployments.rb b/lib/api/deployments.rb
index ff06bdbae16..5346fcf03c9 100644
--- a/lib/api/deployments.rb
+++ b/lib/api/deployments.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
+ feature_category :continuous_delivery
+
params do
requires :id, type: String, desc: 'The project ID'
end
diff --git a/lib/api/discussions.rb b/lib/api/discussions.rb
index 3d2608c8c5a..4c4ec200060 100644
--- a/lib/api/discussions.rb
+++ b/lib/api/discussions.rb
@@ -8,7 +8,7 @@ module API
before { authenticate! }
- Helpers::DiscussionsHelpers.noteable_types.each do |noteable_type|
+ Helpers::DiscussionsHelpers.feature_category_per_noteable_type.each do |noteable_type, feature_category|
parent_type = noteable_type.parent_class.to_s.underscore
noteables_str = noteable_type.to_s.underscore.pluralize
noteables_path = noteable_type == Commit ? "repository/#{noteables_str}" : noteables_str
@@ -25,7 +25,7 @@ module API
use :pagination
end
- get ":id/#{noteables_path}/:noteable_id/discussions" do
+ get ":id/#{noteables_path}/:noteable_id/discussions", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
discussion_ids = paginate(noteable.discussion_ids_relation)
@@ -41,7 +41,7 @@ module API
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
end
- get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do
+ get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id])
@@ -91,7 +91,7 @@ module API
end
end
end
- post ":id/#{noteables_path}/:noteable_id/discussions" do
+ post ":id/#{noteables_path}/:noteable_id/discussions", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
type = params[:position] ? 'DiffNote' : 'DiscussionNote'
id_key = noteable.is_a?(Commit) ? :commit_id : :noteable_id
@@ -121,7 +121,7 @@ module API
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
end
- get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do
+ get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id])
@@ -141,7 +141,7 @@ module API
requires :body, type: String, desc: 'The content of a note'
optional :created_at, type: String, desc: 'The creation date of the note'
end
- post ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do
+ post ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id])
first_note = notes.first
@@ -175,7 +175,7 @@ module API
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :note_id, type: Integer, desc: 'The ID of a note'
end
- get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
+ get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
get_note(noteable, params[:note_id])
@@ -192,7 +192,7 @@ module API
optional :resolved, type: Boolean, desc: 'Mark note resolved/unresolved'
exactly_one_of :body, :resolved
end
- put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
+ put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
if params[:resolved].nil?
@@ -210,7 +210,7 @@ module API
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :note_id, type: Integer, desc: 'The ID of a note'
end
- delete ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
+ delete ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
delete_note(noteable, params[:note_id])
@@ -225,7 +225,7 @@ module API
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :resolved, type: Boolean, desc: 'Mark discussion resolved/unresolved'
end
- put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do
+ put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
resolve_discussion(noteable, params[:discussion_id], params[:resolved])
diff --git a/lib/api/entities/board.rb b/lib/api/entities/board.rb
index 5bb1cde0fa9..b7a50408313 100644
--- a/lib/api/entities/board.rb
+++ b/lib/api/entities/board.rb
@@ -4,6 +4,7 @@ module API
module Entities
class Board < Grape::Entity
expose :id
+ expose :name
expose :project, using: Entities::BasicProjectDetails
expose :lists, using: Entities::List do |board|
diff --git a/lib/api/entities/commit_signature.rb b/lib/api/entities/commit_signature.rb
index b5232273521..505ce462edf 100644
--- a/lib/api/entities/commit_signature.rb
+++ b/lib/api/entities/commit_signature.rb
@@ -4,13 +4,28 @@ module API
module Entities
class CommitSignature < Grape::Entity
expose :signature_type
+
expose :signature, merge: true do |commit, options|
- if commit.signature.is_a?(GpgSignature)
- ::API::Entities::GpgCommitSignature.represent commit.signature, options
+ if commit.signature.is_a?(GpgSignature) || commit.raw_commit_from_rugged?
+ ::API::Entities::GpgCommitSignature.represent commit_signature(commit), options
elsif commit.signature.is_a?(X509CommitSignature)
::API::Entities::X509Signature.represent commit.signature, options
end
end
+
+ expose :commit_source do |commit, _|
+ commit.raw_commit_from_rugged? ? "rugged" : "gitaly"
+ end
+
+ private
+
+ def commit_signature(commit)
+ if commit.raw_commit_from_rugged?
+ commit.gpg_commit.signature
+ else
+ commit.signature
+ end
+ end
end
end
end
diff --git a/lib/api/entities/container_registry.rb b/lib/api/entities/container_registry.rb
index c430b73580b..c9c2c5156cc 100644
--- a/lib/api/entities/container_registry.rb
+++ b/lib/api/entities/container_registry.rb
@@ -10,6 +10,8 @@ module API
end
class Repository < Grape::Entity
+ include ::API::Helpers::RelatedResourcesHelpers
+
expose :id
expose :name
expose :path
@@ -19,6 +21,13 @@ module API
expose :expiration_policy_started_at, as: :cleanup_policy_started_at
expose :tags_count, if: -> (_, options) { options[:tags_count] }
expose :tags, using: Tag, if: -> (_, options) { options[:tags] }
+ expose :delete_api_path, if: ->(object, options) { Ability.allowed?(options[:user], :admin_container_image, object) }
+
+ private
+
+ def delete_api_path
+ expose_url api_v4_projects_registry_repositories_path(repository_id: object.id, id: object.project_id)
+ end
end
class TagDetails < Tag
diff --git a/lib/api/entities/invitation.rb b/lib/api/entities/invitation.rb
new file mode 100644
index 00000000000..342f4804cf3
--- /dev/null
+++ b/lib/api/entities/invitation.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class Invitation < Grape::Entity
+ expose :access_level
+ expose :requested_at
+ expose :expires_at
+ expose :invite_email
+ expose :invite_token
+ expose :user_name, if: -> (member, _) { member.user.present? }
+ expose :created_by_name
+ end
+ end
+end
diff --git a/lib/api/entities/merge_request_changes.rb b/lib/api/entities/merge_request_changes.rb
index a835d119736..488f33dfb93 100644
--- a/lib/api/entities/merge_request_changes.rb
+++ b/lib/api/entities/merge_request_changes.rb
@@ -4,7 +4,27 @@ module API
module Entities
class MergeRequestChanges < MergeRequest
expose :diffs, as: :changes, using: Entities::Diff do |compare, _|
- compare.raw_diffs(limits: false).to_a
+ Array(diff_collection(compare))
+ end
+
+ expose :overflow?, as: :overflow
+
+ private
+
+ def overflow?
+ expose_raw_diffs? ? false : diff_collection(object).overflow?
+ end
+
+ def diff_collection(compare)
+ @diffs ||= if expose_raw_diffs?
+ compare.raw_diffs(limits: false)
+ else
+ compare.diffs.diffs
+ end
+ end
+
+ def expose_raw_diffs?
+ options[:access_raw_diffs] || ::Feature.enabled?(:mrc_api_use_raw_diffs_from_gitaly, options[:project])
end
end
end
diff --git a/lib/api/entities/package.rb b/lib/api/entities/package.rb
index b54f0e04a9d..e7153f9bebb 100644
--- a/lib/api/entities/package.rb
+++ b/lib/api/entities/package.rb
@@ -38,7 +38,8 @@ module API
expose :project_path, if: ->(obj, opts) { opts[:group] && Ability.allowed?(opts[:user], :read_project, obj.project) }
expose :tags
- expose :pipeline, if: ->(package) { package.build_info }, using: Package::Pipeline
+ expose :pipeline, if: ->(package) { package.original_build_info }, using: Package::Pipeline
+ expose :pipelines, if: ->(package) { package.pipelines.present? }, using: Package::Pipeline
expose :versions, using: ::API::Entities::PackageVersion, unless: ->(_, opts) { opts[:collection] }
diff --git a/lib/api/entities/package_file.rb b/lib/api/entities/package_file.rb
index 8be4e5a4316..2cc2f62a948 100644
--- a/lib/api/entities/package_file.rb
+++ b/lib/api/entities/package_file.rb
@@ -6,6 +6,7 @@ module API
expose :id, :package_id, :created_at
expose :file_name, :size
expose :file_md5, :file_sha1
+ expose :pipelines, if: ->(package_file) { package_file.pipelines.present? }, using: Package::Pipeline
end
end
end
diff --git a/lib/api/entities/package_version.rb b/lib/api/entities/package_version.rb
index 5f3e86c3229..82522d3f423 100644
--- a/lib/api/entities/package_version.rb
+++ b/lib/api/entities/package_version.rb
@@ -8,7 +8,7 @@ module API
expose :created_at
expose :tags
- expose :pipeline, if: ->(package) { package.build_info }, using: Package::Pipeline
+ expose :pipeline, if: ->(package) { package.original_build_info }, using: Package::Pipeline
end
end
end
diff --git a/lib/api/entities/project_hook.rb b/lib/api/entities/project_hook.rb
index 751f9500252..6c71e5d317c 100644
--- a/lib/api/entities/project_hook.rb
+++ b/lib/api/entities/project_hook.rb
@@ -5,7 +5,7 @@ module API
class ProjectHook < Hook
expose :project_id, :issues_events, :confidential_issues_events
expose :note_events, :confidential_note_events, :pipeline_events, :wiki_page_events, :deployment_events
- expose :job_events
+ expose :job_events, :releases_events
expose :push_events_branch_filter
end
end
diff --git a/lib/api/entities/release.rb b/lib/api/entities/release.rb
index afe14cf33cf..44a46c5861e 100644
--- a/lib/api/entities/release.rb
+++ b/lib/api/entities/release.rb
@@ -30,8 +30,6 @@ module API
expose :evidences, using: Entities::Releases::Evidence, expose_nil: false, if: ->(_, _) { can_download_code? }
expose :_links do
expose :self_url, as: :self, expose_nil: false
- expose :merge_requests_url, expose_nil: false
- expose :issues_url, expose_nil: false
expose :edit_url, expose_nil: false
end
diff --git a/lib/api/entities/releases/link.rb b/lib/api/entities/releases/link.rb
index 654df2e2caf..c1d83a8924f 100644
--- a/lib/api/entities/releases/link.rb
+++ b/lib/api/entities/releases/link.rb
@@ -14,10 +14,8 @@ module API
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
+ release = object.release.present
+ release.download_url(object.filepath)
end
end
end
diff --git a/lib/api/entities/user_status.rb b/lib/api/entities/user_status.rb
index 9bc4cbf240f..1d5cc27e5ef 100644
--- a/lib/api/entities/user_status.rb
+++ b/lib/api/entities/user_status.rb
@@ -5,6 +5,7 @@ module API
class UserStatus < Grape::Entity
expose :emoji
expose :message
+ expose :availability
expose :message_html do |entity|
MarkupHelper.markdown_field(entity, :message)
end
diff --git a/lib/api/environments.rb b/lib/api/environments.rb
index 0e780d4ef36..5dd2fa22690 100644
--- a/lib/api/environments.rb
+++ b/lib/api/environments.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
+ feature_category :continuous_delivery
+
params do
requires :id, type: String, desc: 'The project ID'
end
diff --git a/lib/api/error_tracking.rb b/lib/api/error_tracking.rb
index 03f83477954..0e44c8b1081 100644
--- a/lib/api/error_tracking.rb
+++ b/lib/api/error_tracking.rb
@@ -4,6 +4,8 @@ module API
class ErrorTracking < ::API::Base
before { authenticate! }
+ feature_category :error_tracking
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/events.rb b/lib/api/events.rb
index 43efacf9c0b..233c62b5389 100644
--- a/lib/api/events.rb
+++ b/lib/api/events.rb
@@ -8,6 +8,8 @@ module API
allow_access_with_scope :read_user, if: -> (request) { request.get? }
+ feature_category :users
+
resource :events do
desc "List currently authenticated user's events" do
detail 'This feature was introduced in GitLab 9.3.'
diff --git a/lib/api/feature_flag_scopes.rb b/lib/api/feature_flag_scopes.rb
index d77e243aa88..3f3bf4d9f42 100644
--- a/lib/api/feature_flag_scopes.rb
+++ b/lib/api/feature_flag_scopes.rb
@@ -7,6 +7,8 @@ module API
ENVIRONMENT_SCOPE_ENDPOINT_REQUIREMENTS = FeatureFlags::FEATURE_FLAG_ENDPOINT_REQUIREMENTS
.merge(environment_scope: API::NO_SLASH_URL_PART_REGEX)
+ feature_category :feature_flags
+
before do
authorize_read_feature_flags!
end
diff --git a/lib/api/feature_flags.rb b/lib/api/feature_flags.rb
index 613c3fb0f5b..67168ba9be6 100644
--- a/lib/api/feature_flags.rb
+++ b/lib/api/feature_flags.rb
@@ -7,6 +7,8 @@ module API
FEATURE_FLAG_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS
.merge(name: API::NO_SLASH_URL_PART_REGEX)
+ feature_category :feature_flags
+
before do
authorize_read_feature_flags!
end
diff --git a/lib/api/feature_flags_user_lists.rb b/lib/api/feature_flags_user_lists.rb
index e5218cfd7f1..086bcbcdc89 100644
--- a/lib/api/feature_flags_user_lists.rb
+++ b/lib/api/feature_flags_user_lists.rb
@@ -8,6 +8,8 @@ module API
message.is_a?(String) ? { message: message }.to_json : message.to_json
}
+ feature_category :feature_flags
+
before do
authorize_admin_feature_flags_user_lists!
end
@@ -22,10 +24,13 @@ module API
success ::API::Entities::FeatureFlag::UserList
end
params do
+ optional :search, type: String, desc: 'Returns the list of user lists matching the search critiera'
+
use :pagination
end
get do
- present paginate(user_project.operations_feature_flags_user_lists),
+ user_lists = ::FeatureFlagsUserListsFinder.new(user_project, current_user, params).execute
+ present paginate(user_lists),
with: ::API::Entities::FeatureFlag::UserList
end
diff --git a/lib/api/features.rb b/lib/api/features.rb
index 5d2e545abd6..2c2e3e3d0c9 100644
--- a/lib/api/features.rb
+++ b/lib/api/features.rb
@@ -4,6 +4,8 @@ module API
class Features < ::API::Base
before { authenticated_as_admin! }
+ feature_category :feature_flags
+
helpers do
def gate_value(params)
case params[:value]
@@ -61,6 +63,8 @@ module API
mutually_exclusive :key, :project
end
post ':name' do
+ validate_feature_flag_name!(params[:name])
+
feature = Feature.get(params[:name]) # rubocop:disable Gitlab/AvoidFeatureGet
targets = gate_targets(params)
value = gate_value(params)
@@ -97,5 +101,13 @@ module API
no_content!
end
end
+
+ helpers do
+ def validate_feature_flag_name!(name)
+ # no-op
+ end
+ end
end
end
+
+API::Features.prepend_if_ee('EE::API::Features')
diff --git a/lib/api/files.rb b/lib/api/files.rb
index 6833fc429e2..cb73bde73f5 100644
--- a/lib/api/files.rb
+++ b/lib/api/files.rb
@@ -9,6 +9,8 @@ module API
# Prevents returning plain/text responses for files with .txt extension
after_validation { content_type "application/json" }
+ feature_category :source_code_management
+
helpers ::API::Helpers::HeadersHelpers
helpers do
diff --git a/lib/api/freeze_periods.rb b/lib/api/freeze_periods.rb
index a83e36165a2..d001ced8581 100644
--- a/lib/api/freeze_periods.rb
+++ b/lib/api/freeze_periods.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :continuous_delivery
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/generic_packages.rb b/lib/api/generic_packages.rb
index a0c33ab65b9..3e1dd044c8d 100644
--- a/lib/api/generic_packages.rb
+++ b/lib/api/generic_packages.rb
@@ -7,6 +7,8 @@ module API
file_name: API::NO_SLASH_URL_PART_REGEX
}.freeze
+ feature_category :package_registry
+
before do
require_packages_enabled!
authenticate!
diff --git a/lib/api/go_proxy.rb b/lib/api/go_proxy.rb
index 30f0cfb4dfd..8fb4c561c40 100755
--- a/lib/api/go_proxy.rb
+++ b/lib/api/go_proxy.rb
@@ -4,11 +4,15 @@ module API
helpers Gitlab::Golang
helpers ::API::Helpers::PackagesHelpers
+ feature_category :package_registry
+
# basic semver, except case encoded (A => !a)
MODULE_VERSION_REGEX = /v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([-.!a-z0-9]+))?(?:\+([-.!a-z0-9]+))?/.freeze
MODULE_VERSION_REQUIREMENTS = { module_version: MODULE_VERSION_REGEX }.freeze
+ content_type :txt, 'text/plain'
+
before { require_packages_enabled! }
helpers do
diff --git a/lib/api/group_boards.rb b/lib/api/group_boards.rb
index d4574b22d99..ac5a1a2ce94 100644
--- a/lib/api/group_boards.rb
+++ b/lib/api/group_boards.rb
@@ -7,6 +7,8 @@ module API
prepend_if_ee('EE::API::BoardsResponses') # rubocop: disable Cop/InjectEnterpriseEditionModule
+ feature_category :boards
+
before do
authenticate!
end
diff --git a/lib/api/group_clusters.rb b/lib/api/group_clusters.rb
index 75429cf7a5c..a435b050042 100644
--- a/lib/api/group_clusters.rb
+++ b/lib/api/group_clusters.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :kubernetes_management
+
params do
requires :id, type: String, desc: 'The ID of the group'
end
diff --git a/lib/api/group_container_repositories.rb b/lib/api/group_container_repositories.rb
index 1bb26b3931c..4fede0ad583 100644
--- a/lib/api/group_container_repositories.rb
+++ b/lib/api/group_container_repositories.rb
@@ -8,6 +8,8 @@ module API
before { authorize_read_group_container_images! }
+ feature_category :package_registry
+
REPOSITORY_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(
tag_name: API::NO_SLASH_URL_PART_REGEX)
diff --git a/lib/api/group_export.rb b/lib/api/group_export.rb
index 6ebaa8de185..29ffbea687a 100644
--- a/lib/api/group_export.rb
+++ b/lib/api/group_export.rb
@@ -10,6 +10,8 @@ module API
authorize! :admin_group, user_group
end
+ feature_category :importers
+
params do
requires :id, type: String, desc: 'The ID of a group'
end
diff --git a/lib/api/group_import.rb b/lib/api/group_import.rb
index e703a217fd5..4a752732652 100644
--- a/lib/api/group_import.rb
+++ b/lib/api/group_import.rb
@@ -2,6 +2,8 @@
module API
class GroupImport < ::API::Base
+ feature_category :importers
+
helpers Helpers::FileUploadHelpers
helpers do
diff --git a/lib/api/group_labels.rb b/lib/api/group_labels.rb
index 8443ddf10ce..bf3ac8800b7 100644
--- a/lib/api/group_labels.rb
+++ b/lib/api/group_labels.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
+ feature_category :issue_tracking
+
params do
requires :id, type: String, desc: 'The ID of a group'
end
@@ -20,10 +22,16 @@ module API
desc: 'Include issue and merge request counts'
optional :include_ancestor_groups, type: Boolean, default: true,
desc: 'Include ancestor groups'
+ optional :include_descendant_groups, type: Boolean, default: false,
+ desc: 'Include descendant groups. This feature was added in GitLab 13.6'
+ optional :only_group_labels, type: Boolean, default: true,
+ desc: 'Toggle to include only group labels or also project labels. This feature was added in GitLab 13.6'
+ optional :search, type: String,
+ desc: 'Keyword to filter labels by. This feature was added in GitLab 13.6'
use :pagination
end
get ':id/labels' do
- get_labels(user_group, Entities::GroupLabel, include_ancestor_groups: params[:include_ancestor_groups])
+ get_labels(user_group, Entities::GroupLabel, declared_params)
end
desc 'Get a single label' do
@@ -33,9 +41,13 @@ module API
params do
optional :include_ancestor_groups, type: Boolean, default: true,
desc: 'Include ancestor groups'
+ optional :include_descendant_groups, type: Boolean, default: false,
+ desc: 'Include descendant groups. This feature was added in GitLab 13.6'
+ optional :only_group_labels, type: Boolean, default: true,
+ desc: 'Toggle to include only group labels or also project labels. This feature was added in GitLab 13.6'
end
get ':id/labels/:name' do
- get_label(user_group, Entities::GroupLabel, include_ancestor_groups: params[:include_ancestor_groups])
+ get_label(user_group, Entities::GroupLabel, declared_params)
end
desc 'Create a new label' do
diff --git a/lib/api/group_milestones.rb b/lib/api/group_milestones.rb
index aef9877b84c..dfffd3b1209 100644
--- a/lib/api/group_milestones.rb
+++ b/lib/api/group_milestones.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
+ feature_category :issue_tracking
+
params do
requires :id, type: String, desc: 'The ID of a group'
end
diff --git a/lib/api/group_packages.rb b/lib/api/group_packages.rb
index 5b6290df0dd..31b28c3990f 100644
--- a/lib/api/group_packages.rb
+++ b/lib/api/group_packages.rb
@@ -8,6 +8,8 @@ module API
authorize_packages_access!(user_group)
end
+ feature_category :package_registry
+
helpers ::API::Helpers::PackagesHelpers
params do
diff --git a/lib/api/group_variables.rb b/lib/api/group_variables.rb
index ee110d67fa5..0c40db02eb5 100644
--- a/lib/api/group_variables.rb
+++ b/lib/api/group_variables.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
before { authorize! :admin_build, user_group }
+ feature_category :continuous_integration
+
params do
requires :id, type: String, desc: 'The ID of a group'
end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index bf3d6c3c7e0..a8b1cdab021 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -7,6 +7,8 @@ module API
before { authenticate_non_get! }
+ feature_category :subgroups
+
helpers Helpers::GroupsHelpers
helpers do
@@ -46,7 +48,7 @@ module API
find_params.fetch(:all_available, current_user&.can_read_all_resources?)
groups = GroupsFinder.new(current_user, find_params).execute
- groups = groups.search(params[:search]) if params[:search].present?
+ groups = groups.search(params[:search], include_parents: true) if params[:search].present?
groups = groups.where.not(id: params[:skip_groups]) if params[:skip_groups].present?
order_options = { params[:order_by] => params[:sort] }
order_options["id"] ||= "asc"
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index c8aee1f3479..147d8407142 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -89,16 +89,15 @@ module API
@project ||= find_project!(params[:id])
end
- def available_labels_for(label_parent, include_ancestor_groups: true)
- search_params = { include_ancestor_groups: include_ancestor_groups }
-
+ def available_labels_for(label_parent, params = { include_ancestor_groups: true, only_group_labels: true })
if label_parent.is_a?(Project)
- search_params[:project_id] = label_parent.id
+ params.delete(:only_group_labels)
+ params[:project_id] = label_parent.id
else
- search_params.merge!(group_id: label_parent.id, only_group_labels: true)
+ params[:group_id] = label_parent.id
end
- LabelsFinder.new(current_user, search_params).execute
+ LabelsFinder.new(current_user, params).execute
end
def find_user(id)
@@ -388,8 +387,8 @@ module API
render_api_error!('401 Unauthorized', 401)
end
- def not_allowed!
- render_api_error!('405 Method Not Allowed', 405)
+ def not_allowed!(message = nil)
+ render_api_error!(message || '405 Method Not Allowed', :method_not_allowed)
end
def not_acceptable!
diff --git a/lib/api/helpers/discussions_helpers.rb b/lib/api/helpers/discussions_helpers.rb
index 799d5582b38..3c0db1d0ea9 100644
--- a/lib/api/helpers/discussions_helpers.rb
+++ b/lib/api/helpers/discussions_helpers.rb
@@ -3,10 +3,15 @@
module API
module Helpers
module DiscussionsHelpers
- def self.noteable_types
+ def self.feature_category_per_noteable_type
# This is a method instead of a constant, allowing EE to more easily
# extend it.
- [Issue, Snippet, MergeRequest, Commit]
+ {
+ Issue => :issue_tracking,
+ Snippet => :snippets,
+ MergeRequest => :code_review,
+ Commit => :code_review
+ }
end
end
end
diff --git a/lib/api/helpers/issues_helpers.rb b/lib/api/helpers/issues_helpers.rb
index 638b31cc7ba..b303f1f845d 100644
--- a/lib/api/helpers/issues_helpers.rb
+++ b/lib/api/helpers/issues_helpers.rb
@@ -5,6 +5,9 @@ module API
module IssuesHelpers
extend Grape::API::Helpers
+ params :negatable_issue_filter_params_ee do
+ end
+
params :optional_issue_params_ee do
end
diff --git a/lib/api/helpers/label_helpers.rb b/lib/api/helpers/label_helpers.rb
index 2fb2d9b79cf..4018f2dec21 100644
--- a/lib/api/helpers/label_helpers.rb
+++ b/lib/api/helpers/label_helpers.rb
@@ -28,23 +28,23 @@ module API
at_least_one_of :new_name, :color, :description
end
- def find_label(parent, id_or_title, include_ancestor_groups: true)
- labels = available_labels_for(parent, include_ancestor_groups: include_ancestor_groups)
+ def find_label(parent, id_or_title, params = { include_ancestor_groups: true })
+ labels = available_labels_for(parent, params)
label = labels.find_by_id(id_or_title) || labels.find_by_title(id_or_title)
label || not_found!('Label')
end
- def get_labels(parent, entity, include_ancestor_groups: true)
- present paginate(available_labels_for(parent, include_ancestor_groups: include_ancestor_groups)),
+ def get_labels(parent, entity, params = {})
+ present paginate(available_labels_for(parent, params)),
with: entity,
current_user: current_user,
parent: parent,
with_counts: params[:with_counts]
end
- def get_label(parent, entity, include_ancestor_groups: true)
- label = find_label(parent, params_id_or_title, include_ancestor_groups: include_ancestor_groups)
+ def get_label(parent, entity, params = {})
+ label = find_label(parent, params_id_or_title, params)
present label, with: entity, current_user: current_user, parent: parent
end
diff --git a/lib/api/helpers/members_helpers.rb b/lib/api/helpers/members_helpers.rb
index 5cc435e6801..431001c227d 100644
--- a/lib/api/helpers/members_helpers.rb
+++ b/lib/api/helpers/members_helpers.rb
@@ -20,12 +20,23 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def retrieve_members(source, params:, deep: false)
- members = deep ? find_all_members(source) : source.members.where.not(user_id: nil)
+ members = deep ? find_all_members(source) : source_members(source).where.not(user_id: nil)
members = members.includes(:user)
members = members.references(:user).merge(User.search(params[:query])) if params[:query].present?
members = members.where(user_id: params[:user_ids]) if params[:user_ids].present?
members
end
+
+ def retrieve_member_invitations(source, query = nil)
+ members = source_members(source).where.not(invite_token: nil)
+ members = members.includes(:user)
+ members = members.where(invite_email: query) if query.present?
+ members
+ end
+
+ def source_members(source)
+ source.members
+ end
# rubocop: enable CodeReuse/ActiveRecord
def find_all_members(source)
@@ -48,6 +59,10 @@ module API
def present_members(members)
present members, with: Entities::Member, current_user: current_user, show_seat_info: params[:show_seat_info]
end
+
+ def present_member_invitations(invitations)
+ present invitations, with: Entities::Invitation, current_user: current_user
+ end
end
end
end
diff --git a/lib/api/helpers/notes_helpers.rb b/lib/api/helpers/notes_helpers.rb
index f61bcfe963e..6798c4d284b 100644
--- a/lib/api/helpers/notes_helpers.rb
+++ b/lib/api/helpers/notes_helpers.rb
@@ -5,10 +5,12 @@ module API
module NotesHelpers
include ::RendersNotes
- def self.noteable_types
- # This is a method instead of a constant, allowing EE to more easily
- # extend it.
- [Issue, MergeRequest, Snippet]
+ def self.feature_category_per_noteable_type
+ {
+ Issue => :issue_tracking,
+ MergeRequest => :code_review,
+ Snippet => :snippets
+ }
end
def update_note(noteable, note_id)
diff --git a/lib/api/helpers/packages/npm.rb b/lib/api/helpers/packages/npm.rb
new file mode 100644
index 00000000000..c1f6a001201
--- /dev/null
+++ b/lib/api/helpers/packages/npm.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module Packages
+ module Npm
+ include Gitlab::Utils::StrongMemoize
+ include ::API::Helpers::PackagesHelpers
+
+ NPM_ENDPOINT_REQUIREMENTS = {
+ package_name: API::NO_SLASH_URL_PART_REGEX
+ }.freeze
+
+ def endpoint_scope
+ params[:id].present? ? :project : :instance
+ end
+
+ def project
+ strong_memoize(:project) do
+ case endpoint_scope
+ when :project
+ user_project
+ when :instance
+ # Simulate the same behavior as #user_project by re-using #find_project!
+ # but take care if the project_id is nil as #find_project! is not designed
+ # to handle it.
+ project_id = project_id_or_nil
+
+ not_found!('Project') unless project_id
+
+ find_project!(project_id)
+ end
+ end
+ end
+
+ def project_or_nil
+ # mainly used by the metadata endpoint where we need to get a project
+ # and return nil if not found (no errors should be raised)
+ strong_memoize(:project_or_nil) do
+ next unless project_id_or_nil
+
+ find_project(project_id_or_nil)
+ end
+ end
+
+ def project_id_or_nil
+ strong_memoize(:project_id_or_nil) do
+ case endpoint_scope
+ when :project
+ params[:id]
+ when :instance
+ ::Packages::Package.npm
+ .with_name(params[:package_name])
+ .first
+ &.project_id
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/resource_label_events_helpers.rb b/lib/api/helpers/resource_label_events_helpers.rb
index 423bd4e704b..ad2733baffc 100644
--- a/lib/api/helpers/resource_label_events_helpers.rb
+++ b/lib/api/helpers/resource_label_events_helpers.rb
@@ -3,10 +3,13 @@
module API
module Helpers
module ResourceLabelEventsHelpers
- def self.eventable_types
+ def self.feature_category_per_eventable_type
# This is a method instead of a constant, allowing EE to more easily
# extend it.
- [Issue, MergeRequest]
+ {
+ Issue => :issue_tracking,
+ MergeRequest => :code_review
+ }
end
end
end
diff --git a/lib/api/import_bitbucket_server.rb b/lib/api/import_bitbucket_server.rb
index a0238c24f3b..ecd78c6e6db 100644
--- a/lib/api/import_bitbucket_server.rb
+++ b/lib/api/import_bitbucket_server.rb
@@ -2,6 +2,8 @@
module API
class ImportBitbucketServer < ::API::Base
+ feature_category :importers
+
helpers do
def client
@client ||= BitbucketServer::Client.new(credentials)
diff --git a/lib/api/import_github.rb b/lib/api/import_github.rb
index 61fce7a2c1b..c91a7700f58 100644
--- a/lib/api/import_github.rb
+++ b/lib/api/import_github.rb
@@ -2,6 +2,8 @@
module API
class ImportGithub < ::API::Base
+ feature_category :importers
+
rescue_from Octokit::Unauthorized, with: :provider_unauthorized
before do
@@ -11,7 +13,7 @@ module API
helpers do
def client
@client ||= if Feature.enabled?(:remove_legacy_github_client)
- Gitlab::GithubImport::Client.new(params[:personal_access_token])
+ Gitlab::GithubImport::Client.new(params[:personal_access_token], host: params[:github_hostname])
else
Gitlab::LegacyGithubImport::Client.new(params[:personal_access_token], client_options)
end
@@ -22,7 +24,7 @@ module API
end
def client_options
- {}
+ { host: params[:github_hostname] }
end
def provider
@@ -43,6 +45,7 @@ module API
requires :repo_id, type: Integer, desc: 'GitHub repository ID'
optional :new_name, type: String, desc: 'New repo name'
requires :target_namespace, type: String, desc: 'Namespace to import repo into'
+ optional :github_hostname, type: String, desc: 'Custom GitHub enterprise hostname'
end
post 'import/github' do
result = Import::GithubService.new(client, current_user, params).execute(access_params, provider)
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
index 6d8f13c36e6..61ef1d5bde0 100644
--- a/lib/api/internal/base.rb
+++ b/lib/api/internal/base.rb
@@ -7,10 +7,16 @@ module API
before { authenticate_by_gitlab_shell_token! }
before do
+ api_endpoint = env['api.endpoint']
+ feature_category = api_endpoint.options[:for].try(:feature_category_for_app, api_endpoint).to_s
+
+ header[Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER] = feature_category
+
Gitlab::ApplicationContext.push(
user: -> { actor&.user },
project: -> { project },
- caller_id: route.origin
+ caller_id: route.origin,
+ feature_category: feature_category
)
end
@@ -28,10 +34,10 @@ module API
{ status: success, message: message }.merge(extra_options).compact
end
- def lfs_authentication_url(project)
+ def lfs_authentication_url(container)
# This is a separate method so that EE can alter its behaviour more
# easily.
- project.http_url_to_repo
+ container.lfs_http_url_to_repo
end
def check_allowed(params)
@@ -122,13 +128,15 @@ module API
# changes - changes as "oldrev newrev ref", see Gitlab::ChangesList
# check_ip - optional, only in EE version, may limit access to
# group resources based on its IP restrictions
- post "/allowed" do
+ post "/allowed", feature_category: :source_code_management do
# It was moved to a separate method so that EE can alter its behaviour more
# easily.
check_allowed(params)
end
- post "/lfs_authenticate" do
+ post "/lfs_authenticate", feature_category: :source_code_management do
+ not_found! unless container&.lfs_enabled?
+
status 200
unless actor.key_or_user
@@ -139,14 +147,14 @@ module API
Gitlab::LfsToken
.new(actor.key_or_user)
- .authentication_payload(lfs_authentication_url(project))
+ .authentication_payload(lfs_authentication_url(container))
end
#
# Get a ssh key using the fingerprint
#
# rubocop: disable CodeReuse/ActiveRecord
- get '/authorized_keys' do
+ get '/authorized_keys', feature_category: :source_code_management do
fingerprint = params.fetch(:fingerprint) do
Gitlab::InsecureKeyFingerprint.new(params.fetch(:key)).fingerprint
end
@@ -159,11 +167,11 @@ module API
#
# Discover user by ssh key, user id or username
#
- get '/discover' do
+ get '/discover', feature_category: :authentication_and_authorization do
present actor.user, with: Entities::UserSafe
end
- get '/check' do
+ get '/check', feature_category: :not_owned do
{
api_version: API.version,
gitlab_version: Gitlab::VERSION,
@@ -172,7 +180,7 @@ module API
}
end
- post '/two_factor_recovery_codes' do
+ post '/two_factor_recovery_codes', feature_category: :authentication_and_authorization do
status 200
actor.update_last_used_at!
@@ -201,7 +209,7 @@ module API
{ success: true, recovery_codes: codes }
end
- post '/personal_access_token' do
+ post '/personal_access_token', feature_category: :authentication_and_authorization do
status 200
actor.update_last_used_at!
@@ -239,7 +247,7 @@ module API
end
result = ::PersonalAccessTokens::CreateService.new(
- user, name: params[:name], scopes: params[:scopes], expires_at: expires_at
+ current_user: user, target_user: user, params: { name: params[:name], scopes: params[:scopes], expires_at: expires_at }
).execute
unless result.status == :success
@@ -251,7 +259,7 @@ module API
{ success: true, token: access_token.token, scopes: access_token.scopes, expires_at: access_token.expires_at }
end
- post '/pre_receive' do
+ post '/pre_receive', feature_category: :source_code_management do
status 200
reference_counter_increased = Gitlab::ReferenceCounter.new(params[:gl_repository]).increase
@@ -259,7 +267,7 @@ module API
{ reference_counter_increased: reference_counter_increased }
end
- post '/post_receive' do
+ post '/post_receive', feature_category: :source_code_management do
status 200
response = PostReceiveService.new(actor.user, repository, project, params).execute
@@ -267,7 +275,7 @@ module API
present response, with: Entities::InternalPostReceive::Response
end
- post '/two_factor_config' do
+ post '/two_factor_config', feature_category: :authentication_and_authorization do
status 200
break { success: false } unless Feature.enabled?(:two_factor_for_cli)
@@ -289,7 +297,7 @@ module API
end
end
- post '/two_factor_otp_check' do
+ post '/two_factor_otp_check', feature_category: :authentication_and_authorization do
status 200
break { success: false } unless Feature.enabled?(:two_factor_for_cli)
diff --git a/lib/api/internal/kubernetes.rb b/lib/api/internal/kubernetes.rb
index 90e224b2ccb..d4690709de4 100644
--- a/lib/api/internal/kubernetes.rb
+++ b/lib/api/internal/kubernetes.rb
@@ -4,6 +4,8 @@ module API
# Kubernetes Internal API
module Internal
class Kubernetes < ::API::Base
+ feature_category :kubernetes_management
+
before do
check_feature_enabled
authenticate_gitlab_kas_request!
diff --git a/lib/api/internal/lfs.rb b/lib/api/internal/lfs.rb
index 630f0ec77a8..66baa4f1034 100644
--- a/lib/api/internal/lfs.rb
+++ b/lib/api/internal/lfs.rb
@@ -7,6 +7,8 @@ module API
before { authenticate_by_gitlab_shell_token! }
+ feature_category :source_code_management
+
helpers do
def find_lfs_object(lfs_oid)
LfsObject.find_by_oid(lfs_oid)
diff --git a/lib/api/internal/pages.rb b/lib/api/internal/pages.rb
index 51136144c19..690f52d89f3 100644
--- a/lib/api/internal/pages.rb
+++ b/lib/api/internal/pages.rb
@@ -4,6 +4,8 @@ module API
# Pages Internal API
module Internal
class Pages < ::API::Base
+ feature_category :pages
+
before do
authenticate_gitlab_pages_request!
end
diff --git a/lib/api/invitations.rb b/lib/api/invitations.rb
new file mode 100644
index 00000000000..be8147908e9
--- /dev/null
+++ b/lib/api/invitations.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module API
+ class Invitations < ::API::Base
+ include PaginationParams
+
+ feature_category :users
+
+ before { authenticate! }
+
+ helpers ::API::Helpers::MembersHelpers
+
+ %w[group project].each do |source_type|
+ params do
+ requires :id, type: String, desc: "The #{source_type} ID"
+ end
+ resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc 'Invite non-members by email address to a group or project.' do
+ detail 'This feature was introduced in GitLab 13.6'
+ success Entities::Invitation
+ end
+ params do
+ requires :email, types: [String, Array[String]], email_or_email_list: true, desc: 'The email address to invite, or multiple emails separated by comma'
+ requires :access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'A valid access level (defaults: `30`, developer access level)'
+ optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
+ end
+ post ":id/invitations" do
+ source = find_source(source_type, params[:id])
+
+ authorize_admin_source!(source_type, source)
+
+ ::Members::InviteService.new(current_user, params).execute(source)
+ end
+
+ desc 'Get a list of group or project invitations viewable by the authenticated user' do
+ detail 'This feature was introduced in GitLab 13.6'
+ success Entities::Invitation
+ end
+ params do
+ optional :query, type: String, desc: 'A query string to search for members'
+ use :pagination
+ end
+ get ":id/invitations" do
+ source = find_source(source_type, params[:id])
+ query = params[:query]
+
+ invitations = paginate(retrieve_member_invitations(source, query))
+
+ present_member_invitations invitations
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/issue_links.rb b/lib/api/issue_links.rb
index db4979c9052..e938dbbae87 100644
--- a/lib/api/issue_links.rb
+++ b/lib/api/issue_links.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :issue_tracking
+
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'
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 143f9e40736..6a6ee7a4e1c 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -8,6 +8,8 @@ module API
before { authenticate_non_get! }
+ feature_category :issue_tracking
+
helpers do
params :negatable_issue_filter_params do
optional :labels, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
@@ -26,6 +28,8 @@ module API
coerce_with: Validations::Validators::CheckAssigneesCount.coerce,
desc: 'Return issues which are assigned to the user with the given username'
mutually_exclusive :assignee_id, :assignee_username
+
+ use :negatable_issue_filter_params_ee
end
params :issues_stats_params do
diff --git a/lib/api/job_artifacts.rb b/lib/api/job_artifacts.rb
index 536b361b308..1faa28d6f07 100644
--- a/lib/api/job_artifacts.rb
+++ b/lib/api/job_artifacts.rb
@@ -4,6 +4,8 @@ module API
class JobArtifacts < ::API::Base
before { authenticate_non_get! }
+ feature_category :continuous_integration
+
# EE::API::JobArtifacts would override the following helpers
helpers do
def authorize_download_artifacts!
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index bdb23b4a9be..51659c2e8a1 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :continuous_integration
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/keys.rb b/lib/api/keys.rb
index 2e4568029b5..fb1bedd5e92 100644
--- a/lib/api/keys.rb
+++ b/lib/api/keys.rb
@@ -5,6 +5,8 @@ module API
class Keys < ::API::Base
before { authenticate! }
+ feature_category :authentication_and_authorization
+
resource :keys do
desc 'Get single ssh key by id. Only available to admin users' do
success Entities::SSHKeyWithUser
diff --git a/lib/api/labels.rb b/lib/api/labels.rb
index 0cc9f33bd07..a8fc277989e 100644
--- a/lib/api/labels.rb
+++ b/lib/api/labels.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
+ feature_category :issue_tracking
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
@@ -19,10 +21,12 @@ module API
desc: 'Include issue and merge request counts'
optional :include_ancestor_groups, type: Boolean, default: true,
desc: 'Include ancestor groups'
+ optional :search, type: String,
+ desc: 'Keyword to filter labels by. This feature was added in GitLab 13.6'
use :pagination
end
get ':id/labels' do
- get_labels(user_project, Entities::ProjectLabel, include_ancestor_groups: params[:include_ancestor_groups])
+ get_labels(user_project, Entities::ProjectLabel, declared_params)
end
desc 'Get a single label' do
@@ -34,7 +38,7 @@ module API
desc: 'Include ancestor groups'
end
get ':id/labels/:name' do
- get_label(user_project, Entities::ProjectLabel, include_ancestor_groups: params[:include_ancestor_groups])
+ get_label(user_project, Entities::ProjectLabel, declared_params)
end
desc 'Create a new label' do
diff --git a/lib/api/lint.rb b/lib/api/lint.rb
index bfd152f70b1..58181adaa93 100644
--- a/lib/api/lint.rb
+++ b/lib/api/lint.rb
@@ -2,6 +2,8 @@
module API
class Lint < ::API::Base
+ feature_category :pipeline_authoring
+
namespace :ci do
desc 'Validation of .gitlab-ci.yml content'
params do
@@ -15,9 +17,9 @@ module API
status 200
response = if error.blank?
- { status: 'valid', errors: [] }
+ { status: 'valid', errors: [], warnings: result.warnings }
else
- { status: 'invalid', errors: [error] }
+ { status: 'invalid', errors: [error], warnings: result.warnings }
end
response.tap do |response|
@@ -44,5 +46,25 @@ module API
present result, with: Entities::Ci::Lint::Result, current_user: current_user
end
end
+
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc 'Validation of .gitlab-ci.yml content' do
+ detail 'This feature was introduced in GitLab 13.6.'
+ end
+ params do
+ requires :content, type: String, desc: 'Content of .gitlab-ci.yml'
+ optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
+ end
+ post ':id/ci/lint' do
+ authorize! :download_code, user_project
+
+ result = Gitlab::Ci::Lint
+ .new(project: user_project, current_user: current_user)
+ .validate(params[:content], dry_run: params[:dry_run])
+
+ status 200
+ present result, with: Entities::Ci::Lint::Result, current_user: current_user
+ end
+ end
end
end
diff --git a/lib/api/markdown.rb b/lib/api/markdown.rb
index 97549abd273..de612ff8321 100644
--- a/lib/api/markdown.rb
+++ b/lib/api/markdown.rb
@@ -2,6 +2,8 @@
module API
class Markdown < ::API::Base
+ feature_category :not_owned
+
params do
requires :text, type: String, desc: "The markdown text to render"
optional :gfm, type: Boolean, desc: "Render text using GitLab Flavored Markdown"
diff --git a/lib/api/maven_packages.rb b/lib/api/maven_packages.rb
index a3e2fa84c32..7b4e52d18e8 100644
--- a/lib/api/maven_packages.rb
+++ b/lib/api/maven_packages.rb
@@ -5,6 +5,8 @@ module API
file_name: API::NO_SLASH_URL_PART_REGEX
}.freeze
+ feature_category :package_registry
+
content_type :md5, 'text/plain'
content_type :sha1, 'text/plain'
content_type :binary, 'application/octet-stream'
@@ -244,7 +246,7 @@ module API
file_md5: params['file.md5']
}
- ::Packages::CreatePackageFileService.new(package, file_params).execute
+ ::Packages::CreatePackageFileService.new(package, file_params.merge(build: current_authenticated_job)).execute
end
end
end
diff --git a/lib/api/members.rb b/lib/api/members.rb
index c28b3b1cc7c..803de51651a 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :authentication_and_authorization
+
helpers ::API::Helpers::MembersHelpers
%w[group project].each do |source_type|
@@ -134,7 +136,7 @@ module API
source = find_source(source_type, params.delete(:id))
authorize_admin_source!(source_type, source)
- member = source.members.find_by!(user_id: params[:user_id])
+ member = source_members(source).find_by!(user_id: params[:user_id])
updated_member =
::Members::UpdateService
.new(current_user, declared_params(include_missing: false))
@@ -157,7 +159,7 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
delete ":id/members/:user_id" do
source = find_source(source_type, params[:id])
- member = source.members.find_by!(user_id: params[:user_id])
+ member = source_members(source).find_by!(user_id: params[:user_id])
destroy_conditionally!(member) do
::Members::DestroyService.new(current_user).execute(member, unassign_issuables: params[:unassign_issuables])
diff --git a/lib/api/merge_request_approvals.rb b/lib/api/merge_request_approvals.rb
index 14d6e3995ea..27ef0b9c7cd 100644
--- a/lib/api/merge_request_approvals.rb
+++ b/lib/api/merge_request_approvals.rb
@@ -4,6 +4,8 @@ module API
class MergeRequestApprovals < ::API::Base
before { authenticate_non_get! }
+ feature_category :code_review
+
helpers do
params :ee_approval_params do
end
diff --git a/lib/api/merge_request_diffs.rb b/lib/api/merge_request_diffs.rb
index 22023888bbd..0ffb38438eb 100644
--- a/lib/api/merge_request_diffs.rb
+++ b/lib/api/merge_request_diffs.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
+ feature_category :code_review
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index b24dd870c8b..d17e451093b 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -8,6 +8,8 @@ module API
before { authenticate_non_get! }
+ feature_category :code_review
+
helpers Helpers::MergeRequestsHelpers
# EE::API::MergeRequests would override the following helpers
@@ -350,7 +352,11 @@ module API
get ':id/merge_requests/:merge_request_iid/changes' do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
- present merge_request, with: Entities::MergeRequestChanges, current_user: current_user, project: user_project
+ present merge_request,
+ with: Entities::MergeRequestChanges,
+ current_user: current_user,
+ project: user_project,
+ access_raw_diffs: params.fetch(:access_raw_diffs, false)
end
desc 'Get the merge request pipelines' do
diff --git a/lib/api/metrics/dashboard/annotations.rb b/lib/api/metrics/dashboard/annotations.rb
index b6bc0af2202..0989340b3ea 100644
--- a/lib/api/metrics/dashboard/annotations.rb
+++ b/lib/api/metrics/dashboard/annotations.rb
@@ -4,6 +4,8 @@ module API
module Metrics
module Dashboard
class Annotations < ::API::Base
+ feature_category :metrics
+
desc 'Create a new monitoring dashboard annotation' do
success Entities::Metrics::Dashboard::Annotation
end
diff --git a/lib/api/metrics/user_starred_dashboards.rb b/lib/api/metrics/user_starred_dashboards.rb
index cb6e7099247..909f7f0405d 100644
--- a/lib/api/metrics/user_starred_dashboards.rb
+++ b/lib/api/metrics/user_starred_dashboards.rb
@@ -3,6 +3,8 @@
module API
module Metrics
class UserStarredDashboards < ::API::Base
+ feature_category :metrics
+
resource :projects do
desc 'Marks selected metrics dashboard as starred' do
success Entities::Metrics::UserStarredDashboard
diff --git a/lib/api/namespaces.rb b/lib/api/namespaces.rb
index f98a1f6dd1d..25a901c18b6 100644
--- a/lib/api/namespaces.rb
+++ b/lib/api/namespaces.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :subgroups
+
helpers do
params :optional_list_params_ee do
# EE::API::Namespaces would override this helper
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index 0db537ca616..d249431b2f8 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -7,7 +7,7 @@ module API
before { authenticate! }
- Helpers::NotesHelpers.noteable_types.each do |noteable_type|
+ Helpers::NotesHelpers.feature_category_per_noteable_type.each do |noteable_type, feature_category|
parent_type = noteable_type.parent_class.to_s.underscore
noteables_str = noteable_type.to_s.underscore.pluralize
@@ -29,7 +29,7 @@ module API
use :pagination
end
# rubocop: disable CodeReuse/ActiveRecord
- get ":id/#{noteables_str}/:noteable_id/notes" do
+ get ":id/#{noteables_str}/:noteable_id/notes", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
# We exclude notes that are cross-references and that cannot be viewed
@@ -57,7 +57,7 @@ module API
requires :note_id, type: Integer, desc: 'The ID of a note'
requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
end
- get ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
+ get ":id/#{noteables_str}/:noteable_id/notes/:note_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
get_note(noteable, params[:note_id])
end
@@ -71,7 +71,7 @@ module API
optional :confidential, type: Boolean, desc: 'Confidentiality note flag, default is false'
optional :created_at, type: String, desc: 'The creation date of the note'
end
- post ":id/#{noteables_str}/:noteable_id/notes" do
+ post ":id/#{noteables_str}/:noteable_id/notes", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
opts = {
@@ -104,7 +104,7 @@ module API
optional :body, type: String, allow_blank: false, desc: 'The content of a note'
optional :confidential, type: Boolean, desc: 'Confidentiality note flag'
end
- put ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
+ put ":id/#{noteables_str}/:noteable_id/notes/:note_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
update_note(noteable, params[:note_id])
diff --git a/lib/api/notification_settings.rb b/lib/api/notification_settings.rb
index bad3f5ead7a..7d28394e034 100644
--- a/lib/api/notification_settings.rb
+++ b/lib/api/notification_settings.rb
@@ -5,6 +5,8 @@ module API
class NotificationSettings < ::API::Base
before { authenticate! }
+ feature_category :users
+
helpers ::API::Helpers::MembersHelpers
resource :notification_settings do
diff --git a/lib/api/npm_instance_packages.rb b/lib/api/npm_instance_packages.rb
new file mode 100644
index 00000000000..12fc008e00f
--- /dev/null
+++ b/lib/api/npm_instance_packages.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+module API
+ class NpmInstancePackages < ::API::Base
+ helpers ::API::Helpers::Packages::Npm
+
+ feature_category :package_registry
+
+ rescue_from ActiveRecord::RecordInvalid do |e|
+ render_api_error!(e.message, 400)
+ end
+
+ namespace 'packages/npm' do
+ include ::API::Concerns::Packages::NpmEndpoints
+ end
+ end
+end
diff --git a/lib/api/npm_packages.rb b/lib/api/npm_packages.rb
deleted file mode 100644
index 1443b28c1ee..00000000000
--- a/lib/api/npm_packages.rb
+++ /dev/null
@@ -1,173 +0,0 @@
-# frozen_string_literal: true
-module API
- class NpmPackages < ::API::Base
- helpers ::API::Helpers::PackagesHelpers
- helpers ::API::Helpers::Packages::DependencyProxyHelpers
-
- NPM_ENDPOINT_REQUIREMENTS = {
- package_name: API::NO_SLASH_URL_PART_REGEX
- }.freeze
-
- rescue_from ActiveRecord::RecordInvalid do |e|
- render_api_error!(e.message, 400)
- end
-
- before do
- require_packages_enabled!
- authenticate_non_get!
- end
-
- helpers do
- def project_by_package_name
- strong_memoize(:project_by_package_name) do
- ::Packages::Package.npm.with_name(params[:package_name]).first&.project
- end
- end
- end
-
- desc 'Get all tags for a given an NPM package' do
- detail 'This feature was introduced in GitLab 12.7'
- success ::API::Entities::NpmPackageTag
- end
- params do
- requires :package_name, type: String, desc: 'Package name'
- end
- get 'packages/npm/-/package/*package_name/dist-tags', format: false, requirements: NPM_ENDPOINT_REQUIREMENTS do
- package_name = params[:package_name]
-
- bad_request!('Package Name') if package_name.blank?
-
- authorize_read_package!(project_by_package_name)
-
- packages = ::Packages::Npm::PackageFinder.new(project_by_package_name, package_name)
- .execute
-
- present ::Packages::Npm::PackagePresenter.new(package_name, packages),
- with: ::API::Entities::NpmPackageTag
- end
-
- params do
- requires :package_name, type: String, desc: 'Package name'
- requires :tag, type: String, desc: "Package dist-tag"
- end
- namespace 'packages/npm/-/package/*package_name/dist-tags/:tag', requirements: NPM_ENDPOINT_REQUIREMENTS do
- desc 'Create or Update the given tag for the given NPM package and version' do
- detail 'This feature was introduced in GitLab 12.7'
- end
- put format: false do
- package_name = params[:package_name]
- version = env['api.request.body']
- tag = params[:tag]
-
- bad_request!('Package Name') if package_name.blank?
- bad_request!('Version') if version.blank?
- bad_request!('Tag') if tag.blank?
-
- authorize_create_package!(project_by_package_name)
-
- package = ::Packages::Npm::PackageFinder
- .new(project_by_package_name, package_name)
- .find_by_version(version)
- not_found!('Package') unless package
-
- ::Packages::Npm::CreateTagService.new(package, tag).execute
-
- no_content!
- end
-
- desc 'Deletes the given tag' do
- detail 'This feature was introduced in GitLab 12.7'
- end
- delete format: false do
- package_name = params[:package_name]
- tag = params[:tag]
-
- bad_request!('Package Name') if package_name.blank?
- bad_request!('Tag') if tag.blank?
-
- authorize_destroy_package!(project_by_package_name)
-
- package_tag = ::Packages::TagsFinder
- .new(project_by_package_name, package_name, package_type: :npm)
- .find_by_name(tag)
-
- not_found!('Package tag') unless package_tag
-
- ::Packages::RemoveTagService.new(package_tag).execute
-
- no_content!
- end
- end
-
- desc 'NPM registry endpoint at instance level' do
- detail 'This feature was introduced in GitLab 11.8'
- end
- params do
- requires :package_name, type: String, desc: 'Package name'
- end
- route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
- get 'packages/npm/*package_name', format: false, requirements: NPM_ENDPOINT_REQUIREMENTS do
- package_name = params[:package_name]
-
- redirect_registry_request(project_by_package_name.blank?, :npm, package_name: package_name) do
- authorize_read_package!(project_by_package_name)
-
- packages = ::Packages::Npm::PackageFinder
- .new(project_by_package_name, package_name).execute
-
- present ::Packages::Npm::PackagePresenter.new(package_name, packages),
- with: ::API::Entities::NpmPackage
- end
- end
-
- params do
- requires :id, type: String, desc: 'The ID of a project'
- end
- resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- desc 'Download the NPM tarball' do
- detail 'This feature was introduced in GitLab 11.8'
- end
- params do
- requires :package_name, type: String, desc: 'Package name'
- requires :file_name, type: String, desc: 'Package file name'
- end
- route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
- get ':id/packages/npm/*package_name/-/*file_name', format: false do
- authorize_read_package!(user_project)
-
- package = user_project.packages.npm
- .by_name_and_file_name(params[:package_name], params[:file_name])
-
- package_file = ::Packages::PackageFileFinder
- .new(package, params[:file_name]).execute!
-
- track_package_event('pull_package', package)
-
- present_carrierwave_file!(package_file.file)
- end
-
- desc 'Create NPM package' do
- detail 'This feature was introduced in GitLab 11.8'
- end
- params do
- requires :package_name, type: String, desc: 'Package name'
- requires :versions, type: Hash, desc: 'Package version info'
- end
- route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
- put ':id/packages/npm/:package_name', requirements: NPM_ENDPOINT_REQUIREMENTS do
- authorize_create_package!(user_project)
-
- track_package_event('push_package', :npm)
-
- created_package = ::Packages::Npm::CreatePackageService
- .new(user_project, current_user, params.merge(build: current_authenticated_job)).execute
-
- if created_package[:status] == :error
- render_api_error!(created_package[:message], created_package[:http_status])
- else
- created_package
- end
- end
- end
- end
-end
diff --git a/lib/api/npm_project_packages.rb b/lib/api/npm_project_packages.rb
new file mode 100644
index 00000000000..887084dc9ae
--- /dev/null
+++ b/lib/api/npm_project_packages.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+module API
+ class NpmProjectPackages < ::API::Base
+ helpers ::API::Helpers::Packages::Npm
+
+ feature_category :package_registry
+
+ rescue_from ActiveRecord::RecordInvalid do |e|
+ render_api_error!(e.message, 400)
+ end
+
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
+ namespace 'projects/:id/packages/npm' do
+ desc 'Download the NPM tarball' do
+ detail 'This feature was introduced in GitLab 11.8'
+ end
+ params do
+ requires :package_name, type: String, desc: 'Package name'
+ requires :file_name, type: String, desc: 'Package file name'
+ end
+ route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
+ get '*package_name/-/*file_name', format: false do
+ authorize_read_package!(project)
+
+ package = project.packages.npm
+ .by_name_and_file_name(params[:package_name], params[:file_name])
+
+ not_found!('Package') unless package
+
+ package_file = ::Packages::PackageFileFinder
+ .new(package, params[:file_name]).execute!
+
+ track_package_event('pull_package', package, category: 'API::NpmPackages')
+
+ present_carrierwave_file!(package_file.file)
+ end
+
+ desc 'Create NPM package' do
+ detail 'This feature was introduced in GitLab 11.8'
+ end
+ params do
+ requires :package_name, type: String, desc: 'Package name'
+ requires :versions, type: Hash, desc: 'Package version info'
+ end
+ route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
+ put ':package_name', requirements: ::API::Helpers::Packages::Npm::NPM_ENDPOINT_REQUIREMENTS do
+ authorize_create_package!(project)
+
+ track_package_event('push_package', :npm, category: 'API::NpmPackages')
+
+ created_package = ::Packages::Npm::CreatePackageService
+ .new(project, current_user, params.merge(build: current_authenticated_job)).execute
+
+ if created_package[:status] == :error
+ render_api_error!(created_package[:message], created_package[:http_status])
+ else
+ created_package
+ end
+ end
+
+ include ::API::Concerns::Packages::NpmEndpoints
+ end
+ end
+end
diff --git a/lib/api/nuget_packages.rb b/lib/api/nuget_packages.rb
index 0f2c956a9df..65a85f3c930 100644
--- a/lib/api/nuget_packages.rb
+++ b/lib/api/nuget_packages.rb
@@ -10,6 +10,8 @@ module API
helpers ::API::Helpers::PackagesManagerClientsHelpers
helpers ::API::Helpers::Packages::BasicAuthHelpers
+ feature_category :package_registry
+
POSITIVE_INTEGER_REGEX = %r{\A[1-9]\d*\z}.freeze
NON_NEGATIVE_INTEGER_REGEX = %r{\A0|[1-9]\d*\z}.freeze
diff --git a/lib/api/package_files.rb b/lib/api/package_files.rb
index c1fc9a6e4d8..4a33f3e8af2 100644
--- a/lib/api/package_files.rb
+++ b/lib/api/package_files.rb
@@ -8,6 +8,8 @@ module API
authorize_packages_access!(user_project)
end
+ feature_category :package_registry
+
helpers ::API::Helpers::PackagesHelpers
params do
diff --git a/lib/api/pages.rb b/lib/api/pages.rb
index 813307c498f..5f695f3853d 100644
--- a/lib/api/pages.rb
+++ b/lib/api/pages.rb
@@ -2,6 +2,8 @@
module API
class Pages < ::API::Base
+ feature_category :pages
+
before do
require_pages_config_enabled!
authenticated_with_can_read_all_resources!
diff --git a/lib/api/pages_domains.rb b/lib/api/pages_domains.rb
index 00c51298c45..2e7f8475509 100644
--- a/lib/api/pages_domains.rb
+++ b/lib/api/pages_domains.rb
@@ -4,6 +4,8 @@ module API
class PagesDomains < ::API::Base
include PaginationParams
+ feature_category :pages
+
PAGES_DOMAINS_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(domain: API::NO_SLASH_URL_PART_REGEX)
before do
diff --git a/lib/api/personal_access_tokens.rb b/lib/api/personal_access_tokens.rb
new file mode 100644
index 00000000000..2c60938b75a
--- /dev/null
+++ b/lib/api/personal_access_tokens.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module API
+ class PersonalAccessTokens < ::API::Base
+ include ::API::PaginationParams
+
+ feature_category :authentication_and_authorization
+
+ desc 'Get all Personal Access Tokens' do
+ detail 'This feature was added in GitLab 13.3'
+ success Entities::PersonalAccessToken
+ end
+ params do
+ optional :user_id, type: Integer, desc: 'User ID'
+
+ use :pagination
+ end
+
+ before do
+ authenticate!
+ restrict_non_admins! unless current_user.admin?
+ end
+
+ helpers do
+ def finder_params(current_user)
+ current_user.admin? ? { user: user(params[:user_id]) } : { user: current_user }
+ end
+
+ def user(user_id)
+ UserFinder.new(user_id).find_by_id
+ end
+
+ def restrict_non_admins!
+ return if params[:user_id].blank?
+
+ unauthorized! unless Ability.allowed?(current_user, :read_user_personal_access_tokens, user(params[:user_id]))
+ end
+
+ def find_token(id)
+ PersonalAccessToken.find(id) || not_found!
+ end
+ end
+
+ resources :personal_access_tokens do
+ get do
+ tokens = PersonalAccessTokensFinder.new(finder_params(current_user), current_user).execute
+
+ present paginate(tokens), with: Entities::PersonalAccessToken
+ end
+
+ delete ':id' do
+ service = ::PersonalAccessTokens::RevokeService.new(
+ current_user,
+ token: find_token(params[:id])
+ ).execute
+
+ service.success? ? no_content! : bad_request!(nil)
+ end
+ end
+ end
+end
diff --git a/lib/api/project_clusters.rb b/lib/api/project_clusters.rb
index 46ccb4ba1a0..cfb0c5fd705 100644
--- a/lib/api/project_clusters.rb
+++ b/lib/api/project_clusters.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :kubernetes_management
+
params do
requires :id, type: String, desc: 'The ID of the project'
end
diff --git a/lib/api/project_container_repositories.rb b/lib/api/project_container_repositories.rb
index d565531d372..3125de88de5 100644
--- a/lib/api/project_container_repositories.rb
+++ b/lib/api/project_container_repositories.rb
@@ -10,6 +10,8 @@ module API
before { authorize_read_container_images! }
+ feature_category :package_registry
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/project_events.rb b/lib/api/project_events.rb
index 3765473bc0e..69b47f9420d 100644
--- a/lib/api/project_events.rb
+++ b/lib/api/project_events.rb
@@ -6,6 +6,8 @@ module API
include APIGuard
helpers ::API::Helpers::EventsHelpers
+ feature_category :users
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/project_export.rb b/lib/api/project_export.rb
index 184f89200ab..76b3dea723a 100644
--- a/lib/api/project_export.rb
+++ b/lib/api/project_export.rb
@@ -4,6 +4,8 @@ module API
class ProjectExport < ::API::Base
helpers Helpers::RateLimiter
+ feature_category :importers
+
before do
not_found! unless Gitlab::CurrentSettings.project_export_enabled?
authorize_admin_project
diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb
index bc2d8c816a8..431ba199131 100644
--- a/lib/api/project_hooks.rb
+++ b/lib/api/project_hooks.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
before { authorize_admin_project }
+ feature_category :integrations
+
helpers do
params :project_hook_properties do
requires :url, type: String, desc: "The URL to send the request to"
@@ -21,6 +23,7 @@ module API
optional :pipeline_events, type: Boolean, desc: "Trigger hook on pipeline events"
optional :wiki_page_events, type: Boolean, desc: "Trigger hook on wiki events"
optional :deployment_events, type: Boolean, desc: "Trigger hook on deployment events"
+ optional :releases_events, type: Boolean, desc: "Trigger hook on release events"
optional :enable_ssl_verification, type: Boolean, desc: "Do SSL verification when triggering the hook"
optional :token, type: String, desc: "Secret token to validate received payloads; this will not be returned in the response"
optional :push_events_branch_filter, type: String, desc: "Trigger hook on specified branch only"
diff --git a/lib/api/project_import.rb b/lib/api/project_import.rb
index 5c4e1d73ee1..15b06cea385 100644
--- a/lib/api/project_import.rb
+++ b/lib/api/project_import.rb
@@ -8,6 +8,8 @@ module API
helpers Helpers::FileUploadHelpers
helpers Helpers::RateLimiter
+ feature_category :importers
+
helpers do
def import_params
declared_params(include_missing: false)
diff --git a/lib/api/project_milestones.rb b/lib/api/project_milestones.rb
index a81118f44bd..8675de33923 100644
--- a/lib/api/project_milestones.rb
+++ b/lib/api/project_milestones.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
+ feature_category :issue_tracking
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/project_packages.rb b/lib/api/project_packages.rb
index b8d97b1243a..56e94333433 100644
--- a/lib/api/project_packages.rb
+++ b/lib/api/project_packages.rb
@@ -8,6 +8,8 @@ module API
authorize_packages_access!(user_project)
end
+ feature_category :package_registry
+
helpers ::API::Helpers::PackagesHelpers
params do
diff --git a/lib/api/project_repository_storage_moves.rb b/lib/api/project_repository_storage_moves.rb
index 38eb74663d3..fe6de3ea385 100644
--- a/lib/api/project_repository_storage_moves.rb
+++ b/lib/api/project_repository_storage_moves.rb
@@ -6,6 +6,8 @@ module API
before { authenticated_as_admin! }
+ feature_category :gitaly
+
resource :project_repository_storage_moves do
desc 'Get a list of all project repository storage moves' do
detail 'This feature was introduced in GitLab 13.0.'
diff --git a/lib/api/project_snapshots.rb b/lib/api/project_snapshots.rb
index e19afb6e8e4..d33d2976b1c 100644
--- a/lib/api/project_snapshots.rb
+++ b/lib/api/project_snapshots.rb
@@ -6,6 +6,8 @@ module API
before { authorize_read_git_snapshot! }
+ feature_category :source_code_management
+
resource :projects do
desc 'Download a (possibly inconsistent) snapshot of a repository' do
detail 'This feature was introduced in GitLab 10.7'
diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb
index b4de260fe49..899984fe0ba 100644
--- a/lib/api/project_snippets.rb
+++ b/lib/api/project_snippets.rb
@@ -6,6 +6,8 @@ module API
before { check_snippets_enabled }
+ feature_category :snippets
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/project_statistics.rb b/lib/api/project_statistics.rb
index 1ead969fc81..3db8d20ebac 100644
--- a/lib/api/project_statistics.rb
+++ b/lib/api/project_statistics.rb
@@ -2,6 +2,8 @@
module API
class ProjectStatistics < ::API::Base
+ feature_category :source_code_management
+
before do
authenticate!
authorize! :daily_statistics, user_project
diff --git a/lib/api/project_templates.rb b/lib/api/project_templates.rb
index 7d851de0237..af5d96969ef 100644
--- a/lib/api/project_templates.rb
+++ b/lib/api/project_templates.rb
@@ -12,6 +12,8 @@ module API
before { authenticate_non_get! }
+ feature_category :templates
+
params do
requires :id, type: String, desc: 'The ID of a project'
requires :type, type: String, values: TEMPLATE_TYPES, desc: 'The type (dockerfiles|gitignores|gitlab_ci_ymls|licenses|metrics_dashboard_ymls|issues|merge_requests) of the template'
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index ecee76ae60c..2012c348cd1 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -11,6 +11,8 @@ module API
before { authenticate_non_get! }
+ feature_category :projects, ['/projects/:id/custom_attributes', '/projects/:id/custom_attributes/:key']
+
helpers do
# EE::API::Projects would override this method
def apply_filters(projects)
@@ -150,7 +152,7 @@ module API
use :statistics_params
use :with_custom_attributes
end
- get ":user_id/projects" do
+ get ":user_id/projects", feature_category: :projects do
user = find_user(params[:user_id])
not_found!('User') unless user
@@ -167,7 +169,7 @@ module API
use :collection_params
use :statistics_params
end
- get ":user_id/starred_projects" do
+ get ":user_id/starred_projects", feature_category: :projects do
user = find_user(params[:user_id])
not_found!('User') unless user
@@ -187,7 +189,7 @@ module API
use :statistics_params
use :with_custom_attributes
end
- get do
+ get feature_category: :projects do
present_projects load_projects
end
@@ -234,7 +236,7 @@ module API
use :create_params
end
# rubocop: disable CodeReuse/ActiveRecord
- post "user/:user_id" do
+ post "user/:user_id", feature_category: :projects do
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/21139')
authenticated_as_admin!
user = User.find_by(id: params.delete(:user_id))
@@ -270,7 +272,7 @@ module API
optional :license, type: Boolean, default: false,
desc: 'Include project license data'
end
- get ":id" do
+ get ":id", feature_category: :projects do
options = {
with: current_user ? Entities::ProjectWithAccess : Entities::BasicProjectDetails,
current_user: current_user,
@@ -294,7 +296,7 @@ module API
optional :path, type: String, desc: 'The path that will be assigned to the fork'
optional :name, type: String, desc: 'The name that will be assigned to the fork'
end
- post ':id/fork' do
+ post ':id/fork', feature_category: :source_code_management do
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42284')
not_found! unless can?(current_user, :fork_project, user_project)
@@ -332,14 +334,14 @@ module API
use :collection_params
use :with_custom_attributes
end
- get ':id/forks' do
+ get ':id/forks', feature_category: :source_code_management do
forks = ForkProjectsFinder.new(user_project, params: project_finder_params, current_user: current_user).execute
present_projects forks, request_scope: user_project
end
desc 'Check pages access of this project'
- get ':id/pages_access' do
+ get ':id/pages_access', feature_category: :pages do
authorize! :read_pages_content, user_project unless user_project.public_pages?
status 200
end
@@ -357,7 +359,7 @@ module API
at_least_one_of(*Helpers::ProjectsHelpers.update_params_at_least_one_of)
end
- put ':id' do
+ put ':id', feature_category: :projects do
authorize_admin_project
attrs = declared_params(include_missing: false)
authorize! :rename_project, user_project if attrs[:name].present?
@@ -381,7 +383,7 @@ module API
desc 'Archive a project' do
success Entities::Project
end
- post ':id/archive' do
+ post ':id/archive', feature_category: :projects do
authorize!(:archive_project, user_project)
::Projects::UpdateService.new(user_project, current_user, archived: true).execute
@@ -392,7 +394,7 @@ module API
desc 'Unarchive a project' do
success Entities::Project
end
- post ':id/unarchive' do
+ post ':id/unarchive', feature_category: :projects do
authorize!(:archive_project, user_project)
::Projects::UpdateService.new(user_project, current_user, archived: false).execute
@@ -403,7 +405,7 @@ module API
desc 'Star a project' do
success Entities::Project
end
- post ':id/star' do
+ post ':id/star', feature_category: :projects do
if current_user.starred?(user_project)
not_modified!
else
@@ -417,7 +419,7 @@ module API
desc 'Unstar a project' do
success Entities::Project
end
- post ':id/unstar' do
+ post ':id/unstar', feature_category: :projects do
if current_user.starred?(user_project)
current_user.toggle_star(user_project)
user_project.reset
@@ -435,21 +437,21 @@ module API
optional :search, type: String, desc: 'Return list of users matching the search criteria'
use :pagination
end
- get ':id/starrers' do
+ get ':id/starrers', feature_category: :projects do
starrers = UsersStarProjectsFinder.new(user_project, params, current_user: current_user).execute
present paginate(starrers), with: Entities::UserStarsProject
end
desc 'Get languages in project repository'
- get ':id/languages' do
+ get ':id/languages', feature_category: :source_code_management do
::Projects::RepositoryLanguagesService
.new(user_project, current_user)
.execute.map { |lang| [lang.name, lang.share] }.to_h
end
desc 'Delete a project'
- delete ":id" do
+ delete ":id", feature_category: :projects do
authorize! :remove_project, user_project
delete_project(user_project)
@@ -459,7 +461,7 @@ module API
params do
requires :forked_from_id, type: String, desc: 'The ID of the project it was forked from'
end
- post ":id/fork/:forked_from_id" do
+ post ":id/fork/:forked_from_id", feature_category: :source_code_management do
authorize! :admin_project, user_project
fork_from_project = find_project!(params[:forked_from_id])
@@ -478,7 +480,7 @@ module API
end
desc 'Remove a forked_from relationship'
- delete ":id/fork" do
+ delete ":id/fork", feature_category: :source_code_management do
authorize! :remove_fork_project, user_project
result = destroy_conditionally!(user_project) do
@@ -496,7 +498,7 @@ module API
requires :group_access, type: Integer, values: Gitlab::Access.values, as: :link_group_access, desc: 'The group access level'
optional :expires_at, type: Date, desc: 'Share expiration date'
end
- post ":id/share" do
+ post ":id/share", feature_category: :authentication_and_authorization do
authorize! :admin_project, user_project
group = Group.find_by_id(params[:group_id])
@@ -518,7 +520,7 @@ module API
requires :group_id, type: Integer, desc: 'The ID of the group'
end
# rubocop: disable CodeReuse/ActiveRecord
- delete ":id/share/:group_id" do
+ delete ":id/share/:group_id", feature_category: :authentication_and_authorization do
authorize! :admin_project, user_project
link = user_project.project_group_links.find_by(group_id: params[:group_id])
@@ -535,7 +537,7 @@ module API
# TODO: remove rubocop disable - https://gitlab.com/gitlab-org/gitlab/issues/14960
requires :file, type: File, desc: 'The file to be uploaded' # rubocop:disable Scalability/FileUploads
end
- post ":id/uploads" do
+ post ":id/uploads", feature_category: :not_owned do
upload = UploadService.new(user_project, params[:file]).execute
present upload, with: Entities::ProjectUpload
@@ -549,7 +551,7 @@ module API
optional :skip_users, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Filter out users with the specified IDs'
use :pagination
end
- get ':id/users' do
+ get ':id/users', feature_category: :authentication_and_authorization do
users = DeclarativePolicy.subject_scope { user_project.team.users }
users = users.search(params[:search]) if params[:search].present?
users = users.where_not_in(params[:skip_users]) if params[:skip_users].present?
@@ -560,7 +562,7 @@ module API
desc 'Start the housekeeping task for a project' do
detail 'This feature was introduced in GitLab 9.0.'
end
- post ':id/housekeeping' do
+ post ':id/housekeeping', feature_category: :source_code_management do
authorize_admin_project
begin
@@ -574,7 +576,7 @@ module API
params do
requires :namespace, type: String, desc: 'The ID or path of the new namespace'
end
- put ":id/transfer" do
+ put ":id/transfer", feature_category: :projects do
authorize! :change_namespace, user_project
namespace = find_namespace!(params[:namespace])
diff --git a/lib/api/protected_branches.rb b/lib/api/protected_branches.rb
index a448682d8bd..17574739a7c 100644
--- a/lib/api/protected_branches.rb
+++ b/lib/api/protected_branches.rb
@@ -8,6 +8,8 @@ module API
before { authorize_admin_project }
+ feature_category :source_code_management
+
helpers Helpers::ProtectedBranchesHelpers
params do
diff --git a/lib/api/protected_tags.rb b/lib/api/protected_tags.rb
index dd3e407ffc9..b9385df1f8d 100644
--- a/lib/api/protected_tags.rb
+++ b/lib/api/protected_tags.rb
@@ -8,6 +8,8 @@ module API
before { authorize_admin_project }
+ feature_category :source_code_management
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/pypi_packages.rb b/lib/api/pypi_packages.rb
index 5622bc6e42d..7104fb8d999 100644
--- a/lib/api/pypi_packages.rb
+++ b/lib/api/pypi_packages.rb
@@ -12,6 +12,8 @@ module API
helpers ::API::Helpers::Packages::BasicAuthHelpers
include ::API::Helpers::Packages::BasicAuthHelpers::Constants
+ feature_category :package_registry
+
default_format :json
rescue_from ArgumentError do |e|
diff --git a/lib/api/release/links.rb b/lib/api/release/links.rb
index 23de9f9fc9f..d3a185a51c8 100644
--- a/lib/api/release/links.rb
+++ b/lib/api/release/links.rb
@@ -10,6 +10,8 @@ module API
before { authorize! :read_release, user_project }
+ feature_category :release_orchestration
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/releases.rb b/lib/api/releases.rb
index 3bd6ea77403..c20e618efd1 100644
--- a/lib/api/releases.rb
+++ b/lib/api/releases.rb
@@ -9,6 +9,8 @@ module API
before { authorize_read_releases! }
+ feature_category :release_orchestration
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
@@ -89,7 +91,7 @@ module API
optional :name, type: String, desc: 'The name of the release'
optional :description, type: String, desc: 'Release notes with markdown support'
optional :released_at, type: DateTime, desc: 'The date when the release will be/was ready.'
- optional :milestones, type: Array, desc: 'The titles of the related milestones'
+ optional :milestones, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The titles of the related milestones'
end
put ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
authorize_update_release!
diff --git a/lib/api/remote_mirrors.rb b/lib/api/remote_mirrors.rb
index f63ea04a529..83096772d32 100644
--- a/lib/api/remote_mirrors.rb
+++ b/lib/api/remote_mirrors.rb
@@ -4,6 +4,8 @@ module API
class RemoteMirrors < ::API::Base
include PaginationParams
+ feature_category :source_code_management
+
before do
unauthorized! unless can?(current_user, :admin_remote_mirror, user_project)
end
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 38ac1f22a48..8af8ffc3b63 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -6,10 +6,14 @@ module API
class Repositories < ::API::Base
include PaginationParams
+ content_type :txt, 'text/plain'
+
helpers ::API::Helpers::HeadersHelpers
before { authorize! :download_code, user_project }
+ feature_category :source_code_management
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/resource_label_events.rb b/lib/api/resource_label_events.rb
index d3a219f0810..33589f6c393 100644
--- a/lib/api/resource_label_events.rb
+++ b/lib/api/resource_label_events.rb
@@ -7,7 +7,7 @@ module API
before { authenticate! }
- Helpers::ResourceLabelEventsHelpers.eventable_types.each do |eventable_type|
+ Helpers::ResourceLabelEventsHelpers.feature_category_per_eventable_type.each do |eventable_type, feature_category|
parent_type = eventable_type.parent_class.to_s.underscore
eventables_str = eventable_type.to_s.underscore.pluralize
@@ -24,7 +24,7 @@ module API
use :pagination
end
- get ":id/#{eventables_str}/:eventable_id/resource_label_events" do
+ get ":id/#{eventables_str}/:eventable_id/resource_label_events", feature_category: feature_category do
eventable = find_noteable(eventable_type, params[:eventable_id])
events = eventable.resource_label_events.inc_relations
@@ -40,7 +40,7 @@ module API
requires :event_id, type: String, desc: 'The ID of a resource label event'
requires :eventable_id, types: [Integer, String], desc: 'The ID of the eventable'
end
- get ":id/#{eventables_str}/:eventable_id/resource_label_events/:event_id" do
+ get ":id/#{eventables_str}/:eventable_id/resource_label_events/:event_id", feature_category: feature_category do
eventable = find_noteable(eventable_type, params[:eventable_id])
event = eventable.resource_label_events.find(params[:event_id])
diff --git a/lib/api/resource_milestone_events.rb b/lib/api/resource_milestone_events.rb
index 21411f68dd5..aeedd7ad109 100644
--- a/lib/api/resource_milestone_events.rb
+++ b/lib/api/resource_milestone_events.rb
@@ -7,7 +7,10 @@ module API
before { authenticate! }
- [Issue, MergeRequest].each do |eventable_type|
+ {
+ Issue => :issue_tracking,
+ MergeRequest => :code_review
+ }.each do |eventable_type, feature_category|
parent_type = eventable_type.parent_class.to_s.underscore
eventables_str = eventable_type.to_s.underscore.pluralize
@@ -23,7 +26,7 @@ module API
use :pagination
end
- get ":id/#{eventables_str}/:eventable_id/resource_milestone_events" do
+ get ":id/#{eventables_str}/:eventable_id/resource_milestone_events", feature_category: feature_category do
eventable = find_noteable(eventable_type, params[:eventable_id])
events = ResourceMilestoneEventFinder.new(current_user, eventable).execute
@@ -38,7 +41,7 @@ module API
requires :event_id, type: String, desc: 'The ID of a resource milestone event'
requires :eventable_id, types: [Integer, String], desc: 'The ID of the eventable'
end
- get ":id/#{eventables_str}/:eventable_id/resource_milestone_events/:event_id" do
+ get ":id/#{eventables_str}/:eventable_id/resource_milestone_events/:event_id", feature_category: feature_category do
eventable = find_noteable(eventable_type, params[:eventable_id])
event = eventable.resource_milestone_events.find(params[:event_id])
diff --git a/lib/api/resource_state_events.rb b/lib/api/resource_state_events.rb
index 9bfda39be90..3460aa2c00e 100644
--- a/lib/api/resource_state_events.rb
+++ b/lib/api/resource_state_events.rb
@@ -7,7 +7,10 @@ module API
before { authenticate! }
- [Issue, MergeRequest].each do |eventable_class|
+ {
+ Issue => :issue_tracking,
+ MergeRequest => :code_review
+ }.each do |eventable_class, feature_category|
eventable_name = eventable_class.to_s.underscore
params do
@@ -22,7 +25,7 @@ module API
use :pagination
end
- get ":id/#{eventable_name.pluralize}/:eventable_iid/resource_state_events" do
+ get ":id/#{eventable_name.pluralize}/:eventable_iid/resource_state_events", feature_category: feature_category do
eventable = find_noteable(eventable_class, params[:eventable_iid])
events = ResourceStateEventFinder.new(current_user, eventable).execute
@@ -37,7 +40,7 @@ module API
requires :eventable_iid, types: Integer, desc: "The IID of the #{eventable_name}"
requires :event_id, type: Integer, desc: 'The ID of a resource state event'
end
- get ":id/#{eventable_name.pluralize}/:eventable_iid/resource_state_events/:event_id" do
+ get ":id/#{eventable_name.pluralize}/:eventable_iid/resource_state_events/:event_id", feature_category: feature_category do
eventable = find_noteable(eventable_class, params[:eventable_iid])
event = ResourceStateEventFinder.new(current_user, eventable).find(params[:event_id])
diff --git a/lib/api/search.rb b/lib/api/search.rb
index 85f0a8e2e60..f0ffe6ba443 100644
--- a/lib/api/search.rb
+++ b/lib/api/search.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :global_search
+
helpers do
SCOPE_ENTITY = {
merge_requests: Entities::MergeRequestBasic,
@@ -35,8 +37,11 @@ module API
state: params[:state],
confidential: params[:confidential],
snippets: snippets?,
+ basic_search: params[:basic_search],
page: params[:page],
- per_page: params[:per_page]
+ per_page: params[:per_page],
+ order_by: params[:order_by],
+ sort: params[:sort]
}.merge(additional_params)
results = SearchService.new(current_user, search_params).search_objects(preload_method)
diff --git a/lib/api/services.rb b/lib/api/services.rb
index 5f3d14010a8..cfcae13e518 100644
--- a/lib/api/services.rb
+++ b/lib/api/services.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
module API
class Services < ::API::Base
+ feature_category :integrations
+
services = Helpers::ServicesHelpers.services
service_classes = Helpers::ServicesHelpers.service_classes
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index dc917d9c529..b95856d99d1 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -4,6 +4,8 @@ module API
class Settings < ::API::Base
before { authenticated_as_admin! }
+ feature_category :not_owned
+
helpers Helpers::SettingsHelpers
helpers do
@@ -51,9 +53,9 @@ module API
optional :default_projects_limit, type: Integer, desc: 'The maximum number of personal projects'
optional :default_snippet_visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The default snippet visibility'
optional :disabled_oauth_sign_in_sources, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Disable certain OAuth sign-in sources'
- optional :domain_blacklist_enabled, type: Boolean, desc: 'Enable domain blacklist for sign ups'
- optional :domain_blacklist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com'
- optional :domain_whitelist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com'
+ optional :domain_denylist_enabled, type: Boolean, desc: 'Enable domain denylist for sign ups'
+ optional :domain_denylist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com'
+ optional :domain_allowlist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com'
optional :eks_integration_enabled, type: Boolean, desc: 'Enable integration with Amazon EKS'
given eks_integration_enabled: -> (val) { val } do
requires :eks_account_id, type: String, desc: 'Amazon account ID for EKS integration'
@@ -157,6 +159,7 @@ module API
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"
+ optional :require_admin_approval_after_user_signup, type: Boolean, desc: 'Require explicit admin approval for new signups'
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 b025dbfab37..680363d036e 100644
--- a/lib/api/sidekiq_metrics.rb
+++ b/lib/api/sidekiq_metrics.rb
@@ -6,6 +6,8 @@ module API
class SidekiqMetrics < ::API::Base
before { authenticated_as_admin! }
+ feature_category :not_owned
+
helpers do
def queue_metrics
Sidekiq::Queue.all.each_with_object({}) do |queue, hash|
diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb
index 2e67b9649bc..52b597fb788 100644
--- a/lib/api/snippets.rb
+++ b/lib/api/snippets.rb
@@ -5,6 +5,8 @@ module API
class Snippets < ::API::Base
include PaginationParams
+ feature_category :snippets
+
resource :snippets do
helpers Helpers::SnippetsHelpers
helpers do
diff --git a/lib/api/statistics.rb b/lib/api/statistics.rb
index fa7176491ba..1814e1a6782 100644
--- a/lib/api/statistics.rb
+++ b/lib/api/statistics.rb
@@ -4,6 +4,8 @@ module API
class Statistics < ::API::Base
before { authenticated_as_admin! }
+ feature_category :instance_statistics
+
COUNTED_ITEMS = [Project, User, Group, ForkNetworkMember, ForkNetwork, Issue,
MergeRequest, Note, Snippet, Key, Milestone].freeze
diff --git a/lib/api/submodules.rb b/lib/api/submodules.rb
index e2ceb49c119..5c71a18c6d0 100644
--- a/lib/api/submodules.rb
+++ b/lib/api/submodules.rb
@@ -4,6 +4,8 @@ module API
class Submodules < ::API::Base
before { authenticate! }
+ feature_category :source_code_management
+
helpers do
def commit_params(attrs)
{
diff --git a/lib/api/subscriptions.rb b/lib/api/subscriptions.rb
index 35a28da4736..914bab52929 100644
--- a/lib/api/subscriptions.rb
+++ b/lib/api/subscriptions.rb
@@ -11,25 +11,29 @@ module API
type: 'merge_requests',
entity: Entities::MergeRequest,
source: Project,
- finder: ->(id) { find_merge_request_with_access(id, :update_merge_request) }
+ finder: ->(id) { find_merge_request_with_access(id, :update_merge_request) },
+ feature_category: :code_review
},
{
type: 'issues',
entity: Entities::Issue,
source: Project,
- finder: ->(id) { find_project_issue(id) }
+ finder: ->(id) { find_project_issue(id) },
+ feature_category: :issue_tracking
},
{
type: 'labels',
entity: Entities::ProjectLabel,
source: Project,
- finder: ->(id) { find_label(user_project, id) }
+ finder: ->(id) { find_label(user_project, id) },
+ feature_category: :issue_tracking
},
{
type: 'labels',
entity: Entities::GroupLabel,
source: Group,
- finder: ->(id) { find_label(user_group, id) }
+ finder: ->(id) { find_label(user_group, id) },
+ feature_category: :issue_tracking
}
]
@@ -44,7 +48,7 @@ module API
desc 'Subscribe to a resource' do
success subscribable[:entity]
end
- post ":id/#{subscribable[:type]}/:subscribable_id/subscribe" do
+ post ":id/#{subscribable[:type]}/:subscribable_id/subscribe", subscribable.slice(:feature_category) do
parent = parent_resource(source_type)
resource = instance_exec(params[:subscribable_id], &subscribable[:finder])
@@ -59,7 +63,7 @@ module API
desc 'Unsubscribe from a resource' do
success subscribable[:entity]
end
- post ":id/#{subscribable[:type]}/:subscribable_id/unsubscribe" do
+ post ":id/#{subscribable[:type]}/:subscribable_id/unsubscribe", subscribable.slice(:feature_category) do
parent = parent_resource(source_type)
resource = instance_exec(params[:subscribable_id], &subscribable[:finder])
diff --git a/lib/api/suggestions.rb b/lib/api/suggestions.rb
index f23d279c3f4..a024d6de874 100644
--- a/lib/api/suggestions.rb
+++ b/lib/api/suggestions.rb
@@ -4,6 +4,8 @@ module API
class Suggestions < ::API::Base
before { authenticate! }
+ feature_category :code_review
+
resource :suggestions do
desc 'Apply suggestion patch in the Merge Request it was created' do
success Entities::Suggestion
diff --git a/lib/api/system_hooks.rb b/lib/api/system_hooks.rb
index 2820d305d0f..42e16d47a0b 100644
--- a/lib/api/system_hooks.rb
+++ b/lib/api/system_hooks.rb
@@ -4,6 +4,8 @@ module API
class SystemHooks < ::API::Base
include PaginationParams
+ feature_category :integrations
+
before do
authenticate!
authenticated_as_admin!
diff --git a/lib/api/tags.rb b/lib/api/tags.rb
index b969394ec47..7636c45bdac 100644
--- a/lib/api/tags.rb
+++ b/lib/api/tags.rb
@@ -23,7 +23,7 @@ module API
optional :search, type: String, desc: 'Return list of tags matching the search criteria'
use :pagination
end
- get ':id/repository/tags' do
+ get ':id/repository/tags', feature_category: :source_code_management do
tags = ::TagsFinder.new(user_project.repository,
sort: "#{params[:order_by]}_#{params[:sort]}",
search: params[:search]).execute
@@ -37,7 +37,7 @@ module API
params do
requires :tag_name, type: String, desc: 'The name of the tag'
end
- get ':id/repository/tags/:tag_name', requirements: TAG_ENDPOINT_REQUIREMENTS do
+ get ':id/repository/tags/:tag_name', requirements: TAG_ENDPOINT_REQUIREMENTS, feature_category: :source_code_management do
tag = user_project.repository.find_tag(params[:tag_name])
not_found!('Tag') unless tag
@@ -54,7 +54,7 @@ module API
optional :message, type: String, desc: 'Specifying a message creates an annotated tag'
optional :release_description, type: String, desc: 'Specifying release notes stored in the GitLab database (deprecated in GitLab 11.7)'
end
- post ':id/repository/tags' do
+ post ':id/repository/tags', :release_orchestration do
authorize_admin_tag
result = ::Tags::CreateService.new(user_project, current_user)
@@ -86,7 +86,7 @@ module API
params do
requires :tag_name, type: String, desc: 'The name of the tag'
end
- delete ':id/repository/tags/:tag_name', requirements: TAG_ENDPOINT_REQUIREMENTS do
+ delete ':id/repository/tags/:tag_name', requirements: TAG_ENDPOINT_REQUIREMENTS, feature_category: :source_code_management do
authorize_admin_tag
tag = user_project.repository.find_tag(params[:tag_name])
@@ -112,7 +112,7 @@ module API
requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
requires :description, type: String, desc: 'Release notes with markdown support'
end
- post ':id/repository/tags/:tag_name/release', requirements: TAG_ENDPOINT_REQUIREMENTS do
+ post ':id/repository/tags/:tag_name/release', requirements: TAG_ENDPOINT_REQUIREMENTS, feature_category: :release_orchestration do
authorize_create_release!
##
@@ -144,7 +144,7 @@ module API
requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
requires :description, type: String, desc: 'Release notes with markdown support'
end
- put ':id/repository/tags/:tag_name/release', requirements: TAG_ENDPOINT_REQUIREMENTS do
+ put ':id/repository/tags/:tag_name/release', requirements: TAG_ENDPOINT_REQUIREMENTS, feature_category: :release_orchestration do
authorize_update_release!
result = ::Releases::UpdateService
diff --git a/lib/api/templates.rb b/lib/api/templates.rb
index 0b427bbf5b9..b7fb35eac03 100644
--- a/lib/api/templates.rb
+++ b/lib/api/templates.rb
@@ -4,6 +4,8 @@ module API
class Templates < ::API::Base
include PaginationParams
+ feature_category :templates
+
GLOBAL_TEMPLATE_TYPES = {
gitignores: {
gitlab_version: 8.8
diff --git a/lib/api/terraform/state.rb b/lib/api/terraform/state.rb
index 3dbde4639ca..c664c0a4590 100644
--- a/lib/api/terraform/state.rb
+++ b/lib/api/terraform/state.rb
@@ -7,6 +7,8 @@ module API
class State < ::API::Base
include ::Gitlab::Utils::StrongMemoize
+ feature_category :infrastructure_as_code
+
default_format :json
before do
@@ -51,7 +53,7 @@ module API
no_content! if data.empty?
remote_state_handler.handle_with_lock do |state|
- state.update_file!(CarrierWaveStringFile.new(data), version: params[:serial])
+ state.update_file!(CarrierWaveStringFile.new(data), version: params[:serial], build: current_authenticated_job)
end
body false
diff --git a/lib/api/terraform/state_version.rb b/lib/api/terraform/state_version.rb
index b4a0efd7a2b..d3680323b9f 100644
--- a/lib/api/terraform/state_version.rb
+++ b/lib/api/terraform/state_version.rb
@@ -5,6 +5,8 @@ module API
class StateVersion < ::API::Base
default_format :json
+ feature_category :infrastructure_as_code
+
before do
authenticate!
authorize! :read_terraform_state, user_project
diff --git a/lib/api/todos.rb b/lib/api/todos.rb
index ce07d13cc9a..03850ba1c4e 100644
--- a/lib/api/todos.rb
+++ b/lib/api/todos.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :issue_tracking
+
ISSUABLE_TYPES = {
'merge_requests' => ->(iid) { find_merge_request_with_access(iid) },
'issues' => ->(iid) { find_project_issue(iid) }
diff --git a/lib/api/triggers.rb b/lib/api/triggers.rb
index 960d004a04c..aebbc95cbea 100644
--- a/lib/api/triggers.rb
+++ b/lib/api/triggers.rb
@@ -6,6 +6,8 @@ module API
HTTP_GITLAB_EVENT_HEADER = "HTTP_#{WebHookService::GITLAB_EVENT_HEADER}".underscore.upcase
+ feature_category :continuous_integration
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/unleash.rb b/lib/api/unleash.rb
index 907422118f1..3148c56339a 100644
--- a/lib/api/unleash.rb
+++ b/lib/api/unleash.rb
@@ -4,6 +4,8 @@ module API
class Unleash < ::API::Base
include PaginationParams
+ feature_category :feature_flags
+
namespace :feature_flags do
resource :unleash, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
params do
diff --git a/lib/api/usage_data.rb b/lib/api/usage_data.rb
index fa5bfc1cbe9..7b038ec74bb 100644
--- a/lib/api/usage_data.rb
+++ b/lib/api/usage_data.rb
@@ -4,6 +4,8 @@ module API
class UsageData < ::API::Base
before { authenticate! }
+ feature_category :collection
+
namespace 'usage_data' do
before do
not_found! unless Feature.enabled?(:usage_data_api, default_enabled: true)
diff --git a/lib/api/user_counts.rb b/lib/api/user_counts.rb
index 6d9db53fec8..3071f08e1de 100644
--- a/lib/api/user_counts.rb
+++ b/lib/api/user_counts.rb
@@ -2,6 +2,8 @@
module API
class UserCounts < ::API::Base
+ feature_category :navigation
+
resource :user_counts do
desc 'Return the user specific counts' do
detail 'Open MR Count'
diff --git a/lib/api/users.rb b/lib/api/users.rb
index e7c1d644324..501ed629c7e 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -8,6 +8,8 @@ module API
allow_access_with_scope :read_user, if: -> (request) { request.get? }
+ feature_category :users, ['/users/:id/custom_attributes', '/users/:id/custom_attributes/:key']
+
resource :users, requirements: { uid: /[0-9]*/, id: /[0-9]*/ } do
include CustomAttributesEndpoints
@@ -63,9 +65,9 @@ module API
params :sort_params do
optional :order_by, type: String, values: %w[id name username created_at updated_at],
- default: 'id', desc: 'Return users ordered by a field'
+ default: 'id', desc: 'Return users ordered by a field'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
- desc: 'Return users sorted in ascending and descending order'
+ desc: 'Return users sorted in ascending and descending order'
end
end
@@ -93,7 +95,7 @@ module API
use :optional_index_params_ee
end
# rubocop: disable CodeReuse/ActiveRecord
- get do
+ get feature_category: :users do
authenticated_as_admin! if params[:external].present? || (params[:extern_uid].present? && params[:provider].present?)
unless current_user&.admin?
@@ -134,7 +136,7 @@ module API
use :with_custom_attributes
end
# rubocop: disable CodeReuse/ActiveRecord
- get ":id" do
+ get ":id", feature_category: :users do
user = User.find_by(id: params[:id])
not_found!('User') unless user && can?(current_user, :read_user, user)
@@ -149,7 +151,7 @@ module API
params do
requires :user_id, type: String, desc: 'The ID or username of the user'
end
- get ":user_id/status", requirements: API::USER_REQUIREMENTS do
+ get ":user_id/status", requirements: API::USER_REQUIREMENTS, feature_category: :users do
user = find_user(params[:user_id])
not_found!('User') unless user && can?(current_user, :read_user, user)
@@ -170,7 +172,7 @@ module API
optional :force_random_password, type: Boolean, desc: 'Flag indicating a random password will be set'
use :optional_attributes
end
- post do
+ post feature_category: :users do
authenticated_as_admin!
params = declared_params(include_missing: false)
@@ -204,7 +206,7 @@ module API
use :optional_attributes
end
# rubocop: disable CodeReuse/ActiveRecord
- put ":id" do
+ put ":id", feature_category: :users do
authenticated_as_admin!
user = User.find_by(id: params.delete(:id))
@@ -245,7 +247,7 @@ module API
requires :provider, type: String, desc: 'The external provider'
end
# rubocop: disable CodeReuse/ActiveRecord
- delete ":id/identities/:provider" do
+ delete ":id/identities/:provider", feature_category: :authentication_and_authorization do
authenticated_as_admin!
user = User.find_by(id: params[:id])
@@ -268,7 +270,7 @@ module API
optional :expires_at, type: DateTime, desc: 'The expiration date of the SSH key in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)'
end
# rubocop: disable CodeReuse/ActiveRecord
- post ":id/keys" do
+ post ":id/keys", feature_category: :authentication_and_authorization do
authenticated_as_admin!
user = User.find_by(id: params.delete(:id))
@@ -291,7 +293,7 @@ module API
requires :user_id, type: String, desc: 'The ID or username of the user'
use :pagination
end
- get ':user_id/keys', requirements: API::USER_REQUIREMENTS do
+ get ':user_id/keys', requirements: API::USER_REQUIREMENTS, feature_category: :authentication_and_authorization do
user = find_user(params[:user_id])
not_found!('User') unless user && can?(current_user, :read_user, user)
@@ -307,7 +309,7 @@ module API
requires :key_id, type: Integer, desc: 'The ID of the SSH key'
end
# rubocop: disable CodeReuse/ActiveRecord
- delete ':id/keys/:key_id' do
+ delete ':id/keys/:key_id', feature_category: :authentication_and_authorization do
authenticated_as_admin!
user = User.find_by(id: params[:id])
@@ -332,7 +334,7 @@ module API
requires :key, type: String, desc: 'The new GPG key'
end
# rubocop: disable CodeReuse/ActiveRecord
- post ':id/gpg_keys' do
+ post ':id/gpg_keys', feature_category: :authentication_and_authorization do
authenticated_as_admin!
user = User.find_by(id: params.delete(:id))
@@ -357,7 +359,7 @@ module API
use :pagination
end
# rubocop: disable CodeReuse/ActiveRecord
- get ':id/gpg_keys' do
+ get ':id/gpg_keys', feature_category: :authentication_and_authorization do
user = User.find_by(id: params[:id])
not_found!('User') unless user
@@ -374,7 +376,7 @@ module API
requires :key_id, type: Integer, desc: 'The ID of the GPG key'
end
# rubocop: disable CodeReuse/ActiveRecord
- get ':id/gpg_keys/:key_id' do
+ get ':id/gpg_keys/:key_id', feature_category: :authentication_and_authorization do
user = User.find_by(id: params[:id])
not_found!('User') unless user
@@ -393,7 +395,7 @@ module API
requires :key_id, type: Integer, desc: 'The ID of the GPG key'
end
# rubocop: disable CodeReuse/ActiveRecord
- delete ':id/gpg_keys/:key_id' do
+ delete ':id/gpg_keys/:key_id', feature_category: :authentication_and_authorization do
authenticated_as_admin!
user = User.find_by(id: params[:id])
@@ -417,7 +419,7 @@ module API
requires :key_id, type: Integer, desc: 'The ID of the GPG key'
end
# rubocop: disable CodeReuse/ActiveRecord
- post ':id/gpg_keys/:key_id/revoke' do
+ post ':id/gpg_keys/:key_id/revoke', feature_category: :authentication_and_authorization do
authenticated_as_admin!
user = User.find_by(id: params[:id])
@@ -440,7 +442,7 @@ module API
optional :skip_confirmation, type: Boolean, desc: 'Skip confirmation of email and assume it is verified'
end
# rubocop: disable CodeReuse/ActiveRecord
- post ":id/emails" do
+ post ":id/emails", feature_category: :users do
authenticated_as_admin!
user = User.find_by(id: params.delete(:id))
@@ -464,7 +466,7 @@ module API
use :pagination
end
# rubocop: disable CodeReuse/ActiveRecord
- get ':id/emails' do
+ get ':id/emails', feature_category: :users do
authenticated_as_admin!
user = User.find_by(id: params[:id])
not_found!('User') unless user
@@ -481,7 +483,7 @@ module API
requires :email_id, type: Integer, desc: 'The ID of the email'
end
# rubocop: disable CodeReuse/ActiveRecord
- delete ':id/emails/:email_id' do
+ delete ':id/emails/:email_id', feature_category: :users do
authenticated_as_admin!
user = User.find_by(id: params[:id])
not_found!('User') unless user
@@ -503,7 +505,7 @@ module API
optional :hard_delete, type: Boolean, desc: "Whether to remove a user's contributions"
end
# rubocop: disable CodeReuse/ActiveRecord
- delete ":id" do
+ delete ":id", feature_category: :users do
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/20757')
authenticated_as_admin!
@@ -523,7 +525,7 @@ module API
requires :id, type: Integer, desc: 'The ID of the user'
end
# rubocop: disable CodeReuse/ActiveRecord
- post ':id/activate' do
+ post ':id/activate', feature_category: :authentication_and_authorization do
authenticated_as_admin!
user = User.find_by(id: params[:id])
@@ -538,7 +540,7 @@ module API
requires :id, type: Integer, desc: 'The ID of the user'
end
# rubocop: disable CodeReuse/ActiveRecord
- post ':id/deactivate' do
+ post ':id/deactivate', feature_category: :authentication_and_authorization do
authenticated_as_admin!
user = User.find_by(id: params[:id])
not_found!('User') unless user
@@ -564,7 +566,7 @@ module API
requires :id, type: Integer, desc: 'The ID of the user'
end
# rubocop: disable CodeReuse/ActiveRecord
- post ':id/block' do
+ post ':id/block', feature_category: :authentication_and_authorization do
authenticated_as_admin!
user = User.find_by(id: params[:id])
not_found!('User') unless user
@@ -589,7 +591,7 @@ module API
requires :id, type: Integer, desc: 'The ID of the user'
end
# rubocop: disable CodeReuse/ActiveRecord
- post ':id/unblock' do
+ post ':id/unblock', feature_category: :authentication_and_authorization do
authenticated_as_admin!
user = User.find_by(id: params[:id])
not_found!('User') unless user
@@ -612,7 +614,7 @@ module API
optional :type, type: String, values: %w[Project Namespace]
use :pagination
end
- get ":user_id/memberships" do
+ get ":user_id/memberships", feature_category: :users do
authenticated_as_admin!
user = find_user_by_id(params)
@@ -656,7 +658,9 @@ module API
use :pagination
optional :state, type: String, default: 'all', values: %w[all active inactive], desc: 'Filters (all|active|inactive) impersonation_tokens'
end
- get { present paginate(finder(declared_params(include_missing: false)).execute), with: Entities::ImpersonationToken }
+ get feature_category :authentication_and_authorization do
+ present paginate(finder(declared_params(include_missing: false)).execute), with: Entities::ImpersonationToken
+ end
desc 'Create a impersonation token. Available only for admins.' do
detail 'This feature was introduced in GitLab 9.0'
@@ -667,7 +671,7 @@ module API
optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the impersonation token'
optional :scopes, type: Array, desc: 'The array of scopes of the impersonation token'
end
- post do
+ post feature_category: :authentication_and_authorization do
impersonation_token = finder.build(declared_params(include_missing: false))
if impersonation_token.save
@@ -684,7 +688,7 @@ module API
params do
requires :impersonation_token_id, type: Integer, desc: 'The ID of the impersonation token'
end
- get ':impersonation_token_id' do
+ get ':impersonation_token_id', feature_category: :authentication_and_authorization do
present find_impersonation_token, with: Entities::ImpersonationToken
end
@@ -694,7 +698,7 @@ module API
params do
requires :impersonation_token_id, type: Integer, desc: 'The ID of the impersonation token'
end
- delete ':impersonation_token_id' do
+ delete ':impersonation_token_id', feature_category: :authentication_and_authorization do
token = find_impersonation_token
destroy_conditionally!(token) do
@@ -702,6 +706,40 @@ module API
end
end
end
+
+ resource :personal_access_tokens do
+ helpers do
+ def target_user
+ find_user_by_id(params)
+ end
+ end
+
+ before { authenticated_as_admin! }
+
+ desc 'Create a personal access token. Available only for admins.' do
+ detail 'This feature was introduced in GitLab 13.6'
+ success Entities::PersonalAccessTokenWithToken
+ end
+ params do
+ requires :name, type: String, desc: 'The name of the personal access token'
+ requires :scopes, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, values: ::Gitlab::Auth.all_available_scopes.map(&:to_s),
+ desc: 'The array of scopes of the personal access token'
+ optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the personal access token'
+ end
+ post feature_category: :authentication_and_authorization do
+ not_found! unless Feature.enabled?(:pat_creation_api_for_admin)
+
+ response = ::PersonalAccessTokens::CreateService.new(
+ current_user: current_user, target_user: target_user, params: declared_params(include_missing: false)
+ ).execute
+
+ if response.success?
+ present response.payload[:personal_access_token], with: Entities::PersonalAccessTokenWithToken
+ else
+ render_api_error!(response.message, response.http_status || :unprocessable_entity)
+ end
+ end
+ end
end
end
@@ -716,7 +754,7 @@ module API
desc 'Get the currently authenticated user' do
success Entities::UserPublic
end
- get do
+ get feature_category: :users do
entity =
if current_user.admin?
Entities::UserWithAdmin
@@ -734,7 +772,7 @@ module API
params do
use :pagination
end
- get "keys" do
+ get "keys", feature_category: :authentication_and_authorization do
keys = current_user.keys.preload_users
present paginate(keys), with: Entities::SSHKey
@@ -747,7 +785,7 @@ module API
requires :key_id, type: Integer, desc: 'The ID of the SSH key'
end
# rubocop: disable CodeReuse/ActiveRecord
- get "keys/:key_id" do
+ get "keys/:key_id", feature_category: :authentication_and_authorization do
key = current_user.keys.find_by(id: params[:key_id])
not_found!('Key') unless key
@@ -763,7 +801,7 @@ module API
requires :title, type: String, desc: 'The title of the new SSH key'
optional :expires_at, type: DateTime, desc: 'The expiration date of the SSH key in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)'
end
- post "keys" do
+ post "keys", feature_category: :authentication_and_authorization do
key = ::Keys::CreateService.new(current_user, declared_params(include_missing: false)).execute
if key.persisted?
@@ -780,7 +818,7 @@ module API
requires :key_id, type: Integer, desc: 'The ID of the SSH key'
end
# rubocop: disable CodeReuse/ActiveRecord
- delete "keys/:key_id" do
+ delete "keys/:key_id", feature_category: :authentication_and_authorization do
key = current_user.keys.find_by(id: params[:key_id])
not_found!('Key') unless key
@@ -798,7 +836,7 @@ module API
params do
use :pagination
end
- get 'gpg_keys' do
+ get 'gpg_keys', feature_category: :authentication_and_authorization do
present paginate(current_user.gpg_keys), with: Entities::GpgKey
end
@@ -810,7 +848,7 @@ module API
requires :key_id, type: Integer, desc: 'The ID of the GPG key'
end
# rubocop: disable CodeReuse/ActiveRecord
- get 'gpg_keys/:key_id' do
+ get 'gpg_keys/:key_id', feature_category: :authentication_and_authorization do
key = current_user.gpg_keys.find_by(id: params[:key_id])
not_found!('GPG Key') unless key
@@ -825,7 +863,7 @@ module API
params do
requires :key, type: String, desc: 'The new GPG key'
end
- post 'gpg_keys' do
+ post 'gpg_keys', feature_category: :authentication_and_authorization do
key = ::GpgKeys::CreateService.new(current_user, declared_params(include_missing: false)).execute
if key.persisted?
@@ -842,7 +880,7 @@ module API
requires :key_id, type: Integer, desc: 'The ID of the GPG key'
end
# rubocop: disable CodeReuse/ActiveRecord
- post 'gpg_keys/:key_id/revoke' do
+ post 'gpg_keys/:key_id/revoke', feature_category: :authentication_and_authorization do
key = current_user.gpg_keys.find_by(id: params[:key_id])
not_found!('GPG Key') unless key
@@ -858,7 +896,7 @@ module API
requires :key_id, type: Integer, desc: 'The ID of the SSH key'
end
# rubocop: disable CodeReuse/ActiveRecord
- delete 'gpg_keys/:key_id' do
+ delete 'gpg_keys/:key_id', feature_category: :authentication_and_authorization do
key = current_user.gpg_keys.find_by(id: params[:key_id])
not_found!('GPG Key') unless key
@@ -875,7 +913,7 @@ module API
params do
use :pagination
end
- get "emails" do
+ get "emails", feature_category: :users do
present paginate(current_user.emails), with: Entities::Email
end
@@ -886,7 +924,7 @@ module API
requires :email_id, type: Integer, desc: 'The ID of the email'
end
# rubocop: disable CodeReuse/ActiveRecord
- get "emails/:email_id" do
+ get "emails/:email_id", feature_category: :users do
email = current_user.emails.find_by(id: params[:email_id])
not_found!('Email') unless email
@@ -900,7 +938,7 @@ module API
params do
requires :email, type: String, desc: 'The new email'
end
- post "emails" do
+ post "emails", feature_category: :users do
email = Emails::CreateService.new(current_user, declared_params.merge(user: current_user)).execute
if email.errors.blank?
@@ -915,7 +953,7 @@ module API
requires :email_id, type: Integer, desc: 'The ID of the email'
end
# rubocop: disable CodeReuse/ActiveRecord
- delete "emails/:email_id" do
+ delete "emails/:email_id", feature_category: :users do
email = current_user.emails.find_by(id: params[:email_id])
not_found!('Email') unless email
@@ -931,7 +969,7 @@ module API
use :pagination
end
# rubocop: disable CodeReuse/ActiveRecord
- get "activities" do
+ get "activities", feature_category: :users do
authenticated_as_admin!
activities = User
@@ -948,8 +986,9 @@ module API
params do
optional :emoji, type: String, desc: "The emoji to set on the status"
optional :message, type: String, desc: "The status message to set"
+ optional :availability, type: String, desc: "The availability of user to set"
end
- put "status" do
+ put "status", feature_category: :users do
forbidden! unless can?(current_user, :update_user_status, current_user)
if ::Users::SetStatusService.new(current_user, declared_params).execute
@@ -962,7 +1001,7 @@ module API
desc 'get the status of the current user' do
success Entities::UserStatus
end
- get 'status' do
+ get 'status', feature_category: :users do
present current_user.status || {}, with: Entities::UserStatus
end
end
diff --git a/lib/api/v3/github.rb b/lib/api/v3/github.rb
index aed88e6091c..327335aec2d 100644
--- a/lib/api/v3/github.rb
+++ b/lib/api/v3/github.rb
@@ -22,6 +22,8 @@ module API
include PaginationParams
+ feature_category :integrations
+
before do
authorize_jira_user_agent!(request)
authenticate!
diff --git a/lib/api/validations/validators/email_or_email_list.rb b/lib/api/validations/validators/email_or_email_list.rb
new file mode 100644
index 00000000000..b7f2a0cd443
--- /dev/null
+++ b/lib/api/validations/validators/email_or_email_list.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module API
+ module Validations
+ module Validators
+ class EmailOrEmailList < Grape::Validations::Base
+ def validate_param!(attr_name, params)
+ value = params[attr_name]
+
+ return unless value
+
+ return if value.split(',').map { |v| ValidateEmail.valid?(v) }.all?
+
+ raise Grape::Exceptions::Validation,
+ params: [@scope.full_name(attr_name)],
+ message: "contains an invalid email address"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/variables.rb b/lib/api/variables.rb
index f5de3d844e6..94fa98b7a14 100644
--- a/lib/api/variables.rb
+++ b/lib/api/variables.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
before { authorize! :admin_build, user_project }
+ feature_category :continuous_integration
+
helpers do
def filter_variable_parameters(params)
# This method exists so that EE can more easily filter out certain
diff --git a/lib/api/version.rb b/lib/api/version.rb
index 841b55f8d6c..f8072658cc6 100644
--- a/lib/api/version.rb
+++ b/lib/api/version.rb
@@ -9,6 +9,8 @@ module API
before { authenticate! }
+ feature_category :not_owned
+
METADATA_QUERY = <<~EOF
{
metadata {
diff --git a/lib/api/wikis.rb b/lib/api/wikis.rb
index 21f457046f1..3fa42be47a9 100644
--- a/lib/api/wikis.rb
+++ b/lib/api/wikis.rb
@@ -4,6 +4,8 @@ module API
class Wikis < ::API::Base
helpers ::API::Helpers::WikisHelpers
+ feature_category :wiki
+
helpers do
attr_reader :container
diff --git a/lib/atlassian/jira_connect/client.rb b/lib/atlassian/jira_connect/client.rb
index 0b578c03782..f81ed462174 100644
--- a/lib/atlassian/jira_connect/client.rb
+++ b/lib/atlassian/jira_connect/client.rb
@@ -3,19 +3,25 @@
module Atlassian
module JiraConnect
class Client < Gitlab::HTTP
+ def self.generate_update_sequence_id
+ Gitlab::Metrics::System.monotonic_time.to_i
+ end
+
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)
+ def store_dev_info(project:, commits: nil, branches: nil, merge_requests: nil, update_sequence_id: nil)
dev_info_json = {
repositories: [
Serializers::RepositoryEntity.represent(
project,
commits: commits,
branches: branches,
- merge_requests: merge_requests
+ merge_requests: merge_requests,
+ user_notes_count: user_notes_count(merge_requests),
+ update_sequence_id: update_sequence_id
)
]
}.to_json
@@ -32,6 +38,14 @@ module Atlassian
private
+ def user_notes_count(merge_requests)
+ return unless merge_requests
+
+ Note.count_for_collection(merge_requests.map(&:id), 'MergeRequest').map do |count_group|
+ [count_group.noteable_id, count_group.count]
+ end.to_h
+ end
+
def jwt_token(http_method, uri)
claims = Atlassian::Jwt.build_claims(
Atlassian::JiraConnect.app_key,
diff --git a/lib/atlassian/jira_connect/serializers/base_entity.rb b/lib/atlassian/jira_connect/serializers/base_entity.rb
index c5490aa3f54..94deb174a45 100644
--- a/lib/atlassian/jira_connect/serializers/base_entity.rb
+++ b/lib/atlassian/jira_connect/serializers/base_entity.rb
@@ -9,12 +9,12 @@ module Atlassian
format_with(:string) { |value| value.to_s }
- expose :monotonic_time, as: :updateSequenceId
+ expose :update_sequence_id, as: :updateSequenceId
private
- def monotonic_time
- Gitlab::Metrics::System.monotonic_time.to_i
+ def update_sequence_id
+ options[:update_sequence_id] || Client.generate_update_sequence_id
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
index 0ddfcbf52ea..e2dc197969b 100644
--- a/lib/atlassian/jira_connect/serializers/pull_request_entity.rb
+++ b/lib/atlassian/jira_connect/serializers/pull_request_entity.rb
@@ -20,7 +20,13 @@ module Atlassian
end
expose :title
expose :author, using: JiraConnect::Serializers::AuthorEntity
- expose :user_notes_count, as: :commentCount
+ expose :commentCount do |mr|
+ if options[:user_notes_count]
+ options[:user_notes_count].fetch(mr.id, 0)
+ else
+ mr.user_notes_count
+ end
+ end
expose :source_branch, as: :sourceBranch
expose :target_branch, as: :destinationBranch
expose :lastUpdate do |mr|
diff --git a/lib/atlassian/jira_connect/serializers/repository_entity.rb b/lib/atlassian/jira_connect/serializers/repository_entity.rb
index 819ca2b62e0..616bbc85bfe 100644
--- a/lib/atlassian/jira_connect/serializers/repository_entity.rb
+++ b/lib/atlassian/jira_connect/serializers/repository_entity.rb
@@ -15,13 +15,17 @@ module Atlassian
end
expose :commits do |project, options|
- JiraConnect::Serializers::CommitEntity.represent options[:commits], project: project
+ JiraConnect::Serializers::CommitEntity.represent options[:commits], project: project, update_sequence_id: options[:update_sequence_id]
end
expose :branches do |project, options|
- JiraConnect::Serializers::BranchEntity.represent options[:branches], project: project
+ JiraConnect::Serializers::BranchEntity.represent options[:branches], project: project, update_sequence_id: options[:update_sequence_id]
end
expose :pullRequests do |project, options|
- JiraConnect::Serializers::PullRequestEntity.represent options[:merge_requests], project: project
+ JiraConnect::Serializers::PullRequestEntity.represent(
+ options[:merge_requests],
+ update_sequence_id: options[:update_sequence_id],
+ user_notes_count: options[:user_notes_count]
+ )
end
end
end
diff --git a/lib/backup/files.rb b/lib/backup/files.rb
index 619a62fd6f6..a0948f8c0f5 100644
--- a/lib/backup/files.rb
+++ b/lib/backup/files.rb
@@ -26,7 +26,7 @@ module Backup
FileUtils.rm_f(backup_tarball)
if ENV['STRATEGY'] == 'copy'
- cmd = [%w(rsync -a), exclude_dirs(:rsync), %W(#{app_files_dir} #{Gitlab.config.backup.path})].flatten
+ 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
@@ -34,19 +34,27 @@ module Backup
raise Backup::Error, 'Backup failed'
end
- tar_cmd = [tar, exclude_dirs(:tar), %W(-C #{@backup_files_dir} -cf - .)].flatten
- run_pipeline!([tar_cmd, gzip_cmd], out: [backup_tarball, 'w', 0600])
+ tar_cmd = [tar, exclude_dirs(:tar), %W[-C #{@backup_files_dir} -cf - .]].flatten
+ status_list, output = run_pipeline!([tar_cmd, gzip_cmd], out: [backup_tarball, 'w', 0600])
FileUtils.rm_rf(@backup_files_dir)
else
- tar_cmd = [tar, exclude_dirs(:tar), %W(-C #{app_files_dir} -cf - .)].flatten
- run_pipeline!([tar_cmd, gzip_cmd], out: [backup_tarball, 'w', 0600])
+ tar_cmd = [tar, exclude_dirs(:tar), %W[-C #{app_files_dir} -cf - .]].flatten
+ status_list, output = run_pipeline!([tar_cmd, gzip_cmd], out: [backup_tarball, 'w', 0600])
+ end
+
+ unless pipeline_succeeded?(tar_status: status_list[0], gzip_status: status_list[1], output: output)
+ raise Backup::Error, "Backup operation failed: #{output}"
end
end
def restore
backup_existing_files_dir
- run_pipeline!([%w(gzip -cd), %W(#{tar} --unlink-first --recursive-unlink -C #{app_files_dir} -xf -)], in: backup_tarball)
+ cmd_list = [%w[gzip -cd], %W[#{tar} --unlink-first --recursive-unlink -C #{app_files_dir} -xf -]]
+ status_list, output = run_pipeline!(cmd_list, in: backup_tarball)
+ unless pipeline_succeeded?(gzip_status: status_list[0], tar_status: status_list[1], output: output)
+ raise Backup::Error, "Restore operation failed: #{output}"
+ end
end
def tar
@@ -78,13 +86,44 @@ module Backup
def run_pipeline!(cmd_list, options = {})
err_r, err_w = IO.pipe
options[:err] = err_w
- status = Open3.pipeline(*cmd_list, options)
+ status_list = Open3.pipeline(*cmd_list, options)
err_w.close
- return if status.compact.all?(&:success?)
- regex = /^g?tar: \.: Cannot mkdir: No such file or directory$/
- error = err_r.read
- raise Backup::Error, "Backup failed. #{error}" unless error =~ regex
+ [status_list, err_r.read]
+ end
+
+ def noncritical_warning?(warning)
+ noncritical_warnings = [
+ /^g?tar: \.: Cannot mkdir: No such file or directory$/
+ ]
+
+ noncritical_warnings.map { |w| warning =~ w }.any?
+ end
+
+ def pipeline_succeeded?(tar_status:, gzip_status:, output:)
+ return false unless gzip_status&.success?
+
+ tar_status&.success? || tar_ignore_non_success?(tar_status.exitstatus, output)
+ end
+
+ def tar_ignore_non_success?(exitstatus, output)
+ # tar can exit with nonzero code:
+ # 1 - if some files changed (i.e. a CI job is currently writes to log)
+ # 2 - if it cannot create `.` directory (see issue https://gitlab.com/gitlab-org/gitlab/-/issues/22442)
+ # http://www.gnu.org/software/tar/manual/html_section/tar_19.html#Synopsis
+ # so check tar status 1 or stderr output against some non-critical warnings
+ if exitstatus == 1
+ $stdout.puts "Ignoring tar exit status 1 'Some files differ': #{output}"
+ return true
+ end
+
+ # allow tar to fail with other non-success status if output contain non-critical warning
+ if noncritical_warning?(output)
+ $stdout.puts "Ignoring non-success exit status #{exitstatus} due to output of non-critical warning(s): #{output}"
+ return true
+ end
+
+ false
end
def exclude_dirs(fmt)
diff --git a/lib/banzai/filter/emoji_filter.rb b/lib/banzai/filter/emoji_filter.rb
index b32fe5e8301..8952a3ff6b4 100644
--- a/lib/banzai/filter/emoji_filter.rb
+++ b/lib/banzai/filter/emoji_filter.rb
@@ -8,6 +8,7 @@ module Banzai
# Based on HTML::Pipeline::EmojiFilter
class EmojiFilter < HTML::Pipeline::Filter
IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set
+ IGNORE_UNICODE_EMOJIS = %w(™ © ®).freeze
def call
doc.search(".//text()").each do |node|
@@ -60,7 +61,11 @@ module Banzai
# Build a regexp that matches all valid unicode emojis names.
def self.emoji_unicode_pattern
- @emoji_unicode_pattern ||= /(#{Gitlab::Emoji.emojis_unicodes.map { |moji| Regexp.escape(moji) }.join('|')})/
+ @emoji_unicode_pattern ||=
+ begin
+ filtered_emojis = Gitlab::Emoji.emojis_unicodes - IGNORE_UNICODE_EMOJIS
+ /(#{filtered_emojis.map { |moji| Regexp.escape(moji) }.join('|')})/
+ end
end
private
diff --git a/lib/banzai/filter/normalize_source_filter.rb b/lib/banzai/filter/normalize_source_filter.rb
new file mode 100644
index 00000000000..975cd540873
--- /dev/null
+++ b/lib/banzai/filter/normalize_source_filter.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ class NormalizeSourceFilter < HTML::Pipeline::Filter
+ UTF8_BOM = "\xEF\xBB\xBF"
+
+ def call
+ # Remove UTF8_BOM from beginning of source text
+ html.delete_prefix(UTF8_BOM)
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb
index cfd4b932568..d22a0e0b504 100644
--- a/lib/banzai/filter/reference_filter.rb
+++ b/lib/banzai/filter/reference_filter.rb
@@ -119,7 +119,7 @@ module Banzai
# Yields the link's URL and inner HTML whenever the node is a valid <a> tag.
def yield_valid_link(node)
- link = CGI.unescape(node.attr('href').to_s)
+ link = unescape_link(node.attr('href').to_s)
inner_html = node.inner_html
return unless link.force_encoding('UTF-8').valid_encoding?
@@ -127,6 +127,10 @@ module Banzai
yield link, inner_html
end
+ def unescape_link(href)
+ CGI.unescape(href)
+ end
+
def replace_text_when_pattern_matches(node, index, pattern)
return unless node.text =~ pattern
diff --git a/lib/banzai/filter/vulnerability_reference_filter.rb b/lib/banzai/filter/vulnerability_reference_filter.rb
new file mode 100644
index 00000000000..a59e9836d69
--- /dev/null
+++ b/lib/banzai/filter/vulnerability_reference_filter.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ # The actual filter is implemented in the EE mixin
+ class VulnerabilityReferenceFilter < IssuableReferenceFilter
+ self.reference_type = :vulnerability
+
+ def self.object_class
+ Vulnerability
+ end
+
+ private
+
+ def project
+ context[:project]
+ end
+ end
+ end
+end
+
+Banzai::Filter::VulnerabilityReferenceFilter.prepend_if_ee('EE::Banzai::Filter::VulnerabilityReferenceFilter')
diff --git a/lib/banzai/pipeline/pre_process_pipeline.rb b/lib/banzai/pipeline/pre_process_pipeline.rb
index 4c2b4ca1665..1f7cb437fcd 100644
--- a/lib/banzai/pipeline/pre_process_pipeline.rb
+++ b/lib/banzai/pipeline/pre_process_pipeline.rb
@@ -5,6 +5,7 @@ module Banzai
class PreProcessPipeline < BasePipeline
def self.filters
FilterArray[
+ Filter::NormalizeSourceFilter,
Filter::FrontMatterFilter,
Filter::BlockquoteFenceFilter,
]
diff --git a/lib/banzai/reference_parser/base_parser.rb b/lib/banzai/reference_parser/base_parser.rb
index c4d7e40b46c..3dfea8ee895 100644
--- a/lib/banzai/reference_parser/base_parser.rb
+++ b/lib/banzai/reference_parser/base_parser.rb
@@ -178,7 +178,10 @@ module Banzai
collection.where(id: to_query).each { |row| cache[row.id] = row }
end
- ids.uniq.map { |id| cache[id] }.compact
+ ids.each_with_object([]) do |id, array|
+ row = cache[id]
+ array << row if row
+ end
else
collection.where(id: ids)
end
diff --git a/lib/banzai/reference_parser/vulnerability_parser.rb b/lib/banzai/reference_parser/vulnerability_parser.rb
new file mode 100644
index 00000000000..143f2605927
--- /dev/null
+++ b/lib/banzai/reference_parser/vulnerability_parser.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Banzai
+ module ReferenceParser
+ # The actual parser is implemented in the EE mixin
+ class VulnerabilityParser < IssuableParser
+ self.reference_type = :vulnerability
+
+ def records_for_nodes(_nodes)
+ {}
+ end
+ end
+ end
+end
+
+Banzai::ReferenceParser::VulnerabilityParser.prepend_if_ee('::EE::Banzai::ReferenceParser::VulnerabilityParser')
diff --git a/lib/bitbucket_server/client.rb b/lib/bitbucket_server/client.rb
index cf55c692271..8e84afe51d7 100644
--- a/lib/bitbucket_server/client.rb
+++ b/lib/bitbucket_server/client.rb
@@ -8,9 +8,9 @@ module BitbucketServer
@connection = Connection.new(options)
end
- def pull_requests(project_key, repo)
+ def pull_requests(project_key, repo, page_offset: 0, limit: nil)
path = "/projects/#{project_key}/repos/#{repo}/pull-requests?state=ALL"
- get_collection(path, :pull_request)
+ get_collection(path, :pull_request, page_offset: page_offset, limit: limit)
end
def activities(project_key, repo, pull_request_id)
diff --git a/lib/bulk_imports/clients/graphql.rb b/lib/bulk_imports/clients/graphql.rb
new file mode 100644
index 00000000000..b067431aeae
--- /dev/null
+++ b/lib/bulk_imports/clients/graphql.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Clients
+ class Graphql
+ class HTTP < Graphlient::Adapters::HTTP::Adapter
+ def execute(document:, operation_name: nil, variables: {}, context: {})
+ response = ::Gitlab::HTTP.post(
+ url,
+ headers: headers,
+ follow_redirects: false,
+ body: {
+ query: document.to_query_string,
+ operationName: operation_name,
+ variables: variables
+ }.to_json
+ )
+
+ ::Gitlab::Json.parse(response.body)
+ end
+ end
+ private_constant :HTTP
+
+ attr_reader :client
+
+ delegate :query, :parse, :execute, to: :client
+
+ def initialize(url: Gitlab::COM_URL, token: nil)
+ @url = Gitlab::Utils.append_path(url, '/api/graphql')
+ @token = token
+ @client = Graphlient::Client.new(
+ @url,
+ options(http: HTTP)
+ )
+ end
+
+ def options(extra = {})
+ return extra unless @token
+
+ {
+ headers: {
+ 'Content-Type' => 'application/json',
+ 'Authorization' => "Bearer #{@token}"
+ }
+ }.merge(extra)
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/clients/http.rb b/lib/bulk_imports/clients/http.rb
new file mode 100644
index 00000000000..2e81863e53a
--- /dev/null
+++ b/lib/bulk_imports/clients/http.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Clients
+ class Http
+ API_VERSION = 'v4'.freeze
+ DEFAULT_PAGE = 1.freeze
+ DEFAULT_PER_PAGE = 30.freeze
+
+ ConnectionError = Class.new(StandardError)
+
+ def initialize(uri:, token:, page: DEFAULT_PAGE, per_page: DEFAULT_PER_PAGE, api_version: API_VERSION)
+ @uri = URI.parse(uri)
+ @token = token&.strip
+ @page = page
+ @per_page = per_page
+ @api_version = api_version
+ end
+
+ def get(resource, query = {})
+ with_error_handling do
+ Gitlab::HTTP.get(
+ resource_url(resource),
+ headers: request_headers,
+ follow_redirects: false,
+ query: query.merge(request_query)
+ )
+ end
+ end
+
+ def each_page(method, resource, query = {}, &block)
+ return to_enum(__method__, method, resource, query) unless block_given?
+
+ next_page = @page
+
+ while next_page
+ @page = next_page.to_i
+
+ response = self.public_send(method, resource, query) # rubocop: disable GitlabSecurity/PublicSend
+ collection = response.parsed_response
+ next_page = response.headers['x-next-page'].presence
+
+ yield collection
+ end
+ end
+
+ private
+
+ def request_query
+ {
+ page: @page,
+ per_page: @per_page
+ }
+ end
+
+ def request_headers
+ {
+ 'Content-Type' => 'application/json',
+ 'Authorization' => "Bearer #{@token}"
+ }
+ end
+
+ def with_error_handling
+ response = yield
+
+ raise ConnectionError.new("Error #{response.code}") unless response.success?
+
+ response
+ rescue *Gitlab::HTTP::HTTP_ERRORS => e
+ raise ConnectionError, e
+ end
+
+ def base_uri
+ @base_uri ||= "#{@uri.scheme}://#{@uri.host}:#{@uri.port}"
+ end
+
+ def api_url
+ Gitlab::Utils.append_path(base_uri, "/api/#{@api_version}")
+ end
+
+ def resource_url(resource)
+ Gitlab::Utils.append_path(api_url, resource)
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/common/extractors/graphql_extractor.rb b/lib/bulk_imports/common/extractors/graphql_extractor.rb
new file mode 100644
index 00000000000..7d58032cfcc
--- /dev/null
+++ b/lib/bulk_imports/common/extractors/graphql_extractor.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Extractors
+ class GraphqlExtractor
+ def initialize(query)
+ @query = query[:query]
+ @query_string = @query.to_s
+ @variables = @query.variables
+ end
+
+ def extract(context)
+ @context = context
+
+ Enumerator.new do |yielder|
+ result = graphql_client.execute(parsed_query, query_variables(context.entity))
+
+ yielder << result.original_hash.deep_dup
+ end
+ end
+
+ private
+
+ def graphql_client
+ @graphql_client ||= BulkImports::Clients::Graphql.new(
+ url: @context.configuration.url,
+ token: @context.configuration.access_token
+ )
+ end
+
+ def parsed_query
+ @parsed_query ||= graphql_client.parse(@query.to_s)
+ end
+
+ def query_variables(entity)
+ return unless @variables
+
+ @variables.transform_values do |entity_attribute|
+ entity.public_send(entity_attribute) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/common/loaders/entity_loader.rb b/lib/bulk_imports/common/loaders/entity_loader.rb
new file mode 100644
index 00000000000..4540b892c88
--- /dev/null
+++ b/lib/bulk_imports/common/loaders/entity_loader.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Loaders
+ class EntityLoader
+ def initialize(*args); end
+
+ def load(context, entity)
+ context.entity.bulk_import.entities.create!(entity)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/common/transformers/graphql_cleaner_transformer.rb b/lib/bulk_imports/common/transformers/graphql_cleaner_transformer.rb
new file mode 100644
index 00000000000..dce0fac6999
--- /dev/null
+++ b/lib/bulk_imports/common/transformers/graphql_cleaner_transformer.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+# Cleanup GraphQL original response hash from unnecessary nesting
+# 1. Remove ['data']['group'] or ['data']['project'] hash nesting
+# 2. Remove ['edges'] & ['nodes'] array wrappings
+# 3. Remove ['node'] hash wrapping
+#
+# @example
+# data = {"data"=>{"group"=> {
+# "name"=>"test",
+# "fullName"=>"test",
+# "description"=>"test",
+# "labels"=>{"edges"=>[{"node"=>{"title"=>"label1"}}, {"node"=>{"title"=>"label2"}}, {"node"=>{"title"=>"label3"}}]}}}}
+#
+# BulkImports::Common::Transformers::GraphqlCleanerTransformer.new.transform(nil, data)
+#
+# {"name"=>"test", "fullName"=>"test", "description"=>"test", "labels"=>[{"title"=>"label1"}, {"title"=>"label2"}, {"title"=>"label3"}]}
+module BulkImports
+ module Common
+ module Transformers
+ class GraphqlCleanerTransformer
+ EDGES = 'edges'
+ NODE = 'node'
+
+ def initialize(options = {})
+ @options = options
+ end
+
+ def transform(_, data)
+ return data unless data.is_a?(Hash)
+
+ data = data.dig('data', 'group') || data.dig('data', 'project') || data
+
+ clean_edges_and_nodes(data)
+ end
+
+ def clean_edges_and_nodes(data)
+ case data
+ when Array
+ data.map(&method(:clean_edges_and_nodes))
+ when Hash
+ if data.key?(NODE)
+ clean_edges_and_nodes(data[NODE])
+ else
+ data.transform_values { |value| clean_edges_and_nodes(value.try(:fetch, EDGES, value) || value) }
+ end
+ else
+ data
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/common/transformers/underscorify_keys_transformer.rb b/lib/bulk_imports/common/transformers/underscorify_keys_transformer.rb
new file mode 100644
index 00000000000..b32ab28fdbb
--- /dev/null
+++ b/lib/bulk_imports/common/transformers/underscorify_keys_transformer.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Transformers
+ class UnderscorifyKeysTransformer
+ def initialize(options = {})
+ @options = options
+ end
+
+ def transform(_, data)
+ data.deep_transform_keys do |key|
+ key.to_s.underscore
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/extractors/subgroups_extractor.rb b/lib/bulk_imports/groups/extractors/subgroups_extractor.rb
new file mode 100644
index 00000000000..5c5e686cec5
--- /dev/null
+++ b/lib/bulk_imports/groups/extractors/subgroups_extractor.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Extractors
+ class SubgroupsExtractor
+ def initialize(*args); end
+
+ def extract(context)
+ encoded_parent_path = ERB::Util.url_encode(context.entity.source_full_path)
+
+ http_client(context.entity.bulk_import.configuration)
+ .each_page(:get, "groups/#{encoded_parent_path}/subgroups")
+ .flat_map(&:itself)
+ end
+
+ private
+
+ def http_client(configuration)
+ @http_client ||= BulkImports::Clients::Http.new(
+ uri: configuration.url,
+ token: configuration.access_token,
+ per_page: 100
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/graphql/get_group_query.rb b/lib/bulk_imports/groups/graphql/get_group_query.rb
new file mode 100644
index 00000000000..c50b99aae4e
--- /dev/null
+++ b/lib/bulk_imports/groups/graphql/get_group_query.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Graphql
+ module GetGroupQuery
+ extend self
+
+ def to_s
+ <<-'GRAPHQL'
+ query($full_path: ID!) {
+ group(fullPath: $full_path) {
+ name
+ path
+ fullPath
+ description
+ visibility
+ emailsDisabled
+ lfsEnabled
+ mentionsDisabled
+ projectCreationLevel
+ requestAccessEnabled
+ requireTwoFactorAuthentication
+ shareWithGroupLock
+ subgroupCreationLevel
+ twoFactorGracePeriod
+ }
+ }
+ GRAPHQL
+ end
+
+ def variables
+ { full_path: :source_full_path }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/loaders/group_loader.rb b/lib/bulk_imports/groups/loaders/group_loader.rb
new file mode 100644
index 00000000000..386fc695182
--- /dev/null
+++ b/lib/bulk_imports/groups/loaders/group_loader.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Loaders
+ class GroupLoader
+ def initialize(options = {})
+ @options = options
+ end
+
+ def load(context, data)
+ return unless user_can_create_group?(context.current_user, data)
+
+ group = ::Groups::CreateService.new(context.current_user, data).execute
+
+ context.entity.update!(group: group)
+
+ group
+ end
+
+ private
+
+ def user_can_create_group?(current_user, data)
+ if data['parent_id']
+ parent = Namespace.find_by_id(data['parent_id'])
+
+ Ability.allowed?(current_user, :create_subgroup, parent)
+ else
+ Ability.allowed?(current_user, :create_group)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/pipelines/group_pipeline.rb b/lib/bulk_imports/groups/pipelines/group_pipeline.rb
new file mode 100644
index 00000000000..2b7d0ef7658
--- /dev/null
+++ b/lib/bulk_imports/groups/pipelines/group_pipeline.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Pipelines
+ class GroupPipeline
+ include Pipeline
+
+ extractor Common::Extractors::GraphqlExtractor, query: Graphql::GetGroupQuery
+
+ transformer Common::Transformers::GraphqlCleanerTransformer
+ transformer Common::Transformers::UnderscorifyKeysTransformer
+ transformer Groups::Transformers::GroupAttributesTransformer
+
+ loader Groups::Loaders::GroupLoader
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline.rb b/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline.rb
new file mode 100644
index 00000000000..6384e9d5972
--- /dev/null
+++ b/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Pipelines
+ class SubgroupEntitiesPipeline
+ include Pipeline
+
+ extractor BulkImports::Groups::Extractors::SubgroupsExtractor
+ transformer BulkImports::Groups::Transformers::SubgroupToEntityTransformer
+ loader BulkImports::Common::Loaders::EntityLoader
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/transformers/group_attributes_transformer.rb b/lib/bulk_imports/groups/transformers/group_attributes_transformer.rb
new file mode 100644
index 00000000000..7de9a430421
--- /dev/null
+++ b/lib/bulk_imports/groups/transformers/group_attributes_transformer.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Transformers
+ class GroupAttributesTransformer
+ def initialize(options = {})
+ @options = options
+ end
+
+ def transform(context, data)
+ import_entity = context.entity
+
+ data
+ .then { |data| transform_name(import_entity, data) }
+ .then { |data| transform_path(import_entity, data) }
+ .then { |data| transform_full_path(data) }
+ .then { |data| transform_parent(context, import_entity, data) }
+ .then { |data| transform_visibility_level(data) }
+ .then { |data| transform_project_creation_level(data) }
+ .then { |data| transform_subgroup_creation_level(data) }
+ end
+
+ private
+
+ def transform_name(import_entity, data)
+ data['name'] = import_entity.destination_name
+ data
+ end
+
+ def transform_path(import_entity, data)
+ data['path'] = import_entity.destination_name.parameterize
+ data
+ end
+
+ def transform_full_path(data)
+ data.delete('full_path')
+ data
+ end
+
+ def transform_parent(context, import_entity, data)
+ current_user = context.current_user
+ namespace = Namespace.find_by_full_path(import_entity.destination_namespace)
+
+ return data if namespace == current_user.namespace
+
+ data['parent_id'] = namespace.id
+ data
+ end
+
+ def transform_visibility_level(data)
+ visibility = data['visibility']
+
+ return data unless visibility.present?
+
+ data['visibility_level'] = Gitlab::VisibilityLevel.string_options[visibility]
+ data.delete('visibility')
+ data
+ end
+
+ def transform_project_creation_level(data)
+ project_creation_level = data['project_creation_level']
+
+ return data unless project_creation_level.present?
+
+ data['project_creation_level'] = Gitlab::Access.project_creation_string_options[project_creation_level]
+ data
+ end
+
+ def transform_subgroup_creation_level(data)
+ subgroup_creation_level = data['subgroup_creation_level']
+
+ return data unless subgroup_creation_level.present?
+
+ data['subgroup_creation_level'] = Gitlab::Access.subgroup_creation_string_options[subgroup_creation_level]
+ data
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/transformers/subgroup_to_entity_transformer.rb b/lib/bulk_imports/groups/transformers/subgroup_to_entity_transformer.rb
new file mode 100644
index 00000000000..6c3c299c2d2
--- /dev/null
+++ b/lib/bulk_imports/groups/transformers/subgroup_to_entity_transformer.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Transformers
+ class SubgroupToEntityTransformer
+ def initialize(*args); end
+
+ def transform(context, entry)
+ {
+ source_type: :group_entity,
+ source_full_path: entry['full_path'],
+ destination_name: entry['name'],
+ destination_namespace: context.entity.group.full_path,
+ parent_id: context.entity.id
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/importers/group_importer.rb b/lib/bulk_imports/importers/group_importer.rb
new file mode 100644
index 00000000000..c7253590c87
--- /dev/null
+++ b/lib/bulk_imports/importers/group_importer.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Importers
+ class GroupImporter
+ def initialize(entity)
+ @entity = entity
+ end
+
+ def execute
+ entity.start!
+ bulk_import = entity.bulk_import
+ configuration = bulk_import.configuration
+
+ context = BulkImports::Pipeline::Context.new(
+ current_user: bulk_import.user,
+ entity: entity,
+ configuration: configuration
+ )
+
+ BulkImports::Groups::Pipelines::GroupPipeline.new.run(context)
+ BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline.new.run(context)
+
+ entity.finish!
+ end
+
+ private
+
+ attr_reader :entity
+ end
+ end
+end
diff --git a/lib/bulk_imports/importers/groups_importer.rb b/lib/bulk_imports/importers/groups_importer.rb
new file mode 100644
index 00000000000..8641577ff47
--- /dev/null
+++ b/lib/bulk_imports/importers/groups_importer.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Importers
+ class GroupsImporter
+ def initialize(bulk_import_id)
+ @bulk_import = BulkImport.find(bulk_import_id)
+ end
+
+ def execute
+ bulk_import.start! unless bulk_import.started?
+
+ if entities_to_import.empty?
+ bulk_import.finish!
+ else
+ entities_to_import.each do |entity|
+ BulkImports::Importers::GroupImporter.new(entity).execute
+ end
+
+ # A new BulkImportWorker job is enqueued to either
+ # - Process the new BulkImports::Entity created for the subgroups
+ # - Or to mark the `bulk_import` as finished.
+ BulkImportWorker.perform_async(bulk_import.id)
+ end
+ end
+
+ private
+
+ attr_reader :bulk_import
+
+ def entities_to_import
+ @entities_to_import ||= bulk_import.entities.with_status(:created)
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/pipeline.rb b/lib/bulk_imports/pipeline.rb
new file mode 100644
index 00000000000..70e6030ea2c
--- /dev/null
+++ b/lib/bulk_imports/pipeline.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Pipeline
+ extend ActiveSupport::Concern
+
+ included do
+ include Attributes
+ include Runner
+ end
+ end
+end
diff --git a/lib/bulk_imports/pipeline/attributes.rb b/lib/bulk_imports/pipeline/attributes.rb
new file mode 100644
index 00000000000..ebfbaf6f6ba
--- /dev/null
+++ b/lib/bulk_imports/pipeline/attributes.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Pipeline
+ module Attributes
+ extend ActiveSupport::Concern
+ include Gitlab::ClassAttributes
+
+ class_methods do
+ def extractor(klass, options = nil)
+ add_attribute(:extractors, klass, options)
+ end
+
+ def transformer(klass, options = nil)
+ add_attribute(:transformers, klass, options)
+ end
+
+ def loader(klass, options = nil)
+ add_attribute(:loaders, klass, options)
+ end
+
+ def add_attribute(sym, klass, options)
+ class_attributes[sym] ||= []
+ class_attributes[sym] << { klass: klass, options: options }
+ end
+
+ def extractors
+ class_attributes[:extractors]
+ end
+
+ def transformers
+ class_attributes[:transformers]
+ end
+
+ def loaders
+ class_attributes[:loaders]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/pipeline/context.rb b/lib/bulk_imports/pipeline/context.rb
new file mode 100644
index 00000000000..ad19f5cad7d
--- /dev/null
+++ b/lib/bulk_imports/pipeline/context.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Pipeline
+ class Context
+ include Gitlab::Utils::LazyAttributes
+
+ Attribute = Struct.new(:name, :type)
+
+ PIPELINE_ATTRIBUTES = [
+ Attribute.new(:current_user, User),
+ Attribute.new(:entity, ::BulkImports::Entity),
+ Attribute.new(:configuration, ::BulkImports::Configuration)
+ ].freeze
+
+ def initialize(args)
+ assign_attributes(args)
+ end
+
+ private
+
+ PIPELINE_ATTRIBUTES.each do |attr|
+ lazy_attr_reader attr.name, type: attr.type
+ end
+
+ def assign_attributes(values)
+ values.slice(*PIPELINE_ATTRIBUTES.map(&:name)).each do |name, value|
+ instance_variable_set("@#{name}", value)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/pipeline/runner.rb b/lib/bulk_imports/pipeline/runner.rb
new file mode 100644
index 00000000000..04038e50399
--- /dev/null
+++ b/lib/bulk_imports/pipeline/runner.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Pipeline
+ module Runner
+ extend ActiveSupport::Concern
+
+ included do
+ private
+
+ def extractors
+ @extractors ||= self.class.extractors.map(&method(:instantiate))
+ end
+
+ def transformers
+ @transformers ||= self.class.transformers.map(&method(:instantiate))
+ end
+
+ def loaders
+ @loaders ||= self.class.loaders.map(&method(:instantiate))
+ end
+
+ def pipeline_name
+ @pipeline ||= self.class.name
+ end
+
+ def instantiate(class_config)
+ class_config[:klass].new(class_config[:options])
+ end
+ end
+
+ def run(context)
+ info(context, message: "Pipeline started", pipeline: pipeline_name)
+
+ extractors.each do |extractor|
+ extractor.extract(context).each do |entry|
+ info(context, extractor: extractor.class.name)
+
+ transformers.each do |transformer|
+ info(context, transformer: transformer.class.name)
+ entry = transformer.transform(context, entry)
+ end
+
+ loaders.each do |loader|
+ info(context, loader: loader.class.name)
+ loader.load(context, entry)
+ end
+ end
+ end
+ end
+
+ private # rubocop:disable Lint/UselessAccessModifier
+
+ def info(context, extra = {})
+ logger.info({
+ entity: context.entity.id,
+ entity_type: context.entity.source_type
+ }.merge(extra))
+ end
+
+ def logger
+ @logger ||= Gitlab::Import::Logger.build
+ end
+ end
+ end
+end
diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb
index e6ca33d749b..35f299c17e4 100644
--- a/lib/container_registry/client.rb
+++ b/lib/container_registry/client.rb
@@ -15,6 +15,7 @@ module ContainerRegistry
CONTAINER_IMAGE_V1_TYPE = 'application/vnd.docker.container.image.v1+json'
REGISTRY_VERSION_HEADER = 'gitlab-container-registry-version'
REGISTRY_FEATURES_HEADER = 'gitlab-container-registry-features'
+ REGISTRY_TAG_DELETE_FEATURE = 'tag_delete'
ACCEPTED_TYPES = [DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE, OCI_MANIFEST_V1_TYPE].freeze
@@ -25,8 +26,6 @@ module ContainerRegistry
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?
@@ -81,6 +80,9 @@ module ContainerRegistry
# the DELETE method in the Allow header. Others reply with an 404 Not Found.
def supports_tag_delete?
strong_memoize(:supports_tag_delete) do
+ registry_features = Gitlab::CurrentSettings.container_registry_features || []
+ next true if ::Gitlab.com? && registry_features.include?(REGISTRY_TAG_DELETE_FEATURE)
+
response = faraday.run_request(:options, '/v2/name/tags/reference/tag', '', {})
response.success? && response.headers['allow']&.include?('DELETE')
end
diff --git a/lib/csv_builders/stream.rb b/lib/csv_builders/stream.rb
new file mode 100644
index 00000000000..a2b9fca84cb
--- /dev/null
+++ b/lib/csv_builders/stream.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module CsvBuilders
+ class Stream < CsvBuilder
+ def render(max_rows = 100_000)
+ max_rows_including_header = max_rows + 1
+
+ Enumerator.new do |csv|
+ csv << CSV.generate_line(headers)
+
+ each do |object|
+ csv << CSV.generate_line(row(object))
+ end
+ end.lazy.take(max_rows_including_header) # rubocop: disable CodeReuse/ActiveRecord
+ end
+ end
+end
diff --git a/lib/expand_variables.rb b/lib/expand_variables.rb
index 3a50925d628..dc8f9d0c970 100644
--- a/lib/expand_variables.rb
+++ b/lib/expand_variables.rb
@@ -1,17 +1,39 @@
# frozen_string_literal: true
module ExpandVariables
+ VARIABLES_REGEXP = /\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}|%\g<1>%/.freeze
+
class << self
def expand(value, variables)
+ replace_with(value, variables) do |vars_hash, last_match|
+ match_or_blank_value(vars_hash, last_match)
+ end
+ end
+
+ def expand_existing(value, variables)
+ replace_with(value, variables) do |vars_hash, last_match|
+ match_or_original_value(vars_hash, last_match)
+ end
+ end
+
+ private
+
+ def replace_with(value, variables)
variables_hash = nil
- value.gsub(/\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}|%\g<1>%/) do
+ value.gsub(VARIABLES_REGEXP) do
variables_hash ||= transform_variables(variables)
- variables_hash[Regexp.last_match(1) || Regexp.last_match(2)]
+ yield(variables_hash, Regexp.last_match)
end
end
- private
+ def match_or_blank_value(variables, last_match)
+ variables[last_match[1] || last_match[2]]
+ end
+
+ def match_or_original_value(variables, last_match)
+ match_or_blank_value(variables, last_match) || last_match[0]
+ end
def transform_variables(variables)
# Lazily initialise variables
diff --git a/lib/extracts_ref.rb b/lib/extracts_ref.rb
index adbe93cfa3a..34511423d4a 100644
--- a/lib/extracts_ref.rb
+++ b/lib/extracts_ref.rb
@@ -68,7 +68,7 @@ module ExtractsRef
raise InvalidPathError if @ref.match?(/\s/)
- @commit = @repo.commit(@ref)
+ @commit = @repo.commit(@ref) if @ref.present?
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
diff --git a/lib/feature/shared.rb b/lib/feature/shared.rb
index 9ec56ee6b52..1fcbc8fa173 100644
--- a/lib/feature/shared.rb
+++ b/lib/feature/shared.rb
@@ -10,6 +10,8 @@ class Feature
# 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`
# ee_only: defines that a feature flag can only be created in a context of EE
+ # deprecated: defines if a feature flag type that is deprecated and to be removed,
+ # the deprecated types are hidden from all interfaces
# example: usage being shown when exception is raised
TYPES = {
development: {
@@ -37,6 +39,7 @@ class Feature
},
licensed: {
description: 'Permanent feature flags used to temporarily disable licensed features.',
+ deprecated: true,
optional: true,
rollout_issue: false,
ee_only: true,
@@ -54,6 +57,7 @@ class Feature
name
introduced_by_url
rollout_issue_url
+ milestone
type
group
default_enabled
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start.rb
index c5f843d5f1a..4bb225b63f1 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start.rb
@@ -18,24 +18,46 @@ module Gitlab
end
def timestamp_projection
- issue_metrics_table[:first_mentioned_in_commit_at]
+ Arel::Nodes::NamedFunction.new('COALESCE', column_list)
end
override :column_list
def column_list
- [timestamp_projection]
+ [
+ issue_metrics_table[:first_mentioned_in_commit_at],
+ mr_metrics_table[:first_commit_at]
+ ]
end
# rubocop: disable CodeReuse/ActiveRecord
def apply_query_customization(query)
- issue_metrics_join = mr_closing_issues_table
- .join(issue_metrics_table)
+ query
+ .joins(merge_requests_closing_issues_join)
+ .joins(issue_metrics_join)
+ .joins(mr_metrics_join)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def issue_metrics_join
+ mr_closing_issues_table
+ .join(issue_metrics_table, Arel::Nodes::OuterJoin)
.on(mr_closing_issues_table[:issue_id].eq(issue_metrics_table[:issue_id]))
.join_sources
+ end
- query.joins(:merge_requests_closing_issues).joins(issue_metrics_join)
+ def merge_requests_closing_issues_join
+ mr_table
+ .join(mr_closing_issues_table, Arel::Nodes::OuterJoin)
+ .on(mr_table[:id].eq(mr_closing_issues_table[:merge_request_id]))
+ .join_sources
+ end
+
+ def mr_metrics_join
+ mr_metrics_table
+ .join(mr_metrics_table, Arel::Nodes::OuterJoin)
+ .on(mr_metrics_table[:merge_request_id].eq(mr_table[:id]))
+ .join_sources
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/lib/gitlab/analytics/instance_statistics/workers_argument_builder.rb b/lib/gitlab/analytics/instance_statistics/workers_argument_builder.rb
index 636bba22c23..54b3bbb3ce6 100644
--- a/lib/gitlab/analytics/instance_statistics/workers_argument_builder.rb
+++ b/lib/gitlab/analytics/instance_statistics/workers_argument_builder.rb
@@ -11,21 +11,36 @@ module Gitlab
def execute
measurement_identifiers.map do |measurement_identifier|
- query_scope = ::Analytics::InstanceStatistics::Measurement::IDENTIFIER_QUERY_MAPPING[measurement_identifier]&.call
+ query_scope = query_mappings[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]
+ [measurement_identifier, *determine_start_and_finish(measurement_identifier, query_scope), recorded_at]
end.compact
end
private
attr_reader :measurement_identifiers, :recorded_at
+
+ # Determining the query range (id range) as early as possible in order to get more accurate counts.
+ def determine_start_and_finish(measurement_identifier, query_scope)
+ queries = custom_min_max_queries[measurement_identifier]
+
+ if queries
+ [queries[:minimum_query].call, queries[:maximum_query].call]
+ else
+ [query_scope.minimum(:id), query_scope.maximum(:id)]
+ end
+ end
+
+ def custom_min_max_queries
+ ::Analytics::InstanceStatistics::Measurement.identifier_min_max_queries
+ end
+
+ def query_mappings
+ ::Analytics::InstanceStatistics::Measurement.identifier_query_mapping
+ end
end
end
end
diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb
index 6173918b453..e92bbe4f529 100644
--- a/lib/gitlab/application_rate_limiter.rb
+++ b/lib/gitlab/application_rate_limiter.rb
@@ -33,7 +33,8 @@ module Gitlab
group_import: { threshold: -> { application_settings.group_import_limit }, interval: 1.minute },
group_testing_hook: { threshold: 5, interval: 1.minute },
profile_add_new_email: { threshold: 5, interval: 1.minute },
- profile_resend_email_confirmation: { threshold: 5, interval: 1.minute }
+ profile_resend_email_confirmation: { threshold: 5, interval: 1.minute },
+ update_environment_canary_ingress: { threshold: 1, interval: 1.minute }
}.freeze
end
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 001c083c778..fadd6eb848d 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -158,7 +158,7 @@ module Gitlab
if Service.available_services_names.include?(underscored_service)
# We treat underscored_service as a trusted input because it is included
- # in the Service.available_services_names whitelist.
+ # in the Service.available_services_names allowlist.
service = project.public_send("#{underscored_service}_service") # rubocop:disable GitlabSecurity/PublicSend
if service && service.activated? && service.valid_token?(password)
diff --git a/lib/gitlab/auth/auth_finders.rb b/lib/gitlab/auth/auth_finders.rb
index 3d3f7212053..f3975fe219a 100644
--- a/lib/gitlab/auth/auth_finders.rb
+++ b/lib/gitlab/auth/auth_finders.rb
@@ -83,6 +83,8 @@ module Gitlab
return unless ::Gitlab::Auth::CI_JOB_USER == login
job = find_valid_running_job_by_token!(password)
+ @current_authenticated_job = job # rubocop:disable Gitlab/ModuleWithInstanceVariables
+
job.user
end
diff --git a/lib/gitlab/background_migration/backfill_design_internal_ids.rb b/lib/gitlab/background_migration/backfill_design_internal_ids.rb
new file mode 100644
index 00000000000..553571d5d00
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_design_internal_ids.rb
@@ -0,0 +1,130 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Backfill design.iid for a range of projects
+ class BackfillDesignInternalIds
+ # See app/models/internal_id
+ # This is a direct copy of the application code with the following changes:
+ # - usage enum is hard-coded to the value for design_management_designs
+ # - init is not passed around, but ignored
+ class InternalId < ActiveRecord::Base
+ def self.track_greatest(subject, scope, new_value)
+ InternalIdGenerator.new(subject, scope).track_greatest(new_value)
+ end
+
+ # Increments #last_value with new_value if it is greater than the current,
+ # and saves the record
+ #
+ # The operation locks the record and gathers a `ROW SHARE` lock (in PostgreSQL).
+ # As such, the increment is atomic and safe to be called concurrently.
+ def track_greatest_and_save!(new_value)
+ update_and_save { self.last_value = [last_value || 0, new_value].max }
+ end
+
+ private
+
+ def update_and_save(&block)
+ lock!
+ yield
+ # update_and_save_counter.increment(usage: usage, changed: last_value_changed?)
+ save!
+ last_value
+ end
+ end
+
+ # See app/models/internal_id
+ class InternalIdGenerator
+ attr_reader :subject, :scope, :scope_attrs
+
+ def initialize(subject, scope)
+ @subject = subject
+ @scope = scope
+
+ raise ArgumentError, 'Scope is not well-defined, need at least one column for scope (given: 0)' if scope.empty?
+ end
+
+ # Create a record in internal_ids if one does not yet exist
+ # and set its new_value if it is higher than the current last_value
+ #
+ # Note this will acquire a ROW SHARE lock on the InternalId record
+ def track_greatest(new_value)
+ subject.transaction do
+ record.track_greatest_and_save!(new_value)
+ end
+ end
+
+ def record
+ @record ||= (lookup || create_record)
+ end
+
+ def lookup
+ InternalId.find_by(**scope, usage: usage_value)
+ end
+
+ def usage_value
+ 10 # see Enums::InternalId - this is the value for design_management_designs
+ end
+
+ # Create InternalId record for (scope, usage) combination, if it doesn't exist
+ #
+ # We blindly insert without synchronization. If another process
+ # was faster in doing this, we'll realize once we hit the unique key constraint
+ # violation. We can safely roll-back the nested transaction and perform
+ # a lookup instead to retrieve the record.
+ def create_record
+ subject.transaction(requires_new: true) do
+ InternalId.create!(
+ **scope,
+ usage: usage_value,
+ last_value: 0
+ )
+ end
+ rescue ActiveRecord::RecordNotUnique
+ lookup
+ end
+ end
+
+ attr_reader :design_class
+
+ def initialize(design_class)
+ @design_class = design_class
+ end
+
+ def perform(relation)
+ start_id, end_id = relation.pluck("min(project_id), max(project_id)").flatten
+ table = 'design_management_designs'
+
+ ActiveRecord::Base.connection.execute <<~SQL
+ WITH
+ starting_iids(project_id, iid) as (
+ SELECT project_id, MAX(COALESCE(iid, 0))
+ FROM #{table}
+ WHERE project_id BETWEEN #{start_id} AND #{end_id}
+ GROUP BY project_id
+ ),
+ with_calculated_iid(id, iid) as (
+ SELECT design.id,
+ init.iid + ROW_NUMBER() OVER (PARTITION BY design.project_id ORDER BY design.id ASC)
+ FROM #{table} as design, starting_iids as init
+ WHERE design.project_id BETWEEN #{start_id} AND #{end_id}
+ AND design.iid IS NULL
+ AND init.project_id = design.project_id
+ )
+
+ UPDATE #{table}
+ SET iid = with_calculated_iid.iid
+ FROM with_calculated_iid
+ WHERE #{table}.id = with_calculated_iid.id
+ SQL
+
+ # track the new greatest IID value
+ relation.each do |design|
+ current_max = design_class.where(project_id: design.project_id).maximum(:iid)
+ scope = { project_id: design.project_id }
+ InternalId.track_greatest(design, scope, current_max)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2.rb b/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2.rb
new file mode 100644
index 00000000000..61145f6a445
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+# Based on https://community.developer.atlassian.com/t/get-rest-api-3-filter-search/29459/2,
+# it's enough at the moment to simply notice if the url is from `atlassian.net`
+module Gitlab
+ module BackgroundMigration
+ # Backfill the deployment_type in jira_tracker_data table
+ class BackfillJiraTrackerDeploymentType2
+ # Migration only version of jira_tracker_data table
+ class JiraTrackerDataTemp < ApplicationRecord
+ self.table_name = 'jira_tracker_data'
+
+ def self.encryption_options
+ {
+ key: Settings.attr_encrypted_db_key_base_32,
+ encode: true,
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm'
+ }
+ end
+
+ attr_encrypted :url, encryption_options
+ attr_encrypted :api_url, encryption_options
+
+ enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment
+ end
+
+ # Migration only version of services table
+ class JiraServiceTemp < ApplicationRecord
+ self.table_name = 'services'
+ self.inheritance_column = :_type_disabled
+ end
+
+ def perform(start_id, stop_id)
+ @server_ids = []
+ @cloud_ids = []
+
+ JiraTrackerDataTemp
+ .where(id: start_id..stop_id, deployment_type: 0)
+ .each do |jira_tracker_data|
+ collect_deployment_type(jira_tracker_data)
+ end
+
+ unless cloud_ids.empty?
+ JiraTrackerDataTemp.where(id: cloud_ids)
+ .update_all(deployment_type: JiraTrackerDataTemp.deployment_types[:cloud])
+ end
+
+ unless server_ids.empty?
+ JiraTrackerDataTemp.where(id: server_ids)
+ .update_all(deployment_type: JiraTrackerDataTemp.deployment_types[:server])
+ end
+
+ mark_jobs_as_succeeded(start_id, stop_id)
+ end
+
+ private
+
+ attr_reader :server_ids, :cloud_ids
+
+ def client_url(jira_tracker_data)
+ jira_tracker_data.api_url.presence || jira_tracker_data.url.presence
+ end
+
+ def server_type(url)
+ url.downcase.include?('.atlassian.net') ? :cloud : :server
+ end
+
+ def collect_deployment_type(jira_tracker_data)
+ url = client_url(jira_tracker_data)
+ return unless url
+
+ case server_type(url)
+ when :cloud
+ cloud_ids << jira_tracker_data.id
+ else
+ server_ids << jira_tracker_data.id
+ end
+ end
+
+ def mark_jobs_as_succeeded(*arguments)
+ Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(self.class.name, arguments)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules.rb b/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules.rb
new file mode 100644
index 00000000000..8a58cf9b302
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Backfill merge request cleanup schedules of closed/merged merge requests
+ # without any corresponding records.
+ class BackfillMergeRequestCleanupSchedules
+ # Model used for migration added in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46782.
+ class MergeRequest < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'merge_requests'
+
+ def self.eligible
+ where('merge_requests.state_id IN (2, 3)')
+ end
+ end
+
+ def perform(start_id, end_id)
+ eligible_mrs = MergeRequest.eligible.where(id: start_id..end_id)
+ scheduled_at_column = "COALESCE(metrics.merged_at, COALESCE(metrics.latest_closed_at, merge_requests.updated_at)) + interval '14 days'"
+ query =
+ eligible_mrs
+ .select("merge_requests.id, #{scheduled_at_column}, NOW(), NOW()")
+ .joins('LEFT JOIN merge_request_metrics metrics ON metrics.merge_request_id = merge_requests.id')
+
+ result = ActiveRecord::Base.connection.execute <<~SQL
+ INSERT INTO merge_request_cleanup_schedules (merge_request_id, scheduled_at, created_at, updated_at)
+ #{query.to_sql}
+ ON CONFLICT (merge_request_id) DO NOTHING;
+ SQL
+
+ ::Gitlab::BackgroundMigration::Logger.info(
+ message: 'Backfilled merge_request_cleanup_schedules records',
+ count: result.cmd_tuples
+ )
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/populate_has_vulnerabilities.rb b/lib/gitlab/background_migration/populate_has_vulnerabilities.rb
new file mode 100644
index 00000000000..78140b768fc
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_has_vulnerabilities.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This class populates missing dismissal information for
+ # vulnerability entries.
+ class PopulateHasVulnerabilities
+ class ProjectSetting < ActiveRecord::Base # rubocop:disable Style/Documentation
+ self.table_name = 'project_settings'
+
+ UPSERT_SQL = <<~SQL
+ WITH upsert_data (project_id, has_vulnerabilities, created_at, updated_at) AS (
+ SELECT projects.id, true, current_timestamp, current_timestamp FROM projects WHERE projects.id IN (%{project_ids})
+ )
+ INSERT INTO project_settings
+ (project_id, has_vulnerabilities, created_at, updated_at)
+ (SELECT * FROM upsert_data)
+ ON CONFLICT (project_id)
+ DO UPDATE SET
+ has_vulnerabilities = true,
+ updated_at = EXCLUDED.updated_at
+ SQL
+
+ def self.upsert_for(project_ids)
+ connection.execute(UPSERT_SQL % { project_ids: project_ids.join(', ') })
+ end
+ end
+
+ class Vulnerability < ActiveRecord::Base # rubocop:disable Style/Documentation
+ include EachBatch
+
+ self.table_name = 'vulnerabilities'
+ end
+
+ def perform(*project_ids)
+ ProjectSetting.upsert_for(project_ids)
+ rescue StandardError => e
+ log_error(e, project_ids)
+ ensure
+ log_info(project_ids)
+ end
+
+ private
+
+ def log_error(error, project_ids)
+ ::Gitlab::BackgroundMigration::Logger.error(
+ migrator: self.class.name,
+ message: error.message,
+ project_ids: project_ids
+ )
+ end
+
+ def log_info(project_ids)
+ ::Gitlab::BackgroundMigration::Logger.info(
+ migrator: self.class.name,
+ message: 'Projects has been processed to populate `has_vulnerabilities` information',
+ count: project_ids.length
+ )
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb b/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb
new file mode 100644
index 00000000000..bc0a181a06c
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This class populates missing dismissal information for
+ # vulnerability entries.
+ class PopulateMissingVulnerabilityDismissalInformation
+ class Vulnerability < ActiveRecord::Base # rubocop:disable Style/Documentation
+ include EachBatch
+
+ self.table_name = 'vulnerabilities'
+
+ has_one :finding, class_name: '::Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation::Finding'
+
+ scope :broken, -> { where('state = 2 AND (dismissed_at IS NULL OR dismissed_by_id IS NULL)') }
+
+ def copy_dismissal_information
+ return unless finding&.dismissal_feedback
+
+ update_columns(
+ dismissed_at: finding.dismissal_feedback.created_at,
+ dismissed_by_id: finding.dismissal_feedback.author_id
+ )
+ end
+ end
+
+ class Finding < ActiveRecord::Base # rubocop:disable Style/Documentation
+ include ShaAttribute
+
+ self.table_name = 'vulnerability_occurrences'
+
+ sha_attribute :project_fingerprint
+
+ def dismissal_feedback
+ Feedback.dismissal.where(category: report_type, project_fingerprint: project_fingerprint, project_id: project_id).first
+ end
+ end
+
+ class Feedback < ActiveRecord::Base # rubocop:disable Style/Documentation
+ DISMISSAL_TYPE = 0
+
+ self.table_name = 'vulnerability_feedback'
+
+ scope :dismissal, -> { where(feedback_type: DISMISSAL_TYPE) }
+ end
+
+ def perform(*vulnerability_ids)
+ Vulnerability.includes(:finding).where(id: vulnerability_ids).each { |vulnerability| populate_for(vulnerability) }
+
+ log_info(vulnerability_ids)
+ end
+
+ private
+
+ def populate_for(vulnerability)
+ log_warning(vulnerability) unless vulnerability.copy_dismissal_information
+ rescue StandardError => error
+ log_error(error, vulnerability)
+ end
+
+ def log_info(vulnerability_ids)
+ ::Gitlab::BackgroundMigration::Logger.info(
+ migrator: self.class.name,
+ message: 'Dismissal information has been copied',
+ count: vulnerability_ids.length
+ )
+ end
+
+ def log_warning(vulnerability)
+ ::Gitlab::BackgroundMigration::Logger.warn(
+ migrator: self.class.name,
+ message: 'Could not update vulnerability!',
+ vulnerability_id: vulnerability.id
+ )
+ end
+
+ def log_error(error, vulnerability)
+ ::Gitlab::BackgroundMigration::Logger.error(
+ migrator: self.class.name,
+ message: error.message,
+ vulnerability_id: vulnerability.id
+ )
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/populate_vulnerability_feedback_pipeline_id.rb b/lib/gitlab/background_migration/populate_vulnerability_feedback_pipeline_id.rb
new file mode 100644
index 00000000000..fc79f7125e3
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_vulnerability_feedback_pipeline_id.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This class updates vulnerability feedback entities with no pipeline id assigned.
+ class PopulateVulnerabilityFeedbackPipelineId
+ def perform(project_ids)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::PopulateVulnerabilityFeedbackPipelineId.prepend_if_ee('EE::Gitlab::BackgroundMigration::PopulateVulnerabilityFeedbackPipelineId')
diff --git a/lib/gitlab/background_migration/replace_blocked_by_links.rb b/lib/gitlab/background_migration/replace_blocked_by_links.rb
index 26626aaef79..0c29887bb00 100644
--- a/lib/gitlab/background_migration/replace_blocked_by_links.rb
+++ b/lib/gitlab/background_migration/replace_blocked_by_links.rb
@@ -12,14 +12,19 @@ module Gitlab
blocked_by_links = IssueLink.where(id: start_id..stop_id).where(link_type: 2)
ActiveRecord::Base.transaction do
- # if there is duplicit bi-directional relation (issue2 is blocked by issue1
- # and issue1 already links issue2), then we can just delete 'blocked by'.
- # This should be rare as we have a pre-create check which checks if issues are
- # already linked
- blocked_by_links
+ # There could be two edge cases:
+ # 1) issue1 is blocked by issue2 AND issue2 blocks issue1 (type 1)
+ # 2) issue1 is blocked by issue2 AND issue2 is related to issue1 (type 0)
+ # In both cases cases we couldn't convert blocked by relation to
+ # `issue2 blocks issue` because there is already a link with the same
+ # source/target id. To avoid these conflicts, we first delete any
+ # "opposite" links before we update `blocked by` relation. This
+ # should be rare as we have a pre-create check which checks if issues
+ # are already linked
+ opposite_ids = blocked_by_links
+ .select('opposite_links.id')
.joins('INNER JOIN issue_links as opposite_links ON issue_links.source_id = opposite_links.target_id AND issue_links.target_id = opposite_links.source_id')
- .where('opposite_links.link_type': 1)
- .delete_all
+ IssueLink.where(id: opposite_ids).delete_all
blocked_by_links.update_all('source_id=target_id,target_id=source_id,link_type=1')
end
diff --git a/lib/gitlab/badge/coverage/report.rb b/lib/gitlab/badge/coverage/report.rb
index 0df6e858bf4..390da014a5a 100644
--- a/lib/gitlab/badge/coverage/report.rb
+++ b/lib/gitlab/badge/coverage/report.rb
@@ -17,8 +17,6 @@ module Gitlab
key_width: opts[:key_width].to_i,
key_text: opts[:key_text]
}
-
- @pipeline = @project.ci_pipelines.latest_successful_for_ref(@ref)
end
def entity
@@ -42,19 +40,35 @@ module Gitlab
private
- # rubocop: disable CodeReuse/ActiveRecord
+ def successful_pipeline
+ @successful_pipeline ||= @project.ci_pipelines.latest_successful_for_ref(@ref)
+ end
+
+ def failed_pipeline
+ @failed_pipeline ||= @project.ci_pipelines.latest_failed_for_ref(@ref)
+ end
+
+ def running_pipeline
+ @running_pipeline ||= @project.ci_pipelines.latest_running_for_ref(@ref)
+ end
+
def raw_coverage
- return unless @pipeline
+ latest =
+ if @job.present?
+ builds = ::Ci::Build
+ .in_pipelines([successful_pipeline, running_pipeline, failed_pipeline])
+ .latest
+ .success
+ .for_ref(@ref)
+ .by_name(@job)
+
+ builds.max_by(&:created_at)
+ else
+ successful_pipeline
+ end
- if @job.blank?
- @pipeline.coverage
- else
- @pipeline.builds
- .find_by(name: @job)
- .try(:coverage)
- end
+ latest&.coverage
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/lib/gitlab/bitbucket_server_import/importer.rb b/lib/gitlab/bitbucket_server_import/importer.rb
index aca5a63a424..d29799f1029 100644
--- a/lib/gitlab/bitbucket_server_import/importer.rb
+++ b/lib/gitlab/bitbucket_server_import/importer.rb
@@ -4,11 +4,14 @@ module Gitlab
module BitbucketServerImport
class Importer
attr_reader :recover_missing_commits
- attr_reader :project, :project_key, :repository_slug, :client, :errors, :users
+ attr_reader :project, :project_key, :repository_slug, :client, :errors, :users, :already_imported_cache_key
attr_accessor :logger
REMOTE_NAME = 'bitbucket_server'
BATCH_SIZE = 100
+ # The base cache key to use for tracking already imported objects.
+ ALREADY_IMPORTED_CACHE_KEY =
+ 'bitbucket_server-importer/already-imported/%{project}/%{collection}'
TempBranch = Struct.new(:name, :sha)
@@ -36,17 +39,25 @@ module Gitlab
@users = {}
@temp_branches = []
@logger = Gitlab::Import::Logger.build
+ @already_imported_cache_key = ALREADY_IMPORTED_CACHE_KEY %
+ { project: project.id, collection: collection_method }
+ end
+
+ def collection_method
+ :pull_requests
end
def execute
import_repository
import_pull_requests
+ download_lfs_objects
delete_temp_branches
handle_errors
metrics.track_finished_import
log_info(stage: "complete")
+ Gitlab::Cache::Import::Caching.expire(already_imported_cache_key, 15.minutes.to_i)
true
end
@@ -148,6 +159,14 @@ module Gitlab
raise
end
+ def download_lfs_objects
+ result = Projects::LfsPointers::LfsImportService.new(project).execute
+
+ if result[:status] == :error
+ errors << { type: :lfs_objects, errors: "The Lfs import process failed. #{result[:message]}" }
+ end
+ end
+
# Bitbucket Server keeps tracks of references for open pull requests in
# refs/heads/pull-requests, but closed and merged requests get moved
# into hidden internal refs under stash-refs/pull-requests. Unless the
@@ -158,16 +177,29 @@ module Gitlab
# on the remote server. Then we have to issue a `git fetch` to download these
# branches.
def import_pull_requests
- pull_requests = client.pull_requests(project_key, repository_slug).to_a
+ page = 0
+
+ log_info(stage: 'import_pull_requests', message: "starting")
+
+ loop do
+ log_debug(stage: 'import_pull_requests', message: "importing page #{page} and batch-size #{BATCH_SIZE} from #{page * BATCH_SIZE} to #{(page + 1) * BATCH_SIZE}")
+
+ pull_requests = client.pull_requests(project_key, repository_slug, page_offset: page, limit: BATCH_SIZE).to_a
- # Creating branches on the server and fetching the newly-created branches
- # may take a number of network round-trips. Do this in batches so that we can
- # avoid doing a git fetch for every new branch.
- pull_requests.each_slice(BATCH_SIZE) do |batch|
- restore_branches(batch) if recover_missing_commits
+ break if pull_requests.empty?
- batch.each do |pull_request|
- import_bitbucket_pull_request(pull_request)
+ # Creating branches on the server and fetching the newly-created branches
+ # may take a number of network round-trips. This used to be done in batches to
+ # avoid doing a git fetch for every new branch, as the whole process is now
+ # batched, we do not need to separately do this in batches.
+ restore_branches(pull_requests) if recover_missing_commits
+
+ pull_requests.each do |pull_request|
+ if already_imported?(pull_request)
+ log_info(stage: 'import_pull_requests', message: 'already imported', iid: pull_request.iid)
+ else
+ import_bitbucket_pull_request(pull_request)
+ end
rescue StandardError => e
Gitlab::ErrorTracking.log_exception(
e,
@@ -177,9 +209,25 @@ module Gitlab
backtrace = Gitlab::BacktraceCleaner.clean_backtrace(e.backtrace)
errors << { type: :pull_request, iid: pull_request.iid, errors: e.message, backtrace: backtrace.join("\n"), raw_response: pull_request.raw }
end
+
+ log_debug(stage: 'import_pull_requests', message: "finished page #{page} and batch-size #{BATCH_SIZE}")
+ page += 1
end
end
+ # Returns true if the given object has already been imported, false
+ # otherwise.
+ #
+ # object - The object to check.
+ def already_imported?(pull_request)
+ Gitlab::Cache::Import::Caching.set_includes?(already_imported_cache_key, pull_request.iid)
+ end
+
+ # Marks the given object as "already imported".
+ def mark_as_imported(pull_request)
+ Gitlab::Cache::Import::Caching.set_add(already_imported_cache_key, pull_request.iid)
+ end
+
def delete_temp_branches
@temp_branches.each do |branch|
client.delete_branch(project_key, repository_slug, branch.name, branch.sha)
@@ -227,6 +275,7 @@ module Gitlab
end
log_info(stage: 'import_bitbucket_pull_requests', message: 'finished', iid: pull_request.iid)
+ mark_as_imported(pull_request)
end
def import_pull_request_comments(pull_request, merge_request)
@@ -378,6 +427,10 @@ module Gitlab
}
end
+ def log_debug(details)
+ logger.debug(log_base_data.merge(details))
+ end
+
def log_info(details)
logger.info(log_base_data.merge(details))
end
diff --git a/lib/gitlab/bulk_import/client.rb b/lib/gitlab/bulk_import/client.rb
deleted file mode 100644
index c6e77a158cd..00000000000
--- a/lib/gitlab/bulk_import/client.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BulkImport
- class Client
- API_VERSION = 'v4'.freeze
- DEFAULT_PAGE = 1.freeze
- DEFAULT_PER_PAGE = 30.freeze
-
- ConnectionError = Class.new(StandardError)
-
- def initialize(uri:, token:, page: DEFAULT_PAGE, per_page: DEFAULT_PER_PAGE, api_version: API_VERSION)
- @uri = URI.parse(uri)
- @token = token&.strip
- @page = page
- @per_page = per_page
- @api_version = api_version
- end
-
- def get(resource, query = {})
- response = with_error_handling do
- Gitlab::HTTP.get(
- resource_url(resource),
- headers: request_headers,
- follow_redirects: false,
- query: query.merge(request_query)
- )
- end
-
- response.parsed_response
- end
-
- private
-
- def request_query
- {
- page: @page,
- per_page: @per_page
- }
- end
-
- def request_headers
- {
- 'Content-Type' => 'application/json',
- 'Authorization' => "Bearer #{@token}"
- }
- end
-
- def with_error_handling
- response = yield
-
- raise ConnectionError.new("Error #{response.code}") unless response.success?
-
- response
- rescue *Gitlab::HTTP::HTTP_ERRORS => e
- raise ConnectionError, e
- end
-
- def base_uri
- @base_uri ||= "#{@uri.scheme}://#{@uri.host}:#{@uri.port}"
- end
-
- def api_url
- Gitlab::Utils.append_path(base_uri, "/api/#{@api_version}")
- end
-
- def resource_url(resource)
- Gitlab::Utils.append_path(api_url, resource)
- end
- end
- end
-end
diff --git a/lib/gitlab/chat/output.rb b/lib/gitlab/chat/output.rb
index 411b1555a7d..4a55b81a9eb 100644
--- a/lib/gitlab/chat/output.rb
+++ b/lib/gitlab/chat/output.rb
@@ -12,7 +12,10 @@ module Gitlab
PRIMARY_SECTION = 'chat_reply'
# The backup trace section in case the primary one could not be found.
- FALLBACK_SECTION = 'build_script'
+ FALLBACK_SECTION = 'step_script'
+
+ # `step_script` used to be `build_script` before runner 13.1
+ LEGACY_SECTION = 'build_script'
# build - The `Ci::Build` to obtain the output from.
def initialize(build)
@@ -37,24 +40,6 @@ module Gitlab
end
end
- # Returns the offset to seek to and the number of bytes to read relative
- # to the offset.
- def read_offset_and_length
- section = find_build_trace_section(PRIMARY_SECTION) ||
- find_build_trace_section(FALLBACK_SECTION)
-
- unless section
- raise(
- MissingBuildSectionError,
- "The build_script trace section could not be found for build #{build.id}"
- )
- end
-
- length = section[:byte_end] - section[:byte_start]
-
- [section[:byte_start], length]
- end
-
# Removes the line containing the executed command from the build output.
#
# output - A `String` containing the output of a trace section.
@@ -88,6 +73,27 @@ module Gitlab
def trace
@trace ||= build.trace
end
+
+ private
+
+ # Returns the offset to seek to and the number of bytes to read relative
+ # to the offset.
+ def read_offset_and_length
+ section = find_build_trace_section(PRIMARY_SECTION) ||
+ find_build_trace_section(FALLBACK_SECTION) ||
+ find_build_trace_section(LEGACY_SECTION)
+
+ unless section
+ raise(
+ MissingBuildSectionError,
+ "The build_script trace section could not be found for build #{build.id}"
+ )
+ end
+
+ length = section[:byte_end] - section[:byte_start]
+
+ [section[:byte_start], length]
+ end
end
end
end
diff --git a/lib/gitlab/ci/build/rules/rule/clause/changes.rb b/lib/gitlab/ci/build/rules/rule/clause/changes.rb
index 728a66ca87f..cbecce57163 100644
--- a/lib/gitlab/ci/build/rules/rule/clause/changes.rb
+++ b/lib/gitlab/ci/build/rules/rule/clause/changes.rb
@@ -11,12 +11,22 @@ module Gitlab
def satisfied_by?(pipeline, context)
return true if pipeline.modified_paths.nil?
+ expanded_globs = expand_globs(pipeline, context)
pipeline.modified_paths.any? do |path|
- @globs.any? do |glob|
+ expanded_globs.any? do |glob|
File.fnmatch?(glob, path, File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB)
end
end
end
+
+ def expand_globs(pipeline, context)
+ return @globs unless ::Feature.enabled?(:ci_variable_expansion_in_rules_changes, pipeline.project, default_enabled: true)
+ return @globs unless context
+
+ @globs.map do |glob|
+ ExpandVariables.expand_existing(glob, context.variables)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/ci/charts.rb b/lib/gitlab/ci/charts.rb
index 3fbfdffe277..25fb9c0ca97 100644
--- a/lib/gitlab/ci/charts.rb
+++ b/lib/gitlab/ci/charts.rb
@@ -3,38 +3,8 @@
module Gitlab
module Ci
module Charts
- module DailyInterval
- # rubocop: disable CodeReuse/ActiveRecord
- def grouped_count(query)
- query
- .group("DATE(#{::Ci::Pipeline.table_name}.created_at)")
- .count(:created_at)
- .transform_keys { |date| date.strftime(@format) } # rubocop:disable Gitlab/ModuleWithInstanceVariables
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def interval_step
- @interval_step ||= 1.day
- end
- end
-
- module MonthlyInterval
- # rubocop: disable CodeReuse/ActiveRecord
- def grouped_count(query)
- query
- .group("to_char(#{::Ci::Pipeline.table_name}.created_at, '01 Month YYYY')")
- .count(:created_at)
- .transform_keys(&:squish)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def interval_step
- @interval_step ||= 1.month
- end
- end
-
class Chart
- attr_reader :labels, :total, :success, :project, :pipeline_times
+ attr_reader :from, :to, :labels, :total, :success, :project, :pipeline_times
def initialize(project)
@labels = []
@@ -46,48 +16,59 @@ module Gitlab
collect
end
+ private
+
+ attr_reader :interval
+
# rubocop: disable CodeReuse/ActiveRecord
def collect
query = project.all_pipelines
- .where("? > #{::Ci::Pipeline.table_name}.created_at AND #{::Ci::Pipeline.table_name}.created_at > ?", @to, @from) # rubocop:disable GitlabSecurity/SqlInjection
+ .where(::Ci::Pipeline.arel_table['created_at'].gteq(@from))
+ .where(::Ci::Pipeline.arel_table['created_at'].lteq(@to))
totals_count = grouped_count(query)
success_count = grouped_count(query.success)
current = @from
- while current < @to
- label = current.strftime(@format)
-
- @labels << label
- @total << (totals_count[label] || 0)
- @success << (success_count[label] || 0)
+ while current <= @to
+ @labels << current.strftime(@format)
+ @total << (totals_count[current] || 0)
+ @success << (success_count[current] || 0)
current += interval_step
end
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def grouped_count(query)
+ query
+ .group("date_trunc('#{interval}', #{::Ci::Pipeline.table_name}.created_at)")
+ .count(:created_at)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def interval_step
+ @interval_step ||= 1.public_send(interval) # rubocop: disable GitlabSecurity/PublicSend
+ end
end
class YearChart < Chart
- include MonthlyInterval
- attr_reader :to, :from
-
def initialize(*)
@to = Date.today.end_of_month.end_of_day
- @from = @to.years_ago(1).beginning_of_month.beginning_of_day
- @format = '%d %B %Y'
+ @from = (@to - 1.year).beginning_of_month.beginning_of_day
+ @interval = :month
+ @format = '%B %Y'
super
end
end
class MonthChart < Chart
- include DailyInterval
- attr_reader :to, :from
-
def initialize(*)
@to = Date.today.end_of_day
- @from = 1.month.ago.beginning_of_day
+ @from = (@to - 1.month).beginning_of_day
+ @interval = :day
@format = '%d %B'
super
@@ -95,12 +76,10 @@ module Gitlab
end
class WeekChart < Chart
- include DailyInterval
- attr_reader :to, :from
-
def initialize(*)
@to = Date.today.end_of_day
- @from = 1.week.ago.beginning_of_day
+ @from = (@to - 1.week).beginning_of_day
+ @interval = :day
@format = '%d %B'
super
diff --git a/lib/gitlab/ci/config/entry/bridge.rb b/lib/gitlab/ci/config/entry/bridge.rb
index 1740032e5c7..70fcc1d586a 100644
--- a/lib/gitlab/ci/config/entry/bridge.rb
+++ b/lib/gitlab/ci/config/entry/bridge.rb
@@ -18,7 +18,6 @@ module Gitlab
validates :config, allowed_keys: ALLOWED_KEYS + PROCESSABLE_ALLOWED_KEYS
with_options allow_nil: true do
- validates :allow_failure, boolean: true
validates :when, inclusion: {
in: ALLOWED_WHEN,
message: "should be one of: #{ALLOWED_WHEN.join(', ')}"
@@ -48,7 +47,7 @@ module Gitlab
inherit: false,
metadata: { allowed_needs: %i[job bridge] }
- attributes :when, :allow_failure
+ attributes :when
def self.matching?(name, config)
!name.to_s.start_with?('.') &&
@@ -60,14 +59,6 @@ module Gitlab
true
end
- def manual_action?
- self.when == 'manual'
- end
-
- def ignored?
- allow_failure.nil? ? manual_action? : allow_failure
- end
-
def value
super.merge(
trigger: (trigger_value if trigger_defined?),
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index ecc2c5cb729..1ce7060df22 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -24,7 +24,6 @@ module Gitlab
validates :script, presence: true
with_options allow_nil: true do
- validates :allow_failure, boolean: true
validates :when, inclusion: {
in: ALLOWED_WHEN,
message: "should be one of: #{ALLOWED_WHEN.join(', ')}"
@@ -118,7 +117,7 @@ module Gitlab
description: 'Parallel configuration for this job.',
inherit: false
- attributes :script, :tags, :allow_failure, :when, :dependencies,
+ attributes :script, :tags, :when, :dependencies,
:needs, :retry, :parallel, :start_in,
:interruptible, :timeout, :resource_group, :release
@@ -141,18 +140,10 @@ module Gitlab
end
end
- def manual_action?
- self.when == 'manual'
- end
-
def delayed?
self.when == 'delayed'
end
- def ignored?
- allow_failure.nil? ? manual_action? : allow_failure
- end
-
def value
super.merge(
before_script: before_script_value,
diff --git a/lib/gitlab/ci/config/entry/processable.rb b/lib/gitlab/ci/config/entry/processable.rb
index f10c509d0cc..c0315e5f901 100644
--- a/lib/gitlab/ci/config/entry/processable.rb
+++ b/lib/gitlab/ci/config/entry/processable.rb
@@ -32,6 +32,7 @@ module Gitlab
with_options allow_nil: true do
validates :extends, array_of_strings_or_string: true
validates :rules, array_of_hashes: true
+ validates :allow_failure, boolean: true
end
end
@@ -64,7 +65,7 @@ module Gitlab
inherit: false,
default: {}
- attributes :extends, :rules
+ attributes :extends, :rules, :allow_failure
end
def compose!(deps = nil)
@@ -136,6 +137,14 @@ module Gitlab
root_variables.merge(variables_value.to_h)
end
+
+ def manual_action?
+ self.when == 'manual'
+ end
+
+ def ignored?
+ allow_failure.nil? ? manual_action? : allow_failure
+ end
end
end
end
diff --git a/lib/gitlab/ci/config/entry/product/variables.rb b/lib/gitlab/ci/config/entry/product/variables.rb
index 2481989060e..aa34cfb3acc 100644
--- a/lib/gitlab/ci/config/entry/product/variables.rb
+++ b/lib/gitlab/ci/config/entry/product/variables.rb
@@ -14,7 +14,7 @@ module Gitlab
validations do
validates :config, variables: { array_values: true }
validates :config, length: {
- minimum: :minimum,
+ minimum: 1,
too_short: 'requires at least %{count} items'
}
end
@@ -28,10 +28,6 @@ module Gitlab
.map { |key, value| [key.to_s, Array(value).map(&:to_s)] }
.to_h
end
-
- def minimum
- ::Gitlab::Ci::Features.one_dimensional_matrix_enabled? ? 1 : 2
- end
end
end
end
diff --git a/lib/gitlab/ci/config/external/mapper.rb b/lib/gitlab/ci/config/external/mapper.rb
index 97ae6c4ceba..90692eafc3f 100644
--- a/lib/gitlab/ci/config/external/mapper.rb
+++ b/lib/gitlab/ci/config/external/mapper.rb
@@ -33,6 +33,7 @@ module Gitlab
locations
.compact
.map(&method(:normalize_location))
+ .flat_map(&method(:expand_project_files))
.each(&method(:verify_duplicates!))
.map(&method(:select_first_matching))
end
@@ -52,6 +53,15 @@ module Gitlab
end
end
+ def expand_project_files(location)
+ return location unless ::Feature.enabled?(:ci_include_multiple_files_from_project, context.project, default_enabled: true)
+ return location unless location[:project]
+
+ Array.wrap(location[:file]).map do |file|
+ location.merge(file: file)
+ end
+ end
+
def normalize_location_string(location)
if ::Gitlab::UrlSanitizer.valid?(location)
{ remote: location }
diff --git a/lib/gitlab/ci/features.rb b/lib/gitlab/ci/features.rb
index 1b58e3ec71a..661189eea50 100644
--- a/lib/gitlab/ci/features.rb
+++ b/lib/gitlab/ci/features.rb
@@ -32,16 +32,12 @@ module Gitlab
end
# 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,
+ # is a safe switch to disable the feature for a particular project when something went wrong,
# therefore it's not supposed to be enabled by default.
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.lint_creates_pipeline_with_dry_run?(project)
- ::Feature.enabled?(:ci_lint_creates_pipeline_with_dry_run, project, default_enabled: true)
- end
-
def self.project_transactionless_destroy?(project)
Feature.enabled?(:project_transactionless_destroy, project, default_enabled: false)
end
@@ -59,13 +55,21 @@ module Gitlab
::Feature.enabled?(:ci_trace_log_invalid_chunks, project, type: :ops, default_enabled: false)
end
- def self.one_dimensional_matrix_enabled?
- ::Feature.enabled?(:one_dimensional_matrix, default_enabled: true)
- end
-
def self.manual_bridges_enabled?(project)
::Feature.enabled?(:ci_manual_bridges, project, default_enabled: true)
end
+
+ def self.auto_rollback_available?(project)
+ ::Feature.enabled?(:cd_auto_rollback, project) && project&.feature_available?(:auto_rollback)
+ end
+
+ def self.seed_block_run_before_workflow_rules_enabled?(project)
+ ::Feature.enabled?(:ci_seed_block_run_before_workflow_rules, project, default_enabled: true)
+ end
+
+ def self.ci_pipeline_editor_page_enabled?(project)
+ ::Feature.enabled?(:ci_pipeline_editor_page, project, default_enabled: false)
+ end
end
end
end
diff --git a/lib/gitlab/ci/jwt.rb b/lib/gitlab/ci/jwt.rb
index 491facd0a43..a8943eadf4f 100644
--- a/lib/gitlab/ci/jwt.rb
+++ b/lib/gitlab/ci/jwt.rb
@@ -6,6 +6,8 @@ module Gitlab
NOT_BEFORE_TIME = 5
DEFAULT_EXPIRE_TIME = 60 * 5
+ NoSigningKeyError = Class.new(StandardError)
+
def self.for_build(build)
self.new(build, ttl: build.metadata_timeout).encoded
end
@@ -27,7 +29,7 @@ module Gitlab
private
- attr_reader :build, :ttl, :key_data
+ attr_reader :build, :ttl
def reserved_claims
now = Time.now.to_i
@@ -60,7 +62,17 @@ module Gitlab
end
def key
- @key ||= OpenSSL::PKey::RSA.new(Rails.application.secrets.openid_connect_signing_key)
+ @key ||= begin
+ key_data = if Feature.enabled?(:ci_jwt_signing_key, build.project, default_enabled: true)
+ Gitlab::CurrentSettings.ci_jwt_signing_key
+ else
+ Rails.application.secrets.openid_connect_signing_key
+ end
+
+ raise NoSigningKeyError unless key_data
+
+ OpenSSL::PKey::RSA.new(key_data)
+ end
end
def public_key
diff --git a/lib/gitlab/ci/lint.rb b/lib/gitlab/ci/lint.rb
index 44f2ac23ce3..fb795152abe 100644
--- a/lib/gitlab/ci/lint.rb
+++ b/lib/gitlab/ci/lint.rb
@@ -24,7 +24,7 @@ module Gitlab
end
def validate(content, dry_run: false)
- if dry_run && Gitlab::Ci::Features.lint_creates_pipeline_with_dry_run?(@project)
+ if dry_run
simulate_pipeline_creation(content)
else
static_validation(content)
diff --git a/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb b/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
index 468f3bc4689..a864c843dd8 100644
--- a/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
+++ b/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
@@ -25,7 +25,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def auto_cancelable_pipelines
- project.ci_pipelines
+ pipelines
.where(ref: pipeline.ref)
.where.not(id: pipeline.same_family_pipeline_ids)
.where.not(sha: project.commit(pipeline.ref).try(:id))
@@ -33,6 +33,14 @@ module Gitlab
.with_only_interruptible_builds
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def pipelines
+ if ::Feature.enabled?(:ci_auto_cancel_all_pipelines, project, default_enabled: false)
+ project.all_pipelines.ci_and_parent_sources
+ else
+ project.ci_pipelines
+ end
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/seed.rb b/lib/gitlab/ci/pipeline/chain/seed.rb
index e10a0bc3718..ba86b08d209 100644
--- a/lib/gitlab/ci/pipeline/chain/seed.rb
+++ b/lib/gitlab/ci/pipeline/chain/seed.rb
@@ -19,10 +19,12 @@ module Gitlab
# Build to prevent erroring out on ambiguous refs.
pipeline.protected = @command.protected_ref?
- ##
- # Populate pipeline with block argument of CreatePipelineService#execute.
- #
- @command.seeds_block&.call(pipeline)
+ unless ::Gitlab::Ci::Features.seed_block_run_before_workflow_rules_enabled?(project)
+ ##
+ # Populate pipeline with block argument of CreatePipelineService#execute.
+ #
+ @command.seeds_block&.call(pipeline)
+ end
##
# Gather all runtime build/stage errors
diff --git a/lib/gitlab/ci/pipeline/chain/seed_block.rb b/lib/gitlab/ci/pipeline/chain/seed_block.rb
new file mode 100644
index 00000000000..f8e62949bea
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/seed_block.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ class SeedBlock < Chain::Base
+ include Chain::Helpers
+ include Gitlab::Utils::StrongMemoize
+
+ def perform!
+ return unless ::Gitlab::Ci::Features.seed_block_run_before_workflow_rules_enabled?(project)
+
+ ##
+ # Populate pipeline with block argument of CreatePipelineService#execute.
+ #
+ @command.seeds_block&.call(pipeline)
+
+ raise "Pipeline cannot be persisted by `seeds_block`" if pipeline.persisted?
+ end
+
+ def break?
+ return false unless ::Gitlab::Ci::Features.seed_block_run_before_workflow_rules_enabled?(project)
+
+ pipeline.errors.any?
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/seed/environment.rb b/lib/gitlab/ci/pipeline/seed/environment.rb
index 42e8c365824..b20dc383419 100644
--- a/lib/gitlab/ci/pipeline/seed/environment.rb
+++ b/lib/gitlab/ci/pipeline/seed/environment.rb
@@ -12,12 +12,23 @@ module Gitlab
end
def to_resource
- job.project.environments
- .safe_find_or_create_by(name: expanded_environment_name)
+ environments.safe_find_or_create_by(name: expanded_environment_name) do |environment|
+ environment.auto_stop_in = auto_stop_in
+ end
end
private
+ def environments
+ job.project.environments
+ end
+
+ def auto_stop_in
+ if Feature.enabled?(:environment_auto_stop_start_on_create)
+ job.environment_auto_stop_in
+ end
+ end
+
def expanded_environment_name
job.expanded_environment_name
end
diff --git a/lib/gitlab/ci/reports/test_case.rb b/lib/gitlab/ci/reports/test_case.rb
index 8c70dbb6931..09121191047 100644
--- a/lib/gitlab/ci/reports/test_case.rb
+++ b/lib/gitlab/ci/reports/test_case.rb
@@ -10,7 +10,7 @@ module Gitlab
STATUS_ERROR = 'error'
STATUS_TYPES = [STATUS_ERROR, STATUS_FAILED, STATUS_SUCCESS, STATUS_SKIPPED].freeze
- attr_reader :suite_name, :name, :classname, :execution_time, :status, :file, :system_output, :stack_trace, :key, :attachment, :job
+ attr_reader :suite_name, :name, :classname, :execution_time, :status, :file, :system_output, :stack_trace, :key, :attachment, :job, :recent_failures
def initialize(params)
@suite_name = params.fetch(:suite_name)
@@ -24,9 +24,15 @@ module Gitlab
@attachment = params.fetch(:attachment, nil)
@job = params.fetch(:job, nil)
+ @recent_failures = nil
+
@key = hash_key("#{suite_name}_#{classname}_#{name}")
end
+ def set_recent_failures(count, base_branch)
+ @recent_failures = { count: count, base_branch: base_branch }
+ end
+
def has_attachment?
attachment.present?
end
diff --git a/lib/gitlab/ci/reports/test_failure_history.rb b/lib/gitlab/ci/reports/test_failure_history.rb
new file mode 100644
index 00000000000..beceac5423a
--- /dev/null
+++ b/lib/gitlab/ci/reports/test_failure_history.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Reports
+ class TestFailureHistory
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(failed_test_cases, project)
+ @failed_test_cases = build_map(failed_test_cases)
+ @project = project
+ end
+
+ def load!
+ return unless Feature.enabled?(:test_failure_history, project)
+
+ recent_failures_count.each do |key_hash, count|
+ failed_test_cases[key_hash].set_recent_failures(count, project.default_branch_or_master)
+ end
+ end
+
+ private
+
+ attr_reader :report, :project, :failed_test_cases
+
+ def recent_failures_count
+ ::Ci::TestCaseFailure.recent_failures_count(
+ project: project,
+ test_case_keys: failed_test_cases.keys
+ )
+ end
+
+ def build_map(test_cases)
+ {}.tap do |hash|
+ test_cases.each do |test_case|
+ hash[test_case.key] = test_case
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/reports/test_suite_comparer.rb b/lib/gitlab/ci/reports/test_suite_comparer.rb
index a58de43e55e..239fc3b15e7 100644
--- a/lib/gitlab/ci/reports/test_suite_comparer.rb
+++ b/lib/gitlab/ci/reports/test_suite_comparer.rb
@@ -6,6 +6,9 @@ module Gitlab
class TestSuiteComparer
include Gitlab::Utils::StrongMemoize
+ DEFAULT_MAX_TESTS = 100
+ DEFAULT_MIN_TESTS = 10
+
attr_reader :name, :base_suite, :head_suite
def initialize(name, base_suite, head_suite)
@@ -81,6 +84,29 @@ module Gitlab
def error_count
new_errors.count + existing_errors.count
end
+
+ # This is used to limit the presented test cases but does not affect
+ # total count of tests in the summary
+ def limited_tests
+ strong_memoize(:limited_tests) do
+ # rubocop: disable CodeReuse/ActiveRecord
+ OpenStruct.new(
+ new_failures: new_failures.take(max_tests),
+ existing_failures: existing_failures.take(max_tests(new_failures)),
+ resolved_failures: resolved_failures.take(max_tests(new_failures, existing_failures)),
+ new_errors: new_errors.take(max_tests),
+ existing_errors: existing_errors.take(max_tests(new_errors)),
+ resolved_errors: resolved_errors.take(max_tests(new_errors, existing_errors))
+ )
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+
+ private
+
+ def max_tests(*used)
+ [DEFAULT_MAX_TESTS - used.map(&:count).sum, DEFAULT_MIN_TESTS].max
+ end
end
end
end
diff --git a/lib/gitlab/ci/runner_instructions.rb b/lib/gitlab/ci/runner_instructions.rb
index 2171637687f..dd0bfa768a8 100644
--- a/lib/gitlab/ci/runner_instructions.rb
+++ b/lib/gitlab/ci/runner_instructions.rb
@@ -106,7 +106,7 @@ module Gitlab
end
def get_file(path)
- File.read(path)
+ File.read(Rails.root.join(path).to_s)
end
def registration_token
diff --git a/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml b/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml
index 82b2f5c035e..453803a6f7e 100644
--- a/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml
@@ -4,6 +4,7 @@ stages:
- review
- deploy
- production
+ - cleanup
variables:
AUTO_DEVOPS_PLATFORM_TARGET: ECS
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index cba13f374f4..a13f2046291 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -160,9 +160,10 @@ include:
- 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/Code-Intelligence.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Code-Intelligence.gitlab-ci.yml
+ - template: Jobs/Code-Intelligence.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Code-Intelligence.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/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/Deploy/EC2.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/EC2.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
diff --git a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
index 0c3598a61a7..1c25d9d583b 100644
--- a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
@@ -16,4 +16,14 @@ build:
fi
- /build/build.sh
rules:
+ - if: '$AUTO_DEVOPS_PLATFORM_TARGET == "EC2"'
+ when: never
- if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
+
+build_artifact:
+ stage: build
+ script:
+ - printf "To build your project, please create a build_artifact job into your .gitlab-ci.yml file.\nMore information at https://docs.gitlab.com/ee/ci/cloud_deployment\n"
+ - exit 1
+ rules:
+ - if: '$AUTO_DEVOPS_PLATFORM_TARGET == "EC2"'
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 ec33020205b..fe23641802b 100644
--- a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
@@ -7,7 +7,7 @@ code_quality:
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
- CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.10-gitlab.1"
+ CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.18"
needs: []
script:
- export SOURCE_CODE=$PWD
@@ -34,6 +34,7 @@ code_quality:
CODECLIMATE_DEBUG \
CODECLIMATE_DEV \
REPORT_STDOUT \
+ REPORT_FORMAT \
ENGINE_MEMORY_LIMIT_BYTES \
) \
--volume "$PWD":/code \
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
index 33d77e39bc9..c4e194bd658 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
@@ -186,7 +186,7 @@ production_manual:
when: never
- if: '$CI_COMMIT_BRANCH != "master"'
when: never
- # $INCREMENTAL_ROLLOUT_ENABLED is for compamtibilty with pre-GitLab 11.4 syntax
+ # $INCREMENTAL_ROLLOUT_ENABLED is for compatibility with pre-GitLab 11.4 syntax
- if: '$INCREMENTAL_ROLLOUT_MODE == "manual" || $INCREMENTAL_ROLLOUT_ENABLED'
when: manual
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
index 8b921305c11..385959389de 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
@@ -183,7 +183,7 @@ production_manual:
when: never
- if: '$CI_COMMIT_BRANCH != "master"'
when: never
- # $INCREMENTAL_ROLLOUT_ENABLED is for compamtibilty with pre-GitLab 11.4 syntax
+ # $INCREMENTAL_ROLLOUT_ENABLED is for compatibility with pre-GitLab 11.4 syntax
- if: '$INCREMENTAL_ROLLOUT_MODE == "manual" || $INCREMENTAL_ROLLOUT_ENABLED'
when: manual
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml
index 317e8bfab0e..0289ba1c473 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml
@@ -8,8 +8,11 @@
#
# More about including CI templates: https://docs.gitlab.com/ee/ci/yaml/#includetemplate
-.deploy_to_ecs:
+.ecs_image:
image: 'registry.gitlab.com/gitlab-org/cloud-deploy/aws-ecs:latest'
+
+.deploy_to_ecs:
+ extends: .ecs_image
dependencies: []
script:
- ecs update-task-definition
@@ -17,8 +20,6 @@
.review_ecs_base:
stage: review
extends: .deploy_to_ecs
- environment:
- name: review/$CI_COMMIT_REF_NAME
.production_ecs_base:
stage: production
@@ -26,8 +27,18 @@
environment:
name: production
+.stop_review_ecs_base:
+ extends: .ecs_image
+ stage: cleanup
+ allow_failure: true
+ script:
+ - ecs stop-task
+
review_ecs:
extends: .review_ecs_base
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ on_stop: stop_review_ecs
rules:
- if: '$AUTO_DEVOPS_PLATFORM_TARGET != "ECS"'
when: never
@@ -39,8 +50,46 @@ review_ecs:
when: never
- if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
+stop_review_ecs:
+ extends: .stop_review_ecs_base
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ action: stop
+ rules:
+ - if: '$AUTO_DEVOPS_PLATFORM_TARGET != "ECS"'
+ when: never
+ - if: '$CI_KUBERNETES_ACTIVE'
+ when: never
+ - if: '$REVIEW_DISABLED'
+ when: never
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: never
+ - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
+ when: manual
+
review_fargate:
extends: .review_ecs_base
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ on_stop: stop_review_fargate
+ script:
+ - ecs update-task-definition
+ rules:
+ - if: '$AUTO_DEVOPS_PLATFORM_TARGET != "FARGATE"'
+ when: never
+ - if: '$CI_KUBERNETES_ACTIVE'
+ when: never
+ - if: '$REVIEW_DISABLED'
+ when: never
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: never
+ - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
+
+stop_review_fargate:
+ extends: .stop_review_ecs_base
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ action: stop
rules:
- if: '$AUTO_DEVOPS_PLATFORM_TARGET != "FARGATE"'
when: never
@@ -51,6 +100,7 @@ review_fargate:
- if: '$CI_COMMIT_BRANCH == "master"'
when: never
- if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
+ when: manual
production_ecs:
extends: .production_ecs_base
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 a9638f564f3..3f62d92ad13 100644
--- a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
@@ -1,6 +1,6 @@
apply:
stage: deploy
- image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.33.0"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.34.1"
environment:
name: production
variables:
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 c3a92b67a8b..0ae8fd833c4 100644
--- a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
@@ -1,3 +1,9 @@
+# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/
+
+# Configure the scanning tool through the environment variables.
+# List of the variables: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/#available-variables
+# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
+
stages:
- build
- test
@@ -7,7 +13,7 @@ stages:
variables:
FUZZAPI_PROFILE: Quick
FUZZAPI_VERSION: latest
- FUZZAPI_CONFIG: "/app/.gitlab-api-fuzzing.yml"
+ FUZZAPI_CONFIG: .gitlab-api-fuzzing.yml
FUZZAPI_TIMEOUT: 30
FUZZAPI_REPORT: gl-api-fuzzing-report.xml
#
@@ -17,9 +23,70 @@ variables:
# available (non 500 response to HTTP(s))
FUZZAPI_SERVICE_START_TIMEOUT: "300"
#
+ FUZZAPI_IMAGE: registry.gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing:${FUZZAPI_VERSION}-engine
+ #
+
+apifuzzer_fuzz_unlicensed:
+ stage: fuzz
+ allow_failure: true
+ rules:
+ - if: '$GITLAB_FEATURES !~ /\bapi_fuzzing\b/ && $API_FUZZING_DISABLED == null'
+ - when: never
+ script:
+ - |
+ echo "Error: Your GitLab project is not licensed for API Fuzzing."
+ - exit 1
apifuzzer_fuzz:
stage: fuzz
+ image:
+ name: $FUZZAPI_IMAGE
+ entrypoint: ["/bin/bash", "-l", "-c"]
+ variables:
+ FUZZAPI_PROJECT: $CI_PROJECT_PATH
+ FUZZAPI_API: http://apifuzzer:80
+ TZ: America/Los_Angeles
+ services:
+ - name: $FUZZAPI_IMAGE
+ alias: apifuzzer
+ entrypoint: ["dotnet", "/peach/Peach.Web.dll"]
+ allow_failure: true
+ rules:
+ - if: $FUZZAPI_D_TARGET_IMAGE
+ when: never
+ - if: $FUZZAPI_D_WORKER_IMAGE
+ when: never
+ - if: $API_FUZZING_DISABLED
+ when: never
+ - if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH &&
+ $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
+ when: never
+ - if: $GITLAB_FEATURES =~ /\bapi_fuzzing\b/
+ script:
+ #
+ # Validate options
+ - |
+ if [ "$FUZZAPI_HAR$FUZZAPI_OPENAPI$FUZZAPI_POSTMAN_COLLECTION" == "" ]; then \
+ echo "Error: One of FUZZAPI_HAR, FUZZAPI_OPENAPI, or FUZZAPI_POSTMAN_COLLECTION must be provided."; \
+ echo "See https://docs.gitlab.com/ee/user/application_security/api_fuzzing/ for information on how to configure API Fuzzing."; \
+ exit 1; \
+ fi
+ #
+ # Run user provided pre-script
+ - sh -c "$FUZZAPI_PRE_SCRIPT"
+ #
+ # Start scanning
+ - worker-entry
+ #
+ # Run user provided post-script
+ - sh -c "$FUZZAPI_POST_SCRIPT"
+ #
+ artifacts:
+ reports:
+ junit: $FUZZAPI_REPORT
+
+apifuzzer_fuzz_dnd:
+ stage: fuzz
image: docker:19.03.12
variables:
DOCKER_DRIVER: overlay2
@@ -28,20 +95,19 @@ apifuzzer_fuzz:
FUZZAPI_API: http://apifuzzer:80
allow_failure: true
rules:
+ - if: $FUZZAPI_D_TARGET_IMAGE == null && $FUZZAPI_D_WORKER_IMAGE == null
+ when: never
- if: $API_FUZZING_DISABLED
when: never
- if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH &&
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
- when: never
- - if: $FUZZAPI_HAR == null &&
- $FUZZAPI_OPENAPI == null &&
- $FUZZAPI_D_WORKER_IMAGE == null
+ $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
when: never
- if: $GITLAB_FEATURES =~ /\bapi_fuzzing\b/
services:
- docker:19.03.12-dind
script:
#
+ #
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
#
- docker network create --driver bridge $FUZZAPI_D_NETWORK
@@ -56,30 +122,13 @@ apifuzzer_fuzz:
--network $FUZZAPI_D_NETWORK \
-e Proxy:Port=8000 \
-e TZ=America/Los_Angeles \
- -e FUZZAPI_API=http://127.0.0.1:80 \
- -e FUZZAPI_PROJECT \
- -e FUZZAPI_PROFILE \
- -e FUZZAPI_CONFIG \
- -e FUZZAPI_REPORT \
- -e FUZZAPI_HAR \
- -e FUZZAPI_OPENAPI \
- -e FUZZAPI_TARGET_URL \
- -e FUZZAPI_OVERRIDES_FILE \
- -e FUZZAPI_OVERRIDES_ENV \
- -e FUZZAPI_OVERRIDES_CMD \
- -e FUZZAPI_OVERRIDES_INTERVAL \
- -e FUZZAPI_TIMEOUT \
- -e FUZZAPI_VERBOSE \
- -e FUZZAPI_SERVICE_START_TIMEOUT \
- -e FUZZAPI_HTTP_USERNAME \
- -e FUZZAPI_HTTP_PASSWORD \
-e 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:${FUZZAPI_VERSION}-engine
+ $FUZZAPI_IMAGE \
+ dotnet /peach/Peach.Web.dll
#
# Start target container
- |
@@ -94,19 +143,31 @@ apifuzzer_fuzz:
$FUZZAPI_D_TARGET_IMAGE \
; fi
#
- # Start worker container
+ # Start worker container if provided
- |
if [ "$FUZZAPI_D_WORKER_IMAGE" != "" ]; then \
- echo "Starting worker image $FUZZAPI_D_WORKER_IMAGE" \
+ echo "Starting worker image $FUZZAPI_D_WORKER_IMAGE"; \
docker run \
--name worker \
--network $FUZZAPI_D_NETWORK \
-e FUZZAPI_API=http://apifuzzer:80 \
-e FUZZAPI_PROJECT \
-e FUZZAPI_PROFILE \
- -e FUZZAPI_AUTOMATION_CMD \
-e FUZZAPI_CONFIG \
-e FUZZAPI_REPORT \
+ -e FUZZAPI_HAR \
+ -e FUZZAPI_OPENAPI \
+ -e FUZZAPI_POSTMAN_COLLECTION \
+ -e FUZZAPI_TARGET_URL \
+ -e FUZZAPI_OVERRIDES_FILE \
+ -e FUZZAPI_OVERRIDES_ENV \
+ -e FUZZAPI_OVERRIDES_CMD \
+ -e FUZZAPI_OVERRIDES_INTERVAL \
+ -e FUZZAPI_TIMEOUT \
+ -e FUZZAPI_VERBOSE \
+ -e FUZZAPI_SERVICE_START_TIMEOUT \
+ -e FUZZAPI_HTTP_USERNAME \
+ -e FUZZAPI_HTTP_PASSWORD \
-e CI_COMMIT_BRANCH=${CI_COMMIT_BRANCH} \
$FUZZAPI_D_WORKER_ENV \
$FUZZAPI_D_WORKER_PORTS \
@@ -115,13 +176,49 @@ apifuzzer_fuzz:
$FUZZAPI_D_WORKER_IMAGE \
; fi
#
- # 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
+ # Start API Fuzzing provided worker if no other worker present
+ - |
+ if [ "$FUZZAPI_D_WORKER_IMAGE" == "" ]; then \
+ if [ "$FUZZAPI_HAR$FUZZAPI_OPENAPI$FUZZAPI_POSTMAN_COLLECTION" == "" ]; then \
+ echo "Error: One of FUZZAPI_HAR, FUZZAPI_OPENAPI, or FUZZAPI_POSTMAN_COLLECTION must be provided."; \
+ echo "See https://docs.gitlab.com/ee/user/application_security/api_fuzzing/ for information on how to configure API Fuzzing."; \
+ exit 1; \
+ fi; \
+ docker run \
+ --name worker \
+ --network $FUZZAPI_D_NETWORK \
+ -e TZ=America/Los_Angeles \
+ -e FUZZAPI_API=http://apifuzzer:80 \
+ -e FUZZAPI_PROJECT \
+ -e FUZZAPI_PROFILE \
+ -e FUZZAPI_CONFIG \
+ -e FUZZAPI_REPORT \
+ -e FUZZAPI_HAR \
+ -e FUZZAPI_OPENAPI \
+ -e FUZZAPI_POSTMAN_COLLECTION \
+ -e FUZZAPI_TARGET_URL \
+ -e FUZZAPI_OVERRIDES_FILE \
+ -e FUZZAPI_OVERRIDES_ENV \
+ -e FUZZAPI_OVERRIDES_CMD \
+ -e FUZZAPI_OVERRIDES_INTERVAL \
+ -e FUZZAPI_TIMEOUT \
+ -e FUZZAPI_VERBOSE \
+ -e FUZZAPI_SERVICE_START_TIMEOUT \
+ -e FUZZAPI_HTTP_USERNAME \
+ -e FUZZAPI_HTTP_PASSWORD \
+ -v $CI_PROJECT_DIR:/app \
+ -p 81:80 \
+ -p 8001:8000 \
+ -p 515:514 \
+ --restart=no \
+ $FUZZAPI_IMAGE \
+ worker-entry \
+ ; 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
+ # Propagate exit code from api fuzzing scanner (if any)
+ - if [[ $(docker inspect apifuzzer --format='{{.State.ExitCode}}') != "0" ]]; then echo "API Fuzzing scanner exited with an error. Logs are available as job artifacts."; exit 1; fi
#
- # Run user provided pre-script
+ # Run user provided post-script
- sh -c "$FUZZAPI_POST_SCRIPT"
#
after_script:
@@ -129,13 +226,13 @@ apifuzzer_fuzz:
# Shutdown all containers
- echo "Stopping all containers"
- if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then docker stop target; fi
- - if [ "$FUZZAPI_D_WORKER_IMAGE" != "" ]; then docker stop worker; fi
+ - docker stop worker
- docker stop apifuzzer
#
# Save docker logs
- docker logs apifuzzer &> gl-api_fuzzing-logs.log
- if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then docker logs target &> gl-api_fuzzing-target-logs.log; fi
- - if [ "$FUZZAPI_D_WORKER_IMAGE" != "" ]; then docker logs worker &> gl-api_fuzzing-worker-logs.log; fi
+ - docker logs worker &> gl-api_fuzzing-worker-logs.log
#
artifacts:
when: always
diff --git a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
index 21bcdd8d9b5..3cbde9d30c8 100644
--- a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
@@ -4,8 +4,7 @@ variables:
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
-
- CS_MAJOR_VERSION: 2
+ CS_MAJOR_VERSION: 3
container_scanning:
stage: test
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 e268b48d133..a1b6dc2cc1b 100644
--- a/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml
@@ -11,6 +11,14 @@ variables:
COVFUZZ_URL_PREFIX: "https://gitlab.com/gitlab-org/security-products/analyzers/gitlab-cov-fuzz/-/raw"
+coverage_fuzzing_unlicensed:
+ stage: test
+ allow_failure: true
+ rules:
+ - if: $GITLAB_FEATURES !~ /\bcoverage_fuzzing\b/ && $COVFUZZ_DISABLED == null
+ script:
+ - echo "ERROR Your GitLab project is missing licensing for Coverage Fuzzing" && exit 1
+
.fuzz_base:
stage: fuzz
allow_failure: true
diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
index 4418ff18d73..a51cb61da6d 100644
--- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
@@ -134,6 +134,7 @@ mobsf-android-sast:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/mobsf:$SAST_ANALYZER_IMAGE_TAG"
+ MOBSF_API_KEY: key
rules:
- if: $SAST_DISABLED
when: never
@@ -152,6 +153,7 @@ mobsf-ios-sast:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/mobsf:$SAST_ANALYZER_IMAGE_TAG"
+ MOBSF_API_KEY: key
rules:
- if: $SAST_DISABLED
when: never
diff --git a/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
index 2d2e0859373..232c320562b 100644
--- a/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
@@ -131,6 +131,8 @@ secrets:
variables:
- $SECURE_BINARIES_DOWNLOAD_IMAGES == "true" &&
$SECURE_BINARIES_ANALYZERS =~ /\bsecrets\b/
+ variables:
+ SECURE_BINARIES_ANALYZER_VERSION: "3"
sobelow:
extends: .download_images
@@ -162,6 +164,8 @@ klar:
variables:
- $SECURE_BINARIES_DOWNLOAD_IMAGES == "true" &&
$SECURE_BINARIES_ANALYZERS =~ /\bklar\b/
+ variables:
+ SECURE_BINARIES_ANALYZER_VERSION: "3"
clair-vulnerabilities-db:
extends: .download_images
diff --git a/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml
index b08ccf18b58..5963d7138c5 100644
--- a/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml
@@ -1,11 +1,12 @@
include:
- - template: Terraform/Base.latest.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml
+ - template: Terraform/Base.latest.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
stages:
- init
- validate
- build
- deploy
+ - cleanup
init:
extends: .init
diff --git a/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
index 000a1a7f580..e455bfac9de 100644
--- a/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
@@ -12,9 +12,6 @@
image:
name: registry.gitlab.com/gitlab-org/terraform-images/stable:latest
-before_script:
- - cd ${TF_ROOT}
-
variables:
TF_ROOT: ${CI_PROJECT_DIR}
@@ -26,16 +23,19 @@ cache:
.init: &init
stage: init
script:
+ - cd ${TF_ROOT}
- gitlab-terraform init
.validate: &validate
stage: validate
script:
+ - cd ${TF_ROOT}
- gitlab-terraform validate
.build: &build
stage: build
script:
+ - cd ${TF_ROOT}
- gitlab-terraform plan
- gitlab-terraform plan-json
artifacts:
@@ -47,7 +47,14 @@ cache:
.deploy: &deploy
stage: deploy
script:
+ - cd ${TF_ROOT}
- gitlab-terraform apply
when: manual
only:
- master
+
+.destroy: &destroy
+ stage: cleanup
+ script:
+ - gitlab-terraform destroy
+ when: manual
diff --git a/lib/gitlab/ci/trace/chunked_io.rb b/lib/gitlab/ci/trace/chunked_io.rb
index e99889f4a25..6f3e4ccf48d 100644
--- a/lib/gitlab/ci/trace/chunked_io.rb
+++ b/lib/gitlab/ci/trace/chunked_io.rb
@@ -75,7 +75,7 @@ module Gitlab
until length <= 0 || eof?
data = chunk_slice_from_offset
- raise FailedToGetChunkError if data.empty?
+ raise FailedToGetChunkError if data.to_s.empty?
chunk_bytes = [CHUNK_SIZE - chunk_offset, length].min
chunk_data_slice = data.byteslice(0, chunk_bytes)
@@ -100,7 +100,7 @@ module Gitlab
until eof?
data = chunk_slice_from_offset
- raise FailedToGetChunkError if data.empty?
+ raise FailedToGetChunkError if data.to_s.empty?
new_line = data.index("\n")
diff --git a/lib/gitlab/conflict/file.rb b/lib/gitlab/conflict/file.rb
index 0ca99506311..4d7590a8e38 100644
--- a/lib/gitlab/conflict/file.rb
+++ b/lib/gitlab/conflict/file.rb
@@ -9,6 +9,11 @@ module Gitlab
CONTEXT_LINES = 3
+ CONFLICT_TYPES = {
+ "old" => "conflict_marker_their",
+ "new" => "conflict_marker_our"
+ }.freeze
+
attr_reader :merge_request
# 'raw' holds the Gitlab::Git::Conflict::File that this instance wraps
@@ -46,6 +51,34 @@ module Gitlab
end
end
+ def diff_lines_for_serializer
+ # calculate sections and highlight lines before changing types
+ sections && highlight_lines!
+
+ sections.flat_map do |section|
+ if section[:conflict]
+ lines = []
+
+ initial_type = nil
+ section[:lines].each do |line|
+ if line.type != initial_type
+ lines << create_separator_line(line)
+ initial_type = line.type
+ end
+
+ line.type = CONFLICT_TYPES[line.type]
+ lines << line
+ end
+
+ lines << create_separator_line(lines.last)
+
+ lines
+ else
+ section[:lines]
+ end
+ end
+ end
+
def sections
return @sections if @sections
@@ -93,9 +126,15 @@ module Gitlab
lines = tail_lines
elsif conflict_before
- # We're at the end of the file (no conflicts after), so just remove extra
- # trailing lines.
+ # We're at the end of the file (no conflicts after)
+ number_of_trailing_lines = lines.size
+
+ # Remove extra trailing lines
lines = lines.first(CONTEXT_LINES)
+
+ if number_of_trailing_lines > CONTEXT_LINES
+ lines << create_match_line(lines.last)
+ end
end
end
@@ -117,6 +156,10 @@ module Gitlab
Gitlab::Diff::Line.new('', 'match', line.index, line.old_pos, line.new_pos)
end
+ def create_separator_line(line)
+ Gitlab::Diff::Line.new('', 'conflict_marker', line.index, nil, nil)
+ end
+
# Any line beginning with a letter, an underscore, or a dollar can be used in a
# match line header. Only context sections can contain match lines, as match lines
# have to exist in both versions of the file.
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 2b08d3c63bb..d0579a44219 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -16,8 +16,8 @@ module Gitlab
@in_memory_application_settings = nil
end
- def method_missing(name, *args, &block)
- current_application_settings.send(name, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
+ def method_missing(name, *args, **kwargs, &block)
+ current_application_settings.send(name, *args, **kwargs, &block) # rubocop:disable GitlabSecurity/PublicSend
end
def respond_to_missing?(name, include_private = false)
diff --git a/lib/gitlab/danger/commit_linter.rb b/lib/gitlab/danger/commit_linter.rb
index 7b01db125a9..2e469359bdc 100644
--- a/lib/gitlab/danger/commit_linter.rb
+++ b/lib/gitlab/danger/commit_linter.rb
@@ -191,7 +191,7 @@ module Gitlab
end
def subject_starts_with_lowercase?
- first_char = subject.sub(/\A\[.+\]\s/, '')[0]
+ first_char = subject.sub(/\A(\[.+\]|\w+:)\s/, '')[0]
first_char_downcased = first_char.downcase
return true unless ('a'..'z').cover?(first_char_downcased)
diff --git a/lib/gitlab/danger/helper.rb b/lib/gitlab/danger/helper.rb
index 783a5f1715c..89f21e8bd23 100644
--- a/lib/gitlab/danger/helper.rb
+++ b/lib/gitlab/danger/helper.rb
@@ -168,7 +168,7 @@ module Gitlab
%r{\A(\.gitlab-ci\.yml\z|\.gitlab\/ci)} => :engineering_productivity,
%r{\A\.codeclimate\.yml\z} => :engineering_productivity,
- %r{\A\.overcommit\.yml\.example\z} => :engineering_productivity,
+ %r{\Alefthook.yml\z} => :engineering_productivity,
%r{\A\.editorconfig\z} => :engineering_productivity,
%r{Dangerfile\z} => :engineering_productivity,
%r{\A(ee/)?(danger/|lib/gitlab/danger/)} => :engineering_productivity,
@@ -190,7 +190,7 @@ module Gitlab
%r{\A(ee/)?vendor/} => :backend,
%r{\A(Gemfile|Gemfile.lock|Rakefile)\z} => :backend,
%r{\A[A-Z_]+_VERSION\z} => :backend,
- %r{\A\.rubocop(_todo)?\.yml\z} => :backend,
+ %r{\A\.rubocop((_manual)?_todo)?\.yml\z} => :backend,
%r{\Afile_hooks/} => :backend,
%r{\A(ee/)?qa/} => :qa,
@@ -200,6 +200,9 @@ module Gitlab
%r{\Alocale/gitlab\.pot\z} => :none,
%r{\Adata/whats_new/} => :none,
+ # GraphQL auto generated doc files and schema
+ %r{\Adoc/api/graphql/reference/} => :backend,
+
# Fallbacks in case the above patterns miss anything
%r{\.rb\z} => :backend,
%r{(
diff --git a/lib/gitlab/data_builder/feature_flag.rb b/lib/gitlab/data_builder/feature_flag.rb
new file mode 100644
index 00000000000..2f675ace7e1
--- /dev/null
+++ b/lib/gitlab/data_builder/feature_flag.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module DataBuilder
+ module FeatureFlag
+ extend self
+
+ def build(feature_flag, user)
+ {
+ object_kind: 'feature_flag',
+ project: feature_flag.project.hook_attrs,
+ user: user.hook_attrs,
+ user_url: Gitlab::UrlBuilder.build(user),
+ object_attributes: feature_flag.hook_attrs
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/batch_count.rb b/lib/gitlab/database/batch_count.rb
index 11d9881aac2..6f79e965cd5 100644
--- a/lib/gitlab/database/batch_count.rb
+++ b/lib/gitlab/database/batch_count.rb
@@ -128,9 +128,9 @@ module Gitlab
end
def between_condition(start, finish)
- return @column.between(start..(finish - 1)) if @column.is_a?(Arel::Attributes::Attribute)
+ return @column.between(start...finish) if @column.is_a?(Arel::Attributes::Attribute)
- { @column => start..(finish - 1) }
+ { @column => start...finish }
end
def actual_start(start)
diff --git a/lib/gitlab/database/partitioning/monthly_strategy.rb b/lib/gitlab/database/partitioning/monthly_strategy.rb
index ecc05d9654a..82ea1ce26fb 100644
--- a/lib/gitlab/database/partitioning/monthly_strategy.rb
+++ b/lib/gitlab/database/partitioning/monthly_strategy.rb
@@ -17,23 +17,8 @@ module Gitlab
end
def current_partitions
- result = connection.select_all(<<~SQL)
- select
- pg_class.relname,
- parent_class.relname as base_table,
- pg_get_expr(pg_class.relpartbound, inhrelid) as condition
- from pg_class
- inner join pg_inherits i on pg_class.oid = inhrelid
- inner join pg_class parent_class on parent_class.oid = inhparent
- inner join pg_namespace ON pg_namespace.oid = pg_class.relnamespace
- where pg_namespace.nspname = #{connection.quote(Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)}
- and parent_class.relname = #{connection.quote(table_name)}
- and pg_class.relispartition
- order by pg_class.relname
- SQL
-
- result.map do |record|
- TimePartition.from_sql(table_name, record['relname'], record['condition'])
+ Gitlab::Database::PostgresPartition.for_parent_table(table_name).map do |partition|
+ TimePartition.from_sql(table_name, partition.name, partition.condition)
end
end
diff --git a/lib/gitlab/database/partitioning/replace_table.rb b/lib/gitlab/database/partitioning/replace_table.rb
new file mode 100644
index 00000000000..6f6af223fa2
--- /dev/null
+++ b/lib/gitlab/database/partitioning/replace_table.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Partitioning
+ class ReplaceTable
+ DELIMITER = ";\n\n"
+
+ attr_reader :original_table, :replacement_table, :replaced_table, :primary_key_column,
+ :sequence, :original_primary_key, :replacement_primary_key, :replaced_primary_key
+
+ def initialize(original_table, replacement_table, replaced_table, primary_key_column)
+ @original_table = original_table
+ @replacement_table = replacement_table
+ @replaced_table = replaced_table
+ @primary_key_column = primary_key_column
+
+ @sequence = default_sequence(original_table, primary_key_column)
+ @original_primary_key = default_primary_key(original_table)
+ @replacement_primary_key = default_primary_key(replacement_table)
+ @replaced_primary_key = default_primary_key(replaced_table)
+ end
+
+ def perform
+ yield sql_to_replace_table if block_given?
+
+ execute(sql_to_replace_table)
+ end
+
+ private
+
+ delegate :execute, :quote_table_name, :quote_column_name, to: :connection
+ def connection
+ @connection ||= ActiveRecord::Base.connection
+ end
+
+ def default_sequence(table, column)
+ "#{table}_#{column}_seq"
+ end
+
+ def default_primary_key(table)
+ "#{table}_pkey"
+ end
+
+ def sql_to_replace_table
+ @sql_to_replace_table ||= combined_sql_statements.map(&:chomp).join(DELIMITER)
+ end
+
+ def combined_sql_statements
+ statements = []
+
+ statements << alter_column_default(original_table, primary_key_column, expression: nil)
+ statements << alter_column_default(replacement_table, primary_key_column,
+ expression: "nextval('#{quote_table_name(sequence)}'::regclass)")
+
+ statements << alter_sequence_owned_by(sequence, replacement_table, primary_key_column)
+
+ rename_table_objects(statements, original_table, replaced_table, original_primary_key, replaced_primary_key)
+ rename_table_objects(statements, replacement_table, original_table, replacement_primary_key, original_primary_key)
+
+ statements
+ end
+
+ def rename_table_objects(statements, old_table, new_table, old_primary_key, new_primary_key)
+ statements << rename_table(old_table, new_table)
+ statements << rename_constraint(new_table, old_primary_key, new_primary_key)
+
+ rename_partitions(statements, old_table, new_table)
+ end
+
+ def rename_partitions(statements, old_table_name, new_table_name)
+ Gitlab::Database::PostgresPartition.for_parent_table(old_table_name).each do |partition|
+ new_partition_name = partition.name.sub(/#{old_table_name}/, new_table_name)
+ old_primary_key = default_primary_key(partition.name)
+ new_primary_key = default_primary_key(new_partition_name)
+
+ statements << rename_constraint(partition.identifier, old_primary_key, new_primary_key)
+ statements << rename_table(partition.identifier, new_partition_name)
+ end
+ end
+
+ def alter_column_default(table_name, column_name, expression:)
+ default_clause = expression.nil? ? 'DROP DEFAULT' : "SET DEFAULT #{expression}"
+
+ <<~SQL
+ ALTER TABLE #{quote_table_name(table_name)}
+ ALTER COLUMN #{quote_column_name(column_name)} #{default_clause}
+ SQL
+ end
+
+ def alter_sequence_owned_by(sequence_name, table_name, column_name)
+ <<~SQL
+ ALTER SEQUENCE #{quote_table_name(sequence_name)}
+ OWNED BY #{quote_table_name(table_name)}.#{quote_column_name(column_name)}
+ SQL
+ end
+
+ def rename_table(old_name, new_name)
+ <<~SQL
+ ALTER TABLE #{quote_table_name(old_name)}
+ RENAME TO #{quote_table_name(new_name)}
+ SQL
+ end
+
+ def rename_constraint(table_name, old_name, new_name)
+ <<~SQL
+ ALTER TABLE #{quote_table_name(table_name)}
+ RENAME CONSTRAINT #{quote_column_name(old_name)} TO #{quote_column_name(new_name)}
+ SQL
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/partitioning_migration_helpers.rb b/lib/gitlab/database/partitioning_migration_helpers.rb
index 881177a195e..3196dd20356 100644
--- a/lib/gitlab/database/partitioning_migration_helpers.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers.rb
@@ -5,6 +5,7 @@ module Gitlab
module PartitioningMigrationHelpers
include ForeignKeyHelpers
include TableManagementHelpers
+ include IndexHelpers
end
end
end
diff --git a/lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb b/lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb
new file mode 100644
index 00000000000..f367292f4b0
--- /dev/null
+++ b/lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module PartitioningMigrationHelpers
+ module IndexHelpers
+ include Gitlab::Database::MigrationHelpers
+ include Gitlab::Database::SchemaHelpers
+
+ # Concurrently creates a new index on a partitioned table. In concept this works similarly to
+ # `add_concurrent_index`, and won't block reads or writes on the table while the index is being built.
+ #
+ # A special helper is required for partitioning because Postgres does not support concurrently building indexes
+ # on partitioned tables. This helper concurrently adds the same index to each partition, and creates the final
+ # index on the parent table once all of the partitions are indexed. This is the recommended safe way to add
+ # indexes to partitioned tables.
+ #
+ # Example:
+ #
+ # add_concurrent_partitioned_index :users, :some_column
+ #
+ # See Rails' `add_index` for more info on the available arguments.
+ def add_concurrent_partitioned_index(table_name, column_names, options = {})
+ raise ArgumentError, 'A name is required for indexes added to partitioned tables' unless options[:name]
+
+ partitioned_table = find_partitioned_table(table_name)
+
+ if index_name_exists?(table_name, options[:name])
+ Gitlab::AppLogger.warn "Index not created because it already exists (this may be due to an aborted" \
+ " migration or similar): table_name: #{table_name}, index_name: #{options[:name]}"
+
+ return
+ end
+
+ partitioned_table.postgres_partitions.each do |partition|
+ partition_index_name = generated_index_name(partition.identifier, options[:name])
+ partition_options = options.merge(name: partition_index_name)
+
+ add_concurrent_index(partition.identifier, column_names, partition_options)
+ end
+
+ with_lock_retries do
+ add_index(table_name, column_names, options)
+ end
+ end
+
+ # Safely removes an existing index from a partitioned table. The method name is a bit inaccurate as it does not
+ # drop the index concurrently, but it's named as such to maintain consistency with other similar helpers, and
+ # indicate that this should be safe to use in a production environment.
+ #
+ # In current versions of Postgres it's impossible to drop an index concurrently, or drop an index from an
+ # individual partition that exists across the entire partitioned table. As a result this helper drops the index
+ # from the parent table, which automatically cascades to all partitions. While this does require an exclusive
+ # lock, dropping an index is a fast operation that won't block the table for a significant period of time.
+ #
+ # Example:
+ #
+ # remove_concurrent_partitioned_index_by_name :users, 'index_name_goes_here'
+ def remove_concurrent_partitioned_index_by_name(table_name, index_name)
+ find_partitioned_table(table_name)
+
+ unless index_name_exists?(table_name, index_name)
+ 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
+
+ with_lock_retries do
+ remove_index(table_name, name: index_name)
+ end
+ end
+
+ private
+
+ def find_partitioned_table(table_name)
+ partitioned_table = Gitlab::Database::PostgresPartitionedTable.find_by_name_in_current_schema(table_name)
+
+ raise ArgumentError, "#{table_name} is not a partitioned table" unless partitioned_table
+
+ partitioned_table
+ end
+
+ def generated_index_name(partition_name, index_name)
+ object_name("#{partition_name}_#{index_name}", 'index')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb b/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
index f7b0306b769..686dda80207 100644
--- a/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
@@ -66,7 +66,10 @@ module Gitlab
create_range_partitioned_copy(table_name, partitioned_table_name, partition_column, primary_key)
create_daterange_partitions(partitioned_table_name, partition_column.name, min_date, max_date)
end
- create_trigger_to_sync_tables(table_name, partitioned_table_name, primary_key)
+
+ with_lock_retries do
+ create_trigger_to_sync_tables(table_name, partitioned_table_name, primary_key)
+ end
end
# Clean up a partitioned copy of an existing table. First, deletes the database function and trigger that were
@@ -81,13 +84,9 @@ module Gitlab
assert_not_in_transaction_block(scope: ERROR_SCOPE)
with_lock_retries do
- trigger_name = make_sync_trigger_name(table_name)
- drop_trigger(table_name, trigger_name)
+ drop_sync_trigger(table_name)
end
- function_name = make_sync_function_name(table_name)
- drop_function(function_name)
-
partitioned_table_name = make_partitioned_table_name(table_name)
drop_table(partitioned_table_name)
end
@@ -177,6 +176,53 @@ module Gitlab
end
end
+ # Replaces a non-partitioned table with its partitioned copy. This is the final step in a partitioning
+ # migration, which makes the partitioned table ready for use by the application. The partitioned copy should be
+ # replaced with the original table in such a way that it appears seamless to any database clients. The replaced
+ # table will be renamed to "#{replaced_table}_archived". Partitions and primary key constraints will also be
+ # renamed to match the naming scheme of the parent table.
+ #
+ # **NOTE** This method should only be used after all other migration steps have completed successfully.
+ # There are several limitations to this method that MUST be handled before, or during, the swap migration:
+ #
+ # - Secondary indexes and foreign keys are not automatically recreated on the partitioned table.
+ # - Some types of constraints (UNIQUE and EXCLUDE) which rely on indexes, will not automatically be recreated
+ # on the partitioned table, since the underlying index will not be present.
+ # - Foreign keys referencing the original non-partitioned table, would also need to be updated to reference the
+ # partitioned table, but unfortunately this is not supported in PG11.
+ # - Views referencing the original table will not be automatically updated to reference the partitioned table.
+ #
+ # Example:
+ #
+ # replace_with_partitioned_table :audit_events
+ #
+ def replace_with_partitioned_table(table_name)
+ assert_table_is_allowed(table_name)
+
+ partitioned_table_name = make_partitioned_table_name(table_name)
+ archived_table_name = make_archived_table_name(table_name)
+ primary_key_name = connection.primary_key(table_name)
+
+ replace_table(table_name, partitioned_table_name, archived_table_name, primary_key_name)
+ end
+
+ # Rolls back a migration that replaced a non-partitioned table with its partitioned copy. This can be used to
+ # restore the original non-partitioned table in the event of an unexpected issue.
+ #
+ # Example:
+ #
+ # rollback_replace_with_partitioned_table :audit_events
+ #
+ def rollback_replace_with_partitioned_table(table_name)
+ assert_table_is_allowed(table_name)
+
+ partitioned_table_name = make_partitioned_table_name(table_name)
+ archived_table_name = make_archived_table_name(table_name)
+ primary_key_name = connection.primary_key(archived_table_name)
+
+ replace_table(table_name, archived_table_name, partitioned_table_name, primary_key_name)
+ end
+
private
def assert_table_is_allowed(table_name)
@@ -190,6 +236,10 @@ module Gitlab
tmp_table_name("#{table}_part")
end
+ def make_archived_table_name(table)
+ "#{table}_archived"
+ end
+
def make_sync_function_name(table)
object_name(table, 'table_sync_function')
end
@@ -270,12 +320,18 @@ module Gitlab
function_name = make_sync_function_name(source_table_name)
trigger_name = make_sync_trigger_name(source_table_name)
- with_lock_retries do
- create_sync_function(function_name, partitioned_table_name, unique_key)
- create_comment('FUNCTION', function_name, "Partitioning migration: table sync for #{source_table_name} table")
+ create_sync_function(function_name, partitioned_table_name, unique_key)
+ create_comment('FUNCTION', function_name, "Partitioning migration: table sync for #{source_table_name} table")
- create_sync_trigger(source_table_name, trigger_name, function_name)
- end
+ create_sync_trigger(source_table_name, trigger_name, function_name)
+ end
+
+ def drop_sync_trigger(source_table_name)
+ trigger_name = make_sync_trigger_name(source_table_name)
+ drop_trigger(source_table_name, trigger_name)
+
+ function_name = make_sync_function_name(source_table_name)
+ drop_function(function_name)
end
def create_sync_function(name, partitioned_table_name, unique_key)
@@ -358,6 +414,21 @@ module Gitlab
end
end
end
+
+ def replace_table(original_table_name, replacement_table_name, replaced_table_name, primary_key_name)
+ replace_table = Gitlab::Database::Partitioning::ReplaceTable.new(original_table_name.to_s,
+ replacement_table_name, replaced_table_name, primary_key_name)
+
+ with_lock_retries do
+ drop_sync_trigger(original_table_name)
+
+ replace_table.perform do |sql|
+ say("replace_table(\"#{sql}\")")
+ end
+
+ create_trigger_to_sync_tables(original_table_name, replaced_table_name, primary_key_name)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/database/postgres_partition.rb b/lib/gitlab/database/postgres_partition.rb
new file mode 100644
index 00000000000..0986372586b
--- /dev/null
+++ b/lib/gitlab/database/postgres_partition.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ class PostgresPartition < ActiveRecord::Base
+ self.primary_key = :identifier
+
+ belongs_to :postgres_partitioned_table, foreign_key: 'parent_identifier', primary_key: 'identifier'
+
+ scope :by_identifier, ->(identifier) do
+ raise ArgumentError, "Partition name is not fully qualified with a schema: #{identifier}" unless identifier =~ /^\w+\.\w+$/
+
+ find(identifier)
+ end
+
+ scope :for_parent_table, ->(name) { where("parent_identifier = concat(current_schema(), '.', ?)", name).order(:name) }
+
+ def to_s
+ name
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/postgres_partitioned_table.rb b/lib/gitlab/database/postgres_partitioned_table.rb
new file mode 100644
index 00000000000..5d2eaa22ee4
--- /dev/null
+++ b/lib/gitlab/database/postgres_partitioned_table.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ class PostgresPartitionedTable < ActiveRecord::Base
+ DYNAMIC_PARTITION_STRATEGIES = %w[range list].freeze
+
+ self.primary_key = :identifier
+
+ has_many :postgres_partitions, foreign_key: 'parent_identifier', primary_key: 'identifier'
+
+ scope :by_identifier, ->(identifier) do
+ raise ArgumentError, "Table name is not fully qualified with a schema: #{identifier}" unless identifier =~ /^\w+\.\w+$/
+
+ find(identifier)
+ end
+
+ def self.find_by_name_in_current_schema(name)
+ find_by("identifier = concat(current_schema(), '.', ?)", name)
+ end
+
+ def dynamic?
+ DYNAMIC_PARTITION_STRATEGIES.include?(strategy)
+ end
+
+ def static?
+ !dynamic?
+ end
+
+ def to_s
+ name
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/reindexing.rb b/lib/gitlab/database/reindexing.rb
index 074752fe75b..c77e000254f 100644
--- a/lib/gitlab/database/reindexing.rb
+++ b/lib/gitlab/database/reindexing.rb
@@ -10,6 +10,7 @@ module Gitlab
def self.candidate_indexes
Gitlab::Database::PostgresIndex
.regular
+ .where('NOT expression')
.not_match("^#{ConcurrentReindex::TEMPORARY_INDEX_PREFIX}")
.not_match("^#{ConcurrentReindex::REPLACED_INDEX_PREFIX}")
end
diff --git a/lib/gitlab/dependency_linker/base_linker.rb b/lib/gitlab/dependency_linker/base_linker.rb
index a4e265eba88..d735fb55652 100644
--- a/lib/gitlab/dependency_linker/base_linker.rb
+++ b/lib/gitlab/dependency_linker/base_linker.rb
@@ -6,6 +6,7 @@ module Gitlab
URL_REGEX = %r{https?://[^'" ]+}.freeze
GIT_INVALID_URL_REGEX = /^git\+#{URL_REGEX}/.freeze
REPO_REGEX = %r{[^/'" ]+/[^/'" ]+}.freeze
+ VALID_LINK_ATTRIBUTES = %w[href rel target].freeze
include ActionView::Helpers::SanitizeHelper
@@ -66,7 +67,7 @@ module Gitlab
def link_tag(name, url)
sanitize(
%{<a href="#{ERB::Util.html_escape_once(url)}" rel="nofollow noreferrer noopener" target="_blank">#{ERB::Util.html_escape_once(name)}</a>},
- attributes: %w[href rel target]
+ attributes: VALID_LINK_ATTRIBUTES
)
end
@@ -77,7 +78,7 @@ module Gitlab
# # Will link `user/repo` in `github: "user/repo"` or `:github => "user/repo"`
def link_regex(regex, &url_proc)
highlighted_lines.map!.with_index do |rich_line, i|
- marker = StringRegexMarker.new(plain_lines[i].chomp, rich_line.html_safe)
+ marker = StringRegexMarker.new((plain_lines[i].chomp! || plain_lines[i]), rich_line.html_safe)
marker.mark(regex, group: :name) do |text, left:, right:|
url = yield(text)
diff --git a/lib/gitlab/design_management/copy_design_collection_model_attributes.yml b/lib/gitlab/design_management/copy_design_collection_model_attributes.yml
index 1d341e6520e..95f15bd6dee 100644
--- a/lib/gitlab/design_management/copy_design_collection_model_attributes.yml
+++ b/lib/gitlab/design_management/copy_design_collection_model_attributes.yml
@@ -29,6 +29,7 @@ ignore_design_attributes:
- id
- issue_id
- project_id
+ - iid
ignore_version_attributes:
- id
diff --git a/lib/gitlab/diff/file_collection/merge_request_diff_batch.rb b/lib/gitlab/diff/file_collection/merge_request_diff_batch.rb
index c6d1e0b93a7..9af66318b89 100644
--- a/lib/gitlab/diff/file_collection/merge_request_diff_batch.rb
+++ b/lib/gitlab/diff/file_collection/merge_request_diff_batch.rb
@@ -18,10 +18,8 @@ module Gitlab
def initialize(merge_request_diff, batch_page, batch_size, diff_options:)
super(merge_request_diff, diff_options: diff_options)
- batch_page ||= DEFAULT_BATCH_PAGE
- batch_size ||= DEFAULT_BATCH_SIZE
+ @paginated_collection = load_paginated_collection(batch_page, batch_size, diff_options)
- @paginated_collection = relation.page(batch_page).per(batch_size)
@pagination_data = {
current_page: @paginated_collection.current_page,
next_page: @paginated_collection.next_page,
@@ -63,6 +61,18 @@ module Gitlab
def relation
@merge_request_diff.merge_request_diff_files
end
+
+ def load_paginated_collection(batch_page, batch_size, diff_options)
+ batch_page ||= DEFAULT_BATCH_PAGE
+ batch_size ||= DEFAULT_BATCH_SIZE
+
+ paths = diff_options&.fetch(:paths, nil)
+
+ paginated_collection = relation.page(batch_page).per(batch_size)
+ paginated_collection = paginated_collection.by_paths(paths) if paths
+
+ paginated_collection
+ end
end
end
end
diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb
index 379fc6af875..af9140215f0 100644
--- a/lib/gitlab/diff/line.rb
+++ b/lib/gitlab/diff/line.rb
@@ -8,9 +8,9 @@ module Gitlab
#
SERIALIZE_KEYS = %i(line_code rich_text text type index old_pos new_pos).freeze
- attr_reader :line_code, :type, :old_pos, :new_pos
+ attr_reader :line_code, :old_pos, :new_pos
attr_writer :rich_text
- attr_accessor :text, :index
+ attr_accessor :text, :index, :type
def initialize(text, type, index, old_pos, new_pos, parent_file: nil, line_code: nil, rich_text: nil)
@text, @type, @index = text, type, index
diff --git a/lib/gitlab/error_tracking.rb b/lib/gitlab/error_tracking.rb
index 803acef9a40..a5ace2be773 100644
--- a/lib/gitlab/error_tracking.rb
+++ b/lib/gitlab/error_tracking.rb
@@ -123,6 +123,7 @@ module Gitlab
end
extra = sanitize_request_parameters(extra)
+ inject_sql_query_into_extra(exception, extra)
if sentry && Raven.configuration.server
Raven.capture_exception(exception, tags: default_tags, extra: extra)
@@ -149,6 +150,12 @@ module Gitlab
filter.filter(parameters)
end
+ def inject_sql_query_into_extra(exception, extra)
+ return unless exception.is_a?(ActiveRecord::StatementInvalid)
+
+ extra[:sql] = PgQuery.normalize(exception.sql.to_s)
+ end
+
def sentry_dsn
return unless Rails.env.production? || Rails.env.development?
return unless Gitlab.config.sentry.enabled
diff --git a/lib/gitlab/etag_caching/middleware.rb b/lib/gitlab/etag_caching/middleware.rb
index 303e1a23e6b..fc3c05c57b2 100644
--- a/lib/gitlab/etag_caching/middleware.rb
+++ b/lib/gitlab/etag_caching/middleware.rb
@@ -3,6 +3,14 @@
module Gitlab
module EtagCaching
class Middleware
+ SKIP_HEADER_KEY = 'X-Gitlab-Skip-Etag'
+
+ class << self
+ def skip!(response)
+ response.set_header(SKIP_HEADER_KEY, '1')
+ end
+ end
+
def initialize(app)
@app = app
end
@@ -22,9 +30,7 @@ module Gitlab
else
track_cache_miss(if_none_match, cached_value_present, route)
- status, headers, body = @app.call(env)
- headers['ETag'] = etag
- [status, headers, body]
+ maybe_apply_etag(etag, *@app.call(env))
end
end
@@ -43,6 +49,13 @@ module Gitlab
[weak_etag_format(current_value), cached_value_present]
end
+ def maybe_apply_etag(etag, status, headers, body)
+ headers['ETag'] = etag unless
+ Gitlab::Utils.to_boolean(headers.delete(SKIP_HEADER_KEY))
+
+ [status, headers, body]
+ end
+
def weak_etag_format(value)
%Q{W/"#{value}"}
end
@@ -54,7 +67,13 @@ module Gitlab
add_instrument_for_cache_hit(status_code, route, request)
- [status_code, { 'ETag' => etag, 'X-Gitlab-From-Cache' => 'true' }, []]
+ new_headers = {
+ 'ETag' => etag,
+ 'X-Gitlab-From-Cache' => 'true',
+ ::Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER => route.feature_category
+ }
+
+ [status_code, new_headers, []]
end
def track_cache_miss(if_none_match, cached_value_present, route)
diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb
index 17d9cf08367..769ac2784d1 100644
--- a/lib/gitlab/etag_caching/router.rb
+++ b/lib/gitlab/etag_caching/router.rb
@@ -3,7 +3,7 @@
module Gitlab
module EtagCaching
class Router
- Route = Struct.new(:regexp, :name)
+ Route = Struct.new(:regexp, :name, :feature_category)
# We enable an ETag for every request matching the regex.
# To match a regex the path needs to match the following:
# - Don't contain a reserved word (expect for the words used in the
@@ -20,59 +20,73 @@ module Gitlab
ROUTES = [
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/noteable/issue/\d+/notes\z),
- 'issue_notes'
+ 'issue_notes',
+ 'issue_tracking'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/noteable/merge_request/\d+/notes\z),
- 'merge_request_notes'
+ 'merge_request_notes',
+ 'code_review'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/issues/\d+/realtime_changes\z),
- 'issue_title'
+ 'issue_title',
+ 'issue_tracking'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/commit/\S+/pipelines\.json\z),
- 'commit_pipelines'
+ 'commit_pipelines',
+ 'continuous_integration'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/merge_requests/new\.json\z),
- 'new_merge_request_pipelines'
+ 'new_merge_request_pipelines',
+ 'continuous_integration'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/merge_requests/\d+/pipelines\.json\z),
- 'merge_request_pipelines'
+ 'merge_request_pipelines',
+ 'continuous_integration'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/pipelines\.json\z),
- 'project_pipelines'
+ 'project_pipelines',
+ 'continuous_integration'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/pipelines/\d+\.json\z),
- 'project_pipeline'
+ 'project_pipeline',
+ 'continuous_integration'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/builds/\d+\.json\z),
- 'project_build'
+ 'project_build',
+ 'continuous_integration'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/clusters/\d+/environments\z),
- 'cluster_environments'
+ 'cluster_environments',
+ 'continuous_delivery'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/environments\.json\z),
- 'environments'
+ 'environments',
+ 'continuous_delivery'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/import/github/realtime_changes\.json\z),
- 'realtime_changes_import_github'
+ 'realtime_changes_import_github',
+ 'importers'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/import/gitea/realtime_changes\.json\z),
- 'realtime_changes_import_gitea'
+ 'realtime_changes_import_gitea',
+ 'importers'
),
Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/merge_requests/\d+/cached_widget\.json\z),
- 'merge_request_widget'
+ 'merge_request_widget',
+ 'code_review'
)
].freeze
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb
index 1ce3ffe4c86..6e39776bbd4 100644
--- a/lib/gitlab/experimentation.rb
+++ b/lib/gitlab/experimentation.rb
@@ -6,6 +6,7 @@
# Experiment options:
# - environment (optional, defaults to enabled for development and GitLab.com)
# - tracking_category (optional, used to set the category when tracking an experiment event)
+# - use_backwards_compatible_subject_index (optional, set this to true if you need backwards compatibility)
#
# The experiment is controlled by a Feature Flag (https://docs.gitlab.com/ee/development/feature_flags/controls.html),
# which is named "#{experiment_key}_experiment_percentage" and *must* be set with a percentage and not be used for other purposes.
@@ -30,168 +31,60 @@
module Gitlab
module Experimentation
EXPERIMENTS = {
- signup_flow: {
- tracking_category: 'Growth::Acquisition::Experiment::SignUpFlow'
- },
onboarding_issues: {
- tracking_category: 'Growth::Conversion::Experiment::OnboardingIssues'
- },
- suggest_pipeline: {
- tracking_category: 'Growth::Expansion::Experiment::SuggestPipeline'
+ tracking_category: 'Growth::Conversion::Experiment::OnboardingIssues',
+ use_backwards_compatible_subject_index: true
},
ci_notification_dot: {
- tracking_category: 'Growth::Expansion::Experiment::CiNotificationDot'
+ tracking_category: 'Growth::Expansion::Experiment::CiNotificationDot',
+ use_backwards_compatible_subject_index: true
},
upgrade_link_in_user_menu_a: {
- tracking_category: 'Growth::Expansion::Experiment::UpgradeLinkInUserMenuA'
+ tracking_category: 'Growth::Expansion::Experiment::UpgradeLinkInUserMenuA',
+ use_backwards_compatible_subject_index: true
},
invite_members_version_a: {
- tracking_category: 'Growth::Expansion::Experiment::InviteMembersVersionA'
+ tracking_category: 'Growth::Expansion::Experiment::InviteMembersVersionA',
+ use_backwards_compatible_subject_index: true
},
invite_members_version_b: {
- tracking_category: 'Growth::Expansion::Experiment::InviteMembersVersionB'
+ tracking_category: 'Growth::Expansion::Experiment::InviteMembersVersionB',
+ use_backwards_compatible_subject_index: true
+ },
+ invite_members_empty_group_version_a: {
+ tracking_category: 'Growth::Expansion::Experiment::InviteMembersEmptyGroupVersionA',
+ use_backwards_compatible_subject_index: true
},
new_create_project_ui: {
- tracking_category: 'Manage::Import::Experiment::NewCreateProjectUi'
+ tracking_category: 'Manage::Import::Experiment::NewCreateProjectUi',
+ use_backwards_compatible_subject_index: true
},
contact_sales_btn_in_app: {
- tracking_category: 'Growth::Conversion::Experiment::ContactSalesInApp'
+ tracking_category: 'Growth::Conversion::Experiment::ContactSalesInApp',
+ use_backwards_compatible_subject_index: true
},
customize_homepage: {
- tracking_category: 'Growth::Expansion::Experiment::CustomizeHomepage'
+ tracking_category: 'Growth::Expansion::Experiment::CustomizeHomepage',
+ use_backwards_compatible_subject_index: true
},
invite_email: {
- tracking_category: 'Growth::Acquisition::Experiment::InviteEmail'
+ tracking_category: 'Growth::Acquisition::Experiment::InviteEmail',
+ use_backwards_compatible_subject_index: true
},
invitation_reminders: {
- tracking_category: 'Growth::Acquisition::Experiment::InvitationReminders'
+ tracking_category: 'Growth::Acquisition::Experiment::InvitationReminders',
+ use_backwards_compatible_subject_index: true
},
group_only_trials: {
- tracking_category: 'Growth::Conversion::Experiment::GroupOnlyTrials'
+ tracking_category: 'Growth::Conversion::Experiment::GroupOnlyTrials',
+ use_backwards_compatible_subject_index: true
},
default_to_issues_board: {
- tracking_category: 'Growth::Conversion::Experiment::DefaultToIssuesBoard'
+ tracking_category: 'Growth::Conversion::Experiment::DefaultToIssuesBoard',
+ use_backwards_compatible_subject_index: true
}
}.freeze
- GROUP_CONTROL = :control
- GROUP_EXPERIMENTAL = :experimental
-
- # Controller concern that checks if an `experimentation_subject_id cookie` is present and sets it if absent.
- # Used for A/B testing of experimental features. Exposes the `experiment_enabled?(experiment_name)` method
- # to controllers and views. It returns true when the experiment is enabled and the user is selected as part
- # of the experimental group.
- #
- module ControllerConcern
- extend ActiveSupport::Concern
-
- included do
- before_action :set_experimentation_subject_id_cookie, unless: :dnt_enabled?
- helper_method :experiment_enabled?, :experiment_tracking_category_and_group
- end
-
- def set_experimentation_subject_id_cookie
- return if cookies[:experimentation_subject_id].present?
-
- cookies.permanent.signed[:experimentation_subject_id] = {
- value: SecureRandom.uuid,
- secure: ::Gitlab.config.gitlab.https,
- httponly: true
- }
- end
-
- def push_frontend_experiment(experiment_key)
- var_name = experiment_key.to_s.camelize(:lower)
- enabled = experiment_enabled?(experiment_key)
-
- gon.push({ experiments: { var_name => enabled } }, true)
- end
-
- def experiment_enabled?(experiment_key)
- return false if dnt_enabled?
-
- return true if Experimentation.enabled_for_value?(experiment_key, experimentation_subject_index)
- return true if forced_enabled?(experiment_key)
-
- false
- end
-
- def track_experiment_event(experiment_key, action, value = nil)
- return if dnt_enabled?
-
- track_experiment_event_for(experiment_key, action, value) do |tracking_data|
- ::Gitlab::Tracking.event(tracking_data.delete(:category), tracking_data.delete(:action), **tracking_data)
- end
- end
-
- def frontend_experimentation_tracking_data(experiment_key, action, value = nil)
- return if dnt_enabled?
-
- track_experiment_event_for(experiment_key, action, value) do |tracking_data|
- gon.push(tracking_data: tracking_data)
- end
- end
-
- def record_experiment_user(experiment_key)
- return if dnt_enabled?
- return unless Experimentation.enabled?(experiment_key) && current_user
-
- ::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?
- Gitlab::Utils.to_boolean(request.headers['DNT'])
- end
-
- def experimentation_subject_id
- cookies.signed[:experimentation_subject_id]
- end
-
- def experimentation_subject_index
- return if experimentation_subject_id.blank?
-
- experimentation_subject_id.delete('-').hex % 100
- end
-
- def track_experiment_event_for(experiment_key, action, value)
- return unless Experimentation.enabled?(experiment_key)
-
- yield experimentation_tracking_data(experiment_key, action, value)
- end
-
- def experimentation_tracking_data(experiment_key, action, value)
- {
- category: tracking_category(experiment_key),
- action: action,
- property: tracking_group(experiment_key, "_group"),
- label: experimentation_subject_id,
- value: value
- }.compact
- end
-
- def tracking_category(experiment_key)
- Experimentation.experiment(experiment_key).tracking_category
- end
-
- def tracking_group(experiment_key, suffix = nil)
- return unless Experimentation.enabled?(experiment_key)
-
- group = experiment_enabled?(experiment_key) ? GROUP_EXPERIMENTAL : GROUP_CONTROL
-
- suffix ? "#{group}#{suffix}" : group
- end
-
- def forced_enabled?(experiment_key)
- params.has_key?(:force_experiment) && params[:force_experiment] == experiment_key.to_s
- end
- end
-
class << self
def experiment(key)
Experiment.new(EXPERIMENTS[key].merge(key: key))
@@ -201,7 +94,7 @@ module Gitlab
return false unless EXPERIMENTS.key?(experiment_key)
experiment = experiment(experiment_key)
- experiment.enabled? && experiment.enabled_for_environment?
+ experiment.enabled_for_environment? && experiment.enabled?
end
def enabled_for_attribute?(experiment_key, attribute)
@@ -209,13 +102,18 @@ module Gitlab
enabled_for_value?(experiment_key, index)
end
- def enabled_for_value?(experiment_key, experimentation_subject_index)
- enabled?(experiment_key) &&
- experiment(experiment_key).enabled_for_index?(experimentation_subject_index)
+ def enabled_for_value?(experiment_key, value)
+ enabled?(experiment_key) && experiment(experiment_key).enabled_for_index?(value)
end
end
- Experiment = Struct.new(:key, :environment, :tracking_category, keyword_init: true) do
+ Experiment = Struct.new(
+ :key,
+ :environment,
+ :tracking_category,
+ :use_backwards_compatible_subject_index,
+ keyword_init: true
+ ) do
def enabled?
experiment_percentage > 0
end
diff --git a/lib/gitlab/experimentation/controller_concern.rb b/lib/gitlab/experimentation/controller_concern.rb
new file mode 100644
index 00000000000..c6d15d7d82d
--- /dev/null
+++ b/lib/gitlab/experimentation/controller_concern.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+require 'zlib'
+
+# Controller concern that checks if an `experimentation_subject_id cookie` is present and sets it if absent.
+# Used for A/B testing of experimental features. Exposes the `experiment_enabled?(experiment_name)` method
+# to controllers and views. It returns true when the experiment is enabled and the user is selected as part
+# of the experimental group.
+#
+module Gitlab
+ module Experimentation
+ module ControllerConcern
+ include ::Gitlab::Experimentation::GroupTypes
+ extend ActiveSupport::Concern
+
+ included do
+ before_action :set_experimentation_subject_id_cookie, unless: :dnt_enabled?
+ helper_method :experiment_enabled?, :experiment_tracking_category_and_group
+ end
+
+ def set_experimentation_subject_id_cookie
+ return if cookies[:experimentation_subject_id].present?
+
+ cookies.permanent.signed[:experimentation_subject_id] = {
+ value: SecureRandom.uuid,
+ secure: ::Gitlab.config.gitlab.https,
+ httponly: true
+ }
+ end
+
+ def push_frontend_experiment(experiment_key)
+ var_name = experiment_key.to_s.camelize(:lower)
+ enabled = experiment_enabled?(experiment_key)
+
+ gon.push({ experiments: { var_name => enabled } }, true)
+ end
+
+ def experiment_enabled?(experiment_key)
+ return false if dnt_enabled?
+
+ return true if Experimentation.enabled_for_value?(experiment_key, experimentation_subject_index(experiment_key))
+ return true if forced_enabled?(experiment_key)
+
+ false
+ end
+
+ def track_experiment_event(experiment_key, action, value = nil)
+ return if dnt_enabled?
+
+ track_experiment_event_for(experiment_key, action, value) do |tracking_data|
+ ::Gitlab::Tracking.event(tracking_data.delete(:category), tracking_data.delete(:action), **tracking_data)
+ end
+ end
+
+ def frontend_experimentation_tracking_data(experiment_key, action, value = nil)
+ return if dnt_enabled?
+
+ track_experiment_event_for(experiment_key, action, value) do |tracking_data|
+ gon.push(tracking_data: tracking_data)
+ end
+ end
+
+ def record_experiment_user(experiment_key)
+ return if dnt_enabled?
+ return unless Experimentation.enabled?(experiment_key) && current_user
+
+ ::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?
+ Gitlab::Utils.to_boolean(request.headers['DNT'])
+ end
+
+ def experimentation_subject_id
+ cookies.signed[:experimentation_subject_id]
+ end
+
+ def experimentation_subject_index(experiment_key)
+ return if experimentation_subject_id.blank?
+
+ if Experimentation.experiment(experiment_key).use_backwards_compatible_subject_index
+ experimentation_subject_id.delete('-').hex % 100
+ else
+ Zlib.crc32("#{experiment_key}#{experimentation_subject_id}") % 100
+ end
+ end
+
+ def track_experiment_event_for(experiment_key, action, value)
+ return unless Experimentation.enabled?(experiment_key)
+
+ yield experimentation_tracking_data(experiment_key, action, value)
+ end
+
+ def experimentation_tracking_data(experiment_key, action, value)
+ {
+ category: tracking_category(experiment_key),
+ action: action,
+ property: tracking_group(experiment_key, "_group"),
+ label: experimentation_subject_id,
+ value: value
+ }.compact
+ end
+
+ def tracking_category(experiment_key)
+ Experimentation.experiment(experiment_key).tracking_category
+ end
+
+ def tracking_group(experiment_key, suffix = nil)
+ return unless Experimentation.enabled?(experiment_key)
+
+ group = experiment_enabled?(experiment_key) ? GROUP_EXPERIMENTAL : GROUP_CONTROL
+
+ suffix ? "#{group}#{suffix}" : group
+ end
+
+ def forced_enabled?(experiment_key)
+ params.has_key?(:force_experiment) && params[:force_experiment] == experiment_key.to_s
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/experimentation/group_types.rb b/lib/gitlab/experimentation/group_types.rb
new file mode 100644
index 00000000000..8e8f7284b99
--- /dev/null
+++ b/lib/gitlab/experimentation/group_types.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Experimentation
+ module GroupTypes
+ GROUP_CONTROL = :control
+ GROUP_EXPERIMENTAL = :experimental
+ end
+ end
+end
diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb
index 78c47023c08..209917073c7 100644
--- a/lib/gitlab/git/diff.rb
+++ b/lib/gitlab/git/diff.rb
@@ -25,7 +25,7 @@ module Gitlab
#
# If this value ever changes, make sure to create a migration to update
# current records, and default of `ApplicationSettings#diff_max_patch_bytes`.
- DEFAULT_MAX_PATCH_BYTES = 100.kilobytes
+ DEFAULT_MAX_PATCH_BYTES = 200.kilobytes
# This is a limitation applied on the source (Gitaly), therefore we don't allow
# persisting limits over that.
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 1a3409c1f84..bc712e87e99 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -302,7 +302,7 @@ module Gitlab
private :archive_file_path
def archive_version_path
- return '' unless Feature.enabled?(:include_lfs_blobs_in_archive)
+ return '' unless Feature.enabled?(:include_lfs_blobs_in_archive, default_enabled: true)
'@v2'
end
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 20ad6d0184b..e41a406ebd3 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -26,8 +26,8 @@ module Gitlab
GitalyClient.call(@storage, :repository_service, :cleanup, request, timeout: GitalyClient.fast_timeout)
end
- def garbage_collect(create_bitmap)
- request = Gitaly::GarbageCollectRequest.new(repository: @gitaly_repo, create_bitmap: create_bitmap)
+ def garbage_collect(create_bitmap, prune:)
+ request = Gitaly::GarbageCollectRequest.new(repository: @gitaly_repo, create_bitmap: create_bitmap, prune: prune)
GitalyClient.call(@storage, :repository_service, :garbage_collect, request, timeout: GitalyClient.long_timeout)
end
diff --git a/lib/gitlab/github_import.rb b/lib/gitlab/github_import.rb
index 9a7c406d981..c3cc15e10f7 100644
--- a/lib/gitlab/github_import.rb
+++ b/lib/gitlab/github_import.rb
@@ -6,10 +6,13 @@ module Gitlab
[:heads, :tags, '+refs/pull/*/head:refs/merge-requests/*/head']
end
- def self.new_client_for(project, token: nil, parallel: true)
+ def self.new_client_for(project, token: nil, host: nil, parallel: true)
token_to_use = token || project.import_data&.credentials&.fetch(:user)
-
- Client.new(token_to_use, parallel: parallel)
+ Client.new(
+ token_to_use,
+ host: host.presence || self.formatted_import_url(project),
+ parallel: parallel
+ )
end
# Returns the ID of the ghost user.
@@ -18,5 +21,17 @@ module Gitlab
Gitlab::Cache::Import::Caching.read_integer(key) || Gitlab::Cache::Import::Caching.write(key, User.select(:id).ghost.id)
end
+
+ # Get formatted GitHub import URL. If github.com is in the import URL, this will return nil and octokit will use the default github.com API URL
+ def self.formatted_import_url(project)
+ url = URI.parse(project.import_url)
+
+ unless url.host == 'github.com'
+ url.user = nil
+ url.password = nil
+ url.path = "/api/v3"
+ url.to_s
+ end
+ end
end
end
diff --git a/lib/gitlab/github_import/client.rb b/lib/gitlab/github_import/client.rb
index 22803c5cd71..dfe60fb5a03 100644
--- a/lib/gitlab/github_import/client.rb
+++ b/lib/gitlab/github_import/client.rb
@@ -18,6 +18,8 @@ module Gitlab
attr_reader :octokit
+ SEARCH_MAX_REQUESTS_PER_MINUTE = 30
+
# A single page of data and the corresponding page number.
Page = Struct.new(:objects, :number)
@@ -28,9 +30,12 @@ module Gitlab
# rate limit at once. The threshold is put in place to not hit the limit
# in most cases.
RATE_LIMIT_THRESHOLD = 50
+ SEARCH_RATE_LIMIT_THRESHOLD = 3
# token - The GitHub API token to use.
#
+ # host - The GitHub hostname. If nil, github.com will be used.
+ #
# per_page - The number of objects that should be displayed per page.
#
# parallel - When set to true hitting the rate limit will result in a
@@ -39,11 +44,13 @@ module Gitlab
# this value to `true` for parallel importing is crucial as
# otherwise hitting the rate limit will result in a thread
# being blocked in a `sleep()` call for up to an hour.
- def initialize(token, per_page: 100, parallel: true)
+ def initialize(token, host: nil, per_page: 100, parallel: true)
+ @host = host
@octokit = ::Octokit::Client.new(
access_token: token,
per_page: per_page,
- api_endpoint: api_endpoint
+ api_endpoint: api_endpoint,
+ web_endpoint: web_endpoint
)
@octokit.connection_options[:ssl] = { verify: verify_ssl }
@@ -148,8 +155,26 @@ module Gitlab
end
end
+ def search_repos_by_name(name)
+ each_page(:search_repositories, search_query(str: name, type: :name))
+ end
+
+ def search_query(str:, type:, include_collaborations: true, include_orgs: true)
+ query = "#{str} in:#{type} is:public,private user:#{octokit.user.login}"
+
+ query = [query, collaborations_subquery].join(' ') if include_collaborations
+ query = [query, organizations_subquery].join(' ') if include_orgs
+
+ query
+ end
+
# Returns `true` if we're still allowed to perform API calls.
+ # Search API has rate limit of 30, use lowered threshold when search is used.
def requests_remaining?
+ if requests_limit == SEARCH_MAX_REQUESTS_PER_MINUTE
+ return remaining_requests > SEARCH_RATE_LIMIT_THRESHOLD
+ end
+
remaining_requests > RATE_LIMIT_THRESHOLD
end
@@ -157,6 +182,10 @@ module Gitlab
octokit.rate_limit.remaining
end
+ def requests_limit
+ octokit.rate_limit.limit
+ end
+
def raise_or_wait_for_rate_limit
rate_limit_counter.increment
@@ -181,7 +210,11 @@ module Gitlab
end
def api_endpoint
- custom_api_endpoint || default_api_endpoint
+ @host || custom_api_endpoint || default_api_endpoint
+ end
+
+ def web_endpoint
+ @host || custom_api_endpoint || ::Octokit::Default.web_endpoint
end
def custom_api_endpoint
@@ -213,6 +246,20 @@ module Gitlab
'The number of GitHub API calls performed when importing projects'
)
end
+
+ private
+
+ def collaborations_subquery
+ each_object(:repos, nil, { affiliation: 'collaborator' })
+ .map { |repo| "repo:#{repo.full_name}" }
+ .join(' ')
+ end
+
+ def organizations_subquery
+ each_object(:organizations)
+ .map { |org| "org:#{org.login}" }
+ .join(' ')
+ end
end
end
end
diff --git a/lib/gitlab/github_import/sequential_importer.rb b/lib/gitlab/github_import/sequential_importer.rb
index 6a181caf65d..cb6b2017208 100644
--- a/lib/gitlab/github_import/sequential_importer.rb
+++ b/lib/gitlab/github_import/sequential_importer.rb
@@ -25,10 +25,11 @@ module Gitlab
# project - The project to import the data into.
# token - The token to use for the GitHub API.
- def initialize(project, token: nil)
+ # host - The GitHub hostname. If nil, github.com will be used.
+ def initialize(project, token: nil, host: nil)
@project = project
@client = GithubImport
- .new_client_for(project, token: token, parallel: false)
+ .new_client_for(project, token: token, host: host, parallel: false)
end
def execute
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index 10660649623..2d41ad76618 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -28,6 +28,7 @@ module Gitlab
gon.sprite_icons = IconsHelper.sprite_icon_path
gon.sprite_file_icons = IconsHelper.sprite_file_icons_path
gon.emoji_sprites_css_path = ActionController::Base.helpers.stylesheet_path('emoji_sprites')
+ gon.select2_css_path = ActionController::Base.helpers.stylesheet_path('lazy_bundles/select2.css')
gon.test_env = Rails.env.test?
gon.disable_animations = Gitlab.config.gitlab['disable_animations']
gon.suggested_label_colors = LabelsHelper.suggested_colors
@@ -58,9 +59,13 @@ module Gitlab
# args - Any additional arguments to pass to `Feature.enabled?`. This allows
# you to check if a flag is enabled for a particular user.
def push_frontend_feature_flag(name, *args, **kwargs)
- var_name = name.to_s.camelize(:lower)
enabled = Feature.enabled?(name, *args, **kwargs)
+ push_to_gon_features(name, enabled)
+ end
+
+ def push_to_gon_features(name, enabled)
+ var_name = name.to_s.camelize(:lower)
# Here the `true` argument signals gon that the value should be merged
# into any existing ones, instead of overwriting them. This allows you to
# use this method to push multiple feature flags.
diff --git a/lib/gitlab/grape_logging/formatters/lograge_with_timestamp.rb b/lib/gitlab/grape_logging/formatters/lograge_with_timestamp.rb
index ac149cadb5b..a0dccbcdab3 100644
--- a/lib/gitlab/grape_logging/formatters/lograge_with_timestamp.rb
+++ b/lib/gitlab/grape_logging/formatters/lograge_with_timestamp.rb
@@ -41,6 +41,8 @@ module Gitlab
data.map! { |v| utf8_encode_values(v) }
when String
encode_utf8(data)
+ when Integer
+ data
end
end
end
diff --git a/lib/gitlab/grape_logging/loggers/content_logger.rb b/lib/gitlab/grape_logging/loggers/content_logger.rb
new file mode 100644
index 00000000000..658953adc80
--- /dev/null
+++ b/lib/gitlab/grape_logging/loggers/content_logger.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GrapeLogging
+ module Loggers
+ class ContentLogger < ::GrapeLogging::Loggers::Base
+ def parameters(request, _)
+ {
+ content_length: request.env['CONTENT_LENGTH'],
+ content_range: request.env['HTTP_CONTENT_RANGE']
+ }.compact
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/authorize/authorize_field_service.rb b/lib/gitlab/graphql/authorize/authorize_field_service.rb
index cbf3e7b8429..e8db619f88a 100644
--- a/lib/gitlab/graphql/authorize/authorize_field_service.rb
+++ b/lib/gitlab/graphql/authorize/authorize_field_service.rb
@@ -46,6 +46,8 @@ module Gitlab
# Returns any authorize metadata from @field
def field_authorizations
+ return [] if @field.metadata[:authorize] == true
+
Array.wrap(@field.metadata[:authorize])
end
@@ -54,7 +56,7 @@ module Gitlab
# The field is a built-in/scalar type, or a list of scalars
# authorize using the parent's object
parent_typed_object.object
- elsif @field.connection? || resolved_type.is_a?(Array)
+ elsif @field.connection? || @field.type.list? || resolved_type.is_a?(Array)
# The field is a connection or a list of non-built-in types, we'll
# authorize each element when rendering
nil
@@ -75,16 +77,25 @@ module Gitlab
# no need to do anything
elsif authorizing_object
# Authorizing fields representing scalars, or a simple field with an object
- resolved_type if allowed_access?(current_user, authorizing_object)
+ ::Gitlab::Graphql::Lazy.with_value(authorizing_object) do |object|
+ resolved_type if allowed_access?(current_user, object)
+ end
elsif @field.connection?
- # A connection with pagination, modify the visible nodes on the
- # connection type in place
- resolved_type.object.edge_nodes.to_a.keep_if { |node| allowed_access?(current_user, node) }
- resolved_type
- elsif resolved_type.is_a? Array
+ ::Gitlab::Graphql::Lazy.with_value(resolved_type) do |type|
+ # A connection with pagination, modify the visible nodes on the
+ # connection type in place
+ nodes = to_nodes(type)
+ nodes.keep_if { |node| allowed_access?(current_user, node) } if nodes
+ type
+ end
+ elsif @field.type.list? || resolved_type.is_a?(Array)
# A simple list of rendered types each object being an object to authorize
- resolved_type.select do |single_object_type|
- allowed_access?(current_user, realized(single_object_type).object)
+ ::Gitlab::Graphql::Lazy.with_value(resolved_type) do |items|
+ items.select do |single_object_type|
+ object_type = realized(single_object_type)
+ object = object_type.try(:object) || object_type
+ allowed_access?(current_user, object)
+ end
end
else
raise "Can't authorize #{@field}"
@@ -93,18 +104,23 @@ module Gitlab
# Ensure that we are dealing with realized objects, not delayed promises
def realized(thing)
- case thing
- when BatchLoader::GraphQL
- thing.sync
- when GraphQL::Execution::Lazy
- thing.value # part of the private api, but we need to unwrap it here.
+ ::Gitlab::Graphql::Lazy.force(thing)
+ end
+
+ # Try to get the connection
+ # can be at type.object or at type
+ def to_nodes(type)
+ if type.respond_to?(:nodes)
+ type.nodes
+ elsif type.respond_to?(:object)
+ to_nodes(type.object)
else
- thing
+ nil
end
end
def allowed_access?(current_user, object)
- object = object.sync if object.respond_to?(:sync)
+ object = realized(object)
authorizations.all? do |ability|
Ability.allowed?(current_user, ability, object)
diff --git a/lib/gitlab/graphql/docs/helper.rb b/lib/gitlab/graphql/docs/helper.rb
index dcd0e12cbfc..503b1064b11 100644
--- a/lib/gitlab/graphql/docs/helper.rb
+++ b/lib/gitlab/graphql/docs/helper.rb
@@ -81,11 +81,15 @@ module Gitlab
# We are ignoring connections and built in types for now,
# they should be added when queries are generated.
def objects
- graphql_object_types.select do |object_type|
+ object_types = graphql_object_types.select do |object_type|
!object_type[:name]["Connection"] &&
!object_type[:name]["Edge"] &&
!object_type[:name]["__"]
end
+
+ object_types.each do |type|
+ type[:fields] += type[:connections]
+ end
end
# We ignore the built-in enum types.
diff --git a/lib/gitlab/graphql/docs/templates/default.md.haml b/lib/gitlab/graphql/docs/templates/default.md.haml
index ec052943589..97df4233905 100644
--- a/lib/gitlab/graphql/docs/templates/default.md.haml
+++ b/lib/gitlab/graphql/docs/templates/default.md.haml
@@ -14,6 +14,8 @@
CAUTION: **Caution:**
Fields that are deprecated are marked with **{warning-solid}**.
+ Items (fields, enums, etc) that have been removed according to our [deprecation process](../index.md#deprecation-process) can be found
+ in [Removed Items](../removed_items.md).
\
:plain
diff --git a/lib/gitlab/graphql/lazy.rb b/lib/gitlab/graphql/lazy.rb
index a7f7610a041..3cc11047387 100644
--- a/lib/gitlab/graphql/lazy.rb
+++ b/lib/gitlab/graphql/lazy.rb
@@ -3,17 +3,41 @@
module Gitlab
module Graphql
class Lazy
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(&block)
+ @proc = block
+ end
+
+ def force
+ strong_memoize(:force) { self.class.force(@proc.call) }
+ end
+
+ def then(&block)
+ self.class.new { yield force }
+ end
+
# Force evaluation of a (possibly) lazy value
def self.force(value)
case value
+ when ::Gitlab::Graphql::Lazy
+ value.force
when ::BatchLoader::GraphQL
value.sync
+ when ::GraphQL::Execution::Lazy
+ value.value # part of the private api, but we can force this as well
when ::Concurrent::Promise
- value.execute.value
+ value.execute if value.state == :unscheduled
+
+ value.value # value.value(10.seconds)
else
value
end
end
+
+ def self.with_value(unforced, &block)
+ self.new { unforced }.then(&block)
+ end
end
end
end
diff --git a/lib/gitlab/graphql/loaders/batch_model_loader.rb b/lib/gitlab/graphql/loaders/batch_model_loader.rb
index 164fe74148c..9b85ba164d4 100644
--- a/lib/gitlab/graphql/loaders/batch_model_loader.rb
+++ b/lib/gitlab/graphql/loaders/batch_model_loader.rb
@@ -12,14 +12,11 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def find
- BatchLoader::GraphQL.for({ model: model_class, id: model_id.to_i }).batch do |loader_info, loader|
- per_model = loader_info.group_by { |info| info[:model] }
- per_model.each do |model, info|
- ids = info.map { |i| i[:id] }
- results = model.where(id: ids)
+ BatchLoader::GraphQL.for(model_id.to_i).batch(key: model_class) do |ids, loader, args|
+ model = args[:key]
+ results = model.where(id: ids)
- results.each { |record| loader.call({ model: model, id: record.id }, record) }
- end
+ results.each { |record| loader.call(record.id, record) }
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/graphql/present/instrumentation.rb b/lib/gitlab/graphql/present/instrumentation.rb
index 941a4f434a1..b8535575da5 100644
--- a/lib/gitlab/graphql/present/instrumentation.rb
+++ b/lib/gitlab/graphql/present/instrumentation.rb
@@ -4,6 +4,8 @@ module Gitlab
module Graphql
module Present
class Instrumentation
+ SAFE_CONTEXT_KEYS = %i[current_user].freeze
+
def instrument(type, field)
return field unless field.metadata[:type_class]
@@ -22,7 +24,8 @@ module Gitlab
next old_resolver.call(presented_type, args, context)
end
- presenter = presented_in.presenter_class.new(object, **context.to_h)
+ attrs = safe_context_values(context)
+ presenter = presented_in.presenter_class.new(object, **attrs)
# we have to use the new `authorized_new` method, as `new` is protected
wrapped = presented_type.class.authorized_new(presenter, context)
@@ -34,6 +37,12 @@ module Gitlab
resolve(resolve_with_presenter)
end
end
+
+ private
+
+ def safe_context_values(context)
+ context.to_h.slice(*SAFE_CONTEXT_KEYS)
+ end
end
end
end
diff --git a/lib/gitlab/group_search_results.rb b/lib/gitlab/group_search_results.rb
index 5fec50eecd2..dd872caee0e 100644
--- a/lib/gitlab/group_search_results.rb
+++ b/lib/gitlab/group_search_results.rb
@@ -4,10 +4,10 @@ module Gitlab
class GroupSearchResults < SearchResults
attr_reader :group
- def initialize(current_user, query, limit_projects = nil, group:, default_project_filter: false, sort: nil, filters: {})
+ def initialize(current_user, query, limit_projects = nil, group:, default_project_filter: false, order_by: nil, sort: nil, filters: {})
@group = group
- super(current_user, query, limit_projects, default_project_filter: default_project_filter, sort: sort, filters: filters)
+ super(current_user, query, limit_projects, default_project_filter: default_project_filter, order_by: order_by, sort: sort, filters: filters)
end
# rubocop:disable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/hook_data/release_builder.rb b/lib/gitlab/hook_data/release_builder.rb
new file mode 100644
index 00000000000..b15c260f4a8
--- /dev/null
+++ b/lib/gitlab/hook_data/release_builder.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module HookData
+ class ReleaseBuilder < BaseBuilder
+ def self.safe_hook_attributes
+ %i[
+ id
+ created_at
+ description
+ name
+ released_at
+ tag
+ ].freeze
+ end
+
+ alias_method :release, :object
+
+ def build(action)
+ attrs = {
+ object_kind: object_kind,
+ project: release.project.hook_attrs,
+ description: absolute_image_urls(release.description),
+ url: Gitlab::UrlBuilder.build(release),
+ action: action,
+ assets: {
+ count: release.assets_count,
+ links: release.links.map(&:hook_attrs),
+ sources: release.sources.map(&:hook_attrs)
+ },
+ commit: release.commit.hook_attrs
+ }
+
+ release.attributes.with_indifferent_access.slice(*self.class.safe_hook_attributes)
+ .merge!(attrs)
+ end
+
+ private
+
+ def object_kind
+ release.class.name.underscore
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/i18n/po_linter.rb b/lib/gitlab/i18n/po_linter.rb
index e56b88dfce0..33054a5b9bf 100644
--- a/lib/gitlab/i18n/po_linter.rb
+++ b/lib/gitlab/i18n/po_linter.rb
@@ -24,7 +24,9 @@ module Gitlab
return 'PO-syntax errors' => [parse_error]
end
- validate_entries
+ Gitlab::I18n.with_locale(locale) do
+ validate_entries
+ end
end
def parse_po
@@ -156,12 +158,10 @@ module Gitlab
end
def validate_translation(errors, entry)
- Gitlab::I18n.with_locale(locale) do
- if entry.has_plural?
- translate_plural(entry)
- else
- translate_singular(entry)
- end
+ if entry.has_plural?
+ translate_plural(entry)
+ else
+ translate_singular(entry)
end
# `sprintf` could raise an `ArgumentError` when invalid passing something
@@ -230,9 +230,7 @@ module Gitlab
# This calls the C function that defines the pluralization rule, it can
# return a boolean (`false` represents 0, `true` represents 1) or an integer
# that specifies the plural form to be used for the given number
- pluralization_result = Gitlab::I18n.with_locale(locale) do
- FastGettext.pluralisation_rule.call(counter)
- end
+ pluralization_result = FastGettext.pluralisation_rule.call(counter)
case pluralization_result
when false
diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb
index 7b8689069d8..8e78f6e274a 100644
--- a/lib/gitlab/import_export/importer.rb
+++ b/lib/gitlab/import_export/importer.rb
@@ -55,9 +55,17 @@ module Gitlab
end
def project_tree
- @project_tree ||= Gitlab::ImportExport::Project::TreeRestorer.new(user: current_user,
- shared: shared,
- project: project)
+ @project_tree ||= project_tree_class.new(user: current_user,
+ shared: shared,
+ project: project)
+ end
+
+ def project_tree_class
+ sample_data_template? ? Gitlab::ImportExport::Project::Sample::TreeRestorer : Gitlab::ImportExport::Project::TreeRestorer
+ end
+
+ def sample_data_template?
+ project&.import_data&.data&.dig('sample_data')
end
def avatar_restorer
diff --git a/lib/gitlab/import_export/json/ndjson_reader.rb b/lib/gitlab/import_export/json/ndjson_reader.rb
index 0d9839b86cf..5c8edd485e5 100644
--- a/lib/gitlab/import_export/json/ndjson_reader.rb
+++ b/lib/gitlab/import_export/json/ndjson_reader.rb
@@ -29,9 +29,9 @@ module Gitlab
json_decode(data)
end
- def consume_relation(importable_path, key)
+ def consume_relation(importable_path, key, mark_as_consumed: true)
Enumerator.new do |documents|
- next unless @consumed_relations.add?("#{importable_path}/#{key}")
+ next if mark_as_consumed && !@consumed_relations.add?("#{importable_path}/#{key}")
# This reads from `tree/project/merge_requests.ndjson`
path = file_path(importable_path, "#{key}.ndjson")
@@ -44,11 +44,6 @@ module Gitlab
end
end
- # TODO: Move clear logic into main comsume_relation method (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41699#note_430465330)
- def clear_consumed_relations
- @consumed_relations.clear
- end
-
private
def json_decode(string)
diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml
index a0526ba0414..ae7ddbc5eba 100644
--- a/lib/gitlab/import_export/project/import_export.yml
+++ b/lib/gitlab/import_export/project/import_export.yml
@@ -185,6 +185,7 @@ excluded_attributes:
- :secret
- :encrypted_secret_token
- :encrypted_secret_token_iv
+ - :repository_read_only
merge_request_diff:
- :external_diff
- :stored_externally
@@ -410,8 +411,25 @@ ee:
- :deploy_access_levels
- :service_desk_setting
- :security_setting
+ - :push_rule
included_attributes:
issuable_sla:
- :issue
- :due_at
+ push_rule:
+ - :force_push_regex
+ - :delete_branch_regex
+ - :commit_message_regex
+ - :author_email_regex
+ - :file_name_regex
+ - :branch_name_regex
+ - :commit_message_negative_regex
+ - :max_file_size
+ - :deny_delete_tag
+ - :member_check
+ - :is_sample
+ - :prevent_secrets
+ - :reject_unsigned_commits
+ - :commit_committer_check
+ - :regexp_uses_re2
diff --git a/lib/gitlab/import_export/project/sample/date_calculator.rb b/lib/gitlab/import_export/project/sample/date_calculator.rb
index 2d989d21166..543fd25d883 100644
--- a/lib/gitlab/import_export/project/sample/date_calculator.rb
+++ b/lib/gitlab/import_export/project/sample/date_calculator.rb
@@ -9,7 +9,6 @@ module Gitlab
def initialize(dates)
@dates = dates.dup
- @dates.flatten!
@dates.compact!
@dates.sort!
@dates.map! { |date| date.to_time.to_f }
diff --git a/lib/gitlab/import_export/project/sample/relation_factory.rb b/lib/gitlab/import_export/project/sample/relation_factory.rb
new file mode 100644
index 00000000000..6e59174f9a3
--- /dev/null
+++ b/lib/gitlab/import_export/project/sample/relation_factory.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ImportExport
+ module Project
+ module Sample
+ class RelationFactory < Project::RelationFactory
+ DATE_MODELS = %i[issues milestones].freeze
+
+ def initialize(date_calculator:, **args)
+ super(**args)
+
+ @date_calculator = date_calculator
+ end
+
+ private
+
+ def setup_models
+ super
+
+ # Override due date attributes in data hash for Sample Data templates
+ # Dates are moved by taking the closest one to average and moving that (and rest around it) to the date of import
+ override_date_attributes
+ end
+
+ def override_date_attributes
+ return unless DATE_MODELS.include?(@relation_name)
+
+ @relation_hash['start_date'] = calculate_by_closest_date(@relation_hash['start_date']&.to_time)
+ @relation_hash['due_date'] = calculate_by_closest_date(@relation_hash['due_date']&.to_time)
+ end
+
+ def calculate_by_closest_date(date)
+ return unless date
+
+ @date_calculator.calculate_by_closest_date_to_average(date)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/project/sample/relation_tree_restorer.rb b/lib/gitlab/import_export/project/sample/relation_tree_restorer.rb
new file mode 100644
index 00000000000..44ccb67a531
--- /dev/null
+++ b/lib/gitlab/import_export/project/sample/relation_tree_restorer.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ImportExport
+ module Project
+ module Sample
+ class RelationTreeRestorer < ImportExport::RelationTreeRestorer
+ def initialize(*args)
+ super
+
+ @date_calculator = Gitlab::ImportExport::Project::Sample::DateCalculator.new(dates)
+ end
+
+ private
+
+ def relation_factory_params(*args)
+ super.merge(date_calculator: @date_calculator)
+ end
+
+ def dates
+ return [] if relation_reader.legacy?
+
+ RelationFactory::DATE_MODELS.flat_map do |tag|
+ relation_reader.consume_relation(@importable_path, tag, mark_as_consumed: false).map do |model|
+ model.first['due_date']
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/project/sample/sample_data_relation_tree_restorer.rb b/lib/gitlab/import_export/project/sample/sample_data_relation_tree_restorer.rb
deleted file mode 100644
index b0c3940b5f9..00000000000
--- a/lib/gitlab/import_export/project/sample/sample_data_relation_tree_restorer.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module ImportExport
- module Project
- module Sample
- class SampleDataRelationTreeRestorer < RelationTreeRestorer
- DATE_MODELS = %i[issues milestones].freeze
-
- def initialize(*args)
- super
-
- date_calculator
- end
-
- private
-
- def build_relation(relation_key, relation_definition, data_hash)
- # Override due date attributes in data hash for Sample Data templates
- # Dates are moved by taking the closest one to average and moving that (and rest around it) to the date of import
- # TODO: To move this logic to RelationFactory (see: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41699#note_430465333)
- override_date_attributes!(relation_key, data_hash)
- super
- end
-
- def override_date_attributes!(relation_key, data_hash)
- return unless DATE_MODELS.include?(relation_key.to_sym)
-
- data_hash['start_date'] = date_calculator.calculate_by_closest_date_to_average(data_hash['start_date'].to_time) unless data_hash['start_date'].nil?
- data_hash['due_date'] = date_calculator.calculate_by_closest_date_to_average(data_hash['due_date'].to_time) unless data_hash['due_date'].nil?
- end
-
- # TODO: Move clear logic into main comsume_relation method (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41699#note_430465330)
- def dates
- unless relation_reader.legacy?
- DATE_MODELS.map do |tag|
- relation_reader.consume_relation(@importable_path, tag).map { |model| model.first['due_date'] }.tap do
- relation_reader.clear_consumed_relations
- end
- end
- end
- end
-
- def date_calculator
- @date_calculator ||= Gitlab::ImportExport::Project::Sample::DateCalculator.new(dates)
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/import_export/project/sample/tree_restorer.rb b/lib/gitlab/import_export/project/sample/tree_restorer.rb
new file mode 100644
index 00000000000..1d4b5328cb9
--- /dev/null
+++ b/lib/gitlab/import_export/project/sample/tree_restorer.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ImportExport
+ module Project
+ module Sample
+ class TreeRestorer < Project::TreeRestorer
+ def relation_tree_restorer_class
+ RelationTreeRestorer
+ end
+
+ def relation_factory
+ RelationFactory
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/project/tree_restorer.rb b/lib/gitlab/import_export/project/tree_restorer.rb
index b1d647281ab..fb9e5be1877 100644
--- a/lib/gitlab/import_export/project/tree_restorer.rb
+++ b/lib/gitlab/import_export/project/tree_restorer.rb
@@ -85,11 +85,7 @@ module Gitlab
end
def relation_tree_restorer_class
- sample_data_template? ? Sample::SampleDataRelationTreeRestorer : RelationTreeRestorer
- end
-
- def sample_data_template?
- @project&.import_data&.data&.dig('sample_data')
+ RelationTreeRestorer
end
def members_mapper
diff --git a/lib/gitlab/import_export/uploads_manager.rb b/lib/gitlab/import_export/uploads_manager.rb
index 26e7d2cf765..428bcbe8dc5 100644
--- a/lib/gitlab/import_export/uploads_manager.rb
+++ b/lib/gitlab/import_export/uploads_manager.rb
@@ -86,6 +86,10 @@ module Gitlab
mkdir_p(File.join(uploads_export_path, secret))
download_or_copy_upload(upload, upload_path)
+ rescue Errno::ENAMETOOLONG => e
+ # Do not fail entire project export if downloaded file has filename that exceeds 255 characters.
+ # Ignore raised exception, skip such upload, log the error and keep going with the export instead.
+ Gitlab::ErrorTracking.log_exception(e, project_id: @project.id)
end
end
end
diff --git a/lib/gitlab/instrumentation/throttle.rb b/lib/gitlab/instrumentation/throttle.rb
new file mode 100644
index 00000000000..0b7e990fb2e
--- /dev/null
+++ b/lib/gitlab/instrumentation/throttle.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Instrumentation
+ class Throttle
+ KEY = :instrumentation_throttle_safelist
+
+ def self.safelist
+ Gitlab::SafeRequestStore[KEY]
+ end
+
+ def self.safelist=(name)
+ Gitlab::SafeRequestStore[KEY] = name
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/instrumentation_helper.rb b/lib/gitlab/instrumentation_helper.rb
index 3a29d2e7efa..d7228099eaf 100644
--- a/lib/gitlab/instrumentation_helper.rb
+++ b/lib/gitlab/instrumentation_helper.rb
@@ -21,6 +21,7 @@ module Gitlab
instrument_rugged(payload)
instrument_redis(payload)
instrument_elasticsearch(payload)
+ instrument_throttle(payload)
end
def instrument_gitaly(payload)
@@ -56,6 +57,11 @@ module Gitlab
payload[:elasticsearch_duration_s] = Gitlab::Instrumentation::ElasticsearchTransport.query_time
end
+ def instrument_throttle(payload)
+ safelist = Gitlab::Instrumentation::Throttle.safelist
+ payload[:throttle_safelist] = safelist if safelist.present?
+ end
+
# Returns the queuing duration for a Sidekiq job in seconds, as a float, if the
# `enqueued_at` field or `created_at` field is available.
#
diff --git a/lib/gitlab/json.rb b/lib/gitlab/json.rb
index 29cfec443e8..8565f664cd4 100644
--- a/lib/gitlab/json.rb
+++ b/lib/gitlab/json.rb
@@ -67,15 +67,6 @@ module Gitlab
::JSON.pretty_generate(object, opts)
end
- # Feature detection for using Oj instead of the `json` gem.
- #
- # @return [Boolean]
- def enable_oj?
- return false unless feature_table_exists?
-
- Feature.enabled?(:oj_json, default_enabled: true)
- end
-
private
# Convert JSON string into Ruby through toggleable adapters.
@@ -91,11 +82,7 @@ module Gitlab
def adapter_load(string, *args, **opts)
opts = standardize_opts(opts)
- if enable_oj?
- Oj.load(string, opts)
- else
- ::JSON.parse(string, opts)
- end
+ Oj.load(string, opts)
rescue Oj::ParseError, Encoding::UndefinedConversionError => ex
raise parser_error.new(ex)
end
@@ -120,11 +107,7 @@ module Gitlab
#
# @return [String]
def adapter_dump(object, *args, **opts)
- if enable_oj?
- Oj.dump(object, opts)
- else
- ::JSON.dump(object, *args)
- end
+ Oj.dump(object, opts)
end
# Generates JSON for an object but with fewer options, using toggleable adapters.
@@ -135,11 +118,7 @@ module Gitlab
def adapter_generate(object, opts = {})
opts = standardize_opts(opts)
- if enable_oj?
- Oj.generate(object, opts)
- else
- ::JSON.generate(object, opts)
- end
+ Oj.generate(object, opts)
end
# Take a JSON standard options hash and standardize it to work across adapters
@@ -149,11 +128,8 @@ module Gitlab
# @return [Hash]
def standardize_opts(opts)
opts ||= {}
-
- if enable_oj?
- opts[:mode] = :rails
- opts[:symbol_keys] = opts[:symbolize_keys] || opts[:symbolize_names]
- end
+ opts[:mode] = :rails
+ opts[:symbol_keys] = opts[:symbolize_keys] || opts[:symbolize_names]
opts
end
@@ -213,7 +189,7 @@ module Gitlab
# @param object [Object]
# @return [String]
def self.call(object, env = nil)
- if Gitlab::Json.enable_oj? && Feature.enabled?(:grape_gitlab_json, default_enabled: true)
+ if Feature.enabled?(:grape_gitlab_json, default_enabled: true)
Gitlab::Json.dump(object)
else
Grape::Formatter::Json.call(object, env)
diff --git a/lib/gitlab/kubernetes/helm/base_command.rb b/lib/gitlab/kubernetes/helm/base_command.rb
deleted file mode 100644
index 49d2969f7f3..00000000000
--- a/lib/gitlab/kubernetes/helm/base_command.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Kubernetes
- module Helm
- class BaseCommand
- attr_reader :name, :files
-
- def initialize(rbac:, name:, files:)
- @rbac = rbac
- @name = name
- @files = files
- end
-
- def rbac?
- @rbac
- end
-
- def pod_resource
- pod_service_account_name = rbac? ? service_account_name : nil
-
- Gitlab::Kubernetes::Helm::Pod.new(self, namespace, service_account_name: pod_service_account_name).generate
- end
-
- def generate_script
- <<~HEREDOC
- set -xeo pipefail
- HEREDOC
- end
-
- def pod_name
- "install-#{name}"
- end
-
- def config_map_resource
- Gitlab::Kubernetes::ConfigMap.new(name, files).generate
- end
-
- def service_account_resource
- return unless rbac?
-
- Gitlab::Kubernetes::ServiceAccount.new(service_account_name, namespace).generate
- end
-
- def cluster_role_binding_resource
- return unless rbac?
-
- subjects = [{ kind: 'ServiceAccount', name: service_account_name, namespace: namespace }]
-
- Gitlab::Kubernetes::ClusterRoleBinding.new(
- cluster_role_binding_name,
- cluster_role_name,
- subjects
- ).generate
- end
-
- def file_names
- files.keys
- end
-
- private
-
- def files_dir
- "/data/helm/#{name}/config"
- end
-
- def namespace
- Gitlab::Kubernetes::Helm::NAMESPACE
- end
-
- def service_account_name
- Gitlab::Kubernetes::Helm::SERVICE_ACCOUNT
- end
-
- def cluster_role_binding_name
- Gitlab::Kubernetes::Helm::CLUSTER_ROLE_BINDING
- end
-
- def cluster_role_name
- Gitlab::Kubernetes::Helm::CLUSTER_ROLE
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/kubernetes/helm/certificate.rb b/lib/gitlab/kubernetes/helm/certificate.rb
deleted file mode 100644
index 598714e0874..00000000000
--- a/lib/gitlab/kubernetes/helm/certificate.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-module Gitlab
- module Kubernetes
- module Helm
- class Certificate
- INFINITE_EXPIRY = 1000.years
- SHORT_EXPIRY = 30.minutes
-
- attr_reader :key, :cert
-
- def key_string
- @key.to_s
- end
-
- def cert_string
- @cert.to_pem
- end
-
- def self.from_strings(key_string, cert_string)
- key = OpenSSL::PKey::RSA.new(key_string)
- cert = OpenSSL::X509::Certificate.new(cert_string)
- new(key, cert)
- end
-
- def self.generate_root
- _issue(signed_by: nil, expires_in: INFINITE_EXPIRY, certificate_authority: true)
- end
-
- def issue(expires_in: SHORT_EXPIRY)
- self.class._issue(signed_by: self, expires_in: expires_in, certificate_authority: false)
- end
-
- private
-
- def self._issue(signed_by:, expires_in:, certificate_authority:)
- key = OpenSSL::PKey::RSA.new(4096)
- public_key = key.public_key
-
- subject = OpenSSL::X509::Name.parse("/C=US")
-
- cert = OpenSSL::X509::Certificate.new
- cert.subject = subject
-
- cert.issuer = signed_by&.cert&.subject || subject
-
- cert.not_before = Time.now
- cert.not_after = expires_in.from_now
- cert.public_key = public_key
- cert.serial = 0x0
- cert.version = 2
-
- if certificate_authority
- extension_factory = OpenSSL::X509::ExtensionFactory.new
- extension_factory.subject_certificate = cert
- extension_factory.issuer_certificate = cert
- cert.add_extension(extension_factory.create_extension('subjectKeyIdentifier', 'hash'))
- cert.add_extension(extension_factory.create_extension('basicConstraints', 'CA:TRUE', true))
- cert.add_extension(extension_factory.create_extension('keyUsage', 'cRLSign,keyCertSign', true))
- end
-
- cert.sign(signed_by&.key || key, OpenSSL::Digest::SHA256.new)
-
- new(key, cert)
- end
-
- def initialize(key, cert)
- @key = key
- @cert = cert
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/kubernetes/helm/client_command.rb b/lib/gitlab/kubernetes/helm/client_command.rb
deleted file mode 100644
index a9e93c0c90e..00000000000
--- a/lib/gitlab/kubernetes/helm/client_command.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Kubernetes
- module Helm
- module ClientCommand
- def init_command
- <<~SHELL.chomp
- export HELM_HOST="localhost:44134"
- tiller -listen ${HELM_HOST} -alsologtostderr &
- helm init --client-only
- SHELL
- end
-
- def repository_command
- ['helm', 'repo', 'add', name, repository].shelljoin if repository
- end
-
- private
-
- def repository_update_command
- 'helm repo update'
- end
-
- def optional_tls_flags
- return [] unless files.key?(:'ca.pem')
-
- [
- '--tls',
- '--tls-ca-cert', "#{files_dir}/ca.pem",
- '--tls-cert', "#{files_dir}/cert.pem",
- '--tls-key', "#{files_dir}/key.pem"
- ]
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/kubernetes/helm/delete_command.rb b/lib/gitlab/kubernetes/helm/delete_command.rb
deleted file mode 100644
index f8b9601bc98..00000000000
--- a/lib/gitlab/kubernetes/helm/delete_command.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Kubernetes
- module Helm
- class DeleteCommand < BaseCommand
- include ClientCommand
-
- attr_reader :predelete, :postdelete
-
- def initialize(predelete: nil, postdelete: nil, **args)
- super(**args)
- @predelete = predelete
- @postdelete = postdelete
- end
-
- def generate_script
- super + [
- init_command,
- predelete,
- delete_command,
- postdelete
- ].compact.join("\n")
- end
-
- def pod_name
- "uninstall-#{name}"
- end
-
- def delete_command
- ['helm', 'delete', '--purge', name].shelljoin
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/kubernetes/helm/init_command.rb b/lib/gitlab/kubernetes/helm/init_command.rb
deleted file mode 100644
index e4844e255c5..00000000000
--- a/lib/gitlab/kubernetes/helm/init_command.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Kubernetes
- module Helm
- class InitCommand < BaseCommand
- def generate_script
- super + [
- init_helm_command
- ].join("\n")
- end
-
- private
-
- def init_helm_command
- command = %w[helm init] + init_command_flags
-
- command.shelljoin
- end
-
- def init_command_flags
- tls_flags + optional_service_account_flag
- end
-
- def tls_flags
- [
- '--tiller-tls',
- '--tiller-tls-verify',
- '--tls-ca-cert', "#{files_dir}/ca.pem",
- '--tiller-tls-cert', "#{files_dir}/cert.pem",
- '--tiller-tls-key', "#{files_dir}/key.pem"
- ]
- end
-
- def optional_service_account_flag
- return [] unless rbac?
-
- ['--service-account', service_account_name]
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/kubernetes/helm/install_command.rb b/lib/gitlab/kubernetes/helm/install_command.rb
deleted file mode 100644
index d166842fce6..00000000000
--- a/lib/gitlab/kubernetes/helm/install_command.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Kubernetes
- module Helm
- class InstallCommand < BaseCommand
- include ClientCommand
-
- attr_reader :chart, :repository, :preinstall, :postinstall
- attr_accessor :version
-
- def initialize(chart:, version: nil, repository: nil, preinstall: nil, postinstall: nil, **args)
- super(**args)
- @chart = chart
- @version = version
- @repository = repository
- @preinstall = preinstall
- @postinstall = postinstall
- end
-
- def generate_script
- super + [
- init_command,
- repository_command,
- repository_update_command,
- preinstall,
- install_command,
- postinstall
- ].compact.join("\n")
- end
-
- private
-
- # Uses `helm upgrade --install` which means we can use this for both
- # installation and uprade of applications
- def install_command
- command = ['helm', 'upgrade', name, chart] +
- install_flag +
- rollback_support_flag +
- reset_values_flag +
- optional_version_flag +
- rbac_create_flag +
- namespace_flag +
- value_flag
-
- command.shelljoin
- end
-
- def install_flag
- ['--install']
- end
-
- def reset_values_flag
- ['--reset-values']
- end
-
- def value_flag
- ['-f', "/data/helm/#{name}/config/values.yaml"]
- end
-
- def namespace_flag
- ['--namespace', Gitlab::Kubernetes::Helm::NAMESPACE]
- end
-
- def rbac_create_flag
- if rbac?
- %w[--set rbac.create=true,rbac.enabled=true]
- else
- %w[--set rbac.create=false,rbac.enabled=false]
- end
- end
-
- def optional_version_flag
- return [] unless version
-
- ['--version', version]
- end
-
- def rollback_support_flag
- ['--atomic', '--cleanup-on-fail']
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/kubernetes/helm/patch_command.rb b/lib/gitlab/kubernetes/helm/patch_command.rb
deleted file mode 100644
index a33dbdac134..00000000000
--- a/lib/gitlab/kubernetes/helm/patch_command.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-# PatchCommand is for updating values in installed charts without overwriting
-# existing values.
-module Gitlab
- module Kubernetes
- module Helm
- class PatchCommand < BaseCommand
- include ClientCommand
-
- attr_reader :chart, :repository
- attr_accessor :version
-
- def initialize(chart:, version:, repository: nil, **args)
- super(**args)
-
- # version is mandatory to prevent chart mismatches
- # we do not want our values interpreted in the context of the wrong version
- raise ArgumentError, 'version is required' if version.blank?
-
- @chart = chart
- @version = version
- @repository = repository
- end
-
- def generate_script
- super + [
- init_command,
- repository_command,
- repository_update_command,
- upgrade_command
- ].compact.join("\n")
- end
-
- private
-
- def upgrade_command
- command = ['helm', 'upgrade', name, chart] +
- reuse_values_flag +
- version_flag +
- namespace_flag +
- value_flag
-
- command.shelljoin
- end
-
- def reuse_values_flag
- ['--reuse-values']
- end
-
- def value_flag
- ['-f', "/data/helm/#{name}/config/values.yaml"]
- end
-
- def namespace_flag
- ['--namespace', Gitlab::Kubernetes::Helm::NAMESPACE]
- end
-
- def version_flag
- ['--version', version]
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/kubernetes/helm/pod.rb b/lib/gitlab/kubernetes/helm/pod.rb
index 75484f80070..9d0207e6b1f 100644
--- a/lib/gitlab/kubernetes/helm/pod.rb
+++ b/lib/gitlab/kubernetes/helm/pod.rb
@@ -27,7 +27,7 @@ module Gitlab
def container_specification
{
name: 'helm',
- image: "registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/#{Gitlab::Kubernetes::Helm::HELM_VERSION}-kube-#{Gitlab::Kubernetes::Helm::KUBECTL_VERSION}",
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/#{command.class::HELM_VERSION}-kube-#{Gitlab::Kubernetes::Helm::KUBECTL_VERSION}-alpine-3.12",
env: generate_pod_env(command),
command: %w(/bin/sh),
args: %w(-c $(COMMAND_SCRIPT))
@@ -50,11 +50,10 @@ module Gitlab
end
def generate_pod_env(command)
- {
- HELM_VERSION: Gitlab::Kubernetes::Helm::HELM_VERSION,
- TILLER_NAMESPACE: namespace_name,
+ command.env.merge(
+ HELM_VERSION: command.class::HELM_VERSION,
COMMAND_SCRIPT: command.generate_script
- }.map { |key, value| { name: key, value: value } }
+ ).map { |key, value| { name: key, value: value } }
end
def volumes_specification
diff --git a/lib/gitlab/kubernetes/helm/reset_command.rb b/lib/gitlab/kubernetes/helm/reset_command.rb
deleted file mode 100644
index f1f7938039c..00000000000
--- a/lib/gitlab/kubernetes/helm/reset_command.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Kubernetes
- module Helm
- class ResetCommand < BaseCommand
- include ClientCommand
-
- def generate_script
- super + [
- reset_helm_command,
- delete_tiller_replicaset,
- delete_tiller_clusterrolebinding
- ].join("\n")
- end
-
- def pod_name
- "uninstall-#{name}"
- end
-
- private
-
- # This method can be delete once we upgrade Helm to > 12.13.0
- # https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/27096#note_159695900
- #
- # Tracking this method to be removed here:
- # https://gitlab.com/gitlab-org/gitlab-foss/issues/52791#note_199374155
- def delete_tiller_replicaset
- delete_args = %w[replicaset -n gitlab-managed-apps -l name=tiller]
-
- Gitlab::Kubernetes::KubectlCmd.delete(*delete_args)
- end
-
- def delete_tiller_clusterrolebinding
- delete_args = %w[clusterrolebinding tiller-admin]
-
- Gitlab::Kubernetes::KubectlCmd.delete(*delete_args)
- end
-
- def reset_helm_command
- command = %w[helm reset] + optional_tls_flags
-
- command.shelljoin
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/kubernetes/helm/v2/base_command.rb b/lib/gitlab/kubernetes/helm/v2/base_command.rb
new file mode 100644
index 00000000000..931c2248310
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/v2/base_command.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ module Helm
+ module V2
+ class BaseCommand
+ attr_reader :name, :files
+
+ HELM_VERSION = '2.16.9'
+
+ def initialize(rbac:, name:, files:)
+ @rbac = rbac
+ @name = name
+ @files = files
+ end
+
+ def env
+ { TILLER_NAMESPACE: namespace }
+ end
+
+ def rbac?
+ @rbac
+ end
+
+ def pod_resource
+ pod_service_account_name = rbac? ? service_account_name : nil
+
+ Gitlab::Kubernetes::Helm::Pod.new(self, namespace, service_account_name: pod_service_account_name).generate
+ end
+
+ def generate_script
+ <<~HEREDOC
+ set -xeo pipefail
+ HEREDOC
+ end
+
+ def pod_name
+ "install-#{name}"
+ end
+
+ def config_map_resource
+ Gitlab::Kubernetes::ConfigMap.new(name, files).generate
+ end
+
+ def service_account_resource
+ return unless rbac?
+
+ Gitlab::Kubernetes::ServiceAccount.new(service_account_name, namespace).generate
+ end
+
+ def cluster_role_binding_resource
+ return unless rbac?
+
+ subjects = [{ kind: 'ServiceAccount', name: service_account_name, namespace: namespace }]
+
+ Gitlab::Kubernetes::ClusterRoleBinding.new(
+ cluster_role_binding_name,
+ cluster_role_name,
+ subjects
+ ).generate
+ end
+
+ def file_names
+ files.keys
+ end
+
+ private
+
+ def files_dir
+ "/data/helm/#{name}/config"
+ end
+
+ def namespace
+ Gitlab::Kubernetes::Helm::NAMESPACE
+ end
+
+ def service_account_name
+ Gitlab::Kubernetes::Helm::SERVICE_ACCOUNT
+ end
+
+ def cluster_role_binding_name
+ Gitlab::Kubernetes::Helm::CLUSTER_ROLE_BINDING
+ end
+
+ def cluster_role_name
+ Gitlab::Kubernetes::Helm::CLUSTER_ROLE
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/v2/certificate.rb b/lib/gitlab/kubernetes/helm/v2/certificate.rb
new file mode 100644
index 00000000000..f603ff44ef3
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/v2/certificate.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+module Gitlab
+ module Kubernetes
+ module Helm
+ module V2
+ class Certificate
+ INFINITE_EXPIRY = 1000.years
+ SHORT_EXPIRY = 30.minutes
+
+ attr_reader :key, :cert
+
+ def key_string
+ @key.to_s
+ end
+
+ def cert_string
+ @cert.to_pem
+ end
+
+ def self.from_strings(key_string, cert_string)
+ key = OpenSSL::PKey::RSA.new(key_string)
+ cert = OpenSSL::X509::Certificate.new(cert_string)
+ new(key, cert)
+ end
+
+ def self.generate_root
+ _issue(signed_by: nil, expires_in: INFINITE_EXPIRY, certificate_authority: true)
+ end
+
+ def issue(expires_in: SHORT_EXPIRY)
+ self.class._issue(signed_by: self, expires_in: expires_in, certificate_authority: false)
+ end
+
+ private
+
+ def self._issue(signed_by:, expires_in:, certificate_authority:)
+ key = OpenSSL::PKey::RSA.new(4096)
+ public_key = key.public_key
+
+ subject = OpenSSL::X509::Name.parse("/C=US")
+
+ cert = OpenSSL::X509::Certificate.new
+ cert.subject = subject
+
+ cert.issuer = signed_by&.cert&.subject || subject
+
+ cert.not_before = Time.now.utc
+ cert.not_after = expires_in.from_now.utc
+ cert.public_key = public_key
+ cert.serial = 0x0
+ cert.version = 2
+
+ if certificate_authority
+ extension_factory = OpenSSL::X509::ExtensionFactory.new
+ extension_factory.subject_certificate = cert
+ extension_factory.issuer_certificate = cert
+ cert.add_extension(extension_factory.create_extension('subjectKeyIdentifier', 'hash'))
+ cert.add_extension(extension_factory.create_extension('basicConstraints', 'CA:TRUE', true))
+ cert.add_extension(extension_factory.create_extension('keyUsage', 'cRLSign,keyCertSign', true))
+ end
+
+ cert.sign(signed_by&.key || key, OpenSSL::Digest::SHA256.new)
+
+ new(key, cert)
+ end
+
+ def initialize(key, cert)
+ @key = key
+ @cert = cert
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/v2/client_command.rb b/lib/gitlab/kubernetes/helm/v2/client_command.rb
new file mode 100644
index 00000000000..88693a28d6c
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/v2/client_command.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ module Helm
+ module V2
+ module ClientCommand
+ def init_command
+ <<~SHELL.chomp
+ export HELM_HOST="localhost:44134"
+ tiller -listen ${HELM_HOST} -alsologtostderr &
+ helm init --client-only
+ SHELL
+ end
+
+ def repository_command
+ ['helm', 'repo', 'add', name, repository].shelljoin if repository
+ end
+
+ private
+
+ def repository_update_command
+ 'helm repo update'
+ end
+
+ def optional_tls_flags
+ return [] unless files.key?(:'ca.pem')
+
+ [
+ '--tls',
+ '--tls-ca-cert', "#{files_dir}/ca.pem",
+ '--tls-cert', "#{files_dir}/cert.pem",
+ '--tls-key', "#{files_dir}/key.pem"
+ ]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/v2/delete_command.rb b/lib/gitlab/kubernetes/helm/v2/delete_command.rb
new file mode 100644
index 00000000000..4d52fc1398f
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/v2/delete_command.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ module Helm
+ module V2
+ class DeleteCommand < BaseCommand
+ include ClientCommand
+
+ attr_reader :predelete, :postdelete
+
+ def initialize(predelete: nil, postdelete: nil, **args)
+ super(**args)
+ @predelete = predelete
+ @postdelete = postdelete
+ end
+
+ def generate_script
+ super + [
+ init_command,
+ predelete,
+ delete_command,
+ postdelete
+ ].compact.join("\n")
+ end
+
+ def pod_name
+ "uninstall-#{name}"
+ end
+
+ def delete_command
+ ['helm', 'delete', '--purge', name].shelljoin
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/v2/init_command.rb b/lib/gitlab/kubernetes/helm/v2/init_command.rb
new file mode 100644
index 00000000000..f8b52feb5b6
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/v2/init_command.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ module Helm
+ module V2
+ class InitCommand < BaseCommand
+ def generate_script
+ super + [
+ init_helm_command
+ ].join("\n")
+ end
+
+ private
+
+ def init_helm_command
+ command = %w[helm init] + init_command_flags
+
+ command.shelljoin
+ end
+
+ def init_command_flags
+ tls_flags + optional_service_account_flag
+ end
+
+ def tls_flags
+ [
+ '--tiller-tls',
+ '--tiller-tls-verify',
+ '--tls-ca-cert', "#{files_dir}/ca.pem",
+ '--tiller-tls-cert', "#{files_dir}/cert.pem",
+ '--tiller-tls-key', "#{files_dir}/key.pem"
+ ]
+ end
+
+ def optional_service_account_flag
+ return [] unless rbac?
+
+ ['--service-account', service_account_name]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/v2/install_command.rb b/lib/gitlab/kubernetes/helm/v2/install_command.rb
new file mode 100644
index 00000000000..10e16723e45
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/v2/install_command.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ module Helm
+ module V2
+ class InstallCommand < BaseCommand
+ include ClientCommand
+
+ attr_reader :chart, :repository, :preinstall, :postinstall
+ attr_accessor :version
+
+ def initialize(chart:, version: nil, repository: nil, preinstall: nil, postinstall: nil, **args)
+ super(**args)
+ @chart = chart
+ @version = version
+ @repository = repository
+ @preinstall = preinstall
+ @postinstall = postinstall
+ end
+
+ def generate_script
+ super + [
+ init_command,
+ repository_command,
+ repository_update_command,
+ preinstall,
+ install_command,
+ postinstall
+ ].compact.join("\n")
+ end
+
+ private
+
+ # Uses `helm upgrade --install` which means we can use this for both
+ # installation and uprade of applications
+ def install_command
+ command = ['helm', 'upgrade', name, chart] +
+ install_flag +
+ rollback_support_flag +
+ reset_values_flag +
+ optional_version_flag +
+ rbac_create_flag +
+ namespace_flag +
+ value_flag
+
+ command.shelljoin
+ end
+
+ def install_flag
+ ['--install']
+ end
+
+ def reset_values_flag
+ ['--reset-values']
+ end
+
+ def value_flag
+ ['-f', "/data/helm/#{name}/config/values.yaml"]
+ end
+
+ def namespace_flag
+ ['--namespace', Gitlab::Kubernetes::Helm::NAMESPACE]
+ end
+
+ def rbac_create_flag
+ if rbac?
+ %w[--set rbac.create=true,rbac.enabled=true]
+ else
+ %w[--set rbac.create=false,rbac.enabled=false]
+ end
+ end
+
+ def optional_version_flag
+ return [] unless version
+
+ ['--version', version]
+ end
+
+ def rollback_support_flag
+ ['--atomic', '--cleanup-on-fail']
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/v2/patch_command.rb b/lib/gitlab/kubernetes/helm/v2/patch_command.rb
new file mode 100644
index 00000000000..2855e6444b1
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/v2/patch_command.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+# PatchCommand is for updating values in installed charts without overwriting
+# existing values.
+module Gitlab
+ module Kubernetes
+ module Helm
+ module V2
+ class PatchCommand < BaseCommand
+ include ClientCommand
+
+ attr_reader :chart, :repository
+ attr_accessor :version
+
+ def initialize(chart:, version:, repository: nil, **args)
+ super(**args)
+
+ # version is mandatory to prevent chart mismatches
+ # we do not want our values interpreted in the context of the wrong version
+ raise ArgumentError, 'version is required' if version.blank?
+
+ @chart = chart
+ @version = version
+ @repository = repository
+ end
+
+ def generate_script
+ super + [
+ init_command,
+ repository_command,
+ repository_update_command,
+ upgrade_command
+ ].compact.join("\n")
+ end
+
+ private
+
+ def upgrade_command
+ command = ['helm', 'upgrade', name, chart] +
+ reuse_values_flag +
+ version_flag +
+ namespace_flag +
+ value_flag
+
+ command.shelljoin
+ end
+
+ def reuse_values_flag
+ ['--reuse-values']
+ end
+
+ def value_flag
+ ['-f', "/data/helm/#{name}/config/values.yaml"]
+ end
+
+ def namespace_flag
+ ['--namespace', Gitlab::Kubernetes::Helm::NAMESPACE]
+ end
+
+ def version_flag
+ ['--version', version]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/v2/reset_command.rb b/lib/gitlab/kubernetes/helm/v2/reset_command.rb
new file mode 100644
index 00000000000..172a0884c49
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/v2/reset_command.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ module Helm
+ module V2
+ class ResetCommand < BaseCommand
+ include ClientCommand
+
+ def generate_script
+ super + [
+ reset_helm_command,
+ delete_tiller_replicaset,
+ delete_tiller_clusterrolebinding
+ ].join("\n")
+ end
+
+ def pod_name
+ "uninstall-#{name}"
+ end
+
+ private
+
+ # This method can be delete once we upgrade Helm to > 12.13.0
+ # https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/27096#note_159695900
+ #
+ # Tracking this method to be removed here:
+ # https://gitlab.com/gitlab-org/gitlab-foss/issues/52791#note_199374155
+ def delete_tiller_replicaset
+ delete_args = %w[replicaset -n gitlab-managed-apps -l name=tiller]
+
+ Gitlab::Kubernetes::KubectlCmd.delete(*delete_args)
+ end
+
+ def delete_tiller_clusterrolebinding
+ delete_args = %w[clusterrolebinding tiller-admin]
+
+ Gitlab::Kubernetes::KubectlCmd.delete(*delete_args)
+ end
+
+ def reset_helm_command
+ command = %w[helm reset] + optional_tls_flags
+
+ command.shelljoin
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/v3/base_command.rb b/lib/gitlab/kubernetes/helm/v3/base_command.rb
new file mode 100644
index 00000000000..ca1bf5462f0
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/v3/base_command.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ module Helm
+ module V3
+ class BaseCommand
+ attr_reader :name, :files
+
+ HELM_VERSION = '3.2.4'
+
+ def initialize(rbac:, name:, files:)
+ @rbac = rbac
+ @name = name
+ @files = files
+ end
+
+ def env
+ {}
+ end
+
+ def rbac?
+ @rbac
+ end
+
+ def pod_resource
+ pod_service_account_name = rbac? ? service_account_name : nil
+
+ Gitlab::Kubernetes::Helm::Pod.new(self, namespace, service_account_name: pod_service_account_name).generate
+ end
+
+ def generate_script
+ <<~HEREDOC
+ set -xeo pipefail
+ HEREDOC
+ end
+
+ def pod_name
+ "install-#{name}"
+ end
+
+ def config_map_resource
+ Gitlab::Kubernetes::ConfigMap.new(name, files).generate
+ end
+
+ def service_account_resource
+ return unless rbac?
+
+ Gitlab::Kubernetes::ServiceAccount.new(service_account_name, namespace).generate
+ end
+
+ def cluster_role_binding_resource
+ return unless rbac?
+
+ subjects = [{ kind: 'ServiceAccount', name: service_account_name, namespace: namespace }]
+
+ Gitlab::Kubernetes::ClusterRoleBinding.new(
+ cluster_role_binding_name,
+ cluster_role_name,
+ subjects
+ ).generate
+ end
+
+ def file_names
+ files.keys
+ end
+
+ def repository_command
+ ['helm', 'repo', 'add', name, repository].shelljoin if repository
+ end
+
+ private
+
+ def repository_update_command
+ 'helm repo update'
+ end
+
+ def namespace_flag
+ ['--namespace', Gitlab::Kubernetes::Helm::NAMESPACE]
+ end
+
+ def namespace
+ Gitlab::Kubernetes::Helm::NAMESPACE
+ end
+
+ def service_account_name
+ Gitlab::Kubernetes::Helm::SERVICE_ACCOUNT
+ end
+
+ def cluster_role_binding_name
+ Gitlab::Kubernetes::Helm::CLUSTER_ROLE_BINDING
+ end
+
+ def cluster_role_name
+ Gitlab::Kubernetes::Helm::CLUSTER_ROLE
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/v3/delete_command.rb b/lib/gitlab/kubernetes/helm/v3/delete_command.rb
new file mode 100644
index 00000000000..f628e852f54
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/v3/delete_command.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ module Helm
+ module V3
+ class DeleteCommand < BaseCommand
+ attr_reader :predelete, :postdelete
+
+ def initialize(predelete: nil, postdelete: nil, **args)
+ super(**args)
+ @predelete = predelete
+ @postdelete = postdelete
+ end
+
+ def generate_script
+ super + [
+ predelete,
+ delete_command,
+ postdelete
+ ].compact.join("\n")
+ end
+
+ def pod_name
+ "uninstall-#{name}"
+ end
+
+ def delete_command
+ ['helm', 'uninstall', name, *namespace_flag].shelljoin
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/v3/install_command.rb b/lib/gitlab/kubernetes/helm/v3/install_command.rb
new file mode 100644
index 00000000000..20d17f49115
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/v3/install_command.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ module Helm
+ module V3
+ class InstallCommand < BaseCommand
+ attr_reader :chart, :repository, :preinstall, :postinstall
+ attr_accessor :version
+
+ def initialize(chart:, version: nil, repository: nil, preinstall: nil, postinstall: nil, **args)
+ super(**args)
+ @chart = chart
+ @version = version
+ @repository = repository
+ @preinstall = preinstall
+ @postinstall = postinstall
+ end
+
+ def generate_script
+ super + [
+ repository_command,
+ repository_update_command,
+ preinstall,
+ install_command,
+ postinstall
+ ].compact.join("\n")
+ end
+
+ private
+
+ # Uses `helm upgrade --install` which means we can use this for both
+ # installation and uprade of applications
+ def install_command
+ command = ['helm', 'upgrade', name, chart] +
+ install_flag +
+ rollback_support_flag +
+ reset_values_flag +
+ optional_version_flag +
+ rbac_create_flag +
+ namespace_flag +
+ value_flag
+
+ command.shelljoin
+ end
+
+ def install_flag
+ ['--install']
+ end
+
+ def reset_values_flag
+ ['--reset-values']
+ end
+
+ def value_flag
+ ['-f', "/data/helm/#{name}/config/values.yaml"]
+ end
+
+ def rbac_create_flag
+ if rbac?
+ %w[--set rbac.create=true,rbac.enabled=true]
+ else
+ %w[--set rbac.create=false,rbac.enabled=false]
+ end
+ end
+
+ def optional_version_flag
+ return [] unless version
+
+ ['--version', version]
+ end
+
+ def rollback_support_flag
+ ['--atomic', '--cleanup-on-fail']
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/v3/patch_command.rb b/lib/gitlab/kubernetes/helm/v3/patch_command.rb
new file mode 100644
index 00000000000..00f340591e7
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/v3/patch_command.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+# PatchCommand is for updating values in installed charts without overwriting
+# existing values.
+module Gitlab
+ module Kubernetes
+ module Helm
+ module V3
+ class PatchCommand < BaseCommand
+ attr_reader :chart, :repository
+ attr_accessor :version
+
+ def initialize(chart:, version:, repository: nil, **args)
+ super(**args)
+
+ # version is mandatory to prevent chart mismatches
+ # we do not want our values interpreted in the context of the wrong version
+ raise ArgumentError, 'version is required' if version.blank?
+
+ @chart = chart
+ @version = version
+ @repository = repository
+ end
+
+ def generate_script
+ super + [
+ repository_command,
+ repository_update_command,
+ upgrade_command
+ ].compact.join("\n")
+ end
+
+ private
+
+ def upgrade_command
+ command = ['helm', 'upgrade', name, chart] +
+ reuse_values_flag +
+ version_flag +
+ namespace_flag +
+ value_flag
+
+ command.shelljoin
+ end
+
+ def reuse_values_flag
+ ['--reuse-values']
+ end
+
+ def value_flag
+ ['-f', "/data/helm/#{name}/config/values.yaml"]
+ end
+
+ def version_flag
+ ['--version', version]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/kube_client.rb b/lib/gitlab/kubernetes/kube_client.rb
index 13cd6dcad3f..a25f005d81e 100644
--- a/lib/gitlab/kubernetes/kube_client.rb
+++ b/lib/gitlab/kubernetes/kube_client.rb
@@ -61,18 +61,11 @@ module Gitlab
# RBAC methods delegates to the apis/rbac.authorization.k8s.io api
# group client
delegate :update_cluster_role_binding,
- to: :rbac_client
-
- # RBAC methods delegates to the apis/rbac.authorization.k8s.io api
- # group client
- delegate :create_role,
- :get_role,
- :update_role,
- to: :rbac_client
-
- # RBAC methods delegates to the apis/rbac.authorization.k8s.io api
- # group client
- delegate :update_role_binding,
+ :create_role,
+ :get_role,
+ :update_role,
+ :delete_role_binding,
+ :update_role_binding,
to: :rbac_client
# non-entity methods that can only work with the core client
@@ -182,10 +175,21 @@ module Gitlab
end
end
+ def patch_ingress(*args)
+ extensions_client.discover unless extensions_client.discovered
+
+ if extensions_client.respond_to?(:patch_ingress)
+ extensions_client.patch_ingress(*args)
+ else
+ networking_client.patch_ingress(*args)
+ end
+ end
+
def create_or_update_cluster_role_binding(resource)
update_cluster_role_binding(resource)
end
+ # Note that we cannot update roleRef as that is immutable
def create_or_update_role_binding(resource)
update_role_binding(resource)
end
diff --git a/lib/gitlab/legacy_github_import/client.rb b/lib/gitlab/legacy_github_import/client.rb
index f7eaafeb446..4482610523e 100644
--- a/lib/gitlab/legacy_github_import/client.rb
+++ b/lib/gitlab/legacy_github_import/client.rb
@@ -24,6 +24,7 @@ module Gitlab
@api ||= ::Octokit::Client.new(
access_token: access_token,
api_endpoint: api_endpoint,
+ web_endpoint: web_endpoint,
# If there is no config, we're connecting to github.com and we
# should verify ssl.
connection_options: {
@@ -85,6 +86,10 @@ module Gitlab
end
end
+ def web_endpoint
+ host.presence || ::Octokit::Default.web_endpoint
+ end
+
def config
Gitlab::Auth::OAuth::Provider.config_for('github')
end
diff --git a/lib/gitlab/legacy_github_import/importer.rb b/lib/gitlab/legacy_github_import/importer.rb
index 3f9fd1b1a19..a17e3b1ad5c 100644
--- a/lib/gitlab/legacy_github_import/importer.rb
+++ b/lib/gitlab/legacy_github_import/importer.rb
@@ -36,7 +36,7 @@ module Gitlab
}
end
- @client = Client.new(credentials[:user], opts)
+ @client = Client.new(credentials[:user], **opts)
end
def execute
@@ -303,6 +303,8 @@ module Gitlab
end
imported!(resource_type)
+ rescue ::Octokit::NotFound => e
+ errors << { type: resource_type, errors: e.message }
end
def imported?(resource_type)
diff --git a/lib/gitlab/metrics/requests_rack_middleware.rb b/lib/gitlab/metrics/requests_rack_middleware.rb
index f6bda0dbea4..23d7eb67312 100644
--- a/lib/gitlab/metrics/requests_rack_middleware.rb
+++ b/lib/gitlab/metrics/requests_rack_middleware.rb
@@ -3,43 +3,70 @@
module Gitlab
module Metrics
class RequestsRackMiddleware
- HTTP_METHODS = %w(delete get head options patch post put).to_set.freeze
+ HTTP_METHODS = {
+ "delete" => %w(200 202 204 303 400 401 403 404 500 503),
+ "get" => %w(200 204 301 302 303 304 307 400 401 403 404 410 422 429 500 503),
+ "head" => %w(200 204 301 302 303 401 403 404 410 500),
+ "options" => %w(200 404),
+ "patch" => %w(200 202 204 400 403 404 409 416 500),
+ "post" => %w(200 201 202 204 301 302 303 304 400 401 403 404 406 409 410 412 422 429 500 503),
+ "put" => %w(200 202 204 400 401 403 404 405 406 409 410 422 500)
+ }.freeze
HEALTH_ENDPOINT = /^\/-\/(liveness|readiness|health|metrics)\/?$/.freeze
FEATURE_CATEGORY_HEADER = 'X-Gitlab-Feature-Category'
FEATURE_CATEGORY_DEFAULT = 'unknown'
+ # These were the top 5 categories at a point in time, chosen as a
+ # reasonable default. If we initialize every category we'll end up
+ # with an explosion in unused metric combinations, but we want the
+ # most common ones to be always present.
+ FEATURE_CATEGORIES_TO_INITIALIZE = ['authentication_and_authorization',
+ 'code_review', 'continuous_integration',
+ 'not_owned', 'source_code_management',
+ FEATURE_CATEGORY_DEFAULT].freeze
+
def initialize(app)
@app = app
end
- def self.http_request_total
- @http_request_total ||= ::Gitlab::Metrics.counter(:http_requests_total, 'Request count')
+ def self.http_requests_total
+ ::Gitlab::Metrics.counter(:http_requests_total, 'Request count')
end
def self.rack_uncaught_errors_count
- @rack_uncaught_errors_count ||= ::Gitlab::Metrics.counter(:rack_uncaught_errors_total, 'Request handling uncaught errors count')
+ ::Gitlab::Metrics.counter(:rack_uncaught_errors_total, 'Request handling uncaught errors count')
end
def self.http_request_duration_seconds
- @http_request_duration_seconds ||= ::Gitlab::Metrics.histogram(:http_request_duration_seconds, 'Request handling execution time',
- {}, [0.05, 0.1, 0.25, 0.5, 0.7, 1, 2.5, 5, 10, 25])
+ ::Gitlab::Metrics.histogram(:http_request_duration_seconds, 'Request handling execution time',
+ {}, [0.05, 0.1, 0.25, 0.5, 0.7, 1, 2.5, 5, 10, 25])
end
def self.http_health_requests_total
- @http_health_requests_total ||= ::Gitlab::Metrics.counter(:http_health_requests_total, 'Health endpoint request count')
+ ::Gitlab::Metrics.counter(:http_health_requests_total, 'Health endpoint request count')
end
- def self.initialize_http_request_duration_seconds
- HTTP_METHODS.each do |method|
+ def self.initialize_metrics
+ # This initialization is done to avoid gaps in scraped metrics after
+ # restarts. It makes sure all counters/histograms are available at
+ # process start.
+ #
+ # For example `rate(http_requests_total{status="500"}[1m])` would return
+ # no data until the first 500 error would occur.
+ HTTP_METHODS.each do |method, statuses|
http_request_duration_seconds.get({ method: method })
+
+ statuses.product(FEATURE_CATEGORIES_TO_INITIALIZE) do |status, feature_category|
+ http_requests_total.get({ method: method, status: status, feature_category: feature_category })
+ end
end
end
def call(env)
method = env['REQUEST_METHOD'].downcase
- method = 'INVALID' unless HTTP_METHODS.include?(method)
+ method = 'INVALID' unless HTTP_METHODS.key?(method)
started = Time.now.to_f
health_endpoint = health_endpoint?(env['PATH_INFO'])
status = 'undefined'
@@ -61,9 +88,13 @@ module Gitlab
raise
ensure
if health_endpoint
- RequestsRackMiddleware.http_health_requests_total.increment(status: status, method: method)
+ RequestsRackMiddleware.http_health_requests_total.increment(status: status.to_s, method: method)
else
- RequestsRackMiddleware.http_request_total.increment(status: status, method: method, feature_category: feature_category || FEATURE_CATEGORY_DEFAULT)
+ RequestsRackMiddleware.http_requests_total.increment(
+ status: status.to_s,
+ method: method,
+ feature_category: feature_category.presence || FEATURE_CATEGORY_DEFAULT
+ )
end
end
end
diff --git a/lib/gitlab/middleware/handle_malformed_strings.rb b/lib/gitlab/middleware/handle_malformed_strings.rb
new file mode 100644
index 00000000000..84f7e2e1b14
--- /dev/null
+++ b/lib/gitlab/middleware/handle_malformed_strings.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Middleware
+ # There is no valid reason for a request to contain a malformed string
+ # so just return HTTP 400 (Bad Request) if we receive one
+ class HandleMalformedStrings
+ include ActionController::HttpAuthentication::Basic
+
+ NULL_BYTE_REGEX = Regexp.new(Regexp.escape("\u0000")).freeze
+
+ attr_reader :app
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ return [400, { 'Content-Type' => 'text/plain' }, ['Bad Request']] if request_contains_malformed_string?(env)
+
+ app.call(env)
+ end
+
+ private
+
+ def request_contains_malformed_string?(env)
+ return false if ENV['DISABLE_REQUEST_VALIDATION'] == '1'
+
+ # Duplicate the env, so it is not modified when accessing the parameters
+ # https://github.com/rails/rails/blob/34991a6ae2fc68347c01ea7382fa89004159e019/actionpack/lib/action_dispatch/http/parameters.rb#L59
+ # The modification causes problems with our multipart middleware
+ request = ActionDispatch::Request.new(env.dup)
+
+ return true if malformed_path?(request.path)
+ return true if credentials_malformed?(request)
+
+ request.params.values.any? do |value|
+ param_has_null_byte?(value)
+ end
+ rescue ActionController::BadRequest
+ # If we can't build an ActionDispatch::Request something's wrong
+ # This would also happen if `#params` contains invalid UTF-8
+ # in this case we'll return a 400
+ #
+ true
+ end
+
+ def malformed_path?(path)
+ string_malformed?(Rack::Utils.unescape(path))
+ rescue ArgumentError
+ # Rack::Utils.unescape raised this, path is malformed.
+ true
+ end
+
+ def credentials_malformed?(request)
+ credentials = if has_basic_credentials?(request)
+ decode_credentials(request).presence
+ else
+ request.authorization.presence
+ end
+
+ return false unless credentials
+
+ string_malformed?(credentials)
+ end
+
+ def param_has_null_byte?(value, depth = 0)
+ # Guard against possible attack sending large amounts of nested params
+ # Should be safe as deeply nested params are highly uncommon.
+ return false if depth > 2
+
+ depth += 1
+
+ if value.respond_to?(:match)
+ string_malformed?(value)
+ elsif value.respond_to?(:values)
+ value.values.any? do |hash_value|
+ param_has_null_byte?(hash_value, depth)
+ end
+ elsif value.is_a?(Array)
+ value.any? do |array_value|
+ param_has_null_byte?(array_value, depth)
+ end
+ else
+ false
+ end
+ end
+
+ def string_malformed?(string)
+ # We're using match rather than include, because that will raise an ArgumentError
+ # when the string contains invalid UTF8
+ #
+ # We try to encode the string from ASCII-8BIT to UTF8. If we failed to do
+ # so for certain characters in the string, those chars are probably incomplete
+ # multibyte characters.
+ string.encode(Encoding::UTF_8).match?(NULL_BYTE_REGEX)
+ rescue ArgumentError, Encoding::UndefinedConversionError
+ # If we're here, we caught a malformed string. Return true
+ true
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/middleware/handle_null_bytes.rb b/lib/gitlab/middleware/handle_null_bytes.rb
deleted file mode 100644
index c88dfb6ee0b..00000000000
--- a/lib/gitlab/middleware/handle_null_bytes.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Middleware
- # There is no valid reason for a request to contain a null byte (U+0000)
- # so just return HTTP 400 (Bad Request) if we receive one
- class HandleNullBytes
- NULL_BYTE_REGEX = Regexp.new(Regexp.escape("\u0000")).freeze
-
- attr_reader :app
-
- def initialize(app)
- @app = app
- end
-
- def call(env)
- return [400, {}, ["Bad Request"]] if request_has_null_byte?(env)
-
- app.call(env)
- end
-
- private
-
- def request_has_null_byte?(request)
- return false if ENV['REJECT_NULL_BYTES'] == "1"
-
- request = Rack::Request.new(request)
-
- request.params.values.any? do |value|
- param_has_null_byte?(value)
- end
- end
-
- def param_has_null_byte?(value, depth = 0)
- # Guard against possible attack sending large amounts of nested params
- # Should be safe as deeply nested params are highly uncommon.
- return false if depth > 2
-
- depth += 1
-
- if value.respond_to?(:match)
- string_contains_null_byte?(value)
- elsif value.respond_to?(:values)
- value.values.any? do |hash_value|
- param_has_null_byte?(hash_value, depth)
- end
- elsif value.is_a?(Array)
- value.any? do |array_value|
- param_has_null_byte?(array_value, depth)
- end
- else
- false
- end
- end
-
- def string_contains_null_byte?(string)
- string.match?(NULL_BYTE_REGEX)
- end
- end
- end
-end
diff --git a/lib/gitlab/middleware/read_only/controller.rb b/lib/gitlab/middleware/read_only/controller.rb
index cfea4aaddf3..101172cdfcc 100644
--- a/lib/gitlab/middleware/read_only/controller.rb
+++ b/lib/gitlab/middleware/read_only/controller.rb
@@ -9,20 +9,19 @@ module Gitlab
APPLICATION_JSON_TYPES = %W{#{APPLICATION_JSON} application/vnd.git-lfs+json}.freeze
ERROR_MESSAGE = 'You cannot perform write operations on a read-only instance'
- WHITELISTED_GIT_ROUTES = {
- 'repositories/git_http' => %w{git_upload_pack git_receive_pack}
+ ALLOWLISTED_GIT_ROUTES = {
+ 'repositories/git_http' => %w{git_upload_pack}
}.freeze
- WHITELISTED_GIT_LFS_ROUTES = {
- 'repositories/lfs_api' => %w{batch},
- 'repositories/lfs_locks_api' => %w{verify create unlock}
+ ALLOWLISTED_GIT_LFS_BATCH_ROUTES = {
+ 'repositories/lfs_api' => %w{batch}
}.freeze
- WHITELISTED_GIT_REVISION_ROUTES = {
+ ALLOWLISTED_GIT_REVISION_ROUTES = {
'projects/compare' => %w{create}
}.freeze
- WHITELISTED_SESSION_ROUTES = {
+ ALLOWLISTED_SESSION_ROUTES = {
'sessions' => %w{destroy},
'admin/sessions' => %w{create destroy}
}.freeze
@@ -55,7 +54,7 @@ module Gitlab
def disallowed_request?
DISALLOWED_METHODS.include?(@env['REQUEST_METHOD']) &&
- !whitelisted_routes
+ !allowlisted_routes
end
def json_request?
@@ -87,8 +86,8 @@ module Gitlab
end
# Overridden in EE module
- def whitelisted_routes
- workhorse_passthrough_route? || internal_route? || lfs_route? || compare_git_revisions_route? || sidekiq_route? || session_route? || graphql_query?
+ def allowlisted_routes
+ workhorse_passthrough_route? || internal_route? || lfs_batch_route? || compare_git_revisions_route? || sidekiq_route? || session_route? || graphql_query?
end
# URL for requests passed through gitlab-workhorse to rails-web
@@ -96,9 +95,9 @@ module Gitlab
def workhorse_passthrough_route?
# Calling route_hash may be expensive. Only do it if we think there's a possible match
return false unless request.post? &&
- request.path.end_with?('.git/git-upload-pack', '.git/git-receive-pack')
+ request.path.end_with?('.git/git-upload-pack')
- WHITELISTED_GIT_ROUTES[route_hash[:controller]]&.include?(route_hash[:action])
+ ALLOWLISTED_GIT_ROUTES[route_hash[:controller]]&.include?(route_hash[:action])
end
def internal_route?
@@ -109,18 +108,16 @@ module Gitlab
# Calling route_hash may be expensive. Only do it if we think there's a possible match
return false unless request.post? && request.path.end_with?('compare')
- WHITELISTED_GIT_REVISION_ROUTES[route_hash[:controller]]&.include?(route_hash[:action])
+ ALLOWLISTED_GIT_REVISION_ROUTES[route_hash[:controller]]&.include?(route_hash[:action])
end
- def lfs_route?
+ # Batch upload requests are blocked in:
+ # https://gitlab.com/gitlab-org/gitlab/blob/master/app/controllers/repositories/lfs_api_controller.rb#L106
+ def lfs_batch_route?
# Calling route_hash may be expensive. Only do it if we think there's a possible match
- unless request.path.end_with?('/info/lfs/objects/batch',
- '/info/lfs/locks', '/info/lfs/locks/verify') ||
- %r{/info/lfs/locks/\d+/unlock\z}.match?(request.path)
- return false
- end
+ return unless request.path.end_with?('/info/lfs/objects/batch')
- WHITELISTED_GIT_LFS_ROUTES[route_hash[:controller]]&.include?(route_hash[:action])
+ ALLOWLISTED_GIT_LFS_BATCH_ROUTES[route_hash[:controller]]&.include?(route_hash[:action])
end
def session_route?
@@ -128,7 +125,7 @@ module Gitlab
return false unless request.post? && request.path.end_with?('/users/sign_out',
'/admin/session', '/admin/session/destroy')
- WHITELISTED_SESSION_ROUTES[route_hash[:controller]]&.include?(route_hash[:action])
+ ALLOWLISTED_SESSION_ROUTES[route_hash[:controller]]&.include?(route_hash[:action])
end
def sidekiq_route?
diff --git a/lib/gitlab/octokit/middleware.rb b/lib/gitlab/octokit/middleware.rb
index 2dd7d08a58b..a3c0fdcf467 100644
--- a/lib/gitlab/octokit/middleware.rb
+++ b/lib/gitlab/octokit/middleware.rb
@@ -8,7 +8,7 @@ module Gitlab
end
def call(env)
- Gitlab::UrlBlocker.validate!(env[:url], { allow_localhost: allow_local_requests?, allow_local_network: allow_local_requests? })
+ Gitlab::UrlBlocker.validate!(env[:url], allow_localhost: allow_local_requests?, allow_local_network: allow_local_requests?)
@app.call(env)
end
diff --git a/lib/gitlab/omniauth_initializer.rb b/lib/gitlab/omniauth_initializer.rb
index b60ecb6631b..541f9b06842 100644
--- a/lib/gitlab/omniauth_initializer.rb
+++ b/lib/gitlab/omniauth_initializer.rb
@@ -96,16 +96,6 @@ module Gitlab
args[:strategy_class] = args[:strategy_class].constantize
end
- # Providers that are known to depend on rack-oauth2, like those using
- # Omniauth::Strategies::OpenIDConnect, need to be quirked so the
- # client_auth_method argument value is passed as a symbol.
- if (args[:strategy_class] == OmniAuth::Strategies::OpenIDConnect ||
- args[:name] == 'openid_connect') &&
- args[:client_auth_method].is_a?(String)
-
- args[:client_auth_method] = args[:client_auth_method].to_sym
- end
-
args
end
diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb
index 706c16f6149..ad0a5c80604 100644
--- a/lib/gitlab/path_regex.rb
+++ b/lib/gitlab/path_regex.rb
@@ -49,6 +49,9 @@ module Gitlab
s
search
sent_notifications
+ sitemap
+ sitemap.xml
+ sitemap.xml.gz
slash-command-logo.png
snippets
unsubscribes
@@ -251,6 +254,14 @@ module Gitlab
%r{#{personal_snippet_path_regex}|#{project_snippet_path_regex}}
end
+ def container_image_regex
+ @container_image_regex ||= %r{([\w\.-]+\/){0,1}[\w\.-]+}.freeze
+ end
+
+ def container_image_blob_sha_regex
+ @container_image_blob_sha_regex ||= %r{[\w+.-]+:?\w+}.freeze
+ end
+
private
def personal_snippet_path_regex
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index 333564bee01..6719dc8362b 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, query, project:, repository_ref: nil, sort: nil, filters: {})
+ def initialize(current_user, query, project:, repository_ref: nil, order_by: nil, sort: nil, filters: {})
@project = project
@repository_ref = repository_ref.presence
- super(current_user, query, [project], sort: sort, filters: filters)
+ super(current_user, query, [project], order_by: order_by, sort: sort, filters: filters)
end
def objects(scope, page: nil, per_page: DEFAULT_PER_PAGE, preload_method: nil)
@@ -75,15 +75,6 @@ module Gitlab
@commits_count ||= commits(limit: count_limit).count
end
- def single_commit_result?
- return false if commits_count != 1
-
- counts = %i(limited_milestones_count limited_notes_count
- limited_merge_requests_count limited_issues_count
- limited_blobs_count wiki_blobs_count)
- counts.all? { |count_method| public_send(count_method) == 0 } # rubocop:disable GitlabSecurity/PublicSend
- end
-
private
def paginated_commits(page, per_page)
diff --git a/lib/gitlab/quick_actions/extractor.rb b/lib/gitlab/quick_actions/extractor.rb
index dd7a27ead01..1294e475145 100644
--- a/lib/gitlab/quick_actions/extractor.rb
+++ b/lib/gitlab/quick_actions/extractor.rb
@@ -29,9 +29,9 @@ module Gitlab
# Anything, including `/cmd arg` which are ignored by this filter
# `
- ^.*`\n*
+ `\n*
.+?
- \n*`$
+ \n*`
)
}mix.freeze
diff --git a/lib/gitlab/quick_actions/merge_request_actions.rb b/lib/gitlab/quick_actions/merge_request_actions.rb
index c8c949a9363..1986b7a1789 100644
--- a/lib/gitlab/quick_actions/merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/merge_request_actions.rb
@@ -56,21 +56,21 @@ module Gitlab
@updates[:merge] = params[:merge_request_diff_head_sha]
end
- desc 'Toggle the Work In Progress status'
+ desc 'Toggle the Draft status'
explanation do
noun = quick_action_target.to_ability_name.humanize(capitalize: false)
if quick_action_target.work_in_progress?
- _("Unmarks this %{noun} as Work In Progress.")
+ _("Unmarks this %{noun} as a draft.")
else
- _("Marks this %{noun} as Work In Progress.")
+ _("Marks this %{noun} as a draft.")
end % { noun: noun }
end
execution_message do
noun = quick_action_target.to_ability_name.humanize(capitalize: false)
if quick_action_target.work_in_progress?
- _("Unmarked this %{noun} as Work In Progress.")
+ _("Unmarked this %{noun} as a draft.")
else
- _("Marked this %{noun} as Work In Progress.")
+ _("Marked this %{noun} as a draft.")
end % { noun: noun }
end
@@ -80,7 +80,7 @@ module Gitlab
# Allow it to mark as WIP on MR creation page _or_ through MR notes.
(quick_action_target.new_record? || current_user.can?(:"update_#{quick_action_target.to_ability_name}", quick_action_target))
end
- command :wip do
+ command :draft, :wip do
@updates[:wip_event] = quick_action_target.work_in_progress? ? 'unwip' : 'wip'
end
diff --git a/lib/gitlab/redis/wrapper.rb b/lib/gitlab/redis/wrapper.rb
index 5584323789b..6f80c7d439f 100644
--- a/lib/gitlab/redis/wrapper.rb
+++ b/lib/gitlab/redis/wrapper.rb
@@ -18,6 +18,10 @@ module Gitlab
pool.with { |redis| yield redis }
end
+ def version
+ with { |redis| redis.info['redis_version'] }
+ end
+
def pool
@pool ||= ConnectionPool.new(size: pool_size) { ::Redis.new(params) }
end
diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb
index 01aff48b08b..d7501fc7068 100644
--- a/lib/gitlab/reference_extractor.rb
+++ b/lib/gitlab/reference_extractor.rb
@@ -4,7 +4,7 @@ module Gitlab
# Extract possible GFM references from an arbitrary String for further processing.
class ReferenceExtractor < Banzai::ReferenceExtractor
REFERABLES = %i(user issue label milestone mentioned_user mentioned_group mentioned_project
- merge_request snippet commit commit_range directly_addressed_user epic iteration).freeze
+ merge_request snippet commit commit_range directly_addressed_user epic iteration vulnerability).freeze
attr_accessor :project, :current_user, :author
# This counter is increased by a number of references filtered out by
# banzai reference exctractor. Note that this counter is stateful and
@@ -38,7 +38,7 @@ module Gitlab
end
REFERABLES.each do |type|
- define_method("#{type}s") do
+ define_method(type.to_s.pluralize) do
@references[type] ||= references(type)
end
end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 1b169b6186b..4ae6297f6f5 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -22,6 +22,10 @@ module Gitlab
@composer_package_version_regex ||= %r{^v?(\d+(\.(\d+|x))*(-.+)?)}.freeze
end
+ def composer_dev_version_regex
+ @composer_dev_version_regex ||= %r{(^dev-)|(-dev$)}.freeze
+ end
+
def package_name_regex
@package_name_regex ||= %r{\A\@?(([\w\-\.\+]*)\/)*([\w\-\.]+)@?(([\w\-\.\+]*)\/)*([\w\-\.]*)\z}.freeze
end
diff --git a/lib/gitlab/repository_size_checker.rb b/lib/gitlab/repository_size_checker.rb
index 03d9f961dd9..0ed31176dd8 100644
--- a/lib/gitlab/repository_size_checker.rb
+++ b/lib/gitlab/repository_size_checker.rb
@@ -32,18 +32,24 @@ module Gitlab
def changes_will_exceed_size_limit?(change_size)
return false unless enabled?
- change_size > limit || exceeded_size(change_size) > 0
+ above_size_limit? || exceeded_size(change_size) > 0
end
# @param change_size [int] in bytes
def exceeded_size(change_size = 0)
- current_size + change_size - limit
+ size = current_size + change_size - limit
+
+ [size, 0].max
end
def error_message
@error_message_object ||= ::Gitlab::RepositorySizeErrorMessage.new(self)
end
+ def additional_repo_storage_available?
+ false
+ end
+
private
attr_reader :namespace
diff --git a/lib/gitlab/repository_size_error_message.rb b/lib/gitlab/repository_size_error_message.rb
index 556190453de..8da840779c9 100644
--- a/lib/gitlab/repository_size_error_message.rb
+++ b/lib/gitlab/repository_size_error_message.rb
@@ -4,7 +4,7 @@ module Gitlab
class RepositorySizeErrorMessage
include ActiveSupport::NumberHelper
- delegate :current_size, :limit, :exceeded_size, to: :@checker
+ delegate :current_size, :limit, :exceeded_size, :additional_repo_storage_available?, to: :@checker
# @param checher [RepositorySizeChecker]
def initialize(checker)
@@ -24,7 +24,11 @@ module Gitlab
end
def new_changes_error
- "Your push to this repository would cause it to exceed the size limit of #{formatted(limit)} so it has been rejected. #{more_info_message}"
+ if additional_repo_storage_available?
+ "Your push to this repository has been rejected because it would exceed storage limits. Please contact your GitLab administrator for more information."
+ else
+ "Your push to this repository would cause it to exceed the size limit of #{formatted(limit)} so it has been rejected. #{more_info_message}"
+ end
end
def more_info_message
diff --git a/lib/gitlab/repository_url_builder.rb b/lib/gitlab/repository_url_builder.rb
index 2b88af1f77c..a2d0d50d20b 100644
--- a/lib/gitlab/repository_url_builder.rb
+++ b/lib/gitlab/repository_url_builder.rb
@@ -4,9 +4,6 @@ module Gitlab
module RepositoryUrlBuilder
class << self
def build(path, protocol: :ssh)
- # TODO: See https://gitlab.com/gitlab-org/gitlab/-/issues/213021
- path = path.sub('@snippets', 'snippets')
-
case protocol
when :ssh
ssh_url(path)
diff --git a/lib/gitlab/robots_txt/parser.rb b/lib/gitlab/robots_txt/parser.rb
index b9a3837e468..604d2f9b35b 100644
--- a/lib/gitlab/robots_txt/parser.rb
+++ b/lib/gitlab/robots_txt/parser.rb
@@ -3,34 +3,68 @@
module Gitlab
module RobotsTxt
class Parser
- attr_reader :disallow_rules
+ DISALLOW_REGEX = /^disallow: /i.freeze
+ ALLOW_REGEX = /^allow: /i.freeze
+
+ attr_reader :disallow_rules, :allow_rules
def initialize(content)
@raw_content = content
- @disallow_rules = parse_raw_content!
+ @disallow_rules, @allow_rules = parse_raw_content!
end
def disallowed?(path)
+ return false if allow_rules.any? { |rule| path =~ rule }
+
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.
+ # This parser is very basic as it only knows about `Disallow:`
+ # and `Allow:` lines, and simply ignores all other lines.
#
- # Order of predecence, 'Allow:`, etc are ignored for now.
+ # Patterns ending in `$`, and `*` for 0 or more characters are recognized.
+ #
+ # It is case insensitive and `Allow` rules takes precedence
+ # over `Disallow`.
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
+ disallowed = []
+ allowed = []
+
+ @raw_content.each_line.each do |line|
+ if disallow_rule?(line)
+ disallowed << get_disallow_pattern(line)
+ elsif allow_rule?(line)
+ allowed << get_allow_pattern(line)
end
- end.compact
+ end
+
+ [disallowed, allowed]
+ end
+
+ def disallow_rule?(line)
+ line =~ DISALLOW_REGEX
+ end
+
+ def get_disallow_pattern(line)
+ get_pattern(line, DISALLOW_REGEX)
+ end
+
+ def allow_rule?(line)
+ line =~ ALLOW_REGEX
+ end
+
+ def get_allow_pattern(line)
+ get_pattern(line, ALLOW_REGEX)
+ end
+
+ def get_pattern(line, rule_regex)
+ value = line.sub(rule_regex, '').strip
+ value = Regexp.escape(value).gsub('\*', '.*')
+ value = value.sub(/\\\$$/, '$')
+ Regexp.new("^#{value}")
end
end
end
diff --git a/lib/gitlab/search/found_blob.rb b/lib/gitlab/search/found_blob.rb
index fc1abc064c7..183e582925d 100644
--- a/lib/gitlab/search/found_blob.rb
+++ b/lib/gitlab/search/found_blob.rb
@@ -9,7 +9,7 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
include BlobActiveModel
- attr_reader :project, :content_match, :blob_path
+ attr_reader :project, :content_match, :blob_path, :highlight_line
PATH_REGEXP = /\A(?<ref>[^:]*):(?<path>[^\x00]*)\x00/.freeze
CONTENT_REGEXP = /^(?<ref>[^:]*):(?<path>[^\x00]*)\x00(?<startline>\d+)\x00/.freeze
@@ -26,6 +26,7 @@ module Gitlab
@binary_basename = opts.fetch(:basename, nil)
@ref = opts.fetch(:ref, nil)
@startline = opts.fetch(:startline, nil)
+ @highlight_line = opts.fetch(:highlight_line, nil)
@binary_data = opts.fetch(:data, nil)
@per_page = opts.fetch(:per_page, 20)
@project = opts.fetch(:project, nil)
diff --git a/lib/gitlab/search/sort_options.rb b/lib/gitlab/search/sort_options.rb
new file mode 100644
index 00000000000..3395c34d171
--- /dev/null
+++ b/lib/gitlab/search/sort_options.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Search
+ module SortOptions
+ def sort_and_direction(order_by, sort)
+ # Due to different uses of sort param in web vs. API requests we prefer
+ # order_by when present
+ case [order_by, sort]
+ when %w[created_at asc], [nil, 'created_asc']
+ :created_at_asc
+ when %w[created_at desc], [nil, 'created_desc']
+ :created_at_desc
+ else
+ :unknown
+ end
+ end
+ module_function :sort_and_direction # rubocop: disable Style/AccessModifierDeclarations
+ end
+ end
+end
diff --git a/lib/gitlab/search_results.rb b/lib/gitlab/search_results.rb
index b81264c5d0c..0091ae1e8ce 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, :sort, :filters
+ attr_reader :current_user, :query, :order_by, :sort, :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, query, limit_projects = nil, sort: nil, default_project_filter: false, filters: {})
+ def initialize(current_user, query, limit_projects = nil, order_by: nil, sort: nil, default_project_filter: false, filters: {})
@current_user = current_user
@query = query
@limit_projects = limit_projects || Project.all
@default_project_filter = default_project_filter
+ @order_by = order_by
@sort = sort
@filters = filters
end
@@ -94,10 +95,6 @@ module Gitlab
@limited_users_count ||= limited_count(users)
end
- def single_commit_result?
- false
- end
-
def count_limit
COUNT_LIMIT
end
@@ -132,13 +129,15 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def apply_sort(scope)
- case sort
- when 'oldest'
+ # Due to different uses of sort param we prefer order_by when
+ # present
+ case ::Gitlab::Search::SortOptions.sort_and_direction(order_by, sort)
+ when :created_at_asc
scope.reorder('created_at ASC')
- when 'newest'
+ when :created_at_desc
scope.reorder('created_at DESC')
else
- scope
+ scope.reorder('created_at DESC')
end
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -219,7 +218,7 @@ module Gitlab
params[:state] = filters[:state] if filters.key?(:state)
- if [true, false].include?(filters[:confidential]) && Feature.enabled?(:search_filter_by_confidential)
+ if [true, false].include?(filters[:confidential])
params[:confidential] = filters[:confidential]
end
end
diff --git a/lib/gitlab/setup_helper.rb b/lib/gitlab/setup_helper.rb
index 4df6a50c8dd..259d3e300b6 100644
--- a/lib/gitlab/setup_helper.rb
+++ b/lib/gitlab/setup_helper.rb
@@ -99,6 +99,7 @@ module Gitlab
config[:'gitlab-shell'] = { dir: Gitlab.config.gitlab_shell.path }
config[:bin_dir] = Gitlab.config.gitaly.client_path
config[:gitlab] = { url: Gitlab.config.gitlab.url }
+ config[:logging] = { dir: Rails.root.join('log').to_s }
TomlRB.dump(config)
end
diff --git a/lib/gitlab/sidekiq_cluster/cli.rb b/lib/gitlab/sidekiq_cluster/cli.rb
index 1e5d23a8405..e471517c50a 100644
--- a/lib/gitlab/sidekiq_cluster/cli.rb
+++ b/lib/gitlab/sidekiq_cluster/cli.rb
@@ -47,16 +47,24 @@ module Gitlab
option_parser.parse!(argv)
+ # Remove with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
+ if @queue_selector && @experimental_queue_selector
+ raise CommandError,
+ 'You cannot specify --queue-selector and --experimental-queue-selector together'
+ end
+
all_queues = SidekiqConfig::CliMethods.all_queues(@rails_path)
queue_names = SidekiqConfig::CliMethods.worker_queues(@rails_path)
queue_groups = argv.map do |queues|
next queue_names if queues == '*'
- # When using the experimental queue query syntax, we treat
- # each queue group as a worker attribute query, and resolve
- # the queues for the queue group using this query.
- if @experimental_queue_selector
+ # When using the queue query syntax, we treat each queue group
+ # as a worker attribute query, and resolve the queues for the
+ # queue group using this query.
+
+ # Simplify with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
+ if @queue_selector || @experimental_queue_selector
SidekiqConfig::CliMethods.query_workers(queues, all_queues)
else
SidekiqConfig::CliMethods.expand_queues(queues.split(','), queue_names)
@@ -182,7 +190,12 @@ module Gitlab
@rails_path = path
end
- opt.on('--experimental-queue-selector', 'EXPERIMENTAL: Run workers based on the provided selector') do |experimental_queue_selector|
+ opt.on('--queue-selector', 'Run workers based on the provided selector') do |queue_selector|
+ @queue_selector = queue_selector
+ end
+
+ # Remove with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
+ opt.on('--experimental-queue-selector', 'DEPRECATED: use --queue-selector-instead') do |experimental_queue_selector|
@experimental_queue_selector = experimental_queue_selector
end
diff --git a/lib/gitlab/sidekiq_logging/logs_jobs.rb b/lib/gitlab/sidekiq_logging/logs_jobs.rb
index 326dfdae661..dc81c34c4d0 100644
--- a/lib/gitlab/sidekiq_logging/logs_jobs.rb
+++ b/lib/gitlab/sidekiq_logging/logs_jobs.rb
@@ -16,7 +16,7 @@ module Gitlab
# Add process id params
job['pid'] = ::Process.pid
- job.delete('args') unless ENV['SIDEKIQ_LOG_ARGUMENTS']
+ job.delete('args') unless SidekiqLogArguments.enabled?
job
end
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies.rb
index 6fdef4c354e..63e8bee4443 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies.rb
@@ -8,6 +8,7 @@ module Gitlab
STRATEGIES = {
until_executing: UntilExecuting,
+ until_executed: UntilExecuted,
none: None
}.freeze
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/base.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/base.rb
new file mode 100644
index 00000000000..df5df590281
--- /dev/null
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/base.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SidekiqMiddleware
+ module DuplicateJobs
+ module Strategies
+ class Base
+ def initialize(duplicate_job)
+ @duplicate_job = duplicate_job
+ end
+
+ def schedule(job)
+ raise NotImplementedError
+ end
+
+ def perform(_job)
+ raise NotImplementedError
+ end
+
+ private
+
+ attr_reader :duplicate_job
+
+ def strategy_name
+ self.class.name.to_s.demodulize.underscore.humanize.downcase
+ end
+
+ def check!
+ # The default expiry time is the DuplicateJob::DUPLICATE_KEY_TTL already
+ # Only the strategies de-duplicating when scheduling
+ duplicate_job.check!
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/deduplicates_when_scheduling.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/deduplicates_when_scheduling.rb
new file mode 100644
index 00000000000..59b0e7e29da
--- /dev/null
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/deduplicates_when_scheduling.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SidekiqMiddleware
+ module DuplicateJobs
+ module Strategies
+ module DeduplicatesWhenScheduling
+ def initialize(duplicate_job)
+ @duplicate_job = duplicate_job
+ end
+
+ def schedule(job)
+ if deduplicatable_job? && check! && duplicate_job.duplicate?
+ job['duplicate-of'] = duplicate_job.existing_jid
+
+ if duplicate_job.droppable?
+ Gitlab::SidekiqLogging::DeduplicationLogger.instance.log(
+ job, "dropped #{strategy_name}", duplicate_job.options)
+ return false
+ end
+ end
+
+ yield
+ end
+
+ private
+
+ def deduplicatable_job?
+ !duplicate_job.scheduled? || duplicate_job.options[:including_scheduled]
+ end
+
+ def check!
+ duplicate_job.check!(expiry)
+ end
+
+ def expiry
+ return DuplicateJob::DUPLICATE_KEY_TTL unless duplicate_job.scheduled?
+
+ time_diff = duplicate_job.scheduled_at.to_i - Time.now.to_i
+
+ time_diff > 0 ? time_diff : DuplicateJob::DUPLICATE_KEY_TTL
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none.rb
index cd101cd16b6..acbe0efaafa 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none.rb
@@ -5,10 +5,7 @@ module Gitlab
module DuplicateJobs
module Strategies
# This strategy will never deduplicate a job
- class None
- def initialize(_duplicate_job)
- end
-
+ class None < Base
def schedule(_job)
yield
end
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed.rb
new file mode 100644
index 00000000000..738efa36fc8
--- /dev/null
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SidekiqMiddleware
+ module DuplicateJobs
+ module Strategies
+ # This strategy takes a lock before scheduling the job in a queue and
+ # removes the lock after the job has executed preventing a new job to be queued
+ # while a job is still executing.
+ class UntilExecuted < Base
+ include DeduplicatesWhenScheduling
+
+ def perform(_job)
+ yield
+
+ duplicate_job.delete!
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing.rb
index 46ce0eb4a91..68d66383b2b 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing.rb
@@ -7,50 +7,14 @@ module Gitlab
# This strategy takes a lock before scheduling the job in a queue and
# removes the lock before the job starts allowing a new job to be queued
# while a job is still executing.
- class UntilExecuting
- def initialize(duplicate_job)
- @duplicate_job = duplicate_job
- end
-
- def schedule(job)
- if deduplicatable_job? && check! && duplicate_job.duplicate?
- job['duplicate-of'] = duplicate_job.existing_jid
-
- if duplicate_job.droppable?
- Gitlab::SidekiqLogging::DeduplicationLogger.instance.log(
- job, "dropped until executing", duplicate_job.options)
- return false
- end
- end
-
- yield
- end
+ class UntilExecuting < Base
+ include DeduplicatesWhenScheduling
def perform(_job)
duplicate_job.delete!
yield
end
-
- private
-
- attr_reader :duplicate_job
-
- def deduplicatable_job?
- !duplicate_job.scheduled? || duplicate_job.options[:including_scheduled]
- end
-
- def check!
- duplicate_job.check!(expiry)
- end
-
- def expiry
- return DuplicateJob::DUPLICATE_KEY_TTL unless duplicate_job.scheduled?
-
- time_diff = duplicate_job.scheduled_at.to_i - Time.now.to_i
-
- time_diff > 0 ? time_diff : DuplicateJob::DUPLICATE_KEY_TTL
- 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
index ff24ec69ab0..0a2cee75af7 100644
--- a/lib/gitlab/static_site_editor/config/generated_config.rb
+++ b/lib/gitlab/static_site_editor/config/generated_config.rb
@@ -34,7 +34,7 @@ module Gitlab
delegate :project, to: :repository
def supported_extensions
- %w[.md].freeze
+ %w[.md .md.erb].freeze
end
def commit_id
@@ -50,8 +50,6 @@ module Gitlab
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
diff --git a/lib/gitlab/template/base_template.rb b/lib/gitlab/template/base_template.rb
index 50e09bdcdd6..e84937ec4ad 100644
--- a/lib/gitlab/template/base_template.rb
+++ b/lib/gitlab/template/base_template.rb
@@ -105,6 +105,20 @@ module Gitlab
files.map { |t| { name: t.name } }
end
end
+
+ def template_subsets(project = nil)
+ return [] if project && !project.repository.exists?
+
+ if categories.any?
+ categories.keys.map do |category|
+ files = self.by_category(category, project)
+ [category, files.map { |t| { key: t.key, name: t.name, content: t.content } }]
+ end.to_h
+ else
+ files = self.all(project)
+ files.map { |t| { key: t.key, name: t.name, content: t.content } }
+ end
+ end
end
end
end
diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
index 02d354ec43a..19be468e3d5 100644
--- a/lib/gitlab/tracking.rb
+++ b/lib/gitlab/tracking.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require 'snowplow-tracker'
-
module Gitlab
module Tracking
SNOWPLOW_NAMESPACE = 'gl'
@@ -27,16 +25,11 @@ module Gitlab
end
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)
+ snowplow.event(category, action, label: label, property: property, value: value, context: context)
end
def self_describing_event(schema_url, event_data_json, context: nil)
- return unless enabled?
-
- event_json = SnowplowTracker::SelfDescribingJson.new(schema_url, event_data_json)
- snowplow.track_self_describing_event(event_json, context, (Time.now.to_f * 1000).to_i)
+ snowplow.self_describing_event(schema_url, event_data_json, context: context)
end
def snowplow_options(group)
@@ -54,19 +47,7 @@ module Gitlab
private
def snowplow
- @snowplow ||= SnowplowTracker::Tracker.new(
- emitter,
- SnowplowTracker::Subject.new,
- SNOWPLOW_NAMESPACE,
- Gitlab::CurrentSettings.snowplow_app_id
- )
- end
-
- def emitter
- SnowplowTracker::AsyncEmitter.new(
- Gitlab::CurrentSettings.snowplow_collector_hostname,
- protocol: 'https'
- )
+ @snowplow ||= Gitlab::Tracking::Destinations::Snowplow.new
end
end
end
diff --git a/lib/gitlab/tracking/destinations/base.rb b/lib/gitlab/tracking/destinations/base.rb
new file mode 100644
index 00000000000..00e92e0bd57
--- /dev/null
+++ b/lib/gitlab/tracking/destinations/base.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Tracking
+ module Destinations
+ class Base
+ def event(category, action, label: nil, property: nil, value: nil, context: nil)
+ raise NotImplementedError, "#{self} does not implement #{__method__}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracking/destinations/snowplow.rb b/lib/gitlab/tracking/destinations/snowplow.rb
new file mode 100644
index 00000000000..9cebcfe5ee1
--- /dev/null
+++ b/lib/gitlab/tracking/destinations/snowplow.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'snowplow-tracker'
+
+module Gitlab
+ module Tracking
+ module Destinations
+ class Snowplow < Base
+ extend ::Gitlab::Utils::Override
+
+ override :event
+ def event(category, action, label: nil, property: nil, value: nil, context: nil)
+ return unless enabled?
+
+ tracker.track_struct_event(category, action, label, property, value, context, (Time.now.to_f * 1000).to_i)
+ end
+
+ def self_describing_event(schema_url, event_data_json, context: nil)
+ return unless enabled?
+
+ event_json = SnowplowTracker::SelfDescribingJson.new(schema_url, event_data_json)
+ tracker.track_self_describing_event(event_json, context, (Time.now.to_f * 1000).to_i)
+ end
+
+ private
+
+ def enabled?
+ Gitlab::CurrentSettings.snowplow_enabled?
+ end
+
+ def tracker
+ @tracker ||= SnowplowTracker::Tracker.new(
+ emitter,
+ SnowplowTracker::Subject.new,
+ Gitlab::Tracking::SNOWPLOW_NAMESPACE,
+ Gitlab::CurrentSettings.snowplow_app_id
+ )
+ end
+
+ def emitter
+ SnowplowTracker::AsyncEmitter.new(
+ Gitlab::CurrentSettings.snowplow_collector_hostname,
+ protocol: 'https'
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb
index 9213b5ebab2..eece2c343d2 100644
--- a/lib/gitlab/url_blocker.rb
+++ b/lib/gitlab/url_blocker.rb
@@ -49,7 +49,7 @@ module Gitlab
return [uri, nil] unless address_info
ip_address = ip_address(address_info)
- return [uri, nil] if domain_whitelisted?(uri) || ip_whitelisted?(ip_address, port: get_port(uri))
+ return [uri, nil] if domain_allowed?(uri) || ip_allowed?(ip_address, port: get_port(uri))
protected_uri_with_hostname = enforce_uri_hostname(ip_address, uri, dns_rebind_protection)
@@ -65,8 +65,8 @@ module Gitlab
protected_uri_with_hostname
end
- def blocked_url?(*args)
- validate!(*args)
+ def blocked_url?(url, **kwargs)
+ validate!(url, **kwargs)
false
rescue BlockedUrlError
@@ -113,8 +113,8 @@ module Gitlab
end
rescue SocketError
# If the dns rebinding protection is not enabled or the domain
- # is whitelisted we avoid the dns rebinding checks
- return if domain_whitelisted?(uri) || !dns_rebind_protection
+ # is allowed we avoid the dns rebinding checks
+ return if domain_allowed?(uri) || !dns_rebind_protection
# In the test suite we use a lot of mocked urls that are either invalid or
# don't exist. In order to avoid modifying a ton of tests and factories
@@ -253,12 +253,12 @@ module Gitlab
(uri.port.blank? || uri.port == config.gitlab_shell.ssh_port)
end
- def domain_whitelisted?(uri)
- Gitlab::UrlBlockers::UrlWhitelist.domain_whitelisted?(uri.normalized_host, port: get_port(uri))
+ def domain_allowed?(uri)
+ Gitlab::UrlBlockers::UrlAllowlist.domain_allowed?(uri.normalized_host, port: get_port(uri))
end
- def ip_whitelisted?(ip_address, port: nil)
- Gitlab::UrlBlockers::UrlWhitelist.ip_whitelisted?(ip_address, port: port)
+ def ip_allowed?(ip_address, port: nil)
+ Gitlab::UrlBlockers::UrlAllowlist.ip_allowed?(ip_address, port: port)
end
def config
diff --git a/lib/gitlab/url_blockers/domain_allowlist_entry.rb b/lib/gitlab/url_blockers/domain_allowlist_entry.rb
new file mode 100644
index 00000000000..b65bd9e1a92
--- /dev/null
+++ b/lib/gitlab/url_blockers/domain_allowlist_entry.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UrlBlockers
+ class DomainAllowlistEntry
+ attr_reader :domain, :port
+
+ def initialize(domain, port: nil)
+ @domain = domain
+ @port = port
+ end
+
+ def match?(requested_domain, requested_port = nil)
+ return false unless domain == requested_domain
+ return true if port.nil?
+
+ port == requested_port
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/url_blockers/domain_whitelist_entry.rb b/lib/gitlab/url_blockers/domain_whitelist_entry.rb
deleted file mode 100644
index b94e8ee3f69..00000000000
--- a/lib/gitlab/url_blockers/domain_whitelist_entry.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module UrlBlockers
- class DomainWhitelistEntry
- attr_reader :domain, :port
-
- def initialize(domain, port: nil)
- @domain = domain
- @port = port
- end
-
- def match?(requested_domain, requested_port = nil)
- return false unless domain == requested_domain
- return true if port.nil?
-
- port == requested_port
- end
- end
- end
-end
diff --git a/lib/gitlab/url_blockers/ip_allowlist_entry.rb b/lib/gitlab/url_blockers/ip_allowlist_entry.rb
new file mode 100644
index 00000000000..b293afe166c
--- /dev/null
+++ b/lib/gitlab/url_blockers/ip_allowlist_entry.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UrlBlockers
+ class IpAllowlistEntry
+ attr_reader :ip, :port
+
+ # Argument ip should be an IPAddr object
+ def initialize(ip, port: nil)
+ @ip = ip
+ @port = port
+ end
+
+ def match?(requested_ip, requested_port = nil)
+ return false unless ip.include?(requested_ip)
+ return true if port.nil?
+
+ port == requested_port
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/url_blockers/ip_whitelist_entry.rb b/lib/gitlab/url_blockers/ip_whitelist_entry.rb
deleted file mode 100644
index 88c76574d3d..00000000000
--- a/lib/gitlab/url_blockers/ip_whitelist_entry.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module UrlBlockers
- class IpWhitelistEntry
- attr_reader :ip, :port
-
- # Argument ip should be an IPAddr object
- def initialize(ip, port: nil)
- @ip = ip
- @port = port
- end
-
- def match?(requested_ip, requested_port = nil)
- return false unless ip.include?(requested_ip)
- return true if port.nil?
-
- port == requested_port
- end
- end
- end
-end
diff --git a/lib/gitlab/url_blockers/url_allowlist.rb b/lib/gitlab/url_blockers/url_allowlist.rb
new file mode 100644
index 00000000000..60238bea75a
--- /dev/null
+++ b/lib/gitlab/url_blockers/url_allowlist.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UrlBlockers
+ class UrlAllowlist
+ class << self
+ def ip_allowed?(ip_string, port: nil)
+ return false if ip_string.blank?
+
+ ip_allowlist, _ = outbound_local_requests_allowlist_arrays
+ ip_obj = Gitlab::Utils.string_to_ip_object(ip_string)
+
+ ip_allowlist.any? do |ip_allowlist_entry|
+ ip_allowlist_entry.match?(ip_obj, port)
+ end
+ end
+
+ def domain_allowed?(domain_string, port: nil)
+ return false if domain_string.blank?
+
+ _, domain_allowlist = outbound_local_requests_allowlist_arrays
+
+ domain_allowlist.any? do |domain_allowlist_entry|
+ domain_allowlist_entry.match?(domain_string, port)
+ end
+ end
+
+ private
+
+ # We cannot use Gitlab::CurrentSettings as ApplicationSetting itself
+ # calls this class. This ends up in a cycle where
+ # Gitlab::CurrentSettings creates an ApplicationSetting which then
+ # calls this method.
+ #
+ # See https://gitlab.com/gitlab-org/gitlab/issues/9833
+ def outbound_local_requests_allowlist_arrays
+ return [[], []] unless ApplicationSetting.current
+
+ ApplicationSetting.current.outbound_local_requests_allowlist_arrays
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/url_blockers/url_whitelist.rb b/lib/gitlab/url_blockers/url_whitelist.rb
deleted file mode 100644
index 59f74dde7fc..00000000000
--- a/lib/gitlab/url_blockers/url_whitelist.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module UrlBlockers
- class UrlWhitelist
- class << self
- def ip_whitelisted?(ip_string, port: nil)
- return false if ip_string.blank?
-
- ip_whitelist, _ = outbound_local_requests_whitelist_arrays
- ip_obj = Gitlab::Utils.string_to_ip_object(ip_string)
-
- ip_whitelist.any? do |ip_whitelist_entry|
- ip_whitelist_entry.match?(ip_obj, port)
- end
- end
-
- def domain_whitelisted?(domain_string, port: nil)
- return false if domain_string.blank?
-
- _, domain_whitelist = outbound_local_requests_whitelist_arrays
-
- domain_whitelist.any? do |domain_whitelist_entry|
- domain_whitelist_entry.match?(domain_string, port)
- end
- end
-
- private
-
- attr_reader :ip_whitelist, :domain_whitelist
-
- # We cannot use Gitlab::CurrentSettings as ApplicationSetting itself
- # calls this class. This ends up in a cycle where
- # Gitlab::CurrentSettings creates an ApplicationSetting which then
- # calls this method.
- #
- # See https://gitlab.com/gitlab-org/gitlab/issues/9833
- def outbound_local_requests_whitelist_arrays
- return [[], []] unless ApplicationSetting.current
-
- ApplicationSetting.current.outbound_local_requests_whitelist_arrays
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb
index 1e522ae63b6..ce59e10241e 100644
--- a/lib/gitlab/url_builder.rb
+++ b/lib/gitlab/url_builder.rb
@@ -32,6 +32,8 @@ module Gitlab
instance.milestone_url(object, **options)
when Note
note_url(object, **options)
+ when Release
+ instance.release_url(object, **options)
when Project
instance.project_url(object, **options)
when Snippet
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index 68f24559b1f..4b0dd54683b 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -40,8 +40,11 @@ module Gitlab
with_finished_at(:recording_ce_finished_at) do
license_usage_data
+ .merge(system_usage_data_license)
+ .merge(system_usage_data_settings)
.merge(system_usage_data)
.merge(system_usage_data_monthly)
+ .merge(system_usage_data_weekly)
.merge(features_usage_data)
.merge(components_usage_data)
.merge(cycle_analytics_usage_data)
@@ -157,6 +160,8 @@ module Gitlab
projects_with_tracing_enabled: count(ProjectTracingSetting),
projects_with_error_tracking_enabled: count(::ErrorTracking::ProjectErrorTrackingSetting.where(enabled: true)),
projects_with_alerts_service_enabled: count(AlertsService.active),
+ projects_with_alerts_created: distinct_count(::AlertManagement::Alert, :project_id),
+ projects_with_enabled_alert_integrations: distinct_count(::AlertManagement::HttpIntegration.active, :project_id),
projects_with_prometheus_alerts: distinct_count(PrometheusAlert, :project_id),
projects_with_terraform_reports: distinct_count(::Ci::JobArtifact.terraform_reports, :project_id),
projects_with_terraform_states: distinct_count(::Terraform::State, :project_id),
@@ -212,9 +217,11 @@ module Gitlab
# 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))
+ project_snippets: count(ProjectSnippet.where(last_28_days_time_period)),
+ projects_with_alerts_created: distinct_count(::AlertManagement::Alert.where(last_28_days_time_period), :project_id)
}.merge(
- snowplow_event_counts(last_28_days_time_period(column: :collector_tstamp))
+ snowplow_event_counts(last_28_days_time_period(column: :collector_tstamp)),
+ aggregated_metrics_monthly
).tap do |data|
data[:snippets] = data[:personal_snippets] + data[:project_snippets]
end
@@ -222,6 +229,27 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
+ def system_usage_data_license
+ {
+ license: {}
+ }
+ end
+
+ def system_usage_data_settings
+ {
+ settings: {}
+ }
+ end
+
+ def system_usage_data_weekly
+ {
+ counts_weekly: {
+ }.merge(
+ aggregated_metrics_weekly
+ )
+ }
+ end
+
def cycle_analytics_usage_data
Gitlab::CycleAnalytics::UsageData.new.to_json
rescue ActiveRecord::StatementInvalid
@@ -500,6 +528,7 @@ module Gitlab
key => {
configure: usage_activity_by_stage_configure(time_period),
create: usage_activity_by_stage_create(time_period),
+ enablement: usage_activity_by_stage_enablement(time_period),
manage: usage_activity_by_stage_manage(time_period),
monitor: usage_activity_by_stage_monitor(time_period),
package: usage_activity_by_stage_package(time_period),
@@ -555,6 +584,11 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
+ # Empty placeholder allows this to match the pattern used by other sections
+ def usage_activity_by_stage_enablement(time_period)
+ {}
+ end
+
# Omitted because no user, creator or author associated: `campaigns_imported_from_github`, `ldap_group_links`
# rubocop: disable CodeReuse/ActiveRecord
def usage_activity_by_stage_manage(time_period)
@@ -564,7 +598,11 @@ module Gitlab
users_created: count(::User.where(time_period), start: user_minimum_id, finish: user_maximum_id),
omniauth_providers: filtered_omniauth_provider_names.reject { |name| name == 'group_saml' },
user_auth_by_provider: distinct_count_user_auth_by_provider(time_period),
+ bulk_imports: {
+ gitlab: distinct_count(::BulkImport.where(time_period, source_type: :gitlab), :user_id)
+ },
projects_imported: {
+ total: count(Project.where(time_period).where.not(import_type: nil)),
gitlab_project: projects_imported_count('gitlab_project', time_period),
gitlab: projects_imported_count('gitlab', time_period),
github: projects_imported_count('github', time_period),
@@ -577,7 +615,8 @@ module Gitlab
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)
+ phabricator: projects_imported_count('phabricator', time_period),
+ csv: distinct_count(Issues::CsvImport.where(time_period), :user_id)
},
groups_imported: distinct_count(::GroupImportState.where(time_period), :user_id)
}
@@ -592,7 +631,10 @@ module Gitlab
operations_dashboard_default_dashboard: count(::User.active.with_dashboard('operations').where(time_period),
start: user_minimum_id,
finish: user_maximum_id),
- projects_with_tracing_enabled: distinct_count(::Project.with_tracing_enabled.where(time_period), :creator_id)
+ projects_with_tracing_enabled: distinct_count(::Project.with_tracing_enabled.where(time_period), :creator_id),
+ projects_with_error_tracking_enabled: distinct_count(::Project.with_enabled_error_tracking.where(time_period), :creator_id),
+ projects_with_incidents: distinct_count(::Issue.incident.where(time_period), :project_id),
+ projects_with_alert_incidents: distinct_count(::Issue.incident.with_alert_management_alerts.where(time_period), :project_id)
}
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -664,6 +706,22 @@ module Gitlab
{ redis_hll_counters: ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events_data }
end
+ def aggregated_metrics_monthly
+ return {} unless Feature.enabled?(:product_analytics_aggregated_metrics)
+
+ {
+ aggregated_metrics: ::Gitlab::UsageDataCounters::HLLRedisCounter.aggregated_metrics_monthly_data
+ }
+ end
+
+ def aggregated_metrics_weekly
+ return {} unless Feature.enabled?(:product_analytics_aggregated_metrics)
+
+ {
+ aggregated_metrics: ::Gitlab::UsageDataCounters::HLLRedisCounter.aggregated_metrics_weekly_data
+ }
+ end
+
def analytics_unique_visits_data
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) }
@@ -709,7 +767,8 @@ module Gitlab
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
+ action_monthly_active_users_wiki_repo: Gitlab::UsageDataCounters::TrackUniqueEvents::WIKI_ACTION,
+ action_monthly_active_users_git_write: Gitlab::UsageDataCounters::TrackUniqueEvents::GIT_WRITE_ACTION
}
data.each do |key, event|
diff --git a/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml b/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml
new file mode 100644
index 00000000000..97ec8423b95
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml
@@ -0,0 +1,17 @@
+#- name: unique name of aggregated metric
+# operator: aggregation operator. Valid values are:
+# - "OR": counts unique elements that were observed triggering any of following events
+# - "AND": counts unique elements that were observed triggering all of following events
+# events: list of events names to aggregate into metric. All events in this list must have the same 'redis_slot' and 'aggregation' attributes
+# see from lib/gitlab/usage_data_counters/known_events/ for the list of valid events.
+# feature_flag: name of development feature flag that will be checked before metrics aggregation is performed.
+# Corresponding feature flag should have `default_enabled` attribute set to `false`.
+# This attribute is OPTIONAL and can be omitted, when `feature_flag` is missing no feature flag will be checked.
+---
+- name: product_analytics_test_metrics_union
+ operator: OR
+ events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
+ feature_flag: product_analytics_aggregated_metrics
+- name: product_analytics_test_metrics_intersection
+ operator: AND
+ events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
diff --git a/lib/gitlab/usage_data_counters/designs_counter.rb b/lib/gitlab/usage_data_counters/designs_counter.rb
index 22188b555d2..07e1963f9fb 100644
--- a/lib/gitlab/usage_data_counters/designs_counter.rb
+++ b/lib/gitlab/usage_data_counters/designs_counter.rb
@@ -1,42 +1,8 @@
# frozen_string_literal: true
module Gitlab::UsageDataCounters
- class DesignsCounter
- extend Gitlab::UsageDataCounters::RedisCounter
-
+ class DesignsCounter < BaseCounter
KNOWN_EVENTS = %w[create update delete].freeze
-
- UnknownEvent = Class.new(StandardError)
-
- class << self
- # Each event gets a unique Redis key
- def redis_key(event)
- raise UnknownEvent, event unless KNOWN_EVENTS.include?(event.to_s)
-
- "USAGE_DESIGN_MANAGEMENT_DESIGNS_#{event}".upcase
- end
-
- def count(event)
- increment(redis_key(event))
- end
-
- def read(event)
- total_count(redis_key(event))
- end
-
- def totals
- KNOWN_EVENTS.map { |event| [counter_key(event), read(event)] }.to_h
- end
-
- def fallback_totals
- KNOWN_EVENTS.map { |event| [counter_key(event), -1] }.to_h
- end
-
- private
-
- def counter_key(event)
- "design_management_designs_#{event}".to_sym
- end
- end
+ PREFIX = 'design_management_designs'
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 eb132ef0967..573ad1dce35 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb
+++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
@@ -5,18 +5,28 @@ module Gitlab
module HLLRedisCounter
DEFAULT_WEEKLY_KEY_EXPIRY_LENGTH = 6.weeks
DEFAULT_DAILY_KEY_EXPIRY_LENGTH = 29.days
- DEFAULT_REDIS_SLOT = ''.freeze
-
- UnknownEvent = Class.new(StandardError)
- UnknownAggregation = Class.new(StandardError)
-
- KNOWN_EVENTS_PATH = 'lib/gitlab/usage_data_counters/known_events.yml'.freeze
+ DEFAULT_REDIS_SLOT = ''
+
+ EventError = Class.new(StandardError)
+ UnknownEvent = Class.new(EventError)
+ UnknownAggregation = Class.new(EventError)
+ AggregationMismatch = Class.new(EventError)
+ SlotMismatch = Class.new(EventError)
+ CategoryMismatch = Class.new(EventError)
+ UnknownAggregationOperator = Class.new(EventError)
+ InvalidContext = Class.new(EventError)
+
+ KNOWN_EVENTS_PATH = File.expand_path('known_events/*.yml', __dir__)
ALLOWED_AGGREGATIONS = %i(daily weekly).freeze
+ UNION_OF_AGGREGATED_METRICS = 'OR'
+ INTERSECTION_OF_AGGREGATED_METRICS = 'AND'
+ ALLOWED_METRICS_AGGREGATIONS = [UNION_OF_AGGREGATED_METRICS, INTERSECTION_OF_AGGREGATED_METRICS].freeze
+ AGGREGATED_METRICS_PATH = File.expand_path('aggregated_metrics/*.yml', __dir__)
# Track event on entity_id
# Increment a Redis HLL counter for unique event_name and entity_id
#
- # All events should be added to know_events file lib/gitlab/usage_data_counters/known_events.yml
+ # All events should be added to known_events yml files lib/gitlab/usage_data_counters/known_events/
#
# Event example:
#
@@ -25,6 +35,7 @@ module Gitlab
# category: compliance # Group events in categories
# expiry: 29 # Optional expiration time in days, default value 29 days for daily and 6.weeks for weekly
# aggregation: daily # Aggregation level, keys are stored daily or weekly
+ # feature_flag: # The event feature flag
#
# Usage:
#
@@ -33,28 +44,24 @@ module Gitlab
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?
-
- Gitlab::Redis::HLL.add(key: redis_key(event, time), value: entity_id, expiry: expiry(event))
+ def track_event(value, event_name, time = Time.zone.now)
+ track(value, event_name, time: time)
end
- def unique_events(event_names:, start_date:, end_date:)
- events = events_for(Array(event_names))
-
- raise 'Events should be in same slot' unless events_in_same_slot?(events)
- raise 'Events should be in same category' unless events_in_same_category?(events)
- raise 'Events should have same aggregation level' unless events_same_aggregation?(events)
-
- aggregation = events.first[:aggregation]
+ def track_event_in_context(value, event_name, context, time = Time.zone.now)
+ return if context.blank?
+ return unless context.in?(valid_context_list)
- keys = keys_for_aggregation(aggregation, events: events, start_date: start_date, end_date: end_date)
+ track(value, event_name, context: context, time: time)
+ end
- redis_usage_data { Gitlab::Redis::HLL.count(keys: keys) }
+ def unique_events(event_names:, start_date:, end_date:, context: '')
+ count_unique_events(event_names: event_names, start_date: start_date, end_date: end_date, context: context) do |events|
+ raise SlotMismatch, events unless events_in_same_slot?(events)
+ raise CategoryMismatch, events unless events_in_same_category?(events)
+ raise AggregationMismatch, events unless events_same_aggregation?(events)
+ raise InvalidContext if context.present? && !context.in?(valid_context_list)
+ end
end
def categories
@@ -72,8 +79,8 @@ module Gitlab
events_names = events_for_category(category)
event_results = events_names.each_with_object({}) do |event, hash|
- hash["#{event}_weekly"] = unique_events(event_names: event, start_date: 7.days.ago.to_date, end_date: Date.current)
- hash["#{event}_monthly"] = unique_events(event_names: event, start_date: 4.weeks.ago.to_date, end_date: Date.current)
+ hash["#{event}_weekly"] = unique_events(event_names: [event], start_date: 7.days.ago.to_date, end_date: Date.current)
+ hash["#{event}_monthly"] = unique_events(event_names: [event], start_date: 4.weeks.ago.to_date, end_date: Date.current)
end
if eligible_for_totals?(events_names)
@@ -89,8 +96,136 @@ module Gitlab
event_for(event_name).present?
end
+ def aggregated_metrics_monthly_data
+ aggregated_metrics_data(4.weeks.ago.to_date)
+ end
+
+ def aggregated_metrics_weekly_data
+ aggregated_metrics_data(7.days.ago.to_date)
+ end
+
+ def known_events
+ @known_events ||= load_events(KNOWN_EVENTS_PATH)
+ end
+
+ def aggregated_metrics
+ @aggregated_metrics ||= load_events(AGGREGATED_METRICS_PATH)
+ end
+
private
+ def track(value, event_name, context: '', time: Time.zone.now)
+ return unless Gitlab::CurrentSettings.usage_ping_enabled?
+
+ event = event_for(event_name)
+ raise UnknownEvent, "Unknown event #{event_name}" unless event.present?
+
+ Gitlab::Redis::HLL.add(key: redis_key(event, time, context), value: value, expiry: expiry(event))
+ end
+
+ # The aray of valid context on which we allow tracking
+ def valid_context_list
+ Plan.all_plans
+ end
+
+ def aggregated_metrics_data(start_date)
+ aggregated_metrics.each_with_object({}) do |aggregation, weekly_data|
+ next if aggregation[:feature_flag] && Feature.disabled?(aggregation[:feature_flag], default_enabled: false, type: :development)
+
+ weekly_data[aggregation[:name]] = calculate_count_for_aggregation(aggregation, start_date: start_date, end_date: Date.current)
+ end
+ end
+
+ def calculate_count_for_aggregation(aggregation, start_date:, end_date:)
+ case aggregation[:operator]
+ when UNION_OF_AGGREGATED_METRICS
+ calculate_events_union(event_names: aggregation[:events], start_date: start_date, end_date: end_date)
+ when INTERSECTION_OF_AGGREGATED_METRICS
+ calculate_events_intersections(event_names: aggregation[:events], start_date: start_date, end_date: end_date)
+ else
+ raise UnknownAggregationOperator, "Events should be aggregated with one of operators #{ALLOWED_METRICS_AGGREGATIONS}"
+ end
+ end
+
+ # calculate intersection of 'n' sets based on inclusion exclusion principle https://en.wikipedia.org/wiki/Inclusion%E2%80%93exclusion_principle
+ # this method will be extracted to dedicated module with https://gitlab.com/gitlab-org/gitlab/-/issues/273391
+ def calculate_events_intersections(event_names:, start_date:, end_date:, subset_powers_cache: Hash.new({}))
+ # calculate power of intersection of all given metrics from inclusion exclusion principle
+ # |A + B + C| = (|A| + |B| + |C|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C|) =>
+ # |A & B & C| = - (|A| + |B| + |C|) + (|A & B| + |A & C| + .. + |C & D|) + |A + B + C|
+ # |A + B + C + D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - |A & B & C & D| =>
+ # |A & B & C & D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - |A + B + C + D|
+
+ # calculate each components of equation except for the last one |A & B & C & D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - ...
+ subset_powers_data = subsets_intersection_powers(event_names, start_date, end_date, subset_powers_cache)
+
+ # calculate last component of the equation |A & B & C & D| = .... - |A + B + C + D|
+ power_of_union_of_all_events = begin
+ subset_powers_cache[event_names.size][event_names.join('_+_')] ||= \
+ calculate_events_union(event_names: event_names, start_date: start_date, end_date: end_date)
+ end
+
+ # in order to determine if part of equation (|A & B & C|, |A & B & C & D|), that represents the intersection that we need to calculate,
+ # is positive or negative in particular equation we need to determine if number of subsets is even or odd. Please take a look at two examples below
+ # |A + B + C| = (|A| + |B| + |C|) - (|A & B| + |A & C| + .. + |C & D|) + |A & B & C| =>
+ # |A & B & C| = - (|A| + |B| + |C|) + (|A & B| + |A & C| + .. + |C & D|) + |A + B + C|
+ # |A + B + C + D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - |A & B & C & D| =>
+ # |A & B & C & D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - |A + B + C + D|
+ subset_powers_size_even = subset_powers_data.size.even?
+
+ # sum all components of equation except for the last one |A & B & C & D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - ... =>
+ sum_of_all_subset_powers = sum_subset_powers(subset_powers_data, subset_powers_size_even)
+
+ # add last component of the equation |A & B & C & D| = sum_of_all_subset_powers - |A + B + C + D|
+ sum_of_all_subset_powers + (subset_powers_size_even ? power_of_union_of_all_events : -power_of_union_of_all_events)
+ end
+
+ def sum_subset_powers(subset_powers_data, subset_powers_size_even)
+ sum_without_sign = subset_powers_data.to_enum.with_index.sum do |value, index|
+ (index + 1).odd? ? value : -value
+ end
+
+ (subset_powers_size_even ? -1 : 1) * sum_without_sign
+ end
+
+ def subsets_intersection_powers(event_names, start_date, end_date, subset_powers_cache)
+ subset_sizes = (1..(event_names.size - 1))
+
+ subset_sizes.map do |subset_size|
+ if subset_size > 1
+ # calculate sum of powers of intersection between each subset (with given size) of metrics: #|A + B + C + D| = ... - (|A & B| + |A & C| + .. + |C & D|)
+ event_names.combination(subset_size).sum do |events_subset|
+ subset_powers_cache[subset_size][events_subset.join('_&_')] ||= \
+ calculate_events_intersections(event_names: events_subset, start_date: start_date, end_date: end_date, subset_powers_cache: subset_powers_cache)
+ end
+ else
+ # calculate sum of powers of each set (metric) alone #|A + B + C + D| = (|A| + |B| + |C| + |D|) - ...
+ event_names.sum do |event|
+ subset_powers_cache[subset_size][event] ||= \
+ unique_events(event_names: event, start_date: start_date, end_date: end_date)
+ end
+ end
+ end
+ end
+
+ def calculate_events_union(event_names:, start_date:, end_date:)
+ count_unique_events(event_names: event_names, start_date: start_date, end_date: end_date) do |events|
+ raise SlotMismatch, events unless events_in_same_slot?(events)
+ raise AggregationMismatch, events unless events_same_aggregation?(events)
+ end
+ end
+
+ def count_unique_events(event_names:, start_date:, end_date:, context: '')
+ events = events_for(Array(event_names).map(&:to_s))
+
+ yield events if block_given?
+
+ aggregation = events.first[:aggregation]
+
+ keys = keys_for_aggregation(aggregation, events: events, start_date: start_date, end_date: end_date, context: context)
+ redis_usage_data { Gitlab::Redis::HLL.count(keys: keys) }
+ end
+
# Allow to add totals for events that are in the same redis slot, category and have the same aggregation level
# and if there are more than 1 event
def eligible_for_totals?(events_names)
@@ -100,16 +235,22 @@ module Gitlab
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:)
+ def keys_for_aggregation(aggregation, events:, start_date:, end_date:, context: '')
if aggregation.to_sym == :daily
- daily_redis_keys(events: events, start_date: start_date, end_date: end_date)
+ daily_redis_keys(events: events, start_date: start_date, end_date: end_date, context: context)
else
- weekly_redis_keys(events: events, start_date: start_date, end_date: end_date)
+ weekly_redis_keys(events: events, start_date: start_date, end_date: end_date, context: context)
end
end
- def known_events
- @known_events ||= YAML.load_file(Rails.root.join(KNOWN_EVENTS_PATH)).map(&:with_indifferent_access)
+ def load_events(wildcard)
+ Dir[wildcard].each_with_object([]) do |path, events|
+ events.push(*load_yaml_from_path(path))
+ end
+ end
+
+ def load_yaml_from_path(path)
+ YAML.safe_load(File.read(path))&.map(&:with_indifferent_access)
end
def known_events_names
@@ -141,7 +282,7 @@ module Gitlab
end
def event_for(event_name)
- known_events.find { |event| event[:name] == event_name }
+ known_events.find { |event| event[:name] == event_name.to_s }
end
def events_for(event_names)
@@ -153,17 +294,26 @@ module Gitlab
end
# Compose the key in order to store events daily or weekly
- def redis_key(event, time)
+ def redis_key(event, time, context = '')
raise UnknownEvent.new("Unknown event #{event[:name]}") unless known_events_names.include?(event[:name].to_s)
raise UnknownAggregation.new("Use :daily or :weekly aggregation") unless ALLOWED_AGGREGATIONS.include?(event[:aggregation].to_sym)
+ key = apply_slot(event)
+ key = apply_time_aggregation(key, time, event)
+ key = "#{context}_#{key}" if context.present?
+ key
+ end
+
+ def apply_slot(event)
slot = redis_slot(event)
- key = if slot.present?
- event[:name].to_s.gsub(slot, "{#{slot}}")
- else
- "{#{event[:name]}}"
- end
+ if slot.present?
+ event[:name].to_s.gsub(slot, "{#{slot}}")
+ else
+ "{#{event[:name]}}"
+ end
+ end
+ def apply_time_aggregation(key, time, event)
if event[:aggregation].to_sym == :daily
year_day = time.strftime('%G-%j')
"#{year_day}-#{key}"
@@ -173,21 +323,29 @@ module Gitlab
end
end
- def daily_redis_keys(events:, start_date:, end_date:)
+ def daily_redis_keys(events:, start_date:, end_date:, context: '')
(start_date.to_date..end_date.to_date).map do |date|
- events.map { |event| redis_key(event, date) }
+ events.map { |event| redis_key(event, date, context) }
end.flatten
end
- def weekly_redis_keys(events:, start_date:, end_date:)
+ def validate_aggregation_operator!(operator)
+ return true if ALLOWED_METRICS_AGGREGATIONS.include?(operator)
+
+ raise UnknownAggregationOperator.new("Events should be aggregated with one of operators #{ALLOWED_METRICS_AGGREGATIONS}")
+ end
+
+ def weekly_redis_keys(events:, start_date:, end_date:, context: '')
weeks = end_date.to_date.cweek - start_date.to_date.cweek
weeks = 1 if weeks == 0
(0..(weeks - 1)).map do |week_increment|
- events.map { |event| redis_key(event, start_date + week_increment * 7.days) }
+ events.map { |event| redis_key(event, start_date + week_increment * 7.days, context) }
end.flatten
end
end
end
end
end
+
+Gitlab::UsageDataCounters::HLLRedisCounter.prepend_if_ee('EE::Gitlab::UsageDataCounters::HLLRedisCounter')
diff --git a/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
index e8839875109..da013a06777 100644
--- a/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
@@ -9,14 +9,12 @@ module Gitlab
ISSUE_CREATED = 'g_project_management_issue_created'
ISSUE_CLOSED = 'g_project_management_issue_closed'
ISSUE_DESCRIPTION_CHANGED = 'g_project_management_issue_description_changed'
- ISSUE_ITERATION_CHANGED = 'g_project_management_issue_iteration_changed'
ISSUE_LABEL_CHANGED = 'g_project_management_issue_label_changed'
ISSUE_MADE_CONFIDENTIAL = 'g_project_management_issue_made_confidential'
ISSUE_MADE_VISIBLE = 'g_project_management_issue_made_visible'
ISSUE_MILESTONE_CHANGED = 'g_project_management_issue_milestone_changed'
ISSUE_REOPENED = 'g_project_management_issue_reopened'
ISSUE_TITLE_CHANGED = 'g_project_management_issue_title_changed'
- ISSUE_WEIGHT_CHANGED = 'g_project_management_issue_weight_changed'
ISSUE_CROSS_REFERENCED = 'g_project_management_issue_cross_referenced'
ISSUE_MOVED = 'g_project_management_issue_moved'
ISSUE_RELATED = 'g_project_management_issue_related'
@@ -24,15 +22,15 @@ module Gitlab
ISSUE_MARKED_AS_DUPLICATE = 'g_project_management_issue_marked_as_duplicate'
ISSUE_LOCKED = 'g_project_management_issue_locked'
ISSUE_UNLOCKED = 'g_project_management_issue_unlocked'
- ISSUE_ADDED_TO_EPIC = 'g_project_management_issue_added_to_epic'
- ISSUE_REMOVED_FROM_EPIC = 'g_project_management_issue_removed_from_epic'
- ISSUE_CHANGED_EPIC = 'g_project_management_issue_changed_epic'
ISSUE_DESIGNS_ADDED = 'g_project_management_issue_designs_added'
ISSUE_DESIGNS_MODIFIED = 'g_project_management_issue_designs_modified'
ISSUE_DESIGNS_REMOVED = 'g_project_management_issue_designs_removed'
ISSUE_DUE_DATE_CHANGED = 'g_project_management_issue_due_date_changed'
ISSUE_TIME_ESTIMATE_CHANGED = 'g_project_management_issue_time_estimate_changed'
ISSUE_TIME_SPENT_CHANGED = 'g_project_management_issue_time_spent_changed'
+ ISSUE_COMMENT_ADDED = 'g_project_management_issue_comment_added'
+ ISSUE_COMMENT_EDITED = 'g_project_management_issue_comment_edited'
+ ISSUE_COMMENT_REMOVED = 'g_project_management_issue_comment_removed'
class << self
def track_issue_created_action(author:, time: Time.zone.now)
@@ -75,14 +73,6 @@ module Gitlab
track_unique_action(ISSUE_MILESTONE_CHANGED, author, time)
end
- def track_issue_iteration_changed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_ITERATION_CHANGED, author, time)
- end
-
- def track_issue_weight_changed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_WEIGHT_CHANGED, author, time)
- end
-
def track_issue_cross_referenced_action(author:, time: Time.zone.now)
track_unique_action(ISSUE_CROSS_REFERENCED, author, time)
end
@@ -111,18 +101,6 @@ module Gitlab
track_unique_action(ISSUE_UNLOCKED, author, time)
end
- def track_issue_added_to_epic_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_ADDED_TO_EPIC, author, time)
- end
-
- def track_issue_removed_from_epic_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_REMOVED_FROM_EPIC, author, time)
- end
-
- def track_issue_changed_epic_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_CHANGED_EPIC, author, time)
- end
-
def track_issue_designs_added_action(author:, time: Time.zone.now)
track_unique_action(ISSUE_DESIGNS_ADDED, author, time)
end
@@ -147,6 +125,18 @@ module Gitlab
track_unique_action(ISSUE_TIME_SPENT_CHANGED, author, time)
end
+ def track_issue_comment_added_action(author:, time: Time.zone.now)
+ track_unique_action(ISSUE_COMMENT_ADDED, author, time)
+ end
+
+ def track_issue_comment_edited_action(author:, time: Time.zone.now)
+ track_unique_action(ISSUE_COMMENT_EDITED, author, time)
+ end
+
+ def track_issue_comment_removed_action(author:, time: Time.zone.now)
+ track_unique_action(ISSUE_COMMENT_REMOVED, author, time)
+ end
+
private
def track_unique_action(action, author, time)
@@ -159,3 +149,5 @@ module Gitlab
end
end
end
+
+Gitlab::UsageDataCounters::IssueActivityUniqueCounter.prepend_if_ee('EE::Gitlab::UsageDataCounters::IssueActivityUniqueCounter')
diff --git a/lib/gitlab/usage_data_counters/known_events.yml b/lib/gitlab/usage_data_counters/known_events.yml
deleted file mode 100644
index bc56c5d6d9b..00000000000
--- a/lib/gitlab/usage_data_counters/known_events.yml
+++ /dev/null
@@ -1,305 +0,0 @@
----
-# Compliance category
-- name: g_compliance_dashboard
- redis_slot: compliance
- category: compliance
- aggregation: weekly
-- name: g_compliance_audit_events
- category: compliance
- redis_slot: compliance
- aggregation: weekly
-- name: i_compliance_audit_events
- category: compliance
- redis_slot: compliance
- aggregation: weekly
-- name: i_compliance_credential_inventory
- category: compliance
- redis_slot: compliance
- 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
- aggregation: weekly
-- name: g_analytics_insights
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: g_analytics_issues
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: g_analytics_productivity
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: g_analytics_valuestream
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: p_analytics_pipelines
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: p_analytics_code_reviews
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: p_analytics_valuestream
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: p_analytics_insights
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: p_analytics_issues
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: p_analytics_repo
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: i_analytics_cohorts
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: i_analytics_dev_ops_score
- category: analytics
- redis_slot: analytics
- 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
-# Testing category
-- name: i_testing_test_case_parsed
- category: testing
- redis_slot: testing
- 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
-- name: g_project_management_issue_created
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_closed
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_reopened
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_label_changed
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_milestone_changed
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_iteration_changed
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_weight_changed
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_cross_referenced
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_moved
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_related
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_unrelated
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_marked_as_duplicate
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_locked
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_unlocked
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_added_to_epic
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_removed_from_epic
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_changed_epic
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_designs_added
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_designs_modified
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_designs_removed
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_due_date_changed
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_time_estimate_changed
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_time_spent_changed
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
diff --git a/lib/gitlab/usage_data_counters/known_events/common.yml b/lib/gitlab/usage_data_counters/known_events/common.yml
new file mode 100644
index 00000000000..85f16ea807b
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/known_events/common.yml
@@ -0,0 +1,404 @@
+---
+# Compliance category
+- name: g_compliance_dashboard
+ redis_slot: compliance
+ category: compliance
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: g_compliance_audit_events
+ category: compliance
+ redis_slot: compliance
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: i_compliance_audit_events
+ category: compliance
+ redis_slot: compliance
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: i_compliance_credential_inventory
+ category: compliance
+ redis_slot: compliance
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: a_compliance_audit_events_api
+ category: compliance
+ redis_slot: compliance
+ aggregation: weekly
+ feature_flag: usage_data_a_compliance_audit_events_api
+# Analytics category
+- name: g_analytics_contribution
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: g_analytics_insights
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: g_analytics_issues
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: g_analytics_productivity
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: g_analytics_valuestream
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: p_analytics_pipelines
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: p_analytics_code_reviews
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: p_analytics_valuestream
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: p_analytics_insights
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: p_analytics_issues
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: p_analytics_repo
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: i_analytics_cohorts
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: i_analytics_dev_ops_score
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: g_analytics_merge_request
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: p_analytics_merge_request
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: i_analytics_instance_statistics
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
+- name: g_edit_by_web_ide
+ category: ide_edit
+ redis_slot: edit
+ expiry: 29
+ aggregation: daily
+ feature_flag: track_editor_edit_actions
+- name: g_edit_by_sfe
+ category: ide_edit
+ redis_slot: edit
+ expiry: 29
+ aggregation: daily
+ feature_flag: track_editor_edit_actions
+- name: g_edit_by_snippet_ide
+ category: ide_edit
+ redis_slot: edit
+ expiry: 29
+ aggregation: daily
+ feature_flag: track_editor_edit_actions
+- name: i_search_total
+ category: search
+ redis_slot: search
+ aggregation: weekly
+ feature_flag: search_track_unique_users
+- name: i_search_advanced
+ category: search
+ redis_slot: search
+ aggregation: weekly
+ feature_flag: search_track_unique_users
+- name: i_search_paid
+ category: search
+ redis_slot: search
+ aggregation: weekly
+ feature_flag: search_track_unique_users
+- 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: git_write_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
+ feature_flag: usage_data_incident_management_alert_status_changed
+- name: incident_management_alert_assigned
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_alert_assigned
+- name: incident_management_alert_todo
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_alert_todo
+- name: incident_management_incident_created
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_incident_created
+- name: incident_management_incident_reopened
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_incident_reopened
+- name: incident_management_incident_closed
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_incident_closed
+- name: incident_management_incident_assigned
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_incident_assigned
+- name: incident_management_incident_todo
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_incident_todo
+- name: incident_management_incident_comment
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_incident_comment
+- name: incident_management_incident_zoom_meeting
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_incident_zoom_meeting
+- name: incident_management_incident_published
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_incident_published
+- name: incident_management_incident_relate
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_incident_relate
+- name: incident_management_incident_unrelate
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_incident_unrelate
+- name: incident_management_incident_change_confidential
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+ feature_flag: usage_data_incident_management_incident_change_confidential
+# Testing category
+- name: i_testing_test_case_parsed
+ category: testing
+ redis_slot: testing
+ aggregation: weekly
+ feature_flag: usage_data_i_testing_test_case_parsed
+# Project Management group
+- name: g_project_management_issue_title_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_description_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_assignee_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_made_confidential
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_made_visible
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_created
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_closed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_reopened
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_label_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_milestone_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_iteration_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_weight_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_cross_referenced
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_moved
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_related
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_unrelated
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_marked_as_duplicate
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_locked
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_unlocked
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_added_to_epic
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_removed_from_epic
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_changed_epic
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_designs_added
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_designs_modified
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_designs_removed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_due_date_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_time_estimate_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_time_spent_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_comment_added
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_comment_edited
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_comment_removed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+- name: g_project_management_issue_health_status_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_issue_activity_actions
+# Secrets Management
+- name: i_ci_secrets_management_vault_build_created
+ category: ci_secrets_management
+ redis_slot: ci_secrets_management
+ aggregation: weekly
+ feature_flag: usage_data_i_ci_secrets_management_vault_build_created
diff --git a/lib/gitlab/usage_data_counters/known_events/package_events.yml b/lib/gitlab/usage_data_counters/known_events/package_events.yml
new file mode 100644
index 00000000000..7ed02aa2a85
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/known_events/package_events.yml
@@ -0,0 +1,265 @@
+---
+- name: i_package_maven_user_push
+ category: maven_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_maven_deploy_token_push
+ category: maven_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_maven_user_delete
+ category: maven_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_maven_deploy_token_delete
+ category: maven_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_maven_user_pull
+ category: maven_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_maven_deploy_token_pull
+ category: maven_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_npm_user_push
+ category: npm_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_npm_deploy_token_push
+ category: npm_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_npm_user_delete
+ category: npm_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_npm_deploy_token_delete
+ category: npm_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_npm_user_pull
+ category: npm_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_npm_deploy_token_pull
+ category: npm_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_conan_user_push
+ category: conan_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_conan_deploy_token_push
+ category: conan_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_conan_user_delete
+ category: conan_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_conan_deploy_token_delete
+ category: conan_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_conan_user_pull
+ category: conan_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_conan_deploy_token_pull
+ category: conan_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_nuget_user_push
+ category: nuget_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_nuget_deploy_token_push
+ category: nuget_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_nuget_user_delete
+ category: nuget_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_nuget_deploy_token_delete
+ category: nuget_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_nuget_user_pull
+ category: nuget_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_nuget_deploy_token_pull
+ category: nuget_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_pypi_user_push
+ category: pypi_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_pypi_deploy_token_push
+ category: pypi_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_pypi_user_delete
+ category: pypi_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_pypi_deploy_token_delete
+ category: pypi_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_pypi_user_pull
+ category: pypi_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_pypi_deploy_token_pull
+ category: pypi_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_composer_user_push
+ category: composer_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_composer_deploy_token_push
+ category: composer_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_composer_user_delete
+ category: composer_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_composer_deploy_token_delete
+ category: composer_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_composer_user_pull
+ category: composer_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_composer_deploy_token_pull
+ category: composer_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_generic_user_push
+ category: generic_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_generic_deploy_token_push
+ category: generic_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_generic_user_delete
+ category: generic_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_generic_deploy_token_delete
+ category: generic_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_generic_user_pull
+ category: generic_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_generic_deploy_token_pull
+ category: generic_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_golang_user_push
+ category: golang_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_golang_deploy_token_push
+ category: golang_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_golang_user_delete
+ category: golang_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_golang_deploy_token_delete
+ category: golang_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_golang_user_pull
+ category: golang_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_golang_deploy_token_pull
+ category: golang_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_debian_user_push
+ category: debian_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_debian_deploy_token_push
+ category: debian_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_debian_user_delete
+ category: debian_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_debian_deploy_token_delete
+ category: debian_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_debian_user_pull
+ category: debian_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_debian_deploy_token_pull
+ category: debian_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_container_user_push
+ category: container_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_container_deploy_token_push
+ category: container_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_container_user_delete
+ category: container_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_container_deploy_token_delete
+ category: container_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_container_user_pull
+ category: container_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_container_deploy_token_pull
+ category: container_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_tag_user_push
+ category: tag_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_tag_deploy_token_push
+ category: tag_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_tag_user_delete
+ category: tag_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_tag_deploy_token_delete
+ category: tag_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_tag_user_pull
+ category: tag_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_tag_deploy_token_pull
+ category: tag_packages
+ aggregation: weekly
+ redis_slot: package
diff --git a/lib/gitlab/usage_data_counters/static_site_editor_counter.rb b/lib/gitlab/usage_data_counters/static_site_editor_counter.rb
index 8886a106da8..3c5989d1e11 100644
--- a/lib/gitlab/usage_data_counters/static_site_editor_counter.rb
+++ b/lib/gitlab/usage_data_counters/static_site_editor_counter.rb
@@ -3,7 +3,7 @@
module Gitlab
module UsageDataCounters
class StaticSiteEditorCounter < BaseCounter
- KNOWN_EVENTS = %w[views].freeze
+ KNOWN_EVENTS = %w[views commits merge_requests].freeze
PREFIX = 'static_site_editor'
class << self
diff --git a/lib/gitlab/usage_data_counters/track_unique_events.rb b/lib/gitlab/usage_data_counters/track_unique_events.rb
index 7053744b665..95380ae0b1d 100644
--- a/lib/gitlab/usage_data_counters/track_unique_events.rb
+++ b/lib/gitlab/usage_data_counters/track_unique_events.rb
@@ -8,6 +8,9 @@ module Gitlab
PUSH_ACTION = :project_action
MERGE_REQUEST_ACTION = :merge_request_action
+ GIT_WRITE_ACTIONS = [WIKI_ACTION, DESIGN_ACTION, PUSH_ACTION].freeze
+ GIT_WRITE_ACTION = :git_write_action
+
ACTION_TRANSFORMATIONS = HashWithIndifferentAccess.new({
wiki: {
created: WIKI_ACTION,
@@ -41,6 +44,8 @@ module Gitlab
return unless Gitlab::UsageDataCounters::HLLRedisCounter.known_event?(transformed_action.to_s)
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(author_id, transformed_action.to_s, time)
+
+ track_git_write_action(author_id, transformed_action, time)
end
def count_unique_events(event_action:, date_from:, date_to:)
@@ -64,6 +69,12 @@ module Gitlab
def valid_action?(action)
Event.actions.key?(action)
end
+
+ def track_git_write_action(author_id, transformed_action, time)
+ return unless GIT_WRITE_ACTIONS.include?(transformed_action)
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(author_id, GIT_WRITE_ACTION, time)
+ end
end
end
end
diff --git a/lib/gitlab/usage_data_counters/web_ide_counter.rb b/lib/gitlab/usage_data_counters/web_ide_counter.rb
index 00fcd42a9af..9f2f4ac3971 100644
--- a/lib/gitlab/usage_data_counters/web_ide_counter.rb
+++ b/lib/gitlab/usage_data_counters/web_ide_counter.rb
@@ -2,54 +2,43 @@
module Gitlab
module UsageDataCounters
- class WebIdeCounter
- extend RedisCounter
- KNOWN_EVENTS = %i[commits views merge_requests previews terminals pipelines].freeze
+ class WebIdeCounter < BaseCounter
+ KNOWN_EVENTS = %w[commits views merge_requests previews terminals pipelines].freeze
PREFIX = 'web_ide'
class << self
def increment_commits_count
- increment(redis_key('commits'))
+ count('commits')
end
def increment_merge_requests_count
- increment(redis_key('merge_requests'))
+ count('merge_requests')
end
def increment_views_count
- increment(redis_key('views'))
+ count('views')
end
def increment_terminals_count
- increment(redis_key('terminals'))
+ count('terminals')
end
def increment_pipelines_count
- increment(redis_key('pipelines'))
+ count('pipelines')
end
def increment_previews_count
return unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?
- increment(redis_key('previews'))
- end
-
- def totals
- KNOWN_EVENTS.map { |event| [counter_key(event), total_count(redis_key(event))] }.to_h
- end
-
- def fallback_totals
- KNOWN_EVENTS.map { |event| [counter_key(event), -1] }.to_h
+ count('previews')
end
private
def redis_key(event)
- "#{PREFIX}_#{event}_count".upcase
- end
+ require_known_event(event)
- def counter_key(event)
- "#{PREFIX}_#{event}".to_sym
+ "#{prefix}_#{event}_count".upcase
end
end
end
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index 1c6ddc2e70f..eec89e1ab72 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -90,9 +90,13 @@ module Gitlab
def can_collaborate?(ref)
assert_project!
+ can_push? || branch_allows_collaboration_for?(ref)
+ end
+
+ def branch_allows_collaboration_for?(ref)
# Checking for an internal project or group to prevent an infinite loop:
# https://gitlab.com/gitlab-org/gitlab/issues/36805
- can_push? || (!project.internal? && project.branch_allows_collaboration?(user, ref))
+ (!project.internal? && project.branch_allows_collaboration?(user, ref))
end
def permission_cache
diff --git a/lib/gitlab/webpack/dev_server_middleware.rb b/lib/gitlab/webpack/dev_server_middleware.rb
index 069e68e8d29..88f2a4455c6 100644
--- a/lib/gitlab/webpack/dev_server_middleware.rb
+++ b/lib/gitlab/webpack/dev_server_middleware.rb
@@ -16,14 +16,14 @@ module Gitlab
super(app, backend: "#{@proxy_scheme}://#{@proxy_host}:#{@proxy_port}", **opts)
end
- # disable SSL check since any cert used here will likely be self-signed
- def rewrite_env(env)
- env["rack.ssl_verify_none"] = true
- env
- end
-
def perform_request(env)
if @proxy_path && env['PATH_INFO'].start_with?("/#{@proxy_path}")
+ # disable SSL check since any cert used here will likely be self-signed
+ env['rack.ssl_verify_none'] = true
+
+ # ensure we pass the expected Host header so webpack-dev-server doesn't complain
+ env['HTTP_HOST'] = "#{@proxy_host}:#{@proxy_port}"
+
if relative_url_root = Rails.application.config.relative_url_root
env['SCRIPT_NAME'] = ""
env['REQUEST_PATH'].sub!(/\A#{Regexp.escape(relative_url_root)}/, '')
diff --git a/lib/gitlab/whats_new.rb b/lib/gitlab/whats_new.rb
index e95ace2c475..69ccb48c544 100644
--- a/lib/gitlab/whats_new.rb
+++ b/lib/gitlab/whats_new.rb
@@ -2,27 +2,39 @@
module Gitlab
module WhatsNew
- CACHE_DURATION = 1.day
+ CACHE_DURATION = 1.hour
WHATS_NEW_FILES_PATH = Rails.root.join('data', 'whats_new', '*.yml')
private
- def whats_new_most_recent_release_items
- Rails.cache.fetch('whats_new:release_items', expires_in: CACHE_DURATION) do
- file = File.read(most_recent_release_file_path)
+ def whats_new_release_items(page: 1)
+ Rails.cache.fetch(whats_new_items_cache_key(page), expires_in: CACHE_DURATION) do
+ index = page - 1
+ file_path = whats_new_file_paths[index]
+
+ next if file_path.nil?
+
+ file = File.read(file_path)
items = YAML.safe_load(file, permitted_classes: [Date])
items if items.is_a?(Array)
end
rescue => e
- Gitlab::ErrorTracking.track_exception(e, yaml_file_path: most_recent_release_file_path)
+ Gitlab::ErrorTracking.track_exception(e, page: page)
nil
end
- def most_recent_release_file_path
- @most_recent_release_file_path ||= Dir.glob(WHATS_NEW_FILES_PATH).max
+ def whats_new_file_paths
+ @whats_new_file_paths ||= Rails.cache.fetch('whats_new:file_paths', expires_in: CACHE_DURATION) do
+ Dir.glob(WHATS_NEW_FILES_PATH).sort.reverse
+ end
+ end
+
+ def whats_new_items_cache_key(page)
+ filename = /\d*\_\d*\_\d*/.match(whats_new_file_paths&.first)
+ "whats_new:release_items:file-#{filename}:page-#{page}"
end
end
end
diff --git a/lib/gitlab/with_feature_category.rb b/lib/gitlab/with_feature_category.rb
new file mode 100644
index 00000000000..65d21daf78a
--- /dev/null
+++ b/lib/gitlab/with_feature_category.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module WithFeatureCategory
+ extend ActiveSupport::Concern
+ include Gitlab::ClassAttributes
+
+ class_methods do
+ def feature_category(category, actions = [])
+ feature_category_configuration[category] ||= []
+ feature_category_configuration[category] += actions.map(&:to_s)
+
+ validate_config!(feature_category_configuration)
+ end
+
+ def feature_category_for_action(action)
+ category_config = feature_category_configuration.find do |_, actions|
+ actions.empty? || actions.include?(action)
+ end
+
+ category_config&.first || superclass_feature_category_for_action(action)
+ end
+
+ private
+
+ def validate_config!(config)
+ empty = config.find { |_, actions| actions.empty? }
+ duplicate_actions = config.values.map(&:uniq).flatten.group_by(&:itself).select { |_, v| v.count > 1 }.keys
+
+ if config.length > 1 && empty
+ raise ArgumentError, "#{empty.first} is defined for all actions, but other categories are set"
+ end
+
+ if duplicate_actions.any?
+ raise ArgumentError, "Actions have multiple feature categories: #{duplicate_actions.join(', ')}"
+ end
+ end
+
+ def feature_category_configuration
+ class_attributes[:feature_category_config] ||= {}
+ end
+
+ def superclass_feature_category_for_action(action)
+ return unless superclass.respond_to?(:feature_category_for_action)
+
+ superclass.feature_category_for_action(action)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index eb780a2f7f6..8e7af8876a4 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -270,7 +270,7 @@ module Gitlab
prefix: metadata['ArchivePrefix'],
format: format,
path: path.presence || "",
- include_lfs_blobs: Feature.enabled?(:include_lfs_blobs_in_archive)
+ include_lfs_blobs: Feature.enabled?(:include_lfs_blobs_in_archive, default_enabled: true)
).to_proto
)
}
diff --git a/lib/quality/test_level.rb b/lib/quality/test_level.rb
index cd94efddc1e..b239b6812ca 100644
--- a/lib/quality/test_level.rb
+++ b/lib/quality/test_level.rb
@@ -12,6 +12,9 @@ module Quality
lib/gitlab/background_migration
lib/ee/gitlab/background_migration
],
+ frontend_fixture: %w[
+ frontend/fixtures
+ ],
unit: %w[
bin
channels
@@ -63,7 +66,7 @@ module Quality
end
def pattern(level)
- @patterns[level] ||= "#{prefix}spec/#{folders_pattern(level)}{,/**/}*_spec.rb"
+ @patterns[level] ||= "#{prefix}spec/#{folders_pattern(level)}{,/**/}*#{suffix(level)}"
end
def regexp(level)
@@ -76,6 +79,9 @@ module Quality
# spec/lib/gitlab/background_migration and tests under spec/lib are unit by default
when regexp(:migration), regexp(:background_migration)
:migration
+ # Detect frontend fixture before matching other unit tests
+ when regexp(:frontend_fixture)
+ :frontend_fixture
when regexp(:unit)
:unit
when regexp(:integration)
@@ -93,6 +99,15 @@ module Quality
private
+ def suffix(level)
+ case level
+ when :frontend_fixture
+ ".rb"
+ else
+ "_spec.rb"
+ end
+ end
+
def migration_and_background_migration_folders
TEST_LEVEL_FOLDERS.fetch(:migration) + TEST_LEVEL_FOLDERS.fetch(:background_migration)
end
diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb
index e2a7d3ef5ba..e7e0d4e471f 100644
--- a/lib/rouge/formatters/html_gitlab.rb
+++ b/lib/rouge/formatters/html_gitlab.rb
@@ -20,7 +20,7 @@ module Rouge
is_first = false
yield %(<span id="LC#{@line_number}" class="line" lang="#{@tag}">)
- line.each { |token, value| yield span(token, value.chomp) }
+ line.each { |token, value| yield span(token, value.chomp! || value) }
yield %(</span>)
@line_number += 1
diff --git a/lib/rspec_flaky/flaky_examples_collection.rb b/lib/rspec_flaky/flaky_examples_collection.rb
index b86ec82bde6..acbfb411873 100644
--- a/lib/rspec_flaky/flaky_examples_collection.rb
+++ b/lib/rspec_flaky/flaky_examples_collection.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'active_support/hash_with_indifferent_access'
+require 'delegate'
require_relative 'flaky_example'
diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab
index fc984d737d5..9eafa5ef008 100644
--- a/lib/support/nginx/gitlab
+++ b/lib/support/nginx/gitlab
@@ -18,7 +18,7 @@
upstream gitlab-workhorse {
# GitLab socket file,
- # for Omnibus this would be: unix:/var/opt/gitlab/gitlab-workhorse/socket
+ # for Omnibus this would be: unix:/var/opt/gitlab/gitlab-workhorse/sockets/socket
server unix:/home/git/gitlab/tmp/sockets/gitlab-workhorse.socket fail_timeout=0;
}
diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl
index ba01e250bbb..ae5c88455e4 100644
--- a/lib/support/nginx/gitlab-ssl
+++ b/lib/support/nginx/gitlab-ssl
@@ -22,7 +22,7 @@
upstream gitlab-workhorse {
# GitLab socket file,
- # for Omnibus this would be: unix:/var/opt/gitlab/gitlab-workhorse/socket
+ # for Omnibus this would be: unix:/var/opt/gitlab/gitlab-workhorse/sockets/socket
server unix:/home/git/gitlab/tmp/sockets/gitlab-workhorse.socket fail_timeout=0;
}
diff --git a/lib/system_check/app/git_version_check.rb b/lib/system_check/app/git_version_check.rb
index 0709f783f09..0f4fbe4fba5 100644
--- a/lib/system_check/app/git_version_check.rb
+++ b/lib/system_check/app/git_version_check.rb
@@ -7,7 +7,7 @@ module SystemCheck
set_check_pass -> { "yes (#{self.current_version})" }
def self.required_version
- @required_version ||= Gitlab::VersionInfo.parse('2.24.0')
+ @required_version ||= Gitlab::VersionInfo.parse('2.29.0')
end
def self.current_version
diff --git a/lib/tasks/gitlab/gitaly.rake b/lib/tasks/gitlab/gitaly.rake
index 74cf3aad951..49d2d3d62a2 100644
--- a/lib/tasks/gitlab/gitaly.rake
+++ b/lib/tasks/gitlab/gitaly.rake
@@ -22,7 +22,7 @@ Usage: rake "gitlab:gitaly:install[/installation/dir,/storage/path]")
if Rails.env.test?
command.push(
'BUNDLE_FLAGS=--no-deployment',
- "BUNDLE_PATH=#{Bundler.bundle_path}")
+ "GEM_HOME=#{Bundler.bundle_path}")
end
storage_paths = { 'default' => args.storage_path }
diff --git a/lib/tasks/gitlab/packages/events.rake b/lib/tasks/gitlab/packages/events.rake
new file mode 100644
index 00000000000..3484b9b6072
--- /dev/null
+++ b/lib/tasks/gitlab/packages/events.rake
@@ -0,0 +1,40 @@
+require 'logger'
+
+desc "GitLab | Packages | Events | Generate hll counter events file for packages"
+namespace :gitlab do
+ namespace :packages do
+ namespace :events do
+ task generate: :environment do
+ logger = Logger.new(STDOUT)
+ logger.info('Building list of package events...')
+
+ path = File.join(File.dirname(::Gitlab::UsageDataCounters::HLLRedisCounter::KNOWN_EVENTS_PATH), 'package_events.yml')
+
+ File.open(path, "w") { |file| file << generate_unique_events_list.to_yaml }
+
+ logger.info("Events file `#{path}` generated successfully")
+ rescue => e
+ logger.error("Error building events list: #{e}")
+ end
+
+ def event_pairs
+ ::Packages::Event.event_types.keys.product(::Packages::Event.originator_types.keys)
+ end
+
+ def generate_unique_events_list
+ ::Packages::Event::EVENT_SCOPES.keys.each_with_object([]) do |event_scope, events|
+ event_pairs.each do |event_type, originator|
+ if name = ::Packages::Event.allowed_event_name(event_scope, event_type, originator)
+ events << {
+ "name" => name,
+ "category" => "#{event_scope}_packages",
+ "aggregation" => "weekly",
+ "redis_slot" => "package"
+ }
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/locale/am_ET/gitlab.po b/locale/am_ET/gitlab.po
index ccb2d2cfd20..91876bbef41 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-10-02 18:45\n"
+"PO-Revision-Date: 2020-11-03 22:44\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d የተስተካከለ የáተሻ á‹áŒ¤á‰µ"
@@ -215,11 +220,6 @@ msgid_plural "%d issues in this group"
msgstr[0] ""
msgstr[1] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d የተመረጠ ርዕሰ ጉዳይ"
-msgstr[1] "%d የተመረጡ ርዕሰ ጉዳዮች"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -407,6 +407,16 @@ msgstr "ከ%{name} %{count} áቃዶች"
msgid "%{count} files touched"
msgstr "%{count} á‹á‹­áˆŽá‰½ ተáŠáŠ­á‰°á‹‹áˆ"
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr "%{count} ተጨማሪ"
@@ -447,6 +457,12 @@ 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 "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr "%{group_name} በቡድን የሚተዳደሩ መለያዎችን ይጠá
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 "%{name} %{resultsString} á‹­á‹­á‹›áˆ"
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index ed9ee601d86..7618208528d 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-10-02 18:46\n"
+"PO-Revision-Date: 2020-11-03 22:46\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -277,6 +277,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -331,15 +340,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -631,6 +631,24 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{count} more"
msgstr ""
@@ -679,6 +697,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -724,6 +748,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -850,9 +880,6 @@ 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 ""
@@ -970,7 +997,7 @@ msgstr[5] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -994,6 +1021,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1231,9 +1261,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1276,6 +1303,18 @@ msgstr[5] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1312,6 +1351,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1321,23 +1363,8 @@ 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] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1660,6 +1687,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1963,6 +1993,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -2116,7 +2149,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -2152,10 +2185,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -2242,6 +2275,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -2266,6 +2302,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2380,6 +2419,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2389,6 +2443,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2401,12 +2461,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2461,6 +2539,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2470,6 +2551,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2515,6 +2599,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2539,6 +2626,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2548,6 +2638,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2563,22 +2656,22 @@ 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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2647,10 +2740,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2767,6 +2860,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2776,10 +2878,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2791,19 +2893,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2818,6 +2929,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2827,7 +2944,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2845,7 +2965,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2854,6 +2974,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2920,9 +3061,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2947,6 +3085,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2968,6 +3109,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2989,12 +3133,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -3043,6 +3193,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -3055,9 +3208,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -3085,9 +3244,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -3175,9 +3340,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -3250,9 +3412,6 @@ 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 ""
@@ -3283,9 +3442,6 @@ 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 ""
@@ -3310,6 +3466,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3334,9 +3493,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3352,6 +3508,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3697,6 +3856,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3949,6 +4111,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -4201,7 +4366,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -4222,6 +4408,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -4240,6 +4429,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -4297,9 +4489,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4381,6 +4570,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4465,6 +4660,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4516,12 +4723,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4540,6 +4756,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4552,6 +4771,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4696,6 +4918,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4732,9 +4957,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4765,7 +5002,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4948,6 +5185,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5359,6 +5599,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5542,9 +5785,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5563,9 +5803,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5674,6 +5911,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5698,7 +5938,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5725,6 +5965,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5908,6 +6151,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5965,9 +6211,6 @@ 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 ""
@@ -6223,9 +6466,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -6241,9 +6481,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6310,9 +6547,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6379,9 +6613,6 @@ 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 ""
@@ -6448,9 +6679,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6511,6 +6739,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6595,6 +6826,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6736,9 +6970,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6850,9 +7081,6 @@ 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 ""
@@ -7168,7 +7396,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -7219,6 +7447,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -7294,6 +7525,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7675,6 +7909,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7735,6 +7972,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7744,6 +7984,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7777,6 +8020,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8029,6 +8275,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -8122,6 +8371,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8377,6 +8629,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8434,6 +8689,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8473,6 +8737,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8494,6 +8764,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8521,15 +8797,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8545,6 +8821,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8584,6 +8863,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8596,6 +8878,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8605,6 +8893,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8761,9 +9052,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8773,6 +9061,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8788,9 +9079,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8812,6 +9100,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8875,12 +9166,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8941,18 +9238,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -9040,9 +9346,6 @@ 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 ""
@@ -9208,6 +9511,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -9256,6 +9565,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9427,6 +9739,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9478,7 +9811,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9631,6 +9964,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9640,6 +9976,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9661,6 +10000,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9688,9 +10030,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9859,15 +10198,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9940,6 +10288,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -10081,6 +10432,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -10108,7 +10465,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -10153,6 +10522,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10180,7 +10552,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10942,12 +11317,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10978,6 +11359,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -11053,6 +11437,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -11155,6 +11542,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -11218,6 +11608,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -11230,6 +11623,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11371,6 +11767,18 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11401,6 +11809,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11452,6 +11863,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11518,10 +11932,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11536,6 +11953,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11554,9 +11974,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11572,15 +11989,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11590,6 +12007,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11647,12 +12067,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11677,6 +12103,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11740,6 +12169,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11773,9 +12205,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11785,9 +12214,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11842,7 +12277,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12388,7 +12823,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12409,6 +12844,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12445,9 +12883,6 @@ 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 ""
@@ -12472,6 +12907,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12784,6 +13225,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12889,7 +13333,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -13048,6 +13492,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -13057,6 +13507,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -13102,12 +13555,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -13120,6 +13591,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -13132,6 +13606,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -13156,6 +13633,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13573,6 +14053,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13627,9 +14110,6 @@ 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 ""
@@ -13642,7 +14122,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13750,6 +14230,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13774,9 +14257,6 @@ 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 ""
@@ -13798,10 +14278,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13891,6 +14371,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -14011,6 +14494,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -14071,6 +14560,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -14080,12 +14572,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -14095,6 +14593,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -14107,6 +14629,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -14182,27 +14707,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -14221,6 +14752,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -14254,6 +14788,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -14263,12 +14842,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -14302,6 +14899,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -14317,37 +14917,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -14356,6 +14977,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14380,9 +15004,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14482,25 +15103,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14548,6 +15169,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14596,6 +15271,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14812,6 +15490,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -15067,6 +15748,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -15085,6 +15769,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -15214,9 +15904,6 @@ 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 ""
@@ -15247,9 +15934,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -15283,6 +15967,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -15316,6 +16003,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15361,6 +16051,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15436,6 +16129,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -16003,9 +16699,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -16024,6 +16717,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -16057,9 +16753,6 @@ 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 ""
@@ -16069,7 +16762,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -16081,6 +16774,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -16144,6 +16840,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -16264,6 +16963,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -16291,15 +16996,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16537,6 +17317,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16948,6 +17731,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -17263,9 +18067,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -17323,6 +18133,42 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17578,6 +18424,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -18046,6 +18895,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -18076,9 +18928,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -18313,6 +19162,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -18358,9 +19210,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -18370,9 +19219,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18496,19 +19342,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18682,6 +19522,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18778,7 +19621,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18802,9 +19645,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18826,7 +19666,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18850,9 +19690,6 @@ 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 ""
@@ -18868,9 +19705,6 @@ 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 ""
@@ -18880,12 +19714,6 @@ 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 ""
@@ -18910,7 +19738,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -19102,7 +19930,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -19114,9 +19942,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -19219,6 +20044,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -19300,6 +20128,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -19318,6 +20149,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -19348,6 +20182,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -19384,6 +20221,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19612,6 +20455,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19621,6 +20467,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19633,12 +20482,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19843,9 +20698,6 @@ 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 ""
@@ -20539,7 +21391,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20842,6 +21694,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20896,6 +21751,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -21352,6 +22210,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21478,6 +22339,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21589,6 +22453,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21670,6 +22537,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21718,9 +22588,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21934,6 +22801,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -22054,6 +22924,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -22075,9 +22948,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -22105,6 +22984,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -22234,7 +23116,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -22246,6 +23134,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -22264,6 +23164,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -22360,7 +23263,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -22393,6 +23296,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22606,6 +23512,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22762,6 +23671,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22789,6 +23704,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22858,6 +23776,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22867,6 +23788,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22882,6 +23809,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22906,9 +23836,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22918,6 +23845,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22957,6 +23887,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22987,7 +23920,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -23044,9 +23977,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -23128,9 +24058,6 @@ 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] ""
@@ -23239,7 +24166,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -23284,10 +24211,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -23416,6 +24343,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23479,6 +24409,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23518,6 +24454,15 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23698,6 +24643,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23713,7 +24661,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23728,9 +24676,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23824,6 +24769,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23938,6 +24886,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -24073,6 +25024,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -24178,6 +25132,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -24196,9 +25159,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -24349,6 +25318,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -24376,6 +25348,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -24385,9 +25360,6 @@ 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 ""
@@ -24397,6 +25369,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24508,27 +25483,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24763,6 +25729,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24871,6 +25840,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24913,9 +25885,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24991,9 +25960,6 @@ 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 ""
@@ -25057,6 +26023,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -25213,6 +26182,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -25342,6 +26314,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -25357,6 +26332,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -25399,6 +26377,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25483,6 +26467,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25504,6 +26491,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25639,12 +26629,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25672,6 +26668,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25918,15 +26917,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -26011,7 +27025,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -26038,9 +27052,6 @@ 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 ""
@@ -26053,9 +27064,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -26152,6 +27169,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -26179,7 +27202,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -26290,7 +27313,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -26350,6 +27373,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -26362,7 +27388,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -26401,6 +27427,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26509,6 +27538,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26704,6 +27736,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26755,7 +27790,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26779,9 +27814,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26914,6 +27955,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26923,6 +27967,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27475,6 +28522,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27517,7 +28570,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27568,7 +28621,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27697,6 +28750,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27769,16 +28825,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27955,6 +29014,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -28105,6 +29167,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -28330,6 +29395,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -28468,10 +29536,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28498,6 +29569,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28510,9 +29584,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28534,15 +29635,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28597,10 +29710,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28720,6 +29830,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28816,9 +29929,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28972,6 +30082,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -29287,7 +30403,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -29371,6 +30493,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -29467,6 +30598,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29491,13 +30625,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29566,15 +30703,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29587,7 +30724,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29833,10 +30970,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29929,6 +31066,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29950,6 +31090,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29962,10 +31105,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29980,6 +31123,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -30181,6 +31333,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -30193,6 +31348,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -30217,9 +31381,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -30277,9 +31438,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -30382,19 +31540,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -30424,6 +31585,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -30439,6 +31603,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30709,9 +31876,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30838,9 +32002,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30886,9 +32047,6 @@ 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 ""
@@ -30976,6 +32134,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -31234,7 +32395,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -31252,6 +32413,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -31270,6 +32434,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -31306,6 +32473,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -31372,6 +32542,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31861,9 +33034,6 @@ 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 ""
@@ -31876,9 +33046,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31960,6 +33127,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -32140,9 +33310,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -32155,3 +33322,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/as_IN/gitlab.po b/locale/as_IN/gitlab.po
index 9d2e0d1981a..11b3760c590 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-10-02 18:44\n"
+"PO-Revision-Date: 2020-11-03 22:43\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/az_AZ/gitlab.po b/locale/az_AZ/gitlab.po
index 1cbe8715233..b68384c0f79 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-10-02 18:42\n"
+"PO-Revision-Date: 2020-11-03 22:41\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/ba_RU/gitlab.po b/locale/ba_RU/gitlab.po
index b2de628096f..a5fbb55523f 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-10-02 18:44\n"
+"PO-Revision-Date: 2020-11-03 22:44\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -162,6 +162,10 @@ msgid "%d failed"
msgid_plural "%d failed"
msgstr[0] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -186,10 +190,6 @@ msgid "%d issue in this group"
msgid_plural "%d issues in this group"
msgstr[0] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -351,6 +351,14 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+
msgid "%{count} more"
msgstr ""
@@ -389,6 +397,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -434,6 +448,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -560,9 +580,6 @@ 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 ""
@@ -655,7 +672,7 @@ msgstr[0] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -669,6 +686,9 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
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] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -876,9 +896,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -916,6 +933,18 @@ msgstr[0] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -942,6 +971,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -951,13 +983,8 @@ msgstr ""
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1205,6 +1232,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1503,6 +1533,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1656,7 +1689,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1692,10 +1725,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1782,6 +1815,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1806,6 +1842,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1920,6 +1959,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -1929,6 +1983,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -1941,12 +2001,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2001,6 +2079,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2010,6 +2091,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2055,6 +2139,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2079,6 +2166,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2088,6 +2178,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2103,22 +2196,22 @@ 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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2182,10 +2275,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2302,6 +2395,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2311,10 +2413,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2326,19 +2428,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2353,6 +2464,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2362,7 +2479,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2380,7 +2500,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2389,6 +2509,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2455,9 +2596,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2482,6 +2620,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2503,6 +2644,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2524,12 +2668,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2578,6 +2728,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2590,9 +2743,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2620,9 +2779,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2710,9 +2875,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2785,9 +2947,6 @@ 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 ""
@@ -2818,9 +2977,6 @@ 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 ""
@@ -2845,6 +3001,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2869,9 +3028,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2887,6 +3043,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3212,6 +3371,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3459,6 +3621,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3701,7 +3866,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3722,6 +3908,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3740,6 +3929,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3797,9 +3989,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3881,6 +4070,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -3965,6 +4160,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4016,12 +4223,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4040,6 +4256,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4052,6 +4271,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4196,6 +4418,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4232,9 +4457,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4265,7 +4502,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4448,6 +4685,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4859,6 +5099,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5042,9 +5285,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5063,9 +5303,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5174,6 +5411,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5198,7 +5438,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5225,6 +5465,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5408,6 +5651,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5465,9 +5711,6 @@ 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 ""
@@ -5723,9 +5966,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5741,9 +5981,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5810,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5879,9 +6113,6 @@ 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 ""
@@ -5948,9 +6179,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6011,6 +6239,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6095,6 +6326,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6236,9 +6470,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6350,9 +6581,6 @@ 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 ""
@@ -6663,7 +6891,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6714,6 +6942,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6779,6 +7010,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7155,6 +7389,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7215,6 +7452,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7224,6 +7464,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7257,6 +7500,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7504,6 +7750,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7597,6 +7846,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7847,6 +8099,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -7904,6 +8159,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -7943,6 +8207,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -7964,6 +8234,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -7991,15 +8267,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8015,6 +8291,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8054,6 +8333,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8066,6 +8348,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8075,6 +8363,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8231,9 +8522,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8243,6 +8531,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8258,9 +8549,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8282,6 +8570,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8345,12 +8636,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8396,18 +8693,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8480,9 +8786,6 @@ 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 ""
@@ -8648,6 +8951,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8696,6 +9005,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8867,6 +9179,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -8918,7 +9251,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9066,6 +9399,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9075,6 +9411,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9096,6 +9435,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9123,9 +9465,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9294,15 +9633,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9375,6 +9723,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9516,6 +9867,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9543,7 +9900,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9588,6 +9957,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9615,7 +9987,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10377,12 +10752,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10413,6 +10794,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10488,6 +10872,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10590,6 +10977,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10653,6 +11043,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10665,6 +11058,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10801,6 +11197,18 @@ msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10831,6 +11239,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10882,6 +11293,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -10948,10 +11362,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -10966,6 +11383,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -10984,9 +11404,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11002,15 +11419,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11020,6 +11437,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11077,12 +11497,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11107,6 +11533,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11170,6 +11599,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11203,9 +11635,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11215,9 +11644,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11272,7 +11707,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11818,7 +12253,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11839,6 +12274,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11875,9 +12313,6 @@ 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 ""
@@ -11902,6 +12337,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12214,6 +12655,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12319,7 +12763,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12478,6 +12922,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12487,6 +12937,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12532,12 +12985,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12550,6 +13021,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12562,6 +13036,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12586,6 +13063,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -12993,6 +13473,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13047,9 +13530,6 @@ 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 ""
@@ -13062,7 +13542,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13170,6 +13650,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13194,9 +13677,6 @@ 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 ""
@@ -13218,10 +13698,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13301,6 +13781,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13421,6 +13904,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13481,6 +13970,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13490,12 +13982,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13505,6 +14003,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13517,6 +14039,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13592,27 +14117,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13631,6 +14162,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13659,6 +14193,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13668,12 +14247,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13707,6 +14304,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13722,37 +14322,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13761,6 +14382,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13785,9 +14409,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -13887,25 +14508,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -13953,6 +14574,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14001,6 +14676,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14217,6 +14895,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14472,6 +15153,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14490,6 +15174,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14619,9 +15309,6 @@ 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 ""
@@ -14647,9 +15334,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14683,6 +15367,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14716,6 +15403,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14761,6 +15451,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14836,6 +15529,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15368,9 +16064,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15389,6 +16082,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15422,9 +16118,6 @@ 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 ""
@@ -15434,7 +16127,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15446,6 +16139,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15509,6 +16205,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15629,6 +16328,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15656,15 +16361,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -15902,6 +16682,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16303,6 +17086,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16618,9 +17422,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16678,6 +17488,32 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -16933,6 +17769,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17396,6 +18235,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17426,9 +18268,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17663,6 +18502,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17708,9 +18550,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17720,9 +18559,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17841,19 +18677,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18027,6 +18857,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18123,7 +18956,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18147,9 +18980,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18171,7 +19001,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18195,9 +19025,6 @@ 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 ""
@@ -18213,9 +19040,6 @@ 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 ""
@@ -18225,12 +19049,6 @@ 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 ""
@@ -18255,7 +19073,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18447,7 +19265,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18459,9 +19277,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18564,6 +19379,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18645,6 +19463,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18663,6 +19484,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18693,6 +19517,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18729,6 +19556,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -18957,6 +19790,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -18966,6 +19802,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -18978,12 +19817,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19188,9 +20033,6 @@ 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 ""
@@ -19884,7 +20726,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20187,6 +21029,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20241,6 +21086,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20697,6 +21545,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20823,6 +21674,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -20934,6 +21788,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21015,6 +21872,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21058,9 +21918,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21269,6 +22126,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21389,6 +22249,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21410,9 +22273,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21440,6 +22309,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21564,7 +22436,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21576,6 +22454,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21594,6 +22484,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21690,7 +22583,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21723,6 +22616,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -21921,6 +22817,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22072,6 +22971,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22099,6 +23004,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22168,6 +23076,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22177,6 +23088,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22192,6 +23109,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22216,9 +23136,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22228,6 +23145,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22267,6 +23187,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22297,7 +23220,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22354,9 +23277,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22438,9 +23358,6 @@ 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] ""
@@ -22494,7 +23411,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22539,10 +23456,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22671,6 +23588,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22734,6 +23654,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22773,6 +23699,10 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -22953,6 +23883,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -22968,7 +23901,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -22983,9 +23916,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23079,6 +24009,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23193,6 +24126,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23328,6 +24264,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23433,6 +24372,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23451,9 +24399,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23594,6 +24548,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23621,6 +24578,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23630,9 +24590,6 @@ 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 ""
@@ -23642,6 +24599,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23753,27 +24713,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24008,6 +24959,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24116,6 +25070,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24158,9 +25115,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24236,9 +25190,6 @@ 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 ""
@@ -24302,6 +25253,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24458,6 +25412,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24587,6 +25544,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24602,6 +25562,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24644,6 +25607,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24728,6 +25697,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24749,6 +25721,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -24884,12 +25859,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -24917,6 +25898,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25148,15 +26132,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25241,7 +26240,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25263,9 +26262,6 @@ 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 ""
@@ -25278,9 +26274,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25377,6 +26379,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25399,7 +26407,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25510,7 +26518,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25570,6 +26578,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25582,7 +26593,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25621,6 +26632,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25729,6 +26743,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -25924,6 +26941,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -25975,7 +26995,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -25999,9 +27019,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26134,6 +27160,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26143,6 +27172,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26695,6 +27727,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26727,7 +27765,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26778,7 +27816,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -26907,6 +27945,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -26979,16 +28020,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27165,6 +28209,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27315,6 +28362,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27540,6 +28590,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27678,10 +28731,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27708,6 +28764,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27720,9 +28779,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27744,15 +28830,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27807,10 +28905,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -27930,6 +29025,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28026,9 +29124,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28182,6 +29277,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28487,7 +29588,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28571,6 +29678,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28667,6 +29783,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28691,13 +29810,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28766,15 +29888,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28787,7 +29909,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29028,10 +30150,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29124,6 +30246,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29145,6 +30270,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29157,10 +30285,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29175,6 +30303,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29376,6 +30513,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29388,6 +30528,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29412,9 +30561,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29472,9 +30618,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29577,19 +30720,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29619,6 +30765,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29634,6 +30783,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -29899,9 +31051,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30028,9 +31177,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30076,9 +31222,6 @@ 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 ""
@@ -30161,6 +31304,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30394,7 +31540,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30412,6 +31558,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30430,6 +31579,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30466,6 +31618,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30527,6 +31682,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -30996,9 +32154,6 @@ 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 ""
@@ -31011,9 +32166,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31090,6 +32242,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31270,9 +32425,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31285,3 +32437,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index e45c2a55932..1a34d69a3f4 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-10-02 18:46\n"
+"PO-Revision-Date: 2020-11-03 22:46\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr "ОпиÑание"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "Да не Ñе показва повече"
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "Файлове"
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Шаблон за интервала"
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr "ПоÑледна Ñхема"
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr "ÐÑма доÑтатъчно данни"
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr "Коефициент на уÑпех:"
msgid "PipelineCharts|Successful:"
msgstr "УÑпешни:"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "Общо:"
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "Създаване на нов план за Ñхема"
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "Изходен код"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,8 +26677,8 @@ msgstr "Етапът на планиране показва колко е вре
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
-msgstr "Ð’Ñеки впиÑан потребител има доÑтъп до проекта."
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr ""
@@ -25726,6 +26737,9 @@ msgstr "Етапът на преглед и одобрение показва в
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr "Общо време за теÑтване на вÑички подаваниÑ/ÑливаниÑ"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index 06b0aaf5053..ba498acb24e 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-10-02 18:42\n"
+"PO-Revision-Date: 2020-11-03 22:41\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index cab59b3f095..29a8842c251 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-10-02 18:44\n"
+"PO-Revision-Date: 2020-11-03 22:44\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/bs_BA/gitlab.po b/locale/bs_BA/gitlab.po
index 69e80843023..5d095bbb2ea 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-10-02 18:43\n"
+"PO-Revision-Date: 2020-11-03 22:43\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -208,6 +208,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -244,12 +250,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -463,6 +463,18 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{count} more"
msgstr ""
@@ -505,6 +517,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -550,6 +568,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -676,9 +700,6 @@ 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 ""
@@ -781,7 +802,7 @@ msgstr[2] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -799,6 +820,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1018,9 +1042,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1060,6 +1081,18 @@ msgstr[2] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1090,6 +1123,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1099,17 +1135,8 @@ 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] ""
-msgstr[2] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1387,6 +1414,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1687,6 +1717,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1840,7 +1873,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1876,10 +1909,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1966,6 +1999,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1990,6 +2026,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2104,6 +2143,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2113,6 +2167,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2125,12 +2185,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2185,6 +2263,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2194,6 +2275,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2239,6 +2323,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2263,6 +2350,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2272,6 +2362,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2287,22 +2380,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2368,10 +2461,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2488,6 +2581,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2497,10 +2599,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2512,19 +2614,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2539,6 +2650,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2548,7 +2665,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2566,7 +2686,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2575,6 +2695,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2641,9 +2782,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2668,6 +2806,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2689,6 +2830,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2710,12 +2854,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2764,6 +2914,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2776,9 +2929,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2806,9 +2965,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2896,9 +3061,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2971,9 +3133,6 @@ 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 ""
@@ -3004,9 +3163,6 @@ 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 ""
@@ -3031,6 +3187,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3055,9 +3214,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3073,6 +3229,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3406,6 +3565,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3655,6 +3817,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3901,7 +4066,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3922,6 +4108,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3940,6 +4129,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3997,9 +4189,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4081,6 +4270,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4165,6 +4360,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4216,12 +4423,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4240,6 +4456,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4252,6 +4471,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4396,6 +4618,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4432,9 +4657,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4465,7 +4702,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4648,6 +4885,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5059,6 +5299,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5242,9 +5485,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5263,9 +5503,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5374,6 +5611,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5398,8 +5638,8 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
-msgstr "Zatvoreno: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
+msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
@@ -5425,6 +5665,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5608,6 +5851,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5665,9 +5911,6 @@ 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 ""
@@ -5923,9 +6166,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5941,9 +6181,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6010,9 +6247,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6079,9 +6313,6 @@ 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 ""
@@ -6148,9 +6379,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6211,6 +6439,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6295,6 +6526,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6436,9 +6670,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6550,9 +6781,6 @@ 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 ""
@@ -6865,7 +7093,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6916,6 +7144,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6985,6 +7216,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7363,6 +7597,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7423,6 +7660,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7432,6 +7672,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7465,6 +7708,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7714,6 +7960,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7807,6 +8056,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8059,6 +8311,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8116,6 +8371,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8155,6 +8419,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8176,6 +8446,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8203,15 +8479,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8227,6 +8503,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8266,6 +8545,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8278,6 +8560,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8287,6 +8575,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8443,9 +8734,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8455,6 +8743,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8470,9 +8761,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8494,6 +8782,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8557,12 +8848,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8614,18 +8911,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8704,9 +9010,6 @@ 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 ""
@@ -8872,6 +9175,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8920,6 +9229,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9091,6 +9403,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9142,7 +9475,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9292,6 +9625,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9301,6 +9637,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9322,6 +9661,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9349,9 +9691,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9520,15 +9859,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9601,6 +9949,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9742,6 +10093,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9769,7 +10126,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9814,6 +10183,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9841,7 +10213,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10603,12 +10978,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10639,6 +11020,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10714,6 +11098,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10816,6 +11203,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10879,6 +11269,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10891,6 +11284,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11029,6 +11425,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11059,6 +11467,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11110,6 +11521,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11176,10 +11590,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11194,6 +11611,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11212,9 +11632,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11230,15 +11647,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11248,6 +11665,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11305,12 +11725,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11335,6 +11761,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11398,6 +11827,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11431,9 +11863,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11443,9 +11872,15 @@ msgstr "Prvi dan sedmice"
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11500,7 +11935,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12046,7 +12481,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12067,6 +12502,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12103,9 +12541,6 @@ 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 ""
@@ -12130,6 +12565,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12442,6 +12883,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12547,7 +12991,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12706,6 +13150,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12715,6 +13165,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12760,12 +13213,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12778,6 +13249,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12790,6 +13264,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12814,6 +13291,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13225,6 +13705,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13279,9 +13762,6 @@ 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 ""
@@ -13294,7 +13774,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13402,6 +13882,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13426,9 +13909,6 @@ 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 ""
@@ -13450,10 +13930,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13537,6 +14017,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13657,6 +14140,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13717,6 +14206,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13726,12 +14218,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13741,6 +14239,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13753,6 +14275,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13828,27 +14353,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13867,6 +14398,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13897,6 +14431,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13906,12 +14485,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13945,6 +14542,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13960,37 +14560,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13999,6 +14620,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14023,9 +14647,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14125,25 +14746,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14191,6 +14812,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14239,6 +14914,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14455,6 +15133,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14710,6 +15391,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14728,6 +15412,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14857,9 +15547,6 @@ 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 ""
@@ -14887,9 +15574,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14923,6 +15607,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14956,6 +15643,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15001,6 +15691,9 @@ msgstr ""
msgid "Learn more"
msgstr "Saznaj više"
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15076,6 +15769,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15622,9 +16318,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15643,6 +16336,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15676,9 +16372,6 @@ 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 ""
@@ -15688,7 +16381,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15700,6 +16393,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15763,6 +16459,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15883,6 +16582,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15910,15 +16615,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16156,6 +16936,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16561,6 +17344,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16876,9 +17680,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16936,6 +17746,36 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17191,6 +18031,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17656,6 +18499,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17686,9 +18532,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17923,6 +18766,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17968,9 +18814,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17980,9 +18823,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18103,19 +18943,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18289,6 +19123,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18385,7 +19222,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18409,9 +19246,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18433,7 +19267,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18457,9 +19291,6 @@ 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 ""
@@ -18475,9 +19306,6 @@ 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 ""
@@ -18487,12 +19315,6 @@ 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 ""
@@ -18517,7 +19339,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18709,7 +19531,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18721,9 +19543,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18826,6 +19645,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18907,6 +19729,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18925,6 +19750,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18955,6 +19783,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18991,6 +19822,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19219,6 +20056,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19228,6 +20068,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19240,12 +20083,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19450,9 +20299,6 @@ 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 ""
@@ -20146,7 +20992,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20449,6 +21295,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20503,6 +21352,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20959,6 +21811,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21085,6 +21940,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21196,6 +22054,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21277,6 +22138,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21322,9 +22186,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21535,6 +22396,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21655,6 +22519,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21676,9 +22543,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21706,6 +22579,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21832,7 +22708,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21844,6 +22726,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21862,6 +22756,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21958,7 +22855,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21991,6 +22888,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22195,6 +23095,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22348,6 +23251,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22375,6 +23284,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22444,6 +23356,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22453,6 +23368,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr "Subota"
@@ -22468,6 +23389,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22492,9 +23416,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22504,6 +23425,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22543,6 +23467,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22573,7 +23500,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22630,9 +23557,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22714,9 +23638,6 @@ 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] ""
@@ -22792,7 +23713,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22837,10 +23758,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22969,6 +23890,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23032,6 +23956,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23071,6 +24001,12 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23251,6 +24187,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23266,7 +24205,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23281,9 +24220,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23377,6 +24313,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23491,6 +24430,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23626,6 +24568,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23731,6 +24676,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23749,9 +24703,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23896,6 +24856,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23923,6 +24886,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23932,9 +24898,6 @@ 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 ""
@@ -23944,6 +24907,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24055,27 +25021,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24310,6 +25267,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24418,6 +25378,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24460,9 +25423,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24538,9 +25498,6 @@ 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 ""
@@ -24604,6 +25561,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24760,6 +25720,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24889,6 +25852,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24904,6 +25870,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24946,6 +25915,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25030,6 +26005,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25051,6 +26029,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25186,12 +26167,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25219,6 +26206,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25456,15 +26446,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25549,7 +26554,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25573,9 +26578,6 @@ 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 ""
@@ -25588,9 +26590,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25687,6 +26695,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25711,7 +26725,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25822,7 +26836,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25882,6 +26896,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25894,7 +26911,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25933,6 +26950,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26041,6 +27061,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26236,6 +27259,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26287,7 +27313,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26311,9 +27337,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26446,6 +27478,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26455,6 +27490,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27007,6 +28045,12 @@ msgstr "maloprije"
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27043,7 +28087,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27094,7 +28138,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27223,6 +28267,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27295,16 +28342,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27481,6 +28531,9 @@ msgstr ""
msgid "Tuesday"
msgstr "Utorak"
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27631,6 +28684,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27856,6 +28912,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27994,10 +29053,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28024,6 +29086,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28036,9 +29101,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28060,15 +29152,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28123,10 +29227,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28246,6 +29347,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28342,9 +29446,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28498,6 +29599,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28807,7 +29914,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28891,6 +30004,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28987,6 +30109,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29011,13 +30136,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29086,15 +30214,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29107,7 +30235,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29350,10 +30478,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29446,6 +30574,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29467,6 +30598,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29479,10 +30613,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29497,6 +30631,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29698,6 +30841,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29710,6 +30856,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29734,9 +30889,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29794,9 +30946,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29899,19 +31048,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29941,6 +31093,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29956,6 +31111,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30223,9 +31381,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30352,9 +31507,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30400,9 +31552,6 @@ 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 ""
@@ -30487,6 +31636,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr "komentar"
@@ -30730,7 +31882,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30748,6 +31900,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30766,6 +31921,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30802,6 +31960,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30865,6 +32026,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31342,9 +32506,6 @@ 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 ""
@@ -31357,9 +32518,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31438,6 +32596,9 @@ msgstr ""
msgid "sign in"
msgstr "prijavi se"
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31618,9 +32779,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31633,3 +32791,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index 77eb61ca568..46d9c3feec8 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-10-02 18:46\n"
+"PO-Revision-Date: 2020-11-03 22:46\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr "%{count} més"
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} GB"
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr "Afegeix una taula"
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Bloca l'usuari"
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr "Tots els usuaris"
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr "Tots els entorns"
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr "Incidències tancades"
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr "Suprimeix la llista"
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr "Descripció"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr "Domini"
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "No ho mostris més"
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "feb."
@@ -11191,12 +11611,18 @@ msgstr "Plantilles de fitxers"
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "Fitxers"
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr "Filtra..."
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr "Versió del Git"
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "Historial"
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr "Mai"
msgid "New"
msgstr "Nou"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr "Aplicació nova"
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index 26c41224f85..cb561eaa887 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-10-02 18:46\n"
+"PO-Revision-Date: 2020-11-03 22:46\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -231,6 +231,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -273,13 +280,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -519,6 +519,20 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} more"
msgstr ""
@@ -563,6 +577,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -608,6 +628,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -734,9 +760,6 @@ 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 ""
@@ -844,7 +867,7 @@ msgstr[3] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -864,6 +887,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1089,9 +1115,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1132,6 +1155,18 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1164,6 +1199,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1173,19 +1211,8 @@ 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] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1478,6 +1505,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1779,6 +1809,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1932,7 +1965,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1968,10 +2001,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -2058,6 +2091,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -2082,6 +2118,9 @@ msgstr "Zastavení úloh selhalo"
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2196,6 +2235,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2205,6 +2259,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2217,12 +2277,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Blokovat uživatele"
@@ -2277,6 +2355,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2286,6 +2367,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2331,6 +2415,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2355,6 +2442,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2364,6 +2454,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2379,22 +2472,22 @@ 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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2461,10 +2554,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2581,6 +2674,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2590,10 +2692,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2605,19 +2707,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2632,6 +2743,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2641,7 +2758,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2659,7 +2779,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2668,6 +2788,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2734,9 +2875,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2761,6 +2899,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2782,6 +2923,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2803,12 +2947,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2857,6 +3007,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2869,9 +3022,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2899,9 +3058,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2989,9 +3154,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -3064,9 +3226,6 @@ 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 ""
@@ -3097,9 +3256,6 @@ 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 ""
@@ -3124,6 +3280,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3148,9 +3307,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3166,6 +3322,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3503,6 +3662,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3753,6 +3915,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -4001,7 +4166,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -4022,6 +4208,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -4040,6 +4229,9 @@ msgstr ""
msgid "Available"
msgstr "K dispozici"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -4097,9 +4289,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4181,6 +4370,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4265,6 +4460,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4316,12 +4523,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4340,6 +4556,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4352,6 +4571,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4496,6 +4718,9 @@ msgstr "nastavení projektu"
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4532,9 +4757,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4565,7 +4802,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4748,6 +4985,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5159,6 +5399,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5342,9 +5585,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5363,9 +5603,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5474,6 +5711,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5498,7 +5738,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5525,6 +5765,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5708,6 +5951,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5765,9 +6011,6 @@ 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 ""
@@ -6023,9 +6266,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -6041,9 +6281,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6110,9 +6347,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6179,9 +6413,6 @@ 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 ""
@@ -6248,9 +6479,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6311,6 +6539,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6395,6 +6626,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6536,9 +6770,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6650,9 +6881,6 @@ 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 ""
@@ -6966,7 +7194,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -7017,6 +7245,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -7088,6 +7319,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7467,6 +7701,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7527,6 +7764,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7536,6 +7776,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7569,6 +7812,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7819,6 +8065,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7912,6 +8161,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8165,6 +8417,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8222,6 +8477,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8261,6 +8525,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8282,6 +8552,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8309,15 +8585,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8333,6 +8609,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8372,6 +8651,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8384,6 +8666,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8393,6 +8681,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8549,9 +8840,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8561,6 +8849,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8576,9 +8867,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8600,6 +8888,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8663,12 +8954,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8723,18 +9020,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8816,9 +9122,6 @@ 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 ""
@@ -8984,6 +9287,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -9032,6 +9341,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9203,6 +9515,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9254,7 +9587,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9405,6 +9738,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9414,6 +9750,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9435,6 +9774,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9462,9 +9804,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9633,15 +9972,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9714,6 +10062,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9855,6 +10206,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9882,7 +10239,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9927,6 +10296,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9954,7 +10326,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10716,12 +11091,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10752,6 +11133,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10827,6 +11211,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10929,6 +11316,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10992,6 +11382,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -11004,6 +11397,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11143,6 +11539,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11173,6 +11581,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11224,6 +11635,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11290,10 +11704,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11308,6 +11725,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11326,9 +11746,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11344,15 +11761,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11362,6 +11779,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11419,12 +11839,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11449,6 +11875,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11512,6 +11941,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11545,9 +11977,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11557,9 +11986,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11614,7 +12049,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12160,7 +12595,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12181,6 +12616,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12217,9 +12655,6 @@ 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 ""
@@ -12244,6 +12679,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12556,6 +12997,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12661,7 +13105,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12820,6 +13264,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12829,6 +13279,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12874,12 +13327,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12892,6 +13363,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12904,6 +13378,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12928,6 +13405,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13341,6 +13821,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13395,9 +13878,6 @@ 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 ""
@@ -13410,7 +13890,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13518,6 +13998,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13542,9 +14025,6 @@ 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 ""
@@ -13566,10 +14046,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13655,6 +14135,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13775,6 +14258,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13835,6 +14324,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13844,12 +14336,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13859,6 +14357,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13871,6 +14393,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13946,27 +14471,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13985,6 +14516,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -14016,6 +14550,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -14025,12 +14604,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -14064,6 +14661,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -14079,37 +14679,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -14118,6 +14739,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14142,9 +14766,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14244,25 +14865,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14310,6 +14931,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14358,6 +15033,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14574,6 +15252,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14829,6 +15510,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14847,6 +15531,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14976,9 +15666,6 @@ 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 ""
@@ -15007,9 +15694,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -15043,6 +15727,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -15076,6 +15763,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15121,6 +15811,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15196,6 +15889,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15749,9 +16445,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15770,6 +16463,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15803,9 +16499,6 @@ 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 ""
@@ -15815,7 +16508,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15827,6 +16520,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15890,6 +16586,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -16010,6 +16709,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -16037,15 +16742,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16283,6 +17063,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16690,6 +17473,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -17005,9 +17809,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -17065,6 +17875,38 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17320,6 +18162,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17786,6 +18631,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17816,9 +18664,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -18053,6 +18898,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -18098,9 +18946,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -18110,9 +18955,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18234,19 +19076,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18420,6 +19256,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18516,7 +19355,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18540,9 +19379,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18564,7 +19400,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18588,9 +19424,6 @@ 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 ""
@@ -18606,9 +19439,6 @@ 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 ""
@@ -18618,12 +19448,6 @@ 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 ""
@@ -18648,7 +19472,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18840,7 +19664,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18852,9 +19676,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18957,6 +19778,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -19038,6 +19862,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -19056,6 +19883,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -19086,6 +19916,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -19122,6 +19955,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19350,6 +20189,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19359,6 +20201,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19371,12 +20216,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19581,9 +20432,6 @@ 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 ""
@@ -20277,7 +21125,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20580,6 +21428,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20634,6 +21485,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -21090,6 +21944,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21216,6 +22073,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21327,6 +22187,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21408,6 +22271,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21454,9 +22320,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21668,6 +22531,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21788,6 +22654,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21809,9 +22678,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21839,6 +22714,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21966,7 +22844,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21978,6 +22862,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21996,6 +22892,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -22092,7 +22991,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -22125,6 +23024,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22332,6 +23234,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22486,6 +23391,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22513,6 +23424,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22582,6 +23496,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22591,6 +23508,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22606,6 +23529,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22630,9 +23556,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22642,6 +23565,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22681,6 +23607,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22711,7 +23640,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22768,9 +23697,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22852,9 +23778,6 @@ 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] ""
@@ -22941,7 +23864,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22986,10 +23909,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -23118,6 +24041,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23181,6 +24107,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23220,6 +24152,13 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23400,6 +24339,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23415,7 +24357,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23430,9 +24372,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23526,6 +24465,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23640,6 +24582,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23775,6 +24720,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23880,6 +24828,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23898,9 +24855,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -24047,6 +25010,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -24074,6 +25040,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -24083,9 +25052,6 @@ 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 ""
@@ -24095,6 +25061,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24206,27 +25175,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24461,6 +25421,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24569,6 +25532,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24611,9 +25577,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24689,9 +25652,6 @@ 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 ""
@@ -24755,6 +25715,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24911,6 +25874,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -25040,6 +26006,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -25055,6 +26024,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -25097,6 +26069,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25181,6 +26159,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25202,6 +26183,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25337,12 +26321,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25370,6 +26360,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25610,15 +26603,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25703,7 +26711,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25728,9 +26736,6 @@ 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 ""
@@ -25743,9 +26748,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25842,6 +26853,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25867,7 +26884,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25978,7 +26995,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -26038,6 +27055,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -26050,7 +27070,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -26089,6 +27109,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26197,6 +27220,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26392,6 +27418,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26443,7 +27472,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26467,9 +27496,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26602,6 +27637,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26611,6 +27649,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27163,6 +28204,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27201,7 +28248,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27252,7 +28299,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27381,6 +28428,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27453,16 +28503,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27639,6 +28692,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27789,6 +28845,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -28014,6 +29073,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -28152,10 +29214,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28182,6 +29247,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28194,9 +29262,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28218,15 +29313,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28281,10 +29388,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28404,6 +29508,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28500,9 +29607,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28656,6 +29760,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28967,7 +30077,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -29051,6 +30167,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -29147,6 +30272,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29171,13 +30299,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29246,15 +30377,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29267,7 +30398,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29511,10 +30642,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29607,6 +30738,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29628,6 +30762,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29640,10 +30777,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29658,6 +30795,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29859,6 +31005,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29871,6 +31020,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29895,9 +31053,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29955,9 +31110,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -30060,19 +31212,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -30102,6 +31257,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -30117,6 +31275,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30385,9 +31546,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30514,9 +31672,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30562,9 +31717,6 @@ 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 ""
@@ -30650,6 +31802,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30898,7 +32053,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30916,6 +32071,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30934,6 +32092,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30970,6 +32131,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -31034,6 +32198,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31515,9 +32682,6 @@ 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 ""
@@ -31530,9 +32694,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31612,6 +32773,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31792,9 +32956,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31807,3 +32968,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index 20a9e54653f..be8ead5547c 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-10-02 18:41\n"
+"PO-Revision-Date: 2020-11-03 22:39\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -277,6 +277,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -331,15 +340,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -631,6 +631,24 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{count} more"
msgstr ""
@@ -679,6 +697,12 @@ 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 "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -724,6 +748,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -850,9 +880,6 @@ 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 ""
@@ -970,7 +997,7 @@ msgstr[5] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -994,6 +1021,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1231,9 +1261,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1276,6 +1303,18 @@ msgstr[5] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1312,6 +1351,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1321,23 +1363,8 @@ 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] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1660,6 +1687,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1963,6 +1993,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -2116,7 +2149,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -2152,10 +2185,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -2242,6 +2275,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -2266,6 +2302,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2380,6 +2419,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2389,6 +2443,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2401,12 +2461,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2461,6 +2539,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2470,6 +2551,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2515,6 +2599,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2539,6 +2626,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2548,6 +2638,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2563,22 +2656,22 @@ 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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2647,10 +2740,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2767,6 +2860,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2776,10 +2878,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2791,19 +2893,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2818,6 +2929,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2827,7 +2944,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2845,7 +2965,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2854,6 +2974,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2920,9 +3061,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2947,6 +3085,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2968,6 +3109,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2989,12 +3133,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -3043,6 +3193,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -3055,9 +3208,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -3085,9 +3244,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -3175,9 +3340,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -3250,9 +3412,6 @@ 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 ""
@@ -3283,9 +3442,6 @@ 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 ""
@@ -3310,6 +3466,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3334,9 +3493,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3352,6 +3508,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3697,6 +3856,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3949,6 +4111,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -4201,7 +4366,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -4222,6 +4408,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -4240,6 +4429,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -4297,9 +4489,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4381,6 +4570,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4465,6 +4660,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4516,12 +4723,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4540,6 +4756,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4552,6 +4771,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4696,6 +4918,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4732,9 +4957,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4765,7 +5002,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4948,6 +5185,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5359,6 +5599,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5542,9 +5785,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5563,9 +5803,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5674,6 +5911,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5698,7 +5938,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5725,6 +5965,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5908,6 +6151,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5965,9 +6211,6 @@ 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 ""
@@ -6223,9 +6466,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -6241,9 +6481,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6310,9 +6547,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6379,9 +6613,6 @@ 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 ""
@@ -6448,9 +6679,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6511,6 +6739,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6595,6 +6826,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6736,9 +6970,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6850,9 +7081,6 @@ 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 ""
@@ -7168,7 +7396,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -7219,6 +7447,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -7294,6 +7525,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7675,6 +7909,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7735,6 +7972,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7744,6 +7984,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7777,6 +8020,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8029,6 +8275,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -8122,6 +8371,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8377,6 +8629,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8434,6 +8689,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8473,6 +8737,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8494,6 +8764,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8521,15 +8797,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8545,6 +8821,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8584,6 +8863,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8596,6 +8878,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8605,6 +8893,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8761,9 +9052,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8773,6 +9061,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8788,9 +9079,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8812,6 +9100,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8875,12 +9166,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8941,18 +9238,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -9040,9 +9346,6 @@ 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 ""
@@ -9208,6 +9511,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -9256,6 +9565,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9427,6 +9739,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9478,7 +9811,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9631,6 +9964,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9640,6 +9976,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9661,6 +10000,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9688,9 +10030,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9859,15 +10198,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9940,6 +10288,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -10081,6 +10432,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -10108,7 +10465,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -10153,6 +10522,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10180,7 +10552,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10942,12 +11317,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10978,6 +11359,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -11053,6 +11437,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -11155,6 +11542,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -11218,6 +11608,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -11230,6 +11623,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11371,6 +11767,18 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11401,6 +11809,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11452,6 +11863,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11518,10 +11932,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11536,6 +11953,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11554,9 +11974,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11572,15 +11989,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11590,6 +12007,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11647,12 +12067,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11677,6 +12103,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11740,6 +12169,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11773,9 +12205,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11785,9 +12214,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11842,7 +12277,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12388,7 +12823,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12409,6 +12844,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12445,9 +12883,6 @@ 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 ""
@@ -12472,6 +12907,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12784,6 +13225,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12889,7 +13333,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -13048,6 +13492,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -13057,6 +13507,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -13102,12 +13555,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -13120,6 +13591,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -13132,6 +13606,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -13156,6 +13633,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13573,6 +14053,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13627,9 +14110,6 @@ 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 ""
@@ -13642,7 +14122,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13750,6 +14230,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13774,9 +14257,6 @@ 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 ""
@@ -13798,10 +14278,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13891,6 +14371,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -14011,6 +14494,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -14071,6 +14560,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -14080,12 +14572,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -14095,6 +14593,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -14107,6 +14629,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -14182,27 +14707,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -14221,6 +14752,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -14254,6 +14788,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -14263,12 +14842,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -14302,6 +14899,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -14317,37 +14917,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -14356,6 +14977,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14380,9 +15004,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14482,25 +15103,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14548,6 +15169,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14596,6 +15271,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14812,6 +15490,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -15067,6 +15748,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -15085,6 +15769,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -15214,9 +15904,6 @@ 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 ""
@@ -15247,9 +15934,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -15283,6 +15967,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -15316,6 +16003,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15361,6 +16051,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15436,6 +16129,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -16003,9 +16699,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -16024,6 +16717,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -16057,9 +16753,6 @@ 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 ""
@@ -16069,7 +16762,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -16081,6 +16774,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -16144,6 +16840,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -16264,6 +16963,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -16291,15 +16996,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16537,6 +17317,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16948,6 +17731,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -17263,9 +18067,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -17323,6 +18133,42 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17578,6 +18424,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -18046,6 +18895,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -18076,9 +18928,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -18313,6 +19162,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -18358,9 +19210,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -18370,9 +19219,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18496,19 +19342,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18682,6 +19522,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18778,7 +19621,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18802,9 +19645,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18826,7 +19666,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18850,9 +19690,6 @@ 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 ""
@@ -18868,9 +19705,6 @@ 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 ""
@@ -18880,12 +19714,6 @@ 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 ""
@@ -18910,7 +19738,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -19102,7 +19930,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -19114,9 +19942,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -19219,6 +20044,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -19300,6 +20128,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -19318,6 +20149,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -19348,6 +20182,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -19384,6 +20221,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19612,6 +20455,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19621,6 +20467,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19633,12 +20482,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19843,9 +20698,6 @@ 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 ""
@@ -20539,7 +21391,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20842,6 +21694,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20896,6 +21751,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -21352,6 +22210,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21478,6 +22339,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21589,6 +22453,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21670,6 +22537,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21718,9 +22588,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21934,6 +22801,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -22054,6 +22924,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -22075,9 +22948,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -22105,6 +22984,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -22234,7 +23116,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -22246,6 +23134,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -22264,6 +23164,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -22360,7 +23263,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -22393,6 +23296,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22606,6 +23512,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22762,6 +23671,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22789,6 +23704,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22858,6 +23776,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22867,6 +23788,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22882,6 +23809,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22906,9 +23836,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22918,6 +23845,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22957,6 +23887,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22987,7 +23920,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -23044,9 +23977,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -23128,9 +24058,6 @@ 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] ""
@@ -23239,7 +24166,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -23284,10 +24211,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -23416,6 +24343,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23479,6 +24409,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23518,6 +24454,15 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23698,6 +24643,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23713,7 +24661,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23728,9 +24676,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23824,6 +24769,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23938,6 +24886,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -24073,6 +25024,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -24178,6 +25132,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -24196,9 +25159,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -24349,6 +25318,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -24376,6 +25348,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -24385,9 +25360,6 @@ 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 ""
@@ -24397,6 +25369,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24508,27 +25483,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24763,6 +25729,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24871,6 +25840,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24913,9 +25885,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24991,9 +25960,6 @@ 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 ""
@@ -25057,6 +26023,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -25213,6 +26182,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -25342,6 +26314,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -25357,6 +26332,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -25399,6 +26377,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25483,6 +26467,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25504,6 +26491,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25639,12 +26629,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25672,6 +26668,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25918,15 +26917,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -26011,7 +27025,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -26038,9 +27052,6 @@ 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 ""
@@ -26053,9 +27064,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -26152,6 +27169,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -26179,7 +27202,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -26290,7 +27313,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -26350,6 +27373,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -26362,7 +27388,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -26401,6 +27427,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26509,6 +27538,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26704,6 +27736,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26755,7 +27790,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26779,9 +27814,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26914,6 +27955,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26923,6 +27967,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27475,6 +28522,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27517,7 +28570,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27568,7 +28621,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27697,6 +28750,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27769,16 +28825,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27955,6 +29014,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -28105,6 +29167,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -28330,6 +29395,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -28468,10 +29536,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28498,6 +29569,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28510,9 +29584,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28534,15 +29635,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28597,10 +29710,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28720,6 +29830,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28816,9 +29929,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28972,6 +30082,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -29287,7 +30403,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -29371,6 +30493,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -29467,6 +30598,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29491,13 +30625,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29566,15 +30703,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29587,7 +30724,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29833,10 +30970,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29929,6 +31066,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29950,6 +31090,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29962,10 +31105,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29980,6 +31123,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -30181,6 +31333,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -30193,6 +31348,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -30217,9 +31381,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -30277,9 +31438,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -30382,19 +31540,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -30424,6 +31585,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -30439,6 +31603,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30709,9 +31876,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30838,9 +32002,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30886,9 +32047,6 @@ 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 ""
@@ -30976,6 +32134,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -31234,7 +32395,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -31252,6 +32413,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -31270,6 +32434,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -31306,6 +32473,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -31372,6 +32542,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31861,9 +33034,6 @@ 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 ""
@@ -31876,9 +33046,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31960,6 +33127,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -32140,9 +33310,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -32155,3 +33322,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index 2f8727463ef..e0666e44dfc 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-10-02 18:47\n"
+"PO-Revision-Date: 2020-11-03 22:46\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index 73d9e05089c..0a5e382d6fc 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-10-02 18:47\n"
+"PO-Revision-Date: 2020-11-03 22:47\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d festes Testergebnis"
@@ -215,11 +220,6 @@ msgid_plural "%d issues in this group"
msgstr[0] ""
msgstr[1] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d Ticket ausgewählt"
-msgstr[1] "%d Tickets ausgewählt"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -407,6 +407,16 @@ msgstr "%{count} Zustimmungen von %{name}"
msgid "%{count} files touched"
msgstr "%{count} Dateien verändert"
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr "%{count} weitere"
@@ -447,6 +457,12 @@ 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 "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr "%{group_name} nutzt Accounts, die von einer Gruppe verwaltet werden. Du
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 "%{name} enthielt %{resultsString}"
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -947,9 +969,6 @@ msgstr "(Fortschritt überprüfen)"
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr "(externe Quelle)"
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr "- weniger anzeigen"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ msgstr "0 für unbegrenzt"
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "1 %{type} Zusatz"
-msgstr[1] "%{count} %{type} Zusätze"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "1 %{type} Änderung"
-msgstr[1] "%{count} %{type} Änderungen"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr "Ein(e) Benutzer(in) mit Schreibzugriff auf den Quellbranch hat diese Opt
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr "Tabelle hinzufügen"
msgid "Add a task list"
msgstr "Eine Aufgabenliste hinzufügen"
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Füge zusätzlichen Text hinzu, der in jeglicher E-Mail-Kommunikation angezeigt wird. Maximal %{character_limit} Zeichen"
@@ -1748,8 +1781,8 @@ msgstr "%{epic_ref} als untergeordnetes Epic hinzugefügt."
msgid "Added %{label_references} %{label_text}."
msgstr "%{label_references} %{label_text} hinzugefügt."
-msgid "Added a To Do."
-msgstr "To Do hinzugefügt."
+msgid "Added a to do."
+msgstr ""
msgid "Added an issue to an epic."
msgstr "Ein Ticket zu einem Epic hinzugefügt."
@@ -1784,12 +1817,12 @@ msgstr "Fügt %{epic_ref} als Sub-Epic hinzu."
msgid "Adds %{labels} %{label_text}."
msgstr "Fügt %{labels} %{label_text} hinzu."
-msgid "Adds a To Do."
-msgstr "To-Do hinzufügen."
-
msgid "Adds a Zoom meeting"
msgstr "Fügt ein Zoom-Meeting hinzu"
+msgid "Adds a to do."
+msgstr ""
+
msgid "Adds an issue to an epic."
msgstr "Fügt ein Ticket zu einem Epic hinzu."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr "Inhaber(in)"
@@ -1898,6 +1934,9 @@ msgstr "Stoppen von Jobs ist fehlgeschlagen"
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr "SSH-Schlüssel"
msgid "AdminStatistics|Snippets"
msgstr "Codeausschnitte"
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr "2FA deaktiviert"
@@ -2021,6 +2075,12 @@ msgstr "2FA aktiviert"
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr "Aktiv"
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr "Admins"
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr "Blockieren"
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Benutzer(in) blockieren"
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr "Das bist du!"
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr "Neue(r) Benutzer(in)"
@@ -2102,6 +2183,9 @@ msgstr "Keine Benutzer(innen) gefunden"
msgid "AdminUsers|Owned groups will be left"
msgstr "Eigene Gruppen werden verlassen"
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr "Persönliche Projekte werden verlassen"
@@ -2147,6 +2231,9 @@ msgstr "Diese(r) Benutzer(in) kann keine Slash-Befehle verwenden"
msgid "AdminUsers|The user will not receive any notifications"
msgstr "Diese(r) Benutzer(in) erhält keine Benachrichtigungen"
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Zur Bestätigung %{projectName} eingeben"
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr "Erweitert"
@@ -2195,22 +2288,22 @@ msgstr ""
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "Erweiterte Berechtigungen, Large File Storage und Einstellungen zur Zwei-Faktor-Authentifizierung."
-msgid "Advanced search functionality"
-msgstr "Erweiterte Suchfunktion"
-
msgid "After a successful password update you will be redirected to login screen."
msgstr "Nach dem erfolgreichen Ändern des Passwortes wirst du zum Anmeldebildschirm weitergeleitet."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Nach einer erfolgreichen Passwortaktualisierung wirst du zur Anmeldeseite weitergeleitet, wo du dich mit deinem neuen Passwort anmelden kannst."
-msgid "After that, you will not to be able to use merge approvals or code quality as well as many other features."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr "Alarme"
msgid "Alerts endpoint"
msgstr "Alarm-Endpunkt"
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr "Algorithmus"
@@ -2548,9 +2689,6 @@ msgstr "Alle Sicherheits-Scans sind aktiviert, weil %{linkStart}Auto DevOps%{lin
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr "Alle Benutzer(innen)"
-
msgid "All users must have a name."
msgstr "Alle Benutzer(innen) benötigen einen Namen."
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "Erlaube es Projekten in dieser Gruppe Git LFS zu verwenden"
@@ -2596,6 +2737,9 @@ msgstr "Anfragen an das lokale Netzwerk von System-Hooks erlauben"
msgid "Allow requests to the local network from web hooks and services"
msgstr "Anfragen an das lokale Netzwerk von Web-Hooks und Diensten erlauben"
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr "Diesem Schlüssel auch erlauben, in das Repository zu pushen? (Normalerweise ist nur Pull-Zugriff erlaubt)"
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr "Scheitern erlaubt"
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Ermöglicht dir das Hinzufügen und Verwalten von Kubernetes-Clustern."
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ 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 "Bei einem leeren GitLab-Benutzerfeld wird der vollständigen Namen des FogBugz-Benutzers/-Benutzerin (z. B. \"Von John Smith\") in die Beschreibung aller Tickets und Kommentare eingefügt. Außerdem werden diese Tickets und Kommentare auch mit dem/der Projektersteller(in) assoziiert und/oder ihm/ihr zugewiesen."
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "Es ist ein Fehler aufgetreten"
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr "Bei der Vorschau des Blobs ist ein Fehler aufgetreten"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "Beim Umschalten des Benachrichtigungs-Abonnements trat ein Fehler auf"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "Beim Aktualisieren der Ticket-Gewichtung ist ein Fehler aufgetreten"
@@ -2803,9 +2968,6 @@ 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 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."
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ msgstr ""
msgid "An error occurred while loading the pipelines jobs."
msgstr ""
-msgid "An error occurred while loading the subscription details."
-msgstr "Beim Laden der Abonnementdetails ist ein Fehler aufgetreten."
-
msgid "An error occurred while making the request."
msgstr "Beim Bearbeiten der Anfrage ist ein Fehler aufgetreten."
@@ -2938,6 +3094,9 @@ msgstr "Beim Rendern der Vorschau der Broadcast-Nachricht ist ein Fehler aufgetr
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr "Beim Umordnen von Tickets ist ein Fehler aufgetreten."
@@ -2962,9 +3121,6 @@ msgstr "Beim Speichern des LDAP-Ãœberschreibungsstatus ist ein Fehler aufgetrete
msgid "An error occurred while saving assignees"
msgstr "Beim Speichern der Zuweisungen ist ein Fehler aufgetreten"
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr "Beim Abonnieren von Benachrichtigungen ist ein Fehler aufgetreten."
@@ -2980,6 +3136,9 @@ msgstr "Beim Abbestellen der Benachrichtigungen ist ein Fehler aufgetreten."
msgid "An error occurred while updating approvers"
msgstr "Beim Ändern der Genehmigungsberechtigten ist ein Fehler aufgetreten"
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr "Jobs archivieren"
msgid "Archive project"
msgstr "Projekt archivieren"
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr "Mir zugewiesen"
@@ -3801,8 +3966,29 @@ msgstr "Deine Anwendung wird, basierend auf den vordefinierten CI/CD-Einstellung
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Erfahre mehr in der %{link_to_documentation}"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "Die Auto-DevOps-Pipeline wurde aktiviert und wird verwendet, falls keine alternative CI-Konfigurationsdatei gefunden wurde. %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr "Autovervollständigung"
@@ -3822,6 +4008,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 "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr "Notiz"
msgid "Available"
msgstr "Verfügbar"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr "Badge-Bild-URL"
msgid "Badges|Badge image preview"
msgstr "Badge-Bild-Vorschau"
-msgid "Badges|Delete badge"
-msgstr "Badge löschen"
-
msgid "Badges|Delete badge?"
msgstr "Badge löschen?"
@@ -3981,6 +4170,12 @@ msgstr "Bamboo Root-URL, z.B. https://bamboo.example.com"
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr "Du musst in Bamboo eine automatische Versionskennzeichnung und einen Repository-Trigger einrichten."
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Vorsicht. Änderungen am Projektnamensraum können unbeabsichtigte Nebenwirkungen haben."
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr "Bitbucket-Server-Import"
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr "Bereich anzeigen"
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr "Branch %{branchName} wurde im Repository dieses Projekts nicht gefunden.
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr "Projekteinstellungen"
msgid "Branches|protected"
msgstr "geschützt"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr "Broadcast-Nachricht wurde erfolgreich erstellt."
@@ -4332,9 +4557,21 @@ msgstr "Integriert"
msgid "Bulk request concurrency"
msgstr "Parallelität von Massenanfragen"
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ msgstr "Von %{user_name}"
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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr "Der Missbrauchsbericht kann nicht erstellt werden. Der/Die Benutzer(in)
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr "Untergeordnetes Epic existiert nicht."
msgid "Child epic doesn't exist."
msgstr "Untergeordnetes Epic existiert nicht."
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr "Alle Umgebungen"
msgid "CiVariable|Create wildcard"
msgstr "Wildcard erstellen"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr "Fehler beim Speichern von Variablen"
-
msgid "CiVariable|Masked"
msgstr "Maskiert"
@@ -5163,9 +5403,6 @@ msgstr "Maskierung umschalten"
msgid "CiVariable|Toggle protected"
msgstr "Schutzstatus umschalten"
-msgid "CiVariable|Validation failed"
-msgstr "Validierung fehlgeschlagen"
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr "Schließe %{tabname}"
msgid "Close epic"
msgstr "Epic schließen"
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr "Meilenstein abschließen"
@@ -5298,7 +5538,7 @@ msgstr "Geschlossene Tickets"
msgid "Closed this %{quick_action_target}."
msgstr "Dieses %{quick_action_target} wurde geschlossen."
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ msgstr ""
msgid "ClusterIntegration|Could not load networks"
msgstr ""
-msgid "ClusterIntegration|Could not load regions from your AWS account"
-msgstr "Regionen konnten nicht von Ihrem AWS-Konto geladen werden"
-
msgid "ClusterIntegration|Could not load security groups for the selected VPC"
msgstr ""
@@ -5823,9 +6066,6 @@ msgstr "Erfahre mehr über %{help_link_start_machine_type}Maschinentypen%{help_l
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "Erfahre mehr über %{help_link_start}Zonen%{help_link_end}."
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr "Lerne mehr über Kubernetes"
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr "Schlüsselpaare werden geladen"
-msgid "ClusterIntegration|Loading Regions"
-msgstr "Regionen werden geladen"
-
msgid "ClusterIntegration|Loading VPCs"
msgstr "VPCs werden geladen"
@@ -5910,9 +6147,6 @@ msgstr "Keine Projekte gefunden"
msgid "ClusterIntegration|No projects matched your search"
msgstr "Keine Projekte entsprechen deiner Suche"
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ msgstr ""
msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "ClusterIntegration|Region"
-msgstr "Region"
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Entferne die Kubernetes-Cluster-Integration"
@@ -6048,9 +6279,6 @@ msgstr "Netzwerke suchen"
msgid "ClusterIntegration|Search projects"
msgstr "Suche Projekte"
-msgid "ClusterIntegration|Search regions"
-msgstr "Regionen suchen"
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr "Wähle ein Projekt aus, um die Zone auszuwählen"
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr "Wähle eine Zone aus"
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr "Wähle ein Netzwerk"
-msgid "ClusterIntergation|Select a region"
-msgstr "Wählen Sie eine Region"
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr "Zeitüberschreitung der Verbindung"
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr "Wenden Sie sich an Sales, um ein Upgrade durchzuführen"
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr "Land"
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr "Erstellt am"
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr "Erstellt am:"
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr "Benutzerdefinierter Hostname (für private Commit-E-Mails)"
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr "Daten werden noch berechnet..."
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr "Codeausschnitt löschen"
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr "Liste löschen"
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr "Codeausschnitt löschen?"
msgid "Delete source branch"
msgstr "Quellbranch löschen"
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr "Diesen Anhang löschen"
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr "Verweigern"
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ msgstr ""
msgid "Deploy to..."
msgstr "Bereitstellen auf..."
-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 ""
@@ -8760,6 +9063,12 @@ msgstr "Bereitgestellt"
msgid "Deployed to"
msgstr "Bereitgestellt für"
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr "Bereitstellung für"
@@ -8808,6 +9117,9 @@ msgstr "Beschreibung"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr "Beschreibungsvorlagen ermöglichen dir, kontextspezifische Vorlagen für das Beschreibungsfeld von Tickets und Merge-Requests für dein Projekts zu definieren."
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr "Diff Inhaltsbeschränkungen"
@@ -9030,7 +9363,7 @@ msgstr "Gruppen-Runner deaktivieren"
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr "Dokumentation für gängige Identitätsanbieter"
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr "Domäne"
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr "Kann Domain nicht löschen, solange sie mit Cluster(n) verknüpft ist."
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "Nicht erneut anzeigen"
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr "Asset herunterladen"
-
msgid "Download codes"
msgstr "Codes herunterladen"
@@ -9407,15 +9746,24 @@ msgstr "Öffentlichen Bereitstellungsschlüssel bearbeiten"
msgid "Edit stage"
msgstr "Phase bearbeiten"
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr "Dieses Release bearbeiten"
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr "Wiki-Seite bearbeiten"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 "Die E-Mail scheint leer zu sein. Stelle sicher, dass sich die Antwort oben in der E-Mail befindet. Wir können keine Inline-Antworten verarbeiten."
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "Endet am (UTC)"
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr "Genehmigungsberechtigte anzeigen"
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr "Gruppe exportieren"
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr "Konfiguriere"
msgid "FeatureFlags|Configure feature flags"
msgstr "Feature-Flags konfigurieren"
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr "Feature-Flag erstellen"
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr "Prozentsatz"
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "Feb"
@@ -11191,12 +11611,18 @@ msgstr "Dateivorlagen"
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "Dateien"
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr "Filter..."
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr "Fertiggestellt"
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr "Erstmals gesehen"
@@ -11329,9 +11758,15 @@ msgstr "Erster Wochentag"
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr "Fester Termin"
@@ -11386,8 +11821,8 @@ 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 "Bei interne Projekte kann jede(r) angemeldete Benutzer(in) die Pipelines anzeigen lassen und auf Job-Details (Ausgabeprotokolle und Artefakte) zugreifen"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
msgid "For more info, read the documentation."
msgstr ""
@@ -11932,7 +12367,7 @@ msgstr "Erste Schritte mit Releases"
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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr "Git-Strategie für Pipelines"
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr "Git-Version"
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr "Gruppen-URL"
msgid "Group avatar"
msgstr "Gruppenavatar"
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr "Äußere Forks verbieten"
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr "Äußere Forks für diese Gruppe verbieten"
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "Verlauf"
@@ -13163,9 +13646,6 @@ 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 "Ich akzeptiere die %{terms_link}"
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "Wenn diese Option aktiviert ist, wird der Zugriff auf Projekte mit einem externen Service anhand ihrer Klassifizierungslabels überprüft."
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr "Importiere mehrere Repositorys, indem du eine Manifestdatei hochlädst."
msgid "Import project"
msgstr "Projekt importieren"
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "Füge Nutzungsbedingungen und eine Datenschutzrichtlinie hinzu, die alle Benutzer(innen) akzeptieren müssen."
@@ -13710,27 +14235,33 @@ msgstr "Gib die Host-Schlüssel manuell ein"
msgid "Input your repository URL"
msgstr "Gib deine Repository-URL ein"
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr "Installiere einen GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "Installiere einen Runner auf Kubernetes"
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,38 +14441,59 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "Interessierte können auch etwas beitragen wenn sie möchten, indem sie Commits pushen."
msgid "Internal"
msgstr ""
-msgid "Internal - The group and any internal projects can be viewed by any logged in user."
-msgstr "Intern - Die Gruppe und alle internen Projekte können von jedem/jeder angemeldeten Benutzer(in) angesehen werden."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
-msgstr "Intern - Auf das Projekt kann von jedem/jeder angemeldeten Benutzer(in) zugegriffen werden."
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "Internal URL (optional)"
msgstr ""
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr "Interne Benutzer(innen)"
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Intervallmuster"
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "Ticketboards"
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr "Jan"
msgid "January"
msgstr "Januar"
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ msgstr "Label hochstufen"
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 "Sprache"
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr "Letzter Zugriff am"
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr "Letzte Pipeline"
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr "Letzte Antwort von"
@@ -14836,6 +15523,9 @@ msgstr "Letzte Aktualisierung"
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr "Mehr Informationen"
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr "Belasse die Optionen \"Dateityp\" und \"Ãœbergabemethode\" auf ihren Sta
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr "März"
msgid "March"
msgstr "März"
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr "Mitgliedersperre"
msgid "Member since %{date}"
msgstr "Mitglied seit %{date}"
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr "Mitglieder"
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ 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 "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr "Namensraum ist leer"
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr "Niemals"
msgid "New"
msgstr "Neu"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr "Neue Anwendung"
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr "Keine"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr "Nicht genügend Daten"
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr "Nicht jetzt"
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,21 +18810,15 @@ msgstr ""
msgid "Open issues"
msgstr ""
-msgid "Open projects"
-msgstr "Projekte öffnen"
-
msgid "Open raw"
msgstr ""
msgid "Open sidebar"
msgstr "Seitenleiste öffnen"
-msgid "Open: %{openIssuesCount}"
+msgid "Open: %{open}"
msgstr ""
-msgid "Open: %{open} • Closed: %{closed}"
-msgstr "Offen: %{open} • Geschlossen: %{closed}"
-
msgid "Opened"
msgstr "Geöffnet"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,8 +19134,8 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
-msgstr "PyPi"
+msgid "PackageRegistry|PyPI"
+msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ msgstr ""
msgid "PackageRegistry|Unable to load package"
msgstr "Paket konnte nicht geladen werden"
-msgid "PackageRegistry|Upcoming package managers"
-msgstr ""
-
msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
msgstr ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,8 +19206,8 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
-msgstr "PyPi"
+msgid "PackageType|PyPI"
+msgstr ""
msgid "Packages"
msgstr "Pakete"
@@ -18578,7 +19398,7 @@ msgstr "Personen ohne Berechtigung werden nie eine Benachrichtigung bekommen und
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr "Leistungsoptimierung"
@@ -18695,6 +19512,9 @@ msgstr "Erfolgsquote:"
msgid "PipelineCharts|Successful:"
msgstr "Erfolgreich:"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "Insgesamt:"
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr "CI Lint"
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr "Erste Schritte mit Pipelines"
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Der Projekt-Cache wurde erfolgreich zurückgesetzt."
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr "Bitte gib einen beschreibenden Namen für deine Gruppe ein."
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Bitte beachte, dass diese Anwendung nicht von GitLab bereitgestellt wird. Du solltest daher die Authentizität überprüfen, bevor du den Zugriff erlaubst."
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr "Schützen"
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr "Push"
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr "Aktualisieren"
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "In einer Sekunde aktualisieren, um den aktualisierten Status anzuzeigen..."
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr "Epic erneut öffnen"
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr "Repository-Einstellungen"
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,8 +22719,8 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
-msgstr "Alle Benutzer(innen) dieser Gruppe müssen die Zwei-Faktor-Authentifizierung einrichten"
+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 "Fordere alle Benutzer(innen) auf, die Nutzungsbedingungen und Datenschutzrichtlinien zu akzeptieren, wenn sie auf GitLab zugreifen."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+msgstr ""
+
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
msgstr "Überprüfe den Prozess zum Konfigurieren von Dienstanbietern bei deinem Identitätsanbieter. In diesem Fall ist GitLab der \"Dienstanbieter\" oder die \"vertrauende Seite\"."
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr "SSH-Hostschlüssel"
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr "Öffentlicher SSH-Schlüssel"
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr "Samstag"
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ msgstr "Zeitplan der Pipeline speichern"
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 variables"
-msgstr "Variablen speichern"
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "Plane eine neue Pipeline"
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr "Suche"
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr "Merge-Requests durchsuchen"
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr "Wähle die Projekte aus, die du importieren möchtest."
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr "Wähle den Branch aus, den du als Standard für dieses Projekt festlegen
msgid "Select the custom project template source group."
msgstr "Wähle die Quellgruppe der benutzerdefinierten Projektvorlage aus."
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr "September"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr "Servicevorlagen"
msgid "Service URL"
msgstr "Service-URL"
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "Richte dein Projekt so ein, dass Änderungen automatisch an ein anderes Repository gesendet bzw. von diesem abgerufen werden. Branches, Tags und Commits werden automatisch synchronisiert."
@@ -23582,6 +24524,15 @@ msgstr "Geteilte Runner"
msgid "Shared projects"
msgstr "Geteilte Projekte"
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ msgstr "Sherlock-Transaktionen"
msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
msgstr ""
+msgid "Show Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr "Alle Mitglieder anzeigen"
@@ -23745,6 +24702,9 @@ msgstr "Anmelden / Registrieren"
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr "Anmeldebeschränkungen"
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr "Registrierungsbeschränkungen"
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr "Zugriffsebene, aufsteigend"
msgid "SortOptions|Access level, descending"
msgstr "Zugriffsebene, absteigend"
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr "Erstellungsdatum"
@@ -24267,6 +25224,9 @@ msgstr "Zuletzt angemeldet"
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr "Größe"
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "Quellcode"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ msgstr "Gib ein Regex-Muster für E-Mail-Adressen an, um interne Standardbenutze
msgid "Specify the following URL during the Runner setup:"
msgstr "Gib die folgende URL während des Runner-Setups an:"
-msgid "Speed up your DevOps%{br_tag}with GitLab"
-msgstr ""
-
msgid "Squash commit message"
msgstr ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr "Statistiken"
msgid "Status"
msgstr "Status"
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr "Als Spam einreichen"
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr "Suche ausführen"
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr "Erfolgreich"
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr "Informationen synchronisieren"
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr "Systemmetriken (benutzerdefiniert)"
msgid "System metrics (Kubernetes)"
msgstr "Systemmetriken (Kubernetes)"
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr "Vielen Dank! Zeig es mir nicht nochmal"
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ msgstr "Das Ticketsystem ist der Ort, um Dinge hinzuzufügen, die in einem Proje
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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,8 +26677,8 @@ msgstr "Die Planungsphase stellt die Zeit vom vorherigen Schritt bis zum Pushen
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr "Der private Schlüssel, der verwendet werden soll, wenn ein Clientzertifikat bereitgestellt wird. Dieser Wert wird im Ruhezustand verschlüsselt."
-msgid "The project can be accessed by any logged in user."
-msgstr "Auf das Projekt kann jede(r) angemeldete Nutzer(in) zugreifen."
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr ""
@@ -25726,6 +26737,9 @@ msgstr "Die Review-Phase stellt die Zeit vom Anlegen eines Merge-Requests bis zu
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "Die Roadmap zeigt den Fortschritt deiner Epics anhand einer Zeitleiste an"
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "Die Benutzerzuordnung legt fest, wie die E-Mail-Adressen und Benutzernamen der FogBuz-Benutzer(innen), die an deinem Projekt teilnehmen, in GitLab importiert werden. Du kannst dies ändern, indem du die Tabelle unten ausfüllst."
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr "Diese Anwendung wurde erstellt von %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Diese Anwendung wird in der Lage sein:"
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr "vor kurzem"
msgid "Timeago|right now"
msgstr "gerade jetzt"
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr "Zeitüberschreitung"
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,8 +27977,8 @@ msgstr "Gib zunächst deine Gitea-Host-URL und einen %{link_to_personal_token} e
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
msgstr "Zur Verbesserung von GitLab und seiner Benutzererfahrung sammelt GitLab regelmäßig Nutzungsinformationen."
-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 "Zur Verbesserung von GitLab würden wir gerne regelmäßig Nutzungsinformationen sammeln. Dies kann jederzeit in den %{settings_link_start}Einstellungen%{link_end} geändert werden. %{info_link_start}Weitere Informationen%{link_end}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
+msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "Um ein SVN-Repository zu importieren, schaue dir %{svn_link} an."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr "Navigation umschalten"
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Seitenleiste ein-/ausblenden"
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr "Gesamte Testzeit für alle Commits/Merges"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr "Gesamt: %{total}"
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr "Dienstag"
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr "Jetzt updaten"
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr "Nutzungsstatistiken"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr "Bereits wegen Missbrauchs gemeldet"
msgid "UserProfile|Blocked user"
msgstr "Blockierte(r) Benutzer(in)"
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr "Alle Tickets anzeigen"
@@ -28647,7 +29751,13 @@ msgstr "Klasse"
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Wenn ein Runner gesperrt ist, kann er keinem anderen Projekt zugewiesen werden"
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr "Du bist auf einer GitLab-Instanz, die nur Lesezugriff erlaubt."
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,12 +30449,12 @@ msgstr "Du kannst stattdessen %{linkStart}den Blob anzeigen%{linkEnd}."
msgid "You can also create a project from the command line."
msgstr "Du kannst ein Projekt auch über die Kommandozeile erstellen."
-msgid "You can also press &#8984;-Enter"
-msgstr ""
-
msgid "You can also press Ctrl-Enter"
msgstr "Sie können auch Strg-Enter drücken"
+msgid "You can also press ⌘-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr "Du kannst auch ein Label markieren, um es zu einem Prioritätslabel zu machen."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr "Du hast keine Berechtigungen"
@@ -29573,9 +30725,6 @@ 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 "Du musst unsere Nutzungsbedingungen und Datenschutzerklärung akzeptieren, um ein Konto registrieren zu können"
-
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr "YouTube"
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr "Deine Gruppen"
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr "Aktivitäten deiner Projekte"
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr "Deine SSH-Schlüssel (%{count})"
@@ -30061,9 +31216,6 @@ msgstr "Branch-Name"
msgid "by"
msgstr "von"
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr "Containerüberprüfung entdeckt bekannte Sicherheitslücken in deinen Do
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr "Gesamten Bericht anzeigen"
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,8 +31711,8 @@ msgstr "ist ein ungültiger IP-Adressbereich"
msgid "is blocked by"
msgstr "wird blockiert von"
-msgid "is enabled."
-msgstr "ist aktiviert."
+msgid "is forbidden by a top-level group"
+msgstr ""
msgid "is invalid because there is downstream lock"
msgstr "ist ungültig, weil es eine Downstream-Sperre gibt"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr "ist kein gültiges X509-Zertifikat."
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr "ist zu lang (maximal 100 Einträge)"
@@ -30634,6 +31789,9 @@ msgstr "ìst zu groß"
msgid "jigsaw is not defined"
msgstr "jigsaw ist nicht definiert"
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr "fehlt"
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr "letzte Bereitstellung"
@@ -31169,9 +32330,6 @@ msgstr ""
msgid "projects"
msgstr "Projekte"
-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 "Schnellzugriff"
@@ -31184,9 +32342,6 @@ msgstr "registrieren"
msgid "relates to"
msgstr "bezieht sich auf"
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr "verbleibend"
@@ -31264,6 +32419,9 @@ msgstr "weniger anzeigen"
msgid "sign in"
msgstr "Einloggen"
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr "Sortierung:"
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr "Wiki-Seite"
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "mit %{additions} Ergänzungen, %{deletions} Löschungen."
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr "yaml ungültig"
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index d64c5723522..589a59ba118 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-10-02 18:47\n"
+"PO-Revision-Date: 2020-11-03 22:47\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/en/gitlab.po b/locale/en/gitlab.po
index 151fbffeb02..4c7435ebfcb 100644
--- a/locale/en/gitlab.po
+++ b/locale/en/gitlab.po
@@ -305,12 +305,6 @@ 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 "Cycle Analytics"
-msgstr ""
-
-msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
-msgstr ""
-
msgid "CycleAnalyticsStage|Code"
msgstr ""
@@ -483,9 +477,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Cycle Analytics"
-msgstr ""
-
msgid "Jobs for last month"
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index 7e549a92ffb..f4bb088b700 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-10-02 18:43\n"
+"PO-Revision-Date: 2020-11-03 22:42\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr "Priskribo"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "Ne montru denove"
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "Dosieroj"
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Intervala Åablono"
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr "Lasta ĉenstablo"
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr "Ne estas sufiĉe da datenoj"
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr "Proporcio de sukceso:"
msgid "PipelineCharts|Successful:"
msgstr "Sukcesaj:"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "Totalo:"
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ msgstr "Konservi ĉenstablan planon"
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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "Plani novan ĉenstablon"
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "Kodo"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,8 +26677,8 @@ msgstr "La etapo de la plano montras la tempon de la antaÅ­a Åtupo Äis la alpu
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
-msgstr "Ĉiu ensalutita uzanto havas atingon al la projekto"
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr ""
@@ -25726,6 +26737,9 @@ msgstr "La etapo de la kontrolo montras la tempon de la kreado de la peto pri ku
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr "Totala tempo por la testado de ĉiuj enmetadoj/kunfandoj"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index d39cf6a2784..68fcb8c6471 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-10-02 18:46\n"
+"PO-Revision-Date: 2020-11-03 22:46\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] "%d fallido"
msgstr[1] "%d fallidos"
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d solucionado el resultado de la prueba"
@@ -215,11 +220,6 @@ msgid_plural "%d issues in this group"
msgstr[0] "%d incidencia en este grupo"
msgstr[1] "%d incidencias en este grupo"
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d incidencia seleccionada"
-msgstr[1] "%d incidencias seleccionadas"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] "%d incidencia importada correctamente con la etiqueta"
@@ -247,8 +247,8 @@ msgstr[1] "%d métricas"
msgid "%d milestone"
msgid_plural "%d milestones"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d hito"
+msgstr[1] "%d hitos"
msgid "%d minute"
msgid_plural "%d minutes"
@@ -262,8 +262,8 @@ msgstr[1] "%d comentarios más"
msgid "%d open issue"
msgid_plural "%d open issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d incidencia abierta"
+msgstr[1] "%d incidencias abiertas"
msgid "%d pending comment"
msgid_plural "%d pending comments"
@@ -337,8 +337,8 @@ msgstr[1] "%d vulnerabilidades descartadas"
msgid "%d warning found:"
msgid_plural "%d warnings found:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d advertencia encontrada:"
+msgstr[1] "%d advertencias encontradas:"
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
@@ -349,7 +349,7 @@ msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
msgid "%{address} is an invalid IP address range"
-msgstr ""
+msgstr "%{address} no es en un rango de direcciones IP válido"
msgid "%{author_link} wrote:"
msgstr "%{author_link} escribió:"
@@ -407,6 +407,16 @@ msgstr "%{count} aprobaciones de %{name}"
msgid "%{count} files touched"
msgstr "%{count} archivos modificados"
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] "%{count} incidencias seleccionadas"
+msgstr[1] "%{count} incidencias seleccionadas"
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr "%{count} más"
@@ -447,6 +457,12 @@ 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 "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr "%{group_name} utiliza cuentas administradas de grupo. Debe crear una nue
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr "%{host} inicia sesión desde una nueva ubicación"
@@ -618,9 +640,6 @@ 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 "%{name} contenido en %{resultsString}"
@@ -718,7 +737,7 @@ msgstr[1] "%{reportType} %{status} detectó %{other} vulnerabilidades."
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr "%{size} %{unit}"
+
msgid "%{size} GiB"
msgstr "%{size} Gb"
@@ -747,7 +769,7 @@ msgid "%{size} bytes"
msgstr "%{size} bytes"
msgid "%{sourceBranch} into %{targetBranch}"
-msgstr ""
+msgstr "%{sourceBranch} en %{targetBranch}"
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} se envió con éxito a Akismet."
@@ -765,7 +787,7 @@ msgid "%{state} epics"
msgstr "%{state} épicas"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
-msgstr ""
+msgstr "%{strongStart}Elimina%{strongEnd} la rama origen"
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -945,16 +967,13 @@ msgid "(check progress)"
msgstr "(comprobar el progreso)"
msgid "(deleted)"
-msgstr ""
-
-msgid "(external source)"
-msgstr "(fuente externa)"
+msgstr "(eliminado)"
msgid "(line: %{startLine})"
-msgstr ""
+msgstr "(línea: %{startLine})"
msgid "(max size 15 MB)"
-msgstr ""
+msgstr "(tamaño máximo 15 MB)"
msgid "(removed)"
msgstr "(eliminado)"
@@ -963,7 +982,7 @@ msgid "(revoked)"
msgstr "(revocado)"
msgid "* * * * *"
-msgstr ""
+msgstr "* * * * *"
msgid "+ %{amount} more"
msgstr "+ %{amount} más"
@@ -988,6 +1007,18 @@ msgstr[1] "+%d más"
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr "+%{tags} más"
@@ -1016,24 +1047,20 @@ msgstr ""
msgid "- show less"
msgstr "- mostrar menos"
-msgid "0 bytes"
+msgid "."
msgstr ""
+msgid "0 bytes"
+msgstr "0 bytes"
+
msgid "0 for unlimited"
msgstr "0 para ilimitado"
msgid "0 for unlimited, only effective with remote storage enabled."
-msgstr ""
+msgstr "0 para ilimitado, solo efectivo con almacenamiento remoto habilitado."
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "1 adición de %{type}"
-msgstr[1] "%{count} %{type} adiciones"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "1 %{type} modificación"
-msgstr[1] "%{count} %{type} modificaciones"
+msgid "0t1DgySidms"
+msgstr "0t1DgySidms"
msgid "1 Day"
msgid_plural "%d Days"
@@ -1042,8 +1069,8 @@ msgstr[1] "%d Días"
msgid "1 Issue"
msgid_plural "%d Issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 incidencia"
+msgstr[1] "%d incidencias"
msgid "1 closed issue"
msgid_plural "%{issues} closed issues"
@@ -1062,8 +1089,8 @@ msgstr[1] "%d días"
msgid "1 deploy key"
msgid_plural "%d deploy keys"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 clave de despliegue"
+msgstr[1] "%d claves de despliegue"
msgid "1 group"
msgid_plural "%d groups"
@@ -1296,6 +1323,9 @@ msgstr "Un usuario con acceso de escritura a la rama origen seleccionó esta opc
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr "Ayuda de la API"
@@ -1501,7 +1531,7 @@ msgid "Add"
msgstr "Añadir"
msgid "Add \"%{value}\""
-msgstr ""
+msgstr "Añadir \"%{value}\""
msgid "Add %d issue"
msgid_plural "Add %d issues"
@@ -1557,7 +1587,7 @@ msgid "Add a To Do"
msgstr "Añadir a tareas pendientes"
msgid "Add a To-Do"
-msgstr ""
+msgstr "Añadir a tareas pendientes"
msgid "Add a bullet list"
msgstr "Añadir una lista de viñetas"
@@ -1595,6 +1625,9 @@ msgstr "Añadir tabla"
msgid "Add a task list"
msgstr "Añadir una lista de tareas"
+msgid "Add a to do"
+msgstr "Añadir a tareas pendientes"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Añada un texto adicional que aparecerá en todas las comunicaciones vía correo electrónico. El límite es de %{character_limit} caracteres"
@@ -1748,8 +1781,8 @@ msgstr "Agregada %{epic_ref} como una tarea épica hija."
msgid "Added %{label_references} %{label_text}."
msgstr "Agregada %{label_references} %{label_text}."
-msgid "Added a To Do."
-msgstr "Agregado a la lista de tareas pendientes."
+msgid "Added a to do."
+msgstr "Añadido a tareas pendientes."
msgid "Added an issue to an epic."
msgstr "Agrada una incidencia a una tarea épica."
@@ -1784,12 +1817,12 @@ msgstr "Añade %{epic_ref} como tarea épica hija."
msgid "Adds %{labels} %{label_text}."
msgstr "Agrega %{labels} %{label_text}."
-msgid "Adds a To Do."
-msgstr "Agregar a la lista de tareas pendientes."
-
msgid "Adds a Zoom meeting"
msgstr "Agregar una reunión de Zoom"
+msgid "Adds a to do."
+msgstr "Añade una tarea pendiente."
+
msgid "Adds an issue to an epic."
msgstr "Agregar una incidencia a una tarea épica."
@@ -1836,7 +1869,7 @@ msgid "AdminArea|Bots"
msgstr "Bots"
msgid "AdminArea|Components"
-msgstr ""
+msgstr "AdminArea|Componentes"
msgid "AdminArea|Developer"
msgstr "Desarrollador"
@@ -1854,31 +1887,34 @@ msgid "AdminArea|Included Free in license"
msgstr "AdminArea|Incluido gratis en la licencia"
msgid "AdminArea|Latest groups"
-msgstr ""
+msgstr "AdminArea|Grupos más recientes"
msgid "AdminArea|Latest projects"
-msgstr ""
+msgstr "AdminArea|Proyectos más recientes"
msgid "AdminArea|Latest users"
-msgstr ""
+msgstr "AdminArea|Usuarios más recientes"
msgid "AdminArea|Maintainer"
msgstr "Mantenedor"
msgid "AdminArea|New group"
-msgstr ""
+msgstr "AdminArea|Nuevo grupo"
msgid "AdminArea|New project"
-msgstr ""
+msgstr "AdminArea|Nuevo proyecto"
msgid "AdminArea|New user"
+msgstr "AdminArea|Nuevo usuario"
+
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
msgstr ""
msgid "AdminArea|Owner"
msgstr "Propietario"
msgid "AdminArea|Projects: %{number_of_projects}"
-msgstr ""
+msgstr "AdminArea|Proyectos: %{number_of_projects}"
msgid "AdminArea|Reporter"
msgstr "Reportador"
@@ -1898,6 +1934,9 @@ msgstr "Error al detener trabajos"
msgid "AdminArea|Total users"
msgstr "Usuarios totales"
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "Estadísticas de usuarios"
@@ -1908,7 +1947,7 @@ msgid "AdminArea|Users without a Group and Project"
msgstr "Usuarios sin grupo y proyecto"
msgid "AdminArea|Users: %{number_of_users}"
-msgstr ""
+msgstr "AdminArea|Usuarios: %{number_of_users}"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Está a punto de detener todos los trabajos. Esto detendrá todos los trabajos que se están ejecutando actualmente."
@@ -2012,6 +2051,21 @@ msgstr "Claves SSH"
msgid "AdminStatistics|Snippets"
msgstr "Fragmentos de código"
+msgid "AdminUsers|(Admin)"
+msgstr "AdminUsers|(Admin)"
+
+msgid "AdminUsers|(Blocked)"
+msgstr "AdminUsers|(Bloqueado)"
+
+msgid "AdminUsers|(Deactivated)"
+msgstr "AdminUsers|(Desactivado)"
+
+msgid "AdminUsers|(Internal)"
+msgstr "AdminUsers|(Interno)"
+
+msgid "AdminUsers|(Pending approval)"
+msgstr "AdminUsers|(Pendiente de aprobación)"
+
msgid "AdminUsers|2FA Disabled"
msgstr "2FA desactivado"
@@ -2019,7 +2073,13 @@ msgid "AdminUsers|2FA Enabled"
msgstr "2FA Habilitado"
msgid "AdminUsers|Access"
-msgstr ""
+msgstr "Acceso"
+
+msgid "AdminUsers|Access Git repositories"
+msgstr "Acceso a los repositorios de Git"
+
+msgid "AdminUsers|Access the API"
+msgstr "Acceder a la API"
msgid "AdminUsers|Active"
msgstr "Activo"
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr "Administradores"
+msgid "AdminUsers|Approve"
+msgstr "Aprobar"
+
+msgid "AdminUsers|Approve user"
+msgstr "Aprobar usuario"
+
+msgid "AdminUsers|Approved users can:"
+msgstr "Los usuarios aprobados pueden:"
+
+msgid "AdminUsers|Are you sure?"
+msgstr "AdminUsers|¿Está seguro?"
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr "Ser añadido a grupos y proyectos"
+
msgid "AdminUsers|Block"
msgstr "Bloquear"
+msgid "AdminUsers|Block this user"
+msgstr "Bloquear a este usuario"
+
msgid "AdminUsers|Block user"
msgstr "Bloquear usuario"
@@ -2093,6 +2171,9 @@ msgstr "Está utilizando un asiento"
msgid "AdminUsers|It's you!"
msgstr "¡Es usted!"
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr "Nuevo usuario"
@@ -2102,6 +2183,9 @@ msgstr "No se encontraron usuarios"
msgid "AdminUsers|Owned groups will be left"
msgstr "Se dejarán los grupos propios"
+msgid "AdminUsers|Pending approval"
+msgstr "Pendiente de aprobación"
+
msgid "AdminUsers|Personal projects will be left"
msgstr "Se dejarán los proyectos personales"
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr "El usuario no recibirá ninguna notificación"
+msgid "AdminUsers|This user has requested access"
+msgstr "Este usuario ha solicitado acceso"
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Para confirmar, escriba %{projectName}"
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr "Siempre puede desbloquear su cuenta, sus datos permanecerán intactos."
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr "‫Administración"
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr "Avanzado"
@@ -2195,22 +2288,22 @@ msgstr "Configuración avanzada"
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "Permisos avanzados, almacenamiento de grandes archivos y configuraciones de autenticación de dos factores."
-msgid "Advanced search functionality"
-msgstr "Funcionalidad de búsqueda avanzada"
-
msgid "After a successful password update you will be redirected to login screen."
msgstr "Después de una actualización correcta de la contraseña, será redirigido a la pantalla de inicio de sesión."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Después de una actualización correcta de la contraseña, se le redirigirá a la página de inicio de sesión donde podrá iniciar sesión con su nueva contraseña."
-msgid "After that, you will not to be able to use merge approvals or code quality as well as many other features."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,12 +2368,12 @@ msgstr "Eventos"
msgid "AlertManagement|High"
msgstr "Alta"
+msgid "AlertManagement|Incident"
+msgstr "Incidente"
+
msgid "AlertManagement|Info"
msgstr "Información"
-msgid "AlertManagement|Issue"
-msgstr ""
-
msgid "AlertManagement|Key"
msgstr ""
@@ -2315,10 +2408,10 @@ msgid "AlertManagement|Open"
msgstr "Abrir"
msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
+msgstr "Opsgenie está habilitado"
msgid "AlertManagement|Please try again."
-msgstr ""
+msgstr "Por favor, inténtelo de nuevo."
msgid "AlertManagement|Reported %{when}"
msgstr "Reportado %{when}"
@@ -2330,7 +2423,7 @@ msgid "AlertManagement|Resolved"
msgstr "Resuelto"
msgid "AlertManagement|Runbook"
-msgstr ""
+msgstr "Runbook"
msgid "AlertManagement|Service"
msgstr "Servicio"
@@ -2378,10 +2471,10 @@ msgid "AlertManagement|Unknown"
msgstr "Desconocido"
msgid "AlertManagement|Value"
-msgstr ""
+msgstr "Valor"
msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
+msgstr "Ver alertas en Opsgenie"
msgid "AlertManagement|View incident"
msgstr ""
@@ -2395,28 +2488,40 @@ 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"
+msgid "AlertSettings|1. Select integration type"
+msgstr "1. Seleccione el tipo de integración"
+
+msgid "AlertSettings|2. Name integration"
msgstr ""
-msgid "AlertSettings|Active"
+msgid "AlertSettings|5. Map fields (optional)"
msgstr ""
+msgid "AlertSettings|API URL"
+msgstr "URL del API"
+
+msgid "AlertSettings|Active"
+msgstr "Activo"
+
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
-msgstr ""
+msgstr "Clave de autorización"
msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
-msgstr ""
+msgstr "La clave de autorización se ha restablecido correctamente. Por favor, guarde los cambios ahora."
msgid "AlertSettings|Copy"
+msgstr "Copiar"
+
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|Enter test alert JSON...."
@@ -2425,13 +2530,19 @@ msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Integration"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2465,7 +2585,7 @@ msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
msgid "AlertSettings|Webhook URL"
-msgstr ""
+msgstr "AlertSettings|URL del 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 ""
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr "Alertas"
msgid "Alerts endpoint"
msgstr "Endpoint de alertas"
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr "Integraciones actuales"
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr "endpoint HTTP"
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr "Nombre de integración"
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr "Todavía no se han añadido integraciones"
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr "Prometheus"
+
msgid "Algorithm"
msgstr "Algoritmo"
@@ -2513,7 +2654,7 @@ msgid "All environments"
msgstr "Todos los entornos"
msgid "All epics"
-msgstr ""
+msgstr "Todas las tareas épicas"
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Todas las funcionalidades están habilitadas para proyectos en blanco, plantillas, o al importar, pero puedes deshabilitarlas posteriormente en la configuración del proyecto."
@@ -2540,7 +2681,7 @@ msgid "All projects"
msgstr "Todos los proyectos"
msgid "All projects selected"
-msgstr ""
+msgstr "Todos los proyectos seleccionados"
msgid "All security scans are enabled because %{linkStart}Auto DevOps%{linkEnd} is enabled on this project"
msgstr "Todas las exploraciones de seguridad están habilitadas porque %{linkStart}Auto DevOps%{linkEnd} está habilitado en este proyecto"
@@ -2548,9 +2689,6 @@ msgstr "Todas las exploraciones de seguridad están habilitadas porque %{linkSta
msgid "All threads resolved"
msgstr "Todos los hilos resueltos"
-msgid "All users"
-msgstr "Todos los usuarios"
-
msgid "All users must have a name."
msgstr "Todos los usuarios deben tener un nombre."
@@ -2558,7 +2696,7 @@ msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Permitir al grupo %{group_name} iniciar sesión"
msgid "Allow access to the following IP addresses"
-msgstr ""
+msgstr "Permitir el acceso a las siguientes direcciones IP"
msgid "Allow commits from members who can merge to the target branch."
msgstr "Permitir commits de los miembros que pueden hacer merge con la rama de destino."
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr "Permitir que los proyectos y subgrupos sobreescriban la configuración del grupo"
+
msgid "Allow projects within this group to use Git LFS"
msgstr "Permitir que los proyectos dentro de este grupo usen Git LFS"
@@ -2596,6 +2737,9 @@ msgstr "Permitir solicitudes a la red local desde hooks de sistema"
msgid "Allow requests to the local network from web hooks and services"
msgstr "Permitir solicitudes a la red local desde web hooks y servicios"
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr "Permitir que los subgrupos configuren sus propias reglas de autenticación de dos factores"
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr "¿Permitir que esta clave también haga push al repositorio? (El valor predeterminado solo permite hacer pull)"
@@ -2612,10 +2756,13 @@ msgid "Allow users to request access (if visibility is public or internal)"
msgstr "Permitir a los usuarios solicitar acceso (si la visibilidad es pública o interna)"
msgid "Allowed"
-msgstr ""
+msgstr "Permitido"
msgid "Allowed Geo IP"
-msgstr ""
+msgstr "Geo IP permitida"
+
+msgid "Allowed domains for sign-ups"
+msgstr "Dominios permitidos para suscripciones"
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Sólo los grupos de nivel superior pueden restringir los dominios de correo electrónico permitidos"
@@ -2623,6 +2770,9 @@ msgstr "Sólo los grupos de nivel superior pueden restringir los dominios de cor
msgid "Allowed to fail"
msgstr "Permitido fallar"
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Le permite agregar y administrar clusters de Kubernetes."
@@ -2630,7 +2780,7 @@ msgid "Almost there"
msgstr "¡Ya queda poco!"
msgid "Already blocked"
-msgstr ""
+msgstr "Ya está bloqueado"
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
msgstr "También llamado \"emisor\" o \"identificador de confianza\""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr "Se ha disparado una alerta en %{project_path}."
@@ -2683,9 +2836,15 @@ 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 "Se agregará a un campo de usuario de Gitlab el nombre completo del usuario de FogBugz (por ejemplo, \"John Smith\") en la descripción de todos los errores y los comentarios. También se asociarán o asignarán estos errores y comentarios al creador del proyecto."
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "Se ha producido un error"
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr "Se ha producido un error al recuperar los autores del proyecto."
msgid "An error occurred previewing the blob"
msgstr "Ha ocurrido un error visualizando el blob"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "Se produjo un error al activar/desactivar la suscripción de notificación"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "Se ha producido un error al actualizar el tamaño de la incidencia"
@@ -2803,9 +2968,6 @@ 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 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."
@@ -2878,9 +3040,6 @@ msgstr "Se ha producido un error al cargar las incidencias"
msgid "An error occurred while loading merge requests."
msgstr "Se ha producido un error al cargar los merge requests."
-msgid "An error occurred while loading milestones"
-msgstr "Se ha producido un error al cargar los hitos"
-
msgid "An error occurred while loading project creation UI"
msgstr "Se ha producido un error al cargar la interfaz de creación del proyecto"
@@ -2911,9 +3070,6 @@ msgstr "Se ha producido un error al cargar el merge request."
msgid "An error occurred while loading the pipelines jobs."
msgstr "Se ha producido un error al cargar los trabajos de lo pipelines."
-msgid "An error occurred while loading the subscription details."
-msgstr "Se ha producido un error al cargar los detalles de la suscripción."
-
msgid "An error occurred while making the request."
msgstr "Se ha producido un error al crear la petición."
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr "Se ha producido un error al renderizar el editor"
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr "Se ha producido un error al ordenar las incidencias."
@@ -2954,7 +3113,7 @@ msgid "An error occurred while retrieving diff files"
msgstr ""
msgid "An error occurred while retrieving projects."
-msgstr ""
+msgstr "Se ha producido un error al obtener los proyectos."
msgid "An error occurred while saving LDAP override status. Please try again."
msgstr "Se ha producido un error al guardar el estado de LDAP. Por favor, inténtalo de nuevo."
@@ -2962,9 +3121,6 @@ msgstr "Se ha producido un error al guardar el estado de LDAP. Por favor, intén
msgid "An error occurred while saving assignees"
msgstr "Se ha producido un error al guardar las asignaciones"
-msgid "An error occurred while searching for milestones"
-msgstr "Se ha producido un error durante la búsqueda de hitos"
-
msgid "An error occurred while subscribing to notifications."
msgstr "Se ha producido un error al suscribirse a las notificaciones."
@@ -2980,8 +3136,11 @@ msgstr "Se ha producido un error al cancelar la suscripción a las notificacione
msgid "An error occurred while updating approvers"
msgstr "Se ha producido un error al actualizar los aprobadores"
+msgid "An error occurred while updating configuration."
+msgstr "Se ha producido un error al actualizar la configuración."
+
msgid "An error occurred while updating labels."
-msgstr ""
+msgstr "Se ha producido un error al actualizar las etiquetas."
msgid "An error occurred while updating the comment"
msgstr "Se ha producido un error al actualizar el comentario"
@@ -2993,7 +3152,7 @@ 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 ""
+msgstr "Se ha producido un error. Por favor, inicie sesión de nuevo."
msgid "An error occurred. Please try again."
msgstr "Se ha producido un error. Por favor inténtelo de nuevo."
@@ -3038,7 +3197,7 @@ msgid "An unknown error occurred while loading this graph."
msgstr "Se ha producido un error desconocido mientras se cargaba este gráfico."
msgid "An unknown error occurred."
-msgstr ""
+msgstr "Se ha producido un error desconocido."
msgid "Analytics"
msgstr "Analíticas"
@@ -3262,7 +3421,7 @@ msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
msgid "Approvals|Section: %section"
-msgstr ""
+msgstr "Sección: %section"
msgid "Approve"
msgstr "Aprobar"
@@ -3298,7 +3457,7 @@ msgid "April"
msgstr "Abril"
msgid "Architecture not found for OS"
-msgstr ""
+msgstr "Arquitectura no encontrada para SO"
msgid "Archive"
msgstr "Archivar"
@@ -3309,11 +3468,14 @@ msgstr "Archivar trabajos"
msgid "Archive project"
msgstr "Archivar proyecto"
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr "Archivado"
msgid "Archived in this version"
-msgstr ""
+msgstr "Archivado en esta versión"
msgid "Archived project! Repository and other project resources are read only"
msgstr "¡Proyecto archivado! El repositorio y otros recursos del proyecto son de sólo lectura"
@@ -3552,11 +3714,14 @@ msgid "Assigned Merge Requests"
msgstr "Merge requests asignados"
msgid "Assigned to %{assigneeName}"
-msgstr ""
+msgstr "Asignado a %{assigneeName}"
msgid "Assigned to %{assignee_name}"
msgstr "Asignado a %{assignee_name}"
+msgid "Assigned to %{name}"
+msgstr "Asignado a %{name}"
+
msgid "Assigned to me"
msgstr "Asignado a mí"
@@ -3670,7 +3835,7 @@ msgid "AuditLogs|Target"
msgstr "Destino"
msgid "AuditLogs|This month"
-msgstr ""
+msgstr "Este mes"
msgid "AuditLogs|User Events"
msgstr "Eventos de usuario"
@@ -3712,16 +3877,16 @@ msgid "Authentication via U2F device failed."
msgstr "Se ha producido un error en la autenticación a través del dispositivo U2F."
msgid "Authentication via WebAuthn device failed."
-msgstr ""
+msgstr "La autenticación vía dispositivo WebAuthn ha fallado."
msgid "Author"
msgstr "Autor"
msgid "Author: %{author_name}"
-msgstr ""
+msgstr "Autores: %{author_name}"
msgid "Authored %{timeago}"
-msgstr ""
+msgstr "Creado %{timeago}"
msgid "Authored %{timeago} by %{author}"
msgstr "Creado %{timeago} por %{author}"
@@ -3745,7 +3910,7 @@ msgid "Authorize %{link_to_client} to use your account?"
msgstr "¿Autorizar %{link_to_client} para utilizar su cuenta?"
msgid "Authorize %{user} to use your account?"
-msgstr ""
+msgstr "¿Autorizar a %{user} para utilizar su cuenta?"
msgid "Authorize external services to send alerts to GitLab"
msgstr "Autorizar a servicios externos enviar alertas a GitLab"
@@ -3801,8 +3966,29 @@ msgstr "Automáticamente construirán, probarán y desplegarán su aplicación c
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Más información en %{link_to_documentation}"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "El pipeline de Auto DevOps ha sido habilitado y será utilizado si no se encuentra un archivo de configuración CI alternativo. %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr "Autocompletar"
@@ -3822,6 +4008,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 "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,11 +4029,14 @@ msgstr "Nota"
msgid "Available"
msgstr "Disponible"
+msgid "Available ID"
+msgstr "ID disponible"
+
msgid "Available Runners: %{runners}"
-msgstr ""
+msgstr "Ejecutores disponibles: %{runners}"
msgid "Available for dependency and container scanning"
-msgstr ""
+msgstr "Disponible para análisis de dependencias y contenedores"
msgid "Available group Runners: %{runners}"
msgstr "Grupo de ejecutores disponible: %{runners}"
@@ -3897,9 +4089,6 @@ msgstr "URL de imagen de la insignia"
msgid "Badges|Badge image preview"
msgstr "Vista previa de la imagen de la insignia"
-msgid "Badges|Delete badge"
-msgstr "Eliminar la insignia"
-
msgid "Badges|Delete badge?"
msgstr "¿Desea eliminar la insignia?"
@@ -3981,6 +4170,12 @@ msgstr "La URL raíz de Bamboo, por ejemplo, https://bamboo.example.com"
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr "Debe configurar el etiquetado automático de revisión y un disparador del repositorio en Bamboo."
+msgid "Based on"
+msgstr "Basado en"
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Tenga cuidado. Cambiar el espacio de nombres del proyecto puede tener efectos secundarios no deseados."
@@ -4003,7 +4198,7 @@ msgid "Bi-weekly code coverage"
msgstr "Cobertura de código quincenal"
msgid "Billable Users:"
-msgstr ""
+msgstr "Usuarios facturables:"
msgid "Billing"
msgstr "Facturación"
@@ -4015,7 +4210,7 @@ msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan.
msgstr "actualmente, @%{user_name} está utilizando el plan %{plan_name}."
msgid "BillingPlans|Congratulations, your free trial is activated."
-msgstr ""
+msgstr "Enhorabuena, su plan de prueba está activado."
msgid "BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}."
msgstr "Si deseas cambiar su plan, por favor, póngase en contacto con %{support_link_start}Atención al cliente%{support_link_end}."
@@ -4060,11 +4255,23 @@ msgid "BillingPlans|per user"
msgstr "por usuario"
msgid "BillingPlan|Contact sales"
-msgstr ""
+msgstr "Contactar con ventas"
msgid "BillingPlan|Upgrade"
msgstr "Actualizar"
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr "Importar desde un servidor de Bitbucket"
@@ -4078,7 +4285,7 @@ msgid "Blame"
msgstr ""
msgid "Block user"
-msgstr ""
+msgstr "Bloquear usuario"
msgid "Blocked"
msgstr "Bloqueado"
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr "Expandir"
msgid "Boards|View scope"
msgstr "Ver alcance"
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr "No se encontró la rama %{branchName} en el repositorio de este proyecto
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr "configuración del proyecto"
msgid "Branches|protected"
msgstr "protegido"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr "El mensaje de difusión se creó correctamente."
@@ -4332,9 +4557,21 @@ msgstr "Integrado"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr "Gráfico de evolución"
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ msgstr "Por %{user_name}"
msgid "By URL"
msgstr "Por URL"
-msgid "By clicking Register, I agree that I have read and accepted the GitLab %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr "No se puede crear el informe de abuso. Este usuario ha sido bloqueado."
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr "La subtarea épica no existe."
msgid "Child epic doesn't exist."
msgstr "La subtarea épica no existe."
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr "Todos los entornos"
msgid "CiVariable|Create wildcard"
msgstr "Crear comodín"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr "Se ha producido un error al guardar las variables"
-
msgid "CiVariable|Masked"
msgstr "Enmascarado"
@@ -5163,9 +5403,6 @@ msgstr "Alternar enmascaramiento"
msgid "CiVariable|Toggle protected"
msgstr "Alternar protegido"
-msgid "CiVariable|Validation failed"
-msgstr "Error de validación"
-
msgid "Classification Label (optional)"
msgstr "Etiqueta de clasificación (opcional)"
@@ -5274,6 +5511,9 @@ msgstr "Cerrar %{tabname}"
msgid "Close epic"
msgstr "Cerrar épica"
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr "Cerrar hito"
@@ -5298,8 +5538,8 @@ msgstr "Incidencias cerradas"
msgid "Closed this %{quick_action_target}."
msgstr "Cerrado este %{quick_action_target}."
-msgid "Closed: %{closedIssuesCount}"
-msgstr "Cerrados: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
+msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "Cierra este %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr "Nivel de clúster"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5458,7 +5701,7 @@ msgid "ClusterIntegration|Authenticate with Amazon Web Services"
msgstr "Autenticar con Amazon Web Services"
msgid "ClusterIntegration|Authentication Error"
-msgstr ""
+msgstr "Error de autenticación"
msgid "ClusterIntegration|Base domain"
msgstr "Dominio base"
@@ -5508,6 +5751,9 @@ msgstr "Limpiar la caché de cluster"
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr "Proyecto de administración de cluster (alpha)"
@@ -5565,9 +5811,6 @@ msgstr "Se ha producido un error al cargar los tipos de instancias"
msgid "ClusterIntegration|Could not load networks"
msgstr "Se ha producido un error al cargar las redes"
-msgid "ClusterIntegration|Could not load regions from your AWS account"
-msgstr "Se ha producido un error al cargar las regiones de su cuenta AWS"
-
msgid "ClusterIntegration|Could not load security groups for the selected VPC"
msgstr "Se ha producido un error al cargar los grupos de seguridad para la VPC seleccionada"
@@ -5725,7 +5968,7 @@ msgid "ClusterIntegration|Group cluster"
msgstr "ClusterIntegration|Grupo de clúster"
msgid "ClusterIntegration|HTTP Error"
-msgstr ""
+msgstr "Error HTTP"
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -5823,9 +6066,6 @@ msgstr "Aprenda más sobre los tipos de %{help_link_start_machine_type}instancia
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "Conozca más sobre las %{help_link_start}zonas%{help_link_end}."
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr "Más información sobre Kubernetes"
@@ -5841,9 +6081,6 @@ msgstr "Cargando roles de IAM"
msgid "ClusterIntegration|Loading Key Pairs"
msgstr "Cargando pares de claves"
-msgid "ClusterIntegration|Loading Regions"
-msgstr "Cargando regiones"
-
msgid "ClusterIntegration|Loading VPCs"
msgstr "Cargando VPCs"
@@ -5910,9 +6147,6 @@ msgstr "No se encontraron proyectos"
msgid "ClusterIntegration|No projects matched your search"
msgstr "No hay proyectos que coincidan con su búsqueda"
-msgid "ClusterIntegration|No region found"
-msgstr "No se encontró ninguna región"
-
msgid "ClusterIntegration|No security group found"
msgstr "No se ha encontrado ningún grupo de seguridad"
@@ -5979,9 +6213,6 @@ msgstr "Lea nuestra %{link_start}página de ayuda%{link_end} sobre la integraciÃ
msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "ClusterIntegration|Region"
-msgstr "Región"
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Eliminar la integración de clústeres de Kubernetes"
@@ -6048,9 +6279,6 @@ msgstr "Buscar redes"
msgid "ClusterIntegration|Search projects"
msgstr "Buscar proyectos"
-msgid "ClusterIntegration|Search regions"
-msgstr "Buscar regiones"
-
msgid "ClusterIntegration|Search security groups"
msgstr "Buscar grupos de seguridad"
@@ -6111,6 +6339,9 @@ msgstr "Seleccione un proyecto para elegir la zona"
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr "Seleccione la zona"
@@ -6195,6 +6426,9 @@ msgstr "El endpoint está en proceso de ser asignado. Por favor verifique su clu
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr "Se ha producido un error durante la autenticación con su cluster. Por favor, asegúrese de que su la CA de su certificado y su token son válidos."
@@ -6295,13 +6529,13 @@ msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knati
msgstr "Debe tener un cluster RBAC habilitado para instalar Knative."
msgid "ClusterIntegration|You must specify a domain before you can install Knative."
-msgstr ""
+msgstr "Debe especificar un dominio antes de poder instalar Knative."
msgid "ClusterIntegration|You should select at least two subnets"
msgstr "Debe seleccionar al menos dos subredes"
msgid "ClusterIntegration|Your Elasticsearch cluster will be re-created during this upgrade. Your logs will be re-indexed, and you will lose historical logs from hosts terminated in the last 30 days."
-msgstr ""
+msgstr "Su cluster Elasticsearch será recreado durante esta actualización. Sus registros serán reindexados y perderá registros históricos de los hosts de los últimos 30 días."
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Su cuenta debe tener %{link_to_kubernetes_engine}"
@@ -6319,7 +6553,7 @@ msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "acceso a Google Kubernetes Engine"
msgid "ClusterIntegration|can be used instead of a custom domain. "
-msgstr ""
+msgstr "puede utilizarse en lugar de un dominio personalizado. "
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr "Seleccione una VPC"
msgid "ClusterIntergation|Select a network"
msgstr "Seleccione una red"
-msgid "ClusterIntergation|Select a region"
-msgstr "Seleccione una región"
-
msgid "ClusterIntergation|Select a security group"
msgstr "Seleccione un grupo de seguridad"
@@ -6358,7 +6589,7 @@ msgid "ClusterIntergation|Select service role"
msgstr "Seleccione el rol de servicio"
msgid "Clusters|An error occurred while loading clusters"
-msgstr ""
+msgstr "Se ha producido un error al cargar los clústeres"
msgid "Code"
msgstr "Código"
@@ -6450,9 +6681,6 @@ msgstr "Nombre del recolector"
msgid "ComboSearch is not defined"
msgstr "ComboSearch no está definido"
-msgid "Coming soon"
-msgstr "Próximamente"
-
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
msgstr "Separados por comas, ej. '1.1.1.1, 2.2.2.0/24'"
@@ -6633,7 +6861,7 @@ msgid "Complete"
msgstr "Completado"
msgid "Completed"
-msgstr ""
+msgstr "Completado"
msgid "Compliance"
msgstr "Cumplimiento"
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr "Tiempo de espera agotado"
msgid "Connection timeout"
msgstr "Tiempo de espera de conexión agotado"
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr "Póngase en contacto con ventas para actualizar"
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr "No es posible eliminar el apodo del chate %{chat_name}."
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr "No se pudo encontrar el diseño."
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr "No es posible eliminar el disparador."
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr "País"
@@ -7466,7 +7712,7 @@ msgid "Create file"
msgstr "Crear archivo"
msgid "Create from"
-msgstr ""
+msgstr "Crear desde"
msgid "Create group"
msgstr "Crear grupo"
@@ -7589,7 +7835,7 @@ msgid "Created by me"
msgstr "Creado por mí"
msgid "Created by:"
-msgstr ""
+msgstr "Creado por:"
msgid "Created date"
msgstr "Fecha de creación"
@@ -7609,6 +7855,9 @@ msgstr "Creado el merge request %{mergeRequestLink} en %{projectLink}"
msgid "Created on"
msgstr "Creado en"
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr "Creado sobre:"
@@ -7702,6 +7951,9 @@ msgstr "Ruta de configuración CI personalizada"
msgid "Custom Git clone URL for HTTP(S)"
msgstr "URL de clon de Git personalizado para HTTP(S)"
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr "Nombre de host personalizado (para los correos electrónicos privados de los commit)"
@@ -7953,6 +8205,9 @@ msgstr "Tareas por tipo"
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr "Nº total de días para completar"
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr "Los datos aún se están calculando..."
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr "Eliminar el comentario"
-msgid "Delete Snippet"
-msgstr "Eliminar fragmento de código"
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr "Eliminar artefactos"
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr "Eliminar el tablero"
@@ -8364,9 +8655,6 @@ msgstr "Eliminar etiqueta"
msgid "Delete label: %{label_name} ?"
msgstr "¿Eliminar la etiqueta: %{label_name}?"
-msgid "Delete list"
-msgstr "Eliminar lista"
-
msgid "Delete pipeline"
msgstr "Eliminar pipeline"
@@ -8388,6 +8676,9 @@ msgstr "¿Eliminar fragmento de código?"
msgid "Delete source branch"
msgstr "Eliminar rama origen"
+msgid "Delete subscription"
+msgstr "Eliminar suscripción"
+
msgid "Delete this attachment"
msgstr "Eliminar este adjunto"
@@ -8446,17 +8737,23 @@ msgid "Deletion pending. This project will be removed on %{date}. Repository and
msgstr "Eliminación pendiente. Este proyecto se eliminará el %{date}. El repositorio y otros recursos del proyecto son de solo lectura."
msgid "Denied"
-msgstr ""
+msgstr "Denegado"
msgid "Denied authorization of chat nickname %{user_name}."
msgstr "Autorización denegada del nick del chat %{user_name}."
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr "Denegar"
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr "Dependencias"
@@ -8505,18 +8802,27 @@ msgstr "Exportar como JSON"
msgid "Dependencies|Job failed to generate the dependency list"
msgstr "El trabajo ha fallado al generar la lista de dependencias"
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr "Licencia"
msgid "Dependencies|Location"
msgstr "Ubicación"
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
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|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ msgstr ""
msgid "Deploy to..."
msgstr "Desplegar en..."
-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 ""
@@ -8760,6 +9063,12 @@ msgstr "Desplegado"
msgid "Deployed to"
msgstr "Desplegado en"
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr "Desplegando en"
@@ -8808,6 +9117,9 @@ msgstr "Descripción"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "Descripción analizada con %{link_start}GitLab Flavored Markdown%{link_end}"
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr "Las plantillas de descripción le permiten definir plantillas relativas al contexto para incidencias y campos de descripción de las peticiones de fusión para tu proyecto."
@@ -8974,11 +9286,32 @@ msgid "Detect host keys"
msgstr "Detectar las claves del host"
msgid "DevOps"
-msgstr ""
+msgstr "DevOps"
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr "Límites de contenido del diff"
@@ -9030,8 +9363,8 @@ msgstr "Desactivar el grupo de ejecutores"
msgid "Disable public access to Pages sites"
msgstr "Deshabilitar el acceso público a los sitios de Pages"
-msgid "Disable shared Runners"
-msgstr "Deshabilitar los ejecutores compartidos"
+msgid "Disable shared runners"
+msgstr ""
msgid "Disable two-factor authentication"
msgstr "Desactivar la autenticación de dos factores"
@@ -9043,7 +9376,7 @@ msgid "Disabled mirrors can only be enabled by instance owners. It is recommende
msgstr "Las réplicas deshabilitadas solo pueden ser habilitadas por los propietarios de las instancias. Se recomienda eliminarlas."
msgid "Discard"
-msgstr ""
+msgstr "Descartar"
msgid "Discard all changes"
msgstr "Descartar todos los cambios"
@@ -9179,6 +9512,9 @@ msgstr "Documentación"
msgid "Documentation for popular identity providers"
msgstr "Documentación para los proveedores de identidad más populares"
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr "Dominio"
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr "La verificación del dominio es una medida de seguridad esencial para los sitios públicos de GitLab. Los usuarios deben demostrar que administran o que son los propietarios de un dominio antes de poder habilitarlo"
@@ -9209,6 +9548,9 @@ msgstr "No incluir la descripción en el mensaje del commit"
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr "No pegue la parte privada de la clave GPG. Pegue la parte pública que empieza por: '----- BEGIN PGP PUBLIC KEY BLOCK -----'."
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "No mostrar de nuevo"
@@ -9234,10 +9576,7 @@ msgid "Download as"
msgstr "Descargar como"
msgid "Download as CSV"
-msgstr ""
-
-msgid "Download asset"
-msgstr "Descargar activo"
+msgstr "Descargar como CSV"
msgid "Download codes"
msgstr "Descargar codigos"
@@ -9279,7 +9618,7 @@ msgid "Downvotes"
msgstr "Voto negativo"
msgid "Draft"
-msgstr ""
+msgstr "Borrador"
msgid "Draft merge requests can't be merged."
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr "Editar clave pública de despliegue"
msgid "Edit stage"
msgstr "Editar etapa"
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr "Editar esta versión"
+msgid "Edit title and description"
+msgstr "Editar título y descripción"
+
msgid "Edit wiki page"
msgstr "Editar página wiki"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "Edite su comentario más reciente en un hilo (desde un cuadro de texto vacío)"
+msgid "Edited"
+msgstr "Editado"
+
msgid "Edited %{timeago}"
msgstr "Editado %{timeago}"
@@ -9488,6 +9836,9 @@ msgstr "Correo enviado"
msgid "Email the pipelines status to a list of recipients."
msgstr "Envía el estado de los pipelines a una lista de destinatarios."
+msgid "Email updates (optional)"
+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 "Parece que el correo electrónico está en blanco. Asegúrese de que su respuesta esté en la parte superior del correo electrónico, no podemos procesar las respuestas en línea."
@@ -9525,7 +9876,7 @@ msgid "Emails sent from Service Desk will have this name"
msgstr "Los correos electrónicos enviados desde Service Desk tendrán este nombre"
msgid "Emails sent to %{email} will still be supported"
-msgstr ""
+msgstr "Los correos electrónicos enviados a %{email} continuarán siendo compatibles"
msgid "Emails separated by comma"
msgstr "Correos electrónicos separados por comas"
@@ -9629,6 +9980,12 @@ msgstr "Habilitar el encabezado y pie de página en los correos electrónicos"
msgid "Enable integration"
msgstr "Habilitar integración"
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "Habilitar el modo de mantenimiento"
@@ -9656,8 +10013,20 @@ msgstr "Habilitar el proxy"
msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr "Habilite reCAPTCHA o Akismet y establezca límites por IP. Para reCAPTCHA, actualmente sólo soportamos %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
-msgid "Enable shared Runners"
-msgstr "Habilitar ejecutores compartidos"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
+msgstr ""
msgid "Enable snowplow tracking"
msgstr ""
@@ -9701,6 +10070,9 @@ msgstr "Habilitar esta opción solo hará que las funciones con licencia EE estÃ
msgid "Encountered an error while rendering: %{err}"
msgstr "Se ha producido un error al renderizar: %{err}"
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "Finaliza a las (UTC)"
@@ -9728,8 +10100,11 @@ msgstr "Introduzca un rango de direcciones IP"
msgid "Enter a number"
msgstr "Introduzca un número"
-msgid "Enter a whole number between 0 and 100"
-msgstr "Introduzca un número entero entre 0 y 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
+msgstr ""
msgid "Enter at least three characters to search"
msgstr "Introduzca al menos tres caracteres para buscar"
@@ -10224,7 +10599,7 @@ msgid "Error loading file viewer."
msgstr "Se ha producido un error al cargar el visor de archivos."
msgid "Error loading issues"
-msgstr ""
+msgstr "Se ha producido un error al cargar las incidencias"
msgid "Error loading iterations"
msgstr ""
@@ -10490,12 +10865,18 @@ msgstr "Ejemplo: Uso = consulta simple. (Solicitado)/(Capacidad) = Varias consul
msgid "Except policy:"
msgstr "Extracto de la política:"
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,9 +10907,12 @@ msgstr ""
msgid "Expand approvers"
msgstr "Expandir aprobadores"
-msgid "Expand milestones"
+msgid "Expand file"
msgstr ""
+msgid "Expand milestones"
+msgstr "Expandir hitos"
+
msgid "Expand sidebar"
msgstr "Expandir barra lateral"
@@ -10590,7 +10974,7 @@ msgid "Explore public groups"
msgstr "Explorar grupos públicos"
msgid "Export"
-msgstr ""
+msgstr "Exportar"
msgid "Export as CSV"
msgstr "Exportar como CSV"
@@ -10601,6 +10985,9 @@ msgstr "Exportar grupo"
msgid "Export issues"
msgstr "Exportar incidencias"
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "Exportar proyecto"
@@ -10665,7 +11052,7 @@ msgid "Failed Jobs"
msgstr "Trabajos fallidos"
msgid "Failed on"
-msgstr ""
+msgstr "Error en"
msgid "Failed to add a Zoom meeting"
msgstr "Se ha producido un error al agregar una reunión de Zoom"
@@ -10703,6 +11090,9 @@ msgstr "Se ha producido un erro al crear una rama para esta incidencia. Por favo
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr "Se ha producido un error al crear el repositorio"
@@ -10766,6 +11156,9 @@ msgstr "Se ha producido un error al cargar las etiquetas. Por favor, inténtelo
msgid "Failed to load milestones. Please try again."
msgstr "Se ha producido un error al cargar los hitos. Por favor, inténtelo de nuevo."
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr "Se ha producido un error al cargar ramas relacionadas"
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr "Se ha producido un error al cargar el stacktrace."
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr "Se ha producido un error al marcar esta incidencia como duplicada ya que se hace referencia a una incidencia no encontrada."
@@ -10857,7 +11253,7 @@ msgid "Failed to update environment!"
msgstr "Se ha producido un error al actualizar el entorno!"
msgid "Failed to update issue status"
-msgstr ""
+msgstr "Se ha producido un error al actualizar el estado de la incidencia"
msgid "Failed to update issues, please try again."
msgstr "Se ha producido un error al actualizar las incidencias. Por favor, inténtalo de nuevo."
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr "* (Todos los entornos)"
@@ -10945,6 +11353,9 @@ msgstr "Configurar"
msgid "FeatureFlags|Configure feature flags"
msgstr "Configurar Feature Flags"
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr "Crear Feature Flag"
@@ -10996,6 +11407,9 @@ msgstr "Se a a eliminar la Feature Flag%{name}. ¿Está seguro de que desea cont
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr "Porcentaje de despliegue"
msgid "FeatureFlags|Rollout Strategy"
msgstr "Estrategia de despliegue"
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr "Se ha producido un error al obtener las Feature Flag."
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,24 +11533,27 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr "Lista"
-
msgid "FeatureFlag|Percentage"
msgstr "Porcentaje"
msgid "FeatureFlag|Select a user list"
msgstr "Seleccione una lista de usuarios"
-msgid "FeatureFlag|There are no configured user lists"
+msgid "FeatureFlag|Select the environment scope for this feature flag"
msgstr ""
+msgid "FeatureFlag|There are no configured user lists"
+msgstr "No hay listas de usuarios configuradas"
+
msgid "FeatureFlag|Type"
msgstr "Tipo"
msgid "FeatureFlag|User IDs"
msgstr "Ids de usuario"
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "Feb"
@@ -11191,12 +11611,18 @@ msgstr "Plantillas de archivos"
msgid "File upload error."
msgstr "Error al subir el archivo."
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "Archivos"
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr "Archivos, directorios y submódulos en la ruta %{path} para la referencia del commit %{ref}"
@@ -11221,6 +11647,9 @@ msgstr "Filtrar por revisión de Git"
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr "Filtrar por etiqueta"
@@ -11282,6 +11711,9 @@ msgid "Filter..."
msgstr "Filtrar..."
msgid "Find File"
+msgstr "Buscar archivo"
+
+msgid "Find bugs in your code with API fuzzing."
msgstr ""
msgid "Find bugs in your code with coverage-guided fuzzing."
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr "Finalizado"
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr "Visto por primera vez"
@@ -11329,9 +11758,15 @@ msgstr "Primer día de la semana"
msgid "First name"
msgstr "Primer nombre"
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr "Visto por primera vez"
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr "Fecha fija"
@@ -11386,8 +11821,8 @@ 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 "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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
msgid "For more info, read the documentation."
msgstr "Para más información, por favor lea la documentación."
@@ -11546,13 +11981,13 @@ msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
msgid "Geo Replication"
-msgstr ""
+msgstr "Replicación de Geo"
msgid "Geo Settings"
-msgstr ""
+msgstr "Configuración de Geo"
msgid "Geo nodes are paused using a command run on the node"
-msgstr ""
+msgstr "Los nodos de Geo se pausan utilizando un comando que se ejecuta en el nodo"
msgid "GeoNodeStatusEvent|%{timeAgoStr} (%{pendingEvents} events)"
msgstr "%{timeAgoStr} (%{pendingEvents} eventos)"
@@ -11932,7 +12367,7 @@ msgstr "Primeros pasos con las versiones"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr "Git LFS no está habilitado en este servidor de GitLab, póngase en contacto con su administrador."
-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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr "Estrategia de Git para los 'pipelines'"
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr "Versión de Git"
@@ -11989,9 +12427,6 @@ 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 "Los ejecutores compartidos de GitLab ejecutan el código de diferentes proyectos en el mismo ejecutor a menos que configure el auto escalado de os ejecutores de GitLab con MaxBuilds 1 (que se encuentra en GitLab.com)."
-
msgid "GitLab Shell"
msgstr ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr "GitLab para Slack"
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr "Ir a sus proyectos"
msgid "Go to your snippets"
msgstr "Ir a sus fragmentos de código"
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr "Google Cloud Platform"
@@ -12433,8 +12877,8 @@ msgstr "URL del grupo"
msgid "Group avatar"
msgstr "Avatar del grupo"
-msgid "Group by:"
-msgstr "Agrupar por:"
+msgid "Group by"
+msgstr ""
msgid "Group description"
msgstr "Descripción del grupo"
@@ -12592,6 +13036,12 @@ msgstr "Para ver la hoja de ruta, agregue la fecha de inicio o la de vencimiento
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Para ampliar su búsqueda, cambie o elimine los filtros; desde %{startDate} a %{endDate}."
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "Huella digital del certificado"
@@ -12601,6 +13051,9 @@ msgstr "Configuración"
msgid "GroupSAML|Copy SAML Response XML"
msgstr "Copiar XML de respuesta de SAML"
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr "NameID"
msgid "GroupSAML|NameID Format"
msgstr "Formato NameID"
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr "Salida de la respuesta SAML"
@@ -12664,6 +13135,9 @@ msgstr "SAML Single Sign On"
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr "Opciones de configuración de SAML Single Sign On"
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr "URL del endpoint de SCIM API"
@@ -12676,6 +13150,9 @@ msgstr "La huella digital SHA1 del certificado de firma de tokens SAML. Puede ob
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr "El token SCIM está oculto. Para ver el valor del token de nuevo, necesita "
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr "Tu token SCIM"
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -12848,10 +13328,10 @@ msgid "Groups (%{groups})"
msgstr "Grupos (%{groups})"
msgid "Groups and projects"
-msgstr ""
+msgstr "Grupos y proyectos"
msgid "Groups and subgroups"
-msgstr ""
+msgstr "Grupos y subgrupos"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "Los grupos también se pueden anidar creando %{subgroup_docs_link_start}subgrupos%{subgroup_docs_link_end}."
@@ -12902,10 +13382,10 @@ msgid "GroupsNew|Contact an administrator to enable options for importing your g
msgstr ""
msgid "GroupsNew|Create"
-msgstr ""
+msgstr "GroupsNew|Crear"
msgid "GroupsNew|Create group"
-msgstr ""
+msgstr "GroupsNew|Crear grupo"
msgid "GroupsNew|Import"
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "Historial"
@@ -13163,9 +13646,6 @@ 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."
-msgid "I accept the %{terms_link_start}Terms of Service and Privacy Policy%{terms_link_end}"
-msgstr "Acepto los %{terms_link_start}Términos de servicio y la Política de privacidad%{terms_link_end}"
-
msgid "I accept the %{terms_link}"
msgstr "Aceptar los %{terms_link}"
@@ -13178,8 +13658,8 @@ msgstr "He olvidado mi contraseña"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr "He leído y acepto los Términos de servicio de %{link_end} Let's Encrypt %{link_start}(PDF)"
-msgid "I'd like to receive updates via email about GitLab"
-msgstr "Me gustaría recibir actualizaciones por correo electrónico sobre GitLab"
+msgid "I'd like to receive updates about GitLab via email"
+msgstr ""
msgid "ID"
msgstr "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "Si está habilitado, el acceso a los proyectos se validará en un servicio externo utilizando su etiqueta de clasificación."
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ msgstr ""
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr "Si pierde los códigos de recuperación, puede generar otros nuevos, invalidando todos los códigos anteriores."
-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 ""
@@ -13334,12 +13814,12 @@ msgstr "Ignorar"
msgid "Ignored"
msgstr "Ignorado"
-msgid "Image Details"
-msgstr "Detalles de la imagen"
-
msgid "Image URL"
msgstr "URL de la imagen"
+msgid "Image details"
+msgstr ""
+
msgid "ImageDiffViewer|2-up"
msgstr "2-up"
@@ -13419,6 +13899,9 @@ msgstr "Importar varios repositorios subiendo un archivo manifiesto."
msgid "Import project"
msgstr "Importar proyecto"
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr "Importar miembros del proyecto"
@@ -13534,11 +14017,17 @@ msgid "In the next step, you'll be able to select the projects you want to impor
msgstr "En el siguiente paso, podrá seleccionar los proyectos que desea importar."
msgid "Incident"
-msgstr ""
+msgstr "Incidente"
msgid "Incident Management Limits"
msgstr "Límites de gestión de incidentes"
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr "horas"
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr "Incidentes"
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "Incluya un acuerdo de términos de servicio y una política de privacidad que todos los usuarios deben aceptar."
@@ -13710,27 +14235,33 @@ msgstr "Introducir las claves del host manualmente"
msgid "Input your repository URL"
msgstr "Introduzca la URL de su repositorio"
-msgid "Insert"
-msgstr "Insertar"
-
msgid "Insert a code block"
msgstr "Insertar un bloque de código"
msgid "Insert a quote"
msgstr "Insertar una cita"
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr "Insertar una imagen"
msgid "Insert code"
msgstr "Insertar código"
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr "Insertar código en línea"
msgid "Insert suggestion"
msgstr "Insertar sugerencia"
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr "Insights"
@@ -13749,6 +14280,9 @@ msgstr "Instalar GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "Instalar Gitlab Runner en Kubernetes"
+msgid "Install a Runner"
+msgstr ""
+
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr "Instale un autenticador de token por software como por ejemplo, %{free_otp_link} o Google Authenticator desde el repositorio de su aplicación y utilice esa aplicación para escanear este código QR. Hay más información disponible en la documentación %{help_link_start}%{help_link_end}."
@@ -13756,7 +14290,7 @@ msgid "Install on clusters"
msgstr "Instala en los clústeres"
msgid "Installation"
-msgstr ""
+msgstr "Instalación"
msgid "Installed"
msgstr "Instalado"
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr "Ya existe el grupo de administrador de instancias"
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,38 +14441,59 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr "Estándar"
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "Las partes interesadas incluso pueden contribuir haciendo push commit si lo desean."
msgid "Internal"
msgstr "Interno"
-msgid "Internal - The group and any internal projects can be viewed by any logged in user."
-msgstr "Interno - cualquier usuario que haya iniciado sesión puede ver el grupo y cualquier proyecto interno."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
-msgstr "Interno - cualquier usuario haya iniciado sesión puede acceder a este proyecto."
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "Internal URL (optional)"
msgstr "URL interna (opcional)"
@@ -13880,6 +14501,9 @@ msgstr "URL interna (opcional)"
msgid "Internal users"
msgstr "Usuarios internos"
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Patrón de intervalo"
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr "URL no válida"
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr "Nombre del contenedor no válido"
@@ -14006,25 +14627,25 @@ msgstr "Invitar al miembro"
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,9 +14693,63 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
-msgid "Invited"
+msgid "InviteMember|Oops, this feature isn't ready yet"
msgstr ""
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "Invited"
+msgstr "Invitado"
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "Tablero de incidencias"
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,9 +15014,12 @@ msgstr "Ene"
msgid "January"
msgstr "Enero"
-msgid "Jira Issues"
+msgid "Japanese language support using"
msgstr ""
+msgid "Jira Issues"
+msgstr "Incidencias de Jira"
+
msgid "Jira display name"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,9 +15293,15 @@ msgstr "Atajos de teclado"
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "Keys"
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
+msgid "Keys"
+msgstr "Claves"
+
msgid "Ki"
msgstr ""
@@ -14738,9 +15428,6 @@ msgstr "Promocionar etiqueta"
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 "Y %{count} más"
-
msgid "Language"
msgstr "Idioma"
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr "Último acceso el"
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr "El apellido es demasiado largo (el número máximo de caracteres es %{max_length})."
-
msgid "Last Pipeline"
msgstr "Último Pipeline"
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr "Apellido(s)"
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr "Última respuesta por"
@@ -14836,6 +15523,9 @@ msgstr "Última actualización"
msgid "Last used"
msgstr "Utilizado por última vez"
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr "Utilizado por última vez en:"
@@ -14881,6 +15571,9 @@ msgstr "Aprenda cómo habilitar la sincronización"
msgid "Learn more"
msgstr "Conozca más"
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr "Aprenda más sobre Auto DevOps"
@@ -14956,6 +15649,9 @@ msgstr "Deja las opciones \"Tipo de archivo\" y \"Método de entrega\" con sus v
msgid "Leave zen mode"
msgstr "Abandonar el modo zen"
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "Let's Encrypt no acepta correos electrónicos de example.com"
@@ -14972,7 +15668,7 @@ msgid "License History"
msgstr "Historial de licencias"
msgid "License ID:"
-msgstr ""
+msgstr "ID de licencia:"
msgid "License overview"
msgstr ""
@@ -15104,7 +15800,7 @@ msgid "Licensed to"
msgstr "Licenciado a"
msgid "Licensed to:"
-msgstr ""
+msgstr "Licenciado a:"
msgid "Licenses"
msgstr "Licencias"
@@ -15495,9 +16191,6 @@ msgstr "Marzo"
msgid "March"
msgstr "Marzo"
-msgid "Mark To Do as done"
-msgstr "Marcar la tarea pendiente como hecha"
-
msgid "Mark as done"
msgstr "Marcar como completado"
@@ -15516,6 +16209,9 @@ msgstr "Marque esta incidencia como duplicada de otra incidencia"
msgid "Mark this issue as related to another issue"
msgstr "Marque esta incidencia como relacionada con otra incidencia"
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr "Markdown"
@@ -15549,9 +16245,6 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
-msgid "Marked To Do as done."
-msgstr "Marcado tarea pendiente como hecha."
-
msgid "Marked this %{noun} as Work In Progress."
msgstr "Marcado este %{noun} como trabajo en progreso."
@@ -15561,8 +16254,8 @@ msgstr "Esta incidencia esta marcada como un duplicado de %{duplicate_param}."
msgid "Marked this issue as related to %{issue_ref}."
msgstr "Marcar esta incidencia como incidencia relacionada con %{issue_ref}."
-msgid "Marks To Do as done."
-msgstr "Marcar tarea pendiente como hecha."
+msgid "Marked to do as done."
+msgstr ""
msgid "Marks this %{noun} as Work In Progress."
msgstr "Marca este %{noun} como un trabajo en progreso."
@@ -15573,6 +16266,9 @@ msgstr "Marca esta incidencia como un duplicada de %{duplicate_reference}."
msgid "Marks this issue as related to %{issue_ref}."
msgstr "Marca esta incidencia como una incidencia relacionada con %{issue_ref}."
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr "Enmascarar variable"
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr "Bloqueo de miembros"
msgid "Member since %{date}"
msgstr "Miembro desde %{date}"
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr "Miembros"
@@ -15783,15 +16488,90 @@ msgstr "Miembros con acceso a %{strong_start}%{group_name}%{strong_end}"
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr "Uso de memoria"
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16195,7 +16978,7 @@ msgid "Metrics|Create your dashboard configuration file"
msgstr ""
msgid "Metrics|Current"
-msgstr ""
+msgstr "Metrics|Actual"
msgid "Metrics|Dashboard files can be found in %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
msgstr ""
@@ -16368,7 +17151,7 @@ msgid "Metrics|Values"
msgstr "Nombre"
msgid "Metrics|View documentation"
-msgstr ""
+msgstr "Metrics|Ver documentación"
msgid "Metrics|View logs"
msgstr "Ver registros"
@@ -16432,6 +17215,27 @@ 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 "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr "Cerrado:"
@@ -16652,7 +17456,7 @@ msgid "Monitoring"
msgstr "Monitorizar"
msgid "Month"
-msgstr ""
+msgstr "Mes"
msgid "Months"
msgstr "Meses"
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr "Espacio de nombres está vacía"
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr "Nunca"
msgid "New"
msgstr "Nuevo"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr "Nueva aplicación"
@@ -17075,10 +17916,10 @@ msgid "New Environment"
msgstr "Nuevo entorno"
msgid "New Epic"
-msgstr ""
+msgstr "Nueva tarea épica"
msgid "New File"
-msgstr ""
+msgstr "Nuevo archivo"
msgid "New Group"
msgstr "Nuevo grupo"
@@ -17128,7 +17969,7 @@ msgid "New Test Case"
msgstr ""
msgid "New User"
-msgstr ""
+msgstr "Nuevo usuario"
msgid "New branch"
msgstr "Nueva rama"
@@ -17350,7 +18191,7 @@ msgid "No estimate or time spent"
msgstr "Sin estimación o tiempo gastado"
msgid "No file chosen"
-msgstr "No se ha seleccionado nignun archivo"
+msgstr "No se ha seleccionado ningún archivo"
msgid "No file hooks found."
msgstr ""
@@ -17374,7 +18215,7 @@ msgid "No issues found"
msgstr ""
msgid "No iteration"
-msgstr ""
+msgstr "Sin iteración"
msgid "No iterations to show"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr "Ninguno"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr "¡No se ha implementado!"
@@ -17556,9 +18400,6 @@ msgstr "No hay suficientes datos"
msgid "Not found."
msgstr "No encontrado."
-msgid "Not now"
-msgstr "Ahora no"
-
msgid "Not ready yet. Try again later."
msgstr "No está listo todavía. Por favor, inténtalo de nuevo más tarde."
@@ -17719,7 +18560,7 @@ msgid "November"
msgstr "Noviembre"
msgid "Novice"
-msgstr ""
+msgstr "Novato"
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr "OmniAuth"
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,20 +18810,14 @@ msgstr ""
msgid "Open issues"
msgstr "Incidencias abiertas"
-msgid "Open projects"
-msgstr "Proyectos abiertos"
-
msgid "Open raw"
msgstr "Abrir raw"
msgid "Open sidebar"
msgstr "Abrir barra lateral"
-msgid "Open: %{openIssuesCount}"
-msgstr "Abiertos: %{openIssuesCount}"
-
-msgid "Open: %{open} • Closed: %{closed}"
-msgstr "Abierto: %{open} • Cerrado: %{closed}"
+msgid "Open: %{open}"
+msgstr ""
msgid "Opened"
msgstr "Abierto"
@@ -18158,6 +18990,9 @@ msgstr "Añadir un remoto de Conan"
msgid "PackageRegistry|Add NuGet Source"
msgstr "Añadir fuente de NuGet"
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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|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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr "Maven XML"
msgid "PackageRegistry|NPM"
msgstr "NPM"
-msgid "PackageRegistry|No upcoming issues"
-msgstr "No hay próximas incidencias"
-
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -18302,8 +19134,8 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
-msgstr "PyPi"
+msgid "PackageRegistry|PyPI"
+msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
@@ -18326,9 +19158,6 @@ msgstr ""
msgid "PackageRegistry|There are no packages yet"
msgstr "Todavía no hay paquetes"
-msgid "PackageRegistry|There are no upcoming issues to display."
-msgstr ""
-
msgid "PackageRegistry|There was a problem fetching the details for this package."
msgstr "Se ha producido un error al obtener los detalles de este paquete."
@@ -18344,9 +19173,6 @@ msgstr ""
msgid "PackageRegistry|Unable to load package"
msgstr "Se ha producido un error al cargar el paquete"
-msgid "PackageRegistry|Upcoming package managers"
-msgstr "Próximos gestores de paquetes"
-
msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
msgstr ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,8 +19206,8 @@ msgstr "NPM"
msgid "PackageType|NuGet"
msgstr "NuGet"
-msgid "PackageType|PyPi"
-msgstr "PyPi"
+msgid "PackageType|PyPI"
+msgstr ""
msgid "Packages"
msgstr "Paquetes"
@@ -18578,7 +19398,7 @@ msgstr "Las personas no autorizadas nunca recibirán una notificación y no podr
msgid "People without permission will never get a notification."
msgstr "Las personas sin permisos nunca recibirán una notificación."
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr "Realice operaciones comunes en el proyecto GitLab"
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr "Optimización del rendimiento"
@@ -18695,6 +19512,9 @@ msgstr "Ratio de éxito"
msgid "PipelineCharts|Successful:"
msgstr "Exitosos:"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "Total:"
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr "CI Lint"
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr "Comenzar a utilizar los pipelines"
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Caché del proyecto restablecida correctamente."
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr "Por favor, introduzca un número no negativo"
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr "Por favor, introduzca un número mayor que %{number} (desde la configuración del proyecto)"
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr "Por favor, introduzca un número válido"
@@ -19097,6 +19935,9 @@ msgstr "Por favor, introduzca o cargue una licencia."
msgid "Please fill in a descriptive name for your group."
msgstr "Por favor ingrese un nombre descriptivo para su grupo."
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr "Por favor, migre todos los proyectos existentes al almacenamiento hashea
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Por favor, tenga en cuenta que esta aplicación no la proporciona GitLab y deberá verificar su autenticidad antes de permitir su acceso."
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr "Por favor, proporcione un nombre"
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr "Por favor proporcione una dirección de correo electrónico válida."
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ".NET Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
msgstr "SalesforceDX"
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr "Serverless Framework/JS"
@@ -20828,6 +21678,9 @@ msgstr "Rama"
msgid "ProtectedBranch|Code owner approval"
msgstr "Aprobación del propietario del código"
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr "Proteger"
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr "Comprar más minutos"
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr "Push"
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21117,7 +21976,7 @@ msgid "Recent searches"
msgstr "Búsquedas recientes"
msgid "Reconfigure"
-msgstr ""
+msgstr "Reconfigurar"
msgid "Recover hidden stage"
msgstr "Recuperar una fase oculta"
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr "Actualizar"
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "Actualizar en un segundo para mostrar el estado actualizado..."
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr "Regístrese en GitLab"
-
msgid "Register now"
msgstr "Registrarse ahora"
@@ -21402,9 +22261,12 @@ msgstr "Eliminar la licencia"
msgid "Remove limit"
msgstr "Eliminar límite"
-msgid "Remove member"
+msgid "Remove list"
msgstr ""
+msgid "Remove member"
+msgstr "Eliminar miembro"
+
msgid "Remove milestone"
msgstr "Eliminar el hito"
@@ -21522,6 +22384,9 @@ msgstr "Elimina la fecha de vencimiento."
msgid "Removes time estimate."
msgstr "Elimina el tiempo estimado."
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr "Volver a abrir %{display_issuable_type}"
msgid "Reopen epic"
msgstr "Reabrir la tarea épica"
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr "Reabrir hito"
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr "Reabrir este%{quick_action_target}"
@@ -21573,6 +22444,9 @@ msgstr "Reemplaza la raíz de la URL de clonado."
msgid "Replication"
msgstr "Replicación"
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21598,7 +22472,7 @@ msgid "Report %{display_issuable_type} that are abusive, inappropriate or spam."
msgstr ""
msgid "Report abuse"
-msgstr ""
+msgstr "Informar de un abuso"
msgid "Report abuse to admin"
msgstr "Informar de un abuso al administrador"
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr "Última actualización"
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr "Gráfico de repositorio"
msgid "Repository Settings"
msgstr "Configuración del repositorio"
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21813,7 +22708,7 @@ msgid "Requested states are invalid"
msgstr ""
msgid "Requests"
-msgstr ""
+msgstr "Peticiones"
msgid "Requests Profiles"
msgstr ""
@@ -21824,8 +22719,8 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
-msgstr "Requerir que todos los usuarios en este grupo configuren la autenticación de dos factores"
+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 "Requerir a todos los usuarios que acepten los términos del servicio y la política de privacidad cuando accedan a GitLab."
@@ -21857,6 +22752,9 @@ msgstr "Se ha reabierto el requisito %{reference}"
msgid "Requirement %{reference} has been updated"
msgstr "Se ha actualizado el requisito %{reference}"
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr "El título del requisito no puede tener más de %{limit} caracteres."
@@ -21988,7 +22886,7 @@ msgid "Restart Terminal"
msgstr "Reiniciar el terminal"
msgid "Restore"
-msgstr ""
+msgstr "Restaurar"
msgid "Restore group"
msgstr "Restaurar grupo"
@@ -22058,6 +22956,9 @@ msgstr "Ver aplicación"
msgid "Review App|View latest app"
msgstr "Ver la última aplicación"
+msgid "Review requested from %{name}"
+msgstr "Revisión solicitada por %{name}"
+
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
msgstr "Revise el proceso de configuración de los proveedores de servicios de su proveedor de identidad; en este caso, GitLab es el \"proveedor de servicios\" o la \"parte confiante\"."
@@ -22088,7 +22989,7 @@ msgid "Revoke"
msgstr "Revocar"
msgid "Revoked"
-msgstr ""
+msgstr "Revocado"
msgid "Revoked impersonation token %{token_name}!"
msgstr "¡Token de suplantación revocado %{token_name}!"
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr "Claves de host 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 ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr "Las claves SSH le permiten establecer una conexión segura entre su ordenador y GitLab."
@@ -22315,6 +23228,12 @@ msgstr "Clave pública SSH"
msgid "SSL Verification:"
msgstr "Verificación SSL:"
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr "Sábado"
@@ -22330,6 +23249,9 @@ msgstr "Guardar cambios"
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr "Guardar de todos modos"
@@ -22354,9 +23276,6 @@ msgstr "Guardar programación del pipeline"
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 variables"
-msgstr "Guardar variables"
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr "Guardando"
msgid "Saving project."
msgstr "Guardar proyecto."
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "Programar un nuevo pipeline"
@@ -22405,9 +23327,12 @@ msgstr "Alcances"
msgid "Scopes can't be blank"
msgstr ""
-msgid "Score"
+msgid "Scopes: %{scope_list}"
msgstr ""
+msgid "Score"
+msgstr "Puntuación"
+
msgid "Scroll down"
msgstr "Desplazar hacia abajo"
@@ -22435,8 +23360,8 @@ msgstr "Buscar"
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
-msgstr "Buscar hitos"
+msgid "Search a group"
+msgstr ""
msgid "Search an environment spec"
msgstr "Buscar un entorno específico"
@@ -22492,9 +23417,6 @@ msgstr "Buscar este texto"
msgid "Search forks"
msgstr "Buscar forks"
-msgid "Search groups"
-msgstr "Buscar grupos"
-
msgid "Search merge requests"
msgstr "Buscar merge requests"
@@ -22576,9 +23498,6 @@ msgstr "Mostrando %{from} - %{to} de %{count} %{scope} para%{term_element}"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for%{term_element} in your personal and project snippets"
msgstr "Mostrando %{from} - %{to} de %{count} %{scope} para%{term_element} en tus fragmentos de código personales y de proyecto"
-msgid "SearchResults|We couldn't find any %{scope} matching %{term}"
-msgstr "No pudimos encontrar ningún %{scope} que coincida con %{term}"
-
msgid "SearchResults|code result"
msgid_plural "SearchResults|code results"
msgstr[0] "Resultado del código"
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22653,7 +23572,7 @@ msgid "Secondary"
msgstr "Secundario"
msgid "Seconds"
-msgstr ""
+msgstr "Segundos"
msgid "Secret"
msgstr "Secreto"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr "False positivo"
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr "Se ha producido un error al eliminar el comentario."
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr "Se ha producido un error al descartar las vulnerabilidades."
@@ -23058,7 +23991,7 @@ msgid "Select epic"
msgstr ""
msgid "Select file"
-msgstr ""
+msgstr "Seleccionar archivo"
msgid "Select group or project"
msgstr "Seleccione un grupo o proyecto"
@@ -23070,7 +24003,7 @@ msgid "Select health status"
msgstr "Seleccionar estado de salud"
msgid "Select label"
-msgstr ""
+msgstr "Seleccionar etiqueta"
msgid "Select labels"
msgstr "Seleccione las etiquetas"
@@ -23102,6 +24035,9 @@ msgstr "Seleccione qué proyectos desea importar."
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr "Seleccionar revisor(es)"
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr "Seleccionar estado"
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,14 +24068,11 @@ msgstr "Seleccione la rama que desea establecer como predeterminada para este pr
msgid "Select the custom project template source group."
msgstr "Seleccione el grupo de origen de plantilla de proyecto personalizado."
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
msgid "Select type"
-msgstr ""
+msgstr "Seleccionar tipo"
msgid "Select user"
msgstr "Seleccione el usuario"
@@ -23228,6 +24161,9 @@ msgstr "Separar temas con comas."
msgid "September"
msgstr "Septiembre"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr "y"
@@ -23342,6 +24278,9 @@ msgstr "Plantillas de Servicio"
msgid "Service URL"
msgstr "URL del servicio"
+msgid "Session ID"
+msgstr "ID de sesión"
+
msgid "Session duration (minutes)"
msgstr "Duración de la sesión (minutos)"
@@ -23477,6 +24416,9 @@ msgstr "Establecer una nueva contraseña"
msgid "Set up pipeline subscriptions for this project."
msgstr "Configure las subscripciones a los pipelines para este proyecto."
+msgid "Set up shared runner availability"
+msgstr ""
+
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 "Configure su proyecto para hacer push o pull de los cambios de manera automática a/desde otro repositorio. Los branchs, los tags y los commits se sincronizarán automáticamente."
@@ -23582,6 +24524,15 @@ msgstr "Ejecturores compartidos"
msgid "Shared projects"
msgstr "Proyectos compartidos"
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr "Enlace de ayuda de los ejecutores compartidos"
@@ -23600,9 +24551,15 @@ msgstr "Transacciones de Sherlock"
msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
msgstr ""
+msgid "Show Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr "Mostrar toda la actividad"
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr "Mostrar todos los miembros"
@@ -23745,6 +24702,9 @@ msgstr "Iniciar sesión / Registro"
msgid "Sign in to \"%{group_name}\""
msgstr "Iniciar sesión en %{group_name}\""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr "Inicie sesión mediante una tarjeta inteligente"
@@ -23772,6 +24732,9 @@ msgstr "¡Registro creado correctamente! Por favor, confirme su dirección de co
msgid "Sign-in restrictions"
msgstr "Restricciones de inicio de sesión"
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr "Restricciones de registro"
@@ -23781,9 +24744,6 @@ msgstr "El nombre es demasiado largo (el tamaño máximo permitido es de %{max_l
msgid "SignUp|Last Name is too long (maximum is %{max_length} characters)."
msgstr "Los apellidos son demasiado largos (el tamaño máximo permitido es de %{max_length} caracteres)."
-msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
-msgstr "El nombre es demasiado largo (el tamaño máximo permitido es de %{max_length} caracteres)."
-
msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
msgstr "El nombre de usuario es demasiado largo (el tamaño máximo permitido es de %{max_length} caracteres)."
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr "Sesión iniciada"
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr "Iniciado con autenticación de %{authentication}"
@@ -23904,27 +24867,18 @@ msgstr "No hay fragmentos de código que mostrar."
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
-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 ""
@@ -24159,6 +25113,9 @@ msgstr "Nivel de acceso, ascendente"
msgid "SortOptions|Access level, descending"
msgstr "Nivel de acceso, descendente"
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr "Fecha de creación"
@@ -24267,6 +25224,9 @@ msgstr "Registro más reciente"
msgid "SortOptions|Recently starred"
msgstr "Destacados más recientes"
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr "Tamaño"
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "Código fuente"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ msgstr "Especifique un patrón para la expresión regular de direcciones de corr
msgid "Specify the following URL during the Runner setup:"
msgstr "Especifique la siguiente dirección URL durante la configuración del ejecutor:"
-msgid "Speed up your DevOps%{br_tag}with GitLab"
-msgstr ""
-
msgid "Squash commit message"
msgstr "Modificar el mensaje de commit"
@@ -24453,6 +25407,9 @@ msgstr "Estrellas"
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr "Iniciar Terminal web"
@@ -24609,6 +25566,9 @@ msgstr "Estadísticas"
msgid "Status"
msgstr "Estado"
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr "Estado:"
@@ -24738,6 +25698,9 @@ msgstr "Enviar como correo no deseado"
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr "Enviar comentarios"
@@ -24753,6 +25716,9 @@ msgstr "Enviar búsqueda"
msgid "Submit the current review."
msgstr "Enviar la revisión actual."
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr "Se ha enviado la revisión actual."
@@ -24795,6 +25761,12 @@ msgstr "Suscripción creada correctamente."
msgid "Subscription successfully deleted."
msgstr "Suscripción eliminada correctamente."
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr "Facturación"
@@ -24879,6 +25851,9 @@ msgstr "Éxito"
msgid "Successfully activated"
msgstr "Activado correctamente"
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "Bloqueado con éxito"
@@ -24900,6 +25875,9 @@ msgstr "Correo electrónico eliminado con éxito."
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr "Se ha programado un pipeline a ejecutar. Vaya a la página %{pipelines_link_start}Pipelines%{pipelines_link_end} para obtener más detalles."
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr "Desbloqueado con éxito"
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr "Sincronizar información"
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr "Sincronizado"
msgid "Synchronization disabled"
msgstr "Sincronización deshabilitada"
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr "Sistema"
@@ -25068,6 +26052,9 @@ msgstr "Métricas del sistema (personalizadas)"
msgid "System metrics (Kubernetes)"
msgstr "Métricas del sistema (Kubernetes)"
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr "Tabla de contenidos"
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,8 +26397,8 @@ msgstr "¡Gracias por su compra!"
msgid "Thanks! Don't show me this again"
msgstr "¡Gracias! No mostrar esto de nuevo"
-msgid "That's it, well done!%{celebrate}"
-msgstr "Eso es todo, ¡bien hecho!%{celebrate}"
+msgid "That's it, well done!"
+msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "El grupo \"%{group_path}\" le permite iniciar sesión utilizando su cuenta de inicio de sesión único"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ msgstr "El gestor de incidencias es el lugar para agregar cosas que necesitan se
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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr "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\")."
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "No se exportarán los siguientes elementos:"
@@ -25555,8 +26566,8 @@ msgstr ""
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr "La configuración global requiere que habilite la autenticación de dos factores para su cuenta."
-msgid "The group and any internal projects can be viewed by any logged in user."
-msgstr "El grupo y cualquier proyecto interno pueden ser vistos por cualquier usuario conectado."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
msgstr "El grupo y cualquier proyecto público se pueden ver sin necesidad de autenticación."
@@ -25666,8 +26677,8 @@ msgstr "La etapa de planificación muestra el tiempo desde el paso anterior hast
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr "La clave privada que se utiliza cuando se proporciona un certificado cliente. Este valor está encriptado."
-msgid "The project can be accessed by any logged in user."
-msgstr "El proyecto puede ser accedido por cualquier usuario conectado."
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr "El proyecto puede ser consultado por cualquier usuario que ha iniciado sesión."
@@ -25726,6 +26737,9 @@ msgstr "La etapa de revisión muestra el tiempo desde la creación de la solicit
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "La hoja de ruta muestra el progreso de sus tareas épicas a lo largo de una línea de tiempo"
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr "¡El horario programado debe ser en el futuro!"
@@ -25738,8 +26752,8 @@ msgstr "El fragmento de código sólo es visible por mí."
msgid "The snippet is visible only to project members."
msgstr "El fragmento de código es visible sólo por los miembros del proyecto."
-msgid "The snippet is visible to any logged in user."
-msgstr "El fragmento de código es visible por cualquier usuario que haya iniciado sesión."
+msgid "The snippet is visible to any logged in user except external users."
+msgstr ""
msgid "The specified tab is invalid, please select another"
msgstr "La pestaña especificada no es válida, por favor seleccione otra"
@@ -25777,6 +26791,9 @@ 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 "El mapa del usuarios es una asignación de los usuarios de FogBugz que participaron en sus proyectos a la forma en que su dirección de correo electrónico y nombre de usuario se importarán a GitLab. Puede cambiar esto rellenando la tabla a continuación."
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr "El usuario que está intentando desactivar ha estado activo en los últimos %{minimum_inactive_days} días y no puede ser desactivado"
@@ -25885,6 +26902,9 @@ msgstr "Ya hay un repositorio con ese nombre en el disco"
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr "No hay datos disponibles. Por favor, cambie su selección."
@@ -25913,13 +26933,13 @@ msgid "There was a problem fetching project branches."
msgstr ""
msgid "There was a problem fetching project tags."
-msgstr ""
+msgstr "Se ha producido un error al recuperar las etiquetas del proyecto."
msgid "There was a problem fetching project users."
-msgstr ""
+msgstr "Se ha producido un problema al recuperar los usuarios del proyecto."
msgid "There was a problem fetching users."
-msgstr ""
+msgstr "Se ha producido un error al recuperar los usuarios."
msgid "There was a problem refreshing the data, please try again"
msgstr ""
@@ -25964,7 +26984,7 @@ msgid "There was an error fetching median data for stages"
msgstr ""
msgid "There was an error fetching the %{replicableType}"
-msgstr ""
+msgstr "Se ha producido un error al obtener el %{replicableType}"
msgid "There was an error fetching the Geo Settings"
msgstr ""
@@ -25976,7 +26996,7 @@ msgid "There was an error fetching the deploy freezes."
msgstr ""
msgid "There was an error fetching the environments information."
-msgstr ""
+msgstr "Se ha producido un error al obtener información sobre los entornos."
msgid "There was an error fetching the top labels for the selected group"
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr "Se ha producido un error con reCAPTCHA. Por favor, resuelva el reCAPTCHA
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr "Estas incidencias tienen un título similar al de la incidencia que está creando. Sería mejor hacer un comentario en alguna de estas en vez de crear otra incidencia similar."
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr "Estas variables están configuradas en la configuración del grupo principal, y estarán activas en el proyecto actual junto con las variables del proyecto."
@@ -26131,7 +27154,7 @@ msgstr "Esta acción puede provocar la pérdida de datos. Para prevenir acciones
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr "Esta aplicación fue creada por %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Está aplicación podrá:"
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr "Este bloque es auto-referencial"
@@ -26290,6 +27319,9 @@ msgstr "Esta es una lista de dispositivos desde los que ha iniciado sesión. Cie
msgid "This is a security log of important events involving your account."
msgstr "Este es un registro de seguridad de eventos importantes relacionados con su cuenta."
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Esta es su sesión actual"
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr "solo ahora"
msgid "Timeago|right now"
msgstr "justo ahora"
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr "Tiempo de espera"
@@ -26885,8 +27926,8 @@ msgstr "Títulos y descripciones"
msgid "To"
msgstr "Para"
-msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
-msgstr "Para %{link_to_help} de su dominio, añada la clave anterior a un registro TXT dentro de su configuración DNS."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
+msgstr ""
msgid "To Do"
msgstr "Tareas pendientes"
@@ -26936,8 +27977,8 @@ msgstr "Para comenzar, introduzca la URL de su servidor de Gitea y un %{link_to_
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
msgstr "Para ayudar a mejorar GitLab y su experiencia de usuario, GitLab recopilará periódicamente información de uso."
-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 "Para ayudar a mejorar GitLab, nos gustaría recopilar periódicamente información de uso. Esto se puede cambiar en cualquier momento en %{settings_link_start}Configuraciones%{link_end}. %{info_link_start}Más información%{link_end}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
+msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "Para importar un repositorio SVN, puede ver %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr "Alternar navegación"
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Ocultar/mostrar barra lateral"
@@ -27117,7 +28161,7 @@ msgid "Total Contributions"
msgstr "Colaboraciones totales"
msgid "Total Score"
-msgstr ""
+msgstr "Puntuación total"
msgid "Total artifacts size: %{total_size}"
msgstr "Tamaño total de los artefactos: %{total_size}"
@@ -27137,17 +28181,20 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr "Tiempo total de pruebas para todos los cambios o integraciones"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr "Peso total"
msgid "Total: %{total}"
msgstr "Total: %{total}"
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
-msgstr "Traza"
+msgid "TotalRefCountIndicator|1000+"
+msgstr ""
msgid "Tracing"
msgstr "Seguimiento"
@@ -27323,6 +28370,9 @@ msgstr "Intentando comunicarse con su dispositivo. Conéctelo (si aún no lo ha
msgid "Tuesday"
msgstr "Martes"
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr "Desactivar"
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr "No se pueden guardar sus cambios. Por favor, inténtelo de nuevo."
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr "No se puede programar un pipeline para que se ejecute inmediatamente"
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr "Actualizar ahora"
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr "Actualizar variable"
@@ -27741,7 +28797,7 @@ msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
msgid "Updates"
-msgstr ""
+msgstr "Actualizaciones"
msgid "Updating"
msgstr "Actualizando"
@@ -27836,11 +28892,14 @@ msgstr "Estadísticas de uso"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr "%{help_link_start}Los ejecutores compartidos%{help_link_end} están deshabilitados, por lo que no hay límites establecidos para el uso de los pipelines"
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "Artefactos"
-msgid "UsageQuota|Build Artifacts"
-msgstr "Artefactos"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
+msgstr ""
msgid "UsageQuota|Buy additional minutes"
msgstr "Comprar minutos adicionales"
@@ -27866,6 +28925,9 @@ msgstr "Pipelines"
msgid "UsageQuota|Purchase more storage"
msgstr "Comprar más almacenamiento"
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr "Repositorios"
@@ -27878,9 +28940,36 @@ msgstr "Fragmentos de código"
msgid "UsageQuota|Storage"
msgstr "Almacenamiento"
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "Este espacio de nombres no tiene proyectos que utilicen ejecutores compartidos"
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr "|Ilimitado"
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr "Uso desde"
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr "Wiki"
msgid "UsageQuota|Wikis"
msgstr "Wikis"
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ 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 IDs"
-msgstr "IDs de usuario"
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr "Ya se informó del abuso"
msgid "UserProfile|Blocked user"
msgstr "Usuario bloqueado"
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr "Proyectos contribuidos"
@@ -28184,9 +29285,6 @@ msgstr "El nombre de usuario no está disponible."
msgid "Username is available."
msgstr "El nombre de usuario está disponible."
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr "Nombre de usuario o email"
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr "Ver documentación"
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr "Ver todas las incidencias"
@@ -28647,7 +29751,13 @@ msgstr "Clase"
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr "No es posible determinar la ruta para eliminar esta tarea épica"
msgid "We could not determine the path to remove the issue"
msgstr "No es posible determinar la ruta para eliminar esta incidencia"
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr "No ha sido posible conectar al servidor de Prometheus. O el servidor ya no existe o debe actualizar los detalles de configuración."
@@ -28792,7 +29911,7 @@ msgid "WebIDE|Merge request"
msgstr ""
msgid "Webhook"
-msgstr ""
+msgstr "Webhook"
msgid "Webhook Logs"
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr "¡Bienvenido a GitLab %{first_name}!"
msgid "Welcome to the guided GitLab tour"
msgstr "Bienvenido a la visita guiada de GitLab"
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr "¿Qué está buscando?"
msgid "What describes you best?"
msgstr "¿Qué le describe mejor?"
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Cuando un ejecutor está bloqueado, no se puede asignar a otros proyectos"
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29124,7 +30249,7 @@ msgid "WikiPage|Write your content or drag files here…"
msgstr "Escriba su contenido o arrastre archivos aquí…"
msgid "Wikis"
-msgstr ""
+msgstr "Wikis"
msgid "Wiki|Create New Page"
msgstr "Crear una página nueva"
@@ -29189,10 +30314,10 @@ msgstr "Trabajo en curso (abierto y sin asignar)"
msgid "Work in progress Limit"
msgstr "Límite de trabajo en progreso"
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr "No tiene permiso para aprobar a un usuario"
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr "Está en una instancia de sólo lectura GitLab."
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr "Está recibiendo este mensaje porque es un administrador de GitLab para %{url}."
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,12 +30449,12 @@ msgstr "Puede %{linkStart}ver el blob%{linkEnd} en su lugar."
msgid "You can also create a project from the command line."
msgstr "También puede crear un proyecto desde la línea de comandos."
-msgid "You can also press &#8984;-Enter"
-msgstr "También puede pulsar &#8984;- Enter"
-
msgid "You can also press Ctrl-Enter"
msgstr "También puede presionar Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
+msgstr "También puede pulsar ⌘-Enter"
+
msgid "You can also star a label to make it a priority label."
msgstr "También puede destacar una etiqueta para convertirla en una etiqueta prioritaria."
@@ -29336,6 +30467,15 @@ msgstr "También puede subir archivos existentes desde su ordenador utilizando l
msgid "You can always edit this later"
msgstr "Siempre puede editar esto más tarde"
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr "Se ha cancelado la suscripción a este hilo."
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr "No tiene permisos"
@@ -29573,9 +30725,6 @@ msgstr "Dejó el \"%{membershipable_human_name}\" %{source_type}."
msgid "You may close the milestone now."
msgstr "Puede cerrar el hito ahora."
-msgid "You must accept our Terms of Service and privacy policy in order to register an account"
-msgstr "Debe aceptar nuestros Términos de servicio y la política de privacidad para poder registrar una cuenta"
-
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ msgstr "Es necesario subir un archivo de exportación de proyecto de GitLab (en
msgid "You need to upload a Google Takeout archive."
msgstr "Necesita subir un archivo de Google Takeout."
-msgid "You reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
-msgstr ""
-
msgid "You successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr "Ya ha habilitado la autenticación de dos pasos utilizando una contraseÃ
msgid "YouTube"
msgstr "YouTube"
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr "Sus grupos"
msgid "Your License"
msgstr "Su licencia"
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr "Sus tokens de acceso personal caducarán en %{days_to_expire} días o menos"
@@ -29795,6 +30947,9 @@ msgstr "Actividad de sus proyectos"
msgid "Your Public Email will be displayed on your public profile."
msgstr "Su dirección de correo electrónico pública se mostrará en su perfil público."
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr "Sus Claves SSH (%{count})"
@@ -29990,7 +31145,7 @@ msgstr[0] "alrededor de 1 hora"
msgstr[1] "alrededor de %d horas"
msgid "access:"
-msgstr ""
+msgstr "acceso:"
msgid "added %{created_at_timeago}"
msgstr "añadido %{created_at_timeago}"
@@ -30020,7 +31175,7 @@ msgid "among other things"
msgstr "entre otras cosas"
msgid "and"
-msgstr ""
+msgstr "y"
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -30038,7 +31193,7 @@ msgid "archived:"
msgstr ""
msgid "as %{role}."
-msgstr ""
+msgstr "cómo %{role}."
msgid "assign yourself"
msgstr "asignar a ti mismo"
@@ -30061,9 +31216,6 @@ msgstr "nombre de la rama"
msgid "by"
msgstr "por"
-msgid "by %{user}"
-msgstr "por %{user}"
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr "El análisis de contenedores detecta vulnerabilidades conocidas en sus i
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ msgstr "Encontrado %{issuesWithCount}"
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "Investigue esta vulnerabilidad creando una incidencia"
-msgid "ciReport|Learn more about interacting with security reports"
-msgstr "Obtenga más información sobre cómo interactuar con los informes de seguridad"
-
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -30324,6 +31470,9 @@ msgstr "Ver informe completo"
msgid "closed issue"
msgstr "incidencia cerrada"
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr "comentario"
@@ -30494,8 +31643,8 @@ msgstr "de"
msgid "from %d job"
msgid_plural "from %d jobs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "de %d trabajo"
+msgstr[1] "de %d trabajos"
msgid "group"
msgstr "grupo"
@@ -30516,7 +31665,7 @@ msgid "help"
msgstr "ayuda"
msgid "http:"
-msgstr ""
+msgstr "http:"
msgid "https://your-bitbucket-server"
msgstr "https://tu-servidor-bitbucket"
@@ -30562,8 +31711,8 @@ msgstr "este es un rango de direcciones IP no válido"
msgid "is blocked by"
msgstr "está bloqueado por"
-msgid "is enabled."
-msgstr "está habilitado."
+msgid "is forbidden by a top-level group"
+msgstr ""
msgid "is invalid because there is downstream lock"
msgstr "no es válido porque hay un bloqueo en sentido descendente"
@@ -30580,6 +31729,9 @@ msgstr "no es un descendiente del grupo que es propietario de la plantilla"
msgid "is not a valid X509 certificate."
msgstr "no es un certificado X509 válido."
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr "es de solo lectura"
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr "es demasiado largo (%{current_value}). El tamaño máximo permitido es de %{max_size}."
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr "es demasiado largo (el máximo es de 100 entradas)"
@@ -30634,9 +31789,12 @@ msgstr "es demasiado grande"
msgid "jigsaw is not defined"
msgstr "jigsaw no está definido"
-msgid "last commit:"
+msgid "kuromoji custom analyzer"
msgstr ""
+msgid "last commit:"
+msgstr "último commit:"
+
msgid "latest"
msgstr "último"
@@ -30665,7 +31823,7 @@ msgid "loading"
msgstr "cargando"
msgid "locked"
-msgstr ""
+msgstr "bloqueado"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "bloqueado por %{path_lock_user_name} %{created_at}"
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr "falta"
+msgid "more information"
+msgstr "más información"
+
msgid "most recent deployment"
msgstr "despliegue más reciente"
@@ -31103,7 +32264,7 @@ msgid "password"
msgstr "contraseña"
msgid "paused"
-msgstr ""
+msgstr "pausado"
msgid "pending comment"
msgstr "comentario pendiente"
@@ -31169,9 +32330,6 @@ msgstr ""
msgid "projects"
msgstr "proyectos"
-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 "acciones rápidas"
@@ -31184,9 +32342,6 @@ msgstr "registrar"
msgid "relates to"
msgstr "relacionado con"
-msgid "released %{time}"
-msgstr "publicado el %{time}"
-
msgid "remaining"
msgstr "restante"
@@ -31211,7 +32366,7 @@ msgstr[0] "respuesta"
msgstr[1] "respuestas"
msgid "repository:"
-msgstr ""
+msgstr "repositorio:"
msgid "reset it."
msgstr "restablecer."
@@ -31264,6 +32419,9 @@ msgstr "mostrar menos"
msgid "sign in"
msgstr "iniciar sesión"
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr "ordenar:"
@@ -31274,7 +32432,7 @@ msgid "source diff"
msgstr ""
msgid "specific"
-msgstr ""
+msgstr "específico"
msgid "specified top is not part of the tree"
msgstr "La parte superior especificada no es parte del árbol"
@@ -31349,7 +32507,7 @@ msgid "to list"
msgstr "para listar"
msgid "toggle collapse"
-msgstr ""
+msgstr "Colapsar/Expandir"
msgid "triggered"
msgstr "disparado"
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr "la página del wiki"
-msgid "will be released %{time}"
-msgstr "será liberado %{time}"
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "con %{additions} adiciones, %{deletions} eliminaciones."
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr "El fichero yaml no es válido"
+msgid "your settings"
+msgstr "sus ajustes"
+
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index 17e0c8aede0..9251ee52619 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-10-02 18:42\n"
+"PO-Revision-Date: 2020-11-03 22:41\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/fa_IR/gitlab.po b/locale/fa_IR/gitlab.po
index ba109409ec6..9dd8cf854a1 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-10-02 18:42\n"
+"PO-Revision-Date: 2020-11-03 22:41\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/fi_FI/gitlab.po b/locale/fi_FI/gitlab.po
index 806b45b525c..b8cc16d8bba 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-10-02 18:47\n"
+"PO-Revision-Date: 2020-11-03 22:47\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index 5a5807e7364..ddc87f7bcda 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-10-02 18:43\n"
+"PO-Revision-Date: 2020-11-03 22:42\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index 4bb8cfa9a60..788f5986a1d 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2020-10-02 18:45\n"
+"PO-Revision-Date: 2020-11-03 22:45\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d résultat du test corrigé"
@@ -215,11 +220,6 @@ msgid_plural "%d issues in this group"
msgstr[0] ""
msgstr[1] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d ticket sélectionné"
-msgstr[1] "%d tickets sélectionnés"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -407,6 +407,16 @@ msgstr "%{count} approbations de %{name}"
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr "encore %{count}"
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr "(source externe)"
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr "- en montrer moins"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ msgstr ""
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "un ajout de %{type}"
-msgstr[1] "%{count} ajouts de %{type}"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "une modification de %{type}"
-msgstr[1] "%{count} modifications de %{type}"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr "Une personne avec un accès en écriture à la branche source a sélecti
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr "Ajouter un tableau"
msgid "Add a task list"
msgstr "Ajouter une liste de tâches"
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Ajouter un texte apparaissant dans toutes communications par courriel (%{character_limit} caractères maximum)"
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr "L’arrêt des tâches a échoué"
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Bloquer ce compte"
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Pour confirmer, veuillez saisir %{projectName}"
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ msgstr ""
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "Autorisations avancées, stockage de fichiers volumineux et paramètres d’authentification à double facteur."
-msgid "Advanced search functionality"
-msgstr ""
-
msgid "After a successful password update you will be redirected to login screen."
msgstr "Après modification de votre mot de passe, vous serez redirigé vers l’écran de connexion."
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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr "Tous les utilisateurs"
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "Autoriser les projets de ce groupe à utiliser le stockage Git LFS"
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Vous permet d’ajouter et de gérer des grappes de serveurs Kubernetes."
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ 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 "Un champ utilisateur Gitlab vide ajoutera le nom complet de l’utilisateur FogBugz (p. ex., « Par John Smith ») dans la description de tous les tickets et commentaires. Il associera ou assignera ces tickets et commentaires au créateur du projet."
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "Une erreur est survenue"
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr "Une erreur s’est produite lors de la prévisualisation du blob"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "Une erreur s’est produite lors de l’activation ou la désactivation de l’abonnement aux notifications"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "Une erreur est survenue lors de la mise à jour du poids du ticket"
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 "Une erreur s’est produite lors de la requête."
@@ -2938,6 +3094,9 @@ msgstr "Une erreur s’est produite lors de la prévisualisation de la bannière
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr "Une erreur est survenue lors de l’enregistrement du statut d’outrepa
msgid "An error occurred while saving assignees"
msgstr "Une erreur s’est produite lors de l’enregistrement des destinataires"
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr "Une erreur est survenue lors de l’abonnement aux notifications."
@@ -2980,6 +3136,9 @@ msgstr "Une erreur est survenue lors du désabonnement aux notifications."
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr "Assigné à moi"
@@ -3801,8 +3966,29 @@ msgstr "Auto DevOps va automatiquement construire, tester et déployer votre app
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Apprenezâ€en davantage en consultant la %{link_to_documentation}"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "Le pipeline Auto DevOps a été activé et sera utilisé si aucun autre fichier de configuration d’intégration continue n’est trouvé. %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr ""
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr "Disponible"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr "URL de l’image du badge"
msgid "Badges|Badge image preview"
msgstr "Aperçu de l’image du badge"
-msgid "Badges|Delete badge"
-msgstr "Supprimer le badge"
-
msgid "Badges|Delete badge?"
msgstr "Supprimer le badge ?"
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr "Importation d’un serveur Bitbucket"
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr "La branche %{branchName} n’a pas été trouvée dans le dépôt de ce
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr "paramètres du projet"
msgid "Branches|protected"
msgstr "protégée"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr "Tous les environnements"
msgid "CiVariable|Create wildcard"
msgstr "Créer un joker"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr "Changer l’état de protection"
-msgid "CiVariable|Validation failed"
-msgstr "La validation a échoué"
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr "Clore l’épopée"
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr "Tickets clos"
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr "En savoir plus sur les %{help_link_start_machine_type}types de machine
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "En savoir plus sur %{help_link_start}les zones%{help_link_end}."
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr "En savoir plus sur Kubernetes"
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr "Aucun projet trouvé"
msgid "ClusterIntegration|No projects matched your search"
msgstr "Aucun projet ne correspond à votre recherche"
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 "Supprimer l’intégration de la grappe de serveurs Kubernetes"
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr "Rechercher des projets"
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr "Sélectionnez le projet afin de choisir la zone"
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr "Sélectionnez la zone"
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr "Créé le"
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr "Créé le :"
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr "Nom d’hôte personnalisé (pour les courriels de commit privés)"
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr "Supprimer L’extrait de code"
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr "Supprimer la liste"
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr "Refuser"
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr "Déployé sur"
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr "En cours de déploiement sur"
@@ -8808,6 +9117,9 @@ msgstr "Description"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr "Les modèles de description permettent de définir des modèles spécifiques au contexte et propres à votre projet pour les champs de description des tickets et des demandes de fusion."
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr "Limites du contenu du diff"
@@ -9030,7 +9363,7 @@ msgstr "Désactiver les exécuteurs de groupe"
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr "Documentation des principaux fournisseurs d’identité"
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr "Domaine"
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "Ne plus afficher"
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "Se termine à (UTC)"
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr "Configurer"
msgid "FeatureFlags|Configure feature flags"
msgstr "Configurer les indicateurs de fonctionnalité"
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr "Créer un indicateur de fonctionnalité"
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "févr."
@@ -11191,12 +11611,18 @@ msgstr "Modèles de fichiers"
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "Fichiers"
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr "Filtrer…"
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr "Terminé"
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr "Date fixée"
@@ -11386,8 +11821,8 @@ 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 "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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
msgid "For more info, read the documentation."
msgstr ""
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr "Stratégie Git pour les pipelines"
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr "Version de Git"
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr "URL du groupe"
msgid "Group avatar"
msgstr "Avatar de groupe"
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "Historique"
@@ -13163,9 +13646,6 @@ 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 "J’accepte les %{terms_link}"
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "Si activé, l’accès aux projets sera validé sur un service externe en se basant sur leurs étiquettes de classification respectives."
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr "Importez plusieurs dépôts en téléversant un fichier manifeste."
msgid "Import project"
msgstr "Importer un projet"
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "Inclure un accord sur les conditions générales d’utilisation et la politique de confidentialité que tous les utilisateurs doivent accepter."
@@ -13710,27 +14235,33 @@ msgstr "Entrer les clefs d’hôte manuellement"
msgid "Input your repository URL"
msgstr "Entrez l’URL de votre dépôt"
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr "Installer GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "Installez un exécuteur sur Kubernetes"
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,38 +14441,59 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "Les personnes intéressées peuvent même contribuer en poussant des commits si elles le souhaitent."
msgid "Internal"
msgstr ""
-msgid "Internal - The group and any internal projects can be viewed by any logged in user."
-msgstr "Interne — le groupe ainsi que tous les projets internes sont accessibles à tout utilisateur connecté."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
-msgstr "Interne — le projet est accessible à n’importe quel·le utilisa·teur·trice connecté·e."
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "Internal URL (optional)"
msgstr ""
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr "Utilisateurs internes"
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Modèle d’intervalle"
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "Tableaux des tickets"
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr "janv."
msgid "January"
msgstr "janvier"
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ msgstr "Promouvoir l’étiquette"
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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr "Dernier pipeline"
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr "Dernière réponse de"
@@ -14836,6 +15523,9 @@ msgstr "Dernière mise à jour"
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr "En savoir plus"
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr "Laisser les options « type de fichier » et « mode de livraisonÂ
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr "mars"
msgid "March"
msgstr "mars"
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr "Verrouillage des membres"
msgid "Member since %{date}"
msgstr "Membre depuis le %{date}"
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr "Membres"
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ 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 "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr "Jamais"
msgid "New"
msgstr "Nouveau"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr "Nouvelle application"
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr "Aucun·e"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr "Données insuffisantes"
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr "Pas maintenant"
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ msgstr ""
msgid "Open issues"
msgstr ""
-msgid "Open projects"
-msgstr "Ouvrir des projets"
-
msgid "Open raw"
msgstr ""
msgid "Open sidebar"
msgstr "Ouvrir la barre latérale"
-msgid "Open: %{openIssuesCount}"
-msgstr ""
-
-msgid "Open: %{open} • Closed: %{closed}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr "Les personnes sans autorisation ne recevront jamais de notifications et
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr "Optimisation des performances"
@@ -18695,6 +19512,9 @@ msgstr "Taux de réussite :"
msgid "PipelineCharts|Successful:"
msgstr "Réussites :"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "Total :"
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr "CI Lint"
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr "Premiers pas avec les pipelines"
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Réinitialisation du cache de projet réussie."
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr "Veuillez saisir un nom descriptif pour votre groupe."
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Veuillez noter que cette application n’est pas fournie par GitLab, vous devriez vérifier son authenticité avant d’autoriser son accès."
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr "Push"
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr "Actualiser"
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "L’affichage sera réactualisé dans une seconde avec le statut mis à jour..."
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr "Rouvrir l’épopée"
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr "Paramètres du dépôt"
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,8 +22719,8 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
-msgstr "Exiger de tous les utilisateurs de ce groupe la configuration de l’authentification à double facteur"
+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 "Exiger que tous les utilisateurs acceptent les conditions générales d’utilisation et la politique de confidentialité quand ils accèdent à GitLab."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+msgstr ""
+
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
msgstr "Revoyez le processus de configuration des fournisseurs de service chez votre fournisseur d’identité — dans le cas présent, GitLab est le « fournisseur de service » ou le « tiers de confiance »."
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr "Clefs SSH de l’hôte"
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr "Clef SSH publique"
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ msgstr "Sauvegarder la planification du pipeline"
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 variables"
-msgstr "Enregistrer les variables"
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "Planifier un nouveau pipeline"
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr "Rechercher"
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr "Rechercher des demandes de fusion"
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr "Sélectionnez les projets que vous souhaitez importer."
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr "Sélectionnez la branche que vous souhaitez définir comme branche par d
msgid "Select the custom project template source group."
msgstr "Sélectionnez le groupe source de modèles de projet personnalisés."
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr "septembre"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr "Modèles de service"
msgid "Service URL"
msgstr "URL du service"
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "Configurez votre projet afin de pouvoir pousser et/ou récupérer automatiquement les modifications vers ou depuis un autre dépôt. Les branches, les étiquetets et les commits seront automatiquement synchronisés."
@@ -23582,6 +24524,15 @@ msgstr "Exécuteurs partagés"
msgid "Shared projects"
msgstr "Projets partagés"
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ msgstr "Transactions Sherlock"
msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
msgstr ""
+msgid "Show Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr "Connexion / Inscription"
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr "Restrictions de connexion"
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr "Restrictions d’inscription"
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr "Niveau d’accès, croissant"
msgid "SortOptions|Access level, descending"
msgstr "Niveau d’accès décroissant"
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr "Date de création décroissante"
@@ -24267,6 +25224,9 @@ msgstr "Date d’inscription décroissante"
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "Code source"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ msgstr "Spécifiez un motif d’expression rationnelle permettant l’identifica
msgid "Specify the following URL during the Runner setup:"
msgstr "Spécifiez l’URL suivante lors de la configuration de l’exécuteur :"
-msgid "Speed up your DevOps%{br_tag}with GitLab"
-msgstr ""
-
msgid "Squash commit message"
msgstr ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr "État "
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr "Soumettre comme indésirable"
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr "Soumettre la recherche"
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr "Synchroniser les informations"
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr "Métriques du système (personnalisées)"
msgid "System metrics (Kubernetes)"
msgstr "Métriques du système (Kubernetes)"
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr "Merci ! Ne plus afficher ce message"
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ msgstr "Le système de suivi est un endroit où l’on peut ouvrir un ticket pou
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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,8 +26677,8 @@ msgstr "L’étape de planification montre le temps entre l’étape précédent
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr "La clef privée à utiliser lorsqu’un certificat client est fourni. Cette valeur est chiffrée au repos."
-msgid "The project can be accessed by any logged in user."
-msgstr "Votre projet est accessible à tous les utilisateur et utilisatrices authentifiés."
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr ""
@@ -25726,6 +26737,9 @@ msgstr "L’étape d’évaluation montre le temps entre la création de la dema
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "La feuille de route affiche la progression de vos épopées dans le temps"
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "La carte des utilisateurs met en correspondance les utilisateurs de FogBugz qui ont participé à vos projets en précisant la manière dont leurs adresses de courriel et leurs noms d’utilisateur sont importés dans GitLab. Vous pouvez y apporter des modifications en remplissant le tableau ciâ€dessous."
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr "Cette application a été créée par %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Cette application sera en mesure de :"
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr "à l’instant"
msgid "Timeago|right now"
msgstr "immédiatement"
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr "Délai d’attente"
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,8 +27977,8 @@ msgstr "Pour commencer, entrez l’URL de votre hôte Gitea et un %{link_to_pers
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
msgstr "Afin d’aider à améliorer GitLab et son expérience utilisateur, GitLab va recueillir périodiquement des informations sur son utilisation."
-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 "Afin d’aider à améliorer GitLab, nous aimerions recueillir périodiquement des informations sur son utilisation. Vous pourrez modifier ceci à tout moment dans les %{settings_link_start}paramètres%{link_end}. %{info_link_start}Plus d’informations…%{link_end}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
+msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "Pour importer un dépôt SVN, consultez %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr "Activer/désactiver la navigation"
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Afficher/masquer la barre latérale"
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr "Temps total de test pour tous les commits/fusions"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr "Total : %{total}"
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr "Mettre à jour maintenant"
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr "Statistiques d’utilisation"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr "Déjà signalé comme abus"
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr "A contribué aux projets"
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr "Classe"
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Lorsqu’un exécuteur est verrouillé, il ne peut pas être affecté à d’autres projets"
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr "Vous êtes sur une instance GitLab en lecture seule."
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr "Vous pouvez %{linkStart}afficher les données brutes%{linkEnd} à la pla
msgid "You can also create a project from the command line."
msgstr "Vous pouvez également créer un projet en ligne de commande."
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr "Vous n’avez pas les autorisations"
@@ -29573,9 +30725,6 @@ 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 "Vous devez accepter les conditions générales d’utilisation et la politique de confidentialité afin de pouvoir vous créer un compte"
-
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr "YouTube"
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr "Vos groupes"
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr "Activité de vos projets favoris"
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr "nom de la branche"
msgid "by"
msgstr "par"
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr "L’analyse des conteneurs permet la détection de vulnérabilités conn
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr "Voir le rapport complet"
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr "n’est pas un certificat X.509 valide."
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr "restant"
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "avec %{additions} ajouts, %{deletions} suppressions."
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 624e0aa9d57..f8ae5fb08cf 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -16,7 +16,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
-msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
+msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
msgid " %{start} to %{end}"
@@ -82,6 +82,11 @@ msgid_plural "%d Approvals"
msgstr[0] ""
msgstr[1] ""
+msgid "%d Other"
+msgid_plural "%d Others"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d Package"
msgid_plural "%d Packages"
msgstr[0] ""
@@ -220,11 +225,6 @@ 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] ""
@@ -356,6 +356,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance."
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -412,6 +415,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -440,6 +453,9 @@ msgstr ""
msgid "%{count} total weight"
msgstr ""
+msgid "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} High%{highEnd} and %{otherStart}%{otherMessage}%{otherEnd}"
+msgstr ""
+
msgid "%{dashboard_path} could not be found."
msgstr ""
@@ -512,21 +528,27 @@ 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 "%{issueType} actions"
+msgstr ""
+
msgid "%{issuesCount} issues with a limit of %{maxIssueCount}"
msgstr ""
msgid "%{issuesSize} with a limit of %{maxIssueCount}"
msgstr ""
+msgid "%{labelStart}Actual response:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{labelStart}Assert:%{labelEnd} %{assertion}"
+msgstr ""
+
msgid "%{labelStart}Class:%{labelEnd} %{class}"
msgstr ""
@@ -542,9 +564,6 @@ msgstr ""
msgid "%{labelStart}File:%{labelEnd} %{file}"
msgstr ""
-msgid "%{labelStart}Headers:%{labelEnd} %{headers}"
-msgstr ""
-
msgid "%{labelStart}Image:%{labelEnd} %{image}"
msgstr ""
@@ -560,13 +579,13 @@ msgstr ""
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
-msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
+msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{labelStart}Status:%{labelEnd} %{status}"
+msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
msgstr ""
-msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
msgid "%{label_for_message} unavailable"
@@ -702,37 +721,16 @@ 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}."
+msgid "%{reportType} %{status}"
msgstr ""
-msgid "%{reportType} %{status} detected %{criticalStart}%{critical} critical%{criticalEnd} and %{highStart}%{high} high%{highEnd} severity vulnerabilities."
+msgid "%{reportType} detected %{totalStart}%{total}%{totalEnd} potential %{vulnMessage}"
msgstr ""
-msgid "%{reportType} %{status} detected %{criticalStart}%{critical} critical%{criticalEnd} severity vulnerabilities out of %{total}."
+msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
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}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -884,6 +882,9 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgstr ""
+
msgid "%{username}'s avatar"
msgstr ""
@@ -1042,6 +1043,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1054,16 +1058,6 @@ msgstr ""
msgid "0t1DgySidms"
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] ""
@@ -1858,9 +1852,15 @@ msgstr ""
msgid "Admin notes"
msgstr ""
+msgid "AdminArea|%{billable_users_link_start}Learn more%{billable_users_link_end} about what defines a billable user"
+msgstr ""
+
msgid "AdminArea|Active users"
msgstr ""
+msgid "AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}."
+msgstr ""
+
msgid "AdminArea|Billable users"
msgstr ""
@@ -1909,6 +1909,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1933,6 +1936,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2287,6 +2293,9 @@ msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
+msgid "After sign-out path"
+msgstr ""
+
msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
@@ -2472,12 +2481,48 @@ msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
msgstr ""
+msgid "AlertMappingBuilder|Define fallback"
+msgstr ""
+
+msgid "AlertMappingBuilder|GitLab alert key"
+msgstr ""
+
+msgid "AlertMappingBuilder|Make selection"
+msgstr ""
+
+msgid "AlertMappingBuilder|Payload alert key"
+msgstr ""
+
+msgid "AlertMappingBuilder|Select key"
+msgstr ""
+
+msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
+msgstr ""
+
msgid "AlertService|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Add link to your Opsgenie alert list"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|3. Set up webhook"
+msgstr ""
+
+msgid "AlertSettings|4. Sample alert payload (optional)"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2502,6 +2547,15 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Delete integration"
+msgstr ""
+
+msgid "AlertSettings|Edit payload"
+msgstr ""
+
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
@@ -2514,24 +2568,66 @@ msgstr ""
msgid "AlertSettings|HTTP endpoint"
msgstr ""
+msgid "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields."
+msgstr ""
+
+msgid "AlertSettings|If you've provided a sample alert payload, you can create a custom mapping for your endpoint. The default GitLab alert keys are listed below. Please define which payload key should map to the specified GitLab key."
+msgstr ""
+
+msgid "AlertSettings|In free versions of GitLab, only one integration for each type can be added. %{linkStart}Upgrade your subscription%{linkEnd} to add additional integrations."
+msgstr ""
+
msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our improvements for %{linkStart}integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
msgstr ""
+msgid "AlertSettings|Proceed with editing"
+msgstr ""
+
+msgid "AlertSettings|Prometheus API base URL"
+msgstr ""
+
+msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to create a custom mapping (optional), or to test the integration (also optional)."
+msgstr ""
+
+msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to test the integration (optional)."
+msgstr ""
+
+msgid "AlertSettings|Reset Key"
+msgstr ""
+
msgid "AlertSettings|Reset key"
msgstr ""
+msgid "AlertSettings|Reset the mapping"
+msgstr ""
+
msgid "AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in."
msgstr ""
msgid "AlertSettings|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
msgstr ""
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgstr ""
+
+msgid "AlertSettings|Save and test payload"
+msgstr ""
+
+msgid "AlertSettings|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
+msgid "AlertSettings|Submit payload"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2550,6 +2646,18 @@ msgstr ""
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
+msgid "AlertSettings|Utilize the URL and authorization key below to authorize Prometheus to send alerts to GitLab. Review the Prometheus documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
+msgstr ""
+
+msgid "AlertSettings|Utilize the URL and authorization key below to authorize an external service to send alerts to GitLab. Review your external service's documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
+msgstr ""
+
+msgid "AlertSettings|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
+msgstr ""
+
+msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2562,6 +2670,9 @@ msgstr ""
msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
+msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
+msgstr ""
+
msgid "Alerts"
msgstr ""
@@ -2583,12 +2694,36 @@ msgstr ""
msgid "AlertsIntegrations|Integration Name"
msgstr ""
+msgid "AlertsIntegrations|Integration payload is invalid. You can still save your changes."
+msgstr ""
+
msgid "AlertsIntegrations|No integrations have been added yet"
msgstr ""
msgid "AlertsIntegrations|Prometheus"
msgstr ""
+msgid "AlertsIntegrations|The current integration could not be updated. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration could not be added. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration could not be deleted. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration has been successfully removed."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration has been successfully saved. Alerts from this new integration should now appear on your alerts list."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|You have opted to delete the %{integrationName} integration. Do you want to proceed? It means you will no longer receive alerts from this endpoint in your alert list, and this action cannot be undone."
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2727,6 +2862,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -2784,6 +2922,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2802,6 +2943,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2835,6 +2979,9 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2919,9 +3066,6 @@ 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 lists. Please try again."
msgstr ""
@@ -2967,6 +3111,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading a section of this page."
+msgstr ""
+
msgid "An error occurred while loading all the files."
msgstr ""
@@ -2994,9 +3141,6 @@ 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 ""
@@ -3024,6 +3168,9 @@ msgstr ""
msgid "An error occurred while loading the merge request."
msgstr ""
+msgid "An error occurred while loading the pipeline."
+msgstr ""
+
msgid "An error occurred while loading the pipelines jobs."
msgstr ""
@@ -3051,9 +3198,6 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
-msgid "An error occurred while rendering the linter"
-msgstr ""
-
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3078,15 +3222,15 @@ msgstr ""
msgid "An error occurred while saving assignees"
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 generate the report. Please try again later."
+msgstr ""
+
msgid "An error occurred while trying to run a new pipeline for this Merge Request."
msgstr ""
@@ -3434,6 +3578,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived (%{movedToStart}moved%{movedToEnd})"
+msgstr ""
+
msgid "Archived in this version"
msgstr ""
@@ -3485,9 +3632,6 @@ 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 ""
@@ -3538,6 +3682,9 @@ msgstr ""
msgid "Are you sure you want to remove this identity?"
msgstr ""
+msgid "Are you sure you want to remove this list?"
+msgstr ""
+
msgid "Are you sure you want to reset registration token?"
msgstr ""
@@ -3929,12 +4076,27 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
msgstr ""
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
msgstr ""
msgid "AutoRemediation|Introducing GitLab auto-fix"
msgstr ""
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
+
msgid "Autocomplete"
msgstr ""
@@ -3953,6 +4115,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -4232,6 +4397,11 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d issue"
+msgid_plural "Blocked by %d issues"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blocked issue"
msgstr ""
@@ -4265,6 +4435,9 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
@@ -4274,9 +4447,15 @@ msgstr ""
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
+msgid "Boards|An error occurred while removing the list. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
@@ -4535,9 +4714,6 @@ msgstr ""
msgid "By %{user_name}"
msgstr ""
-msgid "By URL"
-msgstr ""
-
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4565,6 +4741,9 @@ msgstr ""
msgid "CI Lint"
msgstr ""
+msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
+msgstr ""
+
msgid "CI settings"
msgstr ""
@@ -4688,6 +4867,12 @@ msgstr ""
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
+msgid "Canary Ingress does not exist in the environment."
+msgstr ""
+
+msgid "Canary weight must be specified and valid range (0..100)."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -4721,9 +4906,6 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
-msgid "Cannot find user key."
-msgstr ""
-
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4865,6 +5047,9 @@ msgstr ""
msgid "Changes affect new repositories only. If not specified, Git's default name %{branch_name_default} will be used."
msgstr ""
+msgid "Changes affect new repositories only. If not specified, either the configured application-wide default or Git's default name %{branch_name_default} will be used."
+msgstr ""
+
msgid "Changes are shown as if the %{b_open}source%{b_close} revision was being merged into the %{b_open}target%{b_close} revision."
msgstr ""
@@ -4883,9 +5068,6 @@ 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 ""
@@ -5135,6 +5317,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5174,6 +5359,9 @@ msgstr ""
msgid "Choose labels"
msgstr ""
+msgid "Choose specific groups or storage shards"
+msgstr ""
+
msgid "Choose the top-level group for your repository imports."
msgstr ""
@@ -5318,9 +5506,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5339,9 +5524,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5390,6 +5572,12 @@ msgstr ""
msgid "Clears weight."
msgstr ""
+msgid "Click %{link_start}here%{link_end} to view the request."
+msgstr ""
+
+msgid "Click %{link_to} to view the request."
+msgstr ""
+
msgid "Click the %{strong_open}Download%{strong_close} button and wait for downloading to complete."
msgstr ""
@@ -5444,6 +5632,9 @@ msgstr ""
msgid "Close %{display_issuable_type}"
msgstr ""
+msgid "Close %{issueType}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -5474,7 +5665,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5501,6 +5692,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5537,6 +5731,9 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|%{boldStart}Note:%{boldEnd} Requires Ingress to be installed."
+msgstr ""
+
msgid "ClusterIntegration|%{externalIp}.nip.io"
msgstr ""
@@ -5684,6 +5881,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5741,9 +5941,6 @@ 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 ""
@@ -5999,9 +6196,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -6017,9 +6211,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6086,9 +6277,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6155,9 +6343,6 @@ 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 ""
@@ -6224,9 +6409,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6287,6 +6469,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6371,6 +6556,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6512,9 +6700,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6988,6 +7173,9 @@ msgstr ""
msgid "Consistency guarantee method"
msgstr ""
+msgid "Contact Sales to upgrade"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -7012,7 +7200,7 @@ msgstr ""
msgid "Container repositories"
msgstr ""
-msgid "Container repositories sync capacity"
+msgid "Container repositories synchronization concurrency limit"
msgstr ""
msgid "Container repository"
@@ -7156,6 +7344,9 @@ msgstr ""
msgid "ContainerRegistry|Something went wrong while fetching the cleanup policy."
msgstr ""
+msgid "ContainerRegistry|Something went wrong while fetching the image details."
+msgstr ""
+
msgid "ContainerRegistry|Something went wrong while fetching the repository list."
msgstr ""
@@ -7519,6 +7710,9 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not retrieve custom scanners for scanner filter. Please try again later."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
@@ -7797,6 +7991,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7890,6 +8087,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8037,6 +8237,9 @@ msgstr ""
msgid "CycleAnalyticsEvent|Merge request created"
msgstr ""
+msgid "CycleAnalyticsEvent|Merge request first commit time"
+msgstr ""
+
msgid "CycleAnalyticsEvent|Merge request first deployed to production"
msgstr ""
@@ -8141,6 +8344,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8159,9 +8365,6 @@ msgstr ""
msgid "CycleAnalytics|stage dropdown"
msgstr ""
-msgid "DAG"
-msgstr ""
-
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
@@ -8210,7 +8413,13 @@ 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."
+msgid "DastProfiles|Authentication"
+msgstr ""
+
+msgid "DastProfiles|Authentication URL"
+msgstr ""
+
+msgid "DastProfiles|Copy HTTP header to clipboard"
msgstr ""
msgid "DastProfiles|Could not create the scanner profile. Please try again."
@@ -8237,9 +8446,6 @@ 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 ""
@@ -8270,9 +8476,15 @@ msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
+msgid "DastProfiles|Enable Authentication"
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Header validation"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8306,7 +8518,10 @@ msgstr ""
msgid "DastProfiles|Passive"
msgstr ""
-msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "DastProfiles|Password"
+msgstr ""
+
+msgid "DastProfiles|Password form field"
msgstr ""
msgid "DastProfiles|Please enter a valid timeout value"
@@ -8345,18 +8560,21 @@ 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 HTTP header to your site"
+msgstr ""
+
msgid "DastProfiles|Step 2 - Add following text to the target site"
msgstr ""
+msgid "DastProfiles|Step 3 - Confirm header location and validate"
+msgstr ""
+
msgid "DastProfiles|Step 3 - Confirm text file location and validate"
msgstr ""
@@ -8378,31 +8596,25 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
-msgid "DastProfiles|Validate"
+msgid "DastProfiles|Username"
msgstr ""
-msgid "DastProfiles|Validate target site"
+msgid "DastProfiles|Username form field"
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 failed. Please try again."
+msgid "DastProfiles|Validate"
msgstr ""
-msgid "DastProfiles|Validation is in progress..."
+msgid "DastProfiles|Validating..."
msgstr ""
-msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the chosen method."
msgstr ""
-msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgid "Data is still calculating..."
msgstr ""
-msgid "Data is still calculating..."
+msgid "Database update failed"
msgstr ""
msgid "Datasource name not found"
@@ -8609,6 +8821,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8618,9 +8833,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -8672,12 +8884,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -9041,6 +9259,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9071,6 +9292,9 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
+msgid "DesignManagement|Archive design"
+msgstr ""
+
msgid "DesignManagement|Archive designs"
msgstr ""
@@ -9128,6 +9352,9 @@ msgstr ""
msgid "DesignManagement|Discard comment"
msgstr ""
+msgid "DesignManagement|Download design"
+msgstr ""
+
msgid "DesignManagement|Error uploading a new design. Please try again."
msgstr ""
@@ -9206,10 +9433,64 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps"
+msgid "DevOps Report"
msgstr ""
-msgid "DevOps Report"
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|Approvals"
+msgstr ""
+
+msgid "DevopsAdoption|Deploys"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
+msgid "DevopsAdoption|Issues"
+msgstr ""
+
+msgid "DevopsAdoption|MRs"
+msgstr ""
+
+msgid "DevopsAdoption|Pipelines"
+msgstr ""
+
+msgid "DevopsAdoption|Runners"
+msgstr ""
+
+msgid "DevopsAdoption|Scanning"
+msgstr ""
+
+msgid "DevopsAdoption|Segment"
+msgstr ""
+
+msgid "DevopsAdoption|There was an error fetching Groups"
+msgstr ""
+
+msgid "DevopsReport|Adoption"
+msgstr ""
+
+msgid "DevopsReport|DevOps"
+msgstr ""
+
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|Score"
msgstr ""
msgid "Diff content limits"
@@ -9424,6 +9705,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9445,6 +9729,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9469,9 +9756,6 @@ msgstr ""
msgid "Download as"
msgstr ""
-msgid "Download as CSV"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9520,9 +9804,15 @@ msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
msgstr ""
+msgid "Drop or %{linkStart}upload%{linkEnd} files to attach"
+msgstr ""
+
msgid "Drop your designs to start your upload."
msgstr ""
+msgid "Drop your files to start your upload."
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -9703,6 +9993,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email cannot be blank"
+msgstr ""
+
msgid "Email could not be sent"
msgstr ""
@@ -9730,6 +10023,12 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+msgstr ""
+
+msgid "Email: %{email}"
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -9802,7 +10101,7 @@ msgstr ""
msgid "Enable"
msgstr ""
-msgid "Enable %{link_start}Gitpod%{link_end} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
msgstr ""
msgid "Enable Auto DevOps"
@@ -9871,6 +10170,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9907,6 +10212,12 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
+msgstr ""
+
msgid "Enable snowplow tracking"
msgstr ""
@@ -9979,7 +10290,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10156,6 +10470,9 @@ msgstr ""
msgid "Environments|Delete"
msgstr ""
+msgid "Environments|Delete '%{environmentName}'?"
+msgstr ""
+
msgid "Environments|Delete environment"
msgstr ""
@@ -10267,6 +10584,9 @@ msgstr ""
msgid "Environments|Stopping"
msgstr ""
+msgid "Environments|Stopping %{environmentName}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -10543,6 +10863,9 @@ msgstr ""
msgid "Error occurred. User was not unlocked"
msgstr ""
+msgid "Error parsing CSV file. Please make sure it has"
+msgstr ""
+
msgid "Error rendering markdown preview"
msgstr ""
@@ -10621,6 +10944,9 @@ msgstr ""
msgid "Errors"
msgstr ""
+msgid "Errors found on line %{line_number}: %{error_lines}. Please check if these lines have a requirement title."
+msgstr ""
+
msgid "Errors:"
msgstr ""
@@ -10750,6 +11076,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10780,6 +11109,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10849,12 +11181,18 @@ msgstr ""
msgid "Export as CSV"
msgstr ""
+msgid "Export commit custody report"
+msgstr ""
+
msgid "Export group"
msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10915,6 +11253,11 @@ msgstr ""
msgid "Failed"
msgstr ""
+msgid "Failed %d time in the last 14 days"
+msgid_plural "Failed %d times in the last 14 days"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed Jobs"
msgstr ""
@@ -10957,6 +11300,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -11020,6 +11366,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -11032,6 +11381,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11119,6 +11471,9 @@ msgstr ""
msgid "Failed to update tag!"
msgstr ""
+msgid "Failed to update the Canary Ingress."
+msgstr ""
+
msgid "Failed to update."
msgstr ""
@@ -11158,6 +11513,9 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag is not enabled on the environment's project."
+msgstr ""
+
msgid "Feature flag was not removed."
msgstr ""
@@ -11331,6 +11689,9 @@ msgstr ""
msgid "FeatureFlags|New user list"
msgstr ""
+msgid "FeatureFlags|No user list selected"
+msgstr ""
+
msgid "FeatureFlags|Percent of users"
msgstr ""
@@ -11340,7 +11701,7 @@ msgstr ""
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11373,9 +11734,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11391,9 +11749,6 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
@@ -11412,6 +11767,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11460,7 +11818,7 @@ msgstr ""
msgid "File renamed with no changes."
msgstr ""
-msgid "File sync capacity"
+msgid "File synchronization concurrency limit"
msgstr ""
msgid "File templates"
@@ -11478,6 +11836,9 @@ msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11502,6 +11863,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11610,9 +11974,6 @@ msgstr ""
msgid "First name"
msgstr ""
-msgid "First name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First seen"
msgstr ""
@@ -11673,7 +12034,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12240,6 +12601,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12258,6 +12622,9 @@ msgstr ""
msgid "GitLab API"
msgstr ""
+msgid "GitLab Account Request"
+msgstr ""
+
msgid "GitLab Billing Team."
msgstr ""
@@ -12300,6 +12667,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12495,7 +12868,7 @@ 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."
+msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
msgstr ""
msgid "Go full screen"
@@ -12879,6 +13252,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12888,6 +13267,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12933,12 +13315,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12951,6 +13351,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12963,6 +13366,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12987,6 +13393,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13215,12 +13624,6 @@ 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 ""
@@ -13447,9 +13850,6 @@ 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 ""
@@ -13465,7 +13865,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13591,6 +13991,9 @@ msgstr ""
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
+msgid "If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be able to view the %{codeStart}needs%{codeEnd} relationships between jobs in this tab as a %{linkStart}Directed Acyclic Graph (DAG)%{linkEnd}."
+msgstr ""
+
msgid "If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
msgstr ""
@@ -13757,6 +14160,9 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -13790,6 +14196,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Imported requirements"
+msgstr ""
+
msgid "Improve Issue Boards"
msgstr ""
@@ -14087,6 +14496,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -14116,51 +14528,93 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
-msgid "InstanceAnalytics|Canceled"
+msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
-msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgid "InstanceStatistics|Could not load the pipelines chart. Please refresh the page to try again."
msgstr ""
-msgid "InstanceAnalytics|Failed"
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
msgstr ""
-msgid "InstanceAnalytics|Items"
+msgid "InstanceStatistics|Groups"
msgstr ""
-msgid "InstanceAnalytics|Month"
+msgid "InstanceStatistics|Issues"
msgstr ""
-msgid "InstanceAnalytics|Pipelines"
+msgid "InstanceStatistics|Issues & Merge Requests"
msgstr ""
-msgid "InstanceAnalytics|Skipped"
+msgid "InstanceStatistics|Items"
msgstr ""
-msgid "InstanceAnalytics|Succeeded"
+msgid "InstanceStatistics|Merge Requests"
msgstr ""
-msgid "InstanceAnalytics|There is no data available."
+msgid "InstanceStatistics|Month"
msgstr ""
-msgid "InstanceAnalytics|Total"
+msgid "InstanceStatistics|No data available."
msgstr ""
-msgid "InstanceStatistics|Groups"
+msgid "InstanceStatistics|Pipelines"
msgstr ""
-msgid "InstanceStatistics|Issues"
+msgid "InstanceStatistics|Pipelines canceled"
msgstr ""
-msgid "InstanceStatistics|Merge Requests"
+msgid "InstanceStatistics|Pipelines failed"
msgstr ""
-msgid "InstanceStatistics|Pipelines"
+msgid "InstanceStatistics|Pipelines skipped"
+msgstr ""
+
+msgid "InstanceStatistics|Pipelines succeeded"
+msgstr ""
+
+msgid "InstanceStatistics|Pipelines total"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error fetching the cancelled pipelines"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the failed pipelines"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the issues"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the merge requests"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the skipped pipelines"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the successful pipelines"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the total pipelines"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -14182,6 +14636,9 @@ msgstr ""
msgid "Integrations|All details"
msgstr ""
+msgid "Integrations|All projects inheriting these settings will also be reset."
+msgstr ""
+
msgid "Integrations|Comment detail:"
msgstr ""
@@ -14194,6 +14651,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -14209,7 +14669,19 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
-msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
+msgid "Integrations|Projects using custom settings will not be affected."
+msgstr ""
+
+msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults."
+msgstr ""
+
+msgid "Integrations|Reset integration?"
+msgstr ""
+
+msgid "Integrations|Resetting this integration will clear the settings and deactivate this integration."
msgstr ""
msgid "Integrations|Return to GitLab for Jira"
@@ -14221,9 +14693,15 @@ msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
msgid "Integrations|Update your projects on Packagist, the main Composer repository"
msgstr ""
@@ -14248,10 +14726,10 @@ msgstr ""
msgid "Internal"
msgstr ""
-msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -14317,6 +14795,9 @@ msgstr ""
msgid "Invalid file."
msgstr ""
+msgid "Invalid hash"
+msgstr ""
+
msgid "Invalid import params"
msgstr ""
@@ -14359,6 +14840,9 @@ msgstr ""
msgid "Invalid yaml"
msgstr ""
+msgid "Investigate vulnerability: %{title}"
+msgstr ""
+
msgid "Invitation"
msgstr ""
@@ -14383,28 +14867,31 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite team members"
+msgstr ""
+
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14428,6 +14915,9 @@ msgstr ""
msgid "InviteMembersModal|Choose a role permission"
msgstr ""
+msgid "InviteMembersModal|Close invite team members"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or Email address"
msgstr ""
@@ -14437,16 +14927,16 @@ msgstr ""
msgid "InviteMembersModal|Invite team members"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|User not invited. Feature coming soon!"
+msgid "InviteMembersModal|Search for members to invite"
msgstr ""
-msgid "InviteMembersModal|Users were succesfully added"
+msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{group_name} group"
+msgid "InviteMembersModal|You're inviting members to the %{name} %{type}"
msgstr ""
msgid "InviteMembers|Invite team members"
@@ -14617,6 +15107,9 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while setting notifications status."
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -14770,6 +15263,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14929,6 +15425,15 @@ msgstr ""
msgid "Jobs"
msgstr ""
+msgid "Jobs|Are you sure you want to proceed?"
+msgstr ""
+
+msgid "Jobs|Are you sure you want to retry this job?"
+msgstr ""
+
+msgid "Jobs|You're about to retry a job that failed because it attempted to deploy code that is older than the latest deployment. Retrying this job could result in overwriting the environment with the older source code."
+msgstr ""
+
msgid "Job|Browse"
msgstr ""
@@ -15240,9 +15745,6 @@ msgstr ""
msgid "Last name"
msgstr ""
-msgid "Last name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last reply by"
msgstr ""
@@ -15276,6 +15778,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15333,6 +15838,9 @@ msgstr ""
msgid "Learn more about License-Check"
msgstr ""
+msgid "Learn more about Needs relationships"
+msgstr ""
+
msgid "Learn more about Vulnerability-Check"
msgstr ""
@@ -15360,9 +15868,6 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
-msgid "Learn more about job dependencies"
-msgstr ""
-
msgid "Learn more about signing commits"
msgstr ""
@@ -15459,9 +15964,6 @@ msgstr ""
msgid "LicenseCompliance|Learn more about %{linkStart}License Approvals%{linkEnd}"
msgstr ""
-msgid "LicenseCompliance|License"
-msgstr ""
-
msgid "LicenseCompliance|License Approvals"
msgstr ""
@@ -15501,18 +16003,9 @@ 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 ""
@@ -15528,9 +16021,6 @@ 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 ""
@@ -15636,6 +16126,9 @@ msgstr ""
msgid "Limit namespaces and projects that can be indexed"
msgstr ""
+msgid "Limit the number of concurrent operations this secondary node can run in the background."
+msgstr ""
+
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
@@ -15656,6 +16149,9 @@ msgstr ""
msgid "Link title is required"
msgstr ""
+msgid "Link to an image"
+msgstr ""
+
msgid "Link to go to GitLab pipeline documentation"
msgstr ""
@@ -15995,7 +16491,7 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
-msgid "Marked this %{noun} as Work In Progress."
+msgid "Marked this %{noun} as a draft."
msgstr ""
msgid "Marked this issue as a duplicate of %{duplicate_param}."
@@ -16007,7 +16503,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as Work In Progress."
+msgid "Marks this %{noun} as a draft."
msgstr ""
msgid "Marks this issue as a duplicate of %{duplicate_reference}."
@@ -16055,6 +16551,9 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
+msgid "Max 100,000 events"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16079,9 +16578,6 @@ msgstr ""
msgid "Max role"
msgstr ""
-msgid "Max size 15 MB"
-msgstr ""
-
msgid "MaxBuilds"
msgstr ""
@@ -16205,6 +16701,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -16232,6 +16734,18 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently an LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
msgid "Members|An error occurred while updating the member's role, please try again."
msgstr ""
@@ -16256,9 +16770,21 @@ msgstr ""
msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
msgstr ""
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
msgid "Members|Leave \"%{source}\""
msgstr ""
@@ -16271,6 +16797,12 @@ msgstr ""
msgid "Members|Remove group"
msgstr ""
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
msgid "Members|Role updated successfully."
msgstr ""
@@ -16325,6 +16857,9 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge commit SHA"
+msgstr ""
+
msgid "Merge commit message"
msgstr ""
@@ -16523,6 +17058,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16926,6 +17464,30 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Group milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -17046,12 +17608,6 @@ 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 ""
@@ -17205,6 +17761,9 @@ msgstr ""
msgid "Move selection up"
msgstr ""
+msgid "Move test case"
+msgstr ""
+
msgid "Move this issue to another project."
msgstr ""
@@ -17241,9 +17800,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -17301,8 +17866,10 @@ msgstr ""
msgid "Namespace:"
msgstr ""
-msgid "NamespaceStorageSize|%{namespace_name} contains a locked project"
-msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
msgstr ""
@@ -17310,16 +17877,21 @@ msgstr ""
msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
msgstr ""
-msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free 10GB project limit. You can't %{base_message}"
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
msgstr ""
-msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free 10GB limit. You can't %{base_message}"
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
msgstr ""
msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
msgstr ""
-msgid "NamespaceStorageSize|You have reached the free storage limit of 10GB on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To learn more about reducing storage capacity please visit our docs."
msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
@@ -17355,6 +17927,9 @@ msgstr ""
msgid "Need help?"
msgstr ""
+msgid "Needs"
+msgstr ""
+
msgid "Needs attention"
msgstr ""
@@ -17580,6 +18155,12 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
+msgid "New %{issueType}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17834,9 +18415,6 @@ msgstr ""
msgid "No containers available"
msgstr ""
-msgid "No content to show"
-msgstr ""
-
msgid "No contributions"
msgstr ""
@@ -18059,6 +18637,9 @@ msgstr ""
msgid "Not all data has been processed yet, the accuracy of the chart for the selected timeframe is limited."
msgstr ""
+msgid "Not applicable to personal namespaced projects, which are deleted immediately on request."
+msgstr ""
+
msgid "Not available"
msgstr ""
@@ -18077,9 +18658,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -18131,6 +18709,9 @@ msgstr ""
msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
msgstr ""
+msgid "Notes|You're only seeing %{boldStart}other activity%{boldEnd} in the feed. To add a comment, switch to one of the following options."
+msgstr ""
+
msgid "Nothing found…"
msgstr ""
@@ -18386,7 +18967,7 @@ 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."
+msgid "Once removed, the fork relationship cannot be restored. This project will no longer be able to receive or send merge requests to the source project or other forks."
msgstr ""
msgid "Once the exported file is ready, you will receive a notification email with a download link, or you can download it from this page."
@@ -18493,13 +19074,13 @@ msgstr ""
msgid "Open raw"
msgstr ""
-msgid "Open sidebar"
+msgid "Open registration is enabled on your instance."
msgstr ""
-msgid "Open: %{openIssuesCount}"
+msgid "Open sidebar"
msgstr ""
-msgid "Open: %{open} • Closed: %{closed}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18610,6 +19191,9 @@ msgstr ""
msgid "Outdent"
msgstr ""
+msgid "Overall Activity"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -18904,9 +19488,6 @@ msgstr ""
msgid "Page settings"
msgstr ""
-msgid "Page was successfully deleted"
-msgstr ""
-
msgid "PagerDutySettings|Active"
msgstr ""
@@ -19081,7 +19662,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent rollout must be a whole number between 0 and 100"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -19195,6 +19776,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -19276,6 +19860,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -19294,6 +19881,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -19324,6 +19914,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -19360,6 +19953,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19588,6 +20187,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19597,6 +20199,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19609,6 +20214,9 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
@@ -19720,18 +20328,12 @@ 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 ""
@@ -19741,9 +20343,6 @@ 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 ""
@@ -19765,9 +20364,6 @@ msgstr ""
msgid "Preferences|Show whitespace changes in diffs"
msgstr ""
-msgid "Preferences|Sourcegraph"
-msgstr ""
-
msgid "Preferences|Syntax highlighting theme"
msgstr ""
@@ -19954,6 +20550,24 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfilePreferences|Customize integrations with third party services."
+msgstr ""
+
+msgid "ProfilePreferences|Enable Gitpod integration"
+msgstr ""
+
+msgid "ProfilePreferences|Enable integrated code intelligence on code views"
+msgstr ""
+
+msgid "ProfilePreferences|Gitpod"
+msgstr ""
+
+msgid "ProfilePreferences|Integrations"
+msgstr ""
+
+msgid "ProfilePreferences|Sourcegraph"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -19963,6 +20577,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|\"Busy\" will be shown next to your name"
+msgstr ""
+
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -19993,6 +20610,9 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
+msgid "Profiles|Busy"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -20605,7 +21225,10 @@ msgstr ""
msgid "ProjectSettings|Enable 'Delete source branch' option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains and pipelines for merged results"
+msgid "ProjectSettings|Enable merge trains."
+msgstr ""
+
+msgid "ProjectSettings|Enable merged results pipelines."
msgstr ""
msgid "ProjectSettings|Encourage"
@@ -20647,6 +21270,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|If pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -20707,9 +21333,6 @@ 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 ""
@@ -20731,6 +21354,12 @@ msgstr ""
msgid "ProjectSettings|Require"
msgstr ""
+msgid "ProjectSettings|Requirements"
+msgstr ""
+
+msgid "ProjectSettings|Requirements management system for this project"
+msgstr ""
+
msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
msgstr ""
@@ -20800,6 +21429,9 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access"
msgstr ""
+msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgstr ""
+
msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
msgstr ""
@@ -21181,6 +21813,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote to epic"
+msgstr ""
+
msgid "Promote to group label"
msgstr ""
@@ -21649,6 +22284,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redis"
+msgstr ""
+
msgid "Reduce project visibility"
msgstr ""
@@ -21711,9 +22349,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21809,6 +22444,9 @@ msgstr ""
msgid "ReleaseAssetLinkType|Runbooks"
msgstr ""
+msgid "Released date"
+msgstr ""
+
msgid "Releases"
msgstr ""
@@ -21836,9 +22474,6 @@ msgstr ""
msgid "Remediations"
msgstr ""
-msgid "Remember me"
-msgstr ""
-
msgid "Remind later"
msgstr ""
@@ -22061,6 +22696,9 @@ msgstr ""
msgid "Reopen %{display_issuable_type}"
msgstr ""
+msgid "Reopen %{issueType}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -22142,6 +22780,15 @@ msgstr ""
msgid "Reports|%{combinedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|%{recentlyFailed} out of %{failed} failed test has failed more than once in the last 14 days"
+msgstr ""
+
+msgid "Reports|%{recentlyFailed} out of %{failed} failed tests has failed more than once in the last 14 days"
+msgstr ""
+
+msgid "Reports|%{recentlyFailed} out of %{failed} failed tests have failed more than once in the last 14 days"
+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] ""
@@ -22225,10 +22872,16 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
+msgid "RepositoriesAnalytics|Average Coverage by Job"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -22243,7 +22896,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
-msgid "RepositoriesAnalytics|Number of Coverages"
+msgid "RepositoriesAnalytics|Latest test coverage results"
msgstr ""
msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
@@ -22252,12 +22905,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Tests"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
+msgid "RepositoriesAnalytics|Total Number of Coverages"
+msgstr ""
+
msgid "Repository"
msgstr ""
@@ -22270,6 +22929,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -22315,7 +22977,7 @@ msgstr ""
msgid "Repository storage"
msgstr ""
-msgid "Repository sync capacity"
+msgid "Repository synchronization concurrency limit"
msgstr ""
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets}"
@@ -22436,12 +23098,18 @@ msgstr ""
msgid "Resend it"
msgstr ""
+msgid "Reset"
+msgstr ""
+
msgid "Reset authorization key"
msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset filters"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
@@ -22568,6 +23236,9 @@ msgstr ""
msgid "Retry"
msgstr ""
+msgid "Retry job"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -22758,6 +23429,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22785,6 +23462,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22854,6 +23534,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22908,9 +23591,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22962,7 +23642,7 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
-msgid "Score"
+msgid "Scopes: %{scope_list}"
msgstr ""
msgid "Scroll down"
@@ -22992,7 +23672,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -23049,9 +23729,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -23133,9 +23810,6 @@ 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] ""
@@ -23434,9 +24108,6 @@ msgstr ""
msgid "SecurityReports|Scan details"
msgstr ""
-msgid "SecurityReports|Scanner"
-msgstr ""
-
msgid "SecurityReports|Security Dashboard"
msgstr ""
@@ -23550,6 +24221,12 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgstr ""
+
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgstr ""
+
msgid "See what's new at GitLab"
msgstr ""
@@ -24012,12 +24689,6 @@ 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 ""
@@ -24060,21 +24731,30 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set verification limit and frequency."
+msgstr ""
+
msgid "Set weight"
msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "Set what should be replicated by choosing specific projects or groups by the secondary node."
+msgid "Set what should be replicated by this secondary node."
msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
+msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgstr ""
+
msgid "SetStatusModal|Add status emoji"
msgstr ""
+msgid "SetStatusModal|Busy"
+msgstr ""
+
msgid "SetStatusModal|Clear status"
msgstr ""
@@ -24093,6 +24773,9 @@ msgstr ""
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
+msgid "SetStatusModal|Status updated"
+msgstr ""
+
msgid "SetStatusModal|What's your status?"
msgstr ""
@@ -24189,9 +24872,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -24364,13 +25053,19 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
-msgid "SignUp|First Name is too long (maximum is %{max_length} characters)."
+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)."
+msgid "SignUp|Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Minimum length is %{minimum_password_length} characters."
msgstr ""
msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
@@ -24661,6 +25356,9 @@ msgstr ""
msgid "Something went wrong while performing the action."
msgstr ""
+msgid "Something went wrong while promoting the issue to an epic. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening a requirement."
msgstr ""
@@ -24853,6 +25551,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24943,10 +25644,10 @@ msgstr ""
msgid "SourcegraphPreferences|This feature is experimental."
msgstr ""
-msgid "SourcegraphPreferences|Uses %{link_start}Sourcegraph.com%{link_end}."
+msgid "SourcegraphPreferences|Uses %{linkStart}Sourcegraph.com%{linkEnd}."
msgstr ""
-msgid "SourcegraphPreferences|Uses a custom %{link_start}Sourcegraph instance%{link_end}."
+msgid "SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{linkEnd}."
msgstr ""
msgid "Spam Logs"
@@ -24970,7 +25671,7 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
-msgid "Speed up your DevOps%{br_tag}with GitLab"
+msgid "Speed up your pipelines with Needs relationships"
msgstr ""
msgid "Squash commit message"
@@ -25090,9 +25791,6 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start using Directed Acyclic Graphs (DAG)"
-msgstr ""
-
msgid "Start your Free Gold Trial"
msgstr ""
@@ -25195,6 +25893,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -25318,6 +26019,9 @@ msgstr ""
msgid "Submit a review"
msgstr ""
+msgid "Submit as spam"
+msgstr ""
+
msgid "Submit changes"
msgstr ""
@@ -25471,6 +26175,9 @@ msgstr ""
msgid "Succeeded"
msgstr ""
+msgid "Successful purchase image"
+msgstr ""
+
msgid "Successfully activated"
msgstr ""
@@ -25498,6 +26205,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25633,12 +26343,21 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Synchronization settings"
+msgstr ""
+
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25666,6 +26385,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25843,6 +26565,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terraform"
+msgstr ""
+
msgid "Terraform|%{number} Terraform report failed to generate"
msgid_plural "Terraform|%{number} Terraform reports failed to generate"
msgstr[0] ""
@@ -25853,24 +26578,48 @@ msgid_plural "Terraform|%{number} Terraform reports were generated in your pipel
msgstr[0] ""
msgstr[1] ""
+msgid "Terraform|%{user} updated %{timeAgo}"
+msgstr ""
+
msgid "Terraform|A Terraform report failed to generate."
msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|An error occurred while loading your Terraform States"
+msgstr ""
+
+msgid "Terraform|Find out how to use the %{linkStart}GitLab managed Terraform State%{linkEnd}"
+msgstr ""
+
msgid "Terraform|Generating the report caused an error."
msgstr ""
+msgid "Terraform|Get started with Terraform"
+msgstr ""
+
+msgid "Terraform|Locked"
+msgstr ""
+
+msgid "Terraform|Locked by %{user} %{timeAgo}"
+msgstr ""
+
msgid "Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete"
msgstr ""
+msgid "Terraform|States"
+msgstr ""
+
msgid "Terraform|The Terraform report %{name} failed to generate."
msgstr ""
msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
msgstr ""
+msgid "Terraform|Unknown User"
+msgstr ""
+
msgid "Test"
msgstr ""
@@ -25891,6 +26640,12 @@ msgstr[1] ""
msgid "Test settings"
msgstr ""
+msgid "TestCases|Move test case"
+msgstr ""
+
+msgid "TestCases|Moving test case"
+msgstr ""
+
msgid "TestCases|New Test Case"
msgstr ""
@@ -25918,6 +26673,9 @@ msgstr ""
msgid "TestCases|Something went wrong while marking test case todo as done."
msgstr ""
+msgid "TestCases|Something went wrong while moving test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while updating the test case labels."
msgstr ""
@@ -25948,6 +26706,9 @@ msgstr ""
msgid "TestHooks|Ensure the project has notes."
msgstr ""
+msgid "TestHooks|Ensure the project has releases."
+msgstr ""
+
msgid "TestHooks|Ensure the wiki is enabled and has pages."
msgstr ""
@@ -26145,6 +26906,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -26168,7 +26935,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -26210,6 +26977,12 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
+msgstr ""
+
+msgid "The license for Deploy Board is required to use this feature."
+msgstr ""
+
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -26279,7 +27052,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -26354,7 +27127,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -26366,6 +27139,9 @@ msgstr ""
msgid "The status of the table below only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
msgstr ""
+msgid "The tag name can't be changed for an existing release."
+msgstr ""
+
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
@@ -26405,6 +27181,9 @@ msgstr ""
msgid "The value of the provided variable exceeds the %{count} character limit"
msgstr ""
+msgid "The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -26492,6 +27271,9 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
+msgid "There are running deployments on the environment. Please retry later."
+msgstr ""
+
msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
msgstr ""
@@ -26702,6 +27484,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26753,7 +27538,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26861,6 +27646,9 @@ msgstr ""
msgid "This environment is being re-deployed"
msgstr ""
+msgid "This environment's canary ingress has been updated recently. Please retry later."
+msgstr ""
+
msgid "This epic already has the maximum number of child epics."
msgstr ""
@@ -26924,12 +27712,15 @@ msgstr ""
msgid "This is the highest peak of users on your installation since the license started."
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."
+msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27047,7 +27838,7 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request is still a work in progress."
+msgid "This merge request is still a draft."
msgstr ""
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
@@ -27068,9 +27859,6 @@ 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 ""
@@ -27522,7 +28310,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27573,7 +28361,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27645,7 +28433,7 @@ 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"
+msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
@@ -27744,6 +28532,9 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
+msgid "Too many users specified (limit is %{user_limit})"
+msgstr ""
+
msgid "Too much data"
msgstr ""
@@ -27786,10 +28577,10 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -28224,10 +29015,10 @@ msgstr ""
msgid "Unlocks the discussion."
msgstr ""
-msgid "Unmarked this %{noun} as Work In Progress."
+msgid "Unmarked this %{noun} as a draft."
msgstr ""
-msgid "Unmarks this %{noun} as Work In Progress."
+msgid "Unmarks this %{noun} as a draft."
msgstr ""
msgid "Unreachable"
@@ -28347,6 +29138,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -28440,6 +29234,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload an image"
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -28509,12 +29306,6 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
-msgid "UsageQuota|Learn more about excess storage usage"
-msgstr ""
-
-msgid "UsageQuota|Learn more about usage quotas"
-msgstr ""
-
msgid "UsageQuota|Packages"
msgstr ""
@@ -28539,16 +29330,28 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
msgid "UsageQuota|This namespace contains locked projects"
msgstr ""
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
-msgid "UsageQuota|This project is at risk of being locked."
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
msgstr ""
-msgid "UsageQuota|This project is locked."
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
msgstr ""
msgid "UsageQuota|Total excess storage used"
@@ -28707,6 +29510,12 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserAvailability|%{author} (Busy)"
+msgstr ""
+
+msgid "UserAvailability|(Busy)"
+msgstr ""
+
msgid "UserLists|Add"
msgstr ""
@@ -28764,6 +29573,9 @@ msgstr ""
msgid "UserList|created %{timeago}"
msgstr ""
+msgid "UserProfile|(Busy)"
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -28809,6 +29621,9 @@ msgstr ""
msgid "UserProfile|Report abuse"
msgstr ""
+msgid "UserProfile|Retry"
+msgstr ""
+
msgid "UserProfile|Snippets"
msgstr ""
@@ -28872,10 +29687,10 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
+msgid "Username or email"
msgstr ""
-msgid "Username or email"
+msgid "Username: %{username}"
msgstr ""
msgid "Users"
@@ -28920,15 +29735,15 @@ 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 "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
+msgstr ""
+
msgid "Valid from"
msgstr ""
@@ -28998,7 +29813,7 @@ msgstr ""
msgid "Various settings that affect GitLab performance."
msgstr ""
-msgid "Verification capacity"
+msgid "Verification concurrency limit"
msgstr ""
msgid "Verification information"
@@ -29028,6 +29843,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -29128,6 +29949,9 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View setting"
+msgstr ""
+
msgid "View supported languages and frameworks"
msgstr ""
@@ -29329,6 +30153,12 @@ msgstr ""
msgid "Vulnerability|Activity"
msgstr ""
+msgid "Vulnerability|Actual received response is the one received when this fault was detected"
+msgstr ""
+
+msgid "Vulnerability|Additional Info"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -29377,10 +30207,7 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Request"
-msgstr ""
-
-msgid "Vulnerability|Response"
+msgid "Vulnerability|Request/Response"
msgstr ""
msgid "Vulnerability|Scanner"
@@ -29395,6 +30222,9 @@ msgstr ""
msgid "Vulnerability|Status"
msgstr ""
+msgid "Vulnerability|The unmodified response is the original response that had no mutations done to the request"
+msgstr ""
+
msgid "Wait for the file to load to copy its contents"
msgstr ""
@@ -29425,6 +30255,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -29521,6 +30360,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29536,6 +30378,9 @@ msgstr ""
msgid "Webhooks|Push events"
msgstr ""
+msgid "Webhooks|Releases events"
+msgstr ""
+
msgid "Webhooks|SSL verification"
msgstr ""
@@ -29548,6 +30393,12 @@ msgstr ""
msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
+msgstr ""
+
+msgid "Webhooks|This URL is triggered when a release is created/updated"
+msgstr ""
+
msgid "Webhooks|This URL will be triggered by a push to the repository"
msgstr ""
@@ -29620,9 +30471,6 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
@@ -29694,7 +30542,13 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki was successfully updated."
+msgid "Wiki page was successfully created."
+msgstr ""
+
+msgid "Wiki page was successfully deleted."
+msgstr ""
+
+msgid "Wiki page was successfully updated."
msgstr ""
msgid "WikiClone|Clone your wiki"
@@ -29943,6 +30797,9 @@ msgstr ""
msgid "You already have pending todo for this alert"
msgstr ""
+msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
+msgstr ""
+
msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
msgstr ""
@@ -30021,10 +30878,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -30039,6 +30896,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -30180,6 +31046,9 @@ msgstr ""
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
+msgid "You do not have permission to update the environment."
+msgstr ""
+
msgid "You do not have permissions to run the import."
msgstr ""
@@ -30240,6 +31109,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -30252,6 +31124,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -30381,7 +31262,7 @@ 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."
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "You'll be signed out from your current account automatically."
@@ -30411,9 +31292,6 @@ 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 ""
@@ -30456,6 +31334,9 @@ msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
msgstr ""
+msgid "Your CSV import for project"
+msgstr ""
+
msgid "Your Commit Email will be used for web based operations, such as edits and merges."
msgstr ""
@@ -30468,6 +31349,9 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
+msgid "Your GitLab account request has been approved!"
+msgstr ""
+
msgid "Your GitLab group"
msgstr ""
@@ -30480,6 +31364,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -30495,6 +31382,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30660,6 +31550,9 @@ msgstr ""
msgid "Your search didn't match any commits. Try a different query."
msgstr ""
+msgid "Your sign-in page is %{url}."
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -30669,6 +31562,9 @@ msgstr ""
msgid "Your subscription will expire in %{remaining_days}."
msgstr ""
+msgid "Your username is %{username}."
+msgstr ""
+
msgid "Zoom meeting added"
msgstr ""
@@ -30839,13 +31735,10 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
-msgid "ciReport|(errors when loading results)"
-msgstr ""
-
-msgid "ciReport|(is loading)"
+msgid "ciReport|: Loading resulted in an error"
msgstr ""
-msgid "ciReport|(is loading, errors when loading results)"
+msgid "ciReport|API Fuzzing"
msgstr ""
msgid "ciReport|All projects"
@@ -30887,9 +31780,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -31015,9 +31905,18 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
+msgid "ciReport|is loading"
+msgstr ""
+
+msgid "ciReport|is loading, errors when loading results"
+msgstr ""
+
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -31206,6 +32105,9 @@ msgstr ""
msgid "has already been taken"
msgstr ""
+msgid "has been completed."
+msgstr ""
+
msgid "help"
msgstr ""
@@ -31334,6 +32236,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -31922,6 +32827,9 @@ msgstr ""
msgid "security Reports|There was an error creating the merge request"
msgstr ""
+msgid "severity|Blocker"
+msgstr ""
+
msgid "severity|Critical"
msgstr ""
@@ -31934,9 +32842,15 @@ msgstr ""
msgid "severity|Low"
msgstr ""
+msgid "severity|Major"
+msgstr ""
+
msgid "severity|Medium"
msgstr ""
+msgid "severity|Minor"
+msgstr ""
+
msgid "severity|None"
msgstr ""
@@ -31961,6 +32875,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -32015,10 +32932,10 @@ 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"
+msgid "syntax is correct."
msgstr ""
-msgid "syntax is incorrect"
+msgid "syntax is incorrect."
msgstr ""
msgid "tag name"
@@ -32027,6 +32944,9 @@ msgstr ""
msgid "teammate%{number}@company.com"
msgstr ""
+msgid "the correct format."
+msgstr ""
+
msgid "the following issue(s)"
msgstr ""
@@ -32108,6 +33028,11 @@ msgstr ""
msgid "view the source"
msgstr ""
+msgid "vulnerability"
+msgid_plural "vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "vulnerability|Add a comment"
msgstr ""
@@ -32152,3 +33077,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+
+msgid "your settings"
+msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index 31532eed94d..21f1573b2e1 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-10-02 18:41\n"
+"PO-Revision-Date: 2020-11-03 22:40\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index aadad4d67cd..6bcb90df0b1 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-10-02 18:47\n"
+"PO-Revision-Date: 2020-11-03 22:47\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -231,6 +231,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -273,13 +280,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -519,6 +519,20 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} more"
msgstr ""
@@ -563,6 +577,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -608,6 +628,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -734,9 +760,6 @@ 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 ""
@@ -844,7 +867,7 @@ msgstr[3] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -864,6 +887,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1089,9 +1115,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1132,6 +1155,18 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1164,6 +1199,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1173,19 +1211,8 @@ 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] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1478,6 +1505,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1779,6 +1809,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1932,7 +1965,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1968,10 +2001,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -2058,6 +2091,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -2082,6 +2118,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2196,6 +2235,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2205,6 +2259,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2217,12 +2277,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2277,6 +2355,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2286,6 +2367,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2331,6 +2415,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2355,6 +2442,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2364,6 +2454,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2379,22 +2472,22 @@ 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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2461,10 +2554,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2581,6 +2674,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2590,10 +2692,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2605,19 +2707,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2632,6 +2743,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2641,7 +2758,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2659,7 +2779,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2668,6 +2788,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2734,9 +2875,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2761,6 +2899,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2782,6 +2923,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2803,12 +2947,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2857,6 +3007,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2869,9 +3022,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2899,9 +3058,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2989,9 +3154,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -3064,9 +3226,6 @@ 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 ""
@@ -3097,9 +3256,6 @@ 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 ""
@@ -3124,6 +3280,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3148,9 +3307,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3166,6 +3322,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3503,6 +3662,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3753,6 +3915,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -4001,7 +4166,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -4022,6 +4208,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -4040,6 +4229,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -4097,9 +4289,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4181,6 +4370,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4265,6 +4460,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4316,12 +4523,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4340,6 +4556,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4352,6 +4571,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4496,6 +4718,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4532,9 +4757,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4565,7 +4802,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4748,6 +4985,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5159,6 +5399,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5342,9 +5585,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5363,9 +5603,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5474,6 +5711,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5498,7 +5738,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5525,6 +5765,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5708,6 +5951,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5765,9 +6011,6 @@ 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 ""
@@ -6023,9 +6266,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -6041,9 +6281,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6110,9 +6347,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6179,9 +6413,6 @@ 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 ""
@@ -6248,9 +6479,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6311,6 +6539,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6395,6 +6626,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6536,9 +6770,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6650,9 +6881,6 @@ 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 ""
@@ -6966,7 +7194,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -7017,6 +7245,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -7088,6 +7319,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7467,6 +7701,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7527,6 +7764,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7536,6 +7776,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7569,6 +7812,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7819,6 +8065,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7912,6 +8161,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8165,6 +8417,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8222,6 +8477,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8261,6 +8525,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8282,6 +8552,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8309,15 +8585,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8333,6 +8609,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8372,6 +8651,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8384,6 +8666,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8393,6 +8681,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8549,9 +8840,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8561,6 +8849,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8576,9 +8867,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8600,6 +8888,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8663,12 +8954,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8723,18 +9020,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8816,9 +9122,6 @@ 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 ""
@@ -8984,6 +9287,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -9032,6 +9341,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9203,6 +9515,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9254,7 +9587,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9405,6 +9738,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9414,6 +9750,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9435,6 +9774,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9462,9 +9804,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9633,15 +9972,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9714,6 +10062,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9855,6 +10206,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9882,7 +10239,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9927,6 +10296,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9954,7 +10326,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10716,12 +11091,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10752,6 +11133,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10827,6 +11211,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10929,6 +11316,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10992,6 +11382,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -11004,6 +11397,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11143,6 +11539,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11173,6 +11581,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11224,6 +11635,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11290,10 +11704,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11308,6 +11725,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11326,9 +11746,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11344,15 +11761,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11362,6 +11779,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11419,12 +11839,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11449,6 +11875,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11512,6 +11941,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11545,9 +11977,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11557,9 +11986,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11614,7 +12049,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12160,7 +12595,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12181,6 +12616,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12217,9 +12655,6 @@ 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 ""
@@ -12244,6 +12679,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12556,6 +12997,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12661,7 +13105,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12820,6 +13264,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12829,6 +13279,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12874,12 +13327,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12892,6 +13363,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12904,6 +13378,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12928,6 +13405,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13341,6 +13821,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13395,9 +13878,6 @@ 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 ""
@@ -13410,7 +13890,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13518,6 +13998,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13542,9 +14025,6 @@ 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 ""
@@ -13566,10 +14046,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13655,6 +14135,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13775,6 +14258,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13835,6 +14324,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13844,12 +14336,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13859,6 +14357,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13871,6 +14393,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13946,27 +14471,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13985,6 +14516,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -14016,6 +14550,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -14025,12 +14604,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -14064,6 +14661,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -14079,37 +14679,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -14118,6 +14739,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14142,9 +14766,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14244,25 +14865,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14310,6 +14931,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14358,6 +15033,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14574,6 +15252,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14829,6 +15510,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14847,6 +15531,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14976,9 +15666,6 @@ 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 ""
@@ -15007,9 +15694,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -15043,6 +15727,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -15076,6 +15763,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15121,6 +15811,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15196,6 +15889,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15749,9 +16445,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15770,6 +16463,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15803,9 +16499,6 @@ 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 ""
@@ -15815,7 +16508,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15827,6 +16520,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15890,6 +16586,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -16010,6 +16709,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -16037,15 +16742,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16283,6 +17063,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16690,6 +17473,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -17005,9 +17809,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -17065,6 +17875,38 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17320,6 +18162,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17786,6 +18631,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17816,9 +18664,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -18053,6 +18898,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -18098,9 +18946,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -18110,9 +18955,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18234,19 +19076,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18420,6 +19256,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18516,7 +19355,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18540,9 +19379,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18564,7 +19400,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18588,9 +19424,6 @@ 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 ""
@@ -18606,9 +19439,6 @@ 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 ""
@@ -18618,12 +19448,6 @@ 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 ""
@@ -18648,7 +19472,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18840,7 +19664,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18852,9 +19676,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18957,6 +19778,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -19038,6 +19862,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -19056,6 +19883,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -19086,6 +19916,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -19122,6 +19955,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19350,6 +20189,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19359,6 +20201,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19371,12 +20216,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19581,9 +20432,6 @@ 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 ""
@@ -20277,7 +21125,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20580,6 +21428,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20634,6 +21485,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -21090,6 +21944,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21216,6 +22073,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21327,6 +22187,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21408,6 +22271,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21454,9 +22320,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21668,6 +22531,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21788,6 +22654,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21809,9 +22678,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21839,6 +22714,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21966,7 +22844,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21978,6 +22862,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21996,6 +22892,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -22092,7 +22991,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -22125,6 +23024,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22332,6 +23234,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22486,6 +23391,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22513,6 +23424,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22582,6 +23496,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22591,6 +23508,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22606,6 +23529,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22630,9 +23556,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22642,6 +23565,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22681,6 +23607,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22711,7 +23640,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22768,9 +23697,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22852,9 +23778,6 @@ 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] ""
@@ -22941,7 +23864,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22986,10 +23909,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -23118,6 +24041,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23181,6 +24107,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23220,6 +24152,13 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23400,6 +24339,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23415,7 +24357,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23430,9 +24372,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23526,6 +24465,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23640,6 +24582,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23775,6 +24720,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23880,6 +24828,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23898,9 +24855,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -24047,6 +25010,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -24074,6 +25040,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -24083,9 +25052,6 @@ 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 ""
@@ -24095,6 +25061,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24206,27 +25175,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24461,6 +25421,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24569,6 +25532,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24611,9 +25577,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24689,9 +25652,6 @@ 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 ""
@@ -24755,6 +25715,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24911,6 +25874,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -25040,6 +26006,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -25055,6 +26024,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -25097,6 +26069,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25181,6 +26159,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25202,6 +26183,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25337,12 +26321,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25370,6 +26360,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25610,15 +26603,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25703,7 +26711,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25728,9 +26736,6 @@ 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 ""
@@ -25743,9 +26748,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25842,6 +26853,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25867,7 +26884,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25978,7 +26995,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -26038,6 +27055,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -26050,7 +27070,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -26089,6 +27109,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26197,6 +27220,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26392,6 +27418,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26443,7 +27472,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26467,9 +27496,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26602,6 +27637,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26611,6 +27649,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27163,6 +28204,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27201,7 +28248,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27252,7 +28299,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27381,6 +28428,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27453,16 +28503,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27639,6 +28692,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27789,6 +28845,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -28014,6 +29073,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -28152,10 +29214,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28182,6 +29247,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28194,9 +29262,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28218,15 +29313,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28281,10 +29388,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28404,6 +29508,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28500,9 +29607,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28656,6 +29760,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28967,7 +30077,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -29051,6 +30167,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -29147,6 +30272,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29171,13 +30299,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29246,15 +30377,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29267,7 +30398,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29511,10 +30642,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29607,6 +30738,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29628,6 +30762,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29640,10 +30777,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29658,6 +30795,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29859,6 +31005,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29871,6 +31020,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29895,9 +31053,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29955,9 +31110,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -30060,19 +31212,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -30102,6 +31257,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -30117,6 +31275,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30385,9 +31546,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30514,9 +31672,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30562,9 +31717,6 @@ 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 ""
@@ -30650,6 +31802,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30898,7 +32053,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30916,6 +32071,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30934,6 +32092,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30970,6 +32131,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -31034,6 +32198,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31515,9 +32682,6 @@ 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 ""
@@ -31530,9 +32694,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31612,6 +32773,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31792,9 +32956,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31807,3 +32968,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index a0a439ef7ff..a002fb4c05e 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-10-02 18:42\n"
+"PO-Revision-Date: 2020-11-03 22:42\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index b8e5aaec69e..33b83826f37 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-10-02 18:42\n"
+"PO-Revision-Date: 2020-11-03 22:41\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -208,6 +208,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -244,12 +250,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -463,6 +463,18 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{count} more"
msgstr ""
@@ -505,6 +517,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -550,6 +568,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -676,9 +700,6 @@ 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 ""
@@ -781,7 +802,7 @@ msgstr[2] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -799,6 +820,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1018,9 +1042,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1060,6 +1081,18 @@ msgstr[2] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1090,6 +1123,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1099,17 +1135,8 @@ 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] ""
-msgstr[2] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1387,6 +1414,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1687,6 +1717,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1840,7 +1873,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1876,10 +1909,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1966,6 +1999,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1990,6 +2026,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2104,6 +2143,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2113,6 +2167,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2125,12 +2185,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2185,6 +2263,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2194,6 +2275,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2239,6 +2323,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2263,6 +2350,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2272,6 +2362,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2287,22 +2380,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2368,10 +2461,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2488,6 +2581,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2497,10 +2599,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2512,19 +2614,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2539,6 +2650,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2548,7 +2665,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2566,7 +2686,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2575,6 +2695,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2641,9 +2782,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2668,6 +2806,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2689,6 +2830,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2710,12 +2854,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2764,6 +2914,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2776,9 +2929,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2806,9 +2965,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2896,9 +3061,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2971,9 +3133,6 @@ 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 ""
@@ -3004,9 +3163,6 @@ 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 ""
@@ -3031,6 +3187,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3055,9 +3214,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3073,6 +3229,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3406,6 +3565,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3655,6 +3817,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3901,7 +4066,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3922,6 +4108,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3940,6 +4129,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3997,9 +4189,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4081,6 +4270,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4165,6 +4360,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4216,12 +4423,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4240,6 +4456,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4252,6 +4471,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4396,6 +4618,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4432,9 +4657,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4465,7 +4702,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4648,6 +4885,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5059,6 +5299,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5242,9 +5485,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5263,9 +5503,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5374,6 +5611,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5398,7 +5638,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5425,6 +5665,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5608,6 +5851,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5665,9 +5911,6 @@ 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 ""
@@ -5923,9 +6166,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5941,9 +6181,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6010,9 +6247,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6079,9 +6313,6 @@ 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 ""
@@ -6148,9 +6379,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6211,6 +6439,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6295,6 +6526,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6436,9 +6670,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6550,9 +6781,6 @@ 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 ""
@@ -6865,7 +7093,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6916,6 +7144,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6985,6 +7216,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7363,6 +7597,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7423,6 +7660,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7432,6 +7672,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7465,6 +7708,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7714,6 +7960,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7807,6 +8056,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8059,6 +8311,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8116,6 +8371,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8155,6 +8419,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8176,6 +8446,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8203,15 +8479,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8227,6 +8503,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8266,6 +8545,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8278,6 +8560,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8287,6 +8575,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8443,9 +8734,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8455,6 +8743,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8470,9 +8761,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8494,6 +8782,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8557,12 +8848,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8614,18 +8911,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8704,9 +9010,6 @@ 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 ""
@@ -8872,6 +9175,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8920,6 +9229,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9091,6 +9403,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9142,7 +9475,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9292,6 +9625,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9301,6 +9637,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9322,6 +9661,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9349,9 +9691,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9520,15 +9859,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9601,6 +9949,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9742,6 +10093,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9769,7 +10126,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9814,6 +10183,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9841,7 +10213,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10603,12 +10978,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10639,6 +11020,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10714,6 +11098,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10816,6 +11203,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10879,6 +11269,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10891,6 +11284,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11029,6 +11425,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11059,6 +11467,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11110,6 +11521,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11176,10 +11590,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11194,6 +11611,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11212,9 +11632,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11230,15 +11647,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11248,6 +11665,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11305,12 +11725,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11335,6 +11761,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11398,6 +11827,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11431,9 +11863,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11443,9 +11872,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11500,7 +11935,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12046,7 +12481,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12067,6 +12502,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12103,9 +12541,6 @@ 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 ""
@@ -12130,6 +12565,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12442,6 +12883,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12547,7 +12991,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12706,6 +13150,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12715,6 +13165,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12760,12 +13213,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12778,6 +13249,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12790,6 +13264,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12814,6 +13291,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13225,6 +13705,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13279,9 +13762,6 @@ 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 ""
@@ -13294,7 +13774,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13402,6 +13882,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13426,9 +13909,6 @@ 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 ""
@@ -13450,10 +13930,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13537,6 +14017,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13657,6 +14140,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13717,6 +14206,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13726,12 +14218,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13741,6 +14239,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13753,6 +14275,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13828,27 +14353,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13867,6 +14398,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13897,6 +14431,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13906,12 +14485,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13945,6 +14542,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13960,37 +14560,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13999,6 +14620,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14023,9 +14647,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14125,25 +14746,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14191,6 +14812,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14239,6 +14914,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14455,6 +15133,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14710,6 +15391,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14728,6 +15412,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14857,9 +15547,6 @@ 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 ""
@@ -14887,9 +15574,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14923,6 +15607,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14956,6 +15643,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15001,6 +15691,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15076,6 +15769,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15622,9 +16318,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15643,6 +16336,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15676,9 +16372,6 @@ 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 ""
@@ -15688,7 +16381,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15700,6 +16393,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15763,6 +16459,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15883,6 +16582,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15910,15 +16615,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16156,6 +16936,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16561,6 +17344,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16876,9 +17680,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16936,6 +17746,36 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17191,6 +18031,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17656,6 +18499,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17686,9 +18532,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17923,6 +18766,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17968,9 +18814,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17980,9 +18823,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18103,19 +18943,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18289,6 +19123,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18385,7 +19222,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18409,9 +19246,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18433,7 +19267,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18457,9 +19291,6 @@ 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 ""
@@ -18475,9 +19306,6 @@ 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 ""
@@ -18487,12 +19315,6 @@ 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 ""
@@ -18517,7 +19339,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18709,7 +19531,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18721,9 +19543,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18826,6 +19645,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18907,6 +19729,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18925,6 +19750,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18955,6 +19783,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18991,6 +19822,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19219,6 +20056,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19228,6 +20068,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19240,12 +20083,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19450,9 +20299,6 @@ 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 ""
@@ -20146,7 +20992,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20449,6 +21295,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20503,6 +21352,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20959,6 +21811,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21085,6 +21940,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21196,6 +22054,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21277,6 +22138,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21322,9 +22186,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21535,6 +22396,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21655,6 +22519,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21676,9 +22543,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21706,6 +22579,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21832,7 +22708,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21844,6 +22726,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21862,6 +22756,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21958,7 +22855,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21991,6 +22888,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22195,6 +23095,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22348,6 +23251,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22375,6 +23284,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22444,6 +23356,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22453,6 +23368,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22468,6 +23389,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22492,9 +23416,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22504,6 +23425,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22543,6 +23467,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22573,7 +23500,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22630,9 +23557,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22714,9 +23638,6 @@ 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] ""
@@ -22792,7 +23713,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22837,10 +23758,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22969,6 +23890,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23032,6 +23956,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23071,6 +24001,12 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23251,6 +24187,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23266,7 +24205,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23281,9 +24220,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23377,6 +24313,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23491,6 +24430,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23626,6 +24568,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23731,6 +24676,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23749,9 +24703,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23896,6 +24856,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23923,6 +24886,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23932,9 +24898,6 @@ 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 ""
@@ -23944,6 +24907,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24055,27 +25021,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24310,6 +25267,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24418,6 +25378,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24460,9 +25423,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24538,9 +25498,6 @@ 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 ""
@@ -24604,6 +25561,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24760,6 +25720,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24889,6 +25852,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24904,6 +25870,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24946,6 +25915,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25030,6 +26005,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25051,6 +26029,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25186,12 +26167,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25219,6 +26206,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25456,15 +26446,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25549,7 +26554,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25573,9 +26578,6 @@ 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 ""
@@ -25588,9 +26590,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25687,6 +26695,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25711,7 +26725,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25822,7 +26836,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25882,6 +26896,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25894,7 +26911,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25933,6 +26950,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26041,6 +27061,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26236,6 +27259,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26287,7 +27313,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26311,9 +27337,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26446,6 +27478,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26455,6 +27490,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27007,6 +28045,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27043,7 +28087,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27094,7 +28138,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27223,6 +28267,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27295,16 +28342,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27481,6 +28531,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27631,6 +28684,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27856,6 +28912,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27994,10 +29053,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28024,6 +29086,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28036,9 +29101,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28060,15 +29152,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28123,10 +29227,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28246,6 +29347,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28342,9 +29446,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28498,6 +29599,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28807,7 +29914,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28891,6 +30004,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28987,6 +30109,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29011,13 +30136,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29086,15 +30214,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29107,7 +30235,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29350,10 +30478,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29446,6 +30574,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29467,6 +30598,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29479,10 +30613,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29497,6 +30631,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29698,6 +30841,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29710,6 +30856,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29734,9 +30889,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29794,9 +30946,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29899,19 +31048,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29941,6 +31093,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29956,6 +31111,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30223,9 +31381,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30352,9 +31507,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30400,9 +31552,6 @@ 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 ""
@@ -30487,6 +31636,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30730,7 +31882,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30748,6 +31900,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30766,6 +31921,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30802,6 +31960,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30865,6 +32026,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31342,9 +32506,6 @@ 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 ""
@@ -31357,9 +32518,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31438,6 +32596,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31618,9 +32779,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31633,3 +32791,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index e0a6239f240..865293cd765 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-10-02 18:47\n"
+"PO-Revision-Date: 2020-11-03 22:47\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index 9376db3055f..21c2bc2618f 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-10-02 18:41\n"
+"PO-Revision-Date: 2020-11-03 22:40\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -162,6 +162,10 @@ msgid "%d failed"
msgid_plural "%d failed"
msgstr[0] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -186,10 +190,6 @@ msgid "%d issue in this group"
msgid_plural "%d issues in this group"
msgstr[0] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -351,6 +351,14 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+
msgid "%{count} more"
msgstr ""
@@ -389,6 +397,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -434,6 +448,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -560,9 +580,6 @@ 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 ""
@@ -655,7 +672,7 @@ msgstr[0] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -669,6 +686,9 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
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] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -876,9 +896,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -916,6 +933,18 @@ msgstr[0] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -942,6 +971,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -951,13 +983,8 @@ msgstr ""
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1205,6 +1232,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1503,6 +1533,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1656,7 +1689,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1692,10 +1725,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1782,6 +1815,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1806,6 +1842,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1920,6 +1959,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -1929,6 +1983,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -1941,12 +2001,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2001,6 +2079,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2010,6 +2091,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2055,6 +2139,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2079,6 +2166,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2088,6 +2178,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2103,22 +2196,22 @@ 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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2182,10 +2275,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2302,6 +2395,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2311,10 +2413,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2326,19 +2428,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2353,6 +2464,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2362,7 +2479,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2380,7 +2500,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2389,6 +2509,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2455,9 +2596,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2482,6 +2620,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2503,6 +2644,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2524,12 +2668,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2578,6 +2728,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2590,9 +2743,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2620,9 +2779,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2710,9 +2875,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2785,9 +2947,6 @@ 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 ""
@@ -2818,9 +2977,6 @@ 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 ""
@@ -2845,6 +3001,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2869,9 +3028,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2887,6 +3043,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3212,6 +3371,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3459,6 +3621,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3701,7 +3866,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3722,6 +3908,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3740,6 +3929,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3797,9 +3989,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3881,6 +4070,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -3965,6 +4160,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4016,12 +4223,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4040,6 +4256,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4052,6 +4271,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4196,6 +4418,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4232,9 +4457,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4265,7 +4502,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4448,6 +4685,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4859,6 +5099,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5042,9 +5285,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5063,9 +5303,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5174,6 +5411,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5198,7 +5438,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5225,6 +5465,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5408,6 +5651,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5465,9 +5711,6 @@ 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 ""
@@ -5723,9 +5966,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5741,9 +5981,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5810,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5879,9 +6113,6 @@ 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 ""
@@ -5948,9 +6179,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6011,6 +6239,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6095,6 +6326,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6236,9 +6470,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6350,9 +6581,6 @@ 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 ""
@@ -6663,7 +6891,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6714,6 +6942,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6779,6 +7010,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7155,6 +7389,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7215,6 +7452,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7224,6 +7464,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7257,6 +7500,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7504,6 +7750,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7597,6 +7846,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7847,6 +8099,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -7904,6 +8159,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -7943,6 +8207,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -7964,6 +8234,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -7991,15 +8267,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8015,6 +8291,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8054,6 +8333,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8066,6 +8348,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8075,6 +8363,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8231,9 +8522,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8243,6 +8531,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8258,9 +8549,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8282,6 +8570,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8345,12 +8636,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8396,18 +8693,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8480,9 +8786,6 @@ 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 ""
@@ -8648,6 +8951,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8696,6 +9005,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8867,6 +9179,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -8918,7 +9251,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9066,6 +9399,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9075,6 +9411,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9096,6 +9435,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9123,9 +9465,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9294,15 +9633,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9375,6 +9723,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9516,6 +9867,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9543,7 +9900,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9588,6 +9957,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9615,7 +9987,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10377,12 +10752,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10413,6 +10794,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10488,6 +10872,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10590,6 +10977,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10653,6 +11043,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10665,6 +11058,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10801,6 +11197,18 @@ msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10831,6 +11239,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10882,6 +11293,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -10948,10 +11362,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -10966,6 +11383,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -10984,9 +11404,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11002,15 +11419,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11020,6 +11437,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11077,12 +11497,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11107,6 +11533,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11170,6 +11599,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11203,9 +11635,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11215,9 +11644,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11272,7 +11707,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11818,7 +12253,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11839,6 +12274,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11875,9 +12313,6 @@ 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 ""
@@ -11902,6 +12337,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12214,6 +12655,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12319,7 +12763,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12478,6 +12922,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12487,6 +12937,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12532,12 +12985,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12550,6 +13021,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12562,6 +13036,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12586,6 +13063,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -12993,6 +13473,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13047,9 +13530,6 @@ 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 ""
@@ -13062,7 +13542,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13170,6 +13650,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13194,9 +13677,6 @@ 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 ""
@@ -13218,10 +13698,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13301,6 +13781,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13421,6 +13904,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13481,6 +13970,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13490,12 +13982,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13505,6 +14003,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13517,6 +14039,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13592,27 +14117,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13631,6 +14162,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13659,6 +14193,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13668,12 +14247,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13707,6 +14304,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13722,37 +14322,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13761,6 +14382,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13785,9 +14409,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -13887,25 +14508,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -13953,6 +14574,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14001,6 +14676,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14217,6 +14895,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14472,6 +15153,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14490,6 +15174,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14619,9 +15309,6 @@ 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 ""
@@ -14647,9 +15334,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14683,6 +15367,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14716,6 +15403,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14761,6 +15451,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14836,6 +15529,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15368,9 +16064,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15389,6 +16082,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15422,9 +16118,6 @@ 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 ""
@@ -15434,7 +16127,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15446,6 +16139,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15509,6 +16205,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15629,6 +16328,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15656,15 +16361,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -15902,6 +16682,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16303,6 +17086,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16618,9 +17422,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16678,6 +17488,32 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -16933,6 +17769,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17396,6 +18235,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17426,9 +18268,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17663,6 +18502,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17708,9 +18550,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17720,9 +18559,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17841,19 +18677,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18027,6 +18857,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18123,7 +18956,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18147,9 +18980,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18171,7 +19001,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18195,9 +19025,6 @@ 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 ""
@@ -18213,9 +19040,6 @@ 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 ""
@@ -18225,12 +19049,6 @@ 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 ""
@@ -18255,7 +19073,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18447,7 +19265,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18459,9 +19277,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18564,6 +19379,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18645,6 +19463,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18663,6 +19484,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18693,6 +19517,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18729,6 +19556,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -18957,6 +19790,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -18966,6 +19802,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -18978,12 +19817,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19188,9 +20033,6 @@ 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 ""
@@ -19884,7 +20726,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20187,6 +21029,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20241,6 +21086,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20697,6 +21545,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20823,6 +21674,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -20934,6 +21788,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21015,6 +21872,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21058,9 +21918,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21269,6 +22126,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21389,6 +22249,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21410,9 +22273,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21440,6 +22309,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21564,7 +22436,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21576,6 +22454,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21594,6 +22484,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21690,7 +22583,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21723,6 +22616,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -21921,6 +22817,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22072,6 +22971,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22099,6 +23004,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22168,6 +23076,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22177,6 +23088,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22192,6 +23109,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22216,9 +23136,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22228,6 +23145,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22267,6 +23187,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22297,7 +23220,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22354,9 +23277,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22438,9 +23358,6 @@ 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] ""
@@ -22494,7 +23411,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22539,10 +23456,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22671,6 +23588,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22734,6 +23654,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22773,6 +23699,10 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -22953,6 +23883,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -22968,7 +23901,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -22983,9 +23916,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23079,6 +24009,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23193,6 +24126,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23328,6 +24264,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23433,6 +24372,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23451,9 +24399,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23594,6 +24548,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23621,6 +24578,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23630,9 +24590,6 @@ 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 ""
@@ -23642,6 +24599,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23753,27 +24713,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24008,6 +24959,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24116,6 +25070,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24158,9 +25115,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24236,9 +25190,6 @@ 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 ""
@@ -24302,6 +25253,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24458,6 +25412,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24587,6 +25544,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24602,6 +25562,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24644,6 +25607,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24728,6 +25697,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24749,6 +25721,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -24884,12 +25859,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -24917,6 +25898,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25148,15 +26132,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25241,7 +26240,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25263,9 +26262,6 @@ 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 ""
@@ -25278,9 +26274,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25377,6 +26379,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25399,7 +26407,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25510,7 +26518,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25570,6 +26578,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25582,7 +26593,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25621,6 +26632,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25729,6 +26743,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -25924,6 +26941,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -25975,7 +26995,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -25999,9 +27019,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26134,6 +27160,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26143,6 +27172,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26695,6 +27727,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26727,7 +27765,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26778,7 +27816,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -26907,6 +27945,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -26979,16 +28020,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27165,6 +28209,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27315,6 +28362,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27540,6 +28590,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27678,10 +28731,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27708,6 +28764,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27720,9 +28779,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27744,15 +28830,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27807,10 +28905,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -27930,6 +29025,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28026,9 +29124,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28182,6 +29277,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28487,7 +29588,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28571,6 +29678,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28667,6 +29783,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28691,13 +29810,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28766,15 +29888,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28787,7 +29909,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29028,10 +30150,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29124,6 +30246,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29145,6 +30270,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29157,10 +30285,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29175,6 +30303,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29376,6 +30513,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29388,6 +30528,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29412,9 +30561,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29472,9 +30618,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29577,19 +30720,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29619,6 +30765,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29634,6 +30783,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -29899,9 +31051,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30028,9 +31177,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30076,9 +31222,6 @@ 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 ""
@@ -30161,6 +31304,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30394,7 +31540,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30412,6 +31558,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30430,6 +31579,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30466,6 +31618,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30527,6 +31682,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -30996,9 +32154,6 @@ 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 ""
@@ -31011,9 +32166,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31090,6 +32242,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31270,9 +32425,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31285,3 +32437,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/ig_NG/gitlab.po b/locale/ig_NG/gitlab.po
index 1dc3320936a..dbbfe7418cf 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-10-02 18:45\n"
+"PO-Revision-Date: 2020-11-03 22:45\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -162,6 +162,10 @@ msgid "%d failed"
msgid_plural "%d failed"
msgstr[0] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -186,10 +190,6 @@ msgid "%d issue in this group"
msgid_plural "%d issues in this group"
msgstr[0] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -351,6 +351,14 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+
msgid "%{count} more"
msgstr ""
@@ -389,6 +397,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -434,6 +448,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -560,9 +580,6 @@ 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 ""
@@ -655,7 +672,7 @@ msgstr[0] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -669,6 +686,9 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
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] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -876,9 +896,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -916,6 +933,18 @@ msgstr[0] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -942,6 +971,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -951,13 +983,8 @@ msgstr ""
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1205,6 +1232,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1503,6 +1533,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1656,7 +1689,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1692,10 +1725,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1782,6 +1815,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1806,6 +1842,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1920,6 +1959,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -1929,6 +1983,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -1941,12 +2001,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2001,6 +2079,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2010,6 +2091,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2055,6 +2139,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2079,6 +2166,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2088,6 +2178,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2103,22 +2196,22 @@ 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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2182,10 +2275,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2302,6 +2395,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2311,10 +2413,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2326,19 +2428,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2353,6 +2464,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2362,7 +2479,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2380,7 +2500,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2389,6 +2509,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2455,9 +2596,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2482,6 +2620,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2503,6 +2644,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2524,12 +2668,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2578,6 +2728,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2590,9 +2743,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2620,9 +2779,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2710,9 +2875,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2785,9 +2947,6 @@ 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 ""
@@ -2818,9 +2977,6 @@ 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 ""
@@ -2845,6 +3001,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2869,9 +3028,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2887,6 +3043,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3212,6 +3371,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3459,6 +3621,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3701,7 +3866,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3722,6 +3908,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3740,6 +3929,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3797,9 +3989,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3881,6 +4070,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -3965,6 +4160,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4016,12 +4223,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4040,6 +4256,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4052,6 +4271,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4196,6 +4418,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4232,9 +4457,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4265,7 +4502,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4448,6 +4685,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4859,6 +5099,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5042,9 +5285,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5063,9 +5303,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5174,6 +5411,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5198,7 +5438,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5225,6 +5465,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5408,6 +5651,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5465,9 +5711,6 @@ 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 ""
@@ -5723,9 +5966,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5741,9 +5981,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5810,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5879,9 +6113,6 @@ 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 ""
@@ -5948,9 +6179,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6011,6 +6239,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6095,6 +6326,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6236,9 +6470,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6350,9 +6581,6 @@ 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 ""
@@ -6663,7 +6891,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6714,6 +6942,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6779,6 +7010,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7155,6 +7389,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7215,6 +7452,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7224,6 +7464,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7257,6 +7500,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7504,6 +7750,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7597,6 +7846,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7847,6 +8099,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -7904,6 +8159,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -7943,6 +8207,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -7964,6 +8234,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -7991,15 +8267,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8015,6 +8291,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8054,6 +8333,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8066,6 +8348,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8075,6 +8363,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8231,9 +8522,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8243,6 +8531,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8258,9 +8549,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8282,6 +8570,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8345,12 +8636,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8396,18 +8693,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8480,9 +8786,6 @@ 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 ""
@@ -8648,6 +8951,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8696,6 +9005,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8867,6 +9179,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -8918,7 +9251,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9066,6 +9399,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9075,6 +9411,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9096,6 +9435,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9123,9 +9465,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9294,15 +9633,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9375,6 +9723,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9516,6 +9867,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9543,7 +9900,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9588,6 +9957,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9615,7 +9987,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10377,12 +10752,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10413,6 +10794,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10488,6 +10872,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10590,6 +10977,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10653,6 +11043,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10665,6 +11058,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10801,6 +11197,18 @@ msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10831,6 +11239,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10882,6 +11293,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -10948,10 +11362,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -10966,6 +11383,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -10984,9 +11404,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11002,15 +11419,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11020,6 +11437,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11077,12 +11497,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11107,6 +11533,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11170,6 +11599,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11203,9 +11635,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11215,9 +11644,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11272,7 +11707,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11818,7 +12253,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11839,6 +12274,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11875,9 +12313,6 @@ 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 ""
@@ -11902,6 +12337,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12214,6 +12655,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12319,7 +12763,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12478,6 +12922,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12487,6 +12937,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12532,12 +12985,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12550,6 +13021,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12562,6 +13036,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12586,6 +13063,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -12993,6 +13473,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13047,9 +13530,6 @@ 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 ""
@@ -13062,7 +13542,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13170,6 +13650,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13194,9 +13677,6 @@ 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 ""
@@ -13218,10 +13698,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13301,6 +13781,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13421,6 +13904,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13481,6 +13970,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13490,12 +13982,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13505,6 +14003,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13517,6 +14039,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13592,27 +14117,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13631,6 +14162,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13659,6 +14193,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13668,12 +14247,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13707,6 +14304,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13722,37 +14322,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13761,6 +14382,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13785,9 +14409,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -13887,25 +14508,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -13953,6 +14574,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14001,6 +14676,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14217,6 +14895,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14472,6 +15153,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14490,6 +15174,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14619,9 +15309,6 @@ 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 ""
@@ -14647,9 +15334,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14683,6 +15367,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14716,6 +15403,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14761,6 +15451,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14836,6 +15529,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15368,9 +16064,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15389,6 +16082,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15422,9 +16118,6 @@ 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 ""
@@ -15434,7 +16127,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15446,6 +16139,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15509,6 +16205,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15629,6 +16328,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15656,15 +16361,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -15902,6 +16682,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16303,6 +17086,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16618,9 +17422,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16678,6 +17488,32 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -16933,6 +17769,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17396,6 +18235,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17426,9 +18268,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17663,6 +18502,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17708,9 +18550,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17720,9 +18559,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17841,19 +18677,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18027,6 +18857,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18123,7 +18956,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18147,9 +18980,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18171,7 +19001,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18195,9 +19025,6 @@ 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 ""
@@ -18213,9 +19040,6 @@ 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 ""
@@ -18225,12 +19049,6 @@ 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 ""
@@ -18255,7 +19073,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18447,7 +19265,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18459,9 +19277,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18564,6 +19379,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18645,6 +19463,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18663,6 +19484,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18693,6 +19517,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18729,6 +19556,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -18957,6 +19790,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -18966,6 +19802,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -18978,12 +19817,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19188,9 +20033,6 @@ 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 ""
@@ -19884,7 +20726,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20187,6 +21029,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20241,6 +21086,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20697,6 +21545,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20823,6 +21674,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -20934,6 +21788,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21015,6 +21872,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21058,9 +21918,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21269,6 +22126,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21389,6 +22249,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21410,9 +22273,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21440,6 +22309,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21564,7 +22436,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21576,6 +22454,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21594,6 +22484,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21690,7 +22583,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21723,6 +22616,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -21921,6 +22817,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22072,6 +22971,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22099,6 +23004,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22168,6 +23076,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22177,6 +23088,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22192,6 +23109,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22216,9 +23136,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22228,6 +23145,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22267,6 +23187,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22297,7 +23220,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22354,9 +23277,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22438,9 +23358,6 @@ 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] ""
@@ -22494,7 +23411,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22539,10 +23456,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22671,6 +23588,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22734,6 +23654,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22773,6 +23699,10 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -22953,6 +23883,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -22968,7 +23901,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -22983,9 +23916,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23079,6 +24009,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23193,6 +24126,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23328,6 +24264,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23433,6 +24372,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23451,9 +24399,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23594,6 +24548,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23621,6 +24578,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23630,9 +24590,6 @@ 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 ""
@@ -23642,6 +24599,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23753,27 +24713,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24008,6 +24959,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24116,6 +25070,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24158,9 +25115,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24236,9 +25190,6 @@ 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 ""
@@ -24302,6 +25253,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24458,6 +25412,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24587,6 +25544,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24602,6 +25562,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24644,6 +25607,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24728,6 +25697,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24749,6 +25721,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -24884,12 +25859,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -24917,6 +25898,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25148,15 +26132,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25241,7 +26240,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25263,9 +26262,6 @@ 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 ""
@@ -25278,9 +26274,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25377,6 +26379,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25399,7 +26407,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25510,7 +26518,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25570,6 +26578,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25582,7 +26593,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25621,6 +26632,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25729,6 +26743,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -25924,6 +26941,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -25975,7 +26995,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -25999,9 +27019,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26134,6 +27160,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26143,6 +27172,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26695,6 +27727,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26727,7 +27765,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26778,7 +27816,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -26907,6 +27945,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -26979,16 +28020,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27165,6 +28209,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27315,6 +28362,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27540,6 +28590,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27678,10 +28731,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27708,6 +28764,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27720,9 +28779,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27744,15 +28830,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27807,10 +28905,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -27930,6 +29025,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28026,9 +29124,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28182,6 +29277,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28487,7 +29588,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28571,6 +29678,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28667,6 +29783,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28691,13 +29810,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28766,15 +29888,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28787,7 +29909,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29028,10 +30150,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29124,6 +30246,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29145,6 +30270,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29157,10 +30285,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29175,6 +30303,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29376,6 +30513,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29388,6 +30528,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29412,9 +30561,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29472,9 +30618,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29577,19 +30720,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29619,6 +30765,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29634,6 +30783,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -29899,9 +31051,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30028,9 +31177,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30076,9 +31222,6 @@ 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 ""
@@ -30161,6 +31304,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30394,7 +31540,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30412,6 +31558,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30430,6 +31579,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30466,6 +31618,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30527,6 +31682,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -30996,9 +32154,6 @@ 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 ""
@@ -31011,9 +32166,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31090,6 +32242,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31270,9 +32425,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31285,3 +32437,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/is_IS/gitlab.po b/locale/is_IS/gitlab.po
index 1563d7edcd4..8cd80676f85 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-10-02 18:41\n"
+"PO-Revision-Date: 2020-11-03 22:40\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index 01eeae42c99..7177eae6d03 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-10-02 18:47\n"
+"PO-Revision-Date: 2020-11-03 22:47\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d risultato del test risolto"
@@ -215,11 +220,6 @@ msgid_plural "%d issues in this group"
msgstr[0] ""
msgstr[1] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d problema selezionato"
-msgstr[1] "%d problemi selezionati"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -407,6 +407,16 @@ msgstr "%{count} approvazioni da %{name}"
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr "%{count} altro"
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -947,9 +969,6 @@ msgstr "(verifica progresso)"
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr "(fonte esterna)"
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr "- riduci"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ msgstr "0 = illimitato"
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "1 %{type} inserimento"
-msgstr[1] "%{count} %{type} inserimenti"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "Errore durante l'attivazione/disattivazione della sottoscrizione per l'iscrizione"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ msgstr "Farà automaticamente le build, i test e i rilasci della tua applicazion
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Approfondisci: %{link_to_documentation}"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr "Disponibile"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr "Impostazioni"
msgid "Branches|protected"
msgstr "Protetta"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr "Descrizione"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "Non mostrare più"
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "Feb"
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "Files"
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "Cronologia"
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Intervallo di Pattern"
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr "Gen"
msgid "January"
msgstr "Gennaio"
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr "Ultima Pipeline"
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr "Ultimo aggiornamento"
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr "Mar"
msgid "March"
msgstr "Marzo"
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr "Membri"
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr "Nessuno"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr "Dati insufficienti "
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr "Percentuale di successo"
msgid "PipelineCharts|Successful:"
msgstr "Completata:"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "Totale:"
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ msgstr "Salva pianificazione pipeline"
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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "Pianifica una nuova Pipeline"
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr "Seleziona il ramo che vuoi impostare come predefinito per questo progett
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr "Settembre"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "Codice Sorgente"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,8 +26677,8 @@ msgstr "Lo stadio di pianificazione mostra il tempo trascorso dal primo commit a
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
-msgstr "Qualunque utente autenticato può accedere a questo progetto."
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr ""
@@ -25726,6 +26737,9 @@ msgstr "Lo stadio di revisione mostra il tempo tra una richiesta di merge al suo
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr "poco fa"
msgid "Timeago|right now"
msgstr "adesso"
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr "Tempo totale di test per tutti i commits/merges"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index 08307978560..e887b5692d5 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-10-02 18:48\n"
+"PO-Revision-Date: 2020-11-03 22:48\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -162,6 +162,10 @@ msgid "%d failed"
msgid_plural "%d failed"
msgstr[0] "%d 件ã®å¤±æ•—"
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d 件ã®ãƒ†ã‚¹ãƒˆã§ä¿®æ­£ã•ã‚Œã¾ã—ãŸ"
@@ -186,10 +190,6 @@ msgid "%d issue in this group"
msgid_plural "%d issues in this group"
msgstr[0] "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«%d件ã®èª²é¡Œ"
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d個ã®èª²é¡Œã‚’é¸æŠžæ¸ˆã¿"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] "%d 件ã®èª²é¡Œã‚’ラベル付ãã§ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¾ã—ãŸ"
@@ -351,6 +351,14 @@ msgstr "%{name} ㌠%{count} 件ã®æ‰¿èªã‚’了承ã—ã¾ã—ãŸ"
msgid "%{count} files touched"
msgstr "%{count} ファイルãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸ"
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+
msgid "%{count} more"
msgstr "他 %{count} 件"
@@ -389,6 +397,12 @@ msgstr "%{deployLinkStart}テンプレートを使用ã—ã¦ECS%{deployLinkEnd}ã
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 "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -434,6 +448,12 @@ msgstr "%{group_name} ã¯ã‚°ãƒ«ãƒ¼ãƒ—管ç†ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’使用ã—ã¾ã™ã€‚
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr "æ–°ã—ã„場所%{host} ã‹ã‚‰ã®ãƒ­ã‚°ã‚¤ãƒ³"
@@ -560,9 +580,6 @@ msgstr "%{name_with_link} 㯠%{percent}ã¾ãŸã¯ãれ以下ã®å…±æœ‰ãƒ©ãƒ³ãƒŠã
msgid "%{name_with_link} has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
msgstr ""
-msgid "%{namespace_name} is now read-only. You cannot: %{base_message}"
-msgstr ""
-
msgid "%{name} contained %{resultsString}"
msgstr "%{name} ã«ã¯ %{resultsString} ãŒå«ã¾ã‚Œã¦ã„ã¾ã™"
@@ -655,7 +672,7 @@ msgstr[0] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -669,6 +686,9 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
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] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -876,9 +896,6 @@ msgstr "(進行状æ³ã‚’確èªã™ã‚‹)"
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr "(外部ソース)"
-
msgid "(line: %{startLine})"
msgstr ""
@@ -916,6 +933,18 @@ msgstr[0] "%d 以上"
msgid "+%{approvers} more approvers"
msgstr "%{approvers} 人以上ã®æ‰¿èªè€…"
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -942,6 +971,9 @@ msgstr ""
msgid "- show less"
msgstr "- 折りãŸãŸã‚€"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -951,13 +983,8 @@ msgstr "0ã¯ç„¡åˆ¶é™ã®æ„味"
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "%{count} %{type} 件ã®è¿½åŠ æƒ…å ±"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "%{count} 件 %{type} ã®ä¿®æ­£"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1205,6 +1232,9 @@ msgstr "ã“ã®ã‚ªãƒ—ションをé¸æŠžã—ãŸã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¸ã®æ›¸ãè¾¼
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr "アクションãŒå¿…è¦ï¼šGitLab Pagesã®ãƒ‰ãƒ¡ã‚¤ãƒ³ '%{domain}'ã¸ã®Let's Encrypt証明書ã®å–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1359,7 +1389,7 @@ msgid "AccessibilityReport|Learn more"
msgstr ""
msgid "AccessibilityReport|Message: %{message}"
-msgstr ""
+msgstr "メッセージ: %{message}"
msgid "AccessibilityReport|New"
msgstr " æ–°ã—ã„"
@@ -1417,7 +1447,7 @@ msgid_plural "Add %d issues"
msgstr[0] "課題を%d 件ã€è¿½åŠ "
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
-msgstr ""
+msgstr "リリース㫠%{linkStart}アセット%{linkEnd} を追加ã—ã¾ã™ã€‚ GitLab ã«ã¯ã€ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚„リリースã®ã‚¨ãƒ“デンスãªã©ã®èª­ã¿å–り専用ã®ã‚¢ã‚»ãƒƒãƒˆãŒè‡ªå‹•çš„ã«å«ã¾ã‚Œã¦ã„ã¾ã™ã€‚"
msgid "Add CHANGELOG"
msgstr "変更履歴を追加"
@@ -1503,6 +1533,9 @@ msgstr "テーブルを追加ã™ã‚‹"
msgid "Add a task list"
msgstr "タスクリストを追加"
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "ã™ã¹ã¦ã®ãƒ¡ãƒ¼ãƒ«ã«è¡¨ç¤ºã™ã‚‹ãƒ†ã‚­ã‚¹ãƒˆã‚’追加ã—ã¾ã™ã€‚ ãŸã ã—ã€%{character_limit} 文字ã®åˆ¶é™ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -1656,8 +1689,8 @@ msgstr "%{epic_ref} ã‚’å­ã‚¨ãƒ”ックã¨ã—ã¦è¿½åŠ ã—ã¾ã—ãŸã€‚"
msgid "Added %{label_references} %{label_text}."
msgstr "%{label_references} %{label_text} を追加ã—ã¾ã—ãŸã€‚"
-msgid "Added a To Do."
-msgstr "Todoã¸è¿½åŠ ã—ã¾ã—ãŸã€‚"
+msgid "Added a to do."
+msgstr ""
msgid "Added an issue to an epic."
msgstr "課題をエピックã«è¿½åŠ ã—ã¾ã—ãŸã€‚"
@@ -1692,12 +1725,12 @@ msgstr "%{epic_ref} ã‚’å­ã‚¨ãƒ”ックã¨ã—ã¦è¿½åŠ "
msgid "Adds %{labels} %{label_text}."
msgstr "%{labels} %{label_text} を追加。"
-msgid "Adds a To Do."
-msgstr "Todoを追加。"
-
msgid "Adds a Zoom meeting"
msgstr "Zoom ミーティングを追加"
+msgid "Adds a to do."
+msgstr ""
+
msgid "Adds an issue to an epic."
msgstr "課題をエピックã«è¿½åŠ ã€‚"
@@ -1782,6 +1815,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr "オーナー"
@@ -1806,6 +1842,9 @@ msgstr "ジョブã®åœæ­¢ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "AdminArea|Total users"
msgstr "全ユーザー"
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "ユーザー統計"
@@ -1920,6 +1959,21 @@ msgstr "SSHéµ"
msgid "AdminStatistics|Snippets"
msgstr "スニペット"
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr "2FA 無効"
@@ -1929,6 +1983,12 @@ msgstr "2FA 有効"
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr "アクティブ"
@@ -1941,12 +2001,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr "管ç†è€…"
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr "ブロック"
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "ブロックユーザー"
@@ -2001,6 +2079,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr "ã‚ãªãŸã§ã™ï¼"
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr "æ–°ã—ã„ユーザー"
@@ -2010,6 +2091,9 @@ msgstr "ユーザーãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "AdminUsers|Owned groups will be left"
msgstr "所有グループã¯æ®‹ã‚Šã¾ã™"
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr "個人プロジェクトã¯æ®‹ã‚Šã¾ã™"
@@ -2055,6 +2139,9 @@ msgstr "ユーザーã¯ã‚¹ãƒ©ãƒƒã‚·ãƒ¥ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã§ããªããªã‚Šã¾
msgid "AdminUsers|The user will not receive any notifications"
msgstr "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯é€šçŸ¥ã‚’å—ã‘å–ã‚Œãªããªã‚Šã¾ã™"
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "確èªã®ãŸã‚ã€%{projectName} を入力ã—ã¦ãã ã•ã„"
@@ -2079,6 +2166,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2088,6 +2178,9 @@ msgstr ""
msgid "Administration"
msgstr "管ç†"
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr "高度ãªè¨­å®š"
@@ -2103,22 +2196,22 @@ msgstr "高度ãªè¨­å®š"
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "高度ãªæ¨©é™ã€ãƒ©ãƒ¼ã‚¸ãƒ•ã‚¡ã‚¤ãƒ«ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã€2è¦ç´ èªè¨¼ã®è¨­å®š"
-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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2182,10 +2275,10 @@ msgstr "イベント"
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2302,6 +2395,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2311,10 +2413,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2326,19 +2428,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Integration"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2353,6 +2464,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2362,7 +2479,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2380,7 +2500,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2389,6 +2509,27 @@ msgstr "アラート"
msgid "Alerts endpoint"
msgstr "アラートエンドãƒã‚¤ãƒ³ãƒˆ"
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr "アルゴリズム"
@@ -2455,9 +2596,6 @@ msgstr "ã“ã®ãƒ—ロジェクト㧠%{linkStart} Auto DevOps %{linkEnd} ãŒæœ‰åŠ
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr "ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼"
-
msgid "All users must have a name."
msgstr "ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«åå‰ãŒå¿…è¦ã§ã™ã€‚"
@@ -2482,6 +2620,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr "オーナーãŒLDAPã¨é–¢ä¿‚ãªãユーザーを手動ã§è¿½åŠ ã§ãるよã†ã«ã™ã‚‹"
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—内ã®ãƒ—ロジェクト㫠Git LFS を使用ã§ãるよã†ã«ã™ã‚‹"
@@ -2503,11 +2644,14 @@ msgstr "システムフックã‹ã‚‰ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ãƒªã‚¯
msgid "Allow requests to the local network from web hooks and services"
msgstr "web フックãŠã‚ˆã³ã‚µãƒ¼ãƒ“スã‹ã‚‰ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’許å¯ã™ã‚‹ã€‚"
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr "ã“ã®ã‚­ãƒ¼ã‚‚リãƒã‚¸ãƒˆãƒªã«ãƒ—ッシュã§ãるよã†ã«ã—ã¾ã™ã‹ï¼Ÿ (デフォルトã¯ãƒ—ルアクセスã®ã¿ã‚’許å¯ã—ã¾ã™)"
msgid "Allow this secondary node to replicate content on Object Storage"
-msgstr ""
+msgstr "ã“ã®ã‚»ã‚«ãƒ³ãƒ€ãƒªãƒŽãƒ¼ãƒ‰ãŒã‚ªãƒ–ジェクトストレージ上ã«ã‚³ãƒ³ãƒ†ãƒ³ãƒ„を複製ã™ã‚‹ã“ã¨ã‚’許å¯ã—ã¾ã™"
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -2524,12 +2668,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "メールドメイン制é™ã¯ã€æœ€ä¸Šä½ã‚°ãƒ«ãƒ¼ãƒ—ã«ã®ã¿è¨±å¯ã•ã‚Œã¾ã™"
msgid "Allowed to fail"
msgstr "失敗を許容"
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Kubernetes クラスターを追加ãŠã‚ˆã³ç®¡ç†ã§ãã¾ã™ã€‚"
@@ -2552,7 +2702,7 @@ msgid "Alternate support URL for help page and help dropdown"
msgstr "ヘルプページã¨ãƒ˜ãƒ«ãƒ—ドロップダウン用ã®ä»£æ›¿ã‚µãƒãƒ¼ãƒˆURL"
msgid "Alternatively, you can convert your account to a managed account by the %{group_name} group."
-msgstr ""
+msgstr "別ã®æ–¹æ³•ã¨ã—ã¦ã€ ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ %{group_name} グループã«ã‚ˆã£ã¦ç®¡ç†ã•ã‚ŒãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«å¤‰æ›ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
msgid "Amazon EKS"
msgstr "Amazon EKS"
@@ -2578,9 +2728,12 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
-msgid "An alert has been triggered in %{project_path}."
+msgid "An alert has been resolved in %{project_path}."
msgstr ""
+msgid "An alert has been triggered in %{project_path}."
+msgstr "%{project_path} ã§ã‚¢ãƒ©ãƒ¼ãƒˆãŒ トリガーã•ã‚Œã¾ã—ãŸã€‚"
+
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "アプリケーション㮠%{link_to_client} ãŒã‚ãªãŸã® GitLab アカウントã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’è¦æ±‚ã—ã¦ã„ã¾ã™ã€‚"
@@ -2590,9 +2743,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "GitLab ユーザフィールドãŒç©ºã®å ´åˆã€ã™ã¹ã¦ã®å•é¡Œã¨ã‚³ãƒ¡ãƒ³ãƒˆã®èª¬æ˜Žã« FogBugz ユーザã®ãƒ•ãƒ«ãƒãƒ¼ãƒ  (例ãˆã°ã€By John Smith)を追加ã—ã¾ã™ã€‚ã¾ãŸã€ã“れらã®å•é¡Œã‚„コメントをプロジェクト作æˆè€…ã«é–¢é€£ä»˜ã‘ã‚‹ã‹ã€ã¾ãŸã¯å‰²ã‚Šå½“ã¦ã¾ã™ã€‚"
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2620,9 +2779,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr "Blobã®ãƒ—レビュー中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "通知購読ã®åˆ‡ã‚Šæ›¿ãˆæ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "課題ã®ã‚¦ã‚¨ã‚¤ãƒˆæ›´æ–°æ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -2633,13 +2798,13 @@ msgid "An error occurred while adding approvers"
msgstr ""
msgid "An error occurred while adding formatted title for epic"
-msgstr ""
+msgstr "エピックã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆæ¸ˆã¿ã‚¿ã‚¤ãƒˆãƒ«ã‚’追加ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while checking group path. Please refresh and try again."
msgstr ""
msgid "An error occurred while decoding the file."
-msgstr ""
+msgstr "ファイルã®ãƒ‡ã‚³ãƒ¼ãƒ‰ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while deleting the approvers group"
msgstr "承èªè€…グループã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -2672,7 +2837,7 @@ msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
-msgstr ""
+msgstr "ã‚«ãƒãƒ¬ãƒƒã‚¸ãƒ¬ãƒãƒ¼ãƒˆã®å–å¾—ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while fetching environments."
msgstr "環境ã®çŠ¶æ…‹å–å¾—ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -2710,9 +2875,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 "ボードリストã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -2785,9 +2947,6 @@ 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 ""
@@ -2804,7 +2963,7 @@ msgid "An error occurred while loading the file."
msgstr "ファイルã®ãƒ­ãƒ¼ãƒ‰ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while loading the file. Please try again later."
-msgstr ""
+msgstr "ファイルã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "An error occurred while loading the merge request changes."
msgstr "マージリクエストã®å¤‰æ›´ã‚’読込中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -2818,9 +2977,6 @@ 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 "リクエスト作æˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -2831,7 +2987,7 @@ msgid "An error occurred while parsing recent searches"
msgstr "検索履歴ã®è§£æžä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while parsing the file."
-msgstr ""
+msgstr "ファイルã®ãƒ‘ース中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while removing epics."
msgstr "エピックã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -2845,6 +3001,9 @@ msgstr "プレビュー時ã®ãƒ–ロードキャストメッセージをレンダ
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr "課題ã®ä¸¦ã¹æ›¿ãˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -2869,9 +3028,6 @@ msgstr "LDAP ã®ã‚ªãƒ¼ãƒãƒ¼ãƒ©ã‚¤ãƒ‰çŠ¶æ…‹ã‚’ä¿å­˜ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç
msgid "An error occurred while saving assignees"
msgstr "担当者ã®ç™»éŒ²ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr "通知ã®è³¼èª­ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -2887,6 +3043,9 @@ msgstr "通知ã®è³¼èª­ã‚’解除中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while updating approvers"
msgstr "承èªè€…ã®æ›´æ–°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -2906,7 +3065,7 @@ msgid "An error occurred. Please try again."
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†åº¦ãŠè©¦ã—ãã ã•ã„。"
msgid "An error ocurred while loading your content. Please try again."
-msgstr ""
+msgstr "コンテンツã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "An example project for managing Kubernetes clusters integrated with GitLab."
msgstr ""
@@ -3150,7 +3309,7 @@ msgid "ApprovalRule|Rule name"
msgstr "ルールå"
msgid "ApprovalRule|Target branch"
-msgstr ""
+msgstr "ターゲットブランãƒ"
msgid "ApprovalRule|e.g. QA, Security, etc."
msgstr "例:QAã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãªã©"
@@ -3212,6 +3371,9 @@ msgstr "アーカイブジョブ"
msgid "Archive project"
msgstr "プロジェクトをアーカイブ"
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr "アーカイブ済ã¿"
@@ -3249,7 +3411,7 @@ msgid "Are you sure you want to delete \"%{name}\" Value Stream?"
msgstr ""
msgid "Are you sure you want to delete %{name}?"
-msgstr ""
+msgstr "%{name} を削除ã—ã¾ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to delete these artifacts?"
msgstr "ã“れらã®ã‚¢ãƒ¼ãƒ†ã‚£ãƒ•ã‚¡ã‚¯ãƒˆã‚’削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -3276,7 +3438,7 @@ msgid "Are you sure you want to delete this pipeline? Doing so will expire all p
msgstr "ã“ã®ãƒ‘イプラインを削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿã“ã‚Œã«ã‚ˆã‚Šã€ã™ã¹ã¦ã®ãƒ‘イプラインキャッシュãŒæœŸé™åˆ‡ã‚Œã«ãªã‚Šã€ãƒ“ルドã€ãƒ­ã‚°ã€ã‚¢ãƒ¼ãƒ†ã‚£ãƒ•ã‚¡ã‚¯ãƒˆã€ãƒˆãƒªã‚¬ãƒ¼ãªã©ã®é–¢é€£ã‚ªãƒ–ジェクトãŒã™ã¹ã¦å‰Šé™¤ã•ã‚Œã¾ã™ã€‚ã“ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯å…ƒã«æˆ»ã›ã¾ã›ã‚“。"
msgid "Are you sure you want to deploy this environment?"
-msgstr ""
+msgstr "ã“ã®ç’°å¢ƒã‚’デプロイã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to discard this comment?"
msgstr ""
@@ -3298,7 +3460,7 @@ msgid "Are you sure you want to merge immediately?"
msgstr "本当ã«ã™ãã«ãƒžãƒ¼ã‚¸ã—ã¾ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to re-deploy this environment?"
-msgstr ""
+msgstr "ã“ã®ç’°å¢ƒã‚’å†ãƒ‡ãƒ—ロイã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "公開éµã‚’å†ç”Ÿæˆã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹? ミラーリングを行ã†å‰ã«ãƒªãƒ¢ãƒ¼ãƒˆã‚µãƒ¼ãƒãƒ¼ã®å…¬é–‹éµã‚’æ›´æ–°ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
@@ -3459,6 +3621,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr "自分ã«å‰²ã‚Šå½“ã¦ã‚‹"
@@ -3591,7 +3756,7 @@ msgid "Authenticating"
msgstr "èªè¨¼ä¸­"
msgid "Authentication Failure"
-msgstr ""
+msgstr "èªè¨¼å¤±æ•—"
msgid "Authentication Log"
msgstr "èªè¨¼ãƒ­ã‚°"
@@ -3624,7 +3789,7 @@ msgid "Authored %{timeago}"
msgstr ""
msgid "Authored %{timeago} by %{author}"
-msgstr ""
+msgstr "%{author}ã«ã‚ˆã£ã¦ %{timeago} ã«ä½œæˆã•ã‚Œã¾ã—ãŸ"
msgid "Authorization code:"
msgstr "èªè¨¼ã‚³ãƒ¼ãƒ‰:"
@@ -3701,8 +3866,29 @@ msgstr "ã‚らã‹ã˜ã‚定義ã•ã‚ŒãŸ CI/CD ã®æ§‹æˆã‚’基ã«è‡ªå‹•çš„ã«ã‚¢ãƒ
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "詳ã—ãã¯ã€ %{link_to_documentation} を見ã¦ãã ã•ã„。"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "Auto DevOpsã®ãƒ‘イプラインãŒæœ‰åŠ¹ã«ãªã£ã¦ãŠã‚Šã€ä»£æ›¿ã®CIã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ãŒè¦‹ã¤ã‹ã‚‰ãªã„å ´åˆã«ä½¿ç”¨ã—ã¾ã™ã€‚ %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr "オートコンプリート"
@@ -3722,6 +3908,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 "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3740,6 +3929,9 @@ msgstr "注æ„"
msgid "Available"
msgstr "利用å¯èƒ½"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3768,7 +3960,7 @@ msgid "Average per day: %{average}"
msgstr "1æ—¥ã‚ãŸã‚Šã®å¹³å‡: %{average}"
msgid "Back to page %{number}"
-msgstr ""
+msgstr "%{number}ページã«æˆ»ã‚‹"
msgid "Background Color"
msgstr "背景色"
@@ -3797,9 +3989,6 @@ msgstr "ãƒãƒƒã‚¸ç”»åƒã®URL"
msgid "Badges|Badge image preview"
msgstr "ãƒãƒƒã‚¸ç”»åƒãƒ—レビュー"
-msgid "Badges|Delete badge"
-msgstr "ãƒãƒƒã‚¸ã‚’削除"
-
msgid "Badges|Delete badge?"
msgstr "ãƒãƒƒã‚¸ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ"
@@ -3881,6 +4070,12 @@ msgstr "Bamboo ã®ãƒ«ãƒ¼ãƒˆURL 例: https://bamboo.example.com"
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr "Bambooã§è‡ªå‹•ãƒªãƒ“ジョンラベリングã¨ãƒªãƒã‚¸ãƒˆãƒªãƒˆãƒªã‚¬ãƒ¼ã‚’設定ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "ã”注æ„ãã ã•ã„。プロジェクトã®åå‰ç©ºé–“を変更ã™ã‚‹ã¨ã€æ„図ã—ãªã„副作用ãŒç™ºç”Ÿã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -3965,6 +4160,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "アップグレード"
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr "Bitbucket サーãƒãƒ¼ インãƒãƒ¼ãƒˆ"
@@ -4016,12 +4223,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4040,6 +4256,9 @@ msgstr "å…¨ã¦è¡¨ç¤º"
msgid "Boards|View scope"
msgstr "スコープ表示"
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4052,6 +4271,9 @@ msgstr "%{branchName} ブランãƒã¯ã“ã®ãƒ—ロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4196,6 +4418,9 @@ msgstr "プロジェクト設定"
msgid "Branches|protected"
msgstr "ä¿è­·"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr "ブロードキャストメッセージã¯æ­£å¸¸ã«ä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
@@ -4232,9 +4457,21 @@ msgstr "ビルトイン"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr "ãƒãƒ¼ãƒ³ãƒ€ã‚¦ãƒ³ãƒãƒ£ãƒ¼ãƒˆ"
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr "課題ã®é‡ã¿ã‚’é–‹ã"
@@ -4265,7 +4502,7 @@ msgstr "%{user_name} ã«ã‚ˆã‚‹"
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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4284,7 +4521,7 @@ msgid "CI / CD"
msgstr "CI / CD"
msgid "CI / CD Analytics"
-msgstr ""
+msgstr "CI/CD ã®åˆ†æž"
msgid "CI / CD Settings"
msgstr "CI / CD 設定"
@@ -4448,6 +4685,9 @@ msgstr "ä¸æ­£åˆ©ç”¨ãƒ¬ãƒãƒ¼ãƒˆã‚’作æˆã§ãã¾ã›ã‚“。ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr "複数ã®Jiraインãƒãƒ¼ãƒˆã‚’åŒæ™‚ã«å®Ÿè¡Œã§ãã¾ã›ã‚“"
@@ -4704,7 +4944,7 @@ msgid "Checkout"
msgstr "Checkout"
msgid "Checkout|$%{selectedPlanPrice} per user per year"
-msgstr ""
+msgstr "ユーザー・年間ã‚ãŸã‚Š %{selectedPlanPrice} ドル"
msgid "Checkout|%{cardType} ending in %{lastFourDigits}"
msgstr ""
@@ -4740,7 +4980,7 @@ msgid "Checkout|Continue to billing"
msgstr "請求ã«ç¶šã"
msgid "Checkout|Continue to payment"
-msgstr ""
+msgstr "支払ã„を続行"
msgid "Checkout|Country"
msgstr "国"
@@ -4749,10 +4989,10 @@ msgid "Checkout|Create a new group"
msgstr "æ–°ã—ã„グループを作æˆ"
msgid "Checkout|Credit card form failed to load. Please try again."
-msgstr ""
+msgstr "クレジットカードã®ãƒ•ã‚©ãƒ¼ãƒ èª­ã¿è¾¼ã¿å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Checkout|Credit card form failed to load: %{message}"
-msgstr ""
+msgstr "クレジットカードã®ãƒ•ã‚©ãƒ¼ãƒ èª­ã¿è¾¼ã¿å¤±æ•—ã—ã¾ã—ãŸã€‚: %{message}"
msgid "Checkout|Edit"
msgstr "編集"
@@ -4764,13 +5004,13 @@ msgid "Checkout|Failed to confirm your order! Please try again."
msgstr "注文ã®ç¢ºèªã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Checkout|Failed to confirm your order: %{message}. Please try again."
-msgstr ""
+msgstr "注文ã®ç¢ºèªã«å¤±æ•—ã—ã¾ã—ãŸã€‚: %{message} ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Checkout|Failed to load countries. Please try again."
-msgstr ""
+msgstr "国情報ã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Checkout|Failed to load states. Please try again."
-msgstr ""
+msgstr "都é“府県や州ã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Checkout|Failed to register credit card. Please try again."
msgstr "クレジットカードã®ç™»éŒ²ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -4794,13 +5034,13 @@ msgid "Checkout|Number of users"
msgstr "ユーザー数"
msgid "Checkout|Payment method"
-msgstr ""
+msgstr "支払ã„方法"
msgid "Checkout|Please select a country"
-msgstr ""
+msgstr "国をé¸æŠžã—ã¦ãã ã•ã„"
msgid "Checkout|Please select a state"
-msgstr ""
+msgstr "都é“府県ã¾ãŸã¯å·žã‚’é¸æŠžã—ã¦ãã ã•ã„"
msgid "Checkout|Select"
msgstr "é¸æŠž"
@@ -4830,13 +5070,13 @@ msgid "Checkout|Users"
msgstr "ユーザー"
msgid "Checkout|You'll create your new group after checkout"
-msgstr ""
+msgstr "ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆå¾Œã«æ–°ã—ã„グループを作æˆã—ã¾ã™ã€‚"
msgid "Checkout|Your organization"
msgstr "組織"
msgid "Checkout|Your subscription will be applied to this group"
-msgstr ""
+msgstr "ã‚ãªãŸã®ã‚µãƒ–スクリプションã¯ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«é©ç”¨ã•ã‚Œã¾ã™"
msgid "Checkout|Zip code"
msgstr ""
@@ -4859,6 +5099,9 @@ msgstr "å­ã‚¨ãƒ”ックã¯å­˜åœ¨ã—ã¾ã›ã‚“。"
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5042,9 +5285,6 @@ msgstr "ã™ã¹ã¦ã®ç’°å¢ƒ"
msgid "CiVariable|Create wildcard"
msgstr "ワイルドカードã®ä½œæˆ"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr "変数ä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
-
msgid "CiVariable|Masked"
msgstr "マスク"
@@ -5063,9 +5303,6 @@ msgstr "マスクã®åˆ‡ã‚Šæ›¿ãˆ"
msgid "CiVariable|Toggle protected"
msgstr "ä¿è­·ã®åˆ‡ã‚Šæ›¿ãˆ"
-msgid "CiVariable|Validation failed"
-msgstr "検証ã«å¤±æ•—ã—ã¾ã—ãŸ"
-
msgid "Classification Label (optional)"
msgstr "分類ラベル (オプション)"
@@ -5174,6 +5411,9 @@ msgstr "%{tabname} ã‚’é–‰ã˜ã‚‹"
msgid "Close epic"
msgstr "エピックを閉ã˜ã‚‹"
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr "マイルストーンを閉ã˜ã‚‹"
@@ -5198,8 +5438,8 @@ msgstr "クローズã—ãŸèª²é¡Œ"
msgid "Closed this %{quick_action_target}."
msgstr "%{quick_action_target} ã‚’é–‰ã˜ãŸã€‚"
-msgid "Closed: %{closedIssuesCount}"
-msgstr "é–‰ã˜ãŸä»¶æ•°: %{closedIssuesCount} "
+msgid "Closed: %{closed}"
+msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "ã“ã® %{quick_action_target} ã‚’é–‰ã˜ã‚‹ã€‚"
@@ -5225,6 +5465,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5408,6 +5651,9 @@ msgstr "クラスターã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’削除"
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr "クラスター管ç†ãƒ—ロジェクト(アルファ)"
@@ -5465,9 +5711,6 @@ msgstr "インスタンスタイプをロードã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "ClusterIntegration|Could not load networks"
msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’ロードã§ãã¾ã›ã‚“ã§ã—ãŸ"
-msgid "ClusterIntegration|Could not load regions from your AWS account"
-msgstr "ã‚ãªãŸã®AWSアカウントã‹ã‚‰ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ロードã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
-
msgid "ClusterIntegration|Could not load security groups for the selected VPC"
msgstr "é¸æŠžã—㟠VPC ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚°ãƒ«ãƒ¼ãƒ—をロードã§ãã¾ã›ã‚“ã§ã—ãŸ"
@@ -5723,9 +5966,6 @@ msgstr "%{help_link_start_machine_type}マシンタイプ%{help_link_end}ã¨%{he
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "%{help_link_start}ゾーン%{help_link_end}ã®è©³ç´°ã€‚"
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr "Kubernetes ã®è©³ç´°"
@@ -5741,9 +5981,6 @@ msgstr "IAMロールã®ãƒ­ãƒ¼ãƒ‰"
msgid "ClusterIntegration|Loading Key Pairs"
msgstr "キーペアをロード"
-msgid "ClusterIntegration|Loading Regions"
-msgstr "リージョンã®ãƒ­ãƒ¼ãƒ‰ä¸­"
-
msgid "ClusterIntegration|Loading VPCs"
msgstr "VPC をロード"
@@ -5810,9 +6047,6 @@ msgstr "プロジェクトãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "ClusterIntegration|No projects matched your search"
msgstr "検索æ¡ä»¶ã«ä¸€è‡´ã™ã‚‹ãƒ—ロジェクトã¯ã‚ã‚Šã¾ã›ã‚“"
-msgid "ClusterIntegration|No region found"
-msgstr "リージョンãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
-
msgid "ClusterIntegration|No security group found"
msgstr "セキュリティグループãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
@@ -5879,9 +6113,6 @@ msgstr "çµ±åˆKubernetesクラスターã«ã¤ã„ã¦ã¯ã€%{link_start}ヘルプã
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 "Kubernetes クラスターã®çµ±åˆã‚’削除"
@@ -5948,9 +6179,6 @@ msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®æ¤œç´¢"
msgid "ClusterIntegration|Search projects"
msgstr "プロジェクトã®æ¤œç´¢"
-msgid "ClusterIntegration|Search regions"
-msgstr "リージョンã®æ¤œç´¢"
-
msgid "ClusterIntegration|Search security groups"
msgstr "セキュリティグループを検索"
@@ -6011,6 +6239,9 @@ msgstr "プロジェクトをé¸æŠžã—ã¦ã‚¾ãƒ¼ãƒ³ã‚’é¸æŠž"
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr "ゾーンをé¸æŠž"
@@ -6095,6 +6326,9 @@ msgstr "ã“ã®ã‚¨ãƒ³ãƒ‰ãƒã‚¤ãƒ³ãƒˆã¯å‰²ã‚Šå½“ã¦ãƒ—ロセス実施中ã§ã™ã€‚
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr "クラスターã¨ã®èªè¨¼ã«å•é¡ŒãŒã‚ã‚Šã¾ã—ãŸã€‚ CA証明書ã¨ãƒˆãƒ¼ã‚¯ãƒ³ãŒæœ‰åŠ¹ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
@@ -6236,9 +6470,6 @@ msgstr "VPCã‚’é¸æŠž"
msgid "ClusterIntergation|Select a network"
msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’é¸æŠž"
-msgid "ClusterIntergation|Select a region"
-msgstr "リージョンã®é¸æŠž"
-
msgid "ClusterIntergation|Select a security group"
msgstr "セキュリティグループをé¸æŠž"
@@ -6350,9 +6581,6 @@ msgstr "コレクタã®ãƒ›ã‚¹ãƒˆå"
msgid "ComboSearch is not defined"
msgstr "ComboSearch ãŒå®šç¾©ã•ã‚Œã¦ã„ã¾ã›ã‚“"
-msgid "Coming soon"
-msgstr ""
-
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
msgstr ""
@@ -6535,13 +6763,13 @@ msgid "Completed"
msgstr ""
msgid "Compliance"
-msgstr ""
+msgstr "コンプライアンス"
msgid "Compliance Dashboard"
-msgstr ""
+msgstr "コンプライアンスダッシュボード"
msgid "Compliance framework (optional)"
-msgstr ""
+msgstr "コンプライアンスフレームワーク(オプション)"
msgid "Compliance frameworks"
msgstr ""
@@ -6619,7 +6847,7 @@ msgid "Configure existing installation"
msgstr "既存ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’設定ã™ã‚‹"
msgid "Configure limit for issues created per minute by web and API requests."
-msgstr ""
+msgstr "Web 㨠API リクエストã«ã‚ˆã£ã¦1分ã‚ãŸã‚Šã«ä½œæˆã•ã‚Œã‚‹èª²é¡Œã®åˆ¶é™ã‚’設定ã—ã¾ã™ã€‚"
msgid "Configure limits for Project/Group Import/Export."
msgstr ""
@@ -6663,7 +6891,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6714,6 +6942,9 @@ msgstr "接続タイムアウト"
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr "アップグレードã®å•ã„åˆã‚ã›"
@@ -6779,6 +7010,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -6880,7 +7114,7 @@ msgid "ContainerRegistry|Something went wrong while fetching the repository list
msgstr ""
msgid "ContainerRegistry|Something went wrong while fetching the tags list."
-msgstr ""
+msgstr "tagリストã®å–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "ContainerRegistry|Something went wrong while marking the tag for deletion."
msgstr ""
@@ -7129,7 +7363,7 @@ msgid "Copy file path"
msgstr "ファイルã®ãƒ‘スをコピー"
msgid "Copy key"
-msgstr ""
+msgstr "キーをコピー"
msgid "Copy labels and milestone from %{source_issuable_reference}."
msgstr "%{source_issuable_reference} ã‹ã‚‰ãƒ©ãƒ™ãƒ«ã¨ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’コピー。"
@@ -7155,6 +7389,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7215,6 +7452,9 @@ msgstr "ãƒãƒ£ãƒƒãƒˆã®ãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ  %{chat_name} を削除ã§ãã¾ã›ã‚“ã
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7224,6 +7464,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr "トリガーを除去ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -7257,6 +7500,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr "デザインをアップロードã§ãã¾ã›ã‚“ã§ã—ãŸã€‚アップロードã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã«ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ãªã„ã‚‚ã®ãŒå«ã¾ã‚Œã¦ã„ã¾ã—ãŸã€‚"
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr "国"
@@ -7504,6 +7750,9 @@ msgstr "%{projectLink} ã«ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ %{mergeRequestLink} を作æˆ
msgid "Created on"
msgstr "作æˆæ—¥æ™‚"
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr "作æˆæ—¥æ™‚:"
@@ -7597,6 +7846,9 @@ msgstr "カスタムCIã®è¨­å®šãƒ‘ス"
msgid "Custom Git clone URL for HTTP(S)"
msgstr "HTTP(S) 用ã®ã‚«ã‚¹ã‚¿ãƒ  Git クローン URL"
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr "カスタムホストå (プライベートコミット用メールアドレス)"
@@ -7793,7 +8045,7 @@ msgid "CycleAnalyticsStage|should be under a group"
msgstr "グループã®ä¸‹ã«ã‚ã‚‹ã¹ãã§ã™"
msgid "CycleAnalytics|%{selectedLabelsCount} selected (%{maxLabels} max)"
-msgstr ""
+msgstr "%{selectedLabelsCount} 件é¸æŠžæ¸ˆã¿ (最大 %{maxLabels} 件)"
msgid "CycleAnalytics|%{stageCount} stages selected"
msgstr "%{stageCount} ステージãŒé¸æŠžã•ã‚Œã¾ã—ãŸ"
@@ -7847,11 +8099,14 @@ msgstr "タイプ別ã®ã‚¿ã‚¹ã‚¯"
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr "指定ã•ã‚ŒãŸæ—¥ä»˜ã®ç¯„囲ãŒ180日を超ãˆã¦ã„ã¾ã™ã€‚"
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr "完了ã¾ã§ã®æ—¥æ•°åˆè¨ˆ"
msgid "CycleAnalytics|Type of work"
-msgstr ""
+msgstr "仕事ã®ç¨®é¡ž"
msgid "CycleAnalytics|group dropdown filter"
msgstr "グループドロップダウンフィルター"
@@ -7904,6 +8159,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -7943,6 +8207,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -7964,6 +8234,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -7991,15 +8267,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8015,6 +8291,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8054,6 +8333,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8066,6 +8348,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8075,6 +8363,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr "データã¯ã¾ã è¨ˆç®—中ã§ã™..."
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8231,9 +8522,6 @@ msgstr ""
msgid "Delete Comment"
msgstr "コメントを削除"
-msgid "Delete Snippet"
-msgstr "スニペットを削除"
-
msgid "Delete Value Stream"
msgstr ""
@@ -8243,6 +8531,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr "アーãƒãƒ•ã‚¡ã‚¯ãƒˆã‚’削除"
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr "ボードã®å‰Šé™¤"
@@ -8258,9 +8549,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr "リストを削除ã™ã‚‹"
-
msgid "Delete pipeline"
msgstr "パイプラインã®å‰Šé™¤"
@@ -8282,6 +8570,9 @@ msgstr "スニペットを削除?"
msgid "Delete source branch"
msgstr "ソースブランãƒã‚’削除"
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr "ã“ã®æ·»ä»˜ãƒ•ã‚¡ã‚¤ãƒ«ã‚’削除"
@@ -8345,12 +8636,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr "ãƒãƒ£ãƒƒãƒˆãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ  %{user_name} ã®æ‰¿èªã‚’æ‹’å¦ã—ã¾ã—ãŸã€‚"
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr "æ‹’å¦"
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr "ä¾å­˜é–¢ä¿‚"
@@ -8396,18 +8693,27 @@ msgstr "JSONエクスãƒãƒ¼ãƒˆ"
msgid "Dependencies|Job failed to generate the dependency list"
msgstr "ä¾å­˜é–¢ä¿‚リストã®ç”Ÿæˆã«å¤±æ•—ã—ã¾ã—ãŸ"
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr "ライセンス"
msgid "Dependencies|Location"
msgstr "ロケーション"
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr "パッケージャー"
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr "%{codeStartTag}ä¾å­˜é–¢ä¿‚スキャニング%{codeEndTag}ジョブã«å¤±æ•—ã—ä¾å­˜é–¢ä¿‚リストを生æˆã§ãã¾ã›ã‚“。ジョブãŒæ­£ã—ã実行ã•ã‚Œã¦ã„ã‚‹ã‹ç¢ºèªã—ãŸä¸Šã§ãƒ‘イプラインをå†å®Ÿè¡Œã—ã¦ãã ã•ã„。"
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8480,9 +8786,6 @@ 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 "%{appLabel} ラベルã¯ãƒ‡ãƒ—ロイボードã‹ã‚‰å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚ボード上ã®ã™ã¹ã¦ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’見るãŸã‚ã«ã¯ã€ãƒãƒ£ãƒ¼ãƒˆã‚’æ›´æ–°ã—ã¦å†è¡¨ç¤ºã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-
msgid "DeployFreeze|Freeze end"
msgstr ""
@@ -8568,7 +8871,7 @@ msgid "DeployTokens|Allows write access to the package registry"
msgstr ""
msgid "DeployTokens|Allows write access to the registry images"
-msgstr ""
+msgstr "レジストリイメージã¸ã®æ›¸ãè¾¼ã¿ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã™ã‚‹"
msgid "DeployTokens|Copy deploy token"
msgstr "デプロイトークンをコピー"
@@ -8648,6 +8951,12 @@ msgstr "デプロイ済ã¿"
msgid "Deployed to"
msgstr "デプロイ先"
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr "デプロイ先"
@@ -8696,6 +9005,9 @@ msgstr "説明"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "%{link_start} GitLab風ã®ãƒžãƒ¼ã‚¯ãƒ€ã‚¦ãƒ³ %{link_end} ã§ãƒ‘ースã—ãŸèª¬æ˜Ž"
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr "Description テンプレートを使用ã™ã‚‹ã¨ã€ãƒ—ロジェクトã®èª²é¡ŒãŠã‚ˆã³ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆèª¬æ˜Žã«å¯¾ã™ã‚‹ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆå›ºæœ‰ã®ãƒ†ãƒ³ãƒ—レートを定義ã§ãã¾ã™ã€‚"
@@ -8867,6 +9179,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr "差分コンテンツã®åˆ¶é™"
@@ -8918,8 +9251,8 @@ msgstr "グループ Runner を無効ã«ã™ã‚‹"
msgid "Disable public access to Pages sites"
msgstr "Pages サイトã¸ã®å…¬é–‹ã‚¢ã‚¯ã‚»ã‚¹ã‚’無効ã«ã™ã‚‹"
-msgid "Disable shared Runners"
-msgstr "共有 Runner を無効化"
+msgid "Disable shared runners"
+msgstr ""
msgid "Disable two-factor authentication"
msgstr "2è¦ç´ èªè¨¼ã‚’無効ã«ã™ã‚‹"
@@ -9066,6 +9399,9 @@ msgstr "文書"
msgid "Documentation for popular identity providers"
msgstr "一般的㪠ID プロãƒã‚¤ãƒ€ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ"
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9075,6 +9411,9 @@ msgstr "ドメイン"
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr "ドメイン検証ã¯ã€å…¬é–‹ã—ã¦ã„ã‚‹ GitLab サイトã«ã¨ã£ã¦ä¸å¯æ¬ ãªã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£å¯¾ç­–ã§ã™ã€‚ユーザーã¯ã€ãƒ‰ãƒ¡ã‚¤ãƒ³ãŒæœ‰åŠ¹ã«ãªã‚‹å‰ã«ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’制御ã—ã¦ã„ã‚‹ã“ã¨ã‚’示ã™å¿…è¦ãŒã‚ã‚Šã¾ã™"
@@ -9096,6 +9435,9 @@ 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 "-----BEGIN PGP PUBLIC KEY BLOCK----- ã§å§‹ã¾ã‚‹å…¬é–‹éƒ¨åˆ†ã‚’貼り付ã‘ã¦ãã ã•ã„。 GPG キーã®ç§˜å¯†éƒ¨åˆ†ã‚’貼り付ã‘ãªã„ã§ä¸‹ã•ã„。"
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "次回ã‹ã‚‰è¡¨ç¤ºã—ãªã„"
@@ -9123,9 +9465,6 @@ msgstr "別åã§ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰"
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr "アセットをダウンロード"
-
msgid "Download codes"
msgstr "コードをダウンロード"
@@ -9294,15 +9633,24 @@ msgstr "公開デプロイキーã®ç·¨é›†"
msgid "Edit stage"
msgstr "ステージã®ç·¨é›†"
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr "ã“ã®ãƒªãƒªãƒ¼ã‚¹ã‚’編集ã—ã¾ã™ã€‚"
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr "Wikiページã®ç·¨é›†"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "スレッド内ã®æœ€æ–°ã®ã‚ãªãŸã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’編集 (空ã®ãƒ†ã‚­ã‚¹ãƒˆé ˜åŸŸã‹ã‚‰)"
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9375,6 +9723,9 @@ msgstr "メールé€ä¿¡å®Œäº†"
msgid "Email the pipelines status to a list of recipients."
msgstr "パイプラインã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’å—信者ã®ãƒªã‚¹ãƒˆã«Eメールã§é€šçŸ¥ã—ã¾ã™ã€‚"
+msgid "Email updates (optional)"
+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 "メールãŒç©ºã®ã‚ˆã†ã§ã™ã€‚返信文ãŒãƒ¡ãƒ¼ãƒ«ã®ä¸€ç•ªä¸Šã«ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。インラインã®è¿”ä¿¡ã¯å‡¦ç†ã§ãã¾ã›ã‚“。"
@@ -9516,6 +9867,12 @@ msgstr "メールã®ãƒ˜ãƒƒãƒ€ãƒ¼ã¨ãƒ•ãƒƒã‚¿ãƒ¼ã‚’有効ã«ã™ã‚‹"
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9543,8 +9900,20 @@ msgstr "プロキシを有効ã«ã™ã‚‹"
msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr "reCAPTCHA ã¾ãŸã¯ Akismet を有効ã«ã—ã¦ã€IP制é™ã‚’設定ã—ã¾ã™ã€‚ reCAPTCHA ã«ã¤ã„ã¦ã¯ã€ç¾åœ¨ %{recaptcha_v2_link_start} v2 %{recaptcha_v2_link_end} ã®ã¿ã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚"
-msgid "Enable shared Runners"
-msgstr "共有 Runner を有効化"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
+msgstr ""
msgid "Enable snowplow tracking"
msgstr "スノープロウトラッキングを有効ã«ã™ã‚‹"
@@ -9588,6 +9957,9 @@ msgstr "ã“れを有効ã«ã™ã‚‹ã¨ã€ãƒ—ロジェクトåå‰ç©ºé–“ã®è¨ˆç”»ã«
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "終了時刻 (UTC)"
@@ -9615,7 +9987,10 @@ msgstr "IPアドレスã®ç¯„囲を入力"
msgid "Enter a number"
msgstr "数値ã®å…¥åŠ›"
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -9862,7 +10237,7 @@ msgid "Environments|Open live environment"
msgstr "ライブ環境を開ã"
msgid "Environments|Pod name"
-msgstr ""
+msgstr "ãƒãƒƒãƒ‰å"
msgid "Environments|Re-deploy"
msgstr "å†ãƒ‡ãƒ—ロイ"
@@ -10377,12 +10752,18 @@ msgstr "例: Usage = å˜ä¸€ã‚¯ã‚¨ãƒªã€‚ (Requested) / (Capacity) = å¼ã‚’構æˆã
msgid "Except policy:"
msgstr "除外ãƒãƒªã‚·ãƒ¼:"
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr "マージコミットを除外ã—ã¦ã„ã¾ã™ã€‚%{limit} 件ã®ã‚³ãƒŸãƒƒãƒˆã«åˆ¶é™ã•ã‚Œã¦ã„ã¾ã™ã€‚"
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "マージコミットを除外ã—ã¦ã„ã¾ã™ã€‚ 6,000件ã®ã‚³ãƒŸãƒƒãƒˆã«åˆ¶é™ã•ã‚Œã¦ã„ã¾ã™ã€‚"
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10413,6 +10794,9 @@ msgstr ""
msgid "Expand approvers"
msgstr "承èªè€…を展開"
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10488,6 +10872,9 @@ msgstr ""
msgid "Export issues"
msgstr "課題をエクスãƒãƒ¼ãƒˆ"
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ"
@@ -10590,6 +10977,9 @@ msgstr "ã“ã®èª²é¡Œã®ãŸã‚ã®ãƒ–ランãƒã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10653,6 +11043,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr "関連ã™ã‚‹ãƒ–ランãƒã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ"
@@ -10665,6 +11058,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr "スタックトレースã®ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr "å‚ç…§ã•ã‚ŒãŸèª²é¡ŒãŒè¦‹ã¤ã‹ã‚‰ãªã„ãŸã‚ã€ã“ã®èª²é¡Œã‚’複製ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -10801,6 +11197,18 @@ msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr "* (ã™ã¹ã¦ã®ç’°å¢ƒ)"
@@ -10831,6 +11239,9 @@ msgstr "設定"
msgid "FeatureFlags|Configure feature flags"
msgstr "機能フラグを設定"
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr "機能フラグを作æˆ"
@@ -10882,6 +11293,9 @@ msgstr "機能フラグ%{name} ãŒã€å‰Šé™¤ã•ã‚Œã¾ã™ã€‚本当ã«å‰Šé™¤ã—ã¾ã
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr "機能フラグを有効ã«ã™ã‚‹ã¨ã€ç‰¹å®šã®æ©Ÿèƒ½ã¸ã®å‹•çš„切り替ãˆã«ã‚ˆã£ã¦ã‚³ãƒ¼ãƒ‰ã«ç•°ãªã‚‹ãƒ•ãƒ¬ãƒ¼ãƒãƒ¼ã‚’設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -10948,11 +11362,14 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr "ロールアウト率(対ログインユーザー)"
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
-msgstr "ロールアウト率ã¯0〜100ã®æ•´æ•°ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
+msgstr ""
msgid "FeatureFlags|Protected"
msgstr "ä¿è­·ã•ã‚Œã¦ã„ã¾ã™"
@@ -10966,6 +11383,9 @@ msgstr "ロールアウトパーセント"
msgid "FeatureFlags|Rollout Strategy"
msgstr "ロールアウト戦略"
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -10984,9 +11404,6 @@ msgstr "機能フラグã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11002,15 +11419,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11020,6 +11437,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "2月"
@@ -11077,12 +11497,18 @@ msgstr "ファイルテンプレート"
msgid "File upload error."
msgstr "ファイルアップロードエラー"
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "ファイル"
msgid "Files breadcrumb"
msgstr "ファイルã®ãƒ‘ンããšãƒªã‚¹ãƒˆ"
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr "パス %{path} 内ã®ãƒ•ã‚¡ã‚¤ãƒ«ã€ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã€ãŠã‚ˆã³ã‚µãƒ–モジュールã®ã‚³ãƒŸãƒƒãƒˆå‚ç…§ %{ref}"
@@ -11107,6 +11533,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11170,6 +11599,9 @@ msgstr "フィルター..."
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11203,9 +11635,6 @@ msgstr ""
msgid "Finished"
msgstr "完了"
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr "åãŒé•·ã™ãŽã¾ã™(最大 %{max_length} 文字)。"
-
msgid "First Seen"
msgstr "最åˆã«è¦‹ãŸ"
@@ -11215,9 +11644,15 @@ msgstr "一週間ã®é–‹å§‹æ›œæ—¥"
msgid "First name"
msgstr "åå‰"
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr "最åˆã«è¦‹ãŸ"
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr "日付を固定"
@@ -11272,8 +11707,8 @@ 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 internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
msgid "For more info, read the documentation."
msgstr "詳細ã«ã¤ã„ã¦ã¯ã€ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’読んã§ãã ã•ã„。"
@@ -11818,7 +12253,7 @@ msgstr "リリースã®é–‹å§‹"
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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11839,6 +12274,9 @@ msgstr "Git シャロークローン"
msgid "Git strategy for pipelines"
msgstr "パイプラインã®Git戦略"
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr "Git ãƒãƒ¼ã‚¸ãƒ§ãƒ³"
@@ -11875,9 +12313,6 @@ 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 "GitLab Shared Runnerã¯ã€GitLab Runnerã®ã‚ªãƒ¼ãƒˆã‚¹ã‚±ãƒ¼ãƒ«è¨­å®šã§MaxBuildsã‚’1 (GitLab.com上ã§ã¯ã“ã®è¨­å®š)ã—ãªã„é™ã‚Šã€åŒã˜Runnerã§åˆ¥ã®ãƒ—ロジェクトã®ã‚³ãƒ¼ãƒ‰ã‚’実行ã—ã¾ã™ã€‚"
-
msgid "GitLab Shell"
msgstr ""
@@ -11902,6 +12337,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr "GitLab for Slack"
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -11942,7 +12383,7 @@ msgid "GitLab.com import"
msgstr "GitLab.com インãƒãƒ¼ãƒˆ"
msgid "GitLabPagesDomains|Retry"
-msgstr ""
+msgstr "リトライ"
msgid "GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}."
msgstr "%{domain}ã¯æ¤œè¨¼ã•ã‚Œã¦ã„ã¾ã›ã‚“。 所有権を確èªã™ã‚‹æ–¹æ³•ã«ã¤ã„ã¦ã¯ã€%{link_start}ドメインã®è©³ç´°%{link_end}ã‚’ã”覧ãã ã•ã„。"
@@ -12011,7 +12452,7 @@ 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 ""
+msgstr "%{domain} ã® Let's Encrypt 証明書をå–å¾—ã™ã‚‹éš›ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†è©¦è¡Œã™ã‚‹ã«ã¯ã€ %{link_start} ドメインã®è©³ç´° %{link_end} ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ãã ã•ã„。"
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr "ドメインã¨è¨¼æ˜Žæ›¸ã®ã‚µãƒãƒ¼ãƒˆãŒç„¡åŠ¹ã§ã™ã€‚有効ã«ã™ã‚‹ã«ã¯ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。"
@@ -12214,6 +12655,9 @@ msgstr "ã‚ãªãŸã®ãƒ—ロジェクトã¸ç§»å‹•"
msgid "Go to your snippets"
msgstr "ã‚ãªãŸã®ã‚¹ãƒ‹ãƒšãƒƒãƒˆã¸ç§»å‹•"
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr "Google Cloud Platform"
@@ -12319,7 +12763,7 @@ msgstr "グループ URL"
msgid "Group avatar"
msgstr "グループアãƒã‚¿ãƒ¼"
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12478,6 +12922,12 @@ msgstr "ロードマップを表示ã™ã‚‹ã«ã¯ã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¾ãŸã¯ã
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "検索範囲を広ã’ã‚‹ã«ã¯ã€ãƒ•ã‚£ãƒ«ã‚¿ã‚’変更ã¾ãŸã¯å‰Šé™¤ã—ã¾ã™ã€‚ %{startDate} ã‹ã‚‰ %{endDate} ã¾ã§"
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "証明書ã®ãƒ•ã‚£ãƒ³ã‚¬ãƒ¼ãƒ—リント"
@@ -12487,6 +12937,9 @@ msgstr "設定"
msgid "GroupSAML|Copy SAML Response XML"
msgstr "SAMLレスãƒãƒ³ã‚¹XMLã®ã‚³ãƒ”ー"
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12532,12 +12985,30 @@ msgstr "NameID"
msgid "GroupSAML|NameID Format"
msgstr "NameID ã®å½¢å¼"
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr "SAMLレスãƒãƒ³ã‚¹å‡ºåŠ›"
@@ -12550,6 +13021,9 @@ msgstr "SAML シングルサインオン"
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr "SAML シングル サインオンã®è¨­å®š"
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr "SCIM APIエンドãƒã‚¤ãƒ³ãƒˆã®URL"
@@ -12562,6 +13036,9 @@ msgstr "SAML トークン㮠SHA1 フィンガープリントã§è¨¼æ˜Žæ›¸ã«ç½²å
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr "SCIMトークンã¯éžè¡¨ç¤ºã«ãªã£ã¦ã„ã¾ã™ã€‚トークンã®å€¤ã‚’ã‚‚ã†ä¸€åº¦ç¢ºèªã™ã‚‹ã«ã¯ã€æ¬¡ã®æ‰‹é †ã‚’実行ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ "
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12586,6 +13063,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr "SCIMトークン"
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -12993,6 +13473,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "履歴"
@@ -13047,9 +13530,6 @@ 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} ã®ãƒ¡ãƒ³ãƒãƒ¼ã§ã™ã€‚招待をå—ã‘入れるã«ã¯ã€åˆ¥ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’使用ã—ã¦ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ã¦ãã ã•ã„。"
-msgid "I accept the %{terms_link_start}Terms of Service and Privacy Policy%{terms_link_end}"
-msgstr "%{terms_link_start} 利用è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼ %{terms_link_end} ã«åŒæ„ã—ã¾ã™ã€‚"
-
msgid "I accept the %{terms_link}"
msgstr "%{terms_link} ã«åŒæ„ã™ã‚‹"
@@ -13062,8 +13542,8 @@ msgstr "パスワードを忘れã¾ã—ãŸ"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr "Let's Encryptã® %{link_start} 利用è¦ç´„ %{link_end} (PDF) を読ã¿ã€åŒæ„ã—ã¾ã—ãŸã€‚"
-msgid "I'd like to receive updates via email about GitLab"
-msgstr "GitLabã«ã¤ã„ã¦ã®æœ€æ–°æƒ…報をメールã§å—ã‘å–ã‚ŠãŸã„"
+msgid "I'd like to receive updates about GitLab via email"
+msgstr ""
msgid "ID"
msgstr "ID"
@@ -13170,6 +13650,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "有効ã«è¨­å®šã—ãŸå ´åˆã€å¤–部サービスã‹ã‚‰ãƒ—ロジェクトã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒåˆ†é¡žãƒ©ãƒ™ãƒ«ã‚’使用ã—ã¦åˆ¶å¾¡ã•ã‚Œã¾ã™ã€‚"
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13194,9 +13677,6 @@ 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 ""
@@ -13218,12 +13698,12 @@ msgstr "無視ã™ã‚‹"
msgid "Ignored"
msgstr ""
-msgid "Image Details"
-msgstr ""
-
msgid "Image URL"
msgstr "ç”»åƒã®URL"
+msgid "Image details"
+msgstr ""
+
msgid "ImageDiffViewer|2-up"
msgstr "2-up"
@@ -13301,6 +13781,9 @@ msgstr "manifest ファイルã®ã‚¢ãƒƒãƒ—ロードã«ã‚ˆã‚‹è¤‡æ•°ãƒªãƒã‚¸ãƒˆãƒª
msgid "Import project"
msgstr "プロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr "プロジェクトメンãƒãƒ¼ã‚’インãƒãƒ¼ãƒˆ"
@@ -13421,6 +13904,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr "インシデント管ç†åˆ¶é™"
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13481,6 +13970,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13490,12 +13982,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13505,6 +14003,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr "インシデント"
@@ -13517,6 +14039,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒåŒæ„ã—ãªã‘ã‚Œã°ãªã‚‰ãªã„利用è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼ã‚’å«ã‚ã¾ã™ã€‚"
@@ -13592,27 +14117,33 @@ msgstr "ホストキーã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«å…¥åŠ›"
msgid "Input your repository URL"
msgstr "リãƒã‚¸ãƒˆãƒªã® URL を入力ã—ã¦ãã ã•ã„"
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr "コードブロックを挿入"
msgid "Insert a quote"
msgstr "引用を挿入"
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr "コードを挿入"
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr "候補を挿入ã™ã‚‹"
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr "洞察"
@@ -13631,6 +14162,9 @@ msgstr "GitLab Runner ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«"
msgid "Install Runner on Kubernetes"
msgstr "Kubernetes 㫠Runner をインストール"
+msgid "Install a Runner"
+msgstr ""
+
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr "アプリケーションリãƒã‚¸ãƒˆãƒªã‹ã‚‰ %{free_otp_link} ã‚„Google èªè¨¼ãªã©ã®ã‚½ãƒ•ãƒˆèªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³ã‚’インストールã—ã€ãれを使ã£ã¦ã“ã®QRコードをスキャンã—ã¾ã™ã€‚より詳ã—ã„情報㯠%{help_link_start} 文書 %{help_link_end} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
@@ -13659,6 +14193,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr "インスタンス管ç†è€…グループã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™"
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13668,12 +14247,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13707,6 +14304,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13722,38 +14322,59 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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 group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
-msgstr "内部 - プロジェクトã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„ã‚‹ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚"
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "Internal URL (optional)"
msgstr "内部URL(オプション)"
@@ -13761,6 +14382,9 @@ msgstr "内部URL(オプション)"
msgid "Internal users"
msgstr "内部ユーザー"
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "é–“éš”ã®ãƒ‘ターン"
@@ -13785,9 +14409,6 @@ msgstr ""
msgid "Invalid URL"
msgstr "無効㪠URL"
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -13887,25 +14508,25 @@ msgstr "メンãƒãƒ¼ã‚’招待ã™ã‚‹"
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -13953,6 +14574,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -13996,11 +14671,14 @@ msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}
msgstr "課題 %{issue_reference} をエピック %{epic_reference} ã«è¿½åŠ ã—ã¾ã—ãŸã€‚"
msgid "Issue Analytics"
-msgstr ""
+msgstr "課題分æž"
msgid "Issue Boards"
msgstr "課題ボード"
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14041,28 +14719,28 @@ msgid "IssueAnalytics|Age"
msgstr ""
msgid "IssueAnalytics|Assignees"
-msgstr ""
+msgstr "担当者"
msgid "IssueAnalytics|Due date"
-msgstr ""
+msgstr "期日"
msgid "IssueAnalytics|Failed to load issues. Please try again."
-msgstr ""
+msgstr "課題ã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "IssueAnalytics|Issue"
msgstr ""
msgid "IssueAnalytics|Milestone"
-msgstr ""
+msgstr "マイルストーン"
msgid "IssueAnalytics|Opened by"
msgstr ""
msgid "IssueAnalytics|Status"
-msgstr ""
+msgstr "ステータス"
msgid "IssueAnalytics|Weight"
-msgstr ""
+msgstr "ウェイト"
msgid "IssueBoards|Board"
msgstr "ボード"
@@ -14104,7 +14782,7 @@ msgid "Issues"
msgstr "課題"
msgid "Issues Rate Limits"
-msgstr ""
+msgstr " 課題レート制é™"
msgid "Issues and Merge Requests"
msgstr ""
@@ -14217,6 +14895,9 @@ msgstr "1月"
msgid "January"
msgstr "1月"
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14472,6 +15153,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14490,6 +15174,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14619,9 +15309,6 @@ 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 "%{count} 以上"
-
msgid "Language"
msgstr "言語"
@@ -14647,9 +15334,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr "最終アクセス"
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr "姓ãŒé•·ã™ãŽã¾ã™(最大 %{max_length} 文字)。"
-
msgid "Last Pipeline"
msgstr "最新パイプライン"
@@ -14683,6 +15367,9 @@ msgstr ""
msgid "Last name"
msgstr "姓"
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr "最後ã®è¿”ä¿¡"
@@ -14716,6 +15403,9 @@ msgstr "最終更新"
msgid "Last used"
msgstr "å‰å›žä½¿ç”¨"
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr "最終使用日: "
@@ -14761,6 +15451,9 @@ msgstr ""
msgid "Learn more"
msgstr "詳細"
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr "Auto DevOps ã®è©³ç´°"
@@ -14836,6 +15529,9 @@ msgstr "\"ファイルタイプ\"ã¨\"デリãƒãƒªãƒ¼æ–¹æ³•\"オプションをã
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "Let's Encryptã¯example.comã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’å—ã‘付ã‘ã¾ã›ã‚“"
@@ -14999,7 +15695,7 @@ msgid "Licenses|Detected in Project"
msgstr ""
msgid "Licenses|Detected licenses that are out-of-compliance with the project's assigned policies"
-msgstr ""
+msgstr "プロジェクトã«å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸãƒãƒªã‚·ãƒ¼ã«æº–æ‹ ã—ã¦ã„ãªã„〠検出ã•ã‚ŒãŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹"
msgid "Licenses|Disallow Merge request if detected and will instruct the developer to remove"
msgstr ""
@@ -15026,7 +15722,7 @@ msgid "Licenses|Policy"
msgstr ""
msgid "Licenses|Policy violation: denied"
-msgstr ""
+msgstr "ãƒãƒªã‚·ãƒ¼é•å:æ‹’å¦"
msgid "Licenses|Specified policies in this project"
msgstr ""
@@ -15081,7 +15777,7 @@ msgid "Link title"
msgstr ""
msgid "Link title is required"
-msgstr ""
+msgstr " リンクタイトルã¯å¿…須入力項目ã§ã™"
msgid "Link to go to GitLab pipeline documentation"
msgstr ""
@@ -15368,9 +16064,6 @@ msgstr "3月"
msgid "March"
msgstr "3月"
-msgid "Mark To Do as done"
-msgstr "Todo を完了ã«ã™ã‚‹"
-
msgid "Mark as done"
msgstr "完了ã«ã™ã‚‹"
@@ -15389,6 +16082,9 @@ msgstr "ã“ã®èª²é¡Œã‚’別ã®èª²é¡Œã¨é‡è¤‡ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹"
msgid "Mark this issue as related to another issue"
msgstr "ã“ã®èª²é¡Œã‚’別ã®èª²é¡Œã«é–¢é€£ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹"
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr "Markdown"
@@ -15422,9 +16118,6 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
-msgid "Marked To Do as done."
-msgstr "Todo を完了ã«ã—ãŸã€‚"
-
msgid "Marked this %{noun} as Work In Progress."
msgstr "ã“ã® %{noun} を作業中ã¨ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸã€‚"
@@ -15434,8 +16127,8 @@ msgstr "ã“ã®èª²é¡Œã¯ %{duplicate_param} ã¨é‡è¤‡ã¨ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã
msgid "Marked this issue as related to %{issue_ref}."
msgstr "ã“ã®èª²é¡Œã‚’ %{issue_ref} ã«é–¢é€£ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸã€‚"
-msgid "Marks To Do as done."
-msgstr "Todo を完了ã«ã™ã‚‹."
+msgid "Marked to do as done."
+msgstr ""
msgid "Marks this %{noun} as Work In Progress."
msgstr "ã“ã® %{noun} を作業中ã¨ãƒžãƒ¼ã‚¯ã—ã¾ã™ã€‚"
@@ -15446,6 +16139,9 @@ msgstr "ã“ã®èª²é¡Œã‚’ %{duplicate_reference} ã¨é‡è¤‡ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯
msgid "Marks this issue as related to %{issue_ref}."
msgstr "ã“ã®èª²é¡Œã‚’ %{issue_ref} ã«é–¢é€£ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹ã€‚"
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15509,6 +16205,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15629,6 +16328,12 @@ msgstr "メンãƒãƒ¼ã®ãƒ­ãƒƒã‚¯"
msgid "Member since %{date}"
msgstr "%{date} ã«ãƒ¡ãƒ³ãƒãƒ¼ç™»éŒ²"
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr "メンãƒãƒ¼"
@@ -15656,15 +16361,90 @@ msgstr "%{strong_start}%{group_name}%{strong_end} ã¸ã‚¢ã‚¯ã‚»ã‚¹ã§ãるメン
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr "メモリ使用é‡"
@@ -15681,7 +16461,7 @@ msgid "Merge Request"
msgstr "マージリクエスト"
msgid "Merge Request Analytics"
-msgstr ""
+msgstr "マージリクエスト分æž"
msgid "Merge Request Approvals"
msgstr "マージリクエスト承èª"
@@ -15783,25 +16563,25 @@ msgid "MergeConflict|origin//their changes"
msgstr "origin //相手ã®å¤‰æ›´"
msgid "MergeRequestAnalytics|Assignees"
-msgstr ""
+msgstr "担当者"
msgid "MergeRequestAnalytics|Date Merged"
-msgstr ""
+msgstr "マージ日"
msgid "MergeRequestAnalytics|Line changes"
-msgstr ""
+msgstr "変更行"
msgid "MergeRequestAnalytics|Merge Request"
-msgstr ""
+msgstr "マージリクエスト"
msgid "MergeRequestAnalytics|Milestone"
-msgstr ""
+msgstr "マイルストーン"
msgid "MergeRequestAnalytics|Pipelines"
-msgstr ""
+msgstr "パイプライン"
msgid "MergeRequestAnalytics|Time to merge"
-msgstr ""
+msgstr "マージã¾ã§ã®æ™‚é–“"
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr "%{selectStart} ã‹ã‚‰ %{selectEnd} ã¾ã§ %{end} ã®è¡Œã¸ã®ã‚³ãƒ¡ãƒ³ãƒˆ"
@@ -15902,6 +16682,9 @@ msgstr "マージã—ãŸãƒ–ランãƒã¯å‰Šé™¤ä¸­ã§ã™ã€‚ã“ã‚Œã¯ãƒ–ランãƒã®
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16168,7 +16951,7 @@ msgid "Metrics|Refresh Prometheus data"
msgstr ""
msgid "Metrics|Refresh dashboard"
-msgstr ""
+msgstr "ダッシュボードをリフレッシュ"
msgid "Metrics|Select a value"
msgstr ""
@@ -16186,13 +16969,13 @@ msgid "Metrics|There was an error creating the dashboard. %{error}"
msgstr "ダッシュボードを作æˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚: %{error}"
msgid "Metrics|There was an error fetching annotations. Please try again."
-msgstr ""
+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 ""
+msgstr " アノテーション情報ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Metrics|There was an error getting dashboard validation warnings information."
msgstr ""
@@ -16303,6 +17086,27 @@ msgstr "ç¾åœ¨ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã§ã¯ マイルストーンリストを利用ã
msgid "Milestone lists show all issues from the selected milestone."
msgstr "マイルストーンリストã«ã¯ã€é¸æŠžã—ãŸãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®ã™ã¹ã¦ã®èª²é¡Œã‚’表示ã—ã¾ã™ã€‚"
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16618,9 +17422,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16678,6 +17488,32 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -16933,6 +17769,9 @@ msgstr "ã—ãªã„"
msgid "New"
msgstr "æ–°ã—ã„"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr "æ–°ã—ã„アプリケーション"
@@ -17396,6 +18235,9 @@ msgstr "管ç†è€…ã§ã¯ãªã„ユーザーã¯ã€èª­ã¿å–り専用アクセスã§
msgid "None"
msgstr "ãªã—"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr "未実装"
@@ -17426,9 +18268,6 @@ msgstr "データä¸è¶³"
msgid "Not found."
msgstr "見ã¤ã‹ã‚Šã¾ã›ã‚“。"
-msgid "Not now"
-msgstr "後ã§"
-
msgid "Not ready yet. Try again later."
msgstr "準備ãŒã¾ã ã§ãã¦ã„ã¾ã›ã‚“。ã‚ã¨ã§ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ãã ã•ã„。"
@@ -17663,6 +18502,9 @@ msgstr "OmniAuth"
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17708,9 +18550,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17720,9 +18559,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17841,21 +18677,15 @@ msgstr ""
msgid "Open issues"
msgstr "課題を開ã"
-msgid "Open projects"
-msgstr "プロジェクトを開ã"
-
msgid "Open raw"
msgstr "ãã®ã¾ã¾é–‹ã"
msgid "Open sidebar"
msgstr "サイドãƒãƒ¼ã‚’é–‹ã"
-msgid "Open: %{openIssuesCount}"
+msgid "Open: %{open}"
msgstr ""
-msgid "Open: %{open} • Closed: %{closed}"
-msgstr "オープン: %{open} •クローズ: %{closed}"
-
msgid "Opened"
msgstr "オープン"
@@ -18027,6 +18857,9 @@ msgstr "Conan リモートã®è¿½åŠ "
msgid "PackageRegistry|Add NuGet Source"
msgstr "NuGet ソースを追加"
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18123,8 +18956,8 @@ 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|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}。以下ã¯ã€ç§ãŸã¡ãŒæ³¨ç›®ã—ã¦ã„るパッケージマãƒãƒ¼ã‚¸ãƒ£ã®ãƒªã‚¹ãƒˆã§ã™ã€‚"
+msgid "PackageRegistry|Install package version"
+msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "GitLabã§%{noPackagesLinkStart}ã‚ãªãŸã®ãƒ‘ッケージを公開ã—共有%{noPackagesLinkEnd}ã™ã‚‹æ–¹æ³•ã‚’å­¦ã¶ã€‚"
@@ -18147,9 +18980,6 @@ msgstr "Maven XML"
msgid "PackageRegistry|NPM"
msgstr "NPM"
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -18171,8 +19001,8 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
-msgstr "PyPi"
+msgid "PackageRegistry|PyPI"
+msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
@@ -18195,9 +19025,6 @@ 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 "ã“ã®ãƒ‘ッケージã®è©³ç´°ã®å–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -18213,9 +19040,6 @@ 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 ""
@@ -18225,12 +19049,6 @@ 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|composer.json registry include"
-msgstr ""
-
-msgid "PackageRegistry|composer.json require package include"
-msgstr ""
-
msgid "PackageRegistry|npm command"
msgstr ""
@@ -18255,7 +19073,7 @@ msgstr "NPM"
msgid "PackageType|NuGet"
msgstr "NuGet"
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18447,7 +19265,7 @@ msgstr "権é™ã®ãªã„ユーザーã¯ä¸€åˆ‡é€šçŸ¥ã‚’å—ã‘ã‚‹ã“ã¨ãŒãªãã€
msgid "People without permission will never get a notification."
msgstr "権é™ã®ãªã„人ã«ã¯é€šçŸ¥ã—ã¾ã›ã‚“。"
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18459,9 +19277,6 @@ msgstr "パスã®å¤‰æ›´ã€è»¢é€ã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã€ã‚°ãƒ«ãƒ¼ãƒ—ã®å‰Šé™¤ãª
msgid "Perform common operations on GitLab project"
msgstr "GitLabプロジェクトã§ä¸€èˆ¬çš„ãªæ“作を実施"
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr "パフォーマンスã®æœ€é©åŒ–"
@@ -18550,7 +19365,7 @@ msgid "Pipeline: %{status}"
msgstr "パイプライン: %{status}"
msgid "PipelineCharts|CI / CD Analytics"
-msgstr ""
+msgstr "CI/CD 分æž"
msgid "PipelineCharts|Failed:"
msgstr "失敗:"
@@ -18564,6 +19379,9 @@ msgstr "æˆåŠŸæ¯”率:"
msgid "PipelineCharts|Successful:"
msgstr "æˆåŠŸ:"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "åˆè¨ˆ:"
@@ -18645,6 +19463,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr "CI Lint"
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr "å­ãƒ‘イプライン"
@@ -18663,6 +19484,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr "パイプラインã®åˆ©ç”¨ã‚’開始ã™ã‚‹"
@@ -18693,6 +19517,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "プロジェクトã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’正常ã«ãƒªã‚»ãƒƒãƒˆã—ã¾ã—ãŸã€‚"
@@ -18729,6 +19556,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -18957,6 +19790,9 @@ msgstr "有効ãªã‚¼ãƒ­ä»¥ä¸Šã®æ•°å­—を入力ã—ã¦ãã ã•ã„"
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr "%{number} より大ãã„数字を入力ã—ã¦ãã ã•ã„。(プロジェクト設定ã®ãŸã‚)"
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr "有効ãªæ•°å€¤ã‚’入力ã—ã¦ãã ã•ã„"
@@ -18966,11 +19802,14 @@ 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."
+msgid "Please fill out this field."
msgstr ""
+msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
+msgstr "%{link_start}Let's Encrypt ã®ãƒˆãƒ©ãƒ–ルシューティング手順%{link_end} ã«å¾“ã£ã¦ã€Let's Encrypt ã®è¨¼æ˜Žæ›¸ã‚’å†å–å¾—ã—ã¦ãã ã•ã„。"
+
msgid "Please follow the Let's Encrypt troubleshooting instructions to re-obtain your Let's Encrypt certificate: %{docs_url}."
-msgstr ""
+msgstr "Let's Encrypt ã®ãƒˆãƒ©ãƒ–ルシューティング手順ã«å¾“ã£ã¦ã€Let's Encrypt ã®è¨¼æ˜Žæ›¸ã‚’å†å–å¾—ã—ã¦ãã ã•ã„。: %{docs_url}"
msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
msgstr "ã™ã¹ã¦ã®æ—¢å­˜ã®ãƒ—ロジェクトをãƒãƒƒã‚·ãƒ¥åŒ–ã—ãŸã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã«ç§»è¡Œã—ã¦ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ä¸Šã®å•é¡Œã‚’回é¿ã—ã¦ã€ãƒ‡ãƒ¼ã‚¿æ•´åˆæ€§ã®ç¢ºä¿ã—ã¦ãã ã•ã„。%{migrate_link}"
@@ -18978,12 +19817,18 @@ msgstr "ã™ã¹ã¦ã®æ—¢å­˜ã®ãƒ—ロジェクトをãƒãƒƒã‚·ãƒ¥åŒ–ã—ãŸã‚¹ãƒˆãƒ¬
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "ã“ã®ã‚¢ãƒ—リケーション㯠GitLab ãŒæä¾›ã—ã¦ã„ã¾ã›ã‚“。ãã®ãŸã‚ã‚ãªãŸãŒã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã™ã‚‹å‰ã«ãã®èªè¨¼ã‚’確èªã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr "åå‰ã‚’入力ã—ã¦ãã ã•ã„"
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr "有効ãªãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’入力ã—ã¦ãã ã•ã„"
@@ -19063,7 +19908,7 @@ 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 ""
+msgstr "ドキュメントã€ãƒ“ルドã—ãŸãƒã‚¤ãƒŠãƒªã€ãã®ä»–ã®é–¢é€£è³‡æ–™ç­‰ã€å¥½ããªãƒªãƒ³ã‚¯ã‚’指定ã—ã¦ãã ã•ã„。ã“れらã¯ã€GitLab インスタンスã®å†…部リンクã¾ãŸã¯å¤–部ã¸ã®ãƒªãƒ³ã‚¯ã§ã™ã€‚ãŸã ã— URL ã®é‡è¤‡ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "Pre-defined push rules."
msgstr ""
@@ -19188,9 +20033,6 @@ 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 "ユーザーãŒãƒ¡ãƒ³ãƒ†ãƒŠãƒ³ã‚¹ã®é–“ã« GitLab ã§æ›¸ãè¾¼ã¿æ“作をã§ããªã„よã†ã«ã—ã¾ã™ã€‚"
@@ -19258,7 +20100,7 @@ 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 ""
@@ -19300,16 +20142,16 @@ msgid "ProductivityAnalytics|Merge Requests"
msgstr "マージリクエスト"
msgid "ProductivityAnalytics|Merge date"
-msgstr "マージ日付"
+msgstr "マージ日"
msgid "ProductivityAnalytics|Merge requests"
msgstr "マージリクエスト"
msgid "ProductivityAnalytics|Time to merge"
-msgstr ""
+msgstr "マージã™ã‚‹æ™‚é–“"
msgid "ProductivityAnalytics|Trendline"
-msgstr ""
+msgstr "トレンドライン"
msgid "ProductivityAnalytics|is earlier than the given merged at after date"
msgstr ""
@@ -19884,7 +20726,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20187,6 +21029,9 @@ msgstr ".Net Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20241,6 +21086,9 @@ msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
msgstr "SalesforceDX"
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr "Serverless Framework / JS"
@@ -20697,6 +21545,9 @@ msgstr "ブランãƒ"
msgid "ProtectedBranch|Code owner approval"
msgstr "コードオーナーã®æ‰¿èª"
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr "ä¿è­·"
@@ -20823,6 +21674,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr "プッシュ"
@@ -20934,6 +21788,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr "1分ã‚ãŸã‚Šã®ç”Ÿblobリクエストレート制é™"
@@ -21015,6 +21872,9 @@ msgstr ""
msgid "Refresh"
msgstr "æ›´æ–°"
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "æ›´æ–°ã•ã‚ŒãŸã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’表示ã™ã‚‹ãŸã‚ã«ã€ %d 秒間リフレッシュã—ã¦ã„ã¾ã™..."
@@ -21058,9 +21918,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr "GitLab ã«ç™»éŒ²ã™ã‚‹"
-
msgid "Register now"
msgstr "今ã™ã登録"
@@ -21113,7 +21970,7 @@ msgid "Related merge requests"
msgstr "関連ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "Relates to"
-msgstr ""
+msgstr "以下ã«é–¢ä¿‚ã—ã¦ã„ã‚‹"
msgid "Release"
msgid_plural "Releases"
@@ -21269,6 +22126,9 @@ msgstr ""
msgid "Remove limit"
msgstr "制é™ã®è§£é™¤"
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21389,6 +22249,9 @@ msgstr "期日を削除."
msgid "Removes time estimate."
msgstr "見ç©æ™‚間を削除."
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21410,9 +22273,15 @@ msgstr ""
msgid "Reopen epic"
msgstr "エピックã®å†é–‹"
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr "マイルストーンをå†é–‹"
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr "ã“ã® %{quick_action_target} ã‚’å†ã³é–‹ã"
@@ -21440,6 +22309,9 @@ msgstr "クローンURLã®ãƒ«ãƒ¼ãƒˆã‚’ç½®ãæ›ãˆã‚‹ã€‚"
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21564,7 +22436,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21576,6 +22454,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21594,6 +22484,9 @@ msgstr "リãƒã‚¸ãƒˆãƒªã®ã‚°ãƒ©ãƒ•"
msgid "Repository Settings"
msgstr "リãƒã‚¸ãƒˆãƒªã®è¨­å®š"
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21690,8 +22583,8 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
-msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—内ã®ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«2è¦ç´ èªè¨¼ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã‚’è¦æ±‚ã™ã‚‹"
+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 "GitLab ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹éš›ã«ã€ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒåˆ©ç”¨è¦ç´„ã«åŒæ„ã™ã‚‹ã“ã¨ã‚’è¦æ±‚ã—ã¾ã™ã€‚"
@@ -21723,6 +22616,9 @@ msgstr "è¦ä»¶ã® %{reference} ãŒå†ã‚ªãƒ¼ãƒ—ンã•ã‚Œã¾ã—ãŸ"
msgid "Requirement %{reference} has been updated"
msgstr "è¦ä»¶ã® %{reference} ãŒæ›´æ–°ã•ã‚Œã¾ã—ãŸ"
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -21921,6 +22817,9 @@ msgstr "アプリを表示"
msgid "Review App|View latest app"
msgstr "最新ã®ã‚¢ãƒ—リを表示"
+msgid "Review requested from %{name}"
+msgstr ""
+
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
msgstr "ã‚ãªãŸã® ID プロãƒã‚¤ãƒ€ãƒ¼ã®ã‚µãƒ¼ãƒ“スプロãƒã‚¤ãƒ€ãƒ¼ã‚’構æˆã™ã‚‹ãŸã‚ã®ãƒ—ロセスを確èªã—ã¾ã™ã€‚ ã“ã®ä¾‹ã§ã¯ã€GitLab ã¯ã€Œã‚µãƒ¼ãƒ“スプロãƒã‚¤ãƒ€ãƒ¼ã€ã¾ãŸã¯ã€Œè¨¼æ˜Žæ›¸åˆ©ç”¨è€…ã€ã€‚"
@@ -21928,7 +22827,7 @@ msgid "Review time"
msgstr "レビュー時間"
msgid "Review time is defined as the time it takes from first comment until merged."
-msgstr ""
+msgstr "レビュー時間ã¯æœ€åˆã®ã‚³ãƒ¡ãƒ³ãƒˆã‹ã‚‰ãƒžãƒ¼ã‚¸ã•ã‚Œã‚‹ã¾ã§ã®æ™‚間を表ã—ã¾ã™ã€‚"
msgid "ReviewApp|Enable Review App"
msgstr ""
@@ -22072,6 +22971,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22099,6 +23004,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22168,6 +23076,9 @@ 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 ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr "SSH éµã‚’使用ã™ã‚‹ã¨ã€ã‚³ãƒ³ãƒ”ュータã¨GitLabã®é–“を安全ã«æŽ¥ç¶šã§ãã¾ã™ã€‚"
@@ -22177,6 +23088,12 @@ msgstr "SSH 公開éµ"
msgid "SSL Verification:"
msgstr "SSL ã®æ¤œè¨¼:"
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr "土曜日"
@@ -22192,6 +23109,9 @@ msgstr "変更をä¿å­˜"
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr "強制ä¿å­˜"
@@ -22216,9 +23136,6 @@ 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 variables"
-msgstr "変数をä¿å­˜ã™ã‚‹"
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22228,6 +23145,9 @@ msgstr "ä¿å­˜ä¸­"
msgid "Saving project."
msgstr "プロジェクトをä¿å­˜"
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "æ–°ã—ã„パイプラインã®ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’作æˆ"
@@ -22267,6 +23187,9 @@ msgstr "スコープ"
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22297,7 +23220,7 @@ msgstr "検索"
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22354,9 +23277,6 @@ msgstr "ã“ã®ãƒ†ã‚­ã‚¹ãƒˆã‚’検索"
msgid "Search forks"
msgstr "フォークを検索ã™ã‚‹"
-msgid "Search groups"
-msgstr "グループを検索"
-
msgid "Search merge requests"
msgstr "マージリクエストを検索"
@@ -22438,9 +23358,6 @@ msgstr "%{from} ã‹ã‚‰ %{to} ã¾ã§ã®%{term_element}ã®%{count}%{scope} を表ç
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 "%{term} ã«ä¸€è‡´ã™ã‚‹ %{scope} ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
-
msgid "SearchResults|code result"
msgid_plural "SearchResults|code results"
msgstr[0] "コードçµæžœ"
@@ -22494,7 +23411,7 @@ msgstr "シートリンク"
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22534,67 +23451,67 @@ msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline
msgstr ""
msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "ライセンススキャンを有効ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ %{linkStart}詳細情報%{linkEnd}ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "セキュリティスキャナーを一ã¤ä»¥ä¸Šæœ‰åŠ¹ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ %{linkStart}詳細情報%{linkEnd}ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
-msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
-msgstr ""
+msgstr "マージリクエストã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "SecurityConfiguration|Available for on-demand DAST"
-msgstr ""
+msgstr "オンデマンドDASTã§åˆ©ç”¨å¯èƒ½"
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
msgid "SecurityConfiguration|Configure"
-msgstr ""
+msgstr "設定"
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
-msgstr ""
+msgstr "設定データをå–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ページを更新ã™ã‚‹ã‹ã€ã—ã°ã‚‰ãã—ã¦ã‹ã‚‰ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
msgid "SecurityConfiguration|Create Merge Request"
-msgstr ""
+msgstr "マージリクエストを作æˆ"
msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
-msgstr ""
+msgstr "ã‚ãªãŸã®è¦ä»¶ã«åˆã‚ã›ã¦ä¸€èˆ¬çš„㪠SAST 設定をカスタマイズã—ã¾ã™ã€‚ã“ã“ã§è¡Œã‚ã‚ŒãŸè¨­å®šå¤‰æ›´ã¯ã€GitLab ãŒæä¾›ã™ã‚‹è¨­å®šã‚’上書ãã—ã€æ›´æ–°ã‹ã‚‰é™¤å¤–ã•ã‚Œã¾ã™ã€‚ より高度ãªè¨­å®šã‚ªãƒ—ションã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ %{linkStart}GitLab SAST ドキュメント%{linkEnd} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
msgid "SecurityConfiguration|Enable"
-msgstr ""
+msgstr "有効ã«ã™ã‚‹"
msgid "SecurityConfiguration|Enable via Merge Request"
-msgstr ""
+msgstr "マージリクエストã§æœ‰åŠ¹ã«ã™ã‚‹"
msgid "SecurityConfiguration|Enabled"
-msgstr ""
+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|More information"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
-msgstr ""
+msgstr "有効ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "SecurityConfiguration|SAST Analyzers"
msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
-msgstr ""
+msgstr "SAST 設定"
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -22671,6 +23588,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22734,6 +23654,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22773,6 +23699,10 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -22953,6 +23883,9 @@ msgstr "インãƒãƒ¼ãƒˆå¯¾è±¡ã®ãƒ—ロジェクトをé¸æŠžã—ã¾ã™ã€‚"
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -22968,7 +23901,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -22983,9 +23916,6 @@ msgstr "ã“ã®ãƒ—ロジェクトã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã¨ã—ã¦è¨­å®šã™ã‚‹ãƒ–ラン
msgid "Select the custom project template source group."
msgstr "カスタムã®ãƒ—ロジェクトテンプレートã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠžã—ã¾ã™ã€‚"
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23079,6 +24009,9 @@ msgstr "トピックã¯ã‚³ãƒ³ãƒžã§åŒºåˆ‡ã‚Šã¾ã™ã€‚"
msgid "September"
msgstr "9月"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23167,7 +24100,7 @@ msgid "Serverless|We are continually striving to improve our Serverless function
msgstr ""
msgid "Serverless|Your %{startTag}.gitlab-ci.yml%{endTag} file is not properly configured."
-msgstr ""
+msgstr "%{startTag}.gitlab-ci.yml%{endTag} ファイルãŒé©åˆ‡ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "Serverless|Your repository does not have a corresponding %{startTag}serverless.yml%{endTag} file."
msgstr "リãƒã‚¸ãƒˆãƒªã«ã€å¯¾å¿œã™ã‚‹ %{startTag}serverless.yml%{endTag} ファイルãŒã‚ã‚Šã¾ã›ã‚“。"
@@ -23193,6 +24126,9 @@ msgstr "サービス テンプレート"
msgid "Service URL"
msgstr "サービス URL"
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr "セッション期間 (分)"
@@ -23328,6 +24264,9 @@ msgstr "æ–°ã—ã„パスワードを設定"
msgid "Set up pipeline subscriptions for this project."
msgstr "ã“ã®ãƒ—ロジェクトã®ãƒ‘イプラインサブスクリプションを設定。"
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "プロジェクトを設定ã—ã¦ã€åˆ¥ã®ãƒªãƒã‚¸ãƒˆãƒªã¨ã®é–“ã§å¤‰æ›´ã‚’自動的ã«ãƒ—ッシュ/プルã™ã‚‹ã€‚ブランãƒã€ã‚¿ã‚°ã€ãŠã‚ˆã³ã‚³ãƒŸãƒƒãƒˆã¯è‡ªå‹•çš„ã«åŒæœŸã—ã¾ã™ã€‚"
@@ -23433,6 +24372,15 @@ msgstr "共有 Runner"
msgid "Shared projects"
msgstr "共有プロジェクト"
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr "共有Runnerã®ãƒ˜ãƒ«ãƒ—リンク"
@@ -23451,9 +24399,15 @@ msgstr "シャーロックトランザクション"
msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
msgstr "ã‚ãªãŸã®æºå¸¯é›»è©±ã‚’紛失ã—ãŸã‚Šãƒ¯ãƒ³ã‚¿ã‚¤ãƒ ãƒ‘スワードを紛失ã—ãŸå ´åˆã€ã“れらã®ãƒªã‚«ãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’ãã‚Œãžã‚Œï¼‘回ãšã¤ä½¿ç”¨ã—ã¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’回復ã§ãã¾ã™ã€‚安全ãªå ´æ‰€ã«ä¿å­˜ã—ã¦ãã ã•ã„。ãã†ã—ãªã„ã¨ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¸ã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©ã‚’%{b_start} 失ã„ã¾ã™ã€‚%{b_end}"
+msgid "Show Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr "ã™ã¹ã¦ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティを表示"
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr "å…¨ã¦ã®ãƒ¡ãƒ³ãƒãƒ¼ã‚’表示"
@@ -23594,6 +24548,9 @@ msgstr "サインイン / 登録"
msgid "Sign in to \"%{group_name}\""
msgstr "\"%{group_name}\" ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ã¾ã™"
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr "スマートカードを使ã£ã¦ã‚µã‚¤ãƒ³ã‚¤ãƒ³"
@@ -23621,6 +24578,9 @@ msgstr "登録ã¯æˆåŠŸã—ã¾ã—ãŸï¼ メールアドレスを確èªã—ã¦ã‚µã‚
msgid "Sign-in restrictions"
msgstr "サインインã®åˆ¶é™"
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr "サインアップã®åˆ¶é™"
@@ -23630,9 +24590,6 @@ msgstr "åãŒé•·ã™ãŽã¾ã™ï¼ˆæœ€å¤§ %{max_length} 文字)。"
msgid "SignUp|Last Name is too long (maximum is %{max_length} characters)."
msgstr "姓ãŒé•·ã™ãŽã¾ã™ï¼ˆæœ€å¤§ %{max_length} 文字)。"
-msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
-msgstr "åå‰ãŒé•·ã™ãŽã¾ã™(最大 %{max_length} 文字)"
-
msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
msgstr "ユーザーåãŒé•·ã™ãŽã¾ã™(最大 %{max_length} 文字)"
@@ -23642,6 +24599,9 @@ msgstr ""
msgid "Signed in"
msgstr "サインイン済ã¿"
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr "%{authentication} èªè¨¼ã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³"
@@ -23753,27 +24713,18 @@ msgstr "表示ã™ã‚‹ã‚¹ãƒ‹ãƒšãƒƒãƒˆã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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ã¨ã—ã¦ã‚³ãƒ¼ãƒ‰ãƒã‚¤ãƒ©ã‚¤ãƒˆã•ã‚Œã¾ã™ã€‚"
-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 "スニペットã®æ©Ÿèƒ½ã‚„使用方法ã«ã¤ã„ã¦èª¬æ˜Žã‚’追加ã§ãã¾ã™ï¼ˆä»»æ„)"
@@ -23790,7 +24741,7 @@ msgid "Some child epics may be hidden due to applied filters"
msgstr ""
msgid "Some common domains are not allowed. %{read_more_link}."
-msgstr ""
+msgstr "ã„ãã¤ã‹ã®ä¸€èˆ¬çš„ãªãƒ‰ãƒ¡ã‚¤ãƒ³ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。 %{read_more_link}."
msgid "Some email servers do not support overriding the email sender name. Enable this option to include the name of the author of the issue, merge request or comment in the email body instead."
msgstr "一部ã®ãƒ¡ãƒ¼ãƒ«ã‚µãƒ¼ãƒãƒ¼ã¯ã€ãƒ¡ãƒ¼ãƒ«é€ä¿¡è€…åã®ä¸Šæ›¸ãをサãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“。ã“ã®ã‚ªãƒ—ションを有効ã«ã™ã‚‹ã¨ã€ä»£ã‚ã‚Šã«ãƒ¡ãƒ¼ãƒ«æœ¬æ–‡ã«èª²é¡Œã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ã¾ãŸã¯ã‚³ãƒ¡ãƒ³ãƒˆã®ä½œæˆè€…ã®åå‰ã‚’å«ã‚ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -23922,7 +24873,7 @@ msgid "Something went wrong while moving issues."
msgstr "課題を移動ã™ã‚‹éš›ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Something went wrong while obtaining the Let's Encrypt certificate."
-msgstr ""
+msgstr "Let's Encrypt ã®è¨¼æ˜Žæ›¸ã‚’å–å¾—ã™ã‚‹éš›ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Something went wrong while performing the action."
msgstr "アクションã«å®Ÿæ–½ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -24008,6 +24959,9 @@ msgstr "アクセスレベル昇順"
msgid "SortOptions|Access level, descending"
msgstr "アクセスレベルé™é †"
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr "作æˆæ—¥é †"
@@ -24116,6 +25070,9 @@ msgstr "最近ã®ã‚µã‚¤ãƒ³ã‚¤ãƒ³é †"
msgid "SortOptions|Recently starred"
msgstr "ãŠæ°—ã«ã„ã‚Šã§æ–°ã—ã„é †"
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr "サイズ"
@@ -24158,9 +25115,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "ソースコード"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24236,9 +25190,6 @@ msgstr "メールアドレスã®æ­£è¦è¡¨ç¾ãƒ‘ターンを指定ã—ã¦ã€ãƒ‡ãƒ•
msgid "Specify the following URL during the Runner setup:"
msgstr "Runner セットアップã®éš›ã«æ¬¡ã® URL を指定ã—ã¦ãã ã•ã„:"
-msgid "Speed up your DevOps%{br_tag}with GitLab"
-msgstr ""
-
msgid "Squash commit message"
msgstr "コミットメッセージをスカッシュ"
@@ -24302,6 +25253,9 @@ msgstr "スター"
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr "Webターミナルã®èµ·å‹•"
@@ -24324,7 +25278,7 @@ msgid "Start and due date"
msgstr "開始日ã¨çµ‚了日"
msgid "Start by choosing a group to start exploring the merge requests in that group. You can then proceed to filter by projects, labels, milestones and authors."
-msgstr ""
+msgstr "グループをé¸æŠžã—ã¦ã€ãã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®èª¿æŸ»ã‚’開始ã—ã¾ã™ã€‚ãã‚Œã‹ã‚‰ãƒ—ロジェクトã€ãƒ©ãƒ™ãƒ«ã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã€ã¨ä½œæˆè€…ã«ã‚ˆã‚‹ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã«é€²ã‚“ã§ãã ã•ã„。"
msgid "Start cleanup"
msgstr "クリーンアップ開始"
@@ -24411,16 +25365,16 @@ msgid "StaticSiteEditor|An error occurred while submitting your changes."
msgstr ""
msgid "StaticSiteEditor|Branch could not be created."
-msgstr ""
+msgstr "ブランãƒã‚’作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "StaticSiteEditor|Copy update"
msgstr ""
msgid "StaticSiteEditor|Could not commit the content changes."
-msgstr ""
+msgstr "コンテンツã®å¤‰æ›´ã‚’コミットã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "StaticSiteEditor|Could not create merge request."
-msgstr ""
+msgstr "マージリクエストを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "StaticSiteEditor|Creating your merge request"
msgstr ""
@@ -24441,7 +25395,7 @@ msgid "StaticSiteEditor|To see your changes live you will need to do the followi
msgstr ""
msgid "StaticSiteEditor|Update %{sourcePath} file"
-msgstr ""
+msgstr "%{sourcePath} ファイルを更新"
msgid "StaticSiteEditor|View documentation"
msgstr ""
@@ -24458,6 +25412,9 @@ msgstr "統計"
msgid "Status"
msgstr "状態"
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr "ステータス:"
@@ -24573,10 +25530,10 @@ msgid "Subkeys"
msgstr "サブキー"
msgid "Submit"
-msgstr ""
+msgstr "é€ä¿¡"
msgid "Submit %{humanized_resource_name}"
-msgstr ""
+msgstr "%{humanized_resource_name} ã‚’é€ä¿¡"
msgid "Submit a review"
msgstr "レビューをé€ä¿¡"
@@ -24587,6 +25544,9 @@ msgstr "スパムã¨ã—ã¦å ±å‘Š"
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr "フィードãƒãƒƒã‚¯ã‚’é€ä¿¡"
@@ -24602,6 +25562,9 @@ msgstr "検索ã®æ出"
msgid "Submit the current review."
msgstr "ç¾åœ¨ã®ãƒ¬ãƒ“ューをé€ä¿¡"
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr "ç¾åœ¨ã®ãƒ¬ãƒ“ューをé€ä¿¡ã—ã¾ã—ãŸ"
@@ -24644,6 +25607,12 @@ msgstr "サブスクリプションã®ä½œæˆã«æˆåŠŸã—ã¾ã—ãŸã€‚"
msgid "Subscription successfully deleted."
msgstr "サブスクリプションã®å‰Šé™¤ã«æˆåŠŸã—ã¾ã—ãŸã€‚"
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr "支払ã„"
@@ -24728,6 +25697,9 @@ msgstr "æˆåŠŸã—ã¾ã—ãŸ"
msgid "Successfully activated"
msgstr "有効化ã«æˆåŠŸã—ã¾ã—ãŸ"
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "正常ã«ãƒ–ロックã•ã‚Œã¾ã—ãŸ"
@@ -24749,6 +25721,9 @@ msgstr "メールを削除ã—ã¾ã—ãŸã€‚"
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr "実行ã™ã‚‹ãƒ‘イプラインをスケジュールã—ã¾ã—ãŸã€‚ 詳ã—ãã¯%{pipelines_link_start}パイプラインページ%{pipelines_link_end}ã‚’ã”覧ãã ã•ã„。"
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr "正常ã«ãƒ–ロックãŒè§£é™¤ã•ã‚Œã¾ã—ãŸ"
@@ -24762,13 +25737,13 @@ msgid "Suggest code changes which can be immediately applied in one click. Try i
msgstr "ã™ãã«é©ç”¨ã•ã‚Œã‚‹ã‚³ãƒ¼ãƒ‰å¤‰æ›´ã‚’1クリックã§æ案ã—ã¦ã¿ã‚ˆã†ï¼"
msgid "Suggested Solutions"
-msgstr ""
+msgstr "推奨ソリューション"
msgid "Suggested change"
msgstr "変更ã®æ案"
msgid "Suggested solutions help link"
-msgstr ""
+msgstr "推奨ソリューションã®ãƒ˜ãƒ«ãƒ—リンク"
msgid "SuggestedColors|Bright green"
msgstr "ブライトグリーン"
@@ -24884,12 +25859,18 @@ msgstr ""
msgid "Sync information"
msgstr "åŒæœŸæƒ…å ±"
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr "åŒæœŸæ¸ˆã¿"
msgid "Synchronization disabled"
msgstr "åŒæœŸã¯ç„¡åŠ¹ã§ã™"
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr "システム"
@@ -24917,6 +25898,9 @@ msgstr "システムメトリクス(カスタム)"
msgid "System metrics (Kubernetes)"
msgstr "システムメトリクス (Kubernetes)"
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr "目次"
@@ -25065,7 +26049,7 @@ msgid "Templates"
msgstr "テンプレート"
msgid "TemporaryStorageIncrease|can only be set once"
-msgstr ""
+msgstr "設定ã§ãã‚‹ã®ã¯1回ã ã‘ã§ã™"
msgid "TemporaryStorageIncrease|can only be set with more than %{percentage}%% usage"
msgstr ""
@@ -25148,15 +26132,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25241,7 +26240,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr "ã‚ã‚ŠãŒã¨ã†ï¼ä»Šå¾Œè¡¨ç¤ºã—ãªã„"
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25263,9 +26262,6 @@ 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 ""
@@ -25278,9 +26274,15 @@ msgstr "課題トラッカーã¯ã€ãƒ—ロジェクトを改善ã—ãŸã‚Šè§£æ±ºã—
msgid "The Prometheus server responded with \"bad request\". Please check your queries are correct and are supported in your Prometheus version. %{documentationLink}"
msgstr "Prometheusサーãƒãƒ¼ã¯ã€Œæ‚ªã„リクエストã€ã¨å¿œç­”ã—ã¾ã—ãŸã€‚クエリãŒæ­£ã—ãã‚ãªãŸã®Prometheusã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。 %{documentationLink}"
+msgid "The Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr "Elasticsearchã¸ã®æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹URL。クラスタリングをサãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€ã‚³ãƒ³ãƒžåŒºåˆ‡ã‚Šãƒªã‚¹ãƒˆã‚’使用ã—ã¾ã™(例: http://localhost:9200, http://localhost:9201)。"
@@ -25377,6 +26379,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "次ã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“。"
@@ -25399,8 +26407,8 @@ msgstr ""
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr "グローãƒãƒ«è¨­å®šã§ã¯ã€è‡ªåˆ†ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«å¯¾ã—ã¦2è¦ç´ èªè¨¼ã‚’有効ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-msgid "The group and any internal projects can be viewed by any logged in user."
-msgstr "グループã¨å†…部プロジェクトã¯ã™ã¹ã¦ã€ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„るユーザーãªã‚‰èª°ã§ã‚‚見るã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
msgstr "グループãŠã‚ˆã³å…¬é–‹ãƒ—ロジェクトã¯èªè¨¼ç„¡ã—ã§é–²è¦§ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -25510,8 +26518,8 @@ msgstr "計画ステージã§ã¯ã€èª²é¡Œã‚¹ãƒ†ãƒ¼ã‚¸ã«ç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒ—
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr "クライアント証明書ãŒæä¾›ã•ã‚Œã‚‹ã¨ãã«ä½¿ç”¨ã™ã‚‹ç§˜å¯†éµã€‚ã“ã®å€¤ã¯æš—å·åŒ–ã—ã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚"
-msgid "The project can be accessed by any logged in user."
-msgstr "プロジェクトã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ã‚ã‚Œã°èª°ã§ã‚‚アクセスã§ãã¾ã™ã€‚"
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr "ã“ã®ãƒ—ロジェクトã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ã‚ã‚Œã°èª°ã§ã‚‚アクセスã§ãã¾ã™ã€‚"
@@ -25570,6 +26578,9 @@ msgstr "レビューステージã¨ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’作æˆã—ã¦
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "ロードマップã«ã¯ã€ã‚¿ã‚¤ãƒ ãƒ©ã‚¤ãƒ³ã«æ²¿ã£ãŸã‚¨ãƒ”ックã®é€²æ—ãŒè¡¨ç¤ºã•ã‚Œã¾ã™"
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr "スケジュールã®æ™‚é–“ã¯ç¾åœ¨ä»¥é™ã®æ—¥æ™‚ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“"
@@ -25582,8 +26593,8 @@ msgstr "スニペットã¯ç§ã ã‘ãŒè¦‹ãˆã¾ã™ã€‚"
msgid "The snippet is visible only to project members."
msgstr "スニペットã¯ãƒ—ロジェクトメンãƒãƒ¼ã ã‘ãŒè¦‹ã‚Œã¾ã™ã€‚"
-msgid "The snippet is visible to any logged in user."
-msgstr "スニペットã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„ã‚‹ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒè¦‹ã‚Œã¾ã™ã€‚"
+msgid "The snippet is visible to any logged in user except external users."
+msgstr ""
msgid "The specified tab is invalid, please select another"
msgstr "指定ã—ãŸã‚¿ãƒ–ã¯ç„¡åŠ¹ã§ã™ã€‚別ã®ã‚¿ãƒ–ã‚’é¸æŠžã—ã¦ãã ã•ã„"
@@ -25621,6 +26632,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "ユーザーマップã¯ã€ã‚ãªãŸã®ãƒ—ロジェクトã«å‚加ã—㟠FogBugz ユーザーã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼åã‚’ GitLab ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹æ™‚ã«ãƒžãƒƒãƒ”ングã—ã¾ã™ã€‚ã“れを変更ã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã®è¡¨ã«å…¥åŠ›ã—ã¾ã™ã€‚"
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr "éžæœ‰åŠ¹åŒ–ã—よã†ã¨ã—ã¦ã„るユーザーã¯éŽåŽ» %{minimum_inactive_days} 日間ã«æ´»å‹•ãŒã‚ã‚Šã€éžæœ‰åŠ¹åŒ–ã§ãã¾ã›ã‚“"
@@ -25729,6 +26743,9 @@ msgstr "ãã®åå‰ã®ãƒªãƒã‚¸ãƒˆãƒªã¯ã™ã§ã«ãƒ‡ã‚£ã‚¹ã‚¯ä¸Šã«ã‚ã‚Šã¾ã™
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr "利用ã§ãるデータã¯ã‚ã‚Šã¾ã›ã‚“。é¸æŠžã—ç›´ã—ã¦ãã ã•ã„。"
@@ -25924,6 +26941,9 @@ msgstr "reCAPTCHA ã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã—ãŸã€‚ reCAPTCHA ã‚’ã‚‚ã†ä¸€åº¦å®Ÿ
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr "既存ã®èª²é¡Œã«åŒæ§˜ã®ã‚¿ã‚¤ãƒˆãƒ«ãŒã‚ã‚Šã¾ã™ã€‚別ã®ä¼¼ãŸã‚ˆã†ãªèª²é¡Œã‚’作æˆã™ã‚‹ã‚ˆã‚Šã€ãã“ã«ã‚³ãƒ¡ãƒ³ãƒˆã™ã‚‹æ–¹ãŒè‰¯ã„ã§ã™ã€‚"
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr "ã“れらã®å¤‰æ•°ã¯ã€è¦ªã‚°ãƒ«ãƒ¼ãƒ—設定ã§æ§‹æˆã•ã‚Œã€ãƒ—ロジェクト変数ã«åŠ ãˆã¦ç¾åœ¨ã®ãƒ—ロジェクトã§ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã«ãªã‚Šã¾ã™ã€‚"
@@ -25952,7 +26972,7 @@ msgid "This %{noteableTypeText} is locked."
msgstr ""
msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
-msgstr ""
+msgstr "%{reason} ã®ãŸã‚ã€ã“ã® %{viewer} ã¯è¡¨ç¤ºã§ãã¾ã›ã‚“ã§ã—ãŸã€‚代ã‚ã‚Šã« %{options} ãŒä½¿ç”¨ã§ãã¾ã™ã€‚"
msgid "This Cron pattern is invalid"
msgstr ""
@@ -25967,7 +26987,7 @@ msgid "This Project is currently archived and read-only. Please unarchive the pr
msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
-msgstr ""
+msgstr "ã“ã® URL ã¯åˆ¥ã®ãƒªãƒ³ã‚¯ã§æ—¢ã«ä½¿ç”¨ã—ã¦ã„ã¾ã™ã€‚é‡è¤‡ã—㟠URL ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“"
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr "ã“ã®å‹•ä½œã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãŒå¤±ã‚れるå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚çªç™ºçš„ãªäº‹æ…‹ã‚’防ããŸã‚ã«ã€ä¸€åº¦æ“作ã®æ„図を確èªã—ã¦ãã ã•ã„。ãŠé¡˜ã„ã—ã¾ã™ã€‚"
@@ -25975,7 +26995,7 @@ msgstr "ã“ã®å‹•ä½œã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãŒå¤±ã‚れるå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -25999,9 +27019,15 @@ msgstr "ã“ã®ã‚¢ãƒ—リケーション㯠%{link_to_owner} ã«ã‚ˆã£ã¦ä½œæˆã•
msgid "This application will be able to:"
msgstr "ã“ã®ã‚¢ãƒ—リケーションã¯æ¬¡ã®ã“ã¨ãŒã§ãã¾ã™:"
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr "ã“ã®ãƒ–ロックã¯è‡ªå·±å‚ç…§ã—ã¦ã„ã¾ã™ã€‚"
@@ -26018,7 +27044,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> ã®ç½²åã§ã‚µã‚¤ãƒ³ã•ã‚Œã¦ãŠã‚Šã€ã“ã®ã‚³ãƒŸãƒƒã‚¿ãƒ¼ã®ãƒ¡ãƒ¼ãƒ«ã¯åŒã˜ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚‚ã®ã§ã‚ã‚‹ã“ã¨ãŒæ¤œè¨¼ã•ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -26027,16 +27053,16 @@ 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> ç½²åã§ã‚µã‚¤ãƒ³ã•ã‚Œã¦ã„ã¾ã™ã€‚"
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
-msgstr ""
+msgstr "ã“ã®å†…容ã¯è¡¨ç¤ºã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ç†ç”±ã¯ %{reason} ã§ã™ã€‚代ã‚ã‚Šã« %{options} ãŒä½¿ç”¨ã§ãã¾ã™ã€‚"
msgid "This credential has expired"
msgstr ""
@@ -26134,6 +27160,9 @@ msgstr "ã“ã‚Œã¯ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ãƒ­ã‚°ã‚¤ãƒ³ã—ãŸãƒ‡ãƒã‚¤ã‚¹ã®
msgid "This is a security log of important events involving your account."
msgstr "ã“ã‚Œã¯ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«é–¢ã‚ã‚‹é‡è¦ãªã‚¤ãƒ™ãƒ³ãƒˆã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã§ã™ã€‚"
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26143,6 +27172,9 @@ msgstr ""
msgid "This is your current session"
msgstr "ã“ã‚Œã¯ã‚ãªãŸã®ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã§ã™"
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr "ã“ã®èª²é¡Œã¯ç¾åœ¨ã€æ¬¡ã®èª²é¡Œã«ã‚ˆã£ã¦ãƒ–ロックã•ã‚Œã¦ã„ã¾ã™ã€‚: %{issues}"
@@ -26695,6 +27727,12 @@ msgstr "ãŸã£ãŸä»Š"
msgid "Timeago|right now"
msgstr "今"
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr "タイムアウト"
@@ -26727,8 +27765,8 @@ msgstr "タイトルãŠã‚ˆã³èª¬æ˜Ž"
msgid "To"
msgstr "To"
-msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
-msgstr "ドメイン㮠%{link_to_help} ã«ã€DNSã®TXTレコードã«ä¸Šè¨˜ã®ã‚­ãƒ¼ã‚’追加ã—ã¦ãã ã•ã„。"
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
+msgstr ""
msgid "To Do"
msgstr "To Do"
@@ -26778,8 +27816,8 @@ msgstr "開始ã™ã‚‹ã«ã¯ã€Gitea Host ã® URL 㨠%{link_to_personal_token} ã‚
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
msgstr "GitLab ã®æ”¹å–„㨠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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
+msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "SVN リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€%{svn_link} ã‚’ã”確èªãã ã•ã„。"
@@ -26854,7 +27892,7 @@ msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CS
msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
-msgstr ""
+msgstr "インスタンスレベルã®åˆ†æžã‚’表示ã™ã‚‹ã«ã¯ã€ç®¡ç†è€…ã« %{docLinkStart} 利用状æ³ã®é€ä¿¡ %{docLinkEnd}をオンã«ã™ã‚‹ã‚ˆã†ä¾é ¼ã—ã¦ãã ã•ã„。"
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr "ロードマップを表示ã™ã‚‹ã«ã¯ã€äºˆå®šé–‹å§‹æ—¥ã‹äºˆå®šçµ‚了日をã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‹å­ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚¨ãƒ”ックã®1ã¤ã«è¿½åŠ ã—ã¦ãã ã•ã„。月表示ã§ã¯ã€å‰æœˆã€å½“月ã€ã‚‚ã—ãã¯5ヶ月先ã®ã‚¨ãƒ”ックã®ã¿ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
@@ -26866,7 +27904,7 @@ msgid "To widen your search, change or remove filters."
msgstr "検索範囲を広ã’ã‚‹ã«ã¯ã€ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’変更ã¾ãŸã¯å‰Šé™¤ã—ã¾ã™ã€‚"
msgid "To-Do"
-msgstr ""
+msgstr "To Do"
msgid "To-Do List"
msgstr "To-Do リスト"
@@ -26907,6 +27945,9 @@ msgstr "絵文字リアクションをトグル"
msgid "Toggle navigation"
msgstr "案内ã®åˆ‡ã‚Šæ›¿ãˆ"
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "サイドãƒãƒ¼ã‚’切り替ãˆ"
@@ -26979,17 +28020,20 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr "ã™ã¹ã¦ã®ã‚³ãƒŸãƒƒãƒˆ/マージã®åˆè¨ˆãƒ†ã‚¹ãƒˆæ™‚é–“"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr "ç·ã‚¦ã‚§ã‚¤ãƒˆ"
msgid "Total: %{total}"
msgstr "åˆè¨ˆ:%{total}"
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
-msgstr "トレース"
+msgid "TotalRefCountIndicator|1000+"
+msgstr ""
msgid "Tracing"
msgstr "トレーシング"
@@ -27165,6 +28209,9 @@ msgstr "デãƒã‚¤ã‚¹ã¨é€šä¿¡ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚(ã¾ã æº–å‚™ã§ãã
msgid "Tuesday"
msgstr "ç«æ›œæ—¥"
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr "無効"
@@ -27181,7 +28228,7 @@ msgid "Turn on usage ping"
msgstr ""
msgid "Turn on usage ping to review instance-level analytics."
-msgstr ""
+msgstr "利用状æ³ã®é€ä¿¡ã‚’有効ã«ã—ã¦ã€ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ãƒ¬ãƒ™ãƒ«ã®åˆ†æžã‚’レビューã—ã¾ã™ã€‚"
msgid "Twitter"
msgstr "Twitter"
@@ -27232,10 +28279,10 @@ msgid "URL"
msgstr "URL"
msgid "URL is required"
-msgstr ""
+msgstr "URLãŒå¿…è¦ã§ã™ã€‚"
msgid "URL must start with %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, or %{codeStart}ftp://%{codeEnd}"
-msgstr ""
+msgstr "URL㯠%{codeStart}http://%{codeEnd}〠%{codeStart}https://%{codeEnd}ã€ã¾ãŸã¯ %{codeStart}ftp://%{codeEnd} ã®ã„ãšã‚Œã‹ã§é–‹å§‹ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™"
msgid "URL of the external Spam Check endpoint"
msgstr ""
@@ -27315,6 +28362,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr "変更をä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr "パイプラインを今ã™ã実行ã™ã‚‹ã‚ˆã†ã«ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã§ãã¾ã›ã‚“"
@@ -27540,6 +28590,9 @@ msgstr ""
msgid "Update now"
msgstr "今ã™ãæ›´æ–°"
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27678,11 +28731,14 @@ msgstr "使用状æ³ã®çµ±è¨ˆ"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr "%{help_link_start}共有 Runner%{help_link_end} ã¯ç„¡åŠ¹ã«ãªã£ã¦ã„ã‚‹ãŸã‚ã€ãƒ‘イプラインã®ä½¿ç”¨ã«åˆ¶é™ã¯ã‚ã‚Šã¾ã›ã‚“"
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "アーティファクト"
-msgid "UsageQuota|Build Artifacts"
-msgstr "ビルドアーティファクト"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
+msgstr ""
msgid "UsageQuota|Buy additional minutes"
msgstr "追加分ã®è³¼å…¥"
@@ -27708,6 +28764,9 @@ msgstr "パイプライン"
msgid "UsageQuota|Purchase more storage"
msgstr "追加ã®ã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã‚’購入"
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr "リãƒã‚¸ãƒˆãƒª"
@@ -27720,9 +28779,36 @@ msgstr "スニペット"
msgid "UsageQuota|Storage"
msgstr "ストレージ"
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "ã“ã®ãƒãƒ¼ãƒ ã‚¹ãƒšãƒ¼ã‚¹ã«ã¯ã€å…±æœ‰ãƒ©ãƒ³ãƒŠãƒ¼ã‚’使用ã™ã‚‹ãƒ—ロジェクトã¯ã‚ã‚Šã¾ã›ã‚“。"
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr "無制é™"
@@ -27744,15 +28830,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr "Wiki"
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27807,10 +28905,7 @@ msgstr "ユーザー %{current_user_username} ㌠アカウント%{username} ã®
msgid "User %{username} was successfully removed."
msgstr "ユーザー %{username} を正常ã«å‰Šé™¤ã—ã¾ã—ãŸã€‚"
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -27930,6 +29025,9 @@ msgstr "æ—¢ã«å ±å‘Šã•ã‚ŒãŸä¸æ­£åˆ©ç”¨"
msgid "UserProfile|Blocked user"
msgstr "ブロックã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr "貢献ã—ãŸãƒ—ロジェクト"
@@ -28026,9 +29124,6 @@ msgstr "ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¯æ—¢ã«ä½¿ã‚ã‚Œã¦ã„ã¾ã™ã€‚"
msgid "Username is available."
msgstr "ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¯ä½¿ç”¨å¯èƒ½ã§ã™ã€‚"
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr "ユーザーåãŒé•·ã™ãŽã¾ã™ï¼(最大 %{max_length} 文字)"
-
msgid "Username or email"
msgstr "ユーザーåã¾ãŸã¯ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹"
@@ -28120,13 +29215,13 @@ msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
msgid "ValueStreamAnalytics|%{days}d"
-msgstr ""
+msgstr "%{days}æ—¥"
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
-msgstr ""
+msgstr "最åˆã®ã‚³ãƒŸãƒƒãƒˆã‹ã‚‰èª²é¡Œã®ã‚¯ãƒ­ãƒ¼ã‚ºã¾ã§ã®æ™‚é–“ã®ä¸­å¤®å€¤ã€‚"
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
-msgstr ""
+msgstr "課題ã®ä½œæˆã‹ã‚‰èª²é¡Œã®ã‚¯ãƒ­ãƒ¼ã‚ºã¾ã§ã®æ™‚é–“ã®ä¸­å¤®å€¤ã€‚"
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -28182,6 +29277,12 @@ msgstr ""
msgid "View Documentation"
msgstr "文書ã®è¡¨ç¤º"
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr "ã™ã¹ã¦ã®èª²é¡Œã‚’表示"
@@ -28487,7 +29588,13 @@ msgstr "クラス"
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28571,6 +29678,15 @@ msgstr "エピックを削除ã™ã‚‹ãƒ‘スを特定ã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "We could not determine the path to remove the issue"
msgstr "課題を削除ã™ã‚‹ãŸã‚ã®ãƒ‘スを特定ã§ãã¾ã›ã‚“ã§ã—ãŸ"
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr "Prometheusサーãƒãƒ¼ã«åˆ°é”ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚サーãƒãƒ¼ãŒå­˜åœ¨ã—ãªã„ã‹ã€è¨­å®šã®è©³ç´°ã‚’æ›´æ–°ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -28653,51 +29769,57 @@ msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr "Webhook ã¯è¨­å®šãƒ¡ãƒ‹ãƒ¥ãƒ¼ã«ç§»å‹•ã—ã¾ã—ãŸã€‚"
msgid "Webhooks|Comments"
-msgstr ""
+msgstr "コメント"
msgid "Webhooks|Confidential Comments"
-msgstr ""
+msgstr "機密コメント"
msgid "Webhooks|Confidential Issues events"
-msgstr ""
+msgstr "機密課題イベント"
msgid "Webhooks|Deployment events"
-msgstr ""
+msgstr "デプロイイベント"
msgid "Webhooks|Enable SSL verification"
+msgstr "SSL証明書検証ã®æœ‰åŠ¹åŒ–"
+
+msgid "Webhooks|Feature Flag events"
msgstr ""
msgid "Webhooks|Issues events"
-msgstr ""
+msgstr "課題イベント"
msgid "Webhooks|Job events"
-msgstr ""
+msgstr "ジョブイベント"
msgid "Webhooks|Merge request events"
-msgstr ""
+msgstr "マージリクエストイベント"
msgid "Webhooks|Pipeline events"
-msgstr ""
+msgstr "パイプラインイベント"
msgid "Webhooks|Push events"
-msgstr ""
+msgstr "プッシュイベント"
msgid "Webhooks|SSL verification"
-msgstr ""
+msgstr "SSL検証"
msgid "Webhooks|Secret Token"
-msgstr ""
+msgstr "秘密トークン"
msgid "Webhooks|Tag push events"
+msgstr "タグプッシュイベント"
+
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL will be triggered by a push to the repository"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28725,10 +29847,10 @@ msgid "Webhooks|This URL will be triggered when the pipeline status changes"
msgstr ""
msgid "Webhooks|Trigger"
-msgstr ""
+msgstr "トリガー"
msgid "Webhooks|URL"
-msgstr ""
+msgstr "URL"
msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
msgstr ""
@@ -28766,15 +29888,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr "課題ボードã¸ã‚ˆã†ã“ã"
-
msgid "What are you searching for?"
msgstr "何を探ã—ã¾ã™ã‹?"
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28787,11 +29909,11 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Runner ãŒãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹å ´åˆã€ä»–ã®ãƒ—ロジェクトã«å‰²ã‚Šå½“ã¦ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“"
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
-msgstr ""
+msgstr "有効ã«ã™ã‚‹ã¨ã€ %{host} ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã‚‹ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’作æˆã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚"
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 ""
@@ -29028,12 +30150,12 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
-msgstr "ワークフローã®ãƒ˜ãƒ«ãƒ—"
-
msgid "Would you like to create a new branch?"
msgstr ""
+msgid "Would you like to try auto-generating a branch name?"
+msgstr ""
+
msgid "Write"
msgstr "入力"
@@ -29107,10 +30229,10 @@ msgid "You are connected to the Prometheus server, but there is currently no dat
msgstr "Prometheusサーãƒãƒ¼ã«æŽ¥ç¶šã§ãã¾ã—ãŸãŒã€ç¾åœ¨è¡¨ç¤ºã§ãるデータã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "%{project_full_name} プロジェクトを削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚削除ã•ã‚ŒãŸãƒ—ロジェクトã¯çµ¶å¯¾ã«å…ƒã«ã¯æˆ»ã›ã¾ã›ã‚“ï¼æœ¬å½“ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "%{group_name} を削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã¯ã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—é…下ã®ã‚µãƒ–グループã¨ãƒ—ロジェクトもã™ã¹ã¦å‰Šé™¤ã•ã‚Œã¾ã™ã€‚一度削除ã•ã‚ŒãŸã‚°ãƒ«ãƒ¼ãƒ—を復元ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr "%{project_full_name} プロジェクトã¨ã®ãƒ•ã‚©ãƒ¼ã‚¯ã®é–¢ä¿‚を削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -29119,9 +30241,12 @@ msgid "You are going to transfer %{project_full_name} to another namespace. Are
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 ""
+msgstr "ã‚ãªãŸã¯å…¬é–‹è¨­å®šã«å¤‰æ›´ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã¯%{strongStart}ã™ã¹ã¦ã®äºº%{strongEnd} ãŒé–²è¦§å¯èƒ½ã«ãªã‚Šã€%{issuableType}ã«å¯¾ã—ã¦ã‚³ãƒ¡ãƒ³ãƒˆã‚’残ã™ã“ã¨ãŒã§ãるよã†ã«ãªã‚‹ã“ã¨ã‚’æ„味ã—ã¾ã™ã€‚"
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr "ã‚ãªãŸã¯æ©Ÿå¯†ã‚’有効ã«ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã¯%{strongStart}å°‘ãªãã¨ã‚‚レãƒãƒ¼ã‚¿ãƒ¼æ¨©é™%{strongEnd}ã‚’æŒã£ã¦ã„ã‚‹ãƒãƒ¼ãƒ ãƒ¡ãƒ³ãƒãƒ¼ã®ã¿ãŒ%{issuableType}を閲覧ã§ãコメントを残ã™ã“ã¨ãŒã§ãるよã†ã«ãªã‚‹ã“ã¨ã‚’æ„味ã—ã¾ã™ã€‚"
+
+msgid "You are not allowed to approve a user"
msgstr ""
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
@@ -29145,6 +30270,9 @@ msgstr "読ã¿å–り専用 GitLab インスタンスをå‚照中ã§ã™ã€‚"
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr "ã‚ãªãŸã¯ %{url} ã®GitLab管ç†è€…ã§ã‚ã‚‹ãŸã‚ã€ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’å—ã‘å–ã£ã¦ã„ã¾ã™ã€‚"
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29157,12 +30285,12 @@ msgstr "代ã‚ã‚Šã«ã€%{linkStart} blob を見る%{linkEnd} ã“ã¨ãŒã§ãã¾ã
msgid "You can also create a project from the command line."
msgstr "コマンドラインã‹ã‚‰ãƒ—ロジェクトを作æˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
-msgid "You can also press &#8984;-Enter"
-msgstr "&#8984; ã¨Enter を押ã™ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
-
msgid "You can also press Ctrl-Enter"
msgstr "Ctrl ã¨Enter を押ã™ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
+msgid "You can also press ⌘-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr "ラベルã«ã‚¹ã‚¿ãƒ¼ã‚’付ã‘ã¦å„ªå…ˆãƒ©ãƒ™ãƒ«ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
@@ -29175,6 +30303,15 @@ msgstr "以下ã®æ‰‹é †ã«ãã£ã¦ã€ã‚ãªãŸã®ã‚³ãƒ³ãƒ”ューター上ã®æ—¢
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29209,13 +30346,13 @@ msgid "You can group test cases using labels. To learn about the future directio
msgstr ""
msgid "You can invite a new member to %{project_name} or invite another group."
-msgstr ""
+msgstr "æ–°ã—ã„メンãƒãƒ¼ã‚’%{project_name} ã«æ‹›å¾…ã™ã‚‹ã‹ã€åˆ¥ã®ã‚°ãƒ«ãƒ¼ãƒ—を招待ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "You can invite a new member to %{project_name}."
-msgstr ""
+msgstr "æ–°ã—ã„メンãƒãƒ¼ã‚’%{project_name} ã«æ‹›å¾…ã§ãã¾ã™ã€‚"
msgid "You can invite another group to %{project_name}."
-msgstr ""
+msgstr "ä»–ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’%{project_name} ã«æ‹›å¾…ã§ãã¾ã™ã€‚"
msgid "You can move around the graph by using the arrow keys."
msgstr "矢å°ã‚­ãƒ¼ã‚’使用ã—ã¦ã‚°ãƒ©ãƒ•ã‚’移動ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -29254,7 +30391,7 @@ msgid "You can only upload one design when dropping onto an existing design."
msgstr "既存ã®ãƒ‡ã‚¶ã‚¤ãƒ³ã«ç ´æ£„ã—ãŸã¨ãã«ã‚¢ãƒƒãƒ—ロードã§ãるデザインã¯1ã¤ã ã‘ã§ã™ã€‚"
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} ã«ã‚³ãƒŸãƒƒãƒˆã—ã¾ã™ã€‚"
@@ -29299,7 +30436,7 @@ msgid "You could not create a new trigger."
msgstr "æ–°ã—ã„トリガーを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
-msgstr ""
+msgstr "ã‚ãªãŸã¯%{strong}%{namespace_name}%{strong_close}ã¸ã®ã‚µãƒ–スクリプションを更新ã—ã¾ã›ã‚“ã§ã—ãŸã€‚ãã®ãŸã‚ã€å½“サブスクリプションã¯ç„¡æ–™ãƒ—ランã«ãƒ€ã‚¦ãƒ³ã‚°ãƒ¬ãƒ¼ãƒ‰ã•ã‚Œã¾ã—ãŸã€‚"
msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
@@ -29376,6 +30513,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr "ã‚ãªãŸã¯ã“ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã‹ã‚‰è„±é€€ã—ã¾ã—ãŸã€‚"
@@ -29388,6 +30528,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr "権é™ãŒã‚ã‚Šã¾ã›ã‚“"
@@ -29412,9 +30561,6 @@ msgstr "ã‚ãªãŸã¯ \"%{membershipable_human_name}\"%{source_type} を残ã—ã¾
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 be logged in to search across all of GitLab"
msgstr ""
@@ -29472,9 +30618,6 @@ msgstr "GitLab プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã‚¢ãƒ¼ã‚«ã‚¤ãƒ–(.gz ã§ç
msgid "You need to upload a Google Takeout archive."
msgstr "Google テイクアウトアーカイブをアップロードã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-msgid "You reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
-msgstr ""
-
msgid "You successfully declined the invitation"
msgstr ""
@@ -29577,19 +30720,22 @@ msgstr "ワンタイムパスワードèªè¨¼ã‚’使用ã—ãŸ2è¦ç´ èªè¨¼ã¯æ—¢ã
msgid "YouTube"
msgstr "YouTube"
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your CSV export has started. It will be emailed to %{email} when complete."
msgstr "CSV エクスãƒãƒ¼ãƒˆã‚’開始ã—ã¾ã—ãŸã€‚完了後ã«ã€%{email} ã«ãƒ¡ãƒ¼ãƒ«ã§é€ä¿¡ã—ã¾ã™ã€‚"
-msgid "Your CSV export of %{issues_count} from project %{project_link} has been added to this email as an attachment."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29611,7 +30757,7 @@ msgid "Your GitLab group"
msgstr "ã‚ãªãŸã® GitLab ã®ã‚°ãƒ«ãƒ¼ãƒ—"
msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
-msgstr ""
+msgstr "Gitlab Goldã®è©¦ç”¨æœŸé–“ã¯30日間続ãã€ãã®å¾Œã¯ç„¡æ–™ã®Gitlabアカウントを継続ã—ã¦ç¶­æŒã§ãã¾ã™ã€‚トライアルを有効ã«ã™ã‚‹ãŸã‚ã«ã¯ã€è¿½åŠ æƒ…報をæä¾›ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
msgid "Your Groups"
msgstr "所属グループ"
@@ -29619,6 +30765,9 @@ msgstr "所属グループ"
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr "パーソナルアクセストークン㯠%{days_to_expire} æ—¥ã§æœŸé™ãŒåˆ‡ã‚Œã¾ã™"
@@ -29634,6 +30783,9 @@ msgstr "プロジェクトã®æ´»å‹•"
msgid "Your Public Email will be displayed on your public profile."
msgstr "公開メールをã‚ãªãŸã®å…¬é–‹ãƒ—ロフィールã«è¡¨ç¤ºã—ã¾ã™ã€‚"
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr "SSH éµ (%{count})"
@@ -29899,9 +31051,6 @@ msgstr "ブランãƒå"
msgid "by"
msgstr "by"
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30028,9 +31177,6 @@ msgstr "コンテナスキャンã¯ã€Docker イメージã«å­˜åœ¨ã™ã‚‹æ—¢çŸ¥ã
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30076,9 +31222,6 @@ 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 ""
@@ -30161,6 +31304,9 @@ msgstr "レãƒãƒ¼ãƒˆå…¨ä½“を見る"
msgid "closed issue"
msgstr "クローズã—ãŸèª²é¡Œ"
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr "コメント"
@@ -30394,8 +31540,8 @@ msgstr "無効ãªIPアドレスã®ç¯„囲"
msgid "is blocked by"
msgstr "ã«ã‚ˆã£ã¦ãƒ–ロックã•ã‚Œã¦ã„ã¾ã™"
-msgid "is enabled."
-msgstr "有効ã«ãªã‚Šã¾ã—ãŸ"
+msgid "is forbidden by a top-level group"
+msgstr ""
msgid "is invalid because there is downstream lock"
msgstr "ã¯ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã‚¹ãƒˆãƒªãƒ¼ãƒ ãŒãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹ãŸã‚無効ã§ã™"
@@ -30412,6 +31558,9 @@ msgstr "ã¯ãƒ†ãƒ³ãƒ—レートを利用ã§ãるグループã«æ‰€å±žã—ã¦ã„ã¾
msgid "is not a valid X509 certificate."
msgstr "ã¯æœ‰åŠ¹ãª X509 証明書ã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr "ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。別ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã‚‚ã†ä¸€åº¦è©¦ã™ã‹ã€GitLab管ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
@@ -30430,6 +31579,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr "é•·ã™ãŽã¾ã™(%{current_value})。最大サイズ㯠%{max_size} ã§ã™ã€‚"
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr "ãŒé•·ã™ãŽã¾ã™ (最大100エントリ)"
@@ -30466,6 +31618,9 @@ msgstr "大ãã™ãŽã§ã™"
msgid "jigsaw is not defined"
msgstr "jigsaw ãŒæœªå®šç¾©ã§ã™"
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30527,6 +31682,9 @@ msgstr "metric_id ã¯ãƒ—ロジェクト全体ã§ä¸€æ„ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã
msgid "missing"
msgstr "見ã¤ã‹ã‚Šã¾ã›ã‚“"
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr "最新ã®ãƒ‡ãƒ—ロイ"
@@ -30996,9 +32154,6 @@ 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 "リãƒã‚¸ãƒˆãƒªã¸ã®ãƒ—ッシュã€ãƒ‘イプラインã®ä½œæˆã€èª²é¡Œã®ä½œæˆã€ã‚³ãƒ¡ãƒ³ãƒˆã®è¿½åŠ ã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚ストレージ容é‡ã‚’減らã™ã«ã¯ã€ä½¿ç”¨ã—ã¦ã„ãªã„リãƒã‚¸ãƒˆãƒªã€ã‚¢ãƒ¼ãƒ†ã‚£ãƒ•ã‚¡ã‚¯ãƒˆã€Wikiã€èª²é¡Œã€ãƒ‘イプラインを削除ã—ã¾ã™ã€‚"
-
msgid "quick actions"
msgstr "クイックアクション"
@@ -31011,9 +32166,6 @@ msgstr "登録"
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr "%{time} ã«ãƒªãƒªãƒ¼ã‚¹"
-
msgid "remaining"
msgstr "残り"
@@ -31090,6 +32242,9 @@ msgstr "表示を減らã™"
msgid "sign in"
msgstr "サインイン"
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr "並ã¹æ›¿ãˆ:"
@@ -31270,9 +32425,6 @@ msgstr ""
msgid "wiki page"
msgstr "wiki ページ"
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "%{additions} 件ã®è¿½åŠ ã¨ %{deletions} 件ã®å‰Šé™¤ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -31285,3 +32437,6 @@ msgstr ""
msgid "yaml invalid"
msgstr "yaml ãŒç„¡åŠ¹ã§ã™"
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index 1fd442a5ce1..41dbf79a8a2 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-10-02 18:46\n"
+"PO-Revision-Date: 2020-11-03 22:45\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/kab/gitlab.po b/locale/kab/gitlab.po
index 1d417bb3609..d1df1839e05 100644
--- a/locale/kab/gitlab.po
+++ b/locale/kab/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: kab\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2020-10-02 18:51\n"
+"PO-Revision-Date: 2020-11-03 22:51\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 8bc6ac54040..b1cacbd50b6 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-10-02 18:48\n"
+"PO-Revision-Date: 2020-11-03 22:48\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -162,6 +162,10 @@ msgid "%d failed"
msgid_plural "%d failed"
msgstr[0] "%dê°œì˜ ì‹¤íŒ¨"
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%dê±´ì˜ í…ŒìŠ¤íŠ¸ 결과를 고쳤습니다."
@@ -186,10 +190,6 @@ msgid "%d issue in this group"
msgid_plural "%d issues in this group"
msgstr[0] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d ì´ìŠˆê°€ ì„ íƒë˜ì—ˆìŠµë‹ˆë‹¤."
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -351,6 +351,14 @@ msgstr "%{name}께서 %{count} ê±´ì˜ ìŠ¹ì¸"
msgid "%{count} files touched"
msgstr "%{count} 파ì¼ì´ 변경ë˜ì—ˆìŠµë‹ˆë‹¤"
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+
msgid "%{count} more"
msgstr "%{count} ê°œ ë”보기"
@@ -389,6 +397,12 @@ 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 "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -434,6 +448,12 @@ msgstr "%{group_name}ì€ ê·¸ë£¹ 관리 ê³„ì •ì„ ì‚¬ìš© 합니다. %{group_name}
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr "새로운 위치ì—ì„œ %{host}ì— ë¡œê·¸ì¸ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -560,9 +580,6 @@ 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 "%{name} í¬í•¨ë¨ %{resultsString}"
@@ -655,7 +672,7 @@ msgstr[0] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -669,6 +686,9 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
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] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -876,9 +896,6 @@ msgstr "(진행 ìƒí™© 확ì¸)"
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr "(외부 소스)"
-
msgid "(line: %{startLine})"
msgstr ""
@@ -916,6 +933,18 @@ msgstr[0] "+%d개"
msgid "+%{approvers} more approvers"
msgstr "+%{approvers}ëª…ì˜ ì¶”ê°€ 승ì¸ìž"
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr "+%{tags}개"
@@ -942,6 +971,9 @@ msgstr ""
msgid "- show less"
msgstr "-ëœ ë³´ê¸°"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -951,13 +983,8 @@ msgstr "ë¬´ì œí•œì˜ ê²½ìš° 0"
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "%{count} %{type} ê°œì˜ ì¶”ê°€ ì •ë³´"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "%{count} ê°œ %{type} ì˜ ìˆ˜ì •ì‚¬í•­"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1205,6 +1232,9 @@ msgstr "소스 ë¸Œëžœì¹˜ì— ëŒ€í•œ 쓰기 ê¶Œí•œì´ ìžˆëŠ” 사용ìžê°€ ì´ ì˜µì
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1503,6 +1533,9 @@ msgstr "í…Œì´ë¸” 추가"
msgid "Add a task list"
msgstr "ìž‘ì—… ëª©ë¡ ì¶”ê°€"
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "모든 ì´ë©”ì¼ì— í‘œì‹œë  í…스트를 추가합니다. %{character_limit} ìž ì œí•œì´ ìžˆìŠµë‹ˆë‹¤."
@@ -1656,8 +1689,8 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
-msgstr "í• ì¼ì— 추가ë¨."
+msgid "Added a to do."
+msgstr ""
msgid "Added an issue to an epic."
msgstr ""
@@ -1692,12 +1725,12 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
-msgstr "í•  ì¼ ì¶”ê°€."
-
msgid "Adds a Zoom meeting"
msgstr "줌 미팅 추가"
+msgid "Adds a to do."
+msgstr ""
+
msgid "Adds an issue to an epic."
msgstr ""
@@ -1782,6 +1815,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1806,6 +1842,9 @@ msgstr "ìž‘ì—… ì¤‘ì§€ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤."
msgid "AdminArea|Total users"
msgstr "ì´ ì‚¬ìš©ìž"
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "ì‚¬ìš©ìž í†µê³„"
@@ -1920,6 +1959,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr "2FA 사용 중지"
@@ -1929,6 +1983,12 @@ msgstr "2FA 사용"
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr "활성"
@@ -1941,12 +2001,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr "관리ìžë“¤"
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "ì‚¬ìš©ìž ì°¨ë‹¨"
@@ -2001,6 +2079,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr "ì´ê²ƒì€ 나!"
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr "새로운 유저"
@@ -2010,6 +2091,9 @@ msgstr "유저를 ì°¾ì„ ìˆ˜ ì—†ìŒ"
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2055,6 +2139,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "확ì¸ì„ 위해 %{projectName} 를 입력해주세요."
@@ -2079,6 +2166,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2088,6 +2178,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr "고급"
@@ -2103,22 +2196,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2182,10 +2275,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2302,6 +2395,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2311,10 +2413,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2326,19 +2428,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2353,6 +2464,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2362,7 +2479,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2380,7 +2500,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2389,6 +2509,27 @@ msgstr "알림"
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr "알고리즘"
@@ -2455,9 +2596,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr "모든 사용ìž"
-
msgid "All users must have a name."
msgstr "모든 사용ìžëŠ” ì´ë¦„ì´ ìžˆì–´ì•¼í•©ë‹ˆë‹¤."
@@ -2482,6 +2620,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "ì´ ê·¸ë£¹ì˜ í”„ë¡œì íŠ¸ë“¤ì´ Git LFS를 사용하ë„ë¡ í—ˆìš©"
@@ -2503,6 +2644,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2524,12 +2668,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr "í—ˆìš©ëœ Geo IP"
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr "실패 허용ë¨"
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 추가하고 관리 í•  수 ​​있습니다."
@@ -2578,6 +2728,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2590,9 +2743,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "비어 있는 GitLab User 필드는 FogBugzì˜ ì‚¬ìš©ìž ì „ì²´ ì´ë¦„ (예 : By í™ ê¸¸ë™)ì„ ì´ìŠˆ ë° ì»¤ë§¨íŠ¸ì˜ ì„¤ëª…ìœ¼ë¡œ 추가 합니다. ë˜í•œ ì´ ì´ìŠˆì™€ 커맨트를 프로ì íŠ¸ 작성ìžì— 알리고 할당 í•  것입니다."
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2620,9 +2779,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr "BLOB 미리보기 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "알림 êµ¬ë… ì—¬ë¶€ 변경 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "ì´ìŠˆ ì¤‘ìš”ë„ ì—…ë°ì´íŠ¸ 중 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -2710,9 +2875,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2785,9 +2947,6 @@ 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 ""
@@ -2818,9 +2977,6 @@ 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 "ìš”ì²­ì„ ìƒì„±í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -2845,6 +3001,9 @@ msgstr "방송 메시지 미리보기를 ë Œë”ë§í•˜ëŠ” 중 오류가 ë°œìƒí–ˆ
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2869,9 +3028,6 @@ msgstr "LDAP 무시 ìƒíƒœë¥¼ 저장하는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다
msgid "An error occurred while saving assignees"
msgstr "담당ìžë¥¼ 저장하는 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr "ì•Œë¦¼ì„ êµ¬ë…하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -2887,6 +3043,9 @@ msgstr "알림 구ë…ì„ í•´ì œí•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while updating approvers"
msgstr "승ì¸ìžë¥¼ ì—…ë°ì´íŠ¸í•˜ëŠ” ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤"
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3212,6 +3371,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3459,6 +3621,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr "나ì—게 할당 ë¨"
@@ -3701,8 +3866,29 @@ msgstr "애플리케ì´ì…˜ì˜ 빌드, 테스트, ë°°í¬ê°€ ì‚¬ì „ì— ì •ì˜ëœ C
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "ë” ì•Œì•„ë³´ê¸° %{link_to_documentation}"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "Auto DevOps 파ì´í”„ ë¼ì¸ì´ 활성화ë˜ì—ˆìœ¼ë©° 대체 CI 구성 파ì¼ì´ 없는 ê²½ìš°ì— ì‚¬ìš©ë©ë‹ˆë‹¤. %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr "ìžë™ 완성"
@@ -3722,6 +3908,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 "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3740,6 +3929,9 @@ msgstr "참고"
msgid "Available"
msgstr "ì´ìš© 가능"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3797,9 +3989,6 @@ msgstr "배지 ì´ë¯¸ì§€ URL"
msgid "Badges|Badge image preview"
msgstr "배지 ì´ë¯¸ì§€ 미리 보기"
-msgid "Badges|Delete badge"
-msgstr "배지 삭제"
-
msgid "Badges|Delete badge?"
msgstr "배지를 삭제할까요?"
@@ -3881,6 +4070,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -3965,6 +4160,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "업그레ì´ë“œ"
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr "Bitbucket 서버ì—ì„œ 가져 오기"
@@ -4016,12 +4223,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4040,6 +4256,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4052,6 +4271,9 @@ msgstr "%{branchName} 브랜치는 ì´ í”„ë¡œì íŠ¸ ì €ìž¥ì†Œì— ì—†ìŠµë‹ˆë‹¤."
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4196,6 +4418,9 @@ msgstr "프로ì íŠ¸ 설정"
msgid "Branches|protected"
msgstr "보호ë¨"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4232,9 +4457,21 @@ msgstr "내장ëœ"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4265,7 +4502,7 @@ msgstr "%{user_name} ì˜í•´ì„œ"
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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4448,6 +4685,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4859,6 +5099,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5042,9 +5285,6 @@ msgstr "모든 환경"
msgid "CiVariable|Create wildcard"
msgstr "와ì¼ë“œ ì¹´ë“œ 만들기"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr "변수를 저장하는 ë„중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5063,9 +5303,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr "Toggle 보호ë¨"
-msgid "CiVariable|Validation failed"
-msgstr "유효성 검사 실패"
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5174,6 +5411,9 @@ msgstr ""
msgid "Close epic"
msgstr "ì—픽 닫기"
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr "마ì¼ìŠ¤í†¤ 닫기"
@@ -5198,8 +5438,8 @@ msgstr "닫힌 ì´ìŠˆ"
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
-msgstr "닫힘 : %{closedIssuesCount}"
+msgid "Closed: %{closed}"
+msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
@@ -5225,6 +5465,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5408,6 +5651,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5465,9 +5711,6 @@ 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 ""
@@ -5723,9 +5966,6 @@ msgstr "%{help_link_start_machine_type}머신 유형%{help_link_end} ë° %{help_
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "%{help_link_start}zones%{help_link_end}ì— ëŒ€í•´ ìžì„¸ížˆ 알아보기"
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr "Kubernetesì— ëŒ€í•´ ìžì„¸ížˆ 알아보기."
@@ -5741,9 +5981,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5810,9 +6047,6 @@ msgstr "프로ì íŠ¸ ì—†ìŒ"
msgid "ClusterIntegration|No projects matched your search"
msgstr "검색과 ì¼ì¹˜í•˜ëŠ” 프로ì íŠ¸ê°€ 없습니다."
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5879,9 +6113,6 @@ 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 "Kubernetes í´ëŸ¬ìŠ¤í„° 제거"
@@ -5948,9 +6179,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr "ClusterIntegration|프로ì íŠ¸ 검색"
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6011,6 +6239,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr "ClusterIntegration|지역 ì„ íƒ"
@@ -6095,6 +6326,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6236,9 +6470,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6350,9 +6581,6 @@ 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 ""
@@ -6663,7 +6891,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6714,6 +6942,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr "업그레ì´ë“œ 위해 ì˜ì—…íŒ€ì— ë¬¸ì˜"
@@ -6779,6 +7010,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7155,6 +7389,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7215,6 +7452,9 @@ msgstr "채팅 닉네임 %{chat_name}(ì„)를 삭제할 수 없습니다."
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7224,6 +7464,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7257,6 +7500,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr "êµ­ê°€"
@@ -7504,6 +7750,9 @@ msgstr ""
msgid "Created on"
msgstr "ìƒì„±ì¼"
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr "ìƒì„±ì¼:"
@@ -7597,6 +7846,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr "ì‚¬ìš©ìž ì§€ì • 호스트네임 (ê°œì¸ ì»¤ë°‹ ì´ë©”ì¼ìš©)"
@@ -7847,6 +8099,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -7904,6 +8159,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -7943,6 +8207,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -7964,6 +8234,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -7991,15 +8267,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8015,6 +8291,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8054,6 +8333,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8066,6 +8348,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8075,6 +8363,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr "ë°ì´í„°ê°€ ì•„ì§ ê³„ì‚°ì¤‘ìž…ë‹ˆë‹¤..."
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8231,9 +8522,6 @@ msgstr ""
msgid "Delete Comment"
msgstr "댓글 삭제"
-msgid "Delete Snippet"
-msgstr "스니펫 삭제"
-
msgid "Delete Value Stream"
msgstr ""
@@ -8243,6 +8531,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr "보드 삭제"
@@ -8258,9 +8549,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr "ëª©ë¡ ì‚­ì œ"
-
msgid "Delete pipeline"
msgstr "파ì´í”„ë¼ì¸ ì‚­ì œ"
@@ -8282,6 +8570,9 @@ msgstr ""
msgid "Delete source branch"
msgstr "소스 브랜치 삭제"
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8345,12 +8636,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr "거부"
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8396,18 +8693,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8480,9 +8786,6 @@ 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 ""
@@ -8648,6 +8951,12 @@ msgstr "ë°°í¬ë¨"
msgid "Deployed to"
msgstr "ë°°í¬ë¨"
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr "다ìŒì— ë°°í¬ì¤‘: "
@@ -8696,6 +9005,9 @@ msgstr "설명"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr "설명 í…œí”Œë¦¿ì„ ì‚¬ìš©í•˜ë©´ 프로ì íŠ¸ì˜ ì´ìŠˆ ë° ë³‘í•© 요청 설명 í•„ë“œì— ëŒ€í•œ ìƒí™© 별 í…œí”Œë¦¿ì„ ì •ì˜ í•  수 있습니다."
@@ -8867,6 +9179,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr "diff 컨í…츠 제한"
@@ -8918,8 +9251,8 @@ msgstr "그룹 Runner 사용 중지"
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
-msgstr "공유 러너 사용 중지"
+msgid "Disable shared runners"
+msgstr ""
msgid "Disable two-factor authentication"
msgstr ""
@@ -9066,6 +9399,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr "ì¸ê¸°ìžˆëŠ” ID 제공 ì—…ì²´ì— ëŒ€í•œ 문서"
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9075,6 +9411,9 @@ msgstr "ë„ë©”ì¸"
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9096,6 +9435,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "다시 표시하지 ì•ŠìŒ"
@@ -9123,9 +9465,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr "코드 다운로드"
@@ -9294,15 +9633,24 @@ msgstr "공개 ë°°í¬ í‚¤ 편집"
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr "위키 페ì´ì§€ 편집"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9375,6 +9723,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9516,6 +9867,12 @@ msgstr "ë©”ì¼ ë¨¸ë¦¬ë§ ë° ê¼¬ë¦¬ë§ ì‚¬ìš©"
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9543,8 +9900,20 @@ 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 shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
+msgstr ""
msgid "Enable snowplow tracking"
msgstr ""
@@ -9588,6 +9957,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "(UTC)ì— ì¢…ë£Œë©ë‹ˆë‹¤"
@@ -9615,7 +9987,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10377,12 +10752,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10413,6 +10794,9 @@ msgstr ""
msgid "Expand approvers"
msgstr "승ì¸ìž 확장"
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10488,6 +10872,9 @@ msgstr ""
msgid "Export issues"
msgstr "ì´ìŠˆ 내보내기"
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10590,6 +10977,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10653,6 +11043,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10665,6 +11058,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10801,6 +11197,18 @@ msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10831,6 +11239,9 @@ msgstr "구성"
msgid "FeatureFlags|Configure feature flags"
msgstr "Feature 플래그 구성"
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr "Feature 플래그 ìƒì„±"
@@ -10882,6 +11293,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -10948,10 +11362,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -10966,6 +11383,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -10984,9 +11404,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11002,15 +11419,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11020,6 +11437,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "2ì›”"
@@ -11077,12 +11497,18 @@ msgstr "íŒŒì¼ í…œí”Œë¦¿"
msgid "File upload error."
msgstr "íŒŒì¼ ì—…ë¡œë“œ 오류"
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "파ì¼"
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11107,6 +11533,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11170,6 +11599,9 @@ msgstr "í•„í„°..."
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11203,9 +11635,6 @@ msgstr ""
msgid "Finished"
msgstr "완료"
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11215,9 +11644,15 @@ msgstr "ì£¼ì˜ ì²«ë‚ "
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr "수정 날짜"
@@ -11272,7 +11707,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11818,7 +12253,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11839,6 +12274,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr "파ì´í”„ ë¼ì¸ì— 대한 Git ì „ëžµ"
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr "Git 버전"
@@ -11875,9 +12313,6 @@ 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 ""
@@ -11902,6 +12337,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12214,6 +12655,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12319,7 +12763,7 @@ msgstr "그룹 URL"
msgid "Group avatar"
msgstr "그룹 아바타"
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12478,6 +12922,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12487,6 +12937,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12532,12 +12985,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12550,6 +13021,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12562,6 +13036,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12586,6 +13063,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -12993,6 +13473,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "ì´ë ¥"
@@ -13047,9 +13530,6 @@ 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 "%{terms_link}ì— ë™ì˜í•©ë‹ˆë‹¤."
@@ -13062,7 +13542,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13170,6 +13650,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13194,9 +13677,6 @@ 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 ""
@@ -13218,10 +13698,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13301,6 +13781,9 @@ msgstr "manifest 파ì¼ì„ 업로드하여 ì—¬ëŸ¬ê°œì˜ ì €ìž¥ì†Œë¥¼ 가져오ì„
msgid "Import project"
msgstr "프로ì íŠ¸ 가져오기"
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr "프로ì íŠ¸ 멤버 가져오기"
@@ -13421,6 +13904,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13481,6 +13970,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13490,12 +13982,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13505,6 +14003,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13517,6 +14039,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "모든 사용ìžê°€ 수ë½í•´ì•¼ 하는 서비스 약관 ë° ê°œì¸ ì •ë³´ 보호 ì •ì±…ì„ í¬í•¨í•©ë‹ˆë‹¤."
@@ -13592,27 +14117,33 @@ msgstr "호스트 키를 수ë™ìœ¼ë¡œ ìž…ë ¥"
msgid "Input your repository URL"
msgstr "저장소 URLì„ ìž…ë ¥ 하세요"
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13631,6 +14162,9 @@ msgstr "GitLab Runner 설치"
msgid "Install Runner on Kubernetes"
msgstr "Kubernetesì— Runner 설치"
+msgid "Install a Runner"
+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 ""
@@ -13659,6 +14193,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13668,12 +14247,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13707,6 +14304,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13722,38 +14322,59 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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 group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
-msgstr "내부 - ì´ í”„ë¡œì íŠ¸ëŠ” ë¡œê·¸ì¸ í•œ 사용ìžë§Œ 액세스 í•  수 있습니다."
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "Internal URL (optional)"
msgstr ""
@@ -13761,6 +14382,9 @@ msgstr ""
msgid "Internal users"
msgstr "내부 사용ìž"
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "주기 패턴"
@@ -13785,9 +14409,6 @@ msgstr ""
msgid "Invalid URL"
msgstr "유효하지 ì•Šì€ URL"
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -13887,25 +14508,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -13953,6 +14574,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14001,6 +14676,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "ì´ìŠˆ ë³´ë“œ"
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14217,6 +14895,9 @@ msgstr "1ì›”"
msgid "January"
msgstr "1ì›”"
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14472,6 +15153,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14490,6 +15174,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14619,9 +15309,6 @@ 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 "언어"
@@ -14647,9 +15334,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr "최근 파ì´í”„ë¼ì¸"
@@ -14683,6 +15367,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14716,6 +15403,9 @@ msgstr "최근 ì—…ë°ì´íŠ¸ë¨"
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14761,6 +15451,9 @@ msgstr ""
msgid "Learn more"
msgstr "ë” ì•Œì•„ë³´ê¸°"
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14836,6 +15529,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15368,9 +16064,6 @@ msgstr "3ì›”"
msgid "March"
msgstr "3ì›”"
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15389,6 +16082,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr "Markdown"
@@ -15422,9 +16118,6 @@ 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 ""
@@ -15434,7 +16127,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15446,6 +16139,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15509,6 +16205,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15629,6 +16328,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr "%{date} ì´ëž˜ë¡œ 회ì›"
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr "회ì›"
@@ -15656,15 +16361,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -15902,6 +16682,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16303,6 +17086,27 @@ msgstr "현재 ë¼ì´ì„¼ìŠ¤ì—서는 마ì¼ìŠ¤í†¤ 목ë¡ì„ 사용할 수 없습
msgid "Milestone lists show all issues from the selected milestone."
msgstr "마ì¼ìŠ¤í†¤ 목ë¡ì—는 ì„ íƒí•œ 마ì¼ìŠ¤í†¤ì˜ 모든 문제가 표시ë©ë‹ˆë‹¤."
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16618,9 +17422,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16678,6 +17488,32 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -16933,6 +17769,9 @@ msgstr "절대 아님"
msgid "New"
msgstr "신규"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr "새로운 애플리케ì´ì…˜"
@@ -17396,6 +18235,9 @@ msgstr ""
msgid "None"
msgstr "ì—†ìŒ"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17426,9 +18268,6 @@ msgstr "ë°ì´í„°ê°€ 충분하지 않습니다."
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr "나중ì—"
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17663,6 +18502,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17708,9 +18550,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17720,9 +18559,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17841,19 +18677,13 @@ msgstr ""
msgid "Open issues"
msgstr ""
-msgid "Open projects"
-msgstr ""
-
msgid "Open raw"
msgstr ""
msgid "Open sidebar"
msgstr "사ì´ë“œë°” 열기"
-msgid "Open: %{openIssuesCount}"
-msgstr "열림 : %{openIssuesCount}"
-
-msgid "Open: %{open} • Closed: %{closed}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18027,6 +18857,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18123,7 +18956,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18147,9 +18980,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18171,7 +19001,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18195,9 +19025,6 @@ 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 ""
@@ -18213,9 +19040,6 @@ 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 ""
@@ -18225,12 +19049,6 @@ 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 ""
@@ -18255,7 +19073,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18447,7 +19265,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18459,9 +19277,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr "성능 최ì í™”"
@@ -18564,6 +19379,9 @@ msgstr "성공 비율 :"
msgid "PipelineCharts|Successful:"
msgstr "성공 :"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "합계 :"
@@ -18645,6 +19463,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr "CI Lint"
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18663,6 +19484,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr "파ì´í”„ ë¼ì¸ìœ¼ë¡œ 시작하기"
@@ -18693,6 +19517,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "프로ì íŠ¸ ìºì‹œê°€ 성공ì ìœ¼ë¡œ 재설정ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -18729,6 +19556,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -18957,6 +19790,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -18966,6 +19802,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -18978,12 +19817,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19188,9 +20033,6 @@ 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 ""
@@ -19884,7 +20726,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20187,6 +21029,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20241,6 +21086,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20697,6 +21545,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20823,6 +21674,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr "Push"
@@ -20934,6 +21788,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21015,6 +21872,9 @@ msgstr ""
msgid "Refresh"
msgstr "새로고침"
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21058,9 +21918,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21269,6 +22126,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21389,6 +22249,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21410,9 +22273,15 @@ msgstr ""
msgid "Reopen epic"
msgstr "ì—픽 다시 열기"
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21440,6 +22309,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21564,7 +22436,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21576,6 +22454,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21594,6 +22484,9 @@ msgstr ""
msgid "Repository Settings"
msgstr "저장소 설정"
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21690,7 +22583,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21723,6 +22616,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -21921,6 +22817,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22072,6 +22971,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22099,6 +23004,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22168,6 +23076,9 @@ 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 ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22177,6 +23088,12 @@ msgstr "SSH 공개키"
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr "토요ì¼"
@@ -22192,6 +23109,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22216,9 +23136,6 @@ 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 variables"
-msgstr "변수 저장"
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22228,6 +23145,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "새로운 파ì´í”„ë¼ì¸ 스케줄 잡기"
@@ -22267,6 +23187,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22297,7 +23220,7 @@ msgstr "검색"
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22354,9 +23277,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr "그룹 검색"
-
msgid "Search merge requests"
msgstr "머지 리퀘스트(MR) 검색"
@@ -22438,9 +23358,6 @@ 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] ""
@@ -22494,7 +23411,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22539,10 +23456,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22671,6 +23588,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22734,6 +23654,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22773,6 +23699,10 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -22953,6 +23883,9 @@ msgstr "가져오고 ì‹¶ì€ í”„ë¡œì íŠ¸ë¥¼ ì„ íƒí•˜ì„¸ìš”."
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -22968,7 +23901,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -22983,9 +23916,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23079,6 +24009,9 @@ msgstr ""
msgid "September"
msgstr "9ì›”"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23193,6 +24126,9 @@ msgstr "서비스 템플릿"
msgid "Service URL"
msgstr "서비스 URL"
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23328,6 +24264,9 @@ msgstr "새 비밀번호 설정"
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23433,6 +24372,15 @@ msgstr "공용 Runners"
msgid "Shared projects"
msgstr "ê³µìœ ëœ í”„ë¡œì íŠ¸"
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23451,9 +24399,15 @@ msgstr "ì…œë¡ íŠ¸ëžœì ì…˜"
msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
msgstr "휴대í°ì„ 분실하거나 ì¼íšŒìš© ë¹„ë°€ë²ˆí˜¸ì— ì ‘ê·¼í•˜ì§€ 못하는 경우 ë‹¤ìŒ ë³µêµ¬ 코드를 한번씩 사용하여 ë‚´ ê³„ì •ì— ë‹¤ì‹œ 접근할 수 있습니다. 복구 코드를 안전한 ê³³ì— ë³´ê´€í•´ì£¼ì„¸ìš”. 그렇지 않으면 ê³„ì •ì— ì ‘ê·¼í•  수 %{b_start}없게%{b_end} ë©ë‹ˆë‹¤."
+msgid "Show Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23594,6 +24548,9 @@ msgstr "ë¡œê·¸ì¸ / 등ë¡"
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23621,6 +24578,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr "ë¡œê·¸ì¸ ì œí•œ"
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr "가입 제한"
@@ -23630,9 +24590,6 @@ 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 ""
@@ -23642,6 +24599,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr "%{authentication} ì¸ì¦ìœ¼ë¡œ ë¡œê·¸ì¸ ë¨"
@@ -23753,27 +24713,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24008,6 +24959,9 @@ msgstr "권한 레벨, 오름차순"
msgid "SortOptions|Access level, descending"
msgstr "권한 레벨, 내림차순"
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr "ìƒì„±ì¼"
@@ -24116,6 +25070,9 @@ msgstr "최근 로그ì¸"
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24158,9 +25115,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "소스 코드"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24236,9 +25190,6 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr "Runner 설정 중 ë‹¤ìŒ URLì„ ì§€ì •í•˜ì„¸ìš”."
-msgid "Speed up your DevOps%{br_tag}with GitLab"
-msgstr ""
-
msgid "Squash commit message"
msgstr ""
@@ -24302,6 +25253,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr "웹 í„°ë¯¸ë„ ì‹œìž‘"
@@ -24458,6 +25412,9 @@ msgstr "통계"
msgid "Status"
msgstr "ìƒíƒœ"
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24587,6 +25544,9 @@ msgstr "스팸으로 제출"
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24602,6 +25562,9 @@ msgstr "검색 제출"
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24644,6 +25607,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24728,6 +25697,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24749,6 +25721,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -24884,12 +25859,18 @@ msgstr ""
msgid "Sync information"
msgstr "ì •ë³´ ë™ê¸°í™”"
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -24917,6 +25898,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25148,15 +26132,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25241,7 +26240,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr "ê°ì‚¬í•©ë‹ˆë‹¤! 다시 보지 않겠습니다."
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25263,9 +26262,6 @@ 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 ""
@@ -25278,9 +26274,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25377,6 +26379,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25399,7 +26407,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25510,8 +26518,8 @@ msgstr "ê³„íš ë‹¨ê³„ì—서는 ì´ì „ 단계ì—ì„œ 첫 번째 커밋 ì‹œê°„ì´ í
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
-msgstr "ì´ í”„ë¡œì íŠ¸ëŠ” ë¡œê·¸ì¸ í•œ 사용ìžê°€ë§Œ 액세스 í•  수 있습니다."
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr ""
@@ -25570,6 +26578,9 @@ msgstr "Review 단계ì—서는 머지 리퀘스트(MR)를 작성한 후 머지í•
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25582,7 +26593,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25621,6 +26632,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25729,6 +26743,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -25924,6 +26941,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -25975,7 +26995,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -25999,9 +27019,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr "ì´ ì‘ìš© í”„ë¡œê·¸ëž¨ì€ ë‹¤ìŒì„ 수행 í•  수 있습니다."
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26134,6 +27160,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26143,6 +27172,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26695,6 +27727,12 @@ msgstr "방금 전"
msgid "Timeago|right now"
msgstr "지금"
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr "시간 초과"
@@ -26727,7 +27765,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26778,8 +27816,8 @@ msgstr ""
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
+msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "SVN 저장소ì—ì„œ 가져오려면, %{svn_link}(ì„)를 확ì¸í•˜ì„¸ìš”."
@@ -26907,6 +27945,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr "토글 네비게ì´ì…˜"
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "사ì´ë“œë°” 토글"
@@ -26979,16 +28020,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr "모든 커밋 / ë¨¸ì§€ì˜ ì´ í…ŒìŠ¤íŠ¸ 시간"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr "합계: %{total}"
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27165,6 +28209,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr "ë„기"
@@ -27315,6 +28362,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27540,6 +28590,9 @@ msgstr ""
msgid "Update now"
msgstr "지금 ì—…ë°ì´íŠ¸"
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27678,10 +28731,13 @@ msgstr "사용 통계"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27708,6 +28764,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27720,9 +28779,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27744,15 +28830,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27807,10 +28905,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -27930,6 +29025,9 @@ msgstr "ì´ë¯¸ 악용으로 ì‹ ê³ ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr "기여한 프로ì íŠ¸ë“¤"
@@ -28026,9 +29124,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28182,6 +29277,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28487,7 +29588,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28571,6 +29678,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28667,6 +29783,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28691,13 +29810,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28766,15 +29888,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28787,7 +29909,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Runnerê°€ 잠겨 있으면 다른 프로ì íŠ¸ì— 할당 í•  수 없습니다"
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29028,10 +30150,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29124,6 +30246,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29145,6 +30270,9 @@ msgstr "ì½ê¸°ì „ìš© GitLab ì¸ìŠ¤í„´ìŠ¤ë¥¼ 사용중입니다."
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29157,10 +30285,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr "ëª…ë ¹ì¤„ì„ í†µí•´ 프로ì íŠ¸ë¥¼ ìƒì„±í•  수 있습니다."
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29175,6 +30303,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29376,6 +30513,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29388,6 +30528,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr "ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
@@ -29412,9 +30561,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29472,9 +30618,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29577,19 +30720,22 @@ msgstr "ì´ë¯¸ ì¼íšŒìš© ì¸ì¦ê¸°ë¥¼ ì´ìš©í•˜ì—¬ ì´ì¤‘ ì¸ì¦ì„ 활성화했
msgid "YouTube"
msgstr "YouTube"
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29619,6 +30765,9 @@ msgstr "ë‚˜ì˜ ê·¸ë£¹"
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29634,6 +30783,9 @@ msgstr "ë‹¹ì‹ ì˜ í”„ë¡œì íŠ¸ 활ë™"
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -29899,9 +31051,6 @@ msgstr "브랜치 ì´ë¦„"
msgid "by"
msgstr "by"
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30028,9 +31177,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30076,9 +31222,6 @@ 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 ""
@@ -30161,6 +31304,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30394,7 +31540,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30412,6 +31558,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr "올바른 X509 ì¸ì¦ì„œê°€ 아닙니다."
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30430,6 +31579,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30466,6 +31618,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30527,6 +31682,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -30996,9 +32154,6 @@ 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 ""
@@ -31011,9 +32166,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr "남ì€"
@@ -31090,6 +32242,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr "ì •ë ¬:"
@@ -31270,9 +32425,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "%{additions} ê°œì˜ ì¶”ê°€, %{deletions} ê°œì˜ ì‚­ì œê°€ 있습니다."
@@ -31285,3 +32437,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/ku_TR/gitlab.po b/locale/ku_TR/gitlab.po
index 068097dc42e..070dacb0394 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-10-02 18:48\n"
+"PO-Revision-Date: 2020-11-03 22:48\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/ky_KG/gitlab.po b/locale/ky_KG/gitlab.po
index 0a8af4d8723..42cb361700b 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-10-02 18:43\n"
+"PO-Revision-Date: 2020-11-03 22:42\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/lt_LT/gitlab.po b/locale/lt_LT/gitlab.po
index 8f566274a95..57016e0ef98 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-10-02 18:48\n"
+"PO-Revision-Date: 2020-11-03 22:48\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -231,6 +231,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -273,13 +280,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -519,6 +519,20 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} more"
msgstr ""
@@ -563,6 +577,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -608,6 +628,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -734,9 +760,6 @@ 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 ""
@@ -844,7 +867,7 @@ msgstr[3] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -864,6 +887,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1089,9 +1115,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1132,6 +1155,18 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1164,6 +1199,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1173,19 +1211,8 @@ 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] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1478,6 +1505,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1779,6 +1809,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1932,7 +1965,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1968,10 +2001,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -2058,6 +2091,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -2082,6 +2118,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2196,6 +2235,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2205,6 +2259,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2217,12 +2277,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2277,6 +2355,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2286,6 +2367,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2331,6 +2415,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2355,6 +2442,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2364,6 +2454,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2379,22 +2472,22 @@ 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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2461,10 +2554,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2581,6 +2674,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2590,10 +2692,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2605,19 +2707,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2632,6 +2743,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2641,7 +2758,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2659,7 +2779,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2668,6 +2788,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2734,9 +2875,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2761,6 +2899,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2782,6 +2923,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2803,12 +2947,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2857,6 +3007,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2869,9 +3022,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2899,9 +3058,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2989,9 +3154,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -3064,9 +3226,6 @@ 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 ""
@@ -3097,9 +3256,6 @@ 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 ""
@@ -3124,6 +3280,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3148,9 +3307,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3166,6 +3322,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3503,6 +3662,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3753,6 +3915,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -4001,7 +4166,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -4022,6 +4208,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -4040,6 +4229,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -4097,9 +4289,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4181,6 +4370,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4265,6 +4460,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4316,12 +4523,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4340,6 +4556,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4352,6 +4571,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4496,6 +4718,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4532,9 +4757,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4565,7 +4802,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4748,6 +4985,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5159,6 +5399,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5342,9 +5585,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5363,9 +5603,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5474,6 +5711,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5498,7 +5738,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5525,6 +5765,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5708,6 +5951,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5765,9 +6011,6 @@ 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 ""
@@ -6023,9 +6266,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -6041,9 +6281,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6110,9 +6347,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6179,9 +6413,6 @@ 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 ""
@@ -6248,9 +6479,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6311,6 +6539,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6395,6 +6626,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6536,9 +6770,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6650,9 +6881,6 @@ 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 ""
@@ -6966,7 +7194,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -7017,6 +7245,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -7088,6 +7319,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7467,6 +7701,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7527,6 +7764,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7536,6 +7776,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7569,6 +7812,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7819,6 +8065,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7912,6 +8161,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8165,6 +8417,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8222,6 +8477,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8261,6 +8525,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8282,6 +8552,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8309,15 +8585,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8333,6 +8609,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8372,6 +8651,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8384,6 +8666,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8393,6 +8681,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8549,9 +8840,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8561,6 +8849,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8576,9 +8867,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8600,6 +8888,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8663,12 +8954,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8723,18 +9020,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8816,9 +9122,6 @@ 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 ""
@@ -8984,6 +9287,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -9032,6 +9341,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9203,6 +9515,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9254,7 +9587,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9405,6 +9738,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9414,6 +9750,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9435,6 +9774,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9462,9 +9804,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9633,15 +9972,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9714,6 +10062,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9855,6 +10206,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9882,7 +10239,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9927,6 +10296,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9954,7 +10326,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10716,12 +11091,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10752,6 +11133,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10827,6 +11211,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10929,6 +11316,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10992,6 +11382,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -11004,6 +11397,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11143,6 +11539,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11173,6 +11581,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11224,6 +11635,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11290,10 +11704,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11308,6 +11725,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11326,9 +11746,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11344,15 +11761,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11362,6 +11779,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11419,12 +11839,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11449,6 +11875,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11512,6 +11941,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11545,9 +11977,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11557,9 +11986,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11614,7 +12049,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12160,7 +12595,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12181,6 +12616,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12217,9 +12655,6 @@ 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 ""
@@ -12244,6 +12679,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12556,6 +12997,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12661,7 +13105,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12820,6 +13264,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12829,6 +13279,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12874,12 +13327,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12892,6 +13363,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12904,6 +13378,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12928,6 +13405,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13341,6 +13821,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13395,9 +13878,6 @@ 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 ""
@@ -13410,7 +13890,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13518,6 +13998,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13542,9 +14025,6 @@ 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 ""
@@ -13566,10 +14046,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13655,6 +14135,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13775,6 +14258,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13835,6 +14324,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13844,12 +14336,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13859,6 +14357,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13871,6 +14393,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13946,27 +14471,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13985,6 +14516,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -14016,6 +14550,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -14025,12 +14604,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -14064,6 +14661,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -14079,37 +14679,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -14118,6 +14739,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14142,9 +14766,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14244,25 +14865,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14310,6 +14931,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14358,6 +15033,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14574,6 +15252,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14829,6 +15510,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14847,6 +15531,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14976,9 +15666,6 @@ 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 ""
@@ -15007,9 +15694,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -15043,6 +15727,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -15076,6 +15763,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15121,6 +15811,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15196,6 +15889,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15749,9 +16445,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15770,6 +16463,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15803,9 +16499,6 @@ 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 ""
@@ -15815,7 +16508,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15827,6 +16520,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15890,6 +16586,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -16010,6 +16709,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -16037,15 +16742,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16283,6 +17063,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16690,6 +17473,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -17005,9 +17809,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -17065,6 +17875,38 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17320,6 +18162,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17786,6 +18631,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17816,9 +18664,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -18053,6 +18898,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -18098,9 +18946,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -18110,9 +18955,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18234,19 +19076,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18420,6 +19256,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18516,7 +19355,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18540,9 +19379,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18564,7 +19400,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18588,9 +19424,6 @@ 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 ""
@@ -18606,9 +19439,6 @@ 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 ""
@@ -18618,12 +19448,6 @@ 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 ""
@@ -18648,7 +19472,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18840,7 +19664,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18852,9 +19676,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18957,6 +19778,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -19038,6 +19862,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -19056,6 +19883,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -19086,6 +19916,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -19122,6 +19955,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19350,6 +20189,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19359,6 +20201,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19371,12 +20216,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19581,9 +20432,6 @@ 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 ""
@@ -20277,7 +21125,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20580,6 +21428,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20634,6 +21485,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -21090,6 +21944,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21216,6 +22073,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21327,6 +22187,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21408,6 +22271,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21454,9 +22320,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21668,6 +22531,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21788,6 +22654,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21809,9 +22678,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21839,6 +22714,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21966,7 +22844,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21978,6 +22862,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21996,6 +22892,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -22092,7 +22991,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -22125,6 +23024,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22332,6 +23234,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22486,6 +23391,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22513,6 +23424,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22582,6 +23496,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22591,6 +23508,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22606,6 +23529,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22630,9 +23556,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22642,6 +23565,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22681,6 +23607,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22711,7 +23640,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22768,9 +23697,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22852,9 +23778,6 @@ 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] ""
@@ -22941,7 +23864,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22986,10 +23909,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -23118,6 +24041,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23181,6 +24107,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23220,6 +24152,13 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23400,6 +24339,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23415,7 +24357,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23430,9 +24372,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23526,6 +24465,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23640,6 +24582,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23775,6 +24720,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23880,6 +24828,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23898,9 +24855,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -24047,6 +25010,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -24074,6 +25040,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -24083,9 +25052,6 @@ 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 ""
@@ -24095,6 +25061,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24206,27 +25175,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24461,6 +25421,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24569,6 +25532,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24611,9 +25577,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24689,9 +25652,6 @@ 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 ""
@@ -24755,6 +25715,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24911,6 +25874,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -25040,6 +26006,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -25055,6 +26024,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -25097,6 +26069,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25181,6 +26159,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25202,6 +26183,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25337,12 +26321,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25370,6 +26360,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25610,15 +26603,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25703,7 +26711,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25728,9 +26736,6 @@ 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 ""
@@ -25743,9 +26748,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25842,6 +26853,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25867,7 +26884,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25978,7 +26995,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -26038,6 +27055,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -26050,7 +27070,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -26089,6 +27109,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26197,6 +27220,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26392,6 +27418,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26443,7 +27472,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26467,9 +27496,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26602,6 +27637,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26611,6 +27649,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27163,6 +28204,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27201,7 +28248,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27252,7 +28299,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27381,6 +28428,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27453,16 +28503,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27639,6 +28692,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27789,6 +28845,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -28014,6 +29073,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -28152,10 +29214,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28182,6 +29247,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28194,9 +29262,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28218,15 +29313,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28281,10 +29388,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28404,6 +29508,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28500,9 +29607,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28656,6 +29760,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28967,7 +30077,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -29051,6 +30167,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -29147,6 +30272,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29171,13 +30299,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29246,15 +30377,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29267,7 +30398,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29511,10 +30642,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29607,6 +30738,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29628,6 +30762,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29640,10 +30777,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29658,6 +30795,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29859,6 +31005,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29871,6 +31020,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29895,9 +31053,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29955,9 +31110,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -30060,19 +31212,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -30102,6 +31257,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -30117,6 +31275,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30385,9 +31546,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30514,9 +31672,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30562,9 +31717,6 @@ 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 ""
@@ -30650,6 +31802,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30898,7 +32053,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30916,6 +32071,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30934,6 +32092,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30970,6 +32131,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -31034,6 +32198,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31515,9 +32682,6 @@ 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 ""
@@ -31530,9 +32694,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31612,6 +32773,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31792,9 +32956,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31807,3 +32968,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/mk_MK/gitlab.po b/locale/mk_MK/gitlab.po
new file mode 100644
index 00000000000..5b9d8100bc2
--- /dev/null
+++ b/locale/mk_MK/gitlab.po
@@ -0,0 +1,32619 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: \n"
+"Language-Team: Macedonian\n"
+"Language: mk_MK\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%10==1 && n%100 != 11 ? 0 : 1);\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Project-ID: 288872\n"
+"X-Crowdin-Language: mk\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"X-Crowdin-File-ID: 6\n"
+"PO-Revision-Date: 2020-11-03 22:49\n"
+
+msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
+msgstr ""
+
+msgid " %{start} to %{end}"
+msgstr ""
+
+msgid " (from %{timeoutSource})"
+msgstr ""
+
+msgid " Collected %{time}"
+msgstr ""
+
+msgid " Please sign in."
+msgstr ""
+
+msgid " Try to %{action} this file again."
+msgstr ""
+
+msgid " You need to do this before %{grace_period_deadline}."
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " and "
+msgstr ""
+
+msgid " and %{sliced}"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " or "
+msgstr ""
+
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
+
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
+
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
+
+msgid " or references (e.g. path/to/project!merge_request_id)"
+msgstr ""
+
+msgid "\"%{path}\" did not exist on \"%{ref}\""
+msgstr ""
+
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "%d Approval"
+msgid_plural "%d Approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Package"
+msgid_plural "%d Packages"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Scanned URL"
+msgid_plural "%d Scanned URLs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d URL scanned"
+msgid_plural "%d URLs scanned"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d approver"
+msgid_plural "%d approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d approver (you've approved)"
+msgid_plural "%d approvers (you've approved)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d child epic"
+msgid_plural "%d child epics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d code quality issue"
+msgid_plural "%d code quality issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d comment"
+msgid_plural "%d comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d comment on this commit"
+msgid_plural "%d comments on this commit"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit,"
+msgid_plural "%d commits,"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commits"
+msgstr ""
+
+msgid "%d completed issue"
+msgid_plural "%d completed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d day"
+msgid_plural "%d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d day until tags are automatically removed"
+msgid_plural "%d days until tags are automatically removed"
+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 failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d group selected"
+msgid_plural "%d groups selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d hour"
+msgid_plural "%d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d inaccessible merge request"
+msgid_plural "%d inaccessible merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue in this group"
+msgid_plural "%d issues in this group"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue successfully imported with the label"
+msgid_plural "%d issues successfully imported with the label"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d milestone"
+msgid_plural "%d milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d minute"
+msgid_plural "%d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d pending comment"
+msgid_plural "%d pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d personal project will be removed and cannot be restored."
+msgid_plural "%d personal projects will be removed and cannot be restored."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d previously merged commit"
+msgid_plural "%d previously merged commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d project"
+msgid_plural "%d projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d project selected"
+msgid_plural "%d projects selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d request with warnings"
+msgid_plural "%d requests with warnings"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d second"
+msgid_plural "%d seconds"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d shard selected"
+msgid_plural "%d shards selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d tag"
+msgid_plural "%d tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d tag per image name"
+msgid_plural "%d tags per image name"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unassigned issue"
+msgid_plural "%d unassigned issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unresolved thread"
+msgid_plural "%d unresolved threads"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability"
+msgid_plural "%d vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability dismissed"
+msgid_plural "%d vulnerabilities dismissed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d warning found:"
+msgid_plural "%d warnings found:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
+msgid "%{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 "%{completedCount} completed weight"
+msgstr ""
+
+msgid "%{completedWeight} of %{totalWeight} weight completed"
+msgstr ""
+
+msgid "%{containerScanningLinkStart}Container Scanning%{containerScanningLinkEnd} and/or %{dependencyScanningLinkStart}Dependency Scanning%{dependencyScanningLinkEnd} must be enabled. %{securityBotLinkStart}GitLab-Security-Bot%{securityBotLinkEnd} will be the author of the auto-created merge request. %{moreInfoLinkStart}More information%{moreInfoLinkEnd}."
+msgstr ""
+
+msgid "%{cores} cores"
+msgstr ""
+
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
+msgid "%{count} LOC/commit"
+msgstr ""
+
+msgid "%{count} approval required from %{name}"
+msgid_plural "%{count} approvals required from %{name}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} approvals from %{name}"
+msgstr ""
+
+msgid "%{count} files touched"
+msgstr ""
+
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} more"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} more release"
+msgid_plural "%{count} more releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} of %{required} approvals from %{name}"
+msgstr ""
+
+msgid "%{count} of %{total}"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} related %{pluralized_subject}: %{links}"
+msgstr ""
+
+msgid "%{count} total weight"
+msgstr ""
+
+msgid "%{dashboard_path} could not be found."
+msgstr ""
+
+msgid "%{days} days until tags are automatically removed"
+msgstr ""
+
+msgid "%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}."
+msgstr ""
+
+msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
+msgid "%{due_date} (Past due)"
+msgstr ""
+
+msgid "%{duration}ms"
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to create a new directory again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to upload a file again."
+msgstr ""
+
+msgid "%{extra} more downstream pipelines"
+msgstr ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
+msgstr ""
+
+msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{group_name} group members"
+msgstr ""
+
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
+msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
+msgstr ""
+
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
+msgid "%{host} sign-in from new location"
+msgstr ""
+
+msgid "%{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 "%{issuesCount} 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}Scan 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 "%{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 "%{size} %{unit}"
+msgstr ""
+
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
+msgid "%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
+msgid "%{spanStart}at line%{spanEnd} %{errorLine}%{errorColumn}"
+msgstr ""
+
+msgid "%{spanStart}in%{spanEnd} %{errorFn}"
+msgstr ""
+
+msgid "%{start} to %{end}"
+msgstr ""
+
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
+msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
+msgstr ""
+
+msgid "%{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 "%{timebox_type} does not support burnup charts"
+msgstr ""
+
+msgid "%{timebox_type} must have a start and due date"
+msgstr ""
+
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{token}..."
+msgstr ""
+
+msgid "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} free)"
+msgstr ""
+
+msgid "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} free)"
+msgstr ""
+
+msgid "%{totalWeight} total weight"
+msgstr ""
+
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
+msgid "%{total} open issue weight"
+msgstr ""
+
+msgid "%{total} warnings found: showing first %{warningsDisplayed}"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "%{userName} (cannot merge)"
+msgstr ""
+
+msgid "%{userName}'s avatar"
+msgstr ""
+
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "%{username}'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 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}' Value Stream deleted"
+msgstr ""
+
+msgid "'%{name}' stage already exists"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "'%{template_name}' is unknown or invalid"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
+msgid "(%{value}) has already been taken"
+msgstr ""
+
+msgid "(No changes)"
+msgstr ""
+
+msgid "(check progress)"
+msgstr ""
+
+msgid "(deleted)"
+msgstr ""
+
+msgid "(line: %{startLine})"
+msgstr ""
+
+msgid "(max size 15 MB)"
+msgstr ""
+
+msgid "(removed)"
+msgstr ""
+
+msgid "(revoked)"
+msgstr ""
+
+msgid "* * * * *"
+msgstr ""
+
+msgid "+ %{amount} more"
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "+ %{numberOfHiddenAssignees} more"
+msgstr ""
+
+msgid "+ %{numberOfHiddenReviewers} more"
+msgstr ""
+
+msgid "+%d more"
+msgid_plural "+%d more"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "+%{approvers} more approvers"
+msgstr ""
+
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
+msgid "+%{tags} more"
+msgstr ""
+
+msgid ", or "
+msgstr ""
+
+msgid "- 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 "."
+msgstr ""
+
+msgid "0 bytes"
+msgstr ""
+
+msgid "0 for unlimited"
+msgstr ""
+
+msgid "0 for unlimited, only effective with remote storage enabled."
+msgstr ""
+
+msgid "0t1DgySidms"
+msgstr ""
+
+msgid "1 Day"
+msgid_plural "%d Days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 Issue"
+msgid_plural "%d Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 day"
+msgid_plural "%d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 deploy key"
+msgid_plural "%d deploy keys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 hour"
+msgid_plural "%d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 minute"
+msgid_plural "%d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%{num} users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "20-29 contributions"
+msgstr ""
+
+msgid "2FA"
+msgstr ""
+
+msgid "2FADevice|Registered On"
+msgstr ""
+
+msgid "3 days"
+msgstr ""
+
+msgid "3 hours"
+msgstr ""
+
+msgid "30 days"
+msgstr ""
+
+msgid "30 minutes"
+msgstr ""
+
+msgid "30+ contributions"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "7 days"
+msgstr ""
+
+msgid "8 hours"
+msgstr ""
+
+msgid ":%{startLine} to %{endLine}"
+msgstr ""
+
+msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
+msgstr ""
+
+msgid "A '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 Gitpod configured Webapplication in Spring and Java"
+msgstr ""
+
+msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
+msgstr ""
+
+msgid "A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
+msgstr ""
+
+msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
+msgstr ""
+
+msgid "A Let's Encrypt SSL certificate can not be obtained until your domain is verified."
+msgstr ""
+
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr ""
+
+msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
+msgstr ""
+
+msgid "A 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 Fuzzing"
+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 expires"
+msgstr ""
+
+msgid "Access forbidden. Check your access level."
+msgstr ""
+
+msgid "Access granted"
+msgstr ""
+
+msgid "Access requests"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Access to Pages websites are controlled based on the user's membership to a given project. By checking this box, users will be required to be logged in to have access to all Pages websites in your instance."
+msgstr ""
+
+msgid "AccessDropdown|Deploy Keys"
+msgstr ""
+
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
+msgid "AccessTokens|Access Tokens"
+msgstr ""
+
+msgid "AccessTokens|Are you sure?"
+msgstr ""
+
+msgid "AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will stop working."
+msgstr ""
+
+msgid "AccessTokens|Are you sure? Any issue email addresses currently in use will stop working."
+msgstr ""
+
+msgid "AccessTokens|Created"
+msgstr ""
+
+msgid "AccessTokens|Feed token"
+msgstr ""
+
+msgid "AccessTokens|Incoming email token"
+msgstr ""
+
+msgid "AccessTokens|It cannot be used to access any other data."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can access repository static objects as if they were you. You should %{reset_link_start}reset it%{reset_link_end} if that ever happens."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can create issues as if they were you. You should %{link_reset_it} if that ever happens."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can read activity and issue RSS feeds or your calendar feed as if they were you. You should %{link_reset_it} if that ever happens."
+msgstr ""
+
+msgid "AccessTokens|Personal Access Tokens"
+msgstr ""
+
+msgid "AccessTokens|Static object token"
+msgstr ""
+
+msgid "AccessTokens|They are the only accepted password when you have Two-Factor Authentication (2FA) enabled."
+msgstr ""
+
+msgid "AccessTokens|You can also use personal access tokens to authenticate against Git over HTTP."
+msgstr ""
+
+msgid "AccessTokens|You can generate a personal access token for each application you use that needs access to the GitLab API."
+msgstr ""
+
+msgid "AccessTokens|Your feed token is used to authenticate you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar, and is included in those feed URLs."
+msgstr ""
+
+msgid "AccessTokens|Your incoming email token is used to authenticate you when you create a new issue by email, and is included in your personal project-specific email addresses."
+msgstr ""
+
+msgid "AccessTokens|Your static object token is used to authenticate you when repository static objects (e.g. archives, blobs, ...) are being served from an external storage."
+msgstr ""
+
+msgid "AccessTokens|reset it"
+msgstr ""
+
+msgid "AccessibilityReport|Learn more"
+msgstr ""
+
+msgid "AccessibilityReport|Message: %{message}"
+msgstr ""
+
+msgid "AccessibilityReport|New"
+msgstr ""
+
+msgid "AccessibilityReport|The accessibility scanning found an error of the following type: %{code}"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account ID"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Account: %{account}"
+msgstr ""
+
+msgid "Action to take when receiving an alert. %{docsLink}"
+msgstr ""
+
+msgid "Actions"
+msgstr ""
+
+msgid "Activate"
+msgstr ""
+
+msgid "Activate Service Desk"
+msgstr ""
+
+msgid "Activate user activity analysis"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active %{type} (%{token_length})"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add \"%{value}\""
+msgstr ""
+
+msgid "Add %d issue"
+msgid_plural "Add %d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
+msgstr ""
+
+msgid "Add CHANGELOG"
+msgstr ""
+
+msgid "Add CONTRIBUTING"
+msgstr ""
+
+msgid "Add GitLab to Slack"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add LICENSE"
+msgstr ""
+
+msgid "Add New Node"
+msgstr ""
+
+msgid "Add README"
+msgstr ""
+
+msgid "Add Variable"
+msgstr ""
+
+msgid "Add Zoom meeting"
+msgstr ""
+
+msgid "Add a %{type}"
+msgstr ""
+
+msgid "Add a GPG key"
+msgstr ""
+
+msgid "Add a Grafana button in the admin sidebar, monitoring section, to access a variety of statistics on the health and performance of GitLab."
+msgstr ""
+
+msgid "Add a To Do"
+msgstr ""
+
+msgid "Add a 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 a to do"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an existing issue"
+msgstr ""
+
+msgid "Add an impersonation token"
+msgstr ""
+
+msgid "Add another link"
+msgstr ""
+
+msgid "Add approval rule"
+msgstr ""
+
+msgid "Add approvers"
+msgstr ""
+
+msgid "Add bold text"
+msgstr ""
+
+msgid "Add child epic to an epic"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add comment to design"
+msgstr ""
+
+msgid "Add deploy freeze"
+msgstr ""
+
+msgid "Add domain"
+msgstr ""
+
+msgid "Add email address"
+msgstr ""
+
+msgid "Add environment"
+msgstr ""
+
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
+msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add issues"
+msgstr ""
+
+msgid "Add italic text"
+msgstr ""
+
+msgid "Add key"
+msgstr ""
+
+msgid "Add label(s)"
+msgstr ""
+
+msgid "Add list"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add or remove previously merged commits"
+msgstr ""
+
+msgid "Add or subtract spent time"
+msgstr ""
+
+msgid "Add previously merged commits"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add request manually"
+msgstr ""
+
+msgid "Add strikethrough text"
+msgstr ""
+
+msgid "Add suggestion to batch"
+msgstr ""
+
+msgid "Add system hook"
+msgstr ""
+
+msgid "Add to Slack"
+msgstr ""
+
+msgid "Add to epic"
+msgstr ""
+
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add to tree"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Add variable"
+msgstr ""
+
+msgid "Add webhook"
+msgstr ""
+
+msgid "Add/remove"
+msgstr ""
+
+msgid "AddContextCommits|Add previously merged commits"
+msgstr ""
+
+msgid "AddContextCommits|Add/remove"
+msgstr ""
+
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr ""
+
+msgid "Added"
+msgstr ""
+
+msgid "Added %{epic_ref} as a child epic."
+msgstr ""
+
+msgid "Added %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Added a to do."
+msgstr ""
+
+msgid "Added an issue to an epic."
+msgstr ""
+
+msgid "Added at"
+msgstr ""
+
+msgid "Added for this merge request"
+msgstr ""
+
+msgid "Added in this version"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional Metadata"
+msgstr ""
+
+msgid "Additional minutes"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds %{labels} %{label_text}."
+msgstr ""
+
+msgid "Adds a Zoom meeting"
+msgstr ""
+
+msgid "Adds a to do."
+msgstr ""
+
+msgid "Adds an issue to an epic."
+msgstr ""
+
+msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Note"
+msgstr ""
+
+msgid "Admin Notifications"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin Section"
+msgstr ""
+
+msgid "Admin mode already enabled"
+msgstr ""
+
+msgid "Admin mode disabled"
+msgstr ""
+
+msgid "Admin mode enabled"
+msgstr ""
+
+msgid "Admin notes"
+msgstr ""
+
+msgid "AdminArea|Active users"
+msgstr ""
+
+msgid "AdminArea|Billable users"
+msgstr ""
+
+msgid "AdminArea|Blocked users"
+msgstr ""
+
+msgid "AdminArea|Bots"
+msgstr ""
+
+msgid "AdminArea|Components"
+msgstr ""
+
+msgid "AdminArea|Developer"
+msgstr ""
+
+msgid "AdminArea|Features"
+msgstr ""
+
+msgid "AdminArea|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|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
+msgid "AdminArea|Owner"
+msgstr ""
+
+msgid "AdminArea|Projects: %{number_of_projects}"
+msgstr ""
+
+msgid "AdminArea|Reporter"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|Total users"
+msgstr ""
+
+msgid "AdminArea|User cap"
+msgstr ""
+
+msgid "AdminArea|Users statistics"
+msgstr ""
+
+msgid "AdminArea|Users with highest role"
+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 ""
+
+msgid "AdminDashboard|Error loading the statistics. Please try again"
+msgstr ""
+
+msgid "AdminNote|Note"
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminSettings|Apply integration settings to all Projects"
+msgstr ""
+
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|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|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Access"
+msgstr ""
+
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
+msgid "AdminUsers|Automatically marked as default internal user"
+msgstr ""
+
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
+msgid "AdminUsers|Block"
+msgstr ""
+
+msgid "AdminUsers|Block this user"
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Block user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Blocking user has the following effects:"
+msgstr ""
+
+msgid "AdminUsers|Cannot 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|Log in"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Owned groups will be left"
+msgstr ""
+
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
+msgid "AdminUsers|Personal projects will be left"
+msgstr ""
+
+msgid "AdminUsers|Personal projects, group and user history will be left intact"
+msgstr ""
+
+msgid "AdminUsers|Reactivating a user will:"
+msgstr ""
+
+msgid "AdminUsers|Regular"
+msgstr ""
+
+msgid "AdminUsers|Regular users have access to their groups and projects"
+msgstr ""
+
+msgid "AdminUsers|Restore user access to the account, including web, Git and API."
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
+msgid "AdminUsers|The user will be logged out"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to access git repositories"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to access the API"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to use slash commands"
+msgstr ""
+
+msgid "AdminUsers|The user will not receive any notifications"
+msgstr ""
+
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "AdminUsers|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 %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
+msgid "AdminUsers|You cannot remove your own admin rights."
+msgstr ""
+
+msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
+msgstr ""
+
+msgid "Administration"
+msgstr ""
+
+msgid "Adoption"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Advanced Search"
+msgstr ""
+
+msgid "Advanced Search with Elasticsearch"
+msgstr ""
+
+msgid "Advanced Settings"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "After a successful password update you will be redirected to login screen."
+msgstr ""
+
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "AlertManagement|Acknowledged"
+msgstr ""
+
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
+msgid "AlertManagement|Alert"
+msgstr ""
+
+msgid "AlertManagement|Alert assignee(s): %{assignees}"
+msgstr ""
+
+msgid "AlertManagement|Alert detail"
+msgstr ""
+
+msgid "AlertManagement|Alert details"
+msgstr ""
+
+msgid "AlertManagement|Alert status: %{status}"
+msgstr ""
+
+msgid "AlertManagement|Alerts"
+msgstr ""
+
+msgid "AlertManagement|All alerts"
+msgstr ""
+
+msgid "AlertManagement|Assign status"
+msgstr ""
+
+msgid "AlertManagement|Assignees"
+msgstr ""
+
+msgid "AlertManagement|Authorize external service"
+msgstr ""
+
+msgid "AlertManagement|Create incident"
+msgstr ""
+
+msgid "AlertManagement|Critical"
+msgstr ""
+
+msgid "AlertManagement|Display alerts from all your monitoring tools directly within GitLab. Streamline the investigation of your alerts and the escalation of alerts to incidents."
+msgstr ""
+
+msgid "AlertManagement|Edit"
+msgstr ""
+
+msgid "AlertManagement|Environment"
+msgstr ""
+
+msgid "AlertManagement|Events"
+msgstr ""
+
+msgid "AlertManagement|High"
+msgstr ""
+
+msgid "AlertManagement|Incident"
+msgstr ""
+
+msgid "AlertManagement|Info"
+msgstr ""
+
+msgid "AlertManagement|Key"
+msgstr ""
+
+msgid "AlertManagement|Low"
+msgstr ""
+
+msgid "AlertManagement|Medium"
+msgstr ""
+
+msgid "AlertManagement|Metrics"
+msgstr ""
+
+msgid "AlertManagement|Metrics weren't available in the alerts payload."
+msgstr ""
+
+msgid "AlertManagement|More information"
+msgstr ""
+
+msgid "AlertManagement|No alert data to display."
+msgstr ""
+
+msgid "AlertManagement|No alerts available to display. See %{linkStart}enabling alert management%{linkEnd} for more information on adding alerts to the list."
+msgstr ""
+
+msgid "AlertManagement|No alerts to display."
+msgstr ""
+
+msgid "AlertManagement|None"
+msgstr ""
+
+msgid "AlertManagement|Open"
+msgstr ""
+
+msgid "AlertManagement|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|Value"
+msgstr ""
+
+msgid "AlertManagement|View alerts in Opsgenie"
+msgstr ""
+
+msgid "AlertManagement|View incident"
+msgstr ""
+
+msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
+msgstr ""
+
+msgid "AlertService|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
+msgstr ""
+
+msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
+msgstr ""
+
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
+msgid "AlertSettings|API URL"
+msgstr ""
+
+msgid "AlertSettings|Active"
+msgstr ""
+
+msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
+msgstr ""
+
+msgid "AlertSettings|Add new integrations"
+msgstr ""
+
+msgid "AlertSettings|Alert test payload"
+msgstr ""
+
+msgid "AlertSettings|Authorization key"
+msgstr ""
+
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
+msgstr ""
+
+msgid "AlertSettings|Copy"
+msgstr ""
+
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
+msgid "AlertSettings|Enter test alert JSON...."
+msgstr ""
+
+msgid "AlertSettings|External Prometheus"
+msgstr ""
+
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+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|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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 integration was successfully updated."
+msgstr ""
+
+msgid "Alerts"
+msgstr ""
+
+msgid "Alerts endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+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 projects selected"
+msgstr ""
+
+msgid "All security scans are enabled because %{linkStart}Auto DevOps%{linkEnd} is enabled on this project"
+msgstr ""
+
+msgid "All threads resolved"
+msgstr ""
+
+msgid "All users must have a name."
+msgstr ""
+
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
+msgid "Allow access to the following IP addresses"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow group owners to manage LDAP-related settings"
+msgstr ""
+
+msgid "Allow only the selected protocols to be used for Git access."
+msgstr ""
+
+msgid "Allow owners to manage default branch protection per group"
+msgstr ""
+
+msgid "Allow owners to manually add users outside of LDAP"
+msgstr ""
+
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow repository mirroring to be configured by project maintainers"
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
+msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
+msgstr ""
+
+msgid "Allow this secondary node to replicate content on Object Storage"
+msgstr ""
+
+msgid "Allow users to dismiss the broadcast message"
+msgstr ""
+
+msgid "Allow users to register any application to use GitLab as an OAuth provider"
+msgstr ""
+
+msgid "Allow users to request access (if visibility is public or internal)"
+msgstr ""
+
+msgid "Allowed"
+msgstr ""
+
+msgid "Allowed Geo IP"
+msgstr ""
+
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
+msgid "Allowed email domain restriction only permitted for top-level groups"
+msgstr ""
+
+msgid "Allowed to fail"
+msgstr ""
+
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Almost there"
+msgstr ""
+
+msgid "Already blocked"
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Also unassign this user from related issues and merge requests"
+msgstr ""
+
+msgid "Alternate support URL for help page and help dropdown"
+msgstr ""
+
+msgid "Alternatively, you can convert your account to a managed account by the %{group_name} group."
+msgstr ""
+
+msgid "Amazon EKS"
+msgstr ""
+
+msgid "Amazon EKS integration allows you to provision EKS clusters from GitLab."
+msgstr ""
+
+msgid "Amazon Web Services"
+msgstr ""
+
+msgid "Amazon Web Services Logo"
+msgstr ""
+
+msgid "Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
+msgstr ""
+
+msgid "An administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
+msgid "An alert has been triggered in %{project_path}."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An email notification was recently sent from the admin panel. Please wait %{wait_time_in_words} before attempting to send another message."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
+msgid "An error occured while making the changes: %{error}"
+msgstr ""
+
+msgid "An error occurred adding a draft to the thread."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred creating the new branch."
+msgstr ""
+
+msgid "An error occurred fetching the approval rules."
+msgstr ""
+
+msgid "An error occurred fetching the approvers for the new rule."
+msgstr ""
+
+msgid "An error occurred fetching the dropdown data."
+msgstr ""
+
+msgid "An error occurred fetching the project authors."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when removing the label."
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
+msgid "An error occurred when updating the issue 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 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 lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job logs."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while fetching the releases. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
+msgid "An error occurred while generating a username. Please try again."
+msgstr ""
+
+msgid "An error occurred while getting 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 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 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 rendering the linter"
+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 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 configuration."
+msgstr ""
+
+msgid "An error occurred while updating labels."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+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 "An unknown error occurred."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Analyze a review version of your web application."
+msgstr ""
+
+msgid "Analyze your dependencies for known vulnerabilities."
+msgstr ""
+
+msgid "Analyze your source code and git history for secrets."
+msgstr ""
+
+msgid "Analyze your source code for known vulnerabilities."
+msgstr ""
+
+msgid "Ancestors"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Another action is currently in progress"
+msgstr ""
+
+msgid "Another issue tracker is already in use. Only one issue tracker service can be active at a time"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any %{header}"
+msgstr ""
+
+msgid "Any Author"
+msgstr ""
+
+msgid "Any branch"
+msgstr ""
+
+msgid "Any eligible user"
+msgstr ""
+
+msgid "Any encrypted tokens"
+msgstr ""
+
+msgid "Any files larger than this limit will not be indexed, and thus will not be searchable."
+msgstr ""
+
+msgid "Any label"
+msgstr ""
+
+msgid "Any member with 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 limits saved successfully"
+msgstr ""
+
+msgid "Application settings saved successfully"
+msgstr ""
+
+msgid "Application settings update failed"
+msgstr ""
+
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
+msgid "Application was successfully destroyed."
+msgstr ""
+
+msgid "Application was successfully updated."
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Applied"
+msgstr ""
+
+msgid "Apply"
+msgstr ""
+
+msgid "Apply a label"
+msgstr ""
+
+msgid "Apply a template"
+msgstr ""
+
+msgid "Apply changes"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Apply suggestions"
+msgstr ""
+
+msgid "Apply template"
+msgstr ""
+
+msgid "Apply this approval rule to any branch or a specific protected branch."
+msgstr ""
+
+msgid "Applying"
+msgstr ""
+
+msgid "Applying a template will replace the existing issue description. Any changes you have made will be lost."
+msgstr ""
+
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion..."
+msgstr ""
+
+msgid "Applying suggestions..."
+msgstr ""
+
+msgid "Approval Status"
+msgstr ""
+
+msgid "Approval rules"
+msgstr ""
+
+msgid "Approval rules reset to project defaults"
+msgstr ""
+
+msgid "ApprovalRuleRemove|%d member"
+msgid_plural "ApprovalRuleRemove|%d members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleRemove|Approvals from this member are not revoked."
+msgid_plural "ApprovalRuleRemove|Approvals from these members are not revoked."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{nMembers}."
+msgstr ""
+
+msgid "ApprovalRuleSummary|%d member"
+msgid_plural "ApprovalRuleSummary|%d members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
+msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRule|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 "Archive test case"
+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}\" Value Stream?"
+msgstr ""
+
+msgid "Are you sure you want to delete %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to delete these artifacts?"
+msgstr ""
+
+msgid "Are you sure you want to delete this %{typeOfComment}?"
+msgstr ""
+
+msgid "Are you sure you want to delete this SSH key?"
+msgstr ""
+
+msgid "Are you sure you want to delete this 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 import %d repository?"
+msgid_plural "Are you sure you want to import %d repositories?"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
+msgid "Are you sure you want to merge immediately?"
+msgstr ""
+
+msgid "Are you sure you want to re-deploy this environment?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to reindex?"
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
+msgid "Are you sure you want to remove the license?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to 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 revoke this personal access token? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
+msgid "Arrange charts"
+msgstr ""
+
+msgid "Artifact"
+msgstr ""
+
+msgid "Artifact could not be deleted."
+msgstr ""
+
+msgid "Artifact was successfully deleted."
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assets"
+msgstr ""
+
+msgid "Assets:"
+msgstr ""
+
+msgid "Assign"
+msgstr ""
+
+msgid "Assign Iteration"
+msgstr ""
+
+msgid "Assign To"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign 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 %{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|This month"
+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 "Authentication via WebAuthn device failed."
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Author: %{author_name}"
+msgstr ""
+
+msgid "Authored %{timeago}"
+msgstr ""
+
+msgid "Authored %{timeago} by %{author}"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization key"
+msgstr ""
+
+msgid "Authorization required"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorize %{user} to use your account?"
+msgstr ""
+
+msgid "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."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
+
+msgid "Autocomplete"
+msgstr ""
+
+msgid "Autocomplete description"
+msgstr ""
+
+msgid "Autocomplete hint"
+msgstr ""
+
+msgid "Autocomplete usage hint"
+msgstr ""
+
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
+msgid "Automatically close 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 ID"
+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|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 "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
+msgid "Be careful. Changing the project's namespace can have unintended side effects."
+msgstr ""
+
+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 "Billable Users:"
+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 free 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 "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket Server import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blame"
+msgstr ""
+
+msgid "Block user"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
+msgid "Blocked issue"
+msgstr ""
+
+msgid "Blocking issues"
+msgstr ""
+
+msgid "Blocks"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Board scope"
+msgstr ""
+
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Boards and Board Lists"
+msgstr ""
+
+msgid "Boards|An error occurred while creating the issue. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while creating the list. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while moving the issue. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while updating the list. Please try again."
+msgstr ""
+
+msgid "Boards|Collapse"
+msgstr ""
+
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|Expand"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
+msgid "Board|Load more issues"
+msgstr ""
+
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
+msgid "Branch"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch already exists"
+msgstr ""
+
+msgid "Branch changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
+msgid "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 "Brief title about the change"
+msgstr ""
+
+msgid "Broadcast Message was successfully created."
+msgstr ""
+
+msgid "Broadcast Message was successfully updated."
+msgstr ""
+
+msgid "Broadcast Messages"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse artifacts"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "BuildArtifacts|An error occurred while fetching the artifacts"
+msgstr ""
+
+msgid "BuildArtifacts|Loading artifacts"
+msgstr ""
+
+msgid "Built-in"
+msgstr ""
+
+msgid "Bulk request concurrency"
+msgstr ""
+
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
+msgid "Burndown chart"
+msgstr ""
+
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "Burnup chart"
+msgstr ""
+
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
+msgid "Business"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "Buy License"
+msgstr ""
+
+msgid "Buy more Pipeline minutes"
+msgstr ""
+
+msgid "By %{user_name}"
+msgstr ""
+
+msgid "By URL"
+msgstr ""
+
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
+msgstr ""
+
+msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
+msgstr ""
+
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
+msgid "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 "CODEOWNERS rule violation"
+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 fetch content for the blob: %{err}"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
+msgid "Can't load mermaid module: %{err}"
+msgstr ""
+
+msgid "Can't scan the code?"
+msgstr ""
+
+msgid "Can't update snippet: %{err}"
+msgstr ""
+
+msgid "Canary"
+msgstr ""
+
+msgid "Canary 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 enable shared runners because parent group does not allow it"
+msgstr ""
+
+msgid "Cannot find user key."
+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 "ChangeReviewer|Reviewer changed from %{old} to %{new}"
+msgstr ""
+
+msgid "ChangeReviewer|Reviewer changed to %{new}"
+msgstr ""
+
+msgid "ChangeReviewer|Unassigned"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|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 were successfully made."
+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 "Chinese language support using"
+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"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used as default"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
+msgstr ""
+
+msgid "CiVariables|Variables"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Masked"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle masked"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "Classification Label (optional)"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "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 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 "Client request timeout"
+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 issue"
+msgstr ""
+
+msgid "Close milestone"
+msgstr ""
+
+msgid "Close sidebar"
+msgstr ""
+
+msgid "Close this %{quick_action_target}"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed %{epicTimeagoDate}"
+msgstr ""
+
+msgid "Closed epics"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "Closed this %{quick_action_target}."
+msgstr ""
+
+msgid "Closed: %{closed}"
+msgstr ""
+
+msgid "Closes this %{quick_action_target}."
+msgstr ""
+
+msgid "Cluster"
+msgstr ""
+
+msgid "Cluster Health"
+msgstr ""
+
+msgid "Cluster cache cleared."
+msgstr ""
+
+msgid "Cluster does not exist"
+msgstr ""
+
+msgid "Cluster is required for Stages::ClusterEndpointInserter"
+msgstr ""
+
+msgid "Cluster level"
+msgstr ""
+
+msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
+msgstr ""
+
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
+msgid "ClusterAgents|Configuration"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Name"
+msgstr ""
+
+msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgstr ""
+
+msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes %{code_open}cluster-admin%{code_close} privileges."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|API URL should be a valid http/https url."
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster’s integration"
+msgstr ""
+
+msgid "ClusterIntegration|All data not committed to GitLab will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
+
+msgid "ClusterIntegration|Amazon EKS"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An unknown error occurred while attempting to connect to Kubernetes."
+msgstr ""
+
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
+msgid "ClusterIntegration|Authenticate with AWS"
+msgstr ""
+
+msgid "ClusterIntegration|Authenticate with Amazon Web Services"
+msgstr ""
+
+msgid "ClusterIntegration|Authentication Error"
+msgstr ""
+
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
+msgid "ClusterIntegration|Blocking mode"
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{linkStart}Let's Encrypt%{linkEnd} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Check your CA certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Check your cluster status"
+msgstr ""
+
+msgid "ClusterIntegration|Check your token"
+msgstr ""
+
+msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgstr ""
+
+msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
+msgstr ""
+
+msgid "ClusterIntegration|Choose the worker node %{linkStart}instance type%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Clear cluster cache"
+msgstr ""
+
+msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
+msgstr ""
+
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
+msgid "ClusterIntegration|Cluster management project (alpha)"
+msgstr ""
+
+msgid "ClusterIntegration|Cluster name is required."
+msgstr ""
+
+msgid "ClusterIntegration|Cluster_applications artifact too big. Maximum allowable size: %{human_size}"
+msgstr ""
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Clusters connected with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect cluster with certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Connection Error"
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress Endpoint"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Knative Endpoint"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load IAM roles"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load VPCs for the selected region"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load instance types"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load networks"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load security groups for the selected VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load subnets for the selected VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load subnetworks"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Create a provision role on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the account and external ID above. %{startMoreInfoLink}More information%{endLink}"
+msgstr ""
+
+msgid "ClusterIntegration|Create cluster on"
+msgstr ""
+
+msgid "ClusterIntegration|Create new cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Create new cluster on EKS"
+msgstr ""
+
+msgid "ClusterIntegration|Create new cluster on GKE"
+msgstr ""
+
+msgid "ClusterIntegration|Creating Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Crossplane"
+msgstr ""
+
+msgid "ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{codeStart}kubectl%{codeEnd} or %{linkStart}GitLab Integration%{linkEnd}. Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on."
+msgstr ""
+
+msgid "ClusterIntegration|Deletes all GitLab resources attached to this cluster during removal"
+msgstr ""
+
+msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
+msgstr ""
+
+msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Elastic Kubernetes Service"
+msgstr ""
+
+msgid "ClusterIntegration|Elastic Stack"
+msgstr ""
+
+msgid "ClusterIntegration|Enable Cloud Run for Anthos"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enabled stack"
+msgstr ""
+
+msgid "ClusterIntegration|Enter new Service Token"
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope is required."
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure EKS provider: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to fetch CloudFormation stack: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|Fluentd"
+msgstr ""
+
+msgid "ClusterIntegration|Fluentd is an open source data collector, which lets you unify the data collection and consumption for a better use and understanding of data. It requires at least one of the following logs to be successfully installed."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Agent managed clusters"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Container Network Policies"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab failed to authenticate."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab failed to connect to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Global default"
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google GKE"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|HTTP Error"
+msgstr ""
+
+msgid "ClusterIntegration|Helm 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 with a cluster certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate with a cluster certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer."
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Key pair name"
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Endpoint:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes version"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes version not found"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Loading IAM Roles"
+msgstr ""
+
+msgid "ClusterIntegration|Loading Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Loading VPCs"
+msgstr ""
+
+msgid "ClusterIntegration|Loading instance types"
+msgstr ""
+
+msgid "ClusterIntegration|Loading networks"
+msgstr ""
+
+msgid "ClusterIntegration|Loading security groups"
+msgstr ""
+
+msgid "ClusterIntegration|Loading subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Loading subnetworks"
+msgstr ""
+
+msgid "ClusterIntegration|Logging mode"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your API endpoint is correct"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
+msgstr ""
+
+msgid "ClusterIntegration|Namespace per environment"
+msgstr ""
+
+msgid "ClusterIntegration|No IAM Roles found"
+msgstr ""
+
+msgid "ClusterIntegration|No Key Pairs found"
+msgstr ""
+
+msgid "ClusterIntegration|No VPCs found"
+msgstr ""
+
+msgid "ClusterIntegration|No deployment cluster found for this job"
+msgstr ""
+
+msgid "ClusterIntegration|No deployment found for this job"
+msgstr ""
+
+msgid "ClusterIntegration|No instance type found"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No networks found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No security group found"
+msgstr ""
+
+msgid "ClusterIntegration|No subnet found"
+msgstr ""
+
+msgid "ClusterIntegration|No subnetworks found"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Node calculations use the Kubernetes Metrics API. Make sure your cluster has metrics installed"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes must be a numerical value."
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated endpoint in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace prefix (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{linkStart}GitLab Integration%{linkEnd} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|Protect your clusters with GitLab Container Network Policies by enforcing how pods communicate with each other and other network endpoints. %{linkStart}Learn more about configuring Network Policies here.%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Provider details"
+msgstr ""
+
+msgid "ClusterIntegration|Provision Role ARN"
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{linkStart}help page%{linkEnd} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration and resources"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration and resources?"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration?"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Removes cluster from project but keeps associated resources"
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin uninstalling failed"
+msgstr ""
+
+msgid "ClusterIntegration|SIEM Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|SIEM Port"
+msgstr ""
+
+msgid "ClusterIntegration|SIEM Protocol"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search IAM Roles"
+msgstr ""
+
+msgid "ClusterIntegration|Search Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Search VPCs"
+msgstr ""
+
+msgid "ClusterIntegration|Search domains"
+msgstr ""
+
+msgid "ClusterIntegration|Search instance types"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search networks"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search security groups"
+msgstr ""
+
+msgid "ClusterIntegration|Search subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Search subnetworks"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|Security group"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC to choose a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC to choose a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Select a network to choose a subnetwork"
+msgstr ""
+
+msgid "ClusterIntegration|Select a region to choose a Key Pair"
+msgstr ""
+
+msgid "ClusterIntegration|Select a region to choose a VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Select a stack to install Crossplane."
+msgstr ""
+
+msgid "ClusterIntegration|Select a zone to choose a network"
+msgstr ""
+
+msgid "ClusterIntegration|Select existing domain or use new"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Send Container Network Policies Logs"
+msgstr ""
+
+msgid "ClusterIntegration|Send Web Application Firewall Logs"
+msgstr ""
+
+msgid "ClusterIntegration|Service Token"
+msgstr ""
+
+msgid "ClusterIntegration|Service role"
+msgstr ""
+
+msgid "ClusterIntegration|Service token is required."
+msgstr ""
+
+msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
+msgstr ""
+
+msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while trying to save your settings. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
+msgstr ""
+
+msgid "ClusterIntegration|Subnets"
+msgstr ""
+
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
+msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
+msgstr ""
+
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr ""
+
+msgid "ClusterIntegration|The associated IP and all deployed services will be deleted and cannot be restored. Uninstalling Knative will also remove Istio from your cluster. This will not effect any other applications."
+msgstr ""
+
+msgid "ClusterIntegration|The associated Tiller pod, 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|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
+msgid "ClusterIntegration|There was an HTTP error when connecting to your cluster."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This is necessary if your integration has become out of sync. The cache is repopulated during the next CI job that requires namespace and service accounts."
+msgstr ""
+
+msgid "ClusterIntegration|This is necessary to clear existing environment-namespace associations from clusters previously managed by GitLab."
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgstr ""
+
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
+msgstr ""
+
+msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
+msgstr ""
+
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Troubleshooting tips:"
+msgstr ""
+
+msgid "ClusterIntegration|Unable to Authenticate"
+msgstr ""
+
+msgid "ClusterIntegration|Unable to Connect"
+msgstr ""
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Unknown Error"
+msgstr ""
+
+msgid "ClusterIntegration|Update %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgstr ""
+
+msgid "ClusterIntegration|Use %{query}"
+msgstr ""
+
+msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to remove your cluster integration and all GitLab-created resources associated with this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to remove your cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
+msgstr ""
+
+msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
+msgstr ""
+
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|You must specify a domain before you can install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|You should select at least two subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Your Elasticsearch cluster will be re-created during this upgrade. Your logs will be re-indexed, and you will lose historical logs from hosts terminated in the last 30 days."
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
+msgid "ClusterIntegration|Your service role is distinct from the provision role used when authenticating. It will allow Amazon EKS and the Kubernetes control plane to manage AWS resources on your behalf. To use a new role, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
+
+msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "ClusterIntergation|Select a VPC"
+msgstr ""
+
+msgid "ClusterIntergation|Select a network"
+msgstr ""
+
+msgid "ClusterIntergation|Select a security group"
+msgstr ""
+
+msgid "ClusterIntergation|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntergation|Select a subnetwork"
+msgstr ""
+
+msgid "ClusterIntergation|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntergation|Select key pair"
+msgstr ""
+
+msgid "ClusterIntergation|Select service role"
+msgstr ""
+
+msgid "Clusters|An error occurred while loading clusters"
+msgstr ""
+
+msgid "Code"
+msgstr ""
+
+msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
+msgstr ""
+
+msgid "Code Coverage| Empty code coverage data"
+msgstr ""
+
+msgid "Code Coverage|Couldn't fetch the code coverage data"
+msgstr ""
+
+msgid "Code 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 all threads"
+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 "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 "Community forum"
+msgstr ""
+
+msgid "Company name"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare %{oldCommitId}...%{newCommitId}"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "Compare submodule commit revisions"
+msgstr ""
+
+msgid "Compare with previous version"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Complete"
+msgstr ""
+
+msgid "Completed"
+msgstr ""
+
+msgid "Compliance"
+msgstr ""
+
+msgid "Compliance Dashboard"
+msgstr ""
+
+msgid "Compliance framework (optional)"
+msgstr ""
+
+msgid "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 "Configure which lists are shown for anyone who visits this board"
+msgstr ""
+
+msgid "Confirm"
+msgstr ""
+
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
+msgid "Confirmation required"
+msgstr ""
+
+msgid "Confluence"
+msgstr ""
+
+msgid "ConfluenceService|Confluence Workspace"
+msgstr ""
+
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
+msgstr ""
+
+msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
+msgstr ""
+
+msgid "ConfluenceService|The URL of the Confluence Workspace"
+msgstr ""
+
+msgid "ConfluenceService|Your GitLab Wiki can be accessed here: %{wiki_link}. To re-enable your GitLab Wiki, disable this integration"
+msgstr ""
+
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connected"
+msgstr ""
+
+msgid "Connecting"
+msgstr ""
+
+msgid "Connecting to terminal sync service"
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Connection failed"
+msgstr ""
+
+msgid "Connection failure"
+msgstr ""
+
+msgid "Connection timed out"
+msgstr ""
+
+msgid "Connection timeout"
+msgstr ""
+
+msgid "Consistency guarantee method"
+msgstr ""
+
+msgid "Contact sales to upgrade"
+msgstr ""
+
+msgid "Contact support"
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "Container Scanning"
+msgstr ""
+
+msgid "Container does not exist"
+msgstr ""
+
+msgid "Container registry images"
+msgstr ""
+
+msgid "Container registry is not enabled on this GitLab instance. Ask an administrator to enable it in order for Auto DevOps to work."
+msgstr ""
+
+msgid "Container repositories"
+msgstr ""
+
+msgid "Container repositories 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|Cleanup timed out before it could delete all tags"
+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|Some tags were not deleted"
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the cleanup policy."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the 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 cleanup policy timed out before it could delete all tags. An administrator can %{adminLinkStart}manually run cleanup now%{adminLinkEnd} or you can wait for the cleanup policy to automatically run again. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|The 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 "Contributor"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "Control emails linked to your account"
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Cookie domain"
+msgstr ""
+
+msgid "Copied"
+msgstr ""
+
+msgid "Copied labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy"
+msgstr ""
+
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy %{proxy_url}"
+msgstr ""
+
+msgid "Copy %{type}"
+msgstr ""
+
+msgid "Copy Account ID to clipboard"
+msgstr ""
+
+msgid "Copy External ID to clipboard"
+msgstr ""
+
+msgid "Copy ID"
+msgstr ""
+
+msgid "Copy KRB5 clone URL"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key"
+msgstr ""
+
+msgid "Copy URL"
+msgstr ""
+
+msgid "Copy branch name"
+msgstr ""
+
+msgid "Copy 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 this value"
+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 commit. An unexpected error occurred."
+msgstr ""
+
+msgid "Could not connect to FogBugz, check your URL"
+msgstr ""
+
+msgid "Could not connect to Sentry. Refresh the page to try again."
+msgstr ""
+
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
+msgid "Could not create Wiki Repository at this time. Please try again later."
+msgstr ""
+
+msgid "Could not create environment"
+msgstr ""
+
+msgid "Could not create group"
+msgstr ""
+
+msgid "Could not create issue"
+msgstr ""
+
+msgid "Could not create project"
+msgstr ""
+
+msgid "Could not create wiki page"
+msgstr ""
+
+msgid "Could not delete chat nickname %{chat_name}."
+msgstr ""
+
+msgid "Could not delete wiki page"
+msgstr ""
+
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
+msgid "Could not find design."
+msgstr ""
+
+msgid "Could not find iteration"
+msgstr ""
+
+msgid "Could not load instance counts. Please refresh the page to try again."
+msgstr ""
+
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "Could not remove the trigger."
+msgstr ""
+
+msgid "Could not restore the group"
+msgstr ""
+
+msgid "Could not revoke impersonation token %{token_name}."
+msgstr ""
+
+msgid "Could not revoke personal access token %{personal_access_token_name}."
+msgstr ""
+
+msgid "Could not revoke project access token %{project_access_token_name}."
+msgstr ""
+
+msgid "Could not save group ID"
+msgstr ""
+
+msgid "Could not save project ID"
+msgstr ""
+
+msgid "Could not save prometheus manual configuration"
+msgstr ""
+
+msgid "Could not update the LDAP settings"
+msgstr ""
+
+msgid "Could not update wiki page"
+msgstr ""
+
+msgid "Could not upload your designs as one or more files uploaded are not supported."
+msgstr ""
+
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
+msgid "Country"
+msgstr ""
+
+msgid "Coverage"
+msgstr ""
+
+msgid "Coverage Fuzzing"
+msgstr ""
+
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create %{environment}"
+msgstr ""
+
+msgid "Create %{type}"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create New Domain"
+msgstr ""
+
+msgid "Create Project"
+msgstr ""
+
+msgid "Create Value Stream"
+msgstr ""
+
+msgid "Create a GitLab account first, and then connect it to your %{label} account."
+msgstr ""
+
+msgid "Create a Mattermost team for this group"
+msgstr ""
+
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new deploy key for this project"
+msgstr ""
+
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a new repository"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
+msgid "Create an account using:"
+msgstr ""
+
+msgid "Create an 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 %{created_at}"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creates a branch and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Creating"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
+msgstr ""
+
+msgid "Creation date"
+msgstr ""
+
+msgid "Credentials"
+msgstr ""
+
+msgid "CredentialsInventory|No credentials found"
+msgstr ""
+
+msgid "CredentialsInventory|Personal Access Tokens"
+msgstr ""
+
+msgid "CredentialsInventory|SSH Keys"
+msgstr ""
+
+msgid "Critical vulnerabilities present"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron time zone"
+msgstr ""
+
+msgid "Crossplane"
+msgstr ""
+
+msgid "Current 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 analyzers: language support"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom metrics"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
+msgid "Custom range"
+msgstr ""
+
+msgid "Custom range (UTC)"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Add a stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Add stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Editing stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|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|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
+msgid "CycleAnalytics|Total days to completion"
+msgstr ""
+
+msgid "CycleAnalytics|Type of work"
+msgstr ""
+
+msgid "CycleAnalytics|group dropdown filter"
+msgstr ""
+
+msgid "CycleAnalytics|not allowed for the given start event"
+msgstr ""
+
+msgid "CycleAnalytics|project dropdown filter"
+msgstr ""
+
+msgid "CycleAnalytics|stage dropdown"
+msgstr ""
+
+msgid "DAG"
+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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
+msgid "DastProfiles|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|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
+msgid "DastProfiles|Do you want to discard this site profile?"
+msgstr ""
+
+msgid "DastProfiles|Do you want to discard your changes?"
+msgstr ""
+
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
+msgid "DastProfiles|Edit scanner profile"
+msgstr ""
+
+msgid "DastProfiles|Edit site profile"
+msgstr ""
+
+msgid "DastProfiles|Error Details"
+msgstr ""
+
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+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|Passive"
+msgstr ""
+
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
+msgid "DastProfiles|Profile name"
+msgstr ""
+
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
+msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
+msgstr ""
+
+msgid "DastProfiles|Save profile"
+msgstr ""
+
+msgid "DastProfiles|Scan mode"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Show debug messages"
+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|Turn on AJAX spider"
+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 failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+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 "Database update failed"
+msgstr ""
+
+msgid "Datasource name not found"
+msgstr ""
+
+msgid "Date"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Date range"
+msgstr ""
+
+msgid "Date range cannot exceed %{maxDateRange} days."
+msgstr ""
+
+msgid "Day of month"
+msgstr ""
+
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
+msgid "Days"
+msgstr ""
+
+msgid "Days to merge"
+msgstr ""
+
+msgid "Dear Administrator,"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Decompressed archive size validation failed."
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default CI configuration path"
+msgstr ""
+
+msgid "Default artifacts expiration"
+msgstr ""
+
+msgid "Default branch"
+msgstr ""
+
+msgid "Default branch and protected branches"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default deletion delay"
+msgstr ""
+
+msgid "Default description template for issues"
+msgstr ""
+
+msgid "Default description template for merge requests"
+msgstr ""
+
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
+msgid "Default initial branch name"
+msgstr ""
+
+msgid "Default 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 %{name}"
+msgstr ""
+
+msgid "Delete Comment"
+msgstr ""
+
+msgid "Delete Value Stream"
+msgstr ""
+
+msgid "Delete account"
+msgstr ""
+
+msgid "Delete artifacts"
+msgstr ""
+
+msgid "Delete badge"
+msgstr ""
+
+msgid "Delete board"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete domain"
+msgstr ""
+
+msgid "Delete label"
+msgstr ""
+
+msgid "Delete label: %{label_name} ?"
+msgstr ""
+
+msgid "Delete pipeline"
+msgstr ""
+
+msgid "Delete project"
+msgstr ""
+
+msgid "Delete project. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Delete serverless domain?"
+msgstr ""
+
+msgid "Delete snippet"
+msgstr ""
+
+msgid "Delete snippet?"
+msgstr ""
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete subscription"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
+msgid "Delete user list"
+msgstr ""
+
+msgid "Delete variable"
+msgstr ""
+
+msgid "DeleteProject|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 project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
+msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
+msgstr ""
+
+msgid "Denied"
+msgstr ""
+
+msgid "Denied authorization of chat nickname %{user_name}."
+msgstr ""
+
+msgid "Denied domains for sign-ups"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deny access request"
+msgstr ""
+
+msgid "Denylist file"
+msgstr ""
+
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies help page link"
+msgstr ""
+
+msgid "Dependencies|%d additional vulnerability not shown"
+msgid_plural "Dependencies|%d additional vulnerabilities not shown"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dependencies|%d vulnerability detected"
+msgid_plural "Dependencies|%d vulnerabilities detected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dependencies|%{remainingLicensesCount} more"
+msgstr ""
+
+msgid "Dependencies|(top level)"
+msgstr ""
+
+msgid "Dependencies|All"
+msgstr ""
+
+msgid "Dependencies|Based on the %{linkStart}latest successful%{linkEnd} scan"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Dependency path"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
+msgid "Dependencies|License"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
+msgid "Dependencies|Toggle vulnerability list"
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Vulnerable components"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency List has no entries"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency Scanning"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
+msgid "Depends on %d merge request being merged"
+msgid_plural "Depends on %d merge requests being merged"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "Deploy freezes"
+msgstr ""
+
+msgid "Deploy key was successfully updated."
+msgstr ""
+
+msgid "Deploy keys allow read-only or read-write (if enabled) access to your repository"
+msgstr ""
+
+msgid "Deploy keys allow read-only or read-write (if enabled) access to your repository. Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one."
+msgstr ""
+
+msgid "Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one."
+msgstr ""
+
+msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
+msgstr ""
+
+msgid "Deploy to..."
+msgstr ""
+
+msgid "DeployFreeze|Freeze end"
+msgstr ""
+
+msgid "DeployFreeze|Freeze start"
+msgstr ""
+
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
+msgstr ""
+
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgstr ""
+
+msgid "DeployFreeze|Time zone"
+msgstr ""
+
+msgid "DeployFreeze|You can specify deploy freezes using only %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read access to the package registry"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Allows write access to the package registry"
+msgstr ""
+
+msgid "DeployTokens|Allows write access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token"
+msgstr ""
+
+msgid "DeployTokens|Copy username"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Default format is \"gitlab+deploy-token-{n}\". Enter custom username if you want to change it."
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow access to packages, your repository, and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Group deploy tokens allow access to the packages, repositories, and registry images within the group."
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new group deploy token has been created."
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed"
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deploying to AWS is easy with GitLab"
+msgstr ""
+
+msgid "Deployment Frequency"
+msgstr ""
+
+msgid "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 template"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Descriptive label"
+msgstr ""
+
+msgid "Deselect all"
+msgstr ""
+
+msgid "Design Management files and data"
+msgstr ""
+
+msgid "Design repositories"
+msgstr ""
+
+msgid "Design repository"
+msgstr ""
+
+msgid "DesignManagement|%{current_design} of %{designs_count}"
+msgstr ""
+
+msgid "DesignManagement|%{filename} did not change."
+msgstr ""
+
+msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
+msgstr ""
+
+msgid "DesignManagement|Archive 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|There was an error moving your designs. Please upload your designs below."
+msgstr ""
+
+msgid "DesignManagement|To upload designs, you'll need to enable LFS and have admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+msgstr ""
+
+msgid "DesignManagement|Unresolve thread"
+msgstr ""
+
+msgid "DesignManagement|Upload designs"
+msgstr ""
+
+msgid "DesignManagement|Upload skipped."
+msgstr ""
+
+msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
+msgstr ""
+
+msgid "DesignManagement|and %{moreCount} more."
+msgstr ""
+
+msgid "Designs"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Detail"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Details (default)"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
+msgstr ""
+
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diff view settings"
+msgstr ""
+
+msgid "Difference between start date and now"
+msgstr ""
+
+msgid "DiffsCompareBaseBranch|(HEAD)"
+msgstr ""
+
+msgid "DiffsCompareBaseBranch|(base)"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direct member"
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Disable public access to Pages sites"
+msgstr ""
+
+msgid "Disable shared runners"
+msgstr ""
+
+msgid "Disable two-factor authentication"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
+msgid "Discover GitLab Geo"
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Discover|Check your application for security vulnerabilities that may lead to unauthorized access, data leaks, and denial of services."
+msgstr ""
+
+msgid "Discover|For code that's already live in production, our dashboards give you an easy way to prioritize any issues that are found, empowering your team to ship quickly and securely."
+msgstr ""
+
+msgid "Discover|GitLab will perform static and dynamic tests on the code of your application, looking for known flaws and report them in the merge request so you can fix them before merging."
+msgstr ""
+
+msgid "Discover|Give feedback for this page"
+msgstr ""
+
+msgid "Discover|Security capabilities, integrated into your development lifecycle"
+msgstr ""
+
+msgid "Discover|See the other features of the %{linkStart}gold plan%{linkEnd}"
+msgstr ""
+
+msgid "Discover|Start a free trial"
+msgstr ""
+
+msgid "Discover|Upgrade now"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved."
+msgstr ""
+
+msgid "Discuss a specific suggestion or question."
+msgstr ""
+
+msgid "Discussion to reply to cannot be found"
+msgstr ""
+
+msgid "Disk Usage"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss %d selected vulnerability as"
+msgid_plural "Dismiss %d selected vulnerabilities as"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dismiss DevOps Report introduction"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss Value Stream Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss selected"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Dismissable"
+msgstr ""
+
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
+msgid "Display alerts from all your monitoring tools directly within GitLab."
+msgstr ""
+
+msgid "Display name"
+msgstr ""
+
+msgid "Display rendered file"
+msgstr ""
+
+msgid "Display source"
+msgstr ""
+
+msgid "Do not display offers from third parties within GitLab"
+msgstr ""
+
+msgid "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 "Documentation pages URL"
+msgstr ""
+
+msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Domain cannot be deleted while associated to one or more clusters."
+msgstr ""
+
+msgid "Domain denylist"
+msgstr ""
+
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Domain was successfully created."
+msgstr ""
+
+msgid "Domain was successfully deleted."
+msgstr ""
+
+msgid "Domain was successfully updated."
+msgstr ""
+
+msgid "Don't have an account yet?"
+msgstr ""
+
+msgid "Don't include description in commit message"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
+msgid "Don't send usage data"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download %{format}"
+msgstr ""
+
+msgid "Download %{format}:"
+msgstr ""
+
+msgid "Download CSV"
+msgstr ""
+
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download as"
+msgstr ""
+
+msgid "Download as CSV"
+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 files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit fork in Web IDE"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Edit in Web IDE"
+msgstr ""
+
+msgid "Edit in single-file editor"
+msgstr ""
+
+msgid "Edit issues"
+msgstr ""
+
+msgid "Edit iteration"
+msgstr ""
+
+msgid "Edit public deploy key"
+msgstr ""
+
+msgid "Edit stage"
+msgstr ""
+
+msgid "Edit this file only."
+msgstr ""
+
+msgid "Edit this release"
+msgstr ""
+
+msgid "Edit title and description"
+msgstr ""
+
+msgid "Edit wiki page"
+msgstr ""
+
+msgid "Edit your most recent comment in a thread (from an empty textarea)"
+msgstr ""
+
+msgid "Edited"
+msgstr ""
+
+msgid "Edited %{timeago}"
+msgstr ""
+
+msgid "Editing"
+msgstr ""
+
+msgid "Elasticsearch AWS IAM credentials"
+msgstr ""
+
+msgid "Elasticsearch HTTP client timeout value in seconds."
+msgstr ""
+
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
+msgid "Elasticsearch reindexing is already in progress"
+msgstr ""
+
+msgid "Elasticsearch reindexing triggered"
+msgstr ""
+
+msgid "Elasticsearch returned status code: %{status_code}"
+msgstr ""
+
+msgid "Elasticsearch zero-downtime reindexing"
+msgstr ""
+
+msgid "Elastic|None. Select namespaces to index."
+msgstr ""
+
+msgid "Elastic|None. Select projects to index."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email %{number}"
+msgstr ""
+
+msgid "Email Notification"
+msgstr ""
+
+msgid "Email could not be sent"
+msgstr ""
+
+msgid "Email display name"
+msgstr ""
+
+msgid "Email not verified. Please verify your email in Salesforce."
+msgstr ""
+
+msgid "Email notification for unknown sign-ins"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Email restrictions"
+msgstr ""
+
+msgid "Email restrictions for sign-ups"
+msgstr ""
+
+msgid "Email sent"
+msgstr ""
+
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
+msgid "Email updates (optional)"
+msgstr ""
+
+msgid "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 sent to %{email} will still be supported"
+msgstr ""
+
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Empty file"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable %{link_start}Gitpod%{link_end} integration to launch a development environment in your browser directly from GitLab."
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Gitpod"
+msgstr ""
+
+msgid "Enable Gitpod?"
+msgstr ""
+
+msgid "Enable HTML emails"
+msgstr ""
+
+msgid "Enable Incident Management inbound alert limit"
+msgstr ""
+
+msgid "Enable 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 kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
+msgid "Enable maintenance mode"
+msgstr ""
+
+msgid "Enable mirror configuration"
+msgstr ""
+
+msgid "Enable or disable Seat Link."
+msgstr ""
+
+msgid "Enable or disable keyboard shortcuts"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable protected paths rate limit"
+msgstr ""
+
+msgid "Enable proxy"
+msgstr ""
+
+msgid "Enable reCAPTCHA 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 shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
+msgstr ""
+
+msgid "Enable snowplow tracking"
+msgstr ""
+
+msgid "Enable two-factor authentication"
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "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 Time"
+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 an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
+msgstr ""
+
+msgid "Enter at least three characters to search"
+msgstr ""
+
+msgid "Enter 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 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 burnup chart data"
+msgstr ""
+
+msgid "Error fetching diverging counts for branches. Please try again."
+msgstr ""
+
+msgid "Error fetching forked projects. Please try again."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching payload data."
+msgstr ""
+
+msgid "Error fetching 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 saving reviewers"
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error occurred while updating the issue status"
+msgstr ""
+
+msgid "Error occurred while updating the issue weight"
+msgstr ""
+
+msgid "Error occurred. A blocked user cannot be deactivated"
+msgstr ""
+
+msgid "Error occurred. A blocked user must be unblocked to be activated"
+msgstr ""
+
+msgid "Error occurred. User was not blocked"
+msgstr ""
+
+msgid "Error occurred. User was not confirmed"
+msgstr ""
+
+msgid "Error occurred. User was not unblocked"
+msgstr ""
+
+msgid "Error occurred. User was not unlocked"
+msgstr ""
+
+msgid "Error 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 "Excess storage"
+msgstr ""
+
+msgid "Excluding merge commits. Limited to %{limit} commits."
+msgstr ""
+
+msgid "Excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "Execution time"
+msgstr ""
+
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "Existing 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 all files"
+msgstr ""
+
+msgid "Expand all threads"
+msgstr ""
+
+msgid "Expand approvers"
+msgstr ""
+
+msgid "Expand file"
+msgstr ""
+
+msgid "Expand milestones"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expected documents: %{expected_documents}"
+msgstr ""
+
+msgid "Experienced"
+msgstr ""
+
+msgid "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 merge requests"
+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 To-Do for the design."
+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 new project access token: %{token_response_message}"
+msgstr ""
+
+msgid "Failed to create repository"
+msgstr ""
+
+msgid "Failed to create resources"
+msgstr ""
+
+msgid "Failed to create wiki"
+msgstr ""
+
+msgid "Failed to 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 branches. Please try again."
+msgstr ""
+
+msgid "Failed to load deploy keys."
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to load error details from Sentry."
+msgstr ""
+
+msgid "Failed to load errors from Sentry."
+msgstr ""
+
+msgid "Failed to load group activity metrics. Please try again."
+msgstr ""
+
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load groups, users and deploy keys."
+msgstr ""
+
+msgid "Failed to load labels. Please try again."
+msgstr ""
+
+msgid "Failed to load milestones. Please try again."
+msgstr ""
+
+msgid "Failed to load projects"
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
+msgid "Failed to load sidebar confidential toggle"
+msgstr ""
+
+msgid "Failed to load sidebar lock status"
+msgstr ""
+
+msgid "Failed to load stacktrace."
+msgstr ""
+
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
+msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
+msgstr ""
+
+msgid "Failed to move this issue because label was not found."
+msgstr ""
+
+msgid "Failed to move this issue because only a single label can be provided."
+msgstr ""
+
+msgid "Failed to move this issue because target project doesn't exist."
+msgstr ""
+
+msgid "Failed to promote label due to internal error. Please contact administrators."
+msgstr ""
+
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
+msgid "Failed to publish issue on status page."
+msgstr ""
+
+msgid "Failed to remove To-Do for the design."
+msgstr ""
+
+msgid "Failed to remove a Zoom meeting"
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to remove user identity."
+msgstr ""
+
+msgid "Failed to remove user key."
+msgstr ""
+
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
+msgid "Failed to save new settings"
+msgstr ""
+
+msgid "Failed to save preferences (%{error_message})."
+msgstr ""
+
+msgid "Failed to save preferences."
+msgstr ""
+
+msgid "Failed to set due date because the date format is invalid."
+msgstr ""
+
+msgid "Failed to set iteration on this issue. Please try again."
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to toggle To-Do for the design."
+msgstr ""
+
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
+msgid "Failed to update 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|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Add strategy"
+msgstr ""
+
+msgid "FeatureFlags|All Environments"
+msgstr ""
+
+msgid "FeatureFlags|All Users"
+msgstr ""
+
+msgid "FeatureFlags|All users"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Edit User List"
+msgstr ""
+
+msgid "FeatureFlags|Enable features for specific users and environments by configuring feature flag strategies."
+msgstr ""
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag User List Details"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag has no strategies"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Feature 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|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
+msgid "FeatureFlags|Flag becomes read only soon"
+msgstr ""
+
+msgid "FeatureFlags|Flag is read-only"
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+msgstr ""
+
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
+msgid "FeatureFlags|ID"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
+msgid "FeatureFlags|Include additional user IDs"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docsLinkAnchoredStart}compatible client library%{docsLinkAnchoredEnd} and specify the API URL, application name, and instance ID during the configuration setup. %{docsLinkStart}More Information%{docsLinkEnd}"
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|List details"
+msgstr ""
+
+msgid "FeatureFlags|Loading feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Loading user lists"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|New User List"
+msgstr ""
+
+msgid "FeatureFlags|New feature flag"
+msgstr ""
+
+msgid "FeatureFlags|New user list"
+msgstr ""
+
+msgid "FeatureFlags|Percent of users"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout (logged in users)"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
+msgstr ""
+
+msgid "FeatureFlags|Protected"
+msgstr ""
+
+msgid "FeatureFlags|Remove"
+msgstr ""
+
+msgid "FeatureFlags|Rollout Percentage"
+msgstr ""
+
+msgid "FeatureFlags|Rollout Strategy"
+msgstr ""
+
+msgid "FeatureFlags|Select a user list"
+msgstr ""
+
+msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "FeatureFlags|Strategies"
+msgstr ""
+
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the user lists."
+msgstr ""
+
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "FeatureFlags|User IDs"
+msgstr ""
+
+msgid "FeatureFlags|User List"
+msgstr ""
+
+msgid "FeatureFlags|User Lists"
+msgstr ""
+
+msgid "FeatureFlag|Percentage"
+msgstr ""
+
+msgid "FeatureFlag|Select a user list"
+msgstr ""
+
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
+msgid "FeatureFlag|There are no configured user lists"
+msgstr ""
+
+msgid "FeatureFlag|Type"
+msgstr ""
+
+msgid "FeatureFlag|User IDs"
+msgstr ""
+
+msgid "FeatureFlag|User List"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fetching incoming email"
+msgstr ""
+
+msgid "File"
+msgstr ""
+
+msgid "File %{current} of %{total}"
+msgstr ""
+
+msgid "File Hooks"
+msgstr ""
+
+msgid "File Hooks (%{count})"
+msgstr ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File format is no longer supported"
+msgstr ""
+
+msgid "File hooks are similar to system hooks but are executed as files instead of sending data to a URL."
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
+msgid "File name"
+msgstr ""
+
+msgid "File renamed with no changes."
+msgstr ""
+
+msgid "File sync capacity"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "File upload error."
+msgstr ""
+
+msgid "Filename"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
+msgid "Fill in the fields below, turn on %{strong_open}Enable SAML authentication for this group%{strong_close}, and press %{strong_open}Save changes%{strong_close}"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by %{page_context_word} that are currently opened."
+msgstr ""
+
+msgid "Filter by Git revision"
+msgstr ""
+
+msgid "Filter by issues that are currently closed."
+msgstr ""
+
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
+msgid "Filter by label"
+msgstr ""
+
+msgid "Filter by merge requests that are currently closed and unmerged."
+msgstr ""
+
+msgid "Filter by merge requests that are currently merged."
+msgstr ""
+
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by name"
+msgstr ""
+
+msgid "Filter by requirements that are currently archived."
+msgstr ""
+
+msgid "Filter by requirements that are currently opened."
+msgstr ""
+
+msgid "Filter by status"
+msgstr ""
+
+msgid "Filter by test cases that are currently archived."
+msgstr ""
+
+msgid "Filter by test cases that are currently opened."
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter by user"
+msgstr ""
+
+msgid "Filter parameters are not valid. Make sure that the end date is after the start date."
+msgstr ""
+
+msgid "Filter pipelines"
+msgstr ""
+
+msgid "Filter results"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
+msgid "Filter results..."
+msgstr ""
+
+msgid "Filter your repositories by name"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find File"
+msgstr ""
+
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
+msgid "Find bugs in your code with coverage-guided fuzzing."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find 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 setting up your dedicated account for %{group_name}."
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "First Seen"
+msgstr ""
+
+msgid "First day of the week"
+msgstr ""
+
+msgid "First name"
+msgstr ""
+
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "First seen"
+msgstr ""
+
+msgid "Fixed burndown chart"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "Flags"
+msgstr ""
+
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Folder/%{name}"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+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 except external users can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more info, read the documentation."
+msgstr ""
+
+msgid "For more information on how the number of active users is calculated, see the %{self_managed_subscriptions_doc_link} documentation."
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the File Hooks documentation."
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
+msgstr ""
+
+msgid "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 "Generic package file size in bytes"
+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|Primary node"
+msgstr ""
+
+msgid "Geo|Project"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Remove entry"
+msgstr ""
+
+msgid "Geo|Remove tracking database entry"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Reverify"
+msgstr ""
+
+msgid "Geo|Reverify all"
+msgstr ""
+
+msgid "Geo|Review replication status, and resynchronize and reverify items with the primary node."
+msgstr ""
+
+msgid "Geo|Secondary node"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synced at"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Synchronization of %{itemTitle} is disabled."
+msgstr ""
+
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
+msgid "Geo|There are no %{replicable_type} to show"
+msgstr ""
+
+msgid "Geo|Tracking database entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|URL can't be blank"
+msgstr ""
+
+msgid "Geo|URL must be a valid url (ex: https://gitlab.com)"
+msgstr ""
+
+msgid "Geo|Undefined"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
+msgstr ""
+
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Get started"
+msgstr ""
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Get started with performance monitoring"
+msgstr ""
+
+msgid "Get started!"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
+msgid "Git LFS is not enabled on this GitLab server, contact your admin."
+msgstr ""
+
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
+msgstr ""
+
+msgid "Git LFS status:"
+msgstr ""
+
+msgid "Git global setup"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git shallow clone"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git transfer in progress"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub API rate limit exceeded. Try again after %{reset_time}"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab"
+msgstr ""
+
+msgid "GitLab / Unsubscribe"
+msgstr ""
+
+msgid "GitLab API"
+msgstr ""
+
+msgid "GitLab Billing Team."
+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 Pages"
+msgstr ""
+
+msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
+msgstr ""
+
+msgid "GitLab Shell"
+msgstr ""
+
+msgid "GitLab Support Bot"
+msgstr ""
+
+msgid "GitLab Team Member"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab Workhorse"
+msgstr ""
+
+msgid "GitLab commit"
+msgstr ""
+
+msgid "GitLab export"
+msgstr ""
+
+msgid "GitLab for Slack"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
+msgstr ""
+
+msgid "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later."
+msgstr ""
+
+msgid "GitLab is undergoing maintenance and is operating in a read-only mode."
+msgstr ""
+
+msgid "GitLab member or Email address"
+msgstr ""
+
+msgid "GitLab metadata URL"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab restart is required to apply changes."
+msgstr ""
+
+msgid "GitLab single sign-on URL"
+msgstr ""
+
+msgid "GitLab username"
+msgstr ""
+
+msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com"
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLabPagesDomains|Retry"
+msgstr ""
+
+msgid "GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}."
+msgstr ""
+
+msgid "GitLabPages|Access Control is enabled for this Pages website; only authorized users will be able to access it. To make your website publicly available, navigate to your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} and select %{strong_start}Everyone%{strong_end} in pages section. Read the %{link_start}documentation%{link_end} for more information."
+msgstr ""
+
+msgid "GitLabPages|Access pages"
+msgstr ""
+
+msgid "GitLabPages|Are you sure?"
+msgstr ""
+
+msgid "GitLabPages|Certificate: %{subject}"
+msgstr ""
+
+msgid "GitLabPages|Configure pages"
+msgstr ""
+
+msgid "GitLabPages|Domains"
+msgstr ""
+
+msgid "GitLabPages|Edit"
+msgstr ""
+
+msgid "GitLabPages|Expired"
+msgstr ""
+
+msgid "GitLabPages|Force HTTPS (requires valid certificates)"
+msgstr ""
+
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
+msgstr ""
+
+msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
+msgstr ""
+
+msgid "GitLabPages|Learn 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 "Gitpod"
+msgstr ""
+
+msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
+msgstr ""
+
+msgid "Gitpod|Enable Gitpod integration"
+msgstr ""
+
+msgid "Gitpod|Gitpod URL"
+msgstr ""
+
+msgid "Gitpod|e.g. https://gitpod.example.com"
+msgstr ""
+
+msgid "Given access %{time_ago}"
+msgstr ""
+
+msgid "Given epic is already related to this epic."
+msgstr ""
+
+msgid "Global Shortcuts"
+msgstr ""
+
+msgid "Global notification settings"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go Micro is a framework for micro service development."
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go back (while searching for files)"
+msgstr ""
+
+msgid "Go back to %{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 "Goal of the changes and what reviewers should be aware of"
+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|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
+msgid "GroupSAML|Certificate fingerprint"
+msgstr ""
+
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Copy SAML Response XML"
+msgstr ""
+
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
+msgid "GroupSAML|Default membership role"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforced SSO"
+msgstr ""
+
+msgid "GroupSAML|Generate a SCIM token"
+msgstr ""
+
+msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
+msgstr ""
+
+msgid "GroupSAML|Identity"
+msgstr ""
+
+msgid "GroupSAML|Identity provider single sign-on URL"
+msgstr ""
+
+msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
+msgstr ""
+
+msgid "GroupSAML|Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "GroupSAML|Members"
+msgstr ""
+
+msgid "GroupSAML|Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "GroupSAML|NameID"
+msgstr ""
+
+msgid "GroupSAML|NameID Format"
+msgstr ""
+
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
+msgid "GroupSAML|Prohibit outer forks"
+msgstr ""
+
+msgid "GroupSAML|Prohibit outer forks for this group."
+msgstr ""
+
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
+msgid "GroupSAML|SAML Response Output"
+msgstr ""
+
+msgid "GroupSAML|SAML Response XML"
+msgstr ""
+
+msgid "GroupSAML|SAML Single Sign On"
+msgstr ""
+
+msgid "GroupSAML|SAML Single Sign On Settings"
+msgstr ""
+
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
+msgid "GroupSAML|SCIM API endpoint URL"
+msgstr ""
+
+msgid "GroupSAML|SCIM Token"
+msgstr ""
+
+msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
+msgstr ""
+
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
+msgid "GroupSAML|This will be set as the access level of users added to the group."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
+msgid "GroupSAML|To be able to prohibit outer forks, you first need to enforce dedicate group managed accounts."
+msgstr ""
+
+msgid "GroupSAML|Toggle SAML authentication"
+msgstr ""
+
+msgid "GroupSAML|Valid SAML Response"
+msgstr ""
+
+msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
+msgstr ""
+
+msgid "GroupSAML|Your SCIM token"
+msgstr ""
+
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
+msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
+msgstr ""
+
+msgid "GroupSAML|should be \"persistent\""
+msgstr ""
+
+msgid "GroupSAML|should be a random persistent ID, emails are discouraged"
+msgstr ""
+
+msgid "GroupSettings|Apply integration settings to all Projects"
+msgstr ""
+
+msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Be careful. Changing a group's parent can have unintended %{side_effects_link_start}side effects%{side_effects_link_end}."
+msgstr ""
+
+msgid "GroupSettings|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again."
+msgstr ""
+
+msgid "GroupSettings|Change group URL"
+msgstr ""
+
+msgid "GroupSettings|Changing group URL can have unintended side effects."
+msgstr ""
+
+msgid "GroupSettings|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|Import"
+msgstr ""
+
+msgid "GroupsNew|Import a GitLab group export file"
+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 comments on this file"
+msgstr ""
+
+msgid "Hide details"
+msgstr ""
+
+msgid "Hide file browser"
+msgstr ""
+
+msgid "Hide group projects"
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide list"
+msgstr ""
+
+msgid "Hide marketing-related entries from help"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide shared projects"
+msgstr ""
+
+msgid "Hide stage"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide values"
+msgstr ""
+
+msgid "High or unknown vulnerabilities present"
+msgstr ""
+
+msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
+msgstr ""
+
+msgid "Highest role:"
+msgstr ""
+
+msgid "HighlightBar|Alert events:"
+msgstr ""
+
+msgid "HighlightBar|Alert start time:"
+msgstr ""
+
+msgid "HighlightBar|Original alert:"
+msgstr ""
+
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "History of authentications"
+msgstr ""
+
+msgid "Homepage"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
+msgid "Hook was successfully created."
+msgstr ""
+
+msgid "Hook was successfully updated."
+msgstr ""
+
+msgid "Hostname"
+msgstr ""
+
+msgid "Hour (UTC)"
+msgstr ""
+
+msgid "Housekeeping"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "Housekeeping, export, path, transfer, remove, archive."
+msgstr ""
+
+msgid "How 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}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
+msgstr ""
+
+msgid "I'd like to receive updates about GitLab via email"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "ID:"
+msgstr ""
+
+msgid "IDE"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Commit to %{branchName} branch"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IDE|Successful commit"
+msgstr ""
+
+msgid "IDE|This option is disabled because you are not allowed to create merge requests in this project."
+msgstr ""
+
+msgid "IDE|This option is disabled because you don't have write permissions for the current branch."
+msgstr ""
+
+msgid "INFO: Your SSH key has expired. Please generate a new key."
+msgstr ""
+
+msgid "INFO: Your SSH key is expiring soon. Please generate a new key."
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "IP subnet restriction only allowed for top-level groups"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identifiers"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+msgstr ""
+
+msgid "If 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 the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
+msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
+msgstr ""
+
+msgid "If there is no previous license or if the previous license has expired, some GitLab functionality will be blocked until a new, valid license is uploaded."
+msgstr ""
+
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If you recently signed in and recognize the IP address, you may disregard this email."
+msgstr ""
+
+msgid "If you remove this license, GitLab will fall back on the previous license, if any."
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr ""
+
+msgid "Ignore"
+msgstr ""
+
+msgid "Ignored"
+msgstr ""
+
+msgid "Image URL"
+msgstr ""
+
+msgid "Image details"
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "ImageViewerDimensions|H"
+msgstr ""
+
+msgid "ImageViewerDimensions|W"
+msgstr ""
+
+msgid "Impersonation Tokens"
+msgstr ""
+
+msgid "Impersonation has been disabled"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import %d compatible repository"
+msgid_plural "Import %d compatible repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Import %d repository"
+msgid_plural "Import %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Import CSV"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+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 from"
+msgstr ""
+
+msgid "Import project members"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import 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|Import repositories"
+msgstr ""
+
+msgid "ImportProjects|Importing the project failed"
+msgstr ""
+
+msgid "ImportProjects|Importing the project failed: %{reason}"
+msgstr ""
+
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
+msgid "ImportProjects|Requesting your %{provider} repositories failed"
+msgstr ""
+
+msgid "ImportProjects|Select the repositories you want to import"
+msgstr ""
+
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
+msgid "ImportProjects|Update of imported projects with realtime changes failed"
+msgstr ""
+
+msgid "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 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|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|All"
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
+msgid "IncidentManagement|Assignees"
+msgstr ""
+
+msgid "IncidentManagement|Closed"
+msgstr ""
+
+msgid "IncidentManagement|Create incident"
+msgstr ""
+
+msgid "IncidentManagement|Critical - S1"
+msgstr ""
+
+msgid "IncidentManagement|Date created"
+msgstr ""
+
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
+msgid "IncidentManagement|High - S2"
+msgstr ""
+
+msgid "IncidentManagement|Incident"
+msgstr ""
+
+msgid "IncidentManagement|Incidents"
+msgstr ""
+
+msgid "IncidentManagement|Low - S4"
+msgstr ""
+
+msgid "IncidentManagement|Medium - S3"
+msgstr ""
+
+msgid "IncidentManagement|No incidents to display."
+msgstr ""
+
+msgid "IncidentManagement|Open"
+msgstr ""
+
+msgid "IncidentManagement|Published"
+msgstr ""
+
+msgid "IncidentManagement|Published to status page"
+msgstr ""
+
+msgid "IncidentManagement|Severity"
+msgstr ""
+
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
+msgid "IncidentManagement|There was an error displaying the incidents."
+msgstr ""
+
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
+msgid "IncidentManagement|Unassigned"
+msgstr ""
+
+msgid "IncidentManagement|Unknown"
+msgstr ""
+
+msgid "IncidentManagement|Unpublished"
+msgstr ""
+
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
+msgid "IncidentSettings|Alert integration"
+msgstr ""
+
+msgid "IncidentSettings|Grafana integration"
+msgstr ""
+
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
+msgid "IncidentSettings|Incidents"
+msgstr ""
+
+msgid "IncidentSettings|PagerDuty integration"
+msgstr ""
+
+msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
+msgstr ""
+
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
+msgid "Incidents"
+msgstr ""
+
+msgid "Incident|Alert details"
+msgstr ""
+
+msgid "Incident|Summary"
+msgstr ""
+
+msgid "Incident|There was an issue loading alert data. Please try again."
+msgstr ""
+
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include author name in notification email body"
+msgstr ""
+
+msgid "Include description in commit message"
+msgstr ""
+
+msgid "Include merge request description"
+msgstr ""
+
+msgid "Include the username in the URL if required: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}."
+msgstr ""
+
+msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
+msgstr ""
+
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
+msgid "Incoming email"
+msgstr ""
+
+msgid "Incoming!"
+msgstr ""
+
+msgid "Incompatible 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 "Inherited:"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Insert a code block"
+msgstr ""
+
+msgid "Insert a quote"
+msgstr ""
+
+msgid "Insert a video"
+msgstr ""
+
+msgid "Insert an image"
+msgstr ""
+
+msgid "Insert code"
+msgstr ""
+
+msgid "Insert image"
+msgstr ""
+
+msgid "Insert inline code"
+msgstr ""
+
+msgid "Insert suggestion"
+msgstr ""
+
+msgid "Insert video"
+msgstr ""
+
+msgid "Insights"
+msgstr ""
+
+msgid "Insights|Some items are not visible beacuse the project was filtered out in the insights.yml file (see the projects.only config for more information)."
+msgstr ""
+
+msgid "Insights|This project is filtered out in the insights.yml file (see the projects.only config for more information)."
+msgstr ""
+
+msgid "Install"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Install a Runner"
+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 "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceStatistics|Groups"
+msgstr ""
+
+msgid "InstanceStatistics|Issues"
+msgstr ""
+
+msgid "InstanceStatistics|Merge Requests"
+msgstr ""
+
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
+msgid "InstanceStatistics|Pipelines"
+msgstr ""
+
+msgid "InstanceStatistics|Projects"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
+msgid "InstanceStatistics|Users"
+msgstr ""
+
+msgid "Integration"
+msgstr ""
+
+msgid "Integration Settings"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations|%{integration} settings saved and active."
+msgstr ""
+
+msgid "Integrations|%{integration} settings saved, but not active."
+msgstr ""
+
+msgid "Integrations|All details"
+msgstr ""
+
+msgid "Integrations|Comment detail:"
+msgstr ""
+
+msgid "Integrations|Comment settings:"
+msgstr ""
+
+msgid "Integrations|Connection failed. Please check your settings."
+msgstr ""
+
+msgid "Integrations|Connection successful."
+msgstr ""
+
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
+msgid "Integrations|Enable comments"
+msgstr ""
+
+msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgstr ""
+
+msgid "Integrations|Includes commit title and branch"
+msgstr ""
+
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
+msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
+msgstr ""
+
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
+msgid "Integrations|Save settings?"
+msgstr ""
+
+msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
+msgstr ""
+
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
+msgid "Integrations|Standard"
+msgstr ""
+
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
+msgid "Integrations|Use custom settings"
+msgstr ""
+
+msgid "Integrations|Use default settings"
+msgstr ""
+
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
+msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
+msgstr ""
+
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal"
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
+
+msgid "Internal URL (optional)"
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Value Stream Analytics"
+msgstr ""
+
+msgid "Introducing Your DevOps Report"
+msgstr ""
+
+msgid "Invalid 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 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 "Invitation declined"
+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 "Invite your team"
+msgstr ""
+
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions"
+msgstr ""
+
+msgid "InviteMembersModal|Access expiration date (optional)"
+msgstr ""
+
+msgid "InviteMembersModal|Cancel"
+msgstr ""
+
+msgid "InviteMembersModal|Choose a role permission"
+msgstr ""
+
+msgid "InviteMembersModal|GitLab member or Email address"
+msgstr ""
+
+msgid "InviteMembersModal|Invite"
+msgstr ""
+
+msgid "InviteMembersModal|Invite team members"
+msgstr ""
+
+msgid "InviteMembersModal|Search for members to invite"
+msgstr ""
+
+msgid "InviteMembersModal|User not invited. Feature coming soon!"
+msgstr ""
+
+msgid "InviteMembersModal|Users were succesfully added"
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting members to the %{group_name} group"
+msgstr ""
+
+msgid "InviteMembers|Invite team members"
+msgstr ""
+
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
+msgid "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 actions"
+msgstr ""
+
+msgid "Issue already promoted to epic."
+msgstr ""
+
+msgid "Issue cannot be found."
+msgstr ""
+
+msgid "Issue created from vulnerability %{vulnerability_link}"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "Issue first deployed to production"
+msgstr ""
+
+msgid "Issue label"
+msgstr ""
+
+msgid "Issue or Merge Request ID is required"
+msgstr ""
+
+msgid "Issue published on status page."
+msgstr ""
+
+msgid "Issue 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|EWM work items tracker"
+msgstr ""
+
+msgid "IssueTracker|Redmine issue tracker"
+msgstr ""
+
+msgid "IssueTracker|YouTrack issue tracker"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues Rate Limits"
+msgstr ""
+
+msgid "Issues and Merge Requests"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues 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 may be several days before you see feature usage data."
+msgstr ""
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It seems like the Dependency Scanning job ran successfully, but no dependencies have been detected in your project."
+msgstr ""
+
+msgid "It seems that there is currently no available data for code coverage"
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
+msgid "Iteration"
+msgstr ""
+
+msgid "Iteration changed to"
+msgstr ""
+
+msgid "Iteration 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 "Japanese language support using"
+msgstr ""
+
+msgid "Jira Issues"
+msgstr ""
+
+msgid "Jira display name"
+msgstr ""
+
+msgid "Jira import is already running."
+msgstr ""
+
+msgid "Jira integration not configured."
+msgstr ""
+
+msgid "Jira project key is not configured"
+msgstr ""
+
+msgid "Jira project: %{importProject}"
+msgstr ""
+
+msgid "Jira service not configured."
+msgstr ""
+
+msgid "Jira users have been imported from the configured Jira instance. They can be mapped by selecting a GitLab user from the dropdown in the \"GitLab username\" column. When the form appears, the dropdown defaults to the user conducting the import."
+msgstr ""
+
+msgid "Jira-GitLab user mapping template"
+msgstr ""
+
+msgid "JiraService| on branch %{branch_link}"
+msgstr ""
+
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
+msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
+msgstr ""
+
+msgid "JiraService|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 "Joined %{time_ago}"
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jump to next unresolved thread"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Just me"
+msgstr ""
+
+msgid "K8s pod health"
+msgstr ""
+
+msgid "Keep divergent refs"
+msgstr ""
+
+msgid "Keep editing"
+msgstr ""
+
+msgid "Kerberos access denied"
+msgstr ""
+
+msgid "Key"
+msgstr ""
+
+msgid "Key (PEM)"
+msgstr ""
+
+msgid "Key: %{key}"
+msgstr ""
+
+msgid "Keyboard shortcuts"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl+"
+msgstr ""
+
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+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 group settings"
+msgstr ""
+
+msgid "LDAP settings"
+msgstr ""
+
+msgid "LDAP settings updated"
+msgstr ""
+
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
+msgid "LDAP synchronizations"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFS object"
+msgstr ""
+
+msgid "LFS objects"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "LICENSE"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "Label was created"
+msgstr ""
+
+msgid "Label was removed"
+msgstr ""
+
+msgid "Label was successfully updated."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. If a group label with the same title exists, it will also be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Language"
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last 2 weeks"
+msgstr ""
+
+msgid "Last 30 days"
+msgstr ""
+
+msgid "Last 60 days"
+msgstr ""
+
+msgid "Last 90 days"
+msgstr ""
+
+msgid "Last Accessed On"
+msgstr ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last Seen"
+msgstr ""
+
+msgid "Last Used"
+msgstr ""
+
+msgid "Last accessed on"
+msgstr ""
+
+msgid "Last activity"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last item before this page loaded in your browser:"
+msgstr ""
+
+msgid "Last name"
+msgstr ""
+
+msgid "Last name is too long (maximum is %{max_length} characters)."
+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 %{last_used_at} ago"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
+msgid "Last week"
+msgstr ""
+
+msgid "LastCommit|authored"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Latest pipeline for the most recent commit on this branch"
+msgstr ""
+
+msgid "Launch a ready-to-code development environment for your project."
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Lead Time"
+msgstr ""
+
+msgid "Learn 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 %{username}"
+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 "Legacy burndown chart"
+msgstr ""
+
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "License Compliance"
+msgstr ""
+
+msgid "License History"
+msgstr ""
+
+msgid "License ID:"
+msgstr ""
+
+msgid "License overview"
+msgstr ""
+
+msgid "License-Check"
+msgstr ""
+
+msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are active"
+msgstr ""
+
+msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are inactive"
+msgstr ""
+
+msgid "LicenseCompliance|Acceptable license to be used in the project"
+msgstr ""
+
+msgid "LicenseCompliance|Add a license"
+msgstr ""
+
+msgid "LicenseCompliance|Add license and related policy"
+msgstr ""
+
+msgid "LicenseCompliance|Allow"
+msgstr ""
+
+msgid "LicenseCompliance|Allowed"
+msgstr ""
+
+msgid "LicenseCompliance|Denied"
+msgstr ""
+
+msgid "LicenseCompliance|Deny"
+msgstr ""
+
+msgid "LicenseCompliance|Disallow merge request if detected and will instruct developer to remove"
+msgstr ""
+
+msgid "LicenseCompliance|Learn more about %{linkStart}License Approvals%{linkEnd}"
+msgstr ""
+
+msgid "LicenseCompliance|License"
+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 options"
+msgstr ""
+
+msgid "List settings"
+msgstr ""
+
+msgid "List the merge requests that must be merged before this one."
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Load more"
+msgstr ""
+
+msgid "Load more users"
+msgstr ""
+
+msgid "Loading"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
+msgid "Loading issues"
+msgstr ""
+
+msgid "Loading 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 as done"
+msgstr ""
+
+msgid "Mark as draft"
+msgstr ""
+
+msgid "Mark as ready"
+msgstr ""
+
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
+msgid "Mark this issue as related to another issue"
+msgstr ""
+
+msgid "Mark to do as done"
+msgstr ""
+
+msgid "Markdown"
+msgstr ""
+
+msgid "Markdown Help"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "Markdown is supported"
+msgstr ""
+
+msgid "MarkdownEditor|Add a link (%{modifierKey}K)"
+msgstr ""
+
+msgid "MarkdownEditor|Add a link (%{modifier_key}K)"
+msgstr ""
+
+msgid "MarkdownEditor|Add bold text (%{modifierKey}B)"
+msgstr ""
+
+msgid "MarkdownEditor|Add bold text (%{modifier_key}B)"
+msgstr ""
+
+msgid "MarkdownEditor|Add italic text (%{modifierKey}I)"
+msgstr ""
+
+msgid "MarkdownEditor|Add italic text (%{modifier_key}I)"
+msgstr ""
+
+msgid "Marked For Deletion At - %{deletion_time}"
+msgstr ""
+
+msgid "Marked this %{noun} as 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 "Marked 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 "Marks to do as done."
+msgstr ""
+
+msgid "Mask variable"
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
+msgid "MattermostService|Add to Mattermost"
+msgstr ""
+
+msgid "MattermostService|Command trigger word"
+msgstr ""
+
+msgid "MattermostService|Fill in the word that works best for your team."
+msgstr ""
+
+msgid "MattermostService|Request URL"
+msgstr ""
+
+msgid "MattermostService|Request method"
+msgstr ""
+
+msgid "MattermostService|Response icon"
+msgstr ""
+
+msgid "MattermostService|Response username"
+msgstr ""
+
+msgid "MattermostService|See list of available commands in Mattermost after setting up this service, by entering"
+msgstr ""
+
+msgid "MattermostService|Suggestions:"
+msgstr ""
+
+msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
+msgstr ""
+
+msgid "Max 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 role"
+msgstr ""
+
+msgid "Max size 15 MB"
+msgstr ""
+
+msgid "MaxBuilds"
+msgstr ""
+
+msgid "Maximum Conan package file size in bytes"
+msgstr ""
+
+msgid "Maximum Maven package file size in bytes"
+msgstr ""
+
+msgid "Maximum NPM package file size in bytes"
+msgstr ""
+
+msgid "Maximum NuGet package file size in bytes"
+msgstr ""
+
+msgid "Maximum PyPI package file size in bytes"
+msgstr ""
+
+msgid "Maximum Users:"
+msgstr ""
+
+msgid "Maximum allowable lifetime for personal access token (days)"
+msgstr ""
+
+msgid "Maximum artifacts size (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 "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
+msgstr ""
+
+msgid "Members invited to %{strong_start}%{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 "Members|%{time} by %{user}"
+msgstr ""
+
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
+msgid "Members|Expired"
+msgstr ""
+
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
+msgid "Members|No expiration set"
+msgstr ""
+
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
+msgid "Members|in %{time}"
+msgstr ""
+
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
+msgid "Memory Usage"
+msgstr ""
+
+msgid "Merge"
+msgstr ""
+
+msgid "Merge (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|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a thread"
+msgstr ""
+
+msgid "MergeRequests|started a thread on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a thread on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a thread on an outdated change in commit %{linkStart}%{commitDisplay}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a thread on commit %{linkStart}%{commitDisplay}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequest|Compare %{target} and %{source}"
+msgstr ""
+
+msgid "MergeRequest|Error dismissing suggestion popover. Please try again."
+msgstr ""
+
+msgid "MergeRequest|Error loading full diff. Please try again."
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "MergeRequest|Search files (%{modifier_key}P)"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Merged MRs"
+msgstr ""
+
+msgid "Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Merged this merge request."
+msgstr ""
+
+msgid "Merged: %{merged}"
+msgstr ""
+
+msgid "Merges this merge request immediately."
+msgstr ""
+
+msgid "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 "Message"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Method"
+msgstr ""
+
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
+msgid "Metric:"
+msgstr ""
+
+msgid "MetricChart|Please select a metric"
+msgstr ""
+
+msgid "MetricChart|Selected"
+msgstr ""
+
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Grafana"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics Dashboard"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition is invalid:"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition is valid."
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgstr ""
+
+msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
+msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
+msgstr ""
+
+msgid "MetricsSettings|Choose whether to display dashboard metrics in UTC or the user's local timezone."
+msgstr ""
+
+msgid "MetricsSettings|Dashboard timezone"
+msgstr ""
+
+msgid "MetricsSettings|External dashboard URL"
+msgstr ""
+
+msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgstr ""
+
+msgid "MetricsSettings|Metrics dashboard"
+msgstr ""
+
+msgid "MetricsSettings|UTC (Coordinated Universal Time)"
+msgstr ""
+
+msgid "MetricsSettings|User's local timezone"
+msgstr ""
+
+msgid "Metrics|1. Define and preview panel"
+msgstr ""
+
+msgid "Metrics|2. Paste panel YAML into dashboard"
+msgstr ""
+
+msgid "Metrics|Add metric"
+msgstr ""
+
+msgid "Metrics|Add panel"
+msgstr ""
+
+msgid "Metrics|Avg"
+msgstr ""
+
+msgid "Metrics|Back to dashboard"
+msgstr ""
+
+msgid "Metrics|Cancel"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
+msgid "Metrics|Copy YAML"
+msgstr ""
+
+msgid "Metrics|Copy and paste the panel YAML into your dashboard YAML file."
+msgstr ""
+
+msgid "Metrics|Create custom dashboard %{fileName}"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Create new dashboard"
+msgstr ""
+
+msgid "Metrics|Create your dashboard configuration file"
+msgstr ""
+
+msgid "Metrics|Current"
+msgstr ""
+
+msgid "Metrics|Dashboard files can be found in %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
+msgstr ""
+
+msgid "Metrics|Define panel YAML below to preview panel."
+msgstr ""
+
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
+msgid "Metrics|Duplicate"
+msgstr ""
+
+msgid "Metrics|Duplicate current dashboard"
+msgstr ""
+
+msgid "Metrics|Duplicate dashboard"
+msgstr ""
+
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
+msgid "Metrics|Duplicating..."
+msgstr ""
+
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgid_plural "Metrics|Edit metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Metrics|Expand panel"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Invalid time range, please verify."
+msgstr ""
+
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Link contains an invalid time window, please verify the link to see the requested time range."
+msgstr ""
+
+msgid "Metrics|Link contains invalid chart information, please verify the link to see the expanded panel."
+msgstr ""
+
+msgid "Metrics|Manage chart links"
+msgstr ""
+
+msgid "Metrics|Max"
+msgstr ""
+
+msgid "Metrics|Metrics Settings"
+msgstr ""
+
+msgid "Metrics|Min"
+msgstr ""
+
+msgid "Metrics|More actions"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|Open repository"
+msgstr ""
+
+msgid "Metrics|Panel YAML"
+msgstr ""
+
+msgid "Metrics|Panel YAML copied"
+msgstr ""
+
+msgid "Metrics|Preview panel"
+msgstr ""
+
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
+msgid "Metrics|Refresh dashboard"
+msgstr ""
+
+msgid "Metrics|Select a value"
+msgstr ""
+
+msgid "Metrics|Set refresh rate"
+msgstr ""
+
+msgid "Metrics|Star dashboard"
+msgstr ""
+
+msgid "Metrics|There was an error creating the dashboard."
+msgstr ""
+
+msgid "Metrics|There was an error creating the dashboard. %{error}"
+msgstr ""
+
+msgid "Metrics|There was an error fetching annotations. Please try again."
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting annotations information."
+msgstr ""
+
+msgid "Metrics|There was an error getting dashboard validation warnings information."
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error getting options for variable \"%{name}\"."
+msgstr ""
+
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics. %{message}"
+msgstr ""
+
+msgid "Metrics|To create a new dashboard, add a new YAML file to %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Unstar dashboard"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Validating query"
+msgstr ""
+
+msgid "Metrics|Values"
+msgstr ""
+
+msgid "Metrics|View documentation"
+msgstr ""
+
+msgid "Metrics|View logs"
+msgstr ""
+
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|You can save a copy of this dashboard to your repository so it can be customized. Select a file name and branch to save it."
+msgstr ""
+
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
+
+msgid "Metrics|Your dashboard schema is invalid. Edit the dashboard to correct the YAML schema."
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Mi"
+msgstr ""
+
+msgid "Microsoft Azure"
+msgstr ""
+
+msgid "Middleman project with Static Site Editor support"
+msgstr ""
+
+msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgstr ""
+
+msgid "Migrated %{success_count}/%{total_count} files."
+msgstr ""
+
+msgid "Migration successful."
+msgstr ""
+
+msgid "Milestone"
+msgid_plural "Milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
+msgid "MilestoneSidebar|Closed:"
+msgstr ""
+
+msgid "MilestoneSidebar|Copy reference"
+msgstr ""
+
+msgid "MilestoneSidebar|Due date"
+msgstr ""
+
+msgid "MilestoneSidebar|Edit"
+msgstr ""
+
+msgid "MilestoneSidebar|From"
+msgstr ""
+
+msgid "MilestoneSidebar|Issues"
+msgstr ""
+
+msgid "MilestoneSidebar|Merge requests"
+msgstr ""
+
+msgid "MilestoneSidebar|Merged:"
+msgstr ""
+
+msgid "MilestoneSidebar|New Issue"
+msgstr ""
+
+msgid "MilestoneSidebar|New issue"
+msgstr ""
+
+msgid "MilestoneSidebar|No due date"
+msgstr ""
+
+msgid "MilestoneSidebar|No start date"
+msgstr ""
+
+msgid "MilestoneSidebar|None"
+msgstr ""
+
+msgid "MilestoneSidebar|Open:"
+msgstr ""
+
+msgid "MilestoneSidebar|Reference:"
+msgstr ""
+
+msgid "MilestoneSidebar|Start date"
+msgstr ""
+
+msgid "MilestoneSidebar|Toggle sidebar"
+msgstr ""
+
+msgid "MilestoneSidebar|Until"
+msgstr ""
+
+msgid "MilestoneSidebar|complete"
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|Close Milestone"
+msgstr ""
+
+msgid "Milestones|Completed Issues (closed)"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Group Milestone"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Ongoing Issues (open and assigned)"
+msgstr ""
+
+msgid "Milestones|Project Milestone"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promote to Group Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr ""
+
+msgid "Milestones|Reopen Milestone"
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Milestones|Unstarted Issues (open and unassigned)"
+msgstr ""
+
+msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
+msgstr ""
+
+msgid "Minimum interval in days"
+msgstr ""
+
+msgid "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 HTTP integrations are not supported for this project"
+msgstr ""
+
+msgid "Multiple IP address ranges are supported."
+msgstr ""
+
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
+msgid "Multiple domains are supported."
+msgstr ""
+
+msgid "Multiple 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 ID:"
+msgstr ""
+
+msgid "Namespace is empty"
+msgstr ""
+
+msgid "Namespace:"
+msgstr ""
+
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
+msgid "Namespaces"
+msgstr ""
+
+msgid "Namespaces to index"
+msgstr ""
+
+msgid "Naming, topics, avatar"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Navigate to the project to close the milestone."
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Need help?"
+msgstr ""
+
+msgid "Needs 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|Are you sure you want to delete this policy? This action cannot be undone."
+msgstr ""
+
+msgid "NetworkPolicies|Choose whether to enforce this policy."
+msgstr ""
+
+msgid "NetworkPolicies|Create policy"
+msgstr ""
+
+msgid "NetworkPolicies|Define this policy's location, conditions and actions."
+msgstr ""
+
+msgid "NetworkPolicies|Delete policy"
+msgstr ""
+
+msgid "NetworkPolicies|Delete policy: %{policy}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
+msgid "NetworkPolicies|Description"
+msgstr ""
+
+msgid "NetworkPolicies|Edit policy"
+msgstr ""
+
+msgid "NetworkPolicies|Editor mode"
+msgstr ""
+
+msgid "NetworkPolicies|Enforcement status"
+msgstr ""
+
+msgid "NetworkPolicies|Environment does not have deployment platform"
+msgstr ""
+
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
+msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
+msgstr ""
+
+msgid "NetworkPolicies|Invalid or empty policy"
+msgstr ""
+
+msgid "NetworkPolicies|Kubernetes error: %{error}"
+msgstr ""
+
+msgid "NetworkPolicies|Last modified"
+msgstr ""
+
+msgid "NetworkPolicies|Name"
+msgstr ""
+
+msgid "NetworkPolicies|Namespace"
+msgstr ""
+
+msgid "NetworkPolicies|Network Policy"
+msgstr ""
+
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
+msgid "NetworkPolicies|New policy"
+msgstr ""
+
+msgid "NetworkPolicies|No policies detected"
+msgstr ""
+
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
+msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
+msgstr ""
+
+msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
+msgstr ""
+
+msgid "NetworkPolicies|Policy definition"
+msgstr ""
+
+msgid "NetworkPolicies|Policy description"
+msgstr ""
+
+msgid "NetworkPolicies|Policy editor"
+msgstr ""
+
+msgid "NetworkPolicies|Policy preview"
+msgstr ""
+
+msgid "NetworkPolicies|Policy status"
+msgstr ""
+
+msgid "NetworkPolicies|Policy type"
+msgstr ""
+
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
+msgid "NetworkPolicies|Rule mode"
+msgstr ""
+
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
+msgid "NetworkPolicies|Rules"
+msgstr ""
+
+msgid "NetworkPolicies|Save changes"
+msgstr ""
+
+msgid "NetworkPolicies|Something went wrong, failed to update policy"
+msgstr ""
+
+msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
+msgstr ""
+
+msgid "NetworkPolicies|Status"
+msgstr ""
+
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
+msgid "NetworkPolicies|Unable to parse policy"
+msgstr ""
+
+msgid "NetworkPolicies|YAML editor"
+msgstr ""
+
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New %{display_issuable_type}"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Branch"
+msgstr ""
+
+msgid "New Deploy Key"
+msgstr ""
+
+msgid "New Environment"
+msgstr ""
+
+msgid "New Epic"
+msgstr ""
+
+msgid "New File"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Group Name"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Jira import"
+msgstr ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Merge Request"
+msgstr ""
+
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
+msgid "New Password"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Project"
+msgstr ""
+
+msgid "New Requirement"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Test Case"
+msgstr ""
+
+msgid "New User"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New changes were added. %{linkStart}Reload the page to review them%{linkEnd}"
+msgstr ""
+
+msgid "New confidential epic title "
+msgstr ""
+
+msgid "New confidential issue title"
+msgstr ""
+
+msgid "New deploy key"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New environment"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New epic title"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New 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 test case"
+msgstr ""
+
+msgid "New users set to external"
+msgstr ""
+
+msgid "New! Suggest changes directly"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "Newest first"
+msgstr ""
+
+msgid "Newly registered users will by default be external"
+msgstr ""
+
+msgid "Next"
+msgstr ""
+
+msgid "Next commit"
+msgstr ""
+
+msgid "Next file in diff"
+msgstr ""
+
+msgid "Next unresolved discussion"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No %{header} for this request."
+msgstr ""
+
+msgid "No %{providerTitle} repositories found"
+msgstr ""
+
+msgid "No Epic"
+msgstr ""
+
+msgid "No Matching Results"
+msgstr ""
+
+msgid "No Scopes"
+msgstr ""
+
+msgid "No Tag"
+msgstr ""
+
+msgid "No active admin user found"
+msgstr ""
+
+msgid "No activities found"
+msgstr ""
+
+msgid "No application_settings found"
+msgstr ""
+
+msgid "No authentication methods configured."
+msgstr ""
+
+msgid "No available groups to fork the project."
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No changes between %{sourceBranch} and %{targetBranch}"
+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 content to show"
+msgstr ""
+
+msgid "No contributions"
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No data found"
+msgstr ""
+
+msgid "No data to display"
+msgstr ""
+
+msgid "No deployments found"
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No endpoint provided"
+msgstr ""
+
+msgid "No errors to display."
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No file hooks found."
+msgstr ""
+
+msgid "No file selected"
+msgstr ""
+
+msgid "No files"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No forks are available to you."
+msgstr ""
+
+msgid "No grouping"
+msgstr ""
+
+msgid "No issues found"
+msgstr ""
+
+msgid "No iteration"
+msgstr ""
+
+msgid "No iterations to show"
+msgstr ""
+
+msgid "No job log"
+msgstr ""
+
+msgid "No jobs to show"
+msgstr ""
+
+msgid "No label"
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No matches found"
+msgstr ""
+
+msgid "No matching labels"
+msgstr ""
+
+msgid "No matching results"
+msgstr ""
+
+msgid "No matching results for \"%{query}\""
+msgstr ""
+
+msgid "No members found"
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No milestone"
+msgstr ""
+
+msgid "No milestones to show"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No panels matching properties %{opts}"
+msgstr ""
+
+msgid "No parent group"
+msgstr ""
+
+msgid "No plan"
+msgstr ""
+
+msgid "No pods available"
+msgstr ""
+
+msgid "No policy matches this license"
+msgstr ""
+
+msgid "No preview for this file type"
+msgstr ""
+
+msgid "No prioritized labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No ref selected"
+msgstr ""
+
+msgid "No related merge requests found."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No required pipeline"
+msgstr ""
+
+msgid "No runner executable"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No source selected"
+msgstr ""
+
+msgid "No stack trace for this error"
+msgstr ""
+
+msgid "No starrers matched your search"
+msgstr ""
+
+msgid "No start date"
+msgstr ""
+
+msgid "No 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 "None of the group milestones have the same project as the release"
+msgstr ""
+
+msgid "Not Implemented"
+msgstr ""
+
+msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "Not all browsers support WebAuthn. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even from an unsupported browser."
+msgstr ""
+
+msgid "Not all data has been processed yet, the accuracy of the chart for the selected timeframe is limited."
+msgstr ""
+
+msgid "Not 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 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|Change reviewer merge request"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Fixed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|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"
+msgstr ""
+
+msgid "On track"
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "OnDemandScans|Could not run the scan. Please try again."
+msgstr ""
+
+msgid "OnDemandScans|Create a new scanner profile"
+msgstr ""
+
+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 scanner profile."
+msgstr ""
+
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
+msgid "OnDemandScans|On-demand Scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
+msgstr ""
+
+msgid "OnDemandScans|Run scan"
+msgstr ""
+
+msgid "OnDemandScans|Scanner profile"
+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 profile"
+msgstr ""
+
+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 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 comment type dropdown"
+msgstr ""
+
+msgid "Open epics"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open in file view"
+msgstr ""
+
+msgid "Open issues"
+msgstr ""
+
+msgid "Open raw"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open: %{open}"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened %{epicTimeagoDate}"
+msgstr ""
+
+msgid "Opened MRs"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation not allowed"
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|Add projects"
+msgstr ""
+
+msgid "OperationsDashboard|More information"
+msgstr ""
+
+msgid "OperationsDashboard|Operations Dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "Optional"
+msgstr ""
+
+msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "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 "Orphaned member"
+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 "Our documentation includes an example DevOps Score report."
+msgstr ""
+
+msgid "Out-of-compliance with this project's policies and should be removed"
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
+msgstr ""
+
+msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
+msgstr ""
+
+msgid "Outdent"
+msgstr ""
+
+msgid "Overridden"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owned by %{image_tag}"
+msgstr ""
+
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
+msgid "Owned by:"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package Registry"
+msgstr ""
+
+msgid "Package already exists"
+msgstr ""
+
+msgid "Package deleted successfully"
+msgstr ""
+
+msgid "Package file size limits"
+msgstr ""
+
+msgid "Package recipe already exists"
+msgstr ""
+
+msgid "Package type must be Conan"
+msgstr ""
+
+msgid "Package type must be Maven"
+msgstr ""
+
+msgid "Package type must be NuGet"
+msgstr ""
+
+msgid "Package type must be PyPi"
+msgstr ""
+
+msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|Add Conan Remote"
+msgstr ""
+
+msgid "PackageRegistry|Add NuGet Source"
+msgstr ""
+
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
+msgid "PackageRegistry|App group: %{group}"
+msgstr ""
+
+msgid "PackageRegistry|App name: %{name}"
+msgstr ""
+
+msgid "PackageRegistry|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|Install package version"
+msgstr ""
+
+msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
+msgstr ""
+
+msgid "PackageRegistry|License information located at %{link}"
+msgstr ""
+
+msgid "PackageRegistry|Manually Published"
+msgstr ""
+
+msgid "PackageRegistry|Maven"
+msgstr ""
+
+msgid "PackageRegistry|Maven Command"
+msgstr ""
+
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
+msgid "PackageRegistry|NPM"
+msgstr ""
+
+msgid "PackageRegistry|NuGet"
+msgstr ""
+
+msgid "PackageRegistry|NuGet Command"
+msgstr ""
+
+msgid "PackageRegistry|Package Registry"
+msgstr ""
+
+msgid "PackageRegistry|Pip Command"
+msgstr ""
+
+msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+msgstr ""
+
+msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|PyPI"
+msgstr ""
+
+msgid "PackageRegistry|Recipe: %{recipe}"
+msgstr ""
+
+msgid "PackageRegistry|Remove package"
+msgstr ""
+
+msgid "PackageRegistry|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "PackageRegistry|Source project located at %{link}"
+msgstr ""
+
+msgid "PackageRegistry|There are no %{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 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|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgstr ""
+
+msgid "PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?"
+msgstr ""
+
+msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
+msgstr ""
+
+msgid "PackageRegistry|npm command"
+msgstr ""
+
+msgid "PackageRegistry|published by %{author}"
+msgstr ""
+
+msgid "PackageRegistry|yarn command"
+msgstr ""
+
+msgid "PackageType|Composer"
+msgstr ""
+
+msgid "PackageType|Conan"
+msgstr ""
+
+msgid "PackageType|Maven"
+msgstr ""
+
+msgid "PackageType|NPM"
+msgstr ""
+
+msgid "PackageType|NuGet"
+msgstr ""
+
+msgid "PackageType|PyPI"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Packages & Registries"
+msgstr ""
+
+msgid "Page not found"
+msgstr ""
+
+msgid "Page settings"
+msgstr ""
+
+msgid "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'. Do not paste your private SSH key, as that can compromise your identity."
+msgstr ""
+
+msgid "Patch to apply"
+msgstr ""
+
+msgid "Path"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Paths can contain wildcards, like */welcome"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Pause replication"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "Pending comments"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "People without permission will never get a notification."
+msgstr ""
+
+msgid "Percent rollout must be an integer number between 0 and 100"
+msgstr ""
+
+msgid "Percentage"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, exporting, or removing the group."
+msgstr ""
+
+msgid "Perform common operations on GitLab project"
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "PerformanceBar|Bullet notifications"
+msgstr ""
+
+msgid "PerformanceBar|Download"
+msgstr ""
+
+msgid "PerformanceBar|Elasticsearch calls"
+msgstr ""
+
+msgid "PerformanceBar|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 duration:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineStatusTooltip|Pipeline: %{ciStatus}"
+msgstr ""
+
+msgid "PipelineStatusTooltip|Pipeline: %{ci_status}"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines emails"
+msgstr ""
+
+msgid "Pipelines for last month (%{oneMonthAgo} - %{today})"
+msgstr ""
+
+msgid "Pipelines for last week (%{oneWeekAgo} - %{today})"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
+msgstr ""
+
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgstr ""
+
+msgid "Pipelines|API"
+msgstr ""
+
+msgid "Pipelines|Are you sure you want to run this pipeline?"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|By revoking a trigger you will break any processes making use of it. Are you sure?"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
+msgid "Pipelines|Child pipeline"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Copy trigger token"
+msgstr ""
+
+msgid "Pipelines|Description"
+msgstr ""
+
+msgid "Pipelines|Edit"
+msgstr ""
+
+msgid "Pipelines|Editor"
+msgstr ""
+
+msgid "Pipelines|Get started with 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|Last Used"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|More Information"
+msgstr ""
+
+msgid "Pipelines|No triggers have been created yet. Add one using the form above."
+msgstr ""
+
+msgid "Pipelines|Owner"
+msgstr ""
+
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Revoke"
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|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|Token"
+msgstr ""
+
+msgid "Pipelines|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
+msgid "Pipelines|invalid"
+msgstr ""
+
+msgid "Pipelines|parent"
+msgstr ""
+
+msgid "Pipeline|Branch name"
+msgstr ""
+
+msgid "Pipeline|Canceled"
+msgstr ""
+
+msgid "Pipeline|Checking pipeline status."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "Pipeline|Coverage"
+msgstr ""
+
+msgid "Pipeline|Created"
+msgstr ""
+
+msgid "Pipeline|Date"
+msgstr ""
+
+msgid "Pipeline|Detached merge request pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Failed"
+msgstr ""
+
+msgid "Pipeline|Key"
+msgstr ""
+
+msgid "Pipeline|Manual"
+msgstr ""
+
+msgid "Pipeline|Merge train pipeline"
+msgstr ""
+
+msgid "Pipeline|Merged result pipeline"
+msgstr ""
+
+msgid "Pipeline|Passed"
+msgstr ""
+
+msgid "Pipeline|Pending"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Pipelines"
+msgstr ""
+
+msgid "Pipeline|Raw text search is not currently supported. Please use the available search tokens."
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run for"
+msgstr ""
+
+msgid "Pipeline|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 URL format, ex: http://www.example.com/home"
+msgstr ""
+
+msgid "Please enter a valid number"
+msgstr ""
+
+msgid "Please enter or upload a license."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please fill out this field."
+msgstr ""
+
+msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
+msgstr ""
+
+msgid "Please follow the Let's Encrypt troubleshooting instructions to re-obtain your Let's Encrypt certificate: %{docs_url}."
+msgstr ""
+
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
+msgid "Please provide a name"
+msgstr ""
+
+msgid "Please provide a valid URL"
+msgstr ""
+
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please provide attributes to update"
+msgstr ""
+
+msgid "Please reach out if you have any questions and we'll be happy to assist."
+msgstr ""
+
+msgid "Please refer to %{docs_url}"
+msgstr ""
+
+msgid "Please select"
+msgstr ""
+
+msgid "Please select a Jira project"
+msgstr ""
+
+msgid "Please select a country"
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
+msgid "Please select a group."
+msgstr ""
+
+msgid "Please select a valid target branch"
+msgstr ""
+
+msgid "Please select and add a member"
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please set a new password before proceeding."
+msgstr ""
+
+msgid "Please share your feedback about %{featureName} %{linkStart}in this issue%{linkEnd} to help us improve the experience."
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
+msgstr ""
+
+msgid "Please type the following to confirm:"
+msgstr ""
+
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
+msgstr ""
+
+msgid "Pod does not exist"
+msgstr ""
+
+msgid "Pod not found"
+msgstr ""
+
+msgid "Pods in use"
+msgstr ""
+
+msgid "Point to any links you like: documentation, built binaries, or other related materials. These can be internal or external links from your GitLab instance. Duplicate URLs are not allowed."
+msgstr ""
+
+msgid "Pre-defined push rules."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences saved."
+msgstr ""
+
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage}) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on your homepage."
+msgstr ""
+
+msgid "Preferences|Customize 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 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|%{provider} Active"
+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 %{provider}"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Default notification email"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Disconnect"
+msgstr ""
+
+msgid "Profiles|Disconnect %{provider}"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Expires at"
+msgstr ""
+
+msgid "Profiles|Expires:"
+msgstr ""
+
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Give your individual key a title."
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Key"
+msgstr ""
+
+msgid "Profiles|Last used:"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Location"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Primary email"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Public email"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Social sign-in"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Static object token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
+
+msgid "Profiles|The ability to update your name has been disabled by your administrator."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it? It will be publicly visible."
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more%{commit_email_link_end}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Time settings"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|User ID"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your key has expired"
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profile|%{job_title} at %{organization}"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project \"%{name}\" is no longer available. Select another project to continue."
+msgstr ""
+
+msgid "Project %{project_repo} could not be found"
+msgstr ""
+
+msgid "Project & Group can not be assigned at the same time"
+msgstr ""
+
+msgid "Project '%{project_name}' is being imported."
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' is restored."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project '%{project_name}' will be deleted on %{date}"
+msgstr ""
+
+msgid "Project Access Tokens"
+msgstr ""
+
+msgid "Project Audit Events"
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project Files"
+msgstr ""
+
+msgid "Project ID"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group."
+msgstr ""
+
+msgid "Project already deleted"
+msgstr ""
+
+msgid "Project and wiki repositories"
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
+msgid "Project 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 starts or finishes"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
+msgstr ""
+
+msgid "ProjectService|To set up this service:"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow"
+msgstr ""
+
+msgid "ProjectSettings|Allow 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|Basic"
+msgstr ""
+
+msgid "ProjectTemplates|GitLab Cluster Management"
+msgstr ""
+
+msgid "ProjectTemplates|Gitpod/Spring Petclinic"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|HIPAA Audit Protocol"
+msgstr ""
+
+msgid "ProjectTemplates|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|Serenity Valley"
+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|Does not apply to users allowed to push."
+msgstr ""
+
+msgid "ProtectedBranch|Protect"
+msgstr ""
+
+msgid "ProtectedBranch|Protect a branch"
+msgstr ""
+
+msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
+msgstr ""
+
+msgid "ProtectedBranch|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"
+msgstr ""
+
+msgid "Published on status page"
+msgstr ""
+
+msgid "Publishes this issue to the associated status page."
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Pull requests from fork are not supported"
+msgstr ""
+
+msgid "Puma is running with a thread count above 1 and the Rugged service is enabled. This may decrease performance in some environments. See our %{link_start}documentation%{link_end} for details of this issue."
+msgstr ""
+
+msgid "Purchase more minutes"
+msgstr ""
+
+msgid "Purchase more storage"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rule updated successfully."
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push Rules updated successfully."
+msgstr ""
+
+msgid "Push an existing Git repository"
+msgstr ""
+
+msgid "Push an existing folder"
+msgstr ""
+
+msgid "Push commits to the source branch or add previously merged commits to review them."
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Query"
+msgstr ""
+
+msgid "Query cannot be processed"
+msgstr ""
+
+msgid "Query is valid"
+msgstr ""
+
+msgid "Queued"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "Quick range"
+msgstr ""
+
+msgid "Quickly and easily edit multiple files in your project."
+msgstr ""
+
+msgid "README"
+msgstr ""
+
+msgid "Rails"
+msgstr ""
+
+msgid "Rake Tasks Help"
+msgstr ""
+
+msgid "Random"
+msgstr ""
+
+msgid "Raw blob request rate limit per minute"
+msgstr ""
+
+msgid "Re-authentication period expired or never requested. Please try again"
+msgstr ""
+
+msgid "Re-authentication required"
+msgstr ""
+
+msgid "Re-verification interval"
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
+msgstr ""
+
+msgid "Read more about related issues"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "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 "Refresh the page and try again."
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate export"
+msgstr ""
+
+msgid "Regenerate instance ID"
+msgstr ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Region that Elasticsearch is configured"
+msgstr ""
+
+msgid "Register"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
+msgid "Register WebAuthn Device"
+msgstr ""
+
+msgid "Register device"
+msgstr ""
+
+msgid "Register now"
+msgstr ""
+
+msgid "Register with two-factor app"
+msgstr ""
+
+msgid "Registration|Checkout"
+msgstr ""
+
+msgid "Registration|Your GitLab group"
+msgstr ""
+
+msgid "Registration|Your first project"
+msgstr ""
+
+msgid "Registration|Your profile"
+msgstr ""
+
+msgid "Registry setup"
+msgstr ""
+
+msgid "Regulate approvals by authors/committers, 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 "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 list"
+msgstr ""
+
+msgid "Remove member"
+msgstr ""
+
+msgid "Remove milestone"
+msgstr ""
+
+msgid "Remove node"
+msgstr ""
+
+msgid "Remove parent epic from an epic"
+msgstr ""
+
+msgid "Remove primary node"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove report"
+msgstr ""
+
+msgid "Remove secondary node"
+msgstr ""
+
+msgid "Remove spent time"
+msgstr ""
+
+msgid "Remove stage"
+msgstr ""
+
+msgid "Remove time estimate"
+msgstr ""
+
+msgid "Remove user & report"
+msgstr ""
+
+msgid "Remove user from group"
+msgstr ""
+
+msgid "Removed"
+msgstr ""
+
+msgid "Removed %{assignee_text} %{assignee_references}."
+msgstr ""
+
+msgid "Removed %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removed %{iteration_reference} iteration."
+msgstr ""
+
+msgid "Removed %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Removed %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removed %{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 integrations is not supported for this project"
+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 issue"
+msgstr ""
+
+msgid "Reopen milestone"
+msgstr ""
+
+msgid "Reopen test case"
+msgstr ""
+
+msgid "Reopen this %{quick_action_target}"
+msgstr ""
+
+msgid "Reopened this %{quick_action_target}."
+msgstr ""
+
+msgid "Reopens this %{quick_action_target}."
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Replace"
+msgstr ""
+
+msgid "Replace all label(s)"
+msgstr ""
+
+msgid "Replaced all labels with %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Replaces the clone URL root."
+msgstr ""
+
+msgid "Replication"
+msgstr ""
+
+msgid "Replication details"
+msgstr ""
+
+msgid "Replication enabled"
+msgstr ""
+
+msgid "Replication paused"
+msgstr ""
+
+msgid "Reply by email"
+msgstr ""
+
+msgid "Reply to comment"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Reply..."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report %{display_issuable_type} that are abusive, inappropriate or spam."
+msgstr ""
+
+msgid "Report abuse"
+msgstr ""
+
+msgid "Report abuse to admin"
+msgstr ""
+
+msgid "Reported %{timeAgo} by %{reportedBy}"
+msgstr ""
+
+msgid "Reported by %{reporter}"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{combinedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|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 "Repositories Analytics"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download test coverage data (.csv)"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Test Code Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|There was an error fetching the projects."
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Analytics"
+msgstr ""
+
+msgid "Repository Graph"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository already read-only"
+msgstr ""
+
+msgid "Repository check"
+msgstr ""
+
+msgid "Repository check was triggered."
+msgstr ""
+
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
+msgid "Repository 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 review from"
+msgstr ""
+
+msgid "Request to link SAML account must be authorized"
+msgstr ""
+
+msgid "Requested"
+msgstr ""
+
+msgid "Requested %{time_ago}"
+msgstr ""
+
+msgid "Requested design version does not exist."
+msgstr ""
+
+msgid "Requested states are invalid"
+msgstr ""
+
+msgid "Requests"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
+msgstr ""
+
+msgid "Require admin approval for new sign-ups"
+msgstr ""
+
+msgid "Require all users in this group to setup two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Require 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"
+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 "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 requested from %{name}"
+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 "Reviewer"
+msgid_plural "%d Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reviewer(s)"
+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 "Ruby"
+msgstr ""
+
+msgid "Rule name is already taken."
+msgstr ""
+
+msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
+msgstr ""
+
+msgid "Rules that define what git pushes are accepted for a project. All newly created projects will use these settings."
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run housekeeping"
+msgstr ""
+
+msgid "Run manual or delayed jobs"
+msgstr ""
+
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner 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|Active"
+msgstr ""
+
+msgid "Runners|Architecture"
+msgstr ""
+
+msgid "Runners|Can run untagged jobs"
+msgstr ""
+
+msgid "Runners|Description"
+msgstr ""
+
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
+msgid "Runners|Group"
+msgstr ""
+
+msgid "Runners|IP Address"
+msgstr ""
+
+msgid "Runners|Last contact"
+msgstr ""
+
+msgid "Runners|Locked to this project"
+msgstr ""
+
+msgid "Runners|Maximum job timeout"
+msgstr ""
+
+msgid "Runners|Name"
+msgstr ""
+
+msgid "Runners|Platform"
+msgstr ""
+
+msgid "Runners|Property Name"
+msgstr ""
+
+msgid "Runners|Protected"
+msgstr ""
+
+msgid "Runners|Register Runner"
+msgstr ""
+
+msgid "Runners|Revision"
+msgstr ""
+
+msgid "Runners|Shared"
+msgstr ""
+
+msgid "Runners|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 ""
+
+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"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML discovery tokens"
+msgstr ""
+
+msgid "SAML for %{group_name}"
+msgstr ""
+
+msgid "SAST Configuration"
+msgstr ""
+
+msgid "SHA256"
+msgstr ""
+
+msgid "SSH Key"
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH Keys Help"
+msgstr ""
+
+msgid "SSH host key fingerprints"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
+msgstr ""
+
+msgid "SSH key"
+msgstr ""
+
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification:"
+msgstr ""
+
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
+msgid "Saturday"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save %{name} size limits"
+msgstr ""
+
+msgid "Save Changes"
+msgstr ""
+
+msgid "Save Push Rules"
+msgstr ""
+
+msgid "Save and test payload"
+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 "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
+msgid "Saving"
+msgstr ""
+
+msgid "Saving project."
+msgstr ""
+
+msgid "Scanner"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Scheduled Deletion At - %{permanent_deletion_time}"
+msgstr ""
+
+msgid "Scheduled 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 "Scoped issue boards"
+msgstr ""
+
+msgid "Scopes"
+msgstr ""
+
+msgid "Scopes can't be blank"
+msgstr ""
+
+msgid "Scopes: %{scope_list}"
+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 a group"
+msgstr ""
+
+msgid "Search an environment spec"
+msgstr ""
+
+msgid "Search authors"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search branches, tags, and commits"
+msgstr ""
+
+msgid "Search by Git revision"
+msgstr ""
+
+msgid "Search by author"
+msgstr ""
+
+msgid "Search by commit title or SHA"
+msgstr ""
+
+msgid "Search by message"
+msgstr ""
+
+msgid "Search by name"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for Namespace"
+msgstr ""
+
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search for this text"
+msgstr ""
+
+msgid "Search forks"
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or filter results…"
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search projects..."
+msgstr ""
+
+msgid "Search requirements"
+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|code result"
+msgid_plural "SearchResults|code results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|comment"
+msgid_plural "SearchResults|comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|commit"
+msgid_plural "SearchResults|commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|epic"
+msgid_plural "SearchResults|epics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|issue"
+msgid_plural "SearchResults|issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|merge request"
+msgid_plural "SearchResults|merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|milestone"
+msgid_plural "SearchResults|milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|project"
+msgid_plural "SearchResults|projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|snippet"
+msgid_plural "SearchResults|snippets"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|user"
+msgid_plural "SearchResults|users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|wiki result"
+msgid_plural "SearchResults|wiki results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Searching by both author and message is currently not supported."
+msgstr ""
+
+msgid "Seat Link"
+msgstr ""
+
+msgid "Seat Link is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
+msgstr ""
+
+msgid "Seats usage data is updated every day at 12:00pm UTC"
+msgstr ""
+
+msgid "Secondary"
+msgstr ""
+
+msgid "Seconds"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Secret Detection"
+msgstr ""
+
+msgid "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 Denied licenses. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{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|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
+msgstr ""
+
+msgid "SecurityConfiguration|Configure"
+msgstr ""
+
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
+msgstr ""
+
+msgid "SecurityConfiguration|Enable via Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Enabled"
+msgstr ""
+
+msgid "SecurityConfiguration|Enabled with Auto DevOps"
+msgstr ""
+
+msgid "SecurityConfiguration|Feature documentation for %{featureName}"
+msgstr ""
+
+msgid "SecurityConfiguration|Manage"
+msgstr ""
+
+msgid "SecurityConfiguration|More information"
+msgstr ""
+
+msgid "SecurityConfiguration|Not enabled"
+msgstr ""
+
+msgid "SecurityConfiguration|SAST Analyzers"
+msgstr ""
+
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
+msgid "SecurityConfiguration|Security Control"
+msgstr ""
+
+msgid "SecurityConfiguration|Status"
+msgstr ""
+
+msgid "SecurityConfiguration|Testing & Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
+msgstr ""
+
+msgid "SecurityConfiguration|View history"
+msgstr ""
+
+msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgstr ""
+
+msgid "SecurityReports|Add a project to your dashboard"
+msgstr ""
+
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
+msgstr ""
+
+msgid "SecurityReports|Add projects"
+msgstr ""
+
+msgid "SecurityReports|Add projects to your group"
+msgstr ""
+
+msgid "SecurityReports|Comment added to '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Comment deleted on '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Create issue"
+msgstr ""
+
+msgid "SecurityReports|Dismiss Selected"
+msgstr ""
+
+msgid "SecurityReports|Dismiss vulnerability"
+msgstr ""
+
+msgid "SecurityReports|Dismissed '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
+msgstr ""
+
+msgid "SecurityReports|Download 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|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
+msgid "SecurityReports|False positive"
+msgstr ""
+
+msgid "SecurityReports|Fuzzing artifacts"
+msgstr ""
+
+msgid "SecurityReports|Hide dismissed"
+msgstr ""
+
+msgid "SecurityReports|Issue Created"
+msgstr ""
+
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
+msgstr ""
+
+msgid "SecurityReports|Learn more about setting up your dashboard"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
+msgstr ""
+
+msgid "SecurityReports|More information"
+msgstr ""
+
+msgid "SecurityReports|No vulnerabilities found"
+msgstr ""
+
+msgid "SecurityReports|No vulnerabilities found for this pipeline"
+msgstr ""
+
+msgid "SecurityReports|Oops, something doesn't seem right."
+msgstr ""
+
+msgid "SecurityReports|Project"
+msgstr ""
+
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
+msgid "SecurityReports|Projects added"
+msgstr ""
+
+msgid "SecurityReports|Remove project from dashboard"
+msgstr ""
+
+msgid "SecurityReports|Scan details"
+msgstr ""
+
+msgid "SecurityReports|Scanner"
+msgstr ""
+
+msgid "SecurityReports|Security Dashboard"
+msgstr ""
+
+msgid "SecurityReports|Security reports can only be accessed by authorized users."
+msgstr ""
+
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
+msgid "SecurityReports|Select a project to add by using the project search field above."
+msgstr ""
+
+msgid "SecurityReports|Select a reason"
+msgstr ""
+
+msgid "SecurityReports|Severity"
+msgstr ""
+
+msgid "SecurityReports|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "SecurityReports|Status"
+msgstr ""
+
+msgid "SecurityReports|The rating \"unknown\" indicates that the underlying scanner doesn’t contain or provide a severity rating."
+msgstr ""
+
+msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
+msgstr ""
+
+msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Select \"Edit dashboard\" to add and remove projects."
+msgstr ""
+
+msgid "SecurityReports|The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityReports|There was an error adding the comment."
+msgstr ""
+
+msgid "SecurityReports|There was an error creating the issue."
+msgstr ""
+
+msgid "SecurityReports|There was an error creating the merge request."
+msgstr ""
+
+msgid "SecurityReports|There was an error deleting the comment."
+msgstr ""
+
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SecurityReports|There was an error dismissing the vulnerabilities."
+msgstr ""
+
+msgid "SecurityReports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "SecurityReports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "SecurityReports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityReports|There was an error while generating the report."
+msgstr ""
+
+msgid "SecurityReports|To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
+msgstr ""
+
+msgid "SecurityReports|Unable to add %{invalidProjects}"
+msgstr ""
+
+msgid "SecurityReports|Undo dismiss"
+msgstr ""
+
+msgid "SecurityReports|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 reviewer(s)"
+msgstr ""
+
+msgid "Select shards to replicate"
+msgstr ""
+
+msgid "Select source"
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select start date"
+msgstr ""
+
+msgid "Select status"
+msgstr ""
+
+msgid "Select strategy activation method"
+msgstr ""
+
+msgid "Select subscription"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the 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 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 "Serenity Valley Sample Data template."
+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 ID"
+msgstr ""
+
+msgid "Session duration (minutes)"
+msgstr ""
+
+msgid "Set %{epic_ref} as the parent epic."
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
+msgid "Set a default 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 limit to 0 to allow any file size."
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set milestone"
+msgstr ""
+
+msgid "Set new password"
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set parent epic to an epic"
+msgstr ""
+
+msgid "Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set target branch"
+msgstr ""
+
+msgid "Set target branch to %{branch_name}."
+msgstr ""
+
+msgid "Set the default 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 a hardware device as a second factor to sign in."
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up new device"
+msgstr ""
+
+msgid "Set up new password"
+msgstr ""
+
+msgid "Set up pipeline subscriptions for this project."
+msgstr ""
+
+msgid "Set up shared runner availability"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "Set 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 "Setting this to 0 means using the system default timeout value."
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Settings related to the use and experience of using GitLab's Package Registry."
+msgstr ""
+
+msgid "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 "SeverityWidget|Severity"
+msgstr ""
+
+msgid "SeverityWidget|Severity: %{severity}"
+msgstr ""
+
+msgid "SeverityWidget|There was an error while updating severity."
+msgstr ""
+
+msgid "Shards (%{shards})"
+msgstr ""
+
+msgid "Shards to synchronize"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the %{strong_open}GitLab single sign-on URL%{strong_close} with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
+msgid "Shared runners help link"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
+msgid "Show Runner installation instructions"
+msgstr ""
+
+msgid "Show all activity"
+msgstr ""
+
+msgid "Show all issues."
+msgstr ""
+
+msgid "Show all members"
+msgstr ""
+
+msgid "Show all requirements."
+msgstr ""
+
+msgid "Show all test cases."
+msgstr ""
+
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Show comments on this file"
+msgstr ""
+
+msgid "Show comments only"
+msgstr ""
+
+msgid "Show commit description"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show details"
+msgstr ""
+
+msgid "Show file browser"
+msgstr ""
+
+msgid "Show file contents"
+msgstr ""
+
+msgid "Show 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 the Closed list"
+msgstr ""
+
+msgid "Show the Open list"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Showing %{count} of %{total} projects"
+msgstr ""
+
+msgid "Showing %{count} project"
+msgid_plural "Showing %{count} projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Showing %{limit} of %{total_count} issues. "
+msgstr ""
+
+msgid "Showing %{pageSize} of %{total} issues"
+msgstr ""
+
+msgid "Showing all issues"
+msgstr ""
+
+msgid "Showing graphs based on events of the last %{timerange} days."
+msgstr ""
+
+msgid "Showing last %{size} of log -"
+msgstr ""
+
+msgid "Showing latest version"
+msgstr ""
+
+msgid "Showing version #%{versionNumber}"
+msgstr ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Assign health status"
+msgstr ""
+
+msgid "Sidebar|Health status"
+msgstr ""
+
+msgid "Sidebar|No status"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in to GitLab"
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign in with smart card"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-in text"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "SignUp|First Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Last Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too short (minimum is %{min_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
+msgid "Signing in using %{label} has been disabled"
+msgstr ""
+
+msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgstr ""
+
+msgid "Similar issues"
+msgstr ""
+
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
+msgid "Single or combined queries"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Size limit per repository (MB)"
+msgstr ""
+
+msgid "Size settings for static websites"
+msgstr ""
+
+msgid "Skip outdated deployment jobs"
+msgstr ""
+
+msgid "Skipped"
+msgstr ""
+
+msgid "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|Files"
+msgstr ""
+
+msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
+msgstr ""
+
+msgid "Snippets|Optionally add a description about what your snippet does or how to use it…"
+msgstr ""
+
+msgid "Snowplow"
+msgstr ""
+
+msgid "Solution"
+msgstr ""
+
+msgid "Some changes are not shown"
+msgstr ""
+
+msgid "Some child epics may be hidden due to applied filters"
+msgstr ""
+
+msgid "Some common domains are not allowed. %{read_more_link}."
+msgstr ""
+
+msgid "Some email servers do not support overriding the email sender name. Enable this option to include the name of the author of the issue, merge request or comment in the email body instead."
+msgstr ""
+
+msgid "Some of the designs you tried uploading did not change:"
+msgstr ""
+
+msgid "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|Blocking"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Expired date"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Manual"
+msgstr ""
+
+msgid "SortOptions|Milestone due date"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest starred"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Project"
+msgstr ""
+
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Recently starred"
+msgstr ""
+
+msgid "SortOptions|Relevant"
+msgstr ""
+
+msgid "SortOptions|Size"
+msgstr ""
+
+msgid "SortOptions|Sort by:"
+msgstr ""
+
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Type"
+msgstr ""
+
+msgid "SortOptions|Version"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source Branch"
+msgstr ""
+
+msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
+msgstr ""
+
+msgid "Source code (%{fileExtension})"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Source project cannot be found."
+msgstr ""
+
+msgid "Sourcegraph"
+msgstr ""
+
+msgid "SourcegraphAdmin|Block on private and internal projects"
+msgstr ""
+
+msgid "SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects."
+msgstr ""
+
+msgid "SourcegraphAdmin|Enable Sourcegraph"
+msgstr ""
+
+msgid "SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance's code views and merge requests."
+msgstr ""
+
+msgid "SourcegraphAdmin|If checked, only public projects will have code intelligence and communicate with Sourcegraph."
+msgstr ""
+
+msgid "SourcegraphAdmin|More information"
+msgstr ""
+
+msgid "SourcegraphAdmin|Save changes"
+msgstr ""
+
+msgid "SourcegraphAdmin|Sourcegraph URL"
+msgstr ""
+
+msgid "SourcegraphAdmin|e.g. https://sourcegraph.example.com"
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental and currently limited to certain projects."
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental and limited to public projects."
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental."
+msgstr ""
+
+msgid "SourcegraphPreferences|Uses %{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 "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 Time"
+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 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|A link to view the merge request will appear once ready."
+msgstr ""
+
+msgid "StaticSiteEditor|An error occurred while submitting your changes."
+msgstr ""
+
+msgid "StaticSiteEditor|Branch could not be created."
+msgstr ""
+
+msgid "StaticSiteEditor|Copy update"
+msgstr ""
+
+msgid "StaticSiteEditor|Could not commit the content changes."
+msgstr ""
+
+msgid "StaticSiteEditor|Could not create merge request."
+msgstr ""
+
+msgid "StaticSiteEditor|Creating your merge request"
+msgstr ""
+
+msgid "StaticSiteEditor|Incompatible file content"
+msgstr ""
+
+msgid "StaticSiteEditor|Return to site"
+msgstr ""
+
+msgid "StaticSiteEditor|Static site editor"
+msgstr ""
+
+msgid "StaticSiteEditor|The Static Site Editor is currently configured to only edit Markdown content on pages generated from Middleman. Visit the documentation to learn more about configuring your site to use the Static Site Editor."
+msgstr ""
+
+msgid "StaticSiteEditor|To see your changes live you will need to do the following things:"
+msgstr ""
+
+msgid "StaticSiteEditor|Update %{sourcePath} file"
+msgstr ""
+
+msgid "StaticSiteEditor|View documentation"
+msgstr ""
+
+msgid "StaticSiteEditor|You can set an assignee to get your changes reviewed and deployed once your merge request is created."
+msgstr ""
+
+msgid "StaticSiteEditor|Your merge request has been created"
+msgstr ""
+
+msgid "Statistics"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Status was retried."
+msgstr ""
+
+msgid "Status:"
+msgstr ""
+
+msgid "Status: %{title}"
+msgstr ""
+
+msgid "StatusPage|AWS Secret access key"
+msgstr ""
+
+msgid "StatusPage|AWS access key ID"
+msgstr ""
+
+msgid "StatusPage|AWS documentation"
+msgstr ""
+
+msgid "StatusPage|AWS region"
+msgstr ""
+
+msgid "StatusPage|Active"
+msgstr ""
+
+msgid "StatusPage|Bucket %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|Configure file storage settings to link issues in this project to an external status page."
+msgstr ""
+
+msgid "StatusPage|For help with configuration, visit %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|S3 Bucket name"
+msgstr ""
+
+msgid "StatusPage|Status page"
+msgstr ""
+
+msgid "StatusPage|Status page URL"
+msgstr ""
+
+msgid "StatusPage|Status page frontend documentation"
+msgstr ""
+
+msgid "StatusPage|To publish incidents to an external status page, GitLab will store a JSON file in your Amazon S3 account in a location accessible to your external status page service. Make sure to also set up %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|configuration documentation"
+msgstr ""
+
+msgid "StatusPage|your status page frontend."
+msgstr ""
+
+msgid "Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments."
+msgstr ""
+
+msgid "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 a review"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit changes"
+msgstr ""
+
+msgid "Submit changes..."
+msgstr ""
+
+msgid "Submit feedback"
+msgstr ""
+
+msgid "Submit issue"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Submit the current review."
+msgstr ""
+
+msgid "Submit your changes"
+msgstr ""
+
+msgid "Submitted the current review."
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Subscribed to this %{quick_action_target}."
+msgstr ""
+
+msgid "Subscribes to this %{quick_action_target}."
+msgstr ""
+
+msgid "Subscription"
+msgstr ""
+
+msgid "Subscription deletion failed."
+msgstr ""
+
+msgid "Subscription successfully applied to \"%{group_name}\""
+msgstr ""
+
+msgid "Subscription successfully created."
+msgstr ""
+
+msgid "Subscription successfully deleted."
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|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 approved"
+msgstr ""
+
+msgid "Successfully blocked"
+msgstr ""
+
+msgid "Successfully confirmed"
+msgstr ""
+
+msgid "Successfully deactivated"
+msgstr ""
+
+msgid "Successfully deleted U2F device."
+msgstr ""
+
+msgid "Successfully deleted WebAuthn device."
+msgstr ""
+
+msgid "Successfully removed email."
+msgstr ""
+
+msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
+msgstr ""
+
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
+msgid "Successfully unblocked"
+msgstr ""
+
+msgid "Successfully unlocked"
+msgstr ""
+
+msgid "Successfully verified domain ownership"
+msgstr ""
+
+msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
+msgstr ""
+
+msgid "Suggested Solutions"
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Suggested solutions help link"
+msgstr ""
+
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
+msgid "Suggestion is not applicable as the suggestion was not found."
+msgstr ""
+
+msgid "Suggestions are not applicable as one or more suggestions were not found."
+msgstr ""
+
+msgid "Suggestions are not applicable as their lines cannot overlap."
+msgstr ""
+
+msgid "Suggestions must all be on the same branch."
+msgstr ""
+
+msgid "Suggestions:"
+msgstr ""
+
+msgid "Suite"
+msgstr ""
+
+msgid "Summary"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "Support page URL"
+msgstr ""
+
+msgid "Survey Response"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy the file contents"
+msgstr ""
+
+msgid "Symbolic link"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "Sync now"
+msgstr ""
+
+msgid "Synced"
+msgstr ""
+
+msgid "Synchronization disabled"
+msgstr ""
+
+msgid "Syncing…"
+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 "System output"
+msgstr ""
+
+msgid "Table of Contents"
+msgstr ""
+
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
+
+msgid "Tag name"
+msgstr ""
+
+msgid "Tag name is required"
+msgstr ""
+
+msgid "Tag 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 "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 settings"
+msgstr ""
+
+msgid "TestCases|New Test Case"
+msgstr ""
+
+msgid "TestCases|New test case"
+msgstr ""
+
+msgid "TestCases|Search test cases"
+msgstr ""
+
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
+msgid "TestCases|Something went wrong while creating a test case."
+msgstr ""
+
+msgid "TestCases|Something went wrong while fetching count of test cases."
+msgstr ""
+
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
+msgid "TestCases|Something went wrong while fetching test cases list."
+msgstr ""
+
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
+msgid "TestCases|Submit test case"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has deployments."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
+msgid "TestReports|%{count} errors"
+msgstr ""
+
+msgid "TestReports|%{count} failures"
+msgstr ""
+
+msgid "TestReports|%{count} tests"
+msgstr ""
+
+msgid "TestReports|%{rate}%{sign} success rate"
+msgstr ""
+
+msgid "TestReports|Jobs"
+msgstr ""
+
+msgid "TestReports|Tests"
+msgstr ""
+
+msgid "TestReports|There are no test cases to display."
+msgstr ""
+
+msgid "TestReports|There are no test suites to show."
+msgstr ""
+
+msgid "TestReports|There are no tests to show."
+msgstr ""
+
+msgid "TestReports|There was an error fetching the summary."
+msgstr ""
+
+msgid "TestReports|There was an error fetching the test suite."
+msgstr ""
+
+msgid "Tests"
+msgstr ""
+
+msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
+msgstr ""
+
+msgid "Thank you for your business."
+msgstr ""
+
+msgid "Thank you for your feedback!"
+msgstr ""
+
+msgid "Thank you for your report. A GitLab administrator will look into it shortly."
+msgstr ""
+
+msgid "Thank you for your support request! We are tracking your request as ticket #%{issue_iid}, and will respond as soon as we can."
+msgstr ""
+
+msgid "Thanks for your purchase!"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "That's it, well done!"
+msgstr ""
+
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
+msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgstr ""
+
+msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
+msgstr ""
+
+msgid "The %{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 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
+msgid "The URL defined on the primary node that secondary nodes should use to contact it."
+msgstr ""
+
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
+msgstr ""
+
+msgid "The 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 Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
+msgid "The following items will NOT be exported:"
+msgstr ""
+
+msgid "The following items will be exported:"
+msgstr ""
+
+msgid "The following personal access token: %{token_names} was revoked, because a new policy to expire personal access tokens were set."
+msgid_plural "The following personal access tokens: %{token_names} were revoked, because a new policy to expire personal access tokens were set."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The form contains the following 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 ""
+
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
+
+msgid "The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "The group can be fully restored"
+msgstr ""
+
+msgid "The group export can be downloaded from:"
+msgstr ""
+
+msgid "The group has already been shared with this group"
+msgstr ""
+
+msgid "The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}."
+msgstr ""
+
+msgid "The group will be placed in 'pending removal' state"
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The invitation could not be accepted."
+msgstr ""
+
+msgid "The invitation could not be declined."
+msgstr ""
+
+msgid "The invitation has already been accepted."
+msgstr ""
+
+msgid "The invitation was successfully resent."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The 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 project can be accessed by any logged in user except external users."
+msgstr ""
+
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
+msgid "The project was successfully forked."
+msgstr ""
+
+msgid "The project was successfully imported."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
+msgid "The remote repository is being updated..."
+msgstr ""
+
+msgid "The repository can be committed to, and issues, comments and other entities can be created."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository is being updated..."
+msgstr ""
+
+msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close} or %{code_open}git://%{code_close}."
+msgstr ""
+
+msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} or %{code_open}git://%{code_close}."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
+msgid "The schedule time must be in the future!"
+msgstr ""
+
+msgid "The snippet can be accessed without any authentication."
+msgstr ""
+
+msgid "The snippet is visible only to me."
+msgstr ""
+
+msgid "The snippet is visible only to project members."
+msgstr ""
+
+msgid "The snippet is visible to any logged in user except external users."
+msgstr ""
+
+msgid "The specified tab is invalid, please select another"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The status of the table below only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The uploaded file 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 approve is not pending an approval"
+msgstr ""
+
+msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "The value of the provided variable exceeds the %{count} character limit"
+msgstr ""
+
+msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
+msgstr ""
+
+msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
+msgstr ""
+
+msgid "There are currently no events."
+msgstr ""
+
+msgid "There are merge conflicts"
+msgstr ""
+
+msgid "There are no %{replicableTypeName} to show"
+msgstr ""
+
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no archived requirements"
+msgstr ""
+
+msgid "There are no archived test cases"
+msgstr ""
+
+msgid "There are no changes"
+msgstr ""
+
+msgid "There are no charts configured for this page"
+msgstr ""
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no commits yet."
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no issues to show."
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no matching files"
+msgstr ""
+
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no open requirements"
+msgstr ""
+
+msgid "There are no open test cases"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no variables yet."
+msgstr ""
+
+msgid "There 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 ""
+
+msgid "There is no chart data available."
+msgstr ""
+
+msgid "There is no data available."
+msgstr ""
+
+msgid "There is no data available. Please change your selection."
+msgstr ""
+
+msgid "There is no table data available."
+msgstr ""
+
+msgid "There is too much data to calculate. Please change your selection."
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem fetching branches."
+msgstr ""
+
+msgid "There was a problem fetching groups."
+msgstr ""
+
+msgid "There was a problem fetching labels."
+msgstr ""
+
+msgid "There was a problem fetching milestones."
+msgstr ""
+
+msgid "There was a problem fetching project branches."
+msgstr ""
+
+msgid "There was a problem fetching project tags."
+msgstr ""
+
+msgid "There was a problem fetching project users."
+msgstr ""
+
+msgid "There was a problem fetching 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 paths are protected for POST requests."
+msgstr ""
+
+msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgstr ""
+
+msgid "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, and will permanently delete the %{key} SSH key"
+msgstr ""
+
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgstr ""
+
+msgid "This action has been performed too many times. Try again later."
+msgstr ""
+
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgstr ""
+
+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 %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
+msgid "This block is self-referential"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
+msgid "This comment has changed since you started editing, please review the %{startTag}updated comment%{endTag} to ensure information is not lost."
+msgstr ""
+
+msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
+msgstr ""
+
+msgid "This commit was signed with a %{strong_open}verified%{strong_close} signature and the committer email is verified to belong to the same user."
+msgstr ""
+
+msgid "This commit was signed with a <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 a self-managed instance of GitLab."
+msgstr ""
+
+msgid "This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "This is the number of 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:"
+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 has previously committed to the %{name} project."
+msgstr ""
+
+msgid "This user has the %{access} role in the %{name} project."
+msgstr ""
+
+msgid "This user is the author of this %{noteable}."
+msgstr ""
+
+msgid "This 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|All Environments"
+msgstr ""
+
+msgid "ThreatMonitoring|Anomalous Requests"
+msgstr ""
+
+msgid "ThreatMonitoring|Application firewall not detected"
+msgstr ""
+
+msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
+msgstr ""
+
+msgid "ThreatMonitoring|Container Network Policy"
+msgstr ""
+
+msgid "ThreatMonitoring|Container NetworkPolicies not detected"
+msgstr ""
+
+msgid "ThreatMonitoring|Dropped Packets"
+msgstr ""
+
+msgid "ThreatMonitoring|Environment"
+msgstr ""
+
+msgid "ThreatMonitoring|No environments detected"
+msgstr ""
+
+msgid "ThreatMonitoring|Operations Per Second"
+msgstr ""
+
+msgid "ThreatMonitoring|Packet Activity"
+msgstr ""
+
+msgid "ThreatMonitoring|Policies"
+msgstr ""
+
+msgid "ThreatMonitoring|Requests"
+msgstr ""
+
+msgid "ThreatMonitoring|Show last"
+msgstr ""
+
+msgid "ThreatMonitoring|Something went wrong, unable to fetch environments"
+msgstr ""
+
+msgid "ThreatMonitoring|Something went wrong, unable to fetch statistics"
+msgstr ""
+
+msgid "ThreatMonitoring|Statistics"
+msgstr ""
+
+msgid "ThreatMonitoring|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 "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Timeout connecting to the Google API. Please try again."
+msgstr ""
+
+msgid "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 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 %{docs_link}. This can be changed at any time in %{settings_link}."
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To 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 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 ""
+
+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 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 select"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "Toggle the Performance Bar"
+msgstr ""
+
+msgid "Toggle this dialog"
+msgstr ""
+
+msgid "Toggle thread"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Toggled :%{name}: emoji award."
+msgstr ""
+
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
+msgid "Token valid until revoked"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Too many namespaces enabled. You will need to manage them via the console or the API."
+msgstr ""
+
+msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgstr ""
+
+msgid "Too much data"
+msgstr ""
+
+msgid "Topics (optional)"
+msgstr ""
+
+msgid "Total"
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Score"
+msgstr ""
+
+msgid "Total artifacts size: %{total_size}"
+msgstr ""
+
+msgid "Total cores (CPUs)"
+msgstr ""
+
+msgid "Total days to completion"
+msgstr ""
+
+msgid "Total issues"
+msgstr ""
+
+msgid "Total memory (GB)"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total users"
+msgstr ""
+
+msgid "Total weight"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "TotalMilestonesIndicator|1000+"
+msgstr ""
+
+msgid "TotalRefCountIndicator|1000+"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Track your GitLab projects with GitLab for Slack."
+msgstr ""
+
+msgid "Track your project with Audit Events."
+msgstr ""
+
+msgid "Transfer"
+msgstr ""
+
+msgid "Transfer ownership"
+msgstr ""
+
+msgid "Transfer project"
+msgstr ""
+
+msgid "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|Create a new group to start your GitLab Gold trial."
+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 can apply your trial to a new group or an existing group."
+msgstr ""
+
+msgid "Trials|You can apply your trial to a new group or your personal account."
+msgstr ""
+
+msgid "Trials|You can apply your trial to a new group, an existing group, or your personal account."
+msgstr ""
+
+msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgstr ""
+
+msgid "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 needed) and press the button on the device now."
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
+msgid "Tuesday"
+msgstr ""
+
+msgid "Tuning settings"
+msgstr ""
+
+msgid "Turn Off"
+msgstr ""
+
+msgid "Turn On"
+msgstr ""
+
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-Factor Authentication code"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Type/State"
+msgstr ""
+
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
+msgid "URL"
+msgstr ""
+
+msgid "URL is required"
+msgstr ""
+
+msgid "URL must start with %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, or %{codeStart}ftp://%{codeEnd}"
+msgstr ""
+
+msgid "URL of the external Spam Check endpoint"
+msgstr ""
+
+msgid "URL of the external storage that will serve the repository static objects (e.g. archives, blobs, ...)."
+msgstr ""
+
+msgid "URL or request ID"
+msgstr ""
+
+msgid "USER %{user} WILL BE REMOVED! Are you sure?"
+msgstr ""
+
+msgid "USER WILL BE BLOCKED! Are you sure?"
+msgstr ""
+
+msgid "UTC"
+msgstr ""
+
+msgid "Unable to apply suggestions to a deleted line."
+msgstr ""
+
+msgid "Unable to build Slack link."
+msgstr ""
+
+msgid "Unable to collect CPU info"
+msgstr ""
+
+msgid "Unable to collect memory info"
+msgstr ""
+
+msgid "Unable to connect to Elasticsearch"
+msgstr ""
+
+msgid "Unable to connect to Prometheus server"
+msgstr ""
+
+msgid "Unable to connect to server: %{error}"
+msgstr ""
+
+msgid "Unable to connect to the Jira instance. Please check your Jira integration configuration."
+msgstr ""
+
+msgid "Unable to convert Kubernetes logs encoding to UTF-8"
+msgstr ""
+
+msgid "Unable to fetch unscanned projects"
+msgstr ""
+
+msgid "Unable to fetch vulnerable projects"
+msgstr ""
+
+msgid "Unable to find Jira project to import data from."
+msgstr ""
+
+msgid "Unable to generate new instance ID"
+msgstr ""
+
+msgid "Unable to load commits. Try again later."
+msgstr ""
+
+msgid "Unable to load file contents. Try again later."
+msgstr ""
+
+msgid "Unable to load the diff"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to load the merge request widget. Try reloading the page."
+msgstr ""
+
+msgid "Unable to save iteration. Please try again"
+msgstr ""
+
+msgid "Unable to save your changes. Please try again."
+msgstr ""
+
+msgid "Unable to save your preference"
+msgstr ""
+
+msgid "Unable to schedule a pipeline to run immediately"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to suggest a path. Please refresh and try again."
+msgstr ""
+
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Unable to update this issue at this time."
+msgstr ""
+
+msgid "Unarchive project"
+msgstr ""
+
+msgid "Unarchiving the project will restore 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 "Unexpected error"
+msgstr ""
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
+msgid "Uninstall"
+msgstr ""
+
+msgid "Uninstalling"
+msgstr ""
+
+msgid "Units|ms"
+msgstr ""
+
+msgid "Units|s"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unknown Error"
+msgstr ""
+
+msgid "Unknown cache key"
+msgstr ""
+
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
+msgid "Unless otherwise agreed to in writing with GitLab, by clicking \"Upload License\" you agree that your use of GitLab Software is subject to the %{eula_link_start}Terms of Service%{eula_link_end}."
+msgstr ""
+
+msgid "Unlimited"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock the discussion"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unlocked the discussion."
+msgstr ""
+
+msgid "Unlocks the discussion."
+msgstr ""
+
+msgid "Unmarked this %{noun} as 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 username"
+msgstr ""
+
+msgid "Update variable"
+msgstr ""
+
+msgid "Update your bookmarked URLs as filtered/sorted branches URL has been changed."
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Update your project name, topics, description and avatar."
+msgstr ""
+
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{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|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|Increase storage temporarily"
+msgstr ""
+
+msgid "UsageQuota|LFS Objects"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Purchase more storage"
+msgstr ""
+
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
+msgid "UsageQuota|Repositories"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Snippets"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage of resources across your projects"
+msgstr ""
+
+msgid "UsageQuota|Usage quotas help link"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
+msgid "UsageQuota|Wikis"
+msgstr ""
+
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
+msgid "UsageQuota|You used: %{usage} %{limit}"
+msgstr ""
+
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
+msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
+msgstr ""
+
+msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
+msgid "Use 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 ID"
+msgstr ""
+
+msgid "User OAuth applications"
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User identity was successfully created."
+msgstr ""
+
+msgid "User identity was successfully removed."
+msgstr ""
+
+msgid "User identity was successfully updated."
+msgstr ""
+
+msgid "User is not allowed to resolve thread"
+msgstr ""
+
+msgid "User key was successfully removed."
+msgstr ""
+
+msgid "User list %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
+msgid "User restrictions"
+msgstr ""
+
+msgid "User settings"
+msgstr ""
+
+msgid "User was successfully created."
+msgstr ""
+
+msgid "User was successfully removed from group and any subresources."
+msgstr ""
+
+msgid "User was successfully removed from project."
+msgstr ""
+
+msgid "User was successfully updated."
+msgstr ""
+
+msgid "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|Bot activity"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|No snippets found."
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|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 or email"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Users in License"
+msgstr ""
+
+msgid "Users in License:"
+msgstr ""
+
+msgid "Users or groups set as approvers in the project's or merge request's settings."
+msgstr ""
+
+msgid "Users over License:"
+msgstr ""
+
+msgid "Users 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 "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 "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 "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{days}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
+msgstr ""
+
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
+msgid "Variable"
+msgstr ""
+
+msgid "Variable will be masked in job logs."
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "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 alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
+msgid "View all issues"
+msgstr ""
+
+msgid "View blame prior to this change"
+msgstr ""
+
+msgid "View chart"
+msgid_plural "View charts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "View dependency details for your project"
+msgstr ""
+
+msgid "View deployment"
+msgstr ""
+
+msgid "View details"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View eligible approvers"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View exposed artifact"
+msgid_plural "View %d exposed artifacts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View file @ %{commitSha}"
+msgstr ""
+
+msgid "View 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 "Visualization"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
+msgid "Vulnerabilities over time"
+msgstr ""
+
+msgid "Vulnerability Report"
+msgstr ""
+
+msgid "Vulnerability remediated. Review before resolving."
+msgstr ""
+
+msgid "Vulnerability resolved in %{branch}"
+msgstr ""
+
+msgid "Vulnerability resolved in the default branch"
+msgstr ""
+
+msgid "Vulnerability-Check"
+msgstr ""
+
+msgid "VulnerabilityChart|%{formattedStartDate} to today"
+msgstr ""
+
+msgid "VulnerabilityChart|Severity"
+msgstr ""
+
+msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
+msgstr ""
+
+msgid "VulnerabilityManagement|%{statusStart}Detected%{statusEnd} %{timeago} in pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "VulnerabilityManagement|%{statusStart}Dismissed%{statusEnd} %{timeago} by %{user}"
+msgstr ""
+
+msgid "VulnerabilityManagement|%{statusStart}Resolved%{statusEnd} %{timeago} by %{user}"
+msgstr ""
+
+msgid "VulnerabilityManagement|A true-positive and will fix"
+msgstr ""
+
+msgid "VulnerabilityManagement|Change status"
+msgstr ""
+
+msgid "VulnerabilityManagement|Could not process %{issueReference}: %{errorMessage}."
+msgstr ""
+
+msgid "VulnerabilityManagement|Detected"
+msgstr ""
+
+msgid "VulnerabilityManagement|Needs triage"
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to refresh the vulnerability. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to retrieve the vulnerability history. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to save the comment. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong, could not get user."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
+msgstr ""
+
+msgid "VulnerabilityManagement|Verified as fixed or mitigated"
+msgstr ""
+
+msgid "VulnerabilityManagement|Will not fix or a false-positive"
+msgstr ""
+
+msgid "VulnerabilityManagement|invalid issue link or ID"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|All"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Confirmed"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Detected"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Dismissed"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Resolved"
+msgstr ""
+
+msgid "Vulnerability|%{scannerName} (version %{scannerVersion})"
+msgstr ""
+
+msgid "Vulnerability|Activity"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Comments"
+msgstr ""
+
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|Detected"
+msgstr ""
+
+msgid "Vulnerability|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 the pipeline header."
+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 find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
+msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We have found the following errors:"
+msgstr ""
+
+msgid "We heard back from your device. You have been authenticated."
+msgstr ""
+
+msgid "We recommend that you buy more Pipeline minutes to avoid any interruption of service."
+msgstr ""
+
+msgid "We recommend that you buy more Pipeline minutes to resume normal service."
+msgstr ""
+
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "We will notify %{inviter} that you declined their invitation to join GitLab. You will stop receiving reminders."
+msgstr ""
+
+msgid "We would like to inform you that your subscription GitLab Enterprise Edition %{plan_name} is nearing its user limit. You have %{active_user_count} active users, which is almost at the user limit of %{maximum_user_count}."
+msgstr ""
+
+msgid "We've found no vulnerabilities"
+msgstr ""
+
+msgid "Web Application Firewall"
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web Terminal"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "WebAuthn Devices (%{length})"
+msgstr ""
+
+msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
+msgid "WebIDE|Merge request"
+msgstr ""
+
+msgid "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|Feature Flag events"
+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 is triggered when a deployment starts, finishes, fails, or is canceled"
+msgstr ""
+
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
+msgstr ""
+
+msgid "Webhooks|This URL 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 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 "What are you searching for?"
+msgstr ""
+
+msgid "What describes you best?"
+msgstr ""
+
+msgid "What is squashing?"
+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} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
+msgstr ""
+
+msgid "When enabled, any user visiting %{host} will be able to create an account."
+msgstr ""
+
+msgid "When enabled, if an NPM package isn't found in the GitLab Registry, we will attempt to pull from the global NPM registry."
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "When 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 "With test cases, you can define conditions for your project to meet in determining quality"
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Won't fix / Accept risk"
+msgstr ""
+
+msgid "Work in progress (open and unassigned)"
+msgstr ""
+
+msgid "Work in progress Limit"
+msgstr ""
+
+msgid "Would you like to create a new branch?"
+msgstr ""
+
+msgid "Would you like to try auto-generating a branch name?"
+msgstr ""
+
+msgid "Write"
+msgstr ""
+
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write a comment…"
+msgstr ""
+
+msgid "Write access allowed"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
+msgid "Write your release notes or drag your files here…"
+msgstr ""
+
+msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
+msgstr ""
+
+msgid "YYYY-MM-DD"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes or No"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, close issue"
+msgstr ""
+
+msgid "Yes, delete project"
+msgstr ""
+
+msgid "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 namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
+msgid "You are not allowed to approve a user"
+msgstr ""
+
+msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
+msgstr ""
+
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
+msgid "You are not authorized to perform this action"
+msgstr ""
+
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
+msgid "You are now impersonating %{username}"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
+msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
+msgstr ""
+
+msgid "You are using PostgreSQL %{pg_version_current}, but PostgreSQL %{pg_version_minimum} is required for this version of GitLab. Please upgrade your environment to a supported PostgreSQL version, see %{pg_requirements_url} for details."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
+msgid "You can also press ⌘-Enter"
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}"
+msgstr ""
+
+msgid "You can also upload existing files from your computer using the instructions below."
+msgstr ""
+
+msgid "You can always edit this later"
+msgstr ""
+
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
+msgstr ""
+
+msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
+msgstr ""
+
+msgid "You can create new ones at your %{pat_link_start}Personal Access Tokens%{pat_link_end} settings"
+msgstr ""
+
+msgid "You can create new ones at your Personal Access Tokens settings %{pat_link}"
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can 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 find more information about GitLab subscriptions in %{subscriptions_doc_link}."
+msgstr ""
+
+msgid "You can generate an access token scoped to this project for each application to use the GitLab API."
+msgstr ""
+
+msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
+msgstr ""
+
+msgid "You can group test cases using labels. To learn about the future direction of this feature, visit %{linkStart}Quality Management direction page%{linkEnd}."
+msgstr ""
+
+msgid "You can invite a new member to %{project_name} or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to %{project_name}."
+msgstr ""
+
+msgid "You can invite another group to %{project_name}."
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can notify the app / group or a project by sending them an email notification"
+msgstr ""
+
+msgid "You can now close this window."
+msgstr ""
+
+msgid "You can now export your security dashboard to a CSV report."
+msgstr ""
+
+msgid "You can now 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 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 WebAuthn devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You don't have any deployments right now."
+msgstr ""
+
+msgid "You don't have any open merge requests"
+msgstr ""
+
+msgid "You don't have any projects available."
+msgstr ""
+
+msgid "You don't have any recent searches"
+msgstr ""
+
+msgid "You don't have sufficient permission to perform this action."
+msgstr ""
+
+msgid "You don't have write access to the source branch."
+msgstr ""
+
+msgid "You don’t have access to Productivity Analytics in this group"
+msgstr ""
+
+msgid "You don’t have access to Value Stream Analytics for this group"
+msgstr ""
+
+msgid "You have a license that activates at a future date. Please see the License History table below."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{member_human_access} access to %{title} %{name}."
+msgstr ""
+
+msgid "You have been invited"
+msgstr ""
+
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
+msgid "You have been unsubscribed from this thread."
+msgstr ""
+
+msgid "You have declined the invitation to join %{title} %{name}."
+msgstr ""
+
+msgid "You have imported from this project %{numberOfPreviousImports} times before. Each new import will create duplicate issues."
+msgstr ""
+
+msgid "You have insufficient permissions to create a Todo for this alert"
+msgstr ""
+
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have not added any approvers. Start by adding users or groups."
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
+msgstr ""
+
+msgid "You haven't added any issues to your project yet"
+msgstr ""
+
+msgid "You haven't selected any issues yet"
+msgstr ""
+
+msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
+msgstr ""
+
+msgid "You may close the milestone now."
+msgstr ""
+
+msgid "You must be logged in to search across all of GitLab"
+msgstr ""
+
+msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You must have permission to create a project in a group before forking."
+msgstr ""
+
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
+msgid "You must select a stack for configuring your cloud provider. Learn more about"
+msgstr ""
+
+msgid "You must set up incoming email before it becomes active."
+msgstr ""
+
+msgid "You must upload a file with the same file name when dropping onto an existing design."
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You need to be logged in."
+msgstr ""
+
+msgid "You need to register a two-factor authentication app before you can set up a device."
+msgstr ""
+
+msgid "You need to set terms to be enforced"
+msgstr ""
+
+msgid "You need to specify both an Access Token and a Host URL."
+msgstr ""
+
+msgid "You need to upload a GitLab project export archive (ending in .gz)."
+msgstr ""
+
+msgid "You need to upload a Google Takeout archive."
+msgstr ""
+
+msgid "You successfully declined the invitation"
+msgstr ""
+
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
+msgid "You will be removed from existing projects/groups"
+msgstr ""
+
+msgid "You will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "You will first need to set up Jira Integration to use this feature."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all uncommitted changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will need to update your local repositories to point to the new location."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to create new projects because you have reached your project limit."
+msgstr ""
+
+msgid "You won't be able to pull or push 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 "YouTube URL or ID"
+msgstr ""
+
+msgid "Your %{host} account was signed in to from a new location"
+msgstr ""
+
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
+msgstr ""
+
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
+msgstr ""
+
+msgid "Your CSV export has started. It will be emailed to %{email} when complete."
+msgstr ""
+
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
+msgstr ""
+
+msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
+msgstr ""
+
+msgid "Your 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 Token was revoked"
+msgstr ""
+
+msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
+msgstr ""
+
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH key was deleted"
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
+msgid "Your To-Do List"
+msgstr ""
+
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
+msgid "Your U2F device was registered!"
+msgstr ""
+
+msgid "Your WebAuthn device did not send a valid JSON response."
+msgstr ""
+
+msgid "Your WebAuthn device was registered!"
+msgstr ""
+
+msgid "Your access request to the %{source_type} has been withdrawn."
+msgstr ""
+
+msgid "Your account has been deactivated by your administrator. Please log back in to reactivate your account."
+msgstr ""
+
+msgid "Your account is locked."
+msgstr ""
+
+msgid "Your account uses dedicated credentials for the \"%{group_name}\" group and can only be updated through SSO."
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
+msgid "Your browser doesn't support WebAuthn. Please use a supported browser, e.g. Chrome (67+) or Firefox (60+)."
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your changes have been successfully committed."
+msgstr ""
+
+msgid "Your comment could not be submitted because %{error}"
+msgstr ""
+
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment will be discarded."
+msgstr ""
+
+msgid "Your custom stage '%{title}' was created"
+msgstr ""
+
+msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
+msgstr ""
+
+msgid "Your dashboard has been updated. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
+msgstr ""
+
+msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
+msgstr ""
+
+msgid "Your device is not compatible with GitLab. Please try another device"
+msgstr ""
+
+msgid "Your device needs to be set up. Plug it in (if needed) and click the button on the left."
+msgstr ""
+
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
+msgid "Your 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 "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 "cannot be a date in the past"
+msgstr ""
+
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be changed if shared runners are enabled"
+msgstr ""
+
+msgid "cannot be enabled because parent group does not allow it"
+msgstr ""
+
+msgid "cannot be enabled because parent group has shared Runners disabled"
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot be modified"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot contain HTML/XML tags, including any word between angle brackets (&lt;,&gt;)."
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
+msgid "cannot merge"
+msgstr ""
+
+msgid "child-pipeline"
+msgstr ""
+
+msgid "ciReport|%{degradedNum} degraded"
+msgstr ""
+
+msgid "ciReport|%{improvedNum} improved"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Coverage Fuzzing %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Secret Detection %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|%{sameNum} same"
+msgstr ""
+
+msgid "ciReport|(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"
+msgstr ""
+
+msgid "ciReport|Create a merge request to implement this solution, or download and apply the patch manually."
+msgstr ""
+
+msgid "ciReport|Create issue"
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Download patch to resolve"
+msgstr ""
+
+msgid "ciReport|Download the patch to apply it manually"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Fixed"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Found %{issuesWithCount}"
+msgstr ""
+
+msgid "ciReport|Investigate this vulnerability by creating an issue"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics: "
+msgstr ""
+
+msgid "ciReport|Load performance test metrics: No changes"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|New"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No code quality issues found"
+msgstr ""
+
+msgid "ciReport|RPS"
+msgstr ""
+
+msgid "ciReport|Resolve with merge request"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Secret Detection"
+msgstr ""
+
+msgid "ciReport|Secret scanning"
+msgstr ""
+
+msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|TTFB P90"
+msgstr ""
+
+msgid "ciReport|TTFB P95"
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error creating the merge request. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error fetching the codequality report."
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|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 "collect usage information"
+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 "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "exceeds the limit of %{bytes} bytes"
+msgstr ""
+
+msgid "exceeds the limit of %{bytes} bytes for directory name \"%{dirname}\""
+msgstr ""
+
+msgid "expired on %{timebox_due_date}"
+msgstr ""
+
+msgid "expires on %{timebox_due_date}"
+msgstr ""
+
+msgid "failed"
+msgstr ""
+
+msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
+msgstr ""
+
+msgid "failed to revert associated finding(id=%{finding_id}) to detected"
+msgstr ""
+
+msgid "file"
+msgid_plural "files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "finding is not found or is already attached to a vulnerability"
+msgstr ""
+
+msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
+msgstr ""
+
+msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}"
+msgstr ""
+
+msgid "for %{link_to_pipeline_ref}"
+msgstr ""
+
+msgid "for %{ref}"
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "fork 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 forbidden by a top-level group"
+msgstr ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not"
+msgstr ""
+
+msgid "is not a descendant of the Group owning the template"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
+msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
+msgstr ""
+
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
+msgid "is not an email you own"
+msgstr ""
+
+msgid "is not in the group enforcing Group Managed Account"
+msgstr ""
+
+msgid "is read only"
+msgstr ""
+
+msgid "is too long (%{current_value}). The maximum size is %{max_size}."
+msgstr ""
+
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
+msgid "is too long (maximum is 100 entries)"
+msgstr ""
+
+msgid "is too long (maximum is 1000 entries)"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
+msgid "issues at risk"
+msgstr ""
+
+msgid "issues need attention"
+msgstr ""
+
+msgid "issues on track"
+msgstr ""
+
+msgid "it is larger than %{limit}"
+msgstr ""
+
+msgid "it is stored as a job artifact"
+msgstr ""
+
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "jigsaw is not defined"
+msgstr ""
+
+msgid "kuromoji custom analyzer"
+msgstr ""
+
+msgid "last commit:"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "leave %{group_name}"
+msgstr ""
+
+msgid "less than a minute"
+msgstr ""
+
+msgid "level: %{level}"
+msgstr ""
+
+msgid "limit of %{project_limit} reached"
+msgstr ""
+
+msgid "load it anyway"
+msgstr ""
+
+msgid "loading"
+msgstr ""
+
+msgid "locked"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "log in"
+msgstr ""
+
+msgid "manual"
+msgstr ""
+
+msgid "math|The math in this entry is taking too long to render and may not be displayed as expected. For performance reasons, math blocks are also limited to %{maxChars} characters. Consider splitting up large formulae, splitting math blocks among multiple entries, or using an image instead."
+msgstr ""
+
+msgid "math|There was an error rendering this math block"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "merged %{timeAgo}"
+msgstr ""
+
+msgid "metric_id must be unique across a project"
+msgstr ""
+
+msgid "missing"
+msgstr ""
+
+msgid "more information"
+msgstr ""
+
+msgid "most recent deployment"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|Currently there are no changes in this merge request's source branch. Please push new commits or use a different branch."
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgstr ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
+msgid "mrWidget|%{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 a valid IPv4 or IPv6 address"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
+msgid "must contain only valid frameworks"
+msgstr ""
+
+msgid "my-awesome-group"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "need attention"
+msgstr ""
+
+msgid "needs to be between 10 minutes and 1 month"
+msgstr ""
+
+msgid "never"
+msgstr ""
+
+msgid "never expires"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "no approvers"
+msgstr ""
+
+msgid "no contributions"
+msgstr ""
+
+msgid "no expiration"
+msgstr ""
+
+msgid "no name set"
+msgstr ""
+
+msgid "no one can merge"
+msgstr ""
+
+msgid "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 "quick actions"
+msgstr ""
+
+msgid "recent activity"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
+msgid "relates to"
+msgstr ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "removed a Zoom call from this issue"
+msgstr ""
+
+msgid "rendered diff"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "repository:"
+msgstr ""
+
+msgid "reset it."
+msgstr ""
+
+msgid "revised"
+msgstr ""
+
+msgid "satisfied"
+msgstr ""
+
+msgid "security Reports|There was an error creating the merge request"
+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 "smartcn custom analyzer"
+msgstr ""
+
+msgid "sort:"
+msgstr ""
+
+msgid "source"
+msgstr ""
+
+msgid "source diff"
+msgstr ""
+
+msgid "specific"
+msgstr ""
+
+msgid "specified top is not part of the tree"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "ssh:"
+msgstr ""
+
+msgid "started"
+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 "triggered"
+msgstr ""
+
+msgid "two-factor authentication settings"
+msgstr ""
+
+msgid "unicode domains should use IDNA encoding"
+msgstr ""
+
+msgid "updated"
+msgstr ""
+
+msgid "updated %{timeAgo}"
+msgstr ""
+
+msgid "updated %{time_ago}"
+msgstr ""
+
+msgid "uploaded"
+msgstr ""
+
+msgid "uploads"
+msgstr ""
+
+msgid "user avatar"
+msgstr ""
+
+msgid "user preferences"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "v%{version} published %{timeAgo}"
+msgstr ""
+
+msgid "verify ownership"
+msgstr ""
+
+msgid "version %{versionIndex}"
+msgstr ""
+
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "view the blob"
+msgstr ""
+
+msgid "view the source"
+msgstr ""
+
+msgid "vulnerability|Add a comment"
+msgstr ""
+
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Save comment"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
+msgid "was scheduled to merge after pipeline succeeds by"
+msgstr ""
+
+msgid "wiki page"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "with expiry changing from %{old_expiry} to %{new_expiry}"
+msgstr ""
+
+msgid "with expiry remaining unchanged at %{old_expiry}"
+msgstr ""
+
+msgid "yaml invalid"
+msgstr ""
+
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index 030ac1308e7..febae209fa4 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-10-02 18:48\n"
+"PO-Revision-Date: 2020-11-03 22:49\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index fcf4129f398..5432a7763d1 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-10-02 18:44\n"
+"PO-Revision-Date: 2020-11-03 22:44\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -119,8 +119,8 @@ msgstr[1] ""
msgid "%d code quality issue"
msgid_plural "%d code quality issues"
-msgstr[0] "%d kodekvalitetsproblem"
-msgstr[1] "%d kodekvalitetsproblemer"
+msgstr[0] "%d kodekvalitetssak"
+msgstr[1] "%d kodekvalitetssaker"
msgid "%d comment"
msgid_plural "%d comments"
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] "%d mislyktes"
msgstr[1] "%d mislyktes"
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d fikset testresultat"
@@ -207,19 +212,14 @@ msgstr[1] "%d utilgjengelige fletteforespørsler"
msgid "%d issue"
msgid_plural "%d issues"
-msgstr[0] "%d problem"
-msgstr[1] "%d problemer"
+msgstr[0] "%d sak"
+msgstr[1] "%d saker"
msgid "%d issue in this group"
msgid_plural "%d issues in this group"
msgstr[0] "%d sak i denne gruppen"
msgstr[1] "%d saker i denne gruppen"
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d sak valgt"
-msgstr[1] "%d saker valgt"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] "%d sak vellykket importert med stemplet"
@@ -407,6 +407,16 @@ msgstr "%{count} godkjennelser fra %{name}"
msgid "%{count} files touched"
msgstr "%{count} filer berørt"
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr "%{count} mer"
@@ -447,6 +457,12 @@ msgstr "%{deployLinkStart}Bruke en mal for å distribuere til ECS%{deployLinkEnd
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr "%{due_date} (Forbi måldatoen)"
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr "%{host} pålogging fra nytt sted"
@@ -618,9 +640,6 @@ 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 "%{namespace_name} er nå skrivebeskyttet. Du kan ikke: %{base_message}"
-
msgid "%{name} contained %{resultsString}"
msgstr "%{name} inneholdt %{resultsString}"
@@ -718,8 +737,8 @@ msgstr[1] "%{reportType} %{status} oppdaget %{other} sårbarheter."
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr "%{reportType} %{status} oppdaget ingen sårbarheter."
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
-msgstr "%{retryButtonStart}Prøv igjen%{retryButtonEnd} eller %{newFileButtonStart}legg med en ny fil%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
+msgstr ""
msgid "%{seconds}s"
msgstr "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] "%{securityScanner}-resultatet er ikke tilgjengelig fordi en rørledning ikke er kjørt siden den ble aktivert. %{linkStart}Kjør en rørledning%{linkEnd}"
msgstr[1] "%{securityScanner}-resultater er ikke tilgjengelige fordi en rørledning ikke er kjørt siden den ble aktivert. %{linkStart}Kjør en rørledning%{linkEnd}"
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -762,7 +784,7 @@ msgid "%{start} to %{end}"
msgstr "%{start} til %{end}"
msgid "%{state} epics"
-msgstr "%{state} epics"
+msgstr "%{state} eposer"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr "%{strongStart}Sletter%{strongEnd} kildegrenen"
@@ -947,9 +969,6 @@ msgstr "(sjekk fremgang)"
msgid "(deleted)"
msgstr "(slettet)"
-msgid "(external source)"
-msgstr "(ekstern kilde)"
-
msgid "(line: %{startLine})"
msgstr "(linje: %{startLine})"
@@ -988,6 +1007,18 @@ msgstr[1] "+%d til"
msgid "+%{approvers} more approvers"
msgstr "+%{approvers} flere godkjennere"
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr "+%{tags} til"
@@ -1016,6 +1047,9 @@ msgstr "- av - vektlegging fullført"
msgid "- show less"
msgstr "- Vis mindre"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr "0 byte"
@@ -1025,15 +1059,8 @@ msgstr "0 for ubegrenset"
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "1 %{type}-tillegging"
-msgstr[1] "%{count} %{type}-tillegginger"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "1 %{type} modifikasjon"
-msgstr[1] "%{count} %{type} modifikasjoner"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1087,8 +1114,8 @@ msgstr[1] "%d minutter"
msgid "1 open issue"
msgid_plural "%{issues} open issues"
-msgstr[0] "1 åpent problem"
-msgstr[1] "%{issues} åpne problemer"
+msgstr[0] "1 åpen sak"
+msgstr[1] "%{issues} åpne saker"
msgid "1 open merge request"
msgid_plural "%{merge_requests} open merge requests"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr "API-hjelp"
@@ -1595,6 +1625,9 @@ msgstr "Legg til ny tabell"
msgid "Add a task list"
msgstr "Legg til en oppgaveliste"
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Legge til ekstra tekst som skal vises i all e-postkommunikasjon. Begrensningen er på %{character_limit} tegn"
@@ -1748,8 +1781,8 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr "La til %{label_references} %{label_text}."
-msgid "Added a To Do."
-msgstr "La til et gjøremål."
+msgid "Added a to do."
+msgstr ""
msgid "Added an issue to an epic."
msgstr "La til en sak i en epos."
@@ -1784,12 +1817,12 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr "Legger til %{labels} %{label_text}."
-msgid "Adds a To Do."
-msgstr "Legger til et gjøremål."
-
msgid "Adds a Zoom meeting"
msgstr "Legger til et Zoom-møte"
+msgid "Adds a to do."
+msgstr ""
+
msgid "Adds an issue to an epic."
msgstr "Legger til en sak i en epos."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr "Eier"
@@ -1898,6 +1934,9 @@ msgstr "Stopp jobber som mislyktes"
msgid "AdminArea|Total users"
msgstr "Totalt antall brukere"
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "Statistikk over brukere"
@@ -2012,6 +2051,21 @@ msgstr "SSH-nøkler"
msgid "AdminStatistics|Snippets"
msgstr "Utdrag"
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr "2FA er skrudd av"
@@ -2021,6 +2075,12 @@ msgstr "2FA er skrudd på"
msgid "AdminUsers|Access"
msgstr "Tilgang"
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr "Aktiv"
@@ -2033,12 +2093,30 @@ msgstr "Administratorer har tilgang til alle grupper, prosjekter og brukere og k
msgid "AdminUsers|Admins"
msgstr "Administratorer"
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr "Blokker"
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Blokker bruker"
@@ -2093,6 +2171,9 @@ msgstr "Benytter setet"
msgid "AdminUsers|It's you!"
msgstr "Det er deg!"
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr "Ny bruker"
@@ -2102,6 +2183,9 @@ msgstr "Ingen brukere ble funnet"
msgid "AdminUsers|Owned groups will be left"
msgstr "Eide grupper vil bli forlatt"
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr "Personlige prosjekter vil bli forlatt"
@@ -2147,6 +2231,9 @@ msgstr "Brukeren vil ikke kunne bruke skråstrek-kommandoer"
msgid "AdminUsers|The user will not receive any notifications"
msgstr "Brukeren vil ikke motta noen varsler"
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "For å bekrefte, skriv %{projectName}"
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr "Du kan ikke fjerne dine egne adminrettigheter."
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr "Administrasjon"
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr "Avansert"
@@ -2195,23 +2288,23 @@ msgstr "Avanserte innstillinger"
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "Avanserte tillatelser, stor fillagring, og 2-trinnsautentiseringsinnstillinger."
-msgid "Advanced search functionality"
-msgstr "Avansert søkefunksjonalitet"
-
msgid "After a successful password update you will be redirected to login screen."
msgstr "Etter en vellykket passordoppdatering vil du bli omdirigert til påloggingsskjermen."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Etter en vellykket passordoppdatering, vil du bli omdirigert til påloggingssiden der du kan logge på med ditt nye passord."
-msgid "After that, you will not to be able to use merge approvals or code quality as well as many other features."
-msgstr "Etter det, vil du ikke kunne bruke flettegodkjenninger eller kodekvalitet, så vel som mange andre funksjoner."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
-msgstr "Etter det vil du ikke kunne bruke flettegodkjenninger eller eposer, så vel som mange andre funksjoner."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
-msgstr "Etter det vil du ikke kunne bruke flettegodkjenninger eller eposer, så vel som mange andre sikkerhetsfunksjoner."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgstr ""
msgid "Alert"
msgid_plural "Alerts"
@@ -2275,12 +2368,12 @@ msgstr "Hendelser"
msgid "AlertManagement|High"
msgstr "Høy"
+msgid "AlertManagement|Incident"
+msgstr ""
+
msgid "AlertManagement|Info"
msgstr "Info"
-msgid "AlertManagement|Issue"
-msgstr "Sak"
-
msgid "AlertManagement|Key"
msgstr ""
@@ -2395,6 +2488,15 @@ msgstr "Gå gjennom dokumentasjonen til din eksterne tjeneste for å lære hvor
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 "Du må oppgi denne URL-en og autorisasjonsnøkkelen for å autorisere en ekstern tjeneste til å sende varsler til GitLab. Du kan oppgi denne URL-en og nøkkelen til flere tjenester. Etter at du har konfigurert en ekstern tjeneste, vises varsler fra tjenesten din på GitLab sin %{linkStart}Alarmer%{linkEnd}-side."
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr "API-URL"
@@ -2404,10 +2506,10 @@ msgstr "Aktiv"
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr "Legg til URL og autoriseringsnøkkel i din Prometheus-oppsettsfil"
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr "Kopier"
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr "Ekstern Prometheus"
-msgid "AlertSettings|Generic"
-msgstr "Generisk"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
-msgid "AlertSettings|Integrations"
-msgstr "Integreringer"
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
+msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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 "Gå gjennom dokumentasjonen til din eksterne tjeneste for å lære hvor du kan gi denne informasjonen til din eksterne tjeneste, og %{linkStart}GitLab-dokumentasjonen%{linkEnd} for å lære mer om å sette opp ditt endepunkt."
+msgid "AlertSettings|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,8 +2572,11 @@ 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 "Det oppstod en feil under oppdatering av alarminnstillingene"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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 "Det oppstod en feil under tilbakestilling av nøkkelen. Oppdater siden for å prøve igjen."
@@ -2473,8 +2593,8 @@ msgstr "Du kan nå sette opp varslings-endepunkter for manuelt konfigurerte Prom
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 "Du må oppgi denne URL-en og autorisasjonsnøkkelen for å autorisere en ekstern tjeneste til å sende varsler til GitLab. Du kan oppgi denne URL-en og nøkkelen til flere tjenester. Etter at du har konfigurert en ekstern tjeneste, vises varsler fra tjenesten din på GitLab sin %{linkStart}Alarmer%{linkEnd}-side."
-msgid "AlertSettings|Your changes were successfully updated."
-msgstr "Endringene dine ble vellykket oppdatert."
+msgid "AlertSettings|Your integration was successfully updated."
+msgstr ""
msgid "Alerts"
msgstr "Varsler"
@@ -2482,6 +2602,27 @@ msgstr "Varsler"
msgid "Alerts endpoint"
msgstr "Alarm-endepunkt"
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr "Algoritme"
@@ -2548,9 +2689,6 @@ msgstr "Alle sikkerhetsskanninger er aktivert fordi %{linkStart}Auto DevOps%{lin
msgid "All threads resolved"
msgstr "Alle tråder er oppklart"
-msgid "All users"
-msgstr "Alle brukere"
-
msgid "All users must have a name."
msgstr "Alle brukere må ha et navn."
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr "Tillat eiere å legge til brukere manuelt utenfor LDAP"
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "Tillat prosjekter innenfor denne gruppen å bruke Git LFS"
@@ -2596,6 +2737,9 @@ msgstr "Tillat forespørsler til det lokale nettverket fra systemkroker"
msgid "Allow requests to the local network from web hooks and services"
msgstr "Tillat forespørsler til det lokale nettverket fra Webhooks og tjenester"
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr "Tillatt"
msgid "Allowed Geo IP"
msgstr "Tillatt Geo-IP"
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr "Tillatt å mislykkes"
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Lar deg legge til og behandle Kubernetes-klynger."
@@ -2671,6 +2821,9 @@ msgstr "En %{link_start}alarm%{link_end} med samme fingeravtrykk er allerede åp
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr "En administrator endret passordet til GitLab-kontoen din på %{link_to}."
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr "En alarm har blitt utløst i %{project_path}."
@@ -2683,9 +2836,15 @@ 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 "Et tomt GitLab-brukerfelt vil legge til FogBugz-brukerens fulle navn (f.eks. \"Av John Smith\") i beskrivelsen av alle saker og kommentarer. Det vil også knytte og/eller tildele disse sakene og kommentarene til prosjektskaperen."
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "En feil har oppstått"
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr "Det oppstod en feil under innhenting av prosjektskaperne."
msgid "An error occurred previewing the blob"
msgstr "En feil oppstod under forhåndsvisning av blobben"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "En feil oppstod under veksling av varslingsabonnement"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "En feil oppstod under oppdatering av saksvektleggingen"
@@ -2803,9 +2968,6 @@ msgstr "Det oppstod en feil under innhenting av terraformingsrapporter."
msgid "An error occurred while fetching the Service Desk address."
msgstr "Det oppstod en feil under innhenting av Service Desk-adressen."
-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 ""
@@ -2878,9 +3040,6 @@ msgstr "En feil oppstod under innlasting av saker"
msgid "An error occurred while loading merge requests."
msgstr "Det oppstod en feil under innlasting av fletteforespørsler."
-msgid "An error occurred while loading milestones"
-msgstr "En feil oppstod under innlasting av milepæler"
-
msgid "An error occurred while loading project creation UI"
msgstr "En feil oppstod under innlasting av prosjektopprettings-grensesnittet"
@@ -2911,9 +3070,6 @@ msgstr "En feil oppstod under innlasting av fletteforespørselsen."
msgid "An error occurred while loading the pipelines jobs."
msgstr "En feil oppstod under innhenting av rørledningsjobbene."
-msgid "An error occurred while loading the subscription details."
-msgstr "Det oppstod en feil under innlasting av abonnementsdetaljene."
-
msgid "An error occurred while making the request."
msgstr "Det oppsto en feil under forespørselsforsøket."
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr "En feil oppstod under rendring av redigereren"
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr "En feil oppstod under omsortering av saker."
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr "En feil oppstod under lagring av tilordnede"
-msgid "An error occurred while searching for milestones"
-msgstr "En feil oppstod under søking etter milepæler"
-
msgid "An error occurred while subscribing to notifications."
msgstr "En feil oppstod under abonnering på varsler."
@@ -2980,6 +3136,9 @@ msgstr "En feil oppstod under avabonnering på varsler."
msgid "An error occurred while updating approvers"
msgstr "En feil oppstod under oppdatering av godkjennere"
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr "Arkiver jobber"
msgid "Archive project"
msgstr "Arkiver prosjekt"
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr "Arkivert"
@@ -3325,7 +3487,7 @@ msgid "Archived projects"
msgstr "Arkiverte prosjekter"
msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end}"
-msgstr "Arkivering av prosjektet vil gjøre det helt skrivebeskyttet. Den er skjult fra kontrollpanelet og vises ikke i søk. %{strong_start}Datalageret kan ikke motta commiter, og ingen problemer, kommentarer eller andre enheter kan opprettes.%{strong_end}"
+msgstr "Arkivering av prosjektet vil gjøre det helt skrivebeskyttet. Den er skjult fra kontrollpanelet og vises ikke i søk. %{strong_start}Datalageret kan ikke motta commiter, og ingen saker, kommentarer eller andre enheter kan opprettes.%{strong_end}"
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr "Er du HELT SIKKER på at du vil slette dette prosjektet?"
@@ -3546,7 +3708,7 @@ msgid "Assigned %{assignee_users_sentence}."
msgstr ""
msgid "Assigned Issues"
-msgstr "Tilegnede rapporter"
+msgstr "Tilegnede saker"
msgid "Assigned Merge Requests"
msgstr "Tilordnede fletteforespørsel"
@@ -3557,6 +3719,9 @@ msgstr "Tilordnet til %{assigneeName}"
msgid "Assigned to %{assignee_name}"
msgstr "Tilordnet til %{assignee_name}"
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr "Tilordnet meg"
@@ -3801,8 +3966,29 @@ msgstr "Den vil automatisk bygge, teste og distribuere applikasjonen din basert
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Lær mer i %{link_to_documentation}"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "Auto DevOps-rørledningen har blitt aktivert og vil bli brukt hvis ingen alternative CI-konfigurasjonsfiler blir funnet. %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr "Automatisk fullføring"
@@ -3822,6 +4008,9 @@ msgstr "Automatisk sertifikatshåndtering med %{lets_encrypt_link_start}Let's En
msgid "Automatic certificate management using Let's Encrypt"
msgstr "Automatisk sertifikatshåndtering med Let's Encrypt"
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr "Tilgjengelig"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr "Merkebilde nettadresse"
msgid "Badges|Badge image preview"
msgstr "Forhåndsvisning av merkebilde"
-msgid "Badges|Delete badge"
-msgstr "Slett merket"
-
msgid "Badges|Delete badge?"
msgstr "Slette badge?"
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr "Kontakt salgsavdelingen"
msgid "BillingPlan|Upgrade"
msgstr "Oppgrader"
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr "Bitbucket-tjenerimportering"
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr "Utvid"
msgid "Boards|View scope"
msgstr "Vis omfang"
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr "Grenen %{branchName} ble ikke funnet i dette prosjektet sitt kodelager."
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 "%{branch_name}-grenen ble opprettet. For å konfigurere automatisk distribusjon, velg en GitLab CI Yaml-mal og foreta endringene dine. %{link_to_autodeploy_doc}"
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr "prosjektinnstillinger"
msgid "Branches|protected"
msgstr "beskyttet"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr "Innebygget"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,8 +4602,8 @@ msgstr "Av %{user_name}"
msgid "By URL"
msgstr "Etter URL"
-msgid "By clicking Register, I agree that I have read and accepted the GitLab %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr "Ved å klikke Registrer, godtar jeg at jeg har lest og godtatt GitLab sine %{linkStart}bruksvilkår og personvernregler%{linkEnd}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
+msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "Som standard sender GitLab e-post i HTML- og rentekst-formater slik at e-postklienter kan velge hvilket format de skal bruke. Deaktiver dette alternativet hvis du bare vil sende e-post i rentekstformat."
@@ -4548,6 +4785,9 @@ msgstr "Kan ikke opprette misbruksrapporten. Brukeren har blitt blokkert."
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr "Kan ikke ha flere Jira-importeringer som kjører samtidig"
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr "Velg %{strong_open}Opprett arkiv%{strong_close} og vent til arkivering er fullført."
@@ -5142,9 +5385,6 @@ msgstr "Alle miljøer"
msgid "CiVariable|Create wildcard"
msgstr "Opprett jokertegn"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr "Maskert"
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr "Veksle beskyttelsesstatus"
-msgid "CiVariable|Validation failed"
-msgstr "Validering mislyktes"
-
msgid "Classification Label (optional)"
msgstr "Klassifiseringsetikett (valgfritt)"
@@ -5206,13 +5443,13 @@ msgid "Clear templates search input"
msgstr ""
msgid "Clear weight"
-msgstr "Tøm vekt"
+msgstr "Tøm vektlegging"
msgid "Cleared weight."
-msgstr "Tømte vekt."
+msgstr "Tømte vektleggingen."
msgid "Clears weight."
-msgstr "Tømmer vekten."
+msgstr "Tømmer vektleggingen."
msgid "Click the %{strong_open}Download%{strong_close} button and wait for downloading to complete."
msgstr "Klikk på %{strong_open}Last ned%{strong_close}-knappen og vent til nedlastingen er fullført."
@@ -5274,6 +5511,9 @@ msgstr "Lukk %{tabname}"
msgid "Close epic"
msgstr "Lukk epos"
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr "Lukk milepæl"
@@ -5293,13 +5533,13 @@ msgid "Closed epics"
msgstr "Lukkede eposer"
msgid "Closed issues"
-msgstr "Lukkede rapporter"
+msgstr "Lukkede saker"
msgid "Closed this %{quick_action_target}."
msgstr "Lukket denne %{quick_action_target}."
-msgid "Closed: %{closedIssuesCount}"
-msgstr "Lukket: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
+msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "Lukker denne %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr "Klynge-nivå"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ msgstr "Klarte ikke å laste inn instanstyper"
msgid "ClusterIntegration|Could not load networks"
msgstr "Klarte ikke å laste inn nettverk"
-msgid "ClusterIntegration|Could not load regions from your AWS account"
-msgstr "Kunne ikke laste inn regioner fra AWS-kontoen din"
-
msgid "ClusterIntegration|Could not load security groups for the selected VPC"
msgstr "Kunne ikke laste inn sikkerhetsgrupper for den valgte VPC-en"
@@ -5823,9 +6066,6 @@ msgstr "Lær mer om %{help_link_start_machine_type}maskintyper%{help_link_end} o
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "Lær mer om %{help_link_start}soner%{help_link_end}."
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr "Lær mer om Kubernetes"
@@ -5841,9 +6081,6 @@ msgstr "Laster inn IAM-roller"
msgid "ClusterIntegration|Loading Key Pairs"
msgstr "Laster inn nøkkelpar"
-msgid "ClusterIntegration|Loading Regions"
-msgstr "Laster inn regioner"
-
msgid "ClusterIntegration|Loading VPCs"
msgstr "Laster inn VPC-er"
@@ -5910,9 +6147,6 @@ msgstr "Ingen prosjekter funnet"
msgid "ClusterIntegration|No projects matched your search"
msgstr "Ingen prosjekter samsvarte med søket ditt"
-msgid "ClusterIntegration|No region found"
-msgstr "Ingen region funnet"
-
msgid "ClusterIntegration|No security group found"
msgstr "Ingen sikkerhetsgruppe funnet"
@@ -5979,9 +6213,6 @@ msgstr "Les vår %{link_start}hjelpeside%{link_end} om Kubernetes-klyngeintegras
msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "ClusterIntegration|Region"
-msgstr "Region"
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Fjern Kubernetes-klyngeintegrasjon"
@@ -6048,9 +6279,6 @@ msgstr "Søk blant nettverk"
msgid "ClusterIntegration|Search projects"
msgstr "Søk blant prosjekter"
-msgid "ClusterIntegration|Search regions"
-msgstr "Søk blant regioner"
-
msgid "ClusterIntegration|Search security groups"
msgstr "Søk blant sikkerhetsgrupper"
@@ -6111,6 +6339,9 @@ msgstr "Velg prosjekt for å velge sone"
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr "Velg sone"
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr "Velg en VPC"
msgid "ClusterIntergation|Select a network"
msgstr "Velg et nettverk"
-msgid "ClusterIntergation|Select a region"
-msgstr "Velg en region"
-
msgid "ClusterIntergation|Select a security group"
msgstr "Velg en sikkerhetsgruppe"
@@ -6450,9 +6681,6 @@ msgstr ""
msgid "ComboSearch is not defined"
msgstr "ComboSearch er ikke definert"
-msgid "Coming soon"
-msgstr "Kommer snart"
-
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
msgstr "Kommaseparert, f.eks. '1.1.1.1, 2.2.2.0/24'"
@@ -6764,7 +6992,7 @@ msgstr "Confluence"
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr "Tilkoblingen ble tidsavbrutt"
msgid "Connection timeout"
msgstr "Tidsavbrudd på tilkobling"
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr "Kontakt salgsavdelingen for å oppgradere"
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr "Kopier til utklippstavle"
@@ -7319,6 +7556,9 @@ msgstr "Klarte ikke å slette chat-kallenavnet %{chat_name}."
msgid "Could not delete wiki page"
msgstr "Klarte ikke å slette wiki-side"
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr "Klarte ikke å finne designet."
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr "Klarte ikke å fjerne trigger."
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr "Land"
@@ -7418,7 +7664,7 @@ msgid "Create a new file as there are no files yet. Afterwards, you'll be able t
msgstr "Opprett en ny fil siden det ikke er noen filer ennå. Etterpå vil du kunne utføre endringene dine."
msgid "Create a new issue"
-msgstr "Opprett et nytt problem"
+msgstr "Opprett et nytt sak"
msgid "Create a new repository"
msgstr "Opprett et nytt kodelager"
@@ -7609,6 +7855,9 @@ msgstr "Opprettet fletteforespørselen %{mergeRequestLink} hos %{projectLink}"
msgid "Created on"
msgstr "Opprettet den"
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr "Opprettet den:"
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr "Tilpasset vertsnavn (for private commit-e-poster)"
@@ -7953,6 +8205,9 @@ msgstr "Oppgaver etter type"
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ msgstr "%{firstProject}, %{rest}, og %{secondProject}"
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr "Er du sikker på at du vil slette profilen?"
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr "Klarte ikke å oppdatere nettstedsprofilen. Vennligst prøv igjen."
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr "Vil du forkaste denne skannerprofilen?"
@@ -8070,6 +8340,12 @@ msgstr "Rediger nettstedsprofilen"
msgid "DastProfiles|Error Details"
msgstr "Detaljer om feilen"
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr "Behandle profiler"
@@ -8097,15 +8373,15 @@ msgstr "Ingen profiler er opprettet enda"
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 "Profilnavn"
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr "Skannerprofil"
msgid "DastProfiles|Scanner Profiles"
msgstr "Skanner-profiler"
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr "Nettstedsprofil"
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr "Valider"
@@ -8172,6 +8454,12 @@ msgstr "Validerer …"
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr "Slett kommentar"
-msgid "Delete Snippet"
-msgstr "Slett utdraget"
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr "Slett konto"
msgid "Delete artifacts"
msgstr "Slett artefakter"
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr "Slett tavle"
@@ -8364,9 +8655,6 @@ msgstr "Slett stempel"
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr "Slett liste"
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr "Vil du slette utvalget?"
msgid "Delete source branch"
msgstr "Slett kildegrenen"
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr "Slett dette vedlegget"
@@ -8451,12 +8742,18 @@ msgstr "Avslått"
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr "Avvis"
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr "Avhengigheter"
@@ -8505,18 +8802,27 @@ msgstr "Eksporter som JSON"
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr "Lisens"
msgid "Dependencies|Location"
msgstr "Sted"
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr "Innpakker"
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr "Utstasjonert"
msgid "Deployed to"
msgstr "Utstasjonert til"
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr "Beskrivelse"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr "DevOps"
msgid "DevOps Report"
msgstr "DevOps-rapport"
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr "Dokumentasjon"
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr "Domene"
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr "Ikke inkluder beskrivelsen i commit-meldingen"
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr "Ikke lim inn den private delen av GPG-nøkkelen. Lim inn den offentlige delen som begynner med ' -----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "Ikke vis igjen"
@@ -9236,9 +9578,6 @@ msgstr "Last ned som"
msgid "Download as CSV"
msgstr "Last ned som CSV"
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr "Last ned koder"
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr "Rediger trinn"
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr "Rediger denne utgivelsen"
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr "Rediger wiki-side"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr "Redigert %{timeago}"
@@ -9488,6 +9836,9 @@ msgstr "E-post sendt"
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr "Skru på integrering"
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "Skru på vedlikeholdsmodus"
@@ -9656,7 +10013,19 @@ msgstr "Skru på mellomtjener"
msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared Runners"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "Slutter den (UTC)"
@@ -9728,8 +10100,11 @@ msgstr "Skriv inn IP-adresseområde"
msgid "Enter a number"
msgstr "Skriv inn et nummer"
-msgid "Enter a whole number between 0 and 100"
-msgstr "Skriv inn et helt tall mellom 0 og 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
+msgstr ""
msgid "Enter at least three characters to search"
msgstr "Skriv inn minst tre tegn for å søke"
@@ -9768,7 +10143,7 @@ msgid "Enter the issue description"
msgstr "Skriv inn sakens beskrivelse"
msgid "Enter the issue title"
-msgstr "Skriv inn problemets tittel"
+msgstr "Skriv inn sakstittelen"
msgid "Enter the merge request description"
msgstr ""
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr "Ekskludert innflettings-commiter. Begrenset til %{limit} commiter."
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "Ekskludert innflettings-commiter. Begrenset til 6 000 commiter."
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr "Eksisterende greinnavn, etikett, eller commit-SHA"
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr "Utvid godkjennere"
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr "Utvid milepæler"
@@ -10601,6 +10985,9 @@ msgstr "Eksporter gruppe"
msgid "Export issues"
msgstr "Eksporter saker"
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "Eksporter prosjekt"
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr "Mislyktes i å opprette kodelager"
@@ -10766,6 +11156,9 @@ msgstr "Mislyktes i å laste inn stempler. Vennligst prøv igjen."
msgid "Failed to load milestones. Please try again."
msgstr "Mislyktes i å laste inn milepæler. Vennligst prøv igjen."
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr "Klarte ikke å laste inn relaterte grener"
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] "%d bruker"
msgstr[1] "%d brukere"
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr "* (Alle miljøer)"
@@ -10945,6 +11353,9 @@ msgstr "Sett opp"
msgid "FeatureFlags|Configure feature flags"
msgstr "Sett opp funksjonsflagg"
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr "Opprett funksjonsflagg"
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 "Sett Unleash-klientapplikasjonsnavnet til navnet på miljøet som applikasjonen kjører i. Denne verdien brukes til å samsvare med miljøomfang. Se %{linkStart}eksempelklientoppsettet%{linkEnd}."
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr "Brukerliste"
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr "Prosentandel"
msgid "FeatureFlag|Select a user list"
msgstr "Velg en brukerliste"
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr "Det er ingen oppsatte brukerlister"
@@ -11134,6 +11551,9 @@ msgstr "Type"
msgid "FeatureFlag|User IDs"
msgstr "Bruker-ID-er"
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "Feb"
@@ -11191,12 +11611,18 @@ msgstr "Fil-maler"
msgid "File upload error."
msgstr "Filopplastingsfeil."
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "Filer"
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr "Filtrer etter stempel"
@@ -11284,6 +11713,9 @@ msgstr "Filter..."
msgid "Find File"
msgstr "Finn fil"
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr "Fullført"
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr "Fornavnet er for langt (Maksgrensen er %{max_length} tegn)."
-
msgid "First Seen"
msgstr "Først sett"
@@ -11329,9 +11758,15 @@ msgstr "Første dagen i uken"
msgid "First name"
msgstr "Fornavn"
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr "Først sett"
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr "Fast dato"
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ msgstr "Ã… sette i gang med utgivelser"
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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr "Git-versjon"
@@ -11989,9 +12427,6 @@ msgstr ""
msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
msgstr "GitLab-tjenestedesken er en enkel måte å la folk opprette saksrapporter i din GitLab-forekomst uten å behøve sin egen brukerkonto. Det sørger for en unik e-postadresse for sluttbrukere til å opprette saksrapporter i et prosjekt, og svar kan sendes enten via GitLab-grensesnittet eller via e-post. Sluttbrukere vil bare se tråden via e-post."
-msgid "GitLab 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 ""
@@ -12016,6 +12451,12 @@ msgstr "GitLab-eksport"
msgid "GitLab for Slack"
msgstr "GitLab for Slack"
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr "GÃ¥ til dine prosjekter"
msgid "Go to your snippets"
msgstr "GÃ¥ til utdragene dine"
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,8 +12877,8 @@ msgstr "Gruppe-URL"
msgid "Group avatar"
msgstr "Gruppeavatar"
-msgid "Group by:"
-msgstr "Gruppe av:"
+msgid "Group by"
+msgstr ""
msgid "Group description"
msgstr "Gruppebeskrivelse"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "Sertifikat-fingeravtrykk"
@@ -12601,6 +13051,9 @@ msgstr "Oppsett"
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr "Standardrolle for nye brukere"
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr "Forby ytre utgreininger"
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr "Din SCIM-sjetong"
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "Historie"
@@ -13163,9 +13646,6 @@ msgstr "Hvordan oppgraderer man"
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr "Du er imidlertid allerede et medlem av denne %{member_source}. Logg på med en annen konto for å godta invitasjonen."
-msgid "I accept the %{terms_link_start}Terms of Service and Privacy Policy%{terms_link_end}"
-msgstr ""
-
msgid "I accept the %{terms_link}"
msgstr "Jeg aksepterer %{terms_link}"
@@ -13178,7 +13658,7 @@ msgstr "Jeg glemte passordet mitt"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
-msgid "I'd like to receive updates via email about GitLab"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,12 +13814,12 @@ msgstr "Ignorer"
msgid "Ignored"
msgstr "Ignorert"
-msgid "Image Details"
-msgstr "Bildedetaljer"
-
msgid "Image URL"
msgstr "Bilde URL"
+msgid "Image details"
+msgstr ""
+
msgid "ImageDiffViewer|2-up"
msgstr ""
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr "Importer prosjekt"
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr "Importer prosjektmedlemmer"
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr "Alle"
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr "Utilordnet"
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr "Upublisert"
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr "Skriv inn din kodelager-URL"
-msgid "Insert"
-msgstr "Sett inn"
-
msgid "Insert a code block"
msgstr "Sett inn en kodeblokk"
msgid "Insert a quote"
msgstr "Sett inn et sitat"
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr "Sett inn et bilde"
msgid "Insert code"
msgstr "Sett inn kode"
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr "Sett inn forslag"
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr "Innsikter"
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 "Installer en myksjetongautentikator som %{free_otp_link} eller Google Autentisering fra applikasjonskodelageret ditt og bruk den appen til å skanne QR-koden. Mer informasjon er tilgjengelig i dokumentasjonen %{help_link_start}%{help_link_end}."
@@ -13778,6 +14312,51 @@ msgstr "Instansstatistikker"
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr "Inkluderer commit-tittelen og grenen"
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr "Standard "
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr "Bruk tilpassede innstillinger"
msgid "Integrations|Use default settings"
msgstr "Bruk forvalgte innstillinger"
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
msgid "Internal"
msgstr "Intern"
-msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr "Intern URL (valgfritt)"
msgid "Internal users"
msgstr "Interne brukere"
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr "Ugyldig OS"
msgid "Invalid URL"
msgstr "Ugyldig URL"
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,26 +14627,26 @@ msgstr "Inviter medlem"
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
-msgstr "%{inviter} inviterte deg"
+msgid "Invite your team"
+msgstr ""
+
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
-msgstr "%{project_or_group} som en %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
+msgstr ""
msgid "InviteEmail|Join now"
msgstr "Bli med nå"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
+msgstr ""
+
msgid "InviteEmail|You are invited!"
msgstr "Du har blitt invitert!"
-msgid "InviteEmail|You have been invited"
-msgstr "Du har blitt invitert"
-
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
-msgstr "til å bli med i %{project_or_group_name} %{project_or_group} som en %{role}"
-
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
-msgstr "Til å bli med i %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
msgstr "Samarbeid med teamet ditt"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr "Invitert"
@@ -14120,6 +14795,9 @@ msgstr "Saksanalyse"
msgid "Issue Boards"
msgstr "Problemvegger"
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr "Jan"
msgid "January"
msgstr "januar"
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr "Jira-saker"
@@ -14373,7 +15054,7 @@ msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{proj
msgstr ""
msgid "JiraService|Displaying Jira issues while leaving the GitLab issue functionality enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used."
-msgstr "Å vise Jira-saker mens GitLab-saksfunksjonaliteten er aktivert, kan være forvirrende. Vurder å %{linkStart}deaktivere GitLab-problemer%{linkEnd} hvis de ikke ellers blir brukt."
+msgstr "Å vise Jira-saker mens GitLab-saksfunksjonaliteten er aktivert, kan være forvirrende. Vurder å %{linkStart}deaktivere GitLab-saker%{linkEnd} hvis de ikke ellers blir brukt."
msgid "JiraService|Enable Jira issues"
msgstr "Skru på Jira-saker"
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr "Kerberos-tilgang ble nektet"
@@ -14609,6 +15293,12 @@ msgstr "Tastatursnarveier"
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr "Nøkler"
@@ -14738,9 +15428,6 @@ 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 "Å forfremme %{labelTitle} vil gjøre den tilgjengelig for alle prosjekter innenfor %{groupName}. Eksisterende prosjektstempler med samme tittel vil bli slått sammen. Hvis det finnes et gruppestempel med samme tittel, blir den også slått sammen. Denne handlingen kan ikke reverseres."
-msgid "Labels|and %{count} more"
-msgstr "and %{count} til"
-
msgid "Language"
msgstr "Språk"
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr "Nyeste rørledning"
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr "Etternavn"
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr "Siste svar fra"
@@ -14836,6 +15523,9 @@ msgstr "Sist oppdatert"
msgid "Last used"
msgstr "Sist brukt"
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr "Senest brukt:"
@@ -14881,6 +15571,9 @@ msgstr "Lær hvordan man aktiverer synkronisering"
msgid "Learn more"
msgstr "Lær mer"
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr "Lær mer om Auto DevOps"
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr "Forlat zenmodus"
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr "Mar"
msgid "March"
msgstr "mars"
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr "Marker som ferdig"
@@ -15516,6 +16209,9 @@ msgstr "Merk denne saken som et duplikat av en annet sak"
msgid "Mark this issue as related to another issue"
msgstr "Merk denne saken som relatert til en annen sak"
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr "Markdown"
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr "Medlemslås"
msgid "Member since %{date}"
msgstr "Medlem siden %{date}"
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr "Medlemmer"
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr "Minneforbruk"
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr "Innflettet denne fletteforespørselen."
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr "Lukket:"
@@ -16747,9 +17551,15 @@ msgstr "Multi-prosjekt"
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr "Navnefeltet er tomt"
msgid "Namespace:"
msgstr "Navneområde:"
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr "Navnerom"
@@ -17062,6 +17900,9 @@ msgstr "Aldri"
msgid "New"
msgstr "Ny"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr "Ny applikasjon"
@@ -17091,8 +17932,8 @@ msgstr "Ny identitet"
msgid "New Issue"
msgid_plural "New Issues"
-msgstr[0] "Nytt problem"
-msgstr[1] "Nye problemer"
+msgstr[0] "Ny sak"
+msgstr[1] "Nye saker"
msgid "New Jira import"
msgstr "Ny Jira-import"
@@ -17173,7 +18014,7 @@ msgid "New identity"
msgstr "Ny identitet"
msgid "New issue"
-msgstr "Nytt problem"
+msgstr "Ny sak"
msgid "New issue title"
msgstr "Tittel på den nye saken"
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr "Ingen"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr "Ikke implementert"
@@ -17556,9 +18400,6 @@ msgstr "Ikke nok data"
msgid "Not found."
msgstr "Ikke funnet."
-msgid "Not now"
-msgstr "Ikke nå"
-
msgid "Not ready yet. Try again later."
msgstr "Ikke klar enda. Prøv igjen senere."
@@ -17793,6 +18634,9 @@ msgstr "OmniAuth"
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 "Omnibus Protected Paths-pedalen er aktiv, og prioriterer disse innstillingene. Fra 12.4, avvikles Omnibus-pedalen og vil bli fjernet i en fremtidig utgivelse. Les dokumentasjonen for %{relative_url_link_start}Migrering av beskyttede filbaner%{relative_url_link_end}."
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr "Kjør skanning"
msgid "OnDemandScans|Scanner profile"
msgstr ""
-msgid "OnDemandScans|Scanner settings"
-msgstr "Skannerinnstillinger"
-
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
@@ -17850,9 +18691,6 @@ msgstr "Velg en av de eksisterende profilene"
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr "Nettstedsprofiler"
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,20 +18810,14 @@ msgstr "Ã…pne i filvisning"
msgid "Open issues"
msgstr "Ã…pne saker"
-msgid "Open projects"
-msgstr "Ã…pne prosjekter"
-
msgid "Open raw"
msgstr "Åpne råversjon"
msgid "Open sidebar"
msgstr "Ã…pne sidelinje"
-msgid "Open: %{openIssuesCount}"
-msgstr "Ã…pen: %{openIssuesCount}"
-
-msgid "Open: %{open} • Closed: %{closed}"
-msgstr "Åpen: %{open} • Lukket: %{closed}"
+msgid "Open: %{open}"
+msgstr ""
msgid "Opened"
msgstr "Ã…pnet"
@@ -17997,7 +18829,7 @@ msgid "Opened MRs"
msgstr ""
msgid "Opened issues"
-msgstr "Ã…pnede problemer"
+msgstr "Ã…pnede saker"
msgid "OpenedNDaysAgo|Opened"
msgstr "Ã…pnet"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr "Legg til NuGet-kilde"
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr "Appgruppe: %{group}"
@@ -18254,8 +19089,8 @@ 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 "Mangler din favorittpakkebehandler? Vi vil gjerne hjelpe deg med å bygge førsteklasses støtte til den i GitLab! %{contributionLinkStart}Gå til bidragsdokumentasjonen%{contributionLinkEnd} for å lære mer om hvordan du bygger støtte for nye pakkebehandlere i GitLab. Nedenfor er en liste over pakkebehandlere som er på radaren vår."
+msgid "PackageRegistry|Install package version"
+msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -18278,9 +19113,6 @@ msgstr "Maven-XML"
msgid "PackageRegistry|NPM"
msgstr "NPM"
-msgid "PackageRegistry|No upcoming issues"
-msgstr "Ingen kommende saker"
-
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -18302,8 +19134,8 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
-msgstr "PyPi"
+msgid "PackageRegistry|PyPI"
+msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
@@ -18326,9 +19158,6 @@ msgstr ""
msgid "PackageRegistry|There are no packages yet"
msgstr "Det er ingen pakker enda"
-msgid "PackageRegistry|There are no upcoming issues to display."
-msgstr "Det er ingen kommende saker å vise."
-
msgid "PackageRegistry|There was a problem fetching the details for this package."
msgstr ""
@@ -18344,9 +19173,6 @@ msgstr ""
msgid "PackageRegistry|Unable to load package"
msgstr "Klarte ikke å laste inn pakke"
-msgid "PackageRegistry|Upcoming package managers"
-msgstr "Kommende pakkebehandlere"
-
msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
msgstr ""
@@ -18356,12 +19182,6 @@ 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 "npm-kommando"
@@ -18386,8 +19206,8 @@ msgstr "NPM"
msgid "PackageType|NuGet"
msgstr "NuGet"
-msgid "PackageType|PyPi"
-msgstr "PyPi"
+msgid "PackageType|PyPI"
+msgstr ""
msgid "Packages"
msgstr "Pakker"
@@ -18578,8 +19398,8 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
-msgstr "Prosent av brukere"
+msgid "Percent rollout must be an integer number between 0 and 100"
+msgstr ""
msgid "Percentage"
msgstr "Prosent"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr "Optimalisering av ytelsen"
@@ -18695,6 +19512,9 @@ msgstr "Suksessfrekvens:"
msgid "PipelineCharts|Successful:"
msgstr "Vellykket:"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "Totalt:"
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr "CI Lint"
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr "Vennligst skriv inn et nummer som ikke er negativt"
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr "Vennligst skriv inn et gyldig nummer"
@@ -19097,6 +19935,9 @@ msgstr "Vennligst skriv inn eller last opp en lisens."
msgid "Please fill in a descriptive name for your group."
msgstr "Vennligst skriv inn et beskrivende navn på gruppen din."
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr "Vennligst angi et navn"
msgid "Please provide a valid URL"
msgstr "Vennligst skriv inn en gyldig URL"
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr "Vennligst oppgi en gyldig e-postadresse."
@@ -19152,7 +19999,7 @@ msgid "Please select at least one filter to see results"
msgstr "Vennligst velg minst ett filter for å se resultatene"
msgid "Please set a new password before proceeding."
-msgstr "Vennligst velg et nytt passord før du fortsetter."
+msgstr "Vennligst bestem et nytt passord før du fortsetter."
msgid "Please share your feedback about %{featureName} %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ msgstr "Hendelsen vil bli trigget dersom en commit er opprettet/oppdatert"
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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ".NET Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr "SalesforceDX"
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr "Gren"
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr "Beskytt"
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr "Kjøp flere minutter"
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr "Push"
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr "Referanser"
msgid "Refresh"
msgstr "Oppdater"
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr "Registrer deg på GitLab"
-
msgid "Register now"
msgstr "Registrer deg nå"
@@ -21402,6 +22261,9 @@ msgstr "Fjern lisens"
msgid "Remove limit"
msgstr "Fjern grensen"
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr "Fjern medlem"
@@ -21522,6 +22384,9 @@ msgstr "Fjerner måldatoen."
msgid "Removes time estimate."
msgstr "Fjerner tidsanslag."
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr "Gjenåpne %{display_issuable_type}"
msgid "Reopen epic"
msgstr "Gjenåpne epos"
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr "Gjenåpne milepæl"
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr "Gjenåpne denne %{quick_action_target}"
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr "Kodelagre"
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr "Kodelagerdiagram"
msgid "Repository Settings"
msgstr "Kodelager-innstillinger"
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr "Forespørsler til disse domenene/adressene i det lokale nettverket vil v
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr "Kravet %{reference} har blitt gjenåpnet"
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr "Vis app"
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr "SSH-vertsnøkler"
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr "Offentlig SSH-nøkkel"
msgid "SSL Verification:"
msgstr "SSL-verifisering:"
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr "Lørdag"
@@ -22330,6 +23249,9 @@ msgstr "Lagre endringene"
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr "Lagre likevel"
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr "Lagre variabler"
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr "Lagrer"
msgid "Saving project."
msgstr "Lagrer prosjekt."
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "Planlegg en ny rørledning"
@@ -22405,6 +23327,9 @@ msgstr "Omfang"
msgid "Scopes can't be blank"
msgstr "Omfang kan ikke være tomme"
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr "Score"
@@ -22435,8 +23360,8 @@ msgstr "Søk"
msgid "Search Jira issues"
msgstr "Søk blant Jira-saker"
-msgid "Search Milestones"
-msgstr "Søk blant milepæler"
+msgid "Search a group"
+msgstr ""
msgid "Search an environment spec"
msgstr ""
@@ -22492,9 +23417,6 @@ msgstr "Søk etter denne teksten"
msgid "Search forks"
msgstr "Velg utgreininger"
-msgid "Search groups"
-msgstr "Søk etter grupper"
-
msgid "Search merge requests"
msgstr "Søke i flettede forespørsler"
@@ -22576,9 +23498,6 @@ msgstr "Viser %{from} - %{to} av %{count} %{scope} for%{term_element}"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for%{term_element} in your personal and project snippets"
msgstr "Viser %{from} - %{to} av %{count} %{scope} for%{term_element} i dine personlige og prosjektmessige utdrag"
-msgid "SearchResults|We couldn't find any %{scope} matching %{term}"
-msgstr ""
-
msgid "SearchResults|code result"
msgid_plural "SearchResults|code results"
msgstr[0] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr "Sikkerhetskontrollpanel"
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr "En feil oppstod under oppretting av fletteforespørselen."
msgid "SecurityReports|There was an error deleting the comment."
msgstr "Det oppstod en feil under sletting av kommentaren."
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr "Det oppstod en feil under avfeiing av sårbarhetene."
@@ -23102,6 +24035,9 @@ msgstr "Velg prosjekter du ønsker å importere."
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr "Velg skår å replikere"
@@ -23117,7 +24053,7 @@ msgstr "Velg startdato"
msgid "Select status"
msgstr "Velg status"
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr "Velg grenen du vil angi som standarden for dette prosjektet. Alle flette
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr "Velg tidssone"
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr "September"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr "Tjeneste-URL"
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr "Øktvarighet (i minutter)"
@@ -23477,11 +24416,14 @@ msgstr "Sett opp nytt passord"
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
msgid "Set weight"
-msgstr "Bestem vekt"
+msgstr "Bestem vektlegging"
msgid "Set weight to %{weight}."
msgstr "Sett vektlegging til %{weight}."
@@ -23535,7 +24477,7 @@ msgid "Sets time estimate to %{time_estimate}."
msgstr ""
msgid "Sets weight to %{weight}."
-msgstr "Setter vekten til %{weight}."
+msgstr "Setter vektleggingen til %{weight}."
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr "Delte prosjekter"
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ msgstr ""
msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
msgstr "Hvis du noen gang mister telefonen eller tilgang til din éngangs passordhemmelighet, kan hver av disse gjenopprettingskodene brukes én gang hver for å få tilgang til kontoen din igjen. Vennligst lagre dem på et trygt sted, ellers vil du %{b_start}vil%{b_end} miste tilgang til kontoen din."
+msgid "Show Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr "Vis all aktivitet"
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr "Vis alle medlemmer"
@@ -23734,7 +24691,7 @@ msgid "Sidebar|Only numeral characters allowed"
msgstr ""
msgid "Sidebar|Weight"
-msgstr "Vekt"
+msgstr "Vektlegging"
msgid "Sign in"
msgstr "Logg på"
@@ -23745,6 +24702,9 @@ msgstr "Logg inn / Registrer"
msgid "Sign in to \"%{group_name}\""
msgstr "Logg inn hos «%{group_name}»"
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr "Logg på med smartkort"
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr "PÃ¥loggingsbegrensninger"
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr "Registreringsbegrensninger"
@@ -23781,9 +24744,6 @@ msgstr "Fornavnet er for langt (maksimumet er %{max_length} tegn)."
msgid "SignUp|Last Name is too long (maximum is %{max_length} characters)."
msgstr "Etternavnet er for langt (maksimumet er %{max_length} tegn)."
-msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
-msgstr "Navnet er for langt (maksimumet er %{max_length} tegn)."
-
msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
msgstr "Brukernavnet er for langt (maksimumet er %{max_length} tegn)."
@@ -23793,6 +24753,9 @@ msgstr "Brukernavnet er for kort (minimumet er %{min_length} tegn)."
msgid "Signed in"
msgstr "PÃ¥logget"
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr "Snippets|Legg til en annen fil %{num}/%{total}"
-msgid "Snippets|Authored %{time_ago} by %{author}"
-msgstr ""
-
msgid "Snippets|Delete file"
msgstr "Slett fil"
msgid "Snippets|Description (optional)"
msgstr "Beskrivelse (valgfritt)"
-msgid "Snippets|File"
-msgstr "Fil"
-
msgid "Snippets|Files"
msgstr "Filer"
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 ""
@@ -24159,6 +25113,9 @@ msgstr "Tilgangsnivå, stigende"
msgid "SortOptions|Access level, descending"
msgstr "Tilgangsnivå, synkende"
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr "Opprettelsesdato"
@@ -24199,7 +25156,7 @@ msgid "SortOptions|Least popular"
msgstr "Minst populær"
msgid "SortOptions|Less weight"
-msgstr "Mindre vekt"
+msgstr "Mindre vektlegging"
msgid "SortOptions|Manual"
msgstr ""
@@ -24214,7 +25171,7 @@ msgid "SortOptions|Milestone due soon"
msgstr ""
msgid "SortOptions|More weight"
-msgstr "Mere vekt"
+msgstr "Mere vektlegging"
msgid "SortOptions|Most popular"
msgstr "Mest populær"
@@ -24267,6 +25224,9 @@ msgstr "Nyligst logget inn"
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr "Størrelse"
@@ -24295,7 +25255,7 @@ msgid "SortOptions|Version"
msgstr "Versjon"
msgid "SortOptions|Weight"
-msgstr "Vekt"
+msgstr "Vektlegging"
msgid "Source"
msgstr "Kilde"
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "Kildekode"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr "Stjerner"
msgid "Start Date"
msgstr "Startdato"
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr "Start netterminal"
@@ -24609,6 +25566,9 @@ msgstr "Statistikk"
msgid "Status"
msgstr "Status"
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr "Status:"
@@ -24738,6 +25698,9 @@ msgstr "Send inn som spam"
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr "Send tilbakemelding"
@@ -24753,6 +25716,9 @@ msgstr "Send inn søk"
msgid "Submit the current review."
msgstr "Send inn nåværende vurdering."
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr "Sendte inn den nåværende vurderingen."
@@ -24795,6 +25761,12 @@ msgstr "Abonnementet ble vellykket opprettet."
msgid "Subscription successfully deleted."
msgstr "Abonnementet ble vellykket slettet."
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr "Fakturering"
@@ -24879,6 +25851,9 @@ msgstr "Lyktes"
msgid "Successfully activated"
msgstr "Aktivering vellykket"
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "Vellykket blokkert"
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr "Symbolsk lenke"
msgid "Sync information"
msgstr "Synkroniseringsinformasjon"
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr "Synkronisert"
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr "System"
@@ -25068,6 +26052,9 @@ msgstr "Systemmåltall (egendefinert)"
msgid "System metrics (Kubernetes)"
msgstr "Systemmåltall (Kubernetes)"
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr "Innholdsfortegnelse"
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr "Takk for handelen!"
msgid "Thanks! Don't show me this again"
msgstr "Takk! Ikke vis meg dette igjen"
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ msgstr "Det avansert søket i GitLab er en kraftig søketjeneste som sparer deg
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
msgstr ""
-msgid "The 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "De følgende gjenstander vil IKKE bli eksportert:"
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,8 +26752,8 @@ msgstr "Utdraget er bare synlig for meg."
msgid "The snippet is visible only to project members."
msgstr "Utdraget er bare synlig for prosjektmedlemmer."
-msgid "The snippet is visible to any logged in user."
-msgstr "Utdraget er synlig for alle påloggede brukere."
+msgid "The snippet is visible to any logged in user except external users."
+msgstr ""
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -25777,6 +26791,9 @@ msgstr "Brukerkartet er et JSON-dokument som tilordner Google Code-brukere som d
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "Brukerkartet er en kartlegging av FogBugz-brukerne som deltok på prosjektene dine til måten deres e-postadresse og brukernavn blir importert til GitLab. Du kan endre dette ved å fylle ut tabellen nedenfor."
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
msgstr "Dette vedlegget har blitt avkortet for å unngå å overskride den maksimalt tillatte størrelsen på vedlegg på 15 MB. %{written_count} av %{issues_count} saker har blitt inkludert. Vurder å eksportere på nytt med et smalere valg av saker."
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Dette er din nåværende økt"
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26480,7 +27515,7 @@ msgid "This project will be removed on %{date} since its parent group '%{parent_
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 "Prosjektet vil leve i gruppen din %{strong_open}%{namespace}%{strong_close}. Et prosjekt er der du huser filene dine (kodelager), planlegger arbeidet ditt (problemer), publiserer dokumentasjonen (wiki) og så mye mer."
+msgstr "Prosjektet vil leve i gruppen din %{strong_open}%{namespace}%{strong_close}. Et prosjekt er der du huser filene dine (kodelager), planlegger arbeidet ditt (saker), publiserer dokumentasjonen (wiki) og så mye mer."
msgid "This repository"
msgstr "Dette kodelageret"
@@ -26851,6 +27886,12 @@ msgstr "nå nettopp"
msgid "Timeago|right now"
msgstr "akkurat nå"
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr "Tidsavbrudd"
@@ -26885,7 +27926,7 @@ msgstr "Titler og beskrivelser"
msgid "To"
msgstr "Til"
-msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,8 +27977,8 @@ msgstr "For å komme i gang, skriv inn din Gitea-verts-URL og en %{link_to_perso
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
msgstr "For å forbedre GitLab og brukeropplevelsen dens, vil GitLab med jevne mellomrom samle inn bruksinformasjon."
-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 "For å hjelpe til med å forbedre GitLab, vil vi periodisk samle inn bruksinformasjon. Dette kan endres når som helst i %{settings_link_start}Innstillinger%{link_end}. %{info_link_start}Mer informasjon%{link_end}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
+msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "For å importere et SVN-kodelager, sjekk ut %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr "Veksle navigasjon"
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Veksle sidelinje"
@@ -27137,17 +28181,20 @@ msgstr "Totalt minne (GB)"
msgid "Total test time for all commits/merges"
msgstr "Total testtid for alle commits/innflettinger"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
-msgstr "Total vekt"
+msgstr "Totalvekt"
msgid "Total: %{total}"
msgstr "Totalt: %{total}"
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
-msgstr "Spore"
+msgid "TotalRefCountIndicator|1000+"
+msgstr ""
msgid "Tracing"
msgstr "Sporing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr "Tirsdag"
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr "Slå av"
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr "Klarte ikke å lagre dine endringer. Vennligst prøv igjen."
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr "Oppdater nå"
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr "Oppdater variabel"
@@ -27836,10 +28892,13 @@ msgstr "Bruksstatistikk"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "Artifakter"
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr "Rørledninger"
msgid "UsageQuota|Purchase more storage"
msgstr "Kjøp mer lagringsplass"
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr "Kodelagre"
@@ -27878,9 +28940,36 @@ msgstr "Utdrag"
msgid "UsageQuota|Storage"
msgstr "Lagring"
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr "Ubegrenset"
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr "Benyttelse siden"
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr "Wiki"
msgid "UsageQuota|Wikis"
msgstr "Wikier"
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr "Du har brukt: %{usage} %{limit}"
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,11 +29066,8 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr "Bruker-ID-er"
-
-msgid "User List"
-msgstr "Brukerliste"
+msgid "User ID"
+msgstr ""
msgid "User OAuth applications"
msgstr ""
@@ -28088,6 +29186,9 @@ msgstr "Allerede rapportert for misbruk"
msgid "UserProfile|Blocked user"
msgstr "Blokkert user"
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr "Bidratte prosjekter"
@@ -28184,9 +29285,6 @@ msgstr "Brukernavnet er opptatt."
msgid "Username is available."
msgstr "Brukernavnet er tilgjengelig."
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr "Brukernavnet er for langt (maksimum er %{max_length} tegn)."
-
msgid "Username or email"
msgstr "Brukernavn eller E-postadresse"
@@ -28340,6 +29438,12 @@ msgstr "Versjon %{versionNumber} (nyeste)"
msgid "View Documentation"
msgstr "Vis dokumentasjon"
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr "Vis alle saker"
@@ -28647,8 +29751,14 @@ msgstr "Klasse"
msgid "Vulnerability|Comments"
msgstr "Kommentarer"
-msgid "Vulnerability|Crash Address"
-msgstr "Krasjadresse"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
+msgstr ""
msgid "Vulnerability|Description"
msgstr "Beskrivelse"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28807,7 +29926,7 @@ msgid "Webhooks Help"
msgstr "Webhook-hjelp"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
-msgstr "Webhooks lar deg trigge en URL hvis for eksempel ny kode blir pushet eller en ny sak opprettes. Du kan konfigurere webhooks til å lytte etter spesifikke hendelser som push, problemer eller fletteforespørsler. Gruppe-webhooker vil gjelde for alle prosjekter i en gruppe, slik at du kan standardisere webhook-funksjonalitet i hele gruppen."
+msgstr "Webhooks lar deg trigge en URL hvis for eksempel ny kode blir pushet eller en ny sak opprettes. Du kan konfigurere webhooks til å lytte etter spesifikke hendelser som push, saker eller fletteforespørsler. Gruppe-webhooker vil gjelde for alle prosjekter i en gruppe, slik at du kan standardisere webhook-funksjonalitet i hele gruppen."
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr "Skru på SSL-verifisering"
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr "Hemmelig sjetong"
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28906,10 +30031,10 @@ msgid "Weeks"
msgstr "Uker"
msgid "Weight"
-msgstr "Vekt"
+msgstr "Vektlegging"
msgid "Weight %{weight}"
-msgstr "Vekt %{weight}"
+msgstr "Vektlegging %{weight}"
msgid "Welcome back! Your account had been deactivated due to inactivity but is now reactivated."
msgstr "Velkommen tilbake! Kontoen din hadde blitt deaktivert på grunn av inaktivitet, men er nå aktivert på nytt."
@@ -28926,15 +30051,15 @@ msgstr "Velkommen til GitLab, %{first_name}!"
msgid "Welcome to the guided GitLab tour"
msgstr "Velkommen til den guidede GitLab-turen"
-msgid "Welcome to your issue board!"
-msgstr "Velkommen til sakspanelet ditt!"
-
msgid "What are you searching for?"
msgstr "Hva leter du etter?"
msgid "What describes you best?"
msgstr "Hva beskriver deg best?"
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr "Hva er nytt hos GitLab"
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29073,7 +30198,7 @@ msgid "WikiEmpty|You must be a project member in order to add wiki pages."
msgstr "Du må være prosjektmedlem for å kunne legge til wiki-sider."
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 "Du har aktivert Confluence Workspace-integrasjonen. Wikien din kan vises direkte i Confluence. Vi jobber hardt med å integrere Confluence mer sømløst i GitLab. Hvis du ønsker å holde deg oppdatert, følg vår %{wiki_confluence_epic_link_start}Confluence-epic%{wiki_confluence_epic_link_end}."
+msgstr "Du har aktivert Confluence Workspace-integrasjonen. Wikien din kan vises direkte i Confluence. Vi jobber hardt med å integrere Confluence mer sømløst i GitLab. Hvis du ønsker å holde deg oppdatert, følg vår %{wiki_confluence_epic_link_start}Confluence-epos%{wiki_confluence_epic_link_end}."
msgid "WikiHistoricalPage|This is an old version of this page."
msgstr "Dette er en gammel versjon av denne siden."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ 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 "Du kommer til å slå på konfidensialitet. Dette betyr at bare gruppemedlemmer med %{strongStart}minst «Rapportør»-tilgang%{strongEnd} kan se og legge ut kommentarer på %{issuableType}."
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr "Du mottar denne meldingen fordi du er en GitLab-administrator for %{url}."
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,12 +30449,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr "Du kan også opprette et prosjekt fra kommandolinjen."
-msgid "You can also press &#8984;-Enter"
-msgstr "Du kan også trykke &#8984;-Enter"
-
msgid "You can also press Ctrl-Enter"
msgstr "Du kan også trykke Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -29336,6 +30467,15 @@ msgstr "Du kan ogsÃ¥ laste opp eksisterende filer fra datamaskinen din ved Ã¥ fÃ
msgid "You can always edit this later"
msgstr "Du kan alltid redigere dette senere"
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr "Du har blitt tildelt %{member_human_access}-tilgang til %{title} %{name}
msgid "You have been invited"
msgstr "Du har blitt invitert"
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr "Du har blitt avabonnert på denne tråden."
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr "Du har ingen tillatelser"
@@ -29573,9 +30725,6 @@ msgstr "Du forlot «%{membershipable_human_name}»-%{source_type}."
msgid "You may close the milestone now."
msgstr "Du kan lukke milepælen nå."
-msgid "You must accept our Terms of Service and privacy policy in order to register an account"
-msgstr "Du må godta vilkårene for bruk og personvern for å kunne registrere en konto"
-
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr "Du har allerede aktivert 2-trinnsautentisering ved hjelp av éngangspass
msgid "YouTube"
msgstr "YouTube"
+msgid "YouTube URL or ID"
+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 "Ditt %{strong}%{plan_name}%{strong_close} abonnement på %{strong}%{namespace_name}%{strong_close} vil utløpe den %{strong}%{expires_on}%{strong_close}."
-msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not to be able to create issues or merge requests as well as many other features."
-msgstr "Ditt %{strong}%{plan_name}%{strong_close}-abonnement utløper den %{strong}%{expires_on}%{strong_close}. Etter det vil du ikke kunne lage saker eller fletteforespørsler, samt mange andre funksjoner."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
+msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr "Dine grupper"
msgid "Your License"
msgstr "Din lisens"
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr "SSH-nøklene dine (%{count})"
@@ -30061,9 +31216,6 @@ msgstr "grennavn"
msgid "by"
msgstr "av"
-msgid "by %{user}"
-msgstr "av %{user}"
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ msgstr "Fant %{issuesWithCount}"
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "Undersøk dette sikkerhetsproblemet ved å opprette en sak"
-msgid "ciReport|Learn more about interacting with security reports"
-msgstr "Lær mer om samhandling med sikkerhetsrapporter"
-
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -30260,7 +31406,7 @@ msgid "ciReport|No changes to code quality"
msgstr "Ingen endringer i kodekvalitet"
msgid "ciReport|No code quality issues found"
-msgstr "Ingen kodekvalitetsproblemer ble funnet"
+msgstr "Ingen kodekvalitetssaker ble funnet"
msgid "ciReport|RPS"
msgstr "RPS"
@@ -30324,6 +31470,9 @@ msgstr "Vis fullstendig rapport"
msgid "closed issue"
msgstr "lukket saksrapport"
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr "kommentar"
@@ -30562,8 +31711,8 @@ msgstr "er et ugyldig IP-adresseområde"
msgid "is blocked by"
msgstr "er blokkert av"
-msgid "is enabled."
-msgstr "er skrudd på."
+msgid "is forbidden by a top-level group"
+msgstr ""
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr "er ikke et gyldig X509-sertifikat."
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr "har kun lesetilgang"
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr "er for lang (maksimum er 100 oppføringer)"
@@ -30634,6 +31789,9 @@ msgstr "den er for stor"
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr "seneste commit:"
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr "mangler"
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ msgstr "prosjektmedlemmer"
msgid "projects"
msgstr "prosjekter"
-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 "hurtighandlinger"
@@ -31184,9 +32342,6 @@ msgstr "registrer"
msgid "relates to"
msgstr "relatert til"
-msgid "released %{time}"
-msgstr "utgitt %{time}"
-
msgid "remaining"
msgstr "gjenstår"
@@ -31197,7 +32352,7 @@ msgid "remove due date"
msgstr "fjern forfallsdato"
msgid "remove weight"
-msgstr "fjern vekt"
+msgstr "fjern vektlegging"
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr "vis mindre"
msgid "sign in"
msgstr "logg inn"
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr "sorter:"
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr "wikiside"
-msgid "will be released %{time}"
-msgstr "vil bli utgitt %{time}"
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "med %{additions} tillegg, %{deletions} slettinger."
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr "yaml er ugyldig"
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index 838ca2c1c37..ea2d2693761 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-10-02 18:48\n"
+"PO-Revision-Date: 2020-11-03 22:49\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d opgelost testresultaat"
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr "- toon minder"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ msgstr ""
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "1 %{type} toevoeging"
-msgstr[1] "%{count} %{type} toevoegingen"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "1 %{type} aanpassing"
-msgstr[1] "%{count} %{type} aanpassingen"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index 9e1e60dd256..90a0262d6ef 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-10-02 18:49\n"
+"PO-Revision-Date: 2020-11-03 22:49\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index 131ba69cb00..42be2e638cd 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-10-02 18:49\n"
+"PO-Revision-Date: 2020-11-03 22:49\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -231,6 +231,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -273,13 +280,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -519,6 +519,20 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} more"
msgstr ""
@@ -563,6 +577,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -608,6 +628,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -734,9 +760,6 @@ 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 ""
@@ -844,7 +867,7 @@ msgstr[3] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -864,6 +887,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1089,9 +1115,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1132,6 +1155,18 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1164,6 +1199,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1173,19 +1211,8 @@ 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] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1478,6 +1505,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1779,6 +1809,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1932,7 +1965,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1968,10 +2001,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -2058,6 +2091,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -2082,6 +2118,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2196,6 +2235,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2205,6 +2259,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2217,12 +2277,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2277,6 +2355,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2286,6 +2367,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2331,6 +2415,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2355,6 +2442,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2364,6 +2454,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2379,22 +2472,22 @@ msgstr ""
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "Zaawansowane pozwolenia, Magazyn Dużych Plików i Dwuczynnikowe ustawienia autoryzacji."
-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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2461,10 +2554,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2581,6 +2674,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2590,10 +2692,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2605,19 +2707,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Integration"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2632,6 +2743,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2641,7 +2758,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2659,7 +2779,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2668,6 +2788,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2734,9 +2875,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2761,6 +2899,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2782,6 +2923,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2803,12 +2947,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2857,6 +3007,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2869,9 +3022,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2899,9 +3058,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2989,9 +3154,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -3064,9 +3226,6 @@ 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 ""
@@ -3097,9 +3256,6 @@ 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 ""
@@ -3124,6 +3280,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3148,9 +3307,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3166,6 +3322,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3503,6 +3662,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3753,6 +3915,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -4001,8 +4166,29 @@ 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 "Proces Automatyczny DevOps został włączony i będzie używany, jeśli nie zostanie znaleziony alternatywny plik konfiguracyjny CI. %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr ""
@@ -4022,6 +4208,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -4040,6 +4229,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -4097,9 +4289,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4181,6 +4370,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4265,6 +4460,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4316,12 +4523,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4340,6 +4556,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4352,6 +4571,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4496,6 +4718,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4532,9 +4757,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4565,7 +4802,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4748,6 +4985,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5159,6 +5399,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5342,9 +5585,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr "Utwórz symbole wieloznaczne"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5363,9 +5603,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5474,6 +5711,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5498,7 +5738,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5525,6 +5765,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5708,6 +5951,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5765,9 +6011,6 @@ 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 ""
@@ -6023,9 +6266,6 @@ msgstr "Dowiedz się więcej o %{help_link_start_machine_type}rodzajach maszyn%{
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -6041,9 +6281,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6110,9 +6347,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6179,9 +6413,6 @@ 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 ""
@@ -6248,9 +6479,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6311,6 +6539,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6395,6 +6626,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6536,9 +6770,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6650,9 +6881,6 @@ 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 ""
@@ -6966,7 +7194,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -7017,6 +7245,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -7088,6 +7319,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7467,6 +7701,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7527,6 +7764,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7536,6 +7776,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7569,6 +7812,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7819,6 +8065,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7912,6 +8161,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8165,6 +8417,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8222,6 +8477,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8261,6 +8525,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8282,6 +8552,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8309,15 +8585,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8333,6 +8609,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8372,6 +8651,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8384,6 +8666,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8393,6 +8681,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8549,9 +8840,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8561,6 +8849,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8576,9 +8867,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8600,6 +8888,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8663,12 +8954,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8723,18 +9020,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8816,9 +9122,6 @@ 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 ""
@@ -8984,6 +9287,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -9032,6 +9341,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9203,6 +9515,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9254,7 +9587,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9405,6 +9738,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9414,6 +9750,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9435,6 +9774,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9462,9 +9804,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9633,15 +9972,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9714,6 +10062,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9855,6 +10206,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9882,7 +10239,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9927,6 +10296,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9954,7 +10326,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10716,12 +11091,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10752,6 +11133,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10827,6 +11211,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10929,6 +11316,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10992,6 +11382,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -11004,6 +11397,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11143,6 +11539,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11173,6 +11581,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11224,6 +11635,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11290,10 +11704,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11308,6 +11725,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11326,9 +11746,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11344,15 +11761,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11362,6 +11779,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11419,12 +11839,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11449,6 +11875,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11512,6 +11941,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11545,9 +11977,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11557,9 +11986,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11614,7 +12049,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12160,7 +12595,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12181,6 +12616,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12217,9 +12655,6 @@ 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 ""
@@ -12244,6 +12679,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12556,6 +12997,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12661,7 +13105,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12820,6 +13264,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12829,6 +13279,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12874,12 +13327,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12892,6 +13363,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12904,6 +13378,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12928,6 +13405,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13341,6 +13821,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13395,9 +13878,6 @@ 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 ""
@@ -13410,7 +13890,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13518,6 +13998,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13542,9 +14025,6 @@ 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 ""
@@ -13566,10 +14046,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13655,6 +14135,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13775,6 +14258,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13835,6 +14324,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13844,12 +14336,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13859,6 +14357,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13871,6 +14393,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13946,27 +14471,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13985,6 +14516,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -14016,6 +14550,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -14025,12 +14604,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -14064,6 +14661,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -14079,37 +14679,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -14118,6 +14739,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14142,9 +14766,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14244,25 +14865,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14310,6 +14931,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14358,6 +15033,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14574,6 +15252,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14829,6 +15510,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14847,6 +15531,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14976,9 +15666,6 @@ 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 ""
@@ -15007,9 +15694,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -15043,6 +15727,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -15076,6 +15763,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15121,6 +15811,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15196,6 +15889,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15749,9 +16445,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15770,6 +16463,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15803,9 +16499,6 @@ 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 ""
@@ -15815,7 +16508,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15827,6 +16520,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15890,6 +16586,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -16010,6 +16709,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -16037,15 +16742,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16283,6 +17063,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16690,6 +17473,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -17005,9 +17809,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -17065,6 +17875,38 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17320,6 +18162,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17786,6 +18631,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17816,9 +18664,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -18053,6 +18898,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -18098,9 +18946,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -18110,9 +18955,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18234,19 +19076,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18420,6 +19256,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18516,7 +19355,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18540,9 +19379,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18564,7 +19400,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18588,9 +19424,6 @@ 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 ""
@@ -18606,9 +19439,6 @@ 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 ""
@@ -18618,12 +19448,6 @@ 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 ""
@@ -18648,7 +19472,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18840,7 +19664,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18852,9 +19676,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18957,6 +19778,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -19038,6 +19862,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -19056,6 +19883,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -19086,6 +19916,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -19122,6 +19955,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19350,6 +20189,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19359,6 +20201,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19371,12 +20216,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19581,9 +20432,6 @@ 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 ""
@@ -20277,7 +21125,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20580,6 +21428,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20634,6 +21485,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -21090,6 +21944,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21216,6 +22073,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21327,6 +22187,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21408,6 +22271,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21454,9 +22320,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21668,6 +22531,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21788,6 +22654,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21809,9 +22678,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21839,6 +22714,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21966,7 +22844,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21978,6 +22862,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21996,6 +22892,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -22092,8 +22991,8 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
-msgstr "Wymagaj od wszystkich użytkowników w tej grupie do ustawienia uwierzytelniania Dwuczynnikowego"
+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 "Wymagaj od wszystkich użytkowników akceptacji Warunków Usługi i Polityki Prywatności, gdy będą chcieli korzystać z GitLab."
@@ -22125,6 +23024,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22332,6 +23234,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+msgstr ""
+
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
msgstr "Przejrzyj proces celem konfiguracji dostawców usług u swojego dostawcy tożsamości - w tym przypadku GitLab jest \"dostawcą usług\" lub \"wierzycielem\"."
@@ -22486,6 +23391,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22513,6 +23424,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22582,6 +23496,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22591,6 +23508,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22606,6 +23529,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22630,9 +23556,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22642,6 +23565,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22681,6 +23607,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22711,7 +23640,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22768,9 +23697,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22852,9 +23778,6 @@ 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] ""
@@ -22941,7 +23864,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22986,10 +23909,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -23118,6 +24041,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23181,6 +24107,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23220,6 +24152,13 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23400,6 +24339,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23415,7 +24357,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23430,9 +24372,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23526,6 +24465,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23640,6 +24582,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23775,6 +24720,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23880,6 +24828,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23898,9 +24855,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -24047,6 +25010,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -24074,6 +25040,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -24083,9 +25052,6 @@ 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 ""
@@ -24095,6 +25061,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24206,27 +25175,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24461,6 +25421,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24569,6 +25532,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24611,9 +25577,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24689,9 +25652,6 @@ msgstr "Określ wzór regex adresu e-mail, aby zidentyfikować domyślnych użyt
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 ""
@@ -24755,6 +25715,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24911,6 +25874,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -25040,6 +26006,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -25055,6 +26024,9 @@ msgstr "Zatwierdź wyszukiwanie"
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -25097,6 +26069,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25181,6 +26159,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25202,6 +26183,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25337,12 +26321,18 @@ msgstr ""
msgid "Sync information"
msgstr "Synchronizuj informacje"
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25370,6 +26360,9 @@ msgstr "Metryki systemowe (Niestandardowe)"
msgid "System metrics (Kubernetes)"
msgstr "Metryki systemowe (Kubernetes)"
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25610,15 +26603,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25703,7 +26711,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25728,9 +26736,6 @@ 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 ""
@@ -25743,9 +26748,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25842,6 +26853,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25867,7 +26884,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25978,7 +26995,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr "Klucz prywatny służy do użycia w przypadku, gdy dostarczony jest certyfikat klienta. Ta wartość jest zaszyfrowana w trybie spoczynku."
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -26038,6 +27055,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -26050,7 +27070,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -26089,6 +27109,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "Mapa użytkownika to mapowanie użytkowników FogBugz, którzy uczestniczyli w Twoich projektach, w celu zaimportowania ich adresów e-mail i nazw użytkowników do GitLab. Możesz to zmienić, wypełniając poniższą tabelę."
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26197,6 +27220,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26392,6 +27418,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26443,7 +27472,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26467,9 +27496,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26602,6 +27637,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26611,6 +27649,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27163,6 +28204,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27201,7 +28248,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27252,7 +28299,7 @@ msgstr ""
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
msgstr "Aby usprawnić GitLab i doświadczenie jego użytkowników, GitLab będzie okresowo zbierać informacje o użytkowaniu."
-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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27381,6 +28428,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27453,16 +28503,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27639,6 +28692,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27789,6 +28845,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -28014,6 +29073,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -28152,10 +29214,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28182,6 +29247,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28194,9 +29262,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28218,15 +29313,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28281,10 +29388,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28404,6 +29508,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28500,9 +29607,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28656,6 +29760,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28967,7 +30077,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -29051,6 +30167,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -29147,6 +30272,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29171,13 +30299,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29246,15 +30377,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29267,7 +30398,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29511,10 +30642,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29607,6 +30738,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29628,6 +30762,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29640,10 +30777,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29658,6 +30795,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29859,6 +31005,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29871,6 +31020,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29895,9 +31053,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29955,9 +31110,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -30060,19 +31212,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -30102,6 +31257,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -30117,6 +31275,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30385,9 +31546,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30514,9 +31672,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30562,9 +31717,6 @@ 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 ""
@@ -30650,6 +31802,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30898,7 +32053,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30916,6 +32071,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30934,6 +32092,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30970,6 +32131,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -31034,6 +32198,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31515,9 +32682,6 @@ 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 ""
@@ -31530,9 +32694,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31612,6 +32773,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31792,9 +32956,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31807,3 +32968,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index d877f3e8605..f48ad97d748 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-10-02 18:41\n"
+"PO-Revision-Date: 2020-11-03 22:40\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -26,7 +26,7 @@ msgid " (from %{timeoutSource})"
msgstr " (de %{timeoutSource})"
msgid " Collected %{time}"
-msgstr ""
+msgstr " Coletada %{time}"
msgid " Please sign in."
msgstr " Por favor, entre usando sua conta."
@@ -162,8 +162,8 @@ msgstr[1] "%d contribuições"
msgid "%d day"
msgid_plural "%d days"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d dia"
+msgstr[1] "%d dias"
msgid "%d day until tags are automatically removed"
msgid_plural "%d days until tags are automatically removed"
@@ -172,8 +172,8 @@ msgstr[1] ""
msgid "%d error"
msgid_plural "%d errors"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d: erro"
+msgstr[1] "%d: erros"
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d resultado do teste corrigido"
@@ -197,8 +202,8 @@ msgstr[1] ""
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"
@@ -215,11 +220,6 @@ msgid_plural "%d issues in this group"
msgstr[0] ""
msgstr[1] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d issue selecionada"
-msgstr[1] "%d issues selecionadas"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -267,8 +267,8 @@ msgstr[1] ""
msgid "%d pending comment"
msgid_plural "%d pending comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d comentário pendente"
+msgstr[1] "%d comentários pendentes"
msgid "%d personal project will be removed and cannot be restored."
msgid_plural "%d personal projects will be removed and cannot be restored."
@@ -407,6 +407,16 @@ msgstr "%{count} aprovações de %{name}"
msgid "%{count} files touched"
msgstr "%{count} arquivos modificados"
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr "mais %{count}"
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr "%{group_name} usa contas gerenciadas por grupo. Você precisa criar uma
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 "%{name} continha %{resultsString}"
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -947,9 +969,6 @@ msgstr "(verificar progresso)"
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr "(fonte externa)"
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr "- exibir menos"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ msgstr "0 para ilimitado"
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "1 adição de %{type}"
-msgstr[1] "%{count} adições %{type}"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "1 mudança de %{type}"
-msgstr[1] "%{count} mudanças de %{type}"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr "Um usuário com permissão de escrita no branch de origem selecionou est
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr "Adicionar uma tabela"
msgid "Add a task list"
msgstr "Adicionar uma lista de tarefas"
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Coloque um texto adicional para aparecer em todas as comunicações por email. Limite de %{character_limit} caracteres"
@@ -1748,8 +1781,8 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr "Adicionado %{label_references} %{label_text}."
-msgid "Added a To Do."
-msgstr "Adicionado um afazer."
+msgid "Added a to do."
+msgstr ""
msgid "Added an issue to an epic."
msgstr "Adicionado um issue a um épico."
@@ -1784,10 +1817,10 @@ msgstr "Adiciona %{epic_ref} como épico filho."
msgid "Adds %{labels} %{label_text}."
msgstr "Adiciona %{labels} %{label_text}."
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr "Erro ao parar tarefas"
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr "Chaves SSH"
msgid "AdminStatistics|Snippets"
msgstr "Snippets"
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr "A2F desativada"
@@ -2021,6 +2075,12 @@ msgstr "A2F ativada"
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr "Ativo"
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr "Administradores"
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr "Bloquear"
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Bloquear usuário"
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr "É você!"
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr "Novo usuário"
@@ -2102,6 +2183,9 @@ msgstr "Nenhum usuário encontrado"
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Para confirmar, digite %{projectName}"
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr "Avançado"
@@ -2195,22 +2288,22 @@ msgstr ""
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "Permissões avançadas, armazenamento de arquivos grandes e configurações de autenticação de dois fatores."
-msgid "Advanced search functionality"
-msgstr "Funcionalidade de pesquisa avançada"
-
msgid "After a successful password update you will be redirected to login screen."
msgstr "Após uma atualização de senha bem-sucedida, você será redirecionado para a tela de login."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Após uma atualização de senha bem sucedida, você será redirecionado para a página de login onde você pode entrar com sua nova senha."
-msgid "After that, you will not to be able to use merge approvals or code quality as well as many other features."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Integration"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr "Alertas"
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr "Todos os usuários"
-
msgid "All users must have a name."
msgstr "Todos os usuários devem ter um nome."
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "Permitir que projetos dentro deste grupo usem o Git LFS"
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr "Permitir que esta chave também possa fazer push para o repositório? (Padrão permite apenas acesso para pull.)"
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr "Permitido falhar"
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Permite adicionar e gerenciar clusters do Kubernetes."
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ 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 "Um campo vazio do usuário do GitLab adicionará o nome completo do usuário do FogBugz (por exemplo, \"Por John Smith\") na descrição de todos os issues e comentários. Ele também irá associar e/ou atribuir essas issues e comentários ao criador do projeto."
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "Ocorreu um erro"
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr "Erro ao pré-visualizar o blob"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "Erro ao modificar notificação de assinatura"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "Ocorreu um erro ao atualizar o peso do issue"
@@ -2803,9 +2968,6 @@ 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 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."
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ msgstr ""
msgid "An error occurred while loading the pipelines jobs."
msgstr ""
-msgid "An error occurred while loading the subscription details."
-msgstr "Um erro ocorreu ao carregar os detalhes da inscrição."
-
msgid "An error occurred while making the request."
msgstr "Erro ao fazer a requisição."
@@ -2938,6 +3094,9 @@ msgstr "Erro ao renderizar pré-visualização da mensagem de transmissão"
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr "Ocorreu um erro ao salvar o status de substituição do LDAP. Por favor,
msgid "An error occurred while saving assignees"
msgstr "Erro ao salvar assignees"
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr "Ocorreu um erro ao inscrever às notificações."
@@ -2980,6 +3136,9 @@ msgstr "Ocorreu um erro ao desinscrever às notificações."
msgid "An error occurred while updating approvers"
msgstr "Ocorreu um erro ao atualizar os aprovadores"
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr "Arquivar tarefas"
msgid "Archive project"
msgstr "Arquivar projeto"
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr "Atribuído a mim"
@@ -3801,8 +3966,29 @@ msgstr "Ele gerará a build, testará e fará deploy de sua aplicação automati
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Saiba mais em %{link_to_documentation}"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "A pipeline de Auto DevOps foi ativada e será usada se não for encontrada configuração CI alternativa nos arquivos. %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr "Autocompletar"
@@ -3822,6 +4008,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 "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr "Nota"
msgid "Available"
msgstr "Disponível"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr "URL da imagem do selo"
msgid "Badges|Badge image preview"
msgstr "Pré-visualização da imagem do selo"
-msgid "Badges|Delete badge"
-msgstr "Apagar selo"
-
msgid "Badges|Delete badge?"
msgstr "Apagar selo?"
@@ -3981,6 +4170,12 @@ msgstr "URL raiz de bambu como https://bamboo.exemplo.com"
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr "Você precisa configurar etiquetas de revisão automáticas e um gatilho de repositório no Bamboo."
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Cuidado. Alterar o namespace do projeto pode ter efeitos colaterais indesejados."
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr "Importação de Servidores Bitbucket"
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr "Expandir"
msgid "Boards|View scope"
msgstr "Ver escopo"
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr "O branch %{branchName} não foi encontrado no repositório deste projeto
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr "configurações do projeto"
msgid "Branches|protected"
msgstr "protegido"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr "Transmissão de messagem foi criada com sucesso."
@@ -4332,9 +4557,21 @@ msgstr "Embutido"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ msgstr "Por %{user_name}"
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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr "Não é possível criar o relatório de abuso. Este usuário foi bloquea
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr "Todos os ambientes"
msgid "CiVariable|Create wildcard"
msgstr "Criar curinga"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr "Ocorreu um erro ao salvar variáveis"
-
msgid "CiVariable|Masked"
msgstr "Mascarada"
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr "Alternar proteção"
-msgid "CiVariable|Validation failed"
-msgstr "Falha na validação"
-
msgid "Classification Label (optional)"
msgstr "Etiqueta de Classificação (opcional)"
@@ -5274,6 +5511,9 @@ msgstr "Fechar %{tabname}"
msgid "Close epic"
msgstr "Fechar épico"
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr "Fechar marco"
@@ -5298,7 +5538,7 @@ msgstr "Issues Fechadas"
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ msgstr ""
msgid "ClusterIntegration|Could not load networks"
msgstr ""
-msgid "ClusterIntegration|Could not load regions from your AWS account"
-msgstr "Não foi possível carregar regiões da sua conta AWS"
-
msgid "ClusterIntegration|Could not load security groups for the selected VPC"
msgstr ""
@@ -5823,9 +6066,6 @@ msgstr "Saiba mais sobre os %{help_link_start_machine_type}tipos de máquinas%{h
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "Saiba mais sobre as %{help_link_start}zonas%{help_link_end}."
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr "Saiba mais sobre os Kubernetes"
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr "Nenhum projeto encontrado"
msgid "ClusterIntegration|No projects matched your search"
msgstr "Nenhum projeto corresponde à sua pesquisa"
-msgid "ClusterIntegration|No region found"
-msgstr "Nenhuma região encontrada"
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ msgstr ""
msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "ClusterIntegration|Region"
-msgstr "Região"
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Remover integração com o cluster Kubernetes"
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr "Pesquisar projetos"
-msgid "ClusterIntegration|Search regions"
-msgstr "Pesquisar regiões"
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr "Selecione o projeto para escolher a zona"
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr "Selecione a zona"
@@ -6195,6 +6426,9 @@ msgstr "O endpoint está em processo de atribuição. Verifique o seu cluster Ku
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr "Selecione uma região"
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ msgstr ""
msgid "ComboSearch is not defined"
msgstr "ComboSearch não está definido"
-msgid "Coming soon"
-msgstr ""
-
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
msgstr ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr "Entre em contato com o departamento de vendas para atualizar"
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr "Não foi possível excluir o apelido de bate-papo %{chat_name}."
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr "Não foi possível remover o gatilho."
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr "Criado em"
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr "Criado em:"
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr "Nome de host personalizado (para e-mails de commit privado)"
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr "Os dados ainda estão a ser calculados..."
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr "Excluir Snippet"
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr "Excluir lista"
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr "Excluir branch de origem"
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr "Excluir este anexo"
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr "Negada autorização do apelido de bate-papo %{user_name}."
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr "Recusar"
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr "Dependências"
@@ -8505,18 +8802,27 @@ msgstr "Exportar como JSON"
msgid "Dependencies|Job failed to generate the dependency list"
msgstr "A tarefa falhou em gerar a lista de dependências"
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr "Licença"
msgid "Dependencies|Location"
msgstr "Localização"
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
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|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr "Feito Deploy"
msgid "Deployed to"
msgstr "Deploy para"
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr "Fazer deploy para"
@@ -8808,6 +9117,9 @@ msgstr "Descrição"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "Descrição analisada com %{link_start}GitLab Flavored Markdown%{link_end}"
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr "Os modelos de descrição permitem que você defina modelos específicos de contexto para os campos de descrição de merge request e emissão para seu projeto."
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr "Diferenciar limite de conteúdo"
@@ -9030,8 +9363,8 @@ msgstr "Desabilitar runners de grupo"
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
-msgstr "Desativar Runners compartilhados"
+msgid "Disable shared runners"
+msgstr ""
msgid "Disable two-factor authentication"
msgstr "Desativar autenticação de dois fatores"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr "Documentação para provedores de identidade populares"
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr "Domínio"
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr "A verificação de domínio é uma medida de segurança essencial para sites públicos do GitLab. Os usuários precisam demonstrar que controlam um domínio antes de ser ativado"
@@ -9209,6 +9548,9 @@ 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 "Não cole a parte privada da chave GPG. Cole a parte pública que começa com '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "Não exibir novamente"
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr "Baixar recurso"
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr "Editar chave de deploy pública"
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr "Ativar cabeçalho e rodapé em e-mails"
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,8 +10013,20 @@ msgstr "Habilitar proxy"
msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared Runners"
-msgstr "Ativar Runners partilhados"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
+msgstr ""
msgid "Enable snowplow tracking"
msgstr ""
@@ -9701,6 +10070,9 @@ msgstr "Ativar isto apenas disponibilizará os recursos EE licenciados para proj
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "Termina em (UTC)"
@@ -9728,7 +10100,10 @@ msgstr "Insira o intervalo de endereços IP"
msgid "Enter a number"
msgstr "Digite um número"
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr "Exemplo: Uso = consulta única. (Solicitada) / (Capacidade) = múltiplas
msgid "Except policy:"
msgstr "Exceto da política:"
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr "Expandir aprovadores"
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr "Exportar issues"
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "Exportar projeto"
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr "Falha ao carregar branches relacionados"
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr "Falha ao carregar a stacktrace."
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr "* (Todos os Ambientes)"
@@ -10945,6 +11353,9 @@ msgstr "Configurar"
msgid "FeatureFlags|Configure feature flags"
msgstr "Configurar feature flag"
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr "Criar feature flag"
@@ -10996,6 +11407,9 @@ msgstr "A feature flag %{name} será removido. Você tem certeza?"
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr "Feature flags permitem que você configure o seu código em diferentes versões alterando dinamicamente determinada funcionalidade."
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,11 +11476,14 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr "Porcentagem de rollout (usuários logados)"
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
-msgstr "A porcentagem de rollout deve ser um número inteiro entre 0 e 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
+msgstr ""
msgid "FeatureFlags|Protected"
msgstr "Protegido"
@@ -11080,6 +11497,9 @@ msgstr "Porcentagem de rollout"
msgid "FeatureFlags|Rollout Strategy"
msgstr "Estratégia de Rollout"
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr "Ocorreu um erro ao buscar as feature flag."
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "Fev"
@@ -11191,12 +11611,18 @@ msgstr "Modelos de arquivos"
msgid "File upload error."
msgstr "Erro ao enviar arquivo."
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "Arquivos"
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr "Arquivos, diretórios e submódulos no caminho %{path} para referência de commit %{ref}"
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr "Filtro..."
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr "Finalizado"
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr "Primeiro dia da semana"
msgid "First name"
msgstr "Primeiro nome"
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr "Data fixa"
@@ -11386,8 +11821,8 @@ 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 "Para projetos internos, qualquer usuário conectado pode visualizar pipelines e acessar detalhes da tarefa (logs de saída e artefatos)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
msgid "For more info, read the documentation."
msgstr "Para mais informações, leia a documentação."
@@ -11932,7 +12367,7 @@ msgstr "Introdução às versões"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr "Git LFS não está habilitado neste servidor GitLab, contate seu administrador."
-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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr "Estratégia Git para pipelines"
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr "Versão do Git"
@@ -11989,9 +12427,6 @@ 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 "GitLab Shared Runners executam códigos de projetos diferentes no mesmo Runner, a menos que você configure o GitLab Runner Autoscale com o MaxBuilds 1 (que está no GitLab.com)."
-
msgid "GitLab Shell"
msgstr ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr "GitLab para Slack"
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr "Ir para seus projetos"
msgid "Go to your snippets"
msgstr "Ir para seus snippets"
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr "URL do grupo"
msgid "Group avatar"
msgstr "Avatar do grupo"
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr "Para visualizar o planejamento, adicione uma data de início ou de venci
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Para expandir a sua pesquisa, altere ou remova filtros; de %{startDate} para %{endDate}."
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "Impressão digital do certificado"
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "Histórico"
@@ -13163,9 +13646,6 @@ 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."
-msgid "I accept the %{terms_link_start}Terms of Service and Privacy Policy%{terms_link_end}"
-msgstr ""
-
msgid "I accept the %{terms_link}"
msgstr "Eu aceito o %{terms_link}"
@@ -13178,7 +13658,7 @@ msgstr "Esqueci minha senha"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
-msgid "I'd like to receive updates via email about GitLab"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "Se ativado, o acesso aos projetos será validado em um serviço externo usando sua etiqueta de classificação."
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr "Importar vários repositórios fazendo o upload de um arquivo manifest."
msgid "Import project"
msgstr "Importar projeto"
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr "Importar membros do projeto"
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr "Incidentes"
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "Inclua um contrato de Termos de Serviço e uma Política de Privacidade que todos os usuários devem aceitar."
@@ -13710,27 +14235,33 @@ msgstr "Insira as chaves do host manualmente"
msgid "Input your repository URL"
msgstr "Insira seu URL do repositório"
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr "Inserir uma citação"
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr "Inserir código"
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr "Inserir sugestão"
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr "Insights"
@@ -13749,6 +14280,9 @@ msgstr "Instalar o GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "Instalar Runner no Kubernates"
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr "O grupo de administradores da instância já existe"
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,38 +14441,59 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "As partes interessadas podem até contribuir enviando commits, caso queiram."
msgid "Internal"
msgstr "Interno"
-msgid "Internal - The group and any internal projects can be viewed by any logged in user."
-msgstr "Interno - O grupo e projetos internos podem ser visualizados por qualquer usuário autenticado."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
-msgstr "Interno - O projeto pode ser acessado por qualquer usuário autenticado."
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "Internal URL (optional)"
msgstr ""
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr "Usuários internos"
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Padrão de intervalo"
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr "URL inválida"
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr "Convidar membro"
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "Painéis"
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr "Jan"
msgid "January"
msgstr "Janeiro"
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ msgstr "Promover etiqueta"
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 "e mais %{count}"
-
msgid "Language"
msgstr "Idioma"
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr "Último Pipeline"
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr "Última resposta de"
@@ -14836,6 +15523,9 @@ msgstr "Último atualizado"
msgid "Last used"
msgstr "Usado pela última vez"
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr "Última utilização em:"
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr "Saiba mais"
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr "Saiba mais sobre o Auto DevOps"
@@ -14956,6 +15649,9 @@ msgstr "Deixe as opções \"Tipo de arquivo\" e \"Método de entrega\" em seus v
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "O Let's Encrypt não aceita e-mails de example.com"
@@ -15495,9 +16191,6 @@ msgstr "Mar"
msgid "March"
msgstr "Março"
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr "Marcar esta issue como uma duplicata de outra issue"
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr "Markdown"
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr "Bloqueio de membro"
msgid "Member since %{date}"
msgstr "Membro desde %{date}"
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr "Membros"
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr "Branches com merge realizado estão sendo excluídas. Isso pode levar al
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ 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 "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr "Nunca"
msgid "New"
msgstr "Novo"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr "Novo aplicativo"
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr "Nenhum"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr "Dados insuficientes"
msgid "Not found."
msgstr "Não encontrado."
-msgid "Not now"
-msgstr "Agora não"
-
msgid "Not ready yet. Try again later."
msgstr "Ainda não está pronto. Tente mais tarde."
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ msgstr ""
msgid "Open issues"
msgstr ""
-msgid "Open projects"
-msgstr "Abrir projetos"
-
msgid "Open raw"
msgstr ""
msgid "Open sidebar"
msgstr "Abrir barra lateral"
-msgid "Open: %{openIssuesCount}"
-msgstr ""
-
-msgid "Open: %{open} • Closed: %{closed}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr "Pessoas sem permissão nunca receberão uma notificação e não serão
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr "Otimização de performance"
@@ -18695,6 +19512,9 @@ msgstr "Taxa de sucesso:"
msgid "PipelineCharts|Successful:"
msgstr "Sucesso:"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "Total:"
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr "CI Lint"
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr "Saiba como funcionam as pipelines"
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Cache do projeto redefinido com sucesso."
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr "Digite um número não-negativo"
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr "Por favor, insira um número maior que %{number} (das configurações do projeto)"
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr "Digite um número válido"
@@ -19097,6 +19935,9 @@ msgstr "Por favor, insira ou envie uma licença."
msgid "Please fill in a descriptive name for your group."
msgstr "Por favor, preencha um nome descritivo para o seu grupo."
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Por favor, note que esse aplicativo não é fornecido pelo GitLab e você deve verificar a sua autenticidade antes de permitir o acesso."
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr "Por favor, forneça um nome"
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ".NET Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr "Push"
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr "Atualizar"
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "Atualizando em um segundo para mostrar o status atualizado..."
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr "Reabrir epic"
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr "Reabrir marco"
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr "Configurações do Repositório"
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,8 +22719,8 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
-msgstr "Exigir que todos os usuários deste grupo configurem a autenticação de dois fatores"
+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 "Exija que todos os usuários aceitem Termos de Serviço e Política de Privacidade quando acessarem o GitLab."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+msgstr ""
+
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
msgstr "Revise o processo de configuração de provedores de serviços em seu provedor de identidade - nesse caso, o GitLab é o \"provedor de serviços\" ou a \"terceiro\"."
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr "Chaves SSH do host"
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr "Chave SSH pública"
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr "Sábado"
@@ -22330,6 +23249,9 @@ msgstr "Salvar alterações"
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr "Salvar mesmo assim"
@@ -22354,9 +23276,6 @@ msgstr "Salvar agendamento da pipeline"
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 variables"
-msgstr "Salvar variáveis"
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr "Salvando projeto."
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "Agendar nova pipeline"
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr "Pesquisar"
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr "Pesquisar forks"
-msgid "Search groups"
-msgstr "Procurar grupos"
-
msgid "Search merge requests"
msgstr "Pesquisar merge requests"
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr "Selecione os projetos que você deseja importar."
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr "Selecione o branch que você deseja definir como o padrão para este pro
msgid "Select the custom project template source group."
msgstr "Selecione o grupo de origem dos modelos customizados de projeto."
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr "Separe os tópicos com vírgulas."
msgid "September"
msgstr "Setembro"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr "Modelos de serviço"
msgid "Service URL"
msgstr "URL de serviço"
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr "Duração da sessão (minutos)"
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "Configure seu projeto para fazer push e/ou pull de um repositório para outro automaticamente. Branches, tags e commits serão sincronizados automaticamente."
@@ -23582,6 +24524,15 @@ msgstr "Runners Compartilhados"
msgid "Shared projects"
msgstr "Projetos compartilhados"
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ msgstr "Transações de Sherlock"
msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
msgstr ""
+msgid "Show Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr "Mostrar todas as atividades"
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr "Entrar / Criar conta"
msgid "Sign in to \"%{group_name}\""
msgstr "Entrar em \"%{group_name}\""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr "Entrar usando o cartão inteligente"
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr "Restrições de login"
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr "Restrições de cadastro"
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr "Nível de acesso, ascendente"
msgid "SortOptions|Access level, descending"
msgstr "Nível de acesso, decrescente"
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr "Data de criação"
@@ -24267,6 +25224,9 @@ msgstr "Assinados mais novos"
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "Código-fonte"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ msgstr "Especifique um padrão regex de endereço de e-mail para identificar usu
msgid "Specify the following URL during the Runner setup:"
msgstr "Especifique o seguinte URL durante a configuração do Runner:"
-msgid "Speed up your DevOps%{br_tag}with GitLab"
-msgstr ""
-
msgid "Squash commit message"
msgstr ""
@@ -24453,6 +25407,9 @@ msgstr "Favoritos"
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr "Iniciar Terminal Web"
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr "Status"
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr "Status:"
@@ -24738,6 +25698,9 @@ msgstr "Enviar como spam"
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr "Enviar feedback"
@@ -24753,6 +25716,9 @@ msgstr "Buscar"
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr "Cobrança"
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr "Informação de sincronização"
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr "Sistema"
@@ -25068,6 +26052,9 @@ msgstr "Métricas de sistema (Personalizado)"
msgid "System metrics (Kubernetes)"
msgstr "Métricas do sistema (Kubernetes)"
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr "Tabela de conteúdos"
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr "Obrigado! Não me mostre isso novamente"
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ msgstr "O Rastreador de Issue é o lugar para adicionar coisas que precisam ser
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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "Os seguintes itens NÃO serão exportados:"
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,8 +26677,8 @@ msgstr "A etapa de planejamento mostra o tempo do passo anterior até a publicaÃ
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr "A chave privada a ser usada quando um certificado de cliente é fornecido. Este valor é criptografado."
-msgid "The project can be accessed by any logged in user."
-msgstr "O projeto pode ser acessado por qualquer usuário autenticado."
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr ""
@@ -25726,6 +26737,9 @@ msgstr "A etapa de revisão mostra o tempo de criação de uma solicitação de
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "O roadmap mostra o progresso de seus epics ao longo de uma linha do tempo"
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "O mapa do usuário é um mapeamento dos usuários do FogBugz que participaram de seus projetos para a maneira como seus endereços de e-mail e nomes de usuários serão importados para o GitLab. Você pode alterar isso preenchendo a tabela abaixo."
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr "Já existe um repositório com esse nome no disco"
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr "Esse aplicativo foi criado por %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Esse aplicativo será capaz de:"
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr "Esta é uma lista de dispositivos com os quais você logou em sua conta.
msgid "This is a security log of important events involving your account."
msgstr "Este é um registro de segurança de eventos importantes envolvendo a sua conta."
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Esta é a sua sessão atual"
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr "agora"
msgid "Timeago|right now"
msgstr "agora mesmo"
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr "Tempo limite"
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,8 +27977,8 @@ msgstr "Para começar, insira seu URL de Host do Gitea e um %{link_to_personal_t
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
msgstr "Para ajudar a melhorar o GitLab e sua experiência de usuário, o GitLab coletará periodicamente informações de uso."
-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 "Para ajudar a melhorar o GitLab, gostaríamos de coletar periodicamente informações de uso. Isso pode ser alterado a qualquer momento em %{settings_link_start}Configurações%{link_end}. %{info_link_start}Mais informações%{link_end}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
+msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "Para importar um repositório SVN, confira %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr "Alternar prêmio de emoji"
msgid "Toggle navigation"
msgstr "Alternar navegação"
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Ativar/Desativar barra lateral"
@@ -27137,17 +28181,20 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr "Tempo de teste total para todos os commits/merges"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr "Total: %{total}"
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
-msgstr "Rastreamento"
+msgid "TotalRefCountIndicator|1000+"
+msgstr ""
msgid "Tracing"
msgstr "Rastreamento"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr "Terça-feira"
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr "Atualizar agora"
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr "Estatísticas de uso"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr "Pipelines"
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr "Ilimitado"
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr "Uso desde"
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr "Já denunciado por abuso"
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr "Projetos contribuídos"
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr "Classe"
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Quando um runner está bloqueado, não pode ser atribuído a outros projetos"
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr "Você está em uma instância somente-leitura do GitLab."
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr "Você está recebendo esta mensagem porque você é um administrador do GitLab para %{url}."
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,12 +30449,12 @@ msgstr "Você pode %{linkStart}visualizar o blob%{linkEnd} em vez disso."
msgid "You can also create a project from the command line."
msgstr "Você também pode criar um projeto a partir da linha de comando."
-msgid "You can also press &#8984;-Enter"
-msgstr "Você também pode pressionar &#8984;-Enter"
-
msgid "You can also press Ctrl-Enter"
msgstr "Você também pode pressionar Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr "Você também pode marcar uma etiqueta para torná-la uma etiqueta de prioridade."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr "Você não tem permissão"
@@ -29573,9 +30725,6 @@ 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 "Você deve aceitar nossos Termos de Serviço e política de privacidade para registrar uma conta"
-
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr "YouTube"
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr "Seus Grupos"
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr "Atividade dos seus projetos"
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr "nome da branch"
msgid "by"
msgstr "por"
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr "A varredura de contêiner detectou vulnerabilidades conhecidas em suas i
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr "Visualizar relatório completo"
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr "não é um certificado X509 válido."
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 "ações rápidas"
@@ -31184,9 +32342,6 @@ msgstr "registrar"
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr "restante"
@@ -31264,6 +32419,9 @@ msgstr "mostrar menos"
msgid "sign in"
msgstr "entrar"
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "com %{additions} adições, %{deletions} remoções."
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index 8884f6ffb93..c5956a44e8d 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-10-02 18:49\n"
+"PO-Revision-Date: 2020-11-03 22:50\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d resultado do teste fixo"
@@ -215,11 +220,6 @@ msgid_plural "%d issues in this group"
msgstr[0] ""
msgstr[1] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d problema selecionado"
-msgstr[1] "%d problemas selecionados"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -407,6 +407,16 @@ msgstr "%{count} aprovações de %{name}"
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr "mais %{count}"
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr "%{group_name} usa contas de gestão de grupo. Precisas de criar uma nova
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 "%{name} continha %{resultsString}"
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -947,9 +969,6 @@ msgstr "(verificar progresso)"
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr "(fonte externa)"
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr "- mostrar menos"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ msgstr "0 para ilimitado"
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "1 adição de %{type}"
-msgstr[1] "%{count} adições %{type}"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "1 alteração de %{type}"
-msgstr[1] "%{count} alterações de %{type}"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr "Um utilizador com permissão de escrita ao ramo de origem selecionado pa
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr "Adicionar uma tabela"
msgid "Add a task list"
msgstr "Adicionar uma lista de tarefas"
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Adiciona um texto adicional para aparecer em todas as comunicações por email. Limite de %{character_limit} caracteres"
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr "Adiciona %{epic_ref} como filho épico."
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr "Erro ao parar trabalhos"
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr "A2F Desativada"
@@ -2021,6 +2075,12 @@ msgstr "A2F Ativada"
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr "Ativo"
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr "Administradores"
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Bloquear utilizador"
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr "És tu!"
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr "Novo utilizador"
@@ -2102,6 +2183,9 @@ msgstr "Nenhum utilizador encontrado"
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Para confirmar, digita %{projectName}"
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr "Avançado"
@@ -2195,22 +2288,22 @@ msgstr ""
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "Permissões avançadas, Armazenamento de Ficheiro Grandes e definições de autenticação de Dois Fatores."
-msgid "Advanced search functionality"
-msgstr "Funcionalidade de pesquisa avançada"
-
msgid "After a successful password update you will be redirected to login screen."
msgstr "Após uma atualização de palavra-passe bem-sucedida, serás redirecionado à tela de início de sessão."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Após uma atualização bem-sucedida da palavra-passe, serás redirecionado para a página de início de sessão, onde poderás iniciar a sessão com a nova palavra-passe."
-msgid "After that, you will not to be able to use merge approvals or code quality as well as many other features."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr "Alertas"
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr "Todos os utilizadores"
-
msgid "All users must have a name."
msgstr "Todos os utilizadores devem ter um nome."
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "Permitir que projetos dentro deste grupo usem o Git LFS"
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr "Permitir que esta chave seja também, enviada ao repositório? (O padrão só permite o acesso pull)"
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr "Permissão para falhar"
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Permite -te adicionar e gerir clusters do Kubernetes."
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ 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 "Um campo vazio do Utilizador do GitLab adicionará o nome completo do utilizador do FogBugz (por exemplo, \"Por John Smith\") na descrição de todos os problemas e comentários. Ele também irá associar e/ou atribuir estes problemas e comentários ao criador do projeto."
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "Ocorreu um erro"
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr "Ocorreu um erro ao pré-visualizar o blob"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "Ocorreu um erro ao alternar a notificação de assinatura"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "Ocorreu um erro ao atualizar o peso do problema"
@@ -2803,9 +2968,6 @@ 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 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."
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ msgstr ""
msgid "An error occurred while loading the pipelines jobs."
msgstr ""
-msgid "An error occurred while loading the subscription details."
-msgstr "Ocorreu um erro ao carregar os detalhes da assinatura."
-
msgid "An error occurred while making the request."
msgstr "Ocorreu um erro ao fazer o pedido."
@@ -2938,6 +3094,9 @@ msgstr "Ocorreu um erro ao renderizar a mensagem de pré-visualização da trans
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr "Ocorreu um erro ao guardar o estado de sobreposição do LDAP. Por favor
msgid "An error occurred while saving assignees"
msgstr "Ocorreu um erro ao guardar destinatários"
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr "Ocorreu um erro ao assinar as notificações."
@@ -2980,6 +3136,9 @@ msgstr "Ocorreu um erro ao cancelar a assinatura das notificações."
msgid "An error occurred while updating approvers"
msgstr "Ocorreu um erro ao atualizar aprovadores"
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr "Arquivar trabalhos"
msgid "Archive project"
msgstr "Arquivar projeto"
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr "Atribuído a mim"
@@ -3801,8 +3966,29 @@ msgstr "Ele irá construir, testar e implantar, automaticamente, a tua aplicaçÃ
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Saber mais no %{link_to_documentation}"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "A pipeline Auto DevOps foi ativada e será usada caso nenhum ficheiro de configuração de IC alternativo, for encontrado. %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr ""
@@ -3822,6 +4008,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 "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr "Nota"
msgid "Available"
msgstr "Disponível"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr "URL da imagem do emblema"
msgid "Badges|Badge image preview"
msgstr "Pré-visualização da imagem do emblema"
-msgid "Badges|Delete badge"
-msgstr "Apagar emblema"
-
msgid "Badges|Delete badge?"
msgstr "Apagar emblema?"
@@ -3981,6 +4170,12 @@ msgstr "URL raiz do Bamboo como https://bamboo.example.com"
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr "Deves configurar uma etiqueta de revisão automático e um disparador de repositório no Bamboo."
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Tem cuidado. Alterar o espaço de nomes do projeto pode ter efeitos secundários não intencionais."
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr "Importação de Servidores Bitbucket"
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr "Expandir"
msgid "Boards|View scope"
msgstr "Ver escopo"
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr "O ramo %{branchName} não foi encontrado no repositório deste projeto."
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr "definições do projeto"
msgid "Branches|protected"
msgstr "protegido"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr "Mensagem de transmissão criada com sucesso."
@@ -4332,9 +4557,21 @@ msgstr "Incorporado"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr "Abrir peso do problema"
@@ -4365,7 +4602,7 @@ msgstr "Por %{user_name}"
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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr "Não foi possível criar o relatório de abuso. Este utilizador foi bloq
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr "Todos os ambientes"
msgid "CiVariable|Create wildcard"
msgstr "Criar caractere especial"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr "Ocorreu um erro ao guardar as variáveis"
-
msgid "CiVariable|Masked"
msgstr "Mascarado"
@@ -5163,9 +5403,6 @@ msgstr "Alternar mascarado"
msgid "CiVariable|Toggle protected"
msgstr "Alternar protegido"
-msgid "CiVariable|Validation failed"
-msgstr "Falha na validação"
-
msgid "Classification Label (optional)"
msgstr "Etiqueta de classificação (opcional)"
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr "Fechar épico"
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr "Fechar objetivo"
@@ -5298,7 +5538,7 @@ msgstr "Problemas Fechados"
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr "Aprende mais sobre %{help_link_start_machine_type}tipos de máquina%{hel
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "Aprende mais sobre %{help_link_start}zonas%{help_link_end}."
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr "Aprende mais sobre os Kubernetes"
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr "Nenhum projeto encontrado"
msgid "ClusterIntegration|No projects matched your search"
msgstr "Nenhum projeto correspondeu à tua pesquisa"
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 "Remove a integração do cluster do Kubernetes"
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr "Pesquisar projetos"
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr "Selecionar projeto para escolher a zona"
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr "Selecionar zona"
@@ -6195,6 +6426,9 @@ msgstr "O endereço IP está em processo de atribuição. Verifica o teu cluster
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr "Houve um problema ao autenticar com o teu cluster. Por favor, certifica-te de que o teu Certificado e Token da CA são válidos."
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr "Pedido de mesclagem criado %{mergeRequestLink} em %{projectLink}"
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr "Erro ao enviar o ficheiro."
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr "Ficheiros, diretórios e submódulos no caminho %{path} para referência de envio %{ref}"
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr "Importar vários repositórios ao enviar um ficheiro de manifesto."
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ 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 "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr "Reabrir objetivo"
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr "Executadores Compartilhados"
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr "Conectado com a autenticação de %{authentication}"
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr "A fase de revisão mostra a hora do primeiro envio para criar o envio de
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr "Este é um registo de segurança de eventos importantes que envolvem a tua conta."
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr "Também podes enviar ficheiros existentes do teu computador ao usar as i
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr "nome do ramo"
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index 136ddb9ae67..2c4786bbb63 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-10-02 18:40\n"
+"PO-Revision-Date: 2020-11-03 22:39\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -208,6 +208,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -244,12 +250,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -463,6 +463,18 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{count} more"
msgstr ""
@@ -505,6 +517,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -550,6 +568,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -676,9 +700,6 @@ 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 ""
@@ -781,7 +802,7 @@ msgstr[2] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -799,6 +820,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1018,9 +1042,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1060,6 +1081,18 @@ msgstr[2] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1090,6 +1123,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1099,17 +1135,8 @@ 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] ""
-msgstr[2] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1387,6 +1414,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1687,6 +1717,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1840,7 +1873,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1876,10 +1909,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1966,6 +1999,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1990,6 +2026,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2104,6 +2143,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2113,6 +2167,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2125,12 +2185,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2185,6 +2263,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2194,6 +2275,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2239,6 +2323,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2263,6 +2350,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2272,6 +2362,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2287,22 +2380,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2368,10 +2461,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2488,6 +2581,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2497,10 +2599,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2512,19 +2614,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2539,6 +2650,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2548,7 +2665,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2566,7 +2686,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2575,6 +2695,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2641,9 +2782,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2668,6 +2806,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2689,6 +2830,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2710,12 +2854,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2764,6 +2914,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2776,9 +2929,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2806,9 +2965,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2896,9 +3061,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2971,9 +3133,6 @@ 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 ""
@@ -3004,9 +3163,6 @@ 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 ""
@@ -3031,6 +3187,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3055,9 +3214,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3073,6 +3229,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3406,6 +3565,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3655,6 +3817,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3901,7 +4066,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3922,6 +4108,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3940,6 +4129,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3997,9 +4189,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4081,6 +4270,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4165,6 +4360,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4216,12 +4423,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4240,6 +4456,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4252,6 +4471,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4396,6 +4618,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4432,9 +4657,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4465,7 +4702,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4648,6 +4885,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5059,6 +5299,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5242,9 +5485,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5263,9 +5503,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5374,6 +5611,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5398,7 +5638,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5425,6 +5665,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5608,6 +5851,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5665,9 +5911,6 @@ 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 ""
@@ -5923,9 +6166,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5941,9 +6181,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6010,9 +6247,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6079,9 +6313,6 @@ 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 ""
@@ -6148,9 +6379,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6211,6 +6439,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6295,6 +6526,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6436,9 +6670,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6550,9 +6781,6 @@ 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 ""
@@ -6865,7 +7093,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6916,6 +7144,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6985,6 +7216,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7363,6 +7597,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7423,6 +7660,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7432,6 +7672,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7465,6 +7708,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7714,6 +7960,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7807,6 +8056,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8059,6 +8311,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8116,6 +8371,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8155,6 +8419,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8176,6 +8446,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8203,15 +8479,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8227,6 +8503,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8266,6 +8545,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8278,6 +8560,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8287,6 +8575,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8443,9 +8734,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8455,6 +8743,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8470,9 +8761,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8494,6 +8782,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8557,12 +8848,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8614,18 +8911,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8704,9 +9010,6 @@ 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 ""
@@ -8872,6 +9175,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8920,6 +9229,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9091,6 +9403,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9142,7 +9475,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9292,6 +9625,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9301,6 +9637,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9322,6 +9661,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9349,9 +9691,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9520,15 +9859,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9601,6 +9949,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9742,6 +10093,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9769,7 +10126,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9814,6 +10183,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9841,7 +10213,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10603,12 +10978,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10639,6 +11020,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10714,6 +11098,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10816,6 +11203,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10879,6 +11269,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10891,6 +11284,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11029,6 +11425,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11059,6 +11467,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11110,6 +11521,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11176,10 +11590,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11194,6 +11611,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11212,9 +11632,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11230,15 +11647,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11248,6 +11665,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11305,12 +11725,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11335,6 +11761,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11398,6 +11827,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11431,9 +11863,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11443,9 +11872,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11500,7 +11935,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12046,7 +12481,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12067,6 +12502,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12103,9 +12541,6 @@ 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 ""
@@ -12130,6 +12565,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12442,6 +12883,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12547,7 +12991,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12706,6 +13150,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12715,6 +13165,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12760,12 +13213,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12778,6 +13249,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12790,6 +13264,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12814,6 +13291,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13225,6 +13705,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13279,9 +13762,6 @@ 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 ""
@@ -13294,7 +13774,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13402,6 +13882,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13426,9 +13909,6 @@ 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 ""
@@ -13450,10 +13930,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13537,6 +14017,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13657,6 +14140,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13717,6 +14206,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13726,12 +14218,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13741,6 +14239,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13753,6 +14275,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13828,27 +14353,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13867,6 +14398,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13897,6 +14431,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13906,12 +14485,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13945,6 +14542,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13960,37 +14560,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13999,6 +14620,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14023,9 +14647,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14125,25 +14746,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14191,6 +14812,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14239,6 +14914,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14455,6 +15133,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14710,6 +15391,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14728,6 +15412,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14857,9 +15547,6 @@ 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 ""
@@ -14887,9 +15574,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14923,6 +15607,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14956,6 +15643,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15001,6 +15691,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15076,6 +15769,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15622,9 +16318,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15643,6 +16336,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15676,9 +16372,6 @@ 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 ""
@@ -15688,7 +16381,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15700,6 +16393,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15763,6 +16459,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15883,6 +16582,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15910,15 +16615,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16156,6 +16936,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16561,6 +17344,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16876,9 +17680,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16936,6 +17746,36 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17191,6 +18031,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17656,6 +18499,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17686,9 +18532,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17923,6 +18766,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17968,9 +18814,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17980,9 +18823,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18103,19 +18943,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18289,6 +19123,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18385,7 +19222,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18409,9 +19246,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18433,7 +19267,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18457,9 +19291,6 @@ 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 ""
@@ -18475,9 +19306,6 @@ 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 ""
@@ -18487,12 +19315,6 @@ 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 ""
@@ -18517,7 +19339,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18709,7 +19531,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18721,9 +19543,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18826,6 +19645,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18907,6 +19729,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18925,6 +19750,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18955,6 +19783,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18991,6 +19822,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19219,6 +20056,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19228,6 +20068,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19240,12 +20083,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19450,9 +20299,6 @@ 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 ""
@@ -20146,7 +20992,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20449,6 +21295,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20503,6 +21352,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20959,6 +21811,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21085,6 +21940,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21196,6 +22054,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21277,6 +22138,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21322,9 +22186,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21535,6 +22396,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21655,6 +22519,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21676,9 +22543,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21706,6 +22579,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21832,7 +22708,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21844,6 +22726,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21862,6 +22756,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21958,7 +22855,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21991,6 +22888,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22195,6 +23095,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22348,6 +23251,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22375,6 +23284,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22444,6 +23356,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22453,6 +23368,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22468,6 +23389,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22492,9 +23416,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22504,6 +23425,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22543,6 +23467,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22573,7 +23500,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22630,9 +23557,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22714,9 +23638,6 @@ 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] ""
@@ -22792,7 +23713,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22837,10 +23758,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22969,6 +23890,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23032,6 +23956,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23071,6 +24001,12 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23251,6 +24187,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23266,7 +24205,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23281,9 +24220,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23377,6 +24313,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23491,6 +24430,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23626,6 +24568,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23731,6 +24676,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23749,9 +24703,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23896,6 +24856,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23923,6 +24886,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23932,9 +24898,6 @@ 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 ""
@@ -23944,6 +24907,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24055,27 +25021,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24310,6 +25267,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24418,6 +25378,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24460,9 +25423,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24538,9 +25498,6 @@ 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 ""
@@ -24604,6 +25561,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24760,6 +25720,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24889,6 +25852,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24904,6 +25870,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24946,6 +25915,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25030,6 +26005,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25051,6 +26029,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25186,12 +26167,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25219,6 +26206,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25456,15 +26446,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25549,7 +26554,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25573,9 +26578,6 @@ 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 ""
@@ -25588,9 +26590,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25687,6 +26695,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25711,7 +26725,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25822,7 +26836,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25882,6 +26896,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25894,7 +26911,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25933,6 +26950,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26041,6 +27061,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26236,6 +27259,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26287,7 +27313,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26311,9 +27337,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26446,6 +27478,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26455,6 +27490,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27007,6 +28045,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27043,7 +28087,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27094,7 +28138,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27223,6 +28267,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27295,16 +28342,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27481,6 +28531,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27631,6 +28684,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27856,6 +28912,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27994,10 +29053,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28024,6 +29086,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28036,9 +29101,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28060,15 +29152,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28123,10 +29227,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28246,6 +29347,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28342,9 +29446,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28498,6 +29599,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28807,7 +29914,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28891,6 +30004,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28987,6 +30109,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29011,13 +30136,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29086,15 +30214,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29107,7 +30235,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29350,10 +30478,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29446,6 +30574,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29467,6 +30598,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29479,10 +30613,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29497,6 +30631,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29698,6 +30841,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29710,6 +30856,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29734,9 +30889,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29794,9 +30946,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29899,19 +31048,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29941,6 +31093,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29956,6 +31111,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30223,9 +31381,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30352,9 +31507,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30400,9 +31552,6 @@ 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 ""
@@ -30487,6 +31636,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30730,7 +31882,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30748,6 +31900,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30766,6 +31921,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30802,6 +31960,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30865,6 +32026,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31342,9 +32506,6 @@ 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 ""
@@ -31357,9 +32518,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31438,6 +32596,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31618,9 +32779,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31633,3 +32791,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index 3b4f55c5faa..41f19322101 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-10-02 18:49\n"
+"PO-Revision-Date: 2020-11-03 22:50\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -231,6 +231,13 @@ msgstr[1] "%d провалено"
msgstr[2] "%d провалено"
msgstr[3] "%d провалено"
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d иÑправленный результат теÑта"
@@ -273,13 +280,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d задача выбрана"
-msgstr[1] "%d задачи выбрано"
-msgstr[2] "%d задач выбрано"
-msgstr[3] "%d задач выбрано"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -338,10 +338,10 @@ msgstr[3] "еще %d комментариев"
msgid "%d open issue"
msgid_plural "%d open issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d открытое обÑуждение"
+msgstr[1] "%d открытых обÑуждениÑ"
+msgstr[2] "%d открытых обÑуждений"
+msgstr[3] "%d открытых обÑуждений"
msgid "%d pending comment"
msgid_plural "%d pending comments"
@@ -373,10 +373,10 @@ msgstr[3] "%d проектов"
msgid "%d project selected"
msgid_plural "%d projects selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d проект выбран"
+msgstr[1] "%d проекта выбрано"
+msgstr[2] "%d проектов выбрано"
+msgstr[3] "%d проектов выбрано"
msgid "%d request with warnings"
msgid_plural "%d requests with warnings"
@@ -519,6 +519,20 @@ msgstr "%{count} ÑоглаÑований от %{name}"
msgid "%{count} files touched"
msgstr "затронуто %{count} файлов"
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} more"
msgstr "ещё %{count}"
@@ -563,6 +577,12 @@ 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 "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -608,6 +628,12 @@ msgstr "%{group_name} иÑпользует управлÑемые группов
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -615,7 +641,7 @@ msgid "%{icon}You are about to add %{usersTag} people to the discussion. They wi
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 ""
+msgstr "%{integrations_link_start}Интеграции%{link_end} позволÑÑŽÑ‚ вам Ñделать Ñторонние Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ‡Ð°Ñтью вашего рабочего процеÑÑа GitLab. ЕÑли доÑтупные интеграции не ÑоответÑтвуют вашим потребноÑÑ‚Ñм, раÑÑмотрите возможноÑÑ‚ÑŒ иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ %{webhooks_link_start}веб-обработчика%{link_end}."
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} будет удален! Вы уверены?"
@@ -734,9 +760,6 @@ 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 "%{namespace_name} теперь в режиме только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ. Ð’Ñ‹ не можете: %{base_message}"
-
msgid "%{name} contained %{resultsString}"
msgstr "%{name} Ñодержал %{resultsString}"
@@ -844,7 +867,7 @@ msgstr[3] "%{reportType} %{status} обнаружено %{other} уÑзвимоÑ
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -864,6 +887,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} ГиБ"
@@ -1089,9 +1115,6 @@ msgstr "(прогреÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸)"
msgid "(deleted)"
msgstr "(удалено)"
-msgid "(external source)"
-msgstr "(внешний иÑточник)"
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1132,6 +1155,18 @@ msgstr[3] "+ещё %d"
msgid "+%{approvers} more approvers"
msgstr "+ещё %{approvers} утверждающих"
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr "+ещё %{tags}"
@@ -1164,6 +1199,9 @@ msgstr "- из - приоритета завершено"
msgid "- show less"
msgstr "- Ñвернуть"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr "0 байт"
@@ -1173,19 +1211,8 @@ msgstr "0 — без ограничений"
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "1 дополнение типа %{type}"
-msgstr[1] "%{count} дополнений типа %{type}"
-msgstr[2] "%{count} дополнений типа %{type}"
-msgstr[3] "%{count} дополнений типа %{type}"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "1 Ð¼Ð¾Ð´Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ñ‚Ð¸Ð¿Ð° %{type}"
-msgstr[1] "%{count} модификаций типа %{type}"
-msgstr[2] "%{count} модификаций типа %{type}"
-msgstr[3] "%{count} модификаций типа %{type}"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1196,10 +1223,10 @@ msgstr[3] "%d дней"
msgid "1 Issue"
msgid_plural "%d Issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "1 обÑуждение"
+msgstr[1] "%d обÑуждениÑ"
+msgstr[2] "%d обÑуждений"
+msgstr[3] "%d обÑуждений"
msgid "1 closed issue"
msgid_plural "%{issues} closed issues"
@@ -1365,7 +1392,7 @@ msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still w
msgstr "Сайт GitBook, который иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ ещё Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ замечательными возможноÑÑ‚Ñми GitLab."
msgid "A Gitpod configured Webapplication in Spring and Java"
-msgstr ""
+msgstr "ÐаÑтроенное через Gitpod веб-приложение на Spring и Java"
msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "Сайт Hexo, который иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ ещё Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ замечательными возможноÑÑ‚Ñми GitLab."
@@ -1478,6 +1505,9 @@ msgstr "Пользователь Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸ÐµÐ¼ на запиÑÑŒ в
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr "ТРЕБУЕТСЯ ДЕЙСТВИЕ: Что-то пошло не так при получении Ñертификата Let's Encrypt Ð´Ð»Ñ Ð´Ð¾Ð¼ÐµÐ½Ð° GitLab Pages '%{domain}'"
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr "Справка по API"
@@ -1539,7 +1569,7 @@ msgid "Access expiration date"
msgstr "Дата Ð¿Ñ€ÐµÐºÑ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупа"
msgid "Access expires"
-msgstr ""
+msgstr "ДоÑтуп иÑтекает"
msgid "Access forbidden. Check your access level."
msgstr "ДоÑтуп запрещен. Проверьте Ñвой уровень доÑтупа."
@@ -1779,6 +1809,9 @@ msgstr "Добавить таблицу"
msgid "Add a task list"
msgstr "Добавить ÑпиÑок задач"
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Добавить дополнительный текÑÑ‚, который будет отображатьÑÑ Ð²Ð¾ вÑех ÑообщениÑÑ… Ñлектронной почты. МакÑимум %{character_limit} Ñимволов"
@@ -1932,8 +1965,8 @@ msgstr "Добавлен %{epic_ref} как дочернÑÑ Ñ†ÐµÐ»ÑŒ."
msgid "Added %{label_references} %{label_text}."
msgstr "Добавлена%{label_references} %{label_text}."
-msgid "Added a To Do."
-msgstr "Добавлено в ÑпиÑок задач."
+msgid "Added a to do."
+msgstr ""
msgid "Added an issue to an epic."
msgstr "К цели добавлена задача."
@@ -1968,12 +2001,12 @@ msgstr "ДобавлÑет %{epic_ref} как дочерний Ñлемент."
msgid "Adds %{labels} %{label_text}."
msgstr "ДобавлÑетÑÑ %{labels}%{label_text}."
-msgid "Adds a To Do."
-msgstr "ДобавлÑет в To Do лиÑÑ‚."
-
msgid "Adds a Zoom meeting"
msgstr "ДобавлÑет вÑтречу в Zoom"
+msgid "Adds a to do."
+msgstr ""
+
msgid "Adds an issue to an epic."
msgstr "К цели добавлÑетÑÑ Ð·Ð°Ð´Ð°Ñ‡Ð°."
@@ -2058,6 +2091,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr "Owner"
@@ -2082,6 +2118,9 @@ msgstr "ОÑтановка заданий не удалаÑÑŒ"
msgid "AdminArea|Total users"
msgstr "Ð’Ñего пользователей"
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "СтатиÑтика пользователей"
@@ -2196,6 +2235,21 @@ msgstr "Ключи SSH"
msgid "AdminStatistics|Snippets"
msgstr "Сниппеты"
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr "2FA отключена"
@@ -2205,6 +2259,12 @@ msgstr "2FA включена"
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr "Ðктивные"
@@ -2217,12 +2277,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr "ÐдминиÑтраторы"
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr "Заблокировать"
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Заблокировать пользователÑ"
@@ -2277,6 +2355,9 @@ msgstr "ИÑпользует меÑто"
msgid "AdminUsers|It's you!"
msgstr "Это вы!"
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr "Ðовый пользователь"
@@ -2286,6 +2367,9 @@ msgstr "Пользователи не найдены"
msgid "AdminUsers|Owned groups will be left"
msgstr "Группы, имеющиеÑÑ Ð² ÑобÑтвенноÑти будут Ñохранены"
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr "Личные проекты будут Ñохранены"
@@ -2331,6 +2415,9 @@ msgstr "Пользователь не Ñможет иÑпользовать ко
msgid "AdminUsers|The user will not receive any notifications"
msgstr "Пользователь не будет получать никаких уведомлений"
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ, введите %{projectName}"
@@ -2353,6 +2440,9 @@ msgid "AdminUsers|You are about to permanently delete the user %{username}. Issu
msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
+msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ окончательно удалить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username}. Это удалит вÑе его обÑуждениÑ, запроÑÑ‹ ÑлиÑÐ½Ð¸Ñ Ð¸ ÑвÑзанные Ñ Ð½Ð¸Ð¼Ð¸ группы. Чтобы избежать потери данных, раÑÑмотрите возможноÑÑ‚ÑŒ иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸ %{strongStart}блокировки пользователÑ%{strongEnd}. ПоÑле %{strongStart}ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ%{strongEnd}, Ð½ÐµÐ»ÑŒÐ·Ñ Ð±ÑƒÐ´ÐµÑ‚ его воÑÑтановить или отменить удаление."
+
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
msgid "AdminUsers|You cannot remove your own admin rights."
@@ -2364,6 +2454,9 @@ msgstr ""
msgid "Administration"
msgstr "ÐдминиÑтрирование"
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr "РаÑширенные"
@@ -2379,22 +2472,22 @@ 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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2450,7 +2543,7 @@ msgid "AlertManagement|Display alerts from all your monitoring tools directly wi
msgstr "Выводите ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ‚ вÑех Ñвоих инÑтрументов мониторинга непоÑредÑтвенно в Gitlab. УпроÑтите раÑÑмотрение оповещений и их превращение в инциденты."
msgid "AlertManagement|Edit"
-msgstr ""
+msgstr "Редактировать"
msgid "AlertManagement|Environment"
msgstr ""
@@ -2461,10 +2554,10 @@ msgstr "СобытиÑ"
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2581,6 +2674,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2590,10 +2692,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2605,19 +2707,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2632,6 +2743,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2641,7 +2758,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2659,7 +2779,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2668,6 +2788,27 @@ msgstr "ОповещениÑ"
msgid "Alerts endpoint"
msgstr "Точка Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ð¹"
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr "Ðлгоритм"
@@ -2734,9 +2875,6 @@ msgstr ""
msgid "All threads resolved"
msgstr "Ð’Ñе темы решены"
-msgid "All users"
-msgstr "Ð’Ñе пользователи"
-
msgid "All users must have a name."
msgstr "У вÑех пользователей должно быть имÑ."
@@ -2761,6 +2899,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr "Разрешить владельцам вручную добавлÑÑ‚ÑŒ пользователей вне LDAP"
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "Разрешить проектам в Ñтой группе иÑпользовать Git LFS"
@@ -2782,6 +2923,9 @@ msgstr "Разрешить запроÑÑ‹ к локальной Ñети из Ñ
msgid "Allow requests to the local network from web hooks and services"
msgstr "Разрешать запроÑÑ‹ в локальной Ñети Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ web-перехватов и Ñлужб"
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr "Разрешить Ñтому ключу также отправлÑÑ‚ÑŒ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ (push) в репозиторий? (По умолчанию допуÑкаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ получение.)"
@@ -2803,12 +2947,18 @@ msgstr "Разрешено"
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Разрешено ограничение доменов Ñлектронной почты только Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿ верхнего уровнÑ"
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "ПозволÑет добавлÑÑ‚ÑŒ и управлÑÑ‚ÑŒ клаÑтерами Kubernetes."
@@ -2857,6 +3007,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr "Оповещение было вызвано в %{project_path}."
@@ -2869,9 +3022,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "ПуÑтое значение в поле Пользователь Gitlab добавит полное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ FogBugz (напр., \"От Ивана Кузнецова\") в опиÑание вÑех обÑуждений и комментариев, а также ÑвÑжет и/или назначит Ñти обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¸ комментарии Ñ Ñоздателем проекта."
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "Произошла ошибка"
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2899,9 +3058,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr "Произошла ошибка при предварительном проÑмотре объекта"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "Произошла ошибка при переключении подпиÑки на оповещениÑ"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "Произошла ошибка при обновлении приоритета обÑуждениÑ"
@@ -2989,9 +3154,6 @@ msgstr "Произошла ошибка при получении отчётов
msgid "An error occurred while fetching the Service Desk address."
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 "Произошла ошибка при получении ÑпиÑка панелей управлениÑ. ПожалуйÑта, попробуйте ещё раз."
@@ -3064,9 +3226,6 @@ 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 ""
@@ -3097,9 +3256,6 @@ 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 "Произошла ошибка при выполнении запроÑа."
@@ -3124,6 +3280,9 @@ msgstr "Произошла ошибка при визуализации проÑ
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr "Произошла ошибка при переназначении задач."
@@ -3148,9 +3307,6 @@ msgstr "Произошла ошибка при Ñохранении ÑтатуÑ
msgid "An error occurred while saving assignees"
msgstr "Произошла ошибка при Ñохранении ответÑтвенных"
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr "При подпиÑке на ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð¾ÑˆÐ»Ð° ошибка."
@@ -3166,6 +3322,9 @@ msgstr "При отпиÑке от уведомлений произошла оÑ
msgid "An error occurred while updating approvers"
msgstr "Произошла ошибка при обновлении утверждающих"
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3203,7 +3362,7 @@ msgid "An issue can be a bug, a todo or a feature request that needs to be discu
msgstr "Ðа обÑуждение может выноÑитÑÑ Ð±Ð°Ð³, задача или Ð·Ð°Ð¿Ñ€Ð¾Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° быть раÑÑмотрена в проекте. Кроме того, обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупны Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка и фильтрации."
msgid "An unauthenticated user"
-msgstr ""
+msgstr "Ðеавторизованный пользователь"
msgid "An unexpected error occurred while checking the project environment."
msgstr "Произошла Ð½ÐµÐ¿Ñ€ÐµÐ´Ð²Ð¸Ð´ÐµÐ½Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° при проверке Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°."
@@ -3503,6 +3662,9 @@ msgstr ""
msgid "Archive project"
msgstr "Ðрхивировать проект"
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr "Ðрхивные"
@@ -3709,7 +3871,7 @@ msgid "Assign Iteration"
msgstr ""
msgid "Assign To"
-msgstr ""
+msgstr "Ðазначить на "
msgid "Assign custom color like #FF0000"
msgstr "Ðазначьте пользовательÑкий цвет, например #FF0000"
@@ -3753,6 +3915,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr "Ðазначен %{assignee_name}"
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr "Ðазначить мне"
@@ -3837,10 +4002,10 @@ msgid "AuditLogs|Action"
msgstr ""
msgid "AuditLogs|Author"
-msgstr ""
+msgstr "Ðвтор"
msgid "AuditLogs|Date"
-msgstr ""
+msgstr "Дата"
msgid "AuditLogs|Failed to find %{type}. Please search for another %{type}."
msgstr ""
@@ -3852,7 +4017,7 @@ msgid "AuditLogs|Group Events"
msgstr ""
msgid "AuditLogs|IP Address"
-msgstr ""
+msgstr "IP-адреÑ"
msgid "AuditLogs|Member Events"
msgstr ""
@@ -3861,16 +4026,16 @@ msgid "AuditLogs|No matching %{type} found."
msgstr ""
msgid "AuditLogs|Object"
-msgstr ""
+msgstr "Объект"
msgid "AuditLogs|Project Events"
-msgstr ""
+msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°"
msgid "AuditLogs|Target"
-msgstr ""
+msgstr "Цель"
msgid "AuditLogs|This month"
-msgstr ""
+msgstr "Этот меÑÑц"
msgid "AuditLogs|User Events"
msgstr ""
@@ -3918,13 +4083,13 @@ msgid "Author"
msgstr "Ðвтор"
msgid "Author: %{author_name}"
-msgstr ""
+msgstr "Ðвтор: %{author_name}"
msgid "Authored %{timeago}"
-msgstr ""
+msgstr "Создал %{timeago}"
msgid "Authored %{timeago} by %{author}"
-msgstr ""
+msgstr "Создано %{author} %{timeago}"
msgid "Authorization code:"
msgstr "Код авторизации:"
@@ -3939,13 +4104,13 @@ msgid "Authorization was granted by entering your username and password in the a
msgstr ""
msgid "Authorize"
-msgstr ""
+msgstr "Ðвторизовать"
msgid "Authorize %{link_to_client} to use your account?"
msgstr "ÐвторизуйтеÑÑŒ %{link_to_client} Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð°ÑˆÐµÐ¹ учетной запиÑи?"
msgid "Authorize %{user} to use your account?"
-msgstr ""
+msgstr "Разрешить %{user} иÑпользовать вашу учетную запиÑÑŒ?"
msgid "Authorize external services to send alerts to GitLab"
msgstr ""
@@ -4001,8 +4166,29 @@ msgstr "Ð”Ð»Ñ Ñтого проекта может быть активировÐ
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Подробнее по ÑÑылке %{link_to_documentation}"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ Auto DevOps была включена и будет иÑпользоватьÑÑ, еÑли не найден альтернативный файл конфигурации CI. %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr "Ðвтозаполнение"
@@ -4022,6 +4208,9 @@ msgstr "ÐвтоматичеÑкое управление Ñертификата
msgid "Automatic certificate management using Let's Encrypt"
msgstr "ÐвтоматичеÑкое управление Ñертификатами Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Let's Encrypt"
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -4040,6 +4229,9 @@ msgstr "Заметка"
msgid "Available"
msgstr "ДоÑтупен"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -4097,9 +4289,6 @@ msgstr "URL-Ð°Ð´Ñ€ÐµÑ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐºÐ°"
msgid "Badges|Badge image preview"
msgstr "Предварительный проÑмотра Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐºÐ°"
-msgid "Badges|Delete badge"
-msgstr "Удалить значок"
-
msgid "Badges|Delete badge?"
msgstr "Удалить значок?"
@@ -4181,6 +4370,12 @@ msgstr "Корневой URL-Ð°Ð´Ñ€ÐµÑ Bamboo, подобный https://bamboo.
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr "Ð’Ñ‹ должны наÑтроить автоматичеÑкое приÑвоение меток ревизиÑм и триггер Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ Ð² ÑервиÑе Bamboo."
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Будьте оÑторожны. Изменение пути проекта может вызвать нежелательные побочные Ñффекты."
@@ -4265,6 +4460,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "Улучшить"
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr "Импорт из Bitbucket Server"
@@ -4316,12 +4523,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4340,6 +4556,9 @@ msgstr "Развернуть"
msgid "Boards|View scope"
msgstr "ПроÑмотр облаÑти"
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4352,6 +4571,9 @@ msgstr "Ветка %{branchName} не найдена в репозитории Ð
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4496,6 +4718,9 @@ msgstr "наÑтройках проекта"
msgid "Branches|protected"
msgstr "защищена"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4532,9 +4757,21 @@ msgstr "Ð’Ñтроенный"
msgid "Bulk request concurrency"
msgstr "РаÑпараллеливание маÑÑовых запроÑов"
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr "ÐиÑходÑщий график"
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr "Открыть приоритет задачи"
@@ -4565,7 +4802,7 @@ msgstr "От %{user_name}"
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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4748,6 +4985,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr "Ðевозможно проводить одновременно неÑколько импортов из Jira"
@@ -5049,7 +5289,7 @@ msgid "Checkout|Create a new group"
msgstr ""
msgid "Checkout|Credit card form failed to load. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ загрузить форму кредитной карты. ПожалуйÑта, попробуйте ещё раз."
msgid "Checkout|Credit card form failed to load: %{message}"
msgstr ""
@@ -5061,7 +5301,7 @@ msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
msgid "Checkout|Failed to confirm your order! Please try again."
-msgstr ""
+msgstr "Ðе удалить подтвердить ваш заказ! ПожалуйÑта, попробуйте ещё раз."
msgid "Checkout|Failed to confirm your order: %{message}. Please try again."
msgstr ""
@@ -5136,7 +5376,7 @@ msgid "Checkout|Your organization"
msgstr "Ваша организациÑ"
msgid "Checkout|Your subscription will be applied to this group"
-msgstr ""
+msgstr "Ваша подпиÑка будет применена к Ñтой группе"
msgid "Checkout|Zip code"
msgstr ""
@@ -5159,6 +5399,9 @@ msgstr "Дочерний объект не ÑущеÑтвует."
msgid "Child epic doesn't exist."
msgstr "Дочерней цели не ÑущеÑтвует."
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5205,7 +5448,7 @@ msgid "Choose visibility level, enable/disable project features (issues, reposit
msgstr "Выберите уровень доÑтупа, включите / отключите функции проекта (обÑуждениÑ, репозиторий, Wiki, Ñниппеты) и наÑтройте Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð½Ð° проекте."
msgid "Choose what content you want to see on a group’s overview page."
-msgstr ""
+msgstr "Выберите Ñодержимое, которое вы хотите видеть на Ñтранице обзора группы."
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr ""
@@ -5342,9 +5585,6 @@ msgstr "Ð’Ñе Ñреды"
msgid "CiVariable|Create wildcard"
msgstr "Создать шаблон"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr "Ошибка при Ñохранении переменных"
-
msgid "CiVariable|Masked"
msgstr "ЗамаÑкировано"
@@ -5363,9 +5603,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr "Включить защиту"
-msgid "CiVariable|Validation failed"
-msgstr "Проверка не удалаÑÑŒ"
-
msgid "Classification Label (optional)"
msgstr "Метка клаÑÑификации (опционально)"
@@ -5474,6 +5711,9 @@ msgstr "Закрыть %{tabname}"
msgid "Close epic"
msgstr "Завершить цель"
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr "Закрыть Ñтап"
@@ -5498,7 +5738,7 @@ msgstr "Закрытые обÑуждениÑ"
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5525,6 +5765,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5708,6 +5951,9 @@ msgstr "ОчиÑтить кÑш клаÑтера"
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr "Проект ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÐ»Ð°Ñтером (alpha)"
@@ -5765,9 +6011,6 @@ msgstr "Ðе удалоÑÑŒ загрузить типы ÑкземплÑров"
msgid "ClusterIntegration|Could not load networks"
msgstr ""
-msgid "ClusterIntegration|Could not load regions from your AWS account"
-msgstr "Ðе удалоÑÑŒ загрузить регионы из вашего аккаунта AWS"
-
msgid "ClusterIntegration|Could not load security groups for the selected VPC"
msgstr "Ðе удалоÑÑŒ загрузить группы безопаÑноÑти Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ VPC"
@@ -6023,9 +6266,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -6041,9 +6281,6 @@ msgstr "Загрузка ролей IAM"
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr "Загрузка регионов"
-
msgid "ClusterIntegration|Loading VPCs"
msgstr "Загрузка VPCs"
@@ -6110,9 +6347,6 @@ msgstr "Проекты не найдены"
msgid "ClusterIntegration|No projects matched your search"
msgstr "Ðет проектов, ÑоответÑтвующих вашему поиÑковому запроÑу"
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr "Группы безопаÑноÑти не найдены"
@@ -6179,9 +6413,6 @@ 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 "Удалить интеграцию клаÑтера Kubernetes"
@@ -6248,9 +6479,6 @@ msgstr "ПоиÑк Ñетей"
msgid "ClusterIntegration|Search projects"
msgstr "ПоиÑк проектов"
-msgid "ClusterIntegration|Search regions"
-msgstr "ПоиÑк регионов"
-
msgid "ClusterIntegration|Search security groups"
msgstr "ПоиÑк групп безопаÑноÑти"
@@ -6311,6 +6539,9 @@ msgstr "Выберите проект, чтобы выбрать зону"
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr "Выберете зону"
@@ -6395,6 +6626,9 @@ msgstr "Конечный Ñтап заключаетÑÑ Ð² процеÑÑе нÐ
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr "Произошла ошибка при аутентификации Ñ Ð²Ð°ÑˆÐ¸Ð¼ клаÑтером. УбедитеÑÑŒ, что Ñертификат CA и токен дейÑтвительны."
@@ -6536,9 +6770,6 @@ msgstr "Выберите VPC"
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr "Выберите группу безопаÑноÑти"
@@ -6612,7 +6843,7 @@ msgid "Cohorts|Inactive users"
msgstr ""
msgid "Cohorts|Month %{month_index}"
-msgstr ""
+msgstr "МеÑÑц %{month_index}"
msgid "Cohorts|New users"
msgstr ""
@@ -6650,9 +6881,6 @@ msgstr ""
msgid "ComboSearch is not defined"
msgstr "ComboSearch не определен"
-msgid "Coming soon"
-msgstr ""
-
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
msgstr ""
@@ -6966,7 +7194,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -7017,6 +7245,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr "СвÑзатьÑÑ Ñ Ð¾Ñ‚Ð´ÐµÐ»Ð¾Ð¼ продаж Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ"
@@ -7088,6 +7319,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7131,7 +7365,7 @@ msgid "ContainerRegistry|Expiration schedule:"
msgstr "РаÑпиÑание иÑтечениÑ:"
msgid "ContainerRegistry|Filter by name"
-msgstr ""
+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 ""
@@ -7467,6 +7701,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7527,6 +7764,9 @@ msgstr "Ðе удалоÑÑŒ удалить никнейм чата %{chat_name}.
msgid "Could not delete wiki page"
msgstr "Ðе удалоÑÑŒ удалить вики-Ñтраницу"
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7536,6 +7776,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7569,6 +7812,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr "Страна"
@@ -7676,7 +7922,7 @@ msgid "Create file"
msgstr "Создать файл"
msgid "Create from"
-msgstr ""
+msgstr "Создать из"
msgid "Create group"
msgstr "Создать группу"
@@ -7819,6 +8065,9 @@ msgstr ""
msgid "Created on"
msgstr "Дата ÑозданиÑ"
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr "Дата ÑозданиÑ:"
@@ -7912,6 +8161,9 @@ msgstr "ПользовательÑкий путь конфигурации CI"
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr "ПользовательÑкое Ð¸Ð¼Ñ Ñ…Ð¾Ñта (Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² приватных Ñлектронных адреÑах почты при коммите)"
@@ -8145,7 +8397,7 @@ msgid "CycleAnalytics|Select labels"
msgstr ""
msgid "CycleAnalytics|Show"
-msgstr ""
+msgstr "Показать"
msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
msgstr ""
@@ -8165,6 +8417,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8222,6 +8477,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8261,6 +8525,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8282,6 +8552,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8309,15 +8585,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8333,6 +8609,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8372,6 +8651,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8384,6 +8666,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8393,6 +8681,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr "Данные вÑе еще вычиÑлÑÑŽÑ‚ÑÑ..."
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8409,7 +8700,7 @@ msgid "Date range cannot exceed %{maxDateRange} days."
msgstr ""
msgid "Day of month"
-msgstr ""
+msgstr "День меÑÑца"
msgid "DayTitle|F"
msgstr "Пт"
@@ -8549,9 +8840,6 @@ msgstr ""
msgid "Delete Comment"
msgstr "Удалить комментарий"
-msgid "Delete Snippet"
-msgstr "Удалить Ñниппет"
-
msgid "Delete Value Stream"
msgstr ""
@@ -8561,6 +8849,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr "Удалить артефакты"
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr "Удалить доÑку"
@@ -8576,9 +8867,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr "Удалить ÑпиÑок"
-
msgid "Delete pipeline"
msgstr "Удалить Ñборочную линию"
@@ -8600,6 +8888,9 @@ msgstr ""
msgid "Delete source branch"
msgstr "Удалить иÑходную ветку"
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr "Удалить вложение"
@@ -8607,7 +8898,7 @@ msgid "Delete user list"
msgstr ""
msgid "Delete variable"
-msgstr ""
+msgstr "Удалить переменную"
msgid "DeleteProject|Delete %{name}"
msgstr ""
@@ -8663,12 +8954,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr "Отказано в авторизации под чат никнеймом %{user_name}."
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr "Отклонить"
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8723,18 +9020,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr "Заданию не удалоÑÑŒ Ñгенерировать ÑпиÑок завиÑимоÑтей"
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr "ЛицензиÑ"
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr "Упаковщик"
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr "Произошел Ñбой Ð·Ð°Ð´Ð°Ð½Ð¸Ñ %{codeStartTag}dependency_scanning%{codeEndTag} и не получилоÑÑŒ Ñгенерировать ÑпиÑок. ПожалуйÑта, убедитеÑÑŒ, что задание работает правильно и Ñнова запуÑтите Ñборку."
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8816,9 +9122,6 @@ 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 "СоответÑтвие метке %{appLabel} было удалено Ð´Ð»Ñ Ñтендов развертываниÑ. Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾ чтобы увидеть вÑе ÑкземплÑры на вашем Ñтенде, вы должны обновить ваш график и повторно провеÑти развертывание."
-
msgid "DeployFreeze|Freeze end"
msgstr ""
@@ -8984,6 +9287,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -9032,6 +9341,9 @@ msgstr "ОпиÑание"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "ОпиÑание обработано Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ %{link_start}GitLab Flavored Markdown%{link_end}"
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9192,7 +9504,7 @@ msgid "Details"
msgstr "ИнформациÑ"
msgid "Details (default)"
-msgstr ""
+msgstr "ПодробноÑти (по умолчанию)"
msgid "Detect host keys"
msgstr ""
@@ -9203,6 +9515,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9254,8 +9587,8 @@ msgstr "Выключить групповые обработчиков задаÐ
msgid "Disable public access to Pages sites"
msgstr "Отключить общий доÑтуп к Ñайтам Pages"
-msgid "Disable shared Runners"
-msgstr "Отключить общие Runner'ы"
+msgid "Disable shared runners"
+msgstr ""
msgid "Disable two-factor authentication"
msgstr "Отключить двухфакторную аутентификацию"
@@ -9273,7 +9606,7 @@ msgid "Discard all changes"
msgstr "Отменить вÑе изменениÑ"
msgid "Discard all changes?"
-msgstr ""
+msgstr "Отменить вÑе изменениÑ?"
msgid "Discard changes"
msgstr "Отменить изменениÑ"
@@ -9405,6 +9738,9 @@ msgstr "ДокументациÑ"
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9414,6 +9750,9 @@ msgstr "Домен"
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9435,6 +9774,9 @@ 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 -----»."
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "Ðе показывать Ñнова"
@@ -9462,9 +9804,6 @@ msgstr "Скачать как"
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr "Скачать реÑурÑ"
-
msgid "Download codes"
msgstr "Скачать коды"
@@ -9633,15 +9972,24 @@ msgstr ""
msgid "Edit stage"
msgstr "Редактировать Ñтап"
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr "Изменить wiki Ñтраницу"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9714,6 +10062,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr "Отправить по Ñлектронной почте Ñообщение о ÑтатуÑе Ñборочной ÑпиÑку получателей."
+msgid "Email updates (optional)"
+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 "Похоже, что ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð° пуÑта. УбедитеÑÑŒ, что ваш ответ находитÑÑ Ð²Ð²ÐµÑ€Ñ…Ñƒ пиÑьма, мы не можем обрабатывать вÑтроенные ответы."
@@ -9787,16 +10138,16 @@ msgid "Enable"
msgstr "Включить"
msgid "Enable %{link_start}Gitpod%{link_end} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
+msgstr "Включите интеграцию Ñ %{link_start}Gitpod%{link_end}, чтобы запуÑкать Ñреды разработки в браузере прÑмо через GitLab."
msgid "Enable Auto DevOps"
msgstr "Включить Auto DevOps"
msgid "Enable Gitpod"
-msgstr ""
+msgstr "Включить Gitpod"
msgid "Enable Gitpod?"
-msgstr ""
+msgstr "Включить Gitpod?"
msgid "Enable HTML emails"
msgstr ""
@@ -9855,6 +10206,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9882,7 +10239,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9927,6 +10296,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr "Произошла ошибка во Ð²Ñ€ÐµÐ¼Ñ Ñ€ÐµÐ½Ð´ÐµÑ€Ð¸Ð½Ð³Ð°: %{err}"
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "ЗаканчиваетÑÑ Ð² (UTC)"
@@ -9954,7 +10326,10 @@ msgstr "Введите диапазон IP-адреÑов"
msgid "Enter a number"
msgstr "Введите номер"
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10636,7 +11011,7 @@ msgid "Events"
msgstr "СобытиÑ"
msgid "Events in %{project_path}"
-msgstr ""
+msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð² %{project_path}"
msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
msgstr ""
@@ -10648,13 +11023,13 @@ msgid "Every day (at %{time})"
msgstr ""
msgid "Every month"
-msgstr ""
+msgstr "Каждый меÑÑц"
msgid "Every month (Day %{day} at %{time})"
msgstr ""
msgid "Every three months"
-msgstr ""
+msgstr "Каждые три меÑÑца"
msgid "Every two weeks"
msgstr ""
@@ -10716,12 +11091,18 @@ msgstr ""
msgid "Except policy:"
msgstr "За иÑключением политики:"
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr "ИÑÐºÐ»ÑŽÑ‡Ð°Ñ ÐºÐ¾Ð¼Ð¼Ð¸Ñ‚Ñ‹-ÑлиÑниÑ. Ограничено до %{limit} коммитов."
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "ИÑÐºÐ»ÑŽÑ‡Ð°Ñ ÐºÐ¾Ð¼Ð¼Ð¸Ñ‚Ñ‹-ÑлиÑниÑ. Ограничено до 6000 коммитов."
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10752,6 +11133,9 @@ msgstr ""
msgid "Expand approvers"
msgstr "Развернуть утверждающих"
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10827,6 +11211,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "ЭкÑпорт проекта"
@@ -10924,11 +11311,14 @@ msgid "Failed to create To-Do for the design."
msgstr ""
msgid "Failed to create a branch for this issue. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ Ñоздать ветку Ð´Ð»Ñ Ñтого обÑуждениÑ. ПожалуйÑта, попробуйте ещё раз."
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10992,6 +11382,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr "Ðе удалоÑÑŒ загрузить Ñтапы. ПожалуйÑта, попробуйте еще раз."
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -11004,6 +11397,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr "Ðе удалоÑÑŒ пометить Ñту задачу как дубликат, потому что ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° не была найдена."
@@ -11050,7 +11446,7 @@ msgid "Failed to remove user key."
msgstr ""
msgid "Failed to reset key. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ ÑброÑить ключ. ПожалуйÑта, попробуйте ещё раз."
msgid "Failed to save merge conflicts resolutions. Please try again!"
msgstr ""
@@ -11143,6 +11539,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr "* (Ð’Ñе окружениÑ)"
@@ -11173,6 +11581,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr "ÐаÑтройка функциональных опций"
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr "Создать функциональную опцию"
@@ -11224,6 +11635,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11290,11 +11704,14 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr "Процент Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ (авторизованные пользователи)"
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
-msgstr "Процент Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть целым чиÑлом от 0 до 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
+msgstr ""
msgid "FeatureFlags|Protected"
msgstr "Защищено"
@@ -11308,6 +11725,9 @@ msgstr "Процент развертываниÑ"
msgid "FeatureFlags|Rollout Strategy"
msgstr "Ð¡Ñ‚Ñ€Ð°Ñ‚ÐµÐ³Ð¸Ñ Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ"
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11326,9 +11746,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11344,15 +11761,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11360,6 +11777,9 @@ msgid "FeatureFlag|Type"
msgstr "Тип"
msgid "FeatureFlag|User IDs"
+msgstr "ID пользователей"
+
+msgid "FeatureFlag|User List"
msgstr ""
msgid "Feb"
@@ -11405,7 +11825,7 @@ msgid "File moved"
msgstr "Файл перемещен"
msgid "File name"
-msgstr ""
+msgstr "Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°"
msgid "File renamed with no changes."
msgstr ""
@@ -11419,12 +11839,18 @@ msgstr "Шаблоны файлов"
msgid "File upload error."
msgstr "Ошибка загрузки файла."
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "Файлы"
msgid "Files breadcrumb"
msgstr "Файлы навигации"
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr "Файлы, каталоги и Ñубмодули в пути %{path} Ð´Ð»Ñ ÑÑылки на коммит %{ref}"
@@ -11449,6 +11875,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11504,7 +11933,7 @@ msgid "Filter results..."
msgstr ""
msgid "Filter your repositories by name"
-msgstr ""
+msgstr "Фильтровать ваши репозитории по имени"
msgid "Filter..."
msgstr "Фильтр..."
@@ -11512,6 +11941,9 @@ msgstr "Фильтр..."
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11545,9 +11977,6 @@ msgstr ""
msgid "Finished"
msgstr "Завершено"
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11557,9 +11986,15 @@ msgstr "Первый день недели"
msgid "First name"
msgstr "ИмÑ"
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11614,8 +12049,8 @@ 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 internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
msgid "For more info, read the documentation."
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации читайте документацию."
@@ -12160,7 +12595,7 @@ msgstr "Ðачните работу Ñ Ñ€ÐµÐ»Ð¸Ð·Ð°Ð¼Ð¸"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr "Git LFS не включен на Ñтом GitLab Ñервере, ÑвÑжитеÑÑŒ Ñ Ð²Ð°ÑˆÐ¸Ð¼ админиÑтратором."
-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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12181,6 +12616,9 @@ msgstr "ПоверхноÑтное клонирование Git"
msgid "Git strategy for pipelines"
msgstr "Команда Git Ð´Ð»Ñ Ñборочных линий"
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr "ВерÑÐ¸Ñ Git"
@@ -12217,9 +12655,6 @@ 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 ""
@@ -12244,6 +12679,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr "GitLab Ð´Ð»Ñ Slack"
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12401,19 +12842,19 @@ msgid "Gitlab Pages"
msgstr "Gitlab Pages"
msgid "Gitpod"
-msgstr ""
+msgstr "Gitpod"
msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
+msgstr "Добавьте URL в ваш инÑÑ‚Ð°Ð½Ñ GitLab, наÑтроенный, чтобы читать ваши проекты GitLab."
msgid "Gitpod|Enable Gitpod integration"
-msgstr ""
+msgstr "Включить интеграцию Ñ Gitpod"
msgid "Gitpod|Gitpod URL"
-msgstr ""
+msgstr "URL Gitpod"
msgid "Gitpod|e.g. https://gitpod.example.com"
-msgstr ""
+msgstr "например, https://gitpod.example.com"
msgid "Given access %{time_ago}"
msgstr "ДоÑтуп предоÑтавлен %{time_ago}"
@@ -12556,6 +12997,9 @@ msgstr "Перейдите к вашим проектам"
msgid "Go to your snippets"
msgstr "Перейти к вашим Ñниппетам"
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12661,7 +13105,7 @@ msgstr "URL группы"
msgid "Group avatar"
msgstr "Ðватар группы"
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12719,7 +13163,7 @@ msgid "Group overview"
msgstr ""
msgid "Group overview content"
-msgstr ""
+msgstr "Содержание обзора группы"
msgid "Group path is already taken. Suggestions: "
msgstr ""
@@ -12820,6 +13264,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Чтобы раÑширить поиÑк, измените или удалите фильтры; Ñ %{startDate} до %{endDate}."
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "Отпечаток Ñертификата"
@@ -12829,6 +13279,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12863,7 +13316,7 @@ msgid "GroupSAML|Manage your group’s membership while adding another level of
msgstr ""
msgid "GroupSAML|Members"
-msgstr ""
+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 ""
@@ -12874,12 +13327,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12892,6 +13363,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr "SAML ÐаÑтройки единого входа"
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr "URL конечной точки SCIM API"
@@ -12904,6 +13378,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12928,6 +13405,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr "Ваш токен SCIM"
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13073,7 +13553,7 @@ msgid "Groups (%{count})"
msgstr "Группы (%{count})"
msgid "Groups (%{groups})"
-msgstr ""
+msgstr "Группы (%{groups})"
msgid "Groups and projects"
msgstr ""
@@ -13341,6 +13821,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "ИÑториÑ"
@@ -13395,9 +13878,6 @@ 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}. Войдите, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ аккаунт, чтобы принÑÑ‚ÑŒ приглашение."
-msgid "I accept the %{terms_link_start}Terms of Service and Privacy Policy%{terms_link_end}"
-msgstr ""
-
msgid "I accept the %{terms_link}"
msgstr ""
@@ -13410,8 +13890,8 @@ 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 "Я хотел бы получать Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñлектронной почте о GitLab"
+msgid "I'd like to receive updates about GitLab via email"
+msgstr ""
msgid "ID"
msgstr "ID"
@@ -13518,6 +13998,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13542,9 +14025,6 @@ 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 "ЕÑли вы израÑходуете 100%% ёмкоÑти хранилища, то не Ñможете: %{base_message}"
-
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
@@ -13566,10 +14046,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13629,7 +14109,7 @@ msgid "Import failed due to a GitHub error: %{original}"
msgstr ""
msgid "Import from"
-msgstr ""
+msgstr "Импортировать из"
msgid "Import from Jira"
msgstr "Импортировать из Jira"
@@ -13655,6 +14135,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr "Импорт учаÑтников проекта"
@@ -13775,6 +14258,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr "Лимиты, ÑвÑзанные Ñ Ð£Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸ÐµÐ¼ инцидентами"
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13835,6 +14324,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13844,12 +14336,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13859,6 +14357,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr "Инциденты"
@@ -13871,6 +14393,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13946,27 +14471,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr "Ð’Ñтавить цитату"
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr "Ð’Ñтавить код"
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr "СтатиÑтика (Insights)"
@@ -13985,6 +14516,9 @@ msgstr "УÑтановите GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "УÑтановить Runner на Kubernetes"
+msgid "Install a Runner"
+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 ""
@@ -14016,6 +14550,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -14025,12 +14604,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -14064,6 +14661,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -14079,38 +14679,59 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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 group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
-msgstr "Внутренний - Проект доÑтупен любому зарегиÑтрированному пользователю."
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "Internal URL (optional)"
msgstr "Внутренний URL (необÑзательно)"
@@ -14118,6 +14739,9 @@ msgstr "Внутренний URL (необÑзательно)"
msgid "Internal users"
msgstr "Внутренние пользователи"
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Шаблон интервала"
@@ -14142,9 +14766,6 @@ msgstr ""
msgid "Invalid URL"
msgstr "ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ ÑÑылка"
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14244,25 +14865,25 @@ msgstr "ПриглаÑить учаÑтников"
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14310,6 +14931,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14323,13 +14998,13 @@ msgid "Is blocked by"
msgstr ""
msgid "Is this GitLab trial for your company?"
-msgstr ""
+msgstr "Это пробный период GitLab Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ¹ компании?"
msgid "Is using license seat:"
msgstr ""
msgid "Is using seat"
-msgstr ""
+msgstr "ИÑпользует меÑто"
msgid "IssuableStatus|Closed"
msgstr "Закрыто"
@@ -14358,6 +15033,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "ДоÑки обÑуждений"
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr "ОбÑуждение уже было продвинуто до цели."
@@ -14574,6 +15252,9 @@ msgstr "Янв."
msgid "January"
msgstr "Январь"
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14829,6 +15510,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14847,6 +15531,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr "Ключи"
@@ -14976,9 +15666,6 @@ 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 "и еще %{count}"
-
msgid "Language"
msgstr "Язык"
@@ -15007,9 +15694,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr "ПоÑледнее обращение"
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr "ПоÑледнÑÑ Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð›Ð¸Ð½Ð¸Ñ"
@@ -15043,6 +15727,9 @@ msgstr ""
msgid "Last name"
msgstr "ФамилиÑ"
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr "ПоÑледний ответ от"
@@ -15076,6 +15763,9 @@ msgstr "ПоÑледний раз обновлено"
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr "ПоÑледнее иÑпользование:"
@@ -15121,6 +15811,9 @@ msgstr "Узнайте, как включить Ñинхронизацию"
msgid "Learn more"
msgstr "Подробнее"
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr "Узнайте больше об \"Auto DevOps\""
@@ -15196,6 +15889,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15684,7 +16380,7 @@ msgid "Manage Web IDE features"
msgstr "Управление функциÑми Web IDE"
msgid "Manage access"
-msgstr ""
+msgstr "УправлÑÑ‚ÑŒ доÑтупом"
msgid "Manage all notifications"
msgstr "Управление уведомлениÑми"
@@ -15749,9 +16445,6 @@ msgstr "Мар."
msgid "March"
msgstr "Март"
-msgid "Mark To Do as done"
-msgstr "Отметить как выполненное"
-
msgid "Mark as done"
msgstr "Отметить как выполнено"
@@ -15770,6 +16463,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr "Markdown"
@@ -15803,9 +16499,6 @@ 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 ""
@@ -15815,7 +16508,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15827,6 +16520,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15890,6 +16586,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -16010,6 +16709,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr "УчаÑтник Ñ %{date}"
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr "УчаÑтники"
@@ -16037,15 +16742,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16283,6 +17063,9 @@ msgstr "Объединенные ветви удалÑÑŽÑ‚ÑÑ. Это можеÑ
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16690,6 +17473,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16703,7 +17507,7 @@ msgid "MilestoneSidebar|Edit"
msgstr ""
msgid "MilestoneSidebar|From"
-msgstr ""
+msgstr "С"
msgid "MilestoneSidebar|Issues"
msgstr "ОбÑуждениÑ"
@@ -17005,9 +17809,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -17065,6 +17875,38 @@ msgstr "ПроÑтранÑтво имён пуÑто"
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17320,6 +18162,9 @@ msgstr "Ðикогда"
msgid "New"
msgstr "Ðовый"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr "Ðовое Приложение"
@@ -17786,6 +18631,9 @@ msgstr ""
msgid "None"
msgstr "ПуÑто"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17816,9 +18664,6 @@ msgstr "ÐедоÑтаточно данных"
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr "Ðе ÑейчаÑ"
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17871,7 +18716,7 @@ msgid "Notes|This comment has changed since you started editing, please review t
msgstr "Этот комментарий изменилÑÑ Ñ Ñ‚ÐµÑ… пор, как вы начали редактирование, проÑмотрите %{open_link}обновленный комментарий%{close_link}, чтобы убедитьÑÑ, что Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð½Ðµ потерÑна"
msgid "Nothing found…"
-msgstr ""
+msgstr "Ðичего не найдено…"
msgid "Nothing to preview."
msgstr ""
@@ -18009,7 +18854,7 @@ msgid "Number of commits per MR"
msgstr ""
msgid "Number of employees"
-msgstr ""
+msgstr "ЧиÑло Ñотрудников"
msgid "Number of events"
msgstr ""
@@ -18053,6 +18898,9 @@ msgstr "OmniAuth"
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr "По плану"
@@ -18098,9 +18946,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -18110,9 +18955,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18234,19 +19076,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18420,6 +19256,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr "Добавить иÑточник NuGet"
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18516,7 +19355,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18540,9 +19379,6 @@ msgstr "XML Maven"
msgid "PackageRegistry|NPM"
msgstr "NPM"
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -18564,8 +19400,8 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
-msgstr "PyPi"
+msgid "PackageRegistry|PyPI"
+msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
@@ -18580,7 +19416,7 @@ 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 ""
@@ -18588,9 +19424,6 @@ 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 "Ðе удалоÑÑŒ получить ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¾Ð± Ñтом пакете."
@@ -18606,9 +19439,6 @@ 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 ""
@@ -18618,17 +19448,11 @@ 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|composer.json registry include"
-msgstr ""
-
-msgid "PackageRegistry|composer.json require package include"
-msgstr ""
-
msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
-msgstr ""
+msgstr "опубликовано %{author}"
msgid "PackageRegistry|yarn command"
msgstr ""
@@ -18648,7 +19472,7 @@ msgstr "NPM"
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18840,7 +19664,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18852,9 +19676,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr "ВыполнÑйте обычные дейÑÑ‚Ð²Ð¸Ñ Ð½Ð°Ð´ проектом GitLab"
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr "ÐžÐ¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñти"
@@ -18957,6 +19778,9 @@ msgstr "КоÑффициент уÑпеха:"
msgid "PipelineCharts|Successful:"
msgstr "УÑпех:"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "Ð’Ñего:"
@@ -19038,6 +19862,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr "CI Lint"
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -19056,6 +19883,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr "Ðачало работы Ñо Ñборочными линиÑми"
@@ -19086,6 +19916,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "КÑш проекта уÑпешно очищен."
@@ -19122,6 +19955,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19186,7 +20025,7 @@ msgid "Pipeline|Pipeline"
msgstr ""
msgid "Pipeline|Pipelines"
-msgstr ""
+msgstr "Сборочные линии"
msgid "Pipeline|Raw text search is not currently supported. Please use the available search tokens."
msgstr ""
@@ -19350,6 +20189,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr "ПожалуйÑта введите правильное чиÑло"
@@ -19359,6 +20201,9 @@ msgstr "ПожалуйÑта, введите или загрузите лицеÐ
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19371,12 +20216,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr "ПожалуйÑта, укажите имÑ"
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19477,7 +20328,7 @@ msgid "Preferences|Choose what content you want to see on a project’s overview
msgstr "Выберите, какое Ñодержимое вы хотите видеть на Ñтранице обзора проекта."
msgid "Preferences|Choose what content you want to see on your homepage."
-msgstr ""
+msgstr "Выберите Ñодержимое, которое вы хотите видеть на вашей главной Ñтранице."
msgid "Preferences|Customize integrations with third party services."
msgstr "ÐаÑтройте интеграцию Ñо Ñторонними ÑервиÑами."
@@ -19495,10 +20346,10 @@ msgid "Preferences|For example: 30 mins ago."
msgstr "Ðапример, 30 минут назад."
msgid "Preferences|Homepage content"
-msgstr ""
+msgstr "Содержимое главной Ñтраницы"
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
-msgstr ""
+msgstr "ВмеÑто того чтобы показывать вÑе изменённые файлы, показывать только один файл. Чтобы переключатьÑÑ Ð¼ÐµÐ¶Ð´Ñƒ файлами, нужно будет иÑпользовать браузер файлов."
msgid "Preferences|Integrations"
msgstr "Интеграции"
@@ -19519,7 +20370,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 "Показывать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð±ÐµÐ»Ð¾Ð² в отличиÑÑ…"
@@ -19531,7 +20382,7 @@ msgid "Preferences|Syntax highlighting theme"
msgstr "Тема подÑветки ÑинтакÑиÑа"
msgid "Preferences|Tab width"
-msgstr ""
+msgstr "Ширина табулÑций"
msgid "Preferences|These settings will update how dates and times are displayed for you."
msgstr "Эти наÑтройки обновÑÑ‚ отображение даты и времени Ð´Ð»Ñ Ð²Ð°Ñ."
@@ -19581,9 +20432,6 @@ 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 ""
@@ -20080,7 +20928,7 @@ msgid "Project Access Tokens"
msgstr ""
msgid "Project Audit Events"
-msgstr ""
+msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð°ÑƒÐ´Ð¸Ñ‚Ð° проекта"
msgid "Project Badges"
msgstr "Значки Проекта"
@@ -20277,7 +21125,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20362,7 +21210,7 @@ msgid "ProjectSettings|Do not allow"
msgstr "Ðе разрешать"
msgid "ProjectSettings|Enable 'Delete source branch' option by default"
-msgstr "Включить опцию 'Удалить иÑходную ветку' по-умолчанию"
+msgstr "Включить опцию 'Удалить иÑходную ветку' по умолчанию"
msgid "ProjectSettings|Enable merge trains and pipelines for merged results"
msgstr ""
@@ -20580,6 +21428,9 @@ msgstr ".NET Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20634,6 +21485,9 @@ msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -21090,6 +21944,9 @@ msgstr "Ветка"
msgid "ProtectedBranch|Code owner approval"
msgstr "Одобрение владельцем кода"
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr "Защитить"
@@ -21160,7 +22017,7 @@ msgid "Protip:"
msgstr "ПодÑказка:"
msgid "Protocol"
-msgstr ""
+msgstr "Протокол"
msgid "Provider"
msgstr "Провайдер"
@@ -21187,7 +22044,7 @@ msgid "Public deploy keys (%{deploy_keys_count})"
msgstr "Публичные ключи Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ (%{deploy_keys_count})"
msgid "Public pipelines"
-msgstr ""
+msgstr "Открытые Ñборочные линии"
msgid "Public projects Minutes cost factor"
msgstr ""
@@ -21216,6 +22073,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr "ПриобреÑти больше минут"
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr "Отправить"
@@ -21319,7 +22179,7 @@ msgid "Quickly and easily edit multiple files in your project."
msgstr ""
msgid "README"
-msgstr ""
+msgstr "README"
msgid "Rails"
msgstr ""
@@ -21327,6 +22187,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr "Ограничение количеÑтва запроÑов на бинарные данные в минуту"
@@ -21408,6 +22271,9 @@ msgstr ""
msgid "Refresh"
msgstr "Обновить"
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21454,9 +22320,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21509,7 +22372,7 @@ msgid "Related merge requests"
msgstr "СвÑзанные запроÑÑ‹ на ÑлиÑние"
msgid "Relates to"
-msgstr ""
+msgstr "ОтноÑитÑÑ Ðº"
msgid "Release"
msgid_plural "Releases"
@@ -21668,6 +22531,9 @@ msgstr ""
msgid "Remove limit"
msgstr "Убрать лимит"
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21681,7 +22547,7 @@ msgid "Remove parent epic from an epic"
msgstr "Удалить родительÑкую цель"
msgid "Remove primary node"
-msgstr ""
+msgstr "Удалить оÑновной узел"
msgid "Remove priority"
msgstr ""
@@ -21705,7 +22571,7 @@ msgid "Remove user & report"
msgstr ""
msgid "Remove user from group"
-msgstr ""
+msgstr "Удалить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð· группы"
msgid "Removed"
msgstr ""
@@ -21788,6 +22654,9 @@ msgstr "УдалÑет дату завершениÑ."
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr "Удаление Ñтой группы также приведет к удалению вÑех дочерних проектов, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð°Ñ€Ñ…Ð¸Ð²Ð½Ñ‹Ðµ, а также их реÑурÑов."
@@ -21809,9 +22678,15 @@ msgstr ""
msgid "Reopen epic"
msgstr "Открыть цель повторно"
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr "Вновь открыть Ñтап"
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21839,6 +22714,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21966,7 +22844,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21978,6 +22862,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21996,6 +22892,9 @@ msgstr "Граф репозиториÑ"
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -22092,8 +22991,8 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
-msgstr "Требовать от вÑех пользователей в группе наÑтроить двух-факторную аутентификацию"
+msgid "Require all users 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 ""
@@ -22125,6 +23024,9 @@ msgstr "Требование %{reference} было открыто повторн
msgid "Requirement %{reference} has been updated"
msgstr "Требование %{reference} было обновлено"
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr "Заголовок Ñ‚Ñ€ÐµÐ±Ð¾Ð²Ð°Ð½Ð¸Ñ Ð½Ðµ может Ñодержать больше %{limit} Ñимволов."
@@ -22332,6 +23234,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22486,6 +23391,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22513,6 +23424,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22582,6 +23496,9 @@ 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 ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr "Ключи SSH позволÑÑŽÑ‚ уÑтановить безопаÑное Ñоединение между вашим компьютером и GitLab."
@@ -22591,6 +23508,12 @@ msgstr "Открытый ключ SSH"
msgid "SSL Verification:"
msgstr "Ð’ÐµÑ€Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¿Ð¾ SSL:"
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr "Суббота"
@@ -22606,6 +23529,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr "Сохранить в любом Ñлучае"
@@ -22630,9 +23556,6 @@ 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 variables"
-msgstr "Сохранить переменные"
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22642,6 +23565,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "РаÑпиÑание новой Ñборочной линии"
@@ -22681,6 +23607,9 @@ msgstr "ДоÑтуп"
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22711,7 +23640,7 @@ msgstr "ПоиÑк"
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22768,9 +23697,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr "ПоиÑк групп"
-
msgid "Search merge requests"
msgstr ""
@@ -22852,9 +23778,6 @@ 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 "Мы не Ñмогли найти никаких %{scope}, ÑоответÑтвующих %{term}"
-
msgid "SearchResults|code result"
msgid_plural "SearchResults|code results"
msgstr[0] ""
@@ -22941,7 +23864,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22986,10 +23909,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -23118,6 +24041,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23181,6 +24107,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23209,10 +24141,10 @@ msgid "SecurityReports|The security dashboard displays the latest security repor
msgstr ""
msgid "SecurityReports|There was an error adding the comment."
-msgstr ""
+msgstr "Произошла ошибка при добавлении комментариÑ."
msgid "SecurityReports|There was an error creating the issue."
-msgstr ""
+msgstr "Произошла ошибка при Ñоздании обÑуждениÑ."
msgid "SecurityReports|There was an error creating the merge request."
msgstr ""
@@ -23220,6 +24152,13 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23400,6 +24339,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr "Выберите необходимый регулÑторный Ñтандарт"
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23415,7 +24357,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23430,9 +24372,6 @@ msgstr "Выберите ветвь, которую вы хотите уÑтан
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23526,6 +24465,9 @@ msgstr "РазделÑйте теги запÑтыми."
msgid "September"
msgstr "СентÑбрь"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr "и"
@@ -23640,6 +24582,9 @@ msgstr "Шаблоны Служб"
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr "ПродолжительноÑÑ‚ÑŒ ÑеÑÑии (в минутах)"
@@ -23775,6 +24720,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "ÐаÑтройте Ñвой проект, чтобы автоматичеÑки загружать и/или Ñкачивать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²/из другого репозиториÑ. Ветки, теги и коммиты будут ÑинхронизироватьÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки."
@@ -23880,6 +24828,15 @@ msgstr "Общие Runner'ы"
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr "Справка по общим Runner'ам"
@@ -23898,9 +24855,15 @@ msgstr ""
msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
msgstr "ЕÑли вы когда-нибудь потерÑете Ñвой телефон или доÑтуп к вашему одноразовому паролю, каждый из Ñтих кодов воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть иÑпользован один раз, чтобы воÑÑтановить доÑтуп к вашей учетной запиÑи. ПожалуйÑта, храните их в надежном меÑте, или вы %{b_start}можете%{b_end} потерÑÑ‚ÑŒ доÑтуп к вашему аккаунту."
+msgid "Show Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr "Показывать вÑех учаÑтников"
@@ -24047,6 +25010,9 @@ msgstr "Вход / РегиÑтрациÑ"
msgid "Sign in to \"%{group_name}\""
msgstr "Ð’Ñтупить в \"%{group_name}\""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr "Войдите, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ñмарт-карту"
@@ -24074,6 +25040,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr "ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñ…Ð¾Ð´Ð°"
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr "ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ñ€ÐµÐ³Ð¸Ñтрации"
@@ -24083,9 +25052,6 @@ msgstr "Ð˜Ð¼Ñ Ñлишком длинное (макÑимум - %{max_length} Ñ
msgid "SignUp|Last Name is too long (maximum is %{max_length} characters)."
msgstr "Ð¤Ð°Ð¼Ð¸Ð»Ð¸Ñ Ñлишком Ð´Ð»Ð¸Ð½Ð½Ð°Ñ (макÑимум - %{max_length} Ñимволов)."
-msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
-msgstr "Слишком длинное Ð¸Ð¼Ñ (макÑимум %{max_length} Ñимволов)."
-
msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
msgstr "Слишком длинное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ (макÑимум %{max_length} Ñимволов)."
@@ -24095,6 +25061,9 @@ msgstr ""
msgid "Signed in"
msgstr "ÐвторизовалиÑÑŒ"
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr "Вход Ñ %{authentication} аутентификацией"
@@ -24206,17 +25175,11 @@ msgstr "Ðет Ñниппетов Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ."
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-msgstr ""
-
msgid "Snippets|Delete file"
msgstr ""
msgid "Snippets|Description (optional)"
-msgstr ""
-
-msgid "Snippets|File"
-msgstr ""
+msgstr "ОпиÑание (необÑзательно)"
msgid "Snippets|Files"
msgstr ""
@@ -24224,9 +25187,6 @@ 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 ""
@@ -24461,6 +25421,9 @@ msgstr "Уровень доÑтупа, по возраÑтанию"
msgid "SortOptions|Access level, descending"
msgstr "Уровень доÑтупа, по убыванию"
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr "Дата ÑозданиÑ"
@@ -24569,6 +25532,9 @@ msgstr "Ðедавно заходившие"
msgid "SortOptions|Recently starred"
msgstr "Сначала недавно избранные"
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr "Размер"
@@ -24611,9 +25577,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "ИÑходный код"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24689,9 +25652,6 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr "Укажите Ñледующий URL во Ð²Ñ€ÐµÐ¼Ñ Ð½Ð°Ñтройки Gitlab Runner:"
-msgid "Speed up your DevOps%{br_tag}with GitLab"
-msgstr ""
-
msgid "Squash commit message"
msgstr "ОпиÑание Ð´Ð»Ñ Ð¾Ð±ÑŠÐµÐ´Ð¸Ð½ÐµÐ½Ð½Ð¾Ð³Ð¾ (squash) коммита"
@@ -24755,6 +25715,9 @@ msgstr "В избранное"
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24911,6 +25874,9 @@ msgstr "СтатиÑтика"
msgid "Status"
msgstr "СтатуÑ"
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr "СтатуÑ:"
@@ -25040,6 +26006,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -25055,6 +26024,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -25097,6 +26069,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr "Оплата"
@@ -25181,6 +26159,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "УÑпешно заблокировано"
@@ -25202,6 +26183,9 @@ msgstr "ÐÐ´Ñ€ÐµÑ Ñлектронной почты уÑпешно удален
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr "УÑпешно запланирован запуÑк Ñборочной линии. Перейти к %{pipelines_link_start}Ñтранице Ñборочных линий%{pipelines_link_end} Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ñтей."
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr "УÑпешно разблокировано"
@@ -25337,12 +26321,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr "Синхронизировано"
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr "СиÑтема"
@@ -25370,6 +26360,9 @@ msgstr "СиÑтемные метрики (наÑтраиваемые)"
msgid "System metrics (Kubernetes)"
msgstr "СиÑтемные метрики (Kubernetes)"
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25610,15 +26603,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25703,8 +26711,8 @@ msgstr "СпаÑибо за покупку!"
msgid "Thanks! Don't show me this again"
msgstr "СпаÑибо! Больше не показывать"
-msgid "That's it, well done!%{celebrate}"
-msgstr "Вот и вÑÑ‘, Ð¾Ñ‚Ð»Ð¸Ñ‡Ð½Ð°Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ð°!%{celebrate}"
+msgid "That's it, well done!"
+msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "Группа \"%{group_path}\" позволÑет вам войти в ÑиÑтему Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ учетной запиÑи единого входа"
@@ -25728,9 +26736,6 @@ 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 ""
@@ -25743,9 +26748,15 @@ msgstr "Трекер обÑуждений - Ñто меÑто, где можно
msgid "The Prometheus server responded with \"bad request\". Please check your queries are correct and are supported in your Prometheus version. %{documentationLink}"
msgstr "Сервер Prometheus ответил Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ð¾Ð¼ \"bad request\". ПожалуйÑта, убедитеÑÑŒ, что запроÑÑ‹ верны и поддерживаютÑÑ Ð² вашей верÑии Prometheus. %{documentationLink}"
+msgid "The Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr "URL, иÑпользуемый Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Elasticsearch. ИÑпользуйте ÑпиÑок разделÑемых запÑтыми адреÑов Ð´Ð»Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¸ клаÑтеризации (напр., \"http://localhost:9200, http://localhost:9201\")."
@@ -25792,7 +26803,7 @@ msgid "The contents of this group, its subgroups and projects will be permanentl
msgstr ""
msgid "The current issue"
-msgstr ""
+msgstr "Текущее обÑуждение"
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr "ИÑточник данных подключен, но нет данных Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ. %{documentationLink}"
@@ -25842,6 +26853,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "Следующие Ñлементы ÐЕ будут ÑкÑпортированы:"
@@ -25867,8 +26884,8 @@ 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 internal projects can be viewed by any logged in user except external users."
+msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
msgstr "Группу и любые публичные проекты можно проÑматривать без какой-либо аутентификации."
@@ -25978,8 +26995,8 @@ msgstr "Этап Ð¿Ð»Ð°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ Ð
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr "Закрытый ключ, иÑпользуемый при предоÑтавлении клиентÑкого Ñертификата. Он будет зашифрован в ÑоÑтоÑнии покоÑ."
-msgid "The project can be accessed by any logged in user."
-msgstr "ДоÑтуп к проекту возможен любым зарегиÑтрированным пользователем."
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr "ДоÑтуп к проекту может получить любой пользователь, вошедший в ÑиÑтему."
@@ -26038,6 +27055,9 @@ msgstr "Этап обзора показывает Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ ÑозданÐ
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr "Ð’Ñ€ÐµÐ¼Ñ Ñ€Ð°ÑпиÑÐ°Ð½Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ быть в будущем!"
@@ -26050,8 +27070,8 @@ msgstr "Сниппет виден только мне."
msgid "The snippet is visible only to project members."
msgstr "Сниппет виден только учаÑтникам проекта."
-msgid "The snippet is visible to any logged in user."
-msgstr "Сниппет виден любому пользователю, вошедшему в ÑиÑтему."
+msgid "The snippet is visible to any logged in user except external users."
+msgstr ""
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -26089,6 +27109,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26197,6 +27220,9 @@ msgstr "Ðа диÑке уже еÑÑ‚ÑŒ репозиторий Ñ Ñ‚Ð°ÐºÐ¸Ð¼ иÐ
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr "Ðет доÑтупных данных. ПожалуйÑта, измените ваш выбор."
@@ -26392,6 +27418,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26443,7 +27472,7 @@ msgstr "Это дейÑтвие может привеÑти к потере да
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26467,9 +27496,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26602,6 +27637,9 @@ msgstr "Это ÑпиÑок уÑтройÑтв, c которых вошли в Ð
msgid "This is a security log of important events involving your account."
msgstr "Это журнал безопаÑноÑти важных Ñобытий, ÑвÑзанных Ñ Ð²Ð°ÑˆÐµÐ¹ учетной запиÑью."
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26611,6 +27649,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Это ваша Ñ‚ÐµÐºÑƒÑ‰Ð°Ñ ÑеÑÑиÑ"
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27163,6 +28204,12 @@ msgstr "Только что"
msgid "Timeago|right now"
msgstr "прÑмо ÑейчаÑ"
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr "Таймаут"
@@ -27201,7 +28248,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27252,7 +28299,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27322,7 +28369,7 @@ msgid "To update Snippets with multiple files, you must use the `files` paramete
msgstr ""
msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
+msgstr "Чтобы иÑпользовать Gitpod, Ñначала нужно включить Ñту функцию в разделе интеграций ваших %{user_prefs}."
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
@@ -27381,6 +28428,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Переключить боковую панель"
@@ -27453,16 +28503,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr "Общее Ð²Ñ€ÐµÐ¼Ñ Ñ‚ÐµÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ„Ð¸ÐºÑаций/ÑлиÑний"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr "Итоговый приоритет"
msgid "Total: %{total}"
msgstr "Ð’Ñего: %{total}"
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27639,6 +28692,9 @@ msgstr ""
msgid "Tuesday"
msgstr "Вторник"
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27787,6 +28843,9 @@ msgid "Unable to save iteration. Please try again"
msgstr ""
msgid "Unable to save your changes. Please try again."
+msgstr "Ðевозможно Ñохранить ваши изменениÑ. ПожалуйÑта, попробуйте ещё раз."
+
+msgid "Unable to save your preference"
msgstr ""
msgid "Unable to schedule a pipeline to run immediately"
@@ -27814,7 +28873,7 @@ msgid "Unarchiving the project will restore people's ability to make changes to
msgstr "Разархивирование проекта вернёт людÑм возможноÑÑ‚ÑŒ вноÑить в него изменениÑ. Ð’ репозиторий можно будет отправлÑÑ‚ÑŒ коммиты, а также поÑвитÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑ‚ÑŒ Ñоздавать обÑуждениÑ, комментарии и другие ÑущноÑти. %{strong_start}ПоÑле активации Ñтот проект поÑвитÑÑ Ð² поиÑке и на панели инÑтрументов.%{strong_end}"
msgid "Unassign from commenting user"
-msgstr ""
+msgstr "Отменить назначение комментирующего пользователÑ"
msgid "Unassigned"
msgstr ""
@@ -27913,16 +28972,16 @@ msgid "Unresolved"
msgstr ""
msgid "UnscannedProjects|15 or more days"
-msgstr ""
+msgstr "15 или больше дней"
msgid "UnscannedProjects|30 or more days"
-msgstr ""
+msgstr "30 или больше дней"
msgid "UnscannedProjects|5 or more days"
msgstr ""
msgid "UnscannedProjects|60 or more days"
-msgstr ""
+msgstr "60 или больше дней"
msgid "UnscannedProjects|Default branch scanning by project"
msgstr ""
@@ -28014,6 +29073,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -28152,10 +29214,13 @@ msgstr "СтатиÑтика иÑпользованиÑ"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr "%{help_link_start}Общие Runner'Ñ‹%{help_link_end} отключены, поÑтому нет наÑтроенных ограничений в иÑпользовании Ñборочных линий"
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "Ðртефакты"
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28182,6 +29247,9 @@ msgstr "Сборочные линии"
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28194,9 +29262,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr "Хранилище"
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "Ð’ Ñтом проÑтранÑтве имен нет проектов, которые иÑпользуют общие обработчики заданий"
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr "Ðе ограничена"
@@ -28218,15 +29313,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr "ИÑпользование Ñ"
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr "Wiki"
msgid "UsageQuota|Wikis"
msgstr "Вики"
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28281,10 +29388,7 @@ msgstr "Пользователь %{current_user_username} начал выдавÐ
msgid "User %{username} was successfully removed."
msgstr "Пользователь %{username} был уÑпешно удален."
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28404,6 +29508,9 @@ msgstr "Уже Ñообщили о нарушении"
msgid "UserProfile|Blocked user"
msgstr "Заблокированный пользователь"
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr "Вклад в проекты"
@@ -28500,9 +29607,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ email"
@@ -28558,7 +29662,7 @@ msgid "Using required encryption strategy when encrypted field is missing!"
msgstr ""
msgid "Valid from"
-msgstr ""
+msgstr "ДейÑтвителен Ñ"
msgid "Validate"
msgstr ""
@@ -28656,6 +29760,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28967,7 +30077,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -29051,6 +30167,15 @@ msgstr "Мы не Ñмогли раÑпознать путь Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½
msgid "We could not determine the path to remove the issue"
msgstr "Мы не можем определить путь Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±ÑуждениÑ"
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -29147,6 +30272,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29157,7 +30285,7 @@ msgid "Webhooks|Merge request events"
msgstr ""
msgid "Webhooks|Pipeline events"
-msgstr ""
+msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ñборочной линии"
msgid "Webhooks|Push events"
msgstr ""
@@ -29171,13 +30299,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29241,20 +30372,20 @@ msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
-msgstr ""
+msgstr "Добро пожаловать в GitLab, %{first_name}!"
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29267,7 +30398,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Когда процеÑÑ Runner заблокирован, он не может быть назначен другим проектам"
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29511,10 +30642,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29607,6 +30738,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29628,6 +30762,9 @@ msgstr "Ð’Ñ‹ иÑпользуете GitLab в режиме только Ð´Ð»Ñ Ñ
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr "Ð’Ñ‹ получили Ñто Ñообщение, потому что вы ÑвлÑетеÑÑŒ админиÑтратором GitLab Ð´Ð»Ñ %{url}."
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29640,12 +30777,12 @@ msgstr "ВмеÑто Ñтого вы можете %{linkStart}проÑмотре
msgid "You can also create a project from the command line."
msgstr "Ð’Ñ‹ также можете Ñоздать проект из командной Ñтроки."
-msgid "You can also press &#8984;-Enter"
-msgstr "Вы также можете нажать &#8984;-Enter"
-
msgid "You can also press Ctrl-Enter"
msgstr "Вы также можете нажать Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -29658,6 +30795,15 @@ msgstr "Ð’Ñ‹ также можете загрузить ÑущеÑтвующие
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29859,6 +31005,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29871,6 +31020,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29895,9 +31053,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29955,9 +31110,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -30060,19 +31212,22 @@ msgstr "Вы уже включили двухфакторную аутентиф
msgid "YouTube"
msgstr "YouTube"
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -30102,6 +31257,9 @@ msgstr "Ваши Группы"
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -30117,6 +31275,9 @@ msgstr "ÐктивноÑÑ‚ÑŒ ваших проектов"
msgid "Your Public Email will be displayed on your public profile."
msgstr "Ваша Ð¿ÑƒÐ±Ð»Ð¸Ñ‡Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð° будет отображатьÑÑ Ð² вашем профиле."
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr "Ваши ключи SSH (%{count})"
@@ -30385,9 +31546,6 @@ msgstr "Ð¸Ð¼Ñ Ð²ÐµÑ‚Ð²Ð¸"
msgid "by"
msgstr "по"
-msgid "by %{user}"
-msgstr "от %{user}"
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30514,9 +31672,6 @@ msgstr "Сканирование контейнеров обнаруживает
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30557,14 +31712,11 @@ msgid "ciReport|Fixed:"
msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
-msgstr ""
+msgstr "Ðайдено %{issuesWithCount}"
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 ""
@@ -30650,6 +31802,9 @@ msgstr ""
msgid "closed issue"
msgstr "закрытое обÑуждение"
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr "комментарий"
@@ -30898,8 +32053,8 @@ msgstr "диапазон недопуÑтимых IP адреÑов"
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
-msgstr "включен."
+msgid "is forbidden by a top-level group"
+msgstr ""
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -30916,6 +32071,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr "не разрешено. Попробуйте ещё раз Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼ адреÑом Ñлектронной почты или ÑвÑжитеÑÑŒ Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором GitLab."
@@ -30934,6 +32092,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr "Ñлишком длинный (макÑимум 100 запиÑей)"
@@ -30970,6 +32131,9 @@ msgstr "Ñлишком большой"
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30986,10 +32150,10 @@ msgid "leave %{group_name}"
msgstr ""
msgid "less than a minute"
-msgstr ""
+msgstr "меньше минуты"
msgid "level: %{level}"
-msgstr ""
+msgstr "уровень: %{level}"
msgid "limit of %{project_limit} reached"
msgstr ""
@@ -31034,6 +32198,9 @@ msgstr ""
msgid "missing"
msgstr "отÑутÑтвует"
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr "наиболее недавнее развёртывание"
@@ -31515,9 +32682,6 @@ 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 "быÑтрые дейÑтвиÑ"
@@ -31530,9 +32694,6 @@ msgstr ""
msgid "relates to"
msgstr "отноÑитÑÑ Ðº"
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr "оÑталоÑÑŒ"
@@ -31612,6 +32773,9 @@ msgstr "Ñвернуть"
msgid "sign in"
msgstr "войти"
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr "Ñортировка:"
@@ -31792,9 +32956,6 @@ msgstr ""
msgid "wiki page"
msgstr "wiki-Ñтраница"
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "Ñ %{additions} добавлениÑми, %{deletions} удалениÑми."
@@ -31807,3 +32968,6 @@ msgstr "Ñ Ð¾ÑтавшимÑÑ Ð¸Ñтечением, неизменным на
msgid "yaml invalid"
msgstr "неверный YAML"
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/si_LK/gitlab.po b/locale/si_LK/gitlab.po
index 46cded55d06..836260e1ac4 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-10-02 18:43\n"
+"PO-Revision-Date: 2020-11-03 22:43\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index 331c8a5f3b6..6df0c35cec4 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-10-02 18:50\n"
+"PO-Revision-Date: 2020-11-03 22:50\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -231,6 +231,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -273,13 +280,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -519,6 +519,20 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} more"
msgstr ""
@@ -563,6 +577,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -608,6 +628,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -734,9 +760,6 @@ 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 ""
@@ -844,7 +867,7 @@ msgstr[3] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -864,6 +887,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1089,9 +1115,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1132,6 +1155,18 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1164,6 +1199,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1173,19 +1211,8 @@ 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] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1478,6 +1505,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1779,6 +1809,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1932,7 +1965,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1968,10 +2001,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -2058,6 +2091,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -2082,6 +2118,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2196,6 +2235,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2205,6 +2259,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2217,12 +2277,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2277,6 +2355,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2286,6 +2367,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2331,6 +2415,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2355,6 +2442,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2364,6 +2454,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2379,22 +2472,22 @@ 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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2461,10 +2554,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2581,6 +2674,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2590,10 +2692,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2605,19 +2707,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2632,6 +2743,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2641,7 +2758,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2659,7 +2779,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2668,6 +2788,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2734,9 +2875,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2761,6 +2899,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2782,6 +2923,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2803,12 +2947,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2857,6 +3007,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2869,9 +3022,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2899,9 +3058,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2989,9 +3154,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -3064,9 +3226,6 @@ 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 ""
@@ -3097,9 +3256,6 @@ 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 ""
@@ -3124,6 +3280,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3148,9 +3307,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3166,6 +3322,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3503,6 +3662,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3753,6 +3915,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -4001,7 +4166,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -4022,6 +4208,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -4040,6 +4229,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -4097,9 +4289,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4181,6 +4370,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4265,6 +4460,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4316,12 +4523,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4340,6 +4556,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4352,6 +4571,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4496,6 +4718,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4532,9 +4757,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4565,7 +4802,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4748,6 +4985,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5159,6 +5399,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5342,9 +5585,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5363,9 +5603,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5474,6 +5711,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5498,7 +5738,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5525,6 +5765,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5708,6 +5951,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5765,9 +6011,6 @@ 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 ""
@@ -6023,9 +6266,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -6041,9 +6281,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6110,9 +6347,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6179,9 +6413,6 @@ 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 ""
@@ -6248,9 +6479,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6311,6 +6539,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6395,6 +6626,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6536,9 +6770,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6650,9 +6881,6 @@ 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 ""
@@ -6966,7 +7194,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -7017,6 +7245,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -7088,6 +7319,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7467,6 +7701,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7527,6 +7764,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7536,6 +7776,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7569,6 +7812,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7819,6 +8065,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7912,6 +8161,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8165,6 +8417,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8222,6 +8477,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8261,6 +8525,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8282,6 +8552,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8309,15 +8585,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8333,6 +8609,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8372,6 +8651,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8384,6 +8666,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8393,6 +8681,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8549,9 +8840,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8561,6 +8849,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8576,9 +8867,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8600,6 +8888,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8663,12 +8954,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8723,18 +9020,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8816,9 +9122,6 @@ 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 ""
@@ -8984,6 +9287,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -9032,6 +9341,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9203,6 +9515,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9254,7 +9587,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9405,6 +9738,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9414,6 +9750,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9435,6 +9774,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9462,9 +9804,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9633,15 +9972,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9714,6 +10062,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9855,6 +10206,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9882,7 +10239,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9927,6 +10296,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9954,7 +10326,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10716,12 +11091,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10752,6 +11133,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10827,6 +11211,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10929,6 +11316,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10992,6 +11382,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -11004,6 +11397,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11143,6 +11539,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11173,6 +11581,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11224,6 +11635,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11290,10 +11704,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11308,6 +11725,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11326,9 +11746,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11344,15 +11761,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11362,6 +11779,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11419,12 +11839,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11449,6 +11875,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11512,6 +11941,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11545,9 +11977,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11557,9 +11986,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11614,7 +12049,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12160,7 +12595,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12181,6 +12616,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12217,9 +12655,6 @@ 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 ""
@@ -12244,6 +12679,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12556,6 +12997,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12661,7 +13105,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12820,6 +13264,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12829,6 +13279,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12874,12 +13327,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12892,6 +13363,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12904,6 +13378,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12928,6 +13405,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13341,6 +13821,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13395,9 +13878,6 @@ 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 ""
@@ -13410,7 +13890,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13518,6 +13998,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13542,9 +14025,6 @@ 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 ""
@@ -13566,10 +14046,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13655,6 +14135,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13775,6 +14258,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13835,6 +14324,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13844,12 +14336,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13859,6 +14357,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13871,6 +14393,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13946,27 +14471,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13985,6 +14516,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -14016,6 +14550,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -14025,12 +14604,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -14064,6 +14661,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -14079,37 +14679,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -14118,6 +14739,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14142,9 +14766,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14244,25 +14865,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14310,6 +14931,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14358,6 +15033,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14574,6 +15252,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14829,6 +15510,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14847,6 +15531,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14976,9 +15666,6 @@ 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 ""
@@ -15007,9 +15694,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -15043,6 +15727,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -15076,6 +15763,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15121,6 +15811,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15196,6 +15889,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15749,9 +16445,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15770,6 +16463,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15803,9 +16499,6 @@ 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 ""
@@ -15815,7 +16508,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15827,6 +16520,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15890,6 +16586,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -16010,6 +16709,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -16037,15 +16742,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16283,6 +17063,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16690,6 +17473,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -17005,9 +17809,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -17065,6 +17875,38 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17320,6 +18162,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17786,6 +18631,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17816,9 +18664,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -18053,6 +18898,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -18098,9 +18946,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -18110,9 +18955,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18234,19 +19076,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18420,6 +19256,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18516,7 +19355,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18540,9 +19379,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18564,7 +19400,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18588,9 +19424,6 @@ 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 ""
@@ -18606,9 +19439,6 @@ 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 ""
@@ -18618,12 +19448,6 @@ 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 ""
@@ -18648,7 +19472,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18840,7 +19664,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18852,9 +19676,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18957,6 +19778,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -19038,6 +19862,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -19056,6 +19883,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -19086,6 +19916,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -19122,6 +19955,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19350,6 +20189,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19359,6 +20201,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19371,12 +20216,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19581,9 +20432,6 @@ 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 ""
@@ -20277,7 +21125,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20580,6 +21428,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20634,6 +21485,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -21090,6 +21944,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21216,6 +22073,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21327,6 +22187,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21408,6 +22271,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21454,9 +22320,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21668,6 +22531,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21788,6 +22654,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21809,9 +22678,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21839,6 +22714,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21966,7 +22844,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21978,6 +22862,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21996,6 +22892,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -22092,7 +22991,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -22125,6 +23024,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22332,6 +23234,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22486,6 +23391,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22513,6 +23424,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22582,6 +23496,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22591,6 +23508,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22606,6 +23529,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22630,9 +23556,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22642,6 +23565,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22681,6 +23607,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22711,7 +23640,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22768,9 +23697,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22852,9 +23778,6 @@ 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] ""
@@ -22941,7 +23864,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22986,10 +23909,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -23118,6 +24041,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23181,6 +24107,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23220,6 +24152,13 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23400,6 +24339,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23415,7 +24357,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23430,9 +24372,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23526,6 +24465,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23640,6 +24582,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23775,6 +24720,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23880,6 +24828,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23898,9 +24855,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -24047,6 +25010,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -24074,6 +25040,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -24083,9 +25052,6 @@ 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 ""
@@ -24095,6 +25061,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24206,27 +25175,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24461,6 +25421,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24569,6 +25532,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24611,9 +25577,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24689,9 +25652,6 @@ 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 ""
@@ -24755,6 +25715,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24911,6 +25874,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -25040,6 +26006,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -25055,6 +26024,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -25097,6 +26069,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25181,6 +26159,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25202,6 +26183,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25337,12 +26321,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25370,6 +26360,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25610,15 +26603,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25703,7 +26711,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25728,9 +26736,6 @@ 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 ""
@@ -25743,9 +26748,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25842,6 +26853,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25867,7 +26884,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25978,7 +26995,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -26038,6 +27055,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -26050,7 +27070,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -26089,6 +27109,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26197,6 +27220,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26392,6 +27418,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26443,7 +27472,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26467,9 +27496,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26602,6 +27637,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26611,6 +27649,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27163,6 +28204,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27201,7 +28248,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27252,7 +28299,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27381,6 +28428,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27453,16 +28503,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27639,6 +28692,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27789,6 +28845,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -28014,6 +29073,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -28152,10 +29214,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28182,6 +29247,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28194,9 +29262,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28218,15 +29313,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28281,10 +29388,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28404,6 +29508,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28500,9 +29607,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28656,6 +29760,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28967,7 +30077,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -29051,6 +30167,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -29147,6 +30272,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29171,13 +30299,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29246,15 +30377,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29267,7 +30398,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29511,10 +30642,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29607,6 +30738,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29628,6 +30762,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29640,10 +30777,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29658,6 +30795,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29859,6 +31005,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29871,6 +31020,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29895,9 +31053,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29955,9 +31110,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -30060,19 +31212,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -30102,6 +31257,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -30117,6 +31275,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30385,9 +31546,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30514,9 +31672,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30562,9 +31717,6 @@ 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 ""
@@ -30650,6 +31802,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30898,7 +32053,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30916,6 +32071,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30934,6 +32092,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30970,6 +32131,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -31034,6 +32198,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31515,9 +32682,6 @@ 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 ""
@@ -31530,9 +32694,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31612,6 +32773,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31792,9 +32956,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31807,3 +32968,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/sl_SI/gitlab.po b/locale/sl_SI/gitlab.po
index 769f12b690b..695c70b44b0 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-10-02 18:50\n"
+"PO-Revision-Date: 2020-11-03 22:50\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -231,6 +231,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -273,13 +280,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -519,6 +519,20 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} more"
msgstr ""
@@ -563,6 +577,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -608,6 +628,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -734,9 +760,6 @@ 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 ""
@@ -844,7 +867,7 @@ msgstr[3] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -864,6 +887,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1089,9 +1115,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1132,6 +1155,18 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1164,6 +1199,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1173,19 +1211,8 @@ 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] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1478,6 +1505,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1779,6 +1809,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1932,7 +1965,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1968,10 +2001,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -2058,6 +2091,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -2082,6 +2118,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2196,6 +2235,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2205,6 +2259,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2217,12 +2277,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2277,6 +2355,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2286,6 +2367,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2331,6 +2415,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2355,6 +2442,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2364,6 +2454,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2379,22 +2472,22 @@ 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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2461,10 +2554,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2581,6 +2674,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2590,10 +2692,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2605,19 +2707,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2632,6 +2743,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2641,7 +2758,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2659,7 +2779,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2668,6 +2788,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2734,9 +2875,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2761,6 +2899,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2782,6 +2923,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2803,12 +2947,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2857,6 +3007,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2869,9 +3022,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2899,9 +3058,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2989,9 +3154,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -3064,9 +3226,6 @@ 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 ""
@@ -3097,9 +3256,6 @@ 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 ""
@@ -3124,6 +3280,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3148,9 +3307,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3166,6 +3322,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3503,6 +3662,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3753,6 +3915,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -4001,7 +4166,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -4022,6 +4208,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -4040,6 +4229,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -4097,9 +4289,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4181,6 +4370,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4265,6 +4460,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4316,12 +4523,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4340,6 +4556,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4352,6 +4571,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4496,6 +4718,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4532,9 +4757,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4565,7 +4802,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4748,6 +4985,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5159,6 +5399,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5342,9 +5585,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5363,9 +5603,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5474,6 +5711,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5498,7 +5738,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5525,6 +5765,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5708,6 +5951,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5765,9 +6011,6 @@ 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 ""
@@ -6023,9 +6266,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -6041,9 +6281,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6110,9 +6347,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6179,9 +6413,6 @@ 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 ""
@@ -6248,9 +6479,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6311,6 +6539,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6395,6 +6626,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6536,9 +6770,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6650,9 +6881,6 @@ 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 ""
@@ -6966,7 +7194,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -7017,6 +7245,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -7088,6 +7319,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7467,6 +7701,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7527,6 +7764,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7536,6 +7776,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7569,6 +7812,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7819,6 +8065,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7912,6 +8161,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8165,6 +8417,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8222,6 +8477,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8261,6 +8525,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8282,6 +8552,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8309,15 +8585,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8333,6 +8609,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8372,6 +8651,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8384,6 +8666,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8393,6 +8681,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8549,9 +8840,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8561,6 +8849,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8576,9 +8867,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8600,6 +8888,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8663,12 +8954,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8723,18 +9020,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8816,9 +9122,6 @@ 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 ""
@@ -8984,6 +9287,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -9032,6 +9341,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9203,6 +9515,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9254,7 +9587,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9405,6 +9738,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9414,6 +9750,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9435,6 +9774,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9462,9 +9804,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9633,15 +9972,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9714,6 +10062,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9855,6 +10206,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9882,7 +10239,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9927,6 +10296,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9954,7 +10326,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10716,12 +11091,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10752,6 +11133,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10827,6 +11211,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10929,6 +11316,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10992,6 +11382,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -11004,6 +11397,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11143,6 +11539,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11173,6 +11581,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11224,6 +11635,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11290,10 +11704,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11308,6 +11725,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11326,9 +11746,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11344,15 +11761,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11362,6 +11779,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11419,12 +11839,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11449,6 +11875,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11512,6 +11941,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11545,9 +11977,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11557,9 +11986,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11614,7 +12049,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12160,7 +12595,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12181,6 +12616,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12217,9 +12655,6 @@ 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 ""
@@ -12244,6 +12679,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12556,6 +12997,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12661,7 +13105,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12820,6 +13264,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12829,6 +13279,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12874,12 +13327,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12892,6 +13363,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12904,6 +13378,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12928,6 +13405,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13341,6 +13821,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13395,9 +13878,6 @@ 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 ""
@@ -13410,7 +13890,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13518,6 +13998,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13542,9 +14025,6 @@ 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 ""
@@ -13566,10 +14046,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13655,6 +14135,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13775,6 +14258,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13835,6 +14324,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13844,12 +14336,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13859,6 +14357,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13871,6 +14393,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13946,27 +14471,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13985,6 +14516,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -14016,6 +14550,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -14025,12 +14604,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -14064,6 +14661,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -14079,37 +14679,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -14118,6 +14739,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14142,9 +14766,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14244,25 +14865,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14310,6 +14931,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14358,6 +15033,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14574,6 +15252,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14829,6 +15510,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14847,6 +15531,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14976,9 +15666,6 @@ 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 ""
@@ -15007,9 +15694,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -15043,6 +15727,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -15076,6 +15763,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15121,6 +15811,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15196,6 +15889,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15749,9 +16445,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15770,6 +16463,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15803,9 +16499,6 @@ 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 ""
@@ -15815,7 +16508,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15827,6 +16520,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15890,6 +16586,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -16010,6 +16709,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -16037,15 +16742,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16283,6 +17063,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16690,6 +17473,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -17005,9 +17809,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -17065,6 +17875,38 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17320,6 +18162,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17786,6 +18631,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17816,9 +18664,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -18053,6 +18898,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -18098,9 +18946,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -18110,9 +18955,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18234,19 +19076,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18420,6 +19256,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18516,7 +19355,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18540,9 +19379,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18564,7 +19400,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18588,9 +19424,6 @@ 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 ""
@@ -18606,9 +19439,6 @@ 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 ""
@@ -18618,12 +19448,6 @@ 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 ""
@@ -18648,7 +19472,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18840,7 +19664,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18852,9 +19676,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18957,6 +19778,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -19038,6 +19862,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -19056,6 +19883,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -19086,6 +19916,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -19122,6 +19955,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19350,6 +20189,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19359,6 +20201,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19371,12 +20216,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19581,9 +20432,6 @@ 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 ""
@@ -20277,7 +21125,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20580,6 +21428,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20634,6 +21485,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -21090,6 +21944,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21216,6 +22073,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21327,6 +22187,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21408,6 +22271,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21454,9 +22320,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21668,6 +22531,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21788,6 +22654,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21809,9 +22678,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21839,6 +22714,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21966,7 +22844,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21978,6 +22862,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21996,6 +22892,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -22092,7 +22991,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -22125,6 +23024,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22332,6 +23234,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22486,6 +23391,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22513,6 +23424,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22582,6 +23496,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22591,6 +23508,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22606,6 +23529,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22630,9 +23556,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22642,6 +23565,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22681,6 +23607,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22711,7 +23640,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22768,9 +23697,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22852,9 +23778,6 @@ 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] ""
@@ -22941,7 +23864,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22986,10 +23909,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -23118,6 +24041,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23181,6 +24107,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23220,6 +24152,13 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23400,6 +24339,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23415,7 +24357,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23430,9 +24372,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23526,6 +24465,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23640,6 +24582,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23775,6 +24720,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23880,6 +24828,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23898,9 +24855,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -24047,6 +25010,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -24074,6 +25040,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -24083,9 +25052,6 @@ 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 ""
@@ -24095,6 +25061,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24206,27 +25175,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24461,6 +25421,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24569,6 +25532,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24611,9 +25577,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24689,9 +25652,6 @@ 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 ""
@@ -24755,6 +25715,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24911,6 +25874,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -25040,6 +26006,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -25055,6 +26024,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -25097,6 +26069,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25181,6 +26159,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25202,6 +26183,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25337,12 +26321,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25370,6 +26360,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25610,15 +26603,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25703,7 +26711,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25728,9 +26736,6 @@ 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 ""
@@ -25743,9 +26748,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25842,6 +26853,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25867,7 +26884,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25978,7 +26995,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -26038,6 +27055,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -26050,7 +27070,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -26089,6 +27109,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26197,6 +27220,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26392,6 +27418,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26443,7 +27472,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26467,9 +27496,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26602,6 +27637,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26611,6 +27649,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27163,6 +28204,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27201,7 +28248,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27252,7 +28299,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27381,6 +28428,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27453,16 +28503,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27639,6 +28692,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27789,6 +28845,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -28014,6 +29073,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -28152,10 +29214,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28182,6 +29247,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28194,9 +29262,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28218,15 +29313,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28281,10 +29388,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28404,6 +29508,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28500,9 +29607,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28656,6 +29760,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28967,7 +30077,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -29051,6 +30167,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -29147,6 +30272,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29171,13 +30299,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29246,15 +30377,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29267,7 +30398,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29511,10 +30642,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29607,6 +30738,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29628,6 +30762,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29640,10 +30777,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29658,6 +30795,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29859,6 +31005,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29871,6 +31020,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29895,9 +31053,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29955,9 +31110,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -30060,19 +31212,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -30102,6 +31257,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -30117,6 +31275,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30385,9 +31546,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30514,9 +31672,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30562,9 +31717,6 @@ 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 ""
@@ -30650,6 +31802,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30898,7 +32053,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30916,6 +32071,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30934,6 +32092,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30970,6 +32131,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -31034,6 +32198,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31515,9 +32682,6 @@ 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 ""
@@ -31530,9 +32694,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31612,6 +32773,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31792,9 +32956,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31807,3 +32968,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index b1b63eb174d..7973a80d33b 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-10-02 18:50\n"
+"PO-Revision-Date: 2020-11-03 22:50\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index a6daa719153..d3c6b25a8e1 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-10-02 18:44\n"
+"PO-Revision-Date: 2020-11-03 22:44\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -208,6 +208,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -244,12 +250,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -463,6 +463,18 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{count} more"
msgstr ""
@@ -505,6 +517,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -550,6 +568,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -676,9 +700,6 @@ 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 ""
@@ -781,7 +802,7 @@ msgstr[2] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -799,6 +820,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1018,9 +1042,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1060,6 +1081,18 @@ msgstr[2] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1090,6 +1123,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1099,17 +1135,8 @@ 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] ""
-msgstr[2] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1387,6 +1414,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1687,6 +1717,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1840,7 +1873,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1876,10 +1909,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1966,6 +1999,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1990,6 +2026,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2104,6 +2143,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2113,6 +2167,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2125,12 +2185,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2185,6 +2263,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2194,6 +2275,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2239,6 +2323,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2263,6 +2350,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2272,6 +2362,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2287,22 +2380,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2368,10 +2461,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2488,6 +2581,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2497,10 +2599,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2512,19 +2614,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2539,6 +2650,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2548,7 +2665,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2566,7 +2686,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2575,6 +2695,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2641,9 +2782,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2668,6 +2806,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2689,6 +2830,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2710,12 +2854,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2764,6 +2914,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2776,9 +2929,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2806,9 +2965,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2896,9 +3061,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2971,9 +3133,6 @@ 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 ""
@@ -3004,9 +3163,6 @@ 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 ""
@@ -3031,6 +3187,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3055,9 +3214,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3073,6 +3229,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3406,6 +3565,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3655,6 +3817,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3901,7 +4066,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3922,6 +4108,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3940,6 +4129,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3997,9 +4189,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4081,6 +4270,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4165,6 +4360,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4216,12 +4423,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4240,6 +4456,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4252,6 +4471,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4396,6 +4618,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4432,9 +4657,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4465,7 +4702,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4648,6 +4885,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5059,6 +5299,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5242,9 +5485,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5263,9 +5503,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5374,6 +5611,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5398,7 +5638,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5425,6 +5665,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5608,6 +5851,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5665,9 +5911,6 @@ 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 ""
@@ -5923,9 +6166,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5941,9 +6181,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6010,9 +6247,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6079,9 +6313,6 @@ 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 ""
@@ -6148,9 +6379,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6211,6 +6439,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6295,6 +6526,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6436,9 +6670,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6550,9 +6781,6 @@ 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 ""
@@ -6865,7 +7093,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6916,6 +7144,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6985,6 +7216,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7363,6 +7597,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7423,6 +7660,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7432,6 +7672,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7465,6 +7708,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7714,6 +7960,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7807,6 +8056,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8059,6 +8311,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8116,6 +8371,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8155,6 +8419,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8176,6 +8446,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8203,15 +8479,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8227,6 +8503,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8266,6 +8545,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8278,6 +8560,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8287,6 +8575,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8443,9 +8734,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8455,6 +8743,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8470,9 +8761,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8494,6 +8782,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8557,12 +8848,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8614,18 +8911,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8704,9 +9010,6 @@ 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 ""
@@ -8872,6 +9175,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8920,6 +9229,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9091,6 +9403,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9142,7 +9475,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9292,6 +9625,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9301,6 +9637,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9322,6 +9661,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9349,9 +9691,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9520,15 +9859,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9601,6 +9949,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9742,6 +10093,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9769,7 +10126,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9814,6 +10183,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9841,7 +10213,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10603,12 +10978,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10639,6 +11020,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10714,6 +11098,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10816,6 +11203,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10879,6 +11269,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10891,6 +11284,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11029,6 +11425,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11059,6 +11467,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11110,6 +11521,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11176,10 +11590,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11194,6 +11611,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11212,9 +11632,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11230,15 +11647,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11248,6 +11665,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11305,12 +11725,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11335,6 +11761,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11398,6 +11827,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11431,9 +11863,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11443,9 +11872,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11500,7 +11935,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12046,7 +12481,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12067,6 +12502,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12103,9 +12541,6 @@ 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 ""
@@ -12130,6 +12565,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12442,6 +12883,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12547,7 +12991,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12706,6 +13150,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12715,6 +13165,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12760,12 +13213,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12778,6 +13249,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12790,6 +13264,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12814,6 +13291,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13225,6 +13705,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13279,9 +13762,6 @@ 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 ""
@@ -13294,7 +13774,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13402,6 +13882,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13426,9 +13909,6 @@ 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 ""
@@ -13450,10 +13930,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13537,6 +14017,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13657,6 +14140,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13717,6 +14206,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13726,12 +14218,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13741,6 +14239,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13753,6 +14275,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13828,27 +14353,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13867,6 +14398,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13897,6 +14431,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13906,12 +14485,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13945,6 +14542,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13960,37 +14560,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13999,6 +14620,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14023,9 +14647,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14125,25 +14746,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14191,6 +14812,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14239,6 +14914,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14455,6 +15133,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14710,6 +15391,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14728,6 +15412,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14857,9 +15547,6 @@ 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 ""
@@ -14887,9 +15574,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14923,6 +15607,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14956,6 +15643,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15001,6 +15691,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15076,6 +15769,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15622,9 +16318,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15643,6 +16336,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15676,9 +16372,6 @@ 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 ""
@@ -15688,7 +16381,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15700,6 +16393,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15763,6 +16459,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15883,6 +16582,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15910,15 +16615,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16156,6 +16936,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16561,6 +17344,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16876,9 +17680,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16936,6 +17746,36 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17191,6 +18031,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17656,6 +18499,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17686,9 +18532,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17923,6 +18766,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17968,9 +18814,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17980,9 +18823,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18103,19 +18943,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18289,6 +19123,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18385,7 +19222,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18409,9 +19246,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18433,7 +19267,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18457,9 +19291,6 @@ 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 ""
@@ -18475,9 +19306,6 @@ 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 ""
@@ -18487,12 +19315,6 @@ 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 ""
@@ -18517,7 +19339,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18709,7 +19531,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18721,9 +19543,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18826,6 +19645,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18907,6 +19729,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18925,6 +19750,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18955,6 +19783,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18991,6 +19822,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19219,6 +20056,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19228,6 +20068,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19240,12 +20083,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19450,9 +20299,6 @@ 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 ""
@@ -20146,7 +20992,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20449,6 +21295,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20503,6 +21352,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20959,6 +21811,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21085,6 +21940,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21196,6 +22054,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21277,6 +22138,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21322,9 +22186,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21535,6 +22396,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21655,6 +22519,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21676,9 +22543,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21706,6 +22579,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21832,7 +22708,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21844,6 +22726,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21862,6 +22756,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21958,7 +22855,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21991,6 +22888,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22195,6 +23095,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22348,6 +23251,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22375,6 +23284,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22444,6 +23356,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22453,6 +23368,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22468,6 +23389,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22492,9 +23416,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22504,6 +23425,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22543,6 +23467,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22573,7 +23500,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22630,9 +23557,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22714,9 +23638,6 @@ 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] ""
@@ -22792,7 +23713,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22837,10 +23758,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22969,6 +23890,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23032,6 +23956,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23071,6 +24001,12 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23251,6 +24187,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23266,7 +24205,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23281,9 +24220,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23377,6 +24313,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23491,6 +24430,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23626,6 +24568,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23731,6 +24676,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23749,9 +24703,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23896,6 +24856,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23923,6 +24886,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23932,9 +24898,6 @@ 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 ""
@@ -23944,6 +24907,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24055,27 +25021,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24310,6 +25267,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24418,6 +25378,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24460,9 +25423,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24538,9 +25498,6 @@ 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 ""
@@ -24604,6 +25561,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24760,6 +25720,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24889,6 +25852,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24904,6 +25870,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24946,6 +25915,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25030,6 +26005,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25051,6 +26029,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25186,12 +26167,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25219,6 +26206,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25456,15 +26446,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25549,7 +26554,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25573,9 +26578,6 @@ 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 ""
@@ -25588,9 +26590,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25687,6 +26695,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25711,7 +26725,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25822,7 +26836,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25882,6 +26896,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25894,7 +26911,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25933,6 +26950,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26041,6 +27061,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26236,6 +27259,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26287,7 +27313,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26311,9 +27337,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26446,6 +27478,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26455,6 +27490,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27007,6 +28045,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27043,7 +28087,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27094,7 +28138,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27223,6 +28267,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27295,16 +28342,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27481,6 +28531,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27631,6 +28684,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27856,6 +28912,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27994,10 +29053,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28024,6 +29086,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28036,9 +29101,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28060,15 +29152,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28123,10 +29227,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28246,6 +29347,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28342,9 +29446,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28498,6 +29599,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28807,7 +29914,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28891,6 +30004,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28987,6 +30109,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29011,13 +30136,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29086,15 +30214,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29107,7 +30235,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29350,10 +30478,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29446,6 +30574,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29467,6 +30598,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29479,10 +30613,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29497,6 +30631,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29698,6 +30841,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29710,6 +30856,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29734,9 +30889,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29794,9 +30946,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29899,19 +31048,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29941,6 +31093,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29956,6 +31111,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30223,9 +31381,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30352,9 +31507,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30400,9 +31552,6 @@ 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 ""
@@ -30487,6 +31636,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30730,7 +31882,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30748,6 +31900,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30766,6 +31921,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30802,6 +31960,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30865,6 +32026,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31342,9 +32506,6 @@ 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 ""
@@ -31357,9 +32518,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31438,6 +32596,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31618,9 +32779,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31633,3 +32791,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index 5a1ed95156c..3daac77e0d9 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-10-02 18:50\n"
+"PO-Revision-Date: 2020-11-03 22:50\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -208,6 +208,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -244,12 +250,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -463,6 +463,18 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{count} more"
msgstr ""
@@ -505,6 +517,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -550,6 +568,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -676,9 +700,6 @@ 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 ""
@@ -781,7 +802,7 @@ msgstr[2] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -799,6 +820,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1018,9 +1042,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -1060,6 +1081,18 @@ msgstr[2] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1090,6 +1123,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1099,17 +1135,8 @@ 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] ""
-msgstr[2] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1387,6 +1414,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1687,6 +1717,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1840,7 +1873,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1876,10 +1909,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1966,6 +1999,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1990,6 +2026,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2104,6 +2143,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2113,6 +2167,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2125,12 +2185,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2185,6 +2263,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2194,6 +2275,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2239,6 +2323,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2263,6 +2350,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2272,6 +2362,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2287,22 +2380,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2368,10 +2461,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2488,6 +2581,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2497,10 +2599,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2512,19 +2614,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2539,6 +2650,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2548,7 +2665,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2566,7 +2686,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2575,6 +2695,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2641,9 +2782,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2668,6 +2806,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2689,6 +2830,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2710,12 +2854,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2764,6 +2914,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2776,9 +2929,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2806,9 +2965,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2896,9 +3061,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2971,9 +3133,6 @@ 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 ""
@@ -3004,9 +3163,6 @@ 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 ""
@@ -3031,6 +3187,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -3055,9 +3214,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3073,6 +3229,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3406,6 +3565,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3655,6 +3817,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3901,7 +4066,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3922,6 +4108,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3940,6 +4129,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3997,9 +4189,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -4081,6 +4270,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4165,6 +4360,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4216,12 +4423,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4240,6 +4456,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4252,6 +4471,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4396,6 +4618,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4432,9 +4657,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4465,7 +4702,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4648,6 +4885,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5059,6 +5299,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5242,9 +5485,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5263,9 +5503,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5374,6 +5611,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5398,7 +5638,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5425,6 +5665,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5608,6 +5851,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5665,9 +5911,6 @@ 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 ""
@@ -5923,9 +6166,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5941,9 +6181,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -6010,9 +6247,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -6079,9 +6313,6 @@ 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 ""
@@ -6148,9 +6379,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6211,6 +6439,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6295,6 +6526,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6436,9 +6670,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6550,9 +6781,6 @@ 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 ""
@@ -6865,7 +7093,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6916,6 +7144,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6985,6 +7216,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7363,6 +7597,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7423,6 +7660,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7432,6 +7672,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7465,6 +7708,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7714,6 +7960,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7807,6 +8056,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -8059,6 +8311,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8116,6 +8371,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8155,6 +8419,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8176,6 +8446,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8203,15 +8479,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8227,6 +8503,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8266,6 +8545,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8278,6 +8560,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8287,6 +8575,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8443,9 +8734,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8455,6 +8743,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8470,9 +8761,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8494,6 +8782,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8557,12 +8848,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8614,18 +8911,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8704,9 +9010,6 @@ 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 ""
@@ -8872,6 +9175,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8920,6 +9229,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -9091,6 +9403,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9142,7 +9475,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9292,6 +9625,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9301,6 +9637,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9322,6 +9661,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9349,9 +9691,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9520,15 +9859,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9601,6 +9949,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9742,6 +10093,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9769,7 +10126,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9814,6 +10183,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9841,7 +10213,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10603,12 +10978,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10639,6 +11020,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10714,6 +11098,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10816,6 +11203,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10879,6 +11269,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10891,6 +11284,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -11029,6 +11425,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -11059,6 +11467,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -11110,6 +11521,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11176,10 +11590,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11194,6 +11611,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11212,9 +11632,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11230,15 +11647,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11248,6 +11665,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11305,12 +11725,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11335,6 +11761,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11398,6 +11827,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11431,9 +11863,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11443,9 +11872,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11500,7 +11935,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -12046,7 +12481,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12067,6 +12502,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -12103,9 +12541,6 @@ 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 ""
@@ -12130,6 +12565,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12442,6 +12883,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12547,7 +12991,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12706,6 +13150,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12715,6 +13165,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12760,12 +13213,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12778,6 +13249,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12790,6 +13264,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12814,6 +13291,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13225,6 +13705,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13279,9 +13762,6 @@ 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 ""
@@ -13294,7 +13774,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13402,6 +13882,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13426,9 +13909,6 @@ 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 ""
@@ -13450,10 +13930,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13537,6 +14017,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13657,6 +14140,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13717,6 +14206,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13726,12 +14218,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13741,6 +14239,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13753,6 +14275,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13828,27 +14353,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13867,6 +14398,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13897,6 +14431,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13906,12 +14485,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13945,6 +14542,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13960,37 +14560,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13999,6 +14620,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -14023,9 +14647,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14125,25 +14746,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14191,6 +14812,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14239,6 +14914,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14455,6 +15133,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14710,6 +15391,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14728,6 +15412,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14857,9 +15547,6 @@ 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 ""
@@ -14887,9 +15574,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14923,6 +15607,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14956,6 +15643,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -15001,6 +15691,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -15076,6 +15769,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15622,9 +16318,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15643,6 +16336,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15676,9 +16372,6 @@ 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 ""
@@ -15688,7 +16381,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15700,6 +16393,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15763,6 +16459,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15883,6 +16582,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15910,15 +16615,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16156,6 +16936,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16561,6 +17344,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16876,9 +17680,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16936,6 +17746,36 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17191,6 +18031,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17656,6 +18499,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17686,9 +18532,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17923,6 +18766,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17968,9 +18814,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17980,9 +18823,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18103,19 +18943,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18289,6 +19123,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18385,7 +19222,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18409,9 +19246,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18433,7 +19267,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18457,9 +19291,6 @@ 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 ""
@@ -18475,9 +19306,6 @@ 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 ""
@@ -18487,12 +19315,6 @@ 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 ""
@@ -18517,7 +19339,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18709,7 +19531,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18721,9 +19543,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18826,6 +19645,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18907,6 +19729,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18925,6 +19750,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18955,6 +19783,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18991,6 +19822,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19219,6 +20056,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19228,6 +20068,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19240,12 +20083,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19450,9 +20299,6 @@ 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 ""
@@ -20146,7 +20992,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20449,6 +21295,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20503,6 +21352,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20959,6 +21811,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -21085,6 +21940,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21196,6 +22054,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21277,6 +22138,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21322,9 +22186,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21535,6 +22396,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21655,6 +22519,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21676,9 +22543,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21706,6 +22579,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21832,7 +22708,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21844,6 +22726,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21862,6 +22756,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21958,7 +22855,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21991,6 +22888,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22195,6 +23095,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22348,6 +23251,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22375,6 +23284,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22444,6 +23356,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22453,6 +23368,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22468,6 +23389,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22492,9 +23416,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22504,6 +23425,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22543,6 +23467,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22573,7 +23500,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22630,9 +23557,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22714,9 +23638,6 @@ 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] ""
@@ -22792,7 +23713,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22837,10 +23758,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22969,6 +23890,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23032,6 +23956,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23071,6 +24001,12 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23251,6 +24187,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23266,7 +24205,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23281,9 +24220,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23377,6 +24313,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23491,6 +24430,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23626,6 +24568,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23731,6 +24676,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23749,9 +24703,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23896,6 +24856,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23923,6 +24886,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23932,9 +24898,6 @@ 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 ""
@@ -23944,6 +24907,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -24055,27 +25021,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24310,6 +25267,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24418,6 +25378,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24460,9 +25423,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24538,9 +25498,6 @@ 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 ""
@@ -24604,6 +25561,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24760,6 +25720,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24889,6 +25852,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24904,6 +25870,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24946,6 +25915,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -25030,6 +26005,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -25051,6 +26029,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25186,12 +26167,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25219,6 +26206,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25456,15 +26446,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25549,7 +26554,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25573,9 +26578,6 @@ 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 ""
@@ -25588,9 +26590,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25687,6 +26695,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25711,7 +26725,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25822,7 +26836,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25882,6 +26896,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25894,7 +26911,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25933,6 +26950,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -26041,6 +27061,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26236,6 +27259,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26287,7 +27313,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26311,9 +27337,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26446,6 +27478,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26455,6 +27490,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27007,6 +28045,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -27043,7 +28087,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -27094,7 +28138,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27223,6 +28267,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27295,16 +28342,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27481,6 +28531,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27631,6 +28684,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27856,6 +28912,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27994,10 +29053,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28024,6 +29086,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28036,9 +29101,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -28060,15 +29152,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28123,10 +29227,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28246,6 +29347,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28342,9 +29446,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28498,6 +29599,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28807,7 +29914,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28891,6 +30004,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28987,6 +30109,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29011,13 +30136,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29086,15 +30214,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -29107,7 +30235,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29350,10 +30478,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29446,6 +30574,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29467,6 +30598,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29479,10 +30613,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29497,6 +30631,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29698,6 +30841,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29710,6 +30856,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29734,9 +30889,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29794,9 +30946,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29899,19 +31048,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29941,6 +31093,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29956,6 +31111,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30223,9 +31381,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30352,9 +31507,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30400,9 +31552,6 @@ 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 ""
@@ -30487,6 +31636,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30730,7 +31882,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30748,6 +31900,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30766,6 +31921,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30802,6 +31960,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30865,6 +32026,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31342,9 +32506,6 @@ 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 ""
@@ -31357,9 +32518,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31438,6 +32596,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31618,9 +32779,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31633,3 +32791,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index 93e28b8a8d9..bc5e87bc27e 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-10-02 18:51\n"
+"PO-Revision-Date: 2020-11-03 22:51\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index 82de5bbebf3..c2a03296f39 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-10-02 18:44\n"
+"PO-Revision-Date: 2020-11-03 22:43\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index 1e89acbf717..321e0bed2d5 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-10-02 18:48\n"
+"PO-Revision-Date: 2020-11-03 22:48\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] "%d başarısız"
msgstr[1] "%d başarısız"
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d sabit test sonucu"
@@ -215,11 +220,6 @@ msgid_plural "%d issues in this group"
msgstr[0] "Bu grupta %d sorun"
msgstr[1] "Bu grupta %d sorun"
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d sorun seçili"
-msgstr[1] "%d sorun seçili"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] "%d sorun etiketle başarıyla içe aktarıldı"
@@ -407,6 +407,16 @@ msgstr "%{name} kiÅŸisinden %{count} onay"
msgid "%{count} files touched"
msgstr "%{count} dosyaya dokunuldu"
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr "%{count} daha"
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr "%{host} yeni konumdan oturum açma"
@@ -618,9 +640,6 @@ 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 "%{namespace_name} artık salt okunur. Şunları yapamazsınız: %{base_message}"
-
msgid "%{name} contained %{resultsString}"
msgstr "%{name} %{resultsString} ifadesini içeriyor"
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -947,9 +969,6 @@ msgstr "(ilerlemeyi kontrol et)"
msgid "(deleted)"
msgstr "(silindi)"
-msgid "(external source)"
-msgstr "(dış kaynak)"
-
msgid "(line: %{startLine})"
msgstr "(satır: %{startLine})"
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr "+%{approvers} onaylayan daha"
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr "+%{tags} daha fazla"
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr "- daha az göster"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr "0 bayt"
@@ -1025,15 +1059,8 @@ msgstr "Sınırsız için 0"
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "1 %{type} ek"
-msgstr[1] "%{count} %{type} ek"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "1 %{type} deÄŸiÅŸiklik"
-msgstr[1] "%{count} %{type} deÄŸiÅŸiklik"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr "Bu dala yazma yetkisi olan kullanıcı bu seçeneği seçti"
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr "API Yardımı"
@@ -1595,6 +1625,9 @@ msgstr "Tablo ekle"
msgid "Add a task list"
msgstr "Görev listesi ekle"
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Tüm e-posta iletişiminde görünecek ek metin ekleyin. %{character_limit} karakter sınırı"
@@ -1748,8 +1781,8 @@ msgstr "%{epic_ref} alt epik olarak eklendi."
msgid "Added %{label_references} %{label_text}."
msgstr "%{label_references} %{label_text} eklendi."
-msgid "Added a To Do."
-msgstr "Yapılacaklar listesi eklendi."
+msgid "Added a to do."
+msgstr ""
msgid "Added an issue to an epic."
msgstr "EpiÄŸe bir sorun eklendi."
@@ -1784,12 +1817,12 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr "%{labels} %{label_text} ekler."
-msgid "Adds a To Do."
-msgstr "Yapılacaklar listesi ekler."
-
msgid "Adds a Zoom meeting"
msgstr "Zoom toplantısı ekler"
+msgid "Adds a to do."
+msgstr ""
+
msgid "Adds an issue to an epic."
msgstr "EpiÄŸe bir sorun ekler."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr "Sahibi"
@@ -1898,6 +1934,9 @@ msgstr "İşleri durdurma başarısız oldu"
msgid "AdminArea|Total users"
msgstr "Toplam kullanıcı"
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "Kullanıcı istatistikleri"
@@ -2012,6 +2051,21 @@ msgstr "SSH Anahtarları"
msgid "AdminStatistics|Snippets"
msgstr "Parçacıklar"
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr "2FA Devre dışı"
@@ -2021,6 +2075,12 @@ msgstr "2FA Etkin"
msgid "AdminUsers|Access"
msgstr "EriÅŸim"
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr "Etkin"
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr "Yöneticiler"
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr "Engelle"
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Kullanıcıyı engelle"
@@ -2093,6 +2171,9 @@ msgstr "Koltuğu kullanıyor"
msgid "AdminUsers|It's you!"
msgstr "Bu sensin!"
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr "Yeni kullanıcı"
@@ -2102,6 +2183,9 @@ msgstr "Kullanıcı bulunamadı"
msgid "AdminUsers|Owned groups will be left"
msgstr "Sahip olunan gruplar bırakılacak"
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr "Kişisel projeler bırakılacak"
@@ -2147,6 +2231,9 @@ msgstr "Kullanıcı slash komutlarını kullanamayacak"
msgid "AdminUsers|The user will not receive any notifications"
msgstr "Kullanıcı herhangi bir bildirim almayacak"
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Onaylamak için, %{projectName} yazın"
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr "Yönetim"
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr "GeliÅŸmiÅŸ"
@@ -2195,23 +2288,23 @@ msgstr "GeliÅŸmiÅŸ Ayarlar"
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "Gelişmiş izinler, Büyük Dosya Depolama ve İki Adımlı Kimlik Doğrulama ayarları."
-msgid "Advanced search functionality"
-msgstr "GeliÅŸmiÅŸ arama iÅŸlevi"
-
msgid "After a successful password update you will be redirected to login screen."
msgstr "Başarılı bir şifre güncellemesinden sonra giriş ekranına yönlendirileceksiniz."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Başarılı bir şifre güncellemesinden sonra, yeni şifrenizle giriş yapabileceğiniz giriş sayfasına yönlendirileceksiniz."
-msgid "After that, you will not to be able to use merge approvals or code quality as well as many other features."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
-msgstr "Bundan sonra, birleştirme onaylarını veya epikleri ve diğer birçok özelliği kullanamazsınız."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
-msgstr "Bundan sonra, birleştirme onaylarını veya epikleri ve birçok güvenlik özelliğini kullanamazsınız."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgstr ""
msgid "Alert"
msgid_plural "Alerts"
@@ -2275,12 +2368,12 @@ msgstr "Olaylar"
msgid "AlertManagement|High"
msgstr "Yüksek"
+msgid "AlertManagement|Incident"
+msgstr ""
+
msgid "AlertManagement|Info"
msgstr "Bilgi"
-msgid "AlertManagement|Issue"
-msgstr "Sorun"
-
msgid "AlertManagement|Key"
msgstr ""
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr "API URL"
@@ -2404,10 +2506,10 @@ msgstr "Etkin"
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr "Kopyala"
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
-msgstr "Genel"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
+msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr "Uyarılar"
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr "Algoritma"
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr "Tüm konular çözüldü"
-msgid "All users"
-msgstr "Tüm kullanıcılar"
-
msgid "All users must have a name."
msgstr "Tüm kullanıcıların bir adı olmalıdır."
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "Bu gruptaki projelerin Git LFS'yi kullanmasına izin verin"
@@ -2596,6 +2737,9 @@ msgstr "Sistem kancalarından yerel ağa gelen isteklere izin ver"
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr "Bu anahtarın depoya yollanmasına izin verilsin mi? (Varsayılan yalnızca alma erişimine izin verir.)"
@@ -2617,12 +2761,18 @@ msgstr "Ä°zin verildi"
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr "Ä°zin verilmedi"
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Kubernetes kümelerini eklemeye ve yönetmenize olanak tanır."
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr "%{project_path} dizininde bir alarm tetiklendi."
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "Bir hata oluÅŸtu"
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr "Proje yazarları alınırken bir hata oluştu."
msgid "An error occurred previewing the blob"
msgstr "Blob datanın öngösteriminde, bir hata meydana geldi"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "Bildirim aboneliÄŸini deÄŸiÅŸtirirken bir sorun meydana geldi"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "Sorun ağırlığı güncellenirken bir hata oluştu"
@@ -2803,9 +2968,6 @@ 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 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."
@@ -2878,9 +3040,6 @@ msgstr "Sorunlar yüklenirken bir sorun oluştu"
msgid "An error occurred while loading merge requests."
msgstr "Birleştirme istekleri yüklenirken bir hata oluştu."
-msgid "An error occurred while loading milestones"
-msgstr "Dönüm noktaları yüklenirken bir hata oluştu"
-
msgid "An error occurred while loading project creation UI"
msgstr ""
@@ -2911,9 +3070,6 @@ msgstr "Birleştirme isteği yüklenirken bir hata oluştu."
msgid "An error occurred while loading the pipelines jobs."
msgstr "İş hattı işleri yüklenirken bir hata oluştu."
-msgid "An error occurred while loading the subscription details."
-msgstr "Abonelik ayrıntıları yüklenirken bir hata oluştu."
-
msgid "An error occurred while making the request."
msgstr "Talep edilirken bir hata oluÅŸtu."
@@ -2938,6 +3094,9 @@ msgstr "Önizleme yayını iletisi oluşturulurken bir hata oluştu"
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr "Sorunları yeniden sıralarken bir hata oluştu."
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr "Vekiller kaydedilirken bir hata oluÅŸtu"
-msgid "An error occurred while searching for milestones"
-msgstr "Dönüm noktaları aranırken bir hata oluştu"
-
msgid "An error occurred while subscribing to notifications."
msgstr "Bildirimlere abone olunurken bir hata oluÅŸtu."
@@ -2980,6 +3136,9 @@ msgstr "Bildirim aboneliÄŸi iptal edilirken bir hata oluÅŸtu."
msgid "An error occurred while updating approvers"
msgstr "Onaylama sırasında güncelleme yapılırken bir hata oluştu"
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr "ArÅŸiv iÅŸleri"
msgid "Archive project"
msgstr "Projeyi arÅŸivle"
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr "ArÅŸivlenmiÅŸ"
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr "%{assignee_name} kişisine atandı."
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr "Bana atanan"
@@ -3801,8 +3966,29 @@ msgstr "Önceden tanımlanmış bir CI / CD yapılandırmasına göre uygulamanÄ
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "%{link_to_documentation} adresinden daha fazla bilgi edinin"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "Otomatik DevOps iş hattı etkinleştirildi ve alternatif bir CI yapılandırma dosyası bulunmazsa kullanılacak. %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr "Otomatik tamamla"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr "Let's Encrypt kullanarak otomatik sertifika yönetimi"
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr "Not"
msgid "Available"
msgstr "Kullanılabilir"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr "Rozet resim bağlantısı"
msgid "Badges|Badge image preview"
msgstr "Rozet resmi önizlemesi"
-msgid "Badges|Delete badge"
-msgstr "Rozeti sil"
-
msgid "Badges|Delete badge?"
msgstr "Rozet silinsin mi?"
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Dikkatli olun. Projenin isim alanını değiştirmek, istenmeyen yan etkilere neden olabilir."
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "Yükselt"
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr "GeniÅŸlet"
msgid "Boards|View scope"
msgstr "Kapsamı görüntüle"
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr "Bu projenin deposunda %{branchName} dalı bulunamadı."
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr "proje ayarları"
msgid "Branches|protected"
msgstr "korumalı"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr "Dahili"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ msgstr "%{user_name} tarafından"
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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr "Alt epik mevcut deÄŸil."
msgid "Child epic doesn't exist."
msgstr "Alt epik mevcut deÄŸil."
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr "Tüm ortamlar"
msgid "CiVariable|Create wildcard"
msgstr "Joker oluÅŸtur"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr "DeÄŸiÅŸkenler kaydedilirken hata oluÅŸtu"
-
msgid "CiVariable|Masked"
msgstr "Maskeli"
@@ -5163,9 +5403,6 @@ msgstr "Maskelemeyi aç/kapat"
msgid "CiVariable|Toggle protected"
msgstr "Korumayı aç/kapat"
-msgid "CiVariable|Validation failed"
-msgstr "Doğrulama başarısız"
-
msgid "Classification Label (optional)"
msgstr "Sınıflandırma Etiketi (isteğe bağlı)"
@@ -5274,6 +5511,9 @@ msgstr "%{tabname} sekmesini kapat"
msgid "Close epic"
msgstr "EpiÄŸi kapat"
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr "Dönüm noktasını kapat"
@@ -5298,8 +5538,8 @@ msgstr "Kapalı sorunlar"
msgid "Closed this %{quick_action_target}."
msgstr "%{quick_action_target} kapatıldı."
-msgid "Closed: %{closedIssuesCount}"
-msgstr "Kapatıldı: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
+msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "%{quick_action_target} bunu kapatır."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr "Bölgeler yükleniyor"
-
msgid "ClusterIntegration|Loading VPCs"
msgstr "VPC'ler yükleniyor"
@@ -5910,9 +6147,6 @@ msgstr "Proje bulunamadı"
msgid "ClusterIntegration|No projects matched your search"
msgstr "Aramanız ile eşleşen bir proje yok"
-msgid "ClusterIntegration|No region found"
-msgstr "Bölge bulunamadı"
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ msgstr ""
msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "ClusterIntegration|Region"
-msgstr "Bölge"
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Kubernetes küme bütünleşmesini kaldır"
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr "Projeleri ara"
-msgid "ClusterIntegration|Search regions"
-msgstr "Bölgeleri ara"
-
msgid "ClusterIntegration|Search security groups"
msgstr "Güvenlik gruplarını ara"
@@ -6111,6 +6339,9 @@ msgstr "Seçili alan için proje seç"
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr "Alan seç"
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr "Bir bölge seçin"
-
msgid "ClusterIntergation|Select a security group"
msgstr "Bir güvenlik grubu seçin"
@@ -6450,9 +6681,6 @@ msgstr ""
msgid "ComboSearch is not defined"
msgstr ""
-msgid "Coming soon"
-msgstr "Çok yakında"
-
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
msgstr "Virgülle ayrılmış, örneğin '1.1.1.1, 2.2.2.0/24'"
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr "Bağlantı zaman aşımına uğradı"
msgid "Connection timeout"
msgstr "Bağlantı zaman aşımı"
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr "Yükseltmek için satıcı ile iletişim kurun"
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr "Sohbet takma adı %{chat_name} silinemedi."
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr "Ãœlke"
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr "OluÅŸturulma tarihi"
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr "OluÅŸturulma tarihi:"
@@ -7702,6 +7951,9 @@ msgstr "Özel CI yapılandırma yolu"
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr "Özel ana bilgisayar adı (özel işleme e-postaları için)"
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr "Veri hala hesaplanıyor..."
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr "Veri kaynağı adı bulunamadı"
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr "Yorumu sil"
-msgid "Delete Snippet"
-msgstr "Parçacığı Sil"
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr "Panoyu sil"
@@ -8364,9 +8655,6 @@ msgstr "Etiketi sil"
msgid "Delete label: %{label_name} ?"
msgstr "%{label_name} etiketi silinsin mi?"
-msgid "Delete list"
-msgstr "Listeyi sil"
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr "Kod parçacığı silinsin mi?"
msgid "Delete source branch"
msgstr "Kaynak dalı sil"
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr "Bu eki sil"
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr "%{user_name} sohbet takma adına izin verilmedi."
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr "Lisans"
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr "Açıklama"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr "Bir veya daha fazla kümeyle ilişkilendirilirken etki alanı silinemez."
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "Bir daha gösterme"
@@ -9236,9 +9578,6 @@ msgstr "Farklı indir"
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr "Varlığı indir"
-
msgid "Download codes"
msgstr "Kodları indir"
@@ -9407,15 +9746,24 @@ msgstr "Genel dağıtım anahtarını düzenle"
msgid "Edit stage"
msgstr "Aşamayı düzenle"
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr "Bu sürümü düzenle"
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr "Viki sayfasını düzenle"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "Bir konudaki en son yorumunu düzenle (boş bir metin alanından)"
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr "%{timeago} düzenlendi"
@@ -9488,6 +9836,9 @@ msgstr "E-posta gönderildi"
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr "E-postalarda üstbilgi ve altbilgiyi etkinleştir"
msgid "Enable integration"
msgstr "Entegrasyonu etkinleÅŸtir"
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "Bakım modunu etkinleştir"
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "Birleştirme işlemleri hariç tutuluyor. 6,000 işlem ile sınırlı."
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr "Onaylayanları genişlet"
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr "Dışa aktarma sorunları"
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "Projeyi dışa aktar"
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr "İlgili dalların yüklenmesi başarısız oldu"
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr "* (Tüm Ortamlar)"
@@ -10945,6 +11353,9 @@ msgstr "Yapılandır"
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr "Özellik bayrağı oluştur"
@@ -10996,6 +11407,9 @@ msgstr "Özellik bayrağı %{name} kaldırılacak. Emin misiniz?"
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr "Liste"
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr "Bir kullanıcı listesi seçin"
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr "Yapılandırılmış kullanıcı listesi yok"
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "Åžub"
@@ -11191,12 +11611,18 @@ msgstr "Dosya şablonları"
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "Dosyalar"
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr "Git revizyonuna göre filtrele"
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr "Etikete göre filtrele"
@@ -11284,6 +11713,9 @@ msgstr "Süzgeç..."
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr "İlk Görülme"
@@ -11329,9 +11758,15 @@ msgstr "Haftanın ilk günü"
msgid "First name"
msgstr "Ad"
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr "Düzeltilme zamanı"
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr "Git sürümü"
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr "Projelerinize gidin"
msgid "Go to your snippets"
msgstr "Parçacıklarınıza gidin"
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr "Google Cloud Platformu"
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr "Grup profil resmi"
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Aramanızı genişletmek için süzgeçleri değiştirin veya kaldırın; %{startDate} - %{endDate}."
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr "SAML Response XML'ini Kopyala"
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr "NameID"
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "Geçmiş"
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,8 +13658,8 @@ msgstr "Åžifremi unuttum"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr "Let's Encrypt %{link_start}Hizmet Şartları%{link_end}nı okudum ve kabul ediyorum (PDF)"
-msgid "I'd like to receive updates via email about GitLab"
-msgstr "GitLab ile ilgili e-posta yoluyla güncellemeler almak istiyorum"
+msgid "I'd like to receive updates about GitLab via email"
+msgstr ""
msgid "ID"
msgstr ""
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr "Proje üyelerini içe aktar"
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr "Bir alıntı ekle"
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr "Kod ekle"
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr "Öneri ekle"
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr "Görüşler"
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,38 +14441,59 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr "Standart"
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
msgid "Internal"
msgstr "Dahili"
-msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
-msgstr "Dahili - Projeye giriş yapan herhangi bir kullanıcı tarafından erişilebilir."
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "Internal URL (optional)"
msgstr ""
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Aralık Deseni"
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr "Ãœye davet et"
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "Sorun Panoları"
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr "Oca"
msgid "January"
msgstr "Ocak"
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr "Klavye kısayolları"
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ msgstr "Etiket Tanıtımı"
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 "Dil"
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr "Son EriÅŸim Tarihi"
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr "Son İş Hattı"
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr "Soyadı"
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr "Son cevap:"
@@ -14836,6 +15523,9 @@ msgstr "Son güncelleme"
msgid "Last used"
msgstr "Son kullanılan"
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr "Son kullanım:"
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr "Daha fazlasını öğrenin"
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr "Otomatik DevOps hakkında daha fazla bilgi edinin"
@@ -14956,6 +15649,9 @@ msgstr "\"Dosya türü\" ve \"Teslim yöntemi\" seçeneklerini varsayılan değe
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr "Mar"
msgid "March"
msgstr "Mart"
-msgid "Mark To Do as done"
-msgstr "Yapılacakları yapıldı olarak işaretle"
-
msgid "Mark as done"
msgstr "Bitti olarak iÅŸaretle"
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr "Biçimlendirme"
@@ -15549,9 +16245,6 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
-msgid "Marked To Do as done."
-msgstr "Yapılacaklar yapıldı olarak işaretlendi."
-
msgid "Marked this %{noun} as Work In Progress."
msgstr ""
@@ -15561,8 +16254,8 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
-msgstr "Yapılacakları yapıldı olarak işaretler."
+msgid "Marked to do as done."
+msgstr ""
msgid "Marks this %{noun} as Work In Progress."
msgstr ""
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr "Ãœye kilidi"
msgid "Member since %{date}"
msgstr "%{date} tarihinden beri üye"
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr "Ãœyeler"
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr "Bu birleÅŸtirme isteÄŸi birleÅŸtirildi."
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr "Yeni"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr "Yeni Uygulama"
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr "Yok"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr "Yeterli veri yok"
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,21 +18810,15 @@ msgstr ""
msgid "Open issues"
msgstr ""
-msgid "Open projects"
-msgstr "Projeleri aç"
-
msgid "Open raw"
msgstr "Ham olarak aç"
msgid "Open sidebar"
msgstr "Kenar çubuğunu aç"
-msgid "Open: %{openIssuesCount}"
+msgid "Open: %{open}"
msgstr ""
-msgid "Open: %{open} • Closed: %{closed}"
-msgstr "Açık: %{open} • Kapalı: %{closed}"
-
msgid "Opened"
msgstr "Açıldı"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr "Başarı oranı:"
msgid "PipelineCharts|Successful:"
msgstr "Başarılı:"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "Toplam:"
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr "Android"
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr "Daha fazla dakika satın al"
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "Güncellenmiş durumu göstermek için bir saniye içinde yenilenecek..."
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr "Bitiş tarihini kaldırır."
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr "Epiği yeniden aç"
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr "Depo GrafiÄŸi"
msgid "Repository Settings"
msgstr "Depo Ayarları"
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr "SSH ana bilgisayar anahtarları"
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr "Cumartesi"
@@ -22330,6 +23249,9 @@ msgstr "DeÄŸiÅŸiklikleri Kaydet"
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ msgstr "İş hattı takvimini kaydet"
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 variables"
-msgstr "DeÄŸiÅŸkenleri kaydet"
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "Yeni bir iş hattını zamanla"
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr "Ara"
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr "Çatalları ara"
-msgid "Search groups"
-msgstr "Grupları ara"
-
msgid "Search merge requests"
msgstr "Birleştirme isteklerini arayın"
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr "İçe aktarmak istediğiniz projeleri seçin."
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr "Özel proje şablonu kaynak grubunu seçin."
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr "Konuları virgüllerle ayırın."
msgid "September"
msgstr "Eylül"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr "Hizmet Şablonları"
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr "Oturum süresi (dakika)"
@@ -23477,6 +24416,9 @@ msgstr "Yeni ÅŸifre ayarla"
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr "Paylaşılan projeler"
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr "Tüm üyeleri göster"
@@ -23745,6 +24702,9 @@ msgstr "Oturum aç / Kayıt ol"
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr "Akıllı kart kullanarak oturum açın"
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr "Oturum açma kısıtlamaları"
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr "Kayıt kısıtlamaları"
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr "Oturum açıldı:"
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr "%{authentication} doğrulama ile giriş yapıldı"
@@ -23904,27 +24867,18 @@ msgstr "Gösterilecek parçacık yok."
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr "EriÅŸim seviyesi, artan"
msgid "SortOptions|Access level, descending"
msgstr "EriÅŸim seviyesi, azalan"
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr "OluÅŸturulma tarihi"
@@ -24267,6 +25224,9 @@ msgstr "Son giriÅŸ"
msgid "SortOptions|Recently starred"
msgstr "Yakınlarda yıldızlanan"
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr "Boyut"
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "Kaynak kodu"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr "Yıldızlar"
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr "Durum"
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr "Durum:"
@@ -24738,6 +25698,9 @@ msgstr "Spam olarak gönder"
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr "Geri bildirim gönder"
@@ -24753,6 +25716,9 @@ msgstr "Aramayı gönder"
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr "Abonelik başarıyla oluşturuldu."
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr "Fatura"
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "Başarıyla engellendi"
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr "Sistem"
@@ -25068,6 +26052,9 @@ msgstr "Sistem metrikleri (Özel)"
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr "Teşekkürler! Bu mesajı tekrar gösterme"
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "Yol haritası, epiklerinizin bir zaman çizelgesi boyunca ilerlemesini gösterir"
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr "Bu işlem veri kaybına yol açabilir. Yanlışlıkla yapılacak işleml
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr "Bu, hesabınıza giriÅŸ yaptığınız cihazların listesidir. TanımadÄ
msgid "This is a security log of important events involving your account."
msgstr "Bu, hesabınızla ilgili önemli olayların bir güvenlik günlüğüdür."
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Bu sizin mevcut oturumunuz"
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr "ÅŸimdi"
msgid "Timeago|right now"
msgstr "hemen ÅŸimdi"
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr "Zaman aşımı"
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr "İfade ödülünü aç/kapat"
msgid "Toggle navigation"
msgstr "Gezinmeyi aç/kapat"
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Kenar çubuğunu aç/kapat"
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr "Toplam: %{total}"
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr "Kapat"
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr "Kullanım istatistikleri"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr "İş hatları"
msgid "UsageQuota|Purchase more storage"
msgstr "Daha fazla depolama alanı satın al"
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr "Depolar"
@@ -27878,9 +28940,36 @@ msgstr "Parçacıklar"
msgid "UsageQuota|Storage"
msgstr "Depolama"
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "Bu isim alanının paylaşılan çalıştırıcıları kullanan projeleri yok"
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr "Sınırsız"
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr "Kullanım tarihi:"
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr "Viki"
msgid "UsageQuota|Wikis"
msgstr "Viki"
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr "Kullandığınız: %{usage} %{limit}"
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr "Kullanıcı Kimlikleri"
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr "Suistimal için zaten rapor edildi"
msgid "UserProfile|Blocked user"
msgstr "Engellenmiş kullanıcı"
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr "Katıldığı projeler"
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr "Kullanıcı adı ya da e-posta"
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr "Epik kaldırma yolunu belirleyemedik"
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr "Ä°zinleriniz yok"
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr "YouTube"
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr "Gruplarınız"
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr "Projelerinizin EtkinliÄŸi"
msgid "Your Public Email will be displayed on your public profile."
msgstr "Herkese açık e-postanız, herkese açık profilinizde gösterilecektir."
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr "dal adı"
msgid "by"
msgstr "tarafından"
-msgid "by %{user}"
-msgstr "%{user} tarafından"
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr "Raporun tamamını görüntüle"
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,8 +31711,8 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
-msgstr "etkinleÅŸtirildi."
+msgid "is forbidden by a top-level group"
+msgstr ""
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr "çok uzun (en fazla 100 giriş)"
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr "eksik"
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 "hızlı işlemler"
@@ -31184,9 +32342,6 @@ msgstr "kayıt ol"
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr "%{time} yayınlandı"
-
msgid "remaining"
msgstr "kalan"
@@ -31264,6 +32419,9 @@ msgstr "daha az göster"
msgid "sign in"
msgstr "oturum aç"
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr "sırala:"
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr "viki sayfası"
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "%{additions} ekleme, %{deletions} silme ile."
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr "yaml geçersiz"
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index 1d5c6c6b36e..e50f03847fa 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-10-02 18:45\n"
+"PO-Revision-Date: 2020-11-03 22:45\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -79,21 +79,21 @@ msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\" не Ñ–Ñнував у \"%{ref}\""
msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
+msgstr "Параметр \"el\" необхідний Ð´Ð»Ñ createInstance()"
msgid "%d Approval"
msgid_plural "%d Approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d ЗатвердженнÑ"
+msgstr[1] "%d ЗатвердженнÑ"
+msgstr[2] "%d Затверджень"
+msgstr[3] "%d Затверджень"
msgid "%d Package"
msgid_plural "%d Packages"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d пакет"
+msgstr[1] "%d пакета"
+msgstr[2] "%d пакетів"
+msgstr[3] "%d пакетів"
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
@@ -231,6 +231,13 @@ msgstr[1] "%d невдалих"
msgstr[2] "%d невдалих"
msgstr[3] "%d невдалих"
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d виправлений результат теÑту"
@@ -273,13 +280,6 @@ msgstr[1] "%d задачі в цій групі"
msgstr[2] "%d задач в цій групі"
msgstr[3] "%d задач в цій групі"
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "%d вибрана задача"
-msgstr[1] "%d вибрані задачі"
-msgstr[2] "%d вибраних задач"
-msgstr[3] "%d вибраних задач"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -338,10 +338,10 @@ msgstr[3] "ще %d коментарів"
msgid "%d open issue"
msgid_plural "%d open issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d відкрита задача"
+msgstr[1] "%d відкриті задачі"
+msgstr[2] "%d відкритих задач"
+msgstr[3] "%d відкритих задач"
msgid "%d pending comment"
msgid_plural "%d pending comments"
@@ -519,6 +519,20 @@ msgstr "%{count} Ñхвалень від %{name}"
msgid "%{count} files touched"
msgstr "%{count} файлів змінено"
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} more"
msgstr "%{count} більше"
@@ -563,6 +577,12 @@ 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 "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -608,6 +628,12 @@ msgstr "%{group_name} викориÑтовує облікові запиÑи кÐ
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr "вхід на %{host} з нового розташуваннÑ"
@@ -734,9 +760,6 @@ 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 "%{namespace_name} тепер лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ. Ви не можете: %{base_message}"
-
msgid "%{name} contained %{resultsString}"
msgstr "%{name} міÑтить %{resultsString}"
@@ -844,7 +867,7 @@ msgstr[3] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -864,6 +887,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -1089,9 +1115,6 @@ msgstr "(перевірити прогреÑ)"
msgid "(deleted)"
msgstr "(видалено)"
-msgid "(external source)"
-msgstr "(зовнішнє джерело)"
-
msgid "(line: %{startLine})"
msgstr "(Ñ€Ñдок: %{startLine})"
@@ -1132,6 +1155,18 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr "+%{tags} більше"
@@ -1164,6 +1199,9 @@ msgstr ""
msgid "- show less"
msgstr "- показати менше"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr "0 байт"
@@ -1173,19 +1211,8 @@ msgstr "0 Ð´Ð»Ñ Ð½ÐµÐ¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð¾Ð³Ð¾"
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "1 %{type} доповненнÑ"
-msgstr[1] "%{count} %{type} доповненнÑ"
-msgstr[2] "%{count} %{type} доповнень"
-msgstr[3] "%{count} %{type} доповнень"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "1 %{type} зміна"
-msgstr[1] "%{count} %{type} зміни"
-msgstr[2] "%{count} %{type} змін"
-msgstr[3] "%{count} %{type} змін"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1196,10 +1223,10 @@ msgstr[3] "%d днів"
msgid "1 Issue"
msgid_plural "%d Issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "1 Задача"
+msgstr[1] "%d Задачі"
+msgstr[2] "%d Задач"
+msgstr[3] "%d Задач"
msgid "1 closed issue"
msgid_plural "%{issues} closed issues"
@@ -1478,6 +1505,9 @@ msgstr "КориÑтувач із правом запиÑу в гілку-дже
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr "ÐЕОБХІДÐРДІЯ: ЩоÑÑŒ пішло не так при отриманні Ñертифікату Let's Encrypt Ð´Ð»Ñ Ð´Ð¾Ð¼ÐµÐ½Ñƒ GitLab Pages '%{domain}'"
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr "Довідка API"
@@ -1557,7 +1587,7 @@ msgid "Access to Pages websites are controlled based on the user's membership to
msgstr "ДоÑтуп до Ñайтів Pages контролюєтьÑÑ Ð½Ð° оÑнові належноÑÑ‚Ñ– кориÑтувача до певного проєкту. Якщо вÑтановити цей прапорець, кориÑтувачі повинні будуть увійти в ÑиÑтему, щоб мати доÑтуп до вÑÑ–Ñ… Ñайтів Pages у вашому інÑтанÑÑ–."
msgid "AccessDropdown|Deploy Keys"
-msgstr ""
+msgstr "Ключі Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ"
msgid "AccessDropdown|Groups"
msgstr "Групи"
@@ -1779,6 +1809,9 @@ msgstr "Додати таблицю"
msgid "Add a task list"
msgstr "Додати ÑпиÑок завдань"
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Створіть додатковий текÑÑ‚, Ñкий буде приÑутній у вÑÑ–Ñ… повідомленнÑÑ… електронної пошти. МакÑимальна кількіÑÑ‚ÑŒ Ñимволів — %{character_limit}"
@@ -1932,8 +1965,8 @@ msgstr "Додано %{epic_ref} Ñк дочірній епік."
msgid "Added %{label_references} %{label_text}."
msgstr "Додано %{label_references} %{label_text}."
-msgid "Added a To Do."
-msgstr "Додано нагадуваннÑ."
+msgid "Added a to do."
+msgstr ""
msgid "Added an issue to an epic."
msgstr "Додано задачу до епіку."
@@ -1968,12 +2001,12 @@ msgstr "Додає %{epic_ref} Ñк дочірній епік."
msgid "Adds %{labels} %{label_text}."
msgstr "Додає %{labels} %{label_text}."
-msgid "Adds a To Do."
-msgstr "Додає нагадуваннÑ."
-
msgid "Adds a Zoom meeting"
msgstr "Додає Zoom-зуÑтріч"
+msgid "Adds a to do."
+msgstr ""
+
msgid "Adds an issue to an epic."
msgstr "Додає задачу до епіку."
@@ -2020,13 +2053,13 @@ msgid "AdminArea|Bots"
msgstr "Боти"
msgid "AdminArea|Components"
-msgstr ""
+msgstr "Компоненти"
msgid "AdminArea|Developer"
msgstr "Розробник"
msgid "AdminArea|Features"
-msgstr ""
+msgstr "Функції"
msgid "AdminArea|Groups: %{number_of_groups}"
msgstr ""
@@ -2050,12 +2083,15 @@ msgid "AdminArea|Maintainer"
msgstr "Керівник"
msgid "AdminArea|New group"
-msgstr ""
+msgstr "Ðова група"
msgid "AdminArea|New project"
-msgstr ""
+msgstr "Ðовий проєкт"
msgid "AdminArea|New user"
+msgstr "Ðовий кориÑтувач"
+
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
msgstr ""
msgid "AdminArea|Owner"
@@ -2082,6 +2118,9 @@ msgstr "Зупинка завдань пройшла невдало"
msgid "AdminArea|Total users"
msgstr "Загальна кількіÑÑ‚ÑŒ кориÑтувачів"
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "СтатиÑтика кориÑтувачів"
@@ -2196,6 +2235,21 @@ msgstr "Ключі SSH"
msgid "AdminStatistics|Snippets"
msgstr "Сніпети"
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr "2FA вимкнено"
@@ -2205,6 +2259,12 @@ msgstr "2FA увімкнено"
msgid "AdminUsers|Access"
msgstr "ДоÑтуп"
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr "Ðктивні"
@@ -2217,12 +2277,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr "ÐдмініÑтратори"
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr "Заблокувати"
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Заблоквати кориÑтувача"
@@ -2277,6 +2355,9 @@ msgstr "ВикориÑтовує міÑце"
msgid "AdminUsers|It's you!"
msgstr "Це ви!"
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr "Ðовий кориÑтувач"
@@ -2286,6 +2367,9 @@ msgstr "КориÑтувачів не знайдено"
msgid "AdminUsers|Owned groups will be left"
msgstr "Групи, що Ñ” у влаÑноÑÑ‚Ñ– буде збережено"
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr "ПерÑональні проєкти буде збережено"
@@ -2331,6 +2415,9 @@ msgstr "КориÑтувач не зможе викориÑтовувати ко
msgid "AdminUsers|The user will not receive any notifications"
msgstr "КориÑтувач не отримуватиме Ñповіщень"
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð²ÐµÐ´Ñ–Ñ‚ÑŒ %{projectName}"
@@ -2355,6 +2442,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2364,11 +2454,14 @@ msgstr ""
msgid "Administration"
msgstr "ÐдмініÑтруваннÑ"
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr "Розширений"
msgid "Advanced Search"
-msgstr ""
+msgstr "Розширений пошук"
msgid "Advanced Search with Elasticsearch"
msgstr ""
@@ -2379,22 +2472,22 @@ msgstr "Додаткові налаштуваннÑ"
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "Додаткові дозволи, Ñховище великих файлів (LFS) Ñ– Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації."
-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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2461,14 +2554,14 @@ msgstr "Події"
msgid "AlertManagement|High"
msgstr "ВиÑоке"
+msgid "AlertManagement|Incident"
+msgstr ""
+
msgid "AlertManagement|Info"
msgstr "Інформаційне"
-msgid "AlertManagement|Issue"
-msgstr ""
-
msgid "AlertManagement|Key"
-msgstr ""
+msgstr "Ключ"
msgid "AlertManagement|Low"
msgstr "Ðизьке"
@@ -2564,7 +2657,7 @@ msgid "AlertManagement|Unknown"
msgstr "Ðевідоме"
msgid "AlertManagement|Value"
-msgstr ""
+msgstr "ЗначеннÑ"
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
@@ -2581,6 +2674,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2590,10 +2692,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2605,19 +2707,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|HTTP endpoint"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Integration"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2632,6 +2743,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2641,7 +2758,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2659,7 +2779,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2668,6 +2788,27 @@ msgstr "ПопередженнÑ"
msgid "Alerts endpoint"
msgstr "Кінцева точка Ð´Ð»Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½ÑŒ"
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr "Ðлгоритм"
@@ -2734,9 +2875,6 @@ msgstr "Ð’ÑÑ– ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ увімкнені, тому
msgid "All threads resolved"
msgstr "УÑÑ– Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð¸Ñ€Ñ–ÑˆÐµÐ½Ð¾"
-msgid "All users"
-msgstr "Ð’ÑÑ– кориÑтувачі"
-
msgid "All users must have a name."
msgstr "Ð’ÑÑ– кориÑтувачі повинні мати імена."
@@ -2761,6 +2899,9 @@ msgstr "Дозволити влаÑникам керувати захиÑтом
msgid "Allow owners to manually add users outside of LDAP"
msgstr "Дозволити влаÑникам вручну додавати кориÑтувачів за межами LDAP"
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "Дозволити проєктам в цій групі викориÑтовувати Git LFS"
@@ -2782,6 +2923,9 @@ msgstr "Дозволити запити до локальної мережі Ñ–Ð
msgid "Allow requests to the local network from web hooks and services"
msgstr "Дозволити запити до локальної мережі із вуб-хуків та ÑервіÑів"
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr "Дозволити цьому ключеві також відправлÑти зміни в репозиторій? (За замовчуваннÑм дозволÑєтьÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ отримувати.)"
@@ -2803,12 +2947,18 @@ msgstr "Дозволено"
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½Ð¸Ñ… доменів Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти допуÑкаєтьÑÑ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿ найвищого рівнÑ"
msgid "Allowed to fail"
msgstr "Ðевдача дозволена"
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "ДозволÑÑ” додавати та керувати клаÑтерами Kubernetes."
@@ -2857,6 +3007,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2869,9 +3022,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Порожнє поле Gitlab-кориÑтувача буде заповнено іменем кориÑтувача з FogBugz (наприклад \"John Smith\") в опиÑÑ– вÑÑ–Ñ… задач та коментарів. Крім того ці задачі та коментарі будуть аÑоційовані з та/або призначені на автора проєкту."
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2899,9 +3058,15 @@ msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð°Ð
msgid "An error occurred previewing the blob"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду об'єкта"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð¼Ñ–Ð½Ð¸ підпиÑки на ÑповіщеннÑ"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "Збій під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð°Ð³Ð¸ задачі"
@@ -2989,9 +3154,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 "Помилка при отриманні ÑпиÑків дошки. Будь лаÑка, Ñпробуйте знову."
@@ -3064,9 +3226,6 @@ 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 ""
@@ -3097,9 +3256,6 @@ 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 "Помилка при Ñтворенні запиту."
@@ -3124,6 +3280,9 @@ msgstr "Помилка при попередньому переглÑді ого
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr "Помилка при зміні порÑдку задач."
@@ -3148,9 +3307,6 @@ msgstr "Помилка при збереженні ÑтатуÑу перевиз
msgid "An error occurred while saving assignees"
msgstr "Помилка при збереженні виконавців"
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr "Помилка при підпиÑці на ÑповіщеннÑ."
@@ -3166,6 +3322,9 @@ msgstr "Помилка при відпиÑці від Ñповіщень."
msgid "An error occurred while updating approvers"
msgstr "Помилка при оновленні затверджуючих оÑіб"
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3503,6 +3662,9 @@ msgstr "Ðрхівувати завданнÑ"
msgid "Archive project"
msgstr "Ðрхівувати проєкт"
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr "Заархівовано"
@@ -3753,6 +3915,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr "Призначено %{assignee_name}"
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr "Призначено мені"
@@ -4001,8 +4166,29 @@ msgstr "AutoDevOps буде автоматично збирати, теÑтувÐ
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ в %{link_to_documentation}"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "Конвеєр Auto DevOps увімкнено Ñ– буде викориÑтовуватиÑÑ, Ñкщо не знайдено жодного альтернативного файлу конфігурації CI. %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr "ÐвтодоповненнÑ"
@@ -4022,6 +4208,9 @@ msgstr "Ðвтоматичне ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñертифікатами зÐ
msgid "Automatic certificate management using Let's Encrypt"
msgstr "Ðвтоматичне ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñертифікатами за допомогою Let's Encrypt"
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -4040,6 +4229,9 @@ msgstr "Примітка"
msgid "Available"
msgstr "ДоÑтупно"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -4097,9 +4289,6 @@ msgstr "URL-адреÑа Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð½Ð°Ñ‡ÐºÐ°"
msgid "Badges|Badge image preview"
msgstr "Попередній переглÑд значка"
-msgid "Badges|Delete badge"
-msgstr "Видалити значок"
-
msgid "Badges|Delete badge?"
msgstr "Видалити значок?"
@@ -4181,6 +4370,12 @@ msgstr "Коренева URL-адреÑа Bamboo, наприклад https://bam
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr "Ви повинні налаштувати автоматичне вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¼Ñ–Ñ‚Ð¾Ðº на ревізії, а також тригер репозиторію в Bamboo."
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Будьте обережні. Зміна проÑтору імен проєкту може мати небажані побічні ефекти."
@@ -4265,6 +4460,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "Підвищити"
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr "Імпорт з Bitbucket Server"
@@ -4316,12 +4523,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4340,6 +4556,9 @@ msgstr "Розгорнути"
msgid "Boards|View scope"
msgstr "ПереглÑнути облаÑÑ‚ÑŒ видимоÑÑ‚Ñ–"
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4352,6 +4571,9 @@ msgstr "Гілка %{branchName} відÑÑƒÑ‚Ð½Ñ Ð² репозиторії ць
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4496,6 +4718,9 @@ msgstr "ÐалаштуваннÑÑ… проєкту"
msgid "Branches|protected"
msgstr "захищена"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr "ÐžÐ³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ ÑƒÑпішно Ñтворено."
@@ -4532,9 +4757,21 @@ msgstr "Вбудований"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr "Графік виконаннÑ"
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr "Відкрити вагу задачі"
@@ -4565,7 +4802,7 @@ msgstr "Від %{user_name}"
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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4748,6 +4985,9 @@ msgstr "Ðеможливо Ñтворити звіт про зловживанн
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -5159,6 +5399,9 @@ msgstr "Дочірній епік не Ñ–Ñнує."
msgid "Child epic doesn't exist."
msgstr "Дочірній епік не Ñ–Ñнує."
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5342,9 +5585,6 @@ msgstr "Ð’ÑÑ– Ñередовища"
msgid "CiVariable|Create wildcard"
msgstr "Створити шаблон"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr "Помилка при збереженні змінних"
-
msgid "CiVariable|Masked"
msgstr "Приховано"
@@ -5363,9 +5603,6 @@ msgstr "Ввімкнути/вимкнути приховуваннÑ"
msgid "CiVariable|Toggle protected"
msgstr "Ввімкнути/вимкнути захиÑÑ‚"
-msgid "CiVariable|Validation failed"
-msgstr "Перевірка невдала"
-
msgid "Classification Label (optional)"
msgstr "Мітка клаÑифікації (необов'Ñзково)"
@@ -5474,6 +5711,9 @@ msgstr "Закрити %{tabname}"
msgid "Close epic"
msgstr "Закрити епік"
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr "Закрити етап"
@@ -5498,8 +5738,8 @@ msgstr "Закриті задачі"
msgid "Closed this %{quick_action_target}."
msgstr "Закрито %{quick_action_target}."
-msgid "Closed: %{closedIssuesCount}"
-msgstr "Закрито: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
+msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "Закриває %{quick_action_target}."
@@ -5525,6 +5765,9 @@ msgstr "Рівень клаÑтера"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5538,7 +5781,7 @@ msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
msgid "ClusterAgents|Name"
-msgstr ""
+msgstr "Ім'Ñ"
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -5708,6 +5951,9 @@ msgstr "ОчиÑтити кеш клаÑтера"
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr "Проєкт ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ ÐºÐ»Ð°Ñтером (альфа)"
@@ -5765,9 +6011,6 @@ msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ типи інÑтанÑів"
msgid "ClusterIntegration|Could not load networks"
msgstr ""
-msgid "ClusterIntegration|Could not load regions from your AWS account"
-msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ регіони із вашого облікового запиÑу AWS"
-
msgid "ClusterIntegration|Could not load security groups for the selected VPC"
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ групи безпеки Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ñ— VPC"
@@ -5925,7 +6168,7 @@ msgid "ClusterIntegration|Group cluster"
msgstr "КлаÑтер групи"
msgid "ClusterIntegration|HTTP Error"
-msgstr ""
+msgstr "Помилка HTTP"
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -6023,9 +6266,6 @@ msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про %{help_link_start_machine_type}
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про %{help_link_start}зони%{help_link_end}."
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Kubernetes"
@@ -6041,9 +6281,6 @@ msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ€Ð¾Ð»ÐµÐ¹ IAM"
msgid "ClusterIntegration|Loading Key Pairs"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€ ключів"
-msgid "ClusterIntegration|Loading Regions"
-msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ€ÐµÐ³Ñ–Ð¾Ð½Ñ–Ð²"
-
msgid "ClusterIntegration|Loading VPCs"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ VPC"
@@ -6110,9 +6347,6 @@ msgstr "Проектів не знайдено"
msgid "ClusterIntegration|No projects matched your search"
msgstr "Жоден проєкт не відповідає вашому пошуку"
-msgid "ClusterIntegration|No region found"
-msgstr "Регіони не знайдено"
-
msgid "ClusterIntegration|No security group found"
msgstr "Групи безпеки не знайдно"
@@ -6179,9 +6413,6 @@ msgstr "ПереглÑньте %{link_start}Ñторінку довідки%{lin
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 "Відалити інтеграцію із Kubernetes-клаÑтером"
@@ -6248,9 +6479,6 @@ msgstr "Пошук мереж"
msgid "ClusterIntegration|Search projects"
msgstr "Пошук проєктів"
-msgid "ClusterIntegration|Search regions"
-msgstr "Пошук регіонів"
-
msgid "ClusterIntegration|Search security groups"
msgstr "Пошук груп безпеки"
@@ -6311,6 +6539,9 @@ msgstr "Виберіть проєкт, щоб вибрати зону"
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr "Вибрати зону"
@@ -6395,6 +6626,9 @@ msgstr "ВідбуваєтьÑÑ Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ ÐºÑ–Ð½Ñ†ÐµÐ²Ð¾Ñ— точÐ
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr "Проблема автентифікації у вашому клаÑтері. Будь лаÑка, переконайтеÑÑ, що Ñертифікат CA та токен Ñ” правильними."
@@ -6447,7 +6681,7 @@ msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr "Видалити %{appTitle}"
msgid "ClusterIntegration|Unknown Error"
-msgstr ""
+msgstr "Ðевідома помилка"
msgid "ClusterIntegration|Update %{appTitle}"
msgstr ""
@@ -6536,9 +6770,6 @@ msgstr "Вибрати VPC"
msgid "ClusterIntergation|Select a network"
msgstr "Вибрати мережу"
-msgid "ClusterIntergation|Select a region"
-msgstr "Вибрати регіон"
-
msgid "ClusterIntergation|Select a security group"
msgstr "Вибрати групу безпеки"
@@ -6650,9 +6881,6 @@ msgstr "Ім'Ñ Ñ…Ð¾Ñта колектора"
msgid "ComboSearch is not defined"
msgstr "ComboSearch не визначено"
-msgid "Coming soon"
-msgstr "Ðезабаром"
-
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
msgstr "Розділений комами, напр. '1.1.1.1, 2.2.0/24'"
@@ -6966,7 +7194,7 @@ msgstr "Confluence"
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -7017,6 +7245,9 @@ msgstr "Минув Ñ‡Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ"
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr "ЗвернітьÑÑ Ð´Ð¾ відділу продажів Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð´Ñƒ на вищий тарифний план"
@@ -7088,6 +7319,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7467,6 +7701,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr "Копіювати в буфер обміну"
@@ -7527,6 +7764,9 @@ msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ пÑевдонім Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ дизайн."
@@ -7536,6 +7776,9 @@ msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ ітерацію"
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ тригер."
@@ -7569,6 +7812,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ваші дизайни, оÑкільки один або кілька файлів, що завантажуютьÑÑ, не підтримуютьÑÑ."
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr "Країна"
@@ -7819,6 +8065,9 @@ msgstr "Створено запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %{mergeRequestLink} у %{p
msgid "Created on"
msgstr "Створений"
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr "Створено:"
@@ -7912,6 +8161,9 @@ msgstr "КориÑтувацький шлÑÑ… до конфігурації CI"
msgid "Custom Git clone URL for HTTP(S)"
msgstr "КориÑтувацька URL-адреÑа Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Git через HTTP(S)"
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr "ВлаÑне ім'Ñ Ñ…Ð¾Ñта (Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¸Ñ… повідомлень електронної пошти)"
@@ -8165,6 +8417,9 @@ msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð° типом"
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr "Даний діапазон чаÑу перевищує 180 днів"
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr "Загальна кількіÑÑ‚ÑŒ днів до завершеннÑ"
@@ -8222,6 +8477,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8261,6 +8525,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8282,6 +8552,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8307,10 +8583,7 @@ 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 ""
+msgstr "ПаÑивний"
msgid "DastProfiles|Please enter a valid timeout value"
msgstr ""
@@ -8318,6 +8591,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8325,7 +8601,7 @@ msgid "DastProfiles|Save profile"
msgstr ""
msgid "DastProfiles|Scan mode"
-msgstr ""
+msgstr "Режим ÑкануваннÑ"
msgid "DastProfiles|Scanner Profile"
msgstr ""
@@ -8333,6 +8609,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8372,6 +8651,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8384,6 +8666,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8393,6 +8681,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr "Дані вÑе ще обчиÑлюютьÑÑ..."
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr "Ім'Ñ Ð´Ð¶ÐµÑ€ÐµÐ»Ð° даних не знайдено"
@@ -8430,7 +8721,7 @@ msgid "Days to merge"
msgstr "Днів до злиттÑ"
msgid "Dear Administrator,"
-msgstr ""
+msgstr "Шановний ÐдмініÑтратор,"
msgid "Debug"
msgstr "Відладка"
@@ -8549,9 +8840,6 @@ msgstr ""
msgid "Delete Comment"
msgstr "Видалити коментар"
-msgid "Delete Snippet"
-msgstr "Видалити Ñніпет"
-
msgid "Delete Value Stream"
msgstr ""
@@ -8561,6 +8849,9 @@ msgstr "Видалити обліковий запиÑ"
msgid "Delete artifacts"
msgstr "Видалити артефакти"
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr "Видалити дошку"
@@ -8576,9 +8867,6 @@ msgstr "Видалити мітку"
msgid "Delete label: %{label_name} ?"
msgstr "Видалити мітку: %{label_name}?"
-msgid "Delete list"
-msgstr "Видалити ÑпиÑок"
-
msgid "Delete pipeline"
msgstr "Видалити конвеєр"
@@ -8600,6 +8888,9 @@ msgstr "Видалити Ñніпет?"
msgid "Delete source branch"
msgstr "Видалити гілку-джерело"
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr "Видалити це вкладеннÑ"
@@ -8663,12 +8954,18 @@ msgstr "Відмовлено"
msgid "Denied authorization of chat nickname %{user_name}."
msgstr "Відмовлено в авторизації пÑевдоніму Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ %{user_name}."
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr "Заборонити"
msgid "Deny access request"
msgstr "Відхилити запит доÑтупу"
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr "ЗалежноÑÑ‚Ñ–"
@@ -8723,18 +9020,27 @@ msgstr "ЕкÑпортувати Ñк JSON"
msgid "Dependencies|Job failed to generate the dependency list"
msgstr "Завданню не вдалоÑÑ Ñтворити ÑпиÑок залежноÑтей"
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr "ЛіцензіÑ"
msgid "Dependencies|Location"
msgstr "РозташуваннÑ"
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr "Пакувальник"
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ %{codeStartTag}dependency_scanning%{codeEndTag} закінчилоÑÑ Ð½ÐµÑƒÑпішно Ñ– неможе згенерувати ÑпиÑок. Будь лаÑка, переконайтеÑÑ, що Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ñ€ÑƒÑ”Ñ‚ÑŒÑÑ Ð½Ð°Ð»ÐµÐ¶Ð½Ð¸Ð¼ чином Ñ– перезапуÑÑ‚Ñ–Ñ‚ÑŒ конвеєр."
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8816,9 +9122,6 @@ 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 "Вибір за міткою %{appLabel} видалено із дошок розгортань. Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду уÑÑ–Ñ… інÑтанÑів на вашій дошці, ви повинні оновити chart Ñ– виконати повторне розгортаннÑ."
-
msgid "DeployFreeze|Freeze end"
msgstr ""
@@ -8984,6 +9287,12 @@ msgstr "Розгорнуто"
msgid "Deployed to"
msgstr "Розгорнуто на"
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr "Ð Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð´Ð¾"
@@ -9032,6 +9341,9 @@ msgstr "ОпиÑ"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "ÐžÐ¿Ð¸Ñ Ð¾Ð±Ñ€Ð¾Ð±Ð»ÐµÐ½Ð¾ за допомогою %{link_start}GitLab Flavored Markdown%{link_end}"
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr "Шаблони опиÑу дозволÑÑŽÑ‚ÑŒ визначити конкретні шаблони задач та запитів на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ проєкту."
@@ -9203,6 +9515,27 @@ msgstr "DevOps"
msgid "DevOps Report"
msgstr "Звіт DevOps"
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ñ–Ð²Ð½ÑÐ½Ð½Ñ Ð·Ð¼Ñ–Ñту"
@@ -9254,8 +9587,8 @@ msgstr "Вимкнути групові Runner'и"
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
-msgstr "Вимкнути загальні Runner'и"
+msgid "Disable shared runners"
+msgstr ""
msgid "Disable two-factor authentication"
msgstr "Вимкнути двофакторну автентифікацію"
@@ -9405,6 +9738,9 @@ msgstr "ДокументаціÑ"
msgid "Documentation for popular identity providers"
msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ð´Ð»Ñ Ð¿Ð¾ÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ… провайдерів ідентифікації"
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9414,6 +9750,9 @@ msgstr "Домен"
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr "ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð´Ð¾Ð¼ÐµÐ½Ñƒ Ñ” важливою мірою безпеки Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… Ñайтів GitLab. КориÑтувачі повинні показати, що вони керують доменом, перш ніж його буде увімкнено"
@@ -9435,6 +9774,9 @@ 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-----\"."
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "Ðе показувати знову"
@@ -9462,9 +9804,6 @@ msgstr "Завантажити Ñк"
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr "Завантажити реÑурÑ"
-
msgid "Download codes"
msgstr "Завантажити коди"
@@ -9633,15 +9972,24 @@ msgstr "Редагувати публічний ключ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°
msgid "Edit stage"
msgstr "Редагувати Ñтадію"
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr "Редагувати цей реліз"
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr "Редагувати wiki-Ñторінку"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "Редагувати ваш оÑтанній коментар в обговоренні (в порожньому текÑтовому полі)"
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr "Відредаговано %{timeago}"
@@ -9714,6 +10062,9 @@ msgstr "ЛиÑта відправлено"
msgid "Email the pipelines status to a list of recipients."
msgstr "ÐадіÑлати ÑÑ‚Ð°Ñ‚ÑƒÑ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð° по електронній пошті ÑпиÑку отримувачів."
+msgid "Email updates (optional)"
+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 "Схоже, що Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ð¾Ð¶Ð½Ñ”. ПереконайтеÑÑ, що ваша відповідь знаходитьÑÑ Ð½Ð° початку повідомленнÑ, ми не можемо оброблÑти відповіді, що знаходÑÑ‚ÑŒÑÑ Ð² Ñередині та в кінці."
@@ -9855,6 +10206,12 @@ msgstr "Увімкнути заголовок та футер в електроÐ
msgid "Enable integration"
msgstr "Увімкнути інтеграцію"
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "Увімкнути режим обÑлуговуваннÑ"
@@ -9882,8 +10239,20 @@ msgstr "ЗадіÑти прокÑÑ–-Ñервер"
msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr "Увімкнути reCAPTCHA або Akismet Ñ– вÑтановити Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð¾ IP. У випадку reCAPTCHA ми наразі підтримуємо лише %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
-msgid "Enable shared Runners"
-msgstr "Увімкнути загальні Runner'и"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
+msgstr ""
msgid "Enable snowplow tracking"
msgstr "Увімкнути відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· snowplow"
@@ -9927,6 +10296,9 @@ msgstr "Ð£Ð²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ зробить ліцензовану Ñ„
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "ЗавершуєтьÑÑ Ð¾ (за Грінвічем)"
@@ -9954,8 +10326,11 @@ msgstr "Введіть діапазон IP-адреÑ"
msgid "Enter a number"
msgstr "Введіть номер"
-msgid "Enter a whole number between 0 and 100"
-msgstr "Введіть ціле чиÑло від 0 до 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
+msgstr ""
msgid "Enter at least three characters to search"
msgstr "Введіть щонайменше 3 Ñимволи Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ"
@@ -10716,12 +11091,18 @@ msgstr "Ðаприклад: Usage = одиночний запит. (Requested) /
msgid "Except policy:"
msgstr "Політика виключеннÑ:"
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "Без комітів злиттÑ. Обмежено 6000 комітів."
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10752,6 +11133,9 @@ msgstr ""
msgid "Expand approvers"
msgstr "Розгорнути ÑпиÑок затверджуючих оÑіб"
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10827,6 +11211,9 @@ msgstr "ЕкÑпортувати групу"
msgid "Export issues"
msgstr "ЕкÑпортувати задачі"
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "ЕкÑпорт проєкту"
@@ -10929,6 +11316,9 @@ msgstr "Ðе вдалоÑÑ Ñтворити гілку Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— зада
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr "Ðе вдалоÑÑ Ñтворити репозиторій"
@@ -10992,6 +11382,9 @@ msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ мітки. Будь лаÑк
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ пов’Ñзані гілки"
@@ -11004,6 +11397,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ траÑÑƒÐ²Ð°Ð½Ð½Ñ Ñтеку."
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr "Ðе вдалоÑÑ Ð¿Ð¾Ð·Ð½Ð°Ñ‡Ð¸Ñ‚Ð¸ цю задачу Ñк дублікат, тому що не було знайдено задачу, на Ñку йде поÑиланнÑ."
@@ -11143,6 +11539,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr "* (УÑÑ– Ñередовища)"
@@ -11173,6 +11581,9 @@ msgstr "ÐалаштуваннÑ"
msgid "FeatureFlags|Configure feature flags"
msgstr "Ðалаштувати перемикачі функцій"
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr "Створити перемикач функції"
@@ -11224,6 +11635,9 @@ msgstr "Перемикач функції %{name} буде видалено. Ð’Ð
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr "Перемикачі функцій дозволÑÑŽÑ‚ÑŒ налаштовувати ваш код по-різному за допомогою динамічного ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ‡Ð¸ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¿ÐµÐ²Ð½Ð¾Ñ— функціональноÑÑ‚Ñ–."
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11290,11 +11704,14 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr "Процент Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ (за кориÑтувачами, що здійÑнили вхід)"
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
-msgstr "Процент Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð¼Ð°Ñ” бути цілим чиÑлом між 0 та 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
+msgstr ""
msgid "FeatureFlags|Protected"
msgstr "Захищено"
@@ -11308,6 +11725,9 @@ msgstr "Процент розгортаннÑ"
msgid "FeatureFlags|Rollout Strategy"
msgstr "Ð¡Ñ‚Ñ€Ð°Ñ‚ÐµÐ³Ñ–Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11326,9 +11746,6 @@ msgstr "Помилка при отриманні перемикачів функ
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11342,10 +11759,7 @@ msgid "FeatureFlags|User List"
msgstr ""
msgid "FeatureFlags|User Lists"
-msgstr ""
-
-msgid "FeatureFlag|List"
-msgstr "СпиÑок"
+msgstr "СпиÑки кориÑтувачів"
msgid "FeatureFlag|Percentage"
msgstr "ВідÑоток"
@@ -11353,6 +11767,9 @@ msgstr "ВідÑоток"
msgid "FeatureFlag|Select a user list"
msgstr "Виберіть ÑпиÑок кориÑтувачів"
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11362,6 +11779,9 @@ msgstr "Тип"
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "лют."
@@ -11381,7 +11801,7 @@ msgid "File Hooks"
msgstr ""
msgid "File Hooks (%{count})"
-msgstr ""
+msgstr "Файлові Хуки (%{count})"
msgid "File added"
msgstr "Файл додано"
@@ -11419,12 +11839,18 @@ msgstr "Шаблони файлів"
msgid "File upload error."
msgstr "Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ."
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "Файли"
msgid "Files breadcrumb"
msgstr "ÐÐ°Ð²Ñ–Ð³Ð°Ñ†Ñ–Ñ Ð¿Ð¾ файлам"
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr "Файли, каталоги та підмодулі у шлÑху %{path} Ð´Ð»Ñ Ð¿Ð¾ÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° коміт %{ref}"
@@ -11449,6 +11875,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr "Фільтр за мітками"
@@ -11512,6 +11941,9 @@ msgstr "Фільтр..."
msgid "Find File"
msgstr "Знайти файл"
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11545,9 +11977,6 @@ msgstr ""
msgid "Finished"
msgstr "Завершено"
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr "Ім'Ñ Ð·Ð°Ð½Ð°Ð´Ñ‚Ð¾ довге (макÑимум — %{max_length} знаків)."
-
msgid "First Seen"
msgstr ""
@@ -11557,9 +11986,15 @@ msgstr "Перший день тижнÑ"
msgid "First name"
msgstr "Ім'Ñ"
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr "Перший раз знайдено"
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr "Дата виправленнÑ"
@@ -11614,8 +12049,8 @@ 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 internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
msgid "For more info, read the documentation."
msgstr "Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації читайте документацію."
@@ -12160,7 +12595,7 @@ msgstr "Розпочати роботу з релізами"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr "Git LFS не увімкнено на цьому Ñервері GitLab, звернітьÑÑ Ð´Ð¾ адмініÑтратора."
-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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -12181,6 +12616,9 @@ msgstr "ЧаÑтковий (shallow) клон Git"
msgid "Git strategy for pipelines"
msgstr "Git Ñтратегії Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr "Git-верÑÑ–Ñ"
@@ -12191,13 +12629,13 @@ msgid "GitHub import"
msgstr "GitHub-імпорт"
msgid "GitLab"
-msgstr ""
+msgstr "GitLab"
msgid "GitLab / Unsubscribe"
msgstr "GitLab / СкаÑувати підпиÑку"
msgid "GitLab API"
-msgstr ""
+msgstr "GitLab API"
msgid "GitLab Billing Team."
msgstr ""
@@ -12212,14 +12650,11 @@ msgid "GitLab Issue"
msgstr ""
msgid "GitLab Pages"
-msgstr ""
+msgstr "Gitlab Pages"
msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
msgstr ""
-msgid "GitLab 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 "Загальні Runner'и GitLab виконують код Ð´Ð»Ñ Ñ€Ñ–Ð·Ð½Ð¸Ñ… проєктів на одному Ñ– тому ж Runner, Ñкщо ви не налаштуєте автоматичне маÑÑˆÑ‚Ð°Ð±ÑƒÐ²Ð°Ð½Ð½Ñ GitLab Runner’ів за допомогою MaxBuilds 1 (Ñк зроблено на GitLab.com)."
-
msgid "GitLab Shell"
msgstr ""
@@ -12244,6 +12679,12 @@ msgstr "ЕкÑпорт GitLab"
msgid "GitLab for Slack"
msgstr "GitLab Ð´Ð»Ñ Slack"
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12556,6 +12997,9 @@ msgstr "Перейти до ваших проєктів"
msgid "Go to your snippets"
msgstr "Перейти до ваших Ñніпетів"
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr "Google Cloud Platform"
@@ -12661,8 +13105,8 @@ msgstr "URL-адреÑа групи"
msgid "Group avatar"
msgstr "Ðватар групи"
-msgid "Group by:"
-msgstr "Групувати за:"
+msgid "Group by"
+msgstr ""
msgid "Group description"
msgstr "ÐžÐ¿Ð¸Ñ Ð³Ñ€ÑƒÐ¿Ð¸"
@@ -12820,6 +13264,12 @@ msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду плану-графіку, додайте да
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Щоб розширити пошук, змініть або видаліть фільтри; від %{startDate} до %{endDate}."
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "Відбиток Ñертифікату"
@@ -12829,6 +13279,9 @@ msgstr "ÐалаштуваннÑ"
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12874,12 +13327,30 @@ msgstr "NameID"
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12892,6 +13363,9 @@ msgstr "Єдиний вхід через SAML"
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ”Ð´Ð¸Ð½Ð¾Ð³Ð¾ входу через SAML"
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr "URL кінцевої точки SCIM API"
@@ -12904,6 +13378,9 @@ msgstr "SHA1-відбиток Ñертифікату Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñу SAML
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr "Токен SCIM зараз приховоно. Щоб знову побачити Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚Ð¾ÐºÐµÐ½Ð° вам потрібно "
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12928,6 +13405,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr "Ваш токен SCIM"
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13287,7 +13767,7 @@ msgid "Hide comments on this file"
msgstr ""
msgid "Hide details"
-msgstr ""
+msgstr "Приховати подробиці"
msgid "Hide file browser"
msgstr "Сховати файловий менеджер"
@@ -13341,6 +13821,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "ІÑторіÑ"
@@ -13395,9 +13878,6 @@ 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}. Увійдіть, викориÑтовуючи інший обліковий запиÑ, щоб прийнÑти запрошеннÑ."
-msgid "I accept the %{terms_link_start}Terms of Service and Privacy Policy%{terms_link_end}"
-msgstr "Я приймаю %{terms_link_start}Правила кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑервіÑом Ñ– політику конфіденційноÑÑ‚Ñ–%{terms_link_end}"
-
msgid "I accept the %{terms_link}"
msgstr "Я приймаю %{terms_link}"
@@ -13410,8 +13890,8 @@ msgstr "Я забув пароль"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr "Я прочитав Ñ– згодені із %{link_start}умовами викориÑтаннÑ%{link_end} Let's Encrypt (PDF)"
-msgid "I'd like to receive updates via email about GitLab"
-msgstr "Я бажаю отримувати Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ GitLab по електронній пошті"
+msgid "I'd like to receive updates about GitLab via email"
+msgstr ""
msgid "ID"
msgstr "ID"
@@ -13518,6 +13998,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "Якщо це дозволено, доÑтуп до проєктів буде перевірÑтиÑÑ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾ÑŽ Ñлужбою з викориÑтаннÑм Ñ—Ñ… мітки клаÑифікації."
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13542,9 +14025,6 @@ 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 ""
@@ -13566,12 +14046,12 @@ msgstr "Iгнорувати"
msgid "Ignored"
msgstr ""
-msgid "Image Details"
-msgstr "Деталі образу"
-
msgid "Image URL"
msgstr "URL-адреÑа зображеннÑ"
+msgid "Image details"
+msgstr ""
+
msgid "ImageDiffViewer|2-up"
msgstr "2 поруч"
@@ -13655,6 +14135,9 @@ msgstr "Імпортувати кілька репозиторіїв, надіÑ
msgid "Import project"
msgstr "Імпорт проєкту"
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr "Імпортувати учаÑників проєкту"
@@ -13775,6 +14258,12 @@ msgstr "Інцидент"
msgid "Incident Management Limits"
msgstr "Ліміти, пов’Ñзані із УправліннÑм Інцидентами"
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13835,6 +14324,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13844,12 +14336,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13859,6 +14357,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr "Інциденти"
@@ -13871,6 +14393,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "Включити угоду про Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг та правила конфіденційноÑÑ‚Ñ–, Ñкі повинні прийнÑти вÑÑ– кориÑтувачі."
@@ -13946,27 +14471,33 @@ msgstr "Введіть ключі хоÑта вручну"
msgid "Input your repository URL"
msgstr "Введіть ваш URL репозиторію"
-msgid "Insert"
-msgstr "Ð’Ñтавити"
-
msgid "Insert a code block"
msgstr "Ð’Ñтавити блок коду"
msgid "Insert a quote"
msgstr "Ð’Ñтавити цитату"
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr "Ð’Ñтавити малюнок"
msgid "Insert code"
msgstr "Ð’Ñтавити код"
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr "Додати пропозицію"
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr "СтатиÑтика (Insights)"
@@ -13985,6 +14516,9 @@ msgstr "Ð’Ñтановити GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "Ð’Ñтановити Runner на Kubernetes"
+msgid "Install a Runner"
+msgstr ""
+
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr "Ð’Ñтановіть програмний автентифікатор, наприклад %{free_otp_link} або Google Authenticator зі Ñвого репозиторію заÑтоÑунків Ñ– викориÑтовуйте його Ð´Ð»Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ QR-коду. Більш детальна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð´Ð¾Ñтупна в %{help_link_start}документації%{help_link_end}."
@@ -14016,6 +14550,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr "Група Ð´Ð»Ñ Ð°Ð´Ð¼Ñ–Ð½Ñ–Ñтраторів інÑтанÑу вже Ñ–Ñнує"
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -14025,10 +14604,28 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
-msgid "InstanceStatistics|Pipelines"
+msgid "InstanceStatistics|No data available."
msgstr ""
+msgid "InstanceStatistics|Pipelines"
+msgstr "Конвеєри"
+
msgid "InstanceStatistics|Projects"
+msgstr "Проєкти"
+
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
msgstr ""
msgid "InstanceStatistics|Users"
@@ -14064,6 +14661,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -14079,38 +14679,59 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
-msgid "Integrations|Save settings?"
+msgid "Integrations|Return to GitLab for Jira"
msgstr ""
+msgid "Integrations|Save settings?"
+msgstr "Зберегти налаштуваннÑ?"
+
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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 group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
-msgstr "Внутрішній — будь-Ñкий автентифікований кориÑтувач має доÑтуп до цього проєкту."
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "Internal URL (optional)"
msgstr ""
@@ -14118,6 +14739,9 @@ msgstr ""
msgid "Internal users"
msgstr "Внутрішні кориÑтувачі"
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Шаблон інтервалу"
@@ -14137,19 +14761,16 @@ msgid "Invalid Login or password"
msgstr "Ðеправильний логін або пароль"
msgid "Invalid OS"
-msgstr ""
+msgstr "ÐеприпуÑтима ОС"
msgid "Invalid URL"
msgstr "ÐедійÑна URL адреÑа"
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
msgid "Invalid cursor parameter"
-msgstr ""
+msgstr "Ðеправильний параметр курÑору"
msgid "Invalid cursor value provided"
msgstr "Ðадано неправильне Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ ÐºÑƒÑ€Ñора"
@@ -14200,7 +14821,7 @@ msgid "Invalid repository path"
msgstr "Ðеправильний шлÑÑ… до репозиторію"
msgid "Invalid search parameter"
-msgstr ""
+msgstr "ÐедопуÑтимий параметр пошуку"
msgid "Invalid server response"
msgstr "Ðеправильна відповідь від Ñервера"
@@ -14244,25 +14865,25 @@ msgstr "ЗапроÑити учаÑника"
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14310,6 +14931,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14320,7 +14995,7 @@ msgid "Invocations"
msgstr "Виклики"
msgid "Is blocked by"
-msgstr ""
+msgstr "Заблоковано кориÑтувачем"
msgid "Is this GitLab trial for your company?"
msgstr ""
@@ -14358,6 +15033,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "Дошки Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡"
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr "Задачу вже переведено до епіку."
@@ -14574,6 +15252,9 @@ msgstr "Ñіч."
msgid "January"
msgstr "Ñічень"
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14829,6 +15510,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14847,6 +15531,12 @@ msgstr "Комбінації клавіш"
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr "Ключі"
@@ -14976,9 +15666,6 @@ 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 "і ще %{count}"
-
msgid "Language"
msgstr "Мова"
@@ -14993,23 +15680,20 @@ msgstr[2] "ОÑтанніх %d днів"
msgstr[3] "ОÑтанніх %d днів"
msgid "Last 2 weeks"
-msgstr ""
+msgstr "ОÑтанні 2 тижні"
msgid "Last 30 days"
-msgstr ""
+msgstr "ОÑтанні 30 днів"
msgid "Last 60 days"
-msgstr ""
+msgstr "ОÑтанні 60 днів"
msgid "Last 90 days"
-msgstr ""
+msgstr "ОÑтанні 90 днів"
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr "Прізвище занадто довге (макÑимум — %{max_length} знаків)."
-
msgid "Last Pipeline"
msgstr "ОÑтанній Конвеєр"
@@ -15043,6 +15727,9 @@ msgstr ""
msgid "Last name"
msgstr "Прізвище"
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´ÑŒ від"
@@ -15076,6 +15763,9 @@ msgstr "ВоÑтаннє оновленно"
msgid "Last used"
msgstr "ВоÑтаннє викориÑтано"
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr "ОÑтаннє викориÑтаннÑ:"
@@ -15121,6 +15811,9 @@ msgstr ""
msgid "Learn more"
msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Auto DevOps"
@@ -15196,6 +15889,9 @@ msgstr "Залиште параметри \"Тип файлу\" та \"МетоÐ
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "Let's Encrypt не приймає Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти з example.com"
@@ -15702,7 +16398,7 @@ msgid "Manage labels"
msgstr "Керувати мітками"
msgid "Manage milestones"
-msgstr ""
+msgstr "Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ ÐµÑ‚Ð°Ð¿Ð°Ð¼Ð¸"
msgid "Manage project labels"
msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ñ–Ñ‚ÐºÐ°Ð¼Ð¸ проєкту"
@@ -15749,9 +16445,6 @@ msgstr "бер."
msgid "March"
msgstr "березень"
-msgid "Mark To Do as done"
-msgstr "Відмітити Ð½Ð°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¸Ð¼"
-
msgid "Mark as done"
msgstr "Відмітити Ñк виконано"
@@ -15770,6 +16463,9 @@ msgstr "Позначити задачу Ñк дублікат іншої"
msgid "Mark this issue as related to another issue"
msgstr "Позначити задачу Ñк пов’Ñзану з іншою"
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr "Markdown"
@@ -15803,9 +16499,6 @@ 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 "Позначено цей %{noun} Ñк WIP (в процеÑÑ–)."
@@ -15815,8 +16508,8 @@ msgstr "Цю задачу позначено дублікатом %{duplicate_pa
msgid "Marked this issue as related to %{issue_ref}."
msgstr "Цю задачу позначено пов’Ñзаною з %{issue_ref}."
-msgid "Marks To Do as done."
-msgstr "Позначити Ð½Ð°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¸Ð¼."
+msgid "Marked to do as done."
+msgstr ""
msgid "Marks this %{noun} as Work In Progress."
msgstr "Позначає цей %{noun} Ñк WIP (в процеÑÑ–)."
@@ -15827,6 +16520,9 @@ msgstr "Позначає задачу Ñк дублікат %{duplicate_referenc
msgid "Marks this issue as related to %{issue_ref}."
msgstr "Позначає задачу Ñк пов’Ñзану з %{issue_ref}."
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15890,6 +16586,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -16010,6 +16709,12 @@ msgstr "Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÑƒÑ‡Ð°Ñників"
msgid "Member since %{date}"
msgstr "УчаÑник з %{date}"
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr "КориÑтувачі"
@@ -16037,15 +16742,90 @@ msgstr "УчаÑники із доÑтупом до %{strong_start}%{group_name}
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ð°Ð¼â€™ÑÑ‚Ñ–"
@@ -16179,7 +16959,7 @@ msgid "MergeRequestAnalytics|Milestone"
msgstr ""
msgid "MergeRequestAnalytics|Pipelines"
-msgstr ""
+msgstr "Конвеєри"
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
@@ -16283,6 +17063,9 @@ msgstr "Злиті гілки в процеÑÑ– видаленнÑ. Це можÐ
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16293,7 +17076,7 @@ msgid "Merging immediately isn't recommended as it may negatively impact the exi
msgstr "БезпоÑереднє Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½Ðµ рекомендуєтьÑÑ Ñ‚Ð°Ðº Ñк може негативно вплинути на Ñ–Ñнуючий ланцюжок змін. Прочитайте %{docsLinkStart}документацію%{docsLinkEnd} Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації."
msgid "Message"
-msgstr ""
+msgstr "ПовідомленнÑ"
msgid "Messages"
msgstr "ПовідомленнÑ"
@@ -16690,6 +17473,27 @@ msgstr "СпиÑки етапів не доÑтупні з вашою поточ
msgid "Milestone lists show all issues from the selected milestone."
msgstr "У ÑпиÑках етапу відображаютьÑÑ Ð²ÑÑ– задачі Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ етапу."
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr "Закрито:"
@@ -17005,9 +17809,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -17065,6 +17875,38 @@ msgstr "ПроÑÑ‚Ñ–Ñ€ імен порожній"
msgid "Namespace:"
msgstr "ПроÑÑ‚Ñ–Ñ€ імен:"
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr "ПроÑтори імен"
@@ -17320,6 +18162,9 @@ msgstr "Ðіколи"
msgid "New"
msgstr "Ðовий"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr "Ðовий додаток"
@@ -17786,6 +18631,9 @@ msgstr ""
msgid "None"
msgstr "Ðемає"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr "Ðе реалізовано"
@@ -17816,9 +18664,6 @@ msgstr "ÐедоÑтатньо даних"
msgid "Not found."
msgstr "Ðе знайдено."
-msgid "Not now"
-msgstr "Пізніше"
-
msgid "Not ready yet. Try again later."
msgstr "Ще не готово. Спробуйте знову пізніше."
@@ -18053,6 +18898,9 @@ msgstr "OmniAuth"
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -18098,9 +18946,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -18110,9 +18955,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -18234,19 +19076,13 @@ msgstr "Відкрити файл Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду"
msgid "Open issues"
msgstr "Відкриті задачі"
-msgid "Open projects"
-msgstr "Відкриті проєкти"
-
msgid "Open raw"
msgstr "Відкрити в неформатованому виглÑді"
msgid "Open sidebar"
msgstr "Розгорніть бічну панель"
-msgid "Open: %{openIssuesCount}"
-msgstr "Відкрито: %{openIssuesCount}"
-
-msgid "Open: %{open} • Closed: %{closed}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18420,6 +19256,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr "Додати джерело NuGet"
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18516,7 +19355,7 @@ 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|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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18540,9 +19379,6 @@ msgstr "Maven XML"
msgid "PackageRegistry|NPM"
msgstr "NPM"
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -18564,8 +19400,8 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
-msgstr "PyPi"
+msgid "PackageRegistry|PyPI"
+msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
@@ -18588,9 +19424,6 @@ 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 "Виникла проблема при отриманні інформації про цей пакет."
@@ -18606,9 +19439,6 @@ 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 ""
@@ -18618,12 +19448,6 @@ 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 ""
@@ -18648,8 +19472,8 @@ msgstr "NPM"
msgid "PackageType|NuGet"
msgstr "NuGet"
-msgid "PackageType|PyPi"
-msgstr "PyPi"
+msgid "PackageType|PyPI"
+msgstr ""
msgid "Packages"
msgstr "Пакети"
@@ -18661,7 +19485,7 @@ msgid "Page not found"
msgstr "Сторінку не знайдено"
msgid "Page settings"
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñторінки"
msgid "Page was successfully deleted"
msgstr "Сторінку було уÑпішно видалено"
@@ -18832,7 +19656,7 @@ msgid "Pending"
msgstr "В очікуванні"
msgid "Pending comments"
-msgstr ""
+msgstr "Коментарі в очікуванні"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "Люди без дозволу ніколи не отримуватимуть Ñповіщень Ñ– не зможуть коментувати."
@@ -18840,8 +19664,8 @@ msgstr "Люди без дозволу ніколи не отримуватимÑ
msgid "People without permission will never get a notification."
msgstr "Люди без дозволу ніколи не отримуватимуть Ñповіщень."
-msgid "Percent of users"
-msgstr "ВідÑоток кориÑтувачів"
+msgid "Percent rollout must be an integer number between 0 and 100"
+msgstr ""
msgid "Percentage"
msgstr "ВідÑоток"
@@ -18852,9 +19676,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr "Виконати звичайні операції на проєкті GitLab"
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr "ÐžÐ¿Ñ‚Ð¸Ð¼Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾Ð´ÑƒÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚Ñ–"
@@ -18957,6 +19778,9 @@ msgstr "Коефіцієнт уÑпіху:"
msgid "PipelineCharts|Successful:"
msgstr "УÑпішні:"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "Ð’Ñього:"
@@ -19027,7 +19851,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 "Виконуйте збірки із впевненіÑÑ‚ÑŽ"
@@ -19038,6 +19862,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr "Перевірка конфігурації (CI Lint)"
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr "Дочірній конвеєр"
@@ -19048,12 +19875,15 @@ msgid "Pipelines|Continuous Integration can help catch bugs by running your test
msgstr "Безперервна Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð´Ð¾Ð¿Ð¾Ð¼Ð°Ð³Ð°Ñ” знаходити помилки шлÑхом автоматичного запуÑку теÑтів, а безперервне Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ â€” вÑтановлювати код на цільове Ñередовище."
msgid "Pipelines|Copy trigger token"
-msgstr ""
+msgstr "Скопіювати токен тригера"
msgid "Pipelines|Description"
-msgstr ""
+msgstr "ОпиÑ"
msgid "Pipelines|Edit"
+msgstr "Редагувати"
+
+msgid "Pipelines|Editor"
msgstr ""
msgid "Pipelines|Get started with Pipelines"
@@ -19078,19 +19908,22 @@ msgid "Pipelines|Loading Pipelines"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
msgid "Pipelines|More Information"
-msgstr ""
+msgstr "Більше інформації"
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
msgid "Pipelines|Owner"
+msgstr "ВлаÑник"
+
+msgid "Pipelines|Pipeline Editor"
msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr "Кеш проєкту уÑпішно очищено."
msgid "Pipelines|Revoke"
-msgstr ""
+msgstr "Відкликати"
msgid "Pipelines|Run Pipeline"
msgstr "ЗапуÑтити Конвеєр"
@@ -19117,11 +19950,17 @@ msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Цей проєкт в даний Ñ‡Ð°Ñ Ð½Ðµ налаштований Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку конвеєрів."
msgid "Pipelines|Token"
-msgstr ""
+msgstr "Токен"
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19350,6 +20189,9 @@ msgstr "Будь лаÑка, введіть невід'ємне чиÑло"
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr "Будь лаÑка, введіть чиÑло більше за %{number} (із налаштувань проєкту)"
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr "Будь лаÑка, введіть дійÑний номер"
@@ -19359,6 +20201,9 @@ msgstr "Будь лаÑка, введіть або завантажте ліце
msgid "Please fill in a descriptive name for your group."
msgstr "Введіть опиÑове ім'Ñ Ð³Ñ€ÑƒÐ¿Ð¸."
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19371,12 +20216,18 @@ msgstr "Будь лаÑка, мігруйте вÑÑ– уÑнуючі проєкт
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Зверніть увагу, що Ñ†Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð° не Ñ” чаÑтиною GitLab, Ñ– ви повинні впевнитиÑÑ Ñƒ Ñ—Ñ— безпеці, перш ніж надавати доÑтуп."
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr "Будь лаÑка, задайте ім’Ñ"
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr "Будь лаÑка, вкажіть дійÑну e-mail адреÑу."
@@ -19581,9 +20432,6 @@ 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 ""
@@ -20152,7 +21000,7 @@ msgid "Project members"
msgstr "УчаÑники проєкту"
msgid "Project milestone"
-msgstr ""
+msgstr "Етап проєкту"
msgid "Project name"
msgstr "Ðазва проєкту"
@@ -20277,7 +21125,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20580,6 +21428,9 @@ msgstr ".NET Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20634,6 +21485,9 @@ msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
msgstr "SalesforceDX"
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr "Serverless Framework/JS"
@@ -21090,6 +21944,9 @@ msgstr "Гілка"
msgid "ProtectedBranch|Code owner approval"
msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñника коду"
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr "ЗахиÑтити"
@@ -21216,6 +22073,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr "Придбати більше хвилин"
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr "Відправити (push)"
@@ -21327,6 +22187,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr "Ліміт чаÑтоти запиту бінарних даних на хвилину"
@@ -21408,6 +22271,9 @@ msgstr ""
msgid "Refresh"
msgstr "Оновити"
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· Ñекунду Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð°ÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ñтану..."
@@ -21454,9 +22320,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr "ЗареєÑтруватиÑÑ Ð² GitLab"
-
msgid "Register now"
msgstr "ЗареєÑтруватиÑÑŒ зараз"
@@ -21668,6 +22531,9 @@ msgstr "Вилучити ліцензію"
msgid "Remove limit"
msgstr "Прибрати обмеженнÑ"
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr "Виключити учаÑника"
@@ -21788,6 +22654,9 @@ msgstr "ВидалÑÑ” дату завершеннÑ."
msgid "Removes time estimate."
msgstr "ВидалÑÑ” запланований чаÑ."
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21809,9 +22678,15 @@ msgstr ""
msgid "Reopen epic"
msgstr "Повторне Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ ÐµÐ¿Ñ–ÐºÑƒ"
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr "Повторне Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ ÐµÑ‚Ð°Ð¿Ñƒ"
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr "Повторно відкрити %{quick_action_target}"
@@ -21839,6 +22714,9 @@ msgstr "Замінює кореневу URL-адреÑу Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21966,7 +22844,13 @@ msgstr "Репозиторії"
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21978,6 +22862,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21996,6 +22892,9 @@ msgstr "Граф репозиторію"
msgid "Repository Settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ"
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr "Перевірка репозиторію"
@@ -22092,8 +22991,8 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
-msgstr "Вимагати від вÑÑ–Ñ… кориÑтувачів цієї групи налаштувати двофакторну автентифікацію"
+msgid "Require all users 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 "Вимагати від уÑÑ–Ñ… кориÑтувачів приймати умови Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг та політику конфіденційноÑÑ‚Ñ–, коли вони отримують доÑтуп до GitLab."
@@ -22125,6 +23024,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr "Вимогу %{reference} було оновлено"
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr "Заголовок вимоги не може міÑтити більше %{limit} знаків."
@@ -22332,6 +23234,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+msgstr ""
+
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
msgstr "ПереглÑте Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð²Ð°Ð¹Ð´ÐµÑ€Ñ–Ð² поÑлуг у вашому провайдері ідентифікації — в такому разі GitLab Ñ” \"провайдером поÑлуг\" або \"довірÑючою Ñтороною\"."
@@ -22394,7 +23299,7 @@ msgid "Rook"
msgstr "Rook"
msgid "Ruby"
-msgstr ""
+msgstr "Ruby"
msgid "Rule name is already taken."
msgstr ""
@@ -22475,25 +23380,31 @@ msgid "Runners page."
msgstr "Сторінка Runner'ів."
msgid "Runners|Active"
-msgstr ""
+msgstr "Ðктивні"
msgid "Runners|Architecture"
-msgstr ""
+msgstr "Ðрхітектура"
msgid "Runners|Can run untagged jobs"
msgstr ""
msgid "Runners|Description"
+msgstr "ОпиÑ"
+
+msgid "Runners|Download Latest Binary"
msgstr ""
-msgid "Runners|Group"
+msgid "Runners|Download and Install Binary"
msgstr ""
+msgid "Runners|Group"
+msgstr "Група"
+
msgid "Runners|IP Address"
-msgstr ""
+msgstr "IP-адреÑа"
msgid "Runners|Last contact"
-msgstr ""
+msgstr "ОÑтанній контакт"
msgid "Runners|Locked to this project"
msgstr ""
@@ -22502,34 +23413,37 @@ msgid "Runners|Maximum job timeout"
msgstr ""
msgid "Runners|Name"
-msgstr ""
+msgstr "Ім'Ñ"
msgid "Runners|Platform"
-msgstr ""
+msgstr "Платформа"
msgid "Runners|Property Name"
msgstr ""
msgid "Runners|Protected"
+msgstr "Захищені"
+
+msgid "Runners|Register Runner"
msgstr ""
msgid "Runners|Revision"
-msgstr ""
+msgstr "ВерÑÑ–Ñ"
msgid "Runners|Shared"
-msgstr ""
+msgstr "Спільні"
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
-msgstr ""
+msgstr "Теги"
msgid "Runners|Value"
-msgstr ""
+msgstr "ЗначеннÑ"
msgid "Runners|Version"
-msgstr ""
+msgstr "ВерÑÑ–Ñ"
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "Ви викориÑтали %{quotaUsed} із ваших %{quotaLimit} хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² загальних runner'ів."
@@ -22544,7 +23458,7 @@ msgid "Runs a number of housekeeping tasks within the current repository, such a
msgstr "Виконує Ñ€Ñд задач по очищенню поточного репозиторію, таких Ñк ÑтиÑÐ½ÐµÐ½Ð½Ñ Ñ€ÐµÐ´Ð°ÐºÑ†Ñ–Ð¹ файлів та Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð½ÐµÐ´Ð¾ÑÑжних об'єктів."
msgid "SAML"
-msgstr ""
+msgstr "SAML"
msgid "SAML SSO"
msgstr "Єдиний вхід SAML"
@@ -22582,6 +23496,9 @@ 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 ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr "Ключі SSH дозволÑÑŽÑ‚ÑŒ вÑтановити захищене Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¼Ñ–Ð¶ вашим комп’ютером та GitLab."
@@ -22591,6 +23508,12 @@ msgstr "Відкритий SSH-ключ"
msgid "SSL Verification:"
msgstr "Перевірка SSL:"
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr "Субота"
@@ -22606,6 +23529,9 @@ msgstr "Зберегти зміни"
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr "Ð’Ñе одно зберегти"
@@ -22630,9 +23556,6 @@ 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 variables"
-msgstr "Зберегти змінні"
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22642,6 +23565,9 @@ msgstr "ЗбереженнÑ"
msgid "Saving project."
msgstr "Ð—Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ."
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "Розклад нового конвеєра"
@@ -22681,6 +23607,9 @@ msgstr "ОблаÑÑ‚ÑŒ дії"
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22711,7 +23640,7 @@ msgstr "Пошук"
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22768,9 +23697,6 @@ msgstr "Шукати цей текÑÑ‚"
msgid "Search forks"
msgstr "Пошук форків"
-msgid "Search groups"
-msgstr "Пошук в групах"
-
msgid "Search merge requests"
msgstr "Пошук у запитах на злиттÑ"
@@ -22852,9 +23778,6 @@ 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 "Ми не знайшли %{scope}, що задовільнÑÑ” %{term}"
-
msgid "SearchResults|code result"
msgid_plural "SearchResults|code results"
msgstr[0] "результат в коді"
@@ -22941,7 +23864,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22986,10 +23909,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -23118,6 +24041,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -23181,6 +24107,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -23220,6 +24152,13 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr "Помилка при відхиленні вразливоÑтей."
@@ -23400,6 +24339,9 @@ msgstr "Виберіть проєкти, Ñкі ви хочете імпорту
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr "Виберіть Ñегменти Ð´Ð»Ñ Ñ€ÐµÐ¿Ð»Ñ–ÐºÐ°Ñ†Ñ–Ñ—"
@@ -23415,7 +24357,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23430,9 +24372,6 @@ msgstr "Виберіть гілку по замовчанню Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾
msgid "Select the custom project template source group."
msgstr "Вкажіть групу, де розміщені влаÑні шаблони проєктів."
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr "Обрати чаÑовий поÑÑ"
@@ -23526,6 +24465,9 @@ msgstr "ВідділÑйте теми комами."
msgid "September"
msgstr "вереÑень"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr "Ñ–"
@@ -23640,6 +24582,9 @@ msgstr "Шаблони ÑервіÑів"
msgid "Service URL"
msgstr "URL ÑервіÑу"
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr "ТриваліÑÑ‚ÑŒ ÑеÑÑ–Ñ— (у хвилинах)"
@@ -23775,6 +24720,9 @@ msgstr "Ð’Ñтановити новий пароль"
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "Ðалаштуйте Ñвій проєкт, щоб автоматично відправлÑти/отримувати зміни з іншого репозиторію. Гілки, теги та коміти автоматично будуть ÑинхронізуватиÑÑ."
@@ -23880,6 +24828,15 @@ msgstr "Загальні Runner'и"
msgid "Shared projects"
msgstr "Спільні проєкти"
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr "Допомога по загальним runner'ам"
@@ -23898,9 +24855,15 @@ msgstr "Sherlock транзакції"
msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
msgstr "Якщо ви коли-небудь втратите телефон або доÑтуп до Ñвоїх одноразових паролів, кожен із цих кодів Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶Ðµ бути викориÑтаний один раз Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ñтупу до вашого облікового запиÑу. Будь лаÑка, зберігайте Ñ—Ñ… в надійному міÑці, інакше ви %{b_start}втратите%{b_end} доÑтуп до вашого облікового запиÑу."
+msgid "Show Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr "Показати вÑÑŽ активніÑÑ‚ÑŒ"
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr "Показати вÑÑ–Ñ… учаÑників"
@@ -24047,6 +25010,9 @@ msgstr "Увійти або зареєÑтруватиÑÑ"
msgid "Sign in to \"%{group_name}\""
msgstr "Увійти до \"%{group_name}\""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr "Увійти за допомогою Ñмарт-карти"
@@ -24074,6 +25040,9 @@ msgstr "РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾Ð¹ÑˆÐ»Ð° уÑпішно! Будь лаÑка,
msgid "Sign-in restrictions"
msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ"
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації"
@@ -24083,9 +25052,6 @@ msgstr "Ð†Ð¼â€™Ñ Ð·Ð°Ð½Ð°Ð´Ñ‚Ð¾ довге (макÑимум Ñкладає %{m
msgid "SignUp|Last Name is too long (maximum is %{max_length} characters)."
msgstr "Прізвище занадто довге (макÑимум Ñкладає %{max_length} Ñимволів)."
-msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
-msgstr "Ð†Ð¼â€™Ñ Ð·Ð°Ð½Ð°Ð´Ñ‚Ð¾ довге (макÑимум Ñкладає %{max_length} Ñимволів)."
-
msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
msgstr "Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача занадто довге (макÑимум Ñкладає %{max_length} Ñимволів)."
@@ -24095,6 +25061,9 @@ msgstr ""
msgid "Signed in"
msgstr "Вхід виконано"
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr "Вхід відбувÑÑ Ð·Ð° допомогою %{authentication}"
@@ -24206,27 +25175,18 @@ msgstr "Ðемає Ñніпетів Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ."
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24461,6 +25421,9 @@ msgstr "Рівень доÑтупу, в порÑдку зроÑтаннÑ"
msgid "SortOptions|Access level, descending"
msgstr "Рівень доÑтупу, в порÑдку ÑпаданнÑ"
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr "Дата ÑтвореннÑ"
@@ -24569,6 +25532,9 @@ msgstr "Ðещодавно зареєÑтровані"
msgid "SortOptions|Recently starred"
msgstr "Ðещодавно в обраних"
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr "Розмір"
@@ -24611,9 +25577,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "Код"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24689,9 +25652,6 @@ msgstr "Вкажіть шаблон адреÑи електронної пошт
msgid "Specify the following URL during the Runner setup:"
msgstr "Зазначте наÑтупний URL під Ñ‡Ð°Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Runner-а:"
-msgid "Speed up your DevOps%{br_tag}with GitLab"
-msgstr ""
-
msgid "Squash commit message"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¾Ð±'єднаного (squash) коміту"
@@ -24755,6 +25715,9 @@ msgstr "У обраному"
msgid "Start Date"
msgstr "Дата початку"
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr "ЗапуÑтити Веб-Термінал"
@@ -24911,6 +25874,9 @@ msgstr "СтатиÑтика"
msgid "Status"
msgstr "СтатуÑ"
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr "СтатуÑ:"
@@ -25040,6 +26006,9 @@ msgstr "Позначити Ñк Ñпам"
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr "ÐадіÑлати відгук"
@@ -25055,6 +26024,9 @@ msgstr "ÐадіÑлати пошук"
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -25097,6 +26069,12 @@ msgstr "ПідпиÑку уÑпішно Ñтворено."
msgid "Subscription successfully deleted."
msgstr "ПідпиÑку уÑпішно видалено."
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr "Білінг"
@@ -25181,6 +26159,9 @@ msgstr ""
msgid "Successfully activated"
msgstr "УÑпішно активовано"
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "УÑпішно заблоковано"
@@ -25202,6 +26183,9 @@ msgstr "УÑпішно видалено адреÑу електронної по
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr "УÑпішно заплановано контейнер Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку. Перейдіть на %{pipelines_link_start}Ñторінку конвеєрів%{pipelines_link_end} Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð¸Ñ†ÑŒ."
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr "УÑпішно розблоковано"
@@ -25337,12 +26321,18 @@ msgstr ""
msgid "Sync information"
msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñинхронізацію"
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr "Синхронізовано"
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr "СиÑтемні"
@@ -25370,6 +26360,9 @@ msgstr "СиÑтемні метрики (ВлаÑні)"
msgid "System metrics (Kubernetes)"
msgstr "СиÑтемні метрики (Kubernetes)"
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr "ЗміÑÑ‚"
@@ -25610,15 +26603,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25703,8 +26711,8 @@ msgstr "ДÑкуємо за покупку!"
msgid "Thanks! Don't show me this again"
msgstr "ДÑкую! Більше не показувати це повідомленнÑ"
-msgid "That's it, well done!%{celebrate}"
-msgstr "Це вÑе, хороша робота!%{celebrate}"
+msgid "That's it, well done!"
+msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "Група \"%{group_path}\" дозволÑÑ” увійти за допомогою облікового запиÑу єдиного входу"
@@ -25728,9 +26736,6 @@ 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 ""
@@ -25743,9 +26748,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr "URL-адреÑа Ð´Ð»Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ Elasticsearch. ВикориÑтовуйте ÑпиÑок, розділений комами, Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ клаÑтеризації (наприклад: \"http://localhost:9200, http://localhost:9201\")."
@@ -25842,6 +26853,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "ÐаÑтупні елементи ÐЕ будуть екÑпортовані:"
@@ -25867,8 +26884,8 @@ 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 internal projects can be viewed by any logged in user except external users."
+msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð° та будь-Ñкі проєкти можуть переглÑдатиÑÑ Ð±ÐµÐ· жодної автентифікації."
@@ -25978,8 +26995,8 @@ msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ ÐŸÐ»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶Ð°Ñ” Ñ‡Ð°Ñ Ð²Ñ–Ð´ пÐ
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr "Приватний ключ, Ñкий викориÑтовуєтьÑÑ Ð¿Ñ€Ð¸ наданні клієнтÑького Ñертифіката. Його Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð°ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¾."
-msgid "The project can be accessed by any logged in user."
-msgstr "ДоÑтуп до проєкту можливий будь-Ñким зареєÑтрованим кориÑтувачем."
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr "ДоÑтуп до цього проєкту Ñ” в будь-Ñкого кориÑтувача, Ñкий увійшов у ÑиÑтему."
@@ -26038,6 +27055,9 @@ msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ ÐŸÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ° показує Ñ‡Ð°Ñ Ð²Ñ–Ð´ ÑтворÐ
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "План-графік показує Ñтан ваших епіків у чаÑÑ–"
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr "Запланований Ñ‡Ð°Ñ Ð¼Ð°Ñ” бути в майбутньому!"
@@ -26050,8 +27070,8 @@ msgstr "Цей Ñніпет Ñ” видим лише Ð´Ð»Ñ Ð¼ÐµÐ½Ðµ."
msgid "The snippet is visible only to project members."
msgstr "Цей Ñніпет видимий тільки Ð´Ð»Ñ ÑƒÑ‡Ð°Ñників проєкту."
-msgid "The snippet is visible to any logged in user."
-msgstr "Цей Ñніпет видимий Ð´Ð»Ñ Ð±ÑƒÐ´ÑŒ-Ñкого зареєÑтрованого кориÑтувача."
+msgid "The snippet is visible to any logged in user except external users."
+msgstr ""
msgid "The specified tab is invalid, please select another"
msgstr "Вказана вкладка недійÑна. Будь лаÑка, виберіть іншу"
@@ -26089,6 +27109,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "Мапа кориÑтувачів — це правила Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів FogBugz, Ñкі приймали учаÑÑ‚ÑŒ у ваших проєктах до Gitlab (зокрема Ñ—Ñ… імен та Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти). Ви можете вноÑити зміни шлÑхом Ð·Ð°Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ– нижче."
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr "КориÑтувач Ñкого ви збираєтеÑÑ Ð´ÐµÐ°ÐºÑ‚Ð¸Ð²ÑƒÐ²Ð°Ñ‚Ð¸ був активним протÑгом оÑтанніх %{minimum_inactive_days} днів Ñ– не може бути деактивований"
@@ -26197,6 +27220,9 @@ msgstr "Ðа диÑку вже Ñ–Ñнує репозиторій за таким
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr "Даних немає. Будь лаÑка, змініть Ñвій вибір."
@@ -26392,6 +27418,9 @@ msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° з reCAPTCHA. Будь лаÑка, проÐ
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr "Ці Ñ–Ñнуючі проблеми мають подібні заголовки. Можливо, краще додати коментар до однієї з них заміÑÑ‚ÑŒ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ñ—."
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr "Ці змінні вÑтановлені в налаштуваннÑÑ… батьківÑької групи Ñ– будуть активними в поточному проєкті додатково до проєктних змінних."
@@ -26443,7 +27472,7 @@ msgstr "Ð¦Ñ Ð´Ñ–Ñ Ð¼Ð¾Ð¶Ðµ призвеÑти до втрати даних. Щ
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26467,9 +27496,15 @@ msgstr "Цей заÑтоÑунок було Ñтворено %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Ð¦Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð° зможе:"
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr "Цей блок поÑилаєтьÑÑ Ñам на Ñебе"
@@ -26602,6 +27637,9 @@ msgstr "Це ÑпиÑок приÑтроїв, з котрих заходили Ð
msgid "This is a security log of important events involving your account."
msgstr "Це журнал безпеки, Ñкий міÑтить уÑÑ– важливі події пов’Ñзані із вашим обліковим запиÑом."
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26611,6 +27649,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Це ваш поточний ÑеанÑ"
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -27163,6 +28204,12 @@ msgstr "щойно"
msgid "Timeago|right now"
msgstr "зараз"
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ"
@@ -27201,8 +28248,8 @@ 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 "Ð”Ð»Ñ %{link_to_help} вашого домену, додайте в вищезгаданий ключ до TXT запиÑу у вашій конфігурації DNS."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
+msgstr ""
msgid "To Do"
msgstr "Виконати"
@@ -27252,8 +28299,8 @@ msgstr "Спочатку введіть адреÑу Ñервера GÑ–tea Ñ– %{
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
+msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "Ð”Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ SVN-репозиторію, переглÑньте %{svn_link}."
@@ -27381,6 +28428,9 @@ msgstr "Увімкнути/вимкнути Ñмайлики-нагороди"
msgid "Toggle navigation"
msgstr "Переключити навігацію"
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Перемикач бічної панелі"
@@ -27453,17 +28503,20 @@ msgstr "Ð’Ñього памʼÑÑ‚Ñ– (ГБ)"
msgid "Total test time for all commits/merges"
msgstr "Загальний чаÑ, щоб перевірити вÑÑ– коміти/злиттÑ"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr "Загальна вага"
msgid "Total: %{total}"
msgstr "Ð’Ñього: %{total}"
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
-msgstr "Лог"
+msgid "TotalRefCountIndicator|1000+"
+msgstr ""
msgid "Tracing"
msgstr "ВідÑтеженнÑ"
@@ -27639,6 +28692,9 @@ msgstr "ВідбуваєтьÑÑ Ð·'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñ–Ð· вашим приÑÑ‚Ñ€Ð
msgid "Tuesday"
msgstr "Вівторок"
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr "Вимкнути"
@@ -27789,6 +28845,9 @@ msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ ітерацію. Будь лаÑк
msgid "Unable to save your changes. Please try again."
msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ ваші зміни. Будь лаÑка, Ñпробуйте знову."
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr "ÐевдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити конвеєр негайно"
@@ -28014,6 +29073,9 @@ msgstr "Оновити ітерацію"
msgid "Update now"
msgstr "Оновити зараз"
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr "Оновити змінну"
@@ -28152,10 +29214,13 @@ msgstr "СтатиÑтика викориÑтаннÑ"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr "%{help_link_start}Загальні runner'и%{help_link_end} вимкнено, тому ліміти на викориÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² відÑутні"
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "Ðртефакти"
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -28182,6 +29247,9 @@ msgstr "Конвеєри"
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -28194,9 +29262,36 @@ msgstr "Сніпети"
msgid "UsageQuota|Storage"
msgstr "Сховище"
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "Цей проÑÑ‚Ñ–Ñ€ імен не міÑтить проєктів, що викориÑтовують загальні runner'и"
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr "Без обмежень"
@@ -28218,15 +29313,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ñ–Ð´"
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr "Вікі"
msgid "UsageQuota|Wikis"
msgstr "Вікі"
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -28281,11 +29388,8 @@ msgstr "КориÑтувач %{current_user_username} розпочав імітÑ
msgid "User %{username} was successfully removed."
msgstr "КориÑтувача %{username} уÑпішно видалено."
-msgid "User IDs"
-msgstr "ID кориÑтувачів"
-
-msgid "User List"
-msgstr "СпиÑок кориÑтувачів"
+msgid "User ID"
+msgstr ""
msgid "User OAuth applications"
msgstr "OAuth заÑтоÑунки кориÑтувача"
@@ -28404,6 +29508,9 @@ msgstr "Вже повідомлено про зловживаннÑ"
msgid "UserProfile|Blocked user"
msgstr "Заблокований кориÑтувач"
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr "ВнеÑки в проєкти"
@@ -28500,9 +29607,6 @@ msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача вже зайнÑто."
msgid "Username is available."
msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача доÑтупне."
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача занадто довге (макÑимум %{max_length} Ñимволів)."
-
msgid "Username or email"
msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача або електронна пошта"
@@ -28656,6 +29760,12 @@ msgstr ""
msgid "View Documentation"
msgstr "ПереглÑнути документацію"
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr "ПроглÑнути вÑÑ– задачі"
@@ -28664,10 +29774,10 @@ msgstr ""
msgid "View chart"
msgid_plural "View charts"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "ПереглÑнути графік"
+msgstr[1] "ПереглÑнути графіки"
+msgstr[2] "ПереглÑнути графіки"
+msgstr[3] "ПереглÑнути графіки"
msgid "View dependency details for your project"
msgstr "ПереглÑнути інформацію про залежноÑÑ‚Ñ– Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ проєкту"
@@ -28967,7 +30077,13 @@ msgstr "КлаÑ"
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -29051,6 +30167,15 @@ msgstr "Ми не змогли визначити шлÑÑ… до видаленн
msgid "We could not determine the path to remove the issue"
msgstr "Ми не змогли визначити шлÑÑ… до Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ–"
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr "Ðе вдалоÑÑ Ð¿Ñ–Ð´ÐºÑŽÑ‡Ð¸Ñ‚Ð¸ÑÑ Ð´Ð¾ Ñервера Prometheus. Ðбо Ñервер більше не Ñ–Ñнує, або необхідно оновити деталі конфігурації."
@@ -29147,6 +30272,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -29171,13 +30299,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -29246,15 +30377,15 @@ msgstr "ЛаÑкаво проÑимо до GitLab, %{first_name}!"
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr "Що ви шукаєте?"
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr "Що нового в GitLab"
@@ -29267,7 +30398,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Коли runner закріплений (за проєктами), його не можна викориÑтовувати в інших проєктах"
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29511,10 +30642,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29607,6 +30738,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29628,6 +30762,9 @@ msgstr "Ви знаходитеÑÑ Ð½Ð° інÑтанÑÑ– Gitlab \"тільки
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr "Ви отримуєте це повідомленнÑ, бо ви Ñ” адмініÑтратором GitLab Ð´Ð»Ñ %{url}."
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr "Ви намагаєтеÑÑŒ завантажити щоÑÑŒ, що не Ñ” зображеннÑм. Будь лаÑка, завантажте файл .png, .jpg, .jpeg, .gif, .bmp, .tiff або .ico."
@@ -29640,12 +30777,12 @@ msgstr "ЗаміÑÑ‚ÑŒ цього ви можете %{linkStart}переглÑн
msgid "You can also create a project from the command line."
msgstr "Ви також можете Ñтворити проєкт із командного Ñ€Ñдка."
-msgid "You can also press &#8984;-Enter"
-msgstr "Ви також можете натиÑнути &#8984;-Enter"
-
msgid "You can also press Ctrl-Enter"
msgstr "Ви також можете натиÑнути Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr "Ви можете додати мітку в обрані, щоб зробити її пріоритетною."
@@ -29658,6 +30795,15 @@ msgstr "Також ви можете завантажувати файли з в
msgid "You can always edit this later"
msgstr "Ви завжди можете відредагувати це пізніше"
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29859,6 +31005,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr "Ви відпиÑані від цього обговореннÑ."
@@ -29871,6 +31020,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” прав доÑтупу"
@@ -29895,9 +31053,6 @@ msgstr "Ви залишили \"%{membershipable_human_name}\" %{source_type}."
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 be logged in to search across all of GitLab"
msgstr ""
@@ -29955,9 +31110,6 @@ msgstr "Ви повинні завантажити екÑпортований а
msgid "You need to upload a Google Takeout archive."
msgstr "Вам потрібно завантажити архів Google Takeout."
-msgid "You reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
-msgstr ""
-
msgid "You successfully declined the invitation"
msgstr ""
@@ -30060,19 +31212,22 @@ msgstr "Ви уже увімкнули двофакторну автентифі
msgid "YouTube"
msgstr "YouTube"
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -30102,6 +31257,9 @@ msgstr "Ваші групи"
msgid "Your License"
msgstr "Ваша ліцензіÑ"
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr "Термін дії вашого перÑонального токену доÑтупу закінчитьÑÑ Ñ‡ÐµÑ€ÐµÐ· %{days_to_expire} днів або менше"
@@ -30117,6 +31275,9 @@ msgstr "ÐктивніÑÑ‚ÑŒ ваших проєктів"
msgid "Your Public Email will be displayed on your public profile."
msgstr "Ваша публічна адреÑа електронної пошти буде відображатиÑÑ Ð² публічному профілі."
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr "Ваші ключі SSH (%{count})"
@@ -30385,9 +31546,6 @@ msgstr "ім'Ñ Ð³Ñ–Ð»ÐºÐ¸"
msgid "by"
msgstr "від"
-msgid "by %{user}"
-msgstr "від %{user}"
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30514,9 +31672,6 @@ msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ñ–Ð² виÑвлÑÑ” відомі
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30562,9 +31717,6 @@ msgstr "Знайдено %{issuesWithCount}"
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 ""
@@ -30650,6 +31802,9 @@ msgstr "ПереглÑнути повний звіт"
msgid "closed issue"
msgstr "закрита задача"
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr "коментар"
@@ -30898,8 +32053,8 @@ msgstr "Ñ” недопуÑтимим діапазоном IP-адреÑ"
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
-msgstr "увімкнено."
+msgid "is forbidden by a top-level group"
+msgstr ""
msgid "is invalid because there is downstream lock"
msgstr "неправильний через наÑвніÑÑ‚ÑŒ блокувань на нижчих рівнÑÑ…"
@@ -30916,6 +32071,9 @@ msgstr "не Ñ” нащадком групи, Ñкій належить шаблÐ
msgid "is not a valid X509 certificate."
msgstr "не відповідний Ñертифікат X509."
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr "не дозволено. Спробуйте ще раз з іншою адреÑою електронної пошти або зв'ÑжітьÑÑ Ð· адмініÑтратором GitLab."
@@ -30934,6 +32092,9 @@ msgstr "лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ"
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr "Ñ” занадто довгим (%{current_value}). МакÑимальний розмір Ñкладає %{max_size}."
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr "Ñ” занадто довгим (макÑимум Ñкладає 100 елементів)"
@@ -30970,6 +32131,9 @@ msgstr "те, що він занадто великий"
msgid "jigsaw is not defined"
msgstr "jigsaw не визначено"
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr "оÑтанній коміт:"
@@ -31034,6 +32198,9 @@ msgstr ""
msgid "missing"
msgstr "відÑутні"
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr "оÑтаннє розгортаннÑ"
@@ -31515,9 +32682,6 @@ 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 "швидкі дії"
@@ -31530,9 +32694,6 @@ msgstr "зареєÑтруватиÑÑ"
msgid "relates to"
msgstr "ÑтоÑуєтьÑÑ"
-msgid "released %{time}"
-msgstr "випущено %{time}"
-
msgid "remaining"
msgstr "залишилоÑÑŒ"
@@ -31612,6 +32773,9 @@ msgstr "показати менше"
msgid "sign in"
msgstr "увійти"
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr "Ñортувати:"
@@ -31792,9 +32956,6 @@ msgstr ""
msgid "wiki page"
msgstr "вікі-Ñторінка"
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "з %{additions} додаваннÑми Ñ– %{deletions} видаленнÑми."
@@ -31807,3 +32968,6 @@ msgstr ""
msgid "yaml invalid"
msgstr "yaml недійÑний"
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/ur_PK/gitlab.po b/locale/ur_PK/gitlab.po
index 10b394ca888..f8eacf952c4 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-10-02 18:41\n"
+"PO-Revision-Date: 2020-11-03 22:39\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/uz_UZ/gitlab.po b/locale/uz_UZ/gitlab.po
index 3151fead0de..fa8d9e49323 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-10-02 18:44\n"
+"PO-Revision-Date: 2020-11-03 22:43\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -185,6 +185,11 @@ msgid_plural "%d failed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -215,11 +220,6 @@ 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] ""
@@ -407,6 +407,16 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} more"
msgstr ""
@@ -447,6 +457,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -492,6 +508,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -618,9 +640,6 @@ 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 ""
@@ -718,7 +737,7 @@ msgstr[1] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -734,6 +753,9 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -947,9 +969,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -988,6 +1007,18 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -1016,6 +1047,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -1025,15 +1059,8 @@ 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 "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1296,6 +1323,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1595,6 +1625,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1748,7 +1781,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1784,10 +1817,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1874,6 +1907,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1898,6 +1934,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2012,6 +2051,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2021,6 +2075,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -2033,12 +2093,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2093,6 +2171,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2102,6 +2183,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2147,6 +2231,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2171,6 +2258,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2180,6 +2270,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2195,22 +2288,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2275,10 +2368,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2395,6 +2488,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2404,10 +2506,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2419,19 +2521,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2446,6 +2557,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2455,7 +2572,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2473,7 +2593,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2482,6 +2602,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2548,9 +2689,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2575,6 +2713,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2596,6 +2737,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2617,12 +2761,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2671,6 +2821,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2683,9 +2836,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2713,9 +2872,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2803,9 +2968,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2878,9 +3040,6 @@ 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 ""
@@ -2911,9 +3070,6 @@ 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 ""
@@ -2938,6 +3094,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2962,9 +3121,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2980,6 +3136,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3309,6 +3468,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3557,6 +3719,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3801,7 +3966,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3822,6 +4008,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3840,6 +4029,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3897,9 +4089,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3981,6 +4170,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4065,6 +4260,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4116,12 +4323,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4140,6 +4356,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4152,6 +4371,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4296,6 +4518,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4332,9 +4557,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4365,7 +4602,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4548,6 +4785,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4959,6 +5199,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5142,9 +5385,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5163,9 +5403,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5274,6 +5511,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5298,7 +5538,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5325,6 +5565,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5508,6 +5751,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5565,9 +5811,6 @@ 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 ""
@@ -5823,9 +6066,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5841,9 +6081,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5910,9 +6147,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5979,9 +6213,6 @@ 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 ""
@@ -6048,9 +6279,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6111,6 +6339,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6195,6 +6426,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6336,9 +6570,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6450,9 +6681,6 @@ 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 ""
@@ -6764,7 +6992,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6815,6 +7043,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6882,6 +7113,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7259,6 +7493,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7319,6 +7556,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7328,6 +7568,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7361,6 +7604,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7609,6 +7855,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7702,6 +7951,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7953,6 +8205,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -8010,6 +8265,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8049,6 +8313,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -8070,6 +8340,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -8097,15 +8373,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8121,6 +8397,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8160,6 +8439,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8172,6 +8454,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8181,6 +8469,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8337,9 +8628,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8349,6 +8637,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8364,9 +8655,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8388,6 +8676,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8451,12 +8742,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8505,18 +8802,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8592,9 +8898,6 @@ 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 ""
@@ -8760,6 +9063,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8808,6 +9117,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8979,6 +9291,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -9030,7 +9363,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9179,6 +9512,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9188,6 +9524,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9209,6 +9548,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9236,9 +9578,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9407,15 +9746,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9488,6 +9836,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9629,6 +9980,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9656,7 +10013,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9701,6 +10070,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9728,7 +10100,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10490,12 +10865,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10526,6 +10907,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10601,6 +10985,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10703,6 +11090,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10766,6 +11156,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10778,6 +11171,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10915,6 +11311,18 @@ msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
msgstr[1] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10945,6 +11353,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10996,6 +11407,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -11062,10 +11476,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -11080,6 +11497,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -11098,9 +11518,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11116,15 +11533,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11134,6 +11551,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11191,12 +11611,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11221,6 +11647,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11284,6 +11713,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11317,9 +11749,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11329,9 +11758,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11386,7 +11821,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11932,7 +12367,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11953,6 +12388,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11989,9 +12427,6 @@ 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 ""
@@ -12016,6 +12451,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12328,6 +12769,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12433,7 +12877,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12592,6 +13036,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12601,6 +13051,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12646,12 +13099,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12664,6 +13135,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12676,6 +13150,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12700,6 +13177,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -13109,6 +13589,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13163,9 +13646,6 @@ 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 ""
@@ -13178,7 +13658,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13286,6 +13766,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13310,9 +13793,6 @@ 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 ""
@@ -13334,10 +13814,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13419,6 +13899,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13539,6 +14022,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13599,6 +14088,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13608,12 +14100,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13623,6 +14121,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13635,6 +14157,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13710,27 +14235,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13749,6 +14280,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13778,6 +14312,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13787,12 +14366,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13826,6 +14423,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13841,37 +14441,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13880,6 +14501,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13904,9 +14528,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -14006,25 +14627,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -14072,6 +14693,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14120,6 +14795,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14336,6 +15014,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14591,6 +15272,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14609,6 +15293,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14738,9 +15428,6 @@ 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 ""
@@ -14767,9 +15454,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14803,6 +15487,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14836,6 +15523,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14881,6 +15571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14956,6 +15649,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15495,9 +16191,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15516,6 +16209,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15549,9 +16245,6 @@ 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 ""
@@ -15561,7 +16254,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15573,6 +16266,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15636,6 +16332,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15756,6 +16455,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15783,15 +16488,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -16029,6 +16809,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16432,6 +17215,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16747,9 +17551,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16807,6 +17617,34 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -17062,6 +17900,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17526,6 +18367,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17556,9 +18400,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17793,6 +18634,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17838,9 +18682,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17850,9 +18691,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17972,19 +18810,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18158,6 +18990,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18254,7 +19089,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18278,9 +19113,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18302,7 +19134,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18326,9 +19158,6 @@ 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 ""
@@ -18344,9 +19173,6 @@ 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 ""
@@ -18356,12 +19182,6 @@ 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 ""
@@ -18386,7 +19206,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18578,7 +19398,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18590,9 +19410,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18695,6 +19512,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18776,6 +19596,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18794,6 +19617,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18824,6 +19650,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18860,6 +19689,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -19088,6 +19923,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -19097,6 +19935,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -19109,12 +19950,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19319,9 +20166,6 @@ 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 ""
@@ -20015,7 +20859,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20318,6 +21162,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20372,6 +21219,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20828,6 +21678,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20954,6 +21807,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -21065,6 +21921,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21146,6 +22005,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21190,9 +22052,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21402,6 +22261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21522,6 +22384,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21543,9 +22408,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21573,6 +22444,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21698,7 +22572,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21710,6 +22590,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21728,6 +22620,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21824,7 +22719,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21857,6 +22752,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -22058,6 +22956,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22210,6 +23111,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22237,6 +23144,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22306,6 +23216,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22315,6 +23228,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22330,6 +23249,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22354,9 +23276,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22366,6 +23285,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22405,6 +23327,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22435,7 +23360,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22492,9 +23417,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22576,9 +23498,6 @@ 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] ""
@@ -22643,7 +23562,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22688,10 +23607,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22820,6 +23739,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22883,6 +23805,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22922,6 +23850,11 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -23102,6 +24035,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -23117,7 +24053,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -23132,9 +24068,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23228,6 +24161,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23342,6 +24278,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23477,6 +24416,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23582,6 +24524,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23600,9 +24551,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23745,6 +24702,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23772,6 +24732,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23781,9 +24744,6 @@ 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 ""
@@ -23793,6 +24753,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23904,27 +24867,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24159,6 +25113,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24267,6 +25224,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24309,9 +25269,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24387,9 +25344,6 @@ 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 ""
@@ -24453,6 +25407,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24609,6 +25566,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24738,6 +25698,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24753,6 +25716,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24795,6 +25761,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24879,6 +25851,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24900,6 +25875,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -25035,12 +26013,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -25068,6 +26052,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25302,15 +26289,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25395,7 +26397,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25418,9 +26420,6 @@ 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 ""
@@ -25433,9 +26432,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25532,6 +26537,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25555,7 +26566,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25666,7 +26677,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25726,6 +26737,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25738,7 +26752,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25777,6 +26791,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25885,6 +26902,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -26080,6 +27100,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -26131,7 +27154,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -26155,9 +27178,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26290,6 +27319,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26299,6 +27331,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26851,6 +27886,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26885,7 +27926,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26936,7 +27977,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -27065,6 +28106,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -27137,16 +28181,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27323,6 +28370,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27473,6 +28523,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27698,6 +28751,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27836,10 +28892,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27866,6 +28925,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27878,9 +28940,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27902,15 +28991,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27965,10 +29066,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -28088,6 +29186,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28184,9 +29285,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28340,6 +29438,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28647,7 +29751,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28731,6 +29841,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28827,6 +29946,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28851,13 +29973,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28926,15 +30051,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28947,7 +30072,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29189,10 +30314,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29285,6 +30410,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29306,6 +30434,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29318,10 +30449,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29336,6 +30467,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29537,6 +30677,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29549,6 +30692,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29573,9 +30725,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29633,9 +30782,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29738,19 +30884,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29780,6 +30929,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29795,6 +30947,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -30061,9 +31216,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30190,9 +31342,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30238,9 +31387,6 @@ 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 ""
@@ -30324,6 +31470,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30562,7 +31711,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30580,6 +31729,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30598,6 +31750,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30634,6 +31789,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30696,6 +31854,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -31169,9 +32330,6 @@ 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 ""
@@ -31184,9 +32342,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31264,6 +32419,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31444,9 +32602,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31459,3 +32614,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/vi_VN/gitlab.po b/locale/vi_VN/gitlab.po
index e14d5f906df..1cb42453f2e 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-10-02 18:41\n"
+"PO-Revision-Date: 2020-11-03 22:39\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -162,6 +162,10 @@ msgid "%d failed"
msgid_plural "%d failed"
msgstr[0] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -186,10 +190,6 @@ msgid "%d issue in this group"
msgid_plural "%d issues in this group"
msgstr[0] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] ""
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -351,6 +351,14 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+
msgid "%{count} more"
msgstr ""
@@ -389,6 +397,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -434,6 +448,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -560,9 +580,6 @@ 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 ""
@@ -655,7 +672,7 @@ msgstr[0] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -669,6 +686,9 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
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] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -876,9 +896,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -916,6 +933,18 @@ msgstr[0] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -942,6 +971,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -951,13 +983,8 @@ msgstr ""
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] ""
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1205,6 +1232,9 @@ msgstr ""
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1503,6 +1533,9 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1656,7 +1689,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1692,10 +1725,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1782,6 +1815,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1806,6 +1842,9 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1920,6 +1959,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -1929,6 +1983,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr ""
@@ -1941,12 +2001,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -2001,6 +2079,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2010,6 +2091,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2055,6 +2139,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
@@ -2079,6 +2166,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2088,6 +2178,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2103,22 +2196,22 @@ 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."
+msgid "After sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2182,10 +2275,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2302,6 +2395,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2311,10 +2413,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2326,19 +2428,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2353,6 +2464,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2362,7 +2479,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2380,7 +2500,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2389,6 +2509,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2455,9 +2596,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr ""
-
msgid "All users must have a name."
msgstr ""
@@ -2482,6 +2620,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -2503,6 +2644,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2524,12 +2668,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -2578,6 +2728,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2590,9 +2743,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2620,9 +2779,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr ""
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -2710,9 +2875,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2785,9 +2947,6 @@ 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 ""
@@ -2818,9 +2977,6 @@ 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 ""
@@ -2845,6 +3001,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2869,9 +3028,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -2887,6 +3043,9 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3212,6 +3371,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3459,6 +3621,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3701,7 +3866,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3722,6 +3908,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3740,6 +3929,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3797,9 +3989,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3881,6 +4070,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -3965,6 +4160,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4016,12 +4223,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4040,6 +4256,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4052,6 +4271,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4196,6 +4418,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4232,9 +4457,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4265,7 +4502,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4448,6 +4685,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4859,6 +5099,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5042,9 +5285,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5063,9 +5303,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5174,6 +5411,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5198,7 +5438,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5225,6 +5465,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5408,6 +5651,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5465,9 +5711,6 @@ 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 ""
@@ -5723,9 +5966,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5741,9 +5981,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5810,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5879,9 +6113,6 @@ 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 ""
@@ -5948,9 +6179,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6011,6 +6239,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6095,6 +6326,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6236,9 +6470,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6350,9 +6581,6 @@ 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 ""
@@ -6663,7 +6891,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6714,6 +6942,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6779,6 +7010,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7155,6 +7389,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7215,6 +7452,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7224,6 +7464,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7257,6 +7500,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7504,6 +7750,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7597,6 +7846,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7847,6 +8099,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -7904,6 +8159,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -7943,6 +8207,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -7964,6 +8234,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -7991,15 +8267,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8015,6 +8291,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8054,6 +8333,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8066,6 +8348,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8075,6 +8363,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8231,9 +8522,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8243,6 +8531,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8258,9 +8549,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8282,6 +8570,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8345,12 +8636,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8396,18 +8693,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8480,9 +8786,6 @@ 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 ""
@@ -8648,6 +8951,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8696,6 +9005,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8867,6 +9179,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -8918,7 +9251,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9066,6 +9399,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9075,6 +9411,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9096,6 +9435,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9123,9 +9465,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9294,15 +9633,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9375,6 +9723,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9516,6 +9867,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9543,7 +9900,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9588,6 +9957,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9615,7 +9987,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10377,12 +10752,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10413,6 +10794,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10488,6 +10872,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10590,6 +10977,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10653,6 +11043,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10665,6 +11058,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10801,6 +11197,18 @@ msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10831,6 +11239,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10882,6 +11293,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -10948,10 +11362,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -10966,6 +11383,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -10984,9 +11404,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11002,15 +11419,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11020,6 +11437,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -11077,12 +11497,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11107,6 +11533,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11170,6 +11599,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11203,9 +11635,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11215,9 +11644,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11272,7 +11707,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11818,7 +12253,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11839,6 +12274,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11875,9 +12313,6 @@ 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 ""
@@ -11902,6 +12337,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12214,6 +12655,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12319,7 +12763,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12478,6 +12922,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12487,6 +12937,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12532,12 +12985,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12550,6 +13021,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12562,6 +13036,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12586,6 +13063,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -12993,6 +13473,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13047,9 +13530,6 @@ 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 ""
@@ -13062,7 +13542,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13170,6 +13650,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13194,9 +13677,6 @@ 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 ""
@@ -13218,10 +13698,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13301,6 +13781,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13421,6 +13904,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13481,6 +13970,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13490,12 +13982,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13505,6 +14003,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13517,6 +14039,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13592,27 +14117,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13631,6 +14162,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13659,6 +14193,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13668,12 +14247,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13707,6 +14304,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13722,37 +14322,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13761,6 +14382,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13785,9 +14409,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -13887,25 +14508,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -13953,6 +14574,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14001,6 +14676,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14217,6 +14895,9 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14472,6 +15153,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14490,6 +15174,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14619,9 +15309,6 @@ 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 ""
@@ -14647,9 +15334,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14683,6 +15367,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14716,6 +15403,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14761,6 +15451,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14836,6 +15529,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15368,9 +16064,6 @@ msgstr ""
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15389,6 +16082,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15422,9 +16118,6 @@ 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 ""
@@ -15434,7 +16127,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15446,6 +16139,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15509,6 +16205,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15629,6 +16328,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15656,15 +16361,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -15902,6 +16682,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16303,6 +17086,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16618,9 +17422,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16678,6 +17488,32 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -16933,6 +17769,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17396,6 +18235,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17426,9 +18268,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17663,6 +18502,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17708,9 +18550,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17720,9 +18559,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17841,19 +18677,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18027,6 +18857,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18123,7 +18956,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18147,9 +18980,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18171,7 +19001,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18195,9 +19025,6 @@ 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 ""
@@ -18213,9 +19040,6 @@ 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 ""
@@ -18225,12 +19049,6 @@ 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 ""
@@ -18255,7 +19073,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18447,7 +19265,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18459,9 +19277,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18564,6 +19379,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18645,6 +19463,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18663,6 +19484,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18693,6 +19517,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18729,6 +19556,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -18957,6 +19790,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -18966,6 +19802,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -18978,12 +19817,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19188,9 +20033,6 @@ 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 ""
@@ -19884,7 +20726,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20187,6 +21029,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20241,6 +21086,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20697,6 +21545,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20823,6 +21674,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -20934,6 +21788,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21015,6 +21872,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21058,9 +21918,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21269,6 +22126,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21389,6 +22249,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21410,9 +22273,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21440,6 +22309,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21564,7 +22436,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21576,6 +22454,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21594,6 +22484,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21690,7 +22583,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21723,6 +22616,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -21921,6 +22817,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22072,6 +22971,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22099,6 +23004,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22168,6 +23076,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22177,6 +23088,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22192,6 +23109,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22216,9 +23136,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22228,6 +23145,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22267,6 +23187,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22297,7 +23220,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22354,9 +23277,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22438,9 +23358,6 @@ 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] ""
@@ -22494,7 +23411,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22539,10 +23456,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22671,6 +23588,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22734,6 +23654,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22773,6 +23699,10 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -22953,6 +23883,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -22968,7 +23901,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -22983,9 +23916,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23079,6 +24009,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23193,6 +24126,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23328,6 +24264,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23433,6 +24372,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23451,9 +24399,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23594,6 +24548,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23621,6 +24578,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23630,9 +24590,6 @@ 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 ""
@@ -23642,6 +24599,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23753,27 +24713,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24008,6 +24959,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24116,6 +25070,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24158,9 +25115,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24236,9 +25190,6 @@ 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 ""
@@ -24302,6 +25253,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24458,6 +25412,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24587,6 +25544,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24602,6 +25562,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24644,6 +25607,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24728,6 +25697,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24749,6 +25721,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -24884,12 +25859,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -24917,6 +25898,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25148,15 +26132,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25241,7 +26240,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25263,9 +26262,6 @@ 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 ""
@@ -25278,9 +26274,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25377,6 +26379,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25399,7 +26407,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25510,7 +26518,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25570,6 +26578,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25582,7 +26593,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25621,6 +26632,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25729,6 +26743,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -25924,6 +26941,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -25975,7 +26995,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -25999,9 +27019,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26134,6 +27160,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26143,6 +27172,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26695,6 +27727,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26727,7 +27765,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26778,7 +27816,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -26907,6 +27945,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -26979,16 +28020,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27165,6 +28209,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27315,6 +28362,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27540,6 +28590,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27678,10 +28731,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27708,6 +28764,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27720,9 +28779,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27744,15 +28830,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27807,10 +28905,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -27930,6 +29025,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28026,9 +29124,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28182,6 +29277,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28487,7 +29588,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28571,6 +29678,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28667,6 +29783,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28691,13 +29810,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28766,15 +29888,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28787,7 +29909,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29028,10 +30150,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29124,6 +30246,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29145,6 +30270,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29157,10 +30285,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29175,6 +30303,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29376,6 +30513,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29388,6 +30528,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29412,9 +30561,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29472,9 +30618,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29577,19 +30720,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29619,6 +30765,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29634,6 +30783,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -29899,9 +31051,6 @@ msgstr ""
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30028,9 +31177,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30076,9 +31222,6 @@ 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 ""
@@ -30161,6 +31304,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30394,7 +31540,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30412,6 +31558,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30430,6 +31579,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30466,6 +31618,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30527,6 +31682,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -30996,9 +32154,6 @@ 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 ""
@@ -31011,9 +32166,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31090,6 +32242,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31270,9 +32425,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31285,3 +32437,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index a4d271e26d3..2bf77761c20 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-10-02 18:43\n"
+"PO-Revision-Date: 2020-11-03 22:42\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -162,6 +162,10 @@ msgid "%d failed"
msgid_plural "%d failed"
msgstr[0] "%d个失败"
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d个修å¤çš„测试结果"
@@ -186,10 +190,6 @@ msgid "%d issue in this group"
msgid_plural "%d issues in this group"
msgstr[0] "此群组中的%d个议题"
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "已选择%d个议题"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] "使用标记æˆåŠŸå¯¼å…¥%d个议题"
@@ -351,6 +351,14 @@ msgstr "æ¥è‡ª%{name}çš„%{count}个核准"
msgid "%{count} files touched"
msgstr "已选择 %{count} 个文件"
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+
msgid "%{count} more"
msgstr "其余%{count}项"
@@ -389,6 +397,12 @@ 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 "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -434,6 +448,12 @@ msgstr "%{group_name}使用由群组托管å¸æˆ·ã€‚您需è¦åˆ›å»ºä¸€ä¸ªæ–°çš„Gi
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr "%{host} 从新ä½ç½®ç™»å½•"
@@ -560,9 +580,6 @@ msgstr "%{name_with_link}当å‰å‰©ä½™%{percent}或更少的共享Runneræµæ°´çº¿
msgid "%{name_with_link} has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
msgstr "%{name_with_link}的共享Runneræµæ°´çº¿åˆ†é’Ÿæ•°å·²ç”¨å®Œï¼Œå…¶ä¸‹é¡¹ç›®å°†æ— æ³•è¿è¡Œæ–°çš„作业或æµæ°´çº¿ã€‚"
-msgid "%{namespace_name} is now read-only. You cannot: %{base_message}"
-msgstr "%{namespace_name}ç›®å‰ä¸ºåªè¯»çŠ¶æ€ã€‚您ä¸èƒ½è¿›è¡Œä»¥ä¸‹æ“作:%{base_message}"
-
msgid "%{name} contained %{resultsString}"
msgstr "%{name} åŒ…å« %{resultsString}"
@@ -655,8 +672,8 @@ msgstr[0] "%{reportType}%{status}检测到%{other}个安全æ¼æ´ž."
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr "%{reportType}%{status}未å‘现安全æ¼æ´ž."
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
-msgstr "%{retryButtonStart}é‡è¯•%{retryButtonEnd}或%{newFileButtonStart}添加一个新文件%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
+msgstr ""
msgid "%{seconds}s"
msgstr ""
@@ -669,6 +686,9 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
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] "%{securityScanner}无结果,因为自å¯ç”¨ä»¥æ¥å°šæœªè¿è¡Œæµæ°´çº¿ã€‚%{linkStart}è¿è¡Œæµæ°´çº¿%{linkEnd}"
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -876,9 +896,6 @@ msgstr "(检查进度)"
msgid "(deleted)"
msgstr "(已删除)"
-msgid "(external source)"
-msgstr "(外部资æº)"
-
msgid "(line: %{startLine})"
msgstr "(行: %{startLine})"
@@ -916,6 +933,18 @@ msgstr[0] "+其余%d项"
msgid "+%{approvers} more approvers"
msgstr "+å¦å¤–%{approvers}个核准人"
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr "+其余%{tags}个"
@@ -942,6 +971,9 @@ msgstr "- 于总计 - æƒé‡å·²å®Œæˆ"
msgid "- show less"
msgstr "- 显示较少"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr "0 字节"
@@ -951,13 +983,8 @@ msgstr "0 表示无é™åˆ¶"
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr "0表示无é™åˆ¶ï¼Œä»…在å¯ç”¨è¿œç¨‹å­˜å‚¨æ—¶æœ‰æ•ˆã€‚"
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "%{count} 个 %{type} 的添加"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "%{count} 个 %{type} 的修改"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1205,6 +1232,9 @@ msgstr "具有对æºåˆ†æ”¯çš„写入æƒé™çš„用户选择了此选项"
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr "需è¦å¤„ç†ï¼š 获å–GitLab Pages域%{domain}çš„Let's Encrypt加密è¯ä¹¦æ—¶å‡ºäº†é”™ã€‚"
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr "API帮助"
@@ -1503,6 +1533,9 @@ msgstr "添加表格"
msgid "Add a task list"
msgstr "添加任务列表"
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "添加包å«åœ¨æ‰€æœ‰ç”µå­é‚®ä»¶ä¸­çš„附加文本。 长度ä¸è¶…过%{character_limit} 字符"
@@ -1656,8 +1689,8 @@ msgstr "已添加 %{epic_ref} 为å­å²è¯—。"
msgid "Added %{label_references} %{label_text}."
msgstr "已添加 %{label_references} %{label_text}。"
-msgid "Added a To Do."
-msgstr "已添加一个待办事项。"
+msgid "Added a to do."
+msgstr ""
msgid "Added an issue to an epic."
msgstr "为å²è¯—添加了一个议题。"
@@ -1692,17 +1725,17 @@ msgstr "添加%{epic_ref}作为å­å²è¯—。"
msgid "Adds %{labels} %{label_text}."
msgstr "添加%{labels}%{label_text}。"
-msgid "Adds a To Do."
-msgstr "添加一个待办事项."
-
msgid "Adds a Zoom meeting"
msgstr "添加一个Zoom会议"
+msgid "Adds a to do."
+msgstr ""
+
msgid "Adds an issue to an epic."
msgstr "将议题添加到å²è¯—。"
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
-msgstr "请您调整上é¢çš„过滤器/æœç´¢æ¡ä»¶ã€‚如果您认为此处有误,请å‚阅 %{linkStart}Geo故障排除%{linkEnd}文档以获å–更多信æ¯ã€‚"
+msgstr "请您调整上é¢çš„筛选器/æœç´¢æ¡ä»¶ã€‚如果您认为此处有误,请å‚阅 %{linkStart}Geo故障排除%{linkEnd}文档以获å–更多信æ¯ã€‚"
msgid "Admin Area"
msgstr "管ç†ä¸­å¿ƒ"
@@ -1782,6 +1815,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr "所有者"
@@ -1806,6 +1842,9 @@ msgstr "åœæ­¢ä½œä¸šå¤±è´¥"
msgid "AdminArea|Total users"
msgstr "所有用户"
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "用户统计"
@@ -1920,6 +1959,21 @@ msgstr "SSH密钥"
msgid "AdminStatistics|Snippets"
msgstr "代ç ç‰‡æ®µ"
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr "未å¯ç”¨åŒé‡è®¤è¯"
@@ -1929,6 +1983,12 @@ msgstr "å¯ç”¨åŒé‡è®¤è¯"
msgid "AdminUsers|Access"
msgstr "访问类型"
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr "活跃"
@@ -1941,12 +2001,30 @@ msgstr "管ç†å‘˜å¯ä»¥è®¿é—®æ‰€æœ‰ç¾¤ç»„ã€é¡¹ç›®å’Œç”¨æˆ·ï¼Œå¹¶å¯ä»¥ç®¡ç†æ­¤
msgid "AdminUsers|Admins"
msgstr "管ç†å‘˜"
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr "自动标记为默认内部用户"
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr "ç¦ç”¨"
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "ç¦ç”¨ç”¨æˆ·"
@@ -2001,6 +2079,9 @@ msgstr "正在使用许å¯å¸­ä½"
msgid "AdminUsers|It's you!"
msgstr "自己ï¼"
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr "新用户"
@@ -2010,6 +2091,9 @@ msgstr "未找到用户"
msgid "AdminUsers|Owned groups will be left"
msgstr "拥有的群组将被ä¿ç•™"
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr "个人项目将被ä¿ç•™"
@@ -2055,6 +2139,9 @@ msgstr "此用户无法使用斜线(/)命令"
msgid "AdminUsers|The user will not receive any notifications"
msgstr "此用户将ä¸ä¼šæ”¶åˆ°ä»»ä½•é€šçŸ¥"
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "请输入 %{projectName} æ¥ç¡®è®¤"
@@ -2079,6 +2166,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr "您ä¸èƒ½åˆ é™¤æ‚¨è‡ªå·±çš„管ç†å‘˜æƒé™ã€‚"
@@ -2088,6 +2178,9 @@ msgstr ""
msgid "Administration"
msgstr "管ç†"
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr "高级"
@@ -2103,23 +2196,23 @@ msgstr "高级设置"
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "高级æƒé™ï¼Œå¤§æ–‡ä»¶å­˜å‚¨(LFS)å’ŒåŒé‡è®¤è¯è®¾ç½®ã€‚"
-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 sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
-msgstr "之åŽï¼Œæ‚¨å°†æ— æ³•ä½¿ç”¨åˆå¹¶æ‰¹å‡†æˆ–å²è¯—以åŠä¼—多的其他功能。"
+msgid "After that, you will not be able to use merge approvals or epics as well as many 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 "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgstr ""
msgid "Alert"
msgid_plural "Alerts"
@@ -2182,12 +2275,12 @@ msgstr "事件"
msgid "AlertManagement|High"
msgstr "高"
+msgid "AlertManagement|Incident"
+msgstr ""
+
msgid "AlertManagement|Info"
msgstr "ä¿¡æ¯"
-msgid "AlertManagement|Issue"
-msgstr "议题"
-
msgid "AlertManagement|Key"
msgstr ""
@@ -2302,6 +2395,15 @@ 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 "您必须æ供此URL和授æƒå¯†é’¥æ‰èƒ½æŽˆæƒå¤–部æœåŠ¡å°†è­¦æŠ¥å‘é€åˆ°GitLab。您å¯ä»¥æ供此URL和多个æœåŠ¡çš„密钥。é…置外部æœåŠ¡åŽï¼Œæ¥è‡ªæ‚¨æœåŠ¡çš„警报将显示在GitLab%{linkStart}警报%{linkEnd}页é¢ä¸Šã€‚"
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr "API网å€"
@@ -2311,12 +2413,12 @@ msgstr "å¯ç”¨"
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr "å°†URLå’Œauth密钥添加到Prometheusé…置文件中"
+msgid "AlertSettings|Add new integrations"
+msgstr ""
+
msgid "AlertSettings|Alert test payload"
msgstr "警报测试数æ®"
-msgid "AlertSettings|Alerts endpoint successfully activated."
-msgstr "警报端点已æˆåŠŸæ¿€æ´»ã€‚"
-
msgid "AlertSettings|Authorization key"
msgstr "授æƒå¯†é’¥"
@@ -2326,20 +2428,29 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr "å¤åˆ¶"
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr "输入测试警告JSON ..."
msgid "AlertSettings|External Prometheus"
msgstr "外部Prometheus"
-msgid "AlertSettings|Generic"
-msgstr "常规"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
-msgid "AlertSettings|Integrations"
-msgstr "集æˆ"
+msgid "AlertSettings|Integration"
+msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
-msgstr "了解更多关于%{linkStart}å³å°†åˆ°æ¥çš„集æˆ%{linkEnd}"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
msgid "AlertSettings|Opsgenie"
msgstr "Opsgenie"
@@ -2353,6 +2464,12 @@ 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 "查看外部æœåŠ¡çš„文档以了解将此信æ¯æ供给外部æœåŠ¡çš„ä½ç½®ï¼Œä»¥åŠ%{linkStart}GitLab文档%{linkEnd}æ¥äº†è§£æœ‰å…³é…置端点的更多信æ¯ã€‚"
+msgid "AlertSettings|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr "测试警报数æ®"
@@ -2362,8 +2479,11 @@ 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|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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 "å°è¯•é‡ç½®å¯†é’¥æ—¶å‡ºé”™ã€‚请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
@@ -2380,8 +2500,8 @@ 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 "您必须æ供此URL和授æƒå¯†é’¥æ‰èƒ½æŽˆæƒå¤–部æœåŠ¡å°†è­¦æŠ¥å‘é€åˆ°GitLab。您å¯ä»¥æ供此URL和多个æœåŠ¡çš„密钥。é…置外部æœåŠ¡åŽï¼Œæ¥è‡ªæ‚¨æœåŠ¡çš„警报将显示在GitLab%{linkStart}警报%{linkEnd}页é¢ä¸Šã€‚"
-msgid "AlertSettings|Your changes were successfully updated."
-msgstr "您的更改已æˆåŠŸæ›´æ–°ã€‚"
+msgid "AlertSettings|Your integration was successfully updated."
+msgstr ""
msgid "Alerts"
msgstr "警报"
@@ -2389,6 +2509,27 @@ msgstr "警报"
msgid "Alerts endpoint"
msgstr "警报端点"
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr "算法"
@@ -2455,9 +2596,6 @@ msgstr "所有安全扫æ都已å¯ç”¨ï¼Œå› ä¸ºæ­¤é¡¹ç›®å·²å¼€å¯äº†%{linkStart}
msgid "All threads resolved"
msgstr "所有主题已解决"
-msgid "All users"
-msgstr "所有用户"
-
msgid "All users must have a name."
msgstr "所有的用户都必须具有å称。"
@@ -2482,6 +2620,9 @@ msgstr "å…许所有者管ç†åœ¨ç¾¤ç»„级别默认分支ä¿æŠ¤"
msgid "Allow owners to manually add users outside of LDAP"
msgstr "å…许负责人手动添加LDAP之外的用户"
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "å…许该群组中的项目使用Git LFS"
@@ -2503,6 +2644,9 @@ msgstr "å…许系统钩å­å‘本地网络å‘é€çš„请求"
msgid "Allow requests to the local network from web hooks and services"
msgstr "å…许Webhookå’ŒæœåŠ¡å¯¹æœ¬åœ°ç½‘络的请求"
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr "åŒæ—¶å…许此秘钥推é€æ–‡ä»¶åˆ°ä»“库å—?(默认åªæ‹¥æœ‰æ‹‰å–æƒé™)"
@@ -2524,12 +2668,18 @@ msgstr "å·²å…许"
msgid "Allowed Geo IP"
msgstr "å…许的Geo IP"
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "å…许使用电å­é‚®ä»¶åŸŸåé™åˆ¶ä»…å¯ç”¨äºŽé¡¶çº§ç¾¤ç»„"
msgid "Allowed to fail"
msgstr "å…许失败"
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "这里å¯ä»¥æ·»åŠ å’Œç®¡ç† Kubernetes 集群。"
@@ -2578,6 +2728,9 @@ msgstr "具有相åŒæŒ‡çº¹çš„%{link_start}警报%{link_end}已打开。è¦æ›´æ”¹
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr "在%{project_path}中触å‘了一个警报。"
@@ -2590,9 +2743,15 @@ msgstr "已从管ç†é¢æ¿å‘é€è¿‡äº†ä¸€å°ç”µå­é‚®ä»¶é€šçŸ¥ã€‚请等待 %{wai
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "空GitLab用户字段将在所有问题和注释的æ述中添加FogBugz用户的全å(例如“By John Smithâ€ï¼‰ã€‚它还将与项目创建者关è”å’Œ/或分é…这些问题和评论。"
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "å‘生错误"
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2620,9 +2779,15 @@ msgstr "获å–项目作者时出错。"
msgid "An error occurred previewing the blob"
msgstr "预览 blob 时出错"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "切æ¢é€šçŸ¥è®¢é˜…æ—¶å‘生错误"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "更新议题æƒé‡æ—¶å‘生错误"
@@ -2710,9 +2875,6 @@ msgstr "获å–terraform报告时å‘生错误。"
msgid "An error occurred while fetching the Service Desk address."
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 "读å–看æ¿åˆ—表时出错。请å†è¯•ä¸€æ¬¡ã€‚"
@@ -2785,9 +2947,6 @@ 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 "加载项目创建界é¢æ—¶å‘生错误"
@@ -2818,9 +2977,6 @@ 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 "å‘é€è¯·æ±‚æ—¶å‘生错误。"
@@ -2845,6 +3001,9 @@ msgstr "渲染广播消æ¯æ—¶å‘生错误"
msgid "An error occurred while rendering the editor"
msgstr "在渲染编辑器时出错"
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr "é‡æ–°æŽ’åºè®®é¢˜æ—¶å‘生错误。"
@@ -2869,9 +3028,6 @@ msgstr "ä¿å­˜LDAP覆盖状æ€æ—¶å‘生错误。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "An error occurred while saving assignees"
msgstr "ä¿å­˜è¢«æŒ‡æ´¾äººæ—¶å‡ºçŽ°é”™è¯¯ã€‚"
-msgid "An error occurred while searching for milestones"
-msgstr "æœç´¢é‡Œç¨‹ç¢‘时出错"
-
msgid "An error occurred while subscribing to notifications."
msgstr "订阅通知时å‘生错误。"
@@ -2887,6 +3043,9 @@ msgstr "å–消订阅通知时å‘生错误。"
msgid "An error occurred while updating approvers"
msgstr "更新核准人时å‘生错误"
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -2921,7 +3080,7 @@ 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 "议题å¯ä»¥æ˜¯éœ€è¦åœ¨é¡¹ç›®ä¸­è®¨è®ºçš„缺陷,待办事项或功能请求。此外,议题是å¯æœç´¢å’Œå¯è¿‡æ»¤çš„。"
+msgstr "议题å¯ä»¥æ˜¯éœ€è¦åœ¨é¡¹ç›®ä¸­è®¨è®ºçš„缺陷,待办事项或功能请求。此外,议题是å¯æœç´¢å’Œå¯ç­›é€‰çš„。"
msgid "An unauthenticated user"
msgstr "未ç»è®¤è¯çš„用户"
@@ -3212,6 +3371,9 @@ msgstr "归档作业"
msgid "Archive project"
msgstr "归档项目"
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr "已存档"
@@ -3459,6 +3621,9 @@ msgstr "分é…ç»™%{assigneeName}"
msgid "Assigned to %{assignee_name}"
msgstr "分é…ç»™%{assignee_name}"
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr "已分派给我"
@@ -3701,8 +3866,29 @@ msgstr "将根æ®é¢„定义的 CI/CD é…置自动构建ã€æµ‹è¯•å’Œéƒ¨ç½²åº”用ç¨
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "想了解更多请访问 %{link_to_documentation}"
-msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "Auto DevOpsæµæ°´çº¿å·²å¯ç”¨ã€‚如果未找到CIé…置文件,将使用该æµæ°´çº¿ã€‚ %{more_information_link}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
msgid "Autocomplete"
msgstr "自动补全"
@@ -3722,6 +3908,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 "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3740,6 +3929,9 @@ msgstr "注æ„"
msgid "Available"
msgstr "å¯ç”¨çš„"
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr "å¯ç”¨çš„Runner: %{runners}"
@@ -3797,9 +3989,6 @@ msgstr "徽章图片网å€"
msgid "Badges|Badge image preview"
msgstr "徽章图片预览"
-msgid "Badges|Delete badge"
-msgstr "删除徽章"
-
msgid "Badges|Delete badge?"
msgstr "删除徽章�"
@@ -3881,6 +4070,12 @@ msgstr "Bamboo 根地å€ï¼Œä¾‹å¦‚:https://bambo.example.com"
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr "您必须在Bamboo中设置自动版本标签和仓库触å‘器。"
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "请注æ„,更改项目的命å空间å¯èƒ½ä¼šäº§ç”Ÿéžé¢„期的副作用。"
@@ -3965,6 +4160,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "å‡çº§"
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr "BitbucketæœåŠ¡å™¨å¯¼å…¥"
@@ -4016,12 +4223,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4040,6 +4256,9 @@ msgstr "展开"
msgid "Boards|View scope"
msgstr "查看范围"
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4052,6 +4271,9 @@ msgstr "未在此项目的仓库中找到 %{branchName} 分支。"
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4196,6 +4418,9 @@ msgstr "项目设置"
msgid "Branches|protected"
msgstr "å—ä¿æŠ¤"
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr "广播消æ¯å·²æˆåŠŸåˆ›å»ºã€‚"
@@ -4232,9 +4457,21 @@ msgstr "内置"
msgid "Bulk request concurrency"
msgstr "并å‘批é‡è¯·æ±‚"
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr "燃尽图"
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr "未解决议题æƒé‡"
@@ -4265,8 +4502,8 @@ msgstr "ç”± %{user_name}"
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 "通过å•å‡»æ³¨å†Œï¼Œæˆ‘åŒæ„我已阅读并接å—GitLab%{linkStart}的使用æ¡æ¬¾å’Œéšç§æ”¿ç­–%{linkEnd}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
+msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "默认情况下,GitLab 以 HTML 和纯文本格å¼å‘é€ç”µå­é‚®ä»¶ï¼Œå› æ­¤é‚®ä»¶å®¢æˆ·ç«¯å¯ä»¥é€‰æ‹©ä½¿ç”¨å“ªç§æ ¼å¼ã€‚如果您åªæƒ³ä»¥çº¯æ–‡æœ¬æ ¼å¼å‘é€ç”µå­é‚®ä»¶ï¼Œè¯·ç¦ç”¨æ­¤é€‰é¡¹ã€‚"
@@ -4448,6 +4685,9 @@ msgstr "无法创建滥用报告。此用户已被ç¦ç”¨ã€‚"
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr "ä¸èƒ½åŒæ—¶è¿è¡Œå¤šä¸ªJira导入"
@@ -4859,6 +5099,9 @@ msgstr "å­å²è¯—ä¸å­˜åœ¨ã€‚"
msgid "Child epic doesn't exist."
msgstr "å­å²è¯—ä¸å­˜åœ¨ã€‚"
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr "选择%{strong_open}创建归档%{strong_close}并等待创建过程完æˆã€‚"
@@ -5042,9 +5285,6 @@ msgstr "所有环境"
msgid "CiVariable|Create wildcard"
msgstr "创建通é…符"
-msgid "CiVariable|Error occurred while saving variables"
-msgstr "ä¿å­˜å˜é‡æ—¶å‡ºé”™"
-
msgid "CiVariable|Masked"
msgstr "å·²éšè—"
@@ -5063,9 +5303,6 @@ msgstr "切æ¢éšè—"
msgid "CiVariable|Toggle protected"
msgstr "开关ä¿æŠ¤çŠ¶æ€"
-msgid "CiVariable|Validation failed"
-msgstr "验è¯å¤±è´¥"
-
msgid "Classification Label (optional)"
msgstr "分类标签(å¯é€‰)"
@@ -5085,7 +5322,7 @@ msgid "Clear all repository checks"
msgstr ""
msgid "Clear chart filters"
-msgstr "清除图表过滤器"
+msgstr "清除图表筛选器"
msgid "Clear due date"
msgstr "清除截止日期"
@@ -5174,6 +5411,9 @@ msgstr "关闭%{tabname}"
msgid "Close epic"
msgstr "关闭å²è¯—"
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr "关闭里程碑"
@@ -5198,8 +5438,8 @@ msgstr "已关闭议题"
msgid "Closed this %{quick_action_target}."
msgstr "已关闭此%{quick_action_target}."
-msgid "Closed: %{closedIssuesCount}"
-msgstr "关闭:%{closedIssuesCount}"
+msgid "Closed: %{closed}"
+msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "关闭此%{quick_action_target}."
@@ -5225,6 +5465,9 @@ msgstr "集群级别"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr "Stages::ClusterEndpointInserter需è¦é›†ç¾¤ç±»åž‹"
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5408,6 +5651,9 @@ msgstr "清除集群缓存"
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr "集群管ç†é¡¹ç›®(alpha)"
@@ -5465,9 +5711,6 @@ msgstr "无法加载实例类型"
msgid "ClusterIntegration|Could not load networks"
msgstr "无法加载网络"
-msgid "ClusterIntegration|Could not load regions from your AWS account"
-msgstr "无法从您的AWS账户加载区域"
-
msgid "ClusterIntegration|Could not load security groups for the selected VPC"
msgstr "无法加载选定VPC的安全组"
@@ -5723,9 +5966,6 @@ msgstr "进一步了解 %{help_link_start_machine_type}实例类型%{help_link_e
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "进一步了解 %{help_link_start}地域%{help_link_end}。"
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr "了解更多的Kubernetesä¿¡æ¯"
@@ -5741,9 +5981,6 @@ msgstr "加载IAM角色"
msgid "ClusterIntegration|Loading Key Pairs"
msgstr "加载密钥对"
-msgid "ClusterIntegration|Loading Regions"
-msgstr "加载区域"
-
msgid "ClusterIntegration|Loading VPCs"
msgstr "加载VPC"
@@ -5810,9 +6047,6 @@ msgstr "未找到项目"
msgid "ClusterIntegration|No projects matched your search"
msgstr "未找到您æœç´¢çš„项目"
-msgid "ClusterIntegration|No region found"
-msgstr "未找到区域"
-
msgid "ClusterIntegration|No security group found"
msgstr "没有找到安全组"
@@ -5879,9 +6113,6 @@ msgstr "请查阅关于Kubernetes集群集æˆçš„%{link_start}帮助页é¢%{link_
msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
msgstr "实时Web应用程åºç›‘视,日志记录和访问控制。 %{linkStart}更多信æ¯%{linkEnd}"
-msgid "ClusterIntegration|Region"
-msgstr "区域"
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "删除Kubernetes集群集æˆ"
@@ -5948,9 +6179,6 @@ msgstr "æœç´¢ç½‘络"
msgid "ClusterIntegration|Search projects"
msgstr "æœç´¢é¡¹ç›®"
-msgid "ClusterIntegration|Search regions"
-msgstr "æœç´¢åŒºåŸŸ"
-
msgid "ClusterIntegration|Search security groups"
msgstr "æœç´¢å®‰å…¨ç»„"
@@ -6011,6 +6239,9 @@ msgstr "按项目选择地域"
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr "选择地域"
@@ -6095,6 +6326,9 @@ msgstr "节点正在分é…中。如果花费时间过长,请检查您的Kubern
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr "与当å‰é¡¹ç›®ç›¸å…³è”的命å空间。用于部署看æ¿ã€pod日志和Web terminal。"
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr "群集身份验è¯æ—¶å‡ºçŽ°é—®é¢˜ã€‚请确ä¿æ‚¨çš„CAè¯ä¹¦å’Œä»¤ç‰Œæœ‰æ•ˆã€‚"
@@ -6236,9 +6470,6 @@ msgstr "选择VPC"
msgid "ClusterIntergation|Select a network"
msgstr "选择网络"
-msgid "ClusterIntergation|Select a region"
-msgstr "选择区域"
-
msgid "ClusterIntergation|Select a security group"
msgstr "选择一个安全组"
@@ -6285,7 +6516,7 @@ 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 "代ç è¯„审分æžæ˜¾ç¤ºäº†ä¸€ä¸ªå¤„于代ç è¯„审阶段的开放åˆå¹¶è¯·æ±‚列表。 当å‰æ²¡æœ‰æ­¤é¡¹ç›®å’Œ/或过滤器的åˆå¹¶è¯·æ±‚。"
+msgstr "代ç è¯„审分æžæ˜¾ç¤ºäº†ä¸€ä¸ªå¤„于代ç è¯„审阶段的开放åˆå¹¶è¯·æ±‚列表。 当å‰æ²¡æœ‰æ­¤é¡¹ç›®å’Œ/或筛选器的åˆå¹¶è¯·æ±‚。"
msgid "Code coverage statistics for master %{start_date} - %{end_date}"
msgstr "master上%{start_date} - %{end_date}的代ç è¦†ç›–率统计"
@@ -6350,9 +6581,6 @@ msgstr "Collector主机å"
msgid "ComboSearch is not defined"
msgstr "ComboSearch未定义"
-msgid "Coming soon"
-msgstr "å³å°†ä¸Šçº¿"
-
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
msgstr "以逗å·åˆ†éš”,例如 '1.1.1, 2.2.2.0/24'"
@@ -6442,7 +6670,7 @@ msgid "CommitMessage|Add %{file_name}"
msgstr "添加 %{file_name}"
msgid "CommitWidget|authored"
-msgstr "作者"
+msgstr "编辑于"
msgid "Commits"
msgstr "æ交"
@@ -6663,8 +6891,8 @@ msgstr "Confluence"
msgid "ConfluenceService|Confluence Workspace"
msgstr "Confluence工作区"
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
-msgstr "将Confluence Cloud Workspace连接到您的GitLab项目"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
+msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
msgstr "å¯ç”¨Confluence工作区将ç¦ç”¨é»˜è®¤çš„GitLab Wiki。您的GitLab Wikiæ•°æ®å°†è¢«ä¿å­˜ï¼Œæ‚¨ä»¥åŽéšæ—¶å¯ä»¥é€šè¿‡å…³é—­æ­¤é›†æˆæ¥é‡æ–°å¯ç”¨å®ƒ"
@@ -6714,6 +6942,9 @@ msgstr "连接超时"
msgid "Connection timeout"
msgstr "连接超时"
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr "è”系销售人员进行å‡çº§"
@@ -6779,6 +7010,9 @@ msgstr "清ç†ç­–ç•¥ä¿å­˜æˆåŠŸã€‚"
msgid "ContainerRegistry|Cleanup policy:"
msgstr "清ç†ç­–略:"
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr "é…置摘è¦: %{digest}"
@@ -6822,7 +7056,7 @@ msgid "ContainerRegistry|Expiration schedule:"
msgstr "过期计划:"
msgid "ContainerRegistry|Filter by name"
-msgstr "按å称过滤"
+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 "如果您尚未登录,您需è¦ä½¿ç”¨æ‚¨çš„GitLab用户å和密ç æ¥è¿›è¡Œèº«ä»½è®¤è¯ã€‚如果您å¯ç”¨ %{twofaDocLinkStart}åŒé‡èº«ä»½éªŒè¯%{twofaDocLinkEnd} ,请使用%{personalAccessTokensDocLinkStart}个人访问令牌%{personalAccessTokensDocLinkEnd}而ä¸æ˜¯å¯†ç ã€‚"
@@ -6895,7 +7129,7 @@ msgid "ContainerRegistry|Something went wrong while updating the cleanup policy.
msgstr "更新清ç†æ”¿ç­–时出了错。"
msgid "ContainerRegistry|Sorry, your filter produced no results."
-msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆè¿‡æ»¤å™¨çš„任何结果."
+msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆç­›é€‰å™¨çš„任何结果."
msgid "ContainerRegistry|Tag expiration policy"
msgstr "标签过期策略"
@@ -6940,7 +7174,7 @@ 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 "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„过滤器。"
+msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„筛选器。"
msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
msgstr "当å‰æ— æ³•è¿žæŽ¥åˆ°é•œåƒåº“,原因å¯èƒ½æ˜¯é¡¹ç›®å称或路径的问题。%{docLinkStart}更多信æ¯%{docLinkEnd}"
@@ -7155,6 +7389,9 @@ msgstr "å¤åˆ¶æºåˆ†æ”¯å称"
msgid "Copy the code below to implement tracking in your application:"
msgstr "å¤åˆ¶ä¸‹é¢çš„代ç æ¥å®žçŽ°æ‚¨çš„应用程åºä¸­çš„跟踪:"
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7215,6 +7452,9 @@ msgstr "无法删除èŠå¤©æ˜µç§° %{chat_name}。"
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr "未找到设计."
@@ -7224,6 +7464,9 @@ msgstr "未找到迭代"
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr "无法删除触å‘器。"
@@ -7257,6 +7500,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr "无法上传您的设计,因为ä¸æ”¯æŒå·²ä¸Šä¼ ä¸€ä¸ªæˆ–多个的文件。"
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr "国家/地区"
@@ -7504,6 +7750,9 @@ msgstr "在 %{projectLink} 中创建åˆå¹¶è¯·æ±‚ %{mergeRequestLink}"
msgid "Created on"
msgstr "创建于"
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr "创建于:"
@@ -7597,6 +7846,9 @@ msgstr "自定义CIé…置路径"
msgid "Custom Git clone URL for HTTP(S)"
msgstr "自定义HTTP(S)åè®®Git克隆URL"
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr "自定义主机å(用于ç§æœ‰æ交电å­é‚®ä»¶ï¼‰"
@@ -7808,7 +8060,7 @@ msgid "CycleAnalytics|Days to completion"
msgstr "完æˆæ‰€éœ€å¤©æ•°"
msgid "CycleAnalytics|Display chart filters"
-msgstr "显示图表过滤器"
+msgstr "显示图表筛选器"
msgid "CycleAnalytics|No stages selected"
msgstr "未选择阶段"
@@ -7847,6 +8099,9 @@ msgstr "按类型的任务"
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr "给定的日期范围大于180天"
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr "完æˆæ‰€éœ€æ€»å¤©æ•°"
@@ -7854,13 +8109,13 @@ msgid "CycleAnalytics|Type of work"
msgstr "工作类型"
msgid "CycleAnalytics|group dropdown filter"
-msgstr "群组下拉列表过滤器"
+msgstr "群组下拉列表筛选器"
msgid "CycleAnalytics|not allowed for the given start event"
msgstr "ä¸é€‚用于给定的开始事件"
msgid "CycleAnalytics|project dropdown filter"
-msgstr "项目下拉列表过滤器"
+msgstr "项目下拉列表筛选器"
msgid "CycleAnalytics|stage dropdown"
msgstr "阶段下拉列表"
@@ -7904,6 +8159,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -7943,6 +8207,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr "无法更新站点é…置。请é‡è¯•ã€‚"
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -7964,6 +8234,12 @@ msgstr "编辑站点é…ç½®"
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr "管ç†é…ç½®"
@@ -7991,15 +8267,15 @@ msgstr "尚未创建é…ç½®"
msgid "DastProfiles|Passive"
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 "é…ç½®å称"
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr "将目标站点和扫æ设置的常用设定ä¿å­˜ä¸ºé…置。使用这些é…置进行需求扫æ。"
@@ -8015,6 +8291,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8054,6 +8333,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8066,6 +8348,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8075,6 +8363,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr "æ•°æ®ä»åœ¨è®¡ç®—中……"
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr "找ä¸åˆ°æ•°æ®æºå称"
@@ -8231,9 +8522,6 @@ msgstr ""
msgid "Delete Comment"
msgstr "删除评论"
-msgid "Delete Snippet"
-msgstr "删除代ç ç‰‡æ®µ"
-
msgid "Delete Value Stream"
msgstr ""
@@ -8243,6 +8531,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr "删除产物"
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr "删除看æ¿"
@@ -8258,9 +8549,6 @@ msgstr "删除标签"
msgid "Delete label: %{label_name} ?"
msgstr "删除标记: %{label_name}?"
-msgid "Delete list"
-msgstr "删除列表"
-
msgid "Delete pipeline"
msgstr "删除æµæ°´çº¿"
@@ -8282,6 +8570,9 @@ msgstr "删除代ç ç‰‡æ®µå—?"
msgid "Delete source branch"
msgstr "删除æºåˆ†æ”¯"
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr "删除此附件"
@@ -8345,12 +8636,18 @@ msgstr "已拒ç»"
msgid "Denied authorization of chat nickname %{user_name}."
msgstr "æ‹’ç»èŠå¤©æ˜µç§° %{user_name} 的授æƒã€‚"
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr "æ‹’ç»"
msgid "Deny access request"
msgstr "æ‹’ç»è®¿é—®è¯·æ±‚"
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr "ä¾èµ–项"
@@ -8396,18 +8693,27 @@ msgstr "导出为JSON"
msgid "Dependencies|Job failed to generate the dependency list"
msgstr "作业无法生æˆä¾èµ–项列表"
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr "许å¯è¯"
msgid "Dependencies|Location"
msgstr "ä½ç½®"
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr "打包程åº"
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr "%{codeStartTag}dependency_scanning%{codeEndTag} 作业失败,无法生æˆåˆ—表。请确ä¿ä½œä¸šæ­£å¸¸è¿è¡Œå¹¶é‡å¯æµæ°´çº¿ã€‚"
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8480,9 +8786,6 @@ msgstr "未找到部署进度。è¦æŸ¥çœ‹pod,请确ä¿æ‚¨çš„环境符åˆ%{link
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 "部署é¢æ¿å·²åˆ é™¤æ ‡ç­¾%{appLabel}上的匹é…。è¦æŸ¥çœ‹éƒ¨ç½²é¢æ¿ä¸Šçš„所有实例,您必须更新Chart并é‡æ–°éƒ¨ç½²ã€‚"
-
msgid "DeployFreeze|Freeze end"
msgstr "冻结结æŸ"
@@ -8648,6 +8951,12 @@ msgstr "已部署"
msgid "Deployed to"
msgstr "已部署到"
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr "正在部署到"
@@ -8696,6 +9005,9 @@ msgstr "æè¿°"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "使用%{link_start}GitLab风格Markdown%{link_end}解æžçš„æè¿°"
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr "æ述模æ¿å…许您为项目的问题和åˆå¹¶è¯·æ±‚定义æ述字段的特定模æ¿ã€‚"
@@ -8867,6 +9179,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr "差异内容é™åˆ¶"
@@ -8918,8 +9251,8 @@ msgstr "ç¦ç”¨ç¾¤ç»„Runner"
msgid "Disable public access to Pages sites"
msgstr "ç¦æ­¢å…¬å¼€è®¿é—®Pages网站"
-msgid "Disable shared Runners"
-msgstr "ç¦ç”¨å…±äº«Runner"
+msgid "Disable shared runners"
+msgstr ""
msgid "Disable two-factor authentication"
msgstr "ç¦ç”¨åŒé‡è®¤è¯"
@@ -9066,6 +9399,9 @@ msgstr "文档"
msgid "Documentation for popular identity providers"
msgstr "常è§çš„身份验è¯æ供商的相关文档"
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr "文档é‡å»ºç´¢å¼•: %{processed_documents} (%{percentage}%%)"
@@ -9075,6 +9411,9 @@ msgstr "域å"
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr "如已关è”到一个或多个集群,则域ä¸èƒ½åˆ é™¤ã€‚"
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr "域验è¯æ˜¯å…¬å…± GitLab 站点的基本安全措施。用户需è¦è¯æ˜Žä»–们在å¯ç”¨åŸŸä¹‹å‰æ‹¥æœ‰åŸŸçš„所有æƒ"
@@ -9096,6 +9435,9 @@ 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-----' 为开头的公钥部分。"
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "ä¸å†æ˜¾ç¤º"
@@ -9123,9 +9465,6 @@ msgstr "下载å¦å­˜ä¸º"
msgid "Download as CSV"
msgstr "下载CSV"
-msgid "Download asset"
-msgstr "下载资æº"
-
msgid "Download codes"
msgstr "下载代ç "
@@ -9294,15 +9633,24 @@ msgstr "编辑公共部署密钥"
msgid "Edit stage"
msgstr "编辑阶段"
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr "编辑此å‘布"
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr "编辑Wiki页é¢"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "编辑你在最近主题中的评论(从空白文本区)"
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr "编辑于%{timeago}"
@@ -9375,6 +9723,9 @@ msgstr "邮件已å‘é€"
msgid "Email the pipelines status to a list of recipients."
msgstr "å°†æµæ°´çº¿çŠ¶æ€é€šè¿‡ç”µå­é‚®ä»¶å‘é€ç»™å¤šä¸ªæ”¶ä»¶äººã€‚"
+msgid "Email updates (optional)"
+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 "电å­é‚®ä»¶å†…容空白。请确ä¿æ‚¨çš„回å¤ä½äºŽç”µå­é‚®ä»¶çš„顶部,因为我们无法处ç†å†…è”回å¤ã€‚"
@@ -9516,6 +9867,12 @@ msgstr "在电å­é‚®ä»¶ä¸­å¯ç”¨é¡µçœ‰å’Œé¡µè„š"
msgid "Enable integration"
msgstr "å¯ç”¨é›†æˆ"
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "å¯ç”¨ç»´æŠ¤æ¨¡å¼"
@@ -9543,8 +9900,20 @@ msgstr "å¯ç”¨ä»£ç†"
msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr "å¯ç”¨reCAPTCHA或Akismet并设置IPé™åˆ¶ã€‚对于reCAPTCHA,我们目å‰ä»…æ”¯æŒ %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
-msgid "Enable shared Runners"
-msgstr "å¯ç”¨å…±äº«Runner"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
+msgstr ""
msgid "Enable snowplow tracking"
msgstr "å¯ç”¨Snowplow跟踪"
@@ -9588,6 +9957,9 @@ msgstr "此功能仅在 GitLab EE 许å¯ä¸‹å¯ç”¨ã€‚如果è¦å¯ç”¨ï¼Œè¯·ç¡®è®¤å
msgid "Encountered an error while rendering: %{err}"
msgstr "渲染时出现错误: %{err}"
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "结æŸäºŽ(UTC)"
@@ -9615,8 +9987,11 @@ msgstr "输入IP地å€èŒƒå›´"
msgid "Enter a number"
msgstr "输入数字"
-msgid "Enter a whole number between 0 and 100"
-msgstr "输入0到100之间的整数"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
+msgstr ""
msgid "Enter at least three characters to search"
msgstr "请至少输入三个字符æ‰å¯æœç´¢"
@@ -10273,7 +10648,7 @@ msgid "EventFilterBy|Filter by comments"
msgstr "åªæ˜¾ç¤ºè¯„论事件"
msgid "EventFilterBy|Filter by designs"
-msgstr "按设计过滤"
+msgstr "按设计筛选"
msgid "EventFilterBy|Filter by epic events"
msgstr "按å²è¯—事件筛选"
@@ -10291,7 +10666,7 @@ msgid "EventFilterBy|Filter by team"
msgstr "åªæ˜¾ç¤ºå›¢é˜Ÿäº‹ä»¶"
msgid "EventFilterBy|Filter by wiki"
-msgstr "按Wiki过滤"
+msgstr "按Wiki筛选"
msgid "Events"
msgstr "事件"
@@ -10377,12 +10752,18 @@ msgstr "示例:使用é‡=å•ä¸€æŸ¥è¯¢ã€‚(请求)/(容é‡)=å½¢æˆå…¬å¼çš„多é‡
msgid "Except policy:"
msgstr "除外(Except)æ¡ä»¶ï¼š"
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr "ä¸åŒ…括åˆå¹¶æ交。仅é™%{limit}次æ交。"
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "ä¸åŒ…括åˆå¹¶æ交。仅é™6,000次æ交。"
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10413,6 +10794,9 @@ msgstr ""
msgid "Expand approvers"
msgstr "展开核准人"
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr "展开里程碑"
@@ -10488,6 +10872,9 @@ msgstr "导出群组"
msgid "Export issues"
msgstr "导出议题"
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "导出项目"
@@ -10590,6 +10977,9 @@ msgstr "无法为此问题创建分支。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "Failed to create import label for jira import."
msgstr "为jira导入创建导入标签失败。"
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr "创建仓库失败"
@@ -10653,6 +11043,9 @@ msgstr "加载标记失败。请é‡è¯•ã€‚"
msgid "Failed to load milestones. Please try again."
msgstr "加载里程碑失败。请é‡è¯•ã€‚"
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr "加载相关分支失败"
@@ -10665,6 +11058,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr "加载堆栈跟踪失败。"
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr "无法将此议题标记为é‡å¤ï¼Œå› ä¸ºæœªæ‰¾åˆ°å¼•ç”¨çš„议题。"
@@ -10801,6 +11197,18 @@ msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] "%d个用户"
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr "*(所有环境)"
@@ -10831,6 +11239,9 @@ msgstr "é…ç½®"
msgid "FeatureFlags|Configure feature flags"
msgstr "é…置功能标志"
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr "创建功能标志"
@@ -10882,6 +11293,9 @@ msgstr "功能标志 %{name} 将被删除。您确定å—?"
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr "功能标志å…许通过动æ€åˆ‡æ¢æŸäº›åŠŸèƒ½ä½¿åº”用呈现ä¸åŒç‰¹æ€§ã€‚"
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr "标志å³å°†å˜ä¸ºåªè¯»"
@@ -10948,11 +11362,14 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr "用户百分比"
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr "百分比上线(登录用户)"
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
-msgstr "百分比上线显示必须是0-100之间的整个数字"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
+msgstr ""
msgid "FeatureFlags|Protected"
msgstr "å—ä¿æŠ¤"
@@ -10966,6 +11383,9 @@ msgstr "上线百分比"
msgid "FeatureFlags|Rollout Strategy"
msgstr "上线策略"
+msgid "FeatureFlags|Select a user list"
+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 "设置Unleash客户端应用å称为应用程åºè¿è¡Œçš„环境å称。 此值将用于匹é…环境范围。查看 %{linkStart}客户端é…置示例%{linkEnd}。"
@@ -10984,9 +11404,6 @@ msgstr "获å–功能标志时出错。"
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11002,15 +11419,15 @@ msgstr "用户列表"
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr "列表"
-
msgid "FeatureFlag|Percentage"
msgstr "百分比"
msgid "FeatureFlag|Select a user list"
msgstr "选择一个用户列表"
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr "没有é…置的用户列表"
@@ -11020,6 +11437,9 @@ msgstr "类型"
msgid "FeatureFlag|User IDs"
msgstr "用户ID"
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "2月"
@@ -11077,12 +11497,18 @@ msgstr "文件模æ¿"
msgid "File upload error."
msgstr "文件上传错误。"
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "文件"
msgid "Files breadcrumb"
msgstr "文件导航"
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr "æ交引用%{ref}路径%{path}中的文件,目录和å­æ¨¡å—"
@@ -11093,43 +11519,46 @@ msgid "Filter"
msgstr "筛选器"
msgid "Filter by %{issuable_type} that are currently closed."
-msgstr "过滤器%{issuable_type}当å‰å…³é—­ã€‚"
+msgstr "筛选器%{issuable_type}当å‰å…³é—­ã€‚"
msgid "Filter by %{issuable_type} that are currently opened."
-msgstr "过滤器%{issuable_type}当å‰å¼€å¯ã€‚"
+msgstr "筛选器%{issuable_type}当å‰å¼€å¯ã€‚"
msgid "Filter by %{page_context_word} that are currently opened."
-msgstr "按当å‰å¼€æ”¾çš„%{page_context_word}过滤。"
+msgstr "按当å‰å¼€æ”¾çš„%{page_context_word}筛选。"
msgid "Filter by Git revision"
-msgstr "按Git版本过滤"
+msgstr "按Git版本筛选"
msgid "Filter by issues that are currently closed."
-msgstr "按当å‰å…³é—­çš„议题过滤。"
+msgstr "按当å‰å…³é—­çš„议题筛选。"
+
+msgid "Filter by issues that are currently opened."
+msgstr ""
msgid "Filter by label"
-msgstr "按标记过滤"
+msgstr "按标记筛选"
msgid "Filter by merge requests that are currently closed and unmerged."
-msgstr "按当å‰å·²å…³é—­å’Œæœªåˆå¹¶çš„åˆå¹¶è¯·æ±‚过滤。"
+msgstr "按当å‰å·²å…³é—­å’Œæœªåˆå¹¶çš„åˆå¹¶è¯·æ±‚筛选。"
msgid "Filter by merge requests that are currently merged."
-msgstr "按当å‰å·²åˆå¹¶çš„åˆå¹¶è¯·æ±‚过滤。"
+msgstr "按当å‰å·²åˆå¹¶çš„åˆå¹¶è¯·æ±‚筛选。"
msgid "Filter by milestone name"
-msgstr "按里程碑å称过滤"
+msgstr "按里程碑å称筛选"
msgid "Filter by name"
-msgstr "按å称过滤"
+msgstr "按å称筛选"
msgid "Filter by requirements that are currently archived."
-msgstr "按当å‰å·²å­˜æ¡£çš„需求过滤。"
+msgstr "按当å‰å·²å­˜æ¡£çš„需求筛选。"
msgid "Filter by requirements that are currently opened."
-msgstr "按当å‰å¼€æ”¾çš„需求过滤。"
+msgstr "按当å‰å¼€æ”¾çš„需求筛选。"
msgid "Filter by status"
-msgstr "按状æ€è¿‡æ»¤"
+msgstr "按状æ€ç­›é€‰"
msgid "Filter by test cases that are currently archived."
msgstr ""
@@ -11138,7 +11567,7 @@ msgid "Filter by test cases that are currently opened."
msgstr ""
msgid "Filter by two-factor authentication"
-msgstr "按åŒé‡è®¤è¯è¿‡æ»¤"
+msgstr "按åŒé‡è®¤è¯ç­›é€‰"
msgid "Filter by user"
msgstr "按用户筛选"
@@ -11147,29 +11576,32 @@ msgid "Filter parameters are not valid. Make sure that the end date is after the
msgstr ""
msgid "Filter pipelines"
-msgstr "过滤æµæ°´çº¿"
+msgstr "筛选æµæ°´çº¿"
msgid "Filter results"
-msgstr "过滤结果"
+msgstr "筛选结果"
msgid "Filter results by group"
-msgstr "按群组过滤结果"
+msgstr "按群组筛选结果"
msgid "Filter results by project"
-msgstr "按项目过滤结果"
+msgstr "按项目筛选结果"
msgid "Filter results..."
-msgstr "过滤结果..."
+msgstr "筛选结果..."
msgid "Filter your repositories by name"
msgstr ""
msgid "Filter..."
-msgstr "过滤..."
+msgstr "筛选..."
msgid "Find File"
msgstr "查找文件"
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11203,9 +11635,6 @@ msgstr "完æˆæ‚¨çš„%{group_name}专用å¸æˆ·è®¾ç½®ã€‚"
msgid "Finished"
msgstr "已完æˆ"
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr "å太长(最多为 %{max_length} 个字符)。"
-
msgid "First Seen"
msgstr "首次出现"
@@ -11215,9 +11644,15 @@ msgstr "æ¯å‘¨çš„起始日"
msgid "First name"
msgstr "åå­—"
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr "首次出现"
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr "固定日期"
@@ -11272,8 +11707,8 @@ 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 internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
msgid "For more info, read the documentation."
msgstr "有关详细信æ¯ï¼Œè¯·é˜…读文档。"
@@ -11588,7 +12023,7 @@ msgid "Geo|%{name} is scheduled for re-verify"
msgstr "%{name}已计划é‡æ–°éªŒè¯"
msgid "Geo|Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
-msgstr "请您调整上é¢çš„过滤器/æœç´¢æ¡ä»¶ã€‚如果您认为此处有误,请å‚阅 %{linkStart}Geo Troubleshow%{linkEnd} 文档以获å–更多信æ¯ã€‚"
+msgstr "请您调整上é¢çš„筛选器/æœç´¢æ¡ä»¶ã€‚如果您认为此处有误,请å‚阅 %{linkStart}Geo Troubleshow%{linkEnd} 文档以获å–更多信æ¯ã€‚"
msgid "Geo|All %{replicable_name}"
msgstr "所有%{replicable_name}"
@@ -11630,7 +12065,7 @@ msgid "Geo|Failed"
msgstr "失败"
msgid "Geo|Filter by status"
-msgstr "按状æ€è¿‡æ»¤"
+msgstr "按状æ€ç­›é€‰"
msgid "Geo|Geo Status"
msgstr "Geo状æ€"
@@ -11818,8 +12253,8 @@ msgstr "开始使用å‘布"
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 "如果%{docs_link_start}为项目å¯ç”¨%{docs_link_end}了LFS,则Git LFS对象将在拉å–é•œåƒæ—¶åŒæ­¥ï¼Œ 但%{strong_open}ä¸ä¼š%{strong_close}在推é€é•œåƒæ—¶åŒæ­¥ã€‚"
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
+msgstr ""
msgid "Git LFS status:"
msgstr "Git LFS状æ€ï¼š"
@@ -11839,6 +12274,9 @@ msgstr "Git 浅克隆"
msgid "Git strategy for pipelines"
msgstr "æµæ°´çº¿çš„Gitç­–ç•¥"
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr "Git 版本"
@@ -11875,9 +12313,6 @@ msgstr ""
msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
msgstr "GitLabæœåŠ¡å°èƒ½å¤Ÿä»¥ç®€å•çš„æ–¹å¼è®©ç”¨æˆ·åœ¨æ‚¨çš„GitLab实例中创建议题,而无需创建账å·ã€‚它为最终用户æ供了在项目中创建问题的唯一电å­é‚®ä»¶åœ°å€ï¼Œå¹¶ä¸”å¯ä»¥é€šè¿‡GitLabç•Œé¢æˆ–通过电å­é‚®ä»¶è¿›è¡Œç­”å¤ã€‚最终用户将仅通过电å­é‚®ä»¶çœ‹åˆ°è¯¥ä¸»é¢˜ã€‚"
-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 è¿è¡Œå™¨è‡ªåŠ¨ç¼©æ”¾ã€‚"
-
msgid "GitLab Shell"
msgstr ""
@@ -11902,6 +12337,12 @@ msgstr "GitLab导出"
msgid "GitLab for Slack"
msgstr "GitLab for Slack"
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr "GitLab是æœåŠ¡äºŽæ•´ä¸ªè½¯ä»¶å¼€å‘生命周期的å•ä¸€åº”用程åºã€‚从项目规划和æºç ç®¡ç†åˆ°CI/CDã€ç›‘控和安全。"
@@ -12214,6 +12655,9 @@ msgstr "转到您的项目"
msgid "Go to your snippets"
msgstr "转到您的代ç ç‰‡æ®µ"
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr "谷歌云平å°"
@@ -12319,8 +12763,8 @@ msgstr "群组URL"
msgid "Group avatar"
msgstr "群组头åƒ"
-msgid "Group by:"
-msgstr "分组ä¾æ®ï¼š"
+msgid "Group by"
+msgstr ""
msgid "Group description"
msgstr "群组æè¿°"
@@ -12476,7 +12920,13 @@ msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your
msgstr "è¦æŸ¥çœ‹è·¯çº¿å›¾ï¼Œè¯·åœ¨æ­¤ç¾¤ç»„或其å­ç¾¤ç»„中的一个 å²è¯— 中添加开始日期或截止日期;从 %{startDate} 到 %{endDate}。"
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
-msgstr "è¦æ‰©å¤§æ‚¨çš„æœç´¢ï¼Œè¯·æ›´æ”¹æˆ–移除过滤器,从 %{startDate} 到 %{endDate}。"
+msgstr "è¦æ‰©å¤§æ‚¨çš„æœç´¢ï¼Œè¯·æ›´æ”¹æˆ–移除筛选器,从 %{startDate} 到 %{endDate}。"
+
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr "è¯ä¹¦æŒ‡çº¹"
@@ -12487,6 +12937,9 @@ msgstr "é…ç½®"
msgid "GroupSAML|Copy SAML Response XML"
msgstr "å¤åˆ¶SAMLå“应XML"
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr "默认æˆå‘˜è§’色"
@@ -12532,12 +12985,30 @@ msgstr "NameID"
msgid "GroupSAML|NameID Format"
msgstr "NameIDæ ¼å¼"
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr "ç¦æ­¢å¤–部派生"
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr "ç¦æ­¢ä»Žæ­¤ç¾¤ç»„å‘外派生。"
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr "SAMLå“应输出"
@@ -12550,6 +13021,9 @@ msgstr "SAML å•ç‚¹ç™»å½•"
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr "SAML å•ç‚¹ç™»å½•è®¾ç½®"
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr "SCIM API 端点 URL"
@@ -12562,6 +13036,9 @@ msgstr "SAML令牌签åè¯ä¹¦çš„SHA1指纹。请从身份验è¯æ供商处获å
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr "SCIM 令牌现在已éšè—。è¦å†æ¬¡æŸ¥çœ‹ä»¤ç‰Œçš„å€¼ï¼Œæ‚¨éœ€è¦ "
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr "这将被设置为添加到群组的用户的访问级别。"
@@ -12586,6 +13063,9 @@ msgstr "在ç¦æ­¢å¤–部派生标志å¯ç”¨åŽï¼Œç¾¤ç»„æˆå‘˜å°†åªèƒ½åœ¨æ‚¨çš„群
msgid "GroupSAML|Your SCIM token"
msgstr "您的 SCIM 令牌"
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr "必须匹é…“%{extern_uid}â€å­˜å‚¨çš„NameID,因为它用æ¥æ ‡è¯†ç”¨æˆ·ã€‚如果NameID更改,则用户将无法登录。"
@@ -12993,6 +13473,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "历å²"
@@ -13047,9 +13530,6 @@ 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} çš„æˆå‘˜ã€‚请使用其他å¸æˆ·ç™»å½•ä»¥æŽ¥å—邀请。"
-msgid "I accept the %{terms_link_start}Terms of Service and Privacy Policy%{terms_link_end}"
-msgstr "我接å—%{terms_link_start}æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–%{terms_link_end}"
-
msgid "I accept the %{terms_link}"
msgstr "æˆ‘æŽ¥å— %{terms_link}"
@@ -13062,8 +13542,8 @@ msgstr "我忘记了密ç "
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr "我已ç»é˜…读并åŒæ„Let's Encryptçš„%{link_start}æœåŠ¡æ¡æ¬¾%{link_end}(PDF)"
-msgid "I'd like to receive updates via email about GitLab"
-msgstr "我åŒæ„通过电å­é‚®ä»¶æŽ¥æ”¶æœ‰å…³GitLabçš„æ›´æ–°"
+msgid "I'd like to receive updates about GitLab via email"
+msgstr ""
msgid "ID"
msgstr "ID"
@@ -13170,6 +13650,9 @@ msgstr "如果å¯ç”¨ï¼ŒGitLab将使用Geo处ç†å¯¹è±¡å­˜å‚¨å¤åˆ¶ã€‚ %{linkStart
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "如果å¯ç”¨ï¼Œåˆ™ä½¿ç”¨å¤–部æœåŠ¡ä¸Šçš„分类标签æ¥éªŒè¯å¯¹é¡¹ç›®çš„访问æƒé™ã€‚"
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13194,9 +13677,6 @@ msgstr "如果您最近没有登录,请立å³æ›´æ”¹å¯†ç : %{password_link}。
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 "如果你已使用100%%存储容é‡ï¼Œä½ å°†æ— æ³•: %{base_message}"
-
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr "如果您最近从上述IP地å€ç™»å½•è¿‡ï¼Œåˆ™å¯ä»¥å¿½ç•¥æ­¤ç”µå­é‚®ä»¶ã€‚"
@@ -13218,12 +13698,12 @@ msgstr "忽略"
msgid "Ignored"
msgstr "已忽略"
-msgid "Image Details"
-msgstr "图片详情"
-
msgid "Image URL"
msgstr "图片网å€"
+msgid "Image details"
+msgstr ""
+
msgid "ImageDiffViewer|2-up"
msgstr "并列(2-up)"
@@ -13301,6 +13781,9 @@ msgstr "通过上传manifest文件导入多个仓库"
msgid "Import project"
msgstr "导入项目"
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr "导入项目æˆå‘˜"
@@ -13421,6 +13904,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr "事件管ç†é™åˆ¶"
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr "全部"
@@ -13481,6 +13970,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr "显示事件时出错。"
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr "å–消指派"
@@ -13490,12 +13982,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr "未å‘布"
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr "警报集æˆ"
msgid "IncidentSettings|Grafana integration"
msgstr "Grafana集æˆ"
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr "事件"
@@ -13505,6 +14003,30 @@ msgstr "PagerDuty集æˆ"
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr "设置外部工具集æˆä»¥æ›´å¥½åœ°ç®¡ç†äº‹ä»¶ã€‚"
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr "事故"
@@ -13517,6 +14039,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "包括所有用户必须接å—çš„æœåŠ¡æ¡æ¬¾å议和éšç§æ”¿ç­–。"
@@ -13592,35 +14117,41 @@ msgstr "手动输入主机密钥"
msgid "Input your repository URL"
msgstr "输入您的仓库URL"
-msgid "Insert"
-msgstr "æ’å…¥"
-
msgid "Insert a code block"
msgstr "æ’入代ç å—"
msgid "Insert a quote"
msgstr "æ’入引用"
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr "æ’入图片"
msgid "Insert code"
msgstr "æ’入代ç "
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr "æ’入内è”代ç "
msgid "Insert suggestion"
msgstr "æ’入建议"
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr "洞察"
msgid "Insights|Some items are not visible beacuse the project was filtered out in the insights.yml file (see the projects.only config for more information)."
-msgstr "有些æ¡ç›®ä¸å¯è§ï¼Œç”±äºŽå·²åœ¨insights.yml文件中过滤掉(è§projects.onlyé…置以了解更多信æ¯)。"
+msgstr "有些æ¡ç›®ä¸å¯è§ï¼Œç”±äºŽå·²åœ¨insights.yml文件中筛选掉(è§projects.onlyé…置以了解更多信æ¯)。"
msgid "Insights|This project is filtered out in the insights.yml file (see the projects.only config for more information)."
-msgstr "此项目已在insights.yml文件中过滤掉(è§projects.onlyé…置以了解更多信æ¯)。"
+msgstr "此项目已在insights.yml文件中筛选掉(è§projects.onlyé…置以了解更多信æ¯)。"
msgid "Install"
msgstr "安装"
@@ -13631,6 +14162,9 @@ msgstr "安装GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "在Kubernetes上安装Runner"
+msgid "Install a Runner"
+msgstr ""
+
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr "从您的应用程åºåº“安装软令牌验è¯å™¨å¦‚ %{free_otp_link} 或者谷歌验è¯å™¨ï¼Œç„¶åŽä½¿ç”¨è¯¥éªŒè¯å™¨æ‰«æ此二维ç ã€‚更多信æ¯è¯·æŸ¥çœ‹%{help_link_start}文档%{help_link_end}。"
@@ -13659,6 +14193,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr "实例管ç†å‘˜ç»„已存在"
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13668,12 +14247,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13707,6 +14304,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13722,38 +14322,59 @@ msgstr "包括标准加整个æ交消æ¯ï¼Œæ交哈希和议题ID"
msgid "Integrations|Includes commit title and branch"
msgstr "包括æ交的标题和分支"
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr "标准"
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr "使用自定义设置"
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr "在æ交或åˆå¹¶è¯·æ±‚中æåŠJira议题时,将创建远程链接和评论(如果å¯ç”¨)。"
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+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 group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
-msgstr "内部 - å¯ä»¥é€šè¿‡ä»»ä½•ç™»å½•ç”¨æˆ·è®¿é—®è¯¥é¡¹ç›®ã€‚"
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "Internal URL (optional)"
msgstr "内部URL(å¯é€‰)"
@@ -13761,6 +14382,9 @@ msgstr "内部URL(å¯é€‰)"
msgid "Internal users"
msgstr "内部用户"
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "循环周期"
@@ -13785,9 +14409,6 @@ msgstr ""
msgid "Invalid URL"
msgstr "无效的网å€"
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr "无效的container_name"
@@ -13887,25 +14508,25 @@ msgstr "邀请æˆå‘˜"
msgid "Invite teammates (optional)"
msgstr "邀请团队æˆå‘˜(å¯é€‰)"
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -13953,6 +14574,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14001,6 +14676,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "议题看æ¿"
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr "问题已å‡çº§ä¸ºå²è¯—。"
@@ -14110,7 +14788,7 @@ msgid "Issues and Merge Requests"
msgstr "议题和åˆå¹¶è¯·æ±‚"
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
-msgstr "议题å¯ä»¥æ˜¯ç¼ºé™·ï¼Œä»»åŠ¡æˆ–è¦è®¨è®ºçš„想法。此外,å¯ä»¥é€šè¿‡æœç´¢å’Œè¿‡æ»¤æ¥æŸ¥æ‰¾è®®é¢˜ã€‚"
+msgstr "议题å¯ä»¥æ˜¯ç¼ºé™·ï¼Œä»»åŠ¡æˆ–è¦è®¨è®ºçš„想法。此外,å¯ä»¥é€šè¿‡æœç´¢å’Œç­›é€‰æ¥æŸ¥æ‰¾è®®é¢˜ã€‚"
msgid "Issues closed"
msgstr "关闭议题"
@@ -14143,13 +14821,13 @@ msgid "IssuesAnalytics|Last 12 months"
msgstr "最近12个月"
msgid "IssuesAnalytics|Sorry, your filter produced no results"
-msgstr "对ä¸èµ·ï¼Œæ— ç¬¦åˆè¿‡æ»¤å™¨çš„结果"
+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 "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„过滤æ¡ä»¶"
+msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„筛选æ¡ä»¶"
msgid "IssuesAnalytics|Total:"
msgstr "总计:"
@@ -14217,6 +14895,9 @@ msgstr "1月"
msgid "January"
msgstr "1月"
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr "Jira议题"
@@ -14472,6 +15153,9 @@ msgstr "K8s podå¥åº·"
msgid "Keep divergent refs"
msgstr "ä¿ç•™åˆ†å‰çš„refs"
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr "Kerberos访问被拒ç»"
@@ -14490,6 +15174,12 @@ msgstr "å¿«æ·é”®"
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr "é”®"
@@ -14619,9 +15309,6 @@ 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 "å‡çº§%{labelTitle}将使其å¯ç”¨äºŽ%{groupName}内的所有项目。现有的åŒå项目标记将被åˆå¹¶ã€‚现有的åŒå群组标记也将被åˆå¹¶ã€‚该æ“作ä¸å¯æ’¤é”€ã€‚"
-msgid "Labels|and %{count} more"
-msgstr "以åŠå…¶ä½™%{count}项"
-
msgid "Language"
msgstr "语言"
@@ -14647,9 +15334,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr "最åŽè®¿é—®äºŽ"
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr "姓太长(最多为 %{max_length} 个字符)。"
-
msgid "Last Pipeline"
msgstr "最新æµæ°´çº¿"
@@ -14683,6 +15367,9 @@ msgstr "此页é¢åœ¨æ‚¨çš„æµè§ˆå™¨ä¸­è½½å…¥å‰çš„最åŽä¸€ä¸ªé¡¹ç›®ï¼š"
msgid "Last name"
msgstr "姓"
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr "最åŽå›žå¤æ¥è‡ªäºŽ"
@@ -14716,6 +15403,9 @@ msgstr "最近更新"
msgid "Last used"
msgstr "最åŽä½¿ç”¨"
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr "上次使用于:"
@@ -14761,6 +15451,9 @@ msgstr "了解如何å¯ç”¨åŒæ­¥"
msgid "Learn more"
msgstr "进一步了解"
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr "了解更多关于Auto DevOps"
@@ -14836,6 +15529,9 @@ msgstr "使用默认值设定 \"文件类型\" 和 \"交付方法\""
msgid "Leave zen mode"
msgstr "离开禅模å¼"
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "Let's Encryptä¸æŽ¥å—example.com的电å­é‚®ä»¶"
@@ -15368,9 +16064,6 @@ msgstr "3月"
msgid "March"
msgstr "3月"
-msgid "Mark To Do as done"
-msgstr "将待办事项标记为已完æˆã€‚"
-
msgid "Mark as done"
msgstr "标记为已完æˆ"
@@ -15389,6 +16082,9 @@ msgstr "将此议题标记为å¦ä¸€ä¸ªè®®é¢˜çš„é‡å¤"
msgid "Mark this issue as related to another issue"
msgstr "将此议题标记为与å¦ä¸€ä¸ªè®®é¢˜çš„相关"
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr "Markdown"
@@ -15422,9 +16118,6 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr "标记删除于 - %{deletion_time}"
-msgid "Marked To Do as done."
-msgstr "将待办事项标记为已完æˆã€‚"
-
msgid "Marked this %{noun} as Work In Progress."
msgstr "æ­¤%{noun}已标记为“正在进行中â€ã€‚"
@@ -15434,8 +16127,8 @@ msgstr "标记这个议题为%{duplicate_param}çš„é‡å¤é¡¹ã€‚"
msgid "Marked this issue as related to %{issue_ref}."
msgstr "将此议题标记为%{issue_ref}的相关议题。"
-msgid "Marks To Do as done."
-msgstr "将待办事项标记为已完æˆã€‚"
+msgid "Marked to do as done."
+msgstr ""
msgid "Marks this %{noun} as Work In Progress."
msgstr "将此%{noun}标记为“正在进行中â€ã€‚"
@@ -15446,6 +16139,9 @@ msgstr "将此议题标记为 %{duplicate_reference} çš„é‡å¤ã€‚"
msgid "Marks this issue as related to %{issue_ref}."
msgstr "将此议题标记为%{issue_ref}的相关议题。"
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr "éšè—å˜é‡"
@@ -15509,6 +16205,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15629,6 +16328,12 @@ msgstr "æˆå‘˜é”"
msgid "Member since %{date}"
msgstr "加入于 %{date}"
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr "æˆå‘˜"
@@ -15656,15 +16361,90 @@ msgstr "有æƒè®¿é—®%{strong_start}%{group_name}%{strong_end}çš„æˆå‘˜"
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr "内存使用情况"
@@ -15902,6 +16682,9 @@ msgstr "å·²åˆå¹¶åˆ†æ”¯æ­£åœ¨è¢«åˆ é™¤ã€‚该æ“作å¯èƒ½éœ€è¦ä¸€äº›æ—¶é—´ï¼Œå…·
msgid "Merged this merge request."
msgstr "å·²åˆå¹¶æ­¤åˆå¹¶è¯·æ±‚。"
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr "ç«‹å³åˆå¹¶æ­¤åˆå¹¶è¯·æ±‚。"
@@ -16303,6 +17086,27 @@ msgstr "当å‰è®¸å¯è¯æ— æ³•ä½¿ç”¨é‡Œç¨‹ç¢‘列表"
msgid "Milestone lists show all issues from the selected milestone."
msgstr "里程碑列表显示所选里程碑的所有议题。"
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr "关闭:"
@@ -16618,9 +17422,15 @@ msgstr "多项目"
msgid "Multi-project Runners cannot be removed"
msgstr "多项目Runner无法删除"
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr "支æŒå¤šä¸ªIP地å€èŒƒå›´ã€‚"
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr "支æŒå¤šä¸ªåŸŸå。"
@@ -16678,6 +17488,32 @@ msgstr "命å空间为空"
msgid "Namespace:"
msgstr "命å空间:"
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr "命å空间"
@@ -16933,6 +17769,9 @@ msgstr "从ä¸"
msgid "New"
msgstr "新增"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr "新建应用"
@@ -17175,7 +18014,7 @@ msgid "No changes between %{sourceBranch} and %{targetBranch}"
msgstr ""
msgid "No child epics match applied filters"
-msgstr "没有匹é…当å‰è¿‡æ»¤å™¨çš„å­å²è¯—"
+msgstr "没有匹é…当å‰ç­›é€‰å™¨çš„å­å²è¯—"
msgid "No commits present here"
msgstr "此处无æ交"
@@ -17396,6 +18235,9 @@ msgstr "éžç®¡ç†å‘˜ç”¨æˆ·å¯ä»¥ä½¿ç”¨åªè¯»æƒé™ç™»å½•å¹¶å‘èµ·åªè¯»çš„API请
msgid "None"
msgstr "æ— "
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr "尚未实现"
@@ -17426,9 +18268,6 @@ msgstr "æ•°æ®ä¸è¶³"
msgid "Not found."
msgstr "未找到。"
-msgid "Not now"
-msgstr "æš‚ä¸"
-
msgid "Not ready yet. Try again later."
msgstr "还没有准备好。请ç¨åŽå†è¯•ã€‚"
@@ -17663,6 +18502,9 @@ msgstr "OmniAuth"
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 "Omnibusä¿æŠ¤è·¯å¾„阈值已å¯ç”¨ï¼Œä¸”优先级高于这些设置。从12.4èµ·Omnibus阈值已弃用,并将在未æ¥ç‰ˆæœ¬ä¸­ç§»é™¤ã€‚请å‚阅%{relative_url_link_start}è¿ç§»ä¿æŠ¤è·¯å¾„文档%{relative_url_link_end}。"
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr "进度正常"
@@ -17708,9 +18550,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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}"
@@ -17720,9 +18559,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17841,20 +18677,14 @@ msgstr "在文件视图中打开"
msgid "Open issues"
msgstr "å¼€å¯çš„议题"
-msgid "Open projects"
-msgstr "打开项目"
-
msgid "Open raw"
msgstr "打开原始文件"
msgid "Open sidebar"
msgstr "打开侧边æ "
-msgid "Open: %{openIssuesCount}"
-msgstr "å¼€å¯: %{openIssuesCount}"
-
-msgid "Open: %{open} • Closed: %{closed}"
-msgstr "打开: %{open} • 关闭: %{closed}"
+msgid "Open: %{open}"
+msgstr ""
msgid "Opened"
msgstr "已打开"
@@ -18027,6 +18857,9 @@ msgstr "添加Conan远端"
msgid "PackageRegistry|Add NuGet Source"
msgstr "添加Nugetæº"
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr "应用分组: %{group}"
@@ -18100,7 +18933,7 @@ msgid "PackageRegistry|Delete package"
msgstr "删除软件包"
msgid "PackageRegistry|Filter by name"
-msgstr "按å称过滤"
+msgstr "按å称筛选"
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -18123,8 +18956,8 @@ 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|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中建立对新软件包管ç†å·¥å…·çš„支æŒä¿¡æ¯ã€‚以下是我们关注的软件包管ç†å·¥å…·çš„列表。"
+msgid "PackageRegistry|Install package version"
+msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "了解如何使用GitLab%{noPackagesLinkStart}å‘布和共享您的软件包%{noPackagesLinkEnd}。"
@@ -18147,9 +18980,6 @@ msgstr "Maven XML"
msgid "PackageRegistry|NPM"
msgstr "NPM"
-msgid "PackageRegistry|No upcoming issues"
-msgstr "没有å³å°†åˆ°æ¥çš„议题"
-
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -18171,8 +19001,8 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr "于%{datetime}å‘布到%{project}软件包注册表"
-msgid "PackageRegistry|PyPi"
-msgstr "PyPi"
+msgid "PackageRegistry|PyPI"
+msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr "æž„æˆ: %{recipe}"
@@ -18181,7 +19011,7 @@ msgid "PackageRegistry|Remove package"
msgstr "删除软件包"
msgid "PackageRegistry|Sorry, your filter produced no results"
-msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆè¿‡æ»¤å™¨çš„任何结果"
+msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆç­›é€‰å™¨çš„任何结果"
msgid "PackageRegistry|Source project located at %{link}"
msgstr "æºé¡¹ç›®ä½äºŽ%{link}"
@@ -18195,9 +19025,6 @@ 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 "获å–此软件包的详细信æ¯æ—¶å‡ºçŽ°é—®é¢˜ã€‚"
@@ -18205,7 +19032,7 @@ msgid "PackageRegistry|This NuGet package has no dependencies."
msgstr "这个Nuget包没有ä¾èµ–项目。"
msgid "PackageRegistry|To widen your search, change or remove the filters above."
-msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„过滤器。"
+msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„筛选器。"
msgid "PackageRegistry|Unable to fetch package version information."
msgstr "无法获å–软件包版本信æ¯ã€‚"
@@ -18213,9 +19040,6 @@ 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 "您将è¦åˆ é™¤%{name},此æ“作ä¸å¯é€†ï¼Œç¡®å®šç»§ç»­å—?"
@@ -18225,12 +19049,6 @@ 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|composer.json registry include"
-msgstr ""
-
-msgid "PackageRegistry|composer.json require package include"
-msgstr ""
-
msgid "PackageRegistry|npm command"
msgstr ""
@@ -18255,8 +19073,8 @@ msgstr "NPM"
msgid "PackageType|NuGet"
msgstr "NuGet"
-msgid "PackageType|PyPi"
-msgstr "PyPi"
+msgid "PackageType|PyPI"
+msgstr ""
msgid "Packages"
msgstr "软件包"
@@ -18447,8 +19265,8 @@ msgstr "æƒé™ä¸è¶³çš„用户将无法收到通知,也无法评论。"
msgid "People without permission will never get a notification."
msgstr "无相关æƒé™çš„用户将ä¸ä¼šæ”¶åˆ°é€šçŸ¥ã€‚"
-msgid "Percent of users"
-msgstr "用户百分比"
+msgid "Percent rollout must be an integer number between 0 and 100"
+msgstr ""
msgid "Percentage"
msgstr "百分比"
@@ -18459,9 +19277,6 @@ msgstr "执行高级选项,如改å˜è·¯å¾„ã€è½¬ç§»ã€å¯¼å‡ºæˆ–移除群组。
msgid "Perform common operations on GitLab project"
msgstr "在GitLab项目上执行常è§æ“作"
-msgid "Performance and resource management"
-msgstr "性能和资æºç®¡ç†"
-
msgid "Performance optimization"
msgstr "性能优化"
@@ -18564,6 +19379,9 @@ msgstr "æˆåŠŸçŽ‡ï¼š"
msgid "PipelineCharts|Successful:"
msgstr "æˆåŠŸï¼š"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "总计:"
@@ -18645,6 +19463,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr "CI é…置检查(CI Lint)"
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr "å­æµæ°´çº¿"
@@ -18663,6 +19484,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr "æµæ°´çº¿å…¥é—¨"
@@ -18693,6 +19517,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "项目缓存é‡ç½®æˆåŠŸã€‚"
@@ -18729,6 +19556,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -18957,6 +19790,9 @@ msgstr "请输入一个éžè´Ÿæ•°"
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr "请输入大于%{number}(æ¥è‡ªé¡¹ç›®è®¾ç½®)çš„æ•°å­—"
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr "请输入有效的数字"
@@ -18966,6 +19802,9 @@ msgstr "请输入或上传一个许å¯è¯ã€‚"
msgid "Please fill in a descriptive name for your group."
msgstr "请为您的群组填写æ述性å称。"
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr "请按照%{link_start}Let's Encrypt故障排除指å—%{link_end}æ¥é‡æ–°èŽ·å–加密è¯ä¹¦ã€‚"
@@ -18978,12 +19817,18 @@ msgstr "请将所有现有项目è¿ç§»åˆ°æ•£åˆ—存储,以é¿å…安全问题并
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "请注æ„,GitLabä¸æ供此应用程åºï¼Œæ‚¨åº”该在å…许访问之å‰éªŒè¯å…¶çœŸå®žæ€§ã€‚"
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr "请æä¾›å称"
msgid "Please provide a valid URL"
msgstr "请æ供有效的网å€"
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr "请æ供有效的电å­é‚®ä»¶åœ°å€ã€‚"
@@ -19018,7 +19863,7 @@ msgid "Please select and add a member"
msgstr "请选择并添加一个æˆå‘˜"
msgid "Please select at least one filter to see results"
-msgstr "请至少选择一个过滤器æ¥æŸ¥çœ‹ç»“æžœ"
+msgstr "请至少选择一个筛选器æ¥æŸ¥çœ‹ç»“æžœ"
msgid "Please set a new password before proceeding."
msgstr "请设置新密ç ä»¥ç»§ç»­ä¸‹ä¸€æ­¥ã€‚"
@@ -19188,9 +20033,6 @@ 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 "阻止用户在GitLab进行维护时进行写入æ“作。"
@@ -19884,8 +20726,8 @@ 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 deployment starts or finishes"
+msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
msgstr "åˆå¹¶è¯·æ±‚创建/æ›´æ–°/åˆå¹¶æ—¶äº‹ä»¶å°†è¢«è§¦å‘"
@@ -20187,6 +21029,9 @@ msgstr ".NET Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr "GitLab集群管ç†"
@@ -20241,6 +21086,9 @@ msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
msgstr "SalesforceDX"
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr "Serverless Framework/JS"
@@ -20697,6 +21545,9 @@ msgstr "分支"
msgid "ProtectedBranch|Code owner approval"
msgstr "代ç æ‰€æœ‰è€…批准"
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr "ä¿æŠ¤"
@@ -20823,6 +21674,9 @@ msgstr "Pumaè¿è¡Œçš„线程数大于1,并且å¯ç”¨äº†RuggedæœåŠ¡ã€‚在æŸäº›ç
msgid "Purchase more minutes"
msgstr "购买更多时间"
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr "推é€"
@@ -20934,6 +21788,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr "Rake任务帮助"
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr "æ¯åˆ†é’ŸåŽŸå§‹Blob请求速率é™åˆ¶"
@@ -21015,6 +21872,9 @@ msgstr "引用"
msgid "Refresh"
msgstr "刷新"
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "%d 秒åŽåˆ·æ–°ä»¥æ˜¾ç¤ºæ›´æ–°çŠ¶æ€..."
@@ -21058,9 +21918,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr "注册GitLabå¸æˆ·"
-
msgid "Register now"
msgstr "ç«‹å³æ³¨å†Œ"
@@ -21269,6 +22126,9 @@ msgstr "删除许å¯è¯"
msgid "Remove limit"
msgstr "去除é™åˆ¶"
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr "删除æˆå‘˜"
@@ -21389,6 +22249,9 @@ msgstr "删除截止日期."
msgid "Removes time estimate."
msgstr "删除时间估计。"
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr "删除该群组åŒæ—¶ä¼šåˆ é™¤æ‰€æœ‰å­é¡¹ç›®ï¼ŒåŒ…括已归档项目åŠå…¶ç›¸å…³èµ„æºã€‚"
@@ -21410,9 +22273,15 @@ msgstr "é‡æ–°å¼€å¯%{display_issuable_type}"
msgid "Reopen epic"
msgstr "é‡æ–°å¼€å¯å²è¯—"
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr "é‡æ–°æ‰“开里程碑"
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr "é‡æ–°æ‰“å¼€%{quick_action_target}"
@@ -21440,6 +22309,9 @@ msgstr "替æ¢å…‹éš†URL根地å€ã€‚"
msgid "Replication"
msgstr "å¤åˆ¶"
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr "å¤åˆ¶å·²å¯ç”¨"
@@ -21564,7 +22436,13 @@ msgstr "仓库"
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21576,6 +22454,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21594,6 +22484,9 @@ msgstr "仓库图"
msgid "Repository Settings"
msgstr "仓库设置"
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr "仓库检查"
@@ -21690,8 +22583,8 @@ msgstr "当ä¸å…许æ¥è‡ªé’©å­å’ŒæœåŠ¡çš„本地请求时,将å…许对本地
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
-msgstr "è¦æ±‚此群组中的所有用户都å¯ç”¨åŒé‡è®¤è¯"
+msgid "Require all users 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 "è¦æ±‚所有用户在访问GitLab时接å—æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–。"
@@ -21723,6 +22616,9 @@ msgstr "需求%{reference}å·²é‡æ–°æ‰“å¼€"
msgid "Requirement %{reference} has been updated"
msgstr "需求%{reference}已更新"
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr "需求标题ä¸èƒ½è¶…过%{limit}个字符。"
@@ -21921,6 +22817,9 @@ msgstr "查看应用"
msgid "Review App|View latest app"
msgstr "查看最新应用"
+msgid "Review requested from %{name}"
+msgstr ""
+
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
msgstr "查看在您的身份验è¯æ供商中é…ç½®æœåŠ¡æ供商的æµç¨‹ - 在这里,GitLab是“æœåŠ¡æ供商â€æˆ–“ä¾èµ–æ–¹â€ã€‚"
@@ -22072,6 +22971,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22099,6 +23004,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22168,6 +23076,9 @@ 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 "SSH主机密钥在此系统上ä¸å¯ç”¨ã€‚请使用%{ssh_keyscan}命令或与您的GitLab管ç†å‘˜è”系以获å–更多信æ¯ã€‚"
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr "SSH密钥用于在您的电脑和GitLab建立安全连接。"
@@ -22177,6 +23088,12 @@ msgstr "SSH公钥"
msgid "SSL Verification:"
msgstr "SSL验è¯ï¼š"
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr "星期六"
@@ -22192,6 +23109,9 @@ msgstr "ä¿å­˜ä¿®æ”¹"
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr "ä»ç„¶ä¿å­˜"
@@ -22216,9 +23136,6 @@ 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 variables"
-msgstr "ä¿å­˜å˜é‡"
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22228,6 +23145,9 @@ msgstr "ä¿å­˜ä¸­"
msgid "Saving project."
msgstr "正在ä¿å­˜é¡¹ç›®ã€‚"
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "新建æµæ°´çº¿è®¡åˆ’"
@@ -22267,6 +23187,9 @@ msgstr "范围"
msgid "Scopes can't be blank"
msgstr "范围ä¸èƒ½ä¸ºç©º"
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22297,8 +23220,8 @@ msgstr "æœç´¢"
msgid "Search Jira issues"
msgstr "æœç´¢Jira议题"
-msgid "Search Milestones"
-msgstr "æœç´¢é‡Œç¨‹ç¢‘"
+msgid "Search a group"
+msgstr ""
msgid "Search an environment spec"
msgstr "æœç´¢çŽ¯å¢ƒè§„则"
@@ -22354,9 +23277,6 @@ msgstr "æœç´¢æ­¤æ–‡æœ¬"
msgid "Search forks"
msgstr "æœç´¢æ´¾ç”Ÿ"
-msgid "Search groups"
-msgstr "æœç´¢ç¾¤ç»„"
-
msgid "Search merge requests"
msgstr "æœç´¢åˆå¹¶è¯·æ±‚"
@@ -22364,10 +23284,10 @@ msgid "Search milestones"
msgstr "æœç´¢é‡Œç¨‹ç¢‘"
msgid "Search or filter results..."
-msgstr "æœç´¢æˆ–过滤结果......"
+msgstr "æœç´¢æˆ–筛选结果......"
msgid "Search or filter results…"
-msgstr "æœç´¢æˆ–过滤结果…"
+msgstr "æœç´¢æˆ–筛选结果…"
msgid "Search or jump to…"
msgstr "æœç´¢æˆ–转到..."
@@ -22438,9 +23358,6 @@ msgstr "显示%{term_element}的 %{from} - %{to}/ %{count} %{scope} "
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for%{term_element} in your personal and project snippets"
msgstr "在个人和项目代ç ç‰‡æ®µä¸­æ˜¾ç¤ºæœç´¢%{term_element}结果的%{count}项%{scope}里的第%{from}项 - 第%{to}项"
-msgid "SearchResults|We couldn't find any %{scope} matching %{term}"
-msgstr "找ä¸åˆ°ä»»ä½•åŒ¹é…%{term}çš„%{scope} "
-
msgid "SearchResults|code result"
msgid_plural "SearchResults|code results"
msgstr[0] "代ç ç»“æžœ"
@@ -22494,7 +23411,7 @@ msgstr "座ä½é“¾æŽ¥"
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr "座ä½é“¾æŽ¥å·²ç¦ç”¨ï¼Œæ— æ³•é€šè¿‡æ­¤è¡¨å•è¿›è¡Œé…置。"
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22539,10 +23456,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22671,6 +23588,9 @@ msgstr "获å–æ¼æ´žæ•°é‡æ—¶å‡ºé”™ã€‚请检查您的网络连接,然åŽé‡è¯•
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr "获å–æ¼æ´žåˆ—表时出错。请检查您的网络连接,然åŽé‡è¯•ã€‚"
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr "误报"
@@ -22734,6 +23654,12 @@ msgstr "安全仪表æ¿"
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr "安全报告åªèƒ½ç”±æŽˆæƒçš„用户访问。"
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr "请使用上é¢çš„项目æœç´¢å­—段æ¥é€‰æ‹©è¦æ·»åŠ çš„项目。"
@@ -22744,7 +23670,7 @@ msgid "SecurityReports|Severity"
msgstr "严é‡ç¨‹åº¦"
msgid "SecurityReports|Sorry, your filter produced no results"
-msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆè¿‡æ»¤å™¨çš„任何结果"
+msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆç­›é€‰å™¨çš„任何结果"
msgid "SecurityReports|Status"
msgstr "状æ€"
@@ -22773,6 +23699,10 @@ msgstr "创建åˆå¹¶è¯·æ±‚时出错。"
msgid "SecurityReports|There was an error deleting the comment."
msgstr "删除评论时出错。"
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr "忽略æ¼æ´žæ—¶å‡ºé”™ã€‚"
@@ -22789,7 +23719,7 @@ 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}: %{errorMessage}"
msgstr ""
@@ -22953,6 +23883,9 @@ msgstr "选择è¦å¯¼å…¥çš„项目。"
msgid "Select required regulatory standard"
msgstr "选择所需的法规标准"
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr "选择è¦å¤åˆ¶çš„分片"
@@ -22968,7 +23901,7 @@ msgstr "选择开始日期"
msgid "Select status"
msgstr "选择状æ€"
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -22983,9 +23916,6 @@ msgstr "选择当å‰é¡¹ç›®çš„默认分支。除éžå¦è¡ŒæŒ‡å®šï¼Œå¦åˆ™æ‰€æœ‰åˆ
msgid "Select the custom project template source group."
msgstr "选择自定义项目模æ¿æºç¾¤ç»„。"
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr "选择时区"
@@ -23079,6 +24009,9 @@ msgstr "用逗å·åˆ†éš”主题。"
msgid "September"
msgstr "9月"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr "与"
@@ -23193,6 +24126,9 @@ msgstr "æœåŠ¡æ¨¡æ¿"
msgid "Service URL"
msgstr "æœåŠ¡ URL"
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr "会è¯æŒç»­æ—¶é—´(分钟)"
@@ -23328,6 +24264,9 @@ msgstr "设置新密ç "
msgid "Set up pipeline subscriptions for this project."
msgstr "为此项目设置æµæ°´çº¿è®¢é˜…。"
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "设置项目以自动推é€å’Œ/或从å¦ä¸€ä¸ªä»“库中æå–更改。分支,标签和æ交将自动åŒæ­¥ã€‚"
@@ -23433,6 +24372,15 @@ msgstr "共享Runner"
msgid "Shared projects"
msgstr "分享项目"
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr "共享Runner帮助链接"
@@ -23451,9 +24399,15 @@ msgstr "Sherlock事物"
msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
msgstr "如果您一旦丢失手机或无法访问一次性密ç å¯†ä¿ï¼Œæ‚¨å¯ä»¥ä½¿ç”¨æ¢å¤ç æ¥é‡æ–°èŽ·å¾—您的å¸æˆ·è®¿é—®æƒé™ã€‚æ¯ä¸ªæ¢å¤ç ä»…å¯ä½¿ç”¨ä¸€æ¬¡ã€‚请将它们ä¿å­˜åœ¨å®‰å…¨çš„地方,å¦åˆ™ä¸¢å¤±åŽä½ %{b_start}å°†%{b_end}无法访问您的å¸æˆ·ã€‚"
+msgid "Show Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr "显示所有活动"
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr "显示所有æˆå‘˜"
@@ -23594,6 +24548,9 @@ msgstr "登录/注册"
msgid "Sign in to \"%{group_name}\""
msgstr "登录到 \"%{group_name}\""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr "使用智能å¡ç™»å½•"
@@ -23621,6 +24578,9 @@ msgstr "注册æˆåŠŸï¼è¯·ç¡®è®¤æ‚¨çš„电å­é‚®ä»¶ä»¥ç™»å½•ã€‚"
msgid "Sign-in restrictions"
msgstr "登录é™åˆ¶"
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr "注册é™åˆ¶"
@@ -23630,9 +24590,6 @@ msgstr "å字太长(最多%{max_length}字符)。"
msgid "SignUp|Last Name is too long (maximum is %{max_length} characters)."
msgstr "姓æ°å¤ªé•¿(最多%{max_length}字符)。"
-msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
-msgstr "å称太长(最大为%{max_length}字符)。"
-
msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
msgstr "用户å太长(最大为%{max_length}字符)。"
@@ -23642,6 +24599,9 @@ msgstr "用户å太短(最短为%{min_length}字符)。"
msgid "Signed in"
msgstr "已登录"
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr "使用%{authentication}进行身份验è¯"
@@ -23753,27 +24713,18 @@ msgstr "没有è¦æ˜¾ç¤ºçš„代ç ç‰‡æ®µã€‚"
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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"
-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 "å¯é€‰æ·»åŠ æ述你的代ç ç‰‡æ®µåšä»€ä¹ˆæˆ–如何使用它…"
@@ -23787,7 +24738,7 @@ msgid "Some changes are not shown"
msgstr ""
msgid "Some child epics may be hidden due to applied filters"
-msgstr "æŸäº›å­å²è¯—å¯èƒ½ç”±äºŽåº”用过滤器而被éšè—"
+msgstr "æŸäº›å­å²è¯—å¯èƒ½ç”±äºŽåº”用筛选器而被éšè—"
msgid "Some common domains are not allowed. %{read_more_link}."
msgstr "æŸäº›å¸¸è§åŸŸåä¸è¢«å…许。 %{read_more_link}"
@@ -23988,7 +24939,7 @@ msgid "Sorry, you have exceeded the maximum browsable page number. Please use th
msgstr "对ä¸èµ·ï¼Œæ‚¨å·²ç»è¶…过了最大å¯æµè§ˆçš„页é¢æ•°ã€‚请使用APIæ¥è¿›ä¸€æ­¥èŽ·å–æ•°æ®ã€‚"
msgid "Sorry, your filter produced no results"
-msgstr "对ä¸èµ·ï¼Œæ— ç¬¦åˆè¿‡æ»¤å™¨çš„结果"
+msgstr "对ä¸èµ·ï¼Œæ— ç¬¦åˆç­›é€‰å™¨çš„结果"
msgid "Sort by"
msgstr "排åº"
@@ -24008,6 +24959,9 @@ msgstr "访问级别,å‡åºæŽ’列"
msgid "SortOptions|Access level, descending"
msgstr "访问级别,é™åºæŽ’列"
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr "创建日期"
@@ -24116,6 +25070,9 @@ msgstr "最近登录"
msgid "SortOptions|Recently starred"
msgstr "最近星标"
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr "大å°"
@@ -24158,9 +25115,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "æºä»£ç "
-
msgid "Source code (%{fileExtension})"
msgstr "æºä»£ç (%{fileExtension})"
@@ -24236,9 +25190,6 @@ msgstr "指定电å­é‚®ä»¶åœ°å€æ­£åˆ™è¡¨è¾¾å¼æ¨¡å¼ä»¥æ ‡è¯†é»˜è®¤å†…部用户
msgid "Specify the following URL during the Runner setup:"
msgstr "在 Runner 设置时指定以下 URL:"
-msgid "Speed up your DevOps%{br_tag}with GitLab"
-msgstr "使用GitLab%{br_tag}加速DevOps"
-
msgid "Squash commit message"
msgstr "压缩æ交消æ¯"
@@ -24302,6 +25253,9 @@ msgstr "星标"
msgid "Start Date"
msgstr "开始时间"
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr "å¯åŠ¨Web终端"
@@ -24324,7 +25278,7 @@ msgid "Start and due date"
msgstr "开始和截止日期"
msgid "Start by choosing a group to start exploring the merge requests in that group. You can then proceed to filter by projects, labels, milestones and authors."
-msgstr "首先选择一个群组以开始æµè§ˆè¯¥ç¾¤ç»„中的åˆå¹¶è¯·æ±‚。然åŽæ‚¨å¯ä»¥æŒ‰é¡¹ç›®ã€æ ‡è®°ã€é‡Œç¨‹ç¢‘和作者进行过滤。"
+msgstr "首先选择一个群组以开始æµè§ˆè¯¥ç¾¤ç»„中的åˆå¹¶è¯·æ±‚。然åŽæ‚¨å¯ä»¥æŒ‰é¡¹ç›®ã€æ ‡è®°ã€é‡Œç¨‹ç¢‘和作者进行筛选。"
msgid "Start cleanup"
msgstr "开始清ç†"
@@ -24458,6 +25412,9 @@ msgstr "统计"
msgid "Status"
msgstr "状æ€"
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr "状æ€:"
@@ -24587,6 +25544,9 @@ msgstr "垃圾信æ¯ä¸¾æŠ¥"
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr "æ交å馈"
@@ -24602,6 +25562,9 @@ msgstr "æ交æœç´¢"
msgid "Submit the current review."
msgstr "æ交当å‰è¯„审。"
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr "å·²æ交当å‰è¯„审。"
@@ -24644,6 +25607,12 @@ msgstr "订阅已æˆåŠŸåˆ›å»ºã€‚"
msgid "Subscription successfully deleted."
msgstr "订阅已æˆåŠŸåˆ é™¤ã€‚"
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr "è´¦å•"
@@ -24728,6 +25697,9 @@ msgstr "å·²æˆåŠŸ"
msgid "Successfully activated"
msgstr "å·²æˆåŠŸæ¿€æ´»"
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "æˆåŠŸç¦ç”¨"
@@ -24749,6 +25721,9 @@ msgstr "æˆåŠŸåˆ é™¤ç”µå­é‚®ä»¶ã€‚"
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr "æµæ°´çº¿å·²å®‰æŽ’è¿è¡Œã€‚请查看 %{pipelines_link_start}æµæ°´çº¿é¡µé¢%{pipelines_link_end}ä»¥äº†è§£è¯¦ç»†ä¿¡æ¯ ã€‚"
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr "æˆåŠŸè§£é™¤ç¦ç”¨"
@@ -24884,12 +25859,18 @@ msgstr ""
msgid "Sync information"
msgstr "åŒæ­¥ä¿¡æ¯"
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr "å·²åŒæ­¥"
msgid "Synchronization disabled"
msgstr "åŒæ­¥å·²ç¦ç”¨"
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr "系统"
@@ -24917,6 +25898,9 @@ msgstr "系统指标(自定义)"
msgid "System metrics (Kubernetes)"
msgstr "系统指标(Kubernetes)"
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr "目录"
@@ -24987,7 +25971,7 @@ msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "已存在分支å称,标记或æ交SHA"
msgid "TagsPage|Filter by tag name"
-msgstr "æ ¹æ®æ ‡ç­¾å称过滤"
+msgstr "æ ¹æ®æ ‡ç­¾å称筛选"
msgid "TagsPage|New Tag"
msgstr "新建标签"
@@ -25148,15 +26132,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25241,8 +26240,8 @@ msgstr "感谢购买ï¼"
msgid "Thanks! Don't show me this again"
msgstr "ä¸å†æ˜¾ç¤º"
-msgid "That's it, well done!%{celebrate}"
-msgstr "就这样,åšå¾—好ï¼%{celebrate}"
+msgid "That's it, well done!"
+msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "群组“%{group_path}â€å…许您使用SSO以登录å¸æˆ·"
@@ -25263,9 +26262,6 @@ 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 "CSV导出将在åŽå°åˆ›å»ºã€‚完æˆåŽï¼Œå®ƒå°†ä»¥é™„件形å¼å‘é€åˆ°%{strong_open}%{email}%{strong_close}。"
-msgid "The Git LFS objects will %{strong_open}not%{strong_close} be synced."
-msgstr "Git LFS对象将%{strong_open}ä¸ä¼š%{strong_close}被åŒæ­¥ã€‚"
-
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr "Jira用户%{jiraDisplayName}将映射到的GitLab用户"
@@ -25278,9 +26274,15 @@ msgstr "议题跟踪用于管ç†éœ€æ±‚改进或者解决的问题。请注册或
msgid "The Prometheus server responded with \"bad request\". Please check your queries are correct and are supported in your Prometheus version. %{documentationLink}"
msgstr "PrometheusæœåŠ¡å™¨ä»¥â€œé”™è¯¯è¯·æ±‚â€å“应。请检查您的查询是å¦æ­£ç¡®ï¼Œå¹¶ä¸”当å‰çš„Prometheus版本支æŒã€‚ %{documentationLink}"
+msgid "The Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr "在主节点上定义的URL,次è¦èŠ‚点应使用该URL与其è”系。"
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr "用于连接到Elasticsearchçš„URL。使用逗å·åˆ†éš”的列表æ¥æ”¯æŒç¾¤é›†(例如,“http://localhost:9200, http://localhost:9201â€)。"
@@ -25377,6 +26379,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "以下项目将ä¸ä¼šè¢«å¯¼å‡ºï¼š"
@@ -25399,8 +26407,8 @@ 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 internal projects can be viewed by any logged in user except external users."
+msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
msgstr "群组和任何公共项目å¯ä»¥åœ¨æ²¡æœ‰ä»»ä½•èº«ä»½éªŒè¯çš„情况下查看。"
@@ -25510,8 +26518,8 @@ msgstr "计划阶段概述了从议题添加到日程到推é€é¦–次æ交的时
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr "æ供客户端è¯ä¹¦æ—¶ä½¿ç”¨çš„ç§é’¥ã€‚该值被加密存储。"
-msgid "The project can be accessed by any logged in user."
-msgstr "该项目å…许所有已登录到当å‰GitLabæœåŠ¡å™¨çš„用户访问。"
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr "任何登录的用户都å¯ä»¥è®¿é—®è¯¥é¡¹ç›®ã€‚"
@@ -25570,6 +26578,9 @@ msgstr "审阅阶段概述了从创建åˆå¹¶è¯·æ±‚到被åˆå¹¶çš„时间。当创
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "路线图显示了 å²è¯— 沿ç€æ—¶é—´çº¿çš„进展情况"
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr "计划è¿è¡Œæ—¶é—´å¿…须在将æ¥ï¼"
@@ -25582,8 +26593,8 @@ msgstr "该代ç ç‰‡æ®µä»…对我å¯è§ã€‚"
msgid "The snippet is visible only to project members."
msgstr "该代ç ç‰‡æ®µä»…对项目æˆå‘˜å¯è§ã€‚"
-msgid "The snippet is visible to any logged in user."
-msgstr "任何登录用户都å¯ä»¥çœ‹åˆ°è¯¥ä»£ç ç‰‡æ®µã€‚"
+msgid "The snippet is visible to any logged in user except external users."
+msgstr ""
msgid "The specified tab is invalid, please select another"
msgstr "指定标签页无效,请选择å¦ä¸€ä¸ª"
@@ -25621,6 +26632,9 @@ msgstr "用户映射是一个JSON文档,将å‚与项目的Google Code用户映
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "用户映射是å‚与项目的 FogBugz 用户的电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å将被导入 GitLab çš„æ–¹å¼ã€‚您å¯ä»¥é€šè¿‡ä»¥ä¸‹è¡¨æ ¼æ¥ä¿®æ”¹æ˜ å°„关系。"
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr "您正在å°è¯•å†»ç»“的用户在过去%{minimum_inactive_days}天一直处于活动状æ€ï¼Œå› æ­¤æ— æ³•å†»ç»“。"
@@ -25729,6 +26743,9 @@ msgstr "ç£ç›˜ä¸Šå·²å­˜åœ¨å…·æœ‰è¯¥å称的仓库"
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr "没有å¯ç”¨æ•°æ®ã€‚请更改选择。"
@@ -25924,6 +26941,9 @@ msgstr "reCAPTCHA 验è¯é”™è¯¯ã€‚请å†æ¬¡éªŒè¯ reCAPTCHA。"
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr "这些现有的议题具有类似的标题。在那里评论å¯èƒ½æ›´å¥½ï¼Œè€Œä¸æ˜¯åˆ›å»ºå¦ä¸€ä¸ªç±»ä¼¼çš„问题。"
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr "这些é…置于父群组的å˜é‡ï¼Œå¯ä»¥å’Œé¡¹ç›®å˜é‡ä¸€èµ·ç”¨äºŽå½“å‰é¡¹ç›®ã€‚"
@@ -25975,7 +26995,7 @@ msgstr "æ­¤æ“作å¯èƒ½å¯¼è‡´æ•°æ®ä¸¢å¤±ã€‚为防止æ„外,我们会è¦æ±‚您
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -25999,9 +27019,15 @@ msgstr "这个应用程åºæ˜¯ç”± %{link_to_owner} 创建的。"
msgid "This application will be able to:"
msgstr "此应用程åºå°†å¯ä»¥ï¼š"
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
msgstr "此附件已被截断,以é¿å…超过最大å…许的附件大å°15MB。总计%{issues_count}个议题中的%{written_count}的个议题包å«äºŽå…¶ä¸­ã€‚请考虑选择较少的议题é‡æ–°å¯¼å‡ºã€‚"
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr "该阻塞为自我引用"
@@ -26134,6 +27160,9 @@ msgstr "这是已登录到您å¸æˆ·çš„设备列表。您å¯ä»¥åˆ é™¤ä»»ä½•æ‚¨æ— 
msgid "This is a security log of important events involving your account."
msgstr "这是一个涉åŠæ‚¨çš„å¸æˆ·é‡è¦äº‹ä»¶çš„安全日志。"
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr "此数字为自许å¯è¯å¯åŠ¨ä»¥æ¥ç”¨æˆ·æ•°ç›®çš„最高值。"
@@ -26143,11 +27172,14 @@ msgstr "此数目为当å‰æ´»è·ƒç”¨æˆ·çš„æ•°é‡ï¼Œ 也是更新许å¯è¯æ—¶éœ€è¦
msgid "This is your current session"
msgstr "这是您当å‰çš„会è¯"
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr "此议题目å‰è¢«ä»¥ä¸‹è®®é¢˜é˜»æ­¢ï¼š %{issues}。"
msgid "This issue is in a child epic of the filtered epic"
-msgstr "此议题在过滤å²è¯—çš„å­å²è¯—中"
+msgstr "此议题在筛选å²è¯—çš„å­å²è¯—中"
msgid "This job depends on other jobs with expired/erased artifacts: %{invalid_dependencies}"
msgstr "该作业ä¾èµ–于其他产物已过期/已删除的作业:%{invalid_dependencies}"
@@ -26695,6 +27727,12 @@ msgstr "刚刚"
msgid "Timeago|right now"
msgstr "ç«‹å³"
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr "超时"
@@ -26727,8 +27765,8 @@ 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 "è¦%{link_to_help}到您的域å,请将上述密钥添加到DNSé…置中的TXT记录。"
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
+msgstr ""
msgid "To Do"
msgstr "待处ç†"
@@ -26778,8 +27816,8 @@ msgstr "首先,请您输入您的 Gitea æœåŠ¡å™¨åœ°å€å’Œä¸€ä¸ª %{link_to_per
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
+msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "è¦å¯¼å…¥SVN仓库,请查看 %{svn_link}。"
@@ -26860,10 +27898,10 @@ msgid "To view the roadmap, add a start or due date to one of your epics in this
msgstr "如需查看路线图,请将计划的开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ª å²è¯—。在月视图中,åªæ˜¾ç¤ºä¸Šä¸ªæœˆï¼Œæœ¬æœˆä»¥åŠæŽ¥ä¸‹æ¥5个月的 å²è¯—."
msgid "To widen your search, change or remove filters above"
-msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„过滤器"
+msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„筛选器"
msgid "To widen your search, change or remove filters."
-msgstr "需è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–移除过滤æ¡ä»¶ã€‚"
+msgstr "需è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–移除筛选æ¡ä»¶ã€‚"
msgid "To-Do"
msgstr "待办事项"
@@ -26907,6 +27945,9 @@ msgstr "切æ¢è¡¨æƒ…符å·èµžèµ"
msgid "Toggle navigation"
msgstr "切æ¢å¯¼èˆª"
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "切æ¢è¾¹æ "
@@ -26979,18 +28020,21 @@ msgstr "总内存 (GB)"
msgid "Total test time for all commits/merges"
msgstr "所有æ交和åˆå¹¶çš„总测试时间"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr "总æƒé‡"
msgid "Total: %{total}"
msgstr "总计:%{total}"
+msgid "TotalMilestonesIndicator|1000+"
+msgstr ""
+
msgid "TotalRefCountIndicator|1000+"
msgstr "1000+"
-msgid "Trace"
-msgstr "跟踪"
-
msgid "Tracing"
msgstr "跟踪"
@@ -27145,7 +28189,7 @@ msgid "Try all GitLab has to offer for 30 days."
msgstr "30天内体验GitLab的所有功能。"
msgid "Try changing or removing filters."
-msgstr "请å°è¯•æ›´æ”¹æˆ–删除过滤器。"
+msgstr "请å°è¯•æ›´æ”¹æˆ–删除筛选器。"
msgid "Try to fork again"
msgstr "å°è¯•å†æ¬¡æ´¾ç”Ÿ"
@@ -27165,6 +28209,9 @@ msgstr "å°è¯•ä¸Žæ‚¨çš„设备通信。请将其æ’入并立å³æŒ‰ä¸‹ä¸Šçš„按钮
msgid "Tuesday"
msgstr "星期二"
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr "关闭"
@@ -27315,6 +28362,9 @@ msgstr "无法ä¿å­˜è¿­ä»£ã€‚请é‡è¯•"
msgid "Unable to save your changes. Please try again."
msgstr "无法ä¿å­˜æ‚¨çš„更改。请é‡è¯•ã€‚"
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr "无法安排æµæ°´çº¿ç«‹å³è¿è¡Œ"
@@ -27540,6 +28590,9 @@ msgstr "更新迭代"
msgid "Update now"
msgstr "ç«‹å³æ›´æ–°"
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr "æ›´æ–°å˜é‡"
@@ -27678,11 +28731,14 @@ msgstr "使用情况统计"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr "%{help_link_start}共享Runner%{help_link_end}å·²ç¦ç”¨ï¼Œæ‰€ä»¥æµæ°´çº¿ä½¿ç”¨æ²¡æœ‰è®¾ç½®é™åˆ¶"
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "产物"
-msgid "UsageQuota|Build Artifacts"
-msgstr "构建产物"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
+msgstr ""
msgid "UsageQuota|Buy additional minutes"
msgstr "è´­ä¹°é¢å¤–分钟数"
@@ -27708,6 +28764,9 @@ msgstr "æµæ°´çº¿"
msgid "UsageQuota|Purchase more storage"
msgstr "购买更多存储空间"
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr "仓库"
@@ -27720,9 +28779,36 @@ msgstr "代ç ç‰‡æ®µ"
msgid "UsageQuota|Storage"
msgstr "存储"
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "此命å空间没有使用共享Runner的项目"
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr "æ— é™"
@@ -27744,15 +28830,27 @@ msgstr "使用é…é¢å¸®åŠ©é“¾æŽ¥"
msgid "UsageQuota|Usage since"
msgstr "使用é‡è‡ª"
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr "Wiki"
msgid "UsageQuota|Wikis"
msgstr "Wiki"
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr "您已使用: %{usage} %{limit}"
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ",您命å空间存储上é™æ€»è®¡%{formattedLimit}"
@@ -27807,11 +28905,8 @@ msgstr "用户 %{current_user_username} 已开始使用%{username}的身份"
msgid "User %{username} was successfully removed."
msgstr "用户 %{username} å·²æˆåŠŸåˆ é™¤ã€‚"
-msgid "User IDs"
-msgstr "用户ID"
-
-msgid "User List"
-msgstr "用户列表"
+msgid "User ID"
+msgstr ""
msgid "User OAuth applications"
msgstr "用户的 OAuth 应用程åº"
@@ -27930,6 +29025,9 @@ msgstr "已报告滥用"
msgid "UserProfile|Blocked user"
msgstr "å·²ç¦ç”¨ç”¨æˆ·"
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr "å‚与贡献的项目"
@@ -28026,9 +29124,6 @@ msgstr "用户å已被使用。"
msgid "Username is available."
msgstr "用户åå¯ç”¨ã€‚"
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr "用户å太长 (最大为 %{max_length} 字符)。"
-
msgid "Username or email"
msgstr "用户å或邮箱"
@@ -28182,6 +29277,12 @@ msgstr ""
msgid "View Documentation"
msgstr "查看文档"
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr "查看所有议题"
@@ -28487,8 +29588,14 @@ msgstr "类型"
msgid "Vulnerability|Comments"
msgstr "注释"
-msgid "Vulnerability|Crash Address"
-msgstr "崩溃地å€"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
+msgstr ""
msgid "Vulnerability|Description"
msgstr "说明"
@@ -28571,6 +29678,15 @@ msgstr "我们无法确定删除å²è¯—的路径"
msgid "We could not determine the path to remove the issue"
msgstr "我们无法确定删除议题的路径"
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr "无法连接PrometheusæœåŠ¡å™¨ã€‚æœåŠ¡å™¨ä¸å†å­˜åœ¨ï¼Œæˆ–者é…置信æ¯éœ€è¦æ›´æ–°ã€‚"
@@ -28667,6 +29783,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28691,13 +29810,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28766,15 +29888,15 @@ msgstr "欢迎使用GitLab,%{first_name}ï¼"
msgid "Welcome to the guided GitLab tour"
msgstr "欢迎æ¥åˆ°GitLab导览"
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr "您正在æœç´¢ä»€ä¹ˆï¼Ÿ"
msgid "What describes you best?"
msgstr "如何形容您最åˆé€‚?"
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28787,7 +29909,7 @@ msgstr "当部署作业æˆåŠŸæ—¶ï¼Œè·³è¿‡ä»åœ¨ç­‰å¾…的旧部署作业"
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "当Runner被é”定时,ä¸èƒ½å°†å…¶åˆ†é…给其他项目"
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29028,12 +30150,12 @@ msgstr "正在进行中(开放和未分é…)"
msgid "Work in progress Limit"
msgstr "“进行中â€é™åˆ¶"
-msgid "Workflow Help"
-msgstr "工作æµå¸®åŠ©"
-
msgid "Would you like to create a new branch?"
msgstr ""
+msgid "Would you like to try auto-generating a branch name?"
+msgstr ""
+
msgid "Write"
msgstr "编辑"
@@ -29124,6 +30246,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr "您无æƒæŽ¨é€åˆ°æ­¤åˆ†æ”¯ã€‚请创建一个新的分支或开å¯åˆå¹¶è¯·æ±‚。"
@@ -29145,6 +30270,9 @@ msgstr "当å‰æ­£åœ¨è®¿é—®åªè¯» GitLab 实例。"
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr "您收到此消æ¯æ˜¯å› ä¸ºæ‚¨æ˜¯ %{url} çš„GitLab管ç†å‘˜ã€‚"
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr "您正在å°è¯•ä¸Šä¼ éžå›¾ç‰‡æ–‡ä»¶ã€‚请上传.pngã€.jpgã€.jpegã€.gifã€.bmpã€.tiff或.ico。"
@@ -29157,12 +30285,12 @@ msgstr "您å¯ä»¥ %{linkStart}查看BLOB%{linkEnd} 代替。"
msgid "You can also create a project from the command line."
msgstr "您也å¯ä»¥é€šè¿‡å‘½ä»¤è¡Œæ¥åˆ›å»ºæ–°é¡¹ç›®ã€‚"
-msgid "You can also press &#8984;-Enter"
-msgstr "您也å¯ä»¥æŒ‰ &#8984;-Enter"
-
msgid "You can also press Ctrl-Enter"
msgstr "您也å¯ä»¥æŒ‰ Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr "å¯ä»¥é€šè¿‡ä¸ºæ ‡è®°è®¾ç½®æ˜Ÿæ ‡æ¥æ高其优先级。"
@@ -29175,6 +30303,15 @@ msgstr "您还å¯ä»¥æŒ‰ç…§ä»¥ä¸‹è¯´æ˜Žä»Žè®¡ç®—机中上传现有文件。"
msgid "You can always edit this later"
msgstr "您也å¯ä»¥ç¨åŽç¼–辑此选项。"
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr "您å¯ä»¥åœ¨%{pat_link_start}个人访问令牌%{pat_link_end}设置中创建新的令牌或检查现有的令牌。"
@@ -29194,7 +30331,7 @@ msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_p
msgstr "å¯ä»¥è½»æ¾åœ°åœ¨Kubernetes集群上安装Runner。 %{link_to_help_page}"
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
-msgstr "您å¯ä»¥é€šè¿‡å•å‡»å›¾è¡¨ä¸­çš„列æ¥æŒ‰â€œåˆå¹¶å¤©æ•°â€è¿›è¡Œè¿‡æ»¤ã€‚"
+msgstr "您å¯ä»¥é€šè¿‡å•å‡»å›¾è¡¨ä¸­çš„列æ¥æŒ‰â€œåˆå¹¶å¤©æ•°â€è¿›è¡Œç­›é€‰ã€‚"
msgid "You can find more information about GitLab subscriptions in %{subscriptions_doc_link}."
msgstr ""
@@ -29376,6 +30513,9 @@ msgstr "你已被授予访问%{title}%{name}çš„%{member_human_access}æƒé™ã€‚"
msgid "You have been invited"
msgstr "您已被邀请"
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr "您已å–消订阅该主题。"
@@ -29388,6 +30528,15 @@ msgstr "您已从该项目导入%{numberOfPreviousImports} 次。æ¯æ¬¡å¯¼å…¥éƒ½
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr "您没有足够的æƒé™ä¸ºè¿™ä¸ªè­¦æŠ¥åˆ›å»ºå¾…办事项"
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr "没有æƒé™"
@@ -29412,9 +30561,6 @@ msgstr "ä½ å·²ç»ä»Žâ€œ%{membershipable_human_name}†%{source_type}退出。"
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 be logged in to search across all of GitLab"
msgstr ""
@@ -29472,9 +30618,6 @@ msgstr "您需è¦ä¸Šä¼ GitLab项目导出文件(以.gz结尾)."
msgid "You need to upload a Google Takeout archive."
msgstr "您需è¦ä¸Šä¼ Google Takeout文件。"
-msgid "You reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
-msgstr "你已使用了%{usage_in_percent}çš„%{namespace_name}存储容é‡(已使用%{storage_limit}总计%{used_storage})"
-
msgid "You successfully declined the invitation"
msgstr ""
@@ -29577,20 +30720,23 @@ msgstr "您已ç»ä½¿ç”¨ä¸€æ¬¡å¯†ç éªŒè¯å™¨å¯ç”¨äº†åŒé‡è®¤è¯ã€‚如果您è¦
msgid "YouTube"
msgstr "YouTube"
+msgid "YouTube URL or ID"
+msgstr ""
+
msgid "Your %{host} account was signed in to from a new location"
msgstr "您在%{host}上的å¸æˆ·å·²ä»Žä¸€ä¸ªæ–°çš„ä½ç½®ç™»å½•"
msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
msgstr "您为%{strong}%{namespace_name}%{strong_close}的%{strong}%{plan_name}%{strong_close}订阅将于%{strong}%{expires_on}%{strong_close}到期。"
-msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not to be able to create issues or merge requests as well as many other features."
-msgstr "您的%{strong}%{plan_name}%{strong_close}订阅将于%{strong}%{expires_on}%{strong_close}到期。此åŽï¼Œæ‚¨å°†æ— æ³•åˆ›å»ºè®®é¢˜æˆ–åˆå¹¶è¯·æ±‚,åŒæ—¶ä¹Ÿæ— æ³•è®¿é—®å…¶ä»–众多功能。"
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
+msgstr ""
msgid "Your CSV export has started. It will be emailed to %{email} when complete."
msgstr "CSV导出已ç»å¼€å§‹ã€‚完æˆåŽå°†å‘é€ç”µå­é‚®ä»¶è‡³%{email}。"
-msgid "Your CSV export of %{issues_count} from project %{project_link} has been added to this email as an attachment."
-msgstr "您从项目%{project_link}导出包å«%{issues_count}çš„CSV文件已作为附件添加到此电å­é‚®ä»¶ä¸­ã€‚"
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
+msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
msgstr "您从项目%{project_name}(%{project_url})导出包å«%{written_count}çš„CSV文件已作为附件添加到此电å­é‚®ä»¶ä¸­ã€‚"
@@ -29619,6 +30765,9 @@ msgstr "您的群组"
msgid "Your License"
msgstr "您的许å¯è¯"
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr "您的个人访问令牌将在%{days_to_expire}天内过期。"
@@ -29634,6 +30783,9 @@ msgstr "您的项目动æ€"
msgid "Your Public Email will be displayed on your public profile."
msgstr "您的公共电å­é‚®ä»¶å°†åœ¨æ‚¨çš„公开信æ¯ä¸­æ˜¾ç¤ºã€‚"
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr "您的SSH密钥(%{count})"
@@ -29888,7 +31040,7 @@ msgid "attach a new file"
msgstr "添加新附件"
msgid "authored"
-msgstr "编写于"
+msgstr "编辑于"
msgid "blocks"
msgstr "阻止"
@@ -29899,9 +31051,6 @@ msgstr "分支å称"
msgid "by"
msgstr "æ¥è‡ª"
-msgid "by %{user}"
-msgstr "ç”±%{user}"
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30028,9 +31177,6 @@ msgstr "容器扫æå¯ä»¥æ£€æµ‹Dockeré•œåƒä¸­ä¸­å·²çŸ¥çš„安全æ¼æ´žã€‚"
msgid "ciReport|Coverage Fuzzing"
msgstr "Coverage Fuzzing"
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr "Coverage Fuzzing标题"
-
msgid "ciReport|Coverage fuzzing"
msgstr "Coverage Fuzzing"
@@ -30076,9 +31222,6 @@ msgstr "找到%{issuesWithCount}"
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 "负载性能测试指标:"
@@ -30161,6 +31304,9 @@ msgstr "查看完整报告"
msgid "closed issue"
msgstr "已关闭议题"
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr "评论"
@@ -30394,8 +31540,8 @@ msgstr "是无效的 IP 地å€èŒƒå›´"
msgid "is blocked by"
msgstr "已被阻止。阻止项为"
-msgid "is enabled."
-msgstr "å·²å¯ç”¨ã€‚"
+msgid "is forbidden by a top-level group"
+msgstr ""
msgid "is invalid because there is downstream lock"
msgstr "因下游é”定而无效"
@@ -30412,6 +31558,9 @@ msgstr "相关群组ä¸å«æ¨¡ç‰ˆ"
msgid "is not a valid X509 certificate."
msgstr "ä¸æ˜¯æœ‰æ•ˆçš„X509è¯ä¹¦ã€‚"
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr "ä¸è¢«å…许。请使用其他电å­é‚®ä»¶åœ°å€é‡è¯•ï¼Œæˆ–与您的GitLab管ç†å‘˜è”系。"
@@ -30430,6 +31579,9 @@ msgstr "为åªè¯»"
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr "太长(%{current_value})。最大值为%{max_size}。"
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr "太长(最多100个æ¡ç›®ï¼‰"
@@ -30466,6 +31618,9 @@ msgstr "它太大了"
msgid "jigsaw is not defined"
msgstr "拼图未定义"
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr "最åŽæ交:"
@@ -30527,6 +31682,9 @@ msgstr "metric_id必须是整个项目唯一的"
msgid "missing"
msgstr "丢失"
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr "最近的部署"
@@ -30996,9 +32154,6 @@ 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 "å¿«æ·æ“作"
@@ -31011,9 +32166,6 @@ msgstr "注册"
msgid "relates to"
msgstr "涉åŠåˆ°"
-msgid "released %{time}"
-msgstr "å‘布于%{time}"
-
msgid "remaining"
msgstr "剩余"
@@ -31090,6 +32242,9 @@ msgstr "显示较少"
msgid "sign in"
msgstr "登录"
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr "排åºï¼š"
@@ -31270,9 +32425,6 @@ msgstr "åˆå¹¶è¯·æ±‚已安排在æµæ°´çº¿æˆåŠŸåŽåˆå¹¶ã€‚åˆå¹¶äºº: "
msgid "wiki page"
msgstr "wiki页é¢"
-msgid "will be released %{time}"
-msgstr "å°†å‘布于%{time}"
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "å…± %{additions} æ¡æ–°å¢ž, %{deletions} æ¡åˆ é™¤."
@@ -31285,3 +32437,6 @@ msgstr "过期时间ä¿æŒä¸å˜äºŽ%{old_expiry}"
msgid "yaml invalid"
msgstr "yaml无效"
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 21add9cc170..352e25678c5 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-10-02 18:43\n"
+"PO-Revision-Date: 2020-11-03 22:43\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -162,6 +162,10 @@ msgid "%d failed"
msgid_plural "%d failed"
msgstr[0] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d 個已修復測試çµæžœ"
@@ -186,10 +190,6 @@ msgid "%d issue in this group"
msgid_plural "%d issues in this group"
msgstr[0] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "å·²é¸ %d 個議題"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -351,6 +351,14 @@ msgstr "éœ€è¦ %{count} 個由 %{name} 的批准"
msgid "%{count} files touched"
msgstr ""
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+
msgid "%{count} more"
msgstr "還有 %{count} 項"
@@ -389,6 +397,12 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -434,6 +448,12 @@ msgstr ""
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -560,9 +580,6 @@ 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 ""
@@ -655,7 +672,7 @@ msgstr[0] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -669,6 +686,9 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
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] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -876,9 +896,6 @@ msgstr ""
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr ""
-
msgid "(line: %{startLine})"
msgstr ""
@@ -916,6 +933,18 @@ msgstr[0] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -942,6 +971,9 @@ msgstr ""
msgid "- show less"
msgstr "顯示較少"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -951,13 +983,8 @@ msgstr ""
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "%{count}%{type} 個附加"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "%{count}%{type} 個變更"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1205,6 +1232,9 @@ msgstr "一個有存å–原始分支權é™çš„使用者,é¸æ“‡äº†æ­¤é …ç›®"
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1503,6 +1533,9 @@ msgstr "新增表格"
msgid "Add a task list"
msgstr ""
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
@@ -1656,7 +1689,7 @@ msgstr ""
msgid "Added %{label_references} %{label_text}."
msgstr ""
-msgid "Added a To Do."
+msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
@@ -1692,10 +1725,10 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a To Do."
+msgid "Adds a Zoom meeting"
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
@@ -1782,6 +1815,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1806,6 +1842,9 @@ msgstr "åœæ­¢ä»»å‹™å¤±æ•—"
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1920,6 +1959,21 @@ msgstr ""
msgid "AdminStatistics|Snippets"
msgstr ""
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -1929,6 +1983,12 @@ msgstr ""
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr "æ´»èº"
@@ -1941,12 +2001,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr "管ç†å“¡"
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr ""
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "å°éŽ–使用者"
@@ -2001,6 +2079,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr ""
@@ -2010,6 +2091,9 @@ msgstr ""
msgid "AdminUsers|Owned groups will be left"
msgstr ""
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr ""
@@ -2055,6 +2139,9 @@ msgstr ""
msgid "AdminUsers|The user will not receive any notifications"
msgstr ""
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "請輸入 %{projectName} 以進行確èª"
@@ -2079,6 +2166,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2088,6 +2178,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr ""
@@ -2103,22 +2196,22 @@ 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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2182,10 +2275,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2302,6 +2395,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2311,10 +2413,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2326,19 +2428,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2353,6 +2464,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2362,7 +2479,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2380,7 +2500,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2389,6 +2509,27 @@ msgstr ""
msgid "Alerts endpoint"
msgstr ""
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr ""
@@ -2455,9 +2596,6 @@ msgstr ""
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr "所有使用者"
-
msgid "All users must have a name."
msgstr ""
@@ -2482,6 +2620,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "容許本項目採用 Git LFS"
@@ -2503,6 +2644,9 @@ msgstr ""
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -2524,12 +2668,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
msgid "Allowed to fail"
msgstr ""
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "å…許您增加和管ç†Kuberneteså¢é›†ã€‚"
@@ -2578,6 +2728,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2590,9 +2743,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2620,9 +2779,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr "é è¦½ blob 檔案時發生錯誤"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "切æ›è¨‚閱通知時發生錯誤"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "更新議題權é‡æ™‚發生錯誤"
@@ -2710,9 +2875,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 ""
@@ -2785,9 +2947,6 @@ 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 ""
@@ -2818,9 +2977,6 @@ 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 ""
@@ -2845,6 +3001,9 @@ msgstr ""
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr ""
@@ -2869,9 +3028,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr "儲存指派人時發生錯誤"
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr "訂閱通知時出錯"
@@ -2887,6 +3043,9 @@ msgstr "å–消訂閱通知時出錯"
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3212,6 +3371,9 @@ msgstr ""
msgid "Archive project"
msgstr ""
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3459,6 +3621,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3701,7 +3866,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3722,6 +3908,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3740,6 +3929,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3797,9 +3989,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr "你確定è¦åˆªé™¤å¾½ç« å—Žï¼Ÿ"
@@ -3881,6 +4070,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -3965,6 +4160,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4016,12 +4223,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4040,6 +4256,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4052,6 +4271,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4196,6 +4418,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4232,9 +4457,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4265,7 +4502,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4448,6 +4685,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4859,6 +5099,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5042,9 +5285,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5063,9 +5303,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5174,6 +5411,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr "關閉里程碑"
@@ -5198,7 +5438,7 @@ msgstr "已關閉議題"
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5225,6 +5465,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5408,6 +5651,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5465,9 +5711,6 @@ 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 ""
@@ -5723,9 +5966,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5741,9 +5981,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5810,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5879,9 +6113,6 @@ 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 ""
@@ -5948,9 +6179,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6011,6 +6239,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6095,6 +6326,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6236,9 +6470,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6350,9 +6581,6 @@ 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 ""
@@ -6663,7 +6891,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6714,6 +6942,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6779,6 +7010,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7155,6 +7389,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7215,6 +7452,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7224,6 +7464,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7257,6 +7500,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7504,6 +7750,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7597,6 +7846,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7847,6 +8099,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -7904,6 +8159,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -7943,6 +8207,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -7964,6 +8234,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -7991,15 +8267,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8015,6 +8291,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8054,6 +8333,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8066,6 +8348,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8075,6 +8363,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8231,9 +8522,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8243,6 +8531,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8258,9 +8549,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8282,6 +8570,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8345,12 +8636,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8396,18 +8693,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8480,9 +8786,6 @@ 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 ""
@@ -8648,6 +8951,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8696,6 +9005,9 @@ msgstr "æè¿°"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8867,6 +9179,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -8918,7 +9251,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9066,6 +9399,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9075,6 +9411,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9096,6 +9435,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr "ä¸å†é¡¯ç¤º"
@@ -9123,9 +9465,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9294,15 +9633,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9375,6 +9723,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9516,6 +9867,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9543,7 +9900,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9588,6 +9957,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9615,7 +9987,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10377,12 +10752,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10413,6 +10794,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10488,6 +10872,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10590,6 +10977,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10653,6 +11043,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10665,6 +11058,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10801,6 +11197,18 @@ msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10831,6 +11239,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10882,6 +11293,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -10948,10 +11362,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -10966,6 +11383,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -10984,9 +11404,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11002,15 +11419,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11020,6 +11437,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "二月"
@@ -11077,12 +11497,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr "文件"
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11107,6 +11533,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11170,6 +11599,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11203,9 +11635,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11215,9 +11644,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11272,7 +11707,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11818,7 +12253,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11839,6 +12274,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11875,9 +12313,6 @@ 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 ""
@@ -11902,6 +12337,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12214,6 +12655,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12319,7 +12763,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12478,6 +12922,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12487,6 +12937,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12532,12 +12985,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12550,6 +13021,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12562,6 +13036,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12586,6 +13063,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -12993,6 +13473,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr "æ­·å²ç´€éŒ„"
@@ -13047,9 +13530,6 @@ 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 ""
@@ -13062,7 +13542,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13170,6 +13650,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13194,9 +13677,6 @@ 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 ""
@@ -13218,10 +13698,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13301,6 +13781,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13421,6 +13904,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13481,6 +13970,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13490,12 +13982,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13505,6 +14003,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13517,6 +14039,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13592,27 +14117,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13631,6 +14162,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13659,6 +14193,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13668,12 +14247,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13707,6 +14304,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13722,37 +14322,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13761,6 +14382,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "循環週期"
@@ -13785,9 +14409,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -13887,25 +14508,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -13953,6 +14574,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14001,6 +14676,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14217,6 +14895,9 @@ msgstr "一月"
msgid "January"
msgstr "一月"
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14472,6 +15153,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14490,6 +15174,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14619,9 +15309,6 @@ 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 ""
@@ -14647,9 +15334,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr "最新æµæ°´ç·š"
@@ -14683,6 +15367,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14716,6 +15403,9 @@ msgstr "最後更新"
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14761,6 +15451,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14836,6 +15529,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15368,9 +16064,6 @@ msgstr "三月"
msgid "March"
msgstr "三月"
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15389,6 +16082,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15422,9 +16118,6 @@ 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 ""
@@ -15434,7 +16127,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15446,6 +16139,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15509,6 +16205,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15629,6 +16328,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15656,15 +16361,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -15902,6 +16682,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16303,6 +17086,27 @@ msgstr "ç›®å‰è¨±å¯è­‰ç„¡æ³•ä½¿ç”¨é‡Œç¨‹ç¢‘列表"
msgid "Milestone lists show all issues from the selected milestone."
msgstr "里程碑列表將顯示所é¸é‡Œç¨‹ç¢‘的所有議題"
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16618,9 +17422,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16678,6 +17488,32 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -16933,6 +17769,9 @@ msgstr ""
msgid "New"
msgstr ""
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17396,6 +18235,9 @@ msgstr ""
msgid "None"
msgstr "ç„¡"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17426,9 +18268,6 @@ msgstr "數據ä¸è¶³"
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17663,6 +18502,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17708,9 +18550,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17720,9 +18559,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17841,19 +18677,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18027,6 +18857,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18123,7 +18956,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18147,9 +18980,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18171,7 +19001,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18195,9 +19025,6 @@ 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 ""
@@ -18213,9 +19040,6 @@ 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 ""
@@ -18225,12 +19049,6 @@ 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 ""
@@ -18255,7 +19073,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18447,7 +19265,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18459,9 +19277,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18564,6 +19379,9 @@ msgstr "æˆåŠŸçŽ‡ï¼š"
msgid "PipelineCharts|Successful:"
msgstr "æˆåŠŸï¼š"
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr "總計:"
@@ -18645,6 +19463,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18663,6 +19484,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18693,6 +19517,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18729,6 +19556,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -18957,6 +19790,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -18966,6 +19802,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -18978,12 +19817,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19188,9 +20033,6 @@ 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 ""
@@ -19884,7 +20726,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20187,6 +21029,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20241,6 +21086,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20697,6 +21545,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20823,6 +21674,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -20934,6 +21788,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21015,6 +21872,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21058,9 +21918,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21269,6 +22126,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21389,6 +22249,9 @@ msgstr "刪除截止日期"
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21410,9 +22273,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr "é‡æ–°é–‹å•Ÿé‡Œç¨‹ç¢‘"
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21440,6 +22309,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21564,7 +22436,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21576,6 +22454,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21594,6 +22484,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21690,7 +22583,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21723,6 +22616,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -21921,6 +22817,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22072,6 +22971,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22099,6 +23004,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22168,6 +23076,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22177,6 +23088,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr "星期六"
@@ -22192,6 +23109,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22216,9 +23136,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22228,6 +23145,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr "新建æµæ°´ç·šè¨ˆåŠƒ"
@@ -22267,6 +23187,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22297,7 +23220,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22354,9 +23277,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22438,9 +23358,6 @@ 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] ""
@@ -22494,7 +23411,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22539,10 +23456,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22671,6 +23588,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22734,6 +23654,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22773,6 +23699,10 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -22953,6 +23883,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -22968,7 +23901,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -22983,9 +23916,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23079,6 +24009,9 @@ msgstr ""
msgid "September"
msgstr "ä¹æœˆ"
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23193,6 +24126,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23328,6 +24264,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23433,6 +24372,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23451,9 +24399,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr "顯示所有活動"
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23594,6 +24548,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23621,6 +24578,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23630,9 +24590,6 @@ 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 ""
@@ -23642,6 +24599,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23753,27 +24713,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24008,6 +24959,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24116,6 +25070,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24158,9 +25115,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr "æºä»£ç¢¼"
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24236,9 +25190,6 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr "在 Runner 設置時指定以下 URL:"
-msgid "Speed up your DevOps%{br_tag}with GitLab"
-msgstr ""
-
msgid "Squash commit message"
msgstr ""
@@ -24302,6 +25253,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24458,6 +25412,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24587,6 +25544,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr "æ交æ„見"
@@ -24602,6 +25562,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24644,6 +25607,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24728,6 +25697,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24749,6 +25721,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -24884,12 +25859,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -24917,6 +25898,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25148,15 +26132,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25241,7 +26240,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25263,9 +26262,6 @@ 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 ""
@@ -25278,9 +26274,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25377,6 +26379,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25399,7 +26407,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25510,8 +26518,8 @@ msgstr "計劃階段概述了從議題添加到日程到推é€é¦–次æ交的時
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
-msgstr "該項目å…許已登錄的用戶訪å•ã€‚"
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
msgid "The project can be accessed by any user who is logged in."
msgstr ""
@@ -25570,6 +26578,9 @@ msgstr "評審階段概述了從創建åˆä½µè«‹æ±‚到åˆä½µçš„時間。當創建
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25582,7 +26593,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25621,6 +26632,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25729,6 +26743,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -25924,6 +26941,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -25975,7 +26995,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -25999,9 +27019,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26134,6 +27160,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26143,6 +27172,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26695,6 +27727,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26727,7 +27765,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26778,7 +27816,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -26907,6 +27945,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -26979,16 +28020,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr "所有æ交和åˆä½µçš„總測試時間"
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27165,6 +28209,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27315,6 +28362,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27540,6 +28590,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27678,10 +28731,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27708,6 +28764,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27720,9 +28779,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27744,15 +28830,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27807,10 +28905,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -27930,6 +29025,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr "è²¢ç»çš„專案"
@@ -28026,9 +29124,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28182,6 +29277,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28487,7 +29588,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28571,6 +29678,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28667,6 +29783,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28691,13 +29810,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28766,15 +29888,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28787,7 +29909,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29028,10 +30150,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29124,6 +30246,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29145,6 +30270,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29157,10 +30285,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29175,6 +30303,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29376,6 +30513,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29388,6 +30528,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29412,9 +30561,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29472,9 +30618,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29577,19 +30720,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29619,6 +30765,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29634,6 +30783,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -29899,9 +31051,6 @@ msgstr "分支å稱"
msgid "by"
msgstr ""
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30028,9 +31177,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30076,9 +31222,6 @@ 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 ""
@@ -30161,6 +31304,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30394,7 +31540,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30412,6 +31558,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30430,6 +31579,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30466,6 +31618,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30527,6 +31682,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -30996,9 +32154,6 @@ 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 "快速æ“作"
@@ -31011,9 +32166,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31090,6 +32242,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31270,9 +32425,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31285,3 +32437,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index ea50ffd67ff..4b083af584e 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-10-02 18:45\n"
+"PO-Revision-Date: 2020-11-03 22:45\n"
msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
msgstr ""
@@ -162,6 +162,10 @@ msgid "%d failed"
msgid_plural "%d failed"
msgstr[0] ""
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d 個確定的測試çµæžœ"
@@ -186,10 +190,6 @@ msgid "%d issue in this group"
msgid_plural "%d issues in this group"
msgstr[0] ""
-msgid "%d issue selected"
-msgid_plural "%d issues selected"
-msgstr[0] "å·²é¸å– %d 個議題"
-
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
@@ -351,6 +351,14 @@ msgstr "來自 %{name} 的 %{count} 個核准"
msgid "%{count} files touched"
msgstr "å·²é¸æ“‡ %{count} 個檔案"
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+
msgid "%{count} more"
msgstr "其餘 %{count} 項"
@@ -389,6 +397,12 @@ 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 "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
msgid "%{due_date} (Past due)"
msgstr ""
@@ -434,6 +448,12 @@ msgstr "%{group_name} 使用群組管ç†å¸³æˆ¶ã€‚您需è¦å»ºç«‹ä¸€å€‹æ–°çš„ Git
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
msgstr ""
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
msgid "%{host} sign-in from new location"
msgstr ""
@@ -560,9 +580,6 @@ 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 "%{name} åŒ…å« %{resultsString}"
@@ -655,7 +672,7 @@ msgstr[0] ""
msgid "%{reportType} %{status} detected no vulnerabilities."
msgstr ""
-msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
msgid "%{seconds}s"
@@ -669,6 +686,9 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
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] ""
+msgid "%{size} %{unit}"
+msgstr ""
+
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -876,9 +896,6 @@ msgstr "(檢查進度)"
msgid "(deleted)"
msgstr ""
-msgid "(external source)"
-msgstr "(外部資æº)"
-
msgid "(line: %{startLine})"
msgstr ""
@@ -916,6 +933,18 @@ msgstr[0] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
msgid "+%{tags} more"
msgstr ""
@@ -942,6 +971,9 @@ msgstr ""
msgid "- show less"
msgstr "- 顯示較少內容"
+msgid "."
+msgstr ""
+
msgid "0 bytes"
msgstr ""
@@ -951,13 +983,8 @@ msgstr "0 表示無é™åˆ¶"
msgid "0 for unlimited, only effective with remote storage enabled."
msgstr ""
-msgid "1 %{type} addition"
-msgid_plural "%{count} %{type} additions"
-msgstr[0] "%{count} 個%{type}加入"
-
-msgid "1 %{type} modification"
-msgid_plural "%{count} %{type} modifications"
-msgstr[0] "%{count} 個%{type}修改"
+msgid "0t1DgySidms"
+msgstr ""
msgid "1 Day"
msgid_plural "%d Days"
@@ -1205,6 +1232,9 @@ msgstr "有ä½å…·æœ‰ä¾†æºåˆ†æ”¯å¯«å…¥æ¬Šé™çš„使用者é¸æ“‡äº†æ­¤é¸é …"
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
msgstr ""
+msgid "API Fuzzing"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1503,6 +1533,9 @@ msgstr "加入表格"
msgid "Add a task list"
msgstr "加入作業列表"
+msgid "Add a to do"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "è¦åœ¨æ‰€æœ‰é›»å­éƒµä»¶åŠ å…¥çš„附加文字。長度ä¸èƒ½è¶…éŽ %{character_limit} å­—å…ƒ"
@@ -1656,8 +1689,8 @@ msgstr "已加入 %{epic_ref} 為å­å²è©©ã€‚"
msgid "Added %{label_references} %{label_text}."
msgstr "已加入 %{label_references} %{label_text}。"
-msgid "Added a To Do."
-msgstr "已加入待辦事項。"
+msgid "Added a to do."
+msgstr ""
msgid "Added an issue to an epic."
msgstr "å·²å‘å²è©©åŠ å…¥è­°é¡Œã€‚"
@@ -1692,12 +1725,12 @@ msgstr "加入 %{epic_ref} 作為å­å²è©©ã€‚"
msgid "Adds %{labels} %{label_text}."
msgstr "加入 %{labels}%{label_text}。"
-msgid "Adds a To Do."
-msgstr "加入待辦事項。"
-
msgid "Adds a Zoom meeting"
msgstr "加入 Zoom 會議"
+msgid "Adds a to do."
+msgstr ""
+
msgid "Adds an issue to an epic."
msgstr "å‘å²è©©åŠ å…¥è­°é¡Œã€‚"
@@ -1782,6 +1815,9 @@ msgstr ""
msgid "AdminArea|New user"
msgstr ""
+msgid "AdminArea|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
@@ -1806,6 +1842,9 @@ msgstr "åœæ­¢ä½œæ¥­å¤±æ•—"
msgid "AdminArea|Total users"
msgstr ""
+msgid "AdminArea|User cap"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1920,6 +1959,21 @@ msgstr "SSH 金鑰"
msgid "AdminStatistics|Snippets"
msgstr "程å¼ç¢¼ç‰‡æ®µ"
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
msgid "AdminUsers|2FA Disabled"
msgstr "未啟用兩步驟驗證"
@@ -1929,6 +1983,12 @@ msgstr "已啟用兩步驟驗證"
msgid "AdminUsers|Access"
msgstr ""
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
msgid "AdminUsers|Active"
msgstr "æ´»èº"
@@ -1941,12 +2001,30 @@ msgstr ""
msgid "AdminUsers|Admins"
msgstr "管ç†å“¡"
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
msgid "AdminUsers|Block"
msgstr "å°éŽ–"
+msgid "AdminUsers|Block this user"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "å°éŽ–使用者"
@@ -2001,6 +2079,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr "這就是你ï¼"
+msgid "AdminUsers|Log in"
+msgstr ""
+
msgid "AdminUsers|New user"
msgstr "新增使用者"
@@ -2010,6 +2091,9 @@ msgstr "未找到使用者"
msgid "AdminUsers|Owned groups will be left"
msgstr "將會ä¿ç•™æ“有的群組"
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
msgid "AdminUsers|Personal projects will be left"
msgstr "將會ä¿ç•™å€‹äººå°ˆæ¡ˆ"
@@ -2055,6 +2139,9 @@ msgstr "此使用者將無法使用斜線指令"
msgid "AdminUsers|The user will not receive any notifications"
msgstr "此使用者將ä¸æœƒæ”¶åˆ°ä»»ä½•é€šçŸ¥"
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "請輸入 %{projectName} 來確èª"
@@ -2079,6 +2166,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2088,6 +2178,9 @@ msgstr ""
msgid "Administration"
msgstr ""
+msgid "Adoption"
+msgstr ""
+
msgid "Advanced"
msgstr "進階"
@@ -2103,22 +2196,22 @@ msgstr ""
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "進階權é™ï¼Œå¤§åž‹æª”案儲存 (LFS) 和兩步驟èªè­‰è¨­å®šã€‚"
-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."
+msgid "After sign-out path"
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr ""
-msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
msgid "Alert"
@@ -2182,10 +2275,10 @@ msgstr ""
msgid "AlertManagement|High"
msgstr ""
-msgid "AlertManagement|Info"
+msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Issue"
+msgid "AlertManagement|Info"
msgstr ""
msgid "AlertManagement|Key"
@@ -2302,6 +2395,15 @@ msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
msgid "AlertSettings|API URL"
msgstr ""
@@ -2311,10 +2413,10 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr ""
-msgid "AlertSettings|Alert test payload"
+msgid "AlertSettings|Add new integrations"
msgstr ""
-msgid "AlertSettings|Alerts endpoint successfully activated."
+msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Authorization key"
@@ -2326,19 +2428,28 @@ msgstr ""
msgid "AlertSettings|Copy"
msgstr ""
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus"
msgstr ""
-msgid "AlertSettings|Generic"
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|HTTP endpoint"
+msgstr ""
+
+msgid "AlertSettings|Integration"
msgstr ""
-msgid "AlertSettings|Integrations"
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
msgid "AlertSettings|Opsgenie"
@@ -2353,6 +2464,12 @@ 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|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
msgid "AlertSettings|Test alert payload"
msgstr ""
@@ -2362,7 +2479,10 @@ 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"
+msgid "AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page."
+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."
@@ -2380,7 +2500,7 @@ 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."
+msgid "AlertSettings|Your integration was successfully updated."
msgstr ""
msgid "Alerts"
@@ -2389,6 +2509,27 @@ msgstr "警示"
msgid "Alerts endpoint"
msgstr "警示端點"
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|HTTP endpoint"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|Prometheus"
+msgstr ""
+
msgid "Algorithm"
msgstr "演算法"
@@ -2455,9 +2596,6 @@ msgstr "因為這個專案已開啟 %{linkStart}Auto DevOps%{linkEnd},已啟ç”
msgid "All threads resolved"
msgstr ""
-msgid "All users"
-msgstr "所有使用者"
-
msgid "All users must have a name."
msgstr "所有的使用者都必須具有å稱。"
@@ -2482,6 +2620,9 @@ msgstr ""
msgid "Allow owners to manually add users outside of LDAP"
msgstr ""
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
msgid "Allow projects within this group to use Git LFS"
msgstr "å…許該群組內的專案使用 Git LFS"
@@ -2503,6 +2644,9 @@ msgstr "å…許系統掛鉤å‘本機網路請求"
msgid "Allow requests to the local network from web hooks and services"
msgstr "å…許 Webhook åŠæœå‹™å‘本機網路請求"
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr "åŒæ™‚å…許此金鑰推é€åˆ°ç‰ˆæœ¬åº«å—Žï¼Ÿï¼ˆé è¨­åªæœ‰æ‹‰å–權é™ï¼‰"
@@ -2524,12 +2668,18 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed domains for sign-ups"
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "åªå…許頂層群組使用電å­éƒµä»¶ç¶²åŸŸé™åˆ¶"
msgid "Allowed to fail"
msgstr "å…許失敗"
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "讓你能加入åŠç®¡ç† Kubernetes å¢é›†ã€‚"
@@ -2578,6 +2728,9 @@ msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2590,9 +2743,15 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "空 GitLab 使用者欄ä½å°‡åœ¨æ‰€æœ‰è­°é¡ŒåŠç•™è¨€çš„æ述中加入 FogBugz 使用者的全å(例如「由 John Smithã€ï¼‰ã€‚其還會與專案建立者關è¯å’Œï¼æˆ–分é…這些議題或留言。"
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
msgid "An error has occurred"
msgstr "發生錯誤"
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -2620,9 +2779,15 @@ msgstr ""
msgid "An error occurred previewing the blob"
msgstr "é è¦½ blob 時發生錯誤"
+msgid "An error occurred when removing the label."
+msgstr ""
+
msgid "An error occurred when toggling the notification subscription"
msgstr "切æ›é€šçŸ¥è¨‚閱時發生錯誤"
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "更新議題權é‡æ™‚發生錯誤"
@@ -2710,9 +2875,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
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 "抓å–看æ¿åˆ—表時發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
@@ -2785,9 +2947,6 @@ 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 ""
@@ -2818,9 +2977,6 @@ 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 "建立請求時發生錯誤。"
@@ -2845,6 +3001,9 @@ msgstr "繪製廣播訊æ¯æ™‚發生錯誤"
msgid "An error occurred while rendering the editor"
msgstr ""
+msgid "An error occurred while rendering the linter"
+msgstr ""
+
msgid "An error occurred while reordering issues."
msgstr "é‡æ–°æŽ’åºè­°é¡Œæ™‚發生錯誤。"
@@ -2869,9 +3028,6 @@ msgstr "儲存 LDAP 覆蓋狀態時發生錯誤,請é‡è©¦ã€‚"
msgid "An error occurred while saving assignees"
msgstr "儲存å—託人時發生錯誤。"
-msgid "An error occurred while searching for milestones"
-msgstr ""
-
msgid "An error occurred while subscribing to notifications."
msgstr "訂閱通知時發生錯誤。"
@@ -2887,6 +3043,9 @@ msgstr "å–消訂閱通知時發生錯誤。"
msgid "An error occurred while updating approvers"
msgstr "更新核准者時發生錯誤"
+msgid "An error occurred while updating configuration."
+msgstr ""
+
msgid "An error occurred while updating labels."
msgstr ""
@@ -3212,6 +3371,9 @@ msgstr "歸檔作業"
msgid "Archive project"
msgstr "歸檔專案"
+msgid "Archive test case"
+msgstr ""
+
msgid "Archived"
msgstr ""
@@ -3459,6 +3621,9 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
+msgid "Assigned to %{name}"
+msgstr ""
+
msgid "Assigned to me"
msgstr ""
@@ -3701,7 +3866,28 @@ 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}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
msgid "Autocomplete"
@@ -3722,6 +3908,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
msgid "Automatically close incident issues when the associated Prometheus alert resolves."
msgstr ""
@@ -3740,6 +3929,9 @@ msgstr ""
msgid "Available"
msgstr ""
+msgid "Available ID"
+msgstr ""
+
msgid "Available Runners: %{runners}"
msgstr ""
@@ -3797,9 +3989,6 @@ msgstr ""
msgid "Badges|Badge image preview"
msgstr ""
-msgid "Badges|Delete badge"
-msgstr ""
-
msgid "Badges|Delete badge?"
msgstr ""
@@ -3881,6 +4070,12 @@ msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
+msgid "Based on"
+msgstr ""
+
+msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -3965,6 +4160,18 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Updated live"
+msgstr ""
+
+msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgstr ""
+
msgid "Bitbucket Server Import"
msgstr ""
@@ -4016,12 +4223,21 @@ msgstr ""
msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4040,6 +4256,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|Load more issues"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -4052,6 +4271,9 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
+msgid "Branch already exists"
+msgstr ""
+
msgid "Branch changed"
msgstr ""
@@ -4196,6 +4418,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Brief title about the change"
+msgstr ""
+
msgid "Broadcast Message was successfully created."
msgstr ""
@@ -4232,9 +4457,21 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
msgid "Burndown chart"
msgstr ""
+msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+msgstr ""
+
msgid "BurndownChartLabel|Open issue weight"
msgstr ""
@@ -4265,7 +4502,7 @@ 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}"
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
@@ -4448,6 +4685,9 @@ msgstr ""
msgid "Cannot enable shared runners because parent group does not allow it"
msgstr ""
+msgid "Cannot find user key."
+msgstr ""
+
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -4859,6 +5099,9 @@ msgstr ""
msgid "Child epic doesn't exist."
msgstr ""
+msgid "Chinese language support using"
+msgstr ""
+
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
msgstr ""
@@ -5042,9 +5285,6 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
-
msgid "CiVariable|Masked"
msgstr ""
@@ -5063,9 +5303,6 @@ msgstr ""
msgid "CiVariable|Toggle protected"
msgstr ""
-msgid "CiVariable|Validation failed"
-msgstr ""
-
msgid "Classification Label (optional)"
msgstr ""
@@ -5174,6 +5411,9 @@ msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close issue"
+msgstr ""
+
msgid "Close milestone"
msgstr ""
@@ -5198,7 +5438,7 @@ msgstr ""
msgid "Closed this %{quick_action_target}."
msgstr ""
-msgid "Closed: %{closedIssuesCount}"
+msgid "Closed: %{closed}"
msgstr ""
msgid "Closes this %{quick_action_target}."
@@ -5225,6 +5465,9 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
@@ -5408,6 +5651,9 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
msgstr ""
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
@@ -5465,9 +5711,6 @@ 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 ""
@@ -5723,9 +5966,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{linkStart}Regions%{linkEnd}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
@@ -5741,9 +5981,6 @@ msgstr ""
msgid "ClusterIntegration|Loading Key Pairs"
msgstr ""
-msgid "ClusterIntegration|Loading Regions"
-msgstr ""
-
msgid "ClusterIntegration|Loading VPCs"
msgstr ""
@@ -5810,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|No projects matched your search"
msgstr ""
-msgid "ClusterIntegration|No region found"
-msgstr ""
-
msgid "ClusterIntegration|No security group found"
msgstr ""
@@ -5879,9 +6113,6 @@ 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 ""
@@ -5948,9 +6179,6 @@ msgstr ""
msgid "ClusterIntegration|Search projects"
msgstr ""
-msgid "ClusterIntegration|Search regions"
-msgstr ""
-
msgid "ClusterIntegration|Search security groups"
msgstr ""
@@ -6011,6 +6239,9 @@ msgstr ""
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -6095,6 +6326,9 @@ msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -6236,9 +6470,6 @@ msgstr ""
msgid "ClusterIntergation|Select a network"
msgstr ""
-msgid "ClusterIntergation|Select a region"
-msgstr ""
-
msgid "ClusterIntergation|Select a security group"
msgstr ""
@@ -6350,9 +6581,6 @@ 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 ""
@@ -6663,7 +6891,7 @@ msgstr ""
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
-msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
msgstr ""
msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
@@ -6714,6 +6942,9 @@ msgstr ""
msgid "Connection timeout"
msgstr ""
+msgid "Consistency guarantee method"
+msgstr ""
+
msgid "Contact sales to upgrade"
msgstr ""
@@ -6779,6 +7010,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy:"
msgstr ""
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -7155,6 +7389,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this value"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -7215,6 +7452,9 @@ msgstr ""
msgid "Could not delete wiki page"
msgstr ""
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7224,6 +7464,9 @@ msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -7257,6 +7500,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't calculate number of %{issuables}."
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -7504,6 +7750,9 @@ msgstr ""
msgid "Created on"
msgstr ""
+msgid "Created on %{created_at}"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -7597,6 +7846,9 @@ msgstr ""
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
+msgid "Custom analyzers: language support"
+msgstr ""
+
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -7847,6 +8099,9 @@ msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
@@ -7904,6 +8159,15 @@ 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|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -7943,6 +8207,12 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
@@ -7964,6 +8234,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
msgid "DastProfiles|Manage Profiles"
msgstr ""
@@ -7991,15 +8267,15 @@ 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 ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
@@ -8015,6 +8291,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
msgid "DastProfiles|Site Profile"
msgstr ""
@@ -8054,6 +8333,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
msgid "DastProfiles|Validate"
msgstr ""
@@ -8066,6 +8348,12 @@ msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgstr ""
+msgid "DastProfiles|Validation failed. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Validation is in progress..."
+msgstr ""
+
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
@@ -8075,6 +8363,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Database update failed"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -8231,9 +8522,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Snippet"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -8243,6 +8531,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete badge"
+msgstr ""
+
msgid "Delete board"
msgstr ""
@@ -8258,9 +8549,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete list"
-msgstr ""
-
msgid "Delete pipeline"
msgstr ""
@@ -8282,6 +8570,9 @@ msgstr ""
msgid "Delete source branch"
msgstr ""
+msgid "Delete subscription"
+msgstr ""
+
msgid "Delete this attachment"
msgstr ""
@@ -8345,12 +8636,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
+msgid "Denied domains for sign-ups"
+msgstr ""
+
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
+msgid "Denylist file"
+msgstr ""
+
msgid "Dependencies"
msgstr ""
@@ -8396,18 +8693,27 @@ msgstr ""
msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
msgstr ""
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
msgid "Dependencies|There may be multiple paths"
msgstr ""
@@ -8480,9 +8786,6 @@ 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 ""
@@ -8648,6 +8951,12 @@ msgstr ""
msgid "Deployed to"
msgstr ""
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
msgid "Deploying to"
msgstr ""
@@ -8696,6 +9005,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
+msgid "Description template"
+msgstr ""
+
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
@@ -8867,6 +9179,27 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
+msgid "DevOps Score"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|Add a segment to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add new segment"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -8918,7 +9251,7 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared Runners"
+msgid "Disable shared runners"
msgstr ""
msgid "Disable two-factor authentication"
@@ -9066,6 +9399,9 @@ msgstr ""
msgid "Documentation for popular identity providers"
msgstr ""
+msgid "Documentation pages URL"
+msgstr ""
+
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
@@ -9075,6 +9411,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
+msgid "Domain denylist"
+msgstr ""
+
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
@@ -9096,6 +9435,9 @@ msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
+msgid "Don't send usage data"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -9123,9 +9465,6 @@ msgstr ""
msgid "Download as CSV"
msgstr ""
-msgid "Download asset"
-msgstr ""
-
msgid "Download codes"
msgstr ""
@@ -9294,15 +9633,24 @@ msgstr ""
msgid "Edit stage"
msgstr ""
+msgid "Edit this file only."
+msgstr ""
+
msgid "Edit this release"
msgstr ""
+msgid "Edit title and description"
+msgstr ""
+
msgid "Edit wiki page"
msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edited"
+msgstr ""
+
msgid "Edited %{timeago}"
msgstr ""
@@ -9375,6 +9723,9 @@ msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
+msgid "Email updates (optional)"
+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 ""
@@ -9516,6 +9867,12 @@ msgstr ""
msgid "Enable integration"
msgstr ""
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -9543,7 +9900,19 @@ 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"
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
msgstr ""
msgid "Enable snowplow tracking"
@@ -9588,6 +9957,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
+msgid "End Time"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -9615,7 +9987,10 @@ msgstr ""
msgid "Enter a number"
msgstr ""
-msgid "Enter a whole number between 0 and 100"
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
msgstr ""
msgid "Enter at least three characters to search"
@@ -10377,12 +10752,18 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Excess storage"
+msgstr ""
+
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Execution time"
+msgstr ""
+
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
@@ -10413,6 +10794,9 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
+msgid "Expand file"
+msgstr ""
+
msgid "Expand milestones"
msgstr ""
@@ -10488,6 +10872,9 @@ msgstr ""
msgid "Export issues"
msgstr ""
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -10590,6 +10977,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
msgid "Failed to create repository"
msgstr ""
@@ -10653,6 +11043,9 @@ msgstr ""
msgid "Failed to load milestones. Please try again."
msgstr ""
+msgid "Failed to load projects"
+msgstr ""
+
msgid "Failed to load related branches"
msgstr ""
@@ -10665,6 +11058,9 @@ msgstr ""
msgid "Failed to load stacktrace."
msgstr ""
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -10801,6 +11197,18 @@ msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -10831,6 +11239,9 @@ msgstr ""
msgid "FeatureFlags|Configure feature flags"
msgstr ""
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
msgid "FeatureFlags|Create feature flag"
msgstr ""
@@ -10882,6 +11293,9 @@ msgstr ""
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
@@ -10948,10 +11362,13 @@ msgstr ""
msgid "FeatureFlags|Percent of users"
msgstr ""
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
-msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "FeatureFlags|Protected"
@@ -10966,6 +11383,9 @@ msgstr ""
msgid "FeatureFlags|Rollout Strategy"
msgstr ""
+msgid "FeatureFlags|Select a user list"
+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 ""
@@ -10984,9 +11404,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the user lists."
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 ""
@@ -11002,15 +11419,15 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlag|List"
-msgstr ""
-
msgid "FeatureFlag|Percentage"
msgstr ""
msgid "FeatureFlag|Select a user list"
msgstr ""
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
msgid "FeatureFlag|There are no configured user lists"
msgstr ""
@@ -11020,6 +11437,9 @@ msgstr ""
msgid "FeatureFlag|User IDs"
msgstr ""
+msgid "FeatureFlag|User List"
+msgstr ""
+
msgid "Feb"
msgstr "2月"
@@ -11077,12 +11497,18 @@ msgstr ""
msgid "File upload error."
msgstr ""
+msgid "Filename"
+msgstr ""
+
msgid "Files"
msgstr ""
msgid "Files breadcrumb"
msgstr ""
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr ""
@@ -11107,6 +11533,9 @@ msgstr ""
msgid "Filter by issues that are currently closed."
msgstr ""
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
msgid "Filter by label"
msgstr ""
@@ -11170,6 +11599,9 @@ msgstr ""
msgid "Find File"
msgstr ""
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
msgid "Find bugs in your code with coverage-guided fuzzing."
msgstr ""
@@ -11203,9 +11635,6 @@ msgstr ""
msgid "Finished"
msgstr ""
-msgid "First Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First Seen"
msgstr ""
@@ -11215,9 +11644,15 @@ msgstr ""
msgid "First name"
msgstr ""
+msgid "First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "First seen"
msgstr ""
+msgid "Fixed burndown chart"
+msgstr ""
+
msgid "Fixed date"
msgstr ""
@@ -11272,7 +11707,7 @@ 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)"
+msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For more info, read the documentation."
@@ -11818,7 +12253,7 @@ 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."
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
msgstr ""
msgid "Git LFS status:"
@@ -11839,6 +12274,9 @@ msgstr ""
msgid "Git strategy for pipelines"
msgstr ""
+msgid "Git transfer in progress"
+msgstr ""
+
msgid "Git version"
msgstr ""
@@ -11875,9 +12313,6 @@ 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 ""
@@ -11902,6 +12337,12 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -12214,6 +12655,9 @@ msgstr ""
msgid "Go to your snippets"
msgstr ""
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
msgid "Google Cloud Platform"
msgstr ""
@@ -12319,7 +12763,7 @@ msgstr ""
msgid "Group avatar"
msgstr ""
-msgid "Group by:"
+msgid "Group by"
msgstr ""
msgid "Group description"
@@ -12478,6 +12922,12 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -12487,6 +12937,9 @@ msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
msgstr ""
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
msgid "GroupSAML|Default membership role"
msgstr ""
@@ -12532,12 +12985,30 @@ msgstr ""
msgid "GroupSAML|NameID Format"
msgstr ""
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
msgid "GroupSAML|Prohibit outer forks"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
msgid "GroupSAML|SAML Response Output"
msgstr ""
@@ -12550,6 +13021,9 @@ msgstr ""
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr ""
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
@@ -12562,6 +13036,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr ""
@@ -12586,6 +13063,9 @@ msgstr ""
msgid "GroupSAML|Your SCIM token"
msgstr ""
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
msgstr ""
@@ -12993,6 +13473,9 @@ msgstr ""
msgid "HighlightBar|Original alert:"
msgstr ""
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -13047,9 +13530,6 @@ 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 ""
@@ -13062,7 +13542,7 @@ 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"
+msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "ID"
@@ -13170,6 +13650,9 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
@@ -13194,9 +13677,6 @@ 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 ""
@@ -13218,10 +13698,10 @@ msgstr ""
msgid "Ignored"
msgstr ""
-msgid "Image Details"
+msgid "Image URL"
msgstr ""
-msgid "Image URL"
+msgid "Image details"
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -13301,6 +13781,9 @@ msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project from"
+msgstr ""
+
msgid "Import project members"
msgstr ""
@@ -13421,6 +13904,12 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -13481,6 +13970,9 @@ msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
msgid "IncidentManagement|Unassigned"
msgstr ""
@@ -13490,12 +13982,18 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
msgid "IncidentSettings|Alert integration"
msgstr ""
msgid "IncidentSettings|Grafana integration"
msgstr ""
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
msgid "IncidentSettings|Incidents"
msgstr ""
@@ -13505,6 +14003,30 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
msgid "Incidents"
msgstr ""
@@ -13517,6 +14039,9 @@ msgstr ""
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13592,27 +14117,33 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Insert"
-msgstr ""
-
msgid "Insert a code block"
msgstr ""
msgid "Insert a quote"
msgstr ""
+msgid "Insert a video"
+msgstr ""
+
msgid "Insert an image"
msgstr ""
msgid "Insert code"
msgstr ""
+msgid "Insert image"
+msgstr ""
+
msgid "Insert inline code"
msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Insert video"
+msgstr ""
+
msgid "Insights"
msgstr ""
@@ -13631,6 +14162,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+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 ""
@@ -13659,6 +14193,51 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
+msgid "InstanceAnalytics|Canceled"
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceAnalytics|Failed"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues"
+msgstr ""
+
+msgid "InstanceAnalytics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Items"
+msgstr ""
+
+msgid "InstanceAnalytics|Merge Requests"
+msgstr ""
+
+msgid "InstanceAnalytics|Month"
+msgstr ""
+
+msgid "InstanceAnalytics|Pipelines"
+msgstr ""
+
+msgid "InstanceAnalytics|Skipped"
+msgstr ""
+
+msgid "InstanceAnalytics|Succeeded"
+msgstr ""
+
+msgid "InstanceAnalytics|There is no data available."
+msgstr ""
+
+msgid "InstanceAnalytics|Total"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
msgid "InstanceStatistics|Groups"
msgstr ""
@@ -13668,12 +14247,30 @@ msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
msgid "InstanceStatistics|Users"
msgstr ""
@@ -13707,6 +14304,9 @@ msgstr ""
msgid "Integrations|Connection successful."
msgstr ""
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -13722,37 +14322,58 @@ msgstr ""
msgid "Integrations|Includes commit title and branch"
msgstr ""
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
msgstr ""
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
msgid "Integrations|Use custom settings"
msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "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."
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
-msgid "Internal - The project can be accessed by any logged in user."
+msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal URL (optional)"
@@ -13761,6 +14382,9 @@ msgstr ""
msgid "Internal users"
msgstr ""
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
@@ -13785,9 +14409,6 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
-msgid "Invalid board"
-msgstr ""
-
msgid "Invalid container_name"
msgstr ""
@@ -13887,25 +14508,25 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you"
+msgid "Invite your team"
msgstr ""
-msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|Join now"
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|You are invited!"
+msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|You have been invited"
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgid "InviteEmail|You are invited!"
msgstr ""
-msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
@@ -13953,6 +14574,60 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -14001,6 +14676,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue actions"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -14217,6 +14895,9 @@ msgstr "1月"
msgid "January"
msgstr ""
+msgid "Japanese language support using"
+msgstr ""
+
msgid "Jira Issues"
msgstr ""
@@ -14472,6 +15153,9 @@ msgstr ""
msgid "Keep divergent refs"
msgstr ""
+msgid "Keep editing"
+msgstr ""
+
msgid "Kerberos access denied"
msgstr ""
@@ -14490,6 +15174,12 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14619,9 +15309,6 @@ 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 ""
@@ -14647,9 +15334,6 @@ msgstr ""
msgid "Last Accessed On"
msgstr ""
-msgid "Last Name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last Pipeline"
msgstr ""
@@ -14683,6 +15367,9 @@ msgstr ""
msgid "Last name"
msgstr ""
+msgid "Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
msgid "Last reply by"
msgstr ""
@@ -14716,6 +15403,9 @@ msgstr ""
msgid "Last used"
msgstr ""
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
msgid "Last used on:"
msgstr ""
@@ -14761,6 +15451,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{username}"
+msgstr ""
+
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -14836,6 +15529,9 @@ msgstr ""
msgid "Leave zen mode"
msgstr ""
+msgid "Legacy burndown chart"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -15368,9 +16064,6 @@ msgstr "3月"
msgid "March"
msgstr ""
-msgid "Mark To Do as done"
-msgstr ""
-
msgid "Mark as done"
msgstr ""
@@ -15389,6 +16082,9 @@ msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
+msgid "Mark to do as done"
+msgstr ""
+
msgid "Markdown"
msgstr ""
@@ -15422,9 +16118,6 @@ 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 ""
@@ -15434,7 +16127,7 @@ msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
-msgid "Marks To Do as done."
+msgid "Marked to do as done."
msgstr ""
msgid "Marks this %{noun} as Work In Progress."
@@ -15446,6 +16139,9 @@ msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
+msgid "Marks to do as done."
+msgstr ""
+
msgid "Mask variable"
msgstr ""
@@ -15509,6 +16205,9 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
+msgid "MaxBuilds"
+msgstr ""
+
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -15629,6 +16328,12 @@ msgstr ""
msgid "Member since %{date}"
msgstr ""
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -15656,15 +16361,90 @@ msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
+msgid "Members|%{userName} is currently a LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
msgid "Members|Expired"
msgstr ""
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
msgid "Members|No expiration set"
msgstr ""
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
msgid "Members|in %{time}"
msgstr ""
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
msgid "Memory Usage"
msgstr ""
@@ -15902,6 +16682,9 @@ msgstr ""
msgid "Merged this merge request."
msgstr ""
+msgid "Merged: %{merged}"
+msgstr ""
+
msgid "Merges this merge request immediately."
msgstr ""
@@ -16303,6 +17086,27 @@ msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16618,9 +17422,15 @@ msgstr ""
msgid "Multi-project Runners cannot be removed"
msgstr ""
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
msgid "Multiple IP address ranges are supported."
msgstr ""
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
msgid "Multiple domains are supported."
msgstr ""
@@ -16678,6 +17488,32 @@ msgstr ""
msgid "Namespace:"
msgstr ""
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -16933,6 +17769,9 @@ msgstr ""
msgid "New"
msgstr "新增"
+msgid "New %{display_issuable_type}"
+msgstr ""
+
msgid "New Application"
msgstr ""
@@ -17396,6 +18235,9 @@ msgstr ""
msgid "None"
msgstr "ç„¡"
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -17426,9 +18268,6 @@ msgstr ""
msgid "Not found."
msgstr ""
-msgid "Not now"
-msgstr ""
-
msgid "Not ready yet. Try again later."
msgstr ""
@@ -17663,6 +18502,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
+msgid "On"
+msgstr ""
+
msgid "On track"
msgstr ""
@@ -17708,9 +18550,6 @@ msgstr ""
msgid "OnDemandScans|Scanner profile"
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 ""
@@ -17720,9 +18559,6 @@ msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
-msgid "OnDemandScans|Site profiles"
-msgstr ""
-
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -17841,19 +18677,13 @@ 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}"
+msgid "Open: %{open}"
msgstr ""
msgid "Opened"
@@ -18027,6 +18857,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -18123,7 +18956,7 @@ 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."
+msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
@@ -18147,9 +18980,6 @@ msgstr ""
msgid "PackageRegistry|NPM"
msgstr ""
-msgid "PackageRegistry|No upcoming issues"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -18171,7 +19001,7 @@ msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|PyPi"
+msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
@@ -18195,9 +19025,6 @@ 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 ""
@@ -18213,9 +19040,6 @@ 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 ""
@@ -18225,12 +19049,6 @@ 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 ""
@@ -18255,7 +19073,7 @@ msgstr ""
msgid "PackageType|NuGet"
msgstr ""
-msgid "PackageType|PyPi"
+msgid "PackageType|PyPI"
msgstr ""
msgid "Packages"
@@ -18447,7 +19265,7 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
-msgid "Percent of users"
+msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
msgid "Percentage"
@@ -18459,9 +19277,6 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
-msgid "Performance and resource management"
-msgstr ""
-
msgid "Performance optimization"
msgstr ""
@@ -18564,6 +19379,9 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
+msgid "PipelineCharts|Total duration:"
+msgstr ""
+
msgid "PipelineCharts|Total:"
msgstr ""
@@ -18645,6 +19463,9 @@ msgstr ""
msgid "Pipelines|CI Lint"
msgstr ""
+msgid "Pipelines|CI file could not be loaded: %{reason}"
+msgstr ""
+
msgid "Pipelines|Child pipeline"
msgstr ""
@@ -18663,6 +19484,9 @@ msgstr ""
msgid "Pipelines|Edit"
msgstr ""
+msgid "Pipelines|Editor"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr ""
@@ -18693,6 +19517,9 @@ msgstr ""
msgid "Pipelines|Owner"
msgstr ""
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -18729,6 +19556,12 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
@@ -18957,6 +19790,9 @@ msgstr ""
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
msgid "Please enter a valid number"
msgstr ""
@@ -18966,6 +19802,9 @@ msgstr ""
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill out this field."
+msgstr ""
+
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr ""
@@ -18978,12 +19817,18 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
msgid "Please provide a name"
msgstr ""
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
msgid "Please provide a valid email address."
msgstr ""
@@ -19188,9 +20033,6 @@ 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 ""
@@ -19884,7 +20726,7 @@ 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"
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
@@ -20187,6 +21029,9 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
+msgid "ProjectTemplates|Basic"
+msgstr ""
+
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -20241,6 +21086,9 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
+msgid "ProjectTemplates|Serenity Valley"
+msgstr ""
+
msgid "ProjectTemplates|Serverless Framework/JS"
msgstr ""
@@ -20697,6 +21545,9 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -20823,6 +21674,9 @@ msgstr ""
msgid "Purchase more minutes"
msgstr ""
+msgid "Purchase more storage"
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -20934,6 +21788,9 @@ msgstr ""
msgid "Rake Tasks Help"
msgstr ""
+msgid "Random"
+msgstr ""
+
msgid "Raw blob request rate limit per minute"
msgstr ""
@@ -21015,6 +21872,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
+msgid "Refresh the page and try again."
+msgstr ""
+
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
@@ -21058,9 +21918,6 @@ msgstr ""
msgid "Register device"
msgstr ""
-msgid "Register for GitLab"
-msgstr ""
-
msgid "Register now"
msgstr ""
@@ -21269,6 +22126,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove list"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -21389,6 +22249,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
+msgid "Removing integrations is not supported for this project"
+msgstr ""
+
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -21410,9 +22273,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen issue"
+msgstr ""
+
msgid "Reopen milestone"
msgstr ""
+msgid "Reopen test case"
+msgstr ""
+
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -21440,6 +22309,9 @@ msgstr ""
msgid "Replication"
msgstr ""
+msgid "Replication details"
+msgstr ""
+
msgid "Replication enabled"
msgstr ""
@@ -21564,7 +22436,13 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
-msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
@@ -21576,6 +22454,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -21594,6 +22484,9 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
+msgid "Repository already read-only"
+msgstr ""
+
msgid "Repository check"
msgstr ""
@@ -21690,7 +22583,7 @@ msgstr ""
msgid "Require admin approval for new sign-ups"
msgstr ""
-msgid "Require all users in this group to setup Two-factor authentication"
+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."
@@ -21723,6 +22616,9 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
+msgid "Requirement title"
+msgstr ""
+
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -21921,6 +22817,9 @@ msgstr ""
msgid "Review App|View latest app"
msgstr ""
+msgid "Review requested from %{name}"
+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 ""
@@ -22072,6 +22971,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -22099,6 +23004,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -22168,6 +23076,9 @@ msgstr ""
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
+msgid "SSH key"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -22177,6 +23088,12 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "Sample Data"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
msgid "Saturday"
msgstr ""
@@ -22192,6 +23109,9 @@ msgstr ""
msgid "Save Push Rules"
msgstr ""
+msgid "Save and test payload"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -22216,9 +23136,6 @@ 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 variables"
-msgstr ""
-
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
@@ -22228,6 +23145,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scanner"
+msgstr ""
+
msgid "Schedule a new pipeline"
msgstr ""
@@ -22267,6 +23187,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
msgid "Score"
msgstr ""
@@ -22297,7 +23220,7 @@ msgstr ""
msgid "Search Jira issues"
msgstr ""
-msgid "Search Milestones"
+msgid "Search a group"
msgstr ""
msgid "Search an environment spec"
@@ -22354,9 +23277,6 @@ msgstr ""
msgid "Search forks"
msgstr ""
-msgid "Search groups"
-msgstr ""
-
msgid "Search merge requests"
msgstr ""
@@ -22438,9 +23358,6 @@ 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] ""
@@ -22494,7 +23411,7 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats usage data as of %{last_enqueue_time}"
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
msgid "Seats usage data is updated every day at 12:00pm UTC"
@@ -22539,10 +23456,10 @@ 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}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
@@ -22671,6 +23588,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
msgid "SecurityReports|False positive"
msgstr ""
@@ -22734,6 +23654,12 @@ msgstr ""
msgid "SecurityReports|Security reports can only be accessed by authorized users."
msgstr ""
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
+msgstr ""
+
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -22773,6 +23699,10 @@ msgstr ""
msgid "SecurityReports|There was an error deleting the comment."
msgstr ""
+msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
@@ -22953,6 +23883,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
@@ -22968,7 +23901,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method."
+msgid "Select strategy activation method"
msgstr ""
msgid "Select subscription"
@@ -22983,9 +23916,6 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
-msgid "Select the environment scope for this feature flag."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -23079,6 +24009,9 @@ msgstr ""
msgid "September"
msgstr ""
+msgid "Serenity Valley Sample Data template."
+msgstr ""
+
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -23193,6 +24126,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Session ID"
+msgstr ""
+
msgid "Session duration (minutes)"
msgstr ""
@@ -23328,6 +24264,9 @@ msgstr ""
msgid "Set up pipeline subscriptions for this project."
msgstr ""
+msgid "Set up shared runner availability"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -23433,6 +24372,15 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -23451,9 +24399,15 @@ 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 Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show all issues."
+msgstr ""
+
msgid "Show all members"
msgstr ""
@@ -23594,6 +24548,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -23621,6 +24578,9 @@ msgstr ""
msgid "Sign-in restrictions"
msgstr ""
+msgid "Sign-in text"
+msgstr ""
+
msgid "Sign-up restrictions"
msgstr ""
@@ -23630,9 +24590,6 @@ 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 ""
@@ -23642,6 +24599,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -23753,27 +24713,18 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
-msgid "Snippets|Authored %{time_ago} by %{author}"
-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 ""
@@ -24008,6 +24959,9 @@ msgstr ""
msgid "SortOptions|Access level, descending"
msgstr ""
+msgid "SortOptions|Blocking"
+msgstr ""
+
msgid "SortOptions|Created date"
msgstr ""
@@ -24116,6 +25070,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Relevant"
+msgstr ""
+
msgid "SortOptions|Size"
msgstr ""
@@ -24158,9 +25115,6 @@ msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
-msgid "Source code"
-msgstr ""
-
msgid "Source code (%{fileExtension})"
msgstr ""
@@ -24236,9 +25190,6 @@ 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 ""
@@ -24302,6 +25253,9 @@ msgstr ""
msgid "Start Date"
msgstr ""
+msgid "Start Time"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -24458,6 +25412,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
@@ -24587,6 +25544,9 @@ msgstr ""
msgid "Submit changes"
msgstr ""
+msgid "Submit changes..."
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -24602,6 +25562,9 @@ msgstr ""
msgid "Submit the current review."
msgstr ""
+msgid "Submit your changes"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -24644,6 +25607,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -24728,6 +25697,9 @@ msgstr ""
msgid "Successfully activated"
msgstr ""
+msgid "Successfully approved"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -24749,6 +25721,9 @@ msgstr ""
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -24884,12 +25859,18 @@ msgstr ""
msgid "Sync information"
msgstr ""
+msgid "Sync now"
+msgstr ""
+
msgid "Synced"
msgstr ""
msgid "Synchronization disabled"
msgstr ""
+msgid "Syncing…"
+msgstr ""
+
msgid "System"
msgstr ""
@@ -24917,6 +25898,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "System output"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -25148,15 +26132,30 @@ msgstr ""
msgid "TestCases|Search test cases"
msgstr ""
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
msgid "TestCases|Something went wrong while fetching test cases list."
msgstr ""
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
msgid "TestCases|Submit test case"
msgstr ""
@@ -25241,7 +26240,7 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
-msgid "That's it, well done!%{celebrate}"
+msgid "That's it, well done!"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
@@ -25263,9 +26262,6 @@ 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 ""
@@ -25278,9 +26274,15 @@ 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 Security Dashboard shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
@@ -25377,6 +26379,12 @@ msgstr ""
msgid "The following %{user} can also push to this branch: %{branch}"
msgstr ""
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -25399,7 +26407,7 @@ 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."
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
@@ -25510,7 +26518,7 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The project can be accessed by any logged in user."
+msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed by any user who is logged in."
@@ -25570,6 +26578,9 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "The schedule time must be in the future!"
msgstr ""
@@ -25582,7 +26593,7 @@ msgstr ""
msgid "The snippet is visible only to project members."
msgstr ""
-msgid "The snippet is visible to any logged in user."
+msgid "The snippet is visible to any logged in user except external users."
msgstr ""
msgid "The specified tab is invalid, please select another"
@@ -25621,6 +26632,9 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user you are trying to approve is not pending an approval"
+msgstr ""
+
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
@@ -25729,6 +26743,9 @@ msgstr ""
msgid "There is no chart data available."
msgstr ""
+msgid "There is no data available."
+msgstr ""
+
msgid "There is no data available. Please change your selection."
msgstr ""
@@ -25924,6 +26941,9 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "These paths are protected for POST requests."
+msgstr ""
+
msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
@@ -25975,7 +26995,7 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
@@ -25999,9 +27019,15 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
msgid "This block is self-referential"
msgstr ""
@@ -26134,6 +27160,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -26143,6 +27172,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -26695,6 +27727,12 @@ msgstr ""
msgid "Timeago|right now"
msgstr ""
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
msgid "Timeout"
msgstr ""
@@ -26727,7 +27765,7 @@ 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."
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
msgstr ""
msgid "To Do"
@@ -26778,7 +27816,7 @@ 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}"
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
@@ -26907,6 +27945,9 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project select"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -26979,16 +28020,19 @@ msgstr ""
msgid "Total test time for all commits/merges"
msgstr ""
+msgid "Total users"
+msgstr ""
+
msgid "Total weight"
msgstr ""
msgid "Total: %{total}"
msgstr ""
-msgid "TotalRefCountIndicator|1000+"
+msgid "TotalMilestonesIndicator|1000+"
msgstr ""
-msgid "Trace"
+msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
@@ -27165,6 +28209,9 @@ msgstr ""
msgid "Tuesday"
msgstr ""
+msgid "Tuning settings"
+msgstr ""
+
msgid "Turn Off"
msgstr ""
@@ -27315,6 +28362,9 @@ msgstr ""
msgid "Unable to save your changes. Please try again."
msgstr ""
+msgid "Unable to save your preference"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -27540,6 +28590,9 @@ msgstr ""
msgid "Update now"
msgstr ""
+msgid "Update username"
+msgstr ""
+
msgid "Update variable"
msgstr ""
@@ -27678,10 +28731,13 @@ msgstr ""
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
-msgid "UsageQuota|Build Artifacts"
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -27708,6 +28764,9 @@ msgstr ""
msgid "UsageQuota|Purchase more storage"
msgstr ""
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
msgid "UsageQuota|Repositories"
msgstr ""
@@ -27720,9 +28779,36 @@ msgstr ""
msgid "UsageQuota|Storage"
msgstr ""
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
msgid "UsageQuota|Unlimited"
msgstr ""
@@ -27744,15 +28830,27 @@ msgstr ""
msgid "UsageQuota|Usage since"
msgstr ""
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wikis"
msgstr ""
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -27807,10 +28905,7 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User IDs"
-msgstr ""
-
-msgid "User List"
+msgid "User ID"
msgstr ""
msgid "User OAuth applications"
@@ -27930,6 +29025,9 @@ msgstr ""
msgid "UserProfile|Blocked user"
msgstr ""
+msgid "UserProfile|Bot activity"
+msgstr ""
+
msgid "UserProfile|Contributed projects"
msgstr ""
@@ -28026,9 +29124,6 @@ msgstr ""
msgid "Username is available."
msgstr ""
-msgid "Username is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Username or email"
msgstr ""
@@ -28182,6 +29277,12 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
msgid "View all issues"
msgstr ""
@@ -28487,7 +29588,13 @@ msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
-msgid "Vulnerability|Crash Address"
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
msgstr ""
msgid "Vulnerability|Description"
@@ -28571,6 +29678,15 @@ msgstr ""
msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr ""
@@ -28667,6 +29783,9 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Feature Flag events"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
@@ -28691,13 +29810,16 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+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 merge request is created/updated/merged"
@@ -28766,15 +29888,15 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
-msgid "Welcome to your issue board!"
-msgstr ""
-
msgid "What are you searching for?"
msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What is squashing?"
+msgstr ""
+
msgid "What's new at GitLab"
msgstr ""
@@ -28787,7 +29909,7 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by the admin before they can login. This setting is effective only if sign-ups are enabled."
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
msgstr ""
msgid "When enabled, any user visiting %{host} will be able to create an account."
@@ -29028,10 +30150,10 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Workflow Help"
+msgid "Would you like to create a new branch?"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "Would you like to try auto-generating a branch name?"
msgstr ""
msgid "Write"
@@ -29124,6 +30246,9 @@ msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
msgstr ""
+msgid "You are not allowed to approve a user"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -29145,6 +30270,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -29157,10 +30285,10 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
-msgid "You can also press &#8984;-Enter"
+msgid "You can also press Ctrl-Enter"
msgstr ""
-msgid "You can also press Ctrl-Enter"
+msgid "You can also press ⌘-Enter"
msgstr ""
msgid "You can also star a label to make it a priority label."
@@ -29175,6 +30303,15 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -29376,6 +30513,9 @@ msgstr ""
msgid "You have been invited"
msgstr ""
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
msgid "You have been unsubscribed from this thread."
msgstr ""
@@ -29388,6 +30528,15 @@ msgstr ""
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -29412,9 +30561,6 @@ 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 be logged in to search across all of GitLab"
msgstr ""
@@ -29472,9 +30618,6 @@ 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 successfully declined the invitation"
msgstr ""
@@ -29577,19 +30720,22 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "YouTube URL or ID"
+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."
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
msgid "Your 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."
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
@@ -29619,6 +30765,9 @@ msgstr ""
msgid "Your License"
msgstr ""
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr ""
@@ -29634,6 +30783,9 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key was deleted"
+msgstr ""
+
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -29899,9 +31051,6 @@ msgstr ""
msgid "by"
msgstr "來自"
-msgid "by %{user}"
-msgstr ""
-
msgid "cannot be a date in the past"
msgstr ""
@@ -30028,9 +31177,6 @@ msgstr ""
msgid "ciReport|Coverage Fuzzing"
msgstr ""
-msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
-
msgid "ciReport|Coverage fuzzing"
msgstr ""
@@ -30076,9 +31222,6 @@ 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 ""
@@ -30161,6 +31304,9 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "collect usage information"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -30394,7 +31540,7 @@ msgstr ""
msgid "is blocked by"
msgstr ""
-msgid "is enabled."
+msgid "is forbidden by a top-level group"
msgstr ""
msgid "is invalid because there is downstream lock"
@@ -30412,6 +31558,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
@@ -30430,6 +31579,9 @@ msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -30466,6 +31618,9 @@ msgstr ""
msgid "jigsaw is not defined"
msgstr ""
+msgid "kuromoji custom analyzer"
+msgstr ""
+
msgid "last commit:"
msgstr ""
@@ -30527,6 +31682,9 @@ msgstr ""
msgid "missing"
msgstr ""
+msgid "more information"
+msgstr ""
+
msgid "most recent deployment"
msgstr ""
@@ -30996,9 +32154,6 @@ 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 ""
@@ -31011,9 +32166,6 @@ msgstr ""
msgid "relates to"
msgstr ""
-msgid "released %{time}"
-msgstr ""
-
msgid "remaining"
msgstr ""
@@ -31090,6 +32242,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "smartcn custom analyzer"
+msgstr ""
+
msgid "sort:"
msgstr ""
@@ -31270,9 +32425,6 @@ msgstr ""
msgid "wiki page"
msgstr ""
-msgid "will be released %{time}"
-msgstr ""
-
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -31285,3 +32437,6 @@ msgstr ""
msgid "yaml invalid"
msgstr ""
+msgid "your settings"
+msgstr ""
+
diff --git a/package.json b/package.json
index 513f777d0c5..cc1f4eb1bc8 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
"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",
+ "lint-docs": "scripts/lint-doc.sh",
"prejest": "yarn check-dependencies",
"jest": "jest --config jest.config.js",
"jest-debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
@@ -20,7 +21,7 @@
"karma": "BABEL_ENV=${BABEL_ENV:=karma} karma start --single-run true config/karma.config.js",
"karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js",
"karma-start": "BABEL_ENV=karma karma start config/karma.config.js",
- "markdownlint": "markdownlint -c .markdownlint.json 'doc/**/*.md'",
+ "markdownlint": "markdownlint --config .markdownlint.json",
"postinstall": "node ./scripts/frontend/postinstall.js",
"prettier-staged": "node ./scripts/frontend/prettier.js check",
"prettier-staged-save": "node ./scripts/frontend/prettier.js save",
@@ -42,14 +43,14 @@
"@babel/plugin-syntax-import-meta": "^7.10.1",
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.5",
- "@gitlab/svgs": "1.171.0",
- "@gitlab/ui": "21.33.0",
+ "@gitlab/svgs": "1.175.0",
+ "@gitlab/ui": "23.9.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-3",
"@rails/ujs": "^6.0.3-2",
- "@sourcegraph/code-host-integration": "0.0.50",
- "@toast-ui/editor": "^2.4.0",
- "@toast-ui/vue-editor": "^2.4.0",
+ "@sourcegraph/code-host-integration": "0.0.52",
+ "@toast-ui/editor": "^2.5.0",
+ "@toast-ui/vue-editor": "^2.5.0",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.10",
"apollo-link": "^1.2.14",
@@ -80,7 +81,7 @@
"deckar01-task_list": "^2.3.1",
"diff": "^3.4.0",
"document-register-element": "1.14.3",
- "dompurify": "^2.1.1",
+ "dompurify": "^2.2.2",
"dropzone": "^4.2.0",
"editorconfig": "^0.15.3",
"emoji-regex": "^7.0.3",
@@ -90,8 +91,8 @@
"font-awesome": "4.7.0",
"fuzzaldrin-plus": "^0.6.0",
"glob": "^7.1.6",
- "graphql": "^14.7.0",
- "graphql-tag": "^2.10.1",
+ "graphql": "^15.4.0",
+ "graphql-tag": "^2.11.0",
"immer": "^7.0.7",
"imports-loader": "^0.8.0",
"ipaddr.js": "^1.9.1",
@@ -114,7 +115,7 @@
"mock-apollo-client": "^0.4.0",
"monaco-editor": "^0.20.0",
"monaco-editor-webpack-plugin": "^1.9.0",
- "monaco-yaml": "^2.4.1",
+ "monaco-yaml": "^2.5.1",
"mousetrap": "1.6.5",
"pdfjs-dist": "^2.0.943",
"pikaday": "^1.8.0",
@@ -161,7 +162,7 @@
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
- "@gitlab/eslint-plugin": "4.0.0",
+ "@gitlab/eslint-plugin": "5.0.0",
"@testing-library/dom": "^7.16.2",
"@vue/test-utils": "1.0.0-beta.30",
"acorn": "^6.3.0",
@@ -201,7 +202,7 @@
"karma-mocha-reporter": "^2.2.5",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^4.0.2",
- "markdownlint-cli": "0.23.2",
+ "markdownlint-cli": "0.24.0",
"md5": "^2.2.1",
"node-sass": "^4.14.1",
"nodemon": "^2.0.4",
diff --git a/public/robots.txt b/public/robots.txt
index f3fe51a25b0..4029cae5145 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -14,6 +14,7 @@
# Global routes
User-Agent: *
Disallow: /autocomplete/users
+Disallow: /autocomplete/projects
Disallow: /search
Disallow: /admin
Disallow: /profile
@@ -21,8 +22,11 @@ Disallow: /dashboard
Disallow: /users
Disallow: /help
Disallow: /s/
-# Only specifically allow the Sign In page to avoid very ugly search results
+Disallow: /-/profile
+Disallow: /-/ide/
+# Restrict allowed routes to avoid very ugly search results
Allow: /users/sign_in
+Allow: /users/*/snippets
# Generic resource routes like new, edit, raw
# This will block routes like:
@@ -32,6 +36,7 @@ User-Agent: *
Disallow: /*/new
Disallow: /*/edit
Disallow: /*/raw
+Disallow: /*/realtime_changes
# Group details
User-Agent: *
@@ -41,7 +46,7 @@ Disallow: /groups/*/group_members
# Project details
User-Agent: *
-Disallow: /*/*.git
+Disallow: /*/*.git$
Disallow: /*/archive/
Disallow: /*/repository/archive*
Disallow: /*/activity
@@ -63,3 +68,16 @@ Disallow: /*/protected_branches
Disallow: /*/uploads/
Disallow: /*/project_members
Disallow: /*/settings
+Disallow: /*/-/import
+Disallow: /*/-/environments
+Disallow: /*/-/jobs
+Disallow: /*/-/requirements_management
+Disallow: /*/-/pipelines
+Disallow: /*/-/pipeline_schedules
+Disallow: /*/-/dependencies
+Disallow: /*/-/licenses
+Disallow: /*/-/metrics
+Disallow: /*/-/incidents
+Disallow: /*/-/value_stream_analytics
+Disallow: /*/-/analytics
+Disallow: /*/insights
diff --git a/qa/Dockerfile b/qa/Dockerfile
index 6310e4b290d..925c9758450 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -1,4 +1,4 @@
-FROM ruby:2.6-stretch
+FROM ruby:2.7-buster
LABEL maintainer="GitLab Quality Department <quality@gitlab.com>"
ENV DEBIAN_FRONTEND="noninteractive"
@@ -65,7 +65,7 @@ COPY VERSION ./ee/app/models/license.r[b] /home/gitlab/ee/app/models/
COPY ./lib/gitlab.rb /home/gitlab/lib/
COPY ./lib/gitlab/utils.rb /home/gitlab/lib/gitlab/
COPY ./INSTALLATION_TYPE ./VERSION /home/gitlab/
-RUN cd /home/gitlab/qa/ && bundle install --jobs=$(nproc) --retry=3 --quiet
+RUN cd /home/gitlab/qa/ && bundle install --jobs=$(nproc) --retry=3 --without=development --quiet
COPY ./qa /home/gitlab/qa
ENTRYPOINT ["bin/test"]
diff --git a/qa/Gemfile b/qa/Gemfile
index f00f26a5482..fa8fd40d5bb 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -23,5 +23,4 @@ gem 'rspec-parameterized', '~> 0.4.2'
group :development do
gem 'pry-byebug', '~> 3.5.1', platform: :mri
gem "ruby-debug-ide", "~> 0.7.0"
- gem "debase", "~> 0.2.4.1"
end
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 6cdedc3834d..883c5480689 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -175,4 +175,4 @@ DEPENDENCIES
timecop (~> 0.9.1)
BUNDLED WITH
- 1.17.3
+ 2.1.4
diff --git a/qa/bin/qa b/qa/bin/qa
index 6a772e93cee..cbaad4bd7ad 100755
--- a/qa/bin/qa
+++ b/qa/bin/qa
@@ -2,6 +2,20 @@
require_relative '../qa'
+scenario = ARGV.shift
+
+if scenario.to_s.empty?
+ puts <<~INFO
+ For instructions on how to run tests, please see https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/README.md
+
+ If you are using gitlab-qa, please see https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md
+
+ If you see this message after starting a docker container and you intended to launch an omnibus-gitlab instance, try removing `-qa` from the image name.
+ INFO
+
+ exit
+end
+
QA::Scenario
- .const_get(ARGV.shift)
+ .const_get(scenario)
.launch!(ARGV)
diff --git a/qa/qa.rb b/qa/qa.rb
index f281a4b6ef4..ee7f97e64b1 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -19,6 +19,7 @@ module QA
autoload :Saml, 'qa/flow/saml'
autoload :User, 'qa/flow/user'
autoload :MergeRequest, 'qa/flow/merge_request'
+ autoload :Pipeline, 'qa/flow/pipeline'
end
##
@@ -402,6 +403,7 @@ module QA
module Layout
autoload :Banner, 'qa/page/layout/banner'
+ autoload :Flash, 'qa/page/layout/flash'
autoload :PerformanceBar, 'qa/page/layout/performance_bar'
end
diff --git a/qa/qa/flow/pipeline.rb b/qa/qa/flow/pipeline.rb
new file mode 100644
index 00000000000..ff23907c081
--- /dev/null
+++ b/qa/qa/flow/pipeline.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module QA
+ module Flow
+ module Pipeline
+ module_function
+
+ # In some cases we don't need to wait for anything, blocked, running or pending is acceptable
+ # Some cases only need pipeline to finish with different condition (completion, success or replication)
+ def visit_latest_pipeline(pipeline_condition: nil)
+ Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Pipeline::Index.perform(&:"wait_for_latest_pipeline_#{pipeline_condition}") if pipeline_condition
+ Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline)
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index abd9332ced0..ce4eac7fbc4 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -34,19 +34,26 @@ module QA
@retry_later_backoff = QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME
end
+ def inspect
+ # For prettier failure messages
+ # Eg.: "expected QA::Page::File::Show not to have file "QA Test - File name"
+ # Instead of "expected #<QA::Page::File::Show:0x000055c6511e07b8 @retry_later_backoff=60> not to have file "QA Test - File name"
+ self.class.to_s
+ end
+
def assert_no_element(name)
assert_no_selector(element_selector_css(name))
end
- def refresh
+ def refresh(skip_finished_loading_check: false)
page.refresh
- wait_for_requests
+ wait_for_requests(skip_finished_loading_check: skip_finished_loading_check)
end
- def wait_until(max_duration: 60, sleep_interval: 0.1, reload: true, raise_on_failure: true)
+ def wait_until(max_duration: 60, sleep_interval: 0.1, reload: true, raise_on_failure: true, skip_finished_loading_check_on_refresh: false)
Support::Waiter.wait_until(max_duration: max_duration, sleep_interval: sleep_interval, raise_on_failure: raise_on_failure) do
- yield || (reload && refresh && false)
+ yield || (reload && refresh(skip_finished_loading_check: skip_finished_loading_check_on_refresh) && false)
end
end
diff --git a/qa/qa/page/component/design_management.rb b/qa/qa/page/component/design_management.rb
index fafbda58b07..cccf1cf1a58 100644
--- a/qa/qa/page/component/design_management.rb
+++ b/qa/qa/page/component/design_management.rb
@@ -64,7 +64,7 @@ module QA
# It doesn't work as a CSS selector.
# So instead we use the name attribute as a locator
within_element(:design_dropzone_content) do
- page.attach_file("design_file", design_file_path, make_visible: { display: 'block' })
+ page.attach_file("upload_file", design_file_path, make_visible: { display: 'block' })
end
filename = ::File.basename(design_file_path)
diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb
index 82347ee209a..cc39260ce38 100644
--- a/qa/qa/page/component/issuable/sidebar.rb
+++ b/qa/qa/page/component/issuable/sidebar.rb
@@ -64,8 +64,14 @@ module QA
end
def has_assignee?(username)
- page.within(element_selector_css(:assignee_block)) do
- has_text?(username)
+ within_element(:assignee_block) do
+ has_text?(username, wait: 120)
+ end
+ end
+
+ def has_no_assignee_named?(username)
+ within_element(:assignee_block) do
+ has_no_text?(username, wait: 120)
end
end
diff --git a/qa/qa/page/component/note.rb b/qa/qa/page/component/note.rb
index e6defd2ec0c..5ac72d73c78 100644
--- a/qa/qa/page/component/note.rb
+++ b/qa/qa/page/component/note.rb
@@ -13,20 +13,35 @@ module QA
element :toggle_comments_button
end
+ base.view 'app/assets/javascripts/notes/components/comment_form.vue' do
+ element :comment_button
+ element :comment_field
+ element :discussion_menu_item
+ element :note_dropdown
+ end
+
base.view 'app/assets/javascripts/notes/components/discussion_actions.vue' do
element :discussion_reply_tab
element :resolve_discussion_button
end
- base.view 'app/assets/javascripts/notes/components/comment_form.vue' do
- element :note_dropdown
- element :discussion_menu_item
+ base.view 'app/assets/javascripts/notes/components/discussion_filter.vue' do
+ element :discussion_filter_dropdown, required: true
+ element :filter_menu_item
+ end
+
+ base.view 'app/assets/javascripts/notes/components/discussion_filter_note.vue' do
+ element :discussion_filter_container
end
base.view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do
element :discussion_content
end
+ base.view 'app/assets/javascripts/notes/components/noteable_note.vue' do
+ element :noteable_note_container
+ end
+
base.view 'app/assets/javascripts/notes/components/note_actions.vue' do
element :note_edit_button
end
@@ -36,6 +51,10 @@ module QA
element :reply_comment_button
end
+ base.view 'app/assets/javascripts/notes/components/note_header.vue' do
+ element :system_note_content
+ end
+
base.view 'app/assets/javascripts/notes/components/toggle_replies_widget.vue' do
element :expand_replies_button
element :collapse_replies_button
@@ -44,12 +63,30 @@ module QA
base.view 'app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue' do
element :skeleton_note_placeholder
end
+
+ base.view 'app/views/shared/notes/_form.html.haml' do
+ element :new_note_form, 'new-note' # rubocop:disable QA/ElementWithPattern
+ element :new_note_form, 'attr: :note' # rubocop:disable QA/ElementWithPattern
+ end
end
def collapse_replies
click_element :collapse_replies_button
end
+ # Attachment option should be an absolute path
+ def comment(text, attachment: nil, filter: :all_activities)
+ method("select_#{filter}_filter").call
+ fill_element :comment_field, "#{text}\n"
+
+ unless attachment.nil?
+ QA::Page::Component::Dropzone.new(self, '.new-note')
+ .attach_file(attachment)
+ end
+
+ click_element :comment_button
+ end
+
def edit_comment(text)
click_element :note_edit_button
fill_element :reply_field, text
@@ -60,6 +97,18 @@ module QA
click_element :expand_replies_button
end
+ def has_comment?(comment_text)
+ has_element?(:noteable_note_container, text: comment_text, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
+ end
+
+ def has_system_note?(note_text)
+ has_element?(:system_note_content, text: note_text, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
+ end
+
+ def noteable_note_item
+ find_element(:noteable_note_container)
+ end
+
def reply_to_discussion(position, reply_text)
type_reply_to_discussion(position, reply_text)
click_element :reply_comment_button
@@ -71,6 +120,26 @@ module QA
end
end
+ def select_all_activities_filter
+ select_filter_with_text('Show all activity')
+ end
+
+ def select_comments_only_filter
+ select_filter_with_text('Show comments only')
+
+ wait_until do
+ has_no_element?(:system_note_content)
+ end
+ end
+
+ def select_history_only_filter
+ select_filter_with_text('Show history only')
+
+ wait_until do
+ has_element?(:discussion_filter_container) && has_no_element?(:noteable_note_container)
+ end
+ end
+
def start_discussion(text)
fill_element :comment_field, text
click_element :note_dropdown
@@ -90,6 +159,18 @@ module QA
def wait_for_loading
has_no_element?(:skeleton_note_placeholer)
end
+
+ private
+
+ def select_filter_with_text(text)
+ retry_on_exception do
+ click_element(:title)
+ click_element :discussion_filter_dropdown
+ find_element(:filter_menu_item, text: text).click
+
+ wait_for_loading
+ end
+ end
end
end
end
diff --git a/qa/qa/page/component/select2.rb b/qa/qa/page/component/select2.rb
index 87aed0105aa..7a835af2575 100644
--- a/qa/qa/page/component/select2.rb
+++ b/qa/qa/page/component/select2.rb
@@ -38,6 +38,16 @@ module QA
select_item(item_text)
end
+ def search_and_select_exact(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)
+
+ find('.select2-result-label', text: item_text, exact_text: true).click
+ end
+
def expand_select_list
find('span.select2-arrow').click
end
diff --git a/qa/qa/page/component/snippet.rb b/qa/qa/page/component/snippet.rb
index 9a4b06d8ac7..459c02ec883 100644
--- a/qa/qa/page/component/snippet.rb
+++ b/qa/qa/page/component/snippet.rb
@@ -110,6 +110,18 @@ module QA
end
end
+ def has_no_file_name?(file_name, file_number = nil)
+ if file_number
+ within_element_by_index(:file_title_content, file_number - 1) do
+ has_no_text?(file_name)
+ end
+ else
+ within_element(:file_title_content) do
+ has_no_text?(file_name)
+ end
+ end
+ end
+
def has_file_content?(file_content, file_number = nil)
if file_number
within_element_by_index(:file_content, file_number - 1) do
@@ -170,6 +182,7 @@ module QA
def add_comment(comment)
fill_element(:note_field, comment)
click_element(:comment_button)
+ wait_until(reload: false) { has_element?(:note_author_content) }
end
def has_comment_author?(author_username)
@@ -194,6 +207,7 @@ module QA
click_element(:edit_comment_button)
fill_element(:edit_note_field, comment)
click_element(:save_comment_button)
+ wait_until(reload: false) { has_element?(:note_author_content) }
end
def delete_comment(comment)
@@ -201,6 +215,7 @@ module QA
accept_alert do
click_element(:delete_comment_button)
end
+ wait_until(reload: false) { has_no_text?(comment) }
end
end
end
diff --git a/qa/qa/page/dashboard/snippet/edit.rb b/qa/qa/page/dashboard/snippet/edit.rb
index 37c0747aea4..40add146e97 100644
--- a/qa/qa/page/dashboard/snippet/edit.rb
+++ b/qa/qa/page/dashboard/snippet/edit.rb
@@ -9,6 +9,15 @@ module QA
element :submit_button, required: true
end
+ view 'app/assets/javascripts/snippets/components/snippet_blob_edit.vue' do
+ element :file_name_field
+ element :file_holder_container
+ end
+
+ view 'app/assets/javascripts/blob/components/blob_edit_header.vue' do
+ element :delete_file_button
+ end
+
def add_to_file_content(content)
text_area.set content
text_area.has_text?(content) # wait for changes to take effect
@@ -18,7 +27,38 @@ module QA
choose(visibility_type)
end
+ def click_add_file
+ click_element(:add_file_button)
+ end
+
+ def fill_file_name(name, file_number = nil)
+ if file_number
+ within_element_by_index(:file_holder_container, file_number - 1) do
+ fill_element(:file_name_field, name)
+ end
+ else
+ fill_element(:file_name_field, name)
+ end
+ end
+
+ def fill_file_content(content, file_number = nil)
+ if file_number
+ within_element_by_index(:file_holder_container, file_number - 1) do
+ text_area.set(content)
+ end
+ else
+ text_area.set(content)
+ end
+ end
+
+ def click_delete_file(file_number)
+ within_element_by_index(:file_holder_container, file_number - 1) do
+ click_element(:delete_file_button)
+ end
+ end
+
def save_changes
+ wait_until(reload: false) { !find_element(:submit_button).disabled? }
click_element(:submit_button, Page::Dashboard::Snippet::Show)
end
diff --git a/qa/qa/page/file/shared/commit_message.rb b/qa/qa/page/file/shared/commit_message.rb
index 823ce7bf7f9..906f5f3581a 100644
--- a/qa/qa/page/file/shared/commit_message.rb
+++ b/qa/qa/page/file/shared/commit_message.rb
@@ -13,11 +13,19 @@ module QA
base.view 'app/views/shared/_commit_message_container.html.haml' do
element :commit_message, "text_area_tag 'commit_message'" # rubocop:disable QA/ElementWithPattern
end
+
+ base.view 'app/views/projects/commits/_commit.html.haml' do
+ element :commit_content
+ end
end
def add_commit_message(message)
fill_in 'commit_message', with: message
end
+
+ def has_commit_message?(text)
+ has_element?(:commit_content, text: text)
+ end
end
end
end
diff --git a/qa/qa/page/file/show.rb b/qa/qa/page/file/show.rb
index f5f44909f25..665b3c34dcc 100644
--- a/qa/qa/page/file/show.rb
+++ b/qa/qa/page/file/show.rb
@@ -7,16 +7,25 @@ module QA
include Shared::CommitMessage
include Project::SubMenus::Settings
include Project::SubMenus::Common
+ include Layout::Flash
view 'app/helpers/blob_helper.rb' do
element :edit_button, "_('Edit')" # rubocop:disable QA/ElementWithPattern
element :delete_button, '_("Delete")' # rubocop:disable QA/ElementWithPattern
end
+ view 'app/views/projects/blob/_header_content.html.haml' do
+ element :file_name_content
+ end
+
view 'app/views/projects/blob/_remove.html.haml' do
element :delete_file_button, "button_tag 'Delete file'" # rubocop:disable QA/ElementWithPattern
end
+ view 'app/views/shared/_file_highlight.html.haml' do
+ element :file_content
+ end
+
def click_edit
click_on 'Edit'
end
@@ -28,6 +37,18 @@ module QA
def click_delete_file
click_on 'Delete file'
end
+
+ def has_file?(name)
+ has_element?(:file_name_content, text: name)
+ end
+
+ def has_no_file?(name)
+ has_no_element?(:file_name_content, text: name)
+ end
+
+ def has_file_content?(text)
+ has_element?(:file_content, text: text)
+ end
end
end
end
diff --git a/qa/qa/page/group/members.rb b/qa/qa/page/group/members.rb
index dce18ee5c55..16e447a2be5 100644
--- a/qa/qa/page/group/members.rb
+++ b/qa/qa/page/group/members.rb
@@ -16,17 +16,24 @@ module QA
element :invite_member_button
end
- view 'app/views/shared/members/_member.html.haml' do
+ view 'app/assets/javascripts/pages/groups/group_members/index.js' do
element :member_row
+ element :groups_list
+ element :group_row
+ end
+
+ view 'app/assets/javascripts/vue_shared/components/members/table/role_dropdown.vue' do
element :access_level_dropdown
+ element :access_level_link
+ end
+
+ view 'app/assets/javascripts/vue_shared/components/members/action_buttons/remove_member_button.vue' do
element :delete_member_button
- element :developer_access_level_link, 'qa_selector: "#{role.downcase}_access_level_link"' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck
end
view 'app/views/groups/group_members/index.html.haml' do
element :invite_group_tab
element :groups_list_tab
- element :groups_list
end
view 'app/views/shared/members/_invite_group.html.haml' do
@@ -34,10 +41,6 @@ module QA
element :invite_group_button
end
- view 'app/views/shared/members/_group.html.haml' do
- element :group_row
- end
-
def select_group(group_name)
click_element :group_select_field
search_and_select(group_name)
@@ -57,7 +60,7 @@ module QA
def update_access_level(username, access_level)
within_element(:member_row, text: username) do
click_element :access_level_dropdown
- click_element "#{access_level.downcase}_access_level_link"
+ click_element :access_level_link, text: access_level
end
end
diff --git a/qa/qa/page/group/show.rb b/qa/qa/page/group/show.rb
index 7639def98b7..38d919be4db 100644
--- a/qa/qa/page/group/show.rb
+++ b/qa/qa/page/group/show.rb
@@ -7,11 +7,8 @@ module QA
include Page::Component::GroupsFilter
view 'app/views/groups/_home_panel.html.haml' do
- element :new_project_or_subgroup_dropdown
- element :new_project_or_subgroup_dropdown_toggle
- element :new_project_option
- element :new_subgroup_option
- element :new_in_group_button
+ element :new_project_button
+ element :new_subgroup_button
end
view 'app/assets/javascripts/groups/constants.js' do
@@ -26,8 +23,9 @@ module QA
click_link name
end
- def has_new_project_or_subgroup_dropdown?
- has_element?(:new_project_or_subgroup_dropdown)
+ def has_new_project_and_new_subgroup_buttons?
+ has_element?(:new_project_button)
+ has_element?(:new_subgroup_button)
end
def has_subgroup?(name)
@@ -35,15 +33,11 @@ module QA
end
def go_to_new_subgroup
- select_kind :new_subgroup_option
-
- click_element :new_in_group_button
+ click_element :new_subgroup_button
end
def go_to_new_project
- select_kind :new_project_option
-
- click_element :new_in_group_button
+ click_element :new_project_button
end
def leave_group
@@ -51,23 +45,6 @@ module QA
click_element :leave_group_link
end
end
-
- private
-
- def select_kind(kind)
- QA::Support::Retrier.retry_on_exception(sleep_interval: 1.0) do
- within_element(:new_project_or_subgroup_dropdown) do
- # May need to click again because it is possible to click the button quicker than the JS is bound
- wait_until(reload: false) do
- click_element :new_project_or_subgroup_dropdown_toggle
-
- has_element?(kind)
- end
-
- click_element kind
- end
- end
- end
end
end
end
diff --git a/qa/qa/page/layout/flash.rb b/qa/qa/page/layout/flash.rb
new file mode 100644
index 00000000000..6bd3d6ab76b
--- /dev/null
+++ b/qa/qa/page/layout/flash.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Layout
+ module Flash
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.view 'app/views/layouts/_flash.html.haml' do
+ element :flash_container
+ end
+ end
+
+ def has_notice?(message)
+ within_element(:flash_container) do
+ has_text?(message)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index 8eb28eb53e7..265e2b7573c 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -125,9 +125,9 @@ module QA
click_element :sign_in_tab
end
- def switch_to_register_tab
+ def switch_to_register_page
set_initial_password_if_present
- click_element :register_tab
+ click_element :register_link
end
def switch_to_ldap_tab
diff --git a/qa/qa/page/main/sign_up.rb b/qa/qa/page/main/sign_up.rb
index 98bbbc53027..f8e85798012 100644
--- a/qa/qa/page/main/sign_up.rb
+++ b/qa/qa/page/main/sign_up.rb
@@ -13,20 +13,18 @@ module QA
element :new_user_register_button
end
- view 'app/views/registrations/welcome.html.haml' do
+ view 'app/views/registrations/welcome/show.html.haml' do
element :get_started_button
end
def sign_up!(user)
- fill_element :new_user_first_name_field, user.first_name
- fill_element :new_user_last_name_field, user.last_name
- fill_element :new_user_username_field, user.username
- fill_element :new_user_email_field, user.email
- fill_element :new_user_password_field, user.password
-
- signed_in = retry_until do
+ signed_in = retry_until(raise_on_failure: false) do
+ fill_element :new_user_first_name_field, user.first_name
+ fill_element :new_user_last_name_field, user.last_name
+ fill_element :new_user_username_field, user.username
+ fill_element :new_user_email_field, user.email
+ fill_element :new_user_password_field, user.password
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?)
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index 164f25389c0..ac4d38e5918 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -23,7 +23,6 @@ module QA
element :merge_button
element :fast_forward_message, 'Fast-forward merge without a merge commit' # rubocop:disable QA/ElementWithPattern
element :merge_moment_dropdown
- element :merge_when_pipeline_succeeds_option
element :merge_immediately_option
end
@@ -178,6 +177,10 @@ module QA
has_element?(:file_name_content, text: file_name)
end
+ def has_no_file?(file_name)
+ has_no_element?(:file_name_content, text: file_name)
+ end
+
def has_merge_button?
refresh
@@ -219,6 +222,11 @@ module QA
raise "Merge did not appear to be successful" unless merged?
end
+ def merge_immediately!
+ click_element(:merge_moment_dropdown)
+ click_element(:merge_immediately_option)
+ end
+
def merged?
has_element?(:merged_status_content, text: 'The changes were merged into', wait: 60)
end
diff --git a/qa/qa/page/profile/personal_access_tokens.rb b/qa/qa/page/profile/personal_access_tokens.rb
index fd191fa3e27..caa8c0ceb40 100644
--- a/qa/qa/page/profile/personal_access_tokens.rb
+++ b/qa/qa/page/profile/personal_access_tokens.rb
@@ -6,8 +6,11 @@ module QA
module Page
module Profile
class PersonalAccessTokens < Page::Base
- view 'app/views/shared/access_tokens/_form.html.haml' do
+ view 'app/assets/javascripts/access_tokens/components/expires_at_field.vue' do
element :expiry_date_field
+ end
+
+ view 'app/views/shared/access_tokens/_form.html.haml' do
element :access_token_name_field
element :create_token_button
end
diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb
index b533e0096a8..ad1746258ea 100644
--- a/qa/qa/page/project/import/github.rb
+++ b/qa/qa/page/project/import/github.rb
@@ -67,7 +67,9 @@ module QA
end
def wait_for_success
- wait_until(max_duration: 60, sleep_interval: 1.0, reload: false) do
+ # TODO: set reload:false and remove skip_finished_loading_check_on_refresh when
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/231542 is fixed
+ wait_until(max_duration: 60, sleep_interval: 5.0, reload: true, skip_finished_loading_check_on_refresh: true) do
page.has_content?('Done', wait: 1.0)
end
end
diff --git a/qa/qa/page/project/issue/index.rb b/qa/qa/page/project/issue/index.rb
index 0b47bec2cf1..64bd62c2b54 100644
--- a/qa/qa/page/project/issue/index.rb
+++ b/qa/qa/page/project/issue/index.rb
@@ -15,13 +15,13 @@ module QA
element :avatar_counter_content
end
- view 'app/views/projects/issues/export_csv/_button.html.haml' do
+ view 'app/views/shared/issuable/csv_export/_button.html.haml' do
element :export_as_csv_button
end
- view 'app/views/projects/issues/export_csv/_modal.html.haml' do
+ view 'app/views/shared/issuable/csv_export/_modal.html.haml' do
element :export_issues_button
- element :export_issues_modal
+ element :export_issuable_modal
end
view 'app/views/projects/issues/import_csv/_button.html.haml' do
@@ -64,7 +64,7 @@ module QA
end
def export_issues_modal
- find_element(:export_issues_modal)
+ find_element(:export_issuable_modal)
end
def go_to_jira_import_form
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index a02617def9e..f7bd74d1882 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -10,20 +10,6 @@ module QA
include Page::Component::DesignManagement
include Page::Component::Issuable::Sidebar
- view 'app/assets/javascripts/notes/components/comment_form.vue' do
- element :comment_button
- element :comment_field
- end
-
- view 'app/assets/javascripts/notes/components/discussion_filter.vue' do
- element :discussion_filter, required: true
- element :filter_options
- end
-
- view 'app/assets/javascripts/notes/components/noteable_note.vue' do
- element :noteable_note_item
- end
-
view 'app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue' do
element :remove_related_issue_button
end
@@ -33,11 +19,6 @@ module QA
element :reopen_issue_button
end
- view 'app/views/shared/notes/_form.html.haml' do
- element :new_note_form, 'new-note' # rubocop:disable QA/ElementWithPattern
- 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
@@ -51,8 +32,8 @@ module QA
end
view 'app/assets/javascripts/related_issues/components/related_issues_list.vue' do
- element :related_issuable_item
- element :related_issues_loading_icon
+ element :related_issuable_content
+ element :related_issues_loading_placeholder
end
def relate_issue(issue)
@@ -62,11 +43,11 @@ module QA
end
def related_issuable_item
- find_element(:related_issuable_item)
+ find_element(:related_issuable_content)
end
def wait_for_related_issues_to_load
- has_no_element?(:related_issues_loading_icon, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
+ has_no_element?(:related_issues_loading_placeholder, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
end
def click_remove_related_issue_button
@@ -80,55 +61,9 @@ module QA
click_element :close_issue_button
end
- # Adds a comment to an issue
- # attachment option should be an absolute path
- def comment(text, attachment: nil, filter: :all_activities)
- method("select_#{filter}_filter").call
- fill_element :comment_field, "#{text}\n"
-
- unless attachment.nil?
- QA::Page::Component::Dropzone.new(self, '.new-note')
- .attach_file(attachment)
- end
-
- click_element :comment_button
- end
-
- def has_comment?(comment_text)
- has_element?(:noteable_note_item, text: comment_text, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
- end
-
- def noteable_note_item
- find_element(:noteable_note_item)
- end
-
- def select_all_activities_filter
- select_filter_with_text('Show all activity')
- end
-
- def select_comments_only_filter
- select_filter_with_text('Show comments only')
- end
-
- def select_history_only_filter
- select_filter_with_text('Show history only')
- end
-
def has_metrics_unfurled?
has_element?(:prometheus_graph_widgets, wait: 30)
end
-
- private
-
- def select_filter_with_text(text)
- retry_on_exception do
- click_element(:title)
- click_element :discussion_filter
- find_element(:filter_options, text: text).click
-
- wait_for_loading
- end
- end
end
end
end
diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb
index 0fb5238a308..b32d099d2b0 100644
--- a/qa/qa/page/project/pipeline/show.rb
+++ b/qa/qa/page/project/pipeline/show.rb
@@ -26,6 +26,10 @@ module QA
element :child_pipeline
end
+ view 'app/assets/javascripts/reports/components/report_section.vue' do
+ element :expand_report_button
+ end
+
view 'app/assets/javascripts/vue_shared/components/ci_icon.vue' do
element :status_icon, 'ci-status-icon-${status}' # rubocop:disable QA/ElementWithPattern
end
@@ -78,6 +82,12 @@ module QA
end
end
+ def expand_license_report
+ within_element(:license_report_widget) do
+ click_element(:expand_report_button)
+ end
+ end
+
def click_on_first_job
first('.js-pipeline-graph-job-link', wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME).click
end
diff --git a/qa/qa/page/project/settings/advanced.rb b/qa/qa/page/project/settings/advanced.rb
index 97519c3906c..757084fc5b9 100644
--- a/qa/qa/page/project/settings/advanced.rb
+++ b/qa/qa/page/project/settings/advanced.rb
@@ -11,6 +11,9 @@ module QA
view 'app/views/projects/edit.html.haml' do
element :project_path_field
element :change_path_button
+ end
+
+ view 'app/views/projects/_transfer.html.haml' do
element :transfer_button
end
diff --git a/qa/qa/page/project/settings/mirroring_repositories.rb b/qa/qa/page/project/settings/mirroring_repositories.rb
index ddace6d0533..ce369c90a9f 100644
--- a/qa/qa/page/project/settings/mirroring_repositories.rb
+++ b/qa/qa/page/project/settings/mirroring_repositories.rb
@@ -98,7 +98,7 @@ module QA
sleep 5
refresh
- wait_until(sleep_interval: 1) do
+ wait_until(max_duration: 180, sleep_interval: 1) do
within_element_by_index(:mirrored_repository_row, row_index) do
last_update = find_element(:mirror_last_update_at_cell, wait: 0)
last_update.has_text?('just now') || last_update.has_text?('seconds')
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index d81be2803bd..4f0cf55c127 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -4,9 +4,11 @@ module QA
module Page
module Project
class Show < Page::Base
+ include Layout::Flash
include Page::Component::ClonePanel
include Page::Component::Breadcrumbs
include Page::Project::SubMenus::Settings
+ include Page::File::Shared::CommitMessage
view 'app/assets/javascripts/repository/components/preview/index.vue' do
element :blob_viewer_content
@@ -121,6 +123,12 @@ module QA
end
end
+ def has_no_file?(name)
+ within_element(:file_tree_table) do
+ has_no_element?(:file_name_link, text: name)
+ end
+ end
+
def has_name?(name)
has_element?(:project_name_content, text: name)
end
@@ -129,10 +137,6 @@ module QA
has_element?(:blob_viewer_content, text: text)
end
- def last_commit_content
- find_element(:commit_content).text
- end
-
def new_merge_request
wait_until(reload: true) do
has_css?(element_selector_css(:create_merge_request))
diff --git a/qa/qa/resource/file.rb b/qa/qa/resource/file.rb
index f573f3e89f0..0d2bf9890ea 100644
--- a/qa/qa/resource/file.rb
+++ b/qa/qa/resource/file.rb
@@ -5,14 +5,21 @@ module QA
class File < Base
attr_accessor :author_email,
:author_name,
- :branch,
:content,
:commit_message,
:name
+ attr_writer :branch
attribute :project do
Project.fabricate! do |resource|
resource.name = 'project-with-new-file'
+
+ # Creating the first file via the Wed IDE is tested in
+ # browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb
+ # So here we want to use the old blob viewer, which is not
+ # available via the UI unless at least one file exists, which
+ # is why we create the project with a readme file.
+ resource.initialize_with_readme = true
end
end
@@ -22,28 +29,23 @@ module QA
@commit_message = 'QA Test - Commit message'
end
+ def branch
+ @branch ||= "master"
+ end
+
def fabricate!
project.visit!
- Page::Project::Show.perform(&:create_first_new_file!)
-
- Page::Project::WebIDE::Edit.perform do |ide|
- ide.add_file(@name, @content)
- ide.commit_changes(@commit_message)
- ide.go_to_project
- end
+ Page::Project::Show.perform(&:create_new_file!)
- Page::Project::Show.perform do |project|
- project.click_file(@name)
+ Page::File::Form.perform do |form|
+ form.add_name(@name)
+ form.add_content(@content)
+ form.add_commit_message(@commit_message)
+ form.commit_changes
end
end
- def resource_web_url(resource)
- super
- rescue ResourceURLMissingError
- # this particular resource does not expose a web_url property
- end
-
def api_get_path
"/projects/#{CGI.escape(project.path_with_namespace)}/repository/files/#{CGI.escape(@name)}"
end
@@ -54,13 +56,20 @@ module QA
def api_post_body
{
- branch: @branch || "master",
+ branch: branch,
author_email: @author_email || Runtime::User.default_email,
author_name: @author_name || Runtime::User.username,
content: content,
commit_message: commit_message
}
end
+
+ private
+
+ def transform_api_resource(api_resource)
+ api_resource[:web_url] = "#{Runtime::Scenario.gitlab_address}/#{project.full_path}/-/tree/#{branch}/#{api_resource[:file_path]}"
+ api_resource
+ end
end
end
end
diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb
index 1cb33a7c71c..2e29ec9a6a7 100644
--- a/qa/qa/resource/group.rb
+++ b/qa/qa/resource/group.rb
@@ -44,7 +44,7 @@ module QA
# Ensure that the group was actually created
group_show.wait_until(sleep_interval: 1) do
group_show.has_text?(path) &&
- group_show.has_new_project_or_subgroup_dropdown?
+ group_show.has_new_project_and_new_subgroup_buttons?
end
end
end
diff --git a/qa/qa/resource/issue.rb b/qa/qa/resource/issue.rb
index d96d8d744d2..a6bd8987077 100644
--- a/qa/qa/resource/issue.rb
+++ b/qa/qa/resource/issue.rb
@@ -57,6 +57,21 @@ module QA
hash[:weight] = @weight if @weight
end
end
+
+ def api_put_path
+ "/projects/#{project.id}/issues/#{iid}"
+ end
+
+ def set_issue_assignees(assignee_ids:)
+ put_body = { assignee_ids: assignee_ids }
+ response = put Runtime::API::Request.new(api_client, api_put_path).url, put_body
+
+ unless response.code == HTTP_STATUS_OK
+ raise ResourceUpdateFailedError, "Could not update issue assignees to #{assignee_ids}. Request returned (#{response.code}): `#{response}`."
+ end
+
+ QA::Runtime::Logger.debug("Successfully updated issue assignees to #{assignee_ids}")
+ end
end
end
end
diff --git a/qa/qa/resource/project_imported_from_github.rb b/qa/qa/resource/project_imported_from_github.rb
index df28d63b113..0b817b345fd 100644
--- a/qa/qa/resource/project_imported_from_github.rb
+++ b/qa/qa/resource/project_imported_from_github.rb
@@ -6,6 +6,7 @@ module QA
module Resource
class ProjectImportedFromGithub < Resource::Project
def fabricate!
+ self.import = true
super
group.visit!
diff --git a/qa/qa/resource/project_snippet.rb b/qa/qa/resource/project_snippet.rb
index 6fa38baaa91..c262499664e 100644
--- a/qa/qa/resource/project_snippet.rb
+++ b/qa/qa/resource/project_snippet.rb
@@ -31,6 +31,14 @@ module QA
new_snippet.click_create_snippet_button
end
end
+
+ def api_get_path
+ "/projects/#{project.id}/snippets/#{snippet_id}"
+ end
+
+ def api_post_path
+ "/projects/#{project.id}/snippets"
+ end
end
end
end
diff --git a/qa/qa/resource/runner.rb b/qa/qa/resource/runner.rb
index b2a36f92ffe..2a0823d648e 100644
--- a/qa/qa/resource/runner.rb
+++ b/qa/qa/resource/runner.rb
@@ -29,7 +29,7 @@ module QA
end
def executor_image
- @executor_image || 'registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.6'
+ @executor_image || 'registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7'
end
def fabricate_via_api!
diff --git a/qa/qa/resource/snippet.rb b/qa/qa/resource/snippet.rb
index c4ea6447209..6fdcb1cd29b 100644
--- a/qa/qa/resource/snippet.rb
+++ b/qa/qa/resource/snippet.rb
@@ -3,7 +3,7 @@
module QA
module Resource
class Snippet < Base
- attr_accessor :title, :description, :file_content, :visibility, :file_name
+ attr_accessor :title, :description, :file_content, :visibility, :file_name, :snippet_id
def initialize
@title = 'New snippet title'
@@ -36,6 +36,36 @@ module QA
new_page.click_create_snippet_button
end
end
+
+ def fabricate_via_api!
+ resource_web_url(api_post)
+ rescue ResourceNotFoundError
+ super
+ end
+
+ def api_get_path
+ "/snippets/#{snippet_id}"
+ end
+
+ def api_post_path
+ '/snippets'
+ end
+
+ def api_post_body
+ {
+ title: title,
+ description: description,
+ visibility: visibility.downcase,
+ files: all_file_contents
+ }
+ end
+
+ def all_file_contents
+ @files.insert(0, { name: @file_name, content: @file_content })
+ @files.each do |file|
+ file[:file_path] = file.delete(:name)
+ end
+ end
end
end
end
diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb
index 5cd4147e154..ca30ff12480 100644
--- a/qa/qa/resource/user.rb
+++ b/qa/qa/resource/user.rb
@@ -75,7 +75,7 @@ module QA
end
else
Page::Main::Login.perform do |login|
- login.switch_to_register_tab
+ login.switch_to_register_page
end
Page::Main::SignUp.perform do |signup|
signup.sign_up!(self)
diff --git a/qa/qa/runtime/application_settings.rb b/qa/qa/runtime/application_settings.rb
index c78f4258721..428ed20c83f 100644
--- a/qa/qa/runtime/application_settings.rb
+++ b/qa/qa/runtime/application_settings.rb
@@ -33,7 +33,7 @@ module QA
def api_client
@api_client ||= Runtime::API::Client.as_admin
- rescue AuthorizationError => e
+ rescue API::Client::AuthorizationError => e
raise "Administrator access is required to set application settings. #{e.message}"
end
end
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index ddaf35a2d65..4c4dd416093 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -8,7 +8,7 @@ module QA
module Env
extend self
- attr_writer :personal_access_token, :ldap_username, :ldap_password
+ attr_writer :personal_access_token
ENV_VARIABLES = Gitlab::QA::Runtime::Env::ENV_VARIABLES
@@ -293,6 +293,11 @@ module QA
@ldap_username ||= ENV['GITLAB_LDAP_USERNAME']
end
+ def ldap_username=(ldap_username)
+ @ldap_username = ldap_username # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ ENV['GITLAB_LDAP_USERNAME'] = ldap_username
+ end
+
def ldap_password
@ldap_password ||= ENV['GITLAB_LDAP_PASSWORD']
end
diff --git a/qa/qa/service/docker_run/gitlab_runner.rb b/qa/qa/service/docker_run/gitlab_runner.rb
index e15047a0f1d..a5b129eb1f9 100644
--- a/qa/qa/service/docker_run/gitlab_runner.rb
+++ b/qa/qa/service/docker_run/gitlab_runner.rb
@@ -21,7 +21,7 @@ module QA
@name = name || "qa-runner-#{SecureRandom.hex(4)}"
@run_untagged = true
@executor = :shell
- @executor_image = 'registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.6'
+ @executor_image = 'registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7'
super()
end
diff --git a/qa/qa/service/praefect_manager.rb b/qa/qa/service/praefect_manager.rb
index 3a17acbb317..ab4f28c292f 100644
--- a/qa/qa/service/praefect_manager.rb
+++ b/qa/qa/service/praefect_manager.rb
@@ -206,14 +206,14 @@ module QA
def wait_for_new_primary_node(node)
QA::Runtime::Logger.info("Wait until #{node} is the primary node")
- with_praefect_log do |log|
+ with_praefect_log(max_duration: 120) do |log|
break true if log['msg'] == 'primary node changed' && log['newPrimary'] == node
end
end
def wait_for_new_primary
QA::Runtime::Logger.info("Wait until a new primary node is selected")
- with_praefect_log do |log|
+ with_praefect_log(max_duration: 120) do |log|
break true if log['msg'] == 'primary node changed'
end
end
@@ -406,8 +406,8 @@ module QA
end
end
- def with_praefect_log
- wait_until_shell_command("docker exec #{@praefect} bash -c 'tail -n 1 /var/log/gitlab/praefect/current'") do |line|
+ def with_praefect_log(**kwargs)
+ wait_until_shell_command("docker exec #{@praefect} bash -c 'tail -n 1 /var/log/gitlab/praefect/current'", **kwargs) do |line|
QA::Runtime::Logger.debug(line.chomp)
yield JSON.parse(line)
end
diff --git a/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
index 90f58090ccd..223ed02bb47 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
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- context 'Gitaly automatic failover and manual recovery', :orchestrated, :gitaly_cluster, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/238953', type: :flaky } do
+ context 'Gitaly automatic failover and recovery', :orchestrated, :gitaly_cluster, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/238953', type: :flaky } do
# Variables shared between contexts. They're used and shared between
# contexts so they can't be `let` variables.
praefect_manager = Service::PraefectManager.new
@@ -66,17 +66,13 @@ 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 }, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/977' do
+ it 'automatically reconciles', 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
- # Confirm dataloss (i.e., inconsistent nodes)
- expect(praefect_manager.replicated?(project.id)).to be false
-
- # Reconcile nodes to recover from dataloss
- praefect_manager.reconcile_nodes
- praefect_manager.wait_for_replication(project.id)
+ # Confirm automatic reconciliation
+ expect(praefect_manager.replicated?(project.id)).to be true
# Confirm that all commits are available after reconciliation
expect(project.commits.map { |commit| commit[:message].chomp })
diff --git a/qa/qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb b/qa/qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb
index 6072fd8c1a2..e02d32bc4c7 100644
--- a/qa/qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb
+++ b/qa/qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb
@@ -25,6 +25,18 @@ module QA
push.file_content = "Target branch test target branch #{SecureRandom.hex(8)}"
end
+ # Confirm the target branch can be checked out to avoid a race condition
+ # where the subsequent push option attempts to create an MR before the target branch is ready.
+ Support::Retrier.retry_on_exception(sleep_interval: 5) do
+ Git::Repository.perform do |repository|
+ repository.uri = project.repository_http_location.uri
+ repository.use_default_credentials
+ repository.clone
+ repository.configure_identity('GitLab QA', 'root@gitlab.com')
+ repository.checkout(target_branch)
+ end
+ end
+
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.branch_name = "push-options-test-#{SecureRandom.hex(8)}"
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 23de213012e..163469e1e88 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
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context 'Manage', :requires_admin, :skip_live_env do
+ RSpec.describe 'Manage', :requires_admin, :skip_live_env do
describe '2FA' do
let(:owner_user) do
Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_2fa_owner_username_1, Runtime::Env.gitlab_qa_2fa_owner_password_1)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb
index e81ebd5fa9d..7f3c3049499 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb
@@ -22,7 +22,7 @@ module QA
it 'allows 2FA code recovery via ssh' do
recovery_code = Support::SSH.perform do |ssh|
ssh.key = ssh_key
- ssh.uri = address.gsub(uri.port.to_s, ssh_port)
+ ssh.uri = address.gsub(/(?<=:)(#{uri.port})/, ssh_port)
ssh.setup
output = ssh.reset_2fa_codes
output.scan(/([A-Za-z0-9]{16})\n/).flatten.first
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 e514507fcb6..12a1b419f8b 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
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context 'Manage', :requires_admin, :skip_live_env do
+ RSpec.describe 'Manage', :requires_admin, :skip_live_env do
describe '2FA' do
let(:owner_user) do
Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_2fa_owner_username_1, Runtime::Env.gitlab_qa_2fa_owner_password_1)
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 f6aecff9f26..e4ac59cf5e0 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
@@ -12,7 +12,9 @@ module QA
login_page.login('user1', 'user1pass')
end
- expect(page).to have_content('Welcome to GitLab')
+ Page::Dashboard::Welcome.perform do |welcome|
+ expect(welcome).to have_content('Welcome to GitLab')
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
index 11a6bf6fdfa..2bb03b6154f 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
@@ -13,11 +13,39 @@ module QA
end
end
- RSpec.describe 'Manage', :skip_signup_disabled do
+ RSpec.describe 'Manage', :skip_signup_disabled, :requires_admin do
+ describe 'while LDAP is enabled', :orchestrated, :ldap_no_tls, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/935' do
+ before do
+ # When LDAP is enabled, a previous test might have created a token for the LDAP 'tanuki' user who is not an admin
+ # So we need to set it to nil in order to create a new token for admin user so that we are able to set_application_settings
+ # Also, when GITLAB_LDAP_USERNAME is provided, it is used to create a token. This also needs to be set to nil temporarily
+ # for the same reason as above.
+
+ @personal_access_token = Runtime::Env.personal_access_token
+ Runtime::Env.personal_access_token = nil
+ ldap_username = Runtime::Env.ldap_username
+ Runtime::Env.ldap_username = nil
+
+ disable_require_admin_approval_after_user_signup
+
+ Runtime::Env.ldap_username = ldap_username
+ end
+
+ it_behaves_like 'registration and login'
+
+ after do
+ Runtime::Env.personal_access_token = @personal_access_token
+ end
+ end
+
describe 'standard', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/936' do
+ before(:all) do
+ disable_require_admin_approval_after_user_signup
+ end
+
it_behaves_like 'registration and login'
- context 'when user account is deleted', :requires_admin do
+ context 'when user account is deleted' do
let(:user) do
Resource::User.fabricate_via_api! do |resource|
resource.api_client = admin_api_client
@@ -61,11 +89,10 @@ module QA
end
end
end
- end
- RSpec.describe 'Manage', :orchestrated, :ldap_no_tls, :skip_signup_disabled do
- describe 'while LDAP is enabled', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/935' do
- it_behaves_like 'registration and login'
+ def disable_require_admin_approval_after_user_signup
+ Runtime::ApplicationSettings.set_application_settings(require_admin_approval_after_user_signup: false)
+ sleep 10 # It takes a moment for the setting to come into effect
end
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 27350176a1e..e71cbeb9837 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
@@ -15,9 +15,9 @@ module QA
Page::Project::Menu.perform(&:click_members)
Page::Project::Members.perform do |members|
members.add_member(user.username)
- end
- expect(page).to have_content(/@#{user.username}(\n| )?Given access/)
+ expect(members).to have_content(/@#{user.username}( Is using seat)?(\n| )?Given access/)
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
index 6d07f72a044..2f2f40cba3b 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
@@ -11,12 +11,14 @@ module QA
project.description = 'create awesome project test'
end
- expect(page).to have_content(created_project.name)
- expect(page).to have_content(
- /Project \S?awesome-project\S+ was successfully created/
- )
- expect(page).to have_content('create awesome project test')
- expect(page).to have_content('The repository for this project is empty')
+ Page::Project::Show.perform do |project|
+ expect(project).to have_content(created_project.name)
+ expect(project).to have_content(
+ /Project \S?awesome-project\S+ was successfully created/
+ )
+ expect(project).to have_content('create awesome project test')
+ expect(project).to have_content('The repository for this project is empty')
+ end
end
end
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 83dfb2d9639..d54ce0ac0fc 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
@@ -1,30 +1,35 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :github, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/issues/26952', type: :bug } do
- describe 'Project import from GitHub' do
+ RSpec.describe 'Manage', :github, :requires_admin do
+ describe 'Project import' do
+ let!(:user) do
+ Resource::User.fabricate_via_api! do |resource|
+ resource.api_client = Runtime::API::Client.as_admin
+ end
+ end
+
+ let(:group) { Resource::Group.fabricate_via_api! }
+
let(:imported_project) do
- Resource::ProjectImportedFromGithub.fabricate! do |project|
+ Resource::ProjectImportedFromGithub.fabricate_via_browser_ui! do |project|
project.name = 'imported-project'
- project.personal_access_token = Runtime::Env.github_access_token
- project.github_repository_path = 'gitlab-qa/test-project'
+ project.group = group
+ project.github_personal_access_token = Runtime::Env.github_access_token
+ project.github_repository_path = 'gitlab-qa-github/test-project'
end
end
- after do
- # We need to delete the imported project because it's impossible to import
- # the same GitHub project twice for a given user.
- api_client = Runtime::API::Client.new(:gitlab)
- delete_project_request = Runtime::API::Request.new(api_client, "/projects/#{CGI.escape("#{Runtime::Namespace.path}/#{imported_project.name}")}")
- delete delete_project_request.url
-
- expect_status(202)
+ before do
+ group.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
+ end
- Page::Main::Menu.perform(&:sign_out_if_signed_in)
+ after do
+ user.remove_via_api!
end
- it 'user imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/385' do
- Flow::Login.sign_in
+ it 'imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/385' do
+ Flow::Login.sign_in(as: user)
imported_project # import the project
@@ -44,25 +49,28 @@ module QA
end
def verify_repository_import
- expect(page).to have_content('This test project is used for automated GitHub import by GitLab QA.')
- expect(page).to have_content(imported_project.name)
+ Page::Project::Show.perform do |project|
+ expect(project).to have_content('This test project is used for automated GitHub import by GitLab QA.')
+ expect(project).to have_content(imported_project.name)
+ end
end
def verify_issues_import
QA::Support::Retrier.retry_on_exception do
Page::Project::Menu.perform(&:click_issues)
- expect(page).to have_content('This is a sample issue')
- click_link 'This is a sample issue'
+ Page::Project::Issue::Show.perform do |issue_page|
+ expect(issue_page).to have_content('This is a sample issue')
- expect(page).to have_content('We should populate this project with issues, pull requests and wiki pages.')
+ click_link 'This is a sample issue'
- # Comments
- comment_text = 'This is a comment from @rymai.'
+ expect(issue_page).to have_content('This is a sample first comment')
+
+ # Comments
+ comment_text = 'This is a comment from @sliaquat'
- Page::Project::Issue::Show.perform do |issue_page|
expect(issue_page).to have_comment(comment_text)
- expect(issue_page).to have_label('enhancement')
+ expect(issue_page).to have_label('custom new label')
expect(issue_page).to have_label('help wanted')
expect(issue_page).to have_label('good first issue')
end
@@ -71,26 +79,23 @@ module QA
def verify_merge_requests_import
Page::Project::Menu.perform(&:click_merge_requests)
- expect(page).to have_content('Improve README.md')
- click_link 'Improve README.md'
+ Page::MergeRequest::Show.perform do |merge_request|
+ expect(merge_request).to have_content('Improve readme')
- expect(page).to have_content('This improves the README file a bit.')
+ click_link 'Improve readme'
- # Review comment are not supported yet
- expect(page).not_to have_content('Really nice change.')
+ expect(merge_request).to have_content('This improves the README file a bit.')
- # Comments
- expect(page).to have_content('Nice work! This is a comment from @rymai.')
+ # Comments
+ expect(merge_request).to have_content('[PR comment by @sliaquat] Nice work!')
- # Diff comments
- expect(page).to have_content('[Review comment] I like that!')
- expect(page).to have_content('[Review comment] Nice blank line.')
- expect(page).to have_content('[Single diff comment] Much better without this line!')
+ # Diff comments
+ expect(merge_request).to have_content('[Single diff comment] Good riddance')
+ expect(merge_request).to have_content('[Single diff comment] Nice addition')
- Page::MergeRequest::Show.perform do |merge_request|
expect(merge_request).to have_label('bug')
- expect(merge_request).to have_label('enhancement')
+ expect(merge_request).to have_label('documentation')
end
end
@@ -107,7 +112,9 @@ module QA
def verify_wiki_import
Page::Project::Menu.perform(&:click_wiki)
- expect(page).to have_content('Welcome to the test-project wiki!')
+ Page::Project::Wiki::Show.perform do |wiki|
+ expect(wiki).to have_content('Welcome to the test-project wiki!')
+ end
end
end
end
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 fd6d26153ea..3609d083fde 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
@@ -13,9 +13,11 @@ module QA
end.project.visit!
Page::Project::Menu.perform(&:click_activity)
- Page::Project::Activity.perform(&:click_push_events)
+ Page::Project::Activity.perform do |activity|
+ activity.click_push_events
- expect(page).to have_content('pushed new branch master')
+ expect(activity).to have_content('pushed new branch master')
+ end
end
end
end
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 6b309716f55..22157d648ca 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
@@ -26,7 +26,7 @@ module QA
expect(show).not_to have_content(my_first_reply)
show.expand_replies
- expect(show).to have_content(my_first_reply)
+ expect(show).to have_comment(my_first_reply)
expect(show).not_to have_content(one_reply)
end
end
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 c9ae47459c4..d3780186f36 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
@@ -16,11 +16,11 @@ module QA
show.comment(first_version_of_comment)
- expect(show).to have_content(first_version_of_comment)
+ expect(show).to have_comment(first_version_of_comment)
show.edit_comment(second_version_of_comment)
- expect(show).to have_content(second_version_of_comment)
+ expect(show).to have_comment(second_version_of_comment)
expect(show).not_to have_content(first_version_of_comment)
end
end
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 863c394a9f9..9550572bd5c 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
@@ -19,7 +19,7 @@ module QA
end
end
- 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
+ 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/1085' do
closed_issue.visit!
Page::Project::Issue::Show.perform do |issue_page|
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 9a054e7d1c8..e275c3decd3 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
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Plan', :reliable do
+ RSpec.describe 'Plan' do
describe 'filter issue comments activities' do
before do
Flow::Login.sign_in
@@ -18,16 +18,16 @@ module QA
show.comment(my_own_comment, filter: :comments_only)
expect(show).not_to have_content(made_the_issue_confidential)
- expect(show).to have_content(my_own_comment)
+ expect(show).to have_comment(my_own_comment)
show.select_all_activities_filter
- expect(show).to have_content(made_the_issue_confidential)
- expect(show).to have_content(my_own_comment)
+ expect(show).to have_system_note(made_the_issue_confidential)
+ expect(show).to have_comment(my_own_comment)
show.select_history_only_filter
- expect(show).to have_content(made_the_issue_confidential)
+ expect(show).to have_system_note(made_the_issue_confidential)
expect(show).not_to have_content(my_own_comment)
end
end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb
new file mode 100644
index 00000000000..26a83fc3caa
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Plan', :requires_admin, :actioncable, :orchestrated do
+ describe 'Assignees' do
+ let(:user1) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
+ let(:user2) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_2, Runtime::Env.gitlab_qa_password_2) }
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-to-test-assignees'
+ end
+ end
+
+ before do
+ Runtime::Feature.enable('real_time_issue_sidebar', project: project)
+ Runtime::Feature.enable('broadcast_issue_updates', project: project)
+
+ Flow::Login.sign_in
+
+ project.add_member(user1)
+ project.add_member(user2)
+ end
+
+ after do
+ Runtime::Feature.disable('real_time_issue_sidebar', project: project)
+ Runtime::Feature.disable('broadcast_issue_updates', project: project)
+ end
+
+ it 'update without refresh', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1048' do
+ issue = Resource::Issue.fabricate_via_api! do |issue|
+ issue.project = project
+ issue.assignee_ids = [user1.id]
+ end
+
+ issue.visit!
+
+ Page::Project::Issue::Show.perform do |show|
+ expect(show).to have_assignee(user1.name)
+
+ issue.set_issue_assignees(assignee_ids: [user2.id])
+
+ expect(show).to have_assignee(user2.name)
+ expect(show).to have_no_assignee_named(user1.name)
+
+ issue.set_issue_assignees(assignee_ids: [])
+
+ expect(show).to have_no_assignee_named(user1.name)
+ expect(show).to have_no_assignee_named(user2.name)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb
index 7844d0d7ccb..970615e8b90 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb
@@ -3,8 +3,15 @@
module QA
RSpec.describe 'Create', :requires_admin do
describe 'View merge request merge-ref diff' do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'merge-ref-diff'
+ end
+ end
+
let(:merge_request) do
Resource::MergeRequest.fabricate_via_api! do |merge_request|
+ merge_request.project = project
merge_request.title = 'This is a merge request'
merge_request.description = '... for viewing merge-ref and merge-base diffs'
merge_request.file_content = 'This exists on the source branch only'
@@ -13,16 +20,14 @@ module QA
let(:new_file_name) { "added_file-#{SecureRandom.hex(8)}.txt" }
- before do
- commit_to_branch(merge_request.target_branch, new_file_name)
- commit_to_branch(merge_request.source_branch, new_file_name)
-
- Flow::Login.sign_in
- end
-
context 'when the feature flag default_merge_ref_for_diffs is enabled' do
before do
- Runtime::Feature.enable('default_merge_ref_for_diffs', project: merge_request.project)
+ Runtime::Feature.enable('default_merge_ref_for_diffs', project: project)
+
+ commit_to_branch(merge_request.target_branch, new_file_name)
+ commit_to_branch(merge_request.source_branch, new_file_name)
+
+ Flow::Login.sign_in
merge_request.visit!
end
@@ -42,7 +47,12 @@ module QA
context 'when the feature flag default_merge_ref_for_diffs is disabled' do
before do
- Runtime::Feature.disable('default_merge_ref_for_diffs', project: merge_request.project)
+ Runtime::Feature.disable('default_merge_ref_for_diffs', project: project)
+
+ commit_to_branch(merge_request.target_branch, new_file_name)
+ commit_to_branch(merge_request.source_branch, new_file_name)
+
+ Flow::Login.sign_in
merge_request.visit!
end
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
deleted file mode 100644
index 5aa5f0fc0a3..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create' do
- describe 'Files management' 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)
-
- # Create
- file_name = 'QA Test - File name'
- file_content = 'QA Test - File content'
- commit_message_for_create = 'QA Test - Create new file'
-
- Resource::File.fabricate_via_browser_ui! do |file|
- file.name = file_name
- file.content = file_content
- file.commit_message = commit_message_for_create
- end
-
- expect(page).to have_content(file_name)
- expect(page).to have_content(file_content)
- expect(page).to have_content(commit_message_for_create)
-
- # Edit
- updated_file_content = 'QA Test - Updated file content'
- commit_message_for_update = 'QA Test - Update file'
-
- Page::File::Show.perform(&:click_edit)
-
- Page::File::Form.act do
- remove_content
- add_content(updated_file_content)
- add_commit_message(commit_message_for_update)
- commit_changes
- end
-
- expect(page).to have_content('Your changes have been successfully committed.')
- expect(page).to have_content(updated_file_content)
- expect(page).to have_content(commit_message_for_update)
-
- # Delete
- commit_message_for_delete = 'QA Test - Delete file'
-
- Page::File::Show.act do
- click_delete
- add_commit_message(commit_message_for_delete)
- click_delete_file
- end
-
- expect(page).to have_content('The file has been successfully deleted.')
- expect(page).to have_content(commit_message_for_delete)
- expect(page).to have_no_content(file_name)
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb
new file mode 100644
index 00000000000..cd333b3cea2
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ context 'File management' do
+ file_name = 'QA Test - File name'
+ file_content = 'QA Test - File content'
+ commit_message_for_create = 'QA Test - Create new file'
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ it 'user creates a file via the Web', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1093' do
+ Resource::File.fabricate_via_browser_ui! do |file|
+ file.name = file_name
+ file.content = file_content
+ file.commit_message = commit_message_for_create
+ end
+
+ Page::File::Show.perform do |file|
+ aggregate_failures 'file details' do
+ expect(file).to have_file(file_name)
+ expect(file).to have_file_content(file_content)
+ expect(file).to have_commit_message(commit_message_for_create)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb
new file mode 100644
index 00000000000..903001aa4f0
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ context 'File management' do
+ let(:file) { Resource::File.fabricate_via_api! }
+
+ commit_message_for_delete = 'QA Test - Delete file'
+
+ before do
+ Flow::Login.sign_in
+ file.visit!
+ end
+
+ it 'user deletes a file via the Web', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1095' do
+ Page::File::Show.perform do |file|
+ file.click_delete
+ file.add_commit_message(commit_message_for_delete)
+ file.click_delete_file
+ end
+
+ Page::Project::Show.perform do |project|
+ aggregate_failures 'file details' do
+ expect(project).to have_notice('The file has been successfully deleted.')
+ expect(project).to have_commit_message(commit_message_for_delete)
+ expect(project).not_to have_file(file.name)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb
new file mode 100644
index 00000000000..0da774b557f
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ context 'File management' do
+ let(:file) { Resource::File.fabricate_via_api! }
+
+ updated_file_content = 'QA Test - Updated file content'
+ commit_message_for_update = 'QA Test - Update file'
+
+ before do
+ Flow::Login.sign_in
+ file.visit!
+ end
+
+ it 'user edits a file via the Web', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1094' do
+ Page::File::Show.perform(&:click_edit)
+
+ Page::File::Form.perform do |file|
+ file.remove_content
+ file.add_content(updated_file_content)
+ file.add_commit_message(commit_message_for_update)
+ file.commit_changes
+ end
+
+ Page::File::Show.perform do |file|
+ aggregate_failures 'file details' do
+ expect(file).to have_notice('Your changes have been successfully committed.')
+ expect(file).to have_file_content(updated_file_content)
+ expect(file).to have_commit_message(commit_message_for_update)
+ end
+ end
+ end
+ end
+ end
+end
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
index 45afa252305..e4a492d3487 100644
--- 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
@@ -3,7 +3,7 @@
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
+ it 'configures and syncs LFS objects for a (push) mirrored repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1075' 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_mirroring_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb
index 00d4acbd1e1..f01a3b21eee 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
@@ -35,8 +35,11 @@ module QA
# 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('This is a test project')
+
+ Page::Project::Show.perform do |project|
+ expect(project).to have_content('README.md')
+ expect(project).to have_content('This is a test project')
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb
new file mode 100644
index 00000000000..469335db5ab
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Multiple file snippet' do
+ let(:personal_snippet) do
+ Resource::Snippet.fabricate_via_api! do |snippet|
+ snippet.title = 'Personal snippet to add file to'
+ snippet.file_name = 'Original file name'
+ snippet.file_content = 'Original file content'
+ end
+ end
+
+ let(:project_snippet) do
+ Resource::ProjectSnippet.fabricate_via_api! do |snippet|
+ snippet.title = 'Project snippet to add file to'
+ snippet.file_name = 'Original file name'
+ snippet.file_content = 'Original file content'
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ shared_examples 'adding file to snippet' do |snippet_type|
+ it "adds second file to an existing #{snippet_type} to make it multi-file" do
+ send(snippet_type).visit!
+
+ Page::Dashboard::Snippet::Show.perform(&:click_edit_button)
+
+ Page::Dashboard::Snippet::Edit.perform do |snippet|
+ snippet.click_add_file
+ snippet.fill_file_name('Second file name', 2)
+ snippet.fill_file_content('Second file content', 2)
+ snippet.save_changes
+ end
+
+ Page::Dashboard::Snippet::Show.perform do |snippet|
+ aggregate_failures 'file names and contents' do
+ expect(snippet).to have_file_name('Original file name', 1)
+ expect(snippet).to have_file_content('Original file content', 1)
+ expect(snippet).to have_file_name('Second file name', 2)
+ expect(snippet).to have_file_content('Second file content', 2)
+ end
+ end
+ end
+ end
+
+ it_behaves_like 'adding file to snippet', :personal_snippet
+ it_behaves_like 'adding file to snippet', :project_snippet
+ end
+ end
+end
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 a3f6d521766..efd61a2e63a 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', quarantine: { only: { subdomain: :staging }, issue: 'https://gitlab.com/gitlab-org/gitaly/-/issues/3143', type: :bug } do
+ RSpec.describe 'Create' do
describe 'Version control for personal snippets' do
let(:new_file) { 'new_snippet_file' }
let(:changed_content) { 'changes' }
@@ -22,13 +22,13 @@ module QA
end
let(:repository_uri_http) do
- snippet
+ snippet.visit!
Page::Dashboard::Snippet::Show.perform(&:get_repository_uri_http)
end
let(:repository_uri_ssh) do
ssh_key
- snippet
+ snippet.visit!
Page::Dashboard::Snippet::Show.perform(&:get_repository_uri_ssh)
end
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 be56b870490..79e2677da66 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', quarantine: { only: { subdomain: :staging }, issue: 'https://gitlab.com/gitlab-org/gitaly/-/issues/3143', type: :bug } do
+ RSpec.describe 'Create' do
describe 'Version control for project snippets' do
let(:new_file) { 'new_snippet_file' }
let(:changed_content) { 'changes' }
@@ -22,13 +22,13 @@ module QA
end
let(:repository_uri_http) do
- snippet
+ snippet.visit!
Page::Dashboard::Snippet::Show.perform(&:get_repository_uri_http)
end
let(:repository_uri_ssh) do
ssh_key
- snippet
+ snippet.visit!
Page::Dashboard::Snippet::Show.perform(&:get_repository_uri_ssh)
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb
new file mode 100644
index 00000000000..ca6ea5db65d
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Multiple file snippet' do
+ let(:personal_snippet) do
+ Resource::Snippet.fabricate_via_api! do |snippet|
+ snippet.title = 'Personal snippet to delete file from'
+ snippet.file_name = 'Original file name'
+ snippet.file_content = 'Original file content'
+
+ snippet.add_files do |files|
+ files.append(name: 'Second file name', content: 'Second file content')
+ end
+ end
+ end
+
+ let(:project_snippet) do
+ Resource::ProjectSnippet.fabricate_via_api! do |snippet|
+ snippet.title = 'Project snippet to delete file from'
+ snippet.file_name = 'Original file name'
+ snippet.file_content = 'Original file content'
+
+ snippet.add_files do |files|
+ files.append(name: 'Second file name', content: 'Second file content')
+ end
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ shared_examples 'deleting file from snippet' do |snippet_type|
+ it "deletes second file from an existing #{snippet_type} to make it single-file" do
+ send(snippet_type).visit!
+
+ Page::Dashboard::Snippet::Show.perform(&:click_edit_button)
+
+ Page::Dashboard::Snippet::Edit.perform do |snippet|
+ snippet.click_delete_file(2)
+ snippet.save_changes
+ end
+
+ Page::Dashboard::Snippet::Show.perform do |snippet|
+ aggregate_failures 'file names and contents' do
+ expect(snippet).to have_file_name('Original file name')
+ expect(snippet).to have_file_content('Original file content')
+ expect(snippet).to have_no_file_name('Second file name')
+ expect(snippet).to have_no_file_content('Second file content')
+ end
+ end
+ end
+ end
+
+ it_behaves_like 'deleting file from snippet', :personal_snippet
+ it_behaves_like 'deleting file from snippet', :project_snippet
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
index 6b21d84cb13..971c5371d44 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
@@ -18,7 +18,7 @@ module QA
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
+ snippet.visit!
sharing_link = Page::Dashboard::Snippet::Show.perform do |snippet|
expect(snippet).to have_embed_dropdown
@@ -40,7 +40,7 @@ module QA
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
+ snippet.visit!
Page::Dashboard::Snippet::Show.perform do |snippet|
expect(snippet).to have_embed_dropdown
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 8de739f1559..1e6cb4047f9 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
@@ -65,8 +65,7 @@ module QA
)
end.project.visit!
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
- Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline)
+ Flow::Pipeline.visit_latest_pipeline
{
'test-success': :passed,
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb
new file mode 100644
index 00000000000..cedc2db2a1a
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb
@@ -0,0 +1,138 @@
+# frozen_string_literal: true
+
+require 'faker'
+
+module QA
+ RSpec.describe 'Verify', :runner, :requires_admin, :skip_live_env do
+ describe "Include multiple files from a project" do
+ let(:feature_flag) { :ci_include_multiple_files_from_project }
+ let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" }
+ let(:expected_text) { Faker::Lorem.sentence }
+ let(:unexpected_text) { Faker::Lorem.sentence }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-pipeline-1'
+ end
+ end
+
+ let(:other_project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-pipeline-2'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.project = project
+ runner.name = executor
+ runner.tags = [executor]
+ end
+ end
+
+ before do
+ Runtime::Feature.enable(feature_flag)
+ Flow::Login.sign_in
+ add_included_files
+ add_main_ci_file
+ project.visit!
+ view_the_last_pipeline
+ end
+
+ after do
+ Runtime::Feature.disable(feature_flag)
+ runner.remove_via_api!
+ end
+
+ it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1082' do
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ aggregate_failures 'pipeline has all expected jobs' do
+ expect(pipeline).to have_job('build')
+ expect(pipeline).to have_job('test')
+ expect(pipeline).to have_job('deploy')
+ end
+
+ pipeline.click_job('test')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ aggregate_failures 'main CI is not overridden' do
+ expect(job.output).to have_no_content("#{unexpected_text}")
+ expect(job.output).to have_content("#{expected_text}")
+ end
+ end
+ end
+
+ private
+
+ def add_main_ci_file
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add config file'
+ commit.add_files([main_ci_file])
+ end
+ end
+
+ def add_included_files
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = other_project
+ commit.commit_message = 'Add files'
+ commit.add_files([included_file_1, included_file_2])
+ end
+ end
+
+ def view_the_last_pipeline
+ Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Pipeline::Index.perform(&:wait_for_latest_pipeline_success)
+ Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline)
+ end
+
+ def main_ci_file
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ include:
+ - project: #{other_project.full_path}
+ file:
+ - file1.yml
+ - file2.yml
+
+ build:
+ stage: build
+ tags: ["#{executor}"]
+ script: echo 'build'
+
+ test:
+ stage: test
+ tags: ["#{executor}"]
+ script: echo "#{expected_text}"
+ YAML
+ }
+ end
+
+ def included_file_1
+ {
+ file_path: 'file1.yml',
+ content: <<~YAML
+ test:
+ stage: test
+ tags: ["#{executor}"]
+ script: echo "#{unexpected_text}"
+ YAML
+ }
+ end
+
+ def included_file_2
+ {
+ file_path: 'file2.yml',
+ content: <<~YAML
+ deploy:
+ stage: deploy
+ tags: ["#{executor}"]
+ script: echo 'deploy'
+ YAML
+ }
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb
new file mode 100644
index 00000000000..c5d73d2fd7d
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'faker'
+
+module QA
+ RSpec.describe 'Verify', :runner do
+ context 'When pipeline is blocked' do
+ let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-blocked-pipeline'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.project = project
+ runner.name = executor
+ runner.tags = [executor]
+ end
+ end
+
+ let!(:ci_file) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files(
+ [
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ test_blocked_pipeline:
+ stage: build
+ tags: [#{executor}]
+ script: echo 'OK!'
+
+ manual_job:
+ stage: test
+ needs: [test_blocked_pipeline]
+ script: echo do not click me
+ when: manual
+
+ dummy_job:
+ stage: deploy
+ needs: [manual_job]
+ script: echo nothing
+ YAML
+ ]
+ )
+ end
+ end
+
+ let(:merge_request) do
+ Resource::MergeRequest.fabricate_via_api! do |merge_request|
+ merge_request.project = project
+ merge_request.description = Faker::Lorem.sentence
+ merge_request.target_new_branch = false
+ merge_request.file_name = 'custom_file.txt'
+ merge_request.file_content = Faker::Lorem.sentence
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ merge_request.visit!
+ end
+
+ after do
+ runner.remove_via_api!
+ end
+
+ it 'can still merge MR successfully', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/971' do
+ Page::MergeRequest::Show.perform do |show|
+ show.wait_until(reload: false) { show.has_pipeline_status?('running') }
+ show.merge_immediately!
+
+ expect(show).to be_merged
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb
new file mode 100644
index 00000000000..eafe28c1ee6
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+require 'faker'
+
+module QA
+ RSpec.describe 'Verify', :runner, :requires_admin do
+ describe "Pass dotenv variables to downstream via bridge" do
+ let(:feature_flag) { :ci_bridge_dependency_variables }
+ let(:executor_1) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" }
+ let(:executor_2) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" }
+
+ let(:upstream_project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-pipeline-1'
+ end
+ end
+
+ let(:downstream_project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-pipeline-2'
+ end
+ end
+
+ let!(:runner_1) do
+ Resource::Runner.fabricate! do |runner|
+ runner.project = upstream_project
+ runner.name = executor_1
+ runner.tags = [executor_1]
+ end
+ end
+
+ let!(:runner_2) do
+ Resource::Runner.fabricate! do |runner|
+ runner.project = downstream_project
+ runner.name = executor_2
+ runner.tags = [executor_2]
+ end
+ end
+
+ before do
+ Runtime::Feature.enable(feature_flag)
+ Flow::Login.sign_in
+ add_ci_file(downstream_project, downstream_ci_file)
+ add_ci_file(upstream_project, upstream_ci_file)
+ upstream_project.visit!
+ Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'success')
+ end
+
+ after do
+ Runtime::Feature.disable(feature_flag)
+ runner_1.remove_via_api!
+ runner_2.remove_via_api!
+ end
+
+ it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1086' do
+ Page::Project::Pipeline::Show.perform do |parent_pipeline|
+ Support::Waiter.wait_until { parent_pipeline.has_child_pipeline? }
+ parent_pipeline.expand_child_pipeline
+ parent_pipeline.click_job('downstream_test')
+ end
+
+ Page::Project::Job::Show.perform do |show|
+ expect(show).to have_passed(timeout: 360)
+ end
+ end
+
+ private
+
+ def add_ci_file(project, file)
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add config file'
+ commit.add_files([file])
+ end
+ end
+
+ def upstream_ci_file
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ build:
+ stage: build
+ tags: ["#{executor_1}"]
+ script: echo "MY_VAR=hello" >> variables.env
+ artifacts:
+ reports:
+ dotenv: variables.env
+
+ trigger:
+ stage: deploy
+ variables:
+ PASSED_MY_VAR: $MY_VAR
+ trigger: #{downstream_project.full_path}
+ YAML
+ }
+ end
+
+ def downstream_ci_file
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ downstream_test:
+ stage: test
+ tags: ["#{executor_2}"]
+ script: '[ "$PASSED_MY_VAR" = hello ]; exit "$?"'
+ YAML
+ }
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb
index 153ccafaa20..b79bda108af 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb
@@ -2,11 +2,8 @@
module QA
RSpec.describe 'Verify' do
- describe 'Run pipeline', :requires_admin, :skip_live_env do
- # [TODO]: Developer to remove :requires_admin and :skip_live_env once FF is removed in https://gitlab.com/gitlab-org/gitlab/-/issues/229632
-
+ describe 'Run pipeline', only: { subdomain: :staging } do
context 'with web only rule' do
- let(:feature_flag) { :new_pipeline_form }
let(:job_name) { 'test_job' }
let(:project) do
Resource::Project.fabricate_via_api! do |project|
@@ -20,33 +17,29 @@ module QA
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files(
[
- {
- file_path: '.gitlab-ci.yml',
- content: <<~YAML
- #{job_name}:
- tags:
- - #{project.name}
- script: echo 'OK'
- only:
- - web
- YAML
- }
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ #{job_name}:
+ tags:
+ - #{project.name}
+ script: echo 'OK'
+ only:
+ - web
+
+ YAML
+ }
]
)
end
end
before do
- Runtime::Feature.enable(feature_flag) # [TODO]: Developer to remove when feature flag is removed
Flow::Login.sign_in
project.visit!
Page::Project::Menu.perform(&:click_ci_cd_pipelines)
end
- after do
- Runtime::Feature.disable(feature_flag) # [TODO]: Developer to remove when feature flag is removed
- end
-
it 'can trigger pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/946' do
Page::Project::Pipeline::Index.perform do |index|
expect(index).not_to have_pipeline # should not auto trigger pipeline
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb
index 39d5fbaba6b..2f66ed697a3 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb
@@ -29,7 +29,7 @@ module QA
Flow::Login.sign_in
add_ci_files
project.visit!
- view_the_last_pipeline
+ Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'success')
end
after do
@@ -64,12 +64,6 @@ module QA
end
end
- def view_the_last_pipeline
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
- Page::Project::Pipeline::Index.perform(&:wait_for_latest_pipeline_success)
- Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline)
- end
-
def parent_ci_file
{
file_path: '.gitlab-ci.yml',
diff --git a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb
new file mode 100644
index 00000000000..7783dba3fa7
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :packages do
+ describe 'Composer Repository' do
+ include Runtime::Fixtures
+
+ let(:package_name) { 'my_package' }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'composer-package-project'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let!(:gitlab_address_with_port) do
+ uri = URI.parse(Runtime::Scenario.gitlab_address)
+ "#{uri.scheme}://#{uri.host}:#{uri.port}"
+ end
+
+ let(:composer_json_file) do
+ <<~EOF
+ {
+ "name": "#{project.path_with_namespace}/#{package_name}",
+ "description": "Library XY",
+ "type": "library",
+ "license": "GPL-3.0-only",
+ "authors": [
+ {
+ "name": "John Doe",
+ "email": "john@example.com"
+ }
+ ],
+ "require": {}
+ }
+ EOF
+ end
+
+ let(:gitlab_ci_yaml) do
+ <<~YAML
+ publish:
+ image: curlimages/curl:latest
+ stage: build
+ variables:
+ URL: "$CI_SERVER_PROTOCOL://$CI_SERVER_HOST:$CI_SERVER_PORT/api/v4/projects/$CI_PROJECT_ID/packages/composer?job_token=$CI_JOB_TOKEN"
+ script:
+ - version=$([[ -z "$CI_COMMIT_TAG" ]] && echo "branch=$CI_COMMIT_REF_NAME" || echo "tag=$CI_COMMIT_TAG")
+ - insecure=$([ "$CI_SERVER_PROTOCOL" = "http" ] && echo "--insecure" || echo "")
+ - response=$(curl -s -w "%{http_code}" $insecure --data $version $URL)
+ - code=$(echo "$response" | tail -n 1)
+ - body=$(echo "$response" | head -n 1)
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ end
+
+ before do
+ Flow::Login.sign_in
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content: gitlab_ci_yaml
+ },
+ {
+ file_path: 'composer.json',
+ content: composer_json_file
+ }]
+ )
+ end
+
+ project.visit!
+ Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline)
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('publish')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+ end
+
+ after do
+ runner.remove_via_api!
+ end
+
+ it 'publishes a composer package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1088' do
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package_name)
+ index.click_package(package_name)
+ end
+
+ Page::Project::Packages::Show.perform do |package|
+ package.click_delete
+ end
+
+ Page::Project::Packages::Index.perform do |index|
+ aggregate_failures 'package deletion' do
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).to have_no_package(package_name)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb
new file mode 100644
index 00000000000..2b06ba8646f
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :packages do
+ describe 'Conan Repository' do
+ include Runtime::Fixtures
+
+ let(:package_name) { 'conantest' }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'conan-package-project'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let(:gitlab_address_with_port) do
+ uri = URI.parse(Runtime::Scenario.gitlab_address)
+ "#{uri.scheme}://#{uri.host}:#{uri.port}"
+ end
+
+ after do
+ runner.remove_via_api!
+ end
+
+ it 'publishes a conan package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1077' do
+ Flow::Login.sign_in
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ image: conanio/gcc7
+
+ create_package:
+ stage: deploy
+ script:
+ - "conan remote add gitlab #{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/conan"
+ - "conan new #{package_name}/0.1 -t"
+ - "conan create . mycompany/stable"
+ - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package_name}/0.1@mycompany/stable --all --remote=gitlab"
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ }])
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('create_package')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package_name)
+ index.click_package(package_name)
+ end
+
+ Page::Project::Packages::Show.perform do |package|
+ package.click_delete
+ end
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).to have_no_package(package_name)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
new file mode 100644
index 00000000000..e163fcbe574
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
@@ -0,0 +1,126 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :packages do
+ describe 'Maven Repository with Gradle' do
+ include Runtime::Fixtures
+
+ let(:group_id) { 'com.gitlab.qa' }
+ let(:artifact_id) { 'maven_gradle' }
+ let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') }
+ let(:auth_token) do
+ unless Page::Main::Menu.perform(&:signed_in?)
+ Flow::Login.sign_in
+ end
+
+ Resource::PersonalAccessToken.fabricate!.access_token
+ end
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'maven-with-gradle-project'
+ project.initialize_with_readme = true
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let(:gitlab_address_with_port) do
+ uri = URI.parse(Runtime::Scenario.gitlab_address)
+ "#{uri.scheme}://#{uri.host}:#{uri.port}"
+ end
+
+ after do
+ runner.remove_via_api!
+ end
+
+ it 'publishes a maven package via gradle', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1074' do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ deploy:
+ image: gradle:6.5-jdk11
+ script:
+ - 'gradle publish'
+ only:
+ - master
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ },
+ {
+ file_path: 'build.gradle',
+ content:
+ <<~EOF
+ plugins {
+ id 'java'
+ id 'maven-publish'
+ }
+
+ publishing {
+ publications {
+ library(MavenPublication) {
+ groupId '#{group_id}'
+ artifactId '#{artifact_id}'
+ from components.java
+ }
+ }
+ repositories {
+ maven {
+ url "#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/maven"
+ credentials(HttpHeaderCredentials) {
+ name = "Private-Token"
+ value = "#{auth_token}"
+ }
+ authentication {
+ header(HttpHeaderAuthentication)
+ }
+ }
+ }
+ }
+ EOF
+ }])
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package_name)
+
+ index.click_package(package_name)
+ end
+
+ Page::Project::Packages::Show.perform do |show|
+ show.click_delete
+ end
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).to have_no_package(package_name)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
new file mode 100644
index 00000000000..0b70adf9ff6
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :packages do
+ describe 'NuGet Repository' do
+ include Runtime::Fixtures
+
+ let(:package_name) { 'dotnetcore' }
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'nuget-package-project'
+ project.template_name = 'dotnetcore'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ after do
+ runner.remove_via_api!
+ end
+
+ it 'publishes a nuget package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1073' do
+ Flow::Login.sign_in
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.update_files(
+ [
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ image: mcr.microsoft.com/dotnet/core/sdk:3.1
+
+ stages:
+ - deploy
+
+ deploy:
+ stage: deploy
+ script:
+ - dotnet restore -p:Configuration=Release
+ - dotnet build -c Release
+ - dotnet pack -c Release
+ - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
+ - dotnet nuget push "bin/Release/*.nupkg" --source gitlab
+ only:
+ - master
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ }
+ ]
+ )
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package_name)
+ index.click_package(package_name)
+ end
+
+ Page::Project::Packages::Show.perform do |package|
+ package.click_delete
+ end
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).to have_no_package(package_name)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb
new file mode 100644
index 00000000000..35c41bbb2b0
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :packages do
+ describe 'PyPI Repository' do
+ include Runtime::Fixtures
+
+ let(:package_name) { 'mypypipackage' }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'pypi-package-project'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let(:gitlab_address_with_port) do
+ uri = URI.parse(Runtime::Scenario.gitlab_address)
+ "#{uri.scheme}://#{uri.host}:#{uri.port}"
+ end
+
+ before do
+ Flow::Login.sign_in
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ 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 #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi dist/*"
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ },
+ {
+ file_path: 'setup.py',
+ content:
+ <<~EOF
+ import setuptools
+
+ setuptools.setup(
+ name="mypypipackage",
+ version="0.0.1",
+ author="Example Author",
+ author_email="author@example.com",
+ description="A small example package",
+ packages=setuptools.find_packages(),
+ classifiers=[
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+ ],
+ python_requires='>=3.6',
+ )
+ EOF
+
+ }])
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('run')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+ end
+
+ after do
+ runner.remove_via_api!
+ end
+
+ it 'publishes a pypi package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1087' do
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package_name)
+ index.click_package(package_name)
+ end
+
+ Page::Project::Packages::Show.perform do |package|
+ package.click_delete
+ end
+
+ Page::Project::Packages::Index.perform do |index|
+ aggregate_failures do
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).to have_no_package(package_name)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
index abac4f2b91d..8e61ec4d2d7 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
@@ -77,8 +77,7 @@ module QA
sha1sum = Digest::SHA1.hexdigest(gitlab_ci)
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
- Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline)
+ Flow::Pipeline.visit_latest_pipeline
Page::Project::Pipeline::Show.perform(&:click_on_first_job)
Page::Project::Job::Show.perform do |job|
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 de035e3278a..10795654617 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
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Release', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/213222', type: :flaky } do
+ RSpec.describe 'Release' do
describe 'Deploy token creation' do
it 'user adds a deploy token', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/419' do
Flow::Login.sign_in
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 ece45d093a7..ec26e338b28 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
@@ -27,7 +27,7 @@ module QA
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
+ Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completion')
Page::Project::Pipeline::Show.perform do |parent_pipeline|
expect(parent_pipeline).to have_child_pipeline
@@ -37,7 +37,7 @@ module QA
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
+ Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completion')
Page::Project::Pipeline::Show.perform do |parent_pipeline|
expect(parent_pipeline).to have_child_pipeline
@@ -47,12 +47,6 @@ module QA
private
- def view_pipelines
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
- Page::Project::Pipeline::Index.perform(&:wait_for_latest_pipeline_completion)
- Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline)
- end
-
def success_child_ci_file
{
file_path: '.child-ci.yml',
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 38cee0e62ca..d7f5a326b0e 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
@@ -27,7 +27,7 @@ module QA
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
+ Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completion')
Page::Project::Pipeline::Show.perform do |parent_pipeline|
expect(parent_pipeline).to have_child_pipeline
@@ -37,7 +37,7 @@ module QA
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
+ Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completion')
Page::Project::Pipeline::Show.perform do |parent_pipeline|
expect(parent_pipeline).to have_child_pipeline
@@ -47,12 +47,6 @@ module QA
private
- def view_pipelines
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
- Page::Project::Pipeline::Index.perform(&:wait_for_latest_pipeline_completion)
- Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline)
- end
-
def success_child_ci_file
{
file_path: '.child-ci.yml',
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 6d31780f196..a619ccfad19 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
@@ -54,8 +54,7 @@ module QA
push.commit_message = 'Create Auto DevOps compatible rack application'
end
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
- Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline)
+ Flow::Pipeline.visit_latest_pipeline
Page::Project::Pipeline::Show.perform do |pipeline|
pipeline.click_job('build')
@@ -119,8 +118,7 @@ module QA
end
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)
+ Flow::Pipeline.visit_latest_pipeline
Page::Project::Pipeline::Show.perform do |pipeline|
expect(pipeline).to have_tag('Auto DevOps')
diff --git a/qa/qa/support/page/logging.rb b/qa/qa/support/page/logging.rb
index ea0307e58b2..fca46cc2826 100644
--- a/qa/qa/support/page/logging.rb
+++ b/qa/qa/support/page/logging.rb
@@ -10,7 +10,7 @@ module QA
super
end
- def refresh
+ def refresh(skip_finished_loading_check: false)
log("refreshing #{current_url}")
super
diff --git a/qa/qa/tools/delete_subgroups.rb b/qa/qa/tools/delete_subgroups.rb
index a05ec735632..903f730a030 100644
--- a/qa/qa/tools/delete_subgroups.rb
+++ b/qa/qa/tools/delete_subgroups.rb
@@ -2,9 +2,9 @@
require_relative '../../qa'
-# This script deletes all subgroups of a group specified by ENV['GROUP_NAME_OR_PATH']
+# This script deletes all subgroups of a group specified by ENV['TOP_LEVEL_GROUP_NAME']
# Required environment variables: GITLAB_QA_ACCESS_TOKEN and GITLAB_ADDRESS
-# Optional environment variable: GROUP_NAME_OR_PATH (defaults to 'gitlab-qa-sandbox-group')
+# Optional environment variable: TOP_LEVEL_GROUP_NAME (defaults to 'gitlab-qa-sandbox-group')
# Run `rake delete_subgroups`
module QA
@@ -47,8 +47,9 @@ module QA
end
def fetch_group_id
- group_search_response = get Runtime::API::Request.new(@api_client, "/groups", search: ENV['GROUP_NAME_OR_PATH'] || 'gitlab-qa-sandbox-group').url
- JSON.parse(group_search_response.body).first["id"]
+ group_name = ENV['TOP_LEVEL_GROUP_NAME'] || 'gitlab-qa-sandbox-group'
+ group_search_response = get Runtime::API::Request.new(@api_client, "/groups/#{group_name}" ).url
+ JSON.parse(group_search_response.body)["id"]
end
def fetch_subgroup_ids(group_id, group_pages)
diff --git a/qa/spec/service/docker_run/gitlab_runner_spec.rb b/qa/spec/service/docker_run/gitlab_runner_spec.rb
index db1bb74ca8f..34d95943321 100644
--- a/qa/spec/service/docker_run/gitlab_runner_spec.rb
+++ b/qa/spec/service/docker_run/gitlab_runner_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- describe Service::DockerRun::GitlabRunner do
+ RSpec.describe Service::DockerRun::GitlabRunner do
let(:runner_name) { 'test-runner' }
let(:address) { 'gitlab.test' }
let(:token) { 'abc123' }
diff --git a/qa/spec/service/docker_run/k3s_spec.rb b/qa/spec/service/docker_run/k3s_spec.rb
index 0224b7d6704..e994fbdd30e 100644
--- a/qa/spec/service/docker_run/k3s_spec.rb
+++ b/qa/spec/service/docker_run/k3s_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- describe Service::DockerRun::K3s do
+ RSpec.describe Service::DockerRun::K3s do
describe '#host_name' do
context 'in CI' do
let(:name) { 'k3s-12345' }
diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb
index 81730c3ab13..9785d0a9014 100644
--- a/qa/spec/spec_helper.rb
+++ b/qa/spec/spec_helper.rb
@@ -14,10 +14,13 @@ 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")].sort.each { |f| require f }
+Dir[::File.join(__dir__, "support/matchers/*.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|
+ config.include ::Matchers
+
QA::Specs::Helpers::Quarantine.configure_rspec
config.before do |example|
diff --git a/qa/spec/support/matchers/have_file.rb b/qa/spec/support/matchers/have_file.rb
new file mode 100644
index 00000000000..2ae295d5ca2
--- /dev/null
+++ b/qa/spec/support/matchers/have_file.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Matchers
+ module HaveFile
+ RSpec::Matchers.define :have_file do |file|
+ match do |page_object|
+ page_object.has_file?(file)
+ end
+
+ match_when_negated do |page_object|
+ page_object.has_no_file?(file)
+ end
+ end
+ end
+end
diff --git a/qa/spec/support/matchers/have_text.rb b/qa/spec/support/matchers/have_text.rb
new file mode 100644
index 00000000000..4e6fbf1f6d6
--- /dev/null
+++ b/qa/spec/support/matchers/have_text.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Matchers
+ class HaveText
+ def initialize(expected_text, **kwargs)
+ @expected_text = expected_text
+ @kwargs = kwargs
+ end
+
+ def matches?(actual)
+ @actual = wrap(actual)
+ @actual.has_text?(@expected_text, **@kwargs)
+ end
+
+ def does_not_match?(actual)
+ @actual = wrap(actual)
+ @actual.has_no_text?(@expected_text, **@kwargs)
+ end
+
+ def failure_message
+ "expected to find text \"#{@expected_text}\" in \"#{normalized_actual_text}\""
+ end
+
+ def failure_message_when_negated
+ "expected not to find text \"#{@expected_text}\" in \"#{normalized_actual_text}\""
+ end
+
+ def normalized_actual_text
+ @actual.text.gsub(/\s+/, " ")
+ end
+
+ # From https://github.com/teamcapybara/capybara/blob/fe5940c6afbfe32152df936ce03ad1371ae05354/lib/capybara/rspec/matchers/base.rb#L66
+ def wrap(actual)
+ actual = actual.to_capybara_node if actual.respond_to?(:to_capybara_node)
+ @context_el = if actual.respond_to?(:has_selector?)
+ actual
+ else
+ Capybara.string(actual.to_s)
+ end
+ end
+ end
+
+ def have_text(text, **kwargs) # rubocop:disable Naming/PredicateName
+ HaveText.new(text, **kwargs)
+ end
+
+ alias_method :have_content, :have_text
+end
diff --git a/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb b/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb
index feaeb78815d..610bf8b9e28 100644
--- a/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb
+++ b/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- shared_examples 'code owner merge request' do
+ RSpec.shared_examples 'code owner merge request' do
let(:branch_name) { 'new-branch' }
it 'is approved and merged' do
diff --git a/qa/spec/support/shared_examples/scenario_shared_examples.rb b/qa/spec/support/shared_examples/scenario_shared_examples.rb
index 6e20adbd4ad..637cfb9a05d 100644
--- a/qa/spec/support/shared_examples/scenario_shared_examples.rb
+++ b/qa/spec/support/shared_examples/scenario_shared_examples.rb
@@ -1,73 +1,75 @@
# frozen_string_literal: true
-shared_examples 'a QA scenario class' do
- let(:attributes) { spy('Runtime::Scenario') }
- let(:runner) { spy('Specs::Runner') }
- let(:release) { spy('Runtime::Release') }
- let(:feature) { spy('Runtime::Feature') }
-
- let(:args) { { gitlab_address: 'http://gitlab_address' } }
- let(:named_options) { %w[--address http://gitlab_address] }
- let(:tags) { [] }
- let(:options) { %w[path1 path2] }
-
- before do
- stub_const('QA::Specs::Runner', runner)
- stub_const('QA::Runtime::Release', release)
- stub_const('QA::Runtime::Scenario', attributes)
- stub_const('QA::Runtime::Feature', feature)
-
- allow(runner).to receive(:perform).and_yield(runner)
- allow(QA::Runtime::Address).to receive(:valid?).and_return(true)
- end
+module QA
+ RSpec.shared_examples 'a QA scenario class' do
+ let(:attributes) { spy('Runtime::Scenario') }
+ let(:runner) { spy('Specs::Runner') }
+ let(:release) { spy('Runtime::Release') }
+ let(:feature) { spy('Runtime::Feature') }
+
+ let(:args) { { gitlab_address: 'http://gitlab_address' } }
+ let(:named_options) { %w[--address http://gitlab_address] }
+ let(:tags) { [] }
+ let(:options) { %w[path1 path2] }
+
+ before do
+ stub_const('QA::Specs::Runner', runner)
+ stub_const('QA::Runtime::Release', release)
+ stub_const('QA::Runtime::Scenario', attributes)
+ stub_const('QA::Runtime::Feature', feature)
+
+ allow(runner).to receive(:perform).and_yield(runner)
+ allow(QA::Runtime::Address).to receive(:valid?).and_return(true)
+ end
- it 'responds to perform' do
- expect(subject).to respond_to(:perform)
- end
+ it 'responds to perform' do
+ expect(subject).to respond_to(:perform)
+ end
- it 'sets an address of the subject' do
- subject.perform(args)
+ it 'sets an address of the subject' do
+ subject.perform(args)
- expect(attributes).to have_received(:define).with(:gitlab_address, 'http://gitlab_address').at_least(:once)
- end
+ expect(attributes).to have_received(:define).with(:gitlab_address, 'http://gitlab_address').at_least(:once)
+ end
- it 'performs before hooks only once' do
- subject.perform(args)
+ it 'performs before hooks only once' do
+ subject.perform(args)
- expect(release).to have_received(:perform_before_hooks).once
- end
+ expect(release).to have_received(:perform_before_hooks).once
+ end
- it 'sets tags on runner' do
- subject.perform(args)
+ it 'sets tags on runner' do
+ subject.perform(args)
- expect(runner).to have_received(:tags=).with(tags)
- end
+ expect(runner).to have_received(:tags=).with(tags)
+ end
- context 'specifying RSpec options' do
- it 'sets options on runner' do
- subject.perform(args, *options)
+ context 'specifying RSpec options' do
+ it 'sets options on runner' do
+ subject.perform(args, *options)
- expect(runner).to have_received(:options=).with(options)
+ expect(runner).to have_received(:options=).with(options)
+ end
end
- end
- context 'with named command-line options' do
- it 'converts options to attributes' do
- described_class.launch!(named_options)
+ context 'with named command-line options' do
+ it 'converts options to attributes' do
+ described_class.launch!(named_options)
- args do |k, v|
- expect(attributes).to have_received(:define).with(k, v)
+ args do |k, v|
+ expect(attributes).to have_received(:define).with(k, v)
+ end
end
- end
- it 'raises an error if the option is invalid' do
- expect { described_class.launch!(['--foo']) }.to raise_error(OptionParser::InvalidOption)
- end
+ it 'raises an error if the option is invalid' do
+ expect { described_class.launch!(['--foo']) }.to raise_error(OptionParser::InvalidOption)
+ end
- it 'passes on options after --' do
- expect(described_class).to receive(:perform).with(attributes, *%w[--tag quarantine])
+ it 'passes on options after --' do
+ expect(described_class).to receive(:perform).with(attributes, *%w[--tag quarantine])
- described_class.launch!(named_options.push(*%w[-- --tag quarantine]))
+ described_class.launch!(named_options.push(*%w[-- --tag quarantine]))
+ end
end
end
end
diff --git a/rubocop/cop/code_reuse/active_record.rb b/rubocop/cop/code_reuse/active_record.rb
deleted file mode 100644
index f6b5d66647d..00000000000
--- a/rubocop/cop/code_reuse/active_record.rb
+++ /dev/null
@@ -1,168 +0,0 @@
-# frozen_string_literal: true
-
-require_relative '../../code_reuse_helpers'
-
-module RuboCop
- module Cop
- module CodeReuse
- # Cop that denies the use of ActiveRecord methods outside of models.
- class ActiveRecord < RuboCop::Cop::Cop
- include CodeReuseHelpers
-
- MSG = 'This method can only be used inside an ActiveRecord model: ' \
- 'https://gitlab.com/gitlab-org/gitlab-foss/issues/49653'
-
- # Various methods from ActiveRecord::Querying that are denied. We
- # exclude some generic ones such as `any?` and `first`, as these may
- # lead to too many false positives, since `Array` also supports these
- # methods.
- #
- # The keys of this Hash are the denied method names. The values are
- # booleans that indicate if the method should only be denied if any
- # arguments are provided.
- NOT_ALLOWED = {
- average: true,
- calculate: true,
- count_by_sql: true,
- create_with: true,
- distinct: false,
- eager_load: true,
- exists?: true,
- find_by: true,
- find_by!: true,
- find_by_sql: true,
- find_each: true,
- find_in_batches: true,
- find_or_create_by: true,
- find_or_create_by!: true,
- find_or_initialize_by: true,
- first!: false,
- first_or_create: true,
- first_or_create!: true,
- first_or_initialize: true,
- from: true,
- group: true,
- having: true,
- ids: false,
- includes: true,
- joins: true,
- limit: true,
- lock: false,
- many?: false,
- offset: true,
- order: true,
- pluck: true,
- preload: true,
- readonly: false,
- references: true,
- reorder: true,
- rewhere: true,
- take: false,
- take!: false,
- unscope: false,
- where: false,
- with: true
- }.freeze
-
- # Directories that allow the use of the denied methods. These
- # directories are checked relative to both . and ee/
- ALLOWED_DIRECTORIES = %w[
- app/models
- config
- danger
- db
- lib/backup
- lib/banzai
- lib/gitlab/background_migration
- lib/gitlab/cycle_analytics
- lib/gitlab/database
- lib/gitlab/import_export
- lib/gitlab/project_authorizations
- lib/gitlab/sql
- lib/system_check
- lib/tasks
- qa
- rubocop
- spec
- ].freeze
-
- def on_send(node)
- return if in_allowed_directory?(node)
-
- receiver = node.children[0]
- send_name = node.children[1]
- first_arg = node.children[2]
-
- if receiver && NOT_ALLOWED.key?(send_name)
- # If the rule requires an argument to be given, but none are
- # provided, we won't register an offense. This prevents us from
- # adding offenses for `project.group`, while still covering
- # `Project.group(:name)`.
- return if NOT_ALLOWED[send_name] && !first_arg
-
- add_offense(node, location: :selector)
- end
- end
-
- # Returns true if the node resides in one of the allowed
- # directories.
- def in_allowed_directory?(node)
- path = file_path_for_node(node)
-
- ALLOWED_DIRECTORIES.any? do |directory|
- path.start_with?(
- File.join(rails_root, directory),
- File.join(rails_root, 'ee', directory)
- )
- end
- end
-
- # We can not auto correct code like this, as it requires manual
- # refactoring. Instead, we'll just allow the surrounding scope.
- #
- # Despite this method's presence, you should not use it. This method
- # exists to make it possible to allow large chunks of offenses we
- # can't fix in the short term. If you are writing new code, follow the
- # code reuse guidelines, instead of allowing any new offenses.
- def autocorrect(node)
- scope = surrounding_scope_of(node)
- indent = indentation_of(scope)
-
- lambda do |corrector|
- # This prevents us from inserting the same enable/disable comment
- # for a method or block that has multiple offenses.
- next if allowed_scopes.include?(scope)
-
- corrector.insert_before(
- scope.source_range,
- "# rubocop: disable #{cop_name}\n#{indent}"
- )
-
- corrector.insert_after(
- scope.source_range,
- "\n#{indent}# rubocop: enable #{cop_name}"
- )
-
- allowed_scopes << scope
- end
- end
-
- def indentation_of(node)
- ' ' * node.loc.expression.source_line[/\A */].length
- end
-
- def surrounding_scope_of(node)
- %i[def defs block begin].each do |type|
- if (found = node.each_ancestor(type).first)
- return found
- end
- end
- end
-
- def allowed_scopes
- @allowed_scopes ||= Set.new
- end
- end
- end
- end
-end
diff --git a/rubocop/cop/graphql/resolver_type.rb b/rubocop/cop/graphql/resolver_type.rb
new file mode 100644
index 00000000000..1209c5dbc6b
--- /dev/null
+++ b/rubocop/cop/graphql/resolver_type.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+# This cop checks for missing GraphQL type annotations on resolvers
+#
+# @example
+#
+# # bad
+# module Resolvers
+# class NoTypeResolver < BaseResolver
+# field :some_field, GraphQL::STRING_TYPE
+# end
+# end
+#
+# # good
+# module Resolvers
+# class WithTypeResolver < BaseResolver
+# type MyType, null: true
+#
+# field :some_field, GraphQL::STRING_TYPE
+# end
+# end
+
+module RuboCop
+ module Cop
+ module Graphql
+ class ResolverType < RuboCop::Cop::Cop
+ MSG = 'Missing type annotation: Please add `type` DSL method call. ' \
+ 'e.g: type UserType.connection_type, null: true'
+
+ def_node_matcher :typed?, <<~PATTERN
+ (... (begin <(send nil? :type ...) ...>))
+ PATTERN
+
+ def on_class(node)
+ add_offense(node, location: :expression) if resolver?(node) && !typed?(node)
+ end
+
+ private
+
+ def resolver?(node)
+ node.loc.name.source.end_with?('Resolver')
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/line_break_around_conditional_block.rb b/rubocop/cop/line_break_around_conditional_block.rb
deleted file mode 100644
index 2523cc162f3..00000000000
--- a/rubocop/cop/line_break_around_conditional_block.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-# frozen_string_literal: true
-
-module RuboCop
- module Cop
- # Ensures a line break around conditional blocks.
- #
- # @example
- # # bad
- # do_something
- # if condition
- # do_extra_stuff
- # end
- # do_something_more
- #
- # # good
- # do_something
- #
- # if condition
- # do_extra_stuff
- # end
- #
- # do_something_more
- #
- # # bad
- # do_something
- # unless condition
- # do_extra_stuff
- # end
- #
- # do_something_more
- #
- # # good
- # def a_method
- # if condition
- # do_something
- # end
- # end
- #
- # # good
- # on_block do
- # if condition
- # do_something
- # end
- # end
- class LineBreakAroundConditionalBlock < RuboCop::Cop::Cop
- include RangeHelp
-
- MSG = 'Add a line break around conditional blocks'
-
- def on_if(node)
- # This cop causes errors in haml files, so let's skip those
- return if in_haml?(node)
- return if node.single_line?
- return unless node.if? || node.unless?
-
- add_offense(node, location: :expression, message: MSG) unless previous_line_valid?(node)
- add_offense(node, location: :expression, message: MSG) unless last_line_valid?(node)
- end
-
- def autocorrect(node)
- lambda do |corrector|
- line = range_by_whole_lines(node.source_range)
- unless previous_line_valid?(node)
- corrector.insert_before(line, "\n")
- end
-
- unless last_line_valid?(node)
- corrector.insert_after(line, "\n")
- end
- end
- end
-
- private
-
- def previous_line_valid?(node)
- previous_line(node).empty? ||
- start_clause_line?(previous_line(node)) ||
- block_start?(previous_line(node)) ||
- begin_line?(previous_line(node)) ||
- assignment_line?(previous_line(node)) ||
- rescue_line?(previous_line(node))
- end
-
- def last_line_valid?(node)
- last_line(node).empty? ||
- end_line?(last_line(node)) ||
- end_clause_line?(last_line(node))
- end
-
- def previous_line(node)
- processed_source[node.loc.line - 2]
- end
-
- def last_line(node)
- processed_source[node.loc.last_line]
- end
-
- def start_clause_line?(line)
- line =~ /^\s*(def|=end|#|module|class|if|unless|else|elsif|ensure|when)/
- end
-
- def end_clause_line?(line)
- line =~ /^\s*(#|rescue|else|elsif|when)/
- end
-
- def begin_line?(line)
- # an assignment followed by a begin or ust a begin
- line =~ /^\s*(@?(\w|\|+|=|\[|\]|\s)+begin|begin)/
- end
-
- def assignment_line?(line)
- line =~ /^\s*.*=/
- end
-
- def rescue_line?(line)
- line =~ /^\s*rescue/
- end
-
- def block_start?(line)
- line.match(/ (do|{)( \|.*?\|)?\s?(#.+)?\z/)
- end
-
- def end_line?(line)
- line =~ /^\s*(end|})/
- end
-
- def in_haml?(node)
- node.location.expression.source_buffer.name.end_with?('.haml.rb')
- end
- end
- end
-end
diff --git a/rubocop/qa_helpers.rb b/rubocop/qa_helpers.rb
index 95875d64727..f4adf7f4e9f 100644
--- a/rubocop/qa_helpers.rb
+++ b/rubocop/qa_helpers.rb
@@ -5,7 +5,7 @@ module RuboCop
def in_qa_file?(node)
path = node.location.expression.source_buffer.name
- path.start_with?(File.join(RuboCop::PathUtil.pwd, 'qa'))
+ path.start_with?(File.join(Dir.pwd, 'qa'))
end
end
end
diff --git a/rubocop/rubocop-code_reuse.yml b/rubocop/rubocop-code_reuse.yml
new file mode 100644
index 00000000000..64e51c859f4
--- /dev/null
+++ b/rubocop/rubocop-code_reuse.yml
@@ -0,0 +1,41 @@
+# Denies the use of ActiveRecord methods outside of configured
+# excluded directories
+# Directories that allow the use of the denied methods.
+# To start we provide a default configuration that matches
+# a standard Rails app and enable.
+# The default configuration can be overridden by
+# providing your own Exclusion list as follows:
+# CodeReuse/ActiveRecord:
+# Enabled: true
+# Exclude:
+# - app/models/**/*.rb
+# - config/**/*.rb
+# - db/**/*.rb
+# - lib/tasks/**/*.rb
+# - spec/**/*.rb
+# - lib/gitlab/**/*.rb
+CodeReuse/ActiveRecord:
+ Exclude:
+ - app/models/**/*.rb
+ - config/**/*.rb
+ - db/**/*.rb
+ - lib/tasks/**/*.rake
+ - spec/**/*.rb
+ - danger/**/*.rb
+ - lib/backup/**/*.rb
+ - lib/banzai/**/*.rb
+ - lib/gitlab/background_migration/**/*.rb
+ - lib/gitlab/cycle_analytics/**/*.rb
+ - lib/gitlab/database/**/*.rb
+ - lib/gitlab/database_importers/common_metrics/importer.rb
+ - lib/gitlab/import_export/**/*.rb
+ - lib/gitlab/project_authorizations.rb
+ - lib/gitlab/sql/**/*.rb
+ - lib/system_check/**/*.rb
+ - qa/**/*.rb
+ - rubocop/**/*.rb
+ - ee/app/models/**/*.rb
+ - ee/spec/**/*.rb
+ - ee/db/fixtures/**/*.rb
+ - ee/lib/tasks/**/*.rake
+ - ee/lib/ee/gitlab/background_migration/**/*.rb
diff --git a/rubocop/rubocop-migrations.yml b/rubocop/rubocop-migrations.yml
index f8ff6e005f9..e1772deee9b 100644
--- a/rubocop/rubocop-migrations.yml
+++ b/rubocop/rubocop-migrations.yml
@@ -29,6 +29,7 @@ Migration/UpdateLargeTable:
- :push_event_payloads
- :resource_label_events
- :routes
+ - :security_findings
- :sent_notifications
- :system_note_metadata
- :taggings
diff --git a/rubocop/rubocop-usage-data.yml b/rubocop/rubocop-usage-data.yml
index fdfe2a5e1aa..51ad3ed0bef 100644
--- a/rubocop/rubocop-usage-data.yml
+++ b/rubocop/rubocop-usage-data.yml
@@ -50,3 +50,4 @@ UsageData/DistinctCountByLargeForeignKey:
- 'owner_id'
- 'project_id'
- 'user_id'
+ - 'resource_owner_id'
diff --git a/scripts/build_assets_image b/scripts/build_assets_image
index 12beddfa184..e6a5f036fe5 100755
--- a/scripts/build_assets_image
+++ b/scripts/build_assets_image
@@ -20,13 +20,21 @@ cp Dockerfile.assets assets_container.build/
COMMIT_REF_SLUG_DESTINATION=${ASSETS_IMAGE_PATH}:${CI_COMMIT_REF_SLUG}
COMMIT_SHA_DESTINATION=${ASSETS_IMAGE_PATH}:${CI_COMMIT_SHA}
-COMMIT_REF_NAME_DESTINATION=${ASSETS_IMAGE_PATH}:${CI_COMMIT_REF_NAME}
DESTINATIONS="--destination=$COMMIT_REF_SLUG_DESTINATION --destination=$COMMIT_SHA_DESTINATION"
+# For EE branch builds, add a truncated SHA destination for later use by Omnibus
+# auto-deploy builds
+if [[ "${ASSETS_IMAGE_NAME}" == "gitlab-assets-ee" ]] && [ -n "$CI_COMMIT_BRANCH" ]
+then
+ COMMIT_SHORT_SHA_DESTINATION=${ASSETS_IMAGE_PATH}:${CI_COMMIT_SHA:0:11}
+ DESTINATIONS="$DESTINATIONS --destination=$COMMIT_SHORT_SHA_DESTINATION"
+fi
+
# Also tag the image with GitLab version, if running on a tag pipeline, so
# other projects can simply use that instead of computing the slug.
if [ -n "$CI_COMMIT_TAG" ]; then
+ COMMIT_REF_NAME_DESTINATION=${ASSETS_IMAGE_PATH}:${CI_COMMIT_REF_NAME}
DESTINATIONS="$DESTINATIONS --destination=$COMMIT_REF_NAME_DESTINATION"
fi
diff --git a/scripts/generate-test-mapping b/scripts/generate-test-mapping
new file mode 100755
index 00000000000..eabe6a5b513
--- /dev/null
+++ b/scripts/generate-test-mapping
@@ -0,0 +1,19 @@
+#!/usr/bin/env ruby
+
+require 'json'
+require_relative '../tooling/lib/tooling/test_map_generator'
+
+test_mapping_json = ARGV.shift
+crystalball_yamls = ARGV
+
+unless test_mapping_json && !crystalball_yamls.empty?
+ puts "usage: #{__FILE__} <test_mapping_json> [crystalball_yamls...]"
+ exit 1
+end
+
+map_generator = Tooling::TestMapGenerator.new
+map_generator.parse(crystalball_yamls)
+mapping = map_generator.mapping
+
+File.write(test_mapping_json, JSON.pretty_generate(mapping))
+puts "Saved #{test_mapping_json}."
diff --git a/scripts/lint-doc.sh b/scripts/lint-doc.sh
index 87256269de2..9ae6ce400da 100755
--- a/scripts/lint-doc.sh
+++ b/scripts/lint-doc.sh
@@ -1,6 +1,7 @@
#!/usr/bin/env bash
+set -o pipefail
-cd "$(dirname "$0")/.."
+cd "$(dirname "$0")/.." || exit 1
echo "=> Linting documents at path $(pwd) as $(whoami)..."
echo
ERRORCODE=0
@@ -65,8 +66,11 @@ then
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
+ if [ -n "${MD_DOC_PATH}" ]
+ then
+ echo -e "Merged results pipeline detected. Testing only the following files:\n${MD_DOC_PATH}"
+ fi
+fi
function run_locally_or_in_docker() {
local cmd=$1
@@ -77,7 +81,7 @@ function run_locally_or_in_docker() {
$cmd $args
elif hash docker 2>/dev/null
then
- docker run -t -v ${PWD}:/gitlab -w /gitlab --rm registry.gitlab.com/gitlab-org/gitlab-docs/lint:latest ${cmd} ${args}
+ docker run -t -v ${PWD}:/gitlab -w /gitlab --rm registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.12-vale-2.6.1-markdownlint-0.24.0 ${cmd} ${args}
else
echo
echo " ✖ ERROR: '${cmd}' not found. Install '${cmd}' or Docker to proceed." >&2
@@ -96,10 +100,15 @@ function run_locally_or_in_docker() {
echo '=> Linting markdown style...'
echo
-run_locally_or_in_docker 'markdownlint' "--config .markdownlint.json ${MD_DOC_PATH}"
+if [ -z "${MD_DOC_PATH}" ]
+then
+ echo "Merged results pipeline detected, but no markdown files found. Skipping."
+else
+ run_locally_or_in_docker 'markdownlint' "--config .markdownlint.json ${MD_DOC_PATH}"
+fi
echo '=> Linting prose...'
-run_locally_or_in_docker 'vale' "--minAlertLevel error ${MD_DOC_PATH}"
+run_locally_or_in_docker 'vale' "--minAlertLevel error --output=doc/.vale/vale.tmpl ${MD_DOC_PATH}"
if [ $ERRORCODE -ne 0 ]
then
diff --git a/scripts/lint-rugged b/scripts/lint-rugged
index dfa4df8333f..d7af5499e1c 100755
--- a/scripts/lint-rugged
+++ b/scripts/lint-rugged
@@ -18,6 +18,11 @@ ALLOWED = [
# Needed to detect Rugged enabled: https://gitlab.com/gitlab-org/gitlab/issues/35371
'lib/gitlab/config_checker/puma_rugged_checker.rb',
+ # Needed for GPG/X509 commit signature API
+ #
+ 'app/models/commit.rb',
+ 'lib/api/entities/commit_signature.rb',
+
# Needed for logging
'config/initializers/peek.rb',
'config/initializers/lograge.rb',
diff --git a/scripts/pack-test-mapping b/scripts/pack-test-mapping
new file mode 100755
index 00000000000..58ace3eca67
--- /dev/null
+++ b/scripts/pack-test-mapping
@@ -0,0 +1,19 @@
+#!/usr/bin/env ruby
+
+require 'json'
+require_relative '../tooling/lib/tooling/test_map_packer'
+
+unpacked_json_mapping, packed_json_mapping = ARGV.shift(2)
+unless packed_json_mapping && unpacked_json_mapping
+ puts "usage: #{__FILE__} <unpacked_json_mapping> <packed_json_mapping>"
+ exit 1
+end
+
+puts "Compressing #{unpacked_json_mapping}"
+
+mapping = JSON.parse(File.read(unpacked_json_mapping))
+packed_mapping = Tooling::TestMapPacker.new.pack(mapping)
+
+puts "Writing packed #{packed_json_mapping}"
+File.write(packed_json_mapping, JSON.generate(packed_mapping))
+puts "Saved #{packed_json_mapping}."
diff --git a/scripts/review_apps/base-config.yaml b/scripts/review_apps/base-config.yaml
index 82be2d3a691..bfc35a6abde 100644
--- a/scripts/review_apps/base-config.yaml
+++ b/scripts/review_apps/base-config.yaml
@@ -52,10 +52,10 @@ gitlab:
resources:
requests:
cpu: 855m
- memory: 1071M
+ memory: 1285M
limits:
cpu: 1282m
- memory: 1606M
+ memory: 1927M
hpa:
targetAverageValue: 650m
task-runner:
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index b8cbe625e5b..59e7d183ae7 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -75,7 +75,7 @@ function kubectl_cleanup_release() {
kubectl --namespace "${namespace}" get ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,clusterrole,clusterrolebinding,role,rolebinding,sa,crd 2>&1 \
| grep "${release}" \
| awk '{print $1}' \
- | xargs kubectl --namespace "${namespace}" delete \
+ | xargs kubectl --namespace "${namespace}" delete --ignore-not-found \
|| true
}
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index 3812a8b8ef7..5f003d032b7 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -48,12 +48,49 @@ function update_tests_metadata() {
fi
}
+function retrieve_tests_mapping() {
+ mkdir -p crystalball/
+
+ if [[ ! -f "${RSPEC_PACKED_TESTS_MAPPING_PATH}" ]]; then
+ (wget -O "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz" "http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz" && gzip -d "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz") || echo "{}" > "${RSPEC_PACKED_TESTS_MAPPING_PATH}"
+ fi
+
+ scripts/unpack-test-mapping "${RSPEC_PACKED_TESTS_MAPPING_PATH}" "${RSPEC_TESTS_MAPPING_PATH}"
+}
+
+function update_tests_mapping() {
+ if ! crystalball_rspec_data_exists; then
+ echo "No crystalball rspec data found."
+ return 0
+ fi
+
+ scripts/generate-test-mapping "${RSPEC_TESTS_MAPPING_PATH}" crystalball/rspec*.yml
+
+ scripts/pack-test-mapping "${RSPEC_TESTS_MAPPING_PATH}" "${RSPEC_PACKED_TESTS_MAPPING_PATH}"
+
+ gzip "${RSPEC_PACKED_TESTS_MAPPING_PATH}"
+
+ if [[ -n "${TESTS_METADATA_S3_BUCKET}" ]]; then
+ if [[ "$CI_PIPELINE_SOURCE" == "schedule" ]]; then
+ scripts/sync-reports put "${TESTS_METADATA_S3_BUCKET}" "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz"
+ else
+ echo "Not uploading report to S3 as the pipeline is not a scheduled one."
+ fi
+ fi
+
+ rm -f crystalball/rspec*.yml
+}
+
+function crystalball_rspec_data_exists() {
+ compgen -G "crystalball/rspec*.yml" > /dev/null;
+}
+
function rspec_simple_job() {
local rspec_opts="${1}"
export NO_KNAPSACK="1"
- bin/rspec --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml ${rspec_opts}
+ bin/rspec -Ispec -rspec_helper --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml ${rspec_opts}
}
function rspec_paralellized_job() {
@@ -106,7 +143,7 @@ function rspec_paralellized_job() {
export MEMORY_TEST_PATH="tmp/memory_test/${report_name}_memory.csv"
- knapsack rspec "-Ispec --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml ${rspec_opts}"
+ knapsack rspec "-Ispec -rspec_helper --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml ${rspec_opts}"
date
}
diff --git a/scripts/unpack-test-mapping b/scripts/unpack-test-mapping
new file mode 100755
index 00000000000..c0f706c3f9f
--- /dev/null
+++ b/scripts/unpack-test-mapping
@@ -0,0 +1,17 @@
+#!/usr/bin/env ruby
+
+require 'json'
+require_relative '../tooling/lib/tooling/test_map_packer'
+
+packed_json_mapping, unpacked_json_mapping = ARGV.shift(2)
+unless packed_json_mapping && unpacked_json_mapping
+ puts "usage: #{__FILE__} <packed_json_mapping> <unpacked_json_mapping>"
+ exit 1
+end
+
+packed_mapping = JSON.parse(File.read(packed_json_mapping))
+mapping = Tooling::TestMapPacker.new.unpack(packed_mapping)
+
+puts "Writing unpacked #{unpacked_json_mapping}"
+File.write(unpacked_json_mapping, JSON.generate(mapping))
+puts "Saved #{unpacked_json_mapping}."
diff --git a/scripts/utils.sh b/scripts/utils.sh
index 9d188fc7b77..3829bcdf24e 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -31,8 +31,8 @@ function install_api_client_dependencies_with_apt() {
}
function install_gitlab_gem() {
- gem install httparty --no-document --version 0.17.3
- gem install gitlab --no-document --version 4.13.0
+ gem install httparty --no-document --version 0.18.1
+ gem install gitlab --no-document --version 4.14.1
}
function install_tff_gem() {
diff --git a/scripts/verify-tff-mapping b/scripts/verify-tff-mapping
index 9541d2468b1..1f73753be82 100755
--- a/scripts/verify-tff-mapping
+++ b/scripts/verify-tff-mapping
@@ -40,12 +40,6 @@ tests = [
},
{
- 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']
diff --git a/spec/bin/feature_flag_spec.rb b/spec/bin/feature_flag_spec.rb
index 185a03fc587..710b1606923 100644
--- a/spec/bin/feature_flag_spec.rb
+++ b/spec/bin/feature_flag_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'bin/feature-flag' do
let(:options) { FeatureFlagOptionParser.parse(argv) }
let(:creator) { described_class.new(options) }
let(:existing_flags) do
- { 'existing-feature-flag' => File.join('config', 'feature_flags', 'development', 'existing-feature-flag.yml') }
+ { 'existing_feature_flag' => File.join('config', 'feature_flags', 'development', 'existing_feature_flag.yml') }
end
before do
@@ -32,12 +32,12 @@ RSpec.describe 'bin/feature-flag' do
it 'properly creates a feature flag' do
expect(File).to receive(:write).with(
- File.join('config', 'feature_flags', 'development', 'feature-flag-name.yml'),
+ File.join('config', 'feature_flags', 'development', 'feature_flag_name.yml'),
anything)
expect do
subject
- end.to output(/name: feature-flag-name/).to_stdout
+ end.to output(/name: feature_flag_name/).to_stdout
end
context 'when running on master' do
@@ -123,6 +123,29 @@ RSpec.describe 'bin/feature-flag' do
end
end
+ context 'when there is deprecated feature flag type' do
+ before do
+ stub_const('FeatureFlagOptionParser::TYPES',
+ development: { description: 'short' },
+ deprecated: { description: 'deprecated', deprecated: true }
+ )
+ end
+
+ context 'and deprecated type is given' do
+ let(:type) { 'deprecated' }
+
+ it 'shows error message and retries' do
+ expect($stdin).to receive(:gets).and_return(type)
+ expect($stdin).to receive(:gets).and_raise('EOF')
+
+ expect do
+ expect { described_class.read_type }.to raise_error(/EOF/)
+ end.to output(/Specify the feature flag type/).to_stdout
+ .and output(/Invalid type specified/).to_stderr
+ end
+ end
+ end
+
context 'when there are many types defined' do
before do
stub_const('FeatureFlagOptionParser::TYPES',
diff --git a/spec/bin/sidekiq_cluster_spec.rb b/spec/bin/sidekiq_cluster_spec.rb
index fc5e2ae861a..503cc0999c5 100644
--- a/spec/bin/sidekiq_cluster_spec.rb
+++ b/spec/bin/sidekiq_cluster_spec.rb
@@ -9,6 +9,8 @@ RSpec.describe 'bin/sidekiq-cluster' do
context 'when selecting some queues and excluding others' do
where(:args, :included, :excluded) do
%w[--negate cronjob] | '-qdefault,1' | '-qcronjob,1'
+ %w[--queue-selector resource_boundary=cpu] | '-qupdate_merge_requests,1' | '-qdefault,1'
+ # Remove with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
%w[--experimental-queue-selector resource_boundary=cpu] | '-qupdate_merge_requests,1' | '-qdefault,1'
end
@@ -29,6 +31,8 @@ RSpec.describe 'bin/sidekiq-cluster' do
context 'when selecting all queues' do
[
%w[*],
+ %w[--queue-selector *],
+ # Remove with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
%w[--experimental-queue-selector *]
].each do |args|
it "runs successfully with `#{args}`", :aggregate_failures do
diff --git a/spec/controllers/admin/dashboard_controller_spec.rb b/spec/controllers/admin/dashboard_controller_spec.rb
index 283d82a3ab8..bfbd2ca946f 100644
--- a/spec/controllers/admin/dashboard_controller_spec.rb
+++ b/spec/controllers/admin/dashboard_controller_spec.rb
@@ -4,12 +4,20 @@ require 'spec_helper'
RSpec.describe Admin::DashboardController do
describe '#index' do
+ before do
+ sign_in(create(:admin))
+ end
+
+ it 'retrieves Redis versions' do
+ get :index
+
+ expect(assigns[:redis_versions].length).to eq(1)
+ end
+
context 'with pending_delete projects' do
render_views
it 'does not retrieve projects that are pending deletion' do
- sign_in(create(:admin))
-
project = create(:project)
pending_delete_project = create(:project, pending_delete: true)
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb
index 5312a0db7f5..d0d1fa6a6bc 100644
--- a/spec/controllers/admin/users_controller_spec.rb
+++ b/spec/controllers/admin/users_controller_spec.rb
@@ -107,49 +107,40 @@ RSpec.describe Admin::UsersController do
subject { put :approve, params: { id: user.username } }
- context 'when feature is disabled' do
- before do
- stub_feature_flags(admin_approval_for_new_user_signups: false)
- end
-
- it 'responds with access denied' do
+ context 'when successful' do
+ it 'activates the user' do
subject
- expect(response).to have_gitlab_http_status(:not_found)
+ user.reload
+
+ expect(user).to be_active
+ expect(flash[:notice]).to eq('Successfully approved')
end
- end
- context 'when feature is enabled' do
- before do
- stub_feature_flags(admin_approval_for_new_user_signups: true)
+ it 'emails the user on approval' do
+ expect(DeviseMailer).to receive(:user_admin_approval).with(user).and_call_original
+ expect { subject }.to have_enqueued_mail(DeviseMailer, :user_admin_approval)
end
+ end
- context 'when successful' do
- it 'activates the user' do
- subject
+ context 'when unsuccessful' do
+ let(:user) { create(:user, :blocked) }
- user.reload
+ it 'displays the error' do
+ subject
- expect(user).to be_active
- expect(flash[:notice]).to eq('Successfully approved')
- end
+ expect(flash[:alert]).to eq('The user you are trying to approve is not pending an approval')
end
- context 'when unsuccessful' do
- let(:user) { create(:user, :blocked) }
-
- it 'displays the error' do
- subject
-
- expect(flash[:alert]).to eq('The user you are trying to approve is not pending an approval')
- end
+ it 'does not activate the user' do
+ subject
- it 'does not activate the user' do
- subject
+ user.reload
+ expect(user).not_to be_active
+ end
- user.reload
- expect(user).not_to be_active
- end
+ it 'does not email the pending user' do
+ expect { subject }.not_to have_enqueued_mail(DeviseMailer, :user_admin_approval)
end
end
end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index d95aac2f386..9342513d224 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -171,6 +171,8 @@ RSpec.describe ApplicationController do
describe '#route_not_found' do
controller(described_class) do
+ skip_before_action :authenticate_user!, only: :index
+
def index
route_not_found
end
@@ -184,6 +186,14 @@ RSpec.describe ApplicationController do
expect(response).to have_gitlab_http_status(:not_found)
end
+ it 'renders 404 if client is a search engine crawler' do
+ request.env['HTTP_USER_AGENT'] = 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)'
+
+ get :index
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
it 'redirects to login page if not authenticated' do
get :index
diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb
index e7c0bc43e86..c2eb9d54303 100644
--- a/spec/controllers/autocomplete_controller_spec.rb
+++ b/spec/controllers/autocomplete_controller_spec.rb
@@ -382,6 +382,17 @@ RSpec.describe AutocompleteController do
sign_in(user)
end
+ context 'and they cannot read the project' do
+ it 'returns a not found response' do
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(false)
+
+ get(:deploy_keys_with_owners, params: { project_id: project.id })
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
it 'renders the deploy key in a json payload, with its owner' do
get(:deploy_keys_with_owners, params: { project_id: project.id })
diff --git a/spec/controllers/concerns/controller_with_feature_category_spec.rb b/spec/controllers/concerns/controller_with_feature_category_spec.rb
deleted file mode 100644
index 55e84755f5c..00000000000
--- a/spec/controllers/concerns/controller_with_feature_category_spec.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require_relative "../../../app/controllers/concerns/controller_with_feature_category"
-
-RSpec.describe ControllerWithFeatureCategory do
- describe ".feature_category_for_action" do
- let(:base_controller) do
- Class.new do
- include ControllerWithFeatureCategory
- end
- end
-
- let(:controller) do
- Class.new(base_controller) do
- feature_category :foo, %w(update edit)
- feature_category :bar, %w(index show)
- feature_category :quux, %w(destroy)
- end
- end
-
- let(:subclass) do
- Class.new(controller) do
- feature_category :baz, %w(subclass_index)
- end
- end
-
- it "is nil when nothing was defined" do
- expect(base_controller.feature_category_for_action("hello")).to be_nil
- end
-
- it "returns the expected category", :aggregate_failures do
- expect(controller.feature_category_for_action("update")).to eq(:foo)
- expect(controller.feature_category_for_action("index")).to eq(:bar)
- expect(controller.feature_category_for_action("destroy")).to eq(:quux)
- end
-
- it "returns the expected category for categories defined in subclasses" do
- expect(subclass.feature_category_for_action("subclass_index")).to eq(:baz)
- end
-
- it "raises an error when defining for the controller and for individual actions" do
- expect do
- Class.new(base_controller) do
- feature_category :hello
- feature_category :goodbye, [:world]
- end
- end.to raise_error(ArgumentError, "hello is defined for all actions, but other categories are set")
- end
-
- it "raises an error when multiple calls define the same action" do
- expect do
- Class.new(base_controller) do
- feature_category :hello, [:world]
- feature_category :goodbye, ["world"]
- end
- end.to raise_error(ArgumentError, "Actions have multiple feature categories: world")
- end
- end
-end
diff --git a/spec/controllers/concerns/lfs_request_spec.rb b/spec/controllers/concerns/lfs_request_spec.rb
deleted file mode 100644
index 3bafd761a3e..00000000000
--- a/spec/controllers/concerns/lfs_request_spec.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe LfsRequest do
- include ProjectForksHelper
-
- controller(Repositories::GitHttpClientController) do
- # `described_class` is not available in this context
- include LfsRequest
-
- def show
- head :ok
- end
-
- def project
- @project ||= Project.find_by(id: params[:id])
- end
-
- def download_request?
- true
- end
-
- def upload_request?
- false
- end
-
- def ci?
- false
- end
- end
-
- let(:project) { create(:project, :public) }
-
- before do
- stub_lfs_setting(enabled: true)
- end
-
- context 'user is authenticated without access to lfs' do
- before do
- allow(controller).to receive(:authenticate_user)
- allow(controller).to receive(:authentication_result) do
- Gitlab::Auth::Result.new
- end
- end
-
- context 'with access to the project' do
- it 'returns 403' do
- get :show, params: { id: project.id }
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- context 'without access to the project' do
- context 'project does not exist' do
- it 'returns 404' do
- get :show, params: { id: 'does not exist' }
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'project is private' do
- let(:project) { create(:project, :private) }
-
- it 'returns 404' do
- get :show, params: { id: project.id }
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
- end
-end
diff --git a/spec/controllers/concerns/metrics_dashboard_spec.rb b/spec/controllers/concerns/metrics_dashboard_spec.rb
index 8a4d8828aaa..83546403ce5 100644
--- a/spec/controllers/concerns/metrics_dashboard_spec.rb
+++ b/spec/controllers/concerns/metrics_dashboard_spec.rb
@@ -155,6 +155,7 @@ RSpec.describe MetricsDashboard do
'.gitlab/dashboards/errors.yml' => dashboard_yml
}
end
+
let_it_be(:project) { create(:project, :custom_repo, files: dashboards) }
before do
diff --git a/spec/controllers/concerns/send_file_upload_spec.rb b/spec/controllers/concerns/send_file_upload_spec.rb
index 747ccd7ba1b..f9a6afb95ea 100644
--- a/spec/controllers/concerns/send_file_upload_spec.rb
+++ b/spec/controllers/concerns/send_file_upload_spec.rb
@@ -70,61 +70,18 @@ RSpec.describe SendFileUpload do
allow(uploader).to receive(:model).and_return(image_owner)
end
- 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_requester: true)
- stub_feature_flags(dynamic_image_resizing_owner: true)
- end
-
- it_behaves_like 'handles image resize requests allowed by FFs'
-
- 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 '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
-
- 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
-
- it_behaves_like 'bypasses image resize requests not allowed by FFs'
- end
+ it_behaves_like 'handles image resize requests allowed by FF'
- context 'when both FFs are disabled' do
+ context 'when FF is disabled' do
before do
- stub_feature_flags(dynamic_image_resizing_requester: false)
- stub_feature_flags(dynamic_image_resizing_owner: false)
+ stub_feature_flags(dynamic_image_resizing: false)
end
- it_behaves_like 'bypasses image resize requests not allowed by FFs'
+ it_behaves_like 'bypasses image resize requests not allowed by FF'
end
end
- shared_examples 'bypasses image resize requests not allowed by FFs' do
+ shared_examples 'bypasses image resize requests not allowed by FF' do
it 'does not write workhorse command header' do
expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/)
@@ -132,7 +89,7 @@ RSpec.describe SendFileUpload do
end
end
- shared_examples 'handles image resize requests allowed by FFs' do
+ shared_examples 'handles image resize requests allowed by FF' do
context 'with valid width parameter' do
it 'renders OK with workhorse command header' do
expect(controller).not_to receive(:send_file)
diff --git a/spec/controllers/every_controller_spec.rb b/spec/controllers/every_controller_spec.rb
index b1519c4ef1e..a1c377eff76 100644
--- a/spec/controllers/every_controller_spec.rb
+++ b/spec/controllers/every_controller_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe "Every controller" do
.compact
.select { |route| route[:controller].present? && route[:action].present? }
.map { |route| [constantize_controller(route[:controller]), route[:action]] }
- .select { |(controller, action)| controller&.include?(ControllerWithFeatureCategory) }
+ .select { |(controller, action)| controller&.include?(::Gitlab::WithFeatureCategory) }
.reject { |(controller, action)| controller == ApplicationController || controller == Devise::UnlocksController }
end
diff --git a/spec/controllers/groups/dependency_proxies_controller_spec.rb b/spec/controllers/groups/dependency_proxies_controller_spec.rb
new file mode 100644
index 00000000000..35bd7d47aed
--- /dev/null
+++ b/spec/controllers/groups/dependency_proxies_controller_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::DependencyProxiesController do
+ let(:group) { create(:group) }
+ let(:user) { create(:user) }
+
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ describe 'GET #show' do
+ context 'feature enabled' do
+ before do
+ enable_dependency_proxy
+ end
+
+ it 'returns 200 and renders the view' do
+ get :show, params: { group_id: group.to_param }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template('groups/dependency_proxies/show')
+ end
+ end
+
+ it 'returns 404 when feature is disabled' do
+ disable_dependency_proxy
+
+ get :show, params: { group_id: group.to_param }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ describe 'PUT #update' do
+ context 'feature enabled' do
+ before do
+ enable_dependency_proxy
+ end
+
+ it 'redirects back to show page' do
+ put :update, params: update_params
+
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+
+ it 'returns 404 when feature is disabled' do
+ put :update, params: update_params
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ def update_params
+ {
+ group_id: group.to_param,
+ dependency_proxy_group_setting: { enabled: true }
+ }
+ end
+ end
+
+ def enable_dependency_proxy
+ stub_config(dependency_proxy: { enabled: true })
+
+ group.create_dependency_proxy_setting!(enabled: true)
+ end
+
+ def disable_dependency_proxy
+ group.create_dependency_proxy_setting!(enabled: false)
+ end
+end
diff --git a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
new file mode 100644
index 00000000000..615b56ff22f
--- /dev/null
+++ b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
@@ -0,0 +1,161 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::DependencyProxyForContainersController do
+ let(:group) { create(:group) }
+ let(:token_response) { { status: :success, token: 'abcd1234' } }
+
+ shared_examples 'not found when disabled' do
+ context 'feature disabled' do
+ before do
+ disable_dependency_proxy
+ end
+
+ it 'returns 404' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ before do
+ allow(Gitlab.config.dependency_proxy)
+ .to receive(:enabled).and_return(true)
+
+ allow_next_instance_of(DependencyProxy::RequestTokenService) do |instance|
+ allow(instance).to receive(:execute).and_return(token_response)
+ end
+ end
+
+ describe 'GET #manifest' do
+ let(:manifest) { { foo: 'bar' }.to_json }
+ let(:pull_response) { { status: :success, manifest: manifest } }
+
+ before do
+ allow_next_instance_of(DependencyProxy::PullManifestService) do |instance|
+ allow(instance).to receive(:execute).and_return(pull_response)
+ end
+ end
+
+ subject { get_manifest }
+
+ context 'feature enabled' do
+ before do
+ enable_dependency_proxy
+ end
+
+ context 'remote token request fails' do
+ let(:token_response) do
+ {
+ status: :error,
+ http_status: 503,
+ message: 'Service Unavailable'
+ }
+ end
+
+ it 'proxies status from the remote token request' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:service_unavailable)
+ expect(response.body).to eq('Service Unavailable')
+ end
+ end
+
+ context 'remote manifest request fails' do
+ let(:pull_response) do
+ {
+ status: :error,
+ http_status: 400,
+ message: ''
+ }
+ end
+
+ it 'proxies status from the remote manifest request' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.body).to be_empty
+ end
+ end
+
+ it 'returns 200 with manifest file' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq(manifest)
+ end
+ end
+
+ it_behaves_like 'not found when disabled'
+
+ def get_manifest
+ get :manifest, params: { group_id: group.to_param, image: 'alpine', tag: '3.9.2' }
+ end
+ end
+
+ describe 'GET #blob' do
+ let(:blob) { create(:dependency_proxy_blob) }
+ let(:blob_sha) { blob.file_name.sub('.gz', '') }
+ let(:blob_response) { { status: :success, blob: blob } }
+
+ before do
+ allow_next_instance_of(DependencyProxy::FindOrCreateBlobService) do |instance|
+ allow(instance).to receive(:execute).and_return(blob_response)
+ end
+ end
+
+ subject { get_blob }
+
+ context 'feature enabled' do
+ before do
+ enable_dependency_proxy
+ end
+
+ context 'remote blob request fails' do
+ let(:blob_response) do
+ {
+ status: :error,
+ http_status: 400,
+ message: ''
+ }
+ end
+
+ it 'proxies status from the remote blob request' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.body).to be_empty
+ end
+ end
+
+ it 'sends a file' do
+ expect(controller).to receive(:send_file).with(blob.file.path, {})
+
+ subject
+ end
+
+ it 'returns Content-Disposition: attachment' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers['Content-Disposition']).to match(/^attachment/)
+ end
+ end
+
+ it_behaves_like 'not found when disabled'
+
+ def get_blob
+ get :blob, params: { group_id: group.to_param, image: 'alpine', sha: blob_sha }
+ end
+ end
+
+ def enable_dependency_proxy
+ group.create_dependency_proxy_setting!(enabled: true)
+ end
+
+ def disable_dependency_proxy
+ group.create_dependency_proxy_setting!(enabled: false)
+ end
+end
diff --git a/spec/controllers/groups/registry/repositories_controller_spec.rb b/spec/controllers/groups/registry/repositories_controller_spec.rb
index ae982b02a4f..70125087f30 100644
--- a/spec/controllers/groups/registry/repositories_controller_spec.rb
+++ b/spec/controllers/groups/registry/repositories_controller_spec.rb
@@ -64,12 +64,11 @@ RSpec.describe Groups::Registry::RepositoriesController do
context 'html format' do
let(:format) { :html }
- it 'show index page' do
- expect(Gitlab::Tracking).not_to receive(:event)
-
+ it 'show index page', :snowplow do
subject
expect(response).to have_gitlab_http_status(:ok)
+ expect_no_snowplow_event
end
end
diff --git a/spec/controllers/groups/settings/integrations_controller_spec.rb b/spec/controllers/groups/settings/integrations_controller_spec.rb
index cdcdfde175f..beb2ad3afec 100644
--- a/spec/controllers/groups/settings/integrations_controller_spec.rb
+++ b/spec/controllers/groups/settings/integrations_controller_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe Groups::Settings::IntegrationsController do
describe '#edit' do
context 'when user is not owner' do
it 'renders not_found' do
- get :edit, params: { group_id: group, id: Service.available_services_names.sample }
+ get :edit, params: { group_id: group, id: Service.available_services_names(include_project_specific: false).sample }
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -61,13 +61,13 @@ RSpec.describe Groups::Settings::IntegrationsController do
it 'returns not_found' do
stub_feature_flags(group_level_integrations: false)
- get :edit, params: { group_id: group, id: Service.available_services_names.sample }
+ get :edit, params: { group_id: group, id: Service.available_services_names(include_project_specific: false).sample }
expect(response).to have_gitlab_http_status(:not_found)
end
end
- Service.available_services_names.each do |integration_name|
+ Service.available_services_names(include_project_specific: false).each do |integration_name|
context "#{integration_name}" do
it 'successfully displays the template' do
get :edit, params: { group_id: group, id: integration_name }
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index df7e018b35e..55833ee3aad 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -319,10 +319,10 @@ RSpec.describe GroupsController, factory_default: :keep do
stub_experiment(onboarding_issues: false)
end
- it 'does not track anything' do
- expect(Gitlab::Tracking).not_to receive(:event)
-
+ it 'does not track anything', :snowplow do
create_namespace
+
+ expect_no_snowplow_event
end
end
@@ -336,15 +336,15 @@ RSpec.describe GroupsController, factory_default: :keep do
stub_experiment_for_user(onboarding_issues: false)
end
- it 'tracks the event with the "created_namespace" action with the "control_group" property' do
- expect(Gitlab::Tracking).to receive(:event).with(
- 'Growth::Conversion::Experiment::OnboardingIssues',
- 'created_namespace',
+ it 'tracks the event with the "created_namespace" action with the "control_group" property', :snowplow do
+ create_namespace
+
+ expect_snowplow_event(
+ category: 'Growth::Conversion::Experiment::OnboardingIssues',
+ action: 'created_namespace',
label: anything,
property: 'control_group'
)
-
- create_namespace
end
end
@@ -353,15 +353,15 @@ RSpec.describe GroupsController, factory_default: :keep do
stub_experiment_for_user(onboarding_issues: true)
end
- it 'tracks the event with the "created_namespace" action with the "experimental_group" property' do
- expect(Gitlab::Tracking).to receive(:event).with(
- 'Growth::Conversion::Experiment::OnboardingIssues',
- 'created_namespace',
+ it 'tracks the event with the "created_namespace" action with the "experimental_group" property', :snowplow do
+ create_namespace
+
+ expect_snowplow_event(
+ category: 'Growth::Conversion::Experiment::OnboardingIssues',
+ action: 'created_namespace',
label: anything,
property: 'experimental_group'
)
-
- create_namespace
end
end
end
@@ -1213,4 +1213,60 @@ RSpec.describe GroupsController, factory_default: :keep do
it_behaves_like 'disabled when using an external authorization service'
end
end
+
+ describe 'GET #unfoldered_environment_names' do
+ it 'shows the environment names of a public project to an anonymous user' do
+ public_project = create(:project, :public, namespace: group)
+
+ create(:environment, project: public_project, name: 'foo')
+
+ get(
+ :unfoldered_environment_names,
+ params: { id: group, format: :json }
+ )
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq(%w[foo])
+ end
+
+ it 'does not show environment names of private projects to anonymous users' do
+ create(:environment, project: project, name: 'foo')
+
+ get(
+ :unfoldered_environment_names,
+ params: { id: group, format: :json }
+ )
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_empty
+ end
+
+ it 'shows environment names of a private project to a group member' do
+ create(:environment, project: project, name: 'foo')
+ sign_in(developer)
+
+ get(
+ :unfoldered_environment_names,
+ params: { id: group, format: :json }
+ )
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq(%w[foo])
+ end
+
+ it 'does not show environment names of private projects to a logged-in non-member' do
+ alice = create(:user)
+
+ create(:environment, project: project, name: 'foo')
+ sign_in(alice)
+
+ get(
+ :unfoldered_environment_names,
+ params: { id: group, format: :json }
+ )
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_empty
+ end
+ end
end
diff --git a/spec/controllers/import/bulk_imports_controller_spec.rb b/spec/controllers/import/bulk_imports_controller_spec.rb
index f3850ff844e..dd850a86227 100644
--- a/spec/controllers/import/bulk_imports_controller_spec.rb
+++ b/spec/controllers/import/bulk_imports_controller_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe Import::BulkImportsController do
expect(session[:bulk_import_gitlab_url]).to be_nil
expect(response).to have_gitlab_http_status(:found)
- expect(response).to redirect_to(status_import_bulk_import_url)
+ expect(response).to redirect_to(status_import_bulk_imports_url)
end
end
@@ -37,7 +37,7 @@ RSpec.describe Import::BulkImportsController do
expect(session[:bulk_import_gitlab_access_token]).to eq(token)
expect(session[:bulk_import_gitlab_url]).to eq(url)
expect(response).to have_gitlab_http_status(:found)
- expect(response).to redirect_to(status_import_bulk_import_url)
+ expect(response).to redirect_to(status_import_bulk_imports_url)
end
it 'strips access token with spaces' do
@@ -46,19 +46,21 @@ RSpec.describe Import::BulkImportsController do
post :configure, params: { bulk_import_gitlab_access_token: " #{token} " }
expect(session[:bulk_import_gitlab_access_token]).to eq(token)
- expect(controller).to redirect_to(status_import_bulk_import_url)
+ expect(controller).to redirect_to(status_import_bulk_imports_url)
end
end
describe 'GET status' do
- let(:client) { Gitlab::BulkImport::Client.new(uri: 'http://gitlab.example', token: 'token') }
+ let(:client) { BulkImports::Clients::Http.new(uri: 'http://gitlab.example', token: 'token') }
describe 'serialized group data' do
let(:client_response) do
- [
- { 'id' => 1, 'full_name' => 'group1', 'full_path' => 'full/path/group1' },
- { 'id' => 2, 'full_name' => 'group2', 'full_path' => 'full/path/group2' }
- ]
+ double(
+ parsed_response: [
+ { 'id' => 1, 'full_name' => 'group1', 'full_path' => 'full/path/group1' },
+ { 'id' => 2, 'full_name' => 'group2', 'full_path' => 'full/path/group2' }
+ ]
+ )
end
before do
@@ -69,7 +71,7 @@ RSpec.describe Import::BulkImportsController do
it 'returns serialized group data' do
get :status, format: :json
- expect(response.parsed_body).to eq({ importable_data: client_response }.as_json)
+ expect(json_response).to eq({ importable_data: client_response.parsed_response }.as_json)
end
end
@@ -111,7 +113,7 @@ RSpec.describe Import::BulkImportsController do
context 'when connection error occurs' do
before do
allow(controller).to receive(:client).and_return(client)
- allow(client).to receive(:get).and_raise(Gitlab::BulkImport::Client::ConnectionError)
+ allow(client).to receive(:get).and_raise(BulkImports::Clients::Http::ConnectionError)
end
it 'returns 422' do
@@ -128,9 +130,21 @@ RSpec.describe Import::BulkImportsController do
end
end
end
+
+ describe 'POST create' do
+ it 'executes BulkImportService' do
+ expect_next_instance_of(BulkImportService) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ post :create
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
end
- context 'when gitlab_api_imports feature flag is disabled' do
+ context 'when bulk_import feature flag is disabled' do
before do
stub_feature_flags(bulk_import: false)
end
diff --git a/spec/controllers/import/github_controller_spec.rb b/spec/controllers/import/github_controller_spec.rb
index e19b6caca5b..a408d821833 100644
--- a/spec/controllers/import/github_controller_spec.rb
+++ b/spec/controllers/import/github_controller_spec.rb
@@ -144,6 +144,58 @@ RSpec.describe Import::GithubController do
expect(json_response.dig('provider_repos', 0, 'id')).to eq(repo_1.id)
expect(json_response.dig('provider_repos', 1, 'id')).to eq(repo_2.id)
end
+
+ context 'when filtering' do
+ let(:filter) { 'test' }
+ let(:user_login) { 'user' }
+ let(:collaborations_subquery) { 'repo:repo1 repo:repo2' }
+ let(:organizations_subquery) { 'org:org1 org:org2' }
+
+ before do
+ allow_next_instance_of(Octokit::Client) do |client|
+ allow(client).to receive(:user).and_return(double(login: user_login))
+ end
+ end
+
+ it 'makes request to github search api' do
+ expected_query = "test in:name is:public,private user:#{user_login} #{collaborations_subquery} #{organizations_subquery}"
+
+ expect_next_instance_of(Gitlab::GithubImport::Client) do |client|
+ expect(client).to receive(:collaborations_subquery).and_return(collaborations_subquery)
+ expect(client).to receive(:organizations_subquery).and_return(organizations_subquery)
+ expect(client).to receive(:each_page).with(:search_repositories, expected_query).and_return([].to_enum)
+ end
+
+ get :status, params: { filter: filter }, format: :json
+ end
+
+ context 'when user input contains colons and spaces' do
+ before do
+ stub_client(search_repos_by_name: [])
+ end
+
+ it 'sanitizes user input' do
+ filter = ' test1:test2 test3 : test4 '
+ expected_filter = 'test1test2test3test4'
+
+ get :status, params: { filter: filter }, format: :json
+
+ expect(assigns(:filter)).to eq(expected_filter)
+ end
+ end
+
+ context 'when rate limit threshold is exceeded' do
+ before do
+ allow(controller).to receive(:status).and_raise(Gitlab::GithubImport::RateLimitError)
+ end
+
+ it 'returns 429' do
+ get :status, params: { filter: 'test' }, format: :json
+
+ expect(response).to have_gitlab_http_status(:too_many_requests)
+ end
+ end
+ end
end
end
diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb
index 75a972d2f95..2d13b942c31 100644
--- a/spec/controllers/invites_controller_spec.rb
+++ b/spec/controllers/invites_controller_spec.rb
@@ -9,13 +9,6 @@ RSpec.describe InvitesController, :snowplow do
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
shared_examples 'invalid token' do
context 'when invite token is not valid' do
@@ -94,38 +87,6 @@ RSpec.describe InvitesController, :snowplow do
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
-
it_behaves_like "tracks the 'accepted' event for the invitation reminders experiment"
it_behaves_like 'invalid token'
end
@@ -158,36 +119,6 @@ RSpec.describe InvitesController, :snowplow do
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_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: 'accepted'))
- end
- end
-
it_behaves_like "tracks the 'accepted' event for the invitation reminders experiment"
it_behaves_like 'invalid token'
end
diff --git a/spec/controllers/jwks_controller_spec.rb b/spec/controllers/jwks_controller_spec.rb
new file mode 100644
index 00000000000..013ec01eba2
--- /dev/null
+++ b/spec/controllers/jwks_controller_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JwksController do
+ describe 'GET #index' do
+ let(:ci_jwt_signing_key) { OpenSSL::PKey::RSA.generate(1024) }
+ let(:ci_jwk) { ci_jwt_signing_key.to_jwk }
+ let(:oidc_jwk) { OpenSSL::PKey::RSA.new(Rails.application.secrets.openid_connect_signing_key).to_jwk }
+
+ before do
+ stub_application_setting(ci_jwt_signing_key: ci_jwt_signing_key.to_s)
+ end
+
+ it 'returns signing keys used to sign CI_JOB_JWT' do
+ get :index
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ ids = json_response['keys'].map { |jwk| jwk['kid'] }
+ expect(ids).to contain_exactly(ci_jwk['kid'], oidc_jwk['kid'])
+ end
+
+ it 'does not leak private key data' do
+ get :index
+
+ aggregate_failures do
+ json_response['keys'].each do |jwk|
+ expect(jwk.keys).to contain_exactly('kty', 'kid', 'e', 'n', 'use', 'alg')
+ expect(jwk['use']).to eq('sig')
+ expect(jwk['alg']).to eq('RS256')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb
index 249e6322d1c..7a72a13febe 100644
--- a/spec/controllers/profiles_controller_spec.rb
+++ b/spec/controllers/profiles_controller_spec.rb
@@ -84,9 +84,10 @@ RSpec.describe ProfilesController, :request_store do
it 'allows setting a user status' do
sign_in(user)
- put :update, params: { user: { status: { message: 'Working hard!' } } }
+ put :update, params: { user: { status: { message: 'Working hard!', availability: 'busy' } } }
expect(user.reload.status.message).to eq('Working hard!')
+ expect(user.reload.status.availability).to eq('busy')
expect(response).to have_gitlab_http_status(:found)
end
diff --git a/spec/controllers/projects/alerting/notifications_controller_spec.rb b/spec/controllers/projects/alerting/notifications_controller_spec.rb
index 33fd73c762a..b3d37723ccf 100644
--- a/spec/controllers/projects/alerting/notifications_controller_spec.rb
+++ b/spec/controllers/projects/alerting/notifications_controller_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::Alerting::NotificationsController do
let_it_be(:project) { create(:project) }
let_it_be(:environment) { create(:environment, project: project) }
+ let(:params) { project_params }
describe 'POST #create' do
around do |example|
@@ -20,7 +21,7 @@ RSpec.describe Projects::Alerting::NotificationsController do
end
def make_request
- post :create, params: project_params, body: payload.to_json, as: :json
+ post :create, params: params, body: payload.to_json, as: :json
end
context 'when notification service succeeds' do
@@ -53,26 +54,69 @@ RSpec.describe Projects::Alerting::NotificationsController do
context 'bearer token' do
context 'when set' do
- it 'extracts bearer token' do
- request.headers['HTTP_AUTHORIZATION'] = 'Bearer some token'
+ context 'when extractable' do
+ before do
+ request.headers['HTTP_AUTHORIZATION'] = 'Bearer some token'
+ end
- expect(notify_service).to receive(:execute).with('some token')
+ it 'extracts bearer token' do
+ expect(notify_service).to receive(:execute).with('some token', nil)
- make_request
+ make_request
+ end
+
+ context 'with a corresponding integration' do
+ context 'with integration parameters specified' do
+ let_it_be_with_reload(:integration) { create(:alert_management_http_integration, project: project) }
+ let(:params) { project_params(endpoint_identifier: integration.endpoint_identifier, name: integration.name) }
+
+ context 'the integration is active' do
+ it 'extracts and finds the integration' do
+ expect(notify_service).to receive(:execute).with('some token', integration)
+
+ make_request
+ end
+ end
+
+ context 'when the integration is inactive' do
+ before do
+ integration.update!(active: false)
+ end
+
+ it 'does not find an integration' do
+ expect(notify_service).to receive(:execute).with('some token', nil)
+
+ make_request
+ end
+ end
+ end
+
+ context 'without integration parameters specified' do
+ let_it_be(:integration) { create(:alert_management_http_integration, :legacy, project: project) }
+
+ it 'extracts and finds the legacy integration' do
+ expect(notify_service).to receive(:execute).with('some token', integration)
+
+ make_request
+ end
+ end
+ end
end
- it 'pass nil if cannot extract a non-bearer token' do
- request.headers['HTTP_AUTHORIZATION'] = 'some token'
+ context 'when inextractable' do
+ it 'passes nil for a non-bearer token' do
+ request.headers['HTTP_AUTHORIZATION'] = 'some token'
- expect(notify_service).to receive(:execute).with(nil)
+ expect(notify_service).to receive(:execute).with(nil, nil)
- make_request
+ make_request
+ end
end
end
context 'when missing' do
it 'passes nil' do
- expect(notify_service).to receive(:execute).with(nil)
+ expect(notify_service).to receive(:execute).with(nil, nil)
make_request
end
diff --git a/spec/controllers/projects/avatars_controller_spec.rb b/spec/controllers/projects/avatars_controller_spec.rb
index 16e9c845307..35878fe4c2d 100644
--- a/spec/controllers/projects/avatars_controller_spec.rb
+++ b/spec/controllers/projects/avatars_controller_spec.rb
@@ -3,14 +3,14 @@
require 'spec_helper'
RSpec.describe Projects::AvatarsController do
- let_it_be(:project) { create(:project, :repository) }
+ describe 'GET #show' do
+ let_it_be(:project) { create(:project, :public, :repository) }
- before do
- controller.instance_variable_set(:@project, project)
- end
+ before do
+ controller.instance_variable_set(:@project, project)
+ end
- describe 'GET #show' do
- subject { get :show, params: { namespace_id: project.namespace, project_id: project } }
+ subject { get :show, params: { namespace_id: project.namespace, project_id: project.path } }
context 'when repository has no avatar' do
it 'shows 404' do
@@ -37,6 +37,15 @@ RSpec.describe Projects::AvatarsController do
expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq 'true'
end
+ it 'sets appropriate caching headers' do
+ sign_in(project.owner)
+ subject
+
+ expect(response.cache_control[:public]).to eq(true)
+ expect(response.cache_control[:max_age]).to eq(60)
+ expect(response.cache_control[:no_store]).to be_nil
+ end
+
it_behaves_like 'project cache control headers'
end
@@ -51,9 +60,16 @@ RSpec.describe Projects::AvatarsController do
end
describe 'DELETE #destroy' do
+ let(:project) { create(:project, :repository, avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) }
+
+ before do
+ sign_in(project.owner)
+ end
+
it 'removes avatar from DB by calling destroy' do
- delete :destroy, params: { namespace_id: project.namespace.id, project_id: project.id }
+ delete :destroy, params: { namespace_id: project.namespace.path, project_id: project.path }
+ expect(response).to redirect_to(edit_project_path(project, anchor: 'js-general-project-settings'))
expect(project.avatar.present?).to be_falsey
expect(project).to be_valid
end
diff --git a/spec/controllers/projects/ci/lints_controller_spec.rb b/spec/controllers/projects/ci/lints_controller_spec.rb
index 22f052e39b7..c4e040b0287 100644
--- a/spec/controllers/projects/ci/lints_controller_spec.rb
+++ b/spec/controllers/projects/ci/lints_controller_spec.rb
@@ -47,9 +47,9 @@ RSpec.describe Projects::Ci::LintsController do
describe 'POST #create' do
subject { post :create, params: params }
- let(:format) { :html }
- let(:params) { { namespace_id: project.namespace, project_id: project, content: content, format: format } }
+ let(:params) { { namespace_id: project.namespace, project_id: project, content: content, format: :json } }
let(:remote_file_path) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' }
+ let(:parsed_body) { Gitlab::Json.parse(response.body) }
let(:remote_file_content) do
<<~HEREDOC
@@ -72,17 +72,23 @@ 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) }
+ shared_examples 'returns a successful validation' do
+ before do
+ subject
+ end
- 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
+ it 'returns successfully' do
+ expect(response).to have_gitlab_http_status :ok
+ end
+
+ it 'renders json' do
+ 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
+
+ it 'retrieves project' do
+ expect(assigns(:project)).to eq(project)
end
end
@@ -92,25 +98,7 @@ RSpec.describe Projects::Ci::LintsController do
project.add_developer(user)
end
- shared_examples 'returns a successful validation' do
- before do
- subject
- end
-
- 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
- expect(assigns(:project)).to eq(project)
- end
-
- it_behaves_like 'successful request with format json'
- end
+ it_behaves_like 'returns a successful validation'
context 'using legacy validation (YamlProcessor)' do
it_behaves_like 'returns a successful validation'
@@ -135,20 +123,6 @@ RSpec.describe Projects::Ci::LintsController do
subject
end
-
- context 'when dry_run feature flag is disabled' do
- before do
- stub_feature_flags(ci_lint_creates_pipeline_with_dry_run: false)
- end
-
- it_behaves_like 'returns a successful validation'
-
- it 'runs validations through YamlProcessor' do
- expect(Gitlab::Ci::YamlProcessor).to receive(:new).and_call_original
-
- subject
- end
- end
end
end
@@ -166,27 +140,23 @@ RSpec.describe Projects::Ci::LintsController do
subject
end
+ it_behaves_like 'returns a successful validation'
+
it 'assigns result with errors' do
- expect(assigns[:result].errors).to match_array([
+ expect(parsed_body['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
- 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 result with errors' do
- expect(assigns[:result].errors).to eq(['jobs rubocop config should implement a script: or a trigger: keyword'])
+ expect(parsed_body['errors']).to eq(['jobs rubocop config should implement a script: or a trigger: keyword'])
end
- it_behaves_like 'successful request with format json'
+ it_behaves_like 'returns a successful validation'
end
end
@@ -200,14 +170,6 @@ 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/ci/pipeline_editor_controller_spec.rb b/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb
new file mode 100644
index 00000000000..1bf6ff95c44
--- /dev/null
+++ b/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::Ci::PipelineEditorController do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'GET #show' do
+ context 'with enough privileges' do
+ before do
+ project.add_developer(user)
+
+ get :show, params: { namespace_id: project.namespace, project_id: project }
+ end
+
+ it { expect(response).to have_gitlab_http_status(:ok) }
+
+ it 'renders show page' do
+ expect(response).to render_template :show
+ end
+ end
+
+ context 'without enough privileges' do
+ before do
+ project.add_reporter(user)
+
+ get :show, params: { namespace_id: project.namespace, project_id: project }
+ end
+
+ it 'responds with 404' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when ci_pipeline_editor_page feature flag is disabled' do
+ before do
+ stub_feature_flags(ci_pipeline_editor_page: false)
+ project.add_developer(user)
+
+ get :show, params: { namespace_id: project.namespace, project_id: project }
+ end
+
+ it 'responds with 404' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects/cycle_analytics/events_controller_spec.rb b/spec/controllers/projects/cycle_analytics/events_controller_spec.rb
index c5b72ff2b3b..f940da7ea35 100644
--- a/spec/controllers/projects/cycle_analytics/events_controller_spec.rb
+++ b/spec/controllers/projects/cycle_analytics/events_controller_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Projects::CycleAnalytics::EventsController do
project.add_maintainer(user)
end
- describe 'cycle analytics not set up flag' do
+ describe 'value stream analytics not set up flag' do
context 'with no data' do
it 'is empty' do
get_issue
diff --git a/spec/controllers/projects/cycle_analytics_controller_spec.rb b/spec/controllers/projects/cycle_analytics_controller_spec.rb
index e956065972f..24c2d568d9a 100644
--- a/spec/controllers/projects/cycle_analytics_controller_spec.rb
+++ b/spec/controllers/projects/cycle_analytics_controller_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe Projects::CycleAnalyticsController do
end
end
- describe 'cycle analytics not set up flag' do
+ describe 'value stream analytics not set up flag' do
context 'with no data' do
it 'is true' do
get(:show,
diff --git a/spec/controllers/projects/imports_controller_spec.rb b/spec/controllers/projects/imports_controller_spec.rb
index 029b4210f19..5e09a50aa36 100644
--- a/spec/controllers/projects/imports_controller_spec.rb
+++ b/spec/controllers/projects/imports_controller_spec.rb
@@ -7,10 +7,21 @@ RSpec.describe Projects::ImportsController do
let(:project) { create(:project) }
before do
- sign_in(user)
+ sign_in(user) if user
end
describe 'GET #show' do
+ context 'when user is not authenticated and the project is public' do
+ let(:user) { nil }
+ let(:project) { create(:project, :public) }
+
+ it 'returns 404 response' do
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
context 'when the user has maintainer rights' do
before do
project.add_maintainer(user)
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index f956baa0e22..26e1842468b 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -52,14 +52,14 @@ RSpec.describe Projects::IssuesController do
get :index, params: { namespace_id: project.namespace, project_id: project }
expect(response).to redirect_to(project_issues_path(new_project))
- expect(response).to have_gitlab_http_status(:found)
+ expect(response).to have_gitlab_http_status(:moved_permanently)
end
it 'redirects from an old issue correctly' do
get :show, params: { namespace_id: project.namespace, project_id: project, id: issue }
expect(response).to redirect_to(project_issue_path(new_project, issue))
- expect(response).to have_gitlab_http_status(:found)
+ expect(response).to have_gitlab_http_status(:moved_permanently)
end
end
end
@@ -1869,7 +1869,7 @@ RSpec.describe Projects::IssuesController do
}
expect(response).to redirect_to(designs_project_issue_path(new_project, issue))
- expect(response).to have_gitlab_http_status(:found)
+ expect(response).to have_gitlab_http_status(:moved_permanently)
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 91770a00081..bda1f1a3b1c 100644
--- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
@@ -383,6 +383,7 @@ RSpec.describe Projects::MergeRequests::DiffsController do
environment: nil,
merge_request: merge_request,
diff_view: :inline,
+ merge_ref_head_diff: nil,
pagination_data: {
current_page: nil,
next_page: nil,
@@ -454,6 +455,31 @@ RSpec.describe Projects::MergeRequests::DiffsController do
it_behaves_like 'successful request'
end
+ context 'with paths param' do
+ let(:example_file_path) { "README" }
+ let(:file_path_option) { { paths: [example_file_path] } }
+
+ subject do
+ go(file_path_option)
+ end
+
+ it_behaves_like 'serializes diffs with expected arguments' do
+ let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
+ let(:expected_options) do
+ collection_arguments(current_page: 1, total_pages: 1)
+ end
+ end
+
+ it_behaves_like 'successful request'
+
+ it 'filters down the response to the expected file path' do
+ subject
+
+ expect(json_response["diff_files"].size).to eq(1)
+ expect(json_response["diff_files"].first["file_path"]).to eq(example_file_path)
+ end
+ end
+
context 'with default params' do
subject { go }
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index ee194e5ff2f..f159f0e6099 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -6,14 +6,10 @@ RSpec.describe Projects::MergeRequestsController do
include ProjectForksHelper
include Gitlab::Routing
- let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let_it_be_with_refind(:project) { create(:project, :repository) }
+ let_it_be_with_reload(:project_public_with_private_builds) { create(:project, :repository, :public, :builds_private) }
+ let(:user) { project.owner }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
- let(:merge_request_with_conflicts) do
- create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start', source_project: project, merge_status: :unchecked) do |mr|
- mr.mark_as_unmergeable
- end
- end
before do
sign_in(user)
@@ -99,7 +95,8 @@ RSpec.describe Projects::MergeRequestsController do
project,
merge_request,
'json',
- diff_head: true))
+ diff_head: true,
+ view: 'inline'))
end
end
@@ -107,7 +104,7 @@ RSpec.describe Projects::MergeRequestsController do
render_views
it 'renders merge request page' do
- merge_request.merge_request_diff.destroy
+ merge_request.merge_request_diff.destroy!
go(format: :html)
@@ -147,7 +144,7 @@ RSpec.describe Projects::MergeRequestsController do
let(:new_project) { create(:project) }
before do
- project.route.destroy
+ project.route.destroy!
new_project.redirect_routes.create!(path: project.full_path)
new_project.add_developer(user)
end
@@ -161,7 +158,7 @@ RSpec.describe Projects::MergeRequestsController do
}
expect(response).to redirect_to(project_merge_request_path(new_project, merge_request))
- expect(response).to have_gitlab_http_status(:found)
+ expect(response).to have_gitlab_http_status(:moved_permanently)
end
it 'redirects from an old merge request commits correctly' do
@@ -173,7 +170,7 @@ RSpec.describe Projects::MergeRequestsController do
}
expect(response).to redirect_to(commits_project_merge_request_path(new_project, merge_request))
- expect(response).to have_gitlab_http_status(:found)
+ expect(response).to have_gitlab_http_status(:moved_permanently)
end
end
end
@@ -359,12 +356,11 @@ RSpec.describe Projects::MergeRequestsController do
end
context 'there is no source project' do
- let(:project) { create(:project, :repository) }
let(:forked_project) { fork_project_with_submodules(project) }
let!(:merge_request) { create(:merge_request, source_project: forked_project, source_branch: 'add-submodule-version-bump', target_branch: 'master', target_project: project) }
before do
- forked_project.destroy
+ forked_project.destroy!
end
it 'closes MR without errors' do
@@ -435,7 +431,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'when the merge request is not mergeable' do
before do
- merge_request.update(title: "WIP: #{merge_request.title}")
+ merge_request.update!(title: "WIP: #{merge_request.title}")
post :merge, params: base_params
end
@@ -475,7 +471,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'when squash is passed as 1' do
it 'updates the squash attribute on the MR to true' do
- merge_request.update(squash: false)
+ merge_request.update!(squash: false)
merge_with_sha(squash: '1')
expect(merge_request.reload.squash_on_merge?).to be_truthy
@@ -484,7 +480,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'when squash is passed as 0' do
it 'updates the squash attribute on the MR to false' do
- merge_request.update(squash: true)
+ merge_request.update!(squash: true)
merge_with_sha(squash: '0')
expect(merge_request.reload.squash_on_merge?).to be_falsey
@@ -547,7 +543,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'and head pipeline is not the current one' do
before do
- head_pipeline.update(sha: 'not_current_sha')
+ head_pipeline.update!(sha: 'not_current_sha')
end
it 'returns :failed' do
@@ -667,9 +663,9 @@ RSpec.describe Projects::MergeRequestsController do
end
context "when the user is owner" do
- let(:owner) { create(:user) }
- let(:namespace) { create(:namespace, owner: owner) }
- let(:project) { create(:project, :repository, namespace: namespace) }
+ let_it_be(:owner) { create(:user) }
+ let_it_be(:namespace) { create(:namespace, owner: owner) }
+ let_it_be(:project) { create(:project, :repository, namespace: namespace) }
before do
sign_in owner
@@ -765,7 +761,7 @@ RSpec.describe Projects::MergeRequestsController do
end
context 'with private builds on a public project' do
- let(:project) { create(:project, :repository, :public, :builds_private) }
+ let(:project) { project_public_with_private_builds }
context 'for a project owner' do
it 'responds with serialized pipelines' do
@@ -813,7 +809,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'with public builds' do
let(:forked_project) do
fork_project(project, fork_user, repository: true).tap do |new_project|
- new_project.project_feature.update(builds_access_level: ProjectFeature::ENABLED)
+ new_project.project_feature.update!(builds_access_level: ProjectFeature::ENABLED)
end
end
@@ -855,7 +851,7 @@ RSpec.describe Projects::MergeRequestsController do
end
describe 'GET exposed_artifacts' do
- let(:merge_request) do
+ let_it_be(:merge_request) do
create(:merge_request,
:with_merge_request_pipeline,
target_project: project,
@@ -993,7 +989,7 @@ RSpec.describe Projects::MergeRequestsController do
end
describe 'GET coverage_reports' do
- let(:merge_request) do
+ let_it_be(:merge_request) do
create(:merge_request,
:with_merge_request_pipeline,
target_project: project,
@@ -1123,7 +1119,7 @@ RSpec.describe Projects::MergeRequestsController do
end
describe 'GET terraform_reports' do
- let(:merge_request) do
+ let_it_be(:merge_request) do
create(:merge_request,
:with_merge_request_pipeline,
target_project: project,
@@ -1271,7 +1267,7 @@ RSpec.describe Projects::MergeRequestsController do
end
describe 'GET test_reports' do
- let(:merge_request) do
+ let_it_be(:merge_request) do
create(:merge_request,
:with_diffs,
:with_merge_request_pipeline,
@@ -1382,7 +1378,7 @@ RSpec.describe Projects::MergeRequestsController do
end
describe 'GET accessibility_reports' do
- let(:merge_request) do
+ let_it_be(:merge_request) do
create(:merge_request,
:with_diffs,
:with_merge_request_pipeline,
@@ -1419,7 +1415,7 @@ RSpec.describe Projects::MergeRequestsController do
end
context 'permissions on a public project with private CI/CD' do
- let(:project) { create(:project, :repository, :public, :builds_private) }
+ let(:project) { project_public_with_private_builds }
let(:accessibility_comparison) { { status: :parsed, data: { summary: 1 } } }
context 'while signed out' do
@@ -1505,7 +1501,7 @@ RSpec.describe Projects::MergeRequestsController do
describe 'POST remove_wip' do
before do
merge_request.title = merge_request.wip_title
- merge_request.save
+ merge_request.save!
post :remove_wip,
params: {
@@ -1626,7 +1622,7 @@ RSpec.describe Projects::MergeRequestsController do
it 'links to the environment on that project', :sidekiq_might_not_need_inline do
get_ci_environments_status
- expect(json_response.first['url']).to match /#{forked.full_path}/
+ expect(json_response.first['url']).to match(/#{forked.full_path}/)
end
context "when environment_target is 'merge_commit'", :sidekiq_might_not_need_inline do
@@ -1653,7 +1649,7 @@ RSpec.describe Projects::MergeRequestsController do
get_ci_environments_status(environment_target: 'merge_commit')
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.first['url']).to match /#{project.full_path}/
+ expect(json_response.first['url']).to match(/#{project.full_path}/)
end
end
end
@@ -1773,7 +1769,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'with project member visibility on a public project' do
let(:user) { create(:user) }
- let(:project) { create(:project, :repository, :public, :builds_private) }
+ let(:project) { project_public_with_private_builds }
it 'returns pipeline data to project members' do
project.add_developer(user)
@@ -1999,4 +1995,21 @@ RSpec.describe Projects::MergeRequestsController do
expect(assigns(:noteable)).not_to be_nil
end
end
+
+ describe 'POST export_csv' do
+ subject { post :export_csv, params: { namespace_id: project.namespace, project_id: project } }
+
+ it 'redirects to the merge request index' do
+ subject
+
+ expect(response).to redirect_to(project_merge_requests_path(project))
+ expect(response.flash[:notice]).to match(/\AYour CSV export has started/i)
+ end
+
+ it 'enqueues an IssuableExportCsvWorker worker' do
+ expect(IssuableExportCsvWorker).to receive(:perform_async).with(:merge_request, user.id, project.id, anything)
+
+ subject
+ end
+ end
end
diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb
index 8c59b2b378f..d76432f71b3 100644
--- a/spec/controllers/projects/notes_controller_spec.rb
+++ b/spec/controllers/projects/notes_controller_spec.rb
@@ -113,6 +113,8 @@ RSpec.describe Projects::NotesController do
end
it 'returns the first page of notes' do
+ expect(Gitlab::EtagCaching::Middleware).to receive(:skip!)
+
get :index, params: request_params
expect(json_response['notes'].count).to eq(page_1.count)
@@ -122,6 +124,8 @@ RSpec.describe Projects::NotesController do
end
it 'returns the second page of notes' do
+ expect(Gitlab::EtagCaching::Middleware).to receive(:skip!)
+
request.headers['X-Last-Fetched-At'] = page_1_boundary
get :index, params: request_params
@@ -133,6 +137,8 @@ RSpec.describe Projects::NotesController do
end
it 'returns the final page of notes' do
+ expect(Gitlab::EtagCaching::Middleware).to receive(:skip!)
+
request.headers['X-Last-Fetched-At'] = page_2_boundary
get :index, params: request_params
@@ -142,6 +148,19 @@ RSpec.describe Projects::NotesController do
expect(json_response['last_fetched_at']).to eq(microseconds(Time.zone.now))
expect(response.headers['Poll-Interval'].to_i).to be > 1
end
+
+ it 'returns an empty page of notes' do
+ expect(Gitlab::EtagCaching::Middleware).not_to receive(:skip!)
+
+ request.headers['X-Last-Fetched-At'] = microseconds(Time.zone.now)
+
+ get :index, params: request_params
+
+ expect(json_response['notes']).to be_empty
+ expect(json_response['more']).to be_falsy
+ expect(json_response['last_fetched_at']).to eq(microseconds(Time.zone.now))
+ expect(response.headers['Poll-Interval'].to_i).to be > 1
+ end
end
context 'feature flag disabled' do
diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb
index b3921164c81..43cf1a16051 100644
--- a/spec/controllers/projects/raw_controller_spec.rb
+++ b/spec/controllers/projects/raw_controller_spec.rb
@@ -33,11 +33,6 @@ RSpec.describe Projects::RawController do
it_behaves_like 'project cache control headers'
it_behaves_like 'content disposition headers'
- it_behaves_like 'uncached response' do
- before do
- subject
- end
- end
end
context 'image header' do
@@ -225,6 +220,32 @@ RSpec.describe Projects::RawController do
end
end
end
+
+ describe 'caching' do
+ def request_file
+ get(:show, params: { namespace_id: project.namespace, project_id: project, id: 'master/README.md' })
+ end
+
+ it 'sets appropriate caching headers' do
+ sign_in create(:user)
+ request_file
+
+ expect(response.cache_control[:public]).to eq(true)
+ expect(response.cache_control[:max_age]).to eq(60)
+ expect(response.cache_control[:no_store]).to be_nil
+ end
+
+ context 'when If-None-Match header is set' do
+ it 'returns a 304 status' do
+ request_file
+
+ request.headers['If-None-Match'] = response.headers['ETag']
+ request_file
+
+ expect(response).to have_gitlab_http_status(:not_modified)
+ end
+ end
+ end
end
def execute_raw_requests(requests:, project:, file_path:, **params)
diff --git a/spec/controllers/projects/registry/repositories_controller_spec.rb b/spec/controllers/projects/registry/repositories_controller_spec.rb
index 098fa9bac2c..9b803edd463 100644
--- a/spec/controllers/projects/registry/repositories_controller_spec.rb
+++ b/spec/controllers/projects/registry/repositories_controller_spec.rb
@@ -50,18 +50,17 @@ RSpec.describe Projects::Registry::RepositoriesController do
tags: %w[rc1 latest])
end
- it 'successfully renders container repositories' do
- expect(Gitlab::Tracking).not_to receive(:event)
-
+ it 'successfully renders container repositories', :snowplow do
go_to_index
+ expect_no_snowplow_event
expect(response).to have_gitlab_http_status(:ok)
end
- it 'tracks the event' do
- expect(Gitlab::Tracking).to receive(:event).with(anything, 'list_repositories', {})
-
+ it 'tracks the event', :snowplow do
go_to_index(format: :json)
+
+ expect_snowplow_event(category: anything, action: 'list_repositories')
end
it 'creates a root container repository' do
@@ -132,11 +131,12 @@ RSpec.describe Projects::Registry::RepositoriesController do
expect(response).to have_gitlab_http_status(:no_content)
end
- it 'tracks the event' do
- expect(Gitlab::Tracking).to receive(:event).with(anything, 'delete_repository', {})
+ it 'tracks the event', :snowplow do
allow(DeleteContainerRepositoryWorker).to receive(:perform_async).with(user.id, repository.id)
delete_repository(repository)
+
+ expect_snowplow_event(category: anything, action: 'delete_repository')
end
end
end
diff --git a/spec/controllers/projects/registry/tags_controller_spec.rb b/spec/controllers/projects/registry/tags_controller_spec.rb
index 59df9e78a3c..5bff89b4308 100644
--- a/spec/controllers/projects/registry/tags_controller_spec.rb
+++ b/spec/controllers/projects/registry/tags_controller_spec.rb
@@ -39,10 +39,10 @@ RSpec.describe Projects::Registry::TagsController do
expect(response).to include_pagination_headers
end
- it 'tracks the event' do
- expect(Gitlab::Tracking).to receive(:event).with(anything, 'list_tags', {})
-
+ it 'tracks the event', :snowplow do
get_tags
+
+ expect_snowplow_event(category: anything, action: 'list_tags')
end
end
@@ -109,7 +109,7 @@ RSpec.describe Projects::Registry::TagsController do
it 'tracks the event' do
expect_delete_tags(%w[test.])
- expect(controller).to receive(:track_event).with(:delete_tag, {})
+ expect(controller).to receive(:track_event).with(:delete_tag)
destroy_tag('test.')
end
@@ -148,11 +148,11 @@ RSpec.describe Projects::Registry::TagsController do
bulk_destroy_tags(tags)
end
- it 'tracks the event' do
+ it 'tracks the event', :snowplow do
expect_delete_tags(tags)
- expect(Gitlab::Tracking).to receive(:event).with(anything, 'delete_tag_bulk', {})
-
bulk_destroy_tags(tags)
+
+ expect_snowplow_event(category: anything, action: 'delete_tag_bulk')
end
end
end
diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb
index 420d818daeb..07fb03b39c6 100644
--- a/spec/controllers/projects/releases_controller_spec.rb
+++ b/spec/controllers/projects/releases_controller_spec.rb
@@ -201,102 +201,7 @@ RSpec.describe Projects::ReleasesController do
end
end
- context 'GET #downloads' do
- subject do
- get :downloads, params: { namespace_id: project.namespace, project_id: project, tag: tag, filepath: filepath }
- end
-
- before do
- sign_in(user)
- end
-
- let(:release) { create(:release, project: project, tag: tag ) }
- let!(:link) { create(:release_link, release: release, name: 'linux-amd64 binaries', filepath: '/binaries/linux-amd64', url: 'https://downloads.example.com/bin/gitlab-linux-amd64') }
- let(:tag) { 'v11.9.0-rc2' }
-
- context 'valid filepath' do
- let(:filepath) { CGI.escape('/binaries/linux-amd64') }
-
- it 'redirects to the asset direct link' do
- subject
-
- expect(response).to redirect_to('https://downloads.example.com/bin/gitlab-linux-amd64')
- end
-
- it 'redirects with a status of 302' do
- subject
-
- expect(response).to have_gitlab_http_status(:redirect)
- end
- end
-
- context 'invalid filepath' do
- let(:filepath) { CGI.escape('/binaries/win32') }
-
- it 'is not found' do
- subject
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- context 'GET #downloads' do
- subject do
- get :downloads, params: {
- namespace_id: project.namespace,
- project_id: project,
- tag: tag,
- filepath: filepath
- }
- end
-
- before do
- sign_in(user)
- end
-
- let(:release) { create(:release, project: project, tag: tag ) }
- let(:tag) { 'v11.9.0-rc2' }
- let(:db_filepath) { '/binaries/linux-amd64' }
- let!(:link) do
- create :release_link,
- release: release,
- name: 'linux-amd64 binaries',
- filepath: db_filepath,
- url: 'https://downloads.example.com/bin/gitlab-linux-amd64'
- end
-
- context 'valid filepath' do
- let(:filepath) { CGI.escape('/binaries/linux-amd64') }
-
- it 'redirects to the asset direct link' do
- subject
-
- expect(response).to redirect_to(link.url)
- end
- end
-
- context 'invalid filepath' do
- let(:filepath) { CGI.escape('/binaries/win32') }
-
- it 'is not found' do
- subject
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'ignores filepath extension' do
- let(:db_filepath) { '/binaries/linux-amd64.json' }
- let(:filepath) { CGI.escape(db_filepath) }
-
- it 'redirects to the asset direct link' do
- subject
-
- expect(response).to redirect_to(link.url)
- end
- end
- end
+ # `GET #downloads` is addressed in spec/requests/projects/releases_controller_spec.rb
private
diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb
index 97eea7c7e9d..e7f4a8a1422 100644
--- a/spec/controllers/projects/repositories_controller_spec.rb
+++ b/spec/controllers/projects/repositories_controller_spec.rb
@@ -122,7 +122,9 @@ RSpec.describe Projects::RepositoriesController do
expect(response).to have_gitlab_http_status(:ok)
expect(response.header['ETag']).to be_present
- expect(response.header['Cache-Control']).to include('max-age=60, private')
+ expect(response.cache_control[:public]).to eq(false)
+ expect(response.cache_control[:max_age]).to eq(60)
+ expect(response.cache_control[:no_store]).to be_nil
end
context 'when project is public' do
diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb
index 9fc9da1265e..46f69eaf96a 100644
--- a/spec/controllers/projects/settings/operations_controller_spec.rb
+++ b/spec/controllers/projects/settings/operations_controller_spec.rb
@@ -166,23 +166,22 @@ RSpec.describe Projects::Settings::OperationsController do
context 'updating each incident management setting' do
let(:new_incident_management_settings) { {} }
- shared_examples 'a gitlab tracking event' do |params, event_key|
- it "creates a gitlab tracking event #{event_key}" do
+ shared_examples 'a gitlab tracking event' do |params, event_key, **args|
+ it "creates a gitlab tracking event #{event_key}", :snowplow do
new_incident_management_settings = params
- expect(Gitlab::Tracking).to receive(:event)
- .with('IncidentManagement::Settings', event_key, any_args)
-
patch :update, params: project_params(project, incident_management_setting_attributes: new_incident_management_settings)
project.reload
+
+ expect_snowplow_event(category: 'IncidentManagement::Settings', action: event_key, **args)
end
end
it_behaves_like 'a gitlab tracking event', { create_issue: '1' }, 'enabled_issue_auto_creation_on_alerts'
it_behaves_like 'a gitlab tracking event', { create_issue: '0' }, 'disabled_issue_auto_creation_on_alerts'
- it_behaves_like 'a gitlab tracking event', { issue_template_key: 'template' }, 'enabled_issue_template_on_alerts'
- it_behaves_like 'a gitlab tracking event', { issue_template_key: nil }, 'disabled_issue_template_on_alerts'
+ it_behaves_like 'a gitlab tracking event', { issue_template_key: 'template' }, 'enabled_issue_template_on_alerts', label: "Template name", property: "template"
+ it_behaves_like 'a gitlab tracking event', { issue_template_key: nil }, 'disabled_issue_template_on_alerts', label: "Template name", property: ""
it_behaves_like 'a gitlab tracking event', { send_email: '1' }, 'enabled_sending_emails'
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'
diff --git a/spec/controllers/projects/settings/repository_controller_spec.rb b/spec/controllers/projects/settings/repository_controller_spec.rb
index d93f23ae142..394f1ff28f2 100644
--- a/spec/controllers/projects/settings/repository_controller_spec.rb
+++ b/spec/controllers/projects/settings/repository_controller_spec.rb
@@ -23,13 +23,15 @@ RSpec.describe Projects::Settings::RepositoryController do
describe 'PUT cleanup' do
let(:object_map) { fixture_file_upload('spec/fixtures/bfg_object_map.txt') }
- it 'enqueues a RepositoryCleanupWorker' do
- allow(RepositoryCleanupWorker).to receive(:perform_async)
+ it 'enqueues a project cleanup' do
+ expect(Projects::CleanupService)
+ .to receive(:enqueue)
+ .with(project, user, anything)
+ .and_return(status: :success)
- put :cleanup, params: { namespace_id: project.namespace, project_id: project, project: { object_map: object_map } }
+ put :cleanup, params: { namespace_id: project.namespace, project_id: project, project: { bfg_object_map: object_map } }
expect(response).to redirect_to project_settings_repository_path(project)
- expect(RepositoryCleanupWorker).to have_received(:perform_async).once
end
end
diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb
index 6b394fab14c..f9221c5a4ef 100644
--- a/spec/controllers/projects/snippets_controller_spec.rb
+++ b/spec/controllers/projects/snippets_controller_spec.rb
@@ -180,16 +180,6 @@ RSpec.describe Projects::SnippetsController do
end
end
- describe 'GET #show as JSON' do
- it 'renders the blob from the repository' do
- project_snippet = create(:project_snippet, :public, :repository, project: project, author: user)
-
- get :show, params: { namespace_id: project.namespace, project_id: project, id: project_snippet.to_param }, format: :json
-
- expect(assigns(:blob)).to eq(project_snippet.blobs.first)
- end
- end
-
describe "GET #show for embeddable content" do
let(:project_snippet) { create(:project_snippet, :repository, snippet_permission, project: project, author: user) }
let(:extra_params) { {} }
diff --git a/spec/controllers/projects/static_site_editor_controller_spec.rb b/spec/controllers/projects/static_site_editor_controller_spec.rb
index 6ea730cbf27..867b2b51039 100644
--- a/spec/controllers/projects/static_site_editor_controller_spec.rb
+++ b/spec/controllers/projects/static_site_editor_controller_spec.rb
@@ -105,7 +105,8 @@ RSpec.describe Projects::StaticSiteEditorController do
foo: 'bar'
}
},
- a_boolean: true
+ a_boolean: true,
+ a_nil: nil
}
end
@@ -130,6 +131,10 @@ RSpec.describe Projects::StaticSiteEditorController do
it 'serializes data values which are hashes to JSON' do
expect(assigns_data[:a_hash]).to eq('{"a_deeper_hash":{"foo":"bar"}}')
end
+
+ it 'serializes data values which are nil to an empty string' do
+ expect(assigns_data[:a_nil]).to eq('')
+ end
end
end
end
diff --git a/spec/controllers/projects/tags_controller_spec.rb b/spec/controllers/projects/tags_controller_spec.rb
index 57760088183..efb57494f82 100644
--- a/spec/controllers/projects/tags_controller_spec.rb
+++ b/spec/controllers/projects/tags_controller_spec.rb
@@ -9,18 +9,75 @@ RSpec.describe Projects::TagsController do
let(:user) { create(:user) }
describe 'GET index' do
- before do
- get :index, params: { namespace_id: project.namespace.to_param, project_id: project }
- end
+ subject { get :index, params: { namespace_id: project.namespace.to_param, project_id: project } }
it 'returns the tags for the page' do
+ subject
+
expect(assigns(:tags).map(&:name)).to include('v1.1.0', 'v1.0.0')
end
it 'returns releases matching those tags' do
+ subject
+
expect(assigns(:releases)).to include(release)
expect(assigns(:releases)).not_to include(invalid_release)
end
+
+ context '@tag_pipeline_status' do
+ context 'when no pipelines exist' do
+ it 'is empty' do
+ subject
+
+ expect(assigns(:tag_pipeline_statuses)).to be_empty
+ end
+ end
+
+ context 'when multiple tags exist' do
+ before do
+ create(:ci_pipeline,
+ project: project,
+ ref: 'v1.1.0',
+ sha: project.commit('v1.1.0').sha,
+ status: :running)
+ create(:ci_pipeline,
+ project: project,
+ ref: 'v1.0.0',
+ sha: project.commit('v1.0.0').sha,
+ status: :success)
+ end
+
+ it 'all relevant commit statuses are received' do
+ subject
+
+ expect(assigns(:tag_pipeline_statuses)['v1.1.0'].group).to eq("running")
+ expect(assigns(:tag_pipeline_statuses)['v1.0.0'].group).to eq("success")
+ end
+ end
+
+ context 'when a tag has multiple pipelines' do
+ before do
+ create(:ci_pipeline,
+ project: project,
+ ref: 'v1.0.0',
+ sha: project.commit('v1.0.0').sha,
+ status: :running,
+ created_at: 6.months.ago)
+ create(:ci_pipeline,
+ project: project,
+ ref: 'v1.0.0',
+ sha: project.commit('v1.0.0').sha,
+ status: :success,
+ created_at: 2.months.ago)
+ end
+
+ it 'chooses the latest to determine status' do
+ subject
+
+ expect(assigns(:tag_pipeline_statuses)['v1.0.0'].group).to eq("success")
+ end
+ end
+ end
end
describe 'GET show' do
@@ -70,7 +127,8 @@ RSpec.describe Projects::TagsController do
end
let(:release_description) { nil }
- let(:request) do
+
+ subject(:request) do
post(:create, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -81,7 +139,7 @@ RSpec.describe Projects::TagsController do
end
it 'creates tag' do
- request
+ subject
expect(response).to have_gitlab_http_status(:found)
expect(project.repository.find_tag('1.0')).to be_present
@@ -92,7 +150,7 @@ RSpec.describe Projects::TagsController do
let(:release_description) { 'some release description' }
it 'creates tag and release' do
- request
+ subject
expect(response).to have_gitlab_http_status(:found)
expect(project.repository.find_tag('1.0')).to be_present
@@ -118,7 +176,7 @@ RSpec.describe Projects::TagsController do
expect(service).to receive(:execute).and_call_original
end
- request
+ subject
aggregate_failures do
expect(response).to have_gitlab_http_status(:found)
diff --git a/spec/controllers/projects/templates_controller_spec.rb b/spec/controllers/projects/templates_controller_spec.rb
index 40632e0dea7..01593f4133c 100644
--- a/spec/controllers/projects/templates_controller_spec.rb
+++ b/spec/controllers/projects/templates_controller_spec.rb
@@ -5,35 +5,84 @@ require 'spec_helper'
RSpec.describe Projects::TemplatesController do
let(:project) { create(:project, :repository, :private) }
let(:user) { create(:user) }
- let(:file_path_1) { '.gitlab/issue_templates/issue_template.md' }
- let(:file_path_2) { '.gitlab/merge_request_templates/merge_request_template.md' }
- let!(:file_1) { project.repository.create_file(user, file_path_1, 'issue content', message: 'message', branch_name: 'master') }
- let!(:file_2) { project.repository.create_file(user, file_path_2, 'merge request content', message: 'message', branch_name: 'master') }
+ let(:issue_template_path_1) { '.gitlab/issue_templates/issue_template_1.md' }
+ let(:issue_template_path_2) { '.gitlab/issue_templates/issue_template_2.md' }
+ let(:merge_request_template_path_1) { '.gitlab/merge_request_templates/merge_request_template_1.md' }
+ let(:merge_request_template_path_2) { '.gitlab/merge_request_templates/merge_request_template_2.md' }
+ let!(:issue_template_file_1) { project.repository.create_file(user, issue_template_path_1, 'issue content 1', message: 'message 1', branch_name: 'master') }
+ let!(:issue_template_file_2) { project.repository.create_file(user, issue_template_path_2, 'issue content 2', message: 'message 2', branch_name: 'master') }
+ let!(:merge_request_template_file_1) { project.repository.create_file(user, merge_request_template_path_1, 'merge request content 1', message: 'message 1', branch_name: 'master') }
+ let!(:merge_request_template_file_2) { project.repository.create_file(user, merge_request_template_path_2, 'merge request content 2', message: 'message 2', branch_name: 'master') }
+ let(:expected_issue_template_1) { { 'key' => 'issue_template_1', 'name' => 'issue_template_1', 'content' => 'issue content 1' } }
+ let(:expected_issue_template_2) { { 'key' => 'issue_template_2', 'name' => 'issue_template_2', 'content' => 'issue content 2' } }
+ let(:expected_merge_request_template_1) { { 'key' => 'merge_request_template_1', 'name' => 'merge_request_template_1', 'content' => 'merge request content 1' } }
+ let(:expected_merge_request_template_2) { { 'key' => 'merge_request_template_2', 'name' => 'merge_request_template_2', 'content' => 'merge request content 2' } }
+
+ describe '#index' do
+ before do
+ project.add_developer(user)
+ sign_in(user)
+ end
+
+ shared_examples 'templates request' do
+ it 'returns the templates' do
+ get(:index, params: { namespace_id: project.namespace, template_type: template_type, project_id: project }, format: :json)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to match(expected_templates)
+ end
+
+ it 'fails for user with no access' do
+ other_user = create(:user)
+ sign_in(other_user)
+
+ get(:index, params: { namespace_id: project.namespace, template_type: template_type, project_id: project }, format: :json)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when querying for issue templates' do
+ it_behaves_like 'templates request' do
+ let(:template_type) { 'issue' }
+ let(:expected_templates) { [expected_issue_template_1, expected_issue_template_2] }
+ end
+ end
+
+ context 'when querying for merge_request templates' do
+ it_behaves_like 'templates request' do
+ let(:template_type) { 'merge_request' }
+ let(:expected_templates) { [expected_merge_request_template_1, expected_merge_request_template_2] }
+ end
+ end
+ end
describe '#show' do
shared_examples 'renders issue templates as json' do
+ let(:expected_issue_template) { expected_issue_template_2 }
+
it do
- get(:show, params: { namespace_id: project.namespace, template_type: 'issue', key: 'issue_template', project_id: project }, format: :json)
+ get(:show, params: { namespace_id: project.namespace, template_type: 'issue', key: 'issue_template_2', project_id: project }, format: :json)
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['name']).to eq('issue_template')
- expect(json_response['content']).to eq('issue content')
+ expect(json_response).to match(expected_issue_template)
end
end
shared_examples 'renders merge request templates as json' do
+ let(:expected_merge_request_template) { expected_merge_request_template_2 }
+
it do
- get(:show, params: { namespace_id: project.namespace, template_type: 'merge_request', key: 'merge_request_template', project_id: project }, format: :json)
+ get(:show, params: { namespace_id: project.namespace, template_type: 'merge_request', key: 'merge_request_template_2', project_id: project }, format: :json)
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['name']).to eq('merge_request_template')
- expect(json_response['content']).to eq('merge request content')
+ expect(json_response).to match(expected_merge_request_template)
end
end
shared_examples 'renders 404 when requesting an issue template' do
it do
- get(:show, params: { namespace_id: project.namespace, template_type: 'issue', key: 'issue_template', project_id: project }, format: :json)
+ get(:show, params: { namespace_id: project.namespace, template_type: 'issue', key: 'issue_template_1', project_id: project }, format: :json)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -41,21 +90,23 @@ RSpec.describe Projects::TemplatesController do
shared_examples 'renders 404 when requesting a merge request template' do
it do
- get(:show, params: { namespace_id: project.namespace, template_type: 'merge_request', key: 'merge_request_template', project_id: project }, format: :json)
+ get(:show, params: { namespace_id: project.namespace, template_type: 'merge_request', key: 'merge_request_template_1', project_id: project }, format: :json)
expect(response).to have_gitlab_http_status(:not_found)
end
end
- shared_examples 'renders 404 when params are invalid' do
+ shared_examples 'raises error when template type is invalid' do
it 'does not route when the template type is invalid' do
expect do
- get(:show, params: { namespace_id: project.namespace, template_type: 'invalid_type', key: 'issue_template', project_id: project }, format: :json)
+ get(:show, params: { namespace_id: project.namespace, template_type: 'invalid_type', key: 'issue_template_1', project_id: project }, format: :json)
end.to raise_error(ActionController::UrlGenerationError)
end
+ end
+ shared_examples 'renders 404 when params are invalid' do
it 'renders 404 when the format type is invalid' do
- get(:show, params: { namespace_id: project.namespace, template_type: 'issue', key: 'issue_template', project_id: project }, format: :html)
+ get(:show, params: { namespace_id: project.namespace, template_type: 'issue', key: 'issue_template_1', project_id: project }, format: :html)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -74,7 +125,6 @@ RSpec.describe Projects::TemplatesController do
include_examples 'renders 404 when requesting an issue template'
include_examples 'renders 404 when requesting a merge request template'
- include_examples 'renders 404 when params are invalid'
end
context 'when user is a member of the project' do
@@ -85,7 +135,11 @@ RSpec.describe Projects::TemplatesController do
include_examples 'renders issue templates as json'
include_examples 'renders merge request templates as json'
- include_examples 'renders 404 when params are invalid'
+
+ context 'when params are invalid' do
+ include_examples 'raises error when template type is invalid'
+ include_examples 'renders 404 when params are invalid'
+ end
end
context 'when user is a guest of the project' do
@@ -96,7 +150,6 @@ RSpec.describe Projects::TemplatesController do
include_examples 'renders issue templates as json'
include_examples 'renders 404 when requesting a merge request template'
- include_examples 'renders 404 when params are invalid'
end
end
@@ -111,8 +164,8 @@ RSpec.describe Projects::TemplatesController do
get(:names, params: { namespace_id: project.namespace, template_type: template_type, project_id: project }, format: :json)
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.size).to eq(1)
- expect(json_response[0]['name']).to eq(expected_template_name)
+ expect(json_response.size).to eq(2)
+ expect(json_response).to match(expected_template_names)
end
it 'fails for user with no access' do
@@ -128,14 +181,14 @@ RSpec.describe Projects::TemplatesController do
context 'when querying for issue templates' do
it_behaves_like 'template names request' do
let(:template_type) { 'issue' }
- let(:expected_template_name) { 'issue_template' }
+ let(:expected_template_names) { [{ 'name' => 'issue_template_1' }, { 'name' => 'issue_template_2' }] }
end
end
context 'when querying for merge_request templates' do
it_behaves_like 'template names request' do
let(:template_type) { 'merge_request' }
- let(:expected_template_name) { 'merge_request_template' }
+ let(:expected_template_names) { [{ 'name' => 'merge_request_template_1' }, { 'name' => 'merge_request_template_2' }] }
end
end
end
diff --git a/spec/controllers/projects/terraform_controller_spec.rb b/spec/controllers/projects/terraform_controller_spec.rb
new file mode 100644
index 00000000000..1978b9494fa
--- /dev/null
+++ b/spec/controllers/projects/terraform_controller_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::TerraformController do
+ let_it_be(:project) { create(:project) }
+
+ describe 'GET index' do
+ subject { get :index, params: { namespace_id: project.namespace, project_id: project } }
+
+ context 'when user is authorized' do
+ let(:user) { project.creator }
+
+ before do
+ sign_in(user)
+ subject
+ end
+
+ it 'renders content' do
+ expect(response).to be_successful
+ end
+ end
+
+ context 'when user is unauthorized' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_guest(user)
+ sign_in(user)
+ subject
+ end
+
+ it 'shows 404' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 0640f9e5724..012a98f433e 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -1437,4 +1437,55 @@ RSpec.describe ProjectsController do
def project_moved_message(redirect_route, project)
"Project '#{redirect_route.path}' was moved to '#{project.full_path}'. Please update any links and bookmarks that may still have the old path."
end
+
+ describe 'GET #unfoldered_environment_names' do
+ it 'shows the environment names of a public project to an anonymous user' do
+ create(:environment, project: public_project, name: 'foo')
+
+ get(
+ :unfoldered_environment_names,
+ params: { namespace_id: public_project.namespace, id: public_project, format: :json }
+ )
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq(%w[foo])
+ end
+
+ it 'does not show environment names of a private project to anonymous users' do
+ create(:environment, project: project, name: 'foo')
+
+ get(
+ :unfoldered_environment_names,
+ params: { namespace_id: project.namespace, id: project, format: :json }
+ )
+
+ expect(response).to redirect_to(new_user_session_path)
+ end
+
+ it 'shows environment names of a private project to a project member' do
+ create(:environment, project: project, name: 'foo')
+ project.add_developer(user)
+ sign_in(user)
+
+ get(
+ :unfoldered_environment_names,
+ params: { namespace_id: project.namespace, id: project, format: :json }
+ )
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq(%w[foo])
+ end
+
+ it 'does not show environment names of a private project to a logged-in non-member' do
+ create(:environment, project: project, name: 'foo')
+ sign_in(user)
+
+ get(
+ :unfoldered_environment_names,
+ params: { namespace_id: project.namespace, id: project, format: :json }
+ )
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
end
diff --git a/spec/controllers/registrations/welcome_controller_spec.rb b/spec/controllers/registrations/welcome_controller_spec.rb
new file mode 100644
index 00000000000..d32c936b8c9
--- /dev/null
+++ b/spec/controllers/registrations/welcome_controller_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Registrations::WelcomeController do
+ let(:user) { create(:user) }
+
+ describe '#welcome' do
+ subject(:show) { get :show }
+
+ context 'without a signed in user' do
+ it { is_expected.to redirect_to new_user_registration_path }
+ end
+
+ context 'when role or setup_for_company is not set' do
+ before do
+ sign_in(user)
+ end
+
+ it { is_expected.to render_template(:show) }
+ end
+
+ context 'when role is required and setup_for_company is not set' do
+ before do
+ user.set_role_required!
+ sign_in(user)
+ end
+
+ it { is_expected.to render_template(:show) }
+ end
+
+ context 'when role and setup_for_company is set' do
+ before do
+ user.update!(setup_for_company: false)
+ sign_in(user)
+ end
+
+ it { is_expected.to redirect_to(dashboard_projects_path)}
+ end
+
+ context 'when role is set and setup_for_company is not set' do
+ before do
+ user.update!(role: :software_developer)
+ sign_in(user)
+ end
+
+ it { is_expected.to render_template(:show) }
+ 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
+ end
+ end
+
+ describe '#update' do
+ subject(:update) do
+ patch :update, params: { user: { role: 'software_developer', setup_for_company: 'false' } }
+ end
+
+ context 'without a signed in user' do
+ it { is_expected.to redirect_to new_user_registration_path }
+ end
+
+ context 'with a signed in user' do
+ before do
+ sign_in(user)
+ end
+
+ it { is_expected.to redirect_to(dashboard_projects_path)}
+ end
+ end
+end
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index 501d8d4a78d..2fb17e56f37 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -7,35 +7,16 @@ RSpec.describe RegistrationsController do
before do
stub_feature_flags(invisible_captcha: false)
+ stub_application_setting(require_admin_approval_after_user_signup: false)
end
describe '#new' do
subject { get :new }
- context 'with the experimental signup flow enabled and the user is part of the experimental group' do
- before do
- stub_experiment(signup_flow: true)
- stub_experiment_for_user(signup_flow: true)
- end
-
- it 'renders new template and sets the resource variable' do
- expect(subject).to render_template(:new)
- expect(response).to have_gitlab_http_status(:ok)
- expect(assigns(:resource)).to be_a(User)
- end
- end
-
- context 'with the experimental signup flow enabled and the user is part of the control group' do
- before do
- stub_experiment(signup_flow: true)
- stub_experiment_for_user(signup_flow: false)
- end
-
- it 'renders new template and sets the resource variable' do
- subject
- expect(response).to have_gitlab_http_status(:found)
- expect(response).to redirect_to(new_user_session_path(anchor: 'register-pane'))
- end
+ it 'renders new template and sets the resource variable' do
+ expect(subject).to render_template(:new)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:resource)).to be_a(User)
end
end
@@ -46,102 +27,86 @@ RSpec.describe RegistrationsController do
subject { post(:create, params: user_params) }
context '`blocked_pending_approval` state' do
- context 'when the feature is enabled' do
+ context 'when the `require_admin_approval_after_user_signup` setting is turned on' do
before do
- stub_feature_flags(admin_approval_for_new_user_signups: true)
+ stub_application_setting(require_admin_approval_after_user_signup: true)
end
- context 'when the `require_admin_approval_after_user_signup` setting is turned on' do
- before do
- stub_application_setting(require_admin_approval_after_user_signup: true)
- end
+ it 'signs up the user in `blocked_pending_approval` state' do
+ subject
+ created_user = User.find_by(email: 'new@user.com')
- it 'signs up the user in `blocked_pending_approval` state' do
- subject
- created_user = User.find_by(email: 'new@user.com')
+ expect(created_user).to be_present
+ expect(created_user.blocked_pending_approval?).to eq(true)
+ end
- expect(created_user).to be_present
- expect(created_user.blocked_pending_approval?).to eq(true)
- end
+ it 'does not log in the user after sign up' do
+ subject
- it 'does not log in the user after sign up' do
- subject
+ expect(controller.current_user).to be_nil
+ end
- expect(controller.current_user).to be_nil
- end
+ it 'shows flash message after signing up' do
+ subject
- it 'shows flash message after signing up' do
- subject
+ expect(response).to redirect_to(new_user_session_path(anchor: 'login-pane'))
+ expect(flash[:notice])
+ .to eq('You have signed up successfully. However, we could not sign you in because your account is awaiting approval from your GitLab administrator.')
+ end
- expect(response).to redirect_to(new_user_session_path(anchor: 'login-pane'))
- expect(flash[:notice])
- .to eq('You have signed up successfully. However, we could not sign you in because your account is awaiting approval from your GitLab administrator.')
+ it 'emails the access request to approvers' do
+ expect_next_instance_of(NotificationService) do |notification|
+ allow(notification).to receive(:new_instance_access_request).with(User.find_by(email: 'new@user.com'))
end
- context 'email confirmation' do
- context 'when `send_user_confirmation_email` is true' do
- before do
- stub_application_setting(send_user_confirmation_email: true)
- end
-
- it 'does not send a confirmation email' do
- expect { subject }
- .not_to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
- end
- end
- end
+ subject
end
- context 'when the `require_admin_approval_after_user_signup` setting is turned off' do
- before do
- stub_application_setting(require_admin_approval_after_user_signup: false)
- end
-
- it 'signs up the user in `active` state' do
- subject
- created_user = User.find_by(email: 'new@user.com')
+ context 'email confirmation' do
+ context 'when `send_user_confirmation_email` is true' do
+ before do
+ stub_application_setting(send_user_confirmation_email: true)
+ end
- expect(created_user).to be_present
- expect(created_user.active?).to eq(true)
+ it 'does not send a confirmation email' do
+ expect { subject }
+ .not_to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
+ end
end
+ end
+ end
- it 'does not show any flash message after signing up' do
- subject
+ context 'when the `require_admin_approval_after_user_signup` setting is turned off' do
+ it 'signs up the user in `active` state' do
+ subject
+ created_user = User.find_by(email: 'new@user.com')
- expect(flash[:notice]).to be_nil
- end
+ expect(created_user).to be_present
+ expect(created_user.active?).to eq(true)
+ end
- context 'email confirmation' do
- context 'when `send_user_confirmation_email` is true' do
- before do
- stub_application_setting(send_user_confirmation_email: true)
- end
+ it 'does not show any flash message after signing up' do
+ subject
- it 'sends a confirmation email' do
- expect { subject }
- .to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
- end
- end
- end
+ expect(flash[:notice]).to be_nil
end
- end
- context 'when the feature is disabled' do
- before do
- stub_feature_flags(admin_approval_for_new_user_signups: false)
- end
+ it 'does not email the approvers' do
+ expect(NotificationService).not_to receive(:new)
- context 'when the `require_admin_approval_after_user_signup` setting is turned on' do
- before do
- stub_application_setting(require_admin_approval_after_user_signup: true)
- end
+ subject
+ end
- it 'signs up the user in `active` state' do
- subject
+ context 'email confirmation' do
+ context 'when `send_user_confirmation_email` is true' do
+ before do
+ stub_application_setting(send_user_confirmation_email: true)
+ end
- created_user = User.find_by(email: 'new@user.com')
- expect(created_user).to be_present
- expect(created_user.active?).to eq(true)
+ it 'sends a confirmation email' do
+ expect { subject }
+ .to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
+ end
end
end
end
@@ -448,45 +413,4 @@ RSpec.describe RegistrationsController do
end
end
end
-
- describe '#welcome' do
- subject { get :welcome }
-
- 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
-
- expect(subject).to render_template(expected_layout)
- 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
- end
- end
-
- describe '#update_registration' do
- subject(:update_registration) do
- patch :update_registration, params: { user: { role: 'software_developer', setup_for_company: 'false' } }
- end
-
- context 'without a signed in user' do
- it { is_expected.to redirect_to new_user_registration_path }
- end
-
- context 'with a signed in user' do
- before do
- sign_in(create(:user))
- end
-
- it { is_expected.to redirect_to(dashboard_projects_path)}
- end
- end
end
diff --git a/spec/controllers/repositories/lfs_storage_controller_spec.rb b/spec/controllers/repositories/lfs_storage_controller_spec.rb
index 0201e73728f..4f9d049cf87 100644
--- a/spec/controllers/repositories/lfs_storage_controller_spec.rb
+++ b/spec/controllers/repositories/lfs_storage_controller_spec.rb
@@ -127,6 +127,41 @@ RSpec.describe Repositories::LfsStorageController do
end
end
+ context 'when existing file has been deleted' do
+ let(:lfs_object) { create(:lfs_object, :with_file) }
+
+ before do
+ FileUtils.rm(lfs_object.file.path)
+ params[:oid] = lfs_object.oid
+ params[:size] = lfs_object.size
+ end
+
+ it 'replaces the file' do
+ expect(Gitlab::AppJsonLogger).to receive(:info).with(message: "LFS file replaced because it did not exist", oid: lfs_object.oid, size: lfs_object.size)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(lfs_object.reload.file).to exist
+ end
+
+ context 'with invalid file' do
+ before do
+ allow_next_instance_of(ActionController::Parameters) do |params|
+ allow(params).to receive(:[]).and_call_original
+ allow(params).to receive(:[]).with(:file).and_return({})
+ end
+ end
+
+ it 'renders LFS forbidden' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ expect(lfs_object.reload.file).not_to exist
+ end
+ end
+ end
+
context 'when file is not stored' do
it 'renders unprocessable entity' do
expect(controller).to receive(:store_file!).and_return(nil)
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index a0cb696828d..afebc6982c1 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -268,12 +268,15 @@ RSpec.describe SearchController do
last_payload = payload
end
- get :show, params: { scope: 'issues', search: 'hello world', group_id: '123', project_id: '456' }
+ get :show, params: { scope: 'issues', search: 'hello world', group_id: '123', project_id: '456', confidential: true, state: true, force_search_results: true }
expect(last_payload[:metadata]['meta.search.group_id']).to eq('123')
expect(last_payload[:metadata]['meta.search.project_id']).to eq('456')
expect(last_payload[:metadata]['meta.search.search']).to eq('hello world')
expect(last_payload[:metadata]['meta.search.scope']).to eq('issues')
+ expect(last_payload[:metadata]['meta.search.force_search_results']).to eq('true')
+ expect(last_payload[:metadata]['meta.search.filters.confidential']).to eq('true')
+ expect(last_payload[:metadata]['meta.search.filters.state']).to eq('true')
end
end
end
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index 75bcc32e6f3..c31ba6fe156 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe SessionsController do
post(:create, params: { user: { login: 'invalid', password: 'invalid' } })
expect(response)
- .to set_flash.now[:alert].to /Invalid Login or password/
+ .to set_flash.now[:alert].to(/Invalid Login or password/)
end
end
@@ -299,7 +299,7 @@ RSpec.describe SessionsController do
context 'when using two-factor authentication via OTP' do
let(:user) { create(:user, :two_factor) }
- def authenticate_2fa(user_params, otp_user_id: user.id)
+ def authenticate_2fa(otp_user_id: user.id, **user_params)
post(:create, params: { user: user_params }, session: { otp_user_id: otp_user_id })
end
@@ -343,11 +343,12 @@ RSpec.describe SessionsController do
it 'favors login over otp_user_id when password is present and does not authenticate the user' do
authenticate_2fa(
- { login: 'random_username', password: user.password },
+ login: 'random_username',
+ password: user.password,
otp_user_id: user.id
)
- expect(response).to set_flash.now[:alert].to /Invalid Login or password/
+ expect(response).to set_flash.now[:alert].to(/Invalid Login or password/)
end
end
@@ -396,7 +397,7 @@ RSpec.describe SessionsController do
it 'warns about invalid OTP code' do
expect(response).to set_flash.now[:alert]
- .to /Invalid two-factor code/
+ .to(/Invalid two-factor code/)
end
end
end
diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb
index 1ccba7f9114..993ab5d1c72 100644
--- a/spec/controllers/snippets_controller_spec.rb
+++ b/spec/controllers/snippets_controller_spec.rb
@@ -205,14 +205,6 @@ RSpec.describe SnippetsController do
end
end
end
-
- context 'when requesting JSON' do
- it 'renders the blob from the repository' do
- get :show, params: { id: public_snippet.to_param }, format: :json
-
- expect(assigns(:blob)).to eq(public_snippet.blobs.first)
- end
- end
end
describe 'POST #mark_as_spam' do
diff --git a/spec/crystalball_env.rb b/spec/crystalball_env.rb
new file mode 100644
index 00000000000..a7748cd6627
--- /dev/null
+++ b/spec/crystalball_env.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module CrystalballEnv
+ EXCLUDED_PREFIXES = %w[vendor/ruby].freeze
+
+ extend self
+
+ def start!
+ return unless ENV['CRYSTALBALL'] && ENV['CI_PIPELINE_SOURCE'] == 'schedule' && ENV['FREQUENCY'] == '2-hourly'
+
+ require 'crystalball'
+ require_relative '../tooling/lib/tooling/crystalball/coverage_lines_execution_detector'
+ require_relative '../tooling/lib/tooling/crystalball/coverage_lines_strategy'
+
+ map_storage_path_base = ENV['CI_JOB_NAME'] || 'crystalball_data'
+ map_storage_path = "crystalball/#{map_storage_path_base.gsub(%r{[/ ]}, '_')}.yml"
+
+ execution_detector = Tooling::Crystalball::CoverageLinesExecutionDetector.new(exclude_prefixes: EXCLUDED_PREFIXES)
+
+ Crystalball::MapGenerator.start! do |config|
+ config.map_storage_path = map_storage_path
+ config.register Tooling::Crystalball::CoverageLinesStrategy.new(execution_detector)
+ end
+ end
+end
diff --git a/spec/db/production/settings_spec.rb b/spec/db/production/settings_spec.rb
index 84f7ae12728..f17720466c0 100644
--- a/spec/db/production/settings_spec.rb
+++ b/spec/db/production/settings_spec.rb
@@ -62,4 +62,11 @@ RSpec.describe 'seed production settings' do
end
end
end
+
+ context 'CI JWT signing key' do
+ it 'writes valid RSA key to the database' do
+ expect { load(settings_file) }.to change { settings.reload.ci_jwt_signing_key }.from(nil)
+ expect { OpenSSL::PKey::RSA.new(settings.ci_jwt_signing_key) }.not_to raise_error
+ end
+ end
end
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index 06fafbddced..c35f3831a58 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -241,25 +241,9 @@ RSpec.describe 'Database schema' do
context 'primary keys' do
let(:exceptions) do
%i(
- analytics_language_trend_repository_languages
- approval_project_rules_protected_branches
- ci_build_trace_sections
- deployment_merge_requests
elasticsearch_indexed_namespaces
elasticsearch_indexed_projects
- issue_assignees
- issues_prometheus_alert_events
- issues_self_managed_prometheus_alert_events
merge_request_context_commit_diff_files
- merge_request_diff_commits
- merge_request_diff_files
- milestone_releases
- project_authorizations
- project_pages_metadata
- push_event_payloads
- repository_languages
- user_interacted_projects
- users_security_dashboard_projects
)
end
diff --git a/spec/factories/alert_management/http_integrations.rb b/spec/factories/alert_management/http_integrations.rb
index 9311cb3e114..2b5864c8587 100644
--- a/spec/factories/alert_management/http_integrations.rb
+++ b/spec/factories/alert_management/http_integrations.rb
@@ -10,5 +10,11 @@ FactoryBot.define do
trait :inactive do
active { false }
end
+
+ trait :legacy do
+ endpoint_identifier { 'legacy' }
+ end
+
+ initialize_with { new(**attributes) }
end
end
diff --git a/spec/factories/alerts_service_data.rb b/spec/factories/alerts_service_data.rb
new file mode 100644
index 00000000000..2dd1d0a714e
--- /dev/null
+++ b/spec/factories/alerts_service_data.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :alerts_service_data do
+ service { association(:alerts_service) }
+ token { SecureRandom.hex }
+ end
+end
diff --git a/spec/factories/analytics/devops_adoption/segment_selections.rb b/spec/factories/analytics/devops_adoption/segment_selections.rb
new file mode 100644
index 00000000000..8f10369ba35
--- /dev/null
+++ b/spec/factories/analytics/devops_adoption/segment_selections.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :devops_adoption_segment_selection, class: 'Analytics::DevopsAdoption::SegmentSelection' do
+ association :segment, factory: :devops_adoption_segment
+ project
+
+ trait :project do
+ group { nil }
+ project
+ end
+
+ trait :group do
+ project { nil }
+ group
+ end
+ end
+end
diff --git a/spec/factories/analytics/devops_adoption/segments.rb b/spec/factories/analytics/devops_adoption/segments.rb
new file mode 100644
index 00000000000..367ee01fa18
--- /dev/null
+++ b/spec/factories/analytics/devops_adoption/segments.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :devops_adoption_segment, class: 'Analytics::DevopsAdoption::Segment' do
+ sequence(:name) { |n| "Segment #{n}" }
+ end
+end
diff --git a/spec/factories/instance_statistics/measurement.rb b/spec/factories/analytics/instance_statistics/measurement.rb
index f9398cd3061..f9398cd3061 100644
--- a/spec/factories/instance_statistics/measurement.rb
+++ b/spec/factories/analytics/instance_statistics/measurement.rb
diff --git a/spec/factories/audit_events.rb b/spec/factories/audit_events.rb
index 5497648273c..4e72976a9e5 100644
--- a/spec/factories/audit_events.rb
+++ b/spec/factories/audit_events.rb
@@ -4,7 +4,7 @@ FactoryBot.define do
factory :audit_event, class: 'AuditEvent', aliases: [:user_audit_event] do
user
- transient { target_user { create(:user) } }
+ transient { target_user { association(:user) } }
entity_type { 'User' }
entity_id { target_user.id }
@@ -27,7 +27,7 @@ FactoryBot.define do
end
trait :project_event do
- transient { target_project { create(:project) } }
+ transient { target_project { association(:project) } }
entity_type { 'Project' }
entity_id { target_project.id }
@@ -50,7 +50,7 @@ FactoryBot.define do
end
trait :group_event do
- transient { target_group { create(:group) } }
+ transient { target_group { association(:group) } }
entity_type { 'Group' }
entity_id { target_group.id }
diff --git a/spec/factories/bulk_import.rb b/spec/factories/bulk_import.rb
index 0231fe7cfef..07907bab3df 100644
--- a/spec/factories/bulk_import.rb
+++ b/spec/factories/bulk_import.rb
@@ -4,5 +4,21 @@ FactoryBot.define do
factory :bulk_import, class: 'BulkImport' do
user
source_type { :gitlab }
+
+ trait :created do
+ status { 0 }
+ end
+
+ trait :started do
+ status { 1 }
+ end
+
+ trait :finished do
+ status { 2 }
+ end
+
+ trait :failed do
+ status { -1 }
+ end
end
end
diff --git a/spec/factories/bulk_import/entities.rb b/spec/factories/bulk_import/entities.rb
index 3bf6af92d00..cf31ffec4f6 100644
--- a/spec/factories/bulk_import/entities.rb
+++ b/spec/factories/bulk_import/entities.rb
@@ -17,5 +17,25 @@ FactoryBot.define do
trait(:project_entity) do
source_type { :project_entity }
end
+
+ trait :created do
+ status { 0 }
+ end
+
+ trait :started do
+ status { 1 }
+
+ sequence(:jid) { |n| "bulk_import_entity_#{n}" }
+ end
+
+ trait :finished do
+ status { 2 }
+
+ sequence(:jid) { |n| "bulk_import_entity_#{n}" }
+ end
+
+ trait :failed do
+ status { -1 }
+ end
end
end
diff --git a/spec/factories/bulk_import/trackers.rb b/spec/factories/bulk_import/trackers.rb
new file mode 100644
index 00000000000..7a1fa0849fc
--- /dev/null
+++ b/spec/factories/bulk_import/trackers.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :bulk_import_tracker, class: 'BulkImports::Tracker' do
+ association :entity, factory: :bulk_import_entity
+
+ relation { :relation }
+ has_next_page { false }
+ end
+end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index 73920b76025..11719e40cf2 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -332,6 +332,18 @@ FactoryBot.define do
end
end
+ trait :test_reports_with_duplicate_failed_test_names do
+ after(:build) do |build|
+ build.job_artifacts << create(:ci_job_artifact, :junit_with_duplicate_failed_test_names, job: build)
+ end
+ end
+
+ trait :test_reports_with_three_failures do
+ after(:build) do |build|
+ build.job_artifacts << create(:ci_job_artifact, :junit_with_three_failures, job: build)
+ end
+ end
+
trait :accessibility_reports do
after(:build) do |build|
build.job_artifacts << create(:ci_job_artifact, :accessibility, job: build)
@@ -492,10 +504,21 @@ FactoryBot.define do
failure_reason { 10 }
end
+ trait :forward_deployment_failure do
+ failed
+ failure_reason { 13 }
+ end
+
trait :with_runner_session do
after(:build) do |build|
build.build_runner_session(url: 'https://localhost')
end
end
+
+ trait :interruptible do
+ after(:build) do |build|
+ build.metadata.interruptible = true
+ end
+ end
end
end
diff --git a/spec/factories/ci/daily_build_group_report_results.rb b/spec/factories/ci/daily_build_group_report_results.rb
index 8653316b51a..d836ee9567c 100644
--- a/spec/factories/ci/daily_build_group_report_results.rb
+++ b/spec/factories/ci/daily_build_group_report_results.rb
@@ -3,12 +3,18 @@
FactoryBot.define do
factory :ci_daily_build_group_report_result, class: 'Ci::DailyBuildGroupReportResult' do
ref_path { Gitlab::Git::BRANCH_REF_PREFIX + 'master' }
- date { Time.zone.now.to_date }
+ date { Date.current }
project
last_pipeline factory: :ci_pipeline
group_name { 'rspec' }
data do
{ 'coverage' => 77.0 }
end
+ default_branch { true }
+
+ trait :on_feature_branch do
+ ref_path { Gitlab::Git::BRANCH_REF_PREFIX + 'feature' }
+ default_branch { false }
+ end
end
end
diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb
index 1bd4b2826c4..223184891b7 100644
--- a/spec/factories/ci/job_artifacts.rb
+++ b/spec/factories/ci/job_artifacts.rb
@@ -109,6 +109,16 @@ FactoryBot.define do
end
end
+ trait :junit_with_duplicate_failed_test_names do
+ file_type { :junit }
+ file_format { :gzip }
+
+ after(:build) do |artifact, evaluator|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/junit/junit_with_duplicate_failed_test_names.xml.gz'), 'application/x-gzip')
+ end
+ end
+
trait :junit_with_ant do
file_type { :junit }
file_format { :gzip }
@@ -139,6 +149,16 @@ FactoryBot.define do
end
end
+ trait :junit_with_three_failures do
+ file_type { :junit }
+ file_format { :gzip }
+
+ after(:build) do |artifact, evaluator|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/junit/junit_with_three_failures.xml.gz'), 'application/x-gzip')
+ end
+ end
+
trait :accessibility do
file_type { :accessibility }
file_format { :raw }
diff --git a/spec/factories/ci/pipelines.rb b/spec/factories/ci/pipelines.rb
index 4fa5dde4eff..14bd0ab1bc6 100644
--- a/spec/factories/ci/pipelines.rb
+++ b/spec/factories/ci/pipelines.rb
@@ -121,6 +121,14 @@ FactoryBot.define do
end
end
+ trait :with_test_reports_with_three_failures do
+ status { :success }
+
+ after(:build) do |pipeline, _evaluator|
+ pipeline.builds << build(:ci_build, :test_reports_with_three_failures, pipeline: pipeline, project: pipeline.project)
+ end
+ end
+
trait :with_accessibility_reports do
status { :success }
diff --git a/spec/factories/ci/reports/test_case.rb b/spec/factories/ci/reports/test_case.rb
new file mode 100644
index 00000000000..0626de9d6dc
--- /dev/null
+++ b/spec/factories/ci/reports/test_case.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :report_test_case, class: 'Gitlab::Ci::Reports::TestCase' do
+ suite_name { "rspec" }
+ name { "test-1" }
+ classname { "trace" }
+ file { "spec/trace_spec.rb" }
+ execution_time { 1.23 }
+ status { Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS }
+ system_output { nil }
+ attachment { nil }
+ association :job, factory: :ci_build
+
+ trait :failed do
+ status { Gitlab::Ci::Reports::TestCase::STATUS_FAILED }
+ system_output { "Failure/Error: is_expected.to eq(300) expected: 300 got: -100" }
+ end
+
+ trait :failed_with_attachment do
+ status { Gitlab::Ci::Reports::TestCase::STATUS_FAILED }
+ attachment { "some/path.png" }
+ end
+
+ skip_create
+
+ initialize_with do
+ new(
+ suite_name: suite_name,
+ name: name,
+ classname: classname,
+ file: file,
+ execution_time: execution_time,
+ status: status,
+ system_output: system_output,
+ attachment: attachment,
+ job: job
+ )
+ end
+ end
+end
diff --git a/spec/factories/ci/test_case.rb b/spec/factories/ci/test_case.rb
index 7f99f0e123e..601a3fae970 100644
--- a/spec/factories/ci/test_case.rb
+++ b/spec/factories/ci/test_case.rb
@@ -1,41 +1,8 @@
# frozen_string_literal: true
FactoryBot.define do
- factory :test_case, class: 'Gitlab::Ci::Reports::TestCase' do
- suite_name { "rspec" }
- name { "test-1" }
- classname { "trace" }
- file { "spec/trace_spec.rb" }
- execution_time { 1.23 }
- status { Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS }
- system_output { nil }
- attachment { nil }
- association :job, factory: :ci_build
-
- trait :failed do
- status { Gitlab::Ci::Reports::TestCase::STATUS_FAILED }
- system_output { "Failure/Error: is_expected.to eq(300) expected: 300 got: -100" }
- end
-
- trait :failed_with_attachment do
- status { Gitlab::Ci::Reports::TestCase::STATUS_FAILED }
- attachment { "some/path.png" }
- end
-
- skip_create
-
- initialize_with do
- new(
- suite_name: suite_name,
- name: name,
- classname: classname,
- file: file,
- execution_time: execution_time,
- status: status,
- system_output: system_output,
- attachment: attachment,
- job: job
- )
- end
+ factory :ci_test_case, class: 'Ci::TestCase' do
+ project
+ key_hash { Digest::SHA256.hexdigest(SecureRandom.hex) }
end
end
diff --git a/spec/factories/ci/test_case_failure.rb b/spec/factories/ci/test_case_failure.rb
new file mode 100644
index 00000000000..11fb002804b
--- /dev/null
+++ b/spec/factories/ci/test_case_failure.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ci_test_case_failure, class: 'Ci::TestCaseFailure' do
+ build factory: :ci_build
+ test_case factory: :ci_test_case
+ failed_at { Time.current }
+ end
+end
diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb
index 46aa640780b..01df5cc677d 100644
--- a/spec/factories/clusters/applications/helm.rb
+++ b/spec/factories/clusters/applications/helm.rb
@@ -5,7 +5,7 @@ FactoryBot.define do
cluster factory: %i(cluster provided_by_gcp)
before(:create) do
- allow(Gitlab::Kubernetes::Helm::Certificate).to receive(:generate_root)
+ allow(Gitlab::Kubernetes::Helm::V2::Certificate).to receive(:generate_root)
.and_return(
double(
key_string: File.read(Rails.root.join('spec/fixtures/clusters/sample_key.key')),
@@ -15,7 +15,7 @@ FactoryBot.define do
end
after(:create) do
- allow(Gitlab::Kubernetes::Helm::Certificate).to receive(:generate_root).and_call_original
+ allow(Gitlab::Kubernetes::Helm::V2::Certificate).to receive(:generate_root).and_call_original
end
trait :not_installable do
diff --git a/spec/factories/container_repositories.rb b/spec/factories/container_repositories.rb
index 4cf1537f64b..86bb129067f 100644
--- a/spec/factories/container_repositories.rb
+++ b/spec/factories/container_repositories.rb
@@ -13,6 +13,26 @@ FactoryBot.define do
name { '' }
end
+ trait :status_delete_scheduled do
+ status { :delete_scheduled }
+ end
+
+ trait :status_delete_failed do
+ status { :delete_failed }
+ end
+
+ trait :cleanup_scheduled do
+ expiration_policy_cleanup_status { :cleanup_scheduled }
+ end
+
+ trait :cleanup_unfinished do
+ expiration_policy_cleanup_status { :cleanup_unfinished }
+ end
+
+ trait :cleanup_ongoing do
+ expiration_policy_cleanup_status { :cleanup_ongoing }
+ end
+
after(:build) do |repository, evaluator|
next if evaluator.tags.to_a.none?
diff --git a/spec/factories/custom_emoji.rb b/spec/factories/custom_emoji.rb
index 2d185794ac9..ba1ae11c18d 100644
--- a/spec/factories/custom_emoji.rb
+++ b/spec/factories/custom_emoji.rb
@@ -4,6 +4,7 @@ FactoryBot.define do
factory :custom_emoji, class: 'CustomEmoji' do
sequence(:name) { |n| "custom_emoji#{n}" }
namespace
- file { fixture_file_upload(Rails.root.join('spec/fixtures/dk.png')) }
+ group
+ file { 'https://gitlab.com/images/partyparrot.png' }
end
end
diff --git a/spec/factories/dependency_proxy.rb b/spec/factories/dependency_proxy.rb
new file mode 100644
index 00000000000..5d763392a99
--- /dev/null
+++ b/spec/factories/dependency_proxy.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :dependency_proxy_blob, class: 'DependencyProxy::Blob' do
+ group
+ file { fixture_file_upload('spec/fixtures/dependency_proxy/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4.gz') }
+ file_name { 'a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4.gz' }
+ end
+end
diff --git a/spec/factories/design_management/design_at_version.rb b/spec/factories/design_management/design_at_version.rb
index b73df71595c..3d85269ee27 100644
--- a/spec/factories/design_management/design_at_version.rb
+++ b/spec/factories/design_management/design_at_version.rb
@@ -9,13 +9,13 @@ FactoryBot.define do
version { nil }
transient do
- issue { design&.issue || version&.issue || create(:issue) }
+ issue { design&.issue || version&.issue || association(:issue) }
end
initialize_with do
attrs = attributes.dup
- attrs[:design] ||= create(:design, issue: issue)
- attrs[:version] ||= create(:design_version, issue: issue)
+ attrs[:design] ||= association(:design, issue: issue)
+ attrs[:version] ||= association(:design_version, issue: issue)
new(attrs)
end
diff --git a/spec/factories/design_management/designs.rb b/spec/factories/design_management/designs.rb
index 38d0545483c..c4fb330a0da 100644
--- a/spec/factories/design_management/designs.rb
+++ b/spec/factories/design_management/designs.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
FactoryBot.define do
- factory :design, class: 'DesignManagement::Design' do
- issue { create(:issue) }
- project { issue&.project || create(:project) }
+ factory :design, traits: [:has_internal_id], class: 'DesignManagement::Design' do
+ issue { association(:issue) }
+ project { issue&.project || association(:project) }
sequence(:filename) { |n| "homescreen-#{n}.jpg" }
transient do
diff --git a/spec/factories/design_management/versions.rb b/spec/factories/design_management/versions.rb
index a5c0e7076e9..0233a3b567d 100644
--- a/spec/factories/design_management/versions.rb
+++ b/spec/factories/design_management/versions.rb
@@ -3,8 +3,8 @@
FactoryBot.define do
factory :design_version, class: 'DesignManagement::Version' do
sha
- issue { designs.first&.issue || create(:issue) }
- author { issue&.author || create(:user) }
+ issue { designs.first&.issue || association(:issue) }
+ author { issue&.author || association(:user) }
transient do
designs_count { 1 }
diff --git a/spec/factories/import_configurations.rb b/spec/factories/import_configurations.rb
new file mode 100644
index 00000000000..1686d1b0d75
--- /dev/null
+++ b/spec/factories/import_configurations.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :bulk_import_configuration, class: 'BulkImports::Configuration' do
+ association :bulk_import, factory: :bulk_import
+
+ url { 'https://gitlab.example' }
+ access_token { 'token' }
+ end
+end
diff --git a/spec/factories/issues/csv_import.rb b/spec/factories/issues/csv_import.rb
new file mode 100644
index 00000000000..94688cf6232
--- /dev/null
+++ b/spec/factories/issues/csv_import.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :issue_csv_import, class: 'Issues::CsvImport' do
+ project
+ user
+ end
+end
diff --git a/spec/factories/merge_request_cleanup_schedules.rb b/spec/factories/merge_request_cleanup_schedules.rb
new file mode 100644
index 00000000000..a89d0c88731
--- /dev/null
+++ b/spec/factories/merge_request_cleanup_schedules.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :merge_request_cleanup_schedule, class: 'MergeRequest::CleanupSchedule' do
+ merge_request
+ scheduled_at { Time.current }
+ end
+end
diff --git a/spec/factories/packages.rb b/spec/factories/packages.rb
index e2c5b000988..73870a28b89 100644
--- a/spec/factories/packages.rb
+++ b/spec/factories/packages.rb
@@ -129,7 +129,7 @@ FactoryBot.define do
end
trait(:without_loaded_metadatum) do
- conan_metadatum { build(:conan_metadatum, package: nil) }
+ conan_metadatum { build(:conan_metadatum, package: nil) } # rubocop:disable FactoryBot/InlineAssociation
end
end
@@ -141,16 +141,12 @@ FactoryBot.define do
end
factory :composer_metadatum, class: 'Packages::Composer::Metadatum' do
- package { create(:composer_package) }
+ package { association(:composer_package) }
target_sha { '123' }
composer_json { { name: 'foo' } }
end
- factory :package_build_info, class: 'Packages::BuildInfo' do
- package
- end
-
factory :maven_metadatum, class: 'Packages::Maven::Metadatum' do
association :package, package_type: :maven
path { 'my/company/app/my-app/1.0-SNAPSHOT' }
@@ -166,12 +162,12 @@ FactoryBot.define do
end
factory :pypi_metadatum, class: 'Packages::Pypi::Metadatum' do
- package { create(:pypi_package, without_loaded_metadatum: true) }
+ package { association(:pypi_package, without_loaded_metadatum: true) }
required_python { '>=2.7' }
end
factory :nuget_metadatum, class: 'Packages::Nuget::Metadatum' do
- package { create(:nuget_package) }
+ package { association(:nuget_package) }
license_url { 'http://www.gitlab.com' }
project_url { 'http://www.gitlab.com' }
@@ -179,7 +175,7 @@ FactoryBot.define do
end
factory :conan_file_metadatum, class: 'Packages::Conan::FileMetadatum' do
- package_file { create(:conan_package_file, :conan_recipe_file, without_loaded_metadatum: true) }
+ package_file { association(:conan_package_file, :conan_recipe_file, without_loaded_metadatum: true) }
recipe_revision { '0' }
conan_file_type { 'recipe_file' }
@@ -188,7 +184,7 @@ FactoryBot.define do
end
trait(:package_file) do
- package_file { create(:conan_package_file, :conan_package, without_loaded_metadatum: true) }
+ package_file { association(:conan_package_file, :conan_package, without_loaded_metadatum: true) }
conan_file_type { 'package_file' }
package_revision { '0' }
conan_package_reference { '123456789' }
@@ -201,8 +197,8 @@ FactoryBot.define do
end
factory :packages_dependency_link, class: 'Packages::DependencyLink' do
- package { create(:nuget_package) }
- dependency { create(:packages_dependency) }
+ package { association(:nuget_package) }
+ dependency { association(:packages_dependency) }
dependency_type { :dependencies }
trait(:with_nuget_metadatum) do
@@ -213,7 +209,7 @@ FactoryBot.define do
end
factory :nuget_dependency_link_metadatum, class: 'Packages::Nuget::DependencyLinkMetadatum' do
- dependency_link { create(:packages_dependency_link) }
+ dependency_link { association(:packages_dependency_link) }
target_framework { '.NETStandard2.0' }
end
diff --git a/spec/factories/packages/build_info.rb b/spec/factories/packages/build_info.rb
new file mode 100644
index 00000000000..dc6208d72a9
--- /dev/null
+++ b/spec/factories/packages/build_info.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :package_build_info, class: 'Packages::BuildInfo' do
+ package
+
+ trait :with_pipeline do
+ association :pipeline, factory: [:ci_pipeline, :with_job]
+ end
+ end
+end
diff --git a/spec/factories/packages/package_file.rb b/spec/factories/packages/package_file.rb
index bcca48fb086..643ab8e4f95 100644
--- a/spec/factories/packages/package_file.rb
+++ b/spec/factories/packages/package_file.rb
@@ -15,7 +15,7 @@ FactoryBot.define do
end
factory :conan_package_file do
- package { create(:conan_package, without_package_files: true) }
+ package { association(:conan_package, without_package_files: true) }
transient do
without_loaded_metadatum { false }
diff --git a/spec/factories/packages/package_file_build_infos.rb b/spec/factories/packages/package_file_build_infos.rb
new file mode 100644
index 00000000000..f83c32f4a1a
--- /dev/null
+++ b/spec/factories/packages/package_file_build_infos.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :package_file_build_info, class: 'Packages::PackageFileBuildInfo' do
+ package_file
+
+ trait :with_pipeline do
+ association :pipeline, factory: [:ci_pipeline, :with_job]
+ end
+ end
+end
diff --git a/spec/factories/pages_deployments.rb b/spec/factories/pages_deployments.rb
index f57852a8f94..56aab4fa9f3 100644
--- a/spec/factories/pages_deployments.rb
+++ b/spec/factories/pages_deployments.rb
@@ -5,9 +5,13 @@ FactoryBot.define do
project
after(:build) do |deployment, _evaluator|
- deployment.file = fixture_file_upload(
- Rails.root.join("spec/fixtures/pages.zip")
- )
+ filepath = Rails.root.join("spec/fixtures/pages.zip")
+
+ deployment.file = fixture_file_upload(filepath)
+ deployment.file_sha256 = Digest::SHA256.file(filepath).hexdigest
+ ::Zip::File.open(filepath) do |zip_archive|
+ deployment.file_count = zip_archive.count
+ end
end
end
end
diff --git a/spec/factories/project_hooks.rb b/spec/factories/project_hooks.rb
index 15b240acba4..88c06b3857a 100644
--- a/spec/factories/project_hooks.rb
+++ b/spec/factories/project_hooks.rb
@@ -22,6 +22,8 @@ FactoryBot.define do
pipeline_events { true }
wiki_page_events { true }
deployment_events { true }
+ feature_flag_events { true }
+ releases_events { true }
end
end
end
diff --git a/spec/factories/project_statistics.rb b/spec/factories/project_statistics.rb
index ea003b67db0..ee2ad507c2d 100644
--- a/spec/factories/project_statistics.rb
+++ b/spec/factories/project_statistics.rb
@@ -23,6 +23,7 @@ FactoryBot.define do
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
+ project_statistics.uploads_size = evaluator.size_multiplier * 8
end
end
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 87e4a8e355d..639fff06cec 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -10,8 +10,10 @@ FactoryBot.define do
factory :project, class: 'Project' do
sequence(:name) { |n| "project#{n}" }
path { name.downcase.gsub(/\s/, '_') }
- # Behaves differently to nil due to cache_has_external_issue_tracker
+
+ # Behaves differently to nil due to cache_has_external_* methods.
has_external_issue_tracker { false }
+ has_external_wiki { false }
# Associations
namespace
diff --git a/spec/factories/protected_branches/push_access_levels.rb b/spec/factories/protected_branches/push_access_levels.rb
index fa3a35fe282..b735bcdcc04 100644
--- a/spec/factories/protected_branches/push_access_levels.rb
+++ b/spec/factories/protected_branches/push_access_levels.rb
@@ -3,6 +3,7 @@
FactoryBot.define do
factory :protected_branch_push_access_level, class: 'ProtectedBranch::PushAccessLevel' do
protected_branch
+ deploy_key { nil }
access_level { Gitlab::Access::DEVELOPER }
end
end
diff --git a/spec/factories/resource_label_events.rb b/spec/factories/resource_label_events.rb
index b59da465fc3..35c732fed0f 100644
--- a/spec/factories/resource_label_events.rb
+++ b/spec/factories/resource_label_events.rb
@@ -4,7 +4,7 @@ FactoryBot.define do
factory :resource_label_event do
action { :add }
label
- user { issuable&.author || create(:user) }
+ user { issuable&.author || association(:user) }
after(:build) do |event, evaluator|
event.issue = create(:issue) unless event.issuable
diff --git a/spec/factories/resource_milestone_event.rb b/spec/factories/resource_milestone_event.rb
index 86c54f2be68..a3944e013da 100644
--- a/spec/factories/resource_milestone_event.rb
+++ b/spec/factories/resource_milestone_event.rb
@@ -2,11 +2,11 @@
FactoryBot.define do
factory :resource_milestone_event do
- issue { merge_request.nil? ? create(:issue) : nil }
+ issue { merge_request.nil? ? association(:issue) : nil }
merge_request { nil }
milestone
action { :add }
state { :opened }
- user { issue&.author || merge_request&.author || create(:user) }
+ user { issue&.author || merge_request&.author || association(:user) }
end
end
diff --git a/spec/factories/resource_state_event.rb b/spec/factories/resource_state_event.rb
index e3de462b797..926c6dd8cbc 100644
--- a/spec/factories/resource_state_event.rb
+++ b/spec/factories/resource_state_event.rb
@@ -2,9 +2,9 @@
FactoryBot.define do
factory :resource_state_event do
- issue { merge_request.nil? ? create(:issue) : nil }
+ issue { merge_request.nil? ? association(:issue) : nil }
merge_request { nil }
state { :opened }
- user { issue&.author || merge_request&.author || create(:user) }
+ user { issue&.author || merge_request&.author || association(:user) }
end
end
diff --git a/spec/factories/serverless/domain.rb b/spec/factories/serverless/domain.rb
index 7a6a048fb34..c09af068d19 100644
--- a/spec/factories/serverless/domain.rb
+++ b/spec/factories/serverless/domain.rb
@@ -3,8 +3,8 @@
FactoryBot.define do
factory :serverless_domain, class: '::Serverless::Domain' do
function_name { 'test-function' }
- serverless_domain_cluster { create(:serverless_domain_cluster) }
- environment { create(:environment) }
+ serverless_domain_cluster { association(:serverless_domain_cluster) }
+ environment { association(:environment) }
skip_create
end
diff --git a/spec/factories/serverless/domain_cluster.rb b/spec/factories/serverless/domain_cluster.rb
index 40e0ecad5ad..e8ff6cf42b2 100644
--- a/spec/factories/serverless/domain_cluster.rb
+++ b/spec/factories/serverless/domain_cluster.rb
@@ -2,9 +2,9 @@
FactoryBot.define do
factory :serverless_domain_cluster, class: '::Serverless::DomainCluster' do
- pages_domain { create(:pages_domain) }
- knative { create(:clusters_applications_knative) }
- creator { create(:user) }
+ pages_domain { association(:pages_domain) }
+ knative { association(:clusters_applications_knative) }
+ creator { association(:user) }
certificate do
File.read(Rails.root.join('spec/fixtures/', 'ssl_certificate.pem'))
diff --git a/spec/factories/services.rb b/spec/factories/services.rb
index 13997080817..1935ace8e96 100644
--- a/spec/factories/services.rb
+++ b/spec/factories/services.rb
@@ -56,6 +56,10 @@ FactoryBot.define do
trait :inactive do
active { false }
end
+
+ before(:create) do |service|
+ service.data = build(:alerts_service_data, service: service)
+ end
end
factory :drone_ci_service do
@@ -79,6 +83,8 @@ FactoryBot.define do
jira_issue_transition_id { '56-1' }
issues_enabled { false }
project_key { nil }
+ vulnerabilities_enabled { false }
+ vulnerabilities_issuetype { nil }
end
before(:create) do |service, evaluator|
@@ -86,7 +92,8 @@ FactoryBot.define do
create(:jira_tracker_data, service: service,
url: evaluator.url, api_url: evaluator.api_url, jira_issue_transition_id: evaluator.jira_issue_transition_id,
username: evaluator.username, password: evaluator.password, issues_enabled: evaluator.issues_enabled,
- project_key: evaluator.project_key
+ project_key: evaluator.project_key, vulnerabilities_enabled: evaluator.vulnerabilities_enabled,
+ vulnerabilities_issuetype: evaluator.vulnerabilities_issuetype
)
end
end
@@ -139,6 +146,13 @@ FactoryBot.define do
end
end
+ factory :external_wiki_service do
+ project
+ type { ExternalWikiService }
+ active { true }
+ external_wiki_url { 'http://external-wiki-url.com' }
+ end
+
factory :open_project_service do
project
active { true }
diff --git a/spec/factories/terraform/state.rb b/spec/factories/terraform/state.rb
index d80c1315e28..c54a8aedbc6 100644
--- a/spec/factories/terraform/state.rb
+++ b/spec/factories/terraform/state.rb
@@ -2,7 +2,7 @@
FactoryBot.define do
factory :terraform_state, class: 'Terraform::State' do
- project { create(:project) }
+ project { association(:project) }
sequence(:name) { |n| "state-#{n}" }
@@ -14,12 +14,12 @@ FactoryBot.define do
trait :locked do
sequence(:lock_xid) { |n| "lock-#{n}" }
locked_at { Time.current }
- locked_by_user { create(:user) }
+ locked_by_user { association(:user) }
end
trait :with_version do
after(:create) do |state|
- create(:terraform_state_version, :with_file, terraform_state: state)
+ create(:terraform_state_version, terraform_state: state)
end
end
diff --git a/spec/factories/terraform/state_version.rb b/spec/factories/terraform/state_version.rb
index b45bd01fd3c..c6bd08815cf 100644
--- a/spec/factories/terraform/state_version.rb
+++ b/spec/factories/terraform/state_version.rb
@@ -4,6 +4,7 @@ FactoryBot.define do
factory :terraform_state_version, class: 'Terraform::StateVersion' do
terraform_state factory: :terraform_state
created_by_user factory: :user
+ build { association(:ci_build, project: terraform_state.project) }
sequence(:version)
file { fixture_file_upload('spec/fixtures/terraform/terraform.tfstate', 'application/json') }
diff --git a/spec/factories/uploads.rb b/spec/factories/uploads.rb
index b19af277cc3..85237e2d791 100644
--- a/spec/factories/uploads.rb
+++ b/spec/factories/uploads.rb
@@ -2,7 +2,7 @@
FactoryBot.define do
factory :upload do
- model { create(:project) }
+ model { association(:project) }
size { 100.kilobytes }
uploader { "AvatarUploader" }
mount_point { :avatar }
@@ -20,7 +20,7 @@ FactoryBot.define do
end
trait :personal_snippet_upload do
- model { create(:personal_snippet) }
+ model { association(:personal_snippet) }
path { File.join(secret, filename) }
uploader { "PersonalFileUploader" }
secret { SecureRandom.hex }
@@ -46,7 +46,7 @@ FactoryBot.define do
end
trait :namespace_upload do
- model { create(:group) }
+ model { association(:group) }
path { File.join(secret, filename) }
uploader { "NamespaceFileUploader" }
secret { SecureRandom.hex }
@@ -54,7 +54,7 @@ FactoryBot.define do
end
trait :favicon_upload do
- model { create(:appearance) }
+ model { association(:appearance) }
uploader { "FaviconUploader" }
secret { SecureRandom.hex }
mount_point { :favicon }
@@ -62,13 +62,13 @@ FactoryBot.define do
trait :attachment_upload do
mount_point { :attachment }
- model { create(:note) }
+ model { association(:note) }
uploader { "AttachmentUploader" }
end
trait :design_action_image_v432x230_upload do
mount_point { :image_v432x230 }
- model { create(:design_action) }
+ model { association(:design_action) }
uploader { ::DesignManagement::DesignV432x230Uploader.name }
end
end
diff --git a/spec/factories/usage_data.rb b/spec/factories/usage_data.rb
index adca6eabb0e..87f806a3d74 100644
--- a/spec/factories/usage_data.rb
+++ b/spec/factories/usage_data.rb
@@ -52,6 +52,11 @@ FactoryBot.define do
create(:protected_branch, project: projects[0])
create(:protected_branch, name: 'main', project: projects[0])
+ # Alert Management
+ create(:alert_management_http_integration, project: projects[0], name: 'DataDog')
+ create(:alert_management_http_integration, project: projects[0], name: 'DataCat')
+ create(:alert_management_http_integration, :inactive, project: projects[1], name: 'DataFox')
+
# Tracing
create(:project_tracing_setting, project: projects[0])
diff --git a/spec/factories/users.rb b/spec/factories/users.rb
index 2e5b3be3bf2..1b430009ab5 100644
--- a/spec/factories/users.rb
+++ b/spec/factories/users.rb
@@ -66,7 +66,7 @@ FactoryBot.define do
trait :with_sign_ins do
sign_in_count { 3 }
- current_sign_in_at { Time.now }
+ current_sign_in_at { FFaker::Time.between(10.days.ago, 1.day.ago) }
last_sign_in_at { FFaker::Time.between(10.days.ago, 1.day.ago) }
current_sign_in_ip { '127.0.0.1' }
last_sign_in_ip { '127.0.0.1' }
diff --git a/spec/factories/wiki_pages.rb b/spec/factories/wiki_pages.rb
index 3397277839e..6f912a183e8 100644
--- a/spec/factories/wiki_pages.rb
+++ b/spec/factories/wiki_pages.rb
@@ -39,14 +39,14 @@ FactoryBot.define do
factory :wiki_page_meta, class: 'WikiPage::Meta' do
title { generate(:wiki_page_title) }
- project { create(:project) }
+ project { association(:project) }
trait :for_wiki_page do
transient do
- wiki_page { create(:wiki_page, container: project) }
+ wiki_page { association(:wiki_page, container: project) }
end
- project { @overrides[:wiki_page]&.container || create(:project) }
+ project { @overrides[:wiki_page]&.container || association(:project) }
title { wiki_page.title }
initialize_with do
@@ -58,7 +58,7 @@ FactoryBot.define do
end
factory :wiki_page_slug, class: 'WikiPage::Slug' do
- wiki_page_meta { create(:wiki_page_meta) }
+ wiki_page_meta { association(:wiki_page_meta) }
slug { generate(:sluggified_title) }
canonical { false }
diff --git a/spec/factories/wikis.rb b/spec/factories/wikis.rb
index 86d98bfd756..05f6fb0de58 100644
--- a/spec/factories/wikis.rb
+++ b/spec/factories/wikis.rb
@@ -17,5 +17,9 @@ FactoryBot.define do
container { project }
end
+
+ trait :empty_repo do
+ after(:create, &:create_wiki_repository)
+ end
end
end
diff --git a/spec/fast_spec_helper.rb b/spec/fast_spec_helper.rb
index cbab809cddb..2f0bcd318d9 100644
--- a/spec/fast_spec_helper.rb
+++ b/spec/fast_spec_helper.rb
@@ -1,5 +1,12 @@
# frozen_string_literal: true
+# $" is $LOADED_FEATURES, but RuboCop didn't like it
+if $".include?(File.expand_path('spec_helper.rb', __dir__))
+ # There's no need to load anything here if spec_helper is already loaded
+ # because spec_helper is more extensive than fast_spec_helper
+ return
+end
+
require 'bundler/setup'
ENV['GITLAB_ENV'] = 'test'
diff --git a/spec/features/admin/admin_builds_spec.rb b/spec/features/admin/admin_builds_spec.rb
index 85f0c44ed9c..166fde0f37a 100644
--- a/spec/features/admin/admin_builds_spec.rb
+++ b/spec/features/admin/admin_builds_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Admin Builds' do
context 'All tab' do
context 'when have jobs' do
- it 'shows all jobs' do
+ it 'shows all jobs', :js do
create(:ci_build, pipeline: pipeline, status: :pending)
create(:ci_build, pipeline: pipeline, status: :running)
create(:ci_build, pipeline: pipeline, status: :success)
@@ -24,6 +24,10 @@ RSpec.describe 'Admin Builds' do
expect(page).to have_selector('.row-content-block', text: 'All jobs')
expect(page.all('.build-link').size).to eq(4)
expect(page).to have_button 'Stop all jobs'
+
+ click_button 'Stop all jobs'
+ expect(page).to have_button 'Stop jobs'
+ expect(page).to have_content 'Stop all jobs?'
end
end
diff --git a/spec/features/admin/admin_dev_ops_report_spec.rb b/spec/features/admin/admin_dev_ops_report_spec.rb
index c201011cbea..3b2c9d75870 100644
--- a/spec/features/admin/admin_dev_ops_report_spec.rb
+++ b/spec/features/admin/admin_dev_ops_report_spec.rb
@@ -2,59 +2,65 @@
require 'spec_helper'
-RSpec.describe 'DevOps Report page' do
+RSpec.describe 'DevOps Report page', :js do
before do
sign_in(create(:admin))
end
- it 'has dismissable intro callout', :js do
- visit admin_dev_ops_report_path
+ context 'with devops_adoption feature flag disabled' do
+ before do
+ stub_feature_flags(devops_adoption: false)
+ end
- expect(page).to have_content 'Introducing Your DevOps Report'
+ it 'has dismissable intro callout' do
+ visit admin_dev_ops_report_path
- find('.js-close-callout').click
+ expect(page).to have_content 'Introducing Your DevOps Report'
- expect(page).not_to have_content 'Introducing Your DevOps Report'
- end
+ find('.js-close-callout').click
- context 'when usage ping is disabled' do
- before do
- stub_application_setting(usage_ping_enabled: false)
+ expect(page).not_to have_content 'Introducing Your DevOps Report'
end
- it 'shows empty state', :js do
- visit admin_dev_ops_report_path
+ context 'when usage ping is disabled' do
+ before do
+ stub_application_setting(usage_ping_enabled: false)
+ end
- expect(page).to have_selector(".js-empty-state")
- end
+ it 'shows empty state' do
+ visit admin_dev_ops_report_path
- it 'hides the intro callout' do
- visit admin_dev_ops_report_path
+ expect(page).to have_selector(".js-empty-state")
+ end
- expect(page).not_to have_content 'Introducing Your DevOps Report'
+ it 'hides the intro callout' do
+ visit admin_dev_ops_report_path
+
+ expect(page).not_to have_content 'Introducing Your DevOps Report'
+ end
end
- end
- context 'when there is no data to display' do
- it 'shows empty state' do
- stub_application_setting(usage_ping_enabled: true)
+ 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
+ visit admin_dev_ops_report_path
- expect(page).to have_content('Data is still calculating')
+ expect(page).to have_content('Data is still calculating')
+ end
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)
+ 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
+ visit admin_dev_ops_report_path
- expect(page).to have_content(
- 'Issues created per active user 1.2 You 9.3 Lead 13.3%'
- )
+ expect(page).to have_content(
+ 'Issues created per active user 1.2 You 9.3 Lead 13.3%'
+ )
+ end
end
end
end
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index 653a45a4bb8..96709cf8a12 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Admin Groups' do
include Select2Helper
+ include Spec::Support::Helpers::Features::MembersHelpers
let(:internal) { Gitlab::VisibilityLevel::INTERNAL }
let(:user) { create :user }
@@ -11,8 +12,6 @@ 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
@@ -176,7 +175,7 @@ RSpec.describe 'Admin Groups' do
click_button 'Invite'
- page.within '[data-qa-selector="members_list"]' do
+ page.within members_table do
expect(page).to have_content(current_user.name)
expect(page).to have_content('Developer')
end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 528dfad606e..8929abc7edc 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -132,32 +132,14 @@ RSpec.describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_n
context 'Change Sign-up restrictions' do
context 'Require Admin approval for new signup setting' do
- context 'when feature is enabled' do
- before do
- stub_feature_flags(admin_approval_for_new_user_signups: true)
- end
-
- it 'changes the setting' do
- page.within('.as-signup') do
- check 'Require admin approval for new sign-ups'
- click_button 'Save changes'
- end
-
- expect(current_settings.require_admin_approval_after_user_signup).to be_truthy
- expect(page).to have_content "Application settings saved successfully"
- end
- end
-
- context 'when feature is disabled' do
- before do
- stub_feature_flags(admin_approval_for_new_user_signups: false)
+ it 'changes the setting' do
+ page.within('.as-signup') do
+ check 'Require admin approval for new sign-ups'
+ click_button 'Save changes'
end
- it 'does not show the the setting' do
- page.within('.as-signup') do
- expect(page).not_to have_selector('.application_setting_require_admin_approval_after_user_signup')
- end
- end
+ expect(current_settings.require_admin_approval_after_user_signup).to be_truthy
+ expect(page).to have_content "Application settings saved successfully"
end
end
end
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index e06e2d14f3c..97a30143a59 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -75,26 +75,12 @@ RSpec.describe "Admin::Users" do
end
context '`Pending approval` tab' do
- context 'feature is enabled' do
- before do
- stub_feature_flags(admin_approval_for_new_user_signups: true)
- visit admin_users_path
- end
-
- it 'shows the `Pending approval` tab' do
- expect(page).to have_link('Pending approval', href: admin_users_path(filter: 'blocked_pending_approval'))
- end
+ before do
+ visit admin_users_path
end
- context 'feature is disabled' do
- before do
- stub_feature_flags(admin_approval_for_new_user_signups: false)
- visit admin_users_path
- end
-
- it 'does not show the `Pending approval` tab' do
- expect(page).not_to have_link('Pending approval', href: admin_users_path(filter: 'blocked_pending_approval'))
- end
+ it 'shows the `Pending approval` tab' do
+ expect(page).to have_link('Pending approval', href: admin_users_path(filter: 'blocked_pending_approval'))
end
end
end
@@ -218,6 +204,32 @@ RSpec.describe "Admin::Users" do
expect(page).to have_content(user.email)
end
end
+
+ context 'when blocking a user' do
+ it 'shows confirmation and allows blocking', :js do
+ expect(page).to have_content(user.email)
+
+ find("[data-testid='user-action-button-#{user.id}']").click
+
+ within find("[data-testid='user-action-dropdown-#{user.id}']") do
+ find('li button', text: 'Block').click
+ end
+
+ wait_for_requests
+
+ expect(page).to have_content('Block user')
+ expect(page).to have_content('Blocking user has the following effects')
+ expect(page).to have_content('User will not be able to login')
+ expect(page).to have_content('Owned groups will be left')
+
+ find('.modal-footer button', text: 'Block').click
+
+ wait_for_requests
+
+ expect(page).to have_content('Successfully blocked')
+ expect(page).not_to have_content(user.email)
+ end
+ end
end
describe "GET /admin/users/new" do
@@ -376,6 +388,26 @@ RSpec.describe "Admin::Users" do
end
end
+ context 'when blocking the user' do
+ it 'shows confirmation and allows blocking', :js do
+ visit admin_user_path(user)
+
+ find('button', text: 'Block user').click
+
+ wait_for_requests
+
+ expect(page).to have_content('Block user')
+ expect(page).to have_content('You can always unblock their account, their data will remain intact.')
+
+ find('.modal-footer button', text: 'Block').click
+
+ wait_for_requests
+
+ expect(page).to have_content('Successfully blocked')
+ expect(page).to have_content('This user is blocked')
+ end
+ end
+
describe 'Impersonation' do
let(:another_user) { create(:user) }
diff --git a/spec/features/admin/admin_uses_repository_checks_spec.rb b/spec/features/admin/admin_uses_repository_checks_spec.rb
index 44642983a36..0fb5124f673 100644
--- a/spec/features/admin/admin_uses_repository_checks_spec.rb
+++ b/spec/features/admin/admin_uses_repository_checks_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe 'Admin uses repository checks', :request_store, :clean_gitlab_red
)
visit_admin_project_page(project)
- page.within('.gl-alert') do
+ page.within('[data-testid="last-repository-check-failed-alert"]') do
expect(page.text).to match(/Last repository check \(just now\) failed/)
end
end
diff --git a/spec/features/alert_management_spec.rb b/spec/features/alert_management_spec.rb
index 2989f72e356..3322c9c574f 100644
--- a/spec/features/alert_management_spec.rb
+++ b/spec/features/alert_management_spec.rb
@@ -41,21 +41,6 @@ RSpec.describe 'Alert management', :js do
expect(page).to have_content(environment.name)
end
end
-
- context 'when expose_environment_path_in_alert_details feature flag is disabled' do
- before do
- stub_feature_flags(expose_environment_path_in_alert_details: false)
- end
-
- it 'does not show the environment name' do
- visit(details_project_alert_management_path(project, alert))
-
- within('.alert-management-details-table') do
- expect(page).to have_content(alert.title)
- expect(page).not_to have_content(environment.name)
- end
- end
- end
end
end
end
diff --git a/spec/features/alerts_settings/user_views_alerts_settings_spec.rb b/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
new file mode 100644
index 00000000000..0ded13ae607
--- /dev/null
+++ b/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Alert integrations settings form', :js do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:developer) { create(:user) }
+
+ before_all do
+ project.add_maintainer(maintainer)
+ project.add_developer(developer)
+ end
+
+ before do
+ sign_in(maintainer)
+ end
+
+ describe 'when viewing alert integrations as a maintainer' do
+ context 'with feature flag enabled' do
+ before do
+ visit project_settings_operations_path(project, anchor: 'js-alert-management-settings')
+ wait_for_requests
+ end
+
+ it 'shows the alerts setting form title' do
+ page.within('#js-alert-management-settings') do
+ expect(find('h3')).to have_content('Alerts')
+ end
+ end
+
+ it 'shows the new alerts setting form' do
+ expect(page).to have_content('1. Select integration type')
+ end
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(http_integrations_list: false)
+
+ visit project_settings_operations_path(project, anchor: 'js-alert-management-settings')
+ wait_for_requests
+ end
+
+ it 'shows the old alerts setting form' do
+ expect(page).to have_content('Webhook URL')
+ end
+ end
+ end
+
+ describe 'when viewing alert integrations as a developer' do
+ before do
+ sign_in(developer)
+
+ visit project_settings_operations_path(project, anchor: 'js-alert-management-settings')
+ wait_for_requests
+ end
+
+ it 'shows the old alerts setting form' do
+ expect(page).not_to have_selector('.incident-management-list')
+ expect(page).not_to have_selector('#js-alert-management-settings')
+ end
+ end
+end
diff --git a/spec/features/boards/add_issues_modal_spec.rb b/spec/features/boards/add_issues_modal_spec.rb
index 00efca5d3a8..f941adca233 100644
--- a/spec/features/boards/add_issues_modal_spec.rb
+++ b/spec/features/boards/add_issues_modal_spec.rb
@@ -87,11 +87,12 @@ RSpec.describe 'Issue Boards add issue modal', :js do
end
end
- it 'shows selected issues' do
+ it 'shows selected issues tab and empty state message' do
page.within('.add-issues-modal') do
click_link 'Selected issues'
expect(page).not_to have_selector('.board-card')
+ expect(page).to have_content("Go back to Open issues and select some issues to add to your board.")
end
end
@@ -147,7 +148,7 @@ RSpec.describe 'Issue Boards add issue modal', :js do
end
end
- context 'selecing issues' do
+ context 'selecting issues' do
it 'selects single issue' do
page.within('.add-issues-modal') do
first('.board-card .board-card-number').click
@@ -206,7 +207,7 @@ RSpec.describe 'Issue Boards add issue modal', :js do
end
end
- it 'selects all that arent already selected' do
+ it "selects all that aren't already selected" do
page.within('.add-issues-modal') do
first('.board-card .board-card-number').click
diff --git a/spec/features/breadcrumbs_schema_markup_spec.rb b/spec/features/breadcrumbs_schema_markup_spec.rb
new file mode 100644
index 00000000000..30d5f40fea8
--- /dev/null
+++ b/spec/features/breadcrumbs_schema_markup_spec.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Breadcrumbs schema markup', :aggregate_failures do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, namespace: user.namespace) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:subgroup) { create(:group, :public, parent: group) }
+ let_it_be(:group_project) { create(:project, :public, namespace: subgroup) }
+
+ it 'generates the breadcrumb schema for user projects' do
+ visit project_url(project)
+
+ item_list = get_schema_content
+
+ expect(item_list.size).to eq 3
+ expect(item_list[0]['name']).to eq project.namespace.name
+ expect(item_list[0]['item']).to eq user_url(project.owner)
+
+ expect(item_list[1]['name']).to eq project.name
+ expect(item_list[1]['item']).to eq project_url(project)
+
+ expect(item_list[2]['name']).to eq 'Details'
+ expect(item_list[2]['item']).to eq project_url(project)
+ end
+
+ it 'generates the breadcrumb schema for group projects' do
+ visit project_url(group_project)
+
+ item_list = get_schema_content
+
+ expect(item_list.size).to eq 4
+ expect(item_list[0]['name']).to eq group.name
+ expect(item_list[0]['item']).to eq group_url(group)
+
+ expect(item_list[1]['name']).to eq subgroup.name
+ expect(item_list[1]['item']).to eq group_url(subgroup)
+
+ expect(item_list[2]['name']).to eq group_project.name
+ expect(item_list[2]['item']).to eq project_url(group_project)
+
+ expect(item_list[3]['name']).to eq 'Details'
+ expect(item_list[3]['item']).to eq project_url(group_project)
+ end
+
+ it 'generates the breadcrumb schema for group' do
+ visit group_url(subgroup)
+
+ item_list = get_schema_content
+
+ expect(item_list.size).to eq 3
+ expect(item_list[0]['name']).to eq group.name
+ expect(item_list[0]['item']).to eq group_url(group)
+
+ expect(item_list[1]['name']).to eq subgroup.name
+ expect(item_list[1]['item']).to eq group_url(subgroup)
+
+ expect(item_list[2]['name']).to eq 'Details'
+ expect(item_list[2]['item']).to eq group_url(subgroup)
+ end
+
+ it 'generates the breadcrumb schema for issues' do
+ visit project_issues_url(project)
+
+ item_list = get_schema_content
+
+ expect(item_list.size).to eq 3
+ expect(item_list[0]['name']).to eq project.namespace.name
+ expect(item_list[0]['item']).to eq user_url(project.owner)
+
+ expect(item_list[1]['name']).to eq project.name
+ expect(item_list[1]['item']).to eq project_url(project)
+
+ expect(item_list[2]['name']).to eq 'Issues'
+ expect(item_list[2]['item']).to eq project_issues_url(project)
+ end
+
+ it 'generates the breadcrumb schema for specific issue' do
+ visit project_issue_url(project, issue)
+
+ item_list = get_schema_content
+
+ expect(item_list.size).to eq 4
+ expect(item_list[0]['name']).to eq project.namespace.name
+ expect(item_list[0]['item']).to eq user_url(project.owner)
+
+ expect(item_list[1]['name']).to eq project.name
+ expect(item_list[1]['item']).to eq project_url(project)
+
+ expect(item_list[2]['name']).to eq 'Issues'
+ expect(item_list[2]['item']).to eq project_issues_url(project)
+
+ expect(item_list[3]['name']).to eq issue.to_reference
+ expect(item_list[3]['item']).to eq project_issue_url(project, issue)
+ end
+
+ def get_schema_content
+ content = find('script[type="application/ld+json"]', visible: false).text(:all)
+
+ expect(content).not_to be_nil
+
+ Gitlab::Json.parse(content)['itemListElement']
+ end
+end
diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb
index 5f58fa420fb..60d485d4558 100644
--- a/spec/features/calendar_spec.rb
+++ b/spec/features/calendar_spec.rb
@@ -42,7 +42,7 @@ RSpec.describe 'Contributions Calendar', :js do
"#{contributions} #{'contribution'.pluralize(contributions)}"
end
- "#{get_cell_color_selector(contributions)}[data-original-title='#{contribution_text}<br />#{date}']"
+ "#{get_cell_color_selector(contributions)}[title='#{contribution_text}<br />#{date}']"
end
def push_code_contribution
diff --git a/spec/features/callouts/registration_enabled_spec.rb b/spec/features/callouts/registration_enabled_spec.rb
new file mode 100644
index 00000000000..4055965273f
--- /dev/null
+++ b/spec/features/callouts/registration_enabled_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Registration enabled callout' do
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:non_admin) { create(:user) }
+
+ context 'when "Sign-up enabled" setting is `true`' do
+ before do
+ stub_application_setting(signup_enabled: true)
+ end
+
+ context 'when an admin is logged in' do
+ before do
+ sign_in(admin)
+ visit root_dashboard_path
+ end
+
+ it 'displays callout' do
+ expect(page).to have_content 'Open registration is enabled on your instance.'
+ expect(page).to have_link 'View setting', href: general_admin_application_settings_path(anchor: 'js-signup-settings')
+ end
+
+ context 'when callout is dismissed', :js do
+ before do
+ find('[data-testid="close-registration-enabled-callout"]').click
+
+ visit root_dashboard_path
+ end
+
+ it 'does not display callout' do
+ expect(page).not_to have_content 'Open registration is enabled on your instance.'
+ end
+ end
+ end
+
+ context 'when a non-admin is logged in' do
+ before do
+ sign_in(non_admin)
+ visit root_dashboard_path
+ end
+
+ it 'does not display callout' do
+ expect(page).not_to have_content 'Open registration is enabled on your instance.'
+ end
+ end
+ end
+end
diff --git a/spec/features/canonical_link_spec.rb b/spec/features/canonical_link_spec.rb
new file mode 100644
index 00000000000..8b64e9a5b9d
--- /dev/null
+++ b/spec/features/canonical_link_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Canonical link' do
+ include Spec::Support::Helpers::Features::CanonicalLinkHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, namespace: user.namespace) }
+ let_it_be(:issue) { create(:issue, project: project) }
+
+ let_it_be(:issue_request) { issue_url(issue) }
+ let_it_be(:project_request) { project_url(project) }
+
+ before do
+ sign_in(user)
+ end
+
+ shared_examples 'shows canonical link' do
+ specify do
+ visit request_url
+
+ expect(page).to have_canonical_link(expected_url)
+ end
+ end
+
+ shared_examples 'does not show canonical link' do
+ specify do
+ visit request_url
+
+ expect(page).not_to have_any_canonical_links
+ end
+ end
+
+ it_behaves_like 'does not show canonical link' do
+ let(:request_url) { issue_request }
+ end
+
+ it_behaves_like 'shows canonical link' do
+ let(:request_url) { issue_request + '/' }
+ let(:expected_url) { issue_request }
+ end
+
+ it_behaves_like 'shows canonical link' do
+ let(:request_url) { project_issues_url(project) + "/?state=opened" }
+ let(:expected_url) { project_issues_url(project, state: 'opened') }
+ end
+
+ it_behaves_like 'does not show canonical link' do
+ let(:request_url) { project_request }
+ end
+
+ it_behaves_like 'shows canonical link' do
+ let(:request_url) { project_request + '/' }
+ let(:expected_url) { project_request }
+ end
+
+ it_behaves_like 'shows canonical link' do
+ let(:query_params) { '?foo=bar' }
+ let(:request_url) { project_request + "/#{query_params}" }
+ let(:expected_url) { project_request + query_params }
+ end
+
+ # Hard-coded canonical links
+
+ it_behaves_like 'shows canonical link' do
+ let(:request_url) { explore_root_path }
+ let(:expected_url) { explore_projects_url }
+ end
+end
diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb
index a3eacd6147c..c14a6001a3e 100644
--- a/spec/features/dashboard/datetime_on_tooltips_spec.rb
+++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb
@@ -49,7 +49,7 @@ RSpec.describe 'Tooltips on .timeago dates', :js do
end
def datetime_in_tooltip
- datetime_text = page.find('.local-timeago').text
+ datetime_text = page.find('.tooltip').text
DateTime.parse(datetime_text)
end
end
diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb
index 04bbc3059de..58352518d43 100644
--- a/spec/features/dashboard/shortcuts_spec.rb
+++ b/spec/features/dashboard/shortcuts_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe 'Dashboard shortcuts', :js do
find('body').send_keys([:shift, 'P'])
find('.nothing-here-block')
- expect(page).to have_content("This user doesn't have any personal projects")
+ expect(page).to have_content('Explore public groups to find projects to contribute to.')
end
end
diff --git a/spec/features/discussion_comments/merge_request_spec.rb b/spec/features/discussion_comments/merge_request_spec.rb
index 43801b30608..761cc7ae796 100644
--- a/spec/features/discussion_comments/merge_request_spec.rb
+++ b/spec/features/discussion_comments/merge_request_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe 'Thread Comments Merge Request', :js do
let(:merge_request) { create(:merge_request, source_project: project) }
before do
+ stub_feature_flags(remove_resolve_note: false)
+
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb
index 49343cc7a57..0912df22924 100644
--- a/spec/features/expand_collapse_diffs_spec.rb
+++ b/spec/features/expand_collapse_diffs_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe 'Expand and collapse diffs', :js do
before do
stub_feature_flags(increased_diff_limits: false)
+ allow(Gitlab::CurrentSettings).to receive(:diff_max_patch_bytes).and_return(100.kilobytes)
+
sign_in(create(:admin))
# Ensure that undiffable.md is in .gitattributes
diff --git a/spec/features/explore/user_explores_projects_spec.rb b/spec/features/explore/user_explores_projects_spec.rb
index e217638f62b..bf4d6c946e1 100644
--- a/spec/features/explore/user_explores_projects_spec.rb
+++ b/spec/features/explore/user_explores_projects_spec.rb
@@ -3,65 +3,112 @@
require 'spec_helper'
RSpec.describe 'User explores projects' do
- let_it_be(:archived_project) { create(:project, :archived) }
- let_it_be(:internal_project) { create(:project, :internal) }
- let_it_be(:private_project) { create(:project, :private) }
- let_it_be(:public_project) { create(:project, :public) }
-
- context 'when not signed in' do
- context 'when viewing public projects' do
- before do
- visit(explore_projects_path)
+ context 'when some projects exist' do
+ let_it_be(:archived_project) { create(:project, :archived) }
+ let_it_be(:internal_project) { create(:project, :internal) }
+ let_it_be(:private_project) { create(:project, :private) }
+ let_it_be(:public_project) { create(:project, :public) }
+
+ context 'when not signed in' do
+ context 'when viewing public projects' do
+ before do
+ visit(explore_projects_path)
+ end
+
+ include_examples 'shows public projects'
end
- include_examples 'shows public projects'
+ context 'when visibility is restricted to public' do
+ before do
+ stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
+ visit(explore_projects_path)
+ end
+
+ it 'redirects to login page' do
+ expect(page).to have_current_path(new_user_session_path)
+ end
+ end
end
- context 'when visibility is restricted to public' do
+ context 'when signed in' do
+ let_it_be(:user) { create(:user) }
+
before do
- stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
- visit(explore_projects_path)
+ sign_in(user)
+
+ stub_feature_flags(project_list_filter_bar: false)
+ end
+
+ shared_examples 'empty search results' do
+ it 'shows correct empty state message', :js do
+ fill_in 'name', with: 'zzzzzzzzzzzzzzzzzzz'
+
+ expect(page).to have_content('Explore public groups to find projects to contribute to.')
+ end
end
- it 'redirects to login page' do
- expect(page).to have_current_path(new_user_session_path)
+ context 'when viewing public projects' do
+ before do
+ visit(explore_projects_path)
+ end
+
+ include_examples 'shows public and internal projects'
+ include_examples 'empty search results'
+ end
+
+ context 'when viewing most starred projects' do
+ before do
+ visit(starred_explore_projects_path)
+ end
+
+ include_examples 'shows public and internal projects'
+ include_examples 'empty search results'
+ end
+
+ context 'when viewing trending projects' do
+ before do
+ [archived_project, public_project].each { |project| create(:note_on_issue, project: project) }
+
+ TrendingProject.refresh!
+
+ visit(trending_explore_projects_path)
+ end
+
+ include_examples 'shows public projects'
+ include_examples 'empty search results'
end
end
end
- context 'when signed in' do
- let_it_be(:user) { create(:user) }
-
- before do
- sign_in(user)
+ context 'when there are no projects' do
+ shared_examples 'explore page empty state' do
+ it 'shows correct empty state message' do
+ expect(page).to have_content('Explore public groups to find projects to contribute to.')
+ end
end
context 'when viewing public projects' do
before do
- visit(explore_projects_path)
+ visit explore_projects_path
end
- include_examples 'shows public and internal projects'
+ it_behaves_like 'explore page empty state'
end
context 'when viewing most starred projects' do
before do
- visit(starred_explore_projects_path)
+ visit starred_explore_projects_path
end
- include_examples 'shows public and internal projects'
+ it_behaves_like 'explore page empty state'
end
context 'when viewing trending projects' do
before do
- [archived_project, public_project].each { |project| create(:note_on_issue, project: project) }
-
- TrendingProject.refresh!
-
- visit(trending_explore_projects_path)
+ visit trending_explore_projects_path
end
- include_examples 'shows public projects'
+ it_behaves_like 'explore page empty state'
end
end
end
diff --git a/spec/features/file_uploads/multipart_invalid_uploads_spec.rb b/spec/features/file_uploads/multipart_invalid_uploads_spec.rb
index e9e24c12af1..b3ace2e30ff 100644
--- a/spec/features/file_uploads/multipart_invalid_uploads_spec.rb
+++ b/spec/features/file_uploads/multipart_invalid_uploads_spec.rb
@@ -22,13 +22,13 @@ RSpec.describe 'Invalid uploads that must be rejected', :api, :js do
)
end
- RSpec.shared_examples 'rejecting invalid keys' do |key_name:, message: nil|
+ RSpec.shared_examples 'rejecting invalid keys' do |key_name:, message: nil, status: 500|
context "with invalid key #{key_name}" do
let(:body) { { key_name => file, 'package[test][name]' => 'test' } }
it { expect { subject }.not_to change { Packages::Package.nuget.count } }
- it { expect(subject.code).to eq(500) }
+ it { expect(subject.code).to eq(status) }
it { expect(subject.body).to include(message.presence || "invalid field: \"#{key_name}\"") }
end
@@ -45,7 +45,7 @@ RSpec.describe 'Invalid uploads that must be rejected', :api, :js do
# These keys are rejected directly by rack itself.
# The request will not be received by multipart.rb (can't use the 'handling file uploads' shared example)
it_behaves_like 'rejecting invalid keys', key_name: 'x' * 11000, message: 'Puma caught this error: exceeded available parameter key space (RangeError)'
- it_behaves_like 'rejecting invalid keys', key_name: 'package[]test', message: 'Puma caught this error: expected Hash (got Array)'
+ it_behaves_like 'rejecting invalid keys', key_name: 'package[]test', status: 400, message: 'Bad Request'
it_behaves_like 'handling file uploads', 'by rejecting uploads with an invalid key'
end
diff --git a/spec/features/frequently_visited_projects_and_groups_spec.rb b/spec/features/frequently_visited_projects_and_groups_spec.rb
new file mode 100644
index 00000000000..b8797d9c139
--- /dev/null
+++ b/spec/features/frequently_visited_projects_and_groups_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Frequently visited items', :js do
+ let_it_be(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ context 'for projects' do
+ let_it_be(:project) { create(:project, :public) }
+
+ it 'increments localStorage counter when visiting the project' do
+ visit project_path(project)
+
+ frequent_projects = nil
+
+ wait_for('localStorage frequent-projects') do
+ frequent_projects = page.evaluate_script("localStorage['#{user.username}/frequent-projects']")
+
+ frequent_projects.present?
+ end
+
+ expect(Gitlab::Json.parse(frequent_projects)).to contain_exactly(a_hash_including('id' => project.id, 'frequency' => 1))
+ end
+ end
+
+ context 'for groups' do
+ let_it_be(:group) { create(:group, :public) }
+
+ it 'increments localStorage counter when visiting the group' do
+ visit group_path(group)
+
+ frequent_groups = nil
+
+ wait_for('localStorage frequent-groups') do
+ frequent_groups = page.evaluate_script("localStorage['#{user.username}/frequent-groups']")
+
+ frequent_groups.present?
+ end
+
+ expect(Gitlab::Json.parse(frequent_groups)).to contain_exactly(a_hash_including('id' => group.id, 'frequency' => 1))
+ end
+ end
+end
diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb
index 0ca626381d4..e6e4a55c1bb 100644
--- a/spec/features/global_search_spec.rb
+++ b/spec/features/global_search_spec.rb
@@ -36,15 +36,15 @@ RSpec.describe 'Global search' do
end
end
- it 'closes the dropdown on blur', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/201841' do
+ it 'closes the dropdown on blur', :js do
+ find('#search').click
fill_in 'search', with: "a"
- dropdown = find('.js-dashboard-search-options')
- expect(dropdown[:class]).to include 'show'
+ expect(page).to have_selector("div[data-testid='dashboard-search-options'].show")
find('#search').send_keys(:backspace)
find('body').click
- expect(dropdown[:class]).not_to include 'show'
+ expect(page).to have_no_selector("div[data-testid='dashboard-search-options'].show")
end
end
diff --git a/spec/features/group_variables_spec.rb b/spec/features/group_variables_spec.rb
index 9a3dca61680..c7d37205b71 100644
--- a/spec/features/group_variables_spec.rb
+++ b/spec/features/group_variables_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Group variables', :js do
before do
group.add_owner(user)
gitlab_sign_in(user)
- stub_feature_flags(new_variables_ui: false)
+ wait_for_requests
visit page_path
end
diff --git a/spec/features/groups/container_registry_spec.rb b/spec/features/groups/container_registry_spec.rb
index acac8724edf..1b23b8b4bf9 100644
--- a/spec/features/groups/container_registry_spec.rb
+++ b/spec/features/groups/container_registry_spec.rb
@@ -89,6 +89,20 @@ RSpec.describe 'Container Registry', :js do
end
end
+ context 'when an image has the same name as the subgroup' do
+ before do
+ stub_container_registry_tags(tags: %w[latest], with_manifest: true)
+ project.container_repositories << create(:container_repository, name: group.name)
+ visit_container_registry
+ end
+
+ it 'details page loads properly' do
+ find('a[data-testid="details-link"]').click
+
+ expect(page).to have_content 'latest'
+ end
+ end
+
def visit_container_registry
visit group_container_registries_path(group)
end
diff --git a/spec/features/groups/dependency_proxy_spec.rb b/spec/features/groups/dependency_proxy_spec.rb
new file mode 100644
index 00000000000..9bbfdc488fb
--- /dev/null
+++ b/spec/features/groups/dependency_proxy_spec.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Group Dependency Proxy' do
+ let(:developer) { create(:user) }
+ let(:reporter) { create(:user) }
+ let(:group) { create(:group) }
+ let(:path) { group_dependency_proxy_path(group) }
+
+ before do
+ group.add_developer(developer)
+ group.add_reporter(reporter)
+
+ enable_feature
+ end
+
+ describe 'feature settings' do
+ context 'when not logged in and feature disabled' do
+ it 'does not show the feature settings' do
+ group.create_dependency_proxy_setting(enabled: false)
+
+ visit path
+
+ expect(page).not_to have_css('.js-dependency-proxy-toggle-area')
+ expect(page).not_to have_css('.js-dependency-proxy-url')
+ end
+ end
+
+ context 'feature is available', :js do
+ context 'when logged in as group developer' do
+ before do
+ sign_in(developer)
+ visit path
+ end
+
+ it 'sidebar menu is open' do
+ sidebar = find('.nav-sidebar')
+ expect(sidebar).to have_link _('Dependency Proxy')
+ end
+
+ it 'toggles defaults to enabled' do
+ page.within('.js-dependency-proxy-toggle-area') do
+ expect(find('.js-project-feature-toggle-input', visible: false).value).to eq('true')
+ end
+ end
+
+ it 'shows the proxy URL' do
+ page.within('.edit_dependency_proxy_group_setting') do
+ expect(find('.js-dependency-proxy-url').value).to have_content('/dependency_proxy/containers')
+ end
+ end
+
+ it 'hides the proxy URL when feature is disabled' do
+ page.within('.edit_dependency_proxy_group_setting') do
+ find('.js-project-feature-toggle').click
+ end
+
+ expect(page).not_to have_css('.js-dependency-proxy-url')
+ expect(find('.js-project-feature-toggle-input', visible: false).value).to eq('false')
+ end
+ end
+
+ context 'when logged in as group reporter' do
+ before do
+ sign_in(reporter)
+ visit path
+ end
+
+ it 'does not show the feature toggle but shows the proxy URL' do
+ expect(page).not_to have_css('.js-dependency-proxy-toggle-area')
+ expect(find('.js-dependency-proxy-url').value).to have_content('/dependency_proxy/containers')
+ end
+ end
+ end
+
+ context 'feature is not avaible' do
+ before do
+ sign_in(developer)
+ end
+
+ context 'group is private' do
+ let(:group) { create(:group, :private) }
+
+ it 'informs user that feature is only available for public groups' do
+ visit path
+
+ expect(page).to have_content('Dependency proxy feature is limited to public groups for now.')
+ end
+ end
+
+ context 'feature is disabled globally' do
+ it 'renders 404 page' do
+ disable_feature
+
+ visit path
+
+ expect(page).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+ end
+
+ def enable_feature
+ stub_config(dependency_proxy: { enabled: true })
+ end
+
+ def disable_feature
+ stub_config(dependency_proxy: { enabled: false })
+ end
+end
diff --git a/spec/features/groups/members/filter_members_spec.rb b/spec/features/groups/members/filter_members_spec.rb
index d667690af29..b6d33b3f4aa 100644
--- a/spec/features/groups/members/filter_members_spec.rb
+++ b/spec/features/groups/members/filter_members_spec.rb
@@ -2,16 +2,19 @@
require 'spec_helper'
-RSpec.describe 'Groups > Members > Filter members' do
+RSpec.describe 'Groups > Members > Filter members', :js do
+ include Spec::Support::Helpers::Features::MembersHelpers
+
let(:user) { create(:user) }
let(:nested_group_user) { create(:user) }
let(:user_with_2fa) { create(:user, :two_factor_via_otp) }
let(:group) { create(:group) }
let(:nested_group) { create(:group, parent: group) }
- before do
- stub_feature_flags(vue_group_members_list: false)
+ two_factor_auth_dropdown_toggle_selector = '[data-testid="member-filter-2fa-dropdown"] [data-testid="dropdown-toggle"]'
+ active_inherited_members_filter_selector = '[data-testid="filter-members-with-inherited-permissions"] a.is-active'
+ before do
group.add_owner(user)
group.add_maintainer(user_with_2fa)
nested_group.add_maintainer(nested_group_user)
@@ -24,23 +27,23 @@ RSpec.describe 'Groups > Members > Filter members' do
expect(member(0)).to include(user.name)
expect(member(1)).to include(user_with_2fa.name)
- expect(page).to have_css('.member-filter-2fa-dropdown .dropdown-toggle-text', text: 'Everyone')
+ expect(page).to have_css(two_factor_auth_dropdown_toggle_selector, text: 'Everyone')
end
it 'shows only 2FA members' do
visit_members_list(group, two_factor: 'enabled')
expect(member(0)).to include(user_with_2fa.name)
- expect(members_list.size).to eq(1)
- expect(page).to have_css('.member-filter-2fa-dropdown .dropdown-toggle-text', text: 'Enabled')
+ expect(all_rows.size).to eq(1)
+ expect(page).to have_css(two_factor_auth_dropdown_toggle_selector, text: 'Enabled')
end
it 'shows only non 2FA members' do
visit_members_list(group, two_factor: 'disabled')
expect(member(0)).to include(user.name)
- expect(members_list.size).to eq(1)
- expect(page).to have_css('.member-filter-2fa-dropdown .dropdown-toggle-text', text: 'Disabled')
+ expect(all_rows.size).to eq(1)
+ expect(page).to have_css(two_factor_auth_dropdown_toggle_selector, text: 'Disabled')
end
it 'shows inherited members by default' do
@@ -49,35 +52,31 @@ RSpec.describe 'Groups > Members > Filter members' do
expect(member(0)).to include(user.name)
expect(member(1)).to include(user_with_2fa.name)
expect(member(2)).to include(nested_group_user.name)
- expect(members_list.size).to eq(3)
+ expect(all_rows.size).to eq(3)
- expect(page).to have_css('[data-qa-selector="filter-members-with-inherited-permissions"] a.is-active', text: 'Show all members')
+ expect(page).to have_css(active_inherited_members_filter_selector, text: 'Show all members', visible: false)
end
it 'shows only group members' do
visit_members_list(nested_group, with_inherited_permissions: 'exclude')
expect(member(0)).to include(nested_group_user.name)
- expect(members_list.size).to eq(1)
- expect(page).to have_css('[data-qa-selector="filter-members-with-inherited-permissions"] a.is-active', text: 'Show only direct members')
+ expect(all_rows.size).to eq(1)
+ expect(page).to have_css(active_inherited_members_filter_selector, text: 'Show only direct members', visible: false)
end
it 'shows only inherited members' do
visit_members_list(nested_group, with_inherited_permissions: 'only')
expect(member(0)).to include(user.name)
expect(member(1)).to include(user_with_2fa.name)
- expect(members_list.size).to eq(2)
- expect(page).to have_css('[data-qa-selector="filter-members-with-inherited-permissions"] a.is-active', text: 'Show only inherited members')
+ expect(all_rows.size).to eq(2)
+ expect(page).to have_css(active_inherited_members_filter_selector, text: 'Show only inherited members', visible: false)
end
def visit_members_list(group, options = {})
visit group_group_members_path(group.to_param, options)
end
- def members_list
- page.all('ul.content-list > li')
- end
-
def member(number)
- members_list[number].text
+ all_rows[number].text
end
end
diff --git a/spec/features/groups/members/leave_group_spec.rb b/spec/features/groups/members/leave_group_spec.rb
index 32acf7edd2a..b73313745e9 100644
--- a/spec/features/groups/members/leave_group_spec.rb
+++ b/spec/features/groups/members/leave_group_spec.rb
@@ -3,14 +3,14 @@
require 'spec_helper'
RSpec.describe 'Groups > Members > Leave group' do
+ include Spec::Support::Helpers::Features::MembersHelpers
+
let(:user) { create(:user) }
let(:other_user) { create(:user) }
let(:group) { create(:group) }
before do
- stub_feature_flags(vue_group_members_list: false)
-
- gitlab_sign_in(user)
+ sign_in(user)
end
it 'guest leaves the group' do
@@ -61,7 +61,7 @@ RSpec.describe 'Groups > Members > Leave group' do
expect(group.users).not_to include(user)
end
- it 'owner can not leave the group if they are the last owner' do
+ it 'owner can not leave the group if they are the last owner', :js do
group.add_owner(user)
visit group_path(group)
@@ -70,7 +70,7 @@ RSpec.describe 'Groups > Members > Leave group' do
visit group_group_members_path(group)
- expect(find(:css, '.project-members-page li', text: user.name)).to have_no_selector(:css, 'a.btn-danger')
+ expect(members_table).not_to have_selector 'button[title="Leave"]'
end
it 'owner can not leave the group by url param if they are the last owner', :js do
diff --git a/spec/features/groups/members/list_members_spec.rb b/spec/features/groups/members/list_members_spec.rb
index bcec2b50a24..b0a896ec8cb 100644
--- a/spec/features/groups/members/list_members_spec.rb
+++ b/spec/features/groups/members/list_members_spec.rb
@@ -2,9 +2,8 @@
require 'spec_helper'
-RSpec.describe 'Groups > Members > List members' do
- include Select2Helper
- include Spec::Support::Helpers::Features::ListRowsHelpers
+RSpec.describe 'Groups > Members > List members', :js do
+ include Spec::Support::Helpers::Features::MembersHelpers
let(:user1) { create(:user, name: 'John Doe') }
let(:user2) { create(:user, name: 'Mary Jane') }
@@ -12,8 +11,6 @@ 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
@@ -42,10 +39,12 @@ RSpec.describe 'Groups > Members > List members' do
group.add_developer(user2)
end
- subject { visit group_group_members_path(group) }
+ it 'shows the status' do
+ create(:user_status, user: user2, emoji: 'smirk', message: 'Authoring this object')
+
+ visit group_group_members_path(nested_group)
- it_behaves_like 'showing user status' do
- let(:user_with_status) { user2 }
+ expect(first_row).to have_selector('gl-emoji[data-name="smirk"]')
end
end
end
diff --git a/spec/features/groups/members/manage_groups_spec.rb b/spec/features/groups/members/manage_groups_spec.rb
index 33caa3af36d..31a2c868cac 100644
--- a/spec/features/groups/members/manage_groups_spec.rb
+++ b/spec/features/groups/members/manage_groups_spec.rb
@@ -4,13 +4,11 @@ require 'spec_helper'
RSpec.describe 'Groups > Members > Manage groups', :js do
include Select2Helper
- include Spec::Support::Helpers::Features::ListRowsHelpers
+ include Spec::Support::Helpers::Features::MembersHelpers
let_it_be(:user) { create(:user) }
before do
- stub_feature_flags(vue_group_members_list: false)
-
sign_in(user)
end
@@ -51,7 +49,6 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
end
before do
- travel_to Time.now.utc.beginning_of_day
group_link.update!(additional_link_attrs)
shared_group.add_owner(user)
@@ -63,8 +60,12 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
expect(page).to have_content(shared_with_group.name)
- accept_confirm do
- find(:css, '#tab-groups li', text: shared_with_group.name).find(:css, 'a.btn-danger').click
+ page.within(first_row) do
+ click_button 'Remove group'
+ end
+
+ page.within('[role="dialog"]') do
+ click_button('Remove group')
end
expect(page).not_to have_content(shared_with_group.name)
@@ -75,7 +76,7 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
page.within(first_row) do
click_button('Developer')
- click_link('Maintainer')
+ click_button('Maintainer')
wait_for_requests
@@ -86,33 +87,30 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
it 'updates expiry date' do
click_groups_tab
- expires_at_field = "member_expires_at_#{shared_with_group.id}"
- fill_in "member_expires_at_#{shared_with_group.id}", with: 3.days.from_now.to_date
+ page.within first_row do
+ fill_in 'Expiration date', with: 5.days.from_now.to_date
+ find_field('Expiration date').native.send_keys :enter
- find_field(expires_at_field).native.send_keys :enter
- wait_for_requests
+ wait_for_requests
- page.within(find('li.group_member')) do
- expect(page).to have_content('Expires in 3 days')
+ expect(page).to have_content(/in \d days/)
end
end
context 'when expiry date is set' do
- let(:additional_link_attrs) { { expires_at: 3.days.from_now.to_date } }
+ let(:additional_link_attrs) { { expires_at: 5.days.from_now.to_date } }
it 'clears expiry date' do
click_groups_tab
- page.within(find('li.group_member')) do
- expect(page).to have_content('Expires in 3 days')
+ page.within first_row do
+ expect(page).to have_content(/in \d days/)
- page.within(find('.js-edit-member-form')) do
- find('.js-clear-input').click
- end
+ find('[data-testid="clear-button"]').click
wait_for_requests
- expect(page).not_to have_content('Expires in')
+ expect(page).to have_content('No expiration set')
end
end
end
@@ -128,6 +126,7 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
end
def click_groups_tab
+ expect(page).to have_link 'Groups'
click_link "Groups"
end
end
diff --git a/spec/features/groups/members/manage_members_spec.rb b/spec/features/groups/members/manage_members_spec.rb
index aedb7c170f8..e6da05c4873 100644
--- a/spec/features/groups/members/manage_members_spec.rb
+++ b/spec/features/groups/members/manage_members_spec.rb
@@ -4,15 +4,13 @@ require 'spec_helper'
RSpec.describe 'Groups > Members > Manage members' do
include Select2Helper
- include Spec::Support::Helpers::Features::ListRowsHelpers
+ include Spec::Support::Helpers::Features::MembersHelpers
let(:user1) { create(:user, name: 'John Doe') }
let(:user2) { create(:user, name: 'Mary Jane') }
let(:group) { create(:group) }
before do
- stub_feature_flags(vue_group_members_list: false)
-
sign_in(user1)
end
@@ -24,7 +22,7 @@ RSpec.describe 'Groups > Members > Manage members' do
page.within(second_row) do
click_button('Developer')
- click_link('Owner')
+ click_button('Owner')
expect(page).to have_button('Owner')
end
@@ -71,11 +69,14 @@ RSpec.describe 'Groups > Members > Manage members' do
visit group_group_members_path(group)
# Open modal
- find(:css, '.project-members-page li', text: user2.name).find(:css, 'button.btn-danger').click
-
- expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
+ page.within(second_row) do
+ click_button 'Remove member'
+ end
- click_on('Remove member')
+ page.within('[role="dialog"]') do
+ expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
+ click_button('Remove member')
+ end
wait_for_requests
@@ -103,16 +104,17 @@ RSpec.describe 'Groups > Members > Manage members' do
add_user('test@example.com', 'Reporter')
- click_link('Invited')
+ expect(page).to have_link 'Invited'
+ click_link 'Invited'
- page.within('.content-list.members-list') do
+ page.within(members_table) do
expect(page).to have_content('test@example.com')
expect(page).to have_content('Invited')
expect(page).to have_button('Reporter')
end
end
- it 'guest can not manage other users' do
+ it 'guest can not manage other users', :js do
group.add_guest(user1)
group.add_developer(user2)
@@ -126,7 +128,7 @@ RSpec.describe 'Groups > Members > Manage members' do
expect(page).not_to have_button 'Developer'
# Can not remove user2
- expect(page).not_to have_css('a.btn-danger')
+ expect(page).not_to have_selector 'button[title="Remove member"]'
end
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 dd708c243a8..de9b32e00aa 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
@@ -4,17 +4,13 @@ require 'spec_helper'
RSpec.describe 'Groups > Members > Owner adds member with expiration date', :js do
include Select2Helper
- include ActiveSupport::Testing::TimeHelpers
+ include Spec::Support::Helpers::Features::MembersHelpers
let_it_be(:user1) { create(:user, name: 'John Doe') }
let_it_be(:group) { create(:group) }
let(:new_member) { create(:user, name: 'Mary Jane') }
before do
- stub_feature_flags(vue_group_members_list: false)
-
- travel_to Time.now.utc.beginning_of_day
-
group.add_owner(user1)
sign_in(user1)
end
@@ -22,17 +18,17 @@ RSpec.describe 'Groups > Members > Owner adds member with expiration date', :js
it 'expiration date is displayed in the members list' do
visit group_group_members_path(group)
- page.within '.invite-users-form' do
+ page.within invite_users_form do
select2(new_member.id, from: '#user_ids', multiple: true)
- fill_in 'expires_at', with: 3.days.from_now.to_date
+ fill_in 'expires_at', with: 5.days.from_now.to_date
find_field('expires_at').native.send_keys :enter
click_on 'Invite'
end
- page.within "#group_member_#{group_member_id}" do
- expect(page).to have_content('Expires in 3 days')
+ page.within second_row do
+ expect(page).to have_content(/in \d days/)
end
end
@@ -40,32 +36,28 @@ RSpec.describe 'Groups > Members > Owner adds member with expiration date', :js
group.add_developer(new_member)
visit group_group_members_path(group)
- page.within "#group_member_#{group_member_id}" do
- fill_in 'Expiration date', with: 3.days.from_now.to_date
+ page.within second_row do
+ fill_in 'Expiration date', with: 5.days.from_now.to_date
find_field('Expiration date').native.send_keys :enter
wait_for_requests
- expect(page).to have_content('Expires in 3 days')
+ expect(page).to have_content(/in \d days/)
end
end
it 'clears expiration date' do
- create(:group_member, :developer, user: new_member, group: group, expires_at: 3.days.from_now.to_date)
+ create(:group_member, :developer, user: new_member, group: group, expires_at: 5.days.from_now.to_date)
visit group_group_members_path(group)
- page.within "#group_member_#{group_member_id}" do
- expect(page).to have_content('Expires in 3 days')
+ page.within second_row do
+ expect(page).to have_content(/in \d days/)
- find('.js-clear-input').click
+ find('[data-testid="clear-button"]').click
wait_for_requests
- expect(page).not_to have_content('Expires in')
+ expect(page).to have_content('No expiration set')
end
end
-
- def group_member_id
- group.members.find_by(user_id: new_member).id
- end
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 44fd7380b79..71c9b280ebe 100644
--- a/spec/features/groups/members/master_manages_access_requests_spec.rb
+++ b/spec/features/groups/members/master_manages_access_requests_spec.rb
@@ -3,10 +3,6 @@
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 a95b59cece1..0b2d2fd478d 100644
--- a/spec/features/groups/members/search_members_spec.rb
+++ b/spec/features/groups/members/search_members_spec.rb
@@ -2,7 +2,9 @@
require 'spec_helper'
-RSpec.describe 'Search group member' do
+RSpec.describe 'Search group member', :js do
+ include Spec::Support::Helpers::Features::MembersHelpers
+
let(:user) { create :user }
let(:member) { create :user }
@@ -14,8 +16,6 @@ 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
@@ -23,11 +23,10 @@ RSpec.describe 'Search group member' do
it 'renders member users' do
page.within '[data-testid="user-search-form"]' do
fill_in 'search', with: member.name
- find('.user-search-btn').click
+ find('[data-testid="user-search-submit"]').click
end
- group_members_list = find('[data-qa-selector="members_list"]')
- expect(group_members_list).to have_content(member.name)
- expect(group_members_list).not_to have_content(user.name)
+ expect(members_table).to have_content(member.name)
+ expect(members_table).not_to have_content(user.name)
end
end
diff --git a/spec/features/groups/members/sort_members_spec.rb b/spec/features/groups/members/sort_members_spec.rb
index d940550b18a..f03cc36df18 100644
--- a/spec/features/groups/members/sort_members_spec.rb
+++ b/spec/features/groups/members/sort_members_spec.rb
@@ -2,14 +2,16 @@
require 'spec_helper'
-RSpec.describe 'Groups > Members > Sort members' do
+RSpec.describe 'Groups > Members > Sort members', :js do
+ include Spec::Support::Helpers::Features::MembersHelpers
+
let(:owner) { create(:user, name: 'John Doe') }
let(:developer) { create(:user, name: 'Mary Jane', last_sign_in_at: 5.days.ago) }
let(:group) { create(:group) }
- before do
- stub_feature_flags(vue_group_members_list: false)
+ dropdown_toggle_selector = '[data-testid="user-sort-dropdown"] [data-testid="dropdown-toggle"]'
+ before do
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)
@@ -19,84 +21,76 @@ RSpec.describe 'Groups > Members > Sort members' do
it 'sorts alphabetically by default' do
visit_members_list(sort: nil)
- expect(first_member).to include(owner.name)
- expect(second_member).to include(developer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Name, ascending')
+ expect(first_row.text).to include(owner.name)
+ expect(second_row.text).to include(developer.name)
+ expect(page).to have_css(dropdown_toggle_selector, text: 'Name, ascending')
end
it 'sorts by access level ascending' do
visit_members_list(sort: :access_level_asc)
- expect(first_member).to include(developer.name)
- expect(second_member).to include(owner.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Access level, ascending')
+ expect(first_row.text).to include(developer.name)
+ expect(second_row.text).to include(owner.name)
+ expect(page).to have_css(dropdown_toggle_selector, text: 'Access level, ascending')
end
it 'sorts by access level descending' do
visit_members_list(sort: :access_level_desc)
- expect(first_member).to include(owner.name)
- expect(second_member).to include(developer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Access level, descending')
+ expect(first_row.text).to include(owner.name)
+ expect(second_row.text).to include(developer.name)
+ expect(page).to have_css(dropdown_toggle_selector, text: 'Access level, descending')
end
it 'sorts by last joined' do
visit_members_list(sort: :last_joined)
- expect(first_member).to include(developer.name)
- expect(second_member).to include(owner.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Last joined')
+ expect(first_row.text).to include(developer.name)
+ expect(second_row.text).to include(owner.name)
+ expect(page).to have_css(dropdown_toggle_selector, text: 'Last joined')
end
it 'sorts by oldest joined' do
visit_members_list(sort: :oldest_joined)
- expect(first_member).to include(owner.name)
- expect(second_member).to include(developer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Oldest joined')
+ expect(first_row.text).to include(owner.name)
+ expect(second_row.text).to include(developer.name)
+ expect(page).to have_css(dropdown_toggle_selector, text: 'Oldest joined')
end
it 'sorts by name ascending' do
visit_members_list(sort: :name_asc)
- expect(first_member).to include(owner.name)
- expect(second_member).to include(developer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Name, ascending')
+ expect(first_row.text).to include(owner.name)
+ expect(second_row.text).to include(developer.name)
+ expect(page).to have_css(dropdown_toggle_selector, text: 'Name, ascending')
end
it 'sorts by name descending' do
visit_members_list(sort: :name_desc)
- expect(first_member).to include(developer.name)
- expect(second_member).to include(owner.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Name, descending')
+ expect(first_row.text).to include(developer.name)
+ expect(second_row.text).to include(owner.name)
+ expect(page).to have_css(dropdown_toggle_selector, text: 'Name, descending')
end
it 'sorts by recent sign in', :clean_gitlab_redis_shared_state do
visit_members_list(sort: :recent_sign_in)
- expect(first_member).to include(owner.name)
- expect(second_member).to include(developer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Recent sign in')
+ expect(first_row.text).to include(owner.name)
+ expect(second_row.text).to include(developer.name)
+ expect(page).to have_css(dropdown_toggle_selector, text: 'Recent sign in')
end
it 'sorts by oldest sign in', :clean_gitlab_redis_shared_state do
visit_members_list(sort: :oldest_sign_in)
- expect(first_member).to include(developer.name)
- expect(second_member).to include(owner.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Oldest sign in')
+ expect(first_row.text).to include(developer.name)
+ expect(second_row.text).to include(owner.name)
+ expect(page).to have_css(dropdown_toggle_selector, text: 'Oldest sign in')
end
def visit_members_list(sort:)
visit group_group_members_path(group.to_param, sort: sort)
end
-
- def first_member
- page.all('ul.content-list > li').first.text
- end
-
- def second_member
- page.all('ul.content-list > li').last.text
- end
end
diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb
index 3ae9a2b7555..8d1008b98a6 100644
--- a/spec/features/groups/milestone_spec.rb
+++ b/spec/features/groups/milestone_spec.rb
@@ -83,6 +83,7 @@ RSpec.describe 'Group milestones' do
description: 'Lorem Ipsum is simply dummy text'
)
end
+
let_it_be(:active_project_milestone2) { create(:milestone, project: other_project, state: 'active', title: 'v1.1') }
let_it_be(:closed_project_milestone1) { create(:milestone, project: project, state: 'closed', title: 'v2.0') }
let_it_be(:closed_project_milestone2) { create(:milestone, project: other_project, state: 'closed', title: 'v2.0') }
diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb
index e81f2370d10..dec07eb3783 100644
--- a/spec/features/groups/navbar_spec.rb
+++ b/spec/features/groups/navbar_spec.rb
@@ -50,6 +50,8 @@ RSpec.describe 'Group navbar' do
insert_package_nav(_('Kubernetes'))
stub_feature_flags(group_iterations: false)
+ stub_config(dependency_proxy: { enabled: false })
+ stub_config(registry: { enabled: false })
stub_group_wikis(false)
group.add_maintainer(user)
sign_in(user)
@@ -73,6 +75,18 @@ RSpec.describe 'Group navbar' do
it_behaves_like 'verified navigation bar'
end
+ context 'when dependency proxy is available' do
+ before do
+ stub_config(dependency_proxy: { enabled: true })
+
+ insert_dependency_proxy_nav(_('Dependency Proxy'))
+
+ visit group_path(group)
+ end
+
+ it_behaves_like 'verified navigation bar'
+ end
+
context 'when invite team members is not available' do
it 'does not display the js-invite-members-trigger' do
visit group_path(group)
diff --git a/spec/features/groups/settings/repository_spec.rb b/spec/features/groups/settings/repository_spec.rb
index d20303027e5..3c1609a2605 100644
--- a/spec/features/groups/settings/repository_spec.rb
+++ b/spec/features/groups/settings/repository_spec.rb
@@ -25,4 +25,21 @@ RSpec.describe 'Group Repository settings' do
let(:entity_type) { 'group' }
end
end
+
+ context 'Default initial branch name' do
+ before do
+ visit group_settings_repository_path(group)
+ end
+
+ it 'has the setting section' do
+ expect(page).to have_css("#js-default-branch-name")
+ end
+
+ it 'renders the correct setting section content' do
+ within("#js-default-branch-name") do
+ expect(page).to have_content("Default initial branch name")
+ expect(page).to have_content("Set the default name of the initial branch when creating new repositories through the user interface.")
+ end
+ end
+ end
end
diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb
index 304573ecd6e..97732374eb9 100644
--- a/spec/features/groups/show_spec.rb
+++ b/spec/features/groups/show_spec.rb
@@ -81,8 +81,7 @@ RSpec.describe 'Group show page' do
it 'allows creating subgroups' do
visit path
- expect(page)
- .to have_css("li[data-text='New subgroup']", visible: false)
+ expect(page).to have_link('New subgroup')
end
end
end
@@ -102,8 +101,7 @@ RSpec.describe 'Group show page' do
path = group_path(relaxed_group)
visit path
- expect(page)
- .to have_css("li[data-text='New subgroup']", visible: false)
+ expect(page).to have_link('New subgroup')
end
end
@@ -116,9 +114,7 @@ RSpec.describe 'Group show page' do
path = group_path(restricted_group)
visit path
- expect(page)
- .not_to have_selector("li[data-text='New subgroup']",
- visible: false)
+ expect(page).not_to have_link('New subgroup')
end
end
end
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index 8264ec2eddd..b9fd3a1a5cc 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -294,35 +294,43 @@ RSpec.describe 'Group' do
describe 'new subgroup / project button' do
let(:group) { create(:group, project_creation_level: Gitlab::Access::NO_ONE_PROJECT_ACCESS, subgroup_creation_level: Gitlab::Access::OWNER_SUBGROUP_ACCESS) }
- it 'new subgroup button is displayed without project creation permission' do
- visit group_path(group)
+ context 'when user has subgroup creation permissions but not project creation permissions' do
+ it 'only displays "New subgroup" button' do
+ visit group_path(group)
- page.within '.group-buttons' do
- expect(page).to have_link('New subgroup')
+ page.within '[data-testid="group-buttons"]' do
+ expect(page).to have_link('New subgroup')
+ expect(page).not_to have_link('New project')
+ end
end
end
- it 'new subgroup button is displayed together with new project button when having project creation permission' do
- group.update!(project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
- visit group_path(group)
+ context 'when user has project creation permissions but not subgroup creation permissions' do
+ it 'only displays "New project" button' do
+ group.update!(project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
+ user = create(:user)
- page.within '.group-buttons' do
- expect(page).to have_css("li[data-text='New subgroup']", visible: false)
- expect(page).to have_css("li[data-text='New project']", visible: false)
+ group.add_maintainer(user)
+ sign_out(:user)
+ sign_in(user)
+
+ visit group_path(group)
+ page.within '[data-testid="group-buttons"]' do
+ expect(page).to have_link('New project')
+ expect(page).not_to have_link('New subgroup')
+ end
end
end
- it 'new project button is displayed without subgroup creation permission' do
- group.update!(project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
- user = create(:user)
-
- group.add_maintainer(user)
- sign_out(:user)
- sign_in(user)
+ context 'when user has project and subgroup creation permissions' do
+ it 'displays "New subgroup" and "New project" buttons' do
+ group.update!(project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
+ visit group_path(group)
- visit group_path(group)
- page.within '.group-buttons' do
- expect(page).to have_link('New project')
+ page.within '[data-testid="group-buttons"]' do
+ expect(page).to have_link('New subgroup')
+ expect(page).to have_link('New project')
+ end
end
end
end
diff --git a/spec/features/ide/user_sees_editor_info_spec.rb b/spec/features/ide/user_sees_editor_info_spec.rb
new file mode 100644
index 00000000000..3760d6bd435
--- /dev/null
+++ b/spec/features/ide/user_sees_editor_info_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'IDE user sees editor info', :js do
+ include WebIdeSpecHelpers
+
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:user) { project.owner }
+
+ before do
+ sign_in(user)
+
+ ide_visit(project)
+ end
+
+ it 'shows line position' do
+ ide_open_file('README.md')
+
+ within find('.ide-status-bar') do
+ expect(page).to have_content('1:1')
+ end
+
+ ide_set_editor_position(4, 10)
+
+ within find('.ide-status-bar') do
+ expect(page).not_to have_content('1:1')
+ expect(page).to have_content('4:10')
+ end
+ end
+
+ it 'updates after rename' do
+ ide_open_file('README.md')
+ ide_set_editor_position(4, 10)
+
+ within find('.ide-status-bar') do
+ expect(page).to have_content('markdown')
+ expect(page).to have_content('4:10')
+ end
+
+ ide_rename_file('README.md', 'READMEZ.txt')
+
+ within find('.ide-status-bar') do
+ expect(page).to have_content('plaintext')
+ expect(page).to have_content('1:1')
+ end
+ end
+
+ it 'persists position after rename' do
+ ide_open_file('README.md')
+ ide_set_editor_position(4, 10)
+
+ ide_open_file('files/js/application.js')
+ ide_rename_file('README.md', 'READING_RAINBOW.md')
+
+ ide_open_file('READING_RAINBOW.md')
+
+ within find('.ide-status-bar') do
+ expect(page).to have_content('4:10')
+ end
+ end
+
+ it 'persists position' do
+ ide_open_file('README.md')
+ ide_set_editor_position(4, 10)
+
+ ide_close_file('README.md')
+ ide_open_file('README.md')
+
+ within find('.ide-status-bar') do
+ expect(page).to have_content('markdown')
+ expect(page).to have_content('4:10')
+ end
+ end
+
+ it 'persists viewer' do
+ ide_open_file('README.md')
+ click_link('Preview Markdown')
+
+ within find('.md-previewer') do
+ expect(page).to have_content('testme')
+ end
+
+ # Switch away from and back to the file
+ ide_open_file('.gitignore')
+ ide_open_file('README.md')
+
+ # Preview is still enabled
+ within find('.md-previewer') do
+ expect(page).to have_content('testme')
+ end
+ end
+end
diff --git a/spec/features/incidents/user_views_incident_spec.rb b/spec/features/incidents/user_views_incident_spec.rb
new file mode 100644
index 00000000000..3595f5c03ec
--- /dev/null
+++ b/spec/features/incidents/user_views_incident_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe "User views incident" do
+ let_it_be(:project) { create(:project_empty_repo, :public) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:incident) { create(:incident, project: project, description: "# Description header\n\n**Lorem** _ipsum_ dolor sit [amet](https://example.com)", author: user) }
+ let_it_be(:note) { create(:note, noteable: incident, project: project, author: user) }
+
+ before_all do
+ project.add_developer(user)
+ end
+
+ before do
+ stub_feature_flags(vue_issue_header: false)
+
+ sign_in(user)
+
+ visit(project_issues_incident_path(project, incident))
+ end
+
+ it { expect(page).to have_header_with_correct_id_and_link(1, "Description header", "description-header") }
+
+ it_behaves_like 'page meta description', ' Description header Lorem ipsum dolor sit amet'
+
+ it 'shows the merge request and incident actions', :aggregate_failures do
+ expect(page).to have_link('New incident')
+ expect(page).to have_button('Create merge request')
+ expect(page).to have_link('Close incident')
+ end
+
+ context 'when the project is archived' do
+ before do
+ project.update!(archived: true)
+ visit(project_issues_incident_path(project, incident))
+ end
+
+ it 'hides the merge request and incident actions', :aggregate_failures do
+ expect(page).not_to have_link('New incident')
+ expect(page).not_to have_button('Create merge request')
+ expect(page).not_to have_link('Close incident')
+ end
+ end
+
+ describe 'user status' do
+ subject { visit(project_issues_incident_path(project, incident)) }
+
+ context 'when showing status of the author of the incident' do
+ it_behaves_like 'showing user status' do
+ let(:user_with_status) { user }
+ end
+ end
+
+ context 'when showing status of a user who commented on an incident', :js do
+ it_behaves_like 'showing user status' do
+ let(:user_with_status) { user }
+ end
+ end
+
+ context 'when status message has an emoji', :js do
+ 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
+ expect(page).to have_emoji(message_emoji)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index 8ccaf82536a..2ceffa896eb 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
let(:group_invite) { group.group_members.invite.last }
before do
+ stub_application_setting(require_admin_approval_after_user_signup: false)
project.add_maintainer(owner)
group.add_owner(owner)
group.add_developer('user@example.com', owner)
@@ -58,6 +59,8 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
end
it 'pre-fills the Email field on the sign up box with the invite_email from the invite' do
+ click_link 'Register now'
+
expect(find_field('Email').value).to eq(group_invite.invite_email)
end
@@ -92,6 +95,22 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
before do
stub_application_setting(send_user_confirmation_email: send_email_confirmation)
visit invite_path(group_invite.raw_invite_token)
+ click_link 'Register now'
+ end
+
+ context 'with admin appoval required enabled' do
+ before do
+ stub_application_setting(require_admin_approval_after_user_signup: true)
+ end
+
+ let(:send_email_confirmation) { true }
+
+ it 'does not sign the user in' do
+ fill_in_sign_up_form(new_user)
+
+ expect(current_path).to eq(new_user_session_path)
+ expect(page).to have_content('You have signed up successfully. However, we could not sign you in because your account is awaiting approval from your GitLab administrator')
+ end
end
context 'email confirmation disabled' do
diff --git a/spec/features/issuables/close_reopen_report_toggle_spec.rb b/spec/features/issuables/close_reopen_report_toggle_spec.rb
index 6e99cfb3293..867d2ff7aae 100644
--- a/spec/features/issuables/close_reopen_report_toggle_spec.rb
+++ b/spec/features/issuables/close_reopen_report_toggle_spec.rb
@@ -7,6 +7,10 @@ RSpec.describe 'Issuables Close/Reopen/Report toggle' do
let(:user) { create(:user) }
+ before do
+ stub_feature_flags(vue_issue_header: false)
+ end
+
shared_examples 'an issuable close/reopen/report toggle' do
let(:container) { find('.issuable-close-dropdown') }
let(:human_model_name) { issuable.model_name.human.downcase }
@@ -95,12 +99,13 @@ RSpec.describe 'Issuables Close/Reopen/Report toggle' do
expect(page).to have_link('New issue')
expect(page).not_to have_button('Close issue')
expect(page).not_to have_button('Reopen issue')
- expect(page).not_to have_link('Edit')
+ expect(page).not_to have_link(title: 'Edit title and description')
end
end
end
context 'on a merge request' do
+ let(:container) { find('.detail-page-header-actions') }
let(:project) { create(:project, :repository) }
let(:issuable) { create(:merge_request, source_project: project) }
@@ -116,24 +121,47 @@ RSpec.describe 'Issuables Close/Reopen/Report toggle' do
it_behaves_like 'an issuable close/reopen/report toggle'
+ context 'when the merge request is closed' do
+ let(:issuable) { create(:merge_request, :closed, source_project: project) }
+
+ it 'shows both the `Edit` and `Reopen` button' do
+ expect(container).to have_link('Edit')
+ expect(container).not_to have_button('Report abuse')
+ expect(container).not_to have_button('Close merge request')
+ expect(container).to have_link('Reopen merge request')
+ end
+
+ context 'when the merge request author is the current user' do
+ let(:issuable) { create(:merge_request, :closed, source_project: project, author: user) }
+
+ it 'shows both the `Edit` and `Reopen` button' do
+ expect(container).to have_link('Edit')
+ expect(container).not_to have_link('Report abuse')
+ expect(container).not_to have_selector('button.dropdown-toggle')
+ expect(container).not_to have_button('Close merge request')
+ expect(container).to have_link('Reopen merge request')
+ end
+ end
+ end
+
context 'when the merge request is merged' do
let(:issuable) { create(:merge_request, :merged, source_project: project) }
- it 'shows only the `Report abuse` and `Edit` button' do
- expect(page).to have_link('Report abuse')
- expect(page).to have_link('Edit')
- expect(page).not_to have_button('Close merge request')
- expect(page).not_to have_button('Reopen merge request')
+ it 'shows only the `Edit` button' do
+ expect(container).to have_link(exact_text: 'Edit')
+ expect(container).not_to have_link('Report abuse')
+ expect(container).not_to have_button('Close merge request')
+ expect(container).not_to have_button('Reopen merge request')
end
context 'when the merge request author is the current user' do
let(:issuable) { create(:merge_request, :merged, source_project: project, author: user) }
it 'shows only the `Edit` button' do
- expect(page).to have_link('Edit')
- expect(page).to have_link('Report abuse')
- expect(page).not_to have_button('Close merge request')
- expect(page).not_to have_button('Reopen merge request')
+ expect(container).to have_link(exact_text: 'Edit')
+ expect(container).not_to have_link('Report abuse')
+ expect(container).not_to have_button('Close merge request')
+ expect(container).not_to have_button('Reopen merge request')
end
end
end
@@ -150,10 +178,10 @@ RSpec.describe 'Issuables Close/Reopen/Report toggle' do
end
it 'only shows a `Report abuse` button' do
- expect(page).to have_link('Report abuse')
- expect(page).not_to have_button('Close merge request')
- expect(page).not_to have_button('Reopen merge request')
- expect(page).not_to have_link('Edit')
+ expect(container).to have_link('Report abuse')
+ expect(container).not_to have_button('Close merge request')
+ expect(container).not_to have_button('Reopen merge request')
+ expect(container).not_to have_link(exact_text: 'Edit')
end
end
end
diff --git a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb
index 12682905559..0f0146a26a2 100644
--- a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb
+++ b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb
@@ -18,6 +18,10 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j
end
end
+ before do
+ stub_feature_flags(remove_resolve_note: false)
+ end
+
describe 'as a user with access to the project' do
before do
project.add_maintainer(user)
diff --git a/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb
index 55a02dc4255..b449939a70c 100644
--- a/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb
+++ b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb
@@ -14,6 +14,10 @@ RSpec.describe 'Resolve an open thread in a merge request by creating an issue',
"a[title=\"#{title}\"][href=\"#{url}\"]"
end
+ before do
+ stub_feature_flags(remove_resolve_note: false)
+ end
+
describe 'As a user with access to the project' do
before do
project.add_maintainer(user)
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index ff78b9e608f..06f79f94e8d 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -535,6 +535,21 @@ RSpec.describe 'GFM autocomplete', :js do
expect(find('.tribute-container ul', visible: true)).to have_text(user_xss.username)
end
+ it 'opens autocomplete menu for Milestone when field starts with text with item escaping HTML characters' do
+ milestone_xss_title = 'alert milestone &lt;img src=x onerror="alert(\'Hello xss\');" a'
+ create(:milestone, project: project, title: milestone_xss_title)
+
+ page.within '.timeline-content-form' do
+ find('#note-body').native.send_keys('%')
+ end
+
+ wait_for_requests
+
+ expect(page).to have_selector('.tribute-container', visible: true)
+
+ expect(find('.tribute-container ul', visible: true)).to have_text('alert milestone')
+ end
+
it 'selects the first item for assignee dropdowns' do
page.within '.timeline-content-form' do
find('#note-body').native.send_keys('@')
@@ -799,6 +814,13 @@ RSpec.describe 'GFM autocomplete', :js do
end
end
+ context 'issues' do
+ let(:object) { issue }
+ let(:expected_body) { object.to_reference }
+
+ it_behaves_like 'autocomplete suggestions'
+ end
+
context 'merge requests' do
let(:object) { create(:merge_request, source_project: project) }
let(:expected_body) { object.to_reference }
@@ -806,6 +828,27 @@ RSpec.describe 'GFM autocomplete', :js do
it_behaves_like 'autocomplete suggestions'
end
+ context 'project snippets' do
+ let!(:object) { create(:project_snippet, project: project, title: 'code snippet') }
+ let(:expected_body) { object.to_reference }
+
+ it_behaves_like 'autocomplete suggestions'
+ end
+
+ context 'label' do
+ let!(:object) { label }
+ let(:expected_body) { object.title }
+
+ it_behaves_like 'autocomplete suggestions'
+ end
+
+ context 'milestone' do
+ let!(:object) { create(:milestone, 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/user_creates_branch_and_merge_request_spec.rb b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
index 617eac88973..e225a45481d 100644
--- a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
+++ b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
@@ -250,7 +250,7 @@ RSpec.describe 'User creates branch and merge request on issue page', :js do
def test_selection_mark(li_create_branch, li_create_merge_request, button_create_target, button_create_merge_request)
page.within(li_create_merge_request) do
- expect(page).to have_css('i.fa.fa-check')
+ expect(page).to have_selector('[data-testid="check-icon"]')
expect(button_create_target).to have_text('Create merge request')
expect(button_create_merge_request).to have_text('Create merge request')
end
@@ -258,7 +258,7 @@ RSpec.describe 'User creates branch and merge request on issue page', :js do
li_create_branch.click
page.within(li_create_branch) do
- expect(page).to have_css('i.fa.fa-check')
+ expect(page).to have_selector('[data-testid="check-icon"]')
expect(button_create_target).to have_text('Create branch')
expect(button_create_merge_request).to have_text('Create branch')
end
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index de746415205..11b905735de 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -138,6 +138,33 @@ RSpec.describe "Issues > User edits issue", :js do
expect(page).not_to have_text('verisimilitude')
end
end
+
+ it 'can remove label without removing label added via quick action', :aggregate_failures do
+ # Add `syzygy` label with a quick action
+ note = find('#note-body')
+ page.within '.timeline-content-form' do
+ note.native.send_keys('/label ~syzygy')
+ end
+ click_button 'Comment'
+
+ wait_for_requests
+
+ page.within '.block.labels' do
+ # Remove `verisimilitude` label
+ within '.gl-label' do
+ click_button
+ end
+
+ wait_for_requests
+
+ expect(page).to have_text('syzygy')
+ expect(page).not_to have_text('verisimilitude')
+ end
+
+ expect(page).to have_text('removed verisimilitude label')
+ expect(page).not_to have_text('removed syzygy verisimilitude labels')
+ expect(issue.reload.labels.map(&:title)).to contain_exactly('syzygy')
+ end
end
describe 'update assignee' do
diff --git a/spec/features/issues/user_interacts_with_awards_spec.rb b/spec/features/issues/user_interacts_with_awards_spec.rb
index 7db72f2cd05..fec603e466a 100644
--- a/spec/features/issues/user_interacts_with_awards_spec.rb
+++ b/spec/features/issues/user_interacts_with_awards_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe 'User interacts with awards' do
page.within('.awards') do
expect(page).to have_selector('.js-emoji-btn')
expect(page.find('.js-emoji-btn.active .js-counter')).to have_content('1')
- expect(page).to have_css(".js-emoji-btn.active[data-original-title='You']")
+ expect(page).to have_css(".js-emoji-btn.active[title='You']")
expect do
page.find('.js-emoji-btn.active').click
@@ -294,7 +294,7 @@ RSpec.describe 'User interacts with awards' do
end
end
- it 'toggles the smiley emoji on a note', :js do
+ it 'toggles the smiley emoji on a note', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/267525' do
toggle_smiley_emoji(true)
within('.note-body') do
diff --git a/spec/features/issues/user_sees_live_update_spec.rb b/spec/features/issues/user_sees_live_update_spec.rb
index d27cdb774a5..79c6978cbc0 100644
--- a/spec/features/issues/user_sees_live_update_spec.rb
+++ b/spec/features/issues/user_sees_live_update_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe 'Issues > User sees live update', :js do
end
describe 'confidential issue#show' do
- it 'shows confidential sibebar information as confidential and can be turned off' do
+ it 'shows confidential sibebar information as confidential and can be turned off', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/254644' do
issue = create(:issue, :confidential, project: project)
visit project_issue_path(project, issue)
diff --git a/spec/features/issues/user_views_issue_spec.rb b/spec/features/issues/user_views_issue_spec.rb
index 9b1c8be1513..4128f3478bb 100644
--- a/spec/features/issues/user_views_issue_spec.rb
+++ b/spec/features/issues/user_views_issue_spec.rb
@@ -13,6 +13,8 @@ RSpec.describe "User views issue" do
end
before do
+ stub_feature_flags(vue_issue_header: false)
+
sign_in(user)
visit(project_issue_path(project, issue))
diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb
index ad1ad067935..c452408cff2 100644
--- a/spec/features/merge_request/user_comments_on_diff_spec.rb
+++ b/spec/features/merge_request/user_comments_on_diff_spec.rb
@@ -136,12 +136,6 @@ RSpec.describe 'User comments on a diff', :js do
add_comment('-13', '+15')
end
- it 'allows comments to start above hidden lines and end below' do
- # click +28, select 21 add and verify comment
- click_diff_line(find('div[data-path="files/ruby/popen.rb"] .new_line a[data-linenumber="28"]').find(:xpath, '../..'), 'right')
- add_comment('21', '+28')
- end
-
it 'allows comments on previously hidden lines at the top of a file' do
# Click -9, expand up, select 1 add and verify comment
page.within('[data-path="files/ruby/popen.rb"]') do
diff --git a/spec/features/merge_request/user_comments_on_merge_request_spec.rb b/spec/features/merge_request/user_comments_on_merge_request_spec.rb
index 73f2b1a25ce..43096f8e7f9 100644
--- a/spec/features/merge_request/user_comments_on_merge_request_spec.rb
+++ b/spec/features/merge_request/user_comments_on_merge_request_spec.rb
@@ -30,6 +30,27 @@ RSpec.describe 'User comments on a merge request', :js do
end
end
+ it 'replys to a new comment' do
+ page.within('.js-main-target-form') do
+ fill_in('note[note]', with: 'comment 1')
+ click_button('Comment')
+ end
+
+ wait_for_requests
+
+ page.within('.note') do
+ click_button('Reply to comment')
+
+ fill_in('note[note]', with: 'comment 2')
+ click_button('Add comment now')
+ end
+
+ wait_for_requests
+
+ # Test that the discussion doesn't get auto-resolved
+ expect(page).to have_button('Resolve thread')
+ end
+
it 'loads new comment' do
# Add new comment in background in order to check
# if it's going to be loaded automatically for current user.
diff --git a/spec/features/merge_request/user_expands_diff_spec.rb b/spec/features/merge_request/user_expands_diff_spec.rb
index 0cdc87de761..09c5897f102 100644
--- a/spec/features/merge_request/user_expands_diff_spec.rb
+++ b/spec/features/merge_request/user_expands_diff_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe 'User expands diff', :js do
before do
stub_feature_flags(increased_diff_limits: false)
+ allow(Gitlab::CurrentSettings).to receive(:diff_max_patch_bytes).and_return(100.kilobytes)
+
visit(diffs_project_merge_request_path(project, merge_request))
wait_for_requests
@@ -15,11 +17,11 @@ RSpec.describe 'User expands diff', :js do
it 'allows user to expand diff' do
page.within find('[id="19763941ab80e8c09871c0a425f0560d9053bcb3"]') do
- click_link 'Click to expand it.'
+ find('[data-testid="expand-button"]').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_merges_immediately_spec.rb b/spec/features/merge_request/user_merges_immediately_spec.rb
index 0fb081ec507..64a357de1f7 100644
--- a/spec/features/merge_request/user_merges_immediately_spec.rb
+++ b/spec/features/merge_request/user_merges_immediately_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe 'Merge requests > User merges immediately', :js do
find('.dropdown-toggle').click
Sidekiq::Testing.fake! do
- click_link 'Merge immediately'
+ click_button 'Merge immediately'
expect(find('.accept-merge-request.btn-info')).to have_content('Merge in progress')
diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
index 444d5371e7a..5e99383e4a1 100644
--- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
@@ -93,19 +93,6 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do
it_behaves_like 'Merge when pipeline succeeds activator'
end
end
-
- describe 'enabling Merge when pipeline succeeds via dropdown' do
- it 'activates the Merge when pipeline succeeds feature' do
- wait_for_requests
-
- find('.js-merge-moment').click
- click_link 'Merge when pipeline succeeds'
-
- expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds"
- expect(page).to have_content "The source branch will not be deleted"
- expect(page).to have_link "Cancel automatic merge"
- end
- end
end
context 'when merge when pipeline succeeds is enabled' do
diff --git a/spec/features/merge_request/user_resolves_conflicts_spec.rb b/spec/features/merge_request/user_resolves_conflicts_spec.rb
index f96408fb10b..06405232462 100644
--- a/spec/features/merge_request/user_resolves_conflicts_spec.rb
+++ b/spec/features/merge_request/user_resolves_conflicts_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Merge request > User resolves conflicts', :js do
+ include Spec::Support::Helpers::Features::EditorLiteSpecHelpers
+
let(:project) { create(:project, :repository) }
let(:user) { project.creator }
@@ -64,15 +66,13 @@ RSpec.describe 'Merge request > User resolves conflicts', :js do
within find('.files-wrapper .diff-file', text: 'files/ruby/popen.rb') do
click_button 'Edit inline'
wait_for_requests
- find('.files-wrapper .diff-file pre')
- execute_script('ace.edit($(".files-wrapper .diff-file pre")[0]).setValue("One morning");')
+ editor_set_value("One morning")
end
within find('.files-wrapper .diff-file', text: 'files/ruby/regex.rb') do
click_button 'Edit inline'
wait_for_requests
- find('.files-wrapper .diff-file pre')
- execute_script('ace.edit($(".files-wrapper .diff-file pre")[1]).setValue("Gregor Samsa woke from troubled dreams");')
+ editor_set_value("Gregor Samsa woke from troubled dreams")
end
find_button('Commit to source branch').send_keys(:return)
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 cd06886169d..00f0c88497b 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,6 +15,10 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
diff_refs: merge_request.diff_refs)
end
+ before do
+ stub_feature_flags(remove_resolve_note: false)
+ end
+
context 'no threads' do
before do
project.add_maintainer(user)
diff --git a/spec/features/merge_request/user_resolves_wip_mr_spec.rb b/spec/features/merge_request/user_resolves_wip_mr_spec.rb
index b67167252e1..93b14279a06 100644
--- a/spec/features/merge_request/user_resolves_wip_mr_spec.rb
+++ b/spec/features/merge_request/user_resolves_wip_mr_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Merge request > User resolves Work in Progress', :js do
it 'retains merge request data after clicking Resolve WIP status' do
expect(page.find('.ci-widget-content')).to have_content("Pipeline ##{pipeline.id}")
- expect(page).to have_content "This merge request is still a work in progress."
+ expect(page).to have_content "This merge request is still a draft."
page.within('.mr-state-widget') do
click_button('Mark as ready')
@@ -45,7 +45,7 @@ RSpec.describe 'Merge request > User resolves Work in Progress', :js do
# merge request widget refreshes, which masks missing elements
# that should already be present.
expect(page.find('.ci-widget-content', wait: 0)).to have_content("Pipeline ##{pipeline.id}")
- expect(page).not_to have_content('This merge request is still a work in progress.')
+ expect(page).not_to have_content('This merge request is still a draft.')
end
end
end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index 93fea44707c..0e8012f161f 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -558,8 +558,9 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
end
before do
- allow_any_instance_of(TestSuiteComparerEntity)
- .to receive(:max_tests).and_return(2)
+ stub_const("Gitlab::Ci::Reports::TestSuiteComparer::DEFAULT_MAX_TESTS", 2)
+ stub_const("Gitlab::Ci::Reports::TestSuiteComparer::DEFAULT_MIN_TESTS", 1)
+
allow_any_instance_of(MergeRequest)
.to receive(:has_test_reports?).and_return(true)
allow_any_instance_of(MergeRequest)
diff --git a/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb b/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb
index 93807512d9c..4bb6c3265a4 100644
--- a/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb
+++ b/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb
@@ -9,8 +9,6 @@ RSpec.describe 'Merge request > User sees suggest pipeline', :js do
before do
stub_application_setting(auto_devops_enabled: false)
- stub_experiment(suggest_pipeline: true)
- stub_experiment_for_user(suggest_pipeline: true)
project.add_maintainer(user)
sign_in(user)
visit project_merge_request_path(project, merge_request)
@@ -32,4 +30,40 @@ RSpec.describe 'Merge request > User sees suggest pipeline', :js do
expect(page).not_to have_content('Are you adding technical debt or code vulnerabilities?')
end
+
+ it 'runs tour from start to finish ensuring all nudges are executed' do
+ # nudge 1
+ expect(page).to have_content('Are you adding technical debt or code vulnerabilities?')
+
+ page.within '.mr-pipeline-suggest' do
+ find('[data-testid="ok"]').click
+ end
+
+ wait_for_requests
+
+ # nudge 2
+ expect(page).to have_content('Choose Code Quality to add a pipeline that tests the quality of your code.')
+
+ find('.js-gitlab-ci-yml-selector').click
+
+ wait_for_requests
+
+ within '.gitlab-ci-yml-selector' do
+ find('.dropdown-input-field').set('Jekyll')
+ find('.dropdown-content li', text: 'Jekyll').click
+ end
+
+ wait_for_requests
+
+ expect(page).not_to have_content('Choose Code Quality to add a pipeline that tests the quality of your code.')
+ # nudge 3
+ expect(page).to have_content('The template is ready!')
+
+ find('#commit-changes').click
+
+ wait_for_requests
+
+ # nudge 4
+ expect(page).to have_content("That's it, well done!")
+ end
end
diff --git a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
index 9268190c7e0..1e1888cd826 100644
--- a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
+++ b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
@@ -304,7 +304,7 @@ RSpec.describe 'User comments on a diff', :js do
wait_for_requests
end
- it 'suggestion is presented' do
+ it 'suggestion is presented', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/268240' do
page.within('.diff-discussions') do
expect(page).to have_button('Apply suggestion')
expect(page).to have_content('Suggested change')
diff --git a/spec/features/merge_request/user_views_diffs_spec.rb b/spec/features/merge_request/user_views_diffs_spec.rb
index 928755bf5de..e1865fe2e14 100644
--- a/spec/features/merge_request/user_views_diffs_spec.rb
+++ b/spec/features/merge_request/user_views_diffs_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe 'User views diffs', :js do
end
it 'expands all diffs' do
- first('.js-file-title').click
+ first('.diff-toggle-caret').click
expect(page).to have_button('Expand all')
diff --git a/spec/features/merge_requests/user_exports_as_csv_spec.rb b/spec/features/merge_requests/user_exports_as_csv_spec.rb
new file mode 100644
index 00000000000..a86ff9d7335
--- /dev/null
+++ b/spec/features/merge_requests/user_exports_as_csv_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Merge Requests > Exports as CSV', :js do
+ let!(:project) { create(:project, :public, :repository) }
+ let!(:user) { project.creator }
+ let!(:open_mr) { create(:merge_request, title: 'Bugfix1', source_project: project, target_project: project, source_branch: 'bugfix1') }
+
+ before do
+ sign_in(user)
+ visit(project_merge_requests_path(project))
+ end
+
+ subject { page.find('.nav-controls') }
+
+ it { is_expected.to have_button('Export as CSV') }
+
+ context 'button is clicked' do
+ before do
+ click_button('Export as CSV')
+ end
+
+ it 'shows a success message' do
+ click_link('Export merge requests')
+
+ expect(page).to have_content 'Your CSV export has started.'
+ expect(page).to have_content "It will be emailed to #{user.email} when complete"
+ end
+ end
+end
diff --git a/spec/features/merge_requests/user_filters_by_draft_spec.rb b/spec/features/merge_requests/user_filters_by_draft_spec.rb
new file mode 100644
index 00000000000..de070805d96
--- /dev/null
+++ b/spec/features/merge_requests/user_filters_by_draft_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Merge Requests > User filters by draft', :js do
+ include FilteredSearchHelpers
+
+ let(:project) { create(:project, :public, :repository) }
+ let(:user) { project.creator }
+
+ before do
+ create(:merge_request, title: 'Draft: Bugfix', source_project: project, target_project: project, source_branch: 'bugfix2')
+
+ sign_in(user)
+ visit project_merge_requests_path(project)
+ end
+
+ it 'filters results' do
+ input_filtered_search_keys('draft:=yes')
+
+ expect(page).to have_content('Draft: Bugfix')
+ end
+
+ it 'does not allow filtering by is not equal' do
+ find('#filtered-search-merge_requests').click
+
+ click_button 'Draft'
+
+ expect(page).not_to have_content('!=')
+ end
+end
diff --git a/spec/features/merge_requests/user_filters_by_target_branch_spec.rb b/spec/features/merge_requests/user_filters_by_target_branch_spec.rb
index 540d87eb969..1d9c80238f5 100644
--- a/spec/features/merge_requests/user_filters_by_target_branch_spec.rb
+++ b/spec/features/merge_requests/user_filters_by_target_branch_spec.rb
@@ -44,4 +44,14 @@ RSpec.describe 'Merge Requests > User filters by target branch', :js do
expect(page).not_to have_content mr2.title
end
end
+
+ context 'filtering by target-branch:!=master' do
+ it 'applies the filter' do
+ input_filtered_search('target-branch:!=master')
+
+ expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
+ expect(page).not_to have_content mr1.title
+ expect(page).to have_content mr2.title
+ end
+ end
end
diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb
index fefa2916c30..dce76e4df6d 100644
--- a/spec/features/milestone_spec.rb
+++ b/spec/features/milestone_spec.rb
@@ -76,7 +76,7 @@ RSpec.describe 'Milestone' do
wait_for_requests
- page.within('.time-tracking-no-tracking-pane') do
+ page.within('[data-testid="noTrackingPane"]') do
expect(page).to have_content 'No estimate or time spent'
end
end
@@ -94,7 +94,7 @@ RSpec.describe 'Milestone' do
wait_for_requests
- page.within('.time-tracking-spend-only-pane') do
+ page.within('[data-testid="spentOnlyPane"]') do
expect(page).to have_content 'Spent: 3h'
end
end
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index 4326700bab1..84ea9495f08 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -12,6 +12,9 @@ RSpec.describe 'Profile account page', :js do
describe 'when I delete my account' do
before do
visit profile_account_path
+
+ # Scroll page to the bottom to make Delete account button visible
+ execute_script('window.scrollTo(0, document.body.scrollHeight)')
end
it { expect(page).to have_content('Delete account') }
@@ -101,10 +104,10 @@ RSpec.describe 'Profile account page', :js do
it 'changes my username' do
fill_in 'username-change-input', with: 'new-username'
- page.find('[data-target="#username-change-confirmation-modal"]').click
+ page.find('[data-testid="username-change-confirmation-modal"]').click
page.within('.modal') do
- find('.js-modal-primary-action').click
+ find('.js-modal-action-primary').click
end
expect(page).to have_content('new-username')
diff --git a/spec/features/profiles/account_spec.rb b/spec/features/profiles/account_spec.rb
index e8caa2159a4..62d8a96c1b2 100644
--- a/spec/features/profiles/account_spec.rb
+++ b/spec/features/profiles/account_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Profile > Account', :js do
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')
+ 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
@@ -128,10 +128,10 @@ def update_username(new_username)
fill_in 'username-change-input', with: new_username
- page.find('[data-target="#username-change-confirmation-modal"]').click
+ page.find('[data-testid="username-change-confirmation-modal"]').click
page.within('.modal') do
- find('.js-modal-primary-action').click
+ find('.js-modal-action-primary').click
end
wait_for_requests
diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb
index 4438831fb76..de5a594aca6 100644
--- a/spec/features/profiles/personal_access_tokens_spec.rb
+++ b/spec/features/profiles/personal_access_tokens_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Profile > Personal Access Tokens', :js do
let(:user) { create(:user) }
+ let(:pat_create_service) { double('PersonalAccessTokens::CreateService', execute: ServiceResponse.error(message: 'error', payload: { personal_access_token: PersonalAccessToken.new })) }
def active_personal_access_tokens
find(".table.active-tokens")
@@ -18,7 +19,7 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
end
def disallow_personal_access_token_saves!
- allow_any_instance_of(PersonalAccessToken).to receive(:save).and_return(false)
+ allow(PersonalAccessTokens::CreateService).to receive(:new).and_return(pat_create_service)
errors = ActiveModel::Errors.new(PersonalAccessToken.new).tap { |e| e.add(:name, "cannot be nil") }
allow_any_instance_of(PersonalAccessToken).to receive(:errors).and_return(errors)
@@ -100,7 +101,10 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
context "when revocation fails" do
it "displays an error message" do
visit profile_personal_access_tokens_path
- allow_any_instance_of(PersonalAccessTokens::RevokeService).to receive(:revocation_permitted?).and_return(false)
+
+ allow_next_instance_of(PersonalAccessTokens::RevokeService) do |instance|
+ allow(instance).to receive(:revocation_permitted?).and_return(false)
+ end
accept_confirm { click_on "Revoke" }
expect(active_personal_access_tokens).to have_text(personal_access_token.name)
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index 697fccaca34..d0340dfc880 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -20,6 +20,10 @@ RSpec.describe 'User edit profile' do
wait_for_requests
end
+ def toggle_busy_status
+ find('[data-testid="user-availability-checkbox"]').set(true)
+ end
+
it 'changes user profile' do
fill_in 'user_skype', with: 'testskype'
fill_in 'user_linkedin', with: 'testlinkedin'
@@ -180,20 +184,51 @@ RSpec.describe 'User edit profile' do
expect(page).to have_emoji('speech_balloon')
end
end
+
+ it 'sets the users status to busy' do
+ busy_status = find('[data-testid="user-availability-checkbox"]')
+
+ expect(busy_status.checked?).to eq(false)
+
+ toggle_busy_status
+ submit_settings
+ visit profile_path
+
+ expect(busy_status.checked?).to eq(true)
+ end
+
+ context 'with set_user_availability_status feature flag disabled' do
+ before do
+ stub_feature_flags(set_user_availability_status: false)
+ visit root_path(user)
+ end
+
+ it 'does not display the availability checkbox' do
+ expect(page).not_to have_css('[data-testid="user-availability-checkbox"]')
+ end
+ end
end
context 'user menu' do
let(:issue) { create(:issue, project: project)}
let(:project) { create(:project) }
- def open_user_status_modal
+ def open_modal(button_text)
find('.header-user-dropdown-toggle').click
page.within ".header-user" do
- click_button 'Set status'
+ click_button button_text
end
end
+ def open_user_status_modal
+ open_modal 'Set status'
+ end
+
+ def open_edit_status_modal
+ open_modal 'Edit status'
+ end
+
def set_user_status_in_modal
page.within "#set-user-status-modal" do
click_button 'Set status'
@@ -246,6 +281,19 @@ RSpec.describe 'User edit profile' do
end
end
+ it 'sets the users status to busy' do
+ open_user_status_modal
+ busy_status = find('[data-testid="user-availability-checkbox"]')
+
+ expect(busy_status.checked?).to eq(false)
+
+ toggle_busy_status
+ set_user_status_in_modal
+ open_edit_status_modal
+
+ expect(busy_status.checked?).to eq(true)
+ end
+
it 'opens the emoji modal again after closing it' do
open_user_status_modal
select_emoji('biohazard', true)
@@ -307,11 +355,7 @@ RSpec.describe 'User edit profile' do
expect(page).to have_content user_status.message
end
- find('.header-user-dropdown-toggle').click
-
- page.within ".header-user" do
- click_button 'Edit status'
- end
+ open_edit_status_modal
find('.js-clear-user-status-button').click
set_user_status_in_modal
@@ -333,11 +377,7 @@ RSpec.describe 'User edit profile' do
expect(page).to have_content user_status.message
end
- find('.header-user-dropdown-toggle').click
-
- page.within ".header-user" do
- click_button 'Edit status'
- end
+ open_edit_status_modal
page.within "#set-user-status-modal" do
click_button 'Remove status'
@@ -357,6 +397,19 @@ RSpec.describe 'User edit profile' do
expect(page).to have_emoji('speech_balloon')
end
end
+
+ context 'with set_user_availability_status feature flag disabled' do
+ before do
+ stub_feature_flags(set_user_availability_status: false)
+ visit root_path(user)
+ end
+
+ it 'does not display the availability checkbox' do
+ open_user_status_modal
+
+ expect(page).not_to have_css('[data-testid="user-availability-checkbox"]')
+ end
+ end
end
context 'User time preferences', :js do
diff --git a/spec/features/project_group_variables_spec.rb b/spec/features/project_group_variables_spec.rb
index e964a7def14..d8eba20ac18 100644
--- a/spec/features/project_group_variables_spec.rb
+++ b/spec/features/project_group_variables_spec.rb
@@ -24,7 +24,6 @@ RSpec.describe 'Project group variables', :js do
sign_in(user)
project.add_maintainer(user)
group.add_owner(user)
- stub_feature_flags(new_variables_ui: false)
end
it 'project in group shows inherited vars from ancestor group' do
@@ -53,9 +52,13 @@ RSpec.describe 'Project group variables', :js do
it 'project origin keys link to ancestor groups ci_cd settings' do
visit project_path
+
find('.group-origin-link').click
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
- expect(find('.js-ci-variable-input-key').value).to eq(key1)
+
+ wait_for_requests
+
+ page.within('.ci-variable-table') do
+ expect(find('.js-ci-variable-row:nth-child(1) [data-label="Key"]').text).to eq(key1)
end
end
end
diff --git a/spec/features/project_variables_spec.rb b/spec/features/project_variables_spec.rb
index c67bcbf919b..a7f94f38d85 100644
--- a/spec/features/project_variables_spec.rb
+++ b/spec/features/project_variables_spec.rb
@@ -12,32 +12,29 @@ RSpec.describe 'Project variables', :js do
sign_in(user)
project.add_maintainer(user)
project.variables << variable
- stub_feature_flags(new_variables_ui: false)
visit page_path
end
it_behaves_like 'variable list'
- it 'adds new variable with a special environment scope' do
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('somekey')
- find('.js-ci-variable-input-value').set('somevalue')
+ it 'adds a new variable with an environment scope' do
+ click_button('Add Variable')
- find('.js-variable-environment-toggle').click
- find('.js-variable-environment-dropdown-wrapper .dropdown-input-field').set('review/*')
- find('.js-variable-environment-dropdown-wrapper .js-dropdown-create-new-item').click
+ page.within('#add-ci-variable') do
+ find('[data-qa-selector="ci_variable_key_field"] input').set('akey')
+ find('#ci-variable-value').set('akey_value')
+ find('[data-testid="environment-scope"]').click
+ find_button('clear').click
+ find('[data-testid="ci-environment-search"]').set('review/*')
+ find('[data-testid="create-wildcard-button"]').click
- expect(find('input[name="variables[variables_attributes][][environment_scope]"]', visible: false).value).to eq('review/*')
+ click_button('Add variable')
end
- click_button('Save variables')
wait_for_requests
- visit page_path
-
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
- expect(find('.js-ci-variable-input-key').value).to eq('somekey')
- expect(page).to have_content('review/*')
+ page.within('.ci-variable-table') do
+ expect(find('.js-ci-variable-row:first-child [data-label="Environments"]').text).to eq('review/*')
end
end
end
diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb
index c30c8dda852..3f1c10b3688 100644
--- a/spec/features/projects/blobs/edit_spec.rb
+++ b/spec/features/projects/blobs/edit_spec.rb
@@ -179,12 +179,14 @@ RSpec.describe 'Editing file blob', :js do
end
context 'with protected branch' do
- before do
- visit project_edit_blob_path(project, tree_join(protected_branch, file_path))
- end
-
it 'shows blob editor with patch branch' do
- expect(find('.js-branch-name').value).to eq('patch-1')
+ freeze_time do
+ visit project_edit_blob_path(project, tree_join(protected_branch, file_path))
+
+ epoch = Time.now.strftime('%s%L').last(5)
+
+ expect(find('.js-branch-name').value).to eq "#{user.username}-protected-branch-patch-#{epoch}"
+ end
end
end
end
diff --git a/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb b/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb
index fda2992af8d..6b9fd41059d 100644
--- a/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb
+++ b/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb
@@ -23,8 +23,6 @@ RSpec.describe 'User creates new blob', :js do
ide_commit
- click_button('Commit')
-
expect(page).to have_content('All changes are committed')
expect(project.repository.blob_at('master', 'dummy-file').data).to eql("Hello world\n")
end
diff --git a/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb b/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
index 023e00a3e02..3069405ba63 100644
--- a/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
+++ b/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
@@ -10,7 +10,6 @@ RSpec.describe 'User follows pipeline suggest nudge spec when feature is enabled
describe 'viewing the new blob page' do
before do
- stub_experiment_for_user(suggest_pipeline: true)
sign_in(user)
end
diff --git a/spec/features/projects/ci/editor_spec.rb b/spec/features/projects/ci/editor_spec.rb
new file mode 100644
index 00000000000..7012cc6edaa
--- /dev/null
+++ b/spec/features/projects/ci/editor_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Pipeline Editor', :js do
+ include Spec::Support::Helpers::Features::EditorLiteSpecHelpers
+
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ project.add_developer(user)
+
+ visit project_ci_pipeline_editor_path(project)
+ end
+
+ it 'user sees the Pipeline Editor page' do
+ expect(page).to have_content('Pipeline Editor')
+ end
+end
diff --git a/spec/features/projects/ci/lint_spec.rb b/spec/features/projects/ci/lint_spec.rb
index eb2efb4357d..466c7ba215e 100644
--- a/spec/features/projects/ci/lint_spec.rb
+++ b/spec/features/projects/ci/lint_spec.rb
@@ -11,7 +11,6 @@ RSpec.describe 'CI Lint', :js do
let(:content_selector) { '.content .view-lines' }
before do
- stub_feature_flags(ci_lint_vue: false)
project.add_developer(user)
sign_in(user)
@@ -26,7 +25,6 @@ RSpec.describe 'CI Lint', :js do
describe 'YAML parsing' do
shared_examples 'validates the YAML' do
before do
- stub_feature_flags(ci_lint_vue: false)
click_on 'Validate'
end
@@ -68,14 +66,6 @@ RSpec.describe 'CI Lint', :js do
it_behaves_like 'validates the YAML'
end
-
- describe 'YAML revalidate' do
- let(:yaml_content) { 'my yaml content' }
-
- 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
@@ -89,7 +79,7 @@ RSpec.describe 'CI Lint', :js do
end
it 'YAML content is cleared' do
- expect(page).to have_field('content', with: '', visible: false, type: 'textarea')
+ expect(page).to have_field(class: 'inputarea', with: '', visible: false, type: 'textarea')
end
end
end
diff --git a/spec/features/projects/container_registry_spec.rb b/spec/features/projects/container_registry_spec.rb
index 7514a26f020..45bf35a6aab 100644
--- a/spec/features/projects/container_registry_spec.rb
+++ b/spec/features/projects/container_registry_spec.rb
@@ -10,6 +10,10 @@ RSpec.describe 'Container Registry', :js do
create(:container_repository, name: 'my/image')
end
+ let(:nameless_container_repository) do
+ create(:container_repository, name: '')
+ end
+
before do
sign_in(user)
project.add_developer(user)
@@ -96,6 +100,20 @@ RSpec.describe 'Container Registry', :js do
end
end
+ describe 'image repo details when image has no name' do
+ before do
+ stub_container_registry_tags(tags: %w[latest], with_manifest: true)
+ project.container_repositories << nameless_container_repository
+ visit_container_registry
+ end
+
+ it 'renders correctly' do
+ find('a[data-testid="details-link"]').click
+
+ expect(page).to have_content 'latest'
+ end
+ end
+
context 'when there are more than 10 images' do
before do
create_list(:container_repository, 12, project: project)
diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
index d28e31c08dc..42f8daf9d5e 100644
--- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
+++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
@@ -27,9 +27,7 @@ RSpec.describe 'Projects > Files > Project owner sees a link to create a license
ide_commit
- click_button('Commit')
-
- expect(current_path).to eq("/-/ide/project/#{project.full_path}/tree/master/-/")
+ expect(current_path).to eq("/-/ide/project/#{project.full_path}/tree/master/-/LICENSE/")
expect(page).to have_content('All changes are committed')
diff --git a/spec/features/projects/files/user_browses_files_spec.rb b/spec/features/projects/files/user_browses_files_spec.rb
index a6126fbcb33..4e9e129042c 100644
--- a/spec/features/projects/files/user_browses_files_spec.rb
+++ b/spec/features/projects/files/user_browses_files_spec.rb
@@ -87,26 +87,22 @@ RSpec.describe "User browses files" do
end
it "shows correct files and links" do
- # rubocop:disable Lint/Void
- # Test the full URLs of links instead of relative paths by `have_link(text: "...", href: "...")`.
- find("a", text: /^empty$/)["href"] == project_tree_url(project, "markdown")
- find("a", text: /^#id$/)["href"] == project_tree_url(project, "markdown", anchor: "#id")
- find("a", text: %r{^/#id$})["href"] == project_tree_url(project, "markdown", anchor: "#id")
- find("a", text: /^README.md#id$/)["href"] == project_blob_url(project, "markdown/README.md", anchor: "#id")
- find("a", text: %r{^d/README.md#id$})["href"] == project_blob_url(project, "d/markdown/README.md", anchor: "#id")
- # rubocop:enable Lint/Void
-
expect(current_path).to eq(project_tree_path(project, "markdown"))
expect(page).to have_content("README.md")
- .and have_content("CHANGELOG")
- .and have_content("Welcome to GitLab GitLab is a free project and repository management application")
- .and have_link("GitLab API doc")
- .and have_link("GitLab API website")
- .and have_link("Rake tasks")
- .and have_link("backup and restore procedure")
- .and have_link("GitLab API doc directory")
- .and have_link("Maintenance")
- .and have_header_with_correct_id_and_link(2, "Application details", "application-details")
+ .and have_content("CHANGELOG")
+ .and have_content("Welcome to GitLab GitLab is a free project and repository management application")
+ .and have_link("GitLab API doc")
+ .and have_link("GitLab API website")
+ .and have_link("Rake tasks")
+ .and have_link("backup and restore procedure")
+ .and have_link("GitLab API doc directory")
+ .and have_link("Maintenance")
+ .and have_header_with_correct_id_and_link(2, "Application details", "application-details")
+ .and have_link("empty", href: "")
+ .and have_link("#id", href: "#id")
+ .and have_link("/#id", href: project_blob_path(project, "markdown/README.md", anchor: "id"))
+ .and have_link("README.md#id", href: project_blob_path(project, "markdown/README.md", anchor: "id"))
+ .and have_link("d/README.md#id", href: project_blob_path(project, "markdown/db/README.md", anchor: "id"))
end
it "shows correct content of file" do
@@ -114,10 +110,10 @@ RSpec.describe "User browses files" do
expect(current_path).to eq(project_blob_path(project, "markdown/doc/api/README.md"))
expect(page).to have_content("All API requests require authentication")
- .and have_content("Contents")
- .and have_link("Users")
- .and have_link("Rake tasks")
- .and have_header_with_correct_id_and_link(1, "GitLab API", "gitlab-api")
+ .and have_content("Contents")
+ .and have_link("Users")
+ .and have_link("Rake tasks")
+ .and have_header_with_correct_id_and_link(1, "GitLab API", "gitlab-api")
click_link("Users")
@@ -148,16 +144,13 @@ RSpec.describe "User browses files" do
click_link("d")
end
- # rubocop:disable Lint/Void
- # Test the full URLs of links instead of relative paths by `have_link(text: "...", href: "...")`.
- find("a", text: "..")["href"] == project_tree_url(project, "markdown/d")
- # rubocop:enable Lint/Void
+ expect(page).to have_link("..", href: project_tree_path(project, "markdown/"))
page.within(".tree-table") do
click_link("README.md")
end
- # Test the full URLs of links instead of relative paths by `have_link(text: "...", href: "...")`.
- find("a", text: /^empty$/)["href"] == project_blob_url(project, "markdown/d/README.md")
+
+ expect(page).to have_link("empty", href: "")
end
it "shows correct content of directory" do
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 de1fcc9d787..b5d5527bbfe 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
@@ -51,7 +51,7 @@ RSpec.describe 'User uploads new design', :js do
end
def upload_design(fixture, count:)
- attach_file(:design_file, fixture, match: :first, make_visible: true)
+ attach_file(:upload_file, fixture, match: :first, make_visible: true)
wait_for('designs uploaded') do
issue.reload.designs.count == count
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 404c3e93586..e19337e1ff5 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -1013,7 +1013,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
before do
job.run!
visit project_job_path(project, job)
- find('.js-cancel-job').click
+ find('[data-testid="cancel-button"]').click
end
it 'loads the page and shows all needed controls' do
@@ -1030,7 +1030,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
visit project_job_path(project, job)
wait_for_requests
- find('.js-retry-button').click
+ find('[data-testid="retry-button"]').click
end
it 'shows the right status and buttons' do
@@ -1057,6 +1057,31 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
end
+
+ context "Job that failed because of a forward deployment failure" do
+ let(:job) { create(:ci_build, :forward_deployment_failure, pipeline: pipeline) }
+
+ before do
+ visit project_job_path(project, job)
+ wait_for_requests
+
+ find('[data-testid="retry-button"]').click
+ end
+
+ it 'shows a modal to warn the user' do
+ page.within('.modal-header') do
+ expect(page).to have_content 'Are you sure you want to retry this job?'
+ end
+ end
+
+ it 'retries the job' do
+ find('[data-testid="retry-button-modal"]').click
+
+ within '[data-testid="ci-header-content"]' do
+ expect(page).to have_content('pending')
+ end
+ end
+ end
end
describe "GET /:project/jobs/:id/download", :js do
diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb
index 4ff3827b240..25791b393bc 100644
--- a/spec/features/projects/navbar_spec.rb
+++ b/spec/features/projects/navbar_spec.rb
@@ -67,4 +67,23 @@ RSpec.describe 'Project navbar' do
it_behaves_like 'verified navigation bar'
end
+
+ context 'when invite team members is not available' do
+ it 'does not display the js-invite-members-trigger' do
+ visit project_path(project)
+
+ expect(page).not_to have_selector('.js-invite-members-trigger')
+ end
+ end
+
+ context 'when invite team members is available' do
+ it 'includes the div for js-invite-members-trigger' do
+ stub_feature_flags(invite_members_group_modal: true)
+ allow_any_instance_of(InviteMembersHelper).to receive(:invite_members_allowed?).and_return(true)
+
+ visit project_path(project)
+
+ expect(page).to have_selector('.js-invite-members-trigger')
+ end
+ end
end
diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb
index c3eea0195a6..11f712fde81 100644
--- a/spec/features/projects/pages_spec.rb
+++ b/spec/features/projects/pages_spec.rb
@@ -365,7 +365,7 @@ RSpec.shared_examples 'pages settings editing' do
end
let!(:artifact) do
- create(:ci_job_artifact, :archive,
+ create(:ci_job_artifact, :archive, :correct_checksum,
file: fixture_file_upload(File.join('spec/fixtures/pages.zip')), job: ci_build)
end
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
index 1e2cd3c0a69..94e3331b173 100644
--- a/spec/features/projects/pipeline_schedules_spec.rb
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'Pipeline Schedules', :js do
it 'displays the required information description' do
page.within('.pipeline-schedule-table-row') do
expect(page).to have_content('pipeline schedule')
- expect(find(".next-run-cell time")['data-original-title'])
+ expect(find(".next-run-cell time")['title'])
.to include(pipeline_schedule.real_next_run.strftime('%b %-d, %Y'))
expect(page).to have_link('master')
expect(page).to have_link("##{pipeline.id}")
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 51826d867cd..ac3566fbbdd 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe 'Pipeline', :js do
before do
sign_in(user)
project.add_role(user, role)
+ stub_feature_flags(graphql_pipeline_details: false)
end
shared_context 'pipeline builds' do
@@ -345,7 +346,7 @@ RSpec.describe 'Pipeline', :js do
it 'shows Pipeline, Jobs, DAG and Failed Jobs tabs with link' do
expect(page).to have_link('Pipeline')
expect(page).to have_link('Jobs')
- expect(page).to have_link('DAG')
+ expect(page).to have_link('Needs')
expect(page).to have_link('Failed Jobs')
end
@@ -892,7 +893,7 @@ RSpec.describe 'Pipeline', :js do
it 'shows Pipeline, Jobs and DAG tabs with link' do
expect(page).to have_link('Pipeline')
expect(page).to have_link('Jobs')
- expect(page).to have_link('DAG')
+ expect(page).to have_link('Needs')
end
it 'shows counter in Jobs tab' do
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index 3e78dfc3bc7..450524b8d70 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe 'Pipelines', :js do
before do
sign_in(user)
+ stub_feature_flags(graphql_pipeline_details: false)
project.add_developer(user)
project.update!(auto_devops_attributes: { enabled: false })
end
diff --git a/spec/features/projects/releases/user_views_edit_release_spec.rb b/spec/features/projects/releases/user_views_edit_release_spec.rb
index 9115a135aeb..bb54b6be9c4 100644
--- a/spec/features/projects/releases/user_views_edit_release_spec.rb
+++ b/spec/features/projects/releases/user_views_edit_release_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'User edits Release', :js do
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:release) { create(:release, project: project, name: 'The first release' ) }
+ let_it_be(:release) { create(:release, :with_milestones, milestones_count: 1, project: project, name: 'The first release' ) }
let_it_be(:user) { create(:user) }
before do
diff --git a/spec/features/projects/releases/user_views_releases_spec.rb b/spec/features/projects/releases/user_views_releases_spec.rb
index 323c57570c3..aabbc8cea7b 100644
--- a/spec/features/projects/releases/user_views_releases_spec.rb
+++ b/spec/features/projects/releases/user_views_releases_spec.rb
@@ -3,8 +3,14 @@
require 'spec_helper'
RSpec.describe 'User views releases', :js do
+ let_it_be(:today) { Time.zone.now }
+ let_it_be(:yesterday) { today - 1.day }
+ let_it_be(:tomorrow) { today + 1.day }
+
let_it_be(:project) { create(:project, :repository, :private) }
- let_it_be(:release) { create(:release, project: project, name: 'The first release' ) }
+ let_it_be(:release_v1) { create(:release, project: project, tag: 'v1', name: 'The first release', released_at: yesterday, created_at: today) }
+ let_it_be(:release_v2) { create(:release, project: project, tag: 'v2-with-a/slash', name: 'The second release', released_at: today, created_at: yesterday) }
+ let_it_be(:release_v3) { create(:release, project: project, tag: 'v3', name: 'The third release', released_at: tomorrow, created_at: tomorrow) }
let_it_be(:maintainer) { create(:user) }
let_it_be(:guest) { create(:user) }
@@ -17,38 +23,36 @@ RSpec.describe 'User views releases', :js do
context('when the user is a maintainer') do
before do
sign_in(maintainer)
- end
- it 'sees the release' do
visit project_releases_path(project)
+ end
- expect(page).to have_content(release.name)
- expect(page).to have_content(release.tag)
- expect(page).not_to have_content('Upcoming Release')
+ it 'sees the release' do
+ page.within("##{release_v1.tag}") do
+ expect(page).to have_content(release_v1.name)
+ expect(page).to have_content(release_v1.tag)
+ expect(page).not_to have_content('Upcoming Release')
+ end
end
context 'when there is a link as an asset' do
- let!(:release_link) { create(:release_link, release: release, url: url ) }
+ let!(:release_link) { create(:release_link, release: release_v1, url: url ) }
let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
- let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release) << release_link.filepath }
+ let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release_v1) << "/downloads#{release_link.filepath}" }
it 'sees the link' do
- visit project_releases_path(project)
-
- page.within('.js-assets-list') do
+ page.within("##{release_v1.tag} .js-assets-list") do
expect(page).to have_link release_link.name, href: direct_asset_link
expect(page).not_to have_css('[data-testid="external-link-indicator"]')
end
end
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!(:release_link) { create(:release_link, release: release_v1, name: 'linux-amd64 binaries', filepath: '/binaries/linux-amd64', url: url) }
let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
it 'sees the link' do
- visit project_releases_path(project)
-
- page.within('.js-assets-list') do
+ page.within("##{release_v1.tag} .js-assets-list") do
expect(page).to have_link release_link.name, href: direct_asset_link
expect(page).not_to have_css('[data-testid="external-link-indicator"]')
end
@@ -59,9 +63,7 @@ RSpec.describe 'User views releases', :js 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
+ page.within("##{release_v1.tag} .js-assets-list") do
expect(page).to have_css('[data-testid="external-link-indicator"]')
end
end
@@ -69,23 +71,57 @@ RSpec.describe 'User views releases', :js do
end
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)
-
- expect(page).to have_content('Upcoming Release')
+ page.within("##{release_v3.tag}") do
+ expect(page).to have_content('Upcoming Release')
+ 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'
- visit project_releases_path(project)
+ page.within("##{release_v2.tag.parameterize}") do
+ expect(page).to have_content(release_v2.name)
+ expect(page).to have_content(release_v2.tag)
+ end
+ end
+ end
+
+ context 'sorting' do
+ def sort_page(by:, direction:)
+ within '[data-testid="releases-sort"]' do
+ find('.dropdown-toggle').click
+
+ click_button(by, class: 'dropdown-item')
+
+ find('.sorting-direction-button').click if direction == :ascending
+ end
+ end
+
+ shared_examples 'releases sort order' do
+ it "sorts the releases #{description}" do
+ card_titles = page.all('.release-block .card-title', minimum: expected_releases.count)
+
+ card_titles.each_with_index do |title, index|
+ expect(title).to have_content(expected_releases[index].name)
+ end
+ end
+ end
+
+ context "when the page is sorted by the default sort order" do
+ let(:expected_releases) { [release_v3, release_v2, release_v1] }
+
+ it_behaves_like 'releases sort order'
+ end
+
+ context "when the page is sorted by created_at ascending " do
+ let(:expected_releases) { [release_v2, release_v1, release_v3] }
+
+ before do
+ sort_page by: 'Created date', direction: :ascending
+ end
- expect(page).to have_content(release.name)
- expect(page).to have_content(release.tag)
+ it_behaves_like 'releases sort order'
end
end
end
@@ -98,14 +134,14 @@ RSpec.describe 'User views releases', :js do
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)
+ within('.release-block', match: :first) do
+ expect(page).to have_content(release_v3.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)
+ expect(page).not_to have_content(release_v3.name)
+ expect(page).not_to have_content(release_v3.tag)
+ expect(page).not_to have_content(release_v3.commit.short_id)
end
end
end
diff --git a/spec/features/projects/settings/registry_settings_spec.rb b/spec/features/projects/settings/registry_settings_spec.rb
index 4e1b53ffc87..cb333bdb428 100644
--- a/spec/features/projects/settings/registry_settings_spec.rb
+++ b/spec/features/projects/settings/registry_settings_spec.rb
@@ -15,10 +15,10 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
before do
project.update!(container_registry_enabled: container_registry_enabled_on_project)
+ project.container_expiration_policy.update!(enabled: true)
sign_in(user)
stub_container_registry_config(enabled: container_registry_enabled)
- stub_feature_flags(new_variables_ui: false)
end
context 'as owner' do
@@ -33,13 +33,13 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
subject
within '#js-registry-policies' do
- within '.card-body' do
+ within '.gl-card-body' do
select('7 days until tags are automatically removed', from: 'Expiration interval:')
select('Every day', from: 'Expiration schedule:')
select('50 tags per image name', from: 'Number of tags to retain:')
fill_in('Tags with names matching this regex pattern will expire:', with: '.*-production')
end
- submit_button = find('.card-footer .btn.btn-success')
+ submit_button = find('.gl-card-footer .btn.btn-success')
expect(submit_button).not_to be_disabled
submit_button.click
end
@@ -51,10 +51,10 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
subject
within '#js-registry-policies' do
- within '.card-body' do
+ within '.gl-card-body' do
fill_in('Tags with names matching this regex pattern will expire:', with: '*-production')
end
- submit_button = find('.card-footer .btn.btn-success')
+ submit_button = find('.gl-card-footer .btn.btn-success')
expect(submit_button).not_to be_disabled
submit_button.click
end
@@ -85,7 +85,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
within '#js-registry-policies' do
case result
when :available_section
- expect(find('.card-header')).to have_content('Tag expiration policy')
+ expect(find('.gl-card-header')).to have_content('Tag expiration policy')
when :disabled_message
expect(find('.gl-alert-title')).to have_content('Cleanup policy for tags is disabled')
end
diff --git a/spec/features/projects/settings/service_desk_setting_spec.rb b/spec/features/projects/settings/service_desk_setting_spec.rb
index 7856ab1fb4e..59e6f54da2f 100644
--- a/spec/features/projects/settings/service_desk_setting_spec.rb
+++ b/spec/features/projects/settings/service_desk_setting_spec.rb
@@ -28,6 +28,6 @@ RSpec.describe 'Service Desk Setting', :js do
project.reload
expect(project.service_desk_enabled).to be_truthy
expect(project.service_desk_address).to be_present
- expect(find('.incoming-email').value).to eq(project.service_desk_address)
+ expect(find('[data-testid="incoming-email"]').value).to eq(project.service_desk_address)
end
end
diff --git a/spec/features/projects/settings/webhooks_settings_spec.rb b/spec/features/projects/settings/webhooks_settings_spec.rb
index d184f08bd89..528fd58cbe6 100644
--- a/spec/features/projects/settings/webhooks_settings_spec.rb
+++ b/spec/features/projects/settings/webhooks_settings_spec.rb
@@ -45,6 +45,7 @@ RSpec.describe 'Projects > Settings > Webhook Settings' do
expect(page).to have_content('Merge requests events')
expect(page).to have_content('Pipeline events')
expect(page).to have_content('Wiki page events')
+ expect(page).to have_content('Releases events')
end
it 'create webhook' do
diff --git a/spec/features/projects/show/schema_markup_spec.rb b/spec/features/projects/show/schema_markup_spec.rb
new file mode 100644
index 00000000000..e651798af23
--- /dev/null
+++ b/spec/features/projects/show/schema_markup_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Projects > Show > Schema Markup' do
+ let_it_be(:project) { create(:project, :repository, :public, :with_avatar, description: 'foobar', tag_list: 'tag1, tag2') }
+
+ it 'shows SoftwareSourceCode structured markup', :js do
+ visit project_path(project)
+ wait_for_all_requests
+
+ aggregate_failures do
+ expect(page).to have_selector('[itemscope][itemtype="http://schema.org/SoftwareSourceCode"]')
+ expect(page).to have_selector('img[itemprop="image"]')
+ expect(page).to have_selector('[itemprop="name"]', text: project.name)
+ expect(page).to have_selector('[itemprop="identifier"]', text: "Project ID: #{project.id}")
+ expect(page).to have_selector('[itemprop="abstract"]', text: project.description)
+ expect(page).to have_selector('[itemprop="license"]', text: project.repository.license.name)
+ expect(find_all('[itemprop="keywords"]').map(&:text)).to match_array(project.tag_list.map(&:capitalize))
+ expect(page).to have_selector('[itemprop="about"]')
+ end
+ end
+end
diff --git a/spec/features/projects/snippets/create_snippet_spec.rb b/spec/features/projects/snippets/create_snippet_spec.rb
index 28fe0a0b7e1..0ed9e23c7f8 100644
--- a/spec/features/projects/snippets/create_snippet_spec.rb
+++ b/spec/features/projects/snippets/create_snippet_spec.rb
@@ -62,7 +62,7 @@ RSpec.describe 'Projects > Snippets > Create Snippet', :js do
click_button('Create snippet')
wait_for_requests
- link = find('a.no-attachment-icon img[alt="banana_sample"]')['src']
+ link = find('a.no-attachment-icon img.js-lazy-loaded[alt="banana_sample"]')['src']
expect(link).to match(%r{/#{Regexp.escape(project.full_path)}/uploads/\h{32}/banana_sample\.gif\z})
end
diff --git a/spec/features/projects/terraform_spec.rb b/spec/features/projects/terraform_spec.rb
new file mode 100644
index 00000000000..2680dfb2b13
--- /dev/null
+++ b/spec/features/projects/terraform_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Terraform', :js do
+ let_it_be(:project) { create(:project) }
+
+ let(:user) { project.creator }
+
+ before do
+ gitlab_sign_in(user)
+ end
+
+ context 'when user does not have any terraform states and visits index page' do
+ before do
+ visit project_terraform_index_path(project)
+ end
+
+ it 'sees an empty state' do
+ expect(page).to have_content('Get started with Terraform')
+ end
+ end
+
+ context 'when user has a terraform state' do
+ let_it_be(:terraform_state) { create(:terraform_state, :locked, project: project) }
+
+ context 'when user visits the index page' do
+ before do
+ visit project_terraform_index_path(project)
+ end
+
+ it 'displays a tab with states count' do
+ expect(page).to have_content("States #{project.terraform_states.size}")
+ end
+
+ it 'displays a table with terraform states' do
+ expect(page).to have_selector(
+ '[data-testid="terraform-states-table"] tbody tr',
+ count: project.terraform_states.size
+ )
+ end
+
+ it 'displays terraform information' do
+ expect(page).to have_content(terraform_state.name)
+ end
+ end
+ end
+end
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index 6baeb4ce368..9b5f4ca6d48 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -279,7 +279,7 @@ RSpec.describe 'Project' do
end
it 'deletes a project', :sidekiq_might_not_need_inline do
- expect { remove_with_confirm('Delete project', "Delete #{project.full_name}", 'Yes, delete project') }.to change { Project.count }.by(-1)
+ expect { remove_with_confirm('Delete project', project.path, 'Yes, delete project') }.to change { Project.count }.by(-1)
expect(page).to have_content "Project '#{project.full_name}' is in the process of being deleted."
expect(Project.all.count).to be_zero
expect(project.issues).to be_empty
diff --git a/spec/features/read_only_spec.rb b/spec/features/read_only_spec.rb
index eb043d2193a..11686552062 100644
--- a/spec/features/read_only_spec.rb
+++ b/spec/features/read_only_spec.rb
@@ -9,19 +9,19 @@ RSpec.describe 'read-only message' do
sign_in(user)
end
- it 'shows read-only banner when database is read-only' do
- allow(Gitlab::Database).to receive(:read_only?).and_return(true)
+ context 'when database is read-only' do
+ before do
+ allow(Gitlab::Database).to receive(:read_only?).and_return(true)
+ end
- visit root_dashboard_path
-
- expect(page).to have_content('You are on a read-only GitLab instance.')
+ it_behaves_like 'Read-only instance', /You are on a read\-only GitLab instance./
end
- it 'does not show read-only banner when database is able to read-write' do
- allow(Gitlab::Database).to receive(:read_only?).and_return(false)
-
- visit root_dashboard_path
+ context 'when database is in read-write mode' do
+ before do
+ allow(Gitlab::Database).to receive(:read_only?).and_return(false)
+ end
- expect(page).not_to have_content('You are on a read-only GitLab instance.')
+ it_behaves_like 'Read-write instance', /You are on a read\-only GitLab instance./
end
end
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index 6e18de3be7b..9697e10c3d1 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -122,6 +122,19 @@ RSpec.describe 'Runners' do
end
end
+ context 'when multiple runners are configured' do
+ let!(:specific_runner) { create(:ci_runner, :project, projects: [project]) }
+ let!(:specific_runner_2) { create(:ci_runner, :project, projects: [project]) }
+
+ it 'adds pagination to the runner list' do
+ stub_const('Projects::Settings::CiCdController::NUMBER_OF_RUNNERS_PER_PAGE', 1)
+
+ visit project_runners_path(project)
+
+ expect(find('.pagination')).not_to be_nil
+ end
+ end
+
context 'when a specific runner exists in another project' do
let(:another_project) { create(:project) }
let!(:specific_runner) { create(:ci_runner, :project, projects: [another_project]) }
diff --git a/spec/features/search/user_searches_for_code_spec.rb b/spec/features/search/user_searches_for_code_spec.rb
index a88043c98ac..f761bd30baf 100644
--- a/spec/features/search/user_searches_for_code_spec.rb
+++ b/spec/features/search/user_searches_for_code_spec.rb
@@ -28,10 +28,7 @@ RSpec.describe 'User searches for code' do
before do
visit(search_path)
find('.js-search-project-dropdown').click
-
- page.within('.project-filter') do
- click_link(project.full_name)
- end
+ find('[data-testid="project-filter"]').click_link(project.full_name)
end
include_examples 'top right search form'
diff --git a/spec/features/search/user_searches_for_issues_spec.rb b/spec/features/search/user_searches_for_issues_spec.rb
index 900ed35adea..e2ae2738d2f 100644
--- a/spec/features/search/user_searches_for_issues_spec.rb
+++ b/spec/features/search/user_searches_for_issues_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
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, :closed, :confidential, title: 'Bar', project: project) }
+ let!(:issue1) { create(:issue, title: 'issue Foo', project: project, created_at: 1.hour.ago) }
+ let!(:issue2) { create(:issue, :closed, :confidential, title: 'issue Bar', project: project) }
def search_for_issue(search)
fill_in('dashboard_search', with: search)
@@ -67,13 +67,26 @@ RSpec.describe 'User searches for issues', :js do
end
end
+ it 'sorts by created date' do
+ search_for_issue('issue')
+
+ page.within('.results') do
+ expect(page.all('.search-result-row').first).to have_link(issue2.title)
+ expect(page.all('.search-result-row').last).to have_link(issue1.title)
+ end
+
+ find('.reverse-sort-btn').click
+
+ page.within('.results') do
+ expect(page.all('.search-result-row').first).to have_link(issue1.title)
+ expect(page.all('.search-result-row').last).to have_link(issue2.title)
+ end
+ end
+
context 'when on a project page' do
it 'finds an issue' do
find('.js-search-project-dropdown').click
-
- page.within('.project-filter') do
- click_link(project.full_name)
- end
+ find('[data-testid="project-filter"]').click_link(project.full_name)
search_for_issue(issue1.title)
diff --git a/spec/features/search/user_searches_for_merge_requests_spec.rb b/spec/features/search/user_searches_for_merge_requests_spec.rb
index 40583664958..6f8f6303b66 100644
--- a/spec/features/search/user_searches_for_merge_requests_spec.rb
+++ b/spec/features/search/user_searches_for_merge_requests_spec.rb
@@ -31,10 +31,7 @@ RSpec.describe 'User searches for merge requests', :js do
context 'when on a project page' do
it 'finds a merge request' do
find('.js-search-project-dropdown').click
-
- page.within('.project-filter') do
- click_link(project.full_name)
- end
+ find('[data-testid="project-filter"]').click_link(project.full_name)
fill_in('dashboard_search', with: merge_request1.title)
find('.btn-search').click
diff --git a/spec/features/search/user_searches_for_milestones_spec.rb b/spec/features/search/user_searches_for_milestones_spec.rb
index 64e756db180..1a2227db214 100644
--- a/spec/features/search/user_searches_for_milestones_spec.rb
+++ b/spec/features/search/user_searches_for_milestones_spec.rb
@@ -31,10 +31,7 @@ RSpec.describe 'User searches for milestones', :js do
context 'when on a project page' do
it 'finds a milestone' do
find('.js-search-project-dropdown').click
-
- page.within('.project-filter') do
- click_link(project.full_name)
- end
+ find('[data-testid="project-filter"]').click_link(project.full_name)
fill_in('dashboard_search', with: milestone1.title)
find('.btn-search').click
diff --git a/spec/features/search/user_searches_for_wiki_pages_spec.rb b/spec/features/search/user_searches_for_wiki_pages_spec.rb
index fc60b6244d9..6bf1407fd4f 100644
--- a/spec/features/search/user_searches_for_wiki_pages_spec.rb
+++ b/spec/features/search/user_searches_for_wiki_pages_spec.rb
@@ -19,10 +19,7 @@ RSpec.describe 'User searches for wiki pages', :js do
shared_examples 'search wiki blobs' do
it 'finds a page' do
find('.js-search-project-dropdown').click
-
- page.within('.project-filter') do
- click_link(project.full_name)
- end
+ find('[data-testid="project-filter"]').click_link(project.full_name)
fill_in('dashboard_search', with: search_term)
find('.btn-search').click
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 5cbfacf4e48..9296a3f33d4 100644
--- a/spec/features/search/user_uses_header_search_field_spec.rb
+++ b/spec/features/search/user_uses_header_search_field_spec.rb
@@ -5,11 +5,18 @@ require 'spec_helper'
RSpec.describe 'User uses header search field', :js do
include FilteredSearchHelpers
- let(:project) { create(:project) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:developer) { create(:user) }
+
+ let(:user) { reporter }
+
+ before_all do
+ project.add_reporter(reporter)
+ project.add_developer(developer)
+ end
before do
- project.add_reporter(user)
sign_in(user)
end
@@ -34,7 +41,7 @@ RSpec.describe 'User uses header search field', :js do
wait_for_all_requests
end
- it 'shows the category search dropdown' do
+ it 'shows the category search dropdown', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/250285' do
expect(page).to have_selector('.dropdown-header', text: /#{scope_name}/i)
end
end
@@ -44,7 +51,7 @@ RSpec.describe 'User uses header search field', :js do
page.find('#search').click
end
- it 'shows category search dropdown' do
+ it 'shows category search dropdown', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/250285' do
expect(page).to have_selector('.dropdown-header', text: /#{scope_name}/i)
end
@@ -104,7 +111,7 @@ RSpec.describe 'User uses header search field', :js do
let(:scope_name) { 'All GitLab' }
end
- it 'displays search options' do
+ it 'displays search options', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/251076' do
fill_in_search('test')
expect(page).to have_selector(scoped_search_link('test'))
@@ -132,6 +139,10 @@ RSpec.describe 'User uses header search field', :js do
let(:group) { create(:group) }
let(:project) { create(:project, namespace: group) }
+ before do
+ project.add_reporter(user)
+ end
+
include_examples 'search field examples' do
let(:url) { project_path(project) }
let(:scope_name) { project.name }
@@ -159,6 +170,35 @@ RSpec.describe 'User uses header search field', :js do
expect(page).not_to have_selector(scoped_search_link('test', group_id: project.namespace_id))
expect(page).to have_selector(scoped_search_link('test', project_id: project.id))
end
+
+ it 'displays a link to project merge requests' do
+ fill_in_search('Merge')
+
+ within(dashboard_search_options_popup_menu) do
+ expect(page).to have_text('Merge Requests')
+ end
+ end
+
+ it 'does not display a link to project feature flags' do
+ fill_in_search('Feature')
+
+ within(dashboard_search_options_popup_menu) do
+ expect(page).to have_text('"Feature" in all GitLab')
+ expect(page).to have_no_text('Feature Flags')
+ end
+ end
+
+ context 'and user is a developer' do
+ let(:user) { developer }
+
+ it 'displays a link to project feature flags' do
+ fill_in_search('Feature')
+
+ within(dashboard_search_options_popup_menu) do
+ expect(page).to have_text('Feature Flags')
+ end
+ end
+ end
end
end
@@ -217,4 +257,8 @@ RSpec.describe 'User uses header search field', :js do
".dropdown a[href='#{href}']"
end
+
+ def dashboard_search_options_popup_menu
+ "div[data-testid='dashboard-search-options']"
+ end
end
diff --git a/spec/features/search/user_uses_search_filters_spec.rb b/spec/features/search/user_uses_search_filters_spec.rb
index 080cced21c3..bd77e6003e3 100644
--- a/spec/features/search/user_uses_search_filters_spec.rb
+++ b/spec/features/search/user_uses_search_filters_spec.rb
@@ -18,17 +18,17 @@ RSpec.describe 'User uses search filters', :js do
it 'shows group projects' do
visit search_path
- find('.js-search-group-dropdown').click
+ find('[data-testid="group-filter"]').click
wait_for_requests
- page.within('.search-page-form') do
- click_link(group.name)
+ page.within('[data-testid="group-filter"]') do
+ click_on(group.name)
end
- expect(find('.js-search-group-dropdown')).to have_content(group.name)
+ expect(find('[data-testid="group-filter"]')).to have_content(group.name)
- page.within('.project-filter') do
+ page.within('[data-testid="project-filter"]') do
find('.js-search-project-dropdown').click
wait_for_requests
@@ -44,10 +44,11 @@ RSpec.describe 'User uses search filters', :js do
describe 'clear filter button' do
it 'removes Group and Project filters' do
- link = find('[data-testid="group-filter"] .js-search-clear')
- params = CGI.parse(URI.parse(link[:href]).query)
+ find('[data-testid="group-filter"] [data-testid="clear-icon"]').click
+
+ wait_for_requests
- expect(params).not_to include(:group_id, :project_id)
+ expect(page).to have_current_path(search_path(search: "test"))
end
end
end
@@ -57,7 +58,7 @@ RSpec.describe 'User uses search filters', :js do
it 'shows a project' do
visit search_path
- page.within('.project-filter') do
+ page.within('[data-testid="project-filter"]') do
find('.js-search-project-dropdown').click
wait_for_requests
@@ -77,7 +78,7 @@ RSpec.describe 'User uses search filters', :js do
describe 'clear filter button' do
it 'removes Project filters' do
- link = find('.project-filter .js-search-clear')
+ link = find('[data-testid="project-filter"] .js-search-clear')
params = CGI.parse(URI.parse(link[:href]).query)
expect(params).not_to include(:project_id)
diff --git a/spec/features/static_site_editor_spec.rb b/spec/features/static_site_editor_spec.rb
index 03085917d67..a47579582e2 100644
--- a/spec/features/static_site_editor_spec.rb
+++ b/spec/features/static_site_editor_spec.rb
@@ -73,4 +73,44 @@ RSpec.describe 'Static Site Editor' do
expect(node['data-static-site-generator']).to eq('middleman')
end
end
+
+ describe 'Static Site Editor Content Security Policy' do
+ subject { response_headers['Content-Security-Policy'] }
+
+ context 'when no global CSP config exists' do
+ before do
+ expect_next_instance_of(Projects::StaticSiteEditorController) 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 sse_path
+
+ is_expected.to be_blank
+ end
+ end
+
+ context 'when a global CSP config exists' do
+ let_it_be(:cdn_url) { 'https://some-cdn.test' }
+ let_it_be(:youtube_url) { 'https://www.youtube.com' }
+
+ before do
+ csp = ActionDispatch::ContentSecurityPolicy.new do |p|
+ p.frame_src :self, cdn_url
+ end
+
+ expect_next_instance_of(Projects::StaticSiteEditorController) do |controller|
+ expect(controller).to receive(:current_content_security_policy).and_return(csp)
+ end
+ end
+
+ it 'appends youtube to the CSP frame-src policy' do
+ visit sse_path
+
+ is_expected.to eql("frame-src 'self' #{cdn_url} #{youtube_url}")
+ end
+ end
+ end
end
diff --git a/spec/features/uploads/user_uploads_file_to_note_spec.rb b/spec/features/uploads/user_uploads_file_to_note_spec.rb
index 7f55ddc1d64..589cc9f9b02 100644
--- a/spec/features/uploads/user_uploads_file_to_note_spec.rb
+++ b/spec/features/uploads/user_uploads_file_to_note_spec.rb
@@ -58,8 +58,8 @@ RSpec.describe 'User uploads file to note' do
error_text = 'File is too big (0.06MiB). Max filesize: 0.01MiB.'
expect(page).to have_selector('.uploading-error-message', visible: true, text: error_text)
- expect(page).to have_selector('.retry-uploading-link', visible: true, text: 'Try again')
- expect(page).to have_selector('.attach-new-file', visible: true, text: 'attach a new file')
+ expect(page).to have_button('Try again', visible: true)
+ expect(page).to have_button('attach a new file', visible: true)
expect(page).not_to have_button('Attach a file')
end
end
@@ -78,7 +78,7 @@ RSpec.describe 'User uploads file to note' do
click_button 'Comment'
wait_for_requests
- expect(find('a.no-attachment-icon img[alt="dk"]')['src'])
+ expect(find('a.no-attachment-icon img.js-lazy-loaded[alt="dk"]')['src'])
.to match(%r{/#{project.full_path}/uploads/\h{32}/dk\.png$})
end
end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 853c381fe6b..0761c1871d3 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -26,7 +26,6 @@ RSpec.describe 'Login' do
user.reload
expect(user.reset_password_token).not_to be_nil
- find('a[href="#login-pane"]').click
gitlab_sign_in(user)
expect(current_path).to eq root_path
@@ -593,42 +592,95 @@ RSpec.describe 'Login' do
describe 'UI tabs and panes' do
context 'when no defaults are changed' do
- it 'correctly renders tabs and panes' do
- ensure_tab_pane_correctness
+ it 'does not render any tabs' do
+ visit new_user_session_path
+
+ ensure_no_tabs
+ end
+
+ it 'renders link to sign up path' do
+ visit new_user_session_path
+
+ expect(page.body).to have_link('Register now', href: new_user_registration_path)
end
end
context 'when signup is disabled' do
before do
stub_application_setting(signup_enabled: false)
+
+ visit new_user_session_path
end
- it 'correctly renders tabs and panes' do
- ensure_tab_pane_correctness
+ it 'does not render any tabs' do
+ ensure_no_tabs
+ end
+
+ it 'does not render link to sign up path' do
+ visit new_user_session_path
+
+ expect(page.body).not_to have_link('Register now', href: new_user_registration_path)
end
end
context 'when ldap is enabled' do
+ include LdapHelpers
+
+ let(:provider) { 'ldapmain' }
+ let(:ldap_server_config) do
+ {
+ 'label' => 'Main LDAP',
+ 'provider_name' => provider,
+ 'attributes' => {},
+ 'encryption' => 'plain',
+ 'uid' => 'uid',
+ 'base' => 'dc=example,dc=com'
+ }
+ end
+
before do
+ stub_ldap_setting(enabled: true)
+ allow(::Gitlab::Auth::Ldap::Config).to receive_messages(enabled: true, servers: [ldap_server_config])
+ allow(Gitlab::Auth::OAuth::Provider).to receive_messages(providers: [provider.to_sym])
+
+ Ldap::OmniauthCallbacksController.define_providers!
+ Rails.application.reload_routes!
+
+ allow_next_instance_of(ActionDispatch::Routing::RoutesProxy) do |instance|
+ allow(instance).to receive(:"user_#{provider}_omniauth_callback_path")
+ .and_return("/users/auth/#{provider}/callback")
+ end
+
visit new_user_session_path
- allow(page).to receive(:form_based_providers).and_return([:ldapmain])
- allow(page).to receive(:ldap_enabled).and_return(true)
end
it 'correctly renders tabs and panes' do
- ensure_tab_pane_correctness(false)
+ ensure_tab_pane_correctness(['Main LDAP', 'Standard'])
+ end
+
+ it 'renders link to sign up path' do
+ expect(page.body).to have_link('Register now', href: new_user_registration_path)
end
end
context 'when crowd is enabled' do
before do
+ allow(Gitlab::Auth::OAuth::Provider).to receive_messages(providers: [:crowd])
+ stub_application_setting(crowd_enabled: true)
+
+ Ldap::OmniauthCallbacksController.define_providers!
+ Rails.application.reload_routes!
+
+ allow_next_instance_of(ActionDispatch::Routing::RoutesProxy) do |instance|
+ allow(instance).to receive(:user_crowd_omniauth_authorize_path)
+ .and_return("/users/auth/crowd/callback")
+ end
+
visit new_user_session_path
- allow(page).to receive(:form_based_providers).and_return([:crowd])
- allow(page).to receive(:crowd_enabled?).and_return(true)
end
it 'correctly renders tabs and panes' do
- ensure_tab_pane_correctness(false)
+ ensure_tab_pane_correctness(%w(Crowd Standard))
end
end
end
diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb
index 466b7361da9..aebe2cc602d 100644
--- a/spec/features/users/show_spec.rb
+++ b/spec/features/users/show_spec.rb
@@ -5,11 +5,13 @@ require 'spec_helper'
RSpec.describe 'User page' do
include ExternalAuthorizationServiceHelpers
- let(:user) { create(:user, bio: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') }
+ let_it_be(:user) { create(:user, bio: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') }
+
+ subject { visit(user_path(user)) }
context 'with public profile' do
it 'shows all the tabs' do
- visit(user_path(user))
+ subject
page.within '.nav-links' do
expect(page).to have_link('Overview')
@@ -22,14 +24,12 @@ RSpec.describe 'User page' do
end
it 'does not show private profile message' do
- visit(user_path(user))
+ subject
expect(page).not_to have_content("This user has a private profile")
end
context 'work information' do
- subject { visit(user_path(user)) }
-
it 'shows job title and organization details' do
user.update(organization: 'GitLab - work info test', job_title: 'Frontend Engineer')
@@ -57,24 +57,24 @@ RSpec.describe 'User page' do
end
context 'with private profile' do
- let(:user) { create(:user, private_profile: true) }
+ let_it_be(:user) { create(:user, private_profile: true) }
it 'shows no tab' do
- visit(user_path(user))
+ subject
expect(page).to have_css("div.profile-header")
expect(page).not_to have_css("ul.nav-links")
end
it 'shows private profile message' do
- visit(user_path(user))
+ subject
expect(page).to have_content("This user has a private profile")
end
it 'shows own tabs' do
sign_in(user)
- visit(user_path(user))
+ subject
page.within '.nav-links' do
expect(page).to have_link('Overview')
@@ -88,36 +88,36 @@ RSpec.describe 'User page' do
end
context 'with blocked profile' do
- let(:user) { create(:user, state: :blocked) }
+ let_it_be(:user) { create(:user, state: :blocked) }
it 'shows no tab' do
- visit(user_path(user))
+ subject
expect(page).to have_css("div.profile-header")
expect(page).not_to have_css("ul.nav-links")
end
it 'shows blocked message' do
- visit(user_path(user))
+ subject
expect(page).to have_content("This user is blocked")
end
it 'shows user name as blocked' do
- visit(user_path(user))
+ subject
expect(page).to have_css(".cover-title", text: 'Blocked user')
end
it 'shows no additional fields' do
- visit(user_path(user))
+ subject
expect(page).not_to have_css(".profile-user-bio")
expect(page).not_to have_css(".profile-link-holder")
end
it 'shows username' do
- visit(user_path(user))
+ subject
expect(page).to have_content("@#{user.username}")
end
@@ -126,7 +126,7 @@ RSpec.describe 'User page' do
it 'shows the status if there was one' do
create(:user_status, user: user, message: "Working hard!")
- visit(user_path(user))
+ subject
expect(page).to have_content("Working hard!")
end
@@ -135,7 +135,7 @@ RSpec.describe 'User page' do
it 'shows the sign in link' do
stub_application_setting(signup_enabled: false)
- visit(user_path(user))
+ subject
page.within '.navbar-nav' do
expect(page).to have_link('Sign in')
@@ -147,7 +147,7 @@ RSpec.describe 'User page' do
it 'shows the sign in and register link' do
stub_application_setting(signup_enabled: true)
- visit(user_path(user))
+ subject
page.within '.navbar-nav' do
expect(page).to have_link('Sign in / Register')
@@ -157,7 +157,7 @@ RSpec.describe 'User page' do
context 'most recent activity' do
it 'shows the most recent activity' do
- visit(user_path(user))
+ subject
expect(page).to have_content('Most Recent Activity')
end
@@ -168,7 +168,7 @@ RSpec.describe 'User page' do
end
it 'hides the most recent activity' do
- visit(user_path(user))
+ subject
expect(page).not_to have_content('Most Recent Activity')
end
@@ -177,14 +177,14 @@ RSpec.describe 'User page' do
context 'page description' do
before do
- visit(user_path(user))
+ subject
end
it_behaves_like 'page meta description', 'Lorem ipsum dolor sit amet'
end
context 'with a bot user' do
- let(:user) { create(:user, user_type: :security_bot) }
+ let_it_be(:user) { create(:user, user_type: :security_bot) }
describe 'feature flag enabled' do
before do
@@ -192,7 +192,7 @@ RSpec.describe 'User page' do
end
it 'only shows Overview and Activity tabs' do
- visit(user_path(user))
+ subject
page.within '.nav-links' do
expect(page).to have_link('Overview')
@@ -211,7 +211,7 @@ RSpec.describe 'User page' do
end
it 'only shows Overview and Activity tabs' do
- visit(user_path(user))
+ subject
page.within '.nav-links' do
expect(page).to have_link('Overview')
@@ -224,4 +224,24 @@ RSpec.describe 'User page' do
end
end
end
+
+ context 'structured markup' do
+ let_it_be(:user) { create(:user, website_url: 'https://gitlab.com', organization: 'GitLab', job_title: 'Frontend Engineer', email: 'public@example.com', public_email: 'public@example.com', location: 'Country', created_at: Time.now, updated_at: Time.now) }
+
+ it 'shows Person structured markup' do
+ subject
+
+ aggregate_failures do
+ expect(page).to have_selector('[itemscope][itemtype="http://schema.org/Person"]')
+ expect(page).to have_selector('img[itemprop="image"]')
+ expect(page).to have_selector('[itemprop="name"]')
+ expect(page).to have_selector('[itemprop="address"][itemscope][itemtype="https://schema.org/PostalAddress"]')
+ expect(page).to have_selector('[itemprop="addressLocality"]')
+ expect(page).to have_selector('[itemprop="url"]')
+ expect(page).to have_selector('[itemprop="email"]')
+ expect(page).to have_selector('span[itemprop="jobTitle"]')
+ expect(page).to have_selector('span[itemprop="worksFor"]')
+ end
+ end
+ end
end
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index c59121626f0..bfdd1e1bdb7 100644
--- a/spec/features/users/signup_spec.rb
+++ b/spec/features/users/signup_spec.rb
@@ -2,9 +2,51 @@
require 'spec_helper'
-RSpec.shared_examples 'Signup' do
+RSpec.shared_examples 'Signup name validation' do |field, max_length, label|
+ before do
+ visit new_user_registration_path
+ end
+
+ describe "#{field} validation", :js do
+ it "does not show an error border if the user's fullname length is not longer than #{max_length} characters" do
+ fill_in field, with: 'u' * max_length
+
+ expect(find('.name')).not_to have_css '.gl-field-error-outline'
+ end
+
+ it 'shows an error border if the user\'s fullname contains an emoji' do
+ simulate_input("##{field}", 'Ehsan 🦋')
+
+ expect(find('.name')).to have_css '.gl-field-error-outline'
+ end
+
+ it "shows an error border if the user\'s fullname is longer than #{max_length} characters" do
+ fill_in field, with: 'n' * (max_length + 1)
+
+ expect(find('.name')).to have_css '.gl-field-error-outline'
+ end
+
+ it "shows an error message if the user\'s #{label} is longer than #{max_length} characters" do
+ fill_in field, with: 'n' * (max_length + 1)
+
+ expect(page).to have_content("#{label} is too long (maximum is #{max_length} characters).")
+ end
+
+ it 'shows an error message if the username contains emojis' do
+ simulate_input("##{field}", 'Ehsan 🦋')
+
+ expect(page).to have_content("Invalid input, please avoid emojis")
+ end
+ end
+end
+
+RSpec.describe 'Signup' do
include TermsHelper
+ before do
+ stub_application_setting(require_admin_approval_after_user_signup: false)
+ end
+
let(:new_user) { build_stubbed(:user) }
def fill_in_signup_form
@@ -190,6 +232,22 @@ RSpec.shared_examples 'Signup' do
expect(current_path).to eq users_sign_up_welcome_path
end
end
+
+ context 'with required admin approval enabled' do
+ before do
+ stub_application_setting(require_admin_approval_after_user_signup: true)
+ end
+
+ it 'creates the user but does not sign them in' do
+ visit new_user_registration_path
+
+ fill_in_signup_form
+
+ expect { click_button 'Register' }.to change { User.count }.by(1)
+ expect(current_path).to eq new_user_session_path
+ expect(page).to have_content("You have signed up successfully. However, we could not sign you in because your account is awaiting approval from your GitLab administrator")
+ end
+ end
end
context 'with errors' do
@@ -295,64 +353,7 @@ RSpec.shared_examples 'Signup' do
expect(created_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, label|
- before do
- visit new_user_registration_path
- end
-
- describe "#{field} validation", :js do
- it "does not show an error border if the user's fullname length is not longer than #{max_length} characters" do
- fill_in field, with: 'u' * max_length
-
- expect(find('.name')).not_to have_css '.gl-field-error-outline'
- end
-
- it 'shows an error border if the user\'s fullname contains an emoji' do
- simulate_input("##{field}", 'Ehsan 🦋')
-
- expect(find('.name')).to have_css '.gl-field-error-outline'
- end
-
- it "shows an error border if the user\'s fullname is longer than #{max_length} characters" do
- fill_in field, with: 'n' * (max_length + 1)
-
- expect(find('.name')).to have_css '.gl-field-error-outline'
- end
-
- it "shows an error message if the user\'s #{label} is longer than #{max_length} characters" do
- fill_in field, with: 'n' * (max_length + 1)
-
- expect(page).to have_content("#{label} is too long (maximum is #{max_length} characters).")
- end
-
- it 'shows an error message if the username contains emojis' do
- simulate_input("##{field}", 'Ehsan 🦋')
-
- expect(page).to have_content("Invalid input, please avoid emojis")
- end
- end
-end
-
-RSpec.describe 'With original flow' do
- before do
- stub_experiment(signup_flow: false)
- stub_experiment_for_user(signup_flow: false)
- end
-
- it_behaves_like 'Signup'
- it_behaves_like 'Signup name validation', 'new_user_first_name', 127, 'First name'
- it_behaves_like 'Signup name validation', 'new_user_last_name', 127, 'Last name'
-end
-
-RSpec.describe 'With experimental flow' do
- before do
- stub_experiment(signup_flow: true)
- stub_experiment_for_user(signup_flow: true)
- end
- it_behaves_like 'Signup'
it_behaves_like 'Signup name validation', 'new_user_first_name', 127, 'First name'
it_behaves_like 'Signup name validation', 'new_user_last_name', 127, 'Last name'
end
diff --git a/spec/finders/alert_management/http_integrations_finder_spec.rb b/spec/finders/alert_management/http_integrations_finder_spec.rb
new file mode 100644
index 00000000000..d65de2cdbbd
--- /dev/null
+++ b/spec/finders/alert_management/http_integrations_finder_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AlertManagement::HttpIntegrationsFinder do
+ let_it_be(:project) { create(:project) }
+ let_it_be_with_reload(:integration) { create(:alert_management_http_integration, project: project ) }
+ let_it_be(:extra_integration) { create(:alert_management_http_integration, project: project ) }
+ let_it_be(:alt_project_integration) { create(:alert_management_http_integration) }
+
+ let(:params) { {} }
+
+ describe '#execute' do
+ subject(:execute) { described_class.new(project, params).execute }
+
+ context 'empty params' do
+ it { is_expected.to contain_exactly(integration) }
+ end
+
+ context 'endpoint_identifier param given' do
+ let(:params) { { endpoint_identifier: integration.endpoint_identifier } }
+
+ it { is_expected.to contain_exactly(integration) }
+
+ context 'matches an unavailable integration' do
+ let(:params) { { endpoint_identifier: extra_integration.endpoint_identifier } }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'but unknown' do
+ let(:params) { { endpoint_identifier: 'unknown' } }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'but blank' do
+ let(:params) { { endpoint_identifier: nil } }
+
+ it { is_expected.to contain_exactly(integration) }
+ end
+ end
+
+ context 'active param given' do
+ let(:params) { { active: true } }
+
+ it { is_expected.to contain_exactly(integration) }
+
+ context 'when integration is disabled' do
+ before do
+ integration.update!(active: false)
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'but blank' do
+ let(:params) { { active: nil } }
+
+ it { is_expected.to contain_exactly(integration) }
+ end
+ end
+
+ context 'project has no integrations' do
+ subject(:execute) { described_class.new(create(:project), params).execute }
+
+ it { is_expected.to be_empty }
+ end
+ end
+end
diff --git a/spec/finders/ci/commit_statuses_finder_spec.rb b/spec/finders/ci/commit_statuses_finder_spec.rb
new file mode 100644
index 00000000000..1aa9cb12432
--- /dev/null
+++ b/spec/finders/ci/commit_statuses_finder_spec.rb
@@ -0,0 +1,178 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::CommitStatusesFinder, '#execute' do
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:release) { create(:release, project: project) }
+ let_it_be(:user) { create(:user) }
+
+ context 'tag refs' do
+ let_it_be(:tags) { TagsFinder.new(project.repository, {}).execute }
+ let(:subject) { described_class.new(project, project.repository, user, tags).execute }
+
+ context 'no pipelines' do
+ it 'returns nil' do
+ expect(subject).to be_blank
+ end
+ end
+
+ context 'when multiple tags exist' do
+ before do
+ create(:ci_pipeline,
+ project: project,
+ ref: 'v1.1.0',
+ sha: project.commit('v1.1.0').sha,
+ status: :running)
+ create(:ci_pipeline,
+ project: project,
+ ref: 'v1.0.0',
+ sha: project.commit('v1.0.0').sha,
+ status: :success)
+ end
+
+ it 'all relevant commit statuses are received' do
+ expect(subject['v1.1.0'].group).to eq("running")
+ expect(subject['v1.0.0'].group).to eq("success")
+ end
+ end
+
+ context 'when a tag has multiple pipelines' do
+ before do
+ create(:ci_pipeline,
+ project: project,
+ ref: 'v1.0.0',
+ sha: project.commit('v1.0.0').sha,
+ status: :running,
+ created_at: 6.months.ago)
+ create(:ci_pipeline,
+ project: project,
+ ref: 'v1.0.0',
+ sha: project.commit('v1.0.0').sha,
+ status: :success,
+ created_at: 2.months.ago)
+ end
+
+ it 'chooses the latest to determine status' do
+ expect(subject['v1.0.0'].group).to eq("success")
+ end
+ end
+ end
+
+ context 'branch refs' do
+ let(:subject) { described_class.new(project, project.repository, user, branches).execute }
+
+ before do
+ project.add_developer(user)
+ end
+
+ context 'no pipelines' do
+ let(:branches) { BranchesFinder.new(project.repository, {}).execute }
+
+ it 'returns nil' do
+ expect(subject).to be_blank
+ end
+ end
+
+ context 'when a branch has multiple pipelines' do
+ let(:branches) { BranchesFinder.new(project.repository, {}).execute }
+
+ before do
+ sha = project.repository.create_file(user, generate(:branch), 'content', message: 'message', branch_name: 'master')
+ create(:ci_pipeline,
+ project: project,
+ user: user,
+ ref: "master",
+ sha: sha,
+ status: :running,
+ created_at: 6.months.ago)
+ create(:ci_pipeline,
+ project: project,
+ user: user,
+ ref: "master",
+ sha: sha,
+ status: :success,
+ created_at: 2.months.ago)
+ end
+
+ it 'chooses the latest to determine status' do
+ expect(subject["master"].group).to eq("success")
+ end
+ end
+
+ context 'when multiple branches exist' do
+ let(:branches) { BranchesFinder.new(project.repository, {}).execute }
+
+ before do
+ master_sha = project.repository.create_file(user, generate(:branch), 'content', message: 'message', branch_name: 'master')
+ create(:ci_pipeline,
+ project: project,
+ user: user,
+ ref: "master",
+ sha: master_sha,
+ status: :running,
+ created_at: 6.months.ago)
+ test_sha = project.repository.create_file(user, generate(:branch), 'content', message: 'message', branch_name: 'test')
+ create(:ci_pipeline,
+ project: project,
+ user: user,
+ ref: "test",
+ sha: test_sha,
+ status: :success,
+ created_at: 2.months.ago)
+ end
+
+ it 'all relevant commit statuses are received' do
+ expect(subject["master"].group).to eq("running")
+ expect(subject["test"].group).to eq("success")
+ end
+ end
+ end
+
+ context 'CI pipelines visible to' do
+ let_it_be(:tags) { TagsFinder.new(project.repository, {}).execute }
+ let(:subject) { described_class.new(project, project.repository, user, tags).execute }
+
+ before do
+ create(:ci_pipeline,
+ project: project,
+ ref: 'v1.1.0',
+ sha: project.commit('v1.1.0').sha,
+ status: :running)
+ end
+
+ context 'everyone' do
+ it 'returns something' do
+ expect(subject).not_to be_blank
+ end
+ end
+
+ context 'project members only' do
+ before do
+ project.project_feature.update!(builds_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'returns nil' do
+ expect(subject).to be_empty
+ end
+ end
+
+ context 'when not a member of a private project' do
+ let(:private_project) { create(:project, :private, :repository) }
+ let(:private_tags) { TagsFinder.new(private_tags.repository, {}).execute }
+ let(:private_subject) { described_class.new(private_project, private_project.repository, user, tags).execute }
+
+ before do
+ create(:ci_pipeline,
+ project: private_project,
+ ref: 'v1.1.0',
+ sha: private_project.commit('v1.1.0').sha,
+ status: :running)
+ end
+
+ it 'returns nil' do
+ expect(private_subject).to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/finders/ci/jobs_finder_spec.rb b/spec/finders/ci/jobs_finder_spec.rb
index a6a41c36489..4a6585e3f2b 100644
--- a/spec/finders/ci/jobs_finder_spec.rb
+++ b/spec/finders/ci/jobs_finder_spec.rb
@@ -36,135 +36,62 @@ RSpec.describe Ci::JobsFinder, '#execute' do
end
end
- context 'with ci_jobs_finder_refactor ff enabled' do
- before do
- stub_feature_flags(ci_jobs_finder_refactor: true)
- end
-
- 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
+ context 'scope is present' do
+ let(:jobs) { [job_1, job_2, job_3] }
+
+ where(:scope, :index) do
+ [
+ ['pending', 0],
+ ['running', 1],
+ ['finished', 2]
+ ]
end
- context 'scope is an array' do
- let(:jobs) { [job_1, job_2, job_3] }
- let(:params) {{ scope: ['running'] }}
+ with_them do
+ let(:params) { { scope: scope } }
- it 'filters by the job statuses in the scope' do
- expect(subject).to match_array([job_2])
- end
+ it { expect(subject).to match_array([jobs[index]]) }
end
end
- context 'with ci_jobs_finder_refactor ff disabled' do
- before do
- stub_feature_flags(ci_jobs_finder_refactor: false)
- end
-
- context 'scope is present' do
- let(:jobs) { [job_1, job_2, job_3] }
-
- where(:scope, :index) do
- [
- ['pending', 0],
- ['running', 1],
- ['finished', 2]
- ]
- end
+ context 'scope is an array' do
+ let(:jobs) { [job_1, job_2, job_3] }
+ let(:params) {{ scope: ['running'] }}
- with_them do
- let(:params) { { scope: scope } }
-
- it { expect(subject).to match_array([jobs[index]]) }
- end
+ 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 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
+ context 'a project is present' do
+ subject { described_class.new(current_user: user, project: project, params: params).execute }
- 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
+ context 'user has access to the project' do
+ before do
+ project.add_maintainer(user)
end
- context 'without user' do
- let(:user) { nil }
-
- it 'returns no jobs' do
- expect(subject).to be_empty
- end
+ it 'returns jobs for the specified project' do
+ expect(subject).to match_array([job_3])
end
end
- end
-
- 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 }
- 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
+ context 'user has no access to project builds' do
+ before do
+ project.add_guest(user)
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
+ it 'returns no jobs' do
+ expect(subject).to be_empty
end
+ end
- context 'without user' do
- let(:user) { nil }
+ context 'without user' do
+ let(:user) { nil }
- it 'returns no jobs' do
- expect(subject).to be_empty
- end
+ it 'returns no jobs' do
+ expect(subject).to be_empty
end
end
end
diff --git a/spec/finders/environment_names_finder_spec.rb b/spec/finders/environment_names_finder_spec.rb
index 9244e4fb369..fe00c800f0a 100644
--- a/spec/finders/environment_names_finder_spec.rb
+++ b/spec/finders/environment_names_finder_spec.rb
@@ -5,58 +5,178 @@ require 'spec_helper'
RSpec.describe EnvironmentNamesFinder do
describe '#execute' do
let!(:group) { create(:group) }
- let!(:project1) { create(:project, :public, namespace: group) }
- let!(:project2) { create(:project, :private, namespace: group) }
+ let!(:public_project) { create(:project, :public, namespace: group) }
+ let!(:private_project) { create(:project, :private, namespace: group) }
let!(:user) { create(:user) }
before do
- create(:environment, name: 'gstg', project: project1)
- create(:environment, name: 'gprd', project: project1)
- create(:environment, name: 'gprd', project: project2)
- create(:environment, name: 'gcny', project: project2)
+ create(:environment, name: 'gstg', project: public_project)
+ create(:environment, name: 'gprd', project: public_project)
+ create(:environment, name: 'gprd', project: private_project)
+ create(:environment, name: 'gcny', project: private_project)
end
- context 'using a group and a group member' do
- it 'returns environment names for all projects' do
- group.add_developer(user)
+ context 'using a group' do
+ context 'with a group developer' do
+ it 'returns environment names for all projects' do
+ group.add_developer(user)
- names = described_class.new(group, user).execute
+ names = described_class.new(group, user).execute
- expect(names).to eq(%w[gcny gprd gstg])
+ expect(names).to eq(%w[gcny gprd gstg])
+ end
end
- end
- context 'using a group and a guest' do
- it 'returns environment names for all public projects' do
- names = described_class.new(group, user).execute
+ context 'with a group reporter' do
+ it 'returns environment names for all projects' do
+ group.add_reporter(user)
+
+ names = described_class.new(group, user).execute
- expect(names).to eq(%w[gprd gstg])
+ expect(names).to eq(%w[gcny gprd gstg])
+ end
end
- end
- context 'using a public project and a project member' do
- it 'returns all the unique environment names' do
- project1.team.add_developer(user)
+ context 'with a public project reporter' do
+ it 'returns environment names for all public projects' do
+ public_project.add_reporter(user)
+
+ names = described_class.new(group, user).execute
+
+ expect(names).to eq(%w[gprd gstg])
+ end
+ end
+
+ context 'with a private project reporter' do
+ it 'returns environment names for all public projects' do
+ private_project.add_reporter(user)
+
+ names = described_class.new(group, user).execute
+
+ expect(names).to eq(%w[gcny gprd gstg])
+ end
+ end
+
+ context 'with a group guest' do
+ it 'returns environment names for all public projects' do
+ group.add_guest(user)
+
+ names = described_class.new(group, user).execute
- names = described_class.new(project1, user).execute
+ expect(names).to eq(%w[gprd gstg])
+ end
+ end
+
+ context 'with a non-member' do
+ it 'returns environment names for all public projects' do
+ names = described_class.new(group, user).execute
+
+ expect(names).to eq(%w[gprd gstg])
+ end
+ end
+
+ context 'without a user' do
+ it 'returns environment names for all public projects' do
+ names = described_class.new(group).execute
- expect(names).to eq(%w[gprd gstg])
+ expect(names).to eq(%w[gprd gstg])
+ end
end
end
- context 'using a public project and a guest' do
- it 'returns all the unique environment names' do
- names = described_class.new(project1, user).execute
+ context 'using a public project' do
+ context 'with a project developer' do
+ it 'returns all the unique environment names' do
+ public_project.add_developer(user)
+
+ names = described_class.new(public_project, user).execute
- expect(names).to eq(%w[gprd gstg])
+ expect(names).to eq(%w[gprd gstg])
+ end
+ end
+
+ context 'with a project reporter' do
+ it 'returns all the unique environment names' do
+ public_project.add_reporter(user)
+
+ names = described_class.new(public_project, user).execute
+
+ expect(names).to eq(%w[gprd gstg])
+ end
+ end
+
+ context 'with a project guest' do
+ it 'returns all the unique environment names' do
+ public_project.add_guest(user)
+
+ names = described_class.new(public_project, user).execute
+
+ expect(names).to eq(%w[gprd gstg])
+ end
+ end
+
+ context 'with a non-member' do
+ it 'returns all the unique environment names' do
+ names = described_class.new(public_project, user).execute
+
+ expect(names).to eq(%w[gprd gstg])
+ end
+ end
+
+ context 'without a user' do
+ it 'returns all the unique environment names' do
+ names = described_class.new(public_project).execute
+
+ expect(names).to eq(%w[gprd gstg])
+ end
end
end
- context 'using a private project and a guest' do
- it 'returns all the unique environment names' do
- names = described_class.new(project2, user).execute
+ context 'using a private project' do
+ context 'with a project developer' do
+ it 'returns all the unique environment names' do
+ private_project.add_developer(user)
+
+ names = described_class.new(private_project, user).execute
+
+ expect(names).to eq(%w[gcny gprd])
+ end
+ end
+
+ context 'with a project reporter' do
+ it 'returns all the unique environment names' do
+ private_project.add_reporter(user)
+
+ names = described_class.new(private_project, user).execute
+
+ expect(names).to eq(%w[gcny gprd])
+ end
+ end
+
+ context 'with a project guest' do
+ it 'does not return any environment names' do
+ private_project.add_guest(user)
+
+ names = described_class.new(private_project, user).execute
+
+ expect(names).to be_empty
+ end
+ end
+
+ context 'with a non-member' do
+ it 'does not return any environment names' do
+ names = described_class.new(private_project, user).execute
+
+ expect(names).to be_empty
+ end
+ end
+
+ context 'without a user' do
+ it 'does not return any environment names' do
+ names = described_class.new(private_project).execute
- expect(names).to be_empty
+ expect(names).to be_empty
+ end
end
end
end
diff --git a/spec/finders/feature_flags_user_lists_finder_spec.rb b/spec/finders/feature_flags_user_lists_finder_spec.rb
new file mode 100644
index 00000000000..fc904a174d7
--- /dev/null
+++ b/spec/finders/feature_flags_user_lists_finder_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe FeatureFlagsUserListsFinder do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ before_all do
+ project.add_maintainer(user)
+ end
+
+ describe '#execute' do
+ it 'returns user lists' do
+ finder = described_class.new(project, user, {})
+ user_list = create(:operations_feature_flag_user_list, project: project)
+
+ expect(finder.execute).to contain_exactly(user_list)
+ end
+
+ context 'with search' do
+ it 'returns only matching user lists' do
+ create(:operations_feature_flag_user_list, name: 'do not find', project: project)
+ user_list = create(:operations_feature_flag_user_list, name: 'testing', project: project)
+ finder = described_class.new(project, user, { search: "test" })
+
+ expect(finder.execute).to contain_exactly(user_list)
+ end
+ end
+ end
+end
diff --git a/spec/finders/group_descendants_finder_spec.rb b/spec/finders/group_descendants_finder_spec.rb
index 2f9303606b1..b66d0ffce87 100644
--- a/spec/finders/group_descendants_finder_spec.rb
+++ b/spec/finders/group_descendants_finder_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe GroupDescendantsFinder do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
let(:params) { {} }
subject(:finder) do
@@ -129,6 +129,39 @@ RSpec.describe GroupDescendantsFinder do
end
end
+ context 'with shared groups' do
+ let_it_be(:other_group) { create(:group) }
+ let_it_be(:shared_group_link) do
+ create(:group_group_link,
+ shared_group: group,
+ shared_with_group: other_group)
+ end
+
+ context 'without common ancestor' do
+ it { expect(finder.execute).to be_empty }
+ end
+
+ context 'with common ancestor' do
+ let_it_be(:common_ancestor) { create(:group) }
+ let_it_be(:other_group) { create(:group, parent: common_ancestor) }
+ let_it_be(:group) { create(:group, parent: common_ancestor) }
+
+ context 'querying under the common ancestor' do
+ it { expect(finder.execute).to be_empty }
+ end
+
+ context 'querying the common ancestor' do
+ subject(:finder) do
+ described_class.new(current_user: user, parent_group: common_ancestor, params: params)
+ end
+
+ it 'contains shared subgroups' do
+ expect(finder.execute).to contain_exactly(group, other_group)
+ end
+ end
+ end
+ end
+
context 'with nested groups' do
let!(:project) { create(:project, namespace: group) }
let!(:subgroup) { create(:group, :private, parent: group) }
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 21bc03011c3..3c3bf1a8870 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -472,6 +472,10 @@ RSpec.describe IssuesFinder do
it 'returns issues with title and description match for search term' do
expect(issues).to contain_exactly(issue1, issue2)
end
+
+ it 'uses optimizer hints' do
+ expect(issues.to_sql).to match(/BitmapScan/)
+ end
end
context 'filtering by issue term in title' do
@@ -827,6 +831,46 @@ RSpec.describe IssuesFinder do
let(:project_params) { { project_id: project.id } }
end
end
+
+ context 'filtering by due date' do
+ let_it_be(:issue_overdue) { create(:issue, project: project1, due_date: 2.days.ago) }
+ let_it_be(:issue_due_soon) { create(:issue, project: project1, due_date: 2.days.from_now) }
+
+ let(:scope) { 'all' }
+ let(:base_params) { { project_id: project1.id } }
+
+ context 'with param set to no due date' do
+ let(:params) { base_params.merge(due_date: Issue::NoDueDate.name) }
+
+ it 'returns issues with no due date' do
+ expect(issues).to contain_exactly(issue1)
+ end
+ end
+
+ context 'with param set to overdue' do
+ let(:params) { base_params.merge(due_date: Issue::Overdue.name) }
+
+ it 'returns overdue issues' do
+ expect(issues).to contain_exactly(issue_overdue)
+ end
+ end
+
+ context 'with param set to next month and previous two weeks' do
+ let(:params) { base_params.merge(due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name) }
+
+ it 'returns issues from the previous two weeks and next month' do
+ expect(issues).to contain_exactly(issue_overdue, issue_due_soon)
+ end
+ end
+
+ context 'with invalid param' do
+ let(:params) { base_params.merge(due_date: 'foo') }
+
+ it 'returns no issues' do
+ expect(issues).to be_empty
+ end
+ end
+ end
end
describe '#row_count', :request_store do
diff --git a/spec/finders/merge_requests/by_approvals_finder_spec.rb b/spec/finders/merge_requests/by_approvals_finder_spec.rb
index 0e1856879f1..5c56e610c0b 100644
--- a/spec/finders/merge_requests/by_approvals_finder_spec.rb
+++ b/spec/finders/merge_requests/by_approvals_finder_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe MergeRequests::ByApprovalsFinder do
create(:approval, merge_request: mr, user: first_user)
end
end
+
let_it_be(:merge_request_with_both_approvals) do
create(:merge_request).tap do |mr|
create(:approval, merge_request: mr, user: first_user)
diff --git a/spec/finders/packages/group_packages_finder_spec.rb b/spec/finders/packages/group_packages_finder_spec.rb
index 163c920f621..0db69de65a5 100644
--- a/spec/finders/packages/group_packages_finder_spec.rb
+++ b/spec/finders/packages/group_packages_finder_spec.rb
@@ -2,13 +2,16 @@
require 'spec_helper'
RSpec.describe Packages::GroupPackagesFinder do
- let_it_be(:user) { create(:user) }
- let_it_be(:group) { create(:group) }
- let_it_be(:project) { create(:project, namespace: group) }
- let(:another_group) { create(:group) }
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:user) { create(:user) }
+ let_it_be_with_reload(:group) { create(:group) }
+ let_it_be_with_reload(:project) { create(:project, namespace: group, builds_access_level: ProjectFeature::PRIVATE, merge_requests_access_level: ProjectFeature::PRIVATE) }
+
+ let(:add_user_to_group) { true }
before do
- group.add_developer(user)
+ group.add_developer(user) if add_user_to_group
end
describe '#execute' do
@@ -27,16 +30,16 @@ RSpec.describe Packages::GroupPackagesFinder do
end
context 'group has packages' do
- let!(:package1) { create(:maven_package, project: project) }
- let!(:package2) { create(:maven_package, project: project) }
- let!(:package3) { create(:maven_package) }
+ let_it_be(:package1) { create(:maven_package, project: project) }
+ let_it_be(:package2) { create(:maven_package, project: project) }
+ let_it_be(:package3) { create(:maven_package) }
it { is_expected.to match_array([package1, package2]) }
context 'subgroup has packages' do
- let(:subgroup) { create(:group, parent: group) }
- let(:subproject) { create(:project, namespace: subgroup) }
- let!(:package4) { create(:npm_package, project: subproject) }
+ let_it_be_with_reload(:subgroup) { create(:group, parent: group) }
+ let_it_be_with_reload(:subproject) { create(:project, namespace: subgroup, builds_access_level: ProjectFeature::PRIVATE, merge_requests_access_level: ProjectFeature::PRIVATE) }
+ let_it_be(:package4) { create(:npm_package, project: subproject) }
it { is_expected.to match_array([package1, package2, package4]) }
@@ -45,16 +48,87 @@ RSpec.describe Packages::GroupPackagesFinder do
it { is_expected.to match_array([package1, package2]) }
end
+
+ context 'permissions' do
+ let(:add_user_to_group) { false }
+
+ where(:role, :project_visibility, :repository_visibility, :packages_returned) do
+ :anonymous | :public | :enabled | :all
+ :guest | :public | :enabled | :all
+ :reporter | :public | :enabled | :all
+ :developer | :public | :enabled | :all
+ :maintainer | :public | :enabled | :all
+ :anonymous | :public | :private | :none
+ :guest | :public | :private | :all
+ :reporter | :public | :private | :all
+ :developer | :public | :private | :all
+ :maintainer | :public | :private | :all
+ :anonymous | :private | :enabled | :none
+ :guest | :private | :enabled | :none
+ :reporter | :private | :enabled | :all
+ :developer | :private | :enabled | :all
+ :maintainer | :private | :enabled | :all
+ :anonymous | :private | :private | :none
+ :guest | :private | :private | :none
+ :reporter | :private | :private | :all
+ :developer | :private | :private | :all
+ :maintainer | :private | :private | :all
+ end
+
+ with_them do
+ let(:expected_packages) do
+ case packages_returned
+ when :all
+ [package1, package2, package4]
+ when :none
+ []
+ end
+ end
+
+ before do
+ subgroup.update!(visibility: project_visibility.to_s)
+ group.update!(visibility: project_visibility.to_s)
+ project.update!(
+ visibility: project_visibility.to_s,
+ repository_access_level: repository_visibility.to_s
+ )
+ subproject.update!(
+ visibility: project_visibility.to_s,
+ repository_access_level: repository_visibility.to_s
+ )
+
+ unless role == :anonymous
+ project.add_user(user, role)
+ subproject.add_user(user, role)
+ end
+ end
+
+ it { is_expected.to match_array(expected_packages) }
+ end
+ end
+
+ context 'avoid N+1 query' do
+ it 'avoids N+1 database queries' do
+ count = ActiveRecord::QueryRecorder.new { subject }
+ .count
+
+ Packages::Package.package_types.keys.each do |package_type|
+ create("#{package_type}_package", project: create(:project, namespace: subgroup))
+ end
+
+ expect { described_class.new(user, group, params).execute }.not_to exceed_query_limit(count)
+ end
+ end
end
context 'when there are processing packages' do
- let!(:package4) { create(:nuget_package, project: project, name: Packages::Nuget::CreatePackageService::TEMPORARY_PACKAGE_NAME) }
+ let_it_be(:package4) { create(:nuget_package, project: project, name: Packages::Nuget::CreatePackageService::TEMPORARY_PACKAGE_NAME) }
it { is_expected.to match_array([package1, package2]) }
end
context 'does not include packages without version number' do
- let!(:package_without_version) { create(:maven_package, project: project, version: nil) }
+ let_it_be(:package_without_version) { create(:maven_package, project: project, version: nil) }
it { is_expected.not_to include(package_without_version) }
end
@@ -80,7 +154,7 @@ RSpec.describe Packages::GroupPackagesFinder do
end
context 'group has package of all types' do
- package_types.each { |pt| let!("package_#{pt}") { create("#{pt}_package", project: project) } }
+ package_types.each { |pt| let_it_be("package_#{pt}") { create("#{pt}_package", project: project) } }
package_types.each do |package_type|
it_behaves_like 'with package type', package_type
@@ -98,7 +172,7 @@ RSpec.describe Packages::GroupPackagesFinder do
end
context 'package type is nil' do
- let!(:package1) { create(:maven_package, project: project) }
+ let_it_be(:package1) { create(:maven_package, project: project) }
subject { described_class.new(user, group, package_type: nil).execute }
@@ -110,47 +184,5 @@ RSpec.describe Packages::GroupPackagesFinder do
it { expect { subject }.to raise_exception(described_class::InvalidPackageTypeError) }
end
-
- context 'when project is public' do
- let_it_be(:other_user) { create(:user) }
- let(:finder) { described_class.new(other_user, group) }
-
- before do
- project.update!(visibility_level: ProjectFeature::ENABLED)
- end
-
- context 'when packages are public' do
- before do
- project.project_feature.update!(
- builds_access_level: ProjectFeature::PRIVATE,
- merge_requests_access_level: ProjectFeature::PRIVATE,
- repository_access_level: ProjectFeature::ENABLED)
- end
-
- it 'returns group packages' do
- package1 = create(:maven_package, project: project)
- package2 = create(:maven_package, project: project)
- create(:maven_package)
-
- expect(finder.execute).to match_array([package1, package2])
- end
- end
-
- context 'packages are members only' do
- before do
- project.project_feature.update!(
- builds_access_level: ProjectFeature::PRIVATE,
- merge_requests_access_level: ProjectFeature::PRIVATE,
- repository_access_level: ProjectFeature::PRIVATE)
-
- create(:maven_package, project: project)
- create(:maven_package)
- end
-
- it 'filters out the project if the user doesn\'t have permission' do
- expect(finder.execute).to be_empty
- end
- end
- end
end
end
diff --git a/spec/finders/packages/npm/package_finder_spec.rb b/spec/finders/packages/npm/package_finder_spec.rb
index be54b1f8b18..78c23971f92 100644
--- a/spec/finders/packages/npm/package_finder_spec.rb
+++ b/spec/finders/packages/npm/package_finder_spec.rb
@@ -16,6 +16,12 @@ RSpec.describe ::Packages::Npm::PackageFinder do
it { is_expected.to be_empty }
end
+
+ context 'with nil project' do
+ let(:project) { nil }
+
+ it { is_expected.to be_empty }
+ end
end
describe '#find_by_version' do
diff --git a/spec/finders/personal_access_tokens_finder_spec.rb b/spec/finders/personal_access_tokens_finder_spec.rb
index c8913329839..cece80047e1 100644
--- a/spec/finders/personal_access_tokens_finder_spec.rb
+++ b/spec/finders/personal_access_tokens_finder_spec.rb
@@ -62,6 +62,27 @@ RSpec.describe PersonalAccessTokensFinder do
revoked_impersonation_token, expired_impersonation_token)
end
+ describe 'with users' do
+ let(:user2) { create(:user) }
+
+ before do
+ create(:personal_access_token, user: user2)
+ create(:personal_access_token, :expired, user: user2)
+ create(:personal_access_token, :revoked, user: user2)
+ create(:personal_access_token, :impersonation, user: user2)
+ create(:personal_access_token, :expired, :impersonation, user: user2)
+ create(:personal_access_token, :revoked, :impersonation, user: user2)
+
+ params[:users] = [user]
+ end
+
+ it {
+ is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token,
+ revoked_personal_access_token, expired_personal_access_token,
+ revoked_impersonation_token, expired_impersonation_token)
+ }
+ end
+
describe 'with sort order' do
before do
params[:sort] = 'id_asc'
diff --git a/spec/finders/security/jobs_finder_spec.rb b/spec/finders/security/jobs_finder_spec.rb
new file mode 100644
index 00000000000..9badf9c38cf
--- /dev/null
+++ b/spec/finders/security/jobs_finder_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Security::JobsFinder do
+ it 'is an abstract class that does not permit instantiation' do
+ expect { described_class.new(pipeline: nil) }.to raise_error(
+ NotImplementedError,
+ 'This is an abstract class, please instantiate its descendants'
+ )
+ end
+
+ describe '.allowed_job_types' do
+ it 'must be implemented by child classes' do
+ expect { described_class.allowed_job_types }.to raise_error(
+ NotImplementedError,
+ 'allowed_job_types must be overwritten to return an array of job types'
+ )
+ end
+ end
+end
diff --git a/spec/finders/security/license_compliance_jobs_finder_spec.rb b/spec/finders/security/license_compliance_jobs_finder_spec.rb
new file mode 100644
index 00000000000..3066912df12
--- /dev/null
+++ b/spec/finders/security/license_compliance_jobs_finder_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Security::LicenseComplianceJobsFinder do
+ it_behaves_like ::Security::JobsFinder, described_class.allowed_job_types
+
+ describe "#execute" do
+ subject { finder.execute }
+
+ let(:pipeline) { create(:ci_pipeline) }
+ let(:finder) { described_class.new(pipeline: pipeline) }
+
+ let!(:sast_build) { create(:ci_build, :sast, pipeline: pipeline) }
+ let!(:container_scanning_build) { create(:ci_build, :container_scanning, pipeline: pipeline) }
+ let!(:dast_build) { create(:ci_build, :dast, pipeline: pipeline) }
+ let!(:license_scanning_build) { create(:ci_build, :license_scanning, pipeline: pipeline) }
+ let!(:license_management_build) { create(:ci_build, :license_management, pipeline: pipeline) }
+
+ it 'returns only the license_scanning jobs' do
+ is_expected.to contain_exactly(license_scanning_build, license_management_build)
+ end
+ end
+end
diff --git a/spec/finders/security/security_jobs_finder_spec.rb b/spec/finders/security/security_jobs_finder_spec.rb
new file mode 100644
index 00000000000..fa8253b96b5
--- /dev/null
+++ b/spec/finders/security/security_jobs_finder_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Security::SecurityJobsFinder do
+ it_behaves_like ::Security::JobsFinder, described_class.allowed_job_types
+
+ describe "#execute" do
+ let(:pipeline) { create(:ci_pipeline) }
+ let(:finder) { described_class.new(pipeline: pipeline) }
+
+ subject { finder.execute }
+
+ context 'with specific secure job types' do
+ let!(:sast_build) { create(:ci_build, :sast, pipeline: pipeline) }
+ let!(:container_scanning_build) { create(:ci_build, :container_scanning, pipeline: pipeline) }
+ let!(:dast_build) { create(:ci_build, :dast, pipeline: pipeline) }
+ let!(:secret_detection_build) { create(:ci_build, :secret_detection, pipeline: pipeline) }
+
+ let(:finder) { described_class.new(pipeline: pipeline, job_types: [:sast, :container_scanning, :secret_detection]) }
+
+ it 'returns only those requested' do
+ is_expected.to include(sast_build)
+ is_expected.to include(container_scanning_build)
+ is_expected.to include(secret_detection_build)
+
+ is_expected.not_to include(dast_build)
+ end
+ end
+
+ context 'with combination of security jobs and license management jobs' do
+ let!(:sast_build) { create(:ci_build, :sast, pipeline: pipeline) }
+ let!(:container_scanning_build) { create(:ci_build, :container_scanning, pipeline: pipeline) }
+ let!(:dast_build) { create(:ci_build, :dast, pipeline: pipeline) }
+ let!(:secret_detection_build) { create(:ci_build, :secret_detection, pipeline: pipeline) }
+ let!(:license_management_build) { create(:ci_build, :license_management, pipeline: pipeline) }
+
+ it 'returns only the security jobs' do
+ is_expected.to include(sast_build)
+ is_expected.to include(container_scanning_build)
+ is_expected.to include(dast_build)
+ is_expected.to include(secret_detection_build)
+ is_expected.not_to include(license_management_build)
+ end
+ end
+ end
+end
diff --git a/spec/finders/user_groups_counter_spec.rb b/spec/finders/user_groups_counter_spec.rb
new file mode 100644
index 00000000000..49587e6dada
--- /dev/null
+++ b/spec/finders/user_groups_counter_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe UserGroupsCounter do
+ subject { described_class.new(user_ids).execute }
+
+ describe '#execute' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group1) { create(:group) }
+ let_it_be(:group_member1) { create(:group_member, source: group1, user_id: user.id, access_level: Gitlab::Access::OWNER) }
+ let_it_be(:user_ids) { [user.id] }
+
+ it 'returns authorized group count for the user' do
+ expect(subject[user.id]).to eq(1)
+ end
+
+ context 'when request to join group is pending' do
+ let_it_be(:pending_group) { create(:group) }
+ let_it_be(:pending_group_member) { create(:group_member, requested_at: Time.current.utc, source: pending_group, user_id: user.id) }
+
+ it 'does not include pending group in the count' do
+ expect(subject[user.id]).to eq(1)
+ end
+ end
+
+ context 'when user is part of sub group' do
+ let_it_be(:sub_group) { create(:group, parent: create(:group)) }
+ let_it_be(:sub_group_member1) { create(:group_member, source: sub_group, user_id: user.id, access_level: Gitlab::Access::DEVELOPER) }
+
+ it 'includes sub group in the count' do
+ expect(subject[user.id]).to eq(2)
+ end
+ end
+
+ context 'when user is part of namespaced project' do
+ let_it_be(:project) { create(:project, group: create(:group)) }
+ let_it_be(:project_member) { create(:project_member, source: project, user_id: user.id, access_level: Gitlab::Access::REPORTER) }
+
+ it 'includes the project group' do
+ expect(subject[user.id]).to eq(2)
+ end
+ end
+ end
+end
diff --git a/spec/fixtures/api/schemas/entities/test_case.json b/spec/fixtures/api/schemas/entities/test_case.json
index d731d7eed0a..483fa881f8c 100644
--- a/spec/fixtures/api/schemas/entities/test_case.json
+++ b/spec/fixtures/api/schemas/entities/test_case.json
@@ -12,7 +12,13 @@
"execution_time": { "type": "float" },
"system_output": { "type": ["string", "null"] },
"stack_trace": { "type": ["string", "null"] },
- "attachment_url": { "type": ["string", "null"] }
+ "attachment_url": { "type": ["string", "null"] },
+ "recent_failures": {
+ "oneOf": [
+ { "type": "null" },
+ { "$ref": "test_case/recent_failures.json" }
+ ]
+ }
},
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/entities/test_case/recent_failures.json b/spec/fixtures/api/schemas/entities/test_case/recent_failures.json
new file mode 100644
index 00000000000..7a753101472
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/test_case/recent_failures.json
@@ -0,0 +1,12 @@
+{
+ "type": "object",
+ "required": [
+ "count",
+ "base_branch"
+ ],
+ "properties": {
+ "count": { "type": "integer" },
+ "base_branch": { "type": "string" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/environment.json b/spec/fixtures/api/schemas/environment.json
index 7c49b269994..b8c4253056e 100644
--- a/spec/fixtures/api/schemas/environment.json
+++ b/spec/fixtures/api/schemas/environment.json
@@ -16,6 +16,7 @@
],
"properties": {
"id": { "type": "integer" },
+ "global_id": { "type": "string" },
"name": { "type": "string" },
"state": { "type": "string" },
"external_url": { "$ref": "types/nullable_string.json" },
diff --git a/spec/fixtures/api/schemas/graphql/container_repositories.json b/spec/fixtures/api/schemas/graphql/container_repositories.json
new file mode 100644
index 00000000000..8e8982ff8c7
--- /dev/null
+++ b/spec/fixtures/api/schemas/graphql/container_repositories.json
@@ -0,0 +1,12 @@
+{
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": ["node"],
+ "properties": {
+ "node": {
+ "$ref": "./container_repository.json"
+ }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/graphql/container_repository.json b/spec/fixtures/api/schemas/graphql/container_repository.json
new file mode 100644
index 00000000000..e252bedab82
--- /dev/null
+++ b/spec/fixtures/api/schemas/graphql/container_repository.json
@@ -0,0 +1,40 @@
+{
+ "type": "object",
+ "required": ["id", "name", "path", "location", "createdAt", "updatedAt", "tagsCount", "canDelete", "expirationPolicyCleanupStatus"],
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "createdAt": {
+ "type": "string"
+ },
+ "updatedAt": {
+ "type": "string"
+ },
+ "expirationPolicyStartedAt": {
+ "type": ["string", "null"]
+ },
+ "status": {
+ "type": ["string", "null"]
+ },
+ "tagsCount": {
+ "type": "integer"
+ },
+ "canDelete": {
+ "type": "boolean"
+ },
+ "expirationPolicyCleanupStatus": {
+ "type": "string",
+ "enum": ["UNSCHEDULED", "SCHEDULED", "UNFINISHED", "ONGOING"]
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/graphql/container_repository_details.json b/spec/fixtures/api/schemas/graphql/container_repository_details.json
new file mode 100644
index 00000000000..3db91796fc6
--- /dev/null
+++ b/spec/fixtures/api/schemas/graphql/container_repository_details.json
@@ -0,0 +1,49 @@
+{
+ "type": "object",
+ "required": ["tags"],
+ "allOf": [{ "$ref": "./container_repository.json" }],
+ "properties": {
+ "tags": {
+ "type": "object",
+ "required": ["nodes"],
+ "properties": {
+ "nodes": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": ["name", "path", "location", "digest", "revision", "shortRevision", "totalSize", "createdAt", "canDelete"],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "digest": {
+ "type": "string"
+ },
+ "revision": {
+ "type": "string"
+ },
+ "shortRevision": {
+ "type": "string"
+ },
+ "totalSize": {
+ "type": "integer"
+ },
+ "createdAt": {
+ "type": "string"
+ },
+ "canDelete": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/internal/pages/lookup_path.json b/spec/fixtures/api/schemas/internal/pages/lookup_path.json
index b2b3d3f9d0a..9d81ea495f1 100644
--- a/spec/fixtures/api/schemas/internal/pages/lookup_path.json
+++ b/spec/fixtures/api/schemas/internal/pages/lookup_path.json
@@ -14,8 +14,12 @@
"source": { "type": "object",
"required": ["type", "path"],
"properties" : {
- "type": { "type": "string", "enum": ["file"] },
- "path": { "type": "string" }
+ "type": { "type": "string", "enum": ["file", "zip"] },
+ "path": { "type": "string" },
+ "global_id": { "type": "string" },
+ "sha256": { "type": "string" },
+ "file_size": { "type": "integer" },
+ "file_count": { "type": ["integer", "null"] }
},
"additionalProperties": false
},
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/package_files.json b/spec/fixtures/api/schemas/public_api/v4/packages/package_files.json
index f057adba65c..93b6dcde080 100644
--- a/spec/fixtures/api/schemas/public_api/v4/packages/package_files.json
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/package_files.json
@@ -7,7 +7,10 @@
"id": { "type": "integer" },
"package_id": { "type": "integer" },
"file_name": { "type": "string" },
- "file_sha1": { "type": "string" }
+ "file_sha1": { "type": "string" },
+ "pipelines": {
+ "items": { "$ref": "../pipeline.json" }
+ }
}
}
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/package_with_build.json b/spec/fixtures/api/schemas/public_api/v4/packages/package_with_build.json
index de3ef94138e..86b4e205c3e 100644
--- a/spec/fixtures/api/schemas/public_api/v4/packages/package_with_build.json
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/package_with_build.json
@@ -5,6 +5,9 @@
"name": { "type": "string" },
"version": { "type": "string" },
"package_type": { "type": "string" },
- "pipeline": { "$ref": "../pipeline.json" }
+ "pipeline": { "$ref": "../pipeline.json" },
+ "pipelines": {
+ "items": { "$ref": "../pipeline.json" }
+ }
}
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/release.json b/spec/fixtures/api/schemas/public_api/v4/release.json
index 02e23d2732d..69ac383b7fd 100644
--- a/spec/fixtures/api/schemas/public_api/v4/release.json
+++ b/spec/fixtures/api/schemas/public_api/v4/release.json
@@ -21,7 +21,6 @@
},
"commit_path": { "type": "string" },
"tag_path": { "type": "string" },
- "name": { "type": "string" },
"evidences": {
"type": "array",
"items": { "$ref": "release/evidence.json" }
@@ -42,11 +41,8 @@
"additionalProperties": false
},
"_links": {
- "required": ["merge_requests_url", "issues_url"],
"properties": {
- "merge_requests_url": { "type": "string" },
- "issues_url": { "type": "string" },
- "edit_url": { "type": "string"}
+ "edit_url": { "type": "string" }
}
}
},
diff --git a/spec/fixtures/api/schemas/public_api/v4/release/release_for_guest.json b/spec/fixtures/api/schemas/public_api/v4/release/release_for_guest.json
index 1a1e92ac778..058b7b4b4ed 100644
--- a/spec/fixtures/api/schemas/public_api/v4/release/release_for_guest.json
+++ b/spec/fixtures/api/schemas/public_api/v4/release/release_for_guest.json
@@ -26,11 +26,7 @@
"additionalProperties": false
},
"_links": {
- "required": ["merge_requests_url", "issues_url"],
- "properties": {
- "merge_requests_url": { "type": "string" },
- "issues_url": { "type": "string" }
- }
+ "properties": {}
}
},
"additionalProperties": false
diff --git a/spec/fixtures/csv_no_headers.csv b/spec/fixtures/csv_no_headers.csv
new file mode 100644
index 00000000000..364f7e8f1ae
--- /dev/null
+++ b/spec/fixtures/csv_no_headers.csv
@@ -0,0 +1,3 @@
+Issue in 中文,Test description
+"Hello","World"
+"Title with quote""",Description
diff --git a/spec/fixtures/dependency_proxy/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4.gz b/spec/fixtures/dependency_proxy/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4.gz
new file mode 100644
index 00000000000..14043720eaf
--- /dev/null
+++ b/spec/fixtures/dependency_proxy/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4.gz
Binary files differ
diff --git a/spec/fixtures/domain_blacklist.txt b/spec/fixtures/domain_denylist.txt
index baeb11eda9a..baeb11eda9a 100644
--- a/spec/fixtures/domain_blacklist.txt
+++ b/spec/fixtures/domain_denylist.txt
diff --git a/spec/fixtures/junit/junit_with_duplicate_failed_test_names.xml.gz b/spec/fixtures/junit/junit_with_duplicate_failed_test_names.xml.gz
new file mode 100644
index 00000000000..9bcd06759da
--- /dev/null
+++ b/spec/fixtures/junit/junit_with_duplicate_failed_test_names.xml.gz
Binary files differ
diff --git a/spec/fixtures/junit/junit_with_three_failures.xml.gz b/spec/fixtures/junit/junit_with_three_failures.xml.gz
new file mode 100644
index 00000000000..8ea9a9db437
--- /dev/null
+++ b/spec/fixtures/junit/junit_with_three_failures.xml.gz
Binary files differ
diff --git a/spec/fixtures/lib/gitlab/import_export/complex/project.json b/spec/fixtures/lib/gitlab/import_export/complex/project.json
index d88b2ebc83a..637e01bf123 100644
--- a/spec/fixtures/lib/gitlab/import_export/complex/project.json
+++ b/spec/fixtures/lib/gitlab/import_export/complex/project.json
@@ -7211,5 +7211,23 @@
}
]
}
- ]
+ ],
+ "push_rule": {
+ "force_push_regex": "MustContain",
+ "delete_branch_regex": "MustContain",
+ "commit_message_regex": "MustContain",
+ "author_email_regex": "MustContain",
+ "file_name_regex": "MustContain",
+ "branch_name_regex": "MustContain",
+ "commit_message_negative_regex": "MustNotContain",
+ "max_file_size": 1,
+ "deny_delete_tag": true,
+ "member_check": true,
+ "is_sample": true,
+ "prevent_secrets": true,
+ "reject_unsigned_commits": true,
+ "commit_committer_check": true,
+ "regexp_uses_re2": true
+ }
+
}
diff --git a/spec/fixtures/lib/gitlab/import_export/designs/project.json b/spec/fixtures/lib/gitlab/import_export/designs/project.json
index ebc08868d9e..e11b10a1d4c 100644
--- a/spec/fixtures/lib/gitlab/import_export/designs/project.json
+++ b/spec/fixtures/lib/gitlab/import_export/designs/project.json
@@ -98,6 +98,7 @@
"designs":[
{
"id":38,
+ "iid": 1,
"project_id":30,
"issue_id":469,
"filename":"chirrido3.jpg",
@@ -107,6 +108,7 @@
},
{
"id":39,
+ "iid": 2,
"project_id":30,
"issue_id":469,
"filename":"jonathan_richman.jpg",
@@ -116,6 +118,7 @@
},
{
"id":40,
+ "iid": 3,
"project_id":30,
"issue_id":469,
"filename":"mariavontrap.jpeg",
@@ -137,6 +140,7 @@
"event":0,
"design":{
"id":38,
+ "iid": 1,
"project_id":30,
"issue_id":469,
"filename":"chirrido3.jpg"
@@ -156,6 +160,7 @@
"event":1,
"design":{
"id":38,
+ "iid": 1,
"project_id":30,
"issue_id":469,
"filename":"chirrido3.jpg"
@@ -167,6 +172,7 @@
"event":0,
"design":{
"id":39,
+ "iid": 2,
"project_id":30,
"issue_id":469,
"filename":"jonathan_richman.jpg"
@@ -186,6 +192,7 @@
"event":1,
"design":{
"id":38,
+ "iid": 1,
"project_id":30,
"issue_id":469,
"filename":"chirrido3.jpg"
@@ -197,6 +204,7 @@
"event":2,
"design":{
"id":39,
+ "iid": 2,
"project_id":30,
"issue_id":469,
"filename":"jonathan_richman.jpg"
@@ -208,6 +216,7 @@
"event":0,
"design":{
"id":40,
+ "iid": 3,
"project_id":30,
"issue_id":469,
"filename":"mariavontrap.jpeg"
diff --git a/spec/fixtures/packages/debian/README.md b/spec/fixtures/packages/debian/README.md
new file mode 100644
index 00000000000..e398222ce62
--- /dev/null
+++ b/spec/fixtures/packages/debian/README.md
@@ -0,0 +1,21 @@
+# Build a Debian package
+
+Install the build dependencies:
+
+```shell
+sudo apt install dpkg-dev
+```
+
+Go to the `spec/fixtures/packages/debian` directory and clean up old files:
+
+```shell
+cd spec/fixtures/packages/debian
+rm -v *.tar.* *.dsc *.deb *.udeb *.buildinfo *.changes
+```
+
+Go to the package source directory and build:
+
+```shell
+cd sample
+dpkg-buildpackage --no-sign
+```
diff --git a/spec/fixtures/packages/debian/libsample0_1.2.3~alpha2-1_amd64.deb b/spec/fixtures/packages/debian/libsample0_1.2.3~alpha2-1_amd64.deb
deleted file mode 100644
index c6cac69265a..00000000000
--- a/spec/fixtures/packages/debian/libsample0_1.2.3~alpha2-1_amd64.deb
+++ /dev/null
@@ -1 +0,0 @@
-empty
diff --git a/spec/fixtures/packages/debian/libsample0_1.2.3~alpha2_amd64.deb b/spec/fixtures/packages/debian/libsample0_1.2.3~alpha2_amd64.deb
new file mode 100644
index 00000000000..e428f8fcf76
--- /dev/null
+++ b/spec/fixtures/packages/debian/libsample0_1.2.3~alpha2_amd64.deb
Binary files differ
diff --git a/spec/fixtures/packages/debian/sample-dev_1.2.3~binary_amd64.deb b/spec/fixtures/packages/debian/sample-dev_1.2.3~binary_amd64.deb
new file mode 100644
index 00000000000..70567d75265
--- /dev/null
+++ b/spec/fixtures/packages/debian/sample-dev_1.2.3~binary_amd64.deb
Binary files differ
diff --git a/spec/fixtures/packages/debian/sample-udeb_1.2.3~alpha2_amd64.udeb b/spec/fixtures/packages/debian/sample-udeb_1.2.3~alpha2_amd64.udeb
new file mode 100644
index 00000000000..b69692a26d4
--- /dev/null
+++ b/spec/fixtures/packages/debian/sample-udeb_1.2.3~alpha2_amd64.udeb
Binary files differ
diff --git a/spec/fixtures/packages/debian/sample/debian/.gitignore b/spec/fixtures/packages/debian/sample/debian/.gitignore
new file mode 100644
index 00000000000..cb63a746c89
--- /dev/null
+++ b/spec/fixtures/packages/debian/sample/debian/.gitignore
@@ -0,0 +1,8 @@
+.debhelper
+debhelper-build-stamp
+files
+*.substvars
+libsample0
+sample-dev
+sample-udeb
+
diff --git a/spec/fixtures/packages/debian/sample/debian/changelog b/spec/fixtures/packages/debian/sample/debian/changelog
new file mode 100644
index 00000000000..5c20ee43c36
--- /dev/null
+++ b/spec/fixtures/packages/debian/sample/debian/changelog
@@ -0,0 +1,5 @@
+sample (1.2.3~alpha2) unstable; urgency=medium
+
+ * Initial release
+
+ -- John Doe <john.doe@example.com> Thu, 01 Oct 2020 09:35:15 +0200
diff --git a/spec/fixtures/packages/debian/sample/debian/control b/spec/fixtures/packages/debian/sample/debian/control
new file mode 100644
index 00000000000..168d8e20d62
--- /dev/null
+++ b/spec/fixtures/packages/debian/sample/debian/control
@@ -0,0 +1,35 @@
+Source: sample
+Priority: optional
+Maintainer: John Doe <john.doe@example.com>
+Build-Depends: debhelper-compat (= 13)
+Standards-Version: 4.5.0
+Section: libs
+Homepage: https://gitlab.com/
+#Vcs-Browser: https://salsa.debian.org/debian/sample-1.2.3
+#Vcs-Git: https://salsa.debian.org/debian/sample-1.2.3.git
+Rules-Requires-Root: no
+
+Package: sample-dev
+Section: libdevel
+Architecture: any
+Multi-Arch: same
+Depends: libsample0 (= ${binary:Version}), ${misc:Depends}
+Description: Some mostly empty developpement files
+ Used in GitLab tests.
+ .
+ Testing another paragraph.
+
+Package: libsample0
+Architecture: any
+Multi-Arch: same
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Some mostly empty lib
+ Used in GitLab tests.
+ .
+ Testing another paragraph.
+
+Package: sample-udeb
+Package-Type: udeb
+Architecture: any
+Depends: installed-base
+Description: Some mostly empty udeb
diff --git a/spec/fixtures/packages/debian/sample/debian/rules b/spec/fixtures/packages/debian/sample/debian/rules
new file mode 100755
index 00000000000..8ae87843489
--- /dev/null
+++ b/spec/fixtures/packages/debian/sample/debian/rules
@@ -0,0 +1,6 @@
+#!/usr/bin/make -f
+%:
+ dh $@
+override_dh_gencontrol:
+ dh_gencontrol -psample-dev -- -v'1.2.3~binary'
+ dh_gencontrol --remaining-packages
diff --git a/spec/fixtures/packages/debian/sample/debian/source/format b/spec/fixtures/packages/debian/sample/debian/source/format
new file mode 100644
index 00000000000..89ae9db8f88
--- /dev/null
+++ b/spec/fixtures/packages/debian/sample/debian/source/format
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/spec/fixtures/packages/debian/sample_1.2.3~alpha2.dsc b/spec/fixtures/packages/debian/sample_1.2.3~alpha2.dsc
new file mode 100644
index 00000000000..164d4755ed4
--- /dev/null
+++ b/spec/fixtures/packages/debian/sample_1.2.3~alpha2.dsc
@@ -0,0 +1,19 @@
+Format: 3.0 (native)
+Source: sample
+Binary: sample-dev, libsample0, sample-udeb
+Architecture: any
+Version: 1.2.3~alpha2
+Maintainer: John Doe <john.doe@example.com>
+Homepage: https://gitlab.com/
+Standards-Version: 4.5.0
+Build-Depends: debhelper-compat (= 13)
+Package-List:
+ libsample0 deb libs optional arch=any
+ sample-dev deb libdevel optional arch=any
+ sample-udeb udeb libs optional arch=any
+Checksums-Sha1:
+ 5f8bba5574eb01ac3b1f5e2988e8c29307788236 864 sample_1.2.3~alpha2.tar.xz
+Checksums-Sha256:
+ b5a599e88e7cbdda3bde808160a21ba1dd1ec76b2ec8d4912aae769648d68362 864 sample_1.2.3~alpha2.tar.xz
+Files:
+ d79b34f58f61ff4ad696d9bd0b8daa68 864 sample_1.2.3~alpha2.tar.xz
diff --git a/spec/fixtures/packages/debian/sample_1.2.3~alpha2.tar.xz b/spec/fixtures/packages/debian/sample_1.2.3~alpha2.tar.xz
new file mode 100644
index 00000000000..da70fd2094f
--- /dev/null
+++ b/spec/fixtures/packages/debian/sample_1.2.3~alpha2.tar.xz
Binary files differ
diff --git a/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.buildinfo b/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.buildinfo
new file mode 100644
index 00000000000..dd63727ba31
--- /dev/null
+++ b/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.buildinfo
@@ -0,0 +1,180 @@
+Format: 1.0
+Source: sample
+Binary: libsample0 sample-dev sample-udeb
+Architecture: amd64 source
+Version: 1.2.3~alpha2
+Checksums-Md5:
+ 3b0817804f669e16cdefac583ad88f0e 671 sample_1.2.3~alpha2.dsc
+ fb0842b21adc44207996296fe14439dd 1124 libsample0_1.2.3~alpha2_amd64.deb
+ d2afbd28e4d74430d22f9504e18bfdf5 1164 sample-dev_1.2.3~binary_amd64.deb
+ 72b1dd7d98229e2fb0355feda1d3a165 736 sample-udeb_1.2.3~alpha2_amd64.udeb
+Checksums-Sha1:
+ 32ecbd674f0bfd310df68484d87752490685a8d6 671 sample_1.2.3~alpha2.dsc
+ 5248b95600e85bfe7f63c0dfce330a75f5777366 1124 libsample0_1.2.3~alpha2_amd64.deb
+ f81e4f66c8c6bb899653a3340c157965ee69634f 1164 sample-dev_1.2.3~binary_amd64.deb
+ e42e8f2fe04ed1bb73b44a187674480d0e49dcba 736 sample-udeb_1.2.3~alpha2_amd64.udeb
+Checksums-Sha256:
+ 844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba 671 sample_1.2.3~alpha2.dsc
+ 1c383a525bfcba619c7305ccd106d61db501a6bbaf0003bf8d0c429fbdb7fcc1 1124 libsample0_1.2.3~alpha2_amd64.deb
+ 9fbeee2191ce4dab5288fad5ecac1bd369f58fef9a992a880eadf0caf25f086d 1164 sample-dev_1.2.3~binary_amd64.deb
+ 2b0c152b3ab4cc07663350424de972c2b7621d69fe6df2e0b94308a191e4632f 736 sample-udeb_1.2.3~alpha2_amd64.udeb
+Build-Origin: Debian
+Build-Architecture: amd64
+Build-Date: Thu, 08 Oct 2020 15:15:24 +0200
+Build-Tainted-By:
+ merged-usr-via-symlinks
+ usr-local-has-includes
+ usr-local-has-libraries
+ usr-local-has-programs
+Installed-Build-Depends:
+ autoconf (= 2.69-11.1),
+ automake (= 1:1.16.2-4),
+ autopoint (= 0.19.8.1-10),
+ autotools-dev (= 20180224.1),
+ base-files (= 11),
+ base-passwd (= 3.5.47),
+ bash (= 5.0-7),
+ binutils (= 2.35.1-1),
+ binutils-common (= 2.35.1-1),
+ binutils-x86-64-linux-gnu (= 2.35.1-1),
+ bsdextrautils (= 2.36-3+b1),
+ bsdmainutils (= 12.1.7),
+ bsdutils (= 1:2.36-3+b1),
+ build-essential (= 12.8),
+ bzip2 (= 1.0.8-4),
+ calendar (= 12.1.7),
+ coreutils (= 8.32-4+b1),
+ cpp (= 4:10.2.0-1),
+ cpp-10 (= 10.2.0-9),
+ cpp-9 (= 9.3.0-18),
+ dash (= 0.5.10.2-7),
+ debconf (= 1.5.74),
+ debhelper (= 13.2.1),
+ debianutils (= 4.11.2),
+ dh-autoreconf (= 19),
+ dh-strip-nondeterminism (= 1.9.0-1),
+ diffutils (= 1:3.7-3),
+ dpkg (= 1.20.5),
+ dpkg-dev (= 1.20.5),
+ dwz (= 0.13-5),
+ file (= 1:5.38-5),
+ findutils (= 4.7.0-1),
+ g++ (= 4:10.2.0-1),
+ g++-10 (= 10.2.0-9),
+ gcc (= 4:10.2.0-1),
+ gcc-10 (= 10.2.0-9),
+ gcc-10-base (= 10.2.0-9),
+ gcc-9 (= 9.3.0-18),
+ gcc-9-base (= 9.3.0-18),
+ gettext (= 0.19.8.1-10),
+ gettext-base (= 0.19.8.1-10),
+ grep (= 3.4-1),
+ groff-base (= 1.22.4-5),
+ gzip (= 1.10-2),
+ hostname (= 3.23),
+ init-system-helpers (= 1.58),
+ intltool-debian (= 0.35.0+20060710.5),
+ libacl1 (= 2.2.53-8),
+ libarchive-zip-perl (= 1.68-1),
+ libasan5 (= 9.3.0-18),
+ libasan6 (= 10.2.0-9),
+ libatomic1 (= 10.2.0-9),
+ libattr1 (= 1:2.4.48-5),
+ libaudit-common (= 1:2.8.5-3),
+ libaudit1 (= 1:2.8.5-3+b1),
+ libbinutils (= 2.35.1-1),
+ libblkid1 (= 2.36-3+b1),
+ libbsd0 (= 0.10.0-1),
+ libbz2-1.0 (= 1.0.8-4),
+ libc-bin (= 2.31-3),
+ libc-dev-bin (= 2.31-3),
+ libc6 (= 2.31-3),
+ libc6-dev (= 2.31-3),
+ libcap-ng0 (= 0.7.9-2.2),
+ libcc1-0 (= 10.2.0-9),
+ libcroco3 (= 0.6.13-1),
+ libcrypt-dev (= 1:4.4.17-1),
+ libcrypt1 (= 1:4.4.17-1),
+ libctf-nobfd0 (= 2.35.1-1),
+ libctf0 (= 2.35.1-1),
+ libdb5.3 (= 5.3.28+dfsg1-0.6),
+ libdebconfclient0 (= 0.254),
+ libdebhelper-perl (= 13.2.1),
+ libdpkg-perl (= 1.20.5),
+ libelf1 (= 0.181-1),
+ libffi7 (= 3.3-4),
+ libfile-stripnondeterminism-perl (= 1.9.0-1),
+ libgcc-10-dev (= 10.2.0-9),
+ libgcc-9-dev (= 9.3.0-18),
+ libgcc-s1 (= 10.2.0-9),
+ libgcrypt20 (= 1.8.6-2),
+ libgdbm-compat4 (= 1.18.1-5.1),
+ libgdbm6 (= 1.18.1-5.1),
+ libglib2.0-0 (= 2.66.0-2),
+ libgmp10 (= 2:6.2.0+dfsg-6),
+ libgomp1 (= 10.2.0-9),
+ libgpg-error0 (= 1.38-2),
+ libicu67 (= 67.1-4),
+ libisl22 (= 0.22.1-1),
+ libitm1 (= 10.2.0-9),
+ liblsan0 (= 10.2.0-9),
+ liblz4-1 (= 1.9.2-2),
+ liblzma5 (= 5.2.4-1+b1),
+ libmagic-mgc (= 1:5.38-5),
+ libmagic1 (= 1:5.38-5),
+ libmount1 (= 2.36-3+b1),
+ libmpc3 (= 1.2.0-1),
+ libmpfr6 (= 4.1.0-3),
+ libpam-modules (= 1.3.1-5),
+ libpam-modules-bin (= 1.3.1-5),
+ libpam-runtime (= 1.3.1-5),
+ libpam0g (= 1.3.1-5),
+ libpcre2-8-0 (= 10.34-7),
+ libpcre3 (= 2:8.39-13),
+ libperl5.30 (= 5.30.3-4),
+ libpipeline1 (= 1.5.3-1),
+ libquadmath0 (= 10.2.0-9),
+ libseccomp2 (= 2.4.4-1),
+ libselinux1 (= 3.1-2),
+ libsigsegv2 (= 2.12-2),
+ libsmartcols1 (= 2.36-3+b1),
+ libstdc++-10-dev (= 10.2.0-9),
+ libstdc++6 (= 10.2.0-9),
+ libsub-override-perl (= 0.09-2),
+ libsystemd0 (= 246.6-1),
+ libtinfo6 (= 6.2+20200918-1),
+ libtool (= 2.4.6-14),
+ libtsan0 (= 10.2.0-9),
+ libubsan1 (= 10.2.0-9),
+ libuchardet0 (= 0.0.7-1),
+ libudev1 (= 246.6-1),
+ libunistring2 (= 0.9.10-4),
+ libuuid1 (= 2.36-3+b1),
+ libxml2 (= 2.9.10+dfsg-6),
+ libzstd1 (= 1.4.5+dfsg-4),
+ linux-libc-dev (= 5.8.10-1),
+ login (= 1:4.8.1-1),
+ lsb-base (= 11.1.0),
+ m4 (= 1.4.18-4),
+ make (= 4.3-4),
+ man-db (= 2.9.3-2),
+ mawk (= 1.3.4.20200120-2),
+ ncal (= 12.1.7),
+ ncurses-base (= 6.2+20200918-1),
+ ncurses-bin (= 6.2+20200918-1),
+ patch (= 2.7.6-6),
+ perl (= 5.30.3-4),
+ perl-base (= 5.30.3-4),
+ perl-modules-5.30 (= 5.30.3-4),
+ po-debconf (= 1.0.21),
+ sed (= 4.7-1),
+ sensible-utils (= 0.0.12+nmu1),
+ sysvinit-utils (= 2.96-5),
+ tar (= 1.30+dfsg-7),
+ util-linux (= 2.36-3+b1),
+ xz-utils (= 5.2.4-1+b1),
+ zlib1g (= 1:1.2.11.dfsg-2)
+Environment:
+ DEB_BUILD_OPTIONS="parallel=8"
+ LANG="fr_FR.UTF-8"
+ SOURCE_DATE_EPOCH="1601537715"
diff --git a/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.changes b/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.changes
new file mode 100644
index 00000000000..7a6bb78eb78
--- /dev/null
+++ b/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.changes
@@ -0,0 +1,39 @@
+Format: 1.8
+Date: Thu, 01 Oct 2020 09:35:15 +0200
+Source: sample
+Binary: libsample0 sample-dev sample-udeb
+Architecture: source amd64
+Version: 1.2.3~alpha2
+Distribution: unstable
+Urgency: medium
+Maintainer: John Doe <john.doe@example.com>
+Changed-By: John Doe <john.doe@example.com>
+Description:
+ libsample0 - Some mostly empty lib
+ sample-dev - Some mostly empty developpement files
+ sample-udeb - Some mostly empty udeb (udeb)
+Changes:
+ sample (1.2.3~alpha2) unstable; urgency=medium
+ .
+ * Initial release
+Checksums-Sha1:
+ 32ecbd674f0bfd310df68484d87752490685a8d6 671 sample_1.2.3~alpha2.dsc
+ 5f8bba5574eb01ac3b1f5e2988e8c29307788236 864 sample_1.2.3~alpha2.tar.xz
+ 5248b95600e85bfe7f63c0dfce330a75f5777366 1124 libsample0_1.2.3~alpha2_amd64.deb
+ f81e4f66c8c6bb899653a3340c157965ee69634f 1164 sample-dev_1.2.3~binary_amd64.deb
+ e42e8f2fe04ed1bb73b44a187674480d0e49dcba 736 sample-udeb_1.2.3~alpha2_amd64.udeb
+ 0d47e899f3cc67a2253a4629456ff927e0db5c60 5280 sample_1.2.3~alpha2_amd64.buildinfo
+Checksums-Sha256:
+ 844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba 671 sample_1.2.3~alpha2.dsc
+ b5a599e88e7cbdda3bde808160a21ba1dd1ec76b2ec8d4912aae769648d68362 864 sample_1.2.3~alpha2.tar.xz
+ 1c383a525bfcba619c7305ccd106d61db501a6bbaf0003bf8d0c429fbdb7fcc1 1124 libsample0_1.2.3~alpha2_amd64.deb
+ 9fbeee2191ce4dab5288fad5ecac1bd369f58fef9a992a880eadf0caf25f086d 1164 sample-dev_1.2.3~binary_amd64.deb
+ 2b0c152b3ab4cc07663350424de972c2b7621d69fe6df2e0b94308a191e4632f 736 sample-udeb_1.2.3~alpha2_amd64.udeb
+ f9900d3c94e94b329232668dcbef3dba2d96c07147b15b6dc0533452e4dd8a43 5280 sample_1.2.3~alpha2_amd64.buildinfo
+Files:
+ 3b0817804f669e16cdefac583ad88f0e 671 libs optional sample_1.2.3~alpha2.dsc
+ d79b34f58f61ff4ad696d9bd0b8daa68 864 libs optional sample_1.2.3~alpha2.tar.xz
+ fb0842b21adc44207996296fe14439dd 1124 libs optional libsample0_1.2.3~alpha2_amd64.deb
+ d2afbd28e4d74430d22f9504e18bfdf5 1164 libdevel optional sample-dev_1.2.3~binary_amd64.deb
+ 72b1dd7d98229e2fb0355feda1d3a165 736 libs optional sample-udeb_1.2.3~alpha2_amd64.udeb
+ 4e085dd67c120ca967ec314f65770a42 5280 libs optional sample_1.2.3~alpha2_amd64.buildinfo
diff --git a/spec/fixtures/whats_new/05.yml b/spec/fixtures/whats_new/05.yml
deleted file mode 100644
index 5b8939a2bc6..00000000000
--- a/spec/fixtures/whats_new/05.yml
+++ /dev/null
@@ -1,2 +0,0 @@
----
-- title: bright and sunshinin' day
diff --git a/spec/fixtures/whats_new/01.yml b/spec/fixtures/whats_new/20201225_01_01.yml
index 06db95be44f..06db95be44f 100644
--- a/spec/fixtures/whats_new/01.yml
+++ b/spec/fixtures/whats_new/20201225_01_01.yml
diff --git a/spec/fixtures/whats_new/02.yml b/spec/fixtures/whats_new/20201225_01_02.yml
index 91b0bd7036e..91b0bd7036e 100644
--- a/spec/fixtures/whats_new/02.yml
+++ b/spec/fixtures/whats_new/20201225_01_02.yml
diff --git a/spec/fixtures/whats_new/20201225_01_05.yml b/spec/fixtures/whats_new/20201225_01_05.yml
new file mode 100644
index 00000000000..7c95e386f00
--- /dev/null
+++ b/spec/fixtures/whats_new/20201225_01_05.yml
@@ -0,0 +1,3 @@
+---
+- title: bright and sunshinin' day
+ release: '01.05'
diff --git a/spec/frontend/__mocks__/@gitlab/ui.js b/spec/frontend/__mocks__/@gitlab/ui.js
index 237f8b408f5..94e3f624c25 100644
--- a/spec/frontend/__mocks__/@gitlab/ui.js
+++ b/spec/frontend/__mocks__/@gitlab/ui.js
@@ -18,7 +18,7 @@ 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'],
+ props: ['target', 'id', 'triggers', 'placement', 'container', 'boundary', 'disabled', 'show'],
render(h) {
return h(
'div',
@@ -38,8 +38,16 @@ jest.mock('@gitlab/ui/dist/components/base/popover/popover.js', () => ({
required: false,
default: () => [],
},
+ ...Object.fromEntries(['target', 'triggers', 'placement'].map(prop => [prop, {}])),
},
render(h) {
- return h('div', this.$attrs, Object.keys(this.$slots).map(s => this.$slots[s]));
+ return h(
+ 'div',
+ {
+ class: 'gl-popover',
+ ...this.$attrs,
+ },
+ Object.keys(this.$slots).map(s => this.$slots[s]),
+ );
},
}));
diff --git a/spec/frontend/access_tokens/components/__snapshots__/expires_at_field_spec.js.snap b/spec/frontend/access_tokens/components/__snapshots__/expires_at_field_spec.js.snap
new file mode 100644
index 00000000000..33c29cea6d8
--- /dev/null
+++ b/spec/frontend/access_tokens/components/__snapshots__/expires_at_field_spec.js.snap
@@ -0,0 +1,24 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`~/access_tokens/components/expires_at_field should render datepicker with input info 1`] = `
+<gl-datepicker-stub
+ ariallabel=""
+ autocomplete=""
+ container=""
+ displayfield="true"
+ firstday="0"
+ mindate="Mon Jul 06 2020 00:00:00 GMT+0000 (Greenwich Mean Time)"
+ placeholder="YYYY-MM-DD"
+ theme=""
+>
+ <gl-form-input-stub
+ autocomplete="off"
+ class="datepicker gl-datepicker-input"
+ data-qa-selector="expiry_date_field"
+ id="personal_access_token_expires_at"
+ inputmode="none"
+ name="personal_access_token[expires_at]"
+ placeholder="YYYY-MM-DD"
+ />
+</gl-datepicker-stub>
+`;
diff --git a/spec/frontend/access_tokens/components/expires_at_field_spec.js b/spec/frontend/access_tokens/components/expires_at_field_spec.js
new file mode 100644
index 00000000000..cd235d0afa5
--- /dev/null
+++ b/spec/frontend/access_tokens/components/expires_at_field_spec.js
@@ -0,0 +1,34 @@
+import { shallowMount } from '@vue/test-utils';
+import { useFakeDate } from 'helpers/fake_date';
+import ExpiresAtField from '~/access_tokens/components/expires_at_field.vue';
+
+describe('~/access_tokens/components/expires_at_field', () => {
+ useFakeDate();
+
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(ExpiresAtField, {
+ propsData: {
+ inputAttrs: {
+ id: 'personal_access_token_expires_at',
+ name: 'personal_access_token[expires_at]',
+ placeholder: 'YYYY-MM-DD',
+ },
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should render datepicker with input info', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/alert_management/components/alert_details_spec.js b/spec/frontend/alert_management/components/alert_details_spec.js
index f3ebdfc5cc2..e2d913398f9 100644
--- a/spec/frontend/alert_management/components/alert_details_spec.js
+++ b/spec/frontend/alert_management/components/alert_details_spec.js
@@ -20,11 +20,7 @@ const environmentName = 'Production';
const environmentPath = '/fake/path';
describe('AlertDetails', () => {
- let environmentData = {
- name: environmentName,
- path: environmentPath,
- };
- let glFeatures = { exposeEnvironmentPathInAlertDetails: false };
+ let environmentData = { name: environmentName, path: environmentPath };
let mock;
let wrapper;
const projectPath = 'root/alerts';
@@ -40,7 +36,6 @@ describe('AlertDetails', () => {
projectPath,
projectIssuesPath,
projectId,
- glFeatures,
},
data() {
return {
@@ -159,33 +154,21 @@ describe('AlertDetails', () => {
});
describe('environment fields', () => {
- describe('when exposeEnvironmentPathInAlertDetails is disabled', () => {
- beforeEach(mountComponent);
+ it('should show the environment name with a link to the path', () => {
+ mountComponent();
+ const path = findEnvironmentPath();
- it('should not show the environment', () => {
- expect(findEnvironmentName().exists()).toBe(false);
- expect(findEnvironmentPath().exists()).toBe(false);
- });
+ expect(findEnvironmentName().exists()).toBe(false);
+ expect(path.text()).toBe(environmentName);
+ expect(path.attributes('href')).toBe(environmentPath);
});
- describe('when exposeEnvironmentPathInAlertDetails is enabled', () => {
- beforeEach(() => {
- glFeatures = { exposeEnvironmentPathInAlertDetails: true };
- mountComponent();
- });
-
- it('should show the environment name with link to path', () => {
- expect(findEnvironmentName().exists()).toBe(false);
- expect(findEnvironmentPath().text()).toBe(environmentName);
- expect(findEnvironmentPath().attributes('href')).toBe(environmentPath);
- });
+ it('should only show the environment name if the path is not provided', () => {
+ environmentData = { name: environmentName, path: null };
+ mountComponent();
- it('should only show the environment name if the path is not provided', () => {
- environmentData = { name: environmentName, path: null };
- mountComponent();
- expect(findEnvironmentPath().exists()).toBe(false);
- expect(findEnvironmentName().text()).toBe(environmentName);
- });
+ expect(findEnvironmentPath().exists()).toBe(false);
+ expect(findEnvironmentName().text()).toBe(environmentName);
});
});
@@ -195,6 +178,7 @@ describe('AlertDetails', () => {
mountComponent({
data: { alert: { ...mockAlert, issueIid }, sidebarStatus: false },
});
+
expect(findViewIncidentBtn().exists()).toBe(true);
expect(findViewIncidentBtn().attributes('href')).toBe(
joinPaths(projectIssuesPath, issueIid),
@@ -220,8 +204,8 @@ describe('AlertDetails', () => {
jest
.spyOn(wrapper.vm.$apollo, 'mutate')
.mockResolvedValue({ data: { createAlertIssue: { issue: { iid: issueIid } } } });
-
findCreateIncidentBtn().trigger('click');
+
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: createIssueMutation,
variables: {
@@ -251,6 +235,7 @@ describe('AlertDetails', () => {
beforeEach(() => {
mountComponent({ data: { alert: mockAlert } });
});
+
it('should display a table of raw alert details data', () => {
expect(findDetailsTable().exists()).toBe(true);
});
diff --git a/spec/frontend/alert_settings/__snapshots__/alert_settings_form_spec.js.snap b/spec/frontend/alert_settings/__snapshots__/alert_settings_form_spec.js.snap
deleted file mode 100644
index 5800b160efe..00000000000
--- a/spec/frontend/alert_settings/__snapshots__/alert_settings_form_spec.js.snap
+++ /dev/null
@@ -1,50 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`AlertsSettingsForm with default values renders the initial template 1`] = `
-"<div>
- <integrations-list-stub integrations=\\"[object Object],[object Object]\\"></integrations-list-stub>
- <gl-form-stub>
- <h5 class=\\"gl-font-lg gl-my-5\\">Add new integrations</h5>
- <!---->
- <div data-testid=\\"alert-settings-description\\">
- <p>
- <gl-sprintf-stub message=\\"You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page.\\"></gl-sprintf-stub>
- </p>
- <p>
- <gl-sprintf-stub message=\\"Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.\\"></gl-sprintf-stub>
- </p>
- </div>
- <gl-form-group-stub label-for=\\"integration-type\\" label=\\"Integration\\">
- <gl-form-select-stub id=\\"integration-type\\" options=\\"[object Object],[object Object],[object Object]\\" data-testid=\\"alert-settings-select\\" value=\\"generic\\"></gl-form-select-stub> <span class=\\"gl-text-gray-500\\"><gl-sprintf-stub message=\\"Learn more about our improvements for %{linkStart}integrations%{linkEnd}\\"></gl-sprintf-stub></span>
- </gl-form-group-stub>
- <gl-form-group-stub label=\\"Active\\" label-for=\\"activated\\">
- <toggle-button-stub id=\\"activated\\"></toggle-button-stub>
- </gl-form-group-stub>
- <!---->
- <gl-form-group-stub label=\\"Webhook URL\\" label-for=\\"url\\">
- <gl-form-input-group-stub value=\\"/alerts/notify.json\\" predefinedoptions=\\"[object Object]\\" id=\\"url\\" readonly=\\"\\"></gl-form-input-group-stub> <span class=\\"gl-text-gray-500\\">
-
- </span>
- </gl-form-group-stub>
- <gl-form-group-stub label=\\"Authorization key\\" label-for=\\"authorization-key\\">
- <gl-form-input-group-stub value=\\"abcedfg123\\" predefinedoptions=\\"[object Object]\\" id=\\"authorization-key\\" readonly=\\"\\" class=\\"gl-mb-2\\"></gl-form-input-group-stub>
- <gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\" class=\\"gl-mt-3\\" role=\\"button\\" tabindex=\\"0\\">Reset key</gl-button-stub>
- <gl-modal-stub modalid=\\"authKeyModal\\" titletag=\\"h4\\" modalclass=\\"\\" size=\\"md\\" title=\\"Reset key\\" ok-title=\\"Reset key\\" ok-variant=\\"danger\\">
- Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.
- </gl-modal-stub>
- </gl-form-group-stub>
- <gl-form-group-stub label=\\"Alert test payload\\" label-for=\\"alert-json\\">
- <gl-form-textarea-stub noresize=\\"true\\" id=\\"alert-json\\" disabled=\\"true\\" state=\\"true\\" placeholder=\\"Enter test alert JSON....\\" rows=\\"6\\" max-rows=\\"10\\"></gl-form-textarea-stub>
- </gl-form-group-stub>
- <gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">Test alert payload</gl-button-stub>
- <div class=\\"footer-block row-content-block gl-display-flex gl-justify-content-space-between\\">
- <gl-button-stub category=\\"primary\\" variant=\\"success\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">
- Save changes
- </gl-button-stub>
- <gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">
- Cancel
- </gl-button-stub>
- </div>
- </gl-form-stub>
-</div>"
-`;
diff --git a/spec/frontend/alert_settings/alert_settings_form_spec.js b/spec/frontend/alert_settings/alert_settings_form_spec.js
deleted file mode 100644
index 6e1ea31ed6a..00000000000
--- a/spec/frontend/alert_settings/alert_settings_form_spec.js
+++ /dev/null
@@ -1,231 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlModal, GlAlert } from '@gitlab/ui';
-import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form.vue';
-import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
-import ToggleButton from '~/vue_shared/components/toggle_button.vue';
-import { i18n } from '~/alerts_settings/constants';
-import service from '~/alerts_settings/services';
-
-jest.mock('~/alerts_settings/services');
-
-const PROMETHEUS_URL = '/prometheus/alerts/notify.json';
-const GENERIC_URL = '/alerts/notify.json';
-const KEY = 'abcedfg123';
-const INVALID_URL = 'http://invalid';
-const ACTIVATED = false;
-
-describe('AlertsSettingsForm', () => {
- let wrapper;
-
- const createComponent = ({ methods } = {}, data) => {
- wrapper = shallowMount(AlertsSettingsForm, {
- data() {
- return { ...data };
- },
- provide: {
- generic: {
- authorizationKey: KEY,
- formPath: INVALID_URL,
- url: GENERIC_URL,
- alertsSetupUrl: INVALID_URL,
- alertsUsageUrl: INVALID_URL,
- activated: ACTIVATED,
- },
- prometheus: {
- authorizationKey: KEY,
- prometheusFormPath: INVALID_URL,
- prometheusUrl: PROMETHEUS_URL,
- activated: ACTIVATED,
- },
- opsgenie: {
- opsgenieMvcIsAvailable: true,
- formPath: INVALID_URL,
- activated: ACTIVATED,
- opsgenieMvcTargetUrl: GENERIC_URL,
- },
- },
- methods,
- });
- };
-
- const findSelect = () => wrapper.find('[data-testid="alert-settings-select"]');
- const findJsonInput = () => wrapper.find('#alert-json');
- const findUrl = () => wrapper.find('#url');
- const findAuthorizationKey = () => wrapper.find('#authorization-key');
- const findApiUrl = () => wrapper.find('#api-url');
-
- beforeEach(() => {
- setFixtures(`
- <div>
- <span class="js-service-active-status fa fa-circle" data-value="true"></span>
- <span class="js-service-active-status fa fa-power-off" data-value="false"></span>
- </div>`);
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('with default values', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders the initial template', () => {
- expect(wrapper.html()).toMatchSnapshot();
- });
- });
-
- it('renders alerts integrations list', () => {
- createComponent();
- expect(wrapper.find(IntegrationsList).exists()).toBe(true);
- });
-
- describe('reset key', () => {
- it('triggers resetKey method', () => {
- const resetKey = jest.fn();
- const methods = { resetKey };
- createComponent({ methods });
-
- wrapper.find(GlModal).vm.$emit('ok');
-
- expect(resetKey).toHaveBeenCalled();
- });
-
- it('updates the authorization key on success', () => {
- createComponent(
- {},
- {
- authKey: 'newToken',
- },
- );
-
- expect(findAuthorizationKey().attributes('value')).toBe('newToken');
- });
-
- it('shows a alert message on error', () => {
- service.updateGenericKey.mockRejectedValueOnce({});
-
- createComponent();
-
- return wrapper.vm.resetKey().then(() => {
- expect(wrapper.find(GlAlert).exists()).toBe(true);
- });
- });
- });
-
- describe('activate toggle', () => {
- it('triggers toggleActivated method', () => {
- const toggleService = jest.fn();
- const methods = { toggleService };
- createComponent({ methods });
-
- wrapper.find(ToggleButton).vm.$emit('change', true);
- expect(toggleService).toHaveBeenCalled();
- });
-
- describe('error is encountered', () => {
- it('restores previous value', () => {
- service.updateGenericKey.mockRejectedValueOnce({});
- createComponent();
- return wrapper.vm.resetKey().then(() => {
- expect(wrapper.find(ToggleButton).props('value')).toBe(false);
- });
- });
- });
- });
-
- describe('prometheus is active', () => {
- beforeEach(() => {
- createComponent(
- {},
- {
- selectedEndpoint: 'prometheus',
- },
- );
- });
-
- it('renders a valid "select"', () => {
- expect(findSelect().exists()).toBe(true);
- });
-
- it('shows the API URL input', () => {
- expect(findApiUrl().exists()).toBe(true);
- });
-
- it('shows the correct default API URL', () => {
- expect(findUrl().attributes('value')).toBe(PROMETHEUS_URL);
- });
- });
-
- describe('Opsgenie is active', () => {
- beforeEach(() => {
- createComponent(
- {},
- {
- selectedEndpoint: 'opsgenie',
- },
- );
- });
-
- it('shows a input for the Opsgenie target URL', () => {
- expect(findApiUrl().exists()).toBe(true);
- });
- });
-
- describe('trigger test alert', () => {
- beforeEach(() => {
- createComponent({});
- });
-
- it('should enable the JSON input', () => {
- expect(findJsonInput().exists()).toBe(true);
- expect(findJsonInput().props('value')).toBe(null);
- });
-
- it('should validate JSON input', async () => {
- createComponent(true, {
- testAlertJson: '{ "value": "test" }',
- });
-
- findJsonInput().vm.$emit('change');
-
- await wrapper.vm.$nextTick();
-
- expect(findJsonInput().attributes('state')).toBe('true');
- });
-
- describe('alert service is toggled', () => {
- describe('error handling', () => {
- const toggleService = true;
-
- it('should show generic error', async () => {
- service.updateGenericActive.mockRejectedValueOnce({});
-
- createComponent();
-
- await wrapper.vm.toggleActivated(toggleService);
- expect(wrapper.vm.active).toBe(false);
- expect(wrapper.find(GlAlert).attributes('variant')).toBe('danger');
- expect(wrapper.find(GlAlert).text()).toBe(i18n.errorMsg);
- });
-
- it('should show first field specific error when available', async () => {
- const err1 = "can't be blank";
- const err2 = 'is not a valid URL';
- const key = 'api_url';
- service.updateGenericActive.mockRejectedValueOnce({
- response: { data: { errors: { [key]: [err1, err2] } } },
- });
-
- createComponent();
-
- await wrapper.vm.toggleActivated(toggleService);
-
- expect(wrapper.find(GlAlert).text()).toContain(i18n.errorMsg);
- expect(wrapper.find(GlAlert).text()).toContain(`${key} ${err1}`);
- });
- });
- });
- });
-});
diff --git a/spec/frontend/alert_settings/alerts_integrations_list_spec.js b/spec/frontend/alert_settings/alerts_integrations_list_spec.js
deleted file mode 100644
index 6fc9901db2a..00000000000
--- a/spec/frontend/alert_settings/alerts_integrations_list_spec.js
+++ /dev/null
@@ -1,89 +0,0 @@
-import { GlTable, GlIcon } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import Tracking from '~/tracking';
-import AlertIntegrationsList, {
- i18n,
-} from '~/alerts_settings/components/alerts_integrations_list.vue';
-import { trackAlertIntergrationsViewsOptions } from '~/alerts_settings/constants';
-
-const mockIntegrations = [
- {
- activated: true,
- name: 'Integration 1',
- type: 'HTTP endpoint',
- },
- {
- activated: false,
- name: 'Integration 2',
- type: 'HTTP endpoint',
- },
-];
-
-describe('AlertIntegrationsList', () => {
- let wrapper;
-
- function mountComponent(propsData = {}) {
- wrapper = mount(AlertIntegrationsList, {
- propsData: {
- integrations: mockIntegrations,
- ...propsData,
- },
- stubs: {
- GlIcon: true,
- },
- });
- }
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
- });
-
- beforeEach(() => {
- mountComponent();
- });
-
- const findTableComponent = () => wrapper.find(GlTable);
- const finsStatusCell = () => wrapper.findAll('[data-testid="integration-activated-status"]');
-
- it('renders a table', () => {
- expect(findTableComponent().exists()).toBe(true);
- });
-
- it('renders an empty state when no integrations provided', () => {
- mountComponent({ integrations: [] });
- expect(findTableComponent().text()).toContain(i18n.emptyState);
- });
-
- describe('integration status', () => {
- it('enabled', () => {
- const cell = finsStatusCell().at(0);
- const activatedIcon = cell.find(GlIcon);
- expect(cell.text()).toBe(i18n.status.enabled.name);
- expect(activatedIcon.attributes('name')).toBe('check-circle-filled');
- expect(activatedIcon.attributes('title')).toBe(i18n.status.enabled.tooltip);
- });
-
- it('disabled', () => {
- const cell = finsStatusCell().at(1);
- const notActivatedIcon = cell.find(GlIcon);
- expect(cell.text()).toBe(i18n.status.disabled.name);
- expect(notActivatedIcon.attributes('name')).toBe('warning-solid');
- expect(notActivatedIcon.attributes('title')).toBe(i18n.status.disabled.tooltip);
- });
- });
-
- describe('Snowplow tracking', () => {
- beforeEach(() => {
- jest.spyOn(Tracking, 'event');
- mountComponent();
- });
-
- it('should track alert list page views', () => {
- const { category, action } = trackAlertIntergrationsViewsOptions;
- expect(Tracking.event).toHaveBeenCalledWith(category, action);
- });
- });
-});
diff --git a/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_new_spec.js.snap b/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_new_spec.js.snap
new file mode 100644
index 00000000000..e2ef7483316
--- /dev/null
+++ b/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_new_spec.js.snap
@@ -0,0 +1,97 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AlertsSettingsFormNew with default values renders the initial template 1`] = `
+"<form class=\\"gl-mt-6\\">
+ <h5 class=\\"gl-font-lg gl-my-5\\">Add new integrations</h5>
+ <div id=\\"integration-type\\" role=\\"group\\" class=\\"form-group gl-form-group\\"><label id=\\"integration-type__BV_label_\\" for=\\"integration-type\\" class=\\"d-block col-form-label\\">1. Select integration type</label>
+ <div class=\\"bv-no-focus-ring\\"><select class=\\"gl-form-select custom-select\\" id=\\"__BVID__8\\">
+ <option value=\\"\\">Select integration type</option>
+ <option value=\\"HTTP\\">HTTP Endpoint</option>
+ <option value=\\"PROMETHEUS\\">External Prometheus</option>
+ <option value=\\"OPSGENIE\\">Opsgenie</option>
+ </select>
+ <!---->
+ <!---->
+ <!---->
+ <!---->
+ </div>
+ </div>
+ <div class=\\"gl-mt-3 collapse\\" style=\\"display: none;\\" id=\\"__BVID__10\\">
+ <div>
+ <div id=\\"name-integration\\" role=\\"group\\" class=\\"form-group gl-form-group\\"><label id=\\"name-integration__BV_label_\\" for=\\"name-integration\\" class=\\"d-block col-form-label\\">2. Name integration</label>
+ <div class=\\"bv-no-focus-ring\\"><input type=\\"text\\" placeholder=\\"Enter integration name\\" class=\\"gl-form-input form-control\\" id=\\"__BVID__15\\">
+ <!---->
+ <!---->
+ <!---->
+ </div>
+ </div>
+ <div id=\\"integration-webhook\\" role=\\"group\\" class=\\"form-group gl-form-group\\"><label id=\\"integration-webhook__BV_label_\\" for=\\"integration-webhook\\" class=\\"d-block col-form-label\\">3. Set up webhook</label>
+ <div class=\\"bv-no-focus-ring\\"><span>Utilize the URL and authorization key below to authorize an external service to send alerts to GitLab. Review your external service's documentation to learn where to add these details, and the <a rel=\\"noopener noreferrer\\" target=\\"_blank\\" href=\\"https://docs.gitlab.com/ee/operations/incident_management/alert_integrations.html\\" class=\\"gl-link gl-display-inline-block\\">GitLab documentation</a> to learn more about configuring your endpoint.</span> <label class=\\"gl-display-flex gl-flex-direction-column gl-mb-0 gl-w-max-content gl-my-4 gl-font-weight-normal\\">
+ <div class=\\"gl-toggle-wrapper\\"><span class=\\"gl-toggle-label\\">Active</span>
+ <!----> <button aria-label=\\"Active\\" type=\\"button\\" class=\\"gl-toggle\\"><span class=\\"toggle-icon\\"><svg data-testid=\\"close-icon\\" class=\\"gl-icon s16\\"><use href=\\"#close\\"></use></svg></span></button></div>
+ <!---->
+ </label>
+ <!---->
+ <div class=\\"gl-my-4\\"><span class=\\"gl-font-weight-bold\\">
+ Webhook URL
+ </span>
+ <div id=\\"url\\" readonly=\\"readonly\\">
+ <div role=\\"group\\" class=\\"input-group\\">
+ <!---->
+ <!----> <input id=\\"url\\" type=\\"text\\" readonly=\\"readonly\\" class=\\"gl-form-input form-control\\">
+ <div class=\\"input-group-append\\"><button title=\\"Copy\\" data-clipboard-text=\\"\\" aria-label=\\"Copy this value\\" type=\\"button\\" class=\\"btn gl-m-0! btn-default btn-md gl-button btn-default-secondary btn-icon\\">
+ <!----> <svg data-testid=\\"copy-to-clipboard-icon\\" class=\\"gl-button-icon gl-icon s16\\">
+ <use href=\\"#copy-to-clipboard\\"></use>
+ </svg>
+ <!----></button></div>
+ <!---->
+ </div>
+ </div>
+ </div>
+ <div class=\\"gl-my-4\\"><span class=\\"gl-font-weight-bold\\">
+ Authorization key
+ </span>
+ <div id=\\"authorization-key\\" readonly=\\"readonly\\" class=\\"gl-mb-3\\">
+ <div role=\\"group\\" class=\\"input-group\\">
+ <!---->
+ <!----> <input id=\\"authorization-key\\" type=\\"text\\" readonly=\\"readonly\\" class=\\"gl-form-input form-control\\">
+ <div class=\\"input-group-append\\"><button title=\\"Copy\\" data-clipboard-text=\\"\\" aria-label=\\"Copy this value\\" type=\\"button\\" class=\\"btn gl-m-0! btn-default btn-md gl-button btn-default-secondary btn-icon\\">
+ <!----> <svg data-testid=\\"copy-to-clipboard-icon\\" class=\\"gl-button-icon gl-icon s16\\">
+ <use href=\\"#copy-to-clipboard\\"></use>
+ </svg>
+ <!----></button></div>
+ <!---->
+ </div>
+ </div> <button type=\\"button\\" disabled=\\"disabled\\" class=\\"btn btn-default btn-md disabled gl-button\\">
+ <!---->
+ <!----> <span class=\\"gl-button-text\\">
+ Reset Key
+ </span></button>
+ <!---->
+ </div>
+ <!---->
+ <!---->
+ <!---->
+ </div>
+ </div>
+ <div id=\\"test-integration\\" role=\\"group\\" class=\\"form-group gl-form-group\\"><label id=\\"test-integration__BV_label_\\" for=\\"test-integration\\" class=\\"d-block col-form-label\\">4. Sample alert payload (optional)</label>
+ <div class=\\"bv-no-focus-ring\\"><span>Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to test the integration (optional).</span> <textarea id=\\"test-payload\\" disabled=\\"disabled\\" placeholder=\\"{ &quot;events&quot;: [{ &quot;application&quot;: &quot;Name of application&quot; }] }\\" wrap=\\"soft\\" class=\\"gl-form-input gl-form-textarea gl-my-3 form-control is-valid\\" style=\\"resize: none; overflow-y: scroll;\\"></textarea>
+ <!---->
+ <!---->
+ <!---->
+ </div>
+ </div>
+ <!---->
+ <!---->
+ </div>
+ <div class=\\"gl-display-flex gl-justify-content-start gl-py-3\\"><button data-testid=\\"integration-form-submit\\" type=\\"submit\\" class=\\"btn js-no-auto-disable btn-success btn-md gl-button\\">
+ <!---->
+ <!----> <span class=\\"gl-button-text\\">Save integration
+ </span></button> <button data-testid=\\"integration-test-and-submit\\" type=\\"button\\" class=\\"btn gl-mx-3 js-no-auto-disable btn-success btn-md gl-button btn-success-secondary\\">
+ <!---->
+ <!----> <span class=\\"gl-button-text\\">Save and test payload</span></button> <button type=\\"reset\\" class=\\"btn js-no-auto-disable btn-default btn-md gl-button\\">
+ <!---->
+ <!----> <span class=\\"gl-button-text\\">Cancel</span></button></div>
+ </div>
+</form>"
+`;
diff --git a/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_old_spec.js.snap b/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_old_spec.js.snap
new file mode 100644
index 00000000000..9306bf24baf
--- /dev/null
+++ b/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_old_spec.js.snap
@@ -0,0 +1,47 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AlertsSettingsFormOld with default values renders the initial template 1`] = `
+"<gl-form-stub>
+ <h5 class=\\"gl-font-lg gl-my-5\\"></h5>
+ <!---->
+ <div data-testid=\\"alert-settings-description\\">
+ <p>
+ <gl-sprintf-stub message=\\"You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page.\\"></gl-sprintf-stub>
+ </p>
+ <p>
+ <gl-sprintf-stub message=\\"Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.\\"></gl-sprintf-stub>
+ </p>
+ </div>
+ <gl-form-group-stub label-for=\\"integration-type\\" label=\\"Integration\\">
+ <gl-form-select-stub id=\\"integration-type\\" options=\\"[object Object],[object Object],[object Object]\\" data-testid=\\"alert-settings-select\\" value=\\"HTTP\\"></gl-form-select-stub> <span class=\\"gl-text-gray-500\\"><gl-sprintf-stub message=\\"Learn more about our our upcoming %{linkStart}integrations%{linkEnd}\\"></gl-sprintf-stub></span>
+ </gl-form-group-stub>
+ <gl-form-group-stub label=\\"Active\\" label-for=\\"active\\">
+ <toggle-button-stub id=\\"active\\"></toggle-button-stub>
+ </gl-form-group-stub>
+ <!---->
+ <gl-form-group-stub label=\\"Webhook URL\\" label-for=\\"url\\">
+ <gl-form-input-group-stub value=\\"/alerts/notify.json\\" predefinedoptions=\\"[object Object]\\" id=\\"url\\" readonly=\\"\\"></gl-form-input-group-stub> <span class=\\"gl-text-gray-500\\">
+
+ </span>
+ </gl-form-group-stub>
+ <gl-form-group-stub label-for=\\"authorization-key\\">
+ <gl-form-input-group-stub value=\\"\\" predefinedoptions=\\"[object Object]\\" id=\\"authorization-key\\" readonly=\\"\\" class=\\"gl-mb-2\\"></gl-form-input-group-stub>
+ <gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\" class=\\"gl-mt-3\\" role=\\"button\\" tabindex=\\"0\\">Reset key</gl-button-stub>
+ <gl-modal-stub modalid=\\"tokenModal\\" titletag=\\"h4\\" modalclass=\\"\\" size=\\"md\\" title=\\"Reset key\\" ok-title=\\"Reset key\\" ok-variant=\\"danger\\">
+ Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.
+ </gl-modal-stub>
+ </gl-form-group-stub>
+ <gl-form-group-stub label=\\"Alert test payload\\" label-for=\\"alert-json\\">
+ <gl-form-textarea-stub noresize=\\"true\\" id=\\"alert-json\\" disabled=\\"true\\" state=\\"true\\" placeholder=\\"Enter test alert JSON....\\" rows=\\"6\\" max-rows=\\"10\\"></gl-form-textarea-stub>
+ </gl-form-group-stub>
+ <gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">Test alert payload</gl-button-stub>
+ <div class=\\"footer-block row-content-block gl-display-flex gl-justify-content-space-between\\">
+ <gl-button-stub category=\\"primary\\" variant=\\"success\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">
+ Save changes
+ </gl-button-stub>
+ <gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">
+ Cancel
+ </gl-button-stub>
+ </div>
+</gl-form-stub>"
+`;
diff --git a/spec/frontend/alerts_settings/alert_mapping_builder_spec.js b/spec/frontend/alerts_settings/alert_mapping_builder_spec.js
new file mode 100644
index 00000000000..12536c27dfe
--- /dev/null
+++ b/spec/frontend/alerts_settings/alert_mapping_builder_spec.js
@@ -0,0 +1,97 @@
+import { GlIcon, GlFormInput, GlDropdown, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import AlertMappingBuilder, { i18n } from '~/alerts_settings/components/alert_mapping_builder.vue';
+import gitlabFields from '~/alerts_settings/components/mocks/gitlabFields.json';
+import parsedMapping from '~/alerts_settings/components/mocks/parsedMapping.json';
+
+describe('AlertMappingBuilder', () => {
+ let wrapper;
+
+ function mountComponent() {
+ wrapper = shallowMount(AlertMappingBuilder, {
+ propsData: {
+ payloadFields: parsedMapping.samplePayload.payloadAlerFields.nodes,
+ mapping: parsedMapping.storedMapping.nodes,
+ },
+ });
+ }
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ const findColumnInRow = (row, column) =>
+ wrapper
+ .findAll('.gl-display-table-row')
+ .at(row)
+ .findAll('.gl-display-table-cell ')
+ .at(column);
+
+ it('renders column captions', () => {
+ expect(findColumnInRow(0, 0).text()).toContain(i18n.columns.gitlabKeyTitle);
+ expect(findColumnInRow(0, 2).text()).toContain(i18n.columns.payloadKeyTitle);
+ expect(findColumnInRow(0, 3).text()).toContain(i18n.columns.fallbackKeyTitle);
+
+ const fallbackColumnIcon = findColumnInRow(0, 3).find(GlIcon);
+ expect(fallbackColumnIcon.exists()).toBe(true);
+ expect(fallbackColumnIcon.attributes('name')).toBe('question');
+ expect(fallbackColumnIcon.attributes('title')).toBe(i18n.fallbackTooltip);
+ });
+
+ it('renders disabled form input for each mapped field', () => {
+ gitlabFields.forEach((field, index) => {
+ const input = findColumnInRow(index + 1, 0).find(GlFormInput);
+ expect(input.attributes('value')).toBe(`${field.label} (${field.type.join(' or ')})`);
+ expect(input.attributes('disabled')).toBe('');
+ });
+ });
+
+ it('renders right arrow next to each input', () => {
+ gitlabFields.forEach((field, index) => {
+ const arrow = findColumnInRow(index + 1, 1).find('.right-arrow');
+ expect(arrow.exists()).toBe(true);
+ });
+ });
+
+ it('renders mapping dropdown for each field', () => {
+ gitlabFields.forEach(({ compatibleTypes }, index) => {
+ const dropdown = findColumnInRow(index + 1, 2).find(GlDropdown);
+ const searchBox = dropdown.find(GlSearchBoxByType);
+ const dropdownItems = dropdown.findAll(GlDropdownItem);
+ const { nodes } = parsedMapping.samplePayload.payloadAlerFields;
+ const numberOfMappingOptions = nodes.filter(({ type }) =>
+ type.some(t => compatibleTypes.includes(t)),
+ );
+
+ expect(dropdown.exists()).toBe(true);
+ expect(searchBox.exists()).toBe(true);
+ expect(dropdownItems).toHaveLength(numberOfMappingOptions.length);
+ });
+ });
+
+ it('renders fallback dropdown only for the fields that have fallback', () => {
+ gitlabFields.forEach(({ compatibleTypes, numberOfFallbacks }, index) => {
+ const dropdown = findColumnInRow(index + 1, 3).find(GlDropdown);
+ expect(dropdown.exists()).toBe(Boolean(numberOfFallbacks));
+
+ if (numberOfFallbacks) {
+ const searchBox = dropdown.find(GlSearchBoxByType);
+ const dropdownItems = dropdown.findAll(GlDropdownItem);
+ const { nodes } = parsedMapping.samplePayload.payloadAlerFields;
+ const numberOfMappingOptions = nodes.filter(({ type }) =>
+ type.some(t => compatibleTypes.includes(t)),
+ );
+
+ expect(searchBox.exists()).toBe(Boolean(numberOfFallbacks));
+ expect(dropdownItems).toHaveLength(numberOfMappingOptions.length);
+ }
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/alerts_integrations_list_spec.js b/spec/frontend/alerts_settings/alerts_integrations_list_spec.js
new file mode 100644
index 00000000000..90bb38f0c2b
--- /dev/null
+++ b/spec/frontend/alerts_settings/alerts_integrations_list_spec.js
@@ -0,0 +1,125 @@
+import { GlTable, GlIcon, GlButton } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
+import Tracking from '~/tracking';
+import AlertIntegrationsList, {
+ i18n,
+} from '~/alerts_settings/components/alerts_integrations_list.vue';
+import { trackAlertIntegrationsViewsOptions } from '~/alerts_settings/constants';
+
+const mockIntegrations = [
+ {
+ id: '1',
+ active: true,
+ name: 'Integration 1',
+ type: 'HTTP endpoint',
+ },
+ {
+ id: '2',
+ active: false,
+ name: 'Integration 2',
+ type: 'HTTP endpoint',
+ },
+];
+
+describe('AlertIntegrationsList', () => {
+ let wrapper;
+ const { trigger: triggerIntersection } = useMockIntersectionObserver();
+
+ function mountComponent({ data = {}, props = {} } = {}) {
+ wrapper = mount(AlertIntegrationsList, {
+ data() {
+ return { ...data };
+ },
+ propsData: {
+ integrations: mockIntegrations,
+ ...props,
+ },
+ provide: {
+ glFeatures: { httpIntegrationsList: true },
+ },
+ stubs: {
+ GlIcon: true,
+ GlButton: true,
+ },
+ });
+ }
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ const findTableComponent = () => wrapper.find(GlTable);
+ const findTableComponentRows = () => wrapper.find(GlTable).findAll('table tbody tr');
+ const finsStatusCell = () => wrapper.findAll('[data-testid="integration-activated-status"]');
+
+ it('renders a table', () => {
+ expect(findTableComponent().exists()).toBe(true);
+ });
+
+ it('renders an empty state when no integrations provided', () => {
+ mountComponent({ props: { integrations: [] } });
+ expect(findTableComponent().text()).toContain(i18n.emptyState);
+ });
+
+ it('renders an an edit and delete button for each integration', () => {
+ expect(findTableComponent().findAll(GlButton).length).toBe(4);
+ });
+
+ it('renders an highlighted row when a current integration is selected to edit', () => {
+ mountComponent({ data: { currentIntegration: { id: '1' } } });
+ expect(
+ findTableComponentRows()
+ .at(0)
+ .classes(),
+ ).toContain('gl-bg-blue-50');
+ });
+
+ describe('integration status', () => {
+ it('enabled', () => {
+ const cell = finsStatusCell().at(0);
+ const activatedIcon = cell.find(GlIcon);
+ expect(cell.text()).toBe(i18n.status.enabled.name);
+ expect(activatedIcon.attributes('name')).toBe('check-circle-filled');
+ expect(activatedIcon.attributes('title')).toBe(i18n.status.enabled.tooltip);
+ });
+
+ it('disabled', () => {
+ const cell = finsStatusCell().at(1);
+ const notActivatedIcon = cell.find(GlIcon);
+ expect(cell.text()).toBe(i18n.status.disabled.name);
+ expect(notActivatedIcon.attributes('name')).toBe('warning-solid');
+ expect(notActivatedIcon.attributes('title')).toBe(i18n.status.disabled.tooltip);
+ });
+ });
+
+ describe('Snowplow tracking', () => {
+ beforeEach(() => {
+ mountComponent();
+ jest.spyOn(Tracking, 'event');
+ });
+
+ it('should NOT track alert list page views when list is collapsed', () => {
+ triggerIntersection(wrapper.vm.$el, { entry: { isIntersecting: false } });
+
+ expect(Tracking.event).not.toHaveBeenCalled();
+ });
+
+ it('should track alert list page views only once when list is expanded', () => {
+ triggerIntersection(wrapper.vm.$el, { entry: { isIntersecting: true } });
+ triggerIntersection(wrapper.vm.$el, { entry: { isIntersecting: true } });
+ triggerIntersection(wrapper.vm.$el, { entry: { isIntersecting: true } });
+
+ const { category, action } = trackAlertIntegrationsViewsOptions;
+ expect(Tracking.event).toHaveBeenCalledTimes(1);
+ expect(Tracking.event).toHaveBeenCalledWith(category, action);
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js b/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js
new file mode 100644
index 00000000000..fbd482b1906
--- /dev/null
+++ b/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js
@@ -0,0 +1,364 @@
+import { mount } from '@vue/test-utils';
+import {
+ GlForm,
+ GlFormSelect,
+ GlCollapse,
+ GlFormInput,
+ GlToggle,
+ GlFormTextarea,
+} from '@gitlab/ui';
+import waitForPromises from 'helpers/wait_for_promises';
+import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form_new.vue';
+import { defaultAlertSettingsConfig } from './util';
+import { typeSet } from '~/alerts_settings/constants';
+
+describe('AlertsSettingsFormNew', () => {
+ let wrapper;
+ const mockToastShow = jest.fn();
+
+ const createComponent = ({
+ data = {},
+ props = {},
+ multipleHttpIntegrationsCustomMapping = false,
+ } = {}) => {
+ wrapper = mount(AlertsSettingsForm, {
+ data() {
+ return { ...data };
+ },
+ propsData: {
+ loading: false,
+ canAddIntegration: true,
+ canManageOpsgenie: true,
+ ...props,
+ },
+ provide: {
+ glFeatures: { multipleHttpIntegrationsCustomMapping },
+ ...defaultAlertSettingsConfig,
+ },
+ mocks: {
+ $toast: {
+ show: mockToastShow,
+ },
+ },
+ });
+ };
+
+ const findForm = () => wrapper.find(GlForm);
+ const findSelect = () => wrapper.find(GlFormSelect);
+ const findFormSteps = () => wrapper.find(GlCollapse);
+ const findFormFields = () => wrapper.findAll(GlFormInput);
+ const findFormToggle = () => wrapper.find(GlToggle);
+ const findTestPayloadSection = () => wrapper.find(`[id = "test-integration"]`);
+ const findMappingBuilderSection = () => wrapper.find(`[id = "mapping-builder"]`);
+ const findSubmitButton = () => wrapper.find(`[type = "submit"]`);
+ const findMultiSupportText = () =>
+ wrapper.find(`[data-testid="multi-integrations-not-supported"]`);
+ const findJsonTestSubmit = () => wrapper.find(`[data-testid="integration-test-and-submit"]`);
+ const findJsonTextArea = () => wrapper.find(`[id = "test-payload"]`);
+ const findActionBtn = () => wrapper.find(`[data-testid="payload-action-btn"]`);
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('with default values', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the initial template', () => {
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+
+ it('render the initial form with only an integration type dropdown', () => {
+ expect(findForm().exists()).toBe(true);
+ expect(findSelect().exists()).toBe(true);
+ expect(findMultiSupportText().exists()).toBe(false);
+ expect(findFormSteps().attributes('visible')).toBeUndefined();
+ });
+
+ it('shows the rest of the form when the dropdown is used', async () => {
+ const options = findSelect().findAll('option');
+ await options.at(1).setSelected();
+
+ await wrapper.vm.$nextTick();
+
+ expect(
+ findFormFields()
+ .at(0)
+ .isVisible(),
+ ).toBe(true);
+ });
+
+ it('disabled the dropdown and shows help text when multi integrations are not supported', async () => {
+ createComponent({ props: { canAddIntegration: false } });
+ expect(findSelect().attributes('disabled')).toBe('disabled');
+ expect(findMultiSupportText().exists()).toBe(true);
+ });
+ });
+
+ describe('submitting integration form', () => {
+ it('allows for create-new-integration with the correct form values for HTTP', async () => {
+ createComponent({});
+
+ const options = findSelect().findAll('option');
+ await options.at(1).setSelected();
+
+ await findFormFields()
+ .at(0)
+ .setValue('Test integration');
+ await findFormToggle().trigger('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findSubmitButton().exists()).toBe(true);
+ expect(findSubmitButton().text()).toBe('Save integration');
+
+ findForm().trigger('submit');
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted('create-new-integration')).toBeTruthy();
+ expect(wrapper.emitted('create-new-integration')[0]).toEqual([
+ { type: typeSet.http, variables: { name: 'Test integration', active: true } },
+ ]);
+ });
+
+ it('allows for create-new-integration with the correct form values for PROMETHEUS', async () => {
+ createComponent({});
+
+ const options = findSelect().findAll('option');
+ await options.at(2).setSelected();
+
+ await findFormFields()
+ .at(0)
+ .setValue('Test integration');
+ await findFormFields()
+ .at(1)
+ .setValue('https://test.com');
+ await findFormToggle().trigger('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findSubmitButton().exists()).toBe(true);
+ expect(findSubmitButton().text()).toBe('Save integration');
+
+ findForm().trigger('submit');
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted('create-new-integration')).toBeTruthy();
+ expect(wrapper.emitted('create-new-integration')[0]).toEqual([
+ { type: typeSet.prometheus, variables: { apiUrl: 'https://test.com', active: true } },
+ ]);
+ });
+
+ it('allows for update-integration with the correct form values for HTTP', async () => {
+ createComponent({
+ data: {
+ selectedIntegration: typeSet.http,
+ currentIntegration: { id: '1', name: 'Test integration pre' },
+ },
+ props: {
+ loading: false,
+ },
+ });
+
+ await findFormFields()
+ .at(0)
+ .setValue('Test integration post');
+ await findFormToggle().trigger('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findSubmitButton().exists()).toBe(true);
+ expect(findSubmitButton().text()).toBe('Save integration');
+
+ findForm().trigger('submit');
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted('update-integration')).toBeTruthy();
+ expect(wrapper.emitted('update-integration')[0]).toEqual([
+ { type: typeSet.http, variables: { name: 'Test integration post', active: true } },
+ ]);
+ });
+
+ it('allows for update-integration with the correct form values for PROMETHEUS', async () => {
+ createComponent({
+ data: {
+ selectedIntegration: typeSet.prometheus,
+ currentIntegration: { id: '1', apiUrl: 'https://test-pre.com' },
+ },
+ props: {
+ loading: false,
+ },
+ });
+
+ await findFormFields()
+ .at(0)
+ .setValue('Test integration');
+ await findFormFields()
+ .at(1)
+ .setValue('https://test-post.com');
+ await findFormToggle().trigger('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findSubmitButton().exists()).toBe(true);
+ expect(findSubmitButton().text()).toBe('Save integration');
+
+ findForm().trigger('submit');
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted('update-integration')).toBeTruthy();
+ expect(wrapper.emitted('update-integration')[0]).toEqual([
+ { type: typeSet.prometheus, variables: { apiUrl: 'https://test-post.com', active: true } },
+ ]);
+ });
+ });
+
+ describe('submitting the integration with a JSON test payload', () => {
+ beforeEach(() => {
+ createComponent({
+ data: {
+ selectedIntegration: typeSet.http,
+ currentIntegration: { id: '1', name: 'Test' },
+ active: true,
+ },
+ props: {
+ loading: false,
+ },
+ });
+ });
+
+ it('should not allow a user to test invalid JSON', async () => {
+ jest.useFakeTimers();
+ await findJsonTextArea().setValue('Invalid JSON');
+
+ jest.runAllTimers();
+ await wrapper.vm.$nextTick();
+
+ expect(findJsonTestSubmit().exists()).toBe(true);
+ expect(findJsonTestSubmit().text()).toBe('Save and test payload');
+ expect(findJsonTestSubmit().props('disabled')).toBe(true);
+ });
+
+ it('should allow for the form to be automatically saved if the test payload is successfully submitted', async () => {
+ jest.useFakeTimers();
+ await findJsonTextArea().setValue('{ "value": "value" }');
+
+ jest.runAllTimers();
+ await wrapper.vm.$nextTick();
+ expect(findJsonTestSubmit().props('disabled')).toBe(false);
+ });
+ });
+
+ describe('Test payload section for HTTP integration', () => {
+ beforeEach(() => {
+ createComponent({
+ multipleHttpIntegrationsCustomMapping: true,
+ props: {
+ currentIntegration: {
+ type: typeSet.http,
+ },
+ },
+ });
+ });
+
+ describe.each`
+ active | resetSamplePayloadConfirmed | disabled
+ ${true} | ${true} | ${undefined}
+ ${false} | ${true} | ${'disabled'}
+ ${true} | ${false} | ${'disabled'}
+ ${false} | ${false} | ${'disabled'}
+ `('', ({ active, resetSamplePayloadConfirmed, disabled }) => {
+ const payloadResetMsg = resetSamplePayloadConfirmed ? 'was confirmed' : 'was not confirmed';
+ const enabledState = disabled === 'disabled' ? 'disabled' : 'enabled';
+ const activeState = active ? 'active' : 'not active';
+
+ it(`textarea should be ${enabledState} when payload reset ${payloadResetMsg} and current integration is ${activeState}`, async () => {
+ wrapper.setData({
+ customMapping: { samplePayload: true },
+ active,
+ resetSamplePayloadConfirmed,
+ });
+ await wrapper.vm.$nextTick();
+ expect(
+ findTestPayloadSection()
+ .find(GlFormTextarea)
+ .attributes('disabled'),
+ ).toBe(disabled);
+ });
+ });
+
+ describe('action buttons for sample payload', () => {
+ describe.each`
+ resetSamplePayloadConfirmed | samplePayload | caption
+ ${false} | ${true} | ${'Edit payload'}
+ ${true} | ${false} | ${'Submit payload'}
+ ${true} | ${true} | ${'Submit payload'}
+ ${false} | ${false} | ${'Submit payload'}
+ `('', ({ resetSamplePayloadConfirmed, samplePayload, caption }) => {
+ const samplePayloadMsg = samplePayload ? 'was provided' : 'was not provided';
+ const payloadResetMsg = resetSamplePayloadConfirmed ? 'was confirmed' : 'was not confirmed';
+
+ it(`shows ${caption} button when sample payload ${samplePayloadMsg} and payload reset ${payloadResetMsg}`, async () => {
+ wrapper.setData({
+ selectedIntegration: typeSet.http,
+ customMapping: { samplePayload },
+ resetSamplePayloadConfirmed,
+ });
+ await wrapper.vm.$nextTick();
+ expect(findActionBtn().text()).toBe(caption);
+ });
+ });
+ });
+
+ describe('Parsing payload', () => {
+ it('displays a toast message on successful parse', async () => {
+ jest.useFakeTimers();
+ wrapper.setData({
+ selectedIntegration: typeSet.http,
+ customMapping: { samplePayload: false },
+ });
+ await wrapper.vm.$nextTick();
+
+ findActionBtn().vm.$emit('click');
+ jest.advanceTimersByTime(1000);
+
+ await waitForPromises();
+
+ expect(mockToastShow).toHaveBeenCalledWith(
+ 'Sample payload has been parsed. You can now map the fields.',
+ );
+ });
+ });
+ });
+
+ describe('Mapping builder section', () => {
+ describe.each`
+ featureFlag | integrationOption | visible
+ ${true} | ${1} | ${true}
+ ${true} | ${2} | ${false}
+ ${false} | ${1} | ${false}
+ ${false} | ${2} | ${false}
+ `('', ({ featureFlag, integrationOption, visible }) => {
+ const visibleMsg = visible ? 'is rendered' : 'is not rendered';
+ const featureFlagMsg = featureFlag ? 'is enabled' : 'is disabled';
+ const integrationType = integrationOption === 1 ? typeSet.http : typeSet.prometheus;
+
+ it(`${visibleMsg} when multipleHttpIntegrationsCustomMapping feature flag ${featureFlagMsg} and integration type is ${integrationType}`, async () => {
+ createComponent({ multipleHttpIntegrationsCustomMapping: featureFlag });
+ const options = findSelect().findAll('option');
+ options.at(integrationOption).setSelected();
+ await wrapper.vm.$nextTick();
+ expect(findMappingBuilderSection().exists()).toBe(visible);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/alerts_settings_form_old_spec.js b/spec/frontend/alerts_settings/alerts_settings_form_old_spec.js
new file mode 100644
index 00000000000..3d0dfb44d63
--- /dev/null
+++ b/spec/frontend/alerts_settings/alerts_settings_form_old_spec.js
@@ -0,0 +1,204 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlModal, GlAlert } from '@gitlab/ui';
+import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form_old.vue';
+import ToggleButton from '~/vue_shared/components/toggle_button.vue';
+import { i18n } from '~/alerts_settings/constants';
+import service from '~/alerts_settings/services';
+import { defaultAlertSettingsConfig } from './util';
+
+jest.mock('~/alerts_settings/services');
+
+describe('AlertsSettingsFormOld', () => {
+ let wrapper;
+
+ const createComponent = ({ methods } = {}, data) => {
+ wrapper = shallowMount(AlertsSettingsForm, {
+ data() {
+ return { ...data };
+ },
+ provide: {
+ ...defaultAlertSettingsConfig,
+ },
+ methods,
+ });
+ };
+
+ const findSelect = () => wrapper.find('[data-testid="alert-settings-select"]');
+ const findJsonInput = () => wrapper.find('#alert-json');
+ const findUrl = () => wrapper.find('#url');
+ const findAuthorizationKey = () => wrapper.find('#authorization-key');
+ const findApiUrl = () => wrapper.find('#api-url');
+
+ beforeEach(() => {
+ setFixtures(`
+ <div>
+ <span class="js-service-active-status fa fa-circle" data-value="true"></span>
+ <span class="js-service-active-status fa fa-power-off" data-value="false"></span>
+ </div>`);
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('with default values', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the initial template', () => {
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+ });
+
+ describe('reset key', () => {
+ it('triggers resetKey method', () => {
+ const resetKey = jest.fn();
+ const methods = { resetKey };
+ createComponent({ methods });
+
+ wrapper.find(GlModal).vm.$emit('ok');
+
+ expect(resetKey).toHaveBeenCalled();
+ });
+
+ it('updates the authorization key on success', () => {
+ createComponent(
+ {},
+ {
+ token: 'newToken',
+ },
+ );
+
+ expect(findAuthorizationKey().attributes('value')).toBe('newToken');
+ });
+
+ it('shows a alert message on error', () => {
+ service.updateGenericKey.mockRejectedValueOnce({});
+
+ createComponent();
+
+ return wrapper.vm.resetKey().then(() => {
+ expect(wrapper.find(GlAlert).exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('activate toggle', () => {
+ it('triggers toggleActivated method', () => {
+ const toggleService = jest.fn();
+ const methods = { toggleService };
+ createComponent({ methods });
+
+ wrapper.find(ToggleButton).vm.$emit('change', true);
+ expect(toggleService).toHaveBeenCalled();
+ });
+
+ describe('error is encountered', () => {
+ it('restores previous value', () => {
+ service.updateGenericKey.mockRejectedValueOnce({});
+ createComponent();
+ return wrapper.vm.resetKey().then(() => {
+ expect(wrapper.find(ToggleButton).props('value')).toBe(false);
+ });
+ });
+ });
+ });
+
+ describe('prometheus is active', () => {
+ beforeEach(() => {
+ createComponent(
+ {},
+ {
+ selectedIntegration: 'PROMETHEUS',
+ },
+ );
+ });
+
+ it('renders a valid "select"', () => {
+ expect(findSelect().exists()).toBe(true);
+ });
+
+ it('shows the API URL input', () => {
+ expect(findApiUrl().exists()).toBe(true);
+ });
+
+ it('shows the correct default API URL', () => {
+ expect(findUrl().attributes('value')).toBe(defaultAlertSettingsConfig.prometheus.url);
+ });
+ });
+
+ describe('Opsgenie is active', () => {
+ beforeEach(() => {
+ createComponent(
+ {},
+ {
+ selectedIntegration: 'OPSGENIE',
+ },
+ );
+ });
+
+ it('shows a input for the Opsgenie target URL', () => {
+ expect(findApiUrl().exists()).toBe(true);
+ });
+ });
+
+ describe('trigger test alert', () => {
+ beforeEach(() => {
+ createComponent({});
+ });
+
+ it('should enable the JSON input', () => {
+ expect(findJsonInput().exists()).toBe(true);
+ expect(findJsonInput().props('value')).toBe(null);
+ });
+
+ it('should validate JSON input', async () => {
+ createComponent(true, {
+ testAlertJson: '{ "value": "test" }',
+ });
+
+ findJsonInput().vm.$emit('change');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findJsonInput().attributes('state')).toBe('true');
+ });
+
+ describe('alert service is toggled', () => {
+ describe('error handling', () => {
+ const toggleService = true;
+
+ it('should show generic error', async () => {
+ service.updateGenericActive.mockRejectedValueOnce({});
+
+ createComponent();
+
+ await wrapper.vm.toggleActivated(toggleService);
+ expect(wrapper.vm.active).toBe(false);
+ expect(wrapper.find(GlAlert).attributes('variant')).toBe('danger');
+ expect(wrapper.find(GlAlert).text()).toBe(i18n.errorMsg);
+ });
+
+ it('should show first field specific error when available', async () => {
+ const err1 = "can't be blank";
+ const err2 = 'is not a valid URL';
+ const key = 'api_url';
+ service.updateGenericActive.mockRejectedValueOnce({
+ response: { data: { errors: { [key]: [err1, err2] } } },
+ });
+
+ createComponent();
+
+ await wrapper.vm.toggleActivated(toggleService);
+
+ expect(wrapper.find(GlAlert).text()).toContain(i18n.errorMsg);
+ expect(wrapper.find(GlAlert).text()).toContain(`${key} ${err1}`);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js b/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js
new file mode 100644
index 00000000000..7384cf9a095
--- /dev/null
+++ b/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js
@@ -0,0 +1,415 @@
+import VueApollo from 'vue-apollo';
+import { mount, createLocalVue } from '@vue/test-utils';
+import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
+import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
+import AlertsSettingsWrapper from '~/alerts_settings/components/alerts_settings_wrapper.vue';
+import AlertsSettingsFormOld from '~/alerts_settings/components/alerts_settings_form_old.vue';
+import AlertsSettingsFormNew from '~/alerts_settings/components/alerts_settings_form_new.vue';
+import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
+import getIntegrationsQuery from '~/alerts_settings/graphql/queries/get_integrations.query.graphql';
+import createHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql';
+import createPrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql';
+import updateHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql';
+import updatePrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/update_prometheus_integration.mutation.graphql';
+import destroyHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql';
+import resetHttpTokenMutation from '~/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql';
+import resetPrometheusTokenMutation from '~/alerts_settings/graphql/mutations/reset_prometheus_token.mutation.graphql';
+import { typeSet } from '~/alerts_settings/constants';
+import {
+ ADD_INTEGRATION_ERROR,
+ RESET_INTEGRATION_TOKEN_ERROR,
+ UPDATE_INTEGRATION_ERROR,
+ INTEGRATION_PAYLOAD_TEST_ERROR,
+ DELETE_INTEGRATION_ERROR,
+} from '~/alerts_settings/utils/error_messages';
+import createFlash from '~/flash';
+import { defaultAlertSettingsConfig } from './util';
+import mockIntegrations from './mocks/integrations.json';
+import {
+ createHttpVariables,
+ updateHttpVariables,
+ createPrometheusVariables,
+ updatePrometheusVariables,
+ ID,
+ errorMsg,
+ getIntegrationsQueryResponse,
+ destroyIntegrationResponse,
+ integrationToDestroy,
+ destroyIntegrationResponseWithErrors,
+} from './mocks/apollo_mock';
+
+jest.mock('~/flash');
+
+const localVue = createLocalVue();
+
+describe('AlertsSettingsWrapper', () => {
+ let wrapper;
+ let fakeApollo;
+ let destroyIntegrationHandler;
+ useMockIntersectionObserver();
+
+ const findLoader = () => wrapper.find(IntegrationsList).find(GlLoadingIcon);
+ const findIntegrations = () => wrapper.find(IntegrationsList).findAll('table tbody tr');
+
+ async function destroyHttpIntegration(localWrapper) {
+ await jest.runOnlyPendingTimers();
+ await localWrapper.vm.$nextTick();
+
+ localWrapper
+ .find(IntegrationsList)
+ .vm.$emit('delete-integration', { id: integrationToDestroy.id });
+ }
+
+ async function awaitApolloDomMock() {
+ await wrapper.vm.$nextTick(); // kick off the DOM update
+ await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises)
+ await wrapper.vm.$nextTick(); // kick off the DOM update for flash
+ }
+
+ const createComponent = ({ data = {}, provide = {}, loading = false } = {}) => {
+ wrapper = mount(AlertsSettingsWrapper, {
+ data() {
+ return { ...data };
+ },
+ provide: {
+ ...defaultAlertSettingsConfig,
+ glFeatures: { httpIntegrationsList: false },
+ ...provide,
+ },
+ mocks: {
+ $apollo: {
+ mutate: jest.fn(),
+ query: jest.fn(),
+ queries: {
+ integrations: {
+ loading,
+ },
+ },
+ },
+ },
+ });
+ };
+
+ function createComponentWithApollo({
+ destroyHandler = jest.fn().mockResolvedValue(destroyIntegrationResponse),
+ } = {}) {
+ localVue.use(VueApollo);
+ destroyIntegrationHandler = destroyHandler;
+
+ const requestHandlers = [
+ [getIntegrationsQuery, jest.fn().mockResolvedValue(getIntegrationsQueryResponse)],
+ [destroyHttpIntegrationMutation, destroyIntegrationHandler],
+ ];
+
+ fakeApollo = createMockApollo(requestHandlers);
+
+ wrapper = mount(AlertsSettingsWrapper, {
+ localVue,
+ apolloProvider: fakeApollo,
+ provide: {
+ ...defaultAlertSettingsConfig,
+ glFeatures: { httpIntegrationsList: true },
+ },
+ });
+ }
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('with httpIntegrationsList feature flag disabled', () => {
+ it('renders data driven alerts integrations list and old form by default', () => {
+ createComponent();
+ expect(wrapper.find(IntegrationsList).exists()).toBe(true);
+ expect(wrapper.find(AlertsSettingsFormOld).exists()).toBe(true);
+ expect(wrapper.find(AlertsSettingsFormNew).exists()).toBe(false);
+ });
+ });
+
+ describe('with httpIntegrationsList feature flag enabled', () => {
+ it('renders the GraphQL alerts integrations list and new form', () => {
+ createComponent({ provide: { glFeatures: { httpIntegrationsList: true } } });
+ expect(wrapper.find(IntegrationsList).exists()).toBe(true);
+ expect(wrapper.find(AlertsSettingsFormOld).exists()).toBe(false);
+ expect(wrapper.find(AlertsSettingsFormNew).exists()).toBe(true);
+ });
+
+ it('uses a loading state inside the IntegrationsList table', () => {
+ createComponent({
+ data: { integrations: {} },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: true,
+ });
+ expect(wrapper.find(IntegrationsList).exists()).toBe(true);
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('renders the IntegrationsList table using the API data', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: false,
+ });
+ expect(findLoader().exists()).toBe(false);
+ expect(findIntegrations()).toHaveLength(mockIntegrations.length);
+ });
+
+ it('calls `$apollo.mutate` with `createHttpIntegrationMutation`', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { createHttpIntegrationMutation: { integration: { id: '1' } } },
+ });
+ wrapper.find(AlertsSettingsFormNew).vm.$emit('create-new-integration', {
+ type: typeSet.http,
+ variables: createHttpVariables,
+ });
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: createHttpIntegrationMutation,
+ update: expect.anything(),
+ variables: createHttpVariables,
+ });
+ });
+
+ it('calls `$apollo.mutate` with `updateHttpIntegrationMutation`', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { updateHttpIntegrationMutation: { integration: { id: '1' } } },
+ });
+ wrapper.find(AlertsSettingsFormNew).vm.$emit('update-integration', {
+ type: typeSet.http,
+ variables: updateHttpVariables,
+ });
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: updateHttpIntegrationMutation,
+ variables: updateHttpVariables,
+ });
+ });
+
+ it('calls `$apollo.mutate` with `resetHttpTokenMutation`', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { resetHttpTokenMutation: { integration: { id: '1' } } },
+ });
+ wrapper.find(AlertsSettingsFormNew).vm.$emit('reset-token', {
+ type: typeSet.http,
+ variables: { id: ID },
+ });
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: resetHttpTokenMutation,
+ variables: {
+ id: ID,
+ },
+ });
+ });
+
+ it('calls `$apollo.mutate` with `createPrometheusIntegrationMutation`', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { createPrometheusIntegrationMutation: { integration: { id: '2' } } },
+ });
+ wrapper.find(AlertsSettingsFormNew).vm.$emit('create-new-integration', {
+ type: typeSet.prometheus,
+ variables: createPrometheusVariables,
+ });
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: createPrometheusIntegrationMutation,
+ update: expect.anything(),
+ variables: createPrometheusVariables,
+ });
+ });
+
+ it('calls `$apollo.mutate` with `updatePrometheusIntegrationMutation`', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { updatePrometheusIntegrationMutation: { integration: { id: '2' } } },
+ });
+ wrapper.find(AlertsSettingsFormNew).vm.$emit('update-integration', {
+ type: typeSet.prometheus,
+ variables: updatePrometheusVariables,
+ });
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: updatePrometheusIntegrationMutation,
+ variables: updatePrometheusVariables,
+ });
+ });
+
+ it('calls `$apollo.mutate` with `resetPrometheusTokenMutation`', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { resetPrometheusTokenMutation: { integration: { id: '1' } } },
+ });
+ wrapper.find(AlertsSettingsFormNew).vm.$emit('reset-token', {
+ type: typeSet.prometheus,
+ variables: { id: ID },
+ });
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: resetPrometheusTokenMutation,
+ variables: {
+ id: ID,
+ },
+ });
+ });
+
+ it('shows an error alert when integration creation fails ', async () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(ADD_INTEGRATION_ERROR);
+ wrapper.find(AlertsSettingsFormNew).vm.$emit('create-new-integration', {});
+
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith({ message: ADD_INTEGRATION_ERROR });
+ });
+
+ it('shows an error alert when integration token reset fails ', async () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(RESET_INTEGRATION_TOKEN_ERROR);
+
+ wrapper.find(AlertsSettingsFormNew).vm.$emit('reset-token', {});
+
+ await waitForPromises();
+ expect(createFlash).toHaveBeenCalledWith({ message: RESET_INTEGRATION_TOKEN_ERROR });
+ });
+
+ it('shows an error alert when integration update fails ', async () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
+
+ wrapper.find(AlertsSettingsFormNew).vm.$emit('update-integration', {});
+
+ await waitForPromises();
+ expect(createFlash).toHaveBeenCalledWith({ message: UPDATE_INTEGRATION_ERROR });
+ });
+
+ it('shows an error alert when integration test payload fails ', async () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: false,
+ });
+
+ wrapper.find(AlertsSettingsFormNew).vm.$emit('test-payload-failure');
+
+ await waitForPromises();
+ expect(createFlash).toHaveBeenCalledWith({ message: INTEGRATION_PAYLOAD_TEST_ERROR });
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('with mocked Apollo client', () => {
+ it('has a selection of integrations loaded via the getIntegrationsQuery', async () => {
+ createComponentWithApollo();
+
+ await jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+
+ expect(findIntegrations()).toHaveLength(4);
+ });
+
+ it('calls a mutation with correct parameters and destroys a integration', async () => {
+ createComponentWithApollo();
+
+ await destroyHttpIntegration(wrapper);
+
+ expect(destroyIntegrationHandler).toHaveBeenCalled();
+
+ await wrapper.vm.$nextTick();
+
+ expect(findIntegrations()).toHaveLength(3);
+ });
+
+ it('displays flash if mutation had a recoverable error', async () => {
+ createComponentWithApollo({
+ destroyHandler: jest.fn().mockResolvedValue(destroyIntegrationResponseWithErrors),
+ });
+
+ await destroyHttpIntegration(wrapper);
+ await awaitApolloDomMock();
+
+ expect(createFlash).toHaveBeenCalledWith({ message: 'Houston, we have a problem' });
+ });
+
+ it('displays flash if mutation had a non-recoverable error', async () => {
+ createComponentWithApollo({
+ destroyHandler: jest.fn().mockRejectedValue('Error'),
+ });
+
+ await destroyHttpIntegration(wrapper);
+ await awaitApolloDomMock();
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: DELETE_INTEGRATION_ERROR,
+ });
+ });
+ });
+
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ describe('Opsgenie integration', () => {
+ it.each([true, false])('it shows/hides the alert when opsgenie is %s', active => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ provide: { glFeatures: { httpIntegrationsList: true }, opsgenie: { active } },
+ loading: false,
+ });
+
+ expect(wrapper.find(GlAlert).exists()).toBe(active);
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/mocks/apollo_mock.js b/spec/frontend/alerts_settings/mocks/apollo_mock.js
new file mode 100644
index 00000000000..e0eba1e8421
--- /dev/null
+++ b/spec/frontend/alerts_settings/mocks/apollo_mock.js
@@ -0,0 +1,123 @@
+const projectPath = '';
+export const ID = 'gid://gitlab/AlertManagement::HttpIntegration/7';
+export const errorMsg = 'Something went wrong';
+
+export const createHttpVariables = {
+ name: 'Test Pre',
+ active: true,
+ projectPath,
+};
+
+export const updateHttpVariables = {
+ name: 'Test Pre',
+ active: true,
+ id: ID,
+};
+
+export const createPrometheusVariables = {
+ apiUrl: 'https://test-pre.com',
+ active: true,
+ projectPath,
+};
+
+export const updatePrometheusVariables = {
+ apiUrl: 'https://test-pre.com',
+ active: true,
+ id: ID,
+};
+
+export const getIntegrationsQueryResponse = {
+ data: {
+ project: {
+ alertManagementIntegrations: {
+ nodes: [
+ {
+ id: '37',
+ type: 'HTTP',
+ active: true,
+ name: 'Test 5',
+ url:
+ 'http://127.0.0.1:3000/h5bp/html5-boilerplate/alerts/notify/test-5/d4875758e67334f3.json',
+ token: '89eb01df471d990ff5162a1c640408cf',
+ apiUrl: null,
+ },
+ {
+ id: '41',
+ type: 'HTTP',
+ active: true,
+ name: 'Test 9999',
+ url:
+ 'http://127.0.0.1:3000/h5bp/html5-boilerplate/alerts/notify/test-9999/b78a566e1776cfc2.json',
+ token: 'f7579aa03844e07af3b1f0fca3f79f81',
+ apiUrl: null,
+ },
+ {
+ id: '40',
+ type: 'HTTP',
+ active: true,
+ name: 'Test 6',
+ url:
+ 'http://127.0.0.1:3000/h5bp/html5-boilerplate/alerts/notify/test-6/3e828ae28a240222.json',
+ token: '6536102a607a5dd74fcdde921f2349ee',
+ apiUrl: null,
+ },
+ {
+ id: '12',
+ type: 'PROMETHEUS',
+ active: false,
+ name: 'Prometheus',
+ url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/prometheus/alerts/notify.json',
+ token: '256f687c6225aa5d6ee50c3d68120c4c',
+ apiUrl: 'https://localhost.ieeeesassadasasa',
+ },
+ ],
+ },
+ },
+ },
+};
+
+export const integrationToDestroy = {
+ id: '37',
+ type: 'HTTP',
+ active: true,
+ name: 'Test 5',
+ url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/alerts/notify/test-5/d4875758e67334f3.json',
+ token: '89eb01df471d990ff5162a1c640408cf',
+ apiUrl: null,
+};
+
+export const destroyIntegrationResponse = {
+ data: {
+ httpIntegrationDestroy: {
+ errors: [],
+ integration: {
+ id: '37',
+ type: 'HTTP',
+ active: true,
+ name: 'Test 5',
+ url:
+ 'http://127.0.0.1:3000/h5bp/html5-boilerplate/alerts/notify/test-5/d4875758e67334f3.json',
+ token: '89eb01df471d990ff5162a1c640408cf',
+ apiUrl: null,
+ },
+ },
+ },
+};
+
+export const destroyIntegrationResponseWithErrors = {
+ data: {
+ httpIntegrationDestroy: {
+ errors: ['Houston, we have a problem'],
+ integration: {
+ id: '37',
+ type: 'HTTP',
+ active: true,
+ name: 'Test 5',
+ url:
+ 'http://127.0.0.1:3000/h5bp/html5-boilerplate/alerts/notify/test-5/d4875758e67334f3.json',
+ token: '89eb01df471d990ff5162a1c640408cf',
+ apiUrl: null,
+ },
+ },
+ },
+};
diff --git a/spec/frontend/alerts_settings/mocks/integrations.json b/spec/frontend/alerts_settings/mocks/integrations.json
new file mode 100644
index 00000000000..b1284fc55a2
--- /dev/null
+++ b/spec/frontend/alerts_settings/mocks/integrations.json
@@ -0,0 +1,38 @@
+[
+ {
+ "id": "gid://gitlab/AlertManagement::HttpIntegration/7",
+ "type": "HTTP",
+ "active": true,
+ "name": "test",
+ "url": "http://192.168.1.152:3000/root/autodevops/alerts/notify/test/eddd36969b2d3d6a.json",
+ "token": "7eb24af194116411ec8d66b58c6b0d2e",
+ "apiUrl": null
+ },
+ {
+ "id": "gid://gitlab/AlertManagement::HttpIntegration/6",
+ "type": "HTTP",
+ "active": false,
+ "name": "test",
+ "url": "http://192.168.1.152:3000/root/autodevops/alerts/notify/test/abce123.json",
+ "token": "8639e0ce06c731b00ee3e8dcdfd14fe0",
+ "apiUrl": null
+ },
+ {
+ "id": "gid://gitlab/AlertManagement::HttpIntegration/5",
+ "type": "HTTP",
+ "active": false,
+ "name": "test",
+ "url": "http://192.168.1.152:3000/root/autodevops/alerts/notify/test/bcd64c85f918a2e2.json",
+ "token": "5c8101533d970a55d5c105f8abff2192",
+ "apiUrl": null
+ },
+ {
+ "id": "gid://gitlab/PrometheusService/12",
+ "type": "PROMETHEUS",
+ "active": true,
+ "name": "Prometheus",
+ "url": "http://192.168.1.152:3000/root/autodevops/prometheus/alerts/notify.json",
+ "token": "0b18c37caa8fe980799b349916fe5ddf",
+ "apiUrl": "https://another-url-2.com"
+ }
+]
diff --git a/spec/frontend/alerts_settings/util.js b/spec/frontend/alerts_settings/util.js
new file mode 100644
index 00000000000..f9f9b69791e
--- /dev/null
+++ b/spec/frontend/alerts_settings/util.js
@@ -0,0 +1,30 @@
+const PROMETHEUS_URL = '/prometheus/alerts/notify.json';
+const GENERIC_URL = '/alerts/notify.json';
+const KEY = 'abcedfg123';
+const INVALID_URL = 'http://invalid';
+const ACTIVE = false;
+
+export const defaultAlertSettingsConfig = {
+ generic: {
+ authorizationKey: KEY,
+ formPath: INVALID_URL,
+ url: GENERIC_URL,
+ alertsSetupUrl: INVALID_URL,
+ alertsUsageUrl: INVALID_URL,
+ active: ACTIVE,
+ },
+ prometheus: {
+ authorizationKey: KEY,
+ prometheusFormPath: INVALID_URL,
+ url: PROMETHEUS_URL,
+ active: ACTIVE,
+ },
+ opsgenie: {
+ opsgenieMvcIsAvailable: true,
+ formPath: INVALID_URL,
+ active: ACTIVE,
+ opsgenieMvcTargetUrl: GENERIC_URL,
+ },
+ projectPath: '',
+ multiIntegrations: true,
+};
diff --git a/spec/frontend/analytics/instance_statistics/apollo_mock_data.js b/spec/frontend/analytics/instance_statistics/apollo_mock_data.js
index 2e4eaf3fc96..98eabd577ee 100644
--- a/spec/frontend/analytics/instance_statistics/apollo_mock_data.js
+++ b/spec/frontend/analytics/instance_statistics/apollo_mock_data.js
@@ -1,30 +1,36 @@
-const defaultPageInfo = { hasPreviousPage: false, startCursor: null, endCursor: null };
+const defaultPageInfo = {
+ hasNextPage: false,
+ hasPreviousPage: false,
+ startCursor: null,
+ endCursor: null,
+};
-export function getApolloResponse(options = {}) {
- const {
- pipelinesTotal = [],
- pipelinesSucceeded = [],
- pipelinesFailed = [],
- pipelinesCanceled = [],
- pipelinesSkipped = [],
- hasNextPage = false,
- } = options;
- return {
- data: {
- pipelinesTotal: { pageInfo: { ...defaultPageInfo, hasNextPage }, nodes: pipelinesTotal },
- pipelinesSucceeded: {
- pageInfo: { ...defaultPageInfo, hasNextPage },
- nodes: pipelinesSucceeded,
- },
- pipelinesFailed: { pageInfo: { ...defaultPageInfo, hasNextPage }, nodes: pipelinesFailed },
- pipelinesCanceled: {
- pageInfo: { ...defaultPageInfo, hasNextPage },
- nodes: pipelinesCanceled,
- },
- pipelinesSkipped: {
- pageInfo: { ...defaultPageInfo, hasNextPage },
- nodes: pipelinesSkipped,
- },
+export const mockApolloResponse = ({ hasNextPage = false, key, data }) => ({
+ data: {
+ [key]: {
+ pageInfo: { ...defaultPageInfo, hasNextPage },
+ nodes: data,
},
- };
-}
+ },
+});
+
+export const mockQueryResponse = ({ key, data = [], loading = false, additionalData = [] }) => {
+ const hasNextPage = Boolean(additionalData.length);
+ const response = mockApolloResponse({ hasNextPage, key, data });
+ if (loading) {
+ return jest.fn().mockReturnValue(new Promise(() => {}));
+ }
+ if (hasNextPage) {
+ return jest
+ .fn()
+ .mockResolvedValueOnce(response)
+ .mockResolvedValueOnce(
+ mockApolloResponse({
+ hasNextPage: false,
+ key,
+ data: additionalData,
+ }),
+ );
+ }
+ return jest.fn().mockResolvedValue(response);
+};
diff --git a/spec/frontend/analytics/instance_statistics/components/__snapshots__/instance_statistics_count_chart_spec.js.snap b/spec/frontend/analytics/instance_statistics/components/__snapshots__/instance_statistics_count_chart_spec.js.snap
new file mode 100644
index 00000000000..29bcd5f223b
--- /dev/null
+++ b/spec/frontend/analytics/instance_statistics/components/__snapshots__/instance_statistics_count_chart_spec.js.snap
@@ -0,0 +1,41 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`InstanceStatisticsCountChart when fetching more data when the fetchMore query returns data passes the data to the line chart 1`] = `
+Array [
+ Object {
+ "data": Array [
+ Array [
+ "2020-07-01",
+ 41,
+ ],
+ Array [
+ "2020-06-01",
+ 22,
+ ],
+ Array [
+ "2020-08-01",
+ 5,
+ ],
+ ],
+ "name": "Mock Query",
+ },
+]
+`;
+
+exports[`InstanceStatisticsCountChart with data passes the data to the line chart 1`] = `
+Array [
+ Object {
+ "data": Array [
+ Array [
+ "2020-07-01",
+ 41,
+ ],
+ Array [
+ "2020-06-01",
+ 22,
+ ],
+ ],
+ "name": "Mock Query",
+ },
+]
+`;
diff --git a/spec/frontend/analytics/instance_statistics/components/__snapshots__/pipelines_chart_spec.js.snap b/spec/frontend/analytics/instance_statistics/components/__snapshots__/pipelines_chart_spec.js.snap
deleted file mode 100644
index 0b3b685a9f2..00000000000
--- a/spec/frontend/analytics/instance_statistics/components/__snapshots__/pipelines_chart_spec.js.snap
+++ /dev/null
@@ -1,161 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`PipelinesChart when fetching more data when the fetchMore query returns data passes the data to the line chart 1`] = `
-Array [
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 21,
- ],
- Array [
- "2020-07-01",
- 10,
- ],
- Array [
- "2020-08-01",
- 5,
- ],
- ],
- "name": "Total",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 21,
- ],
- Array [
- "2020-07-01",
- 10,
- ],
- Array [
- "2020-08-01",
- 5,
- ],
- ],
- "name": "Succeeded",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 22,
- ],
- Array [
- "2020-07-01",
- 41,
- ],
- Array [
- "2020-08-01",
- 5,
- ],
- ],
- "name": "Failed",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 21,
- ],
- Array [
- "2020-07-01",
- 10,
- ],
- Array [
- "2020-08-01",
- 5,
- ],
- ],
- "name": "Canceled",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 21,
- ],
- Array [
- "2020-07-01",
- 10,
- ],
- Array [
- "2020-08-01",
- 5,
- ],
- ],
- "name": "Skipped",
- },
-]
-`;
-
-exports[`PipelinesChart with data passes the data to the line chart 1`] = `
-Array [
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 22,
- ],
- Array [
- "2020-07-01",
- 41,
- ],
- ],
- "name": "Total",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 21,
- ],
- Array [
- "2020-07-01",
- 10,
- ],
- ],
- "name": "Succeeded",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 21,
- ],
- Array [
- "2020-07-01",
- 10,
- ],
- ],
- "name": "Failed",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 22,
- ],
- Array [
- "2020-07-01",
- 41,
- ],
- ],
- "name": "Canceled",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 22,
- ],
- Array [
- "2020-07-01",
- 41,
- ],
- ],
- "name": "Skipped",
- },
-]
-`;
diff --git a/spec/frontend/analytics/instance_statistics/components/app_spec.js b/spec/frontend/analytics/instance_statistics/components/app_spec.js
index df13c9f82a9..8ac663b3046 100644
--- a/spec/frontend/analytics/instance_statistics/components/app_spec.js
+++ b/spec/frontend/analytics/instance_statistics/components/app_spec.js
@@ -1,8 +1,9 @@
import { shallowMount } from '@vue/test-utils';
import InstanceStatisticsApp from '~/analytics/instance_statistics/components/app.vue';
import InstanceCounts from '~/analytics/instance_statistics/components//instance_counts.vue';
-import PipelinesChart from '~/analytics/instance_statistics/components/pipelines_chart.vue';
+import InstanceStatisticsCountChart from '~/analytics/instance_statistics/components/instance_statistics_count_chart.vue';
import UsersChart from '~/analytics/instance_statistics/components/users_chart.vue';
+import ProjectsAndGroupsChart from '~/analytics/instance_statistics/components/projects_and_groups_chart.vue';
describe('InstanceStatisticsApp', () => {
let wrapper;
@@ -24,11 +25,21 @@ describe('InstanceStatisticsApp', () => {
expect(wrapper.find(InstanceCounts).exists()).toBe(true);
});
- it('displays the pipelines chart component', () => {
- expect(wrapper.find(PipelinesChart).exists()).toBe(true);
+ ['Pipelines', 'Issues & Merge Requests'].forEach(instance => {
+ it(`displays the ${instance} chart`, () => {
+ const chartTitles = wrapper
+ .findAll(InstanceStatisticsCountChart)
+ .wrappers.map(chartComponent => chartComponent.props('chartTitle'));
+
+ expect(chartTitles).toContain(instance);
+ });
});
it('displays the users chart component', () => {
expect(wrapper.find(UsersChart).exists()).toBe(true);
});
+
+ it('displays the projects and groups chart component', () => {
+ expect(wrapper.find(ProjectsAndGroupsChart).exists()).toBe(true);
+ });
});
diff --git a/spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js b/spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js
new file mode 100644
index 00000000000..275a84988f8
--- /dev/null
+++ b/spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js
@@ -0,0 +1,177 @@
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlLineChart } from '@gitlab/ui/dist/charts';
+import { GlAlert } from '@gitlab/ui';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import InstanceStatisticsCountChart from '~/analytics/instance_statistics/components/instance_statistics_count_chart.vue';
+import statsQuery from '~/analytics/instance_statistics/graphql/queries/instance_count.query.graphql';
+import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
+import { mockCountsData1 } from '../mock_data';
+import { mockQueryResponse, mockApolloResponse } from '../apollo_mock_data';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+const loadChartErrorMessage = 'My load error message';
+const noDataMessage = 'My no data message';
+
+const queryResponseDataKey = 'instanceStatisticsMeasurements';
+const identifier = 'MOCK_QUERY';
+const mockQueryConfig = {
+ identifier,
+ title: 'Mock Query',
+ query: statsQuery,
+ loadError: 'Failed to load mock query data',
+};
+
+const mockChartConfig = {
+ loadChartErrorMessage,
+ noDataMessage,
+ chartTitle: 'Foo',
+ yAxisTitle: 'Bar',
+ xAxisTitle: 'Baz',
+ queries: [mockQueryConfig],
+};
+
+describe('InstanceStatisticsCountChart', () => {
+ let wrapper;
+ let queryHandler;
+
+ const createComponent = ({ responseHandler }) => {
+ return shallowMount(InstanceStatisticsCountChart, {
+ localVue,
+ apolloProvider: createMockApollo([[statsQuery, responseHandler]]),
+ propsData: { ...mockChartConfig },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findLoader = () => wrapper.find(ChartSkeletonLoader);
+ const findChart = () => wrapper.find(GlLineChart);
+ const findAlert = () => wrapper.find(GlAlert);
+
+ describe('while loading', () => {
+ beforeEach(() => {
+ queryHandler = mockQueryResponse({ key: queryResponseDataKey, loading: true });
+ wrapper = createComponent({ responseHandler: queryHandler });
+ });
+
+ it('requests data', () => {
+ expect(queryHandler).toBeCalledTimes(1);
+ });
+
+ it('displays the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('hides the chart', () => {
+ expect(findChart().exists()).toBe(false);
+ });
+
+ it('does not show an error', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('without data', () => {
+ beforeEach(() => {
+ queryHandler = mockQueryResponse({ key: queryResponseDataKey, data: [] });
+ wrapper = createComponent({ responseHandler: queryHandler });
+ });
+
+ it('renders an no data message', () => {
+ expect(findAlert().text()).toBe(noDataMessage);
+ });
+
+ it('hides the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('renders the chart', () => {
+ expect(findChart().exists()).toBe(false);
+ });
+ });
+
+ describe('with data', () => {
+ beforeEach(() => {
+ queryHandler = mockQueryResponse({ key: queryResponseDataKey, data: mockCountsData1 });
+ wrapper = createComponent({ responseHandler: queryHandler });
+ });
+
+ it('requests data', () => {
+ expect(queryHandler).toBeCalledTimes(1);
+ });
+
+ it('hides the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('renders the chart', () => {
+ expect(findChart().exists()).toBe(true);
+ });
+
+ it('passes the data to the line chart', () => {
+ expect(findChart().props('data')).toMatchSnapshot();
+ });
+
+ it('does not show an error', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('when fetching more data', () => {
+ const recordedAt = '2020-08-01';
+ describe('when the fetchMore query returns data', () => {
+ beforeEach(async () => {
+ const newData = [{ recordedAt, count: 5 }];
+ queryHandler = mockQueryResponse({
+ key: queryResponseDataKey,
+ data: mockCountsData1,
+ additionalData: newData,
+ });
+
+ wrapper = createComponent({ responseHandler: queryHandler });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('requests data twice', () => {
+ expect(queryHandler).toBeCalledTimes(2);
+ });
+
+ it('passes the data to the line chart', () => {
+ expect(findChart().props('data')).toMatchSnapshot();
+ });
+ });
+
+ describe('when the fetchMore query throws an error', () => {
+ beforeEach(async () => {
+ queryHandler = jest.fn().mockResolvedValueOnce(
+ mockApolloResponse({
+ key: queryResponseDataKey,
+ data: mockCountsData1,
+ hasNextPage: true,
+ }),
+ );
+
+ wrapper = createComponent({ responseHandler: queryHandler });
+ jest
+ .spyOn(wrapper.vm.$apollo.queries[identifier], 'fetchMore')
+ .mockImplementation(jest.fn().mockRejectedValue());
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it('calls fetchMore', () => {
+ expect(wrapper.vm.$apollo.queries[identifier].fetchMore).toHaveBeenCalledTimes(1);
+ });
+
+ it('show an error message', () => {
+ expect(findAlert().text()).toBe(loadChartErrorMessage);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/analytics/instance_statistics/components/pipelines_chart_spec.js b/spec/frontend/analytics/instance_statistics/components/pipelines_chart_spec.js
deleted file mode 100644
index a06d66f783e..00000000000
--- a/spec/frontend/analytics/instance_statistics/components/pipelines_chart_spec.js
+++ /dev/null
@@ -1,189 +0,0 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlLineChart } from '@gitlab/ui/dist/charts';
-import { GlAlert } from '@gitlab/ui';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
-import PipelinesChart from '~/analytics/instance_statistics/components/pipelines_chart.vue';
-import pipelinesStatsQuery from '~/analytics/instance_statistics/graphql/queries/pipeline_stats.query.graphql';
-import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
-import { mockCountsData1, mockCountsData2 } from '../mock_data';
-import { getApolloResponse } from '../apollo_mock_data';
-
-const localVue = createLocalVue();
-localVue.use(VueApollo);
-
-describe('PipelinesChart', () => {
- let wrapper;
- let queryHandler;
-
- const createApolloProvider = pipelineStatsHandler => {
- return createMockApollo([[pipelinesStatsQuery, pipelineStatsHandler]]);
- };
-
- const createComponent = apolloProvider => {
- return shallowMount(PipelinesChart, {
- localVue,
- apolloProvider,
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- const findLoader = () => wrapper.find(ChartSkeletonLoader);
- const findChart = () => wrapper.find(GlLineChart);
- const findAlert = () => wrapper.find(GlAlert);
-
- describe('while loading', () => {
- beforeEach(() => {
- queryHandler = jest.fn().mockReturnValue(new Promise(() => {}));
- const apolloProvider = createApolloProvider(queryHandler);
- wrapper = createComponent(apolloProvider);
- });
-
- it('requests data', () => {
- expect(queryHandler).toBeCalledTimes(1);
- });
-
- it('displays the skeleton loader', () => {
- expect(findLoader().exists()).toBe(true);
- });
-
- it('hides the chart', () => {
- expect(findChart().exists()).toBe(false);
- });
-
- it('does not show an error', () => {
- expect(findAlert().exists()).toBe(false);
- });
- });
-
- describe('without data', () => {
- beforeEach(() => {
- const emptyResponse = getApolloResponse();
- queryHandler = jest.fn().mockResolvedValue(emptyResponse);
- const apolloProvider = createApolloProvider(queryHandler);
- wrapper = createComponent(apolloProvider);
- });
-
- it('renders an no data message', () => {
- expect(findAlert().text()).toBe('There is no data available.');
- });
-
- it('hides the skeleton loader', () => {
- expect(findLoader().exists()).toBe(false);
- });
-
- it('renders the chart', () => {
- expect(findChart().exists()).toBe(false);
- });
- });
-
- describe('with data', () => {
- beforeEach(() => {
- const response = getApolloResponse({
- pipelinesTotal: mockCountsData1,
- pipelinesSucceeded: mockCountsData2,
- pipelinesFailed: mockCountsData2,
- pipelinesCanceled: mockCountsData1,
- pipelinesSkipped: mockCountsData1,
- });
- queryHandler = jest.fn().mockResolvedValue(response);
- const apolloProvider = createApolloProvider(queryHandler);
- wrapper = createComponent(apolloProvider);
- });
-
- it('requests data', () => {
- expect(queryHandler).toBeCalledTimes(1);
- });
-
- it('hides the skeleton loader', () => {
- expect(findLoader().exists()).toBe(false);
- });
-
- it('renders the chart', () => {
- expect(findChart().exists()).toBe(true);
- });
-
- it('passes the data to the line chart', () => {
- expect(findChart().props('data')).toMatchSnapshot();
- });
-
- it('does not show an error', () => {
- expect(findAlert().exists()).toBe(false);
- });
- });
-
- describe('when fetching more data', () => {
- const recordedAt = '2020-08-01';
- describe('when the fetchMore query returns data', () => {
- beforeEach(async () => {
- const newData = { recordedAt, count: 5 };
- const firstResponse = getApolloResponse({
- pipelinesTotal: mockCountsData2,
- pipelinesSucceeded: mockCountsData2,
- pipelinesFailed: mockCountsData1,
- pipelinesCanceled: mockCountsData2,
- pipelinesSkipped: mockCountsData2,
- hasNextPage: true,
- });
- const secondResponse = getApolloResponse({
- pipelinesTotal: [newData],
- pipelinesSucceeded: [newData],
- pipelinesFailed: [newData],
- pipelinesCanceled: [newData],
- pipelinesSkipped: [newData],
- hasNextPage: false,
- });
- queryHandler = jest
- .fn()
- .mockResolvedValueOnce(firstResponse)
- .mockResolvedValueOnce(secondResponse);
- const apolloProvider = createApolloProvider(queryHandler);
- wrapper = createComponent(apolloProvider);
-
- await wrapper.vm.$nextTick();
- });
-
- it('requests data twice', () => {
- expect(queryHandler).toBeCalledTimes(2);
- });
-
- it('passes the data to the line chart', () => {
- expect(findChart().props('data')).toMatchSnapshot();
- });
- });
-
- describe('when the fetchMore query throws an error', () => {
- beforeEach(async () => {
- const response = getApolloResponse({
- pipelinesTotal: mockCountsData2,
- pipelinesSucceeded: mockCountsData2,
- pipelinesFailed: mockCountsData1,
- pipelinesCanceled: mockCountsData2,
- pipelinesSkipped: mockCountsData2,
- hasNextPage: true,
- });
- queryHandler = jest.fn().mockResolvedValue(response);
- const apolloProvider = createApolloProvider(queryHandler);
- wrapper = createComponent(apolloProvider);
- jest
- .spyOn(wrapper.vm.$apollo.queries.pipelineStats, 'fetchMore')
- .mockImplementation(jest.fn().mockRejectedValue());
- await wrapper.vm.$nextTick();
- });
-
- it('calls fetchMore', () => {
- expect(wrapper.vm.$apollo.queries.pipelineStats.fetchMore).toHaveBeenCalledTimes(1);
- });
-
- it('show an error message', () => {
- expect(findAlert().text()).toBe(
- 'Could not load the pipelines chart. Please refresh the page to try again.',
- );
- });
- });
- });
-});
diff --git a/spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js b/spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js
new file mode 100644
index 00000000000..d9f42430aa8
--- /dev/null
+++ b/spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js
@@ -0,0 +1,216 @@
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlLineChart } from '@gitlab/ui/dist/charts';
+import { GlAlert } from '@gitlab/ui';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import { useFakeDate } from 'helpers/fake_date';
+import ProjectsAndGroupChart from '~/analytics/instance_statistics/components/projects_and_groups_chart.vue';
+import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
+import projectsQuery from '~/analytics/instance_statistics/graphql/queries/projects.query.graphql';
+import groupsQuery from '~/analytics/instance_statistics/graphql/queries/groups.query.graphql';
+import { mockCountsData2, roundedSortedCountsMonthlyChartData2 } from '../mock_data';
+import { mockQueryResponse } from '../apollo_mock_data';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('ProjectsAndGroupChart', () => {
+ let wrapper;
+ let queryResponses = { projects: null, groups: null };
+ const mockAdditionalData = [{ recordedAt: '2020-07-21', count: 5 }];
+
+ const createComponent = ({
+ loadingError = false,
+ projects = [],
+ groups = [],
+ projectsLoading = false,
+ groupsLoading = false,
+ projectsAdditionalData = [],
+ groupsAdditionalData = [],
+ } = {}) => {
+ queryResponses = {
+ projects: mockQueryResponse({
+ key: 'projects',
+ data: projects,
+ loading: projectsLoading,
+ additionalData: projectsAdditionalData,
+ }),
+ groups: mockQueryResponse({
+ key: 'groups',
+ data: groups,
+ loading: groupsLoading,
+ additionalData: groupsAdditionalData,
+ }),
+ };
+
+ return shallowMount(ProjectsAndGroupChart, {
+ props: {
+ startDate: useFakeDate(2020, 9, 26),
+ endDate: useFakeDate(2020, 10, 1),
+ totalDataPoints: mockCountsData2.length,
+ },
+ localVue,
+ apolloProvider: createMockApollo([
+ [projectsQuery, queryResponses.projects],
+ [groupsQuery, queryResponses.groups],
+ ]),
+ data() {
+ return { loadingError };
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ queryResponses = {
+ projects: null,
+ groups: null,
+ };
+ });
+
+ const findLoader = () => wrapper.find(ChartSkeletonLoader);
+ const findAlert = () => wrapper.find(GlAlert);
+ const findChart = () => wrapper.find(GlLineChart);
+
+ describe('while loading', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ projectsLoading: true, groupsLoading: true });
+ });
+
+ it('displays the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('hides the chart', () => {
+ expect(findChart().exists()).toBe(false);
+ });
+ });
+
+ describe('while loading 1 data set', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({
+ projects: mockCountsData2,
+ groupsLoading: true,
+ });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it('hides the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('renders the chart', () => {
+ expect(findChart().exists()).toBe(true);
+ });
+ });
+
+ describe('without data', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({ projects: [] });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('renders a no data message', () => {
+ expect(findAlert().text()).toBe('No data available.');
+ });
+
+ it('hides the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('does not render the chart', () => {
+ expect(findChart().exists()).toBe(false);
+ });
+ });
+
+ describe('with data', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({ projects: mockCountsData2 });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('hides the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('renders the chart', () => {
+ expect(findChart().exists()).toBe(true);
+ });
+
+ it('passes the data to the line chart', () => {
+ expect(findChart().props('data')).toEqual([
+ { data: roundedSortedCountsMonthlyChartData2, name: 'Total projects' },
+ { data: [], name: 'Total groups' },
+ ]);
+ });
+ });
+
+ describe('with errors', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({ loadingError: true });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('renders an error message', () => {
+ expect(findAlert().text()).toBe('No data available.');
+ });
+
+ it('hides the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('hides the chart', () => {
+ expect(findChart().exists()).toBe(false);
+ });
+ });
+
+ describe.each`
+ metric | loadingState | newData
+ ${'projects'} | ${{ projectsAdditionalData: mockAdditionalData }} | ${{ projects: mockCountsData2 }}
+ ${'groups'} | ${{ groupsAdditionalData: mockAdditionalData }} | ${{ groups: mockCountsData2 }}
+ `('$metric - fetchMore', ({ metric, loadingState, newData }) => {
+ describe('when the fetchMore query returns data', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({
+ ...loadingState,
+ ...newData,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo.queries[metric], 'fetchMore');
+ await wrapper.vm.$nextTick();
+ });
+
+ it('requests data twice', () => {
+ expect(queryResponses[metric]).toBeCalledTimes(2);
+ });
+
+ it('calls fetchMore', () => {
+ expect(wrapper.vm.$apollo.queries[metric].fetchMore).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('when the fetchMore query throws an error', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ ...loadingState,
+ ...newData,
+ });
+
+ jest
+ .spyOn(wrapper.vm.$apollo.queries[metric], 'fetchMore')
+ .mockImplementation(jest.fn().mockRejectedValue());
+ return wrapper.vm.$nextTick();
+ });
+
+ it('calls fetchMore', () => {
+ expect(wrapper.vm.$apollo.queries[metric].fetchMore).toHaveBeenCalledTimes(1);
+ });
+
+ it('renders an error message', () => {
+ expect(findAlert().text()).toBe('No data available.');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js b/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js
index 7509c1e6626..6ed9d203f3d 100644
--- a/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js
+++ b/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js
@@ -7,7 +7,12 @@ import { useFakeDate } from 'helpers/fake_date';
import UsersChart from '~/analytics/instance_statistics/components/users_chart.vue';
import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
import usersQuery from '~/analytics/instance_statistics/graphql/queries/users.query.graphql';
-import { mockCountsData2, roundedSortedCountsMonthlyChartData2, mockPageInfo } from '../mock_data';
+import {
+ mockCountsData1,
+ mockCountsData2,
+ roundedSortedCountsMonthlyChartData2,
+} from '../mock_data';
+import { mockQueryResponse } from '../apollo_mock_data';
const localVue = createLocalVue();
localVue.use(VueApollo);
@@ -16,43 +21,13 @@ describe('UsersChart', () => {
let wrapper;
let queryHandler;
- const mockApolloResponse = ({ loading = false, hasNextPage = false, users }) => ({
- data: {
- users: {
- pageInfo: { ...mockPageInfo, hasNextPage },
- nodes: users,
- loading,
- },
- },
- });
-
- const mockQueryResponse = ({ users, loading = false, hasNextPage = false }) => {
- const apolloQueryResponse = mockApolloResponse({ loading, hasNextPage, users });
- if (loading) {
- return jest.fn().mockReturnValue(new Promise(() => {}));
- }
- if (hasNextPage) {
- return jest
- .fn()
- .mockResolvedValueOnce(apolloQueryResponse)
- .mockResolvedValueOnce(
- mockApolloResponse({
- loading,
- hasNextPage: false,
- users: [{ recordedAt: '2020-07-21', count: 5 }],
- }),
- );
- }
- return jest.fn().mockResolvedValue(apolloQueryResponse);
- };
-
const createComponent = ({
loadingError = false,
loading = false,
users = [],
- hasNextPage = false,
+ additionalData = [],
} = {}) => {
- queryHandler = mockQueryResponse({ users, loading, hasNextPage });
+ queryHandler = mockQueryResponse({ key: 'users', data: users, loading, additionalData });
return shallowMount(UsersChart, {
props: {
@@ -157,7 +132,7 @@ describe('UsersChart', () => {
beforeEach(async () => {
wrapper = createComponent({
users: mockCountsData2,
- hasNextPage: true,
+ additionalData: mockCountsData1,
});
jest.spyOn(wrapper.vm.$apollo.queries.users, 'fetchMore');
@@ -177,7 +152,7 @@ describe('UsersChart', () => {
beforeEach(() => {
wrapper = createComponent({
users: mockCountsData2,
- hasNextPage: true,
+ additionalData: mockCountsData1,
});
jest
diff --git a/spec/frontend/analytics/instance_statistics/mock_data.js b/spec/frontend/analytics/instance_statistics/mock_data.js
index b737db4c55f..e86e552a952 100644
--- a/spec/frontend/analytics/instance_statistics/mock_data.js
+++ b/spec/frontend/analytics/instance_statistics/mock_data.js
@@ -33,10 +33,3 @@ export const roundedSortedCountsMonthlyChartData2 = [
['2020-06-01', 21], // average of 2020-06-x items
['2020-07-01', 10], // average of 2020-07-x items
];
-
-export const mockPageInfo = {
- hasNextPage: false,
- hasPreviousPage: false,
- startCursor: null,
- endCursor: null,
-};
diff --git a/spec/frontend/analytics/instance_statistics/utils_spec.js b/spec/frontend/analytics/instance_statistics/utils_spec.js
index d480238419b..3fd89c7f740 100644
--- a/spec/frontend/analytics/instance_statistics/utils_spec.js
+++ b/spec/frontend/analytics/instance_statistics/utils_spec.js
@@ -1,7 +1,7 @@
import {
getAverageByMonth,
- extractValues,
- sortByDate,
+ getEarliestDate,
+ generateDataKeys,
} from '~/analytics/instance_statistics/utils';
import {
mockCountsData1,
@@ -44,41 +44,38 @@ describe('getAverageByMonth', () => {
});
});
-describe('extractValues', () => {
- it('extracts only requested values', () => {
- const data = { fooBar: { baz: 'quis' }, ignored: 'ignored' };
- expect(extractValues(data, ['fooBar'], 'foo', 'baz')).toEqual({ bazBar: 'quis' });
+describe('getEarliestDate', () => {
+ it('returns the date of the final item in the array', () => {
+ expect(getEarliestDate(mockCountsData1)).toBe('2020-06-12');
});
- it('is able to extract multiple values', () => {
- const data = {
- fooBar: { baz: 'quis' },
- fooBaz: { baz: 'quis' },
- fooQuis: { baz: 'quis' },
- };
- expect(extractValues(data, ['fooBar', 'fooBaz', 'fooQuis'], 'foo', 'baz')).toEqual({
- bazBar: 'quis',
- bazBaz: 'quis',
- bazQuis: 'quis',
- });
- });
-
- it('returns empty data set when keys are not found', () => {
- const data = { foo: { baz: 'quis' }, ignored: 'ignored' };
- expect(extractValues(data, ['fooBar'], 'foo', 'baz')).toEqual({});
+ it('returns null for an empty array', () => {
+ expect(getEarliestDate([])).toBeNull();
});
- it('returns empty data when params are missing', () => {
- expect(extractValues()).toEqual({});
+ it("returns null if the array has data but `recordedAt` isn't defined", () => {
+ expect(
+ getEarliestDate(mockCountsData1.map(({ recordedAt: date, ...rest }) => ({ date, ...rest }))),
+ ).toBeNull();
});
});
-describe('sortByDate', () => {
- it('sorts the array by date', () => {
- expect(sortByDate(mockCountsData1)).toStrictEqual([...mockCountsData1].reverse());
+describe('generateDataKeys', () => {
+ const fakeQueries = [
+ { identifier: 'from' },
+ { identifier: 'first' },
+ { identifier: 'to' },
+ { identifier: 'last' },
+ ];
+
+ const defaultValue = 'default value';
+ const res = generateDataKeys(fakeQueries, defaultValue);
+
+ it('extracts each query identifier and sets them as object keys', () => {
+ expect(Object.keys(res)).toEqual(['from', 'first', 'to', 'last']);
});
- it('does not modify the original array', () => {
- expect(sortByDate(countsMonthlyChartData1)).not.toBe(countsMonthlyChartData1);
+ it('sets every value to the `defaultValue` provided', () => {
+ expect(Object.values(res)).toEqual(Array(fakeQueries.length).fill(defaultValue));
});
});
diff --git a/spec/frontend/api_spec.js b/spec/frontend/api_spec.js
index 9924525929b..724d33922a1 100644
--- a/spec/frontend/api_spec.js
+++ b/spec/frontend/api_spec.js
@@ -118,6 +118,24 @@ describe('Api', () => {
});
});
+ describe('container registry', () => {
+ describe('containerRegistryDetails', () => {
+ it('fetch container registry details', async () => {
+ const expectedUrl = `foo`;
+ const apiResponse = {};
+
+ jest.spyOn(axios, 'get');
+ jest.spyOn(Api, 'buildUrl').mockReturnValueOnce(expectedUrl);
+ mock.onGet(expectedUrl).replyOnce(httpStatus.OK, apiResponse);
+
+ const { data } = await Api.containerRegistryDetails(1);
+
+ expect(data).toEqual(apiResponse);
+ expect(axios.get).toHaveBeenCalledWith(expectedUrl, {});
+ });
+ });
+ });
+
describe('group', () => {
it('fetches a group', done => {
const groupId = '123456';
@@ -535,14 +553,15 @@ describe('Api', () => {
});
describe('issueTemplate', () => {
+ const namespace = 'some namespace';
+ const project = 'some project';
+ const templateKey = ' template #%?.key ';
+ const templateType = 'template type';
+ const expectedUrl = `${dummyUrlRoot}/${namespace}/${project}/templates/${templateType}/${encodeURIComponent(
+ templateKey,
+ )}`;
+
it('fetches an issue template', done => {
- const namespace = 'some namespace';
- const project = 'some project';
- const templateKey = ' template #%?.key ';
- const templateType = 'template type';
- const expectedUrl = `${dummyUrlRoot}/${namespace}/${project}/templates/${templateType}/${encodeURIComponent(
- templateKey,
- )}`;
mock.onGet(expectedUrl).reply(httpStatus.OK, 'test');
Api.issueTemplate(namespace, project, templateKey, templateType, (error, response) => {
@@ -550,6 +569,49 @@ describe('Api', () => {
done();
});
});
+
+ describe('when an error occurs while fetching an issue template', () => {
+ it('rejects the Promise', () => {
+ mock.onGet(expectedUrl).replyOnce(httpStatus.INTERNAL_SERVER_ERROR);
+
+ Api.issueTemplate(namespace, project, templateKey, templateType, () => {
+ expect(mock.history.get).toHaveLength(1);
+ });
+ });
+ });
+ });
+
+ describe('issueTemplates', () => {
+ const namespace = 'some namespace';
+ const project = 'some project';
+ const templateType = 'template type';
+ const expectedUrl = `${dummyUrlRoot}/${namespace}/${project}/templates/${templateType}`;
+
+ it('fetches all templates by type', done => {
+ const expectedData = [
+ { key: 'Template1', name: 'Template 1', content: 'This is template 1!' },
+ ];
+ mock.onGet(expectedUrl).reply(httpStatus.OK, expectedData);
+
+ Api.issueTemplates(namespace, project, templateType, (error, response) => {
+ expect(response.length).toBe(1);
+ const { key, name, content } = response[0];
+ expect(key).toBe('Template1');
+ expect(name).toBe('Template 1');
+ expect(content).toBe('This is template 1!');
+ done();
+ });
+ });
+
+ describe('when an error occurs while fetching issue templates', () => {
+ it('rejects the Promise', () => {
+ mock.onGet(expectedUrl).replyOnce(httpStatus.INTERNAL_SERVER_ERROR);
+
+ Api.issueTemplates(namespace, project, templateType, () => {
+ expect(mock.history.get).toHaveLength(1);
+ });
+ });
+ });
});
describe('projectTemplates', () => {
@@ -692,24 +754,23 @@ describe('Api', () => {
});
describe('pipelineJobs', () => {
- it('fetches the jobs for a given pipeline', done => {
- const projectId = 123;
- const pipelineId = 456;
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectId}/pipelines/${pipelineId}/jobs`;
- const payload = [
- {
- name: 'test',
- },
- ];
- mock.onGet(expectedUrl).reply(httpStatus.OK, payload);
+ it.each([undefined, {}, { foo: true }])(
+ 'fetches the jobs for a given pipeline given %p params',
+ async params => {
+ const projectId = 123;
+ const pipelineId = 456;
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectId}/pipelines/${pipelineId}/jobs`;
+ const payload = [
+ {
+ name: 'test',
+ },
+ ];
+ mock.onGet(expectedUrl, { params }).reply(httpStatus.OK, payload);
- Api.pipelineJobs(projectId, pipelineId)
- .then(({ data }) => {
- expect(data).toEqual(payload);
- })
- .then(done)
- .catch(done.fail);
- });
+ const { data } = await Api.pipelineJobs(projectId, pipelineId, params);
+ expect(data).toEqual(payload);
+ },
+ );
});
describe('createBranch', () => {
@@ -1232,4 +1293,91 @@ describe('Api', () => {
});
});
});
+
+ describe('Feature Flag User List', () => {
+ let expectedUrl;
+ let projectId;
+ let mockUserList;
+
+ beforeEach(() => {
+ projectId = 1000;
+ expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectId}/feature_flags_user_lists`;
+ mockUserList = {
+ name: 'mock_user_list',
+ user_xids: '1,2,3,4',
+ project_id: 1,
+ id: 1,
+ iid: 1,
+ };
+ });
+
+ describe('fetchFeatureFlagUserLists', () => {
+ it('GETs the right url', () => {
+ mock.onGet(expectedUrl).replyOnce(httpStatus.OK, []);
+
+ return Api.fetchFeatureFlagUserLists(projectId).then(({ data }) => {
+ expect(data).toEqual([]);
+ });
+ });
+ });
+
+ describe('searchFeatureFlagUserLists', () => {
+ it('GETs the right url', () => {
+ mock.onGet(expectedUrl, { params: { search: 'test' } }).replyOnce(httpStatus.OK, []);
+
+ return Api.searchFeatureFlagUserLists(projectId, 'test').then(({ data }) => {
+ expect(data).toEqual([]);
+ });
+ });
+ });
+
+ describe('createFeatureFlagUserList', () => {
+ it('POSTs data to the right url', () => {
+ const mockUserListData = {
+ name: 'mock_user_list',
+ user_xids: '1,2,3,4',
+ };
+ mock.onPost(expectedUrl, mockUserListData).replyOnce(httpStatus.OK, mockUserList);
+
+ return Api.createFeatureFlagUserList(projectId, mockUserListData).then(({ data }) => {
+ expect(data).toEqual(mockUserList);
+ });
+ });
+ });
+
+ describe('fetchFeatureFlagUserList', () => {
+ it('GETs the right url', () => {
+ mock.onGet(`${expectedUrl}/1`).replyOnce(httpStatus.OK, mockUserList);
+
+ return Api.fetchFeatureFlagUserList(projectId, 1).then(({ data }) => {
+ expect(data).toEqual(mockUserList);
+ });
+ });
+ });
+
+ describe('updateFeatureFlagUserList', () => {
+ it('PUTs the right url', () => {
+ mock
+ .onPut(`${expectedUrl}/1`)
+ .replyOnce(httpStatus.OK, { ...mockUserList, user_xids: '5' });
+
+ return Api.updateFeatureFlagUserList(projectId, {
+ ...mockUserList,
+ user_xids: '5',
+ }).then(({ data }) => {
+ expect(data).toEqual({ ...mockUserList, user_xids: '5' });
+ });
+ });
+ });
+
+ describe('deleteFeatureFlagUserList', () => {
+ it('DELETEs the right url', () => {
+ mock.onDelete(`${expectedUrl}/1`).replyOnce(httpStatus.OK, 'deleted');
+
+ return Api.deleteFeatureFlagUserList(projectId, 1).then(({ data }) => {
+ expect(data).toBe('deleted');
+ });
+ });
+ });
+ });
});
diff --git a/spec/frontend/awards_handler_spec.js b/spec/frontend/awards_handler_spec.js
index 7fd6a9e7b87..c6a9c911ccf 100644
--- a/spec/frontend/awards_handler_spec.js
+++ b/spec/frontend/awards_handler_spec.js
@@ -169,29 +169,6 @@ describe('AwardsHandler', () => {
});
});
- describe('::userAuthored', () => {
- it('should update tooltip to user authored title', () => {
- const $votesBlock = $('.js-awards-block').eq(0);
- const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
- $thumbsUpEmoji.attr('data-title', 'sam');
- awardsHandler.userAuthored($thumbsUpEmoji);
-
- expect($thumbsUpEmoji.data('originalTitle')).toBe(
- 'You cannot vote on your own issue, MR and note',
- );
- });
-
- it('should restore tooltip back to initial vote list', () => {
- const $votesBlock = $('.js-awards-block').eq(0);
- const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
- $thumbsUpEmoji.attr('data-title', 'sam');
- awardsHandler.userAuthored($thumbsUpEmoji);
- jest.advanceTimersByTime(2801);
-
- expect($thumbsUpEmoji.data('originalTitle')).toBe('sam');
- });
- });
-
describe('::getAwardUrl', () => {
it('returns the url for request', () => {
expect(awardsHandler.getAwardUrl()).toBe('http://test.host/-/snippets/1/toggle_award_emoji');
diff --git a/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js b/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
index baedbf5771a..77dcc28dd48 100644
--- a/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
+++ b/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
@@ -1,20 +1,19 @@
import $ from 'jquery';
-import 'mousetrap';
+import Mousetrap from 'mousetrap';
import initCopyAsGFM, { CopyAsGFM } from '~/behaviors/markdown/copy_as_gfm';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import { getSelectedFragment } from '~/lib/utils/common_utils';
-const FORM_SELECTOR = '.js-main-target-form .js-vue-comment-form';
-
jest.mock('~/lib/utils/common_utils', () => ({
...jest.requireActual('~/lib/utils/common_utils'),
getSelectedFragment: jest.fn().mockName('getSelectedFragment'),
}));
describe('ShortcutsIssuable', () => {
- const fixtureName = 'snippets/show.html';
+ const snippetShowFixtureName = 'snippets/show.html';
+ const mrShowFixtureName = 'merge_requests/merge_request_of_current_user.html';
- preloadFixtures(fixtureName);
+ preloadFixtures(snippetShowFixtureName, mrShowFixtureName);
beforeAll(done => {
initCopyAsGFM();
@@ -27,25 +26,27 @@ describe('ShortcutsIssuable', () => {
.catch(done.fail);
});
- beforeEach(() => {
- loadFixtures(fixtureName);
- $('body').append(
- `<div class="js-main-target-form">
- <textarea class="js-vue-comment-form"></textarea>
- </div>`,
- );
- document.querySelector('.js-new-note-form').classList.add('js-main-target-form');
-
- window.shortcut = new ShortcutsIssuable(true);
- });
+ describe('replyWithSelectedText', () => {
+ const FORM_SELECTOR = '.js-main-target-form .js-vue-comment-form';
+
+ beforeEach(() => {
+ loadFixtures(snippetShowFixtureName);
+ $('body').append(
+ `<div class="js-main-target-form">
+ <textarea class="js-vue-comment-form"></textarea>
+ </div>`,
+ );
+ document.querySelector('.js-new-note-form').classList.add('js-main-target-form');
+
+ window.shortcut = new ShortcutsIssuable(true);
+ });
- afterEach(() => {
- $(FORM_SELECTOR).remove();
+ afterEach(() => {
+ $(FORM_SELECTOR).remove();
- delete window.shortcut;
- });
+ delete window.shortcut;
+ });
- describe('replyWithSelectedText', () => {
// Stub getSelectedFragment to return a node with the provided HTML.
const stubSelection = (html, invalidNode) => {
getSelectedFragment.mockImplementation(() => {
@@ -319,4 +320,55 @@ describe('ShortcutsIssuable', () => {
});
});
});
+
+ describe('copyBranchName', () => {
+ let sidebarCollapsedBtn;
+ let sidebarExpandedBtn;
+
+ beforeEach(() => {
+ loadFixtures(mrShowFixtureName);
+
+ window.shortcut = new ShortcutsIssuable();
+
+ [sidebarCollapsedBtn, sidebarExpandedBtn] = document.querySelectorAll(
+ '.sidebar-source-branch button',
+ );
+
+ [sidebarCollapsedBtn, sidebarExpandedBtn].forEach(btn => jest.spyOn(btn, 'click'));
+ });
+
+ afterEach(() => {
+ delete window.shortcut;
+ });
+
+ describe('when the sidebar is expanded', () => {
+ beforeEach(() => {
+ // simulate the applied CSS styles when the
+ // sidebar is expanded
+ sidebarCollapsedBtn.style.display = 'none';
+
+ Mousetrap.trigger('b');
+ });
+
+ it('clicks the "expanded" version of the copy source branch button', () => {
+ expect(sidebarExpandedBtn.click).toHaveBeenCalled();
+ expect(sidebarCollapsedBtn.click).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('when the sidebar is collapsed', () => {
+ beforeEach(() => {
+ // simulate the applied CSS styles when the
+ // sidebar is collapsed
+ sidebarExpandedBtn.style.display = 'none';
+
+ Mousetrap.trigger('b');
+ });
+
+ it('clicks the "collapsed" version of the copy source branch button', () => {
+ expect(sidebarCollapsedBtn.click).toHaveBeenCalled();
+ expect(sidebarExpandedBtn.click).not.toHaveBeenCalled();
+ });
+ });
+ });
});
diff --git a/spec/frontend/blob/components/blob_header_default_actions_spec.js b/spec/frontend/blob/components/blob_header_default_actions_spec.js
index 590e36b16af..e2c73a5d5d9 100644
--- a/spec/frontend/blob/components/blob_header_default_actions_spec.js
+++ b/spec/frontend/blob/components/blob_header_default_actions_spec.js
@@ -14,8 +14,13 @@ describe('Blob Header Default Actions', () => {
let btnGroup;
let buttons;
+ const blobHash = 'foo-bar';
+
function createComponent(propsData = {}) {
wrapper = mount(BlobHeaderActions, {
+ provide: {
+ blobHash,
+ },
propsData: {
rawPath: Blob.rawPath,
...propsData,
diff --git a/spec/frontend/blob/components/blob_header_filepath_spec.js b/spec/frontend/blob/components/blob_header_filepath_spec.js
index 43057353051..067a4ae61a0 100644
--- a/spec/frontend/blob/components/blob_header_filepath_spec.js
+++ b/spec/frontend/blob/components/blob_header_filepath_spec.js
@@ -65,7 +65,7 @@ describe('Blob Header Filepath', () => {
{},
{
scopedSlots: {
- filepathPrepend: `<span>${slotContent}</span>`,
+ 'filepath-prepend': `<span>${slotContent}</span>`,
},
},
);
diff --git a/spec/frontend/blob/components/blob_header_spec.js b/spec/frontend/blob/components/blob_header_spec.js
index 01d4bf834d2..3e84347bee4 100644
--- a/spec/frontend/blob/components/blob_header_spec.js
+++ b/spec/frontend/blob/components/blob_header_spec.js
@@ -11,7 +11,11 @@ describe('Blob Header Default Actions', () => {
function createComponent(blobProps = {}, options = {}, propsData = {}, shouldMount = false) {
const method = shouldMount ? mount : shallowMount;
+ const blobHash = 'foo-bar';
wrapper = method.call(this, BlobHeader, {
+ provide: {
+ blobHash,
+ },
propsData: {
blob: { ...Blob, ...blobProps },
...propsData,
diff --git a/spec/frontend/blob/pipeline_tour_success_mock_data.js b/spec/frontend/blob/pipeline_tour_success_mock_data.js
index 9dea3969d63..dbcba469df5 100644
--- a/spec/frontend/blob/pipeline_tour_success_mock_data.js
+++ b/spec/frontend/blob/pipeline_tour_success_mock_data.js
@@ -3,6 +3,8 @@ const modalProps = {
projectMergeRequestsPath: 'some_mr_path',
commitCookie: 'some_cookie',
humanAccess: 'maintainer',
+ exampleLink: '/example',
+ codeQualityLink: '/code-quality-link',
};
export default modalProps;
diff --git a/spec/frontend/blob/pipeline_tour_success_modal_spec.js b/spec/frontend/blob/pipeline_tour_success_modal_spec.js
index a02c968c4b5..e8011558765 100644
--- a/spec/frontend/blob/pipeline_tour_success_modal_spec.js
+++ b/spec/frontend/blob/pipeline_tour_success_modal_spec.js
@@ -75,7 +75,7 @@ describe('PipelineTourSuccessModal', () => {
});
it('renders the link for codeQualityLink', () => {
- expect(wrapper.find(GlLink).attributes('href')).toBe(wrapper.vm.$options.codeQualityLink);
+ expect(wrapper.find(GlLink).attributes('href')).toBe('/code-quality-link');
});
it('calls to remove cookie', () => {
diff --git a/spec/frontend/boards/board_list_new_spec.js b/spec/frontend/boards/board_list_new_spec.js
index 163611c2197..55516e3fd56 100644
--- a/spec/frontend/boards/board_list_new_spec.js
+++ b/spec/frontend/boards/board_list_new_spec.js
@@ -77,6 +77,8 @@ const createComponent = ({
provide: {
groupId: null,
rootPath: '/',
+ weightFeatureAvailable: false,
+ boardWeight: null,
},
});
diff --git a/spec/frontend/boards/components/board_assignee_dropdown_spec.js b/spec/frontend/boards/components/board_assignee_dropdown_spec.js
new file mode 100644
index 00000000000..e185a6d5419
--- /dev/null
+++ b/spec/frontend/boards/components/board_assignee_dropdown_spec.js
@@ -0,0 +1,308 @@
+import { mount, createLocalVue } from '@vue/test-utils';
+import { GlDropdownItem, GlAvatarLink, GlAvatarLabeled, GlSearchBoxByType } from '@gitlab/ui';
+import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import VueApollo from 'vue-apollo';
+import BoardAssigneeDropdown from '~/boards/components/board_assignee_dropdown.vue';
+import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
+import MultiSelectDropdown from '~/vue_shared/components/sidebar/multiselect_dropdown.vue';
+import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
+import store from '~/boards/stores';
+import getIssueParticipants from '~/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql';
+import searchUsers from '~/boards/queries/users_search.query.graphql';
+import { participants } from '../mock_data';
+
+const localVue = createLocalVue();
+
+localVue.use(VueApollo);
+
+describe('BoardCardAssigneeDropdown', () => {
+ let wrapper;
+ let fakeApollo;
+ let getIssueParticipantsSpy;
+ let getSearchUsersSpy;
+
+ const iid = '111';
+ const activeIssueName = 'test';
+ const anotherIssueName = 'hello';
+
+ const createComponent = (search = '') => {
+ wrapper = mount(BoardAssigneeDropdown, {
+ data() {
+ return {
+ search,
+ selected: store.getters.activeIssue.assignees,
+ participants,
+ };
+ },
+ store,
+ provide: {
+ canUpdate: true,
+ rootPath: '',
+ },
+ });
+ };
+
+ const createComponentWithApollo = (search = '') => {
+ fakeApollo = createMockApollo([
+ [getIssueParticipants, getIssueParticipantsSpy],
+ [searchUsers, getSearchUsersSpy],
+ ]);
+
+ wrapper = mount(BoardAssigneeDropdown, {
+ localVue,
+ apolloProvider: fakeApollo,
+ data() {
+ return {
+ search,
+ selected: store.getters.activeIssue.assignees,
+ participants,
+ };
+ },
+ store,
+ provide: {
+ canUpdate: true,
+ rootPath: '',
+ },
+ });
+ };
+
+ const unassign = async () => {
+ wrapper.find('[data-testid="unassign"]').trigger('click');
+
+ await wrapper.vm.$nextTick();
+ };
+
+ const openDropdown = async () => {
+ wrapper.find('[data-testid="edit-button"]').trigger('click');
+
+ await wrapper.vm.$nextTick();
+ };
+
+ const findByText = text => {
+ return wrapper.findAll(GlDropdownItem).wrappers.find(node => node.text().indexOf(text) === 0);
+ };
+
+ beforeEach(() => {
+ store.state.activeId = '1';
+ store.state.issues = {
+ '1': {
+ iid,
+ assignees: [{ username: activeIssueName, name: activeIssueName, id: activeIssueName }],
+ },
+ };
+
+ jest.spyOn(store, 'dispatch').mockResolvedValue();
+ });
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when mounted', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it.each`
+ text
+ ${anotherIssueName}
+ ${activeIssueName}
+ `('finds item with $text', ({ text }) => {
+ const item = findByText(text);
+
+ expect(item.exists()).toBe(true);
+ });
+
+ it('renders gl-avatar-link in gl-dropdown-item', () => {
+ const item = findByText('hello');
+
+ expect(item.find(GlAvatarLink).exists()).toBe(true);
+ });
+
+ it('renders gl-avatar-labeled in gl-avatar-link', () => {
+ const item = findByText('hello');
+
+ expect(
+ item
+ .find(GlAvatarLink)
+ .find(GlAvatarLabeled)
+ .exists(),
+ ).toBe(true);
+ });
+ });
+
+ describe('when selected users are present', () => {
+ it('renders a divider', () => {
+ createComponent();
+
+ expect(wrapper.find('[data-testid="selected-user-divider"]').exists()).toBe(true);
+ });
+ });
+
+ describe('when collapsed', () => {
+ it('renders IssuableAssignees', () => {
+ createComponent();
+
+ expect(wrapper.find(IssuableAssignees).isVisible()).toBe(true);
+ expect(wrapper.find(MultiSelectDropdown).isVisible()).toBe(false);
+ });
+ });
+
+ describe('when dropdown is open', () => {
+ beforeEach(async () => {
+ createComponent();
+
+ await openDropdown();
+ });
+
+ it('shows assignees dropdown', async () => {
+ expect(wrapper.find(IssuableAssignees).isVisible()).toBe(false);
+ expect(wrapper.find(MultiSelectDropdown).isVisible()).toBe(true);
+ });
+
+ it('shows the issue returned as the activeIssue', async () => {
+ expect(findByText(activeIssueName).props('isChecked')).toBe(true);
+ });
+
+ describe('when "Unassign" is clicked', () => {
+ it('unassigns assignees', async () => {
+ await unassign();
+
+ expect(findByText('Unassign').props('isChecked')).toBe(true);
+ });
+ });
+
+ describe('when an unselected item is clicked', () => {
+ beforeEach(async () => {
+ await unassign();
+ });
+
+ it('assigns assignee in the dropdown', async () => {
+ wrapper.find('[data-testid="item_test"]').trigger('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findByText(activeIssueName).props('isChecked')).toBe(true);
+ });
+
+ it('calls setAssignees with username list', async () => {
+ wrapper.find('[data-testid="item_test"]').trigger('click');
+
+ await wrapper.vm.$nextTick();
+
+ document.body.click();
+
+ await wrapper.vm.$nextTick();
+
+ expect(store.dispatch).toHaveBeenCalledWith('setAssignees', [activeIssueName]);
+ });
+ });
+
+ describe('when the user off clicks', () => {
+ beforeEach(async () => {
+ await unassign();
+
+ document.body.click();
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it('calls setAssignees with username list', async () => {
+ expect(store.dispatch).toHaveBeenCalledWith('setAssignees', []);
+ });
+
+ it('closes the dropdown', async () => {
+ expect(wrapper.find(IssuableAssignees).isVisible()).toBe(true);
+ });
+ });
+ });
+
+ it('renders divider after unassign', () => {
+ createComponent();
+
+ expect(wrapper.find('[data-testid="unassign-divider"]').exists()).toBe(true);
+ });
+
+ it.each`
+ assignees | expected
+ ${[{ id: 5, username: '', name: '' }]} | ${'Assignee'}
+ ${[{ id: 6, username: '', name: '' }, { id: 7, username: '', name: '' }]} | ${'2 Assignees'}
+ `(
+ 'when assignees have a length of $assignees.length, it renders $expected',
+ ({ assignees, expected }) => {
+ store.state.issues['1'].assignees = assignees;
+
+ createComponent();
+
+ expect(wrapper.find(BoardEditableItem).props('title')).toBe(expected);
+ },
+ );
+
+ describe('Apollo', () => {
+ beforeEach(() => {
+ getIssueParticipantsSpy = jest.fn().mockResolvedValue({
+ data: {
+ issue: {
+ participants: {
+ nodes: [
+ {
+ username: 'participant',
+ name: 'participant',
+ webUrl: '',
+ avatarUrl: '',
+ id: '',
+ },
+ ],
+ },
+ },
+ },
+ });
+ getSearchUsersSpy = jest.fn().mockResolvedValue({
+ data: {
+ users: {
+ nodes: [{ username: 'root', name: 'root', webUrl: '', avatarUrl: '', id: '' }],
+ },
+ },
+ });
+ });
+
+ describe('when search is empty', () => {
+ beforeEach(() => {
+ createComponentWithApollo();
+ });
+
+ it('calls getIssueParticipants', async () => {
+ jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+
+ expect(getIssueParticipantsSpy).toHaveBeenCalledWith({ id: 'gid://gitlab/Issue/111' });
+ });
+ });
+
+ describe('when search is not empty', () => {
+ beforeEach(() => {
+ createComponentWithApollo('search term');
+ });
+
+ it('calls searchUsers', async () => {
+ jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+
+ expect(getSearchUsersSpy).toHaveBeenCalledWith({ search: 'search term' });
+ });
+ });
+ });
+
+ it('finds GlSearchBoxByType', async () => {
+ createComponent();
+
+ await openDropdown();
+
+ expect(wrapper.find(GlSearchBoxByType).exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/boards/components/board_card_spec.js b/spec/frontend/boards/components/board_card_spec.js
index a3ddcdf01b7..5e23c781eae 100644
--- a/spec/frontend/boards/components/board_card_spec.js
+++ b/spec/frontend/boards/components/board_card_spec.js
@@ -175,7 +175,7 @@ describe('BoardCard', () => {
wrapper.trigger('mousedown');
wrapper.trigger('mouseup');
- expect(eventHub.$emit).toHaveBeenCalledWith('newDetailIssue', wrapper.vm.issue, undefined);
+ expect(eventHub.$emit).toHaveBeenCalledWith('newDetailIssue', wrapper.vm.issue, false);
expect(boardsStore.detail.list).toEqual(wrapper.vm.list);
});
@@ -188,7 +188,7 @@ describe('BoardCard', () => {
wrapper.trigger('mousedown');
wrapper.trigger('mouseup');
- expect(eventHub.$emit).toHaveBeenCalledWith('clearDetailIssue', undefined);
+ expect(eventHub.$emit).toHaveBeenCalledWith('clearDetailIssue', false);
});
});
diff --git a/spec/frontend/boards/components/board_column_new_spec.js b/spec/frontend/boards/components/board_column_new_spec.js
new file mode 100644
index 00000000000..4aafc3a867a
--- /dev/null
+++ b/spec/frontend/boards/components/board_column_new_spec.js
@@ -0,0 +1,72 @@
+import { shallowMount } from '@vue/test-utils';
+
+import { listObj } from 'jest/boards/mock_data';
+import BoardColumn from '~/boards/components/board_column_new.vue';
+import List from '~/boards/models/list';
+import { ListType } from '~/boards/constants';
+import { createStore } from '~/boards/stores';
+
+describe('Board Column Component', () => {
+ let wrapper;
+ let store;
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const createComponent = ({ listType = ListType.backlog, collapsed = false } = {}) => {
+ const boardId = '1';
+
+ const listMock = {
+ ...listObj,
+ list_type: listType,
+ collapsed,
+ };
+
+ if (listType === ListType.assignee) {
+ delete listMock.label;
+ listMock.user = {};
+ }
+
+ const list = new List({ ...listMock, doNotFetchIssues: true });
+
+ store = createStore();
+
+ wrapper = shallowMount(BoardColumn, {
+ store,
+ propsData: {
+ disabled: false,
+ list,
+ },
+ provide: {
+ boardId,
+ },
+ });
+ };
+
+ const isExpandable = () => wrapper.classes('is-expandable');
+ const isCollapsed = () => wrapper.classes('is-collapsed');
+
+ describe('Given different list types', () => {
+ it('is expandable when List Type is `backlog`', () => {
+ createComponent({ listType: ListType.backlog });
+
+ expect(isExpandable()).toBe(true);
+ });
+ });
+
+ describe('expanded / collapsed column', () => {
+ it('has class is-collapsed when list is collapsed', () => {
+ createComponent({ collapsed: false });
+
+ expect(wrapper.vm.list.isExpanded).toBe(true);
+ });
+
+ it('does not have class is-collapsed when list is expanded', () => {
+ createComponent({ collapsed: true });
+
+ expect(isCollapsed()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/board_column_spec.js b/spec/frontend/boards/components/board_column_spec.js
index 2a4dbbb989e..ba11225676b 100644
--- a/spec/frontend/boards/components/board_column_spec.js
+++ b/spec/frontend/boards/components/board_column_spec.js
@@ -78,7 +78,7 @@ describe('Board Column Component', () => {
});
});
- describe('expanded / collaped column', () => {
+ describe('expanded / collapsed column', () => {
it('has class is-collapsed when list is collapsed', () => {
createComponent({ collapsed: false });
diff --git a/spec/frontend/boards/components/board_list_header_new_spec.js b/spec/frontend/boards/components/board_list_header_new_spec.js
new file mode 100644
index 00000000000..80786d82620
--- /dev/null
+++ b/spec/frontend/boards/components/board_list_header_new_spec.js
@@ -0,0 +1,169 @@
+import Vuex from 'vuex';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+
+import { listObj } from 'jest/boards/mock_data';
+import BoardListHeader from '~/boards/components/board_list_header_new.vue';
+import List from '~/boards/models/list';
+import { ListType } from '~/boards/constants';
+
+const localVue = createLocalVue();
+
+localVue.use(Vuex);
+
+describe('Board List Header Component', () => {
+ let wrapper;
+ let store;
+
+ const updateListSpy = jest.fn();
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+
+ localStorage.clear();
+ });
+
+ const createComponent = ({
+ listType = ListType.backlog,
+ collapsed = false,
+ withLocalStorage = true,
+ currentUserId = null,
+ } = {}) => {
+ const boardId = '1';
+
+ const listMock = {
+ ...listObj,
+ list_type: listType,
+ collapsed,
+ };
+
+ if (listType === ListType.assignee) {
+ delete listMock.label;
+ listMock.user = {};
+ }
+
+ const list = new List({ ...listMock, doNotFetchIssues: true });
+
+ if (withLocalStorage) {
+ localStorage.setItem(
+ `boards.${boardId}.${list.type}.${list.id}.expanded`,
+ (!collapsed).toString(),
+ );
+ }
+
+ store = new Vuex.Store({
+ state: {},
+ actions: { updateList: updateListSpy },
+ getters: {},
+ });
+
+ wrapper = shallowMount(BoardListHeader, {
+ store,
+ localVue,
+ propsData: {
+ disabled: false,
+ list,
+ },
+ provide: {
+ boardId,
+ weightFeatureAvailable: false,
+ currentUserId,
+ },
+ });
+ };
+
+ const isExpanded = () => wrapper.vm.list.isExpanded;
+ const isCollapsed = () => !isExpanded();
+
+ const findAddIssueButton = () => wrapper.find({ ref: 'newIssueBtn' });
+ const findCaret = () => wrapper.find('.board-title-caret');
+
+ describe('Add issue button', () => {
+ const hasNoAddButton = [ListType.promotion, ListType.blank, ListType.closed];
+ const hasAddButton = [ListType.backlog, ListType.label, ListType.milestone, ListType.assignee];
+
+ it.each(hasNoAddButton)('does not render when List Type is `%s`', listType => {
+ createComponent({ listType });
+
+ expect(findAddIssueButton().exists()).toBe(false);
+ });
+
+ it.each(hasAddButton)('does render when List Type is `%s`', listType => {
+ createComponent({ listType });
+
+ expect(findAddIssueButton().exists()).toBe(true);
+ });
+
+ it('has a test for each list type', () => {
+ createComponent();
+
+ Object.values(ListType).forEach(value => {
+ expect([...hasAddButton, ...hasNoAddButton]).toContain(value);
+ });
+ });
+
+ it('does render when logged out', () => {
+ createComponent();
+
+ expect(findAddIssueButton().exists()).toBe(true);
+ });
+ });
+
+ describe('expanding / collapsing the column', () => {
+ it('does not collapse when clicking the header', async () => {
+ createComponent();
+
+ expect(isCollapsed()).toBe(false);
+
+ wrapper.find('[data-testid="board-list-header"]').trigger('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(isCollapsed()).toBe(false);
+ });
+
+ it('collapses expanded Column when clicking the collapse icon', async () => {
+ createComponent();
+
+ expect(isExpanded()).toBe(true);
+
+ findCaret().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(isCollapsed()).toBe(true);
+ });
+
+ it('expands collapsed Column when clicking the expand icon', async () => {
+ createComponent({ collapsed: true });
+
+ expect(isCollapsed()).toBe(true);
+
+ findCaret().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(isCollapsed()).toBe(false);
+ });
+
+ it("when logged in it calls list update and doesn't set localStorage", async () => {
+ createComponent({ withLocalStorage: false, currentUserId: 1 });
+
+ findCaret().vm.$emit('click');
+ await wrapper.vm.$nextTick();
+
+ expect(updateListSpy).toHaveBeenCalledTimes(1);
+ expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(null);
+ });
+
+ it("when logged out it doesn't call list update and sets localStorage", async () => {
+ createComponent();
+
+ findCaret().vm.$emit('click');
+ await wrapper.vm.$nextTick();
+
+ expect(updateListSpy).not.toHaveBeenCalled();
+ expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(String(isExpanded()));
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/board_new_issue_new_spec.js b/spec/frontend/boards/components/board_new_issue_new_spec.js
new file mode 100644
index 00000000000..af4bad65121
--- /dev/null
+++ b/spec/frontend/boards/components/board_new_issue_new_spec.js
@@ -0,0 +1,115 @@
+import Vuex from 'vuex';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import BoardNewIssue from '~/boards/components/board_new_issue_new.vue';
+
+import '~/boards/models/list';
+import { mockListsWithModel } from '../mock_data';
+
+const localVue = createLocalVue();
+
+localVue.use(Vuex);
+
+describe('Issue boards new issue form', () => {
+ let wrapper;
+ let vm;
+
+ const addListNewIssuesSpy = jest.fn();
+
+ const findSubmitButton = () => wrapper.find({ ref: 'submitButton' });
+ const findCancelButton = () => wrapper.find({ ref: 'cancelButton' });
+ const findSubmitForm = () => wrapper.find({ ref: 'submitForm' });
+
+ const submitIssue = () => {
+ const dummySubmitEvent = {
+ preventDefault() {},
+ };
+
+ return findSubmitForm().trigger('submit', dummySubmitEvent);
+ };
+
+ beforeEach(() => {
+ const store = new Vuex.Store({
+ state: {},
+ actions: { addListNewIssue: addListNewIssuesSpy },
+ getters: {},
+ });
+
+ wrapper = shallowMount(BoardNewIssue, {
+ propsData: {
+ disabled: false,
+ list: mockListsWithModel[0],
+ },
+ store,
+ localVue,
+ provide: {
+ groupId: null,
+ weightFeatureAvailable: false,
+ boardWeight: null,
+ },
+ });
+
+ vm = wrapper.vm;
+
+ return vm.$nextTick();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('calls submit if submit button is clicked', async () => {
+ jest.spyOn(wrapper.vm, 'submit').mockImplementation();
+ wrapper.setData({ title: 'Testing Title' });
+
+ await vm.$nextTick();
+ await submitIssue();
+ expect(wrapper.vm.submit).toHaveBeenCalled();
+ });
+
+ it('disables submit button if title is empty', () => {
+ expect(findSubmitButton().props().disabled).toBe(true);
+ });
+
+ it('enables submit button if title is not empty', async () => {
+ wrapper.setData({ title: 'Testing Title' });
+
+ await vm.$nextTick();
+ expect(wrapper.find({ ref: 'input' }).element.value).toBe('Testing Title');
+ expect(findSubmitButton().props().disabled).toBe(false);
+ });
+
+ it('clears title after clicking cancel', async () => {
+ findCancelButton().trigger('click');
+
+ await vm.$nextTick();
+ expect(vm.title).toBe('');
+ });
+
+ describe('submit success', () => {
+ it('creates new issue', async () => {
+ wrapper.setData({ title: 'submit issue' });
+
+ await vm.$nextTick();
+ await submitIssue();
+ expect(addListNewIssuesSpy).toHaveBeenCalled();
+ });
+
+ it('enables button after submit', async () => {
+ jest.spyOn(wrapper.vm, 'submit').mockImplementation();
+ wrapper.setData({ title: 'submit issue' });
+
+ await vm.$nextTick();
+ await submitIssue();
+ expect(findSubmitButton().props().disabled).toBe(false);
+ });
+
+ it('clears title after submit', async () => {
+ wrapper.setData({ title: 'submit issue' });
+
+ await vm.$nextTick();
+ await submitIssue();
+ await vm.$nextTick();
+ expect(vm.title).toBe('');
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js
new file mode 100644
index 00000000000..b034c8cb11d
--- /dev/null
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js
@@ -0,0 +1,137 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlDatepicker } from '@gitlab/ui';
+import BoardSidebarDueDate from '~/boards/components/sidebar/board_sidebar_due_date.vue';
+import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
+import { createStore } from '~/boards/stores';
+import createFlash from '~/flash';
+
+const TEST_DUE_DATE = '2020-02-20';
+const TEST_FORMATTED_DUE_DATE = 'Feb 20, 2020';
+const TEST_PARSED_DATE = new Date(2020, 1, 20);
+const TEST_ISSUE = { id: 'gid://gitlab/Issue/1', iid: 9, dueDate: null, referencePath: 'h/b#2' };
+
+jest.mock('~/flash');
+
+describe('~/boards/components/sidebar/board_sidebar_due_date.vue', () => {
+ let wrapper;
+ let store;
+
+ afterEach(() => {
+ wrapper.destroy();
+ store = null;
+ wrapper = null;
+ });
+
+ const createWrapper = ({ dueDate = null } = {}) => {
+ store = createStore();
+ store.state.issues = { [TEST_ISSUE.id]: { ...TEST_ISSUE, dueDate } };
+ store.state.activeId = TEST_ISSUE.id;
+
+ wrapper = shallowMount(BoardSidebarDueDate, {
+ store,
+ provide: {
+ canUpdate: true,
+ },
+ stubs: {
+ 'board-editable-item': BoardEditableItem,
+ },
+ });
+ };
+
+ const findDatePicker = () => wrapper.find(GlDatepicker);
+ const findResetButton = () => wrapper.find('[data-testid="reset-button"]');
+ const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
+
+ it('renders "None" when no due date is set', () => {
+ createWrapper();
+
+ expect(findCollapsed().text()).toBe('None');
+ expect(findResetButton().exists()).toBe(false);
+ });
+
+ it('renders formatted due date with reset button when set', () => {
+ createWrapper({ dueDate: TEST_DUE_DATE });
+
+ expect(findCollapsed().text()).toContain(TEST_FORMATTED_DUE_DATE);
+ expect(findResetButton().exists()).toBe(true);
+ });
+
+ describe('when due date is submitted', () => {
+ beforeEach(async () => {
+ createWrapper();
+
+ jest.spyOn(wrapper.vm, 'setActiveIssueDueDate').mockImplementation(() => {
+ store.state.issues[TEST_ISSUE.id].dueDate = TEST_DUE_DATE;
+ });
+ findDatePicker().vm.$emit('input', TEST_PARSED_DATE);
+ await wrapper.vm.$nextTick();
+ });
+
+ it('collapses sidebar and renders formatted due date with reset button', () => {
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findCollapsed().text()).toContain(TEST_FORMATTED_DUE_DATE);
+ expect(findResetButton().exists()).toBe(true);
+ });
+
+ it('commits change to the server', () => {
+ expect(wrapper.vm.setActiveIssueDueDate).toHaveBeenCalledWith({
+ dueDate: TEST_DUE_DATE,
+ projectPath: 'h/b',
+ });
+ });
+ });
+
+ describe('when due date is cleared', () => {
+ beforeEach(async () => {
+ createWrapper();
+
+ jest.spyOn(wrapper.vm, 'setActiveIssueDueDate').mockImplementation(() => {
+ store.state.issues[TEST_ISSUE.id].dueDate = null;
+ });
+ findDatePicker().vm.$emit('clear');
+ await wrapper.vm.$nextTick();
+ });
+
+ it('collapses sidebar and renders "None"', () => {
+ expect(wrapper.vm.setActiveIssueDueDate).toHaveBeenCalled();
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findCollapsed().text()).toBe('None');
+ });
+ });
+
+ describe('when due date is resetted', () => {
+ beforeEach(async () => {
+ createWrapper({ dueDate: TEST_DUE_DATE });
+
+ jest.spyOn(wrapper.vm, 'setActiveIssueDueDate').mockImplementation(() => {
+ store.state.issues[TEST_ISSUE.id].dueDate = null;
+ });
+ findResetButton().vm.$emit('click');
+ await wrapper.vm.$nextTick();
+ });
+
+ it('collapses sidebar and renders "None"', () => {
+ expect(wrapper.vm.setActiveIssueDueDate).toHaveBeenCalled();
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findCollapsed().text()).toBe('None');
+ });
+ });
+
+ describe('when the mutation fails', () => {
+ beforeEach(async () => {
+ createWrapper({ dueDate: TEST_DUE_DATE });
+
+ jest.spyOn(wrapper.vm, 'setActiveIssueDueDate').mockImplementation(() => {
+ throw new Error(['failed mutation']);
+ });
+ findDatePicker().vm.$emit('input', 'Invalid date');
+ await wrapper.vm.$nextTick();
+ });
+
+ it('collapses sidebar and renders former issue due date', () => {
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findCollapsed().text()).toContain(TEST_FORMATTED_DUE_DATE);
+ expect(createFlash).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
new file mode 100644
index 00000000000..ee54c662167
--- /dev/null
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
@@ -0,0 +1,157 @@
+import Vuex from 'vuex';
+import { mount, createLocalVue } from '@vue/test-utils';
+import { GlToggle, GlLoadingIcon } from '@gitlab/ui';
+import BoardSidebarSubscription from '~/boards/components/sidebar/board_sidebar_subscription.vue';
+import * as types from '~/boards/stores/mutation_types';
+import { createStore } from '~/boards/stores';
+import { mockActiveIssue } from '../../mock_data';
+import createFlash from '~/flash';
+
+jest.mock('~/flash.js');
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () => {
+ let wrapper;
+ let store;
+
+ const findNotificationHeader = () => wrapper.find("[data-testid='notification-header-text']");
+ const findToggle = () => wrapper.find(GlToggle);
+ const findGlLoadingIcon = () => wrapper.find(GlLoadingIcon);
+
+ const createComponent = (activeIssue = { ...mockActiveIssue }) => {
+ store = createStore();
+ store.state.issues = { [activeIssue.id]: activeIssue };
+ store.state.activeId = activeIssue.id;
+
+ wrapper = mount(BoardSidebarSubscription, {
+ localVue,
+ store,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ store = null;
+ jest.clearAllMocks();
+ });
+
+ describe('Board sidebar subscription component template', () => {
+ it('displays "notifications" heading', () => {
+ createComponent();
+
+ expect(findNotificationHeader().text()).toBe('Notifications');
+ });
+
+ it('renders toggle as "off" when currently not subscribed', () => {
+ createComponent();
+
+ expect(findToggle().exists()).toBe(true);
+ expect(findToggle().props('value')).toBe(false);
+ });
+
+ it('renders toggle as "on" when currently subscribed', () => {
+ createComponent({
+ ...mockActiveIssue,
+ subscribed: true,
+ });
+
+ expect(findToggle().exists()).toBe(true);
+ expect(findToggle().props('value')).toBe(true);
+ });
+
+ describe('when notification emails have been disabled', () => {
+ beforeEach(() => {
+ createComponent({
+ ...mockActiveIssue,
+ emailsDisabled: true,
+ });
+ });
+
+ it('displays a message that notification have been disabled', () => {
+ expect(findNotificationHeader().text()).toBe(
+ 'Notifications have been disabled by the project or group owner',
+ );
+ });
+
+ it('does not render the toggle button', () => {
+ expect(findToggle().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('Board sidebar subscription component `behavior`', () => {
+ const mockSetActiveIssueSubscribed = subscribedState => {
+ jest.spyOn(wrapper.vm, 'setActiveIssueSubscribed').mockImplementation(async () => {
+ store.commit(types.UPDATE_ISSUE_BY_ID, {
+ issueId: mockActiveIssue.id,
+ prop: 'subscribed',
+ value: subscribedState,
+ });
+ });
+ };
+
+ it('subscribing to notification', async () => {
+ createComponent();
+ mockSetActiveIssueSubscribed(true);
+
+ expect(findGlLoadingIcon().exists()).toBe(false);
+
+ findToggle().trigger('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findGlLoadingIcon().exists()).toBe(true);
+ expect(wrapper.vm.setActiveIssueSubscribed).toHaveBeenCalledWith({
+ subscribed: true,
+ projectPath: 'gitlab-org/test-subgroup/gitlab-test',
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(findGlLoadingIcon().exists()).toBe(false);
+ expect(findToggle().props('value')).toBe(true);
+ });
+
+ it('unsubscribing from notification', async () => {
+ createComponent({
+ ...mockActiveIssue,
+ subscribed: true,
+ });
+ mockSetActiveIssueSubscribed(false);
+
+ expect(findGlLoadingIcon().exists()).toBe(false);
+
+ findToggle().trigger('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.setActiveIssueSubscribed).toHaveBeenCalledWith({
+ subscribed: false,
+ projectPath: 'gitlab-org/test-subgroup/gitlab-test',
+ });
+ expect(findGlLoadingIcon().exists()).toBe(true);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findGlLoadingIcon().exists()).toBe(false);
+ expect(findToggle().props('value')).toBe(false);
+ });
+
+ it('flashes an error message when setting the subscribed state fails', async () => {
+ createComponent();
+ jest.spyOn(wrapper.vm, 'setActiveIssueSubscribed').mockImplementation(async () => {
+ throw new Error();
+ });
+
+ findToggle().trigger('click');
+
+ await wrapper.vm.$nextTick();
+ expect(createFlash).toHaveBeenNthCalledWith(1, {
+ message: wrapper.vm.$options.i18n.updateSubscribedErrorMessage,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index 50c0a85fc70..58f67231d55 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -2,6 +2,7 @@
/* global List */
import Vue from 'vue';
+import { keyBy } from 'lodash';
import '~/boards/models/list';
import '~/boards/models/issue';
import boardsStore from '~/boards/stores/boards_store';
@@ -175,6 +176,14 @@ export const mockIssue = {
},
};
+export const mockActiveIssue = {
+ ...mockIssue,
+ id: 436,
+ iid: '27',
+ subscribed: false,
+ emailsDisabled: false,
+};
+
export const mockIssueWithModel = new ListIssue(mockIssue);
export const mockIssue2 = {
@@ -290,6 +299,7 @@ export const mockLists = [
assignee: null,
milestone: null,
loading: false,
+ issuesSize: 1,
},
{
id: 'gid://gitlab/List/2',
@@ -307,9 +317,12 @@ export const mockLists = [
assignee: null,
milestone: null,
loading: false,
+ issuesSize: 0,
},
];
+export const mockListsById = keyBy(mockLists, 'id');
+
export const mockListsWithModel = mockLists.map(listMock =>
Vue.observable(new List({ ...listMock, doNotFetchIssues: true })),
);
@@ -319,6 +332,23 @@ export const mockIssuesByListId = {
'gid://gitlab/List/2': mockIssues.map(({ id }) => id),
};
+export const participants = [
+ {
+ id: '1',
+ username: 'test',
+ name: 'test',
+ avatar: '',
+ avatarUrl: '',
+ },
+ {
+ id: '2',
+ username: 'hello',
+ name: 'hello',
+ avatar: '',
+ avatarUrl: '',
+ },
+];
+
export const issues = {
[mockIssue.id]: mockIssue,
[mockIssue2.id]: mockIssue2,
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index 78e70161121..4d529580a7a 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -2,17 +2,21 @@ import testAction from 'helpers/vuex_action_helper';
import {
mockListsWithModel,
mockLists,
+ mockListsById,
mockIssue,
mockIssueWithModel,
mockIssue2WithModel,
rawIssue,
mockIssues,
labels,
+ mockActiveIssue,
} from '../mock_data';
import actions, { gqlClient } from '~/boards/stores/actions';
import * as types from '~/boards/stores/mutation_types';
-import { inactiveId, ListType } from '~/boards/constants';
+import { inactiveId } from '~/boards/constants';
import issueMoveListMutation from '~/boards/queries/issue_move_list.mutation.graphql';
+import destroyBoardListMutation from '~/boards/queries/board_list_destroy.mutation.graphql';
+import updateAssignees from '~/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql';
import { fullBoardId, formatListIssues, formatBoardLists } from '~/boards/boards_util';
const expectNotImplemented = action => {
@@ -116,7 +120,7 @@ describe('fetchLists', () => {
payload: formattedLists,
},
],
- [{ type: 'showWelcomeList' }],
+ [{ type: 'generateDefaultLists' }],
done,
);
});
@@ -146,14 +150,15 @@ describe('fetchLists', () => {
payload: formattedLists,
},
],
- [{ type: 'createList', payload: { backlog: true } }, { type: 'showWelcomeList' }],
+ [{ type: 'createList', payload: { backlog: true } }, { type: 'generateDefaultLists' }],
done,
);
});
});
-describe('showWelcomeList', () => {
- it('should dispatch addList action', done => {
+describe('generateDefaultLists', () => {
+ let store;
+ beforeEach(() => {
const state = {
endpoints: { fullPath: 'gitlab-org', boardId: '1' },
boardType: 'group',
@@ -161,26 +166,19 @@ describe('showWelcomeList', () => {
boardLists: [{ type: 'backlog' }, { type: 'closed' }],
};
- const blankList = {
- id: 'blank',
- listType: ListType.blank,
- title: 'Welcome to your issue board!',
- position: 0,
- };
-
- testAction(
- actions.showWelcomeList,
- {},
+ store = {
+ commit: jest.fn(),
+ dispatch: jest.fn(() => Promise.resolve()),
state,
- [],
- [{ type: 'addList', payload: blankList }],
- done,
- );
+ };
});
-});
-describe('generateDefaultLists', () => {
- expectNotImplemented(actions.generateDefaultLists);
+ it('should dispatch fetchLabels', () => {
+ return actions.generateDefaultLists(store).then(() => {
+ expect(store.dispatch.mock.calls[0]).toEqual(['fetchLabels', 'to do']);
+ expect(store.dispatch.mock.calls[1]).toEqual(['fetchLabels', 'doing']);
+ });
+ });
});
describe('createList', () => {
@@ -323,8 +321,82 @@ describe('updateList', () => {
});
});
-describe('deleteList', () => {
- expectNotImplemented(actions.deleteList);
+describe('removeList', () => {
+ let state;
+ const list = mockLists[0];
+ const listId = list.id;
+ const mutationVariables = {
+ mutation: destroyBoardListMutation,
+ variables: {
+ listId,
+ },
+ };
+
+ beforeEach(() => {
+ state = {
+ boardLists: mockListsById,
+ };
+ });
+
+ afterEach(() => {
+ state = null;
+ });
+
+ it('optimistically deletes the list', () => {
+ const commit = jest.fn();
+
+ actions.removeList({ commit, state }, listId);
+
+ expect(commit.mock.calls).toEqual([[types.REMOVE_LIST, listId]]);
+ });
+
+ it('keeps the updated list if remove succeeds', async () => {
+ const commit = jest.fn();
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ destroyBoardList: {
+ errors: [],
+ },
+ },
+ });
+
+ await actions.removeList({ commit, state }, listId);
+
+ expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
+ expect(commit.mock.calls).toEqual([[types.REMOVE_LIST, listId]]);
+ });
+
+ it('restores the list if update fails', async () => {
+ const commit = jest.fn();
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue(Promise.reject());
+
+ await actions.removeList({ commit, state }, listId);
+
+ expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
+ expect(commit.mock.calls).toEqual([
+ [types.REMOVE_LIST, listId],
+ [types.REMOVE_LIST_FAILURE, mockListsById],
+ ]);
+ });
+
+ it('restores the list if update response has errors', async () => {
+ const commit = jest.fn();
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ destroyBoardList: {
+ errors: ['update failed, ID invalid'],
+ },
+ },
+ });
+
+ await actions.removeList({ commit, state }, listId);
+
+ expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
+ expect(commit.mock.calls).toEqual([
+ [types.REMOVE_LIST, listId],
+ [types.REMOVE_LIST_FAILURE, mockListsById],
+ ]);
+ });
});
describe('fetchIssuesForList', () => {
@@ -560,41 +632,106 @@ describe('moveIssue', () => {
});
});
-describe('createNewIssue', () => {
- expectNotImplemented(actions.createNewIssue);
+describe('setAssignees', () => {
+ const node = { username: 'name' };
+ const name = 'username';
+ const projectPath = 'h/h';
+ const refPath = `${projectPath}#3`;
+ const iid = '1';
+
+ beforeEach(() => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: { issueSetAssignees: { issue: { assignees: { nodes: [{ ...node }] } } } },
+ });
+ });
+
+ it('calls mutate with the correct values', async () => {
+ await actions.setAssignees(
+ { commit: () => {}, getters: { activeIssue: { iid, referencePath: refPath } } },
+ [name],
+ );
+
+ expect(gqlClient.mutate).toHaveBeenCalledWith({
+ mutation: updateAssignees,
+ variables: { iid, assigneeUsernames: [name], projectPath },
+ });
+ });
+
+ it('calls the correct mutation with the correct values', done => {
+ testAction(
+ actions.setAssignees,
+ {},
+ { activeIssue: { iid, referencePath: refPath }, commit: () => {} },
+ [
+ {
+ type: 'UPDATE_ISSUE_BY_ID',
+ payload: { prop: 'assignees', issueId: undefined, value: [node] },
+ },
+ ],
+ [],
+ done,
+ );
+ });
});
-describe('addListIssue', () => {
- it('should commit UPDATE_LIST_FAILURE mutation when API returns an error', done => {
- const payload = {
- list: mockLists[0],
- issue: mockIssue,
- position: 0,
- };
+describe('createNewIssue', () => {
+ const state = {
+ boardType: 'group',
+ endpoints: {
+ fullPath: 'gitlab-org/gitlab',
+ },
+ };
+
+ it('should return issue from API on success', async () => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ createIssue: {
+ issue: mockIssue,
+ errors: [],
+ },
+ },
+ });
+
+ const result = await actions.createNewIssue({ state }, mockIssue);
+ expect(result).toEqual(mockIssue);
+ });
+
+ it('should commit CREATE_ISSUE_FAILURE mutation when API returns an error', done => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ createIssue: {
+ issue: {},
+ errors: [{ foo: 'bar' }],
+ },
+ },
+ });
+
+ const payload = mockIssue;
testAction(
- actions.addListIssue,
+ actions.createNewIssue,
payload,
- {},
- [{ type: types.ADD_ISSUE_TO_LIST, payload }],
+ state,
+ [{ type: types.CREATE_ISSUE_FAILURE }],
[],
done,
);
});
});
-describe('addListIssueFailure', () => {
- it('should commit UPDATE_LIST_FAILURE mutation when API returns an error', done => {
+describe('addListIssue', () => {
+ it('should commit ADD_ISSUE_TO_LIST mutation', done => {
const payload = {
list: mockLists[0],
issue: mockIssue,
+ position: 0,
};
testAction(
- actions.addListIssueFailure,
+ actions.addListIssue,
payload,
{},
- [{ type: types.ADD_ISSUE_TO_LIST_FAILURE, payload }],
+ [{ type: types.ADD_ISSUE_TO_LIST, payload }],
[],
done,
);
@@ -603,7 +740,7 @@ describe('addListIssueFailure', () => {
describe('setActiveIssueLabels', () => {
const state = { issues: { [mockIssue.id]: mockIssue } };
- const getters = { getActiveIssue: mockIssue };
+ const getters = { activeIssue: mockIssue };
const testLabelIds = labels.map(label => label.id);
const input = {
addLabelIds: testLabelIds,
@@ -617,7 +754,7 @@ describe('setActiveIssueLabels', () => {
.mockResolvedValue({ data: { updateIssue: { issue: { labels: { nodes: labels } } } } });
const payload = {
- issueId: getters.getActiveIssue.id,
+ issueId: getters.activeIssue.id,
prop: 'labels',
value: labels,
};
@@ -646,6 +783,108 @@ describe('setActiveIssueLabels', () => {
});
});
+describe('setActiveIssueDueDate', () => {
+ const state = { issues: { [mockIssue.id]: mockIssue } };
+ const getters = { activeIssue: mockIssue };
+ const testDueDate = '2020-02-20';
+ const input = {
+ dueDate: testDueDate,
+ projectPath: 'h/b',
+ };
+
+ it('should commit due date after setting the issue', done => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ updateIssue: {
+ issue: {
+ dueDate: testDueDate,
+ },
+ errors: [],
+ },
+ },
+ });
+
+ const payload = {
+ issueId: getters.activeIssue.id,
+ prop: 'dueDate',
+ value: testDueDate,
+ };
+
+ testAction(
+ actions.setActiveIssueDueDate,
+ input,
+ { ...state, ...getters },
+ [
+ {
+ type: types.UPDATE_ISSUE_BY_ID,
+ payload,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+
+ it('throws error if fails', async () => {
+ jest
+ .spyOn(gqlClient, 'mutate')
+ .mockResolvedValue({ data: { updateIssue: { errors: ['failed mutation'] } } });
+
+ await expect(actions.setActiveIssueDueDate({ getters }, input)).rejects.toThrow(Error);
+ });
+});
+
+describe('setActiveIssueSubscribed', () => {
+ const state = { issues: { [mockActiveIssue.id]: mockActiveIssue } };
+ const getters = { activeIssue: mockActiveIssue };
+ const subscribedState = true;
+ const input = {
+ subscribedState,
+ projectPath: 'gitlab-org/gitlab-test',
+ };
+
+ it('should commit subscribed status', done => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ issueSetSubscription: {
+ issue: {
+ subscribed: subscribedState,
+ },
+ errors: [],
+ },
+ },
+ });
+
+ const payload = {
+ issueId: getters.activeIssue.id,
+ prop: 'subscribed',
+ value: subscribedState,
+ };
+
+ testAction(
+ actions.setActiveIssueSubscribed,
+ input,
+ { ...state, ...getters },
+ [
+ {
+ type: types.UPDATE_ISSUE_BY_ID,
+ payload,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+
+ it('throws error if fails', async () => {
+ jest
+ .spyOn(gqlClient, 'mutate')
+ .mockResolvedValue({ data: { issueSetSubscription: { errors: ['failed mutation'] } } });
+
+ await expect(actions.setActiveIssueSubscribed({ getters }, input)).rejects.toThrow(Error);
+ });
+});
+
describe('fetchBacklog', () => {
expectNotImplemented(actions.fetchBacklog);
});
diff --git a/spec/frontend/boards/stores/getters_spec.js b/spec/frontend/boards/stores/getters_spec.js
index b987080abab..64025726dd1 100644
--- a/spec/frontend/boards/stores/getters_spec.js
+++ b/spec/frontend/boards/stores/getters_spec.js
@@ -10,13 +10,13 @@ import {
} from '../mock_data';
describe('Boards - Getters', () => {
- describe('getLabelToggleState', () => {
+ describe('labelToggleState', () => {
it('should return "on" when isShowingLabels is true', () => {
const state = {
isShowingLabels: true,
};
- expect(getters.getLabelToggleState(state)).toBe('on');
+ expect(getters.labelToggleState(state)).toBe('on');
});
it('should return "off" when isShowingLabels is false', () => {
@@ -24,7 +24,7 @@ describe('Boards - Getters', () => {
isShowingLabels: false,
};
- expect(getters.getLabelToggleState(state)).toBe('off');
+ expect(getters.labelToggleState(state)).toBe('off');
});
});
@@ -112,7 +112,7 @@ describe('Boards - Getters', () => {
});
});
- describe('getActiveIssue', () => {
+ describe('activeIssue', () => {
it.each`
id | expected
${'1'} | ${'issue'}
@@ -120,11 +120,27 @@ describe('Boards - Getters', () => {
`('returns $expected when $id is passed to state', ({ id, expected }) => {
const state = { issues: { '1': 'issue' }, activeId: id };
- expect(getters.getActiveIssue(state)).toEqual(expected);
+ expect(getters.activeIssue(state)).toEqual(expected);
});
});
- describe('getIssues', () => {
+ describe('projectPathByIssueId', () => {
+ it('returns project path for the active issue', () => {
+ const mockActiveIssue = {
+ referencePath: 'gitlab-org/gitlab-test#1',
+ };
+ expect(getters.projectPathForActiveIssue({}, { activeIssue: mockActiveIssue })).toEqual(
+ 'gitlab-org/gitlab-test',
+ );
+ });
+
+ it('returns empty string as project when active issue is an empty object', () => {
+ const mockActiveIssue = {};
+ expect(getters.projectPathForActiveIssue({}, { activeIssue: mockActiveIssue })).toEqual('');
+ });
+ });
+
+ describe('getIssuesByList', () => {
const boardsState = {
issuesByListId: mockIssuesByListId,
issues,
@@ -132,7 +148,7 @@ describe('Boards - Getters', () => {
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(
+ expect(getters.getIssuesByList(boardsState, { getIssueById })('gid://gitlab/List/2')).toEqual(
mockIssues,
);
});
diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js
index 6e53f184bb3..e1e57a8fd43 100644
--- a/spec/frontend/boards/stores/mutations_spec.js
+++ b/spec/frontend/boards/stores/mutations_spec.js
@@ -82,7 +82,7 @@ describe('Board Store Mutations', () => {
mutations.SET_ACTIVE_ID(state, expected);
});
- it('updates aciveListId to be the value that is passed', () => {
+ it('updates activeListId to be the value that is passed', () => {
expect(state.activeId).toBe(expected.id);
});
@@ -101,6 +101,34 @@ describe('Board Store Mutations', () => {
});
});
+ describe('CREATE_LIST_FAILURE', () => {
+ it('sets error message', () => {
+ mutations.CREATE_LIST_FAILURE(state);
+
+ expect(state.error).toEqual('An error occurred while creating the list. Please try again.');
+ });
+ });
+
+ describe('RECEIVE_LABELS_FAILURE', () => {
+ it('sets error message', () => {
+ mutations.RECEIVE_LABELS_FAILURE(state);
+
+ expect(state.error).toEqual(
+ 'An error occurred while fetching labels. Please reload the page.',
+ );
+ });
+ });
+
+ describe('GENERATE_DEFAULT_LISTS_FAILURE', () => {
+ it('sets error message', () => {
+ mutations.GENERATE_DEFAULT_LISTS_FAILURE(state);
+
+ expect(state.error).toEqual(
+ 'An error occurred while generating lists. Please reload the page.',
+ );
+ });
+ });
+
describe('REQUEST_ADD_LIST', () => {
expectNotImplemented(mutations.REQUEST_ADD_LIST);
});
@@ -156,16 +184,43 @@ describe('Board Store Mutations', () => {
});
});
- describe('REQUEST_REMOVE_LIST', () => {
- expectNotImplemented(mutations.REQUEST_REMOVE_LIST);
- });
+ describe('REMOVE_LIST', () => {
+ it('removes list from boardLists', () => {
+ const [list, secondList] = mockListsWithModel;
+ const expected = {
+ [secondList.id]: secondList,
+ };
+ state = {
+ ...state,
+ boardLists: { ...initialBoardListsState },
+ };
- describe('RECEIVE_REMOVE_LIST_SUCCESS', () => {
- expectNotImplemented(mutations.RECEIVE_REMOVE_LIST_SUCCESS);
+ mutations[types.REMOVE_LIST](state, list.id);
+
+ expect(state.boardLists).toEqual(expected);
+ });
});
- describe('RECEIVE_REMOVE_LIST_ERROR', () => {
- expectNotImplemented(mutations.RECEIVE_REMOVE_LIST_ERROR);
+ describe('REMOVE_LIST_FAILURE', () => {
+ it('restores lists from backup', () => {
+ const backupLists = { ...initialBoardListsState };
+
+ mutations[types.REMOVE_LIST_FAILURE](state, backupLists);
+
+ expect(state.boardLists).toEqual(backupLists);
+ });
+
+ it('sets error state', () => {
+ const backupLists = { ...initialBoardListsState };
+ state = {
+ ...state,
+ error: undefined,
+ };
+
+ mutations[types.REMOVE_LIST_FAILURE](state, backupLists);
+
+ expect(state.error).toEqual('An error occurred while removing the list. Please try again.');
+ });
});
describe('RESET_ISSUES', () => {
@@ -387,6 +442,14 @@ describe('Board Store Mutations', () => {
expectNotImplemented(mutations.RECEIVE_UPDATE_ISSUE_ERROR);
});
+ describe('CREATE_ISSUE_FAILURE', () => {
+ it('sets error message on state', () => {
+ mutations.CREATE_ISSUE_FAILURE(state);
+
+ expect(state.error).toBe('An error occurred while creating the issue. Please try again.');
+ });
+ });
+
describe('ADD_ISSUE_TO_LIST', () => {
it('adds issue to issues state and issue id in list in issuesByListId', () => {
const listIssues = {
@@ -400,17 +463,45 @@ describe('Board Store Mutations', () => {
...state,
issuesByListId: listIssues,
issues,
+ boardLists: initialBoardListsState,
};
- mutations.ADD_ISSUE_TO_LIST(state, { list: mockLists[0], issue: mockIssue2 });
+ expect(state.boardLists['gid://gitlab/List/1'].issuesSize).toBe(1);
+
+ mutations.ADD_ISSUE_TO_LIST(state, { list: mockListsWithModel[0], issue: mockIssue2 });
expect(state.issuesByListId['gid://gitlab/List/1']).toContain(mockIssue2.id);
expect(state.issues[mockIssue2.id]).toEqual(mockIssue2);
+ expect(state.boardLists['gid://gitlab/List/1'].issuesSize).toBe(2);
});
});
describe('ADD_ISSUE_TO_LIST_FAILURE', () => {
- it('removes issue id from list in issuesByListId', () => {
+ it('removes issue id from list in issuesByListId and sets error message', () => {
+ const listIssues = {
+ 'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id],
+ };
+ const issues = {
+ '1': mockIssue,
+ '2': mockIssue2,
+ };
+
+ state = {
+ ...state,
+ issuesByListId: listIssues,
+ issues,
+ boardLists: initialBoardListsState,
+ };
+
+ mutations.ADD_ISSUE_TO_LIST_FAILURE(state, { list: mockLists[0], issueId: mockIssue2.id });
+
+ expect(state.issuesByListId['gid://gitlab/List/1']).not.toContain(mockIssue2.id);
+ expect(state.error).toBe('An error occurred while creating the issue. Please try again.');
+ });
+ });
+
+ describe('REMOVE_ISSUE_FROM_LIST', () => {
+ it('removes issue id from list in issuesByListId and deletes issue from state', () => {
const listIssues = {
'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id],
};
@@ -426,9 +517,10 @@ describe('Board Store Mutations', () => {
boardLists: initialBoardListsState,
};
- mutations.ADD_ISSUE_TO_LIST_FAILURE(state, { list: mockLists[0], issue: mockIssue2 });
+ mutations.ADD_ISSUE_TO_LIST_FAILURE(state, { list: mockLists[0], issueId: mockIssue2.id });
expect(state.issuesByListId['gid://gitlab/List/1']).not.toContain(mockIssue2.id);
+ expect(state.issues).not.toContain(mockIssue2);
});
});
diff --git a/spec/frontend/ci_lint/components/ci_lint_results_spec.js b/spec/frontend/ci_lint/components/ci_lint_results_spec.js
index 37575a988c5..93c2d2dbcf3 100644
--- a/spec/frontend/ci_lint/components/ci_lint_results_spec.js
+++ b/spec/frontend/ci_lint/components/ci_lint_results_spec.js
@@ -1,20 +1,24 @@
import { shallowMount, mount } from '@vue/test-utils';
-import { GlTable } from '@gitlab/ui';
+import { GlTable, GlLink } from '@gitlab/ui';
import CiLintResults from '~/ci_lint/components/ci_lint_results.vue';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { mockJobs, mockErrors, mockWarnings } from '../mock_data';
describe('CI Lint Results', () => {
let wrapper;
+ const defaultProps = {
+ valid: true,
+ jobs: mockJobs,
+ errors: [],
+ warnings: [],
+ dryRun: false,
+ lintHelpPagePath: '/help',
+ };
const createComponent = (props = {}, mountFn = shallowMount) => {
wrapper = mountFn(CiLintResults, {
propsData: {
- valid: true,
- jobs: mockJobs,
- errors: [],
- warnings: [],
- dryRun: false,
+ ...defaultProps,
...props,
},
});
@@ -23,6 +27,7 @@ describe('CI Lint Results', () => {
const findTable = () => wrapper.find(GlTable);
const findByTestId = selector => () => wrapper.find(`[data-testid="ci-lint-${selector}"]`);
const findAllByTestId = selector => () => wrapper.findAll(`[data-testid="ci-lint-${selector}"]`);
+ const findLinkToDoc = () => wrapper.find(GlLink);
const findErrors = findByTestId('errors');
const findWarnings = findByTestId('warnings');
const findStatus = findByTestId('status');
@@ -48,10 +53,15 @@ describe('CI Lint Results', () => {
});
it('displays the invalid status', () => {
- expect(findStatus().text()).toBe(`Status: ${wrapper.vm.$options.incorrect.text}`);
+ expect(findStatus().text()).toContain(`Status: ${wrapper.vm.$options.incorrect.text}`);
expect(findStatus().props('variant')).toBe(wrapper.vm.$options.incorrect.variant);
});
+ it('contains the link to documentation', () => {
+ expect(findLinkToDoc().text()).toBe('More information');
+ expect(findLinkToDoc().attributes('href')).toBe(defaultProps.lintHelpPagePath);
+ });
+
it('displays the error message', () => {
const [expectedError] = mockErrors;
@@ -66,9 +76,9 @@ describe('CI Lint Results', () => {
});
});
- describe('Valid results', () => {
+ describe('Valid results with dry run', () => {
beforeEach(() => {
- createComponent();
+ createComponent({ dryRun: true }, mount);
});
it('displays table', () => {
@@ -76,13 +86,18 @@ describe('CI Lint Results', () => {
});
it('displays the valid status', () => {
- expect(findStatus().text()).toBe(wrapper.vm.$options.correct.text);
+ expect(findStatus().text()).toContain(wrapper.vm.$options.correct.text);
expect(findStatus().props('variant')).toBe(wrapper.vm.$options.correct.variant);
});
it('does not display only/expect values with dry run', () => {
expect(findOnlyExcept().exists()).toBe(false);
});
+
+ it('contains the link to documentation', () => {
+ expect(findLinkToDoc().text()).toBe('More information');
+ expect(findLinkToDoc().attributes('href')).toBe(defaultProps.lintHelpPagePath);
+ });
});
describe('Lint results', () => {
diff --git a/spec/frontend/ci_lint/components/ci_lint_spec.js b/spec/frontend/ci_lint/components/ci_lint_spec.js
index e617cca499d..b353da5910d 100644
--- a/spec/frontend/ci_lint/components/ci_lint_spec.js
+++ b/spec/frontend/ci_lint/components/ci_lint_spec.js
@@ -1,7 +1,11 @@
+import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import waitForPromises from 'helpers/wait_for_promises';
import EditorLite from '~/vue_shared/components/editor_lite.vue';
import CiLint from '~/ci_lint/components/ci_lint.vue';
+import CiLintResults from '~/ci_lint/components/ci_lint_results.vue';
import lintCIMutation from '~/ci_lint/graphql/mutations/lint_ci.mutation.graphql';
+import { mockLintDataValid } from '../mock_data';
describe('CI Lint', () => {
let wrapper;
@@ -9,6 +13,7 @@ describe('CI Lint', () => {
const endpoint = '/namespace/project/-/ci/lint';
const content =
"test_job:\n stage: build\n script: echo 'Building'\n only:\n - web\n - chat\n - pushes\n allow_failure: true ";
+ const mockMutate = jest.fn().mockResolvedValue(mockLintDataValid);
const createComponent = () => {
wrapper = shallowMount(CiLint, {
@@ -19,17 +24,20 @@ describe('CI Lint', () => {
},
propsData: {
endpoint,
- helpPagePath: '/help/ci/lint#pipeline-simulation',
+ pipelineSimulationHelpPagePath: '/help/ci/lint#pipeline-simulation',
+ lintHelpPagePath: '/help/ci/lint#anchor',
},
mocks: {
$apollo: {
- mutate: jest.fn(),
+ mutate: mockMutate,
},
},
});
};
const findEditor = () => wrapper.find(EditorLite);
+ const findAlert = () => wrapper.find(GlAlert);
+ const findCiLintResults = () => wrapper.find(CiLintResults);
const findValidateBtn = () => wrapper.find('[data-testid="ci-lint-validate"]');
const findClearBtn = () => wrapper.find('[data-testid="ci-lint-clear"]');
@@ -38,6 +46,7 @@ describe('CI Lint', () => {
});
afterEach(() => {
+ mockMutate.mockClear();
wrapper.destroy();
});
@@ -67,6 +76,35 @@ describe('CI Lint', () => {
});
});
+ it('validation displays results', async () => {
+ findValidateBtn().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findValidateBtn().props('loading')).toBe(true);
+
+ await waitForPromises();
+
+ expect(findCiLintResults().exists()).toBe(true);
+ expect(findValidateBtn().props('loading')).toBe(false);
+ });
+
+ it('validation displays error', async () => {
+ mockMutate.mockRejectedValue('Error!');
+
+ findValidateBtn().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findValidateBtn().props('loading')).toBe(true);
+
+ await waitForPromises();
+
+ expect(findCiLintResults().exists()).toBe(false);
+ expect(findAlert().text()).toBe('Error!');
+ expect(findValidateBtn().props('loading')).toBe(false);
+ });
+
it('content is cleared on clear action', async () => {
expect(findEditor().props('value')).toBe(content);
diff --git a/spec/frontend/ci_lint/graphql/__snapshots__/resolvers_spec.js.snap b/spec/frontend/ci_lint/graphql/__snapshots__/resolvers_spec.js.snap
new file mode 100644
index 00000000000..87bec82e350
--- /dev/null
+++ b/spec/frontend/ci_lint/graphql/__snapshots__/resolvers_spec.js.snap
@@ -0,0 +1,73 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`~/ci_lint/graphql/resolvers Mutation lintCI resolves lint data with type names 1`] = `
+Object {
+ "__typename": "CiLintContent",
+ "errors": Array [],
+ "jobs": Array [
+ Object {
+ "__typename": "CiLintJob",
+ "afterScript": Array [
+ "echo 'after script 1",
+ ],
+ "allowFailure": false,
+ "beforeScript": Array [
+ "echo 'before script 1'",
+ ],
+ "environment": "prd",
+ "except": Object {
+ "refs": Array [
+ "master@gitlab-org/gitlab",
+ "/^release/.*$/@gitlab-org/gitlab",
+ ],
+ },
+ "name": "job_1",
+ "only": null,
+ "script": Array [
+ "echo 'script 1'",
+ ],
+ "stage": "test",
+ "tagList": Array [
+ "tag 1",
+ ],
+ "when": "on_success",
+ },
+ Object {
+ "__typename": "CiLintJob",
+ "afterScript": Array [
+ "echo 'after script 2",
+ ],
+ "allowFailure": true,
+ "beforeScript": Array [
+ "echo 'before script 2'",
+ ],
+ "environment": "stg",
+ "except": Object {
+ "refs": Array [
+ "master@gitlab-org/gitlab",
+ "/^release/.*$/@gitlab-org/gitlab",
+ ],
+ },
+ "name": "job_2",
+ "only": Object {
+ "__typename": "CiLintJobOnlyPolicy",
+ "refs": Array [
+ "web",
+ "chat",
+ "pushes",
+ ],
+ },
+ "script": Array [
+ "echo 'script 2'",
+ ],
+ "stage": "test",
+ "tagList": Array [
+ "tag 2",
+ ],
+ "when": "on_success",
+ },
+ ],
+ "valid": true,
+ "warnings": Array [],
+}
+`;
diff --git a/spec/frontend/ci_lint/graphql/resolvers_spec.js b/spec/frontend/ci_lint/graphql/resolvers_spec.js
new file mode 100644
index 00000000000..437c52cf6b4
--- /dev/null
+++ b/spec/frontend/ci_lint/graphql/resolvers_spec.js
@@ -0,0 +1,38 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import httpStatus from '~/lib/utils/http_status';
+
+import resolvers from '~/ci_lint/graphql/resolvers';
+import { mockLintResponse } from '../mock_data';
+
+describe('~/ci_lint/graphql/resolvers', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('Mutation', () => {
+ describe('lintCI', () => {
+ const endpoint = '/ci/lint';
+
+ beforeEach(() => {
+ mock.onPost(endpoint).reply(httpStatus.OK, mockLintResponse);
+ });
+
+ it('resolves lint data with type names', async () => {
+ const result = resolvers.Mutation.lintCI(null, {
+ endpoint,
+ content: 'content',
+ dry_run: true,
+ });
+
+ await expect(result).resolves.toMatchSnapshot();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/ci_lint/mock_data.js b/spec/frontend/ci_lint/mock_data.js
index cf7d69dcad3..b87c9f8413b 100644
--- a/spec/frontend/ci_lint/mock_data.js
+++ b/spec/frontend/ci_lint/mock_data.js
@@ -1,3 +1,37 @@
+export const mockLintResponse = {
+ valid: true,
+ errors: [],
+ warnings: [],
+ jobs: [
+ {
+ name: 'job_1',
+ stage: 'test',
+ before_script: ["echo 'before script 1'"],
+ script: ["echo 'script 1'"],
+ after_script: ["echo 'after script 1"],
+ tag_list: ['tag 1'],
+ environment: 'prd',
+ when: 'on_success',
+ allow_failure: false,
+ only: null,
+ except: { refs: ['master@gitlab-org/gitlab', '/^release/.*$/@gitlab-org/gitlab'] },
+ },
+ {
+ name: 'job_2',
+ stage: 'test',
+ before_script: ["echo 'before script 2'"],
+ script: ["echo 'script 2'"],
+ after_script: ["echo 'after script 2"],
+ tag_list: ['tag 2'],
+ environment: 'stg',
+ when: 'on_success',
+ allow_failure: true,
+ only: { refs: ['web', 'chat', 'pushes'] },
+ except: { refs: ['master@gitlab-org/gitlab', '/^release/.*$/@gitlab-org/gitlab'] },
+ },
+ ],
+};
+
export const mockJobs = [
{
name: 'job_1',
@@ -47,3 +81,14 @@ export const mockErrors = [
export const mockWarnings = [
'"jobs:multi_project_job 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"',
];
+
+export const mockLintDataValid = {
+ data: {
+ lintCI: {
+ errors: [],
+ warnings: [],
+ valid: true,
+ jobs: mockJobs,
+ },
+ },
+};
diff --git a/spec/frontend/ci_variable_list/ci_variable_list/ajax_variable_list_spec.js b/spec/frontend/ci_variable_list/ci_variable_list/ajax_variable_list_spec.js
deleted file mode 100644
index 93b185bd242..00000000000
--- a/spec/frontend/ci_variable_list/ci_variable_list/ajax_variable_list_spec.js
+++ /dev/null
@@ -1,203 +0,0 @@
-import $ from 'jquery';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import AjaxFormVariableList from '~/ci_variable_list/ajax_variable_list';
-
-const VARIABLE_PATCH_ENDPOINT = 'http://test.host/frontend-fixtures/builds-project/-/variables';
-const HIDE_CLASS = 'hide';
-
-describe('AjaxFormVariableList', () => {
- preloadFixtures('projects/ci_cd_settings.html');
- preloadFixtures('projects/ci_cd_settings_with_variables.html');
-
- let container;
- let saveButton;
- let errorBox;
-
- let mock;
- let ajaxVariableList;
-
- beforeEach(() => {
- loadFixtures('projects/ci_cd_settings.html');
- container = document.querySelector('.js-ci-variable-list-section');
-
- mock = new MockAdapter(axios);
-
- const ajaxVariableListEl = document.querySelector('.js-ci-variable-list-section');
- saveButton = ajaxVariableListEl.querySelector('.js-ci-variables-save-button');
- errorBox = container.querySelector('.js-ci-variable-error-box');
- ajaxVariableList = new AjaxFormVariableList({
- container,
- formField: 'variables',
- saveButton,
- errorBox,
- saveEndpoint: container.dataset.saveEndpoint,
- maskableRegex: container.dataset.maskableRegex,
- });
-
- jest.spyOn(ajaxVariableList, 'updateRowsWithPersistedVariables');
- jest.spyOn(ajaxVariableList.variableList, 'toggleEnableRow');
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('onSaveClicked', () => {
- it('shows loading spinner while waiting for the request', () => {
- const loadingIcon = saveButton.querySelector('.js-ci-variables-save-loading-icon');
-
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(() => {
- expect(loadingIcon.classList.contains(HIDE_CLASS)).toEqual(false);
-
- return [200, {}];
- });
-
- expect(loadingIcon.classList.contains(HIDE_CLASS)).toEqual(true);
-
- return ajaxVariableList.onSaveClicked().then(() => {
- expect(loadingIcon.classList.contains(HIDE_CLASS)).toEqual(true);
- });
- });
-
- it('calls `updateRowsWithPersistedVariables` with the persisted variables', () => {
- const variablesResponse = [{ id: 1, key: 'foo', value: 'bar' }];
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(200, {
- variables: variablesResponse,
- });
-
- return ajaxVariableList.onSaveClicked().then(() => {
- expect(ajaxVariableList.updateRowsWithPersistedVariables).toHaveBeenCalledWith(
- variablesResponse,
- );
- });
- });
-
- it('hides any previous error box', () => {
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(200);
-
- expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
-
- return ajaxVariableList.onSaveClicked().then(() => {
- expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
- });
- });
-
- it('disables remove buttons while waiting for the request', () => {
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(() => {
- expect(ajaxVariableList.variableList.toggleEnableRow).toHaveBeenCalledWith(false);
-
- return [200, {}];
- });
-
- return ajaxVariableList.onSaveClicked().then(() => {
- expect(ajaxVariableList.variableList.toggleEnableRow).toHaveBeenCalledWith(true);
- });
- });
-
- it('hides secret values', () => {
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(200, {});
-
- const row = container.querySelector('.js-row');
- const valueInput = row.querySelector('.js-ci-variable-input-value');
- const valuePlaceholder = row.querySelector('.js-secret-value-placeholder');
-
- valueInput.value = 'bar';
- $(valueInput).trigger('input');
-
- expect(valuePlaceholder.classList.contains(HIDE_CLASS)).toBe(true);
- expect(valueInput.classList.contains(HIDE_CLASS)).toBe(false);
-
- return ajaxVariableList.onSaveClicked().then(() => {
- expect(valuePlaceholder.classList.contains(HIDE_CLASS)).toBe(false);
- expect(valueInput.classList.contains(HIDE_CLASS)).toBe(true);
- });
- });
-
- it('shows error box with validation errors', () => {
- const validationError = 'some validation error';
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(400, [validationError]);
-
- expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
-
- return ajaxVariableList.onSaveClicked().then(() => {
- expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(false);
- expect(errorBox.textContent.trim().replace(/\n+\s+/m, ' ')).toEqual(
- `Validation failed ${validationError}`,
- );
- });
- });
-
- it('shows flash message when request fails', () => {
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(500);
-
- expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
-
- return ajaxVariableList.onSaveClicked().then(() => {
- expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
- });
- });
- });
-
- describe('updateRowsWithPersistedVariables', () => {
- beforeEach(() => {
- loadFixtures('projects/ci_cd_settings_with_variables.html');
- container = document.querySelector('.js-ci-variable-list-section');
-
- const ajaxVariableListEl = document.querySelector('.js-ci-variable-list-section');
- saveButton = ajaxVariableListEl.querySelector('.js-ci-variables-save-button');
- errorBox = container.querySelector('.js-ci-variable-error-box');
- ajaxVariableList = new AjaxFormVariableList({
- container,
- formField: 'variables',
- saveButton,
- errorBox,
- saveEndpoint: container.dataset.saveEndpoint,
- });
- });
-
- it('removes variable that was removed', () => {
- expect(container.querySelectorAll('.js-row').length).toBe(3);
-
- container.querySelector('.js-row-remove-button').click();
-
- expect(container.querySelectorAll('.js-row').length).toBe(3);
-
- ajaxVariableList.updateRowsWithPersistedVariables([]);
-
- expect(container.querySelectorAll('.js-row').length).toBe(2);
- });
-
- it('updates new variable row with persisted ID', () => {
- const row = container.querySelector('.js-row:last-child');
- const idInput = row.querySelector('.js-ci-variable-input-id');
- const keyInput = row.querySelector('.js-ci-variable-input-key');
- const valueInput = row.querySelector('.js-ci-variable-input-value');
-
- keyInput.value = 'foo';
- $(keyInput).trigger('input');
- valueInput.value = 'bar';
- $(valueInput).trigger('input');
-
- expect(idInput.value).toEqual('');
-
- ajaxVariableList.updateRowsWithPersistedVariables([
- {
- id: 3,
- key: 'foo',
- value: 'bar',
- },
- ]);
-
- expect(idInput.value).toEqual('3');
- expect(row.dataset.isPersisted).toEqual('true');
- });
- });
-
- describe('maskableRegex', () => {
- it('takes in the regex provided by the data attribute', () => {
- expect(container.dataset.maskableRegex).toBe('^[a-zA-Z0-9_+=/@:.-]{8,}$');
- expect(ajaxVariableList.maskableRegex).toBe(container.dataset.maskableRegex);
- });
- });
-});
diff --git a/spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js b/spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js
index 9508203e5c2..4a2e56c570d 100644
--- a/spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js
+++ b/spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js
@@ -1,5 +1,4 @@
import $ from 'jquery';
-import waitForPromises from 'helpers/wait_for_promises';
import VariableList from '~/ci_variable_list/ci_variable_list';
const HIDE_CLASS = 'hide';
@@ -7,7 +6,6 @@ const HIDE_CLASS = 'hide';
describe('VariableList', () => {
preloadFixtures('pipeline_schedules/edit.html');
preloadFixtures('pipeline_schedules/edit_with_variables.html');
- preloadFixtures('projects/ci_cd_settings.html');
let $wrapper;
let variableList;
@@ -113,92 +111,6 @@ describe('VariableList', () => {
});
});
- describe('with all inputs(key, value, protected)', () => {
- beforeEach(() => {
- loadFixtures('projects/ci_cd_settings.html');
- $wrapper = $('.js-ci-variable-list-section');
-
- $wrapper.find('.js-ci-variable-input-protected').attr('data-default', 'false');
-
- variableList = new VariableList({
- container: $wrapper,
- formField: 'variables',
- });
- variableList.init();
- });
-
- it('should not add another row when editing the last rows protected checkbox', () => {
- const $row = $wrapper.find('.js-row:last-child');
- $row.find('.ci-variable-protected-item .js-project-feature-toggle').click();
-
- return waitForPromises().then(() => {
- expect($wrapper.find('.js-row').length).toBe(1);
- });
- });
-
- it('should not add another row when editing the last rows masked checkbox', () => {
- jest.spyOn(variableList, 'checkIfRowTouched');
- const $row = $wrapper.find('.js-row:last-child');
- $row.find('.ci-variable-masked-item .js-project-feature-toggle').click();
-
- return waitForPromises().then(() => {
- // This validates that we are checking after the event listener has run
- expect(variableList.checkIfRowTouched).toHaveBeenCalled();
- expect($wrapper.find('.js-row').length).toBe(1);
- });
- });
-
- describe('validateMaskability', () => {
- let $row;
-
- const maskingErrorElement = '.js-row:last-child .masking-validation-error';
- const clickToggle = () =>
- $row.find('.ci-variable-masked-item .js-project-feature-toggle').click();
-
- beforeEach(() => {
- $row = $wrapper.find('.js-row:last-child');
- });
-
- it('has a regex provided via a data attribute', () => {
- clickToggle();
-
- expect($wrapper.attr('data-maskable-regex')).toBe('^[a-zA-Z0-9_+=/@:.-]{8,}$');
- });
-
- it('allows values that are 8 characters long', () => {
- $row.find('.js-ci-variable-input-value').val('looooong');
-
- clickToggle();
-
- expect($wrapper.find(maskingErrorElement)).toHaveClass('hide');
- });
-
- it('rejects values that are shorter than 8 characters', () => {
- $row.find('.js-ci-variable-input-value').val('short');
-
- clickToggle();
-
- expect($wrapper.find(maskingErrorElement)).toBeVisible();
- });
-
- it('allows values with base 64 characters', () => {
- $row.find('.js-ci-variable-input-value').val('abcABC123_+=/-');
-
- clickToggle();
-
- expect($wrapper.find(maskingErrorElement)).toHaveClass('hide');
- });
-
- it('rejects values with other special characters', () => {
- $row.find('.js-ci-variable-input-value').val('1234567$');
-
- clickToggle();
-
- expect($wrapper.find(maskingErrorElement)).toBeVisible();
- });
- });
- });
-
describe('toggleEnableRow method', () => {
beforeEach(() => {
loadFixtures('pipeline_schedules/edit_with_variables.html');
@@ -247,36 +159,4 @@ describe('VariableList', () => {
expect($wrapper.find('.js-ci-variable-input-key:not([disabled])').length).toBe(3);
});
});
-
- describe('hideValues', () => {
- beforeEach(() => {
- loadFixtures('projects/ci_cd_settings.html');
- $wrapper = $('.js-ci-variable-list-section');
-
- variableList = new VariableList({
- container: $wrapper,
- formField: 'variables',
- });
- variableList.init();
- });
-
- it('should hide value input and show placeholder stars', () => {
- const $row = $wrapper.find('.js-row');
- const $inputValue = $row.find('.js-ci-variable-input-value');
- const $placeholder = $row.find('.js-secret-value-placeholder');
-
- $row
- .find('.js-ci-variable-input-value')
- .val('foo')
- .trigger('input');
-
- expect($placeholder.hasClass(HIDE_CLASS)).toBe(true);
- expect($inputValue.hasClass(HIDE_CLASS)).toBe(false);
-
- variableList.hideValues();
-
- expect($placeholder.hasClass(HIDE_CLASS)).toBe(false);
- expect($inputValue.hasClass(HIDE_CLASS)).toBe(true);
- });
- });
});
diff --git a/spec/frontend/clusters/components/__snapshots__/applications_spec.js.snap b/spec/frontend/clusters/components/__snapshots__/applications_spec.js.snap
index b6e89281fef..744ef318260 100644
--- a/spec/frontend/clusters/components/__snapshots__/applications_spec.js.snap
+++ b/spec/frontend/clusters/components/__snapshots__/applications_spec.js.snap
@@ -73,7 +73,7 @@ exports[`Applications Ingress application shows the correct warning message 1`]
exports[`Applications Knative application shows the correct description 1`] = `
<span
- data-testid="installedVia"
+ data-testid="installed-via"
>
installed via
<a
diff --git a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
index 15eeadcc8b8..de40e03b598 100644
--- a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
+++ b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
@@ -14,6 +14,8 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ
>
<!---->
+ <!---->
+
<span
class="gl-new-dropdown-button-text"
>
diff --git a/spec/frontend/clusters/components/applications_spec.js b/spec/frontend/clusters/components/applications_spec.js
index e0ccf36e868..5438f3053a8 100644
--- a/spec/frontend/clusters/components/applications_spec.js
+++ b/spec/frontend/clusters/components/applications_spec.js
@@ -429,7 +429,7 @@ describe('Applications', () => {
await wrapper.vm.$nextTick();
- expect(findByTestId('installedVia').element).toMatchSnapshot();
+ expect(findByTestId('installed-via').element).toMatchSnapshot();
});
it('emits saveKnativeDomain event when knative domain editor emits save event', () => {
diff --git a/spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap b/spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap
index 62b751ec59b..62e527a2c5f 100644
--- a/spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap
+++ b/spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap
@@ -12,7 +12,7 @@ exports[`Code navigation popover component renders popover 1`] = `
<gl-tabs-stub
contentclass="gl-py-0"
- nav-class="gl-hidden"
+ navclass="gl-hidden"
theme="indigo"
>
<gl-tab-stub
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 2600415fc9f..f9984091df0 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
@@ -16,7 +16,6 @@ describe('EksClusterConfigurationForm', () => {
let getters;
let state;
let rolesState;
- let regionsState;
let vpcsState;
let subnetsState;
let keyPairsState;
@@ -24,7 +23,6 @@ describe('EksClusterConfigurationForm', () => {
let instanceTypesState;
let vpcsActions;
let rolesActions;
- let regionsActions;
let subnetsActions;
let keyPairsActions;
let securityGroupsActions;
@@ -46,9 +44,6 @@ describe('EksClusterConfigurationForm', () => {
setNodeCount: jest.fn(),
setGitlabManagedCluster: jest.fn(),
};
- regionsActions = {
- fetchItems: jest.fn(),
- };
keyPairsActions = {
fetchItems: jest.fn(),
};
@@ -72,10 +67,6 @@ describe('EksClusterConfigurationForm', () => {
...clusterDropdownStoreState(),
...config.rolesState,
};
- regionsState = {
- ...clusterDropdownStoreState(),
- ...config.regionsState,
- };
vpcsState = {
...clusterDropdownStoreState(),
...config.vpcsState,
@@ -109,11 +100,6 @@ describe('EksClusterConfigurationForm', () => {
state: vpcsState,
actions: vpcsActions,
},
- regions: {
- namespaced: true,
- state: regionsState,
- actions: regionsActions,
- },
subnets: {
namespaced: true,
state: subnetsState,
@@ -189,7 +175,6 @@ describe('EksClusterConfigurationForm', () => {
const findClusterNameInput = () => vm.find('[id=eks-cluster-name]');
const findEnvironmentScopeInput = () => vm.find('[id=eks-environment-scope]');
const findKubernetesVersionDropdown = () => vm.find('[field-id="eks-kubernetes-version"]');
- const findRegionDropdown = () => vm.find('[field-id="eks-region"]');
const findKeyPairDropdown = () => vm.find('[field-id="eks-key-pair"]');
const findVpcDropdown = () => vm.find('[field-id="eks-vpc"]');
const findSubnetDropdown = () => vm.find('[field-id="eks-subnet"]');
@@ -200,13 +185,44 @@ describe('EksClusterConfigurationForm', () => {
const findGitlabManagedClusterCheckbox = () => vm.find(GlFormCheckbox);
describe('when mounted', () => {
- it('fetches available regions', () => {
- expect(regionsActions.fetchItems).toHaveBeenCalled();
- });
-
it('fetches available roles', () => {
expect(rolesActions.fetchItems).toHaveBeenCalled();
});
+
+ describe('when fetching vpcs and key pairs', () => {
+ const region = 'us-west-2';
+
+ beforeEach(() => {
+ createValidStateStore({ selectedRegion: region });
+ buildWrapper();
+ });
+
+ it('fetches available vpcs', () => {
+ expect(vpcsActions.fetchItems).toHaveBeenCalledWith(expect.anything(), { region });
+ });
+
+ it('fetches available key pairs', () => {
+ expect(keyPairsActions.fetchItems).toHaveBeenCalledWith(expect.anything(), { region });
+ });
+
+ it('cleans selected vpc', () => {
+ expect(actions.setVpc).toHaveBeenCalledWith(expect.anything(), { vpc: null });
+ });
+
+ it('cleans selected key pair', () => {
+ expect(actions.setKeyPair).toHaveBeenCalledWith(expect.anything(), { keyPair: null });
+ });
+
+ it('cleans selected subnet', () => {
+ expect(actions.setSubnet).toHaveBeenCalledWith(expect.anything(), { subnet: [] });
+ });
+
+ it('cleans selected security group', () => {
+ expect(actions.setSecurityGroup).toHaveBeenCalledWith(expect.anything(), {
+ securityGroup: null,
+ });
+ });
+ });
});
it('sets isLoadingRoles to RoleDropdown loading property', () => {
@@ -229,26 +245,6 @@ describe('EksClusterConfigurationForm', () => {
});
});
- it('sets isLoadingRegions to RegionDropdown loading property', () => {
- regionsState.isLoadingItems = true;
-
- return Vue.nextTick().then(() => {
- expect(findRegionDropdown().props('loading')).toBe(regionsState.isLoadingItems);
- });
- });
-
- it('sets regions to RegionDropdown regions property', () => {
- expect(findRegionDropdown().props('items')).toBe(regionsState.items);
- });
-
- it('sets loadingRegionsError to RegionDropdown error property', () => {
- regionsState.loadingItemsError = new Error();
-
- return Vue.nextTick().then(() => {
- expect(findRegionDropdown().props('hasErrors')).toEqual(true);
- });
- });
-
it('disables KeyPairDropdown when no region is selected', () => {
expect(findKeyPairDropdown().props('disabled')).toBe(true);
});
@@ -394,44 +390,6 @@ describe('EksClusterConfigurationForm', () => {
});
});
- describe('when region is selected', () => {
- const region = { name: 'us-west-2' };
-
- beforeEach(() => {
- findRegionDropdown().vm.$emit('input', region);
- });
-
- it('dispatches setRegion action', () => {
- expect(actions.setRegion).toHaveBeenCalledWith(expect.anything(), { region });
- });
-
- it('fetches available vpcs', () => {
- expect(vpcsActions.fetchItems).toHaveBeenCalledWith(expect.anything(), { region });
- });
-
- it('fetches available key pairs', () => {
- expect(keyPairsActions.fetchItems).toHaveBeenCalledWith(expect.anything(), { region });
- });
-
- it('cleans selected vpc', () => {
- expect(actions.setVpc).toHaveBeenCalledWith(expect.anything(), { vpc: null });
- });
-
- it('cleans selected key pair', () => {
- expect(actions.setKeyPair).toHaveBeenCalledWith(expect.anything(), { keyPair: null });
- });
-
- it('cleans selected subnet', () => {
- expect(actions.setSubnet).toHaveBeenCalledWith(expect.anything(), { subnet: [] });
- });
-
- it('cleans selected security group', () => {
- expect(actions.setSecurityGroup).toHaveBeenCalledWith(expect.anything(), {
- securityGroup: null,
- });
- });
- });
-
it('dispatches setClusterName when cluster name input changes', () => {
const clusterName = 'name';
diff --git a/spec/frontend/create_cluster/eks_cluster/services/aws_services_facade_spec.js b/spec/frontend/create_cluster/eks_cluster/services/aws_services_facade_spec.js
index 0ef09b4b87e..03c22c570a8 100644
--- a/spec/frontend/create_cluster/eks_cluster/services/aws_services_facade_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/services/aws_services_facade_spec.js
@@ -3,12 +3,10 @@ import EC2 from 'aws-sdk/clients/ec2';
import {
setAWSConfig,
fetchRoles,
- fetchRegions,
fetchKeyPairs,
fetchVpcs,
fetchSubnets,
fetchSecurityGroups,
- DEFAULT_REGION,
} from '~/create_cluster/eks_cluster/services/aws_services_facade';
const mockListRolesPromise = jest.fn();
@@ -45,19 +43,17 @@ describe('awsServicesFacade', () => {
vpc = 'vpc-2';
});
- it('setAWSConfig configures AWS SDK with provided credentials and default region', () => {
+ it('setAWSConfig configures AWS SDK with provided credentials', () => {
const awsCredentials = {
accessKeyId: 'access-key',
secretAccessKey: 'secret-key',
sessionToken: 'session-token',
+ region,
};
setAWSConfig({ awsCredentials });
- expect(AWS.config).toEqual({
- ...awsCredentials,
- region: DEFAULT_REGION,
- });
+ expect(AWS.config).toEqual(awsCredentials);
});
describe('when fetchRoles succeeds', () => {
@@ -79,22 +75,6 @@ describe('awsServicesFacade', () => {
});
});
- describe('when fetchRegions succeeds', () => {
- let regions;
- let regionsOutput;
-
- beforeEach(() => {
- regions = [{ RegionName: 'east-1' }, { RegionName: 'west-2' }];
- regionsOutput = regions.map(({ RegionName: name }) => ({ name, value: name }));
-
- mockDescribeRegionsPromise.mockResolvedValueOnce({ Regions: regions });
- });
-
- it('return list of roles where each item has a name and value', () => {
- return expect(fetchRegions()).resolves.toEqual(regionsOutput);
- });
- });
-
describe('when fetchKeyPairs succeeds', () => {
let keyPairs;
let keyPairsOutput;
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 f929216689a..f12f300872a 100644
--- a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
@@ -23,6 +23,7 @@ import {
REQUEST_CREATE_CLUSTER,
CREATE_CLUSTER_ERROR,
} from '~/create_cluster/eks_cluster/store/mutation_types';
+import { DEFAULT_REGION } from '~/create_cluster/eks_cluster/constants';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
@@ -109,12 +110,13 @@ describe('EKS Cluster Store Actions', () => {
secretAccessKey: 'secret-key-id',
};
- describe('when request succeeds', () => {
+ describe('when request succeeds with default region', () => {
beforeEach(() => {
mock
.onPost(state.createRolePath, {
role_arn: payload.roleArn,
role_external_id: payload.externalId,
+ region: DEFAULT_REGION,
})
.reply(201, response);
});
@@ -125,7 +127,51 @@ describe('EKS Cluster Store Actions', () => {
payload,
state,
[],
- [{ type: 'requestCreateRole' }, { type: 'createRoleSuccess', payload: response }],
+ [
+ { type: 'requestCreateRole' },
+ {
+ type: 'createRoleSuccess',
+ payload: {
+ region: DEFAULT_REGION,
+ ...response,
+ },
+ },
+ ],
+ ));
+ });
+
+ describe('when request succeeds with custom region', () => {
+ const customRegion = 'custom-region';
+
+ beforeEach(() => {
+ mock
+ .onPost(state.createRolePath, {
+ role_arn: payload.roleArn,
+ role_external_id: payload.externalId,
+ region: customRegion,
+ })
+ .reply(201, response);
+ });
+
+ it('dispatches createRoleSuccess action', () =>
+ testAction(
+ actions.createRole,
+ {
+ selectedRegion: customRegion,
+ ...payload,
+ },
+ state,
+ [],
+ [
+ { type: 'requestCreateRole' },
+ {
+ type: 'createRoleSuccess',
+ payload: {
+ region: customRegion,
+ ...response,
+ },
+ },
+ ],
));
});
@@ -138,6 +184,7 @@ describe('EKS Cluster Store Actions', () => {
.onPost(state.createRolePath, {
role_arn: payload.roleArn,
role_external_id: payload.externalId,
+ region: DEFAULT_REGION,
})
.reply(400, error);
});
@@ -160,8 +207,14 @@ describe('EKS Cluster Store Actions', () => {
});
describe('createRoleSuccess', () => {
- it('commits createRoleSuccess mutation', () => {
- testAction(actions.createRoleSuccess, null, state, [{ type: CREATE_ROLE_SUCCESS }]);
+ it('sets region and commits createRoleSuccess mutation', () => {
+ testAction(
+ actions.createRoleSuccess,
+ { region },
+ state,
+ [{ type: CREATE_ROLE_SUCCESS }],
+ [{ type: 'setRegion', payload: { region } }],
+ );
});
});
diff --git a/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js b/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
index 9ecf6bf375b..9f28ddfd230 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
@@ -4,6 +4,7 @@ import { GlButton, GlModal } from '@gitlab/ui';
import DeployFreezeModal from '~/deploy_freeze/components/deploy_freeze_modal.vue';
import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
import createStore from '~/deploy_freeze/store';
+import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -11,8 +12,6 @@ localVue.use(Vuex);
describe('Deploy freeze modal', () => {
let wrapper;
let store;
- const freezePeriodsFixture = getJSONFixture('/api/freeze-periods/freeze_periods.json');
- const timezoneDataFixture = getJSONFixture('/api/freeze-periods/timezone_data.json');
beforeEach(() => {
store = createStore({
diff --git a/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js b/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js
index d40df7de7d1..c29a0c0ca73 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js
@@ -4,6 +4,7 @@ import DeployFreezeSettings from '~/deploy_freeze/components/deploy_freeze_setti
import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vue';
import DeployFreezeModal from '~/deploy_freeze/components/deploy_freeze_modal.vue';
import createStore from '~/deploy_freeze/store';
+import { timezoneDataFixture } from '../helpers';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -11,7 +12,6 @@ localVue.use(Vuex);
describe('Deploy freeze settings', () => {
let wrapper;
let store;
- const timezoneDataFixture = getJSONFixture('/api/freeze-periods/timezone_data.json');
beforeEach(() => {
store = createStore({
diff --git a/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js b/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
index 383ffa90b22..8480705b5e3 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
@@ -2,6 +2,7 @@ import Vuex from 'vuex';
import { createLocalVue, mount } from '@vue/test-utils';
import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vue';
import createStore from '~/deploy_freeze/store';
+import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -9,7 +10,6 @@ localVue.use(Vuex);
describe('Deploy freeze table', () => {
let wrapper;
let store;
- const timezoneDataFixture = getJSONFixture('/api/freeze-periods/timezone_data.json');
const createComponent = () => {
store = createStore({
@@ -50,7 +50,6 @@ describe('Deploy freeze table', () => {
});
it('displays data', () => {
- const freezePeriodsFixture = getJSONFixture('/api/freeze-periods/freeze_periods.json');
store.state.freezePeriods = freezePeriodsFixture;
return wrapper.vm.$nextTick(() => {
diff --git a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
index d1219627ca7..2aa977dfa5a 100644
--- a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
+++ b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
@@ -1,9 +1,9 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlDropdownItem, GlDropdown } from '@gitlab/ui';
-import { secondsToHours } from '~/lib/utils/datetime_utility';
import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
import createStore from '~/deploy_freeze/store';
+import { findTzByName, formatTz, timezoneDataFixture } from '../helpers';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -11,12 +11,6 @@ localVue.use(Vuex);
describe('Deploy freeze timezone dropdown', () => {
let wrapper;
let store;
- const timezoneDataFixture = getJSONFixture('/api/freeze-periods/timezone_data.json');
-
- const findTzByName = (identifier = '') =>
- timezoneDataFixture.find(({ name }) => name.toLowerCase() === identifier.toLowerCase());
-
- const formatTz = ({ offset, name }) => `[UTC ${secondsToHours(offset)}] ${name}`;
const createComponent = (searchTerm, selectedTimezone) => {
store = createStore({
diff --git a/spec/frontend/deploy_freeze/helpers.js b/spec/frontend/deploy_freeze/helpers.js
new file mode 100644
index 00000000000..bfb84142662
--- /dev/null
+++ b/spec/frontend/deploy_freeze/helpers.js
@@ -0,0 +1,9 @@
+import { secondsToHours } from '~/lib/utils/datetime_utility';
+
+export const freezePeriodsFixture = getJSONFixture('/api/freeze-periods/freeze_periods.json');
+export const timezoneDataFixture = getJSONFixture('/api/freeze-periods/timezone_data.json');
+
+export const findTzByName = (identifier = '') =>
+ timezoneDataFixture.find(({ name }) => name.toLowerCase() === identifier.toLowerCase());
+
+export const formatTz = ({ offset, name }) => `[UTC ${secondsToHours(offset)}] ${name}`;
diff --git a/spec/frontend/deploy_freeze/store/actions_spec.js b/spec/frontend/deploy_freeze/store/actions_spec.js
index 97f94cdbf5e..3c9d25c4f5c 100644
--- a/spec/frontend/deploy_freeze/store/actions_spec.js
+++ b/spec/frontend/deploy_freeze/store/actions_spec.js
@@ -6,6 +6,7 @@ import { deprecatedCreateFlash as createFlash } from '~/flash';
import getInitialState from '~/deploy_freeze/store/state';
import * as actions from '~/deploy_freeze/store/actions';
import * as types from '~/deploy_freeze/store/mutation_types';
+import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
jest.mock('~/api.js');
jest.mock('~/flash.js');
@@ -13,8 +14,6 @@ jest.mock('~/flash.js');
describe('deploy freeze store actions', () => {
let mock;
let state;
- const freezePeriodsFixture = getJSONFixture('/api/freeze-periods/freeze_periods.json');
- const timezoneDataFixture = getJSONFixture('/api/freeze-periods/timezone_data.json');
beforeEach(() => {
mock = new MockAdapter(axios);
diff --git a/spec/frontend/deploy_freeze/store/mutations_spec.js b/spec/frontend/deploy_freeze/store/mutations_spec.js
index 0453e037e15..7cb208f16b2 100644
--- a/spec/frontend/deploy_freeze/store/mutations_spec.js
+++ b/spec/frontend/deploy_freeze/store/mutations_spec.js
@@ -2,10 +2,10 @@ import state from '~/deploy_freeze/store/state';
import mutations from '~/deploy_freeze/store/mutations';
import * as types from '~/deploy_freeze/store/mutation_types';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { findTzByName, formatTz, freezePeriodsFixture, timezoneDataFixture } from '../helpers';
describe('Deploy freeze mutations', () => {
let stateCopy;
- const timezoneDataFixture = getJSONFixture('/api/freeze-periods/timezone_data.json');
beforeEach(() => {
stateCopy = state({
@@ -28,7 +28,6 @@ describe('Deploy freeze mutations', () => {
describe('RECEIVE_FREEZE_PERIODS_SUCCESS', () => {
it('should set freeze periods and format timezones from identifiers to names', () => {
const timezoneNames = ['Berlin', 'UTC', 'Eastern Time (US & Canada)'];
- const freezePeriodsFixture = getJSONFixture('/api/freeze-periods/freeze_periods.json');
mutations[types.RECEIVE_FREEZE_PERIODS_SUCCESS](stateCopy, freezePeriodsFixture);
@@ -43,9 +42,10 @@ describe('Deploy freeze mutations', () => {
describe('SET_SELECTED_TIMEZONE', () => {
it('should set the cron timezone', () => {
+ const selectedTz = findTzByName('Pacific Time (US & Canada)');
const timezone = {
- formattedTimezone: '[UTC -7] Pacific Time (US & Canada)',
- identifier: 'America/Los_Angeles',
+ formattedTimezone: formatTz(selectedTz),
+ identifier: selectedTz.identifier,
};
mutations[types.SET_SELECTED_TIMEZONE](stateCopy, timezone);
diff --git a/spec/frontend/deploy_keys/components/key_spec.js b/spec/frontend/deploy_keys/components/key_spec.js
index 0b1cbd28274..d990c64c241 100644
--- a/spec/frontend/deploy_keys/components/key_spec.js
+++ b/spec/frontend/deploy_keys/components/key_spec.js
@@ -79,7 +79,7 @@ describe('Deploy keys key', () => {
deployKeysProjects[0] = { ...deployKeysProjects[0], can_push: true };
createComponent({ deployKey: { ...deployKey, deploy_keys_projects: deployKeysProjects } });
- expect(wrapper.find('.deploy-project-label').attributes('data-original-title')).toBe(
+ expect(wrapper.find('.deploy-project-label').attributes('title')).toBe(
'Write access allowed',
);
});
@@ -88,9 +88,7 @@ describe('Deploy keys key', () => {
deployKeysProjects[0] = { ...deployKeysProjects[0], can_push: false };
createComponent({ deployKey: { ...deployKey, deploy_keys_projects: deployKeysProjects } });
- expect(wrapper.find('.deploy-project-label').attributes('data-original-title')).toBe(
- 'Read access only',
- );
+ expect(wrapper.find('.deploy-project-label').attributes('title')).toBe('Read access only');
});
it('shows expandable button if more than two projects', () => {
@@ -99,7 +97,7 @@ describe('Deploy keys key', () => {
expect(labels.length).toBe(2);
expect(labels.at(1).text()).toContain('others');
- expect(labels.at(1).attributes('data-original-title')).toContain('Expand');
+ expect(labels.at(1).attributes('title')).toContain('Expand');
});
it('expands all project labels after click', () => {
@@ -115,7 +113,7 @@ describe('Deploy keys key', () => {
expect(labels.length).toBe(length);
expect(labels.at(1).text()).not.toContain(`+${length} others`);
- expect(labels.at(1).attributes('data-original-title')).not.toContain('Expand');
+ expect(labels.at(1).attributes('title')).not.toContain('Expand');
});
});
diff --git a/spec/frontend/design_management/components/__snapshots__/design_scaler_spec.js.snap b/spec/frontend/design_management/components/__snapshots__/design_scaler_spec.js.snap
deleted file mode 100644
index 0679b485f77..00000000000
--- a/spec/frontend/design_management/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="gl-display-flex gl-justify-content-center gl-align-items-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="gl-display-flex gl-justify-content-center gl-align-items-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="gl-display-flex gl-justify-content-center gl-align-items-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/components/design_overlay_spec.js b/spec/frontend/design_management/components/design_overlay_spec.js
index 4ef067e3f5e..f4fd4c70dfc 100644
--- a/spec/frontend/design_management/components/design_overlay_spec.js
+++ b/spec/frontend/design_management/components/design_overlay_spec.js
@@ -243,11 +243,11 @@ describe('Design overlay component', () => {
});
});
- describe('without [adminNote] permission', () => {
+ describe('without [repositionNote] permission', () => {
const mockNoteNotAuthorised = {
...notes[0],
userPermissions: {
- adminNote: false,
+ repositionNote: false,
},
};
@@ -412,18 +412,18 @@ describe('Design overlay component', () => {
describe('canMoveNote', () => {
it.each`
- adminNotePermission | canMoveNoteResult
- ${true} | ${true}
- ${false} | ${false}
- ${undefined} | ${false}
+ repositionNotePermission | canMoveNoteResult
+ ${true} | ${true}
+ ${false} | ${false}
+ ${undefined} | ${false}
`(
- 'returns [$canMoveNoteResult] when [adminNote permission] is [$adminNotePermission]',
- ({ adminNotePermission, canMoveNoteResult }) => {
+ 'returns [$canMoveNoteResult] when [repositionNote permission] is [$repositionNotePermission]',
+ ({ repositionNotePermission, canMoveNoteResult }) => {
createComponent();
const note = {
userPermissions: {
- adminNote: adminNotePermission,
+ repositionNote: repositionNotePermission,
},
};
expect(wrapper.vm.canMoveNote(note)).toBe(canMoveNoteResult);
diff --git a/spec/frontend/design_management/components/design_scaler_spec.js b/spec/frontend/design_management/components/design_scaler_spec.js
index b06d2f924df..290ec3a18e3 100644
--- a/spec/frontend/design_management/components/design_scaler_spec.js
+++ b/spec/frontend/design_management/components/design_scaler_spec.js
@@ -1,67 +1,93 @@
import { shallowMount } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
import DesignScaler from '~/design_management/components/design_scaler.vue';
describe('Design management design scaler component', () => {
let wrapper;
- function createComponent(propsData, data = {}) {
- wrapper = shallowMount(DesignScaler, {
- propsData,
- });
- wrapper.setData(data);
- }
+ const getButtons = () => wrapper.findAll(GlButton);
+ const getDecreaseScaleButton = () => getButtons().at(0);
+ const getResetScaleButton = () => getButtons().at(1);
+ const getIncreaseScaleButton = () => getButtons().at(2);
- afterEach(() => {
- wrapper.destroy();
- });
+ const setScale = scale => wrapper.vm.setScale(scale);
- const getButton = type => {
- const buttonTypeOrder = ['minus', 'reset', 'plus'];
- const buttons = wrapper.findAll('button');
- return buttons.at(buttonTypeOrder.indexOf(type));
+ const createComponent = () => {
+ wrapper = shallowMount(DesignScaler);
};
- it('emits @scale event when "plus" button clicked', () => {
+ beforeEach(() => {
createComponent();
+ });
- getButton('plus').trigger('click');
- expect(wrapper.emitted('scale')).toEqual([[1.2]]);
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
});
- 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]]);
+ describe('when `scale` value is greater than 1', () => {
+ beforeEach(async () => {
+ setScale(1.6);
+ await wrapper.vm.$nextTick();
});
- });
- it('emits @scale event when "minus" button clicked (scale > 1)', () => {
- createComponent({}, { scale: 1.6 });
+ it('emits @scale event when "reset" button clicked', () => {
+ getResetScaleButton().vm.$emit('click');
+ expect(wrapper.emitted('scale')[1]).toEqual([1]);
+ });
- return wrapper.vm.$nextTick().then(() => {
- getButton('minus').trigger('click');
- expect(wrapper.emitted('scale')).toEqual([[1.4]]);
+ it('emits @scale event when "decrement" button clicked', async () => {
+ getDecreaseScaleButton().vm.$emit('click');
+ expect(wrapper.emitted('scale')[1]).toEqual([1.4]);
});
- });
- it('minus and reset buttons are disabled when scale === 1', () => {
- createComponent();
+ it('enables the "reset" button', () => {
+ const resetButton = getResetScaleButton();
+
+ expect(resetButton.exists()).toBe(true);
+ expect(resetButton.props('disabled')).toBe(false);
+ });
+
+ it('enables the "decrement" button', () => {
+ const decrementButton = getDecreaseScaleButton();
- expect(wrapper.element).toMatchSnapshot();
+ expect(decrementButton.exists()).toBe(true);
+ expect(decrementButton.props('disabled')).toBe(false);
+ });
+ });
+
+ it('emits @scale event when "plus" button clicked', () => {
+ getIncreaseScaleButton().vm.$emit('click');
+ expect(wrapper.emitted('scale')).toEqual([[1.2]]);
});
- it('minus and reset buttons are enabled when scale > 1', () => {
- createComponent({}, { scale: 1.2 });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
+ describe('when `scale` value is 1', () => {
+ it('disables the "reset" button', () => {
+ const resetButton = getResetScaleButton();
+
+ expect(resetButton.exists()).toBe(true);
+ expect(resetButton.props('disabled')).toBe(true);
+ });
+
+ it('disables the "decrement" button', () => {
+ const decrementButton = getDecreaseScaleButton();
+
+ expect(decrementButton.exists()).toBe(true);
+ expect(decrementButton.props('disabled')).toBe(true);
});
});
- it('plus button is disabled when scale === 2', () => {
- createComponent({}, { scale: 2 });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
+ describe('when `scale` value is 2 (maximum)', () => {
+ beforeEach(async () => {
+ setScale(2);
+ await wrapper.vm.$nextTick();
+ });
+
+ it('disables the "increment" button', () => {
+ const incrementButton = getIncreaseScaleButton();
+
+ expect(incrementButton.exists()).toBe(true);
+ expect(incrementButton.props('disabled')).toBe(true);
});
});
});
diff --git a/spec/frontend/design_management/components/toolbar/__snapshots__/index_spec.js.snap b/spec/frontend/design_management/components/toolbar/__snapshots__/index_spec.js.snap
index 723ac0491a7..e2ad4c68bea 100644
--- a/spec/frontend/design_management/components/toolbar/__snapshots__/index_spec.js.snap
+++ b/spec/frontend/design_management/components/toolbar/__snapshots__/index_spec.js.snap
@@ -46,6 +46,7 @@ exports[`Design management toolbar component renders design and updated data 1`]
href="/-/designs/306/7f747adcd4693afadbe968d7ba7d983349b9012d"
icon="download"
size="medium"
+ title="Download design"
variant="default"
/>
@@ -57,6 +58,7 @@ exports[`Design management toolbar component renders design and updated data 1`]
buttonvariant="warning"
class="gl-ml-3"
hasselecteddesigns="true"
+ title="Archive design"
/>
</header>
`;
diff --git a/spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap b/spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap
index eaa7460ae15..2f857247303 100644
--- a/spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap
+++ b/spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap
@@ -14,41 +14,7 @@ exports[`Design management upload button component renders inverted upload desig
>
Upload designs
-
- <!---->
- </gl-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-button-stub
- buttontextclasses=""
- category="primary"
- disabled="true"
- icon=""
- size="small"
- title="Adding a design with the same filename replaces the file in a new version."
- variant="default"
- >
-
- Upload designs
-
- <gl-loading-icon-stub
- class="ml-1"
- color="orange"
- inline="true"
- label="Loading"
- size="sm"
- />
+
</gl-button-stub>
<input
@@ -73,8 +39,7 @@ exports[`Design management upload button component renders upload design button
>
Upload designs
-
- <!---->
+
</gl-button-stub>
<input
diff --git a/spec/frontend/design_management/components/upload/__snapshots__/design_dropzone_spec.js.snap b/spec/frontend/design_management/components/upload/__snapshots__/design_dropzone_spec.js.snap
deleted file mode 100644
index 1ca5360fa59..00000000000
--- a/spec/frontend/design_management/components/upload/__snapshots__/design_dropzone_spec.js.snap
+++ /dev/null
@@ -1,501 +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="gl-w-full gl-relative"
->
- <button
- class="card design-dropzone-card design-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
- data-testid="dropzone-area"
- >
- <gl-icon-stub
- class="gl-mb-2"
- name="upload"
- size="24"
- />
-
- <p
- class="gl-mb-0"
- >
- <gl-sprintf-stub
- message="Drop or %{linkStart}upload%{linkEnd} designs to attach"
- />
- </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 gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
- style=""
- >
- <div
- class="mw-50 gl-text-center"
- style="display: none;"
- >
- <h3
- class=""
- >
- 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 gl-text-center"
- style=""
- >
- <h3
- class=""
- >
- 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="gl-w-full gl-relative"
->
- <button
- class="card design-dropzone-card design-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
- data-testid="dropzone-area"
- >
- <gl-icon-stub
- class="gl-mb-2"
- name="upload"
- size="24"
- />
-
- <p
- class="gl-mb-0"
- >
- <gl-sprintf-stub
- message="Drop or %{linkStart}upload%{linkEnd} designs to attach"
- />
- </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 gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
- style=""
- >
- <div
- class="mw-50 gl-text-center"
- style="display: none;"
- >
- <h3
- class=""
- >
- 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 gl-text-center"
- style=""
- >
- <h3
- class=""
- >
- 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="gl-w-full gl-relative"
->
- <button
- class="card design-dropzone-card design-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
- data-testid="dropzone-area"
- >
- <gl-icon-stub
- class="gl-mb-2"
- name="upload"
- size="24"
- />
-
- <p
- class="gl-mb-0"
- >
- <gl-sprintf-stub
- message="Drop or %{linkStart}upload%{linkEnd} designs to attach"
- />
- </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 gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
- style=""
- >
- <div
- class="mw-50 gl-text-center"
- >
- <h3
- class=""
- >
- 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 gl-text-center"
- style="display: none;"
- >
- <h3
- class=""
- >
- 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="gl-w-full gl-relative"
->
- <button
- class="card design-dropzone-card design-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
- data-testid="dropzone-area"
- >
- <gl-icon-stub
- class="gl-mb-2"
- name="upload"
- size="24"
- />
-
- <p
- class="gl-mb-0"
- >
- <gl-sprintf-stub
- message="Drop or %{linkStart}upload%{linkEnd} designs to attach"
- />
- </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 gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
- style=""
- >
- <div
- class="mw-50 gl-text-center"
- >
- <h3
- class=""
- >
- 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 gl-text-center"
- style="display: none;"
- >
- <h3
- class=""
- >
- 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="gl-w-full gl-relative"
->
- <button
- class="card design-dropzone-card design-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
- data-testid="dropzone-area"
- >
- <gl-icon-stub
- class="gl-mb-2"
- name="upload"
- size="24"
- />
-
- <p
- class="gl-mb-0"
- >
- <gl-sprintf-stub
- message="Drop or %{linkStart}upload%{linkEnd} designs to attach"
- />
- </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 gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
- style="display: none;"
- >
- <div
- class="mw-50 gl-text-center"
- >
- <h3
- class=""
- >
- 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 gl-text-center"
- style="display: none;"
- >
- <h3
- class=""
- >
- 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="gl-w-full gl-relative"
->
- <button
- class="card design-dropzone-card design-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
- data-testid="dropzone-area"
- >
- <gl-icon-stub
- class="gl-mb-2"
- name="upload"
- size="24"
- />
-
- <p
- class="gl-mb-0"
- >
- <gl-sprintf-stub
- message="Drop or %{linkStart}upload%{linkEnd} designs to attach"
- />
- </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 gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
- style="display: none;"
- >
- <div
- class="mw-50 gl-text-center"
- >
- <h3
- class=""
- >
- 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 gl-text-center"
- style="display: none;"
- >
- <h3
- class=""
- >
- 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="gl-w-full gl-relative"
->
- <div>
- dropzone slot
- </div>
-
- <transition-stub
- name="design-dropzone-fade"
- >
- <div
- class="card design-dropzone-border design-dropzone-overlay gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
- style="display: none;"
- >
- <div
- class="mw-50 gl-text-center"
- >
- <h3
- class=""
- >
- 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 gl-text-center"
- style="display: none;"
- >
- <h3
- class=""
- >
- Incoming!
- </h3>
-
- <span>
- Drop your designs to start your upload.
- </span>
- </div>
- </div>
- </transition-stub>
-</div>
-`;
diff --git a/spec/frontend/design_management/components/upload/button_spec.js b/spec/frontend/design_management/components/upload/button_spec.js
index c0a9693dc37..ea738496ad6 100644
--- a/spec/frontend/design_management/components/upload/button_spec.js
+++ b/spec/frontend/design_management/components/upload/button_spec.js
@@ -1,10 +1,11 @@
import { shallowMount } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
import UploadButton from '~/design_management/components/upload/button.vue';
describe('Design management upload button component', () => {
let wrapper;
- function createComponent(isSaving = false, isInverted = false) {
+ function createComponent({ isSaving = false, isInverted = false } = {}) {
wrapper = shallowMount(UploadButton, {
propsData: {
isSaving,
@@ -24,15 +25,19 @@ describe('Design management upload button component', () => {
});
it('renders inverted upload design button', () => {
- createComponent(false, true);
+ createComponent({ isInverted: true });
expect(wrapper.element).toMatchSnapshot();
});
- it('renders loading icon', () => {
- createComponent(true);
+ describe('when `isSaving` prop is `true`', () => {
+ it('Button `loading` prop is `true`', () => {
+ createComponent({ isSaving: true });
- expect(wrapper.element).toMatchSnapshot();
+ const button = wrapper.find(GlButton);
+ expect(button.exists()).toBe(true);
+ expect(button.props('loading')).toBe(true);
+ });
});
describe('onFileUploadChange', () => {
diff --git a/spec/frontend/design_management/components/upload/design_dropzone_spec.js b/spec/frontend/design_management/components/upload/design_dropzone_spec.js
deleted file mode 100644
index bf97399368f..00000000000
--- a/spec/frontend/design_management/components/upload/design_dropzone_spec.js
+++ /dev/null
@@ -1,153 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlIcon } from '@gitlab/ui';
-import DesignDropzone from '~/design_management/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');
- const findDropzoneArea = () => wrapper.find('[data-testid="dropzone-area"]');
- const findIcon = () => wrapper.find(GlIcon);
-
- function createComponent({ slots = {}, data = {}, props = {} } = {}) {
- wrapper = shallowMount(DesignDropzone, {
- slots,
- propsData: {
- hasDesigns: true,
- ...props,
- },
- 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);
- });
- });
- });
-
- it('applies correct classes when there are no designs or no design saving loader', () => {
- createComponent({ props: { hasDesigns: false } });
- expect(findDropzoneArea().classes()).not.toContain('gl-flex-direction-column');
- expect(findIcon().classes()).toEqual(['gl-mr-3', 'gl-text-gray-500']);
- expect(findIcon().props('size')).toBe(16);
- });
-
- it('applies correct classes when there are designs or design saving loader', () => {
- createComponent({ props: { hasDesigns: true } });
- expect(findDropzoneArea().classes()).toContain('gl-flex-direction-column');
- expect(findIcon().classes()).toEqual(['gl-mb-2']);
- expect(findIcon().props('size')).toBe(24);
- });
-});
diff --git a/spec/frontend/design_management/mock_data/apollo_mock.js b/spec/frontend/design_management/mock_data/apollo_mock.js
index 5e41210221b..e53ad2e6afe 100644
--- a/spec/frontend/design_management/mock_data/apollo_mock.js
+++ b/spec/frontend/design_management/mock_data/apollo_mock.js
@@ -1,13 +1,18 @@
export const designListQueryResponse = {
data: {
project: {
+ __typename: 'Project',
id: '1',
issue: {
+ __typename: 'Issue',
designCollection: {
+ __typename: 'DesignCollection',
copyState: 'READY',
designs: {
+ __typename: 'DesignConnection',
nodes: [
{
+ __typename: 'Design',
id: '1',
event: 'NONE',
filename: 'fox_1.jpg',
@@ -15,10 +20,12 @@ export const designListQueryResponse = {
image: 'image-1',
imageV432x230: 'image-1',
currentUserTodos: {
+ __typename: 'ToDo',
nodes: [],
},
},
{
+ __typename: 'Design',
id: '2',
event: 'NONE',
filename: 'fox_2.jpg',
@@ -26,10 +33,12 @@ export const designListQueryResponse = {
image: 'image-2',
imageV432x230: 'image-2',
currentUserTodos: {
+ __typename: 'ToDo',
nodes: [],
},
},
{
+ __typename: 'Design',
id: '3',
event: 'NONE',
filename: 'fox_3.jpg',
@@ -37,12 +46,14 @@ export const designListQueryResponse = {
image: 'image-3',
imageV432x230: 'image-3',
currentUserTodos: {
+ __typename: 'ToDo',
nodes: [],
},
},
],
},
versions: {
+ __typename: 'DesignVersion',
nodes: [],
},
},
@@ -82,9 +93,11 @@ export const designUploadMutationUpdatedResponse = {
export const permissionsQueryResponse = {
data: {
project: {
+ __typename: 'Project',
id: '1',
issue: {
- userPermissions: { createDesign: true },
+ __typename: 'Issue',
+ userPermissions: { __typename: 'UserPermissions', createDesign: true },
},
},
},
@@ -92,6 +105,7 @@ export const permissionsQueryResponse = {
export const reorderedDesigns = [
{
+ __typename: 'Design',
id: '2',
event: 'NONE',
filename: 'fox_2.jpg',
@@ -99,10 +113,12 @@ export const reorderedDesigns = [
image: 'image-2',
imageV432x230: 'image-2',
currentUserTodos: {
+ __typename: 'ToDo',
nodes: [],
},
},
{
+ __typename: 'Design',
id: '1',
event: 'NONE',
filename: 'fox_1.jpg',
@@ -110,10 +126,12 @@ export const reorderedDesigns = [
image: 'image-1',
imageV432x230: 'image-1',
currentUserTodos: {
+ __typename: 'ToDo',
nodes: [],
},
},
{
+ __typename: 'Design',
id: '3',
event: 'NONE',
filename: 'fox_3.jpg',
@@ -121,6 +139,7 @@ export const reorderedDesigns = [
image: 'image-3',
imageV432x230: 'image-3',
currentUserTodos: {
+ __typename: 'ToDo',
nodes: [],
},
},
@@ -130,7 +149,9 @@ export const moveDesignMutationResponse = {
data: {
designManagementMove: {
designCollection: {
+ __typename: 'DesignCollection',
designs: {
+ __typename: 'DesignConnection',
nodes: [...reorderedDesigns],
},
},
diff --git a/spec/frontend/design_management/mock_data/discussion.js b/spec/frontend/design_management/mock_data/discussion.js
index fbf9a2fdcc1..0e59ef29f8f 100644
--- a/spec/frontend/design_management/mock_data/discussion.js
+++ b/spec/frontend/design_management/mock_data/discussion.js
@@ -18,7 +18,7 @@ export default {
},
createdAt: '2020-05-08T07:10:45Z',
userPermissions: {
- adminNote: true,
+ repositionNote: true,
},
resolved: false,
},
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 2d29b79e31c..abd455ae750 100644
--- a/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap
+++ b/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap
@@ -1,240 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Design management index page designs does not render toolbar when there is no permission 1`] = `
-<div
- class="gl-mt-5"
- data-testid="designs-root"
->
- <!---->
-
- <div
- class="gl-mt-6"
- >
- <ol
- class="list-unstyled row"
- >
- <li
- class="gl-flex-direction-column col-md-6 col-lg-3 gl-mb-3"
- data-testid="design-dropzone-wrapper"
- >
- <design-dropzone-stub
- class="design-list-item design-list-item-new"
- data-qa-selector="design_dropzone_content"
- hasdesigns="true"
- />
- </li>
- <li
- class="col-md-6 col-lg-3 gl-mb-3 gl-bg-transparent gl-shadow-none js-design-tile"
- >
- <design-dropzone-stub
- hasdesigns="true"
- >
- <design-stub
- class="gl-bg-white"
- 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-3 gl-mb-3 gl-bg-transparent gl-shadow-none js-design-tile"
- >
- <design-dropzone-stub
- hasdesigns="true"
- >
- <design-stub
- class="gl-bg-white"
- 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-3 gl-mb-3 gl-bg-transparent gl-shadow-none js-design-tile"
- >
- <design-dropzone-stub
- hasdesigns="true"
- >
- <design-stub
- class="gl-bg-white"
- 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
- class="gl-mt-5"
- data-testid="designs-root"
->
- <header
- class="row-content-block gl-border-t-0 gl-p-3 gl-display-flex"
- >
- <div
- class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-w-full"
- >
- <div>
- <span
- class="gl-font-weight-bold gl-mr-3"
- >
- Designs
- </span>
-
- <design-version-dropdown-stub />
- </div>
-
- <div
- class="qa-selector-toolbar gl-display-flex gl-align-items-center"
- >
- <gl-button-stub
- buttontextclasses=""
- category="primary"
- class="gl-mr-4 js-select-all"
- icon=""
- size="small"
- variant="link"
- >
- Select all
-
- </gl-button-stub>
-
- <div>
- <delete-button-stub
- buttoncategory="secondary"
- buttonclass="gl-mr-3"
- buttonsize="small"
- buttonvariant="warning"
- data-qa-selector="archive_button"
- >
-
- Archive selected
-
- </delete-button-stub>
- </div>
-
- <upload-button-stub />
- </div>
- </div>
- </header>
-
- <div
- class="gl-mt-6"
- >
- <ol
- class="list-unstyled row"
- >
- <li
- class="gl-flex-direction-column col-md-6 col-lg-3 gl-mb-3"
- data-testid="design-dropzone-wrapper"
- >
- <design-dropzone-stub
- class="design-list-item design-list-item-new"
- data-qa-selector="design_dropzone_content"
- hasdesigns="true"
- />
- </li>
- <li
- class="col-md-6 col-lg-3 gl-mb-3 gl-bg-transparent gl-shadow-none js-design-tile"
- >
- <design-dropzone-stub
- hasdesigns="true"
- >
- <design-stub
- class="gl-bg-white"
- event="NONE"
- filename="design-1-name"
- id="design-1"
- image="design-1-image"
- notescount="0"
- />
- </design-dropzone-stub>
-
- <input
- class="design-checkbox"
- data-qa-design="design-1-name"
- data-qa-selector="design_checkbox"
- type="checkbox"
- />
- </li>
- <li
- class="col-md-6 col-lg-3 gl-mb-3 gl-bg-transparent gl-shadow-none js-design-tile"
- >
- <design-dropzone-stub
- hasdesigns="true"
- >
- <design-stub
- class="gl-bg-white"
- event="NONE"
- filename="design-2-name"
- id="design-2"
- image="design-2-image"
- notescount="1"
- />
- </design-dropzone-stub>
-
- <input
- class="design-checkbox"
- data-qa-design="design-2-name"
- data-qa-selector="design_checkbox"
- type="checkbox"
- />
- </li>
- <li
- class="col-md-6 col-lg-3 gl-mb-3 gl-bg-transparent gl-shadow-none js-design-tile"
- >
- <design-dropzone-stub
- hasdesigns="true"
- >
- <design-stub
- class="gl-bg-white"
- event="NONE"
- filename="design-3-name"
- id="design-3"
- image="design-3-image"
- notescount="0"
- />
- </design-dropzone-stub>
-
- <input
- class="design-checkbox"
- data-qa-design="design-3-name"
- data-qa-selector="design_checkbox"
- type="checkbox"
- />
- </li>
- </ol>
- </div>
-
- <router-view-stub
- name="default"
- />
-</div>
-`;
-
exports[`Design management index page designs renders error 1`] = `
<div
class="gl-mt-5"
@@ -277,7 +42,7 @@ exports[`Design management index page designs renders loading icon 1`] = `
class="gl-mt-6"
>
<gl-loading-icon-stub
- color="orange"
+ color="dark"
label="Loading"
size="md"
/>
@@ -288,34 +53,3 @@ exports[`Design management index page designs renders loading icon 1`] = `
/>
</div>
`;
-
-exports[`Design management index page when has no designs renders design dropzone 1`] = `
-<div
- class="gl-mt-5"
- data-testid="designs-root"
->
- <!---->
-
- <div
- class="gl-mt-6"
- >
- <ol
- class="list-unstyled row"
- >
- <li
- class="col-12"
- data-testid="design-dropzone-wrapper"
- >
- <design-dropzone-stub
- class=""
- data-qa-selector="design_dropzone_content"
- />
- </li>
- </ol>
- </div>
-
- <router-view-stub
- name="default"
- />
-</div>
-`;
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 3d6c2561ff6..03ae77d4977 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
@@ -136,7 +136,7 @@ exports[`Design management design index page sets loading state 1`] = `
>
<gl-loading-icon-stub
class="gl-align-self-center"
- color="orange"
+ color="dark"
label="Loading"
size="xl"
/>
diff --git a/spec/frontend/design_management/pages/design/index_spec.js b/spec/frontend/design_management/pages/design/index_spec.js
index d9f7146d258..88892bb1878 100644
--- a/spec/frontend/design_management/pages/design/index_spec.js
+++ b/spec/frontend/design_management/pages/design/index_spec.js
@@ -2,7 +2,7 @@ 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 createFlash from '~/flash';
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';
@@ -24,7 +24,13 @@ import mockAllVersions from '../../mock_data/all_versions';
jest.mock('~/flash');
const focusInput = jest.fn();
-
+const mutate = jest.fn().mockResolvedValue();
+const mockPageLayoutElement = {
+ classList: {
+ add: jest.fn(),
+ remove: jest.fn(),
+ },
+};
const DesignReplyForm = {
template: '<div><textarea ref="textarea"></textarea></div>',
methods: {
@@ -37,6 +43,32 @@ const mockDesignNoDiscussions = {
nodes: [],
},
};
+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 localVue = createLocalVue();
localVue.use(VueRouter);
@@ -45,35 +77,6 @@ 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);
@@ -122,19 +125,44 @@ describe('Design management design index page', () => {
wrapper.destroy();
});
- describe('when navigating', () => {
- it('applies fullscreen layout', () => {
- const mockEl = {
- classList: {
- add: jest.fn(),
- remove: jest.fn(),
- },
- };
- jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockEl);
+ describe('when navigating to component', () => {
+ it('applies fullscreen layout class', () => {
+ jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockPageLayoutElement);
createComponent({ loading: true });
- expect(mockEl.classList.add).toHaveBeenCalledTimes(1);
- expect(mockEl.classList.add).toHaveBeenCalledWith(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
+ expect(mockPageLayoutElement.classList.add).toHaveBeenCalledTimes(1);
+ expect(mockPageLayoutElement.classList.add).toHaveBeenCalledWith(
+ ...DESIGN_DETAIL_LAYOUT_CLASSLIST,
+ );
+ });
+ });
+
+ describe('when navigating within the component', () => {
+ it('`scale` prop of DesignPresentation component is 1', async () => {
+ jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockPageLayoutElement);
+ createComponent({ loading: false }, { data: { design, scale: 2 } });
+
+ await wrapper.vm.$nextTick();
+ expect(findDesignPresentation().props('scale')).toBe(2);
+
+ DesignIndex.beforeRouteUpdate.call(wrapper.vm, {}, {}, jest.fn());
+ await wrapper.vm.$nextTick();
+
+ expect(findDesignPresentation().props('scale')).toBe(1);
+ });
+ });
+
+ describe('when navigating away from component', () => {
+ it('removes fullscreen layout class', async () => {
+ jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockPageLayoutElement);
+ createComponent({ loading: true });
+
+ wrapper.vm.$options.beforeRouteLeave[0].call(wrapper.vm, {}, {}, jest.fn());
+
+ expect(mockPageLayoutElement.classList.remove).toHaveBeenCalledTimes(1);
+ expect(mockPageLayoutElement.classList.remove).toHaveBeenCalledWith(
+ ...DESIGN_DETAIL_LAYOUT_CLASSLIST,
+ );
});
});
@@ -267,7 +295,7 @@ describe('Design management design index page', () => {
wrapper.vm.onDesignQueryResult({ data: mockResponseNoDesigns, loading: false });
return wrapper.vm.$nextTick().then(() => {
expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(DESIGN_NOT_FOUND_ERROR);
+ expect(createFlash).toHaveBeenCalledWith({ message: DESIGN_NOT_FOUND_ERROR });
expect(router.push).toHaveBeenCalledTimes(1);
expect(router.push).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME });
});
@@ -288,7 +316,7 @@ describe('Design management design index page', () => {
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(createFlash).toHaveBeenCalledWith({ message: DESIGN_VERSION_NOT_EXIST_ERROR });
expect(router.push).toHaveBeenCalledTimes(1);
expect(router.push).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME });
});
diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js
index 27a91b11448..05238efd761 100644
--- a/spec/frontend/design_management/pages/index_spec.js
+++ b/spec/frontend/design_management/pages/index_spec.js
@@ -5,10 +5,12 @@ import VueRouter from 'vue-router';
import { GlEmptyState } from '@gitlab/ui';
import createMockApollo from 'jest/helpers/mock_apollo_helper';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
+import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
+import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql';
import Index from '~/design_management/pages/index.vue';
import uploadDesignQuery from '~/design_management/graphql/mutations/upload_design.mutation.graphql';
import DesignDestroyer from '~/design_management/components/design_destroyer.vue';
-import DesignDropzone from '~/design_management/components/upload/design_dropzone.vue';
+import DesignDropzone from '~/vue_shared/components/upload_dropzone/upload_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';
@@ -16,10 +18,9 @@ import {
EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE,
EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE,
} from '~/design_management/utils/error_messages';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import 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,
designUploadMutationCreatedResponse,
@@ -29,8 +30,6 @@ import {
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';
import { DESIGN_TRACKING_PAGE_NAME } from '~/design_management/utils/tracking';
@@ -106,6 +105,8 @@ describe('Design management index page', () => {
const findDesignsWrapper = () => wrapper.find('[data-testid="designs-root"]');
const findDesigns = () => wrapper.findAll(Design);
const draggableAttributes = () => wrapper.find(VueDraggable).vm.$attrs;
+ const findDesignUploadButton = () => wrapper.find('[data-testid="design-upload-button"]');
+ const findDesignToolbarWrapper = () => wrapper.find('[data-testid="design-toolbar-wrapper"]');
async function moveDesigns(localWrapper) {
await jest.runOnlyPendingTimers();
@@ -215,13 +216,17 @@ describe('Design management index page', () => {
it('renders designs list and header with upload button', () => {
createComponent({ allVersions: [mockVersion] });
- expect(wrapper.element).toMatchSnapshot();
+ expect(findDesignsWrapper().exists()).toBe(true);
+ expect(findDesigns().length).toBe(3);
+ expect(findDesignToolbarWrapper().exists()).toBe(true);
+ expect(findDesignUploadButton().exists()).toBe(true);
});
it('does not render toolbar when there is no permission', () => {
createComponent({ designs: mockDesigns, allVersions: [mockVersion], createDesign: false });
- expect(wrapper.element).toMatchSnapshot();
+ expect(findDesignToolbarWrapper().exists()).toBe(false);
+ expect(findDesignUploadButton().exists()).toBe(false);
});
it('has correct classes applied to design dropzone', () => {
@@ -248,7 +253,7 @@ describe('Design management index page', () => {
it('renders design dropzone', () =>
wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
+ expect(findDropzone().exists()).toBe(true);
}));
it('has correct classes applied to design dropzone', () => {
@@ -444,10 +449,10 @@ describe('Design management index page', () => {
return uploadDesign.then(() => {
expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(
- 'Upload skipped. test.jpg did not change.',
- 'warning',
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Upload skipped. test.jpg did not change.',
+ types: 'warning',
+ });
});
});
@@ -483,7 +488,7 @@ describe('Design management index page', () => {
designDropzone.vm.$emit('change', eventPayload);
expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(message);
+ expect(createFlash).toHaveBeenCalledWith({ message });
});
});
@@ -682,13 +687,6 @@ describe('Design management index page', () => {
});
describe('when navigating', () => {
- it('ensures fullscreen layout is not applied', () => {
- createComponent({ loading: true });
-
- expect(mockPageEl.classList.remove).toHaveBeenCalledTimes(1);
- expect(mockPageEl.classList.remove).toHaveBeenCalledWith(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
- });
-
it('should trigger a scrollIntoView method if designs route is detected', () => {
router.replace({
path: '/designs',
@@ -755,7 +753,7 @@ describe('Design management index page', () => {
await wrapper.vm.$nextTick();
- expect(createFlash).toHaveBeenCalledWith('Houston, we have a problem');
+ expect(createFlash).toHaveBeenCalledWith({ message: 'Houston, we have a problem' });
});
it('displays flash if mutation had a non-recoverable error', async () => {
@@ -769,9 +767,9 @@ describe('Design management index page', () => {
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',
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Something went wrong when reordering designs. Please try again',
+ });
});
});
});
diff --git a/spec/frontend/design_management/utils/cache_update_spec.js b/spec/frontend/design_management/utils/cache_update_spec.js
index 6c859e8c3e8..2fb08c3ef05 100644
--- a/spec/frontend/design_management/utils/cache_update_spec.js
+++ b/spec/frontend/design_management/utils/cache_update_spec.js
@@ -3,7 +3,7 @@ import {
updateStoreAfterDesignsDelete,
updateStoreAfterAddImageDiffNote,
updateStoreAfterUploadDesign,
- updateStoreAfterUpdateImageDiffNote,
+ updateStoreAfterRepositionImageDiffNote,
} from '~/design_management/utils/cache_update';
import {
designDeletionError,
@@ -11,7 +11,7 @@ import {
UPDATE_IMAGE_DIFF_NOTE_ERROR,
} from '~/design_management/utils/error_messages';
import design from '../mock_data/design';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
jest.mock('~/flash.js');
@@ -26,16 +26,16 @@ describe('Design Management cache update', () => {
describe('error handling', () => {
it.each`
- 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 | subject | errorMessage | extraArgs
+ ${'updateStoreAfterDesignsDelete'} | ${updateStoreAfterDesignsDelete} | ${designDeletionError({ singular: true })} | ${[[design]]}
+ ${'updateStoreAfterAddImageDiffNote'} | ${updateStoreAfterAddImageDiffNote} | ${ADD_IMAGE_DIFF_NOTE_ERROR} | ${[]}
+ ${'updateStoreAfterUploadDesign'} | ${updateStoreAfterUploadDesign} | ${mockErrors[0]} | ${[]}
+ ${'updateStoreAfterUpdateImageDiffNote'} | ${updateStoreAfterRepositionImageDiffNote} | ${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);
+ expect(createFlash).toHaveBeenCalledWith({ message: errorMessage });
});
});
});
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 232cfa2f4ca..368448ead10 100644
--- a/spec/frontend/design_management/utils/design_management_utils_spec.js
+++ b/spec/frontend/design_management/utils/design_management_utils_spec.js
@@ -3,7 +3,7 @@ import {
extractDiscussions,
findVersionId,
designUploadOptimisticResponse,
- updateImageDiffNoteOptimisticResponse,
+ repositionImageDiffNoteOptimisticResponse,
isValidDesignFile,
extractDesign,
extractDesignNoteId,
@@ -112,7 +112,7 @@ describe('optimistic responses', () => {
expect(designUploadOptimisticResponse([{ name: 'test' }])).toEqual(expectedResponse);
});
- it('correctly generated for updateImageDiffNoteOptimisticResponse', () => {
+ it('correctly generated for repositionImageDiffNoteOptimisticResponse', () => {
const mockNote = {
id: 'test-note-id',
};
@@ -126,8 +126,8 @@ describe('optimistic responses', () => {
const expectedResponse = {
__typename: 'Mutation',
- updateImageDiffNote: {
- __typename: 'UpdateImageDiffNotePayload',
+ repositionImageDiffNote: {
+ __typename: 'RepositionImageDiffNotePayload',
note: {
...mockNote,
position: mockPosition,
@@ -135,7 +135,7 @@ describe('optimistic responses', () => {
errors: [],
},
};
- expect(updateImageDiffNoteOptimisticResponse(mockNote, { position: mockPosition })).toEqual(
+ expect(repositionImageDiffNoteOptimisticResponse(mockNote, { position: mockPosition })).toEqual(
expectedResponse,
);
});
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index 86560470ada..225710eab63 100644
--- a/spec/frontend/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -697,7 +697,7 @@ describe('diffs/components/app', () => {
});
describe('collapsed files', () => {
- it('should render the collapsed files warning if there are any collapsed files', () => {
+ it('should render the collapsed files warning if there are any automatically collapsed files', () => {
createComponent({}, ({ state }) => {
state.diffs.diffFiles = [{ viewer: { automaticallyCollapsed: true } }];
});
@@ -705,16 +705,14 @@ describe('diffs/components/app', () => {
expect(getCollapsedFilesWarning(wrapper).exists()).toBe(true);
});
- it('should not render the collapsed files warning if the user has dismissed the alert already', async () => {
+ it('should not render the collapsed files warning if there are no automatically collapsed files', () => {
createComponent({}, ({ state }) => {
- state.diffs.diffFiles = [{ viewer: { automaticallyCollapsed: true } }];
+ state.diffs.diffFiles = [
+ { viewer: { automaticallyCollapsed: false, manuallyCollapsed: true } },
+ { viewer: { automaticallyCollapsed: false, manuallyCollapsed: false } },
+ ];
});
- expect(getCollapsedFilesWarning(wrapper).exists()).toBe(true);
-
- wrapper.vm.collapsedWarningDismissed = true;
- await wrapper.vm.$nextTick();
-
expect(getCollapsedFilesWarning(wrapper).exists()).toBe(false);
});
});
diff --git a/spec/frontend/diffs/components/collapsed_files_warning_spec.js b/spec/frontend/diffs/components/collapsed_files_warning_spec.js
index 7bbffb7a1cd..75e76d88b6b 100644
--- a/spec/frontend/diffs/components/collapsed_files_warning_spec.js
+++ b/spec/frontend/diffs/components/collapsed_files_warning_spec.js
@@ -2,7 +2,8 @@ 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';
+import { CENTERED_LIMITED_CONTAINER_CLASSES, EVT_EXPAND_ALL_FILES } from '~/diffs/constants';
+import eventHub from '~/diffs/event_hub';
const propsData = {
limited: true,
@@ -76,13 +77,13 @@ describe('CollapsedFilesWarning', () => {
expect(wrapper.find('[data-testid="root"]').exists()).toBe(false);
});
- it('triggers the expandAllFiles action when the alert action button is clicked', () => {
+ it(`emits the \`${EVT_EXPAND_ALL_FILES}\` event when the alert action button is clicked`, () => {
createComponent({}, { full: true });
- jest.spyOn(wrapper.vm.$store, 'dispatch').mockReturnValue(undefined);
+ jest.spyOn(eventHub, '$emit');
getAlertActionButton().vm.$emit('click');
- expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith('diffs/expandAllFiles', undefined);
+ expect(eventHub.$emit).toHaveBeenCalledWith(EVT_EXPAND_ALL_FILES);
});
});
diff --git a/spec/frontend/diffs/components/diff_comment_cell_spec.js b/spec/frontend/diffs/components/diff_comment_cell_spec.js
new file mode 100644
index 00000000000..d6b68fc52d7
--- /dev/null
+++ b/spec/frontend/diffs/components/diff_comment_cell_spec.js
@@ -0,0 +1,43 @@
+import { shallowMount } from '@vue/test-utils';
+import DiffCommentCell from '~/diffs/components/diff_comment_cell.vue';
+import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
+import DiffDiscussionReply from '~/diffs/components/diff_discussion_reply.vue';
+
+describe('DiffCommentCell', () => {
+ const createWrapper = (props = {}) => {
+ const { renderDiscussion, ...otherProps } = props;
+ const line = {
+ discussions: [],
+ renderDiscussion,
+ };
+ const diffFileHash = 'abc';
+
+ return shallowMount(DiffCommentCell, {
+ propsData: { line, diffFileHash, ...otherProps },
+ });
+ };
+
+ it('renders discussions if line has discussions', () => {
+ const wrapper = createWrapper({ renderDiscussion: true });
+
+ expect(wrapper.find(DiffDiscussions).exists()).toBe(true);
+ });
+
+ it('does not render discussions if line has no discussions', () => {
+ const wrapper = createWrapper();
+
+ expect(wrapper.find(DiffDiscussions).exists()).toBe(false);
+ });
+
+ it('renders discussion reply if line has no draft', () => {
+ const wrapper = createWrapper();
+
+ expect(wrapper.find(DiffDiscussionReply).exists()).toBe(true);
+ });
+
+ it('does not render discussion reply if line has draft', () => {
+ const wrapper = createWrapper({ hasDraft: true });
+
+ expect(wrapper.find(DiffDiscussionReply).exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js
index 6d0120d888e..e3a6f7f16a9 100644
--- a/spec/frontend/diffs/components/diff_content_spec.js
+++ b/spec/frontend/diffs/components/diff_content_spec.js
@@ -12,6 +12,8 @@ import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
import { IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants';
import diffFileMockData from '../mock_data/diff_file';
import { diffViewerModes } from '~/ide/constants';
+import { diffLines } from '~/diffs/store/getters';
+import DiffView from '~/diffs/components/diff_view.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -33,7 +35,7 @@ describe('DiffContent', () => {
diffFile: JSON.parse(JSON.stringify(diffFileMockData)),
};
- const createComponent = ({ props, state } = {}) => {
+ const createComponent = ({ props, state, provide } = {}) => {
const fakeStore = new Vuex.Store({
getters: {
getNoteableData() {
@@ -55,6 +57,10 @@ describe('DiffContent', () => {
namespaced: true,
getters: {
draftsForFile: () => () => true,
+ draftForLine: () => () => true,
+ shouldRenderDraftRow: () => () => true,
+ hasParallelDraftLeft: () => () => true,
+ hasParallelDraftRight: () => () => true,
},
},
diffs: {
@@ -68,6 +74,7 @@ describe('DiffContent', () => {
isInlineView: isInlineViewGetterMock,
isParallelView: isParallelViewGetterMock,
getCommentFormForDiffFile: getCommentFormForDiffFileGetterMock,
+ diffLines,
},
actions: {
saveDiffDiscussion: saveDiffDiscussionMock,
@@ -77,6 +84,8 @@ describe('DiffContent', () => {
},
});
+ const glFeatures = provide ? { ...provide.glFeatures } : {};
+
wrapper = shallowMount(DiffContentComponent, {
propsData: {
...defaultProps,
@@ -84,6 +93,7 @@ describe('DiffContent', () => {
},
localVue,
store: fakeStore,
+ provide: { glFeatures },
});
};
@@ -112,6 +122,16 @@ describe('DiffContent', () => {
expect(wrapper.find(ParallelDiffView).exists()).toBe(true);
});
+ it('should render diff view if `unifiedDiffLines` & `unifiedDiffComponents` are true', () => {
+ isParallelViewGetterMock.mockReturnValue(true);
+ createComponent({
+ props: { diffFile: textDiffFile },
+ provide: { glFeatures: { unifiedDiffLines: true, unifiedDiffComponents: true } },
+ });
+
+ expect(wrapper.find(DiffView).exists()).toBe(true);
+ });
+
it('renders rendering more lines loading icon', () => {
createComponent({ props: { diffFile: { ...textDiffFile, renderingLines: true } } });
diff --git a/spec/frontend/diffs/components/diff_file_header_spec.js b/spec/frontend/diffs/components/diff_file_header_spec.js
index a04486fc5c7..1b41456f2f5 100644
--- a/spec/frontend/diffs/components/diff_file_header_spec.js
+++ b/spec/frontend/diffs/components/diff_file_header_spec.js
@@ -1,8 +1,12 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { cloneDeep } from 'lodash';
+
+import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
+
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import FileIcon from '~/vue_shared/components/file_icon.vue';
import diffDiscussionsMockData from '../mock_data/diff_discussions';
import { truncateSha } from '~/lib/utils/text_utility';
import { diffViewerModes } from '~/ide/constants';
@@ -136,9 +140,25 @@ describe('DiffFileHeader component', () => {
});
});
- it('displays a copy to clipboard button', () => {
- createComponent();
- expect(wrapper.find(ClipboardButton).exists()).toBe(true);
+ describe('copy to clipboard', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('displays a copy to clipboard button', () => {
+ expect(wrapper.find(ClipboardButton).exists()).toBe(true);
+ });
+
+ it('triggers the copy to clipboard tracking event', () => {
+ const trackingSpy = mockTracking('_category_', wrapper.vm.$el, jest.spyOn);
+
+ triggerEvent('[data-testid="diff-file-copy-clipboard"]');
+
+ expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_copy_file_button', {
+ label: 'diff_copy_file_path_button',
+ property: 'diff_copy_file',
+ });
+ });
});
describe('for submodule', () => {
@@ -188,6 +208,14 @@ describe('DiffFileHeader component', () => {
});
expect(findFileActions().exists()).toBe(false);
});
+
+ it('renders submodule icon', () => {
+ createComponent({
+ diffFile: submoduleDiffFile,
+ });
+
+ expect(wrapper.find(FileIcon).props('submodule')).toBe(true);
+ });
});
describe('for any file', () => {
diff --git a/spec/frontend/diffs/components/diff_file_spec.js b/spec/frontend/diffs/components/diff_file_spec.js
index a6f0d2bf11d..71e0ffd176f 100644
--- a/spec/frontend/diffs/components/diff_file_spec.js
+++ b/spec/frontend/diffs/components/diff_file_spec.js
@@ -1,262 +1,422 @@
-import Vue from 'vue';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
-import { createStore } from '~/mr_notes/stores';
-import DiffFileComponent from '~/diffs/components/diff_file.vue';
-import { diffViewerModes, diffViewerErrors } from '~/ide/constants';
+import Vuex from 'vuex';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+
+import createDiffsStore from '~/diffs/store/modules';
+import createNotesStore from '~/notes/stores/modules';
import diffFileMockDataReadable from '../mock_data/diff_file';
import diffFileMockDataUnreadable from '../mock_data/diff_file_unreadable';
-describe('DiffFile', () => {
- let vm;
- let trackingSpy;
+import DiffFileComponent from '~/diffs/components/diff_file.vue';
+import DiffFileHeaderComponent from '~/diffs/components/diff_file_header.vue';
+import DiffContentComponent from '~/diffs/components/diff_content.vue';
- beforeEach(() => {
- vm = createComponentWithStore(Vue.extend(DiffFileComponent), createStore(), {
- file: JSON.parse(JSON.stringify(diffFileMockDataReadable)),
+import eventHub from '~/diffs/event_hub';
+import {
+ EVT_EXPAND_ALL_FILES,
+ EVT_PERF_MARK_DIFF_FILES_END,
+ EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN,
+} from '~/diffs/constants';
+
+import { diffViewerModes, diffViewerErrors } from '~/ide/constants';
+
+function changeViewer(store, index, { automaticallyCollapsed, manuallyCollapsed, name }) {
+ const file = store.state.diffs.diffFiles[index];
+ const newViewer = {
+ ...file.viewer,
+ };
+
+ if (automaticallyCollapsed !== undefined) {
+ newViewer.automaticallyCollapsed = automaticallyCollapsed;
+ }
+
+ if (manuallyCollapsed !== undefined) {
+ newViewer.manuallyCollapsed = manuallyCollapsed;
+ }
+
+ if (name !== undefined) {
+ newViewer.name = name;
+ }
+
+ Object.assign(file, {
+ viewer: newViewer,
+ });
+}
+
+function forceHasDiff({ store, index = 0, inlineLines, parallelLines, readableText }) {
+ const file = store.state.diffs.diffFiles[index];
+
+ Object.assign(file, {
+ highlighted_diff_lines: inlineLines,
+ parallel_diff_lines: parallelLines,
+ blob: {
+ ...file.blob,
+ readable_text: readableText,
+ },
+ });
+}
+
+function markFileToBeRendered(store, index = 0) {
+ const file = store.state.diffs.diffFiles[index];
+
+ Object.assign(file, {
+ renderIt: true,
+ });
+}
+
+function createComponent({ file, first = false, last = false }) {
+ const localVue = createLocalVue();
+
+ localVue.use(Vuex);
+
+ const store = new Vuex.Store({
+ ...createNotesStore(),
+ modules: {
+ diffs: createDiffsStore(),
+ },
+ });
+
+ store.state.diffs.diffFiles = [file];
+
+ const wrapper = shallowMount(DiffFileComponent, {
+ store,
+ localVue,
+ propsData: {
+ file,
canCurrentUserFork: false,
viewDiffsFileByFile: false,
- }).$mount();
- trackingSpy = mockTracking('_category_', vm.$el, jest.spyOn);
+ isFirstFile: first,
+ isLastFile: last,
+ },
+ });
+
+ return {
+ localVue,
+ wrapper,
+ store,
+ };
+}
+
+const findDiffHeader = wrapper => wrapper.find(DiffFileHeaderComponent);
+const findDiffContentArea = wrapper => wrapper.find('[data-testid="content-area"]');
+const findLoader = wrapper => wrapper.find('[data-testid="loader-icon"]');
+const findToggleButton = wrapper => wrapper.find('[data-testid="expand-button"]');
+
+const toggleFile = wrapper => findDiffHeader(wrapper).vm.$emit('toggleFile');
+const isDisplayNone = element => element.style.display === 'none';
+const getReadableFile = () => JSON.parse(JSON.stringify(diffFileMockDataReadable));
+const getUnreadableFile = () => JSON.parse(JSON.stringify(diffFileMockDataUnreadable));
+
+const makeFileAutomaticallyCollapsed = (store, index = 0) =>
+ changeViewer(store, index, { automaticallyCollapsed: true, manuallyCollapsed: null });
+const makeFileOpenByDefault = (store, index = 0) =>
+ changeViewer(store, index, { automaticallyCollapsed: false, manuallyCollapsed: null });
+const makeFileManuallyCollapsed = (store, index = 0) =>
+ changeViewer(store, index, { automaticallyCollapsed: false, manuallyCollapsed: true });
+const changeViewerType = (store, newType, index = 0) =>
+ changeViewer(store, index, { name: diffViewerModes[newType] });
+
+describe('DiffFile', () => {
+ let wrapper;
+ let store;
+
+ beforeEach(() => {
+ ({ wrapper, store } = createComponent({ file: getReadableFile() }));
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
});
- const findDiffContent = () => vm.$el.querySelector('.diff-content');
- const isVisible = el => el.style.display !== 'none';
+ describe('bus events', () => {
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ });
+
+ describe('during mount', () => {
+ it.each`
+ first | last | events | file
+ ${false} | ${false} | ${[]} | ${{ inlineLines: [], parallelLines: [], readableText: true }}
+ ${true} | ${true} | ${[]} | ${{ inlineLines: [], parallelLines: [], readableText: true }}
+ ${true} | ${false} | ${[EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN]} | ${false}
+ ${false} | ${true} | ${[EVT_PERF_MARK_DIFF_FILES_END]} | ${false}
+ ${true} | ${true} | ${[EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN, EVT_PERF_MARK_DIFF_FILES_END]} | ${false}
+ `(
+ 'emits the events $events based on the file and its position ({ first: $first, last: $last }) among all files',
+ async ({ file, first, last, events }) => {
+ if (file) {
+ forceHasDiff({ store, ...file });
+ }
+
+ ({ wrapper, store } = createComponent({
+ file: store.state.diffs.diffFiles[0],
+ first,
+ last,
+ }));
+
+ await wrapper.vm.$nextTick();
+
+ expect(eventHub.$emit).toHaveBeenCalledTimes(events.length);
+ events.forEach(event => {
+ expect(eventHub.$emit).toHaveBeenCalledWith(event);
+ });
+ },
+ );
+ });
+
+ describe('after loading the diff', () => {
+ it('indicates that it loaded the file', async () => {
+ forceHasDiff({ store, inlineLines: [], parallelLines: [], readableText: true });
+ ({ wrapper, store } = createComponent({
+ file: store.state.diffs.diffFiles[0],
+ first: true,
+ last: true,
+ }));
+
+ jest.spyOn(wrapper.vm, 'loadCollapsedDiff').mockResolvedValue(getReadableFile());
+ jest.spyOn(window, 'requestIdleCallback').mockImplementation(fn => fn());
+
+ makeFileAutomaticallyCollapsed(store);
+
+ await wrapper.vm.$nextTick(); // Wait for store updates to flow into the component
+
+ toggleFile(wrapper);
+
+ await wrapper.vm.$nextTick(); // Wait for the load to resolve
+ await wrapper.vm.$nextTick(); // Wait for the idleCallback
+ await wrapper.vm.$nextTick(); // Wait for nextTick inside postRender
+
+ expect(eventHub.$emit).toHaveBeenCalledTimes(2);
+ expect(eventHub.$emit).toHaveBeenCalledWith(EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN);
+ expect(eventHub.$emit).toHaveBeenCalledWith(EVT_PERF_MARK_DIFF_FILES_END);
+ });
+ });
+ });
describe('template', () => {
- it('should render component with file header, file content components', done => {
- const el = vm.$el;
- const { file_hash, file_path } = vm.file;
+ it('should render component with file header, file content components', async () => {
+ const el = wrapper.vm.$el;
+ const { file_hash } = wrapper.vm.file;
expect(el.id).toEqual(file_hash);
expect(el.classList.contains('diff-file')).toEqual(true);
expect(el.querySelectorAll('.diff-content.hidden').length).toEqual(0);
expect(el.querySelector('.js-file-title')).toBeDefined();
- expect(el.querySelector('[data-testid="diff-file-copy-clipboard"]')).toBeDefined();
- expect(el.querySelector('.file-title-name').innerText.indexOf(file_path)).toBeGreaterThan(-1);
+ expect(wrapper.find(DiffFileHeaderComponent).exists()).toBe(true);
expect(el.querySelector('.js-syntax-highlight')).toBeDefined();
- vm.file.renderIt = true;
+ markFileToBeRendered(store);
+
+ await wrapper.vm.$nextTick();
- vm.$nextTick()
- .then(() => {
- expect(el.querySelectorAll('.line_content').length).toBe(8);
- expect(el.querySelectorAll('.js-line-expansion-content').length).toBe(1);
- triggerEvent('[data-testid="diff-file-copy-clipboard"]');
- })
- .then(done)
- .catch(done.fail);
+ expect(wrapper.find(DiffContentComponent).exists()).toBe(true);
});
+ });
- it('should track a click event on copy to clip board button', done => {
- const el = vm.$el;
+ describe('collapsing', () => {
+ describe(`\`${EVT_EXPAND_ALL_FILES}\` event`, () => {
+ beforeEach(() => {
+ jest.spyOn(wrapper.vm, 'handleToggle').mockImplementation(() => {});
+ });
- expect(el.querySelector('[data-testid="diff-file-copy-clipboard"]')).toBeDefined();
- vm.file.renderIt = true;
- vm.$nextTick()
- .then(() => {
- triggerEvent('[data-testid="diff-file-copy-clipboard"]');
+ it('performs the normal file toggle when the file is collapsed', async () => {
+ makeFileAutomaticallyCollapsed(store);
- expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_copy_file_button', {
- label: 'diff_copy_file_path_button',
- property: 'diff_copy_file',
- });
- })
- .then(done)
- .catch(done.fail);
- });
+ await wrapper.vm.$nextTick();
- describe('collapsed', () => {
- it('should not have file content', done => {
- expect(isVisible(findDiffContent())).toBe(true);
- expect(vm.isCollapsed).toEqual(false);
- vm.isCollapsed = true;
- vm.file.renderIt = true;
+ eventHub.$emit(EVT_EXPAND_ALL_FILES);
- vm.$nextTick(() => {
- expect(isVisible(findDiffContent())).toBe(false);
-
- done();
- });
+ expect(wrapper.vm.handleToggle).toHaveBeenCalledTimes(1);
});
- it('should have collapsed text and link', done => {
- vm.renderIt = true;
- vm.isCollapsed = true;
+ it('does nothing when the file is not collapsed', async () => {
+ eventHub.$emit(EVT_EXPAND_ALL_FILES);
- vm.$nextTick(() => {
- expect(vm.$el.innerText).toContain('This diff is collapsed');
- expect(vm.$el.querySelectorAll('.js-click-to-expand').length).toEqual(1);
+ await wrapper.vm.$nextTick();
- done();
- });
+ expect(wrapper.vm.handleToggle).not.toHaveBeenCalled();
});
+ });
- it('should have collapsed text and link even before rendered', done => {
- vm.renderIt = false;
- vm.isCollapsed = true;
+ describe('user collapsed', () => {
+ beforeEach(() => {
+ makeFileManuallyCollapsed(store);
+ });
- vm.$nextTick(() => {
- expect(vm.$el.innerText).toContain('This diff is collapsed');
- expect(vm.$el.querySelectorAll('.js-click-to-expand').length).toEqual(1);
+ it('should not have any content at all', async () => {
+ await wrapper.vm.$nextTick();
- done();
+ Array.from(findDiffContentArea(wrapper).element.children).forEach(child => {
+ expect(isDisplayNone(child)).toBe(true);
});
});
- it('should be collapsable for unreadable files', done => {
- vm.$destroy();
- vm = createComponentWithStore(Vue.extend(DiffFileComponent), createStore(), {
- file: JSON.parse(JSON.stringify(diffFileMockDataUnreadable)),
- canCurrentUserFork: false,
- viewDiffsFileByFile: false,
- }).$mount();
+ it('should not have the class `has-body` to present the header differently', () => {
+ expect(wrapper.classes('has-body')).toBe(false);
+ });
+ });
- vm.renderIt = false;
- vm.isCollapsed = true;
+ describe('automatically collapsed', () => {
+ beforeEach(() => {
+ makeFileAutomaticallyCollapsed(store);
+ });
- vm.$nextTick(() => {
- expect(vm.$el.innerText).toContain('This diff is collapsed');
- expect(vm.$el.querySelectorAll('.js-click-to-expand').length).toEqual(1);
+ it('should show the collapsed file warning with expansion button', () => {
+ expect(findDiffContentArea(wrapper).html()).toContain(
+ 'Files with large changes are collapsed by default.',
+ );
+ expect(findToggleButton(wrapper).exists()).toBe(true);
+ });
- done();
- });
+ it('should style the component so that it `.has-body` for layout purposes', () => {
+ expect(wrapper.classes('has-body')).toBe(true);
});
+ });
- it('should be collapsed for renamed files', done => {
- vm.renderIt = true;
- vm.isCollapsed = false;
- vm.file.highlighted_diff_lines = null;
- vm.file.viewer.name = diffViewerModes.renamed;
+ describe('not collapsed', () => {
+ beforeEach(() => {
+ makeFileOpenByDefault(store);
+ markFileToBeRendered(store);
+ });
- vm.$nextTick(() => {
- expect(vm.$el.innerText).not.toContain('This diff is collapsed');
+ it('should have the file content', async () => {
+ expect(wrapper.find(DiffContentComponent).exists()).toBe(true);
+ });
- done();
- });
+ it('should style the component so that it `.has-body` for layout purposes', () => {
+ expect(wrapper.classes('has-body')).toBe(true);
});
+ });
- it('should be collapsed for mode changed files', done => {
- vm.renderIt = true;
- vm.isCollapsed = false;
- vm.file.highlighted_diff_lines = null;
- vm.file.viewer.name = diffViewerModes.mode_changed;
+ describe('toggle', () => {
+ it('should update store state', async () => {
+ jest.spyOn(wrapper.vm.$store, 'dispatch').mockImplementation(() => {});
- vm.$nextTick(() => {
- expect(vm.$el.innerText).not.toContain('This diff is collapsed');
+ toggleFile(wrapper);
- done();
+ expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith('diffs/setFileCollapsedByUser', {
+ filePath: wrapper.vm.file.file_path,
+ collapsed: true,
});
});
- it('should have loading icon while loading a collapsed diffs', done => {
- vm.isCollapsed = true;
- vm.isLoadingCollapsedDiff = true;
+ describe('fetch collapsed diff', () => {
+ const prepFile = async (inlineLines, parallelLines, readableText) => {
+ forceHasDiff({
+ store,
+ inlineLines,
+ parallelLines,
+ readableText,
+ });
+
+ await wrapper.vm.$nextTick();
- vm.$nextTick(() => {
- expect(vm.$el.querySelectorAll('.diff-content.loading').length).toEqual(1);
+ toggleFile(wrapper);
+ };
- done();
+ beforeEach(() => {
+ jest.spyOn(wrapper.vm, 'requestDiff').mockImplementation(() => {});
+
+ makeFileAutomaticallyCollapsed(store);
});
- });
- it('should update store state', done => {
- jest.spyOn(vm.$store, 'dispatch').mockImplementation(() => {});
+ it.each`
+ inlineLines | parallelLines | readableText
+ ${[1]} | ${[1]} | ${true}
+ ${[]} | ${[1]} | ${true}
+ ${[1]} | ${[]} | ${true}
+ ${[1]} | ${[1]} | ${false}
+ ${[]} | ${[]} | ${false}
+ `(
+ 'does not make a request to fetch the diff for a diff file like { inline: $inlineLines, parallel: $parallelLines, readableText: $readableText }',
+ async ({ inlineLines, parallelLines, readableText }) => {
+ await prepFile(inlineLines, parallelLines, readableText);
+
+ expect(wrapper.vm.requestDiff).not.toHaveBeenCalled();
+ },
+ );
- vm.isCollapsed = true;
+ it.each`
+ inlineLines | parallelLines | readableText
+ ${[]} | ${[]} | ${true}
+ `(
+ 'makes a request to fetch the diff for a diff file like { inline: $inlineLines, parallel: $parallelLines, readableText: $readableText }',
+ async ({ inlineLines, parallelLines, readableText }) => {
+ await prepFile(inlineLines, parallelLines, readableText);
- vm.$nextTick(() => {
- expect(vm.$store.dispatch).toHaveBeenCalledWith('diffs/setFileCollapsed', {
- filePath: vm.file.file_path,
- collapsed: true,
- });
+ expect(wrapper.vm.requestDiff).toHaveBeenCalled();
+ },
+ );
+ });
+ });
- done();
- });
+ describe('loading', () => {
+ it('should have loading icon while loading a collapsed diffs', async () => {
+ makeFileAutomaticallyCollapsed(store);
+ wrapper.vm.isLoadingCollapsedDiff = true;
+
+ await wrapper.vm.$nextTick();
+
+ expect(findLoader(wrapper).exists()).toBe(true);
});
+ });
- it('updates local state when changing file state', done => {
- vm.file.viewer.automaticallyCollapsed = true;
+ describe('general (other) collapsed', () => {
+ it('should be expandable for unreadable files', async () => {
+ ({ wrapper, store } = createComponent({ file: getUnreadableFile() }));
+ makeFileAutomaticallyCollapsed(store);
- vm.$nextTick(() => {
- expect(vm.isCollapsed).toBe(true);
+ await wrapper.vm.$nextTick();
- done();
- });
+ expect(findDiffContentArea(wrapper).html()).toContain(
+ 'Files with large changes are collapsed by default.',
+ );
+ expect(findToggleButton(wrapper).exists()).toBe(true);
});
+
+ it.each`
+ mode
+ ${'renamed'}
+ ${'mode_changed'}
+ `(
+ 'should render the DiffContent component for files whose mode is $mode',
+ async ({ mode }) => {
+ makeFileOpenByDefault(store);
+ markFileToBeRendered(store);
+ changeViewerType(store, mode);
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.classes('has-body')).toBe(true);
+ expect(wrapper.find(DiffContentComponent).exists()).toBe(true);
+ expect(wrapper.find(DiffContentComponent).isVisible()).toBe(true);
+ },
+ );
});
});
describe('too large diff', () => {
- it('should have too large warning and blob link', done => {
+ it('should have too large warning and blob link', async () => {
+ const file = store.state.diffs.diffFiles[0];
const BLOB_LINK = '/file/view/path';
- vm.file.viewer.error = diffViewerErrors.too_large;
- vm.file.viewer.error_message =
- 'This source diff could not be displayed because it is too large';
- vm.file.view_path = BLOB_LINK;
- vm.file.renderIt = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.innerText).toContain(
- 'This source diff could not be displayed because it is too large',
- );
- done();
+ Object.assign(store.state.diffs.diffFiles[0], {
+ ...file,
+ view_path: BLOB_LINK,
+ renderIt: true,
+ viewer: {
+ ...file.viewer,
+ error: diffViewerErrors.too_large,
+ error_message: 'This source diff could not be displayed because it is too large',
+ },
});
- });
- });
- describe('watch collapsed', () => {
- it('calls handleLoadCollapsedDiff if collapsed changed & file has no lines', done => {
- jest.spyOn(vm, 'handleLoadCollapsedDiff').mockImplementation(() => {});
-
- vm.file.highlighted_diff_lines = [];
- vm.file.parallel_diff_lines = [];
- vm.isCollapsed = true;
-
- vm.$nextTick()
- .then(() => {
- vm.isCollapsed = false;
-
- return vm.$nextTick();
- })
- .then(() => {
- expect(vm.handleLoadCollapsedDiff).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
+ await wrapper.vm.$nextTick();
- it('does not call handleLoadCollapsedDiff if collapsed changed & file is unreadable', done => {
- vm.$destroy();
- vm = createComponentWithStore(Vue.extend(DiffFileComponent), createStore(), {
- file: JSON.parse(JSON.stringify(diffFileMockDataUnreadable)),
- canCurrentUserFork: false,
- viewDiffsFileByFile: false,
- }).$mount();
-
- jest.spyOn(vm, 'handleLoadCollapsedDiff').mockImplementation(() => {});
-
- vm.file.highlighted_diff_lines = [];
- vm.file.parallel_diff_lines = undefined;
- vm.isCollapsed = true;
-
- vm.$nextTick()
- .then(() => {
- vm.isCollapsed = false;
-
- return vm.$nextTick();
- })
- .then(() => {
- expect(vm.handleLoadCollapsedDiff).not.toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
+ expect(wrapper.vm.$el.innerText).toContain(
+ 'This source diff could not be displayed because it is too large',
+ );
});
});
});
diff --git a/spec/frontend/diffs/components/diff_row_spec.js b/spec/frontend/diffs/components/diff_row_spec.js
new file mode 100644
index 00000000000..f9e76cf8107
--- /dev/null
+++ b/spec/frontend/diffs/components/diff_row_spec.js
@@ -0,0 +1,127 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import diffsModule from '~/diffs/store/modules';
+import DiffRow from '~/diffs/components/diff_row.vue';
+
+describe('DiffRow', () => {
+ const testLines = [
+ {
+ left: { old_line: 1, discussions: [] },
+ right: { new_line: 1, discussions: [] },
+ hasDiscussionsLeft: true,
+ hasDiscussionsRight: true,
+ },
+ {
+ left: {},
+ right: {},
+ isMatchLineLeft: true,
+ isMatchLineRight: true,
+ },
+ {},
+ {
+ left: { old_line: 1, discussions: [] },
+ right: { new_line: 1, discussions: [] },
+ },
+ ];
+
+ const createWrapper = ({ props, state, isLoggedIn = true }) => {
+ const localVue = createLocalVue();
+ localVue.use(Vuex);
+
+ const diffs = diffsModule();
+ diffs.state = { ...diffs.state, ...state };
+
+ const getters = { isLoggedIn: () => isLoggedIn };
+
+ const store = new Vuex.Store({
+ modules: { diffs },
+ getters,
+ });
+
+ const propsData = {
+ fileHash: 'abc',
+ filePath: 'abc',
+ line: {},
+ ...props,
+ };
+ return shallowMount(DiffRow, { propsData, localVue, store });
+ };
+
+ it('isHighlighted returns true if isCommented is true', () => {
+ const props = { isCommented: true };
+ const wrapper = createWrapper({ props });
+ expect(wrapper.vm.isHighlighted).toBe(true);
+ });
+
+ it('isHighlighted returns true given line.left', () => {
+ const props = {
+ line: {
+ left: {
+ line_code: 'abc',
+ },
+ },
+ };
+ const state = { highlightedRow: 'abc' };
+ const wrapper = createWrapper({ props, state });
+ expect(wrapper.vm.isHighlighted).toBe(true);
+ });
+
+ it('isHighlighted returns true given line.right', () => {
+ const props = {
+ line: {
+ right: {
+ line_code: 'abc',
+ },
+ },
+ };
+ const state = { highlightedRow: 'abc' };
+ const wrapper = createWrapper({ props, state });
+ expect(wrapper.vm.isHighlighted).toBe(true);
+ });
+
+ it('isHighlighted returns false given line.left', () => {
+ const props = {
+ line: {
+ left: {
+ line_code: 'abc',
+ },
+ },
+ };
+ const wrapper = createWrapper({ props });
+ expect(wrapper.vm.isHighlighted).toBe(false);
+ });
+
+ describe.each`
+ side
+ ${'left'}
+ ${'right'}
+ `('$side side', ({ side }) => {
+ it(`renders empty cells if ${side} is unavailable`, () => {
+ const wrapper = createWrapper({ props: { line: testLines[2] } });
+ expect(wrapper.find(`[data-testid="${side}LineNumber"]`).exists()).toBe(false);
+ expect(wrapper.find(`[data-testid="${side}EmptyCell"]`).exists()).toBe(true);
+ });
+
+ it('renders comment button', () => {
+ const wrapper = createWrapper({ props: { line: testLines[3] } });
+ expect(wrapper.find(`[data-testid="${side}CommentButton"]`).exists()).toBe(true);
+ });
+
+ it('renders avatars', () => {
+ const wrapper = createWrapper({ props: { line: testLines[0] } });
+ expect(wrapper.find(`[data-testid="${side}Discussions"]`).exists()).toBe(true);
+ });
+ });
+
+ it('renders left line numbers', () => {
+ const wrapper = createWrapper({ props: { line: testLines[0] } });
+ const lineNumber = testLines[0].left.old_line;
+ expect(wrapper.find(`[data-linenumber="${lineNumber}"]`).exists()).toBe(true);
+ });
+
+ it('renders right line numbers', () => {
+ const wrapper = createWrapper({ props: { line: testLines[0] } });
+ const lineNumber = testLines[0].right.new_line;
+ expect(wrapper.find(`[data-linenumber="${lineNumber}"]`).exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/diffs/components/diff_row_utils_spec.js b/spec/frontend/diffs/components/diff_row_utils_spec.js
index 394b6cb1914..c001857fa49 100644
--- a/spec/frontend/diffs/components/diff_row_utils_spec.js
+++ b/spec/frontend/diffs/components/diff_row_utils_spec.js
@@ -201,3 +201,76 @@ describe('shouldShowCommentButton', () => {
},
);
});
+
+describe('mapParallel', () => {
+ it('should assign computed properties to the line object', () => {
+ const side = {
+ discussions: [{}],
+ discussionsExpanded: true,
+ hasForm: true,
+ };
+ const content = {
+ diffFile: {},
+ hasParallelDraftLeft: () => false,
+ hasParallelDraftRight: () => false,
+ draftForLine: () => ({}),
+ };
+ const line = { left: side, right: side };
+ const expectation = {
+ commentRowClasses: '',
+ draftRowClasses: 'js-temp-notes-holder',
+ hasDiscussionsLeft: true,
+ hasDiscussionsRight: true,
+ isContextLineLeft: false,
+ isContextLineRight: false,
+ isMatchLineLeft: false,
+ isMatchLineRight: false,
+ isMetaLineLeft: false,
+ isMetaLineRight: false,
+ };
+ const leftExpectation = {
+ renderDiscussion: true,
+ hasDraft: false,
+ lineDraft: {},
+ hasCommentForm: true,
+ };
+ const rightExpectation = {
+ renderDiscussion: false,
+ hasDraft: false,
+ lineDraft: {},
+ hasCommentForm: false,
+ };
+ const mapped = utils.mapParallel(content)(line);
+
+ expect(mapped).toMatchObject(expectation);
+ expect(mapped.left).toMatchObject(leftExpectation);
+ expect(mapped.right).toMatchObject(rightExpectation);
+ });
+});
+
+describe('mapInline', () => {
+ it('should assign computed properties to the line object', () => {
+ const content = {
+ diffFile: {},
+ shouldRenderDraftRow: () => false,
+ };
+ const line = {
+ discussions: [{}],
+ discussionsExpanded: true,
+ hasForm: true,
+ };
+ const expectation = {
+ commentRowClasses: '',
+ hasDiscussions: true,
+ isContextLine: false,
+ isMatchLine: false,
+ isMetaLine: false,
+ renderDiscussion: true,
+ hasDraft: false,
+ hasCommentForm: true,
+ };
+ const mapped = utils.mapInline(content)(line);
+
+ expect(mapped).toMatchObject(expectation);
+ });
+});
diff --git a/spec/frontend/diffs/components/diff_view_spec.js b/spec/frontend/diffs/components/diff_view_spec.js
new file mode 100644
index 00000000000..4d90112d8f6
--- /dev/null
+++ b/spec/frontend/diffs/components/diff_view_spec.js
@@ -0,0 +1,82 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import DiffView from '~/diffs/components/diff_view.vue';
+// import DraftNote from '~/batch_comments/components/draft_note.vue';
+// import DiffRow from '~/diffs/components/diff_row.vue';
+// import DiffCommentCell from '~/diffs/components/diff_comment_cell.vue';
+// import DiffExpansionCell from '~/diffs/components/diff_expansion_cell.vue';
+
+describe('DiffView', () => {
+ const DiffExpansionCell = { template: `<div/>` };
+ const DiffRow = { template: `<div/>` };
+ const DiffCommentCell = { template: `<div/>` };
+ const DraftNote = { template: `<div/>` };
+ const createWrapper = props => {
+ const localVue = createLocalVue();
+ localVue.use(Vuex);
+
+ const batchComments = {
+ getters: {
+ shouldRenderDraftRow: () => false,
+ shouldRenderParallelDraftRow: () => () => true,
+ draftForLine: () => false,
+ draftsForFile: () => false,
+ hasParallelDraftLeft: () => false,
+ hasParallelDraftRight: () => false,
+ },
+ namespaced: true,
+ };
+ const diffs = { getters: { commitId: () => 'abc123' }, namespaced: true };
+ const notes = {
+ state: { selectedCommentPosition: null, selectedCommentPositionHover: null },
+ };
+
+ const store = new Vuex.Store({
+ modules: { diffs, notes, batchComments },
+ });
+
+ const propsData = {
+ diffFile: {},
+ diffLines: [],
+ ...props,
+ };
+ const stubs = { DiffExpansionCell, DiffRow, DiffCommentCell, DraftNote };
+ return shallowMount(DiffView, { propsData, store, localVue, stubs });
+ };
+
+ it('renders a match line', () => {
+ const wrapper = createWrapper({ diffLines: [{ isMatchLineLeft: true }] });
+ expect(wrapper.find(DiffExpansionCell).exists()).toBe(true);
+ });
+
+ it.each`
+ type | side | container | sides | total
+ ${'parallel'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {} }, right: { lineDraft: {} } }} | ${2}
+ ${'parallel'} | ${'right'} | ${'.new'} | ${{ left: { lineDraft: {} }, right: { lineDraft: {} } }} | ${2}
+ ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {} } }} | ${1}
+ ${'inline'} | ${'right'} | ${'.new'} | ${{ right: { lineDraft: {} } }} | ${1}
+ ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {} }, right: { lineDraft: {} } }} | ${1}
+ `(
+ 'renders a $type comment row with comment cell on $side',
+ ({ type, container, sides, total }) => {
+ const wrapper = createWrapper({
+ diffLines: [{ renderCommentRow: true, ...sides }],
+ inline: type === 'inline',
+ });
+ expect(wrapper.findAll(DiffCommentCell).length).toBe(total);
+ expect(
+ wrapper
+ .find(container)
+ .find(DiffCommentCell)
+ .exists(),
+ ).toBe(true);
+ },
+ );
+
+ it('renders a draft row', () => {
+ const wrapper = createWrapper({
+ diffLines: [{ renderCommentRow: true, left: { lineDraft: { isDraft: true } } }],
+ });
+ expect(wrapper.find(DraftNote).exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/diffs/components/inline_diff_expansion_row_spec.js b/spec/frontend/diffs/components/inline_diff_expansion_row_spec.js
deleted file mode 100644
index 81e5403d502..00000000000
--- a/spec/frontend/diffs/components/inline_diff_expansion_row_spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import Vue from 'vue';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/mr_notes/stores';
-import InlineDiffExpansionRow from '~/diffs/components/inline_diff_expansion_row.vue';
-import diffFileMockData from '../mock_data/diff_file';
-
-describe('InlineDiffExpansionRow', () => {
- const mockData = { ...diffFileMockData };
- const matchLine = mockData.highlighted_diff_lines.pop();
-
- const createComponent = (options = {}) => {
- const cmp = Vue.extend(InlineDiffExpansionRow);
- const defaults = {
- fileHash: mockData.file_hash,
- contextLinesPath: 'contextLinesPath',
- line: matchLine,
- isTop: false,
- isBottom: false,
- };
- const props = { ...defaults, ...options };
-
- return createComponentWithStore(cmp, createStore(), props).$mount();
- };
-
- describe('template', () => {
- it('should render expansion row for match lines', () => {
- const vm = createComponent();
-
- expect(vm.$el.classList.contains('line_expansion')).toBe(true);
- });
- });
-});
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 c65a39b9083..21e7d7397a0 100644
--- a/spec/frontend/diffs/components/inline_diff_table_row_spec.js
+++ b/spec/frontend/diffs/components/inline_diff_table_row_spec.js
@@ -4,6 +4,7 @@ import InlineDiffTableRow from '~/diffs/components/inline_diff_table_row.vue';
import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue';
import diffFileMockData from '../mock_data/diff_file';
import discussionsMockData from '../mock_data/diff_discussions';
+import { mapInline } from '~/diffs/components/diff_row_utils';
const TEST_USER_ID = 'abc123';
const TEST_USER = { id: TEST_USER_ID };
@@ -11,7 +12,16 @@ const TEST_USER = { id: TEST_USER_ID };
describe('InlineDiffTableRow', () => {
let wrapper;
let store;
- const thisLine = diffFileMockData.highlighted_diff_lines[0];
+ const mockDiffContent = {
+ diffFile: diffFileMockData,
+ shouldRenderDraftRow: jest.fn(),
+ hasParallelDraftLeft: jest.fn(),
+ hasParallelDraftRight: jest.fn(),
+ draftForLine: jest.fn(),
+ };
+
+ const applyMap = mapInline(mockDiffContent);
+ const thisLine = applyMap(diffFileMockData.highlighted_diff_lines[0]);
const createComponent = (props = {}, propsStore = store) => {
wrapper = shallowMount(InlineDiffTableRow, {
@@ -132,7 +142,7 @@ describe('InlineDiffTableRow', () => {
${true} | ${{ ...thisLine, type: 'old-nonewline', discussions: [] }} | ${false}
${true} | ${{ ...thisLine, discussions: [{}] }} | ${false}
`('visible is $expectation - line ($line)', ({ isHover, line, expectation }) => {
- createComponent({ line });
+ createComponent({ line: applyMap(line) });
wrapper.setData({ isHover });
return wrapper.vm.$nextTick().then(() => {
@@ -148,7 +158,7 @@ describe('InlineDiffTableRow', () => {
'has attribute disabled=$disabled when the outer component has prop commentsDisabled=$commentsDisabled',
({ disabled, commentsDisabled }) => {
createComponent({
- line: { ...thisLine, commentsDisabled },
+ line: applyMap({ ...thisLine, commentsDisabled }),
});
wrapper.setData({ isHover: true });
@@ -177,7 +187,7 @@ describe('InlineDiffTableRow', () => {
'has the correct tooltip when commentsDisabled=$commentsDisabled',
({ tooltip, commentsDisabled }) => {
createComponent({
- line: { ...thisLine, commentsDisabled },
+ line: applyMap({ ...thisLine, commentsDisabled }),
});
wrapper.setData({ isHover: true });
@@ -216,7 +226,7 @@ describe('InlineDiffTableRow', () => {
beforeEach(() => {
jest.spyOn(store, 'dispatch').mockImplementation();
createComponent({
- line: { ...thisLine, ...lineProps },
+ line: applyMap({ ...thisLine, ...lineProps }),
});
});
@@ -268,7 +278,7 @@ describe('InlineDiffTableRow', () => {
describe('with showCommentButton', () => {
it('renders if line has discussions', () => {
- createComponent({ line });
+ createComponent({ line: applyMap(line) });
expect(findAvatars().props()).toEqual({
discussions: line.discussions,
@@ -278,13 +288,13 @@ describe('InlineDiffTableRow', () => {
it('does notrender if line has no discussions', () => {
line.discussions = [];
- createComponent({ line });
+ createComponent({ line: applyMap(line) });
expect(findAvatars().exists()).toEqual(false);
});
it('toggles line discussion', () => {
- createComponent({ line });
+ createComponent({ line: applyMap(line) });
expect(store.dispatch).toHaveBeenCalledTimes(1);
diff --git a/spec/frontend/diffs/components/inline_diff_view_spec.js b/spec/frontend/diffs/components/inline_diff_view_spec.js
index 39c581e2796..6a1791509fd 100644
--- a/spec/frontend/diffs/components/inline_diff_view_spec.js
+++ b/spec/frontend/diffs/components/inline_diff_view_spec.js
@@ -1,54 +1,57 @@
-import Vue from 'vue';
import '~/behaviors/markdown/render_gfm';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { mount } from '@vue/test-utils';
+import { getByText } from '@testing-library/dom';
import { createStore } from '~/mr_notes/stores';
import InlineDiffView from '~/diffs/components/inline_diff_view.vue';
+import { mapInline } from '~/diffs/components/diff_row_utils';
import diffFileMockData from '../mock_data/diff_file';
import discussionsMockData from '../mock_data/diff_discussions';
describe('InlineDiffView', () => {
- let component;
+ let wrapper;
const getDiffFileMock = () => ({ ...diffFileMockData });
const getDiscussionsMockData = () => [{ ...discussionsMockData }];
const notesLength = getDiscussionsMockData()[0].notes.length;
- beforeEach(done => {
- const diffFile = getDiffFileMock();
+ const setup = (diffFile, diffLines) => {
+ const mockDiffContent = {
+ diffFile,
+ shouldRenderDraftRow: jest.fn(),
+ };
const store = createStore();
store.dispatch('diffs/setInlineDiffViewType');
- component = createComponentWithStore(Vue.extend(InlineDiffView), store, {
- diffFile,
- diffLines: diffFile.highlighted_diff_lines,
- }).$mount();
-
- Vue.nextTick(done);
- });
+ wrapper = mount(InlineDiffView, {
+ store,
+ propsData: {
+ diffFile,
+ diffLines: diffLines.map(mapInline(mockDiffContent)),
+ },
+ });
+ };
describe('template', () => {
it('should have rendered diff lines', () => {
- const el = component.$el;
+ const diffFile = getDiffFileMock();
+ setup(diffFile, diffFile.highlighted_diff_lines);
- 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);
+ expect(wrapper.findAll('tr.line_holder').length).toEqual(8);
+ expect(wrapper.findAll('tr.line_holder.new').length).toEqual(4);
+ expect(wrapper.findAll('tr.line_expansion.match').length).toEqual(1);
+ getByText(wrapper.element, /Bad dates/i);
});
- it('should render discussions', done => {
- const el = component.$el;
- component.diffLines[1].discussions = getDiscussionsMockData();
- component.diffLines[1].discussionsExpanded = true;
-
- Vue.nextTick(() => {
- expect(el.querySelectorAll('.notes_holder').length).toEqual(1);
- expect(el.querySelectorAll('.notes_holder .note').length).toEqual(notesLength + 1);
- expect(el.innerText.indexOf('comment 5')).toBeGreaterThan(-1);
- component.$store.dispatch('setInitialNotes', []);
+ it('should render discussions', () => {
+ const diffFile = getDiffFileMock();
+ diffFile.highlighted_diff_lines[1].discussions = getDiscussionsMockData();
+ diffFile.highlighted_diff_lines[1].discussionsExpanded = true;
+ setup(diffFile, diffFile.highlighted_diff_lines);
- done();
- });
+ expect(wrapper.findAll('.notes_holder').length).toEqual(1);
+ expect(wrapper.findAll('.notes_holder .note').length).toEqual(notesLength + 1);
+ getByText(wrapper.element, 'comment 5');
+ wrapper.vm.$store.dispatch('setInitialNotes', []);
});
});
});
diff --git a/spec/frontend/diffs/components/parallel_diff_expansion_row_spec.js b/spec/frontend/diffs/components/parallel_diff_expansion_row_spec.js
deleted file mode 100644
index 38112445e8d..00000000000
--- a/spec/frontend/diffs/components/parallel_diff_expansion_row_spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import Vue from 'vue';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/mr_notes/stores';
-import ParallelDiffExpansionRow from '~/diffs/components/parallel_diff_expansion_row.vue';
-import diffFileMockData from '../mock_data/diff_file';
-
-describe('ParallelDiffExpansionRow', () => {
- const matchLine = diffFileMockData.highlighted_diff_lines[5];
-
- const createComponent = (options = {}) => {
- const cmp = Vue.extend(ParallelDiffExpansionRow);
- const defaults = {
- fileHash: diffFileMockData.file_hash,
- contextLinesPath: 'contextLinesPath',
- line: matchLine,
- isTop: false,
- isBottom: false,
- };
- const props = { ...defaults, ...options };
-
- return createComponentWithStore(cmp, createStore(), props).$mount();
- };
-
- describe('template', () => {
- it('should render expansion row for match lines', () => {
- const vm = createComponent();
-
- expect(vm.$el.classList.contains('line_expansion')).toBe(true);
- });
- });
-});
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 13031bd8b66..57eff177261 100644
--- a/spec/frontend/diffs/components/parallel_diff_table_row_spec.js
+++ b/spec/frontend/diffs/components/parallel_diff_table_row_spec.js
@@ -3,11 +3,22 @@ import { shallowMount } from '@vue/test-utils';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import { createStore } from '~/mr_notes/stores';
import ParallelDiffTableRow from '~/diffs/components/parallel_diff_table_row.vue';
+import { mapParallel } from '~/diffs/components/diff_row_utils';
import diffFileMockData from '../mock_data/diff_file';
import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue';
import discussionsMockData from '../mock_data/diff_discussions';
describe('ParallelDiffTableRow', () => {
+ const mockDiffContent = {
+ diffFile: diffFileMockData,
+ shouldRenderDraftRow: jest.fn(),
+ hasParallelDraftLeft: jest.fn(),
+ hasParallelDraftRight: jest.fn(),
+ draftForLine: jest.fn(),
+ };
+
+ const applyMap = mapParallel(mockDiffContent);
+
describe('when one side is empty', () => {
let wrapper;
let vm;
@@ -18,7 +29,7 @@ describe('ParallelDiffTableRow', () => {
wrapper = shallowMount(ParallelDiffTableRow, {
store: createStore(),
propsData: {
- line: thisLine,
+ line: applyMap(thisLine),
fileHash: diffFileMockData.file_hash,
filePath: diffFileMockData.file_path,
contextLinesPath: 'contextLinesPath',
@@ -67,7 +78,7 @@ describe('ParallelDiffTableRow', () => {
beforeEach(() => {
vm = createComponentWithStore(Vue.extend(ParallelDiffTableRow), createStore(), {
- line: thisLine,
+ line: applyMap(thisLine),
fileHash: diffFileMockData.file_hash,
filePath: diffFileMockData.file_path,
contextLinesPath: 'contextLinesPath',
@@ -243,7 +254,10 @@ describe('ParallelDiffTableRow', () => {
${{ ...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 });
+ createComponent({ line: applyMap(line) }, store, {
+ isLeftHover: true,
+ isCommentButtonRendered: true,
+ });
expect(findNoteButton().isVisible()).toBe(expectation);
});
@@ -320,7 +334,7 @@ describe('ParallelDiffTableRow', () => {
Object.assign(thisLine.left, lineProps);
Object.assign(thisLine.right, lineProps);
createComponent({
- line: { ...thisLine },
+ line: applyMap({ ...thisLine }),
});
});
@@ -357,7 +371,7 @@ describe('ParallelDiffTableRow', () => {
beforeEach(() => {
jest.spyOn(store, 'dispatch').mockImplementation();
- line = {
+ line = applyMap({
left: {
line_code: TEST_LINE_CODE,
type: 'new',
@@ -369,7 +383,7 @@ describe('ParallelDiffTableRow', () => {
rich_text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
meta_data: null,
},
- };
+ });
});
describe('with showCommentButton', () => {
@@ -384,7 +398,7 @@ describe('ParallelDiffTableRow', () => {
it('does notrender if line has no discussions', () => {
line.left.discussions = [];
- createComponent({ line });
+ createComponent({ line: applyMap(line) });
expect(findAvatars().exists()).toEqual(false);
});
diff --git a/spec/frontend/diffs/components/tree_list_spec.js b/spec/frontend/diffs/components/tree_list_spec.js
index cc177a81d88..c89403e4869 100644
--- a/spec/frontend/diffs/components/tree_list_spec.js
+++ b/spec/frontend/diffs/components/tree_list_spec.js
@@ -91,12 +91,12 @@ describe('Diffs tree list component', () => {
expect(
getFileRows()
.at(0)
- .text(),
+ .html(),
).toContain('index.js');
expect(
getFileRows()
.at(1)
- .text(),
+ .html(),
).toContain('app');
});
@@ -138,7 +138,7 @@ describe('Diffs tree list component', () => {
wrapper.vm.$store.state.diffs.renderTreeList = false;
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.file-row').text()).toContain('index.js');
+ expect(wrapper.find('.file-row').html()).toContain('index.js');
});
});
});
diff --git a/spec/frontend/diffs/mock_data/diff_file.js b/spec/frontend/diffs/mock_data/diff_file.js
index d3886819a91..cef776c885a 100644
--- a/spec/frontend/diffs/mock_data/diff_file.js
+++ b/spec/frontend/diffs/mock_data/diff_file.js
@@ -27,6 +27,7 @@ export default {
name: 'text',
error: null,
automaticallyCollapsed: false,
+ manuallyCollapsed: null,
},
added_lines: 2,
removed_lines: 0,
diff --git a/spec/frontend/diffs/mock_data/diff_file_unreadable.js b/spec/frontend/diffs/mock_data/diff_file_unreadable.js
index f6cdca9950a..2a5d694e3b8 100644
--- a/spec/frontend/diffs/mock_data/diff_file_unreadable.js
+++ b/spec/frontend/diffs/mock_data/diff_file_unreadable.js
@@ -26,6 +26,7 @@ export default {
name: 'text',
error: null,
automaticallyCollapsed: false,
+ manuallyCollapsed: null,
},
added_lines: 0,
removed_lines: 0,
diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js
index c3e4ee9c531..0af5ddd9764 100644
--- a/spec/frontend/diffs/store/actions_spec.js
+++ b/spec/frontend/diffs/store/actions_spec.js
@@ -27,7 +27,6 @@ import {
scrollToLineIfNeededInline,
scrollToLineIfNeededParallel,
loadCollapsedDiff,
- expandAllFiles,
toggleFileDiscussions,
saveDiffDiscussion,
setHighlightedRow,
@@ -42,7 +41,7 @@ import {
fetchFullDiff,
toggleFullDiff,
switchToFullDiffFromRenamedFile,
- setFileCollapsed,
+ setFileCollapsedByUser,
setExpandedDiffLines,
setSuggestPopoverDismissed,
changeCurrentCommit,
@@ -658,23 +657,6 @@ describe('DiffsStoreActions', () => {
});
});
- describe('expandAllFiles', () => {
- it('should change the collapsed prop from the diffFiles', done => {
- testAction(
- expandAllFiles,
- null,
- {},
- [
- {
- type: types.EXPAND_ALL_FILES,
- },
- ],
- [],
- done,
- );
- });
- });
-
describe('toggleFileDiscussions', () => {
it('should dispatch collapseDiscussion when all discussions are expanded', () => {
const getters = {
@@ -1167,7 +1149,11 @@ describe('DiffsStoreActions', () => {
file_hash: 'testhash',
alternate_viewer: { name: updatedViewerName },
};
- const updatedViewer = { name: updatedViewerName, automaticallyCollapsed: false };
+ const updatedViewer = {
+ name: updatedViewerName,
+ automaticallyCollapsed: false,
+ manuallyCollapsed: false,
+ };
const testData = [{ rich_text: 'test' }, { rich_text: 'file2' }];
let renamedFile;
let mock;
@@ -1216,13 +1202,18 @@ describe('DiffsStoreActions', () => {
});
});
- describe('setFileCollapsed', () => {
+ describe('setFileUserCollapsed', () => {
it('commits SET_FILE_COLLAPSED', done => {
testAction(
- setFileCollapsed,
+ setFileCollapsedByUser,
{ filePath: 'test', collapsed: true },
null,
- [{ type: types.SET_FILE_COLLAPSED, payload: { filePath: 'test', collapsed: true } }],
+ [
+ {
+ type: types.SET_FILE_COLLAPSED,
+ payload: { filePath: 'test', collapsed: true, trigger: 'manual' },
+ },
+ ],
[],
done,
);
diff --git a/spec/frontend/diffs/store/getters_spec.js b/spec/frontend/diffs/store/getters_spec.js
index 0083f1d8b44..7e936c561fc 100644
--- a/spec/frontend/diffs/store/getters_spec.js
+++ b/spec/frontend/diffs/store/getters_spec.js
@@ -49,23 +49,53 @@ describe('Diffs Module Getters', () => {
});
});
- describe('hasCollapsedFile', () => {
- it('returns true when all files are collapsed', () => {
- localState.diffFiles = [
- { viewer: { automaticallyCollapsed: true } },
- { viewer: { automaticallyCollapsed: true } },
- ];
+ describe('whichCollapsedTypes', () => {
+ const autoCollapsedFile = { viewer: { automaticallyCollapsed: true, manuallyCollapsed: null } };
+ const manuallyCollapsedFile = {
+ viewer: { automaticallyCollapsed: false, manuallyCollapsed: true },
+ };
+ const openFile = { viewer: { automaticallyCollapsed: false, manuallyCollapsed: false } };
+
+ it.each`
+ description | value | files
+ ${'all files are automatically collapsed'} | ${true} | ${[{ ...autoCollapsedFile }, { ...autoCollapsedFile }]}
+ ${'all files are manually collapsed'} | ${true} | ${[{ ...manuallyCollapsedFile }, { ...manuallyCollapsedFile }]}
+ ${'no files are collapsed in any way'} | ${false} | ${[{ ...openFile }, { ...openFile }]}
+ ${'some files are collapsed in either way'} | ${true} | ${[{ ...manuallyCollapsedFile }, { ...autoCollapsedFile }, { ...openFile }]}
+ `('`any` is $value when $description', ({ value, files }) => {
+ localState.diffFiles = files;
+
+ const getterResult = getters.whichCollapsedTypes(localState);
+
+ expect(getterResult.any).toEqual(value);
+ });
+
+ it.each`
+ description | value | files
+ ${'all files are automatically collapsed'} | ${true} | ${[{ ...autoCollapsedFile }, { ...autoCollapsedFile }]}
+ ${'all files are manually collapsed'} | ${false} | ${[{ ...manuallyCollapsedFile }, { ...manuallyCollapsedFile }]}
+ ${'no files are collapsed in any way'} | ${false} | ${[{ ...openFile }, { ...openFile }]}
+ ${'some files are collapsed in either way'} | ${true} | ${[{ ...manuallyCollapsedFile }, { ...autoCollapsedFile }, { ...openFile }]}
+ `('`automatic` is $value when $description', ({ value, files }) => {
+ localState.diffFiles = files;
- expect(getters.hasCollapsedFile(localState)).toEqual(true);
+ const getterResult = getters.whichCollapsedTypes(localState);
+
+ expect(getterResult.automatic).toEqual(value);
});
- it('returns true when at least one file is collapsed', () => {
- localState.diffFiles = [
- { viewer: { automaticallyCollapsed: false } },
- { viewer: { automaticallyCollapsed: true } },
- ];
+ it.each`
+ description | value | files
+ ${'all files are automatically collapsed'} | ${false} | ${[{ ...autoCollapsedFile }, { ...autoCollapsedFile }]}
+ ${'all files are manually collapsed'} | ${true} | ${[{ ...manuallyCollapsedFile }, { ...manuallyCollapsedFile }]}
+ ${'no files are collapsed in any way'} | ${false} | ${[{ ...openFile }, { ...openFile }]}
+ ${'some files are collapsed in either way'} | ${true} | ${[{ ...manuallyCollapsedFile }, { ...autoCollapsedFile }, { ...openFile }]}
+ `('`manual` is $value when $description', ({ value, files }) => {
+ localState.diffFiles = files;
+
+ const getterResult = getters.whichCollapsedTypes(localState);
- expect(getters.hasCollapsedFile(localState)).toEqual(true);
+ expect(getterResult.manual).toEqual(value);
});
});
diff --git a/spec/frontend/diffs/store/mutations_spec.js b/spec/frontend/diffs/store/mutations_spec.js
index a84ad63c695..c0645faf89e 100644
--- a/spec/frontend/diffs/store/mutations_spec.js
+++ b/spec/frontend/diffs/store/mutations_spec.js
@@ -126,21 +126,6 @@ describe('DiffsStoreMutations', () => {
});
});
- describe('EXPAND_ALL_FILES', () => {
- it('should change the collapsed prop from diffFiles', () => {
- const diffFile = {
- viewer: {
- automaticallyCollapsed: true,
- },
- };
- const state = { expandAllFiles: true, diffFiles: [diffFile] };
-
- mutations[types.EXPAND_ALL_FILES](state);
-
- expect(state.diffFiles[0].viewer.automaticallyCollapsed).toEqual(false);
- });
- });
-
describe('ADD_CONTEXT_LINES', () => {
it('should call utils.addContextLines with proper params', () => {
const options = {
diff --git a/spec/frontend/diffs/store/utils_spec.js b/spec/frontend/diffs/store/utils_spec.js
index 39a482c85ae..866be0abd22 100644
--- a/spec/frontend/diffs/store/utils_spec.js
+++ b/spec/frontend/diffs/store/utils_spec.js
@@ -1221,5 +1221,26 @@ describe('DiffsStoreUtils', () => {
file.parallel_diff_lines,
);
});
+
+ /**
+ * What's going on here?
+ *
+ * The inline version of parallelizeDiffLines simply keeps the difflines
+ * in the same order they are received as opposed to shuffling them
+ * to be "side by side".
+ *
+ * This keeps the underlying data structure the same which simplifies
+ * the components, but keeps the changes grouped together as users
+ * expect when viewing changes inline.
+ */
+ it('converts inline diff lines to inline diff lines with a parallel structure', () => {
+ const file = getDiffFileMock();
+ const files = utils.parallelizeDiffLines(file.highlighted_diff_lines, true);
+
+ expect(files[5].left).toEqual(file.parallel_diff_lines[5].left);
+ expect(files[5].right).toBeNull();
+ expect(files[6].left).toBeNull();
+ expect(files[6].right).toEqual(file.parallel_diff_lines[5].right);
+ });
});
});
diff --git a/spec/frontend/editor/editor_lite_spec.js b/spec/frontend/editor/editor_lite_spec.js
index bc17435c6d4..2968984df01 100644
--- a/spec/frontend/editor/editor_lite_spec.js
+++ b/spec/frontend/editor/editor_lite_spec.js
@@ -64,7 +64,7 @@ describe('Base editor', () => {
});
it('creates model to be supplied to Monaco editor', () => {
- editor.createInstance({ el: editorEl, blobPath, blobContent });
+ editor.createInstance({ el: editorEl, blobPath, blobContent, blobGlobalId: '' });
expect(modelSpy).toHaveBeenCalledWith(blobContent, undefined, createUri(blobPath));
expect(setModel).toHaveBeenCalledWith(fakeModel);
diff --git a/spec/frontend/environments/environment_delete_spec.js b/spec/frontend/environments/environment_delete_spec.js
index b4ecb24cbac..a8c288a3bd8 100644
--- a/spec/frontend/environments/environment_delete_spec.js
+++ b/spec/frontend/environments/environment_delete_spec.js
@@ -1,11 +1,9 @@
-import $ from 'jquery';
+import { GlButton } from '@gitlab/ui';
+
import { shallowMount } from '@vue/test-utils';
import DeleteComponent from '~/environments/components/environment_delete.vue';
-import LoadingButton from '~/vue_shared/components/loading_button.vue';
import eventHub from '~/environments/event_hub';
-$.fn.tooltip = () => {};
-
describe('External URL Component', () => {
let wrapper;
@@ -17,7 +15,7 @@ describe('External URL Component', () => {
});
};
- const findButton = () => wrapper.find(LoadingButton);
+ const findButton = () => wrapper.find(GlButton);
beforeEach(() => {
jest.spyOn(window, 'confirm');
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 31f355ce6f1..a77bf39cb54 100644
--- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js
+++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
@@ -1,12 +1,6 @@
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
-import {
- GlEmptyState,
- GlLoadingIcon,
- GlFormInput,
- GlPagination,
- GlDeprecatedDropdown,
-} from '@gitlab/ui';
+import { GlEmptyState, GlLoadingIcon, GlFormInput, GlPagination, GlDropdown } from '@gitlab/ui';
import stubChildren from 'helpers/stub_children';
import ErrorTrackingList from '~/error_tracking/components/error_tracking_list.vue';
import ErrorTrackingActions from '~/error_tracking/components/error_tracking_actions.vue';
@@ -24,19 +18,19 @@ describe('ErrorTrackingList', () => {
const findErrorListTable = () => wrapper.find('table');
const findErrorListRows = () => wrapper.findAll('tbody tr');
- const dropdownsArray = () => wrapper.findAll(GlDeprecatedDropdown);
+ const dropdownsArray = () => wrapper.findAll(GlDropdown);
const findRecentSearchesDropdown = () =>
dropdownsArray()
.at(0)
- .find(GlDeprecatedDropdown);
+ .find(GlDropdown);
const findStatusFilterDropdown = () =>
dropdownsArray()
.at(1)
- .find(GlDeprecatedDropdown);
+ .find(GlDropdown);
const findSortDropdown = () =>
dropdownsArray()
.at(2)
- .find(GlDeprecatedDropdown);
+ .find(GlDropdown);
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findPagination = () => wrapper.find(GlPagination);
const findErrorActions = () => wrapper.find(ErrorTrackingActions);
@@ -134,8 +128,8 @@ describe('ErrorTrackingList', () => {
mountComponent({
stubs: {
GlTable: false,
- GlDeprecatedDropdown: false,
- GlDeprecatedDropdownItem: false,
+ GlDropdown: false,
+ GlDropdownItem: false,
GlLink: false,
},
});
@@ -205,8 +199,8 @@ describe('ErrorTrackingList', () => {
mountComponent({
stubs: {
GlTable: false,
- GlDeprecatedDropdown: false,
- GlDeprecatedDropdownItem: false,
+ GlDropdown: false,
+ GlDropdownItem: false,
},
});
});
@@ -325,8 +319,8 @@ describe('ErrorTrackingList', () => {
beforeEach(() => {
mountComponent({
stubs: {
- GlDeprecatedDropdown: false,
- GlDeprecatedDropdownItem: false,
+ GlDropdown: false,
+ GlDropdownItem: false,
},
});
});
diff --git a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
index 023a3e26781..d924f895da8 100644
--- a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
+++ b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
@@ -1,7 +1,7 @@
import { pick, clone } from 'lodash';
import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlDeprecatedDropdown, GlDeprecatedDropdownItem } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import ProjectDropdown from '~/error_tracking_settings/components/project_dropdown.vue';
import { defaultProps, projectList, staleProject } from '../mock';
@@ -43,7 +43,7 @@ describe('error tracking settings project dropdown', () => {
describe('empty project list', () => {
it('renders the dropdown', () => {
expect(wrapper.find('#project-dropdown').exists()).toBeTruthy();
- expect(wrapper.find(GlDeprecatedDropdown).exists()).toBeTruthy();
+ expect(wrapper.find(GlDropdown).exists()).toBeTruthy();
});
it('shows helper text', () => {
@@ -58,8 +58,8 @@ describe('error tracking settings project dropdown', () => {
});
it('does not contain any dropdown items', () => {
- expect(wrapper.find(GlDeprecatedDropdownItem).exists()).toBeFalsy();
- expect(wrapper.find(GlDeprecatedDropdown).props('text')).toBe('No projects available');
+ expect(wrapper.find(GlDropdownItem).exists()).toBeFalsy();
+ expect(wrapper.find(GlDropdown).props('text')).toBe('No projects available');
});
});
@@ -72,12 +72,12 @@ describe('error tracking settings project dropdown', () => {
it('renders the dropdown', () => {
expect(wrapper.find('#project-dropdown').exists()).toBeTruthy();
- expect(wrapper.find(GlDeprecatedDropdown).exists()).toBeTruthy();
+ expect(wrapper.find(GlDropdown).exists()).toBeTruthy();
});
it('contains a number of dropdown items', () => {
- expect(wrapper.find(GlDeprecatedDropdownItem).exists()).toBeTruthy();
- expect(wrapper.findAll(GlDeprecatedDropdownItem).length).toBe(2);
+ expect(wrapper.find(GlDropdownItem).exists()).toBeTruthy();
+ expect(wrapper.findAll(GlDropdownItem).length).toBe(2);
});
});
diff --git a/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js b/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js
index 0e364c47f8d..67f4bee766b 100644
--- a/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js
+++ b/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js
@@ -99,13 +99,13 @@ describe('Configure Feature Flags Modal', () => {
});
it('should display the api URL in an input box', () => {
- const input = wrapper.find('#api_url');
- expect(input.element.value).toBe('/api/url');
+ const input = wrapper.find('#api-url');
+ expect(input.attributes('value')).toBe('/api/url');
});
it('should display the instance ID in an input box', () => {
const input = wrapper.find('#instance_id');
- expect(input.element.value).toBe('instance-id-token');
+ expect(input.attributes('value')).toBe('instance-id-token');
});
});
@@ -129,7 +129,7 @@ describe('Configure Feature Flags Modal', () => {
expect(findPrimaryAction()).toBe(null);
});
- it('shold not display regenerating instance ID', async () => {
+ it('should not display regenerating instance ID', async () => {
expect(findDangerCallout().exists()).toBe(false);
});
diff --git a/spec/frontend/feature_flags/components/form_spec.js b/spec/frontend/feature_flags/components/form_spec.js
index 33c7eeb54b7..2c2a726d26f 100644
--- a/spec/frontend/feature_flags/components/form_spec.js
+++ b/spec/frontend/feature_flags/components/form_spec.js
@@ -442,12 +442,6 @@ describe('feature flag form', () => {
});
});
- it('should request the user lists on mount', () => {
- return wrapper.vm.$nextTick(() => {
- expect(Api.fetchFeatureFlagUserLists).toHaveBeenCalledWith('1');
- });
- });
-
it('should show the strategy component', () => {
const strategy = wrapper.find(Strategy);
expect(strategy.exists()).toBe(true);
@@ -485,9 +479,5 @@ describe('feature flag form', () => {
expect(wrapper.find(Strategy).props('strategy')).not.toEqual(strategy);
});
});
-
- it('should provide the user lists to the strategy', () => {
- expect(wrapper.find(Strategy).props('userLists')).toEqual([userList]);
- });
});
});
diff --git a/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js b/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js
index f3f70a325d0..725f53d4409 100644
--- a/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js
@@ -100,7 +100,7 @@ describe('feature_flags/components/strategies/flexible_rollout.vue', () => {
});
});
- describe('with percentage that is not a whole number', () => {
+ describe('with percentage that is not an integer number', () => {
beforeEach(() => {
wrapper = factory({ strategy: { parameters: { rollout: '3.14' } } });
});
diff --git a/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js b/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js
index 014c6dd98b9..b34fe7779e3 100644
--- a/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js
@@ -1,51 +1,103 @@
-import { mount } from '@vue/test-utils';
-import { GlFormSelect } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
+import Api from '~/api';
+import createStore from '~/feature_flags/store/new';
import GitlabUserList from '~/feature_flags/components/strategies/gitlab_user_list.vue';
import { userListStrategy, userList } from '../../mock_data';
+jest.mock('~/api');
+
const DEFAULT_PROPS = {
strategy: userListStrategy,
- userLists: [userList],
};
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
describe('~/feature_flags/components/strategies/gitlab_user_list.vue', () => {
let wrapper;
const factory = (props = {}) =>
- mount(GitlabUserList, { propsData: { ...DEFAULT_PROPS, ...props } });
+ mount(GitlabUserList, {
+ localVue,
+ store: createStore({ projectId: '1' }),
+ propsData: { ...DEFAULT_PROPS, ...props },
+ });
+
+ const findDropdown = () => wrapper.find(GlDropdown);
describe('with user lists', () => {
+ const findDropdownItem = () => wrapper.find(GlDropdownItem);
+
beforeEach(() => {
+ Api.searchFeatureFlagUserLists.mockResolvedValue({ data: [userList] });
wrapper = factory();
});
it('should show the input for userListId with the correct value', () => {
- const inputWrapper = wrapper.find(GlFormSelect);
- expect(inputWrapper.exists()).toBe(true);
- expect(inputWrapper.element.value).toBe('2');
+ const dropdownWrapper = findDropdown();
+ expect(dropdownWrapper.exists()).toBe(true);
+ expect(dropdownWrapper.props('text')).toBe(userList.name);
+ });
+
+ it('should show a check for the selected list', () => {
+ const itemWrapper = findDropdownItem();
+ expect(itemWrapper.props('isChecked')).toBe(true);
+ });
+
+ it('should display the name of the list in the drop;down', () => {
+ const itemWrapper = findDropdownItem();
+ expect(itemWrapper.text()).toBe(userList.name);
});
it('should emit a change event when altering the userListId', () => {
- const inputWrapper = wrapper.find(GitlabUserList);
- inputWrapper.vm.$emit('change', {
- userListId: '3',
- });
+ const inputWrapper = findDropdownItem();
+ inputWrapper.vm.$emit('click');
expect(wrapper.emitted('change')).toEqual([
[
{
- userListId: '3',
+ userList,
},
],
]);
});
+
+ it('should search when the filter changes', async () => {
+ let r;
+ Api.searchFeatureFlagUserLists.mockReturnValue(
+ new Promise(resolve => {
+ r = resolve;
+ }),
+ );
+ const searchWrapper = wrapper.find(GlSearchBoxByType);
+ searchWrapper.vm.$emit('input', 'new');
+ await wrapper.vm.$nextTick();
+ const loadingIcon = wrapper.find(GlLoadingIcon);
+
+ expect(loadingIcon.exists()).toBe(true);
+ expect(Api.searchFeatureFlagUserLists).toHaveBeenCalledWith('1', 'new');
+
+ r({ data: [userList] });
+
+ await wrapper.vm.$nextTick();
+
+ expect(loadingIcon.exists()).toBe(false);
+ });
});
+
describe('without user lists', () => {
beforeEach(() => {
- wrapper = factory({ userLists: [] });
+ Api.searchFeatureFlagUserLists.mockResolvedValue({ data: [] });
+ wrapper = factory({ strategy: { ...userListStrategy, userList: null } });
});
it('should display a message that there are no user lists', () => {
expect(wrapper.text()).toContain('There are no configured user lists');
});
+
+ it('should dispaly a message that no list has been selected', () => {
+ expect(findDropdown().text()).toContain('No user list selected');
+ });
});
});
diff --git a/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js b/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js
index de0b439f1c5..696b3b2e4c9 100644
--- a/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js
@@ -63,7 +63,7 @@ describe('~/feature_flags/components/strategies/percent_rollout.vue', () => {
});
});
- describe('with percentage that is not a whole number', () => {
+ describe('with percentage that is not an integer number', () => {
beforeEach(() => {
wrapper = factory({ strategy: { parameters: { percentage: '3.14' } } });
diff --git a/spec/frontend/feature_flags/components/strategy_parameters_spec.js b/spec/frontend/feature_flags/components/strategy_parameters_spec.js
index 314fb0f21f4..a024384e623 100644
--- a/spec/frontend/feature_flags/components/strategy_parameters_spec.js
+++ b/spec/frontend/feature_flags/components/strategy_parameters_spec.js
@@ -11,11 +11,10 @@ import GitlabUserList from '~/feature_flags/components/strategies/gitlab_user_li
import PercentRollout from '~/feature_flags/components/strategies/percent_rollout.vue';
import UsersWithId from '~/feature_flags/components/strategies/users_with_id.vue';
import StrategyParameters from '~/feature_flags/components/strategy_parameters.vue';
-import { allUsersStrategy, userList } from '../mock_data';
+import { allUsersStrategy } from '../mock_data';
const DEFAULT_PROPS = {
strategy: allUsersStrategy,
- userLists: [userList],
};
describe('~/feature_flags/components/strategy_parameters.vue', () => {
@@ -71,13 +70,14 @@ describe('~/feature_flags/components/strategy_parameters.vue', () => {
describe('pass through props', () => {
it('should pass through any extra props that might be needed', () => {
+ const strategy = {
+ name: ROLLOUT_STRATEGY_USER_ID,
+ };
wrapper = factory({
- strategy: {
- name: ROLLOUT_STRATEGY_GITLAB_USER_LIST,
- },
+ strategy,
});
- expect(wrapper.find(GitlabUserList).props('userLists')).toEqual([userList]);
+ expect(wrapper.find(UsersWithId).props('strategy')).toEqual(strategy);
});
});
});
diff --git a/spec/frontend/feature_flags/components/strategy_spec.js b/spec/frontend/feature_flags/components/strategy_spec.js
index 7d6700ba184..67cf70c37e2 100644
--- a/spec/frontend/feature_flags/components/strategy_spec.js
+++ b/spec/frontend/feature_flags/components/strategy_spec.js
@@ -1,6 +1,9 @@
-import { mount } from '@vue/test-utils';
+import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { last } from 'lodash';
import { GlAlert, GlFormSelect, GlLink, GlToken, GlButton } from '@gitlab/ui';
+import Api from '~/api';
+import createStore from '~/feature_flags/store/new';
import {
PERCENT_ROLLOUT_GROUP_ID,
ROLLOUT_STRATEGY_ALL_USERS,
@@ -15,12 +18,17 @@ import StrategyParameters from '~/feature_flags/components/strategy_parameters.v
import { userList } from '../mock_data';
+jest.mock('~/api');
+
const provide = {
strategyTypeDocsPagePath: 'link-to-strategy-docs',
environmentsScopeDocsPath: 'link-scope-docs',
environmentsEndpoint: '',
};
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
describe('Feature flags strategy', () => {
let wrapper;
@@ -32,7 +40,6 @@ describe('Feature flags strategy', () => {
propsData: {
strategy: {},
index: 0,
- userLists: [userList],
},
provide,
},
@@ -41,9 +48,13 @@ describe('Feature flags strategy', () => {
wrapper.destroy();
wrapper = null;
}
- wrapper = mount(Strategy, opts);
+ wrapper = mount(Strategy, { localVue, store: createStore({ projectId: '1' }), ...opts });
};
+ beforeEach(() => {
+ Api.searchFeatureFlagUserLists.mockResolvedValue({ data: [userList] });
+ });
+
afterEach(() => {
if (wrapper) {
wrapper.destroy();
diff --git a/spec/frontend/feature_flags/mock_data.js b/spec/frontend/feature_flags/mock_data.js
index ed06ea059a7..11a91e5b2a8 100644
--- a/spec/frontend/feature_flags/mock_data.js
+++ b/spec/frontend/feature_flags/mock_data.js
@@ -127,7 +127,7 @@ export const userListStrategy = {
name: ROLLOUT_STRATEGY_GITLAB_USER_LIST,
parameters: {},
scopes: [],
- userListId: userList.id,
+ userList,
};
export const percentRolloutStrategy = {
diff --git a/spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js b/spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js
new file mode 100644
index 00000000000..aba578cca59
--- /dev/null
+++ b/spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js
@@ -0,0 +1,60 @@
+import testAction from 'helpers/vuex_action_helper';
+import Api from '~/api';
+import createState from '~/feature_flags/store/gitlab_user_list/state';
+import { fetchUserLists, setFilter } from '~/feature_flags/store/gitlab_user_list/actions';
+import * as types from '~/feature_flags/store/gitlab_user_list/mutation_types';
+import { userList } from '../../mock_data';
+
+jest.mock('~/api');
+
+describe('~/feature_flags/store/gitlab_user_list/actions', () => {
+ let mockedState;
+
+ beforeEach(() => {
+ mockedState = createState({ projectId: '1' });
+ mockedState.filter = 'test';
+ });
+
+ describe('fetchUserLists', () => {
+ it('should commit FETCH_USER_LISTS and RECEIEVE_USER_LISTS_SUCCESS on success', () => {
+ Api.searchFeatureFlagUserLists.mockResolvedValue({ data: [userList] });
+ return testAction(
+ fetchUserLists,
+ undefined,
+ mockedState,
+ [
+ { type: types.FETCH_USER_LISTS },
+ { type: types.RECEIVE_USER_LISTS_SUCCESS, payload: [userList] },
+ ],
+ [],
+ () => expect(Api.searchFeatureFlagUserLists).toHaveBeenCalledWith('1', 'test'),
+ );
+ });
+
+ it('should commit FETCH_USER_LISTS and RECEIEVE_USER_LISTS_ERROR on success', () => {
+ Api.searchFeatureFlagUserLists.mockRejectedValue({ message: 'error' });
+ return testAction(
+ fetchUserLists,
+ undefined,
+ mockedState,
+ [
+ { type: types.FETCH_USER_LISTS },
+ { type: types.RECEIVE_USER_LISTS_ERROR, payload: ['error'] },
+ ],
+ [],
+ () => expect(Api.searchFeatureFlagUserLists).toHaveBeenCalledWith('1', 'test'),
+ );
+ });
+ });
+
+ describe('setFilter', () => {
+ it('commits SET_FILTER and fetches new user lists', () =>
+ testAction(
+ setFilter,
+ 'filter',
+ mockedState,
+ [{ type: types.SET_FILTER, payload: 'filter' }],
+ [{ type: 'fetchUserLists' }],
+ ));
+ });
+});
diff --git a/spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js b/spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js
new file mode 100644
index 00000000000..e267cd59f50
--- /dev/null
+++ b/spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js
@@ -0,0 +1,69 @@
+import {
+ userListOptions,
+ hasUserLists,
+ isLoading,
+ hasError,
+} from '~/feature_flags/store/gitlab_user_list/getters';
+import statuses from '~/feature_flags/store/gitlab_user_list/status';
+import createState from '~/feature_flags/store/gitlab_user_list/state';
+import { userList } from '../../mock_data';
+
+describe('~/feature_flags/store/gitlab_user_list/getters', () => {
+ let mockedState;
+
+ beforeEach(() => {
+ mockedState = createState({ projectId: '8' });
+ mockedState.userLists = [userList];
+ });
+
+ describe('userListOption', () => {
+ it('should return user lists in a way usable by a dropdown', () => {
+ expect(userListOptions(mockedState)).toEqual([{ value: userList.id, text: userList.name }]);
+ });
+
+ it('should return an empty array if there are no lists', () => {
+ mockedState.userLists = [];
+ expect(userListOptions(mockedState)).toEqual([]);
+ });
+ });
+
+ describe('hasUserLists', () => {
+ it.each`
+ userLists | status | result
+ ${[userList]} | ${statuses.IDLE} | ${true}
+ ${[]} | ${statuses.IDLE} | ${false}
+ ${[]} | ${statuses.START} | ${true}
+ `(
+ 'should return $result if there are $userLists.length user lists and the status is $status',
+ ({ userLists, status, result }) => {
+ mockedState.userLists = userLists;
+ mockedState.status = status;
+ expect(hasUserLists(mockedState)).toBe(result);
+ },
+ );
+ });
+
+ describe('isLoading', () => {
+ it.each`
+ status | result
+ ${statuses.LOADING} | ${true}
+ ${statuses.ERROR} | ${false}
+ ${statuses.IDLE} | ${false}
+ `('should return $result if the status is "$status"', ({ status, result }) => {
+ mockedState.status = status;
+ expect(isLoading(mockedState)).toBe(result);
+ });
+ });
+
+ describe('hasError', () => {
+ it.each`
+ status | result
+ ${statuses.LOADING} | ${false}
+ ${statuses.ERROR} | ${true}
+ ${statuses.IDLE} | ${false}
+ `('should return $result if the status is "$status"', ({ status, result }) => {
+ mockedState.status = status;
+ expect(hasError(mockedState)).toBe(result);
+ });
+ });
+});
diff --git a/spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js b/spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js
new file mode 100644
index 00000000000..88d4554a227
--- /dev/null
+++ b/spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js
@@ -0,0 +1,50 @@
+import statuses from '~/feature_flags/store/gitlab_user_list/status';
+import createState from '~/feature_flags/store/gitlab_user_list/state';
+import * as types from '~/feature_flags/store/gitlab_user_list/mutation_types';
+import mutations from '~/feature_flags/store/gitlab_user_list/mutations';
+import { userList } from '../../mock_data';
+
+describe('~/feature_flags/store/gitlab_user_list/mutations', () => {
+ let state;
+
+ beforeEach(() => {
+ state = createState({ projectId: '8' });
+ });
+
+ describe(types.SET_FILTER, () => {
+ it('sets the filter in the state', () => {
+ mutations[types.SET_FILTER](state, 'test');
+ expect(state.filter).toBe('test');
+ });
+ });
+
+ describe(types.FETCH_USER_LISTS, () => {
+ it('sets the status to loading', () => {
+ mutations[types.FETCH_USER_LISTS](state);
+ expect(state.status).toBe(statuses.LOADING);
+ });
+ });
+
+ describe(types.RECEIVE_USER_LISTS_SUCCESS, () => {
+ it('sets the user lists to the ones received', () => {
+ mutations[types.RECEIVE_USER_LISTS_SUCCESS](state, [userList]);
+ expect(state.userLists).toEqual([userList]);
+ });
+
+ it('sets the status to idle', () => {
+ mutations[types.RECEIVE_USER_LISTS_SUCCESS](state, [userList]);
+ expect(state.status).toBe(statuses.IDLE);
+ });
+ });
+ describe(types.RECEIVE_USER_LISTS_ERROR, () => {
+ it('sets the status to error', () => {
+ mutations[types.RECEIVE_USER_LISTS_ERROR](state, 'failure');
+ expect(state.status).toBe(statuses.ERROR);
+ });
+
+ it('sets the error message', () => {
+ mutations[types.RECEIVE_USER_LISTS_ERROR](state, 'failure');
+ expect(state.error).toBe('failure');
+ });
+ });
+});
diff --git a/spec/frontend/filtered_search/filtered_search_manager_spec.js b/spec/frontend/filtered_search/filtered_search_manager_spec.js
index 53c726a6cea..5c37d986ef1 100644
--- a/spec/frontend/filtered_search/filtered_search_manager_spec.js
+++ b/spec/frontend/filtered_search/filtered_search_manager_spec.js
@@ -1,3 +1,5 @@
+import FilteredSearchManager from 'ee_else_ce/filtered_search/filtered_search_manager';
+
import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error';
import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
@@ -5,7 +7,6 @@ import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered
import DropdownUtils from '~/filtered_search/dropdown_utils';
import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dropdown_manager';
-import FilteredSearchManager from '~/filtered_search/filtered_search_manager';
import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
import { BACKSPACE_KEY_CODE, DELETE_KEY_CODE } from '~/lib/utils/keycodes';
import { visitUrl } from '~/lib/utils/url_utility';
diff --git a/spec/frontend/fixtures/freeze_period.rb b/spec/frontend/fixtures/freeze_period.rb
index 7695dbc2e8f..193bd0c3ef2 100644
--- a/spec/frontend/fixtures/freeze_period.rb
+++ b/spec/frontend/fixtures/freeze_period.rb
@@ -17,6 +17,15 @@ RSpec.describe 'Freeze Periods (JavaScript fixtures)' do
remove_repository(project)
end
+ around do |example|
+ freeze_time do
+ # Mock time to sept 19 (intl. talk like a pirate day)
+ Timecop.travel(2020, 9, 19)
+
+ example.run
+ end
+ end
+
describe API::FreezePeriods, '(JavaScript fixtures)', type: :request do
include ApiHelpers
diff --git a/spec/frontend/fixtures/groups.rb b/spec/frontend/fixtures/groups.rb
index 6f0d7aa1f7c..9f0b2c73c93 100644
--- a/spec/frontend/fixtures/groups.rb
+++ b/spec/frontend/fixtures/groups.rb
@@ -15,7 +15,6 @@ RSpec.describe 'Groups (JavaScript fixtures)', type: :controller do
end
before do
- stub_feature_flags(new_variables_ui: false)
group.add_maintainer(admin)
sign_in(admin)
end
@@ -27,12 +26,4 @@ RSpec.describe 'Groups (JavaScript fixtures)', type: :controller do
expect(response).to be_successful
end
end
-
- describe Groups::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do
- it 'groups/ci_cd_settings.html' do
- get :show, params: { group_id: group }
-
- expect(response).to be_successful
- end
- end
end
diff --git a/spec/frontend/fixtures/issues.rb b/spec/frontend/fixtures/issues.rb
index 2c380ba6a96..baea87be45f 100644
--- a/spec/frontend/fixtures/issues.rb
+++ b/spec/frontend/fixtures/issues.rb
@@ -16,6 +16,8 @@ RSpec.describe Projects::IssuesController, '(JavaScript fixtures)', type: :contr
end
before do
+ stub_feature_flags(vue_issue_header: false)
+
sign_in(admin)
end
diff --git a/spec/frontend/fixtures/projects.rb b/spec/frontend/fixtures/projects.rb
index d33909fb98b..d0cedb0ef86 100644
--- a/spec/frontend/fixtures/projects.rb
+++ b/spec/frontend/fixtures/projects.rb
@@ -20,7 +20,6 @@ RSpec.describe 'Projects (JavaScript fixtures)', type: :controller do
end
before do
- stub_feature_flags(new_variables_ui: false)
project.add_maintainer(admin)
sign_in(admin)
allow(SecureRandom).to receive(:hex).and_return('securerandomhex:thereisnospoon')
@@ -58,27 +57,4 @@ RSpec.describe 'Projects (JavaScript fixtures)', type: :controller do
expect(response).to be_successful
end
end
-
- describe Projects::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do
- it 'projects/ci_cd_settings.html' do
- get :show, params: {
- namespace_id: project.namespace.to_param,
- project_id: project
- }
-
- expect(response).to be_successful
- end
-
- it 'projects/ci_cd_settings_with_variables.html' do
- create(:ci_variable, project: project_variable_populated)
- create(:ci_variable, project: project_variable_populated)
-
- get :show, params: {
- namespace_id: project_variable_populated.namespace.to_param,
- project_id: project_variable_populated
- }
-
- expect(response).to be_successful
- end
- end
end
diff --git a/spec/frontend/fixtures/search.rb b/spec/frontend/fixtures/search.rb
index 40f613a9422..7819d0774a7 100644
--- a/spec/frontend/fixtures/search.rb
+++ b/spec/frontend/fixtures/search.rb
@@ -26,8 +26,51 @@ RSpec.describe SearchController, '(JavaScript fixtures)', type: :controller do
context 'search within a project' do
let(:namespace) { create(:namespace, name: 'frontend-fixtures') }
let(:project) { create(:project, :public, :repository, namespace: namespace, path: 'search-project') }
+ let(:blobs) do
+ Kaminari.paginate_array([
+ Gitlab::Search::FoundBlob.new(
+ path: 'CHANGELOG',
+ basename: 'CHANGELOG',
+ ref: 'master',
+ data: "hello\nworld\nfoo\nSend # this is the highligh\nbaz\nboo\nbat",
+ project: project,
+ project_id: project.id,
+ startline: 2),
+ Gitlab::Search::FoundBlob.new(
+ path: 'CONTRIBUTING',
+ basename: 'CONTRIBUTING',
+ ref: 'master',
+ data: "hello\nworld\nfoo\nSend # this is the highligh\nbaz\nboo\nbat",
+ project: project,
+ project_id: project.id,
+ startline: 2),
+ Gitlab::Search::FoundBlob.new(
+ path: 'README',
+ basename: 'README',
+ ref: 'master',
+ data: "foo\nSend # this is the highlight\nbaz\nboo\nbat",
+ project: project,
+ project_id: project.id,
+ startline: 2),
+ Gitlab::Search::FoundBlob.new(
+ path: 'test',
+ basename: 'test',
+ ref: 'master',
+ data: "foo\nSend # this is the highlight\nbaz\nboo\nbat",
+ project: project,
+ project_id: project.id,
+ startline: 2)
+ ],
+ total_count: 4,
+ limit: 4,
+ offset: 0)
+ end
it 'search/blob_search_result.html' do
+ expect_next_instance_of(SearchService) do |search_service|
+ expect(search_service).to receive(:search_objects).and_return(blobs)
+ end
+
get :show, params: {
search: 'Send',
project_id: project.id,
diff --git a/spec/frontend/fixtures/static/signin_tabs.html b/spec/frontend/fixtures/static/signin_tabs.html
index 247a6b03054..7e66ab9394b 100644
--- a/spec/frontend/fixtures/static/signin_tabs.html
+++ b/spec/frontend/fixtures/static/signin_tabs.html
@@ -5,7 +5,4 @@
<li>
<a href="#login-pane">Standard</a>
</li>
-<li>
-<a href="#register-pane">Register</a>
-</li>
</ul>
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js
index 8da4320d993..eb9343847f1 100644
--- a/spec/frontend/gfm_auto_complete_spec.js
+++ b/spec/frontend/gfm_auto_complete_spec.js
@@ -8,15 +8,226 @@ import GfmAutoComplete, { membersBeforeSave } from 'ee_else_ce/gfm_auto_complete
import { TEST_HOST } from 'helpers/test_constants';
import { getJSONFixture } from 'helpers/fixtures';
+import waitForPromises from 'jest/helpers/wait_for_promises';
+
+import MockAdapter from 'axios-mock-adapter';
+import AjaxCache from '~/lib/utils/ajax_cache';
+import axios from '~/lib/utils/axios_utils';
+
const labelsFixture = getJSONFixture('autocomplete_sources/labels.json');
describe('GfmAutoComplete', () => {
- const gfmAutoCompleteCallbacks = GfmAutoComplete.prototype.getDefaultCallbacks.call({
- fetchData: () => {},
- });
+ const fetchDataMock = { fetchData: jest.fn() };
+ let gfmAutoCompleteCallbacks = GfmAutoComplete.prototype.getDefaultCallbacks.call(fetchDataMock);
let atwhoInstance;
let sorterValue;
+ let filterValue;
+
+ describe('DefaultOptions.filter', () => {
+ let items;
+
+ beforeEach(() => {
+ jest.spyOn(fetchDataMock, 'fetchData');
+ jest.spyOn($.fn.atwho.default.callbacks, 'filter').mockImplementation(() => {});
+ });
+
+ describe('assets loading', () => {
+ beforeEach(() => {
+ atwhoInstance = { setting: {}, $inputor: 'inputor', at: '[vulnerability:' };
+ items = ['loading'];
+
+ filterValue = gfmAutoCompleteCallbacks.filter.call(atwhoInstance, '', items);
+ });
+
+ it('should call the fetchData function without query', () => {
+ expect(fetchDataMock.fetchData).toHaveBeenCalledWith('inputor', '[vulnerability:');
+ });
+
+ it('should not call the default atwho filter', () => {
+ expect($.fn.atwho.default.callbacks.filter).not.toHaveBeenCalled();
+ });
+
+ it('should return the passed unfiltered items', () => {
+ expect(filterValue).toEqual(items);
+ });
+ });
+
+ describe('backend filtering', () => {
+ beforeEach(() => {
+ atwhoInstance = { setting: {}, $inputor: 'inputor', at: '[vulnerability:' };
+ items = [];
+ });
+
+ describe('when previous query is different from current one', () => {
+ beforeEach(() => {
+ gfmAutoCompleteCallbacks = GfmAutoComplete.prototype.getDefaultCallbacks.call({
+ previousQuery: 'oldquery',
+ ...fetchDataMock,
+ });
+ filterValue = gfmAutoCompleteCallbacks.filter.call(atwhoInstance, 'newquery', items);
+ });
+
+ it('should call the fetchData function with query', () => {
+ expect(fetchDataMock.fetchData).toHaveBeenCalledWith(
+ 'inputor',
+ '[vulnerability:',
+ 'newquery',
+ );
+ });
+
+ it('should not call the default atwho filter', () => {
+ expect($.fn.atwho.default.callbacks.filter).not.toHaveBeenCalled();
+ });
+
+ it('should return the passed unfiltered items', () => {
+ expect(filterValue).toEqual(items);
+ });
+ });
+
+ describe('when previous query is not different from current one', () => {
+ beforeEach(() => {
+ gfmAutoCompleteCallbacks = GfmAutoComplete.prototype.getDefaultCallbacks.call({
+ previousQuery: 'oldquery',
+ ...fetchDataMock,
+ });
+ filterValue = gfmAutoCompleteCallbacks.filter.call(
+ atwhoInstance,
+ 'oldquery',
+ items,
+ 'searchKey',
+ );
+ });
+
+ it('should not call the fetchData function', () => {
+ expect(fetchDataMock.fetchData).not.toHaveBeenCalled();
+ });
+
+ it('should call the default atwho filter', () => {
+ expect($.fn.atwho.default.callbacks.filter).toHaveBeenCalledWith(
+ 'oldquery',
+ items,
+ 'searchKey',
+ );
+ });
+ });
+ });
+ });
+
+ describe('fetchData', () => {
+ const { fetchData } = GfmAutoComplete.prototype;
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ jest.spyOn(axios, 'get');
+ jest.spyOn(AjaxCache, 'retrieve');
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('already loading data', () => {
+ beforeEach(() => {
+ const context = {
+ isLoadingData: { '[vulnerability:': true },
+ dataSources: {},
+ cachedData: {},
+ };
+ fetchData.call(context, {}, '[vulnerability:', '');
+ });
+
+ it('should not call either axios nor AjaxCache', () => {
+ expect(axios.get).not.toHaveBeenCalled();
+ expect(AjaxCache.retrieve).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('backend filtering', () => {
+ describe('data is not in cache', () => {
+ let context;
+
+ beforeEach(() => {
+ context = {
+ isLoadingData: { '[vulnerability:': false },
+ dataSources: { vulnerabilities: 'vulnerabilities_autocomplete_url' },
+ cachedData: {},
+ };
+ });
+
+ it('should call axios with query', () => {
+ fetchData.call(context, {}, '[vulnerability:', 'query');
+
+ expect(axios.get).toHaveBeenCalledWith('vulnerabilities_autocomplete_url', {
+ params: { search: 'query' },
+ });
+ });
+
+ it.each([200, 500])('should set the loading state', async responseStatus => {
+ mock.onGet('vulnerabilities_autocomplete_url').replyOnce(responseStatus);
+
+ fetchData.call(context, {}, '[vulnerability:', 'query');
+
+ expect(context.isLoadingData['[vulnerability:']).toBe(true);
+
+ await waitForPromises();
+
+ expect(context.isLoadingData['[vulnerability:']).toBe(false);
+ });
+ });
+
+ describe('data is in cache', () => {
+ beforeEach(() => {
+ const context = {
+ isLoadingData: { '[vulnerability:': false },
+ dataSources: { vulnerabilities: 'vulnerabilities_autocomplete_url' },
+ cachedData: { '[vulnerability:': [{}] },
+ };
+ fetchData.call(context, {}, '[vulnerability:', 'query');
+ });
+
+ it('should anyway call axios with query ignoring cache', () => {
+ expect(axios.get).toHaveBeenCalledWith('vulnerabilities_autocomplete_url', {
+ params: { search: 'query' },
+ });
+ });
+ });
+ });
+
+ describe('frontend filtering', () => {
+ describe('data is not in cache', () => {
+ beforeEach(() => {
+ const context = {
+ isLoadingData: { '#': false },
+ dataSources: { issues: 'issues_autocomplete_url' },
+ cachedData: {},
+ };
+ fetchData.call(context, {}, '#', 'query');
+ });
+
+ it('should call AjaxCache', () => {
+ expect(AjaxCache.retrieve).toHaveBeenCalledWith('issues_autocomplete_url', true);
+ });
+ });
+
+ describe('data is in cache', () => {
+ beforeEach(() => {
+ const context = {
+ isLoadingData: { '#': false },
+ dataSources: { issues: 'issues_autocomplete_url' },
+ cachedData: { '#': [{}] },
+ loadData: () => {},
+ };
+ fetchData.call(context, {}, '#', 'query');
+ });
+
+ it('should not call AjaxCache', () => {
+ expect(AjaxCache.retrieve).not.toHaveBeenCalled();
+ });
+ });
+ });
+ });
describe('DefaultOptions.sorter', () => {
describe('assets loading', () => {
@@ -154,7 +365,6 @@ describe('GfmAutoComplete', () => {
'Ñ',
'.',
"'",
- '+',
'-',
'_',
];
@@ -378,6 +588,7 @@ describe('GfmAutoComplete', () => {
username: 'my-group',
title: '',
icon: '',
+ availabilityStatus: '',
}),
).toBe('<li>IMG my-group <small></small> </li>');
});
@@ -389,6 +600,7 @@ describe('GfmAutoComplete', () => {
username: 'my-group',
title: '',
icon: '<i class="icon"/>',
+ availabilityStatus: '',
}),
).toBe('<li>IMG my-group <small></small> <i class="icon"/></li>');
});
@@ -400,9 +612,24 @@ describe('GfmAutoComplete', () => {
username: 'my-group',
title: 'MyGroup+',
icon: '<i class="icon"/>',
+ availabilityStatus: '',
}),
).toBe('<li>IMG my-group <small>MyGroup+</small> <i class="icon"/></li>');
});
+
+ it('should add user availability status if availabilityStatus is set', () => {
+ expect(
+ GfmAutoComplete.Members.templateFunction({
+ avatarTag: 'IMG',
+ username: 'my-group',
+ title: '',
+ icon: '<i class="icon"/>',
+ availabilityStatus: '<span class="gl-text-gray-500"> (Busy)</span>',
+ }),
+ ).toBe(
+ '<li>IMG my-group <small><span class="gl-text-gray-500"> (Busy)</span></small> <i class="icon"/></li>',
+ );
+ });
});
describe('labels', () => {
diff --git a/spec/frontend/graphql_shared/utils_spec.js b/spec/frontend/graphql_shared/utils_spec.js
index 52386bf6ede..6a630195126 100644
--- a/spec/frontend/graphql_shared/utils_spec.js
+++ b/spec/frontend/graphql_shared/utils_spec.js
@@ -11,6 +11,10 @@ describe('getIdFromGraphQLId', () => {
output: null,
},
{
+ input: 2,
+ output: 2,
+ },
+ {
input: 'gid://',
output: null,
},
diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js
index 5d34bc48ed5..691f8896d74 100644
--- a/spec/frontend/groups/components/app_spec.js
+++ b/spec/frontend/groups/components/app_spec.js
@@ -2,6 +2,8 @@ import '~/flash';
import $ from 'jquery';
import Vue from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
+import { GlModal, GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import appComponent from '~/groups/components/app.vue';
@@ -23,47 +25,51 @@ import {
mockPageInfo,
} from '../mock_data';
-const createComponent = (hideProjects = false) => {
- const Component = Vue.extend(appComponent);
- const store = new GroupsStore(false);
- const service = new GroupsService(mockEndpoint);
-
- store.state.pageInfo = mockPageInfo;
-
- return new Component({
- propsData: {
- store,
- service,
- hideProjects,
- },
- });
+const $toast = {
+ show: jest.fn(),
};
describe('AppComponent', () => {
+ let wrapper;
let vm;
let mock;
let getGroupsSpy;
+ const store = new GroupsStore(false);
+ const service = new GroupsService(mockEndpoint);
+
+ const createShallowComponent = (hideProjects = false) => {
+ store.state.pageInfo = mockPageInfo;
+ wrapper = shallowMount(appComponent, {
+ propsData: {
+ store,
+ service,
+ hideProjects,
+ },
+ mocks: {
+ $toast,
+ },
+ });
+ vm = wrapper.vm;
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
beforeEach(() => {
mock = new AxiosMockAdapter(axios);
mock.onGet('/dashboard/groups.json').reply(200, mockGroups);
Vue.component('group-folder', groupFolderComponent);
Vue.component('group-item', groupItemComponent);
- vm = createComponent();
+ createShallowComponent();
getGroupsSpy = jest.spyOn(vm.service, 'getGroups');
return vm.$nextTick();
});
describe('computed', () => {
- beforeEach(() => {
- vm.$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
describe('groups', () => {
it('should return list of groups from store', () => {
jest.spyOn(vm.store, 'getGroups').mockImplementation(() => {});
@@ -88,14 +94,6 @@ describe('AppComponent', () => {
});
describe('methods', () => {
- beforeEach(() => {
- vm.$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
describe('fetchGroups', () => {
it('should call `getGroups` with all the params provided', () => {
return vm
@@ -284,29 +282,15 @@ describe('AppComponent', () => {
it('updates props which show modal confirmation dialog', () => {
const group = { ...mockParentGroupItem };
- expect(vm.showModal).toBe(false);
expect(vm.groupLeaveConfirmationMessage).toBe('');
vm.showLeaveGroupModal(group, mockParentGroupItem);
- expect(vm.showModal).toBe(true);
expect(vm.groupLeaveConfirmationMessage).toBe(
`Are you sure you want to leave the "${group.fullName}" group?`,
);
});
});
- describe('hideLeaveGroupModal', () => {
- it('hides modal confirmation which is shown before leaving the group', () => {
- const group = { ...mockParentGroupItem };
- vm.showLeaveGroupModal(group, mockParentGroupItem);
-
- expect(vm.showModal).toBe(true);
- vm.hideLeaveGroupModal();
-
- expect(vm.showModal).toBe(false);
- });
- });
-
describe('leaveGroup', () => {
let groupItem;
let childGroupItem;
@@ -324,18 +308,16 @@ describe('AppComponent', () => {
const notice = `You left the "${childGroupItem.fullName}" group.`;
jest.spyOn(vm.service, 'leaveGroup').mockResolvedValue({ data: { notice } });
jest.spyOn(vm.store, 'removeGroup');
- jest.spyOn(window, 'Flash').mockImplementation(() => {});
jest.spyOn($, 'scrollTo').mockImplementation(() => {});
vm.leaveGroup();
- expect(vm.showModal).toBe(false);
expect(vm.targetGroup.isBeingRemoved).toBe(true);
expect(vm.service.leaveGroup).toHaveBeenCalledWith(vm.targetGroup.leavePath);
return waitForPromises().then(() => {
expect($.scrollTo).toHaveBeenCalledWith(0);
expect(vm.store.removeGroup).toHaveBeenCalledWith(vm.targetGroup, vm.targetParentGroup);
- expect(window.Flash).toHaveBeenCalledWith(notice, 'notice');
+ expect($toast.show).toHaveBeenCalledWith(notice);
});
});
@@ -417,8 +399,7 @@ describe('AppComponent', () => {
it('should bind event listeners on eventHub', () => {
jest.spyOn(eventHub, '$on').mockImplementation(() => {});
- const newVm = createComponent();
- newVm.$mount();
+ createShallowComponent();
return vm.$nextTick().then(() => {
expect(eventHub.$on).toHaveBeenCalledWith('fetchPage', expect.any(Function));
@@ -426,25 +407,20 @@ describe('AppComponent', () => {
expect(eventHub.$on).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function));
expect(eventHub.$on).toHaveBeenCalledWith('updatePagination', expect.any(Function));
expect(eventHub.$on).toHaveBeenCalledWith('updateGroups', expect.any(Function));
- newVm.$destroy();
});
});
it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `false`', () => {
- const newVm = createComponent();
- newVm.$mount();
+ createShallowComponent();
return vm.$nextTick().then(() => {
- expect(newVm.searchEmptyMessage).toBe('No groups or projects matched your search');
- newVm.$destroy();
+ expect(vm.searchEmptyMessage).toBe('No groups or projects matched your search');
});
});
it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `true`', () => {
- const newVm = createComponent(true);
- newVm.$mount();
+ createShallowComponent(true);
return vm.$nextTick().then(() => {
- expect(newVm.searchEmptyMessage).toBe('No groups matched your search');
- newVm.$destroy();
+ expect(vm.searchEmptyMessage).toBe('No groups matched your search');
});
});
});
@@ -453,9 +429,8 @@ describe('AppComponent', () => {
it('should unbind event listeners on eventHub', () => {
jest.spyOn(eventHub, '$off').mockImplementation(() => {});
- const newVm = createComponent();
- newVm.$mount();
- newVm.$destroy();
+ createShallowComponent();
+ wrapper.destroy();
return vm.$nextTick().then(() => {
expect(eventHub.$off).toHaveBeenCalledWith('fetchPage', expect.any(Function));
@@ -468,19 +443,10 @@ describe('AppComponent', () => {
});
describe('template', () => {
- beforeEach(() => {
- vm.$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
it('should render loading icon', () => {
vm.isLoading = true;
return vm.$nextTick().then(() => {
- expect(vm.$el.querySelector('.loading-animation')).toBeDefined();
- expect(vm.$el.querySelector('span').getAttribute('aria-label')).toBe('Loading groups');
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
});
@@ -493,15 +459,13 @@ describe('AppComponent', () => {
});
it('renders modal confirmation dialog', () => {
- vm.groupLeaveConfirmationMessage = 'Are you sure you want to leave the "foo" group?';
- vm.showModal = true;
- return vm.$nextTick().then(() => {
- const modalDialogEl = vm.$el.querySelector('.modal');
+ createShallowComponent();
- expect(modalDialogEl).not.toBe(null);
- expect(modalDialogEl.querySelector('.modal-title').innerText.trim()).toBe('Are you sure?');
- expect(modalDialogEl.querySelector('.btn.btn-warning').innerText.trim()).toBe('Leave');
- });
+ const findGlModal = wrapper.find(GlModal);
+
+ expect(findGlModal.exists()).toBe(true);
+ expect(findGlModal.attributes('title')).toBe('Are you sure?');
+ expect(findGlModal.props('actionPrimary').text).toBe('Leave group');
});
});
});
diff --git a/spec/frontend/groups/components/item_actions_spec.js b/spec/frontend/groups/components/item_actions_spec.js
index d4aa29eaadd..9adbc9abe13 100644
--- a/spec/frontend/groups/components/item_actions_spec.js
+++ b/spec/frontend/groups/components/item_actions_spec.js
@@ -1,5 +1,4 @@
import { shallowMount } from '@vue/test-utils';
-import { GlIcon } from '@gitlab/ui';
import ItemActions from '~/groups/components/item_actions.vue';
import eventHub from '~/groups/event_hub';
import { mockParentGroupItem, mockChildren } from '../mock_data';
@@ -20,18 +19,25 @@ describe('ItemActions', () => {
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
+ wrapper = null;
});
const findEditGroupBtn = () => wrapper.find('[data-testid="edit-group-btn"]');
- const findEditGroupIcon = () => findEditGroupBtn().find(GlIcon);
const findLeaveGroupBtn = () => wrapper.find('[data-testid="leave-group-btn"]');
- const findLeaveGroupIcon = () => findLeaveGroupBtn().find(GlIcon);
describe('template', () => {
+ let group;
+
+ beforeEach(() => {
+ group = {
+ ...mockParentGroupItem,
+ canEdit: true,
+ canLeave: true,
+ };
+ createComponent({ group });
+ });
+
it('renders component template correctly', () => {
createComponent();
@@ -39,49 +45,46 @@ describe('ItemActions', () => {
});
it('renders "Edit group" button with correct attribute values', () => {
- const group = {
- ...mockParentGroupItem,
- canEdit: true,
- };
-
- createComponent({ group });
-
- expect(findEditGroupBtn().exists()).toBe(true);
- expect(findEditGroupBtn().classes()).toContain('no-expand');
- expect(findEditGroupBtn().attributes('href')).toBe(group.editPath);
- expect(findEditGroupBtn().attributes('aria-label')).toBe('Edit group');
- expect(findEditGroupBtn().attributes('data-original-title')).toBe('Edit group');
- expect(findEditGroupIcon().exists()).toBe(true);
- expect(findEditGroupIcon().props('name')).toBe('settings');
+ const button = findEditGroupBtn();
+ expect(button.exists()).toBe(true);
+ expect(button.props('icon')).toBe('pencil');
+ expect(button.attributes('aria-label')).toBe('Edit group');
});
- describe('`canLeave` is true', () => {
- const group = {
- ...mockParentGroupItem,
- canLeave: true,
- };
+ it('renders "Leave this group" button with correct attribute values', () => {
+ const button = findLeaveGroupBtn();
+ expect(button.exists()).toBe(true);
+ expect(button.props('icon')).toBe('leave');
+ expect(button.attributes('aria-label')).toBe('Leave this group');
+ });
- beforeEach(() => {
- createComponent({ group });
- });
+ it('emits `showLeaveGroupModal` event in the event hub', () => {
+ jest.spyOn(eventHub, '$emit');
+ findLeaveGroupBtn().vm.$emit('click', { stopPropagation: () => {} });
- it('renders "Leave this group" button with correct attribute values', () => {
- expect(findLeaveGroupBtn().exists()).toBe(true);
- expect(findLeaveGroupBtn().classes()).toContain('no-expand');
- expect(findLeaveGroupBtn().attributes('href')).toBe(group.leavePath);
- expect(findLeaveGroupBtn().attributes('aria-label')).toBe('Leave this group');
- expect(findLeaveGroupBtn().attributes('data-original-title')).toBe('Leave this group');
- expect(findLeaveGroupIcon().exists()).toBe(true);
- expect(findLeaveGroupIcon().props('name')).toBe('leave');
- });
+ expect(eventHub.$emit).toHaveBeenCalledWith('showLeaveGroupModal', group, parentGroup);
+ });
+ });
- it('emits event on "Leave this group" button click', () => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ it('does not render leave button if group can not be left', () => {
+ createComponent({
+ group: {
+ ...mockParentGroupItem,
+ canLeave: false,
+ },
+ });
- findLeaveGroupBtn().trigger('click');
+ expect(findLeaveGroupBtn().exists()).toBe(false);
+ });
- expect(eventHub.$emit).toHaveBeenCalledWith('showLeaveGroupModal', group, parentGroup);
- });
+ it('does not render edit button if group can not be edited', () => {
+ createComponent({
+ group: {
+ ...mockParentGroupItem,
+ canEdit: false,
+ },
});
+
+ expect(findEditGroupBtn().exists()).toBe(false);
});
});
diff --git a/spec/frontend/groups/members/index_spec.js b/spec/frontend/groups/members/index_spec.js
index 2fb7904bcfe..aaa36665c45 100644
--- a/spec/frontend/groups/members/index_spec.js
+++ b/spec/frontend/groups/members/index_spec.js
@@ -9,7 +9,12 @@ describe('initGroupMembersApp', () => {
let wrapper;
const setup = () => {
- vm = initGroupMembersApp(el, ['account'], () => ({}));
+ vm = initGroupMembersApp(
+ el,
+ ['account'],
+ { table: { 'data-qa-selector': 'members_list' } },
+ () => ({}),
+ );
wrapper = createWrapper(vm);
};
@@ -68,6 +73,12 @@ describe('initGroupMembersApp', () => {
expect(vm.$store.state.tableFields).toEqual(['account']);
});
+ it('sets `tableAttrs` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.tableAttrs).toEqual({ table: { 'data-qa-selector': 'members_list' } });
+ });
+
it('sets `requestFormatter` in Vuex store', () => {
setup();
diff --git a/spec/frontend/groups/mock_data.js b/spec/frontend/groups/mock_data.js
index 380dda9f7b1..603cb27deec 100644
--- a/spec/frontend/groups/mock_data.js
+++ b/spec/frontend/groups/mock_data.js
@@ -7,13 +7,14 @@ export const ITEM_TYPE = {
export const GROUP_VISIBILITY_TYPE = {
public: 'Public - The group and any public projects can be viewed without any authentication.',
- internal: 'Internal - The group and any internal projects can be viewed by any logged in user.',
+ internal:
+ 'Internal - The group and any internal projects can be viewed by any logged in user except external users.',
private: 'Private - The group and its projects can only be viewed by members.',
};
export const PROJECT_VISIBILITY_TYPE = {
public: 'Public - The project can be accessed without any authentication.',
- internal: 'Internal - The project can be accessed by any logged in user.',
+ internal: 'Internal - The project can be accessed by any logged in user except external users.',
private:
'Private - Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group.',
};
diff --git a/spec/frontend/helpers/fake_date.js b/spec/frontend/helpers/fake_date.js
index 8417b1c520a..387747ab5bd 100644
--- a/spec/frontend/helpers/fake_date.js
+++ b/spec/frontend/helpers/fake_date.js
@@ -15,7 +15,7 @@ export const createFakeDateClass = ctorDefault => {
apply: (target, thisArg, argArray) => {
const ctorArgs = argArray.length ? argArray : ctorDefault;
- return RealDate(...ctorArgs);
+ return new RealDate(...ctorArgs).toString();
},
// We want to overwrite the default 'now', but only if it's not already mocked
get: (target, prop) => {
diff --git a/spec/frontend/helpers/fake_date_spec.js b/spec/frontend/helpers/fake_date_spec.js
index 8afc8225f9b..b3ed13e238a 100644
--- a/spec/frontend/helpers/fake_date_spec.js
+++ b/spec/frontend/helpers/fake_date_spec.js
@@ -13,13 +13,17 @@ describe('spec/helpers/fake_date', () => {
});
it('should use default args', () => {
- expect(new FakeDate()).toEqual(new Date(...DEFAULT_ARGS));
- expect(FakeDate()).toEqual(Date(...DEFAULT_ARGS));
+ expect(new FakeDate()).toMatchInlineSnapshot(`2020-07-06T00:00:00.000Z`);
+ });
+
+ it('should use default args when called as a function', () => {
+ expect(FakeDate()).toMatchInlineSnapshot(
+ `"Mon Jul 06 2020 00:00:00 GMT+0000 (Greenwich Mean Time)"`,
+ );
});
it('should have deterministic now()', () => {
- expect(FakeDate.now()).not.toBe(Date.now());
- expect(FakeDate.now()).toBe(new Date(...DEFAULT_ARGS).getTime());
+ expect(FakeDate.now()).toMatchInlineSnapshot(`1593993600000`);
});
it('should be instanceof Date', () => {
diff --git a/spec/frontend/helpers/mock_apollo_helper.js b/spec/frontend/helpers/mock_apollo_helper.js
index 8a5a160231c..914cce1d662 100644
--- a/spec/frontend/helpers/mock_apollo_helper.js
+++ b/spec/frontend/helpers/mock_apollo_helper.js
@@ -2,14 +2,14 @@ import { InMemoryCache } from 'apollo-cache-inmemory';
import { createMockClient } from 'mock-apollo-client';
import VueApollo from 'vue-apollo';
-export default (handlers = []) => {
+export default (handlers = [], resolvers = {}) => {
const fragmentMatcher = { match: () => true };
const cache = new InMemoryCache({
fragmentMatcher,
addTypename: false,
});
- const mockClient = createMockClient({ cache });
+ const mockClient = createMockClient({ cache, resolvers });
if (Array.isArray(handlers)) {
handlers.forEach(([query, value]) => mockClient.setRequestHandler(query, value));
diff --git a/spec/frontend/helpers/startup_css_helper_spec.js b/spec/frontend/helpers/startup_css_helper_spec.js
index 1a88e80344e..2d560c43fa5 100644
--- a/spec/frontend/helpers/startup_css_helper_spec.js
+++ b/spec/frontend/helpers/startup_css_helper_spec.js
@@ -19,6 +19,26 @@ describe('waitForCSSLoaded', () => {
});
});
+ describe('when gon features is not provided', () => {
+ let originalGon;
+
+ beforeEach(() => {
+ originalGon = window.gon;
+ window.gon = null;
+ });
+
+ afterEach(() => {
+ window.gon = originalGon;
+ });
+
+ it('should invoke the action right away', async () => {
+ const events = waitForCSSLoaded(mockedCallback);
+ await events;
+
+ expect(mockedCallback).toHaveBeenCalledTimes(1);
+ });
+ });
+
describe('with startup css disabled', () => {
gon.features = {
startupCss: false,
diff --git a/spec/frontend/ide/components/commit_sidebar/list_collapsed_spec.js b/spec/frontend/ide/components/commit_sidebar/list_collapsed_spec.js
deleted file mode 100644
index 42e0a20bc7b..00000000000
--- a/spec/frontend/ide/components/commit_sidebar/list_collapsed_spec.js
+++ /dev/null
@@ -1,75 +0,0 @@
-import Vue from 'vue';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
-import listCollapsed from '~/ide/components/commit_sidebar/list_collapsed.vue';
-import { file } from '../../helpers';
-import { removeWhitespace } from '../../../helpers/text_helper';
-
-describe('Multi-file editor commit sidebar list collapsed', () => {
- let vm;
- let store;
-
- beforeEach(() => {
- store = createStore();
-
- const Component = Vue.extend(listCollapsed);
-
- vm = createComponentWithStore(Component, store, {
- files: [
- {
- ...file('file1'),
- tempFile: true,
- },
- file('file2'),
- ],
- iconName: 'staged',
- title: 'Staged',
- });
-
- vm.$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders added & modified files count', () => {
- expect(removeWhitespace(vm.$el.textContent).trim()).toBe('1 1');
- });
-
- describe('addedFilesLength', () => {
- it('returns an length of temp files', () => {
- expect(vm.addedFilesLength).toBe(1);
- });
- });
-
- describe('modifiedFilesLength', () => {
- it('returns an length of modified files', () => {
- expect(vm.modifiedFilesLength).toBe(1);
- });
- });
-
- describe('addedFilesIconClass', () => {
- it('includes multi-file-addition when addedFiles is not empty', () => {
- expect(vm.addedFilesIconClass).toContain('multi-file-addition');
- });
-
- it('excludes multi-file-addition when addedFiles is empty', () => {
- vm.files = [];
-
- expect(vm.addedFilesIconClass).not.toContain('multi-file-addition');
- });
- });
-
- describe('modifiedFilesClass', () => {
- it('includes multi-file-modified when addedFiles is not empty', () => {
- expect(vm.modifiedFilesClass).toContain('multi-file-modified');
- });
-
- it('excludes multi-file-modified when addedFiles is empty', () => {
- vm.files = [];
-
- expect(vm.modifiedFilesClass).not.toContain('multi-file-modified');
- });
- });
-});
diff --git a/spec/frontend/ide/components/commit_sidebar/list_spec.js b/spec/frontend/ide/components/commit_sidebar/list_spec.js
index 2107ff96e95..636dfbf0b2a 100644
--- a/spec/frontend/ide/components/commit_sidebar/list_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/list_spec.js
@@ -16,7 +16,6 @@ describe('Multi-file editor commit sidebar list', () => {
vm = createComponentWithStore(Component, store, {
title: 'Staged',
fileList: [],
- iconName: 'staged',
action: 'stageAllChanges',
actionBtnText: 'stage all',
actionBtnIcon: 'history',
diff --git a/spec/frontend/ide/components/ide_side_bar_spec.js b/spec/frontend/ide/components/ide_side_bar_spec.js
index 86e4e8d8f89..72e9463945b 100644
--- a/spec/frontend/ide/components/ide_side_bar_spec.js
+++ b/spec/frontend/ide/components/ide_side_bar_spec.js
@@ -1,10 +1,12 @@
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { GlSkeletonLoading } from '@gitlab/ui';
+import waitForPromises from 'helpers/wait_for_promises';
import { createStore } from '~/ide/stores';
import IdeSidebar from '~/ide/components/ide_side_bar.vue';
import IdeTree from '~/ide/components/ide_tree.vue';
import RepoCommitSection from '~/ide/components/repo_commit_section.vue';
+import IdeReview from '~/ide/components/ide_review.vue';
import { leftSidebarViews } from '~/ide/constants';
import { projectData } from '../mock_data';
@@ -15,11 +17,12 @@ describe('IdeSidebar', () => {
let wrapper;
let store;
- function createComponent() {
+ function createComponent({ view = leftSidebarViews.edit.name } = {}) {
store = createStore();
store.state.currentProjectId = 'abcproject';
store.state.projects.abcproject = projectData;
+ store.state.currentActivityView = view;
return mount(IdeSidebar, {
store,
@@ -48,22 +51,46 @@ describe('IdeSidebar', () => {
expect(wrapper.findAll(GlSkeletonLoading)).toHaveLength(3);
});
- describe('activityBarComponent', () => {
- it('renders tree component', () => {
+ describe('deferred rendering components', () => {
+ it('fetches components on demand', async () => {
wrapper = createComponent();
expect(wrapper.find(IdeTree).exists()).toBe(true);
- });
+ expect(wrapper.find(IdeReview).exists()).toBe(false);
+ expect(wrapper.find(RepoCommitSection).exists()).toBe(false);
- it('renders commit component', async () => {
- wrapper = createComponent();
+ store.state.currentActivityView = leftSidebarViews.review.name;
+ await waitForPromises();
+ await wrapper.vm.$nextTick();
- store.state.currentActivityView = leftSidebarViews.commit.name;
+ expect(wrapper.find(IdeTree).exists()).toBe(false);
+ expect(wrapper.find(IdeReview).exists()).toBe(true);
+ expect(wrapper.find(RepoCommitSection).exists()).toBe(false);
+ store.state.currentActivityView = leftSidebarViews.commit.name;
+ await waitForPromises();
await wrapper.vm.$nextTick();
+ expect(wrapper.find(IdeTree).exists()).toBe(false);
+ expect(wrapper.find(IdeReview).exists()).toBe(false);
expect(wrapper.find(RepoCommitSection).exists()).toBe(true);
});
+ it.each`
+ view | tree | review | commit
+ ${leftSidebarViews.edit.name} | ${true} | ${false} | ${false}
+ ${leftSidebarViews.review.name} | ${false} | ${true} | ${false}
+ ${leftSidebarViews.commit.name} | ${false} | ${false} | ${true}
+ `('renders correct panels for $view', async ({ view, tree, review, commit } = {}) => {
+ wrapper = createComponent({
+ view,
+ });
+ await waitForPromises();
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(IdeTree).exists()).toBe(tree);
+ expect(wrapper.find(IdeReview).exists()).toBe(review);
+ expect(wrapper.find(RepoCommitSection).exists()).toBe(commit);
+ });
});
it('keeps the current activity view components alive', async () => {
@@ -72,7 +99,7 @@ describe('IdeSidebar', () => {
const ideTreeComponent = wrapper.find(IdeTree).element;
store.state.currentActivityView = leftSidebarViews.commit.name;
-
+ await waitForPromises();
await wrapper.vm.$nextTick();
expect(wrapper.find(IdeTree).exists()).toBe(false);
@@ -80,6 +107,7 @@ describe('IdeSidebar', () => {
store.state.currentActivityView = leftSidebarViews.edit.name;
+ await waitForPromises();
await wrapper.vm.$nextTick();
// reference to the elements remains the same, meaning the components were kept alive
diff --git a/spec/frontend/ide/components/ide_spec.js b/spec/frontend/ide/components/ide_spec.js
index a7b07a9f0e2..ff3852b6775 100644
--- a/spec/frontend/ide/components/ide_spec.js
+++ b/spec/frontend/ide/components/ide_spec.js
@@ -1,127 +1,165 @@
-import Vue from 'vue';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { createStore } from '~/ide/stores';
+import ErrorMessage from '~/ide/components/error_message.vue';
+import FindFile from '~/vue_shared/components/file_finder/index.vue';
+import CommitEditorHeader from '~/ide/components/commit_sidebar/editor_header.vue';
+import RepoTabs from '~/ide/components/repo_tabs.vue';
+import IdeStatusBar from '~/ide/components/ide_status_bar.vue';
+import RightPane from '~/ide/components/panes/right.vue';
+import NewModal from '~/ide/components/new_dropdown/modal.vue';
+
import ide from '~/ide/components/ide.vue';
import { file } from '../helpers';
import { projectData } from '../mock_data';
-import extendStore from '~/ide/stores/extend';
-
-let store;
-function bootstrap(projData) {
- store = createStore();
+const localVue = createLocalVue();
+localVue.use(Vuex);
- extendStore(store, document.createElement('div'));
+describe('WebIDE', () => {
+ const emptyProjData = { ...projectData, empty_repo: true, branches: {} };
- const Component = Vue.extend(ide);
+ let wrapper;
- store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
- store.state.projects.abcproject = { ...projData };
- Vue.set(store.state.trees, 'abcproject/master', {
- tree: [],
- loading: false,
- });
-
- return createComponentWithStore(Component, store, {
- emptyStateSvgPath: 'svg',
- noChangesStateSvgPath: 'svg',
- committedStateSvgPath: 'svg',
- });
-}
+ function createComponent({ projData = emptyProjData, state = {} } = {}) {
+ const store = createStore();
-describe('ide component, empty repo', () => {
- let vm;
+ store.state.currentProjectId = 'abcproject';
+ store.state.currentBranchId = 'master';
+ store.state.projects.abcproject = { ...projData };
+ store.state.trees['abcproject/master'] = {
+ tree: [],
+ loading: false,
+ };
+ Object.keys(state).forEach(key => {
+ store.state[key] = state[key];
+ });
- beforeEach(() => {
- const emptyProjData = { ...projectData, empty_repo: true, branches: {} };
- vm = bootstrap(emptyProjData);
- vm.$mount();
- });
+ return shallowMount(ide, {
+ store,
+ localVue,
+ stubs: {
+ ErrorMessage,
+ GlButton,
+ GlLoadingIcon,
+ CommitEditorHeader,
+ RepoTabs,
+ IdeStatusBar,
+ FindFile,
+ RightPane,
+ NewModal,
+ },
+ });
+ }
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
});
- it('renders "New file" button in empty repo', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-empty-state button[title="New file"]')).not.toBeNull();
- done();
+ describe('ide component, empty repo', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ projData: {
+ empty_repo: true,
+ },
+ });
});
- });
-});
-
-describe('ide component, non-empty repo', () => {
- let vm;
- beforeEach(() => {
- vm = bootstrap(projectData);
- vm.$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
+ it('renders "New file" button in empty repo', async () => {
+ expect(wrapper.find('[title="New file"]').exists()).toBe(true);
+ });
});
- it('shows error message when set', done => {
- expect(vm.$el.querySelector('.gl-alert')).toBe(null);
+ describe('ide component, non-empty repo', () => {
+ describe('error message', () => {
+ it('does not show error message when it is not set', () => {
+ wrapper = createComponent({
+ state: {
+ errorMessage: null,
+ },
+ });
- vm.$store.state.errorMessage = {
- text: 'error',
- };
+ expect(wrapper.find(ErrorMessage).exists()).toBe(false);
+ });
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.gl-alert')).not.toBe(null);
+ it('shows error message when set', () => {
+ wrapper = createComponent({
+ state: {
+ errorMessage: {
+ text: 'error',
+ },
+ },
+ });
- done();
+ expect(wrapper.find(ErrorMessage).exists()).toBe(true);
+ });
});
- });
- describe('onBeforeUnload', () => {
- it('returns undefined when no staged files or changed files', () => {
- expect(vm.onBeforeUnload()).toBe(undefined);
- });
+ describe('onBeforeUnload', () => {
+ it('returns undefined when no staged files or changed files', () => {
+ wrapper = createComponent();
+ expect(wrapper.vm.onBeforeUnload()).toBe(undefined);
+ });
- it('returns warning text when their are changed files', () => {
- vm.$store.state.changedFiles.push(file());
+ it('returns warning text when their are changed files', () => {
+ wrapper = createComponent({
+ state: {
+ changedFiles: [file()],
+ },
+ });
- expect(vm.onBeforeUnload()).toBe('Are you sure you want to lose unsaved changes?');
- });
+ expect(wrapper.vm.onBeforeUnload()).toBe('Are you sure you want to lose unsaved changes?');
+ });
- it('returns warning text when their are staged files', () => {
- vm.$store.state.stagedFiles.push(file());
+ it('returns warning text when their are staged files', () => {
+ wrapper = createComponent({
+ state: {
+ stagedFiles: [file()],
+ },
+ });
- expect(vm.onBeforeUnload()).toBe('Are you sure you want to lose unsaved changes?');
- });
+ expect(wrapper.vm.onBeforeUnload()).toBe('Are you sure you want to lose unsaved changes?');
+ });
- it('updates event object', () => {
- const event = {};
- vm.$store.state.stagedFiles.push(file());
+ it('updates event object', () => {
+ const event = {};
+ wrapper = createComponent({
+ state: {
+ stagedFiles: [file()],
+ },
+ });
- vm.onBeforeUnload(event);
+ wrapper.vm.onBeforeUnload(event);
- expect(event.returnValue).toBe('Are you sure you want to lose unsaved changes?');
+ expect(event.returnValue).toBe('Are you sure you want to lose unsaved changes?');
+ });
});
- });
- describe('non-existent branch', () => {
- it('does not render "New file" button for non-existent branch when repo is not empty', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-empty-state button[title="New file"]')).toBeNull();
- done();
+ describe('non-existent branch', () => {
+ it('does not render "New file" button for non-existent branch when repo is not empty', () => {
+ wrapper = createComponent({
+ state: {
+ projects: {},
+ },
+ });
+
+ expect(wrapper.find('[title="New file"]').exists()).toBe(false);
});
});
- });
- describe('branch with files', () => {
- beforeEach(() => {
- store.state.trees['abcproject/master'].tree = [file()];
- });
+ describe('branch with files', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ projData: {
+ empty_repo: false,
+ },
+ });
+ });
- it('does not render "New file" button', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-empty-state button[title="New file"]')).toBeNull();
- done();
+ it('does not render "New file" button', () => {
+ expect(wrapper.find('[title="New file"]').exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/ide/components/ide_status_list_spec.js b/spec/frontend/ide/components/ide_status_list_spec.js
index bb8165d1a52..02b5dc19bd8 100644
--- a/spec/frontend/ide/components/ide_status_list_spec.js
+++ b/spec/frontend/ide/components/ide_status_list_spec.js
@@ -6,17 +6,21 @@ import TerminalSyncStatusSafe from '~/ide/components/terminal_sync/terminal_sync
const TEST_FILE = {
name: 'lorem.md',
- editorRow: 3,
- editorColumn: 23,
- fileLanguage: 'markdown',
content: 'abc\nndef',
permalink: '/lorem.md',
};
+const TEST_FILE_EDITOR = {
+ fileLanguage: 'markdown',
+ editorRow: 3,
+ editorColumn: 23,
+};
+const TEST_EDITOR_POSITION = `${TEST_FILE_EDITOR.editorRow}:${TEST_FILE_EDITOR.editorColumn}`;
const localVue = createLocalVue();
localVue.use(Vuex);
describe('ide/components/ide_status_list', () => {
+ let activeFileEditor;
let activeFile;
let store;
let wrapper;
@@ -27,6 +31,14 @@ describe('ide/components/ide_status_list', () => {
getters: {
activeFile: () => activeFile,
},
+ modules: {
+ editor: {
+ namespaced: true,
+ getters: {
+ activeFileEditor: () => activeFileEditor,
+ },
+ },
+ },
});
wrapper = shallowMount(IdeStatusList, {
@@ -38,6 +50,7 @@ describe('ide/components/ide_status_list', () => {
beforeEach(() => {
activeFile = TEST_FILE;
+ activeFileEditor = TEST_FILE_EDITOR;
});
afterEach(() => {
@@ -47,8 +60,6 @@ describe('ide/components/ide_status_list', () => {
wrapper = null;
});
- const getEditorPosition = file => `${file.editorRow}:${file.editorColumn}`;
-
describe('with regular file', () => {
beforeEach(() => {
createComponent();
@@ -65,11 +76,11 @@ describe('ide/components/ide_status_list', () => {
});
it('shows file editor position', () => {
- expect(wrapper.text()).toContain(getEditorPosition(TEST_FILE));
+ expect(wrapper.text()).toContain(TEST_EDITOR_POSITION);
});
it('shows file language', () => {
- expect(wrapper.text()).toContain(TEST_FILE.fileLanguage);
+ expect(wrapper.text()).toContain(TEST_FILE_EDITOR.fileLanguage);
});
});
@@ -81,7 +92,7 @@ describe('ide/components/ide_status_list', () => {
});
it('does not show file editor position', () => {
- expect(wrapper.text()).not.toContain(getEditorPosition(TEST_FILE));
+ expect(wrapper.text()).not.toContain(TEST_EDITOR_POSITION);
});
});
diff --git a/spec/frontend/ide/components/pipelines/list_spec.js b/spec/frontend/ide/components/pipelines/list_spec.js
index 7f083fa7c25..c1744fefe20 100644
--- a/spec/frontend/ide/components/pipelines/list_spec.js
+++ b/spec/frontend/ide/components/pipelines/list_spec.js
@@ -1,11 +1,10 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlTab } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants';
import { pipelines } from 'jest/ide/mock_data';
import List from '~/ide/components/pipelines/list.vue';
import JobsList from '~/ide/components/jobs/list.vue';
-import Tab from '~/vue_shared/components/tabs/tab.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import IDEServices from '~/ide/services';
@@ -167,7 +166,7 @@ describe('IDE pipelines list', () => {
createComponent({}, { ...withLatestPipelineState, stages, isLoadingJobs });
const jobProps = wrapper
- .findAll(Tab)
+ .findAll(GlTab)
.at(0)
.find(JobsList)
.props();
@@ -182,7 +181,7 @@ describe('IDE pipelines list', () => {
createComponent({}, { ...withLatestPipelineState, isLoadingJobs });
const jobProps = wrapper
- .findAll(Tab)
+ .findAll(GlTab)
.at(1)
.find(JobsList)
.props();
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index 9f4c9c1622a..71a4f08cfb4 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -55,7 +55,6 @@ describe('RepoEditor', () => {
beforeEach(() => {
const f = {
...file('file.txt'),
- viewMode: FILE_VIEW_MODE_EDITOR,
content: 'hello world',
};
@@ -92,6 +91,8 @@ describe('RepoEditor', () => {
});
const findEditor = () => vm.$el.querySelector('.multi-file-editor-holder');
+ const changeViewMode = viewMode =>
+ store.dispatch('editor/updateFileEditor', { path: vm.file.path, data: { viewMode } });
describe('default', () => {
beforeEach(() => {
@@ -409,7 +410,7 @@ describe('RepoEditor', () => {
describe('when files view mode is preview', () => {
beforeEach(done => {
jest.spyOn(vm.editor, 'updateDimensions').mockImplementation();
- vm.file.viewMode = FILE_VIEW_MODE_PREVIEW;
+ changeViewMode(FILE_VIEW_MODE_PREVIEW);
vm.file.name = 'myfile.md';
vm.file.content = 'hello world';
@@ -423,7 +424,7 @@ describe('RepoEditor', () => {
describe('when file view mode changes to editor', () => {
it('should update dimensions', () => {
- vm.file.viewMode = FILE_VIEW_MODE_EDITOR;
+ changeViewMode(FILE_VIEW_MODE_EDITOR);
return vm.$nextTick().then(() => {
expect(vm.editor.updateDimensions).toHaveBeenCalled();
diff --git a/spec/frontend/ide/components/repo_tab_spec.js b/spec/frontend/ide/components/repo_tab_spec.js
index f35726de27c..a44c8b4d5ee 100644
--- a/spec/frontend/ide/components/repo_tab_spec.js
+++ b/spec/frontend/ide/components/repo_tab_spec.js
@@ -100,6 +100,18 @@ describe('RepoTab', () => {
expect(wrapper.find('.file-modified').exists()).toBe(true);
});
+ it.each`
+ tabProps | closeLabel
+ ${{}} | ${'Close foo.txt'}
+ ${{ changed: true }} | ${'foo.txt changed'}
+ `('close button has label ($closeLabel) with tab ($tabProps)', ({ tabProps, closeLabel }) => {
+ const tab = { ...file('foo.txt'), ...tabProps };
+
+ createComponent({ tab });
+
+ expect(wrapper.find('button').attributes('aria-label')).toBe(closeLabel);
+ });
+
describe('locked file', () => {
let f;
@@ -122,9 +134,7 @@ describe('RepoTab', () => {
});
it('renders a tooltip', () => {
- expect(wrapper.find('span:nth-child(2)').attributes('data-original-title')).toContain(
- 'Locked by testuser',
- );
+ expect(wrapper.find('span:nth-child(2)').attributes('title')).toBe('Locked by testuser');
});
});
diff --git a/spec/frontend/ide/components/terminal/empty_state_spec.js b/spec/frontend/ide/components/terminal/empty_state_spec.js
index a3f2089608d..b62470f67b6 100644
--- a/spec/frontend/ide/components/terminal/empty_state_spec.js
+++ b/spec/frontend/ide/components/terminal/empty_state_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlButton, GlAlert } from '@gitlab/ui';
import { TEST_HOST } from 'spec/test_constants';
import TerminalEmptyState from '~/ide/components/terminal/empty_state.vue';
@@ -36,7 +36,7 @@ describe('IDE TerminalEmptyState', () => {
const img = wrapper.find('.svg-content img');
expect(img.exists()).toBe(true);
- expect(img.attributes('src')).toEqual(TEST_PATH);
+ expect(img.attributes('src')).toBe(TEST_PATH);
});
it('when loading, shows loading icon', () => {
@@ -71,24 +71,23 @@ describe('IDE TerminalEmptyState', () => {
},
});
- button = wrapper.find('button');
+ button = wrapper.find(GlButton);
});
it('shows button', () => {
- expect(button.text()).toEqual('Start Web Terminal');
- expect(button.attributes('disabled')).toBeFalsy();
+ expect(button.text()).toBe('Start Web Terminal');
+ expect(button.props('disabled')).toBe(false);
});
it('emits start when button is clicked', () => {
- expect(wrapper.emitted().start).toBeFalsy();
-
- button.trigger('click');
+ expect(wrapper.emitted().start).toBeUndefined();
+ button.vm.$emit('click');
expect(wrapper.emitted().start).toHaveLength(1);
});
it('shows help path link', () => {
- expect(wrapper.find('a').attributes('href')).toEqual(TEST_HELP_PATH);
+ expect(wrapper.find('a').attributes('href')).toBe(TEST_HELP_PATH);
});
});
@@ -101,7 +100,7 @@ describe('IDE TerminalEmptyState', () => {
},
});
- expect(wrapper.find('button').attributes('disabled')).not.toBe(null);
- expect(wrapper.find('.bs-callout').element.innerHTML).toEqual(TEST_HTML_MESSAGE);
+ expect(wrapper.find(GlButton).props('disabled')).toBe(true);
+ expect(wrapper.find(GlAlert).html()).toContain(TEST_HTML_MESSAGE);
});
});
diff --git a/spec/frontend/ide/helpers.js b/spec/frontend/ide/helpers.js
index 0e85b523cbd..6b65dd96ef4 100644
--- a/spec/frontend/ide/helpers.js
+++ b/spec/frontend/ide/helpers.js
@@ -1,5 +1,6 @@
import * as pathUtils from 'path';
import { decorateData } from '~/ide/stores/utils';
+import { commitActionTypes } from '~/ide/constants';
export const file = (name = 'name', id = name, type = '', parent = null) =>
decorateData({
@@ -28,3 +29,17 @@ export const createEntriesFromPaths = paths =>
...entries,
};
}, {});
+
+export const createTriggerChangeAction = payload => ({
+ type: 'triggerFilesChange',
+ ...(payload ? { payload } : {}),
+});
+
+export const createTriggerRenamePayload = (path, newPath) => ({
+ type: commitActionTypes.move,
+ path,
+ newPath,
+});
+
+export const createTriggerRenameAction = (path, newPath) =>
+ createTriggerChangeAction(createTriggerRenamePayload(path, newPath));
diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js
index 8f7fcc25cf0..cc290fc526e 100644
--- a/spec/frontend/ide/stores/actions/file_spec.js
+++ b/spec/frontend/ide/stores/actions/file_spec.js
@@ -7,7 +7,7 @@ import * as types from '~/ide/stores/mutation_types';
import service from '~/ide/services';
import { createRouter } from '~/ide/ide_router';
import eventHub from '~/ide/eventhub';
-import { file } from '../../helpers';
+import { file, createTriggerRenameAction } from '../../helpers';
const ORIGINAL_CONTENT = 'original content';
const RELATIVE_URL_ROOT = '/gitlab';
@@ -785,13 +785,19 @@ describe('IDE store file actions', () => {
});
describe('triggerFilesChange', () => {
+ const { payload: renamePayload } = createTriggerRenameAction('test', '123');
+
beforeEach(() => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
});
- it('emits event that files have changed', () => {
- return store.dispatch('triggerFilesChange').then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('ide.files.change');
+ it.each`
+ args | payload
+ ${[]} | ${{}}
+ ${[renamePayload]} | ${renamePayload}
+ `('emits event that files have changed (args=$args)', ({ args, payload }) => {
+ return store.dispatch('triggerFilesChange', ...args).then(() => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('ide.files.change', payload);
});
});
});
diff --git a/spec/frontend/ide/stores/actions_spec.js b/spec/frontend/ide/stores/actions_spec.js
index ebf39df2f6f..04128c27e70 100644
--- a/spec/frontend/ide/stores/actions_spec.js
+++ b/spec/frontend/ide/stores/actions_spec.js
@@ -19,7 +19,7 @@ import {
} from '~/ide/stores/actions';
import axios from '~/lib/utils/axios_utils';
import * as types from '~/ide/stores/mutation_types';
-import { file } from '../helpers';
+import { file, createTriggerRenameAction, createTriggerChangeAction } from '../helpers';
import testAction from '../../helpers/vuex_action_helper';
import eventHub from '~/ide/eventhub';
@@ -522,7 +522,7 @@ describe('Multi-file store actions', () => {
'path',
store.state,
[{ type: types.DELETE_ENTRY, payload: 'path' }],
- [{ type: 'stageChange', payload: 'path' }, { type: 'triggerFilesChange' }],
+ [{ type: 'stageChange', payload: 'path' }, createTriggerChangeAction()],
done,
);
});
@@ -551,7 +551,7 @@ describe('Multi-file store actions', () => {
[{ type: types.DELETE_ENTRY, payload: 'testFolder/entry-to-delete' }],
[
{ type: 'stageChange', payload: 'testFolder/entry-to-delete' },
- { type: 'triggerFilesChange' },
+ createTriggerChangeAction(),
],
done,
);
@@ -614,7 +614,7 @@ describe('Multi-file store actions', () => {
testEntry.path,
store.state,
[{ type: types.DELETE_ENTRY, payload: testEntry.path }],
- [{ type: 'stageChange', payload: testEntry.path }, { type: 'triggerFilesChange' }],
+ [{ type: 'stageChange', payload: testEntry.path }, createTriggerChangeAction()],
done,
);
});
@@ -754,7 +754,7 @@ describe('Multi-file store actions', () => {
payload: origEntry,
},
],
- [{ type: 'triggerFilesChange' }],
+ [createTriggerRenameAction('renamed', 'orig')],
done,
);
});
@@ -767,7 +767,7 @@ describe('Multi-file store actions', () => {
{ path: 'orig', name: 'renamed' },
store.state,
[expect.objectContaining({ type: types.RENAME_ENTRY })],
- [{ type: 'triggerFilesChange' }],
+ [createTriggerRenameAction('orig', 'renamed')],
done,
);
});
diff --git a/spec/frontend/ide/stores/modules/editor/actions_spec.js b/spec/frontend/ide/stores/modules/editor/actions_spec.js
new file mode 100644
index 00000000000..6a420ac32de
--- /dev/null
+++ b/spec/frontend/ide/stores/modules/editor/actions_spec.js
@@ -0,0 +1,36 @@
+import testAction from 'helpers/vuex_action_helper';
+import * as types from '~/ide/stores/modules/editor/mutation_types';
+import * as actions from '~/ide/stores/modules/editor/actions';
+import { createTriggerRenamePayload } from '../../../helpers';
+
+describe('~/ide/stores/modules/editor/actions', () => {
+ describe('updateFileEditor', () => {
+ it('commits with payload', () => {
+ const payload = {};
+
+ testAction(actions.updateFileEditor, payload, {}, [
+ { type: types.UPDATE_FILE_EDITOR, payload },
+ ]);
+ });
+ });
+
+ describe('removeFileEditor', () => {
+ it('commits with payload', () => {
+ const payload = 'path/to/file.txt';
+
+ testAction(actions.removeFileEditor, payload, {}, [
+ { type: types.REMOVE_FILE_EDITOR, payload },
+ ]);
+ });
+ });
+
+ describe('renameFileEditor', () => {
+ it('commits with payload', () => {
+ const payload = createTriggerRenamePayload('test', 'test123');
+
+ testAction(actions.renameFileEditor, payload, {}, [
+ { type: types.RENAME_FILE_EDITOR, payload },
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/ide/stores/modules/editor/getters_spec.js b/spec/frontend/ide/stores/modules/editor/getters_spec.js
new file mode 100644
index 00000000000..55e1e31f66f
--- /dev/null
+++ b/spec/frontend/ide/stores/modules/editor/getters_spec.js
@@ -0,0 +1,31 @@
+import { createDefaultFileEditor } from '~/ide/stores/modules/editor/utils';
+import * as getters from '~/ide/stores/modules/editor/getters';
+
+const TEST_PATH = 'test/path.md';
+const TEST_FILE_EDITOR = {
+ ...createDefaultFileEditor(),
+ editorRow: 7,
+ editorColumn: 8,
+ fileLanguage: 'markdown',
+};
+
+describe('~/ide/stores/modules/editor/getters', () => {
+ describe('activeFileEditor', () => {
+ it.each`
+ activeFile | fileEditors | expected
+ ${null} | ${{}} | ${null}
+ ${{}} | ${{}} | ${createDefaultFileEditor()}
+ ${{ path: TEST_PATH }} | ${{}} | ${createDefaultFileEditor()}
+ ${{ path: TEST_PATH }} | ${{ bogus: createDefaultFileEditor(), [TEST_PATH]: TEST_FILE_EDITOR }} | ${TEST_FILE_EDITOR}
+ `(
+ 'with activeFile=$activeFile and fileEditors=$fileEditors',
+ ({ activeFile, fileEditors, expected }) => {
+ const rootGetters = { activeFile };
+ const state = { fileEditors };
+ const result = getters.activeFileEditor(state, {}, {}, rootGetters);
+
+ expect(result).toEqual(expected);
+ },
+ );
+ });
+});
diff --git a/spec/frontend/ide/stores/modules/editor/mutations_spec.js b/spec/frontend/ide/stores/modules/editor/mutations_spec.js
new file mode 100644
index 00000000000..e4b330b3174
--- /dev/null
+++ b/spec/frontend/ide/stores/modules/editor/mutations_spec.js
@@ -0,0 +1,78 @@
+import { createDefaultFileEditor } from '~/ide/stores/modules/editor/utils';
+import * as types from '~/ide/stores/modules/editor/mutation_types';
+import mutations from '~/ide/stores/modules/editor/mutations';
+import { createTriggerRenamePayload } from '../../../helpers';
+
+const TEST_PATH = 'test/path.md';
+
+describe('~/ide/stores/modules/editor/mutations', () => {
+ describe(types.UPDATE_FILE_EDITOR, () => {
+ it('with path that does not exist, should initialize with default values', () => {
+ const state = { fileEditors: {} };
+ const data = { fileLanguage: 'markdown' };
+
+ mutations[types.UPDATE_FILE_EDITOR](state, { path: TEST_PATH, data });
+
+ expect(state.fileEditors).toEqual({
+ [TEST_PATH]: {
+ ...createDefaultFileEditor(),
+ ...data,
+ },
+ });
+ });
+
+ it('with existing path, should overwrite values', () => {
+ const state = {
+ fileEditors: {
+ foo: {},
+ [TEST_PATH]: { ...createDefaultFileEditor(), editorRow: 7, editorColumn: 7 },
+ },
+ };
+
+ mutations[types.UPDATE_FILE_EDITOR](state, {
+ path: TEST_PATH,
+ data: { fileLanguage: 'markdown' },
+ });
+
+ expect(state).toEqual({
+ fileEditors: {
+ foo: {},
+ [TEST_PATH]: {
+ ...createDefaultFileEditor(),
+ editorRow: 7,
+ editorColumn: 7,
+ fileLanguage: 'markdown',
+ },
+ },
+ });
+ });
+ });
+
+ describe(types.REMOVE_FILE_EDITOR, () => {
+ it.each`
+ fileEditors | path | expected
+ ${{}} | ${'does/not/exist.txt'} | ${{}}
+ ${{ foo: {}, [TEST_PATH]: {} }} | ${TEST_PATH} | ${{ foo: {} }}
+ `('removes file $path', ({ fileEditors, path, expected }) => {
+ const state = { fileEditors };
+
+ mutations[types.REMOVE_FILE_EDITOR](state, path);
+
+ expect(state).toEqual({ fileEditors: expected });
+ });
+ });
+
+ describe(types.RENAME_FILE_EDITOR, () => {
+ it.each`
+ fileEditors | payload | expected
+ ${{ foo: {} }} | ${createTriggerRenamePayload('does/not/exist', 'abc')} | ${{ foo: {} }}
+ ${{ foo: { a: 1 }, bar: {} }} | ${createTriggerRenamePayload('foo', 'abc/def')} | ${{ 'abc/def': { a: 1 }, bar: {} }}
+ `('renames fileEditor at $payload', ({ fileEditors, payload, expected }) => {
+ const state = { fileEditors };
+
+ mutations[types.RENAME_FILE_EDITOR](state, payload);
+
+ expect(state).toEqual({ fileEditors: expected });
+ });
+ });
+});
diff --git a/spec/frontend/ide/stores/modules/editor/setup_spec.js b/spec/frontend/ide/stores/modules/editor/setup_spec.js
new file mode 100644
index 00000000000..71b5d7590c5
--- /dev/null
+++ b/spec/frontend/ide/stores/modules/editor/setup_spec.js
@@ -0,0 +1,44 @@
+import Vuex from 'vuex';
+import eventHub from '~/ide/eventhub';
+import { createStoreOptions } from '~/ide/stores';
+import { setupFileEditorsSync } from '~/ide/stores/modules/editor/setup';
+import { createTriggerRenamePayload } from '../../../helpers';
+
+describe('~/ide/stores/modules/editor/setup', () => {
+ let store;
+
+ beforeEach(() => {
+ store = new Vuex.Store(createStoreOptions());
+ store.state.entries = {
+ foo: {},
+ bar: {},
+ };
+ store.state.editor.fileEditors = {
+ foo: {},
+ bizz: {},
+ };
+
+ setupFileEditorsSync(store);
+ });
+
+ it('when files change is emitted, removes unused fileEditors', () => {
+ eventHub.$emit('ide.files.change');
+
+ expect(store.state.entries).toEqual({
+ foo: {},
+ bar: {},
+ });
+ expect(store.state.editor.fileEditors).toEqual({
+ foo: {},
+ });
+ });
+
+ it('when files rename is emitted, renames fileEditor', () => {
+ eventHub.$emit('ide.files.change', createTriggerRenamePayload('foo', 'foo_new'));
+
+ expect(store.state.editor.fileEditors).toEqual({
+ foo_new: {},
+ bizz: {},
+ });
+ });
+});
diff --git a/spec/frontend/ide/stores/mutations/file_spec.js b/spec/frontend/ide/stores/mutations/file_spec.js
index d303de6e9ef..fd39cf21635 100644
--- a/spec/frontend/ide/stores/mutations/file_spec.js
+++ b/spec/frontend/ide/stores/mutations/file_spec.js
@@ -1,6 +1,5 @@
import mutations from '~/ide/stores/mutations/file';
import { createStore } from '~/ide/stores';
-import { FILE_VIEW_MODE_PREVIEW } from '~/ide/constants';
import { file } from '../../helpers';
describe('IDE store file mutations', () => {
@@ -532,17 +531,6 @@ describe('IDE store file mutations', () => {
});
});
- describe('SET_FILE_VIEWMODE', () => {
- it('updates file view mode', () => {
- mutations.SET_FILE_VIEWMODE(localState, {
- file: localFile,
- viewMode: FILE_VIEW_MODE_PREVIEW,
- });
-
- expect(localFile.viewMode).toBe(FILE_VIEW_MODE_PREVIEW);
- });
- });
-
describe('ADD_PENDING_TAB', () => {
beforeEach(() => {
const f = { ...file('openFile'), path: 'openFile', active: true, opened: true };
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 1dbad588ec4..7322c7c1ae1 100644
--- a/spec/frontend/import_projects/components/import_projects_table_spec.js
+++ b/spec/frontend/import_projects/components/import_projects_table_spec.js
@@ -33,7 +33,6 @@ describe('ImportProjectsTable', () => {
const importAllFn = jest.fn();
const importAllModalShowFn = jest.fn();
- const setPageFn = jest.fn();
const fetchReposFn = jest.fn();
function createComponent({
@@ -60,7 +59,6 @@ describe('ImportProjectsTable', () => {
stopJobsPolling: jest.fn(),
clearJobsEtagPoll: jest.fn(),
setFilter: jest.fn(),
- setPage: setPageFn,
},
});
diff --git a/spec/frontend/import_projects/store/actions_spec.js b/spec/frontend/import_projects/store/actions_spec.js
index 6951f2bf04d..06afb20c6a2 100644
--- a/spec/frontend/import_projects/store/actions_spec.js
+++ b/spec/frontend/import_projects/store/actions_spec.js
@@ -16,6 +16,7 @@ import {
RECEIVE_NAMESPACES_SUCCESS,
RECEIVE_NAMESPACES_ERROR,
SET_PAGE,
+ SET_FILTER,
} from '~/import_projects/store/mutation_types';
import actionsFactory from '~/import_projects/store/actions';
import { getImportTarget } from '~/import_projects/store/getters';
@@ -40,7 +41,7 @@ const {
fetchImport,
fetchJobs,
fetchNamespaces,
- setPage,
+ setFilter,
} = actionsFactory({
endpoints,
});
@@ -68,6 +69,7 @@ describe('import_projects store actions', () => {
importStatus: STATUSES.NONE,
},
],
+ provider: 'provider',
};
localState.getImportTarget = getImportTarget(localState);
@@ -149,7 +151,28 @@ describe('import_projects store actions', () => {
);
});
- describe('when /home/xanf/projects/gdk/gitlab/spec/frontend/import_projects/store/actions_spec.jsfiltered', () => {
+ describe('when rate limited', () => {
+ it('commits RECEIVE_REPOS_ERROR and shows rate limited error message', async () => {
+ mock.onGet(`${TEST_HOST}/endpoint.json?filter=filter`).reply(429);
+
+ await testAction(
+ fetchRepos,
+ null,
+ { ...localState, filter: 'filter' },
+ [
+ { type: SET_PAGE, payload: 1 },
+ { type: REQUEST_REPOS },
+ { type: SET_PAGE, payload: 0 },
+ { type: RECEIVE_REPOS_ERROR },
+ ],
+ [],
+ );
+
+ expect(createFlash).toHaveBeenCalledWith('Provider rate limit exceeded. Try again later');
+ });
+ });
+
+ describe('when filtered', () => {
it('fetches repos with filter applied', () => {
mock.onGet(`${TEST_HOST}/endpoint.json?filter=filter`).reply(200, payload);
@@ -359,21 +382,17 @@ describe('import_projects store actions', () => {
],
);
});
+ });
- describe('setPage', () => {
- it('dispatches fetchRepos and commits setPage when page number differs from current one', async () => {
- await testAction(
- setPage,
- 2,
- { ...localState, pageInfo: { page: 1 } },
- [{ type: SET_PAGE, payload: 2 }],
- [{ type: 'fetchRepos' }],
- );
- });
-
- it('does not perform any action if page equals to current one', async () => {
- await testAction(setPage, 2, { ...localState, pageInfo: { page: 2 } }, [], []);
- });
+ describe('setFilter', () => {
+ it('dispatches sets the filter value and dispatches fetchRepos', async () => {
+ await testAction(
+ setFilter,
+ 'filteredRepo',
+ localState,
+ [{ type: SET_FILTER, payload: 'filteredRepo' }],
+ [{ type: 'fetchRepos' }],
+ );
});
});
});
diff --git a/spec/frontend/incidents/components/incidents_list_spec.js b/spec/frontend/incidents/components/incidents_list_spec.js
index 709f66bb352..6329a84ff6e 100644
--- a/spec/frontend/incidents/components/incidents_list_spec.js
+++ b/spec/frontend/incidents/components/incidents_list_spec.js
@@ -10,6 +10,7 @@ import {
TH_CREATED_AT_TEST_ID,
TH_SEVERITY_TEST_ID,
TH_PUBLISHED_TEST_ID,
+ TH_INCIDENT_SLA_TEST_ID,
trackIncidentCreateNewOptions,
trackIncidentListViewsOptions,
} from '~/incidents/constants';
@@ -277,10 +278,11 @@ describe('Incidents List', () => {
const noneSort = 'none';
it.each`
- selector | initialSort | firstSort | nextSort
- ${TH_CREATED_AT_TEST_ID} | ${descSort} | ${ascSort} | ${descSort}
- ${TH_SEVERITY_TEST_ID} | ${noneSort} | ${descSort} | ${ascSort}
- ${TH_PUBLISHED_TEST_ID} | ${noneSort} | ${descSort} | ${ascSort}
+ selector | initialSort | firstSort | nextSort
+ ${TH_CREATED_AT_TEST_ID} | ${descSort} | ${ascSort} | ${descSort}
+ ${TH_SEVERITY_TEST_ID} | ${noneSort} | ${descSort} | ${ascSort}
+ ${TH_PUBLISHED_TEST_ID} | ${noneSort} | ${descSort} | ${ascSort}
+ ${TH_INCIDENT_SLA_TEST_ID} | ${noneSort} | ${ascSort} | ${descSort}
`('updates sort with new direction', async ({ selector, initialSort, firstSort, nextSort }) => {
const [[attr, value]] = Object.entries(selector);
const columnHeader = () => wrapper.find(`[${attr}="${value}"]`);
diff --git a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
index 02f311f579f..b570ab4e844 100644
--- a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
+++ b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
@@ -34,7 +34,7 @@ describe('ConfirmationModal', () => {
'Saving will update the default settings for all projects that are not using custom settings.',
);
expect(findGlModal().text()).toContain(
- 'Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults.',
+ 'Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults.',
);
});
diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js
index efcc727277a..97e77ac87ab 100644
--- a/spec/frontend/integrations/edit/components/integration_form_spec.js
+++ b/spec/frontend/integrations/edit/components/integration_form_spec.js
@@ -5,10 +5,12 @@ import IntegrationForm from '~/integrations/edit/components/integration_form.vue
import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
+import ResetConfirmationModal from '~/integrations/edit/components/reset_confirmation_modal.vue';
import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_fields.vue';
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
+import { integrationLevels } from '~/integrations/edit/constants';
describe('IntegrationForm', () => {
let wrapper;
@@ -43,6 +45,8 @@ describe('IntegrationForm', () => {
const findOverrideDropdown = () => wrapper.find(OverrideDropdown);
const findActiveCheckbox = () => wrapper.find(ActiveCheckbox);
const findConfirmationModal = () => wrapper.find(ConfirmationModal);
+ const findResetConfirmationModal = () => wrapper.find(ResetConfirmationModal);
+ const findResetButton = () => wrapper.find('[data-testid="reset-button"]');
const findJiraTriggerFields = () => wrapper.find(JiraTriggerFields);
const findJiraIssuesFields = () => wrapper.find(JiraIssuesFields);
const findTriggerFields = () => wrapper.find(TriggerFields);
@@ -69,14 +73,70 @@ describe('IntegrationForm', () => {
describe('integrationLevel is instance', () => {
it('renders ConfirmationModal', () => {
createComponent({
- integrationLevel: 'instance',
+ integrationLevel: integrationLevels.INSTANCE,
});
expect(findConfirmationModal().exists()).toBe(true);
});
+
+ describe('resetPath is empty', () => {
+ it('does not render ResetConfirmationModal and button', () => {
+ createComponent({
+ integrationLevel: integrationLevels.INSTANCE,
+ });
+
+ expect(findResetButton().exists()).toBe(false);
+ expect(findResetConfirmationModal().exists()).toBe(false);
+ });
+ });
+
+ describe('resetPath is present', () => {
+ it('renders ResetConfirmationModal and button', () => {
+ createComponent({
+ integrationLevel: integrationLevels.INSTANCE,
+ resetPath: 'resetPath',
+ });
+
+ expect(findResetButton().exists()).toBe(true);
+ expect(findResetConfirmationModal().exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('integrationLevel is group', () => {
+ it('renders ConfirmationModal', () => {
+ createComponent({
+ integrationLevel: integrationLevels.GROUP,
+ });
+
+ expect(findConfirmationModal().exists()).toBe(true);
+ });
+
+ describe('resetPath is empty', () => {
+ it('does not render ResetConfirmationModal and button', () => {
+ createComponent({
+ integrationLevel: integrationLevels.GROUP,
+ });
+
+ expect(findResetButton().exists()).toBe(false);
+ expect(findResetConfirmationModal().exists()).toBe(false);
+ });
+ });
+
+ describe('resetPath is present', () => {
+ it('renders ResetConfirmationModal and button', () => {
+ createComponent({
+ integrationLevel: integrationLevels.GROUP,
+ resetPath: 'resetPath',
+ });
+
+ expect(findResetButton().exists()).toBe(true);
+ expect(findResetConfirmationModal().exists()).toBe(true);
+ });
+ });
});
- describe('integrationLevel is not instance', () => {
+ describe('integrationLevel is project', () => {
it('does not render ConfirmationModal', () => {
createComponent({
integrationLevel: 'project',
@@ -84,6 +144,16 @@ describe('IntegrationForm', () => {
expect(findConfirmationModal().exists()).toBe(false);
});
+
+ it('does not render ResetConfirmationModal and button', () => {
+ createComponent({
+ integrationLevel: 'project',
+ resetPath: 'resetPath',
+ });
+
+ expect(findResetButton().exists()).toBe(false);
+ expect(findResetConfirmationModal().exists()).toBe(false);
+ });
});
describe('type is "slack"', () => {
diff --git a/spec/frontend/integrations/edit/store/actions_spec.js b/spec/frontend/integrations/edit/store/actions_spec.js
index 5356c0a411b..5b5c8d6f76e 100644
--- a/spec/frontend/integrations/edit/store/actions_spec.js
+++ b/spec/frontend/integrations/edit/store/actions_spec.js
@@ -1,6 +1,11 @@
import testAction from 'helpers/vuex_action_helper';
import createState from '~/integrations/edit/store/state';
-import { setOverride } from '~/integrations/edit/store/actions';
+import {
+ setOverride,
+ setIsSaving,
+ setIsTesting,
+ setIsResetting,
+} from '~/integrations/edit/store/actions';
import * as types from '~/integrations/edit/store/mutation_types';
describe('Integration form store actions', () => {
@@ -15,4 +20,24 @@ describe('Integration form store actions', () => {
return testAction(setOverride, true, state, [{ type: types.SET_OVERRIDE, payload: true }]);
});
});
+
+ describe('setIsSaving', () => {
+ it('should commit isSaving mutation', () => {
+ return testAction(setIsSaving, true, state, [{ type: types.SET_IS_SAVING, payload: true }]);
+ });
+ });
+
+ describe('setIsTesting', () => {
+ it('should commit isTesting mutation', () => {
+ return testAction(setIsTesting, true, state, [{ type: types.SET_IS_TESTING, payload: true }]);
+ });
+ });
+
+ describe('setIsResetting', () => {
+ it('should commit isResetting mutation', () => {
+ return testAction(setIsResetting, true, state, [
+ { type: types.SET_IS_RESETTING, payload: true },
+ ]);
+ });
+ });
});
diff --git a/spec/frontend/integrations/edit/store/getters_spec.js b/spec/frontend/integrations/edit/store/getters_spec.js
index 3353e0c84cc..7d4532a1059 100644
--- a/spec/frontend/integrations/edit/store/getters_spec.js
+++ b/spec/frontend/integrations/edit/store/getters_spec.js
@@ -1,5 +1,12 @@
-import { currentKey, isInheriting, propsSource } from '~/integrations/edit/store/getters';
+import {
+ currentKey,
+ isInheriting,
+ isDisabled,
+ propsSource,
+} from '~/integrations/edit/store/getters';
import createState from '~/integrations/edit/store/state';
+import mutations from '~/integrations/edit/store/mutations';
+import * as types from '~/integrations/edit/store/mutation_types';
import { mockIntegrationProps } from '../mock_data';
describe('Integration form store getters', () => {
@@ -45,6 +52,29 @@ describe('Integration form store getters', () => {
});
});
+ describe('isDisabled', () => {
+ it.each`
+ isSaving | isTesting | isResetting | expected
+ ${false} | ${false} | ${false} | ${false}
+ ${true} | ${false} | ${false} | ${true}
+ ${false} | ${true} | ${false} | ${true}
+ ${false} | ${false} | ${true} | ${true}
+ ${false} | ${true} | ${true} | ${true}
+ ${true} | ${false} | ${true} | ${true}
+ ${true} | ${true} | ${false} | ${true}
+ ${true} | ${true} | ${true} | ${true}
+ `(
+ 'when isSaving = $isSaving, isTesting = $isTesting, isResetting = $isResetting then isDisabled = $expected',
+ ({ isSaving, isTesting, isResetting, expected }) => {
+ mutations[types.SET_IS_SAVING](state, isSaving);
+ mutations[types.SET_IS_TESTING](state, isTesting);
+ mutations[types.SET_IS_RESETTING](state, isResetting);
+
+ expect(isDisabled(state)).toBe(expected);
+ },
+ );
+ });
+
describe('propsSource', () => {
beforeEach(() => {
state.defaultState = defaultState;
diff --git a/spec/frontend/integrations/edit/store/mutations_spec.js b/spec/frontend/integrations/edit/store/mutations_spec.js
index 4b733726d44..4707b4b3714 100644
--- a/spec/frontend/integrations/edit/store/mutations_spec.js
+++ b/spec/frontend/integrations/edit/store/mutations_spec.js
@@ -16,4 +16,28 @@ describe('Integration form store mutations', () => {
expect(state.override).toBe(true);
});
});
+
+ describe(`${types.SET_IS_SAVING}`, () => {
+ it('sets isSaving', () => {
+ mutations[types.SET_IS_SAVING](state, true);
+
+ expect(state.isSaving).toBe(true);
+ });
+ });
+
+ describe(`${types.SET_IS_TESTING}`, () => {
+ it('sets isTesting', () => {
+ mutations[types.SET_IS_TESTING](state, true);
+
+ expect(state.isTesting).toBe(true);
+ });
+ });
+
+ describe(`${types.SET_IS_RESETTING}`, () => {
+ it('sets isResetting', () => {
+ mutations[types.SET_IS_RESETTING](state, true);
+
+ expect(state.isResetting).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/integrations/edit/store/state_spec.js b/spec/frontend/integrations/edit/store/state_spec.js
index fc193850a94..4d0f4a1da71 100644
--- a/spec/frontend/integrations/edit/store/state_spec.js
+++ b/spec/frontend/integrations/edit/store/state_spec.js
@@ -7,6 +7,7 @@ describe('Integration form state factory', () => {
customState: {},
isSaving: false,
isTesting: false,
+ isResetting: false,
override: false,
});
});
diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js
index 0be0fbbde2d..4ac2a28105c 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -3,24 +3,31 @@ import { GlDropdown, GlDropdownItem, GlDatepicker, GlSprintf, GlLink } from '@gi
import Api from '~/api';
import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue';
-const groupId = '1';
-const groupName = 'testgroup';
+const id = '1';
+const name = 'testgroup';
+const isProject = false;
const accessLevels = { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 };
const defaultAccessLevel = '10';
const helpLink = 'https://example.com';
-const createComponent = () => {
+const createComponent = (data = {}) => {
return shallowMount(InviteMembersModal, {
propsData: {
- groupId,
- groupName,
+ id,
+ name,
+ isProject,
accessLevels,
defaultAccessLevel,
helpLink,
},
+ data() {
+ return data;
+ },
stubs: {
- GlSprintf,
'gl-modal': '<div><slot name="modal-footer"></slot><slot></slot></div>',
+ 'gl-dropdown': true,
+ 'gl-dropdown-item': true,
+ GlSprintf,
},
});
};
@@ -34,7 +41,7 @@ describe('InviteMembersModal', () => {
});
const findDropdown = () => wrapper.find(GlDropdown);
- const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findDropdownItems = () => findDropdown().findAll(GlDropdownItem);
const findDatepicker = () => wrapper.find(GlDatepicker);
const findLink = () => wrapper.find(GlLink);
const findCancelButton = () => wrapper.find({ ref: 'cancelButton' });
@@ -88,25 +95,69 @@ describe('InviteMembersModal', () => {
format: 'json',
};
- beforeEach(() => {
- wrapper = createComponent();
+ describe('when the invite was sent successfully', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest.spyOn(Api, 'inviteGroupMember').mockResolvedValue({ data: postData });
- jest.spyOn(Api, 'inviteGroupMember').mockResolvedValue({ data: postData });
- wrapper.vm.$toast = { show: jest.fn() };
+ wrapper.vm.submitForm(postData);
+ });
- wrapper.vm.submitForm(postData);
+ it('displays the successful toastMessage', () => {
+ const toastMessageSuccessful = 'Members were successfully added';
+
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
+ toastMessageSuccessful,
+ wrapper.vm.toastOptions,
+ );
+ });
+
+ it('calls Api inviteGroupMember with the correct params', () => {
+ expect(Api.inviteGroupMember).toHaveBeenCalledWith(id, postData);
+ });
});
- it('calls Api inviteGroupMember with the correct params', () => {
- expect(Api.inviteGroupMember).toHaveBeenCalledWith(groupId, postData);
+ describe('when sending the invite for a single member returned an api error', () => {
+ const apiErrorMessage = 'Members already exists';
+
+ beforeEach(() => {
+ wrapper = createComponent({ newUsersToInvite: '123' });
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest
+ .spyOn(Api, 'inviteGroupMember')
+ .mockRejectedValue({ response: { data: { message: apiErrorMessage } } });
+
+ findInviteButton().vm.$emit('click');
+ });
+
+ it('displays the api error message for the toastMessage', () => {
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
+ apiErrorMessage,
+ wrapper.vm.toastOptions,
+ );
+ });
});
- describe('when the invite was sent successfully', () => {
- const toastMessageSuccessful = 'Users were succesfully added';
+ describe('when sending the invite for multiple members returned any error', () => {
+ const genericErrorMessage = 'Some of the members could not be added';
- it('displays the successful toastMessage', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ newUsersToInvite: '123' });
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest
+ .spyOn(Api, 'inviteGroupMember')
+ .mockRejectedValue({ response: { data: { success: false } } });
+
+ findInviteButton().vm.$emit('click');
+ });
+
+ it('displays the expected toastMessage', () => {
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
- toastMessageSuccessful,
+ genericErrorMessage,
wrapper.vm.toastOptions,
);
});
diff --git a/spec/frontend/invite_members/components/members_token_select_spec.js b/spec/frontend/invite_members/components/members_token_select_spec.js
new file mode 100644
index 00000000000..fb0bd6bb195
--- /dev/null
+++ b/spec/frontend/invite_members/components/members_token_select_spec.js
@@ -0,0 +1,112 @@
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { GlTokenSelector } from '@gitlab/ui';
+import waitForPromises from 'helpers/wait_for_promises';
+import Api from '~/api';
+import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
+
+const label = 'testgroup';
+const placeholder = 'Search for a member';
+const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' };
+const user2 = { id: 2, name: 'Name Two', username: 'two_2', avatar_url: '' };
+const allUsers = [user1, user2];
+
+const createComponent = () => {
+ return shallowMount(MembersTokenSelect, {
+ propsData: {
+ ariaLabelledby: label,
+ placeholder,
+ },
+ });
+};
+
+describe('MembersTokenSelect', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ jest.spyOn(Api, 'users').mockResolvedValue({ data: allUsers });
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findTokenSelector = () => wrapper.find(GlTokenSelector);
+
+ describe('rendering the token-selector component', () => {
+ it('renders with the correct props', () => {
+ const expectedProps = {
+ ariaLabelledby: label,
+ placeholder,
+ };
+
+ expect(findTokenSelector().props()).toEqual(expect.objectContaining(expectedProps));
+ });
+ });
+
+ describe('users', () => {
+ describe('when input is focused for the first time (modal auto-focus)', () => {
+ it('does not call the API', async () => {
+ findTokenSelector().vm.$emit('focus');
+
+ await waitForPromises();
+
+ expect(Api.users).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('when input is manually focused', () => {
+ it('calls the API and sets dropdown items as request result', async () => {
+ const tokenSelector = findTokenSelector();
+
+ tokenSelector.vm.$emit('focus');
+ tokenSelector.vm.$emit('blur');
+ tokenSelector.vm.$emit('focus');
+
+ await waitForPromises();
+
+ expect(tokenSelector.props('dropdownItems')).toMatchObject(allUsers);
+ expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
+ });
+ });
+
+ describe('when text input is typed in', () => {
+ it('calls the API with search parameter', async () => {
+ const searchParam = 'One';
+ const tokenSelector = findTokenSelector();
+
+ tokenSelector.vm.$emit('text-input', searchParam);
+
+ await waitForPromises();
+
+ expect(Api.users).toHaveBeenCalledWith(searchParam, wrapper.vm.$options.queryOptions);
+ expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
+ });
+ });
+
+ describe('when user is selected', () => {
+ it('emits `input` event with selected users', () => {
+ findTokenSelector().vm.$emit('input', [
+ { id: 1, name: 'John Smith' },
+ { id: 2, name: 'Jane Doe' },
+ ]);
+
+ expect(wrapper.emitted().input[0][0]).toBe('1,2');
+ });
+ });
+ });
+
+ describe('when text input is blurred', () => {
+ it('clears text input', async () => {
+ const tokenSelector = findTokenSelector();
+
+ tokenSelector.vm.$emit('blur');
+
+ await nextTick();
+
+ expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/issuable/related_issues/components/issue_token_spec.js b/spec/frontend/issuable/related_issues/components/issue_token_spec.js
index f2cb9042ba6..1b4c6b548e2 100644
--- a/spec/frontend/issuable/related_issues/components/issue_token_spec.js
+++ b/spec/frontend/issuable/related_issues/components/issue_token_spec.js
@@ -137,9 +137,7 @@ describe('IssueToken', () => {
});
it('tooltip should not be escaped', () => {
- expect(findRemoveBtn().attributes('data-original-title')).toBe(
- `Remove ${displayReference}`,
- );
+ expect(findRemoveBtn().attributes('aria-label')).toBe(`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
index b758b85beef..dd05f49b458 100644
--- a/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
+++ b/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
@@ -56,7 +56,7 @@ describe('RelatedIssuesBlock', () => {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
},
- slots: { headerText },
+ slots: { 'header-text': headerText },
});
expect(wrapper.find('.card-title').html()).toContain(headerText);
@@ -72,7 +72,7 @@ describe('RelatedIssuesBlock', () => {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
},
- slots: { headerActions },
+ slots: { 'header-actions': headerActions },
});
expect(wrapper.find('[data-testid="custom-button"]').html()).toBe(headerActions);
diff --git a/spec/frontend/issuable_list/components/issuable_bulk_edit_sidebar_spec.js b/spec/frontend/issuable_list/components/issuable_bulk_edit_sidebar_spec.js
new file mode 100644
index 00000000000..52a238eac7c
--- /dev/null
+++ b/spec/frontend/issuable_list/components/issuable_bulk_edit_sidebar_spec.js
@@ -0,0 +1,97 @@
+import { shallowMount } from '@vue/test-utils';
+
+import IssuableBulkEditSidebar from '~/issuable_list/components/issuable_bulk_edit_sidebar.vue';
+
+const createComponent = ({ expanded = true } = {}) =>
+ shallowMount(IssuableBulkEditSidebar, {
+ propsData: {
+ expanded,
+ },
+ slots: {
+ 'bulk-edit-actions': `
+ <button class="js-edit-issuables">Edit issuables</button>
+ `,
+ 'sidebar-items': `
+ <button class="js-sidebar-dropdown">Labels</button>
+ `,
+ },
+ });
+
+describe('IssuableBulkEditSidebar', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ setFixtures('<div class="layout-page right-sidebar-collapsed"></div>');
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('watch', () => {
+ describe('expanded', () => {
+ it.each`
+ expanded | layoutPageClass
+ ${true} | ${'right-sidebar-expanded'}
+ ${false} | ${'right-sidebar-collapsed'}
+ `(
+ 'sets class "$layoutPageClass" on element `.layout-page` when expanded prop is $expanded',
+ async ({ expanded, layoutPageClass }) => {
+ const wrappeCustom = createComponent({
+ expanded: !expanded,
+ });
+
+ // We need to manually flip the value of `expanded` for
+ // watcher to trigger.
+ wrappeCustom.setProps({
+ expanded,
+ });
+
+ await wrappeCustom.vm.$nextTick();
+
+ expect(document.querySelector('.layout-page').classList.contains(layoutPageClass)).toBe(
+ true,
+ );
+
+ wrappeCustom.destroy();
+ },
+ );
+ });
+ });
+
+ describe('template', () => {
+ it.each`
+ expanded | layoutPageClass
+ ${true} | ${'right-sidebar-expanded'}
+ ${false} | ${'right-sidebar-collapsed'}
+ `(
+ 'renders component container with class "$layoutPageClass" when expanded prop is $expanded',
+ async ({ expanded, layoutPageClass }) => {
+ const wrappeCustom = createComponent({
+ expanded: !expanded,
+ });
+
+ // We need to manually flip the value of `expanded` for
+ // watcher to trigger.
+ wrappeCustom.setProps({
+ expanded,
+ });
+
+ await wrappeCustom.vm.$nextTick();
+
+ expect(wrappeCustom.classes()).toContain(layoutPageClass);
+
+ wrappeCustom.destroy();
+ },
+ );
+
+ it('renders contents for slot `bulk-edit-actions`', () => {
+ expect(wrapper.find('button.js-edit-issuables').exists()).toBe(true);
+ });
+
+ it('renders contents for slot `sidebar-items`', () => {
+ expect(wrapper.find('button.js-sidebar-dropdown').exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/issuable_list/components/issuable_item_spec.js b/spec/frontend/issuable_list/components/issuable_item_spec.js
index a96a4e15e6c..3a9a0d3fd59 100644
--- a/spec/frontend/issuable_list/components/issuable_item_spec.js
+++ b/spec/frontend/issuable_list/components/issuable_item_spec.js
@@ -1,29 +1,37 @@
import { shallowMount } from '@vue/test-utils';
-import { GlLink, GlLabel } from '@gitlab/ui';
+import { GlLink, GlLabel, GlIcon, GlFormCheckbox } from '@gitlab/ui';
import IssuableItem from '~/issuable_list/components/issuable_item.vue';
+import IssuableAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
import { mockIssuable, mockRegularLabel, mockScopedLabel } from '../mock_data';
-const createComponent = ({ issuableSymbol = '#', issuable = mockIssuable } = {}) =>
+const createComponent = ({ issuableSymbol = '#', issuable = mockIssuable, slots = {} } = {}) =>
shallowMount(IssuableItem, {
propsData: {
issuableSymbol,
issuable,
+ enableLabelPermalinks: true,
+ showDiscussions: true,
+ showCheckbox: false,
},
+ slots,
});
describe('IssuableItem', () => {
const mockLabels = mockIssuable.labels.nodes;
const mockAuthor = mockIssuable.author;
+ const originalUrl = gon.gitlab_url;
let wrapper;
beforeEach(() => {
+ gon.gitlab_url = 'http://0.0.0.0:3000';
wrapper = createComponent();
});
afterEach(() => {
wrapper.destroy();
+ gon.gitlab_url = originalUrl;
});
describe('computed', () => {
@@ -38,8 +46,8 @@ describe('IssuableItem', () => {
authorId | returnValue
${1} | ${1}
${'1'} | ${1}
- ${'gid://gitlab/User/1'} | ${'1'}
- ${'foo'} | ${''}
+ ${'gid://gitlab/User/1'} | ${1}
+ ${'foo'} | ${null}
`(
'returns $returnValue when value of `issuable.author.id` is $authorId',
async ({ authorId, returnValue }) => {
@@ -60,6 +68,30 @@ describe('IssuableItem', () => {
);
});
+ describe('isIssuableUrlExternal', () => {
+ it.each`
+ issuableWebUrl | urlType | returnValue
+ ${'/gitlab-org/gitlab-test/-/issues/2'} | ${'relative'} | ${false}
+ ${'http://0.0.0.0:3000/gitlab-org/gitlab-test/-/issues/1'} | ${'absolute and internal'} | ${false}
+ ${'http://jira.atlassian.net/browse/IG-1'} | ${'external'} | ${true}
+ ${'https://github.com/gitlabhq/gitlabhq/issues/1'} | ${'external'} | ${true}
+ `(
+ 'returns $returnValue when `issuable.webUrl` is $urlType',
+ async ({ issuableWebUrl, returnValue }) => {
+ wrapper.setProps({
+ issuable: {
+ ...mockIssuable,
+ webUrl: issuableWebUrl,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.isIssuableUrlExternal).toBe(returnValue);
+ },
+ );
+ });
+
describe('labels', () => {
it('returns `issuable.labels.nodes` reference when it is available', () => {
expect(wrapper.vm.labels).toEqual(mockLabels);
@@ -92,6 +124,12 @@ describe('IssuableItem', () => {
});
});
+ describe('assignees', () => {
+ it('returns `issuable.assignees` reference when it is available', () => {
+ expect(wrapper.vm.assignees).toBe(mockIssuable.assignees);
+ });
+ });
+
describe('createdAt', () => {
it('returns string containing timeago string based on `issuable.createdAt`', () => {
expect(wrapper.vm.createdAt).toContain('created');
@@ -105,6 +143,31 @@ describe('IssuableItem', () => {
expect(wrapper.vm.updatedAt).toContain('ago');
});
});
+
+ describe('showDiscussions', () => {
+ it.each`
+ userDiscussionsCount | returnValue
+ ${0} | ${true}
+ ${1} | ${true}
+ ${undefined} | ${false}
+ ${null} | ${false}
+ `(
+ 'returns $returnValue when issuable.userDiscussionsCount is $userDiscussionsCount',
+ ({ userDiscussionsCount, returnValue }) => {
+ const wrapperWithDiscussions = createComponent({
+ issuableSymbol: '#',
+ issuable: {
+ ...mockIssuable,
+ userDiscussionsCount,
+ },
+ });
+
+ expect(wrapperWithDiscussions.vm.showDiscussions).toBe(returnValue);
+
+ wrapperWithDiscussions.destroy();
+ },
+ );
+ });
});
describe('methods', () => {
@@ -120,6 +183,34 @@ describe('IssuableItem', () => {
},
);
});
+
+ describe('labelTitle', () => {
+ it.each`
+ label | propWithTitle | returnValue
+ ${{ title: 'foo' }} | ${'title'} | ${'foo'}
+ ${{ name: 'foo' }} | ${'name'} | ${'foo'}
+ `('returns string value of `label.$propWithTitle`', ({ label, returnValue }) => {
+ expect(wrapper.vm.labelTitle(label)).toBe(returnValue);
+ });
+ });
+
+ describe('labelTarget', () => {
+ it('returns target string for a provided label param when `enableLabelPermalinks` is true', () => {
+ expect(wrapper.vm.labelTarget(mockRegularLabel)).toBe(
+ '?label_name%5B%5D=Documentation%20Update',
+ );
+ });
+
+ it('returns string "#" for a provided label param when `enableLabelPermalinks` is false', async () => {
+ wrapper.setProps({
+ enableLabelPermalinks: false,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.labelTarget(mockRegularLabel)).toBe('#');
+ });
+ });
});
describe('template', () => {
@@ -128,9 +219,47 @@ describe('IssuableItem', () => {
expect(titleEl.exists()).toBe(true);
expect(titleEl.find(GlLink).attributes('href')).toBe(mockIssuable.webUrl);
+ expect(titleEl.find(GlLink).attributes('target')).not.toBeDefined();
expect(titleEl.find(GlLink).text()).toBe(mockIssuable.title);
});
+ it('renders checkbox when `showCheckbox` prop is true', async () => {
+ wrapper.setProps({
+ showCheckbox: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlFormCheckbox).exists()).toBe(true);
+ expect(wrapper.find(GlFormCheckbox).attributes('checked')).not.toBeDefined();
+
+ wrapper.setProps({
+ checked: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlFormCheckbox).attributes('checked')).toBe('true');
+ });
+
+ it('renders issuable title with `target` set as "_blank" when issuable.webUrl is external', async () => {
+ wrapper.setProps({
+ issuable: {
+ ...mockIssuable,
+ webUrl: 'http://jira.atlassian.net/browse/IG-1',
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(
+ wrapper
+ .find('[data-testid="issuable-title"]')
+ .find(GlLink)
+ .attributes('target'),
+ ).toBe('_blank');
+ });
+
it('renders issuable reference', () => {
const referenceEl = wrapper.find('[data-testid="issuable-reference"]');
@@ -138,6 +267,24 @@ describe('IssuableItem', () => {
expect(referenceEl.text()).toBe(`#${mockIssuable.iid}`);
});
+ it('renders issuable reference via slot', () => {
+ const wrapperWithRefSlot = createComponent({
+ issuableSymbol: '#',
+ issuable: mockIssuable,
+ slots: {
+ reference: `
+ <b class="js-reference">${mockIssuable.iid}</b>
+ `,
+ },
+ });
+ const referenceEl = wrapperWithRefSlot.find('.js-reference');
+
+ expect(referenceEl.exists()).toBe(true);
+ expect(referenceEl.text()).toBe(`${mockIssuable.iid}`);
+
+ wrapperWithRefSlot.destroy();
+ });
+
it('renders issuable createdAt info', () => {
const createdAtEl = wrapper.find('[data-testid="issuable-created-at"]');
@@ -151,7 +298,7 @@ describe('IssuableItem', () => {
expect(authorEl.exists()).toBe(true);
expect(authorEl.attributes()).toMatchObject({
- 'data-user-id': wrapper.vm.authorId,
+ 'data-user-id': `${wrapper.vm.authorId}`,
'data-username': mockAuthor.username,
'data-name': mockAuthor.name,
'data-avatar-url': mockAuthor.avatarUrl,
@@ -160,6 +307,42 @@ describe('IssuableItem', () => {
expect(authorEl.text()).toBe(mockAuthor.name);
});
+ it('renders issuable author info via slot', () => {
+ const wrapperWithAuthorSlot = createComponent({
+ issuableSymbol: '#',
+ issuable: mockIssuable,
+ slots: {
+ reference: `
+ <span class="js-author">${mockAuthor.name}</span>
+ `,
+ },
+ });
+ const authorEl = wrapperWithAuthorSlot.find('.js-author');
+
+ expect(authorEl.exists()).toBe(true);
+ expect(authorEl.text()).toBe(mockAuthor.name);
+
+ wrapperWithAuthorSlot.destroy();
+ });
+
+ it('renders timeframe via slot', () => {
+ const wrapperWithTimeframeSlot = createComponent({
+ issuableSymbol: '#',
+ issuable: mockIssuable,
+ slots: {
+ timeframe: `
+ <b class="js-timeframe">Jan 1, 2020 - Mar 31, 2020</b>
+ `,
+ },
+ });
+ const timeframeEl = wrapperWithTimeframeSlot.find('.js-timeframe');
+
+ expect(timeframeEl.exists()).toBe(true);
+ expect(timeframeEl.text()).toBe('Jan 1, 2020 - Mar 31, 2020');
+
+ wrapperWithTimeframeSlot.destroy();
+ });
+
it('renders gl-label component for each label present within `issuable` prop', () => {
const labelsEl = wrapper.findAll(GlLabel);
@@ -170,10 +353,52 @@ describe('IssuableItem', () => {
title: mockLabels[0].title,
description: mockLabels[0].description,
scoped: false,
+ target: wrapper.vm.labelTarget(mockLabels[0]),
size: 'sm',
});
});
+ it('renders issuable status via slot', () => {
+ const wrapperWithStatusSlot = createComponent({
+ issuableSymbol: '#',
+ issuable: mockIssuable,
+ slots: {
+ status: `
+ <b class="js-status">${mockIssuable.state}</b>
+ `,
+ },
+ });
+ const statusEl = wrapperWithStatusSlot.find('.js-status');
+
+ expect(statusEl.exists()).toBe(true);
+ expect(statusEl.text()).toBe(`${mockIssuable.state}`);
+
+ wrapperWithStatusSlot.destroy();
+ });
+
+ it('renders discussions count', () => {
+ const discussionsEl = wrapper.find('[data-testid="issuable-discussions"]');
+
+ expect(discussionsEl.exists()).toBe(true);
+ expect(discussionsEl.find(GlLink).attributes()).toMatchObject({
+ title: 'Comments',
+ href: `${mockIssuable.webUrl}#notes`,
+ });
+ expect(discussionsEl.find(GlIcon).props('name')).toBe('comments');
+ expect(discussionsEl.find(GlLink).text()).toContain('2');
+ });
+
+ it('renders issuable-assignees component', () => {
+ const assigneesEl = wrapper.find(IssuableAssignees);
+
+ expect(assigneesEl.exists()).toBe(true);
+ expect(assigneesEl.props()).toMatchObject({
+ assignees: mockIssuable.assignees,
+ iconSize: 16,
+ maxVisible: 4,
+ });
+ });
+
it('renders issuable updatedAt info', () => {
const updatedAtEl = wrapper.find('[data-testid="issuable-updated-at"]');
diff --git a/spec/frontend/issuable_list/components/issuable_list_root_spec.js b/spec/frontend/issuable_list/components/issuable_list_root_spec.js
index 34184522b55..add5d9e8e2d 100644
--- a/spec/frontend/issuable_list/components/issuable_list_root_spec.js
+++ b/spec/frontend/issuable_list/components/issuable_list_root_spec.js
@@ -1,16 +1,21 @@
import { mount } from '@vue/test-utils';
-import { GlLoadingIcon, GlPagination } from '@gitlab/ui';
+import { GlSkeletonLoading, GlPagination } from '@gitlab/ui';
+
+import { TEST_HOST } from 'helpers/test_constants';
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';
+import { mockIssuableListProps, mockIssuables } from '../mock_data';
-const createComponent = (propsData = mockIssuableListProps) =>
+const createComponent = ({ props = mockIssuableListProps, data = {} } = {}) =>
mount(IssuableListRoot, {
- propsData,
+ propsData: props,
+ data() {
+ return data;
+ },
slots: {
'nav-actions': `
<button class="js-new-issuable">New issuable</button>
@@ -32,6 +37,139 @@ describe('IssuableListRoot', () => {
wrapper.destroy();
});
+ describe('computed', () => {
+ const mockCheckedIssuables = {
+ [mockIssuables[0].iid]: { checked: true, issuable: mockIssuables[0] },
+ [mockIssuables[1].iid]: { checked: true, issuable: mockIssuables[1] },
+ [mockIssuables[2].iid]: { checked: true, issuable: mockIssuables[2] },
+ };
+
+ const mIssuables = [mockIssuables[0], mockIssuables[1], mockIssuables[2]];
+
+ describe('skeletonItemCount', () => {
+ it.each`
+ totalItems | defaultPageSize | currentPage | returnValue
+ ${100} | ${20} | ${1} | ${20}
+ ${105} | ${20} | ${6} | ${5}
+ ${7} | ${20} | ${1} | ${7}
+ ${0} | ${20} | ${1} | ${5}
+ `(
+ 'returns $returnValue when totalItems is $totalItems, defaultPageSize is $defaultPageSize and currentPage is $currentPage',
+ async ({ totalItems, defaultPageSize, currentPage, returnValue }) => {
+ wrapper.setProps({
+ totalItems,
+ defaultPageSize,
+ currentPage,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.skeletonItemCount).toBe(returnValue);
+ },
+ );
+ });
+
+ describe('allIssuablesChecked', () => {
+ it.each`
+ checkedIssuables | issuables | specTitle | returnValue
+ ${mockCheckedIssuables} | ${mIssuables} | ${'same as'} | ${true}
+ ${{}} | ${mIssuables} | ${'not same as'} | ${false}
+ `(
+ 'returns $returnValue when bulkEditIssuables count is $specTitle issuables count',
+ async ({ checkedIssuables, issuables, returnValue }) => {
+ wrapper.setProps({
+ issuables,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ wrapper.setData({
+ checkedIssuables,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.allIssuablesChecked).toBe(returnValue);
+ },
+ );
+ });
+
+ describe('bulkEditIssuables', () => {
+ it('returns array of issuables which have `checked` set to true within checkedIssuables map', async () => {
+ wrapper.setData({
+ checkedIssuables: mockCheckedIssuables,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.bulkEditIssuables).toHaveLength(mIssuables.length);
+ });
+ });
+ });
+
+ describe('watch', () => {
+ describe('issuables', () => {
+ it('populates `checkedIssuables` prop with all issuables', async () => {
+ wrapper.setProps({
+ issuables: [mockIssuables[0]],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(Object.keys(wrapper.vm.checkedIssuables)).toHaveLength(1);
+ expect(wrapper.vm.checkedIssuables[mockIssuables[0].iid]).toEqual({
+ checked: false,
+ issuable: mockIssuables[0],
+ });
+ });
+ });
+
+ describe('urlParams', () => {
+ it('updates window URL reflecting props within `urlParams`', async () => {
+ const urlParams = {
+ state: 'closed',
+ sort: 'updated_asc',
+ page: 1,
+ search: 'foo',
+ };
+
+ wrapper.setProps({
+ urlParams,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(global.window.location.href).toBe(
+ `${TEST_HOST}/?state=${urlParams.state}&sort=${urlParams.sort}&page=${urlParams.page}&search=${urlParams.search}`,
+ );
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('issuableId', () => {
+ it('returns id value from provided issuable object', () => {
+ expect(wrapper.vm.issuableId({ id: 1 })).toBe(1);
+ expect(wrapper.vm.issuableId({ iid: 1 })).toBe(1);
+ expect(wrapper.vm.issuableId({})).toBeDefined();
+ });
+ });
+
+ describe('issuableChecked', () => {
+ it('returns boolean value representing checked status of issuable item', async () => {
+ wrapper.setData({
+ checkedIssuables: {
+ [mockIssuables[0].iid]: { checked: true, issuable: mockIssuables[0] },
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.issuableChecked(mockIssuables[0])).toBe(true);
+ });
+ });
+ });
+
describe('template', () => {
it('renders component container element with class "issuable-list-container"', () => {
expect(wrapper.classes()).toContain('issuable-list-container');
@@ -86,7 +224,7 @@ describe('IssuableListRoot', () => {
await wrapper.vm.$nextTick();
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findAll(GlSkeletonLoading)).toHaveLength(wrapper.vm.skeletonItemCount);
});
it('renders issuable-item component for each item within `issuables` array', () => {
@@ -114,6 +252,7 @@ describe('IssuableListRoot', () => {
it('renders gl-pagination when `showPaginationControls` prop is true', async () => {
wrapper.setProps({
showPaginationControls: true,
+ totalItems: 10,
});
await wrapper.vm.$nextTick();
@@ -125,18 +264,51 @@ describe('IssuableListRoot', () => {
value: 1,
prevPage: 0,
nextPage: 2,
+ totalItems: 10,
align: 'center',
});
});
});
describe('events', () => {
+ let wrapperChecked;
+
+ beforeEach(() => {
+ wrapperChecked = createComponent({
+ data: {
+ checkedIssuables: {
+ [mockIssuables[0].iid]: { checked: true, issuable: mockIssuables[0] },
+ },
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapperChecked.destroy();
+ });
+
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('sets all issuables as checked when filtered-search-bar component emits `checked-input` event', async () => {
+ const searchEl = wrapperChecked.find(FilteredSearchBar);
+
+ searchEl.vm.$emit('checked-input', true);
+
+ await wrapperChecked.vm.$nextTick();
+
+ expect(searchEl.emitted('checked-input')).toBeTruthy();
+ expect(searchEl.emitted('checked-input').length).toBe(1);
+
+ expect(wrapperChecked.vm.checkedIssuables[mockIssuables[0].iid]).toEqual({
+ checked: true,
+ issuable: mockIssuables[0],
+ });
+ });
+
it('filtered-search-bar component emits `filter` event on `onFilter` & `sort` event on `onSort` events', () => {
const searchEl = wrapper.find(FilteredSearchBar);
@@ -146,6 +318,22 @@ describe('IssuableListRoot', () => {
expect(wrapper.emitted('sort')).toBeTruthy();
});
+ it('sets an issuable as checked when issuable-item component emits `checked-input` event', async () => {
+ const issuableItem = wrapperChecked.findAll(IssuableItem).at(0);
+
+ issuableItem.vm.$emit('checked-input', true);
+
+ await wrapperChecked.vm.$nextTick();
+
+ expect(issuableItem.emitted('checked-input')).toBeTruthy();
+ expect(issuableItem.emitted('checked-input').length).toBe(1);
+
+ expect(wrapperChecked.vm.checkedIssuables[mockIssuables[0].iid]).toEqual({
+ checked: true,
+ issuable: mockIssuables[0],
+ });
+ });
+
it('gl-pagination component emits `page-change` event on `input` event', async () => {
wrapper.setProps({
showPaginationControls: true,
diff --git a/spec/frontend/issuable_list/mock_data.js b/spec/frontend/issuable_list/mock_data.js
index 8eab2ca6f94..e19a337473a 100644
--- a/spec/frontend/issuable_list/mock_data.js
+++ b/spec/frontend/issuable_list/mock_data.js
@@ -51,6 +51,8 @@ export const mockIssuable = {
labels: {
nodes: mockLabels,
},
+ assignees: [mockAuthor],
+ userDiscussionsCount: 2,
};
export const mockIssuables = [
diff --git a/spec/frontend/issue_show/components/app_spec.js b/spec/frontend/issue_show/components/app_spec.js
index f4095d4de96..dde4e8458d5 100644
--- a/spec/frontend/issue_show/components/app_spec.js
+++ b/spec/frontend/issue_show/components/app_spec.js
@@ -17,6 +17,7 @@ import {
import IncidentTabs from '~/issue_show/components/incidents/incident_tabs.vue';
import DescriptionComponent from '~/issue_show/components/description.vue';
import PinnedLinks from '~/issue_show/components/pinned_links.vue';
+import { IssuableStatus, IssuableStatusText } from '~/issue_show/constants';
function formatText(text) {
return text.trim().replace(/\s\s+/g, ' ');
@@ -36,6 +37,10 @@ describe('Issuable output', () => {
const findStickyHeader = () => wrapper.find('[data-testid="issue-sticky-header"]');
+ const findLockedBadge = () => wrapper.find('[data-testid="locked"]');
+
+ const findConfidentialBadge = () => wrapper.find('[data-testid="confidential"]');
+
const mountComponent = (props = {}, options = {}) => {
wrapper = mount(IssuableApp, {
propsData: { ...appProps, ...props },
@@ -532,7 +537,7 @@ describe('Issuable output', () => {
describe('sticky header', () => {
describe('when title is in view', () => {
it('is not shown', () => {
- expect(wrapper.find('.issue-sticky-header').exists()).toBe(false);
+ expect(findStickyHeader().exists()).toBe(false);
});
});
@@ -542,24 +547,45 @@ describe('Issuable output', () => {
wrapper.find(GlIntersectionObserver).vm.$emit('disappear');
});
- it('is shown with title', () => {
+ it('shows with title', () => {
expect(findStickyHeader().text()).toContain('Sticky header title');
});
- it('is shown with Open when status is opened', () => {
- wrapper.setProps({ issuableStatus: 'opened' });
+ it.each`
+ title | state
+ ${'shows with Open when status is opened'} | ${IssuableStatus.Open}
+ ${'shows with Closed when status is closed'} | ${IssuableStatus.Closed}
+ ${'shows with Open when status is reopened'} | ${IssuableStatus.Reopened}
+ `('$title', async ({ state }) => {
+ wrapper.setProps({ issuableStatus: state });
- return wrapper.vm.$nextTick(() => {
- expect(findStickyHeader().text()).toContain('Open');
- });
+ await wrapper.vm.$nextTick();
+
+ expect(findStickyHeader().text()).toContain(IssuableStatusText[state]);
});
- it('is shown with Closed when status is closed', () => {
- wrapper.setProps({ issuableStatus: 'closed' });
+ it.each`
+ title | isConfidential
+ ${'does not show confidential badge when issue is not confidential'} | ${true}
+ ${'shows confidential badge when issue is confidential'} | ${false}
+ `('$title', async ({ isConfidential }) => {
+ wrapper.setProps({ isConfidential });
- return wrapper.vm.$nextTick(() => {
- expect(findStickyHeader().text()).toContain('Closed');
- });
+ await wrapper.vm.$nextTick();
+
+ expect(findConfidentialBadge().exists()).toBe(isConfidential);
+ });
+
+ it.each`
+ title | isLocked
+ ${'does not show locked badge when issue is not locked'} | ${true}
+ ${'shows locked badge when issue is locked'} | ${false}
+ `('$title', async ({ isLocked }) => {
+ wrapper.setProps({ isLocked });
+
+ await wrapper.vm.$nextTick();
+
+ expect(findLockedBadge().exists()).toBe(isLocked);
});
});
});
diff --git a/spec/frontend/issue_show/components/header_actions_spec.js b/spec/frontend/issue_show/components/header_actions_spec.js
new file mode 100644
index 00000000000..67b8665a889
--- /dev/null
+++ b/spec/frontend/issue_show/components/header_actions_spec.js
@@ -0,0 +1,328 @@
+import { GlButton, GlDropdown, GlDropdownItem, GlLink, GlModal } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
+import createFlash, { FLASH_TYPES } from '~/flash';
+import { IssuableType } from '~/issuable_show/constants';
+import HeaderActions from '~/issue_show/components/header_actions.vue';
+import { IssuableStatus, IssueStateEvent } from '~/issue_show/constants';
+import promoteToEpicMutation from '~/issue_show/queries/promote_to_epic.mutation.graphql';
+import * as urlUtility from '~/lib/utils/url_utility';
+import createStore from '~/notes/stores';
+
+jest.mock('~/flash');
+
+describe('HeaderActions component', () => {
+ let dispatchEventSpy;
+ let mutateMock;
+ let wrapper;
+ let visitUrlSpy;
+
+ const localVue = createLocalVue();
+ localVue.use(Vuex);
+ const store = createStore();
+
+ const defaultProps = {
+ canCreateIssue: true,
+ canPromoteToEpic: true,
+ canReopenIssue: true,
+ canReportSpam: true,
+ canUpdateIssue: true,
+ iid: '32',
+ isIssueAuthor: true,
+ issueType: IssuableType.Issue,
+ newIssuePath: 'gitlab-org/gitlab-test/-/issues/new',
+ projectPath: 'gitlab-org/gitlab-test',
+ reportAbusePath:
+ '-/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%2Fgitlab-org%2Fgitlab-test%2F-%2Fissues%2F32&user_id=1',
+ submitAsSpamPath: 'gitlab-org/gitlab-test/-/issues/32/submit_as_spam',
+ };
+
+ const updateIssueMutationResponse = { data: { updateIssue: { errors: [] } } };
+
+ const promoteToEpicMutationResponse = {
+ data: {
+ promoteToEpic: {
+ errors: [],
+ epic: {
+ webPath: '/groups/gitlab-org/-/epics/1',
+ },
+ },
+ },
+ };
+
+ const promoteToEpicMutationErrorResponse = {
+ data: {
+ promoteToEpic: {
+ errors: ['The issue has already been promoted to an epic.'],
+ epic: {},
+ },
+ },
+ };
+
+ const findToggleIssueStateButton = () => wrapper.find(GlButton);
+
+ const findDropdownAt = index => wrapper.findAll(GlDropdown).at(index);
+
+ const findMobileDropdownItems = () => findDropdownAt(0).findAll(GlDropdownItem);
+
+ const findDesktopDropdownItems = () => findDropdownAt(1).findAll(GlDropdownItem);
+
+ const findModal = () => wrapper.find(GlModal);
+
+ const findModalLinkAt = index =>
+ findModal()
+ .findAll(GlLink)
+ .at(index);
+
+ const mountComponent = ({
+ props = {},
+ issueState = IssuableStatus.Open,
+ blockedByIssues = [],
+ mutateResponse = {},
+ } = {}) => {
+ mutateMock = jest.fn().mockResolvedValue(mutateResponse);
+
+ store.getters.getNoteableData.state = issueState;
+ store.getters.getNoteableData.blocked_by_issues = blockedByIssues;
+
+ return shallowMount(HeaderActions, {
+ localVue,
+ store,
+ provide: {
+ ...defaultProps,
+ ...props,
+ },
+ mocks: {
+ $apollo: {
+ mutate: mutateMock,
+ },
+ },
+ });
+ };
+
+ afterEach(() => {
+ if (dispatchEventSpy) {
+ dispatchEventSpy.mockRestore();
+ }
+ if (visitUrlSpy) {
+ visitUrlSpy.mockRestore();
+ }
+ wrapper.destroy();
+ });
+
+ describe.each`
+ issueType
+ ${IssuableType.Issue}
+ ${IssuableType.Incident}
+ `('when issue type is $issueType', ({ issueType }) => {
+ describe('close/reopen button', () => {
+ describe.each`
+ description | issueState | buttonText | newIssueState
+ ${`when the ${issueType} is open`} | ${IssuableStatus.Open} | ${`Close ${issueType}`} | ${IssueStateEvent.Close}
+ ${`when the ${issueType} is closed`} | ${IssuableStatus.Closed} | ${`Reopen ${issueType}`} | ${IssueStateEvent.Reopen}
+ `('$description', ({ issueState, buttonText, newIssueState }) => {
+ beforeEach(() => {
+ dispatchEventSpy = jest.spyOn(document, 'dispatchEvent');
+
+ wrapper = mountComponent({
+ props: { issueType },
+ issueState,
+ mutateResponse: updateIssueMutationResponse,
+ });
+ });
+
+ it(`has text "${buttonText}"`, () => {
+ expect(findToggleIssueStateButton().text()).toBe(buttonText);
+ });
+
+ it('calls apollo mutation', () => {
+ findToggleIssueStateButton().vm.$emit('click');
+
+ expect(mutateMock).toHaveBeenCalledWith(
+ expect.objectContaining({
+ variables: {
+ input: {
+ iid: defaultProps.iid,
+ projectPath: defaultProps.projectPath,
+ stateEvent: newIssueState,
+ },
+ },
+ }),
+ );
+ });
+
+ it('dispatches a custom event to update the issue page', async () => {
+ findToggleIssueStateButton().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(dispatchEventSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+ });
+
+ describe.each`
+ description | isCloseIssueItemVisible | findDropdownItems
+ ${'mobile dropdown'} | ${true} | ${findMobileDropdownItems}
+ ${'desktop dropdown'} | ${false} | ${findDesktopDropdownItems}
+ `('$description', ({ isCloseIssueItemVisible, findDropdownItems }) => {
+ describe.each`
+ description | itemText | isItemVisible | canUpdateIssue | canCreateIssue | isIssueAuthor | canReportSpam | canPromoteToEpic
+ ${`when user can update ${issueType}`} | ${`Close ${issueType}`} | ${isCloseIssueItemVisible} | ${true} | ${true} | ${true} | ${true} | ${true}
+ ${`when user cannot update ${issueType}`} | ${`Close ${issueType}`} | ${false} | ${false} | ${true} | ${true} | ${true} | ${true}
+ ${`when user can create ${issueType}`} | ${`New ${issueType}`} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
+ ${`when user cannot create ${issueType}`} | ${`New ${issueType}`} | ${false} | ${true} | ${false} | ${true} | ${true} | ${true}
+ ${'when user can promote to epic'} | ${'Promote to epic'} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
+ ${'when user cannot promote to epic'} | ${'Promote to epic'} | ${false} | ${true} | ${true} | ${true} | ${true} | ${false}
+ ${'when user can report abuse'} | ${'Report abuse'} | ${true} | ${true} | ${true} | ${false} | ${true} | ${true}
+ ${'when user cannot report abuse'} | ${'Report abuse'} | ${false} | ${true} | ${true} | ${true} | ${true} | ${true}
+ ${'when user can submit as spam'} | ${'Submit as spam'} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
+ ${'when user cannot submit as spam'} | ${'Submit as spam'} | ${false} | ${true} | ${true} | ${true} | ${false} | ${true}
+ `(
+ '$description',
+ ({
+ itemText,
+ isItemVisible,
+ canUpdateIssue,
+ canCreateIssue,
+ isIssueAuthor,
+ canReportSpam,
+ canPromoteToEpic,
+ }) => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ props: {
+ canUpdateIssue,
+ canCreateIssue,
+ isIssueAuthor,
+ issueType,
+ canReportSpam,
+ canPromoteToEpic,
+ },
+ });
+ });
+
+ it(`${isItemVisible ? 'shows' : 'hides'} "${itemText}" item`, () => {
+ expect(
+ findDropdownItems()
+ .filter(item => item.text() === itemText)
+ .exists(),
+ ).toBe(isItemVisible);
+ });
+ },
+ );
+ });
+ });
+
+ describe('when "Promote to epic" button is clicked', () => {
+ describe('when response is successful', () => {
+ beforeEach(() => {
+ visitUrlSpy = jest.spyOn(urlUtility, 'visitUrl').mockReturnValue({});
+
+ wrapper = mountComponent({
+ mutateResponse: promoteToEpicMutationResponse,
+ });
+
+ wrapper.find('[data-testid="promote-button"]').vm.$emit('click');
+ });
+
+ it('invokes GraphQL mutation when clicked', () => {
+ expect(mutateMock).toHaveBeenCalledWith(
+ expect.objectContaining({
+ mutation: promoteToEpicMutation,
+ variables: {
+ input: {
+ iid: defaultProps.iid,
+ projectPath: defaultProps.projectPath,
+ },
+ },
+ }),
+ );
+ });
+
+ it('shows a success message and tells the user they are being redirected', () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'The issue was successfully promoted to an epic. Redirecting to epic...',
+ type: FLASH_TYPES.SUCCESS,
+ });
+ });
+
+ it('redirects to newly created epic path', () => {
+ expect(visitUrlSpy).toHaveBeenCalledWith(
+ promoteToEpicMutationResponse.data.promoteToEpic.epic.webPath,
+ );
+ });
+ });
+
+ describe('when response contains errors', () => {
+ beforeEach(() => {
+ visitUrlSpy = jest.spyOn(urlUtility, 'visitUrl').mockReturnValue({});
+
+ wrapper = mountComponent({
+ mutateResponse: promoteToEpicMutationErrorResponse,
+ });
+
+ wrapper.find('[data-testid="promote-button"]').vm.$emit('click');
+ });
+
+ it('shows an error message', () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: promoteToEpicMutationErrorResponse.data.promoteToEpic.errors.join('; '),
+ });
+ });
+ });
+ });
+
+ describe('modal', () => {
+ const blockedByIssues = [
+ { iid: 13, web_url: 'gitlab-org/gitlab-test/-/issues/13' },
+ { iid: 79, web_url: 'gitlab-org/gitlab-test/-/issues/79' },
+ ];
+
+ beforeEach(() => {
+ wrapper = mountComponent({ blockedByIssues });
+ });
+
+ it('has title text', () => {
+ expect(findModal().attributes('title')).toBe(
+ 'Are you sure you want to close this blocked issue?',
+ );
+ });
+
+ it('has body text', () => {
+ expect(findModal().text()).toContain(
+ 'This issue is currently blocked by the following issues:',
+ );
+ });
+
+ it('calls apollo mutation when primary button is clicked', () => {
+ findModal().vm.$emit('primary');
+
+ expect(mutateMock).toHaveBeenCalledWith(
+ expect.objectContaining({
+ variables: {
+ input: {
+ iid: defaultProps.iid.toString(),
+ projectPath: defaultProps.projectPath,
+ stateEvent: IssueStateEvent.Close,
+ },
+ },
+ }),
+ );
+ });
+
+ describe.each`
+ ordinal | index
+ ${'first'} | ${0}
+ ${'second'} | ${1}
+ `('$ordinal blocked-by issue link', ({ index }) => {
+ it('has link text', () => {
+ expect(findModalLinkAt(index).text()).toBe(`#${blockedByIssues[index].iid}`);
+ });
+
+ it('has url', () => {
+ expect(findModalLinkAt(index).attributes('href')).toBe(blockedByIssues[index].web_url);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issue_show/issue_spec.js b/spec/frontend/issue_show/issue_spec.js
index c0175e774a2..7a48353af94 100644
--- a/spec/frontend/issue_show/issue_spec.js
+++ b/spec/frontend/issue_show/issue_spec.js
@@ -2,9 +2,10 @@ 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 { initIssuableApp } from '~/issue_show/issue';
import * as parseData from '~/issue_show/utils/parse_data';
import { appProps } from './mock_data';
+import createStore from '~/notes/stores';
const mock = new MockAdapter(axios);
mock.onGet().reply(200);
@@ -30,7 +31,7 @@ describe('Issue show index', () => {
});
const issuableData = parseData.parseIssuableData();
- initIssuableApp(issuableData);
+ initIssuableApp(issuableData, createStore());
await waitForPromises();
diff --git a/spec/frontend/issues_list/components/issuable_spec.js b/spec/frontend/issues_list/components/issuable_spec.js
index c20684cc385..6e584152551 100644
--- a/spec/frontend/issues_list/components/issuable_spec.js
+++ b/spec/frontend/issues_list/components/issuable_spec.js
@@ -38,7 +38,7 @@ describe('Issuable component', () => {
let DateOrig;
let wrapper;
- const factory = (props = {}, scopedLabels = false) => {
+ const factory = (props = {}, scopedLabelsAvailable = false) => {
wrapper = shallowMount(Issuable, {
propsData: {
issuable: simpleIssue,
@@ -46,9 +46,7 @@ describe('Issuable component', () => {
...props,
},
provide: {
- glFeatures: {
- scopedLabels,
- },
+ scopedLabelsAvailable,
},
stubs: {
'gl-sprintf': GlSprintf,
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 cd0266068aa..fe6d9a34078 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
@@ -91,6 +91,8 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
>
<!---->
+ <!---->
+
<span
class="gl-new-dropdown-button-text"
>
@@ -98,6 +100,7 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
</span>
<svg
+ aria-hidden="true"
class="gl-button-icon dropdown-chevron gl-icon s16"
data-testid="chevron-down-icon"
>
@@ -202,6 +205,8 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
>
<!---->
+ <!---->
+
<span
class="gl-new-dropdown-button-text"
>
@@ -209,6 +214,7 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
</span>
<svg
+ aria-hidden="true"
class="gl-button-icon dropdown-chevron gl-icon s16"
data-testid="chevron-down-icon"
>
diff --git a/spec/frontend/jobs/components/job_retry_forward_deployment_modal_spec.js b/spec/frontend/jobs/components/job_retry_forward_deployment_modal_spec.js
new file mode 100644
index 00000000000..08973223c08
--- /dev/null
+++ b/spec/frontend/jobs/components/job_retry_forward_deployment_modal_spec.js
@@ -0,0 +1,76 @@
+import { GlLink, GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import JobRetryForwardDeploymentModal from '~/jobs/components/job_retry_forward_deployment_modal.vue';
+import { JOB_RETRY_FORWARD_DEPLOYMENT_MODAL } from '~/jobs/constants';
+import createStore from '~/jobs/store';
+import job from '../mock_data';
+
+describe('Job Retry Forward Deployment Modal', () => {
+ let store;
+ let wrapper;
+
+ const retryOutdatedJobDocsUrl = 'url-to-docs';
+ const findLink = () => wrapper.find(GlLink);
+ const findModal = () => wrapper.find(GlModal);
+
+ const createWrapper = ({ props = {}, provide = {}, stubs = {} } = {}) => {
+ store = createStore();
+ wrapper = shallowMount(JobRetryForwardDeploymentModal, {
+ propsData: {
+ modalId: 'modal-id',
+ href: job.retry_path,
+ ...props,
+ },
+ provide,
+ store,
+ stubs,
+ });
+ };
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ beforeEach(createWrapper);
+
+ describe('Modal configuration', () => {
+ it('should display the correct messages', () => {
+ const modal = findModal();
+ expect(modal.attributes('title')).toMatch(JOB_RETRY_FORWARD_DEPLOYMENT_MODAL.title);
+ expect(modal.text()).toMatch(JOB_RETRY_FORWARD_DEPLOYMENT_MODAL.info);
+ expect(modal.text()).toMatch(JOB_RETRY_FORWARD_DEPLOYMENT_MODAL.areYouSure);
+ });
+ });
+
+ describe('Modal docs help link', () => {
+ it('should not display an info link when none is provided', () => {
+ createWrapper();
+
+ expect(findLink().exists()).toBe(false);
+ });
+
+ it('should display an info link when one is provided', () => {
+ createWrapper({ provide: { retryOutdatedJobDocsUrl } });
+
+ expect(findLink().attributes('href')).toBe(retryOutdatedJobDocsUrl);
+ expect(findLink().text()).toMatch(JOB_RETRY_FORWARD_DEPLOYMENT_MODAL.moreInfo);
+ });
+ });
+
+ describe('Modal actions', () => {
+ beforeEach(createWrapper);
+
+ it('should correctly configure the primary action', () => {
+ expect(findModal().props('actionPrimary').attributes).toMatchObject([
+ {
+ 'data-method': 'post',
+ href: job.retry_path,
+ variant: 'danger',
+ },
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/jobs/components/job_sidebar_details_container_spec.js b/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
new file mode 100644
index 00000000000..be684769b46
--- /dev/null
+++ b/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
@@ -0,0 +1,132 @@
+import { shallowMount } from '@vue/test-utils';
+import SidebarJobDetailsContainer from '~/jobs/components/sidebar_job_details_container.vue';
+import DetailRow from '~/jobs/components/sidebar_detail_row.vue';
+import createStore from '~/jobs/store';
+import { extendedWrapper } from '../../helpers/vue_test_utils_helper';
+import job from '../mock_data';
+
+describe('Job Sidebar Details Container', () => {
+ let store;
+ let wrapper;
+
+ const findJobTimeout = () => wrapper.findByTestId('job-timeout');
+ const findJobTags = () => wrapper.findByTestId('job-tags');
+ const findAllDetailsRow = () => wrapper.findAll(DetailRow);
+
+ const createWrapper = ({ props = {} } = {}) => {
+ store = createStore();
+ wrapper = extendedWrapper(
+ shallowMount(SidebarJobDetailsContainer, {
+ propsData: props,
+ store,
+ stubs: {
+ DetailRow,
+ },
+ }),
+ );
+ };
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('when no details are available', () => {
+ it('should render an empty container', () => {
+ createWrapper();
+
+ expect(wrapper.isEmpty()).toBe(true);
+ });
+ });
+
+ describe('when some of the details are available', () => {
+ beforeEach(createWrapper);
+
+ it.each([
+ ['duration', 'Duration: 6 seconds'],
+ ['erased_at', 'Erased: 3 weeks ago'],
+ ['finished_at', 'Finished: 3 weeks ago'],
+ ['queued', 'Queued: 9 seconds'],
+ ['runner', 'Runner: local ci runner (#1)'],
+ ['coverage', 'Coverage: 20%'],
+ ])('uses %s to render job-%s', async (detail, value) => {
+ await store.dispatch('receiveJobSuccess', { [detail]: job[detail] });
+ const detailsRow = findAllDetailsRow();
+
+ expect(wrapper.isEmpty()).toBe(false);
+ expect(detailsRow).toHaveLength(1);
+ expect(detailsRow.at(0).text()).toBe(value);
+ });
+
+ it('only renders tags', async () => {
+ const { tags } = job;
+ await store.dispatch('receiveJobSuccess', { tags });
+ const tagsComponent = findJobTags();
+
+ expect(wrapper.isEmpty()).toBe(false);
+ expect(tagsComponent.text()).toBe('Tags: tag');
+ });
+ });
+
+ describe('when all the info are available', () => {
+ it('renders all the details components', async () => {
+ createWrapper();
+ await store.dispatch('receiveJobSuccess', job);
+
+ expect(findAllDetailsRow()).toHaveLength(7);
+ });
+ });
+
+ describe('timeout', () => {
+ const {
+ metadata: { timeout_human_readable, timeout_source },
+ } = job;
+
+ beforeEach(createWrapper);
+
+ it('does not render if metadata is empty', async () => {
+ const metadata = {};
+ await store.dispatch('receiveJobSuccess', { metadata });
+ const detailsRow = findAllDetailsRow();
+
+ expect(wrapper.isEmpty()).toBe(true);
+ expect(detailsRow.exists()).toBe(false);
+ });
+
+ it('uses metadata to render timeout', async () => {
+ const metadata = { timeout_human_readable };
+ await store.dispatch('receiveJobSuccess', { metadata });
+ const detailsRow = findAllDetailsRow();
+
+ expect(wrapper.isEmpty()).toBe(false);
+ expect(detailsRow).toHaveLength(1);
+ expect(detailsRow.at(0).text()).toBe('Timeout: 1m 40s');
+ });
+
+ it('uses metadata to render timeout and the source', async () => {
+ const metadata = { timeout_human_readable, timeout_source };
+ await store.dispatch('receiveJobSuccess', { metadata });
+ const detailsRow = findAllDetailsRow();
+
+ expect(detailsRow.at(0).text()).toBe('Timeout: 1m 40s (from runner)');
+ });
+
+ it('should not render when no time is provided', async () => {
+ const metadata = { timeout_source };
+ await store.dispatch('receiveJobSuccess', { metadata });
+
+ expect(findJobTimeout().exists()).toBe(false);
+ });
+
+ it('should pass the help URL', async () => {
+ const helpUrl = 'fakeUrl';
+ const props = { runnerHelpUrl: helpUrl };
+ createWrapper({ props });
+ await store.dispatch('receiveJobSuccess', { metadata: { timeout_human_readable } });
+
+ expect(findJobTimeout().props('helpUrl')).toBe(helpUrl);
+ });
+ });
+});
diff --git a/spec/frontend/jobs/components/job_sidebar_retry_button_spec.js b/spec/frontend/jobs/components/job_sidebar_retry_button_spec.js
new file mode 100644
index 00000000000..4bf697ab7cc
--- /dev/null
+++ b/spec/frontend/jobs/components/job_sidebar_retry_button_spec.js
@@ -0,0 +1,70 @@
+import { GlButton, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import job from '../mock_data';
+import JobsSidebarRetryButton from '~/jobs/components/job_sidebar_retry_button.vue';
+import createStore from '~/jobs/store';
+
+describe('Job Sidebar Retry Button', () => {
+ let store;
+ let wrapper;
+
+ const forwardDeploymentFailure = 'forward_deployment_failure';
+ const findRetryButton = () => wrapper.find(GlButton);
+ const findRetryLink = () => wrapper.find(GlLink);
+
+ const createWrapper = ({ props = {} } = {}) => {
+ store = createStore();
+ wrapper = shallowMount(JobsSidebarRetryButton, {
+ propsData: {
+ href: job.retry_path,
+ modalId: 'modal-id',
+ ...props,
+ },
+ store,
+ });
+ };
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ beforeEach(createWrapper);
+
+ it.each([
+ [null, false, true],
+ ['unmet_prerequisites', false, true],
+ [forwardDeploymentFailure, true, false],
+ ])(
+ 'when error is: %s, should render button: %s | should render link: %s',
+ async (failureReason, buttonExists, linkExists) => {
+ await store.dispatch('receiveJobSuccess', { ...job, failure_reason: failureReason });
+
+ expect(findRetryButton().exists()).toBe(buttonExists);
+ expect(findRetryLink().exists()).toBe(linkExists);
+ expect(wrapper.text()).toMatch('Retry');
+ },
+ );
+
+ describe('Button', () => {
+ it('should have the correct configuration', async () => {
+ await store.dispatch('receiveJobSuccess', { failure_reason: forwardDeploymentFailure });
+
+ expect(findRetryButton().attributes()).toMatchObject({
+ category: 'primary',
+ variant: 'info',
+ });
+ });
+ });
+
+ describe('Link', () => {
+ it('should have the correct configuration', () => {
+ expect(findRetryLink().attributes()).toMatchObject({
+ 'data-method': 'post',
+ href: job.retry_path,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/jobs/components/log/line_spec.js b/spec/frontend/jobs/components/log/line_spec.js
index c2412a807c3..314b23ec29b 100644
--- a/spec/frontend/jobs/components/log/line_spec.js
+++ b/spec/frontend/jobs/components/log/line_spec.js
@@ -2,21 +2,26 @@ import { shallowMount } from '@vue/test-utils';
import Line from '~/jobs/components/log/line.vue';
import LineNumber from '~/jobs/components/log/line_number.vue';
+const httpUrl = 'http://example.com';
+const httpsUrl = 'https://example.com';
+
+const mockProps = ({ text = 'Running with gitlab-runner 12.1.0 (de7731dd)' } = {}) => ({
+ line: {
+ content: [
+ {
+ text,
+ style: 'term-fg-l-green',
+ },
+ ],
+ lineNumber: 0,
+ },
+ path: '/jashkenas/underscore/-/jobs/335',
+});
+
describe('Job Log Line', () => {
let wrapper;
-
- const data = {
- line: {
- content: [
- {
- text: 'Running with gitlab-runner 12.1.0 (de7731dd)',
- style: 'term-fg-l-green',
- },
- ],
- lineNumber: 0,
- },
- path: '/jashkenas/underscore/-/jobs/335',
- };
+ let data;
+ let originalGon;
const createComponent = (props = {}) => {
wrapper = shallowMount(Line, {
@@ -26,12 +31,25 @@ describe('Job Log Line', () => {
});
};
+ const findLine = () => wrapper.find('span');
+ const findLink = () => findLine().find('a');
+ const findLinksAt = i =>
+ findLine()
+ .findAll('a')
+ .at(i);
+
beforeEach(() => {
+ originalGon = window.gon;
+ window.gon.features = {
+ ciJobLineLinks: false,
+ };
+
+ data = mockProps();
createComponent(data);
});
afterEach(() => {
- wrapper.destroy();
+ window.gon = originalGon;
});
it('renders the line number component', () => {
@@ -39,10 +57,109 @@ describe('Job Log Line', () => {
});
it('renders a span the provided text', () => {
- expect(wrapper.find('span').text()).toBe(data.line.content[0].text);
+ expect(findLine().text()).toBe(data.line.content[0].text);
});
it('renders the provided style as a class attribute', () => {
- expect(wrapper.find('span').classes()).toContain(data.line.content[0].style);
+ expect(findLine().classes()).toContain(data.line.content[0].style);
+ });
+
+ describe.each([true, false])('when feature ci_job_line_links enabled = %p', ciJobLineLinks => {
+ beforeEach(() => {
+ window.gon.features = {
+ ciJobLineLinks,
+ };
+ });
+
+ it('renders text with symbols', () => {
+ const text = 'apt-get update < /dev/null > /dev/null';
+ createComponent(mockProps({ text }));
+
+ expect(findLine().text()).toBe(text);
+ });
+
+ it.each`
+ tag | text
+ ${'a'} | ${'<a href="#">linked</a>'}
+ ${'script'} | ${'<script>doEvil();</script>'}
+ ${'strong'} | ${'<strong>highlighted</strong>'}
+ `('escapes `<$tag>` tags in text', ({ tag, text }) => {
+ createComponent(mockProps({ text }));
+
+ expect(
+ findLine()
+ .find(tag)
+ .exists(),
+ ).toBe(false);
+ expect(findLine().text()).toBe(text);
+ });
+ });
+
+ describe('when ci_job_line_links is enabled', () => {
+ beforeEach(() => {
+ window.gon.features = {
+ ciJobLineLinks: true,
+ };
+ });
+
+ it('renders an http link', () => {
+ createComponent(mockProps({ text: httpUrl }));
+
+ expect(findLink().text()).toBe(httpUrl);
+ expect(findLink().attributes().href).toBe(httpUrl);
+ });
+
+ it('renders an https link', () => {
+ createComponent(mockProps({ text: httpsUrl }));
+
+ expect(findLink().text()).toBe(httpsUrl);
+ expect(findLink().attributes().href).toBe(httpsUrl);
+ });
+
+ it('renders a multiple links surrounded by text', () => {
+ createComponent(mockProps({ text: `My HTTP url: ${httpUrl} and my HTTPS url: ${httpsUrl}` }));
+ expect(findLine().text()).toBe(
+ 'My HTTP url: http://example.com and my HTTPS url: https://example.com',
+ );
+ expect(findLinksAt(0).attributes().href).toBe(httpUrl);
+ expect(findLinksAt(1).attributes().href).toBe(httpsUrl);
+ });
+
+ it('renders a link with rel nofollow and noopener', () => {
+ createComponent(mockProps({ text: httpsUrl }));
+
+ expect(findLink().attributes().rel).toBe('nofollow noopener noreferrer');
+ });
+
+ it('renders a link with corresponding styles', () => {
+ createComponent(mockProps({ text: httpsUrl }));
+
+ expect(findLink().classes()).toEqual(['gl-reset-color!', 'gl-text-decoration-underline']);
+ });
+
+ it('render links surrounded by text', () => {
+ createComponent(
+ mockProps({ text: `My HTTP url: ${httpUrl} and my HTTPS url: ${httpsUrl} are here.` }),
+ );
+ expect(findLine().text()).toBe(
+ 'My HTTP url: http://example.com and my HTTPS url: https://example.com are here.',
+ );
+ expect(findLinksAt(0).attributes().href).toBe(httpUrl);
+ expect(findLinksAt(1).attributes().href).toBe(httpsUrl);
+ });
+
+ const jshref = 'javascript:doEvil();'; // eslint-disable-line no-script-url
+
+ test.each`
+ type | text
+ ${'js'} | ${jshref}
+ ${'file'} | ${'file:///a-file'}
+ ${'ftp'} | ${'ftp://example.com/file'}
+ ${'email'} | ${'email@example.com'}
+ ${'no scheme'} | ${'example.com/page'}
+ `('does not render a $type link', ({ text }) => {
+ createComponent(mockProps({ text }));
+ expect(findLink().exists()).toBe(false);
+ });
});
});
diff --git a/spec/frontend/jobs/components/sidebar_spec.js b/spec/frontend/jobs/components/sidebar_spec.js
index 48788df0c93..1d4be2fb81e 100644
--- a/spec/frontend/jobs/components/sidebar_spec.js
+++ b/spec/frontend/jobs/components/sidebar_spec.js
@@ -1,167 +1,166 @@
-import Vue from 'vue';
-import sidebarDetailsBlock from '~/jobs/components/sidebar.vue';
+import { shallowMount } from '@vue/test-utils';
+import Sidebar, { forwardDeploymentFailureModalId } from '~/jobs/components/sidebar.vue';
+import StagesDropdown from '~/jobs/components/stages_dropdown.vue';
+import JobsContainer from '~/jobs/components/jobs_container.vue';
+import JobRetryForwardDeploymentModal from '~/jobs/components/job_retry_forward_deployment_modal.vue';
+import JobRetryButton from '~/jobs/components/job_sidebar_retry_button.vue';
import createStore from '~/jobs/store';
import job, { jobsInStage } from '../mock_data';
-import { mountComponentWithStore } from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/text_helper';
+import { extendedWrapper } from '../../helpers/vue_test_utils_helper';
describe('Sidebar details block', () => {
- const SidebarComponent = Vue.extend(sidebarDetailsBlock);
- let vm;
let store;
+ let wrapper;
- beforeEach(() => {
+ const forwardDeploymentFailure = 'forward_deployment_failure';
+ const findModal = () => wrapper.find(JobRetryForwardDeploymentModal);
+ const findCancelButton = () => wrapper.findByTestId('cancel-button');
+ const findNewIssueButton = () => wrapper.findByTestId('job-new-issue');
+ const findRetryButton = () => wrapper.find(JobRetryButton);
+ const findTerminalLink = () => wrapper.findByTestId('terminal-link');
+
+ const createWrapper = ({ props = {} } = {}) => {
store = createStore();
- });
+ wrapper = extendedWrapper(
+ shallowMount(Sidebar, {
+ ...props,
+ store,
+ }),
+ );
+ };
afterEach(() => {
- vm.$destroy();
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
});
describe('when there is no retry path retry', () => {
- it('should not render a retry button', () => {
- const copy = { ...job };
- delete copy.retry_path;
-
- store.dispatch('receiveJobSuccess', copy);
- vm = mountComponentWithStore(SidebarComponent, {
- store,
- });
+ it('should not render a retry button', async () => {
+ createWrapper();
+ const copy = { ...job, retry_path: null };
+ await store.dispatch('receiveJobSuccess', copy);
- expect(vm.$el.querySelector('.js-retry-button')).toBeNull();
+ expect(findRetryButton().exists()).toBe(false);
});
});
describe('without terminal path', () => {
- it('does not render terminal link', () => {
- store.dispatch('receiveJobSuccess', job);
- vm = mountComponentWithStore(SidebarComponent, { store });
+ it('does not render terminal link', async () => {
+ createWrapper();
+ await store.dispatch('receiveJobSuccess', job);
- expect(vm.$el.querySelector('.js-terminal-link')).toBeNull();
+ expect(findTerminalLink().exists()).toBe(false);
});
});
describe('with terminal path', () => {
- it('renders terminal link', () => {
- store.dispatch('receiveJobSuccess', { ...job, terminal_path: 'job/43123/terminal' });
- vm = mountComponentWithStore(SidebarComponent, {
- store,
- });
+ it('renders terminal link', async () => {
+ createWrapper();
+ await store.dispatch('receiveJobSuccess', { ...job, terminal_path: 'job/43123/terminal' });
- expect(vm.$el.querySelector('.js-terminal-link')).not.toBeNull();
+ expect(findTerminalLink().exists()).toBe(true);
});
});
- beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
- vm = mountComponentWithStore(SidebarComponent, { store });
- });
-
describe('actions', () => {
- it('should render link to new issue', () => {
- expect(vm.$el.querySelector('[data-testid="job-new-issue"]').getAttribute('href')).toEqual(
- job.new_issue_path,
- );
+ beforeEach(() => {
+ createWrapper();
+ return store.dispatch('receiveJobSuccess', job);
+ });
- expect(vm.$el.querySelector('[data-testid="job-new-issue"]').textContent.trim()).toEqual(
- 'New issue',
- );
+ it('should render link to new issue', () => {
+ expect(findNewIssueButton().attributes('href')).toBe(job.new_issue_path);
+ expect(findNewIssueButton().text()).toBe('New issue');
});
- it('should render link to retry job', () => {
- expect(vm.$el.querySelector('.js-retry-button').getAttribute('href')).toEqual(job.retry_path);
+ it('should render the retry button', () => {
+ expect(findRetryButton().props('href')).toBe(job.retry_path);
});
it('should render link to cancel job', () => {
- expect(vm.$el.querySelector('.js-cancel-job').getAttribute('href')).toEqual(job.cancel_path);
+ expect(findCancelButton().text()).toMatch('Cancel');
+ expect(findCancelButton().attributes('href')).toBe(job.cancel_path);
});
});
- describe('information', () => {
- it('should render job duration', () => {
- expect(trimText(vm.$el.querySelector('.js-job-duration').textContent)).toEqual(
- 'Duration: 6 seconds',
- );
- });
-
- it('should render erased date', () => {
- expect(trimText(vm.$el.querySelector('.js-job-erased').textContent)).toEqual(
- 'Erased: 3 weeks ago',
- );
- });
-
- it('should render finished date', () => {
- expect(trimText(vm.$el.querySelector('.js-job-finished').textContent)).toEqual(
- 'Finished: 3 weeks ago',
- );
- });
-
- it('should render queued date', () => {
- expect(trimText(vm.$el.querySelector('.js-job-queued').textContent)).toEqual(
- 'Queued: 9 seconds',
+ describe('forward deployment failure', () => {
+ describe('when the relevant data is missing', () => {
+ it.each`
+ retryPath | failureReason
+ ${null} | ${null}
+ ${''} | ${''}
+ ${job.retry_path} | ${''}
+ ${''} | ${forwardDeploymentFailure}
+ ${job.retry_path} | ${'unmet_prerequisites'}
+ `(
+ 'should not render the modal when path and failure are $retryPath, $failureReason',
+ async ({ retryPath, failureReason }) => {
+ createWrapper();
+ await store.dispatch('receiveJobSuccess', {
+ ...job,
+ failure_reason: failureReason,
+ retry_path: retryPath,
+ });
+ expect(findModal().exists()).toBe(false);
+ },
);
});
- it('should render runner ID', () => {
- expect(trimText(vm.$el.querySelector('.js-job-runner').textContent)).toEqual(
- 'Runner: local ci runner (#1)',
- );
- });
+ describe('when there is the relevant error', () => {
+ beforeEach(() => {
+ createWrapper();
+ return store.dispatch('receiveJobSuccess', {
+ ...job,
+ failure_reason: forwardDeploymentFailure,
+ });
+ });
- it('should render timeout information', () => {
- expect(trimText(vm.$el.querySelector('.js-job-timeout').textContent)).toEqual(
- 'Timeout: 1m 40s (from runner)',
- );
- });
+ it('should render the modal', () => {
+ expect(findModal().exists()).toBe(true);
+ });
- it('should render coverage', () => {
- expect(trimText(vm.$el.querySelector('.js-job-coverage').textContent)).toEqual(
- 'Coverage: 20%',
- );
- });
+ it('should provide the modal id to the button and modal', () => {
+ expect(findRetryButton().props('modalId')).toBe(forwardDeploymentFailureModalId);
+ expect(findModal().props('modalId')).toBe(forwardDeploymentFailureModalId);
+ });
- it('should render tags', () => {
- expect(trimText(vm.$el.querySelector('.js-job-tags').textContent)).toEqual('Tags: tag');
+ it('should provide the retry path to the button and modal', () => {
+ expect(findRetryButton().props('href')).toBe(job.retry_path);
+ expect(findModal().props('href')).toBe(job.retry_path);
+ });
});
});
describe('stages dropdown', () => {
beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
+ createWrapper();
+ return store.dispatch('receiveJobSuccess', { ...job, stage: 'aStage' });
});
describe('with stages', () => {
- beforeEach(() => {
- vm = mountComponentWithStore(SidebarComponent, { store });
- });
-
it('renders value provided as selectedStage as selected', () => {
- expect(vm.$el.querySelector('.js-selected-stage').textContent.trim()).toEqual(
- vm.selectedStage,
- );
+ expect(wrapper.find(StagesDropdown).props('selectedStage')).toBe('aStage');
});
});
describe('without jobs for stages', () => {
- beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
- vm = mountComponentWithStore(SidebarComponent, { store });
- });
+ beforeEach(() => store.dispatch('receiveJobSuccess', job));
- it('does not render job container', () => {
- expect(vm.$el.querySelector('.js-jobs-container')).toBeNull();
+ it('does not render jobs container', () => {
+ expect(wrapper.find(JobsContainer).exists()).toBe(false);
});
});
describe('with jobs for stages', () => {
- beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
- store.dispatch('receiveJobsForStageSuccess', jobsInStage.latest_statuses);
- vm = mountComponentWithStore(SidebarComponent, { store });
+ beforeEach(async () => {
+ await store.dispatch('receiveJobSuccess', job);
+ await store.dispatch('receiveJobsForStageSuccess', jobsInStage.latest_statuses);
});
it('renders list of jobs', () => {
- expect(vm.$el.querySelector('.js-jobs-container')).not.toBeNull();
+ expect(wrapper.find(JobsContainer).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/lib/utils/apollo_startup_js_link_spec.js b/spec/frontend/lib/utils/apollo_startup_js_link_spec.js
new file mode 100644
index 00000000000..faead3ff8fe
--- /dev/null
+++ b/spec/frontend/lib/utils/apollo_startup_js_link_spec.js
@@ -0,0 +1,375 @@
+import { ApolloLink, Observable } from 'apollo-link';
+import { StartupJSLink } from '~/lib/utils/apollo_startup_js_link';
+
+describe('StartupJSLink', () => {
+ const FORWARDED_RESPONSE = { data: 'FORWARDED_RESPONSE' };
+
+ const STARTUP_JS_RESPONSE = { data: 'STARTUP_JS_RESPONSE' };
+ const OPERATION_NAME = 'startupJSQuery';
+ const STARTUP_JS_QUERY = `query ${OPERATION_NAME}($id: Int = 3){
+ name
+ id
+ }`;
+
+ const STARTUP_JS_RESPONSE_TWO = { data: 'STARTUP_JS_RESPONSE_TWO' };
+ const OPERATION_NAME_TWO = 'startupJSQueryTwo';
+ const STARTUP_JS_QUERY_TWO = `query ${OPERATION_NAME_TWO}($id: Int = 3){
+ id
+ name
+ }`;
+
+ const ERROR_RESPONSE = {
+ data: {
+ user: null,
+ },
+ errors: [
+ {
+ path: ['user'],
+ locations: [{ line: 2, column: 3 }],
+ extensions: {
+ message: 'Object not found',
+ type: 2,
+ },
+ },
+ ],
+ };
+
+ let startupLink;
+ let link;
+
+ function mockFetchCall(status = 200, response = STARTUP_JS_RESPONSE) {
+ const p = {
+ ok: status >= 200 && status < 300,
+ status,
+ headers: new Headers({ 'Content-Type': 'application/json' }),
+ statusText: `MOCK-FETCH ${status}`,
+ clone: () => p,
+ json: () => Promise.resolve(response),
+ };
+ return Promise.resolve(p);
+ }
+
+ function mockOperation({ operationName = OPERATION_NAME, variables = { id: 3 } } = {}) {
+ return { operationName, variables, setContext: () => {} };
+ }
+
+ const setupLink = () => {
+ startupLink = new StartupJSLink();
+ link = ApolloLink.from([startupLink, new ApolloLink(() => Observable.of(FORWARDED_RESPONSE))]);
+ };
+
+ it('forwards requests if no calls are set up', done => {
+ setupLink();
+ link.request(mockOperation()).subscribe(result => {
+ expect(result).toEqual(FORWARDED_RESPONSE);
+ expect(startupLink.startupCalls).toBe(null);
+ expect(startupLink.request).toEqual(StartupJSLink.noopRequest);
+ done();
+ });
+ });
+
+ it('forwards requests if the operation is not pre-loaded', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(),
+ query: STARTUP_JS_QUERY,
+ variables: { id: 3 },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation({ operationName: 'notLoaded' })).subscribe(result => {
+ expect(result).toEqual(FORWARDED_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(1);
+ done();
+ });
+ });
+
+ describe('variable match errors: ', () => {
+ it('forwards requests if the variables are not matching', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(),
+ query: STARTUP_JS_QUERY,
+ variables: { id: 'NOT_MATCHING' },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation()).subscribe(result => {
+ expect(result).toEqual(FORWARDED_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+
+ it('forwards requests if more variables are set in the operation', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(),
+ query: STARTUP_JS_QUERY,
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation()).subscribe(result => {
+ expect(result).toEqual(FORWARDED_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+
+ it('forwards requests if less variables are set in the operation', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(),
+ query: STARTUP_JS_QUERY,
+ variables: { id: 3, name: 'tanuki' },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation({ variables: { id: 3 } })).subscribe(result => {
+ expect(result).toEqual(FORWARDED_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+
+ it('forwards requests if different variables are set', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(),
+ query: STARTUP_JS_QUERY,
+ variables: { name: 'tanuki' },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation({ variables: { id: 3 } })).subscribe(result => {
+ expect(result).toEqual(FORWARDED_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+
+ it('forwards requests if array variables have a different order', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(),
+ query: STARTUP_JS_QUERY,
+ variables: { id: [3, 4] },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation({ variables: { id: [4, 3] } })).subscribe(result => {
+ expect(result).toEqual(FORWARDED_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+ });
+
+ describe('error handling', () => {
+ it('forwards the call if the fetchCall is failing with a HTTP Error', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(404),
+ query: STARTUP_JS_QUERY,
+ variables: { id: 3 },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation()).subscribe(result => {
+ expect(result).toEqual(FORWARDED_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+
+ it('forwards the call if it errors (e.g. failing JSON)', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: Promise.reject(new Error('Parsing failed')),
+ query: STARTUP_JS_QUERY,
+ variables: { id: 3 },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation()).subscribe(result => {
+ expect(result).toEqual(FORWARDED_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+
+ it('forwards the call if the response contains an error', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(200, ERROR_RESPONSE),
+ query: STARTUP_JS_QUERY,
+ variables: { id: 3 },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation()).subscribe(result => {
+ expect(result).toEqual(FORWARDED_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+
+ it("forwards the call if the response doesn't contain a data object", done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(200, { 'no-data': 'yay' }),
+ query: STARTUP_JS_QUERY,
+ variables: { id: 3 },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation()).subscribe(result => {
+ expect(result).toEqual(FORWARDED_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+ });
+
+ it('resolves the request if the operation is matching', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(),
+ query: STARTUP_JS_QUERY,
+ variables: { id: 3 },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation()).subscribe(result => {
+ expect(result).toEqual(STARTUP_JS_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+
+ it('resolves the request exactly once', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(),
+ query: STARTUP_JS_QUERY,
+ variables: { id: 3 },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation()).subscribe(result => {
+ expect(result).toEqual(STARTUP_JS_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ link.request(mockOperation()).subscribe(result2 => {
+ expect(result2).toEqual(FORWARDED_RESPONSE);
+ done();
+ });
+ });
+ });
+
+ it('resolves the request if the variables have a different order', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(),
+ query: STARTUP_JS_QUERY,
+ variables: { id: 3, name: 'foo' },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation({ variables: { name: 'foo', id: 3 } })).subscribe(result => {
+ expect(result).toEqual(STARTUP_JS_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+
+ it('resolves the request if the variables have undefined values', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(),
+ query: STARTUP_JS_QUERY,
+ variables: { name: 'foo' },
+ },
+ ],
+ };
+ setupLink();
+ link
+ .request(mockOperation({ variables: { name: 'foo', undef: undefined } }))
+ .subscribe(result => {
+ expect(result).toEqual(STARTUP_JS_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+
+ it('resolves the request if the variables are of an array format', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(),
+ query: STARTUP_JS_QUERY,
+ variables: { id: [3, 4] },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation({ variables: { id: [3, 4] } })).subscribe(result => {
+ expect(result).toEqual(STARTUP_JS_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+
+ it('resolves multiple requests correctly', done => {
+ window.gl = {
+ startup_graphql_calls: [
+ {
+ fetchCall: mockFetchCall(),
+ query: STARTUP_JS_QUERY,
+ variables: { id: 3 },
+ },
+ {
+ fetchCall: mockFetchCall(200, STARTUP_JS_RESPONSE_TWO),
+ query: STARTUP_JS_QUERY_TWO,
+ variables: { id: 3 },
+ },
+ ],
+ };
+ setupLink();
+ link.request(mockOperation({ operationName: OPERATION_NAME_TWO })).subscribe(result => {
+ expect(result).toEqual(STARTUP_JS_RESPONSE_TWO);
+ expect(startupLink.startupCalls.size).toBe(1);
+ link.request(mockOperation({ operationName: OPERATION_NAME })).subscribe(result2 => {
+ expect(result2).toEqual(STARTUP_JS_RESPONSE);
+ expect(startupLink.startupCalls.size).toBe(0);
+ done();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js
index effc446d846..09eb362c77e 100644
--- a/spec/frontend/lib/utils/common_utils_spec.js
+++ b/spec/frontend/lib/utils/common_utils_spec.js
@@ -959,6 +959,25 @@ describe('common_utils', () => {
});
});
+ describe('roundDownFloat', () => {
+ it('Rounds down decimal places of a float number with provided precision', () => {
+ expect(commonUtils.roundDownFloat(3.141592, 3)).toBe(3.141);
+ });
+
+ it('Rounds down a float number to a whole number when provided precision is zero', () => {
+ expect(commonUtils.roundDownFloat(3.141592, 0)).toBe(3);
+ expect(commonUtils.roundDownFloat(3.9, 0)).toBe(3);
+ });
+
+ it('Rounds down float number to nearest 0, 10, 100, 1000 and so on when provided precision is below 0', () => {
+ expect(commonUtils.roundDownFloat(34567.14159, -1)).toBeCloseTo(34560);
+ expect(commonUtils.roundDownFloat(34567.14159, -2)).toBeCloseTo(34500);
+ expect(commonUtils.roundDownFloat(34567.14159, -3)).toBeCloseTo(34000);
+ expect(commonUtils.roundDownFloat(34567.14159, -4)).toBeCloseTo(30000);
+ expect(commonUtils.roundDownFloat(34567.14159, -5)).toBeCloseTo(0);
+ });
+ });
+
describe('searchBy', () => {
const searchSpace = {
iid: 1,
diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js
index b0b0b028761..6092b44720f 100644
--- a/spec/frontend/lib/utils/datetime_utility_spec.js
+++ b/spec/frontend/lib/utils/datetime_utility_spec.js
@@ -643,16 +643,15 @@ describe('localTimeAgo', () => {
});
it.each`
- timeagoArg | title | dataOriginalTitle
- ${false} | ${'some time'} | ${null}
- ${true} | ${''} | ${'Feb 18, 2020 10:22pm GMT+0000'}
- `('converts $seconds seconds to $approximation', ({ timeagoArg, title, dataOriginalTitle }) => {
+ timeagoArg | title
+ ${false} | ${'some time'}
+ ${true} | ${'Feb 18, 2020 10:22pm GMT+0000'}
+ `('converts $seconds seconds to $approximation', ({ timeagoArg, title }) => {
const element = document.querySelector('time');
datetimeUtility.localTimeAgo($(element), timeagoArg);
jest.runAllTimers();
- expect(element.getAttribute('data-original-title')).toBe(dataOriginalTitle);
expect(element.getAttribute('title')).toBe(title);
});
});
diff --git a/spec/frontend/lib/utils/dom_utils_spec.js b/spec/frontend/lib/utils/dom_utils_spec.js
index d918016a5f4..f5c2a797df5 100644
--- a/spec/frontend/lib/utils/dom_utils_spec.js
+++ b/spec/frontend/lib/utils/dom_utils_spec.js
@@ -3,6 +3,8 @@ import {
canScrollUp,
canScrollDown,
parseBooleanDataAttributes,
+ isElementVisible,
+ isElementHidden,
} from '~/lib/utils/dom_utils';
const TEST_MARGIN = 5;
@@ -160,4 +162,35 @@ describe('DOM Utils', () => {
});
});
});
+
+ describe.each`
+ offsetWidth | offsetHeight | clientRectsLength | visible
+ ${0} | ${0} | ${0} | ${false}
+ ${1} | ${0} | ${0} | ${true}
+ ${0} | ${1} | ${0} | ${true}
+ ${0} | ${0} | ${1} | ${true}
+ `(
+ 'isElementVisible and isElementHidden',
+ ({ offsetWidth, offsetHeight, clientRectsLength, visible }) => {
+ const element = {
+ offsetWidth,
+ offsetHeight,
+ getClientRects: () => new Array(clientRectsLength),
+ };
+
+ const paramDescription = `offsetWidth=${offsetWidth}, offsetHeight=${offsetHeight}, and getClientRects().length=${clientRectsLength}`;
+
+ describe('isElementVisible', () => {
+ it(`returns ${visible} when ${paramDescription}`, () => {
+ expect(isElementVisible(element)).toBe(visible);
+ });
+ });
+
+ describe('isElementHidden', () => {
+ it(`returns ${!visible} when ${paramDescription}`, () => {
+ expect(isElementHidden(element)).toBe(!visible);
+ });
+ });
+ },
+ );
});
diff --git a/spec/frontend/lib/utils/number_utility_spec.js b/spec/frontend/lib/utils/number_utility_spec.js
index f600f2bcd55..2f8f1092612 100644
--- a/spec/frontend/lib/utils/number_utility_spec.js
+++ b/spec/frontend/lib/utils/number_utility_spec.js
@@ -1,6 +1,5 @@
import {
formatRelevantDigits,
- bytesToKB,
bytesToKiB,
bytesToMiB,
bytesToGiB,
@@ -55,16 +54,6 @@ describe('Number Utils', () => {
});
});
- describe('bytesToKB', () => {
- it.each`
- input | output
- ${1000} | ${1}
- ${1024} | ${1.024}
- `('returns $output KB for $input bytes', ({ input, output }) => {
- expect(bytesToKB(input)).toBe(output);
- });
- });
-
describe('bytesToKiB', () => {
it('calculates KiB for the given bytes', () => {
expect(bytesToKiB(1024)).toEqual(1);
diff --git a/spec/frontend/lib/utils/text_utility_spec.js b/spec/frontend/lib/utils/text_utility_spec.js
index 6fef5f6b63c..d7cedb939d2 100644
--- a/spec/frontend/lib/utils/text_utility_spec.js
+++ b/spec/frontend/lib/utils/text_utility_spec.js
@@ -325,4 +325,19 @@ describe('text_utility', () => {
expect(textUtils.hasContent(txt)).toEqual(result);
});
});
+
+ describe('isValidSha1Hash', () => {
+ const validSha1Hash = '92d10c15';
+ const stringOver40 = new Array(42).join('a');
+
+ it.each`
+ hash | valid
+ ${validSha1Hash} | ${true}
+ ${'__characters'} | ${false}
+ ${'abc'} | ${false}
+ ${stringOver40} | ${false}
+ `(`returns $valid for $hash`, ({ hash, valid }) => {
+ expect(textUtils.isValidSha1Hash(hash)).toBe(valid);
+ });
+ });
});
diff --git a/spec/frontend/milestones/milestone_combobox_spec.js b/spec/frontend/milestones/milestone_combobox_spec.js
new file mode 100644
index 00000000000..047484f117f
--- /dev/null
+++ b/spec/frontend/milestones/milestone_combobox_spec.js
@@ -0,0 +1,518 @@
+import Vuex from 'vuex';
+import { mount, createLocalVue } from '@vue/test-utils';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { ENTER_KEY } from '~/lib/utils/keys';
+import MilestoneCombobox from '~/milestones/components/milestone_combobox.vue';
+import { projectMilestones, groupMilestones } from './mock_data';
+import createStore from '~/milestones/stores/';
+
+const extraLinks = [
+ { text: 'Create new', url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/new' },
+ { text: 'Manage milestones', url: '/h5bp/html5-boilerplate/-/milestones' },
+];
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('Milestone combobox component', () => {
+ const projectId = '8';
+ const groupId = '24';
+ const groupMilestonesAvailable = true;
+ const X_TOTAL_HEADER = 'x-total';
+
+ let wrapper;
+ let projectMilestonesApiCallSpy;
+ let groupMilestonesApiCallSpy;
+ let searchApiCallSpy;
+
+ const createComponent = (props = {}, attrs = {}) => {
+ wrapper = mount(MilestoneCombobox, {
+ propsData: {
+ projectId,
+ groupId,
+ groupMilestonesAvailable,
+ extraLinks,
+ value: [],
+ ...props,
+ },
+ attrs,
+ listeners: {
+ // simulate a parent component v-model binding
+ input: selectedMilestone => {
+ wrapper.setProps({ value: selectedMilestone });
+ },
+ },
+ stubs: {
+ GlSearchBoxByType: true,
+ },
+ localVue,
+ store: createStore(),
+ });
+ };
+
+ beforeEach(() => {
+ const mock = new MockAdapter(axios);
+ gon.api_version = 'v4';
+
+ projectMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, projectMilestones, { [X_TOTAL_HEADER]: '6' }]);
+
+ groupMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, groupMilestones, { [X_TOTAL_HEADER]: '6' }]);
+
+ searchApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, projectMilestones, { [X_TOTAL_HEADER]: '6' }]);
+
+ mock
+ .onGet(`/api/v4/projects/${projectId}/milestones`)
+ .reply(config => projectMilestonesApiCallSpy(config));
+
+ mock
+ .onGet(`/api/v4/groups/${groupId}/milestones`)
+ .reply(config => groupMilestonesApiCallSpy(config));
+
+ mock.onGet(`/api/v4/projects/${projectId}/search`).reply(config => searchApiCallSpy(config));
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ //
+ // Finders
+ //
+ const findButtonContent = () => wrapper.find('[data-testid="milestone-combobox-button-content"]');
+
+ const findNoResults = () => wrapper.find('[data-testid="milestone-combobox-no-results"]');
+
+ const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+
+ const findSearchBox = () => wrapper.find(GlSearchBoxByType);
+
+ const findProjectMilestonesSection = () =>
+ wrapper.find('[data-testid="project-milestones-section"]');
+ const findProjectMilestonesDropdownItems = () =>
+ findProjectMilestonesSection().findAll(GlDropdownItem);
+ const findFirstProjectMilestonesDropdownItem = () => findProjectMilestonesDropdownItems().at(0);
+
+ const findGroupMilestonesSection = () => wrapper.find('[data-testid="group-milestones-section"]');
+ const findGroupMilestonesDropdownItems = () =>
+ findGroupMilestonesSection().findAll(GlDropdownItem);
+ const findFirstGroupMilestonesDropdownItem = () => findGroupMilestonesDropdownItems().at(0);
+
+ //
+ // Expecters
+ //
+ const projectMilestoneSectionContainsErrorMessage = () => {
+ const projectMilestoneSection = findProjectMilestonesSection();
+
+ return projectMilestoneSection
+ .text()
+ .includes(s__('MilestoneCombobox|An error occurred while searching for milestones'));
+ };
+
+ const groupMilestoneSectionContainsErrorMessage = () => {
+ const groupMilestoneSection = findGroupMilestonesSection();
+
+ return groupMilestoneSection
+ .text()
+ .includes(s__('MilestoneCombobox|An error occurred while searching for milestones'));
+ };
+
+ //
+ // Convenience methods
+ //
+ const updateQuery = newQuery => {
+ findSearchBox().vm.$emit('input', newQuery);
+ };
+
+ const selectFirstProjectMilestone = () => {
+ findFirstProjectMilestonesDropdownItem().vm.$emit('click');
+ };
+
+ const selectFirstGroupMilestone = () => {
+ findFirstGroupMilestonesDropdownItem().vm.$emit('click');
+ };
+
+ const waitForRequests = ({ andClearMocks } = { andClearMocks: false }) =>
+ axios.waitForAll().then(() => {
+ if (andClearMocks) {
+ projectMilestonesApiCallSpy.mockClear();
+ groupMilestonesApiCallSpy.mockClear();
+ }
+ });
+
+ describe('initialization behavior', () => {
+ beforeEach(createComponent);
+
+ it('initializes the dropdown with milestones when mounted', () => {
+ return waitForRequests().then(() => {
+ expect(projectMilestonesApiCallSpy).toHaveBeenCalledTimes(1);
+ expect(groupMilestonesApiCallSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ it('shows a spinner while network requests are in progress', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+
+ return waitForRequests().then(() => {
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+ });
+
+ it('shows additional links', () => {
+ const links = wrapper.findAll('[data-testid="milestone-combobox-extra-links"]');
+ links.wrappers.forEach((item, idx) => {
+ expect(item.text()).toBe(extraLinks[idx].text);
+ expect(item.attributes('href')).toBe(extraLinks[idx].url);
+ });
+ });
+ });
+
+ describe('post-initialization behavior', () => {
+ describe('when the parent component provides an `id` binding', () => {
+ const id = '8';
+
+ beforeEach(() => {
+ createComponent({}, { id });
+
+ return waitForRequests();
+ });
+
+ it('adds the provided ID to the GlDropdown instance', () => {
+ expect(wrapper.attributes().id).toBe(id);
+ });
+ });
+
+ describe('when milestones are pre-selected', () => {
+ beforeEach(() => {
+ createComponent({ value: projectMilestones });
+
+ return waitForRequests();
+ });
+
+ it('renders the pre-selected milestones', () => {
+ expect(findButtonContent().text()).toBe('v0.1 + 5 more');
+ });
+ });
+
+ describe('when the search query is updated', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests({ andClearMocks: true });
+ });
+
+ it('requeries the search when the search query is updated', () => {
+ updateQuery('v1.2.3');
+
+ return waitForRequests().then(() => {
+ expect(searchApiCallSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+ });
+
+ describe('when the Enter is pressed', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests({ andClearMocks: true });
+ });
+
+ it('requeries the search when Enter is pressed', () => {
+ findSearchBox().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
+
+ return waitForRequests().then(() => {
+ expect(searchApiCallSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+ });
+
+ describe('when no results are found', () => {
+ beforeEach(() => {
+ projectMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
+
+ groupMilestonesApiCallSpy = jest.fn().mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
+
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ describe('when the search query is empty', () => {
+ it('renders a "no results" message', () => {
+ expect(findNoResults().text()).toBe(s__('MilestoneCombobox|No matching results'));
+ });
+ });
+ });
+
+ describe('project milestones', () => {
+ describe('when the project milestones search returns results', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ it('renders the project milestones section in the dropdown', () => {
+ expect(findProjectMilestonesSection().exists()).toBe(true);
+ });
+
+ it('renders the "Project milestones" heading with a total number indicator', () => {
+ expect(
+ findProjectMilestonesSection()
+ .find('[data-testid="milestone-results-section-header"]')
+ .text(),
+ ).toBe('Project milestones 6');
+ });
+
+ it("does not render an error message in the project milestone section's body", () => {
+ expect(projectMilestoneSectionContainsErrorMessage()).toBe(false);
+ });
+
+ it('renders each project milestones as a selectable item', () => {
+ const dropdownItems = findProjectMilestonesDropdownItems();
+
+ projectMilestones.forEach((milestone, i) => {
+ expect(dropdownItems.at(i).text()).toBe(milestone.title);
+ });
+ });
+ });
+
+ describe('when the project milestones search returns no results', () => {
+ beforeEach(() => {
+ projectMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
+
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ it('does not render the project milestones section in the dropdown', () => {
+ expect(findProjectMilestonesSection().exists()).toBe(false);
+ });
+ });
+
+ describe('when the project milestones search returns an error', () => {
+ beforeEach(() => {
+ projectMilestonesApiCallSpy = jest.fn().mockReturnValue([500]);
+ searchApiCallSpy = jest.fn().mockReturnValue([500]);
+
+ createComponent({ value: [] });
+
+ return waitForRequests();
+ });
+
+ it('renders the project milestones section in the dropdown', () => {
+ expect(findProjectMilestonesSection().exists()).toBe(true);
+ });
+
+ it("renders an error message in the project milestones section's body", () => {
+ expect(projectMilestoneSectionContainsErrorMessage()).toBe(true);
+ });
+ });
+
+ describe('selection', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ it('renders a checkmark by the selected item', async () => {
+ selectFirstProjectMilestone();
+
+ await localVue.nextTick();
+
+ expect(
+ findFirstProjectMilestonesDropdownItem()
+ .find('span')
+ .classes('selected-item'),
+ ).toBe(false);
+
+ selectFirstProjectMilestone();
+
+ await localVue.nextTick();
+
+ expect(
+ findFirstProjectMilestonesDropdownItem()
+ .find('span')
+ .classes('selected-item'),
+ ).toBe(true);
+ });
+
+ describe('when a project milestones is selected', () => {
+ beforeEach(() => {
+ createComponent();
+ projectMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, [{ title: 'v1.0' }], { [X_TOTAL_HEADER]: '1' }]);
+
+ return waitForRequests();
+ });
+
+ it("displays the project milestones name in the dropdown's button", async () => {
+ selectFirstProjectMilestone();
+ await localVue.nextTick();
+
+ expect(findButtonContent().text()).toBe(s__('MilestoneCombobox|No milestone'));
+
+ selectFirstProjectMilestone();
+
+ await localVue.nextTick();
+ expect(findButtonContent().text()).toBe('v1.0');
+ });
+
+ it('updates the v-model binding with the project milestone title', () => {
+ expect(wrapper.vm.value).toEqual([]);
+
+ selectFirstProjectMilestone();
+
+ expect(wrapper.vm.value).toEqual(['v1.0']);
+ });
+ });
+ });
+ });
+
+ describe('group milestones', () => {
+ describe('when the group milestones search returns results', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ it('renders the group milestones section in the dropdown', () => {
+ expect(findGroupMilestonesSection().exists()).toBe(true);
+ });
+
+ it('renders the "Group milestones" heading with a total number indicator', () => {
+ expect(
+ findGroupMilestonesSection()
+ .find('[data-testid="milestone-results-section-header"]')
+ .text(),
+ ).toBe('Group milestones 6');
+ });
+
+ it("does not render an error message in the group milestone section's body", () => {
+ expect(groupMilestoneSectionContainsErrorMessage()).toBe(false);
+ });
+
+ it('renders each group milestones as a selectable item', () => {
+ const dropdownItems = findGroupMilestonesDropdownItems();
+
+ groupMilestones.forEach((milestone, i) => {
+ expect(dropdownItems.at(i).text()).toBe(milestone.title);
+ });
+ });
+ });
+
+ describe('when the group milestones search returns no results', () => {
+ beforeEach(() => {
+ groupMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
+
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ it('does not render the group milestones section in the dropdown', () => {
+ expect(findGroupMilestonesSection().exists()).toBe(false);
+ });
+ });
+
+ describe('when the group milestones search returns an error', () => {
+ beforeEach(() => {
+ groupMilestonesApiCallSpy = jest.fn().mockReturnValue([500]);
+ searchApiCallSpy = jest.fn().mockReturnValue([500]);
+
+ createComponent({ value: [] });
+
+ return waitForRequests();
+ });
+
+ it('renders the group milestones section in the dropdown', () => {
+ expect(findGroupMilestonesSection().exists()).toBe(true);
+ });
+
+ it("renders an error message in the group milestones section's body", () => {
+ expect(groupMilestoneSectionContainsErrorMessage()).toBe(true);
+ });
+ });
+
+ describe('selection', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ it('renders a checkmark by the selected item', async () => {
+ selectFirstGroupMilestone();
+
+ await localVue.nextTick();
+
+ expect(
+ findFirstGroupMilestonesDropdownItem()
+ .find('span')
+ .classes('selected-item'),
+ ).toBe(false);
+
+ selectFirstGroupMilestone();
+
+ await localVue.nextTick();
+
+ expect(
+ findFirstGroupMilestonesDropdownItem()
+ .find('span')
+ .classes('selected-item'),
+ ).toBe(true);
+ });
+
+ describe('when a group milestones is selected', () => {
+ beforeEach(() => {
+ createComponent();
+ groupMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, [{ title: 'group-v1.0' }], { [X_TOTAL_HEADER]: '1' }]);
+
+ return waitForRequests();
+ });
+
+ it("displays the group milestones name in the dropdown's button", async () => {
+ selectFirstGroupMilestone();
+ await localVue.nextTick();
+
+ expect(findButtonContent().text()).toBe(s__('MilestoneCombobox|No milestone'));
+
+ selectFirstGroupMilestone();
+
+ await localVue.nextTick();
+ expect(findButtonContent().text()).toBe('group-v1.0');
+ });
+
+ it('updates the v-model binding with the group milestone title', () => {
+ expect(wrapper.vm.value).toEqual([]);
+
+ selectFirstGroupMilestone();
+
+ expect(wrapper.vm.value).toEqual(['group-v1.0']);
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/milestones/mock_data.js b/spec/frontend/milestones/mock_data.js
index c64eeeba663..71fbfe54141 100644
--- a/spec/frontend/milestones/mock_data.js
+++ b/spec/frontend/milestones/mock_data.js
@@ -1,4 +1,4 @@
-export const milestones = [
+export const projectMilestones = [
{
id: 41,
iid: 6,
@@ -79,4 +79,94 @@ export const milestones = [
},
];
-export default milestones;
+export const groupMilestones = [
+ {
+ id: 141,
+ iid: 16,
+ project_id: 8,
+ group_id: 12,
+ title: 'group-v0.1',
+ description: '',
+ state: 'active',
+ created_at: '2020-04-04T01:30:40.051Z',
+ updated_at: '2020-04-04T01:30:40.051Z',
+ due_date: null,
+ start_date: null,
+ web_url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/6',
+ },
+ {
+ id: 140,
+ iid: 15,
+ project_id: 8,
+ group_id: 12,
+ title: 'group-v4.0',
+ description: 'Laboriosam nisi sapiente dolores et magnam nobis ad earum.',
+ state: 'closed',
+ created_at: '2020-01-13T19:39:15.191Z',
+ updated_at: '2020-01-13T19:39:15.191Z',
+ due_date: null,
+ start_date: null,
+ web_url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/5',
+ },
+ {
+ id: 139,
+ iid: 14,
+ project_id: 8,
+ group_id: 12,
+ title: 'group-v3.0',
+ description: 'Necessitatibus illo alias et repellat dolorum assumenda ut.',
+ state: 'closed',
+ created_at: '2020-01-13T19:39:15.176Z',
+ updated_at: '2020-01-13T19:39:15.176Z',
+ due_date: null,
+ start_date: null,
+ web_url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/4',
+ },
+ {
+ id: 138,
+ iid: 13,
+ project_id: 8,
+ group_id: 12,
+ title: 'group-v2.0',
+ description: 'Doloribus qui repudiandae iste sit.',
+ state: 'closed',
+ created_at: '2020-01-13T19:39:15.161Z',
+ updated_at: '2020-01-13T19:39:15.161Z',
+ due_date: null,
+ start_date: null,
+ web_url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/3',
+ },
+ {
+ id: 137,
+ iid: 12,
+ project_id: 8,
+ group_id: 12,
+ title: 'group-v1.0',
+ description: 'Illo sint odio officia ea.',
+ state: 'closed',
+ created_at: '2020-01-13T19:39:15.146Z',
+ updated_at: '2020-01-13T19:39:15.146Z',
+ due_date: null,
+ start_date: null,
+ web_url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/2',
+ },
+ {
+ id: 136,
+ iid: 11,
+ project_id: 8,
+ group_id: 12,
+ title: 'group-v0.0',
+ description: 'Sed quae facilis deleniti at delectus assumenda nobis veritatis.',
+ state: 'active',
+ created_at: '2020-01-13T19:39:15.127Z',
+ updated_at: '2020-01-13T19:39:15.127Z',
+ due_date: null,
+ start_date: null,
+ web_url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/1',
+ },
+];
+
+export default {
+ projectMilestones,
+ groupMilestones,
+};
diff --git a/spec/frontend/milestones/project_milestone_combobox_spec.js b/spec/frontend/milestones/project_milestone_combobox_spec.js
deleted file mode 100644
index 60d68aa5816..00000000000
--- a/spec/frontend/milestones/project_milestone_combobox_spec.js
+++ /dev/null
@@ -1,186 +0,0 @@
-import axios from 'axios';
-import MockAdapter from 'axios-mock-adapter';
-import { shallowMount } from '@vue/test-utils';
-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' },
- { text: 'Manage milestones', url: '/h5bp/html5-boilerplate/-/milestones' },
-];
-
-const preselectedMilestones = [];
-const projectId = '8';
-
-describe('Milestone selector', () => {
- let wrapper;
- let mock;
-
- const findNoResultsMessage = () => wrapper.find({ ref: 'noResults' });
-
- const findSearchBox = () => wrapper.find(GlSearchBoxByType);
-
- const factory = (options = {}) => {
- wrapper = shallowMount(MilestoneCombobox, {
- ...options,
- });
- };
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- gon.api_version = 'v4';
-
- mock.onGet('/api/v4/projects/8/milestones').reply(200, projectMilestones);
-
- factory({
- propsData: {
- projectId,
- preselectedMilestones,
- extraLinks,
- },
- });
- });
-
- afterEach(() => {
- mock.restore();
- wrapper.destroy();
- wrapper = null;
- });
-
- it('renders the dropdown', () => {
- expect(wrapper.find(GlDropdown)).toExist();
- });
-
- it('renders additional links', () => {
- const links = wrapper.findAll('[href]');
- links.wrappers.forEach((item, idx) => {
- expect(item.text()).toBe(extraLinks[idx].text);
- expect(item.attributes('href')).toBe(extraLinks[idx].url);
- });
- });
-
- describe('before results', () => {
- it('should show a loading icon', () => {
- const request = mock.onGet(TEST_SEARCH_ENDPOINT, {
- params: { search: TEST_SEARCH, scope: 'milestones' },
- });
-
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
-
- return wrapper.vm.$nextTick().then(() => {
- request.reply(200, []);
- });
- });
-
- it('should not show any dropdown items', () => {
- expect(wrapper.findAll('[role="milestone option"]')).toHaveLength(0);
- });
-
- it('should have "No milestone" as the button text', () => {
- expect(wrapper.find({ ref: 'buttonText' }).text()).toBe('No milestone');
- });
- });
-
- describe('with empty results', () => {
- beforeEach(() => {
- mock
- .onGet(TEST_SEARCH_ENDPOINT, { params: { search: TEST_SEARCH, scope: 'milestones' } })
- .reply(200, []);
- findSearchBox().vm.$emit('input', TEST_SEARCH);
- return axios.waitForAll();
- });
-
- it('should display that no matching items are found', () => {
- expect(findNoResultsMessage().exists()).toBe(true);
- });
- });
-
- describe('with results', () => {
- let items;
- beforeEach(() => {
- mock
- .onGet(TEST_SEARCH_ENDPOINT, { params: { search: 'v0.1', scope: 'milestones' } })
- .reply(200, [
- {
- id: 41,
- iid: 6,
- project_id: 8,
- title: 'v0.1',
- description: '',
- state: 'active',
- created_at: '2020-04-04T01:30:40.051Z',
- updated_at: '2020-04-04T01:30:40.051Z',
- due_date: null,
- start_date: null,
- web_url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/6',
- },
- ]);
- findSearchBox().vm.$emit('input', 'v0.1');
- return axios.waitForAll().then(() => {
- items = wrapper.findAll('[role="milestone option"]');
- });
- });
-
- it('should display one item per result', () => {
- expect(items).toHaveLength(1);
- });
-
- it('should emit a change if an item is clicked', () => {
- items.at(0).vm.$emit('click');
- expect(wrapper.emitted().change.length).toBe(1);
- expect(wrapper.emitted().change[0]).toEqual([[{ title: 'v0.1' }]]);
- });
-
- it('should not have a selecton icon on any item', () => {
- items.wrappers.forEach(item => {
- expect(item.find('.selected-item').exists()).toBe(false);
- });
- });
-
- it('should have a selecton icon if an item is clicked', () => {
- items.at(0).vm.$emit('click');
- expect(wrapper.find('.selected-item').exists()).toBe(true);
- });
-
- it('should not display a message about no results', () => {
- 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/milestones/stores/actions_spec.js b/spec/frontend/milestones/stores/actions_spec.js
index ad73d0e4238..a62b0c49a80 100644
--- a/spec/frontend/milestones/stores/actions_spec.js
+++ b/spec/frontend/milestones/stores/actions_spec.js
@@ -4,6 +4,7 @@ import * as actions from '~/milestones/stores/actions';
import * as types from '~/milestones/stores/mutation_types';
let mockProjectMilestonesReturnValue;
+let mockGroupMilestonesReturnValue;
let mockProjectSearchReturnValue;
jest.mock('~/api', () => ({
@@ -13,6 +14,7 @@ jest.mock('~/api', () => ({
default: {
projectMilestones: () => mockProjectMilestonesReturnValue,
projectSearch: () => mockProjectSearchReturnValue,
+ groupMilestones: () => mockGroupMilestonesReturnValue,
},
}));
@@ -32,6 +34,24 @@ describe('Milestone combobox Vuex store actions', () => {
});
});
+ describe('setGroupId', () => {
+ it(`commits ${types.SET_GROUP_ID} with the new group ID`, () => {
+ const groupId = '123';
+ testAction(actions.setGroupId, groupId, state, [
+ { type: types.SET_GROUP_ID, payload: groupId },
+ ]);
+ });
+ });
+
+ describe('setGroupMilestonesAvailable', () => {
+ it(`commits ${types.SET_GROUP_MILESTONES_AVAILABLE} with the boolean indicating if group milestones are available (Premium)`, () => {
+ state.groupMilestonesAvailable = true;
+ testAction(actions.setGroupMilestonesAvailable, state.groupMilestonesAvailable, state, [
+ { type: types.SET_GROUP_MILESTONES_AVAILABLE, payload: state.groupMilestonesAvailable },
+ ]);
+ });
+ });
+
describe('setSelectedMilestones', () => {
it(`commits ${types.SET_SELECTED_MILESTONES} with the new selected milestones name`, () => {
const selectedMilestones = ['v1.2.3'];
@@ -41,6 +61,14 @@ describe('Milestone combobox Vuex store actions', () => {
});
});
+ describe('clearSelectedMilestones', () => {
+ it(`commits ${types.CLEAR_SELECTED_MILESTONES} with the new selected milestones name`, () => {
+ testAction(actions.clearSelectedMilestones, null, state, [
+ { type: types.CLEAR_SELECTED_MILESTONES },
+ ]);
+ });
+ });
+
describe('toggleMilestones', () => {
const selectedMilestone = 'v1.2.3';
it(`commits ${types.ADD_SELECTED_MILESTONE} with the new selected milestone name`, () => {
@@ -58,19 +86,38 @@ describe('Milestone combobox Vuex store actions', () => {
});
describe('search', () => {
- it(`commits ${types.SET_QUERY} with the new search query`, () => {
- const query = 'v1.0';
- testAction(
- actions.search,
- query,
- state,
- [{ type: types.SET_QUERY, payload: query }],
- [{ type: 'searchMilestones' }],
- );
+ describe('when project has license to add group milestones', () => {
+ it(`commits ${types.SET_SEARCH_QUERY} with the new search query to search for project and group milestones`, () => {
+ const getters = {
+ groupMilestonesEnabled: () => true,
+ };
+
+ const searchQuery = 'v1.0';
+ testAction(
+ actions.search,
+ searchQuery,
+ { ...state, ...getters },
+ [{ type: types.SET_SEARCH_QUERY, payload: searchQuery }],
+ [{ type: 'searchProjectMilestones' }, { type: 'searchGroupMilestones' }],
+ );
+ });
+ });
+
+ describe('when project does not have license to add group milestones', () => {
+ it(`commits ${types.SET_SEARCH_QUERY} with the new search query to search for project milestones`, () => {
+ const searchQuery = 'v1.0';
+ testAction(
+ actions.search,
+ searchQuery,
+ state,
+ [{ type: types.SET_SEARCH_QUERY, payload: searchQuery }],
+ [{ type: 'searchProjectMilestones' }],
+ );
+ });
});
});
- describe('searchMilestones', () => {
+ describe('searchProjectMilestones', () => {
describe('when the search is successful', () => {
const projectSearchApiResponse = { data: [{ title: 'v1.0' }] };
@@ -79,7 +126,7 @@ describe('Milestone combobox Vuex store actions', () => {
});
it(`commits ${types.REQUEST_START}, ${types.RECEIVE_PROJECT_MILESTONES_SUCCESS} with the response from the API, and ${types.REQUEST_FINISH}`, () => {
- return testAction(actions.searchMilestones, undefined, state, [
+ return testAction(actions.searchProjectMilestones, undefined, state, [
{ type: types.REQUEST_START },
{ type: types.RECEIVE_PROJECT_MILESTONES_SUCCESS, payload: projectSearchApiResponse },
{ type: types.REQUEST_FINISH },
@@ -95,7 +142,7 @@ describe('Milestone combobox Vuex store actions', () => {
});
it(`commits ${types.REQUEST_START}, ${types.RECEIVE_PROJECT_MILESTONES_ERROR} with the error object, and ${types.REQUEST_FINISH}`, () => {
- return testAction(actions.searchMilestones, undefined, state, [
+ return testAction(actions.searchProjectMilestones, undefined, state, [
{ type: types.REQUEST_START },
{ type: types.RECEIVE_PROJECT_MILESTONES_ERROR, payload: error },
{ type: types.REQUEST_FINISH },
@@ -104,7 +151,71 @@ describe('Milestone combobox Vuex store actions', () => {
});
});
+ describe('searchGroupMilestones', () => {
+ describe('when the search is successful', () => {
+ const groupSearchApiResponse = { data: [{ title: 'group-v1.0' }] };
+
+ beforeEach(() => {
+ mockGroupMilestonesReturnValue = Promise.resolve(groupSearchApiResponse);
+ });
+
+ it(`commits ${types.REQUEST_START}, ${types.RECEIVE_GROUP_MILESTONES_SUCCESS} with the response from the API, and ${types.REQUEST_FINISH}`, () => {
+ return testAction(actions.searchGroupMilestones, undefined, state, [
+ { type: types.REQUEST_START },
+ { type: types.RECEIVE_GROUP_MILESTONES_SUCCESS, payload: groupSearchApiResponse },
+ { type: types.REQUEST_FINISH },
+ ]);
+ });
+ });
+
+ describe('when the search fails', () => {
+ const error = new Error('Something went wrong!');
+
+ beforeEach(() => {
+ mockGroupMilestonesReturnValue = Promise.reject(error);
+ });
+
+ it(`commits ${types.REQUEST_START}, ${types.RECEIVE_GROUP_MILESTONES_ERROR} with the error object, and ${types.REQUEST_FINISH}`, () => {
+ return testAction(actions.searchGroupMilestones, undefined, state, [
+ { type: types.REQUEST_START },
+ { type: types.RECEIVE_GROUP_MILESTONES_ERROR, payload: error },
+ { type: types.REQUEST_FINISH },
+ ]);
+ });
+ });
+ });
+
describe('fetchMilestones', () => {
+ describe('when project has license to add group milestones', () => {
+ it(`dispatchs fetchProjectMilestones and fetchGroupMilestones`, () => {
+ const getters = {
+ groupMilestonesEnabled: () => true,
+ };
+
+ testAction(
+ actions.fetchMilestones,
+ undefined,
+ { ...state, ...getters },
+ [],
+ [{ type: 'fetchProjectMilestones' }, { type: 'fetchGroupMilestones' }],
+ );
+ });
+ });
+
+ describe('when project does not have license to add group milestones', () => {
+ it(`dispatchs fetchProjectMilestones`, () => {
+ testAction(
+ actions.fetchMilestones,
+ undefined,
+ state,
+ [],
+ [{ type: 'fetchProjectMilestones' }],
+ );
+ });
+ });
+ });
+
+ describe('fetchProjectMilestones', () => {
describe('when the fetch is successful', () => {
const projectMilestonesApiResponse = { data: [{ title: 'v1.0' }] };
@@ -113,7 +224,7 @@ describe('Milestone combobox Vuex store actions', () => {
});
it(`commits ${types.REQUEST_START}, ${types.RECEIVE_PROJECT_MILESTONES_SUCCESS} with the response from the API, and ${types.REQUEST_FINISH}`, () => {
- return testAction(actions.fetchMilestones, undefined, state, [
+ return testAction(actions.fetchProjectMilestones, undefined, state, [
{ type: types.REQUEST_START },
{ type: types.RECEIVE_PROJECT_MILESTONES_SUCCESS, payload: projectMilestonesApiResponse },
{ type: types.REQUEST_FINISH },
@@ -129,7 +240,7 @@ describe('Milestone combobox Vuex store actions', () => {
});
it(`commits ${types.REQUEST_START}, ${types.RECEIVE_PROJECT_MILESTONES_ERROR} with the error object, and ${types.REQUEST_FINISH}`, () => {
- return testAction(actions.fetchMilestones, undefined, state, [
+ return testAction(actions.fetchProjectMilestones, undefined, state, [
{ type: types.REQUEST_START },
{ type: types.RECEIVE_PROJECT_MILESTONES_ERROR, payload: error },
{ type: types.REQUEST_FINISH },
@@ -137,4 +248,38 @@ describe('Milestone combobox Vuex store actions', () => {
});
});
});
+
+ describe('fetchGroupMilestones', () => {
+ describe('when the fetch is successful', () => {
+ const groupMilestonesApiResponse = { data: [{ title: 'group-v1.0' }] };
+
+ beforeEach(() => {
+ mockGroupMilestonesReturnValue = Promise.resolve(groupMilestonesApiResponse);
+ });
+
+ it(`commits ${types.REQUEST_START}, ${types.RECEIVE_GROUP_MILESTONES_SUCCESS} with the response from the API, and ${types.REQUEST_FINISH}`, () => {
+ return testAction(actions.fetchGroupMilestones, undefined, state, [
+ { type: types.REQUEST_START },
+ { type: types.RECEIVE_GROUP_MILESTONES_SUCCESS, payload: groupMilestonesApiResponse },
+ { type: types.REQUEST_FINISH },
+ ]);
+ });
+ });
+
+ describe('when the fetch fails', () => {
+ const error = new Error('Something went wrong!');
+
+ beforeEach(() => {
+ mockGroupMilestonesReturnValue = Promise.reject(error);
+ });
+
+ it(`commits ${types.REQUEST_START}, ${types.RECEIVE_GROUP_MILESTONES_ERROR} with the error object, and ${types.REQUEST_FINISH}`, () => {
+ return testAction(actions.fetchGroupMilestones, undefined, state, [
+ { type: types.REQUEST_START },
+ { type: types.RECEIVE_GROUP_MILESTONES_ERROR, payload: error },
+ { type: types.REQUEST_FINISH },
+ ]);
+ });
+ });
+ });
});
diff --git a/spec/frontend/milestones/stores/getter_spec.js b/spec/frontend/milestones/stores/getter_spec.js
index df7c3d28e67..4a6116b642c 100644
--- a/spec/frontend/milestones/stores/getter_spec.js
+++ b/spec/frontend/milestones/stores/getter_spec.js
@@ -12,4 +12,22 @@ describe('Milestone comboxbox Vuex store getters', () => {
expect(getters.isLoading({ requestCount })).toBe(isLoading);
});
});
+
+ describe('groupMilestonesEnabled', () => {
+ it.each`
+ groupId | groupMilestonesAvailable | groupMilestonesEnabled
+ ${'1'} | ${true} | ${true}
+ ${'1'} | ${false} | ${false}
+ ${''} | ${true} | ${false}
+ ${''} | ${false} | ${false}
+ ${null} | ${true} | ${false}
+ `(
+ 'returns true when groupId is a truthy string and groupMilestonesAvailable is true',
+ ({ groupId, groupMilestonesAvailable, groupMilestonesEnabled }) => {
+ expect(getters.groupMilestonesEnabled({ groupId, groupMilestonesAvailable })).toBe(
+ groupMilestonesEnabled,
+ );
+ },
+ );
+ });
});
diff --git a/spec/frontend/milestones/stores/mutations_spec.js b/spec/frontend/milestones/stores/mutations_spec.js
index 8f8ce3c87ad..0b69a9d572d 100644
--- a/spec/frontend/milestones/stores/mutations_spec.js
+++ b/spec/frontend/milestones/stores/mutations_spec.js
@@ -14,13 +14,19 @@ describe('Milestones combobox Vuex store mutations', () => {
expect(state).toEqual({
projectId: null,
groupId: null,
- query: '',
+ groupMilestonesAvailable: false,
+ searchQuery: '',
matches: {
projectMilestones: {
list: [],
totalCount: 0,
error: null,
},
+ groupMilestones: {
+ list: [],
+ totalCount: 0,
+ error: null,
+ },
},
selectedMilestones: [],
requestCount: 0,
@@ -37,6 +43,24 @@ describe('Milestones combobox Vuex store mutations', () => {
});
});
+ describe(`${types.SET_GROUP_ID}`, () => {
+ it('updates the group ID', () => {
+ const newGroupId = '8';
+ mutations[types.SET_GROUP_ID](state, newGroupId);
+
+ expect(state.groupId).toBe(newGroupId);
+ });
+ });
+
+ describe(`${types.SET_GROUP_MILESTONES_AVAILABLE}`, () => {
+ it('sets boolean indicating if group milestones are available', () => {
+ const groupMilestonesAvailable = true;
+ mutations[types.SET_GROUP_MILESTONES_AVAILABLE](state, groupMilestonesAvailable);
+
+ expect(state.groupMilestonesAvailable).toBe(groupMilestonesAvailable);
+ });
+ });
+
describe(`${types.SET_SELECTED_MILESTONES}`, () => {
it('sets the selected milestones', () => {
const selectedMilestones = ['v1.2.3'];
@@ -46,7 +70,21 @@ describe('Milestones combobox Vuex store mutations', () => {
});
});
- describe(`${types.ADD_SELECTED_MILESTONESs}`, () => {
+ describe(`${types.CLEAR_SELECTED_MILESTONES}`, () => {
+ it('clears the selected milestones', () => {
+ const selectedMilestones = ['v1.2.3'];
+
+ // Set state.selectedMilestones
+ mutations[types.SET_SELECTED_MILESTONES](state, selectedMilestones);
+
+ // Clear state.selectedMilestones
+ mutations[types.CLEAR_SELECTED_MILESTONES](state);
+
+ expect(state.selectedMilestones).toEqual([]);
+ });
+ });
+
+ describe(`${types.ADD_SELECTED_MILESTONES}`, () => {
it('adds the selected milestones', () => {
const selectedMilestone = 'v1.2.3';
mutations[types.ADD_SELECTED_MILESTONE](state, selectedMilestone);
@@ -67,12 +105,12 @@ describe('Milestones combobox Vuex store mutations', () => {
});
});
- describe(`${types.SET_QUERY}`, () => {
+ describe(`${types.SET_SEARCH_QUERY}`, () => {
it('updates the search query', () => {
const newQuery = 'hello';
- mutations[types.SET_QUERY](state, newQuery);
+ mutations[types.SET_SEARCH_QUERY](state, newQuery);
- expect(state.query).toBe(newQuery);
+ expect(state.searchQuery).toBe(newQuery);
});
});
@@ -156,4 +194,57 @@ describe('Milestones combobox Vuex store mutations', () => {
});
});
});
+
+ describe(`${types.RECEIVE_GROUP_MILESTONES_SUCCESS}`, () => {
+ it('updates state.matches.groupMilestones based on the provided API response', () => {
+ const response = {
+ data: [
+ {
+ title: 'group-0.1',
+ },
+ {
+ title: 'group-0.2',
+ },
+ ],
+ headers: {
+ 'x-total': 2,
+ },
+ };
+
+ mutations[types.RECEIVE_GROUP_MILESTONES_SUCCESS](state, response);
+
+ expect(state.matches.groupMilestones).toEqual({
+ list: [
+ {
+ title: 'group-0.1',
+ },
+ {
+ title: 'group-0.2',
+ },
+ ],
+ error: null,
+ totalCount: 2,
+ });
+ });
+
+ describe(`${types.RECEIVE_GROUP_MILESTONES_ERROR}`, () => {
+ it('updates state.matches.groupMilestones to an empty state with the error object', () => {
+ const error = new Error('Something went wrong!');
+
+ state.matches.groupMilestones = {
+ list: [{ title: 'group-0.1' }],
+ totalCount: 1,
+ error: null,
+ };
+
+ mutations[types.RECEIVE_GROUP_MILESTONES_ERROR](state, error);
+
+ expect(state.matches.groupMilestones).toEqual({
+ list: [],
+ totalCount: 0,
+ error,
+ });
+ });
+ });
+ });
});
diff --git a/spec/frontend/monitoring/components/charts/column_spec.js b/spec/frontend/monitoring/components/charts/column_spec.js
index 16e2080c000..fbcff33d692 100644
--- a/spec/frontend/monitoring/components/charts/column_spec.js
+++ b/spec/frontend/monitoring/components/charts/column_spec.js
@@ -30,6 +30,7 @@ describe('Column component', () => {
},
metrics: [
{
+ label: 'Mock data',
result: [
{
metric: {},
@@ -96,7 +97,7 @@ describe('Column component', () => {
describe('wrapped components', () => {
describe('GitLab UI column chart', () => {
it('receives data properties needed for proper chart render', () => {
- expect(chartProps('data').values).toEqual(dataValues);
+ expect(chartProps('bars')).toEqual([{ name: 'Mock data', data: dataValues }]);
});
it('passes the y axis name correctly', () => {
diff --git a/spec/frontend/monitoring/components/charts/stacked_column_spec.js b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
index 24a2af87eb8..2032258730a 100644
--- a/spec/frontend/monitoring/components/charts/stacked_column_spec.js
+++ b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
@@ -44,19 +44,19 @@ describe('Stacked column chart component', () => {
});
it('data should match the graphData y value for each series', () => {
- const data = findChart().props('data');
+ const data = findChart().props('bars');
data.forEach((series, index) => {
const { values } = stackedColumnMockedData.metrics[index].result[0];
- expect(series).toEqual(values.map(value => value[1]));
+ expect(series.data).toEqual(values.map(value => value[1]));
});
});
- it('series names should be the same as the graphData metrics labels', () => {
- const seriesNames = findChart().props('seriesNames');
+ it('data should be the same length as the graphData metrics labels', () => {
+ const barDataProp = findChart().props('bars');
- expect(seriesNames).toHaveLength(stackedColumnMockedData.metrics.length);
- seriesNames.forEach((name, index) => {
+ expect(barDataProp).toHaveLength(stackedColumnMockedData.metrics.length);
+ barDataProp.forEach(({ name }, index) => {
expect(stackedColumnMockedData.metrics[index].label).toBe(name);
});
});
diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js
index 7f0ff534db3..8fcee80a2d8 100644
--- a/spec/frontend/monitoring/components/charts/time_series_spec.js
+++ b/spec/frontend/monitoring/components/charts/time_series_spec.js
@@ -226,7 +226,7 @@ describe('Time series component', () => {
]);
expect(
- shallowWrapperContainsSlotText(wrapper.find(GlLineChart), 'tooltipContent', value),
+ shallowWrapperContainsSlotText(wrapper.find(GlLineChart), 'tooltip-content', value),
).toBe(true);
});
@@ -651,7 +651,7 @@ describe('Time series component', () => {
return wrapper.vm.$nextTick(() => {
expect(
- shallowWrapperContainsSlotText(findChartComponent(), 'tooltipTitle', mockTitle),
+ shallowWrapperContainsSlotText(findChartComponent(), 'tooltip-title', mockTitle),
).toBe(true);
});
});
@@ -671,7 +671,7 @@ describe('Time series component', () => {
it('uses deployment title', () => {
expect(
- shallowWrapperContainsSlotText(findChartComponent(), 'tooltipTitle', 'Deployed'),
+ shallowWrapperContainsSlotText(findChartComponent(), 'tooltip-title', 'Deployed'),
).toBe(true);
});
diff --git a/spec/frontend/monitoring/components/dashboard_panel_spec.js b/spec/frontend/monitoring/components/dashboard_panel_spec.js
index ee0e1fd3176..1808faf8f0e 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_spec.js
@@ -106,7 +106,7 @@ describe('Dashboard Panel', () => {
{},
{
slots: {
- topLeft: `<div class="top-left-content">OK</div>`,
+ 'top-left': `<div class="top-left-content">OK</div>`,
},
},
);
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index b7a0ea46b61..27e479ba498 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -508,7 +508,7 @@ describe('Dashboard', () => {
const mockKeyup = key => window.dispatchEvent(new KeyboardEvent('keyup', { key }));
const MockPanel = {
- template: `<div><slot name="topLeft"/></div>`,
+ template: `<div><slot name="top-left"/></div>`,
};
beforeEach(() => {
diff --git a/spec/frontend/monitoring/components/embeds/embed_group_spec.js b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
index b63995ec2d4..01089752933 100644
--- a/spec/frontend/monitoring/components/embeds/embed_group_spec.js
+++ b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
@@ -73,7 +73,7 @@ describe('Embed Group', () => {
metricsWithDataGetter.mockReturnValue([1]);
mountComponent({ shallow: false, stubs: { MetricEmbed: true } });
- expect(wrapper.find('.card-body').classes()).not.toContain('d-none');
+ expect(wrapper.find('.gl-card-body').classes()).not.toContain('d-none');
});
it('collapses when clicked', done => {
@@ -83,7 +83,7 @@ describe('Embed Group', () => {
wrapper.find(GlButton).trigger('click');
wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.card-body').classes()).toContain('d-none');
+ expect(wrapper.find('.gl-card-body').classes()).toContain('d-none');
done();
});
});
diff --git a/spec/frontend/monitoring/components/variables/dropdown_field_spec.js b/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
index 788f3abf617..cc384aef231 100644
--- a/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
+++ b/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlDeprecatedDropdown, GlDeprecatedDropdownItem } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import DropdownField from '~/monitoring/components/variables/dropdown_field.vue';
describe('Custom variable component', () => {
@@ -23,8 +23,8 @@ describe('Custom variable component', () => {
});
};
- const findDropdown = () => wrapper.find(GlDeprecatedDropdown);
- const findDropdownItems = () => wrapper.findAll(GlDeprecatedDropdownItem);
+ const findDropdown = () => wrapper.find(GlDropdown);
+ const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
it('renders dropdown element when all necessary props are passed', () => {
createShallowWrapper();
diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js
index 3e1e43d0c6a..b26eb00bfdc 100644
--- a/spec/frontend/notes/components/discussion_actions_spec.js
+++ b/spec/frontend/notes/components/discussion_actions_spec.js
@@ -13,11 +13,11 @@ const createDiscussionMock = (props = {}) =>
const createNoteMock = (props = {}) =>
Object.assign(JSON.parse(JSON.stringify(discussionMock.notes[0])), props);
const createResolvableNote = () =>
- createNoteMock({ resolvable: true, current_user: { can_resolve: true } });
+ createNoteMock({ resolvable: true, current_user: { can_resolve_discussion: true } });
const createUnresolvableNote = () =>
- createNoteMock({ resolvable: false, current_user: { can_resolve: false } });
+ createNoteMock({ resolvable: false, current_user: { can_resolve_discussion: false } });
const createUnallowedNote = () =>
- createNoteMock({ resolvable: true, current_user: { can_resolve: false } });
+ createNoteMock({ resolvable: true, current_user: { can_resolve_discussion: false } });
describe('DiscussionActions', () => {
let wrapper;
diff --git a/spec/frontend/notes/components/discussion_filter_note_spec.js b/spec/frontend/notes/components/discussion_filter_note_spec.js
index 4701108d315..d35f8f7c28d 100644
--- a/spec/frontend/notes/components/discussion_filter_note_spec.js
+++ b/spec/frontend/notes/components/discussion_filter_note_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { GlButton, GlSprintf } from '@gitlab/ui';
import DiscussionFilterNote from '~/notes/components/discussion_filter_note.vue';
import eventHub from '~/notes/event_hub';
@@ -6,7 +7,11 @@ describe('DiscussionFilterNote component', () => {
let wrapper;
const createComponent = () => {
- wrapper = shallowMount(DiscussionFilterNote);
+ wrapper = shallowMount(DiscussionFilterNote, {
+ stubs: {
+ GlSprintf,
+ },
+ });
};
beforeEach(() => {
@@ -19,21 +24,27 @@ describe('DiscussionFilterNote component', () => {
});
it('timelineContent renders a string containing instruction for switching feed type', () => {
- expect(wrapper.find({ ref: 'timelineContent' }).html()).toBe(
- "<div>You're only seeing <b>other activity</b> in the feed. To add a comment, switch to one of the following options.</div>",
+ expect(wrapper.find('[data-testid="discussion-filter-timeline-content"]').html()).toBe(
+ '<div data-testid="discussion-filter-timeline-content">You\'re only seeing <b>other activity</b> in the feed. To add a comment, switch to one of the following options.</div>',
);
});
it('emits `dropdownSelect` event with 0 parameter on clicking Show all activity button', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- wrapper.find({ ref: 'showAllActivity' }).vm.$emit('click');
+ wrapper
+ .findAll(GlButton)
+ .at(0)
+ .vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('dropdownSelect', 0);
});
it('emits `dropdownSelect` event with 1 parameter on clicking Show comments only button', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- wrapper.find({ ref: 'showComments' }).vm.$emit('click');
+ wrapper
+ .findAll(GlButton)
+ .at(1)
+ .vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('dropdownSelect', 1);
});
diff --git a/spec/frontend/notes/components/note_actions_spec.js b/spec/frontend/notes/components/note_actions_spec.js
index a79c3bbacb7..f01c6c6b84e 100644
--- a/spec/frontend/notes/components/note_actions_spec.js
+++ b/spec/frontend/notes/components/note_actions_spec.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import { shallowMount, createLocalVue, createWrapper } from '@vue/test-utils';
+import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
import { TEST_HOST } from 'spec/test_constants';
import AxiosMockAdapter from 'axios-mock-adapter';
import createStore from '~/notes/stores';
@@ -14,9 +14,9 @@ describe('noteActions', () => {
let actions;
let axiosMock;
- const shallowMountNoteActions = (propsData, computed) => {
+ const mountNoteActions = (propsData, computed) => {
const localVue = createLocalVue();
- return shallowMount(localVue.extend(noteActions), {
+ return mount(localVue.extend(noteActions), {
store,
propsData,
localVue,
@@ -61,7 +61,7 @@ describe('noteActions', () => {
beforeEach(() => {
store.dispatch('setUserData', userDataMock);
- wrapper = shallowMountNoteActions(props);
+ wrapper = mountNoteActions(props);
});
it('should render noteable author badge', () => {
@@ -178,7 +178,7 @@ describe('noteActions', () => {
};
beforeEach(() => {
- wrapper = shallowMountNoteActions(props, {
+ wrapper = mountNoteActions(props, {
targetType: () => 'issue',
});
store.state.noteableData = {
@@ -205,7 +205,7 @@ describe('noteActions', () => {
};
beforeEach(() => {
- wrapper = shallowMountNoteActions(props, {
+ wrapper = mountNoteActions(props, {
targetType: () => 'issue',
});
});
@@ -221,7 +221,7 @@ describe('noteActions', () => {
describe('user is not logged in', () => {
beforeEach(() => {
store.dispatch('setUserData', {});
- wrapper = shallowMountNoteActions({
+ wrapper = mountNoteActions({
...props,
canDelete: false,
canEdit: false,
@@ -241,7 +241,7 @@ describe('noteActions', () => {
describe('for showReply = true', () => {
beforeEach(() => {
- wrapper = shallowMountNoteActions({
+ wrapper = mountNoteActions({
...props,
showReply: true,
});
@@ -256,7 +256,7 @@ describe('noteActions', () => {
describe('for showReply = false', () => {
beforeEach(() => {
- wrapper = shallowMountNoteActions({
+ wrapper = mountNoteActions({
...props,
showReply: false,
});
@@ -273,7 +273,7 @@ describe('noteActions', () => {
beforeEach(() => {
store.dispatch('setUserData', userDataMock);
- wrapper = shallowMountNoteActions({ ...props, canResolve: true, isDraft: true });
+ wrapper = mountNoteActions({ ...props, canResolve: true, isDraft: true });
});
it('should render the right resolve button title', () => {
diff --git a/spec/frontend/notes/components/note_awards_list_spec.js b/spec/frontend/notes/components/note_awards_list_spec.js
index dce5424f154..5ab183e5452 100644
--- a/spec/frontend/notes/components/note_awards_list_spec.js
+++ b/spec/frontend/notes/components/note_awards_list_spec.js
@@ -92,15 +92,14 @@ describe('note_awards_list component', () => {
}).$mount();
};
- const findTooltip = () =>
- vm.$el.querySelector('[data-original-title]').getAttribute('data-original-title');
+ const findTooltip = () => vm.$el.querySelector('[title]').getAttribute('title');
it('should only escape & and " characters', () => {
awardsMock = [...new Array(1)].map(createAwardEmoji);
mountComponent();
const escapedName = awardsMock[0].user.name.replace(/&/g, '&amp;').replace(/"/g, '&quot;');
- expect(vm.$el.querySelector('[data-original-title]').outerHTML).toContain(escapedName);
+ expect(vm.$el.querySelector('[title]').outerHTML).toContain(escapedName);
});
it('should not escape special HTML characters twice when only 1 person awarded', () => {
diff --git a/spec/frontend/notes/components/note_form_spec.js b/spec/frontend/notes/components/note_form_spec.js
index a5b5204509e..cc434d6c952 100644
--- a/spec/frontend/notes/components/note_form_spec.js
+++ b/spec/frontend/notes/components/note_form_spec.js
@@ -272,6 +272,7 @@ describe('issue_note_form component', () => {
wrapper = createComponentWrapper();
wrapper.setProps({
...props,
+ isDraft: true,
noteId: '',
discussion: { ...discussionMock, for_commit: false },
});
@@ -292,6 +293,27 @@ describe('issue_note_form component', () => {
expect(wrapper.find('.js-resolve-checkbox').exists()).toBe(true);
});
+ it('hides resolve checkbox', async () => {
+ wrapper.setProps({
+ isDraft: false,
+ discussion: {
+ ...discussionMock,
+ notes: [
+ ...discussionMock.notes.map(n => ({
+ ...n,
+ resolvable: true,
+ current_user: { ...n.current_user, can_resolve_discussion: false },
+ })),
+ ],
+ for_commit: false,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find('.js-resolve-checkbox').exists()).toBe(false);
+ });
+
it('hides actions for commits', () => {
wrapper.setProps({ discussion: { for_commit: true } });
diff --git a/spec/frontend/notes/components/note_header_spec.js b/spec/frontend/notes/components/note_header_spec.js
index 2bb08b60569..69aab0d051e 100644
--- a/spec/frontend/notes/components/note_header_spec.js
+++ b/spec/frontend/notes/components/note_header_spec.js
@@ -1,7 +1,9 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
import Vuex from 'vuex';
+import { GlSprintf } from '@gitlab/ui';
import NoteHeader from '~/notes/components/note_header.vue';
+import { AVAILABILITY_STATUS } from '~/set_status_modal/utils';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -28,6 +30,9 @@ describe('NoteHeader component', () => {
path: '/root',
state: 'active',
username: 'root',
+ status: {
+ availability: '',
+ },
};
const createComponent = props => {
@@ -37,6 +42,7 @@ describe('NoteHeader component', () => {
actions,
}),
propsData: { ...props },
+ stubs: { GlSprintf },
});
};
@@ -78,7 +84,7 @@ describe('NoteHeader component', () => {
expanded: true,
});
- expect(findChevronIcon().classes()).toContain('fa-chevron-up');
+ expect(findChevronIcon().props('name')).toBe('chevron-up');
});
it('has chevron-down icon if expanded prop is false', () => {
@@ -87,7 +93,7 @@ describe('NoteHeader component', () => {
expanded: false,
});
- expect(findChevronIcon().classes()).toContain('fa-chevron-down');
+ expect(findChevronIcon().props('name')).toBe('chevron-down');
});
});
@@ -97,6 +103,12 @@ describe('NoteHeader component', () => {
expect(wrapper.find('.js-user-link').exists()).toBe(true);
});
+ it('renders busy status if author availability is set', () => {
+ createComponent({ author: { ...author, status: { availability: AVAILABILITY_STATUS.BUSY } } });
+
+ expect(wrapper.find('.js-user-link').text()).toContain('(Busy)');
+ });
+
it('renders deleted user text if author is not passed as a prop', () => {
createComponent();
diff --git a/spec/frontend/notes/mock_data.js b/spec/frontend/notes/mock_data.js
index 4ff64abe4cc..638a4edecd6 100644
--- a/spec/frontend/notes/mock_data.js
+++ b/spec/frontend/notes/mock_data.js
@@ -7,7 +7,7 @@ export const notesDataMock = {
newSessionPath: '/users/sign_in?redirect_to_referer=yes',
notesPath: '/gitlab-org/gitlab-foss/noteable/issue/98/notes',
quickActionsDocsPath: '/help/user/project/quick_actions',
- registerPath: '/users/sign_in?redirect_to_referer=yes#register-pane',
+ registerPath: '/users/sign_up?redirect_to_referer=yes',
prerenderedNotesCount: 1,
closePath: '/twitter/flight/issues/9.json?issue%5Bstate_event%5D=close',
reopenPath: '/twitter/flight/issues/9.json?issue%5Bstate_event%5D=reopen',
@@ -202,6 +202,7 @@ export const discussionMock = {
can_edit: true,
can_award_emoji: true,
can_resolve: true,
+ can_resolve_discussion: true,
},
discussion_id: '9e3bd2f71a01de45fd166e6719eb380ad9f270b1',
emoji_awardable: true,
@@ -249,6 +250,7 @@ export const discussionMock = {
can_edit: true,
can_award_emoji: true,
can_resolve: true,
+ can_resolve_discussion: true,
},
discussion_id: '9e3bd2f71a01de45fd166e6719eb380ad9f270b1',
emoji_awardable: true,
@@ -296,6 +298,7 @@ export const discussionMock = {
can_edit: true,
can_award_emoji: true,
can_resolve: true,
+ can_resolve_discussion: true,
},
discussion_id: '9e3bd2f71a01de45fd166e6719eb380ad9f270b1',
emoji_awardable: true,
diff --git a/spec/frontend/packages/details/components/package_title_spec.js b/spec/frontend/packages/details/components/package_title_spec.js
index d0ed78418af..61c6e824ab7 100644
--- a/spec/frontend/packages/details/components/package_title_spec.js
+++ b/spec/frontend/packages/details/components/package_title_spec.js
@@ -1,5 +1,6 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlBreakpointInstance } from '@gitlab/ui/dist/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';
@@ -53,6 +54,7 @@ describe('PackageTitle', () => {
const pipelineProject = () => wrapper.find('[data-testid="pipeline-project"]');
const packageRef = () => wrapper.find('[data-testid="package-ref"]');
const packageTags = () => wrapper.find(PackageTags);
+ const packageBadges = () => wrapper.findAll('[data-testid="tag-badge"]');
afterEach(() => {
wrapper.destroy();
@@ -70,6 +72,14 @@ describe('PackageTitle', () => {
expect(wrapper.element).toMatchSnapshot();
});
+
+ it('with tags on mobile', async () => {
+ jest.spyOn(GlBreakpointInstance, 'isDesktop').mockReturnValue(false);
+ await createComponent({ packageEntity: { ...mavenPackage, tags: mockTags } });
+ await wrapper.vm.$nextTick();
+
+ expect(packageBadges()).toHaveLength(mockTags.length);
+ });
});
describe('package title', () => {
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 ce3a58c856d..d27038e765f 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
@@ -10,7 +10,7 @@ exports[`packages_list_app renders 1`] = `
activenavitemclass="gl-tab-nav-item-active gl-tab-nav-item-active-indigo"
class="gl-tabs"
contentclass=",gl-tab-content"
- navclass="gl-tabs-nav"
+ navclass=",gl-tabs-nav"
nofade="true"
nonavstyle="true"
tag="div"
diff --git a/spec/frontend/pages/labels/components/promote_label_modal_spec.js b/spec/frontend/pages/labels/components/promote_label_modal_spec.js
index 1fa12cf1365..f969808d78b 100644
--- a/spec/frontend/pages/labels/components/promote_label_modal_spec.js
+++ b/spec/frontend/pages/labels/components/promote_label_modal_spec.js
@@ -32,10 +32,9 @@ describe('Promote label modal', () => {
});
it('contains a label span with the color', () => {
- const labelFromTitle = vm.$el.querySelector('.modal-header .label.color-label');
-
- expect(labelFromTitle.style.backgroundColor).not.toBe(null);
- expect(labelFromTitle.textContent).toContain(vm.labelTitle);
+ expect(vm.labelColor).not.toBe(null);
+ expect(vm.labelColor).toBe(labelMockData.labelColor);
+ expect(vm.labelTitle).toBe(labelMockData.labelTitle);
});
});
diff --git a/spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js b/spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js
index 5da998d9d2d..cfe54016410 100644
--- a/spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js
+++ b/spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js
@@ -1,109 +1,98 @@
-import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
import Cookies from 'js-cookie';
import PipelineSchedulesCallout from '~/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue';
-const PipelineSchedulesCalloutComponent = Vue.extend(PipelineSchedulesCallout);
const cookieKey = 'pipeline_schedules_callout_dismissed';
const docsUrl = 'help/ci/scheduled_pipelines';
-const imageUrl = 'pages/projects/pipeline_schedules/shared/icons/intro_illustration.svg';
+const illustrationUrl = 'pages/projects/pipeline_schedules/shared/icons/intro_illustration.svg';
describe('Pipeline Schedule Callout', () => {
- let calloutComponent;
+ let wrapper;
- beforeEach(() => {
- setFixtures(`
- <div id='pipeline-schedules-callout' data-docs-url=${docsUrl} data-image-url=${imageUrl}></div>
- `);
- });
-
- describe('independent of cookies', () => {
- beforeEach(() => {
- calloutComponent = new PipelineSchedulesCalloutComponent().$mount();
- });
-
- it('the component can be initialized', () => {
- expect(calloutComponent).toBeDefined();
+ const createComponent = () => {
+ wrapper = shallowMount(PipelineSchedulesCallout, {
+ provide: {
+ docsUrl,
+ illustrationUrl,
+ },
});
+ };
- it('correctly sets docsUrl', () => {
- expect(calloutComponent.docsUrl).toContain(docsUrl);
- });
-
- it('correctly sets imageUrl', () => {
- expect(calloutComponent.imageUrl).toContain(imageUrl);
- });
- });
+ const findInnerContentOfCallout = () => wrapper.find('[data-testid="innerContent"]');
+ const findDismissCalloutBtn = () => wrapper.find(GlButton);
describe(`when ${cookieKey} cookie is set`, () => {
- beforeEach(() => {
+ beforeEach(async () => {
Cookies.set(cookieKey, true);
- calloutComponent = new PipelineSchedulesCalloutComponent().$mount();
+ createComponent();
+
+ await wrapper.vm.$nextTick();
});
- it('correctly sets calloutDismissed to true', () => {
- expect(calloutComponent.calloutDismissed).toBe(true);
+ afterEach(() => {
+ wrapper.destroy();
});
it('does not render the callout', () => {
- expect(calloutComponent.$el.childNodes.length).toBe(0);
+ expect(findInnerContentOfCallout().exists()).toBe(false);
});
});
describe('when cookie is not set', () => {
beforeEach(() => {
Cookies.remove(cookieKey);
- calloutComponent = new PipelineSchedulesCalloutComponent().$mount();
+ createComponent();
});
- it('correctly sets calloutDismissed to false', () => {
- expect(calloutComponent.calloutDismissed).toBe(false);
+ afterEach(() => {
+ wrapper.destroy();
});
it('renders the callout container', () => {
- expect(calloutComponent.$el.querySelector('.bordered-box')).not.toBeNull();
- });
-
- it('renders the callout img', () => {
- expect(calloutComponent.$el.outerHTML).toContain('<img');
+ expect(findInnerContentOfCallout().exists()).toBe(true);
});
it('renders the callout title', () => {
- expect(calloutComponent.$el.outerHTML).toContain('Scheduling Pipelines');
+ expect(wrapper.find('h4').text()).toBe('Scheduling Pipelines');
});
it('renders the callout text', () => {
- expect(calloutComponent.$el.outerHTML).toContain('runs pipelines in the future');
+ expect(wrapper.find('p').text()).toContain('runs pipelines in the future');
});
it('renders the documentation url', () => {
- expect(calloutComponent.$el.outerHTML).toContain(docsUrl);
+ expect(wrapper.find('a').attributes('href')).toBe(docsUrl);
});
- it('updates calloutDismissed when close button is clicked', done => {
- calloutComponent.$el.querySelector('#dismiss-callout-btn').click();
+ describe('methods', () => {
+ it('#dismissCallout sets calloutDismissed to true', async () => {
+ expect(wrapper.vm.calloutDismissed).toBe(false);
+
+ findDismissCalloutBtn().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
- Vue.nextTick(() => {
- expect(calloutComponent.calloutDismissed).toBe(true);
- done();
+ expect(findInnerContentOfCallout().exists()).toBe(false);
});
- });
- it('#dismissCallout updates calloutDismissed', done => {
- calloutComponent.dismissCallout();
+ it('sets cookie on dismiss', () => {
+ const setCookiesSpy = jest.spyOn(Cookies, 'set');
+
+ findDismissCalloutBtn().vm.$emit('click');
- Vue.nextTick(() => {
- expect(calloutComponent.calloutDismissed).toBe(true);
- done();
+ expect(setCookiesSpy).toHaveBeenCalledWith('pipeline_schedules_callout_dismissed', true, {
+ expires: 365,
+ });
});
});
- it('is hidden when close button is clicked', done => {
- calloutComponent.$el.querySelector('#dismiss-callout-btn').click();
+ it('is hidden when close button is clicked', async () => {
+ findDismissCalloutBtn().vm.$emit('click');
- Vue.nextTick(() => {
- expect(calloutComponent.$el.childNodes.length).toBe(0);
- done();
- });
+ await wrapper.vm.$nextTick();
+
+ expect(findInnerContentOfCallout().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/pages/search/show/highlight_blob_search_result_spec.js b/spec/frontend/pages/search/show/highlight_blob_search_result_spec.js
deleted file mode 100644
index 4083a65df75..00000000000
--- a/spec/frontend/pages/search/show/highlight_blob_search_result_spec.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import setHighlightClass from '~/pages/search/show/highlight_blob_search_result';
-
-const fixture = 'search/blob_search_result.html';
-
-describe('pages/search/show/highlight_blob_search_result', () => {
- preloadFixtures(fixture);
-
- beforeEach(() => loadFixtures(fixture));
-
- it('highlights lines with search term occurrence', () => {
- setHighlightClass();
-
- expect(document.querySelectorAll('.blob-result .hll').length).toBe(11);
- });
-});
diff --git a/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js b/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
index 0d9af0cb856..4b50342bf84 100644
--- a/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
+++ b/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
@@ -14,18 +14,16 @@ describe('preserve_url_fragment', () => {
loadFixtures('sessions/new.html');
});
- it('adds the url fragment to all login and sign up form actions', () => {
+ it('adds the url fragment to the login form actions', () => {
preserveUrlFragment('#L65');
expect($('#new_user').attr('action')).toBe('http://test.host/users/sign_in#L65');
- expect($('#new_new_user').attr('action')).toBe('http://test.host/users#L65');
});
- it('does not add an empty url fragment to login and sign up form actions', () => {
+ it('does not add an empty url fragment to the login form actions', () => {
preserveUrlFragment();
expect($('#new_user').attr('action')).toBe('http://test.host/users/sign_in');
- expect($('#new_new_user').attr('action')).toBe('http://test.host/users');
});
it('does not add an empty query parameter to OmniAuth login buttons', () => {
diff --git a/spec/frontend/performance_bar/components/detailed_metric_spec.js b/spec/frontend/performance_bar/components/detailed_metric_spec.js
index ff51b1184cb..739b45e2193 100644
--- a/spec/frontend/performance_bar/components/detailed_metric_spec.js
+++ b/spec/frontend/performance_bar/components/detailed_metric_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
import DetailedMetric from '~/performance_bar/components/detailed_metric.vue';
@@ -14,6 +15,11 @@ describe('detailedMetric', () => {
});
};
+ const findAllTraceBlocks = () => wrapper.findAll('pre');
+ const findTraceBlockAtIndex = index => findAllTraceBlocks().at(index);
+ const findExpandBacktraceBtns = () => wrapper.findAll('[data-testid="backtrace-expand-btn"]');
+ const findExpandedBacktraceBtnAtIndex = index => findExpandBacktraceBtns().at(index);
+
afterEach(() => {
wrapper.destroy();
});
@@ -37,7 +43,12 @@ describe('detailedMetric', () => {
describe('when the current request has details', () => {
const requestDetails = [
{ duration: '100', feature: 'find_commit', request: 'abcdef', backtrace: ['hello', 'world'] },
- { duration: '23', feature: 'rebase_in_progress', request: '', backtrace: ['world', 'hello'] },
+ {
+ duration: '23',
+ feature: 'rebase_in_progress',
+ request: '',
+ backtrace: ['other', 'example'],
+ },
];
describe('with a default metric name', () => {
@@ -82,7 +93,7 @@ describe('detailedMetric', () => {
expect(request.text()).toContain(requestDetails[index].request);
});
- expect(wrapper.find('.text-expander.js-toggle-button')).not.toBeNull();
+ expect(wrapper.find('.js-toggle-button')).not.toBeNull();
wrapper.findAll('.performance-bar-modal td:nth-child(2)').wrappers.forEach(request => {
expect(request.text()).toContain('world');
@@ -96,6 +107,30 @@ describe('detailedMetric', () => {
it('displays request warnings', () => {
expect(wrapper.find(RequestWarning).exists()).toBe(true);
});
+
+ it('can open and close traces', async () => {
+ expect(findAllTraceBlocks()).toHaveLength(0);
+
+ // Each block click on a new trace and assert that the correct
+ // count is open and that the content is what we expect to ensure
+ // we opened or closed the right one
+ const secondExpandButton = findExpandedBacktraceBtnAtIndex(1);
+
+ findExpandedBacktraceBtnAtIndex(0).vm.$emit('click');
+ await nextTick();
+ expect(findAllTraceBlocks()).toHaveLength(1);
+ expect(findTraceBlockAtIndex(0).text()).toContain(requestDetails[0].backtrace[0]);
+
+ secondExpandButton.vm.$emit('click');
+ await nextTick();
+ expect(findAllTraceBlocks()).toHaveLength(2);
+ expect(findTraceBlockAtIndex(1).text()).toContain(requestDetails[1].backtrace[0]);
+
+ secondExpandButton.vm.$emit('click');
+ await nextTick();
+ expect(findAllTraceBlocks()).toHaveLength(1);
+ expect(findTraceBlockAtIndex(0).text()).toContain(requestDetails[0].backtrace[0]);
+ });
});
describe('when using a custom metric title', () => {
@@ -140,7 +175,11 @@ describe('detailedMetric', () => {
});
});
- it('renders only the number of calls', () => {
+ it('renders only the number of calls', async () => {
+ expect(trimText(wrapper.text())).toEqual('456 notification bullet');
+
+ findExpandedBacktraceBtnAtIndex(0).vm.$emit('click');
+ await nextTick();
expect(trimText(wrapper.text())).toEqual('456 notification backtrace bullet');
});
});
diff --git a/spec/frontend/pipeline_editor/components/text_editor_spec.js b/spec/frontend/pipeline_editor/components/text_editor_spec.js
new file mode 100644
index 00000000000..39d205839f4
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/text_editor_spec.js
@@ -0,0 +1,41 @@
+import { shallowMount } from '@vue/test-utils';
+import EditorLite from '~/vue_shared/components/editor_lite.vue';
+import { mockCiYml } from '../mock_data';
+
+import TextEditor from '~/pipeline_editor/components/text_editor.vue';
+
+describe('~/pipeline_editor/components/text_editor.vue', () => {
+ let wrapper;
+
+ const createComponent = (props = {}, mountFn = shallowMount) => {
+ wrapper = mountFn(TextEditor, {
+ propsData: {
+ value: mockCiYml,
+ ...props,
+ },
+ });
+ };
+
+ const findEditor = () => wrapper.find(EditorLite);
+
+ it('contains an editor', () => {
+ createComponent();
+
+ expect(findEditor().exists()).toBe(true);
+ });
+
+ it('editor contains the value provided', () => {
+ expect(findEditor().props('value')).toBe(mockCiYml);
+ });
+
+ it('editor is readony and configured for .yml', () => {
+ expect(findEditor().props('editorOptions')).toEqual({ readOnly: true });
+ expect(findEditor().props('fileName')).toBe('*.yml');
+ });
+
+ it('bubbles up editor-ready event', () => {
+ findEditor().vm.$emit('editor-ready');
+
+ expect(wrapper.emitted('editor-ready')).toHaveLength(1);
+ });
+});
diff --git a/spec/frontend/pipeline_editor/graphql/resolvers_spec.js b/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
new file mode 100644
index 00000000000..90acdf3ec0b
--- /dev/null
+++ b/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
@@ -0,0 +1,42 @@
+import Api from '~/api';
+import { mockProjectPath, mockDefaultBranch, mockCiConfigPath, mockCiYml } from '../mock_data';
+
+import { resolvers } from '~/pipeline_editor/graphql/resolvers';
+
+jest.mock('~/api', () => {
+ return {
+ getRawFile: jest.fn(),
+ };
+});
+
+describe('~/pipeline_editor/graphql/resolvers', () => {
+ describe('Query', () => {
+ describe('blobContent', () => {
+ beforeEach(() => {
+ Api.getRawFile.mockResolvedValue({
+ data: mockCiYml,
+ });
+ });
+
+ afterEach(() => {
+ Api.getRawFile.mockReset();
+ });
+
+ it('resolves lint data with type names', async () => {
+ const result = resolvers.Query.blobContent(null, {
+ projectPath: mockProjectPath,
+ path: mockCiConfigPath,
+ ref: mockDefaultBranch,
+ });
+
+ expect(Api.getRawFile).toHaveBeenCalledWith(mockProjectPath, mockCiConfigPath, {
+ ref: mockDefaultBranch,
+ });
+
+ // eslint-disable-next-line no-underscore-dangle
+ expect(result.__typename).toBe('BlobContent');
+ await expect(result.rawData).resolves.toBe(mockCiYml);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/mock_data.js b/spec/frontend/pipeline_editor/mock_data.js
new file mode 100644
index 00000000000..96fa6e5e004
--- /dev/null
+++ b/spec/frontend/pipeline_editor/mock_data.js
@@ -0,0 +1,10 @@
+export const mockProjectPath = 'user1/project1';
+export const mockDefaultBranch = 'master';
+
+export const mockCiConfigPath = '.gitlab-ci.yml';
+export const mockCiYml = `
+job1:
+ stage: test
+ script:
+ - echo 'test'
+`;
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
new file mode 100644
index 00000000000..46523baadf3
--- /dev/null
+++ b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
@@ -0,0 +1,139 @@
+import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import { GlAlert, GlLoadingIcon, GlTabs, GlTab } from '@gitlab/ui';
+
+import { mockProjectPath, mockDefaultBranch, mockCiConfigPath, mockCiYml } from './mock_data';
+import TextEditor from '~/pipeline_editor/components/text_editor.vue';
+import EditorLite from '~/vue_shared/components/editor_lite.vue';
+import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
+import PipelineEditorApp from '~/pipeline_editor/pipeline_editor_app.vue';
+
+describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
+ let wrapper;
+
+ const createComponent = (
+ { props = {}, data = {}, loading = false } = {},
+ mountFn = shallowMount,
+ ) => {
+ wrapper = mountFn(PipelineEditorApp, {
+ propsData: {
+ projectPath: mockProjectPath,
+ defaultBranch: mockDefaultBranch,
+ ciConfigPath: mockCiConfigPath,
+ ...props,
+ },
+ data() {
+ return data;
+ },
+ stubs: {
+ GlTabs,
+ TextEditor,
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ content: {
+ loading,
+ },
+ },
+ },
+ },
+ });
+ };
+
+ const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findAlert = () => wrapper.find(GlAlert);
+ const findTabAt = i => wrapper.findAll(GlTab).at(i);
+ const findEditorLite = () => wrapper.find(EditorLite);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('displays content', () => {
+ createComponent({ data: { content: mockCiYml } });
+
+ expect(findLoadingIcon().exists()).toBe(false);
+ expect(findEditorLite().props('value')).toBe(mockCiYml);
+ });
+
+ it('displays a loading icon if the query is loading', () => {
+ createComponent({ loading: true });
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+
+ describe('tabs', () => {
+ it('displays tabs and their content', () => {
+ createComponent({ data: { content: mockCiYml } });
+
+ expect(
+ findTabAt(0)
+ .find(EditorLite)
+ .exists(),
+ ).toBe(true);
+ expect(
+ findTabAt(1)
+ .find(PipelineGraph)
+ .exists(),
+ ).toBe(true);
+ });
+
+ it('displays editor tab lazily, until editor is ready', async () => {
+ createComponent({ data: { content: mockCiYml } });
+
+ expect(findTabAt(0).attributes('lazy')).toBe('true');
+
+ findEditorLite().vm.$emit('editor-ready');
+ await nextTick();
+
+ expect(findTabAt(0).attributes('lazy')).toBe(undefined);
+ });
+ });
+
+ describe('when in error state', () => {
+ class MockError extends Error {
+ constructor(message, data) {
+ super(message);
+ if (data) {
+ this.networkError = {
+ response: { data },
+ };
+ }
+ }
+ }
+
+ it('shows a generic error', () => {
+ const error = new MockError('An error message');
+ createComponent({ data: { error } });
+
+ expect(findAlert().text()).toBe('CI file could not be loaded: An error message');
+ });
+
+ it('shows a ref missing error state', () => {
+ const error = new MockError('Ref missing!', {
+ error: 'ref is missing, ref is empty',
+ });
+ createComponent({ data: { error } });
+
+ expect(findAlert().text()).toMatch(
+ 'CI file could not be loaded: ref is missing, ref is empty',
+ );
+ });
+
+ it('shows a file missing error state', async () => {
+ const error = new MockError('File missing!', {
+ message: 'file not found',
+ });
+
+ await wrapper.setData({ error });
+
+ expect(findAlert().text()).toMatch('CI file could not be loaded: file not found');
+ });
+ });
+});
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 040c0fbecc5..197f646a22e 100644
--- a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
+++ b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
@@ -1,5 +1,5 @@
import { mount, shallowMount } from '@vue/test-utils';
-import { GlDropdown, GlDropdownItem, GlForm, GlSprintf } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlForm, GlSprintf, GlLoadingIcon } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -35,6 +35,7 @@ describe('Pipeline New Form', () => {
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 findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const getExpectedPostParams = () => JSON.parse(mock.history.post[0].data);
const createComponent = (term = '', props = {}, method = shallowMount) => {
@@ -207,6 +208,25 @@ describe('Pipeline New Form', () => {
window.gon = origGon;
});
+ describe('loading state', () => {
+ it('loading icon is shown when content is requested and hidden when received', async () => {
+ createComponent('', mockParams, mount);
+
+ mock.onGet(configVariablesPath).reply(httpStatusCodes.OK, {
+ [mockYmlKey]: {
+ value: mockYmlValue,
+ description: mockYmlDesc,
+ },
+ });
+
+ expect(findLoadingIcon().exists()).toBe(true);
+
+ await waitForPromises();
+
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+ });
+
describe('when yml defines a variable with description', () => {
beforeEach(async () => {
createComponent('', mockParams, mount);
diff --git a/spec/frontend/pipelines/graph/graph_component_spec.js b/spec/frontend/pipelines/graph/graph_component_spec.js
index 062c9759a65..5a17be1af23 100644
--- a/spec/frontend/pipelines/graph/graph_component_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_spec.js
@@ -159,13 +159,13 @@ describe('graph component', () => {
describe('triggered by', () => {
describe('on click', () => {
- it('should emit `onClickTriggeredBy` when triggered by linked pipeline is clicked', () => {
+ it('should emit `onClickUpstreamPipeline` when triggered by linked pipeline is clicked', () => {
const btnWrapper = findExpandPipelineBtn();
btnWrapper.trigger('click');
btnWrapper.vm.$nextTick(() => {
- expect(wrapper.emitted().onClickTriggeredBy).toEqual([
+ expect(wrapper.emitted().onClickUpstreamPipeline).toEqual([
store.state.pipeline.triggered_by,
]);
});
diff --git a/spec/frontend/pipelines/graph/linked_pipeline_spec.js b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
index 8e65f0d4f71..67986ca7739 100644
--- a/spec/frontend/pipelines/graph/linked_pipeline_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
@@ -2,11 +2,10 @@ import { mount } from '@vue/test-utils';
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import LinkedPipelineComponent from '~/pipelines/components/graph/linked_pipeline.vue';
import CiStatus from '~/vue_shared/components/ci_icon.vue';
-
import mockData from './linked_pipelines_mock_data';
+import { UPSTREAM, DOWNSTREAM } from '~/pipelines/components/graph/constants';
const mockPipeline = mockData.triggered[0];
-
const validTriggeredPipelineId = mockPipeline.project.id;
const invalidTriggeredPipelineId = mockPipeline.project.id + 5;
@@ -40,6 +39,7 @@ describe('Linked pipeline', () => {
pipeline: mockPipeline,
projectId: invalidTriggeredPipelineId,
columnTitle: 'Downstream',
+ type: DOWNSTREAM,
};
beforeEach(() => {
@@ -104,11 +104,13 @@ describe('Linked pipeline', () => {
pipeline: mockPipeline,
projectId: validTriggeredPipelineId,
columnTitle: 'Downstream',
+ type: DOWNSTREAM,
};
const upstreamProps = {
...downstreamProps,
columnTitle: 'Upstream',
+ type: UPSTREAM,
};
it('parent/child label container should exist', () => {
@@ -182,6 +184,7 @@ describe('Linked pipeline', () => {
pipeline: { ...mockPipeline, isLoading: true },
projectId: invalidTriggeredPipelineId,
columnTitle: 'Downstream',
+ type: DOWNSTREAM,
};
beforeEach(() => {
@@ -198,6 +201,7 @@ describe('Linked pipeline', () => {
pipeline: mockPipeline,
projectId: validTriggeredPipelineId,
columnTitle: 'Downstream',
+ type: DOWNSTREAM,
};
beforeEach(() => {
diff --git a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
index 82eaa553d0c..e6ae3154d1d 100644
--- a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
@@ -1,6 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import LinkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue';
import LinkedPipeline from '~/pipelines/components/graph/linked_pipeline.vue';
+import { UPSTREAM } from '~/pipelines/components/graph/constants';
import mockData from './linked_pipelines_mock_data';
describe('Linked Pipelines Column', () => {
@@ -9,6 +10,7 @@ describe('Linked Pipelines Column', () => {
linkedPipelines: mockData.triggered,
graphPosition: 'right',
projectId: 19,
+ type: UPSTREAM,
};
let wrapper;
diff --git a/spec/frontend/pipelines/header_component_spec.js b/spec/frontend/pipelines/header_component_spec.js
index 2e10b0f068c..03e385e3cc8 100644
--- a/spec/frontend/pipelines/header_component_spec.js
+++ b/spec/frontend/pipelines/header_component_spec.js
@@ -1,19 +1,19 @@
import { shallowMount } from '@vue/test-utils';
import { GlModal, GlLoadingIcon } from '@gitlab/ui';
-import MockAdapter from 'axios-mock-adapter';
import {
mockCancelledPipelineHeader,
mockFailedPipelineHeader,
mockRunningPipelineHeader,
mockSuccessfulPipelineHeader,
} from './mock_data';
-import axios from '~/lib/utils/axios_utils';
import HeaderComponent from '~/pipelines/components/header_component.vue';
+import deletePipelineMutation from '~/pipelines/graphql/mutations/delete_pipeline.mutation.graphql';
+import retryPipelineMutation from '~/pipelines/graphql/mutations/retry_pipeline.mutation.graphql';
+import cancelPipelineMutation from '~/pipelines/graphql/mutations/cancel_pipeline.mutation.graphql';
describe('Pipeline details header', () => {
let wrapper;
let glModalDirective;
- let mockAxios;
const findDeleteModal = () => wrapper.find(GlModal);
const findRetryButton = () => wrapper.find('[data-testid="retryPipeline"]');
@@ -25,9 +25,7 @@ describe('Pipeline details header', () => {
pipelineId: 14,
pipelineIid: 1,
paths: {
- retry: '/retry',
- cancel: '/cancel',
- delete: '/delete',
+ pipelinesPath: '/namespace/my-project/-/pipelines',
fullProject: '/namespace/my-project',
},
};
@@ -43,6 +41,7 @@ describe('Pipeline details header', () => {
startPolling: jest.fn(),
},
},
+ mutate: jest.fn(),
};
return shallowMount(HeaderComponent, {
@@ -65,16 +64,9 @@ describe('Pipeline details header', () => {
});
};
- beforeEach(() => {
- mockAxios = new MockAdapter(axios);
- mockAxios.onGet('*').replyOnce(200);
- });
-
afterEach(() => {
wrapper.destroy();
wrapper = null;
-
- mockAxios.restore();
});
describe('initial loading', () => {
@@ -105,19 +97,37 @@ describe('Pipeline details header', () => {
);
});
+ describe('polling', () => {
+ it('is stopped when pipeline is finished', async () => {
+ wrapper = createComponent({ ...mockRunningPipelineHeader });
+
+ await wrapper.setData({
+ pipeline: { ...mockCancelledPipelineHeader },
+ });
+
+ expect(wrapper.vm.$apollo.queries.pipeline.stopPolling).toHaveBeenCalled();
+ });
+
+ it('is not stopped when pipeline is not finished', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.vm.$apollo.queries.pipeline.stopPolling).not.toHaveBeenCalled();
+ });
+ });
+
describe('actions', () => {
describe('Retry action', () => {
beforeEach(() => {
wrapper = createComponent(mockCancelledPipelineHeader);
});
- it('should call axios with the right path when retry button is clicked', async () => {
- jest.spyOn(axios, 'post');
+ it('should call retryPipeline Mutation with pipeline id', () => {
findRetryButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
-
- expect(axios.post).toHaveBeenCalledWith(defaultProvideOptions.paths.retry);
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: retryPipelineMutation,
+ variables: { id: mockCancelledPipelineHeader.id },
+ });
});
});
@@ -126,13 +136,13 @@ describe('Pipeline details header', () => {
wrapper = createComponent(mockRunningPipelineHeader);
});
- it('should call axios with the right path when cancel button is clicked', async () => {
- jest.spyOn(axios, 'post');
+ it('should call cancelPipeline Mutation with pipeline id', () => {
findCancelButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
-
- expect(axios.post).toHaveBeenCalledWith(defaultProvideOptions.paths.cancel);
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: cancelPipelineMutation,
+ variables: { id: mockRunningPipelineHeader.id },
+ });
});
});
@@ -141,24 +151,21 @@ describe('Pipeline details header', () => {
wrapper = createComponent(mockFailedPipelineHeader);
});
- it('displays delete modal when clicking on delete and does not call the delete action', async () => {
- jest.spyOn(axios, 'delete');
+ it('displays delete modal when clicking on delete and does not call the delete action', () => {
findDeleteButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
-
expect(findDeleteModal().props('modalId')).toBe(wrapper.vm.$options.DELETE_MODAL_ID);
expect(glModalDirective).toHaveBeenCalledWith(wrapper.vm.$options.DELETE_MODAL_ID);
- expect(axios.delete).not.toHaveBeenCalled();
+ expect(wrapper.vm.$apollo.mutate).not.toHaveBeenCalled();
});
- it('should call delete path when modal is submitted', async () => {
- jest.spyOn(axios, 'delete');
+ it('should call deletePipeline Mutation with pipeline id when modal is submitted', () => {
findDeleteModal().vm.$emit('ok');
- await wrapper.vm.$nextTick();
-
- expect(axios.delete).toHaveBeenCalledWith(defaultProvideOptions.paths.delete);
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: deletePipelineMutation,
+ variables: { id: mockFailedPipelineHeader.id },
+ });
});
});
});
diff --git a/spec/frontend/pipelines/pipeline_graph/mock_data.js b/spec/frontend/pipelines/pipeline_graph/mock_data.js
index b50932deec6..4f55fdd6b28 100644
--- a/spec/frontend/pipelines/pipeline_graph/mock_data.js
+++ b/spec/frontend/pipelines/pipeline_graph/mock_data.js
@@ -91,3 +91,18 @@ export const pipelineData = {
[jobId4]: {},
},
};
+
+export const singleStageData = {
+ stages: [
+ {
+ name: 'build',
+ groups: [
+ {
+ name: 'build_1',
+ jobs: [{ script: 'echo hello', stage: 'build' }],
+ id: jobId1,
+ },
+ ],
+ },
+ ],
+};
diff --git a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
index 30e192e5726..7c8ebc27974 100644
--- a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
+++ b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { pipelineData } from './mock_data';
+import { pipelineData, singleStageData } 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';
@@ -18,6 +18,8 @@ describe('pipeline graph component', () => {
};
const findAllStagePills = () => wrapper.findAll(StagePill);
+ const findAllStageBackgroundElements = () => wrapper.findAll('[data-testid="stage-background"]');
+ const findStageBackgroundElementAt = index => findAllStageBackgroundElements().at(index);
const findAllJobPills = () => wrapper.findAll(JobPill);
afterEach(() => {
@@ -31,7 +33,9 @@ describe('pipeline graph component', () => {
});
it('renders an empty section', () => {
- expect(wrapper.text()).toContain('No content to show');
+ expect(wrapper.text()).toContain(
+ 'The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax.',
+ );
expect(findAllStagePills()).toHaveLength(0);
expect(findAllJobPills()).toHaveLength(0);
});
@@ -41,12 +45,43 @@ describe('pipeline graph component', () => {
beforeEach(() => {
wrapper = createComponent();
});
+
it('renders the right number of stage pills', () => {
const expectedStagesLength = pipelineData.stages.length;
expect(findAllStagePills()).toHaveLength(expectedStagesLength);
});
+ it.each`
+ cssClass | expectedState
+ ${'gl-rounded-bottom-left-6'} | ${true}
+ ${'gl-rounded-top-left-6'} | ${true}
+ ${'gl-rounded-top-right-6'} | ${false}
+ ${'gl-rounded-bottom-right-6'} | ${false}
+ `(
+ 'rounds corner: $class should be $expectedState on the first element',
+ ({ cssClass, expectedState }) => {
+ const classes = findStageBackgroundElementAt(0).classes();
+
+ expect(classes.includes(cssClass)).toBe(expectedState);
+ },
+ );
+
+ it.each`
+ cssClass | expectedState
+ ${'gl-rounded-bottom-left-6'} | ${false}
+ ${'gl-rounded-top-left-6'} | ${false}
+ ${'gl-rounded-top-right-6'} | ${true}
+ ${'gl-rounded-bottom-right-6'} | ${true}
+ `(
+ 'rounds corner: $class should be $expectedState on the last element',
+ ({ cssClass, expectedState }) => {
+ const classes = findStageBackgroundElementAt(pipelineData.stages.length - 1).classes();
+
+ expect(classes.includes(cssClass)).toBe(expectedState);
+ },
+ );
+
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) => {
@@ -56,4 +91,25 @@ describe('pipeline graph component', () => {
expect(findAllJobPills()).toHaveLength(expectedJobsLength);
});
});
+
+ describe('with only one stage', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ pipelineData: singleStageData });
+ });
+
+ it.each`
+ cssClass | expectedState
+ ${'gl-rounded-bottom-left-6'} | ${true}
+ ${'gl-rounded-top-left-6'} | ${true}
+ ${'gl-rounded-top-right-6'} | ${true}
+ ${'gl-rounded-bottom-right-6'} | ${true}
+ `(
+ 'rounds corner: $class should be $expectedState on the only element',
+ ({ cssClass, expectedState }) => {
+ const classes = findStageBackgroundElementAt(0).classes();
+
+ expect(classes.includes(cssClass)).toBe(expectedState);
+ },
+ );
+ });
});
diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js
index 1298a2a1524..a272803f9b6 100644
--- a/spec/frontend/pipelines/pipelines_spec.js
+++ b/spec/frontend/pipelines/pipelines_spec.js
@@ -74,7 +74,6 @@ describe('Pipelines', () => {
const createComponent = (props = defaultProps, methods) => {
wrapper = mount(PipelinesComponent, {
- provide: { glFeatures: { filterPipelinesSearch: true } },
propsData: {
store: new Store(),
projectId: '21',
@@ -373,7 +372,6 @@ describe('Pipelines', () => {
});
it('should render table', () => {
- expect(wrapper.find('.table-holder').exists()).toBe(true);
expect(wrapper.findAll('.gl-responsive-table-row')).toHaveLength(
pipelines.pipelines.length + 1,
);
diff --git a/spec/frontend/pipelines/test_reports/test_case_details_spec.js b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
new file mode 100644
index 00000000000..9e66012818e
--- /dev/null
+++ b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
@@ -0,0 +1,74 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlModal } from '@gitlab/ui';
+import TestCaseDetails from '~/pipelines/components/test_reports/test_case_details.vue';
+import CodeBlock from '~/vue_shared/components/code_block.vue';
+
+const localVue = createLocalVue();
+
+describe('Test case details', () => {
+ let wrapper;
+ const defaultTestCase = {
+ classname: 'spec.test_spec',
+ name: 'Test#something cool',
+ formattedTime: '10.04ms',
+ system_output: 'Line 42 is broken',
+ };
+
+ const findModal = () => wrapper.find(GlModal);
+ const findName = () => wrapper.find('[data-testid="test-case-name"]');
+ const findDuration = () => wrapper.find('[data-testid="test-case-duration"]');
+ const findSystemOutput = () => wrapper.find('[data-testid="test-case-trace"]');
+
+ const createComponent = (testCase = {}) => {
+ wrapper = shallowMount(TestCaseDetails, {
+ localVue,
+ propsData: {
+ modalId: 'my-modal',
+ testCase: {
+ ...defaultTestCase,
+ ...testCase,
+ },
+ },
+ stubs: { CodeBlock, GlModal },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('required details', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the test case classname as modal title', () => {
+ expect(findModal().attributes('title')).toBe(defaultTestCase.classname);
+ });
+
+ it('renders the test case name', () => {
+ expect(findName().text()).toBe(defaultTestCase.name);
+ });
+
+ it('renders the test case duration', () => {
+ expect(findDuration().text()).toBe(defaultTestCase.formattedTime);
+ });
+ });
+
+ describe('when test case has system output', () => {
+ it('renders the test case system output', () => {
+ createComponent();
+
+ expect(findSystemOutput().text()).toContain(defaultTestCase.system_output);
+ });
+ });
+
+ describe('when test case does not have system output', () => {
+ it('does not render the test case system output', () => {
+ createComponent({ system_output: null });
+
+ expect(findSystemOutput().exists()).toBe(false);
+ });
+ });
+});
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 838e0606375..284099b000b 100644
--- a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
@@ -1,7 +1,7 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { getJSONFixture } from 'helpers/fixtures';
-import { GlButton } from '@gitlab/ui';
+import { GlButton, GlFriendlyWrap } from '@gitlab/ui';
import SuiteTable from '~/pipelines/components/test_reports/test_suite_table.vue';
import * as getters from '~/pipelines/stores/test_reports/getters';
import { TestStatus } from '~/pipelines/constants';
@@ -40,6 +40,7 @@ describe('Test reports suite table', () => {
wrapper = shallowMount(SuiteTable, {
store,
localVue,
+ stubs: { GlFriendlyWrap },
});
};
diff --git a/spec/frontend/popovers/components/popovers_spec.js b/spec/frontend/popovers/components/popovers_spec.js
new file mode 100644
index 00000000000..63e0b3d9c49
--- /dev/null
+++ b/spec/frontend/popovers/components/popovers_spec.js
@@ -0,0 +1,129 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlPopover } from '@gitlab/ui';
+import { useMockMutationObserver } from 'helpers/mock_dom_observer';
+import Popovers from '~/popovers/components/popovers.vue';
+
+describe('popovers/components/popovers.vue', () => {
+ const { trigger: triggerMutate, observersCount } = useMockMutationObserver();
+ let wrapper;
+
+ const buildWrapper = (...targets) => {
+ wrapper = shallowMount(Popovers);
+ wrapper.vm.addPopovers(targets);
+ return wrapper.vm.$nextTick();
+ };
+
+ const createPopoverTarget = (options = {}) => {
+ const target = document.createElement('button');
+ const dataset = {
+ title: 'default title',
+ content: 'some content',
+ ...options,
+ };
+
+ Object.entries(dataset).forEach(([key, value]) => {
+ target.dataset[key] = value;
+ });
+
+ document.body.appendChild(target);
+
+ return target;
+ };
+
+ const allPopovers = () => wrapper.findAll(GlPopover);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('addPopovers', () => {
+ it('attaches popovers to the targets specified', async () => {
+ const target = createPopoverTarget();
+ await buildWrapper(target);
+ expect(wrapper.find(GlPopover).props('target')).toBe(target);
+ });
+
+ it('does not attach a popover twice to the same element', async () => {
+ const target = createPopoverTarget();
+ buildWrapper(target);
+ wrapper.vm.addPopovers([target]);
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.findAll(GlPopover)).toHaveLength(1);
+ });
+
+ it('supports HTML content', async () => {
+ const content = 'content with <b>HTML</b>';
+ await buildWrapper(
+ createPopoverTarget({
+ content,
+ html: true,
+ }),
+ );
+ const html = wrapper.find(GlPopover).html();
+
+ expect(html).toContain(content);
+ });
+
+ it.each`
+ option | value
+ ${'placement'} | ${'bottom'}
+ ${'triggers'} | ${'manual'}
+ `('sets $option to $value when data-$option is set in target', async ({ option, value }) => {
+ await buildWrapper(createPopoverTarget({ [option]: value }));
+
+ expect(wrapper.find(GlPopover).props(option)).toBe(value);
+ });
+ });
+
+ describe('dispose', () => {
+ it('removes all popovers when elements is nil', async () => {
+ await buildWrapper(createPopoverTarget(), createPopoverTarget());
+
+ wrapper.vm.dispose();
+ await wrapper.vm.$nextTick();
+
+ expect(allPopovers()).toHaveLength(0);
+ });
+
+ it('removes the popovers that target the elements specified', async () => {
+ const target = createPopoverTarget();
+
+ await buildWrapper(target, createPopoverTarget());
+
+ wrapper.vm.dispose(target);
+ await wrapper.vm.$nextTick();
+
+ expect(allPopovers()).toHaveLength(1);
+ });
+ });
+
+ describe('observe', () => {
+ it('removes popover when target is removed from the document', async () => {
+ const target = createPopoverTarget();
+ await buildWrapper(target);
+
+ wrapper.vm.addPopovers([target, createPopoverTarget()]);
+ await wrapper.vm.$nextTick();
+
+ triggerMutate(document.body, {
+ entry: { removedNodes: [target] },
+ options: { childList: true },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(allPopovers()).toHaveLength(1);
+ });
+ });
+
+ it('disconnects mutation observer on beforeDestroy', async () => {
+ await buildWrapper(createPopoverTarget());
+
+ expect(observersCount()).toBe(1);
+
+ wrapper.destroy();
+ expect(observersCount()).toBe(0);
+ });
+});
diff --git a/spec/frontend/popovers/index_spec.js b/spec/frontend/popovers/index_spec.js
new file mode 100644
index 00000000000..ea3b78332d7
--- /dev/null
+++ b/spec/frontend/popovers/index_spec.js
@@ -0,0 +1,104 @@
+import { initPopovers, dispose, destroy } from '~/popovers';
+
+describe('popovers/index.js', () => {
+ let popoversApp;
+
+ const createPopoverTarget = (trigger = 'hover') => {
+ const target = document.createElement('button');
+ const dataset = {
+ title: 'default title',
+ content: 'some content',
+ toggle: 'popover',
+ trigger,
+ };
+
+ Object.entries(dataset).forEach(([key, value]) => {
+ target.dataset[key] = value;
+ });
+
+ document.body.appendChild(target);
+
+ return target;
+ };
+
+ const buildPopoversApp = () => {
+ popoversApp = initPopovers('[data-toggle="popover"]');
+ };
+
+ const triggerEvent = (target, eventName = 'mouseenter') => {
+ const event = new Event(eventName);
+
+ target.dispatchEvent(event);
+ };
+
+ afterEach(() => {
+ document.body.innerHTML = '';
+ destroy();
+ });
+
+ describe('initPopover', () => {
+ it('attaches a GlPopover for the elements specified in the selector', async () => {
+ const target = createPopoverTarget();
+
+ buildPopoversApp();
+
+ triggerEvent(target);
+
+ await popoversApp.$nextTick();
+ const html = document.querySelector('.gl-popover').innerHTML;
+
+ expect(document.querySelector('.gl-popover')).not.toBe(null);
+ expect(html).toContain('default title');
+ expect(html).toContain('some content');
+ });
+
+ it('supports triggering a popover via custom events', async () => {
+ const trigger = 'click';
+ const target = createPopoverTarget(trigger);
+
+ buildPopoversApp();
+ triggerEvent(target, trigger);
+
+ await popoversApp.$nextTick();
+
+ expect(document.querySelector('.gl-popover')).not.toBe(null);
+ expect(document.querySelector('.gl-popover').innerHTML).toContain('default title');
+ });
+
+ it('inits popovers on targets added after content load', async () => {
+ buildPopoversApp();
+
+ expect(document.querySelector('.gl-popover')).toBe(null);
+
+ const trigger = 'click';
+ const target = createPopoverTarget(trigger);
+ triggerEvent(target, trigger);
+ await popoversApp.$nextTick();
+
+ expect(document.querySelector('.gl-popover')).not.toBe(null);
+ });
+ });
+
+ describe('dispose', () => {
+ it('removes popovers that target the elements specified', async () => {
+ const fakeTarget = createPopoverTarget();
+ const target = createPopoverTarget();
+ buildPopoversApp();
+ triggerEvent(target);
+ triggerEvent(createPopoverTarget());
+ await popoversApp.$nextTick();
+
+ expect(document.querySelectorAll('.gl-popover')).toHaveLength(2);
+
+ dispose([fakeTarget]);
+ await popoversApp.$nextTick();
+
+ expect(document.querySelectorAll('.gl-popover')).toHaveLength(2);
+
+ dispose([target]);
+ await popoversApp.$nextTick();
+
+ expect(document.querySelectorAll('.gl-popover')).toHaveLength(1);
+ });
+ });
+});
diff --git a/spec/frontend/profile/account/components/update_username_spec.js b/spec/frontend/profile/account/components/update_username_spec.js
index be39a7f4d80..45e5e0f885f 100644
--- a/spec/frontend/profile/account/components/update_username_spec.js
+++ b/spec/frontend/profile/account/components/update_username_spec.js
@@ -1,173 +1,135 @@
-import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import { GlModal } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
-import mountComponent from 'helpers/vue_mount_component_helper';
import axios from '~/lib/utils/axios_utils';
-import updateUsername from '~/profile/account/components/update_username.vue';
+import UpdateUsername from '~/profile/account/components/update_username.vue';
describe('UpdateUsername component', () => {
const rootUrl = TEST_HOST;
const actionUrl = `${TEST_HOST}/update/username`;
- const username = 'hasnoname';
- const newUsername = 'new_username';
- let Component;
- let vm;
+ const defaultProps = {
+ actionUrl,
+ rootUrl,
+ initialUsername: 'hasnoname',
+ };
+ let wrapper;
let axiosMock;
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(UpdateUsername, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ stubs: {
+ GlModal,
+ },
+ });
+ };
+
beforeEach(() => {
axiosMock = new MockAdapter(axios);
- Component = Vue.extend(updateUsername);
- vm = mountComponent(Component, {
- actionUrl,
- rootUrl,
- initialUsername: username,
- });
+ createComponent();
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
axiosMock.restore();
});
const findElements = () => {
- const modalSelector = `#${vm.$options.modalId}`;
+ const modal = wrapper.find(GlModal);
return {
- input: vm.$el.querySelector(`#${vm.$options.inputId}`),
- openModalBtn: vm.$el.querySelector(`[data-target="${modalSelector}"]`),
- modal: vm.$el.querySelector(modalSelector),
- modalBody: vm.$el.querySelector(`${modalSelector} .modal-body`),
- modalHeader: vm.$el.querySelector(`${modalSelector} .modal-title`),
- confirmModalBtn: vm.$el.querySelector(`${modalSelector} .btn-warning`),
+ modal,
+ input: wrapper.find(`#${wrapper.vm.$options.inputId}`),
+ openModalBtn: wrapper.find('[data-testid="username-change-confirmation-modal"]'),
+ modalBody: modal.find('.modal-body'),
+ modalHeader: modal.find('.modal-title'),
+ confirmModalBtn: wrapper.find('.btn-warning'),
};
};
- it('has a disabled button if the username was not changed', done => {
- const { input, openModalBtn } = findElements();
- input.dispatchEvent(new Event('input'));
-
- Vue.nextTick()
- .then(() => {
- expect(vm.username).toBe(username);
- expect(vm.newUsername).toBe(username);
- expect(openModalBtn).toBeDisabled();
- })
- .then(done)
- .catch(done.fail);
+ it('has a disabled button if the username was not changed', async () => {
+ const { openModalBtn } = findElements();
+
+ await wrapper.vm.$nextTick();
+
+ expect(openModalBtn.props('disabled')).toBe(true);
});
- it('has an enabled button which if the username was changed', done => {
+ it('has an enabled button which if the username was changed', async () => {
const { input, openModalBtn } = findElements();
- input.value = newUsername;
- input.dispatchEvent(new Event('input'));
-
- Vue.nextTick()
- .then(() => {
- expect(vm.username).toBe(username);
- expect(vm.newUsername).toBe(newUsername);
- expect(openModalBtn).not.toBeDisabled();
- })
- .then(done)
- .catch(done.fail);
- });
- it('confirmation modal contains proper header and body', done => {
- const { modalBody, modalHeader } = findElements();
+ input.element.value = 'newUsername';
+ input.trigger('input');
- vm.newUsername = newUsername;
+ await wrapper.vm.$nextTick();
- Vue.nextTick()
- .then(() => {
- expect(modalHeader.textContent).toContain('Change username?');
- expect(modalBody.textContent).toContain(
- `You are going to change the username ${username} to ${newUsername}`,
- );
- })
- .then(done)
- .catch(done.fail);
+ expect(openModalBtn.props('disabled')).toBe(false);
});
- it('confirmation modal should escape usernames properly', done => {
- const { modalBody } = findElements();
+ describe('changing username', () => {
+ const newUsername = 'new_username';
- vm.username = '<i>Italic</i>';
- vm.newUsername = vm.username;
+ beforeEach(async () => {
+ createComponent();
+ wrapper.setData({ newUsername });
- Vue.nextTick()
- .then(() => {
- expect(modalBody.innerHTML).toContain('&lt;i&gt;Italic&lt;/i&gt;');
- expect(modalBody.innerHTML).not.toContain(vm.username);
- })
- .then(done)
- .catch(done.fail);
- });
+ await wrapper.vm.$nextTick();
+ });
- it('executes API call on confirmation button click', done => {
- const { confirmModalBtn } = findElements();
+ it('confirmation modal contains proper header and body', async () => {
+ const { modal } = findElements();
- axiosMock.onPut(actionUrl).replyOnce(() => [200, { message: 'Username changed' }]);
- jest.spyOn(axios, 'put');
+ expect(modal.attributes('title')).toBe('Change username?');
+ expect(modal.text()).toContain(
+ `You are going to change the username ${defaultProps.initialUsername} to ${newUsername}`,
+ );
+ });
- vm.newUsername = newUsername;
+ it('executes API call on confirmation button click', async () => {
+ axiosMock.onPut(actionUrl).replyOnce(() => [200, { message: 'Username changed' }]);
+ jest.spyOn(axios, 'put');
- Vue.nextTick()
- .then(() => {
- confirmModalBtn.click();
+ await wrapper.vm.onConfirm();
+ await wrapper.vm.$nextTick();
- expect(axios.put).toHaveBeenCalledWith(actionUrl, { user: { username: newUsername } });
- })
- .then(done)
- .catch(done.fail);
- });
+ expect(axios.put).toHaveBeenCalledWith(actionUrl, { user: { username: newUsername } });
+ });
- it('sets the username after a successful update', done => {
- const { input, openModalBtn } = findElements();
+ it('sets the username after a successful update', async () => {
+ const { input, openModalBtn } = findElements();
- axiosMock.onPut(actionUrl).replyOnce(() => {
- expect(input).toBeDisabled();
- expect(openModalBtn).toBeDisabled();
+ axiosMock.onPut(actionUrl).replyOnce(() => {
+ expect(input.attributes('disabled')).toBe('disabled');
+ expect(openModalBtn.props('disabled')).toBe(true);
- return [200, { message: 'Username changed' }];
+ return [200, { message: 'Username changed' }];
+ });
+
+ await wrapper.vm.onConfirm();
+ await wrapper.vm.$nextTick();
+
+ expect(input.attributes('disabled')).toBe(undefined);
+ expect(openModalBtn.props('disabled')).toBe(true);
});
- vm.newUsername = newUsername;
-
- vm.onConfirm()
- .then(() => {
- expect(vm.username).toBe(newUsername);
- expect(vm.newUsername).toBe(newUsername);
- expect(input).not.toBeDisabled();
- expect(input.value).toBe(newUsername);
- expect(openModalBtn).toBeDisabled();
- })
- .then(done)
- .catch(done.fail);
- });
+ it('does not set the username after a erroneous update', async () => {
+ const { input, openModalBtn } = findElements();
- it('does not set the username after a erroneous update', done => {
- const { input, openModalBtn } = findElements();
+ axiosMock.onPut(actionUrl).replyOnce(() => {
+ expect(input.attributes('disabled')).toBe('disabled');
+ expect(openModalBtn.props('disabled')).toBe(true);
- axiosMock.onPut(actionUrl).replyOnce(() => {
- expect(input).toBeDisabled();
- expect(openModalBtn).toBeDisabled();
+ return [400, { message: 'Invalid username' }];
+ });
- return [400, { message: 'Invalid username' }];
+ await expect(wrapper.vm.onConfirm()).rejects.toThrow();
+ expect(input.attributes('disabled')).toBe(undefined);
+ expect(openModalBtn.props('disabled')).toBe(false);
});
-
- const invalidUsername = 'anything.git';
- vm.newUsername = invalidUsername;
-
- vm.onConfirm()
- .then(() => done.fail('Expected onConfirm to throw!'))
- .catch(() => {
- expect(vm.username).toBe(username);
- expect(vm.newUsername).toBe(invalidUsername);
- expect(input).not.toBeDisabled();
- expect(input.value).toBe(invalidUsername);
- expect(openModalBtn).not.toBeDisabled();
- })
- .then(done)
- .catch(done.fail);
});
});
diff --git a/spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap b/spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap
new file mode 100644
index 00000000000..2fd1fd6a04e
--- /dev/null
+++ b/spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap
@@ -0,0 +1,67 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`IntegrationView component should render IntegrationView properly 1`] = `
+<div
+ name="sourcegraph"
+>
+ <label
+ class="label-bold"
+ >
+
+ Foo
+
+ </label>
+
+ <gl-link-stub
+ class="has-tooltip"
+ href="http://foo.com/help"
+ title="More information"
+ >
+ <gl-icon-stub
+ class="vertical-align-middle"
+ name="question-o"
+ size="16"
+ />
+ </gl-link-stub>
+
+ <div
+ class="form-group form-check"
+ data-testid="profile-preferences-integration-form-group"
+ >
+ <input
+ data-testid="profile-preferences-integration-hidden-field"
+ name="user[foo_enabled]"
+ type="hidden"
+ value="0"
+ />
+
+ <input
+ class="form-check-input"
+ data-testid="profile-preferences-integration-checkbox"
+ id="user_foo_enabled"
+ name="user[foo_enabled]"
+ type="checkbox"
+ value="1"
+ />
+
+ <label
+ class="form-check-label"
+ for="user_foo_enabled"
+ >
+
+ Enable foo
+
+ </label>
+
+ <gl-form-text-stub
+ tag="div"
+ textvariant="muted"
+ >
+ <integration-help-text-stub
+ message="Click %{linkStart}Foo%{linkEnd}!"
+ messageurl="http://foo.com"
+ />
+ </gl-form-text-stub>
+ </div>
+</div>
+`;
diff --git a/spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap b/spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap
new file mode 100644
index 00000000000..4df92cf86a5
--- /dev/null
+++ b/spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap
@@ -0,0 +1,51 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ProfilePreferences component should render ProfilePreferences properly 1`] = `
+<div
+ class="row gl-mt-3 js-preferences-form"
+>
+ <div
+ class="col-sm-12"
+ >
+ <hr
+ data-testid="profile-preferences-integrations-rule"
+ />
+ </div>
+
+ <div
+ class="col-lg-4 profile-settings-sidebar"
+ >
+ <h4
+ class="gl-mt-0"
+ data-testid="profile-preferences-integrations-heading"
+ >
+
+ Integrations
+
+ </h4>
+
+ <p>
+
+ Customize integrations with third party services.
+
+ </p>
+ </div>
+
+ <div
+ class="col-lg-8"
+ >
+ <integration-view-stub
+ config="[object Object]"
+ helplink="http://foo.com/help"
+ message="Click %{linkStart}Foo%{linkEnd}!"
+ messageurl="http://foo.com"
+ />
+ <integration-view-stub
+ config="[object Object]"
+ helplink="http://bar.com/help"
+ message="Click %{linkStart}Bar%{linkEnd}!"
+ messageurl="http://bar.com"
+ />
+ </div>
+</div>
+`;
diff --git a/spec/frontend/profile/preferences/components/integration_view_spec.js b/spec/frontend/profile/preferences/components/integration_view_spec.js
new file mode 100644
index 00000000000..5d55a089119
--- /dev/null
+++ b/spec/frontend/profile/preferences/components/integration_view_spec.js
@@ -0,0 +1,124 @@
+import { shallowMount } from '@vue/test-utils';
+
+import { GlFormText } from '@gitlab/ui';
+import IntegrationView from '~/profile/preferences/components/integration_view.vue';
+import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { integrationViews, userFields } from '../mock_data';
+
+const viewProps = convertObjectPropsToCamelCase(integrationViews[0]);
+
+describe('IntegrationView component', () => {
+ let wrapper;
+ const defaultProps = {
+ config: {
+ title: 'Foo',
+ label: 'Enable foo',
+ formName: 'foo_enabled',
+ },
+ ...viewProps,
+ };
+
+ function createComponent(options = {}) {
+ const { props = {}, provide = {} } = options;
+ return shallowMount(IntegrationView, {
+ provide: {
+ userFields,
+ ...provide,
+ },
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ }
+
+ function findCheckbox() {
+ return wrapper.find('[data-testid="profile-preferences-integration-checkbox"]');
+ }
+ function findFormGroup() {
+ return wrapper.find('[data-testid="profile-preferences-integration-form-group"]');
+ }
+ function findHiddenField() {
+ return wrapper.find('[data-testid="profile-preferences-integration-hidden-field"]');
+ }
+ function findFormGroupLabel() {
+ return wrapper.find('[data-testid="profile-preferences-integration-form-group"] label');
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should render the title correctly', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.find('label.label-bold').text()).toBe('Foo');
+ });
+
+ it('should render the form correctly', () => {
+ wrapper = createComponent();
+
+ expect(findFormGroup().exists()).toBe(true);
+ expect(findHiddenField().exists()).toBe(true);
+ expect(findCheckbox().exists()).toBe(true);
+ expect(findCheckbox().attributes('id')).toBe('user_foo_enabled');
+ expect(findCheckbox().attributes('name')).toBe('user[foo_enabled]');
+ });
+
+ it('should have the checkbox value to be set to 1', () => {
+ wrapper = createComponent();
+
+ expect(findCheckbox().attributes('value')).toBe('1');
+ });
+
+ it('should have the hidden value to be set to 0', () => {
+ wrapper = createComponent();
+
+ expect(findHiddenField().attributes('value')).toBe('0');
+ });
+
+ it('should set the checkbox value to be true', () => {
+ wrapper = createComponent();
+
+ expect(findCheckbox().element.checked).toBe(true);
+ });
+
+ it('should set the checkbox value to be false when false is provided', () => {
+ wrapper = createComponent({
+ provide: {
+ userFields: {
+ foo_enabled: false,
+ },
+ },
+ });
+
+ expect(findCheckbox().element.checked).toBe(false);
+ });
+
+ it('should set the checkbox value to be false when not provided', () => {
+ wrapper = createComponent({ provide: { userFields: {} } });
+
+ expect(findCheckbox().element.checked).toBe(false);
+ });
+
+ it('should render the help text', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.find(GlFormText).exists()).toBe(true);
+ expect(wrapper.find(IntegrationHelpText).exists()).toBe(true);
+ });
+
+ it('should render the label correctly', () => {
+ wrapper = createComponent();
+
+ expect(findFormGroupLabel().text()).toBe('Enable foo');
+ });
+
+ it('should render IntegrationView properly', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/profile/preferences/components/profile_preferences_spec.js b/spec/frontend/profile/preferences/components/profile_preferences_spec.js
new file mode 100644
index 00000000000..fcc27d8faaf
--- /dev/null
+++ b/spec/frontend/profile/preferences/components/profile_preferences_spec.js
@@ -0,0 +1,57 @@
+import { shallowMount } from '@vue/test-utils';
+
+import ProfilePreferences from '~/profile/preferences/components/profile_preferences.vue';
+import IntegrationView from '~/profile/preferences/components/integration_view.vue';
+import { integrationViews, userFields } from '../mock_data';
+
+describe('ProfilePreferences component', () => {
+ let wrapper;
+ const defaultProvide = {
+ integrationViews: [],
+ userFields,
+ };
+
+ function createComponent(options = {}) {
+ const { props = {}, provide = {} } = options;
+ return shallowMount(ProfilePreferences, {
+ provide: {
+ ...defaultProvide,
+ ...provide,
+ },
+ propsData: props,
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should not render Integrations section', () => {
+ wrapper = createComponent();
+ const views = wrapper.findAll(IntegrationView);
+ const divider = wrapper.find('[data-testid="profile-preferences-integrations-rule"]');
+ const heading = wrapper.find('[data-testid="profile-preferences-integrations-heading"]');
+
+ expect(divider.exists()).toBe(false);
+ expect(heading.exists()).toBe(false);
+ expect(views).toHaveLength(0);
+ });
+
+ it('should render Integration section', () => {
+ wrapper = createComponent({ provide: { integrationViews } });
+ const divider = wrapper.find('[data-testid="profile-preferences-integrations-rule"]');
+ const heading = wrapper.find('[data-testid="profile-preferences-integrations-heading"]');
+ const views = wrapper.findAll(IntegrationView);
+
+ expect(divider.exists()).toBe(true);
+ expect(heading.exists()).toBe(true);
+ expect(views).toHaveLength(integrationViews.length);
+ });
+
+ it('should render ProfilePreferences properly', () => {
+ wrapper = createComponent({ provide: { integrationViews } });
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/profile/preferences/mock_data.js b/spec/frontend/profile/preferences/mock_data.js
new file mode 100644
index 00000000000..d07d5f565dc
--- /dev/null
+++ b/spec/frontend/profile/preferences/mock_data.js
@@ -0,0 +1,18 @@
+export const integrationViews = [
+ {
+ name: 'sourcegraph',
+ help_link: 'http://foo.com/help',
+ message: 'Click %{linkStart}Foo%{linkEnd}!',
+ message_url: 'http://foo.com',
+ },
+ {
+ name: 'gitpod',
+ help_link: 'http://bar.com/help',
+ message: 'Click %{linkStart}Bar%{linkEnd}!',
+ message_url: 'http://bar.com',
+ },
+];
+
+export const userFields = {
+ foo_enabled: true,
+};
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 a0fd6012546..4eb5060cb0a 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
@@ -57,7 +57,7 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
</gl-alert-stub>
<p>
- This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc.
+ This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc.
</p>
<p
diff --git a/spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap b/spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap
index ff0351bd099..ac87fe893b9 100644
--- a/spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap
+++ b/spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap
@@ -11,7 +11,6 @@ exports[`StatisticsList matches the snapshot 1`] = `
4 pipelines
</strong>
</li>
-
<li>
<span>
Successful:
@@ -21,7 +20,6 @@ exports[`StatisticsList matches the snapshot 1`] = `
2 pipelines
</strong>
</li>
-
<li>
<span>
Failed:
@@ -31,7 +29,6 @@ exports[`StatisticsList matches the snapshot 1`] = `
2 pipelines
</strong>
</li>
-
<li>
<span>
Success ratio:
@@ -41,5 +38,14 @@ exports[`StatisticsList matches the snapshot 1`] = `
50%
</strong>
</li>
+ <li>
+ <span>
+ Total duration:
+ </span>
+
+ <strong>
+ 00:01:56
+ </strong>
+ </li>
</ul>
`;
diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js
index 883f2bec5f7..0dd3407dbbc 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js
@@ -45,7 +45,7 @@ describe('ProjectsPipelinesChartsApp', () => {
expect(chart.exists()).toBeTruthy();
expect(chart.props('yAxisTitle')).toBe('Minutes');
expect(chart.props('xAxisTitle')).toBe('Commit');
- expect(chart.props('data')).toBe(wrapper.vm.timesChartTransformedData);
+ expect(chart.props('bars')).toBe(wrapper.vm.timesChartTransformedData);
expect(chart.props('option')).toBe(wrapper.vm.$options.timesChartOptions);
});
});
diff --git a/spec/frontend/projects/pipelines/charts/mock_data.js b/spec/frontend/projects/pipelines/charts/mock_data.js
index db5164c8f99..84e0ccb828a 100644
--- a/spec/frontend/projects/pipelines/charts/mock_data.js
+++ b/spec/frontend/projects/pipelines/charts/mock_data.js
@@ -3,6 +3,7 @@ export const counts = {
success: 2,
total: 4,
successRatio: 50,
+ totalDuration: 116158,
};
export const timesChartData = {
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 62aeb4ddee5..7e74a5deee1 100644
--- a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js
+++ b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js
@@ -1,7 +1,8 @@
-import { shallowMount, mount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import ServiceDeskRoot from '~/projects/settings_service_desk/components/service_desk_root.vue';
+import ServiceDeskSetting from '~/projects/settings_service_desk/components/service_desk_setting.vue';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -24,65 +25,6 @@ describe('ServiceDeskRoot', () => {
}
});
- it('fetches incoming email when there is no incoming email provided', () => {
- axiosMock.onGet(endpoint).replyOnce(httpStatusCodes.OK);
-
- wrapper = shallowMount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- initialIncomingEmail: '',
- endpoint,
- },
- });
-
- return wrapper.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(axiosMock.history.get).toHaveLength(1);
- });
- });
-
- it('does not fetch incoming email when there is an incoming email provided', () => {
- axiosMock.onGet(endpoint).replyOnce(httpStatusCodes.OK);
-
- wrapper = shallowMount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- initialIncomingEmail,
- endpoint,
- },
- });
-
- return wrapper.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(axiosMock.history.get).toHaveLength(0);
- });
- });
-
- it('shows an error message when incoming email is not fetched correctly', () => {
- axiosMock.onGet(endpoint).networkError();
-
- wrapper = shallowMount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- initialIncomingEmail: '',
- endpoint,
- },
- });
-
- return wrapper.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(wrapper.html()).toContain(
- 'An error occurred while fetching the Service Desk address.',
- );
- });
- });
-
it('sends a request to toggle service desk off when the toggle is clicked from the on state', () => {
axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK);
@@ -221,4 +163,18 @@ describe('ServiceDeskRoot', () => {
expect(wrapper.html()).toContain('An error occured while making the changes:');
});
});
+
+ it('passes customEmail through updatedCustomEmail correctly', () => {
+ const customEmail = 'foo';
+
+ wrapper = mount(ServiceDeskRoot, {
+ propsData: {
+ initialIsEnabled: true,
+ endpoint,
+ customEmail,
+ },
+ });
+
+ expect(wrapper.find(ServiceDeskSetting).props('customEmail')).toEqual(customEmail);
+ });
});
diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
index cb46751f66a..173a7fc4e11 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
@@ -13,6 +13,7 @@ describe('ServiceDeskSetting', () => {
});
const findTemplateDropdown = () => wrapper.find('#service-desk-template-select');
+ const findIncomingEmail = () => wrapper.find('[data-testid="incoming-email"]');
describe('when isEnabled=true', () => {
describe('only isEnabled', () => {
@@ -35,7 +36,7 @@ describe('ServiceDeskSetting', () => {
it('should see loading spinner and not the incoming email', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.find('.incoming-email').exists()).toBe(false);
+ expect(findIncomingEmail().exists()).toBe(false);
});
});
});
@@ -73,7 +74,7 @@ describe('ServiceDeskSetting', () => {
});
it('should see email and not the loading spinner', () => {
- expect(wrapper.find('.incoming-email').element.value).toEqual(incomingEmail);
+ expect(findIncomingEmail().element.value).toEqual(incomingEmail);
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
@@ -85,6 +86,45 @@ describe('ServiceDeskSetting', () => {
});
});
+ describe('with customEmail', () => {
+ describe('customEmail is different than incomingEmail', () => {
+ const incomingEmail = 'foo@bar.com';
+ const customEmail = 'custom@bar.com';
+
+ beforeEach(() => {
+ wrapper = mount(ServiceDeskSetting, {
+ propsData: {
+ isEnabled: true,
+ incomingEmail,
+ customEmail,
+ },
+ });
+ });
+
+ it('should see custom email', () => {
+ expect(findIncomingEmail().element.value).toEqual(customEmail);
+ });
+ });
+
+ describe('customEmail is the same as incomingEmail', () => {
+ const email = 'foo@bar.com';
+
+ beforeEach(() => {
+ wrapper = mount(ServiceDeskSetting, {
+ propsData: {
+ isEnabled: true,
+ incomingEmail: email,
+ customEmail: email,
+ },
+ });
+ });
+
+ it('should see custom email', () => {
+ expect(findIncomingEmail().element.value).toEqual(email);
+ });
+ });
+ });
+
describe('templates dropdown', () => {
it('renders a dropdown to choose a template', () => {
wrapper = shallowMount(ServiceDeskSetting, {
diff --git a/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js b/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js
index f9e4d55245a..3b960a95db4 100644
--- a/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js
+++ b/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js
@@ -19,24 +19,6 @@ describe('ServiceDeskService', () => {
axiosMock.restore();
});
- describe('fetchIncomingEmail', () => {
- it('makes a request to fetch incoming email', () => {
- axiosMock.onGet(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
-
- return service.fetchIncomingEmail().then(response => {
- expect(response.data).toEqual(dummyResponse);
- });
- });
-
- it('fails on error response', () => {
- axiosMock.onGet(endpoint).networkError();
-
- return service.fetchIncomingEmail().catch(error => {
- expect(error.message).toBe(errorMessage);
- });
- });
- });
-
describe('toggleServiceDesk', () => {
it('makes a request to set service desk', () => {
axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
diff --git a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
index 437a2116f5c..2460851a6a4 100644
--- a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
+++ b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
@@ -27,7 +27,8 @@ describe('PrometheusMetrics', () => {
expect(prometheusMetrics.$monitoredMetricsEmpty).toBeDefined();
expect(prometheusMetrics.$monitoredMetricsList).toBeDefined();
expect(prometheusMetrics.$missingEnvVarPanel).toBeDefined();
- expect(prometheusMetrics.$panelToggle).toBeDefined();
+ expect(prometheusMetrics.$panelToggleRight).toBeDefined();
+ expect(prometheusMetrics.$panelToggleDown).toBeDefined();
expect(prometheusMetrics.$missingEnvVarMetricCount).toBeDefined();
expect(prometheusMetrics.$missingEnvVarMetricsList).toBeDefined();
});
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 ef22979ca7d..3276ef911e3 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
@@ -22,7 +22,7 @@ describe('tags list row', () => {
let wrapper;
const [tag] = [...tagsListResponse.data];
- const defaultProps = { tag, isDesktop: true, index: 0 };
+ const defaultProps = { tag, isMobile: false, index: 0 };
const findCheckbox = () => wrapper.find(GlFormCheckbox);
const findName = () => wrapper.find('[data-testid="name"]');
@@ -114,7 +114,7 @@ describe('tags list row', () => {
});
it('on mobile has mw-s class', () => {
- mountComponent({ ...defaultProps, isDesktop: false });
+ mountComponent({ ...defaultProps, isMobile: true });
expect(findName().classes('mw-s')).toBe(true);
});
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 401202026bb..ebeaa8ff870 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
@@ -14,7 +14,7 @@ describe('Tags List', () => {
const findDeleteButton = () => wrapper.find(GlButton);
const findListTitle = () => wrapper.find('[data-testid="list-title"]');
- const mountComponent = (propsData = { tags, isDesktop: true }) => {
+ const mountComponent = (propsData = { tags, isMobile: false }) => {
wrapper = shallowMount(component, {
propsData,
});
@@ -41,15 +41,15 @@ describe('Tags List', () => {
describe('delete button', () => {
it.each`
- inputTags | isDesktop | isVisible
- ${tags} | ${true} | ${true}
- ${tags} | ${false} | ${false}
- ${readOnlyTags} | ${true} | ${false}
- ${readOnlyTags} | ${false} | ${false}
+ inputTags | isMobile | isVisible
+ ${tags} | ${false} | ${true}
+ ${tags} | ${true} | ${false}
+ ${readOnlyTags} | ${false} | ${false}
+ ${readOnlyTags} | ${true} | ${false}
`(
- 'is $isVisible that delete button exists when tags is $inputTags and isDesktop is $isDesktop',
- ({ inputTags, isDesktop, isVisible }) => {
- mountComponent({ tags: inputTags, isDesktop });
+ 'is $isVisible that delete button exists when tags is $inputTags and isMobile is $isMobile',
+ ({ inputTags, isMobile, isVisible }) => {
+ mountComponent({ tags: inputTags, isMobile });
expect(findDeleteButton().exists()).toBe(isVisible);
},
@@ -110,12 +110,6 @@ describe('Tags List', () => {
expect(rows.at(0).attributes()).toMatchObject({
first: 'true',
- isdesktop: 'true',
- });
-
- // The list has only two tags and for some reasons .at(-1) does not work
- expect(rows.at(1).attributes()).toMatchObject({
- isdesktop: 'true',
});
});
diff --git a/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js b/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
index b4471ab8122..551d1eee68d 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,6 +1,6 @@
import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
-import { GlDeprecatedDropdown } from '@gitlab/ui';
+import { GlDropdown } 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';
@@ -23,7 +23,7 @@ describe('cli_commands', () => {
let wrapper;
let store;
- const findDropdownButton = () => wrapper.find(GlDeprecatedDropdown);
+ const findDropdownButton = () => wrapper.find(GlDropdown);
const findCodeInstruction = () => wrapper.findAll(CodeInstruction);
const mountComponent = () => {
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 ce446e6d93e..9f7a2758ae1 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
@@ -19,7 +19,7 @@ describe('Image List Row', () => {
let wrapper;
const item = imagesListResponse.data[0];
- const findDetailsLink = () => wrapper.find('[data-testid="detailsLink"]');
+ const findDetailsLink = () => wrapper.find('[data-testid="details-link"]');
const findTagsCount = () => wrapper.find('[data-testid="tagsCount"]');
const findDeleteBtn = () => wrapper.find(DeleteButton);
const findClipboardButton = () => wrapper.find(ClipboardButton);
@@ -67,7 +67,12 @@ describe('Image List Row', () => {
mountComponent();
const link = findDetailsLink();
expect(link.html()).toContain(item.path);
- expect(link.props('to').name).toBe('details');
+ expect(link.props('to')).toMatchObject({
+ name: 'details',
+ params: {
+ id: item.id,
+ },
+ });
});
it('contains a clipboard button', () => {
diff --git a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js b/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
index b906e44a4f7..d730bfcde24 100644
--- a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
+++ b/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
@@ -32,6 +32,10 @@ describe('Registry Breadcrumb', () => {
{ name: 'baz', meta: { nameGenerator } },
];
+ const state = {
+ imageDetails: { foo: 'bar' },
+ };
+
const findDivider = () => wrapper.find('.js-divider');
const findRootRoute = () => wrapper.find({ ref: 'rootRouteLink' });
const findChildRoute = () => wrapper.find({ ref: 'childRouteLink' });
@@ -52,6 +56,9 @@ describe('Registry Breadcrumb', () => {
routes,
},
},
+ $store: {
+ state,
+ },
},
});
};
@@ -80,7 +87,7 @@ describe('Registry Breadcrumb', () => {
});
it('the link text is calculated by nameGenerator', () => {
- expect(nameGenerator).toHaveBeenCalledWith(routes[0]);
+ expect(nameGenerator).toHaveBeenCalledWith(state);
expect(nameGenerator).toHaveBeenCalledTimes(1);
});
});
@@ -104,7 +111,7 @@ describe('Registry Breadcrumb', () => {
});
it('the link text is calculated by nameGenerator', () => {
- expect(nameGenerator).toHaveBeenCalledWith(routes[1]);
+ expect(nameGenerator).toHaveBeenCalledWith(state);
expect(nameGenerator).toHaveBeenCalledTimes(2);
});
});
diff --git a/spec/frontend/registry/explorer/mock_data.js b/spec/frontend/registry/explorer/mock_data.js
index a7ffed4c9fd..da5f1840b5c 100644
--- a/spec/frontend/registry/explorer/mock_data.js
+++ b/spec/frontend/registry/explorer/mock_data.js
@@ -97,3 +97,14 @@ export const imagePagination = {
totalPages: 2,
nextPage: 2,
};
+
+export const imageDetailsMock = {
+ id: 1,
+ name: 'rails-32309',
+ path: 'gitlab-org/gitlab-test/rails-32309',
+ project_id: 1,
+ location: '0.0.0.0:5000/gitlab-org/gitlab-test/rails-32309',
+ created_at: '2020-06-29T10:23:47.838Z',
+ cleanup_policy_started_at: null,
+ delete_api_path: 'http://0.0.0.0:3000/api/v4/projects/1/registry/repositories/1',
+};
diff --git a/spec/frontend/registry/explorer/pages/details_spec.js b/spec/frontend/registry/explorer/pages/details_spec.js
index 86b52c4f06a..c09b7e0c067 100644
--- a/spec/frontend/registry/explorer/pages/details_spec.js
+++ b/spec/frontend/registry/explorer/pages/details_spec.js
@@ -14,9 +14,10 @@ import {
SET_TAGS_LIST_SUCCESS,
SET_TAGS_PAGINATION,
SET_INITIAL_STATE,
+ SET_IMAGE_DETAILS,
} from '~/registry/explorer/stores/mutation_types';
-import { tagsListResponse } from '../mock_data';
+import { tagsListResponse, imageDetailsMock } from '../mock_data';
import { DeleteModal } from '../stubs';
describe('Details Page', () => {
@@ -33,8 +34,7 @@ describe('Details Page', () => {
const findEmptyTagsState = () => wrapper.find(EmptyTagsState);
const findPartialCleanupAlert = () => wrapper.find(PartialCleanupAlert);
- const routeIdGenerator = override =>
- window.btoa(JSON.stringify({ name: 'foo', tags_path: 'bar', ...override }));
+ const routeId = 1;
const tagsArrayToSelectedTags = tags =>
tags.reduce((acc, c) => {
@@ -42,7 +42,7 @@ describe('Details Page', () => {
return acc;
}, {});
- const mountComponent = ({ options, routeParams } = {}) => {
+ const mountComponent = ({ options } = {}) => {
wrapper = shallowMount(component, {
store,
stubs: {
@@ -51,7 +51,7 @@ describe('Details Page', () => {
mocks: {
$route: {
params: {
- id: routeIdGenerator(routeParams),
+ id: routeId,
},
},
},
@@ -65,6 +65,7 @@ describe('Details Page', () => {
dispatchSpy.mockResolvedValue();
store.commit(SET_TAGS_LIST_SUCCESS, tagsListResponse.data);
store.commit(SET_TAGS_PAGINATION, tagsListResponse.headers);
+ store.commit(SET_IMAGE_DETAILS, imageDetailsMock);
jest.spyOn(Tracking, 'event');
});
@@ -73,6 +74,13 @@ describe('Details Page', () => {
wrapper = null;
});
+ describe('lifecycle events', () => {
+ it('calls the appropriate action on mount', () => {
+ mountComponent();
+ expect(dispatchSpy).toHaveBeenCalledWith('requestImageDetailsAndTagsList', routeId);
+ });
+ });
+
describe('when isLoading is true', () => {
beforeEach(() => {
store.commit(SET_MAIN_LOADING, true);
@@ -124,7 +132,7 @@ describe('Details Page', () => {
it('has the correct props bound', () => {
expect(findTagsList().props()).toMatchObject({
- isDesktop: true,
+ isMobile: false,
tags: store.state.tags,
});
});
@@ -194,8 +202,7 @@ describe('Details Page', () => {
dispatchSpy.mockResolvedValue();
findPagination().vm.$emit(GlPagination.model.event, 2);
expect(store.dispatch).toHaveBeenCalledWith('requestTagsList', {
- params: wrapper.vm.$route.params.id,
- pagination: { page: 2 },
+ page: 2,
});
});
});
@@ -227,7 +234,6 @@ describe('Details Page', () => {
findDeleteModal().vm.$emit('confirmDelete');
expect(dispatchSpy).toHaveBeenCalledWith('requestDeleteTag', {
tag: store.state.tags[0],
- params: routeIdGenerator(),
});
});
});
@@ -242,7 +248,6 @@ describe('Details Page', () => {
findDeleteModal().vm.$emit('confirmDelete');
expect(dispatchSpy).toHaveBeenCalledWith('requestDeleteTags', {
ids: store.state.tags.map(t => t.name),
- params: routeIdGenerator(),
});
});
});
@@ -257,7 +262,7 @@ describe('Details Page', () => {
it('has the correct props', () => {
mountComponent();
- expect(findDetailsHeader().props()).toEqual({ imageName: 'foo' });
+ expect(findDetailsHeader().props()).toEqual({ imageName: imageDetailsMock.name });
});
});
@@ -293,10 +298,14 @@ describe('Details Page', () => {
};
describe('when expiration_policy_started is not null', () => {
- const routeParams = { cleanup_policy_started_at: Date.now().toString() };
-
+ beforeEach(() => {
+ store.commit(SET_IMAGE_DETAILS, {
+ ...imageDetailsMock,
+ cleanup_policy_started_at: Date.now().toString(),
+ });
+ });
it('exists', () => {
- mountComponent({ routeParams });
+ mountComponent();
expect(findPartialCleanupAlert().exists()).toBe(true);
});
@@ -304,13 +313,13 @@ describe('Details Page', () => {
it('has the correct props', () => {
store.commit(SET_INITIAL_STATE, { ...config });
- mountComponent({ routeParams });
+ mountComponent();
expect(findPartialCleanupAlert().props()).toEqual({ ...config });
});
it('dismiss hides the component', async () => {
- mountComponent({ routeParams });
+ mountComponent();
expect(findPartialCleanupAlert().exists()).toBe(true);
findPartialCleanupAlert().vm.$emit('dismiss');
diff --git a/spec/frontend/registry/explorer/stores/actions_spec.js b/spec/frontend/registry/explorer/stores/actions_spec.js
index fb93ab06ca8..dcd4d8015a4 100644
--- a/spec/frontend/registry/explorer/stores/actions_spec.js
+++ b/spec/frontend/registry/explorer/stores/actions_spec.js
@@ -1,18 +1,29 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'helpers/test_constants';
+import createFlash from '~/flash';
+import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
import * as actions from '~/registry/explorer/stores/actions';
import * as types from '~/registry/explorer/stores/mutation_types';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import { reposServerResponse, registryServerResponse } from '../mock_data';
+import * as utils from '~/registry/explorer/utils';
+import {
+ FETCH_IMAGES_LIST_ERROR_MESSAGE,
+ FETCH_TAGS_LIST_ERROR_MESSAGE,
+ FETCH_IMAGE_DETAILS_ERROR_MESSAGE,
+} from '~/registry/explorer/constants/index';
jest.mock('~/flash.js');
+jest.mock('~/registry/explorer/utils');
describe('Actions RegistryExplorer Store', () => {
let mock;
const endpoint = `${TEST_HOST}/endpoint.json`;
+ const url = `${endpoint}/1}`;
+ jest.spyOn(utils, 'pathGenerator').mockReturnValue(url);
+
beforeEach(() => {
mock = new MockAdapter(axios);
});
@@ -123,7 +134,7 @@ describe('Actions RegistryExplorer Store', () => {
],
[],
() => {
- expect(createFlash).toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalledWith({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
done();
},
);
@@ -131,15 +142,12 @@ describe('Actions RegistryExplorer Store', () => {
});
describe('fetch tags list', () => {
- const url = `${endpoint}/1}`;
- const params = window.btoa(JSON.stringify({ tags_path: `${endpoint}/1}` }));
-
it('sets the tagsList', done => {
mock.onGet(url).replyOnce(200, registryServerResponse, {});
testAction(
actions.requestTagsList,
- { params },
+ {},
{},
[
{ type: types.SET_MAIN_LOADING, payload: true },
@@ -158,7 +166,7 @@ describe('Actions RegistryExplorer Store', () => {
it('should create flash on error', done => {
testAction(
actions.requestTagsList,
- { params },
+ {},
{},
[
{ type: types.SET_MAIN_LOADING, payload: true },
@@ -166,7 +174,7 @@ describe('Actions RegistryExplorer Store', () => {
],
[],
() => {
- expect(createFlash).toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalledWith({ message: FETCH_TAGS_LIST_ERROR_MESSAGE });
done();
},
);
@@ -176,8 +184,6 @@ describe('Actions RegistryExplorer Store', () => {
describe('request delete single tag', () => {
it('successfully performs the delete request', done => {
const deletePath = 'delete/path';
- const params = window.btoa(JSON.stringify({ tags_path: `${endpoint}/1}`, id: 1 }));
-
mock.onDelete(deletePath).replyOnce(200);
testAction(
@@ -186,7 +192,6 @@ describe('Actions RegistryExplorer Store', () => {
tag: {
destroy_path: deletePath,
},
- params,
},
{
tagsPagination: {},
@@ -202,7 +207,7 @@ describe('Actions RegistryExplorer Store', () => {
},
{
type: 'requestTagsList',
- payload: { pagination: {}, params },
+ payload: {},
},
],
done,
@@ -227,18 +232,55 @@ describe('Actions RegistryExplorer Store', () => {
});
});
- describe('request delete multiple tags', () => {
- const url = `project-path/registry/repository/foo/tags`;
- const params = window.btoa(JSON.stringify({ tags_path: `${url}?format=json` }));
+ describe('requestImageDetailsAndTagsList', () => {
+ it('sets the imageDetails and dispatch requestTagsList', done => {
+ const resolvedValue = { foo: 'bar' };
+ jest.spyOn(Api, 'containerRegistryDetails').mockResolvedValue({ data: resolvedValue });
+
+ testAction(
+ actions.requestImageDetailsAndTagsList,
+ 1,
+ {},
+ [
+ { type: types.SET_MAIN_LOADING, payload: true },
+ { type: types.SET_IMAGE_DETAILS, payload: resolvedValue },
+ ],
+ [
+ {
+ type: 'requestTagsList',
+ },
+ ],
+ done,
+ );
+ });
+
+ it('should create flash on error', done => {
+ jest.spyOn(Api, 'containerRegistryDetails').mockRejectedValue();
+ testAction(
+ actions.requestImageDetailsAndTagsList,
+ 1,
+ {},
+ [
+ { type: types.SET_MAIN_LOADING, payload: true },
+ { type: types.SET_MAIN_LOADING, payload: false },
+ ],
+ [],
+ () => {
+ expect(createFlash).toHaveBeenCalledWith({ message: FETCH_IMAGE_DETAILS_ERROR_MESSAGE });
+ done();
+ },
+ );
+ });
+ });
+ describe('request delete multiple tags', () => {
it('successfully performs the delete request', done => {
- mock.onDelete(`${url}/bulk_destroy`).replyOnce(200);
+ mock.onDelete(url).replyOnce(200);
testAction(
actions.requestDeleteTags,
{
ids: [1, 2],
- params,
},
{
tagsPagination: {},
@@ -254,7 +296,7 @@ describe('Actions RegistryExplorer Store', () => {
},
{
type: 'requestTagsList',
- payload: { pagination: {}, params },
+ payload: {},
},
],
done,
@@ -268,7 +310,6 @@ describe('Actions RegistryExplorer Store', () => {
actions.requestDeleteTags,
{
ids: [1, 2],
- params,
},
{
tagsPagination: {},
diff --git a/spec/frontend/registry/explorer/stores/mutations_spec.js b/spec/frontend/registry/explorer/stores/mutations_spec.js
index 4ca0211cdc3..1908d3f0350 100644
--- a/spec/frontend/registry/explorer/stores/mutations_spec.js
+++ b/spec/frontend/registry/explorer/stores/mutations_spec.js
@@ -121,4 +121,13 @@ describe('Mutations Registry Explorer Store', () => {
expect(mockState).toEqual(expectedState);
});
});
+
+ describe('SET_IMAGE_DETAILS', () => {
+ it('should set imageDetails', () => {
+ const expectedState = { ...mockState, imageDetails: { foo: 'bar' } };
+ mutations[types.SET_IMAGE_DETAILS](mockState, { foo: 'bar' });
+
+ expect(mockState).toEqual(expectedState);
+ });
+ });
});
diff --git a/spec/frontend/registry/explorer/utils_spec.js b/spec/frontend/registry/explorer/utils_spec.js
new file mode 100644
index 00000000000..0cd4a1cec29
--- /dev/null
+++ b/spec/frontend/registry/explorer/utils_spec.js
@@ -0,0 +1,45 @@
+import { pathGenerator } from '~/registry/explorer/utils';
+
+describe('Utils', () => {
+ describe('pathGenerator', () => {
+ const imageDetails = {
+ path: 'foo/bar/baz',
+ name: 'baz',
+ id: 1,
+ };
+
+ it('returns the fetch url when no ending is passed', () => {
+ expect(pathGenerator(imageDetails)).toBe('/foo/bar/registry/repository/1/tags?format=json');
+ });
+
+ it('returns the url with an ending when is passed', () => {
+ expect(pathGenerator(imageDetails, '/foo')).toBe('/foo/bar/registry/repository/1/tags/foo');
+ });
+
+ it.each`
+ path | name | result
+ ${'foo/foo'} | ${''} | ${'/foo/foo/registry/repository/1/tags?format=json'}
+ ${'foo/foo/foo'} | ${'foo'} | ${'/foo/foo/registry/repository/1/tags?format=json'}
+ ${'baz/foo/foo/foo'} | ${'foo'} | ${'/baz/foo/foo/registry/repository/1/tags?format=json'}
+ ${'baz/foo/foo/foo'} | ${'foo'} | ${'/baz/foo/foo/registry/repository/1/tags?format=json'}
+ ${'foo/foo/baz/foo/foo'} | ${'foo/foo'} | ${'/foo/foo/baz/registry/repository/1/tags?format=json'}
+ ${'foo/foo/baz/foo/bar'} | ${'foo/bar'} | ${'/foo/foo/baz/registry/repository/1/tags?format=json'}
+ ${'baz/foo/foo'} | ${'foo'} | ${'/baz/foo/registry/repository/1/tags?format=json'}
+ ${'baz/foo/bar'} | ${'foo'} | ${'/baz/foo/bar/registry/repository/1/tags?format=json'}
+ `('returns the correct path when path is $path and name is $name', ({ name, path, result }) => {
+ expect(pathGenerator({ id: 1, name, path })).toBe(result);
+ });
+
+ it('returns the url unchanged when imageDetails have no name', () => {
+ const imageDetailsWithoutName = {
+ path: 'foo/bar/baz',
+ name: '',
+ id: 1,
+ };
+
+ expect(pathGenerator(imageDetailsWithoutName)).toBe(
+ '/foo/bar/baz/registry/repository/1/tags?format=json',
+ );
+ });
+ });
+});
diff --git a/spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap b/spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap
index 69953fb5e03..2ceb2655d40 100644
--- a/spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap
+++ b/spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap
@@ -123,7 +123,7 @@ exports[`Expiration Policy Form renders 1`] = `
disabled="true"
id="expiration-policy-name-matching"
noresize="true"
- placeholder=".*"
+ placeholder=""
trim=""
value=""
/>
diff --git a/spec/frontend/releases/__snapshots__/util_spec.js.snap b/spec/frontend/releases/__snapshots__/util_spec.js.snap
index 25c108e45bc..f49d3d7b716 100644
--- a/spec/frontend/releases/__snapshots__/util_spec.js.snap
+++ b/spec/frontend/releases/__snapshots__/util_spec.js.snap
@@ -5,9 +5,12 @@ Object {
"data": Array [
Object {
"_links": Object {
+ "closedIssuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.1&scope=all&state=closed",
+ "closedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.1&scope=all&state=closed",
"editUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/edit",
- "issuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.1&scope=all&state=opened",
- "mergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.1&scope=all&state=opened",
+ "mergedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.1&scope=all&state=merged",
+ "openedIssuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.1&scope=all&state=opened",
+ "openedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.1&scope=all&state=opened",
"self": "http://localhost/releases-namespace/releases-project/-/releases/v1.1",
"selfUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1",
},
@@ -15,7 +18,7 @@ Object {
"count": 8,
"links": Array [
Object {
- "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-3",
+ "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-3",
"external": true,
"id": "gid://gitlab/Releases::Link/13",
"linkType": "image",
@@ -23,7 +26,7 @@ Object {
"url": "https://example.com/image",
},
Object {
- "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-2",
+ "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-2",
"external": true,
"id": "gid://gitlab/Releases::Link/12",
"linkType": "package",
@@ -31,7 +34,7 @@ Object {
"url": "https://example.com/package",
},
Object {
- "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-1",
+ "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-1",
"external": false,
"id": "gid://gitlab/Releases::Link/11",
"linkType": "runbook",
@@ -39,7 +42,7 @@ Object {
"url": "http://localhost/releases-namespace/releases-project/runbook",
},
Object {
- "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/linux-amd64",
+ "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/linux-amd64",
"external": true,
"id": "gid://gitlab/Releases::Link/10",
"linkType": "other",
@@ -130,9 +133,12 @@ exports[`releases/util.js convertOneReleaseGraphQLResponse matches snapshot 1`]
Object {
"data": Object {
"_links": Object {
+ "closedIssuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.1&scope=all&state=closed",
+ "closedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.1&scope=all&state=closed",
"editUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/edit",
- "issuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.1&scope=all&state=opened",
- "mergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.1&scope=all&state=opened",
+ "mergedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.1&scope=all&state=merged",
+ "openedIssuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.1&scope=all&state=opened",
+ "openedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.1&scope=all&state=opened",
"self": "http://localhost/releases-namespace/releases-project/-/releases/v1.1",
"selfUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1",
},
@@ -140,7 +146,7 @@ Object {
"count": 8,
"links": Array [
Object {
- "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-3",
+ "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-3",
"external": true,
"id": "gid://gitlab/Releases::Link/13",
"linkType": "image",
@@ -148,7 +154,7 @@ Object {
"url": "https://example.com/image",
},
Object {
- "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-2",
+ "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-2",
"external": true,
"id": "gid://gitlab/Releases::Link/12",
"linkType": "package",
@@ -156,7 +162,7 @@ Object {
"url": "https://example.com/package",
},
Object {
- "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-1",
+ "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-1",
"external": false,
"id": "gid://gitlab/Releases::Link/11",
"linkType": "runbook",
@@ -164,7 +170,7 @@ Object {
"url": "http://localhost/releases-namespace/releases-project/runbook",
},
Object {
- "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/linux-amd64",
+ "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/linux-amd64",
"external": true,
"id": "gid://gitlab/Releases::Link/10",
"linkType": "other",
diff --git a/spec/frontend/releases/components/__snapshots__/issuable_stats_spec.js.snap b/spec/frontend/releases/components/__snapshots__/issuable_stats_spec.js.snap
new file mode 100644
index 00000000000..e53ea6b2ec6
--- /dev/null
+++ b/spec/frontend/releases/components/__snapshots__/issuable_stats_spec.js.snap
@@ -0,0 +1,9 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`~/releases/components/issuable_stats.vue matches snapshot 1`] = `
+"<div class=\\"gl-display-flex gl-flex-direction-column gl-flex-shrink-0 gl-mr-6 gl-mb-5\\"><span class=\\"gl-mb-2\\">
+ Items
+ <span class=\\"badge badge-muted badge-pill gl-badge sm\\"><!----> 10</span></span>
+ <div class=\\"gl-display-flex\\"><span data-testid=\\"open-stat\\" class=\\"gl-white-space-pre-wrap\\">Open: <a href=\\"path/to/opened/items\\" class=\\"gl-link\\">1</a></span> <span class=\\"gl-mx-2\\">•</span> <span data-testid=\\"merged-stat\\" class=\\"gl-white-space-pre-wrap\\">Merged: <a href=\\"path/to/merged/items\\" class=\\"gl-link\\">7</a></span> <span class=\\"gl-mx-2\\">•</span> <span data-testid=\\"closed-stat\\" class=\\"gl-white-space-pre-wrap\\">Closed: <a href=\\"path/to/closed/items\\" class=\\"gl-link\\">2</a></span></div>
+</div>"
+`;
diff --git a/spec/frontend/releases/components/app_edit_new_spec.js b/spec/frontend/releases/components/app_edit_new_spec.js
index d92bdc3b99a..1d409b5b590 100644
--- a/spec/frontend/releases/components/app_edit_new_spec.js
+++ b/spec/frontend/releases/components/app_edit_new_spec.js
@@ -24,9 +24,10 @@ describe('Release edit/new component', () => {
state = {
release,
markdownDocsPath: 'path/to/markdown/docs',
- updateReleaseApiDocsPath: 'path/to/update/release/api/docs',
releasesPagePath: 'path/to/releases/page',
projectId: '8',
+ groupId: '42',
+ groupMilestonesAvailable: true,
};
actions = {
diff --git a/spec/frontend/releases/components/issuable_stats_spec.js b/spec/frontend/releases/components/issuable_stats_spec.js
new file mode 100644
index 00000000000..d8211ec2adc
--- /dev/null
+++ b/spec/frontend/releases/components/issuable_stats_spec.js
@@ -0,0 +1,114 @@
+import { GlLink } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { trimText } from 'helpers/text_helper';
+import IssuableStats from '~/releases/components/issuable_stats.vue';
+
+describe('~/releases/components/issuable_stats.vue', () => {
+ let wrapper;
+ let defaultProps;
+
+ const createComponent = propUpdates => {
+ wrapper = mount(IssuableStats, {
+ propsData: {
+ ...defaultProps,
+ ...propUpdates,
+ },
+ });
+ };
+
+ const findOpenStatLink = () => wrapper.find('[data-testid="open-stat"]').find(GlLink);
+ const findMergedStatLink = () => wrapper.find('[data-testid="merged-stat"]').find(GlLink);
+ const findClosedStatLink = () => wrapper.find('[data-testid="closed-stat"]').find(GlLink);
+
+ beforeEach(() => {
+ defaultProps = {
+ label: 'Items',
+ total: 10,
+ closed: 2,
+ merged: 7,
+ openedPath: 'path/to/opened/items',
+ closedPath: 'path/to/closed/items',
+ mergedPath: 'path/to/merged/items',
+ };
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('matches snapshot', () => {
+ createComponent();
+
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+
+ describe('when only total and closed counts are provided', () => {
+ beforeEach(() => {
+ createComponent({ merged: undefined, mergedPath: undefined });
+ });
+
+ it('renders a label with the total count; also, the opened count and the closed count', () => {
+ expect(trimText(wrapper.text())).toMatchInterpolatedText('Items 10 Open: 8 • Closed: 2');
+ });
+ });
+
+ describe('when only total, merged, and closed counts are provided', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders a label with the total count; also, the opened count, the merged count, and the closed count', () => {
+ expect(wrapper.text()).toMatchInterpolatedText('Items 10 Open: 1 • Merged: 7 • Closed: 2');
+ });
+ });
+
+ describe('when path parameters are provided', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the "open" stat as a link', () => {
+ const link = findOpenStatLink();
+
+ expect(link.exists()).toBe(true);
+ expect(link.attributes('href')).toBe(defaultProps.openedPath);
+ });
+
+ it('renders the "merged" stat as a link', () => {
+ const link = findMergedStatLink();
+
+ expect(link.exists()).toBe(true);
+ expect(link.attributes('href')).toBe(defaultProps.mergedPath);
+ });
+
+ it('renders the "closed" stat as a link', () => {
+ const link = findClosedStatLink();
+
+ expect(link.exists()).toBe(true);
+ expect(link.attributes('href')).toBe(defaultProps.closedPath);
+ });
+ });
+
+ describe('when path parameters are not provided', () => {
+ beforeEach(() => {
+ createComponent({
+ openedPath: undefined,
+ closedPath: undefined,
+ mergedPath: undefined,
+ });
+ });
+
+ it('does not render the "open" stat as a link', () => {
+ expect(findOpenStatLink().exists()).toBe(false);
+ });
+
+ it('does not render the "merged" stat as a link', () => {
+ expect(findMergedStatLink().exists()).toBe(false);
+ });
+
+ it('does not render the "closed" stat as a link', () => {
+ expect(findClosedStatLink().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/releases/components/release_block_milestone_info_spec.js b/spec/frontend/releases/components/release_block_milestone_info_spec.js
index 45f4eaa01a9..bb34693c757 100644
--- a/spec/frontend/releases/components/release_block_milestone_info_spec.js
+++ b/spec/frontend/releases/components/release_block_milestone_info_spec.js
@@ -31,7 +31,8 @@ describe('Release block milestone info', () => {
const milestoneProgressBarContainer = () => wrapper.find('.js-milestone-progress-bar-container');
const milestoneListContainer = () => wrapper.find('.js-milestone-list-container');
- const issuesContainer = () => wrapper.find('.js-issues-container');
+ const issuesContainer = () => wrapper.find('[data-testid="issue-stats"]');
+ const mergeRequestsContainer = () => wrapper.find('[data-testid="merge-request-stats"]');
describe('with default props', () => {
beforeEach(() => factory({ milestones }));
@@ -188,66 +189,32 @@ describe('Release block milestone info', () => {
expectAllZeros();
});
- describe('Issue links', () => {
- const findOpenIssuesLink = () => wrapper.find({ ref: 'openIssuesLink' });
- const findOpenIssuesText = () => wrapper.find({ ref: 'openIssuesText' });
- const findClosedIssuesLink = () => wrapper.find({ ref: 'closedIssuesLink' });
- const findClosedIssuesText = () => wrapper.find({ ref: 'closedIssuesText' });
-
- describe('when openIssuePath is provided', () => {
- const openIssuesPath = '/path/to/open/issues';
-
- beforeEach(() => {
- return factory({ milestones, openIssuesPath });
- });
-
- it('renders the open issues as a link', () => {
- expect(findOpenIssuesLink().exists()).toBe(true);
- expect(findOpenIssuesText().exists()).toBe(false);
- });
-
- it('renders the open issues link with the correct href', () => {
- expect(findOpenIssuesLink().attributes().href).toBe(openIssuesPath);
- });
- });
-
- describe('when openIssuePath is not provided', () => {
- beforeEach(() => {
- return factory({ milestones });
- });
+ describe('if the API response is missing the "mr_stats" property', () => {
+ beforeEach(() => factory({ milestones }));
- it('renders the open issues as plain text', () => {
- expect(findOpenIssuesLink().exists()).toBe(false);
- expect(findOpenIssuesText().exists()).toBe(true);
- });
+ it('does not render merge request stats', () => {
+ expect(mergeRequestsContainer().exists()).toBe(false);
});
+ });
- describe('when closedIssuePath is provided', () => {
- const closedIssuesPath = '/path/to/closed/issues';
-
- beforeEach(() => {
- return factory({ milestones, closedIssuesPath });
- });
-
- it('renders the closed issues as a link', () => {
- expect(findClosedIssuesLink().exists()).toBe(true);
- expect(findClosedIssuesText().exists()).toBe(false);
- });
+ describe('if the API response includes the "mr_stats" property', () => {
+ beforeEach(() => {
+ milestones = milestones.map(m => ({
+ ...m,
+ mrStats: {
+ total: 15,
+ merged: 12,
+ closed: 1,
+ },
+ }));
- it('renders the closed issues link with the correct href', () => {
- expect(findClosedIssuesLink().attributes().href).toBe(closedIssuesPath);
- });
+ return factory({ milestones });
});
- describe('when closedIssuePath is not provided', () => {
- beforeEach(() => {
- return factory({ milestones });
- });
-
- it('renders the closed issues as plain text', () => {
- expect(findClosedIssuesLink().exists()).toBe(false);
- expect(findClosedIssuesText().exists()).toBe(true);
- });
+ it('renders merge request stats', () => {
+ expect(trimText(mergeRequestsContainer().text())).toBe(
+ 'Merge Requests 30 Open: 4 • Merged: 24 • Closed: 2',
+ );
});
});
});
diff --git a/spec/frontend/releases/components/releases_sort_spec.js b/spec/frontend/releases/components/releases_sort_spec.js
new file mode 100644
index 00000000000..c089ee3cc38
--- /dev/null
+++ b/spec/frontend/releases/components/releases_sort_spec.js
@@ -0,0 +1,66 @@
+import Vuex from 'vuex';
+import { GlSorting, GlSortingItem } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import ReleasesSort from '~/releases/components/releases_sort.vue';
+import createStore from '~/releases/stores';
+import createListModule from '~/releases/stores/modules/list';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('~/releases/components/releases_sort.vue', () => {
+ let wrapper;
+ let store;
+ let listModule;
+ const projectId = 8;
+
+ const createComponent = () => {
+ listModule = createListModule({ projectId });
+
+ store = createStore({
+ modules: {
+ list: listModule,
+ },
+ });
+
+ store.dispatch = jest.fn();
+
+ wrapper = shallowMount(ReleasesSort, {
+ store,
+ stubs: {
+ GlSortingItem,
+ },
+ localVue,
+ });
+ };
+
+ const findReleasesSorting = () => wrapper.find(GlSorting);
+ const findSortingItems = () => wrapper.findAll(GlSortingItem);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('has all the sortable items', () => {
+ expect(findSortingItems()).toHaveLength(wrapper.vm.sortOptions.length);
+ });
+
+ it('on sort change set sorting in vuex and emit event', () => {
+ findReleasesSorting().vm.$emit('sortDirectionChange');
+ expect(store.dispatch).toHaveBeenCalledWith('list/setSorting', { sort: 'asc' });
+ expect(wrapper.emitted('sort:changed')).toBeTruthy();
+ });
+
+ it('on sort item click set sorting and emit event', () => {
+ const item = findSortingItems().at(0);
+ const { orderBy } = wrapper.vm.sortOptions[0];
+ item.vm.$emit('click');
+ expect(store.dispatch).toHaveBeenCalledWith('list/setSorting', { orderBy });
+ expect(wrapper.emitted('sort:changed')).toBeTruthy();
+ });
+});
diff --git a/spec/frontend/releases/components/tag_field_exsting_spec.js b/spec/frontend/releases/components/tag_field_exsting_spec.js
index 70a195556df..d4110b57776 100644
--- a/spec/frontend/releases/components/tag_field_exsting_spec.js
+++ b/spec/frontend/releases/components/tag_field_exsting_spec.js
@@ -6,7 +6,6 @@ import createStore from '~/releases/stores';
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);
@@ -24,21 +23,11 @@ describe('releases/components/tag_field_existing', () => {
const findInput = () => wrapper.find(GlFormInput);
const findHelp = () => wrapper.find('[data-testid="tag-name-help"]');
- const findHelpLink = () => {
- const link = findHelp().find('a');
-
- return {
- text: link.text(),
- href: link.attributes('href'),
- target: link.attributes('target'),
- };
- };
beforeEach(() => {
store = createStore({
modules: {
detail: createDetailModule({
- updateReleaseApiDocsPath: TEST_DOCS_PATH,
tagName: TEST_TAG_NAME,
}),
},
@@ -68,16 +57,8 @@ describe('releases/components/tag_field_existing', () => {
createComponent(mount);
expect(findHelp().text()).toMatchInterpolatedText(
- 'Changing a Release tag is only supported via Releases API. More information',
+ "The tag name can't be changed for an existing release.",
);
-
- const helpLink = findHelpLink();
-
- expect(helpLink).toEqual({
- text: 'More information',
- href: TEST_DOCS_PATH,
- target: '_blank',
- });
});
});
});
diff --git a/spec/frontend/releases/stores/modules/detail/actions_spec.js b/spec/frontend/releases/stores/modules/detail/actions_spec.js
index d38f6766d4e..abd0db6a589 100644
--- a/spec/frontend/releases/stores/modules/detail/actions_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/actions_spec.js
@@ -47,7 +47,6 @@ describe('Release detail actions', () => {
releasesPagePath: 'path/to/releases/page',
markdownDocsPath: 'path/to/markdown/docs',
markdownPreviewPath: 'path/to/markdown/preview',
- updateReleaseApiDocsPath: 'path/to/api/docs',
}),
...getters,
...rootState,
diff --git a/spec/frontend/releases/stores/modules/detail/mutations_spec.js b/spec/frontend/releases/stores/modules/detail/mutations_spec.js
index f3e84262754..88eddc4019c 100644
--- a/spec/frontend/releases/stores/modules/detail/mutations_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/mutations_spec.js
@@ -18,7 +18,6 @@ describe('Release detail mutations', () => {
releasesPagePath: 'path/to/releases/page',
markdownDocsPath: 'path/to/markdown/docs',
markdownPreviewPath: 'path/to/markdown/preview',
- updateReleaseApiDocsPath: 'path/to/api/docs',
});
release = convertObjectPropsToCamelCase(originalRelease);
});
diff --git a/spec/frontend/releases/stores/modules/list/actions_spec.js b/spec/frontend/releases/stores/modules/list/actions_spec.js
index 4e235e1d00f..35551b77dc4 100644
--- a/spec/frontend/releases/stores/modules/list/actions_spec.js
+++ b/spec/frontend/releases/stores/modules/list/actions_spec.js
@@ -6,6 +6,7 @@ import {
fetchReleasesGraphQl,
fetchReleasesRest,
receiveReleasesError,
+ setSorting,
} from '~/releases/stores/modules/list/actions';
import createState from '~/releases/stores/modules/list/state';
import * as types from '~/releases/stores/modules/list/mutation_types';
@@ -114,7 +115,7 @@ describe('Releases State actions', () => {
it('makes a GraphQl query with a first variable', () => {
expect(gqClient.query).toHaveBeenCalledWith({
query: allReleasesQuery,
- variables: { fullPath: projectPath, first: PAGE_SIZE },
+ variables: { fullPath: projectPath, first: PAGE_SIZE, sort: 'RELEASED_AT_DESC' },
});
});
});
@@ -127,7 +128,7 @@ describe('Releases State actions', () => {
it('makes a GraphQl query with last and before variables', () => {
expect(gqClient.query).toHaveBeenCalledWith({
query: allReleasesQuery,
- variables: { fullPath: projectPath, last: PAGE_SIZE, before },
+ variables: { fullPath: projectPath, last: PAGE_SIZE, before, sort: 'RELEASED_AT_DESC' },
});
});
});
@@ -140,7 +141,7 @@ describe('Releases State actions', () => {
it('makes a GraphQl query with first and after variables', () => {
expect(gqClient.query).toHaveBeenCalledWith({
query: allReleasesQuery,
- variables: { fullPath: projectPath, first: PAGE_SIZE, after },
+ variables: { fullPath: projectPath, first: PAGE_SIZE, after, sort: 'RELEASED_AT_DESC' },
});
});
});
@@ -156,6 +157,29 @@ describe('Releases State actions', () => {
);
});
});
+
+ describe('when the sort parameters are provided', () => {
+ it.each`
+ sort | orderBy | ReleaseSort
+ ${'asc'} | ${'released_at'} | ${'RELEASED_AT_ASC'}
+ ${'desc'} | ${'released_at'} | ${'RELEASED_AT_DESC'}
+ ${'asc'} | ${'created_at'} | ${'CREATED_ASC'}
+ ${'desc'} | ${'created_at'} | ${'CREATED_DESC'}
+ `(
+ 'correctly sets $ReleaseSort based on $sort and $orderBy',
+ ({ sort, orderBy, ReleaseSort }) => {
+ mockedState.sorting.sort = sort;
+ mockedState.sorting.orderBy = orderBy;
+
+ fetchReleasesGraphQl(vuexParams, { before: undefined, after: undefined });
+
+ expect(gqClient.query).toHaveBeenCalledWith({
+ query: allReleasesQuery,
+ variables: { fullPath: projectPath, first: PAGE_SIZE, sort: ReleaseSort },
+ });
+ },
+ );
+ });
});
describe('when the request is successful', () => {
@@ -230,7 +254,11 @@ describe('Releases State actions', () => {
});
it('makes a REST query with a page query parameter', () => {
- expect(api.releases).toHaveBeenCalledWith(projectId, { page });
+ expect(api.releases).toHaveBeenCalledWith(projectId, {
+ page,
+ order_by: 'released_at',
+ sort: 'desc',
+ });
});
});
});
@@ -302,4 +330,16 @@ describe('Releases State actions', () => {
);
});
});
+
+ describe('setSorting', () => {
+ it('should commit SET_SORTING', () => {
+ return testAction(
+ setSorting,
+ { orderBy: 'released_at', sort: 'asc' },
+ null,
+ [{ type: types.SET_SORTING, payload: { orderBy: 'released_at', sort: 'asc' } }],
+ [],
+ );
+ });
+ });
});
diff --git a/spec/frontend/releases/stores/modules/list/mutations_spec.js b/spec/frontend/releases/stores/modules/list/mutations_spec.js
index 521418cbddb..78071573072 100644
--- a/spec/frontend/releases/stores/modules/list/mutations_spec.js
+++ b/spec/frontend/releases/stores/modules/list/mutations_spec.js
@@ -80,4 +80,16 @@ describe('Releases Store Mutations', () => {
expect(stateCopy.graphQlPageInfo).toEqual({});
});
});
+
+ describe('SET_SORTING', () => {
+ it('should merge the sorting object with sort value', () => {
+ mutations[types.SET_SORTING](stateCopy, { sort: 'asc' });
+ expect(stateCopy.sorting).toEqual({ ...stateCopy.sorting, sort: 'asc' });
+ });
+
+ it('should merge the sorting object with order_by value', () => {
+ mutations[types.SET_SORTING](stateCopy, { orderBy: 'created_at' });
+ expect(stateCopy.sorting).toEqual({ ...stateCopy.sorting, orderBy: 'created_at' });
+ });
+ });
});
diff --git a/spec/frontend/releases/util_spec.js b/spec/frontend/releases/util_spec.js
index e7b7766c0d0..fd00a524628 100644
--- a/spec/frontend/releases/util_spec.js
+++ b/spec/frontend/releases/util_spec.js
@@ -22,7 +22,7 @@ describe('releases/util.js', () => {
tagName: 'tag-name',
name: 'Release name',
description: 'Release description',
- milestones: [{ id: 1, title: '13.2' }, { id: 2, title: '13.3' }],
+ milestones: ['13.2', '13.3'],
assets: {
links: [{ url: 'https://gitlab.example.com/link', linkType: 'other' }],
},
@@ -74,14 +74,14 @@ describe('releases/util.js', () => {
});
});
- describe('when release.milestones is falsy', () => {
- it('includes a "milestone" property in the returned result as an empty array', () => {
- const release = {};
-
- const expectedJson = {
- milestones: [],
+ describe('when milestones contains full milestone objects', () => {
+ it('converts the milestone objects into titles', () => {
+ const release = {
+ milestones: [{ title: '13.2' }, { title: '13.3' }, '13.4'],
};
+ const expectedJson = { milestones: ['13.2', '13.3', '13.4'] };
+
expect(releaseToApiJson(release)).toMatchObject(expectedJson);
});
});
diff --git a/spec/frontend/reports/codequality_report/components/codequality_issue_body_spec.js b/spec/frontend/reports/codequality_report/components/codequality_issue_body_spec.js
index 3e11af9c9df..f99dcbffdff 100644
--- a/spec/frontend/reports/codequality_report/components/codequality_issue_body_spec.js
+++ b/spec/frontend/reports/codequality_report/components/codequality_issue_body_spec.js
@@ -1,10 +1,15 @@
+import { GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import component from '~/reports/codequality_report/components/codequality_issue_body.vue';
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants';
describe('code quality issue body issue body', () => {
let wrapper;
+ const findSeverityIcon = () => wrapper.findByTestId('codequality-severity-icon');
+ const findGlIcon = () => wrapper.find(GlIcon);
+
const codequalityIssue = {
name:
'rubygem-rest-client: session fixation vulnerability via Set-Cookie headers in 30x redirection responses',
@@ -14,13 +19,15 @@ describe('code quality issue body issue body', () => {
urlPath: '/Gemfile.lock#L22',
};
- const mountWithStatus = initialStatus => {
- wrapper = shallowMount(component, {
- propsData: {
- issue: codequalityIssue,
- status: initialStatus,
- },
- });
+ const createComponent = (initialStatus, issue = codequalityIssue) => {
+ wrapper = extendedWrapper(
+ shallowMount(component, {
+ propsData: {
+ issue,
+ status: initialStatus,
+ },
+ }),
+ );
};
afterEach(() => {
@@ -28,17 +35,43 @@ describe('code quality issue body issue body', () => {
wrapper = null;
});
+ describe('severity rating', () => {
+ it.each`
+ severity | iconClass | iconName
+ ${'info'} | ${'text-primary-400'} | ${'severity-info'}
+ ${'minor'} | ${'text-warning-200'} | ${'severity-low'}
+ ${'major'} | ${'text-warning-400'} | ${'severity-medium'}
+ ${'critical'} | ${'text-danger-600'} | ${'severity-high'}
+ ${'blocker'} | ${'text-danger-800'} | ${'severity-critical'}
+ ${'unknown'} | ${'text-secondary-400'} | ${'severity-unknown'}
+ ${'invalid'} | ${'text-secondary-400'} | ${'severity-unknown'}
+ `(
+ 'renders correct icon for "$severity" severity rating',
+ ({ severity, iconClass, iconName }) => {
+ createComponent(STATUS_FAILED, {
+ ...codequalityIssue,
+ severity,
+ });
+ const icon = findGlIcon();
+
+ expect(findSeverityIcon().classes()).toContain(iconClass);
+ expect(icon.exists()).toBe(true);
+ expect(icon.props('name')).toBe(iconName);
+ },
+ );
+ });
+
describe('with success', () => {
it('renders fixed label', () => {
- mountWithStatus(STATUS_SUCCESS);
+ createComponent(STATUS_SUCCESS);
expect(wrapper.text()).toContain('Fixed');
});
});
describe('without success', () => {
- it('renders fixed label', () => {
- mountWithStatus(STATUS_FAILED);
+ it('does not render fixed label', () => {
+ createComponent(STATUS_FAILED);
expect(wrapper.text()).not.toContain('Fixed');
});
@@ -46,7 +79,7 @@ describe('code quality issue body issue body', () => {
describe('name', () => {
it('renders name', () => {
- mountWithStatus(STATUS_NEUTRAL);
+ createComponent(STATUS_NEUTRAL);
expect(wrapper.text()).toContain(codequalityIssue.name);
});
@@ -54,7 +87,7 @@ describe('code quality issue body issue body', () => {
describe('path', () => {
it('renders the report-link path using the correct code quality issue', () => {
- mountWithStatus(STATUS_NEUTRAL);
+ createComponent(STATUS_NEUTRAL);
expect(wrapper.find('report-link-stub').props('issue')).toBe(codequalityIssue);
});
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 556904b7da5..ae2718db17f 100644
--- a/spec/frontend/reports/components/grouped_test_reports_app_spec.js
+++ b/spec/frontend/reports/components/grouped_test_reports_app_spec.js
@@ -1,11 +1,13 @@
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
+import { mockTracking } from 'helpers/tracking_helper';
import GroupedTestReportsApp from '~/reports/components/grouped_test_reports_app.vue';
import { getStoreConfig } from '~/reports/store';
import { failedReport } from '../mock_data/mock_data';
import successTestReports from '../mock_data/no_failures_report.json';
import newFailedTestReports from '../mock_data/new_failures_report.json';
+import recentFailuresTestReports from '../mock_data/recent_failures_report.json';
import newErrorsTestReports from '../mock_data/new_errors_report.json';
import mixedResultsTestReports from '../mock_data/new_and_fixed_failures_report.json';
import resolvedFailures from '../mock_data/resolved_failures.json';
@@ -20,7 +22,7 @@ describe('Grouped test reports app', () => {
let wrapper;
let mockStore;
- const mountComponent = ({ props = { pipelinePath } } = {}) => {
+ const mountComponent = ({ props = { pipelinePath }, testFailureHistory = false } = {}) => {
wrapper = mount(Component, {
store: mockStore,
localVue,
@@ -29,6 +31,11 @@ describe('Grouped test reports app', () => {
pipelinePath,
...props,
},
+ provide: {
+ glFeatures: {
+ testFailureHistory,
+ },
+ },
});
};
@@ -39,6 +46,7 @@ describe('Grouped test reports app', () => {
};
const findHeader = () => wrapper.find('[data-testid="report-section-code-text"]');
+ const findExpandButton = () => wrapper.find('[data-testid="report-section-expand-button"]');
const findFullTestReportLink = () => wrapper.find('[data-testid="group-test-reports-full-link"]');
const findSummaryDescription = () => wrapper.find('[data-testid="test-summary-row-description"]');
const findIssueDescription = () => wrapper.find('[data-testid="test-issue-body-description"]');
@@ -96,6 +104,35 @@ describe('Grouped test reports app', () => {
});
});
+ describe('`Expand` button', () => {
+ let trackingSpy;
+
+ beforeEach(() => {
+ setReports(newFailedTestReports);
+ mountComponent();
+ document.body.dataset.page = 'projects:merge_requests:show';
+ trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
+ });
+
+ it('tracks an event on click', () => {
+ findExpandButton().trigger('click');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'expand_test_report_widget', {});
+ });
+
+ it('only tracks the first expansion', () => {
+ expect(trackingSpy).not.toHaveBeenCalled();
+
+ const button = findExpandButton();
+
+ button.trigger('click');
+ button.trigger('click');
+ button.trigger('click');
+
+ expect(trackingSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+
describe('with new failed result', () => {
beforeEach(() => {
setReports(newFailedTestReports);
@@ -203,6 +240,77 @@ describe('Grouped test reports app', () => {
});
});
+ describe('recent failures counts', () => {
+ describe('with recent failures counts', () => {
+ beforeEach(() => {
+ setReports(recentFailuresTestReports);
+ });
+
+ describe('with feature flag enabled', () => {
+ beforeEach(() => {
+ mountComponent({ testFailureHistory: true });
+ });
+
+ it('renders the recently failed tests summary', () => {
+ expect(findHeader().text()).toContain(
+ '2 out of 3 failed tests have failed more than once in the last 14 days',
+ );
+ });
+
+ it('renders the recently failed count on the test suite', () => {
+ expect(findSummaryDescription().text()).toContain(
+ '1 out of 2 failed tests has failed more than once in the last 14 days',
+ );
+ });
+
+ it('renders the recent failures count on the test case', () => {
+ expect(findIssueDescription().text()).toContain('Failed 8 times in the last 14 days');
+ });
+ });
+
+ describe('with feature flag disabled', () => {
+ beforeEach(() => {
+ mountComponent({ testFailureHistory: false });
+ });
+
+ it('does not render the recently failed tests summary', () => {
+ expect(findHeader().text()).not.toContain('failed more than once in the last 14 days');
+ });
+
+ it('does not render the recently failed count on the test suite', () => {
+ expect(findSummaryDescription().text()).not.toContain(
+ 'failed more than once in the last 14 days',
+ );
+ });
+
+ it('renders the recent failures count on the test case', () => {
+ expect(findIssueDescription().text()).not.toContain('in the last 14 days');
+ });
+ });
+ });
+
+ describe('without recent failures counts', () => {
+ beforeEach(() => {
+ setReports(mixedResultsTestReports);
+ mountComponent();
+ });
+
+ it('does not render the recently failed tests summary', () => {
+ expect(findHeader().text()).not.toContain('failed more than once in the last 14 days');
+ });
+
+ it('does not render the recently failed count on the test suite', () => {
+ expect(findSummaryDescription().text()).not.toContain(
+ 'failed more than once in the last 14 days',
+ );
+ });
+
+ it('does not render the recent failures count on the test case', () => {
+ expect(findIssueDescription().text()).not.toContain('in the last 14 days');
+ });
+ });
+ });
+
describe('with a report that failed to load', () => {
beforeEach(() => {
setReports(failedReport);
diff --git a/spec/frontend/reports/components/report_section_spec.js b/spec/frontend/reports/components/report_section_spec.js
index a620b5d9afc..2d228313a9b 100644
--- a/spec/frontend/reports/components/report_section_spec.js
+++ b/spec/frontend/reports/components/report_section_spec.js
@@ -244,7 +244,7 @@ describe('Report section', () => {
hasIssues: true,
},
slots: {
- actionButtons: ['Action!'],
+ 'action-buttons': ['Action!'],
},
});
});
diff --git a/spec/frontend/reports/mock_data/recent_failures_report.json b/spec/frontend/reports/mock_data/recent_failures_report.json
new file mode 100644
index 00000000000..a47bc30a8e5
--- /dev/null
+++ b/spec/frontend/reports/mock_data/recent_failures_report.json
@@ -0,0 +1,46 @@
+{
+ "summary": { "total": 11, "resolved": 0, "errored": 0, "failed": 3, "recentlyFailed": 2 },
+ "suites": [
+ {
+ "name": "rspec:pg",
+ "summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 2, "recentlyFailed": 1 },
+ "new_failures": [
+ {
+ "result": "failure",
+ "name": "Test#sum when a is 1 and b is 2 returns summary",
+ "execution_time": 0.009411,
+ "system_output": "Failure/Error: is_expected.to eq(3)\n\n expected: 3\n got: -1\n\n (compared using ==)\n./spec/test_spec.rb:12:in `block (4 levels) in <top (required)>'",
+ "recent_failures": 8
+ },
+ {
+ "result": "failure",
+ "name": "Test#sum when a is 100 and b is 200 returns summary",
+ "execution_time": 0.000162,
+ "system_output": "Failure/Error: is_expected.to eq(300)\n\n expected: 300\n got: -100\n\n (compared using ==)\n./spec/test_spec.rb:21:in `block (4 levels) in <top (required)>'"
+ }
+ ],
+ "resolved_failures": [],
+ "existing_failures": [],
+ "new_errors": [],
+ "resolved_errors": [],
+ "existing_errors": []
+ },
+ {
+ "name": "java ant",
+ "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 1, "recentlyFailed": 1 },
+ "new_failures": [
+ {
+ "result": "failure",
+ "name": "Test#sum when a is 100 and b is 200 returns summary",
+ "execution_time": 0.000562,
+ "recent_failures": 3
+ }
+ ],
+ "resolved_failures": [],
+ "existing_failures": [],
+ "new_errors": [],
+ "resolved_errors": [],
+ "existing_errors": []
+ }
+ ]
+}
diff --git a/spec/frontend/reports/store/mutations_spec.js b/spec/frontend/reports/store/mutations_spec.js
index 9446cd454ab..82a399c876d 100644
--- a/spec/frontend/reports/store/mutations_spec.js
+++ b/spec/frontend/reports/store/mutations_spec.js
@@ -46,6 +46,7 @@ describe('Reports Store Mutations', () => {
name: 'StringHelper#concatenate when a is git and b is lab returns summary',
execution_time: 0.0092435,
system_output: "Failure/Error: is_expected.to eq('gitlab')",
+ recent_failures: 4,
},
],
resolved_failures: [
@@ -82,6 +83,7 @@ describe('Reports Store Mutations', () => {
expect(stateCopy.summary.total).toEqual(mockedResponse.summary.total);
expect(stateCopy.summary.resolved).toEqual(mockedResponse.summary.resolved);
expect(stateCopy.summary.failed).toEqual(mockedResponse.summary.failed);
+ expect(stateCopy.summary.recentlyFailed).toEqual(1);
});
it('should set reports', () => {
diff --git a/spec/frontend/reports/store/utils_spec.js b/spec/frontend/reports/store/utils_spec.js
index 9ae456658dc..8977268115e 100644
--- a/spec/frontend/reports/store/utils_spec.js
+++ b/spec/frontend/reports/store/utils_spec.js
@@ -168,6 +168,54 @@ describe('Reports store utils', () => {
});
});
+ describe('recentFailuresTextBuilder', () => {
+ it.each`
+ recentlyFailed | failed | expected
+ ${0} | ${1} | ${''}
+ ${1} | ${1} | ${'1 out of 1 failed test has failed more than once in the last 14 days'}
+ ${1} | ${2} | ${'1 out of 2 failed tests has failed more than once in the last 14 days'}
+ ${2} | ${3} | ${'2 out of 3 failed tests have failed more than once in the last 14 days'}
+ `(
+ 'should render summary for $recentlyFailed out of $failed failures',
+ ({ recentlyFailed, failed, expected }) => {
+ const result = utils.recentFailuresTextBuilder({ recentlyFailed, failed });
+
+ expect(result).toBe(expected);
+ },
+ );
+ });
+
+ describe('countRecentlyFailedTests', () => {
+ it('counts tests with more than one recent failure in a report', () => {
+ const report = {
+ new_failures: [{ recent_failures: 2 }],
+ existing_failures: [{ recent_failures: 1 }],
+ resolved_failures: [{ recent_failures: 20 }, { recent_failures: 5 }],
+ };
+ const result = utils.countRecentlyFailedTests(report);
+
+ expect(result).toBe(3);
+ });
+
+ it('counts tests with more than one recent failure in an array of reports', () => {
+ const reports = [
+ {
+ new_failures: [{ recent_failures: 2 }],
+ existing_failures: [{ recent_failures: 20 }, { recent_failures: 5 }],
+ resolved_failures: [{ recent_failures: 2 }],
+ },
+ {
+ new_failures: [{ recent_failures: 8 }, { recent_failures: 14 }],
+ existing_failures: [{ recent_failures: 1 }],
+ resolved_failures: [{ recent_failures: 7 }, { recent_failures: 5 }],
+ },
+ ];
+ const result = utils.countRecentlyFailedTests(reports);
+
+ expect(result).toBe(8);
+ });
+ });
+
describe('statusIcon', () => {
describe('with failed status', () => {
it('returns ICON_WARNING', () => {
diff --git a/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap b/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap
index aaa8bf168f2..be4f8a688e0 100644
--- a/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap
+++ b/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap
@@ -40,7 +40,6 @@ exports[`Repository last commit component renders commit widget 1`] = `
>
Test
-
</gl-link-stub>
authored
@@ -147,7 +146,6 @@ exports[`Repository last commit component renders the signature HTML as returned
>
Test
-
</gl-link-stub>
authored
diff --git a/spec/frontend/repository/components/preview/__snapshots__/index_spec.js.snap b/spec/frontend/repository/components/preview/__snapshots__/index_spec.js.snap
index 23c06dc5e68..e2ccc07d0f2 100644
--- a/spec/frontend/repository/components/preview/__snapshots__/index_spec.js.snap
+++ b/spec/frontend/repository/components/preview/__snapshots__/index_spec.js.snap
@@ -29,6 +29,7 @@ exports[`Repository file preview component renders file HTML 1`] = `
<div
class="blob-viewer"
data-qa-selector="blob_viewer_content"
+ itemprop="about"
>
<div>
<div
diff --git a/spec/frontend/search/dropdown_filter/components/dropdown_filter_spec.js b/spec/frontend/search/dropdown_filter/components/dropdown_filter_spec.js
deleted file mode 100644
index 4a6b5cebe1c..00000000000
--- a/spec/frontend/search/dropdown_filter/components/dropdown_filter_spec.js
+++ /dev/null
@@ -1,196 +0,0 @@
-import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import * as urlUtils from '~/lib/utils/url_utility';
-import initStore from '~/search/store';
-import DropdownFilter from '~/search/dropdown_filter/components/dropdown_filter.vue';
-import stateFilterData from '~/search/dropdown_filter/constants/state_filter_data';
-import confidentialFilterData from '~/search/dropdown_filter/constants/confidential_filter_data';
-import { MOCK_QUERY } from '../mock_data';
-
-jest.mock('~/lib/utils/url_utility', () => ({
- visitUrl: jest.fn(),
- setUrlParams: jest.fn(),
-}));
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('DropdownFilter', () => {
- let wrapper;
- let store;
-
- const createStore = options => {
- store = initStore({ query: MOCK_QUERY, ...options });
- };
-
- const createComponent = (props = { filterData: stateFilterData }) => {
- wrapper = shallowMount(DropdownFilter, {
- localVue,
- store,
- propsData: {
- ...props,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- store = 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('StatusFilter', () => {
- describe('template', () => {
- describe.each`
- scope | showDropdown
- ${'issues'} | ${true}
- ${'merge_requests'} | ${true}
- ${'projects'} | ${false}
- ${'milestones'} | ${false}
- ${'users'} | ${false}
- ${'notes'} | ${false}
- ${'wiki_blobs'} | ${false}
- ${'blobs'} | ${false}
- `(`dropdown`, ({ scope, showDropdown }) => {
- beforeEach(() => {
- createStore({ query: { ...MOCK_QUERY, scope } });
- createComponent();
- });
-
- it(`does${showDropdown ? '' : ' not'} render when scope is ${scope}`, () => {
- expect(findGlDropdown().exists()).toBe(showDropdown);
- });
- });
-
- describe.each`
- initialFilter | label
- ${stateFilterData.filters.ANY.value} | ${`Any ${stateFilterData.header}`}
- ${stateFilterData.filters.OPEN.value} | ${stateFilterData.filters.OPEN.label}
- ${stateFilterData.filters.CLOSED.value} | ${stateFilterData.filters.CLOSED.label}
- `(`filter text`, ({ initialFilter, label }) => {
- describe(`when initialFilter is ${initialFilter}`, () => {
- beforeEach(() => {
- createStore({ query: { ...MOCK_QUERY, [stateFilterData.filterParam]: initialFilter } });
- createComponent();
- });
-
- it(`sets dropdown label to ${label}`, () => {
- expect(findGlDropdown().attributes('text')).toBe(label);
- });
- });
- });
- });
-
- describe('Filter options', () => {
- beforeEach(() => {
- createStore();
- createComponent();
- });
-
- it('renders a dropdown item for each filterOption', () => {
- expect(findDropdownItemsText()).toStrictEqual(
- stateFilterData.filterByScope[stateFilterData.scopes.ISSUES].map(v => {
- return v.label;
- }),
- );
- });
-
- it('clicking a dropdown item calls setUrlParams', () => {
- const filter = stateFilterData.filters[Object.keys(stateFilterData.filters)[0]].value;
- firstDropDownItem().vm.$emit('click');
-
- expect(urlUtils.setUrlParams).toHaveBeenCalledWith({
- [stateFilterData.filterParam]: filter,
- });
- });
-
- it('clicking a dropdown item calls visitUrl', () => {
- firstDropDownItem().vm.$emit('click');
-
- expect(urlUtils.visitUrl).toHaveBeenCalled();
- });
- });
- });
-
- describe('ConfidentialFilter', () => {
- describe('template', () => {
- describe.each`
- scope | showDropdown
- ${'issues'} | ${true}
- ${'merge_requests'} | ${false}
- ${'projects'} | ${false}
- ${'milestones'} | ${false}
- ${'users'} | ${false}
- ${'notes'} | ${false}
- ${'wiki_blobs'} | ${false}
- ${'blobs'} | ${false}
- `(`dropdown`, ({ scope, showDropdown }) => {
- beforeEach(() => {
- createStore({ query: { ...MOCK_QUERY, scope } });
- createComponent({ filterData: confidentialFilterData });
- });
-
- it(`does${showDropdown ? '' : ' not'} render when scope is ${scope}`, () => {
- expect(findGlDropdown().exists()).toBe(showDropdown);
- });
- });
-
- describe.each`
- initialFilter | label
- ${confidentialFilterData.filters.ANY.value} | ${`Any ${confidentialFilterData.header}`}
- ${confidentialFilterData.filters.CONFIDENTIAL.value} | ${confidentialFilterData.filters.CONFIDENTIAL.label}
- ${confidentialFilterData.filters.NOT_CONFIDENTIAL.value} | ${confidentialFilterData.filters.NOT_CONFIDENTIAL.label}
- `(`filter text`, ({ initialFilter, label }) => {
- describe(`when initialFilter is ${initialFilter}`, () => {
- beforeEach(() => {
- createStore({
- query: { ...MOCK_QUERY, [confidentialFilterData.filterParam]: initialFilter },
- });
- createComponent({ filterData: confidentialFilterData });
- });
-
- it(`sets dropdown label to ${label}`, () => {
- expect(findGlDropdown().attributes('text')).toBe(label);
- });
- });
- });
- });
- });
-
- describe('Filter options', () => {
- beforeEach(() => {
- createStore();
- createComponent({ filterData: confidentialFilterData });
- });
-
- it('renders a dropdown item for each filterOption', () => {
- expect(findDropdownItemsText()).toStrictEqual(
- confidentialFilterData.filterByScope[confidentialFilterData.scopes.ISSUES].map(v => {
- return v.label;
- }),
- );
- });
-
- it('clicking a dropdown item calls setUrlParams', () => {
- const filter =
- confidentialFilterData.filters[Object.keys(confidentialFilterData.filters)[0]].value;
- firstDropDownItem().vm.$emit('click');
-
- expect(urlUtils.setUrlParams).toHaveBeenCalledWith({
- [confidentialFilterData.filterParam]: filter,
- });
- });
-
- it('clicking a dropdown item calls visitUrl', () => {
- firstDropDownItem().vm.$emit('click');
-
- expect(urlUtils.visitUrl).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/search/dropdown_filter/mock_data.js b/spec/frontend/search/dropdown_filter/mock_data.js
deleted file mode 100644
index f11ab3d9951..00000000000
--- a/spec/frontend/search/dropdown_filter/mock_data.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export const MOCK_QUERY = {
- scope: 'issues',
- state: 'all',
- confidential: null,
-};
diff --git a/spec/frontend/search/group_filter/components/group_filter_spec.js b/spec/frontend/search/group_filter/components/group_filter_spec.js
new file mode 100644
index 00000000000..fd3a4449f41
--- /dev/null
+++ b/spec/frontend/search/group_filter/components/group_filter_spec.js
@@ -0,0 +1,172 @@
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
+import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlSkeletonLoader } from '@gitlab/ui';
+import * as urlUtils from '~/lib/utils/url_utility';
+import GroupFilter from '~/search/group_filter/components/group_filter.vue';
+import { GROUP_QUERY_PARAM, PROJECT_QUERY_PARAM, ANY_GROUP } from '~/search/group_filter/constants';
+import { MOCK_GROUPS, MOCK_GROUP, MOCK_QUERY } from '../../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+jest.mock('~/flash');
+jest.mock('~/lib/utils/url_utility', () => ({
+ visitUrl: jest.fn(),
+ setUrlParams: jest.fn(),
+}));
+
+describe('Global Search Group Filter', () => {
+ let wrapper;
+
+ const actionSpies = {
+ fetchGroups: jest.fn(),
+ };
+
+ const defaultProps = {
+ initialGroup: null,
+ };
+
+ const createComponent = (initialState, props = {}, mountFn = shallowMount) => {
+ const store = new Vuex.Store({
+ state: {
+ query: MOCK_QUERY,
+ ...initialState,
+ },
+ actions: actionSpies,
+ });
+
+ wrapper = mountFn(GroupFilter, {
+ localVue,
+ store,
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findGlDropdown = () => wrapper.find(GlDropdown);
+ const findGlDropdownSearch = () => findGlDropdown().find(GlSearchBoxByType);
+ const findDropdownText = () => findGlDropdown().find('.dropdown-toggle-text');
+ const findDropdownItems = () => findGlDropdown().findAll(GlDropdownItem);
+ const findDropdownItemsText = () => findDropdownItems().wrappers.map(w => w.text());
+ const findAnyDropdownItem = () => findDropdownItems().at(0);
+ const findFirstGroupDropdownItem = () => findDropdownItems().at(1);
+ const findLoader = () => wrapper.find(GlSkeletonLoader);
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders GlDropdown', () => {
+ expect(findGlDropdown().exists()).toBe(true);
+ });
+
+ describe('findGlDropdownSearch', () => {
+ it('renders always', () => {
+ expect(findGlDropdownSearch().exists()).toBe(true);
+ });
+
+ it('has debounce prop', () => {
+ expect(findGlDropdownSearch().attributes('debounce')).toBe('500');
+ });
+
+ describe('onSearch', () => {
+ const groupSearch = 'test search';
+
+ beforeEach(() => {
+ findGlDropdownSearch().vm.$emit('input', groupSearch);
+ });
+
+ it('calls fetchGroups when input event is fired from GlSearchBoxByType', () => {
+ expect(actionSpies.fetchGroups).toHaveBeenCalledWith(expect.any(Object), groupSearch);
+ });
+ });
+ });
+
+ describe('findDropdownItems', () => {
+ describe('when fetchingGroups is false', () => {
+ beforeEach(() => {
+ createComponent({ groups: MOCK_GROUPS });
+ });
+
+ it('does not render loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('renders an instance for each namespace', () => {
+ const groupsIncludingAny = ['Any'].concat(MOCK_GROUPS.map(n => n.full_name));
+ expect(findDropdownItemsText()).toStrictEqual(groupsIncludingAny);
+ });
+ });
+
+ describe('when fetchingGroups is true', () => {
+ beforeEach(() => {
+ createComponent({ fetchingGroups: true, groups: MOCK_GROUPS });
+ });
+
+ it('does render loader', () => {
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('renders only Any in dropdown', () => {
+ expect(findDropdownItemsText()).toStrictEqual(['Any']);
+ });
+ });
+ });
+
+ describe('Dropdown Text', () => {
+ describe('when initialGroup is null', () => {
+ beforeEach(() => {
+ createComponent({}, {}, mount);
+ });
+
+ it('sets dropdown text to Any', () => {
+ expect(findDropdownText().text()).toBe(ANY_GROUP.name);
+ });
+ });
+
+ describe('initialGroup is set', () => {
+ beforeEach(() => {
+ createComponent({}, { initialGroup: MOCK_GROUP }, mount);
+ });
+
+ it('sets dropdown text to group name', () => {
+ expect(findDropdownText().text()).toBe(MOCK_GROUP.name);
+ });
+ });
+ });
+ });
+
+ describe('actions', () => {
+ beforeEach(() => {
+ createComponent({ groups: MOCK_GROUPS });
+ });
+
+ it('clicking "Any" dropdown item calls setUrlParams with group id null, project id null,and visitUrl', () => {
+ findAnyDropdownItem().vm.$emit('click');
+
+ expect(urlUtils.setUrlParams).toHaveBeenCalledWith({
+ [GROUP_QUERY_PARAM]: ANY_GROUP.id,
+ [PROJECT_QUERY_PARAM]: null,
+ });
+ expect(urlUtils.visitUrl).toHaveBeenCalled();
+ });
+
+ it('clicking group dropdown item calls setUrlParams with group id, project id null, and visitUrl', () => {
+ findFirstGroupDropdownItem().vm.$emit('click');
+
+ expect(urlUtils.setUrlParams).toHaveBeenCalledWith({
+ [GROUP_QUERY_PARAM]: MOCK_GROUPS[0].id,
+ [PROJECT_QUERY_PARAM]: null,
+ });
+ expect(urlUtils.visitUrl).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/search/highlight_blob_search_result_spec.js b/spec/frontend/search/highlight_blob_search_result_spec.js
new file mode 100644
index 00000000000..112e6f5124f
--- /dev/null
+++ b/spec/frontend/search/highlight_blob_search_result_spec.js
@@ -0,0 +1,15 @@
+import setHighlightClass from '~/search/highlight_blob_search_result';
+
+const fixture = 'search/blob_search_result.html';
+
+describe('search/highlight_blob_search_result', () => {
+ preloadFixtures(fixture);
+
+ beforeEach(() => loadFixtures(fixture));
+
+ it('highlights lines with search term occurrence', () => {
+ setHighlightClass();
+
+ expect(document.querySelectorAll('.blob-result .hll').length).toBe(4);
+ });
+});
diff --git a/spec/frontend/search/index_spec.js b/spec/frontend/search/index_spec.js
new file mode 100644
index 00000000000..8a86cc4c52a
--- /dev/null
+++ b/spec/frontend/search/index_spec.js
@@ -0,0 +1,47 @@
+import { initSearchApp } from '~/search';
+import createStore from '~/search/store';
+
+jest.mock('~/search/store');
+jest.mock('~/search/sidebar');
+jest.mock('~/search/group_filter');
+
+describe('initSearchApp', () => {
+ let defaultLocation;
+
+ const setUrl = query => {
+ window.location.href = `https://localhost:3000/search${query}`;
+ window.location.search = query;
+ };
+
+ beforeEach(() => {
+ defaultLocation = window.location;
+ Object.defineProperty(window, 'location', {
+ writable: true,
+ value: { href: '', search: '' },
+ });
+ });
+
+ afterEach(() => {
+ window.location = defaultLocation;
+ });
+
+ describe.each`
+ search | decodedSearch
+ ${'test'} | ${'test'}
+ ${'%2520'} | ${'%20'}
+ ${'test%2Bthis%2Bstuff'} | ${'test+this+stuff'}
+ ${'test+this+stuff'} | ${'test this stuff'}
+ ${'test+%2B+this+%2B+stuff'} | ${'test + this + stuff'}
+ ${'test%2B+%2Bthis%2B+%2Bstuff'} | ${'test+ +this+ +stuff'}
+ ${'test+%2520+this+%2520+stuff'} | ${'test %20 this %20 stuff'}
+ `('parameter decoding', ({ search, decodedSearch }) => {
+ beforeEach(() => {
+ setUrl(`?search=${search}`);
+ initSearchApp();
+ });
+
+ it(`decodes ${search} to ${decodedSearch}`, () => {
+ expect(createStore).toHaveBeenCalledWith({ query: { search: decodedSearch } });
+ });
+ });
+});
diff --git a/spec/frontend/search/mock_data.js b/spec/frontend/search/mock_data.js
new file mode 100644
index 00000000000..68fc432881a
--- /dev/null
+++ b/spec/frontend/search/mock_data.js
@@ -0,0 +1,24 @@
+export const MOCK_QUERY = {
+ scope: 'issues',
+ state: 'all',
+ confidential: null,
+};
+
+export const MOCK_GROUP = {
+ name: 'test group',
+ full_name: 'full name test group',
+ id: 'test_1',
+};
+
+export const MOCK_GROUPS = [
+ {
+ name: 'test group',
+ full_name: 'full name test group',
+ id: 'test_1',
+ },
+ {
+ name: 'test group 2',
+ full_name: 'full name test group 2',
+ id: 'test_2',
+ },
+];
diff --git a/spec/frontend/search/sidebar/components/app_spec.js b/spec/frontend/search/sidebar/components/app_spec.js
new file mode 100644
index 00000000000..d2c0081080c
--- /dev/null
+++ b/spec/frontend/search/sidebar/components/app_spec.js
@@ -0,0 +1,103 @@
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlButton, GlLink } from '@gitlab/ui';
+import { MOCK_QUERY } from 'jest/search/mock_data';
+import GlobalSearchSidebar from '~/search/sidebar/components/app.vue';
+import ConfidentialityFilter from '~/search/sidebar/components/confidentiality_filter.vue';
+import StatusFilter from '~/search/sidebar/components/status_filter.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('GlobalSearchSidebar', () => {
+ let wrapper;
+
+ const actionSpies = {
+ applyQuery: jest.fn(),
+ resetQuery: jest.fn(),
+ };
+
+ const createComponent = initialState => {
+ const store = new Vuex.Store({
+ state: {
+ query: MOCK_QUERY,
+ ...initialState,
+ },
+ actions: actionSpies,
+ });
+
+ wrapper = shallowMount(GlobalSearchSidebar, {
+ localVue,
+ store,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findSidebarForm = () => wrapper.find('form');
+ const findStatusFilter = () => wrapper.find(StatusFilter);
+ const findConfidentialityFilter = () => wrapper.find(ConfidentialityFilter);
+ const findApplyButton = () => wrapper.find(GlButton);
+ const findResetLinkButton = () => wrapper.find(GlLink);
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders StatusFilter always', () => {
+ expect(findStatusFilter().exists()).toBe(true);
+ });
+
+ it('renders ConfidentialityFilter always', () => {
+ expect(findConfidentialityFilter().exists()).toBe(true);
+ });
+
+ it('renders ApplyButton always', () => {
+ expect(findApplyButton().exists()).toBe(true);
+ });
+ });
+
+ describe('ResetLinkButton', () => {
+ describe('with no filter selected', () => {
+ beforeEach(() => {
+ createComponent({ query: {} });
+ });
+
+ it('does not render', () => {
+ expect(findResetLinkButton().exists()).toBe(false);
+ });
+ });
+
+ describe('with filter selected', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('does render when a filter selected', () => {
+ expect(findResetLinkButton().exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('actions', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('clicking ApplyButton calls applyQuery', () => {
+ findSidebarForm().trigger('submit');
+
+ expect(actionSpies.applyQuery).toHaveBeenCalled();
+ });
+
+ it('clicking ResetLinkButton calls resetQuery', () => {
+ findResetLinkButton().vm.$emit('click');
+
+ expect(actionSpies.resetQuery).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js b/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
new file mode 100644
index 00000000000..68d20b2480e
--- /dev/null
+++ b/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
@@ -0,0 +1,65 @@
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { MOCK_QUERY } from 'jest/search/mock_data';
+import ConfidentialityFilter from '~/search/sidebar/components/confidentiality_filter.vue';
+import RadioFilter from '~/search/sidebar/components/radio_filter.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('ConfidentialityFilter', () => {
+ let wrapper;
+
+ const actionSpies = {
+ applyQuery: jest.fn(),
+ resetQuery: jest.fn(),
+ };
+
+ const createComponent = initialState => {
+ const store = new Vuex.Store({
+ state: {
+ query: MOCK_QUERY,
+ ...initialState,
+ },
+ actions: actionSpies,
+ });
+
+ wrapper = shallowMount(ConfidentialityFilter, {
+ localVue,
+ store,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findRadioFilter = () => wrapper.find(RadioFilter);
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ describe.each`
+ scope | showFilter
+ ${'issues'} | ${true}
+ ${'merge_requests'} | ${false}
+ ${'projects'} | ${false}
+ ${'milestones'} | ${false}
+ ${'users'} | ${false}
+ ${'notes'} | ${false}
+ ${'wiki_blobs'} | ${false}
+ ${'blobs'} | ${false}
+ `(`dropdown`, ({ scope, showFilter }) => {
+ beforeEach(() => {
+ createComponent({ query: { scope } });
+ });
+
+ it(`does${showFilter ? '' : ' not'} render when scope is ${scope}`, () => {
+ expect(findRadioFilter().exists()).toBe(showFilter);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/search/sidebar/components/radio_filter_spec.js b/spec/frontend/search/sidebar/components/radio_filter_spec.js
new file mode 100644
index 00000000000..31a4a8859ee
--- /dev/null
+++ b/spec/frontend/search/sidebar/components/radio_filter_spec.js
@@ -0,0 +1,111 @@
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
+import { MOCK_QUERY } from 'jest/search/mock_data';
+import RadioFilter from '~/search/sidebar/components/radio_filter.vue';
+import { stateFilterData } from '~/search/sidebar/constants/state_filter_data';
+import { confidentialFilterData } from '~/search/sidebar/constants/confidential_filter_data';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('RadioFilter', () => {
+ let wrapper;
+
+ const actionSpies = {
+ setQuery: jest.fn(),
+ };
+
+ const defaultProps = {
+ filterData: stateFilterData,
+ };
+
+ const createComponent = (initialState, props = {}) => {
+ const store = new Vuex.Store({
+ state: {
+ query: MOCK_QUERY,
+ ...initialState,
+ },
+ actions: actionSpies,
+ });
+
+ wrapper = shallowMount(RadioFilter, {
+ localVue,
+ store,
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findGlRadioButtonGroup = () => wrapper.find(GlFormRadioGroup);
+ const findGlRadioButtons = () => findGlRadioButtonGroup().findAll(GlFormRadio);
+ const findGlRadioButtonsText = () => findGlRadioButtons().wrappers.map(w => w.text());
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders GlRadioButtonGroup always', () => {
+ expect(findGlRadioButtonGroup().exists()).toBe(true);
+ });
+
+ describe('Radio Buttons', () => {
+ describe('Status Filter', () => {
+ it('renders a radio button for each filterOption', () => {
+ expect(findGlRadioButtonsText()).toStrictEqual(
+ stateFilterData.filterByScope[stateFilterData.scopes.ISSUES].map(f => {
+ return f.value === stateFilterData.filters.ANY.value
+ ? `Any ${stateFilterData.header.toLowerCase()}`
+ : f.label;
+ }),
+ );
+ });
+
+ it('clicking a radio button item calls setQuery', () => {
+ const filter = stateFilterData.filters[Object.keys(stateFilterData.filters)[0]].value;
+ findGlRadioButtonGroup().vm.$emit('input', filter);
+
+ expect(actionSpies.setQuery).toHaveBeenCalledWith(expect.any(Object), {
+ key: stateFilterData.filterParam,
+ value: filter,
+ });
+ });
+ });
+
+ describe('Confidentiality Filter', () => {
+ beforeEach(() => {
+ createComponent({}, { filterData: confidentialFilterData });
+ });
+
+ it('renders a radio button for each filterOption', () => {
+ expect(findGlRadioButtonsText()).toStrictEqual(
+ confidentialFilterData.filterByScope[confidentialFilterData.scopes.ISSUES].map(f => {
+ return f.value === confidentialFilterData.filters.ANY.value
+ ? `Any ${confidentialFilterData.header.toLowerCase()}`
+ : f.label;
+ }),
+ );
+ });
+
+ it('clicking a radio button item calls setQuery', () => {
+ const filter =
+ confidentialFilterData.filters[Object.keys(confidentialFilterData.filters)[0]].value;
+ findGlRadioButtonGroup().vm.$emit('input', filter);
+
+ expect(actionSpies.setQuery).toHaveBeenCalledWith(expect.any(Object), {
+ key: confidentialFilterData.filterParam,
+ value: filter,
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/search/sidebar/components/status_filter_spec.js b/spec/frontend/search/sidebar/components/status_filter_spec.js
new file mode 100644
index 00000000000..188d47b38cd
--- /dev/null
+++ b/spec/frontend/search/sidebar/components/status_filter_spec.js
@@ -0,0 +1,65 @@
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { MOCK_QUERY } from 'jest/search/mock_data';
+import StatusFilter from '~/search/sidebar/components/status_filter.vue';
+import RadioFilter from '~/search/sidebar/components/radio_filter.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('StatusFilter', () => {
+ let wrapper;
+
+ const actionSpies = {
+ applyQuery: jest.fn(),
+ resetQuery: jest.fn(),
+ };
+
+ const createComponent = initialState => {
+ const store = new Vuex.Store({
+ state: {
+ query: MOCK_QUERY,
+ ...initialState,
+ },
+ actions: actionSpies,
+ });
+
+ wrapper = shallowMount(StatusFilter, {
+ localVue,
+ store,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findRadioFilter = () => wrapper.find(RadioFilter);
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ describe.each`
+ scope | showFilter
+ ${'issues'} | ${true}
+ ${'merge_requests'} | ${true}
+ ${'projects'} | ${false}
+ ${'milestones'} | ${false}
+ ${'users'} | ${false}
+ ${'notes'} | ${false}
+ ${'wiki_blobs'} | ${false}
+ ${'blobs'} | ${false}
+ `(`dropdown`, ({ scope, showFilter }) => {
+ beforeEach(() => {
+ createComponent({ query: { scope } });
+ });
+
+ it(`does${showFilter ? '' : ' not'} render when scope is ${scope}`, () => {
+ expect(findRadioFilter().exists()).toBe(showFilter);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/search/store/actions_spec.js b/spec/frontend/search/store/actions_spec.js
new file mode 100644
index 00000000000..c8ea6167399
--- /dev/null
+++ b/spec/frontend/search/store/actions_spec.js
@@ -0,0 +1,90 @@
+import MockAdapter from 'axios-mock-adapter';
+import testAction from 'helpers/vuex_action_helper';
+import * as actions from '~/search/store/actions';
+import * as types from '~/search/store/mutation_types';
+import { setUrlParams, visitUrl } from '~/lib/utils/url_utility';
+import state from '~/search/store/state';
+import axios from '~/lib/utils/axios_utils';
+import createFlash from '~/flash';
+import { MOCK_GROUPS } from '../mock_data';
+
+jest.mock('~/flash');
+jest.mock('~/lib/utils/url_utility', () => ({
+ setUrlParams: jest.fn(),
+ visitUrl: jest.fn(),
+ joinPaths: jest.fn(), // For the axios specs
+}));
+
+describe('Global Search Store Actions', () => {
+ let mock;
+
+ const noCallback = () => {};
+ const flashCallback = () => {
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ createFlash.mockClear();
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe.each`
+ action | axiosMock | type | mutationCalls | callback
+ ${actions.fetchGroups} | ${{ method: 'onGet', code: 200, res: MOCK_GROUPS }} | ${'success'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_SUCCESS, payload: MOCK_GROUPS }]} | ${noCallback}
+ ${actions.fetchGroups} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_ERROR }]} | ${flashCallback}
+ `(`axios calls`, ({ action, axiosMock, type, mutationCalls, callback }) => {
+ describe(action.name, () => {
+ describe(`on ${type}`, () => {
+ beforeEach(() => {
+ mock[axiosMock.method]().replyOnce(axiosMock.code, axiosMock.res);
+ });
+ it(`should dispatch the correct mutations`, () => {
+ return testAction(action, null, state, mutationCalls, []).then(() => callback());
+ });
+ });
+ });
+ });
+
+ describe('setQuery', () => {
+ const payload = { key: 'key1', value: 'value1' };
+
+ it('calls the SET_QUERY mutation', done => {
+ testAction(actions.setQuery, payload, state, [{ type: types.SET_QUERY, payload }], [], done);
+ });
+ });
+
+ describe('applyQuery', () => {
+ it('calls visitUrl and setParams with the state.query', () => {
+ testAction(actions.applyQuery, null, state, [], [], () => {
+ expect(setUrlParams).toHaveBeenCalledWith({ ...state.query, page: null });
+ expect(visitUrl).toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('resetQuery', () => {
+ it('calls visitUrl and setParams with empty values', () => {
+ testAction(actions.resetQuery, null, state, [], [], () => {
+ expect(setUrlParams).toHaveBeenCalledWith({
+ ...state.query,
+ page: null,
+ state: null,
+ confidential: null,
+ });
+ expect(visitUrl).toHaveBeenCalled();
+ });
+ });
+ });
+});
+
+describe('setQuery', () => {
+ const payload = { key: 'key1', value: 'value1' };
+
+ it('calls the SET_QUERY mutation', done => {
+ testAction(actions.setQuery, payload, state, [{ type: types.SET_QUERY, payload }], [], done);
+ });
+});
diff --git a/spec/frontend/search/store/mutations_spec.js b/spec/frontend/search/store/mutations_spec.js
new file mode 100644
index 00000000000..28d9646b97e
--- /dev/null
+++ b/spec/frontend/search/store/mutations_spec.js
@@ -0,0 +1,48 @@
+import mutations from '~/search/store/mutations';
+import createState from '~/search/store/state';
+import * as types from '~/search/store/mutation_types';
+import { MOCK_QUERY, MOCK_GROUPS } from '../mock_data';
+
+describe('Global Search Store Mutations', () => {
+ let state;
+
+ beforeEach(() => {
+ state = createState({ query: MOCK_QUERY });
+ });
+
+ describe('REQUEST_GROUPS', () => {
+ it('sets fetchingGroups to true', () => {
+ mutations[types.REQUEST_GROUPS](state);
+
+ expect(state.fetchingGroups).toBe(true);
+ });
+ });
+
+ describe('RECEIVE_GROUPS_SUCCESS', () => {
+ it('sets fetchingGroups to false and sets groups', () => {
+ mutations[types.RECEIVE_GROUPS_SUCCESS](state, MOCK_GROUPS);
+
+ expect(state.fetchingGroups).toBe(false);
+ expect(state.groups).toBe(MOCK_GROUPS);
+ });
+ });
+
+ describe('RECEIVE_GROUPS_ERROR', () => {
+ it('sets fetchingGroups to false and clears groups', () => {
+ mutations[types.RECEIVE_GROUPS_ERROR](state);
+
+ expect(state.fetchingGroups).toBe(false);
+ expect(state.groups).toEqual([]);
+ });
+ });
+
+ describe('SET_QUERY', () => {
+ const payload = { key: 'key1', value: 'value1' };
+
+ it('sets query key to value', () => {
+ mutations[types.SET_QUERY](state, payload);
+
+ expect(state.query[payload.key]).toBe(payload.value);
+ });
+ });
+});
diff --git a/spec/frontend/search_spec.js b/spec/frontend/search_spec.js
index 1573365538c..cbbc2df6c78 100644
--- a/spec/frontend/search_spec.js
+++ b/spec/frontend/search_spec.js
@@ -1,10 +1,10 @@
import $ from 'jquery';
+import setHighlightClass from 'ee_else_ce/search/highlight_blob_search_result';
import Api from '~/api';
import Search from '~/pages/search/show/search';
-import setHighlightClass from '~/pages/search/show/highlight_blob_search_result';
jest.mock('~/api');
-jest.mock('~/pages/search/show/highlight_blob_search_result');
+jest.mock('ee_else_ce/search/highlight_blob_search_result');
describe('Search', () => {
const fixturePath = 'search/show.html';
@@ -36,16 +36,6 @@ describe('Search', () => {
new Search(); // eslint-disable-line no-new
});
- it('requests groups from backend when filtering', () => {
- jest.spyOn(Api, 'groups').mockImplementation(term => {
- expect(term).toBe(searchTerm);
- });
-
- const inputElement = fillDropdownInput('.js-search-group-dropdown');
-
- $(inputElement).trigger('input');
- });
-
it('requests projects from backend when filtering', () => {
jest.spyOn(Api, 'projects').mockImplementation(term => {
expect(term).toBe(searchTerm);
diff --git a/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js b/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
new file mode 100644
index 00000000000..fad23aa05a4
--- /dev/null
+++ b/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
@@ -0,0 +1,257 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlModal, GlFormCheckbox } from '@gitlab/ui';
+import { initEmojiMock } from 'helpers/emoji';
+import Api from '~/api';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import SetStatusModalWrapper, {
+ AVAILABILITY_STATUS,
+} from '~/set_status_modal/set_status_modal_wrapper.vue';
+
+jest.mock('~/api');
+jest.mock('~/flash');
+
+describe('SetStatusModalWrapper', () => {
+ let wrapper;
+ let mockEmoji;
+ const $toast = {
+ show: jest.fn(),
+ };
+
+ const defaultEmoji = 'speech_balloon';
+ const defaultMessage = "They're comin' in too fast!";
+
+ const defaultProps = {
+ currentEmoji: defaultEmoji,
+ currentMessage: defaultMessage,
+ defaultEmoji,
+ canSetUserAvailability: true,
+ };
+
+ const createComponent = (props = {}) => {
+ return shallowMount(SetStatusModalWrapper, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ mocks: {
+ $toast,
+ },
+ });
+ };
+
+ const findModal = () => wrapper.find(GlModal);
+ const findFormField = field => wrapper.find(`[name="user[status][${field}]"]`);
+ const findClearStatusButton = () => wrapper.find('.js-clear-user-status-button');
+ const findNoEmojiPlaceholder = () => wrapper.find('.js-no-emoji-placeholder');
+ const findToggleEmojiButton = () => wrapper.find('.js-toggle-emoji-menu');
+ const findAvailabilityCheckbox = () => wrapper.find(GlFormCheckbox);
+
+ const initModal = ({ mockOnUpdateSuccess = true, mockOnUpdateFailure = true } = {}) => {
+ const modal = findModal();
+ // mock internal emoji methods
+ wrapper.vm.showEmojiMenu = jest.fn();
+ wrapper.vm.hideEmojiMenu = jest.fn();
+ if (mockOnUpdateSuccess) wrapper.vm.onUpdateSuccess = jest.fn();
+ if (mockOnUpdateFailure) wrapper.vm.onUpdateFail = jest.fn();
+
+ modal.vm.$emit('shown');
+ return wrapper.vm.$nextTick();
+ };
+
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent();
+ return initModal();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ mockEmoji.restore();
+ });
+
+ describe('with minimum props', () => {
+ it('sets the hidden status emoji field', () => {
+ const field = findFormField('emoji');
+ expect(field.exists()).toBe(true);
+ expect(field.element.value).toBe(defaultEmoji);
+ });
+
+ it('sets the message field', () => {
+ const field = findFormField('message');
+ expect(field.exists()).toBe(true);
+ expect(field.element.value).toBe(defaultMessage);
+ });
+
+ it('sets the availability field to false', () => {
+ const field = findAvailabilityCheckbox();
+ expect(field.exists()).toBe(true);
+ expect(field.element.checked).toBeUndefined();
+ });
+
+ it('has a clear status button', () => {
+ expect(findClearStatusButton().isVisible()).toBe(true);
+ });
+
+ it('clicking the toggle emoji button displays the emoji list', () => {
+ expect(wrapper.vm.showEmojiMenu).not.toHaveBeenCalled();
+ findToggleEmojiButton().trigger('click');
+ expect(wrapper.vm.showEmojiMenu).toHaveBeenCalled();
+ });
+ });
+
+ describe('with no currentMessage set', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ currentMessage: '' });
+ return initModal();
+ });
+
+ it('does not set the message field', () => {
+ expect(findFormField('message').element.value).toBe('');
+ });
+
+ it('hides the clear status button', () => {
+ expect(findClearStatusButton().isVisible()).toBe(false);
+ });
+
+ it('shows the placeholder emoji', () => {
+ expect(findNoEmojiPlaceholder().isVisible()).toBe(true);
+ });
+ });
+
+ describe('with no currentEmoji set', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ currentEmoji: '' });
+ return initModal();
+ });
+
+ it('does not set the hidden status emoji field', () => {
+ expect(findFormField('emoji').element.value).toBe('');
+ });
+
+ it('hides the placeholder emoji', () => {
+ expect(findNoEmojiPlaceholder().isVisible()).toBe(false);
+ });
+
+ describe('with no currentMessage set', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
+ return initModal();
+ });
+
+ it('shows the placeholder emoji', () => {
+ expect(findNoEmojiPlaceholder().isVisible()).toBe(true);
+ });
+ });
+ });
+
+ describe('update status', () => {
+ describe('succeeds', () => {
+ beforeEach(() => {
+ jest.spyOn(Api, 'postUserStatus').mockResolvedValue();
+ });
+
+ it('clicking "removeStatus" clears the emoji and message fields', async () => {
+ findModal().vm.$emit('cancel');
+ await wrapper.vm.$nextTick();
+
+ expect(findFormField('message').element.value).toBe('');
+ expect(findFormField('emoji').element.value).toBe('');
+ });
+
+ it('clicking "setStatus" submits the user status', async () => {
+ findModal().vm.$emit('ok');
+ await wrapper.vm.$nextTick();
+
+ // set the availability status
+ findAvailabilityCheckbox().vm.$emit('input', true);
+
+ findModal().vm.$emit('ok');
+ await wrapper.vm.$nextTick();
+
+ const commonParams = { emoji: defaultEmoji, message: defaultMessage };
+
+ expect(Api.postUserStatus).toHaveBeenCalledTimes(2);
+ expect(Api.postUserStatus).toHaveBeenNthCalledWith(1, {
+ availability: AVAILABILITY_STATUS.NOT_SET,
+ ...commonParams,
+ });
+ expect(Api.postUserStatus).toHaveBeenNthCalledWith(2, {
+ availability: AVAILABILITY_STATUS.BUSY,
+ ...commonParams,
+ });
+ });
+
+ it('calls the "onUpdateSuccess" handler', async () => {
+ findModal().vm.$emit('ok');
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.onUpdateSuccess).toHaveBeenCalled();
+ });
+ });
+
+ describe('success message', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
+ jest.spyOn(Api, 'postUserStatus').mockResolvedValue();
+ return initModal({ mockOnUpdateSuccess: false });
+ });
+
+ it('displays a toast success message', async () => {
+ findModal().vm.$emit('ok');
+ await wrapper.vm.$nextTick();
+
+ expect($toast.show).toHaveBeenCalledWith('Status updated', {
+ position: 'top-center',
+ type: 'success',
+ });
+ });
+ });
+
+ describe('with errors', () => {
+ beforeEach(() => {
+ jest.spyOn(Api, 'postUserStatus').mockRejectedValue();
+ });
+
+ it('calls the "onUpdateFail" handler', async () => {
+ findModal().vm.$emit('ok');
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.onUpdateFail).toHaveBeenCalled();
+ });
+ });
+
+ describe('error message', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
+ jest.spyOn(Api, 'postUserStatus').mockRejectedValue();
+ return initModal({ mockOnUpdateFailure: false });
+ });
+
+ it('flashes an error message', async () => {
+ findModal().vm.$emit('ok');
+ await wrapper.vm.$nextTick();
+
+ expect(createFlash).toHaveBeenCalledWith(
+ "Sorry, we weren't able to set your status. Please try again later.",
+ );
+ });
+ });
+ });
+
+ describe('with canSetUserAvailability=false', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ canSetUserAvailability: false });
+ return initModal();
+ });
+
+ it('hides the set availability checkbox', () => {
+ expect(findAvailabilityCheckbox().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/set_status_modal/user_availability_status_spec.js b/spec/frontend/set_status_modal/user_availability_status_spec.js
new file mode 100644
index 00000000000..95ca0251ce0
--- /dev/null
+++ b/spec/frontend/set_status_modal/user_availability_status_spec.js
@@ -0,0 +1,31 @@
+import { shallowMount } from '@vue/test-utils';
+import UserAvailabilityStatus from '~/set_status_modal/components/user_availability_status.vue';
+import { AVAILABILITY_STATUS } from '~/set_status_modal/utils';
+
+describe('UserAvailabilityStatus', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ return shallowMount(UserAvailabilityStatus, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('with availability status', () => {
+ it(`set to ${AVAILABILITY_STATUS.BUSY}`, () => {
+ wrapper = createComponent({ availability: AVAILABILITY_STATUS.BUSY });
+ expect(wrapper.text()).toContain('(Busy)');
+ });
+
+ it(`set to ${AVAILABILITY_STATUS.NOT_SET}`, () => {
+ wrapper = createComponent({ availability: AVAILABILITY_STATUS.NOT_SET });
+ expect(wrapper.html()).toBe('');
+ });
+ });
+});
diff --git a/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap b/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap
index 42012841f0b..6640c0844e2 100644
--- a/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap
+++ b/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap
@@ -27,7 +27,7 @@ exports[`SidebarTodo template renders component container element with proper da
</span>
<gl-loading-icon-stub
- color="orange"
+ color="dark"
inline="true"
label="Loading"
size="sm"
diff --git a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
index 5307be0bf58..bcd2c14f2fa 100644
--- a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
+++ b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
@@ -1,277 +1,226 @@
-import Vue from 'vue';
-
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { createMockDirective } from 'helpers/vue_mock_directive';
+import { mount } from '@vue/test-utils';
import TimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue';
describe('Issuable Time Tracker', () => {
- let initialData;
- let vm;
-
- const initTimeTrackingComponent = ({
- timeEstimate,
- timeSpent,
- timeEstimateHumanReadable,
- timeSpentHumanReadable,
- limitToHours,
- }) => {
- setFixtures(`
- <div>
- <div id="mock-container"></div>
- </div>
- `);
-
- initialData = {
- timeEstimate,
- timeSpent,
- humanTimeEstimate: timeEstimateHumanReadable,
- humanTimeSpent: timeSpentHumanReadable,
- limitToHours: Boolean(limitToHours),
- rootPath: '/',
- };
-
- const TimeTrackingComponent = Vue.extend({
- ...TimeTracker,
- components: {
- ...TimeTracker.components,
- transition: {
- // disable animations
- render(h) {
- return h('div', this.$slots.default);
- },
- },
- },
- });
- vm = mountComponent(TimeTrackingComponent, initialData, '#mock-container');
+ let wrapper;
+
+ const findByTestId = testId => wrapper.find(`[data-testid=${testId}]`);
+ const findComparisonMeter = () => findByTestId('compareMeter').attributes('title');
+ const findCollapsedState = () => findByTestId('collapsedState');
+ const findTimeRemainingProgress = () => findByTestId('timeRemainingProgress');
+
+ const defaultProps = {
+ timeEstimate: 10_000, // 2h 46m
+ timeSpent: 5_000, // 1h 23m
+ humanTimeEstimate: '2h 46m',
+ humanTimeSpent: '1h 23m',
+ limitToHours: false,
};
+ const mountComponent = ({ props = {} } = {}) =>
+ mount(TimeTracker, {
+ propsData: { ...defaultProps, ...props },
+ directives: { GlTooltip: createMockDirective() },
+ });
+
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('Initialization', () => {
beforeEach(() => {
- initTimeTrackingComponent({
- timeEstimate: 10000, // 2h 46m
- timeSpent: 5000, // 1h 23m
- timeEstimateHumanReadable: '2h 46m',
- timeSpentHumanReadable: '1h 23m',
- });
+ wrapper = mountComponent();
});
it('should return something defined', () => {
- expect(vm).toBeDefined();
+ expect(wrapper).toBeDefined();
});
- it('should correctly set timeEstimate', done => {
- Vue.nextTick(() => {
- expect(vm.timeEstimate).toBe(initialData.timeEstimate);
- done();
- });
+ it('should correctly render timeEstimate', () => {
+ expect(findByTestId('timeTrackingComparisonPane').html()).toContain(
+ defaultProps.humanTimeEstimate,
+ );
});
- it('should correctly set time_spent', done => {
- Vue.nextTick(() => {
- expect(vm.timeSpent).toBe(initialData.timeSpent);
- done();
- });
+ it('should correctly render time_spent', () => {
+ expect(findByTestId('timeTrackingComparisonPane').html()).toContain(
+ defaultProps.humanTimeSpent,
+ );
});
});
- describe('Content Display', () => {
- describe('Panes', () => {
- describe('Comparison pane', () => {
- beforeEach(() => {
- initTimeTrackingComponent({
- timeEstimate: 100000, // 1d 3h
- timeSpent: 5000, // 1h 23m
- timeEstimateHumanReadable: '1d 3h',
- timeSpentHumanReadable: '1h 23m',
- });
+ describe('Content panes', () => {
+ describe('Collapsed state', () => {
+ it('should render "time-tracking-collapsed-state" by default when "showCollapsed" prop is not specified', () => {
+ wrapper = mountComponent();
+
+ expect(findCollapsedState().exists()).toBe(true);
+ });
+
+ it('should not render "time-tracking-collapsed-state" when "showCollapsed" is false', () => {
+ wrapper = mountComponent({
+ props: {
+ showCollapsed: false,
+ },
});
- it('should show the "Comparison" pane when timeEstimate and time_spent are truthy', done => {
- Vue.nextTick(() => {
- expect(vm.showComparisonState).toBe(true);
- const $comparisonPane = vm.$el.querySelector('.time-tracking-comparison-pane');
+ expect(findCollapsedState().exists()).toBe(false);
+ });
+ });
- expect($comparisonPane).toBeVisible();
- done();
- });
+ describe('Comparison pane', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ props: {
+ timeEstimate: 100_000, // 1d 3h
+ timeSpent: 5_000, // 1h 23m
+ humanTimeEstimate: '1d 3h',
+ humanTimeSpent: '1h 23m',
+ },
});
+ });
- it('should show full times when the sidebar is collapsed', done => {
- Vue.nextTick(() => {
- const timeTrackingText = vm.$el.querySelector('.time-tracking-collapsed-summary span')
- .textContent;
+ it('should show the "Comparison" pane when timeEstimate and time_spent are truthy', () => {
+ const pane = findByTestId('timeTrackingComparisonPane');
+ expect(pane.exists()).toBe(true);
+ expect(pane.isVisible()).toBe(true);
+ });
- expect(timeTrackingText.trim()).toBe('1h 23m / 1d 3h');
- done();
- });
+ it('should show full times when the sidebar is collapsed', () => {
+ expect(findCollapsedState().text()).toBe('1h 23m / 1d 3h');
+ });
+
+ describe('Remaining meter', () => {
+ it('should display the remaining meter with the correct width', () => {
+ expect(findTimeRemainingProgress().attributes('value')).toBe('5');
});
- describe('Remaining meter', () => {
- it('should display the remaining meter with the correct width', done => {
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.time-tracking-comparison-pane .progress[value="5"]'),
- ).not.toBeNull();
- done();
- });
- });
+ it('should display the remaining meter with the correct background color when within estimate', () => {
+ expect(findTimeRemainingProgress().attributes('variant')).toBe('primary');
+ });
- it('should display the remaining meter with the correct background color when within estimate', done => {
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.time-tracking-comparison-pane .progress[variant="primary"]'),
- ).not.toBeNull();
- done();
- });
+ it('should display the remaining meter with the correct background color when over estimate', () => {
+ wrapper = mountComponent({
+ props: {
+ timeEstimate: 10_000, // 2h 46m
+ timeSpent: 20_000_000, // 231 days
+ },
});
- it('should display the remaining meter with the correct background color when over estimate', done => {
- vm.timeEstimate = 10000; // 2h 46m
- vm.timeSpent = 20000000; // 231 days
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.time-tracking-comparison-pane .progress[variant="danger"]'),
- ).not.toBeNull();
- done();
- });
- });
+ expect(findTimeRemainingProgress().attributes('variant')).toBe('danger');
});
});
+ });
- describe('Comparison pane when limitToHours is true', () => {
- beforeEach(() => {
- initTimeTrackingComponent({
- timeEstimate: 100000, // 1d 3h
- timeSpent: 5000, // 1h 23m
- timeEstimateHumanReadable: '',
- timeSpentHumanReadable: '',
+ describe('Comparison pane when limitToHours is true', () => {
+ beforeEach(async () => {
+ wrapper = mountComponent({
+ props: {
+ timeEstimate: 100_000, // 1d 3h
limitToHours: true,
- });
+ },
});
+ });
- it('should show the correct tooltip text', done => {
- Vue.nextTick(() => {
- expect(vm.showComparisonState).toBe(true);
- const $title = vm.$el.querySelector('.time-tracking-content .compare-meter').title;
+ it('should show the correct tooltip text', async () => {
+ expect(findByTestId('timeTrackingComparisonPane').exists()).toBe(true);
+ await wrapper.vm.$nextTick();
- expect($title).toBe('Time remaining: 26h 23m');
- done();
- });
- });
+ expect(findComparisonMeter()).toBe('Time remaining: 26h 23m');
});
+ });
- describe('Estimate only pane', () => {
- beforeEach(() => {
- initTimeTrackingComponent({
- timeEstimate: 10000, // 2h 46m
+ describe('Estimate only pane', () => {
+ beforeEach(async () => {
+ wrapper = mountComponent({
+ props: {
+ timeEstimate: 10_000, // 2h 46m
timeSpent: 0,
timeEstimateHumanReadable: '2h 46m',
timeSpentHumanReadable: '',
- });
+ },
});
+ await wrapper.vm.$nextTick();
+ });
- it('should display the human readable version of time estimated', done => {
- Vue.nextTick(() => {
- const estimateText = vm.$el.querySelector('.time-tracking-estimate-only-pane')
- .textContent;
- const correctText = 'Estimated: 2h 46m';
-
- expect(estimateText.trim()).toBe(correctText);
- done();
- });
- });
+ it('should display the human readable version of time estimated', () => {
+ const estimateText = findByTestId('estimateOnlyPane').text();
+ expect(estimateText.trim()).toBe('Estimated: 2h 46m');
});
+ });
- describe('Spent only pane', () => {
- beforeEach(() => {
- initTimeTrackingComponent({
+ describe('Spent only pane', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ props: {
timeEstimate: 0,
- timeSpent: 5000, // 1h 23m
+ timeSpent: 5_000, // 1h 23m
timeEstimateHumanReadable: '2h 46m',
timeSpentHumanReadable: '1h 23m',
- });
+ },
});
+ });
- it('should display the human readable version of time spent', done => {
- Vue.nextTick(() => {
- const spentText = vm.$el.querySelector('.time-tracking-spend-only-pane').textContent;
- const correctText = 'Spent: 1h 23m';
-
- expect(spentText).toBe(correctText);
- done();
- });
- });
+ it('should display the human readable version of time spent', () => {
+ const spentText = findByTestId('spentOnlyPane').text();
+ expect(spentText.trim()).toBe('Spent: 1h 23m');
});
+ });
- describe('No time tracking pane', () => {
- beforeEach(() => {
- initTimeTrackingComponent({
+ describe('No time tracking pane', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ props: {
timeEstimate: 0,
timeSpent: 0,
timeEstimateHumanReadable: '',
timeSpentHumanReadable: '',
- });
+ },
});
+ });
- it('should only show the "No time tracking" pane when both timeEstimate and time_spent are falsey', done => {
- Vue.nextTick(() => {
- const $noTrackingPane = vm.$el.querySelector('.time-tracking-no-tracking-pane');
- const noTrackingText = $noTrackingPane.textContent;
- const correctText = 'No estimate or time spent';
-
- expect(vm.showNoTimeTrackingState).toBe(true);
- expect($noTrackingPane).toBeVisible();
- expect(noTrackingText.trim()).toBe(correctText);
- done();
- });
- });
+ it('should only show the "No time tracking" pane when both timeEstimate and time_spent are falsey', () => {
+ const pane = findByTestId('noTrackingPane');
+ const correctText = 'No estimate or time spent';
+ expect(pane.exists()).toBe(true);
+ expect(pane.text().trim()).toBe(correctText);
});
+ });
+
+ describe('Help pane', () => {
+ const findHelpButton = () => findByTestId('helpButton');
+ const findCloseHelpButton = () => findByTestId('closeHelpButton');
- describe('Help pane', () => {
- const helpButton = () => vm.$el.querySelector('.help-button');
- const closeHelpButton = () => vm.$el.querySelector('.close-help-button');
- const helpPane = () => vm.$el.querySelector('.time-tracking-help-state');
+ beforeEach(async () => {
+ wrapper = mountComponent({ props: { timeEstimate: 0, timeSpent: 0 } });
+ await wrapper.vm.$nextTick();
+ });
- beforeEach(() => {
- initTimeTrackingComponent({ timeEstimate: 0, timeSpent: 0 });
+ it('should not show the "Help" pane by default', () => {
+ expect(findByTestId('helpPane').exists()).toBe(false);
+ });
- return vm.$nextTick();
- });
+ it('should show the "Help" pane when help button is clicked', async () => {
+ findHelpButton().trigger('click');
- it('should not show the "Help" pane by default', () => {
- expect(vm.showHelpState).toBe(false);
- expect(helpPane()).toBeNull();
- });
+ await wrapper.vm.$nextTick();
- it('should show the "Help" pane when help button is clicked', () => {
- helpButton().click();
+ expect(findByTestId('helpPane').exists()).toBe(true);
+ });
- return vm.$nextTick().then(() => {
- expect(vm.showHelpState).toBe(true);
+ it('should not show the "Help" pane when help button is clicked and then closed', async () => {
+ findHelpButton().trigger('click');
+ await wrapper.vm.$nextTick();
- // let animations run
- jest.advanceTimersByTime(500);
+ expect(findByTestId('helpPane').classes('help-state-toggle-enter')).toBe(true);
+ expect(findByTestId('helpPane').classes('help-state-toggle-leave')).toBe(false);
- expect(helpPane()).toBeVisible();
- });
- });
+ findCloseHelpButton().trigger('click');
+ await wrapper.vm.$nextTick();
- it('should not show the "Help" pane when help button is clicked and then closed', done => {
- helpButton().click();
-
- Vue.nextTick()
- .then(() => closeHelpButton().click())
- .then(() => Vue.nextTick())
- .then(() => {
- expect(vm.showHelpState).toBe(false);
- expect(helpPane()).toBeNull();
- })
- .then(done)
- .catch(done.fail);
- });
+ expect(findByTestId('helpPane').classes('help-state-toggle-leave')).toBe(true);
+ expect(findByTestId('helpPane').classes('help-state-toggle-enter')).toBe(false);
});
});
});
diff --git a/spec/frontend/sidebar/issuable_assignees_spec.js b/spec/frontend/sidebar/issuable_assignees_spec.js
index aa930bd4198..076616de040 100644
--- a/spec/frontend/sidebar/issuable_assignees_spec.js
+++ b/spec/frontend/sidebar/issuable_assignees_spec.js
@@ -13,7 +13,6 @@ describe('IssuableAssignees', () => {
propsData: { ...props },
});
};
- const findLabel = () => wrapper.find('[data-testid="assigneeLabel"');
const findUncollapsedAssigneeList = () => wrapper.find(UncollapsedAssigneeList);
const findEmptyAssignee = () => wrapper.find('[data-testid="none"]');
@@ -30,10 +29,6 @@ describe('IssuableAssignees', () => {
it('renders "None"', () => {
expect(findEmptyAssignee().text()).toBe('None');
});
-
- it('renders "0 assignees"', () => {
- expect(findLabel().text()).toBe('0 Assignees');
- });
});
describe('when assignees are present', () => {
@@ -42,18 +37,5 @@ describe('IssuableAssignees', () => {
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/sidebar_labels_spec.js b/spec/frontend/sidebar/sidebar_labels_spec.js
index 7a687ffa761..36d1e129b6a 100644
--- a/spec/frontend/sidebar/sidebar_labels_spec.js
+++ b/spec/frontend/sidebar/sidebar_labels_spec.js
@@ -1,16 +1,18 @@
import { shallowMount } from '@vue/test-utils';
-import AxiosMockAdapter from 'axios-mock-adapter';
import {
mockLabels,
mockRegularLabel,
} from 'jest/vue_shared/components/sidebar/labels_select_vue/mock_data';
-import axios from '~/lib/utils/axios_utils';
+import updateIssueLabelsMutation from '~/boards/queries/issue_set_labels.mutation.graphql';
+import { MutationOperationMode } from '~/graphql_shared/utils';
+import { IssuableType } from '~/issue_show/constants';
import SidebarLabels from '~/sidebar/components/labels/sidebar_labels.vue';
+import updateMergeRequestLabelsMutation from '~/sidebar/queries/update_merge_request_labels.mutation.graphql';
+import { toLabelGid } from '~/sidebar/utils';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
describe('sidebar labels', () => {
- let axiosMock;
let wrapper;
const defaultProps = {
@@ -23,29 +25,52 @@ describe('sidebar labels', () => {
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 $apollo = {
+ mutate: jest.fn().mockResolvedValue(),
+ };
+
+ const userUpdatedLabels = [
+ {
+ ...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,
+ },
+ ];
+
const findLabelsSelect = () => wrapper.find(LabelsSelect);
- const mountComponent = () => {
+ const mountComponent = (props = {}) => {
wrapper = shallowMount(SidebarLabels, {
provide: {
...defaultProps,
+ ...props,
+ },
+ mocks: {
+ $apollo,
},
});
};
- beforeEach(() => {
- axiosMock = new AxiosMockAdapter(axios);
- });
-
afterEach(() => {
wrapper.destroy();
wrapper = null;
- axiosMock.restore();
});
describe('LabelsSelect props', () => {
@@ -72,64 +97,94 @@ describe('sidebar labels', () => {
});
});
- describe('when labels are updated', () => {
+ describe('when type is issue', () => {
beforeEach(() => {
- mountComponent();
+ mountComponent({ issuableType: IssuableType.Issue });
});
- 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, 29, 40],
- },
- };
-
- expect(axiosMock.history.put[0].data).toEqual(JSON.stringify(expected));
+ describe('when labels are updated', () => {
+ it('invokes a mutation', () => {
+ findLabelsSelect().vm.$emit('updateSelectedLabels', userUpdatedLabels);
+
+ const expected = {
+ mutation: updateIssueLabelsMutation,
+ variables: {
+ input: {
+ addLabelIds: [40],
+ iid: defaultProps.iid,
+ projectPath: defaultProps.projectPath,
+ removeLabelIds: [26, 55],
+ },
+ },
+ };
+
+ expect($apollo.mutate).toHaveBeenCalledWith(expected);
+ });
+ });
+
+ describe('when label `x` is clicked', () => {
+ it('invokes a mutation', () => {
+ findLabelsSelect().vm.$emit('onLabelRemove', 27);
+
+ const expected = {
+ mutation: updateIssueLabelsMutation,
+ variables: {
+ input: {
+ iid: defaultProps.iid,
+ projectPath: defaultProps.projectPath,
+ removeLabelIds: [27],
+ },
+ },
+ };
+
+ expect($apollo.mutate).toHaveBeenCalledWith(expected);
+ });
});
});
- describe('when label `x` is clicked', () => {
+ describe('when type is merge_request', () => {
beforeEach(() => {
- mountComponent();
+ mountComponent({ issuableType: IssuableType.MergeRequest });
});
- it('makes an API call to update labels', async () => {
- findLabelsSelect().vm.$emit('onLabelRemove', 27);
-
- await axios.waitForAll();
-
- const expected = {
- [defaultProps.issuableType]: {
- label_ids: [26, 28, 29],
- },
- };
+ describe('when labels are updated', () => {
+ it('invokes a mutation', () => {
+ findLabelsSelect().vm.$emit('updateSelectedLabels', userUpdatedLabels);
+
+ const expected = {
+ mutation: updateMergeRequestLabelsMutation,
+ variables: {
+ input: {
+ iid: defaultProps.iid,
+ labelIds: [toLabelGid(27), toLabelGid(28), toLabelGid(29), toLabelGid(40)],
+ operationMode: MutationOperationMode.Replace,
+ projectPath: defaultProps.projectPath,
+ },
+ },
+ };
+
+ expect($apollo.mutate).toHaveBeenCalledWith(expected);
+ });
+ });
- expect(axiosMock.history.put[0].data).toEqual(JSON.stringify(expected));
+ describe('when label `x` is clicked', () => {
+ it('invokes a mutation', () => {
+ findLabelsSelect().vm.$emit('onLabelRemove', 27);
+
+ const expected = {
+ mutation: updateMergeRequestLabelsMutation,
+ variables: {
+ input: {
+ iid: defaultProps.iid,
+ labelIds: [toLabelGid(27)],
+ operationMode: MutationOperationMode.Remove,
+ projectPath: defaultProps.projectPath,
+ },
+ },
+ };
+
+ expect($apollo.mutate).toHaveBeenCalledWith(expected);
+ });
});
});
});
diff --git a/spec/frontend/sidebar/subscriptions_spec.js b/spec/frontend/sidebar/subscriptions_spec.js
index dddb9c2bba9..428441656b3 100644
--- a/spec/frontend/sidebar/subscriptions_spec.js
+++ b/spec/frontend/sidebar/subscriptions_spec.js
@@ -94,7 +94,7 @@ describe('Subscriptions', () => {
it('sets the correct display text', () => {
expect(wrapper.find('.issuable-header-text').text()).toContain(subscribeDisabledDescription);
- expect(wrapper.find({ ref: 'tooltip' }).attributes('data-original-title')).toBe(
+ expect(wrapper.find({ ref: 'tooltip' }).attributes('title')).toBe(
subscribeDisabledDescription,
);
});
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 93684ed48ee..cef5f8cc528 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
@@ -52,9 +52,13 @@ exports[`Snippet Description Edit component rendering matches the snapshot 1`] =
<div
class="div-dropzone-hover"
>
- <i
- class="fa fa-paperclip div-dropzone-icon"
- />
+ <svg
+ class="div-dropzone-icon s24"
+ >
+ <use
+ xlink:href="undefined#paperclip"
+ />
+ </svg>
</div>
</div>
diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js
index c1fad8cebe6..3521733ee5e 100644
--- a/spec/frontend/snippets/components/edit_spec.js
+++ b/spec/frontend/snippets/components/edit_spec.js
@@ -1,7 +1,9 @@
-import { ApolloMutation } from 'vue-apollo';
+import VueApollo, { ApolloMutation } from 'vue-apollo';
import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
+import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import GetSnippetQuery from 'shared_queries/snippet/snippet.query.graphql';
import { deprecatedCreateFlash as Flash } from '~/flash';
import * as urlUtils from '~/lib/utils/url_utility';
import SnippetEditApp from '~/snippets/components/edit.vue';
@@ -10,7 +12,11 @@ import SnippetVisibilityEdit from '~/snippets/components/snippet_visibility_edit
import SnippetBlobActionsEdit from '~/snippets/components/snippet_blob_actions_edit.vue';
import TitleField from '~/vue_shared/components/form/title.vue';
import FormFooterActions from '~/vue_shared/components/form/form_footer_actions.vue';
-import { SNIPPET_VISIBILITY_PRIVATE } from '~/snippets/constants';
+import {
+ SNIPPET_VISIBILITY_PRIVATE,
+ SNIPPET_VISIBILITY_INTERNAL,
+ SNIPPET_VISIBILITY_PUBLIC,
+} from '~/snippets/constants';
import UpdateSnippetMutation from '~/snippets/mutations/updateSnippet.mutation.graphql';
import CreateSnippetMutation from '~/snippets/mutations/createSnippet.mutation.graphql';
import { testEntries } from '../test_utils';
@@ -47,8 +53,12 @@ const createTestSnippet = () => ({
describe('Snippet Edit app', () => {
let wrapper;
+ let fakeApollo;
const relativeUrlRoot = '/foo/';
const originalRelativeUrlRoot = gon.relative_url_root;
+ const GetSnippetQuerySpy = jest.fn().mockResolvedValue({
+ data: { snippets: { nodes: [createTestSnippet()] } },
+ });
const mutationTypes = {
RESOLVE: jest.fn().mockResolvedValue({
@@ -78,12 +88,10 @@ describe('Snippet Edit app', () => {
props = {},
loading = false,
mutationRes = mutationTypes.RESOLVE,
+ selectedLevel = SNIPPET_VISIBILITY_PRIVATE,
+ withApollo = false,
} = {}) {
- if (wrapper) {
- throw new Error('wrapper already exists');
- }
-
- wrapper = shallowMount(SnippetEditApp, {
+ let componentData = {
mocks: {
$apollo: {
queries: {
@@ -92,23 +100,35 @@ describe('Snippet Edit app', () => {
mutate: mutationRes,
},
},
+ };
+
+ if (withApollo) {
+ const localVue = createLocalVue();
+ localVue.use(VueApollo);
+
+ const requestHandlers = [[GetSnippetQuery, GetSnippetQuerySpy]];
+ fakeApollo = createMockApollo(requestHandlers);
+ componentData = {
+ localVue,
+ apolloProvider: fakeApollo,
+ };
+ }
+
+ wrapper = shallowMount(SnippetEditApp, {
+ ...componentData,
stubs: {
ApolloMutation,
FormFooterActions,
},
+ provide: {
+ selectedLevel,
+ },
propsData: {
snippetGid: 'gid://gitlab/PersonalSnippet/42',
markdownPreviewPath: 'http://preview.foo.bar',
markdownDocsPath: 'http://docs.foo.bar',
...props,
},
- data() {
- return {
- snippet: {
- visibilityLevel: SNIPPET_VISIBILITY_PRIVATE,
- },
- };
- },
});
}
@@ -152,16 +172,13 @@ describe('Snippet Edit app', () => {
if (nodes.length) {
wrapper.setData({
snippet: nodes[0],
+ newSnippet: false,
+ });
+ } else {
+ wrapper.setData({
+ newSnippet: true,
});
}
-
- wrapper.vm.onSnippetFetch({
- data: {
- snippets: {
- nodes,
- },
- },
- });
};
describe('rendering', () => {
@@ -228,6 +245,28 @@ describe('Snippet Edit app', () => {
});
describe('functionality', () => {
+ it('does not fetch snippet when create a new snippet', async () => {
+ createComponent({ props: { snippetGid: '' }, withApollo: true });
+
+ jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+
+ expect(GetSnippetQuerySpy).not.toHaveBeenCalled();
+ });
+
+ describe('default visibility', () => {
+ it.each([SNIPPET_VISIBILITY_PRIVATE, SNIPPET_VISIBILITY_INTERNAL, SNIPPET_VISIBILITY_PUBLIC])(
+ 'marks %s visibility by default',
+ async visibility => {
+ createComponent({
+ props: { snippetGid: '' },
+ selectedLevel: visibility,
+ });
+ expect(wrapper.vm.snippet.visibilityLevel).toEqual(visibility);
+ },
+ );
+ });
+
describe('form submission handling', () => {
it.each`
snippetArg | projectPath | uploadedFiles | input | mutation
diff --git a/spec/frontend/snippets/components/snippet_visibility_edit_spec.js b/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
index 3919e4d7993..3151090f388 100644
--- a/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
@@ -1,7 +1,6 @@
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,
@@ -15,36 +14,25 @@ describe('Snippet Visibility Edit component', () => {
let wrapper;
const defaultHelpLink = '/foo/bar';
const defaultVisibilityLevel = 'private';
- const defaultVisibility = defaultSnippetVisibilityLevels([0, 10, 20]);
function createComponent({
propsData = {},
- visibilityLevels = defaultVisibility,
+ visibilityLevels = [0, 10, 20],
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,
- };
+ provide: {
+ visibilityLevels,
+ multipleLevelsRestricted,
},
});
}
@@ -108,7 +96,6 @@ describe('Snippet Visibility Edit component', () => {
it.each`
levels | resultOptions
- ${undefined} | ${[]}
${''} | ${[]}
${[]} | ${[]}
${[0]} | ${[RESULTING_OPTIONS[0]]}
@@ -117,7 +104,7 @@ describe('Snippet Visibility Edit component', () => {
${[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 });
+ createComponent({ visibilityLevels: levels, deep: true });
expect(findRadiosData()).toEqual(resultOptions);
});
@@ -132,7 +119,7 @@ describe('Snippet Visibility Edit component', () => {
'renders correct information about restricted visibility levels for $levels',
({ levels, levelsRestricted, resultText }) => {
createComponent({
- visibilityLevels: defaultSnippetVisibilityLevels(levels),
+ visibilityLevels: levels,
multipleLevelsRestricted: levelsRestricted,
});
expect(findRestrictedInfo().text()).toBe(resultText);
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 7e90b53dd07..247aff57c1a 100644
--- a/spec/frontend/static_site_editor/components/edit_area_spec.js
+++ b/spec/frontend/static_site_editor/components/edit_area_spec.js
@@ -15,6 +15,11 @@ import {
sourceContentHeaderObjYAML as headerSettings,
sourceContentBody as body,
returnUrl,
+ mounts,
+ project,
+ branch,
+ baseUrl,
+ imageRoot,
} from '../mock_data';
jest.mock('~/static_site_editor/services/formatter', () => jest.fn(str => `${str} format-pass`));
@@ -31,6 +36,11 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
title,
content,
returnUrl,
+ mounts,
+ project,
+ branch,
+ baseUrl,
+ imageRoot,
savingChanges,
...propsData,
},
diff --git a/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js b/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js
index 191f91be076..b887570e947 100644
--- a/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js
+++ b/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js
@@ -1,15 +1,12 @@
import { shallowMount } from '@vue/test-utils';
-import { useLocalStorageSpy } from 'helpers/local_storage_helper';
-import { GlFormInput, GlFormTextarea } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlFormInput, GlFormTextarea } from '@gitlab/ui';
import EditMetaControls from '~/static_site_editor/components/edit_meta_controls.vue';
-import { mergeRequestMeta } from '../mock_data';
+import { mergeRequestMeta, mergeRequestTemplates } from '../mock_data';
describe('~/static_site_editor/components/edit_meta_controls.vue', () => {
- useLocalStorageSpy();
-
let wrapper;
let mockSelect;
let mockGlFormInputTitleInstance;
@@ -22,6 +19,8 @@ describe('~/static_site_editor/components/edit_meta_controls.vue', () => {
propsData: {
title,
description,
+ templates: mergeRequestTemplates,
+ currentTemplate: null,
...propsData,
},
});
@@ -34,6 +33,10 @@ describe('~/static_site_editor/components/edit_meta_controls.vue', () => {
};
const findGlFormInputTitle = () => wrapper.find(GlFormInput);
+ const findGlDropdownDescriptionTemplate = () => wrapper.find(GlDropdown);
+ const findAllDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findDropdownItemByIndex = index => findAllDropdownItems().at(index);
+
const findGlFormTextAreaDescription = () => wrapper.find(GlFormTextarea);
beforeEach(() => {
@@ -52,6 +55,10 @@ describe('~/static_site_editor/components/edit_meta_controls.vue', () => {
expect(findGlFormInputTitle().exists()).toBe(true);
});
+ it('renders the description template dropdown', () => {
+ expect(findGlDropdownDescriptionTemplate().exists()).toBe(true);
+ });
+
it('renders the description input', () => {
expect(findGlFormTextAreaDescription().exists()).toBe(true);
});
@@ -68,6 +75,11 @@ describe('~/static_site_editor/components/edit_meta_controls.vue', () => {
expect(mockGlFormInputTitleInstance.$el.select).toHaveBeenCalled();
});
+ it('renders a GlDropdownItem per template plus one (for the starting none option)', () => {
+ expect(findDropdownItemByIndex(0).text()).toBe('None');
+ expect(findAllDropdownItems().length).toBe(mergeRequestTemplates.length + 1);
+ });
+
describe('when inputs change', () => {
const storageKey = 'sse-merge-request-meta-local-storage-editable';
@@ -86,14 +98,18 @@ describe('~/static_site_editor/components/edit_meta_controls.vue', () => {
expect(wrapper.emitted('updateSettings')[0][0]).toMatchObject(newSettings);
});
+ });
- it('should remember the input changes', () => {
- findGlFormInputTitle().vm.$emit('input', newTitle);
- findGlFormTextAreaDescription().vm.$emit('input', newDescription);
-
- const newSettings = { title: newTitle, description: newDescription };
-
- expect(localStorage.setItem).toHaveBeenCalledWith(storageKey, JSON.stringify(newSettings));
+ describe('when templates change', () => {
+ it.each`
+ index | value
+ ${0} | ${null}
+ ${1} | ${mergeRequestTemplates[0]}
+ ${2} | ${mergeRequestTemplates[1]}
+ `('emits a change template event when $index is clicked', ({ index, value }) => {
+ findDropdownItemByIndex(index).vm.$emit('click');
+
+ expect(wrapper.emitted('changeTemplate')[0][0]).toBe(value);
});
});
});
diff --git a/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js b/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js
index 7a5685033f3..c7d0abee05c 100644
--- a/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js
+++ b/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js
@@ -1,48 +1,87 @@
import { shallowMount } from '@vue/test-utils';
-
import { GlModal } from '@gitlab/ui';
-
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import EditMetaModal from '~/static_site_editor/components/edit_meta_modal.vue';
import EditMetaControls from '~/static_site_editor/components/edit_meta_controls.vue';
-
-import { sourcePath, mergeRequestMeta } from '../mock_data';
+import { MR_META_LOCAL_STORAGE_KEY } from '~/static_site_editor/constants';
+import {
+ sourcePath,
+ mergeRequestMeta,
+ mergeRequestTemplates,
+ project as namespaceProject,
+} from '../mock_data';
describe('~/static_site_editor/components/edit_meta_modal.vue', () => {
+ useLocalStorageSpy();
+
let wrapper;
- let resetCachedEditable;
- let mockEditMetaControlsInstance;
+ let mockAxios;
const { title, description } = mergeRequestMeta;
+ const [namespace, project] = namespaceProject.split('/');
- const buildWrapper = (propsData = {}) => {
+ const buildWrapper = (propsData = {}, data = {}) => {
wrapper = shallowMount(EditMetaModal, {
propsData: {
sourcePath,
+ namespace,
+ project,
...propsData,
},
+ data: () => data,
});
};
- const buildMocks = () => {
- resetCachedEditable = jest.fn();
- mockEditMetaControlsInstance = { resetCachedEditable };
- wrapper.vm.$refs.editMetaControls = mockEditMetaControlsInstance;
+ const buildMockAxios = () => {
+ mockAxios = new MockAdapter(axios);
+ const templatesMergeRequestsPath = `templates/merge_request`;
+ mockAxios
+ .onGet(`${namespace}/${project}/${templatesMergeRequestsPath}`)
+ .reply(200, mergeRequestTemplates);
+ };
+
+ const buildMockRefs = () => {
+ wrapper.vm.$refs.editMetaControls = { resetCachedEditable: jest.fn() };
};
const findGlModal = () => wrapper.find(GlModal);
const findEditMetaControls = () => wrapper.find(EditMetaControls);
+ const findLocalStorageSync = () => wrapper.find(LocalStorageSync);
beforeEach(() => {
+ localStorage.setItem(MR_META_LOCAL_STORAGE_KEY);
+
+ buildMockAxios();
buildWrapper();
- buildMocks();
+ buildMockRefs();
return wrapper.vm.$nextTick();
});
afterEach(() => {
+ mockAxios.restore();
+
wrapper.destroy();
wrapper = null;
});
+ it('initializes initial merge request meta with local storage data', async () => {
+ const localStorageMeta = {
+ title: 'stored title',
+ description: 'stored description',
+ templates: null,
+ currentTemplate: null,
+ };
+
+ findLocalStorageSync().vm.$emit('input', localStorageMeta);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findEditMetaControls().props()).toEqual(localStorageMeta);
+ });
+
it('renders the modal', () => {
expect(findGlModal().exists()).toBe(true);
});
@@ -63,18 +102,70 @@ describe('~/static_site_editor/components/edit_meta_modal.vue', () => {
expect(findEditMetaControls().props('description')).toBe(description);
});
- it('emits the primary event with mergeRequestMeta', () => {
- findGlModal().vm.$emit('primary', mergeRequestMeta);
- expect(wrapper.emitted('primary')).toEqual([[mergeRequestMeta]]);
+ it('forwards the templates prop', () => {
+ expect(findEditMetaControls().props('templates')).toBe(null);
+ });
+
+ it('forwards the currentTemplate prop', () => {
+ expect(findEditMetaControls().props('currentTemplate')).toBe(null);
+ });
+
+ describe('when save button is clicked', () => {
+ beforeEach(() => {
+ findGlModal().vm.$emit('primary', mergeRequestMeta);
+ });
+
+ it('removes merge request meta from local storage', () => {
+ expect(findLocalStorageSync().props().clear).toBe(true);
+ });
+
+ it('emits the primary event with mergeRequestMeta', () => {
+ expect(wrapper.emitted('primary')).toEqual([[mergeRequestMeta]]);
+ });
});
- it('calls resetCachedEditable on EditMetaControls when primary emits', () => {
- findGlModal().vm.$emit('primary', mergeRequestMeta);
- expect(mockEditMetaControlsInstance.resetCachedEditable).toHaveBeenCalled();
+ describe('when templates exist', () => {
+ const template1 = mergeRequestTemplates[0];
+
+ beforeEach(() => {
+ buildWrapper({}, { templates: mergeRequestTemplates, currentTemplate: null });
+ });
+
+ it('sets the currentTemplate on the changeTemplate event', async () => {
+ findEditMetaControls().vm.$emit('changeTemplate', template1);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findEditMetaControls().props().currentTemplate).toBe(template1);
+
+ findEditMetaControls().vm.$emit('changeTemplate', null);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findEditMetaControls().props().currentTemplate).toBe(null);
+ });
+
+ it('updates the description on the changeTemplate event', async () => {
+ findEditMetaControls().vm.$emit('changeTemplate', template1);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findEditMetaControls().props().description).toEqual(template1.content);
+ });
});
it('emits the hide event', () => {
findGlModal().vm.$emit('hide');
expect(wrapper.emitted('hide')).toEqual([[]]);
});
+
+ it('stores merge request meta changes in local storage when changes happen', async () => {
+ const newMeta = { title: 'new title', description: 'new description' };
+
+ findEditMetaControls().vm.$emit('updateSettings', newMeta);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findLocalStorageSync().props('value')).toEqual(newMeta);
+ });
});
diff --git a/spec/frontend/static_site_editor/mock_data.js b/spec/frontend/static_site_editor/mock_data.js
index 0b08e290227..8bc65c6ce31 100644
--- a/spec/frontend/static_site_editor/mock_data.js
+++ b/spec/frontend/static_site_editor/mock_data.js
@@ -27,6 +27,7 @@ export const sourceContentTitle = 'Handbook';
export const username = 'gitlabuser';
export const projectId = '123456';
+export const project = 'user1/project1';
export const returnUrl = 'https://www.gitlab.com';
export const sourcePath = 'foobar.md.html';
export const mergeRequestMeta = {
@@ -47,6 +48,10 @@ export const savedContentMeta = {
url: 'foobar/-/merge_requests/123',
},
};
+export const mergeRequestTemplates = [
+ { key: 'Template1', name: 'Template 1', content: 'This is template 1!' },
+ { key: 'Template2', name: 'Template 2', content: 'This is template 2!' },
+];
export const submitChangesError = 'Could not save changes';
export const commitBranchResponse = {
@@ -67,3 +72,20 @@ export const images = new Map([
['path/to/image1.png', 'image1-content'],
['path/to/image2.png', 'image2-content'],
]);
+
+export const mounts = [
+ {
+ source: 'default/source/',
+ target: '',
+ },
+ {
+ source: 'source/with/target',
+ target: 'target',
+ },
+];
+
+export const branch = 'master';
+
+export const baseUrl = '/user1/project1/-/sse/master%2Ftest.md';
+
+export const imageRoot = 'source/images/';
diff --git a/spec/frontend/static_site_editor/pages/home_spec.js b/spec/frontend/static_site_editor/pages/home_spec.js
index 2c69e884005..d0b72ad0cf0 100644
--- a/spec/frontend/static_site_editor/pages/home_spec.js
+++ b/spec/frontend/static_site_editor/pages/home_spec.js
@@ -12,7 +12,7 @@ import { SUCCESS_ROUTE } from '~/static_site_editor/router/constants';
import { TRACKING_ACTION_INITIALIZE_EDITOR } from '~/static_site_editor/constants';
import {
- projectId as project,
+ project,
returnUrl,
sourceContentYAML as content,
sourceContentTitle as title,
@@ -23,6 +23,10 @@ import {
submitChangesError,
trackingCategory,
images,
+ mounts,
+ branch,
+ baseUrl,
+ imageRoot,
} from '../mock_data';
const localVue = createLocalVue();
@@ -41,6 +45,10 @@ describe('static_site_editor/pages/home', () => {
project,
username,
sourcePath,
+ mounts,
+ branch,
+ baseUrl,
+ imageUploadPath: imageRoot,
};
const hasSubmittedChangesMutationPayload = {
data: {
@@ -119,6 +127,7 @@ describe('static_site_editor/pages/home', () => {
it('provides source content, returnUrl, and isSavingChanges to the edit area', () => {
expect(findEditArea().props()).toMatchObject({
title,
+ mounts,
content,
returnUrl,
savingChanges: false,
diff --git a/spec/frontend/static_site_editor/services/front_matterify_spec.js b/spec/frontend/static_site_editor/services/front_matterify_spec.js
index dbaedc30849..866897f21ef 100644
--- a/spec/frontend/static_site_editor/services/front_matterify_spec.js
+++ b/spec/frontend/static_site_editor/services/front_matterify_spec.js
@@ -11,6 +11,7 @@ describe('static_site_editor/services/front_matterify', () => {
const frontMatterifiedContent = {
source: content,
matter: yamlFrontMatterObj,
+ hasMatter: true,
spacing,
content: body,
delimiter: '---',
@@ -19,6 +20,7 @@ describe('static_site_editor/services/front_matterify', () => {
const frontMatterifiedBody = {
source: body,
matter: null,
+ hasMatter: false,
spacing: null,
content: body,
delimiter: null,
@@ -33,6 +35,12 @@ describe('static_site_editor/services/front_matterify', () => {
`('returns $target from $frontMatterified', ({ frontMatterified, target }) => {
expect(frontMatterified).toEqual(target);
});
+
+ it('should throw when matter is invalid', () => {
+ const invalidContent = `---\nkey: val\nkeyNoVal\n---\n${body}`;
+
+ expect(() => frontMatterify(invalidContent)).toThrow();
+ });
});
describe('stringify', () => {
diff --git a/spec/frontend/static_site_editor/services/renderers/render_image_spec.js b/spec/frontend/static_site_editor/services/renderers/render_image_spec.js
new file mode 100644
index 00000000000..e9e40835982
--- /dev/null
+++ b/spec/frontend/static_site_editor/services/renderers/render_image_spec.js
@@ -0,0 +1,96 @@
+import imageRenderer from '~/static_site_editor/services/renderers/render_image';
+import { mounts, project, branch, baseUrl } from '../../mock_data';
+
+describe('rich_content_editor/renderers/render_image', () => {
+ let renderer;
+ let imageRepository;
+
+ beforeEach(() => {
+ renderer = imageRenderer.build(mounts, project, branch, baseUrl, imageRepository);
+ imageRepository = { get: () => null };
+ });
+
+ describe('build', () => {
+ it('builds a renderer object containing `canRender` and `render` functions', () => {
+ expect(renderer).toHaveProperty('canRender', expect.any(Function));
+ expect(renderer).toHaveProperty('render', expect.any(Function));
+ });
+ });
+
+ describe('canRender', () => {
+ it.each`
+ input | result
+ ${{ type: 'image' }} | ${true}
+ ${{ type: 'text' }} | ${false}
+ ${{ type: 'htmlBlock' }} | ${false}
+ `('returns $result when input is $input', ({ input, result }) => {
+ expect(renderer.canRender(input)).toBe(result);
+ });
+ });
+
+ describe('render', () => {
+ let skipChildren;
+ let context;
+ let node;
+
+ beforeEach(() => {
+ skipChildren = jest.fn();
+ context = { skipChildren };
+ node = {
+ firstChild: {
+ type: 'img',
+ literal: 'Some Image',
+ },
+ };
+ });
+
+ it.each`
+ destination | isAbsolute | src
+ ${'http://test.host/absolute/path/to/image.png'} | ${true} | ${'http://test.host/absolute/path/to/image.png'}
+ ${'/relative/path/to/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/master/default/source/relative/path/to/image.png'}
+ ${'/target/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/master/source/with/target/image.png'}
+ ${'relative/to/current/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/master/relative/to/current/image.png'}
+ ${'./relative/to/current/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/master/./relative/to/current/image.png'}
+ ${'../relative/to/current/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/master/../relative/to/current/image.png'}
+ `('returns an image with the correct attributes', ({ destination, isAbsolute, src }) => {
+ node.destination = destination;
+
+ const result = renderer.render(node, context);
+
+ expect(result).toEqual({
+ type: 'openTag',
+ tagName: 'img',
+ selfClose: true,
+ attributes: {
+ 'data-original-src': !isAbsolute ? destination : '',
+ src,
+ alt: 'Some Image',
+ },
+ });
+
+ expect(skipChildren).toHaveBeenCalled();
+ });
+
+ it('renders an image if a cached image is found in the repository, use the base64 content as the source', () => {
+ const imageContent = 'some-content';
+ const originalSrc = 'path/to/image.png';
+
+ imageRepository.get = () => imageContent;
+ renderer = imageRenderer.build(mounts, project, branch, baseUrl, imageRepository);
+ node.destination = originalSrc;
+
+ const result = renderer.render(node, context);
+
+ expect(result).toEqual({
+ type: 'openTag',
+ tagName: 'img',
+ selfClose: true,
+ attributes: {
+ 'data-original-src': originalSrc,
+ src: `data:image;base64,${imageContent}`,
+ alt: 'Some Image',
+ },
+ });
+ });
+ });
+});
diff --git a/spec/frontend/terraform/components/empty_state_spec.js b/spec/frontend/terraform/components/empty_state_spec.js
new file mode 100644
index 00000000000..c86160e18f3
--- /dev/null
+++ b/spec/frontend/terraform/components/empty_state_spec.js
@@ -0,0 +1,26 @@
+import { GlEmptyState, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import EmptyState from '~/terraform/components/empty_state.vue';
+
+describe('EmptyStateComponent', () => {
+ let wrapper;
+
+ const propsData = {
+ image: '/image/path',
+ };
+
+ beforeEach(() => {
+ wrapper = shallowMount(EmptyState, { propsData, stubs: { GlEmptyState, GlSprintf } });
+ return wrapper.vm.$nextTick();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should render content', () => {
+ expect(wrapper.find(GlEmptyState).exists()).toBe(true);
+ expect(wrapper.text()).toContain('Get started with Terraform');
+ });
+});
diff --git a/spec/frontend/terraform/components/states_table_spec.js b/spec/frontend/terraform/components/states_table_spec.js
new file mode 100644
index 00000000000..7a8cb19971e
--- /dev/null
+++ b/spec/frontend/terraform/components/states_table_spec.js
@@ -0,0 +1,102 @@
+import { GlIcon, GlTooltip } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { useFakeDate } from 'helpers/fake_date';
+import StatesTable from '~/terraform/components/states_table.vue';
+
+describe('StatesTable', () => {
+ let wrapper;
+ useFakeDate([2020, 10, 15]);
+
+ const propsData = {
+ states: [
+ {
+ name: 'state-1',
+ lockedAt: '2020-10-13T00:00:00Z',
+ lockedByUser: {
+ name: 'user-1',
+ },
+ updatedAt: '2020-10-13T00:00:00Z',
+ latestVersion: null,
+ },
+ {
+ name: 'state-2',
+ lockedAt: null,
+ lockedByUser: null,
+ updatedAt: '2020-10-10T00:00:00Z',
+ latestVersion: null,
+ },
+ {
+ name: 'state-3',
+ lockedAt: '2020-10-10T00:00:00Z',
+ lockedByUser: {
+ name: 'user-2',
+ },
+ updatedAt: '2020-10-10T00:00:00Z',
+ latestVersion: {
+ updatedAt: '2020-10-11T00:00:00Z',
+ createdByUser: {
+ name: 'user-3',
+ },
+ },
+ },
+ {
+ name: 'state-4',
+ lockedAt: '2020-10-10T00:00:00Z',
+ lockedByUser: null,
+ updatedAt: '2020-10-10T00:00:00Z',
+ latestVersion: {
+ updatedAt: '2020-10-09T00:00:00Z',
+ createdByUser: null,
+ },
+ },
+ ],
+ };
+
+ beforeEach(() => {
+ wrapper = mount(StatesTable, { propsData });
+ return wrapper.vm.$nextTick();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it.each`
+ name | toolTipText | locked | lineNumber
+ ${'state-1'} | ${'Locked by user-1 2 days ago'} | ${true} | ${0}
+ ${'state-2'} | ${null} | ${false} | ${1}
+ ${'state-3'} | ${'Locked by user-2 5 days ago'} | ${true} | ${2}
+ ${'state-4'} | ${'Locked by Unknown User 5 days ago'} | ${true} | ${3}
+ `(
+ 'displays the name and locked information "$name" for line "$lineNumber"',
+ ({ name, toolTipText, locked, lineNumber }) => {
+ const states = wrapper.findAll('[data-testid="terraform-states-table-name"]');
+
+ const state = states.at(lineNumber);
+ const toolTip = state.find(GlTooltip);
+
+ expect(state.text()).toContain(name);
+ expect(state.find(GlIcon).exists()).toBe(locked);
+ expect(toolTip.exists()).toBe(locked);
+
+ if (locked) {
+ expect(toolTip.text()).toMatchInterpolatedText(toolTipText);
+ }
+ },
+ );
+
+ it.each`
+ updateTime | lineNumber
+ ${'updated 2 days ago'} | ${0}
+ ${'updated 5 days ago'} | ${1}
+ ${'user-3 updated 4 days ago'} | ${2}
+ ${'updated 6 days ago'} | ${3}
+ `('displays the time "$updateTime" for line "$lineNumber"', ({ updateTime, lineNumber }) => {
+ const states = wrapper.findAll('[data-testid="terraform-states-table-updated"]');
+
+ const state = states.at(lineNumber);
+
+ expect(state.text()).toMatchInterpolatedText(updateTime);
+ });
+});
diff --git a/spec/frontend/terraform/components/terraform_list_spec.js b/spec/frontend/terraform/components/terraform_list_spec.js
new file mode 100644
index 00000000000..b31afecc816
--- /dev/null
+++ b/spec/frontend/terraform/components/terraform_list_spec.js
@@ -0,0 +1,172 @@
+import { GlAlert, GlBadge, GlKeysetPagination, GlLoadingIcon, GlTab } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import VueApollo from 'vue-apollo';
+import EmptyState from '~/terraform/components/empty_state.vue';
+import StatesTable from '~/terraform/components/states_table.vue';
+import TerraformList from '~/terraform/components/terraform_list.vue';
+import getStatesQuery from '~/terraform/graphql/queries/get_states.query.graphql';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('TerraformList', () => {
+ let wrapper;
+
+ const propsData = {
+ emptyStateImage: '/path/to/image',
+ projectPath: 'path/to/project',
+ };
+
+ const createWrapper = ({ terraformStates, queryResponse = null }) => {
+ const apolloQueryResponse = {
+ data: {
+ project: {
+ terraformStates,
+ },
+ },
+ };
+
+ const statsQueryResponse = queryResponse || jest.fn().mockResolvedValue(apolloQueryResponse);
+ const apolloProvider = createMockApollo([[getStatesQuery, statsQueryResponse]]);
+
+ wrapper = shallowMount(TerraformList, {
+ localVue,
+ apolloProvider,
+ propsData,
+ });
+ };
+
+ const findBadge = () => wrapper.find(GlBadge);
+ const findEmptyState = () => wrapper.find(EmptyState);
+ const findPaginationButtons = () => wrapper.find(GlKeysetPagination);
+ const findStatesTable = () => wrapper.find(StatesTable);
+ const findTab = () => wrapper.find(GlTab);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when the terraform query has succeeded', () => {
+ describe('when there is a list of terraform states', () => {
+ const states = [
+ {
+ id: 'gid://gitlab/Terraform::State/1',
+ name: 'state-1',
+ lockedAt: null,
+ updatedAt: null,
+ lockedByUser: null,
+ latestVersion: null,
+ },
+ {
+ id: 'gid://gitlab/Terraform::State/2',
+ name: 'state-2',
+ lockedAt: null,
+ updatedAt: null,
+ lockedByUser: null,
+ latestVersion: null,
+ },
+ ];
+
+ beforeEach(() => {
+ createWrapper({
+ terraformStates: {
+ nodes: states,
+ count: states.length,
+ pageInfo: {
+ hasNextPage: true,
+ hasPreviousPage: false,
+ startCursor: 'prev',
+ endCursor: 'next',
+ },
+ },
+ });
+
+ return wrapper.vm.$nextTick();
+ });
+
+ it('displays a states tab and count', () => {
+ expect(findTab().text()).toContain('States');
+ expect(findBadge().text()).toBe('2');
+ });
+
+ it('renders the states table and pagination buttons', () => {
+ expect(findStatesTable().exists()).toBe(true);
+ expect(findPaginationButtons().exists()).toBe(true);
+ });
+
+ describe('when list has no additional pages', () => {
+ beforeEach(() => {
+ createWrapper({
+ terraformStates: {
+ nodes: states,
+ count: states.length,
+ pageInfo: {
+ hasNextPage: false,
+ hasPreviousPage: false,
+ startCursor: '',
+ endCursor: '',
+ },
+ },
+ });
+
+ return wrapper.vm.$nextTick();
+ });
+
+ it('renders the states table without pagination buttons', () => {
+ expect(findStatesTable().exists()).toBe(true);
+ expect(findPaginationButtons().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('when the list of terraform states is empty', () => {
+ beforeEach(() => {
+ createWrapper({
+ terraformStates: {
+ nodes: [],
+ count: 0,
+ pageInfo: null,
+ },
+ });
+
+ return wrapper.vm.$nextTick();
+ });
+
+ it('displays a states tab with no count', () => {
+ expect(findTab().text()).toContain('States');
+ expect(findBadge().exists()).toBe(false);
+ });
+
+ it('renders the empty state', () => {
+ expect(findEmptyState().exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('when the terraform query has errored', () => {
+ beforeEach(() => {
+ createWrapper({ terraformStates: null, queryResponse: jest.fn().mockRejectedValue() });
+
+ return wrapper.vm.$nextTick();
+ });
+
+ it('displays an alert message', () => {
+ expect(wrapper.find(GlAlert).exists()).toBe(true);
+ });
+ });
+
+ describe('when the terraform query is loading', () => {
+ beforeEach(() => {
+ createWrapper({
+ terraformStates: null,
+ queryResponse: jest.fn().mockReturnValue(new Promise(() => {})),
+ });
+ });
+
+ it('displays a loading icon', () => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/tooltips/components/tooltips_spec.js b/spec/frontend/tooltips/components/tooltips_spec.js
index 0edc5248629..50848ca2978 100644
--- a/spec/frontend/tooltips/components/tooltips_spec.js
+++ b/spec/frontend/tooltips/components/tooltips_spec.js
@@ -80,6 +80,14 @@ describe('tooltips/components/tooltips.vue', () => {
expect(wrapper.find(GlTooltip).html()).toContain(target.getAttribute('title'));
});
+ it('sets the configuration values passed in the config object', async () => {
+ const config = { show: true };
+ target = createTooltipTarget();
+ wrapper.vm.addTooltips([target], config);
+ await wrapper.vm.$nextTick();
+ expect(wrapper.find(GlTooltip).props()).toMatchObject(config);
+ });
+
it.each`
attribute | value | prop
${'data-placement'} | ${'bottom'} | ${'placement'}
diff --git a/spec/frontend/tooltips/index_spec.js b/spec/frontend/tooltips/index_spec.js
index cc72adee57d..511003fdb8f 100644
--- a/spec/frontend/tooltips/index_spec.js
+++ b/spec/frontend/tooltips/index_spec.js
@@ -1,5 +1,15 @@
import jQuery from 'jquery';
-import { initTooltips, dispose, destroy, hide, show, enable, disable, fixTitle } from '~/tooltips';
+import {
+ add,
+ initTooltips,
+ dispose,
+ destroy,
+ hide,
+ show,
+ enable,
+ disable,
+ fixTitle,
+} from '~/tooltips';
describe('tooltips/index.js', () => {
let tooltipsApp;
@@ -67,6 +77,20 @@ describe('tooltips/index.js', () => {
});
});
+ describe('add', () => {
+ it('adds a GlTooltip for the specified elements', async () => {
+ const target = createTooltipTarget();
+
+ buildTooltipsApp();
+ add([target], { title: 'custom title' });
+
+ await tooltipsApp.$nextTick();
+
+ expect(document.querySelector('.gl-tooltip')).not.toBe(null);
+ expect(document.querySelector('.gl-tooltip').innerHTML).toContain('custom title');
+ });
+ });
+
describe('dispose', () => {
it('removes tooltips that target the elements specified', async () => {
const target = createTooltipTarget();
@@ -136,12 +160,13 @@ describe('tooltips/index.js', () => {
${disable} | ${'disable'} | ${'disable'}
${hide} | ${'hide'} | ${'hide'}
${show} | ${'show'} | ${'show'}
+ ${add} | ${'init'} | ${{ title: 'the title' }}
`('delegates $methodName to bootstrap tooltip API', ({ method, bootstrapParams }) => {
const elements = jQuery(createTooltipTarget());
jest.spyOn(jQuery.fn, 'tooltip');
- method(elements);
+ method(elements, bootstrapParams);
expect(elements.tooltip).toHaveBeenCalledWith(bootstrapParams);
});
diff --git a/spec/frontend/tracking_spec.js b/spec/frontend/tracking_spec.js
index 8c2bef60e74..d4b97532cdd 100644
--- a/spec/frontend/tracking_spec.js
+++ b/spec/frontend/tracking_spec.js
@@ -31,6 +31,7 @@ describe('Tracking', () => {
contexts: { webPage: true, performanceTiming: true },
formTracking: false,
linkClickTracking: false,
+ pageUnloadTimer: 10,
});
});
});
diff --git a/spec/frontend/vue_mr_widget/components/extensions/index_spec.js b/spec/frontend/vue_mr_widget/components/extensions/index_spec.js
new file mode 100644
index 00000000000..8f6fe3cd37a
--- /dev/null
+++ b/spec/frontend/vue_mr_widget/components/extensions/index_spec.js
@@ -0,0 +1,31 @@
+import { registerExtension, extensions } from '~/vue_merge_request_widget/components/extensions';
+import ExtensionBase from '~/vue_merge_request_widget/components/extensions/base.vue';
+
+describe('MR widget extension registering', () => {
+ it('registers a extension', () => {
+ registerExtension({
+ name: 'Test',
+ props: ['helloWorld'],
+ computed: {
+ test() {},
+ },
+ methods: {
+ test() {},
+ },
+ });
+
+ expect(extensions[0]).toEqual(
+ expect.objectContaining({
+ extends: ExtensionBase,
+ name: 'Test',
+ props: ['helloWorld'],
+ computed: {
+ test: expect.any(Function),
+ },
+ methods: {
+ test: expect.any(Function),
+ },
+ }),
+ );
+ });
+});
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 015f8bbac51..266c906ba60 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
@@ -1,13 +1,7 @@
import Vue from 'vue';
-import Mousetrap from 'mousetrap';
import mountComponent from 'helpers/vue_mount_component_helper';
import headerComponent from '~/vue_merge_request_widget/components/mr_widget_header.vue';
-jest.mock('mousetrap', () => ({
- bind: jest.fn(),
- unbind: jest.fn(),
-}));
-
describe('MRWidgetHeader', () => {
let vm;
let Component;
@@ -136,35 +130,6 @@ describe('MRWidgetHeader', () => {
it('renders target branch', () => {
expect(vm.$el.querySelector('.js-target-branch').textContent.trim()).toEqual('master');
});
-
- describe('keyboard shortcuts', () => {
- it('binds a keyboard shortcut handler to the "b" key', () => {
- expect(Mousetrap.bind).toHaveBeenCalledWith('b', expect.any(Function));
- });
-
- it('triggers a click on the "copy to clipboard" button when the handler is executed', () => {
- const testClickHandler = jest.fn();
- vm.$refs.copyBranchNameButton.$el.addEventListener('click', testClickHandler);
-
- // Get a reference to the function that was assigned to the "b" shortcut key.
- const shortcutHandler = Mousetrap.bind.mock.calls[0][1];
-
- expect(testClickHandler).not.toHaveBeenCalled();
-
- // Simulate Mousetrap calling the function.
- shortcutHandler();
-
- expect(testClickHandler).toHaveBeenCalledTimes(1);
- });
-
- it('unbinds the keyboard shortcut when the component is destroyed', () => {
- expect(Mousetrap.unbind).not.toHaveBeenCalled();
-
- vm.$destroy();
-
- expect(Mousetrap.unbind).toHaveBeenCalledWith('b');
- });
- });
});
describe('with an open merge request', () => {
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js
index 5c7e6a87c16..56832f82b05 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlDeprecatedDropdownItem } from '@gitlab/ui';
+import { GlDropdownItem } from '@gitlab/ui';
import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue';
const commits = [
@@ -39,7 +39,7 @@ describe('Commits message dropdown component', () => {
wrapper.destroy();
});
- const findDropdownElements = () => wrapper.findAll(GlDeprecatedDropdownItem);
+ const findDropdownElements = () => wrapper.findAll(GlDropdownItem);
const findFirstDropdownElement = () => findDropdownElements().at(0);
it('should have 3 elements in dropdown list', () => {
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
index 6ccf1e1f56b..907906ebe98 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
@@ -84,7 +84,7 @@ describe('Wip', () => {
it('should have correct elements', () => {
expect(el.classList.contains('mr-widget-body')).toBeTruthy();
- expect(el.innerText).toContain('This merge request is still a work in progress.');
+ expect(el.innerText).toContain('This merge request is still a draft.');
expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy();
expect(el.querySelector('button').innerText).toContain('Merge');
expect(el.querySelector('.js-remove-wip').innerText.replace(/\s\s+/g, ' ')).toContain(
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 25c967996e3..d6f85dcfcc7 100644
--- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
@@ -1,7 +1,6 @@
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import mountComponent from 'helpers/vue_mount_component_helper';
-import { withGonExperiment } from 'helpers/experimentation_helper';
import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
import mrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
@@ -850,7 +849,7 @@ describe('mrWidgetOptions', () => {
});
});
- describe('suggestPipeline Experiment', () => {
+ describe('suggestPipeline feature flag', () => {
beforeEach(() => {
mock.onAny().reply(200);
@@ -859,10 +858,10 @@ describe('mrWidgetOptions', () => {
jest.spyOn(console, 'warn').mockImplementation();
});
- describe('given experiment is enabled', () => {
- withGonExperiment('suggestPipeline');
-
+ describe('given feature flag is enabled', () => {
beforeEach(() => {
+ gon.features = { suggestPipeline: true };
+
createComponent();
vm.mr.hasCI = false;
@@ -893,10 +892,10 @@ describe('mrWidgetOptions', () => {
});
});
- describe('given suggestPipeline experiment is not enabled', () => {
- withGonExperiment('suggestPipeline', false);
-
+ describe('given feature flag is not enabled', () => {
beforeEach(() => {
+ gon.features = { suggestPipeline: false };
+
createComponent();
vm.mr.hasCI = false;
diff --git a/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap
index 82503e5a025..04ae2a0f34d 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap
@@ -6,10 +6,8 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
>
<button
class="btn award-control"
- data-boundary="viewport"
- data-original-title="Ada, Leonardo, and Marie"
data-testid="award-button"
- title=""
+ title="Ada, Leonardo, and Marie"
type="button"
>
<span
@@ -32,10 +30,8 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</button>
<button
class="btn award-control active"
- data-boundary="viewport"
- data-original-title="You, Ada, and Marie"
data-testid="award-button"
- title=""
+ title="You, Ada, and Marie"
type="button"
>
<span
@@ -58,10 +54,8 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</button>
<button
class="btn award-control"
- data-boundary="viewport"
- data-original-title="Ada and Jane"
data-testid="award-button"
- title=""
+ title="Ada and Jane"
type="button"
>
<span
@@ -84,10 +78,8 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</button>
<button
class="btn award-control active"
- data-boundary="viewport"
- data-original-title="You, Ada, Jane, and Leonardo"
data-testid="award-button"
- title=""
+ title="You, Ada, Jane, and Leonardo"
type="button"
>
<span
@@ -110,10 +102,8 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</button>
<button
class="btn award-control active"
- data-boundary="viewport"
- data-original-title="You"
data-testid="award-button"
- title=""
+ title="You"
type="button"
>
<span
@@ -136,10 +126,8 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</button>
<button
class="btn award-control"
- data-boundary="viewport"
- data-original-title="Marie"
data-testid="award-button"
- title=""
+ title="Marie"
type="button"
>
<span
@@ -162,10 +150,8 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</button>
<button
class="btn award-control active"
- data-boundary="viewport"
- data-original-title="You"
data-testid="award-button"
- title=""
+ title="You"
type="button"
>
<span
@@ -193,9 +179,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button
aria-label="Add reaction"
class="award-control btn js-add-award js-test-add-button-class"
- data-boundary="viewport"
- data-original-title="Add reaction"
- title=""
+ title="Add reaction"
type="button"
>
<span
diff --git a/spec/frontend/vue_shared/components/__snapshots__/file_row_header_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/file_row_header_spec.js.snap
index 5ab159a5a84..ca9d4488870 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/file_row_header_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/file_row_header_spec.js.snap
@@ -5,11 +5,11 @@ exports[`File row header component adds multiple ellipsises after 40 characters
class="file-row-header bg-white sticky-top p-2 js-file-row-header"
title="app/assets/javascripts/merge_requests/widget/diffs/notes"
>
- <span
+ <gl-truncate-stub
class="bold"
- >
- app/assets/javascripts/…/…/diffs/notes
- </span>
+ position="middle"
+ text="app/assets/javascripts/merge_requests/widget/diffs/notes"
+ />
</div>
`;
@@ -18,11 +18,11 @@ exports[`File row header component renders file path 1`] = `
class="file-row-header bg-white sticky-top p-2 js-file-row-header"
title="app/assets"
>
- <span
+ <gl-truncate-stub
class="bold"
- >
- app/assets
- </span>
+ position="middle"
+ text="app/assets"
+ />
</div>
`;
@@ -31,10 +31,10 @@ exports[`File row header component trucates path after 40 characters 1`] = `
class="file-row-header bg-white sticky-top p-2 js-file-row-header"
title="app/assets/javascripts/merge_requests"
>
- <span
+ <gl-truncate-stub
class="bold"
- >
- app/assets/javascripts/merge_requests
- </span>
+ position="middle"
+ text="app/assets/javascripts/merge_requests"
+ />
</div>
`;
diff --git a/spec/frontend/vue_shared/components/__snapshots__/integration_help_text_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/integration_help_text_spec.js.snap
new file mode 100644
index 00000000000..df0fcf5da1c
--- /dev/null
+++ b/spec/frontend/vue_shared/components/__snapshots__/integration_help_text_spec.js.snap
@@ -0,0 +1,27 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`IntegrationHelpText component should not render the link when start and end is not provided 1`] = `
+<span>
+ Click nowhere!
+</span>
+`;
+
+exports[`IntegrationHelpText component should render the help text 1`] = `
+<span>
+ Click
+ <gl-link-stub
+ href="http://bar.com"
+ target="_blank"
+ >
+
+ Bar
+
+ <gl-icon-stub
+ class="gl-vertical-align-middle"
+ name="external-link"
+ size="12"
+ />
+ </gl-link-stub>
+ !
+</span>
+`;
diff --git a/spec/frontend/vue_shared/components/alert_details_table_spec.js b/spec/frontend/vue_shared/components/alert_details_table_spec.js
index dff307e92c2..ef7815f9e9e 100644
--- a/spec/frontend/vue_shared/components/alert_details_table_spec.js
+++ b/spec/frontend/vue_shared/components/alert_details_table_spec.js
@@ -23,14 +23,10 @@ const environmentPath = '/fake/path';
describe('AlertDetails', () => {
let environmentData = { name: environmentName, path: environmentPath };
- let glFeatures = { exposeEnvironmentPathInAlertDetails: false };
let wrapper;
function mountComponent(propsData = {}) {
wrapper = mount(AlertDetailsTable, {
- provide: {
- glFeatures,
- },
propsData: {
alert: {
...mockAlert,
@@ -97,34 +93,19 @@ describe('AlertDetails', () => {
expect(findTableField(fields, 'Severity').exists()).toBe(true);
expect(findTableField(fields, 'Status').exists()).toBe(true);
expect(findTableField(fields, 'Hosts').exists()).toBe(true);
- expect(findTableField(fields, 'Environment').exists()).toBe(false);
+ expect(findTableField(fields, 'Environment').exists()).toBe(true);
});
- it('should not show disallowed and flaggedAllowed alert fields', () => {
+ it('should not show disallowed alert fields', () => {
const fields = findTableKeys();
expect(findTableField(fields, 'Typename').exists()).toBe(false);
expect(findTableField(fields, 'Todos').exists()).toBe(false);
expect(findTableField(fields, 'Notes').exists()).toBe(false);
expect(findTableField(fields, 'Assignees').exists()).toBe(false);
- expect(findTableField(fields, 'Environment').exists()).toBe(false);
- });
- });
-
- describe('when exposeEnvironmentPathInAlertDetails is enabled', () => {
- beforeEach(() => {
- glFeatures = { exposeEnvironmentPathInAlertDetails: true };
- mountComponent();
- });
-
- it('should show flaggedAllowed alert fields', () => {
- const fields = findTableKeys();
-
- expect(findTableField(fields, 'Environment').exists()).toBe(true);
});
it('should display only the name for the environment', () => {
- expect(findTableFieldValueByKey('Iid').text()).toBe('1527542');
expect(findTableFieldValueByKey('Environment').text()).toBe(environmentName);
});
diff --git a/spec/frontend/vue_shared/components/awards_list_spec.js b/spec/frontend/vue_shared/components/awards_list_spec.js
index 0abb72ace2e..63fc8a5749d 100644
--- a/spec/frontend/vue_shared/components/awards_list_spec.js
+++ b/spec/frontend/vue_shared/components/awards_list_spec.js
@@ -62,7 +62,7 @@ describe('vue_shared/components/awards_list', () => {
findAwardButtons().wrappers.map(x => {
return {
classes: x.classes(),
- title: x.attributes('data-original-title'),
+ title: x.attributes('title'),
html: x.find('[data-testid="award-html"]').element.innerHTML,
count: Number(x.find('.js-counter').text()),
};
diff --git a/spec/frontend/vue_shared/components/blob_viewers/__snapshots__/simple_viewer_spec.js.snap b/spec/frontend/vue_shared/components/blob_viewers/__snapshots__/simple_viewer_spec.js.snap
index 4909d2d4226..023895099b1 100644
--- a/spec/frontend/vue_shared/components/blob_viewers/__snapshots__/simple_viewer_spec.js.snap
+++ b/spec/frontend/vue_shared/components/blob_viewers/__snapshots__/simple_viewer_spec.js.snap
@@ -59,7 +59,7 @@ exports[`Blob Simple Viewer component rendering matches the snapshot 1`] = `
class="code highlight"
>
<code
- id="blob-code-content"
+ data-blob-hash="foo-bar"
>
<span
id="LC1"
diff --git a/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js b/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js
index 79195aa1350..8434fdaccde 100644
--- a/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js
@@ -5,9 +5,13 @@ import { HIGHLIGHT_CLASS_NAME } from '~/vue_shared/components/blob_viewers/const
describe('Blob Simple Viewer component', () => {
let wrapper;
const contentMock = `<span id="LC1">First</span>\n<span id="LC2">Second</span>\n<span id="LC3">Third</span>`;
+ const blobHash = 'foo-bar';
function createComponent(content = contentMock) {
wrapper = shallowMount(SimpleViewer, {
+ provide: {
+ blobHash,
+ },
propsData: {
content,
type: 'text',
diff --git a/spec/frontend/vue_shared/components/confirm_modal_spec.js b/spec/frontend/vue_shared/components/confirm_modal_spec.js
index 8456ca9d125..96ccf56cbc6 100644
--- a/spec/frontend/vue_shared/components/confirm_modal_spec.js
+++ b/spec/frontend/vue_shared/components/confirm_modal_spec.js
@@ -62,7 +62,7 @@ describe('vue_shared/components/confirm_modal', () => {
wrapper.vm.modalAttributes = MOCK_MODAL_DATA.modalAttributes;
});
- it('renders GlModal wtih data', () => {
+ it('renders GlModal with data', () => {
expect(findModal().exists()).toBeTruthy();
expect(findModal().attributes()).toEqual(
expect.objectContaining({
@@ -72,6 +72,24 @@ describe('vue_shared/components/confirm_modal', () => {
);
});
});
+
+ describe.each`
+ desc | attrs | expectation
+ ${'when message is simple text'} | ${{}} | ${`<div>${MOCK_MODAL_DATA.modalAttributes.message}</div>`}
+ ${'when message has html'} | ${{ messageHtml: '<p>Header</p><ul onhover="alert(1)"><li>First</li></ul>' }} | ${'<p>Header</p><ul><li>First</li></ul>'}
+ `('$desc', ({ attrs, expectation }) => {
+ beforeEach(() => {
+ createComponent();
+ wrapper.vm.modalAttributes = {
+ ...MOCK_MODAL_DATA.modalAttributes,
+ ...attrs,
+ };
+ });
+
+ it('renders message', () => {
+ expect(findForm().element.innerHTML).toContain(expectation);
+ });
+ });
});
describe('methods', () => {
diff --git a/spec/frontend/vue_shared/components/dropdown/dropdown_button_spec.js b/spec/frontend/vue_shared/components/dropdown/dropdown_button_spec.js
index 892a96b76fd..08e5d828b8f 100644
--- a/spec/frontend/vue_shared/components/dropdown/dropdown_button_spec.js
+++ b/spec/frontend/vue_shared/components/dropdown/dropdown_button_spec.js
@@ -60,10 +60,9 @@ describe('DropdownButtonComponent', () => {
});
it('renders dropdown button icon', () => {
- const dropdownIconEl = vm.$el.querySelector('.dropdown-toggle-icon i.fa');
+ const dropdownIconEl = vm.$el.querySelector('[data-testid="chevron-down-icon"]');
expect(dropdownIconEl).not.toBeNull();
- expect(dropdownIconEl.classList.contains('fa-chevron-down')).toBe(true);
});
it('renders slot, if default slot exists', () => {
diff --git a/spec/frontend/vue_shared/components/file_row_spec.js b/spec/frontend/vue_shared/components/file_row_spec.js
index d28c35d26bf..bd6a18bf704 100644
--- a/spec/frontend/vue_shared/components/file_row_spec.js
+++ b/spec/frontend/vue_shared/components/file_row_spec.js
@@ -3,6 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileHeader from '~/vue_shared/components/file_row_header.vue';
+import FileIcon from '~/vue_shared/components/file_icon.vue';
import { escapeFileUrl } from '~/lib/utils/url_utility';
describe('File row component', () => {
@@ -151,4 +152,18 @@ describe('File row component', () => {
expect(wrapper.find('.file-row-name').classes()).toContain('font-weight-bold');
});
+
+ it('renders submodule icon', () => {
+ const submodule = true;
+
+ createComponent({
+ file: {
+ ...file(),
+ submodule,
+ },
+ level: 0,
+ });
+
+ expect(wrapper.find(FileIcon).props('submodule')).toBe(submodule);
+ });
});
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 c79880d4766..64bfff3dfa1 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,5 +1,12 @@
import { shallowMount, mount } from '@vue/test-utils';
-import { GlFilteredSearch, GlButtonGroup, GlButton, GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import {
+ GlFilteredSearch,
+ GlButtonGroup,
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ GlFormCheckbox,
+} 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';
@@ -30,6 +37,8 @@ const createComponent = ({
recentSearchesStorageKey = 'requirements',
tokens = mockAvailableTokens,
sortOptions,
+ showCheckbox = false,
+ checkboxChecked = false,
searchInputPlaceholder = 'Filter requirements',
} = {}) => {
const mountMethod = shallow ? shallowMount : mount;
@@ -40,6 +49,8 @@ const createComponent = ({
recentSearchesStorageKey,
tokens,
sortOptions,
+ showCheckbox,
+ checkboxChecked,
searchInputPlaceholder,
},
});
@@ -364,6 +375,26 @@ describe('FilteredSearchBarRoot', () => {
expect(glFilteredSearchEl.props('historyItems')).toEqual(mockHistoryItems);
});
+ it('renders checkbox when `showCheckbox` prop is true', async () => {
+ let wrapperWithCheckbox = createComponent({
+ showCheckbox: true,
+ });
+
+ expect(wrapperWithCheckbox.find(GlFormCheckbox).exists()).toBe(true);
+ expect(wrapperWithCheckbox.find(GlFormCheckbox).attributes('checked')).not.toBeDefined();
+
+ wrapperWithCheckbox.destroy();
+
+ wrapperWithCheckbox = createComponent({
+ showCheckbox: true,
+ checkboxChecked: true,
+ });
+
+ expect(wrapperWithCheckbox.find(GlFormCheckbox).attributes('checked')).toBe('true');
+
+ wrapperWithCheckbox.destroy();
+ });
+
it('renders search history items dropdown with formatting done using token symbols', async () => {
const wrapperFullMount = createComponent({ sortOptions: mockSortOptions, shallow: false });
wrapperFullMount.vm.recentSearchesStore.addRecentSearch(mockHistoryItems[0]);
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 72840ce381f..3fd1d8b7f42 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
@@ -45,6 +45,7 @@ function createComponent(options = {}) {
provide: {
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
+ suggestionsListClass: 'custom-class',
},
stubs,
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
index 12b7fd58670..5b7f7d242e9 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
@@ -45,6 +45,7 @@ function createComponent(options = {}) {
provide: {
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
+ suggestionsListClass: 'custom-class',
},
stubs,
});
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 3feb05bab35..74172db81c2 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
@@ -50,6 +50,7 @@ function createComponent(options = {}) {
provide: {
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
+ suggestionsListClass: 'custom-class',
},
stubs,
});
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 0ec814e3f15..67f9a9c70cc 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
@@ -48,6 +48,7 @@ function createComponent(options = {}) {
provide: {
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
+ suggestionsListClass: 'custom-class',
},
stubs,
});
@@ -120,7 +121,9 @@ describe('MilestoneToken', () => {
wrapper.vm.fetchMilestoneBySearchTerm('foo');
return waitForPromises().then(() => {
- expect(createFlash).toHaveBeenCalledWith('There was a problem fetching milestones.');
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'There was a problem fetching milestones.',
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/integration_help_text_spec.js b/spec/frontend/vue_shared/components/integration_help_text_spec.js
new file mode 100644
index 00000000000..4269d36d0e2
--- /dev/null
+++ b/spec/frontend/vue_shared/components/integration_help_text_spec.js
@@ -0,0 +1,57 @@
+import { shallowMount } from '@vue/test-utils';
+
+import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
+import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue';
+
+describe('IntegrationHelpText component', () => {
+ let wrapper;
+ const defaultProps = {
+ message: 'Click %{linkStart}Bar%{linkEnd}!',
+ messageUrl: 'http://bar.com',
+ };
+
+ function createComponent(props = {}) {
+ return shallowMount(IntegrationHelpText, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ stubs: {
+ GlSprintf,
+ },
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should use the gl components', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.find(GlSprintf).exists()).toBe(true);
+ expect(wrapper.find(GlIcon).exists()).toBe(true);
+ expect(wrapper.find(GlLink).exists()).toBe(true);
+ });
+
+ it('should render the help text', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('should not use the gl-link and gl-icon components', () => {
+ wrapper = createComponent({ message: 'Click nowhere!' });
+
+ expect(wrapper.find(GlSprintf).exists()).toBe(true);
+ expect(wrapper.find(GlIcon).exists()).toBe(false);
+ expect(wrapper.find(GlLink).exists()).toBe(false);
+ });
+
+ it('should not render the link when start and end is not provided', () => {
+ wrapper = createComponent({ message: 'Click nowhere!' });
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/vue_shared/components/local_storage_sync_spec.js b/spec/frontend/vue_shared/components/local_storage_sync_spec.js
index efa9b5796fb..464fe3411dd 100644
--- a/spec/frontend/vue_shared/components/local_storage_sync_spec.js
+++ b/spec/frontend/vue_shared/components/local_storage_sync_spec.js
@@ -239,4 +239,30 @@ describe('Local Storage Sync', () => {
});
});
});
+
+ it('clears localStorage when clear property is true', async () => {
+ const storageKey = 'key';
+ const value = 'initial';
+
+ createComponent({
+ props: {
+ storageKey,
+ },
+ });
+ wrapper.setProps({
+ value,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(localStorage.getItem(storageKey)).toBe(value);
+
+ wrapper.setProps({
+ clear: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(localStorage.getItem(storageKey)).toBe(null);
+ });
});
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 b19e74b5b11..c0a000690f8 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
@@ -29,6 +29,10 @@ describe('Suggestion Diff component', () => {
});
};
+ beforeEach(() => {
+ window.gon.current_user_id = 1;
+ });
+
afterEach(() => {
wrapper.destroy();
});
@@ -71,6 +75,14 @@ describe('Suggestion Diff component', () => {
expect(addToBatchBtn.html().includes('Add suggestion to batch')).toBe(true);
});
+ it('does not render apply suggestion button with anonymous user', () => {
+ window.gon.current_user_id = null;
+
+ createComponent();
+
+ expect(findApplyButton().exists()).toBe(false);
+ });
+
describe('when apply suggestion is clicked', () => {
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/vue_shared/components/members/mock_data.js b/spec/frontend/vue_shared/components/members/mock_data.js
index d7bb8c0d142..5674929716d 100644
--- a/spec/frontend/vue_shared/components/members/mock_data.js
+++ b/spec/frontend/vue_shared/components/members/mock_data.js
@@ -3,6 +3,7 @@ export const member = {
canUpdate: false,
canRemove: false,
canOverride: false,
+ isOverridden: false,
accessLevel: { integerValue: 50, stringValue: 'Owner' },
source: {
id: 178,
diff --git a/spec/frontend/vue_shared/components/members/table/expiration_datepicker_spec.js b/spec/frontend/vue_shared/components/members/table/expiration_datepicker_spec.js
new file mode 100644
index 00000000000..a1afdbc2b49
--- /dev/null
+++ b/spec/frontend/vue_shared/components/members/table/expiration_datepicker_spec.js
@@ -0,0 +1,166 @@
+import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { nextTick } from 'vue';
+import { GlDatepicker } from '@gitlab/ui';
+import { useFakeDate } from 'helpers/fake_date';
+import waitForPromises from 'helpers/wait_for_promises';
+import ExpirationDatepicker from '~/vue_shared/components/members/table/expiration_datepicker.vue';
+import { member } from '../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('ExpirationDatepicker', () => {
+ // March 15th, 2020 3:00
+ useFakeDate(2020, 2, 15, 3);
+
+ let wrapper;
+ let actions;
+ let resolveUpdateMemberExpiration;
+ const $toast = {
+ show: jest.fn(),
+ };
+
+ const createStore = () => {
+ actions = {
+ updateMemberExpiration: jest.fn(
+ () =>
+ new Promise(resolve => {
+ resolveUpdateMemberExpiration = resolve;
+ }),
+ ),
+ };
+
+ return new Vuex.Store({ actions });
+ };
+
+ const createComponent = (propsData = {}) => {
+ wrapper = mount(ExpirationDatepicker, {
+ propsData: {
+ member,
+ permissions: { canUpdate: true },
+ ...propsData,
+ },
+ localVue,
+ store: createStore(),
+ mocks: {
+ $toast,
+ },
+ });
+ };
+
+ const findInput = () => wrapper.find('input');
+ const findDatepicker = () => wrapper.find(GlDatepicker);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('datepicker input', () => {
+ it('sets `member.expiresAt` as initial date', async () => {
+ createComponent({ member: { ...member, expiresAt: '2020-03-17T00:00:00Z' } });
+
+ await nextTick();
+
+ expect(findInput().element.value).toBe('2020-03-17');
+ });
+ });
+
+ describe('props', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('sets `minDate` prop as tomorrow', () => {
+ expect(
+ findDatepicker()
+ .props('minDate')
+ .toISOString(),
+ ).toBe(new Date('2020-3-16').toISOString());
+ });
+
+ it('sets `target` prop as `null` so datepicker opens on focus', () => {
+ expect(findDatepicker().props('target')).toBe(null);
+ });
+
+ it("sets `container` prop as `null` so table styles don't affect the datepicker styles", () => {
+ expect(findDatepicker().props('container')).toBe(null);
+ });
+
+ it('shows clear button', () => {
+ expect(findDatepicker().props('showClearButton')).toBe(true);
+ });
+ });
+
+ describe('when datepicker is changed', () => {
+ beforeEach(async () => {
+ createComponent();
+
+ findDatepicker().vm.$emit('input', new Date('2020-03-17'));
+ });
+
+ it('calls `updateMemberExpiration` Vuex action', () => {
+ expect(actions.updateMemberExpiration).toHaveBeenCalledWith(expect.any(Object), {
+ memberId: member.id,
+ expiresAt: new Date('2020-03-17'),
+ });
+ });
+
+ it('displays toast when successful', async () => {
+ resolveUpdateMemberExpiration();
+ await waitForPromises();
+
+ expect($toast.show).toHaveBeenCalledWith('Expiration date updated successfully.');
+ });
+
+ it('disables dropdown while waiting for `updateMemberExpiration` to resolve', async () => {
+ expect(findDatepicker().props('disabled')).toBe(true);
+
+ resolveUpdateMemberExpiration();
+ await waitForPromises();
+
+ expect(findDatepicker().props('disabled')).toBe(false);
+ });
+ });
+
+ describe('when datepicker is cleared', () => {
+ beforeEach(async () => {
+ createComponent();
+
+ findInput().setValue('2020-03-17');
+ await nextTick();
+ wrapper.find('[data-testid="clear-button"]').trigger('click');
+ });
+
+ it('calls `updateMemberExpiration` Vuex action', () => {
+ expect(actions.updateMemberExpiration).toHaveBeenCalledWith(expect.any(Object), {
+ memberId: member.id,
+ expiresAt: null,
+ });
+ });
+
+ it('displays toast when successful', async () => {
+ resolveUpdateMemberExpiration();
+ await waitForPromises();
+
+ expect($toast.show).toHaveBeenCalledWith('Expiration date removed successfully.');
+ });
+
+ it('disables datepicker while waiting for `updateMemberExpiration` to resolve', async () => {
+ expect(findDatepicker().props('disabled')).toBe(true);
+
+ resolveUpdateMemberExpiration();
+ await waitForPromises();
+
+ expect(findDatepicker().props('disabled')).toBe(false);
+ });
+ });
+
+ describe('when user does not have `canUpdate` permissions', () => {
+ it('disables datepicker', () => {
+ createComponent({ permissions: { canUpdate: false } });
+
+ expect(findDatepicker().props('disabled')).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/members/table/members_table_spec.js b/spec/frontend/vue_shared/components/members/table/members_table_spec.js
index 20c1c26d2ee..e593e88438c 100644
--- a/spec/frontend/vue_shared/components/members/table/members_table_spec.js
+++ b/spec/frontend/vue_shared/components/members/table/members_table_spec.js
@@ -3,14 +3,16 @@ import Vuex from 'vuex';
import {
getByText as getByTextHelper,
getByTestId as getByTestIdHelper,
+ within,
} from '@testing-library/dom';
-import { GlBadge } from '@gitlab/ui';
+import { GlBadge, GlTable } from '@gitlab/ui';
import MembersTable from '~/vue_shared/components/members/table/members_table.vue';
import MemberAvatar from '~/vue_shared/components/members/table/member_avatar.vue';
import MemberSource from '~/vue_shared/components/members/table/member_source.vue';
import ExpiresAt from '~/vue_shared/components/members/table/expires_at.vue';
import CreatedAt from '~/vue_shared/components/members/table/created_at.vue';
import RoleDropdown from '~/vue_shared/components/members/table/role_dropdown.vue';
+import ExpirationDatepicker from '~/vue_shared/components/members/table/expiration_datepicker.vue';
import MemberActionButtons from '~/vue_shared/components/members/table/member_action_buttons.vue';
import * as initUserPopovers from '~/user_popovers';
import { member as memberMock, invite, accessRequest } from '../mock_data';
@@ -26,7 +28,12 @@ describe('MemberList', () => {
state: {
members: [],
tableFields: [],
+ tableAttrs: {
+ table: { 'data-qa-selector': 'members_list' },
+ tr: { 'data-qa-selector': 'member_row' },
+ },
sourceId: 1,
+ currentUserId: 1,
...state,
},
});
@@ -44,6 +51,7 @@ describe('MemberList', () => {
'member-action-buttons',
'role-dropdown',
'remove-group-link-modal',
+ 'expiration-datepicker',
],
});
};
@@ -54,18 +62,24 @@ describe('MemberList', () => {
const getByTestId = (id, options) =>
createWrapper(getByTestIdHelper(wrapper.element, id, options));
+ const findTable = () => wrapper.find(GlTable);
+
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('fields', () => {
- const memberCanUpdate = {
+ const directMember = {
...memberMock,
- canUpdate: true,
source: { ...memberMock.source, id: 1 },
};
+ const memberCanUpdate = {
+ ...directMember,
+ canUpdate: true,
+ };
+
it.each`
field | label | member | expectedComponent
${'account'} | ${'Account'} | ${memberMock} | ${MemberAvatar}
@@ -75,7 +89,7 @@ describe('MemberList', () => {
${'requested'} | ${'Requested'} | ${accessRequest} | ${CreatedAt}
${'expires'} | ${'Access expires'} | ${memberMock} | ${ExpiresAt}
${'maxRole'} | ${'Max role'} | ${memberCanUpdate} | ${RoleDropdown}
- ${'expiration'} | ${'Expiration'} | ${memberMock} | ${null}
+ ${'expiration'} | ${'Expiration'} | ${memberMock} | ${ExpirationDatepicker}
`('renders the $label field', ({ field, label, member, expectedComponent }) => {
createComponent({
members: [member],
@@ -94,19 +108,60 @@ describe('MemberList', () => {
}
});
- it('renders "Actions" field for screen readers', () => {
- createComponent({ members: [memberMock], tableFields: ['actions'] });
+ describe('"Actions" field', () => {
+ it('renders "Actions" field for screen readers', () => {
+ createComponent({ members: [memberCanUpdate], tableFields: ['actions'] });
- const actionField = getByTestId('col-actions');
+ const actionField = getByTestId('col-actions');
- expect(actionField.exists()).toBe(true);
- expect(actionField.classes('gl-sr-only')).toBe(true);
- expect(
- wrapper
- .find(`[data-label="Actions"][role="cell"]`)
- .find(MemberActionButtons)
- .exists(),
- ).toBe(true);
+ expect(actionField.exists()).toBe(true);
+ expect(actionField.classes('gl-sr-only')).toBe(true);
+ expect(
+ wrapper
+ .find(`[data-label="Actions"][role="cell"]`)
+ .find(MemberActionButtons)
+ .exists(),
+ ).toBe(true);
+ });
+
+ describe('when user is not logged in', () => {
+ it('does not render the "Actions" field', () => {
+ createComponent({ currentUserId: null, tableFields: ['actions'] });
+
+ expect(within(wrapper.element).queryByTestId('col-actions')).toBe(null);
+ });
+ });
+
+ const memberCanRemove = {
+ ...directMember,
+ canRemove: true,
+ };
+
+ describe.each`
+ permission | members
+ ${'canUpdate'} | ${[memberCanUpdate]}
+ ${'canRemove'} | ${[memberCanRemove]}
+ ${'canResend'} | ${[invite]}
+ `('when one of the members has $permission permissions', ({ members }) => {
+ it('renders the "Actions" field', () => {
+ createComponent({ members, tableFields: ['actions'] });
+
+ expect(getByTestId('col-actions').exists()).toBe(true);
+ });
+ });
+
+ describe.each`
+ permission | members
+ ${'canUpdate'} | ${[memberMock]}
+ ${'canRemove'} | ${[memberMock]}
+ ${'canResend'} | ${[{ ...invite, invite: { ...invite.invite, canResend: false } }]}
+ `('when none of the members have $permission permissions', ({ members }) => {
+ it('does not render the "Actions" field', () => {
+ createComponent({ members, tableFields: ['actions'] });
+
+ expect(within(wrapper.element).queryByTestId('col-actions')).toBe(null);
+ });
+ });
});
});
@@ -138,4 +193,20 @@ describe('MemberList', () => {
expect(initUserPopoversMock).toHaveBeenCalled();
});
+
+ it('adds QA selector to table', () => {
+ createComponent();
+
+ expect(findTable().attributes('data-qa-selector')).toBe('members_list');
+ });
+
+ it('adds QA selector to table row', () => {
+ createComponent();
+
+ expect(
+ findTable()
+ .find('tbody tr')
+ .attributes('data-qa-selector'),
+ ).toBe('member_row');
+ });
});
diff --git a/spec/frontend/vue_shared/components/members/table/role_dropdown_spec.js b/spec/frontend/vue_shared/components/members/table/role_dropdown_spec.js
index 1e47953a510..55ec7000693 100644
--- a/spec/frontend/vue_shared/components/members/table/role_dropdown_spec.js
+++ b/spec/frontend/vue_shared/components/members/table/role_dropdown_spec.js
@@ -30,6 +30,7 @@ describe('RoleDropdown', () => {
wrapper = mount(RoleDropdown, {
propsData: {
member,
+ permissions: {},
...propsData,
},
localVue,
@@ -115,11 +116,11 @@ describe('RoleDropdown', () => {
await nextTick();
- expect(findDropdown().attributes('disabled')).toBe('disabled');
+ expect(findDropdown().props('disabled')).toBe(true);
await waitForPromises();
- expect(findDropdown().attributes('disabled')).toBeUndefined();
+ expect(findDropdown().props('disabled')).toBe(false);
});
});
});
diff --git a/spec/frontend/vue_shared/components/members/utils_spec.js b/spec/frontend/vue_shared/components/members/utils_spec.js
index f183abc08d6..3f2b2097133 100644
--- a/spec/frontend/vue_shared/components/members/utils_spec.js
+++ b/spec/frontend/vue_shared/components/members/utils_spec.js
@@ -1,5 +1,19 @@
-import { generateBadges } from '~/vue_shared/components/members/utils';
-import { member as memberMock } from './mock_data';
+import {
+ generateBadges,
+ isGroup,
+ isDirectMember,
+ isCurrentUser,
+ canRemove,
+ canResend,
+ canUpdate,
+ canOverride,
+} from '~/vue_shared/components/members/utils';
+import { member as memberMock, group, invite } from './mock_data';
+
+const DIRECT_MEMBER_ID = 178;
+const INHERITED_MEMBER_ID = 179;
+const IS_CURRENT_USER_ID = 123;
+const IS_NOT_CURRENT_USER_ID = 124;
describe('Members Utils', () => {
describe('generateBadges', () => {
@@ -26,4 +40,83 @@ describe('Members Utils', () => {
expect(generateBadges(member, true)).toContainEqual(expect.objectContaining(expected));
});
});
+
+ describe('isGroup', () => {
+ test.each`
+ member | expected
+ ${group} | ${true}
+ ${memberMock} | ${false}
+ `('returns $expected', ({ member, expected }) => {
+ expect(isGroup(member)).toBe(expected);
+ });
+ });
+
+ describe('isDirectMember', () => {
+ test.each`
+ sourceId | expected
+ ${DIRECT_MEMBER_ID} | ${true}
+ ${INHERITED_MEMBER_ID} | ${false}
+ `('returns $expected', ({ sourceId, expected }) => {
+ expect(isDirectMember(memberMock, sourceId)).toBe(expected);
+ });
+ });
+
+ describe('isCurrentUser', () => {
+ test.each`
+ currentUserId | expected
+ ${IS_CURRENT_USER_ID} | ${true}
+ ${IS_NOT_CURRENT_USER_ID} | ${false}
+ `('returns $expected', ({ currentUserId, expected }) => {
+ expect(isCurrentUser(memberMock, currentUserId)).toBe(expected);
+ });
+ });
+
+ describe('canRemove', () => {
+ const memberCanRemove = {
+ ...memberMock,
+ canRemove: true,
+ };
+
+ test.each`
+ member | sourceId | expected
+ ${memberCanRemove} | ${DIRECT_MEMBER_ID} | ${true}
+ ${memberCanRemove} | ${INHERITED_MEMBER_ID} | ${false}
+ ${memberMock} | ${INHERITED_MEMBER_ID} | ${false}
+ `('returns $expected', ({ member, sourceId, expected }) => {
+ expect(canRemove(member, sourceId)).toBe(expected);
+ });
+ });
+
+ describe('canResend', () => {
+ test.each`
+ member | expected
+ ${invite} | ${true}
+ ${{ ...invite, invite: { ...invite.invite, canResend: false } }} | ${false}
+ `('returns $expected', ({ member, sourceId, expected }) => {
+ expect(canResend(member, sourceId)).toBe(expected);
+ });
+ });
+
+ describe('canUpdate', () => {
+ const memberCanUpdate = {
+ ...memberMock,
+ canUpdate: true,
+ };
+
+ test.each`
+ member | currentUserId | sourceId | expected
+ ${memberCanUpdate} | ${IS_NOT_CURRENT_USER_ID} | ${DIRECT_MEMBER_ID} | ${true}
+ ${memberCanUpdate} | ${IS_CURRENT_USER_ID} | ${DIRECT_MEMBER_ID} | ${false}
+ ${memberCanUpdate} | ${IS_CURRENT_USER_ID} | ${INHERITED_MEMBER_ID} | ${false}
+ ${memberMock} | ${IS_NOT_CURRENT_USER_ID} | ${DIRECT_MEMBER_ID} | ${false}
+ `('returns $expected', ({ member, currentUserId, sourceId, expected }) => {
+ expect(canUpdate(member, currentUserId, sourceId)).toBe(expected);
+ });
+ });
+
+ describe('canOverride', () => {
+ it('returns `false`', () => {
+ expect(canOverride(memberMock)).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/modal_copy_button_spec.js b/spec/frontend/vue_shared/components/modal_copy_button_spec.js
index e5a8860f42e..ca9f8ff54d4 100644
--- a/spec/frontend/vue_shared/components/modal_copy_button_spec.js
+++ b/spec/frontend/vue_shared/components/modal_copy_button_spec.js
@@ -1,9 +1,7 @@
-import Vue from 'vue';
-import { shallowMount } from '@vue/test-utils';
-import modalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
+import { shallowMount, createWrapper } from '@vue/test-utils';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
describe('modal copy button', () => {
- const Component = Vue.extend(modalCopyButton);
let wrapper;
afterEach(() => {
@@ -11,16 +9,18 @@ describe('modal copy button', () => {
});
beforeEach(() => {
- wrapper = shallowMount(Component, {
+ wrapper = shallowMount(ModalCopyButton, {
propsData: {
text: 'copy me',
title: 'Copy this value',
+ id: 'test-id',
},
});
});
describe('clipboard', () => {
it('should fire a `success` event on click', () => {
+ const root = createWrapper(wrapper.vm.$root);
document.execCommand = jest.fn(() => true);
window.getSelection = jest.fn(() => ({
toString: jest.fn(() => 'test'),
@@ -31,6 +31,7 @@ describe('modal copy button', () => {
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().success).not.toBeEmpty();
expect(document.execCommand).toHaveBeenCalledWith('copy');
+ expect(root.emitted('bv::hide::tooltip')).toEqual([['test-id']]);
});
});
it("should propagate the clipboard error event if execCommand doesn't work", () => {
diff --git a/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js b/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js
new file mode 100644
index 00000000000..233c488b60b
--- /dev/null
+++ b/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js
@@ -0,0 +1,31 @@
+import { shallowMount } from '@vue/test-utils';
+import { getByText } from '@testing-library/dom';
+import MultiSelectDropdown from '~/vue_shared/components/sidebar/multiselect_dropdown.vue';
+
+describe('MultiSelectDropdown Component', () => {
+ it('renders items slot', () => {
+ const wrapper = shallowMount(MultiSelectDropdown, {
+ propsData: {
+ text: '',
+ headerText: '',
+ },
+ slots: {
+ items: '<p>Test</p>',
+ },
+ });
+ expect(getByText(wrapper.element, 'Test')).toBeDefined();
+ });
+
+ it('renders search slot', () => {
+ const wrapper = shallowMount(MultiSelectDropdown, {
+ propsData: {
+ text: '',
+ headerText: '',
+ },
+ slots: {
+ search: '<p>Search</p>',
+ },
+ });
+ expect(getByText(wrapper.element, 'Search')).toBeDefined();
+ });
+});
diff --git a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
index d943aaf3e5f..0f7c8e97635 100644
--- a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
+++ b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
@@ -70,7 +70,7 @@ describe('AlertManagementEmptyState', () => {
...props,
},
slots: {
- 'emtpy-state': EmptyStateSlot,
+ 'empty-state': EmptyStateSlot,
'header-actions': HeaderActionsSlot,
title: TitleSlot,
table: TableSlot,
diff --git a/spec/frontend/vue_shared/components/registry/title_area_spec.js b/spec/frontend/vue_shared/components/registry/title_area_spec.js
index 5cb606b58d9..b743a663f06 100644
--- a/spec/frontend/vue_shared/components/registry/title_area_spec.js
+++ b/spec/frontend/vue_shared/components/registry/title_area_spec.js
@@ -5,12 +5,16 @@ import component from '~/vue_shared/components/registry/title_area.vue';
describe('title area', () => {
let wrapper;
+ const DYNAMIC_SLOT = 'metadata-dynamic-slot';
+
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 findInfoMessages = () => wrapper.findAll('[data-testid="info-message"]');
+ const findDynamicSlot = () => wrapper.find(`[data-testid="${DYNAMIC_SLOT}`);
+ const findSlotOrderElements = () => wrapper.findAll('[slot-test]');
const mountComponent = ({ propsData = { title: 'foo' }, slots } = {}) => {
wrapper = shallowMount(component, {
@@ -98,6 +102,59 @@ describe('title area', () => {
});
});
+ describe('dynamic slots', () => {
+ const createDynamicSlot = () => {
+ return wrapper.vm.$createElement('div', {
+ attrs: {
+ 'data-testid': DYNAMIC_SLOT,
+ 'slot-test': true,
+ },
+ });
+ };
+ it('shows dynamic slots', async () => {
+ mountComponent();
+ // we manually add a new slot to simulate dynamic slots being evaluated after the initial mount
+ wrapper.vm.$slots[DYNAMIC_SLOT] = createDynamicSlot();
+
+ await wrapper.vm.$nextTick();
+ expect(findDynamicSlot().exists()).toBe(false);
+
+ await wrapper.vm.$nextTick();
+ expect(findDynamicSlot().exists()).toBe(true);
+ });
+
+ it('preserve the order of the slots', async () => {
+ mountComponent({
+ slots: {
+ 'metadata-foo': '<div slot-test data-testid="metadata-foo"></div>',
+ },
+ });
+
+ // rewrite slot putting dynamic slot as first
+ wrapper.vm.$slots = {
+ 'metadata-dynamic-slot': createDynamicSlot(),
+ 'metadata-foo': wrapper.vm.$slots['metadata-foo'],
+ };
+
+ await wrapper.vm.$nextTick();
+ expect(findDynamicSlot().exists()).toBe(false);
+ expect(findMetadataSlot('metadata-foo').exists()).toBe(true);
+
+ await wrapper.vm.$nextTick();
+
+ expect(
+ findSlotOrderElements()
+ .at(0)
+ .attributes('data-testid'),
+ ).toBe(DYNAMIC_SLOT);
+ expect(
+ findSlotOrderElements()
+ .at(1)
+ .attributes('data-testid'),
+ ).toBe('metadata-foo');
+ });
+ });
+
describe('info-messages', () => {
it('shows a message when the props contains one', () => {
mountComponent({ propsData: { infoMessages: [{ text: 'foo foo bar bar' }] } });
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js
index 0f2f263a776..d79df4d0557 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js
@@ -91,12 +91,25 @@ describe('Editor Service', () => {
});
describe('addImage', () => {
- it('calls the exec method on the instance', () => {
- const mockImage = { imageUrl: 'some/url.png', description: 'some description' };
+ const file = new File([], 'some-file.jpg');
+ const mockImage = { imageUrl: 'some/url.png', altText: 'some alt text' };
- addImage(mockInstance, mockImage);
+ it('calls the insertElement method on the squire instance when in WYSIWYG mode', () => {
+ jest.spyOn(URL, 'createObjectURL');
+ mockInstance.editor.isWysiwygMode.mockReturnValue(true);
+ mockInstance.editor.getSquire.mockReturnValue({ insertElement: jest.fn() });
- expect(mockInstance.editor.exec).toHaveBeenCalledWith('AddImage', mockImage);
+ addImage(mockInstance, mockImage, file);
+
+ expect(mockInstance.editor.getSquire().insertElement).toHaveBeenCalled();
+ expect(global.URL.createObjectURL).toHaveBeenLastCalledWith(file);
+ });
+
+ it('calls the insertText method on the instance when in Markdown mode', () => {
+ mockInstance.editor.isWysiwygMode.mockReturnValue(false);
+ addImage(mockInstance, mockImage, file);
+
+ expect(mockInstance.editor.insertText).toHaveBeenCalledWith('![some alt text](some/url.png)');
});
});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js
index 0c2ac53aa52..16370a7aaad 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js
@@ -15,10 +15,7 @@ describe('Add Image Modal', () => {
const findDescriptionInput = () => wrapper.find({ ref: 'descriptionInput' });
beforeEach(() => {
- wrapper = shallowMount(AddImageModal, {
- provide: { glFeatures: { sseImageUploads: true } },
- propsData,
- });
+ wrapper = shallowMount(AddImageModal, { propsData });
});
describe('when content is loaded', () => {
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js
index 8c2c0413819..d50cf2915e8 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js
@@ -180,7 +180,7 @@ describe('Rich Content Editor', () => {
wrapper.vm.$refs.editor = mockInstance;
findAddImageModal().vm.$emit('addImage', mockImage);
- expect(addImage).toHaveBeenCalledWith(mockInstance, mockImage);
+ expect(addImage).toHaveBeenCalledWith(mockInstance, mockImage, undefined);
});
});
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 fd745c21bb6..85516eae4cf 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
@@ -189,4 +189,30 @@ describe('rich_content_editor/services/html_to_markdown_renderer', () => {
expect(htmlToMarkdownRenderer['PRE CODE'](node, subContent)).toBe(originalConverterResult);
});
});
+
+ describe('IMG', () => {
+ const originalSrc = 'path/to/image.png';
+ const alt = 'alt text';
+ let node;
+
+ beforeEach(() => {
+ node = document.createElement('img');
+ node.alt = alt;
+ node.src = originalSrc;
+ });
+
+ it('returns an image with its original src of the `original-src` attribute is preset', () => {
+ node.dataset.originalSrc = originalSrc;
+ node.src = 'modified/path/to/image.png';
+
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
+
+ expect(htmlToMarkdownRenderer.IMG(node)).toBe(`![${alt}](${originalSrc})`);
+ });
+
+ it('fallback to `src` if no `original-src` is specified on the image', () => {
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
+ expect(htmlToMarkdownRenderer.IMG(node)).toBe(`![${alt}](${originalSrc})`);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/runner_instructions/mock_data.js b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js
new file mode 100644
index 00000000000..01f7f3d49c7
--- /dev/null
+++ b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js
@@ -0,0 +1,107 @@
+export const mockGraphqlRunnerPlatforms = {
+ data: {
+ runnerPlatforms: {
+ nodes: [
+ {
+ name: 'linux',
+ humanReadableName: 'Linux',
+ architectures: {
+ nodes: [
+ {
+ name: 'amd64',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64',
+ __typename: 'RunnerArchitecture',
+ },
+ {
+ name: '386',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-386',
+ __typename: 'RunnerArchitecture',
+ },
+ {
+ name: 'arm',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm',
+ __typename: 'RunnerArchitecture',
+ },
+ {
+ name: 'arm64',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm64',
+ __typename: 'RunnerArchitecture',
+ },
+ ],
+ __typename: 'RunnerArchitectureConnection',
+ },
+ __typename: 'RunnerPlatform',
+ },
+ {
+ name: 'osx',
+ humanReadableName: 'macOS',
+ architectures: {
+ nodes: [
+ {
+ name: 'amd64',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64',
+ __typename: 'RunnerArchitecture',
+ },
+ ],
+ __typename: 'RunnerArchitectureConnection',
+ },
+ __typename: 'RunnerPlatform',
+ },
+ {
+ name: 'windows',
+ humanReadableName: 'Windows',
+ architectures: {
+ nodes: [
+ {
+ name: 'amd64',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-amd64.exe',
+ __typename: 'RunnerArchitecture',
+ },
+ {
+ name: '386',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-386.exe',
+ __typename: 'RunnerArchitecture',
+ },
+ ],
+ __typename: 'RunnerArchitectureConnection',
+ },
+ __typename: 'RunnerPlatform',
+ },
+ {
+ name: 'docker',
+ humanReadableName: 'Docker',
+ architectures: null,
+ __typename: 'RunnerPlatform',
+ },
+ {
+ name: 'kubernetes',
+ humanReadableName: 'Kubernetes',
+ architectures: null,
+ __typename: 'RunnerPlatform',
+ },
+ ],
+ __typename: 'RunnerPlatformConnection',
+ },
+ project: { id: 'gid://gitlab/Project/1', __typename: 'Project' },
+ group: null,
+ },
+};
+
+export const mockGraphqlInstructions = {
+ data: {
+ runnerSetup: {
+ installInstructions:
+ "# Download the binary for your system\nsudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64\n\n# Give it permissions to execute\nsudo chmod +x /usr/local/bin/gitlab-runner\n\n# Create a GitLab CI user\nsudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash\n\n# Install and run as service\nsudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner\nsudo gitlab-runner start\n",
+ registerInstructions:
+ 'sudo gitlab-runner register --url http://192.168.1.81:3000/ --registration-token GE5gsjeep_HAtBf9s3Yz',
+ __typename: 'RunnerSetup',
+ },
+ },
+};
diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
new file mode 100644
index 00000000000..afbcee506c7
--- /dev/null
+++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
@@ -0,0 +1,119 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import RunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue';
+import getRunnerPlatforms from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql';
+import getRunnerSetupInstructions from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql';
+
+import { mockGraphqlRunnerPlatforms, mockGraphqlInstructions } from './mock_data';
+
+const projectPath = 'gitlab-org/gitlab';
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('RunnerInstructions component', () => {
+ let wrapper;
+ let fakeApollo;
+
+ const findModalButton = () => wrapper.find('[data-testid="show-modal-button"]');
+ const findPlatformButtons = () => wrapper.findAll('[data-testid="platform-button"]');
+ const findArchitectureDropdownItems = () =>
+ wrapper.findAll('[data-testid="architecture-dropdown-item"]');
+ const findBinaryInstructionsSection = () => wrapper.find('[data-testid="binary-instructions"]');
+ const findRunnerInstructionsSection = () => wrapper.find('[data-testid="runner-instructions"]');
+
+ beforeEach(() => {
+ const requestHandlers = [
+ [getRunnerPlatforms, jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms)],
+ [getRunnerSetupInstructions, jest.fn().mockResolvedValue(mockGraphqlInstructions)],
+ ];
+
+ fakeApollo = createMockApollo(requestHandlers);
+
+ wrapper = shallowMount(RunnerInstructions, {
+ provide: {
+ projectPath,
+ },
+ localVue,
+ apolloProvider: fakeApollo,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should show the "Show Runner installation instructions" button', () => {
+ const button = findModalButton();
+
+ expect(button.exists()).toBe(true);
+ expect(button.text()).toBe('Show Runner installation instructions');
+ });
+
+ it('should contain a number of platforms buttons', () => {
+ const buttons = findPlatformButtons();
+
+ expect(buttons).toHaveLength(mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes.length);
+ });
+
+ it('should contain a number of dropdown items for the architecture options', () => {
+ const platformButton = findPlatformButtons().at(0);
+ platformButton.vm.$emit('click');
+
+ return wrapper.vm.$nextTick(() => {
+ const dropdownItems = findArchitectureDropdownItems();
+
+ expect(dropdownItems).toHaveLength(
+ mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes[0].architectures.nodes.length,
+ );
+ });
+ });
+
+ it('should display the binary installation instructions for a selected architecture', async () => {
+ const platformButton = findPlatformButtons().at(0);
+ platformButton.vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ const dropdownItem = findArchitectureDropdownItems().at(0);
+ dropdownItem.vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ const runner = findBinaryInstructionsSection();
+
+ expect(runner.text()).toEqual(
+ expect.stringContaining('sudo chmod +x /usr/local/bin/gitlab-runner'),
+ );
+ expect(runner.text()).toEqual(
+ expect.stringContaining(
+ `sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash`,
+ ),
+ );
+ expect(runner.text()).toEqual(
+ expect.stringContaining(
+ 'sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner',
+ ),
+ );
+ expect(runner.text()).toEqual(expect.stringContaining('sudo gitlab-runner start'));
+ });
+
+ it('should display the runner register instructions for a selected architecture', async () => {
+ const platformButton = findPlatformButtons().at(0);
+ platformButton.vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ const dropdownItem = findArchitectureDropdownItems().at(0);
+ dropdownItem.vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ const runner = findRunnerInstructionsSection();
+
+ expect(runner.text()).toEqual(
+ expect.stringContaining(mockGraphqlInstructions.data.runnerSetup.registerInstructions),
+ );
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js b/spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js
new file mode 100644
index 00000000000..a97e26caf53
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js
@@ -0,0 +1,375 @@
+import { shallowMount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import {
+ GlIcon,
+ GlLoadingIcon,
+ GlDropdown,
+ GlDropdownForm,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ GlButton,
+} from '@gitlab/ui';
+
+import axios from '~/lib/utils/axios_utils';
+import IssuableMoveDropdown from '~/vue_shared/components/sidebar/issuable_move_dropdown.vue';
+
+const mockProjects = [
+ {
+ id: 2,
+ name_with_namespace: 'Gitlab Org / Gitlab Shell',
+ full_path: 'gitlab-org/gitlab-shell',
+ },
+ {
+ id: 3,
+ name_with_namespace: 'Gnuwget / Wget2',
+ full_path: 'gnuwget/wget2',
+ },
+ {
+ id: 4,
+ name_with_namespace: 'Commit451 / Lab Coat',
+ full_path: 'Commit451/lab-coat',
+ },
+];
+
+const mockProps = {
+ projectsFetchPath: '/-/autocomplete/projects?project_id=1',
+ dropdownButtonTitle: 'Move issuable',
+ dropdownHeaderTitle: 'Move issuable',
+ moveInProgress: false,
+};
+
+const mockEvent = {
+ stopPropagation: jest.fn(),
+ preventDefault: jest.fn(),
+};
+
+const createComponent = (propsData = mockProps) =>
+ shallowMount(IssuableMoveDropdown, {
+ propsData,
+ });
+
+describe('IssuableMoveDropdown', () => {
+ let mock;
+ let wrapper;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ wrapper = createComponent();
+ wrapper.vm.$refs.dropdown.hide = jest.fn();
+ wrapper.vm.$refs.searchInput.focusInput = jest.fn();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ mock.restore();
+ });
+
+ describe('watch', () => {
+ describe('searchKey', () => {
+ it('calls `fetchProjects` with value of the prop', async () => {
+ jest.spyOn(wrapper.vm, 'fetchProjects');
+ wrapper.setData({
+ searchKey: 'foo',
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.fetchProjects).toHaveBeenCalledWith('foo');
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('fetchProjects', () => {
+ it('sets projectsListLoading to true and projectsListLoadFailed to false', () => {
+ wrapper.vm.fetchProjects();
+
+ expect(wrapper.vm.projectsListLoading).toBe(true);
+ expect(wrapper.vm.projectsListLoadFailed).toBe(false);
+ });
+
+ it('calls `axios.get` with `projectsFetchPath` and query param `search`', () => {
+ jest.spyOn(axios, 'get').mockResolvedValue({
+ data: mockProjects,
+ });
+
+ wrapper.vm.fetchProjects('foo');
+
+ expect(axios.get).toHaveBeenCalledWith(
+ mockProps.projectsFetchPath,
+ expect.objectContaining({
+ params: {
+ search: 'foo',
+ },
+ }),
+ );
+ });
+
+ it('sets response to `projects` and focuses on searchInput when request is successful', async () => {
+ jest.spyOn(axios, 'get').mockResolvedValue({
+ data: mockProjects,
+ });
+
+ await wrapper.vm.fetchProjects('foo');
+
+ expect(wrapper.vm.projects).toBe(mockProjects);
+ expect(wrapper.vm.$refs.searchInput.focusInput).toHaveBeenCalled();
+ });
+
+ it('sets projectsListLoadFailed to true when request fails', async () => {
+ jest.spyOn(axios, 'get').mockRejectedValue({});
+
+ await wrapper.vm.fetchProjects('foo');
+
+ expect(wrapper.vm.projectsListLoadFailed).toBe(true);
+ });
+
+ it('sets projectsListLoading to false when request completes', async () => {
+ jest.spyOn(axios, 'get').mockResolvedValue({
+ data: mockProjects,
+ });
+
+ await wrapper.vm.fetchProjects('foo');
+
+ expect(wrapper.vm.projectsListLoading).toBe(false);
+ });
+ });
+
+ describe('isSelectedProject', () => {
+ it.each`
+ project | selectedProject | title | returnValue
+ ${mockProjects[0]} | ${mockProjects[0]} | ${'are same projects'} | ${true}
+ ${mockProjects[0]} | ${mockProjects[1]} | ${'are different projects'} | ${false}
+ `(
+ 'returns $returnValue when selectedProject and provided project param $title',
+ async ({ project, selectedProject, returnValue }) => {
+ wrapper.setData({
+ selectedProject,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.isSelectedProject(project)).toBe(returnValue);
+ },
+ );
+
+ it('returns false when selectedProject is null', async () => {
+ wrapper.setData({
+ selectedProject: null,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.isSelectedProject(mockProjects[0])).toBe(false);
+ });
+ });
+ });
+
+ describe('template', () => {
+ const findDropdownEl = () => wrapper.find(GlDropdown);
+
+ it('renders collapsed state element with icon', () => {
+ const collapsedEl = wrapper.find('[data-testid="move-collapsed"]');
+
+ expect(collapsedEl.exists()).toBe(true);
+ expect(collapsedEl.attributes('title')).toBe(mockProps.dropdownButtonTitle);
+ expect(collapsedEl.find(GlIcon).exists()).toBe(true);
+ expect(collapsedEl.find(GlIcon).props('name')).toBe('arrow-right');
+ });
+
+ describe('gl-dropdown component', () => {
+ it('renders component container element', () => {
+ expect(findDropdownEl().exists()).toBe(true);
+ expect(findDropdownEl().props('block')).toBe(true);
+ });
+
+ it('renders gl-dropdown-form component', () => {
+ expect(
+ findDropdownEl()
+ .find(GlDropdownForm)
+ .exists(),
+ ).toBe(true);
+ });
+
+ it('renders header element', () => {
+ const headerEl = findDropdownEl().find('[data-testid="header"]');
+
+ expect(headerEl.exists()).toBe(true);
+ expect(headerEl.find('span').text()).toBe(mockProps.dropdownHeaderTitle);
+ expect(headerEl.find(GlButton).props('icon')).toBe('close');
+ });
+
+ it('renders gl-search-box-by-type component', () => {
+ const searchEl = findDropdownEl().find(GlSearchBoxByType);
+
+ expect(searchEl.exists()).toBe(true);
+ expect(searchEl.attributes()).toMatchObject({
+ placeholder: 'Search project',
+ debounce: '300',
+ });
+ });
+
+ it('renders gl-loading-icon component when projectsListLoading prop is true', async () => {
+ wrapper.setData({
+ projectsListLoading: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(
+ findDropdownEl()
+ .find(GlLoadingIcon)
+ .exists(),
+ ).toBe(true);
+ });
+
+ it('renders gl-dropdown-item components for available projects', async () => {
+ wrapper.setData({
+ projects: mockProjects,
+ selectedProject: mockProjects[0],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const dropdownItems = wrapper.findAll(GlDropdownItem);
+
+ expect(dropdownItems).toHaveLength(mockProjects.length);
+ expect(dropdownItems.at(0).props()).toMatchObject({
+ isCheckItem: true,
+ isChecked: true,
+ });
+ expect(dropdownItems.at(0).text()).toBe(mockProjects[0].name_with_namespace);
+ });
+
+ it('renders string "No matching results" when search does not yield any matches', async () => {
+ wrapper.setData({
+ searchKey: 'foo',
+ });
+
+ // Wait for `searchKey` watcher to run.
+ await wrapper.vm.$nextTick();
+
+ wrapper.setData({
+ projects: [],
+ projectsListLoading: false,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const dropdownContentEl = wrapper.find('[data-testid="content"]');
+
+ expect(dropdownContentEl.text()).toContain('No matching results');
+ });
+
+ it('renders string "Failed to load projects" when loading projects list fails', async () => {
+ wrapper.setData({
+ projects: [],
+ projectsListLoading: false,
+ projectsListLoadFailed: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const dropdownContentEl = wrapper.find('[data-testid="content"]');
+
+ expect(dropdownContentEl.text()).toContain('Failed to load projects');
+ });
+
+ it('renders gl-button within footer', async () => {
+ const moveButtonEl = wrapper.find('[data-testid="footer"]').find(GlButton);
+
+ expect(moveButtonEl.text()).toBe('Move');
+ expect(moveButtonEl.attributes('disabled')).toBe('true');
+
+ wrapper.setData({
+ selectedProject: mockProjects[0],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(
+ wrapper
+ .find('[data-testid="footer"]')
+ .find(GlButton)
+ .attributes('disabled'),
+ ).not.toBeDefined();
+ });
+ });
+
+ describe('events', () => {
+ it('collapsed state element emits `toggle-collapse` event on component when clicked', () => {
+ wrapper.find('[data-testid="move-collapsed"]').trigger('click');
+
+ expect(wrapper.emitted('toggle-collapse')).toBeTruthy();
+ });
+
+ it('gl-dropdown component calls `fetchProjects` on `shown` event', () => {
+ jest.spyOn(axios, 'get').mockResolvedValue({
+ data: mockProjects,
+ });
+
+ findDropdownEl().vm.$emit('shown');
+
+ expect(axios.get).toHaveBeenCalled();
+ });
+
+ it('gl-dropdown component prevents dropdown body from closing on `hide` event when `projectItemClick` prop is true', async () => {
+ wrapper.setData({
+ projectItemClick: true,
+ });
+
+ findDropdownEl().vm.$emit('hide', mockEvent);
+
+ expect(mockEvent.preventDefault).toHaveBeenCalled();
+ expect(wrapper.vm.projectItemClick).toBe(false);
+ });
+
+ it('gl-dropdown component emits `dropdown-close` event on component from `hide` event', async () => {
+ findDropdownEl().vm.$emit('hide');
+
+ expect(wrapper.emitted('dropdown-close')).toBeTruthy();
+ });
+
+ it('close icon in dropdown header closes the dropdown when clicked', () => {
+ wrapper
+ .find('[data-testid="header"]')
+ .find(GlButton)
+ .vm.$emit('click', mockEvent);
+
+ expect(wrapper.vm.$refs.dropdown.hide).toHaveBeenCalled();
+ });
+
+ it('sets project for clicked gl-dropdown-item to selectedProject', async () => {
+ wrapper.setData({
+ projects: mockProjects,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ wrapper
+ .findAll(GlDropdownItem)
+ .at(0)
+ .vm.$emit('click', mockEvent);
+
+ expect(wrapper.vm.selectedProject).toBe(mockProjects[0]);
+ });
+
+ it('hides dropdown and emits `move-issuable` event when move button is clicked', async () => {
+ wrapper.setData({
+ selectedProject: mockProjects[0],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ wrapper
+ .find('[data-testid="footer"]')
+ .find(GlButton)
+ .vm.$emit('click');
+
+ expect(wrapper.vm.$refs.dropdown.hide).toHaveBeenCalled();
+ expect(wrapper.emitted('move-issuable')).toBeTruthy();
+ expect(wrapper.emitted('move-issuable')[0]).toEqual([mockProjects[0]]);
+ });
+ });
+ });
+});
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 7847e0ee71d..71c040c6633 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
@@ -81,9 +81,7 @@ describe('DropdownValueCollapsedComponent', () => {
describe('template', () => {
it('renders component container element with tooltip`', () => {
- expect(vm.$el.dataset.placement).toBe('left');
- expect(vm.$el.dataset.container).toBe('body');
- expect(vm.$el.dataset.originalTitle).toBe(vm.labelsList);
+ expect(vm.$el.title).toBe(vm.labelsList);
});
it('renders tags icon element', () => {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
index e8a126d8774..78367b3a5b4 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
@@ -128,6 +128,16 @@ describe('DropdownContentsLabelsView', () => {
});
});
+ describe('handleComponentAppear', () => {
+ it('calls `focusInput` on searchInput field', async () => {
+ wrapper.vm.$refs.searchInput.focusInput = jest.fn();
+
+ await wrapper.vm.handleComponentAppear();
+
+ expect(wrapper.vm.$refs.searchInput.focusInput).toHaveBeenCalled();
+ });
+ });
+
describe('handleComponentDisappear', () => {
it('calls action `receiveLabelsSuccess` with empty array', () => {
jest.spyOn(wrapper.vm, 'receiveLabelsSuccess');
@@ -301,7 +311,6 @@ describe('DropdownContentsLabelsView', () => {
const searchInputEl = wrapper.find(GlSearchBoxByType);
expect(searchInputEl.exists()).toBe(true);
- expect(searchInputEl.attributes('autofocus')).toBe('true');
});
it('renders label elements for all labels', () => {
diff --git a/spec/frontend/vue_shared/components/stacked_progress_bar_spec.js b/spec/frontend/vue_shared/components/stacked_progress_bar_spec.js
index bc86ee5a0c6..0786882f527 100644
--- a/spec/frontend/vue_shared/components/stacked_progress_bar_spec.js
+++ b/spec/frontend/vue_shared/components/stacked_progress_bar_spec.js
@@ -29,6 +29,13 @@ describe('StackedProgressBarComponent', () => {
vm.$destroy();
});
+ const findSuccessBarText = wrapper => wrapper.$el.querySelector('.status-green').innerText.trim();
+ const findNeutralBarText = wrapper =>
+ wrapper.$el.querySelector('.status-neutral').innerText.trim();
+ const findFailureBarText = wrapper => wrapper.$el.querySelector('.status-red').innerText.trim();
+ const findUnavailableBarText = wrapper =>
+ wrapper.$el.querySelector('.status-unavailable').innerText.trim();
+
describe('computed', () => {
describe('neutralCount', () => {
it('returns neutralCount based on totalCount, successCount and failureCount', () => {
@@ -37,24 +44,54 @@ describe('StackedProgressBarComponent', () => {
});
});
- describe('methods', () => {
+ describe('template', () => {
+ it('renders container element', () => {
+ expect(vm.$el.classList.contains('stacked-progress-bar')).toBeTruthy();
+ });
+
+ it('renders empty state when count is unavailable', () => {
+ const vmX = createComponent({ totalCount: 0, successCount: 0, failureCount: 0 });
+
+ expect(findUnavailableBarText(vmX)).not.toBeUndefined();
+ });
+
+ it('renders bar elements when count is available', () => {
+ expect(findSuccessBarText(vm)).not.toBeUndefined();
+ expect(findNeutralBarText(vm)).not.toBeUndefined();
+ expect(findFailureBarText(vm)).not.toBeUndefined();
+ });
+
describe('getPercent', () => {
- it('returns percentage from provided count based on `totalCount`', () => {
- expect(vm.getPercent(500)).toBe(10);
+ it('returns correct percentages from provided count based on `totalCount`', () => {
+ vm = createComponent({ totalCount: 100, successCount: 25, failureCount: 10 });
+
+ expect(findSuccessBarText(vm)).toBe('25%');
+ expect(findNeutralBarText(vm)).toBe('65%');
+ expect(findFailureBarText(vm)).toBe('10%');
});
- it('returns percentage with decimal place from provided count based on `totalCount`', () => {
- expect(vm.getPercent(67)).toBe(1.3);
+ it('returns percentage with decimal place when decimal is greater than 1', () => {
+ vm = createComponent({ successCount: 67 });
+
+ expect(findSuccessBarText(vm)).toBe('1.3%');
});
- it('returns percentage as `< 1` from provided count based on `totalCount` when evaluated value is less than 1', () => {
- expect(vm.getPercent(10)).toBe('< 1');
+ it('returns percentage as `< 1%` from provided count based on `totalCount` when evaluated value is less than 1', () => {
+ vm = createComponent({ successCount: 10 });
+
+ expect(findSuccessBarText(vm)).toBe('< 1%');
});
- it('returns 0 if totalCount is falsy', () => {
+ it('returns not available if totalCount is falsy', () => {
vm = createComponent({ totalCount: 0 });
- expect(vm.getPercent(100)).toBe(0);
+ expect(findUnavailableBarText(vm)).toBe('Not available');
+ });
+
+ it('returns 99.9% when numbers are extreme decimals', () => {
+ vm = createComponent({ totalCount: 1000000 });
+
+ expect(findNeutralBarText(vm)).toBe('99.9%');
});
});
@@ -82,23 +119,4 @@ describe('StackedProgressBarComponent', () => {
});
});
});
-
- describe('template', () => {
- it('renders container element', () => {
- expect(vm.$el.classList.contains('stacked-progress-bar')).toBeTruthy();
- });
-
- it('renders empty state when count is unavailable', () => {
- const vmX = createComponent({ totalCount: 0, successCount: 0, failureCount: 0 });
-
- expect(vmX.$el.querySelectorAll('.status-unavailable').length).not.toBe(0);
- vmX.$destroy();
- });
-
- it('renders bar elements when count is available', () => {
- expect(vm.$el.querySelectorAll('.status-green').length).not.toBe(0);
- expect(vm.$el.querySelectorAll('.status-neutral').length).not.toBe(0);
- expect(vm.$el.querySelectorAll('.status-red').length).not.toBe(0);
- });
- });
});
diff --git a/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap b/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap
new file mode 100644
index 00000000000..d2fe3cd76cb
--- /dev/null
+++ b/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap
@@ -0,0 +1,608 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Upload dropzone component correctly overrides description and drop messages 1`] = `
+<div
+ class="gl-w-full gl-relative"
+>
+ <button
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ >
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
+ data-testid="dropzone-area"
+ >
+ <gl-icon-stub
+ class="gl-mb-2"
+ name="upload"
+ size="24"
+ />
+
+ <p
+ class="gl-mb-0"
+ >
+ <span>
+ Test %{linkStart}description%{linkEnd} message.
+ </span>
+ </p>
+ </div>
+ </button>
+
+ <input
+ accept="image/jpg,image/jpeg"
+ class="hide"
+ multiple="multiple"
+ name="upload_file"
+ type="file"
+ />
+
+ <transition-stub
+ name="upload-dropzone-fade"
+ >
+ <div
+ class="card upload-dropzone-border upload-dropzone-overlay gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
+ style="display: none;"
+ >
+ <div
+ class="mw-50 gl-text-center"
+ >
+ <h3
+ class=""
+ >
+
+ 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 gl-text-center"
+ style="display: none;"
+ >
+ <h3
+ class=""
+ >
+
+ Incoming!
+
+ </h3>
+
+ <span>
+ Test drop-to-start message.
+ </span>
+ </div>
+ </div>
+ </transition-stub>
+</div>
+`;
+
+exports[`Upload dropzone component when dragging renders correct template when drag event contains files 1`] = `
+<div
+ class="gl-w-full gl-relative"
+>
+ <button
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ >
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
+ data-testid="dropzone-area"
+ >
+ <gl-icon-stub
+ class="gl-mb-2"
+ name="upload"
+ size="24"
+ />
+
+ <p
+ class="gl-mb-0"
+ >
+ <gl-sprintf-stub
+ message="Drop or %{linkStart}upload%{linkEnd} files to attach"
+ />
+ </p>
+ </div>
+ </button>
+
+ <input
+ accept="image/*"
+ class="hide"
+ multiple="multiple"
+ name="upload_file"
+ type="file"
+ />
+
+ <transition-stub
+ name="upload-dropzone-fade"
+ >
+ <div
+ class="card upload-dropzone-border upload-dropzone-overlay gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
+ style=""
+ >
+ <div
+ class="mw-50 gl-text-center"
+ style="display: none;"
+ >
+ <h3
+ class=""
+ >
+
+ 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 gl-text-center"
+ style=""
+ >
+ <h3
+ class=""
+ >
+
+ Incoming!
+
+ </h3>
+
+ <span>
+ Drop your files to start your upload.
+ </span>
+ </div>
+ </div>
+ </transition-stub>
+</div>
+`;
+
+exports[`Upload dropzone component when dragging renders correct template when drag event contains files and text 1`] = `
+<div
+ class="gl-w-full gl-relative"
+>
+ <button
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ >
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
+ data-testid="dropzone-area"
+ >
+ <gl-icon-stub
+ class="gl-mb-2"
+ name="upload"
+ size="24"
+ />
+
+ <p
+ class="gl-mb-0"
+ >
+ <gl-sprintf-stub
+ message="Drop or %{linkStart}upload%{linkEnd} files to attach"
+ />
+ </p>
+ </div>
+ </button>
+
+ <input
+ accept="image/*"
+ class="hide"
+ multiple="multiple"
+ name="upload_file"
+ type="file"
+ />
+
+ <transition-stub
+ name="upload-dropzone-fade"
+ >
+ <div
+ class="card upload-dropzone-border upload-dropzone-overlay gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
+ style=""
+ >
+ <div
+ class="mw-50 gl-text-center"
+ style="display: none;"
+ >
+ <h3
+ class=""
+ >
+
+ 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 gl-text-center"
+ style=""
+ >
+ <h3
+ class=""
+ >
+
+ Incoming!
+
+ </h3>
+
+ <span>
+ Drop your files to start your upload.
+ </span>
+ </div>
+ </div>
+ </transition-stub>
+</div>
+`;
+
+exports[`Upload dropzone component when dragging renders correct template when drag event contains text 1`] = `
+<div
+ class="gl-w-full gl-relative"
+>
+ <button
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ >
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
+ data-testid="dropzone-area"
+ >
+ <gl-icon-stub
+ class="gl-mb-2"
+ name="upload"
+ size="24"
+ />
+
+ <p
+ class="gl-mb-0"
+ >
+ <gl-sprintf-stub
+ message="Drop or %{linkStart}upload%{linkEnd} files to attach"
+ />
+ </p>
+ </div>
+ </button>
+
+ <input
+ accept="image/*"
+ class="hide"
+ multiple="multiple"
+ name="upload_file"
+ type="file"
+ />
+
+ <transition-stub
+ name="upload-dropzone-fade"
+ >
+ <div
+ class="card upload-dropzone-border upload-dropzone-overlay gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
+ style=""
+ >
+ <div
+ class="mw-50 gl-text-center"
+ >
+ <h3
+ class=""
+ >
+
+ 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 gl-text-center"
+ style="display: none;"
+ >
+ <h3
+ class=""
+ >
+
+ Incoming!
+
+ </h3>
+
+ <span>
+ Drop your files to start your upload.
+ </span>
+ </div>
+ </div>
+ </transition-stub>
+</div>
+`;
+
+exports[`Upload dropzone component when dragging renders correct template when drag event is empty 1`] = `
+<div
+ class="gl-w-full gl-relative"
+>
+ <button
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ >
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
+ data-testid="dropzone-area"
+ >
+ <gl-icon-stub
+ class="gl-mb-2"
+ name="upload"
+ size="24"
+ />
+
+ <p
+ class="gl-mb-0"
+ >
+ <gl-sprintf-stub
+ message="Drop or %{linkStart}upload%{linkEnd} files to attach"
+ />
+ </p>
+ </div>
+ </button>
+
+ <input
+ accept="image/*"
+ class="hide"
+ multiple="multiple"
+ name="upload_file"
+ type="file"
+ />
+
+ <transition-stub
+ name="upload-dropzone-fade"
+ >
+ <div
+ class="card upload-dropzone-border upload-dropzone-overlay gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
+ style=""
+ >
+ <div
+ class="mw-50 gl-text-center"
+ >
+ <h3
+ class=""
+ >
+
+ 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 gl-text-center"
+ style="display: none;"
+ >
+ <h3
+ class=""
+ >
+
+ Incoming!
+
+ </h3>
+
+ <span>
+ Drop your files to start your upload.
+ </span>
+ </div>
+ </div>
+ </transition-stub>
+</div>
+`;
+
+exports[`Upload dropzone component when dragging renders correct template when dragging stops 1`] = `
+<div
+ class="gl-w-full gl-relative"
+>
+ <button
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ >
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
+ data-testid="dropzone-area"
+ >
+ <gl-icon-stub
+ class="gl-mb-2"
+ name="upload"
+ size="24"
+ />
+
+ <p
+ class="gl-mb-0"
+ >
+ <gl-sprintf-stub
+ message="Drop or %{linkStart}upload%{linkEnd} files to attach"
+ />
+ </p>
+ </div>
+ </button>
+
+ <input
+ accept="image/*"
+ class="hide"
+ multiple="multiple"
+ name="upload_file"
+ type="file"
+ />
+
+ <transition-stub
+ name="upload-dropzone-fade"
+ >
+ <div
+ class="card upload-dropzone-border upload-dropzone-overlay gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
+ style="display: none;"
+ >
+ <div
+ class="mw-50 gl-text-center"
+ >
+ <h3
+ class=""
+ >
+
+ 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 gl-text-center"
+ style="display: none;"
+ >
+ <h3
+ class=""
+ >
+
+ Incoming!
+
+ </h3>
+
+ <span>
+ Drop your files to start your upload.
+ </span>
+ </div>
+ </div>
+ </transition-stub>
+</div>
+`;
+
+exports[`Upload dropzone component when no slot provided renders default dropzone card 1`] = `
+<div
+ class="gl-w-full gl-relative"
+>
+ <button
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ >
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
+ data-testid="dropzone-area"
+ >
+ <gl-icon-stub
+ class="gl-mb-2"
+ name="upload"
+ size="24"
+ />
+
+ <p
+ class="gl-mb-0"
+ >
+ <gl-sprintf-stub
+ message="Drop or %{linkStart}upload%{linkEnd} files to attach"
+ />
+ </p>
+ </div>
+ </button>
+
+ <input
+ accept="image/*"
+ class="hide"
+ multiple="multiple"
+ name="upload_file"
+ type="file"
+ />
+
+ <transition-stub
+ name="upload-dropzone-fade"
+ >
+ <div
+ class="card upload-dropzone-border upload-dropzone-overlay gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
+ style="display: none;"
+ >
+ <div
+ class="mw-50 gl-text-center"
+ >
+ <h3
+ class=""
+ >
+
+ 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 gl-text-center"
+ style="display: none;"
+ >
+ <h3
+ class=""
+ >
+
+ Incoming!
+
+ </h3>
+
+ <span>
+ Drop your files to start your upload.
+ </span>
+ </div>
+ </div>
+ </transition-stub>
+</div>
+`;
+
+exports[`Upload dropzone component when slot provided renders dropzone with slot content 1`] = `
+<div
+ class="gl-w-full gl-relative"
+>
+ <div>
+ dropzone slot
+ </div>
+
+ <transition-stub
+ name="upload-dropzone-fade"
+ >
+ <div
+ class="card upload-dropzone-border upload-dropzone-overlay gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
+ style="display: none;"
+ >
+ <div
+ class="mw-50 gl-text-center"
+ >
+ <h3
+ class=""
+ >
+
+ 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 gl-text-center"
+ style="display: none;"
+ >
+ <h3
+ class=""
+ >
+
+ Incoming!
+
+ </h3>
+
+ <span>
+ Drop your files to start your upload.
+ </span>
+ </div>
+ </div>
+ </transition-stub>
+</div>
+`;
diff --git a/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js b/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
new file mode 100644
index 00000000000..11982eb513d
--- /dev/null
+++ b/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
@@ -0,0 +1,174 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
+import UploadDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
+
+jest.mock('~/flash');
+
+describe('Upload dropzone component', () => {
+ let wrapper;
+
+ const mockDragEvent = ({ types = ['Files'], files = [] }) => {
+ return { dataTransfer: { types, files } };
+ };
+
+ const findDropzoneCard = () => wrapper.find('.upload-dropzone-card');
+ const findDropzoneArea = () => wrapper.find('[data-testid="dropzone-area"]');
+ const findIcon = () => wrapper.find(GlIcon);
+
+ function createComponent({ slots = {}, data = {}, props = {} } = {}) {
+ wrapper = shallowMount(UploadDropzone, {
+ slots,
+ propsData: {
+ displayAsCard: true,
+ ...props,
+ },
+ 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('emits error event when files are invalid', () => {
+ createComponent({ data: mockData });
+ const mockEvent = mockDragEvent({ files: [{ type: 'audio/midi' }] });
+
+ wrapper.vm.ondrop(mockEvent);
+ expect(wrapper.emitted()).toHaveProperty('error');
+ });
+
+ it('allows validation function to be overwritten', () => {
+ createComponent({ data: mockData, props: { isFileValid: () => true } });
+
+ const mockEvent = mockDragEvent({ files: [{ type: 'audio/midi' }] });
+
+ wrapper.vm.ondrop(mockEvent);
+ expect(wrapper.emitted()).not.toHaveProperty('error');
+ });
+ });
+ });
+
+ it('applies correct classes when displaying as a standalone item', () => {
+ createComponent({ props: { displayAsCard: false } });
+ expect(findDropzoneArea().classes()).not.toContain('gl-flex-direction-column');
+ expect(findIcon().classes()).toEqual(['gl-mr-3', 'gl-text-gray-500']);
+ expect(findIcon().props('size')).toBe(16);
+ });
+
+ it('applies correct classes when displaying in card mode', () => {
+ createComponent({ props: { displayAsCard: true } });
+ expect(findDropzoneArea().classes()).toContain('gl-flex-direction-column');
+ expect(findIcon().classes()).toEqual(['gl-mb-2']);
+ expect(findIcon().props('size')).toBe(24);
+ });
+
+ it('correctly overrides description and drop messages', () => {
+ createComponent({
+ props: {
+ dropToStartMessage: 'Test drop-to-start message.',
+ validFileMimetypes: ['image/jpg', 'image/jpeg'],
+ },
+ slots: {
+ 'upload-text': '<span>Test %{linkStart}description%{linkEnd} message.</span>',
+ },
+ });
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
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 c208d7b0226..7d58a865ba3 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,6 +1,8 @@
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlSprintf, GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import UserPopover from '~/vue_shared/components/user_popover/user_popover.vue';
+import UserAvailabilityStatus from '~/set_status_modal/components/user_availability_status.vue';
+import { AVAILABILITY_STATUS } from '~/set_status_modal/utils';
const DEFAULT_PROPS = {
user: {
@@ -34,6 +36,7 @@ describe('User Popover Component', () => {
const findByTestId = testid => wrapper.find(`[data-testid="${testid}"]`);
const findUserStatus = () => wrapper.find('.js-user-status');
const findTarget = () => document.querySelector('.js-user-link');
+ const findAvailabilityStatus = () => wrapper.find(UserAvailabilityStatus);
const createWrapper = (props = {}, options = {}) => {
wrapper = shallowMount(UserPopover, {
@@ -43,7 +46,8 @@ describe('User Popover Component', () => {
...props,
},
stubs: {
- 'gl-sprintf': GlSprintf,
+ GlSprintf,
+ UserAvailabilityStatus,
},
...options,
});
@@ -199,6 +203,30 @@ describe('User Popover Component', () => {
expect(findUserStatus().exists()).toBe(false);
});
+
+ it('should show the busy status if user set to busy', () => {
+ const user = {
+ ...DEFAULT_PROPS.user,
+ status: { availability: AVAILABILITY_STATUS.BUSY },
+ };
+
+ createWrapper({ user });
+
+ expect(findAvailabilityStatus().exists()).toBe(true);
+ expect(wrapper.text()).toContain(user.name);
+ expect(wrapper.text()).toContain('(Busy)');
+ });
+
+ it('should hide the busy status for any other status', () => {
+ const user = {
+ ...DEFAULT_PROPS.user,
+ status: { availability: AVAILABILITY_STATUS.NOT_SET },
+ };
+
+ createWrapper({ user });
+
+ expect(wrapper.text()).not.toContain('(Busy)');
+ });
});
describe('security bot', () => {
diff --git a/spec/frontend/vue_shared/directives/validation_spec.js b/spec/frontend/vue_shared/directives/validation_spec.js
new file mode 100644
index 00000000000..814d6f43589
--- /dev/null
+++ b/spec/frontend/vue_shared/directives/validation_spec.js
@@ -0,0 +1,132 @@
+import { shallowMount } from '@vue/test-utils';
+import validation from '~/vue_shared/directives/validation';
+
+describe('validation directive', () => {
+ let wrapper;
+
+ const createComponent = ({ inputAttributes, showValidation } = {}) => {
+ const defaultInputAttributes = {
+ type: 'text',
+ required: true,
+ };
+
+ const component = {
+ directives: {
+ validation: validation(),
+ },
+ data() {
+ return {
+ attributes: inputAttributes || defaultInputAttributes,
+ showValidation,
+ form: {
+ state: null,
+ fields: {
+ exampleField: {
+ state: null,
+ feedback: '',
+ },
+ },
+ },
+ };
+ },
+ template: `
+ <form>
+ <input v-validation:[showValidation] name="exampleField" v-bind="attributes" />
+ </form>
+ `,
+ };
+
+ wrapper = shallowMount(component, { attachToDocument: true });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const getFormData = () => wrapper.vm.form;
+ const findForm = () => wrapper.find('form');
+ const findInput = () => wrapper.find('input');
+
+ describe.each([true, false])(
+ 'with fields untouched and "showValidation" set to "%s"',
+ showValidation => {
+ beforeEach(() => {
+ createComponent({ showValidation });
+ });
+
+ it('sets the fields validity correctly', () => {
+ expect(getFormData().fields.exampleField).toEqual({
+ state: showValidation ? false : null,
+ feedback: showValidation ? expect.any(String) : '',
+ });
+ });
+
+ it('sets the form validity correctly', () => {
+ expect(getFormData().state).toBe(false);
+ });
+ },
+ );
+
+ describe.each`
+ inputAttributes | validValue | invalidValue
+ ${{ required: true }} | ${'foo'} | ${''}
+ ${{ type: 'url' }} | ${'http://foo.com'} | ${'foo'}
+ ${{ type: 'number', min: 1, max: 5 }} | ${3} | ${0}
+ ${{ type: 'number', min: 1, max: 5 }} | ${3} | ${6}
+ ${{ pattern: 'foo|bar' }} | ${'bar'} | ${'quz'}
+ `(
+ 'with input-attributes set to $inputAttributes',
+ ({ inputAttributes, validValue, invalidValue }) => {
+ const setValueAndTriggerValidation = value => {
+ const input = findInput();
+ input.setValue(value);
+ input.trigger('blur');
+ };
+
+ beforeEach(() => {
+ createComponent({ inputAttributes });
+ });
+
+ describe('with valid value', () => {
+ beforeEach(() => {
+ setValueAndTriggerValidation(validValue);
+ });
+
+ it('sets the field to be valid', () => {
+ expect(getFormData().fields.exampleField).toEqual({
+ state: true,
+ feedback: '',
+ });
+ });
+
+ it('sets the form to be valid', () => {
+ expect(getFormData().state).toBe(true);
+ });
+ });
+
+ describe('with invalid value', () => {
+ beforeEach(() => {
+ setValueAndTriggerValidation(invalidValue);
+ });
+
+ it('sets the field to be invalid', () => {
+ expect(getFormData().fields.exampleField).toEqual({
+ state: false,
+ feedback: expect.any(String),
+ });
+ expect(getFormData().fields.exampleField.feedback.length).toBeGreaterThan(0);
+ });
+
+ it('sets the form to be invalid', () => {
+ expect(getFormData().state).toBe(false);
+ });
+
+ it('sets focus on the first invalid input when the form is submitted', () => {
+ findForm().trigger('submit');
+ expect(findInput().element).toBe(document.activeElement);
+ });
+ });
+ },
+ );
+});
diff --git a/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js b/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js
index 31bdfc931ac..ab87d80b291 100644
--- a/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js
+++ b/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js
@@ -5,7 +5,7 @@ import SecurityReportsApp from '~/vue_shared/security_reports/security_reports_a
jest.mock('~/flash');
-describe('Grouped security reports app', () => {
+describe('Security reports app', () => {
let wrapper;
let mrTabsMock;
@@ -21,6 +21,8 @@ describe('Grouped security reports app', () => {
});
};
+ const anyParams = expect.any(Object);
+
const findPipelinesTabAnchor = () => wrapper.find('[data-testid="show-pipelines"]');
const findHelpLink = () => wrapper.find('[data-testid="help"]');
const setupMrTabsMock = () => {
@@ -43,10 +45,12 @@ describe('Grouped security reports app', () => {
window.mrTabs = { tabShown: jest.fn() };
setupMockJobArtifact(reportType);
createComponent();
+ return wrapper.vm.$nextTick();
});
it('calls the pipelineJobs API correctly', () => {
- expect(Api.pipelineJobs).toHaveBeenCalledWith(props.projectId, props.pipelineId);
+ expect(Api.pipelineJobs).toHaveBeenCalledTimes(1);
+ expect(Api.pipelineJobs).toHaveBeenCalledWith(props.projectId, props.pipelineId, anyParams);
});
it('renders the expected message', () => {
@@ -75,10 +79,12 @@ describe('Grouped security reports app', () => {
beforeEach(() => {
setupMockJobArtifact('foo');
createComponent();
+ return wrapper.vm.$nextTick();
});
it('calls the pipelineJobs API correctly', () => {
- expect(Api.pipelineJobs).toHaveBeenCalledWith(props.projectId, props.pipelineId);
+ expect(Api.pipelineJobs).toHaveBeenCalledTimes(1);
+ expect(Api.pipelineJobs).toHaveBeenCalledWith(props.projectId, props.pipelineId, anyParams);
});
it('renders nothing', () => {
@@ -86,6 +92,42 @@ describe('Grouped security reports app', () => {
});
});
+ describe('security artifacts on last page of multi-page response', () => {
+ const numPages = 3;
+
+ beforeEach(() => {
+ jest
+ .spyOn(Api, 'pipelineJobs')
+ .mockImplementation(async (projectId, pipelineId, { page }) => {
+ const requestedPage = parseInt(page, 10);
+ if (requestedPage < numPages) {
+ return {
+ // Some jobs with no relevant artifacts
+ data: [{}, {}],
+ headers: { 'x-next-page': String(requestedPage + 1) },
+ };
+ } else if (requestedPage === numPages) {
+ return {
+ data: [{ artifacts: [{ file_type: SecurityReportsApp.reportTypes[0] }] }],
+ };
+ }
+
+ throw new Error('Test failed due to request of non-existent jobs page');
+ });
+
+ createComponent();
+ return wrapper.vm.$nextTick();
+ });
+
+ it('fetches all pages', () => {
+ expect(Api.pipelineJobs).toHaveBeenCalledTimes(numPages);
+ });
+
+ it('renders the expected message', () => {
+ expect(wrapper.text()).toMatchInterpolatedText(SecurityReportsApp.i18n.scansHaveRun);
+ });
+ });
+
describe('given an error from the API', () => {
let error;
@@ -93,10 +135,12 @@ describe('Grouped security reports app', () => {
error = new Error('an error');
jest.spyOn(Api, 'pipelineJobs').mockRejectedValue(error);
createComponent();
+ return wrapper.vm.$nextTick();
});
it('calls the pipelineJobs API correctly', () => {
- expect(Api.pipelineJobs).toHaveBeenCalledWith(props.projectId, props.pipelineId);
+ expect(Api.pipelineJobs).toHaveBeenCalledTimes(1);
+ expect(Api.pipelineJobs).toHaveBeenCalledWith(props.projectId, props.pipelineId, anyParams);
});
it('renders nothing', () => {
diff --git a/spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js b/spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js
new file mode 100644
index 00000000000..a11f4e05913
--- /dev/null
+++ b/spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js
@@ -0,0 +1,203 @@
+import MockAdapter from 'axios-mock-adapter';
+import testAction from 'helpers/vuex_action_helper';
+
+import createState from '~/vue_shared/security_reports/store/modules/sast/state';
+import * as types from '~/vue_shared/security_reports/store/modules/sast/mutation_types';
+import * as actions from '~/vue_shared/security_reports/store/modules/sast/actions';
+import axios from '~/lib/utils/axios_utils';
+
+const diffEndpoint = 'diff-endpoint.json';
+const blobPath = 'blob-path.json';
+const reports = {
+ base: 'base',
+ head: 'head',
+ enrichData: 'enrichData',
+ diff: 'diff',
+};
+const error = 'Something went wrong';
+const vulnerabilityFeedbackPath = 'vulnerability-feedback-path';
+const rootState = { vulnerabilityFeedbackPath, blobPath };
+
+let state;
+
+describe('sast report actions', () => {
+ beforeEach(() => {
+ state = createState();
+ });
+
+ describe('setDiffEndpoint', () => {
+ it(`should commit ${types.SET_DIFF_ENDPOINT} with the correct path`, done => {
+ testAction(
+ actions.setDiffEndpoint,
+ diffEndpoint,
+ state,
+ [
+ {
+ type: types.SET_DIFF_ENDPOINT,
+ payload: diffEndpoint,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('requestDiff', () => {
+ it(`should commit ${types.REQUEST_DIFF}`, done => {
+ testAction(actions.requestDiff, {}, state, [{ type: types.REQUEST_DIFF }], [], done);
+ });
+ });
+
+ describe('receiveDiffSuccess', () => {
+ it(`should commit ${types.RECEIVE_DIFF_SUCCESS} with the correct response`, done => {
+ testAction(
+ actions.receiveDiffSuccess,
+ reports,
+ state,
+ [
+ {
+ type: types.RECEIVE_DIFF_SUCCESS,
+ payload: reports,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveDiffError', () => {
+ it(`should commit ${types.RECEIVE_DIFF_ERROR} with the correct response`, done => {
+ testAction(
+ actions.receiveDiffError,
+ error,
+ state,
+ [
+ {
+ type: types.RECEIVE_DIFF_ERROR,
+ payload: error,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('fetchDiff', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ state.paths.diffEndpoint = diffEndpoint;
+ rootState.canReadVulnerabilityFeedback = true;
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('when diff and vulnerability feedback endpoints respond successfully', () => {
+ beforeEach(() => {
+ mock
+ .onGet(diffEndpoint)
+ .replyOnce(200, reports.diff)
+ .onGet(vulnerabilityFeedbackPath)
+ .replyOnce(200, reports.enrichData);
+ });
+
+ it('should dispatch the `receiveDiffSuccess` action', done => {
+ const { diff, enrichData } = reports;
+ testAction(
+ actions.fetchDiff,
+ {},
+ { ...rootState, ...state },
+ [],
+ [
+ { type: 'requestDiff' },
+ {
+ type: 'receiveDiffSuccess',
+ payload: {
+ diff,
+ enrichData,
+ },
+ },
+ ],
+ done,
+ );
+ });
+ });
+
+ describe('when diff endpoint responds successfully and fetching vulnerability feedback is not authorized', () => {
+ beforeEach(() => {
+ rootState.canReadVulnerabilityFeedback = false;
+ mock.onGet(diffEndpoint).replyOnce(200, reports.diff);
+ });
+
+ it('should dispatch the `receiveDiffSuccess` action with empty enrich data', done => {
+ const { diff } = reports;
+ const enrichData = [];
+ testAction(
+ actions.fetchDiff,
+ {},
+ { ...rootState, ...state },
+ [],
+ [
+ { type: 'requestDiff' },
+ {
+ type: 'receiveDiffSuccess',
+ payload: {
+ diff,
+ enrichData,
+ },
+ },
+ ],
+ done,
+ );
+ });
+ });
+
+ describe('when the vulnerability feedback endpoint fails', () => {
+ beforeEach(() => {
+ mock
+ .onGet(diffEndpoint)
+ .replyOnce(200, reports.diff)
+ .onGet(vulnerabilityFeedbackPath)
+ .replyOnce(404);
+ });
+
+ it('should dispatch the `receiveError` action', done => {
+ testAction(
+ actions.fetchDiff,
+ {},
+ { ...rootState, ...state },
+ [],
+ [{ type: 'requestDiff' }, { type: 'receiveDiffError' }],
+ done,
+ );
+ });
+ });
+
+ describe('when the diff endpoint fails', () => {
+ beforeEach(() => {
+ mock
+ .onGet(diffEndpoint)
+ .replyOnce(404)
+ .onGet(vulnerabilityFeedbackPath)
+ .replyOnce(200, reports.enrichData);
+ });
+
+ it('should dispatch the `receiveDiffError` action', done => {
+ testAction(
+ actions.fetchDiff,
+ {},
+ { ...rootState, ...state },
+ [],
+ [{ type: 'requestDiff' }, { type: 'receiveDiffError' }],
+ done,
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/security_reports/store/modules/sast/mutations_spec.js b/spec/frontend/vue_shared/security_reports/store/modules/sast/mutations_spec.js
new file mode 100644
index 00000000000..fd611f38a34
--- /dev/null
+++ b/spec/frontend/vue_shared/security_reports/store/modules/sast/mutations_spec.js
@@ -0,0 +1,84 @@
+import * as types from '~/vue_shared/security_reports/store/modules/sast/mutation_types';
+import createState from '~/vue_shared/security_reports/store/modules/sast/state';
+import mutations from '~/vue_shared/security_reports/store/modules/sast/mutations';
+
+const createIssue = ({ ...config }) => ({ changed: false, ...config });
+
+describe('sast module mutations', () => {
+ const path = 'path';
+ let state;
+
+ beforeEach(() => {
+ state = createState();
+ });
+
+ describe(types.SET_DIFF_ENDPOINT, () => {
+ it('should set the SAST diff endpoint', () => {
+ mutations[types.SET_DIFF_ENDPOINT](state, path);
+
+ expect(state.paths.diffEndpoint).toBe(path);
+ });
+ });
+
+ describe(types.REQUEST_DIFF, () => {
+ it('should set the `isLoading` status to `true`', () => {
+ mutations[types.REQUEST_DIFF](state);
+
+ expect(state.isLoading).toBe(true);
+ });
+ });
+
+ describe(types.RECEIVE_DIFF_SUCCESS, () => {
+ beforeEach(() => {
+ const reports = {
+ diff: {
+ added: [
+ createIssue({ cve: 'CVE-1' }),
+ createIssue({ cve: 'CVE-2' }),
+ createIssue({ cve: 'CVE-3' }),
+ ],
+ fixed: [createIssue({ cve: 'CVE-4' }), createIssue({ cve: 'CVE-5' })],
+ existing: [createIssue({ cve: 'CVE-6' })],
+ base_report_out_of_date: true,
+ },
+ };
+ state.isLoading = true;
+ mutations[types.RECEIVE_DIFF_SUCCESS](state, reports);
+ });
+
+ it('should set the `isLoading` status to `false`', () => {
+ expect(state.isLoading).toBe(false);
+ });
+
+ it('should set the `baseReportOutofDate` status to `false`', () => {
+ expect(state.baseReportOutofDate).toBe(true);
+ });
+
+ it('should have the relevant `new` issues', () => {
+ expect(state.newIssues).toHaveLength(3);
+ });
+
+ it('should have the relevant `resolved` issues', () => {
+ expect(state.resolvedIssues).toHaveLength(2);
+ });
+
+ it('should have the relevant `all` issues', () => {
+ expect(state.allIssues).toHaveLength(1);
+ });
+ });
+
+ describe(types.RECEIVE_DIFF_ERROR, () => {
+ beforeEach(() => {
+ state.isLoading = true;
+ mutations[types.RECEIVE_DIFF_ERROR](state);
+ });
+
+ it('should set the `isLoading` status to `false`', () => {
+ expect(state.isLoading).toBe(false);
+ });
+
+ it('should set the `hasError` status to `true`', () => {
+ expect(state.hasError).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js b/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js
new file mode 100644
index 00000000000..bbcdfb5cd99
--- /dev/null
+++ b/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js
@@ -0,0 +1,203 @@
+import MockAdapter from 'axios-mock-adapter';
+import testAction from 'helpers/vuex_action_helper';
+
+import createState from '~/vue_shared/security_reports/store/modules/secret_detection/state';
+import * as types from '~/vue_shared/security_reports/store/modules/secret_detection/mutation_types';
+import * as actions from '~/vue_shared/security_reports/store/modules/secret_detection/actions';
+import axios from '~/lib/utils/axios_utils';
+
+const diffEndpoint = 'diff-endpoint.json';
+const blobPath = 'blob-path.json';
+const reports = {
+ base: 'base',
+ head: 'head',
+ enrichData: 'enrichData',
+ diff: 'diff',
+};
+const error = 'Something went wrong';
+const vulnerabilityFeedbackPath = 'vulnerability-feedback-path';
+const rootState = { vulnerabilityFeedbackPath, blobPath };
+
+let state;
+
+describe('secret detection report actions', () => {
+ beforeEach(() => {
+ state = createState();
+ });
+
+ describe('setDiffEndpoint', () => {
+ it(`should commit ${types.SET_DIFF_ENDPOINT} with the correct path`, done => {
+ testAction(
+ actions.setDiffEndpoint,
+ diffEndpoint,
+ state,
+ [
+ {
+ type: types.SET_DIFF_ENDPOINT,
+ payload: diffEndpoint,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('requestDiff', () => {
+ it(`should commit ${types.REQUEST_DIFF}`, done => {
+ testAction(actions.requestDiff, {}, state, [{ type: types.REQUEST_DIFF }], [], done);
+ });
+ });
+
+ describe('receiveDiffSuccess', () => {
+ it(`should commit ${types.RECEIVE_DIFF_SUCCESS} with the correct response`, done => {
+ testAction(
+ actions.receiveDiffSuccess,
+ reports,
+ state,
+ [
+ {
+ type: types.RECEIVE_DIFF_SUCCESS,
+ payload: reports,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveDiffError', () => {
+ it(`should commit ${types.RECEIVE_DIFF_ERROR} with the correct response`, done => {
+ testAction(
+ actions.receiveDiffError,
+ error,
+ state,
+ [
+ {
+ type: types.RECEIVE_DIFF_ERROR,
+ payload: error,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('fetchDiff', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ state.paths.diffEndpoint = diffEndpoint;
+ rootState.canReadVulnerabilityFeedback = true;
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('when diff and vulnerability feedback endpoints respond successfully', () => {
+ beforeEach(() => {
+ mock
+ .onGet(diffEndpoint)
+ .replyOnce(200, reports.diff)
+ .onGet(vulnerabilityFeedbackPath)
+ .replyOnce(200, reports.enrichData);
+ });
+
+ it('should dispatch the `receiveDiffSuccess` action', done => {
+ const { diff, enrichData } = reports;
+ testAction(
+ actions.fetchDiff,
+ {},
+ { ...rootState, ...state },
+ [],
+ [
+ { type: 'requestDiff' },
+ {
+ type: 'receiveDiffSuccess',
+ payload: {
+ diff,
+ enrichData,
+ },
+ },
+ ],
+ done,
+ );
+ });
+ });
+
+ describe('when diff endpoint responds successfully and fetching vulnerability feedback is not authorized', () => {
+ beforeEach(() => {
+ rootState.canReadVulnerabilityFeedback = false;
+ mock.onGet(diffEndpoint).replyOnce(200, reports.diff);
+ });
+
+ it('should dispatch the `receiveDiffSuccess` action with empty enrich data', done => {
+ const { diff } = reports;
+ const enrichData = [];
+ testAction(
+ actions.fetchDiff,
+ {},
+ { ...rootState, ...state },
+ [],
+ [
+ { type: 'requestDiff' },
+ {
+ type: 'receiveDiffSuccess',
+ payload: {
+ diff,
+ enrichData,
+ },
+ },
+ ],
+ done,
+ );
+ });
+ });
+
+ describe('when the vulnerability feedback endpoint fails', () => {
+ beforeEach(() => {
+ mock
+ .onGet(diffEndpoint)
+ .replyOnce(200, reports.diff)
+ .onGet(vulnerabilityFeedbackPath)
+ .replyOnce(404);
+ });
+
+ it('should dispatch the `receiveDiffError` action', done => {
+ testAction(
+ actions.fetchDiff,
+ {},
+ { ...rootState, ...state },
+ [],
+ [{ type: 'requestDiff' }, { type: 'receiveDiffError' }],
+ done,
+ );
+ });
+ });
+
+ describe('when the diff endpoint fails', () => {
+ beforeEach(() => {
+ mock
+ .onGet(diffEndpoint)
+ .replyOnce(404)
+ .onGet(vulnerabilityFeedbackPath)
+ .replyOnce(200, reports.enrichData);
+ });
+
+ it('should dispatch the `receiveDiffError` action', done => {
+ testAction(
+ actions.fetchDiff,
+ {},
+ { ...rootState, ...state },
+ [],
+ [{ type: 'requestDiff' }, { type: 'receiveDiffError' }],
+ done,
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/mutations_spec.js b/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/mutations_spec.js
new file mode 100644
index 00000000000..13fcc0f47a3
--- /dev/null
+++ b/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/mutations_spec.js
@@ -0,0 +1,84 @@
+import * as types from '~/vue_shared/security_reports/store/modules/secret_detection/mutation_types';
+import createState from '~/vue_shared/security_reports/store/modules/secret_detection/state';
+import mutations from '~/vue_shared/security_reports/store/modules/secret_detection/mutations';
+
+const createIssue = ({ ...config }) => ({ changed: false, ...config });
+
+describe('secret detection module mutations', () => {
+ const path = 'path';
+ let state;
+
+ beforeEach(() => {
+ state = createState();
+ });
+
+ describe(types.SET_DIFF_ENDPOINT, () => {
+ it('should set the secret detection diff endpoint', () => {
+ mutations[types.SET_DIFF_ENDPOINT](state, path);
+
+ expect(state.paths.diffEndpoint).toBe(path);
+ });
+ });
+
+ describe(types.REQUEST_DIFF, () => {
+ it('should set the `isLoading` status to `true`', () => {
+ mutations[types.REQUEST_DIFF](state);
+
+ expect(state.isLoading).toBe(true);
+ });
+ });
+
+ describe(types.RECEIVE_DIFF_SUCCESS, () => {
+ beforeEach(() => {
+ const reports = {
+ diff: {
+ added: [
+ createIssue({ cve: 'CVE-1' }),
+ createIssue({ cve: 'CVE-2' }),
+ createIssue({ cve: 'CVE-3' }),
+ ],
+ fixed: [createIssue({ cve: 'CVE-4' }), createIssue({ cve: 'CVE-5' })],
+ existing: [createIssue({ cve: 'CVE-6' })],
+ base_report_out_of_date: true,
+ },
+ };
+ state.isLoading = true;
+ mutations[types.RECEIVE_DIFF_SUCCESS](state, reports);
+ });
+
+ it('should set the `isLoading` status to `false`', () => {
+ expect(state.isLoading).toBe(false);
+ });
+
+ it('should set the `baseReportOutofDate` status to `true`', () => {
+ expect(state.baseReportOutofDate).toBe(true);
+ });
+
+ it('should have the relevant `new` issues', () => {
+ expect(state.newIssues).toHaveLength(3);
+ });
+
+ it('should have the relevant `resolved` issues', () => {
+ expect(state.resolvedIssues).toHaveLength(2);
+ });
+
+ it('should have the relevant `all` issues', () => {
+ expect(state.allIssues).toHaveLength(1);
+ });
+ });
+
+ describe(types.RECEIVE_DIFF_ERROR, () => {
+ beforeEach(() => {
+ state.isLoading = true;
+ mutations[types.RECEIVE_DIFF_ERROR](state);
+ });
+
+ it('should set the `isLoading` status to `false`', () => {
+ expect(state.isLoading).toBe(false);
+ });
+
+ it('should set the `hasError` status to `true`', () => {
+ expect(state.hasError).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/vuex_shared/modules/members/actions_spec.js b/spec/frontend/vuex_shared/modules/members/actions_spec.js
index 833bd4cc175..c7048a9c421 100644
--- a/spec/frontend/vuex_shared/modules/members/actions_spec.js
+++ b/spec/frontend/vuex_shared/modules/members/actions_spec.js
@@ -3,79 +3,121 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { members, group } from 'jest/vue_shared/components/members/mock_data';
import testAction from 'helpers/vuex_action_helper';
+import { useFakeDate } from 'helpers/fake_date';
import httpStatusCodes from '~/lib/utils/http_status';
import * as types from '~/vuex_shared/modules/members/mutation_types';
import {
updateMemberRole,
showRemoveGroupLinkModal,
hideRemoveGroupLinkModal,
+ updateMemberExpiration,
} from '~/vuex_shared/modules/members/actions';
describe('Vuex members actions', () => {
- let mock;
+ describe('update member actions', () => {
+ let mock;
- beforeEach(() => {
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('updateMemberRole', () => {
- const memberId = members[0].id;
- const accessLevel = { integerValue: 30, stringValue: 'Developer' };
-
- const payload = {
- memberId,
- accessLevel,
- };
const state = {
members,
memberPath: '/groups/foo-bar/-/group_members/:id',
requestFormatter: noop,
- removeGroupLinkModalVisible: false,
- groupLinkToRemove: null,
};
- describe('successful request', () => {
- it(`commits ${types.RECEIVE_MEMBER_ROLE_SUCCESS} mutation`, async () => {
- let requestPath;
- mock.onPut().replyOnce(config => {
- requestPath = config.url;
- return [httpStatusCodes.OK, {}];
- });
-
- await testAction(updateMemberRole, payload, state, [
- {
- type: types.RECEIVE_MEMBER_ROLE_SUCCESS,
- payload,
- },
- ]);
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
- expect(requestPath).toBe('/groups/foo-bar/-/group_members/238');
- });
+ afterEach(() => {
+ mock.restore();
});
- describe('unsuccessful request', () => {
- beforeEach(() => {
- mock.onPut().replyOnce(httpStatusCodes.BAD_REQUEST, { message: 'Bad request' });
- });
+ describe('updateMemberRole', () => {
+ const memberId = members[0].id;
+ const accessLevel = { integerValue: 30, stringValue: 'Developer' };
+
+ const payload = {
+ memberId,
+ accessLevel,
+ };
+
+ describe('successful request', () => {
+ it(`commits ${types.RECEIVE_MEMBER_ROLE_SUCCESS} mutation`, async () => {
+ mock.onPut().replyOnce(httpStatusCodes.OK);
- it(`commits ${types.RECEIVE_MEMBER_ROLE_ERROR} mutation`, async () => {
- try {
await testAction(updateMemberRole, payload, state, [
{
type: types.RECEIVE_MEMBER_ROLE_SUCCESS,
+ payload,
},
]);
- } catch {
- // Do nothing
- }
+
+ expect(mock.history.put[0].url).toBe('/groups/foo-bar/-/group_members/238');
+ });
+ });
+
+ describe('unsuccessful request', () => {
+ it(`commits ${types.RECEIVE_MEMBER_ROLE_ERROR} mutation and throws error`, async () => {
+ mock.onPut().networkError();
+
+ await expect(
+ testAction(updateMemberRole, payload, state, [
+ {
+ type: types.RECEIVE_MEMBER_ROLE_ERROR,
+ },
+ ]),
+ ).rejects.toThrowError(new Error('Network Error'));
+ });
+ });
+ });
+
+ describe('updateMemberExpiration', () => {
+ useFakeDate(2020, 2, 15, 3);
+
+ const memberId = members[0].id;
+ const expiresAt = '2020-3-17';
+
+ describe('successful request', () => {
+ describe('changing expiration date', () => {
+ it(`commits ${types.RECEIVE_MEMBER_EXPIRATION_SUCCESS} mutation`, async () => {
+ mock.onPut().replyOnce(httpStatusCodes.OK);
+
+ await testAction(updateMemberExpiration, { memberId, expiresAt }, state, [
+ {
+ type: types.RECEIVE_MEMBER_EXPIRATION_SUCCESS,
+ payload: { memberId, expiresAt: '2020-03-17T00:00:00Z' },
+ },
+ ]);
+
+ expect(mock.history.put[0].url).toBe('/groups/foo-bar/-/group_members/238');
+ });
+ });
+
+ describe('removing the expiration date', () => {
+ it(`commits ${types.RECEIVE_MEMBER_EXPIRATION_SUCCESS} mutation`, async () => {
+ mock.onPut().replyOnce(httpStatusCodes.OK);
+
+ await testAction(updateMemberExpiration, { memberId, expiresAt: null }, state, [
+ {
+ type: types.RECEIVE_MEMBER_EXPIRATION_SUCCESS,
+ payload: { memberId, expiresAt: null },
+ },
+ ]);
+ });
+ });
});
- it('throws error', async () => {
- await expect(testAction(updateMemberRole, payload, state)).rejects.toThrowError();
+ describe('unsuccessful request', () => {
+ it(`commits ${types.RECEIVE_MEMBER_EXPIRATION_ERROR} mutation and throws error`, async () => {
+ mock.onPut().networkError();
+
+ await expect(
+ testAction(updateMemberExpiration, { memberId, expiresAt }, state, [
+ {
+ type: types.RECEIVE_MEMBER_EXPIRATION_ERROR,
+ },
+ ]),
+ ).rejects.toThrowError(new Error('Network Error'));
+ });
});
});
});
diff --git a/spec/frontend/vuex_shared/modules/members/mutations_spec.js b/spec/frontend/vuex_shared/modules/members/mutations_spec.js
index 7338b19cfc9..710d43b8990 100644
--- a/spec/frontend/vuex_shared/modules/members/mutations_spec.js
+++ b/spec/frontend/vuex_shared/modules/members/mutations_spec.js
@@ -3,36 +3,63 @@ import mutations from '~/vuex_shared/modules/members/mutations';
import * as types from '~/vuex_shared/modules/members/mutation_types';
describe('Vuex members mutations', () => {
- describe(types.RECEIVE_MEMBER_ROLE_SUCCESS, () => {
- it('updates member', () => {
- const state = {
+ describe('update member mutations', () => {
+ let state;
+
+ beforeEach(() => {
+ state = {
members,
+ showError: false,
+ errorMessage: '',
};
+ });
- const accessLevel = { integerValue: 30, stringValue: 'Developer' };
+ describe(types.RECEIVE_MEMBER_ROLE_SUCCESS, () => {
+ it('updates member', () => {
+ const accessLevel = { integerValue: 30, stringValue: 'Developer' };
- mutations[types.RECEIVE_MEMBER_ROLE_SUCCESS](state, {
- memberId: members[0].id,
- accessLevel,
+ mutations[types.RECEIVE_MEMBER_ROLE_SUCCESS](state, {
+ memberId: members[0].id,
+ accessLevel,
+ });
+
+ expect(state.members[0].accessLevel).toEqual(accessLevel);
});
+ });
+
+ describe(types.RECEIVE_MEMBER_ROLE_ERROR, () => {
+ it('shows error message', () => {
+ mutations[types.RECEIVE_MEMBER_ROLE_ERROR](state);
- expect(state.members[0].accessLevel).toEqual(accessLevel);
+ expect(state.showError).toBe(true);
+ expect(state.errorMessage).toBe(
+ "An error occurred while updating the member's role, please try again.",
+ );
+ });
});
- });
- describe(types.RECEIVE_MEMBER_ROLE_ERROR, () => {
- it('shows error message', () => {
- const state = {
- showError: false,
- errorMessage: '',
- };
+ describe(types.RECEIVE_MEMBER_EXPIRATION_SUCCESS, () => {
+ it('updates member', () => {
+ const expiresAt = '2020-03-17T00:00:00Z';
- mutations[types.RECEIVE_MEMBER_ROLE_ERROR](state);
+ mutations[types.RECEIVE_MEMBER_EXPIRATION_SUCCESS](state, {
+ memberId: members[0].id,
+ expiresAt,
+ });
- expect(state.showError).toBe(true);
- expect(state.errorMessage).toBe(
- "An error occurred while updating the member's role, please try again.",
- );
+ expect(state.members[0].expiresAt).toEqual(expiresAt);
+ });
+ });
+
+ describe(types.RECEIVE_MEMBER_EXPIRATION_ERROR, () => {
+ it('shows error message', () => {
+ mutations[types.RECEIVE_MEMBER_EXPIRATION_ERROR](state);
+
+ expect(state.showError).toBe(true);
+ expect(state.errorMessage).toBe(
+ "An error occurred while updating the member's expiration date, please try again.",
+ );
+ });
});
});
diff --git a/spec/frontend/whats_new/components/app_spec.js b/spec/frontend/whats_new/components/app_spec.js
index 77c2ae19d1f..cba550b19db 100644
--- a/spec/frontend/whats_new/components/app_spec.js
+++ b/spec/frontend/whats_new/components/app_spec.js
@@ -1,8 +1,16 @@
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlDrawer } from '@gitlab/ui';
+import { GlDrawer, GlInfiniteScroll } from '@gitlab/ui';
import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import App from '~/whats_new/components/app.vue';
+import { getDrawerBodyHeight } from '~/whats_new/utils/get_drawer_body_height';
+
+const MOCK_DRAWER_BODY_HEIGHT = 42;
+
+jest.mock('~/whats_new/utils/get_drawer_body_height', () => ({
+ getDrawerBodyHeight: jest.fn().mockImplementation(() => MOCK_DRAWER_BODY_HEIGHT),
+}));
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -20,11 +28,13 @@ describe('App', () => {
openDrawer: jest.fn(),
closeDrawer: jest.fn(),
fetchItems: jest.fn(),
+ setDrawerBodyHeight: jest.fn(),
};
state = {
open: true,
- features: null,
+ features: [],
+ drawerBodyHeight: null,
};
store = new Vuex.Store({
@@ -36,9 +46,15 @@ describe('App', () => {
localVue,
store,
propsData,
+ directives: {
+ GlResizeObserver: createMockDirective(),
+ },
});
};
+ const findInfiniteScroll = () => wrapper.find(GlInfiniteScroll);
+ const emitBottomReached = () => findInfiniteScroll().vm.$emit('bottomReached');
+
beforeEach(async () => {
document.body.dataset.page = 'test-page';
document.body.dataset.namespaceId = 'namespace-840';
@@ -47,6 +63,7 @@ describe('App', () => {
buildWrapper();
wrapper.vm.$store.state.features = [{ title: 'Whats New Drawer', url: 'www.url.com' }];
+ wrapper.vm.$store.state.drawerBodyHeight = MOCK_DRAWER_BODY_HEIGHT;
await wrapper.vm.$nextTick();
});
@@ -61,7 +78,7 @@ describe('App', () => {
expect(getDrawer().exists()).toBe(true);
});
- it('dispatches openDrawer when mounted', () => {
+ it('dispatches openDrawer and tracking calls when mounted', () => {
expect(actions.openDrawer).toHaveBeenCalledWith(expect.any(Object), 'storage-key');
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_whats_new_drawer', {
label: 'namespace_id',
@@ -90,7 +107,7 @@ describe('App', () => {
it('send an event when feature item is clicked', () => {
trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
- const link = wrapper.find('[data-testid="whats-new-title-link"]');
+ const link = wrapper.find('.whats-new-item-title-link');
triggerEvent(link.element);
expect(trackingSpy.mock.calls[1]).toMatchObject([
@@ -102,4 +119,46 @@ describe('App', () => {
},
]);
});
+
+ it('renders infinite scroll', () => {
+ const scroll = findInfiniteScroll();
+
+ expect(scroll.props()).toMatchObject({
+ fetchedItems: wrapper.vm.$store.state.features.length,
+ maxListHeight: MOCK_DRAWER_BODY_HEIGHT,
+ });
+ });
+
+ describe('bottomReached', () => {
+ beforeEach(() => {
+ actions.fetchItems.mockClear();
+ });
+
+ it('when nextPage exists it calls fetchItems', () => {
+ wrapper.vm.$store.state.pageInfo = { nextPage: 840 };
+ emitBottomReached();
+
+ expect(actions.fetchItems).toHaveBeenCalledWith(expect.anything(), 840);
+ });
+
+ it('when nextPage does not exist it does not call fetchItems', () => {
+ wrapper.vm.$store.state.pageInfo = { nextPage: null };
+ emitBottomReached();
+
+ expect(actions.fetchItems).not.toHaveBeenCalled();
+ });
+ });
+
+ it('calls getDrawerBodyHeight and setDrawerBodyHeight when resize directive is triggered', () => {
+ const { value } = getBinding(getDrawer().element, 'gl-resize-observer');
+
+ value();
+
+ expect(getDrawerBodyHeight).toHaveBeenCalledWith(wrapper.find(GlDrawer).element);
+
+ expect(actions.setDrawerBodyHeight).toHaveBeenCalledWith(
+ expect.any(Object),
+ MOCK_DRAWER_BODY_HEIGHT,
+ );
+ });
});
diff --git a/spec/frontend/whats_new/store/actions_spec.js b/spec/frontend/whats_new/store/actions_spec.js
index 95ab667d611..12722b1b3b1 100644
--- a/spec/frontend/whats_new/store/actions_spec.js
+++ b/spec/frontend/whats_new/store/actions_spec.js
@@ -30,7 +30,9 @@ describe('whats new actions', () => {
axiosMock = new MockAdapter(axios);
axiosMock
.onGet('/-/whats_new')
- .replyOnce(200, [{ title: 'Whats New Drawer', url: 'www.url.com' }]);
+ .replyOnce(200, [{ title: 'Whats New Drawer', url: 'www.url.com' }], {
+ 'x-next-page': '2',
+ });
await waitForPromises();
});
@@ -39,10 +41,23 @@ describe('whats new actions', () => {
axiosMock.restore();
});
- it('should commit setFeatures', () => {
+ it('if already fetching, does not fetch', () => {
+ testAction(actions.fetchItems, {}, { fetching: true }, []);
+ });
+
+ it('should commit fetching, setFeatures and setPagination', () => {
testAction(actions.fetchItems, {}, {}, [
- { type: types.SET_FEATURES, payload: [{ title: 'Whats New Drawer', url: 'www.url.com' }] },
+ { type: types.SET_FETCHING, payload: true },
+ { type: types.ADD_FEATURES, payload: [{ title: 'Whats New Drawer', url: 'www.url.com' }] },
+ { type: types.SET_PAGE_INFO, payload: { nextPage: 2 } },
+ { type: types.SET_FETCHING, payload: false },
]);
});
});
+
+ describe('setDrawerBodyHeight', () => {
+ testAction(actions.setDrawerBodyHeight, 42, {}, [
+ { type: types.SET_DRAWER_BODY_HEIGHT, payload: 42 },
+ ]);
+ });
});
diff --git a/spec/frontend/whats_new/store/mutations_spec.js b/spec/frontend/whats_new/store/mutations_spec.js
index feaa1dd2a3b..4967fb51d2b 100644
--- a/spec/frontend/whats_new/store/mutations_spec.js
+++ b/spec/frontend/whats_new/store/mutations_spec.js
@@ -23,10 +23,37 @@ describe('whats new mutations', () => {
});
});
- describe('setFeatures', () => {
- it('sets features to data', () => {
- mutations[types.SET_FEATURES](state, 'bells and whistles');
- expect(state.features).toBe('bells and whistles');
+ describe('addFeatures', () => {
+ it('adds features from data', () => {
+ mutations[types.ADD_FEATURES](state, ['bells and whistles']);
+ expect(state.features).toEqual(['bells and whistles']);
+ });
+
+ it('when there are already items, it adds items', () => {
+ state.features = ['shiny things'];
+ mutations[types.ADD_FEATURES](state, ['bells and whistles']);
+ expect(state.features).toEqual(['shiny things', 'bells and whistles']);
+ });
+ });
+
+ describe('setPageInfo', () => {
+ it('sets page info', () => {
+ mutations[types.SET_PAGE_INFO](state, { nextPage: 8 });
+ expect(state.pageInfo).toEqual({ nextPage: 8 });
+ });
+ });
+
+ describe('setFetching', () => {
+ it('sets fetching', () => {
+ mutations[types.SET_FETCHING](state, true);
+ expect(state.fetching).toBe(true);
+ });
+ });
+
+ describe('setDrawerBodyHeight', () => {
+ it('sets drawerBodyHeight', () => {
+ mutations[types.SET_DRAWER_BODY_HEIGHT](state, 840);
+ expect(state.drawerBodyHeight).toBe(840);
});
});
});
diff --git a/spec/frontend/whats_new/utils/get_drawer_body_height_spec.js b/spec/frontend/whats_new/utils/get_drawer_body_height_spec.js
new file mode 100644
index 00000000000..d096a3cbdc6
--- /dev/null
+++ b/spec/frontend/whats_new/utils/get_drawer_body_height_spec.js
@@ -0,0 +1,38 @@
+import { mount } from '@vue/test-utils';
+import { GlDrawer } from '@gitlab/ui';
+import { getDrawerBodyHeight } from '~/whats_new/utils/get_drawer_body_height';
+
+describe('~/whats_new/utils/get_drawer_body_height', () => {
+ let drawerWrapper;
+
+ beforeEach(() => {
+ drawerWrapper = mount(GlDrawer, {
+ propsData: { open: true },
+ });
+ });
+
+ afterEach(() => {
+ drawerWrapper.destroy();
+ });
+
+ const setClientHeight = (el, height) => {
+ Object.defineProperty(el, 'clientHeight', {
+ get() {
+ return height;
+ },
+ });
+ };
+ const setDrawerDimensions = ({ height, top, headerHeight }) => {
+ const drawer = drawerWrapper.element;
+
+ setClientHeight(drawer, height);
+ jest.spyOn(drawer, 'getBoundingClientRect').mockReturnValue({ top });
+ setClientHeight(drawer.querySelector('.gl-drawer-header'), headerHeight);
+ };
+
+ it('calculates height of drawer body', () => {
+ setDrawerDimensions({ height: 100, top: 5, headerHeight: 40 });
+
+ expect(getDrawerBodyHeight(drawerWrapper.element)).toBe(55);
+ });
+});
diff --git a/spec/frontend_integration/ide/__snapshots__/ide_integration_spec.js.snap b/spec/frontend_integration/ide/__snapshots__/ide_integration_spec.js.snap
index 6c120898f01..877cc78a111 100644
--- a/spec/frontend_integration/ide/__snapshots__/ide_integration_spec.js.snap
+++ b/spec/frontend_integration/ide/__snapshots__/ide_integration_spec.js.snap
@@ -9,12 +9,6 @@ exports[`WebIDE runs 1`] = `
class="ide-view flex-grow d-flex"
>
<div
- class="file-finder-overlay"
- style="display: none;"
- >
- (jest: contents hidden)
- </div>
- <div
class="gl-relative multi-file-commit-panel flex-column"
style="width: 340px;"
>
@@ -109,28 +103,12 @@ exports[`WebIDE runs 1`] = `
<h4>
Make and review changes in the browser with the Web IDE
</h4>
- <div
- class="gl-spinner-container"
- >
- <span
- aria-label="Loading"
- class="align-text-bottom gl-spinner gl-spinner-orange gl-spinner-md"
- />
- </div>
</div>
</div>
</div>
</div>
</div>
</div>
- <footer
- class="ide-status-bar"
- >
- <div
- class="ide-status-list d-flex ml-auto"
- >
- </div>
- </footer>
</article>
</div>
`;
diff --git a/spec/frontend_integration/test_helpers/fixtures.js b/spec/frontend_integration/test_helpers/fixtures.js
index 5f9c0e8dcba..50fa4859dfa 100644
--- a/spec/frontend_integration/test_helpers/fixtures.js
+++ b/spec/frontend_integration/test_helpers/fixtures.js
@@ -1,4 +1,4 @@
-/* eslint-disable global-require */
+/* eslint-disable global-require, import/no-unresolved */
import { memoize } from 'lodash';
export const getProject = () => require('test_fixtures/api/projects/get.json');
diff --git a/spec/graphql/mutations/alert_management/http_integration/create_spec.rb b/spec/graphql/mutations/alert_management/http_integration/create_spec.rb
new file mode 100644
index 00000000000..9aa89761aaf
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/http_integration/create_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::HttpIntegration::Create do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let(:args) { { project_path: project.full_path, active: true, name: 'HTTP Integration' } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_operations) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when HttpIntegrations::CreateService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: ::AlertManagement::HttpIntegration.last!,
+ errors: []
+ )
+ end
+ end
+
+ context 'when HttpIntegrations::CreateService responds with an error' do
+ before do
+ allow_any_instance_of(::AlertManagement::HttpIntegrations::CreateService)
+ .to receive(:execute)
+ .and_return(ServiceResponse.error(payload: { integration: nil }, message: 'An integration already exists'))
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: nil,
+ errors: ['An integration already exists']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb b/spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb
new file mode 100644
index 00000000000..f74f9186743
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::HttpIntegration::Destroy do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let(:integration) { create(:alert_management_http_integration, project: project) }
+ let(:args) { { id: GitlabSchema.id_from_object(integration) } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_operations) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when HttpIntegrations::DestroyService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: []
+ )
+ end
+ end
+
+ context 'when HttpIntegrations::DestroyService responds with an error' do
+ before do
+ allow_any_instance_of(::AlertManagement::HttpIntegrations::DestroyService)
+ .to receive(:execute)
+ .and_return(ServiceResponse.error(payload: { integration: nil }, message: 'An error has occurred'))
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: nil,
+ errors: ['An error has occurred']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/http_integration/reset_token_spec.rb b/spec/graphql/mutations/alert_management/http_integration/reset_token_spec.rb
new file mode 100644
index 00000000000..d3ffb2abb47
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/http_integration/reset_token_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::HttpIntegration::ResetToken do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:alert_management_http_integration, project: project) }
+ let(:args) { { id: GitlabSchema.id_from_object(integration) } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_operations) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has sufficient access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when HttpIntegrations::UpdateService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: []
+ )
+ end
+ end
+
+ context 'when HttpIntegrations::UpdateService responds with an error' do
+ before do
+ allow_any_instance_of(::AlertManagement::HttpIntegrations::UpdateService)
+ .to receive(:execute)
+ .and_return(ServiceResponse.error(payload: { integration: nil }, message: 'Token cannot be reset'))
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: nil,
+ errors: ['Token cannot be reset']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/http_integration/update_spec.rb b/spec/graphql/mutations/alert_management/http_integration/update_spec.rb
new file mode 100644
index 00000000000..d6318e3161d
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/http_integration/update_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::HttpIntegration::Update do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:alert_management_http_integration, project: project) }
+ let(:args) { { id: GitlabSchema.id_from_object(integration), active: false, name: 'New Name' } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_operations) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has sufficient access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when HttpIntegrations::UpdateService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: []
+ )
+ end
+ end
+
+ context 'when HttpIntegrations::UpdateService responds with an error' do
+ before do
+ allow_any_instance_of(::AlertManagement::HttpIntegrations::UpdateService)
+ .to receive(:execute)
+ .and_return(ServiceResponse.error(payload: { integration: nil }, message: 'Failed to update'))
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: nil,
+ errors: ['Failed to update']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/prometheus_integration/create_spec.rb b/spec/graphql/mutations/alert_management/prometheus_integration/create_spec.rb
new file mode 100644
index 00000000000..02a5e2e74e2
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/prometheus_integration/create_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::PrometheusIntegration::Create do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let(:args) { { project_path: project.full_path, active: true, api_url: 'http://prometheus.com/' } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_project) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when Prometheus Integration already exists' do
+ let_it_be(:existing_integration) { create(:prometheus_service, project: project) }
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: nil,
+ errors: ['Multiple Prometheus integrations are not supported']
+ )
+ end
+ end
+
+ context 'when UpdateService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: ::PrometheusService.last!,
+ errors: []
+ )
+ end
+
+ it 'creates a corresponding token' do
+ expect { resolve }.to change(::Alerting::ProjectAlertingSetting, :count).by(1)
+ end
+ end
+
+ context 'when UpdateService responds with an error' do
+ before do
+ allow_any_instance_of(::Projects::Operations::UpdateService)
+ .to receive(:execute)
+ .and_return({ status: :error, message: 'An error occurred' })
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: nil,
+ errors: ['An error occurred']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb b/spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb
new file mode 100644
index 00000000000..45d92695e06
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::PrometheusIntegration::ResetToken do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:prometheus_service, project: project) }
+ let(:args) { { id: GitlabSchema.id_from_object(integration) } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_project) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has sufficient access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when ::Projects::Operations::UpdateService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: []
+ )
+ end
+ end
+
+ context 'when ::Projects::Operations::UpdateService responds with an error' do
+ before do
+ allow_any_instance_of(::Projects::Operations::UpdateService)
+ .to receive(:execute)
+ .and_return({ status: :error, message: 'An error occurred' })
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: ['An error occurred']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/prometheus_integration/update_spec.rb b/spec/graphql/mutations/alert_management/prometheus_integration/update_spec.rb
new file mode 100644
index 00000000000..eab4474d827
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/prometheus_integration/update_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::PrometheusIntegration::Update do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:prometheus_service, project: project) }
+ let(:args) { { id: GitlabSchema.id_from_object(integration), active: false, api_url: 'http://new-url.com' } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_project) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has sufficient access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when ::Projects::Operations::UpdateService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: []
+ )
+ end
+ end
+
+ context 'when ::Projects::Operations::UpdateService responds with an error' do
+ before do
+ allow_any_instance_of(::Projects::Operations::UpdateService)
+ .to receive(:execute)
+ .and_return({ status: :error, message: 'An error occurred' })
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: ['An error occurred']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
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 ab98088ebcd..08761ce64c2 100644
--- a/spec/graphql/mutations/alert_management/update_alert_status_spec.rb
+++ b/spec/graphql/mutations/alert_management/update_alert_status_spec.rb
@@ -37,8 +37,8 @@ RSpec.describe Mutations::AlertManagement::UpdateAlertStatus do
context 'error occurs when updating' do
it 'returns the alert with errors' do
# Stub an error on the alert
- allow_next_instance_of(Resolvers::AlertManagement::AlertResolver) do |resolver|
- allow(resolver).to receive(:resolve).and_return(alert)
+ allow_next_instance_of(::AlertManagement::AlertsFinder) do |finder|
+ allow(finder).to receive(:execute).and_return([alert])
end
allow(alert).to receive(:save).and_return(false)
diff --git a/spec/graphql/mutations/commits/create_spec.rb b/spec/graphql/mutations/commits/create_spec.rb
index fb1baafe7bd..82a5e3a62f5 100644
--- a/spec/graphql/mutations/commits/create_spec.rb
+++ b/spec/graphql/mutations/commits/create_spec.rb
@@ -5,8 +5,9 @@ require 'spec_helper'
RSpec.describe Mutations::Commits::Create do
subject(:mutation) { described_class.new(object: nil, context: context, field: nil) }
- let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+
let(:context) do
GraphQL::Query::Context.new(
query: OpenStruct.new(schema: nil),
@@ -18,9 +19,10 @@ RSpec.describe Mutations::Commits::Create do
specify { expect(described_class).to require_graphql_authorizations(:push_code) }
describe '#resolve' do
- subject { mutation.resolve(project_path: project.full_path, branch: branch, message: message, actions: actions) }
+ subject { mutation.resolve(project_path: project.full_path, branch: branch, start_branch: start_branch, message: message, actions: actions) }
let(:branch) { 'master' }
+ let(:start_branch) { nil }
let(:message) { 'Commit message' }
let(:actions) do
[
@@ -142,6 +144,29 @@ RSpec.describe Mutations::Commits::Create do
end
end
+ context 'when branch does not exist and a start branch is provided' do
+ let(:branch) { 'my-branch' }
+ let(:start_branch) { 'master' }
+ let(:actions) do
+ [
+ {
+ action: 'create',
+ file_path: 'ANOTHER_FILE.md',
+ content: 'Bye'
+ }
+ ]
+ end
+
+ it 'returns a new commit' do
+ expect(mutated_commit).to have_attributes(message: message, project: project)
+ expect(subject[:errors]).to be_empty
+
+ expect_to_contain_deltas([
+ a_hash_including(a_mode: '0', b_mode: '100644', new_file: true, new_path: 'ANOTHER_FILE.md')
+ ])
+ end
+ end
+
context 'when message is not set' do
let(:message) { nil }
diff --git a/spec/graphql/mutations/container_expiration_policies/update_spec.rb b/spec/graphql/mutations/container_expiration_policies/update_spec.rb
index 6aedaab3b53..9c6016e0af4 100644
--- a/spec/graphql/mutations/container_expiration_policies/update_spec.rb
+++ b/spec/graphql/mutations/container_expiration_policies/update_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe Mutations::ContainerExpirationPolicies::Update do
it_behaves_like 'not creating the container expiration policy'
- it "doesn't update the cadence" do
+ it 'doesn\'t update the cadence' do
expect { subject }
.not_to change { container_expiration_policy.reload.cadence }
end
@@ -47,6 +47,24 @@ RSpec.describe Mutations::ContainerExpirationPolicies::Update do
)
end
end
+
+ context 'with blank regex' do
+ let_it_be(:params) { { project_path: project.full_path, name_regex: '', enabled: true } }
+
+ it_behaves_like 'not creating the container expiration policy'
+
+ it "doesn't update the cadence" do
+ expect { subject }
+ .not_to change { container_expiration_policy.reload.cadence }
+ end
+
+ it 'returns an error' do
+ expect(subject).to eq(
+ container_expiration_policy: nil,
+ errors: ['Name regex can\'t be blank']
+ )
+ end
+ end
end
RSpec.shared_examples 'denying access to container expiration policy' do
diff --git a/spec/graphql/mutations/container_repositories/destroy_spec.rb b/spec/graphql/mutations/container_repositories/destroy_spec.rb
new file mode 100644
index 00000000000..3903196a511
--- /dev/null
+++ b/spec/graphql/mutations/container_repositories/destroy_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::ContainerRepositories::Destroy do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be_with_reload(:container_repository) { create(:container_repository) }
+ let_it_be(:user) { create(:user) }
+
+ let(:project) { container_repository.project }
+ let(:id) { container_repository.to_global_id.to_s }
+
+ specify { expect(described_class).to require_graphql_authorizations(:destroy_container_image) }
+
+ describe '#resolve' do
+ subject do
+ described_class.new(object: nil, context: { current_user: user }, field: nil)
+ .resolve(id: id)
+ end
+
+ shared_examples 'destroying the container repository' do
+ it 'destroys the container repistory' do
+ expect(::Packages::CreateEventService)
+ .to receive(:new).with(nil, user, event_name: :delete_repository, scope: :container).and_call_original
+ expect(DeleteContainerRepositoryWorker)
+ .to receive(:perform_async).with(user.id, container_repository.id)
+
+ expect { subject }.to change { ::Packages::Event.count }.by(1)
+ expect(container_repository.reload.delete_scheduled?).to be true
+ end
+ end
+
+ shared_examples 'denying access to container respository' do
+ it 'raises an error' do
+ expect(DeleteContainerRepositoryWorker)
+ .not_to receive(:perform_async).with(user.id, container_repository.id)
+
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'with valid id' do
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'destroying the container repository'
+ :developer | 'destroying the container repository'
+ :reporter | 'denying access to container respository'
+ :guest | 'denying access to container respository'
+ :anonymous | 'denying access to container respository'
+ end
+
+ with_them do
+ before do
+ project.send("add_#{user_role}", user) unless user_role == :anonymous
+ end
+
+ it_behaves_like params[:shared_examples_name]
+ end
+ end
+
+ context 'with invalid id' do
+ let(:id) { 'gid://gitlab/ContainerRepository/5555' }
+
+ it_behaves_like 'denying access to container respository'
+ end
+ end
+end
diff --git a/spec/graphql/mutations/issues/set_assignees_spec.rb b/spec/graphql/mutations/issues/set_assignees_spec.rb
index 77ba511b715..9a27c5acdac 100644
--- a/spec/graphql/mutations/issues/set_assignees_spec.rb
+++ b/spec/graphql/mutations/issues/set_assignees_spec.rb
@@ -3,6 +3,20 @@
require 'spec_helper'
RSpec.describe Mutations::Issues::SetAssignees do
+ context 'when the user does not have permissions' do
+ let_it_be(:issue) { create(:issue) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:assignee) { create(:user) }
+
+ subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
+
+ describe '#resolve' do
+ subject { mutation.resolve(project_path: issue.project.full_path, iid: issue.iid, assignee_usernames: [assignee.username]) }
+
+ it_behaves_like 'permission level for issue mutation is correctly verified'
+ end
+ end
+
it_behaves_like 'an assignable resource' do
let_it_be(:resource, reload: true) { create(:issue) }
end
diff --git a/spec/graphql/mutations/issues/set_confidential_spec.rb b/spec/graphql/mutations/issues/set_confidential_spec.rb
index 0b2fc0ecb93..c3269e5c0c0 100644
--- a/spec/graphql/mutations/issues/set_confidential_spec.rb
+++ b/spec/graphql/mutations/issues/set_confidential_spec.rb
@@ -17,9 +17,7 @@ RSpec.describe Mutations::Issues::SetConfidential do
subject { mutation.resolve(project_path: project.full_path, iid: issue.iid, confidential: confidential) }
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for issue mutation is correctly verified'
context 'when the user can update the issue' do
before do
diff --git a/spec/graphql/mutations/issues/set_due_date_spec.rb b/spec/graphql/mutations/issues/set_due_date_spec.rb
index a638971d966..9f8d0d6c405 100644
--- a/spec/graphql/mutations/issues/set_due_date_spec.rb
+++ b/spec/graphql/mutations/issues/set_due_date_spec.rb
@@ -16,9 +16,7 @@ RSpec.describe Mutations::Issues::SetDueDate do
subject { mutation.resolve(project_path: issue.project.full_path, iid: issue.iid, due_date: due_date) }
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for issue mutation is correctly verified'
context 'when the user can update the issue' do
before do
diff --git a/spec/graphql/mutations/issues/set_locked_spec.rb b/spec/graphql/mutations/issues/set_locked_spec.rb
index 10438226c17..1a0af0c6c63 100644
--- a/spec/graphql/mutations/issues/set_locked_spec.rb
+++ b/spec/graphql/mutations/issues/set_locked_spec.rb
@@ -15,9 +15,7 @@ RSpec.describe Mutations::Issues::SetLocked do
subject { mutation.resolve(project_path: issue.project.full_path, iid: issue.iid, locked: locked) }
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for issue mutation is correctly verified'
context 'when the user can update the issue' do
let(:mutated_issue) { subject[:issue] }
diff --git a/spec/graphql/mutations/issues/set_severity_spec.rb b/spec/graphql/mutations/issues/set_severity_spec.rb
index ed73d3b777e..7698118ae3e 100644
--- a/spec/graphql/mutations/issues/set_severity_spec.rb
+++ b/spec/graphql/mutations/issues/set_severity_spec.rb
@@ -15,11 +15,7 @@ RSpec.describe Mutations::Issues::SetSeverity do
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
+ it_behaves_like 'permission level for issue mutation is correctly verified'
context 'when the user can update the issue' do
before do
diff --git a/spec/graphql/mutations/issues/update_spec.rb b/spec/graphql/mutations/issues/update_spec.rb
index f9f4bdeb6fa..ce1eb874bcf 100644
--- a/spec/graphql/mutations/issues/update_spec.rb
+++ b/spec/graphql/mutations/issues/update_spec.rb
@@ -35,11 +35,7 @@ RSpec.describe Mutations::Issues::Update do
subject { mutation.resolve(mutation_params) }
- context 'when the user cannot access the issue' do
- it 'raises an error' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
- end
+ it_behaves_like 'permission level for issue mutation is correctly verified'
context 'when the user can update the issue' do
before do
diff --git a/spec/graphql/mutations/labels/create_spec.rb b/spec/graphql/mutations/labels/create_spec.rb
new file mode 100644
index 00000000000..8b284816d63
--- /dev/null
+++ b/spec/graphql/mutations/labels/create_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Labels::Create do
+ let_it_be(:user) { create(:user) }
+
+ let(:attributes) do
+ {
+ title: 'new title',
+ description: 'A new label'
+ }
+ end
+
+ let(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
+ let(:mutated_label) { subject[:label] }
+
+ shared_examples 'create labels mutation' do
+ describe '#resolve' do
+ subject { mutation.resolve(attributes.merge(extra_params)) }
+
+ context 'when the user does not have permission to create a label' do
+ before do
+ parent.add_guest(user)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'when the user can create a label' do
+ before do
+ parent.add_developer(user)
+ end
+
+ it 'creates label with correct values' do
+ expect(mutated_label).to have_attributes(attributes)
+ end
+ end
+ end
+ end
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_label) }
+
+ context 'when creating a project label' do
+ let_it_be(:parent) { create(:project) }
+ let(:extra_params) { { project_path: parent.full_path } }
+
+ it_behaves_like 'create labels mutation'
+ end
+
+ context 'when creating a group label' do
+ let_it_be(:parent) { create(:group) }
+ let(:extra_params) { { group_path: parent.full_path } }
+
+ it_behaves_like 'create labels mutation'
+ end
+
+ describe '#ready?' do
+ subject { mutation.ready?(attributes.merge(extra_params)) }
+
+ context 'when passing both project_path and group_path' do
+ let(:extra_params) { { project_path: 'foo', group_path: 'bar' } }
+
+ it 'raises an argument error' do
+ expect { subject }
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, /Exactly one of/)
+ end
+ end
+
+ context 'when passing only project_path or group_path' do
+ let(:extra_params) { { project_path: 'foo' } }
+
+ it 'does not raise an error' do
+ expect { subject }.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/merge_requests/set_assignees_spec.rb b/spec/graphql/mutations/merge_requests/set_assignees_spec.rb
index 4ac40fc09c6..e2eab591341 100644
--- a/spec/graphql/mutations/merge_requests/set_assignees_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_assignees_spec.rb
@@ -3,6 +3,20 @@
require 'spec_helper'
RSpec.describe Mutations::MergeRequests::SetAssignees do
+ context 'when the user does not have permissions' do
+ let_it_be(:merge_request) { create(:merge_request) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:assignee) { create(:user) }
+
+ subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
+
+ describe '#resolve' do
+ subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, assignee_usernames: [assignee.username]) }
+
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
+ end
+ end
+
it_behaves_like 'an assignable resource' do
let_it_be(:resource, reload: true) { create(:merge_request) }
end
diff --git a/spec/graphql/mutations/merge_requests/set_labels_spec.rb b/spec/graphql/mutations/merge_requests/set_labels_spec.rb
index 62a7f650f84..1bb303cf99b 100644
--- a/spec/graphql/mutations/merge_requests/set_labels_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_labels_spec.rb
@@ -18,9 +18,7 @@ RSpec.describe Mutations::MergeRequests::SetLabels do
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, label_ids: label_ids) }
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
context 'when the user can update the merge request' do
before do
diff --git a/spec/graphql/mutations/merge_requests/set_locked_spec.rb b/spec/graphql/mutations/merge_requests/set_locked_spec.rb
index aca7df5445f..03c709e9bb3 100644
--- a/spec/graphql/mutations/merge_requests/set_locked_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_locked_spec.rb
@@ -16,9 +16,7 @@ RSpec.describe Mutations::MergeRequests::SetLocked do
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, locked: locked) }
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
context 'when the user can update the merge request' do
before do
diff --git a/spec/graphql/mutations/merge_requests/set_milestone_spec.rb b/spec/graphql/mutations/merge_requests/set_milestone_spec.rb
index ccb2d9bd132..4de857f43e3 100644
--- a/spec/graphql/mutations/merge_requests/set_milestone_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_milestone_spec.rb
@@ -18,6 +18,8 @@ RSpec.describe Mutations::MergeRequests::SetMilestone do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
+
context 'when the user can update the merge request' do
before do
project.add_developer(user)
diff --git a/spec/graphql/mutations/merge_requests/set_wip_spec.rb b/spec/graphql/mutations/merge_requests/set_wip_spec.rb
index b6cb49724fa..69f6a4328b8 100644
--- a/spec/graphql/mutations/merge_requests/set_wip_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_wip_spec.rb
@@ -16,9 +16,7 @@ RSpec.describe Mutations::MergeRequests::SetWip do
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, wip: wip) }
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
context 'when the user can update the merge request' do
before do
diff --git a/spec/graphql/mutations/merge_requests/update_spec.rb b/spec/graphql/mutations/merge_requests/update_spec.rb
index 4a1fdf6e74b..8acd2562ea8 100644
--- a/spec/graphql/mutations/merge_requests/update_spec.rb
+++ b/spec/graphql/mutations/merge_requests/update_spec.rb
@@ -18,9 +18,7 @@ RSpec.describe Mutations::MergeRequests::Update do
mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, **attributes)
end
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
context 'when the user can update the merge request' do
before do
diff --git a/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb b/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb
new file mode 100644
index 00000000000..8c22e1a1cb6
--- /dev/null
+++ b/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Notes::RepositionImageDiffNote do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ subject do
+ mutation.resolve({ note: note, position: new_position })
+ end
+
+ let_it_be(:noteable) { create(:merge_request) }
+ let_it_be(:project) { noteable.project }
+ let(:note) { create(:image_diff_note_on_merge_request, noteable: noteable, project: project) }
+
+ let(:mutation) do
+ described_class.new(object: nil, context: { current_user: user }, field: nil)
+ end
+
+ let(:new_position) do
+ { x: 10, y: 11, width: 12, height: 13 }
+ end
+
+ context 'when the user does not have permission' do
+ let(:user) { nil }
+
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(
+ Gitlab::Graphql::Errors::ResourceNotAvailable,
+ "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ )
+ end
+ end
+
+ context 'when the user has permission' do
+ let(:user) { project.creator }
+ let(:mutated_note) { subject[:note] }
+ let(:errors) { subject[:errors] }
+
+ it 'mutates the note', :aggregate_failures do
+ expect { subject }.to change { note.reset.position.to_h }.to(include(new_position))
+
+ expect(mutated_note).to eq(note)
+ expect(errors).to be_empty
+ end
+
+ context 'when the note is a DiffNote, but not on an image' do
+ let(:note) { create(:diff_note_on_merge_request, noteable: noteable, project: project) }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(
+ Gitlab::Graphql::Errors::ResourceNotAvailable,
+ 'Resource is not an ImageDiffNote'
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/releases/create_spec.rb b/spec/graphql/mutations/releases/create_spec.rb
new file mode 100644
index 00000000000..d6305691dac
--- /dev/null
+++ b/spec/graphql/mutations/releases/create_spec.rb
@@ -0,0 +1,133 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Releases::Create do
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:milestone_12_3) { create(:milestone, project: project, title: '12.3') }
+ let_it_be(:milestone_12_4) { create(:milestone, project: project, title: '12.4') }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:developer) { create(:user) }
+
+ let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
+
+ let(:tag) { 'v1.1.0'}
+ let(:ref) { 'master'}
+ let(:name) { 'Version 1.0'}
+ let(:description) { 'The first release :rocket:' }
+ let(:released_at) { Time.parse('2018-12-10') }
+ let(:milestones) { [milestone_12_3.title, milestone_12_4.title] }
+ let(:assets) do
+ {
+ links: [
+ {
+ name: 'An asset link',
+ url: 'https://gitlab.example.com/link',
+ filepath: '/permanent/link',
+ link_type: 'other'
+ }
+ ]
+ }
+ end
+
+ let(:mutation_arguments) do
+ {
+ project_path: project.full_path,
+ tag: tag,
+ ref: ref,
+ name: name,
+ description: description,
+ released_at: released_at,
+ milestones: milestones,
+ assets: assets
+ }
+ end
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ before do
+ project.add_reporter(reporter)
+ project.add_developer(developer)
+ end
+
+ describe '#resolve' do
+ subject(:resolve) do
+ mutation.resolve(**mutation_arguments)
+ end
+
+ let(:new_release) { subject[:release] }
+
+ context 'when the current user has access to create releases' do
+ let(:current_user) { developer }
+
+ it 'returns no errors' do
+ expect(resolve).to include(errors: [])
+ end
+
+ it 'creates the release with the correct tag' do
+ expect(new_release.tag).to eq(tag)
+ end
+
+ it 'creates the release with the correct name' do
+ expect(new_release.name).to eq(name)
+ end
+
+ it 'creates the release with the correct description' do
+ expect(new_release.description).to eq(description)
+ end
+
+ it 'creates the release with the correct released_at' do
+ expect(new_release.released_at).to eq(released_at)
+ end
+
+ it 'creates the release with the correct created_at' do
+ expect(new_release.created_at).to eq(Time.current)
+ end
+
+ it 'creates the release with the correct milestone associations' do
+ expected_milestone_titles = [milestone_12_3.title, milestone_12_4.title]
+ actual_milestone_titles = new_release.milestones.map { |m| m.title }
+
+ # Right now the milestones are returned in a non-deterministic order.
+ # `match_array` should be updated to `eq` once
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/259012 is addressed.
+ expect(actual_milestone_titles).to match_array(expected_milestone_titles)
+ end
+
+ describe 'asset links' do
+ let(:expected_link) { assets[:links].first }
+ let(:new_link) { new_release.links.first }
+
+ it 'creates a single asset link' do
+ expect(new_release.links.size).to eq(1)
+ end
+
+ it 'creates the link with the correct name' do
+ expect(new_link.name).to eq(expected_link[:name])
+ end
+
+ it 'creates the link with the correct url' do
+ expect(new_link.url).to eq(expected_link[:url])
+ end
+
+ it 'creates the link with the correct link type' do
+ expect(new_link.link_type).to eq(expected_link[:link_type])
+ end
+
+ it 'creates the link with the correct direct filepath' do
+ expect(new_link.filepath).to eq(expected_link[:filepath])
+ end
+ end
+ end
+
+ context "when the current user doesn't have access to create releases" do
+ let(:current_user) { reporter }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/terraform/state/delete_spec.rb b/spec/graphql/mutations/terraform/state/delete_spec.rb
new file mode 100644
index 00000000000..313a85a4bac
--- /dev/null
+++ b/spec/graphql/mutations/terraform/state/delete_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Terraform::State::Delete do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:state) { create(:terraform_state) }
+
+ let(:mutation) do
+ described_class.new(
+ object: double,
+ context: { current_user: user },
+ field: double
+ )
+ end
+
+ it { expect(described_class.graphql_name).to eq('TerraformStateDelete') }
+ it { expect(described_class).to require_graphql_authorizations(:admin_terraform_state) }
+
+ describe '#resolve' do
+ let(:global_id) { state.to_global_id }
+
+ subject { mutation.resolve(id: global_id) }
+
+ context 'user does not have permission' do
+ it 'raises an error', :aggregate_failures do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect { state.reload }.not_to raise_error
+ end
+ end
+
+ context 'user has permission' do
+ before do
+ state.project.add_maintainer(user)
+ end
+
+ it 'deletes the state', :aggregate_failures do
+ expect do
+ expect(subject).to eq(errors: [])
+ end.to change { ::Terraform::State.count }.by(-1)
+
+ expect { state.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ context 'with invalid params' do
+ let(:global_id) { user.to_global_id }
+
+ it 'raises an error', :aggregate_failures do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect { state.reload }.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/terraform/state/lock_spec.rb b/spec/graphql/mutations/terraform/state/lock_spec.rb
new file mode 100644
index 00000000000..c83563040fd
--- /dev/null
+++ b/spec/graphql/mutations/terraform/state/lock_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Terraform::State::Lock do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:state) { create(:terraform_state) }
+
+ let(:mutation) do
+ described_class.new(
+ object: double,
+ context: { current_user: user },
+ field: double
+ )
+ end
+
+ it { expect(described_class.graphql_name).to eq('TerraformStateLock') }
+ it { expect(described_class).to require_graphql_authorizations(:admin_terraform_state) }
+
+ describe '#resolve' do
+ let(:global_id) { state.to_global_id }
+
+ subject { mutation.resolve(id: global_id) }
+
+ context 'user does not have permission' do
+ it 'raises an error', :aggregate_failures do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect(state.reload).not_to be_locked
+ end
+ end
+
+ context 'user has permission' do
+ before do
+ state.project.add_maintainer(user)
+ end
+
+ it 'locks the state', :aggregate_failures do
+ expect(subject).to eq(errors: [])
+
+ expect(state.reload).to be_locked
+ expect(state.locked_by_user).to eq(user)
+ expect(state.lock_xid).to be_present
+ expect(state.locked_at).to be_present
+ end
+
+ context 'state is already locked' do
+ let(:locked_by_user) { create(:user) }
+ let(:state) { create(:terraform_state, :locked, locked_by_user: locked_by_user) }
+
+ it 'does not modify the existing lock', :aggregate_failures do
+ expect(subject).to eq(errors: ['state is already locked'])
+
+ expect(state.reload).to be_locked
+ expect(state.locked_by_user).to eq(locked_by_user)
+ end
+ end
+ end
+
+ context 'with invalid params' do
+ let(:global_id) { user.to_global_id }
+
+ it 'raises an error', :aggregate_failures do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect(state.reload).not_to be_locked
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/terraform/state/unlock_spec.rb b/spec/graphql/mutations/terraform/state/unlock_spec.rb
new file mode 100644
index 00000000000..4918a1c4abf
--- /dev/null
+++ b/spec/graphql/mutations/terraform/state/unlock_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Terraform::State::Unlock do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:state) { create(:terraform_state, :locked) }
+
+ let(:mutation) do
+ described_class.new(
+ object: double,
+ context: { current_user: user },
+ field: double
+ )
+ end
+
+ it { expect(described_class.graphql_name).to eq('TerraformStateUnlock') }
+ it { expect(described_class).to require_graphql_authorizations(:admin_terraform_state) }
+
+ describe '#resolve' do
+ let(:global_id) { state.to_global_id }
+
+ subject { mutation.resolve(id: global_id) }
+
+ context 'user does not have permission' do
+ it 'raises an error', :aggregate_failures do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect(state.reload).to be_locked
+ end
+ end
+
+ context 'user has permission' do
+ before do
+ state.project.add_maintainer(user)
+ end
+
+ it 'unlocks the state', :aggregate_failures do
+ expect(subject).to eq(errors: [])
+ expect(state.reload).not_to be_locked
+ end
+
+ context 'state is already unlocked' do
+ let(:state) { create(:terraform_state) }
+
+ it 'does not modify the state' do
+ expect(subject).to eq(errors: [])
+ expect(state.reload).not_to be_locked
+ end
+ end
+ end
+
+ context 'with invalid params' do
+ let(:global_id) { user.to_global_id }
+
+ it 'raises an error', :aggregate_failures do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect(state.reload).to be_locked
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/todos/create_spec.rb b/spec/graphql/mutations/todos/create_spec.rb
new file mode 100644
index 00000000000..bbb033e2f33
--- /dev/null
+++ b/spec/graphql/mutations/todos/create_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Todos::Create do
+ include GraphqlHelpers
+ include DesignManagementTestHelpers
+
+ describe '#resolve' do
+ context 'when target does not support todos' do
+ it 'raises error' do
+ current_user = create(:user)
+ mutation = described_class.new(object: nil, context: { current_user: current_user }, field: nil)
+
+ target = create(:milestone)
+
+ expect { mutation.resolve(target_id: global_id_of(target)) }
+ .to raise_error(GraphQL::CoercionError)
+ end
+ end
+
+ context 'with issue as target' do
+ it_behaves_like 'create todo mutation' do
+ let_it_be(:target) { create(:issue) }
+ end
+ end
+
+ context 'with merge request as target' do
+ it_behaves_like 'create todo mutation' do
+ let_it_be(:target) { create(:merge_request) }
+ end
+ end
+
+ context 'with design as target' do
+ before do
+ enable_design_management
+ end
+
+ it_behaves_like 'create todo mutation' do
+ let_it_be(:target) { create(:design) }
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/todos/mark_all_done_spec.rb b/spec/graphql/mutations/todos/mark_all_done_spec.rb
index 2f167164050..f3b6bf52ef7 100644
--- a/spec/graphql/mutations/todos/mark_all_done_spec.rb
+++ b/spec/graphql/mutations/todos/mark_all_done_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Mutations::Todos::MarkAllDone do
expect(todo3.reload.state).to eq('done')
expect(other_user_todo.reload.state).to eq('pending')
- expect(updated_todo_ids).to contain_exactly(global_id_of(todo1), global_id_of(todo3))
+ expect(updated_todo_ids).to contain_exactly(todo1.id, todo3.id)
expect(todos).to contain_exactly(todo1, todo3)
end
diff --git a/spec/graphql/mutations/todos/restore_many_spec.rb b/spec/graphql/mutations/todos/restore_many_spec.rb
index 59995e33f2d..dc10355ef22 100644
--- a/spec/graphql/mutations/todos/restore_many_spec.rb
+++ b/spec/graphql/mutations/todos/restore_many_spec.rb
@@ -24,11 +24,11 @@ RSpec.describe Mutations::Todos::RestoreMany do
expect(todo2.reload.state).to eq('pending')
expect(other_user_todo.reload.state).to eq('done')
- todo_ids = result[:updated_ids]
- expect(todo_ids.size).to eq(1)
- expect(todo_ids.first).to eq(todo1.to_global_id.to_s)
-
- expect(result[:todos]).to contain_exactly(todo1)
+ expect(result).to match(
+ errors: be_empty,
+ updated_ids: contain_exactly(todo1.id),
+ todos: contain_exactly(todo1)
+ )
end
it 'handles a todo which is already pending as expected' do
@@ -36,8 +36,11 @@ RSpec.describe Mutations::Todos::RestoreMany do
expect_states_were_not_changed
- expect(result[:updated_ids]).to eq([])
- expect(result[:todos]).to be_empty
+ expect(result).to match(
+ errors: be_empty,
+ updated_ids: be_empty,
+ todos: be_empty
+ )
end
it 'ignores requests for todos which do not belong to the current user' do
@@ -61,7 +64,7 @@ RSpec.describe Mutations::Todos::RestoreMany do
expect(result[:updated_ids].size).to eq(2)
returned_todo_ids = result[:updated_ids]
- expect(returned_todo_ids).to contain_exactly(todo1.to_global_id.to_s, todo4.to_global_id.to_s)
+ expect(returned_todo_ids).to contain_exactly(todo1.id, todo4.id)
expect(result[:todos]).to contain_exactly(todo1, todo4)
expect(todo1.reload.state).to eq('pending')
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
index c5637d43382..578d679ade4 100644
--- a/spec/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver_spec.rb
+++ b/spec/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver_spec.rb
@@ -14,7 +14,9 @@ RSpec.describe Resolvers::Admin::Analytics::InstanceStatistics::MeasurementsReso
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 }) }
+ let(:arguments) { { identifier: 'projects' } }
+
+ subject { resolve_measurements(arguments, { current_user: current_user }) }
context 'when requesting project count measurements' do
context 'as an admin user' do
@@ -40,6 +42,24 @@ RSpec.describe Resolvers::Admin::Analytics::InstanceStatistics::MeasurementsReso
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
+
+ context 'when filtering by recorded_after and recorded_before' do
+ before do
+ arguments[:recorded_after] = 4.days.ago
+ arguments[:recorded_before] = 1.day.ago
+ end
+
+ it { is_expected.to match_array([project_measurement_new]) }
+
+ context 'when "incorrect" values are passed' do
+ before do
+ arguments[:recorded_after] = 1.day.ago
+ arguments[:recorded_before] = 4.days.ago
+ end
+
+ it { is_expected.to be_empty }
+ end
+ end
end
context 'when requesting pipeline counts by pipeline status' do
diff --git a/spec/graphql/resolvers/alert_management/integrations_resolver_spec.rb b/spec/graphql/resolvers/alert_management/integrations_resolver_spec.rb
new file mode 100644
index 00000000000..36e409e0677
--- /dev/null
+++ b/spec/graphql/resolvers/alert_management/integrations_resolver_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::AlertManagement::IntegrationsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:prometheus_integration) { create(:prometheus_service, project: project) }
+ let_it_be(:active_http_integration) { create(:alert_management_http_integration, project: project) }
+ let_it_be(:inactive_http_integration) { create(:alert_management_http_integration, :inactive, project: project) }
+ let_it_be(:other_proj_integration) { create(:alert_management_http_integration) }
+
+ subject { sync(resolve_http_integrations) }
+
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::AlertManagement::IntegrationType.connection_type)
+ end
+
+ context 'user does not have permission' do
+ it { is_expected.to be_empty }
+ end
+
+ context 'user has permission' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ it { is_expected.to contain_exactly(active_http_integration, prometheus_integration) }
+ end
+
+ private
+
+ def resolve_http_integrations(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: project, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/base_resolver_spec.rb b/spec/graphql/resolvers/base_resolver_spec.rb
index 40dc2370052..e5b9fb57e42 100644
--- a/spec/graphql/resolvers/base_resolver_spec.rb
+++ b/spec/graphql/resolvers/base_resolver_spec.rb
@@ -7,10 +7,13 @@ RSpec.describe Resolvers::BaseResolver do
let(:resolver) do
Class.new(described_class) do
- def resolve(**args)
+ argument :test, ::GraphQL::INT_TYPE, required: false
+ type [::GraphQL::INT_TYPE], null: true
+
+ def resolve(test: 100)
process(object)
- [args, args]
+ [test, test]
end
def process(obj); end
@@ -19,17 +22,75 @@ RSpec.describe Resolvers::BaseResolver do
let(:last_resolver) do
Class.new(described_class) do
+ type [::GraphQL::INT_TYPE], null: true
+
def resolve(**args)
[1, 2]
end
end
end
+ describe '.singular_type' do
+ subject { resolver.singular_type }
+
+ context 'for a connection of scalars' do
+ let(:resolver) do
+ Class.new(described_class) do
+ type ::GraphQL::INT_TYPE.connection_type, null: true
+ end
+ end
+
+ it { is_expected.to eq(::GraphQL::INT_TYPE) }
+ end
+
+ context 'for a connection of objects' do
+ let(:object) do
+ Class.new(::Types::BaseObject) do
+ graphql_name 'Foo'
+ end
+ end
+
+ let(:resolver) do
+ conn = object.connection_type
+
+ Class.new(described_class) do
+ type conn, null: true
+ end
+ end
+
+ it { is_expected.to eq(object) }
+ end
+
+ context 'for a list type' do
+ let(:resolver) do
+ Class.new(described_class) do
+ type [::GraphQL::STRING_TYPE], null: true
+ end
+ end
+
+ it { is_expected.to eq(::GraphQL::STRING_TYPE) }
+ end
+
+ context 'for a scalar type' do
+ let(:resolver) do
+ Class.new(described_class) do
+ type ::GraphQL::BOOLEAN_TYPE, null: true
+ end
+ end
+
+ it { is_expected.to eq(::GraphQL::BOOLEAN_TYPE) }
+ end
+ end
+
describe '.single' do
it 'returns a subclass from the resolver' do
expect(resolver.single.superclass).to eq(resolver)
end
+ it 'has the correct (singular) type' do
+ expect(resolver.single.type).to eq(::GraphQL::INT_TYPE)
+ end
+
it 'returns the same subclass every time' do
expect(resolver.single.object_id).to eq(resolver.single.object_id)
end
@@ -37,15 +98,106 @@ RSpec.describe Resolvers::BaseResolver do
it 'returns a resolver that gives the first result from the original resolver' do
result = resolve(resolver.single, args: { test: 1 })
- expect(result).to eq(test: 1)
+ expect(result).to eq(1)
+ end
+ end
+
+ describe '.when_single' do
+ let(:resolver) do
+ Class.new(described_class) do
+ type [::GraphQL::INT_TYPE], null: true
+
+ when_single do
+ argument :foo, ::GraphQL::INT_TYPE, required: true
+ end
+
+ def resolve(foo: 1)
+ [foo * foo] # rubocop: disable Lint/BinaryOperatorWithIdenticalOperands
+ end
+ end
+ end
+
+ it 'does not apply the block to the resolver' do
+ expect(resolver.field_options).to include(
+ arguments: be_empty
+ )
+ result = resolve(resolver)
+
+ expect(result).to eq([1])
+ end
+
+ it 'applies the block to the single version of the resolver' do
+ expect(resolver.single.field_options).to include(
+ arguments: match('foo' => an_instance_of(::Types::BaseArgument))
+ )
+ result = resolve(resolver.single, args: { foo: 7 })
+
+ expect(result).to eq(49)
+ end
+
+ context 'multiple when_single blocks' do
+ let(:resolver) do
+ Class.new(described_class) do
+ type [::GraphQL::INT_TYPE], null: true
+
+ when_single do
+ argument :foo, ::GraphQL::INT_TYPE, required: true
+ end
+
+ when_single do
+ argument :bar, ::GraphQL::INT_TYPE, required: true
+ end
+
+ def resolve(foo: 1, bar: 2)
+ [foo * bar]
+ end
+ end
+ end
+
+ it 'applies both blocks to the single version of the resolver' do
+ expect(resolver.single.field_options).to include(
+ arguments: match('foo' => ::Types::BaseArgument, 'bar' => ::Types::BaseArgument)
+ )
+ result = resolve(resolver.single, args: { foo: 7, bar: 5 })
+
+ expect(result).to eq(35)
+ end
+ end
+
+ context 'inheritance' do
+ let(:subclass) do
+ Class.new(resolver) do
+ when_single do
+ argument :inc, ::GraphQL::INT_TYPE, required: true
+ end
+
+ def resolve(foo:, inc:)
+ super(foo: foo + inc)
+ end
+ end
+ end
+
+ it 'applies both blocks to the single version of the resolver' do
+ expect(resolver.single.field_options).to include(
+ arguments: match('foo' => ::Types::BaseArgument)
+ )
+ expect(subclass.single.field_options).to include(
+ arguments: match('foo' => ::Types::BaseArgument, 'inc' => ::Types::BaseArgument)
+ )
+ result = resolve(subclass.single, args: { foo: 7, inc: 1 })
+
+ expect(result).to eq(64)
+ end
end
end
context 'when the resolver returns early' do
let(:resolver) do
Class.new(described_class) do
+ type [::GraphQL::STRING_TYPE], null: true
+
def ready?(**args)
- [false, %w(early return)]
+ [false, %w[early return]]
end
def resolve(**args)
@@ -121,28 +273,4 @@ RSpec.describe Resolvers::BaseResolver do
end
end
end
-
- describe '#synchronized_object' do
- let(:object) { double(foo: :the_foo) }
-
- let(:resolver) do
- Class.new(described_class) do
- def resolve(**args)
- [synchronized_object.foo]
- end
- end
- end
-
- it 'handles raw objects' do
- expect(resolve(resolver, obj: object)).to contain_exactly(:the_foo)
- end
-
- it 'handles lazy objects' do
- delayed = BatchLoader::GraphQL.for(1).batch do |_, loader|
- loader.call(1, object)
- end
-
- expect(resolve(resolver, obj: delayed)).to contain_exactly(:the_foo)
- end
- end
end
diff --git a/spec/graphql/resolvers/ci/jobs_resolver_spec.rb b/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
new file mode 100644
index 00000000000..a836c89bd61
--- /dev/null
+++ b/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Ci::JobsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+
+ before_all do
+ create(:ci_build, name: 'Normal job', pipeline: pipeline)
+ create(:ci_build, :sast, name: 'DAST job', pipeline: pipeline)
+ create(:ci_build, :dast, name: 'SAST job', pipeline: pipeline)
+ create(:ci_build, :container_scanning, name: 'Container scanning job', pipeline: pipeline)
+ end
+
+ describe '#resolve' do
+ context 'when security_report_types is empty' do
+ it "returns all of the pipeline's jobs" do
+ jobs = resolve(described_class, obj: pipeline, args: {}, ctx: {})
+
+ job_names = jobs.map(&:name)
+ expect(job_names).to contain_exactly('Normal job', 'DAST job', 'SAST job', 'Container scanning job')
+ end
+ end
+
+ context 'when security_report_types is present' do
+ it "returns the pipeline's jobs with the given security report types" do
+ report_types = [
+ ::Types::Security::ReportTypeEnum.values['SAST'].value,
+ ::Types::Security::ReportTypeEnum.values['DAST'].value
+ ]
+ jobs = resolve(described_class, obj: pipeline, args: { security_report_types: report_types }, ctx: {})
+
+ job_names = jobs.map(&:name)
+ expect(job_names).to contain_exactly('DAST job', 'SAST job')
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb
new file mode 100644
index 00000000000..3d004290d9b
--- /dev/null
+++ b/spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb
@@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Ci::RunnerSetupResolver do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ let(:user) { create(:user) }
+
+ subject(:resolve_subject) { resolve(described_class, ctx: { current_user: user }, args: { platform: platform, architecture: 'amd64' }.merge(target_param)) }
+
+ context 'with container platforms' do
+ let(:platform) { 'docker' }
+ let(:project) { create(:project) }
+ let(:target_param) { { project_id: project.to_global_id } }
+
+ it 'returns install instructions' do
+ expect(resolve_subject[:install_instructions]).not_to eq(nil)
+ end
+
+ it 'does not return register instructions' do
+ expect(resolve_subject[:register_instructions]).to eq(nil)
+ end
+ end
+
+ context 'with regular platforms' do
+ let(:platform) { 'linux' }
+
+ context 'without target parameter' do
+ let(:target_param) { {} }
+
+ context 'when user is not admin' do
+ it 'returns access error' do
+ expect { resolve_subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'when user is admin' do
+ before do
+ user.update!(admin: true)
+ end
+
+ it 'returns install and register instructions' do
+ expect(resolve_subject.keys).to contain_exactly(:install_instructions, :register_instructions)
+ expect(resolve_subject.values).not_to include(nil)
+ end
+ end
+ end
+
+ context 'with project target parameter' do
+ let(:project) { create(:project) }
+ let(:target_param) { { project_id: project.to_global_id } }
+
+ context 'when user has access to admin builds on project' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'returns install and register instructions' do
+ expect(resolve_subject.keys).to contain_exactly(:install_instructions, :register_instructions)
+ expect(resolve_subject.values).not_to include(nil)
+ end
+ end
+
+ context 'when user does not have access to admin builds on project' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'returns access error' do
+ expect { resolve_subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ context 'with group target parameter' do
+ let(:group) { create(:group) }
+ let(:target_param) { { group_id: group.to_global_id } }
+
+ context 'when user has access to admin builds on group' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'returns install and register instructions' do
+ expect(resolve_subject.keys).to contain_exactly(:install_instructions, :register_instructions)
+ expect(resolve_subject.values).not_to include(nil)
+ end
+ end
+
+ context 'when user does not have access to admin builds on group' do
+ before do
+ group.add_developer(user)
+ end
+
+ it 'returns access error' do
+ expect { resolve_subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb b/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb
new file mode 100644
index 00000000000..b6fe94a2312
--- /dev/null
+++ b/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb
@@ -0,0 +1,208 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::CachingArrayResolver do
+ include GraphqlHelpers
+
+ let_it_be(:non_admins) { create_list(:user, 4, admin: false) }
+ let(:query_context) { {} }
+ let(:max_page_size) { 10 }
+ let(:field) { double('Field', max_page_size: max_page_size) }
+ let(:schema) { double('Schema', default_max_page_size: 3) }
+
+ let_it_be(:caching_resolver) do
+ mod = described_class
+
+ Class.new(::Resolvers::BaseResolver) do
+ include mod
+
+ def query_input(is_admin:)
+ is_admin
+ end
+
+ def query_for(is_admin)
+ if is_admin.nil?
+ model_class.all
+ else
+ model_class.where(admin: is_admin)
+ end
+ end
+
+ def model_class
+ User # Happens to include FromUnion, and is cheap-ish to create
+ end
+ end
+ end
+
+ describe '#resolve' do
+ context 'there are more than MAX_UNION_SIZE queries' do
+ let_it_be(:max_union) { 3 }
+ let_it_be(:resolver) do
+ mod = described_class
+ max = max_union
+
+ Class.new(::Resolvers::BaseResolver) do
+ include mod
+
+ def query_input(username:)
+ username
+ end
+
+ def query_for(username)
+ if username.nil?
+ model_class.all
+ else
+ model_class.where(username: username)
+ end
+ end
+
+ def model_class
+ User # Happens to include FromUnion, and is cheap-ish to create
+ end
+
+ define_method :max_union_size do
+ max
+ end
+ end
+ end
+
+ it 'executes the queries in multiple batches' do
+ users = create_list(:user, (max_union * 2) + 1)
+ expect(User).to receive(:from_union).twice.and_call_original
+
+ results = users.in_groups_of(2, false).map do |users|
+ resolve(resolver, args: { username: users.map(&:username) }, field: field, schema: schema)
+ end
+
+ expect(results.flat_map(&method(:force))).to match_array(users)
+ end
+ end
+
+ context 'all queries return results' do
+ let_it_be(:admins) { create_list(:admin, 3) }
+
+ it 'batches the queries' do
+ expect do
+ [resolve_users(true), resolve_users(false)].each(&method(:force))
+ end.to issue_same_number_of_queries_as { force(resolve_users(nil)) }
+ end
+
+ it 'finds the correct values' do
+ found_admins = resolve_users(true)
+ found_others = resolve_users(false)
+ admins_again = resolve_users(true)
+ found_all = resolve_users(nil)
+
+ expect(force(found_admins)).to match_array(admins)
+ expect(force(found_others)).to match_array(non_admins)
+ expect(force(admins_again)).to match_array(admins)
+ expect(force(found_all)).to match_array(admins + non_admins)
+ end
+ end
+
+ it 'does not perform a union of a query with itself' do
+ expect(User).to receive(:where).once.and_call_original
+
+ [resolve_users(false), resolve_users(false)].each(&method(:force))
+ end
+
+ context 'one of the queries returns no results' do
+ it 'finds the correct values' do
+ found_admins = resolve_users(true)
+ found_others = resolve_users(false)
+ found_all = resolve_users(nil)
+
+ expect(force(found_admins)).to be_empty
+ expect(force(found_others)).to match_array(non_admins)
+ expect(force(found_all)).to match_array(non_admins)
+ end
+ end
+
+ context 'one of the queries has already been cached' do
+ before do
+ force(resolve_users(nil))
+ end
+
+ it 'avoids further queries' do
+ expect do
+ repeated_find = resolve_users(nil)
+
+ expect(force(repeated_find)).to match_array(non_admins)
+ end.not_to exceed_query_limit(0)
+ end
+ end
+
+ context 'the resolver overrides item_found' do
+ let_it_be(:admins) { create_list(:admin, 2) }
+ let(:query_context) do
+ {
+ found: { true => [], false => [], nil => [] }
+ }
+ end
+
+ let_it_be(:with_item_found) do
+ Class.new(caching_resolver) do
+ def item_found(key, item)
+ context[:found][key] << item
+ end
+ end
+ end
+
+ it 'receives item_found for each key the item mapped to' do
+ found_admins = resolve_users(true, with_item_found)
+ found_all = resolve_users(nil, with_item_found)
+
+ [found_admins, found_all].each(&method(:force))
+
+ expect(query_context[:found]).to match({
+ false => be_empty,
+ true => match_array(admins),
+ nil => match_array(admins + non_admins)
+ })
+ end
+ end
+
+ context 'the max_page_size is lower than the total result size' do
+ let(:max_page_size) { 2 }
+
+ it 'respects the max_page_size, on a per subset basis' do
+ found_all = resolve_users(nil)
+ found_others = resolve_users(false)
+
+ expect(force(found_all).size).to eq(2)
+ expect(force(found_others).size).to eq(2)
+ end
+ end
+
+ context 'the field does not declare max_page_size' do
+ let(:max_page_size) { nil }
+
+ it 'takes the page size from schema.default_max_page_size' do
+ found_all = resolve_users(nil)
+ found_others = resolve_users(false)
+
+ expect(force(found_all).size).to eq(schema.default_max_page_size)
+ expect(force(found_others).size).to eq(schema.default_max_page_size)
+ end
+ end
+
+ specify 'force . resolve === to_a . query_for . query_input' do
+ r = resolver_instance(caching_resolver)
+ args = { is_admin: false }
+
+ naive = r.query_for(r.query_input(**args)).to_a
+
+ expect(force(r.resolve(**args))).to eq(naive)
+ end
+ end
+
+ def resolve_users(is_admin, resolver = caching_resolver)
+ args = { is_admin: is_admin }
+ resolve(resolver, args: args, field: field, ctx: query_context, schema: schema)
+ end
+
+ def force(lazy)
+ ::Gitlab::Graphql::Lazy.force(lazy)
+ end
+end
diff --git a/spec/graphql/resolvers/container_repositories_resolver_spec.rb b/spec/graphql/resolvers/container_repositories_resolver_spec.rb
new file mode 100644
index 00000000000..b888d79626e
--- /dev/null
+++ b/spec/graphql/resolvers/container_repositories_resolver_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::ContainerRepositoriesResolver do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be_with_reload(:project) { create(:project, group: group) }
+ let_it_be(:container_repositories) { create(:container_repository, project: project) }
+
+ let(:args) { {} }
+
+ describe '#resolve' do
+ let(:object) { project }
+
+ subject { resolve(described_class, ctx: { current_user: user }, args: args, obj: object) }
+
+ shared_examples 'returning container repositories' do
+ it { is_expected.to contain_exactly(container_repositories) }
+
+ context 'with a named search' do
+ let_it_be(:named_container_repository) { create(:container_repository, project: project, name: 'Foobar') }
+
+ let(:args) { { name: 'ooba' } }
+
+ it { is_expected.to contain_exactly(named_container_repository) }
+ end
+ end
+
+ context 'with authorized user' do
+ before do
+ group.add_user(user, :maintainer)
+ end
+
+ context 'when the object is a project' do
+ it_behaves_like 'returning container repositories'
+ end
+
+ context 'when the object is a group' do
+ let(:object) { group }
+
+ it_behaves_like 'returning container repositories'
+ end
+
+ context 'when the object is an invalid type' do
+ let(:object) { Object.new }
+
+ it { expect { subject }.to raise_exception('invalid subject_type') }
+ end
+ end
+
+ context 'with unauthorized user' do
+ it { is_expected.to be nil }
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/design_management/design_resolver_spec.rb b/spec/graphql/resolvers/design_management/design_resolver_spec.rb
index 02d7f94612c..e33eaedf167 100644
--- a/spec/graphql/resolvers/design_management/design_resolver_spec.rb
+++ b/spec/graphql/resolvers/design_management/design_resolver_spec.rb
@@ -6,6 +6,10 @@ RSpec.describe Resolvers::DesignManagement::DesignResolver do
include GraphqlHelpers
include DesignManagementTestHelpers
+ specify do
+ expect(described_class).to have_nullable_graphql_type(::Types::DesignManagement::DesignType)
+ end
+
before do
enable_design_management
end
@@ -57,12 +61,21 @@ RSpec.describe Resolvers::DesignManagement::DesignResolver do
end
context 'the ID belongs to a design on another issue' do
- let(:args) { { id: GitlabSchema.id_from_object(design_on_other_issue).to_s } }
+ let(:args) { { id: global_id_of(design_on_other_issue) } }
it 'returns nothing' do
expect(resolve_design).to be_nil
end
end
+
+ context 'the ID does not belong to a design at all' do
+ let(:args) { { id: global_id_of(issue) } }
+ let(:msg) { /does not represent an instance of DesignManagement::Design/ }
+
+ it 'complains meaningfully' do
+ expect { resolve_design }.to raise_error(msg)
+ end
+ end
end
context 'by filename' do
diff --git a/spec/graphql/resolvers/design_management/designs_resolver_spec.rb b/spec/graphql/resolvers/design_management/designs_resolver_spec.rb
index cfa37d34fd9..28e963c88a9 100644
--- a/spec/graphql/resolvers/design_management/designs_resolver_spec.rb
+++ b/spec/graphql/resolvers/design_management/designs_resolver_spec.rb
@@ -6,6 +6,10 @@ RSpec.describe Resolvers::DesignManagement::DesignsResolver do
include GraphqlHelpers
include DesignManagementTestHelpers
+ specify do
+ expect(described_class).to have_nullable_graphql_type(::Types::DesignManagement::DesignType.connection_type)
+ end
+
before do
enable_design_management
end
@@ -65,8 +69,24 @@ RSpec.describe Resolvers::DesignManagement::DesignsResolver do
let(:second_version) { create(:design_version) }
let(:second_design) { create(:design, issue: issue, versions: [second_version]) }
+ context 'ids is provided but null' do
+ let(:args) { { ids: nil } }
+
+ it 'behaves as if unfiltered' do
+ expect(resolve_designs).to contain_exactly(first_design, second_design)
+ end
+ end
+
+ context 'ids is provided but empty' do
+ let(:args) { { ids: [] } }
+
+ it 'eliminates all values' do
+ expect(resolve_designs).to be_empty
+ end
+ end
+
context 'the ID is on the current issue' do
- let(:args) { { ids: [GitlabSchema.id_from_object(second_design).to_s] } }
+ let(:args) { { ids: [GitlabSchema.id_from_object(second_design)] } }
it 'resolves to just the relevant design' do
expect(resolve_designs).to contain_exactly(second_design)
@@ -77,7 +97,7 @@ RSpec.describe Resolvers::DesignManagement::DesignsResolver do
let(:third_version) { create(:design_version) }
let(:third_design) { create(:design, issue: create(:issue, project: project), versions: [third_version]) }
- let(:args) { { ids: [GitlabSchema.id_from_object(third_design).to_s] } }
+ let(:args) { { ids: [GitlabSchema.id_from_object(third_design)] } }
it 'ignores it' do
expect(resolve_designs).to be_empty
diff --git a/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb b/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb
index 8ad928e9854..403261fc22a 100644
--- a/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb
+++ b/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe Resolvers::DesignManagement::VersionInCollectionResolver do
end
context 'we pass an id' do
- let(:params) { { id: global_id_of(first_version) } }
+ let(:params) { { version_id: global_id_of(first_version) } }
it { is_expected.to eq(first_version) }
end
@@ -44,13 +44,14 @@ RSpec.describe Resolvers::DesignManagement::VersionInCollectionResolver do
end
context 'we pass an inconsistent mixture of sha and version id' do
- let(:params) { { sha: first_version.sha, id: global_id_of(create(:design_version)) } }
+ let(:params) { { sha: first_version.sha, version_id: global_id_of(create(:design_version)) } }
it { is_expected.to be_nil }
end
context 'we pass the id of something that is not a design_version' do
- let(:params) { { id: global_id_of(project) } }
+ let(:params) { { version_id: global_id_of(project) } }
+ let(:appropriate_error) { ::GraphQL::CoercionError }
it 'raises an appropriate error' do
expect { result }.to raise_error(appropriate_error)
diff --git a/spec/graphql/resolvers/echo_resolver_spec.rb b/spec/graphql/resolvers/echo_resolver_spec.rb
index 2182ac221f6..4f48e5e0d7a 100644
--- a/spec/graphql/resolvers/echo_resolver_spec.rb
+++ b/spec/graphql/resolvers/echo_resolver_spec.rb
@@ -8,6 +8,10 @@ RSpec.describe Resolvers::EchoResolver do
let(:current_user) { create(:user) }
let(:text) { 'Message test' }
+ specify do
+ expect(described_class).to have_non_null_graphql_type(::GraphQL::STRING_TYPE)
+ end
+
describe '#resolve' do
it 'echoes text and username' do
expect(resolve_echo(text)).to eq %Q("#{current_user.username}" says: #{text})
diff --git a/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb b/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb
index 7e531910184..bf8d2139c82 100644
--- a/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb
+++ b/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb
@@ -10,6 +10,10 @@ RSpec.describe Resolvers::ErrorTracking::SentryDetailedErrorResolver do
let(:issue_details_service) { spy('ErrorTracking::IssueDetailsService') }
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::ErrorTracking::SentryDetailedErrorType)
+ end
+
before do
project.add_developer(current_user)
@@ -61,7 +65,9 @@ RSpec.describe Resolvers::ErrorTracking::SentryDetailedErrorResolver do
context 'blank id' do
let(:args) { { id: '' } }
- it_behaves_like 'it resolves to nil'
+ it 'responds with an error' do
+ expect { resolve_error(args) }.to raise_error(::GraphQL::CoercionError)
+ end
end
end
diff --git a/spec/graphql/resolvers/error_tracking/sentry_error_collection_resolver_spec.rb b/spec/graphql/resolvers/error_tracking/sentry_error_collection_resolver_spec.rb
index 02e0420be2a..20c2bdcd4e1 100644
--- a/spec/graphql/resolvers/error_tracking/sentry_error_collection_resolver_spec.rb
+++ b/spec/graphql/resolvers/error_tracking/sentry_error_collection_resolver_spec.rb
@@ -10,6 +10,10 @@ RSpec.describe Resolvers::ErrorTracking::SentryErrorCollectionResolver do
let(:list_issues_service) { spy('ErrorTracking::ListIssuesService') }
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::ErrorTracking::SentryErrorCollectionType)
+ end
+
before do
project.add_developer(current_user)
diff --git a/spec/graphql/resolvers/error_tracking/sentry_errors_resolver_spec.rb b/spec/graphql/resolvers/error_tracking/sentry_errors_resolver_spec.rb
index 554873a6e21..edca11f40d7 100644
--- a/spec/graphql/resolvers/error_tracking/sentry_errors_resolver_spec.rb
+++ b/spec/graphql/resolvers/error_tracking/sentry_errors_resolver_spec.rb
@@ -14,6 +14,10 @@ RSpec.describe Resolvers::ErrorTracking::SentryErrorsResolver do
let(:issues) { nil }
let(:pagination) { nil }
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::ErrorTracking::SentryErrorType.connection_type)
+ end
+
describe '#resolve' do
context 'insufficient user permission' do
let(:user) { create(:user) }
diff --git a/spec/graphql/resolvers/group_members_resolver_spec.rb b/spec/graphql/resolvers/group_members_resolver_spec.rb
index bbfea575492..bd0b4870062 100644
--- a/spec/graphql/resolvers/group_members_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_members_resolver_spec.rb
@@ -5,6 +5,10 @@ require 'spec_helper'
RSpec.describe Resolvers::GroupMembersResolver do
include GraphqlHelpers
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::GroupMemberType.connection_type)
+ end
+
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 }
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index 3a6507f906c..43cbd4d2bdd 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -20,6 +20,10 @@ RSpec.describe Resolvers::IssuesResolver do
let_it_be(:label1) { create(:label, project: project) }
let_it_be(:label2) { create(:label, project: project) }
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::IssueType.connection_type)
+ end
+
context "with a project" do
before do
project.add_developer(current_user)
diff --git a/spec/graphql/resolvers/merge_request_pipelines_resolver_spec.rb b/spec/graphql/resolvers/merge_request_pipelines_resolver_spec.rb
index ae3097c1d9e..deb5ff584cf 100644
--- a/spec/graphql/resolvers/merge_request_pipelines_resolver_spec.rb
+++ b/spec/graphql/resolvers/merge_request_pipelines_resolver_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe Resolvers::MergeRequestPipelinesResolver do
sha: merge_request.diff_head_sha
)
end
+
let_it_be(:other_project_pipeline) { create(:ci_pipeline, project: merge_request.source_project, ref: 'other-ref') }
let_it_be(:other_pipeline) { create(:ci_pipeline) }
let(:current_user) { create(:user) }
diff --git a/spec/graphql/resolvers/merge_requests_resolver_spec.rb b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
index aecffc487aa..3a3393a185c 100644
--- a/spec/graphql/resolvers/merge_requests_resolver_spec.rb
+++ b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
@@ -34,13 +34,13 @@ RSpec.describe Resolvers::MergeRequestsResolver do
context 'no arguments' do
it 'returns all merge requests' do
- result = resolve_mr(project, {})
+ 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, merge_request_with_milestone)
end
it 'returns only merge requests that the current user can see' do
- result = resolve_mr(project, {}, user: build(:user))
+ result = resolve_mr(project, user: build(:user))
expect(result).to be_empty
end
@@ -236,10 +236,10 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
def resolve_mr_single(project, iid)
- resolve_mr(project, { iids: iid }, resolver: described_class.single)
+ resolve_mr(project, resolver: described_class.single, iids: iid)
end
- def resolve_mr(project, args, resolver: described_class, user: current_user)
+ def resolve_mr(project, resolver: described_class, user: current_user, **args)
resolve(resolver, obj: project, args: args, ctx: { current_user: user })
end
end
diff --git a/spec/graphql/resolvers/metadata_resolver_spec.rb b/spec/graphql/resolvers/metadata_resolver_spec.rb
index 20556941de4..f8c01f9d531 100644
--- a/spec/graphql/resolvers/metadata_resolver_spec.rb
+++ b/spec/graphql/resolvers/metadata_resolver_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Resolvers::MetadataResolver do
describe '#resolve' do
it 'returns version and revision' do
- expect(resolve(described_class)).to eq(version: Gitlab::VERSION, revision: Gitlab.revision)
+ expect(resolve(described_class)).to have_attributes(version: Gitlab::VERSION, revision: Gitlab.revision)
end
end
end
diff --git a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
index a6a86c49373..1950c2ca067 100644
--- a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
@@ -10,6 +10,10 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
let_it_be(:other_pipeline) { create(:ci_pipeline) }
let(:current_user) { create(:user) }
+ specify do
+ expect(described_class).to have_nullable_graphql_type(::Types::Ci::PipelineType)
+ end
+
def resolve_pipeline(project, args)
resolve(described_class, obj: project, args: args, ctx: { current_user: current_user })
end
diff --git a/spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb b/spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb
index 0775c1c31d1..ad59cb6b95e 100644
--- a/spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb
@@ -5,6 +5,10 @@ require 'spec_helper'
RSpec.describe Resolvers::Projects::JiraImportsResolver do
include GraphqlHelpers
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::JiraImportType.connection_type)
+ end
+
describe '#resolve' do
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project, :public) }
diff --git a/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb b/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb
index 840aea8b8c4..c375345250d 100644
--- a/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb
@@ -5,6 +5,10 @@ require 'spec_helper'
RSpec.describe Resolvers::Projects::JiraProjectsResolver do
include GraphqlHelpers
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::Projects::Services::JiraProjectType.connection_type)
+ end
+
describe '#resolve' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
diff --git a/spec/graphql/resolvers/projects/services_resolver_spec.rb b/spec/graphql/resolvers/projects/services_resolver_spec.rb
index 8b6eff9e8b6..a1b631113b2 100644
--- a/spec/graphql/resolvers/projects/services_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects/services_resolver_spec.rb
@@ -5,6 +5,10 @@ require 'spec_helper'
RSpec.describe Resolvers::Projects::ServicesResolver do
include GraphqlHelpers
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::Projects::ServiceType.connection_type)
+ end
+
describe '#resolve' do
let_it_be(:user) { create(:user) }
diff --git a/spec/graphql/resolvers/projects/snippets_resolver_spec.rb b/spec/graphql/resolvers/projects/snippets_resolver_spec.rb
index b4a5eb8ddb0..6f7feff8fe5 100644
--- a/spec/graphql/resolvers/projects/snippets_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects/snippets_resolver_spec.rb
@@ -56,12 +56,6 @@ RSpec.describe Resolvers::Projects::SnippetsResolver do
expect(snippets).to contain_exactly(project_snippet, other_project_snippet)
end
-
- it 'returns an error if the gid is invalid' do
- expect do
- resolve_snippets(args: { ids: 'foo' })
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
- end
end
context 'when no project is provided' do
diff --git a/spec/graphql/resolvers/projects_resolver_spec.rb b/spec/graphql/resolvers/projects_resolver_spec.rb
index 83a26062957..3de54c7e410 100644
--- a/spec/graphql/resolvers/projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects_resolver_spec.rb
@@ -134,8 +134,8 @@ RSpec.describe Resolvers::ProjectsResolver do
is_expected.to eq([named_project3, named_project1, named_project2])
end
- it 'returns projects not in order of similarity to search if flag is off' do
- is_expected.not_to eq([named_project3, named_project1, named_project2])
+ it 'returns projects in any order if flag is off' do
+ is_expected.to match_array([named_project3, named_project1, named_project2])
end
end
end
diff --git a/spec/graphql/resolvers/release_resolver_spec.rb b/spec/graphql/resolvers/release_resolver_spec.rb
index 666d54fbc3c..04765fc68e9 100644
--- a/spec/graphql/resolvers/release_resolver_spec.rb
+++ b/spec/graphql/resolvers/release_resolver_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Resolvers::ReleaseResolver do
let(:args) { {} }
it 'raises an error' do
- expect { resolve_release }.to raise_error(ArgumentError, "missing keyword: tag_name")
+ expect { resolve_release }.to raise_error(ArgumentError, "missing keyword: :tag_name")
end
end
end
diff --git a/spec/graphql/resolvers/releases_resolver_spec.rb b/spec/graphql/resolvers/releases_resolver_spec.rb
index ee8b33fc748..b9b90686aa7 100644
--- a/spec/graphql/resolvers/releases_resolver_spec.rb
+++ b/spec/graphql/resolvers/releases_resolver_spec.rb
@@ -5,12 +5,19 @@ require 'spec_helper'
RSpec.describe Resolvers::ReleasesResolver do
include GraphqlHelpers
+ let_it_be(:today) { Time.now }
+ let_it_be(:yesterday) { today - 1.day }
+ let_it_be(:tomorrow) { today + 1.day }
+
let_it_be(:project) { create(:project, :private) }
- let_it_be(:release_v1) { create(:release, project: project, tag: 'v1.0.0') }
- let_it_be(:release_v2) { create(:release, project: project, tag: 'v2.0.0') }
+ let_it_be(:release_v1) { create(:release, project: project, tag: 'v1.0.0', released_at: yesterday, created_at: tomorrow) }
+ let_it_be(:release_v2) { create(:release, project: project, tag: 'v2.0.0', released_at: today, created_at: yesterday) }
+ let_it_be(:release_v3) { create(:release, project: project, tag: 'v3.0.0', released_at: tomorrow, created_at: today) }
let_it_be(:developer) { create(:user) }
let_it_be(:public_user) { create(:user) }
+ let(:args) { { sort: :released_at_desc } }
+
before do
project.add_developer(developer)
end
@@ -28,7 +35,41 @@ RSpec.describe Resolvers::ReleasesResolver do
let(:current_user) { developer }
it 'returns all releases associated to the project' do
- expect(resolve_releases).to eq([release_v1, release_v2])
+ expect(resolve_releases).to eq([release_v3, release_v2, release_v1])
+ end
+
+ describe 'sorting behavior' do
+ context 'with sort: :released_at_desc' do
+ let(:args) { { sort: :released_at_desc } }
+
+ it 'returns the releases ordered by released_at in descending order' do
+ expect(resolve_releases).to eq([release_v3, release_v2, release_v1])
+ end
+ end
+
+ context 'with sort: :released_at_asc' do
+ let(:args) { { sort: :released_at_asc } }
+
+ it 'returns the releases ordered by released_at in ascending order' do
+ expect(resolve_releases).to eq([release_v1, release_v2, release_v3])
+ end
+ end
+
+ context 'with sort: :created_desc' do
+ let(:args) { { sort: :created_desc } }
+
+ it 'returns the releases ordered by created_at in descending order' do
+ expect(resolve_releases).to eq([release_v1, release_v3, release_v2])
+ end
+ end
+
+ context 'with sort: :created_asc' do
+ let(:args) { { sort: :created_asc } }
+
+ it 'returns the releases ordered by created_at in ascending order' do
+ expect(resolve_releases).to eq([release_v2, release_v3, release_v1])
+ end
+ end
end
end
end
@@ -37,6 +78,6 @@ RSpec.describe Resolvers::ReleasesResolver do
def resolve_releases
context = { current_user: current_user }
- resolve(described_class, obj: project, args: {}, ctx: context)
+ resolve(described_class, obj: project, args: args, ctx: context)
end
end
diff --git a/spec/graphql/resolvers/snippets/blobs_resolver_spec.rb b/spec/graphql/resolvers/snippets/blobs_resolver_spec.rb
index fdbd87c32be..16e69f662c0 100644
--- a/spec/graphql/resolvers/snippets/blobs_resolver_spec.rb
+++ b/spec/graphql/resolvers/snippets/blobs_resolver_spec.rb
@@ -5,6 +5,10 @@ require 'spec_helper'
RSpec.describe Resolvers::Snippets::BlobsResolver do
include GraphqlHelpers
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::Snippets::BlobType.connection_type)
+ end
+
describe '#resolve' do
let_it_be(:current_user) { create(:user) }
let_it_be(:snippet) { create(:personal_snippet, :private, :repository, author: current_user) }
diff --git a/spec/graphql/resolvers/snippets_resolver_spec.rb b/spec/graphql/resolvers/snippets_resolver_spec.rb
index 180be8e8624..a58d9c5ac3a 100644
--- a/spec/graphql/resolvers/snippets_resolver_spec.rb
+++ b/spec/graphql/resolvers/snippets_resolver_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Resolvers::SnippetsResolver do
context 'when using filters' do
context 'by author id' do
it 'returns the snippets' do
- snippets = resolve_snippets(args: { author_id: current_user.to_global_id })
+ snippets = resolve_snippets(args: { author_id: global_id_of(current_user) })
expect(snippets).to contain_exactly(personal_snippet, project_snippet)
end
@@ -44,7 +44,7 @@ RSpec.describe Resolvers::SnippetsResolver do
it 'returns an error if the param id is invalid' do
expect do
resolve_snippets(args: { author_id: 'foo' })
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end.to raise_error(GraphQL::CoercionError)
end
end
@@ -65,7 +65,7 @@ RSpec.describe Resolvers::SnippetsResolver do
it 'returns an error if the param id is invalid' do
expect do
resolve_snippets(args: { project_id: 'foo' })
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end.to raise_error(GraphQL::CoercionError)
end
end
@@ -99,14 +99,14 @@ RSpec.describe Resolvers::SnippetsResolver do
expect(snippets).to contain_exactly(personal_snippet, project_snippet)
end
- it 'returns an error if the gid is invalid' do
+ it 'returns an error if the id cannot be coerced' do
args = {
ids: [personal_snippet.to_global_id, 'foo']
}
expect do
resolve_snippets(args: args)
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end.to raise_error(GraphQL::CoercionError, '"foo" is not a valid Global ID')
end
it 'returns an error if both project and author are provided' do
diff --git a/spec/graphql/resolvers/todo_resolver_spec.rb b/spec/graphql/resolvers/todo_resolver_spec.rb
index 83e3140b676..c764f389c16 100644
--- a/spec/graphql/resolvers/todo_resolver_spec.rb
+++ b/spec/graphql/resolvers/todo_resolver_spec.rb
@@ -5,6 +5,10 @@ require 'spec_helper'
RSpec.describe Resolvers::TodoResolver do
include GraphqlHelpers
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::TodoType.connection_type)
+ end
+
describe '#resolve' do
let_it_be(:current_user) { create(:user) }
let_it_be(:author1) { create(:user) }
diff --git a/spec/graphql/resolvers/tree_resolver_spec.rb b/spec/graphql/resolvers/tree_resolver_spec.rb
index 7818c25fe47..9eafd272771 100644
--- a/spec/graphql/resolvers/tree_resolver_spec.rb
+++ b/spec/graphql/resolvers/tree_resolver_spec.rb
@@ -7,6 +7,10 @@ RSpec.describe Resolvers::TreeResolver do
let(:repository) { create(:project, :repository).repository }
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::Tree::TreeType)
+ end
+
describe '#resolve' do
it 'resolves to a tree' do
result = resolve_repository({ ref: "master" })
diff --git a/spec/graphql/resolvers/users/group_count_resolver_spec.rb b/spec/graphql/resolvers/users/group_count_resolver_spec.rb
new file mode 100644
index 00000000000..47160a33646
--- /dev/null
+++ b/spec/graphql/resolvers/users/group_count_resolver_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Users::GroupCountResolver do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ let_it_be(:user1) { create(:user) }
+ let_it_be(:user2) { create(:user) }
+ let_it_be(:group1) { create(:group) }
+ let_it_be(:group2) { create(:group) }
+ let_it_be(:project) { create(:project, group: create(:group)) }
+ let_it_be(:group_member1) { create(:group_member, source: group1, user_id: user1.id, access_level: Gitlab::Access::OWNER) }
+ let_it_be(:project_member1) { create(:project_member, source: project, user_id: user1.id, access_level: Gitlab::Access::DEVELOPER) }
+ let_it_be(:group_member2) { create(:group_member, source: group2, user_id: user2.id, access_level: Gitlab::Access::DEVELOPER) }
+
+ it 'resolves group count for users' do
+ current_user = user1
+
+ result = batch_sync do
+ [user1, user2].map { |user| resolve_group_count(user, current_user) }
+ end
+
+ expect(result).to eq([2, nil])
+ end
+
+ context 'permissions' do
+ context 'when current_user is an admin', :enable_admin_mode do
+ let_it_be(:admin) { create(:admin) }
+
+ it do
+ result = batch_sync do
+ [user1, user2].map { |user| resolve_group_count(user, admin) }
+ end
+
+ expect(result).to eq([2, 1])
+ end
+ end
+
+ context 'when current_user does not have access to the requested resource' do
+ it do
+ result = batch_sync { resolve_group_count(user1, user2) }
+
+ expect(result).to be nil
+ end
+ end
+
+ context 'when current_user does not exist' do
+ it do
+ result = batch_sync { resolve_group_count(user1, nil) }
+
+ expect(result).to be nil
+ end
+ end
+ end
+ end
+
+ def resolve_group_count(user, current_user)
+ resolve(described_class, obj: user, ctx: { current_user: current_user })
+ end
+end
diff --git a/spec/graphql/resolvers/users/snippets_resolver_spec.rb b/spec/graphql/resolvers/users/snippets_resolver_spec.rb
index 497b6b11b46..9ccbebc59e6 100644
--- a/spec/graphql/resolvers/users/snippets_resolver_spec.rb
+++ b/spec/graphql/resolvers/users/snippets_resolver_spec.rb
@@ -73,7 +73,7 @@ RSpec.describe Resolvers::Users::SnippetsResolver do
expect do
resolve_snippets(args: args)
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end.to raise_error(GraphQL::CoercionError)
end
end
end
diff --git a/spec/graphql/resolvers/users_resolver_spec.rb b/spec/graphql/resolvers/users_resolver_spec.rb
index e3d595e0790..1aa24055a89 100644
--- a/spec/graphql/resolvers/users_resolver_spec.rb
+++ b/spec/graphql/resolvers/users_resolver_spec.rb
@@ -5,8 +5,12 @@ require 'spec_helper'
RSpec.describe Resolvers::UsersResolver do
include GraphqlHelpers
- let_it_be(:user1) { create(:user) }
- let_it_be(:user2) { create(:user) }
+ let_it_be(:user1) { create(:user, name: "SomePerson") }
+ let_it_be(:user2) { create(:user, username: "someone123784") }
+
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::UserType.connection_type)
+ end
describe '#resolve' do
it 'raises an error when read_users_list is not authorized' do
@@ -43,6 +47,14 @@ RSpec.describe Resolvers::UsersResolver do
).to contain_exactly(user1, user2)
end
end
+
+ context 'when a search term is passed' do
+ it 'returns all users who match', :aggregate_failures do
+ expect(resolve_users(search: "some")).to contain_exactly(user1, user2)
+ expect(resolve_users(search: "123784")).to contain_exactly(user2)
+ expect(resolve_users(search: "someperson")).to contain_exactly(user1)
+ end
+ end
end
def resolve_users(args = {})
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
index 625fb17bbf8..8a7408224a2 100644
--- 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
@@ -6,7 +6,10 @@ 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)
+ ee_only_identifiers = %w[billable_users]
+ identifiers = Analytics::InstanceStatistics::Measurement.identifiers.keys.reject do |x|
+ ee_only_identifiers.include?(x)
+ end.map(&:upcase)
expect(described_class.values.keys).to match_array(identifiers)
end
diff --git a/spec/graphql/types/alert_management/http_integration_type_spec.rb b/spec/graphql/types/alert_management/http_integration_type_spec.rb
new file mode 100644
index 00000000000..a4b64e2e37f
--- /dev/null
+++ b/spec/graphql/types/alert_management/http_integration_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['AlertManagementHttpIntegration'] do
+ specify { expect(described_class.graphql_name).to eq('AlertManagementHttpIntegration') }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_operations) }
+end
diff --git a/spec/graphql/types/alert_management/integration_type_enum_spec.rb b/spec/graphql/types/alert_management/integration_type_enum_spec.rb
new file mode 100644
index 00000000000..0cdd67cb140
--- /dev/null
+++ b/spec/graphql/types/alert_management/integration_type_enum_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['AlertManagementIntegrationType'] do
+ specify { expect(described_class.graphql_name).to eq('AlertManagementIntegrationType') }
+
+ describe 'statuses' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:name, :value) do
+ 'PROMETHEUS' | :prometheus
+ 'HTTP' | :http
+ end
+
+ with_them do
+ it 'exposes a type with the correct value' do
+ expect(described_class.values[name].value).to eq(value)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/types/alert_management/integration_type_spec.rb b/spec/graphql/types/alert_management/integration_type_spec.rb
new file mode 100644
index 00000000000..5d149e6da6e
--- /dev/null
+++ b/spec/graphql/types/alert_management/integration_type_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['AlertManagementIntegration'] do
+ specify { expect(described_class.graphql_name).to eq('AlertManagementIntegration') }
+
+ it 'exposes the expected fields' do
+ expected_fields = %i[
+ id
+ type
+ name
+ active
+ token
+ url
+ api_url
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/alert_management/prometheus_integration_type_spec.rb b/spec/graphql/types/alert_management/prometheus_integration_type_spec.rb
new file mode 100644
index 00000000000..0e9994035d8
--- /dev/null
+++ b/spec/graphql/types/alert_management/prometheus_integration_type_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['AlertManagementPrometheusIntegration'] do
+ include GraphqlHelpers
+
+ specify { expect(described_class.graphql_name).to eq('AlertManagementPrometheusIntegration') }
+ specify { expect(described_class).to require_graphql_authorizations(:admin_project) }
+
+ describe 'resolvers' do
+ shared_examples_for 'has field with value' do |field_name|
+ it 'correctly renders the field' do
+ expect(resolve_field(field_name, integration)).to eq(value)
+ end
+ end
+
+ let_it_be_with_reload(:integration) { create(:prometheus_service) }
+
+ it_behaves_like 'has field with value', 'name' do
+ let(:value) { integration.title }
+ end
+
+ it_behaves_like 'has field with value', 'type' do
+ let(:value) { :prometheus }
+ end
+
+ it_behaves_like 'has field with value', 'token' do
+ let(:value) { nil }
+ end
+
+ it_behaves_like 'has field with value', 'url' do
+ let(:value) { "http://localhost/#{integration.project.full_path}/prometheus/alerts/notify.json" }
+ end
+
+ it_behaves_like 'has field with value', 'active' do
+ let(:value) { integration.manual_configuration? }
+ end
+
+ context 'with alerting setting' do
+ let_it_be(:alerting_setting) { create(:project_alerting_setting, project: integration.project) }
+
+ it_behaves_like 'has field with value', 'token' do
+ let(:value) { alerting_setting.token }
+ end
+ end
+
+ context 'without project' do
+ let_it_be(:integration) { create(:prometheus_service, project: nil, group: create(:group)) }
+
+ it_behaves_like 'has field with value', 'token' do
+ let(:value) { nil }
+ end
+
+ it_behaves_like 'has field with value', 'url' do
+ let(:value) { nil }
+ end
+ end
+ end
+end
diff --git a/spec/graphql/types/availability_enum_spec.rb b/spec/graphql/types/availability_enum_spec.rb
new file mode 100644
index 00000000000..a9bdf5e4da6
--- /dev/null
+++ b/spec/graphql/types/availability_enum_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['AvailabilityEnum'] do
+ specify { expect(described_class.graphql_name).to eq('AvailabilityEnum') }
+
+ it 'exposes all the existing access levels' do
+ expect(described_class.values.keys).to match_array(%w[NOT_SET BUSY])
+ end
+end
diff --git a/spec/graphql/types/ci/detailed_status_type_spec.rb b/spec/graphql/types/ci/detailed_status_type_spec.rb
index ddb3a1450df..9fa3280657a 100644
--- a/spec/graphql/types/ci/detailed_status_type_spec.rb
+++ b/spec/graphql/types/ci/detailed_status_type_spec.rb
@@ -3,11 +3,30 @@
require 'spec_helper'
RSpec.describe Types::Ci::DetailedStatusType do
+ include GraphqlHelpers
+
specify { expect(described_class.graphql_name).to eq('DetailedStatus') }
- it "has all fields" do
+ it 'has all fields' do
expect(described_class).to have_graphql_fields(:group, :icon, :favicon,
:details_path, :has_details,
:label, :text, :tooltip, :action)
end
+
+ describe 'action field' do
+ it 'correctly renders the field' do
+ stage = create(:ci_stage_entity, status: :skipped)
+ status = stage.detailed_status(stage.pipeline.user)
+
+ expected_status = {
+ button_title: status.action_button_title,
+ icon: status.action_icon,
+ method: status.action_method,
+ path: status.action_path,
+ title: status.action_title
+ }
+
+ expect(resolve_field('action', status)).to eq(expected_status)
+ end
+ end
end
diff --git a/spec/graphql/types/ci/job_type_spec.rb b/spec/graphql/types/ci/job_type_spec.rb
index 3a54ed2efed..3dcb81eefbf 100644
--- a/spec/graphql/types/ci/job_type_spec.rb
+++ b/spec/graphql/types/ci/job_type_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Types::Ci::JobType do
it 'exposes the expected fields' do
expected_fields = %i[
+ pipeline
name
needs
detailedStatus
diff --git a/spec/graphql/types/ci/runner_setup_type_spec.rb b/spec/graphql/types/ci/runner_setup_type_spec.rb
new file mode 100644
index 00000000000..197e717e964
--- /dev/null
+++ b/spec/graphql/types/ci/runner_setup_type_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::RunnerSetupType do
+ specify { expect(described_class.graphql_name).to eq('RunnerSetup') }
+
+ it 'exposes the expected fields' do
+ expected_fields = %i[
+ install_instructions
+ register_instructions
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/commit_type_spec.rb b/spec/graphql/types/commit_type_spec.rb
index d222287270d..e9bc7f6bb94 100644
--- a/spec/graphql/types/commit_type_spec.rb
+++ b/spec/graphql/types/commit_type_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe GitlabSchema.types['Commit'] do
it 'contains attributes related to commit' do
expect(described_class).to have_graphql_fields(
:id, :sha, :title, :description, :description_html, :message, :title_html, :authored_date,
- :author_name, :author_gravatar, :author, :web_url, :web_path, :latest_pipeline,
+ :author_name, :author_gravatar, :author, :web_url, :web_path,
:pipelines, :signature_html
)
end
diff --git a/spec/graphql/types/container_repository_cleanup_status_enum_spec.rb b/spec/graphql/types/container_repository_cleanup_status_enum_spec.rb
new file mode 100644
index 00000000000..36cfc789ee9
--- /dev/null
+++ b/spec/graphql/types/container_repository_cleanup_status_enum_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ContainerRepositoryCleanupStatus'] do
+ it 'exposes all statuses' do
+ expected_keys = ContainerRepository.expiration_policy_cleanup_statuses
+ .keys
+ .map { |k| k.gsub('cleanup_', '') }
+ .map(&:upcase)
+ expect(described_class.values.keys).to contain_exactly(*expected_keys)
+ end
+end
diff --git a/spec/graphql/types/container_repository_details_type_spec.rb b/spec/graphql/types/container_repository_details_type_spec.rb
new file mode 100644
index 00000000000..b5ff460fcf7
--- /dev/null
+++ b/spec/graphql/types/container_repository_details_type_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ContainerRepositoryDetails'] do
+ fields = %i[id name path location created_at updated_at expiration_policy_started_at status tags_count can_delete expiration_policy_cleanup_status tags]
+
+ it { expect(described_class.graphql_name).to eq('ContainerRepositoryDetails') }
+
+ it { expect(described_class.description).to eq('Details of a container repository') }
+
+ it { expect(described_class).to require_graphql_authorizations(:read_container_image) }
+
+ it { expect(described_class).to have_graphql_fields(fields) }
+
+ describe 'tags field' do
+ subject { described_class.fields['tags'] }
+
+ it 'returns tags connection type' do
+ is_expected.to have_graphql_type(Types::ContainerRepositoryTagType.connection_type)
+ end
+ end
+end
diff --git a/spec/graphql/types/container_repository_status_enum_spec.rb b/spec/graphql/types/container_repository_status_enum_spec.rb
new file mode 100644
index 00000000000..9598879779a
--- /dev/null
+++ b/spec/graphql/types/container_repository_status_enum_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ContainerRepositoryStatus'] do
+ it 'exposes all statuses' do
+ expect(described_class.values.keys).to contain_exactly(*ContainerRepository.statuses.keys.map(&:upcase))
+ end
+end
diff --git a/spec/graphql/types/container_repository_tag_type_spec.rb b/spec/graphql/types/container_repository_tag_type_spec.rb
new file mode 100644
index 00000000000..1d1a76d6916
--- /dev/null
+++ b/spec/graphql/types/container_repository_tag_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ContainerRepositoryTag'] do
+ fields = %i[name path location digest revision short_revision total_size created_at can_delete]
+
+ it { expect(described_class.graphql_name).to eq('ContainerRepositoryTag') }
+
+ it { expect(described_class.description).to eq('A tag from a container repository') }
+
+ it { expect(described_class).to require_graphql_authorizations(:read_container_image) }
+
+ it { expect(described_class).to have_graphql_fields(fields) }
+end
diff --git a/spec/graphql/types/container_repository_type_spec.rb b/spec/graphql/types/container_repository_type_spec.rb
new file mode 100644
index 00000000000..3d3445ba5c3
--- /dev/null
+++ b/spec/graphql/types/container_repository_type_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ContainerRepository'] do
+ fields = %i[id name path location created_at updated_at expiration_policy_started_at status tags_count can_delete expiration_policy_cleanup_status]
+
+ it { expect(described_class.graphql_name).to eq('ContainerRepository') }
+
+ it { expect(described_class.description).to eq('A container repository') }
+
+ it { expect(described_class).to require_graphql_authorizations(:read_container_image) }
+
+ it { expect(described_class).to have_graphql_fields(fields) }
+
+ describe 'status field' do
+ subject { described_class.fields['status'] }
+
+ it 'returns status enum' do
+ is_expected.to have_graphql_type(Types::ContainerRepositoryStatusEnum)
+ end
+ end
+
+ describe 'expiration_policy_cleanup_status field' do
+ subject { described_class.fields['expirationPolicyCleanupStatus'] }
+
+ it 'returns cleanup status enum' do
+ is_expected.to have_graphql_type(Types::ContainerRepositoryCleanupStatusEnum)
+ end
+ end
+end
diff --git a/spec/graphql/types/countable_connection_type_spec.rb b/spec/graphql/types/countable_connection_type_spec.rb
index af34611ecfe..3b3c02baa5d 100644
--- a/spec/graphql/types/countable_connection_type_spec.rb
+++ b/spec/graphql/types/countable_connection_type_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe GitlabSchema.types['IssueConnection'] do
+RSpec.describe GitlabSchema.types['MergeRequestConnection'] do
it 'has the expected fields' do
expected_fields = %i[count page_info edges nodes]
diff --git a/spec/graphql/types/custom_emoji_type_spec.rb b/spec/graphql/types/custom_emoji_type_spec.rb
new file mode 100644
index 00000000000..7f3c99e4b63
--- /dev/null
+++ b/spec/graphql/types/custom_emoji_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['CustomEmoji'] do
+ specify { expect(described_class.graphql_name).to eq('CustomEmoji') }
+
+ specify { expect(described_class).to require_graphql_authorizations(:read_custom_emoji) }
+
+ specify { expect(described_class).to have_graphql_fields(:id, :name, :url, :external) }
+end
diff --git a/spec/graphql/types/environment_type_spec.rb b/spec/graphql/types/environment_type_spec.rb
index 2220f847e4e..3671d35e8a5 100644
--- a/spec/graphql/types/environment_type_spec.rb
+++ b/spec/graphql/types/environment_type_spec.rb
@@ -44,18 +44,12 @@ RSpec.describe GitlabSchema.types['Environment'] do
expect(subject['data']['project']['environment']['name']).to eq(environment.name)
end
- it 'returns the path when the feature is enabled' do
+ it 'returns the path to the environment' do
expect(subject['data']['project']['environment']['path']).to eq(
Gitlab::Routing.url_helpers.project_environment_path(project, environment)
)
end
- it 'does not return the path when the feature is disabled' do
- stub_feature_flags(expose_environment_path_in_alert_details: false)
-
- expect(subject['data']['project']['environment']['path']).to be_nil
- end
-
context 'when query alert data for the environment' do
let_it_be(:query) do
%(
diff --git a/spec/graphql/types/global_id_type_spec.rb b/spec/graphql/types/global_id_type_spec.rb
index 7589b0e285e..cb129868f7e 100644
--- a/spec/graphql/types/global_id_type_spec.rb
+++ b/spec/graphql/types/global_id_type_spec.rb
@@ -45,8 +45,7 @@ RSpec.describe Types::GlobalIDType do
end
it 'rejects nil' do
- expect { described_class.coerce_isolated_input(nil) }
- .to raise_error(GraphQL::CoercionError)
+ expect(described_class.coerce_isolated_input(nil)).to be_nil
end
it 'rejects gids from different apps' do
diff --git a/spec/graphql/types/grafana_integration_type_spec.rb b/spec/graphql/types/grafana_integration_type_spec.rb
index b4658db08d7..816264c36c8 100644
--- a/spec/graphql/types/grafana_integration_type_spec.rb
+++ b/spec/graphql/types/grafana_integration_type_spec.rb
@@ -7,7 +7,6 @@ RSpec.describe GitlabSchema.types['GrafanaIntegration'] do
%i[
id
grafana_url
- token
enabled
created_at
updated_at
diff --git a/spec/graphql/types/group_invitation_type_spec.rb b/spec/graphql/types/group_invitation_type_spec.rb
new file mode 100644
index 00000000000..dab2d43fc90
--- /dev/null
+++ b/spec/graphql/types/group_invitation_type_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::GroupInvitationType do
+ specify { expect(described_class).to expose_permissions_using(Types::PermissionTypes::Group) }
+
+ specify { expect(described_class.graphql_name).to eq('GroupInvitation') }
+
+ specify { expect(described_class).to require_graphql_authorizations(:read_group) }
+
+ it 'has the expected fields' do
+ expected_fields = %w[
+ email access_level created_by created_at updated_at expires_at group
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/invitation_interface_spec.rb b/spec/graphql/types/invitation_interface_spec.rb
new file mode 100644
index 00000000000..8f345c58ca3
--- /dev/null
+++ b/spec/graphql/types/invitation_interface_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::InvitationInterface do
+ it 'exposes the expected fields' do
+ expected_fields = %i[
+ email
+ 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::ProjectInvitationType }
+ end
+
+ context 'for group member' do
+ let(:object) { build(:group_member) }
+
+ it { is_expected.to be Types::GroupInvitationType }
+ end
+
+ context 'for an unknown 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/issue_type_spec.rb b/spec/graphql/types/issue_type_spec.rb
index c55e624dd11..558fc479af1 100644
--- a/spec/graphql/types/issue_type_spec.rb
+++ b/spec/graphql/types/issue_type_spec.rb
@@ -14,10 +14,10 @@ RSpec.describe GitlabSchema.types['Issue'] do
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 alert_management_alert severity current_user_todos]
+ fields = %i[id iid title description state reference author assignees updated_by participants labels milestone due_date
+ confidential discussion_locked upvotes downvotes user_notes_count user_discussions_count web_path web_url relative_position
+ emails_disabled subscribed time_estimate total_time_spent human_time_estimate human_total_time_spent closed_at created_at updated_at task_completion_status
+ design_collection alert_management_alert severity current_user_todos moved moved_to]
fields.each do |field_name|
expect(described_class).to have_graphql_field(field_name)
diff --git a/spec/graphql/types/merge_request_type_spec.rb b/spec/graphql/types/merge_request_type_spec.rb
index 9d901655b7b..8800250b103 100644
--- a/spec/graphql/types/merge_request_type_spec.rb
+++ b/spec/graphql/types/merge_request_type_spec.rb
@@ -17,11 +17,11 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do
description_html state created_at updated_at source_project target_project
project project_id source_project_id target_project_id source_branch
target_branch work_in_progress merge_when_pipeline_succeeds diff_head_sha
- merge_commit_sha user_notes_count should_remove_source_branch
+ merge_commit_sha user_notes_count user_discussions_count should_remove_source_branch
diff_refs diff_stats diff_stats_summary
force_remove_source_branch merge_status in_progress_merge_commit_sha
merge_error allow_collaboration should_be_rebased rebase_commit_sha
- rebase_in_progress merge_commit_message default_merge_commit_message
+ rebase_in_progress default_merge_commit_message
merge_ongoing mergeable_discussions_state web_url
source_branch_exists target_branch_exists
upvotes downvotes head_pipeline pipelines task_completion_status
diff --git a/spec/graphql/types/permission_types/note_spec.rb b/spec/graphql/types/permission_types/note_spec.rb
index 9769c7b3aa3..d75284951c7 100644
--- a/spec/graphql/types/permission_types/note_spec.rb
+++ b/spec/graphql/types/permission_types/note_spec.rb
@@ -5,9 +5,9 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['NotePermissions'] do
it 'has the expected fields' do
expected_permissions = [
- :read_note, :create_note, :admin_note, :resolve_note, :award_emoji
+ :read_note, :create_note, :admin_note, :resolve_note, :reposition_note, :award_emoji
]
- expect(described_class).to have_graphql_fields(expected_permissions)
+ expect(described_class).to have_graphql_fields(expected_permissions).only
end
end
diff --git a/spec/graphql/types/project_invitation_type_spec.rb b/spec/graphql/types/project_invitation_type_spec.rb
new file mode 100644
index 00000000000..148a763a5fa
--- /dev/null
+++ b/spec/graphql/types/project_invitation_type_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::ProjectInvitationType do
+ specify { expect(described_class).to expose_permissions_using(Types::PermissionTypes::Project) }
+
+ specify { expect(described_class.graphql_name).to eq('ProjectInvitation') }
+
+ specify { expect(described_class).to require_graphql_authorizations(:read_project) }
+
+ it 'has the expected fields' do
+ expected_fields = %w[
+ access_level created_by created_at updated_at expires_at project user
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/project_statistics_type_spec.rb b/spec/graphql/types/project_statistics_type_spec.rb
index e6cffd407de..407ce82e73a 100644
--- a/spec/graphql/types/project_statistics_type_spec.rb
+++ b/spec/graphql/types/project_statistics_type_spec.rb
@@ -6,6 +6,6 @@ RSpec.describe GitlabSchema.types['ProjectStatistics'] do
it 'has all the required fields' do
expect(described_class).to have_graphql_fields(:storage_size, :repository_size, :lfs_objects_size,
:build_artifacts_size, :packages_size, :commit_count,
- :wiki_size, :snippets_size)
+ :wiki_size, :snippets_size, :uploads_size)
end
end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 8aa9e1138cc..be579e92fb3 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -27,7 +27,8 @@ RSpec.describe GitlabSchema.types['Project'] do
environment boards jira_import_status jira_imports services releases release
alert_management_alerts alert_management_alert alert_management_alert_status_counts
container_expiration_policy service_desk_enabled service_desk_address
- issue_status_counts terraform_states
+ issue_status_counts terraform_states alert_management_integrations
+
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/projects/services_enum_spec.rb b/spec/graphql/types/projects/services_enum_spec.rb
index dac1213daf3..b8da9305de4 100644
--- a/spec/graphql/types/projects/services_enum_spec.rb
+++ b/spec/graphql/types/projects/services_enum_spec.rb
@@ -11,5 +11,5 @@ RSpec.describe GitlabSchema.types['ServiceType'] do
end
def available_services_enum
- ::Service.services_types.map(&:underscore).map(&:upcase)
+ ::Service.available_services_types(include_dev: false).map(&:underscore).map(&:upcase)
end
diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb
index 1d9ca8323f8..7a0b3035607 100644
--- a/spec/graphql/types/query_type_spec.rb
+++ b/spec/graphql/types/query_type_spec.rb
@@ -80,4 +80,18 @@ RSpec.describe GitlabSchema.types['Query'] do
is_expected.to have_graphql_type(Types::Ci::RunnerPlatformType.connection_type)
end
end
+
+ describe 'runner_setup field' do
+ subject { described_class.fields['runnerSetup'] }
+
+ it 'returns runner setup instructions' do
+ is_expected.to have_graphql_type(Types::Ci::RunnerSetupType)
+ end
+ end
+
+ describe 'container_repository field' do
+ subject { described_class.fields['containerRepository'] }
+
+ it { is_expected.to have_graphql_type(Types::ContainerRepositoryDetailsType) }
+ end
end
diff --git a/spec/graphql/types/release_asset_link_input_type_spec.rb b/spec/graphql/types/release_asset_link_input_type_spec.rb
new file mode 100644
index 00000000000..d97a91b609a
--- /dev/null
+++ b/spec/graphql/types/release_asset_link_input_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::ReleaseAssetLinkInputType do
+ specify { expect(described_class.graphql_name).to eq('ReleaseAssetLinkInput') }
+
+ it 'has the correct arguments' do
+ expect(described_class.arguments.keys).to match_array(%w[name url directAssetPath linkType])
+ end
+
+ it 'sets the type of link_type argument to ReleaseAssetLinkTypeEnum' do
+ expect(described_class.arguments['linkType'].type).to eq(Types::ReleaseAssetLinkTypeEnum)
+ end
+end
diff --git a/spec/graphql/types/release_assets_input_type_spec.rb b/spec/graphql/types/release_assets_input_type_spec.rb
new file mode 100644
index 00000000000..c44abe1e171
--- /dev/null
+++ b/spec/graphql/types/release_assets_input_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::ReleaseAssetsInputType do
+ specify { expect(described_class.graphql_name).to eq('ReleaseAssetsInput') }
+
+ it 'has the correct arguments' do
+ expect(described_class.arguments.keys).to match_array(%w[links])
+ end
+
+ it 'sets the type of links argument to ReleaseAssetLinkInputType' do
+ expect(described_class.arguments['links'].type.of_type.of_type).to eq(Types::ReleaseAssetLinkInputType)
+ end
+end
diff --git a/spec/graphql/types/release_links_type_spec.rb b/spec/graphql/types/release_links_type_spec.rb
index d505f0a4b5c..38c38d58baa 100644
--- a/spec/graphql/types/release_links_type_spec.rb
+++ b/spec/graphql/types/release_links_type_spec.rb
@@ -8,8 +8,11 @@ RSpec.describe GitlabSchema.types['ReleaseLinks'] do
it 'has the expected fields' do
expected_fields = %w[
selfUrl
- mergeRequestsUrl
- issuesUrl
+ openedMergeRequestsUrl
+ mergedMergeRequestsUrl
+ closedMergeRequestsUrl
+ openedIssuesUrl
+ closedIssuesUrl
editUrl
]
diff --git a/spec/graphql/types/root_storage_statistics_type_spec.rb b/spec/graphql/types/root_storage_statistics_type_spec.rb
index 79d474f13ad..4fef8f6eafd 100644
--- a/spec/graphql/types/root_storage_statistics_type_spec.rb
+++ b/spec/graphql/types/root_storage_statistics_type_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe GitlabSchema.types['RootStorageStatistics'] do
it 'has all the required fields' do
expect(described_class).to have_graphql_fields(:storage_size, :repository_size, :lfs_objects_size,
:build_artifacts_size, :packages_size, :wiki_size, :snippets_size,
- :pipeline_artifacts_size)
+ :pipeline_artifacts_size, :uploads_size)
end
specify { expect(described_class).to require_graphql_authorizations(:read_statistics) }
diff --git a/spec/graphql/types/security/report_types_enum_spec.rb b/spec/graphql/types/security/report_types_enum_spec.rb
new file mode 100644
index 00000000000..2da852606c7
--- /dev/null
+++ b/spec/graphql/types/security/report_types_enum_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['SecurityReportTypeEnum'] do
+ it 'exposes all security report types' do
+ expect(described_class.values.keys).to contain_exactly(
+ *::Security::SecurityJobsFinder.allowed_job_types.map(&:to_s).map(&:upcase)
+ )
+ end
+end
diff --git a/spec/graphql/types/terraform/state_type_spec.rb b/spec/graphql/types/terraform/state_type_spec.rb
index 51508208046..9f65bb926d7 100644
--- a/spec/graphql/types/terraform/state_type_spec.rb
+++ b/spec/graphql/types/terraform/state_type_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['TerraformState'] do
it { expect(described_class).to require_graphql_authorizations(:read_terraform_state) }
describe 'fields' do
- let(:fields) { %i[id name locked_by_user locked_at created_at updated_at] }
+ let(:fields) { %i[id name locked_by_user locked_at latest_version created_at updated_at] }
it { expect(described_class).to have_graphql_fields(fields) }
@@ -17,5 +17,8 @@ RSpec.describe GitlabSchema.types['TerraformState'] do
it { expect(described_class.fields['lockedAt'].type).not_to be_non_null }
it { expect(described_class.fields['createdAt'].type).to be_non_null }
it { expect(described_class.fields['updatedAt'].type).to be_non_null }
+
+ it { expect(described_class.fields['latestVersion'].type).not_to be_non_null }
+ it { expect(described_class.fields['latestVersion'].complexity).to eq(3) }
end
end
diff --git a/spec/graphql/types/terraform/state_version_type_spec.rb b/spec/graphql/types/terraform/state_version_type_spec.rb
new file mode 100644
index 00000000000..1c1e95039dc
--- /dev/null
+++ b/spec/graphql/types/terraform/state_version_type_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['TerraformStateVersion'] do
+ it { expect(described_class.graphql_name).to eq('TerraformStateVersion') }
+ it { expect(described_class).to require_graphql_authorizations(:read_terraform_state) }
+
+ describe 'fields' do
+ let(:fields) { %i[id created_by_user job created_at updated_at] }
+
+ it { expect(described_class).to have_graphql_fields(fields) }
+
+ it { expect(described_class.fields['id'].type).to be_non_null }
+ it { expect(described_class.fields['createdByUser'].type).not_to be_non_null }
+ it { expect(described_class.fields['job'].type).not_to be_non_null }
+ it { expect(described_class.fields['createdAt'].type).to be_non_null }
+ it { expect(described_class.fields['updatedAt'].type).to be_non_null }
+ end
+end
diff --git a/spec/graphql/types/user_status_type_spec.rb b/spec/graphql/types/user_status_type_spec.rb
index c4421a9cc10..ced9c40d552 100644
--- a/spec/graphql/types/user_status_type_spec.rb
+++ b/spec/graphql/types/user_status_type_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe Types::UserStatusType do
emoji
message
message_html
+ availability
]
expect(described_class).to have_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/user_type_spec.rb b/spec/graphql/types/user_type_spec.rb
index 1d5af24b3d9..c8953d9ccb7 100644
--- a/spec/graphql/types/user_type_spec.rb
+++ b/spec/graphql/types/user_type_spec.rb
@@ -24,6 +24,7 @@ RSpec.describe GitlabSchema.types['User'] do
authoredMergeRequests
assignedMergeRequests
groupMemberships
+ groupCount
projectMemberships
starredProjects
]
diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb
index 7f25721801f..479e2d7ef9d 100644
--- a/spec/helpers/application_settings_helper_spec.rb
+++ b/spec/helpers/application_settings_helper_spec.rb
@@ -166,4 +166,32 @@ RSpec.describe ApplicationSettingsHelper do
it { is_expected.to eq(false) }
end
end
+
+ describe '.signup_enabled?' do
+ subject { helper.signup_enabled? }
+
+ context 'when signup is enabled' do
+ before do
+ stub_application_setting(signup_enabled: true)
+ end
+
+ it { is_expected.to be true }
+ end
+
+ context 'when signup is disabled' do
+ before do
+ stub_application_setting(signup_enabled: false)
+ end
+
+ it { is_expected.to be false }
+ end
+
+ context 'when `signup_enabled` is nil' do
+ before do
+ stub_application_setting(signup_enabled: nil)
+ end
+
+ it { is_expected.to be false }
+ end
+ end
end
diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
index e0d316baa17..b4cea7fb695 100644
--- a/spec/helpers/auth_helper_spec.rb
+++ b/spec/helpers/auth_helper_spec.rb
@@ -260,4 +260,41 @@ RSpec.describe AuthHelper do
end
end
end
+
+ describe '#google_tag_manager_enabled?' do
+ let(:is_gitlab_com) { true }
+ let(:user) { nil }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(is_gitlab_com)
+ stub_config(extra: { google_tag_manager_id: 'key' })
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ subject(:google_tag_manager_enabled?) { helper.google_tag_manager_enabled? }
+
+ context 'on gitlab.com and a key set without a current user' do
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when not on gitlab.com' do
+ let(:is_gitlab_com) { false }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when current user is set' do
+ let(:user) { instance_double('User') }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when no key is set' do
+ before do
+ stub_config(extra: {})
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
end
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index baa97781efa..cafe4c4275e 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -236,11 +236,7 @@ RSpec.describe BlobHelper do
let(:data) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
let(:blob) { fake_blob(path: Gitlab::FileDetector::PATTERNS[:gitlab_ci], data: data) }
- context 'experiment enabled' do
- before do
- allow(helper).to receive(:experiment_enabled?).and_return(true)
- end
-
+ context 'feature enabled' do
it 'is true' do
expect(helper.show_suggest_pipeline_creation_celebration?).to be_truthy
end
@@ -284,9 +280,9 @@ RSpec.describe BlobHelper do
end
end
- context 'experiment disabled' do
+ context 'feature disabled' do
before do
- allow(helper).to receive(:experiment_enabled?).and_return(false)
+ stub_feature_flags(suggest_pipeline: false)
end
it 'is false' do
@@ -298,11 +294,7 @@ RSpec.describe BlobHelper do
context 'when file is not a pipeline config file' do
let(:blob) { fake_blob(path: 'LICENSE') }
- context 'experiment enabled' do
- before do
- allow(helper).to receive(:experiment_enabled?).and_return(true)
- end
-
+ context 'feature enabled' do
it 'is false' do
expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
end
@@ -444,6 +436,55 @@ RSpec.describe BlobHelper do
end
end
+ describe '#ide_merge_request_path' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project)}
+
+ it 'returns IDE path for the given MR if MR is not merged' do
+ expect(helper.ide_merge_request_path(merge_request)).to eq("/-/ide/project/#{project.full_path}/merge_requests/#{merge_request.iid}")
+ end
+
+ context 'when the MR comes from a fork' do
+ include ProjectForksHelper
+
+ let(:forked_project) { fork_project(project, nil, repository: true) }
+ let(:merge_request) { create(:merge_request, source_project: forked_project, target_project: project) }
+
+ it 'returns IDE path for MR in the forked repo with target project included as param' do
+ expect(helper.ide_merge_request_path(merge_request)).to eq("/-/ide/project/#{forked_project.full_path}/merge_requests/#{merge_request.iid}?target_project=#{CGI.escape(project.full_path)}")
+ end
+ end
+
+ context 'when the MR is merged' do
+ let(:current_user) { build(:user) }
+
+ let_it_be(:merge_request) { create(:merge_request, :merged, source_project: project, source_branch: 'testing-1', target_branch: 'feature-1') }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(current_user)
+ allow(helper).to receive(:can?).and_return(true)
+ end
+
+ it 'returns default IDE url with master branch' do
+ expect(helper.ide_merge_request_path(merge_request)).to eq("/-/ide/project/#{project.full_path}/edit/master")
+ end
+
+ it 'includes file path passed' do
+ expect(helper.ide_merge_request_path(merge_request, 'README.md')).to eq("/-/ide/project/#{project.full_path}/edit/master/-/README.md")
+ end
+
+ context 'when target branch exists' do
+ before do
+ allow(merge_request).to receive(:target_branch_exists?).and_return(true)
+ end
+
+ it 'returns IDE edit url with the target branch' do
+ expect(helper.ide_merge_request_path(merge_request)).to eq("/-/ide/project/#{project.full_path}/edit/feature-1")
+ end
+ end
+ end
+ end
+
describe '#ide_fork_and_edit_path' do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
diff --git a/spec/helpers/branches_helper_spec.rb b/spec/helpers/branches_helper_spec.rb
index 1f7bf25afcd..2ad15adff59 100644
--- a/spec/helpers/branches_helper_spec.rb
+++ b/spec/helpers/branches_helper_spec.rb
@@ -28,5 +28,23 @@ RSpec.describe BranchesHelper do
expect(subject).to eq(expected_array)
end
end
+
+ context 'when an access level tied to a deploy key is provided' do
+ let!(:protected_branch) { create(:protected_branch, :no_one_can_push) }
+ let!(:deploy_key) { create(:deploy_key, deploy_keys_projects: [create(:deploy_keys_project, :write_access, project: protected_branch.project)]) }
+
+ let(:push_level) { protected_branch.push_access_levels.first }
+ let(:deploy_key_push_level) { create(:protected_branch_push_access_level, protected_branch: protected_branch, deploy_key: deploy_key) }
+ let(:access_levels) { [push_level, deploy_key_push_level] }
+
+ it 'returns the correct array' do
+ expected_array = [
+ { id: push_level.id, type: :role, access_level: Gitlab::Access::NO_ACCESS },
+ { id: deploy_key_push_level.id, type: :deploy_key, deploy_key_id: deploy_key.id }
+ ]
+
+ expect(subject).to eq(expected_array)
+ end
+ end
end
end
diff --git a/spec/helpers/breadcrumbs_helper_spec.rb b/spec/helpers/breadcrumbs_helper_spec.rb
new file mode 100644
index 00000000000..8e2a684656b
--- /dev/null
+++ b/spec/helpers/breadcrumbs_helper_spec.rb
@@ -0,0 +1,145 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BreadcrumbsHelper do
+ describe '#push_to_schema_breadcrumb' do
+ let(:element_name) { 'BreadCrumbElement' }
+ let(:link) { 'http://test.host/foo' }
+ let(:breadcrumb_list) { helper.instance_variable_get(:@schema_breadcrumb_list) }
+
+ subject { helper.push_to_schema_breadcrumb(element_name, link) }
+
+ it 'enqueue element name, link and position' do
+ subject
+
+ aggregate_failures do
+ expect(breadcrumb_list[0]['name']).to eq element_name
+ expect(breadcrumb_list[0]['item']).to eq link
+ expect(breadcrumb_list[0]['position']).to eq(1)
+ end
+ end
+
+ context 'when link is relative' do
+ let(:link) { '/foo' }
+
+ it 'converts the url into absolute' do
+ subject
+
+ expect(breadcrumb_list[0]['item']).to eq "http://test.host#{link}"
+ end
+ end
+
+ describe 'when link is invalid' do
+ let(:link) { 'invalid://foo[]' }
+
+ it 'returns the current url' do
+ subject
+
+ expect(breadcrumb_list[0]['item']).to eq 'http://test.host'
+ end
+ end
+
+ describe 'when link is nil' do
+ let(:link) { nil }
+
+ it 'returns the current url' do
+ subject
+
+ expect(breadcrumb_list[0]['item']).to eq 'http://test.host'
+ end
+ end
+ end
+
+ describe '#schema_breadcrumb_json' do
+ let(:elements) do
+ [
+ %w(element1 http://test.host/link1),
+ %w(element2 http://test.host/link2)
+ ]
+ end
+
+ subject { helper.schema_breadcrumb_json }
+
+ it 'returns the breadcrumb schema in json format' do
+ enqueue_breadcrumb_elements
+
+ expected_result = {
+ '@context' => 'https://schema.org',
+ '@type' => 'BreadcrumbList',
+ 'itemListElement' => [
+ {
+ '@type' => 'ListItem',
+ 'position' => 1,
+ 'name' => elements[0][0],
+ 'item' => elements[0][1]
+ },
+ {
+ '@type' => 'ListItem',
+ 'position' => 2,
+ 'name' => elements[1][0],
+ 'item' => elements[1][1]
+ }
+ ]
+ }.to_json
+
+ expect(subject).to eq expected_result
+ end
+
+ context 'when extra breadcrumb element is added' do
+ let(:extra_elements) do
+ [
+ %w(extra_element1 http://test.host/extra_link1),
+ %w(extra_element2 http://test.host/extra_link2)
+ ]
+ end
+
+ it 'include the extra elements before the last element' do
+ enqueue_breadcrumb_elements
+
+ extra_elements.each do |el|
+ add_to_breadcrumbs(el[0], el[1])
+ end
+
+ expected_result = {
+ '@context' => 'https://schema.org',
+ '@type' => 'BreadcrumbList',
+ 'itemListElement' => [
+ {
+ '@type' => 'ListItem',
+ 'position' => 1,
+ 'name' => elements[0][0],
+ 'item' => elements[0][1]
+ },
+ {
+ '@type' => 'ListItem',
+ 'position' => 2,
+ 'name' => extra_elements[0][0],
+ 'item' => extra_elements[0][1]
+ },
+ {
+ '@type' => 'ListItem',
+ 'position' => 3,
+ 'name' => extra_elements[1][0],
+ 'item' => extra_elements[1][1]
+ },
+ {
+ '@type' => 'ListItem',
+ 'position' => 4,
+ 'name' => elements[1][0],
+ 'item' => elements[1][1]
+ }
+ ]
+ }.to_json
+
+ expect(subject).to eq expected_result
+ end
+ end
+
+ def enqueue_breadcrumb_elements
+ elements.each do |el|
+ helper.push_to_schema_breadcrumb(el[0], el[1])
+ end
+ end
+ end
+end
diff --git a/spec/helpers/ci/pipeline_editor_helper_spec.rb b/spec/helpers/ci/pipeline_editor_helper_spec.rb
new file mode 100644
index 00000000000..8f38d3b1439
--- /dev/null
+++ b/spec/helpers/ci/pipeline_editor_helper_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PipelineEditorHelper do
+ let_it_be(:project) { create(:project) }
+
+ describe 'can_view_pipeline_editor?' do
+ subject { helper.can_view_pipeline_editor?(project) }
+
+ it 'user can view editor if they can collaborate' do
+ allow(helper).to receive(:can_collaborate_with_project?).and_return(true)
+
+ expect(subject).to be true
+ end
+
+ it 'user can not view editor if they cannot collaborate' do
+ allow(helper).to receive(:can_collaborate_with_project?).and_return(false)
+
+ expect(subject).to be false
+ end
+
+ it 'user can not view editor if feature is disabled' do
+ allow(helper).to receive(:can_collaborate_with_project?).and_return(true)
+ stub_feature_flags(ci_pipeline_editor_page: false)
+
+ expect(subject).to be false
+ end
+ end
+end
diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb
index ef1f0940074..c085c3bdbd9 100644
--- a/spec/helpers/diff_helper_spec.rb
+++ b/spec/helpers/diff_helper_spec.rb
@@ -130,6 +130,38 @@ RSpec.describe DiffHelper do
end
end
+ describe "#diff_link_number" do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:line) do
+ double(:line, type: line_type)
+ end
+
+ # This helper is used to generate the line numbers on the
+ # diff lines. It essentially just returns a blank string
+ # on the old/new lines. The following table tests all the
+ # possible permutations for clarity.
+
+ where(:line_type, :match, :line_number, :expected_return_value) do
+ "new" | "new" | 1 | " "
+ "new" | "old" | 2 | 2
+ "old" | "new" | 3 | 3
+ "old" | "old" | 4 | " "
+ "new-nonewline" | "new" | 5 | 5
+ "new-nonewline" | "old" | 6 | 6
+ "old-nonewline" | "new" | 7 | 7
+ "old-nonewline" | "old" | 8 | 8
+ "match" | "new" | 9 | 9
+ "match" | "old" | 10 | 10
+ end
+
+ with_them do
+ it "returns the expected value" do
+ expect(helper.diff_link_number(line.type, match, line_number)).to eq(expected_return_value)
+ end
+ end
+ end
+
describe "#mark_inline_diffs" do
let(:old_line) { %{abc 'def'} }
let(:new_line) { %{abc "def"} }
@@ -326,4 +358,30 @@ RSpec.describe DiffHelper do
expect(diff_file_path_text(diff_file, max: 10)).to eq("...open.rb")
end
end
+
+ describe 'unified_diff_lines_view_type' do
+ before do
+ controller.params[:view] = 'parallel'
+ end
+
+ describe 'unified diffs enabled' do
+ before do
+ stub_feature_flags(unified_diff_lines: true)
+ end
+
+ it 'returns inline view' do
+ expect(helper.unified_diff_lines_view_type(project)).to eq 'inline'
+ end
+ end
+
+ describe 'unified diffs disabled' do
+ before do
+ stub_feature_flags(unified_diff_lines: false)
+ end
+
+ it 'returns parallel view' do
+ expect(helper.unified_diff_lines_view_type(project)).to eq :parallel
+ end
+ end
+ end
end
diff --git a/spec/helpers/dropdowns_helper_spec.rb b/spec/helpers/dropdowns_helper_spec.rb
index fd1125d0024..c30cb159803 100644
--- a/spec/helpers/dropdowns_helper_spec.rb
+++ b/spec/helpers/dropdowns_helper_spec.rb
@@ -246,8 +246,8 @@ RSpec.describe DropdownsHelper do
expect(content).to include('dropdown-loading')
end
- it 'returns an icon in the content' do
- expect(content.scan('icon').count).to eq(1)
+ it 'returns a gl-spinner in the content' do
+ expect(content).to include('gl-spinner')
end
end
end
diff --git a/spec/helpers/gitlab_routing_helper_spec.rb b/spec/helpers/gitlab_routing_helper_spec.rb
index 0088f739879..f23ffcee35d 100644
--- a/spec/helpers/gitlab_routing_helper_spec.rb
+++ b/spec/helpers/gitlab_routing_helper_spec.rb
@@ -322,4 +322,14 @@ RSpec.describe GitlabRoutingHelper do
end
end
end
+
+ context 'releases' do
+ let(:release) { create(:release) }
+
+ describe '#release_url' do
+ it 'returns the url for the release page' do
+ expect(release_url(release)).to eq("http://test.host/#{release.project.full_path}/-/releases/#{release.tag}")
+ end
+ end
+ end
end
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index 08b25d64b43..8eb1b7b3b3d 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -87,15 +87,26 @@ RSpec.describe GroupsHelper do
end
describe 'group_title' do
- let(:group) { create(:group) }
- let(:nested_group) { create(:group, parent: group) }
- let(:deep_nested_group) { create(:group, parent: nested_group) }
- let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:nested_group) { create(:group, parent: group) }
+ let_it_be(:deep_nested_group) { create(:group, parent: nested_group) }
+ let_it_be(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+
+ subject { helper.group_title(very_deep_nested_group) }
it 'outputs the groups in the correct order' do
- expect(helper.group_title(very_deep_nested_group))
+ expect(subject)
.to match(%r{<li style="text-indent: 16px;"><a.*>#{deep_nested_group.name}.*</li>.*<a.*>#{very_deep_nested_group.name}</a>}m)
end
+
+ it 'enqueues the elements in the breadcrumb schema list' do
+ expect(helper).to receive(:push_to_schema_breadcrumb).with(group.name, group_path(group))
+ expect(helper).to receive(:push_to_schema_breadcrumb).with(nested_group.name, group_path(nested_group))
+ expect(helper).to receive(:push_to_schema_breadcrumb).with(deep_nested_group.name, group_path(deep_nested_group))
+ expect(helper).to receive(:push_to_schema_breadcrumb).with(very_deep_nested_group.name, group_path(very_deep_nested_group))
+
+ subject
+ end
end
# rubocop:disable Layout/SpaceBeforeComma
@@ -370,6 +381,26 @@ RSpec.describe GroupsHelper do
end
end
+ describe '#show_thanks_for_purchase_banner?' do
+ subject { helper.show_thanks_for_purchase_banner? }
+
+ it 'returns true with purchased_quantity present in params' do
+ allow(controller).to receive(:params) { { purchased_quantity: '1' } }
+
+ is_expected.to be_truthy
+ end
+
+ it 'returns false with purchased_quantity not present in params' do
+ is_expected.to be_falsey
+ end
+
+ it 'returns false with purchased_quantity is empty in params' do
+ allow(controller).to receive(:params) { { purchased_quantity: '' } }
+
+ 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) }
diff --git a/spec/helpers/icons_helper_spec.rb b/spec/helpers/icons_helper_spec.rb
index 94012de3877..c05b2b206cc 100644
--- a/spec/helpers/icons_helper_spec.rb
+++ b/spec/helpers/icons_helper_spec.rb
@@ -97,19 +97,19 @@ RSpec.describe IconsHelper do
it 'returns right icon name for standard auth' do
icon_name = 'standard'
expect(audit_icon(icon_name).to_s)
- .to eq '<i class="fa fa-key"></i>'
+ .to eq sprite_icon('key')
end
it 'returns right icon name for two-factor auth' do
icon_name = 'two-factor'
expect(audit_icon(icon_name).to_s)
- .to eq '<i class="fa fa-key"></i>'
+ .to eq sprite_icon('key')
end
it 'returns right icon name for google_oauth2 auth' do
icon_name = 'google_oauth2'
expect(audit_icon(icon_name).to_s)
- .to eq '<i class="fa fa-google"></i>'
+ .to eq sprite_icon('google')
end
end
diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb
index b4e05d67553..d75b3c9f2e3 100644
--- a/spec/helpers/invite_members_helper_spec.rb
+++ b/spec/helpers/invite_members_helper_spec.rb
@@ -7,70 +7,110 @@ RSpec.describe InviteMembersHelper do
let_it_be(:developer) { create(:user, developer_projects: [project]) }
let(:owner) { project.owner }
- before do
- assign(:project, project)
- end
+ context 'with project' do
+ before do
+ assign(:project, project)
+ end
- describe "#directly_invite_members?" do
- context 'when the user is an owner' do
- before do
- allow(helper).to receive(:current_user) { owner }
- end
+ describe "#directly_invite_members?" do
+ context 'when the user is an owner' do
+ before do
+ allow(helper).to receive(:current_user) { owner }
+ end
+
+ it 'returns false' do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_version_a) { false }
- it 'returns false' do
- allow(helper).to receive(:experiment_enabled?).with(:invite_members_version_a) { false }
+ expect(helper.directly_invite_members?).to eq false
+ end
- expect(helper.directly_invite_members?).to eq false
+ it 'returns true' do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_version_a) { true }
+
+ expect(helper.directly_invite_members?).to eq true
+ end
end
- it 'returns true' do
- allow(helper).to receive(:experiment_enabled?).with(:invite_members_version_a) { true }
+ context 'when the user is a developer' do
+ before do
+ allow(helper).to receive(:current_user) { developer }
+ end
+
+ it 'returns false' do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_version_a) { true }
- expect(helper.directly_invite_members?).to eq true
+ expect(helper.directly_invite_members?).to eq false
+ end
end
end
- context 'when the user is a developer' do
- before do
- allow(helper).to receive(:current_user) { developer }
+ describe "#indirectly_invite_members?" do
+ context 'when a user is a developer' do
+ before do
+ allow(helper).to receive(:current_user) { developer }
+ end
+
+ it 'returns false' do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_version_b) { false }
+
+ expect(helper.indirectly_invite_members?).to eq false
+ end
+
+ it 'returns true' do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_version_b) { true }
+
+ expect(helper.indirectly_invite_members?).to eq true
+ end
end
- it 'returns false' do
- allow(helper).to receive(:experiment_enabled?).with(:invite_members_version_a) { true }
+ context 'when a user is an owner' do
+ before do
+ allow(helper).to receive(:current_user) { owner }
+ end
- expect(helper.directly_invite_members?).to eq false
+ it 'returns false' do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_version_b) { true }
+
+ expect(helper.indirectly_invite_members?).to eq false
+ end
end
end
end
- describe "#indirectly_invite_members?" do
- context 'when a user is a developer' do
- before do
- allow(helper).to receive(:current_user) { developer }
- end
+ context 'with group' do
+ let_it_be(:group) { create(:group) }
- it 'returns false' do
- allow(helper).to receive(:experiment_enabled?).with(:invite_members_version_b) { false }
+ describe "#invite_group_members?" do
+ context 'when the user is an owner' do
+ before do
+ group.add_owner(owner)
+ allow(helper).to receive(:current_user) { owner }
+ end
- expect(helper.indirectly_invite_members?).to eq false
- end
+ it 'returns false' do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_empty_group_version_a) { false }
- it 'returns true' do
- allow(helper).to receive(:experiment_enabled?).with(:invite_members_version_b) { true }
+ expect(helper.invite_group_members?(group)).to eq false
+ end
- expect(helper.indirectly_invite_members?).to eq true
- end
- end
+ it 'returns true' do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_empty_group_version_a) { true }
- context 'when a user is an owner' do
- before do
- allow(helper).to receive(:current_user) { owner }
+ expect(helper.invite_group_members?(group)).to eq true
+ end
end
- it 'returns false' do
- allow(helper).to receive(:experiment_enabled?).with(:invite_members_version_b) { true }
+ context 'when the user is a developer' do
+ before do
+ group.add_developer(developer)
+ allow(helper).to receive(:current_user) { developer }
+ end
+
+ it 'returns false' do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_empty_group_version_a) { true }
- expect(helper.indirectly_invite_members?).to eq false
+ expect(helper.invite_group_members?(group)).to eq false
+ end
end
end
end
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index e8e5adaa274..0e3752f220e 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -345,42 +345,29 @@ RSpec.describe IssuablesHelper do
end
end
- describe '#sidebar_milestone_tooltip_label' do
- it 'escapes HTML in the milestone title' do
- milestone = build(:milestone, title: '&lt;img onerror=alert(1)&gt;')
+ describe '#issuable_display_type' do
+ using RSpec::Parameterized::TableSyntax
- expect(helper.sidebar_milestone_tooltip_label(milestone)).to eq('&lt;img onerror=alert(1)&gt;<br/>Milestone')
+ where(:issuable_type, :issuable_display_type) do
+ :issue | 'issue'
+ :incident | 'incident'
+ :merge_request | 'merge request'
end
- end
-
- describe '#serialize_issuable' do
- context 'when it is a merge request' do
- let(:merge_request) { build(:merge_request) }
- let(:user) { build(:user) }
-
- before do
- allow(helper).to receive(:current_user) { user }
- end
-
- it 'has suggest_pipeline experiment enabled' do
- allow(helper).to receive(:experiment_enabled?).with(:suggest_pipeline) { true }
- expect_next_instance_of(MergeRequestSerializer) do |serializer|
- expect(serializer).to receive(:represent).with(merge_request, { serializer: 'widget', experiment_enabled: :suggest_pipeline })
- end
+ with_them do
+ let(:issuable) { build_stubbed(issuable_type) }
- helper.serialize_issuable(merge_request, serializer: 'widget')
- end
+ subject { helper.issuable_display_type(issuable) }
- it 'suggest_pipeline experiment disabled' do
- allow(helper).to receive(:experiment_enabled?).with(:suggest_pipeline) { false }
+ it { is_expected.to eq(issuable_display_type) }
+ end
+ end
- expect_next_instance_of(MergeRequestSerializer) do |serializer|
- expect(serializer).to receive(:represent).with(merge_request, { serializer: 'widget' })
- end
+ describe '#sidebar_milestone_tooltip_label' do
+ it 'escapes HTML in the milestone title' do
+ milestone = build(:milestone, title: '&lt;img onerror=alert(1)&gt;')
- helper.serialize_issuable(merge_request, serializer: 'widget')
- end
+ expect(helper.sidebar_milestone_tooltip_label(milestone)).to eq('&lt;img onerror=alert(1)&gt;<br/>Milestone')
end
end
end
diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb
index 302ab0cc137..6c5855eeb91 100644
--- a/spec/helpers/markup_helper_spec.rb
+++ b/spec/helpers/markup_helper_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe MarkupHelper do
project.add_maintainer(user)
user
end
+
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let_it_be(:snippet) { create(:project_snippet, project: project) }
diff --git a/spec/helpers/operations_helper_spec.rb b/spec/helpers/operations_helper_spec.rb
index 8d2fc643caa..09f9bba8f9e 100644
--- a/spec/helpers/operations_helper_spec.rb
+++ b/spec/helpers/operations_helper_spec.rb
@@ -43,7 +43,9 @@ RSpec.describe OperationsHelper do
'prometheus_api_url' => nil,
'prometheus_activated' => 'false',
'prometheus_url' => notify_project_prometheus_alerts_url(project, format: :json),
- 'disabled' => 'false'
+ 'disabled' => 'false',
+ 'project_path' => project.full_path,
+ 'multi_integrations' => 'false'
)
end
end
diff --git a/spec/helpers/page_layout_helper_spec.rb b/spec/helpers/page_layout_helper_spec.rb
index e8a5c4613fe..99cdee6dbb2 100644
--- a/spec/helpers/page_layout_helper_spec.rb
+++ b/spec/helpers/page_layout_helper_spec.rb
@@ -56,19 +56,24 @@ RSpec.describe PageLayoutHelper do
end
%w(project user group).each do |type|
+ let(:object) { build(type, trait) }
+ let(:trait) { :with_avatar }
+
context "with @#{type} assigned" do
- it "uses #{type.titlecase} avatar if available" do
- object = double(avatar_url: 'http://example.com/uploads/-/system/avatar.png')
+ before do
assign(type, object)
+ end
- expect(helper.page_image).to eq object.avatar_url
+ it "uses #{type.titlecase} avatar full url" do
+ expect(helper.page_image).to eq object.avatar_url(only_path: false)
end
- it 'falls back to the default when avatar_url is nil' do
- object = double(avatar_url: nil)
- assign(type, object)
+ context 'when avatar_url is nil' do
+ let(:trait) { nil }
- expect(helper.page_image).to match_asset_path 'assets/gitlab_logo.png'
+ it 'falls back to the default when avatar_url is nil' do
+ expect(helper.page_image).to match_asset_path 'assets/gitlab_logo.png'
+ end
end
end
@@ -132,4 +137,126 @@ RSpec.describe PageLayoutHelper do
end
end
end
+
+ describe '#page_canonical_link' do
+ let(:user) { build(:user) }
+
+ subject { helper.page_canonical_link(link) }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ context 'when link is passed' do
+ let(:link) { 'https://gitlab.com' }
+
+ it 'stores and returns the link value' do
+ expect(subject).to eq link
+ expect(helper.page_canonical_link(nil)).to eq link
+ end
+ end
+
+ context 'when no link is provided' do
+ let(:link) { nil }
+ let(:request) { ActionDispatch::Request.new(env) }
+ let(:env) do
+ {
+ 'ORIGINAL_FULLPATH' => '/foo/',
+ 'PATH_INFO' => '/foo',
+ 'HTTP_HOST' => 'test.host',
+ 'REQUEST_METHOD' => method,
+ 'rack.url_scheme' => 'http'
+ }
+ end
+
+ before do
+ allow(helper).to receive(:request).and_return(request)
+ end
+
+ shared_examples 'generates the canonical url using the params in the context' do
+ specify { expect(subject).to eq 'http://test.host/foo' }
+ end
+
+ shared_examples 'does not return a canonical url' do
+ specify { expect(subject).to be_nil }
+ end
+
+ it_behaves_like 'generates the canonical url using the params in the context' do
+ let(:method) { 'GET' }
+ end
+
+ it_behaves_like 'generates the canonical url using the params in the context' do
+ let(:method) { 'HEAD' }
+ end
+
+ it_behaves_like 'does not return a canonical url' do
+ let(:method) { 'POST' }
+ end
+
+ it_behaves_like 'does not return a canonical url' do
+ let(:method) { 'PUT' }
+ end
+ end
+ end
+
+ describe '#page_itemtype' do
+ subject { helper.page_itemtype(itemtype) }
+
+ context 'when itemtype is passed' do
+ let(:itemtype) { 'http://schema.org/Person' }
+
+ it 'stores and returns the itemtype value' do
+ attrs = { itemscope: true, itemtype: itemtype }
+
+ expect(subject).to eq attrs
+ expect(helper.page_itemtype(nil)).to eq attrs
+ end
+ end
+
+ context 'when no itemtype is provided' do
+ let(:itemtype) { nil }
+
+ it 'returns an empty hash' do
+ expect(subject).to eq({})
+ end
+ end
+ end
+
+ describe '#user_status_properties' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:user) { build(:user) }
+
+ availability_types = Types::AvailabilityEnum.enum
+
+ where(:message, :emoji, :availability) do
+ "Some message" | UserStatus::DEFAULT_EMOJI | availability_types[:busy]
+ "Some message" | UserStatus::DEFAULT_EMOJI | availability_types[:not_set]
+ "Some message" | "basketball" | availability_types[:busy]
+ "Some message" | "basketball" | availability_types[:not_set]
+ "Some message" | "" | availability_types[:busy]
+ "Some message" | "" | availability_types[:not_set]
+ "" | UserStatus::DEFAULT_EMOJI | availability_types[:busy]
+ "" | UserStatus::DEFAULT_EMOJI | availability_types[:not_set]
+ "" | "basketball" | availability_types[:busy]
+ "" | "basketball" | availability_types[:not_set]
+ "" | "" | availability_types[:busy]
+ "" | "" | availability_types[:not_set]
+ end
+
+ with_them do
+ it "sets the default user status fields" do
+ user.status = UserStatus.new(message: message, emoji: emoji, availability: availability)
+ result = {
+ can_set_user_availability: true,
+ current_availability: availability,
+ current_emoji: emoji,
+ current_message: message,
+ default_emoji: UserStatus::DEFAULT_EMOJI
+ }
+
+ expect(helper.user_status_properties(user)).to eq(result)
+ end
+ end
+ end
end
diff --git a/spec/helpers/profiles_helper_spec.rb b/spec/helpers/profiles_helper_spec.rb
index 61b7ff94edb..9687d038162 100644
--- a/spec/helpers/profiles_helper_spec.rb
+++ b/spec/helpers/profiles_helper_spec.rb
@@ -80,6 +80,38 @@ RSpec.describe ProfilesHelper do
end
end
+ describe "#user_status_set_to_busy?" do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:availability, :result) do
+ "busy" | true
+ "not_set" | false
+ "" | false
+ nil | false
+ end
+
+ with_them do
+ it { expect(helper.user_status_set_to_busy?(OpenStruct.new(availability: availability))).to eq(result) }
+ end
+ end
+
+ describe "#show_status_emoji?" do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:message, :emoji, :result) do
+ "Some message" | UserStatus::DEFAULT_EMOJI | true
+ "Some message" | "" | true
+ "" | "basketball" | true
+ "" | "basketball" | true
+ "" | UserStatus::DEFAULT_EMOJI | false
+ "" | UserStatus::DEFAULT_EMOJI | false
+ end
+
+ with_them do
+ it { expect(helper.show_status_emoji?(OpenStruct.new(message: message, emoji: emoji))).to eq(result) }
+ end
+ end
+
def stub_cas_omniauth_provider
provider = OpenStruct.new(
'name' => 'cas3',
diff --git a/spec/helpers/projects/terraform_helper_spec.rb b/spec/helpers/projects/terraform_helper_spec.rb
new file mode 100644
index 00000000000..de363c42d21
--- /dev/null
+++ b/spec/helpers/projects/terraform_helper_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::TerraformHelper do
+ describe '#js_terraform_list_data' do
+ let_it_be(:project) { create(:project) }
+
+ subject { helper.js_terraform_list_data(project) }
+
+ it 'displays image path' do
+ image_path = ActionController::Base.helpers.image_path(
+ 'illustrations/empty-state/empty-serverless-lg.svg'
+ )
+
+ expect(subject[:empty_state_image]).to eq(image_path)
+ end
+
+ it 'displays project path' do
+ expect(subject[:project_path]).to eq(project.full_path)
+ end
+ end
+end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index f081cf225b1..9635a6f9c82 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -999,4 +999,15 @@ RSpec.describe ProjectsHelper do
end
end
end
+
+ describe '#project_title' do
+ subject { helper.project_title(project) }
+
+ it 'enqueues the elements in the breadcrumb schema list' do
+ expect(helper).to receive(:push_to_schema_breadcrumb).with(project.namespace.name, user_path(project.owner))
+ expect(helper).to receive(:push_to_schema_breadcrumb).with(project.name, project_path(project))
+
+ subject
+ end
+ end
end
diff --git a/spec/helpers/recaptcha_experiment_helper_spec.rb b/spec/helpers/recaptcha_experiment_helper_spec.rb
deleted file mode 100644
index e677164c950..00000000000
--- a/spec/helpers/recaptcha_experiment_helper_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe RecaptchaExperimentHelper, type: :helper do
- let(:session) { {} }
-
- before do
- allow(helper).to receive(:session) { session }
- end
-
- describe '.show_recaptcha_sign_up?' do
- context 'when reCAPTCHA is disabled' do
- it 'returns false' do
- stub_application_setting(recaptcha_enabled: false)
-
- expect(helper.show_recaptcha_sign_up?).to be(false)
- end
- end
-
- context 'when reCAPTCHA is enabled' do
- it 'returns true' do
- stub_application_setting(recaptcha_enabled: true)
-
- expect(helper.show_recaptcha_sign_up?).to be(true)
- end
- end
- end
-end
diff --git a/spec/helpers/recaptcha_helper_spec.rb b/spec/helpers/recaptcha_helper_spec.rb
new file mode 100644
index 00000000000..e7f9ba5b73a
--- /dev/null
+++ b/spec/helpers/recaptcha_helper_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe RecaptchaHelper, type: :helper do
+ let(:session) { {} }
+
+ before do
+ allow(helper).to receive(:session) { session }
+ end
+
+ describe '.show_recaptcha_sign_up?' do
+ context 'when reCAPTCHA is disabled' do
+ it 'returns false' do
+ stub_application_setting(recaptcha_enabled: false)
+
+ expect(helper.show_recaptcha_sign_up?).to be(false)
+ end
+ end
+
+ context 'when reCAPTCHA is enabled' do
+ it 'returns true' do
+ stub_application_setting(recaptcha_enabled: true)
+
+ expect(helper.show_recaptcha_sign_up?).to be(true)
+ end
+ end
+ end
+end
diff --git a/spec/helpers/releases_helper_spec.rb b/spec/helpers/releases_helper_spec.rb
index 704e8dc40cb..e6bf91ceef6 100644
--- a/spec/helpers/releases_helper_spec.rb
+++ b/spec/helpers/releases_helper_spec.rb
@@ -64,12 +64,13 @@ RSpec.describe ReleasesHelper do
describe '#data_for_edit_release_page' do
it 'has the needed data to display the "edit release" page' do
keys = %i(project_id
+ group_id
+ group_milestones_available
project_path
tag_name
markdown_preview_path
markdown_docs_path
releases_page_path
- update_release_api_docs_path
release_assets_docs_path
manage_milestones_path
new_milestone_path)
@@ -81,11 +82,12 @@ RSpec.describe ReleasesHelper do
describe '#data_for_new_release_page' do
it 'has the needed data to display the "new release" page' do
keys = %i(project_id
+ group_id
+ group_milestones_available
project_path
releases_page_path
markdown_preview_path
markdown_docs_path
- update_release_api_docs_path
release_assets_docs_path
manage_milestones_path
new_milestone_path
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 6fe071521cd..34af3ce7e5e 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -73,7 +73,7 @@ RSpec.describe SearchHelper do
expect(result.keys).to match_array(%i[category id label url avatar_url])
end
- it 'includes the users recently viewed issues' do
+ it 'includes the users recently viewed issues', :aggregate_failures 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)
@@ -104,7 +104,7 @@ RSpec.describe SearchHelper do
})
end
- it 'includes the users recently viewed merge requests' do
+ it 'includes the users recently viewed merge requests', :aggregate_failures 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)
@@ -143,12 +143,44 @@ RSpec.describe SearchHelper do
context "with a current project" do
before do
@project = create(:project, :repository)
+ allow(self).to receive(:can?).with(user, :read_feature_flag, @project).and_return(false)
end
- it "includes project-specific sections" do
+ it "includes project-specific sections", :aggregate_failures do
expect(search_autocomplete_opts("Files").size).to eq(1)
expect(search_autocomplete_opts("Commits").size).to eq(1)
end
+
+ context 'when user does not have access to project' do
+ it 'does not include issues by iid' do
+ issue = create(:issue, project: @project)
+ results = search_autocomplete_opts("\##{issue.iid}")
+
+ expect(results.count).to eq(0)
+ end
+ end
+
+ context 'when user has project access' do
+ before do
+ @project = create(:project, :repository, namespace: user.namespace)
+ allow(self).to receive(:can?).with(user, :read_feature_flag, @project).and_return(true)
+ end
+
+ it 'includes issues by iid', :aggregate_failures do
+ issue = create(:issue, project: @project, title: 'test title')
+ results = search_autocomplete_opts("\##{issue.iid}")
+
+ expect(results.count).to eq(1)
+
+ expect(results.first).to include({
+ category: 'In this project',
+ id: issue.id,
+ label: 'test title (#1)',
+ url: ::Gitlab::Routing.url_helpers.project_issue_path(issue.project, issue),
+ avatar_url: '' # project has no avatar
+ })
+ end
+ end
end
end
@@ -204,11 +236,34 @@ RSpec.describe SearchHelper do
end
describe 'search_entries_empty_message' do
- it 'returns the formatted entry message' do
- message = search_entries_empty_message('projects', '<h1>foo</h1>')
+ let!(:group) { build(:group) }
+ let!(:project) { build(:project, group: group) }
+
+ context 'global search' do
+ let(:message) { search_entries_empty_message('projects', '<h1>foo</h1>', nil, nil) }
+
+ it 'returns the formatted entry message' do
+ expect(message).to eq("We couldn&#39;t find any projects matching <code>&lt;h1&gt;foo&lt;/h1&gt;</code>")
+ expect(message).to be_html_safe
+ end
+ end
+
+ context 'group search' do
+ let(:message) { search_entries_empty_message('projects', '<h1>foo</h1>', group, nil) }
- expect(message).to eq("We couldn't find any projects matching <code>&lt;h1&gt;foo&lt;/h1&gt;</code>")
- expect(message).to be_html_safe
+ it 'returns the formatted entry message' do
+ expect(message).to start_with('We couldn&#39;t find any projects matching <code>&lt;h1&gt;foo&lt;/h1&gt;</code> in group <a')
+ expect(message).to be_html_safe
+ end
+ end
+
+ context 'project search' do
+ let(:message) { search_entries_empty_message('projects', '<h1>foo</h1>', group, project) }
+
+ it 'returns the formatted entry message' do
+ expect(message).to start_with('We couldn&#39;t find any projects matching <code>&lt;h1&gt;foo&lt;/h1&gt;</code> in project <a')
+ expect(message).to be_html_safe
+ end
end
end
@@ -343,6 +398,19 @@ RSpec.describe SearchHelper do
expect(link).to have_link('Projects', href: search_path(scope: 'projects', search: 'hello', project_id: 23))
end
+ it 'restricts the params' do
+ expect(self).to receive(:params).and_return(
+ ActionController::Parameters.new(
+ search: 'hello',
+ unknown: 42
+ )
+ )
+
+ link = search_filter_link('projects', 'Projects')
+
+ expect(link).to have_link('Projects', href: search_path(scope: 'projects', search: 'hello'))
+ end
+
it 'assigns given data attributes on the list container' do
link = search_filter_link('projects', 'Projects', data: { foo: 'bar' })
@@ -409,7 +477,7 @@ RSpec.describe SearchHelper do
end
end
- describe '#highlight_and_truncate_issue' do
+ describe '#highlight_and_truncate_issuable' do
let(:description) { 'hello world' }
let(:issue) { create(:issue, description: description) }
let(:user) { create(:user) }
@@ -418,7 +486,7 @@ RSpec.describe SearchHelper do
allow(self).to receive(:current_user).and_return(user)
end
- subject { highlight_and_truncate_issue(issue, 'test', {}) }
+ subject { highlight_and_truncate_issuable(issue, 'test', {}) }
context 'when description is not present' do
let(:description) { nil }
@@ -477,4 +545,38 @@ RSpec.describe SearchHelper do
end
end
end
+
+ describe '#issuable_state_to_badge_class' do
+ context 'with merge request' do
+ it 'returns correct badge based on status' do
+ expect(issuable_state_to_badge_class(build(:merge_request, :merged))).to eq(:primary)
+ expect(issuable_state_to_badge_class(build(:merge_request, :closed))).to eq(:danger)
+ expect(issuable_state_to_badge_class(build(:merge_request, :opened))).to eq(:success)
+ end
+ end
+
+ context 'with an issue' do
+ it 'returns correct badge based on status' do
+ expect(issuable_state_to_badge_class(build(:issue, :closed))).to eq(:info)
+ expect(issuable_state_to_badge_class(build(:issue, :opened))).to eq(:success)
+ end
+ end
+ end
+
+ describe '#issuable_state_text' do
+ context 'with merge request' do
+ it 'returns correct badge based on status' do
+ expect(issuable_state_text(build(:merge_request, :merged))).to eq(_('Merged'))
+ expect(issuable_state_text(build(:merge_request, :closed))).to eq(_('Closed'))
+ expect(issuable_state_text(build(:merge_request, :opened))).to eq(_('Open'))
+ end
+ end
+
+ context 'with an issue' do
+ it 'returns correct badge based on status' do
+ expect(issuable_state_text(build(:issue, :closed))).to eq(_('Closed'))
+ expect(issuable_state_text(build(:issue, :opened))).to eq(_('Open'))
+ end
+ end
+ end
end
diff --git a/spec/helpers/sorting_helper_spec.rb b/spec/helpers/sorting_helper_spec.rb
index 6c52016139b..1c300aea2df 100644
--- a/spec/helpers/sorting_helper_spec.rb
+++ b/spec/helpers/sorting_helper_spec.rb
@@ -50,6 +50,24 @@ RSpec.describe SortingHelper do
end
end
+ describe '#search_sort_direction_button' do
+ before do
+ set_sorting_url 'test_label'
+ end
+
+ it 'keeps label filter param' do
+ expect(search_sort_direction_button('created_asc')).to include('label_name=test_label')
+ end
+
+ it 'returns icon with sort-lowest when sort is asc' do
+ expect(search_sort_direction_button('created_asc')).to include('sort-lowest')
+ end
+
+ it 'returns icon with sort-highest when sort is desc' do
+ expect(search_sort_direction_button('created_desc')).to include('sort-highest')
+ end
+ end
+
def stub_controller_path(value)
allow(helper.controller).to receive(:controller_path).and_return(value)
end
diff --git a/spec/helpers/sourcegraph_helper_spec.rb b/spec/helpers/sourcegraph_helper_spec.rb
index 6a95c8e4a43..d03893ea9ae 100644
--- a/spec/helpers/sourcegraph_helper_spec.rb
+++ b/spec/helpers/sourcegraph_helper_spec.rb
@@ -5,60 +5,43 @@ require 'spec_helper'
RSpec.describe SourcegraphHelper do
describe '#sourcegraph_url_message' do
let(:sourcegraph_url) { 'http://sourcegraph.example.com' }
+ let(:feature_conditional) { false }
+ let(:public_only) { false }
+ let(:is_com) { true }
before do
allow(Gitlab::CurrentSettings).to receive(:sourcegraph_url).and_return(sourcegraph_url)
allow(Gitlab::CurrentSettings).to receive(:sourcegraph_url_is_com?).and_return(is_com)
+ allow(Gitlab::CurrentSettings).to receive(:sourcegraph_public_only).and_return(public_only)
+ allow(Gitlab::Sourcegraph).to receive(:feature_conditional?).and_return(feature_conditional)
end
subject { helper.sourcegraph_url_message }
context 'with .com sourcegraph url' do
- let(:is_com) { true }
-
- it { is_expected.to have_text('Uses Sourcegraph.com') }
- it { is_expected.to have_link('Sourcegraph.com', href: sourcegraph_url) }
+ it { is_expected.to have_text('Uses %{linkStart}Sourcegraph.com%{linkEnd}. This feature is experimental.') }
end
context 'with custom sourcegraph url' do
let(:is_com) { false }
- it { is_expected.to have_text('Uses a custom Sourcegraph instance') }
- it { is_expected.to have_link('Sourcegraph instance', href: sourcegraph_url) }
-
- context 'with unsafe url' do
- let(:sourcegraph_url) { '\" onload=\"alert(1);\"' }
-
- it { is_expected.to have_link('Sourcegraph instance', href: sourcegraph_url) }
- end
+ it { is_expected.to have_text('Uses a custom %{linkStart}Sourcegraph instance%{linkEnd}. This feature is experimental.') }
end
- end
-
- describe '#sourcegraph_experimental_message' do
- let(:feature_conditional) { false }
- let(:public_only) { false }
-
- before do
- allow(Gitlab::CurrentSettings).to receive(:sourcegraph_public_only).and_return(public_only)
- allow(Gitlab::Sourcegraph).to receive(:feature_conditional?).and_return(feature_conditional)
- end
-
- subject { helper.sourcegraph_experimental_message }
context 'when not limited by feature or public only' do
- it { is_expected.to eq "This feature is experimental." }
+ it { is_expected.to eq 'Uses %{linkStart}Sourcegraph.com%{linkEnd}. This feature is experimental.' }
end
context 'when limited by feature' do
let(:feature_conditional) { true }
- it { is_expected.to eq "This feature is experimental and currently limited to certain projects." }
+ it { is_expected.to eq 'Uses %{linkStart}Sourcegraph.com%{linkEnd}. This feature is experimental and currently limited to certain projects.' }
end
context 'when limited by public only' do
let(:public_only) { true }
- it { is_expected.to eq "This feature is experimental and limited to public projects." }
+ it { is_expected.to eq 'Uses %{linkStart}Sourcegraph.com%{linkEnd}. This feature is experimental and limited to public projects.' }
end
end
end
diff --git a/spec/helpers/stat_anchors_helper_spec.rb b/spec/helpers/stat_anchors_helper_spec.rb
new file mode 100644
index 00000000000..c6556647bc8
--- /dev/null
+++ b/spec/helpers/stat_anchors_helper_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe StatAnchorsHelper do
+ let(:anchor_klass) { ProjectPresenter::AnchorData }
+
+ describe '#stat_anchor_attrs' do
+ subject { helper.stat_anchor_attrs(anchor) }
+
+ context 'when anchor is a link' do
+ let(:anchor) { anchor_klass.new(true) }
+
+ it 'returns the proper attributes' do
+ expect(subject[:class]).to include('stat-link')
+ end
+ end
+
+ context 'when anchor is not a link' do
+ context 'when class_modifier is set' do
+ let(:anchor) { anchor_klass.new(false, nil, nil, 'default') }
+
+ it 'returns the proper attributes' do
+ expect(subject[:class]).to include('btn btn-default')
+ end
+ end
+
+ context 'when class_modifier is not set' do
+ let(:anchor) { anchor_klass.new(false) }
+
+ it 'returns the proper attributes' do
+ expect(subject[:class]).to include('btn btn-missing')
+ end
+ end
+ end
+
+ context 'when itemprop is not set' do
+ let(:anchor) { anchor_klass.new(false, nil, nil, nil, nil, false) }
+
+ it 'returns the itemprop attributes' do
+ expect(subject[:itemprop]).to be_nil
+ end
+ end
+
+ context 'when itemprop is set set' do
+ let(:anchor) { anchor_klass.new(false, nil, nil, nil, nil, true) }
+
+ it 'returns the itemprop attributes' do
+ expect(subject[:itemprop]).to eq true
+ end
+ end
+ end
+end
diff --git a/spec/helpers/time_helper_spec.rb b/spec/helpers/time_helper_spec.rb
index 6663a5c81c8..3e406f5e74e 100644
--- a/spec/helpers/time_helper_spec.rb
+++ b/spec/helpers/time_helper_spec.rb
@@ -37,4 +37,14 @@ RSpec.describe TimeHelper do
it { expect(duration_in_numbers(duration)).to eq formatted_string }
end
end
+
+ describe "#time_in_milliseconds" do
+ it "returns the time in milliseconds" do
+ freeze_time do
+ time = (Time.now.to_f * 1000).to_i
+
+ expect(time_in_milliseconds).to eq time
+ end
+ end
+ end
end
diff --git a/spec/helpers/todos_helper_spec.rb b/spec/helpers/todos_helper_spec.rb
index 6b658a475b1..9481d756c16 100644
--- a/spec/helpers/todos_helper_spec.rb
+++ b/spec/helpers/todos_helper_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe TodosHelper do
project: issue.project,
note: 'I am note, hear me roar')
end
+
let_it_be(:design_todo) do
create(:todo, :mentioned,
user: user,
@@ -20,6 +21,7 @@ RSpec.describe TodosHelper do
author: author,
note: note)
end
+
let_it_be(:alert_todo) do
alert = create(:alert_management_alert, iid: 1001)
create(:todo, target: alert)
diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb
index b5d356b985c..620bf248d7b 100644
--- a/spec/helpers/tree_helper_spec.rb
+++ b/spec/helpers/tree_helper_spec.rb
@@ -7,6 +7,8 @@ RSpec.describe TreeHelper do
let(:repository) { project.repository }
let(:sha) { 'c1c67abbaf91f624347bb3ae96eabe3a1b742478' }
+ let_it_be(:user) { create(:user) }
+
def create_file(filename)
project.repository.create_file(
project.creator,
@@ -219,7 +221,6 @@ RSpec.describe TreeHelper do
context 'user does not have write access but a personal fork exists' do
include ProjectForksHelper
- let_it_be(:user) { create(:user) }
let(:forked_project) { create(:project, :repository, namespace: user.namespace) }
before do
@@ -277,8 +278,6 @@ RSpec.describe TreeHelper do
end
context 'user has write access' do
- let_it_be(:user) { create(:user) }
-
before do
project.add_developer(user)
@@ -314,8 +313,6 @@ RSpec.describe TreeHelper do
end
context 'gitpod feature is enabled' do
- let_it_be(:user) { create(:user) }
-
before do
stub_feature_flags(gitpod: true)
allow(Gitlab::CurrentSettings)
@@ -358,4 +355,28 @@ RSpec.describe TreeHelper do
end
end
end
+
+ describe '.patch_branch_name' do
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ subject { helper.patch_branch_name('master') }
+
+ it 'returns a patch branch name' do
+ freeze_time do
+ epoch = Time.now.strftime('%s%L').last(5)
+
+ expect(subject).to eq "#{user.username}-master-patch-#{epoch}"
+ end
+ end
+
+ context 'without a current_user' do
+ let(:user) { nil }
+
+ it 'returns nil' do
+ expect(subject).to be nil
+ end
+ end
+ end
end
diff --git a/spec/helpers/user_callouts_helper_spec.rb b/spec/helpers/user_callouts_helper_spec.rb
index bcb0b5c51e7..4ab3be877b4 100644
--- a/spec/helpers/user_callouts_helper_spec.rb
+++ b/spec/helpers/user_callouts_helper_spec.rb
@@ -161,4 +161,50 @@ RSpec.describe UserCalloutsHelper do
it { is_expected.to be_falsy }
end
end
+
+ describe '.show_registration_enabled_user_callout?' do
+ let_it_be(:admin) { create(:user, :admin) }
+
+ subject { helper.show_registration_enabled_user_callout? }
+
+ context 'when `current_user` is not an admin' do
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ stub_application_setting(signup_enabled: true)
+ allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { false }
+ end
+
+ it { is_expected.to be false }
+ end
+
+ context 'when signup is disabled' do
+ before do
+ allow(helper).to receive(:current_user).and_return(admin)
+ stub_application_setting(signup_enabled: false)
+ allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { false }
+ end
+
+ it { is_expected.to be false }
+ end
+
+ context 'when user has dismissed callout' do
+ before do
+ allow(helper).to receive(:current_user).and_return(admin)
+ stub_application_setting(signup_enabled: true)
+ allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { true }
+ end
+
+ it { is_expected.to be false }
+ end
+
+ context 'when `current_user` is an admin, signup is enabled, and user has not dismissed callout' do
+ before do
+ allow(helper).to receive(:current_user).and_return(admin)
+ stub_application_setting(signup_enabled: true)
+ allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { false }
+ end
+
+ it { is_expected.to be true }
+ end
+ end
end
diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb
index c9dc3fcff3f..9ebbf975903 100644
--- a/spec/helpers/users_helper_spec.rb
+++ b/spec/helpers/users_helper_spec.rb
@@ -204,40 +204,72 @@ RSpec.describe UsersHelper do
end
describe '#work_information' do
- subject { helper.work_information(user) }
+ let(:with_schema_markup) { false }
- context 'when both job_title and organization are present' do
- let(:user) { build(:user, organization: 'GitLab', job_title: 'Frontend Engineer') }
+ subject { helper.work_information(user, with_schema_markup: with_schema_markup) }
- it 'returns job title concatenated with organization' do
- is_expected.to eq('Frontend Engineer at GitLab')
- end
+ context 'when neither organization nor job_title are present' do
+ it { is_expected.to be_nil }
end
- context 'when only organization is present' do
- let(:user) { build(:user, organization: 'GitLab') }
+ context 'when user parameter is nil' do
+ let(:user) { nil }
- it "returns organization" do
- is_expected.to eq('GitLab')
- end
+ it { is_expected.to be_nil }
end
- context 'when only job_title is present' do
- let(:user) { build(:user, job_title: 'Frontend Engineer') }
+ context 'without schema markup' do
+ context 'when both job_title and organization are present' do
+ let(:user) { build(:user, organization: 'GitLab', job_title: 'Frontend Engineer') }
- it 'returns job title' do
- is_expected.to eq('Frontend Engineer')
+ it 'returns job title concatenated with organization' do
+ is_expected.to eq('Frontend Engineer at GitLab')
+ end
end
- end
- context 'when neither organization nor job_title are present' do
- it { is_expected.to be_nil }
+ context 'when only organization is present' do
+ let(:user) { build(:user, organization: 'GitLab') }
+
+ it "returns organization" do
+ is_expected.to eq('GitLab')
+ end
+ end
+
+ context 'when only job_title is present' do
+ let(:user) { build(:user, job_title: 'Frontend Engineer') }
+
+ it 'returns job title' do
+ is_expected.to eq('Frontend Engineer')
+ end
+ end
end
- context 'when user parameter is nil' do
- let(:user) { nil }
+ context 'with schema markup' do
+ let(:with_schema_markup) { true }
- it { is_expected.to be_nil }
+ context 'when both job_title and organization are present' do
+ let(:user) { build(:user, organization: 'GitLab', job_title: 'Frontend Engineer') }
+
+ it 'returns job title concatenated with organization' do
+ is_expected.to eq('<span itemprop="jobTitle">Frontend Engineer</span> at <span itemprop="worksFor">GitLab</span>')
+ end
+ end
+
+ context 'when only organization is present' do
+ let(:user) { build(:user, organization: 'GitLab') }
+
+ it "returns organization" do
+ is_expected.to eq('<span itemprop="worksFor">GitLab</span>')
+ end
+ end
+
+ context 'when only job_title is present' do
+ let(:user) { build(:user, job_title: 'Frontend Engineer') }
+
+ it 'returns job title' do
+ is_expected.to eq('<span itemprop="jobTitle">Frontend Engineer</span>')
+ end
+ end
end
end
end
diff --git a/spec/helpers/whats_new_helper_spec.rb b/spec/helpers/whats_new_helper_spec.rb
index 80d4ca8ddea..1c8684de75c 100644
--- a/spec/helpers/whats_new_helper_spec.rb
+++ b/spec/helpers/whats_new_helper_spec.rb
@@ -3,21 +3,23 @@
require 'spec_helper'
RSpec.describe WhatsNewHelper do
+ let(:fixture_dir_glob) { Dir.glob(File.join('spec', 'fixtures', 'whats_new', '*.yml')) }
+
describe '#whats_new_storage_key' do
subject { helper.whats_new_storage_key }
- before do
- allow(helper).to receive(:whats_new_most_recent_version).and_return(version)
- end
-
context 'when version exist' do
- let(:version) { '84.0' }
+ before do
+ allow(Dir).to receive(:glob).with(Rails.root.join('data', 'whats_new', '*.yml')).and_return(fixture_dir_glob)
+ end
- it { is_expected.to eq('display-whats-new-notification-84.0') }
+ it { is_expected.to eq('display-whats-new-notification-01.05') }
end
context 'when recent release items do NOT exist' do
- let(:version) { nil }
+ before do
+ allow(helper).to receive(:whats_new_release_items).and_return(nil)
+ end
it { is_expected.to be_nil }
end
@@ -27,8 +29,6 @@ RSpec.describe WhatsNewHelper do
subject { helper.whats_new_most_recent_release_items_count }
context 'when recent release items exist' do
- let(:fixture_dir_glob) { Dir.glob(File.join('spec', 'fixtures', 'whats_new', '*.yml')) }
-
it 'returns the count from the most recent file' do
expect(Dir).to receive(:glob).with(Rails.root.join('data', 'whats_new', '*.yml')).and_return(fixture_dir_glob)
@@ -48,4 +48,13 @@ RSpec.describe WhatsNewHelper do
end
end
end
+
+ # Testing this important private method here because the request spec required multiple confusing mocks and felt wrong and overcomplicated
+ describe '#whats_new_items_cache_key' do
+ it 'returns a key containing the most recent file name and page parameter' do
+ allow(Dir).to receive(:glob).with(Rails.root.join('data', 'whats_new', '*.yml')).and_return(fixture_dir_glob)
+
+ expect(helper.send(:whats_new_items_cache_key, 2)).to eq('whats_new:release_items:file-20201225_01_05:page-2')
+ end
+ end
end
diff --git a/spec/lib/api/entities/merge_request_changes_spec.rb b/spec/lib/api/entities/merge_request_changes_spec.rb
new file mode 100644
index 00000000000..f46d8981328
--- /dev/null
+++ b/spec/lib/api/entities/merge_request_changes_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::API::Entities::MergeRequestChanges do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:merge_request) { create(:merge_request) }
+ let(:entity) { described_class.new(merge_request, current_user: user) }
+
+ subject(:basic_entity) { entity.as_json }
+
+ it "exposes basic entity fields" do
+ is_expected.to include(:changes, :overflow)
+ end
+
+ context "when #expose_raw_diffs? returns false" do
+ before do
+ expect(entity).to receive(:expose_raw_diffs?).twice.and_return(false)
+ expect_any_instance_of(Gitlab::Git::DiffCollection).to receive(:overflow?)
+ end
+
+ it "does not access merge_request.raw_diffs" do
+ expect(merge_request).not_to receive(:raw_diffs)
+
+ basic_entity
+ end
+ end
+
+ context "when #expose_raw_diffs? returns true" do
+ before do
+ expect(entity).to receive(:expose_raw_diffs?).twice.and_return(true)
+ expect_any_instance_of(Gitlab::Git::DiffCollection).not_to receive(:overflow?)
+ end
+
+ it "does not access merge_request.raw_diffs" do
+ expect(merge_request).to receive(:raw_diffs)
+
+ basic_entity
+ end
+ end
+
+ describe ":overflow field" do
+ context "when :access_raw_diffs is true" do
+ let_it_be(:entity_with_raw_diffs) do
+ described_class.new(merge_request, current_user: user, access_raw_diffs: true).as_json
+ end
+
+ before do
+ expect_any_instance_of(Gitlab::Git::DiffCollection).not_to receive(:overflow?)
+ end
+
+ it "reports false" do
+ expect(entity_with_raw_diffs[:overflow]).to be_falsy
+ end
+ end
+ end
+end
diff --git a/spec/lib/api/every_api_endpoint_spec.rb b/spec/lib/api/every_api_endpoint_spec.rb
new file mode 100644
index 00000000000..ebf75e733d0
--- /dev/null
+++ b/spec/lib/api/every_api_endpoint_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Every API endpoint' do
+ context 'feature categories' do
+ let_it_be(:feature_categories) do
+ YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:to_sym).to_set
+ end
+
+ let_it_be(:api_endpoints) do
+ API::API.routes.map do |route|
+ [route.app.options[:for], API::Base.path_for_app(route.app)]
+ end
+ end
+
+ let_it_be(:routes_without_category) do
+ api_endpoints.map do |(klass, path)|
+ next if klass.try(:feature_category_for_action, path)
+
+ "#{klass}##{path}"
+ end.compact.uniq
+ end
+
+ it "has feature categories" do
+ expect(routes_without_category).to be_empty, "#{routes_without_category} did not have a category"
+ end
+
+ it "recognizes the feature categories" do
+ routes_unknown_category = api_endpoints.map do |(klass, path)|
+ used_category = klass.try(:feature_category_for_action, path)
+ next unless used_category
+ next if used_category == :not_owned
+
+ [path, used_category] unless feature_categories.include?(used_category)
+ end.compact
+
+ expect(routes_unknown_category).to be_empty, "#{routes_unknown_category.first(10)} had an unknown category"
+ end
+
+ # This is required for API::Base.path_for_app to work, as it picks
+ # the first path
+ it "has no routes with multiple paths" do
+ routes_with_multiple_paths = API::API.routes.select { |route| route.app.options[:path].length != 1 }
+ failure_routes = routes_with_multiple_paths.map { |route| "#{route.app.options[:for]}:[#{route.app.options[:path].join(', ')}]" }
+
+ expect(routes_with_multiple_paths).to be_empty, "#{failure_routes} have multiple paths"
+ end
+
+ it "doesn't define or exclude categories on removed actions", :aggregate_failures do
+ api_endpoints.group_by(&:first).each do |klass, paths|
+ existing_paths = paths.map(&:last)
+ used_paths = paths_defined_in_feature_category_config(klass)
+ non_existing_used_paths = used_paths - existing_paths
+
+ expect(non_existing_used_paths).to be_empty,
+ "#{klass} used #{non_existing_used_paths} to define feature category, but the route does not exist"
+ end
+ end
+ end
+
+ def paths_defined_in_feature_category_config(klass)
+ (klass.try(:class_attributes) || {}).fetch(:feature_category_config, {})
+ .values
+ .flatten
+ .map(&:to_s)
+ end
+end
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index 8e738af0fa3..be5f0cc9f9a 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -176,10 +176,10 @@ RSpec.describe API::Helpers do
end
describe '#track_event' do
- it "creates a gitlab tracking event" do
- expect(Gitlab::Tracking).to receive(:event).with('foo', 'my_event', {})
-
+ it "creates a gitlab tracking event", :snowplow do
subject.track_event('my_event', category: 'foo')
+
+ expect_snowplow_event(category: 'foo', action: 'my_event')
end
it "logs an exception" do
diff --git a/spec/lib/api/validations/validators/email_or_email_list_spec.rb b/spec/lib/api/validations/validators/email_or_email_list_spec.rb
new file mode 100644
index 00000000000..ac3111c2319
--- /dev/null
+++ b/spec/lib/api/validations/validators/email_or_email_list_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Validations::Validators::EmailOrEmailList do
+ include ApiValidatorsHelpers
+
+ subject do
+ described_class.new(['email'], {}, false, scope.new)
+ end
+
+ context 'with valid email addresses' do
+ it 'does not raise a validation error' do
+ expect_no_validation_error('test' => 'test@example.org')
+ expect_no_validation_error('test' => 'test1@example.com,test2@example.org')
+ expect_no_validation_error('test' => 'test1@example.com,test2@example.org,test3@example.co.uk')
+ end
+ end
+
+ context 'including any invalid email address' do
+ it 'raises a validation error' do
+ expect_validation_error('test' => 'not')
+ expect_validation_error('test' => '@example.com')
+ expect_validation_error('test' => 'test1@example.com,asdf')
+ expect_validation_error('test' => 'asdf,testa1@example.com,asdf')
+ end
+ end
+end
diff --git a/spec/lib/atlassian/jira_connect/client_spec.rb b/spec/lib/atlassian/jira_connect/client_spec.rb
index 40ffec21b26..cefd1fa3274 100644
--- a/spec/lib/atlassian/jira_connect/client_spec.rb
+++ b/spec/lib/atlassian/jira_connect/client_spec.rb
@@ -11,9 +11,20 @@ RSpec.describe Atlassian::JiraConnect::Client do
Timecop.freeze { example.run }
end
+ describe '.generate_update_sequence_id' do
+ it 'returns monotonic_time converted it to integer' do
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(1.0)
+
+ expect(described_class.generate_update_sequence_id).to eq(1)
+ end
+ end
+
describe '#store_dev_info' do
- it "calls the API with auth headers" do
- expected_jwt = Atlassian::Jwt.encode(
+ let_it_be(:project) { create_default(:project, :repository) }
+ let_it_be(:merge_requests) { create_list(:merge_request, 2, :unique_branches) }
+
+ let(:expected_jwt) do
+ Atlassian::Jwt.encode(
Atlassian::Jwt.build_claims(
Atlassian::JiraConnect.app_key,
'/rest/devinfo/0.10/bulk',
@@ -21,7 +32,9 @@ RSpec.describe Atlassian::JiraConnect::Client do
),
'sample_secret'
)
+ end
+ before do
stub_full_request('https://gitlab-test.atlassian.net/rest/devinfo/0.10/bulk', method: :post)
.with(
headers: {
@@ -29,8 +42,18 @@ RSpec.describe Atlassian::JiraConnect::Client do
'Content-Type' => 'application/json'
}
)
+ end
+
+ it "calls the API with auth headers" do
+ subject.store_dev_info(project: project)
+ end
+
+ it 'avoids N+1 database queries' do
+ control_count = ActiveRecord::QueryRecorder.new { subject.store_dev_info(project: project, merge_requests: merge_requests) }.count
+
+ merge_requests << create(:merge_request, :unique_branches)
- subject.store_dev_info(project: create(:project))
+ expect { subject.store_dev_info(project: project, merge_requests: merge_requests) }.not_to exceed_query_limit(control_count)
end
end
end
diff --git a/spec/lib/atlassian/jira_connect/serializers/base_entity_spec.rb b/spec/lib/atlassian/jira_connect/serializers/base_entity_spec.rb
new file mode 100644
index 00000000000..d7672c0baf1
--- /dev/null
+++ b/spec/lib/atlassian/jira_connect/serializers/base_entity_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Atlassian::JiraConnect::Serializers::BaseEntity do
+ let(:update_sequence_id) { nil }
+
+ subject do
+ described_class.represent(
+ anything,
+ update_sequence_id: update_sequence_id
+ )
+ end
+
+ it 'generates the update_sequence_id' do
+ allow(Atlassian::JiraConnect::Client).to receive(:generate_update_sequence_id).and_return(1)
+
+ expect(subject.value_for(:updateSequenceId)).to eq(1)
+ end
+
+ context 'with update_sequence_id option' do
+ let(:update_sequence_id) { 123 }
+
+ it 'uses the custom update_sequence_id' do
+ expect(subject.value_for(:updateSequenceId)).to eq(123)
+ end
+ end
+end
diff --git a/spec/lib/atlassian/jira_connect/serializers/pull_request_entity_spec.rb b/spec/lib/atlassian/jira_connect/serializers/pull_request_entity_spec.rb
new file mode 100644
index 00000000000..872ba1ab43d
--- /dev/null
+++ b/spec/lib/atlassian/jira_connect/serializers/pull_request_entity_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Atlassian::JiraConnect::Serializers::PullRequestEntity do
+ let_it_be(:project) { create_default(:project, :repository) }
+ let_it_be(:merge_requests) { create_list(:merge_request, 2, :unique_branches) }
+ let_it_be(:notes) { create_list(:note, 2, system: false, noteable: merge_requests.first) }
+
+ subject { described_class.represent(merge_requests).as_json }
+
+ it 'exposes commentCount' do
+ expect(subject.first[:commentCount]).to eq(2)
+ end
+
+ context 'with user_notes_count option' do
+ let(:user_notes_count) { merge_requests.map { |merge_request| [merge_request.id, 1] }.to_h }
+
+ subject { described_class.represent(merge_requests, user_notes_count: user_notes_count).as_json }
+
+ it 'avoids N+1 database queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ described_class.represent(merge_requests, user_notes_count: user_notes_count)
+ end.count
+
+ merge_requests << create(:merge_request, :unique_branches)
+
+ expect { subject }.not_to exceed_query_limit(control_count)
+ end
+
+ it 'uses counts from user_notes_count' do
+ expect(subject.map { |entity| entity[:commentCount] }).to match_array([1, 1, 1])
+ end
+
+ context 'when count is missing for some MRs' do
+ let(:user_notes_count) { [[merge_requests.last.id, 1]].to_h }
+
+ it 'uses 0 as default when count for the MR is not available' do
+ expect(subject.map { |entity| entity[:commentCount] }).to match_array([0, 0, 1])
+ end
+ end
+ 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
index 23ba1770827..9100398ecc5 100644
--- a/spec/lib/atlassian/jira_connect/serializers/repository_entity_spec.rb
+++ b/spec/lib/atlassian/jira_connect/serializers/repository_entity_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Atlassian::JiraConnect::Serializers::RepositoryEntity do
+ let(:update_sequence_id) { nil }
+
subject do
project = create(:project, :repository)
commits = [project.commit]
@@ -13,9 +15,23 @@ RSpec.describe Atlassian::JiraConnect::Serializers::RepositoryEntity do
project,
commits: commits,
branches: branches,
- merge_requests: merge_requests
+ merge_requests: merge_requests,
+ update_sequence_id: update_sequence_id
).to_json
end
it { is_expected.to match_schema('jira_connect/repository') }
+
+ context 'with custom update_sequence_id' do
+ let(:update_sequence_id) { 1.0 }
+
+ it 'passes the update_sequence_id on to the nested entities', :aggregate_failures do
+ parsed_subject = Gitlab::Json.parse(subject)
+
+ expect(parsed_subject['updateSequenceId']).to eq(update_sequence_id)
+ expect(parsed_subject['commits'].first['updateSequenceId']).to eq(update_sequence_id)
+ expect(parsed_subject['branches'].first['updateSequenceId']).to eq(update_sequence_id)
+ expect(parsed_subject['pullRequests'].first['updateSequenceId']).to eq(update_sequence_id)
+ end
+ end
end
diff --git a/spec/lib/backup/artifacts_spec.rb b/spec/lib/backup/artifacts_spec.rb
index 2a3f1949ba5..5a965030b01 100644
--- a/spec/lib/backup/artifacts_spec.rb
+++ b/spec/lib/backup/artifacts_spec.rb
@@ -30,7 +30,8 @@ RSpec.describe Backup::Artifacts do
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)
+ 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).and_return([[true, true], ''])
+ expect(backup).to receive(:pipeline_succeeded?).and_return(true)
backup.dump
end
end
diff --git a/spec/lib/backup/files_spec.rb b/spec/lib/backup/files_spec.rb
index 45cc73974d6..dbc04704fba 100644
--- a/spec/lib/backup/files_spec.rb
+++ b/spec/lib/backup/files_spec.rb
@@ -6,6 +6,10 @@ RSpec.describe Backup::Files do
let(:progress) { StringIO.new }
let!(:project) { create(:project) }
+ let(:status_0) { double('exit 0', success?: true, exitstatus: 0) }
+ let(:status_1) { double('exit 1', success?: false, exitstatus: 1) }
+ let(:status_2) { double('exit 2', success?: false, exitstatus: 2) }
+
before do
allow(progress).to receive(:puts)
allow(progress).to receive(:print)
@@ -24,6 +28,20 @@ RSpec.describe Backup::Files do
allow_any_instance_of(described_class).to receive(:progress).and_return(progress)
end
+ RSpec::Matchers.define :eq_statuslist do |expected|
+ match do |actual|
+ actual.map(&:exitstatus) == expected.map(&:exitstatus)
+ end
+
+ description do
+ 'be an Array of Process::Status with equal exitstatus against expected'
+ end
+
+ failure_message do |actual|
+ "expected #{actual} exitstatuses list to be equal #{expected} exitstatuses list"
+ end
+ end
+
describe '#restore' do
subject { described_class.new('registry', '/var/gitlab-registry') }
@@ -35,8 +53,9 @@ RSpec.describe Backup::Files do
describe 'folders with permission' do
before do
- allow(subject).to receive(:run_pipeline!).and_return(true)
+ allow(subject).to receive(:run_pipeline!).and_return([[true, true], ''])
allow(subject).to receive(:backup_existing_files).and_return(true)
+ allow(subject).to receive(:pipeline_succeeded?).and_return(true)
allow(Dir).to receive(:glob).with("/var/gitlab-registry/*", File::FNM_DOTMATCH).and_return(["/var/gitlab-registry/.", "/var/gitlab-registry/..", "/var/gitlab-registry/sample1"])
end
@@ -54,14 +73,22 @@ RSpec.describe Backup::Files do
expect(subject).to receive(:tar).and_return('blabla-tar')
expect(subject).to receive(:run_pipeline!).with([%w(gzip -cd), %w(blabla-tar --unlink-first --recursive-unlink -C /var/gitlab-registry -xf -)], any_args)
+ expect(subject).to receive(:pipeline_succeeded?).and_return(true)
subject.restore
end
+
+ it 'raises an error on failure' do
+ expect(subject).to receive(:pipeline_succeeded?).and_return(false)
+
+ expect { subject.restore }.to raise_error(/Restore operation failed:/)
+ end
end
describe 'folders without permissions' do
before do
allow(FileUtils).to receive(:mv).and_raise(Errno::EACCES)
- allow(subject).to receive(:run_pipeline!).and_return(true)
+ allow(subject).to receive(:run_pipeline!).and_return([[true, true], ''])
+ allow(subject).to receive(:pipeline_succeeded?).and_return(true)
end
it 'shows error message' do
@@ -73,7 +100,8 @@ RSpec.describe Backup::Files do
describe 'folders that are a mountpoint' do
before do
allow(FileUtils).to receive(:mv).and_raise(Errno::EBUSY)
- allow(subject).to receive(:run_pipeline!).and_return(true)
+ allow(subject).to receive(:run_pipeline!).and_return([[true, true], ''])
+ allow(subject).to receive(:pipeline_succeeded?).and_return(true)
end
it 'shows error message' do
@@ -89,7 +117,8 @@ RSpec.describe Backup::Files do
subject { described_class.new('pages', '/var/gitlab-pages', excludes: ['@pages.tmp']) }
before do
- allow(subject).to receive(:run_pipeline!).and_return(true)
+ allow(subject).to receive(:run_pipeline!).and_return([[true, true], ''])
+ allow(subject).to receive(:pipeline_succeeded?).and_return(true)
end
it 'raises no errors' do
@@ -103,29 +132,190 @@ RSpec.describe Backup::Files do
subject.dump
end
+ it 'raises an error on failure' do
+ allow(subject).to receive(:run_pipeline!).and_return([[true, true], ''])
+ expect(subject).to receive(:pipeline_succeeded?).and_return(false)
+
+ expect do
+ subject.dump
+ end.to raise_error(/Backup operation failed:/)
+ 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")
+ end
+ it 'excludes tmp dirs from rsync' do
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
+
+ it 'raises an error and outputs an error message if rsync failed' do
+ allow(Gitlab::Popen).to receive(:popen).with(%w(rsync -a --exclude=lost+found --exclude=/@pages.tmp /var/gitlab-pages /var/gitlab-backup)).and_return(['rsync failed', 1])
+
+ expect do
+ subject.dump
+ end.to output(/rsync failed/).to_stdout
+ .and raise_error(/Backup failed/)
+ end
+ end
+ end
+
+ describe '#exclude_dirs' do
+ subject { described_class.new('pages', '/var/gitlab-pages', excludes: ['@pages.tmp']) }
+
+ 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
+
+ describe '#run_pipeline!' do
+ subject { described_class.new('registry', '/var/gitlab-registry') }
+
+ it 'executes an Open3.pipeline for cmd_list' do
+ expect(Open3).to receive(:pipeline).with(%w[whew command], %w[another cmd], any_args)
+
+ subject.run_pipeline!([%w[whew command], %w[another cmd]])
+ end
+
+ it 'returns an empty output on success pipeline' do
+ expect(subject.run_pipeline!(%w[true true])[1]).to eq('')
+ end
+
+ it 'returns the stderr for failed pipeline' do
+ expect(
+ subject.run_pipeline!(['echo OMG: failed command present 1>&2; false', 'true'])[1]
+ ).to match(/OMG: failed/)
+ end
+
+ it 'returns the success status list on success pipeline' do
+ expect(
+ subject.run_pipeline!(%w[true true])[0]
+ ).to eq_statuslist([status_0, status_0])
+ end
+
+ it 'returns the failed status in status list for failed commands in pipeline' do
+ expect(subject.run_pipeline!(%w[false true true])[0]).to eq_statuslist([status_1, status_0, status_0])
+ expect(subject.run_pipeline!(%w[true false true])[0]).to eq_statuslist([status_0, status_1, status_0])
+ expect(subject.run_pipeline!(%w[false false true])[0]).to eq_statuslist([status_1, status_1, status_0])
+ expect(subject.run_pipeline!(%w[false true false])[0]).to eq_statuslist([status_1, status_0, status_1])
+ expect(subject.run_pipeline!(%w[false false false])[0]).to eq_statuslist([status_1, status_1, status_1])
+ end
+ end
+
+ describe '#pipeline_succeeded?' do
+ subject { described_class.new('registry', '/var/gitlab-registry') }
+
+ it 'returns true if both tar and gzip succeeeded' do
+ expect(
+ subject.pipeline_succeeded?(tar_status: status_0, gzip_status: status_0, output: 'any_output')
+ ).to be_truthy
+ end
+
+ it 'returns false if gzip failed' do
+ expect(
+ subject.pipeline_succeeded?(tar_status: status_1, gzip_status: status_1, output: 'any_output')
+ ).to be_falsey
+ end
+
+ context 'if gzip succeeded and tar failed non-critically' do
+ before do
+ allow(subject).to receive(:tar_ignore_non_success?).and_return(true)
+ end
+
+ it 'returns true' do
+ expect(
+ subject.pipeline_succeeded?(tar_status: status_1, gzip_status: status_0, output: 'any_output')
+ ).to be_truthy
+ end
+ end
+
+ context 'if gzip succeeded and tar failed in other cases' do
+ before do
+ allow(subject).to receive(:tar_ignore_non_success?).and_return(false)
+ end
+
+ it 'returns false' do
+ expect(
+ subject.pipeline_succeeded?(tar_status: status_1, gzip_status: status_0, output: 'any_output')
+ ).to be_falsey
+ end
+ end
+ end
+
+ describe '#tar_ignore_non_success?' do
+ subject { described_class.new('registry', '/var/gitlab-registry') }
+
+ context 'if `tar` command exits with 1 exitstatus' do
+ it 'returns true' do
+ expect(
+ subject.tar_ignore_non_success?(1, 'any_output')
+ ).to be_truthy
+ end
+
+ it 'outputs a warning' do
+ expect do
+ subject.tar_ignore_non_success?(1, 'any_output')
+ end.to output(/Ignoring tar exit status 1/).to_stdout
+ end
+ end
+
+ context 'if `tar` command exits with 2 exitstatus with non-critical warning' do
+ before do
+ allow(subject).to receive(:noncritical_warning?).and_return(true)
+ end
+
+ it 'returns true' do
+ expect(
+ subject.tar_ignore_non_success?(2, 'any_output')
+ ).to be_truthy
+ end
+
+ it 'outputs a warning' do
+ expect do
+ subject.tar_ignore_non_success?(2, 'any_output')
+ end.to output(/Ignoring non-success exit status/).to_stdout
+ 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'])
+ context 'if `tar` command exits with any other unlisted error' do
+ before do
+ allow(subject).to receive(:noncritical_warning?).and_return(false)
end
- it 'prepends a leading slash to rsync excludes' do
- expect(subject.exclude_dirs(:rsync)).to eq(['--exclude=lost+found', '--exclude=/@pages.tmp'])
+ it 'returns false' do
+ expect(
+ subject.tar_ignore_non_success?(2, 'any_output')
+ ).to be_falsey
end
end
end
+
+ describe '#noncritical_warning?' do
+ subject { described_class.new('registry', '/var/gitlab-registry') }
+
+ it 'returns true if given text matches noncritical warnings list' do
+ expect(
+ subject.noncritical_warning?('tar: .: Cannot mkdir: No such file or directory')
+ ).to be_truthy
+
+ expect(
+ subject.noncritical_warning?('gtar: .: Cannot mkdir: No such file or directory')
+ ).to be_truthy
+ end
+
+ it 'returns false otherwize' do
+ expect(
+ subject.noncritical_warning?('unknown message')
+ ).to be_falsey
+ end
+ end
end
diff --git a/spec/lib/backup/pages_spec.rb b/spec/lib/backup/pages_spec.rb
index 59df4d1adf7..551d2df8f30 100644
--- a/spec/lib/backup/pages_spec.rb
+++ b/spec/lib/backup/pages_spec.rb
@@ -23,7 +23,8 @@ RSpec.describe Backup::Pages 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)
+ 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).and_return([[true, true], ''])
+ expect(subject).to receive(:pipeline_succeeded?).and_return(true)
subject.dump
end
end
diff --git a/spec/lib/backup/uploads_spec.rb b/spec/lib/backup/uploads_spec.rb
index 678b670db34..a82cb764f4d 100644
--- a/spec/lib/backup/uploads_spec.rb
+++ b/spec/lib/backup/uploads_spec.rb
@@ -32,7 +32,8 @@ RSpec.describe Backup::Uploads do
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)
+ expect(backup).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found --exclude=./tmp -C /var/uploads -cf - .), 'gzip -c -1'], any_args).and_return([[true, true], ''])
+ expect(backup).to receive(:pipeline_succeeded?).and_return(true)
backup.dump
end
end
diff --git a/spec/lib/banzai/filter/emoji_filter_spec.rb b/spec/lib/banzai/filter/emoji_filter_spec.rb
index d78763b6939..9005b4401b7 100644
--- a/spec/lib/banzai/filter/emoji_filter_spec.rb
+++ b/spec/lib/banzai/filter/emoji_filter_spec.rb
@@ -21,6 +21,20 @@ RSpec.describe Banzai::Filter::EmojiFilter do
expect(doc.to_html).to match Regexp.escape(exp)
end
+ it 'ignores unicode versions of trademark, copyright, and registered trademark' do
+ exp = act = '<p>™ © ®</p>'
+ doc = filter(act)
+ expect(doc.to_html).to match Regexp.escape(exp)
+ end
+
+ it 'replaces name versions of trademark, copyright, and registered trademark' do
+ doc = filter('<p>:tm: :copyright: :registered:</p>')
+
+ expect(doc.css('gl-emoji')[0].text).to eq 'â„¢'
+ expect(doc.css('gl-emoji')[1].text).to eq '©'
+ expect(doc.css('gl-emoji')[2].text).to eq '®'
+ end
+
it 'correctly encodes the URL' do
doc = filter('<p>:+1:</p>')
expect(doc.css('gl-emoji').first.text).to eq 'ðŸ‘'
diff --git a/spec/lib/banzai/filter/normalize_source_filter_spec.rb b/spec/lib/banzai/filter/normalize_source_filter_spec.rb
new file mode 100644
index 00000000000..8eaeec0e7b0
--- /dev/null
+++ b/spec/lib/banzai/filter/normalize_source_filter_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::NormalizeSourceFilter do
+ include FilterSpecHelper
+
+ it 'removes the UTF8 BOM from the beginning of the text' do
+ content = "\xEF\xBB\xBF---"
+
+ output = filter(content)
+
+ expect(output).to match '---'
+ end
+
+ it 'does not remove those characters from anywhere else in the text' do
+ content = <<~MD
+ \xEF\xBB\xBF---
+ \xEF\xBB\xBF---
+ MD
+
+ output = filter(content)
+
+ expect(output).to match "---\n\xEF\xBB\xBF---\n"
+ end
+end
diff --git a/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb b/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb
new file mode 100644
index 00000000000..fc74c592867
--- /dev/null
+++ b/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Pipeline::PreProcessPipeline do
+ it 'pre-processes the source text' do
+ markdown = <<~MD
+ \xEF\xBB\xBF---
+ foo: :foo_symbol
+ bar: :bar_symbol
+ ---
+
+ >>>
+ blockquote
+ >>>
+ MD
+
+ result = described_class.call(markdown, {})
+
+ aggregate_failures do
+ expect(result[:output]).not_to include "\xEF\xBB\xBF"
+ expect(result[:output]).not_to include '---'
+ expect(result[:output]).to include "```yaml\nfoo: :foo_symbol\n"
+ expect(result[:output]).to include "> blockquote\n"
+ end
+ end
+end
diff --git a/spec/lib/banzai/reference_parser/base_parser_spec.rb b/spec/lib/banzai/reference_parser/base_parser_spec.rb
index 5ab76b2c68b..18d8418ca23 100644
--- a/spec/lib/banzai/reference_parser/base_parser_spec.rb
+++ b/spec/lib/banzai/reference_parser/base_parser_spec.rb
@@ -323,6 +323,9 @@ RSpec.describe Banzai::ReferenceParser::BaseParser do
it 'will not overflow the stack' do
ids = 1.upto(1_000_000).to_a
+ # Avoid executing a large, unnecessary SQL query
+ expect(User).to receive(:where).with(id: ids).and_return(User.none)
+
expect { subject.collection_objects_for_ids(User, ids) }.not_to raise_error
end
end
diff --git a/spec/lib/banzai/reference_parser/design_parser_spec.rb b/spec/lib/banzai/reference_parser/design_parser_spec.rb
index 92d3a4aaad2..a9cb2952c26 100644
--- a/spec/lib/banzai/reference_parser/design_parser_spec.rb
+++ b/spec/lib/banzai/reference_parser/design_parser_spec.rb
@@ -29,9 +29,11 @@ RSpec.describe Banzai::ReferenceParser::DesignParser do
let_it_be(:other_project_link) do
design_link(create(:design, :with_versions))
end
+
let_it_be(:public_link) do
design_link(create(:design, :with_versions, issue: create(:issue, project: public_project)))
end
+
let_it_be(:public_but_confidential_link) do
design_link(create(:design, :with_versions, issue: create(:issue, :confidential, project: public_project)))
end
diff --git a/spec/lib/bitbucket_server/client_spec.rb b/spec/lib/bitbucket_server/client_spec.rb
index 9dcd1500aab..cd3179f19d4 100644
--- a/spec/lib/bitbucket_server/client_spec.rb
+++ b/spec/lib/bitbucket_server/client_spec.rb
@@ -19,6 +19,15 @@ RSpec.describe BitbucketServer::Client do
subject.pull_requests(project, repo_slug)
end
+
+ it 'requests a collection with offset and limit' do
+ offset = 10
+ limit = 100
+
+ expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :pull_request, page_offset: offset, limit: limit)
+
+ subject.pull_requests(project, repo_slug, page_offset: offset, limit: limit)
+ end
end
describe '#activities' do
diff --git a/spec/lib/bulk_imports/clients/http_spec.rb b/spec/lib/bulk_imports/clients/http_spec.rb
new file mode 100644
index 00000000000..2d841b7fac2
--- /dev/null
+++ b/spec/lib/bulk_imports/clients/http_spec.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Clients::Http do
+ include ImportSpecHelper
+
+ let(:uri) { 'http://gitlab.example' }
+ let(:token) { 'token' }
+ let(:resource) { 'resource' }
+
+ subject { described_class.new(uri: uri, token: token) }
+
+ describe '#get' do
+ let(:response_double) { double(code: 200, success?: true, parsed_response: {}) }
+
+ shared_examples 'performs network request' do
+ it 'performs network request' do
+ expect(Gitlab::HTTP).to receive(:get).with(*expected_args).and_return(response_double)
+
+ subject.get(resource)
+ end
+ end
+
+ describe 'request query' do
+ include_examples 'performs network request' do
+ let(:expected_args) do
+ [
+ anything,
+ hash_including(
+ query: {
+ page: described_class::DEFAULT_PAGE,
+ per_page: described_class::DEFAULT_PER_PAGE
+ }
+ )
+ ]
+ end
+ end
+ end
+
+ describe 'request headers' do
+ include_examples 'performs network request' do
+ let(:expected_args) do
+ [
+ anything,
+ hash_including(
+ headers: {
+ 'Content-Type' => 'application/json',
+ 'Authorization' => "Bearer #{token}"
+ }
+ )
+ ]
+ end
+ end
+ end
+
+ describe 'request uri' do
+ include_examples 'performs network request' do
+ let(:expected_args) do
+ ['http://gitlab.example:80/api/v4/resource', anything]
+ end
+ end
+ end
+
+ context 'error handling' do
+ context 'when error occurred' do
+ it 'raises ConnectionError' do
+ allow(Gitlab::HTTP).to receive(:get).and_raise(Errno::ECONNREFUSED)
+
+ expect { subject.get(resource) }.to raise_exception(described_class::ConnectionError)
+ end
+ end
+
+ context 'when response is not success' do
+ it 'raises ConnectionError' do
+ response_double = double(code: 503, success?: false)
+
+ allow(Gitlab::HTTP).to receive(:get).and_return(response_double)
+
+ expect { subject.get(resource) }.to raise_exception(described_class::ConnectionError)
+ end
+ end
+ end
+
+ describe '#each_page' do
+ let(:objects1) { [{ object: 1 }, { object: 2 }] }
+ let(:objects2) { [{ object: 3 }, { object: 4 }] }
+ let(:response1) { double(success?: true, headers: { 'x-next-page' => 2 }, parsed_response: objects1) }
+ let(:response2) { double(success?: true, headers: {}, parsed_response: objects2) }
+
+ before do
+ stub_http_get('groups', { page: 1, per_page: 30 }, response1)
+ stub_http_get('groups', { page: 2, per_page: 30 }, response2)
+ end
+
+ context 'with a block' do
+ it 'yields every retrieved page to the supplied block' do
+ pages = []
+
+ subject.each_page(:get, 'groups') { |page| pages << page }
+
+ expect(pages[0]).to be_an_instance_of(Array)
+ expect(pages[1]).to be_an_instance_of(Array)
+
+ expect(pages[0]).to eq(objects1)
+ expect(pages[1]).to eq(objects2)
+ end
+ end
+
+ context 'without a block' do
+ it 'returns an Enumerator' do
+ expect(subject.each_page(:get, :foo)).to be_an_instance_of(Enumerator)
+ end
+ end
+
+ private
+
+ def stub_http_get(path, query, response)
+ uri = "http://gitlab.example:80/api/v4/#{path}"
+ params = {
+ follow_redirects: false,
+ headers: {
+ "Authorization" => "Bearer token",
+ "Content-Type" => "application/json"
+ }
+ }.merge(query: query)
+
+ allow(Gitlab::HTTP).to receive(:get).with(uri, params).and_return(response)
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb b/spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb
new file mode 100644
index 00000000000..cde8e2d5c18
--- /dev/null
+++ b/spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Extractors::GraphqlExtractor do
+ let(:graphql_client) { instance_double(BulkImports::Clients::Graphql) }
+ let(:import_entity) { create(:bulk_import_entity) }
+ let(:response) { double(original_hash: { foo: :bar }) }
+ let(:query) { { query: double(to_s: 'test', variables: {}) } }
+ let(:context) do
+ instance_double(
+ BulkImports::Pipeline::Context,
+ entity: import_entity
+ )
+ end
+
+ subject { described_class.new(query) }
+
+ before do
+ allow(subject).to receive(:graphql_client).and_return(graphql_client)
+ allow(graphql_client).to receive(:parse)
+ end
+
+ describe '#extract' do
+ before do
+ allow(subject).to receive(:query_variables).and_return({})
+ allow(graphql_client).to receive(:execute).and_return(response)
+ end
+
+ it 'returns an enumerator with fetched results' do
+ response = subject.extract(context)
+
+ expect(response).to be_instance_of(Enumerator)
+ expect(response.first).to eq({ foo: :bar })
+ end
+ end
+
+ describe 'query variables' do
+ before do
+ allow(graphql_client).to receive(:execute).and_return(response)
+ end
+
+ context 'when variables are present' do
+ let(:query) { { query: double(to_s: 'test', variables: { full_path: :source_full_path }) } }
+
+ it 'builds graphql query variables for import entity' do
+ expected_variables = { full_path: import_entity.source_full_path }
+
+ expect(graphql_client).to receive(:execute).with(anything, expected_variables)
+
+ subject.extract(context).first
+ end
+ end
+
+ context 'when no variables are present' do
+ let(:query) { { query: double(to_s: 'test', variables: nil) } }
+
+ it 'returns empty hash' do
+ expect(graphql_client).to receive(:execute).with(anything, nil)
+
+ subject.extract(context).first
+ end
+ end
+
+ context 'when variables are empty hash' do
+ let(:query) { { query: double(to_s: 'test', variables: {}) } }
+
+ it 'makes graphql request with empty hash' do
+ expect(graphql_client).to receive(:execute).with(anything, {})
+
+ subject.extract(context).first
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/common/loaders/entity_loader_spec.rb b/spec/lib/bulk_imports/common/loaders/entity_loader_spec.rb
new file mode 100644
index 00000000000..4de7d95172f
--- /dev/null
+++ b/spec/lib/bulk_imports/common/loaders/entity_loader_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Loaders::EntityLoader do
+ describe '#load' do
+ it "creates entities for the given data" do
+ group = create(:group, path: "imported-group")
+ parent_entity = create(:bulk_import_entity, group: group, bulk_import: create(:bulk_import))
+ context = instance_double(BulkImports::Pipeline::Context, entity: parent_entity)
+
+ data = {
+ source_type: :group_entity,
+ source_full_path: "parent/subgroup",
+ destination_name: "subgroup",
+ destination_namespace: parent_entity.group.full_path,
+ parent_id: parent_entity.id
+ }
+
+ expect { subject.load(context, data) }.to change(BulkImports::Entity, :count).by(1)
+
+ subgroup_entity = BulkImports::Entity.last
+
+ expect(subgroup_entity.source_full_path).to eq 'parent/subgroup'
+ expect(subgroup_entity.destination_namespace).to eq 'imported-group'
+ expect(subgroup_entity.destination_name).to eq 'subgroup'
+ expect(subgroup_entity.parent_id).to eq parent_entity.id
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/common/transformers/graphql_cleaner_transformer_spec.rb b/spec/lib/bulk_imports/common/transformers/graphql_cleaner_transformer_spec.rb
new file mode 100644
index 00000000000..8f39b6e7c93
--- /dev/null
+++ b/spec/lib/bulk_imports/common/transformers/graphql_cleaner_transformer_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Transformers::GraphqlCleanerTransformer do
+ describe '#transform' do
+ let_it_be(:expected_output) do
+ {
+ 'name' => 'test',
+ 'fullName' => 'test',
+ 'description' => 'test',
+ 'labels' => [
+ { 'title' => 'label1' },
+ { 'title' => 'label2' },
+ { 'title' => 'label3' }
+ ]
+ }
+ end
+
+ it 'deep cleans hash from GraphQL keys' do
+ data = {
+ 'data' => {
+ 'group' => {
+ 'name' => 'test',
+ 'fullName' => 'test',
+ 'description' => 'test',
+ 'labels' => {
+ 'edges' => [
+ { 'node' => { 'title' => 'label1' } },
+ { 'node' => { 'title' => 'label2' } },
+ { 'node' => { 'title' => 'label3' } }
+ ]
+ }
+ }
+ }
+ }
+
+ transformed_data = described_class.new.transform(nil, data)
+
+ expect(transformed_data).to eq(expected_output)
+ end
+
+ context 'when data does not have data/group nesting' do
+ it 'deep cleans hash from GraphQL keys' do
+ data = {
+ 'name' => 'test',
+ 'fullName' => 'test',
+ 'description' => 'test',
+ 'labels' => {
+ 'edges' => [
+ { 'node' => { 'title' => 'label1' } },
+ { 'node' => { 'title' => 'label2' } },
+ { 'node' => { 'title' => 'label3' } }
+ ]
+ }
+ }
+
+ transformed_data = described_class.new.transform(nil, data)
+
+ expect(transformed_data).to eq(expected_output)
+ end
+ end
+
+ context 'when data is not a hash' do
+ it 'does not perform transformation' do
+ data = 'test'
+
+ transformed_data = described_class.new.transform(nil, data)
+
+ expect(transformed_data).to eq(data)
+ end
+ end
+
+ context 'when nested data is not an array or hash' do
+ it 'only removes top level data/group keys' do
+ data = {
+ 'data' => {
+ 'group' => 'test'
+ }
+ }
+
+ transformed_data = described_class.new.transform(nil, data)
+
+ expect(transformed_data).to eq('test')
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/common/transformers/underscorify_keys_transformer_spec.rb b/spec/lib/bulk_imports/common/transformers/underscorify_keys_transformer_spec.rb
new file mode 100644
index 00000000000..cdffa750694
--- /dev/null
+++ b/spec/lib/bulk_imports/common/transformers/underscorify_keys_transformer_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Transformers::UnderscorifyKeysTransformer do
+ describe '#transform' do
+ it 'deep underscorifies hash keys' do
+ data = {
+ 'fullPath' => 'Foo',
+ 'snakeKeys' => {
+ 'snakeCaseKey' => 'Bar',
+ 'moreKeys' => {
+ 'anotherSnakeCaseKey' => 'Test'
+ }
+ }
+ }
+
+ transformed_data = described_class.new.transform(nil, data)
+
+ expect(transformed_data).to have_key('full_path')
+ expect(transformed_data).to have_key('snake_keys')
+ expect(transformed_data['snake_keys']).to have_key('snake_case_key')
+ expect(transformed_data['snake_keys']).to have_key('more_keys')
+ expect(transformed_data.dig('snake_keys', 'more_keys')).to have_key('another_snake_case_key')
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb b/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb
new file mode 100644
index 00000000000..b14dfc615a9
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Loaders::GroupLoader do
+ describe '#load' do
+ let(:user) { create(:user) }
+ let(:data) { { foo: :bar } }
+ let(:service_double) { instance_double(::Groups::CreateService) }
+ let(:entity) { create(:bulk_import_entity) }
+ let(:context) do
+ instance_double(
+ BulkImports::Pipeline::Context,
+ entity: entity,
+ current_user: user
+ )
+ end
+
+ subject { described_class.new }
+
+ context 'when user can create group' do
+ shared_examples 'calls Group Create Service to create a new group' do
+ it 'calls Group Create Service to create a new group' do
+ expect(::Groups::CreateService).to receive(:new).with(context.current_user, data).and_return(service_double)
+ expect(service_double).to receive(:execute)
+ expect(entity).to receive(:update!)
+
+ subject.load(context, data)
+ end
+ end
+
+ context 'when there is no parent group' do
+ before do
+ allow(Ability).to receive(:allowed?).with(user, :create_group).and_return(true)
+ end
+
+ include_examples 'calls Group Create Service to create a new group'
+ end
+
+ context 'when there is parent group' do
+ let(:parent) { create(:group) }
+ let(:data) { { 'parent_id' => parent.id } }
+
+ before do
+ allow(Ability).to receive(:allowed?).with(user, :create_subgroup, parent).and_return(true)
+ end
+
+ include_examples 'calls Group Create Service to create a new group'
+ end
+ end
+
+ context 'when user cannot create group' do
+ shared_examples 'does not create new group' do
+ it 'does not create new group' do
+ expect(::Groups::CreateService).not_to receive(:new)
+
+ subject.load(context, data)
+ end
+ end
+
+ context 'when there is no parent group' do
+ before do
+ allow(Ability).to receive(:allowed?).with(user, :create_group).and_return(false)
+ end
+
+ include_examples 'does not create new group'
+ end
+
+ context 'when there is parent group' do
+ let(:parent) { create(:group) }
+ let(:data) { { 'parent_id' => parent.id } }
+
+ before do
+ allow(Ability).to receive(:allowed?).with(user, :create_subgroup, parent).and_return(false)
+ end
+
+ include_examples 'does not create new group'
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
new file mode 100644
index 00000000000..3949dd23b49
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Pipelines::GroupPipeline do
+ describe '#run' do
+ let(:user) { create(:user) }
+ let(:parent) { create(:group) }
+ let(:entity) do
+ create(
+ :bulk_import_entity,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Group',
+ destination_namespace: parent.full_path
+ )
+ end
+
+ let(:context) do
+ BulkImports::Pipeline::Context.new(
+ current_user: user,
+ entity: entity
+ )
+ end
+
+ let(:group_data) do
+ {
+ 'data' => {
+ 'group' => {
+ 'name' => 'source_name',
+ 'fullPath' => 'source/full/path',
+ 'visibility' => 'private',
+ 'projectCreationLevel' => 'developer',
+ 'subgroupCreationLevel' => 'maintainer',
+ 'description' => 'Group Description',
+ 'emailsDisabled' => true,
+ 'lfsEnabled' => false,
+ 'mentionsDisabled' => true
+ }
+ }
+ }
+ end
+
+ subject { described_class.new }
+
+ before do
+ allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return([group_data])
+ end
+
+ parent.add_owner(user)
+ end
+
+ it 'imports new group into destination group' do
+ group_path = 'my-destination-group'
+
+ subject.run(context)
+
+ imported_group = Group.find_by_path(group_path)
+
+ expect(imported_group).not_to be_nil
+ expect(imported_group.parent).to eq(parent)
+ expect(imported_group.path).to eq(group_path)
+ expect(imported_group.description).to eq(group_data.dig('data', 'group', 'description'))
+ expect(imported_group.visibility).to eq(group_data.dig('data', 'group', 'visibility'))
+ expect(imported_group.project_creation_level).to eq(Gitlab::Access.project_creation_string_options[group_data.dig('data', 'group', 'projectCreationLevel')])
+ expect(imported_group.subgroup_creation_level).to eq(Gitlab::Access.subgroup_creation_string_options[group_data.dig('data', 'group', 'subgroupCreationLevel')])
+ expect(imported_group.lfs_enabled?).to eq(group_data.dig('data', 'group', 'lfsEnabled'))
+ expect(imported_group.emails_disabled?).to eq(group_data.dig('data', 'group', 'emailsDisabled'))
+ expect(imported_group.mentions_disabled?).to eq(group_data.dig('data', 'group', 'mentionsDisabled'))
+ end
+ end
+
+ describe 'pipeline parts' do
+ it { expect(described_class).to include_module(BulkImports::Pipeline) }
+ it { expect(described_class).to include_module(BulkImports::Pipeline::Attributes) }
+ it { expect(described_class).to include_module(BulkImports::Pipeline::Runner) }
+
+ it 'has extractors' do
+ expect(described_class.extractors)
+ .to contain_exactly(
+ {
+ klass: BulkImports::Common::Extractors::GraphqlExtractor,
+ options: {
+ query: BulkImports::Groups::Graphql::GetGroupQuery
+ }
+ }
+ )
+ end
+
+ it 'has transformers' do
+ expect(described_class.transformers)
+ .to contain_exactly(
+ { klass: BulkImports::Common::Transformers::GraphqlCleanerTransformer, options: nil },
+ { klass: BulkImports::Common::Transformers::UnderscorifyKeysTransformer, options: nil },
+ { klass: BulkImports::Groups::Transformers::GroupAttributesTransformer, options: nil })
+ end
+
+ it 'has loaders' do
+ expect(described_class.loaders).to contain_exactly({ klass: BulkImports::Groups::Loaders::GroupLoader, options: nil })
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb
new file mode 100644
index 00000000000..60a4a796682
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline do
+ describe '#run' do
+ let_it_be(:user) { create(:user) }
+ let(:parent) { create(:group, name: 'imported-group', path: 'imported-group') }
+ let!(:parent_entity) do
+ create(
+ :bulk_import_entity,
+ destination_namespace: parent.full_path,
+ group: parent
+ )
+ end
+
+ let(:context) do
+ instance_double(
+ BulkImports::Pipeline::Context,
+ current_user: user,
+ entity: parent_entity
+ )
+ end
+
+ let(:subgroup_data) do
+ [
+ {
+ "name" => "subgroup",
+ "full_path" => "parent/subgroup"
+ }
+ ]
+ end
+
+ subject { described_class.new }
+
+ before do
+ allow_next_instance_of(BulkImports::Groups::Extractors::SubgroupsExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(subgroup_data)
+ end
+
+ parent.add_owner(user)
+ end
+
+ it 'creates entities for the subgroups' do
+ expect { subject.run(context) }.to change(BulkImports::Entity, :count).by(1)
+
+ subgroup_entity = BulkImports::Entity.last
+
+ expect(subgroup_entity.source_full_path).to eq 'parent/subgroup'
+ expect(subgroup_entity.destination_namespace).to eq 'imported-group'
+ expect(subgroup_entity.destination_name).to eq 'subgroup'
+ expect(subgroup_entity.parent_id).to eq parent_entity.id
+ end
+ end
+
+ describe 'pipeline parts' do
+ it { expect(described_class).to include_module(BulkImports::Pipeline) }
+ it { expect(described_class).to include_module(BulkImports::Pipeline::Attributes) }
+ it { expect(described_class).to include_module(BulkImports::Pipeline::Runner) }
+
+ it 'has extractors' do
+ expect(described_class.extractors).to contain_exactly(
+ klass: BulkImports::Groups::Extractors::SubgroupsExtractor,
+ options: nil
+ )
+ end
+
+ it 'has transformers' do
+ expect(described_class.transformers).to contain_exactly(
+ klass: BulkImports::Groups::Transformers::SubgroupToEntityTransformer,
+ options: nil
+ )
+ end
+
+ it 'has loaders' do
+ expect(described_class.loaders).to contain_exactly(
+ klass: BulkImports::Common::Loaders::EntityLoader,
+ options: nil
+ )
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb b/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
new file mode 100644
index 00000000000..28a7859915d
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Transformers::GroupAttributesTransformer do
+ describe '#transform' do
+ let(:user) { create(:user) }
+ let(:parent) { create(:group) }
+ let(:group) { create(:group, name: 'My Source Group', parent: parent) }
+ let(:entity) do
+ instance_double(
+ BulkImports::Entity,
+ source_full_path: 'source/full/path',
+ destination_name: group.name,
+ destination_namespace: parent.full_path
+ )
+ end
+
+ let(:context) do
+ instance_double(
+ BulkImports::Pipeline::Context,
+ current_user: user,
+ entity: entity
+ )
+ end
+
+ let(:data) do
+ {
+ 'name' => 'source_name',
+ 'full_path' => 'source/full/path',
+ 'visibility' => 'private',
+ 'project_creation_level' => 'developer',
+ 'subgroup_creation_level' => 'maintainer'
+ }
+ end
+
+ subject { described_class.new }
+
+ it 'transforms name to destination name' do
+ transformed_data = subject.transform(context, data)
+
+ expect(transformed_data['name']).not_to eq('source_name')
+ expect(transformed_data['name']).to eq(group.name)
+ end
+
+ it 'removes full path' do
+ transformed_data = subject.transform(context, data)
+
+ expect(transformed_data).not_to have_key('full_path')
+ end
+
+ it 'transforms path to parameterized name' do
+ transformed_data = subject.transform(context, data)
+
+ expect(transformed_data['path']).to eq(group.name.parameterize)
+ end
+
+ it 'transforms visibility level' do
+ visibility = data['visibility']
+ transformed_data = subject.transform(context, data)
+
+ expect(transformed_data).not_to have_key('visibility')
+ expect(transformed_data['visibility_level']).to eq(Gitlab::VisibilityLevel.string_options[visibility])
+ end
+
+ it 'transforms project creation level' do
+ level = data['project_creation_level']
+ transformed_data = subject.transform(context, data)
+
+ expect(transformed_data['project_creation_level']).to eq(Gitlab::Access.project_creation_string_options[level])
+ end
+
+ it 'transforms subgroup creation level' do
+ level = data['subgroup_creation_level']
+ transformed_data = subject.transform(context, data)
+
+ expect(transformed_data['subgroup_creation_level']).to eq(Gitlab::Access.subgroup_creation_string_options[level])
+ end
+
+ describe 'parent group transformation' do
+ it 'sets parent id' do
+ transformed_data = subject.transform(context, data)
+
+ expect(transformed_data['parent_id']).to eq(parent.id)
+ end
+
+ context 'when destination namespace is user namespace' do
+ let(:entity) do
+ instance_double(
+ BulkImports::Entity,
+ source_full_path: 'source/full/path',
+ destination_name: group.name,
+ destination_namespace: user.namespace.full_path
+ )
+ end
+
+ it 'does not set parent id' do
+ transformed_data = subject.transform(context, data)
+
+ expect(transformed_data).not_to have_key('parent_id')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/transformers/subgroup_to_entity_transformer_spec.rb b/spec/lib/bulk_imports/groups/transformers/subgroup_to_entity_transformer_spec.rb
new file mode 100644
index 00000000000..2f97a5721e7
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/transformers/subgroup_to_entity_transformer_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Transformers::SubgroupToEntityTransformer do
+ describe "#transform" do
+ it "transforms subgroups data in entity params" do
+ parent = create(:group)
+ parent_entity = instance_double(BulkImports::Entity, group: parent, id: 1)
+ context = instance_double(BulkImports::Pipeline::Context, entity: parent_entity)
+ subgroup_data = {
+ "name" => "subgroup",
+ "full_path" => "parent/subgroup"
+ }
+
+ expect(subject.transform(context, subgroup_data)).to eq(
+ source_type: :group_entity,
+ source_full_path: "parent/subgroup",
+ destination_name: "subgroup",
+ destination_namespace: parent.full_path,
+ parent_id: 1
+ )
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/importers/group_importer_spec.rb b/spec/lib/bulk_imports/importers/group_importer_spec.rb
new file mode 100644
index 00000000000..95ac5925c97
--- /dev/null
+++ b/spec/lib/bulk_imports/importers/group_importer_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Importers::GroupImporter do
+ let(:user) { create(:user) }
+ let(:bulk_import) { create(:bulk_import) }
+ let(:bulk_import_entity) { create(:bulk_import_entity, bulk_import: bulk_import) }
+ let(:bulk_import_configuration) { create(:bulk_import_configuration, bulk_import: bulk_import) }
+ let(:context) do
+ BulkImports::Pipeline::Context.new(
+ current_user: user,
+ entity: bulk_import_entity,
+ configuration: bulk_import_configuration
+ )
+ end
+
+ subject { described_class.new(bulk_import_entity) }
+
+ before do
+ allow(BulkImports::Pipeline::Context).to receive(:new).and_return(context)
+ stub_http_requests
+ end
+
+ describe '#execute' do
+ it "starts the entity and run its pipelines" do
+ expect(bulk_import_entity).to receive(:start).and_call_original
+ expect_to_run_pipeline BulkImports::Groups::Pipelines::GroupPipeline, context: context
+ expect_to_run_pipeline BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline, context: context
+
+ subject.execute
+
+ expect(bulk_import_entity.reload).to be_finished
+ end
+ end
+
+ def expect_to_run_pipeline(klass, context:)
+ expect_next_instance_of(klass) do |pipeline|
+ expect(pipeline).to receive(:run).with(context)
+ end
+ end
+
+ def stub_http_requests
+ double_response = double(
+ code: 200,
+ success?: true,
+ parsed_response: {},
+ headers: {}
+ )
+
+ allow_next_instance_of(BulkImports::Clients::Http) do |client|
+ allow(client).to receive(:get).and_return(double_response)
+ allow(client).to receive(:post).and_return(double_response)
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/importers/groups_importer_spec.rb b/spec/lib/bulk_imports/importers/groups_importer_spec.rb
new file mode 100644
index 00000000000..4865034b0cd
--- /dev/null
+++ b/spec/lib/bulk_imports/importers/groups_importer_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Importers::GroupsImporter do
+ let_it_be(:bulk_import) { create(:bulk_import) }
+
+ subject { described_class.new(bulk_import.id) }
+
+ describe '#execute' do
+ context "when there is entities to be imported" do
+ let!(:bulk_import_entity) { create(:bulk_import_entity, bulk_import: bulk_import) }
+
+ it "starts the bulk_import and imports its entities" do
+ expect(BulkImports::Importers::GroupImporter).to receive(:new)
+ .with(bulk_import_entity).and_return(double(execute: true))
+ expect(BulkImportWorker).to receive(:perform_async).with(bulk_import.id)
+
+ subject.execute
+
+ expect(bulk_import.reload).to be_started
+ end
+ end
+
+ context "when there is no entities to be imported" do
+ it "starts the bulk_import and imports its entities" do
+ expect(BulkImports::Importers::GroupImporter).not_to receive(:new)
+ expect(BulkImportWorker).not_to receive(:perform_async)
+
+ subject.execute
+
+ expect(bulk_import.reload).to be_finished
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/pipeline/attributes_spec.rb b/spec/lib/bulk_imports/pipeline/attributes_spec.rb
new file mode 100644
index 00000000000..54c5dbd4cae
--- /dev/null
+++ b/spec/lib/bulk_imports/pipeline/attributes_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Pipeline::Attributes do
+ describe 'pipeline attributes' do
+ before do
+ stub_const('BulkImports::Extractor', Class.new)
+ stub_const('BulkImports::Transformer', Class.new)
+ stub_const('BulkImports::Loader', Class.new)
+
+ klass = Class.new do
+ include BulkImports::Pipeline::Attributes
+
+ extractor BulkImports::Extractor, { foo: :bar }
+ transformer BulkImports::Transformer, { foo: :bar }
+ loader BulkImports::Loader, { foo: :bar }
+ end
+
+ stub_const('BulkImports::MyPipeline', klass)
+ end
+
+ describe 'getters' do
+ it 'retrieves class attributes' do
+ expect(BulkImports::MyPipeline.extractors).to contain_exactly({ klass: BulkImports::Extractor, options: { foo: :bar } })
+ expect(BulkImports::MyPipeline.transformers).to contain_exactly({ klass: BulkImports::Transformer, options: { foo: :bar } })
+ expect(BulkImports::MyPipeline.loaders).to contain_exactly({ klass: BulkImports::Loader, options: { foo: :bar } })
+ end
+ end
+
+ describe 'setters' do
+ it 'sets class attributes' do
+ klass = Class.new
+ options = { test: :test }
+
+ BulkImports::MyPipeline.extractor(klass, options)
+ BulkImports::MyPipeline.transformer(klass, options)
+ BulkImports::MyPipeline.loader(klass, options)
+
+ expect(BulkImports::MyPipeline.extractors)
+ .to contain_exactly(
+ { klass: BulkImports::Extractor, options: { foo: :bar } },
+ { klass: klass, options: options })
+
+ expect(BulkImports::MyPipeline.transformers)
+ .to contain_exactly(
+ { klass: BulkImports::Transformer, options: { foo: :bar } },
+ { klass: klass, options: options })
+
+ expect(BulkImports::MyPipeline.loaders)
+ .to contain_exactly(
+ { klass: BulkImports::Loader, options: { foo: :bar } },
+ { klass: klass, options: options })
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/pipeline/context_spec.rb b/spec/lib/bulk_imports/pipeline/context_spec.rb
new file mode 100644
index 00000000000..e9af6313ca4
--- /dev/null
+++ b/spec/lib/bulk_imports/pipeline/context_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Pipeline::Context do
+ describe '#initialize' do
+ it 'initializes with permitted attributes' do
+ args = {
+ current_user: create(:user),
+ entity: create(:bulk_import_entity),
+ configuration: create(:bulk_import_configuration)
+ }
+
+ context = described_class.new(args)
+
+ args.each do |k, v|
+ expect(context.public_send(k)).to eq(v)
+ end
+ end
+
+ context 'when invalid argument is passed' do
+ it 'raises NoMethodError' do
+ expect { described_class.new(test: 'test').test }.to raise_exception(NoMethodError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/pipeline/runner_spec.rb b/spec/lib/bulk_imports/pipeline/runner_spec.rb
new file mode 100644
index 00000000000..8c882c799ec
--- /dev/null
+++ b/spec/lib/bulk_imports/pipeline/runner_spec.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Pipeline::Runner do
+ describe 'pipeline runner' do
+ before do
+ extractor = Class.new do
+ def initialize(options = {}); end
+
+ def extract(context); end
+ end
+
+ transformer = Class.new do
+ def initialize(options = {}); end
+
+ def transform(context, entry); end
+ end
+
+ loader = Class.new do
+ def initialize(options = {}); end
+
+ def load(context, entry); end
+ end
+
+ stub_const('BulkImports::Extractor', extractor)
+ stub_const('BulkImports::Transformer', transformer)
+ stub_const('BulkImports::Loader', loader)
+
+ pipeline = Class.new do
+ include BulkImports::Pipeline
+
+ extractor BulkImports::Extractor
+ transformer BulkImports::Transformer
+ loader BulkImports::Loader
+ end
+
+ stub_const('BulkImports::MyPipeline', pipeline)
+ end
+
+ it 'runs pipeline extractor, transformer, loader' do
+ context = instance_double(
+ BulkImports::Pipeline::Context,
+ entity: instance_double(BulkImports::Entity, id: 1, source_type: 'group')
+ )
+ entries = [{ foo: :bar }]
+
+ expect_next_instance_of(BulkImports::Extractor) do |extractor|
+ expect(extractor).to receive(:extract).with(context).and_return(entries)
+ end
+
+ expect_next_instance_of(BulkImports::Transformer) do |transformer|
+ expect(transformer).to receive(:transform).with(context, entries.first).and_return(entries.first)
+ end
+
+ expect_next_instance_of(BulkImports::Loader) do |loader|
+ expect(loader).to receive(:load).with(context, entries.first)
+ end
+
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger).to receive(:info)
+ .with(message: "Pipeline started", pipeline: 'BulkImports::MyPipeline', entity: 1, entity_type: 'group')
+ expect(logger).to receive(:info)
+ .with(entity: 1, entity_type: 'group', extractor: 'BulkImports::Extractor')
+ expect(logger).to receive(:info)
+ .with(entity: 1, entity_type: 'group', transformer: 'BulkImports::Transformer')
+ expect(logger).to receive(:info)
+ .with(entity: 1, entity_type: 'group', loader: 'BulkImports::Loader')
+ end
+
+ BulkImports::MyPipeline.new.run(context)
+ end
+ end
+end
diff --git a/spec/lib/container_registry/client_spec.rb b/spec/lib/container_registry/client_spec.rb
index 4daf7375a40..2c08fdc1e75 100644
--- a/spec/lib/container_registry/client_spec.rb
+++ b/spec/lib/container_registry/client_spec.rb
@@ -3,9 +3,12 @@
require 'spec_helper'
RSpec.describe ContainerRegistry::Client do
+ using RSpec::Parameterized::TableSyntax
+
let(:token) { '12345' }
let(:options) { { token: token } }
- let(:client) { described_class.new("http://container-registry", options) }
+ let(:registry_api_url) { 'http://container-registry' }
+ let(:client) { described_class.new(registry_api_url, options) }
let(:push_blob_headers) do
{
'Accept' => 'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json',
@@ -101,16 +104,6 @@ RSpec.describe ContainerRegistry::Client do
end
end
- def stub_upload(path, content, digest, status = 200)
- stub_request(:post, "http://container-registry/v2/#{path}/blobs/uploads/")
- .with(headers: headers_with_accept_types)
- .to_return(status: status, body: "", headers: { 'location' => 'http://container-registry/next_upload?id=someid' })
-
- stub_request(:put, "http://container-registry/next_upload?digest=#{digest}&id=someid")
- .with(body: content, headers: push_blob_headers)
- .to_return(status: status, body: "", headers: {})
- end
-
describe '#upload_blob' do
subject { client.upload_blob('path', 'content', 'sha256:123') }
@@ -221,28 +214,36 @@ RSpec.describe ContainerRegistry::Client do
describe '#supports_tag_delete?' do
subject { client.supports_tag_delete? }
- context 'when the server supports tag deletion' do
- before do
- stub_request(:options, "http://container-registry/v2/name/tags/reference/tag")
- .to_return(status: 200, body: "", headers: { 'Allow' => 'DELETE' })
- end
-
- it { is_expected.to be_truthy }
+ where(:registry_tags_support_enabled, :is_on_dot_com, :container_registry_features, :expect_registry_to_be_pinged, :expected_result) do
+ true | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | true
+ true | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | true | true
+ true | true | [] | true | true
+ true | false | [] | true | true
+ false | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | true
+ false | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | true | false
+ false | true | [] | true | false
+ false | false | [] | true | false
end
- context 'when the server does not support tag deletion' do
+ with_them do
before do
- stub_request(:options, "http://container-registry/v2/name/tags/reference/tag")
- .to_return(status: 404, body: "")
+ allow(::Gitlab).to receive(:com?).and_return(is_on_dot_com)
+ stub_registry_tags_support(registry_tags_support_enabled)
+ stub_application_setting(container_registry_features: container_registry_features)
end
- it { is_expected.to be_falsey }
- end
- end
+ it 'returns the expected result' do
+ if expect_registry_to_be_pinged
+ expect_next_instance_of(Faraday::Connection) do |connection|
+ expect(connection).to receive(:run_request).and_call_original
+ end
+ else
+ expect(Faraday::Connection).not_to receive(:new)
+ end
- def stub_registry_info(headers: {}, status: 200)
- stub_request(:get, 'http://container-registry/v2/')
- .to_return(status: status, body: "", headers: headers)
+ expect(subject).to be expected_result
+ end
+ end
end
describe '#registry_info' do
@@ -291,55 +292,87 @@ RSpec.describe ContainerRegistry::Client do
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)
+ where(:registry_api_url, :registry_enabled, :registry_tags_support_enabled, :is_on_dot_com, :container_registry_features, :expect_registry_to_be_pinged, :expected_result) do
+ 'http://sandbox.local' | true | true | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | true
+ 'http://sandbox.local' | true | true | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | true | true
+ 'http://sandbox.local' | true | false | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | true
+ 'http://sandbox.local' | true | false | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | true | false
+ 'http://sandbox.local' | false | true | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ 'http://sandbox.local' | false | true | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ 'http://sandbox.local' | false | false | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ 'http://sandbox.local' | false | false | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ 'http://sandbox.local' | true | true | true | [] | true | true
+ 'http://sandbox.local' | true | true | false | [] | true | true
+ 'http://sandbox.local' | true | false | true | [] | true | false
+ 'http://sandbox.local' | true | false | false | [] | true | false
+ 'http://sandbox.local' | false | true | true | [] | false | false
+ 'http://sandbox.local' | false | true | false | [] | false | false
+ 'http://sandbox.local' | false | false | true | [] | false | false
+ 'http://sandbox.local' | false | false | false | [] | false | false
+ '' | true | true | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | true | true | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | true | false | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | true | false | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | false | true | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | false | true | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | false | false | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | false | false | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | true | true | true | [] | false | false
+ '' | true | true | false | [] | false | false
+ '' | true | false | true | [] | false | false
+ '' | true | false | false | [] | false | false
+ '' | false | true | true | [] | false | false
+ '' | false | true | false | [] | false | false
+ '' | false | false | true | [] | false | false
+ '' | false | false | false | [] | false | false
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 }
+ with_them do
+ 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)
+ stub_application_setting(container_registry_features: container_registry_features)
end
- context 'when registry server does not support tag deletion' do
- let(:registry_tags_support_enabled) { false }
+ it 'returns the expected result' do
+ if expect_registry_to_be_pinged
+ expect_next_instance_of(Faraday::Connection) do |connection|
+ expect(connection).to receive(:run_request).and_call_original
+ end
+ else
+ expect(Faraday::Connection).not_to receive(:new)
+ end
- it { is_expected.to be false }
+ expect(subject).to be expected_result
end
end
+ end
+
+ def stub_upload(path, content, digest, status = 200)
+ stub_request(:post, "#{registry_api_url}/v2/#{path}/blobs/uploads/")
+ .with(headers: headers_with_accept_types)
+ .to_return(status: status, body: "", headers: { 'location' => "#{registry_api_url}/next_upload?id=someid" })
- context 'with the registry disabled' do
- let(:registry_enabled) { false }
+ stub_request(:put, "#{registry_api_url}/next_upload?digest=#{digest}&id=someid")
+ .with(body: content, headers: push_blob_headers)
+ .to_return(status: status, body: "", headers: {})
+ end
- it { is_expected.to be false }
- end
+ def stub_registry_info(headers: {}, status: 200)
+ stub_request(:get, "#{registry_api_url}/v2/")
+ .to_return(status: status, body: "", headers: headers)
+ 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
+ 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
diff --git a/spec/lib/csv_builders/stream_spec.rb b/spec/lib/csv_builders/stream_spec.rb
new file mode 100644
index 00000000000..204baf965d0
--- /dev/null
+++ b/spec/lib/csv_builders/stream_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe CsvBuilders::Stream do
+ let(:event_1) { double(title: 'Added salt', description: 'A teaspoon') }
+ let(:event_2) { double(title: 'Added sugar', description: 'Just a pinch') }
+ let(:fake_relation) { FakeRelation.new([event_1, event_2]) }
+
+ subject(:builder) { described_class.new(fake_relation, 'Title' => 'title', 'Description' => 'description') }
+
+ describe '#render' do
+ before do
+ stub_const('FakeRelation', Array)
+
+ FakeRelation.class_eval do
+ def find_each(&block)
+ each(&block)
+ end
+ end
+ end
+
+ it 'returns a lazy enumerator' do
+ expect(builder.render).to be_an(Enumerator::Lazy)
+ end
+
+ it 'returns all rows up to default max value' do
+ expect(builder.render.to_a).to eq([
+ "Title,Description\n",
+ "Added salt,A teaspoon\n",
+ "Added sugar,Just a pinch\n"
+ ])
+ end
+
+ it 'truncates to max rows' do
+ expect(builder.render(1).to_a).to eq([
+ "Title,Description\n",
+ "Added salt,A teaspoon\n"
+ ])
+ end
+ end
+end
diff --git a/spec/lib/expand_variables_spec.rb b/spec/lib/expand_variables_spec.rb
index 4a5b70ff248..a994b4b92a6 100644
--- a/spec/lib/expand_variables_spec.rb
+++ b/spec/lib/expand_variables_spec.rb
@@ -3,106 +3,132 @@
require 'spec_helper'
RSpec.describe ExpandVariables do
+ shared_examples 'common variable expansion' do |expander|
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "no expansion": {
+ value: 'key',
+ result: 'key',
+ variables: []
+ },
+ "simple expansion": {
+ value: 'key$variable',
+ result: 'keyvalue',
+ variables: [
+ { key: 'variable', value: 'value' }
+ ]
+ },
+ "simple with hash of variables": {
+ value: 'key$variable',
+ result: 'keyvalue',
+ variables: {
+ 'variable' => 'value'
+ }
+ },
+ "complex expansion": {
+ value: 'key${variable}',
+ result: 'keyvalue',
+ variables: [
+ { key: 'variable', value: 'value' }
+ ]
+ },
+ "simple expansions": {
+ value: 'key$variable$variable2',
+ result: 'keyvalueresult',
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' }
+ ]
+ },
+ "complex expansions": {
+ value: 'key${variable}${variable2}',
+ result: 'keyvalueresult',
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' }
+ ]
+ },
+ "out-of-order expansion": {
+ value: 'key$variable2$variable',
+ result: 'keyresultvalue',
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' }
+ ]
+ },
+ "out-of-order complex expansion": {
+ value: 'key${variable2}${variable}',
+ result: 'keyresultvalue',
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' }
+ ]
+ },
+ "review-apps expansion": {
+ value: 'review/$CI_COMMIT_REF_NAME',
+ result: 'review/feature/add-review-apps',
+ variables: [
+ { key: 'CI_COMMIT_REF_NAME', value: 'feature/add-review-apps' }
+ ]
+ },
+ "do not lazily access variables when no expansion": {
+ value: 'key',
+ result: 'key',
+ variables: -> { raise NotImplementedError }
+ },
+ "lazily access variables": {
+ value: 'key$variable',
+ result: 'keyvalue',
+ variables: -> { [{ key: 'variable', value: 'value' }] }
+ }
+ }
+ end
+
+ with_them do
+ subject { expander.call(value, variables) }
+
+ it { is_expected.to eq(result) }
+ end
+ end
+
describe '#expand' do
context 'table tests' do
- using RSpec::Parameterized::TableSyntax
-
- where do
- {
- "no expansion": {
- value: 'key',
- result: 'key',
- variables: []
- },
- "missing variable": {
- value: 'key$variable',
- result: 'key',
- variables: []
- },
- "simple expansion": {
- value: 'key$variable',
- result: 'keyvalue',
- variables: [
- { key: 'variable', value: 'value' }
- ]
- },
- "simple with hash of variables": {
- value: 'key$variable',
- result: 'keyvalue',
- variables: {
- 'variable' => 'value'
+ it_behaves_like 'common variable expansion', described_class.method(:expand)
+
+ context 'with missing variables' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "missing variable": {
+ value: 'key$variable',
+ result: 'key',
+ variables: []
+ },
+ "complex expansions with missing variable": {
+ value: 'key${variable}${variable2}',
+ result: 'keyvalue',
+ variables: [
+ { key: 'variable', value: 'value' }
+ ]
+ },
+ "complex expansions with missing variable for Windows": {
+ value: 'key%variable%%variable2%',
+ result: 'keyvalue',
+ variables: [
+ { key: 'variable', value: 'value' }
+ ]
}
- },
- "complex expansion": {
- value: 'key${variable}',
- result: 'keyvalue',
- variables: [
- { key: 'variable', value: 'value' }
- ]
- },
- "simple expansions": {
- value: 'key$variable$variable2',
- result: 'keyvalueresult',
- variables: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result' }
- ]
- },
- "complex expansions": {
- value: 'key${variable}${variable2}',
- result: 'keyvalueresult',
- variables: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result' }
- ]
- },
- "complex expansions with missing variable": {
- value: 'key${variable}${variable2}',
- result: 'keyvalue',
- variables: [
- { key: 'variable', value: 'value' }
- ]
- },
- "out-of-order expansion": {
- value: 'key$variable2$variable',
- result: 'keyresultvalue',
- variables: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result' }
- ]
- },
- "out-of-order complex expansion": {
- value: 'key${variable2}${variable}',
- result: 'keyresultvalue',
- variables: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result' }
- ]
- },
- "review-apps expansion": {
- value: 'review/$CI_COMMIT_REF_NAME',
- result: 'review/feature/add-review-apps',
- variables: [
- { key: 'CI_COMMIT_REF_NAME', value: 'feature/add-review-apps' }
- ]
- },
- "do not lazily access variables when no expansion": {
- value: 'key',
- result: 'key',
- variables: -> { raise NotImplementedError }
- },
- "lazily access variables": {
- value: 'key$variable',
- result: 'keyvalue',
- variables: -> { [{ key: 'variable', value: 'value' }] }
}
- }
- end
+ end
- with_them do
- subject { ExpandVariables.expand(value, variables) }
+ with_them do
+ subject { ExpandVariables.expand(value, variables) }
- it { is_expected.to eq(result) }
+ it { is_expected.to eq(result) }
+ end
end
end
@@ -132,4 +158,70 @@ RSpec.describe ExpandVariables do
end
end
end
+
+ describe '#expand_existing' do
+ context 'table tests' do
+ it_behaves_like 'common variable expansion', described_class.method(:expand_existing)
+
+ context 'with missing variables' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "missing variable": {
+ value: 'key$variable',
+ result: 'key$variable',
+ variables: []
+ },
+ "complex expansions with missing variable": {
+ value: 'key${variable}${variable2}',
+ result: 'keyvalue${variable2}',
+ variables: [
+ { key: 'variable', value: 'value' }
+ ]
+ },
+ "complex expansions with missing variable for Windows": {
+ value: 'key%variable%%variable2%',
+ result: 'keyvalue%variable2%',
+ variables: [
+ { key: 'variable', value: 'value' }
+ ]
+ }
+ }
+ end
+
+ with_them do
+ subject { ExpandVariables.expand_existing(value, variables) }
+
+ it { is_expected.to eq(result) }
+ end
+ end
+ end
+
+ context 'lazily inits variables' do
+ let(:variables) { -> { [{ key: 'variable', value: 'result' }] } }
+
+ subject { described_class.expand_existing(value, variables) }
+
+ context 'when expanding variable' do
+ let(:value) { 'key$variable$variable2' }
+
+ it 'calls block at most once' do
+ expect(variables).to receive(:call).once.and_call_original
+
+ is_expected.to eq('keyresult$variable2')
+ end
+ end
+
+ context 'when no expansion is needed' do
+ let(:value) { 'key' }
+
+ it 'does not call block' do
+ expect(variables).not_to receive(:call)
+
+ is_expected.to eq('key')
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb
index dbb3aa8797e..b69cbbf0ec0 100644
--- a/spec/lib/extracts_path_spec.rb
+++ b/spec/lib/extracts_path_spec.rb
@@ -112,6 +112,19 @@ RSpec.describe ExtractsPath do
end
end
end
+
+ context 'ref and path are nil' do
+ let(:params) { { path: nil, ref: nil } }
+
+ it 'does not set commit' do
+ expect(container.repository).not_to receive(:commit).with('')
+ expect(self).to receive(:render_404)
+
+ assign_ref_vars
+
+ expect(@commit).to be_nil
+ end
+ end
end
it_behaves_like 'extracts refs'
diff --git a/spec/lib/extracts_ref_spec.rb b/spec/lib/extracts_ref_spec.rb
index ca2f1fd7dc1..5433a512981 100644
--- a/spec/lib/extracts_ref_spec.rb
+++ b/spec/lib/extracts_ref_spec.rb
@@ -18,6 +18,21 @@ RSpec.describe ExtractsRef do
allow_any_instance_of(described_class).to receive(:repository_container).and_return(container)
end
- it_behaves_like 'assigns ref vars'
+ describe '#assign_ref_vars' do
+ it_behaves_like 'assigns ref vars'
+
+ context 'ref and path are nil' do
+ let(:params) { { path: nil, ref: nil } }
+
+ it 'does not set commit' do
+ expect(container.repository).not_to receive(:commit).with('')
+
+ assign_ref_vars
+
+ expect(@commit).to be_nil
+ end
+ end
+ end
+
it_behaves_like 'extracts refs'
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start_spec.rb
index fe390289ef6..52e9f2d9846 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::CodeStageStart do
let(:subject) { described_class.new({}) }
let(:project) { create(:project) }
- it_behaves_like 'cycle analytics event'
+ it_behaves_like 'value stream analytics event'
it 'needs connection with an issue via merge_requests_closing_issues table' do
issue = create(:issue, project: project)
@@ -15,7 +15,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::CodeStageStart do
other_merge_request = create(:merge_request, source_project: project, source_branch: 'a', target_branch: 'master')
- records = subject.apply_query_customization(MergeRequest.all)
+ records = subject.apply_query_customization(MergeRequest.all).where('merge_requests_closing_issues.issue_id IS NOT NULL')
expect(records).to eq([merge_request])
expect(records).not_to include(other_merge_request)
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_created_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_created_spec.rb
index 5cc6b05407f..224a18653ed 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_created_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_created_spec.rb
@@ -3,5 +3,5 @@
require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::IssueCreated do
- it_behaves_like 'cycle analytics event'
+ it_behaves_like 'value stream analytics event'
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_first_mentioned_in_commit_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_first_mentioned_in_commit_spec.rb
index 715ad5a8e7d..bc0e388cf53 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_first_mentioned_in_commit_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_first_mentioned_in_commit_spec.rb
@@ -3,5 +3,5 @@
require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::IssueFirstMentionedInCommit do
- it_behaves_like 'cycle analytics event'
+ it_behaves_like 'value stream analytics event'
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_stage_end_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_stage_end_spec.rb
index 56241194f36..ddc5f015a8c 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_stage_end_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_stage_end_spec.rb
@@ -3,5 +3,5 @@
require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::IssueStageEnd do
- it_behaves_like 'cycle analytics event'
+ it_behaves_like 'value stream analytics event'
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_created_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_created_spec.rb
index f3202eab5bb..281cc31c9e0 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_created_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_created_spec.rb
@@ -3,5 +3,5 @@
require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::MergeRequestCreated do
- it_behaves_like 'cycle analytics event'
+ it_behaves_like 'value stream analytics event'
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_first_deployed_to_production_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_first_deployed_to_production_spec.rb
index 03b0ccfae43..e1dd2e56e2b 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_first_deployed_to_production_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_first_deployed_to_production_spec.rb
@@ -3,5 +3,5 @@
require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::MergeRequestFirstDeployedToProduction do
- it_behaves_like 'cycle analytics event'
+ it_behaves_like 'value stream analytics event'
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_finished_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_finished_spec.rb
index b0c003e6f2a..51324966f26 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_finished_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_finished_spec.rb
@@ -3,5 +3,5 @@
require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::MergeRequestLastBuildFinished do
- it_behaves_like 'cycle analytics event'
+ it_behaves_like 'value stream analytics event'
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started_spec.rb
index 8f9aaf6f463..10dcaf23b81 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started_spec.rb
@@ -3,5 +3,5 @@
require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::MergeRequestLastBuildStarted do
- it_behaves_like 'cycle analytics event'
+ it_behaves_like 'value stream analytics event'
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged_spec.rb
index f1d2ca9f36e..6e20eb73ed9 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged_spec.rb
@@ -3,5 +3,5 @@
require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::MergeRequestMerged do
- it_behaves_like 'cycle analytics event'
+ it_behaves_like 'value stream analytics event'
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start_spec.rb
index 3248af524bd..b8c68003127 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::PlanStageStart do
let(:subject) { described_class.new({}) }
let(:project) { create(:project) }
- it_behaves_like 'cycle analytics event'
+ it_behaves_like 'value stream analytics event'
it 'filters issues where first_associated_with_milestone_at or first_added_to_board_at is filled' do
issue1 = create(:issue, project: project)
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
index d232e509e00..115c8145f59 100644
--- a/spec/lib/gitlab/analytics/instance_statistics/workers_argument_builder_spec.rb
+++ b/spec/lib/gitlab/analytics/instance_statistics/workers_argument_builder_spec.rb
@@ -42,5 +42,40 @@ RSpec.describe Gitlab::Analytics::InstanceStatistics::WorkersArgumentBuilder do
])
end
end
+
+ context 'when custom min and max queries are present' do
+ let(:min_id) { User.second.id }
+ let(:max_id) { User.maximum(:id) }
+ let(:users_measurement_identifier) { ::Analytics::InstanceStatistics::Measurement.identifiers.fetch(:users) }
+
+ before do
+ create_list(:user, 2)
+
+ min_max_queries = {
+ ::Analytics::InstanceStatistics::Measurement.identifiers[:users] => {
+ minimum_query: -> { min_id },
+ maximum_query: -> { max_id }
+ }
+ }
+
+ allow(::Analytics::InstanceStatistics::Measurement).to receive(:identifier_min_max_queries) { min_max_queries }
+ end
+
+ subject do
+ described_class.new(measurement_identifiers: [users_measurement_identifier], recorded_at: recorded_at)
+ .execute
+ end
+
+ it 'uses custom min/max for ids' do
+ expect(subject).to eq([
+ [
+ users_measurement_identifier,
+ min_id,
+ max_id,
+ recorded_at
+ ]
+ ])
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/auth/auth_finders_spec.rb b/spec/lib/gitlab/auth/auth_finders_spec.rb
index 2ebde145bfd..3c19ef0bd1b 100644
--- a/spec/lib/gitlab/auth/auth_finders_spec.rb
+++ b/spec/lib/gitlab/auth/auth_finders_spec.rb
@@ -607,6 +607,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
set_basic_auth_header(username, build.token)
is_expected.to eq user
+ expect(@current_authenticated_job).to eq build
end
it 'raises error with invalid token' do
diff --git a/spec/lib/gitlab/background_migration/backfill_design_internal_ids_spec.rb b/spec/lib/gitlab/background_migration/backfill_design_internal_ids_spec.rb
new file mode 100644
index 00000000000..4bf59a02a31
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_design_internal_ids_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillDesignInternalIds, :migration, schema: 20201030203854 do
+ subject { described_class.new(designs) }
+
+ let_it_be(:namespaces) { table(:namespaces) }
+ let_it_be(:projects) { table(:projects) }
+ let_it_be(:designs) { table(:design_management_designs) }
+
+ let(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
+ let(:project) { projects.create!(namespace_id: namespace.id) }
+ let(:project_2) { projects.create!(namespace_id: namespace.id) }
+
+ def create_design!(proj = project)
+ designs.create!(project_id: proj.id, filename: generate(:filename))
+ end
+
+ def migrate!
+ relation = designs.where(project_id: [project.id, project_2.id]).select(:project_id).distinct
+
+ subject.perform(relation)
+ end
+
+ it 'backfills the iid for designs' do
+ 3.times { create_design! }
+
+ expect do
+ migrate!
+ end.to change { designs.pluck(:iid) }.from(contain_exactly(nil, nil, nil)).to(contain_exactly(1, 2, 3))
+ end
+
+ it 'scopes IIDs and handles range and starting-point correctly' do
+ create_design!.update!(iid: 10)
+ create_design!.update!(iid: 12)
+ create_design!(project_2).update!(iid: 7)
+ project_3 = projects.create!(namespace_id: namespace.id)
+
+ 2.times { create_design! }
+ 2.times { create_design!(project_2) }
+ 2.times { create_design!(project_3) }
+
+ migrate!
+
+ expect(designs.where(project_id: project.id).pluck(:iid)).to contain_exactly(10, 12, 13, 14)
+ expect(designs.where(project_id: project_2.id).pluck(:iid)).to contain_exactly(7, 8, 9)
+ expect(designs.where(project_id: project_3.id).pluck(:iid)).to contain_exactly(nil, nil)
+ end
+
+ it 'updates the internal ID records' do
+ design = create_design!
+ 2.times { create_design! }
+ design.update!(iid: 10)
+ scope = { project_id: project.id }
+ usage = :design_management_designs
+ init = ->(_d, _s) { 0 }
+
+ ::InternalId.track_greatest(design, scope, usage, 10, init)
+
+ migrate!
+
+ next_iid = ::InternalId.generate_next(design, scope, usage, init)
+
+ expect(designs.pluck(:iid)).to contain_exactly(10, 11, 12)
+ expect(design.reload.iid).to eq(10)
+ expect(next_iid).to eq(13)
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2_spec.rb b/spec/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2_spec.rb
new file mode 100644
index 00000000000..7fe82420364
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillJiraTrackerDeploymentType2, :migration, schema: 20201028182809 do
+ let_it_be(:jira_service_temp) { described_class::JiraServiceTemp }
+ let_it_be(:jira_tracker_data_temp) { described_class::JiraTrackerDataTemp }
+ let_it_be(:atlassian_host) { 'https://api.atlassian.net' }
+ let_it_be(:mixedcase_host) { 'https://api.AtlassiaN.nEt' }
+ let_it_be(:server_host) { 'https://my.server.net' }
+
+ let(:jira_service) { jira_service_temp.create!(type: 'JiraService', active: true, category: 'issue_tracker') }
+
+ subject { described_class.new }
+
+ def create_tracker_data(options = {})
+ jira_tracker_data_temp.create!({ service_id: jira_service.id }.merge(options))
+ end
+
+ describe '#perform' do
+ context do
+ it 'ignores if deployment already set' do
+ tracker_data = create_tracker_data(url: atlassian_host, deployment_type: 'server')
+
+ expect(subject).not_to receive(:collect_deployment_type)
+
+ subject.perform(tracker_data.id, tracker_data.id)
+
+ expect(tracker_data.reload.deployment_type).to eq 'server'
+ end
+
+ it 'ignores if no url is set' do
+ tracker_data = create_tracker_data(deployment_type: 'unknown')
+
+ expect(subject).to receive(:collect_deployment_type)
+
+ subject.perform(tracker_data.id, tracker_data.id)
+
+ expect(tracker_data.reload.deployment_type).to eq 'unknown'
+ end
+ end
+
+ context 'when tracker is valid' do
+ let!(:tracker_1) { create_tracker_data(url: atlassian_host, deployment_type: 0) }
+ let!(:tracker_2) { create_tracker_data(url: mixedcase_host, deployment_type: 0) }
+ let!(:tracker_3) { create_tracker_data(url: server_host, deployment_type: 0) }
+ let!(:tracker_4) { create_tracker_data(api_url: server_host, deployment_type: 0) }
+ let!(:tracker_nextbatch) { create_tracker_data(api_url: atlassian_host, deployment_type: 0) }
+
+ it 'sets the proper deployment_type', :aggregate_failures do
+ subject.perform(tracker_1.id, tracker_4.id)
+
+ expect(tracker_1.reload.deployment_cloud?).to be_truthy
+ expect(tracker_2.reload.deployment_cloud?).to be_truthy
+ expect(tracker_3.reload.deployment_server?).to be_truthy
+ expect(tracker_4.reload.deployment_server?).to be_truthy
+ expect(tracker_nextbatch.reload.deployment_unknown?).to be_truthy
+ end
+ end
+
+ it_behaves_like 'marks background migration job records' do
+ let(:arguments) { [1, 4] }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb b/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb
new file mode 100644
index 00000000000..c2daa35703d
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillMergeRequestCleanupSchedules, schema: 20201103110018 do
+ let(:merge_requests) { table(:merge_requests) }
+ let(:cleanup_schedules) { table(:merge_request_cleanup_schedules) }
+ let(:metrics) { table(:merge_request_metrics) }
+
+ let(:namespace) { table(:namespaces).create!(name: 'name', path: 'path') }
+ let(:project) { table(:projects).create!(namespace_id: namespace.id) }
+
+ subject { described_class.new }
+
+ describe '#perform' do
+ let!(:open_mr) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master') }
+
+ let!(:closed_mr_1) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) }
+ let!(:closed_mr_2) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) }
+ let!(:closed_mr_1_metrics) { metrics.create!(merge_request_id: closed_mr_1.id, target_project_id: project.id, latest_closed_at: Time.current, created_at: Time.current, updated_at: Time.current) }
+ let!(:closed_mr_2_metrics) { metrics.create!(merge_request_id: closed_mr_2.id, target_project_id: project.id, latest_closed_at: Time.current, created_at: Time.current, updated_at: Time.current) }
+ let!(:closed_mr_2_cleanup_schedule) { cleanup_schedules.create!(merge_request_id: closed_mr_2.id, scheduled_at: Time.current) }
+
+ let!(:merged_mr_1) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 3) }
+ let!(:merged_mr_2) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 3, updated_at: Time.current) }
+ let!(:merged_mr_1_metrics) { metrics.create!(merge_request_id: merged_mr_1.id, target_project_id: project.id, merged_at: Time.current, created_at: Time.current, updated_at: Time.current) }
+
+ let!(:closed_mr_3) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) }
+ let!(:closed_mr_3_metrics) { metrics.create!(merge_request_id: closed_mr_3.id, target_project_id: project.id, latest_closed_at: Time.current, created_at: Time.current, updated_at: Time.current) }
+
+ it 'creates records for all closed and merged merge requests in range' do
+ expect(Gitlab::BackgroundMigration::Logger).to receive(:info).with(
+ message: 'Backfilled merge_request_cleanup_schedules records',
+ count: 3
+ )
+
+ subject.perform(open_mr.id, merged_mr_2.id)
+
+ aggregate_failures do
+ expect(cleanup_schedules.all.pluck(:merge_request_id))
+ .to contain_exactly(closed_mr_1.id, closed_mr_2.id, merged_mr_1.id, merged_mr_2.id)
+ expect(cleanup_schedules.find_by(merge_request_id: closed_mr_1.id).scheduled_at.to_s)
+ .to eq((closed_mr_1_metrics.latest_closed_at + 14.days).to_s)
+ expect(cleanup_schedules.find_by(merge_request_id: closed_mr_2.id).scheduled_at.to_s)
+ .to eq(closed_mr_2_cleanup_schedule.scheduled_at.to_s)
+ expect(cleanup_schedules.find_by(merge_request_id: merged_mr_1.id).scheduled_at.to_s)
+ .to eq((merged_mr_1_metrics.merged_at + 14.days).to_s)
+ expect(cleanup_schedules.find_by(merge_request_id: merged_mr_2.id).scheduled_at.to_s)
+ .to eq((merged_mr_2.updated_at + 14.days).to_s)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb b/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb
index 1637589d272..934ab7e37f8 100644
--- a/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb
+++ b/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
# rubocop: disable RSpec/FactoriesInMigrationSpecs
-RSpec.describe Gitlab::BackgroundMigration::LegacyUploadMover do
+RSpec.describe Gitlab::BackgroundMigration::LegacyUploadMover, :aggregate_failures do
let(:test_dir) { FileUploader.options['storage_path'] }
let(:filename) { 'image.png' }
@@ -67,27 +67,35 @@ RSpec.describe Gitlab::BackgroundMigration::LegacyUploadMover do
end
end
- shared_examples 'migrates the file correctly' do
- before do
+ shared_examples 'migrates the file correctly' do |remote|
+ it 'creates a new upload record correctly, updates the legacy upload note so that it references the file in the markdown, removes the attachment from the note model, removes the file, moves legacy uploads to the correct location, removes the upload record' do
+ expect(File.exist?(legacy_upload.absolute_path)).to be_truthy unless remote
+
described_class.new(legacy_upload).execute
- end
- it 'creates a new uplaod record correctly' do
expect(new_upload.secret).not_to be_nil
- expect(new_upload.path).to end_with("#{new_upload.secret}/image.png")
+ expect(new_upload.path).to end_with("#{new_upload.secret}/#{filename}")
expect(new_upload.model_id).to eq(project.id)
expect(new_upload.model_type).to eq('Project')
expect(new_upload.uploader).to eq('FileUploader')
- end
- it 'updates the legacy upload note so that it references the file in the markdown' do
- expected_path = File.join('/uploads', new_upload.secret, 'image.png')
+ expected_path = File.join('/uploads', new_upload.secret, filename)
expected_markdown = "some note \n ![image](#{expected_path})"
+
expect(note.reload.note).to eq(expected_markdown)
- end
+ expect(note.attachment.file).to be_nil
+
+ if remote
+ expect(bucket.files.get(remote_file[:key])).to be_nil
+ connection = ::Fog::Storage.new(FileUploader.object_store_credentials)
+ expect(connection.get_object('uploads', new_upload.path)[:status]).to eq(200)
+ else
+ expect(File.exist?(legacy_upload.absolute_path)).to be_falsey
+ expected_path = File.join(test_dir, 'uploads', project.disk_path, new_upload.secret, filename)
+ expect(File.exist?(expected_path)).to be_truthy
+ end
- it 'removes the attachment from the note model' do
- expect(note.reload.attachment.file).to be_nil
+ expect { legacy_upload.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
end
@@ -120,23 +128,6 @@ RSpec.describe Gitlab::BackgroundMigration::LegacyUploadMover do
end
context 'when the upload is in local storage' do
- shared_examples 'legacy local file' do
- it 'removes the file correctly' do
- expect(File.exist?(legacy_upload.absolute_path)).to be_truthy
-
- described_class.new(legacy_upload).execute
-
- expect(File.exist?(legacy_upload.absolute_path)).to be_falsey
- end
-
- it 'moves legacy uploads to the correct location' do
- described_class.new(legacy_upload).execute
-
- expected_path = File.join(test_dir, 'uploads', project.disk_path, new_upload.secret, filename)
- expect(File.exist?(expected_path)).to be_truthy
- end
- end
-
context 'when the upload file does not exist on the filesystem' do
let(:legacy_upload) { create_upload(note, filename, false) }
@@ -201,15 +192,11 @@ RSpec.describe Gitlab::BackgroundMigration::LegacyUploadMover do
path: "uploads/-/system/note/attachment/#{note.id}/#{filename}", model: note, mount_point: nil)
end
- it_behaves_like 'migrates the file correctly'
- it_behaves_like 'legacy local file'
- it_behaves_like 'legacy upload deletion'
+ it_behaves_like 'migrates the file correctly', false
end
context 'when the file can be handled correctly' do
- it_behaves_like 'migrates the file correctly'
- it_behaves_like 'legacy local file'
- it_behaves_like 'legacy upload deletion'
+ it_behaves_like 'migrates the file correctly', false
end
end
@@ -217,17 +204,13 @@ RSpec.describe Gitlab::BackgroundMigration::LegacyUploadMover do
context 'when the file belongs to a legacy project' do
let(:project) { legacy_project }
- it_behaves_like 'migrates the file correctly'
- it_behaves_like 'legacy local file'
- it_behaves_like 'legacy upload deletion'
+ it_behaves_like 'migrates the file correctly', false
end
context 'when the file belongs to a hashed project' do
let(:project) { hashed_project }
- it_behaves_like 'migrates the file correctly'
- it_behaves_like 'legacy local file'
- it_behaves_like 'legacy upload deletion'
+ it_behaves_like 'migrates the file correctly', false
end
end
@@ -244,17 +227,13 @@ RSpec.describe Gitlab::BackgroundMigration::LegacyUploadMover do
context 'when the file belongs to a legacy project' do
let(:project) { legacy_project }
- it_behaves_like 'migrates the file correctly'
- it_behaves_like 'legacy local file'
- it_behaves_like 'legacy upload deletion'
+ it_behaves_like 'migrates the file correctly', false
end
context 'when the file belongs to a hashed project' do
let(:project) { hashed_project }
- it_behaves_like 'migrates the file correctly'
- it_behaves_like 'legacy local file'
- it_behaves_like 'legacy upload deletion'
+ it_behaves_like 'migrates the file correctly', false
end
end
end
@@ -272,23 +251,6 @@ RSpec.describe Gitlab::BackgroundMigration::LegacyUploadMover do
stub_uploads_object_storage(FileUploader)
end
- shared_examples 'legacy remote file' do
- it 'removes the file correctly' do
- # expect(bucket.files.get(remote_file[:key])).to be_nil
-
- described_class.new(legacy_upload).execute
-
- expect(bucket.files.get(remote_file[:key])).to be_nil
- end
-
- it 'moves legacy uploads to the correct remote location' do
- described_class.new(legacy_upload).execute
-
- connection = ::Fog::Storage.new(FileUploader.object_store_credentials)
- expect(connection.get_object('uploads', new_upload.path)[:status]).to eq(200)
- end
- end
-
context 'when the upload file does not exist on the filesystem' do
it_behaves_like 'legacy upload deletion'
end
@@ -300,9 +262,7 @@ RSpec.describe Gitlab::BackgroundMigration::LegacyUploadMover do
let(:project) { legacy_project }
- it_behaves_like 'migrates the file correctly'
- it_behaves_like 'legacy remote file'
- it_behaves_like 'legacy upload deletion'
+ it_behaves_like 'migrates the file correctly', true
end
context 'when the file belongs to a hashed project' do
@@ -312,9 +272,7 @@ RSpec.describe Gitlab::BackgroundMigration::LegacyUploadMover do
let(:project) { hashed_project }
- it_behaves_like 'migrates the file correctly'
- it_behaves_like 'legacy remote file'
- it_behaves_like 'legacy upload deletion'
+ it_behaves_like 'migrates the file correctly', true
end
end
end
diff --git a/spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb b/spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb
new file mode 100644
index 00000000000..c6385340ca3
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::PopulateHasVulnerabilities, schema: 20201103192526 do
+ let(:users) { table(:users) }
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:project_settings) { table(:project_settings) }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+
+ let(:user) { users.create!(name: 'test', email: 'test@example.com', projects_limit: 5) }
+ let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:vulnerability_base_params) { { title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, author_id: user.id } }
+
+ let!(:project_1) { projects.create!(namespace_id: namespace.id, name: 'foo_1') }
+ let!(:project_2) { projects.create!(namespace_id: namespace.id, name: 'foo_2') }
+ let!(:project_3) { projects.create!(namespace_id: namespace.id, name: 'foo_3') }
+
+ before do
+ project_settings.create!(project_id: project_1.id)
+ vulnerabilities.create!(vulnerability_base_params.merge(project_id: project_1.id))
+ vulnerabilities.create!(vulnerability_base_params.merge(project_id: project_3.id))
+
+ allow(::Gitlab::BackgroundMigration::Logger).to receive_messages(info: true, error: true)
+ end
+
+ describe '#perform' do
+ it 'sets `has_vulnerabilities` attribute of project_settings' do
+ expect { subject.perform(project_1.id, project_3.id) }.to change { project_settings.count }.from(1).to(2)
+ .and change { project_settings.where(has_vulnerabilities: true).count }.from(0).to(2)
+ end
+
+ it 'writes info log message' do
+ subject.perform(project_1.id, project_3.id)
+
+ expect(::Gitlab::BackgroundMigration::Logger).to have_received(:info).with(migrator: described_class.name,
+ message: 'Projects has been processed to populate `has_vulnerabilities` information',
+ count: 2)
+ end
+
+ context 'when non-existing project_id is given' do
+ it 'populates only for the existing projects' do
+ expect { subject.perform(project_1.id, 0, project_3.id) }.to change { project_settings.count }.from(1).to(2)
+ .and change { project_settings.where(has_vulnerabilities: true).count }.from(0).to(2)
+ end
+ end
+
+ context 'when an error happens' do
+ before do
+ allow(described_class::ProjectSetting).to receive(:upsert_for).and_raise('foo')
+ end
+
+ it 'writes error log message' do
+ subject.perform(project_1.id, project_3.id)
+
+ expect(::Gitlab::BackgroundMigration::Logger).to have_received(:error).with(migrator: described_class.name,
+ message: 'foo',
+ project_ids: [project_1.id, project_3.id])
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb b/spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb
new file mode 100644
index 00000000000..44c5f3d1381
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation, schema: 20201028160832 do
+ let(:users) { table(:users) }
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:findings) { table(:vulnerability_occurrences) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let(:identifiers) { table(:vulnerability_identifiers) }
+ let(:feedback) { table(:vulnerability_feedback) }
+
+ let(:user) { users.create!(name: 'test', email: 'test@example.com', projects_limit: 5) }
+ let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
+ let(:vulnerability_1) { vulnerabilities.create!(title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id) }
+ let(:vulnerability_2) { vulnerabilities.create!(title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id) }
+ let(:scanner) { scanners.create!(project_id: project.id, external_id: 'foo', name: 'bar') }
+ let(:identifier) { identifiers.create!(project_id: project.id, fingerprint: 'foo', external_type: 'bar', external_id: 'zoo', name: 'identifier') }
+
+ before do
+ feedback.create!(feedback_type: 0,
+ category: 'sast',
+ project_fingerprint: '418291a26024a1445b23fe64de9380cdcdfd1fa8',
+ project_id: project.id,
+ author_id: user.id,
+ created_at: Time.current)
+
+ findings.create!(name: 'Finding',
+ report_type: 'sast',
+ project_fingerprint: Gitlab::Database::ShaAttribute.new.serialize('418291a26024a1445b23fe64de9380cdcdfd1fa8'),
+ location_fingerprint: 'bar',
+ severity: 1,
+ confidence: 1,
+ metadata_version: 1,
+ raw_metadata: '',
+ uuid: SecureRandom.uuid,
+ project_id: project.id,
+ vulnerability_id: vulnerability_1.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: identifier.id)
+
+ allow(::Gitlab::BackgroundMigration::Logger).to receive_messages(info: true, warn: true, error: true)
+ end
+
+ describe '#perform' do
+ it 'updates the missing dismissal information of the vulnerability' do
+ expect { subject.perform(vulnerability_1.id, vulnerability_2.id) }.to change { vulnerability_1.reload.dismissed_at }.from(nil)
+ .and change { vulnerability_1.reload.dismissed_by_id }.from(nil).to(user.id)
+ end
+
+ it 'writes log messages' do
+ subject.perform(vulnerability_1.id, vulnerability_2.id)
+
+ expect(::Gitlab::BackgroundMigration::Logger).to have_received(:info).with(migrator: described_class.name,
+ message: 'Dismissal information has been copied',
+ count: 2)
+ expect(::Gitlab::BackgroundMigration::Logger).to have_received(:warn).with(migrator: described_class.name,
+ message: 'Could not update vulnerability!',
+ vulnerability_id: vulnerability_2.id)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb b/spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb
index fa4f2d1fd88..561a602fab9 100644
--- a/spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb
+++ b/spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb
@@ -9,28 +9,34 @@ RSpec.describe Gitlab::BackgroundMigration::ReplaceBlockedByLinks, schema: 20201
let(:issue2) { table(:issues).create!(project_id: project.id, title: 'b') }
let(:issue3) { table(:issues).create!(project_id: project.id, title: 'c') }
let(:issue_links) { table(:issue_links) }
- let!(:blocks_link) { issue_links.create!(source_id: issue1.id, target_id: issue2.id, link_type: 1) }
- let!(:bidirectional_link) { issue_links.create!(source_id: issue2.id, target_id: issue1.id, link_type: 2) }
- let!(:blocked_link) { issue_links.create!(source_id: issue1.id, target_id: issue3.id, link_type: 2) }
+ let!(:blocked_link1) { issue_links.create!(source_id: issue2.id, target_id: issue1.id, link_type: 2) }
+ let!(:opposite_link1) { issue_links.create!(source_id: issue1.id, target_id: issue2.id, link_type: 1) }
+ let!(:blocked_link2) { issue_links.create!(source_id: issue1.id, target_id: issue3.id, link_type: 2) }
+ let!(:opposite_link2) { issue_links.create!(source_id: issue3.id, target_id: issue1.id, link_type: 0) }
+ let!(:nochange_link) { issue_links.create!(source_id: issue2.id, target_id: issue3.id, link_type: 1) }
subject { described_class.new.perform(issue_links.minimum(:id), issue_links.maximum(:id)) }
- it 'deletes issue links where opposite relation already exists' do
- expect { subject }.to change { issue_links.count }.by(-1)
+ it 'deletes any opposite relations' do
+ subject
+
+ expect(issue_links.ids).to match_array([nochange_link.id, blocked_link1.id, blocked_link2.id])
end
it 'ignores issue links other than blocked_by' do
subject
- expect(blocks_link.reload.link_type).to eq(1)
+ expect(nochange_link.reload.link_type).to eq(1)
end
it 'updates blocked_by issue links' do
subject
- link = blocked_link.reload
- expect(link.link_type).to eq(1)
- expect(link.source_id).to eq(issue3.id)
- expect(link.target_id).to eq(issue1.id)
+ expect(blocked_link1.reload.link_type).to eq(1)
+ expect(blocked_link1.source_id).to eq(issue1.id)
+ expect(blocked_link1.target_id).to eq(issue2.id)
+ expect(blocked_link2.reload.link_type).to eq(1)
+ expect(blocked_link2.source_id).to eq(issue3.id)
+ expect(blocked_link2.target_id).to eq(issue1.id)
end
end
diff --git a/spec/lib/gitlab/badge/coverage/report_spec.rb b/spec/lib/gitlab/badge/coverage/report_spec.rb
index 4a9508712a4..3b5ea3291e4 100644
--- a/spec/lib/gitlab/badge/coverage/report_spec.rb
+++ b/spec/lib/gitlab/badge/coverage/report_spec.rb
@@ -3,13 +3,24 @@
require 'spec_helper'
RSpec.describe Gitlab::Badge::Coverage::Report do
- let(:project) { create(:project, :repository) }
- let(:job_name) { nil }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:success_pipeline) { create(:ci_pipeline, :success, project: project) }
+ let_it_be(:running_pipeline) { create(:ci_pipeline, :running, project: project) }
+ let_it_be(:failure_pipeline) { create(:ci_pipeline, :failed, project: project) }
+
+ let_it_be(:builds) do
+ [
+ create(:ci_build, :success, pipeline: success_pipeline, coverage: 40, created_at: 9.seconds.ago, name: 'coverage'),
+ create(:ci_build, :success, pipeline: success_pipeline, coverage: 60, created_at: 8.seconds.ago)
+ ]
+ end
let(:badge) do
described_class.new(project, 'master', opts: { job: job_name })
end
+ let(:job_name) { nil }
+
describe '#entity' do
it 'describes a coverage' do
expect(badge.entity).to eq 'coverage'
@@ -28,81 +39,61 @@ RSpec.describe Gitlab::Badge::Coverage::Report do
end
end
- shared_examples 'unknown coverage report' do
- context 'particular job specified' do
- let(:job_name) { '' }
-
- it 'returns nil' do
- expect(badge.status).to be_nil
+ describe '#status' do
+ context 'with no job specified' do
+ it 'returns the most recent successful pipeline coverage value' do
+ expect(badge.status).to eq(50.00)
end
- end
- context 'particular job not specified' do
- let(:job_name) { nil }
+ context 'and no successful pipelines' do
+ before do
+ allow(badge).to receive(:successful_pipeline).and_return(nil)
+ end
- it 'returns nil' do
- expect(badge.status).to be_nil
+ it 'returns nil' do
+ expect(badge.status).to eq(nil)
+ end
end
end
- end
- context 'when latest successful pipeline exists' do
- before do
- create_pipeline do |pipeline|
- create(:ci_build, :success, pipeline: pipeline, name: 'first', coverage: 40)
- create(:ci_build, :success, pipeline: pipeline, coverage: 60)
- end
+ context 'with a blank job name' do
+ let(:job_name) { ' ' }
- create_pipeline do |pipeline|
- create(:ci_build, :failed, pipeline: pipeline, coverage: 10)
+ it 'returns the latest successful pipeline coverage value' do
+ expect(badge.status).to eq(50.00)
end
end
- context 'when particular job specified' do
- let(:job_name) { 'first' }
+ context 'with an unmatching job name specified' do
+ let(:job_name) { 'incorrect name' }
- it 'returns coverage for the particular job' do
- expect(badge.status).to eq 40
+ it 'returns nil' do
+ expect(badge.status).to be_nil
end
end
- context 'when particular job not specified' do
- let(:job_name) { '' }
+ context 'with a matching job name specified' do
+ let(:job_name) { 'coverage' }
- it 'returns arithemetic mean for the pipeline' do
- expect(badge.status).to eq 50
+ it 'returns the pipeline coverage value' do
+ expect(badge.status).to eq(40.00)
end
- end
- end
-
- context 'when only failed pipeline exists' do
- before do
- create_pipeline do |pipeline|
- create(:ci_build, :failed, pipeline: pipeline, coverage: 10)
- end
- end
-
- it_behaves_like 'unknown coverage report'
- context 'particular job specified' do
- let(:job_name) { 'nonexistent' }
+ context 'with a more recent running pipeline' do
+ let!(:another_build) { create(:ci_build, :success, pipeline: running_pipeline, coverage: 20, created_at: 7.seconds.ago, name: 'coverage') }
- it 'retruns nil' do
- expect(badge.status).to be_nil
+ it 'returns the running pipeline coverage value' do
+ expect(badge.status).to eq(20.00)
+ end
end
- end
- end
- context 'pipeline does not exist' do
- it_behaves_like 'unknown coverage report'
- end
-
- def create_pipeline
- opts = { project: project, sha: project.commit.id, ref: 'master' }
+ context 'with a more recent failed pipeline' do
+ let!(:another_build) { create(:ci_build, :success, pipeline: failure_pipeline, coverage: 10, created_at: 6.seconds.ago, name: 'coverage') }
- create(:ci_pipeline, opts).tap do |pipeline|
- yield pipeline
- ::Ci::ProcessPipelineService.new(pipeline).execute
+ it 'returns the failed pipeline coverage value' do
+ expect(badge.status).to eq(10.00)
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
index 80ec5ec1fc7..c9ad78ec760 100644
--- a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
@@ -112,7 +112,13 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
allow(subject).to receive(:delete_temp_branches)
allow(subject).to receive(:restore_branches)
- allow(subject.client).to receive(:pull_requests).and_return([pull_request])
+ allow(subject.client).to receive(:pull_requests).and_return([pull_request], [])
+ end
+
+ # As we are using Caching with redis, it is best to clean the cache after each test run, else we need to wait for
+ # the expiration by the importer
+ after do
+ Gitlab::Cache::Import::Caching.expire(subject.already_imported_cache_key, 0)
end
it 'imports merge event' do
@@ -463,6 +469,47 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
subject.execute
end
+
+ describe 'import pull requests with caching' do
+ let(:pull_request_already_imported) do
+ instance_double(
+ BitbucketServer::Representation::PullRequest,
+ iid: 11)
+ end
+
+ let(:pull_request_to_be_imported) do
+ instance_double(
+ BitbucketServer::Representation::PullRequest,
+ iid: 12,
+ source_branch_sha: sample.commits.last,
+ source_branch_name: Gitlab::Git::BRANCH_REF_PREFIX + sample.source_branch,
+ target_branch_sha: sample.commits.first,
+ target_branch_name: Gitlab::Git::BRANCH_REF_PREFIX + sample.target_branch,
+ title: 'This is a title',
+ description: 'This is a test pull request',
+ state: 'merged',
+ author: 'Test Author',
+ author_email: pull_request_author.email,
+ author_username: pull_request_author.username,
+ created_at: Time.now,
+ updated_at: Time.now,
+ raw: {},
+ merged?: true)
+ end
+
+ before do
+ Gitlab::Cache::Import::Caching.set_add(subject.already_imported_cache_key, pull_request_already_imported.iid)
+ allow(subject.client).to receive(:pull_requests).and_return([pull_request_to_be_imported, pull_request_already_imported], [])
+ end
+
+ it 'only imports one Merge Request, as the other on is in the cache' do
+ expect(subject.client).to receive(:activities).and_return([merge_event])
+ expect { subject.execute }.to change { MergeRequest.count }.by(1)
+
+ expect(Gitlab::Cache::Import::Caching.set_includes?(subject.already_imported_cache_key, pull_request_already_imported.iid)).to eq(true)
+ expect(Gitlab::Cache::Import::Caching.set_includes?(subject.already_imported_cache_key, pull_request_to_be_imported.iid)).to eq(true)
+ end
+ end
end
describe 'inaccessible branches' do
@@ -488,7 +535,7 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
updated_at: Time.now,
merged?: true)
- expect(subject.client).to receive(:pull_requests).and_return([pull_request])
+ expect(subject.client).to receive(:pull_requests).and_return([pull_request], [])
expect(subject.client).to receive(:activities).and_return([])
expect(subject).to receive(:import_repository).twice
end
@@ -525,4 +572,36 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
expect { subject.execute }.to change { MergeRequest.count }.by(1)
end
end
+
+ context "lfs files" do
+ before do
+ allow(project).to receive(:lfs_enabled?).and_return(true)
+ allow(subject).to receive(:import_repository)
+ allow(subject).to receive(:import_pull_requests)
+ end
+
+ it "downloads lfs objects if lfs_enabled is enabled for project" do
+ expect_next_instance_of(Projects::LfsPointers::LfsImportService) do |lfs_import_service|
+ expect(lfs_import_service).to receive(:execute).and_return(status: :success)
+ end
+
+ subject.execute
+ end
+
+ it "adds the error message when the lfs download fails" do
+ allow_next_instance_of(Projects::LfsPointers::LfsImportService) do |lfs_import_service|
+ expect(lfs_import_service).to receive(:execute).and_return(status: :error, message: "LFS server not reachable")
+ end
+
+ subject.execute
+
+ expect(project.import_state.reload.last_error).to eq(Gitlab::Json.dump({
+ message: "The remote data could not be fully imported.",
+ errors: [{
+ type: "lfs_objects",
+ errors: "The Lfs import process failed. LFS server not reachable"
+ }]
+ }))
+ end
+ end
end
diff --git a/spec/lib/gitlab/bulk_import/client_spec.rb b/spec/lib/gitlab/bulk_import/client_spec.rb
deleted file mode 100644
index a6f8dd6d194..00000000000
--- a/spec/lib/gitlab/bulk_import/client_spec.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BulkImport::Client do
- include ImportSpecHelper
-
- let(:uri) { 'http://gitlab.example' }
- let(:token) { 'token' }
- let(:resource) { 'resource' }
-
- subject { described_class.new(uri: uri, token: token) }
-
- describe '#get' do
- let(:response_double) { double(code: 200, success?: true, parsed_response: {}) }
-
- shared_examples 'performs network request' do
- it 'performs network request' do
- expect(Gitlab::HTTP).to receive(:get).with(*expected_args).and_return(response_double)
-
- subject.get(resource)
- end
- end
-
- describe 'parsed response' do
- it 'returns parsed response' do
- response_double = double(code: 200, success?: true, parsed_response: [{ id: 1 }, { id: 2 }])
-
- allow(Gitlab::HTTP).to receive(:get).and_return(response_double)
-
- expect(subject.get(resource)).to eq(response_double.parsed_response)
- end
- end
-
- describe 'request query' do
- include_examples 'performs network request' do
- let(:expected_args) do
- [
- anything,
- hash_including(
- query: {
- page: described_class::DEFAULT_PAGE,
- per_page: described_class::DEFAULT_PER_PAGE
- }
- )
- ]
- end
- end
- end
-
- describe 'request headers' do
- include_examples 'performs network request' do
- let(:expected_args) do
- [
- anything,
- hash_including(
- headers: {
- 'Content-Type' => 'application/json',
- 'Authorization' => "Bearer #{token}"
- }
- )
- ]
- end
- end
- end
-
- describe 'request uri' do
- include_examples 'performs network request' do
- let(:expected_args) do
- ['http://gitlab.example:80/api/v4/resource', anything]
- end
- end
- end
-
- context 'error handling' do
- context 'when error occurred' do
- it 'raises ConnectionError' do
- allow(Gitlab::HTTP).to receive(:get).and_raise(Errno::ECONNREFUSED)
-
- expect { subject.get(resource) }.to raise_exception(described_class::ConnectionError)
- end
- end
-
- context 'when response is not success' do
- it 'raises ConnectionError' do
- response_double = double(code: 503, success?: false)
-
- allow(Gitlab::HTTP).to receive(:get).and_return(response_double)
-
- expect { subject.get(resource) }.to raise_exception(described_class::ConnectionError)
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/chat/output_spec.rb b/spec/lib/gitlab/chat/output_spec.rb
index 38e17c39fad..34f6bc0904c 100644
--- a/spec/lib/gitlab/chat/output_spec.rb
+++ b/spec/lib/gitlab/chat/output_spec.rb
@@ -8,62 +8,67 @@ RSpec.describe Gitlab::Chat::Output do
end
let(:output) { described_class.new(build) }
+ let(:trace) { Gitlab::Ci::Trace.new(build) }
+
+ before do
+ trace.set("\e[0KRunning with gitlab-runner 13.4.0~beta.108.g2ed41114 (2ed41114)
+\e[0;m\e[0K on GDK local runner g_XWCUS4
+\e[0;msection_start:1604068171:resolve_secrets\r\e[0K\e[0K\e[36;1mResolving secrets\e[0;m
+\e[0;msection_end:1604068171:resolve_secrets\r\e[0Ksection_start:1604068171:prepare_executor\r\e[0K\e[0K\e[36;1mPreparing the \"docker\" executor\e[0;m
+\e[0;m\e[0KUsing Docker executor with image ubuntu:20.04 ...
+\e[0;m\e[0KUsing locally found image version due to if-not-present pull policy
+\e[0;m\e[0KUsing docker image sha256:d70eaf7277eada08fca944de400e7e4dd97b1262c06ed2b1011500caa4decaf1 for ubuntu:20.04 with digest ubuntu@sha256:fff16eea1a8ae92867721d90c59a75652ea66d29c05294e6e2f898704bdb8cf1 ...
+\e[0;msection_end:1604068172:prepare_executor\r\e[0Ksection_start:1604068172:prepare_script\r\e[0K\e[0K\e[36;1mPreparing environment\e[0;m
+\e[0;mRunning on runner-gxwcus4-project-21-concurrent-0 via MacBook-Pro.local...
+section_end:1604068173:prepare_script\r\e[0Ksection_start:1604068173:get_sources\r\e[0K\e[0K\e[36;1mGetting source from Git repository\e[0;m
+\e[0;m\e[32;1mFetching changes with git depth set to 50...\e[0;m
+Initialized empty Git repository in /builds/267388-group-1/playground/.git/
+\e[32;1mCreated fresh repository.\e[0;m
+\e[32;1mChecking out 6c8eb7f4 as master...\e[0;m
+
+\e[32;1mSkipping Git submodules setup\e[0;m
+section_end:1604068175:get_sources\r\e[0Ksection_start:1604068175:step_script\r\e[0K\e[0K\e[36;1mExecuting \"step_script\" stage of the job script\e[0;m
+\e[0;m\e[32;1m$ echo \"success!\"\e[0;m
+success!
+section_end:1604068175:step_script\r\e[0Ksection_start:1604068175:chat_reply\r\033[0K
+Chat Reply
+section_end:1604068176:chat_reply\r\033[0K\e[32;1mJob succeeded
+\e[0;m")
+ end
describe '#to_s' do
- it 'returns the build output as a String' do
- trace = Gitlab::Ci::Trace.new(build)
-
- trace.set("echo hello\nhello")
-
- allow(build)
- .to receive(:trace)
- .and_return(trace)
-
- allow(output)
- .to receive(:read_offset_and_length)
- .and_return([0, 13])
-
- expect(output.to_s).to eq('he')
+ it 'returns the chat reply as a String' do
+ expect(output.to_s).to eq("Chat Reply")
end
- end
- describe '#read_offset_and_length' do
context 'without the chat_reply trace section' do
- it 'falls back to using the build_script trace section' do
- expect(output)
- .to receive(:find_build_trace_section)
- .with('chat_reply')
- .and_return(nil)
-
- expect(output)
- .to receive(:find_build_trace_section)
- .with('build_script')
- .and_return({ name: 'build_script', byte_start: 1, byte_end: 4 })
-
- expect(output.read_offset_and_length).to eq([1, 3])
+ before do
+ trace.set(trace.raw.gsub('chat_reply', 'not_found'))
end
- end
- context 'without the build_script trace section' do
- it 'raises MissingBuildSectionError' do
- expect { output.read_offset_and_length }
- .to raise_error(described_class::MissingBuildSectionError)
+ it 'falls back to using the step_script trace section' do
+ expect(output.to_s).to eq("\e[0;m\e[32;1m$ echo \"success!\"\e[0;m\nsuccess!")
end
- end
-
- context 'with the chat_reply trace section' do
- it 'returns the read offset and length as an Array' do
- trace = Gitlab::Ci::Trace.new(build)
-
- allow(build)
- .to receive(:trace)
- .and_return(trace)
-
- allow(trace)
- .to receive(:extract_sections)
- .and_return([{ name: 'chat_reply', byte_start: 1, byte_end: 4 }])
- expect(output.read_offset_and_length).to eq([1, 3])
+ context 'without the step_script trace section' do
+ before do
+ trace.set(trace.raw.gsub('step_script', 'build_script'))
+ end
+
+ it 'falls back to using the build_script trace section' do
+ expect(output.to_s).to eq("\e[0;m\e[32;1m$ echo \"success!\"\e[0;m\nsuccess!")
+ end
+
+ context 'without the build_script trace section' do
+ before do
+ trace.set(trace.raw.gsub('build_script', 'not_found'))
+ end
+
+ it 'raises MissingBuildSectionError' do
+ expect { output.to_s }
+ .to raise_error(described_class::MissingBuildSectionError)
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb b/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
index cf52f601006..d20ea6c9202 100644
--- a/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
@@ -13,5 +13,47 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
subject { described_class.new(globs).satisfied_by?(pipeline, nil) }
end
+
+ context 'when using variable expansion' do
+ let(:pipeline) { build(:ci_pipeline) }
+ let(:modified_paths) { ['helm/test.txt'] }
+ let(:globs) { ['$HELM_DIR/**/*'] }
+ let(:context) { double('context') }
+
+ subject { described_class.new(globs).satisfied_by?(pipeline, context) }
+
+ before do
+ allow(pipeline).to receive(:modified_paths).and_return(modified_paths)
+ end
+
+ context 'when context is nil' do
+ let(:context) {}
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when context has the specified variables' do
+ let(:variables) do
+ [{ key: "HELM_DIR", value: "helm", public: true }]
+ end
+
+ before do
+ allow(context).to receive(:variables).and_return(variables)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when variable expansion does not match' do
+ let(:globs) { ['path/with/$in/it/*'] }
+ let(:modified_paths) { ['path/with/$in/it/file.txt'] }
+
+ before do
+ allow(context).to receive(:variables).and_return([])
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/charts_spec.rb b/spec/lib/gitlab/ci/charts_spec.rb
index e00e5ed3920..cfc2019a89b 100644
--- a/spec/lib/gitlab/ci/charts_spec.rb
+++ b/spec/lib/gitlab/ci/charts_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Charts do
- context "yearchart" do
+ context 'yearchart' do
let(:project) { create(:project) }
let(:chart) { Gitlab::Ci::Charts::YearChart.new(project) }
@@ -16,9 +16,13 @@ RSpec.describe Gitlab::Ci::Charts do
it 'starts at the beginning of the current year' do
expect(chart.from).to eq(chart.to.years_ago(1).beginning_of_month.beginning_of_day)
end
+
+ it 'uses %B %Y as labels format' do
+ expect(chart.labels).to include(chart.from.strftime('%B %Y'))
+ end
end
- context "monthchart" do
+ context 'monthchart' do
let(:project) { create(:project) }
let(:chart) { Gitlab::Ci::Charts::MonthChart.new(project) }
@@ -31,9 +35,13 @@ RSpec.describe Gitlab::Ci::Charts do
it 'starts one month ago' do
expect(chart.from).to eq(1.month.ago.beginning_of_day)
end
+
+ it 'uses %d %B as labels format' do
+ expect(chart.labels).to include(chart.from.strftime('%d %B'))
+ end
end
- context "weekchart" do
+ context 'weekchart' do
let(:project) { create(:project) }
let(:chart) { Gitlab::Ci::Charts::WeekChart.new(project) }
@@ -46,9 +54,13 @@ RSpec.describe Gitlab::Ci::Charts do
it 'starts one week ago' do
expect(chart.from).to eq(1.week.ago.beginning_of_day)
end
+
+ it 'uses %d %B as labels format' do
+ expect(chart.labels).to include(chart.from.strftime('%d %B'))
+ end
end
- context "pipeline_times" do
+ context 'pipeline_times' do
let(:project) { create(:project) }
let(:chart) { Gitlab::Ci::Charts::PipelineTime.new(project) }
diff --git a/spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb b/spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb
index 3388ae0af2f..ff44a235ea5 100644
--- a/spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb
@@ -46,98 +46,53 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Product::Matrix do
end
end
- context 'with one_dimensional_matrix feature flag enabled' do
- before do
- stub_feature_flags(one_dimensional_matrix: true)
- matrix.compose!
+ context 'when entry config has only one variable with multiple values' do
+ let(:config) do
+ [
+ {
+ 'VAR_1' => %w[build test]
+ }
+ ]
end
- context 'when entry config has only one variable with multiple values' do
- let(:config) do
- [
- {
- 'VAR_1' => %w[build test]
- }
- ]
- end
-
- describe '#valid?' do
- it { is_expected.to be_valid }
- end
+ describe '#valid?' do
+ it { is_expected.to be_valid }
+ end
- describe '#errors' do
- it 'returns no errors' do
- expect(matrix.errors)
- .to be_empty
- end
+ describe '#errors' do
+ it 'returns no errors' do
+ expect(matrix.errors)
+ .to be_empty
end
+ end
- describe '#value' do
- before do
- matrix.compose!
- end
-
- it 'returns the value without raising an error' do
- expect(matrix.value).to eq([{ 'VAR_1' => %w[build test] }])
- end
+ describe '#value' do
+ before do
+ matrix.compose!
end
- context 'when entry config has only one variable with one value' do
- let(:config) do
- [
- {
- 'VAR_1' => %w[test]
- }
- ]
- end
-
- describe '#valid?' do
- it { is_expected.to be_valid }
- end
-
- describe '#errors' do
- it 'returns no errors' do
- expect(matrix.errors)
- .to be_empty
- end
- end
-
- describe '#value' do
- before do
- matrix.compose!
- end
-
- it 'returns the value without raising an error' do
- expect(matrix.value).to eq([{ 'VAR_1' => %w[test] }])
- end
- end
+ it 'returns the value without raising an error' do
+ expect(matrix.value).to eq([{ 'VAR_1' => %w[build test] }])
end
end
- end
- context 'with one_dimensional_matrix feature flag disabled' do
- before do
- stub_feature_flags(one_dimensional_matrix: false)
- matrix.compose!
- end
-
- context 'when entry config has only one variable with multiple values' do
+ context 'when entry config has only one variable with one value' do
let(:config) do
[
{
- 'VAR_1' => %w[build test]
+ 'VAR_1' => %w[test]
}
]
end
describe '#valid?' do
- it { is_expected.not_to be_valid }
+ it { is_expected.to be_valid }
end
describe '#errors' do
- it 'returns error about too many jobs' do
+ it 'returns no errors' do
expect(matrix.errors)
- .to include('variables config requires at least 2 items')
+ .to be_empty
end
end
@@ -147,38 +102,7 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Product::Matrix do
end
it 'returns the value without raising an error' do
- expect(matrix.value).to eq([{ 'VAR_1' => %w[build test] }])
- end
- end
-
- context 'when entry config has only one variable with one value' do
- let(:config) do
- [
- {
- 'VAR_1' => %w[test]
- }
- ]
- end
-
- describe '#valid?' do
- it { is_expected.not_to be_valid }
- end
-
- describe '#errors' do
- it 'returns no errors' do
- expect(matrix.errors)
- .to include('variables config requires at least 2 items')
- end
- end
-
- describe '#value' do
- before do
- matrix.compose!
- end
-
- it 'returns the value without raising an error' do
- expect(matrix.value).to eq([{ 'VAR_1' => %w[test] }])
- end
+ expect(matrix.value).to eq([{ 'VAR_1' => %w[test] }])
end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/product/variables_spec.rb b/spec/lib/gitlab/ci/config/entry/product/variables_spec.rb
index 407efb438b5..5e920ce34e0 100644
--- a/spec/lib/gitlab/ci/config/entry/product/variables_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/product/variables_spec.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
-# After Feature one_dimensional_matrix is removed, this can be changed back to fast_spec_helper
-require 'spec_helper'
+require 'fast_spec_helper'
require_dependency 'active_model'
RSpec.describe Gitlab::Ci::Config::Entry::Product::Variables do
@@ -46,70 +45,18 @@ RSpec.describe Gitlab::Ci::Config::Entry::Product::Variables do
end
end
- context 'with one_dimensional_matrix feature flag enabled' do
- context 'with only one variable' do
- before do
- stub_feature_flags(one_dimensional_matrix: true)
- end
- let(:config) { { VAR: 'test' } }
-
- describe '#valid?' do
- it 'is valid' do
- expect(entry).to be_valid
- end
- end
+ context 'with only one variable' do
+ let(:config) { { VAR: 'test' } }
- describe '#errors' do
- it 'does not append errors' do
- expect(entry.errors).to be_empty
- end
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
end
end
- end
-
- context 'with one_dimensional_matrix feature flag disabled' do
- context 'when entry value is not correct' do
- before do
- stub_feature_flags(one_dimensional_matrix: false)
- end
- shared_examples 'invalid variables' do |message|
- describe '#errors' do
- it 'saves errors' do
- expect(entry.errors).to include(message)
- end
- end
-
- describe '#valid?' do
- it 'is not valid' do
- expect(entry).not_to be_valid
- end
- end
- end
-
- context 'with array' do
- let(:config) { [:VAR, 'test'] }
- it_behaves_like 'invalid variables', /should be a hash of key value pairs/
- end
-
- context 'with empty array' do
- let(:config) { { VAR: 'test', VAR2: [] } }
-
- it_behaves_like 'invalid variables', /should be a hash of key value pairs/
- end
-
- context 'with nested array' do
- let(:config) { { VAR: 'test', VAR2: [1, [2]] } }
-
- it_behaves_like 'invalid variables', /should be a hash of key value pairs/
- end
-
- context 'with one_dimensional_matrix feature flag disabled' do
- context 'with only one variable' do
- let(:config) { { VAR: 'test' } }
-
- it_behaves_like 'invalid variables', /variables config requires at least 2 items/
- end
+ describe '#errors' do
+ it 'does not append errors' do
+ expect(entry.errors).to be_empty
end
end
end
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index bf14d8d6b34..7ad57827e30 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -100,6 +100,42 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
expect { subject }.to raise_error(described_class::AmbigiousSpecificationError)
end
end
+
+ context "when the key is a project's file" do
+ let(:values) do
+ { include: { project: project.full_path, file: local_file },
+ image: 'ruby:2.7' }
+ end
+
+ it 'returns File instances' do
+ expect(subject).to contain_exactly(
+ an_instance_of(Gitlab::Ci::Config::External::File::Project))
+ end
+ end
+
+ context "when the key is project's files" do
+ let(:values) do
+ { include: { project: project.full_path, file: [local_file, 'another_file_path.yml'] },
+ image: 'ruby:2.7' }
+ end
+
+ it 'returns two File instances' do
+ expect(subject).to contain_exactly(
+ an_instance_of(Gitlab::Ci::Config::External::File::Project),
+ an_instance_of(Gitlab::Ci::Config::External::File::Project))
+ end
+
+ context 'when FF ci_include_multiple_files_from_project is disabled' do
+ before do
+ stub_feature_flags(ci_include_multiple_files_from_project: false)
+ end
+
+ it 'returns a File instance' do
+ expect(subject).to contain_exactly(
+ an_instance_of(Gitlab::Ci::Config::External::File::Project))
+ end
+ end
+ end
end
context "when 'include' is defined as an array" do
@@ -161,6 +197,16 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
it 'raises an exception' do
expect { subject }.to raise_error(described_class::DuplicateIncludesError)
end
+
+ context 'when including multiple files from a project' do
+ let(:values) do
+ { include: { project: project.full_path, file: [local_file, local_file] } }
+ end
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(described_class::DuplicateIncludesError)
+ end
+ end
end
context "when too many 'includes' are defined" do
@@ -179,6 +225,16 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
it 'raises an exception' do
expect { subject }.to raise_error(described_class::TooManyIncludesError)
end
+
+ context 'when including multiple files from a project' do
+ let(:values) do
+ { include: { project: project.full_path, file: [local_file, 'another_file_path.yml'] } }
+ end
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(described_class::TooManyIncludesError)
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
index 9786e050399..150a2ec2929 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -302,5 +302,82 @@ RSpec.describe Gitlab::Ci::Config::External::Processor do
end
end
end
+
+ context 'when a valid project file is defined' do
+ let(:values) do
+ {
+ include: { project: another_project.full_path, file: '/templates/my-build.yml' },
+ image: 'ruby:2.7'
+ }
+ end
+
+ before do
+ another_project.add_developer(user)
+
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository).to receive(:blob_data_at).with(another_project.commit.id, '/templates/my-build.yml') do
+ <<~HEREDOC
+ my_build:
+ script: echo Hello World
+ HEREDOC
+ end
+ end
+ end
+
+ it 'appends the file to the values' do
+ output = processor.perform
+ expect(output.keys).to match_array([:image, :my_build])
+ end
+ end
+
+ context 'when valid project files are defined in a single include' do
+ let(:values) do
+ {
+ include: {
+ project: another_project.full_path,
+ file: ['/templates/my-build.yml', '/templates/my-test.yml']
+ },
+ image: 'ruby:2.7'
+ }
+ end
+
+ before do
+ another_project.add_developer(user)
+
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository).to receive(:blob_data_at).with(another_project.commit.id, '/templates/my-build.yml') do
+ <<~HEREDOC
+ my_build:
+ script: echo Hello World
+ HEREDOC
+ end
+
+ allow(repository).to receive(:blob_data_at).with(another_project.commit.id, '/templates/my-test.yml') do
+ <<~HEREDOC
+ my_test:
+ script: echo Hello World
+ HEREDOC
+ end
+ end
+ end
+
+ it 'appends the file to the values' do
+ output = processor.perform
+ expect(output.keys).to match_array([:image, :my_build, :my_test])
+ end
+
+ context 'when FF ci_include_multiple_files_from_project is disabled' do
+ before do
+ stub_feature_flags(ci_include_multiple_files_from_project: false)
+ end
+
+ it 'raises an error' do
+ expect { processor.perform }.to raise_error(
+ described_class::IncludeError,
+ 'Included file `["/templates/my-build.yml", "/templates/my-test.yml"]` needs to be a string'
+ )
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index 41a45fe4ab7..b5a0f0e3fd7 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -246,6 +246,14 @@ RSpec.describe Gitlab::Ci::Config do
let(:remote_location) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' }
let(:local_location) { 'spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml' }
+ let(:local_file_content) do
+ File.read(Rails.root.join(local_location))
+ end
+
+ let(:local_location_hash) do
+ YAML.safe_load(local_file_content).deep_symbolize_keys
+ end
+
let(:remote_file_content) do
<<~HEREDOC
variables:
@@ -256,8 +264,8 @@ RSpec.describe Gitlab::Ci::Config do
HEREDOC
end
- let(:local_file_content) do
- File.read(Rails.root.join(local_location))
+ let(:remote_file_hash) do
+ YAML.safe_load(remote_file_content).deep_symbolize_keys
end
let(:gitlab_ci_yml) do
@@ -283,22 +291,11 @@ RSpec.describe Gitlab::Ci::Config do
context "when gitlab_ci_yml has valid 'include' defined" do
it 'returns a composed hash' do
- before_script_values = [
- "apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs", "ruby -v",
- "which ruby",
- "bundle install --jobs $(nproc) \"${FLAGS[@]}\""
- ]
- variables = {
- POSTGRES_USER: "user",
- POSTGRES_PASSWORD: "testing-password",
- POSTGRES_ENABLED: "true",
- POSTGRES_DB: "$CI_ENVIRONMENT_SLUG"
- }
composed_hash = {
- before_script: before_script_values,
+ before_script: local_location_hash[:before_script],
image: "ruby:2.7",
rspec: { script: ["bundle exec rspec"] },
- variables: variables
+ variables: remote_file_hash[:variables]
}
expect(config.to_hash).to eq(composed_hash)
@@ -575,5 +572,56 @@ RSpec.describe Gitlab::Ci::Config do
)
end
end
+
+ context "when including multiple files from a project" do
+ let(:other_file_location) { 'my_builds.yml' }
+
+ let(:other_file_content) do
+ <<~HEREDOC
+ build:
+ stage: build
+ script: echo hello
+
+ rspec:
+ stage: test
+ script: bundle exec rspec
+ HEREDOC
+ end
+
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ - project: #{project.full_path}
+ file:
+ - #{local_location}
+ - #{other_file_location}
+
+ image: ruby:2.7
+ HEREDOC
+ end
+
+ before do
+ project.add_developer(user)
+
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository).to receive(:blob_data_at).with(an_instance_of(String), local_location)
+ .and_return(local_file_content)
+
+ allow(repository).to receive(:blob_data_at).with(an_instance_of(String), other_file_location)
+ .and_return(other_file_content)
+ end
+ end
+
+ it 'returns a composed hash' do
+ composed_hash = {
+ before_script: local_location_hash[:before_script],
+ image: "ruby:2.7",
+ build: { stage: "build", script: "echo hello" },
+ rspec: { stage: "test", script: "bundle exec rspec" }
+ }
+
+ expect(config.to_hash).to eq(composed_hash)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/jwt_spec.rb b/spec/lib/gitlab/ci/jwt_spec.rb
index 9b133efad9c..3130c0c0c41 100644
--- a/spec/lib/gitlab/ci/jwt_spec.rb
+++ b/spec/lib/gitlab/ci/jwt_spec.rb
@@ -93,32 +93,65 @@ RSpec.describe Gitlab::Ci::Jwt do
end
describe '.for_build' do
- let(:rsa_key) { OpenSSL::PKey::RSA.new(Rails.application.secrets.openid_connect_signing_key) }
+ shared_examples 'generating JWT for build' do
+ context 'when signing key is present' do
+ let(:rsa_key) { OpenSSL::PKey::RSA.generate(1024) }
+ let(:rsa_key_data) { rsa_key.to_s }
- subject(:jwt) { described_class.for_build(build) }
+ it 'generates JWT with key id' do
+ _payload, headers = JWT.decode(jwt, rsa_key.public_key, true, { algorithm: 'RS256' })
+
+ expect(headers['kid']).to eq(rsa_key.public_key.to_jwk['kid'])
+ end
+
+ it 'generates JWT for the given job with ttl equal to build timeout' do
+ expect(build).to receive(:metadata_timeout).and_return(3_600)
+
+ payload, _headers = JWT.decode(jwt, rsa_key.public_key, true, { algorithm: 'RS256' })
+ ttl = payload["exp"] - payload["iat"]
+
+ expect(ttl).to eq(3_600)
+ end
+
+ it 'generates JWT for the given job with default ttl if build timeout is not set' do
+ expect(build).to receive(:metadata_timeout).and_return(nil)
+
+ payload, _headers = JWT.decode(jwt, rsa_key.public_key, true, { algorithm: 'RS256' })
+ ttl = payload["exp"] - payload["iat"]
- it 'generates JWT with key id' do
- _payload, headers = JWT.decode(jwt, rsa_key.public_key, true, { algorithm: 'RS256' })
+ expect(ttl).to eq(5.minutes.to_i)
+ end
+ end
+
+ context 'when signing key is missing' do
+ let(:rsa_key_data) { nil }
- expect(headers['kid']).to eq(rsa_key.public_key.to_jwk['kid'])
+ it 'raises NoSigningKeyError' do
+ expect { jwt }.to raise_error described_class::NoSigningKeyError
+ end
+ end
end
- it 'generates JWT for the given job with ttl equal to build timeout' do
- expect(build).to receive(:metadata_timeout).and_return(3_600)
+ subject(:jwt) { described_class.for_build(build) }
+
+ context 'when ci_jwt_signing_key feature flag is disabled' do
+ before do
+ stub_feature_flags(ci_jwt_signing_key: false)
- payload, _headers = JWT.decode(jwt, rsa_key.public_key, true, { algorithm: 'RS256' })
- ttl = payload["exp"] - payload["iat"]
+ allow(Rails.application.secrets).to receive(:openid_connect_signing_key).and_return(rsa_key_data)
+ end
- expect(ttl).to eq(3_600)
+ it_behaves_like 'generating JWT for build'
end
- it 'generates JWT for the given job with default ttl if build timeout is not set' do
- expect(build).to receive(:metadata_timeout).and_return(nil)
+ context 'when ci_jwt_signing_key feature flag is enabled' do
+ before do
+ stub_feature_flags(ci_jwt_signing_key: true)
- payload, _headers = JWT.decode(jwt, rsa_key.public_key, true, { algorithm: 'RS256' })
- ttl = payload["exp"] - payload["iat"]
+ stub_application_setting(ci_jwt_signing_key: rsa_key_data)
+ end
- expect(ttl).to eq(5.minutes.to_i)
+ it_behaves_like 'generating JWT for build'
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb
new file mode 100644
index 00000000000..3eaecb11ae0
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::CancelPendingPipelines do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let(:prev_pipeline) { create(:ci_pipeline, project: project) }
+ let(:new_commit) { create(:commit, project: project) }
+ let(:pipeline) { create(:ci_pipeline, project: project, sha: new_commit.sha) }
+
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(project: project, current_user: user)
+ end
+
+ let(:step) { described_class.new(pipeline, command) }
+
+ before do
+ create(:ci_build, :interruptible, :running, pipeline: prev_pipeline)
+ create(:ci_build, :interruptible, :success, pipeline: prev_pipeline)
+ create(:ci_build, :created, pipeline: prev_pipeline)
+
+ create(:ci_build, :interruptible, pipeline: pipeline)
+ end
+
+ describe '#perform!' do
+ subject(:perform) { step.perform! }
+
+ before do
+ expect(build_statuses(prev_pipeline)).to contain_exactly('running', 'success', 'created')
+ expect(build_statuses(pipeline)).to contain_exactly('pending')
+ end
+
+ context 'when auto-cancel is enabled' do
+ before do
+ project.update!(auto_cancel_pending_pipelines: 'enabled')
+ end
+
+ it 'cancels only previous interruptible builds' do
+ perform
+
+ expect(build_statuses(prev_pipeline)).to contain_exactly('canceled', 'success', 'canceled')
+ expect(build_statuses(pipeline)).to contain_exactly('pending')
+ end
+
+ context 'when the previous pipeline has a child pipeline' do
+ let(:child_pipeline) { create(:ci_pipeline, child_of: prev_pipeline) }
+
+ context 'when the child pipeline has an interruptible job' do
+ before do
+ create(:ci_build, :interruptible, :running, pipeline: child_pipeline)
+ end
+
+ it 'cancels interruptible builds of child pipeline' do
+ expect(build_statuses(child_pipeline)).to contain_exactly('running')
+
+ perform
+
+ expect(build_statuses(child_pipeline)).to contain_exactly('canceled')
+ end
+
+ context 'when FF ci_auto_cancel_all_pipelines is disabled' do
+ before do
+ stub_feature_flags(ci_auto_cancel_all_pipelines: false)
+ end
+
+ it 'does not cancel interruptible builds of child pipeline' do
+ expect(build_statuses(child_pipeline)).to contain_exactly('running')
+
+ perform
+
+ expect(build_statuses(child_pipeline)).to contain_exactly('running')
+ end
+ end
+ end
+
+ context 'when the child pipeline has not an interruptible job' do
+ before do
+ create(:ci_build, :running, pipeline: child_pipeline)
+ end
+
+ it 'does not cancel the build of child pipeline' do
+ expect(build_statuses(child_pipeline)).to contain_exactly('running')
+
+ perform
+
+ expect(build_statuses(child_pipeline)).to contain_exactly('running')
+ end
+ end
+ end
+
+ context 'when the prev pipeline source is webide' do
+ let(:prev_pipeline) { create(:ci_pipeline, :webide, project: project) }
+
+ it 'does not cancel builds of the previous pipeline' do
+ perform
+
+ expect(build_statuses(prev_pipeline)).to contain_exactly('created', 'running', 'success')
+ expect(build_statuses(pipeline)).to contain_exactly('pending')
+ end
+ end
+ end
+
+ context 'when auto-cancel is disabled' do
+ before do
+ project.update!(auto_cancel_pending_pipelines: 'disabled')
+ end
+
+ it 'does not cancel any build' do
+ subject
+
+ expect(build_statuses(prev_pipeline)).to contain_exactly('running', 'success', 'created')
+ expect(build_statuses(pipeline)).to contain_exactly('pending')
+ end
+ end
+ end
+
+ private
+
+ def build_statuses(pipeline)
+ pipeline.builds.pluck(:status)
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
index 8c02121857a..5506b079d0f 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
@@ -22,6 +22,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Populate do
[
Gitlab::Ci::Pipeline::Chain::Config::Content.new(pipeline, command),
Gitlab::Ci::Pipeline::Chain::Config::Process.new(pipeline, command),
+ Gitlab::Ci::Pipeline::Chain::SeedBlock.new(pipeline, command),
Gitlab::Ci::Pipeline::Chain::Seed.new(pipeline, command)
]
end
@@ -180,23 +181,21 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Populate do
->(pipeline) { pipeline.variables.create!(key: 'VAR', value: '123') }
end
- it 'wastes pipeline iid' do
- expect { run_chain }.to raise_error(ActiveRecord::RecordNotSaved)
-
- last_iid = InternalId.ci_pipelines
- .where(project_id: project.id)
- .last.last_value
-
- expect(last_iid).to be > 0
+ it 'raises error' do
+ expect { run_chain }.to raise_error(ActiveRecord::RecordNotSaved,
+ 'You cannot call create unless the parent is saved')
end
end
end
context 'when pipeline gets persisted during the process' do
- let(:pipeline) { create(:ci_pipeline, project: project) }
+ before do
+ dependencies.each(&:perform!)
+ pipeline.save!
+ end
it 'raises error' do
- expect { run_chain }.to raise_error(described_class::PopulateError)
+ expect { step.perform! }.to raise_error(described_class::PopulateError)
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb
new file mode 100644
index 00000000000..85c8e20767f
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::SeedBlock do
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user, developer_projects: [project]) }
+ let(:seeds_block) { }
+
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(
+ project: project,
+ current_user: user,
+ origin_ref: 'master',
+ seeds_block: seeds_block)
+ end
+
+ let(:pipeline) { build(:ci_pipeline, project: project) }
+
+ describe '#perform!' do
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(config))
+ end
+
+ subject(:run_chain) do
+ [
+ Gitlab::Ci::Pipeline::Chain::Config::Content.new(pipeline, command),
+ Gitlab::Ci::Pipeline::Chain::Config::Process.new(pipeline, command)
+ ].map(&:perform!)
+
+ described_class.new(pipeline, command).perform!
+ end
+
+ let(:config) do
+ { rspec: { script: 'rake' } }
+ end
+
+ context 'when there is not seeds_block' do
+ it 'does nothing' do
+ expect { run_chain }.not_to raise_error
+ end
+ end
+
+ context 'when there is seeds_block' do
+ let(:seeds_block) do
+ ->(pipeline) { pipeline.variables.build(key: 'VAR', value: '123') }
+ end
+
+ it 'executes the block' do
+ run_chain
+
+ expect(pipeline.variables.size).to eq(1)
+ end
+
+ context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
+ before do
+ stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
+ end
+
+ it 'does not execute the block' do
+ run_chain
+
+ expect(pipeline.variables.size).to eq(0)
+ end
+ end
+ end
+
+ context 'when the seeds_block tries to save the pipelie' do
+ let(:seeds_block) do
+ ->(pipeline) { pipeline.save! }
+ end
+
+ it 'raises error' do
+ expect { run_chain }.to raise_error('Pipeline cannot be persisted by `seeds_block`')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
index f83cd49d780..d849c768a3c 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
@@ -5,22 +5,14 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
let(:project) { create(:project, :repository) }
let(:user) { create(:user, developer_projects: [project]) }
+ let(:seeds_block) { }
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
project: project,
current_user: user,
origin_ref: 'master',
- seeds_block: nil)
- end
-
- def run_chain(pipeline, command)
- [
- Gitlab::Ci::Pipeline::Chain::Config::Content.new(pipeline, command),
- Gitlab::Ci::Pipeline::Chain::Config::Process.new(pipeline, command)
- ].map(&:perform!)
-
- described_class.new(pipeline, command).perform!
+ seeds_block: seeds_block)
end
let(:pipeline) { build(:ci_pipeline, project: project) }
@@ -28,22 +20,36 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
describe '#perform!' do
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
- run_chain(pipeline, command)
end
let(:config) do
{ rspec: { script: 'rake' } }
end
+ subject(:run_chain) do
+ [
+ Gitlab::Ci::Pipeline::Chain::Config::Content.new(pipeline, command),
+ Gitlab::Ci::Pipeline::Chain::Config::Process.new(pipeline, command)
+ ].map(&:perform!)
+
+ described_class.new(pipeline, command).perform!
+ end
+
it 'allocates next IID' do
+ run_chain
+
expect(pipeline.iid).to be_present
end
it 'ensures ci_ref' do
+ run_chain
+
expect(pipeline.ci_ref).to be_present
end
it 'sets the seeds in the command object' do
+ run_chain
+
expect(command.stage_seeds).to all(be_a Gitlab::Ci::Pipeline::Seed::Base)
expect(command.stage_seeds.count).to eq 1
end
@@ -58,6 +64,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'correctly fabricates a stage seeds object' do
+ run_chain
+
seeds = command.stage_seeds
expect(seeds.size).to eq 2
expect(seeds.first.attributes[:name]).to eq 'test'
@@ -81,6 +89,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'returns stage seeds only assigned to master' do
+ run_chain
+
seeds = command.stage_seeds
expect(seeds.size).to eq 1
@@ -100,6 +110,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'returns stage seeds only assigned to schedules' do
+ run_chain
+
seeds = command.stage_seeds
expect(seeds.size).to eq 1
@@ -127,6 +139,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
let(:pipeline) { build(:ci_pipeline, project: project) }
it 'returns seeds for kubernetes dependent job' do
+ run_chain
+
seeds = command.stage_seeds
expect(seeds.size).to eq 2
@@ -138,6 +152,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
context 'when kubernetes is not active' do
it 'does not return seeds for kubernetes dependent job' do
+ run_chain
+
seeds = command.stage_seeds
expect(seeds.size).to eq 1
@@ -155,11 +171,39 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'returns stage seeds only when variables expression is truthy' do
+ run_chain
+
seeds = command.stage_seeds
expect(seeds.size).to eq 1
expect(seeds.dig(0, 0, :name)).to eq 'unit'
end
end
+
+ context 'when there is seeds_block' do
+ let(:seeds_block) do
+ ->(pipeline) { pipeline.variables.build(key: 'VAR', value: '123') }
+ end
+
+ context 'when FF ci_seed_block_run_before_workflow_rules is enabled' do
+ it 'does not execute the block' do
+ run_chain
+
+ expect(pipeline.variables.size).to eq(0)
+ end
+ end
+
+ context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
+ before do
+ stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
+ end
+
+ it 'executes the block' do
+ run_chain
+
+ expect(pipeline.variables.size).to eq(1)
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
index 0c8a0de2f34..e62bf042fba 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
@@ -16,20 +16,37 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Environment do
subject { seed.to_resource }
shared_examples_for 'returning a correct environment' do
+ let(:expected_auto_stop_in_seconds) do
+ if expected_auto_stop_in
+ ChronicDuration.parse(expected_auto_stop_in).seconds
+ end
+ end
+
it 'returns a persisted environment object' do
- expect { subject }.to change { Environment.count }.by(1)
+ freeze_time do
+ expect { subject }.to change { Environment.count }.by(1)
- expect(subject).to be_a(Environment)
- expect(subject).to be_persisted
- expect(subject.project).to eq(project)
- expect(subject.name).to eq(expected_environment_name)
+ expect(subject).to be_a(Environment)
+ expect(subject).to be_persisted
+ expect(subject.project).to eq(project)
+ expect(subject.name).to eq(expected_environment_name)
+ expect(subject.auto_stop_in).to eq(expected_auto_stop_in_seconds)
+ end
end
context 'when environment has already existed' do
- let!(:environment) { create(:environment, project: project, name: expected_environment_name) }
+ let!(:environment) do
+ create(:environment,
+ project: project,
+ name: expected_environment_name
+ ).tap do |env|
+ env.auto_stop_in = expected_auto_stop_in
+ end
+ end
it 'returns the existing environment object' do
expect { subject }.not_to change { Environment.count }
+ expect { subject }.not_to change { environment.auto_stop_at }
expect(subject).to be_persisted
expect(subject).to eq(environment)
@@ -37,9 +54,10 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Environment do
end
end
- context 'when job has environment attribute' do
+ context 'when job has environment name attribute' do
let(:environment_name) { 'production' }
let(:expected_environment_name) { 'production' }
+ let(:expected_auto_stop_in) { nil }
let(:attributes) do
{
@@ -49,11 +67,41 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Environment do
end
it_behaves_like 'returning a correct environment'
+
+ context 'and job environment also has an auto_stop_in attribute' do
+ let(:environment_auto_stop_in) { '5 minutes' }
+ let(:expected_auto_stop_in) { '5 minutes' }
+
+ let(:attributes) do
+ {
+ environment: environment_name,
+ options: {
+ environment: {
+ name: environment_name,
+ auto_stop_in: environment_auto_stop_in
+ }
+ }
+ }
+ end
+
+ it_behaves_like 'returning a correct environment'
+
+ context 'but the environment auto_stop_in on create flag is disabled' do
+ let(:expected_auto_stop_in) { nil }
+
+ before do
+ stub_feature_flags(environment_auto_stop_start_on_create: false)
+ end
+
+ it_behaves_like 'returning a correct environment'
+ end
+ end
end
context 'when job starts a review app' do
let(:environment_name) { 'review/$CI_COMMIT_REF_NAME' }
let(:expected_environment_name) { "review/#{job.ref}" }
+ let(:expected_auto_stop_in) { nil }
let(:attributes) do
{
@@ -68,6 +116,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Environment do
context 'when job stops a review app' do
let(:environment_name) { 'review/$CI_COMMIT_REF_NAME' }
let(:expected_environment_name) { "review/#{job.ref}" }
+ let(:expected_auto_stop_in) { nil }
let(:attributes) do
{
diff --git a/spec/lib/gitlab/ci/reports/test_case_spec.rb b/spec/lib/gitlab/ci/reports/test_case_spec.rb
index a142846fc18..668a475514e 100644
--- a/spec/lib/gitlab/ci/reports/test_case_spec.rb
+++ b/spec/lib/gitlab/ci/reports/test_case_spec.rb
@@ -2,13 +2,13 @@
require 'spec_helper'
-RSpec.describe Gitlab::Ci::Reports::TestCase do
+RSpec.describe Gitlab::Ci::Reports::TestCase, :aggregate_failures do
describe '#initialize' do
let(:test_case) { described_class.new(params) }
context 'when required params are given' do
let(:job) { build(:ci_build) }
- let(:params) { attributes_for(:test_case).merge!(job: job) }
+ let(:params) { attributes_for(:report_test_case).merge!(job: job) }
it 'initializes an instance', :aggregate_failures do
expect { test_case }.not_to raise_error
@@ -31,7 +31,7 @@ RSpec.describe Gitlab::Ci::Reports::TestCase do
shared_examples 'param is missing' do |param|
let(:job) { build(:ci_build) }
- let(:params) { attributes_for(:test_case).merge!(job: job) }
+ let(:params) { attributes_for(:report_test_case).merge!(job: job) }
it 'raises an error' do
params.delete(param)
@@ -55,7 +55,7 @@ RSpec.describe Gitlab::Ci::Reports::TestCase do
context 'when attachment is present' do
let_it_be(:job) { create(:ci_build) }
- let(:attachment_test_case) { build(:test_case, :failed_with_attachment, job: job) }
+ let(:attachment_test_case) { build(:report_test_case, :failed_with_attachment, job: job) }
it "initializes the attachment if present" do
expect(attachment_test_case.attachment).to eq("some/path.png")
@@ -71,7 +71,7 @@ RSpec.describe Gitlab::Ci::Reports::TestCase do
end
context 'when attachment is missing' do
- let(:test_case) { build(:test_case) }
+ let(:test_case) { build(:report_test_case) }
it '#has_attachment?' do
expect(test_case.has_attachment?).to be_falsy
@@ -82,4 +82,17 @@ RSpec.describe Gitlab::Ci::Reports::TestCase do
end
end
end
+
+ describe '#set_recent_failures' do
+ it 'sets the recent_failures information' do
+ test_case = build(:report_test_case)
+
+ test_case.set_recent_failures(1, 'master')
+
+ expect(test_case.recent_failures).to eq(
+ count: 1,
+ base_branch: 'master'
+ )
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb b/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb
new file mode 100644
index 00000000000..8df34eddffd
--- /dev/null
+++ b/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Reports::TestFailureHistory, :aggregate_failures do
+ include TestReportsHelper
+
+ describe '#load!' do
+ let_it_be(:project) { create(:project) }
+ let(:failed_rspec) { create_test_case_rspec_failed }
+ let(:failed_java) { create_test_case_java_failed }
+
+ subject(:load_history) { described_class.new([failed_rspec, failed_java], project).load! }
+
+ before do
+ allow(Ci::TestCaseFailure)
+ .to receive(:recent_failures_count)
+ .with(project: project, test_case_keys: [failed_rspec.key, failed_java.key])
+ .and_return(
+ failed_rspec.key => 2,
+ failed_java.key => 1
+ )
+ end
+
+ it 'sets the recent failures for each matching failed test case in all test suites' do
+ load_history
+
+ expect(failed_rspec.recent_failures).to eq(count: 2, base_branch: 'master')
+ expect(failed_java.recent_failures).to eq(count: 1, base_branch: 'master')
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(test_failure_history: false)
+ end
+
+ it 'does not set recent failures' do
+ load_history
+
+ expect(failed_rspec.recent_failures).to be_nil
+ expect(failed_java.recent_failures).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/test_reports_spec.rb b/spec/lib/gitlab/ci/reports/test_reports_spec.rb
index 502859852f2..24c00de3731 100644
--- a/spec/lib/gitlab/ci/reports/test_reports_spec.rb
+++ b/spec/lib/gitlab/ci/reports/test_reports_spec.rb
@@ -110,7 +110,7 @@ RSpec.describe Gitlab::Ci::Reports::TestReports do
end
describe '#with_attachment' do
- let(:test_case) { build(:test_case, :failed) }
+ let(:test_case) { build(:report_test_case, :failed) }
subject { test_reports.with_attachment! }
@@ -126,8 +126,8 @@ RSpec.describe Gitlab::Ci::Reports::TestReports do
end
context 'when test suites contain an attachment' do
- let(:test_case_succes) { build(:test_case) }
- let(:test_case_with_attachment) { build(:test_case, :failed_with_attachment) }
+ let(:test_case_succes) { build(:report_test_case) }
+ let(:test_case_with_attachment) { build(:report_test_case, :failed_with_attachment) }
before do
test_reports.get_suite('rspec').add_test_case(test_case_succes)
diff --git a/spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb b/spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb
index 6bb6771678a..c44d32ddb7d 100644
--- a/spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb
+++ b/spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb
@@ -2,11 +2,11 @@
require 'spec_helper'
-RSpec.describe Gitlab::Ci::Reports::TestSuiteComparer do
+RSpec.describe Gitlab::Ci::Reports::TestSuiteComparer, :aggregate_failures do
include TestReportsHelper
let(:comparer) { described_class.new(name, base_suite, head_suite) }
- let(:name) { 'rpsec' }
+ let(:name) { 'rspec' }
let(:base_suite) { Gitlab::Ci::Reports::TestSuite.new(name) }
let(:head_suite) { Gitlab::Ci::Reports::TestSuite.new(name) }
let(:test_case_success) { create_test_case_java_success }
@@ -16,7 +16,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuiteComparer do
describe '#new_failures' do
subject { comparer.new_failures }
- context 'when head sutie has a newly failed test case which does not exist in base' do
+ context 'when head suite has a newly failed test case which does not exist in base' do
before do
base_suite.add_test_case(test_case_success)
head_suite.add_test_case(test_case_failed)
@@ -27,7 +27,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuiteComparer do
end
end
- context 'when head sutie still has a failed test case which failed in base' do
+ context 'when head suite still has a failed test case which failed in base' do
before do
base_suite.add_test_case(test_case_failed)
head_suite.add_test_case(test_case_failed)
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuiteComparer do
end
end
- context 'when head sutie has a success test case which failed in base' do
+ context 'when head suite has a success test case which failed in base' do
before do
base_suite.add_test_case(test_case_failed)
head_suite.add_test_case(test_case_success)
@@ -53,7 +53,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuiteComparer do
describe '#existing_failures' do
subject { comparer.existing_failures }
- context 'when head sutie has a newly failed test case which does not exist in base' do
+ context 'when head suite has a newly failed test case which does not exist in base' do
before do
base_suite.add_test_case(test_case_success)
head_suite.add_test_case(test_case_failed)
@@ -64,7 +64,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuiteComparer do
end
end
- context 'when head sutie still has a failed test case which failed in base' do
+ context 'when head suite still has a failed test case which failed in base' do
before do
base_suite.add_test_case(test_case_failed)
head_suite.add_test_case(test_case_failed)
@@ -75,7 +75,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuiteComparer do
end
end
- context 'when head sutie has a success test case which failed in base' do
+ context 'when head suite has a success test case which failed in base' do
before do
base_suite.add_test_case(test_case_failed)
head_suite.add_test_case(test_case_success)
@@ -90,7 +90,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuiteComparer do
describe '#resolved_failures' do
subject { comparer.resolved_failures }
- context 'when head sutie has a newly failed test case which does not exist in base' do
+ context 'when head suite has a newly failed test case which does not exist in base' do
before do
base_suite.add_test_case(test_case_success)
head_suite.add_test_case(test_case_failed)
@@ -105,7 +105,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuiteComparer do
end
end
- context 'when head sutie still has a failed test case which failed in base' do
+ context 'when head suite still has a failed test case which failed in base' do
before do
base_suite.add_test_case(test_case_failed)
head_suite.add_test_case(test_case_failed)
@@ -120,7 +120,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuiteComparer do
end
end
- context 'when head sutie has a success test case which failed in base' do
+ context 'when head suite has a success test case which failed in base' do
before do
base_suite.add_test_case(test_case_failed)
head_suite.add_test_case(test_case_success)
@@ -347,4 +347,128 @@ RSpec.describe Gitlab::Ci::Reports::TestSuiteComparer do
end
end
end
+
+ describe '#limited_tests' do
+ subject(:limited_tests) { comparer.limited_tests }
+
+ context 'limits amount of tests returned' do
+ before do
+ stub_const("#{described_class}::DEFAULT_MAX_TESTS", 2)
+ stub_const("#{described_class}::DEFAULT_MIN_TESTS", 1)
+ end
+
+ context 'prefers new over existing and resolved' do
+ before do
+ 3.times { add_new_failure }
+ 3.times { add_new_error }
+ 3.times { add_existing_failure }
+ 3.times { add_existing_error }
+ 3.times { add_resolved_failure }
+ 3.times { add_resolved_error }
+ end
+
+ it 'returns 2 of each new category, and 1 of each resolved and existing' do
+ expect(limited_tests.new_failures.count).to eq(2)
+ expect(limited_tests.new_errors.count).to eq(2)
+ expect(limited_tests.existing_failures.count).to eq(1)
+ expect(limited_tests.existing_errors.count).to eq(1)
+ expect(limited_tests.resolved_failures.count).to eq(1)
+ expect(limited_tests.resolved_errors.count).to eq(1)
+ end
+
+ it 'does not affect the overall count' do
+ expect(summary).to include(total: 18, resolved: 6, failed: 6, errored: 6)
+ end
+ end
+
+ context 'prefers existing over resolved' do
+ before do
+ 3.times { add_existing_failure }
+ 3.times { add_existing_error }
+ 3.times { add_resolved_failure }
+ 3.times { add_resolved_error }
+ end
+
+ it 'returns 2 of each existing category, and 1 of each resolved' do
+ expect(limited_tests.new_failures.count).to eq(0)
+ expect(limited_tests.new_errors.count).to eq(0)
+ expect(limited_tests.existing_failures.count).to eq(2)
+ expect(limited_tests.existing_errors.count).to eq(2)
+ expect(limited_tests.resolved_failures.count).to eq(1)
+ expect(limited_tests.resolved_errors.count).to eq(1)
+ end
+
+ it 'does not affect the overall count' do
+ expect(summary).to include(total: 12, resolved: 6, failed: 3, errored: 3)
+ end
+ end
+
+ context 'limits amount of resolved' do
+ before do
+ 3.times { add_resolved_failure }
+ 3.times { add_resolved_error }
+ end
+
+ it 'returns 2 of each resolved category' do
+ expect(limited_tests.new_failures.count).to eq(0)
+ expect(limited_tests.new_errors.count).to eq(0)
+ expect(limited_tests.existing_failures.count).to eq(0)
+ expect(limited_tests.existing_errors.count).to eq(0)
+ expect(limited_tests.resolved_failures.count).to eq(2)
+ expect(limited_tests.resolved_errors.count).to eq(2)
+ end
+
+ it 'does not affect the overall count' do
+ expect(summary).to include(total: 6, resolved: 6, failed: 0, errored: 0)
+ end
+ end
+ end
+
+ def summary
+ {
+ total: comparer.total_count,
+ resolved: comparer.resolved_count,
+ failed: comparer.failed_count,
+ errored: comparer.error_count
+ }
+ end
+
+ def add_new_failure
+ failed_case = create_test_case_rspec_failed(SecureRandom.hex)
+ head_suite.add_test_case(failed_case)
+ end
+
+ def add_new_error
+ error_case = create_test_case_rspec_error(SecureRandom.hex)
+ head_suite.add_test_case(error_case)
+ end
+
+ def add_existing_failure
+ failed_case = create_test_case_rspec_failed(SecureRandom.hex)
+ base_suite.add_test_case(failed_case)
+ head_suite.add_test_case(failed_case)
+ end
+
+ def add_existing_error
+ error_case = create_test_case_rspec_error(SecureRandom.hex)
+ base_suite.add_test_case(error_case)
+ head_suite.add_test_case(error_case)
+ end
+
+ def add_resolved_failure
+ case_name = SecureRandom.hex
+ failed_case = create_test_case_java_failed(case_name)
+ success_case = create_test_case_java_success(case_name)
+ base_suite.add_test_case(failed_case)
+ head_suite.add_test_case(success_case)
+ end
+
+ def add_resolved_error
+ case_name = SecureRandom.hex
+ error_case = create_test_case_java_error(case_name)
+ success_case = create_test_case_java_success(case_name)
+ base_suite.add_test_case(error_case)
+ head_suite.add_test_case(success_case)
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/reports/test_suite_spec.rb b/spec/lib/gitlab/ci/reports/test_suite_spec.rb
index 50d1595da73..1d6b39a7831 100644
--- a/spec/lib/gitlab/ci/reports/test_suite_spec.rb
+++ b/spec/lib/gitlab/ci/reports/test_suite_spec.rb
@@ -91,7 +91,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuite do
subject { test_suite.with_attachment! }
context 'when test cases do not contain an attachment' do
- let(:test_case) { build(:test_case, :failed)}
+ let(:test_case) { build(:report_test_case, :failed)}
before do
test_suite.add_test_case(test_case)
@@ -103,7 +103,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuite do
end
context 'when test cases contain an attachment' do
- let(:test_case_with_attachment) { build(:test_case, :failed_with_attachment)}
+ let(:test_case_with_attachment) { build(:report_test_case, :failed_with_attachment)}
before do
test_suite.add_test_case(test_case_with_attachment)
diff --git a/spec/lib/gitlab/ci/runner_instructions_spec.rb b/spec/lib/gitlab/ci/runner_instructions_spec.rb
index 32ee2ceb040..d1020026fe6 100644
--- a/spec/lib/gitlab/ci/runner_instructions_spec.rb
+++ b/spec/lib/gitlab/ci/runner_instructions_spec.rb
@@ -75,6 +75,13 @@ RSpec.describe Gitlab::Ci::RunnerInstructions do
with_them do
let(:params) { { os: os, arch: arch } }
+ around do |example|
+ # puma in production does not run from Rails.root, ensure file loading does not assume this
+ Dir.chdir(Rails.root.join('tmp').to_s) do
+ example.run
+ end
+ end
+
it 'returns string containing correct params' do
result = subject.install_script
diff --git a/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
new file mode 100644
index 00000000000..4be92e8608e
--- /dev/null
+++ b/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Deploy-ECS.gitlab-ci.yml' do
+ subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('AWS/Deploy-ECS') }
+
+ describe 'the created pipeline' do
+ let_it_be(:user) { create(:admin) }
+ let(:default_branch) { 'master' }
+ let(:pipeline_branch) { default_branch }
+ let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
+ let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
+ let(:pipeline) { service.execute!(:push) }
+ let(:build_names) { pipeline.builds.pluck(:name) }
+ let(:platform_target) { 'ECS' }
+
+ before do
+ create(:ci_variable, project: project, key: 'AUTO_DEVOPS_PLATFORM_TARGET', value: platform_target)
+ stub_ci_pipeline_yaml_file(template.content)
+ allow_any_instance_of(Ci::BuildScheduleWorker).to receive(:perform).and_return(true)
+ allow(project).to receive(:default_branch).and_return(default_branch)
+ end
+
+ shared_examples 'no pipeline yaml error' do
+ it 'does not have any error' do
+ expect(pipeline.has_yaml_errors?).to be_falsey
+ end
+ end
+
+ it_behaves_like 'no pipeline yaml error'
+
+ it 'creates the expected jobs' do
+ expect(build_names).to include('production_ecs')
+ end
+
+ context 'when running a pipeline for a branch' do
+ let(:pipeline_branch) { 'test_branch' }
+
+ before do
+ project.repository.create_branch(pipeline_branch)
+ end
+
+ it_behaves_like 'no pipeline yaml error'
+
+ it 'creates the expected jobs' do
+ expect(build_names).to include('review_ecs', 'stop_review_ecs')
+ end
+
+ context 'when deploying to ECS Fargate' do
+ let(:platform_target) { 'FARGATE' }
+
+ it 'creates the expected jobs' do
+ expect(build_names).to include('review_fargate', 'stop_review_fargate')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
index 4d90e7ca9e6..793df55f45d 100644
--- a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
@@ -94,14 +94,14 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
end
it 'creates an ECS deployment job for review only' do
- expect(review_prod_build_names).to contain_exactly('review_ecs')
+ expect(review_prod_build_names).to contain_exactly('review_ecs', 'stop_review_ecs')
end
context 'with FARGATE as a launch type' do
let(:platform_value) { 'FARGATE' }
it 'creates an FARGATE deployment job for review only' do
- expect(review_prod_build_names).to contain_exactly('review_fargate')
+ expect(review_prod_build_names).to contain_exactly('review_fargate', 'stop_review_fargate')
end
end
end
@@ -122,6 +122,15 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
end
end
end
+
+ context 'when the platform target is EC2' do
+ let(:platform_value) { 'EC2' }
+
+ it 'contains the build_artifact job, not the build job' do
+ expect(build_names).to include('build_artifact')
+ expect(build_names).not_to include('build')
+ end
+ end
end
context 'when the project has no active cluster' do
diff --git a/spec/lib/gitlab/ci/variables/collection/item_spec.rb b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
index eba2f29836d..2e43f22830a 100644
--- a/spec/lib/gitlab/ci/variables/collection/item_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
@@ -15,14 +15,14 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Item do
context 'when unknown keyword is specified' do
it 'raises error' do
expect { described_class.new(key: variable_key, value: 'abc', files: true) }
- .to raise_error ArgumentError, 'unknown keyword: files'
+ .to raise_error ArgumentError, 'unknown keyword: :files'
end
end
context 'when required keywords are not specified' do
it 'raises error' do
expect { described_class.new(key: variable_key) }
- .to raise_error ArgumentError, 'missing keyword: value'
+ .to raise_error ArgumentError, 'missing keyword: :value'
end
end
diff --git a/spec/lib/gitlab/config/entry/simplifiable_spec.rb b/spec/lib/gitlab/config/entry/simplifiable_spec.rb
index 2011587a342..f9088130037 100644
--- a/spec/lib/gitlab/config/entry/simplifiable_spec.rb
+++ b/spec/lib/gitlab/config/entry/simplifiable_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::Config::Entry::Simplifiable do
end
it 'attemps to load a first strategy' do
- expect(first).to receive(:new).with('something', anything)
+ expect(first).to receive(:new).with('something')
entry.new('something')
end
@@ -53,7 +53,7 @@ RSpec.describe Gitlab::Config::Entry::Simplifiable do
end
it 'attemps to load a second strategy' do
- expect(second).to receive(:new).with('test', anything)
+ expect(second).to receive(:new).with('test')
entry.new('test')
end
@@ -68,7 +68,7 @@ RSpec.describe Gitlab::Config::Entry::Simplifiable do
end
it 'instantiates an unknown strategy' do
- expect(unknown).to receive(:new).with('test', anything)
+ expect(unknown).to receive(:new).with('test')
entry.new('test')
end
diff --git a/spec/lib/gitlab/conflict/file_spec.rb b/spec/lib/gitlab/conflict/file_spec.rb
index 80bd517ec92..0de944d3f8a 100644
--- a/spec/lib/gitlab/conflict/file_spec.rb
+++ b/spec/lib/gitlab/conflict/file_spec.rb
@@ -93,6 +93,51 @@ RSpec.describe Gitlab::Conflict::File do
end
end
+ describe '#diff_lines_for_serializer' do
+ let(:diff_line_types) { conflict_file.diff_lines_for_serializer.map(&:type) }
+
+ it 'assigns conflict types to the diff lines' do
+ expect(diff_line_types[4]).to eq('conflict_marker')
+ expect(diff_line_types[5..10]).to eq(['conflict_marker_our'] * 6)
+ expect(diff_line_types[11]).to eq('conflict_marker')
+ expect(diff_line_types[12..17]).to eq(['conflict_marker_their'] * 6)
+ expect(diff_line_types[18]).to eq('conflict_marker')
+
+ expect(diff_line_types[19..24]).to eq([nil] * 6)
+
+ expect(diff_line_types[25]).to eq('conflict_marker')
+ expect(diff_line_types[26..27]).to eq(['conflict_marker_our'] * 2)
+ expect(diff_line_types[28]).to eq('conflict_marker')
+ expect(diff_line_types[29..30]).to eq(['conflict_marker_their'] * 2)
+ expect(diff_line_types[31]).to eq('conflict_marker')
+ end
+
+ it 'does not add a match line to the end of the section' do
+ expect(diff_line_types.last).to eq(nil)
+ end
+
+ context 'when there are unchanged trailing lines' do
+ let(:rugged_conflict) { index.conflicts.first }
+ let(:raw_conflict_content) { index.merge_file('files/ruby/popen.rb')[:data] }
+
+ it 'assign conflict types and adds match line to the end of the section' do
+ expect(diff_line_types).to eq([
+ 'match',
+ nil, nil, nil,
+ "conflict_marker",
+ "conflict_marker_our",
+ "conflict_marker",
+ "conflict_marker_their",
+ "conflict_marker_their",
+ "conflict_marker_their",
+ "conflict_marker",
+ nil, nil, nil,
+ "match"
+ ])
+ end
+ end
+ end
+
describe '#sections' do
it 'only inserts match lines when there is a gap between sections' do
conflict_file.sections.each_with_index do |section, i|
diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb
index a31f34d82d7..2c5988f06b2 100644
--- a/spec/lib/gitlab/cycle_analytics/events_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'cycle analytics events', :aggregate_failures do
+RSpec.describe 'value stream analytics events', :aggregate_failures do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user, :admin) }
let(:from_date) { 10.days.ago }
diff --git a/spec/lib/gitlab/danger/commit_linter_spec.rb b/spec/lib/gitlab/danger/commit_linter_spec.rb
index 882cede759b..ebfeedba700 100644
--- a/spec/lib/gitlab/danger/commit_linter_spec.rb
+++ b/spec/lib/gitlab/danger/commit_linter_spec.rb
@@ -190,7 +190,9 @@ RSpec.describe Gitlab::Danger::CommitLinter do
[
'[ci skip] A commit message',
'[Ci skip] A commit message',
- '[API] A commit message'
+ '[API] A commit message',
+ 'api: A commit message',
+ 'API: A commit message'
].each do |message|
context "when subject is '#{message}'" do
let(:commit_message) { message }
@@ -207,6 +209,9 @@ RSpec.describe Gitlab::Danger::CommitLinter do
'[ci skip]A commit message',
'[Ci skip] A commit message',
'[ci skip] a commit message',
+ 'API: a commit message',
+ 'API: a commit message',
+ 'api: a commit message',
'! A commit message'
].each do |message|
context "when subject is '#{message}'" do
diff --git a/spec/lib/gitlab/danger/helper_spec.rb b/spec/lib/gitlab/danger/helper_spec.rb
index 509649f08c6..f400641706d 100644
--- a/spec/lib/gitlab/danger/helper_spec.rb
+++ b/spec/lib/gitlab/danger/helper_spec.rb
@@ -236,13 +236,16 @@ RSpec.describe Gitlab::Danger::Helper do
'.gitlab/ci/frontend.gitlab-ci.yml' | %i[frontend engineering_productivity]
- 'app/models/foo' | [:backend]
- 'bin/foo' | [:backend]
- 'config/foo' | [:backend]
- 'lib/foo' | [:backend]
- 'rubocop/foo' | [:backend]
- 'spec/foo' | [:backend]
- 'spec/foo/bar' | [:backend]
+ 'app/models/foo' | [:backend]
+ 'bin/foo' | [:backend]
+ 'config/foo' | [:backend]
+ 'lib/foo' | [:backend]
+ 'rubocop/foo' | [:backend]
+ '.rubocop.yml' | [:backend]
+ '.rubocop_todo.yml' | [:backend]
+ '.rubocop_manual_todo.yml' | [:backend]
+ 'spec/foo' | [:backend]
+ 'spec/foo/bar' | [:backend]
'ee/app/foo' | [:backend]
'ee/bin/foo' | [:backend]
@@ -278,9 +281,9 @@ RSpec.describe Gitlab::Danger::Helper do
'scripts/foo' | [:engineering_productivity]
'lib/gitlab/danger/foo' | [:engineering_productivity]
'ee/lib/gitlab/danger/foo' | [:engineering_productivity]
- '.overcommit.yml.example' | [:engineering_productivity]
+ 'lefthook.yml' | [:engineering_productivity]
'.editorconfig' | [:engineering_productivity]
- 'tooling/overcommit/foo' | [:engineering_productivity]
+ 'tooling/bin/find_foss_tests' | [:engineering_productivity]
'.codeclimate.yml' | [:engineering_productivity]
'.gitlab/CODEOWNERS' | [:engineering_productivity]
@@ -312,6 +315,8 @@ RSpec.describe Gitlab::Danger::Helper do
'db/fixtures/foo.rb' | [:backend]
'ee/db/fixtures/foo.rb' | [:backend]
+ 'doc/api/graphql/reference/gitlab_schema.graphql' | [:backend]
+ 'doc/api/graphql/reference/gitlab_schema.json' | [:backend]
'qa/foo' | [:qa]
'ee/qa/foo' | [:qa]
diff --git a/spec/lib/gitlab/data_builder/feature_flag_spec.rb b/spec/lib/gitlab/data_builder/feature_flag_spec.rb
new file mode 100644
index 00000000000..75511fcf9f5
--- /dev/null
+++ b/spec/lib/gitlab/data_builder/feature_flag_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::DataBuilder::FeatureFlag do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:feature_flag) { create(:operations_feature_flag, project: project) }
+
+ describe '.build' do
+ let(:data) { described_class.build(feature_flag, user) }
+
+ it { expect(data).to be_a(Hash) }
+ it { expect(data[:object_kind]).to eq('feature_flag') }
+
+ it 'contains the correct object attributes' do
+ object_attributes = data[:object_attributes]
+
+ expect(object_attributes[:id]).to eq(feature_flag.id)
+ expect(object_attributes[:name]).to eq(feature_flag.name)
+ expect(object_attributes[:description]).to eq(feature_flag.description)
+ expect(object_attributes[:active]).to eq(feature_flag.active)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/batch_count_spec.rb b/spec/lib/gitlab/database/batch_count_spec.rb
index 31a8b4afa03..a1cc759e011 100644
--- a/spec/lib/gitlab/database/batch_count_spec.rb
+++ b/spec/lib/gitlab/database/batch_count_spec.rb
@@ -141,6 +141,29 @@ RSpec.describe Gitlab::Database::BatchCount do
described_class.batch_count(model)
end
+ it 'does not use BETWEEN to define the range' do
+ batch_size = Gitlab::Database::BatchCounter::MIN_REQUIRED_BATCH_SIZE + 1
+ issue = nil
+
+ travel_to(Date.tomorrow) do
+ issue = create(:issue) # created_at: 00:00:00
+ create(:issue, created_at: issue.created_at + batch_size - 0.5) # created_at: 00:20:50.5
+ create(:issue, created_at: issue.created_at + batch_size) # created_at: 00:20:51
+ end
+
+ # When using BETWEEN, the range condition looks like:
+ # Batch 1: WHERE "issues"."created_at" BETWEEN "2020-10-09 00:00:00" AND "2020-10-09 00:20:50"
+ # Batch 2: WHERE "issues"."created_at" BETWEEN "2020-10-09 00:20:51" AND "2020-10-09 00:41:41"
+ # We miss the issue created at 00:20:50.5 because we prevent the batches from overlapping (start..(finish - 1))
+ # See https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_BETWEEN_.28especially_with_timestamps.29
+
+ # When using >= AND <, we eliminate any gaps between batches (start...finish)
+ # This is useful when iterating over a timestamp column
+ # Batch 1: WHERE "issues"."created_at" >= "2020-10-09 00:00:00" AND "issues"."created_at" < "2020-10-09 00:20:51"
+ # Batch 1: WHERE "issues"."created_at" >= "2020-10-09 00:20:51" AND "issues"."created_at" < "2020-10-09 00:41:42"
+ expect(described_class.batch_count(model, :created_at, batch_size: batch_size, start: issue.created_at)).to eq(3)
+ end
+
it_behaves_like 'when a transaction is open' do
subject { described_class.batch_count(model) }
end
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index a8edcc5f7e5..ff6e5437559 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -1680,7 +1680,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
has_internal_id :iid,
scope: :project,
- init: ->(s) { s&.project&.issues&.maximum(:iid) },
+ init: ->(s, _scope) { s&.project&.issues&.maximum(:iid) },
backfill: true,
presence: false
end
diff --git a/spec/lib/gitlab/database/partitioning/replace_table_spec.rb b/spec/lib/gitlab/database/partitioning/replace_table_spec.rb
new file mode 100644
index 00000000000..d47666eeffd
--- /dev/null
+++ b/spec/lib/gitlab/database/partitioning/replace_table_spec.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Partitioning::ReplaceTable, '#perform' do
+ include TableSchemaHelpers
+
+ subject(:replace_table) { described_class.new(original_table, replacement_table, archived_table, 'id').perform }
+
+ let(:original_table) { '_test_original_table' }
+ let(:replacement_table) { '_test_replacement_table' }
+ let(:archived_table) { '_test_archived_table' }
+
+ let(:original_sequence) { "#{original_table}_id_seq" }
+
+ let(:original_primary_key) { "#{original_table}_pkey" }
+ let(:replacement_primary_key) { "#{replacement_table}_pkey" }
+ let(:archived_primary_key) { "#{archived_table}_pkey" }
+
+ before do
+ connection.execute(<<~SQL)
+ CREATE TABLE #{original_table} (
+ id serial NOT NULL PRIMARY KEY,
+ original_column text NOT NULL,
+ created_at timestamptz NOT NULL);
+
+ CREATE TABLE #{replacement_table} (
+ id int NOT NULL,
+ replacement_column text NOT NULL,
+ created_at timestamptz NOT NULL,
+ PRIMARY KEY (id, created_at))
+ PARTITION BY RANGE (created_at);
+ SQL
+ end
+
+ it 'replaces the current table, archiving the old' do
+ expect_table_to_be_replaced { replace_table }
+ end
+
+ it 'transfers the primary key sequence to the replacement table' do
+ expect(sequence_owned_by(original_table, 'id')).to eq(original_sequence)
+ expect(default_expression_for(original_table, 'id')).to eq("nextval('#{original_sequence}'::regclass)")
+
+ expect(sequence_owned_by(replacement_table, 'id')).to be_nil
+ expect(default_expression_for(replacement_table, 'id')).to be_nil
+
+ expect_table_to_be_replaced { replace_table }
+
+ expect(sequence_owned_by(original_table, 'id')).to eq(original_sequence)
+ expect(default_expression_for(original_table, 'id')).to eq("nextval('#{original_sequence}'::regclass)")
+ expect(sequence_owned_by(archived_table, 'id')).to be_nil
+ expect(default_expression_for(archived_table, 'id')).to be_nil
+ end
+
+ it 'renames the primary key constraints to match the new table names' do
+ expect_primary_keys_after_tables([original_table, replacement_table])
+
+ expect_table_to_be_replaced { replace_table }
+
+ expect_primary_keys_after_tables([original_table, archived_table])
+ end
+
+ context 'when the table has partitions' do
+ before do
+ connection.execute(<<~SQL)
+ CREATE TABLE gitlab_partitions_dynamic.#{replacement_table}_202001 PARTITION OF #{replacement_table}
+ FOR VALUES FROM ('2020-01-01') TO ('2020-02-01');
+
+ CREATE TABLE gitlab_partitions_dynamic.#{replacement_table}_202002 PARTITION OF #{replacement_table}
+ FOR VALUES FROM ('2020-02-01') TO ('2020-03-01');
+ SQL
+ end
+
+ it 'renames the partitions to match the new table name' do
+ expect(partitions_for_parent_table(original_table).count).to eq(0)
+ expect(partitions_for_parent_table(replacement_table).count).to eq(2)
+
+ expect_table_to_be_replaced { replace_table }
+
+ expect(partitions_for_parent_table(archived_table).count).to eq(0)
+
+ partitions = partitions_for_parent_table(original_table).all
+
+ expect(partitions.size).to eq(2)
+
+ expect(partitions[0]).to have_attributes(
+ identifier: "gitlab_partitions_dynamic.#{original_table}_202001",
+ condition: "FOR VALUES FROM ('2020-01-01 00:00:00+00') TO ('2020-02-01 00:00:00+00')")
+
+ expect(partitions[1]).to have_attributes(
+ identifier: "gitlab_partitions_dynamic.#{original_table}_202002",
+ condition: "FOR VALUES FROM ('2020-02-01 00:00:00+00') TO ('2020-03-01 00:00:00+00')")
+ end
+
+ it 'renames the primary key constraints to match the new partition names' do
+ original_partitions = ["#{replacement_table}_202001", "#{replacement_table}_202002"]
+ expect_primary_keys_after_tables(original_partitions, schema: 'gitlab_partitions_dynamic')
+
+ expect_table_to_be_replaced { replace_table }
+
+ renamed_partitions = ["#{original_table}_202001", "#{original_table}_202002"]
+ expect_primary_keys_after_tables(renamed_partitions, schema: 'gitlab_partitions_dynamic')
+ end
+ end
+
+ def partitions_for_parent_table(table)
+ Gitlab::Database::PostgresPartition.for_parent_table(table)
+ end
+
+ def expect_table_to_be_replaced(&block)
+ super(original_table: original_table, replacement_table: replacement_table, archived_table: archived_table, &block)
+ end
+end
diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb
new file mode 100644
index 00000000000..7f61ff759fc
--- /dev/null
+++ b/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb
@@ -0,0 +1,186 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::IndexHelpers do
+ include TableSchemaHelpers
+
+ let(:migration) do
+ ActiveRecord::Migration.new.extend(described_class)
+ end
+
+ let(:table_name) { '_test_partitioned_table' }
+ let(:column_name) { 'created_at' }
+ let(:index_name) { '_test_partitioning_index_name' }
+ let(:partition_schema) { 'gitlab_partitions_dynamic' }
+ let(:partition1_identifier) { "#{partition_schema}.#{table_name}_202001" }
+ let(:partition2_identifier) { "#{partition_schema}.#{table_name}_202002" }
+ let(:partition1_index) { "index_#{table_name}_202001_#{column_name}" }
+ let(:partition2_index) { "index_#{table_name}_202002_#{column_name}" }
+
+ before do
+ allow(migration).to receive(:puts)
+
+ connection.execute(<<~SQL)
+ CREATE TABLE #{table_name} (
+ id serial NOT NULL,
+ created_at timestamptz NOT NULL,
+ PRIMARY KEY (id, created_at)
+ ) PARTITION BY RANGE (created_at);
+
+ CREATE TABLE #{partition1_identifier} PARTITION OF #{table_name}
+ FOR VALUES FROM ('2020-01-01') TO ('2020-02-01');
+
+ CREATE TABLE #{partition2_identifier} PARTITION OF #{table_name}
+ FOR VALUES FROM ('2020-02-01') TO ('2020-03-01');
+ SQL
+ end
+
+ describe '#add_concurrent_partitioned_index' do
+ before do
+ allow(migration).to receive(:index_name_exists?).with(table_name, index_name).and_return(false)
+
+ allow(migration).to receive(:generated_index_name).and_return(partition1_index, partition2_index)
+
+ allow(migration).to receive(:with_lock_retries).and_yield
+ end
+
+ context 'when the index does not exist on the parent table' do
+ it 'creates the index on each partition, and the parent table', :aggregate_failures do
+ expect(migration).to receive(:index_name_exists?).with(table_name, index_name).and_return(false)
+
+ expect_add_concurrent_index_and_call_original(partition1_identifier, column_name, partition1_index)
+ expect_add_concurrent_index_and_call_original(partition2_identifier, column_name, partition2_index)
+
+ expect(migration).to receive(:with_lock_retries).ordered.and_yield
+ expect(migration).to receive(:add_index).with(table_name, column_name, name: index_name).ordered.and_call_original
+
+ migration.add_concurrent_partitioned_index(table_name, column_name, name: index_name)
+
+ expect_index_to_exist(partition1_index, schema: partition_schema)
+ expect_index_to_exist(partition2_index, schema: partition_schema)
+ expect_index_to_exist(index_name)
+ end
+
+ def expect_add_concurrent_index_and_call_original(table, column, index)
+ expect(migration).to receive(:add_concurrent_index).ordered.with(table, column, name: index)
+ .and_wrap_original { |_, table, column, options| connection.add_index(table, column, options) }
+ end
+ end
+
+ context 'when the index exists on the parent table' do
+ it 'does not attempt to create any indexes', :aggregate_failures do
+ expect(migration).to receive(:index_name_exists?).with(table_name, index_name).and_return(true)
+
+ expect(migration).not_to receive(:add_concurrent_index)
+ expect(migration).not_to receive(:with_lock_retries)
+ expect(migration).not_to receive(:add_index)
+
+ migration.add_concurrent_partitioned_index(table_name, column_name, name: index_name)
+ end
+ end
+
+ context 'when additional index options are given' do
+ before do
+ connection.execute(<<~SQL)
+ DROP TABLE #{partition2_identifier}
+ SQL
+ end
+
+ it 'forwards them to the index helper methods', :aggregate_failures do
+ expect(migration).to receive(:add_concurrent_index)
+ .with(partition1_identifier, column_name, name: partition1_index, where: 'x > 0', unique: true)
+
+ expect(migration).to receive(:add_index)
+ .with(table_name, column_name, name: index_name, where: 'x > 0', unique: true)
+
+ migration.add_concurrent_partitioned_index(table_name, column_name,
+ name: index_name, where: 'x > 0', unique: true)
+ end
+ end
+
+ context 'when a name argument for the index is not given' do
+ it 'raises an error', :aggregate_failures do
+ expect(migration).not_to receive(:add_concurrent_index)
+ expect(migration).not_to receive(:with_lock_retries)
+ expect(migration).not_to receive(:add_index)
+
+ expect do
+ migration.add_concurrent_partitioned_index(table_name, column_name)
+ end.to raise_error(ArgumentError, /A name is required for indexes added to partitioned tables/)
+ end
+ end
+
+ context 'when the given table is not a partitioned table' do
+ before do
+ allow(Gitlab::Database::PostgresPartitionedTable).to receive(:find_by_name_in_current_schema)
+ .with(table_name).and_return(nil)
+ end
+
+ it 'raises an error', :aggregate_failures do
+ expect(migration).not_to receive(:add_concurrent_index)
+ expect(migration).not_to receive(:with_lock_retries)
+ expect(migration).not_to receive(:add_index)
+
+ expect do
+ migration.add_concurrent_partitioned_index(table_name, column_name, name: index_name)
+ end.to raise_error(ArgumentError, /#{table_name} is not a partitioned table/)
+ end
+ end
+ end
+
+ describe '#remove_concurrent_partitioned_index_by_name' do
+ context 'when the index exists' do
+ before do
+ connection.execute(<<~SQL)
+ CREATE INDEX #{partition1_index} ON #{partition1_identifier} (#{column_name});
+ CREATE INDEX #{partition2_index} ON #{partition2_identifier} (#{column_name});
+
+ CREATE INDEX #{index_name} ON #{table_name} (#{column_name});
+ SQL
+ end
+
+ it 'drops the index on the parent table, cascading to all partitions', :aggregate_failures do
+ expect_index_to_exist(partition1_index, schema: partition_schema)
+ expect_index_to_exist(partition2_index, schema: partition_schema)
+ expect_index_to_exist(index_name)
+
+ expect(migration).to receive(:with_lock_retries).ordered.and_yield
+ expect(migration).to receive(:remove_index).with(table_name, name: index_name).ordered.and_call_original
+
+ migration.remove_concurrent_partitioned_index_by_name(table_name, index_name)
+
+ expect_index_not_to_exist(partition1_index, schema: partition_schema)
+ expect_index_not_to_exist(partition2_index, schema: partition_schema)
+ expect_index_not_to_exist(index_name)
+ end
+ end
+
+ context 'when the index does not exist' do
+ it 'does not attempt to drop the index', :aggregate_failures do
+ expect(migration).to receive(:index_name_exists?).with(table_name, index_name).and_return(false)
+
+ expect(migration).not_to receive(:with_lock_retries)
+ expect(migration).not_to receive(:remove_index)
+
+ migration.remove_concurrent_partitioned_index_by_name(table_name, index_name)
+ end
+ end
+
+ context 'when the given table is not a partitioned table' do
+ before do
+ allow(Gitlab::Database::PostgresPartitionedTable).to receive(:find_by_name_in_current_schema)
+ .with(table_name).and_return(nil)
+ end
+
+ it 'raises an error', :aggregate_failures do
+ expect(migration).not_to receive(:with_lock_retries)
+ expect(migration).not_to receive(:remove_index)
+
+ expect do
+ migration.remove_concurrent_partitioned_index_by_name(table_name, index_name)
+ end.to raise_error(ArgumentError, /#{table_name} is not a partitioned table/)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
index 147637cf471..f10ff704c17 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
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHelpers do
include PartitioningHelpers
include TriggerHelpers
+ include TableSchemaHelpers
let(:migration) do
ActiveRecord::Migration.new.extend(described_class)
@@ -629,6 +630,76 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
end
end
+ describe '#replace_with_partitioned_table' do
+ let(:archived_table) { "#{source_table}_archived" }
+
+ before do
+ migration.partition_table_by_date source_table, partition_column, min_date: min_date, max_date: max_date
+ end
+
+ it 'replaces the original table with the partitioned table' do
+ expect(table_type(source_table)).to eq('normal')
+ expect(table_type(partitioned_table)).to eq('partitioned')
+ expect(table_type(archived_table)).to be_nil
+
+ expect_table_to_be_replaced { migration.replace_with_partitioned_table(source_table) }
+
+ expect(table_type(source_table)).to eq('partitioned')
+ expect(table_type(archived_table)).to eq('normal')
+ expect(table_type(partitioned_table)).to be_nil
+ end
+
+ it 'moves the trigger from the original table to the new table' do
+ expect_function_to_exist(function_name)
+ expect_valid_function_trigger(source_table, trigger_name, function_name, after: %w[delete insert update])
+
+ expect_table_to_be_replaced { migration.replace_with_partitioned_table(source_table) }
+
+ expect_function_to_exist(function_name)
+ expect_valid_function_trigger(source_table, trigger_name, function_name, after: %w[delete insert update])
+ end
+
+ def expect_table_to_be_replaced(&block)
+ super(original_table: source_table, replacement_table: partitioned_table, archived_table: archived_table, &block)
+ end
+ end
+
+ describe '#rollback_replace_with_partitioned_table' do
+ let(:archived_table) { "#{source_table}_archived" }
+
+ before do
+ migration.partition_table_by_date source_table, partition_column, min_date: min_date, max_date: max_date
+
+ migration.replace_with_partitioned_table source_table
+ end
+
+ it 'replaces the partitioned table with the non-partitioned table' do
+ expect(table_type(source_table)).to eq('partitioned')
+ expect(table_type(archived_table)).to eq('normal')
+ expect(table_type(partitioned_table)).to be_nil
+
+ expect_table_to_be_replaced { migration.rollback_replace_with_partitioned_table(source_table) }
+
+ expect(table_type(source_table)).to eq('normal')
+ expect(table_type(partitioned_table)).to eq('partitioned')
+ expect(table_type(archived_table)).to be_nil
+ end
+
+ it 'moves the trigger from the partitioned table to the non-partitioned table' do
+ expect_function_to_exist(function_name)
+ expect_valid_function_trigger(source_table, trigger_name, function_name, after: %w[delete insert update])
+
+ expect_table_to_be_replaced { migration.rollback_replace_with_partitioned_table(source_table) }
+
+ expect_function_to_exist(function_name)
+ expect_valid_function_trigger(source_table, trigger_name, function_name, after: %w[delete insert update])
+ end
+
+ def expect_table_to_be_replaced(&block)
+ super(original_table: source_table, replacement_table: archived_table, archived_table: partitioned_table, &block)
+ end
+ end
+
def filter_columns_by_name(columns, names)
columns.reject { |c| names.include?(c.name) }
end
diff --git a/spec/lib/gitlab/database/postgres_index_spec.rb b/spec/lib/gitlab/database/postgres_index_spec.rb
index 1da67a5a6c0..d65b638f7bc 100644
--- a/spec/lib/gitlab/database/postgres_index_spec.rb
+++ b/spec/lib/gitlab/database/postgres_index_spec.rb
@@ -3,9 +3,13 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::PostgresIndex do
+ let(:schema) { 'public' }
+ let(:name) { 'foo_idx' }
+ let(:identifier) { "#{schema}.#{name}" }
+
before do
ActiveRecord::Base.connection.execute(<<~SQL)
- CREATE INDEX foo_idx ON public.users (name);
+ CREATE INDEX #{name} ON public.users (name);
CREATE UNIQUE INDEX bar_key ON public.users (id);
CREATE TABLE example_table (id serial primary key);
@@ -16,19 +20,7 @@ RSpec.describe Gitlab::Database::PostgresIndex do
described_class.by_identifier(name)
end
- describe '.by_identifier' do
- it 'finds the index' do
- expect(find('public.foo_idx')).to be_a(Gitlab::Database::PostgresIndex)
- end
-
- it 'raises an error if not found' do
- expect { find('public.idontexist') }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'raises ArgumentError if given a non-fully qualified index name' do
- expect { find('foo') }.to raise_error(ArgumentError, /not fully qualified/)
- end
- end
+ it_behaves_like 'a postgres model'
describe '.regular' do
it 'only non-unique indexes' do
@@ -76,7 +68,7 @@ RSpec.describe Gitlab::Database::PostgresIndex do
describe '#valid_index?' do
it 'returns true if the index is invalid' do
- expect(find('public.foo_idx')).to be_valid_index
+ expect(find(identifier)).to be_valid_index
end
it 'returns false if the index is marked as invalid' do
@@ -86,31 +78,13 @@ RSpec.describe Gitlab::Database::PostgresIndex do
WHERE pg_class.relname = 'foo_idx' AND pg_index.indexrelid = pg_class.oid
SQL
- expect(find('public.foo_idx')).not_to be_valid_index
- end
- end
-
- describe '#to_s' do
- it 'returns the index name' do
- expect(find('public.foo_idx').to_s).to eq('foo_idx')
- end
- end
-
- describe '#name' do
- it 'returns the name' do
- expect(find('public.foo_idx').name).to eq('foo_idx')
- end
- end
-
- describe '#schema' do
- it 'returns the index schema' do
- expect(find('public.foo_idx').schema).to eq('public')
+ expect(find(identifier)).not_to be_valid_index
end
end
describe '#definition' do
it 'returns the index definition' do
- expect(find('public.foo_idx').definition).to eq('CREATE INDEX foo_idx ON public.users USING btree (name)')
+ expect(find(identifier).definition).to eq('CREATE INDEX foo_idx ON public.users USING btree (name)')
end
end
end
diff --git a/spec/lib/gitlab/database/postgres_partition_spec.rb b/spec/lib/gitlab/database/postgres_partition_spec.rb
new file mode 100644
index 00000000000..5a44090d5ae
--- /dev/null
+++ b/spec/lib/gitlab/database/postgres_partition_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::PostgresPartition, type: :model do
+ let(:schema) { 'gitlab_partitions_dynamic' }
+ let(:name) { '_test_partition_01' }
+ let(:identifier) { "#{schema}.#{name}" }
+
+ before do
+ ActiveRecord::Base.connection.execute(<<~SQL)
+ CREATE TABLE public._test_partitioned_table (
+ id serial NOT NULL,
+ created_at timestamptz NOT NULL,
+ PRIMARY KEY (id, created_at)
+ ) PARTITION BY RANGE(created_at);
+
+ CREATE TABLE #{identifier} PARTITION OF public._test_partitioned_table
+ FOR VALUES FROM ('2020-01-01') to ('2020-02-01');
+ SQL
+ end
+
+ def find(identifier)
+ described_class.by_identifier(identifier)
+ end
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:postgres_partitioned_table).with_primary_key('identifier').with_foreign_key('parent_identifier') }
+ end
+
+ it_behaves_like 'a postgres model'
+
+ describe '.for_parent_table' do
+ let(:second_name) { '_test_partition_02' }
+
+ before do
+ ActiveRecord::Base.connection.execute(<<~SQL)
+ CREATE TABLE #{schema}.#{second_name} PARTITION OF public._test_partitioned_table
+ FOR VALUES FROM ('2020-02-01') to ('2020-03-01');
+
+ CREATE TABLE #{schema}._test_other_table (
+ id serial NOT NULL,
+ created_at timestamptz NOT NULL,
+ PRIMARY KEY (id, created_at)
+ ) PARTITION BY RANGE(created_at);
+
+ CREATE TABLE #{schema}._test_other_partition_01 PARTITION OF #{schema}._test_other_table
+ FOR VALUES FROM ('2020-01-01') to ('2020-02-01');
+ SQL
+ end
+
+ it 'returns partitions for the parent table in the current schema' do
+ partitions = described_class.for_parent_table('_test_partitioned_table')
+
+ expect(partitions.count).to eq(2)
+ expect(partitions.pluck(:name)).to eq([name, second_name])
+ end
+
+ it 'does not return partitions for tables not in the current schema' do
+ expect(described_class.for_parent_table('_test_other_table').count).to eq(0)
+ end
+ end
+
+ describe '#parent_identifier' do
+ it 'returns the parent table identifier' do
+ expect(find(identifier).parent_identifier).to eq('public._test_partitioned_table')
+ end
+ end
+
+ describe '#condition' do
+ it 'returns the condition for the partitioned values' do
+ expect(find(identifier).condition).to eq("FOR VALUES FROM ('2020-01-01 00:00:00+00') TO ('2020-02-01 00:00:00+00')")
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/postgres_partitioned_table_spec.rb b/spec/lib/gitlab/database/postgres_partitioned_table_spec.rb
new file mode 100644
index 00000000000..21a46f1a0a6
--- /dev/null
+++ b/spec/lib/gitlab/database/postgres_partitioned_table_spec.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::PostgresPartitionedTable, type: :model do
+ let(:schema) { 'public' }
+ let(:name) { 'foo_range' }
+ let(:identifier) { "#{schema}.#{name}" }
+
+ before do
+ ActiveRecord::Base.connection.execute(<<~SQL)
+ CREATE TABLE #{identifier} (
+ id serial NOT NULL,
+ created_at timestamptz NOT NULL,
+ PRIMARY KEY (id, created_at)
+ ) PARTITION BY RANGE(created_at);
+
+ CREATE TABLE public.foo_list (
+ id serial NOT NULL,
+ row_type text NOT NULL,
+ PRIMARY KEY (id, row_type)
+ ) PARTITION BY LIST(row_type);
+
+ CREATE TABLE public.foo_hash (
+ id serial NOT NULL,
+ row_value int NOT NULL,
+ PRIMARY KEY (id, row_value)
+ ) PARTITION BY HASH (row_value);
+ SQL
+ end
+
+ def find(identifier)
+ described_class.by_identifier(identifier)
+ end
+
+ describe 'associations' do
+ it { is_expected.to have_many(:postgres_partitions).with_primary_key('identifier').with_foreign_key('parent_identifier') }
+ end
+
+ it_behaves_like 'a postgres model'
+
+ describe '.find_by_name_in_current_schema' do
+ it 'finds the partitioned tables in the current schema by name', :aggregate_failures do
+ partitioned_table = described_class.find_by_name_in_current_schema(name)
+
+ expect(partitioned_table).not_to be_nil
+ expect(partitioned_table.identifier).to eq(identifier)
+ end
+
+ it 'does not find partitioned tables in a different schema' do
+ ActiveRecord::Base.connection.execute(<<~SQL)
+ ALTER TABLE #{identifier} SET SCHEMA gitlab_partitions_dynamic
+ SQL
+
+ expect(described_class.find_by_name_in_current_schema(name)).to be_nil
+ end
+ end
+
+ describe '#dynamic?' do
+ it 'returns true for tables partitioned by range' do
+ expect(find('public.foo_range')).to be_dynamic
+ end
+
+ it 'returns true for tables partitioned by list' do
+ expect(find('public.foo_list')).to be_dynamic
+ end
+
+ it 'returns false for tables partitioned by hash' do
+ expect(find('public.foo_hash')).not_to be_dynamic
+ end
+ end
+
+ describe '#static?' do
+ it 'returns false for tables partitioned by range' do
+ expect(find('public.foo_range')).not_to be_static
+ end
+
+ it 'returns false for tables partitioned by list' do
+ expect(find('public.foo_list')).not_to be_static
+ end
+
+ it 'returns true for tables partitioned by hash' do
+ expect(find('public.foo_hash')).to be_static
+ end
+ end
+
+ describe '#strategy' do
+ it 'returns the partitioning strategy' do
+ expect(find(identifier).strategy).to eq('range')
+ end
+ end
+
+ describe '#key_columns' do
+ it 'returns the partitioning key columns' do
+ expect(find(identifier).key_columns).to match_array(['created_at'])
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/reindexing_spec.rb b/spec/lib/gitlab/database/reindexing_spec.rb
index 86b3c029944..359e0597f4e 100644
--- a/spec/lib/gitlab/database/reindexing_spec.rb
+++ b/spec/lib/gitlab/database/reindexing_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe Gitlab::Database::Reindexing do
it 'retrieves regular indexes that are no left-overs from previous runs' do
result = double
- expect(Gitlab::Database::PostgresIndex).to receive_message_chain('regular.not_match.not_match').with(no_args).with('^tmp_reindex_').with('^old_reindex_').and_return(result)
+ expect(Gitlab::Database::PostgresIndex).to receive_message_chain('regular.where.not_match.not_match').with(no_args).with('NOT expression').with('^tmp_reindex_').with('^old_reindex_').and_return(result)
expect(subject).to eq(result)
end
diff --git a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
index a38fe2c51ca..2ebfb054a96 100644
--- a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
@@ -11,13 +11,13 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
end
let(:email_raw) { email_fixture('emails/service_desk.eml') }
- let_it_be(:namespace) { create(:namespace, name: "email") }
+ let_it_be(:group) { create(:group, :private, name: "email") }
let(:expected_description) do
"Service desk stuff!\n\n```\na = b\n```\n\n`/label ~label1`\n`/assign @user1`\n`/close`\n![image](uploads/image.png)"
end
context 'service desk is enabled for the project' do
- let_it_be(:project) { create(:project, :repository, :public, namespace: namespace, path: 'test', service_desk_enabled: true) }
+ let_it_be(:project) { create(:project, :repository, :private, group: group, path: 'test', service_desk_enabled: true) }
before do
allow(Gitlab::ServiceDesk).to receive(:supported?).and_return(true)
@@ -101,6 +101,18 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
expect(issue.milestone).to eq(milestone)
end
+ it 'applies group labels using quick actions' do
+ group_label = create(:group_label, group: project.group, title: 'label2')
+ file_content = %(Text from template \n/label ~#{group_label.title}"")
+ set_template_file('with_group_labels', file_content)
+
+ receiver.execute
+
+ issue = Issue.last
+ expect(issue.description).to include('Text from template')
+ expect(issue.label_ids).to include(group_label.id)
+ end
+
it 'redacts quick actions present on user email body' do
set_template_file('service_desk1', 'text from template')
@@ -289,7 +301,8 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
end
context 'service desk is disabled for the project' do
- let(:project) { create(:project, :public, namespace: namespace, path: 'test', service_desk_enabled: false) }
+ let(:group) { create(:group)}
+ let(:project) { create(:project, :public, group: group, path: 'test', service_desk_enabled: false) }
it 'bounces the email' do
expect { receiver.execute }.to raise_error(Gitlab::Email::ProcessingError)
diff --git a/spec/lib/gitlab/error_tracking_spec.rb b/spec/lib/gitlab/error_tracking_spec.rb
index 2cc9ff36c99..68a46b11487 100644
--- a/spec/lib/gitlab/error_tracking_spec.rb
+++ b/spec/lib/gitlab/error_tracking_spec.rb
@@ -198,47 +198,39 @@ RSpec.describe Gitlab::ErrorTracking do
end
describe '.track_exception' do
- it 'calls Raven.capture_exception' do
- expected_extras = {
- some_other_info: 'info',
- issue_url: issue_url
- }
+ let(:extra) { { issue_url: issue_url, some_other_info: 'info' } }
- expected_tags = {
- correlation_id: 'cid'
- }
+ subject(:track_exception) { described_class.track_exception(exception, extra) }
- expect(Raven).to receive(:capture_exception)
- .with(exception,
- tags: a_hash_including(expected_tags),
- extra: a_hash_including(expected_extras))
-
- described_class.track_exception(
- exception,
- issue_url: issue_url,
- some_other_info: 'info'
- )
+ before do
+ allow(Raven).to receive(:capture_exception).and_call_original
+ allow(Gitlab::ErrorTracking::Logger).to receive(:error)
+ end
+
+ it 'calls Raven.capture_exception' do
+ track_exception
+
+ expect(Raven).to have_received(:capture_exception)
+ .with(exception,
+ tags: a_hash_including(correlation_id: 'cid'),
+ extra: a_hash_including(some_other_info: 'info', issue_url: issue_url))
end
it 'calls Gitlab::ErrorTracking::Logger.error with formatted payload' do
- expect(Gitlab::ErrorTracking::Logger).to receive(:error)
- .with(a_hash_including(*expected_payload_includes))
+ track_exception
- described_class.track_exception(
- exception,
- issue_url: issue_url,
- some_other_info: 'info'
- )
+ expect(Gitlab::ErrorTracking::Logger).to have_received(:error)
+ .with(a_hash_including(*expected_payload_includes))
end
context 'with filterable parameters' do
let(:extra) { { test: 1, my_token: 'test' } }
it 'filters parameters' do
- expect(Gitlab::ErrorTracking::Logger).to receive(:error).with(
- hash_including({ 'extra.test' => 1, 'extra.my_token' => '[FILTERED]' }))
+ track_exception
- described_class.track_exception(exception, extra)
+ expect(Gitlab::ErrorTracking::Logger).to have_received(:error)
+ .with(hash_including({ 'extra.test' => 1, 'extra.my_token' => '[FILTERED]' }))
end
end
@@ -247,44 +239,58 @@ RSpec.describe Gitlab::ErrorTracking do
let(:exception) { double(message: 'bang!', sentry_extra_data: extra_info, backtrace: caller) }
it 'includes the extra data from the exception in the tracking information' do
- expect(Raven).to receive(:capture_exception)
- .with(exception, a_hash_including(extra: a_hash_including(extra_info)))
+ track_exception
- described_class.track_exception(exception)
+ expect(Raven).to have_received(:capture_exception)
+ .with(exception, a_hash_including(extra: a_hash_including(extra_info)))
end
end
context 'the exception implements :sentry_extra_data, which returns nil' do
let(:exception) { double(message: 'bang!', sentry_extra_data: nil, backtrace: caller) }
+ let(:extra) { { issue_url: issue_url } }
it 'just includes the other extra info' do
- extra_info = { issue_url: issue_url }
- expect(Raven).to receive(:capture_exception)
- .with(exception, a_hash_including(extra: a_hash_including(extra_info)))
+ track_exception
- described_class.track_exception(exception, extra_info)
+ expect(Raven).to have_received(:capture_exception)
+ .with(exception, a_hash_including(extra: a_hash_including(extra)))
end
end
context 'with sidekiq args' do
- it 'ensures extra.sidekiq.args is a string' do
- extra = { sidekiq: { 'class' => 'PostReceive', 'args' => [1, { 'id' => 2, 'name' => 'hello' }, 'some-value', 'another-value'] } }
+ context 'when the args does not have anything sensitive' do
+ let(:extra) { { sidekiq: { 'class' => 'PostReceive', 'args' => [1, { 'id' => 2, 'name' => 'hello' }, 'some-value', 'another-value'] } } }
- expect(Gitlab::ErrorTracking::Logger).to receive(:error).with(
- hash_including({ 'extra.sidekiq' => { 'class' => 'PostReceive', 'args' => ['1', '{"id"=>2, "name"=>"hello"}', 'some-value', 'another-value'] } }))
+ it 'ensures extra.sidekiq.args is a string' do
+ track_exception
- described_class.track_exception(exception, extra)
+ expect(Gitlab::ErrorTracking::Logger).to have_received(:error).with(
+ hash_including({ 'extra.sidekiq' => { 'class' => 'PostReceive', 'args' => ['1', '{"id"=>2, "name"=>"hello"}', 'some-value', 'another-value'] } }))
+ end
end
- it 'filters sensitive arguments before sending' do
- extra = { sidekiq: { 'class' => 'UnknownWorker', 'args' => ['sensitive string', 1, 2] } }
+ context 'when the args has sensitive information' do
+ let(:extra) { { sidekiq: { 'class' => 'UnknownWorker', 'args' => ['sensitive string', 1, 2] } } }
+
+ it 'filters sensitive arguments before sending' do
+ track_exception
+
+ expect(sentry_event.dig('extra', 'sidekiq', 'args')).to eq(['[FILTERED]', 1, 2])
+ expect(Gitlab::ErrorTracking::Logger).to have_received(:error).with(
+ hash_including('extra.sidekiq' => { 'class' => 'UnknownWorker', 'args' => ['[FILTERED]', '1', '2'] }))
+ end
+ end
+ end
- expect(Gitlab::ErrorTracking::Logger).to receive(:error).with(
- hash_including('extra.sidekiq' => { 'class' => 'UnknownWorker', 'args' => ['[FILTERED]', '1', '2'] }))
+ context 'when the error is kind of an `ActiveRecord::StatementInvalid`' do
+ let(:exception) { ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1') }
- described_class.track_exception(exception, extra)
+ it 'injects the normalized sql query into extra' do
+ track_exception
- expect(sentry_event.dig('extra', 'sidekiq', 'args')).to eq(['[FILTERED]', 1, 2])
+ expect(Raven).to have_received(:capture_exception)
+ .with(exception, a_hash_including(extra: a_hash_including(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')))
end
end
end
diff --git a/spec/lib/gitlab/etag_caching/middleware_spec.rb b/spec/lib/gitlab/etag_caching/middleware_spec.rb
index 361b2329e15..3122a3b1c07 100644
--- a/spec/lib/gitlab/etag_caching/middleware_spec.rb
+++ b/spec/lib/gitlab/etag_caching/middleware_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::EtagCaching::Middleware do
+RSpec.describe Gitlab::EtagCaching::Middleware, :clean_gitlab_redis_shared_state do
let(:app) { double(:app) }
let(:middleware) { described_class.new(app) }
let(:app_status_code) { 200 }
@@ -10,6 +10,17 @@ RSpec.describe Gitlab::EtagCaching::Middleware do
let(:enabled_path) { '/gitlab-org/gitlab-foss/noteable/issue/1/notes' }
let(:endpoint) { 'issue_notes' }
+ describe '.skip!' do
+ it 'sets the skip header on the response' do
+ rsp = ActionDispatch::Response.new
+ rsp.set_header('Anything', 'Else')
+
+ described_class.skip!(rsp)
+
+ expect(rsp.headers.to_h).to eq(described_class::SKIP_HEADER_KEY => '1', 'Anything' => 'Else')
+ end
+ end
+
context 'when ETag caching is not enabled for current route' do
let(:path) { '/gitlab-org/gitlab-foss/tree/master/noteable/issue/1/notes' }
@@ -17,10 +28,12 @@ RSpec.describe Gitlab::EtagCaching::Middleware do
mock_app_response
end
- it 'does not add ETag header' do
+ it 'does not add ETag headers' do
_, headers, _ = middleware.call(build_request(path, if_none_match))
expect(headers['ETag']).to be_nil
+ expect(headers['X-Gitlab-From-Cache']).to be_nil
+ expect(headers[::Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER]).to be_nil
end
it 'passes status code from app' do
@@ -68,13 +81,35 @@ RSpec.describe Gitlab::EtagCaching::Middleware do
mock_value_in_store('123')
end
- it 'returns this value as header' do
+ it 'returns the correct headers' do
_, headers, _ = middleware.call(build_request(path, if_none_match))
expect(headers['ETag']).to eq 'W/"123"'
end
end
+ context 'when the matching route requests that the ETag is skipped' do
+ let(:path) { enabled_path }
+ let(:app) do
+ proc do |_env|
+ response = ActionDispatch::Response.new
+
+ described_class.skip!(response)
+
+ [200, response.headers.to_h, '']
+ end
+ end
+
+ it 'returns the correct headers' do
+ expect(app).to receive(:call).and_call_original
+
+ _, headers, _ = middleware.call(build_request(path, if_none_match))
+
+ expect(headers).not_to have_key('ETag')
+ expect(headers).not_to have_key(described_class::SKIP_HEADER_KEY)
+ end
+ end
+
shared_examples 'sends a process_action.action_controller notification' do |status_code|
let(:expected_items) do
{
@@ -126,6 +161,13 @@ RSpec.describe Gitlab::EtagCaching::Middleware do
expect(status).to eq 304
end
+ it 'sets correct headers' do
+ _, headers, _ = middleware.call(build_request(path, if_none_match))
+
+ expect(headers).to include('X-Gitlab-From-Cache' => 'true',
+ ::Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER => 'issue_tracking')
+ end
+
it_behaves_like 'sends a process_action.action_controller notification', 304
it 'returns empty body' do
diff --git a/spec/lib/gitlab/etag_caching/router_spec.rb b/spec/lib/gitlab/etag_caching/router_spec.rb
index 3e939e588ad..dbd9cc230f1 100644
--- a/spec/lib/gitlab/etag_caching/router_spec.rb
+++ b/spec/lib/gitlab/etag_caching/router_spec.rb
@@ -127,4 +127,12 @@ RSpec.describe Gitlab::EtagCaching::Router do
expect(result).to be_present
expect(result.name).to eq 'project_pipeline'
end
+
+ it 'has a valid feature category for every route', :aggregate_failures do
+ feature_categories = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).to_set
+
+ described_class::ROUTES.each do |route|
+ expect(feature_categories).to include(route.feature_category), "#{route.name} has a category of #{route.feature_category}, which is not valid"
+ end
+ end
end
diff --git a/spec/lib/gitlab/exclusive_lease_helpers_spec.rb b/spec/lib/gitlab/exclusive_lease_helpers_spec.rb
index 40669f06371..8bf06bcebe2 100644
--- a/spec/lib/gitlab/exclusive_lease_helpers_spec.rb
+++ b/spec/lib/gitlab/exclusive_lease_helpers_spec.rb
@@ -88,7 +88,7 @@ RSpec.describe Gitlab::ExclusiveLeaseHelpers, :clean_gitlab_redis_shared_state d
let(:options) { { retries: 0 } }
it 'never sleeps' do
- expect(class_instance).not_to receive(:sleep)
+ expect_any_instance_of(Gitlab::ExclusiveLeaseHelpers::SleepingLock).not_to receive(:sleep)
expect { subject }.to raise_error('Failed to obtain a lock')
end
@@ -98,7 +98,7 @@ RSpec.describe Gitlab::ExclusiveLeaseHelpers, :clean_gitlab_redis_shared_state d
let(:options) { { retries: 1, sleep_sec: 0.05.seconds } }
it 'receives the specified argument' do
- expect_any_instance_of(Object).to receive(:sleep).with(0.05.seconds).once
+ expect_any_instance_of(Gitlab::ExclusiveLeaseHelpers::SleepingLock).to receive(:sleep).with(0.05.seconds).once
expect { subject }.to raise_error('Failed to obtain a lock')
end
@@ -108,8 +108,8 @@ RSpec.describe Gitlab::ExclusiveLeaseHelpers, :clean_gitlab_redis_shared_state d
let(:options) { { retries: 2, sleep_sec: ->(num) { 0.1 + num } } }
it 'receives the specified argument' do
- expect_any_instance_of(Object).to receive(:sleep).with(1.1.seconds).once
- expect_any_instance_of(Object).to receive(:sleep).with(2.1.seconds).once
+ expect_any_instance_of(Gitlab::ExclusiveLeaseHelpers::SleepingLock).to receive(:sleep).with(1.1.seconds).once
+ expect_any_instance_of(Gitlab::ExclusiveLeaseHelpers::SleepingLock).to receive(:sleep).with(2.1.seconds).once
expect { subject }.to raise_error('Failed to obtain a lock')
end
diff --git a/spec/lib/gitlab/experimentation/controller_concern_spec.rb b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
new file mode 100644
index 00000000000..2fe3d36daf7
--- /dev/null
+++ b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
@@ -0,0 +1,438 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
+ before do
+ stub_const('Gitlab::Experimentation::EXPERIMENTS', {
+ backwards_compatible_test_experiment: {
+ environment: environment,
+ tracking_category: 'Team',
+ use_backwards_compatible_subject_index: true
+ },
+ test_experiment: {
+ environment: environment,
+ tracking_category: 'Team'
+ }
+ }
+ )
+
+ Feature.enable_percentage_of_time(:backwards_compatible_test_experiment_experiment_percentage, enabled_percentage)
+ Feature.enable_percentage_of_time(:test_experiment_experiment_percentage, enabled_percentage)
+ end
+
+ let(:environment) { Rails.env.test? }
+ let(:enabled_percentage) { 10 }
+
+ controller(ApplicationController) do
+ include Gitlab::Experimentation::ControllerConcern
+
+ def index
+ head :ok
+ end
+ end
+
+ describe '#set_experimentation_subject_id_cookie' do
+ let(:do_not_track) { nil }
+ let(:cookie) { cookies.permanent.signed[:experimentation_subject_id] }
+
+ before do
+ request.headers['DNT'] = do_not_track if do_not_track.present?
+
+ get :index
+ end
+
+ context 'cookie is present' do
+ before do
+ cookies[:experimentation_subject_id] = 'test'
+ end
+
+ it 'does not change the cookie' do
+ expect(cookies[:experimentation_subject_id]).to eq 'test'
+ end
+ end
+
+ context 'cookie is not present' do
+ it 'sets a permanent signed cookie' do
+ expect(cookie).to be_present
+ end
+
+ context 'DNT: 0' do
+ let(:do_not_track) { '0' }
+
+ it 'sets a permanent signed cookie' do
+ expect(cookie).to be_present
+ end
+ end
+
+ context 'DNT: 1' do
+ let(:do_not_track) { '1' }
+
+ it 'does nothing' do
+ expect(cookie).not_to be_present
+ end
+ end
+ end
+ end
+
+ describe '#push_frontend_experiment' do
+ it 'pushes an experiment to the frontend' do
+ gon = instance_double('gon')
+ experiments = { experiments: { 'myExperiment' => true } }
+
+ stub_experiment_for_user(my_experiment: true)
+ allow(controller).to receive(:gon).and_return(gon)
+
+ expect(gon).to receive(:push).with(experiments, true)
+
+ controller.push_frontend_experiment(:my_experiment)
+ end
+ end
+
+ describe '#experiment_enabled?' do
+ def check_experiment(exp_key = :test_experiment)
+ controller.experiment_enabled?(exp_key)
+ end
+
+ subject { check_experiment }
+
+ context 'cookie is not present' do
+ it 'calls Gitlab::Experimentation.enabled_for_value? with the name of the experiment and an experimentation_subject_index of nil' do
+ expect(Gitlab::Experimentation).to receive(:enabled_for_value?).with(:test_experiment, nil)
+ check_experiment
+ end
+ end
+
+ context 'cookie is present' do
+ using RSpec::Parameterized::TableSyntax
+
+ before do
+ cookies.permanent.signed[:experimentation_subject_id] = 'abcd-1234'
+ get :index
+ end
+
+ where(:experiment_key, :index_value) do
+ :test_experiment | 40 # Zlib.crc32('test_experimentabcd-1234') % 100 = 40
+ :backwards_compatible_test_experiment | 76 # 'abcd1234'.hex % 100 = 76
+ end
+
+ with_them do
+ it 'calls Gitlab::Experimentation.enabled_for_value? with the name of the experiment and the calculated experimentation_subject_index based on the uuid' do
+ expect(Gitlab::Experimentation).to receive(:enabled_for_value?).with(experiment_key, index_value)
+ check_experiment(experiment_key)
+ end
+ end
+ end
+
+ it 'returns true when DNT: 0 is set in the request' do
+ allow(Gitlab::Experimentation).to receive(:enabled_for_value?) { true }
+ controller.request.headers['DNT'] = '0'
+
+ is_expected.to be_truthy
+ end
+
+ it 'returns false when DNT: 1 is set in the request' do
+ allow(Gitlab::Experimentation).to receive(:enabled_for_value?) { true }
+ controller.request.headers['DNT'] = '1'
+
+ is_expected.to be_falsy
+ end
+
+ describe 'URL parameter to force enable experiment' do
+ it 'returns true unconditionally' do
+ get :index, params: { force_experiment: :test_experiment }
+
+ is_expected.to be_truthy
+ end
+ end
+ end
+
+ describe '#track_experiment_event', :snowplow do
+ context 'when the experiment is enabled' do
+ before do
+ stub_experiment(test_experiment: true)
+ end
+
+ context 'the user is part of the experimental group' do
+ before do
+ stub_experiment_for_user(test_experiment: true)
+ end
+
+ it 'tracks the event with the right parameters' do
+ controller.track_experiment_event(:test_experiment, 'start', 1)
+
+ expect_snowplow_event(
+ category: 'Team',
+ action: 'start',
+ property: 'experimental_group',
+ value: 1
+ )
+ end
+ end
+
+ context 'the user is part of the control group' do
+ before do
+ stub_experiment_for_user(test_experiment: false)
+ end
+
+ it 'tracks the event with the right parameters' do
+ controller.track_experiment_event(:test_experiment, 'start', 1)
+
+ expect_snowplow_event(
+ category: 'Team',
+ action: 'start',
+ property: 'control_group',
+ value: 1
+ )
+ end
+ end
+
+ context 'do not track is disabled' do
+ before do
+ request.headers['DNT'] = '0'
+ end
+
+ it 'does track the event' do
+ controller.track_experiment_event(:test_experiment, 'start', 1)
+
+ expect_snowplow_event(
+ category: 'Team',
+ action: 'start',
+ property: 'control_group',
+ value: 1
+ )
+ end
+ end
+
+ context 'do not track enabled' do
+ before do
+ request.headers['DNT'] = '1'
+ end
+
+ it 'does not track the event' do
+ controller.track_experiment_event(:test_experiment, 'start', 1)
+
+ expect_no_snowplow_event
+ end
+ end
+ end
+
+ context 'when the experiment is disabled' do
+ before do
+ stub_experiment(test_experiment: false)
+ end
+
+ it 'does not track the event' do
+ controller.track_experiment_event(:test_experiment, 'start')
+
+ expect_no_snowplow_event
+ end
+ end
+ end
+
+ describe '#frontend_experimentation_tracking_data' do
+ context 'when the experiment is enabled' do
+ before do
+ stub_experiment(test_experiment: true)
+ end
+
+ context 'the user is part of the experimental group' do
+ before do
+ stub_experiment_for_user(test_experiment: true)
+ end
+
+ it 'pushes the right parameters to gon' do
+ controller.frontend_experimentation_tracking_data(:test_experiment, 'start', 'team_id')
+ expect(Gon.tracking_data).to eq(
+ {
+ category: 'Team',
+ action: 'start',
+ property: 'experimental_group',
+ value: 'team_id'
+ }
+ )
+ end
+ end
+
+ context 'the user is part of the control group' do
+ before do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:experiment_enabled?).with(:test_experiment).and_return(false)
+ end
+ end
+
+ it 'pushes the right parameters to gon' do
+ controller.frontend_experimentation_tracking_data(:test_experiment, 'start', 'team_id')
+ expect(Gon.tracking_data).to eq(
+ {
+ category: 'Team',
+ action: 'start',
+ property: 'control_group',
+ value: 'team_id'
+ }
+ )
+ end
+
+ it 'does not send nil value to gon' do
+ controller.frontend_experimentation_tracking_data(:test_experiment, 'start')
+ expect(Gon.tracking_data).to eq(
+ {
+ category: 'Team',
+ action: 'start',
+ property: 'control_group'
+ }
+ )
+ end
+ end
+
+ context 'do not track disabled' do
+ before do
+ request.headers['DNT'] = '0'
+ end
+
+ it 'pushes the right parameters to gon' do
+ controller.frontend_experimentation_tracking_data(:test_experiment, 'start')
+
+ expect(Gon.tracking_data).to eq(
+ {
+ category: 'Team',
+ action: 'start',
+ property: 'control_group'
+ }
+ )
+ end
+ end
+
+ context 'do not track enabled' do
+ before do
+ request.headers['DNT'] = '1'
+ end
+
+ it 'does not push data to gon' do
+ controller.frontend_experimentation_tracking_data(:test_experiment, 'start')
+
+ expect(Gon.method_defined?(:tracking_data)).to be_falsey
+ end
+ end
+ end
+
+ context 'when the experiment is disabled' do
+ before do
+ stub_experiment(test_experiment: false)
+ end
+
+ it 'does not push data to gon' do
+ expect(Gon.method_defined?(:tracking_data)).to be_falsey
+ controller.track_experiment_event(:test_experiment, 'start')
+ end
+ end
+ end
+
+ describe '#record_experiment_user' do
+ let(:user) { build(:user) }
+
+ context 'when the experiment is enabled' do
+ before do
+ stub_experiment(test_experiment: true)
+ allow(controller).to receive(:current_user).and_return(user)
+ end
+
+ context 'the user is part of the experimental group' do
+ before do
+ stub_experiment_for_user(test_experiment: true)
+ end
+
+ it 'calls add_user on the Experiment model' do
+ expect(::Experiment).to receive(:add_user).with(:test_experiment, :experimental, user)
+
+ controller.record_experiment_user(:test_experiment)
+ end
+ end
+
+ context 'the user is part of the control group' do
+ before do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:experiment_enabled?).with(:test_experiment).and_return(false)
+ end
+ end
+
+ it 'calls add_user on the Experiment model' do
+ expect(::Experiment).to receive(:add_user).with(:test_experiment, :control, user)
+
+ controller.record_experiment_user(:test_experiment)
+ end
+ end
+ end
+
+ context 'when the experiment is disabled' do
+ before do
+ stub_experiment(test_experiment: false)
+ allow(controller).to receive(:current_user).and_return(user)
+ end
+
+ it 'does not call add_user on the Experiment model' do
+ expect(::Experiment).not_to receive(:add_user)
+
+ controller.record_experiment_user(:test_experiment)
+ end
+ end
+
+ context 'when there is no current_user' do
+ before do
+ stub_experiment(test_experiment: true)
+ end
+
+ it 'does not call add_user on the Experiment model' do
+ expect(::Experiment).not_to receive(:add_user)
+
+ controller.record_experiment_user(:test_experiment)
+ end
+ end
+
+ context 'do not track' do
+ before do
+ allow(controller).to receive(:current_user).and_return(user)
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:experiment_enabled?).with(:test_experiment).and_return(false)
+ end
+ end
+
+ context 'is disabled' do
+ before do
+ request.headers['DNT'] = '0'
+ end
+
+ it 'calls add_user on the Experiment model' do
+ expect(::Experiment).to receive(:add_user).with(:test_experiment, :control, user)
+
+ controller.record_experiment_user(:test_experiment)
+ end
+ end
+
+ context 'is enabled' do
+ before do
+ request.headers['DNT'] = '1'
+ end
+
+ it 'does not call add_user on the Experiment model' do
+ expect(::Experiment).not_to receive(:add_user)
+
+ controller.record_experiment_user(:test_experiment)
+ end
+ 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
diff --git a/spec/lib/gitlab/experimentation/group_types_spec.rb b/spec/lib/gitlab/experimentation/group_types_spec.rb
new file mode 100644
index 00000000000..599ad08f706
--- /dev/null
+++ b/spec/lib/gitlab/experimentation/group_types_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Experimentation::GroupTypes do
+ it 'defines a GROUP_CONTROL constant' do
+ expect(described_class.const_defined?(:GROUP_CONTROL)).to be_truthy
+ end
+
+ it 'defines a GROUP_EXPERIMENTAL constant' do
+ expect(described_class.const_defined?(:GROUP_EXPERIMENTAL)).to be_truthy
+ end
+end
diff --git a/spec/lib/gitlab/experimentation_spec.rb b/spec/lib/gitlab/experimentation_spec.rb
index e93593d348f..ebf98a0151f 100644
--- a/spec/lib/gitlab/experimentation_spec.rb
+++ b/spec/lib/gitlab/experimentation_spec.rb
@@ -2,423 +2,54 @@
require 'spec_helper'
+# As each associated, backwards-compatible experiment gets cleaned up and removed from the EXPERIMENTS list, its key will also get removed from this list. Once the list here is empty, we can remove the backwards compatibility code altogether.
+# Originally created as part of https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45733 for https://gitlab.com/gitlab-org/gitlab/-/issues/270858.
+RSpec.describe Gitlab::Experimentation::EXPERIMENTS do
+ it 'temporarily ensures we know what experiments exist for backwards compatibility' do
+ expected_experiment_keys = [
+ :onboarding_issues,
+ :ci_notification_dot,
+ :upgrade_link_in_user_menu_a,
+ :invite_members_version_a,
+ :invite_members_version_b,
+ :invite_members_empty_group_version_a,
+ :new_create_project_ui,
+ :contact_sales_btn_in_app,
+ :customize_homepage,
+ :invite_email,
+ :invitation_reminders,
+ :group_only_trials,
+ :default_to_issues_board
+ ]
+
+ backwards_compatible_experiment_keys = described_class.filter { |_, v| v[:use_backwards_compatible_subject_index] }.keys
+
+ expect(backwards_compatible_experiment_keys).not_to be_empty, "Oh, hey! Let's clean up that :use_backwards_compatible_subject_index stuff now :D"
+ expect(backwards_compatible_experiment_keys).to match(expected_experiment_keys)
+ end
+end
+
RSpec.describe Gitlab::Experimentation, :snowplow do
before do
stub_const('Gitlab::Experimentation::EXPERIMENTS', {
+ backwards_compatible_test_experiment: {
+ environment: environment,
+ tracking_category: 'Team',
+ use_backwards_compatible_subject_index: true
+ },
test_experiment: {
environment: environment,
tracking_category: 'Team'
}
})
+ Feature.enable_percentage_of_time(:backwards_compatible_test_experiment_experiment_percentage, enabled_percentage)
Feature.enable_percentage_of_time(:test_experiment_experiment_percentage, enabled_percentage)
end
let(:environment) { Rails.env.test? }
let(:enabled_percentage) { 10 }
- describe Gitlab::Experimentation::ControllerConcern, type: :controller do
- controller(ApplicationController) do
- include Gitlab::Experimentation::ControllerConcern
-
- def index
- head :ok
- end
- end
-
- describe '#set_experimentation_subject_id_cookie' do
- let(:do_not_track) { nil }
- let(:cookie) { cookies.permanent.signed[:experimentation_subject_id] }
-
- before do
- request.headers['DNT'] = do_not_track if do_not_track.present?
-
- get :index
- end
-
- context 'cookie is present' do
- before do
- cookies[:experimentation_subject_id] = 'test'
- end
-
- it 'does not change the cookie' do
- expect(cookies[:experimentation_subject_id]).to eq 'test'
- end
- end
-
- context 'cookie is not present' do
- it 'sets a permanent signed cookie' do
- expect(cookie).to be_present
- end
-
- context 'DNT: 0' do
- let(:do_not_Track) { '0' }
-
- it 'sets a permanent signed cookie' do
- expect(cookie).to be_present
- end
- end
-
- context 'DNT: 1' do
- let(:do_not_track) { '1' }
-
- it 'does nothing' do
- expect(cookie).not_to be_present
- end
- end
- end
- end
-
- describe '#push_frontend_experiment' do
- it 'pushes an experiment to the frontend' do
- gon = instance_double('gon')
- experiments = { experiments: { 'myExperiment' => true } }
-
- stub_experiment_for_user(my_experiment: true)
- allow(controller).to receive(:gon).and_return(gon)
-
- expect(gon).to receive(:push).with(experiments, true)
-
- controller.push_frontend_experiment(:my_experiment)
- end
- end
-
- describe '#experiment_enabled?' do
- subject { controller.experiment_enabled?(:test_experiment) }
-
- context 'cookie is not present' do
- it 'calls Gitlab::Experimentation.enabled_for_value? with the name of the experiment and an experimentation_subject_index of nil' do
- expect(Gitlab::Experimentation).to receive(:enabled_for_value?).with(:test_experiment, nil)
- controller.experiment_enabled?(:test_experiment)
- end
- end
-
- context 'cookie is present' do
- before do
- cookies.permanent.signed[:experimentation_subject_id] = 'abcd-1234'
- get :index
- end
-
- it 'calls Gitlab::Experimentation.enabled_for_value? with the name of the experiment and an experimentation_subject_index of the modulo 100 of the hex value of the uuid' do
- # 'abcd1234'.hex % 100 = 76
- expect(Gitlab::Experimentation).to receive(:enabled_for_value?).with(:test_experiment, 76)
- controller.experiment_enabled?(:test_experiment)
- end
- end
-
- it 'returns true when DNT: 0 is set in the request' do
- allow(Gitlab::Experimentation).to receive(:enabled_for_value?) { true }
- controller.request.headers['DNT'] = '0'
-
- is_expected.to be_truthy
- end
-
- it 'returns false when DNT: 1 is set in the request' do
- allow(Gitlab::Experimentation).to receive(:enabled_for_value?) { true }
- controller.request.headers['DNT'] = '1'
-
- is_expected.to be_falsy
- end
-
- describe 'URL parameter to force enable experiment' do
- it 'returns true unconditionally' do
- get :index, params: { force_experiment: :test_experiment }
-
- is_expected.to be_truthy
- end
- end
- end
-
- describe '#track_experiment_event' do
- context 'when the experiment is enabled' do
- before do
- stub_experiment(test_experiment: true)
- end
-
- context 'the user is part of the experimental group' do
- before do
- stub_experiment_for_user(test_experiment: true)
- end
-
- it 'tracks the event with the right parameters' do
- controller.track_experiment_event(:test_experiment, 'start', 1)
-
- expect_snowplow_event(
- category: 'Team',
- action: 'start',
- property: 'experimental_group',
- value: 1
- )
- end
- end
-
- context 'the user is part of the control group' do
- before do
- stub_experiment_for_user(test_experiment: false)
- end
-
- it 'tracks the event with the right parameters' do
- controller.track_experiment_event(:test_experiment, 'start', 1)
-
- expect_snowplow_event(
- category: 'Team',
- action: 'start',
- property: 'control_group',
- value: 1
- )
- end
- end
-
- context 'do not track is disabled' do
- before do
- request.headers['DNT'] = '0'
- end
-
- it 'does track the event' do
- controller.track_experiment_event(:test_experiment, 'start', 1)
-
- expect_snowplow_event(
- category: 'Team',
- action: 'start',
- property: 'control_group',
- value: 1
- )
- end
- end
-
- context 'do not track enabled' do
- before do
- request.headers['DNT'] = '1'
- end
-
- it 'does not track the event' do
- controller.track_experiment_event(:test_experiment, 'start', 1)
-
- expect_no_snowplow_event
- end
- end
- end
-
- context 'when the experiment is disabled' do
- before do
- stub_experiment(test_experiment: false)
- end
-
- it 'does not track the event' do
- controller.track_experiment_event(:test_experiment, 'start')
-
- expect_no_snowplow_event
- end
- end
- end
-
- describe '#frontend_experimentation_tracking_data' do
- context 'when the experiment is enabled' do
- before do
- stub_experiment(test_experiment: true)
- end
-
- context 'the user is part of the experimental group' do
- before do
- stub_experiment_for_user(test_experiment: true)
- end
-
- it 'pushes the right parameters to gon' do
- controller.frontend_experimentation_tracking_data(:test_experiment, 'start', 'team_id')
- expect(Gon.tracking_data).to eq(
- {
- category: 'Team',
- action: 'start',
- property: 'experimental_group',
- value: 'team_id'
- }
- )
- end
- end
-
- context 'the user is part of the control group' do
- before do
- allow_next_instance_of(described_class) do |instance|
- allow(instance).to receive(:experiment_enabled?).with(:test_experiment).and_return(false)
- end
- end
-
- it 'pushes the right parameters to gon' do
- controller.frontend_experimentation_tracking_data(:test_experiment, 'start', 'team_id')
- expect(Gon.tracking_data).to eq(
- {
- category: 'Team',
- action: 'start',
- property: 'control_group',
- value: 'team_id'
- }
- )
- end
-
- it 'does not send nil value to gon' do
- controller.frontend_experimentation_tracking_data(:test_experiment, 'start')
- expect(Gon.tracking_data).to eq(
- {
- category: 'Team',
- action: 'start',
- property: 'control_group'
- }
- )
- end
- end
-
- context 'do not track disabled' do
- before do
- request.headers['DNT'] = '0'
- end
-
- it 'pushes the right parameters to gon' do
- controller.frontend_experimentation_tracking_data(:test_experiment, 'start')
-
- expect(Gon.tracking_data).to eq(
- {
- category: 'Team',
- action: 'start',
- property: 'control_group'
- }
- )
- end
- end
-
- context 'do not track enabled' do
- before do
- request.headers['DNT'] = '1'
- end
-
- it 'does not push data to gon' do
- controller.frontend_experimentation_tracking_data(:test_experiment, 'start')
-
- expect(Gon.method_defined?(:tracking_data)).to be_falsey
- end
- end
- end
-
- context 'when the experiment is disabled' do
- before do
- stub_experiment(test_experiment: false)
- end
-
- it 'does not push data to gon' do
- expect(Gon.method_defined?(:tracking_data)).to be_falsey
- controller.track_experiment_event(:test_experiment, 'start')
- end
- end
- end
-
- describe '#record_experiment_user' do
- let(:user) { build(:user) }
-
- context 'when the experiment is enabled' do
- before do
- stub_experiment(test_experiment: true)
- allow(controller).to receive(:current_user).and_return(user)
- end
-
- context 'the user is part of the experimental group' do
- before do
- stub_experiment_for_user(test_experiment: true)
- end
-
- it 'calls add_user on the Experiment model' do
- expect(::Experiment).to receive(:add_user).with(:test_experiment, :experimental, user)
-
- controller.record_experiment_user(:test_experiment)
- end
- end
-
- context 'the user is part of the control group' do
- before do
- allow_next_instance_of(described_class) do |instance|
- allow(instance).to receive(:experiment_enabled?).with(:test_experiment).and_return(false)
- end
- end
-
- it 'calls add_user on the Experiment model' do
- expect(::Experiment).to receive(:add_user).with(:test_experiment, :control, user)
-
- controller.record_experiment_user(:test_experiment)
- end
- end
- end
-
- context 'when the experiment is disabled' do
- before do
- stub_experiment(test_experiment: false)
- allow(controller).to receive(:current_user).and_return(user)
- end
-
- it 'does not call add_user on the Experiment model' do
- expect(::Experiment).not_to receive(:add_user)
-
- controller.record_experiment_user(:test_experiment)
- end
- end
-
- context 'when there is no current_user' do
- before do
- stub_experiment(test_experiment: true)
- end
-
- it 'does not call add_user on the Experiment model' do
- expect(::Experiment).not_to receive(:add_user)
-
- controller.record_experiment_user(:test_experiment)
- end
- end
-
- context 'do not track' do
- before do
- allow(controller).to receive(:current_user).and_return(user)
- allow_next_instance_of(described_class) do |instance|
- allow(instance).to receive(:experiment_enabled?).with(:test_experiment).and_return(false)
- end
- end
-
- context 'is disabled' do
- before do
- request.headers['DNT'] = '0'
- end
-
- it 'calls add_user on the Experiment model' do
- expect(::Experiment).to receive(:add_user).with(:test_experiment, :control, user)
-
- controller.record_experiment_user(:test_experiment)
- end
- end
-
- context 'is enabled' do
- before do
- request.headers['DNT'] = '1'
- end
-
- it 'does not call add_user on the Experiment model' do
- expect(::Experiment).not_to receive(:add_user)
-
- controller.record_experiment_user(:test_experiment)
- end
- 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
subject { described_class.enabled?(:test_experiment) }
@@ -442,6 +73,14 @@ RSpec.describe Gitlab::Experimentation, :snowplow do
let(:environment) { ::Gitlab.com? }
it { is_expected.to be_falsey }
+
+ it 'ensures the typically less expensive environment is checked before the more expensive call to database for Feature' do
+ expect_next_instance_of(described_class::Experiment) do |experiment|
+ expect(experiment).not_to receive(:enabled?)
+ end
+
+ subject
+ end
end
end
diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb
index 980a52bb61e..d4174a34433 100644
--- a/spec/lib/gitlab/git/diff_spec.rb
+++ b/spec/lib/gitlab/git/diff_spec.rb
@@ -301,19 +301,19 @@ EOT
describe '#too_large?' do
it 'returns true for a diff that is too large' do
- diff = described_class.new(diff: 'a' * 204800)
+ diff = described_class.new({ diff: 'a' * 204800 })
expect(diff.too_large?).to eq(true)
end
it 'returns false for a diff that is small enough' do
- diff = described_class.new(diff: 'a')
+ diff = described_class.new({ diff: 'a' })
expect(diff.too_large?).to eq(false)
end
it 'returns true for a diff that was explicitly marked as being too large' do
- diff = described_class.new(diff: 'a')
+ diff = described_class.new({ diff: 'a' })
diff.too_large!
@@ -323,19 +323,19 @@ EOT
describe '#collapsed?' do
it 'returns false by default even on quite big diff' do
- diff = described_class.new(diff: 'a' * 20480)
+ diff = described_class.new({ diff: 'a' * 20480 })
expect(diff).not_to be_collapsed
end
it 'returns false by default for a diff that is small enough' do
- diff = described_class.new(diff: 'a')
+ diff = described_class.new({ diff: 'a' })
expect(diff).not_to be_collapsed
end
it 'returns true for a diff that was explicitly marked as being collapsed' do
- diff = described_class.new(diff: 'a')
+ diff = described_class.new({ diff: 'a' })
diff.collapse!
@@ -359,7 +359,7 @@ EOT
describe '#collapse!' do
it 'prunes the diff' do
- diff = described_class.new(diff: "foo\nbar")
+ diff = described_class.new({ diff: "foo\nbar" })
diff.collapse!
diff --git a/spec/lib/gitlab/git_access_snippet_spec.rb b/spec/lib/gitlab/git_access_snippet_spec.rb
index 8c481cdee08..f5d8758a78a 100644
--- a/spec/lib/gitlab/git_access_snippet_spec.rb
+++ b/spec/lib/gitlab/git_access_snippet_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::GitAccessSnippet do
include ProjectHelpers
include TermsHelper
+ include AdminModeHelper
include_context 'ProjectPolicyTable context'
using RSpec::Parameterized::TableSyntax
@@ -207,12 +208,13 @@ RSpec.describe Gitlab::GitAccessSnippet do
let(:snippet) { create(:personal_snippet, snippet_level, :repository) }
let(:user) { membership == :author ? snippet.author : create_user_from_membership(nil, membership) }
- where(:snippet_level, :membership, :_expected_count) do
+ where(:snippet_level, :membership, :admin_mode, :_expected_count) do
permission_table_for_personal_snippet_access
end
with_them do
it "respects accessibility" do
+ enable_admin_mode!(user) if admin_mode
error_class = described_class::ForbiddenError
if Ability.allowed?(user, :update_snippet, snippet)
diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
index f977fe1638f..b09bd9dff1b 100644
--- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe Gitlab::GitalyClient::CommitService do
safe_max_files: 100,
safe_max_lines: 5000,
safe_max_bytes: 512000,
- max_patch_bytes: 102400
+ max_patch_bytes: 204800
)
expect_any_instance_of(Gitaly::DiffService::Stub).to receive(:commit_diff).with(request, kind_of(Hash))
@@ -57,7 +57,7 @@ RSpec.describe Gitlab::GitalyClient::CommitService do
safe_max_files: 100,
safe_max_lines: 5000,
safe_max_bytes: 512000,
- max_patch_bytes: 102400
+ max_patch_bytes: 204800
)
expect_any_instance_of(Gitaly::DiffService::Stub).to receive(:commit_diff).with(request, kind_of(Hash))
diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
index c7ea0a95596..f810a5c15a5 100644
--- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
.with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
.and_return(double(:garbage_collect_response))
- client.garbage_collect(true)
+ client.garbage_collect(true, prune: true)
end
end
diff --git a/spec/lib/gitlab/github_import/client_spec.rb b/spec/lib/gitlab/github_import/client_spec.rb
index 5f6ab42d0d2..bc734644d29 100644
--- a/spec/lib/gitlab/github_import/client_spec.rb
+++ b/spec/lib/gitlab/github_import/client_spec.rb
@@ -203,16 +203,40 @@ RSpec.describe Gitlab::GithubImport::Client do
describe '#requests_remaining?' do
let(:client) { described_class.new('foo') }
- it 'returns true if enough requests remain' do
- expect(client).to receive(:remaining_requests).and_return(9000)
+ context 'when default requests limit is set' do
+ before do
+ allow(client).to receive(:requests_limit).and_return(5000)
+ end
+
+ it 'returns true if enough requests remain' do
+ expect(client).to receive(:remaining_requests).and_return(9000)
+
+ expect(client.requests_remaining?).to eq(true)
+ end
+
+ it 'returns false if not enough requests remain' do
+ expect(client).to receive(:remaining_requests).and_return(1)
- expect(client.requests_remaining?).to eq(true)
+ expect(client.requests_remaining?).to eq(false)
+ end
end
- it 'returns false if not enough requests remain' do
- expect(client).to receive(:remaining_requests).and_return(1)
+ context 'when search requests limit is set' do
+ before do
+ allow(client).to receive(:requests_limit).and_return(described_class::SEARCH_MAX_REQUESTS_PER_MINUTE)
+ end
+
+ it 'returns true if enough requests remain' do
+ expect(client).to receive(:remaining_requests).and_return(described_class::SEARCH_RATE_LIMIT_THRESHOLD + 1)
+
+ expect(client.requests_remaining?).to eq(true)
+ end
+
+ it 'returns false if not enough requests remain' do
+ expect(client).to receive(:remaining_requests).and_return(described_class::SEARCH_RATE_LIMIT_THRESHOLD - 1)
- expect(client.requests_remaining?).to eq(false)
+ expect(client.requests_remaining?).to eq(false)
+ end
end
end
@@ -262,6 +286,16 @@ RSpec.describe Gitlab::GithubImport::Client do
end
end
+ describe '#requests_limit' do
+ it 'returns requests limit' do
+ client = described_class.new('foo')
+ rate_limit = double(limit: 1)
+
+ expect(client.octokit).to receive(:rate_limit).and_return(rate_limit)
+ expect(client.requests_limit).to eq(1)
+ end
+ end
+
describe '#rate_limit_resets_in' do
it 'returns the number of seconds after which the rate limit is reset' do
client = described_class.new('foo')
@@ -299,6 +333,32 @@ RSpec.describe Gitlab::GithubImport::Client do
end
end
+ describe '#web_endpoint' do
+ let(:client) { described_class.new('foo') }
+
+ context 'without a custom endpoint configured in Omniauth' do
+ it 'returns the default web endpoint' do
+ expect(client)
+ .to receive(:custom_api_endpoint)
+ .and_return(nil)
+
+ expect(client.web_endpoint).to eq('https://github.com')
+ end
+ end
+
+ context 'with a custom endpoint configured in Omniauth' do
+ it 'returns the custom endpoint' do
+ endpoint = 'https://github.kittens.com'
+
+ expect(client)
+ .to receive(:custom_api_endpoint)
+ .and_return(endpoint)
+
+ expect(client.web_endpoint).to eq(endpoint)
+ end
+ end
+ end
+
describe '#custom_api_endpoint' do
let(:client) { described_class.new('foo') }
@@ -391,4 +451,61 @@ RSpec.describe Gitlab::GithubImport::Client do
expect(client.rate_limiting_enabled?).to eq(false)
end
end
+
+ describe 'search' do
+ let(:client) { described_class.new('foo') }
+ let(:user) { double(:user, login: 'user') }
+ let(:org1) { double(:org, login: 'org1') }
+ let(:org2) { double(:org, login: 'org2') }
+ let(:repo1) { double(:repo, full_name: 'repo1') }
+ let(:repo2) { double(:repo, full_name: 'repo2') }
+
+ before do
+ allow(client)
+ .to receive(:each_object)
+ .with(:repos, nil, { affiliation: 'collaborator' })
+ .and_return([repo1, repo2].to_enum)
+
+ allow(client)
+ .to receive(:each_object)
+ .with(:organizations)
+ .and_return([org1, org2].to_enum)
+
+ allow(client.octokit).to receive(:user).and_return(user)
+ end
+
+ describe '#search_repos_by_name' do
+ it 'searches for repositories based on name' do
+ expected_search_query = 'test in:name is:public,private user:user repo:repo1 repo:repo2 org:org1 org:org2'
+
+ expect(client).to receive(:each_page).with(:search_repositories, expected_search_query)
+
+ client.search_repos_by_name('test')
+ end
+ end
+
+ describe '#search_query' do
+ it 'returns base search query' do
+ result = client.search_query(str: 'test', type: :test, include_collaborations: false, include_orgs: false)
+
+ expect(result).to eq('test in:test is:public,private user:user')
+ end
+
+ context 'when include_collaborations is true' do
+ it 'returns search query including users' do
+ result = client.search_query(str: 'test', type: :test, include_collaborations: true, include_orgs: false)
+
+ expect(result).to eq('test in:test is:public,private user:user repo:repo1 repo:repo2')
+ end
+ end
+
+ context 'when include_orgs is true' do
+ it 'returns search query including users' do
+ result = client.search_query(str: 'test', type: :test, include_collaborations: false, include_orgs: true)
+
+ expect(result).to eq('test in:test is:public,private user:user org:org1 org:org2')
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/github_import/importer/lfs_object_importer_spec.rb b/spec/lib/gitlab/github_import/importer/lfs_object_importer_spec.rb
index add554992f1..188c56ae81f 100644
--- a/spec/lib/gitlab/github_import/importer/lfs_object_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/lfs_object_importer_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Gitlab::GithubImport::Importer::LfsObjectImporter do
}
end
- let(:lfs_download_object) { LfsDownloadObject.new(lfs_attributes) }
+ let(:lfs_download_object) { LfsDownloadObject.new(**lfs_attributes) }
let(:github_lfs_object) { Gitlab::GithubImport::Representation::LfsObject.new(lfs_attributes) }
let(:importer) { described_class.new(github_lfs_object, project, nil) }
diff --git a/spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb b/spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb
index 1f7b14661c2..6188ba8ec3f 100644
--- a/spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Gitlab::GithubImport::Importer::LfsObjectsImporter do
}
end
- let(:lfs_download_object) { LfsDownloadObject.new(lfs_attributes) }
+ let(:lfs_download_object) { LfsDownloadObject.new(**lfs_attributes) }
describe '#parallel?' do
it 'returns true when running in parallel mode' do
diff --git a/spec/lib/gitlab/github_import/sequential_importer_spec.rb b/spec/lib/gitlab/github_import/sequential_importer_spec.rb
index fe13fcd2568..a5e89049ed9 100644
--- a/spec/lib/gitlab/github_import/sequential_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/sequential_importer_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::GithubImport::SequentialImporter do
describe '#execute' do
it 'imports a project in sequence' do
repository = double(:repository)
- project = double(:project, id: 1, repository: repository)
+ project = double(:project, id: 1, repository: repository, import_url: 'http://t0ken@github.another-domain.com/repo-org/repo.git')
importer = described_class.new(project, token: 'foo')
expect_next_instance_of(Gitlab::GithubImport::Importer::RepositoryImporter) do |instance|
diff --git a/spec/lib/gitlab/github_import_spec.rb b/spec/lib/gitlab/github_import_spec.rb
index 1a690b81d2b..3129da64809 100644
--- a/spec/lib/gitlab/github_import_spec.rb
+++ b/spec/lib/gitlab/github_import_spec.rb
@@ -3,13 +3,13 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport do
- let(:project) { double(:project) }
+ context 'github.com' do
+ let(:project) { double(:project, import_url: 'http://t0ken@github.com/user/repo.git') }
- describe '.new_client_for' do
it 'returns a new Client with a custom token' do
expect(described_class::Client)
.to receive(:new)
- .with('123', parallel: true)
+ .with('123', host: nil, parallel: true)
described_class.new_client_for(project, token: '123')
end
@@ -23,18 +23,57 @@ RSpec.describe Gitlab::GithubImport do
expect(described_class::Client)
.to receive(:new)
- .with('123', parallel: true)
+ .with('123', host: nil, parallel: true)
described_class.new_client_for(project)
end
+
+ it 'returns the ID of the ghost user', :clean_gitlab_redis_cache do
+ expect(described_class.ghost_user_id).to eq(User.ghost.id)
+ end
+
+ it 'caches the ghost user ID', :clean_gitlab_redis_cache do
+ expect(Gitlab::Cache::Import::Caching)
+ .to receive(:write)
+ .once
+ .and_call_original
+
+ 2.times do
+ described_class.ghost_user_id
+ end
+ end
end
- describe '.ghost_user_id', :clean_gitlab_redis_cache do
- it 'returns the ID of the ghost user' do
+ context 'GitHub Enterprise' do
+ let(:project) { double(:project, import_url: 'http://t0ken@github.another-domain.com/repo-org/repo.git') }
+
+ it 'returns a new Client with a custom token' do
+ expect(described_class::Client)
+ .to receive(:new)
+ .with('123', host: 'http://github.another-domain.com/api/v3', parallel: true)
+
+ described_class.new_client_for(project, token: '123')
+ end
+
+ it 'returns a new Client with a token stored in the import data' do
+ import_data = double(:import_data, credentials: { user: '123' })
+
+ expect(project)
+ .to receive(:import_data)
+ .and_return(import_data)
+
+ expect(described_class::Client)
+ .to receive(:new)
+ .with('123', host: 'http://github.another-domain.com/api/v3', parallel: true)
+
+ described_class.new_client_for(project)
+ end
+
+ it 'returns the ID of the ghost user', :clean_gitlab_redis_cache do
expect(described_class.ghost_user_id).to eq(User.ghost.id)
end
- it 'caches the ghost user ID' do
+ it 'caches the ghost user ID', :clean_gitlab_redis_cache do
expect(Gitlab::Cache::Import::Caching)
.to receive(:write)
.once
@@ -44,5 +83,9 @@ RSpec.describe Gitlab::GithubImport do
described_class.ghost_user_id
end
end
+
+ it 'formats the import url' do
+ expect(described_class.formatted_import_url(project)).to eq('http://github.another-domain.com/api/v3')
+ end
end
end
diff --git a/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb b/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb
index 91299de0751..487b19a98e0 100644
--- a/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb
+++ b/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb
@@ -15,7 +15,8 @@ RSpec.describe Gitlab::GrapeLogging::Formatters::LogrageWithTimestamp do
path: '/api/v4/projects/1',
params: {
'description': '[FILTERED]',
- 'name': 'gitlab test'
+ 'name': 'gitlab test',
+ 'int': 42
},
host: 'localhost',
remote_ip: '127.0.0.1',
@@ -44,7 +45,8 @@ RSpec.describe Gitlab::GrapeLogging::Formatters::LogrageWithTimestamp do
expect(params).to eq([
{ 'key' => 'description', 'value' => '[FILTERED]' },
- { 'key' => 'name', 'value' => 'gitlab test' }
+ { 'key' => 'name', 'value' => 'gitlab test' },
+ { 'key' => 'int', 'value' => 42 }
])
end
end
diff --git a/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb b/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb
index 7576523ce52..c88506899cd 100644
--- a/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb
+++ b/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb
@@ -27,13 +27,17 @@ RSpec.describe Gitlab::Graphql::Authorize::AuthorizeFieldService do
end
end
+ def resolve
+ service.authorized_resolve[type_instance, {}, context]
+ end
+
subject(:service) { described_class.new(field) }
describe '#authorized_resolve' do
let_it_be(:current_user) { build(:user) }
let_it_be(:presented_object) { 'presented object' }
let_it_be(:query_type) { GraphQL::ObjectType.new }
- let_it_be(:schema) { GraphQL::Schema.define(query: query_type, mutation: nil)}
+ let_it_be(:schema) { GitlabSchema }
let_it_be(:query) { GraphQL::Query.new(schema, document: nil, context: {}, variables: {}) }
let_it_be(:context) { GraphQL::Query::Context.new(query: query, values: { current_user: current_user }, object: nil) }
@@ -41,125 +45,201 @@ RSpec.describe Gitlab::Graphql::Authorize::AuthorizeFieldService do
let(:type_instance) { type_class.authorized_new(presented_object, context) }
let(:field) { type_class.fields['testField'].to_graphql }
- subject(:resolved) { service.authorized_resolve.call(type_instance, {}, context) }
+ subject(:resolved) { ::Gitlab::Graphql::Lazy.force(resolve) }
- context 'scalar types' do
- shared_examples 'checking permissions on the presented object' do
- it 'checks the abilities on the object being presented and returns the value' do
- expected_permissions.each do |permission|
- spy_ability_check_for(permission, presented_object, passed: true)
- end
+ context 'reading the field of a lazy value' do
+ let(:ability) { :read_field }
+ let(:presented_object) { lazy_upcase('a') }
+ let(:type_class) { type_with_field(GraphQL::STRING_TYPE, ability) }
- expect(resolved).to eq('Resolved value')
+ let(:upcaser) do
+ Module.new do
+ def self.upcase(strs)
+ strs.map(&:upcase)
+ end
end
+ end
- it 'returns nil if the value was not authorized' do
- allow(Ability).to receive(:allowed?).and_return false
-
- expect(resolved).to be_nil
+ def lazy_upcase(str)
+ ::BatchLoader::GraphQL.for(str).batch do |strs, found|
+ strs.zip(upcaser.upcase(strs)).each { |s, us| found[s, us] }
end
end
- context 'when the field is a built-in scalar type' do
- let(:type_class) { type_with_field(GraphQL::STRING_TYPE, :read_field) }
- let(:expected_permissions) { [:read_field] }
+ it 'does not run authorizations until we force the resolved value' do
+ expect(Ability).not_to receive(:allowed?)
- it_behaves_like 'checking permissions on the presented object'
+ expect(resolve).to respond_to(:force)
end
- context 'when the field is a list of scalar types' do
- let(:type_class) { type_with_field([GraphQL::STRING_TYPE], :read_field) }
- let(:expected_permissions) { [:read_field] }
+ it 'runs authorizations when we force the resolved value' do
+ spy_ability_check_for(ability, 'A')
- it_behaves_like 'checking permissions on the presented object'
+ expect(resolved).to eq('Resolved value')
end
- context 'when the field is sub-classed scalar type' do
- let(:type_class) { type_with_field(Types::TimeType, :read_field) }
- let(:expected_permissions) { [:read_field] }
+ it 'redacts values that fail the permissions check' do
+ spy_ability_check_for(ability, 'A', passed: false)
- it_behaves_like 'checking permissions on the presented object'
+ expect(resolved).to be_nil
end
- context 'when the field is a list of sub-classed scalar types' do
- let(:type_class) { type_with_field([Types::TimeType], :read_field) }
- let(:expected_permissions) { [:read_field] }
+ context 'we batch two calls' do
+ def resolve(value)
+ instance = type_class.authorized_new(lazy_upcase(value), context)
+ service.authorized_resolve[instance, {}, context]
+ end
- it_behaves_like 'checking permissions on the presented object'
- end
- end
+ it 'batches resolution, but authorizes each object separately' do
+ expect(upcaser).to receive(:upcase).once.and_call_original
+ spy_ability_check_for(:read_field, 'A', passed: true)
+ spy_ability_check_for(:read_field, 'B', passed: false)
+ spy_ability_check_for(:read_field, 'C', passed: true)
- context 'when the field is a connection' do
- context 'when it resolves to nil' do
- let(:type_class) { type_with_field(Types::QueryType.connection_type, :read_field, nil) }
+ a = resolve('a')
+ b = resolve('b')
+ c = resolve('c')
- it 'does not fail when authorizing' do
- expect(resolved).to be_nil
+ expect(a.force).to be_present
+ expect(b.force).to be_nil
+ expect(c.force).to be_present
end
end
end
- context 'when the field is a specific type' do
- let(:custom_type) { type(:read_type) }
- let(:object_in_field) { double('presented in field') }
+ shared_examples 'authorizing fields' do
+ context 'scalar types' do
+ shared_examples 'checking permissions on the presented object' do
+ it 'checks the abilities on the object being presented and returns the value' do
+ expected_permissions.each do |permission|
+ spy_ability_check_for(permission, presented_object, passed: true)
+ end
- let(:type_class) { type_with_field(custom_type, :read_field, object_in_field) }
- let(:type_instance) { type_class.authorized_new(object_in_field, context) }
+ expect(resolved).to eq('Resolved value')
+ end
- subject(:resolved) { service.authorized_resolve.call(type_instance, {}, context) }
+ it 'returns nil if the value was not authorized' do
+ allow(Ability).to receive(:allowed?).and_return false
- it 'checks both field & type permissions' do
- spy_ability_check_for(:read_field, object_in_field, passed: true)
- spy_ability_check_for(:read_type, object_in_field, passed: true)
+ expect(resolved).to be_nil
+ end
+ end
- expect(resolved).to eq(object_in_field)
- end
+ context 'when the field is a built-in scalar type' do
+ let(:type_class) { type_with_field(GraphQL::STRING_TYPE, :read_field) }
+ let(:expected_permissions) { [:read_field] }
- it 'returns nil if viewing was not allowed' do
- spy_ability_check_for(:read_field, object_in_field, passed: false)
- spy_ability_check_for(:read_type, object_in_field, passed: true)
+ it_behaves_like 'checking permissions on the presented object'
+ end
- expect(resolved).to be_nil
+ context 'when the field is a list of scalar types' do
+ let(:type_class) { type_with_field([GraphQL::STRING_TYPE], :read_field) }
+ let(:expected_permissions) { [:read_field] }
+
+ it_behaves_like 'checking permissions on the presented object'
+ end
+
+ context 'when the field is sub-classed scalar type' do
+ let(:type_class) { type_with_field(Types::TimeType, :read_field) }
+ let(:expected_permissions) { [:read_field] }
+
+ it_behaves_like 'checking permissions on the presented object'
+ end
+
+ context 'when the field is a list of sub-classed scalar types' do
+ let(:type_class) { type_with_field([Types::TimeType], :read_field) }
+ let(:expected_permissions) { [:read_field] }
+
+ it_behaves_like 'checking permissions on the presented object'
+ end
end
- context 'when the field is not nullable' do
- let(:type_class) { type_with_field(custom_type, :read_field, object_in_field, null: false) }
+ context 'when the field is a connection' do
+ context 'when it resolves to nil' do
+ let(:type_class) { type_with_field(Types::QueryType.connection_type, :read_field, nil) }
+
+ it 'does not fail when authorizing' do
+ expect(resolved).to be_nil
+ end
+ end
- it 'returns nil when viewing is not allowed' do
- spy_ability_check_for(:read_type, object_in_field, passed: false)
+ context 'when it returns values' do
+ let(:objects) { [1, 2, 3] }
+ let(:field_type) { type([:read_object]).connection_type }
+ let(:type_class) { type_with_field(field_type, [], objects) }
- expect(resolved).to be_nil
+ it 'filters out unauthorized values' do
+ spy_ability_check_for(:read_object, 1, passed: true)
+ spy_ability_check_for(:read_object, 2, passed: false)
+ spy_ability_check_for(:read_object, 3, passed: true)
+
+ expect(resolved.nodes).to eq [1, 3]
+ end
end
end
- context 'when the field is a list' do
- let(:object_1) { double('presented in field 1') }
- let(:object_2) { double('presented in field 2') }
- let(:presented_types) { [double(object: object_1), double(object: object_2)] }
+ context 'when the field is a specific type' do
+ let(:custom_type) { type(:read_type) }
+ let(:object_in_field) { double('presented in field') }
+
+ let(:type_class) { type_with_field(custom_type, :read_field, object_in_field) }
+ let(:type_instance) { type_class.authorized_new(object_in_field, context) }
+
+ it 'checks both field & type permissions' do
+ spy_ability_check_for(:read_field, object_in_field, passed: true)
+ spy_ability_check_for(:read_type, object_in_field, passed: true)
+
+ expect(resolved).to eq(object_in_field)
+ end
+
+ it 'returns nil if viewing was not allowed' do
+ spy_ability_check_for(:read_field, object_in_field, passed: false)
+ spy_ability_check_for(:read_type, object_in_field, passed: true)
- let(:type_class) { type_with_field([custom_type], :read_field, presented_types) }
- let(:type_instance) { type_class.authorized_new(presented_types, context) }
+ expect(resolved).to be_nil
+ end
- it 'checks all permissions' do
- allow(Ability).to receive(:allowed?) { true }
+ context 'when the field is not nullable' do
+ let(:type_class) { type_with_field(custom_type, :read_field, object_in_field, null: false) }
- spy_ability_check_for(:read_field, object_1, passed: true)
- spy_ability_check_for(:read_type, object_1, passed: true)
- spy_ability_check_for(:read_field, object_2, passed: true)
- spy_ability_check_for(:read_type, object_2, passed: true)
+ it 'returns nil when viewing is not allowed' do
+ spy_ability_check_for(:read_type, object_in_field, passed: false)
- expect(resolved).to eq(presented_types)
+ expect(resolved).to be_nil
+ end
end
- it 'filters out objects that the user cannot see' do
- allow(Ability).to receive(:allowed?) { true }
+ context 'when the field is a list' do
+ let(:object_1) { double('presented in field 1') }
+ let(:object_2) { double('presented in field 2') }
+ let(:presented_types) { [double(object: object_1), double(object: object_2)] }
+
+ let(:type_class) { type_with_field([custom_type], :read_field, presented_types) }
+ let(:type_instance) { type_class.authorized_new(presented_types, context) }
+
+ it 'checks all permissions' do
+ allow(Ability).to receive(:allowed?) { true }
- spy_ability_check_for(:read_type, object_1, passed: false)
+ spy_ability_check_for(:read_field, object_1, passed: true)
+ spy_ability_check_for(:read_type, object_1, passed: true)
+ spy_ability_check_for(:read_field, object_2, passed: true)
+ spy_ability_check_for(:read_type, object_2, passed: true)
- expect(resolved.map(&:object)).to contain_exactly(object_2)
+ expect(resolved).to eq(presented_types)
+ end
+
+ it 'filters out objects that the user cannot see' do
+ allow(Ability).to receive(:allowed?) { true }
+
+ spy_ability_check_for(:read_type, object_1, passed: false)
+
+ expect(resolved).to contain_exactly(have_attributes(object: object_2))
+ end
end
end
end
+
+ it_behaves_like 'authorizing fields'
end
private
diff --git a/spec/lib/gitlab/graphql/lazy_spec.rb b/spec/lib/gitlab/graphql/lazy_spec.rb
new file mode 100644
index 00000000000..795978ab0a4
--- /dev/null
+++ b/spec/lib/gitlab/graphql/lazy_spec.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Graphql::Lazy do
+ def load(key)
+ BatchLoader.for(key).batch do |keys, loader|
+ keys.each { |x| loader.call(x, x * x) }
+ end
+ end
+
+ let(:value) { double(x: 1) }
+
+ describe '#force' do
+ subject { described_class.new { value.x } }
+
+ it 'can extract the value' do
+ expect(subject.force).to be 1
+ end
+
+ it 'can derive new lazy values' do
+ expect(subject.then { |x| x + 2 }.force).to be 3
+ end
+
+ it 'only evaluates once' do
+ expect(value).to receive(:x).once
+
+ expect(subject.force).to eq(subject.force)
+ end
+
+ it 'deals with nested laziness' do
+ expect(described_class.new { load(10) }.force).to eq(100)
+ expect(described_class.new { described_class.new { 5 } }.force).to eq 5
+ end
+ end
+
+ describe '.with_value' do
+ let(:inner) { described_class.new { value.x } }
+
+ subject { described_class.with_value(inner) { |x| x.to_s } }
+
+ it 'defers the application of a block to a value' do
+ expect(value).not_to receive(:x)
+
+ expect(subject).to be_an_instance_of(described_class)
+ end
+
+ it 'evaluates to the application of the block to the value' do
+ expect(value).to receive(:x).once
+
+ expect(subject.force).to eq(inner.force.to_s)
+ end
+ end
+
+ describe '.force' do
+ context 'when given a plain value' do
+ subject { described_class.force(1) }
+
+ it 'unwraps the value' do
+ expect(subject).to be 1
+ end
+ end
+
+ context 'when given a wrapped lazy value' do
+ subject { described_class.force(described_class.new { 2 }) }
+
+ it 'unwraps the value' do
+ expect(subject).to be 2
+ end
+ end
+
+ context 'when the value is from a batchloader' do
+ subject { described_class.force(load(3)) }
+
+ it 'syncs the value' do
+ expect(subject).to be 9
+ end
+ end
+
+ context 'when the value is a GraphQL lazy' do
+ subject { described_class.force(GitlabSchema.after_lazy(load(3)) { |x| x + 1 } ) }
+
+ it 'forces the evaluation' do
+ expect(subject).to be 10
+ end
+ end
+
+ context 'when the value is a promise' do
+ subject { described_class.force(::Concurrent::Promise.new { 4 }) }
+
+ it 'executes the promise and waits for the value' do
+ expect(subject).to be 4
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb b/spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb
index cf1f00bc176..7ae33346388 100644
--- a/spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb
+++ b/spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb
@@ -4,8 +4,9 @@ require 'spec_helper'
RSpec.describe Gitlab::Graphql::Loaders::BatchModelLoader do
describe '#find' do
- let(:issue) { create(:issue) }
- let(:user) { create(:user) }
+ let_it_be(:issue) { create(:issue) }
+ let_it_be(:other_user) { create(:user) }
+ let_it_be(:user) { create(:user) }
it 'finds a model by id' do
issue_result = described_class.new(Issue, issue.id).find
@@ -16,15 +17,25 @@ RSpec.describe Gitlab::Graphql::Loaders::BatchModelLoader do
end
it 'only queries once per model' do
- other_user = create(:user)
- user
- issue
-
expect do
[described_class.new(User, other_user.id).find,
described_class.new(User, user.id).find,
described_class.new(Issue, issue.id).find].map(&:sync)
end.not_to exceed_query_limit(2)
end
+
+ it 'does not force values unnecessarily' do
+ expect do
+ a = described_class.new(User, user.id).find
+ b = described_class.new(Issue, issue.id).find
+
+ b.sync
+
+ c = described_class.new(User, other_user.id).find
+
+ a.sync
+ c.sync
+ end.not_to exceed_query_limit(2)
+ end
end
end
diff --git a/spec/lib/gitlab/hook_data/release_builder_spec.rb b/spec/lib/gitlab/hook_data/release_builder_spec.rb
new file mode 100644
index 00000000000..b630780b162
--- /dev/null
+++ b/spec/lib/gitlab/hook_data/release_builder_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::HookData::ReleaseBuilder do
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let(:release) { create(:release, project: project) }
+ let(:builder) { described_class.new(release) }
+
+ describe '#build' do
+ let(:data) { builder.build('create') }
+
+ it 'includes safe attribute' do
+ %w[
+ id
+ created_at
+ description
+ name
+ released_at
+ tag
+ ].each do |key|
+ expect(data).to include(key)
+ end
+ end
+
+ it 'includes additional attrs' do
+ expect(data[:object_kind]).to eq('release')
+ expect(data[:project]).to eq(builder.release.project.hook_attrs.with_indifferent_access)
+ expect(data[:action]).to eq('create')
+ expect(data).to include(:assets)
+ expect(data).to include(:commit)
+ end
+
+ context 'when the Release has an image in the description' do
+ let(:release_with_description) do
+ create(:release, project: project, description: 'test![Release_Image](/uploads/abc/Release_Image.png)')
+ end
+
+ let(:builder) { described_class.new(release_with_description) }
+
+ it 'sets the image to use an absolute URL' do
+ expected_path = "#{release_with_description.project.path_with_namespace}/uploads/abc/Release_Image.png"
+
+ expect(data[:description])
+ .to eq("test![Release_Image](#{Settings.gitlab.url}/#{expected_path})")
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/i18n/po_linter_spec.rb b/spec/lib/gitlab/i18n/po_linter_spec.rb
index 9165ccfb1ef..e04c0b49480 100644
--- a/spec/lib/gitlab/i18n/po_linter_spec.rb
+++ b/spec/lib/gitlab/i18n/po_linter_spec.rb
@@ -461,9 +461,10 @@ RSpec.describe Gitlab::I18n::PoLinter do
fake_metadata = double
allow(fake_metadata).to receive(:forms_to_test).and_return(4)
allow(linter).to receive(:metadata_entry).and_return(fake_metadata)
- allow(linter).to receive(:locale).and_return('pl_PL')
- numbers = linter.numbers_covering_all_plurals
+ numbers = Gitlab::I18n.with_locale('pl_PL') do
+ linter.numbers_covering_all_plurals
+ end
expect(numbers).to contain_exactly(0, 1, 2)
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 5ee7fb2adbf..38fe2781331 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -179,6 +179,7 @@ merge_requests:
- user_mentions
- system_note_metadata
- note_authors
+- cleanup_schedule
external_pull_requests:
- project
merge_request_diff:
@@ -195,6 +196,8 @@ merge_request_diff_files:
merge_request_context_commits:
- merge_request
- diff_files
+cleanup_schedule:
+- merge_request
ci_pipelines:
- project
- user
@@ -240,6 +243,7 @@ ci_pipelines:
- vulnerability_findings
- pipeline_config
- security_scans
+- security_findings
- daily_build_group_report_results
- latest_builds
- daily_report_results
@@ -317,6 +321,7 @@ push_access_levels:
- protected_branch
- user
- group
+- deploy_key
create_access_levels:
- user
- protected_tag
@@ -652,6 +657,7 @@ milestone_releases:
evidences:
- release
design: &design
+- authors
- issue
- actions
- versions
diff --git a/spec/lib/gitlab/import_export/attributes_finder_spec.rb b/spec/lib/gitlab/import_export/attributes_finder_spec.rb
index 7f6ebf577af..428d8d605ee 100644
--- a/spec/lib/gitlab/import_export/attributes_finder_spec.rb
+++ b/spec/lib/gitlab/import_export/attributes_finder_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe Gitlab::ImportExport::AttributesFinder do
end
before do
- allow_any_instance_of(Gitlab::ImportExport).to receive(:config_file).and_return(test_config)
+ allow(Gitlab::ImportExport).to receive(:config_file).and_return(test_config)
end
it 'generates hash from project tree config' do
diff --git a/spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb b/spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb
index 6b324b952dc..9e1571ae3d8 100644
--- a/spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Gitlab::ImportExport::Group::LegacyTreeSaver do
before do
group.add_maintainer(user)
- allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
+ allow(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
end
after do
diff --git a/spec/lib/gitlab/import_export/importer_spec.rb b/spec/lib/gitlab/import_export/importer_spec.rb
index dc44296321c..0db038785d3 100644
--- a/spec/lib/gitlab/import_export/importer_spec.rb
+++ b/spec/lib/gitlab/import_export/importer_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Gitlab::ImportExport::Importer do
subject(:importer) { described_class.new(project) }
before do
- allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(test_path)
+ allow(Gitlab::ImportExport).to receive(:storage_path).and_return(test_path)
allow_any_instance_of(Gitlab::ImportExport::FileImporter).to receive(:remove_import_file)
stub_uploads_object_storage(FileUploader)
@@ -65,10 +65,22 @@ RSpec.describe Gitlab::ImportExport::Importer do
end
end
- it 'restores the ProjectTree' do
- expect(Gitlab::ImportExport::Project::TreeRestorer).to receive(:new).and_call_original
+ context 'with sample_data_template' do
+ it 'initializes the Sample::TreeRestorer' do
+ project.create_or_update_import_data(data: { sample_data: true })
- importer.execute
+ expect(Gitlab::ImportExport::Project::Sample::TreeRestorer).to receive(:new).and_call_original
+
+ importer.execute
+ end
+ end
+
+ context 'without sample_data_template' do
+ it 'initializes the ProjectTree' do
+ expect(Gitlab::ImportExport::Project::TreeRestorer).to receive(:new).and_call_original
+
+ importer.execute
+ end
end
it 'removes the import file' do
diff --git a/spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb b/spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb
index e208a1c383c..b477ac45577 100644
--- a/spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb
+++ b/spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb
@@ -67,6 +67,14 @@ RSpec.describe Gitlab::ImportExport::JSON::NdjsonReader do
it 'yields nothing to the Enumerator' do
expect(subject.to_a).to eq([])
end
+
+ context 'with mark_as_consumed: false' do
+ subject { ndjson_reader.consume_relation(importable_path, key, mark_as_consumed: false) }
+
+ it 'yields every relation value to the Enumerator' do
+ expect(subject.count).to eq(1)
+ end
+ end
end
context 'key has not been consumed' do
@@ -102,14 +110,4 @@ RSpec.describe Gitlab::ImportExport::JSON::NdjsonReader do
end
end
end
-
- describe '#clear_consumed_relations' do
- let(:dir_path) { fixture }
-
- subject { ndjson_reader.clear_consumed_relations }
-
- it 'returns empty set' do
- expect(subject).to be_empty
- end
- end
end
diff --git a/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb b/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb
index 949cfb5a34d..762687beedb 100644
--- a/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb
+++ b/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb
@@ -19,6 +19,7 @@ RSpec.describe Gitlab::ImportExport::JSON::StreamingSerializer do
group: group,
approvals_before_merge: 1)
end
+
let_it_be(:issue) do
create(:issue,
assignees: [user],
diff --git a/spec/lib/gitlab/import_export/lfs_restorer_spec.rb b/spec/lib/gitlab/import_export/lfs_restorer_spec.rb
index a9f7fb72612..c8887b0ded1 100644
--- a/spec/lib/gitlab/import_export/lfs_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/lfs_restorer_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Gitlab::ImportExport::LfsRestorer do
subject(:restorer) { described_class.new(project: project, shared: shared) }
before do
- allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
+ allow(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
FileUtils.mkdir_p(shared.export_path)
end
diff --git a/spec/lib/gitlab/import_export/project/relation_factory_spec.rb b/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
index 50bc6a30044..56ba730e893 100644
--- a/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
@@ -61,6 +61,7 @@ RSpec.describe Gitlab::ImportExport::Project::RelationFactory do
'enable_ssl_verification' => true,
'job_events' => false,
'wiki_page_events' => true,
+ 'releases_events' => false,
'token' => token
}
end
diff --git a/spec/lib/gitlab/import_export/project/sample/date_calculator_spec.rb b/spec/lib/gitlab/import_export/project/sample/date_calculator_spec.rb
index 82f59245519..645242c6f05 100644
--- a/spec/lib/gitlab/import_export/project/sample/date_calculator_spec.rb
+++ b/spec/lib/gitlab/import_export/project/sample/date_calculator_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Gitlab::ImportExport::Project::Sample::DateCalculator do
end
context 'when dates are not empty' do
- let(:dates) { [[nil, '2020-01-01 00:00:00 +0000'], [nil, '2021-01-01 00:00:00 +0000'], [nil, '2022-01-01 23:59:59 +0000']] }
+ let(:dates) { [nil, '2020-01-01 00:00:00 +0000', '2021-01-01 00:00:00 +0000', nil, '2022-01-01 23:59:59 +0000'] }
it { is_expected.to eq(Time.zone.parse('2021-01-01 00:00:00 +0000')) }
end
diff --git a/spec/lib/gitlab/import_export/project/sample/relation_factory_spec.rb b/spec/lib/gitlab/import_export/project/sample/relation_factory_spec.rb
new file mode 100644
index 00000000000..86d5f2402f8
--- /dev/null
+++ b/spec/lib/gitlab/import_export/project/sample/relation_factory_spec.rb
@@ -0,0 +1,168 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::ImportExport::Project::Sample::RelationFactory do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, :repository, group: group) }
+ let(:members_mapper) { double('members_mapper').as_null_object }
+ let(:admin) { create(:admin) }
+ let(:importer_user) { admin }
+ let(:excluded_keys) { [] }
+ let(:date_calculator) { instance_double(Gitlab::ImportExport::Project::Sample::DateCalculator) }
+ let(:original_project_id) { 8 }
+ let(:start_date) { Time.current - 30.days }
+ let(:due_date) { Time.current - 20.days }
+ let(:created_object) do
+ described_class.create( # rubocop:disable Rails/SaveBang
+ relation_sym: relation_sym,
+ relation_hash: relation_hash,
+ object_builder: Gitlab::ImportExport::Project::ObjectBuilder,
+ members_mapper: members_mapper,
+ user: importer_user,
+ importable: project,
+ excluded_keys: excluded_keys,
+ date_calculator: date_calculator
+ )
+ end
+
+ context 'issue object' do
+ let(:relation_sym) { :issues }
+ let(:id) { 999 }
+
+ let(:relation_hash) do
+ {
+ 'id' => id,
+ 'title' => 'Necessitatibus magnam qui at velit consequatur perspiciatis.',
+ 'project_id' => original_project_id,
+ 'created_at' => '2016-08-12T09:41:03.462Z',
+ 'updated_at' => '2016-08-12T09:41:03.462Z',
+ 'description' => 'Molestiae corporis magnam et fugit aliquid nulla quia.',
+ 'state' => 'closed',
+ 'position' => 0,
+ 'confidential' => false,
+ 'due_date' => due_date
+ }
+ end
+
+ before do
+ allow(date_calculator).to receive(:closest_date_to_average) { Time.current - 10.days }
+ allow(date_calculator).to receive(:calculate_by_closest_date_to_average)
+ end
+
+ it 'correctly updated due date', :aggregate_failures do
+ expect(date_calculator).to receive(:calculate_by_closest_date_to_average)
+ .with(relation_hash['due_date']).and_return(due_date - 10.days)
+
+ expect(created_object.due_date).to eq((due_date - 10.days).to_date)
+ end
+ end
+
+ context 'milestone object' do
+ let(:relation_sym) { :milestones }
+ let(:id) { 1001 }
+
+ let(:relation_hash) do
+ {
+ 'id' => id,
+ 'title' => 'v3.0',
+ 'project_id' => original_project_id,
+ 'created_at' => '2016-08-12T09:41:03.462Z',
+ 'updated_at' => '2016-08-12T09:41:03.462Z',
+ 'description' => 'Rerum at autem exercitationem ea voluptates harum quam placeat.',
+ 'state' => 'closed',
+ 'start_date' => start_date,
+ 'due_date' => due_date
+ }
+ end
+
+ before do
+ allow(date_calculator).to receive(:closest_date_to_average).twice { Time.current - 10.days }
+ allow(date_calculator).to receive(:calculate_by_closest_date_to_average).twice
+ end
+
+ it 'correctly updated due date', :aggregate_failures do
+ expect(date_calculator).to receive(:calculate_by_closest_date_to_average)
+ .with(relation_hash['due_date']).and_return(due_date - 10.days)
+
+ expect(created_object.due_date).to eq((due_date - 10.days).to_date)
+ end
+
+ it 'correctly updated start date', :aggregate_failures do
+ expect(date_calculator).to receive(:calculate_by_closest_date_to_average)
+ .with(relation_hash['start_date']).and_return(start_date - 20.days)
+
+ expect(created_object.start_date).to eq((start_date - 20.days).to_date)
+ end
+ end
+
+ context 'milestone object' do
+ let(:relation_sym) { :milestones }
+ let(:id) { 1001 }
+
+ let(:relation_hash) do
+ {
+ 'id' => id,
+ 'title' => 'v3.0',
+ 'project_id' => original_project_id,
+ 'created_at' => '2016-08-12T09:41:03.462Z',
+ 'updated_at' => '2016-08-12T09:41:03.462Z',
+ 'description' => 'Rerum at autem exercitationem ea voluptates harum quam placeat.',
+ 'state' => 'closed',
+ 'start_date' => start_date,
+ 'due_date' => due_date
+ }
+ end
+
+ before do
+ allow(date_calculator).to receive(:closest_date_to_average).twice { Time.current - 10.days }
+ allow(date_calculator).to receive(:calculate_by_closest_date_to_average).twice
+ end
+
+ it 'correctly updated due date', :aggregate_failures do
+ expect(date_calculator).to receive(:calculate_by_closest_date_to_average)
+ .with(relation_hash['due_date']).and_return(due_date - 10.days)
+
+ expect(created_object.due_date).to eq((due_date - 10.days).to_date)
+ end
+
+ it 'correctly updated start date', :aggregate_failures do
+ expect(date_calculator).to receive(:calculate_by_closest_date_to_average)
+ .with(relation_hash['start_date']).and_return(start_date - 20.days)
+
+ expect(created_object.start_date).to eq((start_date - 20.days).to_date)
+ end
+ end
+
+ context 'hook object' do
+ let(:relation_sym) { :hooks }
+ let(:id) { 999 }
+ let(:service_id) { 99 }
+ let(:token) { 'secret' }
+
+ let(:relation_hash) do
+ {
+ 'id' => id,
+ 'url' => 'https://example.json',
+ 'project_id' => original_project_id,
+ 'created_at' => '2016-08-12T09:41:03.462Z',
+ 'updated_at' => '2016-08-12T09:41:03.462Z',
+ 'service_id' => service_id,
+ 'push_events' => true,
+ 'issues_events' => false,
+ 'confidential_issues_events' => false,
+ 'merge_requests_events' => true,
+ 'tag_push_events' => false,
+ 'note_events' => true,
+ 'enable_ssl_verification' => true,
+ 'job_events' => false,
+ 'wiki_page_events' => true,
+ 'token' => token
+ }
+ end
+
+ it 'does not calculate the closest date to average' do
+ expect(date_calculator).not_to receive(:calculate_by_closest_date_to_average)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
new file mode 100644
index 00000000000..f87f79d4462
--- /dev/null
+++ b/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+# This spec is a lightweight version of:
+# * project/tree_restorer_spec.rb
+#
+# In depth testing is being done in the above specs.
+# This spec tests that restore of the sample project works
+# but does not have 100% relation coverage.
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::ImportExport::Project::Sample::RelationTreeRestorer do
+ include_context 'relation tree restorer shared context'
+
+ let(:sample_data_relation_tree_restorer) do
+ described_class.new(
+ user: user,
+ shared: shared,
+ relation_reader: relation_reader,
+ object_builder: object_builder,
+ members_mapper: members_mapper,
+ relation_factory: relation_factory,
+ reader: reader,
+ importable: importable,
+ importable_path: importable_path,
+ importable_attributes: attributes
+ )
+ end
+
+ subject { sample_data_relation_tree_restorer.restore }
+
+ shared_examples 'import project successfully' do
+ it 'restores project tree' do
+ expect(subject).to eq(true)
+ end
+
+ describe 'imported project' do
+ let(:project) { Project.find_by_path('project') }
+
+ before do
+ subject
+ end
+
+ it 'has the project attributes and relations', :aggregate_failures do
+ expect(project.description).to eq('Nisi et repellendus ut enim quo accusamus vel magnam.')
+ expect(project.issues.count).to eq(10)
+ expect(project.milestones.count).to eq(3)
+ expect(project.labels.count).to eq(2)
+ expect(project.project_feature).not_to be_nil
+ end
+
+ it 'has issues with correctly updated due dates' do
+ due_dates = due_dates(project.issues)
+
+ expect(due_dates).to match_array([Date.today - 7.days, Date.today, Date.today + 7.days])
+ end
+
+ it 'has milestones with correctly updated due dates' do
+ due_dates = due_dates(project.milestones)
+
+ expect(due_dates).to match_array([Date.today - 7.days, Date.today, Date.today + 7.days])
+ end
+
+ def due_dates(relations)
+ due_dates = relations.map { |relation| relation['due_date'] }
+ due_dates.compact!
+ due_dates.sort
+ end
+ end
+ end
+
+ context 'when restoring a project' do
+ let(:importable) { create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project') }
+ let(:importable_name) { 'project' }
+ let(:importable_path) { 'project' }
+ let(:object_builder) { Gitlab::ImportExport::Project::ObjectBuilder }
+ let(:relation_factory) { Gitlab::ImportExport::Project::Sample::RelationFactory }
+ let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/sample_data/tree' }
+ let(:relation_reader) { Gitlab::ImportExport::JSON::NdjsonReader.new(path) }
+
+ it 'initializes relation_factory with date_calculator as parameter' do
+ expect(Gitlab::ImportExport::Project::Sample::RelationFactory).to receive(:create).with(hash_including(:date_calculator)).at_least(:once).times
+
+ subject
+ end
+
+ context 'when relation tree restorer is initialized' do
+ it 'initializes date calculator with due dates' do
+ expect(Gitlab::ImportExport::Project::Sample::DateCalculator).to receive(:new).with(Array)
+
+ sample_data_relation_tree_restorer
+ end
+ end
+
+ context 'using ndjson reader' do
+ it_behaves_like 'import project successfully'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/project/sample/sample_data_relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/sample/sample_data_relation_tree_restorer_spec.rb
deleted file mode 100644
index f173345a4c6..00000000000
--- a/spec/lib/gitlab/import_export/project/sample/sample_data_relation_tree_restorer_spec.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-# frozen_string_literal: true
-
-# This spec is a lightweight version of:
-# * project/tree_restorer_spec.rb
-#
-# In depth testing is being done in the above specs.
-# This spec tests that restore of the sample project works
-# but does not have 100% relation coverage.
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::ImportExport::Project::Sample::SampleDataRelationTreeRestorer do
- include_context 'relation tree restorer shared context'
-
- let(:sample_data_relation_tree_restorer) do
- described_class.new(
- user: user,
- shared: shared,
- relation_reader: relation_reader,
- object_builder: object_builder,
- members_mapper: members_mapper,
- relation_factory: relation_factory,
- reader: reader,
- importable: importable,
- importable_path: importable_path,
- importable_attributes: attributes
- )
- end
-
- subject { sample_data_relation_tree_restorer.restore }
-
- shared_examples 'import project successfully' do
- it 'restores project tree' do
- expect(subject).to eq(true)
- end
-
- describe 'imported project' do
- let(:project) { Project.find_by_path('project') }
-
- before do
- subject
- end
-
- it 'has the project attributes and relations', :aggregate_failures do
- expect(project.description).to eq('Nisi et repellendus ut enim quo accusamus vel magnam.')
- expect(project.issues.count).to eq(10)
- expect(project.milestones.count).to eq(3)
- expect(project.labels.count).to eq(2)
- expect(project.project_feature).not_to be_nil
- end
-
- it 'has issues with correctly updated due dates' do
- due_dates = due_dates(project.issues)
-
- expect(due_dates).to match_array([Date.today - 7.days, Date.today, Date.today + 7.days])
- end
-
- it 'has milestones with correctly updated due dates' do
- due_dates = due_dates(project.milestones)
-
- expect(due_dates).to match_array([Date.today - 7.days, Date.today, Date.today + 7.days])
- end
-
- def due_dates(relations)
- due_dates = relations.map { |relation| relation['due_date'] }
- due_dates.compact!
- due_dates.sort
- end
- end
- end
-
- context 'when restoring a project' do
- let(:importable) { create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project') }
- let(:importable_name) { 'project' }
- let(:importable_path) { 'project' }
- let(:object_builder) { Gitlab::ImportExport::Project::ObjectBuilder }
- let(:relation_factory) { Gitlab::ImportExport::Project::RelationFactory }
- let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
-
- context 'using ndjson reader' do
- let(:path) { 'spec/fixtures/lib/gitlab/import_export/sample_data/tree' }
- let(:relation_reader) { Gitlab::ImportExport::JSON::NdjsonReader.new(path) }
-
- it_behaves_like 'import project successfully'
- end
- end
-end
diff --git a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
index c05968c9a85..fd3b71deb37 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -681,13 +681,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
end
it 'overrides project feature access levels' do
- access_level_keys = project.project_feature.attributes.keys.select { |a| a =~ /_access_level/ }
-
- # `pages_access_level` is not included, since it is not available in the public API
- # and has a dependency on project's visibility level
- # see ProjectFeature model
- access_level_keys.delete('pages_access_level')
-
+ access_level_keys = ProjectFeature.available_features.map { |feature| ProjectFeature.access_level_attribute(feature) }
disabled_access_levels = Hash[access_level_keys.collect { |item| [item, 'disabled'] }]
project.create_import_data(data: { override_params: disabled_access_levels })
@@ -979,6 +973,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
create(:project, :builds_disabled, :issues_disabled,
{ name: 'project', path: 'project' })
end
+
let(:shared) { project.import_export_shared }
let(:project_tree_restorer) { described_class.new(user: user, shared: shared, project: project) }
@@ -1040,41 +1035,6 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
it_behaves_like 'project tree restorer work properly', :legacy_reader, true
it_behaves_like 'project tree restorer work properly', :ndjson_reader, true
-
- context 'Sample Data JSON' do
- let(:user) { create(:user) }
- let!(:project) { create(:project, :builds_disabled, :issues_disabled, name: 'project', path: 'project') }
- let(:project_tree_restorer) { described_class.new(user: user, shared: shared, project: project) }
-
- before do
- setup_import_export_config('sample_data')
- setup_reader(:ndjson_reader)
- end
-
- context 'with sample_data_template' do
- before do
- allow(project).to receive_message_chain(:import_data, :data, :dig).with('sample_data') { true }
- end
-
- it 'initialize SampleDataRelationTreeRestorer' do
- expect_next_instance_of(Gitlab::ImportExport::Project::Sample::SampleDataRelationTreeRestorer) do |restorer|
- expect(restorer).to receive(:restore).and_return(true)
- end
-
- expect(project_tree_restorer.restore).to eq(true)
- end
- end
-
- context 'without sample_data_template' do
- it 'initialize RelationTreeRestorer' do
- expect_next_instance_of(Gitlab::ImportExport::RelationTreeRestorer) do |restorer|
- expect(restorer).to receive(:restore).and_return(true)
- end
-
- expect(project_tree_restorer.restore).to eq(true)
- end
- end
- end
end
context 'disable ndjson import' do
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index e3d1f2c9368..b33462b4096 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -489,6 +489,7 @@ ProjectHook:
- confidential_issues_events
- confidential_note_events
- repository_update_events
+- releases_events
ProtectedBranch:
- id
- project_id
@@ -575,6 +576,7 @@ ProjectFeature:
- repository_access_level
- pages_access_level
- metrics_dashboard_access_level
+- requirements_access_level
- created_at
- updated_at
ProtectedBranch::MergeAccessLevel:
@@ -683,6 +685,7 @@ ProjectCiCdSetting:
ProjectSetting:
- allow_merge_on_skipped_pipeline
- has_confluence
+- has_vulnerabilities
ProtectedEnvironment:
- id
- project_id
@@ -771,6 +774,7 @@ ExternalPullRequest:
- target_sha
DesignManagement::Design:
- id
+- iid
- project_id
- filename
- relative_position
@@ -858,3 +862,25 @@ ProjectSecuritySetting:
IssuableSla:
- issue_id
- due_at
+PushRule:
+ - force_push_regex
+ - delete_branch_regex
+ - commit_message_regex
+ - author_email_regex
+ - file_name_regex
+ - branch_name_regex
+ - commit_message_negative_regex
+ - max_file_size
+ - deny_delete_tag
+ - member_check
+ - is_sample
+ - prevent_secrets
+ - reject_unsigned_commits
+ - commit_committer_check
+ - regexp_uses_re2
+MergeRequest::CleanupSchedule:
+- id
+- scheduled_at
+- completed_at
+- created_at
+- updated_at
diff --git a/spec/lib/gitlab/import_export/uploads_manager_spec.rb b/spec/lib/gitlab/import_export/uploads_manager_spec.rb
index 33ad0e12c37..8282ad9a070 100644
--- a/spec/lib/gitlab/import_export/uploads_manager_spec.rb
+++ b/spec/lib/gitlab/import_export/uploads_manager_spec.rb
@@ -23,13 +23,13 @@ RSpec.describe Gitlab::ImportExport::UploadsManager do
end
describe '#save' do
+ before do
+ project.uploads << upload
+ end
+
context 'when the project has uploads locally stored' do
let(:upload) { create(:upload, :issuable_upload, :with_file, model: project) }
- before do
- project.uploads << upload
- end
-
it 'does not cause errors' do
manager.save
@@ -74,6 +74,22 @@ RSpec.describe Gitlab::ImportExport::UploadsManager do
end
end
end
+
+ context 'when upload is in object storage' do
+ before do
+ stub_uploads_object_storage(FileUploader)
+ allow(manager).to receive(:download_or_copy_upload).and_raise(Errno::ENAMETOOLONG)
+ end
+
+ it 'ignores problematic upload and logs exception' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(Errno::ENAMETOOLONG), project_id: project.id)
+
+ manager.save
+
+ expect(shared.errors).to be_empty
+ expect(File).not_to exist(exported_file_path)
+ end
+ end
end
describe '#restore' do
diff --git a/spec/lib/gitlab/instrumentation_helper_spec.rb b/spec/lib/gitlab/instrumentation_helper_spec.rb
index 35bbdcdccd6..88f2def34d9 100644
--- a/spec/lib/gitlab/instrumentation_helper_spec.rb
+++ b/spec/lib/gitlab/instrumentation_helper_spec.rb
@@ -97,6 +97,16 @@ RSpec.describe Gitlab::InstrumentationHelper do
expect(payload[:gitaly_duration]).to be_nil
end
end
+
+ context 'when the request matched a Rack::Attack safelist' do
+ it 'logs the safelist name' do
+ Gitlab::Instrumentation::Throttle.safelist = 'foobar'
+
+ subject
+
+ expect(payload[:throttle_safelist]).to eq('foobar')
+ end
+ end
end
describe '.queue_duration_for_job' do
diff --git a/spec/lib/gitlab/jira_import_spec.rb b/spec/lib/gitlab/jira_import_spec.rb
index c8cecb576da..2b602c80640 100644
--- a/spec/lib/gitlab/jira_import_spec.rb
+++ b/spec/lib/gitlab/jira_import_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Gitlab::JiraImport do
let_it_be(:project, reload: true) { create(:project) }
let(:additional_params) { {} }
- subject { described_class.validate_project_settings!(project, additional_params) }
+ subject { described_class.validate_project_settings!(project, **additional_params) }
shared_examples 'raise Jira import error' do |message|
it 'returns error' do
diff --git a/spec/lib/gitlab/json_spec.rb b/spec/lib/gitlab/json_spec.rb
index 0402296a3a8..59ec94f2855 100644
--- a/spec/lib/gitlab/json_spec.rb
+++ b/spec/lib/gitlab/json_spec.rb
@@ -7,342 +7,306 @@ RSpec.describe Gitlab::Json do
stub_feature_flags(json_wrapper_legacy_mode: true)
end
- shared_examples "json" do
- describe ".parse" do
- context "legacy_mode is disabled by default" do
- it "parses an object" do
- expect(subject.parse('{ "foo": "bar" }')).to eq({ "foo" => "bar" })
- end
-
- it "parses an array" do
- expect(subject.parse('[{ "foo": "bar" }]')).to eq([{ "foo" => "bar" }])
- end
-
- it "parses a string" do
- expect(subject.parse('"foo"', legacy_mode: false)).to eq("foo")
- end
-
- it "parses a true bool" do
- expect(subject.parse("true", legacy_mode: false)).to be(true)
- end
-
- it "parses a false bool" do
- expect(subject.parse("false", legacy_mode: false)).to be(false)
- end
+ describe ".parse" do
+ context "legacy_mode is disabled by default" do
+ it "parses an object" do
+ expect(subject.parse('{ "foo": "bar" }')).to eq({ "foo" => "bar" })
end
- context "legacy_mode is enabled" do
- it "parses an object" do
- expect(subject.parse('{ "foo": "bar" }', legacy_mode: true)).to eq({ "foo" => "bar" })
- end
-
- it "parses an array" do
- expect(subject.parse('[{ "foo": "bar" }]', legacy_mode: true)).to eq([{ "foo" => "bar" }])
- end
-
- it "raises an error on a string" do
- expect { subject.parse('"foo"', legacy_mode: true) }.to raise_error(JSON::ParserError)
- end
-
- it "raises an error on a true bool" do
- expect { subject.parse("true", legacy_mode: true) }.to raise_error(JSON::ParserError)
- end
-
- it "raises an error on a false bool" do
- expect { subject.parse("false", legacy_mode: true) }.to raise_error(JSON::ParserError)
- end
+ it "parses an array" do
+ expect(subject.parse('[{ "foo": "bar" }]')).to eq([{ "foo" => "bar" }])
end
- context "feature flag is disabled" do
- before do
- stub_feature_flags(json_wrapper_legacy_mode: false)
- end
-
- it "parses an object" do
- expect(subject.parse('{ "foo": "bar" }', legacy_mode: true)).to eq({ "foo" => "bar" })
- end
-
- it "parses an array" do
- expect(subject.parse('[{ "foo": "bar" }]', legacy_mode: true)).to eq([{ "foo" => "bar" }])
- end
-
- it "parses a string" do
- expect(subject.parse('"foo"', legacy_mode: true)).to eq("foo")
- end
+ it "parses a string" do
+ expect(subject.parse('"foo"', legacy_mode: false)).to eq("foo")
+ end
- it "parses a true bool" do
- expect(subject.parse("true", legacy_mode: true)).to be(true)
- end
+ it "parses a true bool" do
+ expect(subject.parse("true", legacy_mode: false)).to be(true)
+ end
- it "parses a false bool" do
- expect(subject.parse("false", legacy_mode: true)).to be(false)
- end
+ it "parses a false bool" do
+ expect(subject.parse("false", legacy_mode: false)).to be(false)
end
end
- describe ".parse!" do
- context "legacy_mode is disabled by default" do
- it "parses an object" do
- expect(subject.parse!('{ "foo": "bar" }')).to eq({ "foo" => "bar" })
- end
+ context "legacy_mode is enabled" do
+ it "parses an object" do
+ expect(subject.parse('{ "foo": "bar" }', legacy_mode: true)).to eq({ "foo" => "bar" })
+ end
- it "parses an array" do
- expect(subject.parse!('[{ "foo": "bar" }]')).to eq([{ "foo" => "bar" }])
- end
+ it "parses an array" do
+ expect(subject.parse('[{ "foo": "bar" }]', legacy_mode: true)).to eq([{ "foo" => "bar" }])
+ end
- it "parses a string" do
- expect(subject.parse!('"foo"', legacy_mode: false)).to eq("foo")
- end
+ it "raises an error on a string" do
+ expect { subject.parse('"foo"', legacy_mode: true) }.to raise_error(JSON::ParserError)
+ end
- it "parses a true bool" do
- expect(subject.parse!("true", legacy_mode: false)).to be(true)
- end
+ it "raises an error on a true bool" do
+ expect { subject.parse("true", legacy_mode: true) }.to raise_error(JSON::ParserError)
+ end
- it "parses a false bool" do
- expect(subject.parse!("false", legacy_mode: false)).to be(false)
- end
+ it "raises an error on a false bool" do
+ expect { subject.parse("false", legacy_mode: true) }.to raise_error(JSON::ParserError)
end
+ end
- context "legacy_mode is enabled" do
- it "parses an object" do
- expect(subject.parse!('{ "foo": "bar" }', legacy_mode: true)).to eq({ "foo" => "bar" })
- end
+ context "feature flag is disabled" do
+ before do
+ stub_feature_flags(json_wrapper_legacy_mode: false)
+ end
- it "parses an array" do
- expect(subject.parse!('[{ "foo": "bar" }]', legacy_mode: true)).to eq([{ "foo" => "bar" }])
- end
+ it "parses an object" do
+ expect(subject.parse('{ "foo": "bar" }', legacy_mode: true)).to eq({ "foo" => "bar" })
+ end
- it "raises an error on a string" do
- expect { subject.parse!('"foo"', legacy_mode: true) }.to raise_error(JSON::ParserError)
- end
+ it "parses an array" do
+ expect(subject.parse('[{ "foo": "bar" }]', legacy_mode: true)).to eq([{ "foo" => "bar" }])
+ end
- it "raises an error on a true bool" do
- expect { subject.parse!("true", legacy_mode: true) }.to raise_error(JSON::ParserError)
- end
+ it "parses a string" do
+ expect(subject.parse('"foo"', legacy_mode: true)).to eq("foo")
+ end
- it "raises an error on a false bool" do
- expect { subject.parse!("false", legacy_mode: true) }.to raise_error(JSON::ParserError)
- end
+ it "parses a true bool" do
+ expect(subject.parse("true", legacy_mode: true)).to be(true)
end
- context "feature flag is disabled" do
- before do
- stub_feature_flags(json_wrapper_legacy_mode: false)
- end
+ it "parses a false bool" do
+ expect(subject.parse("false", legacy_mode: true)).to be(false)
+ end
+ end
+ end
- it "parses an object" do
- expect(subject.parse!('{ "foo": "bar" }', legacy_mode: true)).to eq({ "foo" => "bar" })
- end
+ describe ".parse!" do
+ context "legacy_mode is disabled by default" do
+ it "parses an object" do
+ expect(subject.parse!('{ "foo": "bar" }')).to eq({ "foo" => "bar" })
+ end
- it "parses an array" do
- expect(subject.parse!('[{ "foo": "bar" }]', legacy_mode: true)).to eq([{ "foo" => "bar" }])
- end
+ it "parses an array" do
+ expect(subject.parse!('[{ "foo": "bar" }]')).to eq([{ "foo" => "bar" }])
+ end
- it "parses a string" do
- expect(subject.parse!('"foo"', legacy_mode: true)).to eq("foo")
- end
+ it "parses a string" do
+ expect(subject.parse!('"foo"', legacy_mode: false)).to eq("foo")
+ end
- it "parses a true bool" do
- expect(subject.parse!("true", legacy_mode: true)).to be(true)
- end
+ it "parses a true bool" do
+ expect(subject.parse!("true", legacy_mode: false)).to be(true)
+ end
- it "parses a false bool" do
- expect(subject.parse!("false", legacy_mode: true)).to be(false)
- end
+ it "parses a false bool" do
+ expect(subject.parse!("false", legacy_mode: false)).to be(false)
end
end
- describe ".dump" do
- it "dumps an object" do
- expect(subject.dump({ "foo" => "bar" })).to eq('{"foo":"bar"}')
+ context "legacy_mode is enabled" do
+ it "parses an object" do
+ expect(subject.parse!('{ "foo": "bar" }', legacy_mode: true)).to eq({ "foo" => "bar" })
end
- it "dumps an array" do
- expect(subject.dump([{ "foo" => "bar" }])).to eq('[{"foo":"bar"}]')
+ it "parses an array" do
+ expect(subject.parse!('[{ "foo": "bar" }]', legacy_mode: true)).to eq([{ "foo" => "bar" }])
end
- it "dumps a string" do
- expect(subject.dump("foo")).to eq('"foo"')
+ it "raises an error on a string" do
+ expect { subject.parse!('"foo"', legacy_mode: true) }.to raise_error(JSON::ParserError)
end
- it "dumps a true bool" do
- expect(subject.dump(true)).to eq("true")
+ it "raises an error on a true bool" do
+ expect { subject.parse!("true", legacy_mode: true) }.to raise_error(JSON::ParserError)
end
- it "dumps a false bool" do
- expect(subject.dump(false)).to eq("false")
+ it "raises an error on a false bool" do
+ expect { subject.parse!("false", legacy_mode: true) }.to raise_error(JSON::ParserError)
end
end
- describe ".generate" do
- let(:obj) do
- { test: true, "foo.bar" => "baz", is_json: 1, some: [1, 2, 3] }
+ context "feature flag is disabled" do
+ before do
+ stub_feature_flags(json_wrapper_legacy_mode: false)
end
- it "generates JSON" do
- expected_string = <<~STR.chomp
- {"test":true,"foo.bar":"baz","is_json":1,"some":[1,2,3]}
- STR
+ it "parses an object" do
+ expect(subject.parse!('{ "foo": "bar" }', legacy_mode: true)).to eq({ "foo" => "bar" })
+ end
- expect(subject.generate(obj)).to eq(expected_string)
+ it "parses an array" do
+ expect(subject.parse!('[{ "foo": "bar" }]', legacy_mode: true)).to eq([{ "foo" => "bar" }])
end
- it "allows you to customise the output" do
- opts = {
- indent: " ",
- space: " ",
- space_before: " ",
- object_nl: "\n",
- array_nl: "\n"
- }
+ it "parses a string" do
+ expect(subject.parse!('"foo"', legacy_mode: true)).to eq("foo")
+ end
- json = subject.generate(obj, opts)
-
- expected_string = <<~STR.chomp
- {
- "test" : true,
- "foo.bar" : "baz",
- "is_json" : 1,
- "some" : [
- 1,
- 2,
- 3
- ]
- }
- STR
+ it "parses a true bool" do
+ expect(subject.parse!("true", legacy_mode: true)).to be(true)
+ end
- expect(json).to eq(expected_string)
+ it "parses a false bool" do
+ expect(subject.parse!("false", legacy_mode: true)).to be(false)
end
end
+ end
- describe ".pretty_generate" do
- let(:obj) do
- {
- test: true,
- "foo.bar" => "baz",
- is_json: 1,
- some: [1, 2, 3],
- more: { test: true },
- multi_line_empty_array: [],
- multi_line_empty_obj: {}
- }
- end
+ describe ".dump" do
+ it "dumps an object" do
+ expect(subject.dump({ "foo" => "bar" })).to eq('{"foo":"bar"}')
+ end
- it "generates pretty JSON" do
- expected_string = <<~STR.chomp
- {
- "test": true,
- "foo.bar": "baz",
- "is_json": 1,
- "some": [
- 1,
- 2,
- 3
- ],
- "more": {
- "test": true
- },
- "multi_line_empty_array": [
-
- ],
- "multi_line_empty_obj": {
- }
- }
- STR
+ it "dumps an array" do
+ expect(subject.dump([{ "foo" => "bar" }])).to eq('[{"foo":"bar"}]')
+ end
- expect(subject.pretty_generate(obj)).to eq(expected_string)
- end
+ it "dumps a string" do
+ expect(subject.dump("foo")).to eq('"foo"')
+ end
- it "allows you to customise the output" do
- opts = {
- space_before: " "
- }
+ it "dumps a true bool" do
+ expect(subject.dump(true)).to eq("true")
+ end
- json = subject.pretty_generate(obj, opts)
-
- expected_string = <<~STR.chomp
- {
- "test" : true,
- "foo.bar" : "baz",
- "is_json" : 1,
- "some" : [
- 1,
- 2,
- 3
- ],
- "more" : {
- "test" : true
- },
- "multi_line_empty_array" : [
-
- ],
- "multi_line_empty_obj" : {
- }
- }
- STR
+ it "dumps a false bool" do
+ expect(subject.dump(false)).to eq("false")
+ end
+ end
- expect(json).to eq(expected_string)
- end
+ describe ".generate" do
+ let(:obj) do
+ { test: true, "foo.bar" => "baz", is_json: 1, some: [1, 2, 3] }
end
- context "the feature table is missing" do
- before do
- allow(Feature::FlipperFeature).to receive(:table_exists?).and_return(false)
- end
+ it "generates JSON" do
+ expected_string = <<~STR.chomp
+ {"test":true,"foo.bar":"baz","is_json":1,"some":[1,2,3]}
+ STR
+
+ expect(subject.generate(obj)).to eq(expected_string)
+ end
- it "skips legacy mode handling" do
- expect(Feature).not_to receive(:enabled?).with(:json_wrapper_legacy_mode, default_enabled: true)
+ it "allows you to customise the output" do
+ opts = {
+ indent: " ",
+ space: " ",
+ space_before: " ",
+ object_nl: "\n",
+ array_nl: "\n"
+ }
- subject.send(:handle_legacy_mode!, {})
- end
+ json = subject.generate(obj, opts)
- it "skips oj feature detection" do
- expect(Feature).not_to receive(:enabled?).with(:oj_json, default_enabled: true)
+ expected_string = <<~STR.chomp
+ {
+ "test" : true,
+ "foo.bar" : "baz",
+ "is_json" : 1,
+ "some" : [
+ 1,
+ 2,
+ 3
+ ]
+ }
+ STR
- subject.send(:enable_oj?)
- end
+ expect(json).to eq(expected_string)
end
+ end
- context "the database is missing" do
- before do
- allow(Feature::FlipperFeature).to receive(:table_exists?).and_raise(PG::ConnectionBad)
- end
+ describe ".pretty_generate" do
+ let(:obj) do
+ {
+ test: true,
+ "foo.bar" => "baz",
+ is_json: 1,
+ some: [1, 2, 3],
+ more: { test: true },
+ multi_line_empty_array: [],
+ multi_line_empty_obj: {}
+ }
+ end
- it "still parses json" do
- expect(subject.parse("{}")).to eq({})
- end
+ it "generates pretty JSON" do
+ expected_string = <<~STR.chomp
+ {
+ "test": true,
+ "foo.bar": "baz",
+ "is_json": 1,
+ "some": [
+ 1,
+ 2,
+ 3
+ ],
+ "more": {
+ "test": true
+ },
+ "multi_line_empty_array": [
+
+ ],
+ "multi_line_empty_obj": {
+ }
+ }
+ STR
- it "still generates json" do
- expect(subject.dump({})).to eq("{}")
- end
+ expect(subject.pretty_generate(obj)).to eq(expected_string)
+ end
+
+ it "allows you to customise the output" do
+ opts = {
+ space_before: " "
+ }
+
+ json = subject.pretty_generate(obj, opts)
+
+ expected_string = <<~STR.chomp
+ {
+ "test" : true,
+ "foo.bar" : "baz",
+ "is_json" : 1,
+ "some" : [
+ 1,
+ 2,
+ 3
+ ],
+ "more" : {
+ "test" : true
+ },
+ "multi_line_empty_array" : [
+
+ ],
+ "multi_line_empty_obj" : {
+ }
+ }
+ STR
+
+ expect(json).to eq(expected_string)
end
end
- context "oj gem" do
+ context "the feature table is missing" do
before do
- stub_feature_flags(oj_json: true)
+ allow(Feature::FlipperFeature).to receive(:table_exists?).and_return(false)
end
- it_behaves_like "json"
+ it "skips legacy mode handling" do
+ expect(Feature).not_to receive(:enabled?).with(:json_wrapper_legacy_mode, default_enabled: true)
- describe "#enable_oj?" do
- it "returns true" do
- expect(subject.enable_oj?).to be(true)
- end
+ subject.send(:handle_legacy_mode!, {})
end
end
- context "json gem" do
+ context "the database is missing" do
before do
- stub_feature_flags(oj_json: false)
+ allow(Feature::FlipperFeature).to receive(:table_exists?).and_raise(PG::ConnectionBad)
end
- it_behaves_like "json"
+ it "still parses json" do
+ expect(subject.parse("{}")).to eq({})
+ end
- describe "#enable_oj?" do
- it "returns false" do
- expect(subject.enable_oj?).to be(false)
- end
+ it "still generates json" do
+ expect(subject.dump({})).to eq("{}")
end
end
@@ -353,47 +317,25 @@ RSpec.describe Gitlab::Json do
let(:env) { {} }
let(:result) { "{\"test\":true}" }
- context "oj is enabled" do
+ context "grape_gitlab_json flag is enabled" do
before do
- stub_feature_flags(oj_json: true)
+ stub_feature_flags(grape_gitlab_json: true)
end
- context "grape_gitlab_json flag is enabled" do
- before do
- stub_feature_flags(grape_gitlab_json: true)
- end
-
- it "generates JSON" do
- expect(subject).to eq(result)
- end
-
- it "uses Gitlab::Json" do
- expect(Gitlab::Json).to receive(:dump).with(obj)
-
- subject
- end
+ it "generates JSON" do
+ expect(subject).to eq(result)
end
- context "grape_gitlab_json flag is disabled" do
- before do
- stub_feature_flags(grape_gitlab_json: false)
- end
-
- it "generates JSON" do
- expect(subject).to eq(result)
- end
+ it "uses Gitlab::Json" do
+ expect(Gitlab::Json).to receive(:dump).with(obj)
- it "uses Grape::Formatter::Json" do
- expect(Grape::Formatter::Json).to receive(:call).with(obj, env)
-
- subject
- end
+ subject
end
end
- context "oj is disabled" do
+ context "grape_gitlab_json flag is disabled" do
before do
- stub_feature_flags(oj_json: false)
+ stub_feature_flags(grape_gitlab_json: false)
end
it "generates JSON" do
diff --git a/spec/lib/gitlab/kubernetes/helm/api_spec.rb b/spec/lib/gitlab/kubernetes/helm/api_spec.rb
index bcc95bdbf2b..e022f5bd912 100644
--- a/spec/lib/gitlab/kubernetes/helm/api_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/api_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Gitlab::Kubernetes::Helm::API do
let(:files) { {} }
let(:command) do
- Gitlab::Kubernetes::Helm::InstallCommand.new(
+ Gitlab::Kubernetes::Helm::V2::InstallCommand.new(
name: application_name,
chart: 'chart-name',
rbac: rbac,
@@ -142,7 +142,7 @@ RSpec.describe Gitlab::Kubernetes::Helm::API do
end
context 'with a service account' do
- let(:command) { Gitlab::Kubernetes::Helm::InitCommand.new(name: application_name, files: files, rbac: rbac) }
+ let(:command) { Gitlab::Kubernetes::Helm::V2::InitCommand.new(name: application_name, files: files, rbac: rbac) }
context 'rbac-enabled cluster' do
let(:rbac) { true }
diff --git a/spec/lib/gitlab/kubernetes/helm/base_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/base_command_spec.rb
deleted file mode 100644
index a7abd6ab1bf..00000000000
--- a/spec/lib/gitlab/kubernetes/helm/base_command_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Kubernetes::Helm::BaseCommand do
- subject(:base_command) do
- test_class.new(rbac)
- end
-
- let(:application) { create(:clusters_applications_helm) }
- let(:rbac) { false }
-
- let(:test_class) do
- Class.new(Gitlab::Kubernetes::Helm::BaseCommand) do
- def initialize(rbac)
- super(
- name: 'test-class-name',
- rbac: rbac,
- files: { some: 'value' }
- )
- end
- end
- end
-
- it_behaves_like 'helm command generator' do
- let(:commands) { '' }
- end
-
- describe '#pod_name' do
- subject { base_command.pod_name }
-
- it { is_expected.to eq('install-test-class-name') }
- end
-
- it_behaves_like 'helm command' do
- let(:command) { base_command }
- end
-end
diff --git a/spec/lib/gitlab/kubernetes/helm/certificate_spec.rb b/spec/lib/gitlab/kubernetes/helm/certificate_spec.rb
deleted file mode 100644
index b446c5e1149..00000000000
--- a/spec/lib/gitlab/kubernetes/helm/certificate_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-
-RSpec.describe Gitlab::Kubernetes::Helm::Certificate do
- describe '.generate_root' do
- subject { described_class.generate_root }
-
- it 'generates a root CA that expires a long way in the future' do
- expect(subject.cert.not_after).to be > 999.years.from_now
- end
- end
-
- describe '#issue' do
- subject { described_class.generate_root.issue }
-
- it 'generates a cert that expires soon' do
- expect(subject.cert.not_after).to be < 60.minutes.from_now
- end
-
- context 'passing in INFINITE_EXPIRY' do
- subject { described_class.generate_root.issue(expires_in: described_class::INFINITE_EXPIRY) }
-
- it 'generates a cert that expires a long way in the future' do
- expect(subject.cert.not_after).to be > 999.years.from_now
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/kubernetes/helm/delete_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/delete_command_spec.rb
deleted file mode 100644
index ff2c2d76f22..00000000000
--- a/spec/lib/gitlab/kubernetes/helm/delete_command_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Kubernetes::Helm::DeleteCommand do
- subject(:delete_command) { described_class.new(name: app_name, rbac: rbac, files: files) }
-
- let(:app_name) { 'app-name' }
- let(:rbac) { true }
- let(:files) { {} }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- export HELM_HOST="localhost:44134"
- tiller -listen ${HELM_HOST} -alsologtostderr &
- helm init --client-only
- helm delete --purge app-name
- EOS
- end
- end
-
- describe '#pod_name' do
- subject { delete_command.pod_name }
-
- it { is_expected.to eq('uninstall-app-name') }
- end
-
- it_behaves_like 'helm command' do
- let(:command) { delete_command }
- end
-
- describe '#delete_command' do
- it 'deletes the release' do
- expect(subject.delete_command).to eq('helm delete --purge app-name')
- end
- end
-end
diff --git a/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
deleted file mode 100644
index d538ed12a07..00000000000
--- a/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Kubernetes::Helm::InitCommand do
- subject(:init_command) { described_class.new(name: application.name, files: files, rbac: rbac) }
-
- let(:application) { create(:clusters_applications_helm) }
- let(:rbac) { false }
- let(:files) { {} }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem
- EOS
- end
- end
-
- context 'on a rbac-enabled cluster' do
- let(:rbac) { true }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem --service-account tiller
- EOS
- end
- end
- end
-
- it_behaves_like 'helm command' do
- let(:command) { init_command }
- end
-end
diff --git a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
deleted file mode 100644
index 6ed7323c96f..00000000000
--- a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
+++ /dev/null
@@ -1,214 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Kubernetes::Helm::InstallCommand do
- subject(:install_command) do
- described_class.new(
- name: 'app-name',
- chart: 'chart-name',
- rbac: rbac,
- files: files,
- version: version,
- repository: repository,
- preinstall: preinstall,
- postinstall: postinstall
- )
- end
-
- let(:files) { { 'ca.pem': 'some file content' } }
- let(:repository) { 'https://repository.example.com' }
- let(:rbac) { false }
- let(:version) { '1.2.3' }
- let(:preinstall) { nil }
- let(:postinstall) { nil }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- export HELM_HOST="localhost:44134"
- tiller -listen ${HELM_HOST} -alsologtostderr &
- helm init --client-only
- helm repo add app-name https://repository.example.com
- helm repo update
- #{helm_install_comand}
- EOS
- end
-
- let(:helm_install_comand) do
- <<~EOS.squish
- helm upgrade app-name chart-name
- --install
- --atomic
- --cleanup-on-fail
- --reset-values
- --version 1.2.3
- --set rbac.create\\=false,rbac.enabled\\=false
- --namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml
- EOS
- end
- end
-
- context 'when rbac is true' do
- let(:rbac) { true }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- export HELM_HOST="localhost:44134"
- tiller -listen ${HELM_HOST} -alsologtostderr &
- helm init --client-only
- helm repo add app-name https://repository.example.com
- helm repo update
- #{helm_install_command}
- EOS
- end
-
- let(:helm_install_command) do
- <<~EOS.squish
- helm upgrade app-name chart-name
- --install
- --atomic
- --cleanup-on-fail
- --reset-values
- --version 1.2.3
- --set rbac.create\\=true,rbac.enabled\\=true
- --namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml
- EOS
- end
- end
- end
-
- context 'when there is a pre-install script' do
- let(:preinstall) { ['/bin/date', '/bin/true'] }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- export HELM_HOST="localhost:44134"
- tiller -listen ${HELM_HOST} -alsologtostderr &
- helm init --client-only
- helm repo add app-name https://repository.example.com
- helm repo update
- /bin/date
- /bin/true
- #{helm_install_command}
- EOS
- end
-
- let(:helm_install_command) do
- <<~EOS.squish
- helm upgrade app-name chart-name
- --install
- --atomic
- --cleanup-on-fail
- --reset-values
- --version 1.2.3
- --set rbac.create\\=false,rbac.enabled\\=false
- --namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml
- EOS
- end
- end
- end
-
- context 'when there is a post-install script' do
- let(:postinstall) { ['/bin/date', "/bin/false\n"] }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- export HELM_HOST="localhost:44134"
- tiller -listen ${HELM_HOST} -alsologtostderr &
- helm init --client-only
- helm repo add app-name https://repository.example.com
- helm repo update
- #{helm_install_command}
- /bin/date
- /bin/false
- EOS
- end
-
- let(:helm_install_command) do
- <<~EOS.squish
- helm upgrade app-name chart-name
- --install
- --atomic
- --cleanup-on-fail
- --reset-values
- --version 1.2.3
- --set rbac.create\\=false,rbac.enabled\\=false
- --namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml
- EOS
- end
- end
- end
-
- context 'when there is no ca.pem file' do
- let(:files) { { 'file.txt': 'some content' } }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- export HELM_HOST="localhost:44134"
- tiller -listen ${HELM_HOST} -alsologtostderr &
- helm init --client-only
- helm repo add app-name https://repository.example.com
- helm repo update
- #{helm_install_command}
- EOS
- end
-
- let(:helm_install_command) do
- <<~EOS.squish
- helm upgrade app-name chart-name
- --install
- --atomic
- --cleanup-on-fail
- --reset-values
- --version 1.2.3
- --set rbac.create\\=false,rbac.enabled\\=false
- --namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml
- EOS
- end
- end
- end
-
- context 'when there is no version' do
- let(:version) { nil }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- export HELM_HOST="localhost:44134"
- tiller -listen ${HELM_HOST} -alsologtostderr &
- helm init --client-only
- helm repo add app-name https://repository.example.com
- helm repo update
- #{helm_install_command}
- EOS
- end
-
- let(:helm_install_command) do
- <<~EOS.squish
- helm upgrade app-name chart-name
- --install
- --atomic
- --cleanup-on-fail
- --reset-values
- --set rbac.create\\=false,rbac.enabled\\=false
- --namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml
- EOS
- end
- end
- end
-
- it_behaves_like 'helm command' do
- let(:command) { install_command }
- end
-end
diff --git a/spec/lib/gitlab/kubernetes/helm/patch_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/patch_command_spec.rb
deleted file mode 100644
index 487a38f286d..00000000000
--- a/spec/lib/gitlab/kubernetes/helm/patch_command_spec.rb
+++ /dev/null
@@ -1,114 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Kubernetes::Helm::PatchCommand do
- let(:files) { { 'ca.pem': 'some file content' } }
- let(:repository) { 'https://repository.example.com' }
- let(:rbac) { false }
- let(:version) { '1.2.3' }
-
- subject(:patch_command) do
- described_class.new(
- name: 'app-name',
- chart: 'chart-name',
- rbac: rbac,
- files: files,
- version: version,
- repository: repository
- )
- end
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- export HELM_HOST="localhost:44134"
- tiller -listen ${HELM_HOST} -alsologtostderr &
- helm init --client-only
- helm repo add app-name https://repository.example.com
- helm repo update
- #{helm_upgrade_comand}
- EOS
- end
-
- let(:helm_upgrade_comand) do
- <<~EOS.squish
- helm upgrade app-name chart-name
- --reuse-values
- --version 1.2.3
- --namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml
- EOS
- end
- end
-
- context 'when rbac is true' do
- let(:rbac) { true }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- export HELM_HOST="localhost:44134"
- tiller -listen ${HELM_HOST} -alsologtostderr &
- helm init --client-only
- helm repo add app-name https://repository.example.com
- helm repo update
- #{helm_upgrade_command}
- EOS
- end
-
- let(:helm_upgrade_command) do
- <<~EOS.squish
- helm upgrade app-name chart-name
- --reuse-values
- --version 1.2.3
- --namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml
- EOS
- end
- end
- end
-
- context 'when there is no ca.pem file' do
- let(:files) { { 'file.txt': 'some content' } }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- export HELM_HOST="localhost:44134"
- tiller -listen ${HELM_HOST} -alsologtostderr &
- helm init --client-only
- helm repo add app-name https://repository.example.com
- helm repo update
- #{helm_upgrade_command}
- EOS
- end
-
- let(:helm_upgrade_command) do
- <<~EOS.squish
- helm upgrade app-name chart-name
- --reuse-values
- --version 1.2.3
- --namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml
- EOS
- end
- end
- end
-
- context 'when there is no version' do
- let(:version) { nil }
-
- it { expect { patch_command }.to raise_error(ArgumentError, 'version is required') }
- end
-
- describe '#pod_name' do
- subject { patch_command.pod_name }
-
- it { is_expected.to eq 'install-app-name' }
- end
-
- it_behaves_like 'helm command' do
- let(:command) { patch_command }
- end
-end
diff --git a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
index 54e3289dd25..6d97790fc8b 100644
--- a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
@@ -4,75 +4,84 @@ require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::Pod do
describe '#generate' do
- let(:app) { create(:clusters_applications_prometheus) }
- let(:command) { app.install_command }
- let(:namespace) { Gitlab::Kubernetes::Helm::NAMESPACE }
- let(:service_account_name) { nil }
+ using RSpec::Parameterized::TableSyntax
- subject { described_class.new(command, namespace, service_account_name: service_account_name) }
+ where(:helm_major_version, :expected_helm_version, :expected_command_env) do
+ 2 | '2.16.9' | [:TILLER_NAMESPACE]
+ 3 | '3.2.4' | nil
+ end
- context 'with a command' do
- it 'generates a Kubeclient::Resource' do
- expect(subject.generate).to be_a_kind_of(Kubeclient::Resource)
- end
+ with_them do
+ let(:cluster) { create(:cluster, helm_major_version: helm_major_version) }
+ let(:app) { create(:clusters_applications_prometheus, cluster: cluster) }
+ let(:command) { app.install_command }
+ let(:namespace) { Gitlab::Kubernetes::Helm::NAMESPACE }
+ let(:service_account_name) { nil }
- it 'generates the appropriate metadata' do
- metadata = subject.generate.metadata
- expect(metadata.name).to eq("install-#{app.name}")
- expect(metadata.namespace).to eq('gitlab-managed-apps')
- expect(metadata.labels['gitlab.org/action']).to eq('install')
- expect(metadata.labels['gitlab.org/application']).to eq(app.name)
- end
+ subject { described_class.new(command, namespace, service_account_name: service_account_name) }
- it 'generates a container spec' do
- spec = subject.generate.spec
- expect(spec.containers.count).to eq(1)
- end
+ context 'with a command' do
+ it 'generates a Kubeclient::Resource' do
+ expect(subject.generate).to be_a_kind_of(Kubeclient::Resource)
+ end
- it 'generates the appropriate specifications for the container' do
- container = subject.generate.spec.containers.first
- expect(container.name).to eq('helm')
- expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.16.9-kube-1.13.12')
- expect(container.env.count).to eq(3)
- expect(container.env.map(&:name)).to match_array([:HELM_VERSION, :TILLER_NAMESPACE, :COMMAND_SCRIPT])
- expect(container.command).to match_array(["/bin/sh"])
- expect(container.args).to match_array(["-c", "$(COMMAND_SCRIPT)"])
- end
+ it 'generates the appropriate metadata' do
+ metadata = subject.generate.metadata
+ expect(metadata.name).to eq("install-#{app.name}")
+ expect(metadata.namespace).to eq('gitlab-managed-apps')
+ expect(metadata.labels['gitlab.org/action']).to eq('install')
+ expect(metadata.labels['gitlab.org/application']).to eq(app.name)
+ end
- it 'includes a never restart policy' do
- spec = subject.generate.spec
- expect(spec.restartPolicy).to eq('Never')
- end
+ it 'generates a container spec' do
+ spec = subject.generate.spec
+ expect(spec.containers.count).to eq(1)
+ end
- it 'includes volumes for the container' do
- container = subject.generate.spec.containers.first
- expect(container.volumeMounts.first['name']).to eq('configuration-volume')
- expect(container.volumeMounts.first['mountPath']).to eq("/data/helm/#{app.name}/config")
- end
+ it 'generates the appropriate specifications for the container' do
+ container = subject.generate.spec.containers.first
+ expect(container.name).to eq('helm')
+ expect(container.image).to eq("registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/#{expected_helm_version}-kube-1.13.12-alpine-3.12")
+ expect(container.env.map(&:name)).to include(:HELM_VERSION, :COMMAND_SCRIPT, *expected_command_env)
+ expect(container.command).to match_array(["/bin/sh"])
+ expect(container.args).to match_array(["-c", "$(COMMAND_SCRIPT)"])
+ end
- it 'includes a volume inside the specification' do
- spec = subject.generate.spec
- expect(spec.volumes.first['name']).to eq('configuration-volume')
- end
+ it 'includes a never restart policy' do
+ spec = subject.generate.spec
+ expect(spec.restartPolicy).to eq('Never')
+ end
- it 'mounts configMap specification in the volume' do
- volume = subject.generate.spec.volumes.first
- expect(volume.configMap['name']).to eq("values-content-configuration-#{app.name}")
- expect(volume.configMap['items'].first['key']).to eq(:'values.yaml')
- expect(volume.configMap['items'].first['path']).to eq(:'values.yaml')
- end
+ it 'includes volumes for the container' do
+ container = subject.generate.spec.containers.first
+ expect(container.volumeMounts.first['name']).to eq('configuration-volume')
+ expect(container.volumeMounts.first['mountPath']).to eq("/data/helm/#{app.name}/config")
+ end
- it 'has no serviceAccountName' do
- spec = subject.generate.spec
- expect(spec.serviceAccountName).to be_nil
- end
+ it 'includes a volume inside the specification' do
+ spec = subject.generate.spec
+ expect(spec.volumes.first['name']).to eq('configuration-volume')
+ end
- context 'with a service_account_name' do
- let(:service_account_name) { 'sa' }
+ it 'mounts configMap specification in the volume' do
+ volume = subject.generate.spec.volumes.first
+ expect(volume.configMap['name']).to eq("values-content-configuration-#{app.name}")
+ expect(volume.configMap['items'].first['key']).to eq(:'values.yaml')
+ expect(volume.configMap['items'].first['path']).to eq(:'values.yaml')
+ end
- it 'uses the serviceAccountName provided' do
+ it 'has no serviceAccountName' do
spec = subject.generate.spec
- expect(spec.serviceAccountName).to eq(service_account_name)
+ expect(spec.serviceAccountName).to be_nil
+ end
+
+ context 'with a service_account_name' do
+ let(:service_account_name) { 'sa' }
+
+ it 'uses the serviceAccountName provided' do
+ spec = subject.generate.spec
+ expect(spec.serviceAccountName).to eq(service_account_name)
+ end
end
end
end
diff --git a/spec/lib/gitlab/kubernetes/helm/reset_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/reset_command_spec.rb
deleted file mode 100644
index 5a3ba59b8c0..00000000000
--- a/spec/lib/gitlab/kubernetes/helm/reset_command_spec.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Kubernetes::Helm::ResetCommand do
- subject(:reset_command) { described_class.new(name: name, rbac: rbac, files: files) }
-
- let(:rbac) { true }
- let(:name) { 'helm' }
- let(:files) { {} }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS
- helm reset
- kubectl delete replicaset -n gitlab-managed-apps -l name\\=tiller
- kubectl delete clusterrolebinding tiller-admin
- EOS
- end
- end
-
- context 'when there is a ca.pem file' do
- let(:files) { { 'ca.pem': 'some file content' } }
-
- it_behaves_like 'helm command generator' do
- let(:commands) do
- <<~EOS1.squish + "\n" + <<~EOS2
- helm reset
- --tls
- --tls-ca-cert /data/helm/helm/config/ca.pem
- --tls-cert /data/helm/helm/config/cert.pem
- --tls-key /data/helm/helm/config/key.pem
- EOS1
- kubectl delete replicaset -n gitlab-managed-apps -l name\\=tiller
- kubectl delete clusterrolebinding tiller-admin
- EOS2
- end
- end
- end
-
- describe '#pod_name' do
- subject { reset_command.pod_name }
-
- it { is_expected.to eq('uninstall-helm') }
- end
-
- it_behaves_like 'helm command' do
- let(:command) { reset_command }
- end
-end
diff --git a/spec/lib/gitlab/kubernetes/helm/v2/base_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/v2/base_command_spec.rb
new file mode 100644
index 00000000000..3d2b36b9094
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/helm/v2/base_command_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kubernetes::Helm::V2::BaseCommand do
+ subject(:base_command) do
+ test_class.new(rbac)
+ end
+
+ let(:application) { create(:clusters_applications_helm) }
+ let(:rbac) { false }
+
+ let(:test_class) do
+ Class.new(described_class) do
+ def initialize(rbac)
+ super(
+ name: 'test-class-name',
+ rbac: rbac,
+ files: { some: 'value' }
+ )
+ end
+ end
+ end
+
+ describe 'HELM_VERSION' do
+ subject { described_class::HELM_VERSION }
+
+ it { is_expected.to match /^2\.\d+\.\d+$/ }
+ end
+
+ describe '#env' do
+ subject { base_command.env }
+
+ it { is_expected.to include(TILLER_NAMESPACE: 'gitlab-managed-apps') }
+ end
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) { '' }
+ end
+
+ describe '#pod_name' do
+ subject { base_command.pod_name }
+
+ it { is_expected.to eq('install-test-class-name') }
+ end
+
+ it_behaves_like 'helm command' do
+ let(:command) { base_command }
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/helm/v2/certificate_spec.rb b/spec/lib/gitlab/kubernetes/helm/v2/certificate_spec.rb
new file mode 100644
index 00000000000..a3f0fd9eb9b
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/helm/v2/certificate_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kubernetes::Helm::V2::Certificate do
+ describe '.generate_root' do
+ subject { described_class.generate_root }
+
+ it 'generates a root CA that expires a long way in the future' do
+ expect(subject.cert.not_after).to be > 999.years.from_now
+ end
+ end
+
+ describe '#issue' do
+ subject { described_class.generate_root.issue }
+
+ it 'generates a cert that expires soon' do
+ expect(subject.cert.not_after).to be < 60.minutes.from_now
+ end
+
+ context 'passing in INFINITE_EXPIRY' do
+ subject { described_class.generate_root.issue(expires_in: described_class::INFINITE_EXPIRY) }
+
+ it 'generates a cert that expires a long way in the future' do
+ expect(subject.cert.not_after).to be > 999.years.from_now
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/helm/v2/delete_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/v2/delete_command_spec.rb
new file mode 100644
index 00000000000..4a3a41dba4a
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/helm/v2/delete_command_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kubernetes::Helm::V2::DeleteCommand do
+ subject(:delete_command) { described_class.new(name: app_name, rbac: rbac, files: files) }
+
+ let(:app_name) { 'app-name' }
+ let(:rbac) { true }
+ let(:files) { {} }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ export HELM_HOST="localhost:44134"
+ tiller -listen ${HELM_HOST} -alsologtostderr &
+ helm init --client-only
+ helm delete --purge app-name
+ EOS
+ end
+ end
+
+ describe '#pod_name' do
+ subject { delete_command.pod_name }
+
+ it { is_expected.to eq('uninstall-app-name') }
+ end
+
+ it_behaves_like 'helm command' do
+ let(:command) { delete_command }
+ end
+
+ describe '#delete_command' do
+ it 'deletes the release' do
+ expect(subject.delete_command).to eq('helm delete --purge app-name')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/helm/v2/init_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/v2/init_command_spec.rb
new file mode 100644
index 00000000000..8ae78ada15c
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/helm/v2/init_command_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kubernetes::Helm::V2::InitCommand do
+ subject(:init_command) { described_class.new(name: application.name, files: files, rbac: rbac) }
+
+ let(:application) { create(:clusters_applications_helm) }
+ let(:rbac) { false }
+ let(:files) { {} }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem
+ EOS
+ end
+ end
+
+ context 'on a rbac-enabled cluster' do
+ let(:rbac) { true }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem --service-account tiller
+ EOS
+ end
+ end
+ end
+
+ it_behaves_like 'helm command' do
+ let(:command) { init_command }
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/helm/v2/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/v2/install_command_spec.rb
new file mode 100644
index 00000000000..250d1a82e7a
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/helm/v2/install_command_spec.rb
@@ -0,0 +1,183 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kubernetes::Helm::V2::InstallCommand do
+ subject(:install_command) do
+ described_class.new(
+ name: 'app-name',
+ chart: 'chart-name',
+ rbac: rbac,
+ files: files,
+ version: version,
+ repository: repository,
+ preinstall: preinstall,
+ postinstall: postinstall
+ )
+ end
+
+ let(:files) { { 'ca.pem': 'some file content' } }
+ let(:repository) { 'https://repository.example.com' }
+ let(:rbac) { false }
+ let(:version) { '1.2.3' }
+ let(:preinstall) { nil }
+ let(:postinstall) { nil }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ export HELM_HOST="localhost:44134"
+ tiller -listen ${HELM_HOST} -alsologtostderr &
+ helm init --client-only
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_install_comand}
+ EOS
+ end
+
+ let(:helm_install_comand) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --install
+ --atomic
+ --cleanup-on-fail
+ --reset-values
+ --version 1.2.3
+ --set rbac.create\\=false,rbac.enabled\\=false
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+
+ context 'when rbac is true' do
+ let(:rbac) { true }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ export HELM_HOST="localhost:44134"
+ tiller -listen ${HELM_HOST} -alsologtostderr &
+ helm init --client-only
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_install_command}
+ EOS
+ end
+
+ let(:helm_install_command) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --install
+ --atomic
+ --cleanup-on-fail
+ --reset-values
+ --version 1.2.3
+ --set rbac.create\\=true,rbac.enabled\\=true
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ context 'when there is a pre-install script' do
+ let(:preinstall) { ['/bin/date', '/bin/true'] }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ export HELM_HOST="localhost:44134"
+ tiller -listen ${HELM_HOST} -alsologtostderr &
+ helm init --client-only
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ /bin/date
+ /bin/true
+ #{helm_install_command}
+ EOS
+ end
+
+ let(:helm_install_command) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --install
+ --atomic
+ --cleanup-on-fail
+ --reset-values
+ --version 1.2.3
+ --set rbac.create\\=false,rbac.enabled\\=false
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ context 'when there is a post-install script' do
+ let(:postinstall) { ['/bin/date', "/bin/false\n"] }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ export HELM_HOST="localhost:44134"
+ tiller -listen ${HELM_HOST} -alsologtostderr &
+ helm init --client-only
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_install_command}
+ /bin/date
+ /bin/false
+ EOS
+ end
+
+ let(:helm_install_command) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --install
+ --atomic
+ --cleanup-on-fail
+ --reset-values
+ --version 1.2.3
+ --set rbac.create\\=false,rbac.enabled\\=false
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ context 'when there is no version' do
+ let(:version) { nil }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ export HELM_HOST="localhost:44134"
+ tiller -listen ${HELM_HOST} -alsologtostderr &
+ helm init --client-only
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_install_command}
+ EOS
+ end
+
+ let(:helm_install_command) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --install
+ --atomic
+ --cleanup-on-fail
+ --reset-values
+ --set rbac.create\\=false,rbac.enabled\\=false
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ it_behaves_like 'helm command' do
+ let(:command) { install_command }
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/helm/v2/patch_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/v2/patch_command_spec.rb
new file mode 100644
index 00000000000..98eb77d397c
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/helm/v2/patch_command_spec.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kubernetes::Helm::V2::PatchCommand do
+ let(:files) { { 'ca.pem': 'some file content' } }
+ let(:repository) { 'https://repository.example.com' }
+ let(:rbac) { false }
+ let(:version) { '1.2.3' }
+
+ subject(:patch_command) do
+ described_class.new(
+ name: 'app-name',
+ chart: 'chart-name',
+ rbac: rbac,
+ files: files,
+ version: version,
+ repository: repository
+ )
+ end
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ export HELM_HOST="localhost:44134"
+ tiller -listen ${HELM_HOST} -alsologtostderr &
+ helm init --client-only
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_upgrade_comand}
+ EOS
+ end
+
+ let(:helm_upgrade_comand) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --reuse-values
+ --version 1.2.3
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+
+ context 'when rbac is true' do
+ let(:rbac) { true }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ export HELM_HOST="localhost:44134"
+ tiller -listen ${HELM_HOST} -alsologtostderr &
+ helm init --client-only
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_upgrade_command}
+ EOS
+ end
+
+ let(:helm_upgrade_command) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --reuse-values
+ --version 1.2.3
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ context 'when there is no version' do
+ let(:version) { nil }
+
+ it { expect { patch_command }.to raise_error(ArgumentError, 'version is required') }
+ end
+
+ describe '#pod_name' do
+ subject { patch_command.pod_name }
+
+ it { is_expected.to eq 'install-app-name' }
+ end
+
+ it_behaves_like 'helm command' do
+ let(:command) { patch_command }
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/helm/v2/reset_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/v2/reset_command_spec.rb
new file mode 100644
index 00000000000..9e580cea397
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/helm/v2/reset_command_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kubernetes::Helm::V2::ResetCommand do
+ subject(:reset_command) { described_class.new(name: name, rbac: rbac, files: files) }
+
+ let(:rbac) { true }
+ let(:name) { 'helm' }
+ let(:files) { {} }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ helm reset
+ kubectl delete replicaset -n gitlab-managed-apps -l name\\=tiller
+ kubectl delete clusterrolebinding tiller-admin
+ EOS
+ end
+ end
+
+ context 'when there is a ca.pem file' do
+ let(:files) { { 'ca.pem': 'some file content' } }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS1.squish + "\n" + <<~EOS2
+ helm reset
+ --tls
+ --tls-ca-cert /data/helm/helm/config/ca.pem
+ --tls-cert /data/helm/helm/config/cert.pem
+ --tls-key /data/helm/helm/config/key.pem
+ EOS1
+ kubectl delete replicaset -n gitlab-managed-apps -l name\\=tiller
+ kubectl delete clusterrolebinding tiller-admin
+ EOS2
+ end
+ end
+ end
+
+ describe '#pod_name' do
+ subject { reset_command.pod_name }
+
+ it { is_expected.to eq('uninstall-helm') }
+ end
+
+ it_behaves_like 'helm command' do
+ let(:command) { reset_command }
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/helm/v3/base_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/v3/base_command_spec.rb
new file mode 100644
index 00000000000..ad5ff13b4c9
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/helm/v3/base_command_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kubernetes::Helm::V3::BaseCommand do
+ subject(:base_command) do
+ test_class.new(rbac)
+ end
+
+ let(:application) { create(:clusters_applications_helm) }
+ let(:rbac) { false }
+
+ let(:test_class) do
+ Class.new(described_class) do
+ def initialize(rbac)
+ super(
+ name: 'test-class-name',
+ rbac: rbac,
+ files: { some: 'value' }
+ )
+ end
+ end
+ end
+
+ describe 'HELM_VERSION' do
+ subject { described_class::HELM_VERSION }
+
+ it { is_expected.to match /^3\.\d+\.\d+$/ }
+ end
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) { '' }
+ end
+
+ describe '#pod_name' do
+ subject { base_command.pod_name }
+
+ it { is_expected.to eq('install-test-class-name') }
+ end
+
+ it_behaves_like 'helm command' do
+ let(:command) { base_command }
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/helm/v3/delete_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/v3/delete_command_spec.rb
new file mode 100644
index 00000000000..63e7a8d2f25
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/helm/v3/delete_command_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kubernetes::Helm::V3::DeleteCommand do
+ subject(:delete_command) { described_class.new(name: app_name, rbac: rbac, files: files) }
+
+ let(:app_name) { 'app-name' }
+ let(:rbac) { true }
+ let(:files) { {} }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ helm uninstall app-name --namespace gitlab-managed-apps
+ EOS
+ end
+ end
+
+ describe '#pod_name' do
+ subject { delete_command.pod_name }
+
+ it { is_expected.to eq('uninstall-app-name') }
+ end
+
+ it_behaves_like 'helm command' do
+ let(:command) { delete_command }
+ end
+
+ describe '#delete_command' do
+ it 'deletes the release' do
+ expect(subject.delete_command).to eq('helm uninstall app-name --namespace gitlab-managed-apps')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/helm/v3/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/v3/install_command_spec.rb
new file mode 100644
index 00000000000..2bf1f713b3f
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/helm/v3/install_command_spec.rb
@@ -0,0 +1,168 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kubernetes::Helm::V3::InstallCommand do
+ subject(:install_command) do
+ described_class.new(
+ name: 'app-name',
+ chart: 'chart-name',
+ rbac: rbac,
+ files: files,
+ version: version,
+ repository: repository,
+ preinstall: preinstall,
+ postinstall: postinstall
+ )
+ end
+
+ let(:files) { { 'ca.pem': 'some file content' } }
+ let(:repository) { 'https://repository.example.com' }
+ let(:rbac) { false }
+ let(:version) { '1.2.3' }
+ let(:preinstall) { nil }
+ let(:postinstall) { nil }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_install_comand}
+ EOS
+ end
+
+ let(:helm_install_comand) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --install
+ --atomic
+ --cleanup-on-fail
+ --reset-values
+ --version 1.2.3
+ --set rbac.create\\=false,rbac.enabled\\=false
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+
+ context 'when rbac is true' do
+ let(:rbac) { true }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_install_command}
+ EOS
+ end
+
+ let(:helm_install_command) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --install
+ --atomic
+ --cleanup-on-fail
+ --reset-values
+ --version 1.2.3
+ --set rbac.create\\=true,rbac.enabled\\=true
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ context 'when there is a pre-install script' do
+ let(:preinstall) { ['/bin/date', '/bin/true'] }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ /bin/date
+ /bin/true
+ #{helm_install_command}
+ EOS
+ end
+
+ let(:helm_install_command) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --install
+ --atomic
+ --cleanup-on-fail
+ --reset-values
+ --version 1.2.3
+ --set rbac.create\\=false,rbac.enabled\\=false
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ context 'when there is a post-install script' do
+ let(:postinstall) { ['/bin/date', "/bin/false\n"] }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_install_command}
+ /bin/date
+ /bin/false
+ EOS
+ end
+
+ let(:helm_install_command) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --install
+ --atomic
+ --cleanup-on-fail
+ --reset-values
+ --version 1.2.3
+ --set rbac.create\\=false,rbac.enabled\\=false
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ context 'when there is no version' do
+ let(:version) { nil }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_install_command}
+ EOS
+ end
+
+ let(:helm_install_command) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --install
+ --atomic
+ --cleanup-on-fail
+ --reset-values
+ --set rbac.create\\=false,rbac.enabled\\=false
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ it_behaves_like 'helm command' do
+ let(:command) { install_command }
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/helm/v3/patch_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/v3/patch_command_spec.rb
new file mode 100644
index 00000000000..2f22e0f2e77
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/helm/v3/patch_command_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kubernetes::Helm::V3::PatchCommand do
+ let(:files) { { 'ca.pem': 'some file content' } }
+ let(:repository) { 'https://repository.example.com' }
+ let(:rbac) { false }
+ let(:version) { '1.2.3' }
+
+ subject(:patch_command) do
+ described_class.new(
+ name: 'app-name',
+ chart: 'chart-name',
+ rbac: rbac,
+ files: files,
+ version: version,
+ repository: repository
+ )
+ end
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_upgrade_comand}
+ EOS
+ end
+
+ let(:helm_upgrade_comand) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --reuse-values
+ --version 1.2.3
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+
+ context 'when rbac is true' do
+ let(:rbac) { true }
+
+ it_behaves_like 'helm command generator' do
+ let(:commands) do
+ <<~EOS
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_upgrade_command}
+ EOS
+ end
+
+ let(:helm_upgrade_command) do
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --reuse-values
+ --version 1.2.3
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ context 'when there is no version' do
+ let(:version) { nil }
+
+ it { expect { patch_command }.to raise_error(ArgumentError, 'version is required') }
+ end
+
+ describe '#pod_name' do
+ subject { patch_command.pod_name }
+
+ it { is_expected.to eq 'install-app-name' }
+ end
+
+ it_behaves_like 'helm command' do
+ let(:command) { patch_command }
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/kube_client_spec.rb b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
index 7b6d143dda9..521f13dc9cc 100644
--- a/spec/lib/gitlab/kubernetes/kube_client_spec.rb
+++ b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Gitlab::Kubernetes::KubeClient do
case method_name
when /\A(get_|delete_)/
client.public_send(method_name)
- when /\A(create_|update_)/
+ when /\A(create_|update_|patch_)/
client.public_send(method_name, {})
else
raise "Unknown method name #{method_name}"
@@ -302,6 +302,8 @@ RSpec.describe Gitlab::Kubernetes::KubeClient do
:create_role,
:get_role,
:update_role,
+ :delete_role_binding,
+ :update_role_binding,
:update_cluster_role_binding
].each do |method|
describe "##{method}" do
@@ -375,6 +377,34 @@ RSpec.describe Gitlab::Kubernetes::KubeClient do
end
end
+ describe '#patch_ingress' do
+ let(:extensions_client) { client.extensions_client }
+ let(:networking_client) { client.networking_client }
+
+ include_examples 'redirection not allowed', 'patch_ingress'
+ include_examples 'dns rebinding not allowed', 'patch_ingress'
+
+ it 'delegates to the extensions client' do
+ expect(extensions_client).to receive(:patch_ingress)
+
+ client.patch_ingress
+ end
+
+ context 'extensions does not have ingress for Kubernetes 1.22+ clusters' do
+ before do
+ WebMock
+ .stub_request(:get, api_url + '/apis/extensions/v1beta1')
+ .to_return(kube_response(kube_1_22_extensions_v1beta1_discovery_body))
+ end
+
+ it 'delegates to the apps client' do
+ expect(networking_client).to receive(:patch_ingress)
+
+ client.patch_ingress
+ end
+ end
+ end
+
describe 'istio API group' do
let(:istio_client) { client.istio_client }
diff --git a/spec/lib/gitlab/legacy_github_import/importer_spec.rb b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
index 56d708a1e11..56074147854 100644
--- a/spec/lib/gitlab/legacy_github_import/importer_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
allow_any_instance_of(Octokit::Client).to receive(:milestones).and_return([milestone, milestone])
allow_any_instance_of(Octokit::Client).to receive(:issues).and_return([issue1, issue2])
allow_any_instance_of(Octokit::Client).to receive(:pull_requests).and_return([pull_request, pull_request])
- allow_any_instance_of(Octokit::Client).to receive(:issues_comments).and_return([])
+ allow_any_instance_of(Octokit::Client).to receive(:issues_comments).and_raise(Octokit::NotFound)
allow_any_instance_of(Octokit::Client).to receive(:pull_requests_comments).and_return([])
allow_any_instance_of(Octokit::Client).to receive(:last_response).and_return(double(rels: { next: nil }))
allow_any_instance_of(Octokit::Client).to receive(:releases).and_return([release1, release2])
@@ -169,6 +169,7 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
errors: [
{ type: :label, url: "#{api_root}/repos/octocat/Hello-World/labels/bug", errors: "Validation failed: Title can't be blank, Title is invalid" },
{ type: :issue, url: "#{api_root}/repos/octocat/Hello-World/issues/1348", errors: "Validation failed: Title can't be blank" },
+ { type: :issues_comments, errors: 'Octokit::NotFound' },
{ type: :wiki, errors: "Gitlab::Git::CommandError" }
]
}
@@ -274,7 +275,7 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
allow(project).to receive(:import_data).and_return(double(credentials: credentials))
expect(Gitlab::LegacyGithubImport::Client).to receive(:new).with(
credentials[:user],
- {}
+ **{}
)
subject.client
diff --git a/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb b/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
index 631325402d9..1f7daaa308d 100644
--- a/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
+++ b/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::Metrics::RequestsRackMiddleware do
+RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
let(:app) { double('app') }
subject { described_class.new(app) }
@@ -21,20 +21,15 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware do
allow(app).to receive(:call).and_return([200, nil, nil])
end
- it 'increments requests count' do
- expect(described_class).to receive_message_chain(:http_request_total, :increment).with(method: 'get', status: 200, feature_category: 'unknown')
-
- subject.call(env)
- end
-
RSpec::Matchers.define :a_positive_execution_time do
match { |actual| actual > 0 }
end
- it 'measures execution time' do
+ it 'tracks request count and duration' do
+ expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '200', feature_category: 'unknown')
expect(described_class).to receive_message_chain(:http_request_duration_seconds, :observe).with({ method: 'get' }, a_positive_execution_time)
- Timecop.scale(3600) { subject.call(env) }
+ subject.call(env)
end
context 'request is a health check endpoint' do
@@ -44,15 +39,10 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware do
env['PATH_INFO'] = path
end
- it 'increments health endpoint counter rather than overall counter' do
- expect(described_class).to receive_message_chain(:http_health_requests_total, :increment).with(method: 'get', status: 200)
- expect(described_class).not_to receive(:http_request_total)
-
- subject.call(env)
- end
-
- it 'does not record the request duration' do
+ it 'increments health endpoint counter rather than overall counter and does not record duration' do
expect(described_class).not_to receive(:http_request_duration_seconds)
+ expect(described_class).not_to receive(:http_requests_total)
+ expect(described_class).to receive_message_chain(:http_health_requests_total, :increment).with(method: 'get', status: '200')
subject.call(env)
end
@@ -67,14 +57,9 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware do
env['PATH_INFO'] = path
end
- it 'increments overall counter rather than health endpoint counter' do
- expect(described_class).to receive_message_chain(:http_request_total, :increment).with(method: 'get', status: 200, feature_category: 'unknown')
+ it 'increments regular counters and tracks duration' do
+ expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '200', feature_category: 'unknown')
expect(described_class).not_to receive(:http_health_requests_total)
-
- subject.call(env)
- end
-
- it 'records the request duration' do
expect(described_class)
.to receive_message_chain(:http_request_duration_seconds, :observe)
.with({ method: 'get' }, a_positive_execution_time)
@@ -88,62 +73,91 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware do
context '@app.call throws exception' do
let(:http_request_duration_seconds) { double('http_request_duration_seconds') }
+ let(:http_requests_total) { double('http_requests_total') }
before do
allow(app).to receive(:call).and_raise(StandardError)
allow(described_class).to receive(:http_request_duration_seconds).and_return(http_request_duration_seconds)
+ allow(described_class).to receive(:http_requests_total).and_return(http_requests_total)
end
- it 'increments exceptions count' do
+ it 'tracks the correct metrics' do
expect(described_class).to receive_message_chain(:rack_uncaught_errors_count, :increment)
+ expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: 'undefined', feature_category: 'unknown')
+ expect(described_class.http_request_duration_seconds).not_to receive(:observe)
expect { subject.call(env) }.to raise_error(StandardError)
end
+ end
- it 'increments requests count' do
- expect(described_class).to receive_message_chain(:http_request_total, :increment).with(method: 'get', status: 'undefined', feature_category: 'unknown')
-
- expect { subject.call(env) }.to raise_error(StandardError)
- end
+ context 'feature category header' do
+ context 'when a feature category header is present' do
+ before do
+ allow(app).to receive(:call).and_return([200, { described_class::FEATURE_CATEGORY_HEADER => 'issue_tracking' }, nil])
+ end
- it "does't measure request execution time" do
- expect(described_class.http_request_duration_seconds).not_to receive(:increment)
+ it 'adds the feature category to the labels for http_requests_total' do
+ expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '200', feature_category: 'issue_tracking')
+ expect(described_class).not_to receive(:http_health_requests_total)
- expect { subject.call(env) }.to raise_error(StandardError)
- end
- end
+ subject.call(env)
+ end
- context 'when a feature category header is present' do
- before do
- allow(app).to receive(:call).and_return([200, { described_class::FEATURE_CATEGORY_HEADER => 'issue_tracking' }, nil])
- end
+ it 'does not record a feature category for health check endpoints' do
+ env['PATH_INFO'] = '/-/liveness'
- it 'adds the feature category to the labels for http_request_total' do
- expect(described_class).to receive_message_chain(:http_request_total, :increment).with(method: 'get', status: 200, feature_category: 'issue_tracking')
+ expect(described_class).to receive_message_chain(:http_health_requests_total, :increment).with(method: 'get', status: '200')
+ expect(described_class).not_to receive(:http_requests_total)
- subject.call(env)
+ subject.call(env)
+ end
end
- it 'does not record a feature category for health check endpoints' do
- env['PATH_INFO'] = '/-/liveness'
+ context 'when the feature category header is an empty string' do
+ before do
+ allow(app).to receive(:call).and_return([200, { described_class::FEATURE_CATEGORY_HEADER => '' }, nil])
+ end
- expect(described_class).to receive_message_chain(:http_health_requests_total, :increment).with(method: 'get', status: 200)
- expect(described_class).not_to receive(:http_request_total)
+ it 'sets the feature category to unknown' do
+ expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '200', feature_category: 'unknown')
+ expect(described_class).not_to receive(:http_health_requests_total)
- subject.call(env)
+ subject.call(env)
+ end
end
end
- describe '.initialize_http_request_duration_seconds' do
- it "sets labels" do
+ describe '.initialize_metrics', :prometheus do
+ it "sets labels for http_requests_total" do
expected_labels = []
- described_class::HTTP_METHODS.each do |method|
- expected_labels << { method: method }
+
+ described_class::HTTP_METHODS.each do |method, statuses|
+ statuses.each do |status|
+ described_class::FEATURE_CATEGORIES_TO_INITIALIZE.each do |feature_category|
+ expected_labels << { method: method.to_s, status: status.to_s, feature_category: feature_category.to_s }
+ end
+ end
end
- described_class.initialize_http_request_duration_seconds
+ described_class.initialize_metrics
+
+ expect(described_class.http_requests_total.values.keys).to contain_exactly(*expected_labels)
+ end
+
+ it 'sets labels for http_request_duration_seconds' do
+ expected_labels = described_class::HTTP_METHODS.keys.map { |method| { method: method } }
+
+ described_class.initialize_metrics
+
expect(described_class.http_request_duration_seconds.values.keys).to include(*expected_labels)
end
+
+ it 'has every label in config/feature_categories.yml' do
+ defaults = [described_class::FEATURE_CATEGORY_DEFAULT, 'not_owned']
+ feature_categories = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:strip) + defaults
+
+ expect(described_class::FEATURE_CATEGORIES_TO_INITIALIZE).to all(be_in(feature_categories))
+ end
end
end
end
diff --git a/spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb b/spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb
new file mode 100644
index 00000000000..e806f6478b7
--- /dev/null
+++ b/spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb
@@ -0,0 +1,182 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require "rack/test"
+
+RSpec.describe Gitlab::Middleware::HandleMalformedStrings do
+ include GitHttpHelpers
+
+ let(:null_byte) { "\u0000" }
+ let(:escaped_null_byte) { "%00" }
+ let(:invalid_string) { "mal\xC0formed" }
+ let(:escaped_invalid_string) { "mal%c0formed" }
+ let(:error_400) { [400, { 'Content-Type' => 'text/plain' }, ['Bad Request']] }
+ let(:app) { double(:app) }
+
+ subject { described_class.new(app) }
+
+ before do
+ allow(app).to receive(:call) do |args|
+ args
+ end
+ end
+
+ def env_for(params = {})
+ Rack::MockRequest.env_for('/', { params: params })
+ end
+
+ context 'in the URL' do
+ it 'rejects null bytes' do
+ # We have to create the env separately or Rack::MockRequest complains about invalid URI
+ env = env_for
+ env['PATH_INFO'] = "/someplace/witha#{null_byte}nullbyte"
+
+ expect(subject.call(env)).to eq error_400
+ end
+
+ it 'rejects escaped null bytes' do
+ # We have to create the env separately or Rack::MockRequest complains about invalid URI
+ env = env_for
+ env['PATH_INFO'] = "/someplace/withan#{escaped_null_byte}escaped nullbyte"
+
+ expect(subject.call(env)).to eq error_400
+ end
+
+ it 'rejects malformed strings' do
+ # We have to create the env separately or Rack::MockRequest complains about invalid URI
+ env = env_for
+ env['PATH_INFO'] = "/someplace/with_an/#{invalid_string}"
+
+ expect(subject.call(env)).to eq error_400
+ end
+
+ it 'rejects escaped malformed strings' do
+ # We have to create the env separately or Rack::MockRequest complains about invalid URI
+ env = env_for
+ env['PATH_INFO'] = "/someplace/with_an/#{escaped_invalid_string}"
+
+ expect(subject.call(env)).to eq error_400
+ end
+ end
+
+ context 'in authorization headers' do
+ let(:problematic_input) { null_byte }
+
+ shared_examples 'rejecting invalid input' do
+ it 'rejects problematic input in the password' do
+ env = env_for.merge(auth_env("username", "password#{problematic_input}encoded", nil))
+
+ expect(subject.call(env)).to eq error_400
+ end
+
+ it 'rejects problematic input in the username' do
+ env = env_for.merge(auth_env("username#{problematic_input}", "passwordencoded", nil))
+
+ expect(subject.call(env)).to eq error_400
+ end
+
+ it 'rejects problematic input in non-basic-auth tokens' do
+ env = env_for.merge('HTTP_AUTHORIZATION' => "GL-Geo hello#{problematic_input}world")
+
+ expect(subject.call(env)).to eq error_400
+ end
+ end
+
+ it_behaves_like 'rejecting invalid input' do
+ let(:problematic_input) { null_byte }
+ end
+
+ it_behaves_like 'rejecting invalid input' do
+ let(:problematic_input) { invalid_string }
+ end
+
+ it_behaves_like 'rejecting invalid input' do
+ let(:problematic_input) { "\xC3" }
+ end
+
+ it 'does not reject correct non-basic-auth tokens' do
+ # This token is known to include a null-byte when we were to try to decode it
+ # as Base64, while it wasn't encoded at such.
+ special_token = 'GL-Geo ta8KakZWpu0AcledQ6n0:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoie1wic2NvcGVcIjpcImdlb19hcGlcIn0iLCJqdGkiOiIwYWFmNzVlYi1lNWRkLTRkZjEtODQzYi1lM2E5ODhhNDMwMzIiLCJpYXQiOjE2MDQ3MDI4NzUsIm5iZiI6MTYwNDcwMjg3MCwiZXhwIjoxNjA0NzAyOTM1fQ.NcgDipDyxSP5uSzxc01ylzH4GkTxJRflNNjT7U6fpg4'
+ expect(Base64.decode64(special_token)).to include(null_byte)
+
+ env = env_for.merge('HTTP_AUTHORIZATION' => special_token)
+
+ expect(subject.call(env)).not_to eq error_400
+ end
+ end
+
+ context 'in params' do
+ shared_examples_for 'checks params' do
+ it 'rejects bad params in a top level param' do
+ env = env_for(name: "null#{problematic_input}byte")
+
+ expect(subject.call(env)).to eq error_400
+ end
+
+ it "rejects bad params for hashes with strings" do
+ env = env_for(name: { inner_key: "I am #{problematic_input} bad" })
+
+ expect(subject.call(env)).to eq error_400
+ end
+
+ it "rejects bad params for arrays with strings" do
+ env = env_for(name: ["I am #{problematic_input} bad"])
+
+ expect(subject.call(env)).to eq error_400
+ end
+
+ it "rejects bad params for arrays containing hashes with string values" do
+ env = env_for(name: [
+ {
+ inner_key: "I am #{problematic_input} bad"
+ }
+ ])
+
+ expect(subject.call(env)).to eq error_400
+ end
+ end
+
+ context 'with null byte' do
+ let(:problematic_input) { null_byte }
+
+ it_behaves_like 'checks params'
+
+ it "gives up and does not reject too deeply nested params" do
+ env = env_for(name: [
+ {
+ inner_key: { deeper_key: [{ hash_inside_array_key: "I am #{problematic_input} bad" }] }
+ }
+ ])
+
+ expect(subject.call(env)).not_to eq error_400
+ end
+ end
+
+ context 'with malformed strings' do
+ it_behaves_like 'checks params' do
+ let(:problematic_input) { invalid_string }
+ end
+ end
+ end
+
+ context 'without problematic input' do
+ it "does not error for strings" do
+ env = env_for(name: "safe name")
+
+ expect(subject.call(env)).not_to eq error_400
+ end
+
+ it "does not error with no params" do
+ env = env_for
+
+ expect(subject.call(env)).not_to eq error_400
+ end
+ end
+
+ it 'does not modify the env' do
+ env = env_for
+
+ expect { subject.call(env) }.not_to change { env }
+ end
+end
diff --git a/spec/lib/gitlab/middleware/handle_null_bytes_spec.rb b/spec/lib/gitlab/middleware/handle_null_bytes_spec.rb
deleted file mode 100644
index 76a5174817e..00000000000
--- a/spec/lib/gitlab/middleware/handle_null_bytes_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require "rack/test"
-
-RSpec.describe Gitlab::Middleware::HandleNullBytes do
- let(:null_byte) { "\u0000" }
- let(:error_400) { [400, {}, ["Bad Request"]] }
- let(:app) { double(:app) }
-
- subject { described_class.new(app) }
-
- before do
- allow(app).to receive(:call) do |args|
- args
- end
- end
-
- def env_for(params = {})
- Rack::MockRequest.env_for('/', { params: params })
- end
-
- context 'with null bytes in params' do
- it 'rejects null bytes in a top level param' do
- env = env_for(name: "null#{null_byte}byte")
-
- expect(subject.call(env)).to eq error_400
- end
-
- it "responds with 400 BadRequest for hashes with strings" do
- env = env_for(name: { inner_key: "I am #{null_byte} bad" })
-
- expect(subject.call(env)).to eq error_400
- end
-
- it "responds with 400 BadRequest for arrays with strings" do
- env = env_for(name: ["I am #{null_byte} bad"])
-
- expect(subject.call(env)).to eq error_400
- end
-
- it "responds with 400 BadRequest for arrays containing hashes with string values" do
- env = env_for(name: [
- {
- inner_key: "I am #{null_byte} bad"
- }
- ])
-
- expect(subject.call(env)).to eq error_400
- end
-
- it "gives up and does not 400 with too deeply nested params" do
- env = env_for(name: [
- {
- inner_key: { deeper_key: [{ hash_inside_array_key: "I am #{null_byte} bad" }] }
- }
- ])
-
- expect(subject.call(env)).not_to eq error_400
- end
- end
-
- context 'without null bytes in params' do
- it "does not respond with a 400 for strings" do
- env = env_for(name: "safe name")
-
- expect(subject.call(env)).not_to eq error_400
- end
-
- it "does not respond with a 400 with no params" do
- env = env_for
-
- expect(subject.call(env)).not_to eq error_400
- end
- end
-
- context 'when disabled via env flag' do
- before do
- stub_env('REJECT_NULL_BYTES', '1')
- end
-
- it 'does not respond with a 400 no matter what' do
- env = env_for(name: "null#{null_byte}byte")
-
- expect(subject.call(env)).not_to eq error_400
- end
- end
-end
diff --git a/spec/lib/gitlab/middleware/read_only_spec.rb b/spec/lib/gitlab/middleware/read_only_spec.rb
index 50dd38278b9..642b47fe087 100644
--- a/spec/lib/gitlab/middleware/read_only_spec.rb
+++ b/spec/lib/gitlab/middleware/read_only_spec.rb
@@ -3,209 +3,11 @@
require 'spec_helper'
RSpec.describe Gitlab::Middleware::ReadOnly do
- include Rack::Test::Methods
- using RSpec::Parameterized::TableSyntax
-
- let(:rack_stack) do
- rack = Rack::Builder.new do
- use ActionDispatch::Session::CacheStore
- use ActionDispatch::Flash
- end
-
- rack.run(subject)
- rack.to_app
- end
-
- let(:observe_env) do
- Module.new do
- attr_reader :env
-
- def call(env)
- @env = env
- super
- end
- end
- end
-
- let(:request) { Rack::MockRequest.new(rack_stack) }
-
- subject do
- described_class.new(fake_app).tap do |app|
- app.extend(observe_env)
- end
- end
-
- context 'normal requests to a read-only GitLab instance' do
- let(:fake_app) { lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ['OK']] } }
-
+ context 'when database is read-only' do
before do
allow(Gitlab::Database).to receive(:read_only?) { true }
end
- it 'expects PATCH requests to be disallowed' do
- response = request.patch('/test_request')
-
- expect(response).to be_redirect
- expect(subject).to disallow_request
- end
-
- it 'expects PUT requests to be disallowed' do
- response = request.put('/test_request')
-
- expect(response).to be_redirect
- expect(subject).to disallow_request
- end
-
- it 'expects POST requests to be disallowed' do
- response = request.post('/test_request')
-
- expect(response).to be_redirect
- expect(subject).to disallow_request
- end
-
- it 'expects a internal POST request to be allowed after a disallowed request' do
- response = request.post('/test_request')
-
- expect(response).to be_redirect
-
- response = request.post("/api/#{API::API.version}/internal")
-
- expect(response).not_to be_redirect
- end
-
- it 'expects DELETE requests to be disallowed' do
- response = request.delete('/test_request')
-
- expect(response).to be_redirect
- expect(subject).to disallow_request
- end
-
- it 'expects POST of new file that looks like an LFS batch url to be disallowed' do
- expect(Rails.application.routes).to receive(:recognize_path).and_call_original
- response = request.post('/root/gitlab-ce/new/master/app/info/lfs/objects/batch')
-
- expect(response).to be_redirect
- expect(subject).to disallow_request
- end
-
- it 'returns last_vistited_url for disallowed request' do
- response = request.post('/test_request')
-
- expect(response.location).to eq 'http://localhost/'
- end
-
- context 'whitelisted requests' do
- it 'expects a POST internal request to be allowed' do
- expect(Rails.application.routes).not_to receive(:recognize_path)
- response = request.post("/api/#{API::API.version}/internal")
-
- expect(response).not_to be_redirect
- expect(subject).not_to disallow_request
- end
-
- it 'expects a graphql request to be allowed' do
- response = request.post("/api/graphql")
-
- expect(response).not_to be_redirect
- expect(subject).not_to disallow_request
- end
-
- context 'relative URL is configured' do
- before do
- stub_config_setting(relative_url_root: '/gitlab')
- end
-
- it 'expects a graphql request to be allowed' do
- response = request.post("/gitlab/api/graphql")
-
- expect(response).not_to be_redirect
- expect(subject).not_to disallow_request
- end
- end
-
- context 'sidekiq admin requests' do
- where(:mounted_at) do
- [
- '',
- '/',
- '/gitlab',
- '/gitlab/',
- '/gitlab/gitlab',
- '/gitlab/gitlab/'
- ]
- end
-
- with_them do
- before do
- stub_config_setting(relative_url_root: mounted_at)
- end
-
- it 'allows requests' do
- path = File.join(mounted_at, 'admin/sidekiq')
- response = request.post(path)
-
- expect(response).not_to be_redirect
- expect(subject).not_to disallow_request
-
- response = request.get(path)
-
- expect(response).not_to be_redirect
- expect(subject).not_to disallow_request
- end
- end
- end
-
- where(:description, :path) do
- 'LFS request to batch' | '/root/rouge.git/info/lfs/objects/batch'
- 'LFS request to locks verify' | '/root/rouge.git/info/lfs/locks/verify'
- 'LFS request to locks create' | '/root/rouge.git/info/lfs/locks'
- 'LFS request to locks unlock' | '/root/rouge.git/info/lfs/locks/1/unlock'
- 'request to git-upload-pack' | '/root/rouge.git/git-upload-pack'
- 'request to git-receive-pack' | '/root/rouge.git/git-receive-pack'
- end
-
- with_them do
- it "expects a POST #{description} URL to be allowed" do
- expect(Rails.application.routes).to receive(:recognize_path).and_call_original
- response = request.post(path)
-
- expect(response).not_to be_redirect
- expect(subject).not_to disallow_request
- end
- end
- end
- end
-
- context 'json requests to a read-only GitLab instance' do
- let(:fake_app) { lambda { |env| [200, { 'Content-Type' => 'application/json' }, ['OK']] } }
- let(:content_json) { { 'CONTENT_TYPE' => 'application/json' } }
-
- before do
- allow(Gitlab::Database).to receive(:read_only?) { true }
- end
-
- it 'expects PATCH requests to be disallowed' do
- response = request.patch('/test_request', content_json)
-
- expect(response).to disallow_request_in_json
- end
-
- it 'expects PUT requests to be disallowed' do
- response = request.put('/test_request', content_json)
-
- expect(response).to disallow_request_in_json
- end
-
- it 'expects POST requests to be disallowed' do
- response = request.post('/test_request', content_json)
-
- expect(response).to disallow_request_in_json
- end
-
- it 'expects DELETE requests to be disallowed' do
- response = request.delete('/test_request', content_json)
-
- expect(response).to disallow_request_in_json
- end
+ it_behaves_like 'write access for a read-only GitLab instance'
end
end
diff --git a/spec/lib/gitlab/omniauth_initializer_spec.rb b/spec/lib/gitlab/omniauth_initializer_spec.rb
index a38dffcfce0..577d15b8495 100644
--- a/spec/lib/gitlab/omniauth_initializer_spec.rb
+++ b/spec/lib/gitlab/omniauth_initializer_spec.rb
@@ -101,33 +101,5 @@ RSpec.describe Gitlab::OmniauthInitializer do
subject.execute([google_config])
end
-
- it 'converts client_auth_method to a Symbol for openid_connect' do
- openid_connect_config = {
- 'name' => 'openid_connect',
- 'args' => { name: 'openid_connect', client_auth_method: 'basic' }
- }
-
- expect(devise_config).to receive(:omniauth).with(
- :openid_connect,
- { name: 'openid_connect', client_auth_method: :basic }
- )
-
- subject.execute([openid_connect_config])
- end
-
- it 'converts client_auth_method to a Symbol for strategy_class OpenIDConnect' do
- openid_connect_config = {
- 'name' => 'openid_connect',
- 'args' => { strategy_class: OmniAuth::Strategies::OpenIDConnect, client_auth_method: 'jwt_bearer' }
- }
-
- expect(devise_config).to receive(:omniauth).with(
- :openid_connect,
- { strategy_class: OmniAuth::Strategies::OpenIDConnect, client_auth_method: :jwt_bearer }
- )
-
- subject.execute([openid_connect_config])
- end
end
end
diff --git a/spec/lib/gitlab/path_regex_spec.rb b/spec/lib/gitlab/path_regex_spec.rb
index 7cecc29afa4..f320b8a66e8 100644
--- a/spec/lib/gitlab/path_regex_spec.rb
+++ b/spec/lib/gitlab/path_regex_spec.rb
@@ -101,10 +101,15 @@ RSpec.describe Gitlab::PathRegex do
.concat(ee_top_level_words)
.concat(files_in_public)
.concat(Array(API::API.prefix.to_s))
+ .concat(sitemap_words)
.compact
.uniq
end
+ let(:sitemap_words) do
+ %w(sitemap sitemap.xml sitemap.xml.gz)
+ end
+
let(:ee_top_level_words) do
%w(unsubscribes v2)
end
@@ -172,7 +177,7 @@ RSpec.describe Gitlab::PathRegex do
# We ban new items in this list, see https://gitlab.com/gitlab-org/gitlab/-/issues/215362
it 'does not allow expansion' do
- expect(described_class::TOP_LEVEL_ROUTES.size).to eq(41)
+ expect(described_class::TOP_LEVEL_ROUTES.size).to eq(44)
end
end
@@ -218,6 +223,8 @@ RSpec.describe Gitlab::PathRegex do
expect(subject).not_to match('admin/')
expect(subject).not_to match('api/')
expect(subject).not_to match('.well-known/')
+ expect(subject).not_to match('sitemap.xml/')
+ expect(subject).not_to match('sitemap.xml.gz/')
end
it 'accepts project wildcard routes' do
@@ -458,4 +465,34 @@ RSpec.describe Gitlab::PathRegex do
it_behaves_like 'invalid snippet routes'
end
+
+ describe '.container_image_regex' do
+ subject { described_class.container_image_regex }
+
+ it { is_expected.to match('gitlab-foss') }
+ it { is_expected.to match('gitlab_foss') }
+ it { is_expected.to match('gitlab-org/gitlab-foss') }
+ it { is_expected.to match('100px.com/100px.ruby') }
+
+ it 'only matches at most one slash' do
+ expect(subject.match('foo/bar/baz')[0]).to eq('foo/bar')
+ end
+
+ it 'does not match other non-word characters' do
+ expect(subject.match('ruby:2.7.0')[0]).to eq('ruby')
+ end
+ end
+
+ describe '.container_image_blob_sha_regex' do
+ subject { described_class.container_image_blob_sha_regex }
+
+ it { is_expected.to match('sha256:asdf1234567890ASDF') }
+ it { is_expected.to match('foo:123') }
+ it { is_expected.to match('a12bc3f590szp') }
+ it { is_expected.not_to match('') }
+
+ it 'does not match malicious characters' do
+ expect(subject.match('sha256:asdf1234%2f')[0]).to eq('sha256:asdf1234')
+ end
+ end
end
diff --git a/spec/lib/gitlab/quick_actions/extractor_spec.rb b/spec/lib/gitlab/quick_actions/extractor_spec.rb
index f4104b78d5c..61fffe3fb6b 100644
--- a/spec/lib/gitlab/quick_actions/extractor_spec.rb
+++ b/spec/lib/gitlab/quick_actions/extractor_spec.rb
@@ -264,6 +264,22 @@ RSpec.describe Gitlab::QuickActions::Extractor do
expect(msg).to eq 'Fixes #123'
end
+ it 'does not get confused if command comes before an inline code' do
+ msg = "/reopen\n`some inline code`\n/labels ~a\n`more inline code`"
+ msg, commands = extractor.extract_commands(msg)
+
+ expect(commands).to eq([['reopen'], ['labels', '~a']])
+ expect(msg).to eq "`some inline code`\n`more inline code`"
+ end
+
+ it 'does not get confused if command comes before a blockcode' do
+ msg = "/reopen\n```\nsome blockcode\n```\n/labels ~a\n```\nmore blockcode\n```"
+ msg, commands = extractor.extract_commands(msg)
+
+ expect(commands).to eq([['reopen'], ['labels', '~a']])
+ expect(msg).to eq "```\nsome blockcode\n```\n```\nmore blockcode\n```"
+ end
+
it 'does not extract commands inside a blockcode' do
msg = "Hello\r\n```\r\nThis is some text\r\n/close\r\n/assign @user\r\n```\r\n\r\nWorld"
expected = msg.delete("\r")
diff --git a/spec/lib/gitlab/redis/wrapper_spec.rb b/spec/lib/gitlab/redis/wrapper_spec.rb
index 283853ee863..ec233c022ee 100644
--- a/spec/lib/gitlab/redis/wrapper_spec.rb
+++ b/spec/lib/gitlab/redis/wrapper_spec.rb
@@ -26,6 +26,12 @@ RSpec.describe Gitlab::Redis::Wrapper do
end
end
+ describe '.version' do
+ it 'returns a version' do
+ expect(described_class.version).to be_present
+ end
+ end
+
describe '.instrumentation_class' do
it 'raises a NotImplementedError' do
expect(described_class).to receive(:instrumentation_class).and_call_original
diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb
index 0172defc75d..229d49868d4 100644
--- a/spec/lib/gitlab/reference_extractor_spec.rb
+++ b/spec/lib/gitlab/reference_extractor_spec.rb
@@ -296,7 +296,7 @@ RSpec.describe Gitlab::ReferenceExtractor do
end
it 'returns all supported prefixes' do
- expect(prefixes.keys.uniq).to match_array(%w(@ # ~ % ! $ & *iteration:))
+ expect(prefixes.keys.uniq).to match_array(%w(@ # ~ % ! $ & [vulnerability: *iteration:))
end
it 'does not allow one prefix for multiple referables if not allowed specificly' do
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index 451526021c1..ebb37f45b95 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -248,6 +248,15 @@ RSpec.describe Gitlab::Regex do
it { is_expected.not_to match('!!()()') }
end
+ describe '.composer_dev_version_regex' do
+ subject { described_class.composer_dev_version_regex }
+
+ it { is_expected.to match('dev-master') }
+ it { is_expected.to match('1.x-dev') }
+ it { is_expected.not_to match('foobar') }
+ it { is_expected.not_to match('1.2.3') }
+ end
+
describe '.conan_recipe_component_regex' do
subject { described_class.conan_recipe_component_regex }
diff --git a/spec/lib/gitlab/relative_positioning/mover_spec.rb b/spec/lib/gitlab/relative_positioning/mover_spec.rb
index dafd34585a8..cbb15ae876d 100644
--- a/spec/lib/gitlab/relative_positioning/mover_spec.rb
+++ b/spec/lib/gitlab/relative_positioning/mover_spec.rb
@@ -32,6 +32,7 @@ RSpec.describe RelativePositioning::Mover do
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
diff --git a/spec/lib/gitlab/repository_size_checker_spec.rb b/spec/lib/gitlab/repository_size_checker_spec.rb
index bd030d81d97..20c08da6c54 100644
--- a/spec/lib/gitlab/repository_size_checker_spec.rb
+++ b/spec/lib/gitlab/repository_size_checker_spec.rb
@@ -53,4 +53,10 @@ RSpec.describe Gitlab::RepositorySizeChecker do
describe '#exceeded_size' do
include_examples 'checker size exceeded'
end
+
+ describe '#additional_repo_storage_available?' do
+ it 'returns false' do
+ expect(subject.additional_repo_storage_available?).to eq(false)
+ end
+ end
end
diff --git a/spec/lib/gitlab/repository_size_error_message_spec.rb b/spec/lib/gitlab/repository_size_error_message_spec.rb
index 53b5ed5518f..78504d201d4 100644
--- a/spec/lib/gitlab/repository_size_error_message_spec.rb
+++ b/spec/lib/gitlab/repository_size_error_message_spec.rb
@@ -53,8 +53,18 @@ RSpec.describe Gitlab::RepositorySizeErrorMessage do
end
describe '#new_changes_error' do
- it 'returns the correct message' do
- expect(message.new_changes_error).to eq("Your push to this repository would cause it to exceed the size limit of 10 MB so it has been rejected. #{message.more_info_message}")
+ context 'when additional repo storage is available' do
+ it 'returns the correct message' do
+ allow(checker).to receive(:additional_repo_storage_available?).and_return(true)
+
+ expect(message.new_changes_error).to eq('Your push to this repository has been rejected because it would exceed storage limits. Please contact your GitLab administrator for more information.')
+ end
+ end
+
+ context 'when no additional repo storage is available' do
+ it 'returns the correct message' do
+ expect(message.new_changes_error).to eq("Your push to this repository would cause it to exceed the size limit of 10 MB so it has been rejected. #{message.more_info_message}")
+ end
end
end
end
diff --git a/spec/lib/gitlab/robots_txt/parser_spec.rb b/spec/lib/gitlab/robots_txt/parser_spec.rb
index bb88003ce20..f4e97e5e897 100644
--- a/spec/lib/gitlab/robots_txt/parser_spec.rb
+++ b/spec/lib/gitlab/robots_txt/parser_spec.rb
@@ -14,8 +14,13 @@ RSpec.describe Gitlab::RobotsTxt::Parser do
<<~TXT
User-Agent: *
Disallow: /autocomplete/users
- Disallow: /search
+ disallow: /search
Disallow: /api
+ Allow: /users
+ Disallow: /help
+ allow: /help
+ Disallow: /test$
+ Disallow: /ex$mple$
TXT
end
@@ -28,6 +33,12 @@ RSpec.describe Gitlab::RobotsTxt::Parser do
'/api/grapql' | true
'/api/index.html' | true
'/projects' | false
+ '/users' | false
+ '/help' | false
+ '/test' | true
+ '/testfoo' | false
+ '/ex$mple' | true
+ '/ex$mplefoo' | false
end
with_them do
@@ -47,6 +58,7 @@ RSpec.describe Gitlab::RobotsTxt::Parser do
Disallow: /*/*.git
Disallow: /*/archive/
Disallow: /*/repository/archive*
+ Allow: /*/repository/archive/foo
TXT
end
@@ -61,6 +73,7 @@ RSpec.describe Gitlab::RobotsTxt::Parser do
'/projects' | false
'/git' | false
'/projects/git' | false
+ '/project/repository/archive/foo' | false
end
with_them do
diff --git a/spec/lib/gitlab/search/sort_options_spec.rb b/spec/lib/gitlab/search/sort_options_spec.rb
new file mode 100644
index 00000000000..2044fdfc894
--- /dev/null
+++ b/spec/lib/gitlab/search/sort_options_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'gitlab/search/sort_options'
+
+RSpec.describe ::Gitlab::Search::SortOptions do
+ describe '.sort_and_direction' do
+ context 'using order_by and sort' do
+ it 'returns matched options' do
+ expect(described_class.sort_and_direction('created_at', 'asc')).to eq(:created_at_asc)
+ expect(described_class.sort_and_direction('created_at', 'desc')).to eq(:created_at_desc)
+ end
+ end
+
+ context 'using just sort' do
+ it 'returns matched options' do
+ expect(described_class.sort_and_direction(nil, 'created_asc')).to eq(:created_at_asc)
+ expect(described_class.sort_and_direction(nil, 'created_desc')).to eq(:created_at_desc)
+ end
+ end
+
+ context 'when unknown option' do
+ it 'returns unknown' do
+ expect(described_class.sort_and_direction(nil, 'foo_asc')).to eq(:unknown)
+ expect(described_class.sort_and_direction(nil, 'bar_desc')).to eq(:unknown)
+ expect(described_class.sort_and_direction(nil, 'created_bar')).to eq(:unknown)
+
+ expect(described_class.sort_and_direction('created_at', 'foo')).to eq(:unknown)
+ expect(described_class.sort_and_direction('foo', 'desc')).to eq(:unknown)
+ expect(described_class.sort_and_direction('created_at', nil)).to eq(:unknown)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb b/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb
index cf165d1770b..74834fb9014 100644
--- a/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb
+++ b/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb
@@ -108,101 +108,114 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do
end
end
- context 'with --experimental-queue-selector' do
- where do
- {
- 'memory-bound queues' => {
- query: 'resource_boundary=memory',
- included_queues: %w(project_export),
- excluded_queues: %w(merge)
- },
- 'memory- or CPU-bound queues' => {
- query: 'resource_boundary=memory,cpu',
- included_queues: %w(auto_merge:auto_merge_process project_export),
- excluded_queues: %w(merge)
- },
- 'high urgency CI queues' => {
- query: 'feature_category=continuous_integration&urgency=high',
- included_queues: %w(pipeline_cache:expire_job_cache pipeline_cache:expire_pipeline_cache),
- excluded_queues: %w(merge)
- },
- 'CPU-bound high urgency CI queues' => {
- query: 'feature_category=continuous_integration&urgency=high&resource_boundary=cpu',
- included_queues: %w(pipeline_cache:expire_pipeline_cache),
- excluded_queues: %w(pipeline_cache:expire_job_cache merge)
- },
- 'CPU-bound high urgency non-CI queues' => {
- query: 'feature_category!=continuous_integration&urgency=high&resource_boundary=cpu',
- included_queues: %w(new_issue),
- excluded_queues: %w(pipeline_cache:expire_pipeline_cache)
- },
- 'CI and SCM queues' => {
- query: 'feature_category=continuous_integration|feature_category=source_code_management',
- included_queues: %w(pipeline_cache:expire_job_cache merge),
- excluded_queues: %w(mailers)
- }
- }
+ # Remove with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
+ context 'with --queue-selector and --experimental-queue-selector' do
+ it 'errors' do
+ expect(Gitlab::SidekiqCluster).not_to receive(:start)
+
+ expect { cli.run(%w(--queue-selector name=foo --experimental-queue-selector name=bar)) }
+ .to raise_error(described_class::CommandError)
end
+ end
- with_them do
- it 'expands queues by attributes' do
- expect(Gitlab::SidekiqCluster).to receive(:start) do |queues, opts|
- expect(opts).to eq(default_options)
- expect(queues.first).to include(*included_queues)
- expect(queues.first).not_to include(*excluded_queues)
+ # Simplify with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
+ ['--queue-selector', '--experimental-queue-selector'].each do |flag|
+ context "with #{flag}" do
+ where do
+ {
+ 'memory-bound queues' => {
+ query: 'resource_boundary=memory',
+ included_queues: %w(project_export),
+ excluded_queues: %w(merge)
+ },
+ 'memory- or CPU-bound queues' => {
+ query: 'resource_boundary=memory,cpu',
+ included_queues: %w(auto_merge:auto_merge_process project_export),
+ excluded_queues: %w(merge)
+ },
+ 'high urgency CI queues' => {
+ query: 'feature_category=continuous_integration&urgency=high',
+ included_queues: %w(pipeline_cache:expire_job_cache pipeline_cache:expire_pipeline_cache),
+ excluded_queues: %w(merge)
+ },
+ 'CPU-bound high urgency CI queues' => {
+ query: 'feature_category=continuous_integration&urgency=high&resource_boundary=cpu',
+ included_queues: %w(pipeline_cache:expire_pipeline_cache),
+ excluded_queues: %w(pipeline_cache:expire_job_cache merge)
+ },
+ 'CPU-bound high urgency non-CI queues' => {
+ query: 'feature_category!=continuous_integration&urgency=high&resource_boundary=cpu',
+ included_queues: %w(new_issue),
+ excluded_queues: %w(pipeline_cache:expire_pipeline_cache)
+ },
+ 'CI and SCM queues' => {
+ query: 'feature_category=continuous_integration|feature_category=source_code_management',
+ included_queues: %w(pipeline_cache:expire_job_cache merge),
+ excluded_queues: %w(mailers)
+ }
+ }
+ end
+
+ with_them do
+ it 'expands queues by attributes' do
+ expect(Gitlab::SidekiqCluster).to receive(:start) do |queues, opts|
+ expect(opts).to eq(default_options)
+ expect(queues.first).to include(*included_queues)
+ expect(queues.first).not_to include(*excluded_queues)
+
+ []
+ end
- []
+ cli.run(%W(#{flag} #{query}))
end
- cli.run(%W(--experimental-queue-selector #{query}))
- end
+ it 'works when negated' do
+ expect(Gitlab::SidekiqCluster).to receive(:start) do |queues, opts|
+ expect(opts).to eq(default_options)
+ expect(queues.first).not_to include(*included_queues)
+ expect(queues.first).to include(*excluded_queues)
- it 'works when negated' do
- expect(Gitlab::SidekiqCluster).to receive(:start) do |queues, opts|
- expect(opts).to eq(default_options)
- expect(queues.first).not_to include(*included_queues)
- expect(queues.first).to include(*excluded_queues)
+ []
+ end
- []
+ cli.run(%W(--negate #{flag} #{query}))
end
-
- cli.run(%W(--negate --experimental-queue-selector #{query}))
end
- end
- it 'expands multiple queue groups correctly' do
- expect(Gitlab::SidekiqCluster)
- .to receive(:start)
- .with([['chat_notification'], ['project_export']], default_options)
- .and_return([])
+ it 'expands multiple queue groups correctly' do
+ expect(Gitlab::SidekiqCluster)
+ .to receive(:start)
+ .with([['chat_notification'], ['project_export']], default_options)
+ .and_return([])
- cli.run(%w(--experimental-queue-selector feature_category=chatops&has_external_dependencies=true resource_boundary=memory&feature_category=importers))
- end
+ cli.run(%W(#{flag} feature_category=chatops&has_external_dependencies=true resource_boundary=memory&feature_category=importers))
+ end
- it 'allows the special * selector' do
- worker_queues = %w(foo bar baz)
+ it 'allows the special * selector' do
+ worker_queues = %w(foo bar baz)
- expect(Gitlab::SidekiqConfig::CliMethods)
- .to receive(:worker_queues).and_return(worker_queues)
+ expect(Gitlab::SidekiqConfig::CliMethods)
+ .to receive(:worker_queues).and_return(worker_queues)
- expect(Gitlab::SidekiqCluster)
- .to receive(:start).with([worker_queues], default_options)
+ expect(Gitlab::SidekiqCluster)
+ .to receive(:start).with([worker_queues], default_options)
- cli.run(%w(--experimental-queue-selector *))
- end
+ cli.run(%W(#{flag} *))
+ end
- it 'errors when the selector matches no queues' do
- expect(Gitlab::SidekiqCluster).not_to receive(:start)
+ it 'errors when the selector matches no queues' do
+ expect(Gitlab::SidekiqCluster).not_to receive(:start)
- expect { cli.run(%w(--experimental-queue-selector has_external_dependencies=true&has_external_dependencies=false)) }
- .to raise_error(described_class::CommandError)
- end
+ expect { cli.run(%W(#{flag} has_external_dependencies=true&has_external_dependencies=false)) }
+ .to raise_error(described_class::CommandError)
+ end
- it 'errors on an invalid query multiple queue groups correctly' do
- expect(Gitlab::SidekiqCluster).not_to receive(:start)
+ it 'errors on an invalid query multiple queue groups correctly' do
+ expect(Gitlab::SidekiqCluster).not_to receive(:start)
- expect { cli.run(%w(--experimental-queue-selector unknown_field=chatops)) }
- .to raise_error(Gitlab::SidekiqConfig::CliMethods::QueryError)
+ expect { cli.run(%W(#{flag} unknown_field=chatops)) }
+ .to raise_error(Gitlab::SidekiqConfig::CliMethods::QueryError)
+ end
end
end
end
diff --git a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
index ad106837c47..b99a5352717 100644
--- a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
+++ b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
@@ -119,6 +119,10 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
end
context 'with SIDEKIQ_LOG_ARGUMENTS disabled' do
+ before do
+ stub_env('SIDEKIQ_LOG_ARGUMENTS', '0')
+ end
+
it 'logs start and end of job without args' do
Timecop.freeze(timestamp) do
expect(logger).to receive(:info).with(start_payload.except('args')).ordered
@@ -150,8 +154,8 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
it 'logs with scheduling latency' do
Timecop.freeze(timestamp) do
- expect(logger).to receive(:info).with(start_payload.except('args')).ordered
- expect(logger).to receive(:info).with(end_payload.except('args')).ordered
+ expect(logger).to receive(:info).with(start_payload).ordered
+ expect(logger).to receive(:info).with(end_payload).ordered
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
@@ -173,12 +177,12 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
end
let(:expected_end_payload) do
- end_payload.except('args').merge(timing_data)
+ end_payload.merge(timing_data)
end
it 'logs with Gitaly and Rugged timing data' do
Timecop.freeze(timestamp) do
- expect(logger).to receive(:info).with(start_payload.except('args')).ordered
+ expect(logger).to receive(:info).with(start_payload).ordered
expect(logger).to receive(:info).with(expected_end_payload).ordered
subject.call(job, 'test_queue') do
@@ -194,10 +198,10 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
allow(Process).to receive(:clock_gettime).and_call_original
end
- let(:expected_start_payload) { start_payload.except('args') }
+ let(:expected_start_payload) { start_payload }
let(:expected_end_payload) do
- end_payload.except('args').merge('cpu_s' => a_value >= 0)
+ end_payload.merge('cpu_s' => a_value >= 0)
end
let(:expected_end_payload_with_db) do
@@ -228,10 +232,10 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
end
context 'when there is extra metadata set for the done log' do
- let(:expected_start_payload) { start_payload.except('args') }
+ let(:expected_start_payload) { start_payload }
let(:expected_end_payload) do
- end_payload.except('args').merge("#{ApplicationWorker::LOGGING_EXTRA_KEY}.key1" => 15, "#{ApplicationWorker::LOGGING_EXTRA_KEY}.key2" => 16)
+ end_payload.merge("#{ApplicationWorker::LOGGING_EXTRA_KEY}.key1" => 15, "#{ApplicationWorker::LOGGING_EXTRA_KEY}.key2" => 16)
end
it 'logs it in the done log' do
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/client_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/client_spec.rb
index 98350fb9b8e..4d12e4b3f6f 100644
--- a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/client_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/client_spec.rb
@@ -3,79 +3,84 @@
require 'spec_helper'
RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::Client, :clean_gitlab_redis_queues do
- let(:worker_class) do
- Class.new do
- def self.name
- 'TestDeduplicationWorker'
- end
+ shared_context 'deduplication worker class' do |strategy, including_scheduled|
+ let(:worker_class) do
+ Class.new do
+ def self.name
+ 'TestDeduplicationWorker'
+ end
+
+ include ApplicationWorker
+
+ deduplicate strategy, including_scheduled: including_scheduled
- include ApplicationWorker
+ include ApplicationWorker
- def perform(*args)
+ def perform(*args)
+ end
end
end
- end
- before do
- stub_const('TestDeduplicationWorker', worker_class)
+ before do
+ stub_const('TestDeduplicationWorker', worker_class)
+ end
end
- describe '#call' do
- it 'adds a correct duplicate tag to the jobs', :aggregate_failures do
- TestDeduplicationWorker.bulk_perform_async([['args1'], ['args2'], ['args1']])
+ shared_examples 'client duplicate job' do |strategy|
+ describe '#call' do
+ include_context 'deduplication worker class', strategy, false
- job1, job2, job3 = TestDeduplicationWorker.jobs
-
- expect(job1['duplicate-of']).to be_nil
- expect(job2['duplicate-of']).to be_nil
- expect(job3['duplicate-of']).to eq(job1['jid'])
- end
-
- context 'without scheduled deduplication' do
- it "does not mark a job that's scheduled in the future as a duplicate" do
- TestDeduplicationWorker.perform_async('args1')
- TestDeduplicationWorker.perform_at(1.day.from_now, 'args1')
- TestDeduplicationWorker.perform_in(3.hours, 'args1')
+ it 'adds a correct duplicate tag to the jobs', :aggregate_failures do
+ TestDeduplicationWorker.bulk_perform_async([['args1'], ['args2'], ['args1']])
- duplicates = TestDeduplicationWorker.jobs.map { |job| job['duplicate-of'] }
+ job1, job2, job3 = TestDeduplicationWorker.jobs
- expect(duplicates).to all(be_nil)
+ expect(job1['duplicate-of']).to be_nil
+ expect(job2['duplicate-of']).to be_nil
+ expect(job3['duplicate-of']).to eq(job1['jid'])
end
- end
-
- context 'with scheduled deduplication' do
- let(:scheduled_worker_class) do
- Class.new do
- def self.name
- 'TestDeduplicationWorker'
- end
- include ApplicationWorker
+ context 'without scheduled deduplication' do
+ it "does not mark a job that's scheduled in the future as a duplicate" do
+ TestDeduplicationWorker.perform_async('args1')
+ TestDeduplicationWorker.perform_at(1.day.from_now, 'args1')
+ TestDeduplicationWorker.perform_in(3.hours, 'args1')
- deduplicate :until_executing, including_scheduled: true
+ duplicates = TestDeduplicationWorker.jobs.map { |job| job['duplicate-of'] }
- def perform(*args)
- end
+ expect(duplicates).to all(be_nil)
end
end
- before do
- stub_const('TestDeduplicationWorker', scheduled_worker_class)
- end
+ context 'with scheduled deduplication' do
+ include_context 'deduplication worker class', strategy, true
- it 'adds a correct duplicate tag to the jobs', :aggregate_failures do
- TestDeduplicationWorker.perform_async('args1')
- TestDeduplicationWorker.perform_at(1.day.from_now, 'args1')
- TestDeduplicationWorker.perform_in(3.hours, 'args1')
- TestDeduplicationWorker.perform_in(3.hours, 'args2')
+ before do
+ stub_const('TestDeduplicationWorker', worker_class)
+ end
- job1, job2, job3, job4 = TestDeduplicationWorker.jobs
+ it 'adds a correct duplicate tag to the jobs', :aggregate_failures do
+ TestDeduplicationWorker.perform_async('args1')
+ TestDeduplicationWorker.perform_at(1.day.from_now, 'args1')
+ TestDeduplicationWorker.perform_in(3.hours, 'args1')
+ TestDeduplicationWorker.perform_in(3.hours, 'args2')
- expect(job1['duplicate-of']).to be_nil
- expect(job2['duplicate-of']).to eq(job1['jid'])
- expect(job3['duplicate-of']).to eq(job1['jid'])
- expect(job4['duplicate-of']).to be_nil
+ job1, job2, job3, job4 = TestDeduplicationWorker.jobs
+
+ expect(job1['duplicate-of']).to be_nil
+ expect(job2['duplicate-of']).to eq(job1['jid'])
+ expect(job3['duplicate-of']).to eq(job1['jid'])
+ expect(job4['duplicate-of']).to be_nil
+ end
end
end
end
+
+ context 'with until_executing strategy' do
+ it_behaves_like 'client duplicate job', :until_executing
+ end
+
+ context 'with until_executed strategy' do
+ it_behaves_like 'client duplicate job', :until_executed
+ end
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/server_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/server_spec.rb
index 3f75d867936..09548d21106 100644
--- a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/server_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/server_spec.rb
@@ -3,39 +3,71 @@
require 'spec_helper'
RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::Server, :clean_gitlab_redis_queues do
- let(:worker_class) do
- Class.new do
- def self.name
- 'TestDeduplicationWorker'
+ shared_context 'server duplicate job' do |strategy|
+ let(:worker_class) do
+ Class.new do
+ def self.name
+ 'TestDeduplicationWorker'
+ end
+
+ include ApplicationWorker
+
+ deduplicate strategy
+
+ def perform(*args)
+ self.class.work
+ end
+
+ def self.work
+ end
end
+ end
- include ApplicationWorker
+ before do
+ stub_const('TestDeduplicationWorker', worker_class)
+ end
- def perform(*args)
+ around do |example|
+ with_sidekiq_server_middleware do |chain|
+ chain.add described_class
+ Sidekiq::Testing.inline! { example.run }
end
end
end
- before do
- stub_const('TestDeduplicationWorker', worker_class)
- end
+ context 'with until_executing strategy' do
+ include_context 'server duplicate job', :until_executing
- around do |example|
- with_sidekiq_server_middleware do |chain|
- chain.add described_class
- Sidekiq::Testing.inline! { example.run }
+ describe '#call' do
+ it 'removes the stored job from redis before execution' do
+ bare_job = { 'class' => 'TestDeduplicationWorker', 'args' => ['hello'] }
+ job_definition = Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob.new(bare_job.dup, 'test_deduplication')
+
+ expect(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob)
+ .to receive(:new).with(a_hash_including(bare_job), 'test_deduplication')
+ .and_return(job_definition).twice # once in client middleware
+
+ expect(job_definition).to receive(:delete!).ordered.and_call_original
+ expect(TestDeduplicationWorker).to receive(:work).ordered.and_call_original
+
+ TestDeduplicationWorker.perform_async('hello')
+ end
end
end
- describe '#call' do
- it 'removes the stored job from redis' do
+ context 'with until_executed strategy' do
+ include_context 'server duplicate job', :until_executed
+
+ it 'removes the stored job from redis after execution' do
bare_job = { 'class' => 'TestDeduplicationWorker', 'args' => ['hello'] }
job_definition = Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob.new(bare_job.dup, 'test_deduplication')
expect(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob)
.to receive(:new).with(a_hash_including(bare_job), 'test_deduplication')
.and_return(job_definition).twice # once in client middleware
- expect(job_definition).to receive(:delete!).and_call_original
+
+ expect(TestDeduplicationWorker).to receive(:work).ordered.and_call_original
+ expect(job_definition).to receive(:delete!).ordered.and_call_original
TestDeduplicationWorker.perform_async('hello')
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed_spec.rb
new file mode 100644
index 00000000000..b3d463b6f6b
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::UntilExecuted do
+ it_behaves_like 'deduplicating jobs when scheduling', :until_executed do
+ describe '#perform' do
+ let(:proc) { -> {} }
+
+ it 'deletes the lock after executing' do
+ expect(proc).to receive(:call).ordered
+ expect(fake_duplicate_job).to receive(:delete!).ordered
+
+ strategy.perform({}) do
+ proc.call
+ end
+ end
+ 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 10b18052e9a..d45b6c5fcd1 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,146 +1,20 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::UntilExecuting do
- let(:fake_duplicate_job) do
- instance_double(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob)
- end
-
- subject(:strategy) { described_class.new(fake_duplicate_job) }
-
- describe '#schedule' do
- before do
- allow(Gitlab::SidekiqLogging::DeduplicationLogger.instance).to receive(:log)
- end
-
- it 'checks for duplicates before yielding' do
- expect(fake_duplicate_job).to receive(:scheduled?).twice.ordered.and_return(false)
- expect(fake_duplicate_job).to(
- receive(:check!)
- .with(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob::DUPLICATE_KEY_TTL)
- .ordered
- .and_return('a jid'))
- expect(fake_duplicate_job).to receive(:duplicate?).ordered.and_return(false)
-
- expect { |b| strategy.schedule({}, &b) }.to yield_control
- end
-
- it 'checks worker options for scheduled jobs' do
- expect(fake_duplicate_job).to receive(:scheduled?).ordered.and_return(true)
- expect(fake_duplicate_job).to receive(:options).ordered.and_return({})
- expect(fake_duplicate_job).not_to receive(:check!)
-
- expect { |b| strategy.schedule({}, &b) }.to yield_control
- end
-
- context 'job marking' do
- it 'adds the jid of the existing job to the job hash' do
- allow(fake_duplicate_job).to receive(:scheduled?).and_return(false)
- allow(fake_duplicate_job).to receive(:check!).and_return('the jid')
- allow(fake_duplicate_job).to receive(:droppable?).and_return(true)
- allow(fake_duplicate_job).to receive(:options).and_return({})
- job_hash = {}
+ it_behaves_like 'deduplicating jobs when scheduling', :until_executing do
+ describe '#perform' do
+ let(:proc) { -> {} }
- expect(fake_duplicate_job).to receive(:duplicate?).and_return(true)
- expect(fake_duplicate_job).to receive(:existing_jid).and_return('the jid')
+ it 'deletes the lock before executing' do
+ expect(fake_duplicate_job).to receive(:delete!).ordered
+ expect(proc).to receive(:call).ordered
- strategy.schedule(job_hash) {}
-
- expect(job_hash).to include('duplicate-of' => 'the jid')
- end
-
- context 'scheduled jobs' do
- let(:time_diff) { 1.minute }
-
- context 'scheduled in the past' do
- it 'adds the jid of the existing job to the job hash' 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 })
- allow(fake_duplicate_job).to(
- receive(:check!)
- .with(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob::DUPLICATE_KEY_TTL)
- .and_return('the jid'))
- allow(fake_duplicate_job).to receive(:droppable?).and_return(true)
- job_hash = {}
-
- expect(fake_duplicate_job).to receive(:duplicate?).and_return(true)
- expect(fake_duplicate_job).to receive(:existing_jid).and_return('the jid')
-
- strategy.schedule(job_hash) {}
-
- expect(job_hash).to include('duplicate-of' => 'the jid')
- end
+ strategy.perform({}) do
+ proc.call
end
-
- context 'scheduled in the future' do
- it 'adds the jid of the existing job to the job hash' 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 })
- allow(fake_duplicate_job).to(
- receive(:check!).with(time_diff.to_i).and_return('the jid'))
- allow(fake_duplicate_job).to receive(:droppable?).and_return(true)
- job_hash = {}
-
- expect(fake_duplicate_job).to receive(:duplicate?).and_return(true)
- expect(fake_duplicate_job).to receive(:existing_jid).and_return('the jid')
-
- strategy.schedule(job_hash) {}
-
- expect(job_hash).to include('duplicate-of' => 'the jid')
- end
- end
- end
- end
- end
-
- context "when the job is droppable" do
- before do
- allow(fake_duplicate_job).to receive(:scheduled?).and_return(false)
- allow(fake_duplicate_job).to receive(:check!).and_return('the jid')
- allow(fake_duplicate_job).to receive(:duplicate?).and_return(true)
- allow(fake_duplicate_job).to receive(:options).and_return({})
- allow(fake_duplicate_job).to receive(:existing_jid).and_return('the jid')
- allow(fake_duplicate_job).to receive(:droppable?).and_return(true)
- end
-
- it 'drops the job' do
- schedule_result = nil
-
- expect(fake_duplicate_job).to receive(:droppable?).and_return(true)
-
- expect { |b| schedule_result = strategy.schedule({}, &b) }.not_to yield_control
- expect(schedule_result).to be(false)
- end
-
- it 'logs that the job was dropped' do
- fake_logger = instance_double(Gitlab::SidekiqLogging::DeduplicationLogger)
-
- expect(Gitlab::SidekiqLogging::DeduplicationLogger).to receive(:instance).and_return(fake_logger)
- expect(fake_logger).to receive(:log).with(a_hash_including({ 'jid' => 'new jid' }), 'dropped until executing', {})
-
- strategy.schedule({ 'jid' => 'new jid' }) {}
- end
-
- it 'logs the deduplication options of the worker' do
- fake_logger = instance_double(Gitlab::SidekiqLogging::DeduplicationLogger)
-
- expect(Gitlab::SidekiqLogging::DeduplicationLogger).to receive(:instance).and_return(fake_logger)
- allow(fake_duplicate_job).to receive(:options).and_return({ foo: :bar })
- expect(fake_logger).to receive(:log).with(a_hash_including({ 'jid' => 'new jid' }), 'dropped until executing', { foo: :bar })
-
- strategy.schedule({ 'jid' => 'new jid' }) {}
end
end
end
-
- describe '#perform' do
- it 'deletes the lock before executing' do
- expect(fake_duplicate_job).to receive(:delete!).ordered
- expect { |b| strategy.perform({}, &b) }.to yield_control
- end
- end
end
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 84856238aab..e35d779f334 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 `until_executed`' do
+ expect(described_class.for(:until_executed)).to eq(described_class::UntilExecuted)
+ end
+
it 'returns the right class for `none`' do
expect(described_class.for(:none)).to eq(described_class::None)
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
index 2f761b69e60..0b2055d3db5 100644
--- a/spec/lib/gitlab/static_site_editor/config/generated_config_spec.rb
+++ b/spec/lib/gitlab/static_site_editor/config/generated_config_spec.rb
@@ -58,25 +58,9 @@ RSpec.describe Gitlab::StaticSiteEditor::Config::GeneratedConfig do
)
end
- context 'when feature flag is enabled' do
- let(:path) { 'FEATURE_ON.md.erb' }
+ let(:path) { 'README.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
+ it { is_expected.to include(is_supported_content: true) }
end
context 'when file path is nested' do
diff --git a/spec/lib/gitlab/throttle_spec.rb b/spec/lib/gitlab/throttle_spec.rb
index ca2abe94ad2..7462b2e1c38 100644
--- a/spec/lib/gitlab/throttle_spec.rb
+++ b/spec/lib/gitlab/throttle_spec.rb
@@ -12,4 +12,22 @@ RSpec.describe Gitlab::Throttle do
subject
end
end
+
+ describe '.bypass_header' do
+ subject { described_class.bypass_header }
+
+ it 'is nil' do
+ expect(subject).to be_nil
+ end
+
+ context 'when a header is configured' do
+ before do
+ stub_env('GITLAB_THROTTLE_BYPASS_HEADER', 'My-Custom-Header')
+ end
+
+ it 'is a funny upper case rack key' do
+ expect(subject).to eq('HTTP_MY_CUSTOM_HEADER')
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/tracking/destinations/snowplow_spec.rb b/spec/lib/gitlab/tracking/destinations/snowplow_spec.rb
new file mode 100644
index 00000000000..ee63eb6de04
--- /dev/null
+++ b/spec/lib/gitlab/tracking/destinations/snowplow_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Tracking::Destinations::Snowplow do
+ let(:emitter) { SnowplowTracker::Emitter.new('localhost', buffer_size: 1) }
+ let(:tracker) { SnowplowTracker::Tracker.new(emitter, SnowplowTracker::Subject.new, 'namespace', 'app_id') }
+
+ before do
+ stub_application_setting(snowplow_collector_hostname: 'gitfoo.com')
+ stub_application_setting(snowplow_app_id: '_abc123_')
+ end
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ context 'when snowplow is enabled' do
+ before do
+ stub_application_setting(snowplow_enabled: true)
+
+ expect(SnowplowTracker::AsyncEmitter)
+ .to receive(:new)
+ .with('gitfoo.com', { protocol: 'https' })
+ .and_return(emitter)
+
+ expect(SnowplowTracker::Tracker)
+ .to receive(:new)
+ .with(emitter, an_instance_of(SnowplowTracker::Subject), Gitlab::Tracking::SNOWPLOW_NAMESPACE, '_abc123_')
+ .and_return(tracker)
+ end
+
+ describe '#event' do
+ it 'sends event to tracker' do
+ allow(tracker).to receive(:track_struct_event).and_call_original
+
+ subject.event('category', 'action', label: 'label', property: 'property', value: 1.5)
+
+ expect(tracker)
+ .to have_received(:track_struct_event)
+ .with('category', 'action', 'label', 'property', 1.5, nil, (Time.now.to_f * 1000).to_i)
+ end
+ end
+
+ describe '#self_describing_event' do
+ it 'sends event to tracker' do
+ allow(tracker).to receive(:track_self_describing_event).and_call_original
+
+ subject.self_describing_event('iglu:com.gitlab/foo/jsonschema/1-0-0', foo: 'bar')
+
+ expect(tracker).to have_received(:track_self_describing_event) do |event, context, timestamp|
+ expect(event.to_json[:schema]).to eq('iglu:com.gitlab/foo/jsonschema/1-0-0')
+ expect(event.to_json[:data]).to eq(foo: 'bar')
+ expect(context).to eq(nil)
+ expect(timestamp).to eq((Time.now.to_f * 1000).to_i)
+ end
+ end
+ end
+ end
+
+ context 'when snowplow is not enabled' do
+ describe '#event' do
+ it 'does not send event to tracker' do
+ expect_any_instance_of(SnowplowTracker::Tracker).not_to receive(:track_struct_event)
+
+ subject.event('category', 'action', label: 'label', property: 'property', value: 1.5)
+ end
+ end
+
+ describe '#self_describing_event' do
+ it 'does not send event to tracker' do
+ expect_any_instance_of(SnowplowTracker::Tracker).not_to receive(:track_self_describing_event)
+
+ subject.self_describing_event('iglu:com.gitlab/foo/jsonschema/1-0-0', foo: 'bar')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tracking/incident_management_spec.rb b/spec/lib/gitlab/tracking/incident_management_spec.rb
index 9c49c76ead7..fbcb9bf3e4c 100644
--- a/spec/lib/gitlab/tracking/incident_management_spec.rb
+++ b/spec/lib/gitlab/tracking/incident_management_spec.rb
@@ -62,7 +62,7 @@ RSpec.describe Gitlab::Tracking::IncidentManagement do
context 'param without label' do
let(:params) { { create_issue: '1' } }
- it_behaves_like 'a tracked event', "enabled_issue_auto_creation_on_alerts", {}
+ it_behaves_like 'a tracked event', "enabled_issue_auto_creation_on_alerts"
end
end
diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb
index 6ddeaf98370..805bd92fd43 100644
--- a/spec/lib/gitlab/tracking_spec.rb
+++ b/spec/lib/gitlab/tracking_spec.rb
@@ -2,13 +2,13 @@
require 'spec_helper'
RSpec.describe Gitlab::Tracking do
- let(:timestamp) { Time.utc(2017, 3, 22) }
-
before do
stub_application_setting(snowplow_enabled: true)
stub_application_setting(snowplow_collector_hostname: 'gitfoo.com')
stub_application_setting(snowplow_cookie_domain: '.gitfoo.com')
stub_application_setting(snowplow_app_id: '_abc123_')
+
+ described_class.instance_variable_set("@snowplow", nil)
end
describe '.snowplow_options' do
@@ -35,99 +35,23 @@ RSpec.describe Gitlab::Tracking do
end
end
- describe 'tracking events' do
- shared_examples 'events not tracked' do
- it 'does not track events' do
- stub_application_setting(snowplow_enabled: false)
- expect(SnowplowTracker::AsyncEmitter).not_to receive(:new)
- expect(SnowplowTracker::Tracker).not_to receive(:new)
-
- track_event
- end
- end
-
- around do |example|
- travel_to(timestamp) { example.run }
- end
-
- before do
- described_class.instance_variable_set("@snowplow", nil)
- end
-
- let(:tracker) { double }
-
- def receive_events
- expect(SnowplowTracker::AsyncEmitter).to receive(:new).with(
- 'gitfoo.com', { protocol: 'https' }
- ).and_return('_emitter_')
+ describe '.event' do
+ it 'delegates to snowplow destination' do
+ expect_any_instance_of(Gitlab::Tracking::Destinations::Snowplow)
+ .to receive(:event)
+ .with('category', 'action', label: 'label', property: 'property', value: 1.5, context: nil)
- expect(SnowplowTracker::Tracker).to receive(:new).with(
- '_emitter_',
- an_instance_of(SnowplowTracker::Subject),
- 'gl',
- '_abc123_'
- ).and_return(tracker)
+ described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5)
end
+ end
- describe '.event' do
- let(:track_event) do
- described_class.event('category', 'action',
- label: '_label_',
- property: '_property_',
- value: '_value_',
- context: nil
- )
- end
-
- it_behaves_like 'events not tracked'
-
- it 'can track events' do
- receive_events
- expect(tracker).to receive(:track_struct_event).with(
- 'category',
- 'action',
- '_label_',
- '_property_',
- '_value_',
- nil,
- (timestamp.to_f * 1000).to_i
- )
-
- track_event
- end
- end
-
- describe '.self_describing_event' do
- let(:track_event) do
- described_class.self_describing_event('iglu:com.gitlab/example/jsonschema/1-0-2',
- {
- foo: 'bar',
- foo_count: 42
- },
- context: nil
- )
- end
-
- it_behaves_like 'events not tracked'
-
- it 'can track self describing events' do
- receive_events
- expect(SnowplowTracker::SelfDescribingJson).to receive(:new).with(
- 'iglu:com.gitlab/example/jsonschema/1-0-2',
- {
- foo: 'bar',
- foo_count: 42
- }
- ).and_return('_event_json_')
-
- expect(tracker).to receive(:track_self_describing_event).with(
- '_event_json_',
- nil,
- (timestamp.to_f * 1000).to_i
- )
+ describe '.self_describing_event' do
+ it 'delegates to snowplow destination' do
+ expect_any_instance_of(Gitlab::Tracking::Destinations::Snowplow)
+ .to receive(:self_describing_event)
+ .with('iglu:com.gitlab/foo/jsonschema/1-0-0', { foo: 'bar' }, context: nil)
- track_event
- end
+ described_class.self_describing_event('iglu:com.gitlab/foo/jsonschema/1-0-0', foo: 'bar')
end
end
end
diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb
index b49efd6a092..f466d117851 100644
--- a/spec/lib/gitlab/url_blocker_spec.rb
+++ b/spec/lib/gitlab/url_blocker_spec.rb
@@ -350,7 +350,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
expect(described_class).to be_blocked_url('http://[fe80::c800:eff:fe74:8]', allow_local_network: false)
end
- context 'when local domain/IP is whitelisted' do
+ context 'when local domain/IP is allowed' do
let(:url_blocker_attributes) do
{
allow_localhost: false,
@@ -360,11 +360,11 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
before do
allow(ApplicationSetting).to receive(:current).and_return(ApplicationSetting.new)
- stub_application_setting(outbound_local_requests_whitelist: whitelist)
+ stub_application_setting(outbound_local_requests_whitelist: allowlist)
end
- context 'with IPs in whitelist' do
- let(:whitelist) do
+ context 'with IPs in allowlist' do
+ let(:allowlist) do
[
'0.0.0.0',
'127.0.0.1',
@@ -396,7 +396,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
it_behaves_like 'allows local requests', { allow_localhost: false, allow_local_network: false }
- it 'whitelists IP when dns_rebind_protection is disabled' do
+ it 'allows IP when dns_rebind_protection is disabled' do
url = "http://example.com"
attrs = url_blocker_attributes.merge(dns_rebind_protection: false)
@@ -410,8 +410,8 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
end
end
- context 'with domains in whitelist' do
- let(:whitelist) do
+ context 'with domains in allowlist' do
+ let(:allowlist) do
[
'www.example.com',
'example.com',
@@ -420,7 +420,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
]
end
- it 'allows domains present in whitelist' do
+ it 'allows domains present in allowlist' do
domain = 'example.com'
subdomain1 = 'www.example.com'
subdomain2 = 'subdomain.example.com'
@@ -435,7 +435,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
url_blocker_attributes)
end
- # subdomain2 is not part of the whitelist so it should be blocked
+ # subdomain2 is not part of the allowlist so it should be blocked
stub_domain_resolv(subdomain2, '192.168.1.1') do
expect(described_class).to be_blocked_url("http://#{subdomain2}",
url_blocker_attributes)
@@ -458,8 +458,8 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
end
shared_examples 'dns rebinding checks' do
- shared_examples 'whitelists the domain' do
- let(:whitelist) { [domain] }
+ shared_examples 'allowlists the domain' do
+ let(:allowlist) { [domain] }
let(:url) { "http://#{domain}" }
before do
@@ -475,13 +475,13 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
context 'enabled' do
let(:dns_rebind_value) { true }
- it_behaves_like 'whitelists the domain'
+ it_behaves_like 'allowlists the domain'
end
context 'disabled' do
let(:dns_rebind_value) { false }
- it_behaves_like 'whitelists the domain'
+ it_behaves_like 'allowlists the domain'
end
end
end
@@ -504,11 +504,11 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
end
context 'with ports' do
- let(:whitelist) do
+ let(:allowlist) do
["127.0.0.1:2000"]
end
- it 'allows domain with port when resolved ip has port whitelisted' do
+ it 'allows domain with port when resolved ip has port allowed' do
stub_domain_resolv("www.resolve-domain.com", '127.0.0.1') do
expect(described_class).not_to be_blocked_url("http://www.resolve-domain.com:2000", url_blocker_attributes)
end
diff --git a/spec/lib/gitlab/url_blockers/domain_allowlist_entry_spec.rb b/spec/lib/gitlab/url_blockers/domain_allowlist_entry_spec.rb
new file mode 100644
index 00000000000..ece0a018d53
--- /dev/null
+++ b/spec/lib/gitlab/url_blockers/domain_allowlist_entry_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UrlBlockers::DomainAllowlistEntry do
+ let(:domain) { 'www.example.com' }
+
+ describe '#initialize' do
+ it 'initializes without port' do
+ domain_allowlist_entry = described_class.new(domain)
+
+ expect(domain_allowlist_entry.domain).to eq(domain)
+ expect(domain_allowlist_entry.port).to be(nil)
+ end
+
+ it 'initializes with port' do
+ port = 8080
+ domain_allowlist_entry = described_class.new(domain, port: port)
+
+ expect(domain_allowlist_entry.domain).to eq(domain)
+ expect(domain_allowlist_entry.port).to eq(port)
+ end
+ end
+
+ describe '#match?' do
+ it 'matches when domain and port are equal' do
+ port = 8080
+ domain_allowlist_entry = described_class.new(domain, port: port)
+
+ expect(domain_allowlist_entry).to be_match(domain, port)
+ end
+
+ it 'matches any port when port is nil' do
+ domain_allowlist_entry = described_class.new(domain)
+
+ expect(domain_allowlist_entry).to be_match(domain, 8080)
+ expect(domain_allowlist_entry).to be_match(domain, 9090)
+ end
+
+ it 'does not match when port is present but requested_port is nil' do
+ domain_allowlist_entry = described_class.new(domain, port: 8080)
+
+ expect(domain_allowlist_entry).not_to be_match(domain, nil)
+ end
+
+ it 'matches when port and requested_port are nil' do
+ domain_allowlist_entry = described_class.new(domain)
+
+ expect(domain_allowlist_entry).to be_match(domain)
+ end
+
+ it 'does not match if domain is not equal' do
+ domain_allowlist_entry = described_class.new(domain)
+
+ expect(domain_allowlist_entry).not_to be_match('www.gitlab.com', 8080)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/url_blockers/domain_whitelist_entry_spec.rb b/spec/lib/gitlab/url_blockers/domain_whitelist_entry_spec.rb
deleted file mode 100644
index 58bae109146..00000000000
--- a/spec/lib/gitlab/url_blockers/domain_whitelist_entry_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::UrlBlockers::DomainWhitelistEntry do
- let(:domain) { 'www.example.com' }
-
- describe '#initialize' do
- it 'initializes without port' do
- domain_whitelist_entry = described_class.new(domain)
-
- expect(domain_whitelist_entry.domain).to eq(domain)
- expect(domain_whitelist_entry.port).to be(nil)
- end
-
- it 'initializes with port' do
- port = 8080
- domain_whitelist_entry = described_class.new(domain, port: port)
-
- expect(domain_whitelist_entry.domain).to eq(domain)
- expect(domain_whitelist_entry.port).to eq(port)
- end
- end
-
- describe '#match?' do
- it 'matches when domain and port are equal' do
- port = 8080
- domain_whitelist_entry = described_class.new(domain, port: port)
-
- expect(domain_whitelist_entry).to be_match(domain, port)
- end
-
- it 'matches any port when port is nil' do
- domain_whitelist_entry = described_class.new(domain)
-
- expect(domain_whitelist_entry).to be_match(domain, 8080)
- expect(domain_whitelist_entry).to be_match(domain, 9090)
- end
-
- it 'does not match when port is present but requested_port is nil' do
- domain_whitelist_entry = described_class.new(domain, port: 8080)
-
- expect(domain_whitelist_entry).not_to be_match(domain, nil)
- end
-
- it 'matches when port and requested_port are nil' do
- domain_whitelist_entry = described_class.new(domain)
-
- expect(domain_whitelist_entry).to be_match(domain)
- end
-
- it 'does not match if domain is not equal' do
- domain_whitelist_entry = described_class.new(domain)
-
- expect(domain_whitelist_entry).not_to be_match('www.gitlab.com', 8080)
- end
- end
-end
diff --git a/spec/lib/gitlab/url_blockers/ip_allowlist_entry_spec.rb b/spec/lib/gitlab/url_blockers/ip_allowlist_entry_spec.rb
new file mode 100644
index 00000000000..110a6c17adb
--- /dev/null
+++ b/spec/lib/gitlab/url_blockers/ip_allowlist_entry_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UrlBlockers::IpAllowlistEntry do
+ let(:ipv4) { IPAddr.new('192.168.1.1') }
+
+ describe '#initialize' do
+ it 'initializes without port' do
+ ip_allowlist_entry = described_class.new(ipv4)
+
+ expect(ip_allowlist_entry.ip).to eq(ipv4)
+ expect(ip_allowlist_entry.port).to be(nil)
+ end
+
+ it 'initializes with port' do
+ port = 8080
+ ip_allowlist_entry = described_class.new(ipv4, port: port)
+
+ expect(ip_allowlist_entry.ip).to eq(ipv4)
+ expect(ip_allowlist_entry.port).to eq(port)
+ end
+ end
+
+ describe '#match?' do
+ it 'matches with equivalent IP and port' do
+ port = 8080
+ ip_allowlist_entry = described_class.new(ipv4, port: port)
+
+ expect(ip_allowlist_entry).to be_match(ipv4.to_s, port)
+ end
+
+ it 'matches any port when port is nil' do
+ ip_allowlist_entry = described_class.new(ipv4)
+
+ expect(ip_allowlist_entry).to be_match(ipv4.to_s, 8080)
+ expect(ip_allowlist_entry).to be_match(ipv4.to_s, 9090)
+ end
+
+ it 'does not match when port is present but requested_port is nil' do
+ ip_allowlist_entry = described_class.new(ipv4, port: 8080)
+
+ expect(ip_allowlist_entry).not_to be_match(ipv4.to_s, nil)
+ end
+
+ it 'matches when port and requested_port are nil' do
+ ip_allowlist_entry = described_class.new(ipv4)
+
+ expect(ip_allowlist_entry).to be_match(ipv4.to_s)
+ end
+
+ it 'works with ipv6' do
+ ipv6 = IPAddr.new('fe80::c800:eff:fe74:8')
+ ip_allowlist_entry = described_class.new(ipv6)
+
+ expect(ip_allowlist_entry).to be_match(ipv6.to_s, 8080)
+ end
+
+ it 'matches ipv4 within IPv4 range' do
+ ipv4_range = IPAddr.new('127.0.0.0/28')
+ ip_allowlist_entry = described_class.new(ipv4_range)
+
+ expect(ip_allowlist_entry).to be_match(ipv4_range.to_range.last.to_s, 8080)
+ expect(ip_allowlist_entry).not_to be_match('127.0.1.1', 8080)
+ end
+
+ it 'matches IPv6 within IPv6 range' do
+ ipv6_range = IPAddr.new('fd84:6d02:f6d8:c89e::/124')
+ ip_allowlist_entry = described_class.new(ipv6_range)
+
+ expect(ip_allowlist_entry).to be_match(ipv6_range.to_range.last.to_s, 8080)
+ expect(ip_allowlist_entry).not_to be_match('fd84:6d02:f6d8:f::f', 8080)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/url_blockers/ip_whitelist_entry_spec.rb b/spec/lib/gitlab/url_blockers/ip_whitelist_entry_spec.rb
deleted file mode 100644
index 52f9b31165a..00000000000
--- a/spec/lib/gitlab/url_blockers/ip_whitelist_entry_spec.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::UrlBlockers::IpWhitelistEntry do
- let(:ipv4) { IPAddr.new('192.168.1.1') }
-
- describe '#initialize' do
- it 'initializes without port' do
- ip_whitelist_entry = described_class.new(ipv4)
-
- expect(ip_whitelist_entry.ip).to eq(ipv4)
- expect(ip_whitelist_entry.port).to be(nil)
- end
-
- it 'initializes with port' do
- port = 8080
- ip_whitelist_entry = described_class.new(ipv4, port: port)
-
- expect(ip_whitelist_entry.ip).to eq(ipv4)
- expect(ip_whitelist_entry.port).to eq(port)
- end
- end
-
- describe '#match?' do
- it 'matches with equivalent IP and port' do
- port = 8080
- ip_whitelist_entry = described_class.new(ipv4, port: port)
-
- expect(ip_whitelist_entry).to be_match(ipv4.to_s, port)
- end
-
- it 'matches any port when port is nil' do
- ip_whitelist_entry = described_class.new(ipv4)
-
- expect(ip_whitelist_entry).to be_match(ipv4.to_s, 8080)
- expect(ip_whitelist_entry).to be_match(ipv4.to_s, 9090)
- end
-
- it 'does not match when port is present but requested_port is nil' do
- ip_whitelist_entry = described_class.new(ipv4, port: 8080)
-
- expect(ip_whitelist_entry).not_to be_match(ipv4.to_s, nil)
- end
-
- it 'matches when port and requested_port are nil' do
- ip_whitelist_entry = described_class.new(ipv4)
-
- expect(ip_whitelist_entry).to be_match(ipv4.to_s)
- end
-
- it 'works with ipv6' do
- ipv6 = IPAddr.new('fe80::c800:eff:fe74:8')
- ip_whitelist_entry = described_class.new(ipv6)
-
- expect(ip_whitelist_entry).to be_match(ipv6.to_s, 8080)
- end
-
- it 'matches ipv4 within IPv4 range' do
- ipv4_range = IPAddr.new('127.0.0.0/28')
- ip_whitelist_entry = described_class.new(ipv4_range)
-
- expect(ip_whitelist_entry).to be_match(ipv4_range.to_range.last.to_s, 8080)
- expect(ip_whitelist_entry).not_to be_match('127.0.1.1', 8080)
- end
-
- it 'matches IPv6 within IPv6 range' do
- ipv6_range = IPAddr.new('fd84:6d02:f6d8:c89e::/124')
- ip_whitelist_entry = described_class.new(ipv6_range)
-
- expect(ip_whitelist_entry).to be_match(ipv6_range.to_range.last.to_s, 8080)
- expect(ip_whitelist_entry).not_to be_match('fd84:6d02:f6d8:f::f', 8080)
- end
- end
-end
diff --git a/spec/lib/gitlab/url_blockers/url_allowlist_spec.rb b/spec/lib/gitlab/url_blockers/url_allowlist_spec.rb
new file mode 100644
index 00000000000..d9e44e9b85c
--- /dev/null
+++ b/spec/lib/gitlab/url_blockers/url_allowlist_spec.rb
@@ -0,0 +1,164 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UrlBlockers::UrlAllowlist do
+ include StubRequests
+
+ let(:allowlist) { [] }
+
+ before do
+ allow(ApplicationSetting).to receive(:current).and_return(ApplicationSetting.new)
+ stub_application_setting(outbound_local_requests_whitelist: allowlist)
+ end
+
+ describe '#domain_allowed?' do
+ let(:allowlist) { %w[www.example.com example.com] }
+
+ it 'returns true if domains present in allowlist' do
+ not_allowed = %w[subdomain.example.com example.org]
+
+ aggregate_failures do
+ allowlist.each do |domain|
+ expect(described_class).to be_domain_allowed(domain)
+ end
+
+ not_allowed.each do |domain|
+ expect(described_class).not_to be_domain_allowed(domain)
+ end
+ end
+ end
+
+ it 'returns false when domain is blank' do
+ expect(described_class).not_to be_domain_allowed(nil)
+ end
+
+ context 'with ports' do
+ let(:allowlist) { ['example.io:3000'] }
+
+ it 'returns true if domain and ports present in allowlist' do
+ parsed_allowlist = [['example.io', { port: 3000 }]]
+ not_allowed = [
+ 'example.io',
+ ['example.io', { port: 3001 }]
+ ]
+
+ aggregate_failures do
+ parsed_allowlist.each do |domain_and_port|
+ expect(described_class).to be_domain_allowed(*domain_and_port)
+ end
+
+ not_allowed.each do |domain_and_port|
+ expect(described_class).not_to be_domain_allowed(*domain_and_port)
+ end
+ end
+ end
+ end
+ end
+
+ describe '#ip_allowed?' do
+ let(:allowlist) do
+ [
+ '0.0.0.0',
+ '127.0.0.1',
+ '192.168.1.1',
+ '0:0:0:0:0:ffff:192.168.1.2',
+ '::ffff:c0a8:102',
+ 'fc00:bf8b:e62c:abcd:abcd:aaaa:aaaa:aaaa',
+ '0:0:0:0:0:ffff:169.254.169.254',
+ '::ffff:a9fe:a9fe',
+ '::ffff:a9fe:a864',
+ 'fe80::c800:eff:fe74:8'
+ ]
+ end
+
+ it 'returns true if ips present in allowlist' do
+ aggregate_failures do
+ allowlist.each do |ip_address|
+ expect(described_class).to be_ip_allowed(ip_address)
+ end
+
+ %w[172.16.2.2 127.0.0.2 fe80::c800:eff:fe74:9].each do |ip_address|
+ expect(described_class).not_to be_ip_allowed(ip_address)
+ end
+ end
+ end
+
+ it 'returns false when ip is blank' do
+ expect(described_class).not_to be_ip_allowed(nil)
+ end
+
+ context 'with ip ranges in allowlist' do
+ let(:ipv4_range) { '127.0.0.0/28' }
+ let(:ipv6_range) { 'fd84:6d02:f6d8:c89e::/124' }
+
+ let(:allowlist) do
+ [
+ ipv4_range,
+ ipv6_range
+ ]
+ end
+
+ it 'does not allowlist ipv4 range when not in allowlist' do
+ stub_application_setting(outbound_local_requests_whitelist: [])
+
+ IPAddr.new(ipv4_range).to_range.to_a.each do |ip|
+ expect(described_class).not_to be_ip_allowed(ip.to_s)
+ end
+ end
+
+ it 'allowlists all ipv4s in the range when in allowlist' do
+ IPAddr.new(ipv4_range).to_range.to_a.each do |ip|
+ expect(described_class).to be_ip_allowed(ip.to_s)
+ end
+ end
+
+ it 'does not allowlist ipv6 range when not in allowlist' do
+ stub_application_setting(outbound_local_requests_whitelist: [])
+
+ IPAddr.new(ipv6_range).to_range.to_a.each do |ip|
+ expect(described_class).not_to be_ip_allowed(ip.to_s)
+ end
+ end
+
+ it 'allowlists all ipv6s in the range when in allowlist' do
+ IPAddr.new(ipv6_range).to_range.to_a.each do |ip|
+ expect(described_class).to be_ip_allowed(ip.to_s)
+ end
+ end
+
+ it 'does not allowlist IPs outside the range' do
+ expect(described_class).not_to be_ip_allowed("fd84:6d02:f6d8:c89e:0:0:1:f")
+
+ expect(described_class).not_to be_ip_allowed("127.0.1.15")
+ end
+ end
+
+ context 'with ports' do
+ let(:allowlist) { %w[127.0.0.9:3000 [2001:db8:85a3:8d3:1319:8a2e:370:7348]:443] }
+
+ it 'returns true if ip and ports present in allowlist' do
+ parsed_allowlist = [
+ ['127.0.0.9', { port: 3000 }],
+ ['[2001:db8:85a3:8d3:1319:8a2e:370:7348]', { port: 443 }]
+ ]
+ not_allowed = [
+ '127.0.0.9',
+ ['127.0.0.9', { port: 3001 }],
+ '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
+ ['[2001:db8:85a3:8d3:1319:8a2e:370:7348]', { port: 3001 }]
+ ]
+
+ aggregate_failures do
+ parsed_allowlist.each do |ip_and_port|
+ expect(described_class).to be_ip_allowed(*ip_and_port)
+ end
+
+ not_allowed.each do |ip_and_port|
+ expect(described_class).not_to be_ip_allowed(*ip_and_port)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/url_blockers/url_whitelist_spec.rb b/spec/lib/gitlab/url_blockers/url_whitelist_spec.rb
deleted file mode 100644
index 7a65516be3c..00000000000
--- a/spec/lib/gitlab/url_blockers/url_whitelist_spec.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::UrlBlockers::UrlWhitelist do
- include StubRequests
-
- let(:whitelist) { [] }
-
- before do
- allow(ApplicationSetting).to receive(:current).and_return(ApplicationSetting.new)
- stub_application_setting(outbound_local_requests_whitelist: whitelist)
- end
-
- describe '#domain_whitelisted?' do
- let(:whitelist) { ['www.example.com', 'example.com'] }
-
- it 'returns true if domains present in whitelist' do
- not_whitelisted = ['subdomain.example.com', 'example.org']
-
- aggregate_failures do
- whitelist.each do |domain|
- expect(described_class).to be_domain_whitelisted(domain)
- end
-
- not_whitelisted.each do |domain|
- expect(described_class).not_to be_domain_whitelisted(domain)
- end
- end
- end
-
- it 'returns false when domain is blank' do
- expect(described_class).not_to be_domain_whitelisted(nil)
- end
-
- context 'with ports' do
- let(:whitelist) { ['example.io:3000'] }
-
- it 'returns true if domain and ports present in whitelist' do
- parsed_whitelist = [['example.io', { port: 3000 }]]
- not_whitelisted = [
- 'example.io',
- ['example.io', { port: 3001 }]
- ]
-
- aggregate_failures do
- parsed_whitelist.each do |domain_and_port|
- expect(described_class).to be_domain_whitelisted(*domain_and_port)
- end
-
- not_whitelisted.each do |domain_and_port|
- expect(described_class).not_to be_domain_whitelisted(*domain_and_port)
- end
- end
- end
- end
- end
-
- describe '#ip_whitelisted?' do
- let(:whitelist) do
- [
- '0.0.0.0',
- '127.0.0.1',
- '192.168.1.1',
- '0:0:0:0:0:ffff:192.168.1.2',
- '::ffff:c0a8:102',
- 'fc00:bf8b:e62c:abcd:abcd:aaaa:aaaa:aaaa',
- '0:0:0:0:0:ffff:169.254.169.254',
- '::ffff:a9fe:a9fe',
- '::ffff:a9fe:a864',
- 'fe80::c800:eff:fe74:8'
- ]
- end
-
- it 'returns true if ips present in whitelist' do
- aggregate_failures do
- whitelist.each do |ip_address|
- expect(described_class).to be_ip_whitelisted(ip_address)
- end
-
- ['172.16.2.2', '127.0.0.2', 'fe80::c800:eff:fe74:9'].each do |ip_address|
- expect(described_class).not_to be_ip_whitelisted(ip_address)
- end
- end
- end
-
- it 'returns false when ip is blank' do
- expect(described_class).not_to be_ip_whitelisted(nil)
- end
-
- context 'with ip ranges in whitelist' do
- let(:ipv4_range) { '127.0.0.0/28' }
- let(:ipv6_range) { 'fd84:6d02:f6d8:c89e::/124' }
-
- let(:whitelist) do
- [
- ipv4_range,
- ipv6_range
- ]
- end
-
- it 'does not whitelist ipv4 range when not in whitelist' do
- stub_application_setting(outbound_local_requests_whitelist: [])
-
- IPAddr.new(ipv4_range).to_range.to_a.each do |ip|
- expect(described_class).not_to be_ip_whitelisted(ip.to_s)
- end
- end
-
- it 'whitelists all ipv4s in the range when in whitelist' do
- IPAddr.new(ipv4_range).to_range.to_a.each do |ip|
- expect(described_class).to be_ip_whitelisted(ip.to_s)
- end
- end
-
- it 'does not whitelist ipv6 range when not in whitelist' do
- stub_application_setting(outbound_local_requests_whitelist: [])
-
- IPAddr.new(ipv6_range).to_range.to_a.each do |ip|
- expect(described_class).not_to be_ip_whitelisted(ip.to_s)
- end
- end
-
- it 'whitelists all ipv6s in the range when in whitelist' do
- IPAddr.new(ipv6_range).to_range.to_a.each do |ip|
- expect(described_class).to be_ip_whitelisted(ip.to_s)
- end
- end
-
- it 'does not whitelist IPs outside the range' do
- expect(described_class).not_to be_ip_whitelisted("fd84:6d02:f6d8:c89e:0:0:1:f")
-
- expect(described_class).not_to be_ip_whitelisted("127.0.1.15")
- end
- end
-
- context 'with ports' do
- let(:whitelist) { ['127.0.0.9:3000', '[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443'] }
-
- it 'returns true if ip and ports present in whitelist' do
- parsed_whitelist = [
- ['127.0.0.9', { port: 3000 }],
- ['[2001:db8:85a3:8d3:1319:8a2e:370:7348]', { port: 443 }]
- ]
- not_whitelisted = [
- '127.0.0.9',
- ['127.0.0.9', { port: 3001 }],
- '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
- ['[2001:db8:85a3:8d3:1319:8a2e:370:7348]', { port: 3001 }]
- ]
-
- aggregate_failures do
- parsed_whitelist.each do |ip_and_port|
- expect(described_class).to be_ip_whitelisted(*ip_and_port)
- end
-
- not_whitelisted.each do |ip_and_port|
- expect(described_class).not_to be_ip_whitelisted(*ip_and_port)
- end
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb
index b58b5a84662..c892f1f0410 100644
--- a/spec/lib/gitlab/url_builder_spec.rb
+++ b/spec/lib/gitlab/url_builder_spec.rb
@@ -24,6 +24,7 @@ RSpec.describe Gitlab::UrlBuilder do
:project_milestone | ->(milestone) { "/#{milestone.project.full_path}/-/milestones/#{milestone.iid}" }
:project_snippet | ->(snippet) { "/#{snippet.project.full_path}/-/snippets/#{snippet.id}" }
:project_wiki | ->(wiki) { "/#{wiki.container.full_path}/-/wikis/home" }
+ :release | ->(release) { "/#{release.project.full_path}/-/releases/#{release.tag}" }
:ci_build | ->(build) { "/#{build.project.full_path}/-/jobs/#{build.id}" }
:design | ->(design) { "/#{design.project.full_path}/-/design_management/designs/#{design.id}/raw_image" }
diff --git a/spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb b/spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb
new file mode 100644
index 00000000000..e9fb5346eae
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'aggregated metrics' do
+ RSpec::Matchers.define :be_known_event do
+ match do |event|
+ Gitlab::UsageDataCounters::HLLRedisCounter.known_event?(event)
+ end
+
+ failure_message do
+ "Event with name: `#{event}` can not be found within `#{Gitlab::UsageDataCounters::HLLRedisCounter::KNOWN_EVENTS_PATH}`"
+ end
+ end
+
+ let_it_be(:known_events) do
+ Gitlab::UsageDataCounters::HLLRedisCounter.known_events
+ end
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.aggregated_metrics.tap do |aggregated_metrics|
+ it 'all events has unique name' do
+ event_names = aggregated_metrics&.map { |event| event[:name] }
+
+ expect(event_names).to eq(event_names&.uniq)
+ end
+
+ aggregated_metrics&.each do |aggregate|
+ context "for #{aggregate[:name]} aggregate of #{aggregate[:events].join(' ')}" do
+ let_it_be(:events_records) { known_events.select { |event| aggregate[:events].include?(event[:name]) } }
+
+ it "only refers to known events" do
+ expect(aggregate[:events]).to all be_known_event
+ end
+
+ it "has expected structure" do
+ expect(aggregate.keys).to include(*%w[name operator events])
+ end
+
+ it "uses allowed aggregation operators" do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter::ALLOWED_METRICS_AGGREGATIONS).to include aggregate[:operator]
+ end
+
+ it "uses events from the same Redis slot" do
+ event_slots = events_records.map { |event| event[:redis_slot] }.uniq
+
+ expect(event_slots).to contain_exactly(be_present)
+ end
+
+ it "uses events with the same aggregation period" do
+ event_slots = events_records.map { |event| event[:aggregation] }.uniq
+
+ expect(event_slots).to contain_exactly(be_present)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
index e84c3c17274..93704a39555 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,6 +8,9 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
let(:entity3) { '34rfjuuy-ce56-sa35-ds34-dfer567dfrf2' }
let(:entity4) { '8b9a2671-2abf-4bec-a682-22f6a8f7bf31' }
+ let(:default_context) { 'default' }
+ let(:invalid_context) { 'invalid' }
+
around do |example|
# We need to freeze to a reference time
# because visits are grouped by the week number in the year
@@ -20,7 +23,28 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
describe '.categories' do
it 'gets all unique category names' do
- expect(described_class.categories).to contain_exactly('analytics', 'compliance', 'ide_edit', 'search', 'source_code', 'incident_management', 'issues_edit', 'testing')
+ expect(described_class.categories).to contain_exactly(
+ 'compliance',
+ 'analytics',
+ 'ide_edit',
+ 'search',
+ 'source_code',
+ 'incident_management',
+ 'testing',
+ 'issues_edit',
+ 'ci_secrets_management',
+ 'maven_packages',
+ 'npm_packages',
+ 'conan_packages',
+ 'nuget_packages',
+ 'pypi_packages',
+ 'composer_packages',
+ 'generic_packages',
+ 'golang_packages',
+ 'debian_packages',
+ 'container_packages',
+ 'tag_packages'
+ )
end
end
@@ -34,11 +58,13 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
let(:no_slot) { 'no_slot' }
let(:different_aggregation) { 'different_aggregation' }
let(:custom_daily_event) { 'g_analytics_custom' }
+ let(:context_event) { 'context_event' }
let(:global_category) { 'global' }
- let(:compliance_category) {'compliance' }
- let(:productivity_category) {'productivity' }
+ let(:compliance_category) { 'compliance' }
+ let(:productivity_category) { 'productivity' }
let(:analytics_category) { 'analytics' }
+ let(:other_category) { 'other' }
let(:known_events) do
[
@@ -47,7 +73,8 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
{ 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" }
+ { name: different_aggregation, category: global_category, aggregation: "monthly" },
+ { name: context_event, category: other_category, expiry: 6, aggregation: 'weekly' }
].map(&:with_indifferent_access)
end
@@ -77,12 +104,18 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
stub_application_setting(usage_ping_enabled: true)
end
+ it 'tracks event when using symbol' do
+ expect(Gitlab::Redis::HLL).to receive(:add)
+
+ described_class.track_event(entity1, :g_analytics_contribution)
+ end
+
it "raise error if metrics don't have same aggregation" do
- expect { described_class.track_event(entity1, different_aggregation, Date.current) } .to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownAggregation)
+ expect { described_class.track_event(entity1, different_aggregation, Date.current) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownAggregation)
end
it 'raise error if metrics of unknown aggregation' do
- expect { described_class.track_event(entity1, 'unknown', Date.current) } .to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent)
+ expect { described_class.track_event(entity1, 'unknown', Date.current) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent)
end
context 'for weekly events' do
@@ -143,6 +176,34 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
end
end
+ describe '.track_event_in_context' do
+ context 'with valid contex' do
+ it 'increments conext event counte' do
+ expect(Gitlab::Redis::HLL).to receive(:add) do |kwargs|
+ expect(kwargs[:key]).to match(/^#{default_context}\_.*/)
+ end
+
+ described_class.track_event_in_context(entity1, context_event, default_context)
+ end
+ end
+
+ context 'with empty context' do
+ it 'does not increment a counter' do
+ expect(Gitlab::Redis::HLL).not_to receive(:add)
+
+ described_class.track_event_in_context(entity1, context_event, '')
+ end
+ end
+
+ context 'when sending invalid context' do
+ it 'does not increment a counter' do
+ expect(Gitlab::Redis::HLL).not_to receive(:add)
+
+ described_class.track_event_in_context(entity1, context_event, invalid_context)
+ end
+ end
+ end
+
describe '.unique_events' do
before do
# events in current week, should not be counted as week is not complete
@@ -178,37 +239,89 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
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')
+ expect do
+ described_class.unique_events(event_names: [compliance_slot_event, analytics_slot_event], start_date: 4.weeks.ago, end_date: Date.current)
+ end.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::SlotMismatch)
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')
+ expect do
+ described_class.unique_events(event_names: [category_analytics_event, category_productivity_event], start_date: 4.weeks.ago, end_date: Date.current)
+ end.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::CategoryMismatch)
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')
+ expect do
+ described_class.unique_events(event_names: [daily_event, weekly_event], start_date: 4.weeks.ago, end_date: Date.current)
+ end.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::AggregationMismatch)
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) }
+ 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) }
+ 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) }
+ 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 symbol as parameter' do
+ it { expect(described_class.unique_events(event_names: [weekly_event.to_sym], 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) }
+ 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) }
+ 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
+
+ describe 'context level tracking' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:known_events) do
+ [
+ { name: 'event_name_1', redis_slot: 'event', category: 'category1', aggregation: "weekly" },
+ { name: 'event_name_2', redis_slot: 'event', category: 'category1', aggregation: "weekly" },
+ { name: 'event_name_3', redis_slot: 'event', category: 'category1', aggregation: "weekly" }
+ ].map(&:with_indifferent_access)
+ end
+
+ 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_in_context([entity1, entity3], 'event_name_1', default_context, 2.days.ago)
+ described_class.track_event_in_context(entity3, 'event_name_1', default_context, 2.days.ago)
+ described_class.track_event_in_context(entity3, 'event_name_1', invalid_context, 2.days.ago)
+ described_class.track_event_in_context([entity1, entity2], 'event_name_2', '', 2.weeks.ago)
+ end
+
+ subject(:unique_events) { described_class.unique_events(event_names: event_names, start_date: 4.weeks.ago, end_date: Date.current, context: context) }
+
+ context 'with correct arguments' do
+ where(:event_names, :context, :value) do
+ ['event_name_1'] | 'default' | 2
+ ['event_name_1'] | '' | 0
+ ['event_name_2'] | '' | 0
+ end
+
+ with_them do
+ it { is_expected.to eq value }
+ end
+ end
+
+ context 'with invalid context' do
+ it 'raise error' do
+ expect { described_class.unique_events(event_names: 'event_name_1', start_date: 4.weeks.ago, end_date: Date.current, context: invalid_context) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::InvalidContext)
end
end
end
@@ -257,4 +370,183 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
expect(subject.unique_events_data).to eq(results)
end
end
+
+ context 'aggregated_metrics_data' do
+ let(:known_events) do
+ [
+ { name: 'event1_slot', redis_slot: "slot", category: 'category1', aggregation: "weekly" },
+ { name: 'event2_slot', redis_slot: "slot", category: 'category2', aggregation: "weekly" },
+ { name: 'event3_slot', redis_slot: "slot", category: 'category3', aggregation: "weekly" },
+ { name: 'event5_slot', redis_slot: "slot", category: 'category4', aggregation: "weekly" },
+ { name: 'event4', category: 'category2', aggregation: "weekly" }
+ ].map(&:with_indifferent_access)
+ end
+
+ before do
+ allow(described_class).to receive(:known_events).and_return(known_events)
+ end
+
+ shared_examples 'aggregated_metrics_data' do
+ context 'no aggregated metrics is defined' do
+ it 'returns empty hash' do
+ allow(described_class).to receive(:aggregated_metrics).and_return([])
+
+ expect(aggregated_metrics_data).to eq({})
+ end
+ end
+
+ context 'there are aggregated metrics defined' do
+ before do
+ allow(described_class).to receive(:aggregated_metrics).and_return(aggregated_metrics)
+ end
+
+ context 'with AND operator' do
+ let(:aggregated_metrics) do
+ [
+ { name: 'gmau_1', events: %w[event1_slot event2_slot], operator: "AND" },
+ { name: 'gmau_2', events: %w[event1_slot event2_slot event3_slot], operator: "AND" },
+ { name: 'gmau_3', events: %w[event1_slot event2_slot event3_slot event5_slot], operator: "AND" },
+ { name: 'gmau_4', events: %w[event4], operator: "AND" }
+ ].map(&:with_indifferent_access)
+ end
+
+ it 'returns the number of unique events for all known events' do
+ results = {
+ 'gmau_1' => 3,
+ 'gmau_2' => 2,
+ 'gmau_3' => 1,
+ 'gmau_4' => 3
+ }
+
+ expect(aggregated_metrics_data).to eq(results)
+ end
+ end
+
+ context 'with OR operator' do
+ let(:aggregated_metrics) do
+ [
+ { name: 'gmau_1', events: %w[event3_slot event5_slot], operator: "OR" },
+ { name: 'gmau_2', events: %w[event1_slot event2_slot event3_slot event5_slot], operator: "OR" },
+ { name: 'gmau_3', events: %w[event4], operator: "OR" }
+ ].map(&:with_indifferent_access)
+ end
+
+ it 'returns the number of unique events for all known events' do
+ results = {
+ 'gmau_1' => 2,
+ 'gmau_2' => 3,
+ 'gmau_3' => 3
+ }
+
+ expect(aggregated_metrics_data).to eq(results)
+ end
+ end
+
+ context 'hidden behind feature flag' do
+ let(:enabled_feature_flag) { 'test_ff_enabled' }
+ let(:disabled_feature_flag) { 'test_ff_disabled' }
+ let(:aggregated_metrics) do
+ [
+ # represents stable aggregated metrics that has been fully released
+ { name: 'gmau_without_ff', events: %w[event3_slot event5_slot], operator: "OR" },
+ # represents new aggregated metric that is under performance testing on gitlab.com
+ { name: 'gmau_enabled', events: %w[event4], operator: "AND", feature_flag: enabled_feature_flag },
+ # represents aggregated metric that is under development and shouldn't be yet collected even on gitlab.com
+ { name: 'gmau_disabled', events: %w[event4], operator: "AND", feature_flag: disabled_feature_flag }
+ ].map(&:with_indifferent_access)
+ end
+
+ it 'returns the number of unique events for all known events' do
+ skip_feature_flags_yaml_validation
+ stub_feature_flags(enabled_feature_flag => true, disabled_feature_flag => false)
+
+ expect(aggregated_metrics_data).to eq('gmau_without_ff' => 2, 'gmau_enabled' => 3)
+ end
+ end
+ end
+ end
+
+ describe '.aggregated_metrics_weekly_data' do
+ subject(:aggregated_metrics_data) { described_class.aggregated_metrics_weekly_data }
+
+ before do
+ described_class.track_event(entity1, 'event1_slot', 2.days.ago)
+ described_class.track_event(entity2, 'event1_slot', 2.days.ago)
+ described_class.track_event(entity3, 'event1_slot', 2.days.ago)
+ described_class.track_event(entity1, 'event2_slot', 2.days.ago)
+ described_class.track_event(entity2, 'event2_slot', 3.days.ago)
+ described_class.track_event(entity3, 'event2_slot', 3.days.ago)
+ described_class.track_event(entity1, 'event3_slot', 3.days.ago)
+ described_class.track_event(entity2, 'event3_slot', 3.days.ago)
+ described_class.track_event(entity2, 'event5_slot', 3.days.ago)
+
+ # events out of time scope
+ described_class.track_event(entity3, 'event2_slot', 8.days.ago)
+
+ # events in different slots
+ described_class.track_event(entity1, 'event4', 2.days.ago)
+ described_class.track_event(entity2, 'event4', 2.days.ago)
+ described_class.track_event(entity4, 'event4', 2.days.ago)
+ end
+
+ it_behaves_like 'aggregated_metrics_data'
+ end
+
+ describe '.aggregated_metrics_monthly_data' do
+ subject(:aggregated_metrics_data) { described_class.aggregated_metrics_monthly_data }
+
+ it_behaves_like 'aggregated_metrics_data' do
+ before do
+ described_class.track_event(entity1, 'event1_slot', 2.days.ago)
+ described_class.track_event(entity2, 'event1_slot', 2.days.ago)
+ described_class.track_event(entity3, 'event1_slot', 2.days.ago)
+ described_class.track_event(entity1, 'event2_slot', 2.days.ago)
+ described_class.track_event(entity2, 'event2_slot', 3.days.ago)
+ described_class.track_event(entity3, 'event2_slot', 3.days.ago)
+ described_class.track_event(entity1, 'event3_slot', 3.days.ago)
+ described_class.track_event(entity2, 'event3_slot', 10.days.ago)
+ described_class.track_event(entity2, 'event5_slot', 4.weeks.ago.advance(days: 1))
+
+ # events out of time scope
+ described_class.track_event(entity1, 'event5_slot', 4.weeks.ago.advance(days: -1))
+
+ # events in different slots
+ described_class.track_event(entity1, 'event4', 2.days.ago)
+ described_class.track_event(entity2, 'event4', 2.days.ago)
+ described_class.track_event(entity4, 'event4', 2.days.ago)
+ end
+ end
+
+ context 'Redis calls' do
+ let(:aggregated_metrics) do
+ [
+ { name: 'gmau_3', events: %w[event1_slot event2_slot event3_slot event5_slot], operator: "AND" }
+ ].map(&:with_indifferent_access)
+ end
+
+ let(:known_events) do
+ [
+ { name: 'event1_slot', redis_slot: "slot", category: 'category1', aggregation: "weekly" },
+ { name: 'event2_slot', redis_slot: "slot", category: 'category2', aggregation: "weekly" },
+ { name: 'event3_slot', redis_slot: "slot", category: 'category3', aggregation: "weekly" },
+ { name: 'event5_slot', redis_slot: "slot", category: 'category4', aggregation: "weekly" }
+ ].map(&:with_indifferent_access)
+ end
+
+ it 'caches intermediate operations' do
+ allow(described_class).to receive(:known_events).and_return(known_events)
+ allow(described_class).to receive(:aggregated_metrics).and_return(aggregated_metrics)
+
+ 4.downto(1) do |subset_size|
+ known_events.combination(subset_size).each do |events|
+ keys = described_class.send(:weekly_redis_keys, events: events, start_date: 4.weeks.ago.to_date, end_date: Date.current)
+ expect(Gitlab::Redis::HLL).to receive(:count).with(keys: keys).once.and_return(0)
+ end
+ end
+
+ subject
+ end
+ end
+ 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
index e08dc41d0cc..803eff05efe 100644
--- 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
@@ -8,42 +8,8 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
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
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_TITLE_CHANGED }
def track_action(params)
@@ -53,7 +19,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue description edit actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_DESCRIPTION_CHANGED }
def track_action(params)
@@ -63,7 +29,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue assignee edit actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_ASSIGNEE_CHANGED }
def track_action(params)
@@ -73,7 +39,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue make confidential actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_MADE_CONFIDENTIAL }
def track_action(params)
@@ -83,7 +49,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue make visible actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_MADE_VISIBLE }
def track_action(params)
@@ -93,7 +59,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue created actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_CREATED }
def track_action(params)
@@ -103,7 +69,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue closed actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_CLOSED }
def track_action(params)
@@ -113,7 +79,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue reopened actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_REOPENED }
def track_action(params)
@@ -123,7 +89,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue label changed actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_LABEL_CHANGED }
def track_action(params)
@@ -133,7 +99,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue cross-referenced actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_CROSS_REFERENCED }
def track_action(params)
@@ -143,7 +109,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue moved actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_MOVED }
def track_action(params)
@@ -153,7 +119,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue relate actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_RELATED }
def track_action(params)
@@ -163,7 +129,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue unrelate actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_UNRELATED }
def track_action(params)
@@ -173,7 +139,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue marked as duplicate actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_MARKED_AS_DUPLICATE }
def track_action(params)
@@ -183,7 +149,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue locked actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_LOCKED }
def track_action(params)
@@ -193,7 +159,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue unlocked actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_UNLOCKED }
def track_action(params)
@@ -202,38 +168,8 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
end
- context 'for Issue added to epic actions' do
- it_behaves_like 'tracks and counts action' do
- let(:action) { described_class::ISSUE_ADDED_TO_EPIC}
-
- def track_action(params)
- described_class.track_issue_added_to_epic_action(**params)
- end
- end
- end
-
- context 'for Issue removed from epic actions' do
- it_behaves_like 'tracks and counts action' do
- let(:action) { described_class::ISSUE_REMOVED_FROM_EPIC}
-
- def track_action(params)
- described_class.track_issue_removed_from_epic_action(**params)
- end
- end
- end
-
- context 'for Issue changed epic actions' do
- it_behaves_like 'tracks and counts action' do
- let(:action) { described_class::ISSUE_CHANGED_EPIC}
-
- def track_action(params)
- described_class.track_issue_changed_epic_action(**params)
- end
- end
- end
-
context 'for Issue designs added actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_DESIGNS_ADDED }
def track_action(params)
@@ -243,7 +179,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue designs modified actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_DESIGNS_MODIFIED }
def track_action(params)
@@ -253,7 +189,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue designs removed actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_DESIGNS_REMOVED }
def track_action(params)
@@ -263,7 +199,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue due date changed actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_DUE_DATE_CHANGED }
def track_action(params)
@@ -273,7 +209,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue time estimate changed actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_TIME_ESTIMATE_CHANGED }
def track_action(params)
@@ -283,7 +219,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue time spent changed actions' do
- it_behaves_like 'tracks and counts action' do
+ it_behaves_like 'a tracked issue edit event' do
let(:action) { described_class::ISSUE_TIME_SPENT_CHANGED }
def track_action(params)
@@ -292,6 +228,36 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
end
+ context 'for Issue comment added actions' do
+ it_behaves_like 'a tracked issue edit event' do
+ let(:action) { described_class::ISSUE_COMMENT_ADDED }
+
+ def track_action(params)
+ described_class.track_issue_comment_added_action(**params)
+ end
+ end
+ end
+
+ context 'for Issue comment edited actions' do
+ it_behaves_like 'a tracked issue edit event' do
+ let(:action) { described_class::ISSUE_COMMENT_EDITED }
+
+ def track_action(params)
+ described_class.track_issue_comment_edited_action(**params)
+ end
+ end
+ end
+
+ context 'for Issue comment removed actions' do
+ it_behaves_like 'a tracked issue edit event' do
+ let(:action) { described_class::ISSUE_COMMENT_REMOVED }
+
+ def track_action(params)
+ described_class.track_issue_comment_removed_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)
diff --git a/spec/lib/gitlab/usage_data_counters/static_site_editor_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/static_site_editor_counter_spec.rb
index aaa576865f6..1bf5dad1c9f 100644
--- a/spec/lib/gitlab/usage_data_counters/static_site_editor_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/static_site_editor_counter_spec.rb
@@ -4,7 +4,11 @@ require 'spec_helper'
RSpec.describe Gitlab::UsageDataCounters::StaticSiteEditorCounter do
it_behaves_like 'a redis usage counter', 'StaticSiteEditor', :views
+ it_behaves_like 'a redis usage counter', 'StaticSiteEditor', :commits
+ it_behaves_like 'a redis usage counter', 'StaticSiteEditor', :merge_requests
it_behaves_like 'a redis usage counter with totals', :static_site_editor,
- views: 3
+ views: 3,
+ commits: 4,
+ merge_requests: 5
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index f64fa2b868d..d305b2c5bfe 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -12,33 +12,37 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
describe '.uncached_data' do
- describe '.usage_activity_by_stage' do
- subject { described_class.uncached_data }
-
- 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(subject[:usage_activity_by_stage_monthly])
- .to include(:configure, :create, :manage, :monitor, :plan, :release, :verify)
- end
-
- it 'clears memoized values' do
- allow(described_class).to receive(:clear_memoization)
+ subject { described_class.uncached_data }
+
+ it 'includes basic top and second level keys' do
+ is_expected.to include(:counts)
+ is_expected.to include(:counts_monthly)
+ is_expected.to include(:counts_weekly)
+ is_expected.to include(:license)
+ is_expected.to include(:settings)
+
+ # usage_activity_by_stage data
+ 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(subject[:usage_activity_by_stage_monthly])
+ .to include(:configure, :create, :manage, :monitor, :plan, :release, :verify)
+ expect(subject[:usage_activity_by_stage][:create])
+ .not_to include(:merge_requests_users)
+ expect(subject[:usage_activity_by_stage_monthly][:create])
+ .to include(:merge_requests_users)
+ expect(subject[:counts_weekly]).to include(:aggregated_metrics)
+ expect(subject[:counts_monthly]).to include(:aggregated_metrics)
+ end
- subject
+ it 'clears memoized values' do
+ allow(described_class).to receive(:clear_memoization)
- described_class::CE_MEMOIZED_VALUES.each do |key|
- expect(described_class).to have_received(:clear_memoization).with(key)
- end
- end
+ subject
- it 'merge_requests_users is included only in montly counters' do
- expect(subject[:usage_activity_by_stage][:create])
- .not_to include(:merge_requests_users)
- expect(subject[:usage_activity_by_stage_monthly][:create])
- .to include(:merge_requests_users)
+ described_class::CE_MEMOIZED_VALUES.each do |key|
+ expect(described_class).to have_received(:clear_memoization).with(key)
end
end
@@ -48,7 +52,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
expect(described_class).to receive(:recorded_at).and_raise(Exception.new('Stopped calculating recorded_at'))
- expect { described_class.uncached_data }.to raise_error('Stopped calculating recorded_at')
+ expect { subject }.to raise_error('Stopped calculating recorded_at')
end
end
@@ -168,6 +172,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
omniauth:
{ providers: omniauth_providers }
)
+ allow(Devise).to receive(:omniauth_providers).and_return(%w(ldapmain ldapsecondary group_saml))
for_defined_days_back do
user = create(:user)
@@ -186,14 +191,14 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
groups: 2,
users_created: 6,
omniauth_providers: ['google_oauth2'],
- user_auth_by_provider: { 'group_saml' => 2, 'ldap' => 4 }
+ user_auth_by_provider: { 'group_saml' => 2, 'ldap' => 4, 'standard' => 0, 'two-factor' => 0, 'two-factor-via-u2f-device' => 0, "two-factor-via-webauthn-device" => 0 }
)
expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period)).to include(
events: 1,
groups: 1,
users_created: 3,
omniauth_providers: ['google_oauth2'],
- user_auth_by_provider: { 'group_saml' => 1, 'ldap' => 2 }
+ user_auth_by_provider: { 'group_saml' => 1, 'ldap' => 2, 'standard' => 0, 'two-factor' => 0, 'two-factor-via-u2f-device' => 0, "two-factor-via-webauthn-device" => 0 }
)
end
@@ -201,17 +206,25 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
for_defined_days_back do
user = create(:user)
+ create(:bulk_import, user: 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)
+
+ create(:issue_csv_import, user: user)
end
expect(described_class.usage_activity_by_stage_manage({})).to include(
{
+ bulk_imports: {
+ gitlab: 2
+ },
projects_imported: {
+ total: 20,
gitlab_project: 2,
gitlab: 2,
github: 2,
@@ -224,13 +237,18 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
issues_imported: {
jira: 2,
fogbugz: 2,
- phabricator: 2
+ phabricator: 2,
+ csv: 2
}
}
)
expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period)).to include(
{
+ bulk_imports: {
+ gitlab: 1
+ },
projects_imported: {
+ total: 10,
gitlab_project: 1,
gitlab: 1,
github: 1,
@@ -243,7 +261,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
issues_imported: {
jira: 1,
fogbugz: 1,
- phabricator: 1
+ phabricator: 1,
+ csv: 1
}
}
)
@@ -280,19 +299,29 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
create(:project, creator: user)
create(:clusters_applications_prometheus, :installed, cluster: cluster)
create(:project_tracing_setting)
+ create(:project_error_tracking_setting)
+ create(:incident)
+ create(:incident, alert_management_alert: create(:alert_management_alert))
end
expect(described_class.usage_activity_by_stage_monitor({})).to include(
clusters: 2,
clusters_applications_prometheus: 2,
operations_dashboard_default_dashboard: 2,
- projects_with_tracing_enabled: 2
+ projects_with_tracing_enabled: 2,
+ projects_with_error_tracking_enabled: 2,
+ projects_with_incidents: 4,
+ projects_with_alert_incidents: 2
)
+
expect(described_class.usage_activity_by_stage_monitor(described_class.last_28_days_time_period)).to include(
clusters: 1,
clusters_applications_prometheus: 1,
operations_dashboard_default_dashboard: 1,
- projects_with_tracing_enabled: 1
+ projects_with_tracing_enabled: 1,
+ projects_with_error_tracking_enabled: 1,
+ projects_with_incidents: 2,
+ projects_with_alert_incidents: 1
)
end
end
@@ -446,9 +475,11 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(count_data[:projects_with_error_tracking_enabled]).to eq(1)
expect(count_data[:projects_with_tracing_enabled]).to eq(1)
expect(count_data[:projects_with_alerts_service_enabled]).to eq(1)
+ expect(count_data[:projects_with_enabled_alert_integrations]).to eq(1)
expect(count_data[:projects_with_prometheus_alerts]).to eq(2)
expect(count_data[:projects_with_terraform_reports]).to eq(2)
expect(count_data[:projects_with_terraform_states]).to eq(2)
+ expect(count_data[:projects_with_alerts_created]).to eq(1)
expect(count_data[:protected_branches]).to eq(2)
expect(count_data[:protected_branches_except_default]).to eq(1)
expect(count_data[:terraform_reports]).to eq(6)
@@ -532,13 +563,13 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
subject { described_class.data[:counts] }
it 'gathers usage data' do
- expect(subject[:projects_with_expiration_policy_enabled]).to eq 22
- expect(subject[:projects_with_expiration_policy_disabled]).to eq 1
+ expect(subject[:projects_with_expiration_policy_enabled]).to eq 18
+ expect(subject[:projects_with_expiration_policy_disabled]).to eq 5
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_unset]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_1]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_5]).to eq 1
- expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_10]).to eq 16
+ expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_10]).to eq 12
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_25]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_50]).to eq 1
@@ -546,9 +577,9 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_7d]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_14d]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_30d]).to eq 1
- expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_90d]).to eq 18
+ expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_90d]).to eq 14
- expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_1d]).to eq 18
+ expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_1d]).to eq 14
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_7d]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_14d]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_1month]).to eq 1
@@ -577,9 +608,22 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
describe '.system_usage_data_monthly' do
let_it_be(:project) { create(:project) }
- let!(:ud) { build(:usage_data) }
before do
+ project = create(:project)
+ env = create(:environment)
+ create(:package, project: project, created_at: 3.days.ago)
+ create(:package, created_at: 2.months.ago, project: project)
+
+ [3, 31].each do |n|
+ deployment_options = { created_at: n.days.ago, project: env.project, environment: env }
+ create(:deployment, :failed, deployment_options)
+ create(:deployment, :success, deployment_options)
+ create(:project_snippet, project: project, created_at: n.days.ago)
+ create(:personal_snippet, created_at: n.days.ago)
+ create(:alert_management_alert, project: project, created_at: n.days.ago)
+ end
+
stub_application_setting(self_monitoring_project: project)
for_defined_days_back do
@@ -595,10 +639,11 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(counts_monthly[:deployments]).to eq(2)
expect(counts_monthly[:successful_deployments]).to eq(1)
expect(counts_monthly[:failed_deployments]).to eq(1)
- expect(counts_monthly[:snippets]).to eq(3)
+ expect(counts_monthly[:snippets]).to eq(2)
expect(counts_monthly[:personal_snippets]).to eq(1)
- expect(counts_monthly[:project_snippets]).to eq(2)
- expect(counts_monthly[:packages]).to eq(3)
+ expect(counts_monthly[:project_snippets]).to eq(1)
+ expect(counts_monthly[:projects_with_alerts_created]).to eq(1)
+ expect(counts_monthly[:packages]).to eq(1)
expect(counts_monthly[:promoted_issues]).to eq(1)
end
end
@@ -1047,6 +1092,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
let(:user1) { build(:user, id: 1) }
let(:user2) { build(:user, id: 2) }
let(:user3) { build(:user, id: 3) }
+ let(:user4) { build(:user, id: 4) }
before do
counter = Gitlab::UsageDataCounters::TrackUniqueEvents
@@ -1061,6 +1107,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
counter.track_event(event_action: :pushed, event_target: project, author_id: 4, 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.track_event(event_action: :created, event_target: design, author_id: 4)
counter = Gitlab::UsageDataCounters::EditorUniqueCounter
@@ -1080,9 +1127,10 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
it 'returns the distinct count of user actions within the specified time period' do
expect(described_class.action_monthly_active_users(time_period)).to eq(
{
- action_monthly_active_users_design_management: 1,
+ action_monthly_active_users_design_management: 2,
action_monthly_active_users_project_repo: 3,
action_monthly_active_users_wiki_repo: 1,
+ action_monthly_active_users_git_write: 4,
action_monthly_active_users_web_ide_edit: 2,
action_monthly_active_users_sfe_edit: 2,
action_monthly_active_users_snippet_editor_edit: 2,
@@ -1187,7 +1235,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
subject { described_class.redis_hll_counters }
let(:categories) { ::Gitlab::UsageDataCounters::HLLRedisCounter.categories }
- let(:ineligible_total_categories) { %w[source_code testing] }
+ let(:ineligible_total_categories) { %w[source_code testing ci_secrets_management] }
it 'has all known_events' do
expect(subject).to have_key(:redis_hll_counters)
@@ -1208,6 +1256,48 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
+ describe 'aggregated_metrics' do
+ shared_examples 'aggregated_metrics_for_time_range' do
+ context 'with product_analytics_aggregated_metrics feature flag on' do
+ before do
+ stub_feature_flags(product_analytics_aggregated_metrics: true)
+ end
+
+ it 'uses ::Gitlab::UsageDataCounters::HLLRedisCounter#aggregated_metrics_data', :aggregate_failures do
+ expect(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(aggregated_metrics_data_method).and_return(global_search_gmau: 123)
+ expect(aggregated_metrics_payload).to eq(aggregated_metrics: { global_search_gmau: 123 })
+ end
+ end
+
+ context 'with product_analytics_aggregated_metrics feature flag off' do
+ before do
+ stub_feature_flags(product_analytics_aggregated_metrics: false)
+ end
+
+ it 'returns empty hash', :aggregate_failures do
+ expect(::Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(aggregated_metrics_data_method)
+ expect(aggregated_metrics_payload).to be {}
+ end
+ end
+ end
+
+ describe '.aggregated_metrics_weekly' do
+ subject(:aggregated_metrics_payload) { described_class.aggregated_metrics_weekly }
+
+ let(:aggregated_metrics_data_method) { :aggregated_metrics_weekly_data }
+
+ it_behaves_like 'aggregated_metrics_for_time_range'
+ end
+
+ describe '.aggregated_metrics_monthly' do
+ subject(:aggregated_metrics_payload) { described_class.aggregated_metrics_monthly }
+
+ let(:aggregated_metrics_data_method) { :aggregated_metrics_monthly_data }
+
+ it_behaves_like 'aggregated_metrics_for_time_range'
+ end
+ end
+
describe '.service_desk_counts' do
subject { described_class.send(:service_desk_counts) }
diff --git a/spec/lib/gitlab/with_feature_category_spec.rb b/spec/lib/gitlab/with_feature_category_spec.rb
new file mode 100644
index 00000000000..b6fe1c84b26
--- /dev/null
+++ b/spec/lib/gitlab/with_feature_category_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_relative "../../../lib/gitlab/with_feature_category"
+
+RSpec.describe Gitlab::WithFeatureCategory do
+ describe ".feature_category_for_action" do
+ let(:base_controller) do
+ Class.new do
+ include ::Gitlab::WithFeatureCategory
+ end
+ end
+
+ let(:controller) do
+ Class.new(base_controller) do
+ feature_category :foo, %w(update edit)
+ feature_category :bar, %w(index show)
+ feature_category :quux, %w(destroy)
+ end
+ end
+
+ let(:subclass) do
+ Class.new(controller) do
+ feature_category :baz, %w(subclass_index)
+ end
+ end
+
+ it "is nil when nothing was defined" do
+ expect(base_controller.feature_category_for_action("hello")).to be_nil
+ end
+
+ it "returns the expected category", :aggregate_failures do
+ expect(controller.feature_category_for_action("update")).to eq(:foo)
+ expect(controller.feature_category_for_action("index")).to eq(:bar)
+ expect(controller.feature_category_for_action("destroy")).to eq(:quux)
+ end
+
+ it "returns the expected category for categories defined in subclasses" do
+ expect(subclass.feature_category_for_action("subclass_index")).to eq(:baz)
+ end
+
+ it "raises an error when defining for the controller and for individual actions" do
+ expect do
+ Class.new(base_controller) do
+ feature_category :hello
+ feature_category :goodbye, [:world]
+ end
+ end.to raise_error(ArgumentError, "hello is defined for all actions, but other categories are set")
+ end
+
+ it "raises an error when multiple calls define the same action" do
+ expect do
+ Class.new(base_controller) do
+ feature_category :hello, [:world]
+ feature_category :goodbye, ["world"]
+ end
+ end.to raise_error(ArgumentError, "Actions have multiple feature categories: world")
+ end
+
+ it "does not raise an error when multiple calls define the same action and feature category" do
+ expect do
+ Class.new(base_controller) do
+ feature_category :hello, [:world]
+ feature_category :hello, ["world"]
+ end
+ end.not_to raise_error
+ end
+ end
+end
diff --git a/spec/lib/quality/test_level_spec.rb b/spec/lib/quality/test_level_spec.rb
index 0b113e8b63a..0239c974755 100644
--- a/spec/lib/quality/test_level_spec.rb
+++ b/spec/lib/quality/test_level_spec.rb
@@ -18,6 +18,13 @@ RSpec.describe Quality::TestLevel do
end
end
+ context 'when level is frontend_fixture' do
+ it 'returns a pattern' do
+ expect(subject.pattern(:frontend_fixture))
+ .to eq("spec/{frontend/fixtures}{,/**/}*.rb")
+ end
+ end
+
context 'when level is unit' do
it 'returns a pattern' do
expect(subject.pattern(:unit))
@@ -86,6 +93,13 @@ RSpec.describe Quality::TestLevel do
end
end
+ context 'when level is frontend_fixture' do
+ it 'returns a regexp' do
+ expect(subject.regexp(:frontend_fixture))
+ .to eq(%r{spec/(frontend/fixtures)})
+ end
+ end
+
context 'when level is unit' do
it 'returns a regexp' do
expect(subject.regexp(:unit))
@@ -144,6 +158,10 @@ RSpec.describe Quality::TestLevel do
expect(subject.level_for('spec/models/abuse_report_spec.rb')).to eq(:unit)
end
+ it 'returns the correct level for a frontend fixture test' do
+ expect(subject.level_for('spec/frontend/fixtures/pipelines.rb')).to eq(:frontend_fixture)
+ end
+
it 'returns the correct level for a tooling test' do
expect(subject.level_for('spec/tooling/lib/tooling/test_file_finder_spec.rb')).to eq(:unit)
end
diff --git a/spec/mailers/devise_mailer_spec.rb b/spec/mailers/devise_mailer_spec.rb
index 2ee15308400..c9dfee8255d 100644
--- a/spec/mailers/devise_mailer_spec.rb
+++ b/spec/mailers/devise_mailer_spec.rb
@@ -64,4 +64,34 @@ RSpec.describe DeviseMailer do
is_expected.to have_body_text /#{Gitlab.config.gitlab.url}/
end
end
+
+ describe '#user_admin_approval' do
+ subject { described_class.user_admin_approval(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 'Welcome to GitLab!'
+ end
+
+ it 'greets the user' do
+ is_expected.to have_body_text /Hi #{user.name}!/
+ end
+
+ it 'includes the correct content' do
+ is_expected.to have_body_text /Your GitLab account request has been approved!/
+ end
+
+ it 'includes a link to GitLab' do
+ is_expected.to have_link(Gitlab.config.gitlab.url)
+ end
+ end
end
diff --git a/spec/mailers/emails/merge_requests_spec.rb b/spec/mailers/emails/merge_requests_spec.rb
index 9235a946394..412cdff3aba 100644
--- a/spec/mailers/emails/merge_requests_spec.rb
+++ b/spec/mailers/emails/merge_requests_spec.rb
@@ -52,7 +52,8 @@ RSpec.describe Emails::MergeRequests do
it { expect(subject.subject).to eq("#{project.name} | Exported merge requests") }
it { expect(subject.to).to contain_exactly(user.notification_email_for(project.group)) }
- it { expect(subject).to have_content('Your CSV export of 10 merge requests from project')}
+ it { expect(subject.html_part).to have_content("Your CSV export of 10 merge requests from project") }
+ it { expect(subject.text_part).to have_content("Your CSV export of 10 merge requests from project") }
context 'when truncated' do
let(:export_status) do
diff --git a/spec/mailers/emails/projects_spec.rb b/spec/mailers/emails/projects_spec.rb
index aa5947bf68e..6c23625d4a3 100644
--- a/spec/mailers/emails/projects_spec.rb
+++ b/spec/mailers/emails/projects_spec.rb
@@ -32,19 +32,13 @@ RSpec.describe Emails::Projects do
describe '#prometheus_alert_fired_email' do
let(:default_title) { Gitlab::AlertManagement::Payload::Generic::DEFAULT_TITLE }
let(:payload) { { 'startsAt' => Time.now.rfc3339 } }
- let(:alert_attributes) { build(:alert_management_alert, :from_payload, payload: payload, project: project).attributes }
+ let(:alert) { create(:alert_management_alert, :from_payload, payload: payload, project: project) }
subject do
- Notify.prometheus_alert_fired_email(project.id, user.id, alert_attributes)
+ Notify.prometheus_alert_fired_email(project, user, alert)
end
- context 'missing required attributes' do
- let(:alert_attributes) { build(:alert_management_alert, :prometheus, :from_payload, payload: payload, project: project).attributes }
-
- it_behaves_like 'no email'
- end
-
- context 'with minimum required attributes' do
+ context 'with empty payload' do
let(:payload) { {} }
it_behaves_like 'an email sent from GitLab'
@@ -58,6 +52,7 @@ RSpec.describe Emails::Projects do
it 'has expected content' do
is_expected.to have_body_text('An alert has been triggered')
is_expected.to have_body_text(project.full_path)
+ is_expected.to have_body_text(alert.details_url)
is_expected.not_to have_body_text('Description:')
is_expected.not_to have_body_text('Environment:')
is_expected.not_to have_body_text('Metric:')
@@ -78,6 +73,7 @@ RSpec.describe Emails::Projects do
it 'has expected content' do
is_expected.to have_body_text('An alert has been triggered')
is_expected.to have_body_text(project.full_path)
+ is_expected.to have_body_text(alert.details_url)
is_expected.to have_body_text('Description:')
is_expected.to have_body_text('alert description')
is_expected.not_to have_body_text('Environment:')
@@ -101,6 +97,7 @@ RSpec.describe Emails::Projects do
it 'has expected content' do
is_expected.to have_body_text('An alert has been triggered')
is_expected.to have_body_text(project.full_path)
+ is_expected.to have_body_text(alert.details_url)
is_expected.to have_body_text('Environment:')
is_expected.to have_body_text(environment.name)
is_expected.not_to have_body_text('Description:')
@@ -112,7 +109,7 @@ RSpec.describe Emails::Projects do
let_it_be(:prometheus_alert) { create(:prometheus_alert, project: project) }
let_it_be(:environment) { prometheus_alert.environment }
- let(:alert_attributes) { build(:alert_management_alert, :prometheus, :from_payload, payload: payload, project: project).attributes }
+ let(:alert) { create(:alert_management_alert, :prometheus, :from_payload, payload: payload, project: project) }
let(:title) { "#{prometheus_alert.title} #{prometheus_alert.computed_operator} #{prometheus_alert.threshold}" }
let(:metrics_url) { metrics_project_environment_url(project, environment) }
@@ -135,6 +132,7 @@ RSpec.describe Emails::Projects do
it 'has expected content' do
is_expected.to have_body_text('An alert has been triggered')
is_expected.to have_body_text(project.full_path)
+ is_expected.to have_body_text(alert.details_url)
is_expected.to have_body_text('Environment:')
is_expected.to have_body_text(environment.name)
is_expected.to have_body_text('Metric:')
@@ -143,5 +141,23 @@ RSpec.describe Emails::Projects do
is_expected.not_to have_body_text('Description:')
end
end
+
+ context 'resolved' do
+ let_it_be(:alert) { create(:alert_management_alert, :resolved, project: project) }
+
+ 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 'has expected subject' do
+ is_expected.to have_subject("#{project.name} | Alert: #{alert.title}")
+ end
+
+ it 'has expected content' do
+ is_expected.to have_body_text('An alert has been resolved')
+ is_expected.to have_body_text(project.full_path)
+ is_expected.to have_body_text(alert.details_url)
+ end
+ end
end
end
diff --git a/spec/mailers/emails/service_desk_spec.rb b/spec/mailers/emails/service_desk_spec.rb
index 842f82539cb..7d04b373be6 100644
--- a/spec/mailers/emails/service_desk_spec.rb
+++ b/spec/mailers/emails/service_desk_spec.rb
@@ -183,6 +183,25 @@ RSpec.describe Emails::ServiceDesk do
it_behaves_like 'handle template content', 'new_note'
end
+
+ context 'with upload link in the note' do
+ let_it_be(:upload_path) { '/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg' }
+ let_it_be(:note) { create(:note_on_issue, noteable: issue, project: project, note: "a new comment with [file](#{upload_path})") }
+
+ let(:template_content) { 'some text %{ NOTE_TEXT }' }
+ let(:expected_body) { %Q(some text a new comment with <a href="#{project.web_url}#{upload_path}" data-link="true" class="gfm">file</a>) }
+
+ it_behaves_like 'handle template content', 'new_note'
+ end
+
+ context 'with all-user reference in a an external author comment' do
+ let_it_be(:note) { create(:note_on_issue, noteable: issue, project: project, note: "Hey @all, just a ping", author: User.support_bot) }
+
+ let(:template_content) { 'some text %{ NOTE_TEXT }' }
+ let(:expected_body) { 'Hey , just a ping' }
+
+ it_behaves_like 'handle template content', 'new_note'
+ end
end
end
end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 8604939ead9..3cc5f202b1f 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -619,6 +619,7 @@ RSpec.describe Notify do
let(:mailer) do
mailer = described_class.new
mailer.instance_variable_set(:@note, mail_thread_note)
+ mailer.instance_variable_set(:@target_url, "https://some.link")
mailer
end
@@ -887,96 +888,30 @@ RSpec.describe Notify do
subject { described_class.member_invited_email('project', project_member.id, project_member.invite_token) }
- context 'when invite_email_experiment is disabled' do
- before do
- stub_feature_flags(invite_email_experiment: false)
- 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"
- it_behaves_like 'appearance header and footer enabled'
- it_behaves_like 'appearance header and footer not enabled'
+ 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 'does not render a manage notifications link'
+ context 'when there is an inviter' do
it 'contains all the useful information' do
- is_expected.to have_subject "Invitation to join the #{project.full_name} project"
+ 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
+ is_expected.to have_body_text project_member.human_access.downcase
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 no inviter' do
+ let(:inviter) { nil }
- 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
+ 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
end
@@ -1547,95 +1482,31 @@ RSpec.describe Notify do
end
end
- context 'when invite_email_experiment is disabled' do
- before do
- stub_feature_flags(invite_email_experiment: false)
- 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"
- 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_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_behaves_like 'does not render a manage notifications link'
+ context 'when there is an inviter' do
it 'contains all the useful information' do
- is_expected.to have_subject "Invitation to join the #{group.name} group"
+ 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.web_url
- is_expected.to have_body_text group_member.human_access
+ is_expected.to have_body_text group_member.human_access.downcase
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 no inviter' do
+ let(:inviter) { nil }
- 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
+ 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
end
diff --git a/spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb b/spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb
index 196f5ead8d2..11398685549 100644
--- a/spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb
+++ b/spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190924152703_migrate_issue_trackers_data.rb')
+require_migration!('migrate_issue_trackers_data')
RSpec.describe MigrateIssueTrackersData do
let(:services) { table(:services) }
diff --git a/spec/migrations/20191015154408_drop_merge_requests_require_code_owner_approval_from_projects_spec.rb b/spec/migrations/20191015154408_drop_merge_requests_require_code_owner_approval_from_projects_spec.rb
index e2eacc00e5a..731bc923910 100644
--- a/spec/migrations/20191015154408_drop_merge_requests_require_code_owner_approval_from_projects_spec.rb
+++ b/spec/migrations/20191015154408_drop_merge_requests_require_code_owner_approval_from_projects_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20191015154408_drop_merge_requests_require_code_owner_approval_from_projects.rb')
+require_migration!('drop_merge_requests_require_code_owner_approval_from_projects')
RSpec.describe DropMergeRequestsRequireCodeOwnerApprovalFromProjects do
let(:projects_table) { table(:projects) }
diff --git a/spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb b/spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb
new file mode 100644
index 00000000000..c1fbde69100
--- /dev/null
+++ b/spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20201027002551_migrate_services_to_http_integrations.rb')
+
+RSpec.describe MigrateServicesToHttpIntegrations do
+ let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
+ let!(:project) { table(:projects).create!(id: 1, namespace_id: namespace.id) }
+ let!(:alert_service) { table(:services).create!(type: 'AlertsService', project_id: project.id, active: true) }
+ let!(:alert_service_data) { table(:alerts_service_data).create!(service_id: alert_service.id, encrypted_token: 'test', encrypted_token_iv: 'test')}
+ let(:http_integrations) { table(:alert_management_http_integrations) }
+
+ describe '#up' do
+ it 'creates the http integrations from the alert services', :aggregate_failures do
+ expect { migrate! }.to change { http_integrations.count }.by(1)
+
+ http_integration = http_integrations.last
+ expect(http_integration.project_id).to eq(alert_service.project_id)
+ expect(http_integration.encrypted_token).to eq(alert_service_data.encrypted_token)
+ expect(http_integration.encrypted_token_iv).to eq(alert_service_data.encrypted_token_iv)
+ expect(http_integration.active).to eq(alert_service.active)
+ expect(http_integration.name).to eq(described_class::SERVICE_NAMES_IDENTIFIER[:name])
+ expect(http_integration.endpoint_identifier).to eq(described_class::SERVICE_NAMES_IDENTIFIER[:identifier])
+ end
+ end
+end
diff --git a/spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb b/spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb
new file mode 100644
index 00000000000..658b26b1c49
--- /dev/null
+++ b/spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20201028182809_backfill_jira_tracker_deployment_type2.rb')
+
+RSpec.describe BackfillJiraTrackerDeploymentType2, :sidekiq, schema: 20201028182809 do
+ let(:services) { table(:services) }
+ let(:jira_tracker_data) { table(:jira_tracker_data) }
+ let(:migration) { described_class.new }
+ let(:batch_interval) { described_class::DELAY_INTERVAL }
+
+ describe '#up' do
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 2)
+
+ active_service = services.create!(type: 'JiraService', active: true)
+ inactive_service = services.create!(type: 'JiraService', active: false)
+
+ jira_tracker_data.create!(id: 1, service_id: active_service.id, deployment_type: 0)
+ jira_tracker_data.create!(id: 2, service_id: active_service.id, deployment_type: 1)
+ jira_tracker_data.create!(id: 3, service_id: inactive_service.id, deployment_type: 2)
+ jira_tracker_data.create!(id: 4, service_id: inactive_service.id, deployment_type: 0)
+ jira_tracker_data.create!(id: 5, service_id: active_service.id, deployment_type: 0)
+ end
+
+ it 'schedules BackfillJiraTrackerDeploymentType2 background jobs' do
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migration.up
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(batch_interval, 1, 4)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(batch_interval * 2, 5, 5)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb b/spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb
index 523c8864b63..382ce2e1da4 100644
--- a/spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb
+++ b/spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb
@@ -32,17 +32,19 @@ RSpec.describe CapDesignsFilenameLengthToNewLimit, :migration, schema: 202005281
end
it 'correctly sets filenames that are above the limit' do
- [
+ designs = [
filename_below_limit,
filename_at_limit,
filename_above_limit
- ].each(&method(:create_design))
+ ].map(&method(:create_design))
migrate!
- expect(designs.find(1).filename).to eq(filename_below_limit)
- expect(designs.find(2).filename).to eq(filename_at_limit)
- expect(designs.find(3).filename).to eq([described_class::MODIFIED_NAME, 3, described_class::MODIFIED_EXTENSION].join)
+ designs.each(&:reload)
+
+ expect(designs[0].filename).to eq(filename_below_limit)
+ expect(designs[1].filename).to eq(filename_at_limit)
+ expect(designs[2].filename).to eq([described_class::MODIFIED_NAME, designs[2].id, described_class::MODIFIED_EXTENSION].join)
end
it 'runs after filename limit has been set' do
diff --git a/spec/migrations/deduplicate_epic_iids_spec.rb b/spec/migrations/deduplicate_epic_iids_spec.rb
new file mode 100644
index 00000000000..8afb8b06948
--- /dev/null
+++ b/spec/migrations/deduplicate_epic_iids_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20201106134950_deduplicate_epic_iids.rb')
+
+RSpec.describe DeduplicateEpicIids, :migration, schema: 20201106082723 do
+ let(:routes) { table(:routes) }
+ let(:epics) { table(:epics) }
+ let(:users) { table(:users) }
+ let(:namespaces) { table(:namespaces) }
+
+ let!(:group) { create_group('foo') }
+ let!(:user) { users.create!(email: 'test@example.com', projects_limit: 100, username: 'test') }
+ let!(:dup_epic1) { epics.create!(iid: 1, title: 'epic 1', group_id: group.id, author_id: user.id, created_at: Time.now, updated_at: Time.now, title_html: 'any') }
+ let!(:dup_epic2) { epics.create!(iid: 1, title: 'epic 2', group_id: group.id, author_id: user.id, created_at: Time.now, updated_at: Time.now, title_html: 'any') }
+ let!(:dup_epic3) { epics.create!(iid: 1, title: 'epic 3', group_id: group.id, author_id: user.id, created_at: Time.now, updated_at: Time.now, title_html: 'any') }
+
+ it 'deduplicates epic iids', :aggregate_failures do
+ duplicate_epics_count = epics.where(iid: 1, group_id: group.id).count
+ expect(duplicate_epics_count).to eq 3
+
+ migrate!
+
+ duplicate_epics_count = epics.where(iid: 1, group_id: group.id).count
+ expect(duplicate_epics_count).to eq 1
+ expect(dup_epic1.reload.iid).to eq 1
+ expect(dup_epic2.reload.iid).to eq 2
+ expect(dup_epic3.reload.iid).to eq 3
+ end
+
+ def create_group(path)
+ namespaces.create!(name: path, path: path, type: 'Group').tap do |namespace|
+ routes.create!(path: namespace.path, name: namespace.name, source_id: namespace.id, source_type: 'Namespace')
+ end
+ end
+end
diff --git a/spec/migrations/generate_ci_jwt_signing_key_spec.rb b/spec/migrations/generate_ci_jwt_signing_key_spec.rb
new file mode 100644
index 00000000000..4cfaa8701aa
--- /dev/null
+++ b/spec/migrations/generate_ci_jwt_signing_key_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require Rails.root.join('db', 'migrate', '20201008013434_generate_ci_jwt_signing_key.rb')
+
+RSpec.describe GenerateCiJwtSigningKey do
+ let(:application_settings) do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = 'application_settings'
+
+ attr_encrypted :ci_jwt_signing_key, {
+ mode: :per_attribute_iv,
+ key: Rails.application.secrets.db_key_base[0..31],
+ algorithm: 'aes-256-gcm',
+ encode: true
+ }
+ end
+ end
+
+ it 'generates JWT signing key' do
+ application_settings.create!
+
+ reversible_migration do |migration|
+ migration.before -> {
+ settings = application_settings.first
+
+ expect(settings.ci_jwt_signing_key).to be_nil
+ expect(settings.encrypted_ci_jwt_signing_key).to be_nil
+ expect(settings.encrypted_ci_jwt_signing_key_iv).to be_nil
+ }
+
+ migration.after -> {
+ settings = application_settings.first
+
+ expect(settings.encrypted_ci_jwt_signing_key).to be_present
+ expect(settings.encrypted_ci_jwt_signing_key_iv).to be_present
+ expect { OpenSSL::PKey::RSA.new(settings.ci_jwt_signing_key) }.not_to raise_error
+ }
+ end
+ end
+end
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 92a49046193..699e9507f50 100644
--- a/spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb
+++ b/spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe MigrateDiscussionIdOnPromotedEpics do
end
def create_epic
- epics.create!(author_id: user.id, iid: 1,
+ epics.create!(author_id: user.id, iid: epics.maximum(:iid).to_i + 1,
group_id: namespace.id,
title: 'Epic with discussion',
title_html: 'Epic with discussion')
diff --git a/spec/migrations/rename_sitemap_namespace_spec.rb b/spec/migrations/rename_sitemap_namespace_spec.rb
new file mode 100644
index 00000000000..83f0721c600
--- /dev/null
+++ b/spec/migrations/rename_sitemap_namespace_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20201102112206_rename_sitemap_namespace.rb')
+
+RSpec.describe RenameSitemapNamespace do
+ let(:namespaces) { table(:namespaces) }
+ let(:routes) { table(:routes) }
+ let(:sitemap_path) { 'sitemap' }
+
+ it 'correctly run #up and #down' do
+ create_namespace(sitemap_path)
+
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(namespaces.pluck(:path)).to contain_exactly(sitemap_path)
+ }
+
+ migration.after -> {
+ expect(namespaces.pluck(:path)).to contain_exactly(sitemap_path + '0')
+ }
+ end
+ end
+
+ def create_namespace(path)
+ namespaces.create!(name: path, path: path).tap do |namespace|
+ routes.create!(path: namespace.path, name: namespace.name, source_id: namespace.id, source_type: 'Namespace')
+ end
+ end
+end
diff --git a/spec/migrations/rename_sitemap_root_namespaces_spec.rb b/spec/migrations/rename_sitemap_root_namespaces_spec.rb
new file mode 100644
index 00000000000..7cbf27849b0
--- /dev/null
+++ b/spec/migrations/rename_sitemap_root_namespaces_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20201019094741_rename_sitemap_root_namespaces.rb')
+
+RSpec.describe RenameSitemapRootNamespaces do
+ let(:namespaces) { table(:namespaces) }
+ let(:routes) { table(:routes) }
+ let(:sitemap_path) { 'sitemap.xml' }
+ let(:sitemap_gz_path) { 'sitemap.xml.gz' }
+ let(:other_path1) { 'sitemap.xmlfoo' }
+ let(:other_path2) { 'foositemap.xml' }
+
+ it 'correctly run #up and #down' do
+ create_namespace(sitemap_path)
+ create_namespace(sitemap_gz_path)
+ create_namespace(other_path1)
+ create_namespace(other_path2)
+
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(namespaces.pluck(:path)).to contain_exactly(sitemap_path, sitemap_gz_path, other_path1, other_path2)
+ }
+
+ migration.after -> {
+ expect(namespaces.pluck(:path)).to contain_exactly(sitemap_path + '0', sitemap_gz_path + '0', other_path1, other_path2)
+ }
+ end
+ end
+
+ def create_namespace(path)
+ namespaces.create!(name: path, path: path).tap do |namespace|
+ routes.create!(path: namespace.path, name: namespace.name, source_id: namespace.id, source_type: 'Namespace')
+ end
+ end
+end
diff --git a/spec/migrations/reseed_merge_trains_enabled_spec.rb b/spec/migrations/reseed_merge_trains_enabled_spec.rb
new file mode 100644
index 00000000000..71ef0b47da9
--- /dev/null
+++ b/spec/migrations/reseed_merge_trains_enabled_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20201112195322_reseed_merge_trains_enabled.rb')
+
+RSpec.describe ReseedMergeTrainsEnabled do
+ describe 'migrate' do
+ let(:project_ci_cd_settings) { table(:project_ci_cd_settings) }
+ let(:projects) { table(:projects) }
+ let(:namespaces) { table(:namespaces) }
+
+ context 'when on Gitlab.com' do
+ before do
+ namespace = namespaces.create!(name: 'hello', path: 'hello/')
+ project1 = projects.create!(namespace_id: namespace.id)
+ project2 = projects.create!(namespace_id: namespace.id)
+ project_ci_cd_settings.create!(project_id: project1.id, merge_pipelines_enabled: true)
+ project_ci_cd_settings.create!(project_id: project2.id, merge_pipelines_enabled: false)
+ end
+
+ it 'updates merge_trains_enabled to true for where merge_pipelines_enabled is true' do
+ expect { migrate! }.to change(project_ci_cd_settings.where(merge_trains_enabled: true), :count).by(1)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb b/spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb
new file mode 100644
index 00000000000..9cd1b98fbd7
--- /dev/null
+++ b/spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20201102073808_schedule_blocked_by_links_replacement_second_try')
+
+RSpec.describe ScheduleBlockedByLinksReplacementSecondTry do
+ let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { table(:projects).create!(namespace_id: namespace.id, name: 'gitlab') }
+ let(:issue1) { table(:issues).create!(project_id: project.id, title: 'a') }
+ let(:issue2) { table(:issues).create!(project_id: project.id, title: 'b') }
+ let(:issue3) { table(:issues).create!(project_id: project.id, title: 'c') }
+ let!(:issue_links) do
+ [
+ table(:issue_links).create!(source_id: issue1.id, target_id: issue2.id, link_type: 1),
+ table(:issue_links).create!(source_id: issue2.id, target_id: issue1.id, link_type: 2),
+ table(:issue_links).create!(source_id: issue1.id, target_id: issue3.id, link_type: 2)
+ ]
+ end
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 1)
+ end
+
+ it 'schedules jobs for blocked_by links' do
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(
+ 2.minutes, issue_links[1].id, issue_links[1].id)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(
+ 4.minutes, issue_links[2].id, issue_links[2].id)
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/schedule_blocked_by_links_replacement_spec.rb b/spec/migrations/schedule_blocked_by_links_replacement_spec.rb
deleted file mode 100644
index 36610507921..00000000000
--- a/spec/migrations/schedule_blocked_by_links_replacement_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201015073808_schedule_blocked_by_links_replacement')
-
-RSpec.describe ScheduleBlockedByLinksReplacement do
- let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
- let(:project) { table(:projects).create!(namespace_id: namespace.id, name: 'gitlab') }
- let(:issue1) { table(:issues).create!(project_id: project.id, title: 'a') }
- let(:issue2) { table(:issues).create!(project_id: project.id, title: 'b') }
- let(:issue3) { table(:issues).create!(project_id: project.id, title: 'c') }
- let!(:issue_links) do
- [
- table(:issue_links).create!(source_id: issue1.id, target_id: issue2.id, link_type: 1),
- table(:issue_links).create!(source_id: issue2.id, target_id: issue1.id, link_type: 2),
- table(:issue_links).create!(source_id: issue1.id, target_id: issue3.id, link_type: 2)
- ]
- end
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 1)
- end
-
- it 'schedules jobs for blocked_by links' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(
- 2.minutes, issue_links[1].id, issue_links[1].id)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(
- 4.minutes, issue_links[2].id, issue_links[2].id)
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb b/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb
new file mode 100644
index 00000000000..fa8dd38619a
--- /dev/null
+++ b/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe ScheduleMergeRequestCleanupSchedulesBackfill, :sidekiq, schema: 20201023114628 do
+ let(:merge_requests) { table(:merge_requests) }
+ let(:cleanup_schedules) { table(:merge_request_cleanup_schedules) }
+
+ let(:namespace) { table(:namespaces).create!(name: 'name', path: 'path') }
+ let(:project) { table(:projects).create!(namespace_id: namespace.id) }
+
+ describe '#up' do
+ let!(:open_mr) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master') }
+
+ let!(:closed_mr_1) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) }
+ let!(:closed_mr_2) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) }
+
+ let!(:merged_mr_1) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 3) }
+ let!(:merged_mr_2) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 3) }
+
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 2)
+ end
+
+ it 'schdules BackfillMergeRequestCleanupSchedules background jobs' do
+ Sidekiq::Testing.fake! do
+ migrate!
+
+ aggregate_failures do
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(2.minutes, closed_mr_1.id, closed_mr_2.id)
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(4.minutes, merged_mr_1.id, merged_mr_2.id)
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/migrations/schedule_populate_has_vulnerabilities_spec.rb b/spec/migrations/schedule_populate_has_vulnerabilities_spec.rb
new file mode 100644
index 00000000000..edae7330b1e
--- /dev/null
+++ b/spec/migrations/schedule_populate_has_vulnerabilities_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe SchedulePopulateHasVulnerabilities do
+ let(:users) { table(:users) }
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:user) { users.create!(name: 'test', email: 'test@example.com', projects_limit: 5) }
+ let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:vulnerability_base_params) { { title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, author_id: user.id } }
+ let!(:project_1) { projects.create!(namespace_id: namespace.id, name: 'foo_1') }
+ let!(:project_2) { projects.create!(namespace_id: namespace.id, name: 'foo_2') }
+ let!(:project_3) { projects.create!(namespace_id: namespace.id, name: 'foo_3') }
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 1)
+
+ vulnerabilities.create!(vulnerability_base_params.merge(project_id: project_1.id))
+ vulnerabilities.create!(vulnerability_base_params.merge(project_id: project_3.id))
+ end
+
+ it 'schedules the background jobs', :aggregate_failures do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to be(2)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(2.minutes, project_1.id)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(4.minutes, project_3.id)
+ end
+end
diff --git a/spec/migrations/schedule_populate_missing_dismissal_information_for_vulnerabilities_spec.rb b/spec/migrations/schedule_populate_missing_dismissal_information_for_vulnerabilities_spec.rb
new file mode 100644
index 00000000000..e5934f2171f
--- /dev/null
+++ b/spec/migrations/schedule_populate_missing_dismissal_information_for_vulnerabilities_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe SchedulePopulateMissingDismissalInformationForVulnerabilities do
+ let(:users) { table(:users) }
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:user) { users.create!(name: 'test', email: 'test@example.com', projects_limit: 5) }
+ let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
+
+ let!(:vulnerability_1) { vulnerabilities.create!(title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id) }
+ let!(:vulnerability_2) { vulnerabilities.create!(title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id, dismissed_at: Time.now) }
+ let!(:vulnerability_3) { vulnerabilities.create!(title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id, dismissed_by_id: user.id) }
+ let!(:vulnerability_4) { vulnerabilities.create!(title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id, dismissed_at: Time.now, dismissed_by_id: user.id) }
+ let!(:vulnerability_5) { vulnerabilities.create!(title: 'title', state: 1, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id) }
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 1)
+ end
+
+ it 'schedules the background jobs', :aggregate_failures do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to be(3)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(3.minutes, vulnerability_1.id)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(6.minutes, vulnerability_2.id)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(9.minutes, vulnerability_3.id)
+ end
+end
diff --git a/spec/migrations/seed_merge_trains_enabled_spec.rb b/spec/migrations/seed_merge_trains_enabled_spec.rb
new file mode 100644
index 00000000000..2abb064a111
--- /dev/null
+++ b/spec/migrations/seed_merge_trains_enabled_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20201026200736_seed_merge_trains_enabled.rb')
+
+RSpec.describe SeedMergeTrainsEnabled do
+ describe 'migrate' do
+ let(:project_ci_cd_settings) { table(:project_ci_cd_settings) }
+ let(:projects) { table(:projects) }
+ let(:namespaces) { table(:namespaces) }
+
+ context 'when on Gitlab.com' do
+ before do
+ namespace = namespaces.create!(name: 'hello', path: 'hello/')
+ project1 = projects.create!(namespace_id: namespace.id)
+ project2 = projects.create!(namespace_id: namespace.id)
+ project_ci_cd_settings.create!(project_id: project1.id, merge_pipelines_enabled: true)
+ project_ci_cd_settings.create!(project_id: project2.id, merge_pipelines_enabled: false)
+ end
+
+ it 'updates merge_trains_enabled to true for where merge_pipelines_enabled is true' do
+ migrate!
+
+ expect(project_ci_cd_settings.where(merge_trains_enabled: true).count).to be(1)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/update_historical_data_recorded_at_spec.rb b/spec/migrations/update_historical_data_recorded_at_spec.rb
new file mode 100644
index 00000000000..bccc711f339
--- /dev/null
+++ b/spec/migrations/update_historical_data_recorded_at_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require Rails.root.join('db', 'migrate', '20201022094846_update_historical_data_recorded_at.rb')
+
+RSpec.describe UpdateHistoricalDataRecordedAt do
+ let(:historical_data_table) { table(:historical_data) }
+
+ it 'reversibly populates recorded_at from created_at or date' do
+ row1 = historical_data_table.create!(
+ date: Date.current - 1.day,
+ created_at: Time.current - 1.day
+ )
+
+ row2 = historical_data_table.create!(date: Date.current - 2.days)
+ row2.update!(created_at: nil)
+
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(row1.reload.recorded_at).to eq(nil)
+ expect(row2.reload.recorded_at).to eq(nil)
+ }
+
+ migration.after -> {
+ expect(row1.reload.recorded_at).to eq(row1.created_at)
+ expect(row2.reload.recorded_at).to eq(row2.date.in_time_zone(Time.zone).change(hour: 12))
+ }
+ end
+ end
+end
diff --git a/spec/models/alert_management/http_integration_spec.rb b/spec/models/alert_management/http_integration_spec.rb
index 37d67dfe09a..a3e7b47c116 100644
--- a/spec/models/alert_management/http_integration_spec.rb
+++ b/spec/models/alert_management/http_integration_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe AlertManagement::HttpIntegration do
+ include ::Gitlab::Routing.url_helpers
+
let_it_be(:project) { create(:project) }
subject(:integration) { build(:alert_management_http_integration) }
@@ -15,19 +17,17 @@ RSpec.describe AlertManagement::HttpIntegration do
it { is_expected.to validate_presence_of(:project) }
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_length_of(:name).is_at_most(255) }
- it { is_expected.to validate_presence_of(:endpoint_identifier) }
- it { is_expected.to validate_length_of(:endpoint_identifier).is_at_most(255) }
context 'when active' do
# Using `create` instead of `build` the integration so `token` is set.
# Uniqueness spec saves integration with `validate: false` otherwise.
- subject { create(:alert_management_http_integration) }
+ subject { create(:alert_management_http_integration, :legacy) }
it { is_expected.to validate_uniqueness_of(:endpoint_identifier).scoped_to(:project_id, :active) }
end
context 'when inactive' do
- subject { create(:alert_management_http_integration, :inactive) }
+ subject { create(:alert_management_http_integration, :legacy, :inactive) }
it { is_expected.not_to validate_uniqueness_of(:endpoint_identifier).scoped_to(:project_id, :active) }
end
@@ -51,10 +51,6 @@ RSpec.describe AlertManagement::HttpIntegration do
context 'when unsaved' do
context 'when unassigned' do
- before do
- integration.valid?
- end
-
it_behaves_like 'valid token'
end
@@ -89,4 +85,75 @@ RSpec.describe AlertManagement::HttpIntegration do
end
end
end
+
+ describe '#endpoint_identifier' do
+ subject { integration.endpoint_identifier }
+
+ context 'when defined on initialize' do
+ let(:integration) { described_class.new }
+
+ it { is_expected.to match(/\A\h{16}\z/) }
+ end
+
+ context 'when included in initialization args' do
+ let(:integration) { described_class.new(endpoint_identifier: 'legacy') }
+
+ it { is_expected.to eq('legacy') }
+ end
+
+ context 'when reassigning' do
+ let(:integration) { create(:alert_management_http_integration) }
+ let!(:starting_identifier) { subject }
+
+ it 'does not allow reassignment' do
+ integration.endpoint_identifier = 'newValidId'
+ integration.save!
+
+ expect(integration.reload.endpoint_identifier).to eq(starting_identifier)
+ end
+ end
+ end
+
+ describe '#url' do
+ subject { integration.url }
+
+ it do
+ is_expected.to eq(
+ project_alert_http_integration_url(
+ integration.project,
+ 'datadog',
+ integration.endpoint_identifier,
+ format: :json
+ )
+ )
+ end
+
+ context 'when name is not defined' do
+ let(:integration) { described_class.new(project: project) }
+
+ it do
+ is_expected.to eq(
+ project_alert_http_integration_url(
+ integration.project,
+ 'http-endpoint',
+ integration.endpoint_identifier,
+ format: :json
+ )
+ )
+ end
+ end
+
+ context 'for a legacy integration' do
+ let(:integration) { build(:alert_management_http_integration, :legacy) }
+
+ it do
+ is_expected.to eq(
+ project_alerts_notify_url(
+ integration.project,
+ format: :json
+ )
+ )
+ end
+ end
+ end
end
diff --git a/spec/models/analytics/cycle_analytics/project_stage_spec.rb b/spec/models/analytics/cycle_analytics/project_stage_spec.rb
index 4675f037957..fce31af619c 100644
--- a/spec/models/analytics/cycle_analytics/project_stage_spec.rb
+++ b/spec/models/analytics/cycle_analytics/project_stage_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Analytics::CycleAnalytics::ProjectStage do
end
end
- it_behaves_like 'cycle analytics stage' do
+ it_behaves_like 'value stream analytics stage' do
let(:parent) { build(:project) }
let(:parent_name) { :project }
end
diff --git a/spec/models/analytics/devops_adoption/segment_selection_spec.rb b/spec/models/analytics/devops_adoption/segment_selection_spec.rb
new file mode 100644
index 00000000000..5866cbaa48e
--- /dev/null
+++ b/spec/models/analytics/devops_adoption/segment_selection_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Analytics::DevopsAdoption::SegmentSelection, type: :model do
+ subject { build(:devops_adoption_segment_selection, :project) }
+
+ describe 'validation' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project) }
+
+ it { is_expected.to validate_presence_of(:segment) }
+
+ context do
+ subject { create(:devops_adoption_segment_selection, :project, project: project) }
+
+ it { is_expected.to validate_uniqueness_of(:project_id).scoped_to(:segment_id) }
+ end
+
+ context do
+ subject { create(:devops_adoption_segment_selection, :group, group: group) }
+
+ it { is_expected.to validate_uniqueness_of(:group_id).scoped_to(:segment_id) }
+ end
+
+ it 'project is required' do
+ selection = build(:devops_adoption_segment_selection, project: nil, group: nil)
+
+ selection.validate
+
+ expect(selection.errors).to have_key(:project)
+ end
+
+ it 'project is not required when a group is given' do
+ selection = build(:devops_adoption_segment_selection, :group, group: group)
+
+ expect(selection).to be_valid
+ end
+
+ it 'does not allow group to be set when project is present' do
+ selection = build(:devops_adoption_segment_selection)
+
+ selection.group = group
+ selection.project = project
+
+ selection.validate
+
+ expect(selection.errors[:group]).to eq([s_('DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time')])
+ end
+
+ context 'limit the number of segment selections' do
+ let_it_be(:segment) { create(:devops_adoption_segment) }
+
+ subject { build(:devops_adoption_segment_selection, segment: segment, project: project) }
+
+ before do
+ create(:devops_adoption_segment_selection, :project, segment: segment)
+
+ stub_const("#{described_class}::ALLOWED_SELECTIONS_PER_SEGMENT", 1)
+ end
+
+ it 'shows validation error' do
+ subject.validate
+
+ expect(subject.errors[:segment]).to eq([s_('DevopsAdoptionSegment|The maximum number of selections has been reached')])
+ end
+ end
+ end
+end
diff --git a/spec/models/analytics/instance_statistics/measurement_spec.rb b/spec/models/analytics/instance_statistics/measurement_spec.rb
index 379272cfcb9..dbb16c5ffbe 100644
--- a/spec/models/analytics/instance_statistics/measurement_spec.rb
+++ b/spec/models/analytics/instance_statistics/measurement_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Analytics::InstanceStatistics::Measurement, type: :model do
describe 'identifiers enum' do
it 'maps to the correct values' do
- expect(described_class.identifiers).to eq({
+ identifiers = {
projects: 1,
users: 2,
issues: 3,
@@ -24,8 +24,11 @@ RSpec.describe Analytics::InstanceStatistics::Measurement, type: :model do
pipelines_succeeded: 7,
pipelines_failed: 8,
pipelines_canceled: 9,
- pipelines_skipped: 10
- }.with_indifferent_access)
+ pipelines_skipped: 10,
+ billable_users: 11
+ }
+
+ expect(described_class.identifiers).to eq(identifiers.with_indifferent_access)
end
end
@@ -45,29 +48,71 @@ RSpec.describe Analytics::InstanceStatistics::Measurement, type: :model do
it { is_expected.to match_array([measurement_1, measurement_2]) }
end
- end
- describe '#measurement_identifier_values' do
- subject { described_class.measurement_identifier_values.count }
+ describe '.recorded_after' do
+ subject { described_class.recorded_after(8.days.ago) }
- context 'when the `store_ci_pipeline_counts_by_status` feature flag is off' do
- let(:expected_count) { Analytics::InstanceStatistics::Measurement.identifiers.size - Analytics::InstanceStatistics::Measurement::EXPERIMENTAL_IDENTIFIERS.size }
+ it { is_expected.to match_array([measurement_2, measurement_3]) }
- before do
- stub_feature_flags(store_ci_pipeline_counts_by_status: false)
+ context 'when nil is given' do
+ subject { described_class.recorded_after(nil) }
+
+ it 'does not apply filtering' do
+ expect(subject).to match_array([measurement_1, measurement_2, measurement_3])
+ end
end
+ end
+
+ describe '.recorded_before' do
+ subject { described_class.recorded_before(4.days.ago) }
- it { is_expected.to eq(expected_count) }
+ it { is_expected.to match_array([measurement_1, measurement_3]) }
+
+ context 'when nil is given' do
+ subject { described_class.recorded_after(nil) }
+
+ it 'does not apply filtering' do
+ expect(subject).to match_array([measurement_1, measurement_2, measurement_3])
+ end
+ end
end
+ end
+
+ describe '.identifier_query_mapping' do
+ subject { described_class.identifier_query_mapping }
+
+ it { is_expected.to be_a Hash }
+ end
+
+ describe '.identifier_min_max_queries' do
+ subject { described_class.identifier_min_max_queries }
+
+ it { is_expected.to be_a Hash }
+ end
+
+ describe '.measurement_identifier_values' do
+ let(:expected_count) { described_class.identifiers.size }
+
+ subject { described_class.measurement_identifier_values.count }
+
+ it { is_expected.to eq(expected_count) }
+ end
- context 'when the `store_ci_pipeline_counts_by_status` feature flag is on' do
- let(:expected_count) { Analytics::InstanceStatistics::Measurement.identifiers.size }
+ describe '.find_latest_or_fallback' do
+ subject(:count) { described_class.find_latest_or_fallback(:pipelines_skipped).count }
- before do
- stub_feature_flags(store_ci_pipeline_counts_by_status: true)
+ context 'with instance statistics' do
+ let!(:measurement) { create(:instance_statistics_measurement, :pipelines_skipped_count) }
+
+ it 'returns the latest stored measurement' do
+ expect(count).to eq measurement.count
end
+ end
- it { is_expected.to eq(expected_count) }
+ context 'without instance statistics' do
+ it 'returns the realtime query of the measurement' do
+ expect(count).to eq 0
+ end
end
end
end
diff --git a/spec/models/application_record_spec.rb b/spec/models/application_record_spec.rb
index d080b298e2f..6a0f2290b4c 100644
--- a/spec/models/application_record_spec.rb
+++ b/spec/models/application_record_spec.rb
@@ -67,7 +67,8 @@ RSpec.describe ApplicationRecord do
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)
+ expect { Suggestion.safe_find_or_create_by!(note: nil) }
+ .to raise_error(ActiveRecord::RecordInvalid)
end
it 'passes a block to find_or_create_by' do
@@ -75,6 +76,14 @@ RSpec.describe ApplicationRecord do
Suggestion.safe_find_or_create_by!(suggestion_attributes, &block)
end.to yield_with_args(an_object_having_attributes(suggestion_attributes))
end
+
+ it 'raises a record not found error in case of attributes mismatch' do
+ suggestion = Suggestion.safe_find_or_create_by!(suggestion_attributes)
+ attributes = suggestion_attributes.merge(outdated: !suggestion.outdated)
+
+ expect { Suggestion.safe_find_or_create_by!(attributes) }
+ .to raise_error(ActiveRecord::RecordNotFound)
+ end
end
end
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index fb702d10a42..efe62a1d086 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -72,6 +72,7 @@ RSpec.describe ApplicationSetting do
it { is_expected.not_to allow_value(nil).for(:push_event_activities_limit) }
it { is_expected.to validate_numericality_of(:container_registry_delete_tags_service_timeout).only_integer.is_greater_than_or_equal_to(0) }
+ it { is_expected.to validate_numericality_of(:container_registry_expiration_policies_worker_capacity).only_integer.is_greater_than_or_equal_to(0) }
it { is_expected.to validate_numericality_of(:snippet_size_limit).only_integer.is_greater_than(0) }
it { is_expected.to validate_numericality_of(:wiki_page_max_content_bytes).only_integer.is_greater_than_or_equal_to(1024) }
@@ -647,6 +648,37 @@ RSpec.describe ApplicationSetting do
end
end
end
+
+ describe '#ci_jwt_signing_key' do
+ it { is_expected.not_to allow_value('').for(:ci_jwt_signing_key) }
+ it { is_expected.not_to allow_value('invalid RSA key').for(:ci_jwt_signing_key) }
+ it { is_expected.to allow_value(nil).for(:ci_jwt_signing_key) }
+ it { is_expected.to allow_value(OpenSSL::PKey::RSA.new(1024).to_pem).for(:ci_jwt_signing_key) }
+
+ it 'is encrypted' do
+ subject.ci_jwt_signing_key = OpenSSL::PKey::RSA.new(1024).to_pem
+
+ aggregate_failures do
+ expect(subject.encrypted_ci_jwt_signing_key).to be_present
+ expect(subject.encrypted_ci_jwt_signing_key_iv).to be_present
+ expect(subject.encrypted_ci_jwt_signing_key).not_to eq(subject.ci_jwt_signing_key)
+ end
+ end
+ end
+
+ describe '#cloud_license_auth_token' do
+ it { is_expected.to allow_value(nil).for(:cloud_license_auth_token) }
+
+ it 'is encrypted' do
+ subject.cloud_license_auth_token = 'token-from-customers-dot'
+
+ aggregate_failures do
+ expect(subject.encrypted_cloud_license_auth_token).to be_present
+ expect(subject.encrypted_cloud_license_auth_token_iv).to be_present
+ expect(subject.encrypted_cloud_license_auth_token).not_to eq(subject.cloud_license_auth_token)
+ end
+ end
+ end
end
context 'static objects external storage' do
diff --git a/spec/models/authentication_event_spec.rb b/spec/models/authentication_event_spec.rb
index 483d45c08be..83598fa6765 100644
--- a/spec/models/authentication_event_spec.rb
+++ b/spec/models/authentication_event_spec.rb
@@ -37,15 +37,11 @@ RSpec.describe AuthenticationEvent do
describe '.providers' do
before do
- create(:authentication_event, provider: :ldapmain)
- create(:authentication_event, provider: :google_oauth2)
- create(:authentication_event, provider: :standard)
- create(:authentication_event, provider: :standard)
- create(:authentication_event, provider: :standard)
+ allow(Devise).to receive(:omniauth_providers).and_return(%w(ldapmain google_oauth2))
end
it 'returns an array of distinct providers' do
- expect(described_class.providers).to match_array %w(ldapmain google_oauth2 standard)
+ expect(described_class.providers).to match_array %w(ldapmain google_oauth2 standard two-factor two-factor-via-u2f-device two-factor-via-webauthn-device)
end
end
end
diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb
index fc463c6af52..c4d17905637 100644
--- a/spec/models/broadcast_message_spec.rb
+++ b/spec/models/broadcast_message_spec.rb
@@ -161,6 +161,12 @@ RSpec.describe BroadcastMessage do
expect(subject.call('/group/issues/test').length).to eq(1)
end
+
+ it "does not return message if the target path is set but no current path is provided" do
+ create(:broadcast_message, target_path: "*/issues/*", broadcast_type: broadcast_type)
+
+ expect(subject.call.length).to eq(0)
+ end
end
describe '.current', :use_clean_rails_memory_store_caching do
diff --git a/spec/models/bulk_imports/tracker_spec.rb b/spec/models/bulk_imports/tracker_spec.rb
new file mode 100644
index 00000000000..8eb5a6c27dd
--- /dev/null
+++ b/spec/models/bulk_imports/tracker_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Tracker, type: :model do
+ describe 'associations' do
+ it { is_expected.to belong_to(:entity).required }
+ end
+
+ describe 'validations' do
+ before do
+ create(:bulk_import_tracker)
+ end
+
+ it { is_expected.to validate_presence_of(:relation) }
+ it { is_expected.to validate_uniqueness_of(:relation).scoped_to(:bulk_import_entity_id) }
+
+ context 'when has_next_page is true' do
+ it "validates presence of `next_page`" do
+ tracker = build(:bulk_import_tracker, has_next_page: true)
+
+ expect(tracker).not_to be_valid
+ expect(tracker.errors).to include(:next_page)
+ end
+ end
+ end
+end
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index c464e176c17..51e82061d97 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -55,6 +55,17 @@ RSpec.describe Ci::Bridge do
expect(bridge.scoped_variables_hash.keys).to include(*variables)
end
+
+ context 'when bridge has dependency which has dotenv variable' do
+ let(:test) { create(:ci_build, pipeline: pipeline, stage_idx: 0) }
+ let(:bridge) { create(:ci_bridge, pipeline: pipeline, stage_idx: 1, options: { dependencies: [test.name] }) }
+
+ let!(:job_variable) { create(:ci_job_variable, :dotenv_source, job: test) }
+
+ it 'includes inherited variable' do
+ expect(bridge.scoped_variables_hash).to include(job_variable.key => job_variable.value)
+ end
+ end
end
describe 'state machine transitions' do
@@ -357,4 +368,53 @@ RSpec.describe Ci::Bridge do
it { is_expected.to be_falsey }
end
end
+
+ describe '#dependency_variables' do
+ subject { bridge.dependency_variables }
+
+ shared_context 'when ci_bridge_dependency_variables is disabled' do
+ before do
+ stub_feature_flags(ci_bridge_dependency_variables: false)
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'when downloading from previous stages' do
+ let!(:prepare1) { create(:ci_build, name: 'prepare1', pipeline: pipeline, stage_idx: 0) }
+ let!(:bridge) { create(:ci_bridge, pipeline: pipeline, stage_idx: 1) }
+
+ let!(:job_variable_1) { create(:ci_job_variable, :dotenv_source, job: prepare1) }
+ let!(:job_variable_2) { create(:ci_job_variable, job: prepare1) }
+
+ it 'inherits only dependent variables' do
+ expect(subject.to_hash).to eq(job_variable_1.key => job_variable_1.value)
+ end
+
+ it_behaves_like 'when ci_bridge_dependency_variables is disabled'
+ end
+
+ context 'when using needs' do
+ let!(:prepare1) { create(:ci_build, name: 'prepare1', pipeline: pipeline, stage_idx: 0) }
+ let!(:prepare2) { create(:ci_build, name: 'prepare2', pipeline: pipeline, stage_idx: 0) }
+ let!(:prepare3) { create(:ci_build, name: 'prepare3', pipeline: pipeline, stage_idx: 0) }
+ let!(:bridge) do
+ create(:ci_bridge, pipeline: pipeline,
+ stage_idx: 1,
+ scheduling_type: 'dag',
+ needs_attributes: [{ name: 'prepare1', artifacts: true },
+ { name: 'prepare2', artifacts: false }])
+ end
+
+ let!(:job_variable_1) { create(:ci_job_variable, :dotenv_source, job: prepare1) }
+ let!(:job_variable_2) { create(:ci_job_variable, :dotenv_source, job: prepare2) }
+ let!(:job_variable_3) { create(:ci_job_variable, :dotenv_source, job: prepare3) }
+
+ it 'inherits only needs with artifacts variables' do
+ expect(subject.to_hash).to eq(job_variable_1.key => job_variable_1.value)
+ end
+
+ it_behaves_like 'when ci_bridge_dependency_variables is disabled'
+ end
+ end
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index f1d51324bbf..5ff9b4dd493 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -2464,7 +2464,7 @@ RSpec.describe Ci::Build do
end
before do
- allow(Gitlab::Ci::Jwt).to receive(:for_build).with(build).and_return('ci.job.jwt')
+ allow(Gitlab::Ci::Jwt).to receive(:for_build).and_return('ci.job.jwt')
build.set_token('my-token')
build.yaml_variables = []
end
@@ -2482,12 +2482,17 @@ RSpec.describe Ci::Build do
end
context 'when CI_JOB_JWT generation fails' do
- it 'CI_JOB_JWT is not included' do
- expect(Gitlab::Ci::Jwt).to receive(:for_build).and_raise(OpenSSL::PKey::RSAError, 'Neither PUB key nor PRIV key: not enough data')
- expect(Gitlab::ErrorTracking).to receive(:track_exception)
-
- expect { subject }.not_to raise_error
- expect(subject.pluck(:key)).not_to include('CI_JOB_JWT')
+ [
+ OpenSSL::PKey::RSAError,
+ Gitlab::Ci::Jwt::NoSigningKeyError
+ ].each do |reason_to_fail|
+ it 'CI_JOB_JWT is not included' do
+ expect(Gitlab::Ci::Jwt).to receive(:for_build).and_raise(reason_to_fail)
+ expect(Gitlab::ErrorTracking).to receive(:track_exception)
+
+ expect { subject }.not_to raise_error
+ expect(subject.pluck(:key)).not_to include('CI_JOB_JWT')
+ end
end
end
diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb
index 871f279db08..dce7b1d30ca 100644
--- a/spec/models/ci/build_trace_chunk_spec.rb
+++ b/spec/models/ci/build_trace_chunk_spec.rb
@@ -100,15 +100,15 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
subject { described_class.all_stores }
it 'returns a correctly ordered array' do
- is_expected.to eq(%w[redis database fog])
+ is_expected.to eq(%i[redis database fog])
end
it 'returns redis store as the lowest precedence' do
- expect(subject.first).to eq('redis')
+ expect(subject.first).to eq(:redis)
end
it 'returns fog store as the highest precedence' do
- expect(subject.last).to eq('fog')
+ expect(subject.last).to eq(:fog)
end
end
@@ -135,32 +135,40 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
context 'when data_store is fog' do
let(:data_store) { :fog }
- context 'when legacy Fog is enabled' do
- before do
- stub_feature_flags(ci_trace_new_fog_store: false)
- build_trace_chunk.send(:unsafe_set_data!, +'Sample data in fog')
- end
+ before do
+ build_trace_chunk.send(:unsafe_set_data!, +'Sample data in fog')
+ end
- it { is_expected.to eq('Sample data in fog') }
+ it { is_expected.to eq('Sample data in fog') }
- it 'returns a LegacyFog store' do
- expect(described_class.get_store_class(data_store)).to be_a(Ci::BuildTraceChunks::LegacyFog)
- end
+ it 'returns a new Fog store' do
+ expect(described_class.get_store_class(data_store)).to be_a(Ci::BuildTraceChunks::Fog)
end
+ end
+ end
- context 'when new Fog is enabled' do
- before do
- stub_feature_flags(ci_trace_new_fog_store: true)
- build_trace_chunk.send(:unsafe_set_data!, +'Sample data in fog')
- end
+ describe '#get_store_class' do
+ using RSpec::Parameterized::TableSyntax
- it { is_expected.to eq('Sample data in fog') }
+ where(:data_store, :expected_store) do
+ :redis | Ci::BuildTraceChunks::Redis
+ :database | Ci::BuildTraceChunks::Database
+ :fog | Ci::BuildTraceChunks::Fog
+ end
- it 'returns a new Fog store' do
- expect(described_class.get_store_class(data_store)).to be_a(Ci::BuildTraceChunks::Fog)
+ with_them do
+ context "with store" do
+ it 'returns an instance of the right class' do
+ expect(expected_store).to receive(:new).twice.and_call_original
+ expect(described_class.get_store_class(data_store.to_s)).to be_a(expected_store)
+ expect(described_class.get_store_class(data_store.to_sym)).to be_a(expected_store)
end
end
end
+
+ it 'raises an error' do
+ expect { described_class.get_store_class('unknown') }.to raise_error('Unknown store type: unknown')
+ end
end
describe '#append' do
@@ -614,23 +622,19 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
context 'when the chunk is being locked by a different worker' do
let(:metrics) { spy('metrics') }
- it 'does not raise an exception' do
- lock_chunk do
- expect { build_trace_chunk.persist_data! }.not_to raise_error
- end
- end
-
it 'increments stalled chunk trace metric' do
allow(build_trace_chunk)
.to receive(:metrics)
.and_return(metrics)
- lock_chunk { build_trace_chunk.persist_data! }
+ expect do
+ subject
- expect(metrics)
- .to have_received(:increment_trace_operation)
- .with(operation: :stalled)
- .once
+ expect(metrics)
+ .to have_received(:increment_trace_operation)
+ .with(operation: :stalled)
+ .once
+ end.to raise_error(described_class::FailedToPersistDataError)
end
def lock_chunk(&block)
diff --git a/spec/models/ci/build_trace_chunks/legacy_fog_spec.rb b/spec/models/ci/build_trace_chunks/legacy_fog_spec.rb
deleted file mode 100644
index ca4b414b992..00000000000
--- a/spec/models/ci/build_trace_chunks/legacy_fog_spec.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::BuildTraceChunks::LegacyFog do
- let(:data_store) { described_class.new }
-
- before do
- stub_artifacts_object_storage
- end
-
- describe '#available?' do
- subject { data_store.available? }
-
- context 'when object storage is enabled' do
- it { is_expected.to be_truthy }
- end
-
- context 'when object storage is disabled' do
- before do
- stub_artifacts_object_storage(enabled: false)
- end
-
- it { is_expected.to be_falsy }
- end
- end
-
- describe '#data' do
- subject { data_store.data(model) }
-
- context 'when data exists' do
- let(:model) { create(:ci_build_trace_chunk, :fog_with_data, initial_data: 'sample data in fog') }
-
- it 'returns the data' do
- is_expected.to eq('sample data in fog')
- end
- end
-
- context 'when data does not exist' do
- let(:model) { create(:ci_build_trace_chunk, :fog_without_data) }
-
- it 'returns nil' do
- expect(data_store.data(model)).to be_nil
- end
- end
- end
-
- describe '#set_data' do
- 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') }
-
- it 'overwrites data' do
- expect(data_store.data(model)).to eq('sample data in fog')
-
- data_store.set_data(model, new_data)
-
- expect(data_store.data(model)).to eq new_data
- end
- end
-
- context 'when data does not exist' do
- let(:model) { create(:ci_build_trace_chunk, :fog_without_data) }
-
- it 'sets new data' do
- expect(data_store.data(model)).to be_nil
-
- data_store.set_data(model, new_data)
-
- expect(data_store.data(model)).to eq new_data
- end
- end
- end
-
- describe '#delete_data' do
- subject { data_store.delete_data(model) }
-
- context 'when data exists' do
- let(:model) { create(:ci_build_trace_chunk, :fog_with_data, initial_data: 'sample data in fog') }
-
- it 'deletes data' do
- expect(data_store.data(model)).to eq('sample data in fog')
-
- subject
-
- expect(data_store.data(model)).to be_nil
- end
- end
-
- context 'when data does not exist' do
- let(:model) { create(:ci_build_trace_chunk, :fog_without_data) }
-
- it 'does nothing' do
- expect(data_store.data(model)).to be_nil
-
- subject
-
- expect(data_store.data(model)).to be_nil
- end
- end
- end
-
- describe '#size' do
- context 'when data exists' do
- let(:model) { create(:ci_build_trace_chunk, :fog_with_data, initial_data: 'üabcd') }
-
- it 'returns data bytesize correctly' do
- expect(data_store.size(model)).to eq 6
- end
- end
-
- context 'when data does not exist' do
- let(:model) { create(:ci_build_trace_chunk, :fog_without_data) }
-
- it 'returns zero' do
- expect(data_store.size(model)).to be_zero
- end
- end
- end
-
- describe '#keys' do
- subject { data_store.keys(relation) }
-
- let(:build) { create(:ci_build) }
- let(:relation) { build.trace_chunks }
-
- before do
- create(:ci_build_trace_chunk, :fog_with_data, chunk_index: 0, build: build)
- create(:ci_build_trace_chunk, :fog_with_data, chunk_index: 1, build: build)
- end
-
- it 'returns keys' do
- is_expected.to eq([[build.id, 0], [build.id, 1]])
- end
- end
-
- describe '#delete_keys' do
- subject { data_store.delete_keys(keys) }
-
- let(:build) { create(:ci_build) }
- let(:relation) { build.trace_chunks }
- let(:keys) { data_store.keys(relation) }
-
- before do
- create(:ci_build_trace_chunk, :fog_with_data, chunk_index: 0, build: build)
- create(:ci_build_trace_chunk, :fog_with_data, chunk_index: 1, build: build)
- end
-
- it 'deletes multiple data' do
- ::Fog::Storage.new(JobArtifactUploader.object_store_credentials).tap do |connection|
- expect(connection.get_object('artifacts', "tmp/builds/#{build.id}/chunks/0.log")[:body]).to be_present
- expect(connection.get_object('artifacts', "tmp/builds/#{build.id}/chunks/1.log")[:body]).to be_present
- end
-
- subject
-
- ::Fog::Storage.new(JobArtifactUploader.object_store_credentials).tap do |connection|
- expect { connection.get_object('artifacts', "tmp/builds/#{build.id}/chunks/0.log")[:body] }.to raise_error(Excon::Error::NotFound)
- expect { connection.get_object('artifacts', "tmp/builds/#{build.id}/chunks/1.log")[:body] }.to raise_error(Excon::Error::NotFound)
- end
- end
- end
-end
diff --git a/spec/models/ci/daily_build_group_report_result_spec.rb b/spec/models/ci/daily_build_group_report_result_spec.rb
index 326366666cb..f16396d62c9 100644
--- a/spec/models/ci/daily_build_group_report_result_spec.rb
+++ b/spec/models/ci/daily_build_group_report_result_spec.rb
@@ -81,4 +81,81 @@ RSpec.describe Ci::DailyBuildGroupReportResult do
end
end
end
+
+ describe 'scopes' do
+ let_it_be(:project) { create(:project) }
+ let(:recent_build_group_report_result) { create(:ci_daily_build_group_report_result, project: project) }
+ let(:old_build_group_report_result) do
+ create(:ci_daily_build_group_report_result, date: 1.week.ago, project: project)
+ end
+
+ describe '.by_projects' do
+ subject { described_class.by_projects([project.id]) }
+
+ it 'returns records by projects' do
+ expect(subject).to contain_exactly(recent_build_group_report_result, old_build_group_report_result)
+ end
+ end
+
+ describe '.with_coverage' do
+ subject { described_class.with_coverage }
+
+ it 'returns data with coverage' do
+ expect(subject).to contain_exactly(recent_build_group_report_result, old_build_group_report_result)
+ end
+ end
+
+ describe '.with_default_branch' do
+ subject(:coverages) { described_class.with_default_branch }
+
+ context 'when coverage for the default branch exist' do
+ let!(:recent_build_group_report_result) { create(:ci_daily_build_group_report_result, project: project) }
+ let!(:coverage_feature_branch) { create(:ci_daily_build_group_report_result, :on_feature_branch, project: project) }
+
+ it 'returns coverage with the default branch' do
+ expect(coverages).to contain_exactly(recent_build_group_report_result)
+ end
+ end
+
+ context 'when coverage for the default branch does not exist' do
+ it 'returns an empty collection' do
+ expect(coverages).to be_empty
+ end
+ end
+ end
+
+ describe '.by_date' do
+ subject(:coverages) { described_class.by_date(start_date) }
+
+ let!(:coverage_1) { create(:ci_daily_build_group_report_result, date: 1.week.ago) }
+
+ context 'when project has several coverage' do
+ let!(:coverage_2) { create(:ci_daily_build_group_report_result, date: 2.weeks.ago) }
+ let(:start_date) { 1.week.ago.to_date.to_s }
+
+ it 'returns the coverage from the start_date' do
+ expect(coverages).to contain_exactly(coverage_1)
+ end
+ end
+
+ context 'when start_date is over 90 days' do
+ let!(:coverage_2) { create(:ci_daily_build_group_report_result, date: 90.days.ago) }
+ let!(:coverage_3) { create(:ci_daily_build_group_report_result, date: 91.days.ago) }
+ let(:start_date) { 1.year.ago.to_date.to_s }
+
+ it 'returns the coverage in the last 90 days' do
+ expect(coverages).to contain_exactly(coverage_1, coverage_2)
+ end
+ end
+
+ context 'when start_date is not a string' do
+ let!(:coverage_2) { create(:ci_daily_build_group_report_result, date: 90.days.ago) }
+ let(:start_date) { 1.week.ago }
+
+ it 'returns the coverage in the last 90 days' do
+ expect(coverages).to contain_exactly(coverage_1, coverage_2)
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 88d08f1ec45..1ca370dc950 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -625,7 +625,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
- describe "coverage" do
+ describe '#coverage' do
let(:project) { create(:project, build_coverage_regex: "/.*/") }
let(:pipeline) { create(:ci_empty_pipeline, project: project) }
@@ -1972,6 +1972,32 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
+ describe '.latest_running_for_ref' do
+ include_context 'with some outdated pipelines'
+
+ let!(:latest_running_pipeline) do
+ create_pipeline(:running, 'ref', 'D', project)
+ end
+
+ it 'returns the latest running pipeline' do
+ expect(described_class.latest_running_for_ref('ref'))
+ .to eq(latest_running_pipeline)
+ end
+ end
+
+ describe '.latest_failed_for_ref' do
+ include_context 'with some outdated pipelines'
+
+ let!(:latest_failed_pipeline) do
+ create_pipeline(:failed, 'ref', 'D', project)
+ end
+
+ it 'returns the latest failed pipeline' do
+ expect(described_class.latest_failed_for_ref('ref'))
+ .to eq(latest_failed_pipeline)
+ end
+ end
+
describe '.latest_successful_for_sha' do
include_context 'with some outdated pipelines'
diff --git a/spec/models/ci/test_case_failure_spec.rb b/spec/models/ci/test_case_failure_spec.rb
new file mode 100644
index 00000000000..34f89b663ed
--- /dev/null
+++ b/spec/models/ci/test_case_failure_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::TestCaseFailure do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:build) }
+ it { is_expected.to belong_to(:test_case) }
+ end
+
+ describe 'validations' do
+ subject { build(:ci_test_case_failure) }
+
+ it { is_expected.to validate_presence_of(:test_case) }
+ it { is_expected.to validate_presence_of(:build) }
+ it { is_expected.to validate_presence_of(:failed_at) }
+ end
+
+ describe '.recent_failures_count' do
+ let_it_be(:project) { create(:project) }
+
+ subject(:recent_failures) do
+ described_class.recent_failures_count(
+ project: project,
+ test_case_keys: test_case_keys
+ )
+ end
+
+ context 'when test case failures are within the date range and are for the test case keys' do
+ let(:tc_1) { create(:ci_test_case, project: project) }
+ let(:tc_2) { create(:ci_test_case, project: project) }
+ let(:test_case_keys) { [tc_1.key_hash, tc_2.key_hash] }
+
+ before do
+ create_list(:ci_test_case_failure, 3, test_case: tc_1, failed_at: 1.day.ago)
+ create_list(:ci_test_case_failure, 2, test_case: tc_2, failed_at: 3.days.ago)
+ end
+
+ it 'returns the number of failures for each test case key hash for the past 14 days by default' do
+ expect(recent_failures).to eq(
+ tc_1.key_hash => 3,
+ tc_2.key_hash => 2
+ )
+ end
+ end
+
+ context 'when test case failures are within the date range but are not for the test case keys' do
+ let(:tc) { create(:ci_test_case, project: project) }
+ let(:test_case_keys) { ['some-other-key-hash'] }
+
+ before do
+ create(:ci_test_case_failure, test_case: tc, failed_at: 1.day.ago)
+ end
+
+ it 'excludes them from the count' do
+ expect(recent_failures[tc.key_hash]).to be_nil
+ end
+ end
+
+ context 'when test case failures are not within the date range but are for the test case keys' do
+ let(:tc) { create(:ci_test_case, project: project) }
+ let(:test_case_keys) { [tc.key_hash] }
+
+ before do
+ create(:ci_test_case_failure, test_case: tc, failed_at: 15.days.ago)
+ end
+
+ it 'excludes them from the count' do
+ expect(recent_failures[tc.key_hash]).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/models/ci/test_case_spec.rb b/spec/models/ci/test_case_spec.rb
new file mode 100644
index 00000000000..45311e285a6
--- /dev/null
+++ b/spec/models/ci/test_case_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::TestCase do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:project) }
+ it { is_expected.to have_many(:test_case_failures) }
+ end
+
+ describe 'validations' do
+ subject { build(:ci_test_case) }
+
+ it { is_expected.to validate_presence_of(:project) }
+ it { is_expected.to validate_presence_of(:key_hash) }
+ end
+
+ describe '.find_or_create_by_batch' do
+ it 'finds or creates records for the given test case keys', :aggregate_failures do
+ project = create(:project)
+ existing_tc = create(:ci_test_case, project: project)
+ new_key = Digest::SHA256.hexdigest(SecureRandom.hex)
+ keys = [existing_tc.key_hash, new_key]
+
+ result = described_class.find_or_create_by_batch(project, keys)
+
+ expect(result.map(&:key_hash)).to match_array([existing_tc.key_hash, new_key])
+ expect(result).to all(be_persisted)
+ end
+ end
+end
diff --git a/spec/models/clusters/agent_token_spec.rb b/spec/models/clusters/agent_token_spec.rb
index ad9dd11b24e..9110fdeda52 100644
--- a/spec/models/clusters/agent_token_spec.rb
+++ b/spec/models/clusters/agent_token_spec.rb
@@ -14,5 +14,10 @@ RSpec.describe Clusters::AgentToken do
expect(agent_token.token).to be_present
end
+
+ it 'is at least 50 characters' do
+ agent_token = create(:cluster_agent_token)
+ expect(agent_token.token.length).to be >= 50
+ end
end
end
diff --git a/spec/models/clusters/applications/cert_manager_spec.rb b/spec/models/clusters/applications/cert_manager_spec.rb
index 7ca7f533a27..3044260a000 100644
--- a/spec/models/clusters/applications/cert_manager_spec.rb
+++ b/spec/models/clusters/applications/cert_manager_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe Clusters::Applications::CertManager do
subject { cert_manager.install_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with cert_manager arguments' do
expect(subject.name).to eq('certmanager')
@@ -90,7 +90,7 @@ RSpec.describe Clusters::Applications::CertManager do
describe '#uninstall_command' do
subject { cert_manager.uninstall_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::DeleteCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand) }
it 'is initialized with cert_manager arguments' do
expect(subject.name).to eq('certmanager')
diff --git a/spec/models/clusters/applications/crossplane_spec.rb b/spec/models/clusters/applications/crossplane_spec.rb
index a41c5f6586b..7082576028b 100644
--- a/spec/models/clusters/applications/crossplane_spec.rb
+++ b/spec/models/clusters/applications/crossplane_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Clusters::Applications::Crossplane do
subject { crossplane.install_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with crossplane arguments' do
expect(subject.name).to eq('crossplane')
diff --git a/spec/models/clusters/applications/elastic_stack_spec.rb b/spec/models/clusters/applications/elastic_stack_spec.rb
index 62123ffa542..74cacd486b0 100644
--- a/spec/models/clusters/applications/elastic_stack_spec.rb
+++ b/spec/models/clusters/applications/elastic_stack_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Clusters::Applications::ElasticStack do
subject { elastic_stack.install_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with elastic stack arguments' do
expect(subject.name).to eq('elastic-stack')
@@ -57,7 +57,7 @@ RSpec.describe Clusters::Applications::ElasticStack do
it 'includes a preinstall script' do
expect(subject.preinstall).not_to be_empty
- expect(subject.preinstall.first).to include("delete")
+ expect(subject.preinstall.first).to include("helm uninstall")
end
end
@@ -69,7 +69,7 @@ RSpec.describe Clusters::Applications::ElasticStack do
it 'includes a preinstall script' do
expect(subject.preinstall).not_to be_empty
- expect(subject.preinstall.first).to include("delete")
+ expect(subject.preinstall.first).to include("helm uninstall")
end
end
@@ -123,7 +123,7 @@ RSpec.describe Clusters::Applications::ElasticStack do
subject { elastic_stack.uninstall_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::DeleteCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand) }
it 'is initialized with elastic stack arguments' do
expect(subject.name).to eq('elastic-stack')
diff --git a/spec/models/clusters/applications/fluentd_spec.rb b/spec/models/clusters/applications/fluentd_spec.rb
index 3bda3e99ec1..ccdf6b0e40d 100644
--- a/spec/models/clusters/applications/fluentd_spec.rb
+++ b/spec/models/clusters/applications/fluentd_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Clusters::Applications::Fluentd do
describe '#install_command' do
subject { fluentd.install_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with fluentd arguments' do
expect(subject.name).to eq('fluentd')
diff --git a/spec/models/clusters/applications/helm_spec.rb b/spec/models/clusters/applications/helm_spec.rb
index 6d2ecaa6d47..ad1ebd4966a 100644
--- a/spec/models/clusters/applications/helm_spec.rb
+++ b/spec/models/clusters/applications/helm_spec.rb
@@ -56,7 +56,7 @@ RSpec.describe Clusters::Applications::Helm do
subject { application.issue_client_cert }
it 'returns a new cert' do
- is_expected.to be_kind_of(Gitlab::Kubernetes::Helm::Certificate)
+ is_expected.to be_kind_of(Gitlab::Kubernetes::Helm::V2::Certificate)
expect(subject.cert_string).not_to eq(application.ca_cert)
expect(subject.key_string).not_to eq(application.ca_key)
end
@@ -67,7 +67,7 @@ RSpec.describe Clusters::Applications::Helm do
subject { helm.install_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InitCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V2::InitCommand) }
it 'is initialized with 1 arguments' do
expect(subject.name).to eq('helm')
@@ -104,7 +104,7 @@ RSpec.describe Clusters::Applications::Helm do
subject { helm.uninstall_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::ResetCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V2::ResetCommand) }
it 'has name' do
expect(subject.name).to eq('helm')
diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb
index 196d57aff7b..1bc1a4343aa 100644
--- a/spec/models/clusters/applications/ingress_spec.rb
+++ b/spec/models/clusters/applications/ingress_spec.rb
@@ -131,7 +131,7 @@ RSpec.describe Clusters::Applications::Ingress do
describe '#install_command' do
subject { ingress.install_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with ingress arguments' do
expect(subject.name).to eq('ingress')
diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb
index 3cf24f1a9ef..e7de2d24334 100644
--- a/spec/models/clusters/applications/jupyter_spec.rb
+++ b/spec/models/clusters/applications/jupyter_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe Clusters::Applications::Jupyter do
subject { jupyter.install_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with 4 arguments' do
expect(subject.name).to eq('jupyter')
diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb
index b14161ce8e6..41b4ec86233 100644
--- a/spec/models/clusters/applications/knative_spec.rb
+++ b/spec/models/clusters/applications/knative_spec.rb
@@ -119,7 +119,7 @@ RSpec.describe Clusters::Applications::Knative do
shared_examples 'a command' do
it 'is an instance of Helm::InstallCommand' do
- expect(subject).to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand)
+ expect(subject).to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand)
end
it 'is initialized with knative arguments' do
@@ -171,7 +171,7 @@ RSpec.describe Clusters::Applications::Knative do
describe '#uninstall_command' do
subject { knative.uninstall_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::DeleteCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand) }
it "removes knative deployed services before uninstallation" do
2.times do |i|
diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb
index b450900bee6..032de6aa7c2 100644
--- a/spec/models/clusters/applications/prometheus_spec.rb
+++ b/spec/models/clusters/applications/prometheus_spec.rb
@@ -148,7 +148,7 @@ RSpec.describe Clusters::Applications::Prometheus do
subject { prometheus.install_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with 3 arguments' do
expect(subject.name).to eq('prometheus')
@@ -195,7 +195,7 @@ RSpec.describe Clusters::Applications::Prometheus do
subject { prometheus.uninstall_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::DeleteCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand) }
it 'has the application name' do
expect(subject.name).to eq('prometheus')
@@ -236,7 +236,7 @@ RSpec.describe Clusters::Applications::Prometheus do
let(:prometheus) { build(:clusters_applications_prometheus) }
let(:values) { prometheus.values }
- it { is_expected.to be_an_instance_of(::Gitlab::Kubernetes::Helm::PatchCommand) }
+ it { is_expected.to be_an_instance_of(::Gitlab::Kubernetes::Helm::V3::PatchCommand) }
it 'is initialized with 3 arguments' do
expect(patch_command.name).to eq('prometheus')
diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb
index ef916c73e0b..43e2eab3b9d 100644
--- a/spec/models/clusters/applications/runner_spec.rb
+++ b/spec/models/clusters/applications/runner_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Clusters::Applications::Runner do
subject { gitlab_runner.install_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with 4 arguments' do
expect(subject.name).to eq('runner')
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index dd9b96f39ad..ed74a841044 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -540,6 +540,27 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
end
end
+
+ describe 'helm_major_version can only be 2 or 3' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:helm_major_version, :expect_valid) do
+ 2 | true
+ 3 | true
+ 4 | false
+ -1 | false
+ end
+
+ with_them do
+ let(:cluster) { build(:cluster, helm_major_version: helm_major_version) }
+
+ it { is_expected.to eq(expect_valid) }
+ end
+ end
+ end
+
+ it 'has default helm_major_version 3' do
+ expect(create(:cluster).helm_major_version).to eq(3)
end
describe '.ancestor_clusters_for_clusterable' do
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 877188097fd..9824eb91bc7 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -493,104 +493,49 @@ RSpec.describe CommitStatus do
end
end
- context 'with the one_dimensional_matrix feature flag disabled' do
- describe '#group_name' do
- before do
- stub_feature_flags(one_dimensional_matrix: false)
- end
-
- let(:commit_status) do
- build(:commit_status, pipeline: pipeline, stage: 'test')
- end
-
- subject { commit_status.group_name }
-
- tests = {
- 'rspec:windows' => 'rspec:windows',
- 'rspec:windows 0' => 'rspec:windows 0',
- 'rspec:windows 0 test' => 'rspec:windows 0 test',
- 'rspec:windows 0 1' => 'rspec:windows',
- 'rspec:windows 0 1 name' => 'rspec:windows name',
- 'rspec:windows 0/1' => 'rspec:windows',
- 'rspec:windows 0/1 name' => 'rspec:windows name',
- 'rspec:windows 0:1' => 'rspec:windows',
- 'rspec:windows 0:1 name' => 'rspec:windows name',
- 'rspec:windows 10000 20000' => 'rspec:windows',
- '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',
- '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|
- it "'#{name}' puts in '#{group_name}'" do
- commit_status.name = name
-
- is_expected.to eq(group_name)
- end
- end
- end
- end
+ describe '#group_name' do
+ using RSpec::Parameterized::TableSyntax
- context 'with one_dimensional_matrix feature flag enabled' do
- describe '#group_name' do
- before do
- stub_feature_flags(one_dimensional_matrix: true)
- end
+ let(:commit_status) do
+ build(:commit_status, pipeline: pipeline, stage: 'test')
+ end
+
+ subject { commit_status.group_name }
+
+ where(:name, :group_name) do
+ 'rspec:windows' | 'rspec:windows'
+ 'rspec:windows 0' | 'rspec:windows 0'
+ 'rspec:windows 0 test' | 'rspec:windows 0 test'
+ 'rspec:windows 0 1' | 'rspec:windows'
+ 'rspec:windows 0 1 name' | 'rspec:windows name'
+ 'rspec:windows 0/1' | 'rspec:windows'
+ 'rspec:windows 0/1 name' | 'rspec:windows name'
+ 'rspec:windows 0:1' | 'rspec:windows'
+ 'rspec:windows 0:1 name' | 'rspec:windows name'
+ 'rspec:windows 10000 20000' | 'rspec:windows'
+ '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'
+ 'rspec: [aws]' | 'rspec'
+ 'rspec: [aws] 0/1' | 'rspec'
+ 'rspec: [aws, max memory]' | 'rspec'
+ 'rspec:linux: [aws, max memory, data]' | 'rspec:linux'
+ 'rspec: [inception: [something, other thing], value]' | 'rspec'
+ 'rspec:windows 0/1: [name, other]' | 'rspec:windows'
+ 'rspec:windows: [name, other] 0/1' | 'rspec:windows'
+ 'rspec:windows: [name, 0/1] 0/1' | 'rspec:windows'
+ 'rspec:windows: [0/1, name]' | 'rspec:windows'
+ 'rspec:windows: [, ]' | 'rspec:windows'
+ 'rspec:windows: [name]' | 'rspec:windows'
+ 'rspec:windows: [name,other]' | 'rspec:windows'
+ end
+
+ with_them do
+ it "#{params[:name]} puts in #{params[:group_name]}" do
+ commit_status.name = name
- let(:commit_status) do
- build(:commit_status, pipeline: pipeline, stage: 'test')
- end
-
- subject { commit_status.group_name }
-
- tests = {
- 'rspec:windows' => 'rspec:windows',
- 'rspec:windows 0' => 'rspec:windows 0',
- 'rspec:windows 0 test' => 'rspec:windows 0 test',
- 'rspec:windows 0 1' => 'rspec:windows',
- 'rspec:windows 0 1 name' => 'rspec:windows name',
- 'rspec:windows 0/1' => 'rspec:windows',
- 'rspec:windows 0/1 name' => 'rspec:windows name',
- 'rspec:windows 0:1' => 'rspec:windows',
- 'rspec:windows 0:1 name' => 'rspec:windows name',
- 'rspec:windows 10000 20000' => 'rspec:windows',
- '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',
- 'rspec: [aws]' => 'rspec',
- 'rspec: [aws] 0/1' => 'rspec',
- 'rspec: [aws, max memory]' => 'rspec',
- 'rspec:linux: [aws, max memory, data]' => 'rspec:linux',
- 'rspec: [inception: [something, other thing], value]' => 'rspec',
- 'rspec:windows 0/1: [name, other]' => 'rspec:windows',
- 'rspec:windows: [name, other] 0/1' => 'rspec:windows',
- 'rspec:windows: [name, 0/1] 0/1' => 'rspec:windows',
- 'rspec:windows: [0/1, name]' => 'rspec:windows',
- 'rspec:windows: [, ]' => 'rspec:windows',
- 'rspec:windows: [name]' => 'rspec:windows',
- 'rspec:windows: [name,other]' => 'rspec:windows'
- }
-
- tests.each do |name, group_name|
- it "'#{name}' puts in '#{group_name}'" do
- commit_status.name = name
-
- is_expected.to eq(group_name)
- end
+ is_expected.to eq(group_name)
end
end
end
diff --git a/spec/models/concerns/atomic_internal_id_spec.rb b/spec/models/concerns/atomic_internal_id_spec.rb
index 8c3537f1dcc..5ee3c012dc9 100644
--- a/spec/models/concerns/atomic_internal_id_spec.rb
+++ b/spec/models/concerns/atomic_internal_id_spec.rb
@@ -86,4 +86,20 @@ RSpec.describe AtomicInternalId do
expect { subject }.to change { milestone.iid }.from(nil).to(iid.to_i)
end
end
+
+ describe '.with_project_iid_supply' do
+ let(:iid) { 100 }
+
+ it 'wraps generate and track_greatest in a concurrency-safe lock' do
+ expect_next_instance_of(InternalId::InternalIdGenerator) do |g|
+ expect(g).to receive(:with_lock).and_call_original
+ expect(g.record).to receive(:last_value).and_return(iid)
+ expect(g).to receive(:track_greatest).with(iid + 4)
+ end
+
+ ::Milestone.with_project_iid_supply(milestone.project) do |supply|
+ 4.times { supply.next_value }
+ end
+ end
+ end
end
diff --git a/spec/models/concerns/from_union_spec.rb b/spec/models/concerns/from_union_spec.rb
index bd2893090a8..4f4d948fe48 100644
--- a/spec/models/concerns/from_union_spec.rb
+++ b/spec/models/concerns/from_union_spec.rb
@@ -3,13 +3,5 @@
require 'spec_helper'
RSpec.describe FromUnion do
- [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
-
- it_behaves_like 'from set operator', Gitlab::SQL::Union
- end
- end
+ it_behaves_like 'from set operator', Gitlab::SQL::Union
end
diff --git a/spec/models/concerns/optionally_search_spec.rb b/spec/models/concerns/optionally_search_spec.rb
index c8e2e6da51f..8067ad50322 100644
--- a/spec/models/concerns/optionally_search_spec.rb
+++ b/spec/models/concerns/optionally_search_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe OptionallySearch do
it 'delegates to the search method' do
expect(model)
.to receive(:search)
- .with('foo', {})
+ .with('foo')
.and_call_original
expect(model.optionally_search('foo')).to eq(['foo', {}])
diff --git a/spec/models/container_expiration_policy_spec.rb b/spec/models/container_expiration_policy_spec.rb
index 1d9dbe8a867..32ec5ed161a 100644
--- a/spec/models/container_expiration_policy_spec.rb
+++ b/spec/models/container_expiration_policy_spec.rb
@@ -38,10 +38,43 @@ RSpec.describe ContainerExpirationPolicy, type: :model do
it { is_expected.not_to allow_value('foo').for(:keep_n) }
end
+ describe '#disable!' do
+ let_it_be(:policy) { create(:container_expiration_policy) }
+
+ subject { policy.disable! }
+
+ it 'disables the container expiration policy' do
+ expect { subject }.to change { policy.reload.enabled }.from(true).to(false)
+ end
+ end
+
+ describe '#policy_params' do
+ let_it_be(:policy) { create(:container_expiration_policy) }
+
+ let(:expected) do
+ {
+ 'older_than' => policy.older_than,
+ 'keep_n' => policy.keep_n,
+ 'name_regex' => policy.name_regex,
+ 'name_regex_keep' => policy.name_regex_keep
+ }
+ end
+
+ subject { policy.policy_params }
+
+ it { is_expected.to eq(expected) }
+ end
+
context 'with a set of regexps' do
+ let_it_be(:container_expiration_policy) { create(:container_expiration_policy) }
+
+ subject { container_expiration_policy }
+
valid_regexps = %w[master .* v.+ v10.1.* (?:v.+|master|release)]
invalid_regexps = ['[', '(?:v.+|master|release']
+ it { is_expected.to validate_presence_of(:name_regex) }
+
valid_regexps.each do |valid_regexp|
it { is_expected.to allow_value(valid_regexp).for(:name_regex) }
it { is_expected.to allow_value(valid_regexp).for(:name_regex_keep) }
@@ -57,6 +90,8 @@ RSpec.describe ContainerExpirationPolicy, type: :model do
subject { container_expiration_policy }
+ it { is_expected.not_to validate_presence_of(:name_regex) }
+
valid_regexps.each do |valid_regexp|
it { is_expected.to allow_value(valid_regexp).for(:name_regex) }
it { is_expected.to allow_value(valid_regexp).for(:name_regex_keep) }
@@ -104,25 +139,15 @@ RSpec.describe ContainerExpirationPolicy, type: :model do
end
end
- describe '.executable' do
- subject { described_class.executable }
+ describe '.with_container_repositories' do
+ subject { described_class.with_container_repositories }
- let_it_be(:policy1) { create(:container_expiration_policy, :runnable) }
+ let_it_be(:policy1) { create(:container_expiration_policy) }
let_it_be(:container_repository1) { create(:container_repository, project: policy1.project) }
- let_it_be(:policy2) { create(:container_expiration_policy, :runnable) }
+ let_it_be(:policy2) { create(:container_expiration_policy) }
let_it_be(:container_repository2) { create(:container_repository, project: policy2.project) }
- let_it_be(:policy3) { create(:container_expiration_policy, :runnable) }
+ let_it_be(:policy3) { create(:container_expiration_policy) }
it { is_expected.to contain_exactly(policy1, policy2) }
end
-
- describe '#disable!' do
- let_it_be(:container_expiration_policy) { create(:container_expiration_policy) }
-
- subject { container_expiration_policy.disable! }
-
- it 'disables the container expiration policy' do
- expect { subject }.to change { container_expiration_policy.reload.enabled }.from(true).to(false)
- end
- end
end
diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb
index 2a7aaed5204..2adceb1c960 100644
--- a/spec/models/container_repository_spec.rb
+++ b/spec/models/container_repository_spec.rb
@@ -352,4 +352,20 @@ RSpec.describe ContainerRepository do
it { is_expected.to contain_exactly(repository) }
end
+
+ describe '.for_project_id' do
+ subject { described_class.for_project_id(project.id) }
+
+ it { is_expected.to contain_exactly(repository) }
+ end
+
+ describe '.waiting_for_cleanup' do
+ let_it_be(:repository_cleanup_scheduled) { create(:container_repository, :cleanup_scheduled) }
+ let_it_be(:repository_cleanup_unfinished) { create(:container_repository, :cleanup_unfinished) }
+ let_it_be(:repository_cleanup_ongoing) { create(:container_repository, :cleanup_ongoing) }
+
+ subject { described_class.waiting_for_cleanup }
+
+ it { is_expected.to contain_exactly(repository_cleanup_scheduled, repository_cleanup_unfinished) }
+ end
end
diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb
index 836c4139107..62380299ea0 100644
--- a/spec/models/custom_emoji_spec.rb
+++ b/spec/models/custom_emoji_spec.rb
@@ -13,20 +13,28 @@ RSpec.describe CustomEmoji do
describe 'exclusion of duplicated emoji' do
let(:emoji_name) { Gitlab::Emoji.emojis_names.sample }
+ let(:group) { create(:group, :private) }
it 'disallows emoji names of built-in emoji' do
- new_emoji = build(:custom_emoji, name: emoji_name)
+ new_emoji = build(:custom_emoji, name: emoji_name, group: group)
expect(new_emoji).not_to be_valid
expect(new_emoji.errors.messages).to eq(name: ["#{emoji_name} is already being used for another emoji"])
end
it 'disallows duplicate custom emoji names within namespace' do
- old_emoji = create(:custom_emoji)
- new_emoji = build(:custom_emoji, name: old_emoji.name, namespace: old_emoji.namespace)
+ old_emoji = create(:custom_emoji, group: group)
+ new_emoji = build(:custom_emoji, name: old_emoji.name, namespace: old_emoji.namespace, group: group)
expect(new_emoji).not_to be_valid
expect(new_emoji.errors.messages).to eq(name: ["has already been taken"])
end
+
+ it 'disallows non http and https file value' do
+ emoji = build(:custom_emoji, name: 'new-name', group: group, file: 'ftp://some-url.in')
+
+ expect(emoji).not_to be_valid
+ expect(emoji.errors.messages).to eq(file: ["is blocked: Only allowed schemes are http, https"])
+ end
end
end
diff --git a/spec/models/dependency_proxy/blob_spec.rb b/spec/models/dependency_proxy/blob_spec.rb
new file mode 100644
index 00000000000..7c8a1eb95e8
--- /dev/null
+++ b/spec/models/dependency_proxy/blob_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe DependencyProxy::Blob, type: :model do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:group) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:group) }
+ it { is_expected.to validate_presence_of(:file) }
+ it { is_expected.to validate_presence_of(:file_name) }
+ end
+
+ describe '.total_size' do
+ it 'returns 0 if no files' do
+ expect(described_class.total_size).to eq(0)
+ end
+
+ it 'returns a correct sum of all files sizes' do
+ create(:dependency_proxy_blob, size: 10)
+ create(:dependency_proxy_blob, size: 20)
+
+ expect(described_class.total_size).to eq(30)
+ end
+ end
+
+ describe '.find_or_build' do
+ let!(:blob) { create(:dependency_proxy_blob) }
+
+ it 'builds new instance if not found' do
+ expect(described_class.find_or_build('foo.gz')).not_to be_persisted
+ end
+
+ it 'finds an existing blob' do
+ expect(described_class.find_or_build(blob.file_name)).to eq(blob)
+ end
+ end
+
+ describe 'file is being stored' do
+ subject { create(:dependency_proxy_blob) }
+
+ 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_dependency_proxy_object_storage(direct_upload: true)
+ end
+
+ it_behaves_like 'mounted file in object store'
+ end
+ end
+end
diff --git a/spec/models/dependency_proxy/group_setting_spec.rb b/spec/models/dependency_proxy/group_setting_spec.rb
new file mode 100644
index 00000000000..c4c4a877d50
--- /dev/null
+++ b/spec/models/dependency_proxy/group_setting_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DependencyProxy::GroupSetting, type: :model do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:group) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:group) }
+ end
+end
diff --git a/spec/models/dependency_proxy/registry_spec.rb b/spec/models/dependency_proxy/registry_spec.rb
new file mode 100644
index 00000000000..5bfa75a2eed
--- /dev/null
+++ b/spec/models/dependency_proxy/registry_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe DependencyProxy::Registry, type: :model do
+ let(:tag) { '2.3.5-alpine' }
+ let(:blob_sha) { '40bd001563085fc35165329ea1ff5c5ecbdbbeef' }
+
+ context 'image name without namespace' do
+ let(:image) { 'ruby' }
+
+ describe '#auth_url' do
+ it 'returns a correct auth url' do
+ expect(described_class.auth_url(image))
+ .to eq('https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/ruby:pull')
+ end
+ end
+
+ describe '#manifest_url' do
+ it 'returns a correct manifest url' do
+ expect(described_class.manifest_url(image, tag))
+ .to eq('https://registry-1.docker.io/v2/library/ruby/manifests/2.3.5-alpine')
+ end
+ end
+
+ describe '#blob_url' do
+ it 'returns a correct blob url' do
+ expect(described_class.blob_url(image, blob_sha))
+ .to eq('https://registry-1.docker.io/v2/library/ruby/blobs/40bd001563085fc35165329ea1ff5c5ecbdbbeef')
+ end
+ end
+ end
+
+ context 'image name with namespace' do
+ let(:image) { 'foo/ruby' }
+
+ describe '#auth_url' do
+ it 'returns a correct auth url' do
+ expect(described_class.auth_url(image))
+ .to eq('https://auth.docker.io/token?service=registry.docker.io&scope=repository:foo/ruby:pull')
+ end
+ end
+
+ describe '#manifest_url' do
+ it 'returns a correct manifest url' do
+ expect(described_class.manifest_url(image, tag))
+ .to eq('https://registry-1.docker.io/v2/foo/ruby/manifests/2.3.5-alpine')
+ end
+ end
+
+ describe '#blob_url' do
+ it 'returns a correct blob url' do
+ expect(described_class.blob_url(image, blob_sha))
+ .to eq('https://registry-1.docker.io/v2/foo/ruby/blobs/40bd001563085fc35165329ea1ff5c5ecbdbbeef')
+ end
+ end
+ end
+end
diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb
index 00114a94b56..d4ccaa6a10e 100644
--- a/spec/models/deploy_key_spec.rb
+++ b/spec/models/deploy_key_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe DeployKey, :mailer do
describe "Associations" do
it { is_expected.to have_many(:deploy_keys_projects) }
it { is_expected.to have_many(:projects) }
+ it { is_expected.to have_many(:protected_branch_push_access_levels) }
end
describe 'notification' do
@@ -40,4 +41,56 @@ RSpec.describe DeployKey, :mailer do
end
end
end
+
+ describe '.with_write_access_for_project' do
+ let_it_be(:project) { create(:project, :private) }
+
+ subject { described_class.with_write_access_for_project(project) }
+
+ context 'when no project is passed in' do
+ let(:project) { nil }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'when a project is passed in' do
+ let_it_be(:deploy_keys_project) { create(:deploy_keys_project, :write_access, project: project) }
+ let_it_be(:deploy_key) { deploy_keys_project.deploy_key }
+
+ it 'only returns deploy keys with write access' do
+ create(:deploy_keys_project, project: project)
+
+ is_expected.to contain_exactly(deploy_key)
+ end
+
+ it 'returns deploy keys only for this project' do
+ other_project = create(:project)
+ create(:deploy_keys_project, :write_access, project: other_project)
+
+ is_expected.to contain_exactly(deploy_key)
+ end
+
+ context 'and a specific deploy key is passed in' do
+ subject { described_class.with_write_access_for_project(project, deploy_key: specific_deploy_key) }
+
+ context 'and this deploy key is not linked to the project' do
+ let(:specific_deploy_key) { create(:deploy_key) }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'and this deploy key has not write access to the project' do
+ let(:specific_deploy_key) { create(:deploy_key, deploy_keys_projects: [create(:deploy_keys_project, project: project)]) }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'and this deploy key has write access to the project' do
+ let(:specific_deploy_key) { create(:deploy_key, deploy_keys_projects: [create(:deploy_keys_project, :write_access, project: project)]) }
+
+ it { is_expected.to contain_exactly(specific_deploy_key) }
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/deploy_keys_project_spec.rb b/spec/models/deploy_keys_project_spec.rb
index 7dd4d3129de..ccc2c64e02c 100644
--- a/spec/models/deploy_keys_project_spec.rb
+++ b/spec/models/deploy_keys_project_spec.rb
@@ -13,21 +13,6 @@ RSpec.describe DeployKeysProject do
it { is_expected.to validate_presence_of(:deploy_key) }
end
- describe '.with_deploy_keys' do
- subject(:scoped_query) { described_class.with_deploy_keys.last }
-
- it 'includes deploy_keys in query' do
- project = create(:project)
- create(:deploy_keys_project, project: project, deploy_key: create(:deploy_key))
-
- includes_query_count = ActiveRecord::QueryRecorder.new { scoped_query }.count
- deploy_key_query_count = ActiveRecord::QueryRecorder.new { scoped_query.deploy_key }.count
-
- expect(includes_query_count).to eq(2)
- expect(deploy_key_query_count).to eq(0)
- end
- end
-
describe "Destroying" do
let(:project) { create(:project) }
subject { create(:deploy_keys_project, project: project) }
diff --git a/spec/models/deploy_token_spec.rb b/spec/models/deploy_token_spec.rb
index 60a3e3fc0e2..c7e1d5fc0d5 100644
--- a/spec/models/deploy_token_spec.rb
+++ b/spec/models/deploy_token_spec.rb
@@ -124,6 +124,39 @@ RSpec.describe DeployToken do
end
end
+ # override the default PolicyActor implementation that always returns false
+ describe "#deactivated?" do
+ context "when it has been revoked" do
+ it 'returns true' do
+ deploy_token.revoke!
+
+ expect(deploy_token.deactivated?).to be_truthy
+ end
+ end
+
+ context "when it hasn't been revoked and is not expired" do
+ it 'returns false' do
+ expect(deploy_token.deactivated?).to be_falsy
+ end
+ end
+
+ context "when it hasn't been revoked and is expired" do
+ it 'returns false' do
+ deploy_token.update_attribute(:expires_at, Date.today - 5.days)
+
+ expect(deploy_token.deactivated?).to be_truthy
+ end
+ end
+
+ context "when it hasn't been revoked and has no expiry" do
+ let(:deploy_token) { create(:deploy_token, expires_at: nil) }
+
+ it 'returns false' do
+ expect(deploy_token.deactivated?).to be_falsy
+ end
+ end
+ end
+
describe '#username' do
context 'persisted records' do
it 'returns a default username if none is set' do
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index 3e855584c38..9afacd518af 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -114,14 +114,6 @@ RSpec.describe Deployment do
deployment.run!
end
- it 'does not execute Deployments::ExecuteHooksWorker when feature is disabled' do
- stub_feature_flags(ci_send_deployment_hook_when_start: false)
- expect(Deployments::ExecuteHooksWorker)
- .not_to receive(:perform_async).with(deployment.id)
-
- deployment.run!
- end
-
it 'executes Deployments::DropOlderDeploymentsWorker asynchronously' do
expect(Deployments::DropOlderDeploymentsWorker)
.to receive(:perform_async).once.with(deployment.id)
diff --git a/spec/models/design_management/design_at_version_spec.rb b/spec/models/design_management/design_at_version_spec.rb
index 220de80a52a..a7cf6a9652b 100644
--- a/spec/models/design_management/design_at_version_spec.rb
+++ b/spec/models/design_management/design_at_version_spec.rb
@@ -185,7 +185,7 @@ RSpec.describe DesignManagement::DesignAtVersion do
end
describe 'validations' do
- subject(:design_at_version) { build(:design_at_version) }
+ subject(:design_at_version) { build_stubbed(:design_at_version) }
it { is_expected.to be_valid }
diff --git a/spec/models/design_management/design_spec.rb b/spec/models/design_management/design_spec.rb
index 2ce9f00a056..d3ce2f2d48f 100644
--- a/spec/models/design_management/design_spec.rb
+++ b/spec/models/design_management/design_spec.rb
@@ -11,6 +11,14 @@ RSpec.describe DesignManagement::Design do
let_it_be(:design3) { create(:design, :with_versions, issue: issue, versions_count: 1) }
let_it_be(:deleted_design) { create(:design, :with_versions, deleted: true) }
+ it_behaves_like 'AtomicInternalId', validate_presence: true do
+ let(:internal_id_attribute) { :iid }
+ let(:instance) { build(:design, issue: issue) }
+ let(:scope) { :project }
+ let(:scope_attrs) { { project: instance.project } }
+ let(:usage) { :design_management_designs }
+ end
+
it_behaves_like 'a class that supports relative positioning' do
let_it_be(:relative_parent) { create(:issue) }
@@ -23,8 +31,20 @@ RSpec.describe DesignManagement::Design do
it { is_expected.to belong_to(:issue) }
it { is_expected.to have_many(:actions) }
it { is_expected.to have_many(:versions) }
+ it { is_expected.to have_many(:authors) }
it { is_expected.to have_many(:notes).dependent(:delete_all) }
it { is_expected.to have_many(:user_mentions) }
+
+ describe '#authors' do
+ it 'returns unique version authors', :aggregate_failures do
+ author = create(:user)
+ create_list(:design_version, 2, designs: [design1], author: author)
+ version_authors = design1.versions.map(&:author)
+
+ expect(version_authors).to contain_exactly(issue.author, author, author)
+ expect(design1.authors).to contain_exactly(issue.author, author)
+ end
+ end
end
describe 'validations' do
@@ -326,6 +346,38 @@ RSpec.describe DesignManagement::Design do
end
end
+ describe '#participants' do
+ let_it_be_with_refind(:design) { create(:design, issue: issue) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:version_author) { create(:user) }
+ let_it_be(:note_author) { create(:user) }
+ let_it_be(:mentioned_user) { create(:user) }
+ let_it_be(:design_version) { create(:design_version, :committed, designs: [design], author: version_author) }
+ let_it_be(:note) do
+ create(:diff_note_on_design,
+ noteable: design,
+ issue: issue,
+ project: issue.project,
+ author: note_author,
+ note: mentioned_user.to_reference
+ )
+ end
+
+ subject { design.participants(current_user) }
+
+ it { is_expected.to be_empty }
+
+ context 'when participants can read the project' do
+ before do
+ design.project.add_guest(version_author)
+ design.project.add_guest(note_author)
+ design.project.add_guest(mentioned_user)
+ end
+
+ it { is_expected.to contain_exactly(version_author, note_author, mentioned_user) }
+ end
+ end
+
describe "#new_design?" do
let(:design) { design1 }
diff --git a/spec/models/design_management/version_spec.rb b/spec/models/design_management/version_spec.rb
index cd52f4129dc..e004ad024bc 100644
--- a/spec/models/design_management/version_spec.rb
+++ b/spec/models/design_management/version_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe DesignManagement::Version do
it { is_expected.to validate_presence_of(:author) }
it { is_expected.to validate_presence_of(:sha) }
it { is_expected.to validate_presence_of(:designs) }
- it { is_expected.to validate_presence_of(:issue_id) }
+ it { is_expected.to validate_presence_of(:issue) }
it { is_expected.to validate_uniqueness_of(:sha).scoped_to(:issue_id).case_insensitive }
end
diff --git a/spec/models/diff_viewer/image_spec.rb b/spec/models/diff_viewer/image_spec.rb
new file mode 100644
index 00000000000..e959a7d5eb2
--- /dev/null
+++ b/spec/models/diff_viewer/image_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DiffViewer::Image do
+ describe '.can_render?' do
+ let(:diff_file) { double(Gitlab::Diff::File) }
+ let(:blob) { double(Gitlab::Git::Blob, binary_in_repo?: true, extension: 'png') }
+
+ subject { described_class.can_render?(diff_file, verify_binary: false) }
+
+ it 'returns false if both old and new blob are absent' do
+ allow(diff_file).to receive(:old_blob) { nil }
+ allow(diff_file).to receive(:new_blob) { nil }
+
+ is_expected.to be_falsy
+ end
+
+ it 'returns true if the old blob is present' do
+ allow(diff_file).to receive(:old_blob) { blob }
+ allow(diff_file).to receive(:new_blob) { nil }
+
+ is_expected.to be_truthy
+ end
+
+ it 'returns true if the new blob is present' do
+ allow(diff_file).to receive(:old_blob) { nil }
+ allow(diff_file).to receive(:new_blob) { blob }
+
+ is_expected.to be_truthy
+ end
+
+ it 'returns true if both old and new blobs are present' do
+ allow(diff_file).to receive(:old_blob) { blob }
+ allow(diff_file).to receive(:new_blob) { blob }
+
+ is_expected.to be_truthy
+ end
+ end
+end
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 06d3e9da286..179f2a1b0e0 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -982,6 +982,22 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
end
+ describe '#has_running_deployments?' do
+ subject { environment.has_running_deployments? }
+
+ it 'return false when no deployments exist' do
+ is_expected.to eq(false)
+ end
+
+ context 'when deployment is running on the environment' do
+ let!(:deployment) { create(:deployment, :running, environment: environment) }
+
+ it 'return true' do
+ is_expected.to eq(true)
+ end
+ end
+ end
+
describe '#metrics' do
let(:project) { create(:prometheus_project) }
diff --git a/spec/models/experiment_spec.rb b/spec/models/experiment_spec.rb
index 64cd2da4621..587f410c9be 100644
--- a/spec/models/experiment_spec.rb
+++ b/spec/models/experiment_spec.rb
@@ -7,32 +7,6 @@ RSpec.describe Experiment do
describe 'associations' do
it { is_expected.to have_many(:experiment_users) }
- it { is_expected.to have_many(:users) }
- it { is_expected.to have_many(:control_group_users) }
- it { is_expected.to have_many(:experimental_group_users) }
-
- describe 'control_group_users and experimental_group_users' do
- let(:experiment) { create(:experiment) }
- let(:control_group_user) { build(:user) }
- let(:experimental_group_user) { build(:user) }
-
- before do
- experiment.control_group_users << control_group_user
- experiment.experimental_group_users << experimental_group_user
- end
-
- describe 'control_group_users' do
- subject { experiment.control_group_users }
-
- it { is_expected.to contain_exactly(control_group_user) }
- end
-
- describe 'experimental_group_users' do
- subject { experiment.experimental_group_users }
-
- it { is_expected.to contain_exactly(experimental_group_user) }
- end
- end
end
describe 'validations' do
@@ -42,71 +16,83 @@ RSpec.describe Experiment do
end
describe '.add_user' do
- let(:name) { :experiment_key }
- let(:user) { build(:user) }
+ let_it_be(:experiment_name) { :experiment_key }
+ let_it_be(:user) { 'a user' }
+ let_it_be(:group) { 'a group' }
- let!(:experiment) { create(:experiment, name: name) }
+ subject(:add_user) { described_class.add_user(experiment_name, group, user) }
- subject { described_class.add_user(name, :control, user) }
-
- describe 'creating a new experiment record' do
- context 'an experiment with the provided name already exists' do
- it 'does not create a new experiment record' do
- expect { subject }.not_to change(Experiment, :count)
+ context 'when an experiment with the provided name does not exist' do
+ it 'creates a new experiment record' do
+ allow_next_instance_of(described_class) do |experiment|
+ allow(experiment).to receive(:record_user_and_group).with(user, group)
end
+ expect { add_user }.to change(described_class, :count).by(1)
end
- context 'an experiment with the provided name does not exist yet' do
- let(:experiment) { nil }
-
- it 'creates a new experiment record' do
- expect { subject }.to change(Experiment, :count).by(1)
+ it 'forwards the user and group_type to the instance' do
+ expect_next_instance_of(described_class) do |experiment|
+ expect(experiment).to receive(:record_user_and_group).with(user, group)
end
+ add_user
end
end
- describe 'creating a new experiment_user record' do
- context 'an experiment_user record for this experiment already exists' do
- before do
- subject
- end
+ context 'when an experiment with the provided name already exists' do
+ let_it_be(:experiment) { create(:experiment, name: experiment_name) }
- it 'does not create a new experiment_user record' do
- expect { subject }.not_to change(ExperimentUser, :count)
+ it 'does not create a new experiment record' do
+ allow_next_found_instance_of(described_class) do |experiment|
+ allow(experiment).to receive(:record_user_and_group).with(user, group)
end
+ expect { add_user }.not_to change(described_class, :count)
end
- context 'an experiment_user record for this experiment does not exist yet' do
- it 'creates a new experiment_user record' do
- expect { subject }.to change(ExperimentUser, :count).by(1)
- end
-
- it 'assigns the correct group_type to the experiment_user' do
- expect { subject }.to change { experiment.control_group_users.count }.by(1)
+ it 'forwards the user and group_type to the instance' do
+ expect_next_found_instance_of(described_class) do |experiment|
+ expect(experiment).to receive(:record_user_and_group).with(user, group)
end
+ add_user
end
end
end
- describe '#add_control_user' do
- let(:experiment) { create(:experiment) }
- let(:user) { build(:user) }
+ describe '#record_user_and_group' do
+ let_it_be(:experiment) { create(:experiment) }
+ let_it_be(:user) { create(:user) }
- subject { experiment.add_control_user(user) }
+ let(:group) { :control }
- it 'creates a new experiment_user record and assigns the correct group_type' do
- expect { subject }.to change { experiment.control_group_users.count }.by(1)
+ subject(:record_user_and_group) { experiment.record_user_and_group(user, group) }
+
+ context 'when an experiment_user does not yet exist for the given user' do
+ it 'creates a new experiment_user record' do
+ expect { record_user_and_group }.to change(ExperimentUser, :count).by(1)
+ end
+
+ it 'assigns the correct group_type to the experiment_user' do
+ record_user_and_group
+ expect(ExperimentUser.last.group_type).to eq('control')
+ end
end
- end
- describe '#add_experimental_user' do
- let(:experiment) { create(:experiment) }
- let(:user) { build(:user) }
+ context 'when an experiment_user already exists for the given user' do
+ before do
+ # Create an existing experiment_user for this experiment and the :control group
+ experiment.record_user_and_group(user, :control)
+ end
+
+ it 'does not create a new experiment_user record' do
+ expect { record_user_and_group }.not_to change(ExperimentUser, :count)
+ end
- subject { experiment.add_experimental_user(user) }
+ context 'but the group_type has changed' do
+ let(:group) { :experimental }
- it 'creates a new experiment_user record and assigns the correct group_type' do
- expect { subject }.to change { experiment.experimental_group_users.count }.by(1)
+ it 'updates the existing experiment_user record' do
+ expect { record_user_and_group }.to change { ExperimentUser.last.group_type }
+ end
+ end
end
end
end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index cc29e20710a..dd1faf999b3 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -28,6 +28,8 @@ RSpec.describe Group do
it { is_expected.to have_many(:iterations) }
it { is_expected.to have_many(:group_deploy_keys) }
it { is_expected.to have_many(:services) }
+ it { is_expected.to have_one(:dependency_proxy_setting) }
+ it { is_expected.to have_many(:dependency_proxy_blobs) }
describe '#members & #requesters' do
let(:requester) { create(:user) }
@@ -308,8 +310,10 @@ RSpec.describe Group do
end
describe 'scopes' do
- let!(:private_group) { create(:group, :private) }
- let!(:internal_group) { create(:group, :internal) }
+ let_it_be(:private_group) { create(:group, :private) }
+ let_it_be(:internal_group) { create(:group, :internal) }
+ let_it_be(:user1) { create(:user) }
+ let_it_be(:user2) { create(:user) }
describe 'public_only' do
subject { described_class.public_only.to_a }
@@ -328,6 +332,27 @@ RSpec.describe Group do
it { is_expected.to match_array([private_group, internal_group]) }
end
+
+ describe 'for_authorized_group_members' do
+ let_it_be(:group_member1) { create(:group_member, source: private_group, user_id: user1.id, access_level: Gitlab::Access::OWNER) }
+
+ it do
+ result = described_class.for_authorized_group_members([user1.id, user2.id])
+
+ expect(result).to match_array([private_group])
+ end
+ end
+
+ describe 'for_authorized_project_members' do
+ let_it_be(:project) { create(:project, group: internal_group) }
+ let_it_be(:project_member1) { create(:project_member, source: project, user_id: user1.id, access_level: Gitlab::Access::DEVELOPER) }
+
+ it do
+ result = described_class.for_authorized_project_members([user1.id, user2.id])
+
+ expect(result).to match_array([internal_group])
+ end
+ end
end
describe '#to_reference' do
@@ -944,23 +969,72 @@ RSpec.describe Group do
context 'expanded group members' do
let(:indirect_user) { create(:user) }
- it 'enables two_factor_requirement for subgroup member' do
- subgroup = create(:group, :nested, parent: group)
- subgroup.add_user(indirect_user, GroupMember::OWNER)
+ context 'two_factor_requirement is enabled' do
+ context 'two_factor_requirement is also enabled for ancestor group' do
+ it 'enables two_factor_requirement for subgroup member' do
+ subgroup = create(:group, :nested, parent: group)
+ subgroup.add_user(indirect_user, GroupMember::OWNER)
- group.update!(require_two_factor_authentication: true)
+ group.update!(require_two_factor_authentication: true)
+
+ expect(indirect_user.reload.require_two_factor_authentication_from_group).to be_truthy
+ end
+ end
+
+ context 'two_factor_requirement is disabled for ancestor group' do
+ it 'enables two_factor_requirement for subgroup member' do
+ subgroup = create(:group, :nested, parent: group, require_two_factor_authentication: true)
+ subgroup.add_user(indirect_user, GroupMember::OWNER)
+
+ group.update!(require_two_factor_authentication: false)
+
+ expect(indirect_user.reload.require_two_factor_authentication_from_group).to be_truthy
+ end
+
+ it 'enable two_factor_requirement for ancestor group member' do
+ ancestor_group = create(:group)
+ ancestor_group.add_user(indirect_user, GroupMember::OWNER)
+ group.update!(parent: ancestor_group)
+
+ group.update!(require_two_factor_authentication: true)
- expect(indirect_user.reload.require_two_factor_authentication_from_group).to be_truthy
+ expect(indirect_user.reload.require_two_factor_authentication_from_group).to be_truthy
+ end
+ end
end
- it 'does not enable two_factor_requirement for ancestor group member' do
- ancestor_group = create(:group)
- ancestor_group.add_user(indirect_user, GroupMember::OWNER)
- group.update!(parent: ancestor_group)
+ context 'two_factor_requirement is disabled' do
+ context 'two_factor_requirement is enabled for ancestor group' do
+ it 'enables two_factor_requirement for subgroup member' do
+ subgroup = create(:group, :nested, parent: group)
+ subgroup.add_user(indirect_user, GroupMember::OWNER)
- group.update!(require_two_factor_authentication: true)
+ group.update!(require_two_factor_authentication: true)
+
+ expect(indirect_user.reload.require_two_factor_authentication_from_group).to be_truthy
+ end
+ end
+
+ context 'two_factor_requirement is also disabled for ancestor group' do
+ it 'disables two_factor_requirement for subgroup member' do
+ subgroup = create(:group, :nested, parent: group)
+ subgroup.add_user(indirect_user, GroupMember::OWNER)
- expect(indirect_user.reload.require_two_factor_authentication_from_group).to be_falsey
+ group.update!(require_two_factor_authentication: false)
+
+ expect(indirect_user.reload.require_two_factor_authentication_from_group).to be_falsey
+ end
+
+ it 'disables two_factor_requirement for ancestor group member' do
+ ancestor_group = create(:group, require_two_factor_authentication: false)
+ indirect_user.update!(require_two_factor_authentication_from_group: true)
+ ancestor_group.add_user(indirect_user, GroupMember::OWNER)
+
+ group.update!(require_two_factor_authentication: false)
+
+ expect(indirect_user.reload.require_two_factor_authentication_from_group).to be_falsey
+ end
+ end
end
end
@@ -1591,4 +1665,47 @@ RSpec.describe Group do
end
end
end
+
+ describe 'has_project_with_service_desk_enabled?' do
+ let_it_be(:group) { create(:group, :private) }
+
+ subject { group.has_project_with_service_desk_enabled? }
+
+ before do
+ allow(Gitlab::ServiceDesk).to receive(:supported?).and_return(true)
+ end
+
+ context 'when service desk is enabled' do
+ context 'for top level group' do
+ let_it_be(:project) { create(:project, group: group, service_desk_enabled: true) }
+
+ it { is_expected.to eq(true) }
+
+ context 'when service desk is not supported' do
+ before do
+ allow(Gitlab::ServiceDesk).to receive(:supported?).and_return(false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ context 'for subgroup project' do
+ let_it_be(:subgroup) { create(:group, :private, parent: group)}
+ let_it_be(:project) { create(:project, group: subgroup, service_desk_enabled: true) }
+
+ it { is_expected.to eq(true) }
+ end
+ end
+
+ context 'when none of group child projects has service desk enabled' do
+ let_it_be(:project) { create(:project, group: group, service_desk_enabled: false) }
+
+ before do
+ project.update(service_desk_enabled: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
end
diff --git a/spec/models/instance_metadata_spec.rb b/spec/models/instance_metadata_spec.rb
new file mode 100644
index 00000000000..1835dc8a9af
--- /dev/null
+++ b/spec/models/instance_metadata_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe InstanceMetadata do
+ it 'has the correct properties' do
+ expect(subject).to have_attributes(
+ version: Gitlab::VERSION,
+ revision: Gitlab.revision
+ )
+ end
+end
diff --git a/spec/models/internal_id_spec.rb b/spec/models/internal_id_spec.rb
index 751e8724872..07f62b9de55 100644
--- a/spec/models/internal_id_spec.rb
+++ b/spec/models/internal_id_spec.rb
@@ -6,8 +6,9 @@ RSpec.describe InternalId do
let(:project) { create(:project) }
let(:usage) { :issues }
let(:issue) { build(:issue, project: project) }
+ let(:id_subject) { issue }
let(:scope) { { project: project } }
- let(:init) { ->(s) { s.project.issues.size } }
+ let(:init) { ->(issue, scope) { issue&.project&.issues&.size || Issue.where(**scope).count } }
it_behaves_like 'having unique enum values'
@@ -39,7 +40,7 @@ RSpec.describe InternalId do
end
describe '.generate_next' do
- subject { described_class.generate_next(issue, scope, usage, init) }
+ subject { described_class.generate_next(id_subject, scope, usage, init) }
context 'in the absence of a record' do
it 'creates a record if not yet present' do
@@ -88,6 +89,14 @@ RSpec.describe InternalId do
expect(normalized).to eq((0..seq.size - 1).to_a)
end
+
+ context 'there are no instances to pass in' do
+ let(:id_subject) { Issue }
+
+ it 'accepts classes instead' do
+ expect(subject).to eq(1)
+ end
+ end
end
describe '.reset' do
@@ -130,7 +139,7 @@ RSpec.describe InternalId do
describe '.track_greatest' do
let(:value) { 9001 }
- subject { described_class.track_greatest(issue, scope, usage, value, init) }
+ subject { described_class.track_greatest(id_subject, scope, usage, value, init) }
context 'in the absence of a record' do
it 'creates a record if not yet present' do
@@ -166,6 +175,14 @@ RSpec.describe InternalId do
expect(subject).to eq 10_001
end
end
+
+ context 'there are no instances to pass in' do
+ let(:id_subject) { Issue }
+
+ it 'accepts classes instead' do
+ expect(subject).to eq(value)
+ end
+ end
end
describe '#increment_and_save!' do
diff --git a/spec/models/issue_link_spec.rb b/spec/models/issue_link_spec.rb
index 00791d4a48b..ef41108ebea 100644
--- a/spec/models/issue_link_spec.rb
+++ b/spec/models/issue_link_spec.rb
@@ -27,7 +27,14 @@ RSpec.describe IssueLink do
.with_message(/already related/)
end
- context 'self relation' do
+ it 'is not valid if an opposite link already exists' do
+ issue_link = build(:issue_link, source: subject.target, target: subject.source)
+
+ expect(issue_link).to be_invalid
+ expect(issue_link.errors[:source]).to include('is already related to this issue')
+ end
+
+ context 'when it relates to itself' do
let(:issue) { create :issue }
context 'cannot be validated' do
diff --git a/spec/models/issues/csv_import_spec.rb b/spec/models/issues/csv_import_spec.rb
new file mode 100644
index 00000000000..2911a79e505
--- /dev/null
+++ b/spec/models/issues/csv_import_spec.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Issues::CsvImport, type: :model do
+ describe 'associations' do
+ it { is_expected.to belong_to(:project).required }
+ it { is_expected.to belong_to(:user).required }
+ end
+end
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 1e14864676c..3d33a39d353 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -108,7 +108,7 @@ RSpec.describe Key, :mailer do
expect(build(:key, key: 'ssh-rsa an-invalid-key==')).not_to be_valid
end
- where(:factory, :chars, :expected_sections) do
+ where(:factory, :characters, :expected_sections) do
[
[:key, ["\n", "\r\n"], 3],
[:key, [' ', ' '], 3],
@@ -122,7 +122,7 @@ RSpec.describe Key, :mailer do
let!(:original_fingerprint_sha256) { key.fingerprint_sha256 }
it 'accepts a key with blank space characters after stripping them' do
- modified_key = key.key.insert(100, chars.first).insert(40, chars.last)
+ modified_key = key.key.insert(100, characters.first).insert(40, characters.last)
_, content = modified_key.split
key.update!(key: modified_key)
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index 118b1492cd6..1a791820f1b 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -252,12 +252,17 @@ RSpec.describe Member do
end
describe '.last_ten_days_excluding_today' do
- let_it_be(:created_today) { create(:group_member, created_at: Date.today.beginning_of_day) }
- let_it_be(:created_yesterday) { create(:group_member, created_at: 1.day.ago) }
- let_it_be(:created_eleven_days_ago) { create(:group_member, created_at: 11.days.ago) }
+ let_it_be(:now) { Time.current }
+ let_it_be(:created_today) { create(:group_member, created_at: now.beginning_of_day) }
+ let_it_be(:created_yesterday) { create(:group_member, created_at: now - 1.day) }
+ let_it_be(:created_eleven_days_ago) { create(:group_member, created_at: now - 11.days) }
subject { described_class.last_ten_days_excluding_today }
+ before do
+ travel_to now
+ end
+
it { is_expected.to include(created_yesterday) }
it { is_expected.not_to include(created_today, created_eleven_days_ago) }
end
diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb
index 9af620e70a5..2b24e2d6455 100644
--- a/spec/models/members/group_member_spec.rb
+++ b/spec/models/members/group_member_spec.rb
@@ -4,9 +4,10 @@ require 'spec_helper'
RSpec.describe GroupMember do
context 'scopes' do
+ let_it_be(:user_1) { create(:user) }
+ let_it_be(:user_2) { create(:user) }
+
it 'counts users by group ID' do
- user_1 = create(:user)
- user_2 = create(:user)
group_1 = create(:group)
group_2 = create(:group)
@@ -25,6 +26,15 @@ RSpec.describe GroupMember do
expect(described_class.of_ldap_type).to eq([group_member])
end
end
+
+ describe '.with_user' do
+ it 'returns requested user' do
+ group_member = create(:group_member, user: user_2)
+ create(:group_member, user: user_1)
+
+ expect(described_class.with_user(user_2)).to eq([group_member])
+ end
+ end
end
describe '.access_level_roles' do
diff --git a/spec/models/merge_request/cleanup_schedule_spec.rb b/spec/models/merge_request/cleanup_schedule_spec.rb
new file mode 100644
index 00000000000..925d287088b
--- /dev/null
+++ b/spec/models/merge_request/cleanup_schedule_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequest::CleanupSchedule do
+ describe 'associations' do
+ it { is_expected.to belong_to(:merge_request) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:scheduled_at) }
+ end
+
+ describe '.scheduled_merge_request_ids' do
+ let_it_be(:mr_cleanup_schedule_1) { create(:merge_request_cleanup_schedule, scheduled_at: 2.days.ago) }
+ let_it_be(:mr_cleanup_schedule_2) { create(:merge_request_cleanup_schedule, scheduled_at: 1.day.ago) }
+ let_it_be(:mr_cleanup_schedule_3) { create(:merge_request_cleanup_schedule, scheduled_at: 1.day.ago, completed_at: Time.current) }
+ let_it_be(:mr_cleanup_schedule_4) { create(:merge_request_cleanup_schedule, scheduled_at: 4.days.ago) }
+ let_it_be(:mr_cleanup_schedule_5) { create(:merge_request_cleanup_schedule, scheduled_at: 3.days.ago) }
+ let_it_be(:mr_cleanup_schedule_6) { create(:merge_request_cleanup_schedule, scheduled_at: 1.day.from_now) }
+ let_it_be(:mr_cleanup_schedule_7) { create(:merge_request_cleanup_schedule, scheduled_at: 5.days.ago) }
+
+ it 'only includes incomplete schedule within the specified limit' do
+ expect(described_class.scheduled_merge_request_ids(4)).to eq([
+ mr_cleanup_schedule_2.merge_request_id,
+ mr_cleanup_schedule_1.merge_request_id,
+ mr_cleanup_schedule_5.merge_request_id,
+ mr_cleanup_schedule_4.merge_request_id
+ ])
+ end
+ end
+end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index ddb3ffdda2f..9574c57e46c 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -30,6 +30,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
it { is_expected.to have_many(:resource_state_events) }
it { is_expected.to have_many(:draft_notes) }
it { is_expected.to have_many(:reviews).inverse_of(:merge_request) }
+ it { is_expected.to have_one(:cleanup_schedule).inverse_of(:merge_request) }
context 'for forks' do
let!(:project) { create(:project) }
@@ -79,6 +80,18 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
+ describe '.with_jira_issue_keys' do
+ let_it_be(:mr_with_jira_title) { create(:merge_request, :unique_branches, title: 'Fix TEST-123') }
+ let_it_be(:mr_with_jira_description) { create(:merge_request, :unique_branches, description: 'this closes TEST-321') }
+ let_it_be(:mr_without_jira_reference) { create(:merge_request, :unique_branches) }
+
+ subject { described_class.with_jira_issue_keys }
+
+ it { is_expected.to contain_exactly(mr_with_jira_title, mr_with_jira_description) }
+
+ it { is_expected.not_to include(mr_without_jira_reference) }
+ end
+
describe '#squash_in_progress?' do
let(:repo_path) do
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
diff --git a/spec/models/namespace/root_storage_statistics_spec.rb b/spec/models/namespace/root_storage_statistics_spec.rb
index 92a8d17a2a8..b725d2366a1 100644
--- a/spec/models/namespace/root_storage_statistics_spec.rb
+++ b/spec/models/namespace/root_storage_statistics_spec.rb
@@ -45,6 +45,7 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
total_storage_size = stat1.storage_size + stat2.storage_size
total_snippets_size = stat1.snippets_size + stat2.snippets_size
total_pipeline_artifacts_size = stat1.pipeline_artifacts_size + stat2.pipeline_artifacts_size
+ total_uploads_size = stat1.uploads_size + stat2.uploads_size
expect(root_storage_statistics.repository_size).to eq(total_repository_size)
expect(root_storage_statistics.wiki_size).to eq(total_wiki_size)
@@ -54,6 +55,7 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
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)
+ expect(root_storage_statistics.uploads_size).to eq(total_uploads_size)
end
it 'works when there are no projects' do
diff --git a/spec/models/namespace_setting_spec.rb b/spec/models/namespace_setting_spec.rb
index c6e8d5b129c..59b7510051f 100644
--- a/spec/models/namespace_setting_spec.rb
+++ b/spec/models/namespace_setting_spec.rb
@@ -36,13 +36,10 @@ RSpec.describe NamespaceSetting, type: :model do
context "when an empty string" do
before do
- namespace_settings.default_branch_name = ''
+ namespace_settings.default_branch_name = ""
end
- it "returns an error" do
- expect(namespace_settings.valid?).to be_falsey
- expect(namespace_settings.errors.full_messages).not_to be_empty
- end
+ it_behaves_like "doesn't return an error"
end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 91b18f346c6..85f9005052e 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -147,30 +147,45 @@ RSpec.describe Namespace do
end
describe '.search' do
- let(:namespace) { create(:namespace) }
+ let_it_be(:first_namespace) { build(:namespace, name: 'my first namespace', path: 'old-path').tap(&:save!) }
+ let_it_be(:parent_namespace) { build(:namespace, name: 'my parent namespace', path: 'parent-path').tap(&:save!) }
+ let_it_be(:second_namespace) { build(:namespace, name: 'my second namespace', path: 'new-path', parent: parent_namespace).tap(&:save!) }
+ let_it_be(:project_with_same_path) { create(:project, id: second_namespace.id, path: first_namespace.path) }
it 'returns namespaces with a matching name' do
- expect(described_class.search(namespace.name)).to eq([namespace])
+ expect(described_class.search('my first namespace')).to eq([first_namespace])
end
it 'returns namespaces with a partially matching name' do
- expect(described_class.search(namespace.name[0..2])).to eq([namespace])
+ expect(described_class.search('first')).to eq([first_namespace])
end
it 'returns namespaces with a matching name regardless of the casing' do
- expect(described_class.search(namespace.name.upcase)).to eq([namespace])
+ expect(described_class.search('MY FIRST NAMESPACE')).to eq([first_namespace])
end
it 'returns namespaces with a matching path' do
- expect(described_class.search(namespace.path)).to eq([namespace])
+ expect(described_class.search('old-path')).to eq([first_namespace])
end
it 'returns namespaces with a partially matching path' do
- expect(described_class.search(namespace.path[0..2])).to eq([namespace])
+ expect(described_class.search('old')).to eq([first_namespace])
end
it 'returns namespaces with a matching path regardless of the casing' do
- expect(described_class.search(namespace.path.upcase)).to eq([namespace])
+ expect(described_class.search('OLD-PATH')).to eq([first_namespace])
+ end
+
+ it 'returns namespaces with a matching route path' do
+ expect(described_class.search('parent-path/new-path', include_parents: true)).to eq([second_namespace])
+ end
+
+ it 'returns namespaces with a partially matching route path' do
+ expect(described_class.search('parent-path/new', include_parents: true)).to eq([second_namespace])
+ end
+
+ it 'returns namespaces with a matching route path regardless of the casing' do
+ expect(described_class.search('PARENT-PATH/NEW-PATH', include_parents: true)).to eq([second_namespace])
end
end
@@ -672,7 +687,7 @@ RSpec.describe Namespace do
let!(:project) { create(:project_empty_repo, namespace: namespace) }
it 'has no repositories base directories to remove' do
- allow(GitlabShellWorker).to receive(:perform_in)
+ expect(GitlabShellWorker).not_to receive(:perform_in)
expect(File.exist?(path_in_dir)).to be(false)
@@ -855,8 +870,8 @@ RSpec.describe Namespace do
end
describe '#all_projects' do
- shared_examples 'all projects for a namespace' do
- let(:namespace) { create(:namespace) }
+ shared_examples 'all projects for a group' do
+ let(:namespace) { create(:group) }
let(:child) { create(:group, parent: namespace) }
let!(:project1) { create(:project_empty_repo, namespace: namespace) }
let!(:project2) { create(:project_empty_repo, namespace: child) }
@@ -865,30 +880,34 @@ RSpec.describe Namespace do
it { expect(child.all_projects.to_a).to match_array([project2]) }
end
- shared_examples 'all project examples' do
- include_examples 'all projects for a namespace'
+ shared_examples 'all projects for personal namespace' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:user_namespace) { create(:namespace, owner: user) }
+ let_it_be(:project) { create(:project, namespace: user_namespace) }
+
+ it { expect(user_namespace.all_projects.to_a).to match_array([project]) }
+ end
+ context 'with recursive approach' do
context 'when namespace is a group' do
- let_it_be(:namespace) { create(:group) }
+ include_examples 'all projects for a group'
+
+ it 'queries for the namespace and its descendants' do
+ expect(Project).to receive(:where).with(namespace: [namespace, child])
- include_examples 'all projects for a namespace'
+ namespace.all_projects
+ end
end
context 'when namespace is a user namespace' do
- let_it_be(:user) { create(:user) }
- let_it_be(:user_namespace) { create(:namespace, owner: user) }
- let_it_be(:project) { create(:project, namespace: user_namespace) }
+ include_examples 'all projects for personal namespace'
- it { expect(user_namespace.all_projects.to_a).to match_array([project]) }
- end
- end
+ it 'only queries for the namespace itself' do
+ expect(Project).to receive(:where).with(namespace: user_namespace)
- context 'with recursive approach' do
- before do
- stub_feature_flags(recursive_approach_for_all_projects: true)
+ user_namespace.all_projects
+ end
end
-
- include_examples 'all project examples'
end
context 'with route path wildcard approach' do
@@ -896,7 +915,13 @@ RSpec.describe Namespace do
stub_feature_flags(recursive_approach_for_all_projects: false)
end
- include_examples 'all project examples'
+ context 'when namespace is a group' do
+ include_examples 'all projects for a group'
+ end
+
+ context 'when namespace is a user namespace' do
+ include_examples 'all projects for personal namespace'
+ end
end
end
@@ -1246,24 +1271,6 @@ RSpec.describe Namespace do
expect(virtual_domain.lookup_paths).not_to be_empty
end
end
-
- it 'preloads project_feature and route' do
- project2 = create(:project, namespace: namespace)
- project3 = create(:project, namespace: namespace)
-
- project.mark_pages_as_deployed
- project2.mark_pages_as_deployed
- project3.mark_pages_as_deployed
-
- virtual_domain = namespace.pages_virtual_domain
-
- queries = ActiveRecord::QueryRecorder.new { virtual_domain.lookup_paths }
-
- # 1 to load projects
- # 1 to preload project features
- # 1 to load routes
- expect(queries.count).to eq(3)
- end
end
end
diff --git a/spec/models/operations/feature_flag_spec.rb b/spec/models/operations/feature_flag_spec.rb
index b4e941f2856..93dd7d4f0bb 100644
--- a/spec/models/operations/feature_flag_spec.rb
+++ b/spec/models/operations/feature_flag_spec.rb
@@ -261,4 +261,38 @@ RSpec.describe Operations::FeatureFlag do
expect(flags.map(&:id)).to eq([feature_flag.id, feature_flag_b.id])
end
end
+
+ describe '#hook_attrs' do
+ it 'includes expected attributes' do
+ hook_attrs = {
+ id: subject.id,
+ name: subject.name,
+ description: subject.description,
+ active: subject.active
+ }
+ expect(subject.hook_attrs).to eq(hook_attrs)
+ end
+ end
+
+ describe "#execute_hooks" do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project) }
+
+ it 'does not execute the hook when feature_flag event is disabled' do
+ create(:project_hook, project: project, feature_flag_events: false)
+ expect(WebHookWorker).not_to receive(:perform_async)
+
+ feature_flag.execute_hooks(user)
+ feature_flag.touch
+ end
+
+ it 'executes hook when feature_flag event is enabled' do
+ hook = create(:project_hook, project: project, feature_flag_events: true)
+ expect(WebHookWorker).to receive(:perform_async).with(hook.id, an_instance_of(Hash), 'feature_flag_hooks')
+
+ feature_flag.execute_hooks(user)
+ feature_flag.touch
+ 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
index 020416aa7bc..3a48d3389a3 100644
--- a/spec/models/operations/feature_flags/user_list_spec.rb
+++ b/spec/models/operations/feature_flags/user_list_spec.rb
@@ -92,6 +92,25 @@ RSpec.describe Operations::FeatureFlags::UserList do
end
end
+ describe '.for_name_like' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user_list_one) { create(:operations_feature_flag_user_list, project: project, name: 'one') }
+ let_it_be(:user_list_two) { create(:operations_feature_flag_user_list, project: project, name: 'list_two') }
+ let_it_be(:user_list_three) { create(:operations_feature_flag_user_list, project: project, name: 'list_three') }
+
+ it 'returns a found name' do
+ lists = project.operations_feature_flags_user_lists.for_name_like('list')
+
+ expect(lists).to contain_exactly(user_list_two, user_list_three)
+ end
+
+ it 'returns an empty array when no lists match the query' do
+ lists = project.operations_feature_flags_user_lists.for_name_like('no match')
+
+ expect(lists).to be_empty
+ end
+ end
+
it_behaves_like 'AtomicInternalId' do
let(:internal_id_attribute) { :iid }
let(:instance) { build(:operations_feature_flag_user_list) }
diff --git a/spec/models/packages/build_info_spec.rb b/spec/models/packages/build_info_spec.rb
new file mode 100644
index 00000000000..a4369c56fe2
--- /dev/null
+++ b/spec/models/packages/build_info_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::BuildInfo, type: :model do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:package) }
+ it { is_expected.to belong_to(:pipeline) }
+ end
+end
diff --git a/spec/models/packages/package_file_build_info_spec.rb b/spec/models/packages/package_file_build_info_spec.rb
new file mode 100644
index 00000000000..18d6e720bf8
--- /dev/null
+++ b/spec/models/packages/package_file_build_info_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::PackageFileBuildInfo, type: :model do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:package_file) }
+ it { is_expected.to belong_to(:pipeline) }
+ end
+end
diff --git a/spec/models/packages/package_file_spec.rb b/spec/models/packages/package_file_spec.rb
index 6b992dbc2a5..ef09fb037e9 100644
--- a/spec/models/packages/package_file_spec.rb
+++ b/spec/models/packages/package_file_spec.rb
@@ -5,6 +5,8 @@ RSpec.describe Packages::PackageFile, type: :model do
describe 'relationships' do
it { is_expected.to belong_to(:package) }
it { is_expected.to have_one(:conan_file_metadatum) }
+ it { is_expected.to have_many(:package_file_build_infos).inverse_of(:package_file) }
+ it { is_expected.to have_many(:pipelines).through(:package_file_build_infos) }
end
describe 'validations' do
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index 41a731b87e9..705a1991845 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -10,6 +10,8 @@ RSpec.describe Packages::Package, type: :model do
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) }
+ it { is_expected.to have_many(:build_infos).inverse_of(:package) }
+ it { is_expected.to have_many(:pipelines).through(:build_infos) }
it { is_expected.to have_one(:conan_metadatum).inverse_of(:package) }
it { is_expected.to have_one(:maven_metadatum).inverse_of(:package) }
it { is_expected.to have_one(:nuget_metadatum).inverse_of(:package) }
@@ -171,6 +173,13 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) }
end
+ context 'composer package' do
+ it_behaves_like 'validating version to be SemVer compliant for', :composer_package
+
+ it { is_expected.to allow_value('dev-master').for(:version) }
+ it { is_expected.to allow_value('2.x-dev').for(:version) }
+ end
+
context 'maven package' do
subject { build_stubbed(:maven_package) }
@@ -573,7 +582,7 @@ RSpec.describe Packages::Package, type: :model do
end
describe '#pipeline' do
- let_it_be(:package) { create(:maven_package) }
+ let_it_be_with_refind(:package) { create(:maven_package) }
context 'package without pipeline' do
it 'returns nil if there is no pipeline' do
@@ -585,7 +594,7 @@ RSpec.describe Packages::Package, type: :model do
let_it_be(:pipeline) { create(:ci_pipeline) }
before do
- package.create_build_info!(pipeline: pipeline)
+ package.build_infos.create!(pipeline: pipeline)
end
it 'returns the pipeline' do
@@ -630,4 +639,23 @@ RSpec.describe Packages::Package, type: :model do
end
end
end
+
+ describe '#original_build_info' do
+ let_it_be_with_refind(:package) { create(:npm_package) }
+
+ context 'without build_infos' do
+ it 'returns nil' do
+ expect(package.original_build_info).to be_nil
+ end
+ end
+
+ context 'with build_infos' do
+ let_it_be(:first_build_info) { create(:package_build_info, :with_pipeline, package: package) }
+ let_it_be(:second_build_info) { create(:package_build_info, :with_pipeline, package: package) }
+
+ it 'returns the first build info' do
+ expect(package.original_build_info).to eq(first_build_info)
+ end
+ end
+ end
end
diff --git a/spec/models/pages/lookup_path_spec.rb b/spec/models/pages/lookup_path_spec.rb
index cb1938a0113..f8ebc237577 100644
--- a/spec/models/pages/lookup_path_spec.rb
+++ b/spec/models/pages/lookup_path_spec.rb
@@ -3,15 +3,14 @@
require 'spec_helper'
RSpec.describe Pages::LookupPath do
- let_it_be(:project) do
- create(:project, :pages_private, pages_https_only: true)
- end
+ let(:project) { create(:project, :pages_private, pages_https_only: true) }
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
+ stub_pages_object_storage(::Pages::DeploymentUploader)
end
describe '#project_id' do
@@ -47,18 +46,78 @@ RSpec.describe Pages::LookupPath do
end
describe '#source' do
- shared_examples 'uses disk storage' do
- it 'sets the source type to "file"' do
- expect(lookup_path.source[:type]).to eq('file')
- end
+ let(:source) { lookup_path.source }
- 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/")
+ shared_examples 'uses disk storage' do
+ it 'uses disk storage', :aggregate_failures do
+ expect(source[:type]).to eq('file')
+ expect(source[:path]).to eq(project.full_path + "/public/")
end
end
include_examples 'uses disk storage'
+ context 'when there is pages deployment' do
+ let(:deployment) { create(:pages_deployment, project: project) }
+
+ before do
+ project.mark_pages_as_deployed
+ project.pages_metadatum.update!(pages_deployment: deployment)
+ end
+
+ it 'uses deployment from object storage' do
+ Timecop.freeze do
+ expect(source).to(
+ eq({
+ type: 'zip',
+ path: deployment.file.url(expire_at: 1.day.from_now),
+ global_id: "gid://gitlab/PagesDeployment/#{deployment.id}",
+ sha256: deployment.file_sha256,
+ file_size: deployment.size,
+ file_count: deployment.file_count
+ })
+ )
+ end
+ end
+
+ context 'when deployment is in the local storage' do
+ before do
+ deployment.file.migrate!(::ObjectStorage::Store::LOCAL)
+ end
+
+ it 'uses file protocol' do
+ Timecop.freeze do
+ expect(source).to(
+ eq({
+ type: 'zip',
+ path: 'file://' + deployment.file.path,
+ global_id: "gid://gitlab/PagesDeployment/#{deployment.id}",
+ sha256: deployment.file_sha256,
+ file_size: deployment.size,
+ file_count: deployment.file_count
+ })
+ )
+ end
+ end
+
+ context 'when pages_serve_with_zip_file_protocol feature flag is disabled' do
+ before do
+ stub_feature_flags(pages_serve_with_zip_file_protocol: false)
+ end
+
+ include_examples 'uses disk storage'
+ end
+ end
+
+ context 'when pages_serve_from_deployments feature flag is disabled' do
+ before do
+ stub_feature_flags(pages_serve_from_deployments: false)
+ end
+
+ include_examples 'uses disk storage'
+ end
+ end
+
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) }
@@ -66,26 +125,51 @@ RSpec.describe Pages::LookupPath 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
+ it 'uses artifacts object storage' 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")
+ expect(source).to(
+ eq({
+ type: 'zip',
+ path: artifacts_archive.file.url(expire_at: 1.day.from_now),
+ global_id: "gid://gitlab/Ci::JobArtifact/#{artifacts_archive.id}",
+ sha256: artifacts_archive.file_sha256,
+ file_size: artifacts_archive.size,
+ file_count: nil
+ })
+ )
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'
+ it 'uses file protocol', :aggregate_failures do
+ Timecop.freeze do
+ expect(source).to(
+ eq({
+ type: 'zip',
+ path: 'file://' + artifacts_archive.file.path,
+ global_id: "gid://gitlab/Ci::JobArtifact/#{artifacts_archive.id}",
+ sha256: artifacts_archive.file_sha256,
+ file_size: artifacts_archive.size,
+ file_count: nil
+ })
+ )
+ end
+ end
+
+ context 'when pages_serve_with_zip_file_protocol feature flag is disabled' do
+ before do
+ stub_feature_flags(pages_serve_with_zip_file_protocol: false)
+ end
+
+ include_examples 'uses disk storage'
+ end
end
context 'when feature flag is disabled' do
before do
- stub_feature_flags(pages_artifacts_archive: false)
+ stub_feature_flags(pages_serve_from_artifacts_archive: false)
end
include_examples 'uses disk storage'
diff --git a/spec/models/pages_deployment_spec.rb b/spec/models/pages_deployment_spec.rb
index 5d26ade740e..e83cbc15004 100644
--- a/spec/models/pages_deployment_spec.rb
+++ b/spec/models/pages_deployment_spec.rb
@@ -10,8 +10,15 @@ RSpec.describe PagesDeployment do
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_presence_of(:file_count) }
+ it { is_expected.to validate_numericality_of(:file_count).only_integer.is_greater_than_or_equal_to(0) }
+
+ it { is_expected.to validate_presence_of(:file_sha256) }
+
it { is_expected.to validate_inclusion_of(:file_store).in_array(ObjectStorage::SUPPORTED_STORES) }
it 'is valid when created from the factory' do
@@ -20,14 +27,26 @@ RSpec.describe PagesDeployment do
end
describe 'default for file_store' do
+ let(:project) { create(:project) }
+ let(:deployment) do
+ filepath = Rails.root.join("spec/fixtures/pages.zip")
+
+ described_class.create!(
+ project: project,
+ file: fixture_file_upload(filepath),
+ file_sha256: Digest::SHA256.file(filepath).hexdigest,
+ file_count: 3
+ )
+ end
+
it 'uses local store when object storage is not enabled' do
- expect(build(:pages_deployment).file_store).to eq(ObjectStorage::Store::LOCAL)
+ expect(deployment.file_store).to eq(ObjectStorage::Store::LOCAL)
end
it 'uses remote store when object storage is enabled' do
stub_pages_object_storage(::Pages::DeploymentUploader)
- expect(build(:pages_deployment).file_store).to eq(ObjectStorage::Store::REMOTE)
+ expect(deployment.file_store).to eq(ObjectStorage::Store::REMOTE)
end
end
@@ -35,4 +54,17 @@ RSpec.describe PagesDeployment do
deployment = create(:pages_deployment)
expect(deployment.size).to eq(deployment.file.size)
end
+
+ describe '.older_than' do
+ it 'returns deployments with lower id' do
+ old_deployments = create_list(:pages_deployment, 2)
+
+ deployment = create(:pages_deployment)
+
+ # new deployment
+ create(:pages_deployment)
+
+ expect(PagesDeployment.older_than(deployment.id)).to eq(old_deployments)
+ end
+ end
end
diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb
index 9e80d0e0886..67ecbe13c1a 100644
--- a/spec/models/personal_access_token_spec.rb
+++ b/spec/models/personal_access_token_spec.rb
@@ -31,6 +31,18 @@ RSpec.describe PersonalAccessToken do
expect(described_class.for_user(user_1)).to contain_exactly(token_of_user_1)
end
end
+
+ describe '.for_users' do
+ it 'returns personal access tokens for the specified users only' do
+ user_1 = create(:user)
+ user_2 = create(:user)
+ token_of_user_1 = create(:personal_access_token, user: user_1)
+ token_of_user_2 = create(:personal_access_token, user: user_2)
+ create_list(:personal_access_token, 3)
+
+ expect(described_class.for_users([user_1, user_2])).to contain_exactly(token_of_user_1, token_of_user_2)
+ end
+ end
end
describe ".active?" do
diff --git a/spec/models/personal_snippet_spec.rb b/spec/models/personal_snippet_spec.rb
index 234f6e4b4b5..212605445ff 100644
--- a/spec/models/personal_snippet_spec.rb
+++ b/spec/models/personal_snippet_spec.rb
@@ -20,9 +20,8 @@ RSpec.describe PersonalSnippet do
it_behaves_like 'model with repository' do
let_it_be(:container) { create(:personal_snippet, :repository) }
let(:stubbed_container) { build_stubbed(:personal_snippet) }
- let(:expected_full_path) { "@snippets/#{container.id}" }
+ let(:expected_full_path) { "snippets/#{container.id}" }
let(:expected_web_url_path) { "-/snippets/#{container.id}" }
- let(:expected_repo_url_path) { "snippets/#{container.id}" }
end
describe '#parent_user' do
diff --git a/spec/models/project_snippet_spec.rb b/spec/models/project_snippet_spec.rb
index 3bcbf6b9e1b..3d1c87771f3 100644
--- a/spec/models/project_snippet_spec.rb
+++ b/spec/models/project_snippet_spec.rb
@@ -36,8 +36,7 @@ RSpec.describe ProjectSnippet do
it_behaves_like 'model with repository' do
let_it_be(:container) { create(:project_snippet, :repository) }
let(:stubbed_container) { build_stubbed(:project_snippet) }
- let(:expected_full_path) { "#{container.project.full_path}/@snippets/#{container.id}" }
+ let(:expected_full_path) { "#{container.project.full_path}/snippets/#{container.id}" }
let(:expected_web_url_path) { "#{container.project.full_path}/-/snippets/#{container.id}" }
- let(:expected_repo_url_path) { "#{container.project.full_path}/snippets/#{container.id}" }
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 53a213891e9..c8b96963d5d 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -2,12 +2,14 @@
require 'spec_helper'
-RSpec.describe Project do
+RSpec.describe Project, factory_default: :keep do
include ProjectForksHelper
include GitHelpers
include ExternalAuthorizationServiceHelpers
using RSpec::Parameterized::TableSyntax
+ let_it_be(:namespace) { create_default(:namespace) }
+
it_behaves_like 'having unique enum values'
describe 'associations' do
@@ -3003,14 +3005,23 @@ RSpec.describe Project do
describe '#set_repository_read_only!' do
let(:project) { create(:project) }
- it 'returns true when there is no existing git transfer in progress' do
- expect(project.set_repository_read_only!).to be_truthy
+ it 'makes the repository read-only' do
+ expect { project.set_repository_read_only! }
+ .to change(project, :repository_read_only?)
+ .from(false)
+ .to(true)
end
- it 'returns false when there is an existing git transfer in progress' do
+ it 'raises an error if the project is already read-only' do
+ project.set_repository_read_only!
+
+ expect { project.set_repository_read_only! }.to raise_error(described_class::RepositoryReadOnlyError, /already read-only/)
+ end
+
+ it 'raises an error when there is an existing git transfer in progress' do
allow(project).to receive(:git_transfer_in_progress?) { true }
- expect(project.set_repository_read_only!).to be_falsey
+ expect { project.set_repository_read_only! }.to raise_error(described_class::RepositoryReadOnlyError, /in progress/)
end
end
@@ -3657,7 +3668,7 @@ RSpec.describe Project do
let(:project) { create(:project) }
before do
- project.namespace_id = 7
+ project.namespace_id = project.namespace_id + 1
end
it { expect(project.parent_changed?).to be_truthy }
@@ -3985,8 +3996,16 @@ RSpec.describe Project do
context 'when feature is private' do
let(:project) { create(:project, :public, :merge_requests_private) }
- it 'returns projects with the project feature private' do
- is_expected.to include(project)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns projects with the project feature private' do
+ is_expected.to include(project)
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'does not return projects with the project feature private' do
+ is_expected.not_to include(project)
+ end
end
end
end
@@ -4009,7 +4028,7 @@ RSpec.describe Project do
end
end
- describe '.filter_by_feature_visibility', :enable_admin_mode do
+ describe '.filter_by_feature_visibility' do
include_context 'ProjectPolicyTable context'
include ProjectHelpers
using RSpec::Parameterized::TableSyntax
@@ -4021,12 +4040,13 @@ RSpec.describe Project do
context 'reporter level access' do
let(:feature) { MergeRequest }
- where(:project_level, :feature_access_level, :membership, :expected_count) do
+ where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
permission_table_for_reporter_feature_access
end
with_them do
it "respects visibility" do
+ enable_admin_mode!(user) if admin_mode
update_feature_access_level(project, feature_access_level)
expected_objects = expected_count == 1 ? [project] : []
@@ -4041,12 +4061,13 @@ RSpec.describe Project do
context 'issues' do
let(:feature) { Issue }
- where(:project_level, :feature_access_level, :membership, :expected_count) do
+ where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
permission_table_for_guest_feature_access
end
with_them do
it "respects visibility" do
+ enable_admin_mode!(user) if admin_mode
update_feature_access_level(project, feature_access_level)
expected_objects = expected_count == 1 ? [project] : []
@@ -4061,12 +4082,13 @@ RSpec.describe Project do
context 'wiki' do
let(:feature) { :wiki }
- where(:project_level, :feature_access_level, :membership, :expected_count) do
+ where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
permission_table_for_guest_feature_access
end
with_them do
it "respects visibility" do
+ enable_admin_mode!(user) if admin_mode
update_feature_access_level(project, feature_access_level)
expected_objects = expected_count == 1 ? [project] : []
@@ -4081,12 +4103,13 @@ RSpec.describe Project do
context 'code' do
let(:feature) { :repository }
- where(:project_level, :feature_access_level, :membership, :expected_count) do
+ where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
permission_table_for_guest_feature_access_and_non_private_project_only
end
with_them do
it "respects visibility" do
+ enable_admin_mode!(user) if admin_mode
update_feature_access_level(project, feature_access_level)
expected_objects = expected_count == 1 ? [project] : []
@@ -4208,6 +4231,27 @@ RSpec.describe Project do
expect { project.destroy }.not_to raise_error
end
+
+ context 'when there is an old pages deployment' do
+ let!(:old_deployment_from_another_project) { create(:pages_deployment) }
+ let!(:old_deployment) { create(:pages_deployment, project: project) }
+
+ it 'schedules a destruction of pages deployments' do
+ expect(DestroyPagesDeploymentsWorker).to(
+ receive(:perform_async).with(project.id)
+ )
+
+ project.remove_pages
+ end
+
+ it 'removes pages deployments', :sidekiq_inline do
+ expect do
+ project.remove_pages
+ end.to change { PagesDeployment.count }.by(-1)
+
+ expect(PagesDeployment.find_by_id(old_deployment.id)).to be_nil
+ end
+ end
end
describe '#remove_export' do
@@ -5507,15 +5551,16 @@ RSpec.describe Project do
end
describe '#find_or_initialize_services' do
- it 'returns only enabled services' do
+ before do
allow(Service).to receive(:available_services_names).and_return(%w[prometheus pushover teamcity])
- allow(Service).to receive(:project_specific_services_names).and_return(%w[asana])
allow(subject).to receive(:disabled_services).and_return(%w[prometheus])
+ end
+ it 'returns only enabled services' do
services = subject.find_or_initialize_services
- expect(services.count).to eq(3)
- expect(services.map(&:title)).to eq(['Asana', 'JetBrains TeamCity CI', 'Pushover'])
+ expect(services.count).to eq(2)
+ expect(services.map(&:title)).to eq(['JetBrains TeamCity CI', 'Pushover'])
end
end
@@ -5895,6 +5940,26 @@ RSpec.describe Project do
end
end
+ describe '#update_pages_deployment!' do
+ let(:project) { create(:project) }
+ let(:deployment) { create(:pages_deployment, project: project) }
+
+ it "creates new metadata record if none exists yet and sets deployment" do
+ project.pages_metadatum.destroy!
+ project.reload
+
+ project.update_pages_deployment!(deployment)
+
+ expect(project.pages_metadatum.pages_deployment).to eq(deployment)
+ end
+
+ it "updates the existing metadara record with deployment" do
+ expect do
+ project.update_pages_deployment!(deployment)
+ end.to change { project.pages_metadatum.reload.pages_deployment }.from(nil).to(deployment)
+ end
+ end
+
describe '#has_pool_repsitory?' do
it 'returns false when it does not have a pool repository' do
subject = create(:project, :repository)
diff --git a/spec/models/project_statistics_spec.rb b/spec/models/project_statistics_spec.rb
index 9f40dbb3401..2d283766edb 100644
--- a/spec/models/project_statistics_spec.rb
+++ b/spec/models/project_statistics_spec.rb
@@ -34,7 +34,8 @@ RSpec.describe ProjectStatistics do
lfs_objects_size: 2.exabytes,
build_artifacts_size: 1.exabyte,
snippets_size: 1.exabyte,
- pipeline_artifacts_size: 1.exabyte - 1
+ pipeline_artifacts_size: 512.petabytes - 1,
+ uploads_size: 512.petabytes
)
statistics.reload
@@ -46,7 +47,8 @@ RSpec.describe ProjectStatistics do
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)
+ expect(statistics.pipeline_artifacts_size).to eq(512.petabytes - 1)
+ expect(statistics.uploads_size).to eq(512.petabytes)
end
end
@@ -57,6 +59,7 @@ RSpec.describe ProjectStatistics do
statistics.lfs_objects_size = 3
statistics.build_artifacts_size = 4
statistics.snippets_size = 5
+ statistics.uploads_size = 3
expect(statistics.total_repository_size).to eq 5
end
@@ -98,6 +101,7 @@ RSpec.describe ProjectStatistics do
allow(statistics).to receive(:update_lfs_objects_size)
allow(statistics).to receive(:update_snippets_size)
allow(statistics).to receive(:update_storage_size)
+ allow(statistics).to receive(:update_uploads_size)
end
context "without arguments" do
@@ -111,6 +115,7 @@ RSpec.describe ProjectStatistics do
expect(statistics).to have_received(:update_wiki_size)
expect(statistics).to have_received(:update_lfs_objects_size)
expect(statistics).to have_received(:update_snippets_size)
+ expect(statistics).to have_received(:update_uploads_size)
end
end
@@ -125,6 +130,7 @@ RSpec.describe ProjectStatistics do
expect(statistics).not_to have_received(:update_repository_size)
expect(statistics).not_to have_received(:update_wiki_size)
expect(statistics).not_to have_received(:update_snippets_size)
+ expect(statistics).not_to have_received(:update_uploads_size)
end
end
@@ -139,10 +145,12 @@ RSpec.describe ProjectStatistics do
expect(statistics).to have_received(:update_repository_size)
expect(statistics).to have_received(:update_wiki_size)
expect(statistics).to have_received(:update_snippets_size)
+ expect(statistics).to have_received(:update_uploads_size)
expect(statistics.repository_size).to eq(0)
expect(statistics.commit_count).to eq(0)
expect(statistics.wiki_size).to eq(0)
expect(statistics.snippets_size).to eq(0)
+ expect(statistics.uploads_size).to eq(0)
end
end
@@ -163,10 +171,12 @@ RSpec.describe ProjectStatistics do
expect(statistics).to have_received(:update_repository_size)
expect(statistics).to have_received(:update_wiki_size)
expect(statistics).to have_received(:update_snippets_size)
+ expect(statistics).to have_received(:update_uploads_size)
expect(statistics.repository_size).to eq(0)
expect(statistics.commit_count).to eq(0)
expect(statistics.wiki_size).to eq(0)
expect(statistics.snippets_size).to eq(0)
+ expect(statistics.uploads_size).to eq(0)
end
end
@@ -211,6 +221,7 @@ RSpec.describe ProjectStatistics do
expect(statistics).not_to receive(:update_wiki_size)
expect(statistics).not_to receive(:update_lfs_objects_size)
expect(statistics).not_to receive(:update_snippets_size)
+ expect(statistics).not_to receive(:update_uploads_size)
expect(statistics).not_to receive(:save!)
expect(Namespaces::ScheduleAggregationWorker)
.not_to receive(:perform_async)
@@ -295,6 +306,26 @@ RSpec.describe ProjectStatistics do
end
end
+ describe '#update_uploads_size' do
+ let!(:upload1) { create(:upload, model: project, size: 1.megabyte) }
+ let!(:upload2) { create(:upload, model: project, size: 2.megabytes) }
+
+ it 'stores the size of related uploaded files' do
+ expect(statistics.update_uploads_size).to eq(3.megabytes)
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ statistics.update_columns(uploads_size: 0)
+ stub_feature_flags(count_uploads_size_in_storage_stats: false)
+ end
+
+ it 'does not store the size of related uploaded files' do
+ expect(statistics.update_uploads_size).to eq(0)
+ end
+ end
+ end
+
describe '#update_storage_size' do
it "sums all storage counters" do
statistics.update!(
@@ -302,12 +333,13 @@ RSpec.describe ProjectStatistics do
wiki_size: 4,
lfs_objects_size: 3,
snippets_size: 2,
- pipeline_artifacts_size: 3
+ pipeline_artifacts_size: 3,
+ uploads_size: 5
)
statistics.reload
- expect(statistics.storage_size).to eq 14
+ expect(statistics.storage_size).to eq 19
end
it 'works during wiki_size backfill' do
diff --git a/spec/models/protected_branch/push_access_level_spec.rb b/spec/models/protected_branch/push_access_level_spec.rb
index 77fe9814c86..0aba51ea567 100644
--- a/spec/models/protected_branch/push_access_level_spec.rb
+++ b/spec/models/protected_branch/push_access_level_spec.rb
@@ -4,4 +4,34 @@ require 'spec_helper'
RSpec.describe ProtectedBranch::PushAccessLevel do
it { is_expected.to validate_inclusion_of(:access_level).in_array([Gitlab::Access::MAINTAINER, Gitlab::Access::DEVELOPER, Gitlab::Access::NO_ACCESS]) }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:deploy_key) }
+ end
+
+ describe 'validations' do
+ it 'is not valid when a record exists with the same access level' do
+ protected_branch = create(:protected_branch)
+ create(:protected_branch_push_access_level, protected_branch: protected_branch)
+ level = build(:protected_branch_push_access_level, protected_branch: protected_branch)
+
+ expect(level).to be_invalid
+ end
+
+ it 'is not valid when a record exists with the same access level' do
+ protected_branch = create(:protected_branch)
+ deploy_key = create(:deploy_key, projects: [protected_branch.project])
+ create(:protected_branch_push_access_level, protected_branch: protected_branch, deploy_key: deploy_key)
+ level = build(:protected_branch_push_access_level, protected_branch: protected_branch, deploy_key: deploy_key)
+
+ expect(level).to be_invalid
+ end
+
+ it 'checks that a deploy key is enabled for the same project as the protected branch\'s' do
+ level = build(:protected_branch_push_access_level, deploy_key: create(:deploy_key))
+
+ expect { level.save! }.to raise_error
+ expect(level.errors.full_messages).to contain_exactly('Deploy key is not enabled for this project')
+ end
+ end
end
diff --git a/spec/models/route_spec.rb b/spec/models/route_spec.rb
index 0f1637016d6..eb81db95cd3 100644
--- a/spec/models/route_spec.rb
+++ b/spec/models/route_spec.rb
@@ -62,6 +62,15 @@ RSpec.describe Route do
end
end
+ describe '.for_routable_type' do
+ let!(:nested_group) { create(:group, path: 'foo', name: 'foo', parent: group) }
+ let!(:project) { create(:project, path: 'other-project') }
+
+ it 'returns correct routes' do
+ expect(described_class.for_routable_type(Project.name)).to match_array([project.route])
+ end
+ end
+
describe '#rename_descendants' do
let!(:nested_group) { create(:group, path: 'test', name: 'test', parent: group) }
let!(:deep_nested_group) { create(:group, path: 'foo', name: 'foo', parent: nested_group) }
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index db3cf19a03f..402c1a3d19b 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Service do
+ using RSpec::Parameterized::TableSyntax
+
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
@@ -15,8 +17,6 @@ RSpec.describe Service do
end
describe 'validations' do
- using RSpec::Parameterized::TableSyntax
-
it { is_expected.to validate_presence_of(:type) }
where(:project_id, :group_id, :template, :instance, :valid) do
@@ -208,27 +208,27 @@ RSpec.describe Service do
end
end
- describe '.find_or_initialize_integration' do
+ describe '.find_or_initialize_non_project_specific_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)
+ expect(Service.find_or_initialize_non_project_specific_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 }
+ expect { Service.find_or_initialize_non_project_specific_integration('redmine', group_id: group) }.not_to change { Service.count }
end
end
- describe '.find_or_initialize_all' do
+ describe '.find_or_initialize_all_non_project_specific' do
shared_examples 'service instances' do
it 'returns the available service instances' do
- expect(Service.find_or_initialize_all(Service.for_instance).pluck(:type)).to match_array(Service.available_services_types)
+ expect(Service.find_or_initialize_all_non_project_specific(Service.for_instance).pluck(:type)).to match_array(Service.available_services_types(include_project_specific: false))
end
it 'does not create service instances' do
- expect { Service.find_or_initialize_all(Service.for_instance) }.not_to change { Service.count }
+ expect { Service.find_or_initialize_all_non_project_specific(Service.for_instance) }.not_to change { Service.count }
end
end
@@ -237,7 +237,7 @@ RSpec.describe Service do
context 'with all existing instances' do
before do
Service.insert_all(
- Service.available_services_types.map { |type| { instance: true, type: type } }
+ Service.available_services_types(include_project_specific: false).map { |type| { instance: true, type: type } }
)
end
@@ -265,13 +265,13 @@ RSpec.describe Service do
describe 'template' do
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)
+ expect(Service.find_or_create_templates.pluck(:type)).to match_array(Service.available_services_types(include_project_specific: false))
end
end
describe '.find_or_create_templates' do
it 'creates service templates' do
- expect { Service.find_or_create_templates }.to change { Service.count }.from(0).to(Service.available_services_names.size)
+ expect { Service.find_or_create_templates }.to change { Service.count }.from(0).to(Service.available_services_names(include_project_specific: false).size)
end
it_behaves_like 'retrieves service templates'
@@ -279,7 +279,7 @@ RSpec.describe Service do
context 'with all existing templates' do
before do
Service.insert_all(
- Service.available_services_types.map { |type| { template: true, type: type } }
+ Service.available_services_types(include_project_specific: false).map { |type| { template: true, type: type } }
)
end
@@ -305,7 +305,7 @@ RSpec.describe Service do
end
it 'creates the rest of the service templates' do
- expect { Service.find_or_create_templates }.to change { Service.count }.from(1).to(Service.available_services_names.size)
+ expect { Service.find_or_create_templates }.to change { Service.count }.from(1).to(Service.available_services_names(include_project_specific: false).size)
end
it_behaves_like 'retrieves service templates'
@@ -599,6 +599,23 @@ RSpec.describe Service do
end
end
+ describe '.inherited_descendants_from_self_or_ancestors_from' do
+ let_it_be(:subgroup1) { create(:group, parent: group) }
+ let_it_be(:subgroup2) { create(:group, parent: group) }
+ let_it_be(:project1) { create(:project, group: subgroup1) }
+ let_it_be(:project2) { create(:project, group: subgroup2) }
+ let_it_be(:group_integration) { create(:prometheus_service, group: group, project: nil) }
+ let_it_be(:subgroup_integration1) { create(:prometheus_service, group: subgroup1, project: nil, inherit_from_id: group_integration.id) }
+ let_it_be(:subgroup_integration2) { create(:prometheus_service, group: subgroup2, project: nil) }
+ let_it_be(:project_integration1) { create(:prometheus_service, group: nil, project: project1, inherit_from_id: group_integration.id) }
+ let_it_be(:project_integration2) { create(:prometheus_service, group: nil, project: project2, inherit_from_id: subgroup_integration2.id) }
+
+ it 'returns the groups and projects inheriting from integration ancestors', :aggregate_failures do
+ expect(described_class.inherited_descendants_from_self_or_ancestors_from(group_integration)).to eq([subgroup_integration1, project_integration1])
+ expect(described_class.inherited_descendants_from_self_or_ancestors_from(subgroup_integration2)).to eq([project_integration2])
+ end
+ end
+
describe "{property}_changed?" do
let(:service) do
BambooService.create(
@@ -826,5 +843,78 @@ RSpec.describe Service do
service.log_error(test_message, additional_argument: 'some argument')
end
+
+ context 'when project is nil' do
+ let(:project) { nil }
+ let(:arguments) do
+ {
+ service_class: service.class.name,
+ project_path: nil,
+ project_id: nil,
+ message: test_message,
+ additional_argument: 'some argument'
+ }
+ end
+
+ it 'logs info messages using json logger' do
+ expect(Gitlab::JsonLogger).to receive(:info).with(arguments)
+
+ service.log_info(test_message, additional_argument: 'some argument')
+ end
+ end
+ end
+
+ describe '#external_issue_tracker?' do
+ where(:category, :active, :result) do
+ :issue_tracker | true | true
+ :issue_tracker | false | false
+ :common | true | false
+ end
+
+ with_them do
+ it 'returns the right result' do
+ expect(build(:service, category: category, active: active).external_issue_tracker?).to eq(result)
+ end
+ end
+ end
+
+ describe '#external_wiki?' do
+ where(:type, :active, :result) do
+ 'ExternalWikiService' | true | true
+ 'ExternalWikiService' | false | false
+ 'SlackService' | true | false
+ end
+
+ with_them do
+ it 'returns the right result' do
+ expect(build(:service, type: type, active: active).external_wiki?).to eq(result)
+ end
+ end
+ end
+
+ describe '.available_services_names' do
+ it 'calls the right methods' do
+ expect(described_class).to receive(:services_names).and_call_original
+ expect(described_class).to receive(:dev_services_names).and_call_original
+ expect(described_class).to receive(:project_specific_services_names).and_call_original
+
+ described_class.available_services_names
+ end
+
+ it 'does not call project_specific_services_names with include_project_specific false' do
+ expect(described_class).to receive(:services_names).and_call_original
+ expect(described_class).to receive(:dev_services_names).and_call_original
+ expect(described_class).not_to receive(:project_specific_services_names)
+
+ described_class.available_services_names(include_project_specific: false)
+ end
+
+ it 'does not call dev_services_names with include_dev false' do
+ expect(described_class).to receive(:services_names).and_call_original
+ expect(described_class).not_to receive(:dev_services_names)
+ expect(described_class).to receive(:project_specific_services_names).and_call_original
+
+ described_class.available_services_names(include_dev: false)
+ end
end
end
diff --git a/spec/models/terraform/state_spec.rb b/spec/models/terraform/state_spec.rb
index 608c5bdf03a..ca8fe4cca3b 100644
--- a/spec/models/terraform/state_spec.rb
+++ b/spec/models/terraform/state_spec.rb
@@ -97,10 +97,11 @@ RSpec.describe Terraform::State do
end
describe '#update_file!' do
- let(:version) { 3 }
- let(:data) { Hash[terraform_version: '0.12.21'].to_json }
+ let_it_be(:build) { create(:ci_build) }
+ let_it_be(:version) { 3 }
+ let_it_be(:data) { Hash[terraform_version: '0.12.21'].to_json }
- subject { terraform_state.update_file!(CarrierWaveStringFile.new(data), version: version) }
+ subject { terraform_state.update_file!(CarrierWaveStringFile.new(data), version: version, build: build) }
context 'versioning is enabled' do
let(:terraform_state) { create(:terraform_state) }
@@ -109,6 +110,7 @@ RSpec.describe Terraform::State do
expect { subject }.to change { Terraform::StateVersion.count }
expect(terraform_state.latest_version.version).to eq(version)
+ expect(terraform_state.latest_version.build).to eq(build)
expect(terraform_state.latest_version.file.read).to eq(data)
end
end
diff --git a/spec/models/terraform/state_version_spec.rb b/spec/models/terraform/state_version_spec.rb
index cc5ea87159d..97ac77d5e7b 100644
--- a/spec/models/terraform/state_version_spec.rb
+++ b/spec/models/terraform/state_version_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Terraform::StateVersion do
it { is_expected.to belong_to(:terraform_state).required }
it { is_expected.to belong_to(:created_by_user).class_name('User').optional }
+ it { is_expected.to belong_to(:build).class_name('Ci::Build').optional }
describe 'scopes' do
describe '.ordered_by_version_desc' do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 64bff5d00aa..19a6a3ce3c4 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -319,7 +319,7 @@ RSpec.describe User do
expect(subject).to validate_presence_of(:username)
end
- it 'rejects blacklisted names' do
+ it 'rejects denied names' do
user = build(:user, username: 'dashboard')
expect(user).not_to be_valid
@@ -442,9 +442,9 @@ RSpec.describe User do
end
describe 'email' do
- context 'when no signup domains whitelisted' do
+ context 'when no signup domains allowed' do
before do
- allow_any_instance_of(ApplicationSetting).to receive(:domain_whitelist).and_return([])
+ allow_any_instance_of(ApplicationSetting).to receive(:domain_allowlist).and_return([])
end
it 'accepts any email' do
@@ -455,7 +455,7 @@ RSpec.describe User do
context 'bad regex' do
before do
- allow_any_instance_of(ApplicationSetting).to receive(:domain_whitelist).and_return(['([a-zA-Z0-9]+)+\.com'])
+ allow_any_instance_of(ApplicationSetting).to receive(:domain_allowlist).and_return(['([a-zA-Z0-9]+)+\.com'])
end
it 'does not hang on evil input' do
@@ -467,9 +467,9 @@ RSpec.describe User do
end
end
- context 'when a signup domain is whitelisted and subdomains are allowed' do
+ context 'when a signup domain is allowed and subdomains are allowed' do
before do
- allow_any_instance_of(ApplicationSetting).to receive(:domain_whitelist).and_return(['example.com', '*.example.com'])
+ allow_any_instance_of(ApplicationSetting).to receive(:domain_allowlist).and_return(['example.com', '*.example.com'])
end
it 'accepts info@example.com' do
@@ -488,9 +488,9 @@ RSpec.describe User do
end
end
- context 'when a signup domain is whitelisted and subdomains are not allowed' do
+ context 'when a signup domain is allowed and subdomains are not allowed' do
before do
- allow_any_instance_of(ApplicationSetting).to receive(:domain_whitelist).and_return(['example.com'])
+ allow_any_instance_of(ApplicationSetting).to receive(:domain_allowlist).and_return(['example.com'])
end
it 'accepts info@example.com' do
@@ -514,15 +514,15 @@ RSpec.describe User do
end
end
- context 'domain blacklist' do
+ context 'domain denylist' do
before do
- allow_any_instance_of(ApplicationSetting).to receive(:domain_blacklist_enabled?).and_return(true)
- allow_any_instance_of(ApplicationSetting).to receive(:domain_blacklist).and_return(['example.com'])
+ allow_any_instance_of(ApplicationSetting).to receive(:domain_denylist_enabled?).and_return(true)
+ allow_any_instance_of(ApplicationSetting).to receive(:domain_denylist).and_return(['example.com'])
end
context 'bad regex' do
before do
- allow_any_instance_of(ApplicationSetting).to receive(:domain_blacklist).and_return(['([a-zA-Z0-9]+)+\.com'])
+ allow_any_instance_of(ApplicationSetting).to receive(:domain_denylist).and_return(['([a-zA-Z0-9]+)+\.com'])
end
it 'does not hang on evil input' do
@@ -534,7 +534,7 @@ RSpec.describe User do
end
end
- context 'when a signup domain is blacklisted' do
+ context 'when a signup domain is denied' do
it 'accepts info@test.com' do
user = build(:user, email: 'info@test.com')
expect(user).to be_valid
@@ -551,13 +551,13 @@ RSpec.describe User do
end
end
- context 'when a signup domain is blacklisted but a wildcard subdomain is allowed' do
+ context 'when a signup domain is denied but a wildcard subdomain is allowed' do
before do
- allow_any_instance_of(ApplicationSetting).to receive(:domain_blacklist).and_return(['test.example.com'])
- allow_any_instance_of(ApplicationSetting).to receive(:domain_whitelist).and_return(['*.example.com'])
+ allow_any_instance_of(ApplicationSetting).to receive(:domain_denylist).and_return(['test.example.com'])
+ allow_any_instance_of(ApplicationSetting).to receive(:domain_allowlist).and_return(['*.example.com'])
end
- it 'gives priority to whitelist and allow info@test.example.com' do
+ it 'gives priority to allowlist and allow info@test.example.com' do
user = build(:user, email: 'info@test.example.com')
expect(user).to be_valid
end
@@ -565,7 +565,7 @@ RSpec.describe User do
context 'with both lists containing a domain' do
before do
- allow_any_instance_of(ApplicationSetting).to receive(:domain_whitelist).and_return(['test.com'])
+ allow_any_instance_of(ApplicationSetting).to receive(:domain_allowlist).and_return(['test.com'])
end
it 'accepts info@test.com' do
@@ -1740,6 +1740,16 @@ RSpec.describe User do
end
end
+ describe '.instance_access_request_approvers_to_be_notified' do
+ let_it_be(:admin_list) { create_list(:user, 12, :admin, :with_sign_ins) }
+
+ it 'returns up to the ten most recently active instance admins' do
+ active_admins_in_recent_sign_in_desc_order = User.admins.active.order_recent_sign_in.limit(10)
+
+ expect(User.instance_access_request_approvers_to_be_notified).to eq(active_admins_in_recent_sign_in_desc_order)
+ end
+ end
+
describe '.filter_items' do
let(:user) { double }
@@ -2906,6 +2916,34 @@ RSpec.describe User do
subject { user.authorized_groups }
it { is_expected.to contain_exactly private_group, project_group }
+
+ context 'with shared memberships' do
+ let!(:shared_group) { create(:group) }
+ let!(:other_group) { create(:group) }
+
+ before do
+ create(:group_group_link, shared_group: shared_group, shared_with_group: private_group)
+ create(:group_group_link, shared_group: private_group, shared_with_group: other_group)
+ end
+
+ context 'when shared_group_membership_auth is enabled' do
+ before do
+ stub_feature_flags(shared_group_membership_auth: user)
+ end
+
+ it { is_expected.to include shared_group }
+ it { is_expected.not_to include other_group }
+ end
+
+ context 'when shared_group_membership_auth is disabled' do
+ before do
+ stub_feature_flags(shared_group_membership_auth: false)
+ end
+
+ it { is_expected.not_to include shared_group }
+ it { is_expected.not_to include other_group }
+ end
+ end
end
describe '#membership_groups' do
@@ -3637,9 +3675,9 @@ RSpec.describe User do
end
end
- context 'when a domain whitelist is in place' do
+ context 'when a domain allowlist is in place' do
before do
- stub_application_setting(domain_whitelist: ['gitlab.com'])
+ stub_application_setting(domain_allowlist: ['gitlab.com'])
end
it 'creates a ghost user' do
diff --git a/spec/policies/alert_management/http_integration_policy_spec.rb b/spec/policies/alert_management/http_integration_policy_spec.rb
new file mode 100644
index 00000000000..8e8348ad7f5
--- /dev/null
+++ b/spec/policies/alert_management/http_integration_policy_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AlertManagement::HttpIntegrationPolicy, :models do
+ let(:integration) { create(:alert_management_http_integration) }
+ let(:project) { integration.project }
+ let(:user) { create(:user) }
+
+ subject(:policy) { described_class.new(user, integration) }
+
+ describe 'rules' do
+ it { is_expected.to be_disallowed :admin_operations }
+
+ context 'when maintainer' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it { is_expected.to be_allowed :admin_operations }
+ end
+ end
+end
diff --git a/spec/policies/base_policy_spec.rb b/spec/policies/base_policy_spec.rb
index 103f2e9bc39..226660dc955 100644
--- a/spec/policies/base_policy_spec.rb
+++ b/spec/policies/base_policy_spec.rb
@@ -22,6 +22,34 @@ RSpec.describe BasePolicy do
end
end
+ shared_examples 'admin only access' do |policy|
+ let(:current_user) { build_stubbed(:user) }
+
+ subject { described_class.new(current_user, nil) }
+
+ it { is_expected.not_to be_allowed(policy) }
+
+ context 'for admins' do
+ let(:current_user) { build_stubbed(:admin) }
+
+ it 'allowed when in admin mode' do
+ enable_admin_mode!(current_user)
+
+ is_expected.to be_allowed(policy)
+ end
+
+ it 'prevented when not in admin mode' do
+ is_expected.not_to be_allowed(policy)
+ end
+ end
+
+ context 'for anonymous' do
+ let(:current_user) { nil }
+
+ it { is_expected.not_to be_allowed(policy) }
+ end
+ end
+
describe 'read cross project' do
let(:current_user) { build_stubbed(:user) }
let(:user) { build_stubbed(:user) }
@@ -41,51 +69,15 @@ RSpec.describe BasePolicy do
enable_external_authorization_service_check
end
- it { is_expected.not_to be_allowed(:read_cross_project) }
-
- context 'for admins' do
- let(:current_user) { build_stubbed(:admin) }
-
- subject { described_class.new(current_user, nil) }
-
- it 'allowed when in admin mode' do
- enable_admin_mode!(current_user)
-
- is_expected.to be_allowed(:read_cross_project)
- end
-
- it 'prevented when not in admin mode' do
- is_expected.not_to be_allowed(:read_cross_project)
- end
- end
-
- context 'for anonymous' do
- let(:current_user) { nil }
-
- it { is_expected.not_to be_allowed(:read_cross_project) }
- end
+ it_behaves_like 'admin only access', :read_cross_project
end
end
describe 'full private access' do
- let(:current_user) { build_stubbed(:user) }
-
- subject { described_class.new(current_user, nil) }
-
- it { is_expected.not_to be_allowed(:read_all_resources) }
-
- context 'for admins' do
- let(:current_user) { build_stubbed(:admin) }
-
- it 'allowed when in admin mode' do
- enable_admin_mode!(current_user)
-
- is_expected.to be_allowed(:read_all_resources)
- end
+ it_behaves_like 'admin only access', :read_all_resources
+ end
- it 'prevented when not in admin mode' do
- is_expected.not_to be_allowed(:read_all_resources)
- end
- end
+ describe 'change_repository_storage' do
+ it_behaves_like 'admin only access', :change_repository_storage
end
end
diff --git a/spec/policies/blob_policy_spec.rb b/spec/policies/blob_policy_spec.rb
index fc46b25f25c..daabcd844af 100644
--- a/spec/policies/blob_policy_spec.rb
+++ b/spec/policies/blob_policy_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe BlobPolicy, :enable_admin_mode do
+RSpec.describe BlobPolicy do
include_context 'ProjectPolicyTable context'
include ProjectHelpers
using RSpec::Parameterized::TableSyntax
@@ -13,12 +13,13 @@ RSpec.describe BlobPolicy, :enable_admin_mode do
subject(:policy) { described_class.new(user, blob) }
- where(:project_level, :feature_access_level, :membership, :expected_count) do
+ where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
permission_table_for_guest_feature_access_and_non_private_project_only
end
with_them do
it "grants permission" do
+ enable_admin_mode!(user) if admin_mode
update_feature_access_level(project, feature_access_level)
if expected_count == 1
diff --git a/spec/policies/group_member_policy_spec.rb b/spec/policies/group_member_policy_spec.rb
index 4215fa09301..9e58ea81ef3 100644
--- a/spec/policies/group_member_policy_spec.rb
+++ b/spec/policies/group_member_policy_spec.rb
@@ -42,6 +42,7 @@ RSpec.describe GroupMemberPolicy do
it do
expect_disallowed(:destroy_group_member)
expect_disallowed(:update_group_member)
+ expect_allowed(:read_group)
end
end
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index fecf5f3e4f8..7cded27e449 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -876,10 +876,30 @@ RSpec.describe GroupPolicy do
let(:deploy_token) { create(:deploy_token, :group, write_package_registry: true) }
it { is_expected.to be_allowed(:create_package) }
+ it { is_expected.to be_allowed(:read_package) }
it { is_expected.to be_allowed(:read_group) }
it { is_expected.to be_disallowed(:destroy_package) }
end
end
it_behaves_like 'Self-managed Core resource access tokens'
+
+ context 'support bot' do
+ let_it_be(:group) { create(:group, :private) }
+ let_it_be(:current_user) { User.support_bot }
+
+ before do
+ allow(Gitlab::ServiceDesk).to receive(:supported?).and_return(true)
+ end
+
+ it { expect_disallowed(:read_label) }
+
+ context 'when group hierarchy has a project with service desk enabled' do
+ let_it_be(:subgroup) { create(:group, :private, parent: group)}
+ let_it_be(:project) { create(:project, group: subgroup, service_desk_enabled: true) }
+
+ it { expect_allowed(:read_label) }
+ it { expect(described_class.new(current_user, subgroup)).to be_allowed(:read_label) }
+ end
+ end
end
diff --git a/spec/policies/instance_metadata_policy_spec.rb b/spec/policies/instance_metadata_policy_spec.rb
new file mode 100644
index 00000000000..2c8e18483e6
--- /dev/null
+++ b/spec/policies/instance_metadata_policy_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe InstanceMetadataPolicy do
+ subject { described_class.new(user, InstanceMetadata.new) }
+
+ context 'for any logged-in user' do
+ let(:user) { create(:user) }
+
+ specify { expect_allowed(:read_instance_metadata) }
+ end
+
+ context 'for anonymous users' do
+ let(:user) { nil }
+
+ specify { expect_disallowed(:read_instance_metadata) }
+ end
+end
diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb
index e352b990159..76788ae2cb7 100644
--- a/spec/policies/issue_policy_spec.rb
+++ b/spec/policies/issue_policy_spec.rb
@@ -139,8 +139,13 @@ RSpec.describe IssuePolicy do
create(:project_group_link, group: group, project: project)
end
+ it 'does not allow guest to create todos' do
+ expect(permissions(nil, issue)).to be_allowed(:read_issue)
+ expect(permissions(nil, issue)).to be_disallowed(:create_todo)
+ end
+
it 'allows guests to read issues' do
- expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid)
+ expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid, :create_todo)
expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue)
expect(permissions(guest, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
diff --git a/spec/policies/merge_request_policy_spec.rb b/spec/policies/merge_request_policy_spec.rb
index 3a46d5b9226..744822f58d1 100644
--- a/spec/policies/merge_request_policy_spec.rb
+++ b/spec/policies/merge_request_policy_spec.rb
@@ -24,6 +24,7 @@ RSpec.describe MergeRequestPolicy do
mr_perms = %i[create_merge_request_in
create_merge_request_from
read_merge_request
+ create_todo
approve_merge_request
create_note].freeze
@@ -47,6 +48,18 @@ RSpec.describe MergeRequestPolicy do
end
end
+ context 'when merge request is public' do
+ context 'and user is anonymous' do
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: author) }
+
+ subject { permissions(nil, merge_request) }
+
+ it do
+ is_expected.to be_disallowed(:create_todo)
+ end
+ end
+ end
+
context 'when merge requests have been disabled' do
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: author) }
diff --git a/spec/policies/note_policy_spec.rb b/spec/policies/note_policy_spec.rb
index a4cc3a1e9af..f6cd84f29ae 100644
--- a/spec/policies/note_policy_spec.rb
+++ b/spec/policies/note_policy_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe NotePolicy do
- describe '#rules' do
+ describe '#rules', :aggregate_failures do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
let(:issue) { create(:issue, project: project) }
@@ -11,14 +11,15 @@ RSpec.describe NotePolicy do
let(:policy) { described_class.new(user, note) }
let(:note) { create(:note, noteable: noteable, author: user, project: project) }
+ shared_examples_for 'user cannot read or act on the note' do
+ specify do
+ expect(policy).to be_disallowed(:admin_note, :reposition_note, :resolve_note, :read_note, :award_emoji)
+ end
+ end
+
shared_examples_for 'a discussion with a private noteable' do
context 'when the note author can no longer see the noteable' do
- it 'can not edit nor read the note' do
- expect(policy).to be_disallowed(:admin_note)
- expect(policy).to be_disallowed(:resolve_note)
- expect(policy).to be_disallowed(:read_note)
- expect(policy).to be_disallowed(:award_emoji)
- end
+ it_behaves_like 'user cannot read or act on the note'
end
context 'when the note author can still see the noteable' do
@@ -28,6 +29,7 @@ RSpec.describe NotePolicy do
it 'can edit the note' do
expect(policy).to be_allowed(:admin_note)
+ expect(policy).to be_allowed(:reposition_note)
expect(policy).to be_allowed(:resolve_note)
expect(policy).to be_allowed(:read_note)
expect(policy).to be_allowed(:award_emoji)
@@ -35,6 +37,13 @@ RSpec.describe NotePolicy do
end
end
+ shared_examples_for 'a note on a public noteable' do
+ it 'can only read and award emoji on the note' do
+ expect(policy).to be_allowed(:read_note, :award_emoji)
+ expect(policy).to be_disallowed(:reposition_note, :admin_note, :resolve_note)
+ end
+ end
+
context 'when the noteable is a deleted commit' do
let(:commit) { nil }
let(:note) { create(:note_on_commit, commit_id: '12345678', author: user, project: project) }
@@ -42,6 +51,7 @@ RSpec.describe NotePolicy do
it 'allows to read' do
expect(policy).to be_allowed(:read_note)
expect(policy).to be_disallowed(:admin_note)
+ expect(policy).to be_disallowed(:reposition_note)
expect(policy).to be_disallowed(:resolve_note)
expect(policy).to be_disallowed(:award_emoji)
end
@@ -66,31 +76,60 @@ RSpec.describe NotePolicy do
end
end
+ context 'when the noteable is a Design' do
+ include DesignManagementTestHelpers
+
+ let(:note) { create(:note, noteable: noteable, project: project) }
+ let(:noteable) { create(:design, issue: issue) }
+
+ before do
+ enable_design_management
+ end
+
+ it 'can read, award emoji and reposition the note' do
+ expect(policy).to be_allowed(:reposition_note, :read_note, :award_emoji)
+ expect(policy).to be_disallowed(:admin_note, :resolve_note)
+ end
+
+ context 'when project is private' do
+ let(:project) { create(:project, :private) }
+
+ it_behaves_like 'user cannot read or act on the note'
+ end
+ end
+
context 'when the noteable is a personal snippet' do
let(:noteable) { create(:personal_snippet, :public) }
- let(:note) { create(:note, noteable: noteable, author: user) }
+ let(:note) { create(:note, noteable: noteable) }
- it 'can edit note' do
- expect(policy).to be_allowed(:admin_note)
- expect(policy).to be_allowed(:resolve_note)
- expect(policy).to be_allowed(:read_note)
- end
+ it_behaves_like 'a note on a public noteable'
+
+ context 'when user is the author of the personal snippet' do
+ let(:note) { create(:note, noteable: noteable, author: user) }
- context 'when it is private' do
- let(:noteable) { create(:personal_snippet, :private) }
+ it 'can edit note' do
+ expect(policy).to be_allowed(:read_note, :award_emoji, :admin_note, :reposition_note, :resolve_note)
+ end
+
+ context 'when it is private' do
+ let(:noteable) { create(:personal_snippet, :private) }
- it 'can not edit nor read the note' do
- expect(policy).to be_disallowed(:admin_note)
- expect(policy).to be_disallowed(:resolve_note)
- expect(policy).to be_disallowed(:read_note)
+ it_behaves_like 'user cannot read or act on the note'
end
end
end
context 'when the project is public' do
+ context 'when user is not the author of the note' do
+ let(:note) { create(:note, noteable: noteable, project: project) }
+
+ it_behaves_like 'a note on a public noteable'
+ end
+
context 'when the note author is not a project member' do
it 'can edit a note' do
expect(policy).to be_allowed(:admin_note)
+ expect(policy).to be_allowed(:reposition_note)
expect(policy).to be_allowed(:resolve_note)
expect(policy).to be_allowed(:read_note)
end
@@ -101,6 +140,7 @@ RSpec.describe NotePolicy do
it 'can edit note' do
expect(policy).to be_allowed(:admin_note)
+ expect(policy).to be_allowed(:reposition_note)
expect(policy).to be_allowed(:resolve_note)
expect(policy).to be_allowed(:read_note)
end
@@ -132,6 +172,7 @@ RSpec.describe NotePolicy do
it 'can edit a note' do
expect(policy).to be_allowed(:admin_note)
+ expect(policy).to be_allowed(:reposition_note)
expect(policy).to be_allowed(:resolve_note)
expect(policy).to be_allowed(:read_note)
end
@@ -140,6 +181,7 @@ RSpec.describe NotePolicy do
context 'when the note author is not a project member' do
it 'can not edit a note' do
expect(policy).to be_disallowed(:admin_note)
+ expect(policy).to be_disallowed(:reposition_note)
expect(policy).to be_disallowed(:resolve_note)
end
@@ -154,6 +196,7 @@ RSpec.describe NotePolicy do
it 'allows the author to manage the discussion' do
expect(policy).to be_allowed(:admin_note)
+ expect(policy).to be_allowed(:reposition_note)
expect(policy).to be_allowed(:resolve_note)
expect(policy).to be_allowed(:read_note)
expect(policy).to be_allowed(:award_emoji)
@@ -180,21 +223,13 @@ RSpec.describe NotePolicy do
shared_examples_for 'user can act on the note' do
it 'allows the user to read the note' do
- expect(policy).not_to be_allowed(:admin_note)
+ expect(policy).to be_disallowed(:admin_note)
+ expect(policy).to be_disallowed(:reposition_note)
expect(policy).to be_allowed(:resolve_note)
expect(policy).to be_allowed(:award_emoji)
end
end
- shared_examples_for 'user cannot read or act on the note' do
- it 'allows user to read the note' do
- expect(policy).not_to be_allowed(:admin_note)
- expect(policy).not_to be_allowed(:resolve_note)
- expect(policy).not_to be_allowed(:read_note)
- expect(policy).not_to be_allowed(:award_emoji)
- end
- end
-
context 'when noteable is a public issue' do
let(:note) { create(:note, system: true, noteable: noteable, author: user, project: project) }
@@ -274,42 +309,42 @@ RSpec.describe NotePolicy do
shared_examples_for 'confidential notes permissions' do
it 'does not allow non members to read confidential notes and replies' do
- expect(permissions(non_member, confidential_note)).to be_disallowed(:read_note, :admin_note, :resolve_note, :award_emoji)
+ expect(permissions(non_member, confidential_note)).to be_disallowed(:read_note, :admin_note, :reposition_note, :resolve_note, :award_emoji)
end
it 'does not allow guests to read confidential notes and replies' do
- expect(permissions(guest, confidential_note)).to be_disallowed(:read_note, :admin_note, :resolve_note, :award_emoji)
+ expect(permissions(guest, confidential_note)).to be_disallowed(:read_note, :admin_note, :reposition_note, :resolve_note, :award_emoji)
end
it 'allows reporter to read all notes but not resolve and admin them' do
expect(permissions(reporter, confidential_note)).to be_allowed(:read_note, :award_emoji)
- expect(permissions(reporter, confidential_note)).to be_disallowed(:admin_note, :resolve_note)
+ expect(permissions(reporter, confidential_note)).to be_disallowed(:admin_note, :reposition_note, :resolve_note)
end
it 'allows developer to read and resolve all notes' do
expect(permissions(developer, confidential_note)).to be_allowed(:read_note, :award_emoji, :resolve_note)
- expect(permissions(developer, confidential_note)).to be_disallowed(:admin_note)
+ expect(permissions(developer, confidential_note)).to be_disallowed(:admin_note, :reposition_note)
end
it 'allows maintainers to read all notes and admin them' do
- expect(permissions(maintainer, confidential_note)).to be_allowed(:read_note, :admin_note, :resolve_note, :award_emoji)
+ expect(permissions(maintainer, confidential_note)).to be_allowed(:read_note, :admin_note, :reposition_note, :resolve_note, :award_emoji)
end
context 'when admin mode is enabled', :enable_admin_mode do
it 'allows admins to read all notes and admin them' do
- expect(permissions(admin, confidential_note)).to be_allowed(:read_note, :admin_note, :resolve_note, :award_emoji)
+ expect(permissions(admin, confidential_note)).to be_allowed(:read_note, :admin_note, :reposition_note, :resolve_note, :award_emoji)
end
end
context 'when admin mode is disabled' do
it 'does not allow non members to read confidential notes and replies' do
- expect(permissions(admin, confidential_note)).to be_disallowed(:read_note, :admin_note, :resolve_note, :award_emoji)
+ expect(permissions(admin, confidential_note)).to be_disallowed(:read_note, :admin_note, :reposition_note, :resolve_note, :award_emoji)
end
end
it 'allows noteable author to read and resolve all notes' do
expect(permissions(author, confidential_note)).to be_allowed(:read_note, :resolve_note, :award_emoji)
- expect(permissions(author, confidential_note)).to be_disallowed(:admin_note)
+ expect(permissions(author, confidential_note)).to be_disallowed(:admin_note, :reposition_note)
end
end
@@ -321,7 +356,7 @@ RSpec.describe NotePolicy do
it 'allows noteable assignees to read all notes' do
expect(permissions(assignee, confidential_note)).to be_allowed(:read_note, :award_emoji)
- expect(permissions(assignee, confidential_note)).to be_disallowed(:admin_note, :resolve_note)
+ expect(permissions(assignee, confidential_note)).to be_disallowed(:admin_note, :reposition_note, :resolve_note)
end
end
@@ -333,7 +368,7 @@ RSpec.describe NotePolicy do
it 'allows noteable assignees to read all notes' do
expect(permissions(assignee, confidential_note)).to be_allowed(:read_note, :award_emoji)
- expect(permissions(assignee, confidential_note)).to be_disallowed(:admin_note, :resolve_note)
+ expect(permissions(assignee, confidential_note)).to be_disallowed(:admin_note, :reposition_note, :resolve_note)
end
end
@@ -350,11 +385,11 @@ RSpec.describe NotePolicy do
it 'allows snippet author to read and resolve all notes' do
expect(permissions(author, confidential_note)).to be_allowed(:read_note, :resolve_note, :award_emoji)
- expect(permissions(author, confidential_note)).to be_disallowed(:admin_note)
+ expect(permissions(author, confidential_note)).to be_disallowed(:admin_note, :reposition_note)
end
it 'does not allow maintainers to read confidential notes and replies' do
- expect(permissions(maintainer, confidential_note)).to be_disallowed(:read_note, :admin_note, :resolve_note, :award_emoji)
+ expect(permissions(maintainer, confidential_note)).to be_disallowed(:read_note, :admin_note, :reposition_note, :resolve_note, :award_emoji)
end
end
end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index b28fb9a0255..6c281030618 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -697,6 +697,7 @@ RSpec.describe ProjectPolicy do
let(:deploy_token) { create(:deploy_token, write_package_registry: true) }
it { is_expected.to be_allowed(:create_package) }
+ it { is_expected.to be_allowed(:read_package) }
it { is_expected.to be_allowed(:read_project) }
it { is_expected.to be_disallowed(:destroy_package) }
end
diff --git a/spec/policies/service_policy_spec.rb b/spec/policies/service_policy_spec.rb
new file mode 100644
index 00000000000..5d2c9c1f6c3
--- /dev/null
+++ b/spec/policies/service_policy_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ServicePolicy, :models do
+ let_it_be(:user) { create(:user) }
+ let(:project) { integration.project }
+
+ subject(:policy) { Ability.policy_for(user, integration) }
+
+ context 'when the integration is a prometheus_service' do
+ let(:integration) { create(:prometheus_service) }
+
+ describe 'rules' do
+ it { is_expected.to be_disallowed :admin_project }
+
+ context 'when maintainer' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it { is_expected.to be_allowed :admin_project }
+ end
+ end
+ end
+end
diff --git a/spec/policies/terraform/state_version_policy_spec.rb b/spec/policies/terraform/state_version_policy_spec.rb
new file mode 100644
index 00000000000..6614e073332
--- /dev/null
+++ b/spec/policies/terraform/state_version_policy_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Terraform::StateVersionPolicy do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:terraform_state) { create(:terraform_state, :with_version, project: project)}
+
+ subject { described_class.new(user, terraform_state.latest_version) }
+
+ describe 'rules' do
+ context 'no access' do
+ let(:user) { create(:user) }
+
+ it { is_expected.to be_disallowed(:read_terraform_state) }
+ it { is_expected.to be_disallowed(:admin_terraform_state) }
+ end
+
+ context 'developer' do
+ let(:user) { create(:user, developer_projects: [project]) }
+
+ it { is_expected.to be_allowed(:read_terraform_state) }
+ it { is_expected.to be_disallowed(:admin_terraform_state) }
+ end
+
+ context 'maintainer' do
+ let(:user) { create(:user, maintainer_projects: [project]) }
+
+ it { is_expected.to be_allowed(:read_terraform_state) }
+ it { is_expected.to be_allowed(:admin_terraform_state) }
+ end
+ end
+end
diff --git a/spec/policies/user_policy_spec.rb b/spec/policies/user_policy_spec.rb
index 38641558b6b..17ac7d0e44d 100644
--- a/spec/policies/user_policy_spec.rb
+++ b/spec/policies/user_policy_spec.rb
@@ -40,6 +40,46 @@ RSpec.describe UserPolicy do
end
end
+ describe "creating a different user's Personal Access Tokens" do
+ context 'when current_user is admin' do
+ let(:current_user) { create(:user, :admin) }
+
+ context 'when admin mode is enabled and current_user is not blocked', :enable_admin_mode do
+ it { is_expected.to be_allowed(:create_user_personal_access_token) }
+ end
+
+ context 'when admin mode is enabled and current_user is blocked', :enable_admin_mode do
+ let(:current_user) { create(:admin, :blocked) }
+
+ it { is_expected.not_to be_allowed(:create_user_personal_access_token) }
+ end
+
+ context 'when admin mode is disabled' do
+ it { is_expected.not_to be_allowed(:create_user_personal_access_token) }
+ end
+ end
+
+ context 'when current_user is not an admin' do
+ context 'creating their own personal access tokens' do
+ subject { described_class.new(current_user, current_user) }
+
+ context 'when current_user is not blocked' do
+ it { is_expected.to be_allowed(:create_user_personal_access_token) }
+ end
+
+ context 'when current_user is blocked' do
+ let(:current_user) { create(:user, :blocked) }
+
+ it { is_expected.not_to be_allowed(:create_user_personal_access_token) }
+ end
+ end
+
+ context "creating a different user's personal access tokens" do
+ it { is_expected.not_to be_allowed(:create_user_personal_access_token) }
+ end
+ end
+ end
+
shared_examples 'changing a user' do |ability|
context "when a regular user tries to destroy another regular user" do
it { is_expected.not_to be_allowed(ability) }
@@ -102,4 +142,22 @@ RSpec.describe UserPolicy do
end
end
end
+
+ describe "reading a user's group count" do
+ context "when current_user is an admin", :enable_admin_mode do
+ let(:current_user) { create(:user, :admin) }
+
+ it { is_expected.to be_allowed(:read_group_count) }
+ end
+
+ context "for self users" do
+ let(:user) { current_user }
+
+ it { is_expected.to be_allowed(:read_group_count) }
+ end
+
+ context "when accessing a different user's group count" do
+ it { is_expected.not_to be_allowed(:read_group_count) }
+ end
+ end
end
diff --git a/spec/policies/wiki_page_policy_spec.rb b/spec/policies/wiki_page_policy_spec.rb
index 093db9f8374..a2fa7f29135 100644
--- a/spec/policies/wiki_page_policy_spec.rb
+++ b/spec/policies/wiki_page_policy_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe WikiPagePolicy, :enable_admin_mode do
+RSpec.describe WikiPagePolicy do
include_context 'ProjectPolicyTable context'
include ProjectHelpers
using RSpec::Parameterized::TableSyntax
@@ -13,12 +13,13 @@ RSpec.describe WikiPagePolicy, :enable_admin_mode do
subject(:policy) { described_class.new(user, wiki_page) }
- where(:project_level, :feature_access_level, :membership, :expected_count) do
+ where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
permission_table_for_guest_feature_access
end
with_them do
it "grants permission" do
+ enable_admin_mode!(user) if admin_mode
update_feature_access_level(project, feature_access_level)
if expected_count == 1
diff --git a/spec/presenters/issue_presenter_spec.rb b/spec/presenters/issue_presenter_spec.rb
index f08cd0f2026..55a6b50ffa7 100644
--- a/spec/presenters/issue_presenter_spec.rb
+++ b/spec/presenters/issue_presenter_spec.rb
@@ -40,4 +40,20 @@ RSpec.describe IssuePresenter do
expect(presenter.issue_path).to eq("/#{group.name}/#{project.name}/-/issues/#{issue.iid}")
end
end
+
+ describe '#project_emails_disabled?' do
+ subject { presenter.project_emails_disabled? }
+
+ it 'returns false when emails notifications is enabled for project' do
+ is_expected.to be(false)
+ end
+
+ context 'when emails notifications is disabled for project' do
+ before do
+ allow(project).to receive(:emails_disabled?).and_return(true)
+ end
+
+ it { is_expected.to be(true) }
+ end
+ end
end
diff --git a/spec/presenters/packages/detail/package_presenter_spec.rb b/spec/presenters/packages/detail/package_presenter_spec.rb
index 8ece27e9b5f..e38bbbe600c 100644
--- a/spec/presenters/packages/detail/package_presenter_spec.rb
+++ b/spec/presenters/packages/detail/package_presenter_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe ::Packages::Detail::PackagePresenter do
end
let(:pipeline_info) do
- pipeline = package.build_info.pipeline
+ pipeline = package.original_build_info.pipeline
{
created_at: pipeline.created_at,
id: pipeline.id,
@@ -56,16 +56,44 @@ RSpec.describe ::Packages::Detail::PackagePresenter do
}
end
- context 'detail_view' do
+ describe '#detail_view' do
context 'with build_info' do
let_it_be(:package) { create(:npm_package, :with_build, project: project) }
- let(:expected_package_details) { super().merge(pipeline: pipeline_info) }
+
+ let(:expected_package_details) do
+ super().merge(
+ pipeline: pipeline_info,
+ pipelines: [pipeline_info]
+ )
+ end
it 'returns details with pipeline' do
expect(presenter.detail_view).to match expected_package_details
end
end
+ context 'with multiple build_infos' do
+ let_it_be(:package) { create(:npm_package, :with_build, project: project) }
+ let_it_be(:build_info2) { create(:package_build_info, :with_pipeline, package: package) }
+
+ it 'returns details with two pipelines' do
+ expect(presenter.detail_view[:pipelines].size).to eq(2)
+ end
+ end
+
+ context 'with package_file_build_infos' do
+ let_it_be(:package) { create(:npm_package, :with_build, project: project) }
+
+ let_it_be(:package_file_build_info) do
+ create(:package_file_build_info, package_file: package.package_files.first,
+ pipeline: package.pipelines.first)
+ end
+
+ it 'returns details with package_file pipeline' do
+ expect(presenter.detail_view[:package_files].first[:pipelines].size).to eq(1)
+ end
+ end
+
context 'without build info' do
let_it_be(:package) { create(:npm_package, project: project) }
diff --git a/spec/presenters/release_presenter_spec.rb b/spec/presenters/release_presenter_spec.rb
index eb4d755205b..b518584569b 100644
--- a/spec/presenters/release_presenter_spec.rb
+++ b/spec/presenters/release_presenter_spec.rb
@@ -12,6 +12,11 @@ RSpec.describe ReleasePresenter do
let(:release) { create(:release, project: project) }
let(:presenter) { described_class.new(release, current_user: user) }
+ let(:base_url_params) { { scope: 'all', release_tag: release.tag } }
+ let(:opened_url_params) { { state: 'opened', **base_url_params } }
+ let(:merged_url_params) { { state: 'merged', **base_url_params } }
+ let(:closed_url_params) { { state: 'closed', **base_url_params } }
+
before do
project.add_developer(developer)
project.add_guest(guest)
@@ -55,15 +60,63 @@ RSpec.describe ReleasePresenter do
subject { presenter.self_url }
it 'returns its own url' do
- is_expected.to match /#{project_release_url(project, release)}/
+ is_expected.to eq(project_release_url(project, release))
+ end
+ end
+
+ describe '#opened_merge_requests_url' do
+ subject { presenter.opened_merge_requests_url }
+
+ it 'returns merge requests url with state=open' do
+ is_expected.to eq(project_merge_requests_url(project, opened_url_params))
+ end
+
+ context 'when release_mr_issue_urls feature flag is disabled' do
+ before do
+ stub_feature_flags(release_mr_issue_urls: false)
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '#merged_merge_requests_url' do
+ subject { presenter.merged_merge_requests_url }
+
+ it 'returns merge requests url with state=merged' do
+ is_expected.to eq(project_merge_requests_url(project, merged_url_params))
+ end
+
+ context 'when release_mr_issue_urls feature flag is disabled' do
+ before do
+ stub_feature_flags(release_mr_issue_urls: false)
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '#closed_merge_requests_url' do
+ subject { presenter.closed_merge_requests_url }
+
+ it 'returns merge requests url with state=closed' do
+ is_expected.to eq(project_merge_requests_url(project, closed_url_params))
+ end
+
+ context 'when release_mr_issue_urls feature flag is disabled' do
+ before do
+ stub_feature_flags(release_mr_issue_urls: false)
+ end
+
+ it { is_expected.to be_nil }
end
end
- describe '#merge_requests_url' do
- subject { presenter.merge_requests_url }
+ describe '#opened_issues_url' do
+ subject { presenter.opened_issues_url }
- it 'returns merge requests url' do
- is_expected.to match /#{project_merge_requests_url(project)}/
+ it 'returns issues url with state=open' do
+ is_expected.to eq(project_issues_url(project, opened_url_params))
end
context 'when release_mr_issue_urls feature flag is disabled' do
@@ -75,11 +128,11 @@ RSpec.describe ReleasePresenter do
end
end
- describe '#issues_url' do
- subject { presenter.issues_url }
+ describe '#closed_issues_url' do
+ subject { presenter.closed_issues_url }
- it 'returns merge requests url' do
- is_expected.to match /#{project_issues_url(project)}/
+ it 'returns issues url with state=closed' do
+ is_expected.to eq(project_issues_url(project, closed_url_params))
end
context 'when release_mr_issue_urls feature flag is disabled' do
@@ -95,7 +148,7 @@ RSpec.describe ReleasePresenter do
subject { presenter.edit_url }
it 'returns release edit url' do
- is_expected.to match /#{edit_project_release_url(project, release)}/
+ is_expected.to eq(edit_project_release_url(project, release))
end
context 'when a user is not allowed to update a release' do
diff --git a/spec/requests/api/admin/instance_clusters_spec.rb b/spec/requests/api/admin/instance_clusters_spec.rb
index 9d0661089a9..1052080aad4 100644
--- a/spec/requests/api/admin/instance_clusters_spec.rb
+++ b/spec/requests/api/admin/instance_clusters_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe ::API::Admin::InstanceClusters do
user: admin_user,
projects: [project])
end
+
let(:project_cluster_id) { project_cluster.id }
describe "GET /admin/clusters" do
diff --git a/spec/requests/api/api_spec.rb b/spec/requests/api/api_spec.rb
index 7d637757f38..3cc8764de4a 100644
--- a/spec/requests/api/api_spec.rb
+++ b/spec/requests/api/api_spec.rb
@@ -92,4 +92,36 @@ RSpec.describe API::API do
end
end
end
+
+ context 'application context' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.owner }
+
+ it 'logs all application context fields' do
+ allow_any_instance_of(Gitlab::GrapeLogging::Loggers::ContextLogger).to receive(:parameters) do
+ Labkit::Context.current.to_h.tap do |log_context|
+ expect(log_context).to match('correlation_id' => an_instance_of(String),
+ 'meta.caller_id' => '/api/:version/projects/:id/issues',
+ 'meta.project' => project.full_path,
+ 'meta.root_namespace' => project.namespace.full_path,
+ 'meta.user' => user.username,
+ 'meta.feature_category' => 'issue_tracking')
+ end
+ end
+
+ get(api("/projects/#{project.id}/issues", user))
+ end
+
+ it 'skips fields that do not apply' do
+ allow_any_instance_of(Gitlab::GrapeLogging::Loggers::ContextLogger).to receive(:parameters) do
+ Labkit::Context.current.to_h.tap do |log_context|
+ expect(log_context).to match('correlation_id' => an_instance_of(String),
+ 'meta.caller_id' => '/api/:version/users',
+ 'meta.feature_category' => 'users')
+ end
+ end
+
+ get(api('/users'))
+ end
+ end
end
diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb
index a63198c5407..36fc6101b84 100644
--- a/spec/requests/api/boards_spec.rb
+++ b/spec/requests/api/boards_spec.rb
@@ -35,7 +35,46 @@ RSpec.describe API::Boards do
it_behaves_like 'group and project boards', "/projects/:id/boards"
- describe "POST /projects/:id/boards/lists" do
+ describe "POST /projects/:id/boards" do
+ let(:url) { "/projects/#{board_parent.id}/boards" }
+
+ it 'creates a new issue board' do
+ post api(url, user), params: { name: 'foo' }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['name']).to eq('foo')
+ end
+
+ it 'fails to create a new board' do
+ post api(url, user), params: { some_name: 'foo' }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('name is missing')
+ end
+ end
+
+ describe "PUT /projects/:id/boards/:board_id" do
+ let(:url) { "/projects/#{board_parent.id}/boards/#{board.id}" }
+
+ it 'updates the issue board' do
+ put api(url, user), params: { name: 'changed board name' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['name']).to eq('changed board name')
+ end
+ end
+
+ describe "DELETE /projects/:id/boards/:board_id" do
+ let(:url) { "/projects/#{board_parent.id}/boards/#{board.id}" }
+
+ it 'delete the issue board' do
+ delete api(url, user)
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
+
+ describe "POST /projects/:id/boards/:board_id/lists" do
let(:url) { "/projects/#{board_parent.id}/boards/#{board.id}/lists" }
it 'creates a new issue board list for group labels' do
@@ -65,7 +104,7 @@ RSpec.describe API::Boards do
end
end
- describe "POST /groups/:id/boards/lists" do
+ describe "POST /groups/:id/boards/:board_id/lists" do
let_it_be(:group) { create(:group) }
let_it_be(:board_parent) { create(:group, parent: group ) }
let(:url) { "/groups/#{board_parent.id}/boards/#{board.id}/lists" }
diff --git a/spec/requests/api/ci/pipelines_spec.rb b/spec/requests/api/ci/pipelines_spec.rb
index 577b43e6e42..767b5704851 100644
--- a/spec/requests/api/ci/pipelines_spec.rb
+++ b/spec/requests/api/ci/pipelines_spec.rb
@@ -325,236 +325,113 @@ RSpec.describe API::Ci::Pipelines do
end
end
- context 'with ci_jobs_finder_refactor ff enabled' do
- before do
- stub_feature_flags(ci_jobs_finder_refactor: true)
+ 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
- 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
+ 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
- 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
+ it_behaves_like 'a job with artifacts and trace' do
+ let(:api_endpoint) { "/projects/#{project.id}/pipelines/#{pipeline.id}/jobs" }
end
- context 'unauthorized user' do
- context 'when user is not logged in' do
- let(:api_user) { nil }
+ it 'returns pipeline data' do
+ json_job = json_response.first
- 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
+ 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
- end
- context 'with ci_jobs_finder ff disabled' do
- before do
- stub_feature_flags(ci_jobs_finder_refactor: false)
- end
+ context 'filter jobs with one scope element' do
+ let(:query) { { 'scope' => 'pending' } }
- context 'authorized user' do
- it 'returns pipeline jobs' do
+ it do
expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
expect(json_response).to be_an Array
end
+ 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
+ context 'filter jobs with hash' do
+ let(:query) { { scope: { hello: 'pending', world: 'running' } } }
- 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
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
+ end
- context 'filter jobs with one scope element' do
- let(:query) { { 'scope' => 'pending' } }
+ 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
+ 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' } } }
+ 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
+ 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) } }
+ context 'jobs in different pipelines' do
+ let!(:pipeline2) { create(:ci_empty_pipeline, project: project) }
+ let!(:job2) { create(:ci_build, pipeline: pipeline2) }
- it do
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response).to be_an Array
- end
+ it 'excludes jobs from other pipelines' do
+ json_response.each { |job| expect(job['pipeline']['id']).to eq(pipeline.id) }
end
+ end
- context 'respond 400 when scope contains invalid state' do
- let(:query) { { scope: %w(unknown running) } }
+ 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
- it { expect(response).to have_gitlab_http_status(:bad_request) }
- end
+ create_list(:ci_build, 3, :trace_artifact, :artifacts, :test_reports, pipeline: pipeline)
- 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
+ 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
- create_list(:ci_build, 3, :trace_artifact, :artifacts, :test_reports, pipeline: pipeline)
+ context 'no pipeline is found' do
+ it 'does not return jobs' do
+ get api("/projects/#{project2.id}/pipelines/#{pipeline.id}/jobs", user)
- 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
+ expect(json_response['message']).to eq '404 Project Not Found'
+ expect(response).to have_gitlab_http_status(:not_found)
end
+ end
- context 'no pipeline is found' do
- it 'does not return jobs' do
- get api("/projects/#{project2.id}/pipelines/#{pipeline.id}/jobs", user)
+ 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 '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 }
- 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
+ it 'does not return jobs' do
+ expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
@@ -583,314 +460,152 @@ RSpec.describe API::Ci::Pipelines do
end
end
- context 'with ci_jobs_finder_refactor ff enabled' do
- before do
- stub_feature_flags(ci_jobs_finder_refactor: true)
+ 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
- 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 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
- 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
- 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
- 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
- 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
+ context 'filter bridges' do
+ before_all do
+ create_bridge(pipeline, :pending)
+ create_bridge(pipeline, :running)
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) } }
+ 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
+ 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
+ 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 '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 'with array of scope elements' do
+ let(:query) { { scope: %w(pending running) } }
- context 'in a string' do
- let(:query) { { scope: "unknown" } }
+ it :skip_before_request do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
- it { expect(response).to have_gitlab_http_status(:bad_request) }
+ 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 'bridges in different pipelines' do
- let!(:pipeline2) { create(:ci_empty_pipeline, project: project) }
- let!(:bridge2) { create(:ci_bridge, pipeline: pipeline2) }
+ context 'respond 400 when scope contains invalid state' do
+ context 'in an array' do
+ let(:query) { { scope: %w(unknown running) } }
- it 'excludes bridges from other pipelines' do
- json_response.each { |bridge| expect(bridge['pipeline']['id']).to eq(pipeline.id) }
- end
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
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) }
+ context 'in a hash' do
+ let(:query) { { scope: { unknown: true } } }
- expect do
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
- end.not_to exceed_all_query_limit(control_count)
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
end
- end
- context 'no pipeline is found' do
- it 'does not return bridges' do
- get api("/projects/#{project2.id}/pipelines/#{pipeline.id}/bridges", user)
+ context 'in a string' do
+ let(:query) { { scope: "unknown" } }
- expect(json_response['message']).to eq '404 Project Not Found'
- expect(response).to have_gitlab_http_status(:not_found)
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
end
end
- context 'unauthorized user' do
- context 'when user is not logged in' do
- let(:api_user) { nil }
+ context 'bridges in different pipelines' do
+ let!(:pipeline2) { create(:ci_empty_pipeline, project: project) }
+ let!(:bridge2) { create(:ci_bridge, pipeline: pipeline2) }
- 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
+ it 'excludes bridges from other pipelines' do
+ json_response.each { |bridge| expect(bridge['pipeline']['id']).to eq(pipeline.id) }
end
+ end
- context 'when user is guest' do
- let(:api_user) { guest }
- let(:guest) { create(:project_member, :guest, project: project).user }
+ 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
- it 'does not return bridges' do
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
+ 3.times { create_bridge(pipeline) }
- 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
+ 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 '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
+ context 'no pipeline is found' do
+ it 'does not return bridges' do
+ get api("/projects/#{project2.id}/pipelines/#{pipeline.id}/bridges", user)
- 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
+ expect(json_response['message']).to eq '404 Project Not Found'
+ expect(response).to have_gitlab_http_status(:not_found)
end
+ end
- context 'no pipeline is found' do
- it 'does not return bridges' do
- get api("/projects/#{project2.id}/pipelines/#{pipeline.id}/bridges", user)
+ 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 'unauthorized user' do
- context 'when user is not logged in' do
- let(:api_user) { nil }
+ 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(json_response['message']).to eq '404 Project Not Found'
- expect(response).to have_gitlab_http_status(:not_found)
- end
+ it 'does not return bridges' do
+ expect(response).to have_gitlab_http_status(:forbidden)
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
+ context 'when user has no read_build access for project' do
+ before do
+ project.add_guest(api_user)
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
+ 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
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index d455ed9c194..de2cfb8fea0 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -1991,6 +1991,17 @@ RSpec.describe API::Commits do
expect(json_response['x509_certificate']['x509_issuer']['subject']).to eq(commit.signature.x509_certificate.x509_issuer.subject)
expect(json_response['x509_certificate']['x509_issuer']['subject_key_identifier']).to eq(commit.signature.x509_certificate.x509_issuer.subject_key_identifier)
expect(json_response['x509_certificate']['x509_issuer']['crl_url']).to eq(commit.signature.x509_certificate.x509_issuer.crl_url)
+ expect(json_response['commit_source']).to eq('gitaly')
+ end
+
+ context 'with Rugged enabled', :enable_rugged do
+ it 'returns correct JSON' do
+ get api(route, current_user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['signature_type']).to eq('PGP')
+ expect(json_response['commit_source']).to eq('rugged')
+ end
end
end
end
diff --git a/spec/requests/api/container_repositories_spec.rb b/spec/requests/api/container_repositories_spec.rb
new file mode 100644
index 00000000000..8d7494ffce1
--- /dev/null
+++ b/spec/requests/api/container_repositories_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::ContainerRepositories do
+ let_it_be(:project) { create(:project, :private) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:repository) { create(:container_repository, project: project) }
+
+ let(:users) do
+ {
+ anonymous: nil,
+ guest: guest,
+ reporter: reporter
+ }
+ end
+
+ let(:api_user) { reporter }
+
+ before do
+ project.add_reporter(reporter)
+ project.add_guest(guest)
+
+ stub_container_registry_config(enabled: true)
+ end
+
+ describe 'GET /registry/repositories/:id' do
+ let(:url) { "/registry/repositories/#{repository.id}" }
+
+ subject { get api(url, api_user) }
+
+ it_behaves_like 'rejected container repository access', :guest, :forbidden
+ it_behaves_like 'rejected container repository access', :anonymous, :unauthorized
+
+ context 'for allowed user' do
+ it 'returns a repository' do
+ subject
+
+ expect(json_response['id']).to eq(repository.id)
+ expect(response.body).not_to include('tags')
+ end
+
+ it 'returns a matching schema' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('registry/repository')
+ end
+
+ context 'with tags param' do
+ let(:url) { "/registry/repositories/#{repository.id}?tags=true" }
+
+ before do
+ stub_container_registry_tags(repository: repository.path, tags: %w(rootA latest), with_manifest: true)
+ end
+
+ it 'returns a repository and its tags' do
+ subject
+
+ expect(json_response['id']).to eq(repository.id)
+ expect(response.body).to include('tags')
+ end
+ end
+
+ context 'with tags_count param' do
+ let(:url) { "/registry/repositories/#{repository.id}?tags_count=true" }
+
+ before do
+ stub_container_registry_tags(repository: repository.path, tags: %w(rootA latest), with_manifest: true)
+ end
+
+ it 'returns a repository and its tags_count' do
+ subject
+
+ expect(response.body).to include('tags_count')
+ expect(json_response['tags_count']).to eq(2)
+ end
+ end
+ end
+
+ context 'with invalid repository id' do
+ let(:url) { "/registry/repositories/#{non_existing_record_id}" }
+
+ it_behaves_like 'returning response status', :not_found
+ end
+ end
+end
diff --git a/spec/requests/api/dependency_proxy_spec.rb b/spec/requests/api/dependency_proxy_spec.rb
new file mode 100644
index 00000000000..d59f2bf06e3
--- /dev/null
+++ b/spec/requests/api/dependency_proxy_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::DependencyProxy, api: true do
+ include ExclusiveLeaseHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:blob) { create(:dependency_proxy_blob )}
+ let_it_be(:group, reload: true) { blob.group }
+
+ before do
+ group.add_owner(user)
+ stub_config(dependency_proxy: { enabled: true })
+ stub_last_activity_update
+ group.create_dependency_proxy_setting!(enabled: true)
+ end
+
+ describe 'DELETE /groups/:id/dependency_proxy/cache' do
+ subject { delete api("/groups/#{group.id}/dependency_proxy/cache", user) }
+
+ context 'with feature available and enabled' do
+ let_it_be(:lease_key) { "dependency_proxy:delete_group_blobs:#{group.id}" }
+
+ context 'an admin user' do
+ it 'deletes the blobs and returns no content' do
+ stub_exclusive_lease(lease_key, timeout: 1.hour)
+ expect(PurgeDependencyProxyCacheWorker).to receive(:perform_async)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+
+ context 'called multiple times in one hour', :clean_gitlab_redis_shared_state do
+ it 'returns 409 with an error message' do
+ stub_exclusive_lease_taken(lease_key, timeout: 1.hour)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:conflict)
+ expect(response.body).to include('This request has already been made.')
+ end
+
+ it 'executes service only for the first time' do
+ expect(PurgeDependencyProxyCacheWorker).to receive(:perform_async).once
+
+ 2.times { subject }
+ end
+ end
+ end
+
+ context 'a non-admin' do
+ let(:user) { create(:user) }
+
+ before do
+ group.add_maintainer(user)
+ end
+
+ it_behaves_like 'returning response status', :forbidden
+ end
+ end
+
+ context 'depencency proxy is not enabled' do
+ before do
+ stub_config(dependency_proxy: { enabled: false })
+ end
+
+ it_behaves_like 'returning response status', :not_found
+ end
+ end
+end
diff --git a/spec/requests/api/feature_flags_user_lists_spec.rb b/spec/requests/api/feature_flags_user_lists_spec.rb
index 469210040dd..e2a3f92df10 100644
--- a/spec/requests/api/feature_flags_user_lists_spec.rb
+++ b/spec/requests/api/feature_flags_user_lists_spec.rb
@@ -95,6 +95,39 @@ RSpec.describe API::FeatureFlagsUserLists do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to eq([])
end
+
+ context 'when filtering' do
+ it 'returns lists matching the search term' do
+ create_list(name: 'test_list', user_xids: 'user1')
+ create_list(name: 'list_b', user_xids: 'user1,user2,user3')
+
+ get api("/projects/#{project.id}/feature_flags_user_lists?search=test", developer)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.map { |list| list['name'] }).to eq(['test_list'])
+ end
+
+ it 'returns lists matching multiple search terms' do
+ create_list(name: 'test_list', user_xids: 'user1')
+ create_list(name: 'list_b', user_xids: 'user1,user2,user3')
+ create_list(name: 'test_again', user_xids: 'user1,user2,user3')
+
+ get api("/projects/#{project.id}/feature_flags_user_lists?search=test list", developer)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.map { |list| list['name'] }).to eq(['test_list'])
+ end
+
+ it 'returns all lists with no query' do
+ create_list(name: 'list_a', user_xids: 'user1')
+ create_list(name: 'list_b', user_xids: 'user1,user2,user3')
+
+ get api("/projects/#{project.id}/feature_flags_user_lists?search=", developer)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.map { |list| list['name'] }.sort).to eq(%w[list_a list_b])
+ end
+ end
end
describe 'GET /projects/:id/feature_flags_user_lists/:iid' do
diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb
index f77f127ddc8..8cd2f00a718 100644
--- a/spec/requests/api/files_spec.rb
+++ b/spec/requests/api/files_spec.rb
@@ -73,18 +73,20 @@ RSpec.describe API::Files do
describe "HEAD /projects/:id/repository/files/:file_path" do
shared_examples_for 'repository files' do
+ let(:options) { {} }
+
it 'returns 400 when file path is invalid' do
- head api(route(rouge_file_path), current_user), params: params
+ head api(route(rouge_file_path), current_user, **options), params: params
expect(response).to have_gitlab_http_status(:bad_request)
end
it_behaves_like 'when path is absolute' do
- subject { head api(route(absolute_path), current_user), params: params }
+ subject { head api(route(absolute_path), current_user, **options), params: params }
end
it 'returns file attributes in headers' do
- head api(route(file_path), current_user), params: params
+ head api(route(file_path), current_user, **options), params: params
expect(response).to have_gitlab_http_status(:ok)
expect(response.headers['X-Gitlab-File-Path']).to eq(CGI.unescape(file_path))
@@ -98,7 +100,7 @@ RSpec.describe API::Files do
file_path = "files%2Fjs%2Fcommit%2Ejs%2Ecoffee"
params[:ref] = "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9"
- head api(route(file_path), current_user), params: params
+ head api(route(file_path), current_user, **options), params: params
expect(response).to have_gitlab_http_status(:ok)
expect(response.headers['X-Gitlab-File-Name']).to eq('commit.js.coffee')
@@ -107,7 +109,7 @@ RSpec.describe API::Files do
context 'when mandatory params are not given' do
it "responds with a 400 status" do
- head api(route("any%2Ffile"), current_user)
+ head api(route("any%2Ffile"), current_user, **options)
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -117,7 +119,7 @@ RSpec.describe API::Files do
it "responds with a 404 status" do
params[:ref] = 'master'
- head api(route('app%2Fmodels%2Fapplication%2Erb'), current_user), params: params
+ head api(route('app%2Fmodels%2Fapplication%2Erb'), current_user, **options), params: params
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -127,7 +129,7 @@ RSpec.describe API::Files do
include_context 'disabled repository'
it "responds with a 403 status" do
- head api(route(file_path), current_user), params: params
+ head api(route(file_path), current_user, **options), params: params
expect(response).to have_gitlab_http_status(:forbidden)
end
@@ -154,8 +156,8 @@ RSpec.describe API::Files do
context 'when PATs are used' do
it_behaves_like 'repository files' do
let(:token) { create(:personal_access_token, scopes: ['read_repository'], user: user) }
- let(:current_user) { user }
- let(:api_user) { { personal_access_token: token } }
+ let(:current_user) { nil }
+ let(:options) { { personal_access_token: token } }
end
end
@@ -174,21 +176,21 @@ RSpec.describe API::Files do
describe "GET /projects/:id/repository/files/:file_path" do
shared_examples_for 'repository files' do
- let(:api_user) { current_user }
+ let(:options) { {} }
it 'returns 400 for invalid file path' do
- get api(route(rouge_file_path), api_user), params: params
+ get api(route(rouge_file_path), api_user, **options), params: params
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq(invalid_file_message)
end
it_behaves_like 'when path is absolute' do
- subject { get api(route(absolute_path), api_user), params: params }
+ subject { get api(route(absolute_path), api_user, **options), params: params }
end
it 'returns file attributes as json' do
- get api(route(file_path), api_user), params: params
+ get api(route(file_path), api_user, **options), params: params
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['file_path']).to eq(CGI.unescape(file_path))
@@ -201,10 +203,10 @@ RSpec.describe API::Files do
it 'returns json when file has txt extension' do
file_path = "bar%2Fbranch-test.txt"
- get api(route(file_path), api_user), params: params
+ get api(route(file_path), api_user, **options), params: params
expect(response).to have_gitlab_http_status(:ok)
- expect(response.content_type).to eq('application/json')
+ expect(response.media_type).to eq('application/json')
end
context 'with filename with pathspec characters' do
@@ -218,7 +220,7 @@ RSpec.describe API::Files do
it 'returns JSON wth commit SHA' do
params[:ref] = 'master'
- get api(route(file_path), api_user), params: params
+ get api(route(file_path), api_user, **options), params: params
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['file_path']).to eq(file_path)
@@ -232,7 +234,7 @@ RSpec.describe API::Files do
file_path = "files%2Fjs%2Fcommit%2Ejs%2Ecoffee"
params[:ref] = "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9"
- get api(route(file_path), api_user), params: params
+ get api(route(file_path), api_user, **options), params: params
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['file_name']).to eq('commit.js.coffee')
@@ -244,7 +246,7 @@ RSpec.describe API::Files do
url = route(file_path) + "/raw"
expect(Gitlab::Workhorse).to receive(:send_git_blob)
- get api(url, api_user), params: params
+ get api(url, api_user, **options), params: params
expect(response).to have_gitlab_http_status(:ok)
expect(headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
@@ -253,7 +255,7 @@ RSpec.describe API::Files do
it 'returns blame file info' do
url = route(file_path) + '/blame'
- get api(url, api_user), params: params
+ get api(url, api_user, **options), params: params
expect(response).to have_gitlab_http_status(:ok)
end
@@ -261,14 +263,14 @@ RSpec.describe API::Files do
it 'sets inline content disposition by default' do
url = route(file_path) + "/raw"
- get api(url, api_user), params: params
+ get api(url, api_user, **options), params: params
expect(headers['Content-Disposition']).to eq(%q(inline; filename="popen.rb"; filename*=UTF-8''popen.rb))
end
context 'when mandatory params are not given' do
it_behaves_like '400 response' do
- let(:request) { get api(route("any%2Ffile"), current_user) }
+ let(:request) { get api(route("any%2Ffile"), current_user, **options) }
end
end
@@ -276,7 +278,7 @@ RSpec.describe API::Files do
let(:params) { { ref: 'master' } }
it_behaves_like '404 response' do
- let(:request) { get api(route('app%2Fmodels%2Fapplication%2Erb'), api_user), params: params }
+ let(:request) { get api(route('app%2Fmodels%2Fapplication%2Erb'), api_user, **options), params: params }
let(:message) { '404 File Not Found' }
end
end
@@ -285,7 +287,7 @@ RSpec.describe API::Files do
include_context 'disabled repository'
it_behaves_like '403 response' do
- let(:request) { get api(route(file_path), api_user), params: params }
+ let(:request) { get api(route(file_path), api_user, **options), params: params }
end
end
end
@@ -294,6 +296,7 @@ RSpec.describe API::Files do
it_behaves_like 'repository files' do
let(:project) { create(:project, :public, :repository) }
let(:current_user) { nil }
+ let(:api_user) { nil }
end
end
@@ -301,7 +304,8 @@ RSpec.describe API::Files do
it_behaves_like 'repository files' do
let(:token) { create(:personal_access_token, scopes: ['read_repository'], user: user) }
let(:current_user) { user }
- let(:api_user) { { personal_access_token: token } }
+ let(:api_user) { nil }
+ let(:options) { { personal_access_token: token } }
end
end
@@ -315,6 +319,7 @@ RSpec.describe API::Files do
context 'when authenticated', 'as a developer' do
it_behaves_like 'repository files' do
let(:current_user) { user }
+ let(:api_user) { user }
end
end
@@ -532,13 +537,16 @@ RSpec.describe API::Files do
expect(response).to have_gitlab_http_status(:ok)
end
- it_behaves_like 'uncached response' do
- before do
- url = route('.gitignore') + "/raw"
- expect(Gitlab::Workhorse).to receive(:send_git_blob)
+ it 'sets no-cache headers' do
+ url = route('.gitignore') + "/raw"
+ expect(Gitlab::Workhorse).to receive(:send_git_blob)
- get api(url, current_user), params: params
- end
+ get api(url, current_user), params: params
+
+ expect(response.headers["Cache-Control"]).to include("no-store")
+ expect(response.headers["Cache-Control"]).to include("no-cache")
+ expect(response.headers["Pragma"]).to eq("no-cache")
+ expect(response.headers["Expires"]).to eq("Fri, 01 Jan 1990 00:00:00 GMT")
end
context 'when mandatory params are not given' do
@@ -687,7 +695,7 @@ RSpec.describe API::Files do
post api(route("new_file_with_author%2Etxt"), user), params: params
expect(response).to have_gitlab_http_status(:created)
- expect(response.content_type).to eq('application/json')
+ expect(response.media_type).to eq('application/json')
last_commit = project.repository.commit.raw
expect(last_commit.author_email).to eq(author_email)
expect(last_commit.author_name).to eq(author_name)
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
index 2cb686167f1..b8e79853486 100644
--- a/spec/requests/api/generic_packages_spec.rb
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -195,7 +195,7 @@ RSpec.describe API::GenericPackages do
package = project.packages.generic.last
expect(package.name).to eq('mypackage')
expect(package.version).to eq('0.0.1')
- expect(package.build_info).to be_nil
+ expect(package.original_build_info).to be_nil
package_file = package.package_files.last
expect(package_file.file_name).to eq('myfile.tar.gz')
@@ -215,7 +215,7 @@ RSpec.describe API::GenericPackages do
package = project.packages.generic.last
expect(package.name).to eq('mypackage')
expect(package.version).to eq('0.0.1')
- expect(package.build_info.pipeline).to eq(ci_build.pipeline)
+ expect(package.original_build_info.pipeline).to eq(ci_build.pipeline)
package_file = package.package_files.last
expect(package_file.file_name).to eq('myfile.tar.gz')
diff --git a/spec/requests/api/graphql/ci/jobs_spec.rb b/spec/requests/api/graphql/ci/jobs_spec.rb
index 7d416f4720b..618705e5f94 100644
--- a/spec/requests/api/graphql/ci/jobs_spec.rb
+++ b/spec/requests/api/graphql/ci/jobs_spec.rb
@@ -34,6 +34,9 @@ RSpec.describe 'Query.project.pipeline.stages.groups.jobs' do
jobs {
nodes {
name
+ pipeline {
+ id
+ }
}
}
}
@@ -53,7 +56,7 @@ RSpec.describe 'Query.project.pipeline.stages.groups.jobs' do
end
context 'when fetching jobs from the pipeline' do
- it 'avoids N+1 queries' do
+ it 'avoids N+1 queries', :aggregate_failures do
control_count = ActiveRecord::QueryRecorder.new do
post_graphql(query, current_user: user)
end
@@ -86,8 +89,27 @@ RSpec.describe 'Query.project.pipeline.stages.groups.jobs' do
docker_jobs = docker_group.dig('jobs', 'nodes')
rspec_jobs = rspec_group.dig('jobs', 'nodes')
- expect(docker_jobs).to eq([{ 'name' => 'docker 1 2' }, { 'name' => 'docker 2 2' }])
- expect(rspec_jobs).to eq([{ 'name' => 'rspec 1 2' }, { 'name' => 'rspec 2 2' }])
+ expect(docker_jobs).to eq([
+ {
+ 'name' => 'docker 1 2',
+ 'pipeline' => { 'id' => pipeline.to_global_id.to_s }
+ },
+ {
+ 'name' => 'docker 2 2',
+ 'pipeline' => { 'id' => pipeline.to_global_id.to_s }
+ }
+ ])
+
+ expect(rspec_jobs).to eq([
+ {
+ 'name' => 'rspec 1 2',
+ 'pipeline' => { 'id' => pipeline.to_global_id.to_s }
+ },
+ {
+ 'name' => 'rspec 2 2',
+ 'pipeline' => { 'id' => pipeline.to_global_id.to_s }
+ }
+ ])
end
end
end
diff --git a/spec/requests/api/graphql/ci/pipelines_spec.rb b/spec/requests/api/graphql/ci/pipelines_spec.rb
new file mode 100644
index 00000000000..414ddabbac9
--- /dev/null
+++ b/spec/requests/api/graphql/ci/pipelines_spec.rb
@@ -0,0 +1,221 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Query.project(fullPath).pipelines' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:first_user) { create(:user) }
+ let_it_be(:second_user) { create(:user) }
+
+ describe '.jobs' do
+ let_it_be(:query) do
+ %(
+ query {
+ project(fullPath: "#{project.full_path}") {
+ pipelines {
+ nodes {
+ jobs {
+ nodes {
+ name
+ }
+ }
+ }
+ }
+ }
+ }
+ )
+ end
+
+ it 'fetches the jobs without an N+1' do
+ pipeline = create(:ci_pipeline, project: project)
+ create(:ci_build, pipeline: pipeline, name: 'Job 1')
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(query, current_user: first_user)
+ end
+
+ pipeline = create(:ci_pipeline, project: project)
+ create(:ci_build, pipeline: pipeline, name: 'Job 2')
+
+ expect do
+ post_graphql(query, current_user: second_user)
+ end.not_to exceed_query_limit(control_count)
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ pipelines_data = graphql_data.dig('project', 'pipelines', 'nodes')
+
+ job_names = pipelines_data.map do |pipeline_data|
+ jobs_data = pipeline_data.dig('jobs', 'nodes')
+ jobs_data.map { |job_data| job_data['name'] }
+ end.flatten
+
+ expect(job_names).to contain_exactly('Job 1', 'Job 2')
+ end
+ end
+
+ describe '.jobs(securityReportTypes)' do
+ let_it_be(:query) do
+ %(
+ query {
+ project(fullPath: "#{project.full_path}") {
+ pipelines {
+ nodes {
+ jobs(securityReportTypes: [SAST]) {
+ nodes {
+ name
+ }
+ }
+ }
+ }
+ }
+ }
+ )
+ end
+
+ it 'fetches the jobs matching the report type filter' do
+ pipeline = create(:ci_pipeline, project: project)
+ create(:ci_build, :dast, name: 'DAST Job 1', pipeline: pipeline)
+ create(:ci_build, :sast, name: 'SAST Job 1', pipeline: pipeline)
+
+ post_graphql(query, current_user: first_user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ pipelines_data = graphql_data.dig('project', 'pipelines', 'nodes')
+
+ job_names = pipelines_data.map do |pipeline_data|
+ jobs_data = pipeline_data.dig('jobs', 'nodes')
+ jobs_data.map { |job_data| job_data['name'] }
+ end.flatten
+
+ expect(job_names).to contain_exactly('SAST Job 1')
+ end
+ end
+
+ describe 'upstream' do
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: first_user) }
+ let_it_be(:upstream_project) { create(:project, :repository, :public) }
+ let_it_be(:upstream_pipeline) { create(:ci_pipeline, project: upstream_project, user: first_user) }
+ let(:upstream_pipelines_graphql_data) { graphql_data.dig(*%w[project pipelines nodes]).first['upstream'] }
+
+ let(:query) do
+ %(
+ query {
+ project(fullPath: "#{project.full_path}") {
+ pipelines {
+ nodes {
+ upstream {
+ iid
+ }
+ }
+ }
+ }
+ }
+ )
+ end
+
+ before do
+ create(:ci_sources_pipeline, source_pipeline: upstream_pipeline, pipeline: pipeline )
+
+ post_graphql(query, current_user: first_user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns the upstream pipeline of a pipeline' do
+ expect(upstream_pipelines_graphql_data['iid'].to_i).to eq(upstream_pipeline.iid)
+ end
+
+ context 'when fetching the upstream pipeline from the pipeline' do
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(query, current_user: first_user)
+ end
+
+ pipeline_2 = create(:ci_pipeline, project: project, user: first_user)
+ upstream_pipeline_2 = create(:ci_pipeline, project: upstream_project, user: first_user)
+ create(:ci_sources_pipeline, source_pipeline: upstream_pipeline_2, pipeline: pipeline_2 )
+ pipeline_3 = create(:ci_pipeline, project: project, user: first_user)
+ upstream_pipeline_3 = create(:ci_pipeline, project: upstream_project, user: first_user)
+ create(:ci_sources_pipeline, source_pipeline: upstream_pipeline_3, pipeline: pipeline_3 )
+
+ expect do
+ post_graphql(query, current_user: second_user)
+ end.not_to exceed_query_limit(control_count)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
+ describe 'downstream' do
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: first_user) }
+ let(:pipeline_2) { create(:ci_pipeline, project: project, user: first_user) }
+
+ let_it_be(:downstream_project) { create(:project, :repository, :public) }
+ let_it_be(:downstream_pipeline_a) { create(:ci_pipeline, project: downstream_project, user: first_user) }
+ let_it_be(:downstream_pipeline_b) { create(:ci_pipeline, project: downstream_project, user: first_user) }
+
+ let(:pipelines_graphql_data) { graphql_data.dig(*%w[project pipelines nodes]) }
+
+ let(:query) do
+ %(
+ query {
+ project(fullPath: "#{project.full_path}") {
+ pipelines {
+ nodes {
+ downstream {
+ nodes {
+ iid
+ }
+ }
+ }
+ }
+ }
+ }
+ )
+ end
+
+ before do
+ create(:ci_sources_pipeline, source_pipeline: pipeline, pipeline: downstream_pipeline_a)
+ create(:ci_sources_pipeline, source_pipeline: pipeline_2, pipeline: downstream_pipeline_b)
+
+ post_graphql(query, current_user: first_user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns the downstream pipelines of a pipeline' do
+ downstream_pipelines_graphql_data = pipelines_graphql_data.map { |pip| pip['downstream']['nodes'] }.flatten
+
+ expect(
+ downstream_pipelines_graphql_data.map { |pip| pip['iid'].to_i }
+ ).to contain_exactly(downstream_pipeline_a.iid, downstream_pipeline_b.iid)
+ end
+
+ context 'when fetching the downstream pipelines from the pipeline' do
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(query, current_user: first_user)
+ end
+
+ downstream_pipeline_2a = create(:ci_pipeline, project: downstream_project, user: first_user)
+ create(:ci_sources_pipeline, source_pipeline: pipeline, pipeline: downstream_pipeline_2a)
+ downsteam_pipeline_3a = create(:ci_pipeline, project: downstream_project, user: first_user)
+ create(:ci_sources_pipeline, source_pipeline: pipeline, pipeline: downsteam_pipeline_3a)
+
+ downstream_pipeline_2b = create(:ci_pipeline, project: downstream_project, user: first_user)
+ create(:ci_sources_pipeline, source_pipeline: pipeline_2, pipeline: downstream_pipeline_2b)
+ downsteam_pipeline_3b = create(:ci_pipeline, project: downstream_project, user: first_user)
+ create(:ci_sources_pipeline, source_pipeline: pipeline_2, pipeline: downsteam_pipeline_3b)
+
+ expect do
+ post_graphql(query, current_user: second_user)
+ end.not_to exceed_query_limit(control_count)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb b/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb
new file mode 100644
index 00000000000..3c1c63c1670
--- /dev/null
+++ b/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'container repository details' do
+ using RSpec::Parameterized::TableSyntax
+ include GraphqlHelpers
+
+ let_it_be_with_reload(:project) { create(:project) }
+ let_it_be(:container_repository) { create(:container_repository, project: project) }
+
+ let(:query) do
+ graphql_query_for(
+ 'containerRepository',
+ { id: container_repository_global_id },
+ all_graphql_fields_for('ContainerRepositoryDetails')
+ )
+ end
+
+ let(:user) { project.owner }
+ let(:variables) { {} }
+ let(:tags) { %w(latest tag1 tag2 tag3 tag4 tag5) }
+ let(:container_repository_global_id) { container_repository.to_global_id.to_s }
+ let(:container_repository_details_response) { graphql_data.dig('containerRepository') }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ stub_container_registry_tags(repository: container_repository.path, tags: tags, with_manifest: true)
+ end
+
+ subject { post_graphql(query, current_user: user, variables: variables) }
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ subject
+ end
+
+ it 'matches the JSON schema' do
+ expect(container_repository_details_response).to match_schema('graphql/container_repository_details')
+ end
+ end
+
+ context 'with different permissions' do
+ let_it_be(:user) { create(:user) }
+
+ let(:tags_response) { container_repository_details_response.dig('tags', 'nodes') }
+
+ where(:project_visibility, :role, :access_granted, :can_delete) do
+ :private | :maintainer | true | true
+ :private | :developer | true | true
+ :private | :reporter | true | false
+ :private | :guest | false | false
+ :private | :anonymous | false | false
+ :public | :maintainer | true | true
+ :public | :developer | true | true
+ :public | :reporter | true | false
+ :public | :guest | true | false
+ :public | :anonymous | true | false
+ end
+
+ with_them do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility.to_s.upcase, false))
+ project.add_user(user, role) unless role == :anonymous
+ end
+
+ it 'return the proper response' do
+ subject
+
+ if access_granted
+ expect(tags_response.size).to eq(tags.size)
+ expect(container_repository_details_response.dig('canDelete')).to eq(can_delete)
+ else
+ expect(container_repository_details_response).to eq(nil)
+ end
+ end
+ end
+ end
+
+ context 'limiting the number of tags' do
+ let(:limit) { 2 }
+ let(:tags_response) { container_repository_details_response.dig('tags', 'edges') }
+ let(:variables) do
+ { id: container_repository_global_id, n: limit }
+ end
+
+ let(:query) do
+ <<~GQL
+ query($id: ID!, $n: Int) {
+ containerRepository(id: $id) {
+ tags(first: $n) {
+ edges {
+ node {
+ #{all_graphql_fields_for('ContainerRepositoryTag')}
+ }
+ }
+ }
+ }
+ }
+ GQL
+ end
+
+ it 'only returns n tags' do
+ subject
+
+ expect(tags_response.size).to eq(limit)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/custom_emoji_query_spec.rb b/spec/requests/api/graphql/custom_emoji_query_spec.rb
new file mode 100644
index 00000000000..d5a423d0eba
--- /dev/null
+++ b/spec/requests/api/graphql/custom_emoji_query_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'getting custom emoji within namespace' do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group) { create(:group, :private) }
+ let_it_be(:custom_emoji) { create(:custom_emoji, group: group) }
+
+ before do
+ stub_feature_flags(custom_emoji: true)
+ group.add_developer(current_user)
+ end
+
+ describe "Query CustomEmoji on Group" do
+ def custom_emoji_query(group)
+ graphql_query_for('group', 'fullPath' => group.full_path)
+ end
+
+ it 'returns emojis when authorised' do
+ post_graphql(custom_emoji_query(group), current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(graphql_data['group']['customEmoji']['nodes'].count). to eq(1)
+ expect(graphql_data['group']['customEmoji']['nodes'].first['name']). to eq(custom_emoji.name)
+ end
+
+ it 'returns nil when unauthorised' do
+ user = create(:user)
+ post_graphql(custom_emoji_query(group), current_user: user)
+
+ expect(graphql_data['group']).to be_nil
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/group/container_repositories_spec.rb b/spec/requests/api/graphql/group/container_repositories_spec.rb
new file mode 100644
index 00000000000..bcf689a5e8f
--- /dev/null
+++ b/spec/requests/api/graphql/group/container_repositories_spec.rb
@@ -0,0 +1,146 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'getting container repositories in a group' do
+ using RSpec::Parameterized::TableSyntax
+ include GraphqlHelpers
+
+ let_it_be(:owner) { create(:user) }
+ let_it_be_with_reload(:group) { create(:group) }
+ let_it_be_with_reload(:project) { create(:project, group: group) }
+ let_it_be(:container_repository) { create(:container_repository, project: project) }
+ let_it_be(:container_repositories_delete_scheduled) { create_list(:container_repository, 2, :status_delete_scheduled, project: project) }
+ let_it_be(:container_repositories_delete_failed) { create_list(:container_repository, 2, :status_delete_failed, project: project) }
+ let_it_be(:container_repositories) { [container_repository, container_repositories_delete_scheduled, container_repositories_delete_failed].flatten }
+ let_it_be(:container_expiration_policy) { project.container_expiration_policy }
+
+ let(:fields) do
+ <<~GQL
+ edges {
+ node {
+ #{all_graphql_fields_for('container_repositories'.classify)}
+ }
+ }
+ GQL
+ end
+
+ let(:query) do
+ graphql_query_for(
+ 'group',
+ { 'fullPath' => group.full_path },
+ query_graphql_field('container_repositories', {}, fields)
+ )
+ end
+
+ let(:user) { owner }
+ let(:variables) { {} }
+ let(:container_repositories_response) { graphql_data.dig('group', 'containerRepositories', 'edges') }
+
+ before do
+ group.add_owner(owner)
+ stub_container_registry_config(enabled: true)
+ container_repositories.each do |repository|
+ stub_container_registry_tags(repository: repository.path, tags: %w(tag1 tag2 tag3), with_manifest: false)
+ end
+ end
+
+ subject { post_graphql(query, current_user: user, variables: variables) }
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ subject
+ end
+ end
+
+ context 'with different permissions' do
+ let_it_be(:user) { create(:user) }
+
+ where(:group_visibility, :role, :access_granted, :can_delete) do
+ :private | :maintainer | true | true
+ :private | :developer | true | true
+ :private | :reporter | true | false
+ :private | :guest | false | false
+ :private | :anonymous | false | false
+ :public | :maintainer | true | true
+ :public | :developer | true | true
+ :public | :reporter | true | false
+ :public | :guest | false | false
+ :public | :anonymous | false | false
+ end
+
+ with_them do
+ before do
+ group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility.to_s.upcase, false))
+ project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility.to_s.upcase, false))
+
+ group.add_user(user, role) unless role == :anonymous
+ end
+
+ it 'return the proper response' do
+ subject
+
+ if access_granted
+ expect(container_repositories_response.size).to eq(container_repositories.size)
+ container_repositories_response.each do |repository_response|
+ expect(repository_response.dig('node', 'canDelete')).to eq(can_delete)
+ end
+ else
+ expect(container_repositories_response).to eq(nil)
+ end
+ end
+ end
+ end
+
+ context 'limiting the number of repositories' do
+ let(:limit) { 1 }
+ let(:variables) do
+ { path: group.full_path, n: limit }
+ end
+
+ let(:query) do
+ <<~GQL
+ query($path: ID!, $n: Int) {
+ group(fullPath: $path) {
+ containerRepositories(first: $n) { #{fields} }
+ }
+ }
+ GQL
+ end
+
+ it 'only returns N repositories' do
+ subject
+
+ expect(container_repositories_response.size).to eq(limit)
+ end
+ end
+
+ context 'filter by name' do
+ let_it_be(:container_repository) { create(:container_repository, name: 'fooBar', project: project) }
+
+ let(:name) { 'ooba' }
+ let(:query) do
+ <<~GQL
+ query($path: ID!, $name: String) {
+ group(fullPath: $path) {
+ containerRepositories(name: $name) { #{fields} }
+ }
+ }
+ GQL
+ end
+
+ let(:variables) do
+ { path: group.full_path, name: name }
+ end
+
+ before do
+ stub_container_registry_tags(repository: container_repository.path, tags: %w(tag4 tag5 tag6), with_manifest: false)
+ end
+
+ it 'returns the searched container repository' do
+ subject
+
+ expect(container_repositories_response.size).to eq(1)
+ expect(container_repositories_response.first.dig('node', 'id')).to eq(container_repository.to_global_id.to_s)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/instance_statistics_measurements_spec.rb b/spec/requests/api/graphql/instance_statistics_measurements_spec.rb
index 5d7dbcf2e3c..eb73dc59253 100644
--- a/spec/requests/api/graphql/instance_statistics_measurements_spec.rb
+++ b/spec/requests/api/graphql/instance_statistics_measurements_spec.rb
@@ -9,7 +9,8 @@ RSpec.describe 'InstanceStatisticsMeasurements' do
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 identifier }') }
+ let(:arguments) { 'identifier: PROJECTS' }
+ let(:query) { graphql_query_for(:instanceStatisticsMeasurements, arguments, 'nodes { count identifier }') }
before do
post_graphql(query, current_user: current_user)
@@ -21,4 +22,14 @@ RSpec.describe 'InstanceStatisticsMeasurements' do
{ "count" => 5, 'identifier' => 'PROJECTS' }
])
end
+
+ context 'with recorded_at filters' do
+ let(:arguments) { %(identifier: PROJECTS, recordedAfter: "#{15.days.ago.to_date}", recordedBefore: "#{5.days.ago.to_date}") }
+
+ it 'returns filtered measurement objects' do
+ expect(graphql_data.dig('instanceStatisticsMeasurements', 'nodes')).to eq([
+ { "count" => 10, 'identifier' => 'PROJECTS' }
+ ])
+ end
+ end
end
diff --git a/spec/requests/api/graphql/issue/issue_spec.rb b/spec/requests/api/graphql/issue/issue_spec.rb
index 1c9d6b25856..d7fa680d29b 100644
--- a/spec/requests/api/graphql/issue/issue_spec.rb
+++ b/spec/requests/api/graphql/issue/issue_spec.rb
@@ -71,14 +71,34 @@ RSpec.describe 'Query.issue(id)' do
end
context 'selecting multiple fields' do
- let(:issue_fields) { %w(title description) }
+ let(:issue_fields) { ['title', 'description', 'updatedBy { username }'] }
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.keys).to eq( %w(title description updatedBy) )
expect(issue_data['title']).to eq(issue.title)
expect(issue_data['description']).to eq(issue.description)
+ expect(issue_data['updatedBy']['username']).to eq(issue.author.username)
+ end
+ end
+
+ context 'when issue got moved' do
+ let_it_be(:issue_fields) { ['moved', 'movedTo { title }'] }
+ let_it_be(:new_issue) { create(:issue) }
+ let_it_be(:issue) { create(:issue, project: project, moved_to: new_issue) }
+ let_it_be(:issue_params) { { 'id' => issue.to_global_id.to_s } }
+
+ before_all do
+ new_issue.project.add_developer(current_user)
+ end
+
+ it 'returns correct attributes' do
+ post_graphql(query, current_user: current_user)
+
+ expect(issue_data.keys).to eq( %w(moved movedTo) )
+ expect(issue_data['moved']).to eq(true)
+ expect(issue_data['movedTo']['title']).to eq(new_issue.title)
end
end
diff --git a/spec/requests/api/graphql/metrics/dashboard/annotations_spec.rb b/spec/requests/api/graphql/metrics/dashboard/annotations_spec.rb
index ca5a9165760..72ec2b8e070 100644
--- a/spec/requests/api/graphql/metrics/dashboard/annotations_spec.rb
+++ b/spec/requests/api/graphql/metrics/dashboard/annotations_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe 'Getting Metrics Dashboard Annotations' do
let_it_be(:to_old_annotation) do
create(:metrics_dashboard_annotation, environment: environment, starting_at: Time.parse(from).advance(minutes: -5), dashboard_path: path)
end
+
let_it_be(:to_new_annotation) do
create(:metrics_dashboard_annotation, environment: environment, starting_at: to.advance(minutes: 5), dashboard_path: path)
end
diff --git a/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb b/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb
new file mode 100644
index 00000000000..a285cebc805
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Creating a new HTTP Integration' do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let(:variables) do
+ {
+ project_path: project.full_path,
+ active: false,
+ name: 'New HTTP Integration'
+ }
+ end
+
+ let(:mutation) do
+ graphql_mutation(:http_integration_create, variables) do
+ <<~QL
+ clientMutationId
+ errors
+ integration {
+ id
+ type
+ name
+ active
+ token
+ url
+ apiUrl
+ }
+ QL
+ end
+ end
+
+ let(:mutation_response) { graphql_mutation_response(:http_integration_create) }
+
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ it 'creates a new integration' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ new_integration = ::AlertManagement::HttpIntegration.last!
+ integration_response = mutation_response['integration']
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(integration_response['id']).to eq(GitlabSchema.id_from_object(new_integration).to_s)
+ expect(integration_response['type']).to eq('HTTP')
+ expect(integration_response['name']).to eq(new_integration.name)
+ expect(integration_response['active']).to eq(new_integration.active)
+ expect(integration_response['token']).to eq(new_integration.token)
+ expect(integration_response['url']).to eq(new_integration.url)
+ expect(integration_response['apiUrl']).to eq(nil)
+ end
+
+ [:project_path, :active, :name].each do |argument|
+ context "without required argument #{argument}" do
+ before do
+ variables.delete(argument)
+ end
+
+ it_behaves_like 'an invalid argument to the mutation', argument_name: argument
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/alert_management/http_integration/destroy_spec.rb b/spec/requests/api/graphql/mutations/alert_management/http_integration/destroy_spec.rb
new file mode 100644
index 00000000000..1ecb5c76b57
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/alert_management/http_integration/destroy_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Removing an HTTP Integration' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:alert_management_http_integration, project: project) }
+
+ let(:mutation) do
+ variables = {
+ id: GitlabSchema.id_from_object(integration).to_s
+ }
+ graphql_mutation(:http_integration_destroy, variables) do
+ <<~QL
+ clientMutationId
+ errors
+ integration {
+ id
+ type
+ name
+ active
+ token
+ url
+ apiUrl
+ }
+ QL
+ end
+ end
+
+ let(:mutation_response) { graphql_mutation_response(:http_integration_destroy) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'removes the integration' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ integration_response = mutation_response['integration']
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(integration_response['id']).to eq(GitlabSchema.id_from_object(integration).to_s)
+ expect(integration_response['type']).to eq('HTTP')
+ expect(integration_response['name']).to eq(integration.name)
+ expect(integration_response['active']).to eq(integration.active)
+ expect(integration_response['token']).to eq(integration.token)
+ expect(integration_response['url']).to eq(integration.url)
+ expect(integration_response['apiUrl']).to eq(nil)
+
+ expect { integration.reload }.to raise_error ActiveRecord::RecordNotFound
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/alert_management/http_integration/reset_token_spec.rb b/spec/requests/api/graphql/mutations/alert_management/http_integration/reset_token_spec.rb
new file mode 100644
index 00000000000..badd9412589
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/alert_management/http_integration/reset_token_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Resetting a token on an existing HTTP Integration' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:alert_management_http_integration, project: project) }
+
+ let(:mutation) do
+ variables = {
+ id: GitlabSchema.id_from_object(integration).to_s
+ }
+ graphql_mutation(:http_integration_reset_token, variables) do
+ <<~QL
+ clientMutationId
+ errors
+ integration {
+ id
+ token
+ }
+ QL
+ end
+ end
+
+ let(:mutation_response) { graphql_mutation_response(:http_integration_reset_token) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'updates the integration' do
+ previous_token = integration.token
+
+ post_graphql_mutation(mutation, current_user: user)
+ integration_response = mutation_response['integration']
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(integration_response['id']).to eq(GitlabSchema.id_from_object(integration).to_s)
+ expect(integration_response['token']).not_to eq(previous_token)
+ expect(integration_response['token']).to eq(integration.reload.token)
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb b/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb
new file mode 100644
index 00000000000..bf7eb3d980c
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Updating an existing HTTP Integration' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:alert_management_http_integration, project: project) }
+
+ let(:mutation) do
+ variables = {
+ id: GitlabSchema.id_from_object(integration).to_s,
+ name: 'Modified Name',
+ active: false
+ }
+ graphql_mutation(:http_integration_update, variables) do
+ <<~QL
+ clientMutationId
+ errors
+ integration {
+ id
+ name
+ active
+ url
+ }
+ QL
+ end
+ end
+
+ let(:mutation_response) { graphql_mutation_response(:http_integration_update) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'updates the integration' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ integration_response = mutation_response['integration']
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(integration_response['id']).to eq(GitlabSchema.id_from_object(integration).to_s)
+ expect(integration_response['name']).to eq('Modified Name')
+ expect(integration_response['active']).to be_falsey
+ expect(integration_response['url']).to include('modified-name')
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb
new file mode 100644
index 00000000000..0ef61ae0d5b
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Creating a new Prometheus Integration' do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let(:variables) do
+ {
+ project_path: project.full_path,
+ active: false,
+ api_url: 'https://prometheus-url.com'
+ }
+ end
+
+ let(:mutation) do
+ graphql_mutation(:prometheus_integration_create, variables) do
+ <<~QL
+ clientMutationId
+ errors
+ integration {
+ id
+ type
+ name
+ active
+ token
+ url
+ apiUrl
+ }
+ QL
+ end
+ end
+
+ let(:mutation_response) { graphql_mutation_response(:prometheus_integration_create) }
+
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ it 'creates a new integration' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ new_integration = ::PrometheusService.last!
+ integration_response = mutation_response['integration']
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(integration_response['id']).to eq(GitlabSchema.id_from_object(new_integration).to_s)
+ expect(integration_response['type']).to eq('PROMETHEUS')
+ expect(integration_response['name']).to eq(new_integration.title)
+ expect(integration_response['active']).to eq(new_integration.manual_configuration?)
+ expect(integration_response['token']).to eq(new_integration.project.alerting_setting.token)
+ expect(integration_response['url']).to eq("http://localhost/#{project.full_path}/prometheus/alerts/notify.json")
+ expect(integration_response['apiUrl']).to eq(new_integration.api_url)
+ end
+
+ [:project_path, :active, :api_url].each do |argument|
+ context "without required argument #{argument}" do
+ before do
+ variables.delete(argument)
+ end
+
+ it_behaves_like 'an invalid argument to the mutation', argument_name: argument
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb
new file mode 100644
index 00000000000..d8d0ace5981
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Resetting a token on an existing Prometheus Integration' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:prometheus_service, project: project) }
+
+ let(:mutation) do
+ variables = {
+ id: GitlabSchema.id_from_object(integration).to_s
+ }
+ graphql_mutation(:prometheus_integration_reset_token, variables) do
+ <<~QL
+ clientMutationId
+ errors
+ integration {
+ id
+ token
+ }
+ QL
+ end
+ end
+
+ let(:mutation_response) { graphql_mutation_response(:prometheus_integration_reset_token) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'creates a token' do
+ post_graphql_mutation(mutation, current_user: user)
+ integration_response = mutation_response['integration']
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(integration_response['id']).to eq(GitlabSchema.id_from_object(integration).to_s)
+ expect(integration_response['token']).not_to be_nil
+ expect(integration_response['token']).to eq(project.alerting_setting.token)
+ end
+
+ context 'with an existing alerting setting' do
+ let_it_be(:alerting_setting) { create(:project_alerting_setting, project: project) }
+
+ it 'updates the token' do
+ previous_token = alerting_setting.token
+
+ post_graphql_mutation(mutation, current_user: user)
+ integration_response = mutation_response['integration']
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(integration_response['id']).to eq(GitlabSchema.id_from_object(integration).to_s)
+ expect(integration_response['token']).not_to eq(previous_token)
+ expect(integration_response['token']).to eq(alerting_setting.reload.token)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/update_spec.rb b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/update_spec.rb
new file mode 100644
index 00000000000..6c4a647a353
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/update_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Updating an existing Prometheus Integration' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:prometheus_service, project: project) }
+
+ let(:mutation) do
+ variables = {
+ id: GitlabSchema.id_from_object(integration).to_s,
+ api_url: 'http://modified-url.com',
+ active: true
+ }
+ graphql_mutation(:prometheus_integration_update, variables) do
+ <<~QL
+ clientMutationId
+ errors
+ integration {
+ id
+ active
+ apiUrl
+ }
+ QL
+ end
+ end
+
+ let(:mutation_response) { graphql_mutation_response(:prometheus_integration_update) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'updates the integration' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ integration_response = mutation_response['integration']
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(integration_response['id']).to eq(GitlabSchema.id_from_object(integration).to_s)
+ expect(integration_response['apiUrl']).to eq('http://modified-url.com')
+ expect(integration_response['active']).to be_truthy
+ 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 ac4fa7cfe83..375d4f10b40 100644
--- a/spec/requests/api/graphql/mutations/commits/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/commits/create_spec.rb
@@ -23,6 +23,18 @@ RSpec.describe 'Creation of a new commit' do
let(:mutation) { graphql_mutation(:commit_create, input) }
let(:mutation_response) { graphql_mutation_response(:commit_create) }
+ shared_examples 'a commit is successful' do
+ it 'creates a new commit' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+
+ expect(mutation_response['commit']).to include(
+ 'title' => message
+ )
+ end
+ end
+
context 'the user is not allowed to create a commit' do
it_behaves_like 'a mutation that returns a top-level access error'
end
@@ -32,14 +44,7 @@ RSpec.describe 'Creation of a new commit' do
project.add_developer(current_user)
end
- it 'creates a new commit' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_response['commit']).to include(
- 'title' => message
- )
- end
+ it_behaves_like 'a commit is successful'
context 'when branch is not correct' do
let(:branch) { 'unknown' }
@@ -47,5 +52,22 @@ RSpec.describe 'Creation of a new commit' do
it_behaves_like 'a mutation that returns errors in the response',
errors: ['You can only create or edit files when you are on a branch']
end
+
+ context 'when branch is new, and a start_branch is defined' do
+ let(:input) { { project_path: project.full_path, branch: branch, start_branch: start_branch, message: message, actions: actions } }
+ let(:branch) { 'new-branch' }
+ let(:start_branch) { 'master' }
+ let(:actions) do
+ [
+ {
+ action: 'CREATE',
+ filePath: 'ANOTHER_FILE.md',
+ content: 'Bye'
+ }
+ ]
+ end
+
+ it_behaves_like 'a commit is successful'
+ end
end
end
diff --git a/spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb b/spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb
index 7bef812bfec..23e8e366483 100644
--- a/spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb
@@ -73,6 +73,29 @@ RSpec.describe 'Updating the container expiration policy' do
end
end
+ RSpec.shared_examples 'rejecting blank name_regex when enabled' do
+ context "for blank name_regex" do
+ let(:params) do
+ {
+ project_path: project.full_path,
+ name_regex: '',
+ enabled: true
+ }
+ end
+
+ it_behaves_like 'returning response status', :success
+
+ it_behaves_like 'not creating the container expiration policy'
+
+ it 'returns an error' do
+ subject
+
+ expect(graphql_data['updateContainerExpirationPolicy']['errors'].size).to eq(1)
+ expect(graphql_data['updateContainerExpirationPolicy']['errors']).to include("Name regex can't be blank")
+ end
+ end
+ end
+
RSpec.shared_examples 'accepting the mutation request updating the container expiration policy' do
it_behaves_like 'updating the container expiration policy attributes', mode: :update, from: { cadence: '1d', keep_n: 10, older_than: '90d' }, to: { cadence: '3month', keep_n: 100, older_than: '14d' }
@@ -80,6 +103,7 @@ RSpec.describe 'Updating the container expiration policy' do
it_behaves_like 'rejecting invalid regex for', :name_regex
it_behaves_like 'rejecting invalid regex for', :name_regex_keep
+ it_behaves_like 'rejecting blank name_regex when enabled'
end
RSpec.shared_examples 'accepting the mutation request creating the container expiration policy' do
@@ -89,6 +113,7 @@ RSpec.describe 'Updating the container expiration policy' do
it_behaves_like 'rejecting invalid regex for', :name_regex
it_behaves_like 'rejecting invalid regex for', :name_regex_keep
+ it_behaves_like 'rejecting blank name_regex when enabled'
end
RSpec.shared_examples 'denying the mutation request' do
diff --git a/spec/requests/api/graphql/mutations/container_repository/destroy_spec.rb b/spec/requests/api/graphql/mutations/container_repository/destroy_spec.rb
new file mode 100644
index 00000000000..645edfc2e43
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/container_repository/destroy_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Destroying a container repository' do
+ using RSpec::Parameterized::TableSyntax
+
+ include GraphqlHelpers
+
+ let_it_be_with_reload(:container_repository) { create(:container_repository) }
+ let_it_be(:user) { create(:user) }
+
+ let(:project) { container_repository.project }
+ let(:id) { container_repository.to_global_id.to_s }
+
+ let(:query) do
+ <<~GQL
+ containerRepository {
+ #{all_graphql_fields_for('ContainerRepository')}
+ }
+ errors
+ GQL
+ end
+
+ let(:params) { { id: container_repository.to_global_id.to_s } }
+ let(:mutation) { graphql_mutation(:destroy_container_repository, params, query) }
+ let(:mutation_response) { graphql_mutation_response(:destroyContainerRepository) }
+ let(:container_repository_mutation_response) { mutation_response['containerRepository'] }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ stub_container_registry_tags(tags: %w[a b c])
+ end
+
+ shared_examples 'destroying the container repository' do
+ it 'destroy the container repository' do
+ expect(::Packages::CreateEventService)
+ .to receive(:new).with(nil, user, event_name: :delete_repository, scope: :container).and_call_original
+ expect(DeleteContainerRepositoryWorker)
+ .to receive(:perform_async).with(user.id, container_repository.id)
+
+ expect { subject }.to change { ::Packages::Event.count }.by(1)
+
+ expect(container_repository_mutation_response).to match_schema('graphql/container_repository')
+ expect(container_repository_mutation_response['status']).to eq('DELETE_SCHEDULED')
+ end
+
+ it_behaves_like 'returning response status', :success
+ end
+
+ shared_examples 'denying the mutation request' do
+ it 'does not destroy the container repository' do
+ expect(DeleteContainerRepositoryWorker)
+ .not_to receive(:perform_async).with(user.id, container_repository.id)
+
+ expect { subject }.not_to change { ::Packages::Event.count }
+
+ expect(mutation_response).to be_nil
+ end
+
+ it_behaves_like 'returning response status', :success
+ end
+
+ describe 'post graphql mutation' do
+ subject { post_graphql_mutation(mutation, current_user: user) }
+
+ context 'with valid id' do
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'destroying the container repository'
+ :developer | 'destroying the container repository'
+ :reporter | 'denying the mutation request'
+ :guest | 'denying the mutation request'
+ :anonymous | 'denying the mutation request'
+ end
+
+ with_them do
+ before do
+ project.send("add_#{user_role}", user) unless user_role == :anonymous
+ end
+
+ it_behaves_like params[:shared_examples_name]
+ end
+ end
+
+ context 'with invalid id' do
+ let(:params) { { id: 'gid://gitlab/ContainerRepository/5555' } }
+
+ it_behaves_like 'denying the mutation request'
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb b/spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb
new file mode 100644
index 00000000000..c91437fa355
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Creation of a new Custom Emoji' do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ let(:attributes) do
+ {
+ name: 'my_new_emoji',
+ url: 'https://example.com/image.png',
+ group_path: group.full_path
+ }
+ end
+
+ let(:mutation) do
+ graphql_mutation(:create_custom_emoji, attributes)
+ end
+
+ context 'when the user has no permission' do
+ it 'does not create custom emoji' do
+ expect { post_graphql_mutation(mutation, current_user: current_user) }.not_to change(CustomEmoji, :count)
+ end
+ end
+
+ context 'when user has permission' do
+ before do
+ group.add_developer(current_user)
+ end
+
+ it 'creates custom emoji' do
+ expect { post_graphql_mutation(mutation, current_user: current_user) }.to change(CustomEmoji, :count).by(1)
+
+ gql_response = graphql_mutation_response(:create_custom_emoji)
+ expect(gql_response['errors']).to eq([])
+ expect(gql_response['customEmoji']['name']).to eq(attributes[:name])
+ expect(gql_response['customEmoji']['url']).to eq(attributes[:url])
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/labels/create_spec.rb b/spec/requests/api/graphql/mutations/labels/create_spec.rb
new file mode 100644
index 00000000000..28284408306
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/labels/create_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Labels::Create do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+
+ let(:params) do
+ {
+ 'title' => 'foo',
+ 'description' => 'some description',
+ 'color' => '#FF0000'
+ }
+ end
+
+ let(:mutation) { graphql_mutation(:label_create, params.merge(extra_params)) }
+
+ subject { post_graphql_mutation(mutation, current_user: current_user) }
+
+ def mutation_response
+ graphql_mutation_response(:label_create)
+ end
+
+ shared_examples_for 'labels create mutation' do
+ context 'when the user does not have permission to create a label' do
+ it_behaves_like 'a mutation that returns a top-level access error'
+
+ it 'does not create the label' do
+ expect { subject }.not_to change { Label.count }
+ end
+ end
+
+ context 'when the user has permission to create a label' do
+ before do
+ parent.add_developer(current_user)
+ end
+
+ context 'when the parent (project_path or group_path) param is given' do
+ it 'creates the label' do
+ expect { subject }.to change { Label.count }.to(1)
+
+ expect(mutation_response).to include(
+ 'label' => a_hash_including(params))
+ end
+
+ it 'does not create a label when there are errors' do
+ label_factory = parent.is_a?(Group) ? :group_label : :label
+ create(label_factory, title: 'foo', parent.class.name.underscore.to_sym => parent)
+
+ expect { subject }.not_to change { Label.count }
+
+ expect(mutation_response).to have_key('label')
+ expect(mutation_response['label']).to be_nil
+ expect(mutation_response['errors'].first).to eq('Title has already been taken')
+ end
+ end
+ end
+ end
+
+ context 'when creating a project label' do
+ let_it_be(:parent) { create(:project) }
+ let(:extra_params) { { project_path: parent.full_path } }
+
+ it_behaves_like 'labels create mutation'
+ end
+
+ context 'when creating a group label' do
+ let_it_be(:parent) { create(:group) }
+ let(:extra_params) { { group_path: parent.full_path } }
+
+ it_behaves_like 'labels create mutation'
+ end
+
+ context 'when neither project_path nor group_path param is given' do
+ let(:mutation) { graphql_mutation(:label_create, params) }
+
+ it_behaves_like 'a mutation that returns top-level errors',
+ errors: ['Exactly one of group_path or project_path arguments is required']
+
+ it 'does not create the label' do
+ expect { subject }.not_to change { Label.count }
+ end
+ end
+end
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 81d13b29dde..2a39757e103 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,9 +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' do
- let(:match_errors) { include(/is not a valid Global ID/) }
- end
+ it_behaves_like 'an invalid argument to the mutation', argument_name: :environment_id
end
end
end
@@ -190,9 +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' do
- let(:match_errors) { include(/is not a valid Global ID/) }
- end
+ it_behaves_like 'an invalid argument to the mutation', argument_name: :cluster_id
end
end
@@ -213,35 +209,26 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create do
it_behaves_like 'a mutation that returns top-level errors', errors: [described_class::ANNOTATION_SOURCE_ARGUMENT_ERROR]
end
- context 'when a non-cluster or environment id is provided' do
- let(:gid) { { environment_id: project.to_global_id.to_s } }
- let(:mutation) do
- variables = {
- starting_at: starting_at,
- ending_at: ending_at,
- dashboard_path: dashboard_path,
- description: description
- }.merge!(gid)
-
- graphql_mutation(:create_annotation, variables)
- end
-
- before do
- project.add_developer(current_user)
- end
+ [:environment_id, :cluster_id].each do |arg_name|
+ context "when #{arg_name} is given an ID of the wrong type" do
+ let(:gid) { global_id_of(project) }
+ let(:mutation) do
+ variables = {
+ starting_at: starting_at,
+ ending_at: ending_at,
+ dashboard_path: dashboard_path,
+ description: description,
+ arg_name => gid
+ }
- describe 'non-environment id' do
- it_behaves_like 'a mutation that returns top-level errors' do
- let(:match_errors) { include(/does not represent an instance of Environment/) }
+ graphql_mutation(:create_annotation, variables)
end
- end
-
- describe 'non-cluster id' do
- let(:gid) { { cluster_id: project.to_global_id.to_s } }
- it_behaves_like 'a mutation that returns top-level errors' do
- let(:match_errors) { include(/does not represent an instance of Clusters::Cluster/) }
+ before do
+ project.add_developer(current_user)
end
+
+ it_behaves_like 'an invalid argument to the mutation', argument_name: arg_name
end
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 9a612c841a2..b956734068c 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
@@ -36,7 +36,7 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Delete do
let(:variables) { { id: GitlabSchema.id_from_object(project).to_s } }
it_behaves_like 'a mutation that returns top-level errors' do
- let(:match_errors) { eq(["#{variables[:id]} is not a valid ID for #{annotation.class}."]) }
+ let(:match_errors) { contain_exactly(include('invalid value for id')) }
end
end
diff --git a/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb
new file mode 100644
index 00000000000..4efa7f9d509
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Repositioning an ImageDiffNote' do
+ include GraphqlHelpers
+
+ let_it_be(:noteable) { create(:merge_request) }
+ let_it_be(:project) { noteable.project }
+ let(:note) { create(:image_diff_note_on_merge_request, noteable: noteable, project: project) }
+ let(:new_position) { { x: 10 } }
+ let(:current_user) { project.creator }
+
+ let(:mutation_variables) do
+ {
+ id: global_id_of(note),
+ position: new_position
+ }
+ end
+
+ let(:mutation) do
+ graphql_mutation(:reposition_image_diff_note, mutation_variables) do
+ <<~QL
+ note {
+ id
+ }
+ errors
+ QL
+ end
+ end
+
+ def mutation_response
+ graphql_mutation_response(:reposition_image_diff_note)
+ end
+
+ it 'updates the note', :aggregate_failures do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.to change { note.reset.position.x }.to(10)
+
+ expect(mutation_response['note']).to eq('id' => global_id_of(note))
+ expect(mutation_response['errors']).to be_empty
+ end
+
+ context 'when the note is not a DiffNote' do
+ let(:note) { project }
+
+ it_behaves_like 'a mutation that returns top-level errors' do
+ let(:match_errors) { include(/does not represent an instance of DiffNote/) }
+ end
+ end
+
+ context 'when a position arg is nil' do
+ let(:new_position) { { x: nil, y: 10 } }
+
+ it 'does not set the property to nil', :aggregate_failures do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.not_to change { note.reset.position.x }
+
+ expect(mutation_response['note']).to eq('id' => global_id_of(note))
+ expect(mutation_response['errors']).to be_empty
+ end
+ end
+
+ context 'when all position args are nil' do
+ let(:new_position) { { x: nil } }
+
+ it_behaves_like 'a mutation that returns top-level errors' do
+ let(:match_errors) { include(/RepositionImageDiffNoteInput! was provided invalid value/) }
+ end
+
+ it 'contains an explanation for the error' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ explanation = graphql_errors.first['extensions']['problems'].first['explanation']
+
+ expect(explanation).to eq('At least one property of `UpdateDiffImagePositionInput` must be set')
+ end
+ end
+end
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 efa2ceb65c2..713b26a6a9b 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
@@ -20,6 +20,7 @@ RSpec.describe 'Updating an image DiffNote' do
position_type: 'image'
)
end
+
let_it_be(:updated_body) { 'Updated body' }
let_it_be(:updated_width) { 50 }
let_it_be(:updated_height) { 100 }
@@ -31,7 +32,7 @@ RSpec.describe 'Updating an image DiffNote' do
height: updated_height,
x: updated_x,
y: updated_y
- }
+ }.compact.presence
end
let!(:diff_note) do
@@ -45,10 +46,11 @@ RSpec.describe 'Updating an image DiffNote' do
let(:mutation) do
variables = {
id: GitlabSchema.id_from_object(diff_note).to_s,
- body: updated_body,
- position: updated_position
+ body: updated_body
}
+ variables[:position] = updated_position if updated_position
+
graphql_mutation(:update_image_diff_note, variables)
end
diff --git a/spec/requests/api/graphql/mutations/releases/create_spec.rb b/spec/requests/api/graphql/mutations/releases/create_spec.rb
new file mode 100644
index 00000000000..d745eb3083d
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/releases/create_spec.rb
@@ -0,0 +1,375 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Creation of a new release' do
+ include GraphqlHelpers
+ include Presentable
+
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:milestone_12_3) { create(:milestone, project: project, title: '12.3') }
+ let_it_be(:milestone_12_4) { create(:milestone, project: project, title: '12.4') }
+ let_it_be(:public_user) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:developer) { create(:user) }
+
+ let(:mutation_name) { :release_create }
+
+ let(:tag_name) { 'v7.12.5'}
+ let(:ref) { 'master'}
+ let(:name) { 'Version 7.12.5'}
+ let(:description) { 'Release 7.12.5 :rocket:' }
+ let(:released_at) { '2018-12-10' }
+ let(:milestones) { [milestone_12_3.title, milestone_12_4.title] }
+ let(:asset_link) { { name: 'An asset link', url: 'https://gitlab.example.com/link', directAssetPath: '/permanent/link', linkType: 'OTHER' } }
+ let(:assets) { { links: [asset_link] } }
+
+ let(:mutation_arguments) do
+ {
+ projectPath: project.full_path,
+ tagName: tag_name,
+ ref: ref,
+ name: name,
+ description: description,
+ releasedAt: released_at,
+ milestones: milestones,
+ assets: assets
+ }
+ end
+
+ let(:mutation) do
+ graphql_mutation(mutation_name, mutation_arguments, <<~FIELDS)
+ release {
+ tagName
+ name
+ description
+ releasedAt
+ createdAt
+ milestones {
+ nodes {
+ title
+ }
+ }
+ assets {
+ links {
+ nodes {
+ name
+ url
+ linkType
+ external
+ directAssetUrl
+ }
+ }
+ }
+ }
+ errors
+ FIELDS
+ end
+
+ let(:create_release) { post_graphql_mutation(mutation, current_user: current_user) }
+ let(:mutation_response) { graphql_mutation_response(mutation_name)&.with_indifferent_access }
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ before do
+ project.add_guest(guest)
+ project.add_reporter(reporter)
+ project.add_developer(developer)
+
+ stub_default_url_options(host: 'www.example.com')
+ end
+
+ shared_examples 'no errors' do
+ it 'returns no errors' do
+ create_release
+
+ expect(graphql_errors).not_to be_present
+ end
+ end
+
+ shared_examples 'top-level error with message' do |error_message|
+ it 'returns a top-level error with message' do
+ create_release
+
+ expect(mutation_response).to be_nil
+ expect(graphql_errors.count).to eq(1)
+ expect(graphql_errors.first['message']).to eq(error_message)
+ end
+ end
+
+ shared_examples 'errors-as-data with message' do |error_message|
+ it 'returns an error-as-data with message' do
+ create_release
+
+ expect(mutation_response[:release]).to be_nil
+ expect(mutation_response[:errors].count).to eq(1)
+ expect(mutation_response[:errors].first).to match(error_message)
+ end
+ end
+
+ context 'when the current user has access to create releases' do
+ let(:current_user) { developer }
+
+ context 'when all available mutation arguments are provided' do
+ it_behaves_like 'no errors'
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ it 'returns the new release data' do
+ create_release
+
+ release = mutation_response[:release]
+ expected_direct_asset_url = Gitlab::Routing.url_helpers.project_release_url(project, Release.find_by(tag: tag_name)) << "/downloads#{asset_link[:directAssetPath]}"
+
+ expected_attributes = {
+ tagName: tag_name,
+ name: name,
+ description: description,
+ releasedAt: Time.parse(released_at).utc.iso8601,
+ createdAt: Time.current.utc.iso8601,
+ assets: {
+ links: {
+ nodes: [{
+ name: asset_link[:name],
+ url: asset_link[:url],
+ linkType: asset_link[:linkType],
+ external: true,
+ directAssetUrl: expected_direct_asset_url
+ }]
+ }
+ }
+ }
+
+ expect(release).to include(expected_attributes)
+
+ # Right now the milestones are returned in a non-deterministic order.
+ # This `milestones` test should be moved up into the expect(release)
+ # above (and `.to include` updated to `.to eq`) once
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/259012 is addressed.
+ expect(release['milestones']['nodes']).to match_array([
+ { 'title' => '12.4' },
+ { 'title' => '12.3' }
+ ])
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+
+ context 'when only the required mutation arguments are provided' do
+ let(:mutation_arguments) { super().slice(:projectPath, :tagName, :ref) }
+
+ it_behaves_like 'no errors'
+
+ it 'returns the new release data' do
+ create_release
+
+ expected_response = {
+ tagName: tag_name,
+ name: tag_name,
+ description: nil,
+ releasedAt: Time.current.utc.iso8601,
+ createdAt: Time.current.utc.iso8601,
+ milestones: {
+ nodes: []
+ },
+ assets: {
+ links: {
+ nodes: []
+ }
+ }
+ }.with_indifferent_access
+
+ expect(mutation_response[:release]).to eq(expected_response)
+ end
+ end
+
+ context 'when the provided tag already exists' do
+ let(:tag_name) { 'v1.1.0' }
+
+ it_behaves_like 'no errors'
+
+ it 'does not create a new tag' do
+ expect { create_release }.not_to change { Project.find_by_id(project.id).repository.tag_count }
+ end
+ end
+
+ context 'when the provided tag does not already exist' do
+ let(:tag_name) { 'v7.12.5-alpha' }
+
+ it_behaves_like 'no errors'
+
+ it 'creates a new tag' do
+ expect { create_release }.to change { Project.find_by_id(project.id).repository.tag_count }.by(1)
+ end
+ end
+
+ context 'when a local timezone is provided for releasedAt' do
+ let(:released_at) { Time.parse(super()).in_time_zone('Hawaii').iso8601 }
+
+ it_behaves_like 'no errors'
+
+ it 'returns the correct releasedAt date in UTC' do
+ create_release
+
+ expect(mutation_response[:release]).to include({ releasedAt: Time.parse(released_at).utc.iso8601 })
+ end
+ end
+
+ context 'when no releasedAt is provided' do
+ let(:mutation_arguments) { super().except(:releasedAt) }
+
+ it_behaves_like 'no errors'
+
+ it 'sets releasedAt to the current time' do
+ create_release
+
+ expect(mutation_response[:release]).to include({ releasedAt: Time.current.utc.iso8601 })
+ end
+ end
+
+ context "when a release asset doesn't include an explicit linkType" do
+ let(:asset_link) { super().except(:linkType) }
+
+ it_behaves_like 'no errors'
+
+ it 'defaults the linkType to OTHER' do
+ create_release
+
+ returned_asset_link_type = mutation_response.dig(:release, :assets, :links, :nodes, 0, :linkType)
+
+ expect(returned_asset_link_type).to eq('OTHER')
+ end
+ end
+
+ context "when a release asset doesn't include a directAssetPath" do
+ let(:asset_link) { super().except(:directAssetPath) }
+
+ it_behaves_like 'no errors'
+
+ it 'returns the provided url as the directAssetUrl' do
+ create_release
+
+ returned_asset_link_type = mutation_response.dig(:release, :assets, :links, :nodes, 0, :directAssetUrl)
+
+ expect(returned_asset_link_type).to eq(asset_link[:url])
+ end
+ end
+
+ context 'empty milestones' do
+ shared_examples 'no associated milestones' do
+ it_behaves_like 'no errors'
+
+ it 'creates a release with no associated milestones' do
+ create_release
+
+ returned_milestones = mutation_response.dig(:release, :milestones, :nodes)
+
+ expect(returned_milestones.count).to eq(0)
+ end
+ end
+
+ context 'when the milestones parameter is not provided' do
+ let(:mutation_arguments) { super().except(:milestones) }
+
+ it_behaves_like 'no associated milestones'
+ end
+
+ context 'when the milestones parameter is null' do
+ let(:milestones) { nil }
+
+ it_behaves_like 'no associated milestones'
+ end
+
+ context 'when the milestones parameter is an empty array' do
+ let(:milestones) { [] }
+
+ it_behaves_like 'no associated milestones'
+ end
+ end
+
+ context 'validation' do
+ context 'when a release is already associated to the specified tag' do
+ before do
+ create(:release, project: project, tag: tag_name)
+ end
+
+ it_behaves_like 'errors-as-data with message', 'Release already exists'
+ end
+
+ context "when a provided milestone doesn\'t exist" do
+ let(:milestones) { ['a fake milestone'] }
+
+ it_behaves_like 'errors-as-data with message', 'Milestone(s) not found: a fake milestone'
+ end
+
+ context "when a provided milestone belongs to a different project than the release" do
+ let(:milestone_in_different_project) { create(:milestone, title: 'different milestone') }
+ let(:milestones) { [milestone_in_different_project.title] }
+
+ it_behaves_like 'errors-as-data with message', "Milestone(s) not found: different milestone"
+ end
+
+ context 'when two release assets share the same name' do
+ let(:asset_link_1) { { name: 'My link', url: 'https://example.com/1' } }
+ let(:asset_link_2) { { name: 'My link', url: 'https://example.com/2' } }
+ let(:assets) { { links: [asset_link_1, asset_link_2] } }
+
+ # Right now the raw Postgres error message is sent to the user as the validation message.
+ # We should catch this validation error and return a nicer message:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/277087
+ it_behaves_like 'errors-as-data with message', 'PG::UniqueViolation'
+ end
+
+ context 'when two release assets share the same URL' do
+ let(:asset_link_1) { { name: 'My first link', url: 'https://example.com' } }
+ let(:asset_link_2) { { name: 'My second link', url: 'https://example.com' } }
+ let(:assets) { { links: [asset_link_1, asset_link_2] } }
+
+ # Same note as above about the ugly error message
+ it_behaves_like 'errors-as-data with message', 'PG::UniqueViolation'
+ end
+
+ context 'when the provided tag name is HEAD' do
+ let(:tag_name) { 'HEAD' }
+
+ it_behaves_like 'errors-as-data with message', 'Tag name invalid'
+ end
+
+ context 'when the provided tag name is empty' do
+ let(:tag_name) { '' }
+
+ it_behaves_like 'errors-as-data with message', 'Tag name invalid'
+ end
+
+ context "when the provided tag doesn't already exist, and no ref parameter was provided" do
+ let(:ref) { nil }
+ let(:tag_name) { 'v7.12.5-beta' }
+
+ it_behaves_like 'errors-as-data with message', 'Ref is not specified'
+ end
+ end
+ end
+
+ context "when the current user doesn't have access to create releases" do
+ expected_error_message = "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+
+ context 'when the current user is a Reporter' do
+ let(:current_user) { reporter }
+
+ it_behaves_like 'top-level error with message', expected_error_message
+ end
+
+ context 'when the current user is a Guest' do
+ let(:current_user) { guest }
+
+ it_behaves_like 'top-level error with message', expected_error_message
+ end
+
+ context 'when the current user is a public user' do
+ let(:current_user) { public_user }
+
+ it_behaves_like 'top-level error with message', expected_error_message
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb b/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb
index b71f87d2702..1be8ce142ac 100644
--- a/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb
@@ -53,10 +53,11 @@ RSpec.describe 'Destroying a Snippet' do
let!(:snippet_gid) { project.to_gid.to_s }
it 'returns an error' do
+ err_message = %Q["#{snippet_gid}" does not represent an instance of Snippet]
+
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."))
+ expect(graphql_errors).to include(a_hash_including('message' => a_string_including(err_message)))
end
it 'does not destroy the Snippet' do
diff --git a/spec/requests/api/graphql/mutations/todos/create_spec.rb b/spec/requests/api/graphql/mutations/todos/create_spec.rb
new file mode 100644
index 00000000000..aca00519682
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/todos/create_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Create a todo' do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:target) { create(:issue) }
+
+ let(:input) do
+ {
+ 'targetId' => target.to_global_id.to_s
+ }
+ end
+
+ let(:mutation) { graphql_mutation(:todoCreate, input) }
+
+ let(:mutation_response) { graphql_mutation_response(:todoCreate) }
+
+ context 'the user is not allowed to create todo' do
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when user has permissions to create todo' do
+ before do
+ target.project.add_guest(current_user)
+ end
+
+ it 'creates todo' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['todo']['body']).to eq(target.title)
+ expect(mutation_response['todo']['state']).to eq('pending')
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb b/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb
new file mode 100644
index 00000000000..3e96d5c5058
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Restoring many Todos' do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:author) { create(:user) }
+ let_it_be(:other_user) { create(:user) }
+
+ let_it_be(:todo1) { create(:todo, user: current_user, author: author, state: :done) }
+ let_it_be(:todo2) { create(:todo, user: current_user, author: author, state: :done) }
+
+ let_it_be(:other_user_todo) { create(:todo, user: other_user, author: author, state: :done) }
+
+ let(:input_ids) { [todo1, todo2].map { |obj| global_id_of(obj) } }
+ let(:input) { { ids: input_ids } }
+
+ let(:mutation) do
+ graphql_mutation(:todo_restore_many, input,
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ updatedIds
+ todos {
+ id
+ state
+ }
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:todo_restore_many)
+ end
+
+ it 'restores many todos' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(todo1.reload.state).to eq('pending')
+ expect(todo2.reload.state).to eq('pending')
+ expect(other_user_todo.reload.state).to eq('done')
+
+ expect(mutation_response).to include(
+ 'errors' => be_empty,
+ 'updatedIds' => match_array(input_ids),
+ 'todos' => contain_exactly(
+ { 'id' => global_id_of(todo1), 'state' => 'pending' },
+ { 'id' => global_id_of(todo2), 'state' => 'pending' }
+ )
+ )
+ end
+
+ context 'when using an invalid gid' do
+ let(:input_ids) { [global_id_of(author)] }
+ let(:invalid_gid_error) { /does not represent an instance of #{todo1.class}/ }
+
+ it 'contains the expected error' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ errors = json_response['errors']
+ expect(errors).not_to be_blank
+ expect(errors.first['message']).to match(invalid_gid_error)
+
+ expect(todo1.reload.state).to eq('done')
+ expect(todo2.reload.state).to eq('done')
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/namespace/root_storage_statistics_spec.rb b/spec/requests/api/graphql/namespace/root_storage_statistics_spec.rb
index 44e68c59248..37cc502103d 100644
--- a/spec/requests/api/graphql/namespace/root_storage_statistics_spec.rb
+++ b/spec/requests/api/graphql/namespace/root_storage_statistics_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'rendering namespace statistics' do
include GraphqlHelpers
let(:namespace) { user.namespace }
- let!(:statistics) { create(:namespace_root_storage_statistics, namespace: namespace, packages_size: 5.gigabytes) }
+ let!(:statistics) { create(:namespace_root_storage_statistics, namespace: namespace, packages_size: 5.gigabytes, uploads_size: 3.gigabytes) }
let(:user) { create(:user) }
let(:query) do
@@ -28,6 +28,12 @@ RSpec.describe 'rendering namespace statistics' do
expect(graphql_data['namespace']['rootStorageStatistics']).not_to be_blank
expect(graphql_data['namespace']['rootStorageStatistics']['packagesSize']).to eq(5.gigabytes)
end
+
+ it 'includes uploads size if the user can read the statistics' do
+ post_graphql(query, current_user: user)
+
+ expect(graphql_data_at(:namespace, :root_storage_statistics, :uploads_size)).to eq(3.gigabytes)
+ end
end
it_behaves_like 'a working namespace with storage statistics query'
diff --git a/spec/requests/api/graphql/project/alert_management/integrations_spec.rb b/spec/requests/api/graphql/project/alert_management/integrations_spec.rb
new file mode 100644
index 00000000000..b13805a61ce
--- /dev/null
+++ b/spec/requests/api/graphql/project/alert_management/integrations_spec.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'getting Alert Management Integrations' do
+ include ::Gitlab::Routing
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:prometheus_service) { create(:prometheus_service, project: project) }
+ let_it_be(:project_alerting_setting) { create(:project_alerting_setting, project: project) }
+ let_it_be(:active_http_integration) { create(:alert_management_http_integration, project: project) }
+ let_it_be(:inactive_http_integration) { create(:alert_management_http_integration, :inactive, project: project) }
+ let_it_be(:other_project_http_integration) { create(:alert_management_http_integration) }
+
+ let(:fields) do
+ <<~QUERY
+ nodes {
+ #{all_graphql_fields_for('AlertManagementIntegration')}
+ }
+ QUERY
+ end
+
+ let(:query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ query_graphql_field('alertManagementIntegrations', {}, fields)
+ )
+ end
+
+ context 'with integrations' do
+ let(:integrations) { graphql_data.dig('project', 'alertManagementIntegrations', 'nodes') }
+
+ context 'without project permissions' do
+ let(:user) { create(:user) }
+
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it { expect(integrations).to be_nil }
+ end
+
+ context 'with project permissions' do
+ before do
+ project.add_maintainer(current_user)
+ post_graphql(query, current_user: current_user)
+ end
+
+ let(:http_integration) { integrations.first }
+ let(:prometheus_integration) { integrations.second }
+
+ it_behaves_like 'a working graphql query'
+
+ it { expect(integrations.size).to eq(2) }
+
+ it 'returns the correct properties of the integrations' do
+ expect(http_integration).to include(
+ 'id' => GitlabSchema.id_from_object(active_http_integration).to_s,
+ 'type' => 'HTTP',
+ 'name' => active_http_integration.name,
+ 'active' => active_http_integration.active,
+ 'token' => active_http_integration.token,
+ 'url' => active_http_integration.url,
+ 'apiUrl' => nil
+ )
+
+ expect(prometheus_integration).to include(
+ 'id' => GitlabSchema.id_from_object(prometheus_service).to_s,
+ 'type' => 'PROMETHEUS',
+ 'name' => 'Prometheus',
+ 'active' => prometheus_service.manual_configuration?,
+ 'token' => project_alerting_setting.token,
+ 'url' => "http://localhost/#{project.full_path}/prometheus/alerts/notify.json",
+ 'apiUrl' => prometheus_service.api_url
+ )
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/container_repositories_spec.rb b/spec/requests/api/graphql/project/container_repositories_spec.rb
new file mode 100644
index 00000000000..7e32f54bf1d
--- /dev/null
+++ b/spec/requests/api/graphql/project/container_repositories_spec.rb
@@ -0,0 +1,145 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'getting container repositories in a project' do
+ using RSpec::Parameterized::TableSyntax
+ include GraphqlHelpers
+
+ let_it_be_with_reload(:project) { create(:project, :private) }
+ let_it_be(:container_repository) { create(:container_repository, project: project) }
+ let_it_be(:container_repositories_delete_scheduled) { create_list(:container_repository, 2, :status_delete_scheduled, project: project) }
+ let_it_be(:container_repositories_delete_failed) { create_list(:container_repository, 2, :status_delete_failed, project: project) }
+ let_it_be(:container_repositories) { [container_repository, container_repositories_delete_scheduled, container_repositories_delete_failed].flatten }
+ let_it_be(:container_expiration_policy) { project.container_expiration_policy }
+
+ let(:fields) do
+ <<~GQL
+ edges {
+ node {
+ #{all_graphql_fields_for('container_repositories'.classify)}
+ }
+ }
+ GQL
+ end
+
+ let(:query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ query_graphql_field('container_repositories', {}, fields)
+ )
+ end
+
+ let(:user) { project.owner }
+ let(:variables) { {} }
+ let(:container_repositories_response) { graphql_data.dig('project', 'containerRepositories', 'edges') }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ container_repositories.each do |repository|
+ stub_container_registry_tags(repository: repository.path, tags: %w(tag1 tag2 tag3), with_manifest: false)
+ end
+ end
+
+ subject { post_graphql(query, current_user: user, variables: variables) }
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ subject
+ end
+
+ it 'matches the JSON schema' do
+ expect(container_repositories_response).to match_schema('graphql/container_repositories')
+ end
+ end
+
+ context 'with different permissions' do
+ let_it_be(:user) { create(:user) }
+
+ where(:project_visibility, :role, :access_granted, :can_delete) do
+ :private | :maintainer | true | true
+ :private | :developer | true | true
+ :private | :reporter | true | false
+ :private | :guest | false | false
+ :private | :anonymous | false | false
+ :public | :maintainer | true | true
+ :public | :developer | true | true
+ :public | :reporter | true | false
+ :public | :guest | true | false
+ :public | :anonymous | true | false
+ end
+
+ with_them do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility.to_s.upcase, false))
+ project.add_user(user, role) unless role == :anonymous
+ end
+
+ it 'return the proper response' do
+ subject
+
+ if access_granted
+ expect(container_repositories_response.size).to eq(container_repositories.size)
+ container_repositories_response.each do |repository_response|
+ expect(repository_response.dig('node', 'canDelete')).to eq(can_delete)
+ end
+ else
+ expect(container_repositories_response).to eq(nil)
+ end
+ end
+ end
+ end
+
+ context 'limiting the number of repositories' do
+ let(:limit) { 1 }
+ let(:variables) do
+ { path: project.full_path, n: limit }
+ end
+
+ let(:query) do
+ <<~GQL
+ query($path: ID!, $n: Int) {
+ project(fullPath: $path) {
+ containerRepositories(first: $n) { #{fields} }
+ }
+ }
+ GQL
+ end
+
+ it 'only returns N repositories' do
+ subject
+
+ expect(container_repositories_response.size).to eq(limit)
+ end
+ end
+
+ context 'filter by name' do
+ let_it_be(:container_repository) { create(:container_repository, name: 'fooBar', project: project) }
+
+ let(:name) { 'ooba' }
+ let(:query) do
+ <<~GQL
+ query($path: ID!, $name: String) {
+ project(fullPath: $path) {
+ containerRepositories(name: $name) { #{fields} }
+ }
+ }
+ GQL
+ end
+
+ let(:variables) do
+ { path: project.full_path, name: name }
+ end
+
+ before do
+ stub_container_registry_tags(repository: container_repository.path, tags: %w(tag4 tag5 tag6), with_manifest: false)
+ end
+
+ it 'returns the searched container repository' do
+ subject
+
+ expect(container_repositories_response.size).to eq(1)
+ expect(container_repositories_response.first.dig('node', 'id')).to eq(container_repository.to_global_id.to_s)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb b/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb
index cd84ce9cb96..c7d327a62af 100644
--- a/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb
+++ b/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb
@@ -29,10 +29,12 @@ RSpec.describe 'sentry errors requests' do
let(:error_data) { graphql_data.dig('project', 'sentryErrors', 'detailedError') }
- it_behaves_like 'a working graphql query' do
- before do
- post_graphql(query, current_user: current_user)
- end
+ it 'returns a successful response', :aggregate_failures, :quarantine do
+ post_graphql(query, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(graphql_errors).to be_nil
+ expect(json_response.keys).to include('data')
end
context 'when data is loading via reactive cache' do
@@ -191,7 +193,7 @@ RSpec.describe 'sentry errors requests' do
describe 'getting a stack trace' do
let_it_be(:sentry_stack_trace) { build(:error_tracking_error_event) }
- let(:sentry_gid) { Gitlab::ErrorTracking::DetailedError.new(id: 1).to_global_id.to_s }
+ let(:sentry_gid) { global_id_of(Gitlab::ErrorTracking::DetailedError.new(id: 1)) }
let(:stack_trace_fields) do
all_graphql_fields_for('SentryErrorStackTrace'.classify)
diff --git a/spec/requests/api/graphql/project/grafana_integration_spec.rb b/spec/requests/api/graphql/project/grafana_integration_spec.rb
index 688959e622d..9b24698f40c 100644
--- a/spec/requests/api/graphql/project/grafana_integration_spec.rb
+++ b/spec/requests/api/graphql/project/grafana_integration_spec.rb
@@ -45,7 +45,6 @@ RSpec.describe 'Getting Grafana Integration' do
it_behaves_like 'a working graphql query'
- specify { expect(integration_data['token']).to eql grafana_integration.masked_token }
specify { expect(integration_data['grafanaUrl']).to eql grafana_integration.grafana_url }
specify do
diff --git a/spec/requests/api/graphql/project/issue/design_collection/version_spec.rb b/spec/requests/api/graphql/project/issue/design_collection/version_spec.rb
index 1b654e660e3..4bce3c7fe0f 100644
--- a/spec/requests/api/graphql/project/issue/design_collection/version_spec.rb
+++ b/spec/requests/api/graphql/project/issue/design_collection/version_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe 'Query.project(fullPath).issue(iid).designCollection.version(sha)
create(:design_version, issue: issue,
created_designs: create_list(:design, 3, issue: issue))
end
+
let_it_be(:version) do
create(:design_version, issue: issue,
modified_designs: old_version.designs,
diff --git a/spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb b/spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb
index 640ac95cd86..ee0085718b3 100644
--- a/spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb
+++ b/spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb
@@ -11,12 +11,15 @@ RSpec.describe 'Getting versions related to an issue' do
let_it_be(:version_a) do
create(:design_version, issue: issue)
end
+
let_it_be(:version_b) do
create(:design_version, issue: issue)
end
+
let_it_be(:version_c) do
create(:design_version, issue: issue)
end
+
let_it_be(:version_d) do
create(:design_version, issue: issue)
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 e25453510d5..a671ddc7ab1 100644
--- a/spec/requests/api/graphql/project/issue/designs/notes_spec.rb
+++ b/spec/requests/api/graphql/project/issue/designs/notes_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'Getting designs related to an issue' do
post_graphql(query(note_fields), current_user: nil)
- designs_data = graphql_data['project']['issue']['designs']['designs']
+ designs_data = graphql_data['project']['issue']['designCollection']['designs']
design_data = designs_data['nodes'].first
note_data = design_data['notes']['nodes'].first
@@ -56,7 +56,7 @@ RSpec.describe 'Getting designs related to an issue' do
'issue',
{ iid: design.issue.iid.to_s },
query_graphql_field(
- 'designs', {}, design_node
+ 'designCollection', {}, design_node
)
)
)
diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb
index 40fec6ba068..4f27f08bf98 100644
--- a/spec/requests/api/graphql/project/issues_spec.rb
+++ b/spec/requests/api/graphql/project/issues_spec.rb
@@ -9,10 +9,9 @@ RSpec.describe 'getting an issue list for a project' 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, :with_alert, project: project)]
- end
+ let_it_be(:issue_a, reload: true) { create(:issue, project: project, discussion_locked: true) }
+ let_it_be(:issue_b, reload: true) { create(:issue, :with_alert, project: project) }
+ let_it_be(:issues, reload: true) { [issue_a, issue_b] }
let(:fields) do
<<~QUERY
@@ -414,4 +413,42 @@ RSpec.describe 'getting an issue list for a project' do
expect(response_assignee_ids(issues_data)).to match_array(assignees_as_global_ids(new_issues))
end
end
+
+ describe 'N+1 query checks' do
+ let(:extra_iid_for_second_query) { issue_b.iid.to_s }
+ let(:search_params) { { iids: [issue_a.iid.to_s] } }
+
+ def execute_query
+ query = graphql_query_for(
+ :project,
+ { full_path: project.full_path },
+ query_graphql_field(:issues, search_params, [
+ query_graphql_field(:nodes, nil, requested_fields)
+ ])
+ )
+ post_graphql(query, current_user: current_user)
+ end
+
+ context 'when requesting `user_notes_count`' do
+ let(:requested_fields) { [:user_notes_count] }
+
+ before do
+ create_list(:note_on_issue, 2, noteable: issue_a, project: project)
+ create(:note_on_issue, noteable: issue_b, project: project)
+ end
+
+ include_examples 'N+1 query check'
+ end
+
+ context 'when requesting `user_discussions_count`' do
+ let(:requested_fields) { [:user_discussions_count] }
+
+ before do
+ create_list(:note_on_issue, 2, noteable: issue_a, project: project)
+ create(:note_on_issue, noteable: issue_b, project: project)
+ end
+
+ include_examples 'N+1 query check'
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/jira_import_spec.rb b/spec/requests/api/graphql/project/jira_import_spec.rb
index 1cc30b95162..98a3f08baa6 100644
--- a/spec/requests/api/graphql/project/jira_import_spec.rb
+++ b/spec/requests/api/graphql/project/jira_import_spec.rb
@@ -19,6 +19,7 @@ RSpec.describe 'query Jira import data' do
total_issue_count: 4
)
end
+
let_it_be(:jira_import2) do
create(
:jira_import_state, :finished,
@@ -31,6 +32,7 @@ RSpec.describe 'query Jira import data' do
total_issue_count: 3
)
end
+
let(:query) do
%(
query {
diff --git a/spec/requests/api/graphql/project/merge_requests_spec.rb b/spec/requests/api/graphql/project/merge_requests_spec.rb
index c737e0b8caf..2b8d537f9fc 100644
--- a/spec/requests/api/graphql/project/merge_requests_spec.rb
+++ b/spec/requests/api/graphql/project/merge_requests_spec.rb
@@ -243,6 +243,17 @@ RSpec.describe 'getting merge request listings nested in a project' do
include_examples 'N+1 query check'
end
+
+ context 'when requesting `user_discussions_count`' do
+ let(:requested_fields) { [:user_discussions_count] }
+
+ before do
+ create_list(:note_on_merge_request, 2, noteable: merge_request_a, project: project)
+ create(:note_on_merge_request, noteable: merge_request_c, project: project)
+ end
+
+ include_examples 'N+1 query check'
+ end
end
describe 'sorting and pagination' do
diff --git a/spec/requests/api/graphql/project/project_statistics_spec.rb b/spec/requests/api/graphql/project/project_statistics_spec.rb
index c226b10ab51..b57c594c64f 100644
--- a/spec/requests/api/graphql/project/project_statistics_spec.rb
+++ b/spec/requests/api/graphql/project/project_statistics_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'rendering project statistics' do
include GraphqlHelpers
let(:project) { create(:project) }
- let!(:project_statistics) { create(:project_statistics, project: project, packages_size: 5.gigabytes) }
+ let!(:project_statistics) { create(:project_statistics, project: project, packages_size: 5.gigabytes, uploads_size: 3.gigabytes) }
let(:user) { create(:user) }
let(:query) do
@@ -31,6 +31,12 @@ RSpec.describe 'rendering project statistics' do
expect(graphql_data['project']['statistics']['packagesSize']).to eq(5.gigabytes)
end
+ it 'includes uploads size if the user can read the statistics' do
+ post_graphql(query, current_user: user)
+
+ expect(graphql_data_at(:project, :statistics, :uploadsSize)).to eq(3.gigabytes)
+ end
+
context 'when the project is public' do
let(:project) { create(:project, :public) }
diff --git a/spec/requests/api/graphql/project/release_spec.rb b/spec/requests/api/graphql/project/release_spec.rb
index 8fce29d0dc6..57dbe258ce4 100644
--- a/spec/requests/api/graphql/project/release_spec.rb
+++ b/spec/requests/api/graphql/project/release_spec.rb
@@ -13,7 +13,11 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
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(:base_url_params) { { scope: 'all', release_tag: release.tag } }
+ let(:opened_url_params) { { state: 'opened', **base_url_params } }
+ let(:merged_url_params) { { state: 'merged', **base_url_params } }
+ let(:closed_url_params) { { state: 'closed', **base_url_params } }
+
let(:post_query) { post_graphql(query, current_user: current_user) }
let(:path_prefix) { %w[project release] }
let(:data) { graphql_data.dig(*path) }
@@ -143,7 +147,7 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
'name' => link.name,
'url' => link.url,
'external' => link.external?,
- 'directAssetUrl' => link.filepath ? Gitlab::Routing.url_helpers.project_release_url(project, release) << link.filepath : link.url
+ 'directAssetUrl' => link.filepath ? Gitlab::Routing.url_helpers.project_release_url(project, release) << "/downloads#{link.filepath}" : link.url
}
end
@@ -180,8 +184,11 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
let(:release_fields) do
query_graphql_field(:links, nil, %{
selfUrl
- mergeRequestsUrl
- issuesUrl
+ openedMergeRequestsUrl
+ mergedMergeRequestsUrl
+ closedMergeRequestsUrl
+ openedIssuesUrl
+ closedIssuesUrl
})
end
@@ -190,8 +197,11 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
expect(data).to eq(
'selfUrl' => project_release_url(project, release),
- 'mergeRequestsUrl' => project_merge_requests_url(project, params_for_issues_and_mrs),
- 'issuesUrl' => project_issues_url(project, params_for_issues_and_mrs)
+ 'openedMergeRequestsUrl' => project_merge_requests_url(project, opened_url_params),
+ 'mergedMergeRequestsUrl' => project_merge_requests_url(project, merged_url_params),
+ 'closedMergeRequestsUrl' => project_merge_requests_url(project, closed_url_params),
+ 'openedIssuesUrl' => project_issues_url(project, opened_url_params),
+ 'closedIssuesUrl' => project_issues_url(project, closed_url_params)
)
end
end
diff --git a/spec/requests/api/graphql/project/releases_spec.rb b/spec/requests/api/graphql/project/releases_spec.rb
index 7c57c0e9177..6e364c7d7b5 100644
--- a/spec/requests/api/graphql/project/releases_spec.rb
+++ b/spec/requests/api/graphql/project/releases_spec.rb
@@ -10,6 +10,11 @@ RSpec.describe 'Query.project(fullPath).releases()' do
let_it_be(:reporter) { create(:user) }
let_it_be(:developer) { create(:user) }
+ let(:base_url_params) { { scope: 'all', release_tag: release.tag } }
+ let(:opened_url_params) { { state: 'opened', **base_url_params } }
+ let(:merged_url_params) { { state: 'merged', **base_url_params } }
+ let(:closed_url_params) { { state: 'closed', **base_url_params } }
+
let(:query) do
graphql_query_for(:project, { fullPath: project.full_path },
%{
@@ -37,8 +42,11 @@ RSpec.describe 'Query.project(fullPath).releases()' do
}
links {
selfUrl
- mergeRequestsUrl
- issuesUrl
+ openedMergeRequestsUrl
+ mergedMergeRequestsUrl
+ closedMergeRequestsUrl
+ openedIssuesUrl
+ closedIssuesUrl
}
}
}
@@ -101,8 +109,11 @@ RSpec.describe 'Query.project(fullPath).releases()' do
},
'links' => {
'selfUrl' => project_release_url(project, release),
- 'mergeRequestsUrl' => project_merge_requests_url(project, params_for_issues_and_mrs),
- 'issuesUrl' => project_issues_url(project, params_for_issues_and_mrs)
+ 'openedMergeRequestsUrl' => project_merge_requests_url(project, opened_url_params),
+ 'mergedMergeRequestsUrl' => project_merge_requests_url(project, merged_url_params),
+ 'closedMergeRequestsUrl' => project_merge_requests_url(project, closed_url_params),
+ 'openedIssuesUrl' => project_issues_url(project, opened_url_params),
+ 'closedIssuesUrl' => project_issues_url(project, closed_url_params)
}
)
end
@@ -300,4 +311,77 @@ RSpec.describe 'Query.project(fullPath).releases()' do
it_behaves_like 'no access to any release data'
end
end
+
+ describe 'sorting behavior' do
+ let_it_be(:today) { Time.now }
+ let_it_be(:yesterday) { today - 1.day }
+ let_it_be(:tomorrow) { today + 1.day }
+
+ let_it_be(:project) { create(:project, :repository, :public) }
+
+ let_it_be(:release_v1) { create(:release, project: project, tag: 'v1', released_at: yesterday, created_at: tomorrow) }
+ let_it_be(:release_v2) { create(:release, project: project, tag: 'v2', released_at: today, created_at: yesterday) }
+ let_it_be(:release_v3) { create(:release, project: project, tag: 'v3', released_at: tomorrow, created_at: today) }
+
+ let(:current_user) { developer }
+
+ let(:params) { nil }
+
+ let(:sorted_tags) do
+ graphql_data.dig('project', 'releases', 'nodes').map { |release| release['tagName'] }
+ end
+
+ let(:query) do
+ graphql_query_for(:project, { fullPath: project.full_path },
+ %{
+ releases#{params ? "(#{params})" : ""} {
+ nodes {
+ tagName
+ }
+ }
+ })
+ end
+
+ before do
+ post_query
+ end
+
+ context 'when no sort: parameter is provided' do
+ it 'returns the results with the default sort applied (sort: RELEASED_AT_DESC)' do
+ expect(sorted_tags).to eq(%w(v3 v2 v1))
+ end
+ end
+
+ context 'with sort: RELEASED_AT_DESC' do
+ let(:params) { 'sort: RELEASED_AT_DESC' }
+
+ it 'returns the releases ordered by released_at in descending order' do
+ expect(sorted_tags).to eq(%w(v3 v2 v1))
+ end
+ end
+
+ context 'with sort: RELEASED_AT_ASC' do
+ let(:params) { 'sort: RELEASED_AT_ASC' }
+
+ it 'returns the releases ordered by released_at in ascending order' do
+ expect(sorted_tags).to eq(%w(v1 v2 v3))
+ end
+ end
+
+ context 'with sort: CREATED_DESC' do
+ let(:params) { 'sort: CREATED_DESC' }
+
+ it 'returns the releases ordered by created_at in descending order' do
+ expect(sorted_tags).to eq(%w(v1 v3 v2))
+ end
+ end
+
+ context 'with sort: CREATED_ASC' do
+ let(:params) { 'sort: CREATED_ASC' }
+
+ it 'returns the releases ordered by created_at in ascending order' do
+ expect(sorted_tags).to eq(%w(v2 v3 v1))
+ end
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/terraform/states_spec.rb b/spec/requests/api/graphql/project/terraform/states_spec.rb
new file mode 100644
index 00000000000..8b67b549efa
--- /dev/null
+++ b/spec/requests/api/graphql/project/terraform/states_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'query terraform states' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:terraform_state) { create(:terraform_state, :with_version, :locked, project: project) }
+ let_it_be(:latest_version) { terraform_state.latest_version }
+
+ let(:query) do
+ graphql_query_for(:project, { fullPath: project.full_path },
+ %{
+ terraformStates {
+ count
+ nodes {
+ id
+ name
+ lockedAt
+ createdAt
+ updatedAt
+
+ latestVersion {
+ id
+ createdAt
+ updatedAt
+
+ createdByUser {
+ id
+ }
+
+ job {
+ name
+ }
+ }
+
+ lockedByUser {
+ id
+ }
+ }
+ }
+ })
+ end
+
+ let(:current_user) { project.creator }
+ let(:data) { graphql_data.dig('project', 'terraformStates') }
+
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it 'returns terraform state data', :aggregate_failures do
+ state = data.dig('nodes', 0)
+ version = state['latestVersion']
+
+ expect(state['id']).to eq(terraform_state.to_global_id.to_s)
+ expect(state['name']).to eq(terraform_state.name)
+ expect(state['lockedAt']).to eq(terraform_state.locked_at.iso8601)
+ expect(state['createdAt']).to eq(terraform_state.created_at.iso8601)
+ expect(state['updatedAt']).to eq(terraform_state.updated_at.iso8601)
+ expect(state.dig('lockedByUser', 'id')).to eq(terraform_state.locked_by_user.to_global_id.to_s)
+
+ expect(version['id']).to eq(latest_version.to_global_id.to_s)
+ expect(version['createdAt']).to eq(latest_version.created_at.iso8601)
+ expect(version['updatedAt']).to eq(latest_version.updated_at.iso8601)
+ expect(version.dig('createdByUser', 'id')).to eq(latest_version.created_by_user.to_global_id.to_s)
+ expect(version.dig('job', 'name')).to eq(latest_version.build.name)
+ end
+
+ it 'returns count of terraform states' do
+ count = data.dig('count')
+ expect(count).to be(project.terraform_states.size)
+ end
+
+ context 'unauthorized users' do
+ let(:current_user) { nil }
+
+ it { expect(data).to be_nil }
+ end
+end
diff --git a/spec/requests/api/graphql/read_only_spec.rb b/spec/requests/api/graphql/read_only_spec.rb
index ce8a3f6ef5c..d2a45603886 100644
--- a/spec/requests/api/graphql/read_only_spec.rb
+++ b/spec/requests/api/graphql/read_only_spec.rb
@@ -3,55 +3,11 @@
require 'spec_helper'
RSpec.describe 'Requests on a read-only node' do
- include GraphqlHelpers
-
- before do
- allow(Gitlab::Database).to receive(:read_only?) { true }
- end
-
- context 'mutations' do
- let(:current_user) { note.author }
- let!(:note) { create(:note) }
-
- let(:mutation) do
- variables = {
- id: GitlabSchema.id_from_object(note).to_s
- }
-
- graphql_mutation(:destroy_note, variables)
- end
-
- def mutation_response
- graphql_mutation_response(:destroy_note)
- end
-
- it 'disallows the query' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(json_response['errors'].first['message']).to eq(Mutations::BaseMutation::ERROR_MESSAGE)
- end
-
- it 'does not destroy the Note' do
- expect do
- post_graphql_mutation(mutation, current_user: current_user)
- end.not_to change { Note.count }
- end
- end
-
- context 'read-only queries' do
- let(:current_user) { create(:user) }
- let(:project) { create(:project, :repository) }
-
+ context 'when db is read-only' do
before do
- project.add_developer(current_user)
+ allow(Gitlab::Database).to receive(:read_only?) { true }
end
- it 'allows the query' do
- query = graphql_query_for('project', 'fullPath' => project.full_path)
-
- post_graphql(query, current_user: current_user)
-
- expect(graphql_data['project']).not_to be_nil
- end
+ it_behaves_like 'graphql on a read-only GitLab instance'
end
end
diff --git a/spec/requests/api/graphql/terraform/state/delete_spec.rb b/spec/requests/api/graphql/terraform/state/delete_spec.rb
new file mode 100644
index 00000000000..35927d03b49
--- /dev/null
+++ b/spec/requests/api/graphql/terraform/state/delete_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'delete a terraform state' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user, maintainer_projects: [project]) }
+
+ let(:state) { create(:terraform_state, project: project) }
+ let(:mutation) { graphql_mutation(:terraform_state_delete, id: state.to_global_id.to_s) }
+
+ before do
+ post_graphql_mutation(mutation, current_user: user)
+ end
+
+ include_examples 'a working graphql query'
+
+ it 'deletes the state' do
+ expect { state.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+end
diff --git a/spec/requests/api/graphql/terraform/state/lock_spec.rb b/spec/requests/api/graphql/terraform/state/lock_spec.rb
new file mode 100644
index 00000000000..e4d3b6336ab
--- /dev/null
+++ b/spec/requests/api/graphql/terraform/state/lock_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'lock a terraform state' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user, maintainer_projects: [project]) }
+
+ let(:state) { create(:terraform_state, project: project) }
+ let(:mutation) { graphql_mutation(:terraform_state_lock, id: state.to_global_id.to_s) }
+
+ before do
+ expect(state).not_to be_locked
+ post_graphql_mutation(mutation, current_user: user)
+ end
+
+ include_examples 'a working graphql query'
+
+ it 'locks the state' do
+ expect(state.reload).to be_locked
+ expect(state.locked_by_user).to eq(user)
+ end
+end
diff --git a/spec/requests/api/graphql/terraform/state/unlock_spec.rb b/spec/requests/api/graphql/terraform/state/unlock_spec.rb
new file mode 100644
index 00000000000..e90730f2d8f
--- /dev/null
+++ b/spec/requests/api/graphql/terraform/state/unlock_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'unlock a terraform state' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user, maintainer_projects: [project]) }
+
+ let(:state) { create(:terraform_state, :locked, project: project) }
+ let(:mutation) { graphql_mutation(:terraform_state_unlock, id: state.to_global_id.to_s) }
+
+ before do
+ expect(state).to be_locked
+ post_graphql_mutation(mutation, current_user: user)
+ end
+
+ include_examples 'a working graphql query'
+
+ it 'unlocks the state' do
+ expect(state.reload).not_to be_locked
+ end
+end
diff --git a/spec/requests/api/graphql/user/group_member_query_spec.rb b/spec/requests/api/graphql/user/group_member_query_spec.rb
index 3a16d962214..e47cef8cc37 100644
--- a/spec/requests/api/graphql/user/group_member_query_spec.rb
+++ b/spec/requests/api/graphql/user/group_member_query_spec.rb
@@ -19,6 +19,7 @@ RSpec.describe 'GroupMember' do
}
HEREDOC
end
+
let_it_be(:query) do
graphql_query_for('user', { id: member.user.to_global_id.to_s }, query_graphql_field("groupMemberships", {}, fields))
end
diff --git a/spec/requests/api/graphql/user/project_member_query_spec.rb b/spec/requests/api/graphql/user/project_member_query_spec.rb
index 0790e148caf..01827e94d5d 100644
--- a/spec/requests/api/graphql/user/project_member_query_spec.rb
+++ b/spec/requests/api/graphql/user/project_member_query_spec.rb
@@ -19,6 +19,7 @@ RSpec.describe 'ProjectMember' do
}
HEREDOC
end
+
let_it_be(:query) do
graphql_query_for('user', { id: member.user.to_global_id.to_s }, query_graphql_field("projectMemberships", {}, fields))
end
diff --git a/spec/requests/api/graphql/user_query_spec.rb b/spec/requests/api/graphql/user_query_spec.rb
index 79debd0b7ef..738e120549e 100644
--- a/spec/requests/api/graphql/user_query_spec.rb
+++ b/spec/requests/api/graphql/user_query_spec.rb
@@ -32,22 +32,27 @@ RSpec.describe 'getting user information' do
create(:merge_request, :unique_branches, :unique_author,
source_project: project_a, assignees: [user])
end
+
let_it_be(:assigned_mr_b) do
create(:merge_request, :unique_branches, :unique_author,
source_project: project_b, assignees: [user])
end
+
let_it_be(:assigned_mr_c) do
create(:merge_request, :unique_branches, :unique_author,
source_project: project_b, assignees: [user])
end
+
let_it_be(:authored_mr) do
create(:merge_request, :unique_branches,
source_project: project_a, author: user)
end
+
let_it_be(:authored_mr_b) do
create(:merge_request, :unique_branches,
source_project: project_b, author: user)
end
+
let_it_be(:authored_mr_c) do
create(:merge_request, :unique_branches,
source_project: project_b, author: user)
@@ -59,6 +64,7 @@ RSpec.describe 'getting user information' do
let(:user_params) { { username: user.username } }
before do
+ create(:user_status, user: user)
post_graphql(query, current_user: current_user)
end
@@ -76,9 +82,15 @@ RSpec.describe 'getting user information' do
'username' => presenter.username,
'webUrl' => presenter.web_url,
'avatarUrl' => presenter.avatar_url,
- 'status' => presenter.status,
'email' => presenter.email
))
+
+ expect(graphql_data['user']['status']).to match(
+ a_hash_including(
+ 'emoji' => presenter.status.emoji,
+ 'message' => presenter.status.message,
+ 'availability' => presenter.status.availability.upcase
+ ))
end
describe 'assignedMergeRequests' do
diff --git a/spec/requests/api/graphql_spec.rb b/spec/requests/api/graphql_spec.rb
index 94a66f54e4d..5dc8edb87e9 100644
--- a/spec/requests/api/graphql_spec.rb
+++ b/spec/requests/api/graphql_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'GraphQL' do
include GraphqlHelpers
- let(:query) { graphql_query_for('echo', 'text' => 'Hello world' ) }
+ let(:query) { graphql_query_for('echo', text: 'Hello world' ) }
context 'logging' do
shared_examples 'logging a graphql query' do
diff --git a/spec/requests/api/group_labels_spec.rb b/spec/requests/api/group_labels_spec.rb
index f965a845bbe..72621e2ce5e 100644
--- a/spec/requests/api/group_labels_spec.rb
+++ b/spec/requests/api/group_labels_spec.rb
@@ -7,60 +7,97 @@ RSpec.describe API::GroupLabels do
let(:group) { create(:group) }
let(:subgroup) { create(:group, parent: group) }
let!(:group_member) { create(:group_member, group: group, user: user) }
- let!(:group_label1) { create(:group_label, title: 'feature', group: group) }
+ let!(:group_label1) { create(:group_label, title: 'feature-label', group: group) }
let!(:group_label2) { create(:group_label, title: 'bug', group: group) }
- let!(:subgroup_label) { create(:group_label, title: 'support', group: subgroup) }
+ let!(:subgroup_label) { create(:group_label, title: 'support-label', group: subgroup) }
describe 'GET :id/labels' do
- it 'returns all available labels for the group' do
- get api("/groups/#{group.id}/labels", user)
+ context 'get current group labels' do
+ let(:request) { get api("/groups/#{group.id}/labels", user) }
+ let(:expected_labels) { [group_label1.name, group_label2.name] }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response).to all(match_schema('public_api/v4/labels/label'))
- expect(json_response.size).to eq(2)
- expect(json_response.map {|r| r['name'] }).to contain_exactly('feature', 'bug')
- end
-
- context 'when the with_counts parameter is set' do
- it 'includes counts in the response' do
- get api("/groups/#{group.id}/labels", user), params: { with_counts: true }
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response).to all(match_schema('public_api/v4/labels/label_with_counts'))
- expect(json_response.size).to eq(2)
- expect(json_response.map { |r| r['open_issues_count'] }).to contain_exactly(0, 0)
+ it_behaves_like 'fetches labels'
+
+ context 'when search param is provided' do
+ let(:request) { get api("/groups/#{group.id}/labels?search=lab", user) }
+ let(:expected_labels) { [group_label1.name] }
+
+ it_behaves_like 'fetches labels'
end
- end
- end
- describe 'GET :subgroup_id/labels' do
- context 'when the include_ancestor_groups parameter is not set' do
- it 'returns all available labels for the group and ancestor groups' do
- get api("/groups/#{subgroup.id}/labels", user)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response).to all(match_schema('public_api/v4/labels/label'))
- expect(json_response.size).to eq(3)
- expect(json_response.map {|r| r['name'] }).to contain_exactly('feature', 'bug', 'support')
+ context 'when the with_counts parameter is set' do
+ it 'includes counts in the response' do
+ get api("/groups/#{group.id}/labels", user), params: { with_counts: true }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response).to all(match_schema('public_api/v4/labels/label_with_counts'))
+ expect(json_response.size).to eq(2)
+ expect(json_response.map { |r| r['open_issues_count'] }).to contain_exactly(0, 0)
+ end
+ end
+
+ context 'when include_descendant_groups param is provided' do
+ let!(:project) { create(:project, group: group) }
+ let!(:project_label1) { create(:label, title: 'project-label1', project: project, priority: 3) }
+ let!(:project_label2) { create(:label, title: 'project-bug', project: project) }
+
+ let(:request) { get api("/groups/#{group.id}/labels", user), params: { include_descendant_groups: true } }
+ let(:expected_labels) { [group_label1.name, group_label2.name, subgroup_label.name] }
+
+ it_behaves_like 'fetches labels'
+
+ context 'when search param is provided' do
+ let(:request) { get api("/groups/#{group.id}/labels", user), params: { search: 'lab', include_descendant_groups: true } }
+ let(:expected_labels) { [group_label1.name, subgroup_label.name] }
+
+ it_behaves_like 'fetches labels'
+ end
+
+ context 'when only_group_labels param is false' do
+ let(:request) { get api("/groups/#{group.id}/labels", user), params: { include_descendant_groups: true, only_group_labels: false } }
+ let(:expected_labels) { [group_label1.name, group_label2.name, subgroup_label.name, project_label1.name, project_label2.name] }
+
+ it_behaves_like 'fetches labels'
+
+ context 'when search param is provided' do
+ let(:request) { get api("/groups/#{group.id}/labels", user), params: { search: 'lab', include_descendant_groups: true, only_group_labels: false } }
+ let(:expected_labels) { [group_label1.name, subgroup_label.name, project_label1.name] }
+
+ it_behaves_like 'fetches labels'
+ end
+ end
end
end
- context 'when the include_ancestor_groups parameter is set to false' do
- it 'returns all available labels for the group but not for ancestor groups' do
- get api("/groups/#{subgroup.id}/labels", user), params: { include_ancestor_groups: false }
+ describe 'with subgroup labels' do
+ context 'when the include_ancestor_groups parameter is not set' do
+ let(:request) { get api("/groups/#{subgroup.id}/labels", user) }
+ let(:expected_labels) { [group_label1.name, group_label2.name, subgroup_label.name] }
+
+ it_behaves_like 'fetches labels'
+
+ context 'when search param is provided' do
+ let(:request) { get api("/groups/#{subgroup.id}/labels?search=lab", user) }
+ let(:expected_labels) { [group_label1.name, subgroup_label.name] }
+
+ it_behaves_like 'fetches labels'
+ end
+ end
+
+ context 'when the include_ancestor_groups parameter is set to false' do
+ let(:request) { get api("/groups/#{subgroup.id}/labels", user), params: { include_ancestor_groups: false } }
+ let(:expected_labels) { [subgroup_label.name] }
+
+ it_behaves_like 'fetches labels'
+
+ context 'when search param is provided' do
+ let(:request) { get api("/groups/#{subgroup.id}/labels?search=lab", user), params: { include_ancestor_groups: false } }
+ let(:expected_labels) { [subgroup_label.name] }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response).to all(match_schema('public_api/v4/labels/label'))
- expect(json_response.size).to eq(1)
- expect(json_response.map {|r| r['name'] }).to contain_exactly('support')
+ it_behaves_like 'fetches labels'
+ end
end
end
end
@@ -223,7 +260,7 @@ RSpec.describe API::GroupLabels do
expect(response).to have_gitlab_http_status(:ok)
expect(subgroup.labels[0].name).to eq('New Label')
- expect(group_label1.name).to eq('feature')
+ expect(group_label1.name).to eq(group_label1.title)
end
it 'returns 404 if label does not exist' do
@@ -278,7 +315,7 @@ RSpec.describe API::GroupLabels do
expect(response).to have_gitlab_http_status(:ok)
expect(subgroup.labels[0].name).to eq('New Label')
- expect(group_label1.name).to eq('feature')
+ expect(group_label1.name).to eq(group_label1.title)
end
it 'returns 404 if label does not exist' do
diff --git a/spec/requests/api/import_github_spec.rb b/spec/requests/api/import_github_spec.rb
index bbfb17fe753..5bbcb0c1950 100644
--- a/spec/requests/api/import_github_spec.rb
+++ b/spec/requests/api/import_github_spec.rb
@@ -57,6 +57,22 @@ RSpec.describe API::ImportGithub do
expect(json_response['name']).to eq(project.name)
end
+ it 'returns 201 response when the project is imported successfully from GHE' do
+ allow(Gitlab::LegacyGithubImport::ProjectCreator)
+ .to receive(:new).with(provider_repo, provider_repo.name, user.namespace, user, access_params, type: provider)
+ .and_return(double(execute: project))
+
+ post api("/import/github", user), params: {
+ target_namespace: user.namespace_path,
+ personal_access_token: token,
+ repo_id: non_existing_record_id,
+ github_hostname: "https://github.somecompany.com/"
+ }
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to be_a Hash
+ expect(json_response['name']).to eq(project.name)
+ end
+
it 'returns 422 response when user can not create projects in the chosen namespace' do
other_namespace = create(:group, name: 'other_namespace')
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index ab5f09305ce..6fe77727702 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -253,6 +253,7 @@ RSpec.describe API::Internal::Base do
describe "POST /internal/lfs_authenticate" do
before do
+ stub_lfs_setting(enabled: true)
project.add_developer(user)
end
@@ -293,6 +294,33 @@ RSpec.describe API::Internal::Base do
expect(response).to have_gitlab_http_status(:not_found)
end
+
+ it 'returns a 404 when LFS is disabled on the project' do
+ project.update!(lfs_enabled: false)
+ lfs_auth_user(user.id, project)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'other repository types' do
+ it 'returns the correct information for a project wiki' do
+ wiki = create(:project_wiki, project: project)
+ lfs_auth_user(user.id, wiki)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['username']).to eq(user.username)
+ expect(json_response['repository_http_path']).to eq(wiki.http_url_to_repo)
+ expect(json_response['expires_in']).to eq(Gitlab::LfsToken::DEFAULT_EXPIRE_TIME)
+ expect(Gitlab::LfsToken.new(user).token_valid?(json_response['lfs_token'])).to be_truthy
+ end
+
+ it 'returns a 404 when the container does not support LFS' do
+ snippet = create(:project_snippet)
+ lfs_auth_user(user.id, snippet)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
end
context 'deploy key' do
diff --git a/spec/requests/api/internal/pages_spec.rb b/spec/requests/api/internal/pages_spec.rb
index e58eba02132..9a63e2a8ed5 100644
--- a/spec/requests/api/internal/pages_spec.rb
+++ b/spec/requests/api/internal/pages_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe API::Internal::Pages do
before do
allow(Gitlab::Pages).to receive(:secret).and_return(pages_secret)
+ stub_pages_object_storage(::Pages::DeploymentUploader)
end
describe "GET /internal/pages/status" do
@@ -38,6 +39,12 @@ RSpec.describe API::Internal::Pages do
get api("/internal/pages"), headers: headers, params: { host: host }
end
+ around do |example|
+ freeze_time do
+ example.run
+ end
+ end
+
context 'not authenticated' do
it 'responds with 401 Unauthorized' do
query_host('pages.gitlab.io')
@@ -55,7 +62,9 @@ RSpec.describe API::Internal::Pages do
end
def deploy_pages(project)
+ deployment = create(:pages_deployment, project: project)
project.mark_pages_as_deployed
+ project.update_pages_deployment!(deployment)
end
context 'domain does not exist' do
@@ -182,6 +191,7 @@ RSpec.describe API::Internal::Pages do
expect(json_response['certificate']).to eq(pages_domain.certificate)
expect(json_response['key']).to eq(pages_domain.key)
+ deployment = project.pages_metadatum.pages_deployment
expect(json_response['lookup_paths']).to eq(
[
{
@@ -190,8 +200,12 @@ RSpec.describe API::Internal::Pages do
'https_only' => false,
'prefix' => '/',
'source' => {
- 'type' => 'file',
- 'path' => 'gitlab-org/gitlab-ce/public/'
+ 'type' => 'zip',
+ 'path' => deployment.file.url(expire_at: 1.day.from_now),
+ 'global_id' => "gid://gitlab/PagesDeployment/#{deployment.id}",
+ 'sha256' => deployment.file_sha256,
+ 'file_size' => deployment.size,
+ 'file_count' => deployment.file_count
}
}
]
@@ -218,6 +232,7 @@ RSpec.describe API::Internal::Pages do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('internal/pages/virtual_domain')
+ deployment = project.pages_metadatum.pages_deployment
expect(json_response['lookup_paths']).to eq(
[
{
@@ -226,8 +241,12 @@ RSpec.describe API::Internal::Pages do
'https_only' => false,
'prefix' => '/myproject/',
'source' => {
- 'type' => 'file',
- 'path' => 'mygroup/myproject/public/'
+ 'type' => 'zip',
+ 'path' => deployment.file.url(expire_at: 1.day.from_now),
+ 'global_id' => "gid://gitlab/PagesDeployment/#{deployment.id}",
+ 'sha256' => deployment.file_sha256,
+ 'file_size' => deployment.size,
+ 'file_count' => deployment.file_count
}
}
]
@@ -235,6 +254,20 @@ RSpec.describe API::Internal::Pages do
end
end
+ it 'avoids N+1 queries' do
+ project = create(:project, group: group)
+ deploy_pages(project)
+
+ control = ActiveRecord::QueryRecorder.new { query_host('mygroup.gitlab-pages.io') }
+
+ 3.times do
+ project = create(:project, group: group)
+ deploy_pages(project)
+ end
+
+ expect { query_host('mygroup.gitlab-pages.io') }.not_to exceed_query_limit(control)
+ end
+
context 'group root project' do
it 'responds with the correct domain configuration' do
project = create(:project, group: group, name: 'mygroup.gitlab-pages.io')
@@ -245,6 +278,7 @@ RSpec.describe API::Internal::Pages do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('internal/pages/virtual_domain')
+ deployment = project.pages_metadatum.pages_deployment
expect(json_response['lookup_paths']).to eq(
[
{
@@ -253,8 +287,12 @@ RSpec.describe API::Internal::Pages do
'https_only' => false,
'prefix' => '/',
'source' => {
- 'type' => 'file',
- 'path' => 'mygroup/mygroup.gitlab-pages.io/public/'
+ 'type' => 'zip',
+ 'path' => deployment.file.url(expire_at: 1.day.from_now),
+ 'global_id' => "gid://gitlab/PagesDeployment/#{deployment.id}",
+ 'sha256' => deployment.file_sha256,
+ 'file_size' => deployment.size,
+ 'file_count' => deployment.file_count
}
}
]
diff --git a/spec/requests/api/invitations_spec.rb b/spec/requests/api/invitations_spec.rb
new file mode 100644
index 00000000000..75586970abb
--- /dev/null
+++ b/spec/requests/api/invitations_spec.rb
@@ -0,0 +1,301 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Invitations do
+ let(:maintainer) { create(:user, username: 'maintainer_user') }
+ let(:developer) { create(:user) }
+ let(:access_requester) { create(:user) }
+ let(:stranger) { create(:user) }
+ let(:email) { 'email1@example.com' }
+ let(:email2) { 'email2@example.com' }
+
+ let(:project) do
+ create(:project, :public, creator_id: maintainer.id, namespace: maintainer.namespace) do |project|
+ project.add_developer(developer)
+ project.add_maintainer(maintainer)
+ project.request_access(access_requester)
+ end
+ end
+
+ let!(:group) do
+ create(:group, :public) do |group|
+ group.add_developer(developer)
+ group.add_owner(maintainer)
+ group.request_access(access_requester)
+ end
+ end
+
+ def invitations_url(source, user)
+ api("/#{source.model_name.plural}/#{source.id}/invitations", user)
+ end
+
+ shared_examples 'POST /:source_type/:id/invitations' do |source_type|
+ context "with :source_type == #{source_type.pluralize}" do
+ it_behaves_like 'a 404 response when source is private' do
+ let(:route) do
+ post invitations_url(source, stranger),
+ params: { email: email, access_level: Member::MAINTAINER }
+ end
+ end
+
+ context 'when authenticated as a non-member or member with insufficient rights' do
+ %i[access_requester stranger developer].each do |type|
+ context "as a #{type}" do
+ it 'returns 403' do
+ user = public_send(type)
+
+ post invitations_url(source, user), params: { email: email, access_level: Member::MAINTAINER }
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+ end
+
+ context 'when authenticated as a maintainer/owner' do
+ context 'and new member is already a requester' do
+ it 'does not transform the requester into a proper member' do
+ expect do
+ post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ params: { email: email, access_level: Member::MAINTAINER }
+
+ expect(response).to have_gitlab_http_status(:created)
+ end.not_to change { source.members.count }
+ end
+ end
+
+ it 'invites a new member' do
+ expect do
+ post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ params: { email: email, access_level: Member::DEVELOPER }
+
+ expect(response).to have_gitlab_http_status(:created)
+ end.to change { source.requesters.count }.by(1)
+ end
+
+ it 'invites a list of new email addresses' do
+ expect do
+ email_list = [email, email2].join(',')
+
+ post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ params: { email: email_list, access_level: Member::DEVELOPER }
+
+ expect(response).to have_gitlab_http_status(:created)
+ end.to change { source.requesters.count }.by(2)
+ end
+ end
+
+ context 'access levels' do
+ it 'does not create the member if group level is higher' do
+ parent = create(:group)
+
+ group.update!(parent: parent)
+ project.update!(group: group)
+ parent.add_developer(stranger)
+
+ post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ params: { email: stranger.email, access_level: Member::REPORTER }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['message'][stranger.email]).to eq("Access level should be greater than or equal to Developer inherited membership from group #{parent.name}")
+ end
+
+ it 'creates the member if group level is lower' do
+ parent = create(:group)
+
+ group.update!(parent: parent)
+ project.update!(group: group)
+ parent.add_developer(stranger)
+
+ post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ params: { email: stranger.email, access_level: Member::MAINTAINER }
+
+ expect(response).to have_gitlab_http_status(:created)
+ end
+ end
+
+ context 'access expiry date' do
+ subject do
+ post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ params: { email: email, access_level: Member::DEVELOPER, expires_at: expires_at }
+ end
+
+ context 'when set to a date in the past' do
+ let(:expires_at) { 2.days.ago.to_date }
+
+ it 'does not create a member' do
+ expect do
+ subject
+ end.not_to change { source.members.count }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['message'][email]).to eq('Expires at cannot be a date in the past')
+ end
+ end
+
+ context 'when set to a date in the future' do
+ let(:expires_at) { 2.days.from_now.to_date }
+
+ it 'invites a member' do
+ expect do
+ subject
+ end.to change { source.requesters.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:created)
+ end
+ end
+ end
+
+ it "returns a message if member already exists" do
+ post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ params: { email: maintainer.email, access_level: Member::MAINTAINER }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['message'][maintainer.email]).to eq("Already a member of #{source.name}")
+ end
+
+ it 'returns 404 when the email is not valid' do
+ post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ params: { email: '', access_level: Member::MAINTAINER }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['message']).to eq('Email cannot be blank')
+ end
+
+ it 'returns 404 when the email list is not a valid format' do
+ post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ params: { email: 'email1@example.com,not-an-email', access_level: Member::MAINTAINER }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('email contains an invalid email address')
+ end
+
+ it 'returns 400 when email is not given' do
+ post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ params: { access_level: Member::MAINTAINER }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ it 'returns 400 when access_level is not given' do
+ post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ params: { email: email }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ it 'returns 400 when access_level is not valid' do
+ post invitations_url(source, maintainer),
+ params: { email: email, access_level: non_existing_record_access_level }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+ end
+
+ describe 'POST /projects/:id/invitations' do
+ it_behaves_like 'POST /:source_type/:id/invitations', 'project' do
+ let(:source) { project }
+ end
+ end
+
+ describe 'POST /groups/:id/invitations' do
+ it_behaves_like 'POST /:source_type/:id/invitations', 'group' do
+ let(:source) { group }
+ end
+ end
+
+ shared_examples 'GET /:source_type/:id/invitations' do |source_type|
+ context "with :source_type == #{source_type.pluralize}" do
+ it_behaves_like 'a 404 response when source is private' do
+ let(:route) { get invitations_url(source, stranger) }
+ end
+
+ %i[maintainer developer access_requester stranger].each do |type|
+ context "when authenticated as a #{type}" do
+ it 'returns 200' do
+ user = public_send(type)
+
+ get invitations_url(source, user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(0)
+ end
+ end
+ end
+
+ it 'avoids N+1 queries' do
+ # Establish baseline
+ get invitations_url(source, maintainer)
+
+ control = ActiveRecord::QueryRecorder.new do
+ get invitations_url(source, maintainer)
+ end
+
+ invite_member_by_email(source, source_type, email, maintainer)
+
+ expect do
+ get invitations_url(source, maintainer)
+ end.not_to exceed_query_limit(control)
+ end
+
+ it 'does not find confirmed members' do
+ get invitations_url(source, developer)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(0)
+ expect(json_response.map { |u| u['id'] }).not_to match_array [maintainer.id, developer.id]
+ end
+
+ it 'finds all members with no query string specified' do
+ invite_member_by_email(source, source_type, email, developer)
+ invite_member_by_email(source, source_type, email2, developer)
+
+ get invitations_url(source, developer), params: { query: '' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+
+ expect(json_response).to be_an Array
+ expect(json_response.count).to eq(2)
+ expect(json_response.map { |u| u['invite_email'] }).to match_array [email, email2]
+ end
+
+ it 'finds the invitation by invite_email with query string' do
+ invite_member_by_email(source, source_type, email, developer)
+ invite_member_by_email(source, source_type, email2, developer)
+
+ get invitations_url(source, developer), params: { query: email }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.count).to eq(1)
+ expect(json_response.first['invite_email']).to eq(email)
+ expect(json_response.first['created_by_name']).to eq(developer.name)
+ expect(json_response.first['user_name']).to eq(nil)
+ end
+
+ def invite_member_by_email(source, source_type, email, created_by)
+ create(:"#{source_type}_member", invite_token: '123', invite_email: email, source: source, user: nil, created_by: created_by)
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/invitations' do
+ it_behaves_like 'GET /:source_type/:id/invitations', 'project' do
+ let(:source) { project }
+ end
+ end
+
+ describe 'GET /groups/:id/invitations' do
+ it_behaves_like 'GET /:source_type/:id/invitations', 'group' do
+ let(:source) { group }
+ end
+ end
+end
diff --git a/spec/requests/api/issues/get_project_issues_spec.rb b/spec/requests/api/issues/get_project_issues_spec.rb
index 4228ca2d5fd..da0bae8d5e7 100644
--- a/spec/requests/api/issues/get_project_issues_spec.rb
+++ b/spec/requests/api/issues/get_project_issues_spec.rb
@@ -54,11 +54,13 @@ RSpec.describe API::Issues do
let_it_be(:label) do
create(:label, title: 'label', color: '#FFAABB', project: project)
end
+
let!(:label_link) { create(:label_link, label: label, target: issue) }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
let_it_be(:empty_milestone) do
create(:milestone, title: '2.0.0', project: project)
end
+
let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }
let(:no_milestone_title) { 'None' }
diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb
index b8cbddd9ed4..0fe68be027c 100644
--- a/spec/requests/api/issues/issues_spec.rb
+++ b/spec/requests/api/issues/issues_spec.rb
@@ -54,11 +54,13 @@ RSpec.describe API::Issues do
let_it_be(:label) do
create(:label, title: 'label', color: '#FFAABB', project: project)
end
+
let!(:label_link) { create(:label_link, label: label, target: issue) }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
let_it_be(:empty_milestone) do
create(:milestone, title: '2.0.0', project: project)
end
+
let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }
let(:no_milestone_title) { 'None' }
diff --git a/spec/requests/api/issues/post_projects_issues_spec.rb b/spec/requests/api/issues/post_projects_issues_spec.rb
index a7fe4d4509a..5b3e2363669 100644
--- a/spec/requests/api/issues/post_projects_issues_spec.rb
+++ b/spec/requests/api/issues/post_projects_issues_spec.rb
@@ -53,11 +53,13 @@ RSpec.describe API::Issues do
let_it_be(:label) do
create(:label, title: 'label', color: '#FFAABB', project: project)
end
+
let!(:label_link) { create(:label_link, label: label, target: issue) }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
let_it_be(:empty_milestone) do
create(:milestone, title: '2.0.0', project: project)
end
+
let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }
let(:no_milestone_title) { 'None' }
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index fc674fca9b2..b368f6e329c 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -178,8 +178,8 @@ RSpec.describe API::Labels do
end
describe 'GET /projects/:id/labels' do
- let(:group) { create(:group) }
- let!(:group_label) { create(:group_label, title: 'feature', group: group) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:group_label) { create(:group_label, title: 'feature label', group: group) }
before do
project.update!(group: group)
@@ -250,49 +250,41 @@ RSpec.describe API::Labels do
end
end
- context 'when the include_ancestor_groups parameter is not set' do
- let(:group) { create(:group) }
- let!(:group_label) { create(:group_label, title: 'feature', group: group) }
- let(:subgroup) { create(:group, parent: group) }
- let!(:subgroup_label) { create(:group_label, title: 'support', group: subgroup) }
+ context 'with subgroups' do
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let_it_be(:subgroup_label) { create(:group_label, title: 'support label', group: subgroup) }
before do
subgroup.add_owner(user)
project.update!(group: subgroup)
end
- it 'returns all available labels for the project, parent group and ancestor groups' do
- get api("/projects/#{project.id}/labels", user)
+ context 'when the include_ancestor_groups parameter is not set' do
+ let(:request) { get api("/projects/#{project.id}/labels", user) }
+ let(:expected_labels) { [priority_label.name, group_label.name, subgroup_label.name, label1.name] }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response).to all(match_schema('public_api/v4/labels/label'))
- expect(json_response.size).to eq(4)
- expect(json_response.map {|r| r['name'] }).to contain_exactly(group_label.name, subgroup_label.name, priority_label.name, label1.name)
- end
- end
+ it_behaves_like 'fetches labels'
- context 'when the include_ancestor_groups parameter is set to false' do
- let(:group) { create(:group) }
- let!(:group_label) { create(:group_label, title: 'feature', group: group) }
- let(:subgroup) { create(:group, parent: group) }
- let!(:subgroup_label) { create(:group_label, title: 'support', group: subgroup) }
+ context 'when search param is provided' do
+ let(:request) { get api("/projects/#{project.id}/labels?search=lab", user) }
+ let(:expected_labels) { [group_label.name, subgroup_label.name, label1.name] }
- before do
- subgroup.add_owner(user)
- project.update!(group: subgroup)
+ it_behaves_like 'fetches labels'
+ end
end
- it 'returns all available labels for the project and the parent group only' do
- get api("/projects/#{project.id}/labels", user), params: { include_ancestor_groups: false }
+ context 'when the include_ancestor_groups parameter is set to false' do
+ let(:request) { get api("/projects/#{project.id}/labels", user), params: { include_ancestor_groups: false } }
+ let(:expected_labels) { [subgroup_label.name, priority_label.name, label1.name] }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response).to all(match_schema('public_api/v4/labels/label'))
- expect(json_response.size).to eq(3)
- expect(json_response.map {|r| r['name'] }).to contain_exactly(subgroup_label.name, priority_label.name, label1.name)
+ it_behaves_like 'fetches labels'
+
+ context 'when search param is provided' do
+ let(:request) { get api("/projects/#{project.id}/labels?search=lab", user), params: { include_ancestor_groups: false } }
+ let(:expected_labels) { [subgroup_label.name, label1.name] }
+
+ it_behaves_like 'fetches labels'
+ end
end
end
end
@@ -513,7 +505,7 @@ RSpec.describe API::Labels do
end
describe 'PUT /projects/:id/labels/promote' do
- let(:group) { create(:group) }
+ let_it_be(:group) { create(:group) }
before do
group.add_owner(user)
diff --git a/spec/requests/api/lint_spec.rb b/spec/requests/api/lint_spec.rb
index 9890cdc20c0..aecbcfb5b5a 100644
--- a/spec/requests/api/lint_spec.rb
+++ b/spec/requests/api/lint_spec.rb
@@ -9,12 +9,13 @@ RSpec.describe API::Lint do
File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
end
- it 'passes validation' do
+ it 'passes validation without warnings or errors' do
post api('/ci/lint'), params: { content: yaml_content }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Hash
expect(json_response['status']).to eq('valid')
+ expect(json_response['warnings']).to eq([])
expect(json_response['errors']).to eq([])
end
@@ -26,6 +27,20 @@ RSpec.describe API::Lint do
end
end
+ context 'with valid .gitlab-ci.yaml with warnings' do
+ let(:yaml_content) { { job: { script: 'ls', rules: [{ when: 'always' }] } }.to_yaml }
+
+ it 'passes validation but returns warnings' do
+ post api('/ci/lint'), params: { content: yaml_content }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['status']).to eq('valid')
+ expect(json_response['warnings']).not_to be_empty
+ expect(json_response['status']).to eq('valid')
+ expect(json_response['errors']).to eq([])
+ end
+ end
+
context 'with an invalid .gitlab_ci.yml' do
context 'with invalid syntax' do
let(:yaml_content) { 'invalid content' }
@@ -35,6 +50,7 @@ RSpec.describe API::Lint do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['status']).to eq('invalid')
+ expect(json_response['warnings']).to eq([])
expect(json_response['errors']).to eq(['Invalid configuration format'])
end
@@ -54,6 +70,7 @@ RSpec.describe API::Lint do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['status']).to eq('invalid')
+ expect(json_response['warnings']).to eq([])
expect(json_response['errors']).to eq(['jobs config should contain at least one visible job'])
end
@@ -82,7 +99,18 @@ RSpec.describe API::Lint do
let(:project) { create(:project, :repository) }
let(:dry_run) { nil }
- RSpec.shared_examples 'valid config' do
+ RSpec.shared_examples 'valid config with warnings' do
+ it 'passes validation with warnings' do
+ ci_lint
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['valid']).to eq(true)
+ expect(json_response['errors']).to eq([])
+ expect(json_response['warnings']).not_to be_empty
+ end
+ end
+
+ RSpec.shared_examples 'valid config without warnings' do
it 'passes validation' do
ci_lint
@@ -94,6 +122,7 @@ RSpec.describe API::Lint do
expect(json_response).to be_an Hash
expect(json_response['merged_yaml']).to eq(expected_yaml)
expect(json_response['valid']).to eq(true)
+ expect(json_response['warnings']).to eq([])
expect(json_response['errors']).to eq([])
end
end
@@ -105,6 +134,7 @@ RSpec.describe API::Lint do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['merged_yaml']).to eq(yaml_content)
expect(json_response['valid']).to eq(false)
+ expect(json_response['warnings']).to eq([])
expect(json_response['errors']).to eq(['jobs config should contain at least one visible job'])
end
end
@@ -157,6 +187,7 @@ RSpec.describe API::Lint do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['merged_yaml']).to eq(nil)
expect(json_response['valid']).to eq(false)
+ expect(json_response['warnings']).to eq([])
expect(json_response['errors']).to eq(['Insufficient permissions to create a new pipeline'])
end
end
@@ -186,7 +217,7 @@ RSpec.describe API::Lint do
)
end
- it_behaves_like 'valid config'
+ it_behaves_like 'valid config without warnings'
end
end
end
@@ -242,13 +273,19 @@ RSpec.describe API::Lint do
context 'when running as dry run' do
let(:dry_run) { true }
- it_behaves_like 'valid config'
+ it_behaves_like 'valid config without warnings'
end
context 'when running static validation' do
let(:dry_run) { false }
- it_behaves_like 'valid config'
+ it_behaves_like 'valid config without warnings'
+ end
+
+ context 'With warnings' do
+ let(:yaml_content) { { job: { script: 'ls', rules: [{ when: 'always' }] } }.to_yaml }
+
+ it_behaves_like 'valid config with warnings'
end
end
@@ -275,4 +312,167 @@ RSpec.describe API::Lint do
end
end
end
+
+ describe 'POST /projects/:id/ci/lint' do
+ subject(:ci_lint) { post api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run, content: yaml_content } }
+
+ let(:project) { create(:project, :repository) }
+ let(:dry_run) { nil }
+
+ let_it_be(:api_user) { create(:user) }
+
+ let_it_be(:yaml_content) do
+ { include: { local: 'another-gitlab-ci.yml' }, test: { stage: 'test', script: 'echo 1' } }.to_yaml
+ end
+
+ let_it_be(:included_content) do
+ { another_test: { stage: 'test', script: 'echo 1' } }.to_yaml
+ end
+
+ RSpec.shared_examples 'valid project config' do
+ it 'passes validation' do
+ ci_lint
+
+ included_config = YAML.safe_load(included_content, [Symbol])
+ root_config = YAML.safe_load(yaml_content, [Symbol])
+ expected_yaml = included_config.merge(root_config).except(:include).to_yaml
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Hash
+ expect(json_response['merged_yaml']).to eq(expected_yaml)
+ expect(json_response['valid']).to eq(true)
+ expect(json_response['errors']).to eq([])
+ end
+ end
+
+ RSpec.shared_examples 'invalid project config' do
+ it 'responds with errors about invalid configuration' do
+ ci_lint
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['merged_yaml']).to eq(yaml_content)
+ expect(json_response['valid']).to eq(false)
+ expect(json_response['errors']).to eq(['jobs config should contain at least one visible job'])
+ end
+ end
+
+ context 'when unauthenticated' do
+ let_it_be(:api_user) { nil }
+
+ it 'returns authentication error' do
+ ci_lint
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when authenticated as non-member' do
+ context 'when project is private' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ it 'returns authentication error' do
+ ci_lint
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when project is public' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ end
+
+ context 'when running as dry run' do
+ let(:dry_run) { true }
+
+ it 'returns pipeline creation error' do
+ ci_lint
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['merged_yaml']).to eq(nil)
+ expect(json_response['valid']).to eq(false)
+ expect(json_response['errors']).to eq(['Insufficient permissions to create a new pipeline'])
+ end
+ end
+
+ context 'when running static validation' do
+ let(:dry_run) { false }
+
+ before do
+ project.repository.create_file(
+ project.creator,
+ 'another-gitlab-ci.yml',
+ included_content,
+ message: 'Automatically created another-gitlab-ci.yml',
+ branch_name: 'master'
+ )
+ end
+
+ it_behaves_like 'valid project config'
+ end
+ end
+ end
+
+ context 'when authenticated as project guest' do
+ before do
+ project.add_guest(api_user)
+ end
+
+ it 'returns authentication error' do
+ ci_lint
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when authenticated as project developer' do
+ before do
+ project.add_developer(api_user)
+ end
+
+ context 'with valid .gitlab-ci.yml content' do
+ before do
+ project.repository.create_file(
+ project.creator,
+ 'another-gitlab-ci.yml',
+ included_content,
+ message: 'Automatically created another-gitlab-ci.yml',
+ branch_name: 'master'
+ )
+ end
+
+ context 'when running as dry run' do
+ let(:dry_run) { true }
+
+ it_behaves_like 'valid project config'
+ end
+
+ context 'when running static validation' do
+ let(:dry_run) { false }
+
+ it_behaves_like 'valid project config'
+ end
+ end
+
+ context 'with invalid .gitlab-ci.yml content' do
+ let(:yaml_content) do
+ { image: 'ruby:2.7', services: ['postgres'] }.to_yaml
+ end
+
+ context 'when running as dry run' do
+ let(:dry_run) { true }
+
+ it_behaves_like 'invalid project config'
+ end
+
+ context 'when running static validation' do
+ let(:dry_run) { false }
+
+ it_behaves_like 'invalid project config'
+ end
+ end
+ end
+ end
end
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index 37748fe5ea7..f9ba819c9aa 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -92,15 +92,30 @@ RSpec.describe API::MavenPackages do
end
shared_examples 'downloads with a deploy token' do
- it 'allows download with deploy token' do
- download_file(
- package_file.file_name,
- {},
- Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => deploy_token.token
- )
+ context 'successful download' do
+ subject do
+ download_file(
+ package_file.file_name,
+ {},
+ Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => deploy_token.token
+ )
+ end
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
+ it 'allows download with deploy token' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+
+ it 'allows download with deploy token with only write_package_registry scope' do
+ deploy_token.update!(read_package_registry: false)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
end
end
@@ -355,6 +370,15 @@ RSpec.describe API::MavenPackages do
expect(response).to have_gitlab_http_status(:ok)
expect(response.media_type).to eq('application/octet-stream')
end
+
+ it 'returns the file with only write_package_registry scope' do
+ deploy_token_for_group.update!(read_package_registry: false)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
end
end
@@ -601,7 +625,7 @@ RSpec.describe API::MavenPackages do
upload_file(params: params.merge(job_token: job.token))
expect(response).to have_gitlab_http_status(:ok)
- expect(project.reload.packages.last.build_info.pipeline).to eq job.pipeline
+ expect(project.reload.packages.last.original_build_info.pipeline).to eq job.pipeline
end
it 'rejects upload without running job token' do
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index 047b9423906..919c8d29406 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe API::Members do
let(:developer) { create(:user) }
let(:access_requester) { create(:user) }
let(:stranger) { create(:user) }
+ let(:user_with_minimal_access) { create(:user) }
let(:project) do
create(:project, :public, creator_id: maintainer.id, namespace: maintainer.namespace) do |project|
@@ -20,6 +21,7 @@ RSpec.describe API::Members do
create(:group, :public) do |group|
group.add_developer(developer)
group.add_owner(maintainer)
+ create(:group_member, :minimal_access, source: group, user: user_with_minimal_access)
group.request_access(access_requester)
end
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 506607f4cc2..e7005bd3ec5 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -1312,13 +1312,44 @@ 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) }
+ let_it_be(:merge_request) do
+ create(
+ :merge_request,
+ :simple,
+ author: user,
+ assignees: [user],
+ source_project: project,
+ target_project: project,
+ source_branch: 'markdown',
+ title: "Test",
+ created_at: base_time
+ )
+ end
- it 'returns the change information of the merge_request' do
- get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/changes", user)
+ shared_examples 'find an existing merge request' do
+ it 'returns the change information of the merge_request' do
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/changes", user)
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['changes'].size).to eq(merge_request.diffs.size)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['changes'].size).to eq(merge_request.diffs.size)
+ expect(json_response['overflow']).to be_falsy
+ end
+ end
+
+ shared_examples 'accesses diffs via raw_diffs' do
+ let(:params) { {} }
+
+ it 'as expected' do
+ expect_any_instance_of(MergeRequest) do |merge_request|
+ expect(merge_request).to receive(:raw_diffs).and_call_original
+ end
+
+ expect_any_instance_of(MergeRequest) do |merge_request|
+ expect(merge_request).not_to receive(:diffs)
+ end
+
+ get(api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/changes", user), params: params)
+ end
end
it 'returns a 404 when merge_request_iid not found' do
@@ -1331,6 +1362,53 @@ RSpec.describe API::MergeRequests do
expect(response).to have_gitlab_http_status(:not_found)
end
+
+ it_behaves_like 'find an existing merge request'
+ it_behaves_like 'accesses diffs via raw_diffs'
+
+ it 'returns the overflow status as false' do
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/changes", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['overflow']).to be_falsy
+ end
+
+ context 'when using DB-backed diffs via feature flag' do
+ before do
+ stub_feature_flags(mrc_api_use_raw_diffs_from_gitaly: false)
+ end
+
+ it_behaves_like 'find an existing merge request'
+
+ it 'accesses diffs via DB-backed diffs.diffs' do
+ expect_any_instance_of(MergeRequest) do |merge_request|
+ expect(merge_request).to receive(:diffs).and_call_original
+ end
+
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/changes", user)
+ end
+
+ context 'when the diff_collection has overflowed its size limits' do
+ before do
+ expect_next_instance_of(Gitlab::Git::DiffCollection) do |diff_collection|
+ expect(diff_collection).to receive(:overflow?).and_return(true)
+ end
+ end
+
+ it 'returns the overflow status as true' do
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/changes", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['overflow']).to be_truthy
+ end
+ end
+
+ context 'when access_raw_diffs is passed as an option' do
+ it_behaves_like 'accesses diffs via raw_diffs' do
+ let(:params) { { access_raw_diffs: true } }
+ end
+ end
+ end
end
describe 'GET /projects/:id/merge_requests/:merge_request_iid/pipelines' do
diff --git a/spec/requests/api/npm_instance_packages_spec.rb b/spec/requests/api/npm_instance_packages_spec.rb
new file mode 100644
index 00000000000..8299717b5c7
--- /dev/null
+++ b/spec/requests/api/npm_instance_packages_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::NpmInstancePackages do
+ include_context 'npm api setup'
+
+ describe 'GET /api/v4/packages/npm/*package_name' do
+ it_behaves_like 'handling get metadata requests' do
+ let(:url) { api("/packages/npm/#{package_name}") }
+ end
+ end
+
+ describe 'GET /api/v4/packages/npm/-/package/*package_name/dist-tags' do
+ it_behaves_like 'handling get dist tags requests', scope: :instance do
+ let(:url) { api("/packages/npm/-/package/#{package_name}/dist-tags") }
+ end
+ end
+
+ describe 'PUT /api/v4/packages/npm/-/package/*package_name/dist-tags/:tag' do
+ it_behaves_like 'handling create dist tag requests', scope: :instance do
+ let(:url) { api("/packages/npm/-/package/#{package_name}/dist-tags/#{tag_name}") }
+ end
+ end
+
+ describe 'DELETE /api/v4/packages/npm/-/package/*package_name/dist-tags/:tag' do
+ it_behaves_like 'handling delete dist tag requests', scope: :instance do
+ let(:url) { api("/packages/npm/-/package/#{package_name}/dist-tags/#{tag_name}") }
+ end
+ end
+end
diff --git a/spec/requests/api/npm_packages_spec.rb b/spec/requests/api/npm_packages_spec.rb
deleted file mode 100644
index 8a3ccd7c6e3..00000000000
--- a/spec/requests/api/npm_packages_spec.rb
+++ /dev/null
@@ -1,556 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe API::NpmPackages do
- include PackagesManagerApiSpecHelpers
- include HttpBasicAuthHelpers
-
- let_it_be(:user) { create(:user) }
- let_it_be(:group) { create(:group) }
- let_it_be(:project, reload: true) { create(:project, :public, namespace: group) }
- let_it_be(:package, reload: true) { create(:npm_package, project: project) }
- let_it_be(:token) { create(:oauth_access_token, scopes: 'api', resource_owner: user) }
- let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
- let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running) }
- let_it_be(: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) }
-
- before do
- project.add_developer(user)
- end
-
- shared_examples 'a package that requires auth' do
- it 'returns the package info with oauth token' do
- get_package_with_token(package)
-
- expect_a_valid_package_response
- end
-
- it 'returns the package info with running job token' do
- get_package_with_job_token(package)
-
- expect_a_valid_package_response
- end
-
- it 'denies request without running job token' do
- job.update!(status: :success)
- get_package_with_job_token(package)
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
-
- it 'denies request without oauth token' do
- get_package(package)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
- it 'returns the package info with deploy token' do
- get_package_with_deploy_token(package)
-
- expect_a_valid_package_response
- end
- end
-
- describe 'GET /api/v4/packages/npm/*package_name' do
- let_it_be(:package_dependency_link1) { create(:packages_dependency_link, package: package, dependency_type: :dependencies) }
- let_it_be(:package_dependency_link2) { create(:packages_dependency_link, package: package, dependency_type: :devDependencies) }
- let_it_be(:package_dependency_link3) { create(:packages_dependency_link, package: package, dependency_type: :bundleDependencies) }
- let_it_be(:package_dependency_link4) { create(:packages_dependency_link, package: package, dependency_type: :peerDependencies) }
-
- shared_examples 'returning the npm package info' do
- it 'returns the package info' do
- get_package(package)
-
- expect_a_valid_package_response
- end
- end
-
- shared_examples 'returning forbidden for unknown package' do
- context 'with an unknown package' do
- it 'returns forbidden' do
- get api("/packages/npm/unknown")
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
- end
-
- context 'a public project' do
- it_behaves_like 'returning the npm package info'
-
- context 'with application setting enabled' do
- before do
- stub_application_setting(npm_package_requests_forwarding: true)
- end
-
- it_behaves_like 'returning the npm package info'
-
- context 'with unknown package' do
- subject { get api("/packages/npm/unknown") }
-
- it 'returns a redirect' do
- subject
-
- expect(response).to have_gitlab_http_status(:found)
- expect(response.headers['Location']).to eq('https://registry.npmjs.org/unknown')
- end
-
- it_behaves_like 'a gitlab tracking event', described_class.name, 'npm_request_forward'
- end
- end
-
- context 'with application setting disabled' do
- before do
- stub_application_setting(npm_package_requests_forwarding: false)
- end
-
- it_behaves_like 'returning the npm package info'
-
- it_behaves_like 'returning forbidden for unknown package'
- end
-
- context 'project path with a dot' do
- before do
- project.update!(path: 'foo.bar')
- end
-
- it_behaves_like 'returning the npm package info'
- end
- end
-
- context 'internal project' do
- before do
- project.team.truncate
- project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
- end
-
- it_behaves_like 'a package that requires auth'
- end
-
- context 'private project' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
-
- it_behaves_like 'a package that requires auth'
-
- it 'denies request when not enough permissions' do
- project.add_guest(user)
-
- get_package_with_token(package)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- def get_package(package, params = {}, headers = {})
- get api("/packages/npm/#{package.name}"), params: params, headers: headers
- end
-
- def get_package_with_token(package, params = {})
- get_package(package, params.merge(access_token: token.token))
- end
-
- def get_package_with_job_token(package, params = {})
- get_package(package, params.merge(job_token: job.token))
- end
-
- def get_package_with_deploy_token(package, params = {})
- get_package(package, {}, build_token_auth_header(deploy_token.token))
- end
- end
-
- describe 'GET /api/v4/projects/:id/packages/npm/*package_name/-/*file_name' do
- let_it_be(:package_file) { package.package_files.first }
-
- shared_examples 'a package file that requires auth' do
- it 'returns the file with an access token' do
- get_file_with_token(package_file)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
-
- it 'returns the file with a job token' do
- get_file_with_job_token(package_file)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
-
- it 'denies download with no token' do
- get_file(package_file)
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'a public project' do
- subject { get_file(package_file) }
-
- it 'returns the file with no token needed' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
-
- it_behaves_like 'a package tracking event', described_class.name, 'pull_package'
- end
-
- context 'private project' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
-
- it_behaves_like 'a package file that requires auth'
-
- it 'denies download when not enough permissions' do
- project.add_guest(user)
-
- get_file_with_token(package_file)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- context 'internal project' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
- end
-
- it_behaves_like 'a package file that requires auth'
- end
-
- def get_file(package_file, params = {})
- get api("/projects/#{project.id}/packages/npm/" \
- "#{package_file.package.name}/-/#{package_file.file_name}"), params: params
- end
-
- def get_file_with_token(package_file, params = {})
- get_file(package_file, params.merge(access_token: token.token))
- end
-
- def get_file_with_job_token(package_file, params = {})
- get_file(package_file, params.merge(job_token: job.token))
- end
- end
-
- describe 'PUT /api/v4/projects/:id/packages/npm/:package_name' do
- RSpec.shared_examples 'handling invalid record with 400 error' do
- it 'handles an ActiveRecord::RecordInvalid exception with 400 error' do
- expect { upload_package_with_token(package_name, params) }
- .not_to change { project.packages.count }
-
- expect(response).to have_gitlab_http_status(:bad_request)
- end
- end
-
- context 'when params are correct' do
- context 'invalid package record' do
- context 'unscoped package' do
- let(:package_name) { 'my_unscoped_package' }
- let(:params) { upload_params(package_name: package_name) }
-
- it_behaves_like 'handling invalid record with 400 error'
-
- context 'with empty versions' do
- let(:params) { upload_params(package_name: package_name).merge!(versions: {}) }
-
- it 'throws a 400 error' do
- expect { upload_package_with_token(package_name, params) }
- .not_to change { project.packages.count }
-
- expect(response).to have_gitlab_http_status(:bad_request)
- end
- end
- end
-
- context 'invalid package name' do
- let(:package_name) { "@#{group.path}/my_inv@@lid_package_name" }
- let(:params) { upload_params(package_name: package_name) }
-
- it_behaves_like 'handling invalid record with 400 error'
- end
-
- context 'invalid package version' do
- using RSpec::Parameterized::TableSyntax
-
- let(:package_name) { "@#{group.path}/my_package_name" }
-
- where(:version) do
- [
- '1',
- '1.2',
- '1./2.3',
- '../../../../../1.2.3',
- '%2e%2e%2f1.2.3'
- ]
- end
-
- with_them do
- let(:params) { upload_params(package_name: package_name, package_version: version) }
-
- it_behaves_like 'handling invalid record with 400 error'
- end
- end
- end
-
- context 'scoped package' do
- let(:package_name) { "@#{group.path}/my_package_name" }
- let(:params) { upload_params(package_name: package_name) }
-
- context 'with access token' do
- subject { upload_package_with_token(package_name, params) }
-
- it_behaves_like 'a package tracking event', described_class.name, 'push_package'
-
- it 'creates npm package with file' do
- expect { subject }
- .to change { project.packages.count }.by(1)
- .and change { Packages::PackageFile.count }.by(1)
- .and change { Packages::Tag.count }.by(1)
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- it 'creates npm package with file with job token' do
- expect { upload_package_with_job_token(package_name, params) }
- .to change { project.packages.count }.by(1)
- .and change { Packages::PackageFile.count }.by(1)
-
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- context 'with an authenticated job token' do
- let!(:job) { create(:ci_build, user: user) }
-
- before do
- Grape::Endpoint.before_each do |endpoint|
- expect(endpoint).to receive(:current_authenticated_job) { job }
- end
- end
-
- after do
- Grape::Endpoint.before_each nil
- end
-
- it 'creates the package metadata' do
- upload_package_with_token(package_name, params)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(project.reload.packages.find(json_response['id']).build_info.pipeline).to eq job.pipeline
- end
- end
- end
-
- context 'package creation fails' do
- let(:package_name) { "@#{group.path}/my_package_name" }
- let(:params) { upload_params(package_name: package_name) }
-
- it 'returns an error if the package already exists' do
- create(:npm_package, project: project, version: '1.0.1', name: "@#{group.path}/my_package_name")
- expect { upload_package_with_token(package_name, params) }
- .not_to change { project.packages.count }
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- context 'with dependencies' do
- let(:package_name) { "@#{group.path}/my_package_name" }
- let(:params) { upload_params(package_name: package_name, file: 'npm/payload_with_duplicated_packages.json') }
-
- it 'creates npm package with file and dependencies' do
- expect { upload_package_with_token(package_name, params) }
- .to change { project.packages.count }.by(1)
- .and change { Packages::PackageFile.count }.by(1)
- .and change { Packages::Dependency.count}.by(4)
- .and change { Packages::DependencyLink.count}.by(6)
-
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- context 'with existing dependencies' do
- before do
- name = "@#{group.path}/existing_package"
- upload_package_with_token(name, upload_params(package_name: name, file: 'npm/payload_with_duplicated_packages.json'))
- end
-
- it 'reuses them' do
- expect { upload_package_with_token(package_name, params) }
- .to change { project.packages.count }.by(1)
- .and change { Packages::PackageFile.count }.by(1)
- .and not_change { Packages::Dependency.count}
- .and change { Packages::DependencyLink.count}.by(6)
- end
- end
- end
- end
-
- def upload_package(package_name, params = {})
- put api("/projects/#{project.id}/packages/npm/#{package_name.sub('/', '%2f')}"), params: params
- end
-
- def upload_package_with_token(package_name, params = {})
- upload_package(package_name, params.merge(access_token: token.token))
- end
-
- def upload_package_with_job_token(package_name, params = {})
- upload_package(package_name, params.merge(job_token: job.token))
- end
-
- def upload_params(package_name:, package_version: '1.0.1', file: 'npm/payload.json')
- Gitlab::Json.parse(fixture_file("packages/#{file}")
- .gsub('@root/npm-test', package_name)
- .gsub('1.0.1', package_version))
- end
- end
-
- describe 'GET /api/v4/packages/npm/-/package/*package_name/dist-tags' do
- let_it_be(:package_tag1) { create(:packages_tag, package: package) }
- let_it_be(:package_tag2) { create(:packages_tag, package: package) }
-
- let(:package_name) { package.name }
- let(:url) { "/packages/npm/-/package/#{package_name}/dist-tags" }
-
- subject { get api(url) }
-
- context 'with public project' do
- context 'with authenticated user' do
- subject { get api(url, personal_access_token: personal_access_token) }
-
- it_behaves_like 'returns package tags', :maintainer
- it_behaves_like 'returns package tags', :developer
- it_behaves_like 'returns package tags', :reporter
- it_behaves_like 'returns package tags', :guest
- end
-
- context 'with unauthenticated user' do
- it_behaves_like 'returns package tags', :no_type
- end
- end
-
- context 'with private project' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
-
- context 'with authenticated user' do
- subject { get api(url, personal_access_token: personal_access_token) }
-
- it_behaves_like 'returns package tags', :maintainer
- it_behaves_like 'returns package tags', :developer
- it_behaves_like 'returns package tags', :reporter
- it_behaves_like 'rejects package tags access', :guest, :forbidden
- end
-
- context 'with unauthenticated user' do
- it_behaves_like 'rejects package tags access', :no_type, :forbidden
- end
- end
- end
-
- describe 'PUT /api/v4/packages/npm/-/package/*package_name/dist-tags/:tag' do
- let_it_be(:tag_name) { 'test' }
-
- let(:package_name) { package.name }
- let(:version) { package.version }
- let(:url) { "/packages/npm/-/package/#{package_name}/dist-tags/#{tag_name}" }
-
- subject { put api(url), env: { 'api.request.body': version } }
-
- context 'with public project' do
- context 'with authenticated user' do
- subject { put api(url, personal_access_token: personal_access_token), env: { 'api.request.body': version } }
-
- it_behaves_like 'create package tag', :maintainer
- it_behaves_like 'create package tag', :developer
- it_behaves_like 'rejects package tags access', :reporter, :forbidden
- it_behaves_like 'rejects package tags access', :guest, :forbidden
- end
-
- context 'with unauthenticated user' do
- it_behaves_like 'rejects package tags access', :no_type, :unauthorized
- end
- end
-
- context 'with private project' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
-
- context 'with authenticated user' do
- subject { put api(url, personal_access_token: personal_access_token), env: { 'api.request.body': version } }
-
- it_behaves_like 'create package tag', :maintainer
- it_behaves_like 'create package tag', :developer
- it_behaves_like 'rejects package tags access', :reporter, :forbidden
- it_behaves_like 'rejects package tags access', :guest, :forbidden
- end
-
- context 'with unauthenticated user' do
- it_behaves_like 'rejects package tags access', :no_type, :unauthorized
- end
- end
- end
-
- describe 'DELETE /api/v4/packages/npm/-/package/*package_name/dist-tags/:tag' do
- let_it_be(:package_tag) { create(:packages_tag, package: package) }
-
- let(:package_name) { package.name }
- let(:tag_name) { package_tag.name }
- let(:url) { "/packages/npm/-/package/#{package_name}/dist-tags/#{tag_name}" }
-
- subject { delete api(url) }
-
- context 'with public project' do
- context 'with authenticated user' do
- subject { delete api(url, personal_access_token: personal_access_token) }
-
- it_behaves_like 'delete package tag', :maintainer
- it_behaves_like 'rejects package tags access', :developer, :forbidden
- it_behaves_like 'rejects package tags access', :reporter, :forbidden
- it_behaves_like 'rejects package tags access', :guest, :forbidden
- end
-
- context 'with unauthenticated user' do
- it_behaves_like 'rejects package tags access', :no_type, :unauthorized
- end
- end
-
- context 'with private project' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
-
- context 'with authenticated user' do
- subject { delete api(url, personal_access_token: personal_access_token) }
-
- it_behaves_like 'delete package tag', :maintainer
- it_behaves_like 'rejects package tags access', :developer, :forbidden
- it_behaves_like 'rejects package tags access', :reporter, :forbidden
- it_behaves_like 'rejects package tags access', :guest, :forbidden
- end
-
- context 'with unauthenticated user' do
- it_behaves_like 'rejects package tags access', :no_type, :unauthorized
- end
- end
- end
-
- def expect_a_valid_package_response
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/json')
- expect(response).to match_response_schema('public_api/v4/packages/npm_package')
- expect(json_response['name']).to eq(package.name)
- expect(json_response['versions'][package.version]).to match_schema('public_api/v4/packages/npm_package_version')
- ::Packages::Npm::PackagePresenter::NPM_VALID_DEPENDENCY_TYPES.each do |dependency_type|
- expect(json_response.dig('versions', package.version, dependency_type.to_s)).to be_any
- end
- expect(json_response['dist-tags']).to match_schema('public_api/v4/packages/npm_package_tags')
- end
-end
diff --git a/spec/requests/api/npm_project_packages_spec.rb b/spec/requests/api/npm_project_packages_spec.rb
new file mode 100644
index 00000000000..1421f20ac28
--- /dev/null
+++ b/spec/requests/api/npm_project_packages_spec.rb
@@ -0,0 +1,281 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::NpmProjectPackages do
+ include_context 'npm api setup'
+
+ describe 'GET /api/v4/projects/:id/packages/npm/*package_name' do
+ it_behaves_like 'handling get metadata requests' do
+ let(:url) { api("/projects/#{project.id}/packages/npm/#{package_name}") }
+ end
+ end
+
+ describe 'GET /api/v4/projects/:id/packages/npm/-/package/*package_name/dist-tags' do
+ it_behaves_like 'handling get dist tags requests' do
+ let(:url) { api("/projects/#{project.id}/packages/npm/-/package/#{package_name}/dist-tags") }
+ end
+ end
+
+ describe 'PUT /api/v4/projects/:id/packages/npm/-/package/*package_name/dist-tags/:tag' do
+ it_behaves_like 'handling create dist tag requests' do
+ let(:url) { api("/projects/#{project.id}/packages/npm/-/package/#{package_name}/dist-tags/#{tag_name}") }
+ end
+ end
+
+ describe 'DELETE /api/v4/projects/:id/packages/npm/-/package/*package_name/dist-tags/:tag' do
+ it_behaves_like 'handling delete dist tag requests' do
+ let(:url) { api("/projects/#{project.id}/packages/npm/-/package/#{package_name}/dist-tags/#{tag_name}") }
+ end
+ end
+
+ describe 'GET /api/v4/projects/:id/packages/npm/*package_name/-/*file_name' do
+ let_it_be(:package_file) { package.package_files.first }
+
+ let(:params) { {} }
+ let(:url) { api("/projects/#{project.id}/packages/npm/#{package_file.package.name}/-/#{package_file.file_name}") }
+
+ subject { get(url, params: params) }
+
+ shared_examples 'a package file that requires auth' do
+ it 'denies download with no token' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'with access token' do
+ let(:params) { { access_token: token.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
+
+ context 'with job token' do
+ let(:params) { { job_token: job.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
+ end
+
+ context 'a public project' do
+ it 'returns the file with no token needed' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+
+ it_behaves_like 'a package tracking event', 'API::NpmPackages', 'pull_package'
+ end
+
+ context 'private project' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ it_behaves_like 'a package file that requires auth'
+
+ context 'with guest' do
+ let(:params) { { access_token: token.token } }
+
+ it 'denies download when not enough permissions' do
+ project.add_guest(user)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+
+ context 'internal project' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ end
+
+ it_behaves_like 'a package file that requires auth'
+ end
+ end
+
+ describe 'PUT /api/v4/projects/:id/packages/npm/:package_name' do
+ RSpec.shared_examples 'handling invalid record with 400 error' do
+ it 'handles an ActiveRecord::RecordInvalid exception with 400 error' do
+ expect { upload_package_with_token(package_name, params) }
+ .not_to change { project.packages.count }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context 'when params are correct' do
+ context 'invalid package record' do
+ context 'unscoped package' do
+ let(:package_name) { 'my_unscoped_package' }
+ let(:params) { upload_params(package_name: package_name) }
+
+ it_behaves_like 'handling invalid record with 400 error'
+
+ context 'with empty versions' do
+ let(:params) { upload_params(package_name: package_name).merge!(versions: {}) }
+
+ it 'throws a 400 error' do
+ expect { upload_package_with_token(package_name, params) }
+ .not_to change { project.packages.count }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+ end
+
+ context 'invalid package name' do
+ let(:package_name) { "@#{group.path}/my_inv@@lid_package_name" }
+ let(:params) { upload_params(package_name: package_name) }
+
+ it_behaves_like 'handling invalid record with 400 error'
+ end
+
+ context 'invalid package version' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:package_name) { "@#{group.path}/my_package_name" }
+
+ where(:version) do
+ [
+ '1',
+ '1.2',
+ '1./2.3',
+ '../../../../../1.2.3',
+ '%2e%2e%2f1.2.3'
+ ]
+ end
+
+ with_them do
+ let(:params) { upload_params(package_name: package_name, package_version: version) }
+
+ it_behaves_like 'handling invalid record with 400 error'
+ end
+ end
+ end
+
+ context 'scoped package' do
+ let(:package_name) { "@#{group.path}/my_package_name" }
+ let(:params) { upload_params(package_name: package_name) }
+
+ context 'with access token' do
+ subject { upload_package_with_token(package_name, params) }
+
+ it_behaves_like 'a package tracking event', 'API::NpmPackages', 'push_package'
+
+ it 'creates npm package with file' do
+ expect { subject }
+ .to change { project.packages.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(1)
+ .and change { Packages::Tag.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ it 'creates npm package with file with job token' do
+ expect { upload_package_with_job_token(package_name, params) }
+ .to change { project.packages.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ context 'with an authenticated job token' do
+ let!(:job) { create(:ci_build, user: user) }
+
+ before do
+ Grape::Endpoint.before_each do |endpoint|
+ expect(endpoint).to receive(:current_authenticated_job) { job }
+ end
+ end
+
+ after do
+ Grape::Endpoint.before_each nil
+ end
+
+ it 'creates the package metadata' do
+ upload_package_with_token(package_name, params)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(project.reload.packages.find(json_response['id']).original_build_info.pipeline).to eq job.pipeline
+ end
+ end
+ end
+
+ context 'package creation fails' do
+ let(:package_name) { "@#{group.path}/my_package_name" }
+ let(:params) { upload_params(package_name: package_name) }
+
+ it 'returns an error if the package already exists' do
+ create(:npm_package, project: project, version: '1.0.1', name: "@#{group.path}/my_package_name")
+ expect { upload_package_with_token(package_name, params) }
+ .not_to change { project.packages.count }
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'with dependencies' do
+ let(:package_name) { "@#{group.path}/my_package_name" }
+ let(:params) { upload_params(package_name: package_name, file: 'npm/payload_with_duplicated_packages.json') }
+
+ it 'creates npm package with file and dependencies' do
+ expect { upload_package_with_token(package_name, params) }
+ .to change { project.packages.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(1)
+ .and change { Packages::Dependency.count}.by(4)
+ .and change { Packages::DependencyLink.count}.by(6)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ context 'with existing dependencies' do
+ before do
+ name = "@#{group.path}/existing_package"
+ upload_package_with_token(name, upload_params(package_name: name, file: 'npm/payload_with_duplicated_packages.json'))
+ end
+
+ it 'reuses them' do
+ expect { upload_package_with_token(package_name, params) }
+ .to change { project.packages.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(1)
+ .and not_change { Packages::Dependency.count}
+ .and change { Packages::DependencyLink.count}.by(6)
+ end
+ end
+ end
+ end
+
+ def upload_package(package_name, params = {})
+ put api("/projects/#{project.id}/packages/npm/#{package_name.sub('/', '%2f')}"), params: params
+ end
+
+ def upload_package_with_token(package_name, params = {})
+ upload_package(package_name, params.merge(access_token: token.token))
+ end
+
+ def upload_package_with_job_token(package_name, params = {})
+ upload_package(package_name, params.merge(job_token: job.token))
+ end
+
+ def upload_params(package_name:, package_version: '1.0.1', file: 'npm/payload.json')
+ Gitlab::Json.parse(fixture_file("packages/#{file}")
+ .gsub('@root/npm-test', package_name)
+ .gsub('1.0.1', package_version))
+ end
+ end
+end
diff --git a/spec/requests/api/personal_access_tokens_spec.rb b/spec/requests/api/personal_access_tokens_spec.rb
new file mode 100644
index 00000000000..ccc5f322ff9
--- /dev/null
+++ b/spec/requests/api/personal_access_tokens_spec.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::PersonalAccessTokens do
+ let_it_be(:path) { '/personal_access_tokens' }
+ let_it_be(:token1) { create(:personal_access_token) }
+ let_it_be(:token2) { create(:personal_access_token) }
+ let_it_be(:current_user) { create(:user) }
+
+ describe 'GET /personal_access_tokens' do
+ context 'logged in as an Administrator' do
+ let_it_be(:current_user) { create(:admin) }
+
+ it 'returns all PATs by default' do
+ get api(path, current_user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.count).to eq(PersonalAccessToken.all.count)
+ end
+
+ context 'filtered with user_id parameter' do
+ it 'returns only PATs belonging to that user' do
+ get api(path, current_user), params: { user_id: token1.user.id }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.count).to eq(1)
+ expect(json_response.first['user_id']).to eq(token1.user.id)
+ end
+ end
+
+ context 'logged in as a non-Administrator' do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:token) { create(:personal_access_token, user: current_user)}
+ let_it_be(:other_token) { create(:personal_access_token, user: user) }
+
+ it 'returns all PATs belonging to the signed-in user' do
+ get api(path, current_user, personal_access_token: token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.count).to eq(1)
+ expect(json_response.map { |r| r['user_id'] }.uniq).to contain_exactly(current_user.id)
+ end
+
+ context 'filtered with user_id parameter' do
+ it 'returns PATs belonging to the specific user' do
+ get api(path, current_user, personal_access_token: token), params: { user_id: current_user.id }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.count).to eq(1)
+ expect(json_response.map { |r| r['user_id'] }.uniq).to contain_exactly(current_user.id)
+ end
+
+ it 'is unauthorized if filtered by a user other than current_user' do
+ get api(path, current_user, personal_access_token: token), params: { user_id: user.id }
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+
+ context 'not authenticated' do
+ it 'is forbidden' do
+ get api(path)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+ end
+
+ describe 'DELETE /personal_access_tokens/:id' do
+ let(:path) { "/personal_access_tokens/#{token1.id}" }
+
+ context 'when current_user is an administrator', :enable_admin_mode do
+ let_it_be(:admin_user) { create(:admin) }
+ let_it_be(:admin_token) { create(:personal_access_token, user: admin_user) }
+ let_it_be(:admin_path) { "/personal_access_tokens/#{admin_token.id}" }
+
+ it 'revokes a different users token' do
+ delete api(path, admin_user)
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ expect(token1.reload.revoked?).to be true
+ end
+
+ it 'revokes their own token' do
+ delete api(admin_path, admin_user)
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
+
+ context 'when current_user is not an administrator' do
+ let_it_be(:user_token) { create(:personal_access_token, user: current_user) }
+ let_it_be(:user_token_path) { "/personal_access_tokens/#{user_token.id}" }
+
+ it 'fails revokes a different users token' do
+ delete api(path, current_user)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ it 'revokes their own token' do
+ delete api(user_token_path, current_user)
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/project_container_repositories_spec.rb b/spec/requests/api/project_container_repositories_spec.rb
index 34476b10576..15871426ec5 100644
--- a/spec/requests/api/project_container_repositories_spec.rb
+++ b/spec/requests/api/project_container_repositories_spec.rb
@@ -299,7 +299,7 @@ RSpec.describe API::ProjectContainerRepositories do
it_behaves_like 'rejected container repository access', :reporter, :forbidden
it_behaves_like 'rejected container repository access', :anonymous, :not_found
- context 'for developer' do
+ context 'for developer', :snowplow do
let(:api_user) { developer }
context 'when there are multiple tags' do
@@ -310,11 +310,11 @@ RSpec.describe API::ProjectContainerRepositories do
it 'properly removes tag' do
expect(service).to receive(:execute).with(root_repository) { { status: :success } }
expect(Projects::ContainerRepository::DeleteTagsService).to receive(:new).with(root_repository.project, api_user, tags: %w[rootA]) { service }
- expect(Gitlab::Tracking).to receive(:event).with(described_class.name, 'delete_tag', {})
subject
expect(response).to have_gitlab_http_status(:ok)
+ expect_snowplow_event(category: described_class.name, action: 'delete_tag')
end
end
@@ -326,11 +326,11 @@ RSpec.describe API::ProjectContainerRepositories do
it 'properly removes tag' do
expect(service).to receive(:execute).with(root_repository) { { status: :success } }
expect(Projects::ContainerRepository::DeleteTagsService).to receive(:new).with(root_repository.project, api_user, tags: %w[rootA]) { service }
- expect(Gitlab::Tracking).to receive(:event).with(described_class.name, 'delete_tag', {})
subject
expect(response).to have_gitlab_http_status(:ok)
+ expect_snowplow_event(category: described_class.name, action: 'delete_tag')
end
end
end
diff --git a/spec/requests/api/project_export_spec.rb b/spec/requests/api/project_export_spec.rb
index 09d295afbea..ac24aeee52c 100644
--- a/spec/requests/api/project_export_spec.rb
+++ b/spec/requests/api/project_export_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe API::ProjectExport, :clean_gitlab_redis_cache do
let(:export_path) { "#{Dir.tmpdir}/project_export_spec" }
before do
- allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
+ allow(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
allow_next_instance_of(ProjectExportWorker) do |job|
allow(job).to receive(:jid).and_return(SecureRandom.hex(8))
end
diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb
index 3b2a7895630..b5aedde2b2e 100644
--- a/spec/requests/api/project_hooks_spec.rb
+++ b/spec/requests/api/project_hooks_spec.rb
@@ -41,6 +41,7 @@ RSpec.describe API::ProjectHooks, 'ProjectHooks' do
expect(json_response.first['pipeline_events']).to eq(true)
expect(json_response.first['wiki_page_events']).to eq(true)
expect(json_response.first['deployment_events']).to eq(true)
+ expect(json_response.first['releases_events']).to eq(true)
expect(json_response.first['enable_ssl_verification']).to eq(true)
expect(json_response.first['push_events_branch_filter']).to eq('master')
end
@@ -72,6 +73,7 @@ RSpec.describe API::ProjectHooks, 'ProjectHooks' do
expect(json_response['job_events']).to eq(hook.job_events)
expect(json_response['pipeline_events']).to eq(hook.pipeline_events)
expect(json_response['wiki_page_events']).to eq(hook.wiki_page_events)
+ expect(json_response['releases_events']).to eq(hook.releases_events)
expect(json_response['deployment_events']).to eq(true)
expect(json_response['enable_ssl_verification']).to eq(hook.enable_ssl_verification)
end
@@ -97,7 +99,7 @@ RSpec.describe API::ProjectHooks, 'ProjectHooks' do
post(api("/projects/#{project.id}/hooks", user),
params: { url: "http://example.com", issues_events: true,
confidential_issues_events: true, wiki_page_events: true,
- job_events: true, deployment_events: true,
+ job_events: true, deployment_events: true, releases_events: true,
push_events_branch_filter: 'some-feature-branch' })
end.to change {project.hooks.count}.by(1)
@@ -114,6 +116,7 @@ RSpec.describe API::ProjectHooks, 'ProjectHooks' do
expect(json_response['pipeline_events']).to eq(false)
expect(json_response['wiki_page_events']).to eq(true)
expect(json_response['deployment_events']).to eq(true)
+ expect(json_response['releases_events']).to eq(true)
expect(json_response['enable_ssl_verification']).to eq(true)
expect(json_response['push_events_branch_filter']).to eq('some-feature-branch')
expect(json_response).not_to include('token')
@@ -169,6 +172,7 @@ RSpec.describe API::ProjectHooks, 'ProjectHooks' do
expect(json_response['job_events']).to eq(hook.job_events)
expect(json_response['pipeline_events']).to eq(hook.pipeline_events)
expect(json_response['wiki_page_events']).to eq(hook.wiki_page_events)
+ expect(json_response['releases_events']).to eq(hook.releases_events)
expect(json_response['enable_ssl_verification']).to eq(hook.enable_ssl_verification)
end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 2abcb39a1c8..4a792fc218d 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -890,7 +890,7 @@ RSpec.describe API::Projects do
expect(response).to have_gitlab_http_status(:created)
project.each_pair do |k, v|
- next if %i[has_external_issue_tracker issues_enabled merge_requests_enabled wiki_enabled storage_version].include?(k)
+ next if %i[has_external_issue_tracker has_external_wiki issues_enabled merge_requests_enabled wiki_enabled storage_version].include?(k)
expect(json_response[k.to_s]).to eq(v)
end
@@ -1309,7 +1309,7 @@ RSpec.describe API::Projects do
expect(response).to have_gitlab_http_status(:created)
project.each_pair do |k, v|
- next if %i[has_external_issue_tracker path storage_version].include?(k)
+ next if %i[has_external_issue_tracker has_external_wiki path storage_version].include?(k)
expect(json_response[k.to_s]).to eq(v)
end
@@ -2659,6 +2659,7 @@ RSpec.describe API::Projects do
project_param = {
container_expiration_policy_attributes: {
cadence: '1month',
+ enabled: true,
keep_n: 1,
name_regex_keep: '['
}
diff --git a/spec/requests/api/release/links_spec.rb b/spec/requests/api/release/links_spec.rb
index 82d0d64eba4..c03dd0331cf 100644
--- a/spec/requests/api/release/links_spec.rb
+++ b/spec/requests/api/release/links_spec.rb
@@ -146,7 +146,7 @@ RSpec.describe API::Release::Links do
specify do
get api("/projects/#{project.id}/releases/v0.1/assets/links/#{link.id}", maintainer)
- expect(json_response['direct_asset_url']).to eq("http://localhost/#{project.namespace.path}/#{project.name}/-/releases/#{release.tag}/bin/bigfile.exe")
+ expect(json_response['direct_asset_url']).to eq("http://localhost/#{project.namespace.path}/#{project.name}/-/releases/#{release.tag}/downloads/bin/bigfile.exe")
end
end
diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb
index e78d05835f2..58b321a255e 100644
--- a/spec/requests/api/releases_spec.rb
+++ b/spec/requests/api/releases_spec.rb
@@ -110,22 +110,6 @@ RSpec.describe API::Releases do
expect(json_response.second['commit_path']).to eq("/#{release_1.project.full_path}/-/commit/#{release_1.commit.id}")
expect(json_response.second['tag_path']).to eq("/#{release_1.project.full_path}/-/tags/#{release_1.tag}")
end
-
- it 'returns the merge requests and issues links, with correct query' do
- get api("/projects/#{project.id}/releases", maintainer)
-
- links = json_response.first['_links']
- release = json_response.first['tag_name']
- expected_query = "release_tag=#{release}&scope=all&state=opened"
- path_base = "/#{project.namespace.path}/#{project.path}"
- mr_uri = URI.parse(links['merge_requests_url'])
- issue_uri = URI.parse(links['issues_url'])
-
- expect(mr_uri.path).to eq("#{path_base}/-/merge_requests")
- expect(issue_uri.path).to eq("#{path_base}/-/issues")
- expect(mr_uri.query).to eq(expected_query)
- expect(issue_uri.query).to eq(expected_query)
- end
end
it 'returns an upcoming_release status for a future release' do
@@ -1014,6 +998,17 @@ RSpec.describe API::Releases do
end
end
+ context 'without milestones parameter' do
+ let(:params) { { name: 'some new name' } }
+
+ it 'does not change the milestone' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(returned_milestones).to match_array(['v1.0'])
+ end
+ end
+
context 'multiple milestones' do
context 'with one new' do
let!(:milestone2) { create(:milestone, project: project, title: 'milestone2') }
diff --git a/spec/requests/api/search_spec.rb b/spec/requests/api/search_spec.rb
index 05cfad9cc62..8012892a571 100644
--- a/spec/requests/api/search_spec.rb
+++ b/spec/requests/api/search_spec.rb
@@ -23,6 +23,48 @@ RSpec.describe API::Search do
end
end
+ shared_examples 'orderable by created_at' do |scope:|
+ it 'allows ordering results by created_at asc' do
+ get api(endpoint, user), params: { scope: scope, search: 'sortable', order_by: 'created_at', sort: 'asc' }
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(json_response.count).to be > 1
+
+ created_ats = json_response.map { |r| Time.parse(r['created_at']) }
+ expect(created_ats.uniq.count).to be > 1
+
+ expect(created_ats).to eq(created_ats.sort)
+ end
+
+ it 'allows ordering results by created_at desc' do
+ get api(endpoint, user), params: { scope: scope, search: 'sortable', order_by: 'created_at', sort: 'desc' }
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(json_response.count).to be > 1
+
+ created_ats = json_response.map { |r| Time.parse(r['created_at']) }
+ expect(created_ats.uniq.count).to be > 1
+
+ expect(created_ats).to eq(created_ats.sort.reverse)
+ end
+ end
+
+ shared_examples 'issues orderable by created_at' do
+ before do
+ create_list(:issue, 3, title: 'sortable item', project: project)
+ end
+
+ it_behaves_like 'orderable by created_at', scope: :issues
+ end
+
+ shared_examples 'merge_requests orderable by created_at' do
+ before do
+ create_list(:merge_request, 3, :unique_branches, title: 'sortable item', target_project: repo_project, source_project: repo_project)
+ end
+
+ it_behaves_like 'orderable by created_at', scope: :merge_requests
+ end
+
shared_examples 'pagination' do |scope:, search: ''|
it 'returns a different result for each page' do
get api(endpoint, user), params: { scope: scope, search: search, page: 1, per_page: 1 }
@@ -121,6 +163,8 @@ RSpec.describe API::Search do
it_behaves_like 'ping counters', scope: :issues
+ it_behaves_like 'issues orderable by created_at'
+
describe 'pagination' do
before do
create(:issue, project: project, title: 'another issue')
@@ -151,7 +195,6 @@ RSpec.describe API::Search do
context 'filter by confidentiality' do
before do
- stub_feature_flags(search_filter_by_confidential: true)
create(:issue, project: project, author: user, title: 'awesome non-confidential issue')
create(:issue, :confidential, project: project, author: user, title: 'awesome confidential issue')
end
@@ -182,6 +225,8 @@ RSpec.describe API::Search do
it_behaves_like 'ping counters', scope: :merge_requests
+ it_behaves_like 'merge_requests orderable by created_at'
+
describe 'pagination' do
before do
create(:merge_request, source_project: repo_project, title: 'another mr', target_branch: 'another_branch')
@@ -355,6 +400,8 @@ RSpec.describe API::Search do
it_behaves_like 'ping counters', scope: :issues
+ it_behaves_like 'issues orderable by created_at'
+
describe 'pagination' do
before do
create(:issue, project: project, title: 'another issue')
@@ -375,6 +422,8 @@ RSpec.describe API::Search do
it_behaves_like 'ping counters', scope: :merge_requests
+ it_behaves_like 'merge_requests orderable by created_at'
+
describe 'pagination' do
before do
create(:merge_request, source_project: repo_project, title: 'another mr', target_branch: 'another_branch')
@@ -507,6 +556,8 @@ RSpec.describe API::Search do
it_behaves_like 'ping counters', scope: :issues
+ it_behaves_like 'issues orderable by created_at'
+
describe 'pagination' do
before do
create(:issue, project: project, title: 'another issue')
@@ -516,6 +567,14 @@ RSpec.describe API::Search do
end
end
+ context 'when requesting basic search' do
+ it 'passes the parameter to search service' do
+ expect(SearchService).to receive(:new).with(user, hash_including(basic_search: 'true'))
+
+ get api(endpoint, user), params: { scope: 'issues', search: 'awesome', basic_search: 'true' }
+ end
+ end
+
context 'for merge_requests scope' do
let(:endpoint) { "/projects/#{repo_project.id}/search" }
@@ -529,6 +588,8 @@ RSpec.describe API::Search do
it_behaves_like 'ping counters', scope: :merge_requests
+ it_behaves_like 'merge_requests orderable by created_at'
+
describe 'pagination' do
before do
create(:merge_request, source_project: repo_project, title: 'another mr', target_branch: 'another_branch')
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 8b5f74df8f8..03320549e44 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -22,6 +22,8 @@ RSpec.describe API::Settings, 'Settings' do
expect(json_response['default_ci_config_path']).to be_nil
expect(json_response['sourcegraph_enabled']).to be_falsey
expect(json_response['sourcegraph_url']).to be_nil
+ expect(json_response['secret_detection_token_revocation_url']).to be_nil
+ expect(json_response['secret_detection_revocation_token_types_url']).to be_nil
expect(json_response['sourcegraph_public_only']).to be_truthy
expect(json_response['default_project_visibility']).to be_a String
expect(json_response['default_snippet_visibility']).to be_a String
@@ -40,6 +42,7 @@ RSpec.describe API::Settings, 'Settings' do
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)
+ expect(json_response['require_admin_approval_after_user_signup']).to eq(true)
end
end
@@ -105,7 +108,7 @@ RSpec.describe API::Settings, 'Settings' do
enforce_terms: true,
terms: 'Hello world!',
performance_bar_allowed_group_path: group.full_path,
- diff_max_patch_bytes: 150_000,
+ diff_max_patch_bytes: 300_000,
default_branch_protection: ::Gitlab::Access::PROTECTION_DEV_CAN_MERGE,
local_markdown_version: 3,
allow_local_requests_from_web_hooks_and_services: true,
@@ -148,7 +151,7 @@ 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['diff_max_patch_bytes']).to eq(150_000)
+ expect(json_response['diff_max_patch_bytes']).to eq(300_000)
expect(json_response['default_branch_protection']).to eq(Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
expect(json_response['local_markdown_version']).to eq(3)
expect(json_response['allow_local_requests_from_web_hooks_and_services']).to eq(true)
@@ -377,41 +380,41 @@ RSpec.describe API::Settings, 'Settings' do
end
end
- context 'domain_blacklist settings' do
- it 'rejects domain_blacklist_enabled when domain_blacklist is empty' do
+ context 'domain_denylist settings' do
+ it 'rejects domain_denylist_enabled when domain_denylist is empty' do
put api('/application/settings', admin),
params: {
- domain_blacklist_enabled: true,
- domain_blacklist: []
+ domain_denylist_enabled: true,
+ domain_denylist: []
}
expect(response).to have_gitlab_http_status(:bad_request)
message = json_response["message"]
- expect(message["domain_blacklist"]).to eq(["Domain blacklist cannot be empty if Blacklist is enabled."])
+ expect(message["domain_denylist"]).to eq(["Domain denylist cannot be empty if denylist is enabled."])
end
- it 'allows array for domain_blacklist' do
+ it 'allows array for domain_denylist' do
put api('/application/settings', admin),
params: {
- domain_blacklist_enabled: true,
- domain_blacklist: ['domain1.com', 'domain2.com']
+ domain_denylist_enabled: true,
+ domain_denylist: ['domain1.com', 'domain2.com']
}
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['domain_blacklist_enabled']).to be(true)
- expect(json_response['domain_blacklist']).to eq(['domain1.com', 'domain2.com'])
+ expect(json_response['domain_denylist_enabled']).to be(true)
+ expect(json_response['domain_denylist']).to eq(['domain1.com', 'domain2.com'])
end
- it 'allows a string for domain_blacklist' do
+ it 'allows a string for domain_denylist' do
put api('/application/settings', admin),
params: {
- domain_blacklist_enabled: true,
- domain_blacklist: 'domain3.com, *.domain4.com'
+ domain_denylist_enabled: true,
+ domain_denylist: 'domain3.com, *.domain4.com'
}
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['domain_blacklist_enabled']).to be(true)
- expect(json_response['domain_blacklist']).to eq(['domain3.com', '*.domain4.com'])
+ expect(json_response['domain_denylist_enabled']).to be(true)
+ expect(json_response['domain_denylist']).to eq(['domain3.com', '*.domain4.com'])
end
end
@@ -423,6 +426,14 @@ RSpec.describe API::Settings, 'Settings' do
expect(json_response['abuse_notification_email']).to eq('test@example.com')
end
+ it 'supports setting require_admin_approval_after_user_signup' do
+ put api('/application/settings', admin),
+ params: { require_admin_approval_after_user_signup: true }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['require_admin_approval_after_user_signup']).to eq(true)
+ end
+
context "missing sourcegraph_url value when sourcegraph_enabled is true" do
it "returns a blank parameter error message" do
put api("/application/settings", admin), params: { sourcegraph_enabled: true }
diff --git a/spec/requests/api/terraform/state_spec.rb b/spec/requests/api/terraform/state_spec.rb
index b91f6e1aa88..0fa088a641e 100644
--- a/spec/requests/api/terraform/state_spec.rb
+++ b/spec/requests/api/terraform/state_spec.rb
@@ -113,7 +113,7 @@ RSpec.describe API::Terraform::State do
end
describe 'POST /projects/:id/terraform/state/:name' do
- let(:params) { { 'instance': 'example-instance', 'serial': '1' } }
+ let(:params) { { 'instance': 'example-instance', 'serial': state.latest_version.version + 1 } }
subject(:request) { post api(state_path), headers: auth_header, as: :json, params: params }
@@ -202,6 +202,18 @@ RSpec.describe API::Terraform::State do
end
end
end
+
+ context 'when using job token authentication' do
+ let(:job) { create(:ci_build, status: :running, project: project, user: maintainer) }
+ let(:auth_header) { job_basic_auth_header(job) }
+
+ it 'associates the job with the newly created state version' do
+ expect { request }.to change { state.versions.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(state.reload_latest_version.build).to eq(job)
+ end
+ end
end
describe 'DELETE /projects/:id/terraform/state/:name' do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 7330c89fe77..98840d6238a 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -161,7 +161,7 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
end
context 'accesses the profile of another admin' do
- let(:admin_2) {create(:admin, note: '2010-10-10 | 2FA added | admin requested | www.gitlab.com')}
+ let(:admin_2) { create(:admin, note: '2010-10-10 | 2FA added | admin requested | www.gitlab.com') }
it 'contains the note of the user' do
get api("/user?private_token=#{admin_personal_access_token}&sudo=#{admin_2.id}")
@@ -772,11 +772,11 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
it "does not create user with invalid email" do
post api('/users', admin),
- params: {
- email: 'invalid email',
- password: 'password',
- name: 'test'
- }
+ params: {
+ email: 'invalid email',
+ password: 'password',
+ name: 'test'
+ }
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -811,14 +811,14 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
it 'returns 400 error if user does not validate' do
post api('/users', admin),
- params: {
- password: 'pass',
- email: 'test@example.com',
- username: 'test!',
- name: 'test',
- bio: 'g' * 256,
- projects_limit: -1
- }
+ params: {
+ password: 'pass',
+ email: 'test@example.com',
+ username: 'test!',
+ name: 'test',
+ bio: 'g' * 256,
+ projects_limit: -1
+ }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']['password'])
.to eq(['is too short (minimum is 8 characters)'])
@@ -838,23 +838,23 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
context 'with existing user' do
before do
post api('/users', admin),
- params: {
- email: 'test@example.com',
- password: 'password',
- username: 'test',
- name: 'foo'
- }
+ params: {
+ email: 'test@example.com',
+ password: 'password',
+ username: 'test',
+ name: 'foo'
+ }
end
it 'returns 409 conflict error if user with same email exists' do
expect do
post api('/users', admin),
- params: {
- name: 'foo',
- email: 'test@example.com',
- password: 'password',
- username: 'foo'
- }
+ params: {
+ name: 'foo',
+ email: 'test@example.com',
+ password: 'password',
+ username: 'foo'
+ }
end.to change { User.count }.by(0)
expect(response).to have_gitlab_http_status(:conflict)
expect(json_response['message']).to eq('Email has already been taken')
@@ -863,12 +863,12 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
it 'returns 409 conflict error if same username exists' do
expect do
post api('/users', admin),
- params: {
- name: 'foo',
- email: 'foo@example.com',
- password: 'password',
- username: 'test'
- }
+ params: {
+ name: 'foo',
+ email: 'foo@example.com',
+ password: 'password',
+ username: 'test'
+ }
end.to change { User.count }.by(0)
expect(response).to have_gitlab_http_status(:conflict)
expect(json_response['message']).to eq('Username has already been taken')
@@ -877,12 +877,12 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
it 'returns 409 conflict error if same username exists (case insensitive)' do
expect do
post api('/users', admin),
- params: {
- name: 'foo',
- email: 'foo@example.com',
- password: 'password',
- username: 'TEST'
- }
+ params: {
+ name: 'foo',
+ email: 'foo@example.com',
+ password: 'password',
+ username: 'TEST'
+ }
end.to change { User.count }.by(0)
expect(response).to have_gitlab_http_status(:conflict)
expect(json_response['message']).to eq('Username has already been taken')
@@ -1185,14 +1185,14 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
it 'returns 400 error if user does not validate' do
put api("/users/#{user.id}", admin),
- params: {
- password: 'pass',
- email: 'test@example.com',
- username: 'test!',
- name: 'test',
- bio: 'g' * 256,
- projects_limit: -1
- }
+ params: {
+ password: 'pass',
+ email: 'test@example.com',
+ username: 'test!',
+ name: 'test',
+ bio: 'g' * 256,
+ projects_limit: -1
+ }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']['password'])
.to eq(['is too short (minimum is 8 characters)'])
@@ -1714,14 +1714,14 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
context "hard delete disabled" do
it "does not delete user" do
- perform_enqueued_jobs { delete api("/users/#{user.id}", admin)}
+ perform_enqueued_jobs { delete api("/users/#{user.id}", admin) }
expect(response).to have_gitlab_http_status(:conflict)
end
end
context "hard delete enabled" do
it "delete user and group", :sidekiq_might_not_need_inline do
- perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin)}
+ perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin) }
expect(response).to have_gitlab_http_status(:no_content)
expect(Group.exists?(group.id)).to be_falsy
end
@@ -1993,7 +1993,7 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
delete api("/user/keys/#{key.id}", user)
expect(response).to have_gitlab_http_status(:no_content)
- end.to change { user.keys.count}.by(-1)
+ end.to change { user.keys.count }.by(-1)
end
it_behaves_like '412 response' do
@@ -2124,7 +2124,7 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
post api("/user/gpg_keys/#{gpg_key.id}/revoke", user)
expect(response).to have_gitlab_http_status(:accepted)
- end.to change { user.gpg_keys.count}.by(-1)
+ end.to change { user.gpg_keys.count }.by(-1)
end
it 'returns 404 if key ID not found' do
@@ -2157,7 +2157,7 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
delete api("/user/gpg_keys/#{gpg_key.id}", user)
expect(response).to have_gitlab_http_status(:no_content)
- end.to change { user.gpg_keys.count}.by(-1)
+ end.to change { user.gpg_keys.count }.by(-1)
end
it 'returns 404 if key ID not found' do
@@ -2279,7 +2279,7 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
delete api("/user/emails/#{email.id}", user)
expect(response).to have_gitlab_http_status(:no_content)
- end.to change { user.emails.count}.by(-1)
+ end.to change { user.emails.count }.by(-1)
end
it_behaves_like '412 response' do
@@ -2756,6 +2756,124 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
end
end
+ describe 'POST /users/:user_id/personal_access_tokens' do
+ let(:name) { 'new pat' }
+ let(:expires_at) { 3.days.from_now.to_date.to_s }
+ let(:scopes) { %w(api read_user) }
+
+ context 'when feature flag is enabled' do
+ before do
+ stub_feature_flags(pat_creation_api_for_admin: true)
+ end
+
+ it 'returns error if required attributes are missing' do
+ post api("/users/#{user.id}/personal_access_tokens", admin)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('name is missing, scopes is missing, scopes does not have a valid value')
+ end
+
+ it 'returns a 404 error if user not found' do
+ post api("/users/#{non_existing_record_id}/personal_access_tokens", admin),
+ params: {
+ name: name,
+ scopes: scopes,
+ expires_at: expires_at
+ }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 User Not Found')
+ end
+
+ it 'returns a 401 error when not authenticated' do
+ post api("/users/#{user.id}/personal_access_tokens"),
+ params: {
+ name: name,
+ scopes: scopes,
+ expires_at: expires_at
+ }
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(json_response['message']).to eq('401 Unauthorized')
+ end
+
+ it 'returns a 403 error when authenticated as normal user' do
+ post api("/users/#{user.id}/personal_access_tokens", user),
+ params: {
+ name: name,
+ scopes: scopes,
+ expires_at: expires_at
+ }
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ expect(json_response['message']).to eq('403 Forbidden')
+ end
+
+ it 'creates a personal access token when authenticated as admin' do
+ post api("/users/#{user.id}/personal_access_tokens", admin),
+ params: {
+ name: name,
+ expires_at: expires_at,
+ scopes: scopes
+ }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['name']).to eq(name)
+ expect(json_response['scopes']).to eq(scopes)
+ expect(json_response['expires_at']).to eq(expires_at)
+ expect(json_response['id']).to be_present
+ expect(json_response['created_at']).to be_present
+ expect(json_response['active']).to be_truthy
+ expect(json_response['revoked']).to be_falsey
+ expect(json_response['token']).to be_present
+ end
+
+ context 'when an error is thrown by the model' do
+ let!(:admin_personal_access_token) { create(:personal_access_token, user: admin) }
+ let(:error_message) { 'error message' }
+
+ before do
+ allow_next_instance_of(PersonalAccessToken) do |personal_access_token|
+ allow(personal_access_token).to receive_message_chain(:errors, :full_messages)
+ .and_return([error_message])
+
+ allow(personal_access_token).to receive(:save).and_return(false)
+ end
+ end
+
+ it 'returns the error' do
+ post api("/users/#{user.id}/personal_access_tokens", personal_access_token: admin_personal_access_token),
+ params: {
+ name: name,
+ expires_at: expires_at,
+ scopes: scopes
+ }
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ expect(json_response['message']).to eq(error_message)
+ end
+ end
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(pat_creation_api_for_admin: false)
+ end
+
+ it 'returns a 404' do
+ post api("/users/#{user.id}/personal_access_tokens", admin),
+ params: {
+ name: name,
+ expires_at: expires_at,
+ scopes: scopes
+ }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 Not Found')
+ end
+ end
+ end
+
describe 'GET /users/:user_id/impersonation_tokens' do
let_it_be(:active_personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:revoked_personal_access_token) { create(:personal_access_token, :revoked, user: user) }
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index a3bfa7ea33c..dc735e3714d 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -433,7 +433,7 @@ RSpec.describe 'Git HTTP requests' do
let(:path) { "#{redirect.path}.git" }
it 'downloads get status 200 for redirects' do
- clone_get(path, {})
+ clone_get(path)
expect(response).to have_gitlab_http_status(:ok)
end
@@ -465,7 +465,7 @@ RSpec.describe 'Git HTTP requests' do
path: "/#{path}/info/refs?service=git-upload-pack"
})
- clone_get(path, env)
+ clone_get(path, **env)
expect(response).to have_gitlab_http_status(:forbidden)
end
@@ -493,7 +493,7 @@ RSpec.describe 'Git HTTP requests' do
it "rejects pulls with 401 Unauthorized for unknown projects (no project existence information leak)" do
user.block
- download('doesnt/exist.git', env) do |response|
+ download('doesnt/exist.git', **env) do |response|
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
@@ -693,7 +693,7 @@ RSpec.describe 'Git HTTP requests' do
end
it 'downloads get status 200' do
- clone_get(path, env)
+ clone_get(path, **env)
expect(response).to have_gitlab_http_status(:ok)
end
@@ -745,7 +745,7 @@ RSpec.describe 'Git HTTP requests' do
# We know for sure it is not an information leak since pulls using
# the build token must be allowed.
it "rejects pushes with 403 Forbidden" do
- push_get(path, env)
+ push_get(path, **env)
expect(response).to have_gitlab_http_status(:forbidden)
expect(response.body).to eq(git_access_error(:auth_upload))
@@ -754,7 +754,7 @@ RSpec.describe 'Git HTTP requests' do
# We are "authenticated" as CI using a valid token here. But we are
# not authorized to see any other project, so return "not found".
it "rejects pulls for other project with 404 Not Found" do
- clone_get("#{other_project.full_path}.git", env)
+ clone_get("#{other_project.full_path}.git", **env)
expect(response).to have_gitlab_http_status(:not_found)
expect(response.body).to eq(git_access_error(:project_not_found))
@@ -777,7 +777,7 @@ RSpec.describe 'Git HTTP requests' do
let(:project) { create(:project) }
it 'rejects pulls with 404 Not Found' do
- clone_get path, env
+ clone_get(path, **env)
expect(response).to have_gitlab_http_status(:not_found)
expect(response.body).to eq(git_access_error(:no_repo))
@@ -785,7 +785,7 @@ RSpec.describe 'Git HTTP requests' do
end
it 'rejects pushes with 403 Forbidden' do
- push_get path, env
+ push_get(path, **env)
expect(response).to have_gitlab_http_status(:forbidden)
expect(response.body).to eq(git_access_error(:auth_upload))
@@ -889,7 +889,7 @@ RSpec.describe 'Git HTTP requests' do
end
it "responds with status 200" do
- clone_get(path, env) do |response|
+ clone_get(path, **env) do |response|
expect(response).to have_gitlab_http_status(:ok)
end
end
@@ -913,7 +913,7 @@ RSpec.describe 'Git HTTP requests' do
end
it 'blocks git access when the user did not accept terms', :aggregate_failures do
- clone_get(path, env) do |response|
+ clone_get(path, **env) do |response|
expect(response).to have_gitlab_http_status(:forbidden)
end
@@ -932,7 +932,7 @@ RSpec.describe 'Git HTTP requests' do
end
it 'allows clones' do
- clone_get(path, env) do |response|
+ clone_get(path, **env) do |response|
expect(response).to have_gitlab_http_status(:ok)
end
end
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index 31bb0586e9f..48d125a37c3 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -9,18 +9,17 @@ RSpec.describe 'Git LFS API and storage' do
let_it_be(:project, reload: true) { create(:project, :repository) }
let_it_be(:other_project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
- let!(:lfs_object) { create(:lfs_object, :with_file) }
+ let(:lfs_object) { create(:lfs_object, :with_file) }
let(:headers) do
{
'Authorization' => authorization,
- 'X-Sendfile-Type' => sendfile
+ 'X-Sendfile-Type' => 'X-Sendfile'
}.compact
end
let(:include_workhorse_jwt_header) { true }
let(:authorization) { }
- let(:sendfile) { }
let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:sample_oid) { lfs_object.oid }
@@ -37,18 +36,6 @@ RSpec.describe 'Git LFS API and storage' do
stub_lfs_setting(enabled: lfs_enabled)
end
- describe 'when LFS is disabled' do
- let(:lfs_enabled) { false }
- let(:body) { upload_body(multiple_objects) }
- let(:authorization) { authorize_user }
-
- before do
- post_lfs_json batch_url(project), body, headers
- end
-
- it_behaves_like 'LFS http 501 response'
- end
-
context 'project specific LFS settings' do
let(:body) { upload_body(sample_object) }
let(:authorization) { authorize_user }
@@ -60,105 +47,36 @@ RSpec.describe 'Git LFS API and storage' do
subject
end
- context 'with LFS disabled globally' do
- let(:lfs_enabled) { false }
-
- describe 'LFS disabled in project' do
- let(:project_lfs_enabled) { false }
-
- context 'when uploading' do
- subject { post_lfs_json(batch_url(project), body, headers) }
-
- it_behaves_like 'LFS http 501 response'
- end
+ describe 'LFS disabled in project' do
+ let(:project_lfs_enabled) { false }
- context 'when downloading' do
- subject { get(objects_url(project, sample_oid), params: {}, headers: headers) }
+ context 'when uploading' do
+ subject { post_lfs_json(batch_url(project), body, headers) }
- it_behaves_like 'LFS http 501 response'
- end
+ it_behaves_like 'LFS http 404 response'
end
- describe 'LFS enabled in project' do
- let(:project_lfs_enabled) { true }
-
- context 'when uploading' do
- subject { post_lfs_json(batch_url(project), body, headers) }
-
- it_behaves_like 'LFS http 501 response'
- end
+ context 'when downloading' do
+ subject { get(objects_url(project, sample_oid), params: {}, headers: headers) }
- context 'when downloading' do
- subject { get(objects_url(project, sample_oid), params: {}, headers: headers) }
-
- it_behaves_like 'LFS http 501 response'
- end
+ it_behaves_like 'LFS http 404 response'
end
end
- context 'with LFS enabled globally' do
- describe 'LFS disabled in project' do
- let(:project_lfs_enabled) { false }
-
- context 'when uploading' do
- subject { post_lfs_json(batch_url(project), body, headers) }
-
- it_behaves_like 'LFS http 403 response'
- end
-
- context 'when downloading' do
- subject { get(objects_url(project, sample_oid), params: {}, headers: headers) }
-
- it_behaves_like 'LFS http 403 response'
- end
- end
-
- describe 'LFS enabled in project' do
- let(:project_lfs_enabled) { true }
-
- context 'when uploading' do
- subject { post_lfs_json(batch_url(project), body, headers) }
-
- it_behaves_like 'LFS http 200 response'
- end
+ describe 'LFS enabled in project' do
+ let(:project_lfs_enabled) { true }
- context 'when downloading' do
- subject { get(objects_url(project, sample_oid), params: {}, headers: headers) }
+ context 'when uploading' do
+ subject { post_lfs_json(batch_url(project), body, headers) }
- it_behaves_like 'LFS http 200 response'
- end
+ it_behaves_like 'LFS http 200 response'
end
- end
- end
- describe 'deprecated API' do
- let(:authorization) { authorize_user }
+ context 'when downloading' do
+ subject { get(objects_url(project, sample_oid), params: {}, headers: headers) }
- shared_examples 'deprecated request' do
- before do
- subject
+ it_behaves_like 'LFS http 200 blob response'
end
-
- it_behaves_like 'LFS http expected response code and message' do
- let(:response_code) { 501 }
- let(:message) { 'Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.' }
- end
- end
-
- context 'when fetching LFS object using deprecated API' do
- subject { get(deprecated_objects_url(project, sample_oid), params: {}, headers: headers) }
-
- it_behaves_like 'deprecated request'
- end
-
- context 'when handling LFS request using deprecated API' do
- subject { post_lfs_json(deprecated_objects_url(project), nil, headers) }
-
- it_behaves_like 'deprecated request'
- end
-
- def deprecated_objects_url(project, oid = nil)
- File.join(["#{project.http_url_to_repo}/info/lfs/objects/", oid].compact)
end
end
@@ -167,196 +85,133 @@ RSpec.describe 'Git LFS API and storage' do
let(:before_get) { }
before do
+ project.lfs_objects << lfs_object
update_permissions
before_get
+
get objects_url(project, sample_oid), params: {}, headers: headers
end
- context 'and request comes from gitlab-workhorse' do
- context 'without user being authorized' do
- it_behaves_like 'LFS http 401 response'
- end
+ context 'when LFS uses object storage' do
+ let(:authorization) { authorize_user }
- context 'with required headers' do
- shared_examples 'responds with a file' do
- let(:sendfile) { 'X-Sendfile' }
+ let(:update_permissions) do
+ project.add_maintainer(user)
+ end
- it_behaves_like 'LFS http 200 response'
+ context 'when proxy download is enabled' do
+ let(:before_get) do
+ stub_lfs_object_storage(proxy_download: true)
+ lfs_object.file.migrate!(LfsObjectUploader::Store::REMOTE)
+ end
- it 'responds with the file location' do
- expect(response.headers['Content-Type']).to eq('application/octet-stream')
- expect(response.headers['X-Sendfile']).to eq(lfs_object.file.path)
- end
+ it 'responds with the workhorse send-url' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("send-url:")
end
+ end
- context 'with user is authorized' do
- let(:authorization) { authorize_user }
+ context 'when proxy download is disabled' do
+ let(:before_get) do
+ stub_lfs_object_storage(proxy_download: false)
+ lfs_object.file.migrate!(LfsObjectUploader::Store::REMOTE)
+ end
- context 'and does not have project access' do
- let(:update_permissions) do
- project.lfs_objects << lfs_object
- end
+ it 'responds with redirect' do
+ expect(response).to have_gitlab_http_status(:found)
+ end
- it_behaves_like 'LFS http 404 response'
- end
+ it 'responds with the file location' do
+ expect(response.location).to include(lfs_object.reload.file.path)
+ end
+ end
+ end
- context 'and does have project access' do
- let(:update_permissions) do
- project.add_maintainer(user)
- project.lfs_objects << lfs_object
- end
+ context 'when deploy key is authorized' do
+ let(:key) { create(:deploy_key) }
+ let(:authorization) { authorize_deploy_key }
- it_behaves_like 'responds with a file'
+ let(:update_permissions) do
+ project.deploy_keys << key
+ end
- context 'when LFS uses object storage' do
- context 'when proxy download is enabled' do
- let(:before_get) do
- stub_lfs_object_storage(proxy_download: true)
- lfs_object.file.migrate!(LfsObjectUploader::Store::REMOTE)
- end
+ it_behaves_like 'LFS http 200 blob response'
+ end
- it_behaves_like 'LFS http 200 response'
+ context 'when using a user key (LFSToken)' do
+ let(:authorization) { authorize_user_key }
- it 'responds with the workhorse send-url' do
- expect(response.headers[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("send-url:")
- end
- end
+ context 'when user allowed' do
+ let(:update_permissions) do
+ project.add_maintainer(user)
+ end
- context 'when proxy download is disabled' do
- let(:before_get) do
- stub_lfs_object_storage(proxy_download: false)
- lfs_object.file.migrate!(LfsObjectUploader::Store::REMOTE)
- end
+ it_behaves_like 'LFS http 200 blob response'
- it 'responds with redirect' do
- expect(response).to have_gitlab_http_status(:found)
- end
+ context 'when user password is expired' do
+ let(:user) { create(:user, password_expires_at: 1.minute.ago)}
- it 'responds with the file location' do
- expect(response.location).to include(lfs_object.reload.file.path)
- end
- end
- end
- end
+ it_behaves_like 'LFS http 401 response'
end
- context 'when deploy key is authorized' do
- let(:key) { create(:deploy_key) }
- let(:authorization) { authorize_deploy_key }
-
- let(:update_permissions) do
- project.deploy_keys << key
- project.lfs_objects << lfs_object
- end
+ context 'when user is blocked' do
+ let(:user) { create(:user, :blocked)}
- it_behaves_like 'responds with a file'
+ it_behaves_like 'LFS http 401 response'
end
+ end
- describe 'when using a user key (LFSToken)' do
- let(:authorization) { authorize_user_key }
-
- context 'when user allowed' do
- let(:update_permissions) do
- project.add_maintainer(user)
- project.lfs_objects << lfs_object
- end
+ context 'when user not allowed' do
+ it_behaves_like 'LFS http 404 response'
+ end
+ end
- it_behaves_like 'responds with a file'
+ context 'when build is authorized as' do
+ let(:authorization) { authorize_ci_project }
- context 'when user password is expired' do
- let(:user) { create(:user, password_expires_at: 1.minute.ago)}
+ shared_examples 'can download LFS only from own projects' do
+ context 'for owned project' do
+ let(:project) { create(:project, namespace: user.namespace) }
- it_behaves_like 'LFS http 401 response'
- end
+ it_behaves_like 'LFS http 200 blob response'
+ end
- context 'when user is blocked' do
- let(:user) { create(:user, :blocked)}
+ context 'for member of project' do
+ let(:pipeline) { create(:ci_empty_pipeline, project: project) }
- it_behaves_like 'LFS http 401 response'
- end
+ let(:update_permissions) do
+ project.add_reporter(user)
end
- context 'when user not allowed' do
- let(:update_permissions) do
- project.lfs_objects << lfs_object
- end
-
- it_behaves_like 'LFS http 404 response'
- end
+ it_behaves_like 'LFS http 200 blob response'
end
- context 'when build is authorized as' do
- let(:authorization) { authorize_ci_project }
-
- shared_examples 'can download LFS only from own projects' do
- context 'for owned project' do
- let(:project) { create(:project, namespace: user.namespace) }
-
- let(:update_permissions) do
- project.lfs_objects << lfs_object
- end
-
- it_behaves_like 'responds with a file'
- end
-
- context 'for member of project' do
- let(:pipeline) { create(:ci_empty_pipeline, project: project) }
-
- let(:update_permissions) do
- project.add_reporter(user)
- project.lfs_objects << lfs_object
- end
-
- it_behaves_like 'responds with a file'
- end
+ context 'for other project' do
+ let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
- context 'for other project' do
- let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
-
- let(:update_permissions) do
- project.lfs_objects << lfs_object
- end
-
- it 'rejects downloading code' do
- expect(response).to have_gitlab_http_status(other_project_status)
- end
- end
- end
-
- context 'administrator' do
- let(:user) { create(:admin) }
- let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
-
- it_behaves_like 'can download LFS only from own projects' do
- # We render 403, because administrator does have normally access
- let(:other_project_status) { 403 }
- end
+ it 'rejects downloading code' do
+ expect(response).to have_gitlab_http_status(:not_found)
end
+ end
+ end
- context 'regular user' do
- let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
+ context 'administrator' do
+ let(:user) { create(:admin) }
+ let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
- it_behaves_like 'can download LFS only from own projects' do
- # We render 404, to prevent data leakage about existence of the project
- let(:other_project_status) { 404 }
- end
- end
+ it_behaves_like 'can download LFS only from own projects'
+ end
- context 'does not have user' do
- let(:build) { create(:ci_build, :running, pipeline: pipeline) }
+ context 'regular user' do
+ let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
- it_behaves_like 'can download LFS only from own projects' do
- # We render 404, to prevent data leakage about existence of the project
- let(:other_project_status) { 404 }
- end
- end
- end
+ it_behaves_like 'can download LFS only from own projects'
end
- context 'without required headers' do
- let(:authorization) { authorize_user }
+ context 'does not have user' do
+ let(:build) { create(:ci_build, :running, pipeline: pipeline) }
- it_behaves_like 'LFS http 404 response'
+ it_behaves_like 'can download LFS only from own projects'
end
end
end
@@ -511,7 +366,7 @@ RSpec.describe 'Git LFS API and storage' do
let(:role) { :reporter }
end
- context 'when user does is not member of the project' do
+ context 'when user is not a member of the project' do
let(:update_user_permissions) { nil }
it_behaves_like 'LFS http 404 response'
@@ -520,7 +375,7 @@ RSpec.describe 'Git LFS API and storage' do
context 'when user does not have download access' do
let(:role) { :guest }
- it_behaves_like 'LFS http 403 response'
+ it_behaves_like 'LFS http 404 response'
end
context 'when user password is expired' do
@@ -591,7 +446,7 @@ RSpec.describe 'Git LFS API and storage' do
let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
it 'rejects downloading code' do
- expect(response).to have_gitlab_http_status(other_project_status)
+ expect(response).to have_gitlab_http_status(:not_found)
end
end
end
@@ -600,28 +455,19 @@ RSpec.describe 'Git LFS API and storage' do
let(:user) { create(:admin) }
let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
- it_behaves_like 'can download LFS only from own projects', renew_authorization: true do
- # We render 403, because administrator does have normally access
- let(:other_project_status) { 403 }
- end
+ it_behaves_like 'can download LFS only from own projects', renew_authorization: true
end
context 'regular user' do
let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
- it_behaves_like 'can download LFS only from own projects', renew_authorization: true do
- # We render 404, to prevent data leakage about existence of the project
- let(:other_project_status) { 404 }
- end
+ it_behaves_like 'can download LFS only from own projects', renew_authorization: true
end
context 'does not have user' do
let(:build) { create(:ci_build, :running, pipeline: pipeline) }
- it_behaves_like 'can download LFS only from own projects', renew_authorization: false do
- # We render 404, to prevent data leakage about existence of the project
- let(:other_project_status) { 404 }
- end
+ it_behaves_like 'can download LFS only from own projects', renew_authorization: false
end
end
@@ -919,11 +765,7 @@ RSpec.describe 'Git LFS API and storage' do
put_authorize
end
- it_behaves_like 'LFS http 200 response'
-
- it 'uses the gitlab-workhorse content type' do
- expect(response.media_type).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
- end
+ it_behaves_like 'LFS http 200 workhorse response'
end
shared_examples 'a local file' do
@@ -1142,7 +984,7 @@ RSpec.describe 'Git LFS API and storage' do
put_authorize
end
- it_behaves_like 'LFS http 404 response'
+ it_behaves_like 'LFS http 403 response'
end
end
@@ -1155,7 +997,7 @@ RSpec.describe 'Git LFS API and storage' do
put_authorize
end
- it_behaves_like 'LFS http 200 response'
+ it_behaves_like 'LFS http 200 workhorse response'
context 'when user password is expired' do
let(:user) { create(:user, password_expires_at: 1.minute.ago)}
@@ -1202,7 +1044,7 @@ RSpec.describe 'Git LFS API and storage' do
put_authorize
end
- it_behaves_like 'LFS http 200 response'
+ it_behaves_like 'LFS http 200 workhorse response'
it 'with location of LFS store and object details' do
expect(json_response['TempPath']).to eq(LfsObjectUploader.workhorse_local_upload_path)
@@ -1330,4 +1172,50 @@ RSpec.describe 'Git LFS API and storage' do
"#{sample_oid}012345678"
end
end
+
+ context 'with projects' do
+ it_behaves_like 'LFS http requests' do
+ let(:container) { project }
+ let(:authorize_guest) { project.add_guest(user) }
+ let(:authorize_download) { project.add_reporter(user) }
+ let(:authorize_upload) { project.add_developer(user) }
+ end
+ end
+
+ context 'with project wikis' do
+ it_behaves_like 'LFS http requests' do
+ let(:container) { create(:project_wiki, :empty_repo, project: project) }
+ let(:authorize_guest) { project.add_guest(user) }
+ let(:authorize_download) { project.add_reporter(user) }
+ let(:authorize_upload) { project.add_developer(user) }
+ end
+ end
+
+ context 'with snippets' do
+ # LFS is not supported on snippets, so we override the shared examples
+ # to expect 404 responses instead.
+ [
+ 'LFS http 200 response',
+ 'LFS http 200 blob response',
+ 'LFS http 403 response'
+ ].each do |examples|
+ shared_examples_for(examples) { it_behaves_like 'LFS http 404 response' }
+ end
+
+ context 'with project snippets' do
+ it_behaves_like 'LFS http requests' do
+ let(:container) { create(:project_snippet, :empty_repo, project: project) }
+ let(:authorize_guest) { project.add_guest(user) }
+ let(:authorize_download) { project.add_reporter(user) }
+ let(:authorize_upload) { project.add_developer(user) }
+ end
+ end
+
+ context 'with personal snippets' do
+ it_behaves_like 'LFS http requests' do
+ let(:container) { create(:personal_snippet, :empty_repo) }
+ let(:authorize_upload) { container.update!(author: user) }
+ end
+ end
+ end
end
diff --git a/spec/requests/lfs_locks_api_spec.rb b/spec/requests/lfs_locks_api_spec.rb
index 34e345cb1cf..0eb3cb4ca07 100644
--- a/spec/requests/lfs_locks_api_spec.rb
+++ b/spec/requests/lfs_locks_api_spec.rb
@@ -3,24 +3,38 @@
require 'spec_helper'
RSpec.describe 'Git LFS File Locking API' do
+ include LfsHttpHelpers
include WorkhorseHelpers
- let(:project) { create(:project) }
- let(:maintainer) { create(:user) }
- let(:developer) { create(:user) }
- let(:guest) { create(:user) }
- let(:path) { 'README.md' }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:path) { 'README.md' }
+
+ let(:user) { developer }
let(:headers) do
{
- 'Authorization' => authorization
+ 'Authorization' => authorize_user
}.compact
end
shared_examples 'unauthorized request' do
- context 'when user is not authorized' do
- let(:authorization) { authorize_user(guest) }
+ context 'when user does not have download permission' do
+ let(:user) { guest }
- it 'returns a forbidden 403 response' do
+ it 'returns a 404 response' do
+ post_lfs_json url, body, headers
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when user does not have upload permission' do
+ let(:user) { reporter }
+
+ it 'returns a 403 response' do
post_lfs_json url, body, headers
expect(response).to have_gitlab_http_status(:forbidden)
@@ -31,15 +45,15 @@ RSpec.describe 'Git LFS File Locking API' do
before do
allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
- project.add_developer(maintainer)
+ project.add_maintainer(maintainer)
project.add_developer(developer)
+ project.add_reporter(reporter)
project.add_guest(guest)
end
describe 'Create File Lock endpoint' do
- let(:url) { "#{project.http_url_to_repo}/info/lfs/locks" }
- let(:authorization) { authorize_user(developer) }
- let(:body) { { path: path } }
+ let(:url) { "#{project.http_url_to_repo}/info/lfs/locks" }
+ let(:body) { { path: path } }
include_examples 'unauthorized request'
@@ -76,8 +90,7 @@ RSpec.describe 'Git LFS File Locking API' do
end
describe 'Listing File Locks endpoint' do
- let(:url) { "#{project.http_url_to_repo}/info/lfs/locks" }
- let(:authorization) { authorize_user(developer) }
+ let(:url) { "#{project.http_url_to_repo}/info/lfs/locks" }
include_examples 'unauthorized request'
@@ -95,8 +108,7 @@ RSpec.describe 'Git LFS File Locking API' do
end
describe 'List File Locks for verification endpoint' do
- let(:url) { "#{project.http_url_to_repo}/info/lfs/locks/verify" }
- let(:authorization) { authorize_user(developer) }
+ let(:url) { "#{project.http_url_to_repo}/info/lfs/locks/verify" }
include_examples 'unauthorized request'
@@ -116,9 +128,8 @@ RSpec.describe 'Git LFS File Locking API' do
end
describe 'Delete File Lock endpoint' do
- let!(:lock) { lock_file('README.md', developer) }
- let(:url) { "#{project.http_url_to_repo}/info/lfs/locks/#{lock[:id]}/unlock" }
- let(:authorization) { authorize_user(developer) }
+ let!(:lock) { lock_file('README.md', developer) }
+ let(:url) { "#{project.http_url_to_repo}/info/lfs/locks/#{lock[:id]}/unlock" }
include_examples 'unauthorized request'
@@ -136,7 +147,7 @@ RSpec.describe 'Git LFS File Locking API' do
end
context 'when a maintainer uses force' do
- let(:authorization) { authorize_user(maintainer) }
+ let(:user) { maintainer }
it 'deletes the lock' do
project.add_maintainer(maintainer)
@@ -154,14 +165,6 @@ RSpec.describe 'Git LFS File Locking API' do
result[:lock]
end
- def authorize_user(user)
- ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password)
- end
-
- def post_lfs_json(url, body = nil, headers = nil)
- post(url, params: body.try(:to_json), headers: (headers || {}).merge('Content-Type' => LfsRequest::CONTENT_TYPE))
- end
-
def do_get(url, params = nil, headers = nil)
get(url, params: (params || {}), headers: (headers || {}).merge('Content-Type' => LfsRequest::CONTENT_TYPE))
end
diff --git a/spec/requests/projects/metrics/dashboards/builder_spec.rb b/spec/requests/projects/metrics/dashboards/builder_spec.rb
index e59ed591f63..002acca2135 100644
--- a/spec/requests/projects/metrics/dashboards/builder_spec.rb
+++ b/spec/requests/projects/metrics/dashboards/builder_spec.rb
@@ -32,6 +32,7 @@ RSpec.describe 'Projects::Metrics::Dashboards::BuilderController' do
label: Legend Label
YML
end
+
let_it_be(:invalid_panel_yml) do
<<~YML
---
diff --git a/spec/requests/projects/noteable_notes_spec.rb b/spec/requests/projects/noteable_notes_spec.rb
new file mode 100644
index 00000000000..2bf1ffb2edc
--- /dev/null
+++ b/spec/requests/projects/noteable_notes_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project noteable notes' do
+ describe '#index' do
+ let_it_be(:merge_request) { create(:merge_request) }
+
+ let(:etag_store) { Gitlab::EtagCaching::Store.new }
+ let(:notes_path) { project_noteable_notes_path(project, target_type: merge_request.class.name.underscore, target_id: merge_request.id) }
+ let(:project) { merge_request.project }
+ let(:user) { project.owner }
+
+ let(:response_etag) { response.headers['ETag'] }
+ let(:stored_etag) { "W/\"#{etag_store.get(notes_path)}\"" }
+
+ before do
+ login_as(user)
+ end
+
+ it 'does not set a Gitlab::EtagCaching ETag if there is a note' do
+ create(:note_on_merge_request, noteable: merge_request, project: merge_request.project)
+
+ get notes_path
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ # Rack::ETag will set an etag based on the body digest, but that doesn't
+ # interfere with notes pagination
+ expect(response_etag).not_to eq(stored_etag)
+ end
+
+ it 'sets a Gitlab::EtagCaching ETag if there is no note' do
+ get notes_path
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response_etag).to eq(stored_etag)
+ end
+ end
+end
diff --git a/spec/requests/projects/releases_controller_spec.rb b/spec/requests/projects/releases_controller_spec.rb
new file mode 100644
index 00000000000..8e492125ace
--- /dev/null
+++ b/spec/requests/projects/releases_controller_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Projects::ReleasesController' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ before do
+ project.add_developer(user)
+ login_as(user)
+ end
+
+ # Added as a request spec because of https://gitlab.com/gitlab-org/gitlab/-/issues/232386
+ describe 'GET #downloads' do
+ context 'filepath redirection' do
+ let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2' ) }
+ let!(:link) { create(:release_link, release: release, name: 'linux-amd64 binaries', filepath: filepath, url: 'https://aws.example.com/s3/project/bin/hello-darwin-amd64') }
+ let_it_be(:url) { "#{project_releases_path(project)}/#{release.tag}/downloads/bin/darwin-amd64" }
+
+ let(:subject) { get url }
+
+ context 'valid filepath' do
+ let(:filepath) { '/bin/darwin-amd64' }
+
+ it 'redirects to the asset direct link' do
+ subject
+
+ expect(response).to redirect_to('https://aws.example.com/s3/project/bin/hello-darwin-amd64')
+ end
+
+ it 'redirects with a status of 302' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:redirect)
+ end
+ end
+
+ context 'invalid filepath' do
+ let(:filepath) { '/binaries/win32' }
+
+ it 'is not found' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'invalid filepath' do
+ let(:invalid_filepath) { 'bin/darwin-amd64' }
+
+ let(:subject) { create(:release_link, name: 'linux-amd64 binaries', filepath: invalid_filepath, url: 'https://aws.example.com/s3/project/bin/hello-darwin-amd64') }
+
+ it 'cannot create an invalid filepath' do
+ expect { subject }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+ end
+end
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index 9fdafc06695..805ac5a9118 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -125,7 +125,8 @@ RSpec.describe 'Rack Attack global throttles' do
env: :throttle,
remote_ip: '127.0.0.1',
request_method: 'GET',
- path: '/users/sign_in'
+ path: '/users/sign_in',
+ matched: 'throttle_unauthenticated'
}
expect(Gitlab::AuthLogger).to receive(:error).with(arguments)
@@ -319,4 +320,62 @@ RSpec.describe 'Rack Attack global throttles' do
it_behaves_like 'rate-limited web authenticated requests'
end
end
+
+ describe 'throttle bypass header' do
+ let(:headers) { {} }
+ let(:bypass_header) { 'gitlab-bypass-rate-limiting' }
+
+ def do_request
+ get '/users/sign_in', headers: headers
+ end
+
+ before do
+ # Disabling protected paths throttle, otherwise requests to
+ # '/users/sign_in' are caught by this throttle.
+ settings_to_set[:throttle_protected_paths_enabled] = false
+
+ # Set low limits
+ settings_to_set[:throttle_unauthenticated_requests_per_period] = requests_per_period
+ settings_to_set[:throttle_unauthenticated_period_in_seconds] = period_in_seconds
+
+ stub_env('GITLAB_THROTTLE_BYPASS_HEADER', bypass_header)
+ settings_to_set[:throttle_unauthenticated_enabled] = true
+
+ stub_application_setting(settings_to_set)
+ end
+
+ shared_examples 'reject requests over the rate limit' do
+ it 'rejects requests over the rate limit' do
+ # At first, allow requests under the rate limit.
+ requests_per_period.times do
+ do_request
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ # the last straw
+ expect_rejection { do_request }
+ end
+ end
+
+ context 'without the bypass header set' do
+ it_behaves_like 'reject requests over the rate limit'
+ end
+
+ context 'with bypass header set to 1' do
+ let(:headers) { { bypass_header => '1' } }
+
+ it 'does not throttle' do
+ (1 + requests_per_period).times do
+ do_request
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
+ context 'with bypass header set to some other value' do
+ let(:headers) { { bypass_header => 'some other value' } }
+
+ it_behaves_like 'reject requests over the rate limit'
+ end
+ end
end
diff --git a/spec/requests/robots_txt_spec.rb b/spec/requests/robots_txt_spec.rb
new file mode 100644
index 00000000000..a8be4093a71
--- /dev/null
+++ b/spec/requests/robots_txt_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Robots.txt Requests', :aggregate_failures do
+ before do
+ Gitlab::Testing::RobotsBlockerMiddleware.block_requests!
+ end
+
+ after do
+ Gitlab::Testing::RobotsBlockerMiddleware.allow_requests!
+ end
+
+ it 'allows the requests' do
+ requests = [
+ '/users/sign_in',
+ '/namespace/subnamespace/design.gitlab.com',
+ '/users/foo/snippets',
+ '/users/foo/snippets/1'
+ ]
+
+ requests.each do |request|
+ get request
+
+ expect(response).not_to have_gitlab_http_status(:service_unavailable), "#{request} must be allowed"
+ end
+ end
+
+ it 'blocks the requests' do
+ requests = [
+ '/autocomplete/users',
+ '/autocomplete/projects',
+ '/search',
+ '/admin',
+ '/profile',
+ '/dashboard',
+ '/users',
+ '/users/foo',
+ '/help',
+ '/s/',
+ '/-/profile',
+ '/-/ide/project',
+ '/foo/bar/new',
+ '/foo/bar/edit',
+ '/foo/bar/raw',
+ '/groups/foo/analytics',
+ '/groups/foo/contribution_analytics',
+ '/groups/foo/group_members',
+ '/foo/bar/project.git',
+ '/foo/bar/archive/foo',
+ '/foo/bar/repository/archive',
+ '/foo/bar/activity',
+ '/foo/bar/blame',
+ '/foo/bar/commits',
+ '/foo/bar/commit',
+ '/foo/bar/compare',
+ '/foo/bar/network',
+ '/foo/bar/graphs',
+ '/foo/bar/merge_requests/1.patch',
+ '/foo/bar/merge_requests/1.diff',
+ '/foo/bar/merge_requests/1/diffs',
+ '/foo/bar/deploy_keys',
+ '/foo/bar/hooks',
+ '/foo/bar/services',
+ '/foo/bar/protected_branches',
+ '/foo/bar/uploads/foo',
+ '/foo/bar/project_members',
+ '/foo/bar/settings',
+ '/namespace/subnamespace/design.gitlab.com/settings',
+ '/foo/bar/-/import',
+ '/foo/bar/-/environments',
+ '/foo/bar/-/jobs',
+ '/foo/bar/-/requirements_management',
+ '/foo/bar/-/pipelines',
+ '/foo/bar/-/pipeline_schedules',
+ '/foo/bar/-/dependencies',
+ '/foo/bar/-/licenses',
+ '/foo/bar/-/metrics',
+ '/foo/bar/-/incidents',
+ '/foo/bar/-/value_stream_analytics',
+ '/foo/bar/-/analytics',
+ '/foo/bar/insights',
+ '/foo/bar/-/issues/123/realtime_changes',
+ '/groups/group/-/epics/123/realtime_changes'
+ ]
+
+ requests.each do |request|
+ get request
+
+ expect(response).to have_gitlab_http_status(:service_unavailable), "#{request} must be disallowed"
+ end
+ end
+end
diff --git a/spec/requests/search_controller_spec.rb b/spec/requests/search_controller_spec.rb
index 52bfc480313..93a2fecab74 100644
--- a/spec/requests/search_controller_spec.rb
+++ b/spec/requests/search_controller_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe SearchController, type: :request do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :public, :repository, :wiki_repo, name: 'awesome project', group: group) }
- before_all do
+ before do
login_as(user)
end
@@ -31,9 +31,11 @@ RSpec.describe SearchController, type: :request do
context 'for issues scope' do
let(:object) { :issue }
- let(:creation_args) { { project: project } }
- let(:params) { { search: '*', scope: 'issues' } }
- let(:threshold) { 0 }
+ let(:creation_args) { { project: project, title: 'foo' } }
+ let(:params) { { search: 'foo', scope: 'issues' } }
+ # there are 4 additional queries run for the logged in user:
+ # (1) geo_nodes, (1) users, (2) broadcast_messages
+ let(:threshold) { 4 }
it_behaves_like 'an efficient database result'
end
@@ -41,9 +43,11 @@ RSpec.describe SearchController, type: :request do
context 'for merge_request scope' do
let(:creation_traits) { [:unique_branches] }
let(:object) { :merge_request }
- let(:creation_args) { { source_project: project } }
- let(:params) { { search: '*', scope: 'merge_requests' } }
- let(:threshold) { 0 }
+ let(:creation_args) { { source_project: project, title: 'bar' } }
+ let(:params) { { search: 'bar', scope: 'merge_requests' } }
+ # there are 4 additional queries run for the logged in user:
+ # - (1) geo_nodes, (1) users, (2) broadcast_messages
+ let(:threshold) { 4 }
it_behaves_like 'an efficient database result'
end
@@ -51,16 +55,74 @@ RSpec.describe SearchController, type: :request do
context 'for project scope' do
let(:creation_traits) { [:public] }
let(:object) { :project }
- let(:creation_args) { {} }
- let(:params) { { search: '*', scope: 'projects' } }
+ let(:creation_args) { { name: 'project' } }
+ let(:params) { { search: 'project', scope: 'projects' } }
# some N+1 queries still exist
# each project requires 3 extra queries
# - one count for forks
# - one count for open MRs
# - one count for open Issues
- let(:threshold) { 9 }
+ # there are 4 additional queries run for the logged in user:
+ # (1) geo_nodes, (1) users, (2) broadcast_messages
+ let(:threshold) { 13 }
it_behaves_like 'an efficient database result'
end
+
+ context 'when searching by SHA' do
+ let(:sha) { '6d394385cf567f80a8fd85055db1ab4c5295806f' }
+
+ it 'finds a commit and redirects to its page' do
+ send_search_request({ search: sha, scope: 'projects', project_id: project.id })
+
+ expect(response).to redirect_to(project_commit_path(project, sha))
+ end
+
+ it 'finds a commit in uppercase and redirects to its page' do
+ send_search_request( { search: sha.upcase, scope: 'projects', project_id: project.id })
+
+ expect(response).to redirect_to(project_commit_path(project, sha))
+ end
+
+ it 'finds a commit with a partial sha and redirects to its page' do
+ send_search_request( { search: sha[0..10], scope: 'projects', project_id: project.id })
+
+ expect(response).to redirect_to(project_commit_path(project, sha))
+ end
+
+ it 'redirects to the commit even if another scope result is returned' do
+ create(:note, project: project, note: "This is the #{sha}")
+ send_search_request( { search: sha, scope: 'projects', project_id: project.id })
+
+ expect(response).to redirect_to(project_commit_path(project, sha))
+ end
+
+ it 'goes to search results with the force_search_results param set' do
+ send_search_request({ search: sha, force_search_results: true, project_id: project.id })
+
+ expect(response).not_to redirect_to(project_commit_path(project, sha))
+ end
+
+ it 'does not redirect if user cannot download_code from project' do
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(user, :download_code, project).and_return(false)
+
+ send_search_request({ search: sha, project_id: project.id })
+
+ expect(response).not_to redirect_to(project_commit_path(project, sha))
+ end
+
+ it 'does not redirect if commit sha not found in project' do
+ send_search_request({ search: '23594bc765e25c5b22c17a8cca25ebd50f792598', project_id: project.id })
+
+ expect(response).not_to redirect_to(project_commit_path(project, sha))
+ end
+
+ it 'does not redirect if not using project scope' do
+ send_search_request({ search: sha, group_id: project.root_namespace.id })
+
+ expect(response).not_to redirect_to(project_commit_path(project, sha))
+ end
+ end
end
end
diff --git a/spec/requests/user_sends_malformed_strings_spec.rb b/spec/requests/user_sends_malformed_strings_spec.rb
new file mode 100644
index 00000000000..da533606be5
--- /dev/null
+++ b/spec/requests/user_sends_malformed_strings_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'User sends malformed strings' do
+ include GitHttpHelpers
+
+ let(:null_byte) { "\u0000" }
+ let(:invalid_string) { "mal\xC0formed" }
+
+ it 'raises a 400 error with a null byte' do
+ post '/nonexistent', params: { a: "A #{null_byte} nasty string" }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ it 'raises a 400 error with an invalid string' do
+ post '/nonexistent', params: { a: "A #{invalid_string} nasty string" }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ it 'raises a 400 error with null bytes in the auth headers' do
+ clone_get("project/path", user: "hello#{null_byte}", password: "nothing to see")
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+end
diff --git a/spec/requests/user_sends_null_bytes_spec.rb b/spec/requests/user_sends_null_bytes_spec.rb
deleted file mode 100644
index 1ddfad40996..00000000000
--- a/spec/requests/user_sends_null_bytes_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'User sends null bytes as params' do
- let(:null_byte) { "\u0000" }
-
- it 'raises a 400 error' do
- post '/nonexistent', params: { a: "A #{null_byte} nasty string" }
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(response.body).to eq('Bad Request')
- end
-end
diff --git a/spec/requests/whats_new_controller_spec.rb b/spec/requests/whats_new_controller_spec.rb
index 29500a7b5f9..c04a6b00a93 100644
--- a/spec/requests/whats_new_controller_spec.rb
+++ b/spec/requests/whats_new_controller_spec.rb
@@ -4,19 +4,44 @@ require 'spec_helper'
RSpec.describe WhatsNewController do
describe 'whats_new_path' do
- before do
- allow_any_instance_of(WhatsNewController).to receive(:whats_new_most_recent_release_items).and_return('items')
- end
-
context 'with whats_new_drawer feature enabled' do
+ let(:fixture_dir_glob) { Dir.glob(File.join('spec', 'fixtures', 'whats_new', '*.yml')) }
+
before do
stub_feature_flags(whats_new_drawer: true)
+ allow(Dir).to receive(:glob).with(Rails.root.join('data', 'whats_new', '*.yml')).and_return(fixture_dir_glob)
end
- it 'is successful' do
- get whats_new_path, xhr: true
+ context 'with no page param' do
+ it 'responds with paginated data and headers' do
+ get whats_new_path, xhr: true
+
+ expect(response.body).to eq([{ title: "bright and sunshinin' day", release: "01.05" }].to_json)
+ expect(response.headers['X-Next-Page']).to eq(2)
+ end
+ end
+
+ context 'with page param' do
+ it 'responds with paginated data and headers' do
+ get whats_new_path(page: 2), xhr: true
+
+ expect(response.body).to eq([{ title: 'bright' }].to_json)
+ expect(response.headers['X-Next-Page']).to eq(3)
+ end
+
+ it 'returns a 404 if page param is negative' do
+ get whats_new_path(page: -1), xhr: true
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
- expect(response).to have_gitlab_http_status(:ok)
+ context 'when there are no more paginated results' do
+ it 'responds with nil X-Next-Page header' do
+ get whats_new_path(page: 3), xhr: true
+ expect(response.body).to eq([{ title: "It's gonna be a bright" }].to_json)
+ expect(response.headers['X-Next-Page']).to be nil
+ end
+ end
end
end
diff --git a/spec/routing/group_routing_spec.rb b/spec/routing/group_routing_spec.rb
index 9de99b73d23..f4d5ccc81b6 100644
--- a/spec/routing/group_routing_spec.rb
+++ b/spec/routing/group_routing_spec.rb
@@ -79,4 +79,40 @@ RSpec.describe "Groups", "routing" do
let(:group_path) { 'projects.abc123' }
end
end
+
+ describe 'dependency proxy for containers' do
+ context 'image name without namespace' do
+ it 'routes to #manifest' do
+ expect(get('/v2/gitlabhq/dependency_proxy/containers/ruby/manifests/2.3.6'))
+ .to route_to('groups/dependency_proxy_for_containers#manifest', group_id: 'gitlabhq', image: 'ruby', tag: '2.3.6')
+ end
+
+ it 'routes to #blob' do
+ expect(get('/v2/gitlabhq/dependency_proxy/containers/ruby/blobs/abc12345'))
+ .to route_to('groups/dependency_proxy_for_containers#blob', group_id: 'gitlabhq', image: 'ruby', sha: 'abc12345')
+ end
+
+ it 'does not route to #blob with an invalid sha' do
+ expect(get('/v2/gitlabhq/dependency_proxy/containers/ruby/blobs/sha256:asdf1234%2f%2e%2e'))
+ .not_to route_to(group_id: 'gitlabhq', image: 'ruby', sha: 'sha256:asdf1234%2f%2e%2e')
+ end
+
+ it 'does not route to #blob with an invalid image' do
+ expect(get('/v2/gitlabhq/dependency_proxy/containers/ru*by/blobs/abc12345'))
+ .not_to route_to('groups/dependency_proxy_for_containers#blob', group_id: 'gitlabhq', image: 'ru*by', sha: 'abc12345')
+ end
+ end
+
+ context 'image name with namespace' do
+ it 'routes to #manifest' do
+ expect(get('/v2/gitlabhq/dependency_proxy/containers/foo/bar/manifests/2.3.6'))
+ .to route_to('groups/dependency_proxy_for_containers#manifest', group_id: 'gitlabhq', image: 'foo/bar', tag: '2.3.6')
+ end
+
+ it 'routes to #blob' do
+ expect(get('/v2/gitlabhq/dependency_proxy/containers/foo/bar/blobs/abc12345'))
+ .to route_to('groups/dependency_proxy_for_containers#blob', group_id: 'gitlabhq', image: 'foo/bar', sha: 'abc12345')
+ end
+ end
+ end
end
diff --git a/spec/routing/openid_connect_spec.rb b/spec/routing/openid_connect_spec.rb
index b5291953730..dc9190114fd 100644
--- a/spec/routing/openid_connect_spec.rb
+++ b/spec/routing/openid_connect_spec.rb
@@ -3,7 +3,6 @@
require 'spec_helper'
# oauth_discovery_keys GET /oauth/discovery/keys(.:format) doorkeeper/openid_connect/discovery#keys
-# jwks GET /-/jwks(.:format) doorkeeper/openid_connect/discovery#keys
# oauth_discovery_provider GET /.well-known/openid-configuration(.:format) doorkeeper/openid_connect/discovery#provider
# oauth_discovery_webfinger GET /.well-known/webfinger(.:format) doorkeeper/openid_connect/discovery#webfinger
RSpec.describe Doorkeeper::OpenidConnect::DiscoveryController, 'routing' do
@@ -18,10 +17,6 @@ RSpec.describe Doorkeeper::OpenidConnect::DiscoveryController, 'routing' do
it "to #keys" do
expect(get('/oauth/discovery/keys')).to route_to('doorkeeper/openid_connect/discovery#keys')
end
-
- it "/-/jwks" do
- expect(get('/-/jwks')).to route_to('doorkeeper/openid_connect/discovery#keys')
- end
end
# oauth_userinfo GET /oauth/userinfo(.:format) doorkeeper/openid_connect/userinfo#show
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index f665dc31ee4..76ccdf3237c 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -369,3 +369,10 @@ RSpec.describe RunnerSetupController, 'routing' do
expect(get("/-/runner_setup/platforms")).to route_to('runner_setup#platforms')
end
end
+
+# jwks GET /-/jwks(.:format) jwks#index
+RSpec.describe JwksController, "routing" do
+ it "to #index" do
+ expect(get('/-/jwks')).to route_to('jwks#index')
+ end
+end
diff --git a/spec/rubocop/cop/code_reuse/active_record_spec.rb b/spec/rubocop/cop/code_reuse/active_record_spec.rb
deleted file mode 100644
index e15b9e11aed..00000000000
--- a/spec/rubocop/cop/code_reuse/active_record_spec.rb
+++ /dev/null
@@ -1,134 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rubocop'
-require_relative '../../../../rubocop/cop/code_reuse/active_record'
-
-RSpec.describe RuboCop::Cop::CodeReuse::ActiveRecord, type: :rubocop do
- include CopHelper
-
- subject(:cop) { described_class.new }
-
- it 'flags the use of "where" without any arguments' do
- expect_offense(<<~SOURCE)
- def foo
- User.where
- ^^^^^ This method can only be used inside an ActiveRecord model: https://gitlab.com/gitlab-org/gitlab-foss/issues/49653
- end
- SOURCE
- end
-
- it 'flags the use of "where" with arguments' do
- expect_offense(<<~SOURCE)
- def foo
- User.where(id: 10)
- ^^^^^ This method can only be used inside an ActiveRecord model: https://gitlab.com/gitlab-org/gitlab-foss/issues/49653
- end
- SOURCE
- end
-
- it 'does not flag the use of "group" without any arguments' do
- expect_no_offenses(<<~SOURCE)
- def foo
- project.group
- end
- SOURCE
- end
-
- it 'flags the use of "group" with arguments' do
- expect_offense(<<~SOURCE)
- def foo
- project.group(:name)
- ^^^^^ This method can only be used inside an ActiveRecord model: https://gitlab.com/gitlab-org/gitlab-foss/issues/49653
- end
- SOURCE
- end
-
- it 'does not flag the use of ActiveRecord models in a model' do
- path = rails_root_join('app', 'models', 'foo.rb').to_s
-
- expect_no_offenses(<<~SOURCE, path)
- def foo
- project.group(:name)
- end
- SOURCE
- end
-
- it 'does not flag the use of ActiveRecord models in a spec' do
- path = rails_root_join('spec', 'foo_spec.rb').to_s
-
- expect_no_offenses(<<~SOURCE, path)
- def foo
- project.group(:name)
- end
- SOURCE
- end
-
- it 'does not flag the use of ActiveRecord models in a background migration' do
- path = rails_root_join('lib', 'gitlab', 'background_migration', 'foo.rb').to_s
-
- expect_no_offenses(<<~SOURCE, path)
- def foo
- project.group(:name)
- end
- SOURCE
- end
-
- it 'does not flag the use of ActiveRecord models in lib/gitlab/database' do
- path = rails_root_join('lib', 'gitlab', 'database', 'foo.rb').to_s
-
- expect_no_offenses(<<~SOURCE, path)
- def foo
- project.group(:name)
- end
- SOURCE
- end
-
- it 'autocorrects offenses in instance methods by allowing them' do
- corrected = autocorrect_source(<<~SOURCE)
- def foo
- User.where
- end
- SOURCE
-
- expect(corrected).to eq(<<~SOURCE)
- # rubocop: disable CodeReuse/ActiveRecord
- def foo
- User.where
- end
- # rubocop: enable CodeReuse/ActiveRecord
- SOURCE
- end
-
- it 'autocorrects offenses in class methods by allowing them' do
- corrected = autocorrect_source(<<~SOURCE)
- def self.foo
- User.where
- end
- SOURCE
-
- expect(corrected).to eq(<<~SOURCE)
- # rubocop: disable CodeReuse/ActiveRecord
- def self.foo
- User.where
- end
- # rubocop: enable CodeReuse/ActiveRecord
- SOURCE
- end
-
- it 'autocorrects offenses in blocks by allowing them' do
- corrected = autocorrect_source(<<~SOURCE)
- get '/' do
- User.where
- end
- SOURCE
-
- expect(corrected).to eq(<<~SOURCE)
- # rubocop: disable CodeReuse/ActiveRecord
- get '/' do
- User.where
- end
- # rubocop: enable CodeReuse/ActiveRecord
- SOURCE
- end
-end
diff --git a/spec/rubocop/cop/graphql/resolver_type_spec.rb b/spec/rubocop/cop/graphql/resolver_type_spec.rb
new file mode 100644
index 00000000000..4807d66396a
--- /dev/null
+++ b/spec/rubocop/cop/graphql/resolver_type_spec.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rubocop'
+
+require_relative '../../../../rubocop/cop/graphql/resolver_type'
+
+RSpec.describe RuboCop::Cop::Graphql::ResolverType, type: :rubocop do
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ it 'adds an offense when there is no type annotaion' do
+ lacks_type = <<-SRC
+ module Resolvers
+ class FooResolver < BaseResolver
+ def resolve(**args)
+ [:thing]
+ end
+ end
+ end
+ SRC
+
+ inspect_source(lacks_type)
+
+ expect(cop.offenses.size).to eq 1
+ end
+
+ it 'does not add an offense for resolvers that have a type call' do
+ expect_no_offenses(<<-SRC)
+ module Resolvers
+ class FooResolver < BaseResolver
+ type [SomeEnum], null: true
+
+ def resolve(**args)
+ [:thing]
+ end
+ end
+ end
+ SRC
+ end
+
+ it 'ignores type calls on other objects' do
+ lacks_type = <<-SRC
+ module Resolvers
+ class FooResolver < BaseResolver
+ class FalsePositive < BaseObject
+ type RedHerringType, null: true
+ end
+
+ def resolve(**args)
+ [:thing]
+ end
+ end
+ end
+ SRC
+
+ inspect_source(lacks_type)
+
+ expect(cop.offenses.size).to eq 1
+ end
+
+ it 'does not add an offense unless the class is named using the Resolver convention' do
+ expect_no_offenses(<<-TYPE)
+ module Resolvers
+ class FooThingy
+ def something_other_than_resolve(**args)
+ [:thing]
+ end
+ end
+ end
+ TYPE
+ end
+end
diff --git a/spec/rubocop/cop/line_break_around_conditional_block_spec.rb b/spec/rubocop/cop/line_break_around_conditional_block_spec.rb
deleted file mode 100644
index 0a26ef49e35..00000000000
--- a/spec/rubocop/cop/line_break_around_conditional_block_spec.rb
+++ /dev/null
@@ -1,454 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rubocop'
-require 'rubocop/rspec/support'
-require_relative '../../../rubocop/cop/line_break_around_conditional_block'
-
-RSpec.describe RuboCop::Cop::LineBreakAroundConditionalBlock, type: :rubocop do
- include CopHelper
-
- subject(:cop) { described_class.new }
-
- shared_examples 'examples with conditional' do |conditional|
- it "flags violation for #{conditional} without line break before" do
- source = <<~RUBY
- do_something
- #{conditional} condition
- do_something_more
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses.size).to eq(1)
- offense = cop.offenses.first
-
- expect(offense.line).to eq(2)
- expect(cop.highlights).to eq(["#{conditional} condition\n do_something_more\nend"])
- expect(offense.message).to eq('Add a line break around conditional blocks')
- end
-
- it "flags violation for #{conditional} without line break after" do
- source = <<~RUBY
- #{conditional} condition
- do_something
- end
- do_something_more
- RUBY
- inspect_source(source)
-
- expect(cop.offenses.size).to eq(1)
- offense = cop.offenses.first
-
- expect(offense.line).to eq(1)
- expect(cop.highlights).to eq(["#{conditional} condition\n do_something\nend"])
- expect(offense.message).to eq('Add a line break around conditional blocks')
- end
-
- it "doesn't flag violation for #{conditional} with line break before and after" do
- source = <<~RUBY
- #{conditional} condition
- do_something
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by a method definition" do
- source = <<~RUBY
- def a_method
- #{conditional} condition
- do_something
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by a class definition" do
- source = <<~RUBY
- class Foo
- #{conditional} condition
- do_something
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by a module definition" do
- source = <<~RUBY
- module Foo
- #{conditional} condition
- do_something
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by a begin definition" do
- source = <<~RUBY
- begin
- #{conditional} condition
- do_something
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by an assign/begin definition" do
- source = <<~RUBY
- @project ||= begin
- #{conditional} condition
- do_something
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by a block definition" do
- source = <<~RUBY
- on_block(param_a) do |item|
- #{conditional} condition
- do_something
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by a block definition with a comment" do
- source = <<~RUBY
- on_block(param_a) do |item| # a short comment
- #{conditional} condition
- do_something
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by a block definition using brackets" do
- source = <<~RUBY
- on_block(param_a) { |item|
- #{conditional} condition
- do_something
- end
- }
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by a comment" do
- source = <<~RUBY
- # a short comment
- #{conditional} condition
- do_something
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by an assignment" do
- source = <<~RUBY
- foo =
- #{conditional} condition
- do_something
- else
- do_something_more
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by a multiline comment" do
- source = <<~RUBY
- =begin
- a multiline comment
- =end
- #{conditional} condition
- do_something
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by another conditional" do
- source = <<~RUBY
- #{conditional} condition_a
- #{conditional} condition_b
- do_something
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by an else" do
- source = <<~RUBY
- if condition_a
- do_something
- else
- #{conditional} condition_b
- do_something_extra
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by an elsif" do
- source = <<~RUBY
- if condition_a
- do_something
- elsif condition_b
- #{conditional} condition_c
- do_something_extra
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by an ensure" do
- source = <<~RUBY
- def a_method
- ensure
- #{conditional} condition_c
- do_something_extra
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by a when" do
- source = <<~RUBY
- case field
- when value
- #{conditional} condition_c
- do_something_extra
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} followed by a comment" do
- source = <<~RUBY
- #{conditional} condition
- do_something
- end
- # a short comment
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} followed by an end" do
- source = <<~RUBY
- class Foo
-
- #{conditional} condition
- do_something
- end
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} followed by an else" do
- source = <<~RUBY
- #{conditional} condition_a
- #{conditional} condition_b
- do_something
- end
- else
- do_something_extra
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} followed by a when" do
- source = <<~RUBY
- case
- when condition_a
- #{conditional} condition_b
- do_something
- end
- when condition_c
- do_something_extra
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} followed by an elsif" do
- source = <<~RUBY
- if condition_a
- #{conditional} condition_b
- do_something
- end
- elsif condition_c
- do_something_extra
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} preceded by a rescue" do
- source = <<~RUBY
- def a_method
- do_something
- rescue
- #{conditional} condition
- do_something
- end
- end
- RUBY
-
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "doesn't flag violation for #{conditional} followed by a rescue" do
- source = <<~RUBY
- def a_method
- #{conditional} condition
- do_something
- end
- rescue
- do_something_extra
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-
- it "autocorrects #{conditional} without line break before" do
- source = <<~RUBY
- do_something
- #{conditional} condition
- do_something_more
- end
- RUBY
- autocorrected = autocorrect_source(source)
-
- expected_source = <<~RUBY
- do_something
-
- #{conditional} condition
- do_something_more
- end
- RUBY
- expect(autocorrected).to eql(expected_source)
- end
-
- it "autocorrects #{conditional} without line break after" do
- source = <<~RUBY
- #{conditional} condition
- do_something
- end
- do_something_more
- RUBY
- autocorrected = autocorrect_source(source)
-
- expected_source = <<~RUBY
- #{conditional} condition
- do_something
- end
-
- do_something_more
- RUBY
- expect(autocorrected).to eql(expected_source)
- end
-
- it "autocorrects #{conditional} without line break before and after" do
- source = <<~RUBY
- do_something
- #{conditional} condition
- do_something_more
- end
- do_something_extra
- RUBY
- autocorrected = autocorrect_source(source)
-
- expected_source = <<~RUBY
- do_something
-
- #{conditional} condition
- do_something_more
- end
-
- do_something_extra
- RUBY
- expect(autocorrected).to eql(expected_source)
- end
- end
-
- %w[if unless].each do |example|
- it_behaves_like 'examples with conditional', example
- end
-
- it "doesn't flag violation for if with elsif" do
- source = <<~RUBY
- if condition
- do_something
- elsif another_condition
- do_something_more
- end
- RUBY
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
-end
diff --git a/spec/rubocop/cop/rspec/be_success_matcher_spec.rb b/spec/rubocop/cop/rspec/be_success_matcher_spec.rb
index a16cd8b634f..b14cf39cbde 100644
--- a/spec/rubocop/cop/rspec/be_success_matcher_spec.rb
+++ b/spec/rubocop/cop/rspec/be_success_matcher_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-
+require 'rubocop'
require_relative '../../../../rubocop/cop/rspec/be_success_matcher'
RSpec.describe RuboCop::Cop::RSpec::BeSuccessMatcher, type: :rubocop do
diff --git a/spec/serializers/base_discussion_entity_spec.rb b/spec/serializers/base_discussion_entity_spec.rb
new file mode 100644
index 00000000000..5f483da4113
--- /dev/null
+++ b/spec/serializers/base_discussion_entity_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BaseDiscussionEntity do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:note) { create(:discussion_note_on_merge_request) }
+
+ let(:request) { double('request', note_entity: ProjectNoteEntity) }
+ let(:controller) { double('controller') }
+ let(:entity) { described_class.new(discussion, request: request, context: controller) }
+ let(:discussion) { note.discussion }
+
+ subject { entity.as_json }
+
+ before do
+ allow(controller).to receive(:render_to_string)
+ allow(request).to receive(:current_user).and_return(user)
+ allow(request).to receive(:noteable).and_return(note.noteable)
+ end
+
+ it 'exposes correct attributes' do
+ expect(subject.keys.sort).to include(
+ :commit_id,
+ :confidential,
+ :diff_discussion,
+ :discussion_path,
+ :expanded,
+ :for_commit,
+ :id,
+ :individual_note,
+ :resolvable,
+ :resolve_path,
+ :resolve_with_issue_path
+ )
+ end
+
+ context 'when is LegacyDiffDiscussion' do
+ let(:project) { create(:project) }
+ let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:discussion) { create(:legacy_diff_note_on_merge_request, noteable: merge_request, project: project).to_discussion }
+
+ it 'exposes correct attributes' do
+ expect(subject.keys.sort).to include(
+ :commit_id,
+ :diff_discussion,
+ :discussion_path,
+ :expanded,
+ :for_commit,
+ :id,
+ :individual_note
+ )
+ end
+ end
+
+ context 'when diff file is present' do
+ let(:note) { create(:diff_note_on_merge_request) }
+
+ it 'exposes diff file attributes' do
+ expect(subject.keys.sort).to include(
+ :active,
+ :diff_file,
+ :line_code,
+ :position,
+ :truncated_diff_lines
+ )
+ end
+ end
+end
diff --git a/spec/serializers/diff_file_entity_spec.rb b/spec/serializers/diff_file_entity_spec.rb
index bebe2e2dfb5..1b8456e5c49 100644
--- a/spec/serializers/diff_file_entity_spec.rb
+++ b/spec/serializers/diff_file_entity_spec.rb
@@ -69,4 +69,15 @@ RSpec.describe DiffFileEntity do
end
end
end
+
+ describe '#is_fully_expanded' do
+ context 'file with a conflict' do
+ let(:options) { { conflicts: { diff_file.new_path => double(diff_lines_for_serializer: []) } } }
+
+ it 'returns false' do
+ expect(diff_file).not_to receive(:fully_expanded?)
+ expect(subject[:is_fully_expanded]).to eq(false)
+ end
+ end
+ end
end
diff --git a/spec/serializers/diffs_entity_spec.rb b/spec/serializers/diffs_entity_spec.rb
index 5928a1c24b3..7569493573b 100644
--- a/spec/serializers/diffs_entity_spec.rb
+++ b/spec/serializers/diffs_entity_spec.rb
@@ -8,9 +8,12 @@ RSpec.describe DiffsEntity do
let(:request) { EntityRequest.new(project: project, current_user: user) }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
let(:merge_request_diffs) { merge_request.merge_request_diffs }
+ let(:options) do
+ { request: request, merge_request: merge_request, merge_request_diffs: merge_request_diffs }
+ end
let(:entity) do
- described_class.new(merge_request_diffs.first.diffs, request: request, merge_request: merge_request, merge_request_diffs: merge_request_diffs)
+ described_class.new(merge_request_diffs.first.diffs, options)
end
context 'as json' do
@@ -68,5 +71,50 @@ RSpec.describe DiffsEntity do
end
end
end
+
+ context 'when there are conflicts' do
+ let(:diff_files) { merge_request_diffs.first.diffs.diff_files }
+ let(:diff_file_with_conflict) { diff_files.to_a.last }
+ let(:diff_file_without_conflict) { diff_files.to_a[-2] }
+
+ let(:resolvable_conflicts) { true }
+ let(:conflict_file) { double(our_path: diff_file_with_conflict.new_path) }
+ let(:conflicts) { double(conflicts: double(files: [conflict_file]), can_be_resolved_in_ui?: resolvable_conflicts) }
+
+ let(:merge_ref_head_diff) { true }
+ let(:options) { super().merge(merge_ref_head_diff: merge_ref_head_diff) }
+
+ before do
+ allow(MergeRequests::Conflicts::ListService).to receive(:new).and_return(conflicts)
+ end
+
+ it 'conflicts are highlighted' do
+ expect(conflict_file).to receive(:diff_lines_for_serializer)
+ expect(diff_file_with_conflict).not_to receive(:diff_lines_for_serializer)
+ expect(diff_file_without_conflict).to receive(:diff_lines_for_serializer).twice # for highlighted_diff_lines and is_fully_expanded
+
+ subject
+ end
+
+ context 'merge ref head diff is not chosen to be displayed' do
+ let(:merge_ref_head_diff) { false }
+
+ it 'conflicts are not calculated' do
+ expect(MergeRequests::Conflicts::ListService).not_to receive(:new)
+ end
+ end
+
+ context 'when conflicts cannot be resolved' do
+ let(:resolvable_conflicts) { false }
+
+ it 'conflicts are not highlighted' do
+ expect(conflict_file).not_to receive(:diff_lines_for_serializer)
+ expect(diff_file_with_conflict).to receive(:diff_lines_for_serializer).twice # for highlighted_diff_lines and is_fully_expanded
+ expect(diff_file_without_conflict).to receive(:diff_lines_for_serializer).twice # for highlighted_diff_lines and is_fully_expanded
+
+ subject
+ end
+ end
+ end
end
end
diff --git a/spec/serializers/discussion_entity_spec.rb b/spec/serializers/discussion_entity_spec.rb
index e1734d5290f..0645d19da5b 100644
--- a/spec/serializers/discussion_entity_spec.rb
+++ b/spec/serializers/discussion_entity_spec.rb
@@ -39,6 +39,10 @@ RSpec.describe DiscussionEntity do
)
end
+ it 'does not include base discussion in the notes' do
+ expect(subject[:notes].first.keys).not_to include(:base_discussion)
+ end
+
it 'resolved_by matches note_user_entity schema' do
Notes::ResolveService.new(note.project, user).execute(note)
diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb
index c90f771335e..f5d6706a844 100644
--- a/spec/serializers/environment_entity_spec.rb
+++ b/spec/serializers/environment_entity_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe EnvironmentEntity do
end
it 'exposes core elements of environment' do
- expect(subject).to include(:id, :name, :state, :environment_path)
+ expect(subject).to include(:id, :global_id, :name, :state, :environment_path)
end
it 'exposes folder path' do
diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index 5cad35eaedf..3f7d5542ae8 100644
--- a/spec/serializers/merge_request_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -106,29 +106,16 @@ RSpec.describe MergeRequestWidgetEntity do
let(:merge_base_job_id) { merge_base_pipeline.builds.first.id }
it 'has head_path and base_path entries' do
- expect(subject[:codeclimate][:head_path]).to be_present
- expect(subject[:codeclimate][:base_path]).to be_present
+ expect(subject[:codeclimate][:head_path]).to include("/jobs/#{generic_job_id}/artifacts/download?file_type=codequality")
+ expect(subject[:codeclimate][:base_path]).to include("/jobs/#{generic_job_id}/artifacts/download?file_type=codequality")
end
context 'on pipelines for merged results' do
let(:pipeline) { create(:ci_pipeline, :merged_result_pipeline, :with_codequality_report, project: project) }
- context 'with merge_base_pipelines enabled' do
- it 'returns URLs from the head_pipeline and merge_base_pipeline' do
- expect(subject[:codeclimate][:head_path]).to include("/jobs/#{generic_job_id}/artifacts/download?file_type=codequality")
- expect(subject[:codeclimate][:base_path]).to include("/jobs/#{merge_base_job_id}/artifacts/download?file_type=codequality")
- end
- end
-
- context 'with merge_base_pipelines disabled' do
- before do
- stub_feature_flags(merge_base_pipelines: false)
- end
-
- it 'returns URLs from the head_pipeline and base_pipeline' do
- expect(subject[:codeclimate][:head_path]).to include("/jobs/#{generic_job_id}/artifacts/download?file_type=codequality")
- expect(subject[:codeclimate][:base_path]).to include("/jobs/#{generic_job_id}/artifacts/download?file_type=codequality")
- end
+ it 'returns URLs from the head_pipeline and merge_base_pipeline' do
+ expect(subject[:codeclimate][:head_path]).to include("/jobs/#{generic_job_id}/artifacts/download?file_type=codequality")
+ expect(subject[:codeclimate][:base_path]).to include("/jobs/#{merge_base_job_id}/artifacts/download?file_type=codequality")
end
end
end
@@ -333,6 +320,10 @@ RSpec.describe MergeRequestWidgetEntity do
end
context 'when suggest pipeline feature is not enabled' do
+ before do
+ stub_feature_flags(suggest_pipeline: false)
+ end
+
it 'provides no valid value for user callout path' do
expect(subject[:user_callouts_path]).to be_nil
end
diff --git a/spec/serializers/move_to_project_entity_spec.rb b/spec/serializers/move_to_project_entity_spec.rb
index a14bc3ae622..fad49ceb067 100644
--- a/spec/serializers/move_to_project_entity_spec.rb
+++ b/spec/serializers/move_to_project_entity_spec.rb
@@ -12,8 +12,12 @@ RSpec.describe MoveToProjectEntity do
expect(subject[:id]).to eq(project.id)
end
- it 'includes the full path' do
+ it 'includes the human-readable full path' do
expect(subject[:name_with_namespace]).to eq(project.name_with_namespace)
end
+
+ it 'includes the full path' do
+ expect(subject[:full_path]).to eq(project.full_path)
+ end
end
end
diff --git a/spec/serializers/paginated_diff_entity_spec.rb b/spec/serializers/paginated_diff_entity_spec.rb
index 821ed34d3ec..551b392c9e9 100644
--- a/spec/serializers/paginated_diff_entity_spec.rb
+++ b/spec/serializers/paginated_diff_entity_spec.rb
@@ -31,4 +31,50 @@ RSpec.describe PaginatedDiffEntity do
total_pages: 7
)
end
+
+ context 'when there are conflicts' do
+ let(:diff_batch) { merge_request.merge_request_diff.diffs_in_batch(7, 3, diff_options: nil) }
+ let(:diff_files) { diff_batch.diff_files.to_a }
+ let(:diff_file_with_conflict) { diff_files.last }
+ let(:diff_file_without_conflict) { diff_files.first }
+
+ let(:resolvable_conflicts) { true }
+ let(:conflict_file) { double(our_path: diff_file_with_conflict.new_path) }
+ let(:conflicts) { double(conflicts: double(files: [conflict_file]), can_be_resolved_in_ui?: resolvable_conflicts) }
+
+ let(:merge_ref_head_diff) { true }
+ let(:options) { super().merge(merge_ref_head_diff: merge_ref_head_diff) }
+
+ before do
+ allow(MergeRequests::Conflicts::ListService).to receive(:new).and_return(conflicts)
+ end
+
+ it 'conflicts are highlighted' do
+ expect(conflict_file).to receive(:diff_lines_for_serializer)
+ expect(diff_file_with_conflict).not_to receive(:diff_lines_for_serializer)
+ expect(diff_file_without_conflict).to receive(:diff_lines_for_serializer).twice # for highlighted_diff_lines and is_fully_expanded
+
+ subject
+ end
+
+ context 'merge ref head diff is not chosen to be displayed' do
+ let(:merge_ref_head_diff) { false }
+
+ it 'conflicts are not calculated' do
+ expect(MergeRequests::Conflicts::ListService).not_to receive(:new)
+ end
+ end
+
+ context 'when conflicts cannot be resolved' do
+ let(:resolvable_conflicts) { false }
+
+ it 'conflicts are not highlighted' do
+ expect(conflict_file).not_to receive(:diff_lines_for_serializer)
+ expect(diff_file_with_conflict).to receive(:diff_lines_for_serializer).twice # for highlighted_diff_lines and is_fully_expanded
+ expect(diff_file_without_conflict).to receive(:diff_lines_for_serializer).twice # for highlighted_diff_lines and is_fully_expanded
+
+ subject
+ end
+ end
+ end
end
diff --git a/spec/serializers/test_case_entity_spec.rb b/spec/serializers/test_case_entity_spec.rb
index 45e63e3feec..e2b0f722f41 100644
--- a/spec/serializers/test_case_entity_spec.rb
+++ b/spec/serializers/test_case_entity_spec.rb
@@ -27,12 +27,17 @@ RSpec.describe TestCaseEntity do
context 'when test case is failed' do
let(:test_case) { create_test_case_rspec_failed }
+ before do
+ test_case.set_recent_failures(3, 'master')
+ end
+
it 'contains correct test case details' do
expect(subject[:status]).to eq('failed')
expect(subject[:name]).to eq('Test#sum when a is 1 and b is 3 returns summary')
expect(subject[:classname]).to eq('spec.test_spec')
expect(subject[:file]).to eq('./spec/test_spec.rb')
expect(subject[:execution_time]).to eq(2.22)
+ expect(subject[:recent_failures]).to eq({ count: 3, base_branch: 'master' })
end
end
@@ -42,7 +47,7 @@ RSpec.describe TestCaseEntity do
end
context 'when attachment is present' do
- let(:test_case) { build(:test_case, :failed_with_attachment, job: job) }
+ let(:test_case) { build(:report_test_case, :failed_with_attachment, job: job) }
it 'returns the attachment_url' do
expect(subject).to include(:attachment_url)
@@ -50,7 +55,7 @@ RSpec.describe TestCaseEntity do
end
context 'when attachment is not present' do
- let(:test_case) { build(:test_case, job: job) }
+ let(:test_case) { build(:report_test_case, job: job) }
it 'returns a nil attachment_url' do
expect(subject[:attachment_url]).to be_nil
@@ -64,7 +69,7 @@ RSpec.describe TestCaseEntity do
end
context 'when attachment is present' do
- let(:test_case) { build(:test_case, :failed_with_attachment, job: job) }
+ let(:test_case) { build(:report_test_case, :failed_with_attachment, job: job) }
it 'returns no attachment_url' do
expect(subject).not_to include(:attachment_url)
@@ -72,7 +77,7 @@ RSpec.describe TestCaseEntity do
end
context 'when attachment is not present' do
- let(:test_case) { build(:test_case, job: job) }
+ let(:test_case) { build(:report_test_case, job: job) }
it 'returns no attachment_url' do
expect(subject).not_to include(:attachment_url)
diff --git a/spec/serializers/test_suite_comparer_entity_spec.rb b/spec/serializers/test_suite_comparer_entity_spec.rb
index 882991a6208..a63f5683779 100644
--- a/spec/serializers/test_suite_comparer_entity_spec.rb
+++ b/spec/serializers/test_suite_comparer_entity_spec.rb
@@ -100,109 +100,5 @@ RSpec.describe TestSuiteComparerEntity do
expect(subject[:existing_failures]).to be_empty
end
end
-
- context 'limits amount of tests returned' do
- before do
- stub_const('TestSuiteComparerEntity::DEFAULT_MAX_TESTS', 2)
- stub_const('TestSuiteComparerEntity::DEFAULT_MIN_TESTS', 1)
- end
-
- context 'prefers new over existing and resolved' do
- before do
- 3.times { add_new_failure }
- 3.times { add_new_error }
- 3.times { add_existing_failure }
- 3.times { add_existing_error }
- 3.times { add_resolved_failure }
- 3.times { add_resolved_error }
- end
-
- it 'returns 2 of each new category, and 1 of each resolved and existing' do
- expect(subject[:summary]).to include(total: 18, resolved: 6, failed: 6, errored: 6)
- expect(subject[:new_failures].count).to eq(2)
- expect(subject[:new_errors].count).to eq(2)
- expect(subject[:existing_failures].count).to eq(1)
- expect(subject[:existing_errors].count).to eq(1)
- expect(subject[:resolved_failures].count).to eq(1)
- expect(subject[:resolved_errors].count).to eq(1)
- end
- end
-
- context 'prefers existing over resolved' do
- before do
- 3.times { add_existing_failure }
- 3.times { add_existing_error }
- 3.times { add_resolved_failure }
- 3.times { add_resolved_error }
- end
-
- it 'returns 2 of each existing category, and 1 of each resolved' do
- expect(subject[:summary]).to include(total: 12, resolved: 6, failed: 3, errored: 3)
- expect(subject[:new_failures].count).to eq(0)
- expect(subject[:new_errors].count).to eq(0)
- expect(subject[:existing_failures].count).to eq(2)
- expect(subject[:existing_errors].count).to eq(2)
- expect(subject[:resolved_failures].count).to eq(1)
- expect(subject[:resolved_errors].count).to eq(1)
- end
- end
-
- context 'limits amount of resolved' do
- before do
- 3.times { add_resolved_failure }
- 3.times { add_resolved_error }
- end
-
- it 'returns 2 of each resolved category' do
- expect(subject[:summary]).to include(total: 6, resolved: 6, failed: 0, errored: 0)
- expect(subject[:new_failures].count).to eq(0)
- expect(subject[:new_errors].count).to eq(0)
- expect(subject[:existing_failures].count).to eq(0)
- expect(subject[:existing_errors].count).to eq(0)
- expect(subject[:resolved_failures].count).to eq(2)
- expect(subject[:resolved_errors].count).to eq(2)
- end
- end
-
- private
-
- def add_new_failure
- failed_case = create_test_case_rspec_failed(SecureRandom.hex)
- head_suite.add_test_case(failed_case)
- end
-
- def add_new_error
- error_case = create_test_case_rspec_error(SecureRandom.hex)
- head_suite.add_test_case(error_case)
- end
-
- def add_existing_failure
- failed_case = create_test_case_rspec_failed(SecureRandom.hex)
- base_suite.add_test_case(failed_case)
- head_suite.add_test_case(failed_case)
- end
-
- def add_existing_error
- error_case = create_test_case_rspec_error(SecureRandom.hex)
- base_suite.add_test_case(error_case)
- head_suite.add_test_case(error_case)
- end
-
- def add_resolved_failure
- case_name = SecureRandom.hex
- failed_case = create_test_case_java_failed(case_name)
- success_case = create_test_case_java_success(case_name)
- base_suite.add_test_case(failed_case)
- head_suite.add_test_case(success_case)
- end
-
- def add_resolved_error
- case_name = SecureRandom.hex
- error_case = create_test_case_java_error(case_name)
- success_case = create_test_case_java_success(case_name)
- base_suite.add_test_case(error_case)
- head_suite.add_test_case(success_case)
- end
- end
end
end
diff --git a/spec/services/admin/propagate_integration_service_spec.rb b/spec/services/admin/propagate_integration_service_spec.rb
index 5df4d9db8b1..13320528e4f 100644
--- a/spec/services/admin/propagate_integration_service_spec.rb
+++ b/spec/services/admin/propagate_integration_service_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe Admin::PropagateIntegrationService do
let_it_be(:inherited_integration) do
create(:jira_service, project: create(:project), inherit_from_id: instance_integration.id)
end
+
let_it_be(:different_type_inherited_integration) do
create(:redmine_service, project: project, inherit_from_id: instance_integration.id)
end
@@ -67,7 +68,7 @@ RSpec.describe Admin::PropagateIntegrationService do
end
end
- context 'with a group without integration' do
+ context 'with a subgroup without integration' do
let(:subgroup) { create(:group, parent: group) }
it 'calls to PropagateIntegrationGroupWorker' do
@@ -77,6 +78,18 @@ RSpec.describe Admin::PropagateIntegrationService do
described_class.propagate(group_integration)
end
end
+
+ context 'with a subgroup with integration' do
+ let(:subgroup) { create(:group, parent: group) }
+ let(:subgroup_integration) { create(:jira_service, group: subgroup, project: nil, inherit_from_id: group_integration.id) }
+
+ it 'calls to PropagateIntegrationInheritDescendantWorker' do
+ expect(PropagateIntegrationInheritDescendantWorker).to receive(:perform_async)
+ .with(group_integration.id, subgroup_integration.id, subgroup_integration.id)
+
+ described_class.propagate(group_integration)
+ end
+ 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 f2be317a13d..2834322be7b 100644
--- a/spec/services/alert_management/create_alert_issue_service_spec.rb
+++ b/spec/services/alert_management/create_alert_issue_service_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe AlertManagement::CreateAlertIssueService do
'generatorURL' => 'http://8d467bd4607a:9090/graph?g0.expr=vector%281%29&g0.tab=1'
}
end
+
let_it_be(:generic_alert, reload: true) { create(:alert_management_alert, :triggered, project: project, payload: payload) }
let_it_be(:prometheus_alert, reload: true) { create(:alert_management_alert, :triggered, :prometheus, project: project, payload: payload) }
let(:alert) { generic_alert }
diff --git a/spec/services/alert_management/http_integrations/create_service_spec.rb b/spec/services/alert_management/http_integrations/create_service_spec.rb
new file mode 100644
index 00000000000..ac5c62caf84
--- /dev/null
+++ b/spec/services/alert_management/http_integrations/create_service_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AlertManagement::HttpIntegrations::CreateService do
+ let_it_be(:user_with_permissions) { create(:user) }
+ let_it_be(:user_without_permissions) { create(:user) }
+ let_it_be_with_reload(:project) { create(:project) }
+
+ let(:current_user) { user_with_permissions }
+ let(:params) { {} }
+
+ let(:service) { described_class.new(project, current_user, params) }
+
+ before_all do
+ project.add_maintainer(user_with_permissions)
+ end
+
+ describe '#execute' do
+ shared_examples 'error response' do |message|
+ it 'has an informative message' do
+ expect(response).to be_error
+ expect(response.message).to eq(message)
+ end
+ end
+
+ subject(:response) { service.execute }
+
+ context 'when the current_user is anonymous' do
+ let(:current_user) { nil }
+
+ it_behaves_like 'error response', 'You have insufficient permissions to create an HTTP integration for this project'
+ end
+
+ context 'when current_user does not have permission to create integrations' do
+ let(:current_user) { user_without_permissions }
+
+ it_behaves_like 'error response', 'You have insufficient permissions to create an HTTP integration for this project'
+ end
+
+ context 'when an integration already exists' do
+ let_it_be(:existing_integration) { create(:alert_management_http_integration, project: project) }
+
+ it_behaves_like 'error response', 'Multiple HTTP integrations are not supported for this project'
+ end
+
+ context 'when an error occurs during update' do
+ it_behaves_like 'error response', "Name can't be blank"
+ end
+
+ context 'with valid params' do
+ let(:params) { { name: 'New HTTP Integration', active: true } }
+
+ it 'successfully creates an integration' do
+ expect(response).to be_success
+
+ integration = response.payload[:integration]
+ expect(integration).to be_a(::AlertManagement::HttpIntegration)
+ expect(integration.name).to eq('New HTTP Integration')
+ expect(integration).to be_active
+ expect(integration.token).to be_present
+ expect(integration.endpoint_identifier).to be_present
+ end
+ end
+ end
+end
diff --git a/spec/services/alert_management/http_integrations/destroy_service_spec.rb b/spec/services/alert_management/http_integrations/destroy_service_spec.rb
new file mode 100644
index 00000000000..cd949d728de
--- /dev/null
+++ b/spec/services/alert_management/http_integrations/destroy_service_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AlertManagement::HttpIntegrations::DestroyService do
+ let_it_be(:user_with_permissions) { create(:user) }
+ let_it_be(:user_without_permissions) { create(:user) }
+ let_it_be(:project) { create(:project) }
+
+ let!(:integration) { create(:alert_management_http_integration, project: project) }
+ let(:current_user) { user_with_permissions }
+ let(:params) { {} }
+ let(:service) { described_class.new(integration, current_user) }
+
+ before_all do
+ project.add_maintainer(user_with_permissions)
+ end
+
+ describe '#execute' do
+ shared_examples 'error response' do |message|
+ it 'has an informative message' do
+ expect(response).to be_error
+ expect(response.message).to eq(message)
+ end
+ end
+
+ subject(:response) { service.execute }
+
+ context 'when the current_user is anonymous' do
+ let(:current_user) { nil }
+
+ it_behaves_like 'error response', 'You have insufficient permissions to remove this HTTP integration'
+ end
+
+ context 'when current_user does not have permission to create integrations' do
+ let(:current_user) { user_without_permissions }
+
+ it_behaves_like 'error response', 'You have insufficient permissions to remove this HTTP integration'
+ end
+
+ context 'when an error occurs during removal' do
+ before do
+ allow(integration).to receive(:destroy).and_return(false)
+ integration.errors.add(:name, 'cannot be removed')
+ end
+
+ it_behaves_like 'error response', 'Name cannot be removed'
+ end
+
+ it 'successfully returns the integration' do
+ expect(response).to be_success
+
+ integration_result = response.payload[:integration]
+ expect(integration_result).to be_a(::AlertManagement::HttpIntegration)
+ expect(integration_result.name).to eq(integration.name)
+ expect(integration_result.active).to eq(integration.active)
+ expect(integration_result.token).to eq(integration.token)
+ expect(integration_result.endpoint_identifier).to eq(integration.endpoint_identifier)
+
+ expect { integration.reload }.to raise_error ActiveRecord::RecordNotFound
+ end
+ end
+end
diff --git a/spec/services/alert_management/http_integrations/update_service_spec.rb b/spec/services/alert_management/http_integrations/update_service_spec.rb
new file mode 100644
index 00000000000..94c34d9a29c
--- /dev/null
+++ b/spec/services/alert_management/http_integrations/update_service_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AlertManagement::HttpIntegrations::UpdateService do
+ let_it_be(:user_with_permissions) { create(:user) }
+ let_it_be(:user_without_permissions) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be_with_reload(:integration) { create(:alert_management_http_integration, :inactive, project: project, name: 'Old Name') }
+
+ let(:current_user) { user_with_permissions }
+ let(:params) { {} }
+
+ let(:service) { described_class.new(integration, current_user, params) }
+
+ before_all do
+ project.add_maintainer(user_with_permissions)
+ end
+
+ describe '#execute' do
+ shared_examples 'error response' do |message|
+ it 'has an informative message' do
+ expect(response).to be_error
+ expect(response.message).to eq(message)
+ end
+ end
+
+ subject(:response) { service.execute }
+
+ context 'when the current_user is anonymous' do
+ let(:current_user) { nil }
+
+ it_behaves_like 'error response', 'You have insufficient permissions to update this HTTP integration'
+ end
+
+ context 'when current_user does not have permission to create integrations' do
+ let(:current_user) { user_without_permissions }
+
+ it_behaves_like 'error response', 'You have insufficient permissions to update this HTTP integration'
+ end
+
+ context 'when an error occurs during update' do
+ let(:params) { { name: '' } }
+
+ it_behaves_like 'error response', "Name can't be blank"
+ end
+
+ context 'with name param' do
+ let(:params) { { name: 'New Name' } }
+
+ it 'successfully updates the integration' do
+ expect(response).to be_success
+ expect(response.payload[:integration].name).to eq('New Name')
+ end
+ end
+
+ context 'with active param' do
+ let(:params) { { active: true } }
+
+ it 'successfully updates the integration' do
+ expect(response).to be_success
+ expect(response.payload[:integration]).to be_active
+ end
+ end
+
+ context 'with regenerate_token flag' do
+ let(:params) { { regenerate_token: true } }
+
+ it 'successfully updates the integration' do
+ previous_token = integration.token
+
+ expect(response).to be_success
+ expect(response.payload[:integration].token).not_to eq(previous_token)
+ end
+ end
+ end
+end
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 ae0b8d6d7ac..2f920de7fc7 100644
--- a/spec/services/alert_management/process_prometheus_alert_service_spec.rb
+++ b/spec/services/alert_management/process_prometheus_alert_service_spec.rb
@@ -11,9 +11,16 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
describe '#execute' do
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 }
+ let(:send_email) { true }
+ let(:incident_management_setting) do
+ double(
+ auto_close_incident?: auto_close_incident,
+ create_issue?: create_issue,
+ send_email?: send_email
+ )
+ end
before do
allow(service)
@@ -55,6 +62,7 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
it_behaves_like 'adds an alert management alert event'
it_behaves_like 'processes incident issues'
+ it_behaves_like 'Alert Notification Service sends notification email'
context 'existing alert is resolved' do
let!(:alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint) }
@@ -92,28 +100,48 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
end
end
- context 'when auto-alert creation is disabled' do
+ context 'when auto-creation of issues is disabled' do
let(:create_issue) { false }
it_behaves_like 'does not process incident issues'
end
+
+ context 'when emails are disabled' do
+ let(:send_email) { false }
+
+ it 'does not send notification' do
+ expect(NotificationService).not_to receive(:new)
+
+ expect(subject).to be_success
+ end
+ 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_behaves_like 'Alert Notification Service sends notification email'
+ it_behaves_like 'processes incident issues'
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'
-
context 'when auto-alert creation is disabled' do
let(:create_issue) { false }
it_behaves_like 'does not process incident issues'
end
+
+ context 'when emails are disabled' do
+ let(:send_email) { false }
+
+ it 'does not send notification' do
+ expect(NotificationService).not_to receive(:new)
+
+ expect(subject).to be_success
+ end
+ end
end
context 'when alert cannot be created' do
@@ -125,6 +153,9 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
allow(service).to receive_message_chain(:alert, :errors).and_return(errors)
end
+ it_behaves_like 'Alert Notification Service sends no notifications', http_status: :bad_request
+ it_behaves_like 'does not process incident issues due to error', http_status: :bad_request
+
it 'writes a warning to the log' do
expect(Gitlab::AppLogger).to receive(:warn).with(
message: 'Unable to create AlertManagement::Alert',
@@ -134,8 +165,6 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
execute
end
-
- it_behaves_like 'does not process incident issues'
end
it { is_expected.to be_success }
@@ -148,6 +177,9 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
context 'when auto_resolve_incident set to true' do
context 'when status can be changed' do
+ it_behaves_like 'Alert Notification Service sends notification email'
+ it_behaves_like 'does not process incident issues'
+
it 'resolves an existing alert' do
expect { execute }.to change { alert.reload.resolved? }.to(true)
end
@@ -185,6 +217,8 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
execute
end
+
+ it_behaves_like 'Alert Notification Service sends notification email'
end
it { is_expected.to be_success }
@@ -197,6 +231,16 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
expect { execute }.not_to change { alert.reload.resolved? }
end
end
+
+ context 'when emails are disabled' do
+ let(:send_email) { false }
+
+ it 'does not send notification' do
+ expect(NotificationService).not_to receive(:new)
+
+ expect(subject).to be_success
+ end
+ end
end
context 'environment given' do
diff --git a/spec/services/alert_management/sync_alert_service_data_service_spec.rb b/spec/services/alert_management/sync_alert_service_data_service_spec.rb
new file mode 100644
index 00000000000..ecec60011db
--- /dev/null
+++ b/spec/services/alert_management/sync_alert_service_data_service_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AlertManagement::SyncAlertServiceDataService do
+ let_it_be(:alerts_service) do
+ AlertsService.skip_callback(:save, :after, :update_http_integration)
+ service = create(:alerts_service, :active)
+ AlertsService.set_callback(:save, :after, :update_http_integration)
+
+ service
+ end
+
+ describe '#execute' do
+ subject(:execute) { described_class.new(alerts_service).execute }
+
+ context 'without http integration' do
+ it 'creates the integration' do
+ expect { execute }
+ .to change { AlertManagement::HttpIntegration.count }.by(1)
+ end
+
+ it 'returns a success' do
+ expect(subject.success?).to eq(true)
+ end
+ end
+
+ context 'existing legacy http integration' do
+ let_it_be(:integration) { create(:alert_management_http_integration, :legacy, project: alerts_service.project) }
+
+ it 'updates the integration' do
+ expect { execute }
+ .to change { integration.reload.encrypted_token }.to(alerts_service.data.encrypted_token)
+ .and change { integration.encrypted_token_iv }.to(alerts_service.data.encrypted_token_iv)
+ end
+
+ it 'returns a success' do
+ expect(subject.success?).to eq(true)
+ end
+ end
+
+ context 'existing other http integration' do
+ let_it_be(:integration) { create(:alert_management_http_integration, project: alerts_service.project) }
+
+ it 'creates the integration' do
+ expect { execute }
+ .to change { AlertManagement::HttpIntegration.count }.by(1)
+ end
+
+ it 'returns a success' do
+ expect(subject.success?).to eq(true)
+ end
+ end
+ end
+end
diff --git a/spec/services/application_settings/update_service_spec.rb b/spec/services/application_settings/update_service_spec.rb
index e5060fa2eeb..03e55b3ec46 100644
--- a/spec/services/application_settings/update_service_spec.rb
+++ b/spec/services/application_settings/update_service_spec.rb
@@ -66,7 +66,7 @@ RSpec.describe ApplicationSettings::UpdateService do
context 'when params is blank' do
let(:params) { {} }
- it 'does not add to whitelist' do
+ it 'does not add to allowlist' do
expect { subject.execute }.not_to change {
application_settings.outbound_local_requests_whitelist
}
@@ -80,7 +80,7 @@ RSpec.describe ApplicationSettings::UpdateService do
let(:params) { { add_to_outbound_local_requests_whitelist: ['example.com', ''] } }
- it 'adds to whitelist' do
+ it 'adds to allowlist' do
expect { subject.execute }.to change {
application_settings.outbound_local_requests_whitelist
}
@@ -91,14 +91,14 @@ RSpec.describe ApplicationSettings::UpdateService do
end
end
- context 'when param outbound_local_requests_whitelist_raw is passed' do
+ context 'when param outbound_local_requests_allowlist_raw is passed' do
before do
application_settings.outbound_local_requests_whitelist = ['127.0.0.1']
end
- let(:params) { { outbound_local_requests_whitelist_raw: 'example.com;gitlab.com' } }
+ let(:params) { { outbound_local_requests_allowlist_raw: 'example.com;gitlab.com' } }
- it 'overwrites the existing whitelist' do
+ it 'overwrites the existing allowlist' do
expect { subject.execute }.to change {
application_settings.outbound_local_requests_whitelist
}
diff --git a/spec/services/audit_event_service_spec.rb b/spec/services/audit_event_service_spec.rb
index 3317fcf8444..997f506c269 100644
--- a/spec/services/audit_event_service_spec.rb
+++ b/spec/services/audit_event_service_spec.rb
@@ -3,17 +3,13 @@
require 'spec_helper'
RSpec.describe AuditEventService do
- let(:project) { create(:project) }
- let(:user) { create(:user, :with_sign_ins) }
- let(:project_member) { create(:project_member, user: user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user, :with_sign_ins) }
+ let_it_be(:project_member) { create(:project_member, user: user) }
let(:service) { described_class.new(user, project, { action: :destroy }) }
let(:logger) { instance_double(Gitlab::AuditJsonLogger) }
describe '#security_event' do
- before do
- stub_licensed_features(admin_audit_log: false)
- end
-
it 'creates an event and logs to a file' do
expect(service).to receive(:file_logger).and_return(logger)
expect(logger).to receive(:info).with(author_id: user.id,
@@ -78,6 +74,31 @@ RSpec.describe AuditEventService do
audit_service.for_authentication.security_event
end
+
+ context 'with IP address', :request_store do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:from_caller, :from_context, :from_author_sign_in, :output) do
+ '192.168.0.1' | '192.168.0.2' | '192.168.0.3' | '192.168.0.1'
+ nil | '192.168.0.2' | '192.168.0.3' | '192.168.0.2'
+ nil | nil | '192.168.0.3' | '192.168.0.3'
+ end
+
+ with_them do
+ let(:user) { create(:user, current_sign_in_ip: from_author_sign_in) }
+ let(:audit_service) { described_class.new(user, user, with: 'standard', ip_address: from_caller) }
+
+ before do
+ allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return(from_context)
+ end
+
+ specify do
+ expect(AuthenticationEvent).to receive(:new).with(hash_including(ip_address: output))
+
+ audit_service.for_authentication.security_event
+ end
+ end
+ end
end
end
diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb
index bc85f4f0087..90ef32f1c5c 100644
--- a/spec/services/auth/container_registry_authentication_service_spec.rb
+++ b/spec/services/auth/container_registry_authentication_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Auth::ContainerRegistryAuthenticationService do
+ include AdminModeHelper
+
let(:current_project) { nil }
let(:current_user) { nil }
let(:current_params) { {} }
@@ -135,7 +137,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
describe '#full_access_token' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
let(:token) { described_class.full_access_token(project.full_path) }
subject { { token: token } }
@@ -148,7 +150,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
describe '#pull_access_token' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
let(:token) { described_class.pull_access_token(project.full_path) }
subject { { token: token } }
@@ -161,7 +163,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'user authorization' do
- let(:current_user) { create(:user) }
+ let_it_be(:current_user) { create(:user) }
context 'for registry catalog' do
let(:current_params) do
@@ -175,14 +177,14 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for private project' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
context 'allow to use scope-less authentication' do
it_behaves_like 'a valid token'
end
context 'allow developer to push images' do
- before do
+ before_all do
project.add_developer(current_user)
end
@@ -195,7 +197,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'disallow developer to delete images' do
- before do
+ before_all do
project.add_developer(current_user)
end
@@ -222,7 +224,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'disallow developer to delete images since registry 2.7' do
- before do
+ before_all do
project.add_developer(current_user)
end
@@ -235,7 +237,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'allow reporter to pull images' do
- before do
+ before_all do
project.add_reporter(current_user)
end
@@ -250,7 +252,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'disallow reporter to delete images' do
- before do
+ before_all do
project.add_reporter(current_user)
end
@@ -263,7 +265,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'disallow reporter to delete images since registry 2.7' do
- before do
+ before_all do
project.add_reporter(current_user)
end
@@ -276,7 +278,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'return a least of privileges' do
- before do
+ before_all do
project.add_reporter(current_user)
end
@@ -289,7 +291,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'disallow guest to pull or push images' do
- before do
+ before_all do
project.add_guest(current_user)
end
@@ -302,7 +304,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'disallow guest to delete images' do
- before do
+ before_all do
project.add_guest(current_user)
end
@@ -315,7 +317,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'disallow guest to delete images since registry 2.7' do
- before do
+ before_all do
project.add_guest(current_user)
end
@@ -329,7 +331,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for public project' do
- let(:project) { create(:project, :public) }
+ let_it_be(:project) { create(:project, :public) }
context 'allow anyone to pull images' do
let(:current_params) do
@@ -378,7 +380,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for internal project' do
- let(:project) { create(:project, :internal) }
+ let_it_be(:project) { create(:project, :internal) }
context 'for internal user' do
context 'allow anyone to pull images' do
@@ -420,7 +422,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
context 'for external user' do
context 'disallow anyone to pull or push images' do
- let(:current_user) { create(:user, external: true) }
+ let_it_be(:current_user) { create(:user, external: true) }
let(:current_params) do
{ scopes: ["repository:#{project.full_path}:pull,push"] }
end
@@ -430,7 +432,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'disallow anyone to delete images' do
- let(:current_user) { create(:user, external: true) }
+ let_it_be(:current_user) { create(:user, external: true) }
let(:current_params) do
{ scopes: ["repository:#{project.full_path}:*"] }
end
@@ -440,7 +442,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'disallow anyone to delete images since registry 2.7' do
- let(:current_user) { create(:user, external: true) }
+ let_it_be(:current_user) { create(:user, external: true) }
let(:current_params) do
{ scopes: ["repository:#{project.full_path}:delete"] }
end
@@ -453,14 +455,14 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'delete authorized as maintainer' do
- let(:current_project) { create(:project) }
- let(:current_user) { create(:user) }
+ let_it_be(:current_project) { create(:project) }
+ let_it_be(:current_user) { create(:user) }
let(:authentication_abilities) do
[:admin_container_image]
end
- before do
+ before_all do
current_project.add_maintainer(current_user)
end
@@ -488,14 +490,14 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'build authorized as user' do
- let(:current_project) { create(:project) }
- let(:current_user) { create(:user) }
+ let_it_be(:current_project) { create(:project) }
+ let_it_be(:current_user) { create(:user) }
let(:authentication_abilities) do
[:build_read_container_image, :build_create_container_image, :build_destroy_container_image]
end
- before do
+ before_all do
current_project.add_developer(current_user)
end
@@ -550,7 +552,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'allow for public' do
- let(:project) { create(:project, :public) }
+ let_it_be(:project) { create(:project, :public) }
it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
@@ -563,7 +565,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'when you are member' do
- before do
+ before_all do
project.add_developer(current_user)
end
@@ -572,7 +574,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'when you are owner' do
- let(:project) { create(:project, namespace: current_user.namespace) }
+ let_it_be(:project) { create(:project, namespace: current_user.namespace) }
it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
@@ -580,12 +582,12 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for private' do
- let(:project) { create(:project, :private) }
+ let_it_be(:project) { create(:project, :private) }
it_behaves_like 'pullable for being team member'
context 'when you are admin' do
- let(:current_user) { create(:admin) }
+ let_it_be(:current_user) { create(:admin) }
context 'when you are not member' do
it_behaves_like 'an inaccessible'
@@ -593,7 +595,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'when you are member' do
- before do
+ before_all do
project.add_developer(current_user)
end
@@ -602,7 +604,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'when you are owner' do
- let(:project) { create(:project, namespace: current_user.namespace) }
+ let_it_be(:project) { create(:project, namespace: current_user.namespace) }
it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
@@ -618,9 +620,9 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
context 'disallow for all' do
context 'when you are member' do
- let(:project) { create(:project, :public) }
+ let_it_be(:project) { create(:project, :public) }
- before do
+ before_all do
project.add_developer(current_user)
end
@@ -629,7 +631,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'when you are owner' do
- let(:project) { create(:project, :public, namespace: current_user.namespace) }
+ let_it_be(:project) { create(:project, :public, namespace: current_user.namespace) }
it_behaves_like 'an inaccessible'
it_behaves_like 'not a container repository factory'
@@ -639,10 +641,10 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for project without container registry' do
- let(:project) { create(:project, :public, container_registry_enabled: false) }
+ let_it_be(:project) { create(:project, :public, container_registry_enabled: false) }
before do
- project.update(container_registry_enabled: false)
+ project.update!(container_registry_enabled: false)
end
context 'disallow when pulling' do
@@ -656,7 +658,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for project that disables repository' do
- let(:project) { create(:project, :public, :repository_disabled) }
+ let_it_be(:project) { create(:project, :public, :repository_disabled) }
context 'disallow when pulling' do
let(:current_params) do
@@ -670,8 +672,8 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'registry catalog browsing authorized as admin' do
- let(:current_user) { create(:user, :admin) }
- let(:project) { create(:project, :public) }
+ let_it_be(:current_user) { create(:user, :admin) }
+ let_it_be(:project) { create(:project, :public) }
let(:current_params) do
{ scopes: ["registry:catalog:*"] }
@@ -681,8 +683,8 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'support for multiple scopes' do
- let(:internal_project) { create(:project, :internal) }
- let(:private_project) { create(:project, :private) }
+ let_it_be(:internal_project) { create(:project, :internal) }
+ let_it_be(:private_project) { create(:project, :private) }
let(:current_params) do
{
@@ -694,7 +696,11 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'user has access to all projects' do
- let(:current_user) { create(:user, :admin) }
+ let_it_be(:current_user) { create(:user, :admin) }
+
+ before do
+ enable_admin_mode!(current_user)
+ end
it_behaves_like 'a browsable' do
let(:access) do
@@ -711,7 +717,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'user only has access to internal project' do
- let(:current_user) { create(:user) }
+ let_it_be(:current_user) { create(:user) }
it_behaves_like 'a browsable' do
let(:access) do
@@ -747,7 +753,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for private project' do
- let(:project) { create(:project, :private) }
+ let_it_be(:project) { create(:project, :private) }
let(:current_params) do
{ scopes: ["repository:#{project.full_path}:pull"] }
@@ -757,7 +763,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for public project' do
- let(:project) { create(:project, :public) }
+ let_it_be(:project) { create(:project, :public) }
context 'when pulling and pushing' do
let(:current_params) do
@@ -806,7 +812,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for public project' do
- let(:project) { create(:project, :public) }
+ let_it_be(:project) { create(:project, :public) }
context 'when pulling' do
it_behaves_like 'a pullable'
@@ -824,7 +830,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for internal project' do
- let(:project) { create(:project, :internal) }
+ let_it_be(:project) { create(:project, :internal) }
context 'when pulling' do
it_behaves_like 'a pullable'
@@ -842,7 +848,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for private project' do
- let(:project) { create(:project, :private) }
+ let_it_be(:project) { create(:project, :private) }
context 'when pulling' do
it_behaves_like 'a pullable'
@@ -880,7 +886,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for public project' do
- let(:project) { create(:project, :public) }
+ let_it_be(:project) { create(:project, :public) }
context 'when pulling' do
it_behaves_like 'a pullable'
@@ -890,7 +896,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for internal project' do
- let(:project) { create(:project, :internal) }
+ let_it_be(:project) { create(:project, :internal) }
context 'when pulling' do
it_behaves_like 'an inaccessible'
@@ -900,7 +906,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for private project' do
- let(:project) { create(:project, :internal) }
+ let_it_be(:project) { create(:project, :internal) }
context 'when pulling' do
it_behaves_like 'an inaccessible'
@@ -918,10 +924,10 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'when deploy token is not related to the project' do
- let(:current_user) { create(:deploy_token, read_registry: false) }
+ let_it_be(:current_user) { create(:deploy_token, read_registry: false) }
context 'for public project' do
- let(:project) { create(:project, :public) }
+ let_it_be(:project) { create(:project, :public) }
context 'when pulling' do
it_behaves_like 'a pullable'
@@ -929,7 +935,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for internal project' do
- let(:project) { create(:project, :internal) }
+ let_it_be(:project) { create(:project, :internal) }
context 'when pulling' do
it_behaves_like 'an inaccessible'
@@ -937,7 +943,7 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'for private project' do
- let(:project) { create(:project, :internal) }
+ let_it_be(:project) { create(:project, :internal) }
context 'when pulling' do
it_behaves_like 'an inaccessible'
@@ -949,19 +955,19 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
let(:current_user) { create(:deploy_token, :revoked, projects: [project]) }
context 'for public project' do
- let(:project) { create(:project, :public) }
+ let_it_be(:project) { create(:project, :public) }
it_behaves_like 'a pullable'
end
context 'for internal project' do
- let(:project) { create(:project, :internal) }
+ let_it_be(:project) { create(:project, :internal) }
it_behaves_like 'an inaccessible'
end
context 'for private project' do
- let(:project) { create(:project, :internal) }
+ let_it_be(:project) { create(:project, :internal) }
it_behaves_like 'an inaccessible'
end
@@ -969,14 +975,13 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
end
context 'user authorization' do
- let(:current_user) { create(:user) }
+ let_it_be(:current_user) { create(:user) }
context 'with multiple scopes' do
- let(:project) { create(:project) }
- let(:project2) { create }
+ let_it_be(:project) { create(:project) }
context 'allow developer to push images' do
- before do
+ before_all do
project.add_developer(current_user)
end
diff --git a/spec/services/auto_merge/base_service_spec.rb b/spec/services/auto_merge/base_service_spec.rb
index 98fa6012089..1d33dc15838 100644
--- a/spec/services/auto_merge/base_service_spec.rb
+++ b/spec/services/auto_merge/base_service_spec.rb
@@ -131,7 +131,7 @@ RSpec.describe AutoMerge::BaseService do
end
describe '#update' do
- subject { service.update(merge_request) }
+ subject { service.update(merge_request) } # rubocop:disable Rails/SaveBang
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
diff --git a/spec/services/auto_merge_service_spec.rb b/spec/services/auto_merge_service_spec.rb
index eab95973e1b..3f7a26aa00e 100644
--- a/spec/services/auto_merge_service_spec.rb
+++ b/spec/services/auto_merge_service_spec.rb
@@ -148,7 +148,7 @@ RSpec.describe AutoMergeService do
end
describe '#update' do
- subject { service.update(merge_request) }
+ subject { service.update(merge_request) } # rubocop:disable Rails/SaveBang
context 'when auto merge is enabled' do
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
diff --git a/spec/services/bulk_create_integration_service_spec.rb b/spec/services/bulk_create_integration_service_spec.rb
index 5d896f78b35..674382ee14f 100644
--- a/spec/services/bulk_create_integration_service_spec.rb
+++ b/spec/services/bulk_create_integration_service_spec.rb
@@ -5,13 +5,15 @@ require 'spec_helper'
RSpec.describe BulkCreateIntegrationService do
include JiraServiceHelper
- before do
+ before_all do
stub_jira_service_test
end
+ let_it_be(:excluded_group) { create(:group) }
+ let_it_be(:excluded_project) { create(:project, group: excluded_group) }
+ let(:instance_integration) { create(:jira_service, :instance) }
+ let(:template_integration) { create(:jira_service, :template) }
let(:excluded_attributes) { %w[id project_id group_id inherit_from_id instance template created_at updated_at] }
- let!(:instance_integration) { create(:jira_service, :instance) }
- let!(:template_integration) { create(:jira_service, :template) }
shared_examples 'creates integration from batch ids' do
it 'updates the inherited integrations' do
@@ -37,71 +39,125 @@ RSpec.describe BulkCreateIntegrationService do
it 'updates inherit_from_id attributes' do
described_class.new(integration, batch, association).execute
- expect(created_integration.reload.inherit_from_id).to eq(integration.id)
+ expect(created_integration.reload.inherit_from_id).to eq(inherit_from_id)
end
end
- shared_examples 'runs project callbacks' do
+ shared_examples 'updates project callbacks' do
it 'updates projects#has_external_issue_tracker for issue tracker services' do
described_class.new(integration, batch, association).execute
expect(project.reload.has_external_issue_tracker).to eq(true)
+ expect(excluded_project.reload.has_external_issue_tracker).to eq(false)
end
context 'with an external wiki integration' do
- let(:integration) do
- ExternalWikiService.create!(
- instance: true,
- active: true,
- push_events: false,
- external_wiki_url: 'http://external-wiki-url.com'
- )
+ before do
+ integration.update!(category: 'common', type: 'ExternalWikiService')
end
it 'updates projects#has_external_wiki for external wiki services' do
described_class.new(integration, batch, association).execute
expect(project.reload.has_external_wiki).to eq(true)
+ expect(excluded_project.reload.has_external_wiki).to eq(false)
end
end
end
- context 'with an instance-level integration' do
+ shared_examples 'does not update project callbacks' do
+ it 'does not update projects#has_external_issue_tracker for issue tracker services' do
+ described_class.new(integration, batch, association).execute
+
+ expect(project.reload.has_external_issue_tracker).to eq(false)
+ end
+
+ context 'with an inactive external wiki integration' do
+ let(:integration) { create(:external_wiki_service, :instance, active: false) }
+
+ it 'does not update projects#has_external_wiki for external wiki services' do
+ described_class.new(integration, batch, association).execute
+
+ expect(project.reload.has_external_wiki).to eq(false)
+ end
+ end
+ end
+
+ context 'passing an instance-level integration' do
let(:integration) { instance_integration }
+ let(:inherit_from_id) { integration.id }
context 'with a project association' do
let!(:project) { create(:project) }
let(:created_integration) { project.jira_service }
- let(:batch) { Project.all }
+ let(:batch) { Project.where(id: project.id) }
let(:association) { 'project' }
it_behaves_like 'creates integration from batch ids'
it_behaves_like 'updates inherit_from_id'
- it_behaves_like 'runs project callbacks'
+ it_behaves_like 'updates project callbacks'
+
+ context 'when integration is not active' do
+ before do
+ integration.update!(active: false)
+ end
+
+ it_behaves_like 'does not update project callbacks'
+ end
end
context 'with a group association' do
let!(:group) { create(:group) }
let(:created_integration) { Service.find_by(group: group) }
- let(:batch) { Group.all }
+ let(:batch) { Group.where(id: group.id) }
+ let(:association) { 'group' }
+
+ it_behaves_like 'creates integration from batch ids'
+ it_behaves_like 'updates inherit_from_id'
+ end
+ end
+
+ context 'passing a group integration' do
+ let_it_be(:group) { create(:group) }
+
+ context 'with a project association' do
+ let!(:project) { create(:project, group: group) }
+ let(:integration) { create(:jira_service, group: group, project: nil) }
+ let(:created_integration) { project.jira_service }
+ let(:batch) { Project.where(id: Project.minimum(:id)..Project.maximum(:id)).without_integration(integration).in_namespace(integration.group.self_and_descendants) }
+ let(:association) { 'project' }
+ let(:inherit_from_id) { integration.id }
+
+ it_behaves_like 'creates integration from batch ids'
+ it_behaves_like 'updates inherit_from_id'
+ it_behaves_like 'updates project callbacks'
+ end
+
+ context 'with a group association' do
+ let!(:subgroup) { create(:group, parent: group) }
+ let(:integration) { create(:jira_service, group: group, project: nil, inherit_from_id: instance_integration.id) }
+ let(:created_integration) { Service.find_by(group: subgroup) }
+ let(:batch) { Group.where(id: subgroup.id) }
let(:association) { 'group' }
+ let(:inherit_from_id) { instance_integration.id }
it_behaves_like 'creates integration from batch ids'
it_behaves_like 'updates inherit_from_id'
end
end
- context 'with a template integration' do
+ context 'passing a template integration' do
let(:integration) { template_integration }
context 'with a project association' do
let!(:project) { create(:project) }
let(:created_integration) { project.jira_service }
- let(:batch) { Project.all }
+ let(:batch) { Project.where(id: project.id) }
let(:association) { 'project' }
+ let(:inherit_from_id) { integration.id }
it_behaves_like 'creates integration from batch ids'
- it_behaves_like 'runs project callbacks'
+ it_behaves_like 'updates project callbacks'
end
end
end
diff --git a/spec/services/bulk_import_service_spec.rb b/spec/services/bulk_import_service_spec.rb
new file mode 100644
index 00000000000..e4a50b9d523
--- /dev/null
+++ b/spec/services/bulk_import_service_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImportService do
+ let(:user) { create(:user) }
+ let(:credentials) { { url: 'http://gitlab.example', access_token: 'token' } }
+ let(:params) do
+ [
+ {
+ source_type: 'group_entity',
+ source_full_path: 'full/path/to/group1',
+ destination_name: 'destination group 1',
+ destination_namespace: 'full/path/to/destination1'
+ },
+ {
+ source_type: 'group_entity',
+ source_full_path: 'full/path/to/group2',
+ destination_name: 'destination group 2',
+ destination_namespace: 'full/path/to/destination2'
+ },
+ {
+ source_type: 'project_entity',
+ source_full_path: 'full/path/to/project1',
+ destination_name: 'destination project 1',
+ destination_namespace: 'full/path/to/destination1'
+ }
+ ]
+ end
+
+ subject { described_class.new(user, params, credentials) }
+
+ describe '#execute' do
+ it 'creates bulk import' do
+ expect { subject.execute }.to change { BulkImport.count }.by(1)
+ end
+
+ it 'creates bulk import entities' do
+ expect { subject.execute }.to change { BulkImports::Entity.count }.by(3)
+ end
+
+ it 'creates bulk import configuration' do
+ expect { subject.execute }.to change { BulkImports::Configuration.count }.by(1)
+ end
+
+ it 'enqueues BulkImportWorker' do
+ expect(BulkImportWorker).to receive(:perform_async)
+
+ subject.execute
+ end
+ end
+end
diff --git a/spec/services/bulk_update_integration_service_spec.rb b/spec/services/bulk_update_integration_service_spec.rb
index 2f0bfd31600..e7944f07bb7 100644
--- a/spec/services/bulk_update_integration_service_spec.rb
+++ b/spec/services/bulk_update_integration_service_spec.rb
@@ -5,52 +5,74 @@ require 'spec_helper'
RSpec.describe BulkUpdateIntegrationService do
include JiraServiceHelper
- before do
+ before_all do
stub_jira_service_test
end
let(:excluded_attributes) { %w[id project_id group_id inherit_from_id instance template created_at updated_at] }
- let!(:instance_integration) do
+ let(:batch) do
+ Service.inherited_descendants_from_self_or_ancestors_from(subgroup_integration).where(id: group_integration.id..integration.id)
+ end
+
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let_it_be(:group_integration) do
+ JiraService.create!(
+ group: group,
+ url: 'http://group.jira.com'
+ )
+ end
+
+ let_it_be(:subgroup_integration) do
JiraService.create!(
- instance: true,
- active: true,
- push_events: true,
- url: 'http://update-jira.instance.com',
- username: 'user',
- password: 'secret'
+ inherit_from_id: group_integration.id,
+ group: subgroup,
+ url: 'http://subgroup.jira.com',
+ push_events: true
)
end
- let!(:integration) do
+ let_it_be(:excluded_integration) do
JiraService.create!(
- project: create(:project),
- inherit_from_id: instance_integration.id,
- instance: false,
- active: true,
- push_events: false,
- url: 'http://jira.instance.com',
- username: 'user',
- password: 'secret'
+ group: create(:group),
+ url: 'http://another.jira.com',
+ push_events: false
+ )
+ end
+
+ let_it_be(:integration) do
+ JiraService.create!(
+ project: create(:project, group: subgroup),
+ inherit_from_id: subgroup_integration.id,
+ url: 'http://project.jira.com',
+ push_events: false
)
end
context 'with inherited integration' do
- it 'updates the integration' do
- described_class.new(instance_integration, Service.inherit_from_id(instance_integration.id)).execute
+ it 'updates the integration', :aggregate_failures do
+ described_class.new(subgroup_integration, batch).execute
+
+ expect(integration.reload.inherit_from_id).to eq(group_integration.id)
+ expect(integration.reload.attributes.except(*excluded_attributes))
+ .to eq(subgroup_integration.attributes.except(*excluded_attributes))
- expect(integration.reload.inherit_from_id).to eq(instance_integration.id)
- expect(integration.attributes.except(*excluded_attributes))
- .to eq(instance_integration.attributes.except(*excluded_attributes))
+ expect(excluded_integration.reload.inherit_from_id).not_to eq(group_integration.id)
+ expect(excluded_integration.reload.attributes.except(*excluded_attributes))
+ .not_to eq(subgroup_integration.attributes.except(*excluded_attributes))
end
context 'with integration with data fields' do
let(:excluded_attributes) { %w[id service_id created_at updated_at] }
- it 'updates the data fields from the integration' do
- described_class.new(instance_integration, Service.inherit_from_id(instance_integration.id)).execute
+ it 'updates the data fields from the integration', :aggregate_failures do
+ described_class.new(subgroup_integration, batch).execute
+
+ expect(integration.data_fields.attributes.except(*excluded_attributes))
+ .to eq(subgroup_integration.data_fields.attributes.except(*excluded_attributes))
- expect(integration.reload.data_fields.attributes.except(*excluded_attributes))
- .to eq(instance_integration.data_fields.attributes.except(*excluded_attributes))
+ expect(integration.data_fields.attributes.except(*excluded_attributes))
+ .not_to eq(excluded_integration.data_fields.attributes.except(*excluded_attributes))
end
end
end
diff --git a/spec/services/ci/append_build_trace_service_spec.rb b/spec/services/ci/append_build_trace_service_spec.rb
new file mode 100644
index 00000000000..a0a7f594881
--- /dev/null
+++ b/spec/services/ci/append_build_trace_service_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::AppendBuildTraceService do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:build) { create(:ci_build, :running, pipeline: pipeline) }
+
+ before do
+ stub_feature_flags(ci_enable_live_trace: true)
+ end
+
+ context 'build trace append is successful' do
+ it 'returns a correct stream size and status code' do
+ stream_size = 192.kilobytes
+ body_data = 'x' * stream_size
+ content_range = "0-#{stream_size}"
+
+ result = described_class
+ .new(build, content_range: content_range)
+ .execute(body_data)
+
+ expect(result.status).to eq 202
+ expect(result.stream_size).to eq stream_size
+ expect(build.trace_chunks.count).to eq 2
+ end
+ end
+
+ context 'when could not correctly append to a trace' do
+ it 'responds with content range violation and data stored' do
+ allow(build).to receive_message_chain(:trace, :append) { 16 }
+
+ result = described_class
+ .new(build, content_range: '0-128')
+ .execute('x' * 128)
+
+ expect(result.status).to eq 416
+ expect(result.stream_size).to eq 16
+ end
+
+ it 'logs exception if build has live trace' do
+ build.trace.append('abcd', 0)
+
+ expect(::Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(anything, hash_including(chunk_index: 0, chunk_store: 'redis'))
+
+ result = described_class
+ .new(build, content_range: '0-128')
+ .execute('x' * 128)
+
+ expect(result.status).to eq 416
+ expect(result.stream_size).to eq 4
+ end
+ end
+end
diff --git a/spec/services/ci/build_report_result_service_spec.rb b/spec/services/ci/build_report_result_service_spec.rb
index 134b662a72a..7c2702af086 100644
--- a/spec/services/ci/build_report_result_service_spec.rb
+++ b/spec/services/ci/build_report_result_service_spec.rb
@@ -26,18 +26,6 @@ RSpec.describe Ci::BuildReportResultService do
expect(unique_test_cases_parsed).to eq(4)
end
- context 'when feature flag for tracking is disabled' do
- before do
- stub_feature_flags(track_unique_test_cases_parsed: false)
- end
-
- it 'creates the report but does not track the event' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
- expect(build_report_result.tests_name).to eq("test")
- expect(Ci::BuildReportResult.count).to eq(1)
- end
- end
-
context 'when data has already been persisted' do
it 'raises an error and do not persist the same data twice' do
expect { 2.times { described_class.new.execute(build) } }.to raise_error(ActiveRecord::RecordNotUnique)
diff --git a/spec/services/ci/compare_test_reports_service_spec.rb b/spec/services/ci/compare_test_reports_service_spec.rb
index 7d31db73b6a..377c801b008 100644
--- a/spec/services/ci/compare_test_reports_service_spec.rb
+++ b/spec/services/ci/compare_test_reports_service_spec.rb
@@ -7,15 +7,15 @@ RSpec.describe Ci::CompareTestReportsService do
let(:project) { create(:project, :repository) }
describe '#execute' do
- subject { service.execute(base_pipeline, head_pipeline) }
+ subject(:comparison) { service.execute(base_pipeline, head_pipeline) }
context 'when head pipeline has test reports' do
let!(:base_pipeline) { nil }
let!(:head_pipeline) { create(:ci_pipeline, :with_test_reports, project: project) }
it 'returns status and data' do
- expect(subject[:status]).to eq(:parsed)
- expect(subject[:data]).to match_schema('entities/test_reports_comparer')
+ expect(comparison[:status]).to eq(:parsed)
+ expect(comparison[:data]).to match_schema('entities/test_reports_comparer')
end
end
@@ -24,8 +24,8 @@ RSpec.describe Ci::CompareTestReportsService do
let!(:head_pipeline) { create(:ci_pipeline, :with_test_reports, project: project) }
it 'returns status and data' do
- expect(subject[:status]).to eq(:parsed)
- expect(subject[:data]).to match_schema('entities/test_reports_comparer')
+ expect(comparison[:status]).to eq(:parsed)
+ expect(comparison[:data]).to match_schema('entities/test_reports_comparer')
end
end
@@ -39,9 +39,44 @@ RSpec.describe Ci::CompareTestReportsService do
end
it 'returns a parsed TestReports success status and failure on the individual suite' do
- expect(subject[:status]).to eq(:parsed)
- expect(subject.dig(:data, 'status')).to eq('success')
- expect(subject.dig(:data, 'suites', 0, 'status') ).to eq('error')
+ expect(comparison[:status]).to eq(:parsed)
+ expect(comparison.dig(:data, 'status')).to eq('success')
+ expect(comparison.dig(:data, 'suites', 0, 'status') ).to eq('error')
+ end
+ end
+
+ context 'test failure history' do
+ let!(:base_pipeline) { nil }
+ let!(:head_pipeline) { create(:ci_pipeline, :with_test_reports_with_three_failures, project: project) }
+
+ let(:new_failures) do
+ comparison.dig(:data, 'suites', 0, 'new_failures')
+ end
+
+ let(:recent_failures_per_test_case) do
+ new_failures.map { |f| f['recent_failures'] }
+ end
+
+ # Create test case failure records based on the head pipeline build
+ before do
+ stub_const("Gitlab::Ci::Reports::TestSuiteComparer::DEFAULT_MAX_TESTS", 2)
+ stub_const("Gitlab::Ci::Reports::TestSuiteComparer::DEFAULT_MIN_TESTS", 1)
+
+ build = head_pipeline.builds.last
+ build.update_column(:finished_at, 1.day.ago) # Just to be sure we are included in the report window
+
+ # The JUnit fixture for the given build has 3 failures.
+ # This service will create 1 test case failure record for each.
+ Ci::TestCasesService.new.execute(build)
+ end
+
+ it 'loads recent failures on limited test cases to avoid building up a huge DB query', :aggregate_failures do
+ expect(comparison[:data]).to match_schema('entities/test_reports_comparer')
+ expect(recent_failures_per_test_case).to eq([
+ { 'count' => 1, 'base_branch' => 'master' },
+ { 'count' => 1, 'base_branch' => 'master' }
+ ])
+ expect(new_failures.count).to eq(2)
end
end
end
diff --git a/spec/services/ci/create_downstream_pipeline_service_spec.rb b/spec/services/ci/create_downstream_pipeline_service_spec.rb
index 0cc380439a7..03cea4074bf 100644
--- a/spec/services/ci/create_downstream_pipeline_service_spec.rb
+++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb
@@ -581,5 +581,40 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do
)
end
end
+
+ context 'when downstream pipeline has workflow rule' do
+ before do
+ stub_ci_pipeline_yaml_file(config)
+ end
+
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - if: $my_var
+
+ regular-job:
+ script: 'echo Hello, World!'
+ EOY
+ end
+
+ context 'when passing the required variable' do
+ before do
+ bridge.yaml_variables = [{ key: 'my_var', value: 'var', public: true }]
+ end
+
+ it 'creates the pipeline' do
+ expect { service.execute(bridge) }.to change(downstream_project.ci_pipelines, :count).by(1)
+
+ expect(bridge.reload).to be_success
+ end
+ end
+
+ context 'when not passing the required variable' do
+ it 'does not create the pipeline' do
+ expect { service.execute(bridge) }.not_to change(downstream_project.ci_pipelines, :count)
+ end
+ end
+ end
end
end
diff --git a/spec/services/ci/create_pipeline_service/cache_spec.rb b/spec/services/ci/create_pipeline_service/cache_spec.rb
index 1438c2e4aa0..5f74c2f1cef 100644
--- a/spec/services/ci/create_pipeline_service/cache_spec.rb
+++ b/spec/services/ci/create_pipeline_service/cache_spec.rb
@@ -4,13 +4,13 @@ require 'spec_helper'
RSpec.describe Ci::CreatePipelineService do
context 'cache' do
- let(:user) { create(:admin) }
+ let(:project) { create(:project, :custom_repo, files: files) }
+ let(:user) { project.owner }
let(:ref) { 'refs/heads/master' }
let(:source) { :push }
let(:service) { described_class.new(project, user, { ref: ref }) }
let(:pipeline) { service.execute(source) }
let(:job) { pipeline.builds.find_by(name: 'job') }
- let(:project) { create(:project, :custom_repo, files: files) }
before do
stub_ci_pipeline_yaml_file(config)
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 b5b3832ac00..9ccf289df7c 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
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe Ci::CreatePipelineService do
describe 'creation errors and warnings' do
- let_it_be(:user) { create(:admin) }
- let_it_be(:project) { create(:project, :repository, creator: user) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
let(:ref) { 'refs/heads/master' }
let(:source) { :push }
diff --git a/spec/services/ci/create_pipeline_service/custom_config_content_spec.rb b/spec/services/ci/create_pipeline_service/custom_config_content_spec.rb
index 122870e0f3a..6320a16d646 100644
--- a/spec/services/ci/create_pipeline_service/custom_config_content_spec.rb
+++ b/spec/services/ci/create_pipeline_service/custom_config_content_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
RSpec.describe Ci::CreatePipelineService do
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { create(:admin) }
+ let_it_be(:user) { project.owner }
let(:ref) { 'refs/heads/master' }
let(:service) { described_class.new(project, user, { ref: ref }) }
diff --git a/spec/services/ci/create_pipeline_service/dry_run_spec.rb b/spec/services/ci/create_pipeline_service/dry_run_spec.rb
index 93378df80f0..60c56ed0f67 100644
--- a/spec/services/ci/create_pipeline_service/dry_run_spec.rb
+++ b/spec/services/ci/create_pipeline_service/dry_run_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Ci::CreatePipelineService do
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { create(:admin) }
+ let_it_be(:user) { project.owner }
let(:ref) { 'refs/heads/master' }
let(:service) { described_class.new(project, user, { ref: ref }) }
diff --git a/spec/services/ci/create_pipeline_service/needs_spec.rb b/spec/services/ci/create_pipeline_service/needs_spec.rb
index 915dc46d664..512091035a2 100644
--- a/spec/services/ci/create_pipeline_service/needs_spec.rb
+++ b/spec/services/ci/create_pipeline_service/needs_spec.rb
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe Ci::CreatePipelineService do
context 'needs' do
- let_it_be(:user) { create(:admin) }
- let_it_be(:project) { create(:project, :repository, creator: user) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
let(:ref) { 'refs/heads/master' }
let(:source) { :push }
@@ -14,6 +14,7 @@ RSpec.describe Ci::CreatePipelineService do
before do
stub_ci_pipeline_yaml_file(config)
+ project.add_developer(user)
end
context 'with a valid config' do
diff --git a/spec/services/ci/create_pipeline_service/parameter_content_spec.rb b/spec/services/ci/create_pipeline_service/parameter_content_spec.rb
index f656ad52ac8..90b8baa23a7 100644
--- a/spec/services/ci/create_pipeline_service/parameter_content_spec.rb
+++ b/spec/services/ci/create_pipeline_service/parameter_content_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Ci::CreatePipelineService do
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { create(:admin) }
+ let_it_be(:user) { project.owner }
let(:service) { described_class.new(project, user, { ref: 'refs/heads/master' }) }
let(:content) do
<<~EOY
diff --git a/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb b/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
index fb6cdf55be3..8df9b0c3e60 100644
--- a/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
+++ b/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
@@ -279,6 +279,40 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
end
end
end
+
+ context 'when specifying multiple files' do
+ let(:config) do
+ <<~YAML
+ test:
+ script: rspec
+ deploy:
+ variables:
+ CROSS: downstream
+ stage: deploy
+ trigger:
+ include:
+ - project: my-namespace/my-project
+ file:
+ - 'path/to/child1.yml'
+ - 'path/to/child2.yml'
+ YAML
+ end
+
+ it_behaves_like 'successful creation' do
+ let(:expected_bridge_options) do
+ {
+ 'trigger' => {
+ 'include' => [
+ {
+ 'file' => ["path/to/child1.yml", "path/to/child2.yml"],
+ 'project' => 'my-namespace/my-project'
+ }
+ ]
+ }
+ }
+ end
+ end
+ end
end
end
diff --git a/spec/services/ci/create_pipeline_service/pre_post_stages_spec.rb b/spec/services/ci/create_pipeline_service/pre_post_stages_spec.rb
index 00a2dd74968..c84d9a53973 100644
--- a/spec/services/ci/create_pipeline_service/pre_post_stages_spec.rb
+++ b/spec/services/ci/create_pipeline_service/pre_post_stages_spec.rb
@@ -3,8 +3,8 @@ require 'spec_helper'
RSpec.describe Ci::CreatePipelineService do
describe '.pre/.post stages' do
- let_it_be(:user) { create(:admin) }
- let_it_be(:project) { create(:project, :repository, creator: user) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
let(:source) { :push }
let(:service) { described_class.new(project, user, { ref: ref }) }
diff --git a/spec/services/ci/create_pipeline_service/rules_spec.rb b/spec/services/ci/create_pipeline_service/rules_spec.rb
index 1a1fa6e8f5d..a0ff2fff0ef 100644
--- a/spec/services/ci/create_pipeline_service/rules_spec.rb
+++ b/spec/services/ci/create_pipeline_service/rules_spec.rb
@@ -2,10 +2,10 @@
require 'spec_helper'
RSpec.describe Ci::CreatePipelineService do
- let(:user) { create(:admin) }
+ let(:project) { create(:project, :repository) }
+ let(:user) { project.owner }
let(:ref) { 'refs/heads/master' }
let(:source) { :push }
- let(:project) { create(:project, :repository) }
let(:service) { described_class.new(project, user, { ref: ref }) }
let(:pipeline) { service.execute(source) }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index c28c3449485..f9015752644 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Ci::CreatePipelineService do
include ProjectForksHelper
let_it_be(:project, reload: true) { create(:project, :repository) }
- let(:user) { create(:admin) }
+ let_it_be(:user, reload: true) { project.owner }
let(:ref_name) { 'refs/heads/master' }
before do
@@ -41,7 +41,9 @@ RSpec.describe Ci::CreatePipelineService do
save_on_errors: save_on_errors,
trigger_request: trigger_request,
merge_request: merge_request,
- external_pull_request: external_pull_request)
+ external_pull_request: external_pull_request) do |pipeline|
+ yield(pipeline) if block_given?
+ end
end
# rubocop:enable Metrics/ParameterLists
@@ -153,6 +155,11 @@ RSpec.describe Ci::CreatePipelineService do
context 'when merge request target project is different from source project' do
let!(:project) { fork_project(target_project, nil, repository: true) }
let!(:target_project) { create(:project, :repository) }
+ let!(:user) { create(:user) }
+
+ before do
+ project.add_developer(user)
+ end
it 'updates head pipeline for merge request', :sidekiq_might_not_need_inline do
merge_request = create(:merge_request, source_branch: 'feature',
@@ -1440,6 +1447,11 @@ RSpec.describe Ci::CreatePipelineService do
let(:ref_name) { 'refs/heads/feature' }
let!(:project) { fork_project(target_project, nil, repository: true) }
let!(:target_project) { create(:project, :repository) }
+ let!(:user) { create(:user) }
+
+ before do
+ project.add_developer(user)
+ end
it 'creates a legacy detached merge request pipeline in the forked project', :sidekiq_might_not_need_inline do
expect(pipeline).to be_persisted
@@ -1858,6 +1870,12 @@ RSpec.describe Ci::CreatePipelineService do
- changes:
- README.md
allow_failure: true
+
+ README:
+ script: "I use variables for changes!"
+ rules:
+ - changes:
+ - $CI_JOB_NAME*
EOY
end
@@ -1867,10 +1885,10 @@ RSpec.describe Ci::CreatePipelineService do
.to receive(:modified_paths).and_return(%w[README.md])
end
- it 'creates two jobs' do
+ it 'creates five jobs' do
expect(pipeline).to be_persisted
expect(build_names)
- .to contain_exactly('regular-job', 'rules-job', 'delayed-job', 'negligible-job')
+ .to contain_exactly('regular-job', 'rules-job', 'delayed-job', 'negligible-job', 'README')
end
it 'sets when: for all jobs' do
@@ -2274,6 +2292,207 @@ RSpec.describe Ci::CreatePipelineService do
end
end
end
+
+ context 'with workflow rules with persisted variables' do
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - if: $CI_COMMIT_REF_NAME == "master"
+
+ regular-job:
+ script: 'echo Hello, World!'
+ EOY
+ end
+
+ context 'with matches' do
+ it 'creates a pipeline' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('regular-job')
+ end
+ end
+
+ context 'with no matches' do
+ let(:ref_name) { 'refs/heads/feature' }
+
+ it 'does not create a pipeline' do
+ expect(pipeline).not_to be_persisted
+ end
+ end
+ end
+
+ context 'with workflow rules with pipeline variables' do
+ let(:pipeline) do
+ execute_service(variables_attributes: variables_attributes)
+ end
+
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - if: $SOME_VARIABLE
+
+ regular-job:
+ script: 'echo Hello, World!'
+ EOY
+ end
+
+ context 'with matches' do
+ let(:variables_attributes) do
+ [{ key: 'SOME_VARIABLE', secret_value: 'SOME_VAR' }]
+ end
+
+ it 'creates a pipeline' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('regular-job')
+ end
+ end
+
+ context 'with no matches' do
+ let(:variables_attributes) { {} }
+
+ it 'does not create a pipeline' do
+ expect(pipeline).not_to be_persisted
+ end
+ end
+ end
+
+ context 'with workflow rules with trigger variables' do
+ let(:pipeline) do
+ execute_service do |pipeline|
+ pipeline.variables.build(variables)
+ end
+ end
+
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - if: $SOME_VARIABLE
+
+ regular-job:
+ script: 'echo Hello, World!'
+ EOY
+ end
+
+ context 'with matches' do
+ let(:variables) do
+ [{ key: 'SOME_VARIABLE', secret_value: 'SOME_VAR' }]
+ end
+
+ it 'creates a pipeline' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('regular-job')
+ end
+
+ context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
+ before do
+ stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
+ end
+
+ it 'does not a pipeline' do
+ expect(pipeline).not_to be_persisted
+ end
+ end
+
+ context 'when a job requires the same variable' do
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - if: $SOME_VARIABLE
+
+ build:
+ stage: build
+ script: 'echo build'
+ rules:
+ - if: $SOME_VARIABLE
+
+ test1:
+ stage: test
+ script: 'echo test1'
+ needs: [build]
+
+ test2:
+ stage: test
+ script: 'echo test2'
+ EOY
+ end
+
+ it 'creates a pipeline' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('build', 'test1', 'test2')
+ end
+
+ context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
+ before do
+ stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
+ end
+
+ it 'does not a pipeline' do
+ expect(pipeline).not_to be_persisted
+ end
+ end
+ end
+ end
+
+ context 'with no matches' do
+ let(:variables) { {} }
+
+ it 'does not create a pipeline' do
+ expect(pipeline).not_to be_persisted
+ end
+
+ context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
+ before do
+ stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
+ end
+
+ it 'does not create a pipeline' do
+ expect(pipeline).not_to be_persisted
+ end
+ end
+
+ context 'when a job requires the same variable' do
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - if: $SOME_VARIABLE
+
+ build:
+ stage: build
+ script: 'echo build'
+ rules:
+ - if: $SOME_VARIABLE
+
+ test1:
+ stage: test
+ script: 'echo test1'
+ needs: [build]
+
+ test2:
+ stage: test
+ script: 'echo test2'
+ EOY
+ end
+
+ it 'does not create a pipeline' do
+ expect(pipeline).not_to be_persisted
+ end
+
+ context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
+ before do
+ stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
+ end
+
+ it 'does not create a pipeline' do
+ expect(pipeline).not_to be_persisted
+ end
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/services/ci/daily_build_group_report_result_service_spec.rb b/spec/services/ci/daily_build_group_report_result_service_spec.rb
index f196afb05e8..e54f10cc4f4 100644
--- a/spec/services/ci/daily_build_group_report_result_service_spec.rb
+++ b/spec/services/ci/daily_build_group_report_result_service_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Ci::DailyBuildGroupReportResultService, '#execute' do
let!(:rspec_job) { create(:ci_build, pipeline: pipeline, name: '3/3 rspec', coverage: 80) }
let!(:karma_job) { create(:ci_build, pipeline: pipeline, name: '2/2 karma', coverage: 90) }
let!(:extra_job) { create(:ci_build, pipeline: pipeline, name: 'extra', coverage: nil) }
+ let(:coverages) { Ci::DailyBuildGroupReportResult.all }
it 'creates daily code coverage record for each job in the pipeline that has coverage value' do
described_class.new.execute(pipeline)
@@ -158,4 +159,30 @@ RSpec.describe Ci::DailyBuildGroupReportResultService, '#execute' do
expect { described_class.new.execute(new_pipeline) }.not_to raise_error
end
end
+
+ context 'when pipeline ref_path is the project default branch' do
+ let(:default_branch) { 'master' }
+
+ before do
+ allow(pipeline.project).to receive(:default_branch).and_return(default_branch)
+ end
+
+ it 'sets default branch to true' do
+ described_class.new.execute(pipeline)
+
+ coverages.each do |coverage|
+ expect(coverage.default_branch).to be_truthy
+ end
+ end
+ end
+
+ context 'when pipeline ref_path is not the project default branch' do
+ it 'sets default branch to false' do
+ described_class.new.execute(pipeline)
+
+ coverages.each do |coverage|
+ expect(coverage.default_branch).to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb b/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb
index 3d5329811ad..c8d426ee657 100644
--- a/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb
+++ b/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb
@@ -5,26 +5,85 @@ require 'spec_helper'
RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared_state do
include ExclusiveLeaseHelpers
+ let(:service) { described_class.new }
+
describe '.execute' do
subject { service.execute }
- let(:service) { described_class.new }
-
- let_it_be(:artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
+ let_it_be(:artifact, reload: true) do
+ create(:ci_job_artifact, expire_at: 1.day.ago)
+ end
before(:all) do
artifact.job.pipeline.unlocked!
end
context 'when artifact is expired' do
- context 'when artifact is not locked' do
+ context 'with preloaded relationships' do
before do
- artifact.job.pipeline.unlocked!
+ job = create(:ci_build, pipeline: artifact.job.pipeline)
+ create(:ci_job_artifact, :archive, :expired, job: job)
+
+ stub_const('Ci::DestroyExpiredJobArtifactsService::LOOP_LIMIT', 1)
end
- it 'destroys job artifact' do
+ it 'performs the smallest number of queries for job_artifacts' do
+ log = ActiveRecord::QueryRecorder.new { subject }
+
+ # SELECT expired ci_job_artifacts
+ # PRELOAD projects, routes, project_statistics
+ # BEGIN
+ # INSERT into ci_deleted_objects
+ # DELETE loaded ci_job_artifacts
+ # DELETE security_findings -- for EE
+ # COMMIT
+ expect(log.count).to be_within(1).of(8)
+ end
+ end
+
+ context 'when artifact is not locked' do
+ it 'deletes job artifact record' do
expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
end
+
+ context 'when the artifact does not a file attached to it' do
+ it 'does not create deleted objects' do
+ expect(artifact.exists?).to be_falsy # sanity check
+
+ expect { subject }.not_to change { Ci::DeletedObject.count }
+ end
+ end
+
+ context 'when the artifact has a file attached to it' do
+ before do
+ artifact.file = fixture_file_upload(Rails.root.join('spec/fixtures/ci_build_artifacts.zip'), 'application/zip')
+ artifact.save!
+ end
+
+ it 'creates a deleted object' do
+ expect { subject }.to change { Ci::DeletedObject.count }.by(1)
+ end
+
+ it 'resets project statistics' do
+ expect(ProjectStatistics).to receive(:increment_statistic).once
+ .with(artifact.project, :build_artifacts_size, -artifact.file.size)
+ .and_call_original
+
+ subject
+ end
+
+ it 'does not remove the files' do
+ expect { subject }.not_to change { artifact.file.exists? }
+ end
+
+ it 'reports metrics for destroyed artifacts' do
+ counter = service.send(:destroyed_artifacts_counter)
+
+ expect(counter).to receive(:increment).with({}, 1).and_call_original
+
+ subject
+ end
+ end
end
context 'when artifact is locked' do
@@ -61,14 +120,34 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
context 'when failed to destroy artifact' do
before do
stub_const('Ci::DestroyExpiredJobArtifactsService::LOOP_LIMIT', 10)
+ end
- allow_any_instance_of(Ci::JobArtifact)
- .to receive(:destroy!)
- .and_raise(ActiveRecord::RecordNotDestroyed)
+ context 'when the import fails' do
+ before do
+ expect(Ci::DeletedObject)
+ .to receive(:bulk_import)
+ .once
+ .and_raise(ActiveRecord::RecordNotDestroyed)
+ end
+
+ it 'raises an exception and stop destroying' do
+ expect { subject }.to raise_error(ActiveRecord::RecordNotDestroyed)
+ .and not_change { Ci::JobArtifact.count }.from(1)
+ end
end
- it 'raises an exception and stop destroying' do
- expect { subject }.to raise_error(ActiveRecord::RecordNotDestroyed)
+ context 'when the delete fails' do
+ before do
+ expect(Ci::JobArtifact)
+ .to receive(:id_in)
+ .once
+ .and_raise(ActiveRecord::RecordNotDestroyed)
+ end
+
+ it 'raises an exception rolls back the insert' do
+ expect { subject }.to raise_error(ActiveRecord::RecordNotDestroyed)
+ .and not_change { Ci::DeletedObject.count }.from(0)
+ end
end
end
@@ -85,7 +164,7 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
context 'when timeout happens' do
before do
stub_const('Ci::DestroyExpiredJobArtifactsService::LOOP_TIMEOUT', 1.second)
- allow_any_instance_of(described_class).to receive(:destroy_batch) { true }
+ allow_any_instance_of(described_class).to receive(:destroy_artifacts_batch) { true }
end
it 'returns false and does not continue destroying' do
@@ -176,4 +255,16 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
end
end
end
+
+ describe '.destroy_job_artifacts_batch' do
+ it 'returns a falsy value without artifacts' do
+ expect(service.send(:destroy_job_artifacts_batch)).to be_falsy
+ end
+ end
+
+ describe '.destroy_pipeline_artifacts_batch' do
+ it 'returns a falsy value without artifacts' do
+ expect(service.send(:destroy_pipeline_artifacts_batch)).to be_falsy
+ end
+ end
end
diff --git a/spec/services/ci/list_config_variables_service_spec.rb b/spec/services/ci/list_config_variables_service_spec.rb
index 5cc0481768b..95c98c2b5ef 100644
--- a/spec/services/ci/list_config_variables_service_spec.rb
+++ b/spec/services/ci/list_config_variables_service_spec.rb
@@ -3,8 +3,9 @@
require 'spec_helper'
RSpec.describe Ci::ListConfigVariablesService do
- let_it_be(:project) { create(:project, :repository) }
- let(:service) { described_class.new(project) }
+ let(:project) { create(:project, :repository) }
+ let(:user) { project.creator }
+ let(:service) { described_class.new(project, user) }
let(:result) { YAML.dump(ci_config) }
subject { service.execute(sha) }
@@ -38,6 +39,40 @@ RSpec.describe Ci::ListConfigVariablesService do
end
end
+ context 'when config has includes' do
+ let(:sha) { 'master' }
+ let(:ci_config) do
+ {
+ include: [{ local: 'other_file.yml' }],
+ variables: {
+ KEY1: { value: 'val 1', description: 'description 1' }
+ },
+ test: {
+ stage: 'test',
+ script: 'echo'
+ }
+ }
+ end
+
+ before do
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository).to receive(:blob_data_at).with(sha, 'other_file.yml') do
+ <<~HEREDOC
+ variables:
+ KEY2:
+ value: 'val 2'
+ description: 'description 2'
+ HEREDOC
+ end
+ end
+ end
+
+ it 'returns variable list' do
+ expect(subject['KEY1']).to eq({ value: 'val 1', description: 'description 1' })
+ expect(subject['KEY2']).to eq({ value: 'val 2', description: 'description 2' })
+ end
+ end
+
context 'when sending an invalid sha' do
let(:sha) { 'invalid-sha' }
let(:ci_config) { nil }
diff --git a/spec/services/ci/test_cases_service_spec.rb b/spec/services/ci/test_cases_service_spec.rb
new file mode 100644
index 00000000000..b61d308640f
--- /dev/null
+++ b/spec/services/ci/test_cases_service_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::TestCasesService, :aggregate_failures do
+ describe '#execute' do
+ subject(:execute_service) { described_class.new.execute(build) }
+
+ context 'when build has test reports' do
+ let(:build) { create(:ci_build, :success, :test_reports) } # The test report has 2 test case failures
+
+ it 'creates test case failures records' do
+ execute_service
+
+ expect(Ci::TestCase.count).to eq(2)
+ expect(Ci::TestCaseFailure.count).to eq(2)
+ end
+
+ context 'when feature flag for test failure history is disabled' do
+ before do
+ stub_feature_flags(test_failure_history: false)
+ end
+
+ it 'does not persist data' do
+ execute_service
+
+ expect(Ci::TestCase.count).to eq(0)
+ expect(Ci::TestCaseFailure.count).to eq(0)
+ end
+ end
+
+ context 'when build is not for the default branch' do
+ before do
+ build.update_column(:ref, 'new-feature')
+ end
+
+ it 'does not persist data' do
+ execute_service
+
+ expect(Ci::TestCase.count).to eq(0)
+ expect(Ci::TestCaseFailure.count).to eq(0)
+ end
+ end
+
+ context 'when test failure data have already been persisted with the same exact attributes' do
+ before do
+ execute_service
+ end
+
+ it 'does not fail but does not persist new data' do
+ expect { described_class.new.execute(build) }.not_to raise_error
+
+ expect(Ci::TestCase.count).to eq(2)
+ expect(Ci::TestCaseFailure.count).to eq(2)
+ end
+ end
+
+ context 'when test failure data have duplicates within the same payload (happens when the JUnit report has duplicate test case names but have different failures)' do
+ let(:build) { create(:ci_build, :success, :test_reports_with_duplicate_failed_test_names) } # The test report has 2 test case failures but with the same test case keys
+
+ it 'does not fail but does not persist duplicate data' do
+ expect { described_class.new.execute(build) }.not_to raise_error
+
+ expect(Ci::TestCase.count).to eq(1)
+ expect(Ci::TestCaseFailure.count).to eq(1)
+ end
+ end
+
+ context 'when number of failed test cases exceed the limit' do
+ before do
+ stub_const("#{described_class.name}::MAX_TRACKABLE_FAILURES", 1)
+ end
+
+ it 'does not persist data' do
+ execute_service
+
+ expect(Ci::TestCase.count).to eq(0)
+ expect(Ci::TestCaseFailure.count).to eq(0)
+ end
+ end
+ end
+
+ context 'when build has no test reports' do
+ let(:build) { create(:ci_build, :running) }
+
+ it 'does not persist data' do
+ execute_service
+
+ expect(Ci::TestCase.count).to eq(0)
+ expect(Ci::TestCaseFailure.count).to eq(0)
+ end
+ end
+ end
+end
diff --git a/spec/services/clusters/applications/check_installation_progress_service_spec.rb b/spec/services/clusters/applications/check_installation_progress_service_spec.rb
index 13f7cd62002..698804ff6af 100644
--- a/spec/services/clusters/applications/check_installation_progress_service_spec.rb
+++ b/spec/services/clusters/applications/check_installation_progress_service_spec.rb
@@ -161,10 +161,10 @@ RSpec.describe Clusters::Applications::CheckInstallationProgressService, '#execu
expect(application.status_reason).to be_nil
end
- it 'tracks application install' do
- expect(Gitlab::Tracking).to receive(:event).with('cluster:applications', "cluster_application_helm_installed")
-
+ it 'tracks application install', :snowplow do
service.execute
+
+ expect_snowplow_event(category: 'cluster:applications', action: 'cluster_application_helm_installed')
end
end
diff --git a/spec/services/clusters/applications/uninstall_service_spec.rb b/spec/services/clusters/applications/uninstall_service_spec.rb
index 50d7e82c47e..bfe38ba670d 100644
--- a/spec/services/clusters/applications/uninstall_service_spec.rb
+++ b/spec/services/clusters/applications/uninstall_service_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Clusters::Applications::UninstallService, '#execute' do
context 'when there are no errors' do
before do
- expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::DeleteCommand))
+ expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand))
allow(worker_class).to receive(:perform_in).and_return(nil)
end
@@ -36,7 +36,7 @@ RSpec.describe Clusters::Applications::UninstallService, '#execute' do
let(:error) { Kubeclient::HttpError.new(500, 'system failure', nil) }
before do
- expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::DeleteCommand)).and_raise(error)
+ expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand)).and_raise(error)
end
include_examples 'logs kubernetes errors' do
@@ -58,7 +58,7 @@ RSpec.describe Clusters::Applications::UninstallService, '#execute' do
let(:error) { StandardError.new('something bad happened') }
before do
- expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::DeleteCommand)).and_raise(error)
+ expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand)).and_raise(error)
end
include_examples 'logs kubernetes errors' do
diff --git a/spec/services/clusters/aws/authorize_role_service_spec.rb b/spec/services/clusters/aws/authorize_role_service_spec.rb
index 5b47cf0ecde..302bae6e3ff 100644
--- a/spec/services/clusters/aws/authorize_role_service_spec.rb
+++ b/spec/services/clusters/aws/authorize_role_service_spec.rb
@@ -11,14 +11,16 @@ RSpec.describe Clusters::Aws::AuthorizeRoleService do
let(:credentials_service) { instance_double(Clusters::Aws::FetchCredentialsService, execute: credentials) }
let(:role_arn) { 'arn:my-role' }
+ let(:region) { 'region' }
let(:params) do
params = ActionController::Parameters.new({
cluster: {
- role_arn: role_arn
+ role_arn: role_arn,
+ region: region
}
})
- params.require(:cluster).permit(:role_arn)
+ params.require(:cluster).permit(:role_arn, :region)
end
before do
diff --git a/spec/services/clusters/aws/fetch_credentials_service_spec.rb b/spec/services/clusters/aws/fetch_credentials_service_spec.rb
index a0e63d96a5c..361a947f634 100644
--- a/spec/services/clusters/aws/fetch_credentials_service_spec.rb
+++ b/spec/services/clusters/aws/fetch_credentials_service_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Clusters::Aws::FetchCredentialsService do
subject { described_class.new(provision_role, provider: provider).execute }
context 'provision role is configured' do
- let(:provision_role) { create(:aws_role, user: user) }
+ let(:provision_role) { create(:aws_role, user: user, region: 'custom-region') }
before do
stub_application_setting(eks_access_key_id: gitlab_access_key_id)
@@ -53,10 +53,12 @@ RSpec.describe Clusters::Aws::FetchCredentialsService do
context 'provider is not specifed' do
let(:provider) { nil }
- let(:region) { Clusters::Providers::Aws::DEFAULT_REGION }
+ let(:region) { provision_role.region }
let(:session_name) { "gitlab-eks-autofill-user-#{user.id}" }
let(:session_policy) { 'policy-document' }
+ subject { described_class.new(provision_role, provider: provider).execute }
+
before do
allow(File).to receive(:read)
.with(Rails.root.join('vendor', 'aws', 'iam', 'eks_cluster_read_only_policy.json'))
@@ -64,6 +66,13 @@ RSpec.describe Clusters::Aws::FetchCredentialsService do
end
it { is_expected.to eq assumed_role_credentials }
+
+ context 'region is not specifed' do
+ let(:region) { Clusters::Providers::Aws::DEFAULT_REGION }
+ let(:provision_role) { create(:aws_role, user: user, region: nil) }
+
+ it { is_expected.to eq assumed_role_credentials }
+ end
end
end
diff --git a/spec/services/clusters/kubernetes/create_or_update_namespace_service_spec.rb b/spec/services/clusters/kubernetes/create_or_update_namespace_service_spec.rb
index 7e3f1fdb379..90956e7b4ea 100644
--- a/spec/services/clusters/kubernetes/create_or_update_namespace_service_spec.rb
+++ b/spec/services/clusters/kubernetes/create_or_update_namespace_service_spec.rb
@@ -28,6 +28,7 @@ RSpec.describe Clusters::Kubernetes::CreateOrUpdateNamespaceService, '#execute'
stub_kubeclient_get_secret_error(api_url, 'gitlab-token')
stub_kubeclient_create_secret(api_url)
+ stub_kubeclient_delete_role_binding(api_url, "gitlab-#{namespace}", namespace: namespace)
stub_kubeclient_put_role_binding(api_url, "gitlab-#{namespace}", namespace: namespace)
stub_kubeclient_get_namespace(api_url, namespace: namespace)
stub_kubeclient_get_service_account_error(api_url, "#{namespace}-service-account", namespace: namespace)
diff --git a/spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb b/spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb
index 257e2e53733..a4f018aec0c 100644
--- a/spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb
+++ b/spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb
@@ -141,6 +141,7 @@ RSpec.describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do
before do
cluster.platform_kubernetes.rbac!
+ stub_kubeclient_delete_role_binding(api_url, role_binding_name, namespace: namespace)
stub_kubeclient_put_role_binding(api_url, role_binding_name, namespace: namespace)
stub_kubeclient_put_role(api_url, Clusters::Kubernetes::GITLAB_KNATIVE_SERVING_ROLE_NAME, namespace: namespace)
stub_kubeclient_put_role_binding(api_url, Clusters::Kubernetes::GITLAB_KNATIVE_SERVING_ROLE_BINDING_NAME, namespace: namespace)
@@ -160,60 +161,26 @@ RSpec.describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do
it_behaves_like 'creates service account and token'
- context 'kubernetes_cluster_namespace_role_admin FF is enabled' do
- before do
- stub_feature_flags(kubernetes_cluster_namespace_role_admin: true)
- end
-
- it 'creates a namespaced role binding with admin access' do
- subject
-
- expect(WebMock).to have_requested(:put, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings/#{role_binding_name}").with(
- body: hash_including(
- metadata: { name: "gitlab-#{namespace}", namespace: "#{namespace}" },
- roleRef: {
- apiGroup: 'rbac.authorization.k8s.io',
- kind: 'ClusterRole',
- name: 'admin'
- },
- subjects: [
- {
- kind: 'ServiceAccount',
- name: service_account_name,
- namespace: namespace
- }
- ]
- )
- )
- end
- end
+ it 'creates a namespaced role binding with admin access' do
+ subject
- context 'kubernetes_cluster_namespace_role_admin FF is disabled' do
- before do
- stub_feature_flags(kubernetes_cluster_namespace_role_admin: false)
- end
-
- it 'creates a namespaced role binding with edit access' do
- subject
-
- expect(WebMock).to have_requested(:put, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings/#{role_binding_name}").with(
- body: hash_including(
- metadata: { name: "gitlab-#{namespace}", namespace: "#{namespace}" },
- roleRef: {
- apiGroup: 'rbac.authorization.k8s.io',
- kind: 'ClusterRole',
- name: 'edit'
- },
- subjects: [
- {
- kind: 'ServiceAccount',
- name: service_account_name,
- namespace: namespace
- }
- ]
- )
+ expect(WebMock).to have_requested(:put, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings/#{role_binding_name}").with(
+ body: hash_including(
+ metadata: { name: "gitlab-#{namespace}", namespace: "#{namespace}" },
+ roleRef: {
+ apiGroup: 'rbac.authorization.k8s.io',
+ kind: 'ClusterRole',
+ name: 'admin'
+ },
+ subjects: [
+ {
+ kind: 'ServiceAccount',
+ name: service_account_name,
+ namespace: namespace
+ }
+ ]
)
- end
+ )
end
it 'creates a role binding granting crossplane database permissions to the service account' do
diff --git a/spec/services/clusters/update_service_spec.rb b/spec/services/clusters/update_service_spec.rb
index e496ccd5c23..9aead97f41c 100644
--- a/spec/services/clusters/update_service_spec.rb
+++ b/spec/services/clusters/update_service_spec.rb
@@ -197,7 +197,7 @@ RSpec.describe Clusters::UpdateService do
context 'manangement_project is outside of the namespace scope' do
before do
- management_project.update(group: create(:group))
+ management_project.update!(group: create(:group))
end
let(:params) do
@@ -224,7 +224,7 @@ RSpec.describe Clusters::UpdateService do
context 'manangement_project is outside of the namespace scope' do
before do
- management_project.update(group: create(:group))
+ management_project.update!(group: create(:group))
end
let(:params) do
diff --git a/spec/services/container_expiration_policies/cleanup_service_spec.rb b/spec/services/container_expiration_policies/cleanup_service_spec.rb
new file mode 100644
index 00000000000..2da35cfc3fb
--- /dev/null
+++ b/spec/services/container_expiration_policies/cleanup_service_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ContainerExpirationPolicies::CleanupService do
+ let_it_be(:repository, reload: true) { create(:container_repository) }
+ let_it_be(:project) { repository.project }
+
+ let(:service) { described_class.new(repository) }
+
+ describe '#execute' do
+ subject { service.execute }
+
+ context 'with a successful cleanup tags service execution' do
+ let(:cleanup_tags_service_params) { project.container_expiration_policy.policy_params.merge('container_expiration_policy' => true) }
+ let(:cleanup_tags_service) { instance_double(Projects::ContainerRepository::CleanupTagsService) }
+
+ it 'completely clean up the repository' do
+ expect(Projects::ContainerRepository::CleanupTagsService)
+ .to receive(:new).with(project, nil, cleanup_tags_service_params).and_return(cleanup_tags_service)
+ expect(cleanup_tags_service).to receive(:execute).with(repository).and_return(status: :success)
+
+ response = subject
+
+ aggregate_failures "checking the response and container repositories" do
+ expect(response.success?).to eq(true)
+ expect(response.payload).to include(cleanup_status: :finished, container_repository_id: repository.id)
+ expect(ContainerRepository.waiting_for_cleanup.count).to eq(0)
+ expect(repository.reload.cleanup_unscheduled?).to be_truthy
+ expect(repository.expiration_policy_started_at).to eq(nil)
+ end
+ end
+ end
+
+ context 'without a successful cleanup tags service execution' do
+ it 'partially clean up the repository' do
+ expect(Projects::ContainerRepository::CleanupTagsService)
+ .to receive(:new).and_return(double(execute: { status: :error, message: 'timeout' }))
+
+ response = subject
+
+ aggregate_failures "checking the response and container repositories" do
+ expect(response.success?).to eq(true)
+ expect(response.payload).to include(cleanup_status: :unfinished, container_repository_id: repository.id)
+ expect(ContainerRepository.waiting_for_cleanup.count).to eq(1)
+ expect(repository.reload.cleanup_unfinished?).to be_truthy
+ expect(repository.expiration_policy_started_at).not_to eq(nil)
+ end
+ end
+ end
+
+ context 'with no repository' do
+ let(:service) { described_class.new(nil) }
+
+ it 'returns an error response' do
+ response = subject
+
+ expect(response.success?).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/services/container_expiration_policy_service_spec.rb b/spec/services/container_expiration_policy_service_spec.rb
index dfce51d73ad..4294e6b3f06 100644
--- a/spec/services/container_expiration_policy_service_spec.rb
+++ b/spec/services/container_expiration_policy_service_spec.rb
@@ -27,20 +27,5 @@ RSpec.describe ContainerExpirationPolicyService do
expect(container_expiration_policy.next_run_at).to be > Time.zone.now
end
-
- context 'with an invalid container expiration policy' do
- before do
- allow(container_expiration_policy).to receive(:valid?).and_return(false)
- end
-
- it 'disables it' do
- expect(container_expiration_policy).not_to receive(:schedule_next_run!)
- expect(CleanupContainerRepositoryWorker).not_to receive(:perform_async)
-
- expect { subject }
- .to change { container_expiration_policy.reload.enabled }.from(true).to(false)
- .and raise_error(ContainerExpirationPolicyService::InvalidPolicyError)
- end
- end
end
end
diff --git a/spec/services/dependency_proxy/download_blob_service_spec.rb b/spec/services/dependency_proxy/download_blob_service_spec.rb
new file mode 100644
index 00000000000..4b5c6b5bd6a
--- /dev/null
+++ b/spec/services/dependency_proxy/download_blob_service_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe DependencyProxy::DownloadBlobService do
+ include DependencyProxyHelpers
+
+ let(:image) { 'alpine' }
+ let(:token) { Digest::SHA256.hexdigest('123') }
+ let(:blob_sha) { Digest::SHA256.hexdigest('ruby:2.7.0') }
+
+ subject { described_class.new(image, blob_sha, token).execute }
+
+ context 'remote request is successful' do
+ before do
+ stub_blob_download(image, blob_sha)
+ end
+
+ it { expect(subject[:status]).to eq(:success) }
+ it { expect(subject[:file]).to be_a(Tempfile) }
+ it { expect(subject[:file].size).to eq(6) }
+ end
+
+ context 'remote request is not found' do
+ before do
+ stub_blob_download(image, blob_sha, 404)
+ end
+
+ it { expect(subject[:status]).to eq(:error) }
+ it { expect(subject[:http_status]).to eq(404) }
+ it { expect(subject[:message]).to eq('Non-success response code on downloading blob fragment') }
+ end
+
+ context 'net timeout exception' do
+ before do
+ blob_url = DependencyProxy::Registry.blob_url(image, blob_sha)
+
+ stub_full_request(blob_url).to_timeout
+ end
+
+ it { expect(subject[:status]).to eq(:error) }
+ it { expect(subject[:http_status]).to eq(599) }
+ it { expect(subject[:message]).to eq('execution expired') }
+ end
+end
diff --git a/spec/services/dependency_proxy/find_or_create_blob_service_spec.rb b/spec/services/dependency_proxy/find_or_create_blob_service_spec.rb
new file mode 100644
index 00000000000..4ba53d49d38
--- /dev/null
+++ b/spec/services/dependency_proxy/find_or_create_blob_service_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe DependencyProxy::FindOrCreateBlobService do
+ include DependencyProxyHelpers
+
+ let(:blob) { create(:dependency_proxy_blob) }
+ let(:group) { blob.group }
+ let(:image) { 'alpine' }
+ let(:tag) { '3.9' }
+ let(:token) { Digest::SHA256.hexdigest('123') }
+ let(:blob_sha) { '40bd001563085fc35165329ea1ff5c5ecbdbbeef' }
+
+ subject { described_class.new(group, image, token, blob_sha).execute }
+
+ before do
+ stub_registry_auth(image, token)
+ end
+
+ context 'no cache' do
+ before do
+ stub_blob_download(image, blob_sha)
+ end
+
+ it 'downloads blob from remote registry if there is no cached one' do
+ expect(subject[:status]).to eq(:success)
+ expect(subject[:blob]).to be_a(DependencyProxy::Blob)
+ expect(subject[:blob]).to be_persisted
+ end
+ end
+
+ context 'cached blob' do
+ let(:blob_sha) { blob.file_name.sub('.gz', '') }
+
+ it 'uses cached blob instead of downloading one' do
+ expect(subject[:status]).to eq(:success)
+ expect(subject[:blob]).to be_a(DependencyProxy::Blob)
+ expect(subject[:blob]).to eq(blob)
+ end
+ end
+
+ context 'no such blob exists remotely' do
+ before do
+ stub_blob_download(image, blob_sha, 404)
+ end
+
+ it 'returns error message and http status' do
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:message]).to eq('Failed to download the blob')
+ expect(subject[:http_status]).to eq(404)
+ end
+ end
+end
diff --git a/spec/services/dependency_proxy/pull_manifest_service_spec.rb b/spec/services/dependency_proxy/pull_manifest_service_spec.rb
new file mode 100644
index 00000000000..030ed9c001b
--- /dev/null
+++ b/spec/services/dependency_proxy/pull_manifest_service_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe DependencyProxy::PullManifestService do
+ include DependencyProxyHelpers
+
+ let(:image) { 'alpine' }
+ let(:tag) { '3.9' }
+ let(:token) { Digest::SHA256.hexdigest('123') }
+ let(:manifest) { { foo: 'bar' }.to_json }
+
+ subject { described_class.new(image, tag, token).execute }
+
+ context 'remote request is successful' do
+ before do
+ stub_manifest_download(image, tag)
+ end
+
+ it { expect(subject[:status]).to eq(:success) }
+ it { expect(subject[:manifest]).to eq(manifest) }
+ end
+
+ context 'remote request is not found' do
+ before do
+ stub_manifest_download(image, tag, 404, 'Not found')
+ end
+
+ it { expect(subject[:status]).to eq(:error) }
+ it { expect(subject[:http_status]).to eq(404) }
+ it { expect(subject[:message]).to eq('Not found') }
+ end
+
+ context 'net timeout exception' do
+ before do
+ manifest_link = DependencyProxy::Registry.manifest_url(image, tag)
+
+ stub_full_request(manifest_link).to_timeout
+ end
+
+ it { expect(subject[:status]).to eq(:error) }
+ it { expect(subject[:http_status]).to eq(599) }
+ it { expect(subject[:message]).to eq('execution expired') }
+ end
+end
diff --git a/spec/services/dependency_proxy/request_token_service_spec.rb b/spec/services/dependency_proxy/request_token_service_spec.rb
new file mode 100644
index 00000000000..8b3ba783b8d
--- /dev/null
+++ b/spec/services/dependency_proxy/request_token_service_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe DependencyProxy::RequestTokenService do
+ include DependencyProxyHelpers
+
+ let(:image) { 'alpine:3.9' }
+ let(:token) { Digest::SHA256.hexdigest('123') }
+
+ subject { described_class.new(image).execute }
+
+ context 'remote request is successful' do
+ before do
+ stub_registry_auth(image, token)
+ end
+
+ it { expect(subject[:status]).to eq(:success) }
+ it { expect(subject[:token]).to eq(token) }
+ end
+
+ context 'remote request is not found' do
+ before do
+ stub_registry_auth(image, token, 404)
+ end
+
+ it { expect(subject[:status]).to eq(:error) }
+ it { expect(subject[:http_status]).to eq(404) }
+ it { expect(subject[:message]).to eq('Expected 200 response code for an access token') }
+ end
+
+ context 'failed to parse response body' do
+ before do
+ stub_registry_auth(image, token, 200, 'dasd1321: wow')
+ end
+
+ it { expect(subject[:status]).to eq(:error) }
+ it { expect(subject[:http_status]).to eq(500) }
+ it { expect(subject[:message]).to eq('Failed to parse a response body for an access token') }
+ end
+
+ context 'net timeout exception' do
+ before do
+ auth_link = DependencyProxy::Registry.auth_url(image)
+
+ stub_full_request(auth_link, method: :any).to_timeout
+ end
+
+ it { expect(subject[:status]).to eq(:error) }
+ it { expect(subject[:http_status]).to eq(599) }
+ it { expect(subject[:message]).to eq('execution expired') }
+ end
+end
diff --git a/spec/services/deploy_keys/collect_keys_service_spec.rb b/spec/services/deploy_keys/collect_keys_service_spec.rb
deleted file mode 100644
index 3442e5e456a..00000000000
--- a/spec/services/deploy_keys/collect_keys_service_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe DeployKeys::CollectKeysService do
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project, :private) }
-
- subject { DeployKeys::CollectKeysService.new(project, user) }
-
- before do
- project&.add_developer(user)
- end
-
- context 'when no project is passed in' do
- let(:project) { nil }
-
- it 'returns an empty Array' do
- expect(subject.execute).to be_empty
- end
- end
-
- context 'when no user is passed in' do
- let(:user) { nil }
-
- it 'returns an empty Array' do
- expect(subject.execute).to be_empty
- end
- end
-
- context 'when a project is passed in' do
- let_it_be(:deploy_keys_project) { create(:deploy_keys_project, :write_access, project: project) }
- let_it_be(:deploy_key) { deploy_keys_project.deploy_key }
-
- it 'only returns deploy keys with write access' do
- create(:deploy_keys_project, project: project)
-
- expect(subject.execute).to contain_exactly(deploy_key)
- end
-
- it 'returns deploy keys only for this project' do
- other_project = create(:project)
- create(:deploy_keys_project, :write_access, project: other_project)
-
- expect(subject.execute).to contain_exactly(deploy_key)
- end
- end
-
- context 'when the user cannot read the project' do
- before do
- project.members.delete_all
- end
-
- it 'returns an empty Array' do
- expect(subject.execute).to be_empty
- end
- end
-end
diff --git a/spec/services/design_management/copy_design_collection/copy_service_spec.rb b/spec/services/design_management/copy_design_collection/copy_service_spec.rb
index e93e5f13fea..ddbed91815f 100644
--- a/spec/services/design_management/copy_design_collection/copy_service_spec.rb
+++ b/spec/services/design_management/copy_design_collection/copy_service_spec.rb
@@ -68,6 +68,31 @@ RSpec.describe DesignManagement::CopyDesignCollection::CopyService, :clean_gitla
include_examples 'service error', message: 'Target design collection already has designs'
end
+ context 'when target project already has designs' do
+ let!(:issue_x) { create(:issue, project: target_issue.project) }
+ let!(:existing) { create(:design, issue: issue_x, project: target_issue.project) }
+
+ let(:new_designs) do
+ target_issue.reset
+ target_issue.designs.where.not(id: existing.id)
+ end
+
+ it 'sets IIDs for new designs above existing ones' do
+ subject
+
+ expect(new_designs).to all(have_attributes(iid: (be > existing.iid)))
+ end
+
+ it 'does not allow for IID collisions' do
+ subject
+ create(:design, issue: issue_x, project: target_issue.project)
+
+ design_iids = target_issue.project.designs.map(&:id)
+
+ expect(design_iids).to match_array(design_iids.uniq)
+ end
+ end
+
include_examples 'service success'
it 'creates a design repository for the target project' do
@@ -162,9 +187,7 @@ RSpec.describe DesignManagement::CopyDesignCollection::CopyService, :clean_gitla
it 'copies the Git repository data', :aggregate_failures do
subject
- commit_shas = target_repository.commits('master', limit: 99).map(&:id)
-
- expect(commit_shas).to include(*target_issue.design_versions.ordered.pluck(:sha))
+ expect(commits_on_master(limit: 99)).to include(*target_issue.design_versions.ordered.pluck(:sha))
end
it 'creates a master branch if none previously existed' do
@@ -212,9 +235,7 @@ RSpec.describe DesignManagement::CopyDesignCollection::CopyService, :clean_gitla
issue_2 = create(:issue, project: target_issue.project)
create(:design, :with_file, issue: issue_2, project: target_issue.project)
- expect { subject }.not_to change {
- expect(target_repository.commits('master', limit: 10).size).to eq(1)
- }
+ expect { subject }.not_to change { commits_on_master }
end
it 'sets the design collection copy state' do
@@ -223,6 +244,10 @@ RSpec.describe DesignManagement::CopyDesignCollection::CopyService, :clean_gitla
expect(target_issue.design_collection).to be_copy_error
end
end
+
+ def commits_on_master(limit: 10)
+ target_repository.commits('master', limit: limit).map(&:id)
+ end
end
end
end
diff --git a/spec/services/design_management/generate_image_versions_service_spec.rb b/spec/services/design_management/generate_image_versions_service_spec.rb
index 749030af97d..e06b6fbf116 100644
--- a/spec/services/design_management/generate_image_versions_service_spec.rb
+++ b/spec/services/design_management/generate_image_versions_service_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe DesignManagement::GenerateImageVersionsService do
end
it 'logs if the raw image cannot be found' do
- version.designs.first.update(filename: 'foo.png')
+ version.designs.first.update!(filename: 'foo.png')
expect(Gitlab::AppLogger).to receive(:error).with("No design file found for Action: #{action.id}")
diff --git a/spec/services/discussions/resolve_service_spec.rb b/spec/services/discussions/resolve_service_spec.rb
index 5ff0d535b46..42c4ef52741 100644
--- a/spec/services/discussions/resolve_service_spec.rb
+++ b/spec/services/discussions/resolve_service_spec.rb
@@ -40,11 +40,11 @@ RSpec.describe Discussions::ResolveService do
context 'with a project that requires all discussion to be resolved' do
before do
- project.update(only_allow_merge_if_all_discussions_are_resolved: true)
+ project.update!(only_allow_merge_if_all_discussions_are_resolved: true)
end
after do
- project.update(only_allow_merge_if_all_discussions_are_resolved: false)
+ project.update!(only_allow_merge_if_all_discussions_are_resolved: false)
end
let_it_be(:other_discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project).to_discussion }
diff --git a/spec/services/draft_notes/destroy_service_spec.rb b/spec/services/draft_notes/destroy_service_spec.rb
index f725f08f3c7..1f246a56eb3 100644
--- a/spec/services/draft_notes/destroy_service_spec.rb
+++ b/spec/services/draft_notes/destroy_service_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe DraftNotes::DestroyService do
it 'destroys all draft notes for a user in a merge request' do
create_list(:draft_note, 2, merge_request: merge_request, author: user)
- expect { destroy }.to change { DraftNote.count }.by(-2)
+ expect { destroy }.to change { DraftNote.count }.by(-2) # rubocop:disable Rails/SaveBang
expect(DraftNote.count).to eq(0)
end
@@ -45,7 +45,7 @@ RSpec.describe DraftNotes::DestroyService do
allow_any_instance_of(DraftNote).to receive_message_chain(:diff_file, :unfolded?) { true }
expect(merge_request).to receive_message_chain(:diffs, :clear_cache)
- destroy
+ destroy # rubocop:disable Rails/SaveBang
end
end
end
diff --git a/spec/services/emails/confirm_service_spec.rb b/spec/services/emails/confirm_service_spec.rb
index 935a673f548..d3a745bc744 100644
--- a/spec/services/emails/confirm_service_spec.rb
+++ b/spec/services/emails/confirm_service_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Emails::ConfirmService do
describe '#execute' do
it 'enqueues a background job to send confirmation email again' do
- email = user.emails.create(email: 'new@email.com')
+ email = user.emails.create!(email: 'new@email.com')
expect { service.execute(email) }.to have_enqueued_job.on_queue('mailers')
end
diff --git a/spec/services/feature_flags/update_service_spec.rb b/spec/services/feature_flags/update_service_spec.rb
index a982dd5166b..66a75a2c24e 100644
--- a/spec/services/feature_flags/update_service_spec.rb
+++ b/spec/services/feature_flags/update_service_spec.rb
@@ -100,6 +100,13 @@ RSpec.describe FeatureFlags::UpdateService do
include('Updated active from <strong>"true"</strong> to <strong>"false"</strong>.')
)
end
+
+ it 'executes hooks' do
+ hook = create(:project_hook, :all_events_enabled, project: project)
+ expect(WebHookWorker).to receive(:perform_async).with(hook.id, an_instance_of(Hash), 'feature_flag_hooks')
+
+ subject
+ end
end
context 'when scope active state is changed' do
diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb
index 31afdba8192..e06f09d0463 100644
--- a/spec/services/groups/destroy_service_spec.rb
+++ b/spec/services/groups/destroy_service_spec.rb
@@ -95,7 +95,7 @@ RSpec.describe Groups::DestroyService do
context 'projects in pending_delete' do
before do
project.pending_delete = true
- project.save
+ project.save!
end
it_behaves_like 'group destruction', false
diff --git a/spec/services/groups/import_export/import_service_spec.rb b/spec/services/groups/import_export/import_service_spec.rb
index f284225e23a..f8cb55a9955 100644
--- a/spec/services/groups/import_export/import_service_spec.rb
+++ b/spec/services/groups/import_export/import_service_spec.rb
@@ -63,7 +63,7 @@ RSpec.describe Groups::ImportExport::ImportService do
before do
stub_feature_flags(group_import_ndjson: false)
- ImportExportUpload.create(group: group, import_file: import_file)
+ ImportExportUpload.create!(group: group, import_file: import_file)
allow(Gitlab::Import::Logger).to receive(:build).and_return(import_logger)
allow(import_logger).to receive(:error)
@@ -105,7 +105,7 @@ RSpec.describe Groups::ImportExport::ImportService do
subject { service.execute }
before do
- ImportExportUpload.create(group: group, import_file: import_file)
+ ImportExportUpload.create!(group: group, import_file: import_file)
allow(Gitlab::Import::Logger).to receive(:build).and_return(import_logger)
allow(import_logger).to receive(:error)
@@ -216,7 +216,7 @@ RSpec.describe Groups::ImportExport::ImportService do
subject { service.execute }
before do
- ImportExportUpload.create(group: group, import_file: import_file)
+ ImportExportUpload.create!(group: group, import_file: import_file)
allow(Gitlab::Import::Logger).to receive(:build).and_return(import_logger)
allow(import_logger).to receive(:error)
diff --git a/spec/services/issuable/common_system_notes_service_spec.rb b/spec/services/issuable/common_system_notes_service_spec.rb
index fc01ee8f672..a988ab81754 100644
--- a/spec/services/issuable/common_system_notes_service_spec.rb
+++ b/spec/services/issuable/common_system_notes_service_spec.rb
@@ -36,28 +36,28 @@ RSpec.describe Issuable::CommonSystemNotesService do
context 'adding Draft note' do
let(:issuable) { create(:merge_request, title: "merge request") }
- it_behaves_like 'system note creation', { title: "Draft: merge request" }, 'marked as a **Work In Progress**'
+ it_behaves_like 'system note creation', { title: "Draft: merge request" }, 'marked this merge request as **draft**'
context 'and changing title' do
before do
issuable.update_attribute(:title, "Draft: changed title")
end
- it_behaves_like 'draft notes creation', 'marked'
+ it_behaves_like 'draft notes creation', 'draft'
end
end
context 'removing Draft note' do
let(:issuable) { create(:merge_request, title: "Draft: merge request") }
- it_behaves_like 'system note creation', { title: "merge request" }, 'unmarked as a **Work In Progress**'
+ it_behaves_like 'system note creation', { title: "merge request" }, 'marked this merge request as **ready**'
context 'and changing title' do
before do
issuable.update_attribute(:title, "changed title")
end
- it_behaves_like 'draft notes creation', 'unmarked'
+ it_behaves_like 'draft notes creation', 'ready'
end
end
end
diff --git a/spec/services/issues/import_csv_service_spec.rb b/spec/services/issues/import_csv_service_spec.rb
index cc3e1d23a74..fa40b75190f 100644
--- a/spec/services/issues/import_csv_service_spec.rb
+++ b/spec/services/issues/import_csv_service_spec.rb
@@ -5,108 +5,15 @@ require 'spec_helper'
RSpec.describe Issues::ImportCsvService do
let(:project) { create(:project) }
let(:user) { create(:user) }
-
- subject do
+ let(:service) do
uploader = FileUploader.new(project)
uploader.store!(file)
- described_class.new(user, project, uploader).execute
+ described_class.new(user, project, uploader)
end
- describe '#execute' do
- context 'invalid file' do
- let(:file) { fixture_file_upload('spec/fixtures/banana_sample.gif') }
-
- it 'returns invalid file error' do
- expect(Notify).to receive_message_chain(:import_issues_csv_email, :deliver_later)
-
- expect(subject[:success]).to eq(0)
- expect(subject[:parse_error]).to eq(true)
- end
- end
-
- context 'with a file generated by Gitlab CSV export' do
- let(:file) { fixture_file_upload('spec/fixtures/csv_gitlab_export.csv') }
-
- it 'imports the CSV without errors' do
- expect(Notify).to receive_message_chain(:import_issues_csv_email, :deliver_later)
-
- expect(subject[:success]).to eq(4)
- expect(subject[:error_lines]).to eq([])
- expect(subject[:parse_error]).to eq(false)
- end
-
- it 'correctly sets the issue attributes' do
- expect { subject }.to change { project.issues.count }.by 4
-
- expect(project.issues.reload.last).to have_attributes(
- title: 'Test Title',
- description: 'Test Description'
- )
- end
- end
-
- context 'comma delimited file' do
- let(:file) { fixture_file_upload('spec/fixtures/csv_comma.csv') }
-
- it 'imports CSV without errors' do
- expect(Notify).to receive_message_chain(:import_issues_csv_email, :deliver_later)
-
- expect(subject[:success]).to eq(3)
- expect(subject[:error_lines]).to eq([])
- expect(subject[:parse_error]).to eq(false)
- end
-
- it 'correctly sets the issue attributes' do
- expect { subject }.to change { project.issues.count }.by 3
-
- expect(project.issues.reload.last).to have_attributes(
- title: 'Title with quote"',
- description: 'Description'
- )
- end
- end
-
- context 'tab delimited file with error row' do
- let(:file) { fixture_file_upload('spec/fixtures/csv_tab.csv') }
-
- it 'imports CSV with some error rows' do
- expect(Notify).to receive_message_chain(:import_issues_csv_email, :deliver_later)
-
- expect(subject[:success]).to eq(2)
- expect(subject[:error_lines]).to eq([3])
- expect(subject[:parse_error]).to eq(false)
- end
-
- it 'correctly sets the issue attributes' do
- expect { subject }.to change { project.issues.count }.by 2
-
- expect(project.issues.reload.last).to have_attributes(
- title: 'Hello',
- description: 'World'
- )
- end
- end
-
- context 'semicolon delimited file with CRLF' do
- let(:file) { fixture_file_upload('spec/fixtures/csv_semicolon.csv') }
-
- it 'imports CSV with a blank row' do
- expect(Notify).to receive_message_chain(:import_issues_csv_email, :deliver_later)
-
- expect(subject[:success]).to eq(3)
- expect(subject[:error_lines]).to eq([4])
- expect(subject[:parse_error]).to eq(false)
- end
-
- it 'correctly sets the issue attributes' do
- expect { subject }.to change { project.issues.count }.by 3
-
- expect(project.issues.reload.last).to have_attributes(
- title: 'Hello',
- description: 'World'
- )
- end
- end
+ include_examples 'issuable import csv service', 'issue' do
+ let(:issuables) { project.issues }
+ let(:email_method) { :import_issues_csv_email }
end
end
diff --git a/spec/services/issues/move_service_spec.rb b/spec/services/issues/move_service_spec.rb
index ae1454ce9bb..9b8d21bb8eb 100644
--- a/spec/services/issues/move_service_spec.rb
+++ b/spec/services/issues/move_service_spec.rb
@@ -321,21 +321,40 @@ RSpec.describe Issues::MoveService do
before do
authorized_project.add_developer(user)
+ authorized_project.add_developer(admin)
authorized_project2.add_developer(user)
+ authorized_project2.add_developer(admin)
end
context 'multiple related issues' do
- it 'moves all related issues and retains permissions' do
- new_issue = move_service.execute(old_issue, new_project)
+ context 'when admin mode is enabled', :enable_admin_mode 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
- expect(new_issue.related_issues(admin))
- .to match_array([authorized_issue_b, authorized_issue_c, authorized_issue_d, unauthorized_issue])
+ context 'when admin mode is disabled' do
+ it 'moves all related issues and retains permissions' do
+ new_issue = move_service.execute(old_issue, new_project)
- expect(new_issue.related_issues(user))
- .to match_array([authorized_issue_b, authorized_issue_c, authorized_issue_d])
+ expect(new_issue.related_issues(admin))
+ .to match_array([authorized_issue_b, authorized_issue_c, authorized_issue_d])
- expect(authorized_issue_d.related_issues(user))
- .to match_array([new_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
end
diff --git a/spec/services/issues/related_branches_service_spec.rb b/spec/services/issues/related_branches_service_spec.rb
index 1780023803a..a8a1f95e800 100644
--- a/spec/services/issues/related_branches_service_spec.rb
+++ b/spec/services/issues/related_branches_service_spec.rb
@@ -74,8 +74,16 @@ RSpec.describe Issues::RelatedBranchesService do
context 'the user has access to otherwise unreadable pipelines' do
let(:user) { create(:admin) }
- it 'returns info a developer could not see' do
- expect(branch_info.pluck(:pipeline_status)).to include(an_instance_of(Gitlab::Ci::Status::Running))
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns info a developer could not see' do
+ expect(branch_info.pluck(:pipeline_status)).to include(an_instance_of(Gitlab::Ci::Status::Running))
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'does not return info a developer could not see' do
+ expect(branch_info.pluck(:pipeline_status)).not_to include(an_instance_of(Gitlab::Ci::Status::Running))
+ end
end
end
diff --git a/spec/services/issues/zoom_link_service_spec.rb b/spec/services/issues/zoom_link_service_spec.rb
index b095cb24212..8e8adc516cf 100644
--- a/spec/services/issues/zoom_link_service_spec.rb
+++ b/spec/services/issues/zoom_link_service_spec.rb
@@ -46,10 +46,15 @@ RSpec.describe Issues::ZoomLinkService do
expect(ZoomMeeting.canonical_meeting_url(issue)).to eq(zoom_link)
end
- it 'tracks the add event' do
- expect(Gitlab::Tracking).to receive(:event)
- .with('IncidentManagement::ZoomIntegration', 'add_zoom_meeting', label: 'Issue ID', value: issue.id)
+ it 'tracks the add event', :snowplow do
result
+
+ expect_snowplow_event(
+ category: 'IncidentManagement::ZoomIntegration',
+ action: 'add_zoom_meeting',
+ label: 'Issue ID',
+ value: issue.id
+ )
end
it 'creates a zoom_link_added notification' do
@@ -180,10 +185,15 @@ RSpec.describe Issues::ZoomLinkService do
expect(ZoomMeeting.canonical_meeting_url(issue)).to eq(nil)
end
- it 'tracks the remove event' do
- expect(Gitlab::Tracking).to receive(:event)
- .with('IncidentManagement::ZoomIntegration', 'remove_zoom_meeting', label: 'Issue ID', value: issue.id)
+ it 'tracks the remove event', :snowplow do
result
+
+ expect_snowplow_event(
+ category: 'IncidentManagement::ZoomIntegration',
+ action: 'remove_zoom_meeting',
+ label: 'Issue ID',
+ value: issue.id
+ )
end
end
diff --git a/spec/services/jira_connect/sync_service_spec.rb b/spec/services/jira_connect/sync_service_spec.rb
index e26ca30d0e1..83088bb2e79 100644
--- a/spec/services/jira_connect/sync_service_spec.rb
+++ b/spec/services/jira_connect/sync_service_spec.rb
@@ -23,7 +23,8 @@ RSpec.describe JiraConnect::SyncService do
project: project,
commits: commits,
branches: [instance_of(Gitlab::Git::Branch)],
- merge_requests: merge_requests
+ merge_requests: merge_requests,
+ update_sequence_id: anything
).and_return(return_value)
end
end
diff --git a/spec/services/jira_connect_subscriptions/create_service_spec.rb b/spec/services/jira_connect_subscriptions/create_service_spec.rb
index 77e758cf6fe..9750c671fa2 100644
--- a/spec/services/jira_connect_subscriptions/create_service_spec.rb
+++ b/spec/services/jira_connect_subscriptions/create_service_spec.rb
@@ -32,6 +32,36 @@ RSpec.describe JiraConnectSubscriptions::CreateService do
it 'returns success' do
expect(subject[:status]).to eq(:success)
end
+
+ context 'namespace has projects' do
+ let!(:project_1) { create(:project, group: group) }
+ let!(:project_2) { create(:project, group: group) }
+
+ before do
+ stub_const("#{described_class}::MERGE_REQUEST_SYNC_BATCH_SIZE", 1)
+ end
+
+ it 'starts workers to sync projects in batches with delay' do
+ allow(Atlassian::JiraConnect::Client).to receive(:generate_update_sequence_id).and_return(123)
+
+ expect(JiraConnect::SyncProjectWorker).to receive(:bulk_perform_in).with(1.minute, [[project_1.id, 123]])
+ expect(JiraConnect::SyncProjectWorker).to receive(:bulk_perform_in).with(2.minutes, [[project_2.id, 123]])
+
+ subject
+ end
+
+ context 'when the jira_connect_full_namespace_sync feature flag is disabled' do
+ before do
+ stub_feature_flags(jira_connect_full_namespace_sync: false)
+ end
+
+ specify do
+ expect(JiraConnect::SyncProjectWorker).not_to receive(:bulk_perform_in_with_contexts)
+
+ subject
+ end
+ end
+ end
end
context 'when path is invalid' do
diff --git a/spec/services/jira_import/cloud_users_mapper_service_spec.rb b/spec/services/jira_import/cloud_users_mapper_service_spec.rb
index 591f80f3efc..6b06a982a80 100644
--- a/spec/services/jira_import/cloud_users_mapper_service_spec.rb
+++ b/spec/services/jira_import/cloud_users_mapper_service_spec.rb
@@ -5,15 +5,44 @@ require 'spec_helper'
RSpec.describe JiraImport::CloudUsersMapperService do
let(:start_at) { 7 }
let(:url) { "/rest/api/2/users?maxResults=50&startAt=#{start_at}" }
+
+ let_it_be(:user_1) { create(:user, username: 'randomuser', name: 'USER-name1', email: 'uji@example.com') }
+ let_it_be(:user_2) { create(:user, username: 'username-2') }
+ let_it_be(:user_5) { create(:user, username: 'username-5') }
+ let_it_be(:user_4) { create(:user, email: 'user-4@example.com') }
+ let_it_be(:user_6) { create(:user, email: 'user-6@example.com') }
+ let_it_be(:user_7) { create(:user, username: 'username-7') }
+ let_it_be(:user_8) do
+ create(:user).tap { |user| create(:email, user: user, email: 'user8_email@example.com') }
+ end
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+
let(:jira_users) do
[
- { 'accountId' => 'abcd', 'displayName' => 'user1' },
- { 'accountId' => 'efg' },
- { 'accountId' => 'hij', 'displayName' => 'user3', 'emailAddress' => 'user3@example.com' }
+ { 'accountId' => 'abcd', 'displayName' => 'User-Name1' }, # matched by name
+ { 'accountId' => 'efg', 'displayName' => 'username-2' }, # matcher by username
+ { 'accountId' => 'hij' }, # no match
+ { 'accountId' => '123', 'displayName' => 'user-4', 'emailAddress' => 'user-4@example.com' }, # matched by email
+ { 'accountId' => '456', 'displayName' => 'username5foo', 'emailAddress' => 'user-5@example.com' }, # no match
+ { 'accountId' => '789', 'displayName' => 'user-6', 'emailAddress' => 'user-6@example.com' }, # matched by email, no project member
+ { 'accountId' => 'xyz', 'displayName' => 'username-7', 'emailAddress' => 'user-7@example.com' }, # matched by username, no project member
+ { 'accountId' => 'vhk', 'displayName' => 'user-8', 'emailAddress' => 'user8_email@example.com' }, # matched by secondary email
+ { 'accountId' => 'uji', 'displayName' => 'user-9', 'emailAddress' => 'uji@example.com' } # matched by email, same as user_1
]
end
describe '#execute' do
+ before do
+ project.add_developer(current_user)
+ project.add_developer(user_1)
+ project.add_developer(user_2)
+ group.add_developer(user_4)
+ group.add_guest(user_8)
+ end
+
it_behaves_like 'mapping jira users'
end
end
diff --git a/spec/services/jira_import/server_users_mapper_service_spec.rb b/spec/services/jira_import/server_users_mapper_service_spec.rb
index 22cb0327cc5..71cb8aea0be 100644
--- a/spec/services/jira_import/server_users_mapper_service_spec.rb
+++ b/spec/services/jira_import/server_users_mapper_service_spec.rb
@@ -5,15 +5,44 @@ require 'spec_helper'
RSpec.describe JiraImport::ServerUsersMapperService do
let(:start_at) { 7 }
let(:url) { "/rest/api/2/user/search?username=''&maxResults=50&startAt=#{start_at}" }
+
+ let_it_be(:user_1) { create(:user, username: 'randomuser', name: 'USER-name1', email: 'uji@example.com') }
+ let_it_be(:user_2) { create(:user, username: 'username-2') }
+ let_it_be(:user_5) { create(:user, username: 'username-5') }
+ let_it_be(:user_4) { create(:user, email: 'user-4@example.com') }
+ let_it_be(:user_6) { create(:user, email: 'user-6@example.com') }
+ let_it_be(:user_7) { create(:user, username: 'username-7') }
+ let_it_be(:user_8) do
+ create(:user).tap { |user| create(:email, user: user, email: 'user8_email@example.com') }
+ end
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+
let(:jira_users) do
[
- { 'key' => 'abcd', 'name' => 'user1' },
- { 'key' => 'efg' },
- { 'key' => 'hij', 'name' => 'user3', 'emailAddress' => 'user3@example.com' }
+ { 'key' => 'abcd', 'name' => 'User-Name1' }, # matched by name
+ { 'key' => 'efg', 'name' => 'username-2' }, # matcher by username
+ { 'key' => 'hij' }, # no match
+ { 'key' => '123', 'name' => 'user-4', 'emailAddress' => 'user-4@example.com' }, # matched by email
+ { 'key' => '456', 'name' => 'username5foo', 'emailAddress' => 'user-5@example.com' }, # no match
+ { 'key' => '789', 'name' => 'user-6', 'emailAddress' => 'user-6@example.com' }, # matched by email, no project member
+ { 'key' => 'xyz', 'name' => 'username-7', 'emailAddress' => 'user-7@example.com' }, # matched by username, no project member
+ { 'key' => 'vhk', 'name' => 'user-8', 'emailAddress' => 'user8_email@example.com' }, # matched by secondary email
+ { 'key' => 'uji', 'name' => 'user-9', 'emailAddress' => 'uji@example.com' } # matched by email, same as user_1
]
end
describe '#execute' do
+ before do
+ project.add_developer(current_user)
+ project.add_developer(user_1)
+ project.add_developer(user_2)
+ group.add_developer(user_4)
+ group.add_guest(user_8)
+ end
+
it_behaves_like 'mapping jira users'
end
end
diff --git a/spec/services/jira_import/users_importer_spec.rb b/spec/services/jira_import/users_importer_spec.rb
index efb303dab9f..7112443502c 100644
--- a/spec/services/jira_import/users_importer_spec.rb
+++ b/spec/services/jira_import/users_importer_spec.rb
@@ -6,7 +6,8 @@ RSpec.describe JiraImport::UsersImporter do
include JiraServiceHelper
let_it_be(:user) { create(:user) }
- let_it_be(:project, reload: true) { create(:project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project, reload: true) { create(:project, group: group) }
let_it_be(:start_at) { 7 }
let(:importer) { described_class.new(user, project, start_at) }
@@ -18,19 +19,15 @@ RSpec.describe JiraImport::UsersImporter do
[
{
jira_account_id: 'acc1',
- jira_display_name: 'user1',
+ jira_display_name: 'user-name1',
jira_email: 'sample@jira.com',
- gitlab_id: nil,
- gitlab_username: nil,
- gitlab_name: nil
+ gitlab_id: project_member.id
},
{
jira_account_id: 'acc2',
- jira_display_name: 'user2',
+ jira_display_name: 'user-name2',
jira_email: nil,
- gitlab_id: nil,
- gitlab_username: nil,
- gitlab_name: nil
+ gitlab_id: group_member.id
}
]
end
@@ -69,13 +66,22 @@ RSpec.describe JiraImport::UsersImporter do
context 'when jira client returns an empty array' do
let(:jira_users) { [] }
- it 'retturns nil payload' do
+ it 'returns nil payload' do
expect(subject.success?).to be_truthy
expect(subject.payload).to be_empty
end
end
context 'when jira client returns an results' do
+ let_it_be(:project_member) { create(:user, email: 'sample@jira.com') }
+ let_it_be(:group_member) { create(:user, name: 'user-name2') }
+ let_it_be(:other_user) { create(:user) }
+
+ before do
+ project.add_developer(project_member)
+ group.add_developer(group_member)
+ end
+
it 'returns the mapped users' do
expect(subject.success?).to be_truthy
expect(subject.payload).to eq(mapped_users)
@@ -90,8 +96,8 @@ RSpec.describe JiraImport::UsersImporter do
let(:url) { "/rest/api/2/user/search?username=''&maxResults=50&startAt=#{start_at}" }
let(:jira_users) do
[
- { 'key' => 'acc1', 'name' => 'user1', 'emailAddress' => 'sample@jira.com' },
- { 'key' => 'acc2', 'name' => 'user2' }
+ { 'key' => 'acc1', 'name' => 'user-name1', 'emailAddress' => 'sample@jira.com' },
+ { 'key' => 'acc2', 'name' => 'user-name2' }
]
end
@@ -110,8 +116,8 @@ RSpec.describe JiraImport::UsersImporter do
let(:url) { "/rest/api/2/users?maxResults=50&startAt=#{start_at}" }
let(:jira_users) do
[
- { 'accountId' => 'acc1', 'displayName' => 'user1', 'emailAddress' => 'sample@jira.com' },
- { 'accountId' => 'acc2', 'displayName' => 'user2' }
+ { 'accountId' => 'acc1', 'displayName' => 'user-name1', 'emailAddress' => 'sample@jira.com' },
+ { 'accountId' => 'acc2', 'displayName' => 'user-name2' }
]
end
diff --git a/spec/services/labels/promote_service_spec.rb b/spec/services/labels/promote_service_spec.rb
index 7674ec36331..15d53857f33 100644
--- a/spec/services/labels/promote_service_spec.rb
+++ b/spec/services/labels/promote_service_spec.rb
@@ -63,139 +63,149 @@ RSpec.describe Labels::PromoteService do
expect(service.execute(group_label)).to be_falsey
end
- it 'is truthy on success' do
- expect(service.execute(project_label_1_1)).to be_truthy
- end
+ shared_examples 'promoting a project label to a group label' do
+ it 'is truthy on success' do
+ expect(service.execute(project_label_1_1)).to be_truthy
+ end
- it 'recreates the label as a group label' do
- expect { service.execute(project_label_1_1) }
- .to change(project_1.labels, :count).by(-1)
- .and change(group_1.labels, :count).by(1)
- expect(new_label).not_to be_nil
- end
+ it 'removes all project labels with that title within the group' do
+ expect { service.execute(project_label_1_1) }.to change(project_2.labels, :count).by(-1).and \
+ change(project_3.labels, :count).by(-1)
+ end
- it 'copies title, description and color' do
- service.execute(project_label_1_1)
+ it 'keeps users\' subscriptions' do
+ user2 = create(:user)
+ project_label_1_1.subscriptions.create!(user: user, subscribed: true)
+ project_label_2_1.subscriptions.create!(user: user, subscribed: true)
+ project_label_3_2.subscriptions.create!(user: user, subscribed: true)
+ project_label_2_1.subscriptions.create!(user: user2, subscribed: true)
- expect(new_label.title).to eq(promoted_label_name)
- expect(new_label.description).to eq(promoted_description)
- expect(new_label.color).to eq(promoted_color)
- end
+ expect { service.execute(project_label_1_1) }.to change { Subscription.count }.from(4).to(3)
- it 'merges labels with the same name in group' do
- expect { service.execute(project_label_1_1) }.to change(project_2.labels, :count).by(-1).and \
- change(project_3.labels, :count).by(-1)
- end
-
- it 'keeps users\' subscriptions' do
- user2 = create(:user)
- project_label_1_1.subscriptions.create(user: user, subscribed: true)
- project_label_2_1.subscriptions.create(user: user, subscribed: true)
- project_label_3_2.subscriptions.create(user: user, subscribed: true)
- project_label_2_1.subscriptions.create(user: user2, subscribed: true)
+ expect(new_label.subscribed?(user)).to be_truthy
+ expect(new_label.subscribed?(user2)).to be_truthy
+ end
- expect { service.execute(project_label_1_1) }.to change { Subscription.count }.from(4).to(3)
+ it 'recreates priorities' do
+ service.execute(project_label_1_1)
- expect(new_label.subscribed?(user)).to be_truthy
- expect(new_label.subscribed?(user2)).to be_truthy
- end
+ expect(new_label.priority(project_1)).to be_nil
+ expect(new_label.priority(project_2)).to eq(label_2_1_priority)
+ expect(new_label.priority(project_3)).to eq(label_3_1_priority)
+ end
- it 'recreates priorities' do
- service.execute(project_label_1_1)
+ it 'does not touch project out of promoted group' do
+ service.execute(project_label_1_1)
+ project_4_new_label = project_4.labels.find_by(title: promoted_label_name)
- expect(new_label.priority(project_1)).to be_nil
- expect(new_label.priority(project_2)).to eq(label_2_1_priority)
- expect(new_label.priority(project_3)).to eq(label_3_1_priority)
- end
+ expect(project_4_new_label).not_to be_nil
+ expect(project_4_new_label.id).to eq(project_label_4_1.id)
+ end
- it 'does not touch project out of promoted group' do
- service.execute(project_label_1_1)
- project_4_new_label = project_4.labels.find_by(title: promoted_label_name)
+ it 'does not touch out of group priority' do
+ service.execute(project_label_1_1)
- expect(project_4_new_label).not_to be_nil
- expect(project_4_new_label.id).to eq(project_label_4_1.id)
- end
+ expect(new_label.priority(project_4)).to be_nil
+ end
- it 'does not touch out of group priority' do
- service.execute(project_label_1_1)
+ it 'relinks issue with the promoted label' do
+ service.execute(project_label_1_1)
+ issue_label = issue_1_1.labels.find_by(title: promoted_label_name)
- expect(new_label.priority(project_4)).to be_nil
- end
+ expect(issue_label).not_to be_nil
+ expect(issue_label.id).to eq(new_label.id)
+ end
- it 'relinks issue with the promoted label' do
- service.execute(project_label_1_1)
- issue_label = issue_1_1.labels.find_by(title: promoted_label_name)
+ it 'does not remove untouched labels from issue' do
+ expect { service.execute(project_label_1_1) }.not_to change(issue_1_1.labels, :count)
+ end
- expect(issue_label).not_to be_nil
- expect(issue_label.id).to eq(new_label.id)
- end
+ it 'does not relink untouched label in issue' do
+ service.execute(project_label_1_1)
+ issue_label = issue_1_2.labels.find_by(title: untouched_label_name)
- it 'does not remove untouched labels from issue' do
- expect { service.execute(project_label_1_1) }.not_to change(issue_1_1.labels, :count)
- end
+ expect(issue_label).not_to be_nil
+ expect(issue_label.id).to eq(project_label_1_2.id)
+ end
- it 'does not relink untouched label in issue' do
- service.execute(project_label_1_1)
- issue_label = issue_1_2.labels.find_by(title: untouched_label_name)
+ it 'relinks issues with merged labels' do
+ service.execute(project_label_1_1)
+ issue_label = issue_2_1.labels.find_by(title: promoted_label_name)
- expect(issue_label).not_to be_nil
- expect(issue_label.id).to eq(project_label_1_2.id)
- end
+ expect(issue_label).not_to be_nil
+ expect(issue_label.id).to eq(new_label.id)
+ end
- it 'relinks issues with merged labels' do
- service.execute(project_label_1_1)
- issue_label = issue_2_1.labels.find_by(title: promoted_label_name)
+ it 'does not relink issues from other group' do
+ service.execute(project_label_1_1)
+ issue_label = issue_4_1.labels.find_by(title: promoted_label_name)
- expect(issue_label).not_to be_nil
- expect(issue_label.id).to eq(new_label.id)
- end
+ expect(issue_label).not_to be_nil
+ expect(issue_label.id).to eq(project_label_4_1.id)
+ end
- it 'does not relink issues from other group' do
- service.execute(project_label_1_1)
- issue_label = issue_4_1.labels.find_by(title: promoted_label_name)
+ it 'updates merge request' do
+ service.execute(project_label_1_1)
+ merge_label = merge_3_1.labels.find_by(title: promoted_label_name)
- expect(issue_label).not_to be_nil
- expect(issue_label.id).to eq(project_label_4_1.id)
- end
+ expect(merge_label).not_to be_nil
+ expect(merge_label.id).to eq(new_label.id)
+ end
- it 'updates merge request' do
- service.execute(project_label_1_1)
- merge_label = merge_3_1.labels.find_by(title: promoted_label_name)
+ it 'updates board lists' do
+ service.execute(project_label_1_1)
+ list = issue_board_2_1.lists.find_by(label: new_label)
- expect(merge_label).not_to be_nil
- expect(merge_label.id).to eq(new_label.id)
- end
+ expect(list).not_to be_nil
+ end
- it 'updates board lists' do
- service.execute(project_label_1_1)
- list = issue_board_2_1.lists.find_by(label: new_label)
+ # In case someone adds a new relation to Label.rb and forgets to relink it
+ # and the database doesn't have foreign key constraints
+ it 'relinks all relations' do
+ service.execute(project_label_1_1)
- expect(list).not_to be_nil
+ Label.reflect_on_all_associations.each do |association|
+ expect(project_label_1_1.send(association.name).any?).to be_falsey
+ end
+ end
end
- # In case someone adds a new relation to Label.rb and forgets to relink it
- # and the database doesn't have foreign key constraints
- it 'relinks all relations' do
- service.execute(project_label_1_1)
+ context 'if there is an existing identical group label' do
+ let!(:existing_group_label) { create(:group_label, group: group_1, title: project_label_1_1.title ) }
+
+ it 'uses the existing group label' do
+ expect { service.execute(project_label_1_1) }
+ .to change(project_1.labels, :count).by(-1)
+ .and not_change(group_1.labels, :count)
+ expect(new_label).not_to be_nil
+ end
- Label.reflect_on_all_associations.each do |association|
- expect(project_label_1_1.send(association.name).any?).to be_falsey
+ it 'does not create a new group label clone' do
+ expect { service.execute(project_label_1_1) }.not_to change { GroupLabel.maximum(:id) }
end
+
+ it_behaves_like 'promoting a project label to a group label'
end
- context 'with invalid group label' do
- before do
- allow(service).to receive(:clone_label_to_group_label).and_wrap_original do |m, *args|
- label = m.call(*args)
- allow(label).to receive(:valid?).and_return(false)
+ context 'if there is no existing identical group label' do
+ let(:existing_group_label) { nil }
- label
- end
+ it 'recreates the label as a group label' do
+ expect { service.execute(project_label_1_1) }
+ .to change(project_1.labels, :count).by(-1)
+ .and change(group_1.labels, :count).by(1)
+ expect(new_label).not_to be_nil
end
- it 'raises an exception' do
- expect { service.execute(project_label_1_1) }.to raise_error(ActiveRecord::RecordInvalid)
+ it 'copies title, description and color to cloned group label' do
+ service.execute(project_label_1_1)
+
+ expect(new_label.title).to eq(promoted_label_name)
+ expect(new_label.description).to eq(promoted_description)
+ expect(new_label.color).to eq(promoted_color)
end
+
+ it_behaves_like 'promoting a project label to a group label'
end
end
end
diff --git a/spec/services/labels/transfer_service_spec.rb b/spec/services/labels/transfer_service_spec.rb
index 2c0c82ed976..18fd401f383 100644
--- a/spec/services/labels/transfer_service_spec.rb
+++ b/spec/services/labels/transfer_service_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Labels::TransferService do
describe '#execute' do
- let_it_be(:user) { create(:admin) }
+ let_it_be(:user) { create(:user) }
let_it_be(:old_group_ancestor) { create(:group) }
let_it_be(:old_group) { create(:group, parent: old_group_ancestor) }
@@ -15,6 +15,11 @@ RSpec.describe Labels::TransferService do
subject(:service) { described_class.new(user, old_group, project) }
+ before do
+ old_group_ancestor.add_developer(user)
+ new_group.add_developer(user)
+ end
+
it 'recreates missing group labels at project level and assigns them to the issuables' do
old_group_label_1 = create(:group_label, group: old_group)
old_group_label_2 = create(:group_label, group: old_group)
diff --git a/spec/services/members/invite_service_spec.rb b/spec/services/members/invite_service_spec.rb
new file mode 100644
index 00000000000..12a1a54696b
--- /dev/null
+++ b/spec/services/members/invite_service_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Members::InviteService do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:project_user) { create(:user) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'adds an existing user to members' do
+ params = { email: project_user.email.to_s, access_level: Gitlab::Access::GUEST }
+ result = described_class.new(user, params).execute(project)
+
+ expect(result[:status]).to eq(:success)
+ expect(project.users).to include project_user
+ end
+
+ it 'creates a new user for an unknown email address' do
+ params = { email: 'email@example.org', access_level: Gitlab::Access::GUEST }
+ result = described_class.new(user, params).execute(project)
+
+ expect(result[:status]).to eq(:success)
+ end
+
+ it 'limits the number of emails to 100' do
+ emails = Array.new(101).map { |n| "email#{n}@example.com" }
+ params = { email: emails, access_level: Gitlab::Access::GUEST }
+
+ result = described_class.new(user, params).execute(project)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Too many users specified (limit is 100)')
+ end
+
+ it 'does not invite an invalid email' do
+ params = { email: project_user.id.to_s, access_level: Gitlab::Access::GUEST }
+ result = described_class.new(user, params).execute(project)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message][project_user.id.to_s]).to eq("Invite email is invalid")
+ expect(project.users).not_to include project_user
+ end
+
+ it 'does not invite to an invalid access level' do
+ params = { email: project_user.email, access_level: -1 }
+ result = described_class.new(user, params).execute(project)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message][project_user.email]).to eq("Access level is not included in the list")
+ end
+
+ it 'does not add a member with an existing invite' do
+ invited_member = create(:project_member, :invited, project: project)
+
+ params = { email: invited_member.invite_email,
+ access_level: Gitlab::Access::GUEST }
+ result = described_class.new(user, params).execute(project)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message][invited_member.invite_email]).to eq("Member already invited to #{project.name}")
+ end
+end
diff --git a/spec/services/merge_requests/add_context_service_spec.rb b/spec/services/merge_requests/add_context_service_spec.rb
index 58ed91218d1..27b46a9023c 100644
--- a/spec/services/merge_requests/add_context_service_spec.rb
+++ b/spec/services/merge_requests/add_context_service_spec.rb
@@ -12,10 +12,20 @@ RSpec.describe MergeRequests::AddContextService do
subject(:service) { described_class.new(project, admin, merge_request: merge_request, commits: commits) }
describe "#execute" do
- it "adds context commit" do
- service.execute
+ context "when admin mode is enabled", :enable_admin_mode do
+ it "adds context commit" do
+ service.execute
- expect(merge_request.merge_request_context_commit_diff_files.length).to eq(2)
+ expect(merge_request.merge_request_context_commit_diff_files.length).to eq(2)
+ end
+ end
+
+ context "when admin mode is disabled" do
+ it "doesn't add context commit" do
+ subject.execute
+
+ expect(merge_request.merge_request_context_commit_diff_files.length).to eq(0)
+ end
end
context "when user doesn't have permission to update merge request" do
diff --git a/spec/services/merge_requests/cleanup_refs_service_spec.rb b/spec/services/merge_requests/cleanup_refs_service_spec.rb
index a051b3c9355..38c0e204e54 100644
--- a/spec/services/merge_requests/cleanup_refs_service_spec.rb
+++ b/spec/services/merge_requests/cleanup_refs_service_spec.rb
@@ -4,14 +4,15 @@ require 'spec_helper'
RSpec.describe MergeRequests::CleanupRefsService do
describe '.schedule' do
- let(:merge_request) { build(:merge_request) }
+ let(:merge_request) { create(:merge_request) }
- it 'schedules MergeRequestCleanupRefsWorker' do
- expect(MergeRequestCleanupRefsWorker)
- .to receive(:perform_in)
- .with(described_class::TIME_THRESHOLD, merge_request.id)
+ it 'creates a merge request cleanup schedule' do
+ freeze_time do
+ described_class.schedule(merge_request)
- described_class.schedule(merge_request)
+ expect(merge_request.reload.cleanup_schedule.scheduled_at)
+ .to eq(described_class::TIME_THRESHOLD.from_now)
+ end
end
end
@@ -20,6 +21,8 @@ RSpec.describe MergeRequests::CleanupRefsService 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
+
+ merge_request.create_cleanup_schedule(scheduled_at: described_class::TIME_THRESHOLD.ago)
end
subject(:result) { described_class.new(merge_request).execute }
@@ -32,6 +35,7 @@ RSpec.describe MergeRequests::CleanupRefsService do
expect(result[:status]).to eq(:success)
expect(kept_around?(old_ref_head)).to be_truthy
expect(ref_head).to be_nil
+ expect(merge_request.cleanup_schedule.completed_at).to be_present
end
end
@@ -43,6 +47,7 @@ RSpec.describe MergeRequests::CleanupRefsService do
it 'does not fail' do
expect(result[:status]).to eq(:success)
+ expect(merge_request.cleanup_schedule.completed_at).to be_present
end
end
@@ -85,6 +90,44 @@ RSpec.describe MergeRequests::CleanupRefsService do
it_behaves_like 'service that does not clean up merge request refs'
end
+
+ context 'when cleanup schedule fails to update' do
+ before do
+ allow(merge_request.cleanup_schedule).to receive(:update).and_return(false)
+ end
+
+ it 'creates keep around ref and deletes merge request refs' do
+ old_ref_head = ref_head
+
+ aggregate_failures do
+ expect(result[:status]).to eq(:error)
+ expect(kept_around?(old_ref_head)).to be_truthy
+ expect(ref_head).to be_nil
+ expect(merge_request.cleanup_schedule.completed_at).not_to be_present
+ end
+ end
+ end
+
+ context 'when merge request is not scheduled to be cleaned up yet' do
+ before do
+ merge_request.cleanup_schedule.update!(scheduled_at: 1.day.from_now)
+ end
+
+ it_behaves_like 'service that does not clean up merge request refs'
+ end
+
+ context 'when repository no longer exists' do
+ before do
+ Repositories::DestroyService.new(merge_request.project.repository).execute
+ end
+
+ it 'does not fail and still mark schedule as complete' do
+ aggregate_failures do
+ expect(result[:status]).to eq(:success)
+ expect(merge_request.cleanup_schedule.completed_at).to be_present
+ end
+ end
+ end
end
shared_examples_for 'service that does not clean up merge request refs' do
@@ -92,6 +135,7 @@ RSpec.describe MergeRequests::CleanupRefsService do
aggregate_failures do
expect(result[:status]).to eq(:error)
expect(ref_head).to be_present
+ expect(merge_request.cleanup_schedule.completed_at).not_to be_present
end
end
end
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index d603cbb16aa..3ccf02fcdfb 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -683,14 +683,14 @@ RSpec.describe MergeRequests::RefreshService do
end
end
- context 'marking the merge request as work in progress' do
+ context 'marking the merge request as draft' do
let(:refresh_service) { service.new(@project, @user) }
before do
allow(refresh_service).to receive(:execute_hooks)
end
- it 'marks the merge request as work in progress from fixup commits' do
+ it 'marks the merge request as draft from fixup commits' do
fixup_merge_request = create(:merge_request,
source_project: @project,
source_branch: 'wip',
@@ -705,11 +705,11 @@ RSpec.describe MergeRequests::RefreshService do
expect(fixup_merge_request.work_in_progress?).to eq(true)
expect(fixup_merge_request.notes.last.note).to match(
- /marked as a \*\*Work In Progress\*\* from #{Commit.reference_pattern}/
+ /marked this merge request as \*\*draft\*\* from #{Commit.reference_pattern}/
)
end
- it 'references the commit that caused the Work in Progress status' do
+ it 'references the commit that caused the draft status' do
wip_merge_request = create(:merge_request,
source_project: @project,
source_branch: 'wip',
@@ -724,11 +724,11 @@ RSpec.describe MergeRequests::RefreshService do
refresh_service.execute(oldrev, newrev, 'refs/heads/wip')
expect(wip_merge_request.reload.notes.last.note).to eq(
- "marked as a **Work In Progress** from #{wip_commit.id}"
+ "marked this merge request as **draft** from #{wip_commit.id}"
)
end
- it 'does not mark as WIP based on commits that do not belong to an MR' do
+ it 'does not mark as draft based on commits that do not belong to an MR' do
allow(refresh_service).to receive(:find_new_commits)
refresh_service.instance_variable_set("@commits", [
double(
diff --git a/spec/services/merge_requests/reopen_service_spec.rb b/spec/services/merge_requests/reopen_service_spec.rb
index ffc2ebb344c..2bd83dc36a8 100644
--- a/spec/services/merge_requests/reopen_service_spec.rb
+++ b/spec/services/merge_requests/reopen_service_spec.rb
@@ -23,6 +23,8 @@ RSpec.describe MergeRequests::ReopenService do
before do
allow(service).to receive(:execute_hooks)
+ merge_request.create_cleanup_schedule(scheduled_at: Time.current)
+ merge_request.update_column(:merge_ref_sha, 'abc123')
perform_enqueued_jobs do
service.execute(merge_request)
@@ -43,6 +45,14 @@ RSpec.describe MergeRequests::ReopenService do
expect(email.subject).to include(merge_request.title)
end
+ it 'destroys cleanup schedule record' do
+ expect(merge_request.reload.cleanup_schedule).to be_nil
+ end
+
+ it 'clears the cached merge_ref_sha' do
+ expect(merge_request.reload.merge_ref_sha).to be_nil
+ end
+
context 'note creation' do
it 'creates resource state event about merge_request reopen' do
event = merge_request.resource_state_events.last
diff --git a/spec/services/metrics/dashboard/panel_preview_service_spec.rb b/spec/services/metrics/dashboard/panel_preview_service_spec.rb
index d58dee3e7a3..2877d22d1f3 100644
--- a/spec/services/metrics/dashboard/panel_preview_service_spec.rb
+++ b/spec/services/metrics/dashboard/panel_preview_service_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe Metrics::Dashboard::PanelPreviewService do
title: test panel
YML
end
+
let_it_be(:dashboard) do
{
panel_groups: [
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index 1e5536a2d0b..3118956951e 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -67,147 +67,164 @@ RSpec.describe Notes::CreateService do
let(:current_user) { user }
end
end
- end
- context 'noteable highlight cache clearing' do
- let(:project_with_repo) { create(:project, :repository) }
- let(:merge_request) do
- create(:merge_request, source_project: project_with_repo,
- target_project: project_with_repo)
- end
+ it 'tracks issue comment usage data', :clean_gitlab_redis_shared_state do
+ event = Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_COMMENT_ADDED
+ counter = Gitlab::UsageDataCounters::HLLRedisCounter
- let(:position) do
- Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
- new_path: "files/ruby/popen.rb",
- old_line: nil,
- new_line: 14,
- diff_refs: merge_request.diff_refs)
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_comment_added_action).with(author: user).and_call_original
+ expect do
+ described_class.new(project, user, opts).execute
+ end.to change { counter.unique_events(event_names: event, start_date: 1.day.ago, end_date: 1.day.from_now) }.by(1)
end
- let(:new_opts) do
- opts.merge(in_reply_to_discussion_id: nil,
- type: 'DiffNote',
- noteable_type: 'MergeRequest',
- noteable_id: merge_request.id,
- position: position.to_h)
- end
+ context 'in a merge request' do
+ let_it_be(:project_with_repo) { create(:project, :repository) }
+ let_it_be(:merge_request) do
+ create(:merge_request, source_project: project_with_repo,
+ target_project: project_with_repo)
+ end
- before do
- allow_any_instance_of(Gitlab::Diff::Position)
- .to receive(:unfolded_diff?) { true }
- end
+ context 'issue comment usage data' do
+ let(:opts) do
+ { note: 'Awesome comment', noteable_type: 'MergeRequest', noteable_id: merge_request.id }
+ end
- it 'clears noteable diff cache when it was unfolded for the note position' do
- expect_any_instance_of(Gitlab::Diff::HighlightCache).to receive(:clear)
+ it 'does not track' do
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_comment_added_action)
- described_class.new(project_with_repo, user, new_opts).execute
- end
+ described_class.new(project, user, opts).execute
+ end
+ end
- it 'does not clear cache when note is not the first of the discussion' do
- prev_note =
- create(:diff_note_on_merge_request, noteable: merge_request,
- project: project_with_repo)
- reply_opts =
- opts.merge(in_reply_to_discussion_id: prev_note.discussion_id,
- type: 'DiffNote',
- noteable_type: 'MergeRequest',
- noteable_id: merge_request.id,
- position: position.to_h)
+ context 'noteable highlight cache clearing' do
+ let(:position) do
+ Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: nil,
+ new_line: 14,
+ diff_refs: merge_request.diff_refs)
+ end
- expect(merge_request).not_to receive(:diffs)
+ let(:new_opts) do
+ opts.merge(in_reply_to_discussion_id: nil,
+ type: 'DiffNote',
+ noteable_type: 'MergeRequest',
+ noteable_id: merge_request.id,
+ position: position.to_h)
+ end
- described_class.new(project_with_repo, user, reply_opts).execute
- end
- end
+ before do
+ allow_any_instance_of(Gitlab::Diff::Position)
+ .to receive(:unfolded_diff?) { true }
+ end
- context 'note diff file' do
- let(:project_with_repo) { create(:project, :repository) }
- let(:merge_request) do
- create(:merge_request,
- source_project: project_with_repo,
- target_project: project_with_repo)
- end
+ it 'clears noteable diff cache when it was unfolded for the note position' do
+ expect_any_instance_of(Gitlab::Diff::HighlightCache).to receive(:clear)
- let(:line_number) { 14 }
- let(:position) do
- Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
- new_path: "files/ruby/popen.rb",
- old_line: nil,
- new_line: line_number,
- diff_refs: merge_request.diff_refs)
- end
+ described_class.new(project_with_repo, user, new_opts).execute
+ end
- let(:previous_note) do
- create(:diff_note_on_merge_request, noteable: merge_request, project: project_with_repo)
- end
+ it 'does not clear cache when note is not the first of the discussion' do
+ prev_note =
+ create(:diff_note_on_merge_request, noteable: merge_request,
+ project: project_with_repo)
+ reply_opts =
+ opts.merge(in_reply_to_discussion_id: prev_note.discussion_id,
+ type: 'DiffNote',
+ noteable_type: 'MergeRequest',
+ noteable_id: merge_request.id,
+ position: position.to_h)
- before do
- project_with_repo.add_maintainer(user)
- end
+ expect(merge_request).not_to receive(:diffs)
- context 'when eligible to have a note diff file' do
- let(:new_opts) do
- opts.merge(in_reply_to_discussion_id: nil,
- type: 'DiffNote',
- noteable_type: 'MergeRequest',
- noteable_id: merge_request.id,
- position: position.to_h)
+ described_class.new(project_with_repo, user, reply_opts).execute
+ end
end
- it 'note is associated with a note diff file' do
- MergeRequests::MergeToRefService.new(merge_request.project, merge_request.author).execute(merge_request)
-
- note = described_class.new(project_with_repo, user, new_opts).execute
-
- expect(note).to be_persisted
- expect(note.note_diff_file).to be_present
- expect(note.diff_note_positions).to be_present
- end
- end
+ context 'note diff file' do
+ let(:line_number) { 14 }
+ let(:position) do
+ Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: nil,
+ new_line: line_number,
+ diff_refs: merge_request.diff_refs)
+ end
- context 'when DiffNote is a reply' do
- let(:new_opts) do
- opts.merge(in_reply_to_discussion_id: previous_note.discussion_id,
- type: 'DiffNote',
- noteable_type: 'MergeRequest',
- noteable_id: merge_request.id,
- position: position.to_h)
- end
+ let(:previous_note) do
+ create(:diff_note_on_merge_request, noteable: merge_request, project: project_with_repo)
+ end
- it 'note is not associated with a note diff file' do
- expect(Discussions::CaptureDiffNotePositionService).not_to receive(:new)
+ before do
+ project_with_repo.add_maintainer(user)
+ end
- note = described_class.new(project_with_repo, user, new_opts).execute
+ context 'when eligible to have a note diff file' do
+ let(:new_opts) do
+ opts.merge(in_reply_to_discussion_id: nil,
+ type: 'DiffNote',
+ noteable_type: 'MergeRequest',
+ noteable_id: merge_request.id,
+ position: position.to_h)
+ end
- expect(note).to be_persisted
- expect(note.note_diff_file).to be_nil
- end
+ it 'note is associated with a note diff file' do
+ MergeRequests::MergeToRefService.new(merge_request.project, merge_request.author).execute(merge_request)
- context 'when DiffNote from an image' do
- let(:image_position) do
- Gitlab::Diff::Position.new(old_path: "files/images/6049019_460s.jpg",
- new_path: "files/images/6049019_460s.jpg",
- width: 100,
- height: 100,
- x: 1,
- y: 100,
- diff_refs: merge_request.diff_refs,
- position_type: 'image')
- end
+ note = described_class.new(project_with_repo, user, new_opts).execute
- let(:new_opts) do
- opts.merge(in_reply_to_discussion_id: nil,
- type: 'DiffNote',
- noteable_type: 'MergeRequest',
- noteable_id: merge_request.id,
- position: image_position.to_h)
+ expect(note).to be_persisted
+ expect(note.note_diff_file).to be_present
+ expect(note.diff_note_positions).to be_present
+ end
end
- it 'note is not associated with a note diff file' do
- note = described_class.new(project_with_repo, user, new_opts).execute
-
- expect(note).to be_persisted
- expect(note.note_diff_file).to be_nil
+ context 'when DiffNote is a reply' do
+ let(:new_opts) do
+ opts.merge(in_reply_to_discussion_id: previous_note.discussion_id,
+ type: 'DiffNote',
+ noteable_type: 'MergeRequest',
+ noteable_id: merge_request.id,
+ position: position.to_h)
+ end
+
+ it 'note is not associated with a note diff file' do
+ expect(Discussions::CaptureDiffNotePositionService).not_to receive(:new)
+
+ note = described_class.new(project_with_repo, user, new_opts).execute
+
+ expect(note).to be_persisted
+ expect(note.note_diff_file).to be_nil
+ end
+
+ context 'when DiffNote from an image' do
+ let(:image_position) do
+ Gitlab::Diff::Position.new(old_path: "files/images/6049019_460s.jpg",
+ new_path: "files/images/6049019_460s.jpg",
+ width: 100,
+ height: 100,
+ x: 1,
+ y: 100,
+ diff_refs: merge_request.diff_refs,
+ position_type: 'image')
+ end
+
+ let(:new_opts) do
+ opts.merge(in_reply_to_discussion_id: nil,
+ type: 'DiffNote',
+ noteable_type: 'MergeRequest',
+ noteable_id: merge_request.id,
+ position: image_position.to_h)
+ end
+
+ it 'note is not associated with a note diff file' do
+ note = described_class.new(project_with_repo, user, new_opts).execute
+
+ expect(note).to be_persisted
+ expect(note.note_diff_file).to be_nil
+ end
+ end
end
end
end
@@ -286,7 +303,7 @@ RSpec.describe Notes::CreateService do
QuickAction.new(
action_text: "/wip",
before_action: -> {
- issuable.reload.update(title: "title")
+ issuable.reload.update!(title: "title")
},
expectation: ->(issuable, can_use_quick_action) {
expect(issuable.work_in_progress?).to eq(can_use_quick_action)
@@ -296,7 +313,7 @@ RSpec.describe Notes::CreateService do
QuickAction.new(
action_text: "/wip",
before_action: -> {
- issuable.reload.update(title: "WIP: title")
+ issuable.reload.update!(title: "WIP: title")
},
expectation: ->(noteable, can_use_quick_action) {
expect(noteable.work_in_progress?).not_to eq(can_use_quick_action)
diff --git a/spec/services/notes/destroy_service_spec.rb b/spec/services/notes/destroy_service_spec.rb
index d1076f77cec..0859c28cbe7 100644
--- a/spec/services/notes/destroy_service_spec.rb
+++ b/spec/services/notes/destroy_service_spec.rb
@@ -24,36 +24,55 @@ RSpec.describe Notes::DestroyService do
.to change { user.todos_pending_count }.from(1).to(0)
end
- context 'noteable highlight cache clearing' do
- let(:repo_project) { create(:project, :repository) }
- let(:merge_request) do
+ it 'tracks issue comment removal usage data', :clean_gitlab_redis_shared_state do
+ note = create(:note, project: project, noteable: issue)
+ event = Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_COMMENT_REMOVED
+ counter = Gitlab::UsageDataCounters::HLLRedisCounter
+
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_comment_removed_action).with(author: user).and_call_original
+ expect do
+ described_class.new(project, user).execute(note)
+ end.to change { counter.unique_events(event_names: event, start_date: 1.day.ago, end_date: 1.day.from_now) }.by(1)
+ end
+
+ context 'in a merge request' do
+ let_it_be(:repo_project) { create(:project, :repository) }
+ let_it_be(:merge_request) do
create(:merge_request, source_project: repo_project,
- target_project: repo_project)
+ target_project: repo_project)
end
- let(:note) do
+ let_it_be(:note) do
create(:diff_note_on_merge_request, project: repo_project,
- noteable: merge_request)
+ noteable: merge_request)
end
- before do
- allow(note.position).to receive(:unfolded_diff?) { true }
- end
-
- it 'clears noteable diff cache when it was unfolded for the note position' do
- expect(merge_request).to receive_message_chain(:diffs, :clear_cache)
+ it 'does not track issue comment removal usage data' do
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_comment_removed_action)
described_class.new(repo_project, user).execute(note)
end
- it 'does not clear cache when note is not the first of the discussion' do
- reply_note = create(:diff_note_on_merge_request, in_reply_to: note,
- project: repo_project,
- noteable: merge_request)
+ context 'noteable highlight cache clearing' do
+ before do
+ allow(note.position).to receive(:unfolded_diff?) { true }
+ end
+
+ it 'clears noteable diff cache when it was unfolded for the note position' do
+ expect(merge_request).to receive_message_chain(:diffs, :clear_cache)
+
+ described_class.new(repo_project, user).execute(note)
+ end
+
+ it 'does not clear cache when note is not the first of the discussion' do
+ reply_note = create(:diff_note_on_merge_request, in_reply_to: note,
+ project: repo_project,
+ noteable: merge_request)
- expect(merge_request).not_to receive(:diffs)
+ expect(merge_request).not_to receive(:diffs)
- described_class.new(repo_project, user).execute(reply_note)
+ described_class.new(repo_project, user).execute(reply_note)
+ end
end
end
end
diff --git a/spec/services/notes/update_service_spec.rb b/spec/services/notes/update_service_spec.rb
index 66efdf8abe7..e2f51c9af67 100644
--- a/spec/services/notes/update_service_spec.rb
+++ b/spec/services/notes/update_service_spec.rb
@@ -47,6 +47,22 @@ RSpec.describe Notes::UpdateService do
end
end
+ it 'does not track usage data when params is blank' do
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_comment_edited_action)
+
+ update_note({})
+ end
+
+ it 'tracks usage data', :clean_gitlab_redis_shared_state do
+ event = Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_COMMENT_EDITED
+ counter = Gitlab::UsageDataCounters::HLLRedisCounter
+
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_comment_edited_action).with(author: user).and_call_original
+ expect do
+ update_note(note: 'new text')
+ end.to change { counter.unique_events(event_names: event, start_date: 1.day.ago, end_date: 1.day.from_now) }.by(1)
+ end
+
context 'with system note' do
before do
note.update_column(:system, true)
@@ -55,6 +71,12 @@ RSpec.describe Notes::UpdateService do
it 'does not update the note' do
expect { update_note(note: 'new text') }.not_to change { note.reload.note }
end
+
+ it 'does not track usage data' do
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_comment_edited_action)
+
+ update_note(note: 'new text')
+ end
end
context 'suggestions' do
@@ -220,6 +242,12 @@ RSpec.describe Notes::UpdateService do
expect(note).not_to receive(:create_new_cross_references!)
update_note({ note: "Updated with new reference: #{issue.to_reference}" })
end
+
+ it 'does not track usage data' do
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_comment_edited_action)
+
+ update_note(note: 'new text')
+ end
end
end
end
diff --git a/spec/services/notification_recipients/build_service_spec.rb b/spec/services/notification_recipients/build_service_spec.rb
index 5c8add250c2..cc08f9fceff 100644
--- a/spec/services/notification_recipients/build_service_spec.rb
+++ b/spec/services/notification_recipients/build_service_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe NotificationRecipients::BuildService do
context 'when there are multiple subscribers' do
def create_user
subscriber = create(:user)
- issue.subscriptions.create(user: subscriber, project: project, subscribed: true)
+ issue.subscriptions.create!(user: subscriber, project: project, subscribed: true)
end
include_examples 'no N+1 queries'
@@ -96,7 +96,7 @@ RSpec.describe NotificationRecipients::BuildService do
context 'when there are multiple subscribers' do
def create_user
subscriber = create(:user)
- merge_request.subscriptions.create(user: subscriber, project: project, subscribed: true)
+ merge_request.subscriptions.create!(user: subscriber, project: project, subscribed: true)
end
include_examples 'no N+1 queries'
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index caa9961424e..f9a89c6281e 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -361,7 +361,7 @@ RSpec.describe NotificationService, :mailer do
context 'where the project has disabled the feature' do
before do
- project.update(service_desk_enabled: false)
+ project.update!(service_desk_enabled: false)
end
it_should_not_email!
@@ -453,7 +453,7 @@ RSpec.describe NotificationService, :mailer do
context 'by note' do
before do
note.author = @u_lazy_participant
- note.save
+ note.save!
end
it { expect { subject }.not_to have_enqueued_email(@u_lazy_participant.id, note.id, mail: "note_issue_email") }
@@ -467,7 +467,7 @@ RSpec.describe NotificationService, :mailer 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
+ note.project.save!
@u_watcher.notification_settings_for(note.project).participating!
@u_watcher.notification_settings_for(group).global!
@@ -834,53 +834,47 @@ RSpec.describe NotificationService, :mailer do
end
end
- context 'when notified of a new design diff note' do
+ context 'design diff note', :deliver_mails_inline do
include DesignManagementTestHelpers
let_it_be(:design) { create(:design, :with_file) }
let_it_be(:project) { design.project }
- let_it_be(:dev) { create(:user) }
- let_it_be(:stranger) { create(:user) }
+ let_it_be(:member_and_mentioned) { create(:user, developer_projects: [project]) }
+ let_it_be(:member_and_author_of_second_note) { create(:user, developer_projects: [project]) }
+ let_it_be(:member_and_not_mentioned) { create(:user, developer_projects: [project]) }
+ let_it_be(:non_member_and_mentioned) { create(:user) }
let_it_be(:note) do
create(:diff_note_on_design,
noteable: design,
- note: "Hello #{dev.to_reference}, G'day #{stranger.to_reference}")
+ note: "Hello #{member_and_mentioned.to_reference}, G'day #{non_member_and_mentioned.to_reference}")
+ end
+
+ let_it_be(:note_2) do
+ create(:diff_note_on_design, noteable: design, author: member_and_author_of_second_note)
end
- let(:mailer) { double(deliver_later: true) }
context 'design management is enabled' do
before do
enable_design_management
- project.add_developer(dev)
- allow(Notify).to receive(:note_design_email) { mailer }
- end
-
- it 'sends new note notifications' do
- expect(subject).to receive(:send_new_note_notifications).with(note)
-
- subject.new_note(note)
- end
-
- it 'sends a mail to the developer' do
- expect(Notify)
- .to receive(:note_design_email).with(dev.id, note.id, 'mentioned')
-
- subject.new_note(note)
end
- it 'does not notify non-developers' do
- expect(Notify)
- .not_to receive(:note_design_email).with(stranger.id, note.id)
+ it 'sends new note notifications', :aggregate_failures do
+ notification.new_note(note)
- subject.new_note(note)
+ should_email(design.authors.first)
+ should_email(member_and_mentioned)
+ should_email(member_and_author_of_second_note)
+ should_not_email(member_and_not_mentioned)
+ should_not_email(non_member_and_mentioned)
+ should_not_email(note.author)
end
end
context 'design management is disabled' do
- it 'does not notify the user' do
- expect(Notify).not_to receive(:note_design_email)
+ it 'does not notify anyone' do
+ notification.new_note(note)
- subject.new_note(note)
+ should_not_email_anyone
end
end
end
@@ -1719,7 +1713,7 @@ RSpec.describe NotificationService, :mailer do
before do
merge_request.author = participant
- merge_request.save
+ merge_request.save!
notification.new_merge_request(merge_request, @u_disabled)
end
@@ -1962,7 +1956,7 @@ RSpec.describe NotificationService, :mailer do
describe 'when merge_when_pipeline_succeeds is true' do
before do
- merge_request.update(
+ merge_request.update!(
merge_when_pipeline_succeeds: true,
merge_user: create(:user)
)
@@ -2312,6 +2306,26 @@ RSpec.describe NotificationService, :mailer do
end
end
+ describe '#new_instance_access_request', :deliver_mails_inline do
+ let_it_be(:user) { create(:user, :blocked_pending_approval) }
+ let_it_be(:admins) { create_list(:admin, 12, :with_sign_ins) }
+
+ subject { notification.new_instance_access_request(user) }
+
+ before do
+ reset_delivered_emails!
+ stub_application_setting(require_admin_approval_after_user_signup: true)
+ end
+
+ it 'sends notification only to a maximum of ten most recently active instance admins' do
+ ten_most_recently_active_instance_admins = User.admins.active.sort_by(&:current_sign_in_at).last(10)
+
+ subject
+
+ should_only_email(*ten_most_recently_active_instance_admins)
+ end
+ end
+
describe 'GroupMember', :deliver_mails_inline do
let(:added_user) { create(:user) }
@@ -2725,7 +2739,7 @@ RSpec.describe NotificationService, :mailer do
before do
group = create(:group)
- project.update(group: group)
+ project.update!(group: group)
create(:email, :confirmed, user: u_custom_notification_enabled, email: group_notification_email)
create(:notification_setting, user: u_custom_notification_enabled, source: group, notification_email: group_notification_email)
@@ -2761,7 +2775,7 @@ RSpec.describe NotificationService, :mailer do
before do
group = create(:group)
- project.update(group: group)
+ project.update!(group: group)
create(:email, :confirmed, user: u_member, email: group_notification_email)
create(:notification_setting, user: u_member, source: group, notification_email: group_notification_email)
end
@@ -2821,7 +2835,7 @@ RSpec.describe NotificationService, :mailer do
context 'when the creator has no read_build access' do
before do
pipeline = create_pipeline(u_member, :failed)
- project.update(public_builds: false)
+ project.update!(public_builds: false)
project.team.truncate
notification.pipeline_finished(pipeline)
end
@@ -2855,7 +2869,7 @@ RSpec.describe NotificationService, :mailer do
before do
group = create(:group)
- project.update(group: group)
+ project.update!(group: group)
create(:email, :confirmed, user: u_member, email: group_notification_email)
create(:notification_setting, user: u_member, source: group, notification_email: group_notification_email)
end
@@ -3089,37 +3103,51 @@ RSpec.describe NotificationService, :mailer do
subject.new_issue(issue, member)
end
- it 'still delivers email to admins' do
- member.update!(admin: true)
+ context 'with admin user' do
+ before do
+ member.update!(admin: true)
+ end
- expect(Notify).to receive(:new_issue_email).at_least(:once).with(member.id, issue.id, nil).and_call_original
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'still delivers email to admins' do
+ expect(Notify).to receive(:new_issue_email).at_least(:once).with(member.id, issue.id, nil).and_call_original
- subject.new_issue(issue, member)
+ subject.new_issue(issue, member)
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'does not send an email' do
+ expect(Notify).not_to receive(:new_issue_email)
+
+ subject.new_issue(issue, member)
+ end
+ end
end
end
end
describe '#prometheus_alerts_fired' do
- let!(:project) { create(:project) }
- let!(:master) { create(:user) }
- let!(:developer) { create(:user) }
- let(:alert_attributes) { build(:alert_management_alert, project: project).attributes }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:master) { create(:user) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:alert) { create(:alert_management_alert, project: project) }
before do
project.add_maintainer(master)
end
it 'sends the email to owners and masters' do
- expect(Notify).to receive(:prometheus_alert_fired_email).with(project.id, master.id, alert_attributes).and_call_original
- expect(Notify).to receive(:prometheus_alert_fired_email).with(project.id, project.owner.id, alert_attributes).and_call_original
- expect(Notify).not_to receive(:prometheus_alert_fired_email).with(project.id, developer.id, alert_attributes)
+ expect(Notify).to receive(:prometheus_alert_fired_email).with(project, master, alert).and_call_original
+ expect(Notify).to receive(:prometheus_alert_fired_email).with(project, project.owner, alert).and_call_original
+ expect(Notify).not_to receive(:prometheus_alert_fired_email).with(project, developer, alert)
- subject.prometheus_alerts_fired(project, [alert_attributes])
+ subject.prometheus_alerts_fired(project, [alert])
end
it_behaves_like 'project emails are disabled' do
let(:notification_target) { project }
- let(:notification_trigger) { subject.prometheus_alerts_fired(project, [alert_attributes]) }
+ let(:notification_trigger) { subject.prometheus_alerts_fired(project, [alert]) }
around do |example|
perform_enqueued_jobs { example.run }
@@ -3212,7 +3240,7 @@ RSpec.describe NotificationService, :mailer do
# with different notification settings
def build_group(project, visibility: :public)
group = create_nested_group(visibility)
- project.update(namespace_id: group.id)
+ project.update!(namespace_id: group.id)
# Group member: global=disabled, group=watch
@g_watcher ||= create_user_with_notification(:watch, 'group_watcher', project.group)
@@ -3277,11 +3305,11 @@ RSpec.describe NotificationService, :mailer do
end
def add_user_subscriptions(issuable)
- issuable.subscriptions.create(user: @unsubscribed_mentioned, project: project, subscribed: false)
- issuable.subscriptions.create(user: @subscriber, project: project, subscribed: true)
- issuable.subscriptions.create(user: @subscribed_participant, project: project, subscribed: true)
- issuable.subscriptions.create(user: @unsubscriber, project: project, subscribed: false)
+ issuable.subscriptions.create!(user: @unsubscribed_mentioned, project: project, subscribed: false)
+ issuable.subscriptions.create!(user: @subscriber, project: project, subscribed: true)
+ issuable.subscriptions.create!(user: @subscribed_participant, project: project, subscribed: true)
+ issuable.subscriptions.create!(user: @unsubscriber, project: project, subscribed: false)
# Make the watcher a subscriber to detect dupes
- issuable.subscriptions.create(user: @watcher_and_subscriber, project: project, subscribed: true)
+ issuable.subscriptions.create!(user: @watcher_and_subscriber, project: project, subscribed: true)
end
end
diff --git a/spec/services/packages/composer/version_parser_service_spec.rb b/spec/services/packages/composer/version_parser_service_spec.rb
index 904c75ab0a1..1a2f653c042 100644
--- a/spec/services/packages/composer/version_parser_service_spec.rb
+++ b/spec/services/packages/composer/version_parser_service_spec.rb
@@ -19,9 +19,11 @@ RSpec.describe Packages::Composer::VersionParserService do
nil | '1.7.x' | '1.7.x-dev'
'v1.0.0' | nil | '1.0.0'
'v1.0' | nil | '1.0'
+ 'v1.0.1+meta' | nil | '1.0.1+meta'
'1.0' | nil | '1.0'
'1.0.2' | nil | '1.0.2'
'1.0.2-beta2' | nil | '1.0.2-beta2'
+ '1.0.1+meta' | nil | '1.0.1+meta'
end
with_them do
diff --git a/spec/services/packages/conan/create_package_file_service_spec.rb b/spec/services/packages/conan/create_package_file_service_spec.rb
index 0e9cbba5fc1..bd6a91c883a 100644
--- a/spec/services/packages/conan/create_package_file_service_spec.rb
+++ b/spec/services/packages/conan/create_package_file_service_spec.rb
@@ -100,7 +100,7 @@ RSpec.describe Packages::Conan::CreatePackageFileService do
end
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/services/packages/create_event_service_spec.rb b/spec/services/packages/create_event_service_spec.rb
index 7e66b430a8c..55703e9127f 100644
--- a/spec/services/packages/create_event_service_spec.rb
+++ b/spec/services/packages/create_event_service_spec.rb
@@ -15,40 +15,92 @@ RSpec.describe Packages::CreateEventService do
subject { described_class.new(nil, user, params).execute }
describe '#execute' do
- shared_examples 'package event creation' do |originator_type, expected_scope|
- it 'creates the event' do
- expect { subject }.to change { Packages::Event.count }.by(1)
-
- expect(subject.originator_type).to eq(originator_type)
- expect(subject.originator).to eq(user&.id)
- expect(subject.event_scope).to eq(expected_scope)
- expect(subject.event_type).to eq(event_name)
+ shared_examples 'db package event creation' do |originator_type, expected_scope|
+ before do
+ allow(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event)
+ end
+
+ context 'with feature flag disable' do
+ before do
+ stub_feature_flags(collect_package_events: false)
+ end
+
+ it 'does not create an event object' do
+ expect { subject }.not_to change { Packages::Event.count }
+ end
+ end
+
+ context 'with feature flag enabled' do
+ before do
+ stub_feature_flags(collect_package_events: true)
+ end
+
+ it 'creates the event' do
+ expect { subject }.to change { Packages::Event.count }.by(1)
+
+ expect(subject.originator_type).to eq(originator_type)
+ expect(subject.originator).to eq(user&.id)
+ expect(subject.event_scope).to eq(expected_scope)
+ expect(subject.event_type).to eq(event_name)
+ end
+ end
+ end
+
+ shared_examples 'redis package event creation' do |originator_type, expected_scope|
+ context 'with feature flag disable' do
+ before do
+ stub_feature_flags(collect_package_events_redis: false)
+ end
+
+ it 'does not track the event' do
+ expect(::Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ subject
+ end
+ end
+
+ it 'tracks the event' do
+ expect(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(user.id, Packages::Event.allowed_event_name(expected_scope, event_name, originator_type))
+
+ subject
end
end
context 'with a user' do
let(:user) { create(:user) }
- it_behaves_like 'package event creation', 'user', 'container'
+ it_behaves_like 'db package event creation', 'user', 'container'
+ it_behaves_like 'redis package event creation', 'user', 'container'
end
context 'with a deploy token' do
let(:user) { create(:deploy_token) }
- it_behaves_like 'package event creation', 'deploy_token', 'container'
+ it_behaves_like 'db package event creation', 'deploy_token', 'container'
+ it_behaves_like 'redis package event creation', 'deploy_token', 'container'
end
context 'with no user' do
let(:user) { nil }
- it_behaves_like 'package event creation', 'guest', 'container'
+ it_behaves_like 'db package event creation', 'guest', 'container'
end
context 'with a package as scope' do
- let(:user) { nil }
let(:scope) { create(:npm_package) }
- it_behaves_like 'package event creation', 'guest', 'npm'
+ context 'as guest' do
+ let(:user) { nil }
+
+ it_behaves_like 'db package event creation', 'guest', 'npm'
+ end
+
+ context 'with user' do
+ let(:user) { create(:user) }
+
+ it_behaves_like 'db package event creation', 'user', 'npm'
+ it_behaves_like 'redis package event creation', 'user', 'npm'
+ end
end
end
end
diff --git a/spec/services/packages/create_package_file_service_spec.rb b/spec/services/packages/create_package_file_service_spec.rb
index 93dde54916a..12fd1039d30 100644
--- a/spec/services/packages/create_package_file_service_spec.rb
+++ b/spec/services/packages/create_package_file_service_spec.rb
@@ -2,7 +2,10 @@
require 'spec_helper'
RSpec.describe Packages::CreatePackageFileService do
- let(:package) { create(:maven_package) }
+ let_it_be(:package) { create(:maven_package) }
+ let_it_be(:user) { create(:user) }
+
+ subject { described_class.new(package, params) }
describe '#execute' do
context 'with valid params' do
@@ -14,7 +17,7 @@ RSpec.describe Packages::CreatePackageFileService do
end
it 'creates a new package file' do
- package_file = described_class.new(package, params).execute
+ package_file = subject.execute
expect(package_file).to be_valid
expect(package_file.file_name).to eq('foo.jar')
@@ -29,9 +32,17 @@ RSpec.describe Packages::CreatePackageFileService do
end
it 'raises an error' do
- service = described_class.new(package, params)
+ expect { subject.execute }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+
+ context 'with a build' do
+ let_it_be(:pipeline) { create(:ci_pipeline, user: user) }
+ let(:build) { double('build', pipeline: pipeline) }
+ let(:params) { { file: Tempfile.new, file_name: 'foo.jar', build: build } }
- expect { service.execute }.to raise_error(ActiveRecord::RecordInvalid)
+ it 'creates a build_info' do
+ expect { subject.execute }.to change { Packages::PackageFileBuildInfo.count }.by(1)
end
end
end
diff --git a/spec/services/packages/debian/extract_deb_metadata_service_spec.rb b/spec/services/packages/debian/extract_deb_metadata_service_spec.rb
new file mode 100644
index 00000000000..33059adf8a2
--- /dev/null
+++ b/spec/services/packages/debian/extract_deb_metadata_service_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::ExtractDebMetadataService do
+ subject { described_class.new(file_path) }
+
+ let(:file_name) { 'libsample0_1.2.3~alpha2_amd64.deb' }
+ let(:file_path) { "spec/fixtures/packages/debian/#{file_name}" }
+
+ context 'with correct file' do
+ it 'return as expected' do
+ expected = {
+ 'Package': 'libsample0',
+ 'Source': 'sample',
+ 'Version': '1.2.3~alpha2',
+ 'Architecture': 'amd64',
+ 'Maintainer': 'John Doe <john.doe@example.com>',
+ 'Installed-Size': '7',
+ 'Section': 'libs',
+ 'Priority': 'optional',
+ 'Multi-Arch': 'same',
+ 'Homepage': 'https://gitlab.com/',
+ 'Description': "Some mostly empty lib\nUsed in GitLab tests.\n\nTesting another paragraph."
+ }
+
+ expect(subject.execute).to eq expected
+ end
+ end
+
+ context 'with incorrect file' do
+ let(:file_name) { 'README.md' }
+
+ it 'raise error' do
+ expect {subject.execute}.to raise_error(described_class::CommandFailedError, /is not a Debian format archive/i)
+ end
+ end
+end
diff --git a/spec/services/packages/debian/parse_debian822_service_spec.rb b/spec/services/packages/debian/parse_debian822_service_spec.rb
new file mode 100644
index 00000000000..b67daca89c4
--- /dev/null
+++ b/spec/services/packages/debian/parse_debian822_service_spec.rb
@@ -0,0 +1,148 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::ParseDebian822Service do
+ subject { described_class.new(input) }
+
+ context 'with dpkg-deb --field output' do
+ let(:input) do
+ <<~HEREDOC
+ Package: libsample0
+ Source: sample
+ Version: 1.2.3~alpha2
+ Architecture: amd64
+ Maintainer: John Doe <john.doe@example.com>
+ Installed-Size: 9
+ Section: libs
+ Priority: optional
+ Multi-Arch: same
+ Homepage: https://gitlab.com/
+ Description: Some mostly empty lib
+ Used in GitLab tests.
+ .
+ Testing another paragraph.
+ HEREDOC
+ end
+
+ it 'return as expected, preserving order' do
+ expected = {
+ 'Package: libsample0' => {
+ 'Package': 'libsample0',
+ 'Source': 'sample',
+ 'Version': '1.2.3~alpha2',
+ 'Architecture': 'amd64',
+ 'Maintainer': 'John Doe <john.doe@example.com>',
+ 'Installed-Size': '9',
+ 'Section': 'libs',
+ 'Priority': 'optional',
+ 'Multi-Arch': 'same',
+ 'Homepage': 'https://gitlab.com/',
+ 'Description': "Some mostly empty lib\nUsed in GitLab tests.\n\nTesting another paragraph."
+ }
+ }
+
+ expect(subject.execute.to_s).to eq(expected.to_s)
+ end
+ end
+
+ context 'with control file' do
+ let(:input) { fixture_file('packages/debian/sample/debian/control') }
+
+ it 'return as expected, preserving order' do
+ expected = {
+ 'Source: sample' => {
+ 'Source': 'sample',
+ 'Priority': 'optional',
+ 'Maintainer': 'John Doe <john.doe@example.com>',
+ 'Build-Depends': 'debhelper-compat (= 13)',
+ 'Standards-Version': '4.5.0',
+ 'Section': 'libs',
+ 'Homepage': 'https://gitlab.com/',
+ # 'Vcs-Browser': 'https://salsa.debian.org/debian/sample-1.2.3',
+ # '#Vcs-Git': 'https://salsa.debian.org/debian/sample-1.2.3.git',
+ 'Rules-Requires-Root': 'no'
+ },
+ 'Package: sample-dev' => {
+ 'Package': 'sample-dev',
+ 'Section': 'libdevel',
+ 'Architecture': 'any',
+ 'Multi-Arch': 'same',
+ 'Depends': 'libsample0 (= ${binary:Version}), ${misc:Depends}',
+ 'Description': "Some mostly empty developpement files\nUsed in GitLab tests.\n\nTesting another paragraph."
+ },
+ 'Package: libsample0' => {
+ 'Package': 'libsample0',
+ 'Architecture': 'any',
+ 'Multi-Arch': 'same',
+ 'Depends': '${shlibs:Depends}, ${misc:Depends}',
+ 'Description': "Some mostly empty lib\nUsed in GitLab tests.\n\nTesting another paragraph."
+ },
+ 'Package: sample-udeb' => {
+ 'Package': 'sample-udeb',
+ 'Package-Type': 'udeb',
+ 'Architecture': 'any',
+ 'Depends': 'installed-base',
+ 'Description': 'Some mostly empty udeb'
+ }
+ }
+
+ expect(subject.execute.to_s).to eq(expected.to_s)
+ end
+ end
+
+ context 'with empty input' do
+ let(:input) { '' }
+
+ it 'return a empty hash' do
+ expect(subject.execute).to eq({})
+ end
+ end
+
+ context 'with unexpected continuation line' do
+ let(:input) { ' continuation' }
+
+ it 'raise error' do
+ expect {subject.execute}.to raise_error(described_class::InvalidDebian822Error, 'Parse error. Unexpected continuation line')
+ end
+ end
+
+ context 'with duplicate field' do
+ let(:input) do
+ <<~HEREDOC
+ Package: libsample0
+ Source: sample
+ Source: sample
+ HEREDOC
+ end
+
+ it 'raise error' do
+ expect {subject.execute}.to raise_error(described_class::InvalidDebian822Error, "Duplicate field 'Source' in section 'Package: libsample0'")
+ end
+ end
+
+ context 'with incorrect input' do
+ let(:input) do
+ <<~HEREDOC
+ Hello
+ HEREDOC
+ end
+
+ it 'raise error' do
+ expect {subject.execute}.to raise_error(described_class::InvalidDebian822Error, 'Parse error on line Hello')
+ end
+ end
+
+ context 'with duplicate section' do
+ let(:input) do
+ <<~HEREDOC
+ Package: libsample0
+
+ Package: libsample0
+ HEREDOC
+ end
+
+ it 'raise error' do
+ expect {subject.execute}.to raise_error(described_class::InvalidDebian822Error, "Duplicate section 'Package: libsample0'")
+ end
+ end
+end
diff --git a/spec/services/packages/generic/create_package_file_service_spec.rb b/spec/services/packages/generic/create_package_file_service_spec.rb
index 0ae109ef996..907483e3d7f 100644
--- a/spec/services/packages/generic/create_package_file_service_spec.rb
+++ b/spec/services/packages/generic/create_package_file_service_spec.rb
@@ -5,6 +5,8 @@ require 'spec_helper'
RSpec.describe Packages::Generic::CreatePackageFileService do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
+ let_it_be(:pipeline) { create(:ci_pipeline, user: user) }
+ let(:build) { double('build', pipeline: pipeline) }
describe '#execute' do
let(:sha256) { '440e5e148a25331bbd7991575f7d54933c0ebf6cc735a18ee5066ac1381bb590' }
@@ -16,7 +18,8 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
package_name: 'mypackage',
package_version: '0.0.1',
file: file,
- file_name: 'myfile.tar.gz.1'
+ file_name: 'myfile.tar.gz.1',
+ build: build
}
end
@@ -41,6 +44,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
service = described_class.new(project, user, params)
expect { service.execute }.to change { package.package_files.count }.by(1)
+ .and change { Packages::PackageFileBuildInfo.count }.by(1)
package_file = package.package_files.last
aggregate_failures do
diff --git a/spec/services/packages/generic/find_or_create_package_service_spec.rb b/spec/services/packages/generic/find_or_create_package_service_spec.rb
index 5a9b8b03279..a045cb36418 100644
--- a/spec/services/packages/generic/find_or_create_package_service_spec.rb
+++ b/spec/services/packages/generic/find_or_create_package_service_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do
expect(package.creator).to eq(user)
expect(package.name).to eq('mypackage')
expect(package.version).to eq('0.0.1')
- expect(package.build_info).to be_nil
+ expect(package.original_build_info).to be_nil
end
end
@@ -42,7 +42,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do
expect(package.creator).to eq(user)
expect(package.name).to eq('mypackage')
expect(package.version).to eq('0.0.1')
- expect(package.build_info.pipeline).to eq(ci_build.pipeline)
+ expect(package.original_build_info.pipeline).to eq(ci_build.pipeline)
end
end
end
@@ -60,7 +60,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do
expect(found_package).to eq(package)
end.not_to change { project.packages.generic.count }
- expect(package.reload.build_info).to be_nil
+ expect(package.reload.original_build_info).to be_nil
end
end
@@ -68,7 +68,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do
let(:pipeline) { create(:ci_pipeline, project: project) }
before do
- package.create_build_info!(pipeline: pipeline)
+ package.build_infos.create!(pipeline: pipeline)
end
it 'finds the package and does not change package build info even if build is provided' do
@@ -80,7 +80,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do
expect(found_package).to eq(package)
end.not_to change { project.packages.generic.count }
- expect(package.reload.build_info.pipeline).to eq(pipeline)
+ expect(package.reload.original_build_info.pipeline).to eq(pipeline)
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 7ec368aa00f..11bf00c1399 100644
--- a/spec/services/packages/maven/create_package_service_spec.rb
+++ b/spec/services/packages/maven/create_package_service_spec.rb
@@ -33,8 +33,6 @@ RSpec.describe Packages::Maven::CreatePackageService do
expect(package.maven_metadatum.app_version).to eq(version)
end
- it_behaves_like 'assigns build to package'
-
it_behaves_like 'assigns the package creator'
end
diff --git a/spec/services/packages/maven/find_or_create_package_service_spec.rb b/spec/services/packages/maven/find_or_create_package_service_spec.rb
index 4406e4037e2..2eaad7db445 100644
--- a/spec/services/packages/maven/find_or_create_package_service_spec.rb
+++ b/spec/services/packages/maven/find_or_create_package_service_spec.rb
@@ -10,11 +10,12 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do
let(:version) { '1.0.0' }
let(:file_name) { 'test.jar' }
let(:param_path) { "#{path}/#{version}" }
+ let(:params) { { path: param_path, file_name: file_name } }
describe '#execute' do
using RSpec::Parameterized::TableSyntax
- subject { described_class.new(project, user, { path: param_path, file_name: file_name }).execute }
+ subject { described_class.new(project, user, params).execute }
RSpec.shared_examples 'reuse existing package' do
it { expect { subject}.not_to change { Packages::Package.count } }
@@ -23,7 +24,7 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do
end
RSpec.shared_examples 'create package' do
- it { expect { subject}.to change { Packages::Package.count }.by(1) }
+ it { expect { subject }.to change { Packages::Package.count }.by(1) }
it 'sets the proper name and version' do
pkg = subject
@@ -31,6 +32,8 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do
expect(pkg.name).to eq(path)
expect(pkg.version).to eq(version)
end
+
+ it_behaves_like 'assigns build to package'
end
context 'path with version' do
@@ -77,5 +80,15 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do
end
end
end
+
+ context 'with a build' do
+ let_it_be(:pipeline) { create(:ci_pipeline, user: user) }
+ let(:build) { double('build', pipeline: pipeline) }
+ let(:params) { { path: param_path, file_name: file_name, build: build } }
+
+ it 'creates a build_info' do
+ expect { subject }.to change { Packages::BuildInfo.count }.by(1)
+ end
+ end
end
end
diff --git a/spec/services/packages/npm/create_package_service_spec.rb b/spec/services/packages/npm/create_package_service_spec.rb
index c8431c640da..6db3777cde8 100644
--- a/spec/services/packages/npm/create_package_service_spec.rb
+++ b/spec/services/packages/npm/create_package_service_spec.rb
@@ -48,7 +48,16 @@ RSpec.describe Packages::Npm::CreatePackageService do
context 'scoped package' do
it_behaves_like 'valid package'
- it_behaves_like 'assigns build to package'
+ context 'with build info' do
+ let(:job) { create(:ci_build, user: user) }
+ let(:params) { super().merge(build: job) }
+
+ it_behaves_like 'assigns build to package'
+
+ it 'creates a package file build info' do
+ expect { subject }.to change { Packages::PackageFileBuildInfo.count }.by(1)
+ end
+ end
end
context 'invalid package name' do
diff --git a/spec/services/pages/destroy_deployments_service_spec.rb b/spec/services/pages/destroy_deployments_service_spec.rb
new file mode 100644
index 00000000000..0f8e8b6573e
--- /dev/null
+++ b/spec/services/pages/destroy_deployments_service_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Pages::DestroyDeploymentsService do
+ let(:project) { create(:project) }
+ let!(:old_deployments) { create_list(:pages_deployment, 2, project: project) }
+ let!(:last_deployment) { create(:pages_deployment, project: project) }
+ let!(:newer_deployment) { create(:pages_deployment, project: project) }
+ let!(:deployment_from_another_project) { create(:pages_deployment) }
+
+ it 'destroys all deployments of the project' do
+ expect do
+ described_class.new(project).execute
+ end.to change { PagesDeployment.count }.by(-4)
+
+ expect(deployment_from_another_project.reload).to be
+ end
+
+ it 'destroy only deployments older than last deployment if it is provided' do
+ expect do
+ described_class.new(project, last_deployment.id).execute
+ end.to change { PagesDeployment.count }.by(-2)
+
+ expect(last_deployment.reload).to be
+ expect(newer_deployment.reload).to be
+ expect(deployment_from_another_project.reload).to be
+ end
+end
diff --git a/spec/services/personal_access_tokens/create_service_spec.rb b/spec/services/personal_access_tokens/create_service_spec.rb
index 475ade95948..842bebd13a1 100644
--- a/spec/services/personal_access_tokens/create_service_spec.rb
+++ b/spec/services/personal_access_tokens/create_service_spec.rb
@@ -3,21 +3,59 @@
require 'spec_helper'
RSpec.describe PersonalAccessTokens::CreateService do
+ shared_examples_for 'a successfully created token' do
+ it 'creates personal access token record' do
+ expect(subject.success?).to be true
+ expect(token.name).to eq(params[:name])
+ expect(token.impersonation).to eq(params[:impersonation])
+ expect(token.scopes).to eq(params[:scopes])
+ expect(token.expires_at).to eq(params[:expires_at])
+ expect(token.user).to eq(user)
+ end
+
+ it 'logs the event' do
+ expect(Gitlab::AppLogger).to receive(:info).with(/PAT CREATION: created_by: '#{current_user.username}', created_for: '#{user.username}', token_id: '\d+'/)
+
+ subject
+ end
+ end
+
+ shared_examples_for 'an unsuccessfully created token' do
+ it { expect(subject.success?).to be false }
+ it { expect(subject.message).to eq('Not permitted to create') }
+ it { expect(token).to be_nil }
+ end
+
describe '#execute' do
- context 'with valid params' do
- it 'creates personal access token record' do
- user = create(:user)
- params = { name: 'Test token', impersonation: true, scopes: [:api], expires_at: Date.today + 1.month }
-
- response = described_class.new(user, params).execute
- personal_access_token = response.payload[:personal_access_token]
-
- expect(response.success?).to be true
- expect(personal_access_token.name).to eq(params[:name])
- expect(personal_access_token.impersonation).to eq(params[:impersonation])
- expect(personal_access_token.scopes).to eq(params[:scopes])
- expect(personal_access_token.expires_at).to eq(params[:expires_at])
- expect(personal_access_token.user).to eq(user)
+ subject { service.execute }
+
+ let(:current_user) { create(:user) }
+ let(:user) { create(:user) }
+ let(:params) { { name: 'Test token', impersonation: false, scopes: [:api], expires_at: Date.today + 1.month } }
+ let(:service) { described_class.new(current_user: current_user, target_user: user, params: params) }
+ let(:token) { subject.payload[:personal_access_token] }
+
+ context 'when current_user is an administrator' do
+ let(:current_user) { create(:admin) }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it_behaves_like 'a successfully created token'
+ end
+
+ context 'when admin mode is disabled' do
+ it_behaves_like 'an unsuccessfully created token'
+ end
+ end
+
+ context 'when current_user is not an administrator' do
+ context 'target_user is not the same as current_user' do
+ it_behaves_like 'an unsuccessfully created token'
+ end
+
+ context 'target_user is same as current_user' do
+ let(:current_user) { user }
+
+ it_behaves_like 'a successfully created token'
end
end
end
diff --git a/spec/services/personal_access_tokens/revoke_service_spec.rb b/spec/services/personal_access_tokens/revoke_service_spec.rb
index 5afa43cef76..a25484e218e 100644
--- a/spec/services/personal_access_tokens/revoke_service_spec.rb
+++ b/spec/services/personal_access_tokens/revoke_service_spec.rb
@@ -6,6 +6,11 @@ RSpec.describe PersonalAccessTokens::RevokeService do
shared_examples_for 'a successfully revoked token' do
it { expect(subject.success?).to be true }
it { expect(service.token.revoked?).to be true }
+ it 'logs the event' do
+ expect(Gitlab::AppLogger).to receive(:info).with(/PAT REVOCATION: revoked_by: '#{current_user.username}', revoked_for: '#{token.user.username}', token_id: '\d+'/)
+
+ subject
+ end
end
shared_examples_for 'an unsuccessfully revoked token' do
@@ -19,10 +24,19 @@ RSpec.describe PersonalAccessTokens::RevokeService do
let(:service) { described_class.new(current_user, token: token) }
context 'when current_user is an administrator' do
- let_it_be(:current_user) { create(:admin) }
- let_it_be(:token) { create(:personal_access_token) }
+ context 'when admin mode is enabled', :enable_admin_mode do
+ let_it_be(:current_user) { create(:admin) }
+ let_it_be(:token) { create(:personal_access_token) }
+
+ it_behaves_like 'a successfully revoked token'
+ end
+
+ context 'when admin mode is disabled' do
+ let_it_be(:current_user) { create(:admin) }
+ let_it_be(:token) { create(:personal_access_token) }
- it_behaves_like 'a successfully revoked token'
+ it_behaves_like 'an unsuccessfully revoked token'
+ end
end
context 'when current_user is not an administrator' do
diff --git a/spec/services/post_receive_service_spec.rb b/spec/services/post_receive_service_spec.rb
index c726e1851a7..7c4b7f51cc3 100644
--- a/spec/services/post_receive_service_spec.rb
+++ b/spec/services/post_receive_service_spec.rb
@@ -232,6 +232,49 @@ RSpec.describe PostReceiveService do
end
end
+ context "broadcast message has a target_path" do
+ let!(:older_scoped_message) do
+ create(:broadcast_message, message: "Old top secret", target_path: "/company/sekrit-project")
+ end
+
+ let!(:latest_scoped_message) do
+ create(:broadcast_message, message: "Top secret", target_path: "/company/sekrit-project")
+ end
+
+ let!(:unscoped_message) do
+ create(:broadcast_message, message: "Hi")
+ end
+
+ context "no project path matches" do
+ it "does not output the scoped broadcast messages" do
+ expect(subject).not_to include(build_alert_message(older_scoped_message.message))
+ expect(subject).not_to include(build_alert_message(latest_scoped_message.message))
+ end
+
+ it "does output another message that doesn't have a target_path" do
+ expect(subject).to include(build_alert_message(unscoped_message.message))
+ end
+ end
+
+ context "project path matches" do
+ before do
+ allow(project).to receive(:full_path).and_return("/company/sekrit-project")
+ end
+
+ it "does output the latest scoped broadcast message" do
+ expect(subject).to include(build_alert_message(latest_scoped_message.message))
+ end
+
+ it "does not output the older scoped broadcast message" do
+ expect(subject).not_to include(build_alert_message(older_scoped_message.message))
+ end
+
+ it "does not output another message that doesn't have a target_path" do
+ expect(subject).not_to include(build_alert_message(unscoped_message.message))
+ end
+ end
+ end
+
context 'with a redirected data' do
it 'returns redirected message on the response' do
project_moved = Gitlab::Checks::ProjectMoved.new(project.repository, user, 'http', 'foo/baz')
diff --git a/spec/services/projects/alerting/notify_service_spec.rb b/spec/services/projects/alerting/notify_service_spec.rb
index 809b12910a1..4674f614cf1 100644
--- a/spec/services/projects/alerting/notify_service_spec.rb
+++ b/spec/services/projects/alerting/notify_service_spec.rb
@@ -34,13 +34,11 @@ RSpec.describe Projects::Alerting::NotifyService do
let(:payload) { ActionController::Parameters.new(payload_raw).permit! }
- subject { service.execute(token) }
-
- context 'with activated Alerts Service' do
- let_it_be_with_reload(:alerts_service) { create(:alerts_service, project: project) }
+ subject { service.execute(token, nil) }
+ shared_examples 'notifcations are handled correctly' do
context 'with valid token' do
- let(:token) { alerts_service.token }
+ let(:token) { integration.token }
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 }
@@ -131,6 +129,12 @@ RSpec.describe Projects::Alerting::NotifyService do
it { expect { subject }.to change { issue.reload.state }.from('opened').to('closed') }
it { expect { subject }.to change(ResourceStateEvent, :count).by(1) }
end
+
+ context 'with issue enabled' do
+ let(:issue_enabled) { true }
+
+ it_behaves_like 'does not process incident issues'
+ end
end
end
@@ -197,7 +201,7 @@ RSpec.describe Projects::Alerting::NotifyService do
it 'creates a system note corresponding to alert creation' do
expect { subject }.to change(Note, :count).by(1)
- expect(Note.last.note).to include('Generic Alert Endpoint')
+ expect(Note.last.note).to include(source)
end
end
end
@@ -247,10 +251,20 @@ RSpec.describe Projects::Alerting::NotifyService do
it_behaves_like 'does not process incident issues due to error', http_status: :unauthorized
it_behaves_like 'does not an create alert management alert'
end
+ end
+
+ context 'with an HTTP Integration' do
+ let_it_be_with_reload(:integration) { create(:alert_management_http_integration, project: project) }
+
+ subject { service.execute(token, integration) }
+
+ it_behaves_like 'notifcations are handled correctly' do
+ let(:source) { integration.name }
+ end
- context 'with deactivated Alerts Service' do
+ context 'with deactivated HTTP Integration' do
before do
- alerts_service.update!(active: false)
+ integration.update!(active: false)
end
it_behaves_like 'does not process incident issues due to error', http_status: :forbidden
diff --git a/spec/services/projects/autocomplete_service_spec.rb b/spec/services/projects/autocomplete_service_spec.rb
index aff1aa41091..ef7741c2d0f 100644
--- a/spec/services/projects/autocomplete_service_spec.rb
+++ b/spec/services/projects/autocomplete_service_spec.rb
@@ -79,14 +79,28 @@ RSpec.describe Projects::AutocompleteService do
expect(issues.count).to eq 3
end
- it 'lists all project issues for admin' do
- autocomplete = described_class.new(project, admin)
- issues = autocomplete.issues.map(&:iid)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'lists all project issues for admin', :enable_admin_mode do
+ autocomplete = described_class.new(project, admin)
+ issues = autocomplete.issues.map(&:iid)
+
+ expect(issues).to include issue.iid
+ expect(issues).to include security_issue_1.iid
+ expect(issues).to include security_issue_2.iid
+ expect(issues.count).to eq 3
+ end
+ end
- expect(issues).to include issue.iid
- expect(issues).to include security_issue_1.iid
- expect(issues).to include security_issue_2.iid
- expect(issues.count).to eq 3
+ context 'when admin mode is disabled' do
+ it 'does not list project confidential issues for admin' do
+ autocomplete = described_class.new(project, admin)
+ issues = autocomplete.issues.map(&:iid)
+
+ expect(issues).to include issue.iid
+ expect(issues).not_to include security_issue_1.iid
+ expect(issues).not_to include security_issue_2.iid
+ expect(issues.count).to eq 1
+ end
end
end
end
diff --git a/spec/services/projects/cleanup_service_spec.rb b/spec/services/projects/cleanup_service_spec.rb
index 7c28b729e84..6fd29813d98 100644
--- a/spec/services/projects/cleanup_service_spec.rb
+++ b/spec/services/projects/cleanup_service_spec.rb
@@ -3,14 +3,84 @@
require 'spec_helper'
RSpec.describe Projects::CleanupService do
- let(:project) { create(:project, :repository, bfg_object_map: fixture_file_upload('spec/fixtures/bfg_object_map.txt')) }
- let(:object_map) { project.bfg_object_map }
+ subject(:service) { described_class.new(project) }
- let(:cleaner) { service.__send__(:repository_cleaner) }
+ describe '.enqueue' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
- subject(:service) { described_class.new(project) }
+ let(:object_map_file) { fixture_file_upload('spec/fixtures/bfg_object_map.txt') }
+
+ subject(:enqueue) { described_class.enqueue(project, user, object_map_file) }
+
+ it 'makes the repository read-only' do
+ expect { enqueue }
+ .to change(project, :repository_read_only?)
+ .from(false)
+ .to(true)
+ end
+
+ it 'sets the bfg_object_map of the project' do
+ enqueue
+
+ expect(project.bfg_object_map.read).to eq(object_map_file.read)
+ end
+
+ it 'enqueues a RepositoryCleanupWorker' do
+ enqueue
+
+ expect(RepositoryCleanupWorker.jobs.count).to eq(1)
+ end
+
+ it 'returns success' do
+ expect(enqueue[:status]).to eq(:success)
+ end
+
+ it 'returns an error if making the repository read-only fails' do
+ project.set_repository_read_only!
+
+ expect(enqueue[:status]).to eq(:error)
+ end
+
+ it 'returns an error if updating the project fails' do
+ expect_next_instance_of(Projects::UpdateService) do |service|
+ expect(service).to receive(:execute).and_return(status: :error)
+ end
+
+ expect(enqueue[:status]).to eq(:error)
+ expect(project.reload.repository_read_only?).to be_falsy
+ end
+ end
+
+ describe '.cleanup_after' do
+ let(:project) { create(:project, :repository, bfg_object_map: fixture_file_upload('spec/fixtures/bfg_object_map.txt')) }
+
+ subject(:cleanup_after) { described_class.cleanup_after(project) }
+
+ before do
+ project.set_repository_read_only!
+ end
+
+ it 'sets the repository read-write' do
+ expect { cleanup_after }.to change(project, :repository_read_only?).from(true).to(false)
+ end
+
+ it 'removes the BFG object map' do
+ cleanup_after
+
+ expect(project.bfg_object_map).not_to be_exist
+ end
+ end
describe '#execute' do
+ let(:project) { create(:project, :repository, bfg_object_map: fixture_file_upload('spec/fixtures/bfg_object_map.txt')) }
+ let(:object_map) { project.bfg_object_map }
+ let(:cleaner) { service.__send__(:repository_cleaner) }
+
+ before do
+ project.set_repository_read_only!
+ end
+
it 'runs the apply_bfg_object_map_stream gitaly RPC' do
expect(cleaner).to receive(:apply_bfg_object_map_stream).with(kind_of(IO))
@@ -19,7 +89,7 @@ RSpec.describe Projects::CleanupService do
it 'runs garbage collection on the repository' do
expect_next_instance_of(GitGarbageCollectWorker) do |worker|
- expect(worker).to receive(:perform).with(project.id, :gc, "project_cleanup:gc:#{project.id}")
+ expect(worker).to receive(:perform).with(project.id, :prune, "project_cleanup:gc:#{project.id}")
end
service.execute
@@ -37,6 +107,13 @@ RSpec.describe Projects::CleanupService do
expect(object_map.exists?).to be_falsy
end
+ it 'makes the repository read-write again' do
+ expect { service.execute }
+ .to change(project, :repository_read_only?)
+ .from(true)
+ .to(false)
+ end
+
context 'with a tainted merge request diff' do
let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let(:diff) { merge_request.merge_request_diff }
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 c3ae26b1f05..a012ec29be5 100644
--- a/spec/services/projects/container_repository/delete_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/delete_tags_service_spec.rb
@@ -27,13 +27,17 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
end
end
- RSpec.shared_examples 'logging an error response' do |message: 'could not delete tags'|
+ RSpec.shared_examples 'logging an error response' do |message: 'could not delete tags', extra_log: {}|
it 'logs an error message' do
- expect(service).to receive(:log_error).with(
- service_class: 'Projects::ContainerRepository::DeleteTagsService',
- message: message,
- container_repository_id: repository.id
- )
+ log_data = {
+ service_class: 'Projects::ContainerRepository::DeleteTagsService',
+ message: message,
+ container_repository_id: repository.id
+ }
+
+ log_data.merge!(extra_log) if extra_log.any?
+
+ expect(service).to receive(:log_error).with(log_data)
subject
end
@@ -115,7 +119,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
it { is_expected.to include(status: :error, message: 'timeout while deleting tags') }
- it_behaves_like 'logging an error response', message: 'timeout while deleting tags'
+ it_behaves_like 'logging an error response', message: 'timeout while deleting tags', extra_log: { deleted_tags_count: 0 }
end
end
end
diff --git a/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb b/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb
index 3bbcec8775e..988971171fc 100644
--- a/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb
@@ -67,7 +67,7 @@ RSpec.describe Projects::ContainerRepository::Gitlab::DeleteTagsService do
stub_delete_reference_requests('A' => 200)
end
- it { is_expected.to include(status: :error, message: 'timeout while deleting tags') }
+ it { is_expected.to eq(status: :error, message: 'timeout while deleting tags', deleted: ['A']) }
it 'tracks the exception' do
expect(::Gitlab::ErrorTracking)
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index d959cc87901..6c0e6654622 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -72,14 +72,25 @@ RSpec.describe Projects::CreateService, '#execute' do
end
context "admin creates project with other user's namespace_id" do
- it 'sets the correct permissions' do
- admin = create(:admin)
- project = create_project(admin, opts)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'sets the correct permissions' do
+ admin = create(:admin)
+ project = create_project(admin, opts)
- expect(project).to be_persisted
- expect(project.owner).to eq(user)
- expect(project.team.maintainers).to contain_exactly(user)
- expect(project.namespace).to eq(user.namespace)
+ expect(project).to be_persisted
+ expect(project.owner).to eq(user)
+ expect(project.team.maintainers).to contain_exactly(user)
+ expect(project.namespace).to eq(user.namespace)
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'is not allowed' do
+ admin = create(:admin)
+ project = create_project(admin, opts)
+
+ expect(project).not_to be_persisted
+ end
end
end
@@ -336,7 +347,15 @@ RSpec.describe Projects::CreateService, '#execute' do
)
end
- it 'allows a restricted visibility level for admins' do
+ it 'does not allow a restricted visibility level for admins when admin mode is disabled' do
+ admin = create(:admin)
+ project = create_project(admin, opts)
+
+ expect(project.errors.any?).to be(true)
+ expect(project.saved?).to be_falsey
+ end
+
+ it 'allows a restricted visibility level for admins when admin mode is enabled', :enable_admin_mode do
admin = create(:admin)
project = create_project(admin, opts)
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 cfe8e863223..1b829df6e6a 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
@@ -241,18 +241,6 @@ RSpec.describe Projects::LfsPointers::LfsDownloadService do
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
diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb
index d3eb84a3137..d2c6c0eb971 100644
--- a/spec/services/projects/update_pages_service_spec.rb
+++ b/spec/services/projects/update_pages_service_spec.rb
@@ -27,7 +27,7 @@ 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) }
+ let!(:artifacts_archive) { create(:ci_job_artifact, :correct_checksum, file: file, job: build) }
before do
create(:ci_job_artifact, file_type: :metadata, file_format: :gzip, file: metadata, job: build)
@@ -66,9 +66,45 @@ RSpec.describe Projects::UpdatePagesService do
expect(deployment.size).to eq(file.size)
expect(deployment.file).to be
+ expect(deployment.file_count).to eq(3)
+ expect(deployment.file_sha256).to eq(artifacts_archive.file_sha256)
expect(project.pages_metadatum.reload.pages_deployment_id).to eq(deployment.id)
end
+ it 'does not fail if pages_metadata is absent' do
+ project.pages_metadatum.destroy!
+ project.reload
+
+ expect do
+ expect(execute).to eq(:success)
+ end.to change { project.pages_deployments.count }.by(1)
+
+ expect(project.pages_metadatum.reload.pages_deployment).to eq(project.pages_deployments.last)
+ end
+
+ context 'when there is an old pages deployment' do
+ let!(:old_deployment_from_another_project) { create(:pages_deployment) }
+ let!(:old_deployment) { create(:pages_deployment, project: project) }
+
+ it 'schedules a destruction of older deployments' do
+ expect(DestroyPagesDeploymentsWorker).to(
+ receive(:perform_in).with(described_class::OLD_DEPLOYMENTS_DESTRUCTION_DELAY,
+ project.id,
+ instance_of(Integer))
+ )
+
+ execute
+ end
+
+ it 'removes older deployments', :sidekiq_inline do
+ expect do
+ execute
+ end.not_to change { PagesDeployment.count } # it creates one and deletes one
+
+ expect(PagesDeployment.find_by_id(old_deployment.id)).to be_nil
+ end
+ end
+
it 'does not create deployment when zip_pages_deployments feature flag is disabled' do
stub_feature_flags(zip_pages_deployments: false)
@@ -188,6 +224,25 @@ RSpec.describe Projects::UpdatePagesService do
end
end
+ # this situation should never happen in real life because all new archives have sha256
+ # and we only use new archives
+ # this test is here just to clarify that this behavior is intentional
+ context 'when artifacts archive does not have sha256' do
+ let!(:artifacts_archive) { create(:ci_job_artifact, file: file, job: build) }
+
+ before do
+ create(:ci_job_artifact, file_type: :metadata, file_format: :gzip, file: metadata, job: build)
+
+ build.reload
+ end
+
+ it 'fails with exception raised' do
+ expect do
+ execute
+ end.to raise_error("Validation failed: File sha256 can't be blank")
+ end
+ end
+
it 'fails to remove project pages when no pages is deployed' do
expect(PagesWorker).not_to receive(:perform_in)
expect(project.pages_deployed?).to be_falsey
@@ -210,7 +265,7 @@ RSpec.describe Projects::UpdatePagesService do
file = fixture_file_upload('spec/fixtures/pages.zip')
metafile = fixture_file_upload('spec/fixtures/pages.zip.meta')
- create(:ci_job_artifact, :archive, file: file, job: build)
+ create(:ci_job_artifact, :archive, :correct_checksum, file: file, job: build)
create(:ci_job_artifact, :metadata, file: metafile, job: build)
allow(build).to receive(:artifacts_metadata_entry)
diff --git a/spec/services/projects/update_repository_storage_service_spec.rb b/spec/services/projects/update_repository_storage_service_spec.rb
index 0fcd14f3bc9..123f604e7a4 100644
--- a/spec/services/projects/update_repository_storage_service_spec.rb
+++ b/spec/services/projects/update_repository_storage_service_spec.rb
@@ -168,6 +168,24 @@ RSpec.describe Projects::UpdateRepositoryStorageService do
end
end
+ context 'project with no repositories' do
+ let(:project) { create(:project) }
+ let(:repository_storage_move) { create(:project_repository_storage_move, :scheduled, project: project, destination_storage_name: 'test_second_storage') }
+
+ it 'updates the database' do
+ allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('default').and_call_original
+ allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('test_second_storage').and_return(SecureRandom.uuid)
+
+ result = subject.execute
+ project.reload
+
+ expect(result).to be_success
+ expect(project).not_to be_repository_read_only
+ expect(project.repository_storage).to eq('test_second_storage')
+ expect(project.project_repository.shard_name).to eq('test_second_storage')
+ end
+ end
+
context 'with wiki repository' do
include_examples 'moves repository to another storage', 'wiki' do
let(:project) { create(:project, :repository, wiki_enabled: true) }
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index 989426fde8b..760cd85bf71 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -127,11 +127,22 @@ RSpec.describe Projects::UpdateService do
end
context 'when updated by an admin' do
- it 'updates the project to public' do
- result = update_project(project, admin, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'updates the project to public' do
+ result = update_project(project, admin, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
- expect(result).to eq({ status: :success })
- expect(project).to be_public
+ expect(result).to eq({ status: :success })
+ expect(project).to be_public
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'does not update the project to public' do
+ result = update_project(project, admin, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+
+ expect(result).to eq({ status: :error, message: 'New visibility level not allowed!' })
+ expect(project).to be_private
+ end
end
end
end
@@ -144,7 +155,7 @@ RSpec.describe Projects::UpdateService do
project.update!(namespace: group, visibility_level: group.visibility_level)
end
- it 'does not update project visibility level' do
+ it 'does not update project visibility level even if admin', :enable_admin_mode do
result = update_project(project, admin, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
expect(result).to eq({ status: :error, message: 'Visibility level public is not allowed in a internal group.' })
@@ -181,6 +192,7 @@ RSpec.describe Projects::UpdateService do
describe 'when updating project that has forks' do
let(:project) { create(:project, :internal) }
+ let(:user) { project.owner }
let(:forked_project) { fork_project(project) }
context 'and unlink forks feature flag is off' do
@@ -194,7 +206,7 @@ RSpec.describe Projects::UpdateService do
expect(project).to be_internal
expect(forked_project).to be_internal
- expect(update_project(project, admin, opts)).to eq({ status: :success })
+ expect(update_project(project, user, opts)).to eq({ status: :success })
expect(project).to be_private
expect(forked_project.reload).to be_private
@@ -206,7 +218,7 @@ RSpec.describe Projects::UpdateService do
expect(project).to be_internal
expect(forked_project).to be_internal
- expect(update_project(project, admin, opts)).to eq({ status: :success })
+ expect(update_project(project, user, opts)).to eq({ status: :success })
expect(project).to be_public
expect(forked_project.reload).to be_internal
@@ -220,7 +232,7 @@ RSpec.describe Projects::UpdateService do
expect(project).to be_internal
expect(forked_project).to be_internal
- expect(update_project(project, admin, opts)).to eq({ status: :success })
+ expect(update_project(project, user, opts)).to eq({ status: :success })
expect(project).to be_private
expect(forked_project.reload).to be_internal
@@ -576,15 +588,21 @@ RSpec.describe Projects::UpdateService do
context 'authenticated as admin' do
let(:user) { create(:admin) }
- it 'schedules the transfer of the repository to the new storage and locks the project' do
- update_project(project, admin, opts)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'schedules the transfer of the repository to the new storage and locks the project' do
+ update_project(project, admin, opts)
- expect(project).to be_repository_read_only
- expect(project.repository_storage_moves.last).to have_attributes(
- state: ::ProjectRepositoryStorageMove.state_machines[:state].states[:scheduled].value,
- source_storage_name: 'default',
- destination_storage_name: 'test_second_storage'
- )
+ expect(project).to be_repository_read_only
+ expect(project.repository_storage_moves.last).to have_attributes(
+ state: ::ProjectRepositoryStorageMove.state_machines[:state].states[:scheduled].value,
+ source_storage_name: 'default',
+ destination_storage_name: 'test_second_storage'
+ )
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it_behaves_like 'the transfer was not scheduled'
end
context 'the repository is read-only' do
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index 6f3814095f9..1f521ed4a93 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -312,8 +312,8 @@ RSpec.describe QuickActions::InterpretService do
end
end
- shared_examples 'wip command' do
- it 'returns wip_event: "wip" if content contains /wip' do
+ shared_examples 'draft command' do
+ it 'returns wip_event: "wip" if content contains /draft' do
_, updates, _ = service.execute(content, issuable)
expect(updates).to eq(wip_event: 'wip')
@@ -322,12 +322,12 @@ RSpec.describe QuickActions::InterpretService do
it 'returns the wip message' do
_, _, message = service.execute(content, issuable)
- expect(message).to eq("Marked this #{issuable.to_ability_name.humanize(capitalize: false)} as Work In Progress.")
+ expect(message).to eq("Marked this #{issuable.to_ability_name.humanize(capitalize: false)} as a draft.")
end
end
- shared_examples 'unwip command' do
- it 'returns wip_event: "unwip" if content contains /wip' do
+ shared_examples 'undraft command' do
+ it 'returns wip_event: "unwip" if content contains /draft' do
issuable.update!(title: issuable.wip_title)
_, updates, _ = service.execute(content, issuable)
@@ -338,7 +338,7 @@ RSpec.describe QuickActions::InterpretService do
issuable.update!(title: issuable.wip_title)
_, _, message = service.execute(content, issuable)
- expect(message).to eq("Unmarked this #{issuable.to_ability_name.humanize(capitalize: false)} as Work In Progress.")
+ expect(message).to eq("Unmarked this #{issuable.to_ability_name.humanize(capitalize: false)} as a draft.")
end
end
@@ -1026,16 +1026,26 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { issue }
end
- it_behaves_like 'wip command' do
+ it_behaves_like 'draft command' do
let(:content) { '/wip' }
let(:issuable) { merge_request }
end
- it_behaves_like 'unwip command' do
+ it_behaves_like 'undraft command' do
let(:content) { '/wip' }
let(:issuable) { merge_request }
end
+ it_behaves_like 'draft command' do
+ let(:content) { '/draft' }
+ let(:issuable) { merge_request }
+ end
+
+ it_behaves_like 'undraft command' do
+ let(:content) { '/draft' }
+ let(:issuable) { merge_request }
+ end
+
it_behaves_like 'empty command' do
let(:content) { '/remove_due_date' }
let(:issuable) { merge_request }
@@ -1896,13 +1906,13 @@ RSpec.describe QuickActions::InterpretService do
end
end
- describe 'wip command' do
- let(:content) { '/wip' }
+ describe 'draft command' do
+ let(:content) { '/draft' }
it 'includes the new status' do
_, explanations = service.explain(content, merge_request)
- expect(explanations).to eq(['Marks this merge request as Work In Progress.'])
+ expect(explanations).to eq(['Marks this merge request as a draft.'])
end
end
diff --git a/spec/services/releases/create_service_spec.rb b/spec/services/releases/create_service_spec.rb
index 90648340b66..b9294182883 100644
--- a/spec/services/releases/create_service_spec.rb
+++ b/spec/services/releases/create_service_spec.rb
@@ -22,6 +22,12 @@ RSpec.describe Releases::CreateService do
it 'creates a new release' do
expected_job_count = MailScheduler::NotificationServiceWorker.jobs.size + 1
+ expect_next_instance_of(Release) do |release|
+ expect(release)
+ .to receive(:execute_hooks)
+ .with('create')
+ end
+
result = service.execute
expect(project.releases.count).to eq(1)
diff --git a/spec/services/releases/update_service_spec.rb b/spec/services/releases/update_service_spec.rb
index 00544b820cb..932a7fab5ec 100644
--- a/spec/services/releases/update_service_spec.rb
+++ b/spec/services/releases/update_service_spec.rb
@@ -32,6 +32,12 @@ RSpec.describe Releases::UpdateService do
expect(result[:release].description).to eq(new_description)
end
+ it 'executes hooks' do
+ expect(service.release).to receive(:execute_hooks).with('update')
+
+ service.execute
+ end
+
context 'when the tag does not exists' do
let(:tag_name) { 'foobar' }
diff --git a/spec/services/reset_project_cache_service_spec.rb b/spec/services/reset_project_cache_service_spec.rb
index 3e79270da8d..165b38ee338 100644
--- a/spec/services/reset_project_cache_service_spec.rb
+++ b/spec/services/reset_project_cache_service_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe ResetProjectCacheService do
context 'when project cache_index is a numeric value' do
before do
- project.update(jobs_cache_index: 1)
+ project.update!(jobs_cache_index: 1)
end
it 'increments project cache index' do
diff --git a/spec/services/resource_access_tokens/create_service_spec.rb b/spec/services/resource_access_tokens/create_service_spec.rb
index d8b12cda632..5cfa1ae93e6 100644
--- a/spec/services/resource_access_tokens/create_service_spec.rb
+++ b/spec/services/resource_access_tokens/create_service_spec.rb
@@ -11,16 +11,15 @@ RSpec.describe ResourceAccessTokens::CreateService do
describe '#execute' do
# Created shared_examples as it will easy to include specs for group bots in https://gitlab.com/gitlab-org/gitlab/-/issues/214046
- shared_examples 'fails when user does not have the permission to create a Resource Bot' do
- before_all do
- resource.add_developer(user)
- end
+ shared_examples 'token creation fails' do
+ let(:resource) { create(:project)}
- it 'returns error' do
- response = subject
+ it 'does not add the project bot as a member' do
+ expect { subject }.not_to change { resource.members.count }
+ end
- expect(response.error?).to be true
- expect(response.message).to eq("User does not have permission to create #{resource_type} Access Token")
+ it 'immediately destroys the bot user if one was created', :sidekiq_inline do
+ expect { subject }.not_to change { User.bots.count }
end
end
@@ -47,8 +46,18 @@ RSpec.describe ResourceAccessTokens::CreateService do
end
context 'when created by an admin' do
- it_behaves_like 'creates a user that has their email confirmed' do
- let(:user) { create(:admin) }
+ let(:user) { create(:admin) }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it_behaves_like 'creates a user that has their email confirmed'
+ end
+
+ context 'when admin mode is disabled' do
+ it 'returns error' do
+ response = subject
+
+ expect(response.error?).to be true
+ end
end
end
@@ -154,24 +163,36 @@ RSpec.describe ResourceAccessTokens::CreateService do
context 'when invalid scope is passed' do
let_it_be(:params) { { scopes: [:invalid_scope] } }
- it 'returns error' do
+ it_behaves_like 'token creation fails'
+
+ it 'returns the scope error message' do
response = subject
expect(response.error?).to be true
+ expect(response.errors).to include("Scopes can only contain available scopes")
end
end
end
- end
- context 'when access provisioning fails' do
- before do
- allow(resource).to receive(:add_user).and_return(nil)
- end
+ context "when access provisioning fails" do
+ let_it_be(:bot_user) { create(:user, :project_bot) }
+ let(:unpersisted_member) { build(:project_member, source: resource, user: bot_user) }
- it 'returns error' do
- response = subject
+ before do
+ allow_next_instance_of(ResourceAccessTokens::CreateService) do |service|
+ allow(service).to receive(:create_user).and_return(bot_user)
+ allow(service).to receive(:create_membership).and_return(unpersisted_member)
+ end
+ end
- expect(response.error?).to be true
+ it_behaves_like 'token creation fails'
+
+ it 'returns the provisioning error message' do
+ response = subject
+
+ expect(response.error?).to be true
+ expect(response.errors).to include("Could not provision maintainer access to project access token")
+ end
end
end
end
@@ -180,7 +201,16 @@ RSpec.describe ResourceAccessTokens::CreateService do
let_it_be(:resource_type) { 'project' }
let_it_be(:resource) { project }
- it_behaves_like 'fails when user does not have the permission to create a Resource Bot'
+ context 'when user does not have permission to create a resource bot' do
+ it_behaves_like 'token creation fails'
+
+ it 'returns the permission error message' do
+ response = subject
+
+ expect(response.error?).to be true
+ expect(response.errors).to include("User does not have permission to create #{resource_type} Access Token")
+ end
+ end
context 'user with valid permission' do
before_all do
diff --git a/spec/services/resource_events/change_milestone_service_spec.rb b/spec/services/resource_events/change_milestone_service_spec.rb
index 3a9dadbd40e..a2131c5c1b0 100644
--- a/spec/services/resource_events/change_milestone_service_spec.rb
+++ b/spec/services/resource_events/change_milestone_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe ResourceEvents::ChangeMilestoneService do
[:issue, :merge_request].each do |issuable|
it_behaves_like 'timebox(milestone or iteration) resource events creator', ResourceMilestoneEvent do
- let_it_be(:resource) { create(issuable) }
+ let_it_be(:resource) { create(issuable) } # rubocop:disable Rails/SaveBang
end
end
end
diff --git a/spec/services/search/snippet_service_spec.rb b/spec/services/search/snippet_service_spec.rb
index ceaf3d055bf..d204f626635 100644
--- a/spec/services/search/snippet_service_spec.rb
+++ b/spec/services/search/snippet_service_spec.rb
@@ -49,12 +49,24 @@ RSpec.describe Search::SnippetService do
expect(results.objects('snippet_titles')).to match_array [public_snippet, internal_snippet, private_snippet, project_public_snippet, project_internal_snippet]
end
- it 'returns all snippets when user is admin' do
- admin = create(:admin)
- search = described_class.new(admin, search: 'bar')
- results = search.execute
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns all snippets when user is admin' do
+ admin = create(:admin)
+ search = described_class.new(admin, search: 'bar')
+ results = search.execute
+
+ expect(results.objects('snippet_titles')).to match_array [public_snippet, internal_snippet, private_snippet, project_public_snippet, project_internal_snippet, project_private_snippet]
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'returns only public & internal snippets when user is admin' do
+ admin = create(:admin)
+ search = described_class.new(admin, search: 'bar')
+ results = search.execute
- expect(results.objects('snippet_titles')).to match_array [public_snippet, internal_snippet, private_snippet, project_public_snippet, project_internal_snippet, project_private_snippet]
+ expect(results.objects('snippet_titles')).to match_array [public_snippet, internal_snippet, project_public_snippet, project_internal_snippet]
+ end
end
end
end
diff --git a/spec/services/search_service_spec.rb b/spec/services/search_service_spec.rb
index fc613a6224a..40fb257b23e 100644
--- a/spec/services/search_service_spec.rb
+++ b/spec/services/search_service_spec.rb
@@ -18,9 +18,10 @@ RSpec.describe SearchService do
let(:group_project) { create(:project, group: accessible_group, name: 'group_project') }
let(:public_project) { create(:project, :public, name: 'public_project') }
+ let(:page) { 1 }
let(:per_page) { described_class::DEFAULT_PER_PAGE }
- subject(:search_service) { described_class.new(user, search: search, scope: scope, page: 1, per_page: per_page) }
+ subject(:search_service) { described_class.new(user, search: search, scope: scope, page: page, per_page: per_page) }
before do
accessible_project.add_maintainer(user)
@@ -242,10 +243,10 @@ RSpec.describe SearchService do
end
describe '#search_objects' do
- context 'handling per_page param' do
- let(:search) { '' }
- let(:scope) { nil }
+ let(:search) { '' }
+ let(:scope) { nil }
+ describe 'per_page: parameter' do
context 'when nil' do
let(:per_page) { nil }
@@ -312,6 +313,34 @@ RSpec.describe SearchService do
end
end
+ describe 'page: parameter' do
+ context 'when < 1' do
+ let(:page) { 0 }
+
+ it "defaults to 1" do
+ expect_any_instance_of(Gitlab::SearchResults)
+ .to receive(:objects)
+ .with(anything, hash_including(page: 1))
+ .and_call_original
+
+ subject.search_objects
+ end
+ end
+
+ context 'when nil' do
+ let(:page) { nil }
+
+ it "defaults to 1" do
+ expect_any_instance_of(Gitlab::SearchResults)
+ .to receive(:objects)
+ .with(anything, hash_including(page: 1))
+ .and_call_original
+
+ subject.search_objects
+ end
+ end
+ end
+
context 'with accessible project_id' do
it 'returns objects in the project' do
search_objects = described_class.new(
diff --git a/spec/services/snippets/create_service_spec.rb b/spec/services/snippets/create_service_spec.rb
index b7fb5a98d06..96807fd629f 100644
--- a/spec/services/snippets/create_service_spec.rb
+++ b/spec/services/snippets/create_service_spec.rb
@@ -147,9 +147,11 @@ RSpec.describe Snippets::CreateService do
end
context 'when the commit action fails' do
+ let(:error) { SnippetRepository::CommitError.new('foobar') }
+
before do
allow_next_instance_of(SnippetRepository) do |instance|
- allow(instance).to receive(:multi_files_action).and_raise(SnippetRepository::CommitError.new('foobar'))
+ allow(instance).to receive(:multi_files_action).and_raise(error)
end
end
@@ -172,7 +174,7 @@ RSpec.describe Snippets::CreateService do
end
it 'logs the error' do
- expect(Gitlab::AppLogger).to receive(:error).with('foobar')
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(error, service: 'Snippets::CreateService')
subject
end
diff --git a/spec/services/snippets/update_service_spec.rb b/spec/services/snippets/update_service_spec.rb
index 406ece30bd7..a2341dc71b2 100644
--- a/spec/services/snippets/update_service_spec.rb
+++ b/spec/services/snippets/update_service_spec.rb
@@ -277,14 +277,14 @@ RSpec.describe Snippets::UpdateService do
end
context 'when an error is raised' do
- let(:error_message) { 'foobar' }
+ let(:error) { SnippetRepository::CommitError.new('foobar') }
before do
- allow(snippet.snippet_repository).to receive(:multi_files_action).and_raise(SnippetRepository::CommitError, error_message)
+ allow(snippet.snippet_repository).to receive(:multi_files_action).and_raise(error)
end
it 'logs the error' do
- expect(Gitlab::AppLogger).to receive(:error).with(error_message)
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(error, service: 'Snippets::UpdateService')
subject
end
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index bdc40a92e91..b25837ca260 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -85,7 +85,7 @@ RSpec.describe SystemHooksService do
end
it 'handles nil datetime columns' do
- user.update(created_at: nil, updated_at: nil)
+ user.update!(created_at: nil, updated_at: nil)
data = event_data(user, :destroy)
expect(data[:created_at]).to be(nil)
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 42e48b9ad81..a4ae7e42958 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -378,13 +378,13 @@ RSpec.describe SystemNoteService do
noteable_types.each do |type|
context "when noteable is a #{type}" do
it "blocks cross reference when #{type.underscore}_events is false" do
- jira_tracker.update("#{type}_events" => false)
+ jira_tracker.update!("#{type}_events" => false)
expect(cross_reference(type)).to eq(s_('JiraService|Events for %{noteable_model_name} are disabled.') % { noteable_model_name: type.pluralize.humanize.downcase })
end
it "creates cross reference when #{type.underscore}_events is true" do
- jira_tracker.update("#{type}_events" => true)
+ jira_tracker.update!("#{type}_events" => true)
expect(cross_reference(type)).to eq(success_message)
end
@@ -566,25 +566,25 @@ RSpec.describe SystemNoteService do
end
end
- describe '.handle_merge_request_wip' do
+ describe '.handle_merge_request_draft' do
it 'calls MergeRequestsService' do
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
- expect(service).to receive(:handle_merge_request_wip)
+ expect(service).to receive(:handle_merge_request_draft)
end
- described_class.handle_merge_request_wip(noteable, project, author)
+ described_class.handle_merge_request_draft(noteable, project, author)
end
end
- describe '.add_merge_request_wip_from_commit' do
+ describe '.add_merge_request_draft_from_commit' do
it 'calls MergeRequestsService' do
commit = double
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
- expect(service).to receive(:add_merge_request_wip_from_commit).with(commit)
+ expect(service).to receive(:add_merge_request_draft_from_commit).with(commit)
end
- described_class.add_merge_request_wip_from_commit(noteable, project, author, commit)
+ described_class.add_merge_request_draft_from_commit(noteable, project, author, commit)
end
end
diff --git a/spec/services/system_notes/issuables_service_spec.rb b/spec/services/system_notes/issuables_service_spec.rb
index e78b00fb67a..b70c5e899fc 100644
--- a/spec/services/system_notes/issuables_service_spec.rb
+++ b/spec/services/system_notes/issuables_service_spec.rb
@@ -373,7 +373,7 @@ RSpec.describe ::SystemNotes::IssuablesService do
before do
# Mention issue (noteable) from commit0
system_note = service.cross_reference(commit0)
- system_note.update(note: system_note.note.capitalize)
+ system_note.update!(note: system_note.note.capitalize)
end
it 'is truthy when already mentioned' do
@@ -407,7 +407,7 @@ RSpec.describe ::SystemNotes::IssuablesService do
before do
# Mention commit1 from commit0
system_note = service.cross_reference(commit1)
- system_note.update(note: system_note.note.capitalize)
+ system_note.update!(note: system_note.note.capitalize)
end
it 'is truthy when already mentioned' do
@@ -436,7 +436,7 @@ RSpec.describe ::SystemNotes::IssuablesService do
context 'legacy capitalized cross reference' do
before do
system_note = service.cross_reference(commit0)
- system_note.update(note: system_note.note.capitalize)
+ system_note.update!(note: system_note.note.capitalize)
end
it 'is true when a fork mentions an external issue' do
@@ -582,7 +582,7 @@ RSpec.describe ::SystemNotes::IssuablesService do
it 'creates the note text correctly' do
[:issue, :merge_request].each do |type|
- issuable = create(type)
+ issuable = create(type) # rubocop:disable Rails/SaveBang
service = described_class.new(noteable: issuable, author: author)
expect(service.discussion_lock.note)
diff --git a/spec/services/system_notes/merge_requests_service_spec.rb b/spec/services/system_notes/merge_requests_service_spec.rb
index 067e1cef64d..50d16231e8f 100644
--- a/spec/services/system_notes/merge_requests_service_spec.rb
+++ b/spec/services/system_notes/merge_requests_service_spec.rb
@@ -51,44 +51,44 @@ RSpec.describe ::SystemNotes::MergeRequestsService do
end
end
- describe '.handle_merge_request_wip' do
+ describe '.handle_merge_request_draft' do
context 'adding draft note' do
let(:noteable) { create(:merge_request, source_project: project, title: 'Draft: Lorem ipsum') }
- subject { service.handle_merge_request_wip }
+ subject { service.handle_merge_request_draft }
it_behaves_like 'a system note' do
let(:action) { 'title' }
end
it 'sets the note text' do
- expect(subject.note).to eq 'marked as a **Work In Progress**'
+ expect(subject.note).to eq 'marked this merge request as **draft**'
end
end
- context 'removing wip note' do
- subject { service.handle_merge_request_wip }
+ context 'removing draft note' do
+ subject { service.handle_merge_request_draft }
it_behaves_like 'a system note' do
let(:action) { 'title' }
end
it 'sets the note text' do
- expect(subject.note).to eq 'unmarked as a **Work In Progress**'
+ expect(subject.note).to eq 'marked this merge request as **ready**'
end
end
end
- describe '.add_merge_request_wip_from_commit' do
- subject { service.add_merge_request_wip_from_commit(noteable.diff_head_commit) }
+ describe '.add_merge_request_draft_from_commit' do
+ subject { service.add_merge_request_draft_from_commit(noteable.diff_head_commit) }
it_behaves_like 'a system note' do
let(:action) { 'title' }
end
- it "posts the 'marked as a Work In Progress from commit' system note" do
+ it "posts the 'marked this merge request as draft from commit' system note" do
expect(subject.note).to match(
- /marked as a \*\*Work In Progress\*\* from #{Commit.reference_pattern}/
+ /marked this merge request as \*\*draft\*\* from #{Commit.reference_pattern}/
)
end
end
diff --git a/spec/services/test_hooks/project_service_spec.rb b/spec/services/test_hooks/project_service_spec.rb
index e4cc3a2d652..7470bdff527 100644
--- a/spec/services/test_hooks/project_service_spec.rb
+++ b/spec/services/test_hooks/project_service_spec.rb
@@ -186,5 +186,23 @@ RSpec.describe TestHooks::ProjectService do
expect(service.execute).to include(success_result)
end
end
+
+ context 'releases_events' do
+ let(:trigger) { 'releases_events' }
+ let(:trigger_key) { :release_hooks }
+
+ it 'returns error message if not enough data' do
+ expect(hook).not_to receive(:execute)
+ expect(service.execute).to include({ status: :error, message: 'Ensure the project has releases.' })
+ end
+
+ it 'executes hook' do
+ allow(project).to receive(:releases).and_return([Release.new])
+ allow_any_instance_of(Release).to receive(:to_hook_data).and_return(sample_data)
+
+ expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
+ expect(service.execute).to include(success_result)
+ end
+ end
end
end
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index 60903f8f367..90325c564bc 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -145,12 +145,12 @@ RSpec.describe TodoService do
end
it 'creates correct todos for each valid user based on the type of mention' do
- issue.update(description: directly_addressed_and_mentioned)
+ issue.update!(description: directly_addressed_and_mentioned)
service.new_issue(issue, author)
should_create_todo(user: member, target: issue, action: Todo::DIRECTLY_ADDRESSED)
- should_create_todo(user: admin, target: issue, action: Todo::MENTIONED)
+ should_not_create_todo(user: admin, target: issue, action: Todo::MENTIONED)
should_create_todo(user: guest, target: issue, action: Todo::MENTIONED)
end
@@ -160,7 +160,7 @@ RSpec.describe TodoService do
should_create_todo(user: assignee, target: confidential_issue, author: john_doe, action: Todo::ASSIGNED)
should_create_todo(user: author, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
should_create_todo(user: member, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
- should_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
+ should_not_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
should_not_create_todo(user: guest, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
should_create_todo(user: john_doe, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
end
@@ -171,7 +171,7 @@ RSpec.describe TodoService do
should_create_todo(user: assignee, target: addressed_confident_issue, author: john_doe, action: Todo::ASSIGNED)
should_create_todo(user: author, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
should_create_todo(user: member, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
- should_create_todo(user: admin, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: admin, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
should_not_create_todo(user: guest, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
should_create_todo(user: john_doe, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
end
@@ -222,13 +222,13 @@ RSpec.describe TodoService do
end
it 'creates a todo for each valid user not included in skip_users based on the type of mention' do
- issue.update(description: directly_addressed_and_mentioned)
+ issue.update!(description: directly_addressed_and_mentioned)
service.update_issue(issue, author, skip_users)
should_create_todo(user: member, target: issue, action: Todo::DIRECTLY_ADDRESSED)
should_create_todo(user: guest, target: issue, action: Todo::MENTIONED)
- should_create_todo(user: admin, target: issue, action: Todo::MENTIONED)
+ should_not_create_todo(user: admin, target: issue, action: Todo::MENTIONED)
should_not_create_todo(user: skipped, target: issue)
end
@@ -273,7 +273,7 @@ RSpec.describe TodoService do
should_create_todo(user: author, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
should_create_todo(user: assignee, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
should_create_todo(user: member, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
- should_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
+ should_not_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
should_not_create_todo(user: guest, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
should_create_todo(user: john_doe, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
end
@@ -284,14 +284,14 @@ RSpec.describe TodoService do
should_create_todo(user: author, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
should_create_todo(user: assignee, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
should_create_todo(user: member, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
- should_create_todo(user: admin, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: admin, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
should_not_create_todo(user: guest, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
should_create_todo(user: john_doe, target: addressed_confident_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED)
end
context 'issues with a task list' do
it 'does not create todo when tasks are marked as completed' do
- issue.update(description: "- [x] Task 1\n- [X] Task 2 #{mentions}")
+ issue.update!(description: "- [x] Task 1\n- [X] Task 2 #{mentions}")
service.update_issue(issue, author)
@@ -304,7 +304,7 @@ RSpec.describe TodoService do
end
it 'does not create directly addressed todo when tasks are marked as completed' do
- addressed_issue.update(description: "#{directly_addressed}\n- [x] Task 1\n- [x] Task 2\n")
+ addressed_issue.update!(description: "#{directly_addressed}\n- [x] Task 1\n- [x] Task 2\n")
service.update_issue(addressed_issue, author)
@@ -317,7 +317,7 @@ RSpec.describe TodoService do
end
it 'does not raise an error when description not change' do
- issue.update(title: 'Sample')
+ issue.update!(title: 'Sample')
expect { service.update_issue(issue, author) }.not_to raise_error
end
@@ -427,12 +427,12 @@ RSpec.describe TodoService do
end
it 'creates a todo for each valid user based on the type of mention' do
- note.update(note: directly_addressed_and_mentioned)
+ note.update!(note: directly_addressed_and_mentioned)
service.new_note(note, john_doe)
should_create_todo(user: member, target: issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED, note: note)
- should_create_todo(user: admin, target: issue, author: john_doe, action: Todo::MENTIONED, note: note)
+ should_not_create_todo(user: admin, target: issue, author: john_doe, action: Todo::MENTIONED, note: note)
should_create_todo(user: guest, target: issue, author: john_doe, action: Todo::MENTIONED, note: note)
end
@@ -452,7 +452,7 @@ RSpec.describe TodoService do
should_create_todo(user: author, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
should_create_todo(user: assignee, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
should_create_todo(user: member, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
- should_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
+ should_not_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
should_not_create_todo(user: guest, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
should_create_todo(user: john_doe, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
end
@@ -463,7 +463,7 @@ RSpec.describe TodoService do
should_create_todo(user: author, target: confidential_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED, note: addressed_note_on_confidential_issue)
should_create_todo(user: assignee, target: confidential_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED, note: addressed_note_on_confidential_issue)
should_create_todo(user: member, target: confidential_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED, note: addressed_note_on_confidential_issue)
- should_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED, note: addressed_note_on_confidential_issue)
+ should_not_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED, note: addressed_note_on_confidential_issue)
should_not_create_todo(user: guest, target: confidential_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED, note: addressed_note_on_confidential_issue)
should_create_todo(user: john_doe, target: confidential_issue, author: john_doe, action: Todo::DIRECTLY_ADDRESSED, note: addressed_note_on_confidential_issue)
end
@@ -694,12 +694,12 @@ RSpec.describe TodoService do
end
it 'creates a todo for each valid user based on the type of mention' do
- mr_assigned.update(description: directly_addressed_and_mentioned)
+ mr_assigned.update!(description: directly_addressed_and_mentioned)
service.new_merge_request(mr_assigned, author)
should_create_todo(user: member, target: mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_create_todo(user: admin, target: mr_assigned, action: Todo::MENTIONED)
+ should_not_create_todo(user: admin, target: mr_assigned, action: Todo::MENTIONED)
end
it 'creates a directly addressed todo for each valid addressed user' do
@@ -726,12 +726,12 @@ RSpec.describe TodoService do
end
it 'creates a todo for each valid user not included in skip_users based on the type of mention' do
- mr_assigned.update(description: directly_addressed_and_mentioned)
+ mr_assigned.update!(description: directly_addressed_and_mentioned)
service.update_merge_request(mr_assigned, author, skip_users)
should_create_todo(user: member, target: mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_create_todo(user: admin, target: mr_assigned, action: Todo::MENTIONED)
+ should_not_create_todo(user: admin, target: mr_assigned, action: Todo::MENTIONED)
should_not_create_todo(user: skipped, target: mr_assigned)
end
@@ -772,7 +772,7 @@ RSpec.describe TodoService do
context 'with a task list' do
it 'does not create todo when tasks are marked as completed' do
- mr_assigned.update(description: "- [x] Task 1\n- [X] Task 2 #{mentions}")
+ mr_assigned.update!(description: "- [x] Task 1\n- [X] Task 2 #{mentions}")
service.update_merge_request(mr_assigned, author)
@@ -786,7 +786,7 @@ RSpec.describe TodoService do
end
it 'does not create directly addressed todo when tasks are marked as completed' do
- addressed_mr_assigned.update(description: "#{directly_addressed}\n- [x] Task 1\n- [X] Task 2")
+ addressed_mr_assigned.update!(description: "#{directly_addressed}\n- [x] Task 1\n- [X] Task 2")
service.update_merge_request(addressed_mr_assigned, author)
@@ -800,7 +800,7 @@ RSpec.describe TodoService do
end
it 'does not raise an error when description not change' do
- mr_assigned.update(title: 'Sample')
+ mr_assigned.update!(title: 'Sample')
expect { service.update_merge_request(mr_assigned, author) }.not_to raise_error
end
@@ -883,7 +883,7 @@ RSpec.describe TodoService do
end
it 'creates a pending todo for each merge_participant' do
- mr_unassigned.update(merge_when_pipeline_succeeds: true, merge_user: admin)
+ mr_unassigned.update!(merge_when_pipeline_succeeds: true, merge_user: admin)
service.merge_request_became_unmergeable(mr_unassigned)
merge_participants.each do |participant|
@@ -991,13 +991,13 @@ RSpec.describe TodoService do
end
it 'creates a todo for each valid user not included in skip_users based on the type of mention' do
- note.update(note: directly_addressed_and_mentioned)
+ note.update!(note: directly_addressed_and_mentioned)
service.update_note(note, author, skip_users)
should_create_todo(user: member, target: noteable, action: Todo::DIRECTLY_ADDRESSED)
should_create_todo(user: guest, target: noteable, action: Todo::MENTIONED)
- should_create_todo(user: admin, target: noteable, action: Todo::MENTIONED)
+ should_not_create_todo(user: admin, target: noteable, action: Todo::MENTIONED)
should_not_create_todo(user: skipped, target: noteable)
end
diff --git a/spec/services/todos/destroy/confidential_issue_service_spec.rb b/spec/services/todos/destroy/confidential_issue_service_spec.rb
index ddce45e7968..e3dcc2bae95 100644
--- a/spec/services/todos/destroy/confidential_issue_service_spec.rb
+++ b/spec/services/todos/destroy/confidential_issue_service_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe Todos::Destroy::ConfidentialIssueService do
context 'when provided issue is not confidential' do
it 'does not remove any todos' do
- issue_1.update(confidential: false)
+ issue_1.update!(confidential: false)
expect { subject }.not_to change { Todo.count }
end
diff --git a/spec/services/two_factor/destroy_service_spec.rb b/spec/services/two_factor/destroy_service_spec.rb
index 3df4d1593c6..30c189520fd 100644
--- a/spec/services/two_factor/destroy_service_spec.rb
+++ b/spec/services/two_factor/destroy_service_spec.rb
@@ -85,7 +85,7 @@ RSpec.describe TwoFactor::DestroyService do
it_behaves_like 'disables two-factor authentication'
end
- context 'admin disables the two-factor authentication of another user' do
+ context 'admin disables the two-factor authentication of another user', :enable_admin_mode do
let(:current_user) { create(:admin) }
let(:user) { create(:user, :two_factor) }
diff --git a/spec/services/users/approve_service_spec.rb b/spec/services/users/approve_service_spec.rb
index 50f2b6b0827..55b2c83f4a8 100644
--- a/spec/services/users/approve_service_spec.rb
+++ b/spec/services/users/approve_service_spec.rb
@@ -19,85 +19,101 @@ RSpec.describe Users::ApproveService do
end
end
- context 'when user is not in pending approval state' do
- let(:user) { create(:user, state: 'active') }
-
+ context 'when the executor user is an admin not in admin mode' do
it 'returns error result' do
expect(subject[:status]).to eq(:error)
- expect(subject[:message])
- .to match(/The user you are trying to approve is not pending an approval/)
+ expect(subject[:message]).to match(/You are not allowed to approve a user/)
end
end
- context 'when user cannot be activated' do
- let(:user) do
- build(:user, state: 'blocked_pending_approval', email: 'invalid email')
- end
+ context 'when the executor user is an admin in admin mode', :enable_admin_mode do
+ context 'when user is not in pending approval state' do
+ let(:user) { create(:user, state: 'active') }
- it 'returns error result' do
- expect(subject[:status]).to eq(:error)
- expect(subject[:message]).to match(/Email is invalid/)
+ it 'returns error result' do
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:message])
+ .to match(/The user you are trying to approve is not pending an approval/)
+ end
end
- it 'does not change the state of the user' do
- expect { subject }.not_to change { user.state }
+ context 'when user cannot be activated' do
+ let(:user) do
+ build(:user, state: 'blocked_pending_approval', email: 'invalid email')
+ end
+
+ it 'returns error result' do
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:message]).to match(/Email is invalid/)
+ end
+
+ it 'does not change the state of the user' do
+ expect { subject }.not_to change { user.state }
+ end
end
end
end
context 'success' do
- it 'activates the user' do
- expect(subject[:status]).to eq(:success)
- expect(user.reload).to be_active
- end
+ context 'when the executor user is an admin in admin mode', :enable_admin_mode do
+ it 'activates the user' do
+ expect(subject[:status]).to eq(:success)
+ expect(user.reload).to be_active
+ end
- context 'email confirmation status' do
- context 'user is unconfirmed' do
- let(:user) { create(:user, :blocked_pending_approval, :unconfirmed) }
+ it 'emails the user on approval' do
+ expect(DeviseMailer).to receive(:user_admin_approval).with(user).and_call_original
+ expect { subject }.to have_enqueued_mail(DeviseMailer, :user_admin_approval)
+ end
- it 'sends confirmation instructions' do
- expect { subject }
- .to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
+ context 'email confirmation status' do
+ context 'user is unconfirmed' do
+ let(:user) { create(:user, :blocked_pending_approval, :unconfirmed) }
+
+ it 'sends confirmation instructions' do
+ expect { subject }
+ .to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
+ end
end
- end
- context 'user is confirmed' do
- it 'does not send a confirmation email' do
- expect { subject }
- .not_to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
+ context 'user is confirmed' do
+ it 'does not send a confirmation email' do
+ expect { subject }
+ .not_to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
+ end
end
end
- end
- context 'pending invitiations' do
- let!(:project_member_invite) { create(:project_member, :invited, invite_email: user.email) }
- let!(:group_member_invite) { create(:group_member, :invited, invite_email: user.email) }
+ context 'pending invitations' do
+ let!(:project_member_invite) { create(:project_member, :invited, invite_email: user.email) }
+ let!(:group_member_invite) { create(:group_member, :invited, invite_email: user.email) }
- context 'user is unconfirmed' do
- let(:user) { create(:user, :blocked_pending_approval, :unconfirmed) }
+ context 'user is unconfirmed' do
+ let(:user) { create(:user, :blocked_pending_approval, :unconfirmed) }
- it 'does not accept pending invites of the user' do
- expect(subject[:status]).to eq(:success)
+ it 'does not accept pending invites of the user' do
+ expect(subject[:status]).to eq(:success)
- group_member_invite.reload
- project_member_invite.reload
+ group_member_invite.reload
+ project_member_invite.reload
- expect(group_member_invite).to be_invite
- expect(project_member_invite).to be_invite
+ expect(group_member_invite).to be_invite
+ expect(project_member_invite).to be_invite
+ end
end
- end
- context 'user is confirmed' do
- it 'accepts pending invites of the user' do
- expect(subject[:status]).to eq(:success)
+ context 'user is confirmed' do
+ it 'accepts pending invites of the user' do
+ expect(subject[:status]).to eq(:success)
- group_member_invite.reload
- project_member_invite.reload
+ group_member_invite.reload
+ project_member_invite.reload
- expect(group_member_invite).not_to be_invite
- expect(project_member_invite).not_to be_invite
- expect(group_member_invite.user).to eq(user)
- expect(project_member_invite.user).to eq(user)
+ expect(group_member_invite).not_to be_invite
+ expect(project_member_invite).not_to be_invite
+ expect(group_member_invite.user).to eq(user)
+ expect(project_member_invite.user).to eq(user)
+ end
end
end
end
diff --git a/spec/services/users/destroy_service_spec.rb b/spec/services/users/destroy_service_spec.rb
index 6de685dd89a..76b84e3b4ab 100644
--- a/spec/services/users/destroy_service_spec.rb
+++ b/spec/services/users/destroy_service_spec.rb
@@ -3,14 +3,14 @@
require 'spec_helper'
RSpec.describe Users::DestroyService do
- describe "Deletes a user and all their personal projects" do
- let!(:user) { create(:user) }
- let!(:admin) { create(:admin) }
- let!(:namespace) { user.namespace }
- let!(:project) { create(:project, namespace: namespace) }
- let(:service) { described_class.new(admin) }
- let(:gitlab_shell) { Gitlab::Shell.new }
-
+ let!(:user) { create(:user) }
+ let!(:admin) { create(:admin) }
+ let!(:namespace) { user.namespace }
+ let!(:project) { create(:project, namespace: namespace) }
+ let(:service) { described_class.new(admin) }
+ let(:gitlab_shell) { Gitlab::Shell.new }
+
+ describe "Deletes a user and all their personal projects", :enable_admin_mode do
context 'no options are given' do
it 'deletes the user' do
user_data = service.execute(user)
@@ -108,7 +108,7 @@ RSpec.describe Users::DestroyService do
context 'projects in pending_delete' do
before do
project.pending_delete = true
- project.save
+ project.save!
end
it 'destroys a project in pending_delete' do
@@ -215,35 +215,6 @@ RSpec.describe Users::DestroyService do
end
end
- context "deletion permission checks" do
- it 'does not delete the user when user is not an admin' do
- other_user = create(:user)
-
- expect { described_class.new(other_user).execute(user) }.to raise_error(Gitlab::Access::AccessDeniedError)
- expect(User.exists?(user.id)).to be(true)
- end
-
- it 'allows admins to delete anyone' do
- described_class.new(admin).execute(user)
-
- expect(User.exists?(user.id)).to be(false)
- end
-
- it 'allows users to delete their own account' do
- described_class.new(user).execute(user)
-
- expect(User.exists?(user.id)).to be(false)
- end
-
- it 'allows user to be deleted if skip_authorization: true' do
- other_user = create(:user)
-
- described_class.new(user).execute(other_user, skip_authorization: true)
-
- expect(User.exists?(other_user.id)).to be(false)
- end
- end
-
context "migrating associated records" do
let!(:issue) { create(:issue, author: user) }
@@ -310,7 +281,7 @@ RSpec.describe Users::DestroyService do
it 'of group_members' do
group_member = create(:group_member)
- group_member.group.group_members.create(user: user, access_level: 40)
+ group_member.group.group_members.create!(user: user, access_level: 40)
expect_any_instance_of(GroupMember).to receive(:run_callbacks).with(:find).once
expect_any_instance_of(GroupMember).to receive(:run_callbacks).with(:initialize).once
@@ -320,4 +291,43 @@ RSpec.describe Users::DestroyService do
end
end
end
+
+ describe "Deletion permission checks" do
+ it 'does not delete the user when user is not an admin' do
+ other_user = create(:user)
+
+ expect { described_class.new(other_user).execute(user) }.to raise_error(Gitlab::Access::AccessDeniedError)
+ expect(User.exists?(user.id)).to be(true)
+ end
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'allows admins to delete anyone' do
+ described_class.new(admin).execute(user)
+
+ expect(User.exists?(user.id)).to be(false)
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'disallows admins to delete anyone' do
+ expect { described_class.new(admin).execute(user) }.to raise_error(Gitlab::Access::AccessDeniedError)
+
+ expect(User.exists?(user.id)).to be(true)
+ end
+ end
+
+ it 'allows users to delete their own account' do
+ described_class.new(user).execute(user)
+
+ expect(User.exists?(user.id)).to be(false)
+ end
+
+ it 'allows user to be deleted if skip_authorization: true' do
+ other_user = create(:user)
+
+ described_class.new(user).execute(other_user, skip_authorization: true)
+
+ expect(User.exists?(other_user.id)).to be(false)
+ end
+ end
end
diff --git a/spec/services/users/repair_ldap_blocked_service_spec.rb b/spec/services/users/repair_ldap_blocked_service_spec.rb
index b33dcb92f45..54540d68af2 100644
--- a/spec/services/users/repair_ldap_blocked_service_spec.rb
+++ b/spec/services/users/repair_ldap_blocked_service_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Users::RepairLdapBlockedService do
describe '#execute' do
it 'changes to normal block after destroying last ldap identity' do
- identity.destroy
+ identity.destroy!
service.execute
expect(user.reload).not_to be_ldap_blocked
diff --git a/spec/services/users/set_status_service_spec.rb b/spec/services/users/set_status_service_spec.rb
index 54489adceb0..69cd647eaeb 100644
--- a/spec/services/users/set_status_service_spec.rb
+++ b/spec/services/users/set_status_service_spec.rb
@@ -9,13 +9,14 @@ RSpec.describe Users::SetStatusService do
describe '#execute' do
context 'when params are set' do
- let(:params) { { emoji: 'taurus', message: 'a random status' } }
+ let(:params) { { emoji: 'taurus', message: 'a random status', availability: 'busy' } }
it 'creates a status' do
service.execute
expect(current_user.status.emoji).to eq('taurus')
expect(current_user.status.message).to eq('a random status')
+ expect(current_user.status.availability).to eq('busy')
end
it 'updates a status if it already existed' do
@@ -25,13 +26,33 @@ RSpec.describe Users::SetStatusService do
expect(current_user.status.message).to eq('a random status')
end
+ it 'returns true' do
+ create(:user_status, user: current_user)
+ expect(service.execute).to be(true)
+ end
+
+ context 'when the given availability value is not valid' do
+ let(:params) { { availability: 'not a valid value' } }
+
+ it 'does not update the status' do
+ user_status = create(:user_status, user: current_user)
+
+ expect { service.execute }.not_to change { user_status.reload }
+ end
+
+ it 'returns false' do
+ create(:user_status, user: current_user)
+ expect(service.execute).to be(false)
+ end
+ end
+
context 'for another user' do
let(:target_user) { create(:user) }
let(:params) do
{ emoji: 'taurus', message: 'a random status', user: target_user }
end
- context 'the current user is admin' do
+ context 'the current user is admin', :enable_admin_mode do
let(:current_user) { create(:admin) }
it 'changes the status when the current user is allowed to do that' do
diff --git a/spec/services/verify_pages_domain_service_spec.rb b/spec/services/verify_pages_domain_service_spec.rb
index 29ad85a16ce..ae079229891 100644
--- a/spec/services/verify_pages_domain_service_spec.rb
+++ b/spec/services/verify_pages_domain_service_spec.rb
@@ -189,7 +189,7 @@ RSpec.describe VerifyPagesDomainService do
let(:domain) { build(:pages_domain, :expired, :with_missing_chain) }
before do
- domain.save(validate: false)
+ domain.save!(validate: false)
end
it 'can be disabled' do
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index b7b81d33c3e..a607a6734b0 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe WebHookService do
let(:headers) do
{
'Content-Type' => 'application/json',
+ 'User-Agent' => "GitLab/#{Gitlab::VERSION}",
'X-Gitlab-Event' => 'Push Hook'
}
end
diff --git a/spec/sidekiq/cron/job_gem_dependency_spec.rb b/spec/sidekiq/cron/job_gem_dependency_spec.rb
index 2924c86c8d0..38c658feba6 100644
--- a/spec/sidekiq/cron/job_gem_dependency_spec.rb
+++ b/spec/sidekiq/cron/job_gem_dependency_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Sidekiq::Cron::Job do
context 'when Fugit depends on ZoTime or EoTime' do
before do
described_class
- .create(name: 'TestCronWorker',
+ .create(name: 'TestCronWorker', # rubocop:disable Rails/SaveBang
cron: Settings.cron_jobs[:pipeline_schedule_worker]['cron'],
class: Settings.cron_jobs[:pipeline_schedule_worker]['job_class'])
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 11a45e005b8..38e3f851116 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,8 +1,19 @@
# frozen_string_literal: true
+# $" is $LOADED_FEATURES, but RuboCop didn't like it
+if $".include?(File.expand_path('fast_spec_helper.rb', __dir__))
+ warn 'Detected fast_spec_helper is loaded first than spec_helper.'
+ warn 'If running test files using both spec_helper and fast_spec_helper,'
+ warn 'make sure test file with spec_helper is loaded first.'
+ abort 'Aborting...'
+end
+
require './spec/simplecov_env'
SimpleCovEnv.start!
+require './spec/crystalball_env'
+CrystalballEnv.start!
+
ENV["RAILS_ENV"] = 'test'
ENV["IN_MEMORY_APPLICATION_SETTINGS"] = 'true'
ENV["RSPEC_ALLOW_INVALID_URLS"] = 'true'
@@ -45,6 +56,7 @@ require_relative('../ee/spec/spec_helper') if Gitlab.ee?
# Load these first since they may be required by other helpers
require Rails.root.join("spec/support/helpers/git_helpers.rb")
+require Rails.root.join("spec/support/helpers/stub_requests.rb")
# Then the rest
Dir[Rails.root.join("spec/support/helpers/*.rb")].sort.each { |f| require f }
@@ -119,7 +131,6 @@ 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
@@ -273,12 +284,10 @@ RSpec.configure do |config|
./ee/spec/lib
./ee/spec/requests/admin
./ee/spec/serializers
- ./ee/spec/services
./ee/spec/support/protected_tags
./ee/spec/support/shared_examples/features
./ee/spec/support/shared_examples/finders/geo
./ee/spec/support/shared_examples/graphql/geo
- ./ee/spec/support/shared_examples/services
./spec/features
./spec/finders
./spec/frontend
@@ -286,7 +295,6 @@ RSpec.configure do |config|
./spec/lib
./spec/requests
./spec/serializers
- ./spec/services
./spec/support/protected_tags
./spec/support/shared_examples/features
./spec/support/shared_examples/requests
@@ -358,7 +366,7 @@ RSpec.configure do |config|
end
config.before(:example, :prometheus) do
- matching_files = File.join(::Prometheus::Client.configuration.multiprocess_files_dir, "*.db")
+ matching_files = File.join(::Prometheus::Client.configuration.multiprocess_files_dir, "**/*.db")
Dir[matching_files].map { |filename| File.delete(filename) if File.file?(filename) }
Gitlab::Metrics.reset_registry!
diff --git a/spec/support/cycle_analytics_helpers/test_generation.rb b/spec/support/cycle_analytics_helpers/test_generation.rb
index c577e5cc665..f866220b919 100644
--- a/spec/support/cycle_analytics_helpers/test_generation.rb
+++ b/spec/support/cycle_analytics_helpers/test_generation.rb
@@ -6,7 +6,7 @@
# multiple nested contexts. This shouldn't count as a violation.
module CycleAnalyticsHelpers
module TestGeneration
- # Generate the most common set of specs that all cycle analytics phases need to have.
+ # Generate the most common set of specs that all value stream analytics phases need to have.
#
# Arguments:
#
@@ -14,10 +14,10 @@ module CycleAnalyticsHelpers
# data_fn: A function that returns a hash, constituting initial data for the test case
# start_time_conditions: An array of `conditions`. Each condition is an tuple of `condition_name` and `condition_fn`. `condition_fn` is called with
# `context` (no lexical scope, so need to do `context.create` for factories, for example) and `data` (from the `data_fn`).
- # Each `condition_fn` is expected to implement a case which consitutes the start of the given cycle analytics phase.
+ # Each `condition_fn` is expected to implement a case which consitutes the start of the given value stream analytics phase.
# end_time_conditions: An array of `conditions`. Each condition is an tuple of `condition_name` and `condition_fn`. `condition_fn` is called with
# `context` (no lexical scope, so need to do `context.create` for factories, for example) and `data` (from the `data_fn`).
- # Each `condition_fn` is expected to implement a case which consitutes the end of the given cycle analytics phase.
+ # Each `condition_fn` is expected to implement a case which consitutes the end of the given value stream analytics phase.
# before_end_fn: This function is run before calling the end time conditions. Used for setup that needs to be run between the start and end conditions.
# post_fn: Code that needs to be run after running the end time conditions.
diff --git a/spec/support/helpers/admin_mode_helpers.rb b/spec/support/helpers/admin_mode_helpers.rb
index 36ed262f8ae..a6e31791127 100644
--- a/spec/support/helpers/admin_mode_helpers.rb
+++ b/spec/support/helpers/admin_mode_helpers.rb
@@ -13,6 +13,8 @@ module AdminModeHelper
def enable_admin_mode!(user)
fake_user_mode = instance_double(Gitlab::Auth::CurrentUserMode)
+ allow(Gitlab::Auth::CurrentUserMode).to receive(:new).and_call_original
+
allow(Gitlab::Auth::CurrentUserMode).to receive(:new).with(user).and_return(fake_user_mode)
allow(fake_user_mode).to receive(:admin_mode?).and_return(user&.admin?)
end
diff --git a/spec/support/helpers/api_helpers.rb b/spec/support/helpers/api_helpers.rb
index b1e6078c4f2..d3cc7367b6e 100644
--- a/spec/support/helpers/api_helpers.rb
+++ b/spec/support/helpers/api_helpers.rb
@@ -61,7 +61,6 @@ module ApiHelpers
def expect_response_contain_exactly(*items)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
- expect(json_response.length).to eq(items.size)
expect(json_response.map { |item| item['id'] }).to contain_exactly(*items)
end
diff --git a/spec/support/helpers/dependency_proxy_helpers.rb b/spec/support/helpers/dependency_proxy_helpers.rb
new file mode 100644
index 00000000000..545b9d1f4d0
--- /dev/null
+++ b/spec/support/helpers/dependency_proxy_helpers.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module DependencyProxyHelpers
+ include StubRequests
+
+ def stub_registry_auth(image, token, status = 200, body = nil)
+ auth_body = { 'token' => token }.to_json
+ auth_link = registry.auth_url(image)
+
+ stub_full_request(auth_link)
+ .to_return(status: status, body: body || auth_body)
+ end
+
+ def stub_manifest_download(image, tag, status = 200, body = nil)
+ manifest_url = registry.manifest_url(image, tag)
+
+ stub_full_request(manifest_url)
+ .to_return(status: status, body: body || manifest)
+ end
+
+ def stub_blob_download(image, blob_sha, status = 200, body = '123456')
+ download_link = registry.blob_url(image, blob_sha)
+
+ stub_full_request(download_link)
+ .to_return(status: status, body: body)
+ end
+
+ private
+
+ def registry
+ @registry ||= DependencyProxy::Registry
+ end
+end
diff --git a/spec/support/helpers/features/members_table_helpers.rb b/spec/support/helpers/features/members_table_helpers.rb
new file mode 100644
index 00000000000..5394e370900
--- /dev/null
+++ b/spec/support/helpers/features/members_table_helpers.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Spec
+ module Support
+ module Helpers
+ module Features
+ module MembersHelpers
+ def members_table
+ page.find('[data-testid="members-table"]')
+ end
+
+ def all_rows
+ page.within(members_table) do
+ page.all('tbody > tr')
+ end
+ end
+
+ def first_row
+ all_rows[0]
+ end
+
+ def second_row
+ all_rows[1]
+ end
+
+ def third_row
+ all_rows[2]
+ end
+
+ def invite_users_form
+ page.find('[data-testid="invite-users-form"]')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/features/releases_helpers.rb b/spec/support/helpers/features/releases_helpers.rb
index 0d46918b05c..44087f71cfa 100644
--- a/spec/support/helpers/features/releases_helpers.rb
+++ b/spec/support/helpers/features/releases_helpers.rb
@@ -66,7 +66,7 @@ module Spec
focused_element.send_keys(:enter)
# Wait for the dropdown to be rendered
- page.find('.project-milestone-combobox .dropdown-menu')
+ page.find('.milestone-combobox .dropdown-menu')
# Clear any existing input
focused_element.attribute('value').length.times { focused_element.send_keys(:backspace) }
@@ -75,7 +75,7 @@ module Spec
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)
+ page.find('.milestone-combobox .dropdown-item', text: milestone_title, match: :first)
focused_element.send_keys(:arrow_down, :arrow_down, :enter)
diff --git a/spec/support/helpers/features/web_ide_spec_helpers.rb b/spec/support/helpers/features/web_ide_spec_helpers.rb
index 123bd9b5070..12d3cecd052 100644
--- a/spec/support/helpers/features/web_ide_spec_helpers.rb
+++ b/spec/support/helpers/features/web_ide_spec_helpers.rb
@@ -22,6 +22,8 @@ module WebIdeSpecHelpers
click_link('Web IDE')
wait_for_requests
+
+ save_monaco_editor_reference
end
def ide_tree_body
@@ -36,8 +38,8 @@ module WebIdeSpecHelpers
".js-ide-#{mode}-mode"
end
- def ide_file_row_open?(row)
- row.matches_css?('.is-open')
+ def ide_folder_row_open?(row)
+ row.matches_css?('.folder.is-open')
end
# Creates a file in the IDE by expanding directories
@@ -63,6 +65,17 @@ module WebIdeSpecHelpers
ide_set_editor_value(content)
end
+ def ide_rename_file(path, new_path)
+ container = ide_traverse_to_file(path)
+
+ click_file_action(container, 'Rename/Move')
+
+ within '#ide-new-entry' do
+ find('input').fill_in(with: new_path)
+ click_button('Rename file')
+ end
+ end
+
# Deletes a file by traversing to `path`
# then clicking the 'Delete' action.
#
@@ -90,8 +103,22 @@ module WebIdeSpecHelpers
container
end
+ def ide_close_file(name)
+ within page.find('.multi-file-tabs') do
+ click_button("Close #{name}")
+ end
+ end
+
+ def ide_open_file(path)
+ row = ide_traverse_to_file(path)
+
+ ide_open_file_row(row)
+
+ wait_for_requests
+ end
+
def ide_open_file_row(row)
- return if ide_file_row_open?(row)
+ return if ide_folder_row_open?(row)
row.click
end
@@ -103,6 +130,10 @@ module WebIdeSpecHelpers
execute_script("monaco.editor.getModel('#{uri}').setValue('#{escape_javascript(value)}')")
end
+ def ide_set_editor_position(line, col)
+ execute_script("TEST_EDITOR.setPosition(#{{ lineNumber: line, column: col }.to_json})")
+ end
+
def ide_editor_value
editor = find('.monaco-editor')
uri = editor['data-uri']
@@ -149,4 +180,8 @@ module WebIdeSpecHelpers
wait_for_requests
end
end
+
+ def save_monaco_editor_reference
+ evaluate_script("monaco.editor.onDidCreateEditor(editor => { window.TEST_EDITOR = editor; })")
+ end
end
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index db769041f1e..a1b4e6eee92 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -17,8 +17,8 @@ module GraphqlHelpers
# ready, then the early return is returned instead.
#
# Then the resolve method is called.
- def resolve(resolver_class, obj: nil, args: {}, ctx: {}, field: nil)
- resolver = resolver_class.new(object: obj, context: ctx, field: field)
+ def resolve(resolver_class, args: {}, **resolver_args)
+ resolver = resolver_instance(resolver_class, **resolver_args)
ready, early_return = sync_all { resolver.ready?(**args) }
return early_return unless ready
@@ -26,6 +26,15 @@ module GraphqlHelpers
resolver.resolve(**args)
end
+ def resolver_instance(resolver_class, obj: nil, ctx: {}, field: nil, schema: GitlabSchema)
+ if ctx.is_a?(Hash)
+ q = double('Query', schema: schema)
+ ctx = GraphQL::Query::Context.new(query: q, object: obj, values: ctx)
+ end
+
+ resolver_class.new(object: obj, context: ctx, field: field)
+ end
+
# Eagerly run a loader's named resolver
# (syncs any lazy values returned by resolve)
def eager_resolve(resolver_class, **opts)
@@ -112,6 +121,16 @@ module GraphqlHelpers
end
end
+ def resolve_field(name, object, args = {})
+ context = double("Context",
+ schema: GitlabSchema,
+ query: GraphQL::Query.new(GitlabSchema),
+ parent: nil)
+ field = described_class.fields[name]
+ instance = described_class.authorized_new(object, context)
+ field.resolve_field(instance, {}, context)
+ end
+
# Recursively convert a Hash with Ruby-style keys to GraphQL fieldname-style keys
#
# prepare_input_for_mutation({ 'my_key' => 1 })
@@ -468,6 +487,8 @@ module GraphqlHelpers
use Gitlab::Graphql::Authorize
use Gitlab::Graphql::Pagination::Connections
+ lazy_resolve ::Gitlab::Graphql::Lazy, :force
+
query(query_type)
end
diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index 113bb31e4be..ff61cceba06 100644
--- a/spec/support/helpers/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
@@ -33,8 +33,8 @@ module KubernetesHelpers
kube_response(kube_deployments_body)
end
- def kube_ingresses_response
- kube_response(kube_ingresses_body)
+ def kube_ingresses_response(with_canary: false)
+ kube_response(kube_ingresses_body(with_canary: with_canary))
end
def stub_kubeclient_discover_base(api_url)
@@ -155,12 +155,12 @@ module KubernetesHelpers
WebMock.stub_request(:get, deployments_url).to_return(response || kube_deployments_response)
end
- def stub_kubeclient_ingresses(namespace, status: nil)
+ def stub_kubeclient_ingresses(namespace, status: nil, method: :get, resource_path: "", response: kube_ingresses_response)
stub_kubeclient_discover(service.api_url)
- ingresses_url = service.api_url + "/apis/extensions/v1beta1/namespaces/#{namespace}/ingresses"
+ ingresses_url = service.api_url + "/apis/extensions/v1beta1/namespaces/#{namespace}/ingresses#{resource_path}"
response = { status: status } if status
- WebMock.stub_request(:get, ingresses_url).to_return(response || kube_ingresses_response)
+ WebMock.stub_request(method, ingresses_url).to_return(response)
end
def stub_kubeclient_knative_services(options = {})
@@ -250,6 +250,11 @@ module KubernetesHelpers
.to_return(kube_response({}))
end
+ def stub_kubeclient_delete_role_binding(api_url, name, namespace: 'default')
+ WebMock.stub_request(:delete, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings/#{name}")
+ .to_return(kube_response({}))
+ end
+
def stub_kubeclient_put_role_binding(api_url, name, namespace: 'default')
WebMock.stub_request(:put, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings/#{name}")
.to_return(kube_response({}))
@@ -541,10 +546,12 @@ module KubernetesHelpers
}
end
- def kube_ingresses_body
+ def kube_ingresses_body(with_canary: false)
+ items = with_canary ? [kube_ingress, kube_ingress(track: :canary)] : [kube_ingress]
+
{
"kind" => "List",
- "items" => [kube_ingress]
+ "items" => items
}
end
diff --git a/spec/support/helpers/lfs_http_helpers.rb b/spec/support/helpers/lfs_http_helpers.rb
index 0537b122040..199d5e70e32 100644
--- a/spec/support/helpers/lfs_http_helpers.rb
+++ b/spec/support/helpers/lfs_http_helpers.rb
@@ -31,16 +31,16 @@ module LfsHttpHelpers
post(url, params: params, headers: headers)
end
- def batch_url(project)
- "#{project.http_url_to_repo}/info/lfs/objects/batch"
+ def batch_url(container)
+ "#{container.http_url_to_repo}/info/lfs/objects/batch"
end
- def objects_url(project, oid = nil, size = nil)
- File.join(["#{project.http_url_to_repo}/gitlab-lfs/objects", oid, size].compact.map(&:to_s))
+ def objects_url(container, oid = nil, size = nil)
+ File.join(["#{container.http_url_to_repo}/gitlab-lfs/objects", oid, size].compact.map(&:to_s))
end
- def authorize_url(project, oid, size)
- File.join(objects_url(project, oid, size), 'authorize')
+ def authorize_url(container, oid, size)
+ File.join(objects_url(container, oid, size), 'authorize')
end
def download_body(objects)
diff --git a/spec/support/helpers/navbar_structure_helper.rb b/spec/support/helpers/navbar_structure_helper.rb
index 11e67ba394c..e18a708e41c 100644
--- a/spec/support/helpers/navbar_structure_helper.rb
+++ b/spec/support/helpers/navbar_structure_helper.rb
@@ -36,4 +36,12 @@ module NavbarStructureHelper
new_sub_nav_item_name: _('Container Registry')
)
end
+
+ def insert_dependency_proxy_nav(within)
+ insert_after_sub_nav_item(
+ _('Package Registry'),
+ within: _('Packages & Registries'),
+ new_sub_nav_item_name: _('Dependency Proxy')
+ )
+ end
end
diff --git a/spec/support/helpers/require_migration.rb b/spec/support/helpers/require_migration.rb
index d3f192a4142..c2902aa4ec7 100644
--- a/spec/support/helpers/require_migration.rb
+++ b/spec/support/helpers/require_migration.rb
@@ -3,26 +3,46 @@
require 'find'
class RequireMigration
- MIGRATION_FOLDERS = %w(db/migrate db/post_migrate ee/db/geo/migrate ee/db/geo/post_migrate).freeze
+ class AutoLoadError < RuntimeError
+ MESSAGE = "Can not find any migration file for `%{file_name}`!\n" \
+ "You can try to provide the migration file name manually."
+
+ def initialize(file_name)
+ message = format(MESSAGE, file_name: file_name)
+
+ super(message)
+ end
+ end
+
+ MIGRATION_FOLDERS = %w[db/migrate db/post_migrate].freeze
SPEC_FILE_PATTERN = /.+\/(?<file_name>.+)_spec\.rb/.freeze
class << self
def require_migration!(file_name)
file_paths = search_migration_file(file_name)
+ raise AutoLoadError.new(file_name) unless file_paths.first
require file_paths.first
end
def search_migration_file(file_name)
- MIGRATION_FOLDERS.flat_map do |path|
+ migration_folders.flat_map do |path|
migration_path = Rails.root.join(path).to_s
Find.find(migration_path).grep(/\d+_#{file_name}\.rb/)
end
end
+
+ private
+
+ def migration_folders
+ MIGRATION_FOLDERS
+ end
end
end
+RequireMigration.prepend_if_ee('EE::RequireMigration')
+
def require_migration!(file_name = nil)
location_info = caller_locations.first.path.match(RequireMigration::SPEC_FILE_PATTERN)
file_name ||= location_info[:file_name]
diff --git a/spec/support/helpers/search_helpers.rb b/spec/support/helpers/search_helpers.rb
index 328f272724a..3d4ff4801a7 100644
--- a/spec/support/helpers/search_helpers.rb
+++ b/spec/support/helpers/search_helpers.rb
@@ -3,13 +3,14 @@
module SearchHelpers
def fill_in_search(text)
page.within('.search-input-wrap') do
+ find('#search').click
fill_in('search', with: text)
end
wait_for_all_requests
end
- def submit_search(query, scope: nil)
+ def submit_search(query)
page.within('.search-form, .search-page-form') do
field = find_field('search')
field.fill_in(with: query)
diff --git a/spec/support/helpers/snowplow_helpers.rb b/spec/support/helpers/snowplow_helpers.rb
index 3bde01c6fbf..15eac1b24fc 100644
--- a/spec/support/helpers/snowplow_helpers.rb
+++ b/spec/support/helpers/snowplow_helpers.rb
@@ -32,16 +32,8 @@ module SnowplowHelpers
# end
# end
def expect_snowplow_event(category:, action:, **kwargs)
- # This check will no longer be needed with Ruby 2.7 which
- # would not pass any arguments when using **kwargs.
- # https://gitlab.com/gitlab-org/gitlab/-/issues/263430
- if kwargs.present?
- expect(Gitlab::Tracking).to have_received(:event)
- .with(category, action, **kwargs).at_least(:once)
- else
- expect(Gitlab::Tracking).to have_received(:event)
- .with(category, action).at_least(:once)
- end
+ expect(Gitlab::Tracking).to have_received(:event) # rubocop:disable RSpec/ExpectGitlabTracking
+ .with(category, action, **kwargs).at_least(:once)
end
# Asserts that no call to `Gitlab::Tracking#event` was made.
@@ -56,6 +48,6 @@ module SnowplowHelpers
# end
# end
def expect_no_snowplow_event
- expect(Gitlab::Tracking).not_to have_received(:event)
+ expect(Gitlab::Tracking).not_to have_received(:event) # rubocop:disable RSpec/ExpectGitlabTracking
end
end
diff --git a/spec/support/helpers/table_schema_helpers.rb b/spec/support/helpers/table_schema_helpers.rb
new file mode 100644
index 00000000000..28794211190
--- /dev/null
+++ b/spec/support/helpers/table_schema_helpers.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+module TableSchemaHelpers
+ def connection
+ ActiveRecord::Base.connection
+ end
+
+ def expect_table_to_be_replaced(original_table:, replacement_table:, archived_table:)
+ original_oid = table_oid(original_table)
+ replacement_oid = table_oid(replacement_table)
+
+ yield
+
+ expect(table_oid(original_table)).to eq(replacement_oid)
+ expect(table_oid(archived_table)).to eq(original_oid)
+ expect(table_oid(replacement_table)).to be_nil
+ end
+
+ def expect_index_to_exist(name, schema: nil)
+ expect(index_exists_by_name(name, schema: schema)).to eq(true)
+ end
+
+ def expect_index_not_to_exist(name, schema: nil)
+ expect(index_exists_by_name(name, schema: schema)).to be_nil
+ end
+
+ def expect_primary_keys_after_tables(tables, schema: nil)
+ tables.each do |table|
+ primary_key = primary_key_constraint_name(table, schema: schema)
+
+ expect(primary_key).to eq("#{table}_pkey")
+ end
+ end
+
+ def table_oid(name)
+ connection.select_value(<<~SQL)
+ SELECT oid
+ FROM pg_catalog.pg_class
+ WHERE relname = '#{name}'
+ SQL
+ end
+
+ def table_type(name)
+ connection.select_value(<<~SQL)
+ SELECT
+ CASE class.relkind
+ WHEN 'r' THEN 'normal'
+ WHEN 'p' THEN 'partitioned'
+ ELSE 'other'
+ END as table_type
+ FROM pg_catalog.pg_class class
+ WHERE class.relname = '#{name}'
+ SQL
+ end
+
+ def sequence_owned_by(table_name, column_name)
+ connection.select_value(<<~SQL)
+ SELECT
+ sequence.relname as name
+ FROM pg_catalog.pg_class as sequence
+ INNER JOIN pg_catalog.pg_depend depend
+ ON depend.objid = sequence.oid
+ INNER JOIN pg_catalog.pg_class class
+ ON class.oid = depend.refobjid
+ INNER JOIN pg_catalog.pg_attribute attribute
+ ON attribute.attnum = depend.refobjsubid
+ AND attribute.attrelid = depend.refobjid
+ WHERE class.relname = '#{table_name}'
+ AND attribute.attname = '#{column_name}'
+ SQL
+ end
+
+ def default_expression_for(table_name, column_name)
+ connection.select_value(<<~SQL)
+ SELECT
+ pg_get_expr(attrdef.adbin, attrdef.adrelid) AS default_value
+ FROM pg_catalog.pg_attribute attribute
+ INNER JOIN pg_catalog.pg_attrdef attrdef
+ ON attribute.attrelid = attrdef.adrelid
+ AND attribute.attnum = attrdef.adnum
+ WHERE attribute.attrelid = '#{table_name}'::regclass
+ AND attribute.attname = '#{column_name}'
+ SQL
+ end
+
+ def primary_key_constraint_name(table_name, schema: nil)
+ table_name = schema ? "#{schema}.#{table_name}" : table_name
+
+ connection.select_value(<<~SQL)
+ SELECT
+ conname AS constraint_name
+ FROM pg_catalog.pg_constraint
+ WHERE pg_constraint.conrelid = '#{table_name}'::regclass
+ AND pg_constraint.contype = 'p'
+ SQL
+ end
+
+ def index_exists_by_name(index, schema: nil)
+ schema = schema ? "'#{schema}'" : 'current_schema'
+
+ connection.select_value(<<~SQL)
+ SELECT true
+ FROM pg_catalog.pg_index i
+ INNER JOIN pg_catalog.pg_class c
+ ON c.oid = i.indexrelid
+ INNER JOIN pg_catalog.pg_namespace n
+ ON c.relnamespace = n.oid
+ WHERE c.relname = '#{index}'
+ AND n.nspname = #{schema}
+ SQL
+ end
+end
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index 641ed24207e..4c78ca0117c 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -517,6 +517,8 @@ module TestEnv
return false if component_matches_git_sha?(component_folder, expected_version)
+ return false if component_ahead_of_target?(component_folder, expected_version)
+
version = File.read(File.join(component_folder, 'VERSION')).strip
# Notice that this will always yield true when using branch versions
@@ -527,6 +529,20 @@ module TestEnv
true
end
+ def component_ahead_of_target?(component_folder, expected_version)
+ # The HEAD of the component_folder will be used as heuristic for the version
+ # of the binaries, allowing to use Git to determine if HEAD is later than
+ # the expected version. Note: Git considers HEAD to be an anchestor of HEAD.
+ _out, exit_status = Gitlab::Popen.popen(%W[
+ #{Gitlab.config.git.bin_path}
+ -C #{component_folder}
+ merge-base --is-ancestor
+ #{expected_version} HEAD
+])
+
+ exit_status == 0
+ end
+
def component_matches_git_sha?(component_folder, expected_version)
# Not a git SHA, so return early
return false unless expected_version =~ ::Gitlab::Git::COMMIT_ID
diff --git a/spec/support/helpers/usage_data_helpers.rb b/spec/support/helpers/usage_data_helpers.rb
index 2592d9f8b42..8e8aeea2ea1 100644
--- a/spec/support/helpers/usage_data_helpers.rb
+++ b/spec/support/helpers/usage_data_helpers.rb
@@ -98,6 +98,7 @@ module UsageDataHelpers
projects_with_repositories_enabled
projects_with_error_tracking_enabled
projects_with_alerts_service_enabled
+ projects_with_enabled_alert_integrations
projects_with_prometheus_alerts
projects_with_tracing_enabled
projects_with_expiration_policy_enabled
diff --git a/spec/support/helpers/user_login_helper.rb b/spec/support/helpers/user_login_helper.rb
index 66606832883..47e858cb68c 100644
--- a/spec/support/helpers/user_login_helper.rb
+++ b/spec/support/helpers/user_login_helper.rb
@@ -1,18 +1,25 @@
# frozen_string_literal: true
module UserLoginHelper
- def ensure_tab_pane_correctness(visit_path = true)
- if visit_path
- visit new_user_session_path
- end
-
- ensure_tab_pane_counts
+ def ensure_tab_pane_correctness(tab_names)
+ ensure_tab_pane_counts(tab_names.size)
+ ensure_tab_labels(tab_names)
ensure_one_active_tab
ensure_one_active_pane
end
- def ensure_tab_pane_counts
- tabs_count = page.all('[role="tab"]').size
+ def ensure_no_tabs
+ expect(page.all('[role="tab"]').size).to eq(0)
+ end
+
+ def ensure_tab_labels(tab_names)
+ tab_labels = page.all('[role="tab"]').map(&:text)
+
+ expect(tab_names).to match_array(tab_labels)
+ end
+
+ def ensure_tab_pane_counts(tabs_count)
+ expect(page.all('[role="tab"]').size).to eq(tabs_count)
expect(page).to have_selector('[role="tabpanel"]', visible: :all, count: tabs_count)
end
diff --git a/spec/support/helpers/wiki_helpers.rb b/spec/support/helpers/wiki_helpers.rb
index 8873a90579d..e276c896da2 100644
--- a/spec/support/helpers/wiki_helpers.rb
+++ b/spec/support/helpers/wiki_helpers.rb
@@ -4,7 +4,6 @@ module WikiHelpers
extend self
def stub_group_wikis(enabled)
- stub_feature_flags(group_wikis: enabled)
stub_licensed_features(group_wikis: enabled)
end
diff --git a/spec/support/import_export/common_util.rb b/spec/support/import_export/common_util.rb
index c0c3559cca0..ae951ea35af 100644
--- a/spec/support/import_export/common_util.rb
+++ b/spec/support/import_export/common_util.rb
@@ -15,7 +15,7 @@ module ImportExport
export_path = [prefix, 'spec', 'fixtures', 'lib', 'gitlab', 'import_export', name].compact
export_path = File.join(*export_path)
- allow_any_instance_of(Gitlab::ImportExport).to receive(:export_path) { export_path }
+ allow(Gitlab::ImportExport).to receive(:export_path) { export_path }
end
def setup_reader(reader)
diff --git a/spec/support/matchers/graphql_matchers.rb b/spec/support/matchers/graphql_matchers.rb
index 7fa06e25405..8c4ba387a74 100644
--- a/spec/support/matchers/graphql_matchers.rb
+++ b/spec/support/matchers/graphql_matchers.rb
@@ -109,15 +109,82 @@ RSpec::Matchers.define :have_graphql_arguments do |*expected|
end
end
-RSpec::Matchers.define :have_graphql_type do |expected|
- match do |field|
- expect(field.type).to eq(expected)
+module GraphQLTypeHelpers
+ def message(object, expected, **opts)
+ non_null = expected.non_null? || (opts.key?(:null) && !opts[:null])
+
+ actual = object.type
+ actual_type = actual.unwrap.graphql_name
+ actual_type += '!' if actual.non_null?
+
+ expected_type = expected.unwrap.graphql_name
+ expected_type += '!' if non_null
+
+ "expected #{describe_object(object)} to have GraphQL type #{expected_type}, but got #{actual_type}"
+ end
+
+ def describe_object(object)
+ case object
+ when Types::BaseField
+ "#{describe_object(object.owner_type)}.#{object.graphql_name}"
+ when Types::BaseArgument
+ "#{describe_object(object.owner)}.#{object.graphql_name}"
+ when Class
+ object.try(:graphql_name) || object.name
+ else
+ object.to_s
+ end
+ end
+
+ def nullified(type, can_be_nil)
+ return type if can_be_nil.nil? # unknown!
+ return type if can_be_nil
+
+ type.to_non_null_type
+ end
+end
+
+RSpec::Matchers.define :have_graphql_type do |expected, opts = {}|
+ include GraphQLTypeHelpers
+
+ match do |object|
+ expect(object.type).to eq(nullified(expected, opts[:null]))
+ end
+
+ failure_message do |object|
+ message(object, expected, **opts)
+ end
+end
+
+RSpec::Matchers.define :have_nullable_graphql_type do |expected|
+ include GraphQLTypeHelpers
+
+ match do |object|
+ expect(object).to have_graphql_type(expected.unwrap, { null: true })
+ end
+
+ description do
+ "have nullable GraphQL type #{expected.graphql_name}"
+ end
+
+ failure_message do |object|
+ message(object, expected, null: true)
end
end
RSpec::Matchers.define :have_non_null_graphql_type do |expected|
- match do |field|
- expect(field.type.to_graphql).to eq(!expected.to_graphql)
+ include GraphQLTypeHelpers
+
+ match do |object|
+ expect(object).to have_graphql_type(expected, { null: false })
+ end
+
+ description do
+ "have non-null GraphQL type #{expected.graphql_name}"
+ end
+
+ failure_message do |object|
+ message(object, expected, null: false)
end
end
diff --git a/spec/support/patches/rspec_mocks_prepended_methods.rb b/spec/support/patches/rspec_mocks_prepended_methods.rb
new file mode 100644
index 00000000000..fa3a74c670c
--- /dev/null
+++ b/spec/support/patches/rspec_mocks_prepended_methods.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+# This patch allows stubbing of prepended methods
+# Based on https://github.com/rspec/rspec-mocks/pull/1218
+
+module RSpec
+ module Mocks
+ module InstanceMethodStasherForPrependedMethods
+ private
+
+ def method_owned_by_klass?
+ owner = @klass.instance_method(@method).owner
+ owner = owner.class unless Module === owner
+
+ owner == @klass ||
+ # When `extend self` is used, and not under any instance of
+ (owner.singleton_class == @klass && !Mocks.space.any_instance_recorder_for(owner, true)) ||
+ !method_defined_on_klass?(owner)
+ end
+ end
+ end
+end
+
+module RSpec
+ module Mocks
+ module MethodDoubleForPrependedMethods
+ def restore_original_method
+ return show_frozen_warning if object_singleton_class.frozen?
+ return unless @method_is_proxied
+
+ remove_method_from_definition_target
+
+ if @method_stasher.method_is_stashed?
+ @method_stasher.restore
+ restore_original_visibility
+ end
+
+ @method_is_proxied = false
+ end
+
+ def restore_original_visibility
+ method_owner.__send__(@original_visibility, @method_name)
+ end
+
+ private
+
+ def method_owner
+ @method_owner ||= Object.instance_method(:method).bind(object).call(@method_name).owner
+ end
+ end
+ end
+end
+
+RSpec::Mocks::InstanceMethodStasher.prepend(RSpec::Mocks::InstanceMethodStasherForPrependedMethods)
+RSpec::Mocks::MethodDouble.prepend(RSpec::Mocks::MethodDoubleForPrependedMethods)
diff --git a/spec/support/rspec.rb b/spec/support/rspec.rb
index 861b57c9efa..32f738faa9b 100644
--- a/spec/support/rspec.rb
+++ b/spec/support/rspec.rb
@@ -5,6 +5,13 @@ require_relative "helpers/stub_metrics"
require_relative "helpers/stub_object_storage"
require_relative "helpers/stub_env"
require_relative "helpers/fast_rails_root"
+
+# so we need to load rubocop here due to the rubocop support file loading cop_helper
+# which monkey patches class Cop
+# if cop helper is loaded before rubocop (where class Cop is defined as class Cop < Base)
+# we get a `superclass mismatch for class Cop` error when running a rspec for a locally defined
+# rubocop cop - therefore we need rubocop required first since it had an inheritance added to the Cop class
+require 'rubocop'
require 'rubocop/rspec/support'
RSpec.configure do |config|
diff --git a/spec/support/services/issuable_import_csv_service_shared_examples.rb b/spec/support/services/issuable_import_csv_service_shared_examples.rb
new file mode 100644
index 00000000000..20ac2ff5c7c
--- /dev/null
+++ b/spec/support/services/issuable_import_csv_service_shared_examples.rb
@@ -0,0 +1,142 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'issuable import csv service' do |issuable_type|
+ let_it_be_with_refind(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ subject { service.execute }
+
+ shared_examples_for 'an issuable importer' do
+ if issuable_type == 'issue'
+ it 'records the import attempt if resource is an issue' do
+ expect { subject }
+ .to change { Issues::CsvImport.where(project: project, user: user).count }
+ .by 1
+ end
+ end
+ end
+
+ shared_examples_for 'importer with email notification' do
+ it 'notifies user of import result' do
+ expect(Notify).to receive_message_chain(email_method, :deliver_later)
+
+ subject
+ end
+ end
+
+ describe '#execute' do
+ context 'invalid file' do
+ let(:file) { fixture_file_upload('spec/fixtures/banana_sample.gif') }
+
+ it 'returns invalid file error' do
+ expect(subject[:success]).to eq(0)
+ expect(subject[:parse_error]).to eq(true)
+ end
+
+ it_behaves_like 'importer with email notification'
+ it_behaves_like 'an issuable importer'
+ end
+
+ context 'file without headers' do
+ let(:file) { fixture_file_upload('spec/fixtures/csv_no_headers.csv') }
+
+ it 'returns invalid file error' do
+ expect(subject[:success]).to eq(0)
+ expect(subject[:parse_error]).to eq(true)
+ end
+
+ it_behaves_like 'importer with email notification'
+ it_behaves_like 'an issuable importer'
+ end
+
+ context 'with a file generated by Gitlab CSV export' do
+ let(:file) { fixture_file_upload('spec/fixtures/csv_gitlab_export.csv') }
+
+ it 'imports the CSV without errors' do
+ expect(subject[:success]).to eq(4)
+ expect(subject[:error_lines]).to eq([])
+ expect(subject[:parse_error]).to eq(false)
+ end
+
+ it 'correctly sets the issuable attributes' do
+ expect { subject }.to change { issuables.count }.by 4
+
+ expect(issuables.reload.last).to have_attributes(
+ title: 'Test Title',
+ description: 'Test Description'
+ )
+ end
+
+ it_behaves_like 'importer with email notification'
+ it_behaves_like 'an issuable importer'
+ end
+
+ context 'comma delimited file' do
+ let(:file) { fixture_file_upload('spec/fixtures/csv_comma.csv') }
+
+ it 'imports CSV without errors' do
+ expect(subject[:success]).to eq(3)
+ expect(subject[:error_lines]).to eq([])
+ expect(subject[:parse_error]).to eq(false)
+ end
+
+ it 'correctly sets the issuable attributes' do
+ expect { subject }.to change { issuables.count }.by 3
+
+ expect(issuables.reload.last).to have_attributes(
+ title: 'Title with quote"',
+ description: 'Description'
+ )
+ end
+
+ it_behaves_like 'importer with email notification'
+ it_behaves_like 'an issuable importer'
+ end
+
+ context 'tab delimited file with error row' do
+ let(:file) { fixture_file_upload('spec/fixtures/csv_tab.csv') }
+
+ it 'imports CSV with some error rows' do
+ expect(subject[:success]).to eq(2)
+ expect(subject[:error_lines]).to eq([3])
+ expect(subject[:parse_error]).to eq(false)
+ end
+
+ it 'correctly sets the issuable attributes' do
+ expect { subject }.to change { issuables.count }.by 2
+
+ expect(issuables.reload.last).to have_attributes(
+ title: 'Hello',
+ description: 'World'
+ )
+ end
+
+ it_behaves_like 'importer with email notification'
+ it_behaves_like 'an issuable importer'
+ end
+
+ context 'semicolon delimited file with CRLF' do
+ let(:file) { fixture_file_upload('spec/fixtures/csv_semicolon.csv') }
+
+ it 'imports CSV with a blank row' do
+ expect(subject[:success]).to eq(3)
+ expect(subject[:error_lines]).to eq([4])
+ expect(subject[:parse_error]).to eq(false)
+ end
+
+ it 'correctly sets the issuable attributes' do
+ expect { subject }.to change { issuables.count }.by 3
+
+ expect(issuables.reload.last).to have_attributes(
+ title: 'Hello',
+ description: 'World'
+ )
+ end
+
+ it_behaves_like 'importer with email notification'
+ it_behaves_like 'an issuable importer'
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/design_management_shared_contexts.rb b/spec/support/shared_contexts/design_management_shared_contexts.rb
index 3ff6a521338..e6ae7e03664 100644
--- a/spec/support/shared_contexts/design_management_shared_contexts.rb
+++ b/spec/support/shared_contexts/design_management_shared_contexts.rb
@@ -18,12 +18,14 @@ RSpec.shared_context 'four designs in three versions' do
modified_designs: [],
deleted_designs: [])
end
+
let_it_be(:second_version) do
create(:design_version, issue: issue,
created_designs: [design_b, design_c, design_d],
modified_designs: [design_a],
deleted_designs: [])
end
+
let_it_be(:third_version) do
create(:design_version, issue: issue,
created_designs: [],
diff --git a/spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb
index 2b6edb4c07d..68ff16922d8 100644
--- a/spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb
+++ b/spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb
@@ -1,21 +1,21 @@
# frozen_string_literal: true
RSpec.shared_context 'GroupProjectsFinder context' do
- let(:group) { create(:group) }
- let(:subgroup) { create(:group, parent: group) }
- let(:current_user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let_it_be(:current_user) { create(:user) }
let(:params) { {} }
let(:options) { {} }
let(:finder) { described_class.new(group: group, current_user: current_user, params: params, options: options) }
- let!(:public_project) { create(:project, :public, group: group, path: '1') }
- let!(:private_project) { create(:project, :private, group: group, path: '2') }
- let!(:shared_project_1) { create(:project, :public, path: '3') }
- let!(:shared_project_2) { create(:project, :private, path: '4') }
- let!(:shared_project_3) { create(:project, :internal, path: '5') }
- let!(:subgroup_project) { create(:project, :public, path: '6', group: subgroup) }
- let!(:subgroup_private_project) { create(:project, :private, path: '7', group: subgroup) }
+ let_it_be(:public_project) { create(:project, :public, group: group, path: '1') }
+ let_it_be(:private_project) { create(:project, :private, group: group, path: '2') }
+ let_it_be(:shared_project_1) { create(:project, :public, path: '3') }
+ let_it_be(:shared_project_2) { create(:project, :private, path: '4') }
+ let_it_be(:shared_project_3) { create(:project, :internal, path: '5') }
+ let_it_be(:subgroup_project) { create(:project, :public, path: '6', group: subgroup) }
+ let_it_be(:subgroup_private_project) { create(:project, :private, path: '7', group: subgroup) }
before do
shared_project_1.project_group_links.create!(group_access: Gitlab::Access::MAINTAINER, group: group)
diff --git a/spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb
index 010c445d8df..88c31bf9cfd 100644
--- a/spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb
+++ b/spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb
@@ -23,6 +23,7 @@ RSpec.shared_context 'MergeRequestsFinder multiple projects with merge requests
# We cannot use `let_it_be` here otherwise we get:
# Failure/Error: allow(RepositoryForkWorker).to receive(:perform_async).and_return(true)
# The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported.
+
let!(:project2) do
allow_gitaly_n_plus_1 do
fork_project(project1, user)
@@ -40,9 +41,11 @@ RSpec.shared_context 'MergeRequestsFinder multiple projects with merge requests
let_it_be(:project4, reload: true) do
allow_gitaly_n_plus_1 { create(:project, :repository, group: subgroup) }
end
+
let_it_be(:project5, reload: true) do
allow_gitaly_n_plus_1 { create(:project, group: subgroup) }
end
+
let_it_be(:project6, reload: true) do
allow_gitaly_n_plus_1 { create(:project, group: subgroup) }
end
diff --git a/spec/support/shared_contexts/lib/gitlab/middleware/with_a_mocked_gitlab_instance_shared_context.rb b/spec/support/shared_contexts/lib/gitlab/middleware/with_a_mocked_gitlab_instance_shared_context.rb
new file mode 100644
index 00000000000..3830b89f1ff
--- /dev/null
+++ b/spec/support/shared_contexts/lib/gitlab/middleware/with_a_mocked_gitlab_instance_shared_context.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'with a mocked GitLab instance' do
+ let(:rack_stack) do
+ rack = Rack::Builder.new do
+ use ActionDispatch::Session::CacheStore
+ use ActionDispatch::Flash
+ end
+
+ rack.run(subject)
+ rack.to_app
+ end
+
+ let(:observe_env) do
+ Module.new do
+ attr_reader :env
+
+ def call(env)
+ @env = env
+ super
+ end
+ end
+ end
+
+ let(:request) { Rack::MockRequest.new(rack_stack) }
+
+ subject do
+ described_class.new(fake_app).tap do |app|
+ app.extend(observe_env)
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index 9ebfdcb9522..ed74c3f179f 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -56,6 +56,7 @@ RSpec.shared_context 'project navbar structure' do
nav_item: _('CI / CD'),
nav_sub_items: [
_('Pipelines'),
+ s_('Pipelines|Editor'),
_('Jobs'),
_('Artifacts'),
_('Schedules')
@@ -71,6 +72,7 @@ RSpec.shared_context 'project navbar structure' do
_('Alerts'),
_('Incidents'),
_('Serverless'),
+ _('Terraform'),
_('Kubernetes'),
_('Environments'),
_('Feature Flags'),
diff --git a/spec/support/shared_contexts/policies/project_policy_table_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_table_shared_context.rb
index efd82ecb15a..8c9a60fa703 100644
--- a/spec/support/shared_contexts/policies/project_policy_table_shared_context.rb
+++ b/spec/support/shared_contexts/policies/project_policy_table_shared_context.rb
@@ -3,6 +3,8 @@
RSpec.shared_context 'ProjectPolicyTable context' do
using RSpec::Parameterized::TableSyntax
+ include AdminModeHelper
+
let(:pendings) { {} }
let(:pending?) do
pendings.include?(
@@ -10,106 +12,117 @@ RSpec.shared_context 'ProjectPolicyTable context' do
project_level: project_level,
feature_access_level: feature_access_level,
membership: membership,
+ admin_mode: admin_mode,
expected_count: expected_count
}
)
end
# rubocop:disable Metrics/AbcSize
- # project_level, :feature_access_level, :membership, :expected_count
+ # project_level, :feature_access_level, :membership, :admin_mode, :expected_count
def permission_table_for_reporter_feature_access
- :public | :enabled | :admin | 1
- :public | :enabled | :reporter | 1
- :public | :enabled | :guest | 1
- :public | :enabled | :non_member | 1
- :public | :enabled | :anonymous | 1
-
- :public | :private | :admin | 1
- :public | :private | :reporter | 1
- :public | :private | :guest | 0
- :public | :private | :non_member | 0
- :public | :private | :anonymous | 0
-
- :public | :disabled | :reporter | 0
- :public | :disabled | :guest | 0
- :public | :disabled | :non_member | 0
- :public | :disabled | :anonymous | 0
-
- :internal | :enabled | :admin | 1
- :internal | :enabled | :reporter | 1
- :internal | :enabled | :guest | 1
- :internal | :enabled | :non_member | 1
- :internal | :enabled | :anonymous | 0
-
- :internal | :private | :admin | 1
- :internal | :private | :reporter | 1
- :internal | :private | :guest | 0
- :internal | :private | :non_member | 0
- :internal | :private | :anonymous | 0
-
- :internal | :disabled | :reporter | 0
- :internal | :disabled | :guest | 0
- :internal | :disabled | :non_member | 0
- :internal | :disabled | :anonymous | 0
-
- :private | :private | :admin | 1
- :private | :private | :reporter | 1
- :private | :private | :guest | 0
- :private | :private | :non_member | 0
- :private | :private | :anonymous | 0
-
- :private | :disabled | :reporter | 0
- :private | :disabled | :guest | 0
- :private | :disabled | :non_member | 0
- :private | :disabled | :anonymous | 0
+ :public | :enabled | :admin | true | 1
+ :public | :enabled | :admin | false | 1
+ :public | :enabled | :reporter | nil | 1
+ :public | :enabled | :guest | nil | 1
+ :public | :enabled | :non_member | nil | 1
+ :public | :enabled | :anonymous | nil | 1
+
+ :public | :private | :admin | true | 1
+ :public | :private | :admin | false | 0
+ :public | :private | :reporter | nil | 1
+ :public | :private | :guest | nil | 0
+ :public | :private | :non_member | nil | 0
+ :public | :private | :anonymous | nil | 0
+
+ :public | :disabled | :reporter | nil | 0
+ :public | :disabled | :guest | nil | 0
+ :public | :disabled | :non_member | nil | 0
+ :public | :disabled | :anonymous | nil | 0
+
+ :internal | :enabled | :admin | true | 1
+ :internal | :enabled | :admin | false | 1
+ :internal | :enabled | :reporter | nil | 1
+ :internal | :enabled | :guest | nil | 1
+ :internal | :enabled | :non_member | nil | 1
+ :internal | :enabled | :anonymous | nil | 0
+
+ :internal | :private | :admin | true | 1
+ :internal | :private | :admin | false | 0
+ :internal | :private | :reporter | nil | 1
+ :internal | :private | :guest | nil | 0
+ :internal | :private | :non_member | nil | 0
+ :internal | :private | :anonymous | nil | 0
+
+ :internal | :disabled | :reporter | nil | 0
+ :internal | :disabled | :guest | nil | 0
+ :internal | :disabled | :non_member | nil | 0
+ :internal | :disabled | :anonymous | nil | 0
+
+ :private | :private | :admin | true | 1
+ :private | :private | :admin | false | 0
+ :private | :private | :reporter | nil | 1
+ :private | :private | :guest | nil | 0
+ :private | :private | :non_member | nil | 0
+ :private | :private | :anonymous | nil | 0
+
+ :private | :disabled | :reporter | nil | 0
+ :private | :disabled | :guest | nil | 0
+ :private | :disabled | :non_member | nil | 0
+ :private | :disabled | :anonymous | nil | 0
end
- # project_level, :feature_access_level, :membership, :expected_count
+ # project_level, :feature_access_level, :membership, :admin_mode, :expected_count
def permission_table_for_guest_feature_access
- :public | :enabled | :admin | 1
- :public | :enabled | :reporter | 1
- :public | :enabled | :guest | 1
- :public | :enabled | :non_member | 1
- :public | :enabled | :anonymous | 1
-
- :public | :private | :admin | 1
- :public | :private | :reporter | 1
- :public | :private | :guest | 1
- :public | :private | :non_member | 0
- :public | :private | :anonymous | 0
-
- :public | :disabled | :reporter | 0
- :public | :disabled | :guest | 0
- :public | :disabled | :non_member | 0
- :public | :disabled | :anonymous | 0
-
- :internal | :enabled | :admin | 1
- :internal | :enabled | :reporter | 1
- :internal | :enabled | :guest | 1
- :internal | :enabled | :non_member | 1
- :internal | :enabled | :anonymous | 0
-
- :internal | :private | :admin | 1
- :internal | :private | :reporter | 1
- :internal | :private | :guest | 1
- :internal | :private | :non_member | 0
- :internal | :private | :anonymous | 0
-
- :internal | :disabled | :reporter | 0
- :internal | :disabled | :guest | 0
- :internal | :disabled | :non_member | 0
- :internal | :disabled | :anonymous | 0
-
- :private | :private | :admin | 1
- :private | :private | :reporter | 1
- :private | :private | :guest | 1
- :private | :private | :non_member | 0
- :private | :private | :anonymous | 0
-
- :private | :disabled | :reporter | 0
- :private | :disabled | :guest | 0
- :private | :disabled | :non_member | 0
- :private | :disabled | :anonymous | 0
+ :public | :enabled | :admin | true | 1
+ :public | :enabled | :admin | false | 1
+ :public | :enabled | :reporter | nil | 1
+ :public | :enabled | :guest | nil | 1
+ :public | :enabled | :non_member | nil | 1
+ :public | :enabled | :anonymous | nil | 1
+
+ :public | :private | :admin | true | 1
+ :public | :private | :admin | false | 0
+ :public | :private | :reporter | nil | 1
+ :public | :private | :guest | nil | 1
+ :public | :private | :non_member | nil | 0
+ :public | :private | :anonymous | nil | 0
+
+ :public | :disabled | :reporter | nil | 0
+ :public | :disabled | :guest | nil | 0
+ :public | :disabled | :non_member | nil | 0
+ :public | :disabled | :anonymous | nil | 0
+
+ :internal | :enabled | :admin | true | 1
+ :internal | :enabled | :admin | false | 1
+ :internal | :enabled | :reporter | nil | 1
+ :internal | :enabled | :guest | nil | 1
+ :internal | :enabled | :non_member | nil | 1
+ :internal | :enabled | :anonymous | nil | 0
+
+ :internal | :private | :admin | true | 1
+ :internal | :private | :admin | false | 0
+ :internal | :private | :reporter | nil | 1
+ :internal | :private | :guest | nil | 1
+ :internal | :private | :non_member | nil | 0
+ :internal | :private | :anonymous | nil | 0
+
+ :internal | :disabled | :reporter | nil | 0
+ :internal | :disabled | :guest | nil | 0
+ :internal | :disabled | :non_member | nil | 0
+ :internal | :disabled | :anonymous | nil | 0
+
+ :private | :private | :admin | true | 1
+ :private | :private | :admin | false | 0
+ :private | :private | :reporter | nil | 1
+ :private | :private | :guest | nil | 1
+ :private | :private | :non_member | nil | 0
+ :private | :private | :anonymous | nil | 0
+
+ :private | :disabled | :reporter | nil | 0
+ :private | :disabled | :guest | nil | 0
+ :private | :disabled | :non_member | nil | 0
+ :private | :disabled | :anonymous | nil | 0
end
# This table is based on permission_table_for_guest_feature_access,
@@ -121,184 +134,208 @@ RSpec.shared_context 'ProjectPolicyTable context' do
# e.g. `repository` feature has minimum requirement of GUEST,
# but a GUEST are prohibited from reading code if project is private.
#
- # project_level, :feature_access_level, :membership, :expected_count
+ # project_level, :feature_access_level, :membership, :admin_mode, :expected_count
def permission_table_for_guest_feature_access_and_non_private_project_only
- :public | :enabled | :admin | 1
- :public | :enabled | :reporter | 1
- :public | :enabled | :guest | 1
- :public | :enabled | :non_member | 1
- :public | :enabled | :anonymous | 1
-
- :public | :private | :admin | 1
- :public | :private | :reporter | 1
- :public | :private | :guest | 1
- :public | :private | :non_member | 0
- :public | :private | :anonymous | 0
-
- :public | :disabled | :reporter | 0
- :public | :disabled | :guest | 0
- :public | :disabled | :non_member | 0
- :public | :disabled | :anonymous | 0
-
- :internal | :enabled | :admin | 1
- :internal | :enabled | :reporter | 1
- :internal | :enabled | :guest | 1
- :internal | :enabled | :non_member | 1
- :internal | :enabled | :anonymous | 0
-
- :internal | :private | :admin | 1
- :internal | :private | :reporter | 1
- :internal | :private | :guest | 1
- :internal | :private | :non_member | 0
- :internal | :private | :anonymous | 0
-
- :internal | :disabled | :reporter | 0
- :internal | :disabled | :guest | 0
- :internal | :disabled | :non_member | 0
- :internal | :disabled | :anonymous | 0
-
- :private | :private | :admin | 1
- :private | :private | :reporter | 1
- :private | :private | :guest | 0
- :private | :private | :non_member | 0
- :private | :private | :anonymous | 0
-
- :private | :disabled | :reporter | 0
- :private | :disabled | :guest | 0
- :private | :disabled | :non_member | 0
- :private | :disabled | :anonymous | 0
+ :public | :enabled | :admin | true | 1
+ :public | :enabled | :admin | false | 1
+ :public | :enabled | :reporter | nil | 1
+ :public | :enabled | :guest | nil | 1
+ :public | :enabled | :non_member | nil | 1
+ :public | :enabled | :anonymous | nil | 1
+
+ :public | :private | :admin | true | 1
+ :public | :private | :admin | false | 0
+ :public | :private | :reporter | nil | 1
+ :public | :private | :guest | nil | 1
+ :public | :private | :non_member | nil | 0
+ :public | :private | :anonymous | nil | 0
+
+ :public | :disabled | :reporter | nil | 0
+ :public | :disabled | :guest | nil | 0
+ :public | :disabled | :non_member | nil | 0
+ :public | :disabled | :anonymous | nil | 0
+
+ :internal | :enabled | :admin | true | 1
+ :internal | :enabled | :admin | false | 1
+ :internal | :enabled | :reporter | nil | 1
+ :internal | :enabled | :guest | nil | 1
+ :internal | :enabled | :non_member | nil | 1
+ :internal | :enabled | :anonymous | nil | 0
+
+ :internal | :private | :admin | true | 1
+ :internal | :private | :admin | false | 0
+ :internal | :private | :reporter | nil | 1
+ :internal | :private | :guest | nil | 1
+ :internal | :private | :non_member | nil | 0
+ :internal | :private | :anonymous | nil | 0
+
+ :internal | :disabled | :reporter | nil | 0
+ :internal | :disabled | :guest | nil | 0
+ :internal | :disabled | :non_member | nil | 0
+ :internal | :disabled | :anonymous | nil | 0
+
+ :private | :private | :admin | true | 1
+ :private | :private | :admin | false | 0
+ :private | :private | :reporter | nil | 1
+ :private | :private | :guest | nil | 0
+ :private | :private | :non_member | nil | 0
+ :private | :private | :anonymous | nil | 0
+
+ :private | :disabled | :reporter | nil | 0
+ :private | :disabled | :guest | nil | 0
+ :private | :disabled | :non_member | nil | 0
+ :private | :disabled | :anonymous | nil | 0
end
- # :project_level, :issues_access_level, :merge_requests_access_level, :membership, :expected_count
+ # :project_level, :issues_access_level, :merge_requests_access_level, :membership, :admin_mode, :expected_count
def permission_table_for_milestone_access
- :public | :enabled | :enabled | :admin | 1
- :public | :enabled | :enabled | :reporter | 1
- :public | :enabled | :enabled | :guest | 1
- :public | :enabled | :enabled | :non_member | 1
- :public | :enabled | :enabled | :anonymous | 1
-
- :public | :enabled | :private | :admin | 1
- :public | :enabled | :private | :reporter | 1
- :public | :enabled | :private | :guest | 1
- :public | :enabled | :private | :non_member | 1
- :public | :enabled | :private | :anonymous | 1
-
- :public | :enabled | :disabled | :admin | 1
- :public | :enabled | :disabled | :reporter | 1
- :public | :enabled | :disabled | :guest | 1
- :public | :enabled | :disabled | :non_member | 1
- :public | :enabled | :disabled | :anonymous | 1
-
- :public | :private | :enabled | :admin | 1
- :public | :private | :enabled | :reporter | 1
- :public | :private | :enabled | :guest | 1
- :public | :private | :enabled | :non_member | 1
- :public | :private | :enabled | :anonymous | 1
-
- :public | :private | :private | :admin | 1
- :public | :private | :private | :reporter | 1
- :public | :private | :private | :guest | 1
- :public | :private | :private | :non_member | 0
- :public | :private | :private | :anonymous | 0
-
- :public | :private | :disabled | :admin | 1
- :public | :private | :disabled | :reporter | 1
- :public | :private | :disabled | :guest | 1
- :public | :private | :disabled | :non_member | 0
- :public | :private | :disabled | :anonymous | 0
-
- :public | :disabled | :enabled | :admin | 1
- :public | :disabled | :enabled | :reporter | 1
- :public | :disabled | :enabled | :guest | 1
- :public | :disabled | :enabled | :non_member | 1
- :public | :disabled | :enabled | :anonymous | 1
-
- :public | :disabled | :private | :admin | 1
- :public | :disabled | :private | :reporter | 1
- :public | :disabled | :private | :guest | 0
- :public | :disabled | :private | :non_member | 0
- :public | :disabled | :private | :anonymous | 0
-
- :public | :disabled | :disabled | :reporter | 0
- :public | :disabled | :disabled | :guest | 0
- :public | :disabled | :disabled | :non_member | 0
- :public | :disabled | :disabled | :anonymous | 0
-
- :internal | :enabled | :enabled | :admin | 1
- :internal | :enabled | :enabled | :reporter | 1
- :internal | :enabled | :enabled | :guest | 1
- :internal | :enabled | :enabled | :non_member | 1
- :internal | :enabled | :enabled | :anonymous | 0
-
- :internal | :enabled | :private | :admin | 1
- :internal | :enabled | :private | :reporter | 1
- :internal | :enabled | :private | :guest | 1
- :internal | :enabled | :private | :non_member | 1
- :internal | :enabled | :private | :anonymous | 0
-
- :internal | :enabled | :disabled | :admin | 1
- :internal | :enabled | :disabled | :reporter | 1
- :internal | :enabled | :disabled | :guest | 1
- :internal | :enabled | :disabled | :non_member | 1
- :internal | :enabled | :disabled | :anonymous | 0
-
- :internal | :private | :enabled | :admin | 1
- :internal | :private | :enabled | :reporter | 1
- :internal | :private | :enabled | :guest | 1
- :internal | :private | :enabled | :non_member | 1
- :internal | :private | :enabled | :anonymous | 0
-
- :internal | :private | :private | :admin | 1
- :internal | :private | :private | :reporter | 1
- :internal | :private | :private | :guest | 1
- :internal | :private | :private | :non_member | 0
- :internal | :private | :private | :anonymous | 0
-
- :internal | :private | :disabled | :admin | 1
- :internal | :private | :disabled | :reporter | 1
- :internal | :private | :disabled | :guest | 1
- :internal | :private | :disabled | :non_member | 0
- :internal | :private | :disabled | :anonymous | 0
-
- :internal | :disabled | :enabled | :admin | 1
- :internal | :disabled | :enabled | :reporter | 1
- :internal | :disabled | :enabled | :guest | 1
- :internal | :disabled | :enabled | :non_member | 1
- :internal | :disabled | :enabled | :anonymous | 0
-
- :internal | :disabled | :private | :admin | 1
- :internal | :disabled | :private | :reporter | 1
- :internal | :disabled | :private | :guest | 0
- :internal | :disabled | :private | :non_member | 0
- :internal | :disabled | :private | :anonymous | 0
-
- :internal | :disabled | :disabled | :reporter | 0
- :internal | :disabled | :disabled | :guest | 0
- :internal | :disabled | :disabled | :non_member | 0
- :internal | :disabled | :disabled | :anonymous | 0
-
- :private | :private | :private | :admin | 1
- :private | :private | :private | :reporter | 1
- :private | :private | :private | :guest | 1
- :private | :private | :private | :non_member | 0
- :private | :private | :private | :anonymous | 0
-
- :private | :private | :disabled | :admin | 1
- :private | :private | :disabled | :reporter | 1
- :private | :private | :disabled | :guest | 1
- :private | :private | :disabled | :non_member | 0
- :private | :private | :disabled | :anonymous | 0
-
- :private | :disabled | :private | :admin | 1
- :private | :disabled | :private | :reporter | 1
- :private | :disabled | :private | :guest | 0
- :private | :disabled | :private | :non_member | 0
- :private | :disabled | :private | :anonymous | 0
-
- :private | :disabled | :disabled | :reporter | 0
- :private | :disabled | :disabled | :guest | 0
- :private | :disabled | :disabled | :non_member | 0
- :private | :disabled | :disabled | :anonymous | 0
+ :public | :enabled | :enabled | :admin | true | 1
+ :public | :enabled | :enabled | :admin | false | 1
+ :public | :enabled | :enabled | :reporter | nil | 1
+ :public | :enabled | :enabled | :guest | nil | 1
+ :public | :enabled | :enabled | :non_member | nil | 1
+ :public | :enabled | :enabled | :anonymous | nil | 1
+
+ :public | :enabled | :private | :admin | true | 1
+ :public | :enabled | :private | :admin | false | 1
+ :public | :enabled | :private | :reporter | nil | 1
+ :public | :enabled | :private | :guest | nil | 1
+ :public | :enabled | :private | :non_member | nil | 1
+ :public | :enabled | :private | :anonymous | nil | 1
+
+ :public | :enabled | :disabled | :admin | true | 1
+ :public | :enabled | :disabled | :admin | false | 1
+ :public | :enabled | :disabled | :reporter | nil | 1
+ :public | :enabled | :disabled | :guest | nil | 1
+ :public | :enabled | :disabled | :non_member | nil | 1
+ :public | :enabled | :disabled | :anonymous | nil | 1
+
+ :public | :private | :enabled | :admin | true | 1
+ :public | :private | :enabled | :admin | false | 1
+ :public | :private | :enabled | :reporter | nil | 1
+ :public | :private | :enabled | :guest | nil | 1
+ :public | :private | :enabled | :non_member | nil | 1
+ :public | :private | :enabled | :anonymous | nil | 1
+
+ :public | :private | :private | :admin | true | 1
+ :public | :private | :private | :admin | false | 0
+ :public | :private | :private | :reporter | nil | 1
+ :public | :private | :private | :guest | nil | 1
+ :public | :private | :private | :non_member | nil | 0
+ :public | :private | :private | :anonymous | nil | 0
+
+ :public | :private | :disabled | :admin | true | 1
+ :public | :private | :disabled | :admin | false | 0
+ :public | :private | :disabled | :reporter | nil | 1
+ :public | :private | :disabled | :guest | nil | 1
+ :public | :private | :disabled | :non_member | nil | 0
+ :public | :private | :disabled | :anonymous | nil | 0
+
+ :public | :disabled | :enabled | :admin | true | 1
+ :public | :disabled | :enabled | :admin | false | 1
+ :public | :disabled | :enabled | :reporter | nil | 1
+ :public | :disabled | :enabled | :guest | nil | 1
+ :public | :disabled | :enabled | :non_member | nil | 1
+ :public | :disabled | :enabled | :anonymous | nil | 1
+
+ :public | :disabled | :private | :admin | true | 1
+ :public | :disabled | :private | :admin | false | 0
+ :public | :disabled | :private | :reporter | nil | 1
+ :public | :disabled | :private | :guest | nil | 0
+ :public | :disabled | :private | :non_member | nil | 0
+ :public | :disabled | :private | :anonymous | nil | 0
+
+ :public | :disabled | :disabled | :reporter | nil | 0
+ :public | :disabled | :disabled | :guest | nil | 0
+ :public | :disabled | :disabled | :non_member | nil | 0
+ :public | :disabled | :disabled | :anonymous | nil | 0
+
+ :internal | :enabled | :enabled | :admin | true | 1
+ :internal | :enabled | :enabled | :admin | false | 1
+ :internal | :enabled | :enabled | :reporter | nil | 1
+ :internal | :enabled | :enabled | :guest | nil | 1
+ :internal | :enabled | :enabled | :non_member | nil | 1
+ :internal | :enabled | :enabled | :anonymous | nil | 0
+
+ :internal | :enabled | :private | :admin | true | 1
+ :internal | :enabled | :private | :admin | false | 1
+ :internal | :enabled | :private | :reporter | nil | 1
+ :internal | :enabled | :private | :guest | nil | 1
+ :internal | :enabled | :private | :non_member | nil | 1
+ :internal | :enabled | :private | :anonymous | nil | 0
+
+ :internal | :enabled | :disabled | :admin | true | 1
+ :internal | :enabled | :disabled | :admin | false | 1
+ :internal | :enabled | :disabled | :reporter | nil | 1
+ :internal | :enabled | :disabled | :guest | nil | 1
+ :internal | :enabled | :disabled | :non_member | nil | 1
+ :internal | :enabled | :disabled | :anonymous | nil | 0
+
+ :internal | :private | :enabled | :admin | true | 1
+ :internal | :private | :enabled | :admin | false | 1
+ :internal | :private | :enabled | :reporter | nil | 1
+ :internal | :private | :enabled | :guest | nil | 1
+ :internal | :private | :enabled | :non_member | nil | 1
+ :internal | :private | :enabled | :anonymous | nil | 0
+
+ :internal | :private | :private | :admin | true | 1
+ :internal | :private | :private | :admin | false | 0
+ :internal | :private | :private | :reporter | nil | 1
+ :internal | :private | :private | :guest | nil | 1
+ :internal | :private | :private | :non_member | nil | 0
+ :internal | :private | :private | :anonymous | nil | 0
+
+ :internal | :private | :disabled | :admin | true | 1
+ :internal | :private | :disabled | :admin | false | 0
+ :internal | :private | :disabled | :reporter | nil | 1
+ :internal | :private | :disabled | :guest | nil | 1
+ :internal | :private | :disabled | :non_member | nil | 0
+ :internal | :private | :disabled | :anonymous | nil | 0
+
+ :internal | :disabled | :enabled | :admin | true | 1
+ :internal | :disabled | :enabled | :admin | false | 1
+ :internal | :disabled | :enabled | :reporter | nil | 1
+ :internal | :disabled | :enabled | :guest | nil | 1
+ :internal | :disabled | :enabled | :non_member | nil | 1
+ :internal | :disabled | :enabled | :anonymous | nil | 0
+
+ :internal | :disabled | :private | :admin | true | 1
+ :internal | :disabled | :private | :admin | false | 0
+ :internal | :disabled | :private | :reporter | nil | 1
+ :internal | :disabled | :private | :guest | nil | 0
+ :internal | :disabled | :private | :non_member | nil | 0
+ :internal | :disabled | :private | :anonymous | nil | 0
+
+ :internal | :disabled | :disabled | :reporter | nil | 0
+ :internal | :disabled | :disabled | :guest | nil | 0
+ :internal | :disabled | :disabled | :non_member | nil | 0
+ :internal | :disabled | :disabled | :anonymous | nil | 0
+
+ :private | :private | :private | :admin | true | 1
+ :private | :private | :private | :admin | false | 0
+ :private | :private | :private | :reporter | nil | 1
+ :private | :private | :private | :guest | nil | 1
+ :private | :private | :private | :non_member | nil | 0
+ :private | :private | :private | :anonymous | nil | 0
+
+ :private | :private | :disabled | :admin | true | 1
+ :private | :private | :disabled | :admin | false | 0
+ :private | :private | :disabled | :reporter | nil | 1
+ :private | :private | :disabled | :guest | nil | 1
+ :private | :private | :disabled | :non_member | nil | 0
+ :private | :private | :disabled | :anonymous | nil | 0
+
+ :private | :disabled | :private | :admin | true | 1
+ :private | :disabled | :private | :admin | false | 0
+ :private | :disabled | :private | :reporter | nil | 1
+ :private | :disabled | :private | :guest | nil | 0
+ :private | :disabled | :private | :non_member | nil | 0
+ :private | :disabled | :private | :anonymous | nil | 0
+
+ :private | :disabled | :disabled | :reporter | nil | 0
+ :private | :disabled | :disabled | :guest | nil | 0
+ :private | :disabled | :disabled | :non_member | nil | 0
+ :private | :disabled | :disabled | :anonymous | nil | 0
end
# :project_level, :membership, :expected_count
@@ -321,166 +358,192 @@ RSpec.shared_context 'ProjectPolicyTable context' do
# :snippet_level, :project_level, :feature_access_level, :membership, :expected_count
def permission_table_for_project_snippet_access
- :public | :public | :enabled | :admin | 1
- :public | :public | :enabled | :reporter | 1
- :public | :public | :enabled | :guest | 1
- :public | :public | :enabled | :non_member | 1
- :public | :public | :enabled | :anonymous | 1
-
- :public | :public | :private | :admin | 1
- :public | :public | :private | :reporter | 1
- :public | :public | :private | :guest | 1
- :public | :public | :private | :non_member | 0
- :public | :public | :private | :anonymous | 0
-
- :public | :public | :disabled | :admin | 1
- :public | :public | :disabled | :reporter | 0
- :public | :public | :disabled | :guest | 0
- :public | :public | :disabled | :non_member | 0
- :public | :public | :disabled | :anonymous | 0
-
- :public | :internal | :enabled | :admin | 1
- :public | :internal | :enabled | :reporter | 1
- :public | :internal | :enabled | :guest | 1
- :public | :internal | :enabled | :non_member | 1
- :public | :internal | :enabled | :anonymous | 0
-
- :public | :internal | :private | :admin | 1
- :public | :internal | :private | :reporter | 1
- :public | :internal | :private | :guest | 1
- :public | :internal | :private | :non_member | 0
- :public | :internal | :private | :anonymous | 0
-
- :public | :internal | :disabled | :admin | 1
- :public | :internal | :disabled | :reporter | 0
- :public | :internal | :disabled | :guest | 0
- :public | :internal | :disabled | :non_member | 0
- :public | :internal | :disabled | :anonymous | 0
-
- :public | :private | :private | :admin | 1
- :public | :private | :private | :reporter | 1
- :public | :private | :private | :guest | 1
- :public | :private | :private | :non_member | 0
- :public | :private | :private | :anonymous | 0
-
- :public | :private | :disabled | :reporter | 0
- :public | :private | :disabled | :guest | 0
- :public | :private | :disabled | :non_member | 0
- :public | :private | :disabled | :anonymous | 0
-
- :internal | :public | :enabled | :admin | 1
- :internal | :public | :enabled | :reporter | 1
- :internal | :public | :enabled | :guest | 1
- :internal | :public | :enabled | :non_member | 1
- :internal | :public | :enabled | :anonymous | 0
-
- :internal | :public | :private | :admin | 1
- :internal | :public | :private | :reporter | 1
- :internal | :public | :private | :guest | 1
- :internal | :public | :private | :non_member | 0
- :internal | :public | :private | :anonymous | 0
-
- :internal | :public | :disabled | :admin | 1
- :internal | :public | :disabled | :reporter | 0
- :internal | :public | :disabled | :guest | 0
- :internal | :public | :disabled | :non_member | 0
- :internal | :public | :disabled | :anonymous | 0
-
- :internal | :internal | :enabled | :admin | 1
- :internal | :internal | :enabled | :reporter | 1
- :internal | :internal | :enabled | :guest | 1
- :internal | :internal | :enabled | :non_member | 1
- :internal | :internal | :enabled | :anonymous | 0
-
- :internal | :internal | :private | :admin | 1
- :internal | :internal | :private | :reporter | 1
- :internal | :internal | :private | :guest | 1
- :internal | :internal | :private | :non_member | 0
- :internal | :internal | :private | :anonymous | 0
-
- :internal | :internal | :disabled | :admin | 1
- :internal | :internal | :disabled | :reporter | 0
- :internal | :internal | :disabled | :guest | 0
- :internal | :internal | :disabled | :non_member | 0
- :internal | :internal | :disabled | :anonymous | 0
-
- :internal | :private | :private | :admin | 1
- :internal | :private | :private | :reporter | 1
- :internal | :private | :private | :guest | 1
- :internal | :private | :private | :non_member | 0
- :internal | :private | :private | :anonymous | 0
-
- :internal | :private | :disabled | :admin | 1
- :internal | :private | :disabled | :reporter | 0
- :internal | :private | :disabled | :guest | 0
- :internal | :private | :disabled | :non_member | 0
- :internal | :private | :disabled | :anonymous | 0
-
- :private | :public | :enabled | :admin | 1
- :private | :public | :enabled | :reporter | 1
- :private | :public | :enabled | :guest | 1
- :private | :public | :enabled | :non_member | 0
- :private | :public | :enabled | :anonymous | 0
-
- :private | :public | :private | :admin | 1
- :private | :public | :private | :reporter | 1
- :private | :public | :private | :guest | 1
- :private | :public | :private | :non_member | 0
- :private | :public | :private | :anonymous | 0
-
- :private | :public | :disabled | :admin | 1
- :private | :public | :disabled | :reporter | 0
- :private | :public | :disabled | :guest | 0
- :private | :public | :disabled | :non_member | 0
- :private | :public | :disabled | :anonymous | 0
-
- :private | :internal | :enabled | :admin | 1
- :private | :internal | :enabled | :reporter | 1
- :private | :internal | :enabled | :guest | 1
- :private | :internal | :enabled | :non_member | 0
- :private | :internal | :enabled | :anonymous | 0
-
- :private | :internal | :private | :admin | 1
- :private | :internal | :private | :reporter | 1
- :private | :internal | :private | :guest | 1
- :private | :internal | :private | :non_member | 0
- :private | :internal | :private | :anonymous | 0
-
- :private | :internal | :disabled | :admin | 1
- :private | :internal | :disabled | :reporter | 0
- :private | :internal | :disabled | :guest | 0
- :private | :internal | :disabled | :non_member | 0
- :private | :internal | :disabled | :anonymous | 0
-
- :private | :private | :private | :admin | 1
- :private | :private | :private | :reporter | 1
- :private | :private | :private | :guest | 1
- :private | :private | :private | :non_member | 0
- :private | :private | :private | :anonymous | 0
-
- :private | :private | :disabled | :admin | 1
- :private | :private | :disabled | :reporter | 0
- :private | :private | :disabled | :guest | 0
- :private | :private | :disabled | :non_member | 0
- :private | :private | :disabled | :anonymous | 0
+ :public | :public | :enabled | :admin | true | 1
+ :public | :public | :enabled | :admin | false | 1
+ :public | :public | :enabled | :reporter | nil | 1
+ :public | :public | :enabled | :guest | nil | 1
+ :public | :public | :enabled | :non_member | nil | 1
+ :public | :public | :enabled | :anonymous | nil | 1
+
+ :public | :public | :private | :admin | true | 1
+ :public | :public | :private | :admin | false | 0
+ :public | :public | :private | :reporter | nil | 1
+ :public | :public | :private | :guest | nil | 1
+ :public | :public | :private | :non_member | nil | 0
+ :public | :public | :private | :anonymous | nil | 0
+
+ :public | :public | :disabled | :admin | true | 1
+ :public | :public | :disabled | :admin | false | 0
+ :public | :public | :disabled | :reporter | nil | 0
+ :public | :public | :disabled | :guest | nil | 0
+ :public | :public | :disabled | :non_member | nil | 0
+ :public | :public | :disabled | :anonymous | nil | 0
+
+ :public | :internal | :enabled | :admin | true | 1
+ :public | :internal | :enabled | :admin | false | 1
+ :public | :internal | :enabled | :reporter | nil | 1
+ :public | :internal | :enabled | :guest | nil | 1
+ :public | :internal | :enabled | :non_member | nil | 1
+ :public | :internal | :enabled | :anonymous | nil | 0
+
+ :public | :internal | :private | :admin | true | 1
+ :public | :internal | :private | :admin | false | 0
+ :public | :internal | :private | :reporter | nil | 1
+ :public | :internal | :private | :guest | nil | 1
+ :public | :internal | :private | :non_member | nil | 0
+ :public | :internal | :private | :anonymous | nil | 0
+
+ :public | :internal | :disabled | :admin | true | 1
+ :public | :internal | :disabled | :admin | false | 0
+ :public | :internal | :disabled | :reporter | nil | 0
+ :public | :internal | :disabled | :guest | nil | 0
+ :public | :internal | :disabled | :non_member | nil | 0
+ :public | :internal | :disabled | :anonymous | nil | 0
+
+ :public | :private | :private | :admin | true | 1
+ :public | :private | :private | :admin | false | 0
+ :public | :private | :private | :reporter | nil | 1
+ :public | :private | :private | :guest | nil | 1
+ :public | :private | :private | :non_member | nil | 0
+ :public | :private | :private | :anonymous | nil | 0
+
+ :public | :private | :disabled | :reporter | nil | 0
+ :public | :private | :disabled | :guest | nil | 0
+ :public | :private | :disabled | :non_member | nil | 0
+ :public | :private | :disabled | :anonymous | nil | 0
+
+ :internal | :public | :enabled | :admin | true | 1
+ :internal | :public | :enabled | :admin | false | 1
+ :internal | :public | :enabled | :reporter | nil | 1
+ :internal | :public | :enabled | :guest | nil | 1
+ :internal | :public | :enabled | :non_member | nil | 1
+ :internal | :public | :enabled | :anonymous | nil | 0
+
+ :internal | :public | :private | :admin | true | 1
+ :internal | :public | :private | :admin | false | 0
+ :internal | :public | :private | :reporter | nil | 1
+ :internal | :public | :private | :guest | nil | 1
+ :internal | :public | :private | :non_member | nil | 0
+ :internal | :public | :private | :anonymous | nil | 0
+
+ :internal | :public | :disabled | :admin | true | 1
+ :internal | :public | :disabled | :admin | false | 0
+ :internal | :public | :disabled | :reporter | nil | 0
+ :internal | :public | :disabled | :guest | nil | 0
+ :internal | :public | :disabled | :non_member | nil | 0
+ :internal | :public | :disabled | :anonymous | nil | 0
+
+ :internal | :internal | :enabled | :admin | true | 1
+ :internal | :internal | :enabled | :admin | false | 1
+ :internal | :internal | :enabled | :reporter | nil | 1
+ :internal | :internal | :enabled | :guest | nil | 1
+ :internal | :internal | :enabled | :non_member | nil | 1
+ :internal | :internal | :enabled | :anonymous | nil | 0
+
+ :internal | :internal | :private | :admin | true | 1
+ :internal | :internal | :private | :admin | false | 0
+ :internal | :internal | :private | :reporter | nil | 1
+ :internal | :internal | :private | :guest | nil | 1
+ :internal | :internal | :private | :non_member | nil | 0
+ :internal | :internal | :private | :anonymous | nil | 0
+
+ :internal | :internal | :disabled | :admin | true | 1
+ :internal | :internal | :disabled | :admin | false | 0
+ :internal | :internal | :disabled | :reporter | nil | 0
+ :internal | :internal | :disabled | :guest | nil | 0
+ :internal | :internal | :disabled | :non_member | nil | 0
+ :internal | :internal | :disabled | :anonymous | nil | 0
+
+ :internal | :private | :private | :admin | true | 1
+ :internal | :private | :private | :admin | false | 0
+ :internal | :private | :private | :reporter | nil | 1
+ :internal | :private | :private | :guest | nil | 1
+ :internal | :private | :private | :non_member | nil | 0
+ :internal | :private | :private | :anonymous | nil | 0
+
+ :internal | :private | :disabled | :admin | true | 1
+ :internal | :private | :disabled | :admin | false | 0
+ :internal | :private | :disabled | :reporter | nil | 0
+ :internal | :private | :disabled | :guest | nil | 0
+ :internal | :private | :disabled | :non_member | nil | 0
+ :internal | :private | :disabled | :anonymous | nil | 0
+
+ :private | :public | :enabled | :admin | true | 1
+ :private | :public | :enabled | :admin | false | 0
+ :private | :public | :enabled | :reporter | nil | 1
+ :private | :public | :enabled | :guest | nil | 1
+ :private | :public | :enabled | :non_member | nil | 0
+ :private | :public | :enabled | :anonymous | nil | 0
+
+ :private | :public | :private | :admin | true | 1
+ :private | :public | :private | :admin | false | 0
+ :private | :public | :private | :reporter | nil | 1
+ :private | :public | :private | :guest | nil | 1
+ :private | :public | :private | :non_member | nil | 0
+ :private | :public | :private | :anonymous | nil | 0
+
+ :private | :public | :disabled | :admin | true | 1
+ :private | :public | :disabled | :admin | false | 0
+ :private | :public | :disabled | :reporter | nil | 0
+ :private | :public | :disabled | :guest | nil | 0
+ :private | :public | :disabled | :non_member | nil | 0
+ :private | :public | :disabled | :anonymous | nil | 0
+
+ :private | :internal | :enabled | :admin | true | 1
+ :private | :internal | :enabled | :admin | false | 0
+ :private | :internal | :enabled | :reporter | nil | 1
+ :private | :internal | :enabled | :guest | nil | 1
+ :private | :internal | :enabled | :non_member | nil | 0
+ :private | :internal | :enabled | :anonymous | nil | 0
+
+ :private | :internal | :private | :admin | true | 1
+ :private | :internal | :private | :admin | false | 0
+ :private | :internal | :private | :reporter | nil | 1
+ :private | :internal | :private | :guest | nil | 1
+ :private | :internal | :private | :non_member | nil | 0
+ :private | :internal | :private | :anonymous | nil | 0
+
+ :private | :internal | :disabled | :admin | true | 1
+ :private | :internal | :disabled | :admin | false | 0
+ :private | :internal | :disabled | :reporter | nil | 0
+ :private | :internal | :disabled | :guest | nil | 0
+ :private | :internal | :disabled | :non_member | nil | 0
+ :private | :internal | :disabled | :anonymous | nil | 0
+
+ :private | :private | :private | :admin | true | 1
+ :private | :private | :private | :admin | false | 0
+ :private | :private | :private | :reporter | nil | 1
+ :private | :private | :private | :guest | nil | 1
+ :private | :private | :private | :non_member | nil | 0
+ :private | :private | :private | :anonymous | nil | 0
+
+ :private | :private | :disabled | :admin | true | 1
+ :private | :private | :disabled | :admin | false | 0
+ :private | :private | :disabled | :reporter | nil | 0
+ :private | :private | :disabled | :guest | nil | 0
+ :private | :private | :disabled | :non_member | nil | 0
+ :private | :private | :disabled | :anonymous | nil | 0
end
# :snippet_level, :membership, :expected_count
def permission_table_for_personal_snippet_access
- :public | :admin | 1
- :public | :author | 1
- :public | :non_member | 1
- :public | :anonymous | 1
-
- :internal | :admin | 1
- :internal | :author | 1
- :internal | :non_member | 1
- :internal | :anonymous | 0
-
- :private | :admin | 1
- :private | :author | 1
- :private | :non_member | 0
- :private | :anonymous | 0
+ :public | :admin | true | 1
+ :public | :admin | false | 1
+ :public | :author | nil | 1
+ :public | :non_member | nil | 1
+ :public | :anonymous | nil | 1
+
+ :internal | :admin | true | 1
+ :internal | :admin | false | 1
+ :internal | :author | nil | 1
+ :internal | :non_member | nil | 1
+ :internal | :anonymous | nil | 0
+
+ :private | :admin | true | 1
+ :private | :admin | false | 0
+ :private | :author | nil | 1
+ :private | :non_member | nil | 0
+ :private | :anonymous | nil | 0
end
# rubocop:enable Metrics/AbcSize
end
diff --git a/spec/support/shared_contexts/requests/api/graphql/jira_import/jira_projects_context.rb b/spec/support/shared_contexts/requests/api/graphql/jira_import/jira_projects_context.rb
index edc5b313220..de40b926a1c 100644
--- a/spec/support/shared_contexts/requests/api/graphql/jira_import/jira_projects_context.rb
+++ b/spec/support/shared_contexts/requests/api/graphql/jira_import/jira_projects_context.rb
@@ -116,6 +116,7 @@ RSpec.shared_context 'Jira projects request context' do
"uuid": "14935009-f8aa-481e-94bc-f7251f320b0e"
}]'
end
+
let_it_be(:empty_jira_projects_json) do
'{
"self": "https://your-domain.atlassian.net/rest/api/2/project/search?startAt=0&maxResults=2",
diff --git a/spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb b/spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb
new file mode 100644
index 00000000000..7c23ec33cf8
--- /dev/null
+++ b/spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'npm api setup' do
+ include PackagesManagerApiSpecHelpers
+ include HttpBasicAuthHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project, reload: true) { create(:project, :public, namespace: group) }
+ let_it_be(:package, reload: true) { create(:npm_package, project: project) }
+ let_it_be(:token) { create(:oauth_access_token, scopes: 'api', resource_owner: user) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+ let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running) }
+ let_it_be(: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(:package_name) { package.name }
+
+ before do
+ project.add_developer(user)
+ end
+end
diff --git a/spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb b/spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb
index 84910d0dfe4..38a5ed244c4 100644
--- a/spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb
+++ b/spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb
@@ -48,7 +48,7 @@ RSpec.shared_examples 'multiple issue boards' do
expect(page).to have_button('This is a new board')
end
- it 'deletes board' do
+ it 'deletes board', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/280554' do
in_boards_switcher_dropdown do
click_button 'Delete board'
end
diff --git a/spec/support/shared_examples/cached_response_shared_examples.rb b/spec/support/shared_examples/cached_response_shared_examples.rb
deleted file mode 100644
index 34e5f741b4e..00000000000
--- a/spec/support/shared_examples/cached_response_shared_examples.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-#
-# Negates lib/gitlab/no_cache_headers.rb
-#
-
-RSpec.shared_examples 'cached response' do
- it 'defines a cached header response' do
- expect(response.headers["Cache-Control"]).not_to include("no-store", "no-cache")
- expect(response.headers["Pragma"]).not_to eq("no-cache")
- expect(response.headers["Expires"]).not_to eq("Fri, 01 Jan 1990 00:00:00 GMT")
- end
-end
diff --git a/spec/support/shared_examples/controllers/access_tokens_controller_shared_examples.rb b/spec/support/shared_examples/controllers/access_tokens_controller_shared_examples.rb
index 54d41f9a68c..dd71107455f 100644
--- a/spec/support/shared_examples/controllers/access_tokens_controller_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/access_tokens_controller_shared_examples.rb
@@ -73,7 +73,23 @@ RSpec.shared_examples 'project access tokens available #create' do
end
end
- it { expect(subject).to render_template(:index) }
+ it 'does not create the token' do
+ expect { subject }.not_to change { PersonalAccessToken.count }
+ end
+
+ it 'does not add the project bot as a member' do
+ expect { subject }.not_to change { Member.count }
+ end
+
+ it 'does not create the project bot user' do
+ expect { subject }.not_to change { User.count }
+ end
+
+ it 'shows a failure alert' do
+ subject
+
+ expect(response.flash[:alert]).to match("Failed to create new project access token: Failed!")
+ end
end
end
diff --git a/spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb b/spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb
index 2fcc88ef36a..5a4322f73b6 100644
--- a/spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb
@@ -145,6 +145,8 @@ RSpec.shared_examples 'a GitHub-ish import controller: GET status' do
group.add_owner(user)
client = stub_client(repos: repos, orgs: [org], org_repos: [org_repo])
allow(client).to receive(:each_page).and_return([OpenStruct.new(objects: repos)].to_enum)
+ # GitHub controller has filtering done using GitHub Search API
+ stub_feature_flags(remove_legacy_github_client: false)
end
it 'filters list of repositories by name' do
@@ -157,6 +159,16 @@ RSpec.shared_examples 'a GitHub-ish import controller: GET status' do
expect(json_response.dig("namespaces", 0, "id")).to eq(group.id)
end
+ it 'filters the list, ignoring the case of the name' do
+ get :status, params: { filter: 'EMACS' }, format: :json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.dig("imported_projects").count).to eq(0)
+ expect(json_response.dig("provider_repos").count).to eq(1)
+ expect(json_response.dig("provider_repos", 0, "id")).to eq(repo_2.id)
+ expect(json_response.dig("namespaces", 0, "id")).to eq(group.id)
+ end
+
context 'when user input contains html' do
let(:expected_filter) { 'test' }
let(:filter) { "<html>#{expected_filter}</html>" }
@@ -167,6 +179,23 @@ RSpec.shared_examples 'a GitHub-ish import controller: GET status' do
expect(assigns(:filter)).to eq(expected_filter)
end
end
+
+ context 'when the client returns a non-string name' do
+ before do
+ repos = [build(:project, name: 2, path: 'test')]
+
+ client = stub_client(repos: repos)
+ allow(client).to receive(:each_page).and_return([OpenStruct.new(objects: repos)].to_enum)
+ end
+
+ it 'does not raise an error' do
+ get :status, params: { filter: '2' }, format: :json
+
+ expect(response).to have_gitlab_http_status :ok
+
+ expect(json_response.dig("provider_repos").count).to eq(1)
+ end
+ end
end
end
diff --git a/spec/support/shared_examples/controllers/trackable_shared_examples.rb b/spec/support/shared_examples/controllers/trackable_shared_examples.rb
index e82c27c43f5..dac7d8c94ff 100644
--- a/spec/support/shared_examples/controllers/trackable_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/trackable_shared_examples.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.shared_examples 'a Trackable Controller' do
- describe '#track_event' do
+ describe '#track_event', :snowplow do
before do
sign_in user
end
@@ -14,9 +14,10 @@ RSpec.shared_examples 'a Trackable Controller' do
end
end
- it 'tracks the action name' do
- expect(Gitlab::Tracking).to receive(:event).with('AnonymousController', 'index', {})
+ it 'tracks the action name', :snowplow do
get :index
+
+ expect_snowplow_event(category: 'AnonymousController', action: 'index')
end
end
@@ -29,8 +30,9 @@ RSpec.shared_examples 'a Trackable Controller' do
end
it 'tracks with the specified param' do
- expect(Gitlab::Tracking).to receive(:event).with('SomeCategory', 'some_event', label: 'errorlabel')
get :index
+
+ expect_snowplow_event(category: 'SomeCategory', action: 'some_event', label: 'errorlabel')
end
end
end
diff --git a/spec/support/shared_examples/features/discussion_comments_shared_example.rb b/spec/support/shared_examples/features/discussion_comments_shared_example.rb
index 9fc5d8933e5..560cfbfb117 100644
--- a/spec/support/shared_examples/features/discussion_comments_shared_example.rb
+++ b/spec/support/shared_examples/features/discussion_comments_shared_example.rb
@@ -56,12 +56,12 @@ RSpec.shared_examples 'thread comments' do |resource_name|
expect(items.first).to have_content 'Comment'
expect(items.first).to have_content "Add a general comment to this #{resource_name}."
- expect(items.first).to have_selector '.fa-check'
+ expect(items.first).to have_selector '[data-testid="check-icon"]'
expect(items.first['class']).to match 'droplab-item-selected'
expect(items.last).to have_content 'Start thread'
expect(items.last).to have_content "Discuss a specific suggestion or question#{' that needs to be resolved' if resource_name == 'merge request'}."
- expect(items.last).not_to have_selector '.fa-check'
+ expect(items.last).not_to have_selector '[data-testid="check-icon"]'
expect(items.last['class']).not_to match 'droplab-item-selected'
end
@@ -228,11 +228,11 @@ RSpec.shared_examples 'thread comments' do |resource_name|
items = all("#{menu_selector} li")
expect(items.first).to have_content 'Comment'
- expect(items.first).not_to have_selector '.fa-check'
+ expect(items.first).not_to have_selector '[data-testid="check-icon"]'
expect(items.first['class']).not_to match 'droplab-item-selected'
expect(items.last).to have_content 'Start thread'
- expect(items.last).to have_selector '.fa-check'
+ expect(items.last).to have_selector '[data-testid="check-icon"]'
expect(items.last['class']).to match 'droplab-item-selected'
end
@@ -274,11 +274,11 @@ RSpec.shared_examples 'thread comments' do |resource_name|
aggregate_failures do
expect(items.first).to have_content 'Comment'
- expect(items.first).to have_selector '.fa-check'
+ expect(items.first).to have_selector '[data-testid="check-icon"]'
expect(items.first['class']).to match 'droplab-item-selected'
expect(items.last).to have_content 'Start thread'
- expect(items.last).not_to have_selector '.fa-check'
+ expect(items.last).not_to have_selector '[data-testid="check-icon"]'
expect(items.last['class']).not_to match 'droplab-item-selected'
end
end
diff --git a/spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb b/spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb
index ffe4fb83283..724d6db2705 100644
--- a/spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb
+++ b/spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
RSpec.shared_examples 'Maintainer manages access requests' do
+ include Spec::Support::Helpers::Features::MembersHelpers
+
let(:user) { create(:user) }
let(:maintainer) { create(:user) }
@@ -26,7 +28,7 @@ RSpec.shared_examples 'Maintainer manages access requests' do
expect_no_visible_access_request(entity, user)
- page.within('[data-qa-selector="members_list"]') do
+ page.within(members_table) do
expect(page).to have_content user.name
end
end
@@ -35,7 +37,7 @@ RSpec.shared_examples 'Maintainer manages access requests' do
expect_visible_access_request(entity, user)
# Open modal
- click_on 'Deny access request'
+ click_on 'Deny access'
expect(page).not_to have_field "Also unassign this user from related issues and merge requests"
diff --git a/spec/support/shared_examples/features/variable_list_shared_examples.rb b/spec/support/shared_examples/features/variable_list_shared_examples.rb
index 218ef070221..e0d169c6868 100644
--- a/spec/support/shared_examples/features/variable_list_shared_examples.rb
+++ b/spec/support/shared_examples/features/variable_list_shared_examples.rb
@@ -1,387 +1,295 @@
# frozen_string_literal: true
RSpec.shared_examples 'variable list' do
- it 'shows list of variables' do
- page.within('.js-ci-variable-list-section') do
- expect(first('.js-ci-variable-input-key').value).to eq(variable.key)
+ it 'shows a list of variables' do
+ page.within('.ci-variable-table') do
+ expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Key"]').text).to eq(variable.key)
end
end
- it 'adds new CI variable' do
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('key')
- find('.js-ci-variable-input-value').set('key_value')
+ it 'adds a new CI variable' do
+ click_button('Add Variable')
+
+ fill_variable('key', 'key_value') do
+ click_button('Add variable')
end
- click_button('Save variables')
wait_for_requests
- visit page_path
-
- # We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
- expect(find('.js-ci-variable-input-key').value).to eq('key')
- expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
+ page.within('.ci-variable-table') do
+ expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Key"]').text).to eq('key')
end
end
it 'adds a new protected variable' do
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('key')
- find('.js-ci-variable-input-value').set('key_value')
+ click_button('Add Variable')
- expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
+ fill_variable('key', 'key_value') do
+ click_button('Add variable')
end
- click_button('Save variables')
wait_for_requests
- visit page_path
-
- # We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
- expect(find('.js-ci-variable-input-key').value).to eq('key')
- expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
- expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
+ page.within('.ci-variable-table') do
+ expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Key"]').text).to eq('key')
+ expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Protected"] svg[data-testid="mobile-issue-close-icon"]')).to be_present
end
end
it 'defaults to unmasked' do
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('key')
- find('.js-ci-variable-input-value').set('key_value')
+ click_button('Add Variable')
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
+ fill_variable('key', 'key_value') do
+ click_button('Add variable')
end
- click_button('Save variables')
wait_for_requests
- visit page_path
-
- # We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
- expect(find('.js-ci-variable-input-key').value).to eq('key')
- expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
- end
- end
-
- context 'defaults to the application setting' do
- context 'application setting is true' do
- before do
- stub_application_setting(protected_ci_variables: true)
-
- visit page_path
- end
-
- it 'defaults to protected' do
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('key')
- end
-
- values = all('.js-ci-variable-input-protected', visible: false).map(&:value)
-
- expect(values).to eq %w(false true true)
- end
-
- it 'shows a message regarding the changed default' do
- expect(page).to have_content 'Environment variables are configured by your administrator to be protected by default'
- end
- end
-
- context 'application setting is false' do
- before do
- stub_application_setting(protected_ci_variables: false)
-
- visit page_path
- end
-
- it 'defaults to unprotected' do
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('key')
- end
-
- values = all('.js-ci-variable-input-protected', visible: false).map(&:value)
-
- expect(values).to eq %w(false false false)
- end
-
- it 'does not show a message regarding the default' do
- expect(page).not_to have_content 'Environment variables are configured by your administrator to be protected by default'
- end
+ page.within('.ci-variable-table') do
+ expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Key"]').text).to eq('key')
+ expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Masked"] svg[data-testid="close-icon"]')).to be_present
end
end
it 'reveals and hides variables' do
- page.within('.js-ci-variable-list-section') do
- expect(first('.js-ci-variable-input-key').value).to eq(variable.key)
- expect(first('.js-ci-variable-input-value', visible: false).value).to eq(variable.value)
+ page.within('.ci-variable-table') do
+ expect(first('.js-ci-variable-row td[data-label="Key"]').text).to eq(variable.key)
expect(page).to have_content('*' * 17)
click_button('Reveal value')
- expect(first('.js-ci-variable-input-key').value).to eq(variable.key)
- expect(first('.js-ci-variable-input-value').value).to eq(variable.value)
+ expect(first('.js-ci-variable-row td[data-label="Key"]').text).to eq(variable.key)
+ expect(first('.js-ci-variable-row td[data-label="Value"]').text).to eq(variable.value)
expect(page).not_to have_content('*' * 17)
click_button('Hide value')
- expect(first('.js-ci-variable-input-key').value).to eq(variable.key)
- expect(first('.js-ci-variable-input-value', visible: false).value).to eq(variable.value)
+ expect(first('.js-ci-variable-row td[data-label="Key"]').text).to eq(variable.key)
expect(page).to have_content('*' * 17)
end
end
- it 'deletes variable' do
- page.within('.js-ci-variable-list-section') do
- expect(page).to have_selector('.js-row', count: 2)
+ it 'deletes a variable' do
+ expect(page).to have_selector('.js-ci-variable-row', count: 1)
- first('.js-row-remove-button').click
-
- click_button('Save variables')
- wait_for_requests
-
- expect(page).to have_selector('.js-row', count: 1)
+ page.within('.ci-variable-table') do
+ click_button('Edit')
end
- end
- it 'edits variable' do
- page.within('.js-ci-variable-list-section') do
- click_button('Reveal value')
-
- page.within('.js-row:nth-child(2)') do
- find('.js-ci-variable-input-key').set('new_key')
- find('.js-ci-variable-input-value').set('new_value')
- end
+ page.within('#add-ci-variable') do
+ click_button('Delete variable')
+ end
- click_button('Save variables')
- wait_for_requests
+ wait_for_requests
- visit page_path
+ expect(first('.js-ci-variable-row').text).to eq('There are no variables yet.')
+ end
- page.within('.js-row:nth-child(2)') do
- expect(find('.js-ci-variable-input-key').value).to eq('new_key')
- expect(find('.js-ci-variable-input-value', visible: false).value).to eq('new_value')
- end
+ it 'edits a variable' do
+ page.within('.ci-variable-table') do
+ click_button('Edit')
end
- end
- it 'edits variable to be protected' do
- # Create the unprotected variable
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('unprotected_key')
- find('.js-ci-variable-input-value').set('unprotected_value')
- find('.ci-variable-protected-item .js-project-feature-toggle').click
+ page.within('#add-ci-variable') do
+ find('[data-qa-selector="ci_variable_key_field"] input').set('new_key')
- expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('false')
+ click_button('Update variable')
end
- click_button('Save variables')
wait_for_requests
- visit page_path
+ expect(first('.js-ci-variable-row td[data-label="Key"]').text).to eq('new_key')
+ end
+
+ it 'edits a variable to be unmasked' do
+ page.within('.ci-variable-table') do
+ click_button('Edit')
+ end
- # We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(3)') do
- find('.ci-variable-protected-item .js-project-feature-toggle').click
+ page.within('#add-ci-variable') do
+ find('[data-testid="ci-variable-protected-checkbox"]').click
+ find('[data-testid="ci-variable-masked-checkbox"]').click
- expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
+ click_button('Update variable')
end
- click_button('Save variables')
wait_for_requests
- visit page_path
-
- # We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(3)') do
- expect(find('.js-ci-variable-input-key').value).to eq('unprotected_key')
- expect(find('.js-ci-variable-input-value', visible: false).value).to eq('unprotected_value')
- expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
+ page.within('.ci-variable-table') do
+ expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Masked"] svg[data-testid="close-icon"]')).to be_present
end
end
- it 'edits variable to be unprotected' do
- # Create the protected variable
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('protected_key')
- find('.js-ci-variable-input-value').set('protected_value')
+ it 'edits a variable to be masked' do
+ page.within('.ci-variable-table') do
+ click_button('Edit')
+ end
+
+ page.within('#add-ci-variable') do
+ find('[data-testid="ci-variable-masked-checkbox"]').click
- expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
+ click_button('Update variable')
end
- click_button('Save variables')
wait_for_requests
- visit page_path
+ page.within('.ci-variable-table') do
+ click_button('Edit')
+ end
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
- find('.ci-variable-protected-item .js-project-feature-toggle').click
+ page.within('#add-ci-variable') do
+ find('[data-testid="ci-variable-masked-checkbox"]').click
- expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('false')
+ click_button('Update variable')
end
- click_button('Save variables')
- wait_for_requests
+ page.within('.ci-variable-table') do
+ expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Masked"] svg[data-testid="mobile-issue-close-icon"]')).to be_present
+ end
+ end
- visit page_path
+ it 'shows a validation error box about duplicate keys' do
+ click_button('Add Variable')
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
- expect(find('.js-ci-variable-input-key').value).to eq('protected_key')
- expect(find('.js-ci-variable-input-value', visible: false).value).to eq('protected_value')
- expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('false')
+ fill_variable('key', 'key_value') do
+ click_button('Add variable')
end
- end
- it 'edits variable to be unmasked' do
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('unmasked_key')
- find('.js-ci-variable-input-value').set('unmasked_value')
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
+ wait_for_requests
- find('.ci-variable-masked-item .js-project-feature-toggle').click
+ click_button('Add Variable')
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
+ fill_variable('key', 'key_value') do
+ click_button('Add variable')
end
- click_button('Save variables')
wait_for_requests
- visit page_path
+ expect(find('.flash-container')).to be_present
+ expect(find('.flash-text').text).to have_content('Variables key (key) has already been taken')
+ end
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
+ it 'prevents a variable to be added if no values are provided when a variable is set to masked' do
+ click_button('Add Variable')
- find('.ci-variable-masked-item .js-project-feature-toggle').click
+ page.within('#add-ci-variable') do
+ find('[data-qa-selector="ci_variable_key_field"] input').set('empty_mask_key')
+ find('[data-testid="ci-variable-protected-checkbox"]').click
+ find('[data-testid="ci-variable-masked-checkbox"]').click
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
+ expect(find_button('Add variable', disabled: true)).to be_present
end
+ end
- click_button('Save variables')
- wait_for_requests
-
- visit page_path
+ it 'shows validation error box about unmaskable values' do
+ click_button('Add Variable')
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
+ fill_variable('empty_mask_key', '???', protected: true, masked: true) do
+ expect(page).to have_content('This variable can not be masked')
+ expect(find_button('Add variable', disabled: true)).to be_present
end
end
- it 'edits variable to be masked' do
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('masked_key')
- find('.js-ci-variable-input-value').set('masked_value')
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
+ it 'handles multiple edits and a deletion' do
+ # Create two variables
+ click_button('Add Variable')
- find('.ci-variable-masked-item .js-project-feature-toggle').click
-
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
+ fill_variable('akey', 'akeyvalue') do
+ click_button('Add variable')
end
- click_button('Save variables')
wait_for_requests
- visit page_path
+ click_button('Add Variable')
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
+ fill_variable('zkey', 'zkeyvalue') do
+ click_button('Add variable')
end
- end
-
- it 'handles multiple edits and deletion in the middle' do
- page.within('.js-ci-variable-list-section') do
- # Create 2 variables
- page.within('.js-row:last-child') do
- find('.js-ci-variable-input-key').set('akey')
- find('.js-ci-variable-input-value').set('akeyvalue')
- end
- page.within('.js-row:last-child') do
- find('.js-ci-variable-input-key').set('zkey')
- find('.js-ci-variable-input-value').set('zkeyvalue')
- end
- click_button('Save variables')
- wait_for_requests
+ wait_for_requests
- expect(page).to have_selector('.js-row', count: 4)
+ expect(page).to have_selector('.js-ci-variable-row', count: 3)
- # Remove the `akey` variable
- page.within('.js-row:nth-child(3)') do
- first('.js-row-remove-button').click
+ # Remove the `akey` variable
+ page.within('.ci-variable-table') do
+ page.within('.js-ci-variable-row:first-child') do
+ click_button('Edit')
end
+ end
- # Add another variable
- page.within('.js-row:last-child') do
- find('.js-ci-variable-input-key').set('ckey')
- find('.js-ci-variable-input-value').set('ckeyvalue')
- end
+ page.within('#add-ci-variable') do
+ click_button('Delete variable')
+ end
- click_button('Save variables')
- wait_for_requests
+ wait_for_requests
- visit page_path
+ # Add another variable
+ click_button('Add Variable')
- # Expect to find 3 variables(4 rows) in alphbetical order
- expect(page).to have_selector('.js-row', count: 4)
- row_keys = all('.js-ci-variable-input-key')
- expect(row_keys[0].value).to eq('ckey')
- expect(row_keys[1].value).to eq('test_key')
- expect(row_keys[2].value).to eq('zkey')
- expect(row_keys[3].value).to eq('')
+ fill_variable('ckey', 'ckeyvalue') do
+ click_button('Add variable')
end
+
+ wait_for_requests
+
+ # expect to find 3 rows of variables in alphabetical order
+ expect(page).to have_selector('.js-ci-variable-row', count: 3)
+ rows = all('.js-ci-variable-row')
+ expect(rows[0].find('td[data-label="Key"]').text).to eq('ckey')
+ expect(rows[1].find('td[data-label="Key"]').text).to eq('test_key')
+ expect(rows[2].find('td[data-label="Key"]').text).to eq('zkey')
end
- it 'shows validation error box about duplicate keys' do
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('samekey')
- find('.js-ci-variable-input-value').set('value123')
- end
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('samekey')
- find('.js-ci-variable-input-value').set('value456')
- end
+ context 'defaults to the application setting' do
+ context 'application setting is true' do
+ before do
+ stub_application_setting(protected_ci_variables: true)
- click_button('Save variables')
- wait_for_requests
+ visit page_path
+ end
- expect(all('.js-ci-variable-list-section .js-ci-variable-error-box ul li').count).to eq(1)
+ it 'defaults to protected' do
+ click_button('Add Variable')
- # We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section') do
- expect(find('.js-ci-variable-error-box')).to have_content(/Validation failed Variables have duplicate values \(.+\)/)
- end
- end
+ page.within('#add-ci-variable') do
+ expect(find('[data-testid="ci-variable-protected-checkbox"]')).to be_checked
+ end
+ end
- it 'shows validation error box about masking empty values' do
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('empty_value')
- find('.js-ci-variable-input-value').set('')
- find('.ci-variable-masked-item .js-project-feature-toggle').click
+ it 'shows a message regarding the changed default' do
+ expect(page).to have_content 'Environment variables are configured by your administrator to be protected by default'
+ end
end
- click_button('Save variables')
- wait_for_requests
+ context 'application setting is false' do
+ before do
+ stub_application_setting(protected_ci_variables: false)
- page.within('.js-ci-variable-list-section') do
- expect(all('.js-ci-variable-error-box ul li').count).to eq(1)
- expect(find('.js-ci-variable-error-box')).to have_content(/Validation failed Variables value is invalid/)
- end
- end
+ visit page_path
+ end
- it 'shows validation error box about unmaskable values' do
- page.within('.js-ci-variable-list-section .js-row:last-child') do
- find('.js-ci-variable-input-key').set('unmaskable_value')
- find('.js-ci-variable-input-value').set('???')
- find('.ci-variable-masked-item .js-project-feature-toggle').click
+ it 'defaults to unprotected' do
+ click_button('Add Variable')
+
+ page.within('#add-ci-variable') do
+ expect(find('[data-testid="ci-variable-protected-checkbox"]')).not_to be_checked
+ end
+ end
+
+ it 'does not show a message regarding the default' do
+ expect(page).not_to have_content 'Environment variables are configured by your administrator to be protected by default'
+ end
end
+ end
- click_button('Save variables')
- wait_for_requests
+ def fill_variable(key, value, protected: false, masked: false)
+ page.within('#add-ci-variable') do
+ find('[data-qa-selector="ci_variable_key_field"] input').set(key)
+ find('[data-qa-selector="ci_variable_value_field"]').set(value) if value.present?
+ find('[data-testid="ci-variable-protected-checkbox"]').click if protected
+ find('[data-testid="ci-variable-masked-checkbox"]').click if masked
- page.within('.js-ci-variable-list-section') do
- expect(all('.js-ci-variable-error-box ul li').count).to eq(1)
- expect(find('.js-ci-variable-error-box')).to have_content(/Validation failed Variables value is invalid/)
+ yield
end
end
end
diff --git a/spec/support/shared_examples/features/wiki/user_deletes_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_deletes_wiki_page_shared_examples.rb
index e1fd9c8dbec..ee0261771f9 100644
--- a/spec/support/shared_examples/features/wiki/user_deletes_wiki_page_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_deletes_wiki_page_shared_examples.rb
@@ -17,8 +17,8 @@ RSpec.shared_examples 'User deletes wiki page' do
it 'deletes a page', :js do
click_on('Edit')
click_on('Delete')
- find('.modal-footer .btn-danger').click
+ find('[data-testid="confirm_deletion_button"]').click
- expect(page).to have_content('Page was successfully deleted')
+ expect(page).to have_content('Wiki page was successfully deleted.')
end
end
diff --git a/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb
index 1a5f8d7d8df..3350e54a8a7 100644
--- a/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb
@@ -213,11 +213,11 @@ RSpec.shared_examples 'User updates wiki page' do
visit wiki_page_path(wiki_page.wiki, wiki_page, action: :edit)
end
- it 'allows changing the title if the content does not change' do
+ it 'allows changing the title if the content does not change', :js do
fill_in 'Title', with: 'new title'
click_on 'Save changes'
- expect(page).to have_content('Wiki was successfully updated.')
+ expect(page).to have_content('Wiki page was successfully updated.')
end
it 'shows a validation error when trying to change the content' do
diff --git a/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb
index 85eedbf4cc5..af769be6d4b 100644
--- a/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb
@@ -33,7 +33,7 @@ RSpec.shared_examples 'User views a wiki page' do
click_on('Create page')
end
- expect(page).to have_content('Wiki was successfully updated.')
+ expect(page).to have_content('Wiki page was successfully created.')
end
it 'shows the history of a page that has a path' do
@@ -49,7 +49,7 @@ RSpec.shared_examples 'User views a wiki page' do
end
end
- it 'shows an old version of a page' do
+ it 'shows an old version of a page', :js do
expect(current_path).to include('one/two/three-test')
expect(find('.wiki-pages')).to have_content('three')
@@ -65,7 +65,7 @@ RSpec.shared_examples 'User views a wiki page' do
fill_in('Content', with: 'Updated Wiki Content')
click_on('Save changes')
- expect(page).to have_content('Wiki was successfully updated.')
+ expect(page).to have_content('Wiki page was successfully updated.')
click_on('Page history')
diff --git a/spec/support/shared_examples/finders/security/jobs_finder_shared_examples.rb b/spec/support/shared_examples/finders/security/jobs_finder_shared_examples.rb
new file mode 100644
index 00000000000..a332b213866
--- /dev/null
+++ b/spec/support/shared_examples/finders/security/jobs_finder_shared_examples.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples ::Security::JobsFinder do |default_job_types|
+ let(:pipeline) { create(:ci_pipeline) }
+
+ describe '#new' do
+ it "does not get initialized for unsupported job types" do
+ expect { described_class.new(pipeline: pipeline, job_types: [:abcd]) }.to raise_error(
+ ArgumentError,
+ "job_types must be from the following: #{default_job_types}"
+ )
+ end
+ end
+
+ describe '#execute' do
+ let(:finder) { described_class.new(pipeline: pipeline) }
+
+ subject { finder.execute }
+
+ shared_examples 'JobsFinder core functionality' do
+ context 'when the pipeline has no jobs' do
+ it { is_expected.to be_empty }
+ end
+
+ context 'when the pipeline has no Secure jobs' do
+ before do
+ create(:ci_build, pipeline: pipeline)
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'when the pipeline only has jobs without report artifacts' do
+ before do
+ create(:ci_build, pipeline: pipeline, options: { artifacts: { file: 'test.file' } })
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'when the pipeline only has jobs with reports unrelated to Secure products' do
+ before do
+ create(:ci_build, pipeline: pipeline, options: { artifacts: { reports: { file: 'test.file' } } })
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'when the pipeline only has jobs with reports with paths similar but not identical to Secure reports' do
+ before do
+ create(:ci_build, pipeline: pipeline, options: { artifacts: { reports: { file: 'report:sast:result.file' } } })
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'when there is more than one pipeline' do
+ let(:job_type) { default_job_types.first }
+ let!(:build) { create(:ci_build, job_type, pipeline: pipeline) }
+
+ before do
+ create(:ci_build, job_type, pipeline: create(:ci_pipeline))
+ end
+
+ it 'returns jobs associated with provided pipeline' do
+ is_expected.to eq([build])
+ end
+ end
+ end
+
+ context 'when using legacy CI build metadata config storage' do
+ before do
+ stub_feature_flags(ci_build_metadata_config: false)
+ end
+
+ it_behaves_like 'JobsFinder core functionality'
+ end
+
+ context 'when using the new CI build metadata config storage' do
+ before do
+ stub_feature_flags(ci_build_metadata_config: true)
+ end
+
+ it_behaves_like 'JobsFinder core functionality'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/graphql/label_fields.rb b/spec/support/shared_examples/graphql/label_fields.rb
index b1bfb395bc6..caf5dae409a 100644
--- a/spec/support/shared_examples/graphql/label_fields.rb
+++ b/spec/support/shared_examples/graphql/label_fields.rb
@@ -106,13 +106,11 @@ RSpec.shared_examples 'querying a GraphQL type with labels' do
end
it 'batches queries for labels by title' do
- pending('See: https://gitlab.com/gitlab-org/gitlab/-/issues/217767')
-
multi_selection = query_for(label_b, label_c)
single_selection = query_for(label_d)
expect { run_query(multi_selection) }
- .to issue_same_number_of_queries_as { run_query(single_selection) }
+ .to issue_same_number_of_queries_as { run_query(single_selection) }.ignoring_cached_queries
end
end
diff --git a/spec/support/shared_examples/graphql/mutations/boards_create_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/boards_create_shared_examples.rb
index ec64519cd9c..9c0b398a5c1 100644
--- a/spec/support/shared_examples/graphql/mutations/boards_create_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/mutations/boards_create_shared_examples.rb
@@ -65,7 +65,7 @@ RSpec.shared_examples 'boards create mutation' do
let(:params) { { name: name } }
it_behaves_like 'a mutation that returns top-level errors',
- errors: ['group_path or project_path arguments are required']
+ errors: ['Exactly one of group_path or project_path arguments is required']
it 'does not create the board' do
expect { subject }.not_to change { Board.count }
diff --git a/spec/support/shared_examples/graphql/mutations/create_todo_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/create_todo_shared_examples.rb
new file mode 100644
index 00000000000..fbef8be9e88
--- /dev/null
+++ b/spec/support/shared_examples/graphql/mutations/create_todo_shared_examples.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'create todo mutation' do
+ let_it_be(:current_user) { create(:user) }
+
+ let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
+
+ context 'when user does not have permission to create todo' do
+ it 'raises error' do
+ expect { mutation.resolve(target_id: global_id_of(target)) }
+ .to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'when user has permission to create todo' do
+ it 'creates a todo' do
+ target.resource_parent.add_reporter(current_user)
+
+ result = mutation.resolve(target_id: global_id_of(target))
+
+ expect(result[:todo]).to be_valid
+ expect(result[:todo].target).to eq(target)
+ expect(result[:todo].state).to eq('pending')
+ end
+ end
+end
diff --git a/spec/support/shared_examples/graphql/mutations/issues/permission_check_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/issues/permission_check_shared_examples.rb
new file mode 100644
index 00000000000..34c58f524cd
--- /dev/null
+++ b/spec/support/shared_examples/graphql/mutations/issues/permission_check_shared_examples.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'permission level for issue mutation is correctly verified' do |raises_for_all_errors = false|
+ before do
+ issue.assignees = []
+ issue.author = user
+ end
+
+ shared_examples_for 'when the user does not have access to the resource' do |raise_for_assigned|
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+
+ context 'even if assigned to the issue' do
+ before do
+ issue.assignees.push(user)
+ end
+
+ it 'does not modify issue' do
+ if raises_for_all_errors || raise_for_assigned
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ else
+ expect(subject[:issue]).to eq issue
+ end
+ end
+ end
+
+ context 'even if author of the issue' do
+ before do
+ issue.author = user
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ context 'when the user is not a project member' do
+ it_behaves_like 'when the user does not have access to the resource', true
+ end
+
+ context 'when the user is a project member' do
+ context 'with guest role' do
+ before do
+ issue.project.add_guest(user)
+ end
+
+ it_behaves_like 'when the user does not have access to the resource', false
+ end
+ end
+end
diff --git a/spec/support/shared_examples/graphql/mutations/merge_requests/permission_check_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/merge_requests/permission_check_shared_examples.rb
new file mode 100644
index 00000000000..1ddbad1cea7
--- /dev/null
+++ b/spec/support/shared_examples/graphql/mutations/merge_requests/permission_check_shared_examples.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'permission level for merge request mutation is correctly verified' do
+ before do
+ merge_request.assignees = []
+ merge_request.reviewers = []
+ merge_request.author = nil
+ end
+
+ shared_examples_for 'when the user does not have access to the resource' do |raise_for_assigned|
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+
+ context 'even if assigned to the merge request' do
+ before do
+ merge_request.assignees.push(user)
+ end
+
+ it 'does not modify merge request' do
+ if raise_for_assigned
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ else
+ # In some cases we simply do nothing instead of raising
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/196241
+ expect(subject[:merge_request]).to eq merge_request
+ end
+ end
+ end
+
+ context 'even if reviewer of the merge request' do
+ before do
+ merge_request.reviewers.push(user)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'even if author of the merge request' do
+ before do
+ merge_request.author = user
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ context 'when the user is not a project member' do
+ it_behaves_like 'when the user does not have access to the resource', true
+ end
+
+ context 'when the user is a project member' do
+ context 'with guest role' do
+ before do
+ merge_request.project.add_guest(user)
+ end
+
+ it_behaves_like 'when the user does not have access to the resource', true
+ end
+
+ context 'with reporter role' do
+ before do
+ merge_request.project.add_reporter(user)
+ end
+
+ it_behaves_like 'when the user does not have access to the resource', false
+ end
+ end
+end
diff --git a/spec/support/shared_examples/helm_commands_shared_examples.rb b/spec/support/shared_examples/helm_commands_shared_examples.rb
index 0a94c6648cc..64f176c5ae9 100644
--- a/spec/support/shared_examples/helm_commands_shared_examples.rb
+++ b/spec/support/shared_examples/helm_commands_shared_examples.rb
@@ -15,6 +15,18 @@ RSpec.shared_examples 'helm command generator' do
end
RSpec.shared_examples 'helm command' do
+ describe 'HELM_VERSION' do
+ subject { command.class::HELM_VERSION }
+
+ it { is_expected.to match(/\d+\.\d+\.\d+/) }
+ end
+
+ describe '#env' do
+ subject { command.env }
+
+ it { is_expected.to be_a Hash }
+ end
+
describe '#rbac?' do
subject { command.rbac? }
diff --git a/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb
index d0e41605e00..145a7290ac8 100644
--- a/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples_for 'cycle analytics event' do
+RSpec.shared_examples_for 'value stream analytics event' do
let(:params) { {} }
let(:instance) { described_class.new(params) }
diff --git a/spec/support/shared_examples/lib/gitlab/database/background_migration_job_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/database/background_migration_job_shared_examples.rb
new file mode 100644
index 00000000000..20f3270526e
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/database/background_migration_job_shared_examples.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'marks background migration job records' do
+ it 'marks each job record as succeeded after processing' do
+ create(:background_migration_job, class_name: "::#{described_class.name}",
+ arguments: arguments)
+
+ expect(::Gitlab::Database::BackgroundMigrationJob).to receive(:mark_all_as_succeeded).and_call_original
+
+ expect do
+ subject.perform(*arguments)
+ 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: arguments)
+
+ jobs_updated = subject.perform(*arguments)
+
+ expect(jobs_updated).to eq(1)
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/database/postgres_model_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/database/postgres_model_shared_examples.rb
new file mode 100644
index 00000000000..ffebbabca58
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/database/postgres_model_shared_examples.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'a postgres model' do
+ describe '.by_identifier' do
+ it "finds the #{described_class}" do
+ expect(find(identifier)).to be_a(described_class)
+ end
+
+ it 'raises an error if not found' do
+ expect { find('public.idontexist') }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'raises ArgumentError if given a non-fully qualified identifier' do
+ expect { find('foo') }.to raise_error(ArgumentError, /not fully qualified/)
+ end
+ end
+
+ describe '#to_s' do
+ it 'returns the name' do
+ expect(find(identifier).to_s).to eq(name)
+ end
+ end
+
+ describe '#schema' do
+ it 'returns the schema' do
+ expect(find(identifier).schema).to eq(schema)
+ end
+ end
+
+ describe '#name' do
+ it 'returns the name' do
+ expect(find(identifier).name).to eq(name)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/middleware/read_only_gitlab_instance_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/middleware/read_only_gitlab_instance_shared_examples.rb
new file mode 100644
index 00000000000..e07d3e2dec9
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/middleware/read_only_gitlab_instance_shared_examples.rb
@@ -0,0 +1,189 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'write access for a read-only GitLab instance' do
+ include Rack::Test::Methods
+ using RSpec::Parameterized::TableSyntax
+
+ include_context 'with a mocked GitLab instance'
+
+ context 'normal requests to a read-only GitLab instance' do
+ let(:fake_app) { lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ['OK']] } }
+
+ it 'expects PATCH requests to be disallowed' do
+ response = request.patch('/test_request')
+
+ expect(response).to be_redirect
+ expect(subject).to disallow_request
+ end
+
+ it 'expects PUT requests to be disallowed' do
+ response = request.put('/test_request')
+
+ expect(response).to be_redirect
+ expect(subject).to disallow_request
+ end
+
+ it 'expects POST requests to be disallowed' do
+ response = request.post('/test_request')
+
+ expect(response).to be_redirect
+ expect(subject).to disallow_request
+ end
+
+ it 'expects a internal POST request to be allowed after a disallowed request' do
+ response = request.post('/test_request')
+
+ expect(response).to be_redirect
+
+ response = request.post("/api/#{API::API.version}/internal")
+
+ expect(response).not_to be_redirect
+ end
+
+ it 'expects DELETE requests to be disallowed' do
+ response = request.delete('/test_request')
+
+ expect(response).to be_redirect
+ expect(subject).to disallow_request
+ end
+
+ it 'expects POST of new file that looks like an LFS batch url to be disallowed' do
+ expect(Rails.application.routes).to receive(:recognize_path).and_call_original
+ response = request.post('/root/gitlab-ce/new/master/app/info/lfs/objects/batch')
+
+ expect(response).to be_redirect
+ expect(subject).to disallow_request
+ end
+
+ it 'returns last_vistited_url for disallowed request' do
+ response = request.post('/test_request')
+
+ expect(response.location).to eq 'http://localhost/'
+ end
+
+ context 'allowlisted requests' do
+ it 'expects a POST internal request to be allowed' do
+ expect(Rails.application.routes).not_to receive(:recognize_path)
+ response = request.post("/api/#{API::API.version}/internal")
+
+ expect(response).not_to be_redirect
+ expect(subject).not_to disallow_request
+ end
+
+ it 'expects a graphql request to be allowed' do
+ response = request.post("/api/graphql")
+
+ expect(response).not_to be_redirect
+ expect(subject).not_to disallow_request
+ end
+
+ context 'relative URL is configured' do
+ before do
+ stub_config_setting(relative_url_root: '/gitlab')
+ end
+
+ it 'expects a graphql request to be allowed' do
+ response = request.post("/gitlab/api/graphql")
+
+ expect(response).not_to be_redirect
+ expect(subject).not_to disallow_request
+ end
+ end
+
+ context 'sidekiq admin requests' do
+ where(:mounted_at) do
+ [
+ '',
+ '/',
+ '/gitlab',
+ '/gitlab/',
+ '/gitlab/gitlab',
+ '/gitlab/gitlab/'
+ ]
+ end
+
+ with_them do
+ before do
+ stub_config_setting(relative_url_root: mounted_at)
+ end
+
+ it 'allows requests' do
+ path = File.join(mounted_at, 'admin/sidekiq')
+ response = request.post(path)
+
+ expect(response).not_to be_redirect
+ expect(subject).not_to disallow_request
+
+ response = request.get(path)
+
+ expect(response).not_to be_redirect
+ expect(subject).not_to disallow_request
+ end
+ end
+ end
+
+ where(:description, :path) do
+ 'LFS request to batch' | '/root/rouge.git/info/lfs/objects/batch'
+ 'request to git-upload-pack' | '/root/rouge.git/git-upload-pack'
+ end
+
+ with_them do
+ it "expects a POST #{description} URL to be allowed" do
+ expect(Rails.application.routes).to receive(:recognize_path).and_call_original
+ response = request.post(path)
+
+ expect(response).not_to be_redirect
+ expect(subject).not_to disallow_request
+ end
+ end
+
+ where(:description, :path) do
+ 'LFS request to locks verify' | '/root/rouge.git/info/lfs/locks/verify'
+ 'LFS request to locks create' | '/root/rouge.git/info/lfs/locks'
+ 'LFS request to locks unlock' | '/root/rouge.git/info/lfs/locks/1/unlock'
+ end
+
+ with_them do
+ it "expects a POST #{description} URL not to be allowed" do
+ response = request.post(path)
+
+ expect(response).to be_redirect
+ expect(subject).to disallow_request
+ end
+ end
+ end
+ end
+
+ context 'json requests to a read-only GitLab instance' do
+ let(:fake_app) { lambda { |env| [200, { 'Content-Type' => 'application/json' }, ['OK']] } }
+ let(:content_json) { { 'CONTENT_TYPE' => 'application/json' } }
+
+ before do
+ allow(Gitlab::Database).to receive(:read_only?) { true }
+ end
+
+ it 'expects PATCH requests to be disallowed' do
+ response = request.patch('/test_request', content_json)
+
+ expect(response).to disallow_request_in_json
+ end
+
+ it 'expects PUT requests to be disallowed' do
+ response = request.put('/test_request', content_json)
+
+ expect(response).to disallow_request_in_json
+ end
+
+ it 'expects POST requests to be disallowed' do
+ response = request.post('/test_request', content_json)
+
+ expect(response).to disallow_request_in_json
+ end
+
+ it 'expects DELETE requests to be disallowed' do
+ response = request.delete('/test_request', content_json)
+
+ expect(response).to disallow_request_in_json
+ end
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/repository_size_checker_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/repository_size_checker_shared_examples.rb
index bb909ffe82a..30413f206f8 100644
--- a/spec/support/shared_examples/lib/gitlab/repository_size_checker_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/repository_size_checker_shared_examples.rb
@@ -17,35 +17,58 @@ RSpec.shared_examples 'checker size not over limit' do
end
RSpec.shared_examples 'checker size exceeded' do
- context 'when current size is below or equal to the limit' do
- let(:current_size) { 50 }
+ context 'when no change size provided' do
+ context 'when current size is below the limit' do
+ let(:current_size) { limit - 1 }
- it 'returns zero' do
- expect(subject.exceeded_size).to eq(0)
+ it 'returns zero' do
+ expect(subject.exceeded_size).to eq(0)
+ end
end
- end
- context 'when current size is over the limit' do
- let(:current_size) { 51 }
+ context 'when current size is equal to the limit' do
+ let(:current_size) { limit }
- it 'returns zero' do
- expect(subject.exceeded_size).to eq(1.megabytes)
+ it 'returns zero' do
+ expect(subject.exceeded_size).to eq(0)
+ end
end
- end
- context 'when change size will be over the limit' do
- let(:current_size) { 50 }
+ context 'when current size is over the limit' do
+ let(:current_size) { limit + 1 }
+ let(:total_repository_size_excess) { 1 }
- it 'returns zero' do
- expect(subject.exceeded_size(1.megabytes)).to eq(1.megabytes)
+ it 'returns a positive number' do
+ expect(subject.exceeded_size).to eq(1.megabyte)
+ end
end
end
- context 'when change size will not be over the limit' do
- let(:current_size) { 49 }
+ context 'when a change size is provided' do
+ let(:change_size) { 1.megabyte }
+
+ context 'when change size will be over the limit' do
+ let(:current_size) { limit }
+
+ it 'returns a positive number' do
+ expect(subject.exceeded_size(change_size)).to eq(1.megabyte)
+ end
+ end
+
+ context 'when change size will be at the limit' do
+ let(:current_size) { limit - 1 }
+
+ it 'returns zero' do
+ expect(subject.exceeded_size(change_size)).to eq(0)
+ end
+ end
+
+ context 'when change size will be under the limit' do
+ let(:current_size) { limit - 2 }
- it 'returns zero' do
- expect(subject.exceeded_size(1.megabytes)).to eq(0)
+ it 'returns zero' do
+ expect(subject.exceeded_size(change_size)).to eq(0)
+ end
end
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/search_confidential_filter_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/search_confidential_filter_shared_examples.rb
index d0bef2ad730..e70dfec80b1 100644
--- a/spec/support/shared_examples/lib/gitlab/search_confidential_filter_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/search_confidential_filter_shared_examples.rb
@@ -4,66 +4,27 @@ RSpec.shared_examples 'search results filtered by confidential' do
context 'filter not provided (all behavior)' do
let(:filters) { {} }
- context 'when Feature search_filter_by_confidential enabled' do
- it 'returns confidential and not confidential results', :aggregate_failures do
- expect(results.objects('issues')).to include confidential_result
- expect(results.objects('issues')).to include opened_result
- end
- end
-
- context 'when Feature search_filter_by_confidential not enabled' do
- before do
- stub_feature_flags(search_filter_by_confidential: false)
- end
-
- it 'returns confidential and not confidential results', :aggregate_failures do
- expect(results.objects('issues')).to include confidential_result
- expect(results.objects('issues')).to include opened_result
- end
+ it 'returns confidential and not confidential results', :aggregate_failures do
+ expect(results.objects('issues')).to include confidential_result
+ expect(results.objects('issues')).to include opened_result
end
end
context 'confidential filter' do
let(:filters) { { confidential: true } }
- context 'when Feature search_filter_by_confidential enabled' do
- it 'returns only confidential results', :aggregate_failures do
- expect(results.objects('issues')).to include confidential_result
- expect(results.objects('issues')).not_to include opened_result
- end
- end
-
- context 'when Feature search_filter_by_confidential not enabled' do
- before do
- stub_feature_flags(search_filter_by_confidential: false)
- end
-
- it 'returns confidential and not confidential results', :aggregate_failures do
- expect(results.objects('issues')).to include confidential_result
- expect(results.objects('issues')).to include opened_result
- end
+ it 'returns only confidential results', :aggregate_failures do
+ expect(results.objects('issues')).to include confidential_result
+ expect(results.objects('issues')).not_to include opened_result
end
end
context 'not confidential filter' do
let(:filters) { { confidential: false } }
- context 'when Feature search_filter_by_confidential enabled' do
- it 'returns not confidential results', :aggregate_failures do
- expect(results.objects('issues')).not_to include confidential_result
- expect(results.objects('issues')).to include opened_result
- end
- end
-
- context 'when Feature search_filter_by_confidential not enabled' do
- before do
- stub_feature_flags(search_filter_by_confidential: false)
- end
-
- it 'returns confidential and not confidential results', :aggregate_failures do
- expect(results.objects('issues')).to include confidential_result
- expect(results.objects('issues')).to include opened_result
- end
+ it 'returns not confidential results', :aggregate_failures do
+ expect(results.objects('issues')).not_to include confidential_result
+ expect(results.objects('issues')).to include opened_result
end
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb
index 765279a78fe..07d01d5c50e 100644
--- a/spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb
@@ -2,7 +2,7 @@
RSpec.shared_examples 'search results sorted' do
context 'sort: newest' do
- let(:sort) { 'newest' }
+ let(:sort) { 'created_desc' }
it 'sorts results by created_at' do
expect(results.objects(scope).map(&:id)).to eq([new_result.id, old_result.id, very_old_result.id])
@@ -10,7 +10,7 @@ RSpec.shared_examples 'search results sorted' do
end
context 'sort: oldest' do
- let(:sort) { 'oldest' }
+ let(:sort) { 'created_asc' }
it 'sorts results by created_at' do
expect(results.objects(scope).map(&:id)).to eq([very_old_result.id, old_result.id, new_result.id])
diff --git a/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb
new file mode 100644
index 00000000000..2936bb354cf
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb
@@ -0,0 +1,139 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name|
+ let(:fake_duplicate_job) do
+ instance_double(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob)
+ end
+
+ let(:expected_message) { "dropped #{strategy_name.to_s.humanize.downcase}" }
+
+ subject(:strategy) { Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies.for(strategy_name).new(fake_duplicate_job) }
+
+ describe '#schedule' do
+ before do
+ allow(Gitlab::SidekiqLogging::DeduplicationLogger.instance).to receive(:log)
+ end
+
+ it 'checks for duplicates before yielding' do
+ expect(fake_duplicate_job).to receive(:scheduled?).twice.ordered.and_return(false)
+ expect(fake_duplicate_job).to(
+ receive(:check!)
+ .with(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob::DUPLICATE_KEY_TTL)
+ .ordered
+ .and_return('a jid'))
+ expect(fake_duplicate_job).to receive(:duplicate?).ordered.and_return(false)
+
+ expect { |b| strategy.schedule({}, &b) }.to yield_control
+ end
+
+ it 'checks worker options for scheduled jobs' do
+ expect(fake_duplicate_job).to receive(:scheduled?).ordered.and_return(true)
+ expect(fake_duplicate_job).to receive(:options).ordered.and_return({})
+ expect(fake_duplicate_job).not_to receive(:check!)
+
+ expect { |b| strategy.schedule({}, &b) }.to yield_control
+ end
+
+ context 'job marking' do
+ it 'adds the jid of the existing job to the job hash' do
+ allow(fake_duplicate_job).to receive(:scheduled?).and_return(false)
+ allow(fake_duplicate_job).to receive(:check!).and_return('the jid')
+ allow(fake_duplicate_job).to receive(:droppable?).and_return(true)
+ allow(fake_duplicate_job).to receive(:options).and_return({})
+ job_hash = {}
+
+ expect(fake_duplicate_job).to receive(:duplicate?).and_return(true)
+ expect(fake_duplicate_job).to receive(:existing_jid).and_return('the jid')
+
+ strategy.schedule(job_hash) {}
+
+ expect(job_hash).to include('duplicate-of' => 'the jid')
+ end
+
+ context 'scheduled jobs' do
+ let(:time_diff) { 1.minute }
+
+ context 'scheduled in the past' do
+ it 'adds the jid of the existing job to the job hash' 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 })
+ allow(fake_duplicate_job).to(
+ receive(:check!)
+ .with(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob::DUPLICATE_KEY_TTL)
+ .and_return('the jid'))
+ allow(fake_duplicate_job).to receive(:droppable?).and_return(true)
+ job_hash = {}
+
+ expect(fake_duplicate_job).to receive(:duplicate?).and_return(true)
+ expect(fake_duplicate_job).to receive(:existing_jid).and_return('the jid')
+
+ strategy.schedule(job_hash) {}
+
+ expect(job_hash).to include('duplicate-of' => 'the jid')
+ end
+ end
+
+ context 'scheduled in the future' do
+ it 'adds the jid of the existing job to the job hash' 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 })
+ allow(fake_duplicate_job).to(
+ receive(:check!).with(time_diff.to_i).and_return('the jid'))
+ allow(fake_duplicate_job).to receive(:droppable?).and_return(true)
+ job_hash = {}
+
+ expect(fake_duplicate_job).to receive(:duplicate?).and_return(true)
+ expect(fake_duplicate_job).to receive(:existing_jid).and_return('the jid')
+
+ strategy.schedule(job_hash) {}
+
+ expect(job_hash).to include('duplicate-of' => 'the jid')
+ end
+ end
+ end
+ end
+ end
+
+ context "when the job is droppable" do
+ before do
+ allow(fake_duplicate_job).to receive(:scheduled?).and_return(false)
+ allow(fake_duplicate_job).to receive(:check!).and_return('the jid')
+ allow(fake_duplicate_job).to receive(:duplicate?).and_return(true)
+ allow(fake_duplicate_job).to receive(:options).and_return({})
+ allow(fake_duplicate_job).to receive(:existing_jid).and_return('the jid')
+ allow(fake_duplicate_job).to receive(:droppable?).and_return(true)
+ end
+
+ it 'drops the job' do
+ schedule_result = nil
+
+ expect(fake_duplicate_job).to receive(:droppable?).and_return(true)
+
+ expect { |b| schedule_result = strategy.schedule({}, &b) }.not_to yield_control
+ expect(schedule_result).to be(false)
+ end
+
+ it 'logs that the job was dropped' do
+ fake_logger = instance_double(Gitlab::SidekiqLogging::DeduplicationLogger)
+
+ expect(Gitlab::SidekiqLogging::DeduplicationLogger).to receive(:instance).and_return(fake_logger)
+ expect(fake_logger).to receive(:log).with(a_hash_including({ 'jid' => 'new jid' }), expected_message, {})
+
+ strategy.schedule({ 'jid' => 'new jid' }) {}
+ end
+
+ it 'logs the deduplication options of the worker' do
+ fake_logger = instance_double(Gitlab::SidekiqLogging::DeduplicationLogger)
+
+ expect(Gitlab::SidekiqLogging::DeduplicationLogger).to receive(:instance).and_return(fake_logger)
+ allow(fake_duplicate_job).to receive(:options).and_return({ foo: :bar })
+ expect(fake_logger).to receive(:log).with(a_hash_including({ 'jid' => 'new jid' }), expected_message, { foo: :bar })
+
+ strategy.schedule({ 'jid' => 'new jid' }) {}
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issue_activity_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issue_activity_shared_examples.rb
new file mode 100644
index 00000000000..286305f2506
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issue_activity_shared_examples.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'a tracked issue edit event' do |event|
+ before do
+ stub_application_setting(usage_ping_enabled: true)
+ end
+
+ def count_unique(date_from:, date_to:)
+ Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: action, start_date: date_from, end_date: date_to)
+ end
+
+ 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
diff --git a/spec/support/shared_examples/mailers/notify_shared_examples.rb b/spec/support/shared_examples/mailers/notify_shared_examples.rb
index 7ce7b2161f6..0143bf693c7 100644
--- a/spec/support/shared_examples/mailers/notify_shared_examples.rb
+++ b/spec/support/shared_examples/mailers/notify_shared_examples.rb
@@ -273,3 +273,12 @@ RSpec.shared_examples 'no email is sent' do
expect(subject.message).to be_a_kind_of(ActionMailer::Base::NullMail)
end
end
+
+RSpec.shared_examples 'does not render a manage notifications link' do
+ it do
+ aggregate_failures do
+ expect(subject).not_to have_body_text("Manage all notifications")
+ expect(subject).not_to have_body_text(profile_notifications_url)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/application_setting_shared_examples.rb b/spec/support/shared_examples/models/application_setting_shared_examples.rb
index 01513161d24..92fd4363134 100644
--- a/spec/support/shared_examples/models/application_setting_shared_examples.rb
+++ b/spec/support/shared_examples/models/application_setting_shared_examples.rb
@@ -1,84 +1,84 @@
# frozen_string_literal: true
-RSpec.shared_examples 'string of domains' do |attribute|
+RSpec.shared_examples 'string of domains' do |mapped_name, attribute|
it 'sets single domain' do
- setting.method("#{attribute}_raw=").call('example.com')
+ setting.method("#{mapped_name}_raw=").call('example.com')
expect(setting.method(attribute).call).to eq(['example.com'])
end
it 'sets multiple domains with spaces' do
- setting.method("#{attribute}_raw=").call('example.com *.example.com')
+ setting.method("#{mapped_name}_raw=").call('example.com *.example.com')
expect(setting.method(attribute).call).to eq(['example.com', '*.example.com'])
end
it 'sets multiple domains with newlines and a space' do
- setting.method("#{attribute}_raw=").call("example.com\n *.example.com")
+ setting.method("#{mapped_name}_raw=").call("example.com\n *.example.com")
expect(setting.method(attribute).call).to eq(['example.com', '*.example.com'])
end
it 'sets multiple domains with commas' do
- setting.method("#{attribute}_raw=").call("example.com, *.example.com")
+ setting.method("#{mapped_name}_raw=").call("example.com, *.example.com")
expect(setting.method(attribute).call).to eq(['example.com', '*.example.com'])
end
it 'sets multiple domains with semicolon' do
- setting.method("#{attribute}_raw=").call("example.com; *.example.com")
+ setting.method("#{mapped_name}_raw=").call("example.com; *.example.com")
expect(setting.method(attribute).call).to contain_exactly('example.com', '*.example.com')
end
it 'sets multiple domains with mixture of everything' do
- setting.method("#{attribute}_raw=").call("example.com; *.example.com\n test.com\sblock.com yes.com")
+ setting.method("#{mapped_name}_raw=").call("example.com; *.example.com\n test.com\sblock.com yes.com")
expect(setting.method(attribute).call).to contain_exactly('example.com', '*.example.com', 'test.com', 'block.com', 'yes.com')
end
it 'removes duplicates' do
- setting.method("#{attribute}_raw=").call("example.com; example.com; 127.0.0.1; 127.0.0.1")
+ setting.method("#{mapped_name}_raw=").call("example.com; example.com; 127.0.0.1; 127.0.0.1")
expect(setting.method(attribute).call).to contain_exactly('example.com', '127.0.0.1')
end
it 'does not fail with garbage values' do
- setting.method("#{attribute}_raw=").call("example;34543:garbage:fdh5654;")
+ setting.method("#{mapped_name}_raw=").call("example;34543:garbage:fdh5654;")
expect(setting.method(attribute).call).to contain_exactly('example', '34543:garbage:fdh5654')
end
it 'does not raise error with nil' do
- setting.method("#{attribute}_raw=").call(nil)
+ setting.method("#{mapped_name}_raw=").call(nil)
expect(setting.method(attribute).call).to eq([])
end
end
RSpec.shared_examples 'application settings examples' do
context 'restricted signup domains' do
- it_behaves_like 'string of domains', :domain_whitelist
+ it_behaves_like 'string of domains', :domain_allowlist, :domain_allowlist
end
- context 'blacklisted signup domains' do
- it_behaves_like 'string of domains', :domain_blacklist
+ context 'denied signup domains' do
+ it_behaves_like 'string of domains', :domain_denylist, :domain_denylist
it 'sets multiple domain with file' do
- setting.domain_blacklist_file = File.open(Rails.root.join('spec/fixtures/', 'domain_blacklist.txt'))
- expect(setting.domain_blacklist).to contain_exactly('example.com', 'test.com', 'foo.bar')
+ setting.domain_denylist_file = File.open(Rails.root.join('spec/fixtures/', 'domain_denylist.txt'))
+ expect(setting.domain_denylist).to contain_exactly('example.com', 'test.com', 'foo.bar')
end
end
context 'outbound_local_requests_whitelist' do
- it_behaves_like 'string of domains', :outbound_local_requests_whitelist
+ it_behaves_like 'string of domains', :outbound_local_requests_allowlist, :outbound_local_requests_whitelist
- it 'clears outbound_local_requests_whitelist_arrays memoization' do
- setting.outbound_local_requests_whitelist_raw = 'example.com'
+ it 'clears outbound_local_requests_allowlist_arrays memoization' do
+ setting.outbound_local_requests_allowlist_raw = 'example.com'
- expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
+ expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly(
[], [an_object_having_attributes(domain: 'example.com')]
)
- setting.outbound_local_requests_whitelist_raw = 'gitlab.com'
- expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
+ setting.outbound_local_requests_allowlist_raw = 'gitlab.com'
+ expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly(
[], [an_object_having_attributes(domain: 'gitlab.com')]
)
end
end
- context 'outbound_local_requests_whitelist_arrays' do
+ context 'outbound_local_requests_allowlist_arrays' do
it 'separates the IPs and domains' do
setting.outbound_local_requests_whitelist = [
'192.168.1.1',
@@ -118,7 +118,7 @@ RSpec.shared_examples 'application settings examples' do
an_object_having_attributes(domain: 'example.com', port: 8080)
]
- expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
+ expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly(
ip_whitelist, domain_whitelist
)
end
@@ -139,10 +139,10 @@ RSpec.shared_examples 'application settings examples' do
)
end
- it 'clears outbound_local_requests_whitelist_arrays memoization' do
+ it 'clears outbound_local_requests_allowlist_arrays memoization' do
setting.outbound_local_requests_whitelist = ['example.com']
- expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
+ expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly(
[],
[an_object_having_attributes(domain: 'example.com')]
)
@@ -151,7 +151,7 @@ RSpec.shared_examples 'application settings examples' do
['example.com', 'gitlab.com']
)
- expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
+ expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly(
[],
[an_object_having_attributes(domain: 'example.com'), an_object_having_attributes(domain: 'gitlab.com')]
)
@@ -163,7 +163,7 @@ RSpec.shared_examples 'application settings examples' do
setting.add_to_outbound_local_requests_whitelist(['gitlab.com'])
expect(setting.outbound_local_requests_whitelist).to contain_exactly('gitlab.com')
- expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
+ expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly(
[], [an_object_having_attributes(domain: 'gitlab.com')]
)
end
@@ -171,7 +171,7 @@ RSpec.shared_examples 'application settings examples' do
it 'does not raise error with nil' do
setting.outbound_local_requests_whitelist = nil
- expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly([], [])
+ expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly([], [])
end
end
diff --git a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
index 62d56f2e86e..fe99b1cacd9 100644
--- a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
+++ b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
@@ -76,6 +76,26 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
end
end
+ describe 'supply of internal ids' do
+ let(:scope_value) { scope_attrs.each_value.first }
+ let(:method_name) { :"with_#{scope}_#{internal_id_attribute}_supply" }
+
+ it 'provides a persistent supply of IID values, sensitive to the current state' do
+ iid = rand(1..1000)
+ write_internal_id(iid)
+ instance.public_send(:"track_#{scope}_#{internal_id_attribute}!")
+
+ # Allocate 3 IID values
+ described_class.public_send(method_name, scope_value) do |supply|
+ 3.times { supply.next_value }
+ end
+
+ current_value = described_class.public_send(method_name, scope_value, &:current_value)
+
+ expect(current_value).to eq(iid + 3)
+ end
+ end
+
describe "#reset_scope_internal_id_attribute" do
it 'rewinds the allocated IID' do
expect { ensure_scope_attribute! }.not_to raise_error
diff --git a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
index 85a7c90ee42..51071ae47c3 100644
--- a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
+++ b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
@@ -25,4 +25,21 @@ RSpec.shared_examples 'cluster application core specs' do |application_name|
describe '.association_name' do
it { expect(described_class.association_name).to eq(:"application_#{subject.name}") }
end
+
+ describe '#helm_command_module' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:helm_major_version, :expected_helm_command_module) do
+ 2 | Gitlab::Kubernetes::Helm::V2
+ 3 | Gitlab::Kubernetes::Helm::V3
+ end
+
+ with_them do
+ subject { described_class.new(cluster: cluster).helm_command_module }
+
+ let(:cluster) { build(:cluster, helm_major_version: helm_major_version)}
+
+ it { is_expected.to eq(expected_helm_command_module) }
+ end
+ end
end
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 ac8022a4726..187a44ec3cd 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
@@ -6,7 +6,7 @@ RSpec.shared_examples 'cluster application helm specs' do |application_name|
describe '#uninstall_command' do
subject { application.uninstall_command }
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::DeleteCommand) }
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand) }
it 'has files' do
expect(subject.files).to eq(application.files)
diff --git a/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb b/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb
index 8092f87383d..17948d648cb 100644
--- a/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb
+++ b/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples 'cycle analytics stage' do
+RSpec.shared_examples 'value stream analytics stage' do
let(:valid_params) do
{
name: 'My Stage',
@@ -111,7 +111,7 @@ RSpec.shared_examples 'cycle analytics stage' do
end
end
-RSpec.shared_examples 'cycle analytics label based stage' do
+RSpec.shared_examples 'value stream analytics label based stage' do
context 'when creating label based event' do
context 'when the label id is not passed' do
it 'returns validation error when `start_event_label_id` is missing' do
diff --git a/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb
index 37ee2548dfe..17fd2b836d3 100644
--- a/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb
@@ -13,7 +13,7 @@ RSpec.shared_examples 'issuable time tracker' do |issuable_type|
end
it 'renders the sidebar component empty state' do
- page.within '.time-tracking-no-tracking-pane' do
+ page.within '[data-testid="noTrackingPane"]' do
expect(page).to have_content 'No estimate or time spent'
end
end
@@ -22,7 +22,7 @@ RSpec.shared_examples 'issuable time tracker' do |issuable_type|
submit_time('/estimate 3w 1d 1h')
wait_for_requests
- page.within '.time-tracking-estimate-only-pane' do
+ page.within '[data-testid="estimateOnlyPane"]' do
expect(page).to have_content '3w 1d 1h'
end
end
@@ -31,7 +31,7 @@ RSpec.shared_examples 'issuable time tracker' do |issuable_type|
submit_time('/spend 3w 1d 1h')
wait_for_requests
- page.within '.time-tracking-spend-only-pane' do
+ page.within '[data-testid="spentOnlyPane"]' do
expect(page).to have_content '3w 1d 1h'
end
end
@@ -41,7 +41,7 @@ RSpec.shared_examples 'issuable time tracker' do |issuable_type|
submit_time('/spend 3w 1d 1h')
wait_for_requests
- page.within '.time-tracking-comparison-pane' do
+ page.within '[data-testid="timeTrackingComparisonPane"]' do
expect(page).to have_content '3w 1d 1h'
end
end
diff --git a/spec/support/shared_examples/read_only_message_shared_examples.rb b/spec/support/shared_examples/read_only_message_shared_examples.rb
new file mode 100644
index 00000000000..4ae97ea7748
--- /dev/null
+++ b/spec/support/shared_examples/read_only_message_shared_examples.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'Read-only instance' do |message|
+ it 'shows read-only banner' do
+ visit root_dashboard_path
+
+ expect(page).to have_content(message)
+ end
+end
+
+RSpec.shared_examples 'Read-write instance' do |message|
+ it 'does not show read-only banner' do
+ visit root_dashboard_path
+
+ expect(page).not_to have_content(message)
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
index ec32cb4b2ff..f55043fe64f 100644
--- a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
@@ -20,7 +20,7 @@ RSpec.shared_context 'Debian repository shared context' do |object_type|
let(:source_package) { 'sample' }
let(:letter) { source_package[0..2] == 'lib' ? source_package[0..3] : source_package[0] }
let(:package_name) { 'libsample0' }
- let(:package_version) { '1.2.3~alpha2-1' }
+ let(:package_version) { '1.2.3~alpha2' }
let(:file_name) { "#{package_name}_#{package_version}_#{architecture}.deb" }
let(:method) { :get }
diff --git a/spec/support/shared_examples/requests/api/discussions_shared_examples.rb b/spec/support/shared_examples/requests/api/discussions_shared_examples.rb
index 6315c10b0c4..a12cb24a513 100644
--- a/spec/support/shared_examples/requests/api/discussions_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/discussions_shared_examples.rb
@@ -117,15 +117,10 @@ RSpec.shared_examples 'discussions API' do |parent_type, noteable_type, id_name,
expect(response).to have_gitlab_http_status(:unauthorized)
end
- it 'tracks a Notes::CreateService event' do
- expect(Gitlab::Tracking).to receive(:event) do |category, action, data|
- expect(category).to eq('Notes::CreateService')
- expect(action).to eq('execute')
- expect(data[:label]).to eq('note')
- expect(data[:value]).to be_an(Integer)
- end
-
+ it 'tracks a Notes::CreateService event', :snowplow do
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user), params: { body: 'hi!' }
+
+ expect_snowplow_event(category: 'Notes::CreateService', action: 'execute', label: 'note', value: anything)
end
context 'with notes_create_service_tracking feature flag disabled' do
@@ -133,10 +128,10 @@ RSpec.shared_examples 'discussions API' do |parent_type, noteable_type, id_name,
stub_feature_flags(notes_create_service_tracking: false)
end
- it 'does not track any events' do
- expect(Gitlab::Tracking).not_to receive(:event)
-
+ it 'does not track any events', :snowplow do
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions"), params: { body: 'hi!' }
+
+ expect_no_snowplow_event
end
end
diff --git a/spec/support/shared_examples/requests/api/graphql/read_only_instance_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/read_only_instance_shared_examples.rb
new file mode 100644
index 00000000000..be163d6aa0e
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/graphql/read_only_instance_shared_examples.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'graphql on a read-only GitLab instance' do
+ include GraphqlHelpers
+
+ context 'mutations' do
+ let(:current_user) { note.author }
+ let!(:note) { create(:note) }
+
+ let(:mutation) do
+ variables = {
+ id: GitlabSchema.id_from_object(note).to_s
+ }
+
+ graphql_mutation(:destroy_note, variables)
+ end
+
+ it 'disallows the query' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(json_response['errors'].first['message']).to eq(Mutations::BaseMutation::ERROR_MESSAGE)
+ end
+
+ it 'does not destroy the Note' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.not_to change { Note.count }
+ end
+ end
+
+ context 'read-only queries' do
+ let(:current_user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ it 'allows the query' do
+ query = graphql_query_for('project', 'fullPath' => project.full_path)
+
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data['project']).not_to be_nil
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/labels_api_shared_examples.rb b/spec/support/shared_examples/requests/api/labels_api_shared_examples.rb
new file mode 100644
index 00000000000..02e50b789cc
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/labels_api_shared_examples.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'fetches labels' do
+ it 'returns correct labels' do
+ request
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response).to all(match_schema('public_api/v4/labels/label'))
+ expect(json_response.size).to eq(expected_labels.size)
+ expect(json_response.map {|r| r['name'] }).to match_array(expected_labels)
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/multiple_and_scoped_issue_boards_shared_examples.rb b/spec/support/shared_examples/requests/api/multiple_and_scoped_issue_boards_shared_examples.rb
new file mode 100644
index 00000000000..54aa9d47dd8
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/multiple_and_scoped_issue_boards_shared_examples.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'multiple and scoped issue boards' do |route_definition|
+ let(:root_url) { route_definition.gsub(":id", board_parent.id.to_s) }
+
+ context 'multiple issue boards' do
+ before do
+ board_parent.add_reporter(user)
+ stub_licensed_features(multiple_group_issue_boards: true)
+ end
+
+ describe "POST #{route_definition}" do
+ it 'creates a board' do
+ post api(root_url, user), params: { name: "new board" }
+
+ expect(response).to have_gitlab_http_status(:created)
+
+ expect(response).to match_response_schema('public_api/v4/board', dir: "ee")
+ end
+ end
+
+ describe "PUT #{route_definition}/:board_id" do
+ let(:url) { "#{root_url}/#{board.id}" }
+
+ it 'updates a board' do
+ put api(url, user), params: { name: 'new name', weight: 4, labels: 'foo, bar' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ expect(response).to match_response_schema('public_api/v4/board', dir: "ee")
+
+ board.reload
+
+ expect(board.name).to eq('new name')
+ expect(board.weight).to eq(4)
+ expect(board.labels.map(&:title)).to contain_exactly('foo', 'bar')
+ end
+
+ it 'does not remove missing attributes from the board' do
+ expect { put api(url, user), params: { name: 'new name' } }
+ .to not_change { board.reload.assignee }
+ .and not_change { board.reload.milestone }
+ .and not_change { board.reload.weight }
+ .and not_change { board.reload.labels.map(&:title).sort }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/board', dir: "ee")
+ end
+
+ it 'allows removing optional attributes' do
+ put api(url, user), params: { name: 'new name', assignee_id: nil, milestone_id: nil, weight: nil, labels: nil }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/board', dir: "ee")
+
+ board.reload
+
+ expect(board.name).to eq('new name')
+ expect(board.assignee).to be_nil
+ expect(board.milestone).to be_nil
+ expect(board.weight).to be_nil
+ expect(board.labels).to be_empty
+ end
+ end
+
+ describe "DELETE #{route_definition}/:board_id" do
+ let(:url) { "#{root_url}/#{board.id}" }
+
+ it 'deletes a board' do
+ delete api(url, user)
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
+ end
+
+ context 'with the scoped_issue_board-feature available' do
+ it 'returns the milestone when the `scoped_issue_board` feature is enabled' do
+ stub_licensed_features(scoped_issue_board: true)
+
+ get api(root_url, user)
+
+ expect(json_response.first["milestone"]).not_to be_nil
+ end
+
+ it 'hides the milestone when the `scoped_issue_board` feature is disabled' do
+ stub_licensed_features(scoped_issue_board: false)
+
+ get api(root_url, user)
+
+ expect(json_response.first["milestone"]).to be_nil
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
new file mode 100644
index 00000000000..d3ad7aa0595
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
@@ -0,0 +1,270 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'handling get metadata requests' do
+ let_it_be(:package_dependency_link1) { create(:packages_dependency_link, package: package, dependency_type: :dependencies) }
+ let_it_be(:package_dependency_link2) { create(:packages_dependency_link, package: package, dependency_type: :devDependencies) }
+ let_it_be(:package_dependency_link3) { create(:packages_dependency_link, package: package, dependency_type: :bundleDependencies) }
+ let_it_be(:package_dependency_link4) { create(:packages_dependency_link, package: package, dependency_type: :peerDependencies) }
+
+ let(:params) { {} }
+ let(:headers) { {} }
+
+ subject { get(url, params: params, headers: headers) }
+
+ shared_examples 'returning the npm package info' do
+ it 'returns the package info' do
+ subject
+
+ expect_a_valid_package_response
+ end
+ end
+
+ shared_examples 'a package that requires auth' do
+ it 'denies request without oauth token' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'with oauth token' do
+ let(:params) { { access_token: token.token } }
+
+ it 'returns the package info with oauth token' do
+ subject
+
+ expect_a_valid_package_response
+ end
+ end
+
+ context 'with job token' do
+ let(:params) { { job_token: job.token } }
+
+ it 'returns the package info with running job token' do
+ subject
+
+ expect_a_valid_package_response
+ end
+
+ it 'denies request without running job token' do
+ job.update!(status: :success)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'with deploy token' do
+ let(:headers) { build_token_auth_header(deploy_token.token) }
+
+ it 'returns the package info with deploy token' do
+ subject
+
+ expect_a_valid_package_response
+ end
+ end
+ end
+
+ context 'a public project' do
+ it_behaves_like 'returning the npm package info'
+
+ context 'project path with a dot' do
+ before do
+ project.update!(path: 'foo.bar')
+ end
+
+ it_behaves_like 'returning the npm package info'
+ end
+
+ context 'with request forward disabled' do
+ before do
+ stub_application_setting(npm_package_requests_forwarding: false)
+ end
+
+ it_behaves_like 'returning the npm package info'
+
+ context 'with unknown package' do
+ let(:package_name) { 'unknown' }
+
+ it 'returns the proper response' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'with request forward enabled' do
+ before do
+ stub_application_setting(npm_package_requests_forwarding: true)
+ end
+
+ it_behaves_like 'returning the npm package info'
+
+ context 'with unknown package' do
+ let(:package_name) { 'unknown' }
+
+ it 'returns a redirect' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(response.headers['Location']).to eq('https://registry.npmjs.org/unknown')
+ end
+
+ it_behaves_like 'a gitlab tracking event', described_class.name, 'npm_request_forward'
+ end
+ end
+ end
+
+ context 'internal project' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ end
+
+ it_behaves_like 'a package that requires auth'
+ end
+
+ context 'private project' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ it_behaves_like 'a package that requires auth'
+
+ context 'with guest' do
+ let(:params) { { access_token: token.token } }
+
+ it 'denies request when not enough permissions' do
+ project.add_guest(user)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+
+ def expect_a_valid_package_response
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/json')
+ expect(response).to match_response_schema('public_api/v4/packages/npm_package')
+ expect(json_response['name']).to eq(package.name)
+ expect(json_response['versions'][package.version]).to match_schema('public_api/v4/packages/npm_package_version')
+ ::Packages::Npm::PackagePresenter::NPM_VALID_DEPENDENCY_TYPES.each do |dependency_type|
+ expect(json_response.dig('versions', package.version, dependency_type.to_s)).to be_any
+ end
+ expect(json_response['dist-tags']).to match_schema('public_api/v4/packages/npm_package_tags')
+ end
+end
+
+RSpec.shared_examples 'handling get dist tags requests' do
+ let_it_be(:package_tag1) { create(:packages_tag, package: package) }
+ let_it_be(:package_tag2) { create(:packages_tag, package: package) }
+
+ let(:params) { {} }
+
+ subject { get(url, params: params) }
+
+ context 'with public project' do
+ context 'with authenticated user' do
+ let(:params) { { private_token: personal_access_token.token } }
+
+ it_behaves_like 'returns package tags', :maintainer
+ it_behaves_like 'returns package tags', :developer
+ it_behaves_like 'returns package tags', :reporter
+ it_behaves_like 'returns package tags', :guest
+ end
+
+ context 'with unauthenticated user' do
+ it_behaves_like 'returns package tags', :no_type
+ end
+ end
+
+ context 'with private project' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ context 'with authenticated user' do
+ let(:params) { { private_token: personal_access_token.token } }
+
+ it_behaves_like 'returns package tags', :maintainer
+ it_behaves_like 'returns package tags', :developer
+ it_behaves_like 'returns package tags', :reporter
+ it_behaves_like 'rejects package tags access', :guest, :forbidden
+ end
+
+ context 'with unauthenticated user' do
+ it_behaves_like 'rejects package tags access', :no_type, :not_found
+ end
+ end
+end
+
+RSpec.shared_examples 'handling create dist tag requests' do
+ let_it_be(:tag_name) { 'test' }
+
+ let(:params) { {} }
+ let(:env) { {} }
+ let(:version) { package.version }
+
+ subject { put(url, env: env, params: params) }
+
+ context 'with public project' do
+ context 'with authenticated user' do
+ let(:params) { { private_token: personal_access_token.token } }
+ let(:env) { { 'api.request.body': version } }
+
+ it_behaves_like 'create package tag', :maintainer
+ it_behaves_like 'create package tag', :developer
+ it_behaves_like 'rejects package tags access', :reporter, :forbidden
+ it_behaves_like 'rejects package tags access', :guest, :forbidden
+ end
+
+ context 'with unauthenticated user' do
+ it_behaves_like 'rejects package tags access', :no_type, :unauthorized
+ end
+ end
+end
+
+RSpec.shared_examples 'handling delete dist tag requests' do
+ let_it_be(:package_tag) { create(:packages_tag, package: package) }
+
+ let(:params) { {} }
+ let(:tag_name) { package_tag.name }
+
+ subject { delete(url, params: params) }
+
+ context 'with public project' do
+ context 'with authenticated user' do
+ let(:params) { { private_token: personal_access_token.token } }
+
+ it_behaves_like 'delete package tag', :maintainer
+ it_behaves_like 'rejects package tags access', :developer, :forbidden
+ it_behaves_like 'rejects package tags access', :reporter, :forbidden
+ it_behaves_like 'rejects package tags access', :guest, :forbidden
+ end
+
+ context 'with unauthenticated user' do
+ it_behaves_like 'rejects package tags access', :no_type, :unauthorized
+ end
+ end
+
+ context 'with private project' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ context 'with authenticated user' do
+ let(:params) { { private_token: personal_access_token.token } }
+
+ it_behaves_like 'delete package tag', :maintainer
+ it_behaves_like 'rejects package tags access', :developer, :forbidden
+ it_behaves_like 'rejects package tags access', :reporter, :forbidden
+ it_behaves_like 'rejects package tags access', :guest, :forbidden
+ end
+
+ context 'with unauthenticated user' do
+ it_behaves_like 'rejects package tags access', :no_type, :unauthorized
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/packages_shared_examples.rb b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
index d730ed53109..3833604e304 100644
--- a/spec/support/shared_examples/requests/api/packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
@@ -128,9 +128,13 @@ RSpec.shared_examples 'job token for package uploads' do
end
RSpec.shared_examples 'a package tracking event' do |category, action|
- it "creates a gitlab tracking event #{action}" do
- expect(Gitlab::Tracking).to receive(:event).with(category, action, {})
+ before do
+ stub_feature_flags(collect_package_events: true)
+ end
+ it "creates a gitlab tracking event #{action}", :snowplow do
expect { subject }.to change { Packages::Event.count }.by(1)
+
+ expect_snowplow_event(category: category, action: action)
end
end
diff --git a/spec/support/shared_examples/requests/api/packages_tags_shared_examples.rb b/spec/support/shared_examples/requests/api/packages_tags_shared_examples.rb
index a371d380f47..2c203dc096e 100644
--- a/spec/support/shared_examples/requests/api/packages_tags_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/packages_tags_shared_examples.rb
@@ -40,7 +40,7 @@ RSpec.shared_examples 'returns package tags' do |user_type|
context 'with invalid package name' do
where(:package_name, :status) do
'%20' | :bad_request
- nil | :forbidden
+ nil | :not_found
end
with_them do
@@ -95,7 +95,7 @@ RSpec.shared_examples 'create package tag' do |user_type|
context 'with invalid package name' do
where(:package_name, :status) do
- 'unknown' | :forbidden
+ 'unknown' | :not_found
'' | :not_found
'%20' | :bad_request
end
@@ -160,7 +160,7 @@ RSpec.shared_examples 'delete package tag' do |user_type|
context 'with invalid package name' do
where(:package_name, :status) do
- 'unknown' | :forbidden
+ 'unknown' | :not_found
'' | :not_found
'%20' | :bad_request
end
diff --git a/spec/support/shared_examples/requests/api/tracking_shared_examples.rb b/spec/support/shared_examples/requests/api/tracking_shared_examples.rb
index 2e6feae3f98..826139635ed 100644
--- a/spec/support/shared_examples/requests/api/tracking_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/tracking_shared_examples.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
RSpec.shared_examples 'a gitlab tracking event' do |category, action|
- it "creates a gitlab tracking event #{action}" do
- expect(Gitlab::Tracking).to receive(:event).with(category, action, {})
-
+ it "creates a gitlab tracking event #{action}", :snowplow do
subject
+
+ expect_snowplow_event(category: category, action: action)
end
end
diff --git a/spec/support/shared_examples/requests/lfs_http_shared_examples.rb b/spec/support/shared_examples/requests/lfs_http_shared_examples.rb
index 48c5a5933e6..4ae77179527 100644
--- a/spec/support/shared_examples/requests/lfs_http_shared_examples.rb
+++ b/spec/support/shared_examples/requests/lfs_http_shared_examples.rb
@@ -2,42 +2,252 @@
RSpec.shared_examples 'LFS http 200 response' do
it_behaves_like 'LFS http expected response code and message' do
- let(:response_code) { 200 }
+ let(:response_code) { :ok }
+ end
+end
+
+RSpec.shared_examples 'LFS http 200 blob response' do
+ it_behaves_like 'LFS http expected response code and message' do
+ let(:response_code) { :ok }
+ let(:content_type) { Repositories::LfsApiController::LFS_TRANSFER_CONTENT_TYPE }
+ let(:response_headers) { { 'X-Sendfile' => lfs_object.file.path } }
+ end
+end
+
+RSpec.shared_examples 'LFS http 200 workhorse response' do
+ it_behaves_like 'LFS http expected response code and message' do
+ let(:response_code) { :ok }
+ let(:content_type) { Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE }
end
end
RSpec.shared_examples 'LFS http 401 response' do
it_behaves_like 'LFS http expected response code and message' do
- let(:response_code) { 401 }
+ let(:response_code) { :unauthorized }
+ let(:content_type) { 'text/plain' }
end
end
RSpec.shared_examples 'LFS http 403 response' do
it_behaves_like 'LFS http expected response code and message' do
- let(:response_code) { 403 }
+ let(:response_code) { :forbidden }
let(:message) { 'Access forbidden. Check your access level.' }
end
end
RSpec.shared_examples 'LFS http 501 response' do
it_behaves_like 'LFS http expected response code and message' do
- let(:response_code) { 501 }
+ let(:response_code) { :not_implemented }
let(:message) { 'Git LFS is not enabled on this GitLab server, contact your admin.' }
end
end
RSpec.shared_examples 'LFS http 404 response' do
it_behaves_like 'LFS http expected response code and message' do
- let(:response_code) { 404 }
+ let(:response_code) { :not_found }
end
end
RSpec.shared_examples 'LFS http expected response code and message' do
let(:response_code) { }
- let(:message) { }
+ let(:response_headers) { {} }
+ let(:content_type) { LfsRequest::CONTENT_TYPE }
+ let(:message) {}
- it 'responds with the expected response code and message' do
+ specify do
expect(response).to have_gitlab_http_status(response_code)
+ expect(response.headers.to_hash).to include(response_headers)
+ expect(response.media_type).to match(content_type)
expect(json_response['message']).to eq(message) if message
end
end
+
+RSpec.shared_examples 'LFS http requests' do
+ include LfsHttpHelpers
+
+ let(:authorize_guest) {}
+ let(:authorize_download) {}
+ let(:authorize_upload) {}
+
+ let(:lfs_object) { create(:lfs_object, :with_file) }
+ let(:sample_oid) { lfs_object.oid }
+
+ let(:authorization) { authorize_user }
+ let(:headers) do
+ {
+ 'Authorization' => authorization,
+ 'X-Sendfile-Type' => 'X-Sendfile'
+ }
+ end
+
+ let(:request_download) do
+ get objects_url(container, sample_oid), params: {}, headers: headers
+ end
+
+ let(:request_upload) do
+ post_lfs_json batch_url(container), upload_body(multiple_objects), headers
+ end
+
+ before do
+ stub_lfs_setting(enabled: true)
+ end
+
+ context 'when LFS is disabled globally' do
+ before do
+ stub_lfs_setting(enabled: false)
+ end
+
+ describe 'download request' do
+ before do
+ request_download
+ end
+
+ it_behaves_like 'LFS http 501 response'
+ end
+
+ describe 'upload request' do
+ before do
+ request_upload
+ end
+
+ it_behaves_like 'LFS http 501 response'
+ end
+ end
+
+ context 'unauthenticated' do
+ let(:headers) { {} }
+
+ describe 'download request' do
+ before do
+ request_download
+ end
+
+ it_behaves_like 'LFS http 401 response'
+ end
+
+ describe 'upload request' do
+ before do
+ request_upload
+ end
+
+ it_behaves_like 'LFS http 401 response'
+ end
+ end
+
+ context 'without access' do
+ describe 'download request' do
+ before do
+ request_download
+ end
+
+ it_behaves_like 'LFS http 404 response'
+ end
+
+ describe 'upload request' do
+ before do
+ request_upload
+ end
+
+ it_behaves_like 'LFS http 404 response'
+ end
+ end
+
+ context 'with guest access' do
+ before do
+ authorize_guest
+ end
+
+ describe 'download request' do
+ before do
+ request_download
+ end
+
+ it_behaves_like 'LFS http 404 response'
+ end
+
+ describe 'upload request' do
+ before do
+ request_upload
+ end
+
+ it_behaves_like 'LFS http 404 response'
+ end
+ end
+
+ context 'with download permission' do
+ before do
+ authorize_download
+ end
+
+ describe 'download request' do
+ before do
+ request_download
+ end
+
+ it_behaves_like 'LFS http 200 blob response'
+
+ context 'when container does not exist' do
+ def objects_url(*args)
+ super.sub(container.full_path, 'missing/path')
+ end
+
+ it_behaves_like 'LFS http 404 response'
+ end
+ end
+
+ describe 'upload request' do
+ before do
+ request_upload
+ end
+
+ it_behaves_like 'LFS http 403 response'
+ end
+ end
+
+ context 'with upload permission' do
+ before do
+ authorize_upload
+ end
+
+ describe 'upload request' do
+ before do
+ request_upload
+ end
+
+ it_behaves_like 'LFS http 200 response'
+ end
+ end
+
+ describe 'deprecated API' do
+ shared_examples 'deprecated request' do
+ before do
+ request
+ end
+
+ it_behaves_like 'LFS http expected response code and message' do
+ let(:response_code) { 501 }
+ let(:message) { 'Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.' }
+ end
+ end
+
+ context 'when fetching LFS object using deprecated API' do
+ subject(:request) do
+ get deprecated_objects_url(container, sample_oid), params: {}, headers: headers
+ end
+
+ it_behaves_like 'deprecated request'
+ end
+
+ context 'when handling LFS request using deprecated API' do
+ subject(:request) do
+ post_lfs_json deprecated_objects_url(container), nil, headers
+ end
+
+ it_behaves_like 'deprecated request'
+ end
+
+ def deprecated_objects_url(container, oid = nil)
+ File.join(["#{container.http_url_to_repo}/info/lfs/objects/", oid].compact)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
index 730df4dc5ab..d4ee68309ff 100644
--- a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
+++ b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
@@ -81,8 +81,15 @@ RSpec.shared_examples 'rate-limited token-authenticated requests' do
end
it 'logs RackAttack info into structured logs' do
- requests_per_period.times do
- make_request(request_args)
+ control_count = 0
+
+ requests_per_period.times do |i|
+ if i == 0
+ control_count = ActiveRecord::QueryRecorder.new { make_request(request_args) }.count
+ else
+ make_request(request_args)
+ end
+
expect(response).not_to have_gitlab_http_status(:too_many_requests)
end
@@ -93,13 +100,15 @@ RSpec.shared_examples 'rate-limited token-authenticated requests' do
request_method: request_method,
path: request_args.first,
user_id: user.id,
- username: user.username,
- throttle_type: throttle_types[throttle_setting_prefix]
+ 'meta.user' => user.username,
+ matched: throttle_types[throttle_setting_prefix]
}
expect(Gitlab::AuthLogger).to receive(:error).with(arguments).once
- expect_rejection { make_request(request_args) }
+ expect_rejection do
+ expect { make_request(request_args) }.not_to exceed_query_limit(control_count)
+ end
end
end
@@ -210,8 +219,15 @@ RSpec.shared_examples 'rate-limited web authenticated requests' do
end
it 'logs RackAttack info into structured logs' do
- requests_per_period.times do
- request_authenticated_web_url
+ control_count = 0
+
+ requests_per_period.times do |i|
+ if i == 0
+ control_count = ActiveRecord::QueryRecorder.new { request_authenticated_web_url }.count
+ else
+ request_authenticated_web_url
+ end
+
expect(response).not_to have_gitlab_http_status(:too_many_requests)
end
@@ -222,13 +238,12 @@ RSpec.shared_examples 'rate-limited web authenticated requests' do
request_method: request_method,
path: url_that_requires_authentication,
user_id: user.id,
- username: user.username,
- throttle_type: throttle_types[throttle_setting_prefix]
+ 'meta.user' => user.username,
+ matched: throttle_types[throttle_setting_prefix]
}
expect(Gitlab::AuthLogger).to receive(:error).with(arguments).once
-
- request_authenticated_web_url
+ expect { request_authenticated_web_url }.not_to exceed_query_limit(control_count)
end
end
diff --git a/spec/support/shared_examples/serializers/note_entity_shared_examples.rb b/spec/support/shared_examples/serializers/note_entity_shared_examples.rb
index a90a2dc3667..9af6ec45e49 100644
--- a/spec/support/shared_examples/serializers/note_entity_shared_examples.rb
+++ b/spec/support/shared_examples/serializers/note_entity_shared_examples.rb
@@ -5,8 +5,21 @@ RSpec.shared_examples 'note entity' do
context 'basic note' do
it 'exposes correct elements' do
- expect(subject).to include(:type, :author, :note, :note_html, :current_user, :discussion_id,
- :emoji_awardable, :award_emoji, :report_abuse_path, :attachment, :noteable_note_url, :resolvable)
+ expect(subject).to include(
+ :attachment,
+ :author,
+ :award_emoji,
+ :base_discussion,
+ :current_user,
+ :discussion_id,
+ :emoji_awardable,
+ :note,
+ :note_html,
+ :noteable_note_url,
+ :report_abuse_path,
+ :resolvable,
+ :type
+ )
end
it 'does not expose elements for specific notes cases' do
@@ -20,6 +33,39 @@ RSpec.shared_examples 'note entity' do
it 'does not expose web_url for author' do
expect(subject[:author]).not_to include(:web_url)
end
+
+ it 'exposes permission fields on current_user' do
+ expect(subject[:current_user]).to include(:can_edit, :can_award_emoji, :can_resolve, :can_resolve_discussion)
+ end
+
+ describe ':can_resolve_discussion' do
+ context 'discussion is resolvable' do
+ before do
+ expect(note.discussion).to receive(:resolvable?).and_return(true)
+ end
+
+ context 'user can resolve' do
+ it 'is true' do
+ expect(note.discussion).to receive(:can_resolve?).with(user).and_return(true)
+ expect(subject[:current_user][:can_resolve_discussion]).to be_truthy
+ end
+ end
+
+ context 'user cannot resolve' do
+ it 'is false' do
+ expect(note.discussion).to receive(:can_resolve?).with(user).and_return(false)
+ expect(subject[:current_user][:can_resolve_discussion]).to be_falsey
+ end
+ end
+ end
+
+ context 'discussion is not resolvable' do
+ it 'is false' do
+ expect(note.discussion).to receive(:resolvable?).and_return(false)
+ expect(subject[:current_user][:can_resolve_discussion]).to be_falsey
+ end
+ end
+ end
end
context 'when note was edited' do
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 1ae74979b7a..003705ca21c 100644
--- a/spec/support/shared_examples/services/alert_management_shared_examples.rb
+++ b/spec/support/shared_examples/services/alert_management_shared_examples.rb
@@ -8,11 +8,11 @@ RSpec.shared_examples 'creates an alert management alert' do
end
it 'executes the alert service hooks' do
- slack_service = create(:service, type: 'SlackService', project: project, alert_events: true, active: true)
+ expect_next_instance_of(AlertManagement::Alert) do |alert|
+ expect(alert).to receive(:execute_services)
+ end
subject
-
- expect(ProjectServiceWorker).to have_received(:perform_async).with(slack_service.id, an_instance_of(Hash))
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 5b95a5753a1..7b277d4bede 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
@@ -17,13 +17,13 @@ RSpec.shared_examples 'system note creation' do |update_params, note_text|
end
end
-RSpec.shared_examples 'draft notes creation' do |wip_action|
+RSpec.shared_examples 'draft notes creation' do |action|
subject { described_class.new(project, user).execute(issuable, old_labels: []) }
it 'creates Draft toggle and title change notes' do
expect { subject }.to change { Note.count }.from(0).to(2)
- expect(Note.first.note).to match("#{wip_action} as a **Work In Progress**")
+ expect(Note.first.note).to match("marked this merge request as **#{action}**")
expect(Note.second.note).to match('changed title')
end
end
diff --git a/spec/support/shared_examples/services/jira_import/user_mapper_services_shared_examples.rb b/spec/support/shared_examples/services/jira_import/user_mapper_services_shared_examples.rb
index 7fc7ff8a8de..cbe5c7d89db 100644
--- a/spec/support/shared_examples/services/jira_import/user_mapper_services_shared_examples.rb
+++ b/spec/support/shared_examples/services/jira_import/user_mapper_services_shared_examples.rb
@@ -3,7 +3,6 @@
RSpec.shared_examples 'mapping jira users' do
let(:client) { double }
- let_it_be(:project) { create(:project) }
let_it_be(:jira_service) { create(:jira_service, project: project, active: true) }
before do
@@ -11,7 +10,7 @@ RSpec.shared_examples 'mapping jira users' do
allow(client).to receive(:get).with(url).and_return(jira_users)
end
- subject { described_class.new(jira_service, start_at) }
+ subject { described_class.new(current_user, project, start_at) }
context 'jira_users is nil' do
let(:jira_users) { nil }
@@ -22,18 +21,27 @@ RSpec.shared_examples 'mapping jira users' do
end
context 'when jira_users is present' do
- # TODO: now we only create an array in a proper format
- # mapping is tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/219023
let(:mapped_users) do
[
- { jira_account_id: 'abcd', jira_display_name: 'user1', jira_email: nil, gitlab_id: nil, gitlab_username: nil, gitlab_name: nil },
- { jira_account_id: 'efg', jira_display_name: nil, jira_email: nil, gitlab_id: nil, gitlab_username: nil, gitlab_name: nil },
- { jira_account_id: 'hij', jira_display_name: 'user3', jira_email: 'user3@example.com', gitlab_id: nil, gitlab_username: nil, gitlab_name: nil }
+ { jira_account_id: 'abcd', jira_display_name: 'User-Name1', jira_email: nil, gitlab_id: user_1.id },
+ { jira_account_id: 'efg', jira_display_name: 'username-2', jira_email: nil, gitlab_id: user_2.id },
+ { jira_account_id: 'hij', jira_display_name: nil, jira_email: nil, gitlab_id: nil },
+ { jira_account_id: '123', jira_display_name: 'user-4', jira_email: 'user-4@example.com', gitlab_id: user_4.id },
+ { jira_account_id: '456', jira_display_name: 'username5foo', jira_email: 'user-5@example.com', gitlab_id: nil },
+ { jira_account_id: '789', jira_display_name: 'user-6', jira_email: 'user-6@example.com', gitlab_id: nil },
+ { jira_account_id: 'xyz', jira_display_name: 'username-7', jira_email: 'user-7@example.com', gitlab_id: nil },
+ { jira_account_id: 'vhk', jira_display_name: 'user-8', jira_email: 'user8_email@example.com', gitlab_id: user_8.id },
+ { jira_account_id: 'uji', jira_display_name: 'user-9', jira_email: 'uji@example.com', gitlab_id: user_1.id }
]
end
it 'returns users mapped to Gitlab' do
expect(subject.execute).to eq(mapped_users)
end
+
+ # 1 query for getting matched users, 3 queries for MembersFinder
+ it 'runs only 4 queries' do
+ expect { subject }.not_to exceed_query_limit(4)
+ 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 65f4b3b5513..7987f2c296b 100644
--- a/spec/support/shared_examples/services/packages_shared_examples.rb
+++ b/spec/support/shared_examples/services/packages_shared_examples.rb
@@ -8,8 +8,8 @@ RSpec.shared_examples 'assigns build to package' do
it 'assigns the pipeline to the package' do
package = subject
- expect(package.build_info).to be_present
- expect(package.build_info.pipeline).to eq job.pipeline
+ expect(package.original_build_info).to be_present
+ expect(package.original_build_info.pipeline).to eq job.pipeline
end
end
end
diff --git a/spec/support/shared_examples/services/pages_size_limit_shared_examples.rb b/spec/support/shared_examples/services/pages_size_limit_shared_examples.rb
index 15bf0d3698a..d9e906ebb75 100644
--- a/spec/support/shared_examples/services/pages_size_limit_shared_examples.rb
+++ b/spec/support/shared_examples/services/pages_size_limit_shared_examples.rb
@@ -4,6 +4,7 @@ RSpec.shared_examples 'pages size limit is' do |size_limit|
context "when size is below the limit" do
before do
allow(metadata).to receive(:total_size).and_return(size_limit - 1.megabyte)
+ allow(metadata).to receive(:entries).and_return([])
end
it 'updates pages correctly' do
@@ -17,6 +18,7 @@ RSpec.shared_examples 'pages size limit is' do |size_limit|
context "when size is above the limit" do
before do
allow(metadata).to receive(:total_size).and_return(size_limit + 1.megabyte)
+ allow(metadata).to receive(:entries).and_return([])
end
it 'limits the maximum size of gitlab pages' do
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
deleted file mode 100644
index 5a9a3dfc2d2..00000000000
--- a/spec/support/shared_examples/uploaders/workers/object_storage/migrate_uploads_shared_examples.rb
+++ /dev/null
@@ -1,120 +0,0 @@
-# frozen_string_literal: true
-
-# Expects the calling spec to define:
-# - model_class
-# - mounted_as
-# - to_store
-RSpec.shared_examples 'uploads migration worker' do
- def perform(uploads, store = nil)
- described_class.new.perform(uploads.ids, model_class.to_s, mounted_as, store || to_store)
- rescue ObjectStorage::MigrateUploadsWorker::Report::MigrationFailures
- # swallow
- end
-
- describe '.enqueue!' do
- def enqueue!
- described_class.enqueue!(uploads, model_class, mounted_as, to_store)
- end
-
- it 'is guarded by .sanity_check!' do
- expect(described_class).to receive(:perform_async)
- expect(described_class).to receive(:sanity_check!)
-
- enqueue!
- end
-
- context 'sanity_check! fails' do
- include_context 'sanity_check! fails'
-
- it 'does not enqueue a job' do
- expect(described_class).not_to receive(:perform_async)
-
- expect { enqueue! }.to raise_error(described_class::SanityCheckError)
- end
- end
- end
-
- describe '.sanity_check!' do
- shared_examples 'raises a SanityCheckError' do |expected_message|
- let(:mount_point) { nil }
-
- it do
- expect { described_class.sanity_check!(uploads, model_class, mount_point) }
- .to raise_error(described_class::SanityCheckError).with_message(expected_message)
- end
- end
-
- context 'uploader types mismatch' do
- let!(:outlier) { create(:upload, uploader: 'GitlabUploader') }
-
- include_examples 'raises a SanityCheckError', /Multiple uploaders found/
- end
-
- context 'mount point not found' do
- include_examples 'raises a SanityCheckError', /Mount point [a-z:]+ not found in/ do
- let(:mount_point) { :potato }
- end
- end
- end
-
- describe '#perform' do
- shared_examples 'outputs correctly' do |success: 0, failures: 0|
- total = success + failures
-
- if success > 0
- it 'outputs the reports' do
- expect(Gitlab::AppLogger).to receive(:info).with(%r{Migrated #{success}/#{total} files})
-
- perform(uploads)
- end
- end
-
- if failures > 0
- it 'outputs upload failures' do
- expect(Gitlab::AppLogger).to receive(:warn).with(/Error .* I am a teapot/)
-
- perform(uploads)
- end
- end
- end
-
- it_behaves_like 'outputs correctly', success: 10
-
- it 'migrates files to remote storage' do
- perform(uploads)
-
- expect(Upload.where(store: ObjectStorage::Store::LOCAL).count).to eq(0)
- end
-
- context 'reversed' do
- let(:to_store) { ObjectStorage::Store::LOCAL }
-
- before do
- perform(uploads, ObjectStorage::Store::REMOTE)
- end
-
- it 'migrates files to local storage' do
- expect(Upload.where(store: ObjectStorage::Store::REMOTE).count).to eq(10)
-
- perform(uploads)
-
- expect(Upload.where(store: ObjectStorage::Store::LOCAL).count).to eq(10)
- end
- end
-
- context 'migration is unsuccessful' do
- before do
- allow_any_instance_of(ObjectStorage::Concern)
- .to receive(:migrate!).and_raise(CarrierWave::UploadError, 'I am a teapot.')
- end
-
- it_behaves_like 'outputs correctly', failures: 10
- end
- end
-end
-
-RSpec.shared_context 'sanity_check! fails' do
- before do
- expect(described_class).to receive(:sanity_check!).and_raise(described_class::SanityCheckError)
- end
-end
diff --git a/spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb b/spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb
index 50879969e90..37f44f98cda 100644
--- a/spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb
+++ b/spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb
@@ -1,40 +1,32 @@
# frozen_string_literal: true
-# Expects `worker_class` to be defined
+# Expects `subject` to be a job/worker instance
RSpec.shared_examples 'reenqueuer' do
- subject(:job) { worker_class.new }
-
before do
- allow(job).to receive(:sleep) # faster tests
+ allow(subject).to receive(:sleep) # faster tests
end
it 'implements lease_timeout' do
- expect(job.lease_timeout).to be_a(ActiveSupport::Duration)
+ expect(subject.lease_timeout).to be_a(ActiveSupport::Duration)
end
describe '#perform' do
it 'tries to obtain a lease' do
- expect_to_obtain_exclusive_lease(job.lease_key)
+ expect_to_obtain_exclusive_lease(subject.lease_key)
- job.perform
+ subject.perform
end
end
end
-# Example usage:
-#
-# it_behaves_like 'it is rate limited to 1 call per', 5.seconds do
-# subject { described_class.new }
-# let(:rate_limited_method) { subject.perform }
-# end
-#
-RSpec.shared_examples 'it is rate limited to 1 call per' do |minimum_duration|
+# Expects `subject` to be a job/worker instance
+RSpec.shared_examples '#perform is rate limited to 1 call per' do |minimum_duration|
before do
# Allow Timecop freeze and travel without the block form
Timecop.safe_mode = false
Timecop.freeze
- time_travel_during_rate_limited_method(actual_duration)
+ time_travel_during_perform(actual_duration)
end
after do
@@ -48,7 +40,7 @@ RSpec.shared_examples 'it is rate limited to 1 call per' do |minimum_duration|
it 'sleeps exactly the minimum duration' do
expect(subject).to receive(:sleep).with(a_value_within(0.01).of(minimum_duration))
- rate_limited_method
+ subject.perform
end
end
@@ -58,7 +50,7 @@ RSpec.shared_examples 'it is rate limited to 1 call per' do |minimum_duration|
it 'sleeps 90% of minimum duration' do
expect(subject).to receive(:sleep).with(a_value_within(0.01).of(0.9 * minimum_duration))
- rate_limited_method
+ subject.perform
end
end
@@ -68,7 +60,7 @@ RSpec.shared_examples 'it is rate limited to 1 call per' do |minimum_duration|
it 'sleeps 10% of minimum duration' do
expect(subject).to receive(:sleep).with(a_value_within(0.01).of(0.1 * minimum_duration))
- rate_limited_method
+ subject.perform
end
end
@@ -78,7 +70,7 @@ RSpec.shared_examples 'it is rate limited to 1 call per' do |minimum_duration|
it 'does not sleep' do
expect(subject).not_to receive(:sleep)
- rate_limited_method
+ subject.perform
end
end
@@ -88,7 +80,7 @@ RSpec.shared_examples 'it is rate limited to 1 call per' do |minimum_duration|
it 'does not sleep' do
expect(subject).not_to receive(:sleep)
- rate_limited_method
+ subject.perform
end
end
@@ -98,11 +90,11 @@ RSpec.shared_examples 'it is rate limited to 1 call per' do |minimum_duration|
it 'does not sleep' do
expect(subject).not_to receive(:sleep)
- rate_limited_method
+ subject.perform
end
end
- def time_travel_during_rate_limited_method(actual_duration)
+ def time_travel_during_perform(actual_duration)
# Save the original implementation of ensure_minimum_duration
original_ensure_minimum_duration = subject.method(:ensure_minimum_duration)
diff --git a/spec/support/snowplow.rb b/spec/support/snowplow.rb
index 58812b8f4e6..b67fa96fab8 100644
--- a/spec/support/snowplow.rb
+++ b/spec/support/snowplow.rb
@@ -1,22 +1,24 @@
# frozen_string_literal: true
RSpec.configure do |config|
+ config.include SnowplowHelpers, :snowplow
+
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)
+ allow_any_instance_of(Gitlab::Tracking::Destinations::Snowplow)
.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
+ allow(Gitlab::Tracking).to receive(:event).and_call_original # rubocop:disable RSpec/ExpectGitlabTracking
end
config.after(:each, :snowplow) do
- Gitlab::Tracking.send(:snowplow).flush
+ Gitlab::Tracking.send(:snowplow).send(:tracker).flush
end
end
diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb
index c59370a7a32..efc983d526f 100644
--- a/spec/tasks/gitlab/gitaly_rake_spec.rb
+++ b/spec/tasks/gitlab/gitaly_rake_spec.rb
@@ -89,7 +89,7 @@ RSpec.describe 'gitlab:gitaly namespace rake task' do
let(:command) do
%W[make
BUNDLE_FLAGS=--no-deployment
- BUNDLE_PATH=#{Bundler.bundle_path}]
+ GEM_HOME=#{Bundler.bundle_path}]
end
before do
diff --git a/spec/tasks/gitlab/packages/events_rake_spec.rb b/spec/tasks/gitlab/packages/events_rake_spec.rb
new file mode 100644
index 00000000000..ac28f9b5fc2
--- /dev/null
+++ b/spec/tasks/gitlab/packages/events_rake_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'rake_helper'
+
+RSpec.describe 'gitlab:packages:events namespace rake task' do
+ before :all do
+ Rake.application.rake_require 'tasks/gitlab/packages/events'
+ end
+
+ describe 'generate' do
+ subject do
+ file = double('file')
+ yml_file = nil
+
+ allow(file).to receive(:<<) { |contents| yml_file = contents }
+ allow(File).to receive(:open).and_yield(file)
+
+ run_rake_task('gitlab:packages:events:generate')
+
+ YAML.safe_load(yml_file)
+ end
+
+ it 'excludes guest events' do
+ expect(subject.find { |event| event['name'].include?("guest") }).to be_nil
+ end
+
+ ::Packages::Event::EVENT_SCOPES.keys.each do |event_scope|
+ it "includes includes `#{event_scope}` scope" do
+ expect(subject.find { |event| event['name'].include?(event_scope) }).not_to be_nil
+ end
+ end
+
+ it 'excludes some event types' do
+ expect(subject.find { |event| event['name'].include?("search_package") }).to be_nil
+ expect(subject.find { |event| event['name'].include?("list_package") }).to be_nil
+ end
+ end
+end
diff --git a/spec/tooling/lib/tooling/crystalball/coverage_lines_execution_detector_spec.rb b/spec/tooling/lib/tooling/crystalball/coverage_lines_execution_detector_spec.rb
new file mode 100644
index 00000000000..6b7373cb3c7
--- /dev/null
+++ b/spec/tooling/lib/tooling/crystalball/coverage_lines_execution_detector_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require_relative '../../../../../tooling/lib/tooling/crystalball/coverage_lines_execution_detector'
+
+RSpec.describe Tooling::Crystalball::CoverageLinesExecutionDetector do
+ subject(:detector) { described_class.new(root, exclude_prefixes: %w[vendor/ruby]) }
+
+ let(:root) { '/tmp' }
+ let(:before_map) { { path => { lines: [0, 2, nil] } } }
+ let(:after_map) { { path => { lines: [0, 3, nil] } } }
+ let(:path) { '/tmp/file.rb' }
+
+ describe '#detect' do
+ subject { detector.detect(before_map, after_map) }
+
+ it { is_expected.to eq(%w[file.rb]) }
+
+ context 'with no changes' do
+ let(:after_map) { { path => { lines: [0, 2, nil] } } }
+
+ it { is_expected.to eq([]) }
+ end
+
+ context 'with previously uncovered file' do
+ let(:before_map) { {} }
+
+ it { is_expected.to eq(%w[file.rb]) }
+ end
+
+ context 'with path outside of root' do
+ let(:path) { '/abc/file.rb' }
+
+ it { is_expected.to eq([]) }
+ end
+
+ context 'with path in excluded prefix' do
+ let(:path) { '/tmp/vendor/ruby/dependency.rb' }
+
+ it { is_expected.to eq([]) }
+ end
+ end
+end
diff --git a/spec/tooling/lib/tooling/crystalball/coverage_lines_strategy_spec.rb b/spec/tooling/lib/tooling/crystalball/coverage_lines_strategy_spec.rb
new file mode 100644
index 00000000000..fd8fc4114a1
--- /dev/null
+++ b/spec/tooling/lib/tooling/crystalball/coverage_lines_strategy_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative '../../../../../tooling/lib/tooling/crystalball/coverage_lines_strategy'
+
+RSpec.describe Tooling::Crystalball::CoverageLinesStrategy do
+ subject { described_class.new(execution_detector) }
+
+ let(:execution_detector) { instance_double('Tooling::Crystalball::CoverageLinesExecutionDetector') }
+
+ describe '#after_register' do
+ it 'starts coverage' do
+ expect(Coverage).to receive(:start).with(lines: true)
+ subject.after_register
+ end
+ end
+end
diff --git a/spec/tooling/lib/tooling/test_file_finder_spec.rb b/spec/tooling/lib/tooling/test_file_finder_spec.rb
index 64b55b9b1d6..683bc647b8a 100644
--- a/spec/tooling/lib/tooling/test_file_finder_spec.rb
+++ b/spec/tooling/lib/tooling/test_file_finder_spec.rb
@@ -63,14 +63,6 @@ RSpec.describe Tooling::TestFileFinder do
end
end
- context 'when given a lib file in ee/' do
- let(:file) { 'ee/lib/flipper_session.rb' }
-
- it 'returns the matching ee/ lib test file' do
- expect(subject.test_files).to contain_exactly('ee/spec/lib/flipper_session_spec.rb')
- end
- end
-
context 'when given a test file in ee/' do
let(:file) { 'ee/spec/models/container_registry/event_spec.rb' }
diff --git a/spec/tooling/lib/tooling/test_map_generator_spec.rb b/spec/tooling/lib/tooling/test_map_generator_spec.rb
new file mode 100644
index 00000000000..7f3b2807162
--- /dev/null
+++ b/spec/tooling/lib/tooling/test_map_generator_spec.rb
@@ -0,0 +1,109 @@
+# frozen_string_literal: true
+
+require_relative '../../../../tooling/lib/tooling/test_map_generator'
+
+RSpec.describe Tooling::TestMapGenerator do
+ subject { described_class.new }
+
+ describe '#parse' do
+ let(:yaml1) do
+ <<~YAML
+ ---
+ :type: Crystalball::ExecutionMap
+ :commit: a7d57d333042f3b0334b2f8a282354eef7365976
+ :timestamp: 1602668405
+ :version:
+ ---
+ "./spec/factories_spec.rb[1]":
+ - lib/gitlab/current_settings.rb
+ - lib/feature.rb
+ - lib/gitlab/marginalia.rb
+ YAML
+ end
+
+ let(:yaml2) do
+ <<~YAML
+ ---
+ :type: Crystalball::ExecutionMap
+ :commit: 74056e8d9cf3773f43faa1cf5416f8779c8284c8
+ :timestamp: 1602671965
+ :version:
+ ---
+ "./spec/models/project_spec.rb[1]":
+ - lib/gitlab/current_settings.rb
+ - lib/feature.rb
+ - lib/gitlab/marginalia.rb
+ YAML
+ end
+
+ let(:pathname) { instance_double(Pathname) }
+
+ before do
+ allow(File).to receive(:read).with('yaml1.yml').and_return(yaml1)
+ allow(File).to receive(:read).with('yaml2.yml').and_return(yaml2)
+ end
+
+ context 'with single yaml' do
+ let(:expected_mapping) do
+ {
+ 'lib/gitlab/current_settings.rb' => [
+ './spec/factories_spec.rb'
+ ],
+ 'lib/feature.rb' => [
+ './spec/factories_spec.rb'
+ ],
+ 'lib/gitlab/marginalia.rb' => [
+ './spec/factories_spec.rb'
+ ]
+ }
+ end
+
+ it 'parses crystalball data into test mapping' do
+ subject.parse('yaml1.yml')
+
+ expect(subject.mapping.keys).to match_array(expected_mapping.keys)
+ end
+
+ it 'stores test files without example uid' do
+ subject.parse('yaml1.yml')
+
+ expected_mapping.each do |file, tests|
+ expect(subject.mapping[file]).to match_array(tests)
+ end
+ end
+ end
+
+ context 'with multiple yamls' do
+ let(:expected_mapping) do
+ {
+ 'lib/gitlab/current_settings.rb' => [
+ './spec/factories_spec.rb',
+ './spec/models/project_spec.rb'
+ ],
+ 'lib/feature.rb' => [
+ './spec/factories_spec.rb',
+ './spec/models/project_spec.rb'
+ ],
+ 'lib/gitlab/marginalia.rb' => [
+ './spec/factories_spec.rb',
+ './spec/models/project_spec.rb'
+ ]
+ }
+ end
+
+ it 'parses crystalball data into test mapping' do
+ subject.parse(%w[yaml1.yml yaml2.yml])
+
+ expect(subject.mapping.keys).to match_array(expected_mapping.keys)
+ end
+
+ it 'stores test files without example uid' do
+ subject.parse(%w[yaml1.yml yaml2.yml])
+
+ expected_mapping.each do |file, tests|
+ expect(subject.mapping[file]).to match_array(tests)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/tooling/lib/tooling/test_map_packer_spec.rb b/spec/tooling/lib/tooling/test_map_packer_spec.rb
new file mode 100644
index 00000000000..233134d2524
--- /dev/null
+++ b/spec/tooling/lib/tooling/test_map_packer_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require_relative '../../../../tooling/lib/tooling/test_map_packer'
+
+RSpec.describe Tooling::TestMapPacker do
+ subject { described_class.new }
+
+ let(:map) do
+ {
+ 'file1.rb' => [
+ './a/b/c/test_1.rb',
+ './a/b/test_2.rb',
+ './a/b/test_3.rb',
+ './a/test_4.rb',
+ './test_5.rb'
+ ],
+ 'file2.rb' => [
+ './a/b/c/test_1.rb',
+ './a/test_4.rb',
+ './test_5.rb'
+ ]
+ }
+ end
+
+ let(:compact_map) do
+ {
+ 'file1.rb' => {
+ '.' => {
+ 'a' => {
+ 'b' => {
+ 'c' => {
+ 'test_1.rb' => 1
+ },
+ 'test_2.rb' => 1,
+ 'test_3.rb' => 1
+ },
+ 'test_4.rb' => 1
+ },
+ 'test_5.rb' => 1
+ }
+ },
+ 'file2.rb' => {
+ '.' => {
+ 'a' => {
+ 'b' => {
+ 'c' => {
+ 'test_1.rb' => 1
+ }
+ },
+ 'test_4.rb' => 1
+ },
+ 'test_5.rb' => 1
+ }
+ }
+ }
+ end
+
+ describe '#pack' do
+ it 'compacts list of test files into a prefix tree' do
+ expect(subject.pack(map)).to eq(compact_map)
+ end
+
+ it 'does nothing to empty hash' do
+ expect(subject.pack({})).to eq({})
+ end
+ end
+
+ describe '#unpack' do
+ it 'unpack prefix tree into list of test files' do
+ expect(subject.unpack(compact_map)).to eq(map)
+ end
+
+ it 'does nothing to empty hash' do
+ expect(subject.unpack({})).to eq({})
+ end
+ end
+end
diff --git a/spec/uploaders/dependency_proxy/file_uploader_spec.rb b/spec/uploaders/dependency_proxy/file_uploader_spec.rb
new file mode 100644
index 00000000000..724a9c42f47
--- /dev/null
+++ b/spec/uploaders/dependency_proxy/file_uploader_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe DependencyProxy::FileUploader do
+ let(:blob) { create(:dependency_proxy_blob) }
+ let(:uploader) { described_class.new(blob, :file) }
+ let(:path) { Gitlab.config.dependency_proxy.storage_path }
+
+ subject { uploader }
+
+ it_behaves_like "builds correct paths",
+ store_dir: %r[\h{2}/\h{2}],
+ cache_dir: %r[/dependency_proxy/tmp/cache],
+ work_dir: %r[/dependency_proxy/tmp/work]
+
+ context 'object store is remote' do
+ before do
+ stub_dependency_proxy_object_storage
+ end
+
+ include_context 'with storage', described_class::Store::REMOTE
+
+ it_behaves_like "builds correct paths",
+ store_dir: %r[\h{2}/\h{2}]
+ end
+end
diff --git a/spec/uploaders/gitlab_uploader_spec.rb b/spec/uploaders/gitlab_uploader_spec.rb
index 72845b47a53..4e661e458ad 100644
--- a/spec/uploaders/gitlab_uploader_spec.rb
+++ b/spec/uploaders/gitlab_uploader_spec.rb
@@ -141,5 +141,23 @@ RSpec.describe GitlabUploader do
end
end
end
+
+ describe '#url_or_file_path' do
+ let(:options) { { expire_at: 1.day.from_now } }
+
+ it 'returns url when in remote storage' do
+ expect(subject).to receive(:file_storage?).and_return(false)
+ expect(subject).to receive(:url).with(options).and_return("http://example.com")
+
+ expect(subject.url_or_file_path(options)).to eq("http://example.com")
+ end
+
+ it 'returns url when in remote storage' do
+ expect(subject).to receive(:file_storage?).and_return(true)
+ expect(subject).to receive(:path).and_return("/tmp/file")
+
+ expect(subject.url_or_file_path(options)).to eq("file:///tmp/file")
+ end
+ end
end
end
diff --git a/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb b/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
index ef5459ce788..fd01a18e810 100644
--- a/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
+++ b/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
@@ -13,8 +13,103 @@ RSpec.describe ObjectStorage::MigrateUploadsWorker do
# swallow
end
+ # Expects the calling spec to define:
+ # - model_class
+ # - mounted_as
+ # - to_store
+ RSpec.shared_examples 'uploads migration worker' do
+ describe '.enqueue!' do
+ def enqueue!
+ described_class.enqueue!(uploads, model_class, mounted_as, to_store)
+ end
+
+ it 'is guarded by .sanity_check!' do
+ expect(described_class).to receive(:perform_async)
+ expect(described_class).to receive(:sanity_check!)
+
+ enqueue!
+ end
+
+ context 'sanity_check! fails' do
+ before do
+ expect(described_class).to receive(:sanity_check!).and_raise(described_class::SanityCheckError)
+ end
+
+ it 'does not enqueue a job' do
+ expect(described_class).not_to receive(:perform_async)
+
+ expect { enqueue! }.to raise_error(described_class::SanityCheckError)
+ end
+ end
+ end
+
+ describe '.sanity_check!' do
+ shared_examples 'raises a SanityCheckError' do |expected_message|
+ let(:mount_point) { nil }
+
+ it do
+ expect { described_class.sanity_check!(uploads, model_class, mount_point) }
+ .to raise_error(described_class::SanityCheckError).with_message(expected_message)
+ end
+ end
+
+ context 'uploader types mismatch' do
+ let!(:outlier) { create(:upload, uploader: 'GitlabUploader') }
+
+ include_examples 'raises a SanityCheckError', /Multiple uploaders found/
+ end
+
+ context 'mount point not found' do
+ include_examples 'raises a SanityCheckError', /Mount point [a-z:]+ not found in/ do
+ let(:mount_point) { :potato }
+ end
+ end
+ end
+
+ describe '#perform' do
+ it 'migrates files to remote storage' do
+ expect(Gitlab::AppLogger).to receive(:info).with(%r{Migrated 1/1 files})
+
+ perform(uploads)
+
+ expect(Upload.where(store: ObjectStorage::Store::LOCAL).count).to eq(0)
+ end
+
+ context 'reversed' do
+ let(:to_store) { ObjectStorage::Store::LOCAL }
+
+ before do
+ perform(uploads, ObjectStorage::Store::REMOTE)
+ end
+
+ it 'migrates files to local storage' do
+ expect(Upload.where(store: ObjectStorage::Store::REMOTE).count).to eq(1)
+
+ perform(uploads)
+
+ expect(Upload.where(store: ObjectStorage::Store::LOCAL).count).to eq(1)
+ end
+ end
+
+ context 'migration is unsuccessful' do
+ before do
+ allow_any_instance_of(ObjectStorage::Concern)
+ .to receive(:migrate!).and_raise(CarrierWave::UploadError, 'I am a teapot.')
+ end
+
+ it 'does not migrate files to remote storage' do
+ expect(Gitlab::AppLogger).to receive(:warn).with(/Error .* I am a teapot/)
+
+ perform(uploads)
+
+ expect(Upload.where(store: ObjectStorage::Store::LOCAL).count).to eq(1)
+ end
+ end
+ end
+ end
+
context "for AvatarUploader" do
- let!(:projects) { create_list(:project, 10, :with_avatar) }
+ let!(:project_with_avatar) { create(:project, :with_avatar) }
let(:mounted_as) { :avatar }
before do
@@ -27,16 +122,15 @@ RSpec.describe ObjectStorage::MigrateUploadsWorker do
it "to N*5" do
query_count = ActiveRecord::QueryRecorder.new { perform(uploads) }
- more_projects = create_list(:project, 3, :with_avatar)
+ create(:project, :with_avatar)
- expected_queries_per_migration = 5 * more_projects.count
- expect { perform(Upload.all) }.not_to exceed_query_limit(query_count).with_threshold(expected_queries_per_migration)
+ expect { perform(Upload.all) }.not_to exceed_query_limit(query_count).with_threshold(5)
end
end
end
context "for FileUploader" do
- let!(:projects) { create_list(:project, 10) }
+ let!(:project_with_file) { create(:project) }
let(:secret) { SecureRandom.hex }
let(:mounted_as) { nil }
@@ -48,7 +142,7 @@ RSpec.describe ObjectStorage::MigrateUploadsWorker do
before do
stub_uploads_object_storage(FileUploader)
- projects.map(&method(:upload_file))
+ upload_file(project_with_file)
end
it_behaves_like "uploads migration worker"
@@ -57,18 +151,16 @@ RSpec.describe ObjectStorage::MigrateUploadsWorker do
it "to N*5" do
query_count = ActiveRecord::QueryRecorder.new { perform(uploads) }
- more_projects = create_list(:project, 3)
- more_projects.map(&method(:upload_file))
+ upload_file(create(:project))
- expected_queries_per_migration = 5 * more_projects.count
- expect { perform(Upload.all) }.not_to exceed_query_limit(query_count).with_threshold(expected_queries_per_migration)
+ expect { perform(Upload.all) }.not_to exceed_query_limit(query_count).with_threshold(5)
end
end
end
context 'for DesignManagement::DesignV432x230Uploader' do
let(:model_class) { DesignManagement::Action }
- let!(:design_actions) { create_list(:design_action, 10, :with_image_v432x230) }
+ let!(:design_action) { create(:design_action, :with_image_v432x230) }
let(:mounted_as) { :image_v432x230 }
before do
diff --git a/spec/validators/rsa_key_validator_spec.rb b/spec/validators/rsa_key_validator_spec.rb
new file mode 100644
index 00000000000..b4e74ec5605
--- /dev/null
+++ b/spec/validators/rsa_key_validator_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe RsaKeyValidator do
+ let(:validatable) do
+ Class.new do
+ include ActiveModel::Validations
+
+ attr_accessor :signing_key
+
+ validates :signing_key, rsa_key: true
+
+ def initialize(signing_key)
+ @signing_key = signing_key
+ end
+ end
+ end
+
+ subject(:validator) { described_class.new(attributes: [:signing_key]) }
+
+ it 'is not valid when invalid RSA key is provided' do
+ record = validatable.new('invalid RSA key')
+
+ validator.validate(record)
+
+ aggregate_failures do
+ expect(record).not_to be_valid
+ expect(record.errors[:signing_key]).to include('is not a valid RSA key')
+ end
+ end
+
+ it 'is valid when valid RSA key is provided' do
+ record = validatable.new(OpenSSL::PKey::RSA.new(1024).to_pem)
+
+ validator.validate(record)
+
+ expect(record).to be_valid
+ end
+end
diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
index 3fb9fb54b01..c5b56b15431 100644
--- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
@@ -219,6 +219,22 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
end
+ describe 'pipeline editor link' do
+ it 'shows the pipeline editor link' do
+ render
+
+ expect(rendered).to have_link('Editor', href: project_ci_pipeline_editor_path(project))
+ end
+
+ it 'does not show the pipeline editor link' do
+ allow(view).to receive(:can_view_pipeline_editor?).and_return(false)
+
+ render
+
+ expect(rendered).not_to have_link('Editor', href: project_ci_pipeline_editor_path(project))
+ end
+ end
+
describe 'operations settings tab' do
describe 'archive projects' do
before do
diff --git a/spec/views/profiles/preferences/show.html.haml_spec.rb b/spec/views/profiles/preferences/show.html.haml_spec.rb
index aab50209953..2fe941b9f14 100644
--- a/spec/views/profiles/preferences/show.html.haml_spec.rb
+++ b/spec/views/profiles/preferences/show.html.haml_spec.rb
@@ -68,61 +68,4 @@ RSpec.describe 'profiles/preferences/show' do
expect(rendered).to have_css('#localization')
end
end
-
- context 'sourcegraph' do
- def have_sourcegraph_field(*args)
- have_field('user_sourcegraph_enabled', *args)
- end
-
- def have_integrations_section
- have_css('#integrations.profile-settings-sidebar', text: 'Integrations')
- end
-
- before do
- stub_feature_flags(sourcegraph: sourcegraph_feature)
- stub_application_setting(sourcegraph_enabled: sourcegraph_enabled)
- end
-
- context 'when not fully enabled' do
- where(:feature, :admin_enabled) do
- false | false
- false | true
- true | false
- end
-
- with_them do
- let(:sourcegraph_feature) { feature }
- let(:sourcegraph_enabled) { admin_enabled }
-
- before do
- render
- end
-
- it 'does not display sourcegraph field' do
- expect(rendered).not_to have_sourcegraph_field
- end
-
- it 'does not display Integration Settings' do
- expect(rendered).not_to have_integrations_section
- end
- end
- end
-
- context 'when fully enabled' do
- let(:sourcegraph_feature) { true }
- let(:sourcegraph_enabled) { true }
-
- before do
- render
- end
-
- it 'displays the sourcegraph field' do
- expect(rendered).to have_sourcegraph_field
- end
-
- it 'displays the integrations section' do
- expect(rendered).to have_integrations_section
- end
- 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
deleted file mode 100644
index f59ad3f5f84..00000000000
--- a/spec/views/projects/ci/lints/show.html.haml_spec.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'projects/ci/lints/show' do
- include Devise::Test::ControllerHelpers
- 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(:result, result)
- stub_feature_flags(ci_lint_vue: false)
- end
-
- context 'when builds attrbiutes contain HTML nodes' do
- let(:content) do
- {
- rspec: {
- script: '<h1>rspec</h1>',
- stage: 'test'
- }
- }
- end
-
- it 'does not render HTML elements' do
- render
-
- expect(rendered).not_to have_css('h1', text: 'rspec')
- end
- end
-
- context 'when builds attributes do not contain HTML nodes' do
- let(:content) do
- {
- rspec: {
- script: 'rspec',
- stage: 'test'
- }
- }
- end
-
- it 'shows configuration in the table' do
- render
-
- expect(rendered).to have_css('td pre', text: 'rspec')
- end
- end
- end
-
- context 'when the content is valid' do
- let(:content) do
- {
- build_template: {
- script: './build.sh',
- tags: ['dotnet'],
- only: ['test@dude/repo'],
- except: ['deploy'],
- environment: 'testing'
- }
- }
- end
-
- before do
- assign(:project, project)
- assign(:result, result)
- stub_feature_flags(ci_lint_vue: false)
- end
-
- it 'shows the correct values' do
- render
-
- expect(rendered).to have_content('Status: syntax is correct')
- expect(rendered).to have_content('Tag list: dotnet')
- expect(rendered).to have_content('Only policy: refs, test@dude/repo')
- expect(rendered).to have_content('Except policy: refs, deploy')
- expect(rendered).to have_content('Environment: testing')
- expect(rendered).to have_content('When: on_success')
- end
-
- context 'when content has warnings' do
- before do
- allow(result).to receive(:warnings).and_return(['Warning 1', 'Warning 2'])
- end
-
- it 'shows warning messages' do
- render
-
- expect(rendered).to have_content('2 warning(s) found:')
- expect(rendered).to have_content('Warning 1')
- expect(rendered).to have_content('Warning 2')
- end
- end
- 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(:result, result)
- stub_feature_flags(ci_lint_vue: false)
- end
-
- it 'shows error message' do
- render
-
- expect(rendered).to have_content('Status: syntax is incorrect')
- expect(rendered).to have_content('Undefined error')
- expect(rendered).not_to have_content('Tag list:')
- end
-
- it 'shows warning messages' do
- render
-
- expect(rendered).to have_content('2 warning(s) found:')
- expect(rendered).to have_content('Warning 1')
- expect(rendered).to have_content('Warning 2')
- end
- end
-end
diff --git a/spec/views/projects/merge_requests/show.html.haml_spec.rb b/spec/views/projects/merge_requests/show.html.haml_spec.rb
index 1acc07dabb6..9b4f2774c5b 100644
--- a/spec/views/projects/merge_requests/show.html.haml_spec.rb
+++ b/spec/views/projects/merge_requests/show.html.haml_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe 'projects/merge_requests/show.html.haml' do
render
- expect(rendered).not_to have_css('.cannot-be-merged')
+ expect(rendered).not_to have_css('.merge-icon')
end
end
end
diff --git a/spec/views/projects/settings/operations/show.html.haml_spec.rb b/spec/views/projects/settings/operations/show.html.haml_spec.rb
index 24ab64b20f5..facb4e2016d 100644
--- a/spec/views/projects/settings/operations/show.html.haml_spec.rb
+++ b/spec/views/projects/settings/operations/show.html.haml_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'projects/settings/operations/show' do
end
before_all do
- project.add_reporter(user)
+ project.add_maintainer(user)
end
before do
diff --git a/spec/views/projects/tags/index.html.haml_spec.rb b/spec/views/projects/tags/index.html.haml_spec.rb
index 4d501b82238..8cc86b75873 100644
--- a/spec/views/projects/tags/index.html.haml_spec.rb
+++ b/spec/views/projects/tags/index.html.haml_spec.rb
@@ -57,4 +57,29 @@ RSpec.describe 'projects/tags/index.html.haml' do
expect(rendered).not_to have_link(href: latest_succeeded_project_artifacts_path(project, "#{pipeline.ref}/download", job: 'test'))
end
end
+
+ context 'build stats' do
+ let(:tag) { 'v1.0.0' }
+ let(:page) { Capybara::Node::Simple.new(rendered) }
+
+ it 'shows build status or placeholder when pipelines present' do
+ create(:ci_pipeline,
+ project: project,
+ ref: tag,
+ sha: project.commit(tag).sha,
+ status: :success)
+ assign(:tag_pipeline_statuses, Ci::CommitStatusesFinder.new(project, project.repository, project.namespace.owner, tags).execute)
+
+ render
+
+ expect(page.find('.tags .content-list li', text: tag)).to have_css 'a.ci-status-icon-success'
+ expect(page.all('.tags .content-list li')).to all(have_css('svg.s24'))
+ end
+
+ it 'shows no build status or placeholder when no pipelines present' do
+ render
+
+ expect(page.all('.tags .content-list li')).not_to have_css 'svg.s24'
+ end
+ end
end
diff --git a/spec/views/registrations/welcome.html.haml_spec.rb b/spec/views/registrations/welcome.html.haml_spec.rb
deleted file mode 100644
index 56a7784a134..00000000000
--- a/spec/views/registrations/welcome.html.haml_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# 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/registrations/welcome/show.html.haml_spec.rb b/spec/views/registrations/welcome/show.html.haml_spec.rb
new file mode 100644
index 00000000000..bede52bed4b
--- /dev/null
+++ b/spec/views/registrations/welcome/show.html.haml_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'registrations/welcome/show' 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/_filter.html.haml_spec.rb b/spec/views/search/_filter.html.haml_spec.rb
index eb32528e3c7..9a5ff2e4518 100644
--- a/spec/views/search/_filter.html.haml_spec.rb
+++ b/spec/views/search/_filter.html.haml_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'search/_filter' do
render
expect(rendered).to have_selector('label[for="dashboard_search_group"]')
- expect(rendered).to have_selector('button#dashboard_search_group')
+ expect(rendered).to have_selector('input#js-search-group-dropdown')
expect(rendered).to have_selector('label[for="dashboard_search_project"]')
expect(rendered).to have_selector('button#dashboard_search_project')
diff --git a/spec/views/search/_results.html.haml_spec.rb b/spec/views/search/_results.html.haml_spec.rb
index 033b2304e33..6299fd0cf36 100644
--- a/spec/views/search/_results.html.haml_spec.rb
+++ b/spec/views/search/_results.html.haml_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe 'search/_results' do
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|
+ %w[issues merge_requests].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) }
@@ -55,32 +55,30 @@ RSpec.describe 'search/_results' do
expect(rendered).to have_selector('[data-track-property=search_result]')
end
- it 'renders the state filter drop down' do
+ it 'does render the sidebar' do
render
- expect(rendered).to have_selector('#js-search-filter-by-state')
+ expect(rendered).to have_selector('#js-search-sidebar')
end
+ end
+ end
- context 'Feature search_filter_by_confidential' do
- context 'when disabled' do
- before do
- stub_feature_flags(search_filter_by_confidential: false)
- end
+ %w[blobs notes wiki_blobs 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 'does not render the confidential drop down' do
- render
+ it 'renders the click text event tracking attributes' do
+ render
- expect(rendered).not_to have_selector('#js-search-filter-by-confidential')
- end
- end
+ expect(rendered).to have_selector('[data-track-event=click_text]')
+ expect(rendered).to have_selector('[data-track-property=search_result]')
+ end
- context 'when enabled' do
- it 'renders the confidential drop down' do
- render
+ it 'does not render the sidebar' do
+ render
- expect(rendered).to have_selector('#js-search-filter-by-confidential')
- end
- end
+ expect(rendered).not_to have_selector('#js-search-sidebar')
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
index ff692d0eda6..c7de8553d86 100644
--- a/spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb
+++ b/spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb
@@ -6,7 +6,7 @@ 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 }
+ let(:expected_count) { Analytics::InstanceStatistics::Measurement.identifier_query_mapping.keys.size }
it 'triggers CounterJobWorker jobs' do
subject.perform
diff --git a/spec/workers/background_migration_worker_spec.rb b/spec/workers/background_migration_worker_spec.rb
index 15e93d62c7d..8094efcaf04 100644
--- a/spec/workers/background_migration_worker_spec.rb
+++ b/spec/workers/background_migration_worker_spec.rb
@@ -12,45 +12,91 @@ RSpec.describe BackgroundMigrationWorker, :clean_gitlab_redis_shared_state do
end
describe '#perform' do
- it 'performs a background migration' do
- expect(Gitlab::BackgroundMigration)
- .to receive(:perform)
- .with('Foo', [10, 20])
+ before do
+ allow(worker).to receive(:jid).and_return(1)
+ expect(worker).to receive(:always_perform?).and_return(false)
+ end
- worker.perform('Foo', [10, 20])
+ context 'when lease can be obtained' do
+ before do
+ expect(Gitlab::BackgroundMigration)
+ .to receive(:perform)
+ .with('Foo', [10, 20])
+ end
+
+ it 'performs a background migration' do
+ worker.perform('Foo', [10, 20])
+ end
+
+ context 'when lease_attempts is 1' do
+ it 'performs a background migration' do
+ worker.perform('Foo', [10, 20], 1)
+ end
+ end
end
- it 'reschedules a migration if it was performed recently' do
- expect(worker)
- .to receive(:always_perform?)
- .and_return(false)
+ context 'when lease not obtained (migration of same class was performed recently)' do
+ before do
+ expect(Gitlab::BackgroundMigration).not_to receive(:perform)
+
+ worker.lease_for('Foo').try_obtain
+ end
- worker.lease_for('Foo').try_obtain
+ it 'reschedules the migration and decrements the lease_attempts' do
+ expect(described_class)
+ .to receive(:perform_in)
+ .with(a_kind_of(Numeric), 'Foo', [10, 20], 4)
- expect(Gitlab::BackgroundMigration)
- .not_to receive(:perform)
+ worker.perform('Foo', [10, 20], 5)
+ end
- expect(described_class)
- .to receive(:perform_in)
- .with(a_kind_of(Numeric), 'Foo', [10, 20])
+ context 'when lease_attempts is 1' do
+ it 'reschedules the migration and decrements the lease_attempts' do
+ expect(described_class)
+ .to receive(:perform_in)
+ .with(a_kind_of(Numeric), 'Foo', [10, 20], 0)
- worker.perform('Foo', [10, 20])
+ worker.perform('Foo', [10, 20], 1)
+ end
+ end
+
+ context 'when lease_attempts is 0' do
+ it 'gives up performing the migration' do
+ expect(described_class).not_to receive(:perform_in)
+ expect(Sidekiq.logger).to receive(:warn).with(
+ class: 'Foo',
+ message: 'Job could not get an exclusive lease after several tries. Giving up.',
+ job_id: 1)
+
+ worker.perform('Foo', [10, 20], 0)
+ end
+ end
end
- it 'reschedules a migration if the database is not healthy' do
- allow(worker)
- .to receive(:always_perform?)
- .and_return(false)
+ context 'when database is not healthy' do
+ before do
+ allow(worker).to receive(:healthy_database?).and_return(false)
+ end
- allow(worker)
- .to receive(:healthy_database?)
- .and_return(false)
+ it 'reschedules a migration if the database is not healthy' do
+ expect(described_class)
+ .to receive(:perform_in)
+ .with(a_kind_of(Numeric), 'Foo', [10, 20], 4)
- expect(described_class)
- .to receive(:perform_in)
- .with(a_kind_of(Numeric), 'Foo', [10, 20])
+ worker.perform('Foo', [10, 20])
+ end
- worker.perform('Foo', [10, 20])
+ context 'when lease_attempts is 0' do
+ it 'gives up performing the migration' do
+ expect(described_class).not_to receive(:perform_in)
+ expect(Sidekiq.logger).to receive(:warn).with(
+ class: 'Foo',
+ message: 'Database was unhealthy after several tries. Giving up.',
+ job_id: 1)
+
+ worker.perform('Foo', [10, 20], 0)
+ end
+ end
end
it 'sets the class that will be executed as the caller_id' do
diff --git a/spec/workers/build_finished_worker_spec.rb b/spec/workers/build_finished_worker_spec.rb
index 11b50961e9e..b0058c76e27 100644
--- a/spec/workers/build_finished_worker_spec.rb
+++ b/spec/workers/build_finished_worker_spec.rb
@@ -11,18 +11,28 @@ RSpec.describe BuildFinishedWorker do
context 'when build exists' do
let!(:build) { create(:ci_build) }
- it 'calculates coverage and calls hooks' do
- expect(BuildTraceSectionsWorker)
- .to receive(:new).ordered.and_call_original
- expect(BuildCoverageWorker)
- .to receive(:new).ordered.and_call_original
-
- expect_any_instance_of(BuildTraceSectionsWorker).to receive(:perform)
- expect_any_instance_of(BuildCoverageWorker).to receive(:perform)
+ it 'calculates coverage and calls hooks', :aggregate_failures do
+ trace_worker = double('trace worker')
+ coverage_worker = double('coverage worker')
+
+ allow(BuildTraceSectionsWorker).to receive(:new).and_return(trace_worker)
+ allow(BuildCoverageWorker).to receive(:new).and_return(coverage_worker)
+
+ # Unfortunately, `ordered` does not seem to work when called within `allow_next_instance_of`
+ # so we're doing this the long and dirty way
+ expect(trace_worker).to receive(:perform).ordered
+ expect(coverage_worker).to receive(:perform).ordered
+
+ expect_next_instance_of(Ci::BuildReportResultWorker) do |instance|
+ expect(instance).to receive(:perform)
+ end
+ expect_next_instance_of(Ci::TestCasesService) do |instance|
+ expect(instance).to receive(:execute)
+ end
+
expect(BuildHooksWorker).to receive(:perform_async)
expect(ExpirePipelineCacheWorker).to receive(:perform_async)
expect(ChatNotificationWorker).not_to receive(:perform_async)
- expect(Ci::BuildReportResultWorker).not_to receive(:perform)
expect(ArchiveTraceWorker).to receive(:perform_in)
subject
@@ -31,7 +41,7 @@ RSpec.describe BuildFinishedWorker do
context 'when build does not exist' do
it 'does not raise exception' do
- expect { described_class.new.perform(123) }
+ expect { described_class.new.perform(non_existing_record_id) }
.not_to raise_error
end
end
@@ -45,17 +55,5 @@ RSpec.describe BuildFinishedWorker do
subject
end
end
-
- context 'when build has a test report' do
- let(:build) { create(:ci_build, :test_reports) }
-
- it 'schedules a BuildReportResult job' do
- expect_next_instance_of(Ci::BuildReportResultWorker) do |worker|
- expect(worker).to receive(:perform).with(build.id)
- end
-
- subject
- end
- end
end
end
diff --git a/spec/workers/bulk_import_worker_spec.rb b/spec/workers/bulk_import_worker_spec.rb
new file mode 100644
index 00000000000..12783f40528
--- /dev/null
+++ b/spec/workers/bulk_import_worker_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImportWorker do
+ describe '#perform' do
+ it 'executes Group Importer' do
+ bulk_import_id = 1
+
+ expect(BulkImports::Importers::GroupsImporter)
+ .to receive(:new).with(bulk_import_id).and_return(double(execute: true))
+
+ described_class.new.perform(bulk_import_id)
+ end
+ end
+end
diff --git a/spec/workers/ci/delete_objects_worker_spec.rb b/spec/workers/ci/delete_objects_worker_spec.rb
index 6cb8e0cba37..52d90d7667a 100644
--- a/spec/workers/ci/delete_objects_worker_spec.rb
+++ b/spec/workers/ci/delete_objects_worker_spec.rb
@@ -9,9 +9,14 @@ RSpec.describe Ci::DeleteObjectsWorker do
describe '#perform' do
it 'executes a service' do
+ allow(worker).to receive(:max_running_jobs).and_return(25)
+
expect_next_instance_of(Ci::DeleteObjectsService) do |instance|
expect(instance).to receive(:execute)
- expect(instance).to receive(:remaining_batches_count).once.and_call_original
+ expect(instance).to receive(:remaining_batches_count)
+ .with(max_batch_count: 25)
+ .once
+ .and_call_original
end
worker.perform
@@ -23,7 +28,6 @@ RSpec.describe Ci::DeleteObjectsWorker do
before do
stub_feature_flags(
- ci_delete_objects_low_concurrency: low,
ci_delete_objects_medium_concurrency: medium,
ci_delete_objects_high_concurrency: high
)
@@ -31,13 +35,11 @@ RSpec.describe Ci::DeleteObjectsWorker do
subject(:max_running_jobs) { worker.max_running_jobs }
- where(:low, :medium, :high, :expected) do
- false | false | false | 0
- true | true | true | 2
- true | false | false | 2
- false | true | false | 20
- false | true | true | 20
- false | false | true | 50
+ where(:medium, :high, :expected) do
+ false | false | 2
+ true | false | 20
+ true | true | 20
+ false | true | 50
end
with_them do
diff --git a/spec/workers/concerns/application_worker_spec.rb b/spec/workers/concerns/application_worker_spec.rb
index a18b83f199b..07e11f014c3 100644
--- a/spec/workers/concerns/application_worker_spec.rb
+++ b/spec/workers/concerns/application_worker_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe ApplicationWorker do
instance.jid = 'a jid'
expect(result).to include(
- 'class' => worker.class,
+ 'class' => instance.class.name,
'job_status' => 'running',
'queue' => worker.queue,
'jid' => instance.jid
@@ -69,7 +69,7 @@ RSpec.describe ApplicationWorker do
it 'does not override predefined context keys with custom payload' do
payload['class'] = 'custom value'
- expect(result).to include('class' => worker.class)
+ expect(result).to include('class' => instance.class.name)
end
end
diff --git a/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb b/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb
index 09d64fe50bd..8727756ce50 100644
--- a/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb
+++ b/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe Gitlab::GithubImport::ReschedulingMethods do
end
context 'with an existing project' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, import_url: 'https://t0ken@github.com/repo/repo.git') }
it 'notifies any waiters upon successfully importing the data' do
expect(worker)
diff --git a/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb b/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb
index b7635748498..03e875bcb87 100644
--- a/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb
+++ b/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb
@@ -9,6 +9,8 @@ RSpec.describe Gitlab::GithubImport::StageMethods do
end
describe '#perform' do
+ let(:project) { create(:project, import_url: 'https://t0ken@github.com/repo/repo.git') }
+
it 'returns if no project could be found' do
expect(worker).not_to receive(:try_import)
diff --git a/spec/workers/concerns/limited_capacity/worker_spec.rb b/spec/workers/concerns/limited_capacity/worker_spec.rb
index 8a15675c04d..2c33c8666ec 100644
--- a/spec/workers/concerns/limited_capacity/worker_spec.rb
+++ b/spec/workers/concerns/limited_capacity/worker_spec.rb
@@ -121,7 +121,8 @@ RSpec.describe LimitedCapacity::Worker, :clean_gitlab_redis_queues, :aggregate_f
it 'reports prometheus metrics' do
allow(worker).to receive(:perform_work)
- expect(worker).to receive(:report_prometheus_metrics)
+ expect(worker).to receive(:report_prometheus_metrics).once.and_call_original
+ expect(worker).to receive(:report_running_jobs_metrics).twice.and_call_original
perform
end
diff --git a/spec/workers/concerns/reenqueuer_spec.rb b/spec/workers/concerns/reenqueuer_spec.rb
index df0724045c1..ab44042834f 100644
--- a/spec/workers/concerns/reenqueuer_spec.rb
+++ b/spec/workers/concerns/reenqueuer_spec.rb
@@ -40,9 +40,7 @@ RSpec.describe Reenqueuer do
it_behaves_like 'reenqueuer'
- it_behaves_like 'it is rate limited to 1 call per', 5.seconds do
- let(:rate_limited_method) { subject.perform }
- end
+ it_behaves_like '#perform is rate limited to 1 call per', 5.seconds
it 'disables Sidekiq retries' do
expect(job.sidekiq_options_hash).to include('retry' => false)
@@ -98,7 +96,7 @@ RSpec.describe Reenqueuer::ReenqueuerSleeper do
Class.new do
include Reenqueuer::ReenqueuerSleeper
- def rate_limited_method
+ def perform
ensure_minimum_duration(11.seconds) do
# do work
end
@@ -108,12 +106,11 @@ RSpec.describe Reenqueuer::ReenqueuerSleeper do
subject(:dummy) { dummy_class.new }
- # Test that rate_limited_method is rate limited by ensure_minimum_duration
- it_behaves_like 'it is rate limited to 1 call per', 11.seconds do
- let(:rate_limited_method) { dummy.rate_limited_method }
- end
+ # Slightly higher-level test of ensure_minimum_duration since we conveniently
+ # already have this shared example anyway.
+ it_behaves_like '#perform is rate limited to 1 call per', 11.seconds
- # Test ensure_minimum_duration more directly
+ # Unit test ensure_minimum_duration
describe '#ensure_minimum_duration' do
around do |example|
# Allow Timecop.travel without the block form
diff --git a/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
new file mode 100644
index 00000000000..d98ea1b6ab2
--- /dev/null
+++ b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
@@ -0,0 +1,234 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
+ let_it_be(:repository, reload: true) { create(:container_repository, :cleanup_scheduled) }
+ let_it_be(:project) { repository.project }
+ let_it_be(:policy) { project.container_expiration_policy }
+ let_it_be(:other_repository) { create(:container_repository) }
+
+ let(:worker) { described_class.new }
+
+ describe '#perform_work' do
+ subject { worker.perform_work }
+
+ before do
+ policy.update_column(:enabled, true)
+ end
+
+ RSpec.shared_examples 'handling all repository conditions' do
+ it 'sends the repository for cleaning' do
+ expect(ContainerExpirationPolicies::CleanupService)
+ .to receive(:new).with(repository).and_return(double(execute: cleanup_service_response(repository: repository)))
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_status, :finished)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:container_repository_id, repository.id)
+
+ subject
+ end
+
+ context 'with unfinished cleanup' do
+ it 'logs an unfinished cleanup' do
+ expect(ContainerExpirationPolicies::CleanupService)
+ .to receive(:new).with(repository).and_return(double(execute: cleanup_service_response(status: :unfinished, repository: repository)))
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_status, :unfinished)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:container_repository_id, repository.id)
+
+ subject
+ end
+ end
+
+ context 'with policy running shortly' do
+ before do
+ repository.project
+ .container_expiration_policy
+ .update_column(:next_run_at, 1.minute.from_now)
+ end
+
+ it 'skips the repository' do
+ expect(ContainerExpirationPolicies::CleanupService).not_to receive(:new)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:container_repository_id, repository.id)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_status, :skipped)
+
+ expect { subject }.to change { ContainerRepository.waiting_for_cleanup.count }.from(1).to(0)
+ expect(repository.reload.cleanup_unscheduled?).to be_truthy
+ end
+ end
+
+ context 'with disabled policy' do
+ before do
+ repository.project
+ .container_expiration_policy
+ .disable!
+ end
+
+ it 'skips the repository' do
+ expect(ContainerExpirationPolicies::CleanupService).not_to receive(:new)
+
+ expect { subject }.to change { ContainerRepository.waiting_for_cleanup.count }.from(1).to(0)
+ expect(repository.reload.cleanup_unscheduled?).to be_truthy
+ end
+ end
+ end
+
+ context 'with repository in cleanup scheduled state' do
+ it_behaves_like 'handling all repository conditions'
+ end
+
+ context 'with repository in cleanup unfinished state' do
+ before do
+ repository.cleanup_unfinished!
+ end
+
+ it_behaves_like 'handling all repository conditions'
+ end
+
+ context 'with another repository in cleanup unfinished state' do
+ let_it_be(:another_repository) { create(:container_repository, :cleanup_unfinished) }
+
+ it 'process the cleanup scheduled repository first' do
+ expect(ContainerExpirationPolicies::CleanupService)
+ .to receive(:new).with(repository).and_return(double(execute: cleanup_service_response(repository: repository)))
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_status, :finished)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:container_repository_id, repository.id)
+
+ subject
+ end
+ end
+
+ context 'with multiple repositories in cleanup unfinished state' do
+ let_it_be(:repository2) { create(:container_repository, :cleanup_unfinished, expiration_policy_started_at: 20.minutes.ago) }
+ let_it_be(:repository3) { create(:container_repository, :cleanup_unfinished, expiration_policy_started_at: 10.minutes.ago) }
+
+ before do
+ repository.update!(expiration_policy_cleanup_status: :cleanup_unfinished, expiration_policy_started_at: 30.minutes.ago)
+ end
+
+ it 'process the repository with the oldest expiration_policy_started_at' do
+ expect(ContainerExpirationPolicies::CleanupService)
+ .to receive(:new).with(repository).and_return(double(execute: cleanup_service_response(repository: repository)))
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_status, :finished)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:container_repository_id, repository.id)
+
+ subject
+ end
+ end
+
+ context 'with repository in cleanup ongoing state' do
+ before do
+ repository.cleanup_ongoing!
+ end
+
+ it 'does not process it' do
+ expect(Projects::ContainerRepository::CleanupTagsService).not_to receive(:new)
+
+ expect { subject }.not_to change { ContainerRepository.waiting_for_cleanup.count }
+ expect(repository.cleanup_ongoing?).to be_truthy
+ end
+ end
+
+ context 'with no repository in any cleanup state' do
+ before do
+ repository.cleanup_unscheduled!
+ end
+
+ it 'does not process it' do
+ expect(Projects::ContainerRepository::CleanupTagsService).not_to receive(:new)
+
+ expect { subject }.not_to change { ContainerRepository.waiting_for_cleanup.count }
+ expect(repository.cleanup_unscheduled?).to be_truthy
+ end
+ end
+
+ context 'with no container repository waiting' do
+ before do
+ repository.destroy!
+ end
+
+ it 'does not execute the cleanup tags service' do
+ expect(Projects::ContainerRepository::CleanupTagsService).not_to receive(:new)
+
+ expect { subject }.not_to change { ContainerRepository.waiting_for_cleanup.count }
+ end
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(container_registry_expiration_policies_throttling: false)
+ end
+
+ it 'is a no-op' do
+ expect(Projects::ContainerRepository::CleanupTagsService).not_to receive(:new)
+
+ expect { subject }.not_to change { ContainerRepository.waiting_for_cleanup.count }
+ end
+ end
+
+ def cleanup_service_response(status: :finished, repository:)
+ ServiceResponse.success(message: "cleanup #{status}", payload: { cleanup_status: status, container_repository_id: repository.id })
+ end
+ end
+
+ describe '#remaining_work_count' do
+ subject { worker.remaining_work_count }
+
+ context 'with container repositoires waiting for cleanup' do
+ let_it_be(:unfinished_repositories) { create_list(:container_repository, 2, :cleanup_unfinished) }
+
+ it { is_expected.to eq(3) }
+
+ it 'logs the work count' do
+ expect_log_info(
+ cleanup_scheduled_count: 1,
+ cleanup_unfinished_count: 2,
+ cleanup_total_count: 3
+ )
+
+ subject
+ end
+ end
+
+ context 'with no container repositories waiting for cleanup' do
+ before do
+ repository.cleanup_ongoing!
+ end
+
+ it { is_expected.to eq(0) }
+
+ it 'logs 0 work count' do
+ expect_log_info(
+ cleanup_scheduled_count: 0,
+ cleanup_unfinished_count: 0,
+ cleanup_total_count: 0
+ )
+
+ subject
+ end
+ end
+ end
+
+ describe '#max_running_jobs' do
+ let(:capacity) { 50 }
+
+ subject { worker.max_running_jobs }
+
+ before do
+ stub_application_setting(container_registry_expiration_policies_worker_capacity: capacity)
+ end
+
+ it { is_expected.to eq(capacity) }
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(container_registry_expiration_policies_throttling: false)
+ end
+
+ it { is_expected.to eq(0) }
+ end
+ end
+
+ def expect_log_info(structure)
+ expect(worker.logger)
+ .to receive(:info).with(worker.structured_payload(structure))
+ end
+end
diff --git a/spec/workers/container_expiration_policy_worker_spec.rb b/spec/workers/container_expiration_policy_worker_spec.rb
index 6b185c30670..d9a4f6396f8 100644
--- a/spec/workers/container_expiration_policy_worker_spec.rb
+++ b/spec/workers/container_expiration_policy_worker_spec.rb
@@ -5,71 +5,151 @@ require 'spec_helper'
RSpec.describe ContainerExpirationPolicyWorker do
include ExclusiveLeaseHelpers
- subject { described_class.new.perform }
+ let(:worker) { described_class.new }
+ let(:started_at) { nil }
- RSpec.shared_examples 'not executing any policy' do
- it 'does not run any policy' do
- expect(ContainerExpirationPolicyService).not_to receive(:new)
+ describe '#perform' do
+ subject { worker.perform }
- subject
+ RSpec.shared_examples 'not executing any policy' do
+ it 'does not run any policy' do
+ expect(ContainerExpirationPolicyService).not_to receive(:new)
+
+ subject
+ end
end
- end
- context 'With no container expiration policies' do
- it_behaves_like 'not executing any policy'
- end
+ context 'With no container expiration policies' do
+ it 'does not execute any policies' do
+ expect(ContainerRepository).not_to receive(:for_project_id)
- context 'With container expiration policies' do
- let_it_be(:container_expiration_policy, reload: true) { create(:container_expiration_policy, :runnable) }
- let_it_be(:container_repository) { create(:container_repository, project: container_expiration_policy.project) }
- let_it_be(:user) { container_expiration_policy.project.owner }
+ expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count }
+ end
+ end
- context 'a valid policy' do
- it 'runs the policy' do
- service = instance_double(ContainerExpirationPolicyService, execute: true)
+ context 'with container expiration policies' do
+ let_it_be(:container_expiration_policy) { create(:container_expiration_policy, :runnable) }
+ let_it_be(:container_repository) { create(:container_repository, project: container_expiration_policy.project) }
- expect(ContainerExpirationPolicyService)
- .to receive(:new).with(container_expiration_policy.project, user).and_return(service)
+ context 'with a valid container expiration policy' do
+ it 'schedules the next run' do
+ expect { subject }.to change { container_expiration_policy.reload.next_run_at }
+ end
- subject
- end
- end
+ it 'marks the container repository as scheduled for cleanup' do
+ expect { subject }.to change { container_repository.reload.cleanup_scheduled? }.from(false).to(true)
+ expect(ContainerRepository.cleanup_scheduled.count).to eq(1)
+ end
- context 'a disabled policy' do
- before do
- container_expiration_policy.disable!
+ it 'calls the limited capacity worker' do
+ expect(ContainerExpirationPolicies::CleanupContainerRepositoryWorker).to receive(:perform_with_capacity)
+
+ subject
+ end
end
- it_behaves_like 'not executing any policy'
- end
+ context 'with a disabled container expiration policy' do
+ before do
+ container_expiration_policy.disable!
+ end
- context 'a policy that is not due for a run' do
- before do
- container_expiration_policy.update_column(:next_run_at, 2.minutes.from_now)
+ it 'does not run the policy' do
+ expect(ContainerRepository).not_to receive(:for_project_id)
+
+ expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count }
+ end
end
- it_behaves_like 'not executing any policy'
+ context 'with an invalid container expiration policy' do
+ let(:user) { container_expiration_policy.project.owner }
+
+ before do
+ container_expiration_policy.update_column(:name_regex, '*production')
+ end
+
+ it 'disables the policy and tracks an error' do
+ expect(ContainerRepository).not_to receive(:for_project_id)
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(described_class::InvalidPolicyError), container_expiration_policy_id: container_expiration_policy.id)
+
+ expect { subject }.to change { container_expiration_policy.reload.enabled }.from(true).to(false)
+ expect(ContainerRepository.cleanup_scheduled).to be_empty
+ end
+ end
end
- context 'a policy linked to no container repository' do
+ context 'with exclusive lease taken' do
before do
- container_expiration_policy.container_repositories.delete_all
+ stub_exclusive_lease_taken(worker.lease_key, timeout: 5.hours)
end
- it_behaves_like 'not executing any policy'
+ it 'does not execute any policy' do
+ expect(ContainerExpirationPolicies::CleanupContainerRepositoryWorker).not_to receive(:perform_with_capacity)
+ expect(worker).not_to receive(:runnable_policies)
+
+ expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count }
+ end
end
- context 'an invalid policy' do
+ context 'with throttling disabled' do
before do
- container_expiration_policy.update_column(:name_regex, '*production')
+ stub_feature_flags(container_registry_expiration_policies_throttling: false)
end
- it 'runs the policy and tracks an error' do
- expect(ContainerExpirationPolicyService)
- .to receive(:new).with(container_expiration_policy.project, user).and_call_original
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(ContainerExpirationPolicyService::InvalidPolicyError), container_expiration_policy_id: container_expiration_policy.id)
+ context 'with no container expiration policies' do
+ it_behaves_like 'not executing any policy'
+ end
- expect { subject }.to change { container_expiration_policy.reload.enabled }.from(true).to(false)
+ context 'with container expiration policies' do
+ let_it_be(:container_expiration_policy, reload: true) { create(:container_expiration_policy, :runnable) }
+ let_it_be(:container_repository) { create(:container_repository, project: container_expiration_policy.project) }
+ let_it_be(:user) { container_expiration_policy.project.owner }
+
+ context 'a valid policy' do
+ it 'runs the policy' do
+ expect(ContainerExpirationPolicyService)
+ .to receive(:new).with(container_expiration_policy.project, user).and_call_original
+ expect(CleanupContainerRepositoryWorker).to receive(:perform_async).once.and_call_original
+
+ expect { subject }.not_to raise_error
+ end
+ end
+
+ context 'a disabled policy' do
+ before do
+ container_expiration_policy.disable!
+ end
+
+ it_behaves_like 'not executing any policy'
+ end
+
+ context 'a policy that is not due for a run' do
+ before do
+ container_expiration_policy.update_column(:next_run_at, 2.minutes.from_now)
+ end
+
+ it_behaves_like 'not executing any policy'
+ end
+
+ context 'a policy linked to no container repository' do
+ before do
+ container_expiration_policy.container_repositories.delete_all
+ end
+
+ it_behaves_like 'not executing any policy'
+ end
+
+ context 'an invalid policy' do
+ before do
+ container_expiration_policy.update_column(:name_regex, '*production')
+ end
+
+ it 'disables the policy and tracks an error' do
+ expect(ContainerExpirationPolicyService).not_to receive(:new).with(container_expiration_policy, user)
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(described_class::InvalidPolicyError), container_expiration_policy_id: container_expiration_policy.id)
+
+ expect { subject }.to change { container_expiration_policy.reload.enabled }.from(true).to(false)
+ end
+ end
end
end
end
diff --git a/spec/workers/destroy_pages_deployments_worker_spec.rb b/spec/workers/destroy_pages_deployments_worker_spec.rb
new file mode 100644
index 00000000000..2c20c9004ef
--- /dev/null
+++ b/spec/workers/destroy_pages_deployments_worker_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DestroyPagesDeploymentsWorker do
+ subject(:worker) { described_class.new }
+
+ let(:project) { create(:project) }
+ let!(:old_deployment) { create(:pages_deployment, project: project) }
+ let!(:last_deployment) { create(:pages_deployment, project: project) }
+ let!(:another_deployment) { create(:pages_deployment) }
+
+ it "doesn't fail if project is already removed" do
+ expect do
+ worker.perform(-1)
+ end.not_to raise_error
+ end
+
+ it 'can be called without last_deployment_id' do
+ expect_next_instance_of(::Pages::DestroyDeploymentsService, project, nil) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
+
+ expect do
+ worker.perform(project.id)
+ end.to change { PagesDeployment.count }.by(-2)
+ end
+
+ it 'calls destroy service' do
+ expect_next_instance_of(::Pages::DestroyDeploymentsService, project, last_deployment.id) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
+
+ expect do
+ worker.perform(project.id, last_deployment.id)
+ end.to change { PagesDeployment.count }.by(-1)
+ end
+end
diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb
index fc9115a5ea1..13089549086 100644
--- a/spec/workers/git_garbage_collect_worker_spec.rb
+++ b/spec/workers/git_garbage_collect_worker_spec.rb
@@ -272,6 +272,11 @@ RSpec.describe GitGarbageCollectWorker do
expect(before_packs.count).to be >= 1
+ expect_any_instance_of(Gitlab::GitalyClient::RepositoryService)
+ .to receive(:garbage_collect)
+ .with(bitmaps_enabled, prune: false)
+ .and_call_original
+
subject.perform(project.id, 'gc', lease_key, lease_uuid)
after_packed_refs = packed_refs(project)
after_packs = packs(project)
@@ -292,6 +297,15 @@ RSpec.describe GitGarbageCollectWorker do
subject.perform(project.id, 'gc', lease_key, lease_uuid)
end
+
+ it 'prune calls garbage_collect with the option prune: true' do
+ expect_any_instance_of(Gitlab::GitalyClient::RepositoryService)
+ .to receive(:garbage_collect)
+ .with(bitmaps_enabled, prune: true)
+ .and_return(nil)
+
+ subject.perform(project.id, 'prune', lease_key, lease_uuid)
+ end
end
context 'with bitmaps enabled' do
diff --git a/spec/workers/jira_connect/sync_branch_worker_spec.rb b/spec/workers/jira_connect/sync_branch_worker_spec.rb
index 2da3ea9d256..4aa2f89de7b 100644
--- a/spec/workers/jira_connect/sync_branch_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_branch_worker_spec.rb
@@ -4,7 +4,10 @@ require 'spec_helper'
RSpec.describe JiraConnect::SyncBranchWorker do
describe '#perform' do
- let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :repository, group: group) }
+ let_it_be(:subscription) { create(:jira_connect_subscription, installation: create(:jira_connect_installation), namespace: group) }
+
let(:project_id) { project.id }
let(:branch_name) { 'master' }
let(:commit_shas) { %w(b83d6e3 5a62481) }
@@ -13,7 +16,7 @@ RSpec.describe JiraConnect::SyncBranchWorker do
def expect_jira_sync_service_execute(args)
expect_next_instance_of(JiraConnect::SyncService) do |instance|
- expect(instance).to receive(:execute).with(args)
+ expect(instance).to receive(:execute).with(args.merge(update_sequence_id: nil))
end
end
@@ -61,5 +64,31 @@ RSpec.describe JiraConnect::SyncBranchWorker do
subject
end
end
+
+ context 'with update_sequence_id' do
+ let(:update_sequence_id) { 1 }
+ let(:request_url) { 'https://sample.atlassian.net/rest/devinfo/0.10/bulk' }
+ let(:request_body) do
+ {
+ repositories: [
+ Atlassian::JiraConnect::Serializers::RepositoryEntity.represent(
+ project,
+ commits: project.commits_by(oids: commit_shas),
+ branches: [project.repository.find_branch(branch_name)],
+ update_sequence_id: update_sequence_id
+ )
+ ]
+ }.to_json
+ end
+
+ subject { described_class.new.perform(project_id, branch_name, commit_shas, update_sequence_id) }
+
+ it 'sends the reqeust with custom update_sequence_id' do
+ expect(Atlassian::JiraConnect::Client).to receive(:post)
+ .with(URI(request_url), headers: anything, body: request_body)
+
+ subject
+ end
+ end
end
end
diff --git a/spec/workers/jira_connect/sync_merge_request_worker_spec.rb b/spec/workers/jira_connect/sync_merge_request_worker_spec.rb
index 764201e750a..b3c0db4f260 100644
--- a/spec/workers/jira_connect/sync_merge_request_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_merge_request_worker_spec.rb
@@ -4,14 +4,18 @@ require 'spec_helper'
RSpec.describe JiraConnect::SyncMergeRequestWorker do
describe '#perform' do
- let(:merge_request) { create(:merge_request) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :repository, group: group) }
+ let_it_be(:subscription) { create(:jira_connect_subscription, installation: create(:jira_connect_installation), namespace: group) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+
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])
+ expect(service).to receive(:execute).with(merge_requests: [merge_request], update_sequence_id: nil)
end
subject
@@ -26,5 +30,30 @@ RSpec.describe JiraConnect::SyncMergeRequestWorker do
subject
end
end
+
+ context 'with update_sequence_id' do
+ let(:update_sequence_id) { 1 }
+ let(:request_url) { 'https://sample.atlassian.net/rest/devinfo/0.10/bulk' }
+ let(:request_body) do
+ {
+ repositories: [
+ Atlassian::JiraConnect::Serializers::RepositoryEntity.represent(
+ project,
+ merge_requests: [merge_request],
+ update_sequence_id: update_sequence_id
+ )
+ ]
+ }.to_json
+ end
+
+ subject { described_class.new.perform(merge_request_id, update_sequence_id) }
+
+ it 'sends the request with custom update_sequence_id' do
+ expect(Atlassian::JiraConnect::Client).to receive(:post)
+ .with(URI(request_url), headers: anything, body: request_body)
+
+ subject
+ end
+ end
end
end
diff --git a/spec/workers/jira_connect/sync_project_worker_spec.rb b/spec/workers/jira_connect/sync_project_worker_spec.rb
new file mode 100644
index 00000000000..25210de828c
--- /dev/null
+++ b/spec/workers/jira_connect/sync_project_worker_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnect::SyncProjectWorker, factory_default: :keep do
+ describe '#perform' do
+ let_it_be(:project) { create_default(:project) }
+ let!(:mr_with_jira_title) { create(:merge_request, :unique_branches, title: 'TEST-123') }
+ let!(:mr_with_jira_description) { create(:merge_request, :unique_branches, description: 'TEST-323') }
+ let!(:mr_with_other_title) { create(:merge_request, :unique_branches) }
+ let!(:jira_subscription) { create(:jira_connect_subscription, namespace: project.namespace) }
+
+ let(:jira_connect_sync_service) { JiraConnect::SyncService.new(project) }
+ let(:job_args) { [project.id, update_sequence_id] }
+ let(:update_sequence_id) { 1 }
+
+ before do
+ stub_request(:post, 'https://sample.atlassian.net/rest/devinfo/0.10/bulk').to_return(status: 200, body: '', headers: {})
+
+ jira_connect_sync_service
+ allow(JiraConnect::SyncService).to receive(:new) { jira_connect_sync_service }
+ end
+
+ context 'when the project is not found' do
+ it 'does not raise an error' do
+ expect { described_class.new.perform('non_existing_record_id', update_sequence_id) }.not_to raise_error
+ end
+ end
+
+ it 'avoids N+1 database queries' do
+ control_count = ActiveRecord::QueryRecorder.new { described_class.new.perform(project.id, update_sequence_id) }.count
+
+ create(:merge_request, :unique_branches, title: 'TEST-123')
+
+ expect { described_class.new.perform(project.id, update_sequence_id) }.not_to exceed_query_limit(control_count)
+ end
+
+ it_behaves_like 'an idempotent worker' do
+ let(:request_url) { 'https://sample.atlassian.net/rest/devinfo/0.10/bulk' }
+ let(:request_body) do
+ {
+ repositories: [
+ Atlassian::JiraConnect::Serializers::RepositoryEntity.represent(
+ project,
+ merge_requests: [mr_with_jira_description, mr_with_jira_title],
+ update_sequence_id: update_sequence_id
+ )
+ ]
+ }.to_json
+ end
+
+ it 'sends the request with custom update_sequence_id' do
+ expect(Atlassian::JiraConnect::Client).to receive(:post)
+ .exactly(IdempotentWorkerHelper::WORKER_EXEC_TIMES).times
+ .with(URI(request_url), headers: anything, body: request_body)
+
+ subject
+ end
+
+ context 'when the number of merge requests to sync is higher than the limit' do
+ let!(:most_recent_merge_request) { create(:merge_request, :unique_branches, description: 'TEST-323', title: 'TEST-123') }
+
+ before do
+ stub_const("#{described_class}::MERGE_REQUEST_LIMIT", 1)
+ end
+
+ it 'syncs only the most recent merge requests within the limit' do
+ expect(jira_connect_sync_service).to receive(:execute)
+ .exactly(IdempotentWorkerHelper::WORKER_EXEC_TIMES).times
+ .with(merge_requests: [most_recent_merge_request], update_sequence_id: update_sequence_id)
+
+ subject
+ end
+ end
+ end
+ end
+end
diff --git a/spec/workers/propagate_integration_inherit_descendant_worker_spec.rb b/spec/workers/propagate_integration_inherit_descendant_worker_spec.rb
new file mode 100644
index 00000000000..b5eb0f69017
--- /dev/null
+++ b/spec/workers/propagate_integration_inherit_descendant_worker_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe PropagateIntegrationInheritDescendantWorker do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let_it_be(:group_integration) { create(:redmine_service, group: group, project: nil) }
+ let_it_be(:subgroup_integration) { create(:redmine_service, group: subgroup, project: nil, inherit_from_id: group_integration.id) }
+
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [group_integration.id, subgroup_integration.id, subgroup_integration.id] }
+
+ it 'calls to BulkUpdateIntegrationService' do
+ expect(BulkUpdateIntegrationService).to receive(:new)
+ .with(group_integration, match_array(subgroup_integration)).twice
+ .and_return(double(execute: nil))
+
+ subject
+ end
+ end
+
+ context 'with an invalid integration id' do
+ it 'returns without failure' do
+ expect(BulkUpdateIntegrationService).not_to receive(:new)
+
+ subject.perform(0, subgroup_integration.id, subgroup_integration.id)
+ end
+ end
+end
diff --git a/spec/workers/propagate_integration_inherit_worker_spec.rb b/spec/workers/propagate_integration_inherit_worker_spec.rb
index cbfee29a6a0..39219eaa3b5 100644
--- a/spec/workers/propagate_integration_inherit_worker_spec.rb
+++ b/spec/workers/propagate_integration_inherit_worker_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe PropagateIntegrationInheritWorker do
it_behaves_like 'an idempotent worker' do
let(:job_args) { [integration.id, integration1.id, integration3.id] }
- it 'calls to BulkCreateIntegrationService' do
+ it 'calls to BulkUpdateIntegrationService' do
expect(BulkUpdateIntegrationService).to receive(:new)
.with(integration, match_array(integration1)).twice
.and_return(double(execute: nil))
diff --git a/spec/workers/purge_dependency_proxy_cache_worker_spec.rb b/spec/workers/purge_dependency_proxy_cache_worker_spec.rb
new file mode 100644
index 00000000000..9cd3b6636f5
--- /dev/null
+++ b/spec/workers/purge_dependency_proxy_cache_worker_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe PurgeDependencyProxyCacheWorker do
+ let_it_be(:user) { create(:admin) }
+ let_it_be(:blob) { create(:dependency_proxy_blob )}
+ let_it_be(:group, reload: true) { blob.group }
+ let_it_be(:group_id) { group.id }
+
+ subject { described_class.new.perform(user.id, group_id) }
+
+ before do
+ stub_config(dependency_proxy: { enabled: true })
+ group.create_dependency_proxy_setting!(enabled: true)
+ end
+
+ describe '#perform' do
+ shared_examples 'returns nil' do
+ it 'returns nil' do
+ expect { subject }.not_to change { group.dependency_proxy_blobs.size }
+ expect(subject).to be_nil
+ end
+ end
+
+ context 'an admin user' do
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [user.id, group_id] }
+
+ it 'deletes the blobs and returns ok' do
+ expect(group.dependency_proxy_blobs.size).to eq(1)
+
+ subject
+
+ expect(group.dependency_proxy_blobs.size).to eq(0)
+ end
+ end
+ end
+
+ context 'a non-admin user' do
+ let(:user) { create(:user) }
+
+ it_behaves_like 'returns nil'
+ end
+
+ context 'an invalid user id' do
+ let(:user) { double('User', id: 99999 ) }
+
+ it_behaves_like 'returns nil'
+ end
+
+ context 'an invalid group' do
+ let(:group_id) { 99999 }
+
+ it_behaves_like 'returns nil'
+ end
+ end
+end
diff --git a/spec/workers/remove_expired_members_worker_spec.rb b/spec/workers/remove_expired_members_worker_spec.rb
index 8a34b41834b..5642de05731 100644
--- a/spec/workers/remove_expired_members_worker_spec.rb
+++ b/spec/workers/remove_expired_members_worker_spec.rb
@@ -31,6 +31,50 @@ RSpec.describe RemoveExpiredMembersWorker do
end
end
+ context 'project bots' do
+ let(:project) { create(:project) }
+
+ context 'expired project bot', :sidekiq_inline do
+ let_it_be(:expired_project_bot) { create(:user, :project_bot) }
+
+ before do
+ project.add_user(expired_project_bot, :maintainer, expires_at: 1.day.from_now)
+ travel_to(3.days.from_now)
+ end
+
+ it 'removes expired project bot membership' do
+ expect { worker.perform }.to change { Member.count }.by(-1)
+ expect(Member.find_by(user_id: expired_project_bot.id)).to be_nil
+ end
+
+ it 'deletes expired project bot' do
+ worker.perform
+
+ expect(User.exists?(expired_project_bot.id)).to be(false)
+ end
+ end
+
+ context 'non-expired project bot' do
+ let_it_be(:other_project_bot) { create(:user, :project_bot) }
+
+ before do
+ project.add_user(other_project_bot, :maintainer, expires_at: 10.days.from_now)
+ travel_to(3.days.from_now)
+ end
+
+ it 'does not remove expired project bot that expires in the future' do
+ expect { worker.perform }.to change { Member.count }.by(0)
+ expect(other_project_bot.reload).to be_present
+ end
+
+ it 'does not delete project bot expiring in the future' do
+ worker.perform
+
+ expect(User.exists?(other_project_bot.id)).to be(true)
+ end
+ end
+ end
+
context 'group members' do
let_it_be(:expired_group_member) { create(:group_member, expires_at: 1.day.from_now, access_level: GroupMember::DEVELOPER) }
let_it_be(:group_member_expiring_in_future) { create(:group_member, expires_at: 10.days.from_now, access_level: GroupMember::DEVELOPER) }
diff --git a/spec/workers/repository_cleanup_worker_spec.rb b/spec/workers/repository_cleanup_worker_spec.rb
index f5887d08bd2..2b700b944d2 100644
--- a/spec/workers/repository_cleanup_worker_spec.rb
+++ b/spec/workers/repository_cleanup_worker_spec.rb
@@ -40,6 +40,8 @@ RSpec.describe RepositoryCleanupWorker do
describe '#sidekiq_retries_exhausted' do
let(:job) { { 'args' => [project.id, user.id], 'error_message' => 'Error' } }
+ subject(:sidekiq_retries_exhausted) { described_class.sidekiq_retries_exhausted_block.call(job, StandardError.new) }
+
it 'does not send a failure notification for a RecordNotFound error' do
expect(NotificationService).not_to receive(:new)
@@ -51,7 +53,13 @@ RSpec.describe RepositoryCleanupWorker do
expect(service).to receive(:repository_cleanup_failure).with(project, user, 'Error')
end
- described_class.sidekiq_retries_exhausted_block.call(job, StandardError.new)
+ sidekiq_retries_exhausted
+ end
+
+ it 'cleans up the attempt' do
+ expect(Projects::CleanupService).to receive(:cleanup_after).with(project)
+
+ sidekiq_retries_exhausted
end
end
end
diff --git a/spec/workers/schedule_merge_request_cleanup_refs_worker_spec.rb b/spec/workers/schedule_merge_request_cleanup_refs_worker_spec.rb
new file mode 100644
index 00000000000..0dd50efba1c
--- /dev/null
+++ b/spec/workers/schedule_merge_request_cleanup_refs_worker_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ScheduleMergeRequestCleanupRefsWorker do
+ subject(:worker) { described_class.new }
+
+ describe '#perform' do
+ before do
+ allow(MergeRequest::CleanupSchedule)
+ .to receive(:scheduled_merge_request_ids)
+ .with(described_class::LIMIT)
+ .and_return([1, 2, 3, 4])
+ end
+
+ it 'does nothing if the database is read-only' do
+ allow(Gitlab::Database).to receive(:read_only?).and_return(true)
+ expect(MergeRequestCleanupRefsWorker).not_to receive(:bulk_perform_in)
+
+ worker.perform
+ end
+
+ include_examples 'an idempotent worker' do
+ it 'schedules MergeRequestCleanupRefsWorker to be performed by batch' do
+ expect(MergeRequestCleanupRefsWorker)
+ .to receive(:bulk_perform_in)
+ .with(
+ described_class::DELAY,
+ [[1], [2], [3], [4]],
+ batch_size: described_class::BATCH_SIZE
+ )
+
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:merge_requests_count, 4)
+
+ worker.perform
+ end
+ end
+ end
+end
diff --git a/tooling/README.md b/tooling/README.md
new file mode 100644
index 00000000000..29706a5af14
--- /dev/null
+++ b/tooling/README.md
@@ -0,0 +1,4 @@
+# Tooling
+
+This directory contains tools and configuration for development only.
+
diff --git a/tooling/eslint-config/conditionally_ignore_ee.js b/tooling/eslint-config/conditionally_ignore_ee.js
new file mode 100644
index 00000000000..e5e3c8013f4
--- /dev/null
+++ b/tooling/eslint-config/conditionally_ignore_ee.js
@@ -0,0 +1,5 @@
+/* eslint-disable import/no-commonjs */
+
+const IS_EE = require('../../config/helpers/is_ee_env');
+
+module.exports = IS_EE ? {} : { ignorePatterns: ['ee/**/*.*'] };
diff --git a/tooling/lib/tooling/crystalball/coverage_lines_execution_detector.rb b/tooling/lib/tooling/crystalball/coverage_lines_execution_detector.rb
new file mode 100644
index 00000000000..47ddf568fe4
--- /dev/null
+++ b/tooling/lib/tooling/crystalball/coverage_lines_execution_detector.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'crystalball/map_generator/helpers/path_filter'
+
+module Tooling
+ module Crystalball
+ # Class for detecting code execution path based on coverage information diff
+ class CoverageLinesExecutionDetector
+ include ::Crystalball::MapGenerator::Helpers::PathFilter
+
+ attr_reader :exclude_prefixes
+
+ def initialize(*args, exclude_prefixes: [])
+ super(*args)
+ @exclude_prefixes = exclude_prefixes
+ end
+
+ # Detects files affected during example execution based on line coverage.
+ # Transforms absolute paths to relative.
+ # Exclude paths outside of repository and in excluded prefixes
+ #
+ # @param[Hash] hash of files affected before example execution
+ # @param[Hash] hash of files affected after example execution
+ # @return [Array<String>]
+ def detect(before, after)
+ file_names = after.keys
+ covered_files = file_names.reject { |file_name| same_coverage?(before, after, file_name) }
+ filter(covered_files)
+ end
+
+ private
+
+ def same_coverage?(before, after, file_name)
+ before[file_name] && before[file_name][:lines] == after[file_name][:lines]
+ end
+
+ def filter(paths)
+ super.reject do |file_name|
+ exclude_prefixes.any? { |prefix| file_name.start_with?(prefix) }
+ end
+ end
+ end
+ end
+end
diff --git a/tooling/lib/tooling/crystalball/coverage_lines_strategy.rb b/tooling/lib/tooling/crystalball/coverage_lines_strategy.rb
new file mode 100644
index 00000000000..ebcaab0b8d8
--- /dev/null
+++ b/tooling/lib/tooling/crystalball/coverage_lines_strategy.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'coverage'
+require 'crystalball/map_generator/coverage_strategy'
+require_relative './coverage_lines_execution_detector'
+
+module Tooling
+ module Crystalball
+ # Crystalball map generator strategy based on Crystalball::MapGenerator::CoverageStrategy,
+ # modified to use Coverage.start(lines: true)
+ # This maintains compatibility with SimpleCov on Ruby >= 2.5 with start arguments
+ # and SimpleCov.start uses Coverage.start(lines: true) by default
+ class CoverageLinesStrategy < ::Crystalball::MapGenerator::CoverageStrategy
+ def initialize(execution_detector = CoverageLinesExecutionDetector)
+ super(execution_detector)
+ end
+
+ def after_register
+ Coverage.start(lines: true)
+ end
+ end
+ end
+end
diff --git a/tooling/lib/tooling/helm3_client.rb b/tooling/lib/tooling/helm3_client.rb
index 802ff9b9661..d6671688794 100644
--- a/tooling/lib/tooling/helm3_client.rb
+++ b/tooling/lib/tooling/helm3_client.rb
@@ -3,7 +3,6 @@
require 'time'
require 'json'
require_relative '../../../lib/gitlab/popen' unless defined?(Gitlab::Popen)
-require_relative '../../../lib/gitlab/json' unless defined?(Gitlab::Json)
module Tooling
class Helm3Client
@@ -67,7 +66,7 @@ module Tooling
%(--output json),
*args
]
- releases = Gitlab::Json.parse(run_command(command))
+ releases = JSON.parse(run_command(command)) # rubocop:disable Gitlab/Json
releases.map do |release|
Release.new(*release.values_at(*RELEASE_JSON_ATTRIBUTES))
diff --git a/tooling/lib/tooling/test_map_generator.rb b/tooling/lib/tooling/test_map_generator.rb
new file mode 100644
index 00000000000..bd0415f6e67
--- /dev/null
+++ b/tooling/lib/tooling/test_map_generator.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'set'
+require 'yaml'
+
+module Tooling
+ class TestMapGenerator
+ def initialize
+ @mapping = Hash.new { |h, k| h[k] = Set.new }
+ end
+
+ def parse(yaml_files)
+ Array(yaml_files).each do |yaml_file|
+ data = File.read(yaml_file)
+ _metadata, example_groups = data.split("---\n").reject(&:empty?).map { |yml| YAML.safe_load(yml, [Symbol]) }
+
+ example_groups.each do |example_id, files|
+ files.each do |file|
+ spec_file = strip_example_uid(example_id)
+ @mapping[file] << spec_file
+ end
+ end
+ end
+ end
+
+ def mapping
+ @mapping.transform_values { |set| set.to_a }
+ end
+
+ private
+
+ def strip_example_uid(example_id)
+ example_id.gsub(/\[.+\]/, '')
+ end
+ end
+end
diff --git a/tooling/lib/tooling/test_map_packer.rb b/tooling/lib/tooling/test_map_packer.rb
new file mode 100644
index 00000000000..520d69610eb
--- /dev/null
+++ b/tooling/lib/tooling/test_map_packer.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Tooling
+ class TestMapPacker
+ SEPARATOR = '/'.freeze
+ MARKER = 1
+
+ def pack(map)
+ map.transform_values(&method(:create_tree_from_tests))
+ end
+
+ def unpack(compact_map)
+ compact_map.transform_values(&method(:retrieve_tests_from_tree))
+ end
+
+ private
+
+ def create_tree_from_tests(tests)
+ tests.inject({}) do |tree, test|
+ segments = test.split(SEPARATOR)
+ branch = create_branch_from_segments(segments)
+ deep_merge(tree, branch)
+ end
+ end
+
+ def create_branch_from_segments(segments)
+ segments.reverse.inject(MARKER) { |node, parent| { parent => node } }
+ end
+
+ def deep_merge(hash, other)
+ hash.merge(other) do |_, this_val, other_val|
+ if this_val.is_a?(Hash) && other_val.is_a?(Hash)
+ deep_merge(this_val, other_val)
+ else
+ other_val
+ end
+ end
+ end
+
+ def retrieve_tests_from_tree(tree)
+ traverse(tree).inject([]) do |tests, test|
+ tests << test
+ end
+ end
+
+ def traverse(tree, segments = [], &block)
+ return to_enum(__method__, tree, segments) unless block_given?
+
+ if tree == MARKER
+ return yield segments.join(SEPARATOR)
+ end
+
+ tree.each do |key, value|
+ traverse(value, segments + [key], &block)
+ end
+ end
+ end
+end
diff --git a/tooling/overcommit/Gemfile b/tooling/overcommit/Gemfile
index 615da316fd5..08f08018ffb 100644
--- a/tooling/overcommit/Gemfile
+++ b/tooling/overcommit/Gemfile
@@ -4,6 +4,6 @@
source 'https://rubygems.org'
gem 'overcommit'
-gem 'gitlab-styles', '~> 4.3.0', require: false
+gem 'gitlab-styles', '~> 5.1.0', require: false
gem 'scss_lint', '~> 0.56.0', require: false
gem 'haml_lint', '~> 0.34.0', require: false
diff --git a/tooling/overcommit/Gemfile.lock b/tooling/overcommit/Gemfile.lock
index d3a98855d96..5bada88e1dc 100644
--- a/tooling/overcommit/Gemfile.lock
+++ b/tooling/overcommit/Gemfile.lock
@@ -1,22 +1,22 @@
GEM
remote: https://rubygems.org/
specs:
- activesupport (6.0.3)
+ activesupport (6.0.3.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
- ast (2.4.0)
+ ast (2.4.1)
childprocess (3.0.0)
- concurrent-ruby (1.1.6)
+ concurrent-ruby (1.1.7)
ffi (1.12.2)
- gitlab-styles (4.3.0)
- rubocop (~> 0.82.0)
+ gitlab-styles (5.1.0)
+ rubocop (~> 0.89.1)
rubocop-gitlab-security (~> 0.1.0)
- rubocop-performance (~> 1.5.2)
- rubocop-rails (~> 2.5)
- rubocop-rspec (~> 1.36)
+ rubocop-performance (~> 1.8.1)
+ rubocop-rails (~> 2.8)
+ rubocop-rspec (~> 1.44)
haml (5.1.2)
temple (>= 0.8.0)
tilt
@@ -25,42 +25,47 @@ GEM
rainbow
rubocop (>= 0.50.0)
sysexits (~> 1.1)
- i18n (1.8.2)
+ i18n (1.8.5)
concurrent-ruby (~> 1.0)
iniparse (1.5.0)
- jaro_winkler (1.5.4)
- minitest (5.11.3)
+ minitest (5.14.2)
overcommit (0.53.0)
childprocess (>= 0.6.3, < 4)
iniparse (~> 1.4)
- parallel (1.19.1)
- parser (2.7.1.2)
- ast (~> 2.4.0)
- rack (2.0.9)
+ parallel (1.19.2)
+ parser (2.7.2.0)
+ ast (~> 2.4.1)
+ rack (2.2.3)
rainbow (3.0.0)
rake (12.3.3)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
+ regexp_parser (1.8.2)
rexml (3.2.4)
- rubocop (0.82.0)
- jaro_winkler (~> 1.5.1)
+ rubocop (0.89.1)
parallel (~> 1.10)
- parser (>= 2.7.0.1)
+ parser (>= 2.7.1.1)
rainbow (>= 2.2.2, < 4.0)
+ regexp_parser (>= 1.7)
rexml
+ rubocop-ast (>= 0.3.0, < 1.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
+ rubocop-ast (0.8.0)
+ parser (>= 2.7.1.5)
rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51)
- rubocop-performance (1.5.2)
- rubocop (>= 0.71.0)
- rubocop-rails (2.5.2)
- activesupport
+ rubocop-performance (1.8.1)
+ rubocop (>= 0.87.0)
+ rubocop-ast (>= 0.4.0)
+ rubocop-rails (2.8.1)
+ activesupport (>= 4.2.0)
rack (>= 1.1)
- rubocop (>= 0.72.0)
- rubocop-rspec (1.37.0)
- rubocop (>= 0.68.1)
+ rubocop (>= 0.87.0)
+ rubocop-rspec (1.44.1)
+ rubocop (~> 0.87)
+ rubocop-ast (>= 0.7.1)
ruby-progressbar (1.10.1)
sass (3.5.5)
sass-listen (~> 4.0.0)
@@ -74,19 +79,19 @@ GEM
temple (0.8.2)
thread_safe (0.3.6)
tilt (2.0.10)
- tzinfo (1.2.7)
+ tzinfo (1.2.8)
thread_safe (~> 0.1)
unicode-display_width (1.7.0)
- zeitwerk (2.3.0)
+ zeitwerk (2.4.1)
PLATFORMS
ruby
DEPENDENCIES
- gitlab-styles (~> 4.3.0)
+ gitlab-styles (~> 5.1.0)
haml_lint (~> 0.34.0)
overcommit
scss_lint (~> 0.56.0)
BUNDLED WITH
- 1.17.3
+ 2.1.4
diff --git a/vendor/assets/javascripts/snowplow/sp.js b/vendor/assets/javascripts/snowplow/sp.js
index 7ea5f1a464f..d9b4b583b4e 100644
--- a/vendor/assets/javascripts/snowplow/sp.js
+++ b/vendor/assets/javascripts/snowplow/sp.js
@@ -1,22 +1,162 @@
-/*
- * Snowplow - The world's most powerful web analytics platform
- *
+/**
* @description JavaScript tracker for Snowplow
- * @version 2.10.0
- * @author Alex Dean, Simon Andersson, Anthon Pang, Fred Blundun, Joshua Beemster, Michael Hadam
+ * @version 2.16.2
* @copyright Anthon Pang, Snowplow Analytics Ltd
* @license Simplified BSD
- *
- * For technical documentation:
- * https://github.com/snowplow/snowplow/wiki/javascript-tracker
- *
- * For the setup guide:
- * https://github.com/snowplow/snowplow/wiki/javascript-tracker-setup
- *
- * Minimum supported browsers:
- * - Firefox 27
- * - Chrome 32
- * - IE 9
- * - Safari 8
+ *
+ * Documentation: http://bit.ly/sp-js
*/
-"use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}!function o(i,c,s){function u(t,e){if(!c[t]){if(!i[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(l)return l(t,!0);var r=new Error("Cannot find module '"+t+"'");throw r.code="MODULE_NOT_FOUND",r}var a=c[t]={exports:{}};i[t][0].call(a.exports,function(e){return u(i[t][1][e]||e)},a,a.exports,o,i,c,s)}return c[t].exports}for(var l="function"==typeof require&&require,e=0;e<s.length;e++)u(s[e]);return u}({1:[function(e,t,n){this.cookie=function(e,t,n,r,a,o){return 1<arguments.length?document.cookie=e+"="+escape(t)+(n?"; expires="+new Date(+new Date+1e3*n).toUTCString():"")+(r?"; path="+r:"")+(a?"; domain="+a:"")+(o?"; secure":""):unescape((("; "+document.cookie).split("; "+e+"=")[1]||"").split(";")[0])}},{}],2:[function(e,t,n){var r={utf8:{stringToBytes:function(e){return r.bin.stringToBytes(unescape(encodeURIComponent(e)))},bytesToString:function(e){return decodeURIComponent(escape(r.bin.bytesToString(e)))}},bin:{stringToBytes:function(e){for(var t=[],n=0;n<e.length;n++)t.push(255&e.charCodeAt(n));return t},bytesToString:function(e){for(var t=[],n=0;n<e.length;n++)t.push(String.fromCharCode(e[n]));return t.join("")}}};t.exports=r},{}],3:[function(e,t,n){var o,r;o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",r={rotl:function(e,t){return e<<t|e>>>32-t},rotr:function(e,t){return e<<32-t|e>>>t},endian:function(e){if(e.constructor==Number)return 16711935&r.rotl(e,8)|4278255360&r.rotl(e,24);for(var t=0;t<e.length;t++)e[t]=r.endian(e[t]);return e},randomBytes:function(e){for(var t=[];0<e;e--)t.push(Math.floor(256*Math.random()));return t},bytesToWords:function(e){for(var t=[],n=0,r=0;n<e.length;n++,r+=8)t[r>>>5]|=e[n]<<24-r%32;return t},wordsToBytes:function(e){for(var t=[],n=0;n<32*e.length;n+=8)t.push(e[n>>>5]>>>24-n%32&255);return t},bytesToHex:function(e){for(var t=[],n=0;n<e.length;n++)t.push((e[n]>>>4).toString(16)),t.push((15&e[n]).toString(16));return t.join("")},hexToBytes:function(e){for(var t=[],n=0;n<e.length;n+=2)t.push(parseInt(e.substr(n,2),16));return t},bytesToBase64:function(e){for(var t=[],n=0;n<e.length;n+=3)for(var r=e[n]<<16|e[n+1]<<8|e[n+2],a=0;a<4;a++)8*n+6*a<=8*e.length?t.push(o.charAt(r>>>6*(3-a)&63)):t.push("=");return t.join("")},base64ToBytes:function(e){e=e.replace(/[^A-Z0-9+\/]/gi,"");for(var t=[],n=0,r=0;n<e.length;r=++n%4)0!=r&&t.push((o.indexOf(e.charAt(n-1))&Math.pow(2,-2*r+8)-1)<<2*r|o.indexOf(e.charAt(n))>>>6-2*r);return t}},t.exports=r},{}],4:[function(e,t,n){var r,a,o,i,c,s;r=this,a=function(e){var t=-e.getTimezoneOffset();return null!==t?t:0},o=function(e,t,n){var r=new Date;return void 0!==e&&r.setFullYear(e),r.setMonth(t),r.setDate(n),r},i=function(e){return a(o(e,0,2))},c=function(e){return a(o(e,5,2))},(s={determine:function(){var e,t,n,r=(e=i(),t=c(),(n=e-t)<0?e+",1":0<n?t+",1,s":e+",0");return new s.TimeZone(s.olson.timezones[r])},date_is_dst:function(e){var t=7<e.getMonth(),n=t?c(e.getFullYear()):i(e.getFullYear()),r=n-a(e);return n<0||t?0!==r:r<0},dst_start_for:function(e){var t=new Date(2010,6,15,1,0,0,0);return{"America/Denver":new Date(2011,2,13,3,0,0,0),"America/Mazatlan":new Date(2011,3,3,3,0,0,0),"America/Chicago":new Date(2011,2,13,3,0,0,0),"America/Mexico_City":new Date(2011,3,3,3,0,0,0),"America/Asuncion":new Date(2012,9,7,3,0,0,0),"America/Santiago":new Date(2012,9,3,3,0,0,0),"America/Campo_Grande":new Date(2012,9,21,5,0,0,0),"America/Montevideo":new Date(2011,9,2,3,0,0,0),"America/Sao_Paulo":new Date(2011,9,16,5,0,0,0),"America/Los_Angeles":new Date(2011,2,13,8,0,0,0),"America/Santa_Isabel":new Date(2011,3,5,8,0,0,0),"America/Havana":new Date(2012,2,10,2,0,0,0),"America/New_York":new Date(2012,2,10,7,0,0,0),"Europe/Helsinki":new Date(2013,2,31,5,0,0,0),"Pacific/Auckland":new Date(2011,8,26,7,0,0,0),"America/Halifax":new Date(2011,2,13,6,0,0,0),"America/Goose_Bay":new Date(2011,2,13,2,1,0,0),"America/Miquelon":new Date(2011,2,13,5,0,0,0),"America/Godthab":new Date(2011,2,27,1,0,0,0),"Europe/Moscow":t,"Asia/Amman":new Date(2013,2,29,1,0,0,0),"Asia/Beirut":new Date(2013,2,31,2,0,0,0),"Asia/Damascus":new Date(2013,3,6,2,0,0,0),"Asia/Jerusalem":new Date(2013,2,29,5,0,0,0),"Asia/Yekaterinburg":t,"Asia/Omsk":t,"Asia/Krasnoyarsk":t,"Asia/Irkutsk":t,"Asia/Yakutsk":t,"Asia/Vladivostok":t,"Asia/Baku":new Date(2013,2,31,4,0,0),"Asia/Yerevan":new Date(2013,2,31,3,0,0),"Asia/Kamchatka":t,"Asia/Gaza":new Date(2010,2,27,4,0,0),"Africa/Cairo":new Date(2010,4,1,3,0,0),"Europe/Minsk":t,"Pacific/Apia":new Date(2010,10,1,1,0,0,0),"Pacific/Fiji":new Date(2010,11,1,0,0,0),"Australia/Perth":new Date(2008,10,1,1,0,0,0)}[e]},TimeZone:function(e){var a={"America/Denver":["America/Denver","America/Mazatlan"],"America/Chicago":["America/Chicago","America/Mexico_City"],"America/Santiago":["America/Santiago","America/Asuncion","America/Campo_Grande"],"America/Montevideo":["America/Montevideo","America/Sao_Paulo"],"Asia/Beirut":["Asia/Amman","Asia/Jerusalem","Asia/Beirut","Europe/Helsinki","Asia/Damascus"],"Pacific/Auckland":["Pacific/Auckland","Pacific/Fiji"],"America/Los_Angeles":["America/Los_Angeles","America/Santa_Isabel"],"America/New_York":["America/Havana","America/New_York"],"America/Halifax":["America/Goose_Bay","America/Halifax"],"America/Godthab":["America/Miquelon","America/Godthab"],"Asia/Dubai":["Europe/Moscow"],"Asia/Dhaka":["Asia/Yekaterinburg"],"Asia/Jakarta":["Asia/Omsk"],"Asia/Shanghai":["Asia/Krasnoyarsk","Australia/Perth"],"Asia/Tokyo":["Asia/Irkutsk"],"Australia/Brisbane":["Asia/Yakutsk"],"Pacific/Noumea":["Asia/Vladivostok"],"Pacific/Tarawa":["Asia/Kamchatka","Pacific/Fiji"],"Pacific/Tongatapu":["Pacific/Apia"],"Asia/Baghdad":["Europe/Minsk"],"Asia/Baku":["Asia/Yerevan","Asia/Baku"],"Africa/Johannesburg":["Asia/Gaza","Africa/Cairo"]},o=e;return void 0!==a[o]&&function(){for(var e=a[o],t=e.length,n=0,r=e[0];n<t;n+=1)if(r=e[n],s.date_is_dst(s.dst_start_for(r)))return o=r}(),{name:function(){return o}}},olson:{}}).olson.timezones={"-720,0":"Pacific/Majuro","-660,0":"Pacific/Pago_Pago","-600,1":"America/Adak","-600,0":"Pacific/Honolulu","-570,0":"Pacific/Marquesas","-540,0":"Pacific/Gambier","-540,1":"America/Anchorage","-480,1":"America/Los_Angeles","-480,0":"Pacific/Pitcairn","-420,0":"America/Phoenix","-420,1":"America/Denver","-360,0":"America/Guatemala","-360,1":"America/Chicago","-360,1,s":"Pacific/Easter","-300,0":"America/Bogota","-300,1":"America/New_York","-270,0":"America/Caracas","-240,1":"America/Halifax","-240,0":"America/Santo_Domingo","-240,1,s":"America/Santiago","-210,1":"America/St_Johns","-180,1":"America/Godthab","-180,0":"America/Argentina/Buenos_Aires","-180,1,s":"America/Montevideo","-120,0":"America/Noronha","-120,1":"America/Noronha","-60,1":"Atlantic/Azores","-60,0":"Atlantic/Cape_Verde","0,0":"UTC","0,1":"Europe/London","60,1":"Europe/Berlin","60,0":"Africa/Lagos","60,1,s":"Africa/Windhoek","120,1":"Asia/Beirut","120,0":"Africa/Johannesburg","180,0":"Asia/Baghdad","180,1":"Europe/Moscow","210,1":"Asia/Tehran","240,0":"Asia/Dubai","240,1":"Asia/Baku","270,0":"Asia/Kabul","300,1":"Asia/Yekaterinburg","300,0":"Asia/Karachi","330,0":"Asia/Kolkata","345,0":"Asia/Kathmandu","360,0":"Asia/Dhaka","360,1":"Asia/Omsk","390,0":"Asia/Rangoon","420,1":"Asia/Krasnoyarsk","420,0":"Asia/Jakarta","480,0":"Asia/Shanghai","480,1":"Asia/Irkutsk","525,0":"Australia/Eucla","525,1,s":"Australia/Eucla","540,1":"Asia/Yakutsk","540,0":"Asia/Tokyo","570,0":"Australia/Darwin","570,1,s":"Australia/Adelaide","600,0":"Australia/Brisbane","600,1":"Asia/Vladivostok","600,1,s":"Australia/Sydney","630,1,s":"Australia/Lord_Howe","660,1":"Asia/Kamchatka","660,0":"Pacific/Noumea","690,0":"Pacific/Norfolk","720,1,s":"Pacific/Auckland","720,0":"Pacific/Tarawa","765,1,s":"Pacific/Chatham","780,0":"Pacific/Tongatapu","780,1,s":"Pacific/Apia","840,0":"Pacific/Kiritimati"},void 0!==n?n.jstz=s:r.jstz=s},{}],5:[function(e,t,n){var r=e("./_getNative")(e("./_root"),"DataView");t.exports=r},{"./_getNative":68,"./_root":105}],6:[function(e,t,n){var r=e("./_hashClear"),a=e("./_hashDelete"),o=e("./_hashGet"),i=e("./_hashHas"),c=e("./_hashSet");function s(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}s.prototype.clear=r,s.prototype.delete=a,s.prototype.get=o,s.prototype.has=i,s.prototype.set=c,t.exports=s},{"./_hashClear":75,"./_hashDelete":76,"./_hashGet":77,"./_hashHas":78,"./_hashSet":79}],7:[function(e,t,n){var r=e("./_listCacheClear"),a=e("./_listCacheDelete"),o=e("./_listCacheGet"),i=e("./_listCacheHas"),c=e("./_listCacheSet");function s(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}s.prototype.clear=r,s.prototype.delete=a,s.prototype.get=o,s.prototype.has=i,s.prototype.set=c,t.exports=s},{"./_listCacheClear":87,"./_listCacheDelete":88,"./_listCacheGet":89,"./_listCacheHas":90,"./_listCacheSet":91}],8:[function(e,t,n){var r=e("./_getNative")(e("./_root"),"Map");t.exports=r},{"./_getNative":68,"./_root":105}],9:[function(e,t,n){var r=e("./_mapCacheClear"),a=e("./_mapCacheDelete"),o=e("./_mapCacheGet"),i=e("./_mapCacheHas"),c=e("./_mapCacheSet");function s(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}s.prototype.clear=r,s.prototype.delete=a,s.prototype.get=o,s.prototype.has=i,s.prototype.set=c,t.exports=s},{"./_mapCacheClear":92,"./_mapCacheDelete":93,"./_mapCacheGet":94,"./_mapCacheHas":95,"./_mapCacheSet":96}],10:[function(e,t,n){var r=e("./_getNative")(e("./_root"),"Promise");t.exports=r},{"./_getNative":68,"./_root":105}],11:[function(e,t,n){var r=e("./_getNative")(e("./_root"),"Set");t.exports=r},{"./_getNative":68,"./_root":105}],12:[function(e,t,n){var r=e("./_MapCache"),a=e("./_setCacheAdd"),o=e("./_setCacheHas");function i(e){var t=-1,n=null==e?0:e.length;for(this.__data__=new r;++t<n;)this.add(e[t])}i.prototype.add=i.prototype.push=a,i.prototype.has=o,t.exports=i},{"./_MapCache":9,"./_setCacheAdd":106,"./_setCacheHas":107}],13:[function(e,t,n){var r=e("./_ListCache"),a=e("./_stackClear"),o=e("./_stackDelete"),i=e("./_stackGet"),c=e("./_stackHas"),s=e("./_stackSet");function u(e){var t=this.__data__=new r(e);this.size=t.size}u.prototype.clear=a,u.prototype.delete=o,u.prototype.get=i,u.prototype.has=c,u.prototype.set=s,t.exports=u},{"./_ListCache":7,"./_stackClear":109,"./_stackDelete":110,"./_stackGet":111,"./_stackHas":112,"./_stackSet":113}],14:[function(e,t,n){var r=e("./_root").Symbol;t.exports=r},{"./_root":105}],15:[function(e,t,n){var r=e("./_root").Uint8Array;t.exports=r},{"./_root":105}],16:[function(e,t,n){var r=e("./_getNative")(e("./_root"),"WeakMap");t.exports=r},{"./_getNative":68,"./_root":105}],17:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=null==e?0:e.length;++n<r&&!1!==t(e[n],n,e););return e}},{}],18:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=null==e?0:e.length;++n<r;)if(!t(e[n],n,e))return!1;return!0}},{}],19:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=null==e?0:e.length,a=0,o=[];++n<r;){var i=e[n];t(i,n,e)&&(o[a++]=i)}return o}},{}],20:[function(e,t,n){var l=e("./_baseTimes"),f=e("./isArguments"),d=e("./isArray"),p=e("./isBuffer"),h=e("./_isIndex"),m=e("./isTypedArray"),v=Object.prototype.hasOwnProperty;t.exports=function(e,t){var n=d(e),r=!n&&f(e),a=!n&&!r&&p(e),o=!n&&!r&&!a&&m(e),i=n||r||a||o,c=i?l(e.length,String):[],s=c.length;for(var u in e)!t&&!v.call(e,u)||i&&("length"==u||a&&("offset"==u||"parent"==u)||o&&("buffer"==u||"byteLength"==u||"byteOffset"==u)||h(u,s))||c.push(u);return c}},{"./_baseTimes":50,"./_isIndex":80,"./isArguments":128,"./isArray":129,"./isBuffer":131,"./isTypedArray":140}],21:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=null==e?0:e.length,a=Array(r);++n<r;)a[n]=t(e[n],n,e);return a}},{}],22:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=t.length,a=e.length;++n<r;)e[a+n]=t[n];return e}},{}],23:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=null==e?0:e.length;++n<r;)if(t(e[n],n,e))return!0;return!1}},{}],24:[function(e,t,n){var r=e("./eq");t.exports=function(e,t){for(var n=e.length;n--;)if(r(e[n][0],t))return n;return-1}},{"./eq":118}],25:[function(e,t,n){var r=e("./_defineProperty");t.exports=function(e,t,n){"__proto__"==t&&r?r(e,t,{configurable:!0,enumerable:!0,value:n,writable:!0}):e[t]=n}},{"./_defineProperty":60}],26:[function(e,t,n){var r=e("./_baseForOwn"),a=e("./_createBaseEach")(r);t.exports=a},{"./_baseForOwn":31,"./_createBaseEach":57}],27:[function(e,t,n){var o=e("./_baseEach");t.exports=function(e,r){var a=!0;return o(e,function(e,t,n){return a=!!r(e,t,n)}),a}},{"./_baseEach":26}],28:[function(e,t,n){var o=e("./_baseEach");t.exports=function(e,r){var a=[];return o(e,function(e,t,n){r(e,t,n)&&a.push(e)}),a}},{"./_baseEach":26}],29:[function(e,t,n){t.exports=function(e,t,n,r){for(var a=e.length,o=n+(r?1:-1);r?o--:++o<a;)if(t(e[o],o,e))return o;return-1}},{}],30:[function(e,t,n){var r=e("./_createBaseFor")();t.exports=r},{"./_createBaseFor":58}],31:[function(e,t,n){var r=e("./_baseFor"),a=e("./keys");t.exports=function(e,t){return e&&r(e,t,a)}},{"./_baseFor":30,"./keys":142}],32:[function(e,t,n){var a=e("./_castPath"),o=e("./_toKey");t.exports=function(e,t){for(var n=0,r=(t=a(t,e)).length;null!=e&&n<r;)e=e[o(t[n++])];return n&&n==r?e:void 0}},{"./_castPath":55,"./_toKey":115}],33:[function(e,t,n){var a=e("./_arrayPush"),o=e("./isArray");t.exports=function(e,t,n){var r=t(e);return o(e)?r:a(r,n(e))}},{"./_arrayPush":22,"./isArray":129}],34:[function(e,t,n){var r=e("./_Symbol"),a=e("./_getRawTag"),o=e("./_objectToString"),i=r?r.toStringTag:void 0;t.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?a(e):o(e)}},{"./_Symbol":14,"./_getRawTag":70,"./_objectToString":103}],35:[function(e,t,n){var r=Object.prototype.hasOwnProperty;t.exports=function(e,t){return null!=e&&r.call(e,t)}},{}],36:[function(e,t,n){t.exports=function(e,t){return null!=e&&t in Object(e)}},{}],37:[function(e,t,n){var r=e("./_baseGetTag"),a=e("./isObjectLike");t.exports=function(e){return a(e)&&"[object Arguments]"==r(e)}},{"./_baseGetTag":34,"./isObjectLike":136}],38:[function(e,t,n){var i=e("./_baseIsEqualDeep"),c=e("./isObjectLike");t.exports=function e(t,n,r,a,o){return t===n||(null==t||null==n||!c(t)&&!c(n)?t!=t&&n!=n:i(t,n,r,a,e,o))}},{"./_baseIsEqualDeep":39,"./isObjectLike":136}],39:[function(e,t,n){var g=e("./_Stack"),y=e("./_equalArrays"),_=e("./_equalByTag"),b=e("./_equalObjects"),w=e("./_getTag"),k=e("./isArray"),A=e("./isBuffer"),x=e("./isTypedArray"),C="[object Arguments]",S="[object Array]",j="[object Object]",T=Object.prototype.hasOwnProperty;t.exports=function(e,t,n,r,a,o){var i=k(e),c=k(t),s=i?S:w(e),u=c?S:w(t),l=(s=s==C?j:s)==j,f=(u=u==C?j:u)==j,d=s==u;if(d&&A(e)){if(!A(t))return!1;l=!(i=!0)}if(d&&!l)return o||(o=new g),i||x(e)?y(e,t,n,r,a,o):_(e,t,s,n,r,a,o);if(!(1&n)){var p=l&&T.call(e,"__wrapped__"),h=f&&T.call(t,"__wrapped__");if(p||h){var m=p?e.value():e,v=h?t.value():t;return o||(o=new g),a(m,v,n,r,o)}}return!!d&&(o||(o=new g),b(e,t,n,r,a,o))}},{"./_Stack":13,"./_equalArrays":61,"./_equalByTag":62,"./_equalObjects":63,"./_getTag":72,"./isArray":129,"./isBuffer":131,"./isTypedArray":140}],40:[function(e,t,n){var p=e("./_Stack"),h=e("./_baseIsEqual");t.exports=function(e,t,n,r){var a=n.length,o=a,i=!r;if(null==e)return!o;for(e=Object(e);a--;){var c=n[a];if(i&&c[2]?c[1]!==e[c[0]]:!(c[0]in e))return!1}for(;++a<o;){var s=(c=n[a])[0],u=e[s],l=c[1];if(i&&c[2]){if(void 0===u&&!(s in e))return!1}else{var f=new p;if(r)var d=r(u,l,s,e,t,f);if(!(void 0===d?h(l,u,3,r,f):d))return!1}}return!0}},{"./_Stack":13,"./_baseIsEqual":38}],41:[function(e,t,n){var r=e("./isFunction"),a=e("./_isMasked"),o=e("./isObject"),i=e("./_toSource"),c=/^\[object .+?Constructor\]$/,s=Function.prototype,u=Object.prototype,l=s.toString,f=u.hasOwnProperty,d=RegExp("^"+l.call(f).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");t.exports=function(e){return!(!o(e)||a(e))&&(r(e)?d:c).test(i(e))}},{"./_isMasked":84,"./_toSource":116,"./isFunction":133,"./isObject":135}],42:[function(e,t,n){var r=e("./_baseGetTag"),a=e("./isLength"),o=e("./isObjectLike"),i={};i["[object Float32Array]"]=i["[object Float64Array]"]=i["[object Int8Array]"]=i["[object Int16Array]"]=i["[object Int32Array]"]=i["[object Uint8Array]"]=i["[object Uint8ClampedArray]"]=i["[object Uint16Array]"]=i["[object Uint32Array]"]=!0,i["[object Arguments]"]=i["[object Array]"]=i["[object ArrayBuffer]"]=i["[object Boolean]"]=i["[object DataView]"]=i["[object Date]"]=i["[object Error]"]=i["[object Function]"]=i["[object Map]"]=i["[object Number]"]=i["[object Object]"]=i["[object RegExp]"]=i["[object Set]"]=i["[object String]"]=i["[object WeakMap]"]=!1,t.exports=function(e){return o(e)&&a(e.length)&&!!i[r(e)]}},{"./_baseGetTag":34,"./isLength":134,"./isObjectLike":136}],43:[function(e,t,n){var r=e("./_baseMatches"),a=e("./_baseMatchesProperty"),o=e("./identity"),i=e("./isArray"),c=e("./property");t.exports=function(e){return"function"==typeof e?e:null==e?o:"object"==_typeof(e)?i(e)?a(e[0],e[1]):r(e):c(e)}},{"./_baseMatches":46,"./_baseMatchesProperty":47,"./identity":127,"./isArray":129,"./property":146}],44:[function(e,t,n){var r=e("./_isPrototype"),a=e("./_nativeKeys"),o=Object.prototype.hasOwnProperty;t.exports=function(e){if(!r(e))return a(e);var t=[];for(var n in Object(e))o.call(e,n)&&"constructor"!=n&&t.push(n);return t}},{"./_isPrototype":85,"./_nativeKeys":101}],45:[function(e,t,n){var i=e("./_baseEach"),c=e("./isArrayLike");t.exports=function(e,r){var a=-1,o=c(e)?Array(e.length):[];return i(e,function(e,t,n){o[++a]=r(e,t,n)}),o}},{"./_baseEach":26,"./isArrayLike":130}],46:[function(e,t,n){var r=e("./_baseIsMatch"),a=e("./_getMatchData"),o=e("./_matchesStrictComparable");t.exports=function(t){var n=a(t);return 1==n.length&&n[0][2]?o(n[0][0],n[0][1]):function(e){return e===t||r(e,t,n)}}},{"./_baseIsMatch":40,"./_getMatchData":67,"./_matchesStrictComparable":98}],47:[function(e,t,n){var a=e("./_baseIsEqual"),o=e("./get"),i=e("./hasIn"),c=e("./_isKey"),s=e("./_isStrictComparable"),u=e("./_matchesStrictComparable"),l=e("./_toKey");t.exports=function(n,r){return c(n)&&s(r)?u(l(n),r):function(e){var t=o(e,n);return void 0===t&&t===r?i(e,n):a(r,t,3)}}},{"./_baseIsEqual":38,"./_isKey":82,"./_isStrictComparable":86,"./_matchesStrictComparable":98,"./_toKey":115,"./get":124,"./hasIn":126}],48:[function(e,t,n){t.exports=function(t){return function(e){return null==e?void 0:e[t]}}},{}],49:[function(e,t,n){var r=e("./_baseGet");t.exports=function(t){return function(e){return r(e,t)}}},{"./_baseGet":32}],50:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=Array(e);++n<e;)r[n]=t(n);return r}},{}],51:[function(e,t,n){var r=e("./_Symbol"),a=e("./_arrayMap"),o=e("./isArray"),i=e("./isSymbol"),c=1/0,s=r?r.prototype:void 0,u=s?s.toString:void 0;t.exports=function e(t){if("string"==typeof t)return t;if(o(t))return a(t,e)+"";if(i(t))return u?u.call(t):"";var n=t+"";return"0"==n&&1/t==-c?"-0":n}},{"./_Symbol":14,"./_arrayMap":21,"./isArray":129,"./isSymbol":139}],52:[function(e,t,n){t.exports=function(t){return function(e){return t(e)}}},{}],53:[function(e,t,n){t.exports=function(e,t){return e.has(t)}},{}],54:[function(e,t,n){var r=e("./identity");t.exports=function(e){return"function"==typeof e?e:r}},{"./identity":127}],55:[function(e,t,n){var r=e("./isArray"),a=e("./_isKey"),o=e("./_stringToPath"),i=e("./toString");t.exports=function(e,t){return r(e)?e:a(e,t)?[e]:o(i(e))}},{"./_isKey":82,"./_stringToPath":114,"./isArray":129,"./toString":152}],56:[function(e,t,n){var r=e("./_root")["__core-js_shared__"];t.exports=r},{"./_root":105}],57:[function(e,t,n){var c=e("./isArrayLike");t.exports=function(o,i){return function(e,t){if(null==e)return e;if(!c(e))return o(e,t);for(var n=e.length,r=i?n:-1,a=Object(e);(i?r--:++r<n)&&!1!==t(a[r],r,a););return e}}},{"./isArrayLike":130}],58:[function(e,t,n){t.exports=function(s){return function(e,t,n){for(var r=-1,a=Object(e),o=n(e),i=o.length;i--;){var c=o[s?i:++r];if(!1===t(a[c],c,a))break}return e}}},{}],59:[function(e,t,n){var c=e("./_baseIteratee"),s=e("./isArrayLike"),u=e("./keys");t.exports=function(i){return function(e,t,n){var r=Object(e);if(!s(e)){var a=c(t,3);e=u(e),t=function(e){return a(r[e],e,r)}}var o=i(e,t,n);return-1<o?r[a?e[o]:o]:void 0}}},{"./_baseIteratee":43,"./isArrayLike":130,"./keys":142}],60:[function(e,t,n){var r=e("./_getNative"),a=function(){try{var e=r(Object,"defineProperty");return e({},"",{}),e}catch(e){}}();t.exports=a},{"./_getNative":68}],61:[function(e,t,n){var v=e("./_SetCache"),g=e("./_arraySome"),y=e("./_cacheHas");t.exports=function(e,t,n,r,a,o){var i=1&n,c=e.length,s=t.length;if(c!=s&&!(i&&c<s))return!1;var u=o.get(e);if(u&&o.get(t))return u==t;var l=-1,f=!0,d=2&n?new v:void 0;for(o.set(e,t),o.set(t,e);++l<c;){var p=e[l],h=t[l];if(r)var m=i?r(h,p,l,t,e,o):r(p,h,l,e,t,o);if(void 0!==m){if(m)continue;f=!1;break}if(d){if(!g(t,function(e,t){if(!y(d,t)&&(p===e||a(p,e,n,r,o)))return d.push(t)})){f=!1;break}}else if(p!==h&&!a(p,h,n,r,o)){f=!1;break}}return o.delete(e),o.delete(t),f}},{"./_SetCache":12,"./_arraySome":23,"./_cacheHas":53}],62:[function(e,t,n){var r=e("./_Symbol"),f=e("./_Uint8Array"),d=e("./eq"),p=e("./_equalArrays"),h=e("./_mapToArray"),m=e("./_setToArray"),a=r?r.prototype:void 0,v=a?a.valueOf:void 0;t.exports=function(e,t,n,r,a,o,i){switch(n){case"[object DataView]":if(e.byteLength!=t.byteLength||e.byteOffset!=t.byteOffset)return!1;e=e.buffer,t=t.buffer;case"[object ArrayBuffer]":return!(e.byteLength!=t.byteLength||!o(new f(e),new f(t)));case"[object Boolean]":case"[object Date]":case"[object Number]":return d(+e,+t);case"[object Error]":return e.name==t.name&&e.message==t.message;case"[object RegExp]":case"[object String]":return e==t+"";case"[object Map]":var c=h;case"[object Set]":var s=1&r;if(c||(c=m),e.size!=t.size&&!s)return!1;var u=i.get(e);if(u)return u==t;r|=2,i.set(e,t);var l=p(c(e),c(t),r,a,o,i);return i.delete(e),l;case"[object Symbol]":if(v)return v.call(e)==v.call(t)}return!1}},{"./_Symbol":14,"./_Uint8Array":15,"./_equalArrays":61,"./_mapToArray":97,"./_setToArray":108,"./eq":118}],63:[function(e,t,n){var _=e("./_getAllKeys"),b=Object.prototype.hasOwnProperty;t.exports=function(e,t,n,r,a,o){var i=1&n,c=_(e),s=c.length;if(s!=_(t).length&&!i)return!1;for(var u=s;u--;){var l=c[u];if(!(i?l in t:b.call(t,l)))return!1}var f=o.get(e);if(f&&o.get(t))return f==t;var d=!0;o.set(e,t),o.set(t,e);for(var p=i;++u<s;){var h=e[l=c[u]],m=t[l];if(r)var v=i?r(m,h,l,t,e,o):r(h,m,l,e,t,o);if(!(void 0===v?h===m||a(h,m,n,r,o):v)){d=!1;break}p||(p="constructor"==l)}if(d&&!p){var g=e.constructor,y=t.constructor;g!=y&&"constructor"in e&&"constructor"in t&&!("function"==typeof g&&g instanceof g&&"function"==typeof y&&y instanceof y)&&(d=!1)}return o.delete(e),o.delete(t),d}},{"./_getAllKeys":65}],64:[function(e,n,t){(function(e){var t="object"==_typeof(e)&&e&&e.Object===Object&&e;n.exports=t}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],65:[function(e,t,n){var r=e("./_baseGetAllKeys"),a=e("./_getSymbols"),o=e("./keys");t.exports=function(e){return r(e,o,a)}},{"./_baseGetAllKeys":33,"./_getSymbols":71,"./keys":142}],66:[function(e,t,n){var r=e("./_isKeyable");t.exports=function(e,t){var n=e.__data__;return r(t)?n["string"==typeof t?"string":"hash"]:n.map}},{"./_isKeyable":83}],67:[function(e,t,n){var o=e("./_isStrictComparable"),i=e("./keys");t.exports=function(e){for(var t=i(e),n=t.length;n--;){var r=t[n],a=e[r];t[n]=[r,a,o(a)]}return t}},{"./_isStrictComparable":86,"./keys":142}],68:[function(e,t,n){var r=e("./_baseIsNative"),a=e("./_getValue");t.exports=function(e,t){var n=a(e,t);return r(n)?n:void 0}},{"./_baseIsNative":41,"./_getValue":73}],69:[function(e,t,n){var r=e("./_overArg")(Object.getPrototypeOf,Object);t.exports=r},{"./_overArg":104}],70:[function(e,t,n){var r=e("./_Symbol"),a=Object.prototype,o=a.hasOwnProperty,i=a.toString,c=r?r.toStringTag:void 0;t.exports=function(e){var t=o.call(e,c),n=e[c];try{var r=!(e[c]=void 0)}catch(e){}var a=i.call(e);return r&&(t?e[c]=n:delete e[c]),a}},{"./_Symbol":14}],71:[function(e,t,n){var r=e("./_arrayFilter"),a=e("./stubArray"),o=Object.prototype.propertyIsEnumerable,i=Object.getOwnPropertySymbols,c=i?function(t){return null==t?[]:(t=Object(t),r(i(t),function(e){return o.call(t,e)}))}:a;t.exports=c},{"./_arrayFilter":19,"./stubArray":147}],72:[function(e,t,n){var r=e("./_DataView"),a=e("./_Map"),o=e("./_Promise"),i=e("./_Set"),c=e("./_WeakMap"),s=e("./_baseGetTag"),u=e("./_toSource"),l="[object Map]",f="[object Promise]",d="[object Set]",p="[object WeakMap]",h="[object DataView]",m=u(r),v=u(a),g=u(o),y=u(i),_=u(c),b=s;(r&&b(new r(new ArrayBuffer(1)))!=h||a&&b(new a)!=l||o&&b(o.resolve())!=f||i&&b(new i)!=d||c&&b(new c)!=p)&&(b=function(e){var t=s(e),n="[object Object]"==t?e.constructor:void 0,r=n?u(n):"";if(r)switch(r){case m:return h;case v:return l;case g:return f;case y:return d;case _:return p}return t}),t.exports=b},{"./_DataView":5,"./_Map":8,"./_Promise":10,"./_Set":11,"./_WeakMap":16,"./_baseGetTag":34,"./_toSource":116}],73:[function(e,t,n){t.exports=function(e,t){return null==e?void 0:e[t]}},{}],74:[function(e,t,n){var c=e("./_castPath"),s=e("./isArguments"),u=e("./isArray"),l=e("./_isIndex"),f=e("./isLength"),d=e("./_toKey");t.exports=function(e,t,n){for(var r=-1,a=(t=c(t,e)).length,o=!1;++r<a;){var i=d(t[r]);if(!(o=null!=e&&n(e,i)))break;e=e[i]}return o||++r!=a?o:!!(a=null==e?0:e.length)&&f(a)&&l(i,a)&&(u(e)||s(e))}},{"./_castPath":55,"./_isIndex":80,"./_toKey":115,"./isArguments":128,"./isArray":129,"./isLength":134}],75:[function(e,t,n){var r=e("./_nativeCreate");t.exports=function(){this.__data__=r?r(null):{},this.size=0}},{"./_nativeCreate":100}],76:[function(e,t,n){t.exports=function(e){var t=this.has(e)&&delete this.__data__[e];return this.size-=t?1:0,t}},{}],77:[function(e,t,n){var r=e("./_nativeCreate"),a=Object.prototype.hasOwnProperty;t.exports=function(e){var t=this.__data__;if(r){var n=t[e];return"__lodash_hash_undefined__"===n?void 0:n}return a.call(t,e)?t[e]:void 0}},{"./_nativeCreate":100}],78:[function(e,t,n){var r=e("./_nativeCreate"),a=Object.prototype.hasOwnProperty;t.exports=function(e){var t=this.__data__;return r?void 0!==t[e]:a.call(t,e)}},{"./_nativeCreate":100}],79:[function(e,t,n){var r=e("./_nativeCreate");t.exports=function(e,t){var n=this.__data__;return this.size+=this.has(e)?0:1,n[e]=r&&void 0===t?"__lodash_hash_undefined__":t,this}},{"./_nativeCreate":100}],80:[function(e,t,n){var r=/^(?:0|[1-9]\d*)$/;t.exports=function(e,t){var n=_typeof(e);return!!(t=null==t?9007199254740991:t)&&("number"==n||"symbol"!=n&&r.test(e))&&-1<e&&e%1==0&&e<t}},{}],81:[function(e,t,n){var a=e("./eq"),o=e("./isArrayLike"),i=e("./_isIndex"),c=e("./isObject");t.exports=function(e,t,n){if(!c(n))return!1;var r=_typeof(t);return!!("number"==r?o(n)&&i(t,n.length):"string"==r&&t in n)&&a(n[t],e)}},{"./_isIndex":80,"./eq":118,"./isArrayLike":130,"./isObject":135}],82:[function(e,t,n){var r=e("./isArray"),a=e("./isSymbol"),o=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,i=/^\w*$/;t.exports=function(e,t){if(r(e))return!1;var n=_typeof(e);return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=e&&!a(e))||i.test(e)||!o.test(e)||null!=t&&e in Object(t)}},{"./isArray":129,"./isSymbol":139}],83:[function(e,t,n){t.exports=function(e){var t=_typeof(e);return"string"==t||"number"==t||"symbol"==t||"boolean"==t?"__proto__"!==e:null===e}},{}],84:[function(e,t,n){var r,a=e("./_coreJsData"),o=(r=/[^.]+$/.exec(a&&a.keys&&a.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"";t.exports=function(e){return!!o&&o in e}},{"./_coreJsData":56}],85:[function(e,t,n){var r=Object.prototype;t.exports=function(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||r)}},{}],86:[function(e,t,n){var r=e("./isObject");t.exports=function(e){return e==e&&!r(e)}},{"./isObject":135}],87:[function(e,t,n){t.exports=function(){this.__data__=[],this.size=0}},{}],88:[function(e,t,n){var r=e("./_assocIndexOf"),a=Array.prototype.splice;t.exports=function(e){var t=this.__data__,n=r(t,e);return!(n<0||(n==t.length-1?t.pop():a.call(t,n,1),--this.size,0))}},{"./_assocIndexOf":24}],89:[function(e,t,n){var r=e("./_assocIndexOf");t.exports=function(e){var t=this.__data__,n=r(t,e);return n<0?void 0:t[n][1]}},{"./_assocIndexOf":24}],90:[function(e,t,n){var r=e("./_assocIndexOf");t.exports=function(e){return-1<r(this.__data__,e)}},{"./_assocIndexOf":24}],91:[function(e,t,n){var a=e("./_assocIndexOf");t.exports=function(e,t){var n=this.__data__,r=a(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}},{"./_assocIndexOf":24}],92:[function(e,t,n){var r=e("./_Hash"),a=e("./_ListCache"),o=e("./_Map");t.exports=function(){this.size=0,this.__data__={hash:new r,map:new(o||a),string:new r}}},{"./_Hash":6,"./_ListCache":7,"./_Map":8}],93:[function(e,t,n){var r=e("./_getMapData");t.exports=function(e){var t=r(this,e).delete(e);return this.size-=t?1:0,t}},{"./_getMapData":66}],94:[function(e,t,n){var r=e("./_getMapData");t.exports=function(e){return r(this,e).get(e)}},{"./_getMapData":66}],95:[function(e,t,n){var r=e("./_getMapData");t.exports=function(e){return r(this,e).has(e)}},{"./_getMapData":66}],96:[function(e,t,n){var a=e("./_getMapData");t.exports=function(e,t){var n=a(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this}},{"./_getMapData":66}],97:[function(e,t,n){t.exports=function(e){var n=-1,r=Array(e.size);return e.forEach(function(e,t){r[++n]=[t,e]}),r}},{}],98:[function(e,t,n){t.exports=function(t,n){return function(e){return null!=e&&e[t]===n&&(void 0!==n||t in Object(e))}}},{}],99:[function(e,t,n){var r=e("./memoize");t.exports=function(e){var t=r(e,function(e){return 500===n.size&&n.clear(),e}),n=t.cache;return t}},{"./memoize":145}],100:[function(e,t,n){var r=e("./_getNative")(Object,"create");t.exports=r},{"./_getNative":68}],101:[function(e,t,n){var r=e("./_overArg")(Object.keys,Object);t.exports=r},{"./_overArg":104}],102:[function(e,t,n){var r=e("./_freeGlobal"),a="object"==_typeof(n)&&n&&!n.nodeType&&n,o=a&&"object"==_typeof(t)&&t&&!t.nodeType&&t,i=o&&o.exports===a&&r.process,c=function(){try{var e=o&&o.require&&o.require("util").types;return e||i&&i.binding&&i.binding("util")}catch(e){}}();t.exports=c},{"./_freeGlobal":64}],103:[function(e,t,n){var r=Object.prototype.toString;t.exports=function(e){return r.call(e)}},{}],104:[function(e,t,n){t.exports=function(t,n){return function(e){return t(n(e))}}},{}],105:[function(e,t,n){var r=e("./_freeGlobal"),a="object"==("undefined"==typeof self?"undefined":_typeof(self))&&self&&self.Object===Object&&self,o=r||a||Function("return this")();t.exports=o},{"./_freeGlobal":64}],106:[function(e,t,n){t.exports=function(e){return this.__data__.set(e,"__lodash_hash_undefined__"),this}},{}],107:[function(e,t,n){t.exports=function(e){return this.__data__.has(e)}},{}],108:[function(e,t,n){t.exports=function(e){var t=-1,n=Array(e.size);return e.forEach(function(e){n[++t]=e}),n}},{}],109:[function(e,t,n){var r=e("./_ListCache");t.exports=function(){this.__data__=new r,this.size=0}},{"./_ListCache":7}],110:[function(e,t,n){t.exports=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}},{}],111:[function(e,t,n){t.exports=function(e){return this.__data__.get(e)}},{}],112:[function(e,t,n){t.exports=function(e){return this.__data__.has(e)}},{}],113:[function(e,t,n){var a=e("./_ListCache"),o=e("./_Map"),i=e("./_MapCache");t.exports=function(e,t){var n=this.__data__;if(n instanceof a){var r=n.__data__;if(!o||r.length<199)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new i(r)}return n.set(e,t),this.size=n.size,this}},{"./_ListCache":7,"./_Map":8,"./_MapCache":9}],114:[function(e,t,n){var r=e("./_memoizeCapped"),o=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,i=/\\(\\)?/g,a=r(function(e){var a=[];return 46===e.charCodeAt(0)&&a.push(""),e.replace(o,function(e,t,n,r){a.push(n?r.replace(i,"$1"):t||e)}),a});t.exports=a},{"./_memoizeCapped":99}],115:[function(e,t,n){var r=e("./isSymbol");t.exports=function(e){if("string"==typeof e||r(e))return e;var t=e+"";return"0"==t&&1/e==-1/0?"-0":t}},{"./isSymbol":139}],116:[function(e,t,n){var r=Function.prototype.toString;t.exports=function(e){if(null!=e){try{return r.call(e)}catch(e){}try{return e+""}catch(e){}}return""}},{}],117:[function(e,t,n){t.exports=function(e){for(var t=-1,n=null==e?0:e.length,r=0,a=[];++t<n;){var o=e[t];o&&(a[r++]=o)}return a}},{}],118:[function(e,t,n){t.exports=function(e,t){return e===t||e!=e&&t!=t}},{}],119:[function(e,t,n){var a=e("./_arrayEvery"),o=e("./_baseEvery"),i=e("./_baseIteratee"),c=e("./isArray"),s=e("./_isIterateeCall");t.exports=function(e,t,n){var r=c(e)?a:o;return n&&s(e,t,n)&&(t=void 0),r(e,i(t,3))}},{"./_arrayEvery":18,"./_baseEvery":27,"./_baseIteratee":43,"./_isIterateeCall":81,"./isArray":129}],120:[function(e,t,n){var r=e("./_arrayFilter"),a=e("./_baseFilter"),o=e("./_baseIteratee"),i=e("./isArray");t.exports=function(e,t){return(i(e)?r:a)(e,o(t,3))}},{"./_arrayFilter":19,"./_baseFilter":28,"./_baseIteratee":43,"./isArray":129}],121:[function(e,t,n){var r=e("./_createFind")(e("./findIndex"));t.exports=r},{"./_createFind":59,"./findIndex":122}],122:[function(e,t,n){var o=e("./_baseFindIndex"),i=e("./_baseIteratee"),c=e("./toInteger"),s=Math.max;t.exports=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var a=null==n?0:c(n);return a<0&&(a=s(r+a,0)),o(e,i(t,3),a)}},{"./_baseFindIndex":29,"./_baseIteratee":43,"./toInteger":150}],123:[function(e,t,n){var r=e("./_arrayEach"),a=e("./_baseEach"),o=e("./_castFunction"),i=e("./isArray");t.exports=function(e,t){return(i(e)?r:a)(e,o(t))}},{"./_arrayEach":17,"./_baseEach":26,"./_castFunction":54,"./isArray":129}],124:[function(e,t,n){var a=e("./_baseGet");t.exports=function(e,t,n){var r=null==e?void 0:a(e,t);return void 0===r?n:r}},{"./_baseGet":32}],125:[function(e,t,n){var r=e("./_baseHas"),a=e("./_hasPath");t.exports=function(e,t){return null!=e&&a(e,t,r)}},{"./_baseHas":35,"./_hasPath":74}],126:[function(e,t,n){var r=e("./_baseHasIn"),a=e("./_hasPath");t.exports=function(e,t){return null!=e&&a(e,t,r)}},{"./_baseHasIn":36,"./_hasPath":74}],127:[function(e,t,n){t.exports=function(e){return e}},{}],128:[function(e,t,n){var r=e("./_baseIsArguments"),a=e("./isObjectLike"),o=Object.prototype,i=o.hasOwnProperty,c=o.propertyIsEnumerable,s=r(function(){return arguments}())?r:function(e){return a(e)&&i.call(e,"callee")&&!c.call(e,"callee")};t.exports=s},{"./_baseIsArguments":37,"./isObjectLike":136}],129:[function(e,t,n){var r=Array.isArray;t.exports=r},{}],130:[function(e,t,n){var r=e("./isFunction"),a=e("./isLength");t.exports=function(e){return null!=e&&a(e.length)&&!r(e)}},{"./isFunction":133,"./isLength":134}],131:[function(e,t,n){var r=e("./_root"),a=e("./stubFalse"),o="object"==_typeof(n)&&n&&!n.nodeType&&n,i=o&&"object"==_typeof(t)&&t&&!t.nodeType&&t,c=i&&i.exports===o?r.Buffer:void 0,s=(c?c.isBuffer:void 0)||a;t.exports=s},{"./_root":105,"./stubFalse":148}],132:[function(e,t,n){var r=e("./_baseIsEqual");t.exports=function(e,t){return r(e,t)}},{"./_baseIsEqual":38}],133:[function(e,t,n){var r=e("./_baseGetTag"),a=e("./isObject");t.exports=function(e){if(!a(e))return!1;var t=r(e);return"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t}},{"./_baseGetTag":34,"./isObject":135}],134:[function(e,t,n){t.exports=function(e){return"number"==typeof e&&-1<e&&e%1==0&&e<=9007199254740991}},{}],135:[function(e,t,n){t.exports=function(e){var t=_typeof(e);return null!=e&&("object"==t||"function"==t)}},{}],136:[function(e,t,n){t.exports=function(e){return null!=e&&"object"==_typeof(e)}},{}],137:[function(e,t,n){var r=e("./_baseGetTag"),a=e("./_getPrototype"),o=e("./isObjectLike"),i=Function.prototype,c=Object.prototype,s=i.toString,u=c.hasOwnProperty,l=s.call(Object);t.exports=function(e){if(!o(e)||"[object Object]"!=r(e))return!1;var t=a(e);if(null===t)return!0;var n=u.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&s.call(n)==l}},{"./_baseGetTag":34,"./_getPrototype":69,"./isObjectLike":136}],138:[function(e,t,n){var r=e("./_baseGetTag"),a=e("./isArray"),o=e("./isObjectLike");t.exports=function(e){return"string"==typeof e||!a(e)&&o(e)&&"[object String]"==r(e)}},{"./_baseGetTag":34,"./isArray":129,"./isObjectLike":136}],139:[function(e,t,n){var r=e("./_baseGetTag"),a=e("./isObjectLike");t.exports=function(e){return"symbol"==_typeof(e)||a(e)&&"[object Symbol]"==r(e)}},{"./_baseGetTag":34,"./isObjectLike":136}],140:[function(e,t,n){var r=e("./_baseIsTypedArray"),a=e("./_baseUnary"),o=e("./_nodeUtil"),i=o&&o.isTypedArray,c=i?a(i):r;t.exports=c},{"./_baseIsTypedArray":42,"./_baseUnary":52,"./_nodeUtil":102}],141:[function(e,t,n){t.exports=function(e){return void 0===e}},{}],142:[function(e,t,n){var r=e("./_arrayLikeKeys"),a=e("./_baseKeys"),o=e("./isArrayLike");t.exports=function(e){return o(e)?r(e):a(e)}},{"./_arrayLikeKeys":20,"./_baseKeys":44,"./isArrayLike":130}],143:[function(e,t,n){var r=e("./_arrayMap"),a=e("./_baseIteratee"),o=e("./_baseMap"),i=e("./isArray");t.exports=function(e,t){return(i(e)?r:o)(e,a(t,3))}},{"./_arrayMap":21,"./_baseIteratee":43,"./_baseMap":45,"./isArray":129}],144:[function(e,t,n){var o=e("./_baseAssignValue"),i=e("./_baseForOwn"),c=e("./_baseIteratee");t.exports=function(e,r){var a={};return r=c(r,3),i(e,function(e,t,n){o(a,t,r(e,t,n))}),a}},{"./_baseAssignValue":25,"./_baseForOwn":31,"./_baseIteratee":43}],145:[function(e,t,n){var r=e("./_MapCache"),a="Expected a function";function c(o,i){if("function"!=typeof o||null!=i&&"function"!=typeof i)throw new TypeError(a);var e=function e(){var t=arguments,n=i?i.apply(this,t):t[0],r=e.cache;if(r.has(n))return r.get(n);var a=o.apply(this,t);return e.cache=r.set(n,a)||r,a};return e.cache=new(c.Cache||r),e}c.Cache=r,t.exports=c},{"./_MapCache":9}],146:[function(e,t,n){var r=e("./_baseProperty"),a=e("./_basePropertyDeep"),o=e("./_isKey"),i=e("./_toKey");t.exports=function(e){return o(e)?r(i(e)):a(e)}},{"./_baseProperty":48,"./_basePropertyDeep":49,"./_isKey":82,"./_toKey":115}],147:[function(e,t,n){t.exports=function(){return[]}},{}],148:[function(e,t,n){t.exports=function(){return!1}},{}],149:[function(e,t,n){var r=e("./toNumber");t.exports=function(e){return e?(e=r(e))!==1/0&&e!==-1/0?e==e?e:0:17976931348623157e292*(e<0?-1:1):0===e?e:0}},{"./toNumber":151}],150:[function(e,t,n){var r=e("./toFinite");t.exports=function(e){var t=r(e),n=t%1;return t==t?n?t-n:t:0}},{"./toFinite":149}],151:[function(e,t,n){var r=e("./isObject"),a=e("./isSymbol"),o=/^\s+|\s+$/g,i=/^[-+]0x[0-9a-f]+$/i,c=/^0b[01]+$/i,s=/^0o[0-7]+$/i,u=parseInt;t.exports=function(e){if("number"==typeof e)return e;if(a(e))return NaN;if(r(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=r(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(o,"");var n=c.test(e);return n||s.test(e)?u(e.slice(2),n?2:8):i.test(e)?NaN:+e}},{"./isObject":135,"./isSymbol":139}],152:[function(e,t,n){var r=e("./_baseToString");t.exports=function(e){return null==e?"":r(e)}},{"./_baseToString":51}],153:[function(e,a,t){!function(){var e=this;function t(e,t){var n,r,a,o,i,c,s,u;for(n=3&e.length,r=e.length-n,a=t,i=3432918353,c=461845907,u=0;u<r;)s=255&e.charCodeAt(u)|(255&e.charCodeAt(++u))<<8|(255&e.charCodeAt(++u))<<16|(255&e.charCodeAt(++u))<<24,++u,a=27492+(65535&(o=5*(65535&(a=(a^=s=(65535&(s=(s=(65535&s)*i+(((s>>>16)*i&65535)<<16)&4294967295)<<15|s>>>17))*c+(((s>>>16)*c&65535)<<16)&4294967295)<<13|a>>>19))+((5*(a>>>16)&65535)<<16)&4294967295))+((58964+(o>>>16)&65535)<<16);switch(s=0,n){case 3:s^=(255&e.charCodeAt(u+2))<<16;case 2:s^=(255&e.charCodeAt(u+1))<<8;case 1:a^=s=(65535&(s=(s=(65535&(s^=255&e.charCodeAt(u)))*i+(((s>>>16)*i&65535)<<16)&4294967295)<<15|s>>>17))*c+(((s>>>16)*c&65535)<<16)&4294967295}return a^=e.length,a=2246822507*(65535&(a^=a>>>16))+((2246822507*(a>>>16)&65535)<<16)&4294967295,a=3266489909*(65535&(a^=a>>>13))+((3266489909*(a>>>16)&65535)<<16)&4294967295,(a^=a>>>16)>>>0}var n=t;if(n.v2=function(e,t){for(var n,r=e.length,a=t^r,o=0;4<=r;)n=1540483477*(65535&(n=255&e.charCodeAt(o)|(255&e.charCodeAt(++o))<<8|(255&e.charCodeAt(++o))<<16|(255&e.charCodeAt(++o))<<24))+((1540483477*(n>>>16)&65535)<<16),a=1540483477*(65535&a)+((1540483477*(a>>>16)&65535)<<16)^(n=1540483477*(65535&(n^=n>>>24))+((1540483477*(n>>>16)&65535)<<16)),r-=4,++o;switch(r){case 3:a^=(255&e.charCodeAt(o+2))<<16;case 2:a^=(255&e.charCodeAt(o+1))<<8;case 1:a=1540483477*(65535&(a^=255&e.charCodeAt(o)))+((1540483477*(a>>>16)&65535)<<16)}return a=1540483477*(65535&(a^=a>>>13))+((1540483477*(a>>>16)&65535)<<16),(a^=a>>>15)>>>0},n.v3=t,void 0!==a)a.exports=n;else{var r=e.murmur;n.noConflict=function(){return e.murmur=r,n},e.murmur=n}}()},{}],154:[function(e,t,n){var y,_,r,a;y=e("crypt"),_=e("charenc").utf8,r=e("charenc").bin,(a=function(e,t){var n=y.wordsToBytes(function(e){e.constructor==String&&(e=_.stringToBytes(e));var t=y.bytesToWords(e),n=8*e.length,r=[],a=1732584193,o=-271733879,i=-1732584194,c=271733878,s=-1009589776;t[n>>5]|=128<<24-n%32,t[15+(n+64>>>9<<4)]=n;for(var u=0;u<t.length;u+=16){for(var l=a,f=o,d=i,p=c,h=s,m=0;m<80;m++){if(m<16)r[m]=t[u+m];else{var v=r[m-3]^r[m-8]^r[m-14]^r[m-16];r[m]=v<<1|v>>>31}var g=(a<<5|a>>>27)+s+(r[m]>>>0)+(m<20?1518500249+(o&i|~o&c):m<40?1859775393+(o^i^c):m<60?(o&i|o&c|i&c)-1894007588:(o^i^c)-899497514);s=c,c=i,i=o<<30|o>>>2,o=a,a=g}a+=l,o+=f,i+=d,c+=p,s+=h}return[a,o,i,c,s]}(e));return t&&t.asBytes?n:t&&t.asString?r.bytesToString(n):y.bytesToHex(n)})._blocksize=16,a._digestsize=20,t.exports=a},{charenc:2,crypt:3}],155:[function(e,t,n){Object.defineProperty(n,"__esModule",{value:!0});var r=e("./lib/core");n.trackerCore=r.trackerCore},{"./lib/core":158}],156:[function(e,t,n){function r(e){var t,n,r,a,o,i,c,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",u=0,l=0,f="",d=[];if(!e)return e;for(e+="";t=(i=s.indexOf(e.charAt(u++))<<18|s.indexOf(e.charAt(u++))<<12|(a=s.indexOf(e.charAt(u++)))<<6|(o=s.indexOf(e.charAt(u++))))>>16&255,n=i>>8&255,r=255&i,d[l++]=64===a?String.fromCharCode(t):64===o?String.fromCharCode(t,n):String.fromCharCode(t,n,r),u<e.length;);return f=d.join(""),c=f.replace(/\0+$/,""),decodeURIComponent(c.split("").map(function(e){return"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)}).join(""))}Object.defineProperty(n,"__esModule",{value:!0}),n.base64urldecode=function(e){if(!e)return e;switch(4-e.length%4){case 2:e+="==";break;case 3:e+="="}return r(e.replace(/-/g,"+").replace(/_/g,"/"))},n.base64encode=function(e){var t,n,r,a,o,i,c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",s=0,u=0,l=[];if(!e)return e;for(e=unescape(encodeURIComponent(e));t=(o=e.charCodeAt(s++)<<16|e.charCodeAt(s++)<<8|e.charCodeAt(s++))>>18&63,n=o>>12&63,r=o>>6&63,a=63&o,l[u++]=c.charAt(t)+c.charAt(n)+c.charAt(r)+c.charAt(a),s<e.length;);i=l.join("");var f=e.length%3;return(f?i.slice(0,f-3):i)+"===".slice(f||3)},n.base64decode=r},{}],157:[function(e,t,n){var r=this&&this.__assign||Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var a in t=arguments[n])Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e};Object.defineProperty(n,"__esModule",{value:!0});var a=e("./payload"),o=e("./base64"),s=e("lodash/isEqual"),i=e("lodash/has"),c=e("lodash/get"),u=e("lodash/isPlainObject"),l=e("lodash/every"),f=e("lodash/compact"),d=e("lodash/map");function p(e){var t=new RegExp("^iglu:([a-zA-Z0-9-_.]+)/([a-zA-Z0-9-_]+)/jsonschema/([1-9][0-9]*)-(0|[1-9][0-9]*)-(0|[1-9][0-9]*)$").exec(e);if(null!==t)return t.slice(1,6)}function h(e){if("*"===e[0]||"*"===e[1])return!1;if(0<e.slice(2).length){for(var t=!1,n=0,r=e.slice(2);n<r.length;n++){if("*"===r[n])t=!0;else if(t)return!1}return!0}return 2==e.length}function m(e){var t=e.split(".");return!!(t&&1<t.length)&&h(t)}function v(e){var t=new RegExp("^iglu:((?:(?:[a-zA-Z0-9-_]+|\\*).)+(?:[a-zA-Z0-9-_]+|\\*))/([a-zA-Z0-9-_.]+|\\*)/jsonschema/([1-9][0-9]*|\\*)-(0|[1-9][0-9]*|\\*)-(0|[1-9][0-9]*|\\*)$").exec(e);if(null!==t&&m(t[1]))return t.slice(1,6)}function g(e){var t=v(e);if(t){var n=t[0];return 5===t.length&&m(n)}return!1}function y(e){return Array.isArray(e)&&e.every(function(e){return"string"==typeof e})}function _(e){return y(e)?e.every(function(e){return g(e)}):"string"==typeof e&&g(e)}function b(e){return!!(a.isNonEmptyJson(e)&&"schema"in e&&"data"in e)&&("string"==typeof e.schema&&"object"===_typeof(e.data))}function w(e){return!!(a.isNonEmptyJson(e)&&"e"in e)&&"string"==typeof e.e}function k(e){var t=0;if(u(e)){if(i(e,"accept")){if(!_(e.accept))return!1;t+=1}if(i(e,"reject")){if(!_(e.reject))return!1;t+=1}return 0<t&&t<=2}return!1}function A(e){return"function"==typeof e&&e.length<=1}function x(e){return"function"==typeof e&&e.length<=1}function C(e){return A(e)||b(e)}function S(e){return!(!Array.isArray(e)||2!==e.length)&&(Array.isArray(e[1])?x(e[0])&&l(e[1],C):x(e[0])&&C(e[1]))}function j(e){return!(!Array.isArray(e)||2!==e.length)&&(!!k(e[0])&&(Array.isArray(e[1])?l(e[1],C):C(e[1])))}function T(e){return S(e)||j(e)}function O(e,t){if(!g(e))return!1;var n=v(e),r=p(t);if(n&&r){if(!P(n[0],r[0]))return!1;for(var a=1;a<5;a++)if(!I(n[a],r[a]))return!1;return!0}return!1}function P(e,t){var n=t.split("."),r=e.split(".");if(n&&r){if(n.length!==r.length)return!1;for(var a=0;a<r.length;a++)if(!I(n[a],r[a]))return!1;return!0}return!1}function I(e,t){return e&&t&&"*"===e||e===t}function E(e,t){var n=0,r=0,a=c(e,"accept");Array.isArray(a)?e.accept.some(function(e){return O(e,t)})&&r++:"string"==typeof a&&O(a,t)&&r++;var o=c(e,"reject");return Array.isArray(o)?e.reject.some(function(e){return O(e,t)})&&n++:"string"==typeof o&&O(o,t)&&n++,0<r&&0===n}function L(e){return"string"==typeof c(e,"ue_px.data.schema")?c(e,"ue_px.data.schema"):"string"==typeof c(e,"ue_pr.data.schema")?c(e,"ue_pr.data.schema"):"string"==typeof c(e,"schema")?c(e,"schema"):""}function D(e){var t=r({},e);try{i(t,"ue_px")&&(t.ue_px=JSON.parse(o.base64urldecode(c(t,["ue_px"]))))}catch(e){}return t}function M(e){return c(e,"e","")}function N(e,t,n,r){var a=void 0;try{return b(a=e({event:t,eventType:n,eventSchema:r}))?a:Array.isArray(a)&&l(a,b)?a:void 0}catch(e){a=void 0}return a}function F(e){return Array.isArray(e)?e:Array.of(e)}function z(e,n,r,a){var t=F(e),o=d(t,function(e){var t=U(e,n,r,a);if(t&&0!==t.length)return t});return[].concat.apply([],f(o))}function U(e,t,n,r){if(b(e))return[e];if(A(e)){var a=N(e,t,n,r);if(b(a))return[a];if(Array.isArray(a))return a}}function B(e,t,n,r){if(S(e)){var a=e[0],o=!1;try{o=a({event:t,eventType:n,eventSchema:r})}catch(e){o=!1}if(!0===o)return z(e[1],t,n,r)}else if(j(e)&&E(e[0],r))return z(e[1],t,n,r);return[]}function G(e,n,r,a){var t=F(e),o=d(t,function(e){var t=B(e,n,r,a);if(t&&0!==t.length)return t});return[].concat.apply([],f(o))}n.getSchemaParts=p,n.validateVendorParts=h,n.validateVendor=m,n.getRuleParts=v,n.isValidRule=g,n.isStringArray=y,n.isValidRuleSetArg=_,n.isSelfDescribingJson=b,n.isEventJson=w,n.isRuleSet=k,n.isContextGenerator=A,n.isContextFilter=x,n.isContextPrimitive=C,n.isFilterProvider=S,n.isRuleSetProvider=j,n.isConditionalContextProvider=T,n.matchSchemaAgainstRule=O,n.matchVendor=P,n.matchPart=I,n.matchSchemaAgainstRuleSet=E,n.getUsefulSchema=L,n.getDecodedEvent=D,n.getEventType=M,n.buildGenerator=N,n.normalizeToArray=F,n.generatePrimitives=z,n.evaluatePrimitive=U,n.evaluateProvider=B,n.generateConditionals=G,n.contextModule=function(){var i=[],c=[];return{getGlobalPrimitives:function(){return i},getConditionalProviders:function(){return c},addGlobalContexts:function(e){for(var t=[],n=[],r=0,a=e;r<a.length;r++){var o=a[r];T(o)?t.push(o):C(o)&&n.push(o)}i=i.concat(n),c=c.concat(t)},clearGlobalContexts:function(){c=[],i=[]},removeGlobalContexts:function(e){for(var t=function(t){T(t)?c=c.filter(function(e){return!s(e,t)}):C(t)&&(i=i.filter(function(e){return!s(e,t)}))},n=0,r=e;n<r.length;n++)t(r[n])},getApplicableContexts:function(e){var t=e.build();return w(t)?function(e){var t=L(e),n=M(e),r=[],a=z(i,e,n,t);r.push.apply(r,a);var o=G(c,e,n,t);return r.push.apply(r,o),r}(D(t)):[]}}}},{"./base64":156,"./payload":159,"lodash/compact":117,"lodash/every":119,"lodash/get":124,"lodash/has":125,"lodash/isEqual":132,"lodash/isPlainObject":137,"lodash/map":143}],158:[function(e,t,n){Object.defineProperty(n,"__esModule",{value:!0});var u=e("uuid"),m=e("./payload"),r=e("./contexts");n.trackerCore=function(d,i){void 0===d&&(d=!0);var c={},o=r.contextModule();function n(e,t){c[e]=t}function f(e,t){var n={};for(var r in t=t||{},e)(t[r]||null!==e[r]&&void 0!==e[r])&&(n[r]=e[r]);return n}function s(e,t){var n,r=(n=e,o.getApplicableContexts(n)),a=[];return t&&t.length&&a.push.apply(a,t),r&&r.length&&a.push.apply(a,r),a}function p(e,t,n){e.addDict(c),e.add("eid",u.v4());var r,a=null==(r=n)?{type:"dtm",value:(new Date).getTime()}:"number"==typeof r?{type:"dtm",value:r}:"ttm"===r.type?{type:"ttm",value:r.value}:{type:"dtm",value:r.value||(new Date).getTime()};e.add(a.type,a.value.toString());var o=function(e){if(e&&e.length)return{schema:"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0",data:e}}(s(e,t));return void 0!==o&&e.addJson("cx","co",o),"function"==typeof i&&i(e),e}function h(e,t,n){var r=m.payloadBuilder(d),a={schema:"iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0",data:e};return r.add("e","ue"),r.addJson("ue_px","ue_pr",a),p(r,t,n)}return{setBase64Encoding:function(e){d=e},addPayloadPair:n,addPayloadDict:function(e){for(var t in e)e.hasOwnProperty(t)&&(c[t]=e[t])},resetPayloadPairs:function(e){c=m.isJson(e)?e:{}},setTrackerVersion:function(e){n("tv",e)},setTrackerNamespace:function(e){n("tna",e)},setAppId:function(e){n("aid",e)},setPlatform:function(e){n("p",e)},setUserId:function(e){n("uid",e)},setScreenResolution:function(e,t){n("res",e+"x"+t)},setViewport:function(e,t){n("vp",e+"x"+t)},setColorDepth:function(e){n("cd",e)},setTimezone:function(e){n("tz",e)},setLang:function(e){n("lang",e)},setIpAddress:function(e){n("ip",e)},trackUnstructEvent:h,trackSelfDescribingEvent:h,trackPageView:function(e,t,n,r,a){var o=m.payloadBuilder(d);return o.add("e","pv"),o.add("url",e),o.add("page",t),o.add("refr",n),p(o,r,a)},trackPagePing:function(e,t,n,r,a,o,i,c,s){var u=m.payloadBuilder(d);return u.add("e","pp"),u.add("url",e),u.add("page",t),u.add("refr",n),u.add("pp_mix",r.toString()),u.add("pp_max",a.toString()),u.add("pp_miy",o.toString()),u.add("pp_may",i.toString()),p(u,c,s)},trackStructEvent:function(e,t,n,r,a,o,i){var c=m.payloadBuilder(d);return c.add("e","se"),c.add("se_ca",e),c.add("se_ac",t),c.add("se_la",n),c.add("se_pr",r),c.add("se_va",null==a?void 0:a.toString()),p(c,o,i)},trackEcommerceTransaction:function(e,t,n,r,a,o,i,c,s,u,l){var f=m.payloadBuilder(d);return f.add("e","tr"),f.add("tr_id",e),f.add("tr_af",t),f.add("tr_tt",n),f.add("tr_tx",r),f.add("tr_sh",a),f.add("tr_ci",o),f.add("tr_st",i),f.add("tr_co",c),f.add("tr_cu",s),p(f,u,l)},trackEcommerceTransactionItem:function(e,t,n,r,a,o,i,c,s){var u=m.payloadBuilder(d);return u.add("e","ti"),u.add("ti_id",e),u.add("ti_sk",t),u.add("ti_nm",n),u.add("ti_ca",r),u.add("ti_pr",a),u.add("ti_qu",o),u.add("ti_cu",i),p(u,c,s)},trackScreenView:function(e,t,n,r){return h({schema:"iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0",data:f({name:e,id:t})},n,r)},trackLinkClick:function(e,t,n,r,a,o,i){return h({schema:"iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1",data:f({targetUrl:e,elementId:t,elementClasses:n,elementTarget:r,elementContent:a})},o,i)},trackAdImpression:function(e,t,n,r,a,o,i,c,s,u){return h({schema:"iglu:com.snowplowanalytics.snowplow/ad_impression/jsonschema/1-0-0",data:f({impressionId:e,costModel:t,cost:n,targetUrl:r,bannerId:a,zoneId:o,advertiserId:i,campaignId:c})},s,u)},trackAdClick:function(e,t,n,r,a,o,i,c,s,u,l){return h({schema:"iglu:com.snowplowanalytics.snowplow/ad_click/jsonschema/1-0-0",data:f({targetUrl:e,clickId:t,costModel:n,cost:r,bannerId:a,zoneId:o,impressionId:i,advertiserId:c,campaignId:s})},u,l)},trackAdConversion:function(e,t,n,r,a,o,i,c,s,u,l){return h({schema:"iglu:com.snowplowanalytics.snowplow/ad_conversion/jsonschema/1-0-0",data:f({conversionId:e,costModel:t,cost:n,category:r,action:a,property:o,initialValue:i,advertiserId:c,campaignId:s})},u,l)},trackSocialInteraction:function(e,t,n,r,a){return h({schema:"iglu:com.snowplowanalytics.snowplow/social_interaction/jsonschema/1-0-0",data:f({action:e,network:t,target:n})},r,a)},trackAddToCart:function(e,t,n,r,a,o,i,c){return h({schema:"iglu:com.snowplowanalytics.snowplow/add_to_cart/jsonschema/1-0-0",data:f({sku:e,name:t,category:n,unitPrice:r,quantity:a,currency:o})},i,c)},trackRemoveFromCart:function(e,t,n,r,a,o,i,c){return h({schema:"iglu:com.snowplowanalytics.snowplow/remove_from_cart/jsonschema/1-0-0",data:f({sku:e,name:t,category:n,unitPrice:r,quantity:a,currency:o})},i,c)},trackFormFocusOrChange:function(e,t,n,r,a,o,i,c,s){var u="";return"change_form"===e?u="iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0":"focus_form"===e&&(u="iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0"),h({schema:u,data:f({formId:t,elementId:n,nodeName:r,type:a,elementClasses:o,value:i},{value:!0})},c,s)},trackFormSubmission:function(e,t,n,r,a){return h({schema:"iglu:com.snowplowanalytics.snowplow/submit_form/jsonschema/1-0-0",data:f({formId:e,formClasses:t,elements:n})},r,a)},trackSiteSearch:function(e,t,n,r,a,o){return h({schema:"iglu:com.snowplowanalytics.snowplow/site_search/jsonschema/1-0-0",data:f({terms:e,filters:t,totalResults:n,pageResults:r})},a,o)},trackConsentWithdrawn:function(e,t,n,r,a,o,i){var c={schema:"iglu:com.snowplowanalytics.snowplow/consent_document/jsonschema/1-0-0",data:f({id:t,version:n,name:r,description:a})};return h({schema:"iglu:com.snowplowanalytics.snowplow/consent_withdrawn/jsonschema/1-0-0",data:f({all:e})},c.data&&o?o.concat([c]):o,i)},trackConsentGranted:function(e,t,n,r,a,o,i){var c={schema:"iglu:com.snowplowanalytics.snowplow/consent_document/jsonschema/1-0-0",data:f({id:e,version:t,name:n,description:r})};return h({schema:"iglu:com.snowplowanalytics.snowplow/consent_granted/jsonschema/1-0-0",data:f({expiry:a})},o?o.concat([c]):[c],i)},addGlobalContexts:function(e){o.addGlobalContexts(e)},clearGlobalContexts:function(){o.clearGlobalContexts()},removeGlobalContexts:function(e){o.removeGlobalContexts(e)}}}},{"./contexts":157,"./payload":159,uuid:161}],159:[function(e,t,n){Object.defineProperty(n,"__esModule",{value:!0});var c=e("./base64");function s(e){if(!r(e))return!1;for(var t in e)if(e.hasOwnProperty(t))return!0;return!1}function r(e){return null!=e&&(e.constructor==={}.constructor||e.constructor===[].constructor)}n.isNonEmptyJson=s,n.isJson=r,n.payloadBuilder=function(o){var n={},i=function(e,t){null!=t&&""!==t&&(n[e]=t)};return{add:i,addDict:function(e){for(var t in e)e.hasOwnProperty(t)&&i(t,e[t])},addJson:function(e,t,n){if(s(n)){var r=JSON.stringify(n);o?i(e,(a=r)?c.base64encode(a).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_"):a):i(t,r)}var a},build:function(){return n}}}},{"./base64":156}],160:[function(e,o,t){(function(e){var t,n=e.crypto||e.msCrypto;if(n&&n.getRandomValues){var r=new Uint8Array(16);t=function(){return n.getRandomValues(r),r}}if(!t){var a=new Array(16);t=function(){for(var e,t=0;t<16;t++)0==(3&t)&&(e=4294967296*Math.random()),a[t]=e>>>((3&t)<<3)&255;return a}}o.exports=t}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],161:[function(e,t,n){for(var i=e("./rng"),a=[],o={},r=0;r<256;r++)a[r]=(r+256).toString(16).substr(1),o[a[r]]=r;function p(e,t){var n=t||0,r=a;return r[e[n++]]+r[e[n++]]+r[e[n++]]+r[e[n++]]+"-"+r[e[n++]]+r[e[n++]]+"-"+r[e[n++]]+r[e[n++]]+"-"+r[e[n++]]+r[e[n++]]+"-"+r[e[n++]]+r[e[n++]]+r[e[n++]]+r[e[n++]]+r[e[n++]]+r[e[n++]]}var c=i(),h=[1|c[0],c[1],c[2],c[3],c[4],c[5]],m=16383&(c[6]<<8|c[7]),v=0,g=0;function s(e,t,n){var r=t&&n||0;"string"==typeof e&&(t="binary"==e?new Array(16):null,e=null);var a=(e=e||{}).random||(e.rng||i)();if(a[6]=15&a[6]|64,a[8]=63&a[8]|128,t)for(var o=0;o<16;o++)t[r+o]=a[o];return t||p(a)}var u=s;u.v1=function(e,t,n){var r=t&&n||0,a=t||[],o=void 0!==(e=e||{}).clockseq?e.clockseq:m,i=void 0!==e.msecs?e.msecs:(new Date).getTime(),c=void 0!==e.nsecs?e.nsecs:g+1,s=i-v+(c-g)/1e4;if(s<0&&void 0===e.clockseq&&(o=o+1&16383),(s<0||v<i)&&void 0===e.nsecs&&(c=0),1e4<=c)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");v=i,m=o;var u=(1e4*(268435455&(i+=122192928e5))+(g=c))%4294967296;a[r++]=u>>>24&255,a[r++]=u>>>16&255,a[r++]=u>>>8&255,a[r++]=255&u;var l=i/4294967296*1e4&268435455;a[r++]=l>>>8&255,a[r++]=255&l,a[r++]=l>>>24&15|16,a[r++]=l>>>16&255,a[r++]=o>>>8|128,a[r++]=255&o;for(var f=e.node||h,d=0;d<6;d++)a[r+d]=f[d];return t||p(a)},u.v4=s,u.parse=function(e,t,n){var r=t&&n||0,a=0;for(t=t||[],e.toLowerCase().replace(/[0-9a-f]{2}/g,function(e){a<16&&(t[r+a++]=o[e])});a<16;)t[r+a++]=0;return t},u.unparse=p,t.exports=u},{"./rng":160}],162:[function(e,t,n){var u=e("lodash/isFunction"),r=e("./lib/helpers"),a=window;(void 0!==n?n:this).errorManager=function(c){function s(e,t,n,r,a,o){var i=a&&a.stack?a.stack:null;c.trackSelfDescribingEvent({schema:"iglu:com.snowplowanalytics.snowplow/application_error/jsonschema/1-0-1",data:{programmingLanguage:"JAVASCRIPT",message:e||"JS Exception. Browser doesn't support ErrorEvent API",stackTrace:i,lineNumber:n,lineColumn:r,fileName:t}},o)}return{trackError:s,enableErrorTracking:function(o,i,c){r.addEventListener(a,"error",function(e){var t,n,r,a;(u(o)&&o(e)||null==o)&&(t=e,n=c,a=u(r=i)?n.concat(r(t)):n,s(t.message,t.filename,t.lineno,t.colno,t.error,a))},!0)}}}},{"./lib/helpers":168,"lodash/isFunction":133}],163:[function(e,t,n){var p=e("lodash/forEach"),h=e("lodash/filter"),m=e("lodash/find"),v=e("./lib/helpers");(void 0!==n?n:this).getFormTrackingManager=function(i,e,c){var s=["textarea","input","select"],u=e+"form",r=function(){return!0},a=function(){return!0},l=function(e){return e};function f(t){return t[m(["name","id","type","nodeName"],function(e){return t[e]&&"string"==typeof t[e]})]}function o(a,o){return function(e){var t=e.target,n=t.nodeName&&"INPUT"===t.nodeName.toUpperCase()?t.type:null,r="checkbox"!==t.type||t.checked?l(t.value):null;("change_form"===a||"checkbox"!==n&&"radio"!==n)&&i.trackFormFocusOrChange(a,function(e){for(;e&&e.nodeName&&"HTML"!==e.nodeName.toUpperCase()&&"FORM"!==e.nodeName.toUpperCase();)e=e.parentNode;if(e&&e.nodeName&&"FORM"===e.nodeName.toUpperCase())return f(e)}(t),f(t),t.nodeName,n,v.getCssClasses(t),r,c(v.resolveDynamicContexts(o,t,n,r)))}}function d(o){return function(e){var n,r,t=e.target,a=(n=t,r=[],p(s,function(e){var t=h(n.getElementsByTagName(e),function(e){return e.hasOwnProperty(u)});p(t,function(e){if("submit"!==e.type){var t={name:f(e),value:e.value,nodeName:e.nodeName};e.type&&"INPUT"===e.nodeName.toUpperCase()&&(t.type=e.type),"checkbox"!==e.type&&"radio"!==e.type||e.checked||(t.value=null),r.push(t)}})}),r);p(a,function(e){e.value=l(e.value)}),i.trackFormSubmission(f(t),v.getCssClasses(t),a,c(v.resolveDynamicContexts(o,t,a)))}}return{configureFormTracking:function(e){e&&(r=v.getFilter(e.forms,!0),a=v.getFilter(e.fields,!1),l=v.getTransform(e.fields))},addFormListeners:function(n){p(document.getElementsByTagName("form"),function(t){r(t)&&!t[u]&&(p(s,function(e){p(t.getElementsByTagName(e),function(e){a(e)&&!e[u]&&"password"!==e.type.toLowerCase()&&(v.addEventListener(e,"focus",o("focus_form",n),!1),v.addEventListener(e,"change",o("change_form",n),!1),e[u]=!0)})}),v.addEventListener(t,"submit",d(n)),t[u]=!0)})}}}},{"./lib/helpers":168,"lodash/filter":120,"lodash/find":121,"lodash/forEach":123}],164:[function(e,t,n){n.productionize=function(a){var o={};return"object"===_typeof(a)&&null!==a&&Object.getOwnPropertyNames(a).forEach(function(e,t,n){var r;"function"==typeof a[e]&&(o[e]=(r=a[e],function(){try{return r.apply(this,arguments)}catch(e){}}))}),o}},{}],165:[function(e,t,n){!function(){var c=e("lodash/map"),v=e("lodash/isUndefined"),g=e("lodash/isFunction"),y=e("./lib/helpers");(void 0!==n?n:this).InQueueManager=function(r,a,o,e,i){var p={};function h(e){var t=[];if(e&&0!==e.length)for(var n=0;n<e.length;n++)p.hasOwnProperty(e[n])?t.push(p[e[n]]):y.warn('Warning: Tracker namespace "'+e[n]+'" not configured');else t=c(p);return 0===t.length&&y.warn("Warning: No tracker configured"),t}function m(e,t,n){n=n||{},p.hasOwnProperty(e)?y.warn("Tracker namespace "+e+" already exists."):(p[e]=new r(i,e,a,o,n),p[e].setCollectorUrl(t))}function t(){var e,t,n,r,a,o,i,c,s,u,l,f,d;for(e=0;e<arguments.length;e+=1)if(r=arguments[e],a=Array.prototype.shift.call(r),g(a))a.apply(p,r);else if(d=void 0,i=(o=[(d=a.split(":"))[0],1<d.length?d[1].split(";"):[]])[1],"newTracker"!==(n=o[0]))if("setCollectorCf"!==n&&"setCollectorUrl"!==n||i&&0!==i.length)for(c=h(i),t=0;t<c.length;t++)c[t][n].apply(c[t],r);else s=n,u=r[0],l=r[1],f=void 0,y.warn(s+" is deprecated. Set the collector when a new tracker instance using newTracker."),m(f=v(l)?"sp":l),p[f][s](u);else m(r[0],r[1],r[2])}for(var n=0;n<e.length;n++)t(e[n]);return{push:t}}}()},{"./lib/helpers":168,"lodash/isFunction":133,"lodash/isUndefined":141,"lodash/map":143}],166:[function(e,t,n){var r,a,o=e("./snowplow"),i=window;i.GlobalSnowplowNamespace&&0<i.GlobalSnowplowNamespace.length?(r=i.GlobalSnowplowNamespace.shift(),(a=i[r]).q=new o.Snowplow(a.q,r)):(i._snaq=i._snaq||[],i._snaq=new o.Snowplow(i._snaq,"_snaq"))},{"./snowplow":172}],167:[function(t,e,r){!function(){var i=t("lodash/isFunction"),c=t("lodash/isUndefined"),s=t("murmurhash").v3,e=t("jstimezonedetect").jstz.determine(),n=t("browser-cookie-lite"),u=void 0!==r?r:this,l=window,f=navigator,d=screen,o=document;u.hasSessionStorage=function(){try{return!!l.sessionStorage}catch(e){return!0}},u.hasLocalStorage=function(){try{return!!l.localStorage}catch(e){return!0}},u.localStorageAccessible=function(){var e="modernizr";if(!u.hasLocalStorage())return!1;try{return l.localStorage.setItem(e,e),l.localStorage.removeItem(e),!0}catch(e){return!1}},u.hasCookies=function(e){var t=e||"testcookie";return c(f.cookieEnabled)?(n.cookie(t,"1"),"1"===n.cookie(t)?"1":"0"):f.cookieEnabled?"1":"0"},u.detectSignature=function(e){var t=[f.userAgent,[d.height,d.width,d.colorDepth].join("x"),(new Date).getTimezoneOffset(),u.hasSessionStorage(),u.hasLocalStorage()],n=[];if(f.plugins)for(var r=0;r<f.plugins.length;r++)if(f.plugins[r]){for(var a=[],o=0;o<f.plugins[r].length;o++)a.push([f.plugins[r][o].type,f.plugins[r][o].suffixes]);n.push([f.plugins[r].name+"::"+f.plugins[r].description,a.join("~")])}return s(t.join("###")+"###"+n.sort().join(";"),e)},u.detectTimezone=function(){return void 0===e?"":e.name()},u.detectViewport=function(){var e=l,t="inner";"innerWidth"in l||(t="client",e=o.documentElement||o.body);var n=e[t+"Width"],r=e[t+"Height"];return 0<=n&&0<=r?n+"x"+r:null},u.detectDocumentSize=function(){var e=o.documentElement,t=o.body,n=t?Math.max(t.offsetHeight,t.scrollHeight):0,r=Math.max(e.clientWidth,e.offsetWidth,e.scrollWidth),a=Math.max(e.clientHeight,e.offsetHeight,e.scrollHeight,n);return isNaN(r)||isNaN(a)?"":r+"x"+a},u.detectBrowserFeatures=function(e,t){var n,r,a={pdf:"application/pdf",qt:"video/quicktime",realp:"audio/x-pn-realaudio-plugin",wma:"application/x-mplayer2",dir:"application/x-director",fla:"application/x-shockwave-flash",java:"application/x-java-vm",gears:"application/x-googlegears",ag:"application/x-silverlight"},o={};if(f.mimeTypes&&f.mimeTypes.length)for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(r=f.mimeTypes[a[n]],o[n]=r&&r.enabledPlugin?"1":"0");return f.constructor===window.Navigator&&"unknown"!=typeof f.javaEnabled&&!c(f.javaEnabled)&&f.javaEnabled()&&(o.java="1"),i(l.GearsFactory)&&(o.gears="1"),o.res=d.width+"x"+d.height,o.cd=d.colorDepth,e&&(o.cookie=u.hasCookies(t)),o}}()},{"browser-cookie-lite":1,jstimezonedetect:4,"lodash/isFunction":133,"lodash/isUndefined":141,murmurhash:153}],168:[function(e,t,o){!function(){var n=e("lodash/isString"),r=e("lodash/isUndefined"),i=e("lodash/isObject"),a=e("lodash/map"),s=e("browser-cookie-lite"),u=void 0!==o?o:this;u.fixupTitle=function(e){if(!n(e)){e=e.text||"";var t=document.getElementsByTagName("title");t&&!r(t[0])&&(e=t[0].text)}return e},u.getHostName=function(e){var t=new RegExp("^(?:(?:https?|ftp):)/*(?:[^@]+@)?([^:/#]+)").exec(e);return t?t[1]:e},u.fixupDomain=function(e){var t=e.length;return"."===e.charAt(--t)&&(e=e.slice(0,t)),"*."===e.slice(0,2)&&(e=e.slice(1)),e},u.getReferrer=function(e){var t="",n=u.fromQuerystring("referrer",window.location.href)||u.fromQuerystring("referer",window.location.href);if(n)return n;if(e)return e;try{t=window.top.document.referrer}catch(e){if(window.parent)try{t=window.parent.document.referrer}catch(e){t=""}}return""===t&&(t=document.referrer),t},u.addEventListener=function(e,t,n,r){return e.addEventListener?(e.addEventListener(t,n,r),!0):e.attachEvent?e.attachEvent("on"+t,n):void(e["on"+t]=n)},u.fromQuerystring=function(e,t){var n=new RegExp("^[^#]*[?&]"+e+"=([^&#]*)").exec(t);return n?decodeURIComponent(n[1].replace(/\+/g," ")):null},u.resolveDynamicContexts=function(e){var t=Array.prototype.slice.call(arguments,1);return a(e,function(e){if("function"!=typeof e)return e;try{return e.apply(null,t)}catch(e){}})},u.warn=function(e){"undefined"!=typeof console&&console.warn("Snowplow: "+e)},u.getCssClasses=function(e){return e.className.match(/\S+/g)||[]},u.getFilter=function(e,t){if(Array.isArray(e)||!i(e))return function(){return!0};if(e.hasOwnProperty("filter"))return e.filter;var n=e.hasOwnProperty("whitelist"),r=e.whitelist||e.blacklist;Array.isArray(r)||(r=[r]);for(var a={},o=0;o<r.length;o++)a[r[o]]=!0;return t?function(e){return function(e,t){var n,r=u.getCssClasses(e);for(n=0;n<r.length;n++)if(t[r[n]])return!0;return!1}(e,a)===n}:function(e){return e.name in a===n}},u.getTransform=function(e){return i(e)?e.hasOwnProperty("transform")?e.transform:function(e){return e}:function(e){return e}},u.decorateQuerystring=function(e,t,n){var r=t+"="+n,a=e.split("#"),o=a[0].split("?"),i=o.shift(),c=o.join("?");if(c){for(var s=!0,u=c.split("&"),l=0;l<u.length;l++)if(u[l].substr(0,t.length+1)===t+"="){s=!1,u[l]=r,c=u.join("&");break}s&&(c=r+"&"+c)}else c=r;return a[0]=i+"?"+c,a.join("#")},u.attemptGetLocalStorage=function(e){try{return localStorage.getItem(e)}catch(e){}},u.attemptWriteLocalStorage=function(e,t){try{return localStorage.setItem(e,t),!0}catch(e){return!1}},u.findRootDomain=function(){for(var e="_sp_root_domain_test_",t=e+(new Date).getTime(),n="_test_value_"+(new Date).getTime(),r=window.location.hostname.split("."),a=r.length-1;0<=a;){var o=r.slice(a,r.length).join(".");if(s.cookie(t,n,0,"/",o),s.cookie(t)===n){u.deleteCookie(t,o);for(var i=u.getCookiesWithPrefix(e),c=0;c<i.length;c++)u.deleteCookie(i[c],o);return o}a-=1}return window.location.hostname},u.isValueInArray=function(e,t){for(var n=0;n<t.length;n++)if(t[n]===e)return!0;return!1},u.deleteCookie=function(e,t){s.cookie(e,"",-1,"/",t)},u.getCookiesWithPrefix=function(e){for(var t=document.cookie.split("; "),n=[],r=0;r<t.length;r++)t[r].substring(0,e.length)===e&&n.push(t[r]);return n},u.parseInt=function(e){var t=parseInt(e);return isNaN(t)?void 0:t},u.parseFloat=function(e){var t=parseFloat(e);return isNaN(t)?void 0:t}}()},{"browser-cookie-lite":1,"lodash/isObject":135,"lodash/isString":138,"lodash/isUndefined":141,"lodash/map":143}],169:[function(e,t,n){!function(){var i=e("./helpers");function c(e){var t,n,r;if(r=e,new RegExp("^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$").test(r))try{return t=document.body.children[0].children[0].children[0].children[0].children[0].children[0].innerHTML,n="You have reached the cached page for",t.slice(0,n.length)===n}catch(e){return!1}}(void 0!==n?n:this).fixupUrl=function(e,t,n){var r,a,o;return"translate.googleusercontent.com"===e?(""===n&&(n=t),r=t,a="u",o=new RegExp("^(?:https?|ftp)(?::/*(?:[^?]+))([?][^#]+)").exec(r),t=i.fromQuerystring(a,o[1]),e=i.getHostName(t)):("cc.bingj.com"===e||"webcache.googleusercontent.com"===e||c(e))&&(t=document.links[0].href,e=i.getHostName(t)),[e,t,n]}}()},{"./helpers":168}],170:[function(e,t,n){var h=e("lodash/isUndefined"),m=e("./lib/helpers");(void 0!==n?n:this).getLinkTrackingManager=function(f,r,d){var a,o,p,i,c,s;function u(e,t){for(var n,r,a,o,i,c;null!==(n=e.parentNode)&&!h(n)&&"A"!==(r=e.tagName.toUpperCase())&&"AREA"!==r;)e=n;if(!h(e.href)){var s=e.hostname||m.getHostName(e.href),u=s.toLowerCase(),l=e.href.replace(s,u);new RegExp("^(javascript|vbscript|jscript|mocha|livescript|ecmascript|mailto):","i").test(l)||(a=e.id,o=m.getCssClasses(e),i=e.target,c=p?e.innerHTML:null,l=unescape(l),f.trackLinkClick(l,a,o,i,c,d(m.resolveDynamicContexts(t,e))))}}function l(r){return function(e){var t,n;t=(e=e||window.event).which||e.button,n=e.target||e.srcElement,"click"===e.type?n&&u(n,r):"mousedown"===e.type?1!==t&&2!==t||!n?c=s=null:(c=t,s=n):"mouseup"===e.type&&(t===c&&n===s&&u(n,r),c=s=null)}}return{configureLinkClickTracking:function(e,t,n,r){p=n,i=r,o=t,a=m.getFilter(e,!0)},addClickListeners:function(){var e,t,n=document.links;for(e=0;e<n.length;e++)a(n[e])&&!n[e][r]&&(t=n[e],o?(m.addEventListener(t,"mouseup",l(i),!1),m.addEventListener(t,"mousedown",l(i),!1)):m.addEventListener(t,"click",l(i),!1),n[e][r]=!0)}}}},{"./lib/helpers":168,"lodash/isUndefined":141}],171:[function(e,t,n){!function(){var b=e("lodash/mapValues"),w=e("lodash/isString"),k=e("lodash/map"),A=e("./lib/detectors").localStorageAccessible,x=e("./lib/helpers");(void 0!==n?n:this).OutQueueManager=function(e,t,n,s,r,a,o,u){var l,f,d,p=!1,i=null===(r=r.toLowerCase?r.toLowerCase():r)||!0===r||"beacon"===r||"true"===r,h=Boolean(i&&navigator&&navigator.sendBeacon)&&i,m=("post"===r||h)&&!("get"===r),c=(m=m&&Boolean(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest))?a:"/i";if(o=A()&&s&&m&&o||1,l=["snowplowOutQueue",e,t,m?"post2":"get"].join("_"),s)try{d=JSON.parse(localStorage.getItem(l))}catch(e){}function v(){for(;d.length&&"string"!=typeof d[0]&&"object"!==_typeof(d[0]);)d.shift();if(d.length<1)p=!1;else{if(!w(f))throw"No Snowplow collector configured, cannot track";p=!0;var e=d[0];if(m){var t=g(f),n=setTimeout(function(){t.abort(),p=!1},5e3),r=function(e){for(var t=0,n=0;t<e.length&&(n+=e[t].bytes,!(u<=n));)t+=1;return t}(d);t.onreadystatechange=function(){if(4===t.readyState&&200<=t.status&&t.status<400){for(var e=0;e<r;e++)d.shift();s&&x.attemptWriteLocalStorage(l,JSON.stringify(d)),clearTimeout(n),v()}else 4===t.readyState&&400<=t.status&&(clearTimeout(n),p=!1)};var a=k(d.slice(0,r),function(e){return e.evt});if(0<a.length){var o;if(h){var i=new Blob([y(_(a))],{type:"application/json"});o=navigator.sendBeacon(f,i)}h&&o||t.send(y(_(a)))}}else{var c=new Image(1,1);c.onload=function(){d.shift(),s&&x.attemptWriteLocalStorage(l,JSON.stringify(d)),v()},c.onerror=function(){p=!1},c.src=f+e.replace("?","?stm="+(new Date).getTime()+"&")}}}function g(e){var t=new XMLHttpRequest;return t.open("POST",e,!0),t.withCredentials=!0,t.setRequestHeader("Content-Type","application/json; charset=UTF-8"),t}function y(e){return JSON.stringify({schema:"iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-4",data:e})}function _(e){for(var t=(new Date).getTime().toString(),n=0;n<e.length;n++)e[n].stm=t;return e}return Array.isArray(d)||(d=[]),n.outQueues.push(d),m&&1<o&&n.bufferFlushers.push(function(){p||v()}),{enqueueRequest:function(e,t){if(f=t+c,m){var n={evt:r=b(e,function(e){return e.toString()}),bytes:function(e){for(var t=0,n=0;n<e.length;n++){var r=e.charCodeAt(n);r<=127?t+=1:r<=2047?t+=2:55296<=r&&r<=57343?(t+=4,n++):t+=r<65535?3:4}return t}(JSON.stringify(r))};if(u<=n.bytes)return x.warn("Event of size "+n.bytes+" is too long - the maximum size is "+u),void g(f).send(y(_([n.evt])));d.push(n)}else d.push(function(e){var t="?",n={co:!0,cx:!0},r=!0;for(var a in e)e.hasOwnProperty(a)&&!n.hasOwnProperty(a)&&(r?r=!1:t+="&",t+=encodeURIComponent(a)+"="+encodeURIComponent(e[a]));for(var o in n)e.hasOwnProperty(o)&&n.hasOwnProperty(o)&&(t+="&"+o+"="+encodeURIComponent(e[o]));return t}(e));var r,a=!1;s&&(a=x.attemptWriteLocalStorage(l,JSON.stringify(d))),p||a&&!(d.length>=o)||v()},executeQueue:v}}}()},{"./lib/detectors":167,"./lib/helpers":168,"lodash/isString":138,"lodash/map":143,"lodash/mapValues":144}],172:[function(e,t,n){!function(){e("uuid");var s=e("lodash/forEach"),u=e("lodash/filter"),l=e("./lib/helpers"),f=e("./in_queue"),d=e("./tracker");(void 0!==n?n:this).Snowplow=function(e,n){var t,r=document,a=window,o="js-2.10.0",i={outQueues:[],bufferFlushers:[],expireDateTime:null,hasLoaded:!1,registeredOnLoadHandlers:[],pageViewId:null};function c(){var e;if(!i.hasLoaded)for(i.hasLoaded=!0,e=0;e<i.registeredOnLoadHandlers.length;e++)i.registeredOnLoadHandlers[e]();return!0}return a.Snowplow={getTrackerCf:function(e){var t=new d.Tracker(n,"",o,i,{});return t.setCollectorCf(e),t},getTrackerUrl:function(e){var t=new d.Tracker(n,"",o,i,{});return t.setCollectorUrl(e),t},getAsyncTracker:function(){return new d.Tracker(n,"",o,i,{})}},l.addEventListener(a,"beforeunload",function(){var e;if(s(i.bufferFlushers,function(e){e()}),i.expireDateTime)do{if(e=new Date,0===u(i.outQueues,function(e){return 0<e.length}).length)break}while(e.getTime()<i.expireDateTime)},!1),r.addEventListener?l.addEventListener(r,"DOMContentLoaded",function e(){r.removeEventListener("DOMContentLoaded",e,!1),c()}):r.attachEvent&&(r.attachEvent("onreadystatechange",function e(){"complete"===r.readyState&&(r.detachEvent("onreadystatechange",e),c())}),r.documentElement.doScroll&&a===a.top&&function t(){if(!i.hasLoaded){try{r.documentElement.doScroll("left")}catch(e){return void setTimeout(t,0)}c()}}()),new RegExp("WebKit").test(navigator.userAgent)&&(t=setInterval(function(){(i.hasLoaded||/loaded|complete/.test(r.readyState))&&(clearInterval(t),c())},10)),l.addEventListener(a,"load",c,!1),new f.InQueueManager(d.Tracker,o,i,e,n)}}()},{"./in_queue":165,"./lib/helpers":168,"./tracker":173,"lodash/filter":120,"lodash/forEach":123,uuid:161}],173:[function(e,t,n){!function(){var Xe=e("lodash/forEach"),et=e("lodash/map"),tt=e("./lib/helpers"),nt=e("./lib/proxies"),rt=e("browser-cookie-lite"),at=e("./lib/detectors"),ot=e("sha1"),it=e("./links"),ct=e("./forms"),st=e("./errors"),ut=e("./out_queue"),lt=e("snowplow-tracker-core").trackerCore,ft=e("./guard").productionize,dt=e("uuid");(void 0!==n?n:this).Tracker=function(e,t,n,s,r){(r=r||{}).hasOwnProperty("post")?r.eventMethod=!0===r.post?"post":"get":r.eventMethod=r.eventMethod||"beacon";var u,h,a,m,l,f,d,o,v,i,p,g,y,_,b,c,w,k,A,x,C,S,j=lt(!0,function(e){!function(e){var t,n=Math.round((new Date).getTime()/1e3),r=Pe("id"),a=Pe("ses"),o=Ie("ses"),i=Ge(),c=i[0],s=i[1],u=i[2],l=i[3],f=i[4],d=i[5],p=i[6];t=!!v&&!!rt.cookie(v);if((Q||t)&&"none"!=ae)return"localStorage"==ae?(tt.attemptWriteLocalStorage(r,""),tt.attemptWriteLocalStorage(a,"")):"cookie"!=ae&&"cookieAndLocalStorage"!=ae||(rt.cookie(r,"",-1,J,K),rt.cookie(a,"",-1,J,K));"0"===c?(k=p,o||"none"==ae||(l++,d=f,k=dt.v4()),de=l):(new Date).getTime()-le>1e3*Y&&(k=dt.v4(),de++);e.add("vp",at.detectViewport()),e.add("ds",at.detectDocumentSize()),e.add("vid",de),e.add("sid",k),e.add("duid",s),e.add("fp",ce),e.add("uid",A),Ce(),e.add("refr",Te(h||z)),e.add("url",Te(m||F)),"none"!=ae&&(Ue(s,u,de,n,d,k),ze());le=(new Date).getTime()}(e),function(e,t){var n,r=new Date;n=!!v&&!!rt.cookie(v);Q||n||(ge.enqueueRequest(e.build(),a),s.expireDateTime=r.getTime()+t)}(e,R)}),T=!1,O={},P={},I={},E=document,L=window,D=navigator,M=nt.fixupUrl(E.domain,L.location.href,tt.getReferrer()),N=tt.fixupDomain(M[0]),F=M[1],z=M[2],U=r.hasOwnProperty("platform")?r.platform:"web",B=r.hasOwnProperty("postPath")?r.postPath:"/com.snowplowanalytics.snowplow/tp2",G=r.hasOwnProperty("appId")?r.appId:"",q=E.title,R=r.hasOwnProperty("pageUnloadTimer")?r.pageUnloadTimer:500,H=!1,V=r.hasOwnProperty("cookieName")?r.cookieName:"_sp_",K=r.hasOwnProperty("cookieDomain")?r.cookieDomain:null,J="/",W=D.doNotTrack||D.msDoNotTrack||L.doNotTrack,Q=!!r.hasOwnProperty("respectDoNotTrack")&&(r.respectDoNotTrack&&("yes"===W||"1"===W)),$=r.hasOwnProperty("cookieLifetime")?r.cookieLifetime:63072e3,Y=r.hasOwnProperty("sessionCookieTimeout")?r.sessionCookieTimeout:1800,Z=r.hasOwnProperty("userFingerprintSeed")?r.userFingerprintSeed:123412414,X=E.characterSet||E.charset,ee=!!r.hasOwnProperty("forceSecureTracker")&&!0===r.forceSecureTracker,te=!(ee||!r.hasOwnProperty("forceUnsecureTracker"))&&!0===r.forceUnsecureTracker,ne=!r.hasOwnProperty("useLocalStorage")||(tt.warn("argmap.useLocalStorage is deprecated. Use argmap.stateStorageStrategy instead."),r.useLocalStorage),re=!r.hasOwnProperty("useCookies")||(tt.warn("argmap.useCookies is deprecated. Use argmap.stateStorageStrategy instead."),r.useCookies),ae=r.hasOwnProperty("stateStorageStrategy")?r.stateStorageStrategy:re||ne?re&&ne?"cookieAndLocalStorage":re?"cookie":"localStorage":"none",oe=D.userLanguage||D.language,ie=at.detectBrowserFeatures("cookie"==ae||"cookieAndLocalStorage"==ae,Pe("testcookie")),ce=!1===r.userFingerprint?"":at.detectSignature(Z),se=e+"_"+t,ue=!1,le=(new Date).getTime(),fe=ot,de=1,pe={transaction:{},items:[]},he=it.getLinkTrackingManager(j,se,Re),me=ct.getFormTrackingManager(j,se,Re),ve=st.errorManager(j),ge=new ut.OutQueueManager(e,t,s,"localStorage"==ae||"cookieAndLocalStorage"==ae,r.eventMethod,B,r.bufferSize,r.maxPostBytes||4e4),ye=!1,_e=r.contexts||{},be=[],we=[],ke=!1,Ae=!1;for(var xe in r.hasOwnProperty("discoverRootDomain")&&r.discoverRootDomain&&(K=tt.findRootDomain()),_e.gaCookies&&be.push((x={},Xe(["__utma","__utmb","__utmc","__utmv","__utmz","_ga"],function(e){var t=rt.cookie(e);t&&(x[e]=t)}),{schema:"iglu:com.google.analytics/cookies/jsonschema/1-0-0",data:x})),_e.geolocation&&Je(),j.setBase64Encoding(!r.hasOwnProperty("encodeBase64")||r.encodeBase64),j.setTrackerVersion(n),j.setTrackerNamespace(t),j.setAppId(G),j.setPlatform(U),j.setTimezone(at.detectTimezone()),j.addPayloadPair("lang",oe),j.addPayloadPair("cs",X),ie)Object.prototype.hasOwnProperty.call(ie,xe)&&("res"===xe||"cd"===xe||"cookie"===xe?j.addPayloadPair(xe,ie[xe]):j.addPayloadPair("f_"+xe,ie[xe]));function Ce(){(M=nt.fixupUrl(E.domain,L.location.href,tt.getReferrer()))[1]!==F&&(z=tt.getReferrer(F)),N=tt.fixupDomain(M[0]),F=M[1]}function Se(){var e=(new Date).getTime();this.href&&(this.href=tt.decorateQuerystring(this.href,"_sp",w+"."+e))}function je(e){for(var t=0;t<E.links.length;t++){var n=E.links[t];!n.spDecorationEnabled&&e(n)&&(tt.addEventListener(n,"click",Se,!0),tt.addEventListener(n,"mousedown",Se,!0),n.spDecorationEnabled=!0)}}function Te(e){var t;return o?(t=new RegExp("#.*"),e.replace(t,"")):e}function Oe(e){var t=new RegExp("^([a-z]+):").exec(e);return t?t[1]:null}function Pe(e){return V+e+"."+c}function Ie(e){var t=Pe(e);return"localStorage"==ae?tt.attemptGetLocalStorage(t):"cookie"==ae||"cookieAndLocalStorage"==ae?rt.cookie(t):void 0}function Ee(){Ce(),c=fe((K||N)+(J||"/")).slice(0,4)}function Le(){var e=new Date;p=e.getTime()}function De(){!function(){var e=Me(),t=e[0];t<g?g=t:y<t&&(y=t);var n=e[1];n<_?_=n:b<n&&(b=n)}(),Le()}function Me(){var e=E.compatMode&&"BackCompat"!==E.compatMode?E.documentElement:E.body;return[e.scrollLeft||L.pageXOffset,e.scrollTop||L.pageYOffset]}function Ne(){var e=Me(),t=e[0];y=g=t;var n=e[1];b=_=n}function Fe(e){var t=Math.round(e);if(!isNaN(t))return t}function ze(){Be(Pe("ses"),"*",Y)}function Ue(e,t,n,r,a,o){Be(Pe("id"),e+"."+t+"."+n+"."+r+"."+a+"."+o,$)}function Be(e,t,n){"localStorage"==ae?tt.attemptWriteLocalStorage(e,t):"cookie"!=ae&&"cookieAndLocalStorage"!=ae||rt.cookie(e,t,n,J,K)}function Ge(){if("none"==ae)return[];var e,t=new Date,n=Math.round(t.getTime()/1e3),r=Ie("id");return r?(e=r.split(".")).unshift("0"):e=["1",w,n,0,n,""],e[6]||(e[6]=dt.v4()),e}function qe(e){return ee?"https://"+e:te?"http://"+e:("https:"===E.location.protocol?"https":"http")+"://"+e}function Re(e){var t,n,r,a,o,i=be.concat(e||[]);if(_e.webPage&&i.push({schema:"iglu:com.snowplowanalytics.snowplow/web_page/jsonschema/1-0-0",data:{id:He()}}),_e.performanceTiming){var c=function(){var e=["navigationStart","redirectStart","redirectEnd","fetchStart","domainLookupStart","domainLookupEnd","connectStart","secureConnectionStart","connectEnd","requestStart","responseStart","responseEnd","unloadEventStart","unloadEventEnd","domLoading","domInteractive","domContentLoadedEventStart","domContentLoadedEventEnd","domComplete","loadEventStart","loadEventEnd","msFirstPaint","chromeFirstPaint","requestEnd","proxyStart","proxyEnd"],t=L.performance||L.mozPerformance||L.msPerformance||L.webkitPerformance;if(t){var n={};for(var r in t.timing)tt.isValueInArray(r,e)&&null!==t.timing[r]&&(n[r]=t.timing[r]);return delete n.requestEnd,L.chrome&&L.chrome.loadTimes&&"number"==typeof L.chrome.loadTimes().firstPaintTime&&(n.chromeFirstPaint=Math.round(1e3*L.chrome.loadTimes().firstPaintTime)),{schema:"iglu:org.w3/PerformanceTiming/jsonschema/1-0-0",data:n}}}();c&&i.push(c)}if(L.optimizely){if(_e.optimizelySummary){var s=et((a=Ve("state"),o=Ve("experiments"),et(a&&o&&a.activeExperiments,function(e){var t=o[e];return{activeExperimentId:e.toString(),variation:a.variationIdsMap[e][0].toString(),conditional:t&&t.conditional,manual:t&&t.manual,name:t&&t.name}})),function(e){return{schema:"iglu:com.optimizely.snowplow/optimizely_summary/jsonschema/1-0-0",data:e}});Xe(s,function(e){i.push(e)})}if(_e.optimizelyXSummary){s=et((t=Ke("state"),n=t.getActiveExperimentIds(),Ke("data","experiments"),r=Ke("visitor"),et(n,function(e){return variation=t.getVariationMap()[e],variationName=variation.name,variationId=variation.id,visitorId=r.visitorId,{experimentId:parseInt(e),variationName:variationName,variation:parseInt(variationId),visitorId:visitorId}})),function(e){return{schema:"iglu:com.optimizely.optimizelyx/summary/jsonschema/1-0-0",data:e}});Xe(s,function(e){i.push(e)})}if(_e.optimizelyExperiments)for(var u=function(){var e=Ve("experiments");if(e){var t=[];for(var n in e)if(e.hasOwnProperty(n)){var r={};r.id=n;var a=e[n];r.code=a.code,r.manual=a.manual,r.conditional=a.conditional,r.name=a.name,r.variationIds=a.variation_ids,t.push({schema:"iglu:com.optimizely/experiment/jsonschema/1-0-0",data:r})}return t}return[]}(),l=0;l<u.length;l++)i.push(u[l]);if(_e.optimizelyStates){var f=function(){var e=[],t=Ve("experiments");if(t)for(var n in t)t.hasOwnProperty(n)&&e.push(n);var r=Ve("state");if(r){for(var a=[],o=r.activeExperiments||[],i=0;i<e.length;i++){var c=e[i],s={};s.experimentId=c,s.isActive=tt.isValueInArray(e[i],o);var u=r.variationMap||{};s.variationIndex=u[c];var l=r.variationNamesMap||{};s.variationName=l[c];var f=r.variationIdsMap||{};f[c]&&1===f[c].length&&(s.variationId=f[c][0]),a.push({schema:"iglu:com.optimizely/state/jsonschema/1-0-0",data:s})}return a}return[]}();for(l=0;l<f.length;l++)i.push(f[l])}if(_e.optimizelyVariations){var d=function(){var e=Ve("variations");if(e){var t=[];for(var n in e)if(e.hasOwnProperty(n)){var r={};r.id=n;var a=e[n];r.name=a.name,r.code=a.code,t.push({schema:"iglu:com.optimizely/variation/jsonschema/1-0-0",data:r})}return t}return[]}();for(l=0;l<d.length;l++)i.push(d[l])}if(_e.optimizelyVisitor){var p=function(){var e=Ve("visitor");if(e){var t={};t.browser=e.browser,t.browserVersion=e.browserVersion,t.device=e.device,t.deviceType=e.deviceType,t.ip=e.ip;var n=e.platform||{};t.platformId=n.id,t.platformVersion=n.version;var r=e.location||{};return t.locationCity=r.city,t.locationRegion=r.region,t.locationCountry=r.country,t.mobile=e.mobile,t.mobileId=e.mobileId,t.referrer=e.referrer,t.os=e.os,{schema:"iglu:com.optimizely/visitor/jsonschema/1-0-0",data:t}}}();p&&i.push(p)}if(_e.optimizelyAudiences){var h=function(){var e=Ve("visitor","audiences");if(e){var t=[];for(var n in e)if(e.hasOwnProperty(n)){var r={id:n,isMember:e[n]};t.push({schema:"iglu:com.optimizely/visitor_audience/jsonschema/1-0-0",data:r})}return t}return[]}();for(l=0;l<h.length;l++)i.push(h[l])}if(_e.optimizelyDimensions){var m=function(){var e=Ve("visitor","dimensions");if(e){var t=[];for(var n in e)if(e.hasOwnProperty(n)){var r={id:n,value:e[n]};t.push({schema:"iglu:com.optimizely/visitor_dimension/jsonschema/1-0-0",data:r})}return t}return[]}();for(l=0;l<m.length;l++)i.push(m[l])}}if(_e.augurIdentityLite){var v=function(){var e=L.augur;if(e){var t={consumer:{},device:{}},n=e.consumer||{};t.consumer.UUID=n.UID;var r=e.device||{};t.device.ID=r.ID,t.device.isBot=r.isBot,t.device.isProxied=r.isProxied,t.device.isTor=r.isTor;var a=r.fingerprint||{};return t.device.isIncognito=a.browserHasIncognitoEnabled,{schema:"iglu:io.augur.snowplow/identity_lite/jsonschema/1-0-0",data:t}}}();v&&i.push(v)}if(_e.parrable){var g=function(){var e=window._hawk;if(e){var t={encryptedId:null,optout:null};t.encryptedId=e.browserid;var n=new RegExp("(?:^|;)\\s?"+"_parrable_hawk_optout".replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")+"=(.*?)(?:;|$)","i"),r=document.cookie.match(n);return t.optout=r&&decodeURIComponent(r[1])?r&&decodeURIComponent(r[1]):"false",{schema:"iglu:com.parrable/encrypted_payload/jsonschema/1-0-0",data:t}}}();g&&i.push(g)}return i}function He(){return null==s.pageViewId&&(s.pageViewId=dt.v4()),s.pageViewId}function Ve(e,t){var n;return L.optimizely&&L.optimizely.data&&(n=L.optimizely.data[e],void 0!==t&&void 0!==n&&(n=n[t])),n}function Ke(e,t){var n;return L.optimizely&&(n=L.optimizely.get(e),void 0!==t&&void 0!==n&&(n=n[t])),n}function Je(){!ye&&D.geolocation&&D.geolocation.getCurrentPosition&&(ye=!0,D.geolocation.getCurrentPosition(function(e){var t=e.coords,n={schema:"iglu:com.snowplowanalytics.snowplow/geolocation_context/jsonschema/1-1-0",data:{latitude:t.latitude,longitude:t.longitude,latitudeLongitudeAccuracy:t.accuracy,altitude:t.altitude,altitudeAccuracy:t.altitudeAccuracy,bearing:t.heading,speed:t.speed,timestamp:Math.round(e.timestamp)}};be.push(n)}))}function We(e,t){return(e||[]).concat(t?t():[])}function Qe(e,t,n,r){Ce(),Ae&&(ke&&null!=s.pageViewId||(s.pageViewId=dt.v4())),Ae=!0,q=E.title,l=e;var a=tt.fixupTitle(l||q);j.trackPageView(Te(m||F),a,Te(h||z),Re(We(t,n)),r);var o=new Date;if(H&&!ue){ue=!0;var i={update:function(){if("undefined"!=typeof window&&"function"==typeof window.addEventListener){var e=!1,t=Object.defineProperty({},"passive",{get:function(){e=!0}}),n=function(){};window.addEventListener("testPassiveEventSupport",n,t),window.removeEventListener("testPassiveEventSupport",n,t),i.hasSupport=e}}};i.update();var c="onwheel"in document.createElement("div")?"wheel":void 0!==document.onmousewheel?"mousewheel":"DOMMouseScroll";Object.prototype.hasOwnProperty.call(i,"hasSupport")?tt.addEventListener(E,c,Le,{passive:!0}):tt.addEventListener(E,c,Le),Ne(),tt.addEventListener(E,"click",Le),tt.addEventListener(E,"mouseup",Le),tt.addEventListener(E,"mousedown",Le),tt.addEventListener(E,"mousemove",Le),tt.addEventListener(L,"scroll",De),tt.addEventListener(E,"keypress",Le),tt.addEventListener(E,"keydown",Le),tt.addEventListener(E,"keyup",Le),tt.addEventListener(L,"resize",Le),tt.addEventListener(L,"focus",Le),tt.addEventListener(L,"blur",Le),p=o.getTime(),clearInterval(u),u=setInterval(function(){var e=new Date;p+d>e.getTime()&&f<e.getTime()&&function(e){Ce();var t=E.title;t!==q&&(q=t,l=null);j.trackPagePing(Te(m||F),tt.fixupTitle(l||q),Te(h||z),Fe(g),Fe(y),Fe(_),Fe(b),Re(e)),Ne()}(We(t,n))},d)}}function $e(e,t){return""!==e?e+t.charAt(0).toUpperCase()+t.slice(1):t}function Ye(t){var e,n,r,a=["","webkit","ms","moz"];if(!i)for(n=0;n<a.length;n++){if(E[$e(r=a[n],"hidden")]){"prerender"===E[$e(r,"visibilityState")]&&(e=!0);break}if(!1===E[$e(r,"hidden")])break}e?tt.addEventListener(E,r+"visibilitychange",function e(){E.removeEventListener(r+"visibilitychange",e,!1),t()}):t()}function Ze(){I=T?O:P}return Ee(),C="none"!=ae&&!!Ie("ses"),(S=Ge())[1]?w=S[1]:(w=dt.v4(),S[1]=w),k=S[6],C||(S[3]++,k=dt.v4(),S[6]=k,S[5]=S[4]),"none"!=ae&&(ze(),S[4]=Math.round((new Date).getTime()/1e3),S.shift(),Ue.apply(null,S)),r.crossDomainLinker&&je(r.crossDomainLinker),O.getDomainSessionIndex=function(){return de},O.getPageViewId=function(){return He()},O.newSession=function(){var e=Math.round((new Date).getTime()/1e3),t=(Ie("ses"),Ge()),n=t[0],r=t[1],a=t[2],o=t[3],i=t[4],c=t[5],s=t[6];"0"===n?(k=s,"none"!=ae&&(o++,c=i,k=dt.v4()),de=o,ze()):(k=dt.v4(),de++),"none"!=ae&&(Ue(r,a,de,e,c,k),ze()),le=(new Date).getTime()},O.getCookieName=function(e){return Pe(e)},O.getUserId=function(){return A},O.getDomainUserId=function(){return Ge()[1]},O.getDomainUserInfo=function(){return Ge()},O.getUserFingerprint=function(){return ce},O.setAppId=function(e){tt.warn('setAppId is deprecated. Instead add an "appId" field to the argmap argument of newTracker.'),j.setAppId(e)},O.setReferrerUrl=function(e){h=e},O.setCustomUrl=function(e){var t,n,r;Ce(),t=F,m=Oe(n=e)?n:"/"===n.slice(0,1)?Oe(t)+"://"+tt.getHostName(t)+n:(0<=(r=(t=Te(t)).indexOf("?"))&&(t=t.slice(0,r)),(r=t.lastIndexOf("/"))!==t.length-1&&(t=t.slice(0,r+1)),t+n)},O.setDocumentTitle=function(e){q=E.title,l=e},O.discardHashTag=function(e){o=e},O.setCookieNamePrefix=function(e){tt.warn('setCookieNamePrefix is deprecated. Instead add a "cookieName" field to the argmap argument of newTracker.'),V=e},O.setCookieDomain=function(e){tt.warn('setCookieDomain is deprecated. Instead add a "cookieDomain" field to the argmap argument of newTracker.'),K=tt.fixupDomain(e),Ee()},O.setCookiePath=function(e){J=e,Ee()},O.setVisitorCookieTimeout=function(e){$=e},O.setSessionCookieTimeout=function(e){tt.warn('setSessionCookieTimeout is deprecated. Instead add a "sessionCookieTimeout" field to the argmap argument of newTracker.'),Y=e},O.setUserFingerprintSeed=function(e){tt.warn('setUserFingerprintSeed is deprecated. Instead add a "userFingerprintSeed" field to the argmap argument of newTracker.'),Z=e,ce=at.detectSignature(Z)},O.enableUserFingerprint=function(e){tt.warn('enableUserFingerprintSeed is deprecated. Instead add a "userFingerprint" field to the argmap argument of newTracker.'),e||(ce="")},O.respectDoNotTrack=function(e){tt.warn('This usage of respectDoNotTrack is deprecated. Instead add a "respectDoNotTrack" field to the argmap argument of newTracker.');var t=D.doNotTrack||D.msDoNotTrack;Q=e&&("yes"===t||"1"===t)},O.crossDomainLinker=function(e){je(e)},O.enableLinkClickTracking=function(e,t,n,r){s.hasLoaded?(he.configureLinkClickTracking(e,t,n,r),he.addClickListeners()):s.registeredOnLoadHandlers.push(function(){he.configureLinkClickTracking(e,t,n,r),he.addClickListeners()})},O.refreshLinkClickTracking=function(){s.hasLoaded?he.addClickListeners():s.registeredOnLoadHandlers.push(function(){he.addClickListeners()})},O.enableActivityTracking=function(e,t){e===parseInt(e,10)&&t===parseInt(t,10)?(H=!0,f=(new Date).getTime()+1e3*e,d=1e3*t):tt.warn("Activity tracking not enabled, please provide integer values for minimumVisitLength and heartBeatDelay.")},O.updatePageActivity=function(){Le()},O.enableFormTracking=function(e,t){s.hasLoaded?(me.configureFormTracking(e),me.addFormListeners(t)):s.registeredOnLoadHandlers.push(function(){me.configureFormTracking(e),me.addFormListeners(t)})},O.killFrame=function(){L.location!==L.top.location&&(L.top.location=L.location)},O.redirectFile=function(e){"file:"===L.location.protocol&&(L.location=e)},O.setOptOutCookie=function(e){v=e},O.setCountPreRendered=function(e){i=e},O.setUserId=function(e){A=e},O.identifyUser=function(e){setUserId(e)},O.setUserIdFromLocation=function(e){Ce(),A=tt.fromQuerystring(e,F)},O.setUserIdFromReferrer=function(e){Ce(),A=tt.fromQuerystring(e,z)},O.setUserIdFromCookie=function(e){A=rt.cookie(e)},O.setCollectorCf=function(e){a=qe(e+".cloudfront.net")},O.setCollectorUrl=function(e){a=qe(e)},O.setPlatform=function(e){tt.warn('setPlatform is deprecated. Instead add a "platform" field to the argmap argument of newTracker.'),j.setPlatform(e)},O.encodeBase64=function(e){tt.warn('This usage of encodeBase64 is deprecated. Instead add an "encodeBase64" field to the argmap argument of newTracker.'),j.setBase64Encoding(e)},O.flushBuffer=function(){ge.executeQueue()},O.enableGeolocationContext=Je,O.trackPageView=function(e,t,n,r){Ye(function(){Qe(e,t,n,r)})},O.trackStructEvent=function(e,t,n,r,a,o,i){Ye(function(){j.trackStructEvent(e,t,n,r,a,Re(o),i)})},O.trackSelfDescribingEvent=function(e,t,n){Ye(function(){j.trackSelfDescribingEvent(e,Re(t),n)})},O.trackUnstructEvent=function(e,t,n){Ye(function(){j.trackSelfDescribingEvent(e,Re(t),n)})},O.addTrans=function(e,t,n,r,a,o,i,c,s,u,l){pe.transaction={orderId:e,affiliation:t,total:n,tax:r,shipping:a,city:o,state:i,country:c,currency:s,context:u,tstamp:l}},O.addItem=function(e,t,n,r,a,o,i,c,s){pe.items.push({orderId:e,sku:t,name:n,category:r,price:a,quantity:o,currency:i,context:c,tstamp:s})},O.trackTrans=function(){Ye(function(){var e,t,n,r,a,o,i,c,s,u,l,f,d,p,h,m,v,g,y,_;e=pe.transaction.orderId,t=pe.transaction.affiliation,n=pe.transaction.total,r=pe.transaction.tax,a=pe.transaction.shipping,o=pe.transaction.city,i=pe.transaction.state,c=pe.transaction.country,s=pe.transaction.currency,u=pe.transaction.context,l=pe.transaction.tstamp,j.trackEcommerceTransaction(e,t,n,r,a,o,i,c,s,Re(u),l);for(var b=0;b<pe.items.length;b++){var w=pe.items[b];f=w.orderId,d=w.sku,p=w.name,h=w.category,m=w.price,v=w.quantity,g=w.currency,y=w.context,_=w.tstamp,j.trackEcommerceTransactionItem(f,d,p,h,m,v,g,Re(y),_)}pe={transaction:{},items:[]}})},O.trackLinkClick=function(e,t,n,r,a,o,i){Ye(function(){j.trackLinkClick(e,t,n,r,a,Re(o),i)})},O.trackAdImpression=function(e,t,n,r,a,o,i,c,s,u){Ye(function(){j.trackAdImpression(e,t,n,r,a,o,i,c,Re(s),u)})},O.trackAdClick=function(e,t,n,r,a,o,i,c,s,u,l){Ye(function(){j.trackAdClick(e,t,n,r,a,o,i,c,s,Re(u),l)})},O.trackAdConversion=function(e,t,n,r,a,o,i,c,s,u,l){Ye(function(){j.trackAdConversion(e,t,n,r,a,o,i,c,s,Re(u),l)})},O.trackSocialInteraction=function(e,t,n,r,a){Ye(function(){j.trackSocialInteraction(e,t,n,Re(r),a)})},O.trackAddToCart=function(e,t,n,r,a,o,i,c){Ye(function(){j.trackAddToCart(e,t,n,r,a,o,Re(i),c)})},O.trackRemoveFromCart=function(e,t,n,r,a,o,i,c){Ye(function(){j.trackRemoveFromCart(e,t,n,r,a,o,Re(i),c)})},O.trackSiteSearch=function(e,t,n,r,a,o){Ye(function(){j.trackSiteSearch(e,t,n,r,Re(a),o)})},O.trackTiming=function(e,t,n,r,a,o){Ye(function(){j.trackSelfDescribingEvent({schema:"iglu:com.snowplowanalytics.snowplow/timing/jsonschema/1-0-0",data:{category:e,variable:t,timing:n,label:r}},Re(a),o)})},O.trackConsentWithdrawn=function(e,t,n,r,a,o,i){Ye(function(){j.trackConsentWithdrawn(e,t,n,r,a,Re(o),i)})},O.trackConsentGranted=function(e,t,n,r,a,o,i){Ye(function(){j.trackConsentGranted(e,t,n,r,a,Re(o),i)})},O.trackEnhancedEcommerceAction=function(e,t,n){var r=we.concat(t||[]);we.length=0,Ye(function(){j.trackSelfDescribingEvent({schema:"iglu:com.google.analytics.enhanced-ecommerce/action/jsonschema/1-0-0",data:{action:e}},Re(r),n)})},O.addEnhancedEcommerceActionContext=function(e,t,n,r,a,o,i,c,s,u){we.push({schema:"iglu:com.google.analytics.enhanced-ecommerce/actionFieldObject/jsonschema/1-0-0",data:{id:e,affiliation:t,revenue:tt.parseFloat(n),tax:tt.parseFloat(r),shipping:tt.parseFloat(a),coupon:o,list:i,step:tt.parseInt(c),option:s,currency:u}})},O.addEnhancedEcommerceImpressionContext=function(e,t,n,r,a,o,i,c,s){we.push({schema:"iglu:com.google.analytics.enhanced-ecommerce/impressionFieldObject/jsonschema/1-0-0",data:{id:e,name:t,list:n,brand:r,category:a,variant:o,position:tt.parseInt(i),price:tt.parseFloat(c),currency:s}})},O.addEnhancedEcommerceProductContext=function(e,t,n,r,a,o,i,c,s,u,l){we.push({schema:"iglu:com.google.analytics.enhanced-ecommerce/productFieldObject/jsonschema/1-0-0",data:{id:e,name:t,list:n,brand:r,category:a,variant:o,price:tt.parseFloat(i),quantity:tt.parseInt(c),coupon:s,position:tt.parseInt(u),currency:l}})},O.addEnhancedEcommercePromoContext=function(e,t,n,r,a){we.push({schema:"iglu:com.google.analytics.enhanced-ecommerce/promoFieldObject/jsonschema/1-0-0",data:{id:e,name:t,creative:n,position:r,currency:a}})},O.addGlobalContexts=function(e){j.addGlobalContexts(e)},O.removeGlobalContexts=function(e){j.removeGlobalContexts(e)},O.clearGlobalContexts=function(){j.clearGlobalContexts()},O.enableErrorTracking=function(e,t){ve.enableErrorTracking(e,t,Re())},O.trackError=function(e,t,n,r,a,o){var i=Re(o);ve.trackError(e,t,n,r,a,i)},O.preservePageViewId=function(){ke=!0},O.setDebug=function(e){T=Boolean(e).valueOf(),Ze()},P=ft(O),Ze(),I}}()},{"./errors":162,"./forms":163,"./guard":164,"./lib/detectors":167,"./lib/helpers":168,"./lib/proxies":169,"./links":170,"./out_queue":171,"browser-cookie-lite":1,"lodash/forEach":123,"lodash/map":143,sha1:154,"snowplow-tracker-core":155,uuid:161}]},{},[166]);
+
+'use strict';(function(){function H(a){"@babel/helpers - typeof";H="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"===typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};return H(a)}function Db(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var e=Object.getOwnPropertySymbols(a);b&&(e=e.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable}));c.push.apply(c,e)}return c}
+function ld(a){for(var b=1;b<arguments.length;b++){var c=null!=arguments[b]?arguments[b]:{};b%2?Db(Object(c),!0).forEach(function(b){var d=c[b];b in a?Object.defineProperty(a,b,{value:d,enumerable:!0,configurable:!0,writable:!0}):a[b]=d}):Object.getOwnPropertyDescriptors?Object.defineProperties(a,Object.getOwnPropertyDescriptors(c)):Db(Object(c)).forEach(function(b){Object.defineProperty(a,b,Object.getOwnPropertyDescriptor(c,b))})}return a}function pa(a){var b=Array.isArray(a)?hb(a):void 0;b||(b=
+"undefined"!==typeof Symbol&&Symbol.iterator in Object(a)?Array.from(a):void 0);if(!(a=b||Eb(a)))throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");return a}function Eb(a,b){if(a){if("string"===typeof a)return hb(a,b);var c=Object.prototype.toString.call(a).slice(8,-1);"Object"===c&&a.constructor&&(c=a.constructor.name);if("Map"===c||"Set"===c)return Array.from(a);if("Arguments"===c||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c))return hb(a,
+b)}}function hb(a,b){if(null==b||b>a.length)b=a.length;for(var c=0,e=Array(b);c<b;c++)e[c]=a[c];return e}function Fa(a,b){var c;if("undefined"===typeof Symbol||null==a[Symbol.iterator]){if(Array.isArray(a)||(c=Eb(a))||b&&a&&"number"===typeof a.length){c&&(a=c);var e=0;b=function(){};return{s:b,n:function(){return e>=a.length?{done:!0}:{done:!1,value:a[e++]}},e:function(a){throw a;},f:b}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
+}var d=!0,f=!1,h;return{s:function(){c=a[Symbol.iterator]()},n:function(){var a=c.next();d=a.done;return a},e:function(a){f=!0;h=a},f:function(){try{d||null==c.return||c.return()}finally{if(f)throw h;}}}}function qa(a,b,c){return c={path:b,exports:{},require:function(a,b){throw Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs");}},a(c,c.exports),c.exports}function ra(a){var b=-1,c=null==a?0:a.length;for(this.clear();++b<c;){var e=a[b];this.set(e[0],e[1])}}function Y(a){var b=
+-1,c=null==a?0:a.length;for(this.clear();++b<c;){var e=a[b];this.set(e[0],e[1])}}function sa(a){var b=-1,c=null==a?0:a.length;for(this.clear();++b<c;){var e=a[b];this.set(e[0],e[1])}}function ta(a){this.size=(this.__data__=new Ga(a)).size}function ua(a){var b=-1,c=null==a?0:a.length;for(this.__data__=new Ha;++b<c;)this.add(a[b])}function Ia(a,b,c,e,d){if(a===b)b=!0;else if(null==a||null==b||!T(a)&&!T(b))b=a!==a&&b!==b;else a:{var f=F(a),h=F(b),g=f?"[object Array]":Fb(a),k=h?"[object Array]":Fb(b);
+g="[object Arguments]"==g?"[object Object]":g;k="[object Arguments]"==k?"[object Object]":k;var p="[object Object]"==g;h="[object Object]"==k;if((k=g==k)&&ib(a)){if(!ib(b)){b=!1;break a}f=!0;p=!1}if(k&&!p)d||(d=new Ja),b=f||Rb(a)?gc(a,b,c,e,Ia,d):md(a,b,g,c,e,Ia,d);else{if(!(c&1)&&(f=p&&hc.call(a,"__wrapped__"),g=h&&hc.call(b,"__wrapped__"),f||g)){a=f?a.value():a;b=g?b.value():b;d||(d=new Ja);b=Ia(a,b,c,e,d);break a}if(k)b:if(d||(d=new Ja),f=c&1,g=ic(a,Ka,jc),h=g.length,k=ic(b,Ka,jc).length,h==k||
+f){for(k=h;k--;){var x=g[k];if(!(f?x in b:nd.call(b,x))){b=!1;break b}}p=d.get(a);x=d.get(b);if(p&&x)b=p==b&&x==a;else{p=!0;d.set(a,b);d.set(b,a);for(var q=f;++k<h;){x=g[k];var n=a[x],z=b[x];if(e)var t=f?e(z,n,x,b,a,d):e(n,z,x,a,b,d);if(void 0===t?n!==z&&!Ia(n,z,c,e,d):!t){p=!1;break}q||(q="constructor"==x)}p&&!q&&(c=a.constructor,e=b.constructor,c!=e&&"constructor"in a&&"constructor"in b&&!("function"==typeof c&&c instanceof c&&"function"==typeof e&&e instanceof e)&&(p=!1));d["delete"](a);d["delete"](b);
+b=p}}else b=!1;else b=!1}}return b}function jb(a,b){if("function"!=typeof a||null!=b&&"function"!=typeof b)throw new TypeError("Expected a function");var c=function d(){var c=arguments,h=b?b.apply(this,c):c[0],g=d.cache;if(g.has(h))return g.get(h);c=a.apply(this,c);d.cache=g.set(h,c)||g;return c};c.cache=new (jb.Cache||Ha);return c}function kc(a){if("string"==typeof a)return a;if(F(a))return lc(a,kc)+"";if(ba(a))return mc?mc.call(a):"";var b=a+"";return"0"==b&&1/a==-od?"-0":b}function nc(a){if(!oc(a)){a=
+a.text||"";var b=va.getElementsByTagName("title");b&&void 0!==b[0]&&(a=b[0].text)}return a}function Sb(a){var b=/^(?:(?:https?|ftp):)\/*(?:[^@]+@)?([^:/#]+)/.exec(a);return b?b[1]:a}function bc(a){var b=a.length;"."===a.charAt(--b)&&(a=a.slice(0,b));"*."===a.slice(0,2)&&(a=a.slice(1));return a}function cc(a){var b="",c=Gb("referrer",ca.location.href)||Gb("referer",ca.location.href);if(c)return c;if(a)return a;try{b=ca.top.document.referrer}catch(e){if(ca.parent)try{b=ca.parent.document.referrer}catch(d){b=
+""}}""===b&&(b=va.referrer);return b}function v(a,b,c,e){if(a.addEventListener)return a.addEventListener(b,c,e),!0;if(a.attachEvent)return a.attachEvent("on"+b,c);a["on"+b]=c}function Gb(a,b){return(a=(new RegExp("^[^#]*[?&]"+a+"=([^&#]*)")).exec(b))?decodeURIComponent(a[1].replace(/\+/g," ")):null}function La(a){var b=Array.prototype.slice.call(arguments,1);return pd(da(a,function(a){if("function"===typeof a)try{return a.apply(null,b)}catch(e){}else return a}))}function E(a){"undefined"!==typeof console&&
+console.warn("Snowplow: "+a)}function kb(a){return a.className.match(/\S+/g)||[]}function Hb(a,b){if(Array.isArray(a)||!N(a))return function(){return!0};if(a.hasOwnProperty("filter"))return a.filter;var c=a.hasOwnProperty("whitelist");a=a.whitelist||a.blacklist;Array.isArray(a)||(a=[a]);for(var e={},d=0;d<a.length;d++)e[a[d]]=!0;return b?function(a){a:{a=kb(a);var b;for(b=0;b<a.length;b++)if(e[a[b]]){a=!0;break a}a=!1}return a===c}:function(a){return a.name in e===c}}function qd(a){return N(a)?a.hasOwnProperty("transform")?
+a.transform:function(a){return a}:function(a){return a}}function Tb(a,b){var c=2<arguments.length&&void 0!==arguments[2]?arguments[2]:63072E3;try{var e=Date.now()+1E3*c;wa.setItem("".concat(a,".expires"),e);wa.setItem(a,b);return!0}catch(d){return!1}}function pc(a){try{return wa.removeItem(a),wa.removeItem(a+".expires"),!0}catch(b){return!1}}function rd(){for(var a="_sp_root_domain_test_"+(new Date).getTime(),b="_test_value_"+(new Date).getTime(),c=ca.location.hostname.split("."),e=c.length-1;0<=
+e;){var d=c.slice(e,c.length).join(".");A(a,b,0,"/",d);if(A(a)===b){A(a,"",-1,"/",d);a=va.cookie.split("; ");b=[];for(c=0;c<a.length;c++)"_sp_root_domain_test_"===a[c].substring(0,21)&&b.push(a[c]);a=b;for(b=0;b<a.length;b++)A(a[b],"",-1,"/",d);return d}--e}return ca.location.hostname}function qc(a,b){for(var c=0;c<b.length;c++)if(b[c]===a)return!0;return!1}function A(a,b,c,e,d,f,h){return 1<arguments.length?va.cookie=a+"="+encodeURIComponent(b)+(c?"; Expires="+(new Date(+new Date+1E3*c)).toUTCString():
+"")+(e?"; Path="+e:"")+(d?"; Domain="+d:"")+(f?"; SameSite="+f:"")+(h?"; Secure":""):decodeURIComponent((("; "+va.cookie).split("; "+a+"=")[1]||"").split(";")[0])}function lb(a){a=parseInt(a);return isNaN(a)?void 0:a}function Ib(a){a=parseFloat(a);return isNaN(a)?void 0:a}function xa(a){return a&&"function"===typeof a?!0:!1}function sd(a,b,c,e,d){function f(e,f,h){h=h||{};g.hasOwnProperty(e)?E("Tracker namespace "+e+" already exists."):(g[e]=new a(d,e,b,c,h),g[e].setCollectorUrl(f))}function h(){var a;
+for(a=0;a<arguments.length;a+=1){var b=arguments[a];var c=Array.prototype.shift.call(b);if(xa(c))try{c.apply(g,b)}catch(mb){E("Custom callback error - ".concat(mb))}finally{continue}var d=c.split(":");c=d[0];d=1<d.length?d[1].split(";"):[];d=[c,d];c=d[0];d=d[1];if("newTracker"===c)f(b[0],b[1],b[2]);else if("setCollectorCf"!==c&&"setCollectorUrl"!==c||d&&0!==d.length){var e=[];if(d&&0!==d.length)for(var h=0;h<d.length;h++)g.hasOwnProperty(d[h])?e.push(g[d[h]]):E('Warning: Tracker namespace "'+d[h]+
+'" not configured');else e=da(g);0===e.length&&E("Warning: No tracker configured");for(d=0;d<e.length;d++)e[d][c].apply(e[d],b)}else d=b[0],b=b[1],E(c+" is deprecated. Set the collector when a new tracker instance using newTracker."),b=void 0===b?"sp":b,f(b),g[b][c](d)}}for(var g={},k=0;k<e.length;k++)h(e[k]);return{push:h}}function rc(a,b,c){if("translate.googleusercontent.com"===a)""===c&&(c=b),a=/^(?:https?|ftp)(?::\/*(?:[^?]+))([?][^#]+)/.exec(b),b=Gb("u",a[1]),a=Sb(b);else{var e;if(!(e="cc.bingj.com"===
+a||"webcache.googleusercontent.com"===a))a:{if(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(a))try{var d=document.body.children[0].children[0].children[0].children[0].children[0].children[0].innerHTML;e="You have reached the cached page for"===d.slice(0,36);break a}catch(f){e=!1;break a}e=void 0}e&&(b=document.links[0].href,a=Sb(b))}return[a,b,c]}function td(){try{var a=!!ya.localStorage}catch(b){a=
+!0}if(!a)return!1;try{return ya.localStorage.setItem("modernizr","modernizr"),ya.localStorage.removeItem("modernizr"),!0}catch(b){return!1}}function ud(){var a=ya,b="inner";"innerWidth"in ya||(b="client",a=Ma.documentElement||Ma.body);var c=a[b+"Width"];a=a[b+"Height"];return 0<=c&&0<=a?c+"x"+a:null}function vd(){var a=Ma.documentElement,b=Ma.body,c=Math.max(a.clientWidth,a.offsetWidth,a.scrollWidth);a=Math.max(a.clientHeight,a.offsetHeight,a.scrollHeight,b?Math.max(b.offsetHeight,b.scrollHeight):
+0);return isNaN(c)||isNaN(a)?"":c+"x"+a}function wd(a,b){var c,e={pdf:"application/pdf",qt:"video/quicktime",realp:"audio/x-pn-realaudio-plugin",wma:"application/x-mplayer2",dir:"application/x-director",fla:"application/x-shockwave-flash",java:"application/x-java-vm",gears:"application/x-googlegears",ag:"application/x-silverlight"},d={};if(R.mimeTypes&&R.mimeTypes.length)for(c in e)if(Object.prototype.hasOwnProperty.call(e,c)){var f=R.mimeTypes[e[c]];d[c]=f&&f.enabledPlugin?"1":"0"}R.constructor===
+window.Navigator&&"unknown"!==typeof R.javaEnabled&&void 0!==R.javaEnabled&&R.javaEnabled()&&(d.java="1");xa(ya.GearsFactory)&&(d.gears="1");d.res=nb.width+"x"+nb.height;d.cd=nb.colorDepth;a&&(a=b||"testcookie",void 0===R.cookieEnabled?(A(a,"1"),a="1"===A(a)?"1":"0"):a=R.cookieEnabled?"1":"0",d.cookie=a);return d}function xd(a,b,c){function e(b,d){for(var e,f,h,k;null!==(e=b.parentNode)&&void 0!==e&&"A"!==(f=b.tagName.toUpperCase())&&"AREA"!==f;)b=e;if(void 0!==b.href){e=b.hostname||Sb(b.href);f=
+e.toLowerCase();var p=b.href.replace(e,f);/^(javascript|vbscript|jscript|mocha|livescript|ecmascript|mailto):/i.test(p)||(e=b.id,f=kb(b),h=b.target,k=g?b.innerHTML:null,p=unescape(p),a.trackLinkClick(p,e,f,h,k,c(La(d,b))))}}function d(a){return function(b){b=b||window.event;var c=b.which||b.button;var d=b.target||b.srcElement;"click"===b.type?d&&e(d,a):"mousedown"===b.type?1!==c&&2!==c||!d?p=x=null:(p=c,x=d):"mouseup"===b.type&&(c===p&&d===x&&e(d,a),p=x=null)}}var f,h,g,k,p,x;return{configureLinkClickTracking:function(a,
+b,c,d){g=c;k=d;h=b;f=Hb(a,!0)},addClickListeners:function(){var a=document.links,c;for(c=0;c<a.length;c++)if(f(a[c])&&!a[c][b]){var e=a[c];h?(v(e,"mouseup",d(k),!1),v(e,"mousedown",d(k),!1)):v(e,"click",d(k),!1);a[c][b]=!0}}}}function yd(a,b,c){function e(a){return a[zd(["name","id","type","nodeName"],function(b){return a[b]&&"string"===typeof a[b]})]}function d(a){for(;a&&a.nodeName&&"HTML"!==a.nodeName.toUpperCase()&&"FORM"!==a.nodeName.toUpperCase();)a=a.parentNode;if(a&&a.nodeName&&"FORM"===a.nodeName.toUpperCase())return e(a)}
+function f(a){var b=[];L(k,function(c){c=a.getElementsByTagName(c).filter(function(a){return a.hasOwnProperty(p)});L(c,function(a){if("submit"!==a.type){var c={name:e(a),value:a.value,nodeName:a.nodeName};a.type&&"INPUT"===a.nodeName.toUpperCase()&&(c.type=a.type);"checkbox"!==a.type&&"radio"!==a.type||a.checked||(c.value=null);b.push(c)}})});return b}function h(b,f){return function(g){g=g.target;var h=g.nodeName&&"INPUT"===g.nodeName.toUpperCase()?g.type:null,k="checkbox"!==g.type||g.checked?n(g.value,
+g):null;("change_form"===b||"checkbox"!==h&&"radio"!==h)&&a.trackFormFocusOrChange(b,d(g),e(g),g.nodeName,h,kb(g),k,c(La(f,g,h,k)))}}function g(b){return function(d){d=d.target;var g=f(d);L(g,function(a){a.value=n(a.value,a)});a.trackFormSubmission(e(d),kb(d),g,c(La(b,d,g)))}}var k=["textarea","input","select"],p=b+"form",x=function(){return!0},q=function(){return!0},n=function(a){return a};return{configureFormTracking:function(a){a&&(x=Hb(a.forms,!0),q=Hb(a.fields,!1),n=qd(a.fields))},addFormListeners:function(a){L(document.getElementsByTagName("form"),
+function(b){x(b)&&!b[p]&&(L(k,function(c){L(b.getElementsByTagName(c),function(b){q(b)&&!b[p]&&"password"!==b.type.toLowerCase()&&(v(b,"focus",h("focus_form",a),!1),v(b,"change",h("change_form",a),!1),b[p]=!0)})}),v(b,"submit",g(a)),b[p]=!0)})}}}function Ad(a){function b(b,e,d,f,h,g){a.trackSelfDescribingEvent({schema:"iglu:com.snowplowanalytics.snowplow/application_error/jsonschema/1-0-1",data:{programmingLanguage:"JAVASCRIPT",message:b||"JS Exception. Browser doesn't support ErrorEvent API",stackTrace:h&&
+h.stack?h.stack:null,lineNumber:d,lineColumn:f,fileName:e}},g)}return{trackError:b,enableErrorTracking:function(a,e,d){v(Bd,"error",function(c){if(xa(a)&&a(c)||null==a){var f=xa(e)?d.concat(e(c)):d;b(c.message,c.filename,c.lineno,c.colno,c.error,f)}},!0)}}}function sc(a,b,c,e,d,f,h,g,k,p,x){function q(a){var b="?",c={co:!0,cx:!0},d=!0,e;for(e in a)a.hasOwnProperty(e)&&!c.hasOwnProperty(e)&&(d?d=!1:b+="&",b+=encodeURIComponent(e)+"="+encodeURIComponent(a[e]));for(var g in c)a.hasOwnProperty(g)&&c.hasOwnProperty(g)&&
+(b+="&"+g+"="+encodeURIComponent(a[g]));return b}function n(a){a=Cd(a,function(a){return a.toString()});return{evt:a,bytes:z(JSON.stringify(a))}}function z(a){for(var b=0,c=0;c<a.length;c++){var d=a.charCodeAt(c);127>=d?b+=1:2047>=d?b+=2:55296<=d&&57343>=d?(b+=4,c++):b=65535>d?b+3:b+4}return b}function t(){for(;D.length&&"string"!==typeof D[0]&&"object"!==H(D[0]);)D.shift();if(1>D.length)O=!1;else{if(!oc(r))throw"No Snowplow collector configured, cannot track";O=!0;var a=D[0];if(P){var b=function(a){for(var b=
+0;b<a;b++)D.shift();e&&Tb(w,JSON.stringify(D.slice(0,p)));t()},c=mb(r),d=setTimeout(function(){c.abort();O=!1},x),f=function(a){for(var b=0,c=0;b<a.length&&!(c+=a[b].bytes,c>=g);)b+=1;return b}(D);c.onreadystatechange=function(){if(4===c.readyState&&200<=c.status&&400>c.status){clearTimeout(d);if(A&&!v)try{uc.setItem(J,!0)}catch(tc){}b(f)}else 4===c.readyState&&400<=c.status&&(clearTimeout(d),O=!1)};a=da(D.slice(0,f),function(a){return a.evt});if(0<a.length){var h;if(!(h=v)&&(h=A))try{h=uc.getItem(J)}catch(tc){h=
+void 0}if(v=h){h=new Blob([m(Jb(a))],{type:"application/json"});try{var q=navigator.sendBeacon(r,h)}catch(tc){q=!1}}!0===q&&b(f);A&&q||c.send(m(Jb(a)))}}else{q=new Image(1,1);var n=!0;q.onload=function(){n&&(n=!1,D.shift(),e&&Tb(w,JSON.stringify(D.slice(0,p))),t())};q.onerror=function(){n&&(O=n=!1)};q.src=k?r+a.replace("?","?stm="+(new Date).getTime()+"&"):r+a;setTimeout(function(){n&&O&&(n=!1,t())},x)}}}function mb(a){var b=new XMLHttpRequest;b.open("POST",a,!0);b.withCredentials=!0;b.setRequestHeader("Content-Type",
+"application/json; charset=UTF-8");return b}function m(a){return JSON.stringify({schema:"iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-4",data:a})}function Jb(a){for(var b=(new Date).getTime().toString(),c=0;c<a.length;c++)a[c].stm=b;return a}var y=window.localStorage,O=!1,r,v;d=d.toLowerCase?d.toLowerCase():d;var F=null===d||!0===d||"beacon"===d||"true"===d,A=!!(F&&navigator&&navigator.sendBeacon)&&F,P=("post"===d||A)&&"get"!==d,L=(P=P&&!!(window.XMLHttpRequest&&"withCredentials"in
+new XMLHttpRequest))?f:"/i";h=td()&&e&&P&&h||1;var w="snowplowOutQueue_".concat(a,"_").concat(b,"_").concat(P?"post2":"get");var J="spBeaconPreflight_".concat(a,"_").concat(b);if(e)try{var D=JSON.parse(y.getItem(w))}catch($e){}Array.isArray(D)||(D=[]);c.outQueues.push(D);P&&1<h&&c.bufferFlushers.push(function(){O||t()});return{enqueueRequest:function(a,b){r=b+L;if(P){a=n(a);if(a.bytes>=g){E("Event of size "+a.bytes+" is too long - the maximum size is "+g);mb(r).send(m(Jb([a.evt])));return}D.push(a)}else D.push(q(a));
+a=!1;e&&(a=Tb(w,JSON.stringify(D.slice(0,p))));O||a&&!(D.length>=h)||t()},executeQueue:t}}function Dd(a){var b={};"object"===H(a)&&null!==a&&Object.getOwnPropertyNames(a).forEach(function(c,e,d){"function"===typeof a[c]&&(b[c]=Ed(a[c]))});return b}function Fd(a){if(!a)return a;switch(4-a.length%4){case 2:a+="==";break;case 3:a+="="}a=a.replace(/-/g,"+").replace(/_/g,"/");return Gd(a)}function Gd(a){var b=0,c=0;var e="";var d=[];if(!a)return a;a+="";do{var f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a.charAt(b++));
+var h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a.charAt(b++));e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a.charAt(b++));var g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a.charAt(b++));var k=f<<18|h<<12|e<<6|g;f=k>>16&255;h=k>>8&255;k&=255;64===e?d[c++]=String.fromCharCode(f):64===g?d[c++]=String.fromCharCode(f,h):d[c++]=String.fromCharCode(f,h,k)}while(b<a.length);e=d.join("");return function(a){return decodeURIComponent(a.split("").map(function(a){return"%"+
+("00"+a.charCodeAt(0).toString(16)).slice(-2)}).join(""))}(e.replace(/\0+$/,""))}function Kb(a){if(!vc(a))return!1;for(var b in a)if(Object.prototype.hasOwnProperty.call(a,b))return!0;return!1}function vc(a){return"undefined"!==typeof a&&null!==a&&(a.constructor==={}.constructor||a.constructor===[].constructor)}function za(a){var b={},c=function(a,c){null!=c&&""!==c&&(b[a]=c)};return{add:c,addDict:function(a){for(var b in a)Object.prototype.hasOwnProperty.call(a,b)&&c(b,a[b])},addJson:function(b,
+d,f){if(f&&Kb(f))if(f=JSON.stringify(f),a){if(f){d=f;var e=f=0,g=[];if(d){d=unescape(encodeURIComponent(d));do{var k=d.charCodeAt(f++);var p=d.charCodeAt(f++);var x=d.charCodeAt(f++);var q=k<<16|p<<8|x;k=q>>18&63;p=q>>12&63;x=q>>6&63;q&=63;g[e++]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(k)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(p)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(x)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(q)}while(f<
+d.length);f=g.join("");d=d.length%3;d=(d?f.slice(0,d-3):f)+"===".slice(d||3)}d=d.replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}else d=f;c(b,d)}else c(d,f)},build:function(){return b}}}function Hd(){var a=[],b=[];return{getGlobalPrimitives:function(){return a},getConditionalProviders:function(){return b},addGlobalContexts:function(c){var e=[],d=[];c=Fa(c);var f;try{for(c.s();!(f=c.n()).done;){var h=f.value;wc(h)?e.push(h):fa(h)&&d.push(h)}}catch(g){c.e(g)}finally{c.f()}a=a.concat(d);b=b.concat(e)},
+clearGlobalContexts:function(){b=[];a=[]},removeGlobalContexts:function(c){c=Fa(c);var e;try{var d=function(){var c=e.value;wc(c)?b=b.filter(function(a){return!ob(a,c)}):fa(c)&&(a=a.filter(function(a){return!ob(a,c)}))};for(c.s();!(e=c.n()).done;)d()}catch(f){c.e(f)}finally{c.f()}},getApplicableContexts:function(c){c=c.build();var e=Kb(c)&&"e"in c?"string"===typeof c.e:!1;if(e){c=ld({},c);try{null!=c&&pb(c,"ue_px",qb)&&(c.ue_px=JSON.parse(Fd(J(c,["ue_px"]))));var d=c}catch(g){d=c}c=d;e="string"===
+typeof J(c,"ue_px.data.schema")?J(c,"ue_px.data.schema"):"string"===typeof J(c,"ue_pr.data.schema")?J(c,"ue_pr.data.schema"):"string"===typeof J(c,"schema")?J(c,"schema"):"";var f=J(c,"e","");d=[];var h=Na(a,c,f,e);d.push.apply(d,pa(h));c=Id(b,c,f,e);d.push.apply(d,pa(c));return d}return[]}}}function Jd(a){if("*"===a[0]||"*"===a[1])return!1;if(0<a.slice(2).length){var b=!1;a=Fa(a.slice(2));var c;try{for(a.s();!(c=a.n()).done;)if("*"===c.value)b=!0;else if(b)return!1}catch(e){a.e(e)}finally{a.f()}return!0}return 2==
+a.length?!0:!1}function xc(a){return(a=a.split("."))&&1<a.length?Jd(a):!1}function yc(a){a=/^iglu:((?:(?:[a-zA-Z0-9-_]+|\*).)+(?:[a-zA-Z0-9-_]+|\*))\/([a-zA-Z0-9-_.]+|\*)\/jsonschema\/([1-9][0-9]*|\*)-(0|[1-9][0-9]*|\*)-(0|[1-9][0-9]*|\*)$/.exec(a);if(null!==a&&xc(a[1]))return a.slice(1,6)}function Lb(a){if(a=yc(a)){var b=a[0];return 5===a.length&&xc(b)}return!1}function Kd(a){return Array.isArray(a)&&a.every(function(a){return"string"===typeof a})}function zc(a){return Kd(a)?a.every(function(a){return Lb(a)}):
+"string"===typeof a?Lb(a):!1}function Oa(a){return Kb(a)&&"schema"in a&&"data"in a?"string"===typeof a.schema&&"object"===H(a.data):!1}function Ld(a){var b=0;if(T(a)&&"[object Object]"==U(a)){var c=Md(a);null===c?c=!0:(c=Nd.call(c,"constructor")&&c.constructor,c="function"==typeof c&&c instanceof c&&Ac.call(c)==Od)}else c=!1;if(c){if(null!=a&&pb(a,"accept",qb))if(zc(a.accept))b+=1;else return!1;if(null!=a&&pb(a,"reject",qb))if(zc(a.reject))b+=1;else return!1;return 0<b&&2>=b}return!1}function Bc(a){return"function"===
+typeof a&&1>=a.length}function fa(a){return"function"===typeof a&&1>=a.length||Oa(a)}function Cc(a){return Array.isArray(a)&&2===a.length?Array.isArray(a[1])?Bc(a[0])&&rb(a[1],fa):Bc(a[0])&&fa(a[1]):!1}function Dc(a){return Array.isArray(a)&&2===a.length?Ld(a[0])?Array.isArray(a[1])?rb(a[1],fa):fa(a[1]):!1:!1}function wc(a){return Cc(a)||Dc(a)}function Pd(a,b){var c=0,e=0,d=J(a,"accept");Array.isArray(d)?a.accept.some(function(a){return sb(a,b)})&&e++:"string"===typeof d&&sb(d,b)&&e++;d=J(a,"reject");
+Array.isArray(d)?a.reject.some(function(a){return sb(a,b)})&&c++:"string"===typeof d&&sb(d,b)&&c++;return 0<e&&0===c?!0:!1}function sb(a,b){if(!Lb(a))return!1;a=yc(a);b=/^iglu:([a-zA-Z0-9-_.]+)\/([a-zA-Z0-9-_]+)\/jsonschema\/([1-9][0-9]*)-(0|[1-9][0-9]*)-(0|[1-9][0-9]*)$/.exec(b);b=null!==b?b.slice(1,6):void 0;if(a&&b){if(!Qd(a[0],b[0]))return!1;for(var c=1;5>c;c++)if(!Ec(a[c],b[c]))return!1;return!0}return!1}function Qd(a,b){b=b.split(".");a=a.split(".");if(b&&a){if(b.length!==a.length)return!1;
+for(var c=0;c<a.length;c++)if(!Ec(b[c],a[c]))return!1;return!0}return!1}function Ec(a,b){return a&&b&&"*"===a||a===b}function Fc(a){return Array.isArray(a)?a:[a]}function Na(a,b,c,e){var d;a=Fc(a);a=da(a,function(a){a:if(Oa(a))a=[a];else{if("function"===typeof a&&1>=a.length){b:{var d=void 0;try{d=a({event:b,eventType:c,eventSchema:e});if(Oa(d)||Array.isArray(d)&&rb(d,Oa)){var g=d;break b}g=void 0;break b}catch(k){}g=void 0}if(Oa(g)){a=[g];break a}else if(Array.isArray(g)){a=g;break a}}a=void 0}if(a&&
+0!==a.length)return a});return(d=[]).concat.apply(d,pa(Gc(a)))}function Id(a,b,c,e){var d;a=Fc(a);a=da(a,function(a){a:{if(Cc(a)){var d=a[0],g=!1;try{g=d({event:b,eventType:c,eventSchema:e})}catch(k){g=!1}if(!0===g){a=Na(a[1],b,c,e);break a}}else if(Dc(a)&&Pd(a[0],e)){a=Na(a[1],b,c,e);break a}a=[]}if(a&&0!==a.length)return a});return(d=[]).concat.apply(d,pa(Gc(a)))}function Rd(a,b){var c=Hd(),e={};"undefined"===typeof a&&(a=!0);var d=function(a,b){var c={};b=b||{};for(var d in a)if(b[d]||null!==a[d]&&
+"undefined"!==typeof a[d])c[d]=a[d];return c},f=function(a,d,f,h){a.addDict(e);a.add("eid",Sd.v4());f=null==f?{type:"dtm",value:(new Date).getTime()}:"number"===typeof f?{type:"dtm",value:f}:"ttm"===f.type?{type:"ttm",value:f.value}:{type:"dtm",value:f.value||(new Date).getTime()};a.add(f.type,f.value.toString());f=c.getApplicableContexts(a);var g=[];d&&d.length&&g.push.apply(g,pa(d));f&&f.length&&g.push.apply(g,pa(f));d=g&&g.length?{schema:"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0",
+data:g}:void 0;void 0!==d&&a.addJson("cx","co",d);"function"===typeof b&&b(a);try{h&&h(a.build())}catch(n){console.warn("Snowplow: error running custom callback")}return a},h=function(b,c,d,e){var g=za(a);b={schema:"iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0",data:b};g.add("e","ue");g.addJson("ue_px","ue_pr",b);return f(g,c,d,e)};return{addPayloadPair:function(a,b){e[a]=b},setBase64Encoding:function(b){a=b},addPayloadDict:function(a){for(var b in a)Object.prototype.hasOwnProperty.call(a,
+b)&&(e[b]=a[b])},resetPayloadPairs:function(a){e=vc(a)?a:{}},setTrackerVersion:function(a){e.tv=a},setTrackerNamespace:function(a){e.tna=a},setAppId:function(a){e.aid=a},setPlatform:function(a){e.p=a},setUserId:function(a){e.uid=a},setScreenResolution:function(a,b){e.res=a+"x"+b},setViewport:function(a,b){e.vp=a+"x"+b},setColorDepth:function(a){e.cd=a},setTimezone:function(a){e.tz=a},setLang:function(a){e.lang=a},setIpAddress:function(a){e.ip=a},setUseragent:function(a){e.ua=a},trackUnstructEvent:h,
+trackSelfDescribingEvent:h,trackPageView:function(b,c,d,e,h,n){var g=za(a);g.add("e","pv");g.add("url",b);g.add("page",c);g.add("refr",d);return f(g,e,h,n)},trackPagePing:function(b,c,d,e,h,n,z,t,mb,m){var g=za(a);g.add("e","pp");g.add("url",b);g.add("page",c);g.add("refr",d);g.add("pp_mix",e.toString());g.add("pp_max",h.toString());g.add("pp_miy",n.toString());g.add("pp_may",z.toString());return f(g,t,mb,m)},trackStructEvent:function(b,c,d,e,h,n,z,t){var g=za(a);g.add("e","se");g.add("se_ca",b);
+g.add("se_ac",c);g.add("se_la",d);g.add("se_pr",e);g.add("se_va",null==h?void 0:h.toString());return f(g,n,z,t)},trackEcommerceTransaction:function(b,c,d,e,h,n,z,t,m,r,Jb,y){var g=za(a);g.add("e","tr");g.add("tr_id",b);g.add("tr_af",c);g.add("tr_tt",d);g.add("tr_tx",e);g.add("tr_sh",h);g.add("tr_ci",n);g.add("tr_st",z);g.add("tr_co",t);g.add("tr_cu",m);return f(g,r,Jb,y)},trackEcommerceTransactionItem:function(b,c,d,e,h,n,z,t,m,r){var g=za(a);g.add("e","ti");g.add("ti_id",b);g.add("ti_sk",c);g.add("ti_nm",
+d);g.add("ti_ca",e);g.add("ti_pr",h);g.add("ti_qu",n);g.add("ti_cu",z);return f(g,t,m,r)},trackScreenView:function(a,b,c,e,f){return h({schema:"iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0",data:d({name:a,id:b})},c,e,f)},trackLinkClick:function(a,b,c,e,f,n,z,t){a={schema:"iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1",data:d({targetUrl:a,elementId:b,elementClasses:c,elementTarget:e,elementContent:f})};return h(a,n,z,t)},trackAdImpression:function(a,b,c,e,f,n,
+z,t,m,r,v){a={schema:"iglu:com.snowplowanalytics.snowplow/ad_impression/jsonschema/1-0-0",data:d({impressionId:a,costModel:b,cost:c,targetUrl:e,bannerId:f,zoneId:n,advertiserId:z,campaignId:t})};return h(a,m,r,v)},trackAdClick:function(a,b,c,e,f,n,z,t,m,r,v,y){a={schema:"iglu:com.snowplowanalytics.snowplow/ad_click/jsonschema/1-0-0",data:d({targetUrl:a,clickId:b,costModel:c,cost:e,bannerId:f,zoneId:n,impressionId:z,advertiserId:t,campaignId:m})};return h(a,r,v,y)},trackAdConversion:function(a,b,c,
+e,f,n,z,t,m,r,v,y){a={schema:"iglu:com.snowplowanalytics.snowplow/ad_conversion/jsonschema/1-0-0",data:d({conversionId:a,costModel:b,cost:c,category:e,action:f,property:n,initialValue:z,advertiserId:t,campaignId:m})};return h(a,r,v,y)},trackSocialInteraction:function(a,b,c,e,f,n){a={schema:"iglu:com.snowplowanalytics.snowplow/social_interaction/jsonschema/1-0-0",data:d({action:a,network:b,target:c})};return h(a,e,f,n)},trackAddToCart:function(a,b,c,e,f,n,z,t,m){return h({schema:"iglu:com.snowplowanalytics.snowplow/add_to_cart/jsonschema/1-0-0",
+data:d({sku:a,name:b,category:c,unitPrice:e,quantity:f,currency:n})},z,t,m)},trackRemoveFromCart:function(a,b,c,e,f,n,m,t,r){return h({schema:"iglu:com.snowplowanalytics.snowplow/remove_from_cart/jsonschema/1-0-0",data:d({sku:a,name:b,category:c,unitPrice:e,quantity:f,currency:n})},m,t,r)},trackFormFocusOrChange:function(a,b,c,e,f,n,m,t,r,v){var g="";b={formId:b,elementId:c,nodeName:e,elementClasses:n,value:m};"change_form"===a?(g="iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0",
+b.type=f):"focus_form"===a&&(g="iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0",b.elementType=f);return h({schema:g,data:d(b,{value:!0})},t,r,v)},trackFormSubmission:function(a,b,c,e,f,n){return h({schema:"iglu:com.snowplowanalytics.snowplow/submit_form/jsonschema/1-0-0",data:d({formId:a,formClasses:b,elements:c})},e,f,n)},trackSiteSearch:function(a,b,c,e,f,n,m){return h({schema:"iglu:com.snowplowanalytics.snowplow/site_search/jsonschema/1-0-0",data:d({terms:a,filters:b,totalResults:c,
+pageResults:e})},f,n,m)},trackConsentWithdrawn:function(a,b,c,e,f,n,m,t){b={schema:"iglu:com.snowplowanalytics.snowplow/consent_document/jsonschema/1-0-0",data:d({id:b,version:c,name:e,description:f})};return h({schema:"iglu:com.snowplowanalytics.snowplow/consent_withdrawn/jsonschema/1-0-0",data:d({all:a})},b.data&&n?n.concat([b]):n,m,t)},trackConsentGranted:function(a,b,c,e,f,n,m,t){a={schema:"iglu:com.snowplowanalytics.snowplow/consent_document/jsonschema/1-0-0",data:d({id:a,version:b,name:c,description:e})};
+return h({schema:"iglu:com.snowplowanalytics.snowplow/consent_granted/jsonschema/1-0-0",data:d({expiry:f})},n?n.concat([a]):[a],m,t)},addGlobalContexts:function(a){c.addGlobalContexts(a)},clearGlobalContexts:function(){c.clearGlobalContexts()},removeGlobalContexts:function(a){c.removeGlobalContexts(a)}}}function Pa(a,b,c,e,d){function f(a){return-1<Rb.map(function(a){return a.toLowerCase()}).indexOf(a.toLowerCase())}function h(){Qa=rc(B.domain,C.location.href,cc());Qa[1]!==Aa&&(Mb=cc(Aa));Ja=bc(Qa[0]);
+Aa=Qa[1]}function g(){var a=(new Date).getTime();if(this.href){a="_sp="+(Nb+"."+a);var b=this.href.split("#"),c=b[0].split("?"),d=c.shift();if(c=c.join("?")){for(var e=!0,f=c.split("&"),g=0;g<f.length;g++)if("_sp="===f[g].substr(0,4)){e=!1;f[g]=a;c=f.join("&");break}e&&(c=a+"&"+c)}else c=a;b[0]=d+"?"+c;this.href=b.join("#")}}function k(a){for(var b=0;b<B.links.length;b++){var c=B.links[b];!c.spDecorationEnabled&&a(c)&&(v(c,"click",g,!0),v(c,"mousedown",g,!0),c.spDecorationEnabled=!0)}}function p(a){if(Pa){var b=
+/#.*/;a=a.replace(b,"")}Sa&&(b=/[{}]/g,a=a.replace(b,""));return a}function m(a){return(a=/^([a-z]+):/.exec(a))?a[1]:null}function q(a){return Ua+a+"."+zb}function n(a){a=q(a);if("localStorage"==G){a:{try{var b=wa.getItem(a+".expires");if(null===b||+b>Date.now()){var c=wa.getItem(a);break a}else wa.removeItem(a),wa.removeItem(a+".expires");c=void 0;break a}catch(af){}c=void 0}return c}if("cookie"==G||"cookieAndLocalStorage"==G)return A(a)}function r(){h();zb=Qb((ka||Ja)+(Da||"/")).slice(0,4)}function t(){Ub=
+(new Date).getTime()}function F(){var a=H(),b=a[0];b<Vb?Vb=b:b>Wb&&(Wb=b);a=a[1];a<Xb?Xb=a:a>Yb&&(Yb=a);t()}function H(){var a=B.compatMode&&"BackCompat"!==B.compatMode?B.documentElement:B.body;return[a.scrollLeft||C.pageXOffset,a.scrollTop||C.pageYOffset]}function J(){var a=H(),b=a[0];Wb=Vb=b;Yb=Xb=a=a[1]}function y(a){a=Math.round(a);if(!isNaN(a))return a}function O(){var a=q("ses");R(a,"*",La)}function N(a,b,c,d,e,f){var dc=q("id");R(dc,a+"."+b+"."+c+"."+d+"."+e+"."+f,jb)}function R(a,b,c){if(!ha||
+tb)"localStorage"==G?Tb(a,b,c):("cookie"==G||"cookieAndLocalStorage"==G)&&A(a,b,c,Da,ka,Ab,Bb)}function S(){var a=q("id"),b=q("ses");pc(a);pc(b);A(a,"",-1,"/",void 0);A(b,"",-1,"/",void 0)}function T(){if(!ha||tb){var a="none"!=G&&!!n("ses"),b=P();b[1]?Nb=b[1]:(Nb=ha?"":V(),b[1]=Nb);Q=b[6];a||(b[3]++,Q=V(),b[6]=Q,b[5]=b[4]);"none"!=G&&(O(),b[4]=Math.round((new Date).getTime()/1E3),b.shift(),N.apply(null,b))}}function P(){if("none"==G)return[];var a=Math.round((new Date).getTime()/1E3),b=n("id");b?
+(a=b.split("."),a.unshift("0")):a=["1",Nb,a,0,a,""];a[6]||(a[6]=V());return a}function U(a){return nb?"https://"+a:Kb?"http://"+a:("https:"===B.location.protocol?"https":"http")+"://"+a}function w(a){var b=ec.concat(a||[]);I.webPage&&b.push({schema:"iglu:com.snowplowanalytics.snowplow/web_page/jsonschema/1-0-0",data:{id:D()}});I.performanceTiming&&(a=aa())&&b.push(a);if(C.optimizely){I.optimizelySummary&&(a=ta(),L(a,function(a){b.push(a)}));I.optimizelyXSummary&&(a=ya(),L(a,function(a){b.push(a)}));
+if(I.optimizelyExperiments){var c=ma();for(a=0;a<c.length;a++)b.push(c[a])}if(I.optimizelyStates)for(c=oa(),a=0;a<c.length;a++)b.push(c[a]);if(I.optimizelyVariations)for(c=pa(),a=0;a<c.length;a++)b.push(c[a]);I.optimizelyVisitor&&(a=qa())&&b.push(a);if(I.optimizelyAudiences)for(c=ra(),a=0;a<c.length;a++)b.push(c[a]);if(I.optimizelyDimensions)for(c=sa(),a=0;a<c.length;a++)b.push(c[a])}I.parrable&&(a=za())&&b.push(a);I.gdprBasis&&Ra.gdprBasis&&(a=Ra.gdprBasis?{schema:"iglu:com.snowplowanalytics.snowplow/gdpr/jsonschema/1-0-0",
+data:{basisForProcessing:Ra.gdprBasis,documentId:Ra.gdprDocId||null,documentVersion:Ra.gdprDocVer||null,documentDescription:Ra.gdprDocDesc||null}}:void 0,a&&b.push(a));I.clientHints&&Ba&&b.push({schema:"iglu:org.ietf/http_client_hints/jsonschema/1-0-0",data:Ba});return b}function X(){Eb&&null!=e.pageViewId||(e.pageViewId=V())}function D(){null==e.pageViewId&&(e.pageViewId=V());return e.pageViewId}function aa(){var a="navigationStart redirectStart redirectEnd fetchStart domainLookupStart domainLookupEnd connectStart secureConnectionStart connectEnd requestStart responseStart responseEnd unloadEventStart unloadEventEnd domLoading domInteractive domContentLoadedEventStart domContentLoadedEventEnd domComplete loadEventStart loadEventEnd msFirstPaint chromeFirstPaint requestEnd proxyStart proxyEnd".split(" "),
+b=C.performance||C.mozPerformance||C.msPerformance||C.webkitPerformance;if(b){var c={},d;for(d in b.timing)qc(d,a)&&null!==b.timing[d]&&(c[d]=b.timing[d]);delete c.requestEnd;return{schema:"iglu:org.w3/PerformanceTiming/jsonschema/1-0-0",data:c}}}function ea(a,b){if(C.optimizely&&C.optimizely.data){var c=C.optimizely.data[a];"undefined"!==typeof b&&void 0!==c&&(c=c[b])}return c}function Y(a,b){if(C.optimizely&&"function"===typeof C.optimizely.get){var c=C.optimizely.get(a);"undefined"!==typeof b&&
+void 0!==c&&(c=c[b])}return c}function ca(){var a=ea("state"),b=ea("experiments");return da(a&&b&&a.activeExperiments,function(c){var d=b[c];return{activeExperimentId:c.toString(),variation:a.variationIdsMap[c][0].toString(),conditional:d&&d.conditional,manual:d&&d.manual,name:d&&d.name}})}function la(){var a=Y("state"),b=a&&a.getActiveExperimentIds(),c=a&&a.getVariationMap(),d=Y("visitor");return da(b,function(a){var b=c[a],e=b&&b.name&&b.name.toString()||null;b=b&&b.id;var f=d&&d.visitorId&&d.visitorId.toString()||
+null;return{experimentId:lb(a)||null,variationName:e,variation:lb(b)||null,visitorId:f}})}function ma(){var a=ea("experiments");if(a){var b=[],c;for(c in a)if(a.hasOwnProperty(c)){var d={};d.id=c;var e=a[c];d.code=e.code;d.manual=e.manual;d.conditional=e.conditional;d.name=e.name;d.variationIds=e.variation_ids;b.push({schema:"iglu:com.optimizely/experiment/jsonschema/1-0-0",data:d})}return b}return[]}function oa(){var a=[],b=ea("experiments");if(b)for(var c in b)b.hasOwnProperty(c)&&a.push(c);if(b=
+ea("state")){c=[];for(var d=b.activeExperiments||[],e=0;e<a.length;e++){var f=a[e],g={};g.experimentId=f;g.isActive=qc(a[e],d);g.variationIndex=(b.variationMap||{})[f];g.variationName=(b.variationNamesMap||{})[f];var h=b.variationIdsMap||{};h[f]&&1===h[f].length&&(g.variationId=h[f][0]);c.push({schema:"iglu:com.optimizely/state/jsonschema/1-0-0",data:g})}return c}return[]}function pa(){var a=ea("variations");if(a){var b=[],c;for(c in a)if(a.hasOwnProperty(c)){var d={};d.id=c;var e=a[c];d.name=e.name;
+d.code=e.code;b.push({schema:"iglu:com.optimizely/variation/jsonschema/1-0-0",data:d})}return b}return[]}function qa(){var a=ea("visitor");if(a){var b={};b.browser=a.browser;b.browserVersion=a.browserVersion;b.device=a.device;b.deviceType=a.deviceType;b.ip=a.ip;var c=a.platform||{};b.platformId=c.id;b.platformVersion=c.version;c=a.location||{};b.locationCity=c.city;b.locationRegion=c.region;b.locationCountry=c.country;b.mobile=a.mobile;b.mobileId=a.mobileId;b.referrer=a.referrer;b.os=a.os;return{schema:"iglu:com.optimizely/visitor/jsonschema/1-0-0",
+data:b}}}function ra(){var a=ea("visitor","audiences");if(a){var b=[],c;for(c in a)a.hasOwnProperty(c)&&b.push({schema:"iglu:com.optimizely/visitor_audience/jsonschema/1-0-0",data:{id:c,isMember:a[c]}});return b}return[]}function sa(){var a=ea("visitor","dimensions");if(a){var b=[],c;for(c in a)a.hasOwnProperty(c)&&b.push({schema:"iglu:com.optimizely/visitor_dimension/jsonschema/1-0-0",data:{id:c,value:a[c]}});return b}return[]}function ta(){return da(ca(),function(a){return{schema:"iglu:com.optimizely.snowplow/optimizely_summary/jsonschema/1-0-0",
+data:a}})}function ya(){return da(la(),function(a){return{schema:"iglu:com.optimizely.optimizelyx/summary/jsonschema/1-0-0",data:a}})}function za(){var a=window._hawk;if(a){var b={encryptedId:null,optout:null};b.encryptedId=a.browserid;a=new RegExp("(?:^|;)\\s?"+"_parrable_hawk_optout".replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")+"=(.*?)(?:;|$)","i");a=document.cookie.match(a);b.optout=a&&decodeURIComponent(a[1])?a&&decodeURIComponent(a[1]):"false";return{schema:"iglu:com.parrable/encrypted_payload/jsonschema/1-0-0",
+data:b}}}function fa(){!Db&&M.geolocation&&M.geolocation.getCurrentPosition&&(Db=!0,M.geolocation.getCurrentPosition(function(a){var b=a.coords;ec.push({schema:"iglu:com.snowplowanalytics.snowplow/geolocation_context/jsonschema/1-1-0",data:{latitude:b.latitude,longitude:b.longitude,latitudeLongitudeAccuracy:b.accuracy,altitude:b.altitude,altitudeAccuracy:b.altitudeAccuracy,bearing:b.heading,speed:b.speed,timestamp:Math.round(a.timestamp)}})}))}function Ea(){var a={};L("__utma __utmb __utmc __utmv __utmz _ga".split(" "),
+function(b){var c=A(b);c&&(a[b]=c)});return{schema:"iglu:com.google.analytics/cookies/jsonschema/1-0-0",data:a}}function Ia(a,b,c,d,e){h();Fb&&X();Fb=!0;ub=B.title;Ob=a;a=nc(Ob||ub);u.trackPageView(p(vb||Aa),a,p(ba||Mb),w((b||[]).concat(c?c():[])),d,e);d=new Date;e=!1;if(W.enabled&&!W.installed){e=W.installed=!0;var f={update:function(){if("undefined"!==typeof window&&"function"===typeof window.addEventListener){var a=!1,b=Object.defineProperty({},"passive",{get:function(){a=!0}}),c=function(){};
+window.addEventListener("testPassiveEventSupport",c,b);window.removeEventListener("testPassiveEventSupport",c,b);f.hasSupport=a}}};f.update();a="onwheel"in document.createElement("div")?"wheel":void 0!==document.onmousewheel?"mousewheel":"DOMMouseScroll";Object.prototype.hasOwnProperty.call(f,"hasSupport")?v(B,a,t,{passive:!0}):v(B,a,t);J();a=function(a){var b=1<arguments.length&&void 0!==arguments[1]?arguments[1]:t;return function(a){return v(B,a,b)}};L("click mouseup mousedown mousemove keypress keydown keyup".split(" "),
+a(B));L(["resize","focus","blur"],a(C));a(C,F)("scroll")}if(W.enabled&&(sb||e)){Ub=d.getTime();for(var g in W.configurations)W.configurations.hasOwnProperty(g)&&(d=W.configurations[g],clearInterval(d.activityInterval),Ka(d,(b||[]).concat(c?c():[])))}}function Ka(a,b){var c=function(a,b){h();a({context:b,pageViewId:D(),minXOffset:Vb,minYOffset:Xb,maxXOffset:Wb,maxYOffset:Yb});J()},d=function(){Ub+a.configHeartBeatTimer>(new Date).getTime()&&c(a.callback,b)};a.activityInterval=0!=a.configMinimumVisitLength?
+setTimeout(function(){Ub+a.configMinimumVisitLength>(new Date).getTime()&&c(a.callback,b);a.activityInterval=setInterval(d,a.configHeartBeatTimer)},a.configMinimumVisitLength):setInterval(d,a.configHeartBeatTimer)}function va(a,b,c){if("number"==typeof a&&a==fc(a)&&"number"==typeof b&&b==fc(b))return{configMinimumVisitLength:1E3*a,configHeartBeatTimer:1E3*b,activityInterval:null,callback:c};E("Activity tracking not enabled, please provide integer values for minimumVisitLength and heartBeatDelay.");
+return{}}function Oa(a){var b=a.context,c=a.minXOffset,d=a.minYOffset,e=a.maxXOffset;a=a.maxYOffset;var f=B.title;f!==ub&&(ub=f,Ob=null);u.trackPagePing(p(vb||Aa),nc(Ob||ub),p(ba||Mb),y(c),y(e),y(d),y(a),w(b))}function ja(a,b){return""!==a?a+b.charAt(0).toUpperCase()+b.slice(1):b}function K(a){var b,c,d=["","webkit","ms","moz"];if(!ib)for(c=0;c<d.length;c++){var e=d[c];if(B[ja(e,"hidden")]){"prerender"===B[ja(e,"visibilityState")]&&(b=!0);break}else if(!1===B[ja(e,"hidden")])break}b?v(B,e+"visibilitychange",
+function Td(){B.removeEventListener(e+"visibilitychange",Td,!1);a()}):a()}d=d||{};d.hasOwnProperty("post")?d.eventMethod=!0===d.post?"post":"get":d.eventMethod=d.eventMethod||"post";d.hasOwnProperty("useStm")||(d.useStm=!0);var Ca=function(a){return a.hasOwnProperty("stateStorageStrategy")?a.stateStorageStrategy:Na||qb?Na&&qb?"cookieAndLocalStorage":Na?"cookie":"localStorage":"none"},na=function(a){return a.hasOwnProperty("anonymousTracking")?!0===a.anonymousTracking.withSessionTracking:!1},Wa=Object.freeze({consent:"consent",
+contract:"contract",legalObligation:"legal_obligation",vitalInterests:"vital_interests",publicTask:"public_task",legitimateInterests:"legitimate_interests"}),u=Rd(!0,function(a){var b=Math.round((new Date).getTime()/1E3),c=n("ses"),d=P(),f=d[0],g=d[1],dc=d[2],k=d[3],l=d[4],m=d[5];d=d[6];var q=Pb?!!A(Pb):!1;Fa||q?S():("0"===f?(Q=d,c||"none"==G||(k++,m=l,Q=V()),ia=k):(new Date).getTime()-Ta>1E3*La&&(Q=V(),ia++),a.add("vp",ud()),a.add("ds",vd()),a.add("vid",tb?ia:ha?null:ia),a.add("sid",tb?Q:ha?null:
+Q),a.add("duid",ha?null:g),a.add("uid",ha?null:wb),h(),a.add("refr",p(ba||Mb)),a.add("url",p(vb||Aa)),"none"!=G&&(N(g,dc,ia,b,m,Q),O()),Ta=(new Date).getTime());b=pb;c=new Date;f=Pb?!!A(Pb):!1;Fa||f||(gb.enqueueRequest(a.build(),xa),e.expireDateTime=c.getTime()+b)}),Ga=!1,l={},ua={},Ha={},B=document,C=window,M=navigator,Qa=rc(B.domain,C.location.href,cc()),Ja=bc(Qa[0]),Aa=Qa[1],Mb=Qa[2],ba,kb=d.hasOwnProperty("platform")?d.platform:"web",xa,Ma=d.hasOwnProperty("postPath")?d.postPath:"/com.snowplowanalytics.snowplow/tp2",
+ob=d.hasOwnProperty("appId")?d.appId:"",vb,ub=B.title,Ob,pb=d.hasOwnProperty("pageUnloadTimer")?d.pageUnloadTimer:500,sb=d.hasOwnProperty("resetActivityTrackingOnPageView")?d.resetActivityTrackingOnPageView:!0,Pa,Sa,Ua=d.hasOwnProperty("cookieName")?d.cookieName:"_sp_",ka=d.hasOwnProperty("cookieDomain")?d.cookieDomain:null,Da="/",Ab=d.hasOwnProperty("cookieSameSite")?d.cookieSameSite:"None",Bb=d.hasOwnProperty("cookieSecure")?d.cookieSecure:!0,hb=M.doNotTrack||M.msDoNotTrack||C.doNotTrack,Fa=d.hasOwnProperty("respectDoNotTrack")?
+d.respectDoNotTrack&&("yes"===hb||"1"===hb):!1,Pb,ib,jb=d.hasOwnProperty("cookieLifetime")?d.cookieLifetime:63072E3,La=d.hasOwnProperty("sessionCookieTimeout")?d.sessionCookieTimeout:1800,Hb=B.characterSet||B.charset,nb=d.hasOwnProperty("forceSecureTracker")?!0===d.forceSecureTracker:!1,Kb=!nb&&d.hasOwnProperty("forceUnsecureTracker")?!0===d.forceUnsecureTracker:!1,tb=na(d),ha=!!d.anonymousTracking,qb=d.hasOwnProperty("useLocalStorage")?(E("argmap.useLocalStorage is deprecated. Use argmap.stateStorageStrategy instead."),
+d.useLocalStorage):!0,Na=d.hasOwnProperty("useCookies")?(E("argmap.useCookies is deprecated. Use argmap.stateStorageStrategy instead."),d.useCookies):!0,G=Ca(d),Lb=M.userLanguage||M.language,Zb=wd("cookie"==G||"cookieAndLocalStorage"==G,q("testcookie")),rb=a+"_"+b,Ub,Ta=(new Date).getTime(),Vb,Wb,Xb,Yb,Qb=Ud,zb,Nb,Q,ia=1,wb,Va,Xa,Ya,Za,$a,ab,bb,cb,db,eb,fb,$b=[],xb=new xd(u,rb,w),ac=new yd(u,rb,w),Cb=new Ad(u),gb=new sc(a,b,e,"localStorage"==G||"cookieAndLocalStorage"==G,d.eventMethod,Ma,d.bufferSize,
+d.maxPostBytes||4E4,d.useStm,d.maxLocalStorageQueueSize||1E3,d.connectionTimeout||5E3),Db=!1,I=d.contexts||{},ec=[],yb=[],Eb=!1,Fb=!1,W={enabled:!1,installed:!1,configurations:{}},Ba=null;I.clientHints&&M.userAgentData&&(Ba={isMobile:M.userAgentData.mobile,brands:M.userAgentData.brands},I.clientHints.includeHighEntropy&&M.userAgentData.getHighEntropyValues&&M.userAgentData.getHighEntropyValues(["platform","platformVersion","architecture","model","uaFullVersion"]).then(function(a){Ba.architecture=
+a.architecture;Ba.model=a.model;Ba.platform=a.platform;Ba.uaFullVersion=a.uaFullVersion;Ba.platformVersion=a.platformVersion}));var Rb=d.skippedBrowserFeatures||[],Ra={};d.hasOwnProperty("discoverRootDomain")&&d.discoverRootDomain&&(ka=rd());I.gaCookies&&ec.push(Ea());I.geolocation&&fa();u.setBase64Encoding(d.hasOwnProperty("encodeBase64")?d.encodeBase64:!0);u.setTrackerVersion(c);u.setTrackerNamespace(b);u.setAppId(ob);u.setPlatform(kb);u.setTimezone(Vd.jstz.determine().name());u.addPayloadPair("lang",
+Lb);u.addPayloadPair("cs",Hb);for(var Z in Zb)Object.prototype.hasOwnProperty.call(Zb,Z)&&("res"!==Z&&"cd"!==Z&&"cookie"!==Z||f(Z)?f(Z)||u.addPayloadPair("f_"+Z,Zb[Z]):u.addPayloadPair(Z,Zb[Z]));r();T();d.crossDomainLinker&&k(d.crossDomainLinker);l.getDomainSessionIndex=function(){return ia};l.getPageViewId=function(){return D()};l.newSession=function(){var a=Math.round((new Date).getTime()/1E3),b=P(),c=b[1],d=b[2],e=b[3],f=b[4],g=b[5],h=b[6];"0"===b[0]?(Q=h,"none"!=G&&(e++,g=f,Q=V()),ia=e,O()):(Q=
+V(),ia++);"none"!=G&&(N(c,d,ia,a,g,Q),O());Ta=(new Date).getTime()};l.getCookieName=function(a){return q(a)};l.getUserId=function(){return wb};l.getDomainUserId=function(){return P()[1]};l.getDomainUserInfo=function(){return P()};l.getUserFingerprint=function(){E("User Fingerprinting is no longer supported. This function will be removed in a future release.");return 0};l.setAppId=function(a){E("setAppId is deprecated. Instead use the argmap argument on tracker initialisation: appId");u.setAppId(a)};
+l.setReferrerUrl=function(a){ba=a};l.setCustomUrl=function(a){h();var b=Aa,c;m(a)?vb=a:"/"===a.slice(0,1)?vb=m(b)+"://"+Sb(b)+a:(b=p(b),0<=(c=b.indexOf("?"))&&(b=b.slice(0,c)),(c=b.lastIndexOf("/"))!==b.length-1&&(b=b.slice(0,c+1)),vb=b+a)};l.setDocumentTitle=function(a){ub=B.title;Ob=a};l.discardHashTag=function(a){Pa=a};l.discardBrace=function(a){Sa=a};l.setCookieNamePrefix=function(a){E("setCookieNamePrefix is deprecated. Instead use the argmap argument on tracker initialisation: cookieName");
+Ua=a};l.setCookieDomain=function(a){E("setCookieDomain is deprecated. Instead use the argmap argument on tracker initialisation: cookieDomain");ka=bc(a);r()};l.setCookiePath=function(a){Da=a;r()};l.setVisitorCookieTimeout=function(a){jb=a};l.setSessionCookieTimeout=function(a){E("setSessionCookieTimeout is deprecated. Instead use the argmap argument on tracker initialisation: sessionCookieTimeout");La=a};l.setUserFingerprintSeed=function(){E("User Fingerprinting is no longer supported. This function will be removed in a future release.")};
+l.enableUserFingerprint=function(){E("User Fingerprinting is no longer supported. This function will be removed in a future release.")};l.respectDoNotTrack=function(a){E("respectDoNotTrack is deprecated. Instead use the argmap argument on tracker initialisation: respectDoNotTrack");var b=M.doNotTrack||M.msDoNotTrack;Fa=a&&("yes"===b||"1"===b)};l.crossDomainLinker=function(a){k(a)};l.enableLinkClickTracking=function(a,b,c,d){e.hasLoaded?(xb.configureLinkClickTracking(a,b,c,d),xb.addClickListeners()):
+e.registeredOnLoadHandlers.push(function(){xb.configureLinkClickTracking(a,b,c,d);xb.addClickListeners()})};l.refreshLinkClickTracking=function(){e.hasLoaded?xb.addClickListeners():e.registeredOnLoadHandlers.push(function(){xb.addClickListeners()})};l.enableActivityTracking=function(a,b){W.enabled=!0;W.configurations.pagePing=va(a,b,Oa)};l.enableActivityTrackingCallback=function(a,b,c){W.enabled=!0;W.configurations.callback=va(a,b,c)};l.updatePageActivity=function(){t()};l.enableFormTracking=function(a,
+b){e.hasLoaded?(ac.configureFormTracking(a),ac.addFormListeners(b)):e.registeredOnLoadHandlers.push(function(){ac.configureFormTracking(a);ac.addFormListeners(b)})};l.killFrame=function(){C.location!==C.top.location&&(C.top.location=C.location)};l.redirectFile=function(a){"file:"===C.location.protocol&&(C.location=a)};l.setOptOutCookie=function(a){Pb=a};l.setCountPreRendered=function(a){ib=a};l.setUserId=function(a){wb=a};l.identifyUser=function(a){l.setUserId(a)};l.setUserIdFromLocation=function(a){h();
+wb=Gb(a,Aa)};l.setUserIdFromReferrer=function(a){h();wb=Gb(a,Mb)};l.setUserIdFromCookie=function(a){wb=A(a)};l.setCollectorCf=function(a){xa=U(a+".cloudfront.net")};l.setCollectorUrl=function(a){xa=U(a)};l.setPlatform=function(a){E("setPlatform is deprecated. Instead use the argmap argument on tracker initialisation: platform");u.setPlatform(a)};l.encodeBase64=function(a){E("encodeBase64 is deprecated. Instead use the argmap argument on tracker initialisation: encodeBase64");u.setBase64Encoding(a)};
+l.flushBuffer=function(){gb.executeQueue()};l.enableGeolocationContext=fa;l.trackPageView=function(a,b,c,d,e){K(function(){Ia(a,b,c,d,e)})};l.trackStructEvent=function(a,b,c,d,e,f,g,h){K(function(){u.trackStructEvent(a,b,c,d,e,w(f),g,h)})};l.trackSelfDescribingEvent=function(a,b,c,d){K(function(){u.trackSelfDescribingEvent(a,w(b),c,d)})};l.trackUnstructEvent=function(a,b,c){K(function(){u.trackSelfDescribingEvent(a,w(b),c)})};l.addTrans=function(a,b,c,d,e,f,g,h,k,l,p){Va=a;Xa=b;Ya=c;Za=d;$a=e;ab=
+f;bb=g;cb=h;db=k;eb=l;fb=p};l.addItem=function(a,b,c,d,e,f,g,h,k){$b.push({orderId:a,sku:b,name:c,category:d,price:e,quantity:f,currency:g,context:h,tstamp:k})};l.trackTrans=function(){K(function(){var a=fb;u.trackEcommerceTransaction(Va,Xa,Ya,Za,$a,ab,bb,cb,db,w(eb),a);for(a=0;a<$b.length;a++){var b=$b[a],c=b.tstamp;u.trackEcommerceTransactionItem(b.orderId,b.sku,b.name,b.category,b.price,b.quantity,b.currency,w(b.context),c)}fb=eb=db=cb=bb=ab=$a=Za=Ya=Xa=Va=void 0;$b=[]})};l.trackLinkClick=function(a,
+b,c,d,e,f,g){K(function(){u.trackLinkClick(a,b,c,d,e,w(f),g)})};l.trackAdImpression=function(a,b,c,d,e,f,g,h,k,l){K(function(){u.trackAdImpression(a,b,c,d,e,f,g,h,w(k),l)})};l.trackAdClick=function(a,b,c,d,e,f,g,h,k,l,p){K(function(){u.trackAdClick(a,b,c,d,e,f,g,h,k,w(l),p)})};l.trackAdConversion=function(a,b,c,d,e,f,g,h,k,l,p){K(function(){u.trackAdConversion(a,b,c,d,e,f,g,h,k,w(l),p)})};l.trackSocialInteraction=function(a,b,c,d,e){K(function(){u.trackSocialInteraction(a,b,c,w(d),e)})};l.trackAddToCart=
+function(a,b,c,d,e,f,g,h){K(function(){u.trackAddToCart(a,b,c,d,e,f,w(g),h)})};l.trackRemoveFromCart=function(a,b,c,d,e,f,g,h){K(function(){u.trackRemoveFromCart(a,b,c,d,e,f,w(g),h)})};l.trackSiteSearch=function(a,b,c,d,e,f){K(function(){u.trackSiteSearch(a,b,c,d,w(e),f)})};l.trackTiming=function(a,b,c,d,e,f){K(function(){u.trackSelfDescribingEvent({schema:"iglu:com.snowplowanalytics.snowplow/timing/jsonschema/1-0-0",data:{category:a,variable:b,timing:c,label:d}},w(e),f)})};l.trackConsentWithdrawn=
+function(a,b,c,d,e,f,g){K(function(){u.trackConsentWithdrawn(a,b,c,d,e,w(f),g)})};l.trackConsentGranted=function(a,b,c,d,e,f,g){K(function(){u.trackConsentGranted(a,b,c,d,e,w(f),g)})};l.trackEnhancedEcommerceAction=function(a,b,c){var d=yb.concat(b||[]);yb.length=0;K(function(){u.trackSelfDescribingEvent({schema:"iglu:com.google.analytics.enhanced-ecommerce/action/jsonschema/1-0-0",data:{action:a}},w(d),c)})};l.addEnhancedEcommerceActionContext=function(a,b,c,d,e,f,g,h,k,l){yb.push({schema:"iglu:com.google.analytics.enhanced-ecommerce/actionFieldObject/jsonschema/1-0-0",
+data:{id:a,affiliation:b,revenue:Ib(c),tax:Ib(d),shipping:Ib(e),coupon:f,list:g,step:lb(h),option:k,currency:l}})};l.addEnhancedEcommerceImpressionContext=function(a,b,c,d,e,f,g,h,k){yb.push({schema:"iglu:com.google.analytics.enhanced-ecommerce/impressionFieldObject/jsonschema/1-0-0",data:{id:a,name:b,list:c,brand:d,category:e,variant:f,position:lb(g),price:Ib(h),currency:k}})};l.addEnhancedEcommerceProductContext=function(a,b,c,d,e,f,g,h,k,l,p){yb.push({schema:"iglu:com.google.analytics.enhanced-ecommerce/productFieldObject/jsonschema/1-0-0",
+data:{id:a,name:b,list:c,brand:d,category:e,variant:f,price:Ib(g),quantity:lb(h),coupon:k,position:lb(l),currency:p}})};l.addEnhancedEcommercePromoContext=function(a,b,c,d,e){yb.push({schema:"iglu:com.google.analytics.enhanced-ecommerce/promoFieldObject/jsonschema/1-0-0",data:{id:a,name:b,creative:c,position:d,currency:e}})};l.enableGdprContext=function(a){var b=1<arguments.length&&void 0!==arguments[1]?arguments[1]:null,c=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null,d=3<arguments.length&&
+void 0!==arguments[3]?arguments[3]:null,e=Wa[a];e?(I.gdprBasis=!0,Ra={gdprBasis:e,gdprDocId:b,gdprDocVer:c,gdprDocDesc:d}):E("enableGdprContext failed. basisForProcessing must be set to one of: consent, legalObligation, vitalInterests publicTask, legitimateInterests")};l.addGlobalContexts=function(a){u.addGlobalContexts(a)};l.removeGlobalContexts=function(a){u.removeGlobalContexts(a)};l.clearGlobalContexts=function(){u.clearGlobalContexts()};l.enableErrorTracking=function(a,b){Cb.enableErrorTracking(a,
+b,w())};l.trackError=function(a,b,c,d,e,f){f=w(f);Cb.trackError(a,b,c,d,e,f)};l.preservePageViewId=function(){Eb=!0};l.disableAnonymousTracking=function(c){c?(Object.assign(d,{stateStorageStrategy:c,anonymousTracking:!1}),G=Ca(d),gb=new sc(a,b,e,"localStorage"==G||"cookieAndLocalStorage"==G,d.eventMethod,Ma,d.bufferSize,d.maxPostBytes||4E4,d.useStm,d.maxLocalStorageQueueSize||1E3,d.connectionTimeout||5E3)):Object.assign(d,{anonymousTracking:!1});ha=!!d.anonymousTracking;tb=na(d);T()};l.enableAnonymousTracking=
+function(a){Object.assign(d,{anonymousTracking:a||!0});ha=!!d.anonymousTracking;(tb=na(d))||X()};l.clearUserData=S;l.setDebug=function(a){Ha=(Ga=(!!a).valueOf())?l:ua};ua=Dd(l);return Ha=Ga?l:ua}function Hc(a,b){function c(){var a;if(!f.hasLoaded)for(f.hasLoaded=!0,a=0;a<f.registeredOnLoadHandlers.length;a++)f.registeredOnLoadHandlers[a]();return!0}var e=document,d=window,f={outQueues:[],bufferFlushers:[],expireDateTime:null,hasLoaded:!1,registeredOnLoadHandlers:[],pageViewId:null};d.Snowplow={getTrackerCf:function(a){var c=
+new Pa(b,"","js-2.16.2",f,{});c.setCollectorCf(a);return c},getTrackerUrl:function(a){var c=new Pa(b,"","js-2.16.2",f,{});c.setCollectorUrl(a);return c},getAsyncTracker:function(){return new Pa(b,"","js-2.16.2",f,{})}};v(d,"beforeunload",function(){L(f.bufferFlushers,function(a){a()});if(f.expireDateTime){do{var a=new Date;if(0===f.outQueues.filter(function(a){return 0<a.length}).length)break}while(a.getTime()<f.expireDateTime)}},!1);(function(){var a;e.addEventListener?v(e,"DOMContentLoaded",function k(){e.removeEventListener("DOMContentLoaded",
+k,!1);c()}):e.attachEvent&&(e.attachEvent("onreadystatechange",function k(){"complete"===e.readyState&&(e.detachEvent("onreadystatechange",k),c())}),e.documentElement.doScroll&&d===d.top&&function p(){if(!f.hasLoaded){try{e.documentElement.doScroll("left")}catch(x){setTimeout(p,0);return}c()}}());/WebKit/.test(navigator.userAgent)&&(a=setInterval(function(){if(f.hasLoaded||/loaded|complete/.test(e.readyState))clearInterval(a),c()},10));v(d,"load",c,!1)})();return new sd(Pa,"js-2.16.2",f,a,b)}var Wd=
+function(a,b){for(var c=-1,e=null==a?0:a.length;++c<e&&!1!==b(a[c],c,a););return a},Xd=function(a){return function(b,c,e){var d=-1,f=Object(b);e=e(b);for(var h=e.length;h--;){var g=e[a?h:++d];if(!1===c(f[g],g,f))break}return b}}(),Sa="undefined"!==typeof globalThis?globalThis:"undefined"!==typeof window?window:"undefined"!==typeof global?global:"undefined"!==typeof self?self:{},Ic="object"==H(Sa)&&Sa&&Sa.Object===Object&&Sa,Yd="object"==("undefined"===typeof self?"undefined":H(self))&&self&&self.Object===
+Object&&self,S=Ic||Yd||Function("return this")(),X=S.Symbol,Jc=Object.prototype,Zd=Jc.hasOwnProperty,$d=Jc.toString,ja=X?X.toStringTag:void 0,ae=Object.prototype.toString,Kc=X?X.toStringTag:void 0,U=function(a){if(null==a)a=void 0===a?"[object Undefined]":"[object Null]";else if(Kc&&Kc in Object(a)){var b=Zd.call(a,ja),c=a[ja];try{a[ja]=void 0;var e=!0}catch(f){}var d=$d.call(a);e&&(b?a[ja]=c:delete a[ja]);a=d}else a=ae.call(a);return a},T=function(a){return null!=a&&"object"==H(a)},Lc=function(a){return T(a)&&
+"[object Arguments]"==U(a)},Mc=Object.prototype,be=Mc.hasOwnProperty,ce=Mc.propertyIsEnumerable,Nc=Lc(function(){return arguments}())?Lc:function(a){return T(a)&&be.call(a,"callee")&&!ce.call(a,"callee")},F=Array.isArray,de=function(){return!1},ib=qa(function(a,b){var c=(b=b&&!b.nodeType&&b)&&a&&!a.nodeType&&a;b=c&&c.exports===b?S.Buffer:void 0;a.exports=(b?b.isBuffer:void 0)||de}),ee=/^(?:0|[1-9]\d*)$/,Ta=function(a,b){var c=H(a);b=null==b?9007199254740991:b;return!!b&&("number"==c||"symbol"!=c&&
+ee.test(a))&&-1<a&&0==a%1&&a<b},Qb=function(a){return"number"==typeof a&&-1<a&&0==a%1&&9007199254740991>=a},m={};m["[object Float32Array]"]=m["[object Float64Array]"]=m["[object Int8Array]"]=m["[object Int16Array]"]=m["[object Int32Array]"]=m["[object Uint8Array]"]=m["[object Uint8ClampedArray]"]=m["[object Uint16Array]"]=m["[object Uint32Array]"]=!0;m["[object Arguments]"]=m["[object Array]"]=m["[object ArrayBuffer]"]=m["[object Boolean]"]=m["[object DataView]"]=m["[object Date]"]=m["[object Error]"]=
+m["[object Function]"]=m["[object Map]"]=m["[object Number]"]=m["[object Object]"]=m["[object RegExp]"]=m["[object Set]"]=m["[object String]"]=m["[object WeakMap]"]=!1;var fe=function(a){return T(a)&&Qb(a.length)&&!!m[U(a)]},ge=function(a){return function(b){return a(b)}},Oc=qa(function(a,b){var c=b&&!b.nodeType&&b;c=(b=c&&a&&!a.nodeType&&a)&&b.exports===c&&Ic.process;a:{try{var e=b&&b.require&&b.require("util").types;if(e){var d=e;break a}d=c&&c.binding&&c.binding("util");break a}catch(f){}d=void 0}a.exports=
+d}),Pc=Oc&&Oc.isTypedArray,Rb=Pc?ge(Pc):fe,he=Object.prototype.hasOwnProperty,ie=Object.prototype,Qc=function(a,b){return function(c){return a(b(c))}},je=Qc(Object.keys,Object),ke=Object.prototype.hasOwnProperty,N=function(a){var b=H(a);return null!=a&&("object"==b||"function"==b)},Rc=function(a){if(!N(a))return!1;a=U(a);return"[object Function]"==a||"[object GeneratorFunction]"==a||"[object AsyncFunction]"==a||"[object Proxy]"==a},Ca=function(a){return null!=a&&Qb(a.length)&&!Rc(a)},Ka=function(a){if(Ca(a)){var b=
+F(a),c=!b&&Nc(a),e=!b&&!c&&ib(a),d=!b&&!c&&!e&&Rb(a);if(b=b||c||e||d){c=a.length;for(var f=String,h=-1,g=Array(c);++h<c;)g[h]=f(h);c=g}else c=[];f=c.length;for(var k in a)!he.call(a,k)||b&&("length"==k||e&&("offset"==k||"parent"==k)||d&&("buffer"==k||"byteLength"==k||"byteOffset"==k)||Ta(k,f))||c.push(k);a=c}else if(k=a&&a.constructor,a===("function"==typeof k&&k.prototype||ie)){k=[];for(e in Object(a))ke.call(a,e)&&"constructor"!=e&&k.push(e);a=k}else a=je(a);return a},Sc=function(a,b){return a&&
+Xd(a,b,Ka)},Ua=function(a,b){return function(c,e){if(null==c)return c;if(!Ca(c))return a(c,e);for(var d=c.length,f=b?d:-1,h=Object(c);(b?f--:++f<d)&&!1!==e(h[f],f,h););return c}}(Sc),Tc=function(a){return a},L=function(a,b){return(F(a)?Wd:Ua)(a,"function"==typeof b?b:Tc)},Uc=function(a,b){for(var c=-1,e=null==a?0:a.length,d=0,f=[];++c<e;){var h=a[c];b(h,c,a)&&(f[d++]=h)}return f},le=function(a,b){var c=[];Ua(a,function(a,d,f){b(a,d,f)&&c.push(a)});return c},zb=function(a,b){return a===b||a!==a&&b!==
+b},ka=function(a,b){for(var c=a.length;c--;)if(zb(a[c][0],b))return c;return-1},me=Array.prototype.splice;ra.prototype.clear=function(){this.__data__=[];this.size=0};ra.prototype["delete"]=function(a){var b=this.__data__;a=ka(b,a);if(0>a)return!1;a==b.length-1?b.pop():me.call(b,a,1);--this.size;return!0};ra.prototype.get=function(a){var b=this.__data__;a=ka(b,a);return 0>a?void 0:b[a][1]};ra.prototype.has=function(a){return-1<ka(this.__data__,a)};ra.prototype.set=function(a,b){var c=this.__data__,
+e=ka(c,a);0>e?(++this.size,c.push([a,b])):c[e][1]=b;return this};var Ga=ra,Va=S["__core-js_shared__"],Vc=function(){var a=/[^.]+$/.exec(Va&&Va.keys&&Va.keys.IE_PROTO||"");return a?"Symbol(src)_1."+a:""}(),ne=Function.prototype.toString,la=function(a){if(null!=a){try{return ne.call(a)}catch(b){}return a+""}return""},oe=/^\[object .+?Constructor\]$/,pe=RegExp("^"+Function.prototype.toString.call(Object.prototype.hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,
+"$1.*?")+"$"),ma=function(a,b){a=null==a?void 0:a[b];return(!N(a)||Vc&&Vc in a?0:(Rc(a)?pe:oe).test(la(a)))?a:void 0},na=ma(S,"Map"),Wa=ma(Object,"create"),qe=Object.prototype.hasOwnProperty,re=Object.prototype.hasOwnProperty;Y.prototype.clear=function(){this.__data__=Wa?Wa(null):{};this.size=0};Y.prototype["delete"]=function(a){a=this.has(a)&&delete this.__data__[a];this.size-=a?1:0;return a};Y.prototype.get=function(a){var b=this.__data__;return Wa?(a=b[a],"__lodash_hash_undefined__"===a?void 0:
+a):qe.call(b,a)?b[a]:void 0};Y.prototype.has=function(a){var b=this.__data__;return Wa?void 0!==b[a]:re.call(b,a)};Y.prototype.set=function(a,b){var c=this.__data__;this.size+=this.has(a)?0:1;c[a]=Wa&&void 0===b?"__lodash_hash_undefined__":b;return this};var Da=function(a,b){a=a.__data__;var c=H(b);return("string"==c||"number"==c||"symbol"==c||"boolean"==c?"__proto__"!==b:null===b)?a["string"==typeof b?"string":"hash"]:a.map};sa.prototype.clear=function(){this.size=0;this.__data__={hash:new Y,map:new (na||
+Ga),string:new Y}};sa.prototype["delete"]=function(a){a=Da(this,a)["delete"](a);this.size-=a?1:0;return a};sa.prototype.get=function(a){return Da(this,a).get(a)};sa.prototype.has=function(a){return Da(this,a).has(a)};sa.prototype.set=function(a,b){var c=Da(this,a),e=c.size;c.set(a,b);this.size+=c.size==e?0:1;return this};var Ha=sa;ta.prototype.clear=function(){this.__data__=new Ga;this.size=0};ta.prototype["delete"]=function(a){var b=this.__data__;a=b["delete"](a);this.size=b.size;return a};ta.prototype.get=
+function(a){return this.__data__.get(a)};ta.prototype.has=function(a){return this.__data__.has(a)};ta.prototype.set=function(a,b){var c=this.__data__;if(c instanceof Ga){var e=c.__data__;if(!na||199>e.length)return e.push([a,b]),this.size=++c.size,this;c=this.__data__=new Ha(e)}c.set(a,b);this.size=c.size;return this};var Ja=ta;ua.prototype.add=ua.prototype.push=function(a){this.__data__.set(a,"__lodash_hash_undefined__");return this};ua.prototype.has=function(a){return this.__data__.has(a)};var se=
+function(a,b){for(var c=-1,e=null==a?0:a.length;++c<e;)if(b(a[c],c,a))return!0;return!1},gc=function(a,b,c,e,d,f){var h=c&1,g=a.length,k=b.length;if(g!=k&&!(h&&k>g))return!1;k=f.get(a);var p=f.get(b);if(k&&p)return k==b&&p==a;k=-1;p=!0;var m=c&2?new ua:void 0;f.set(a,b);for(f.set(b,a);++k<g;){var q=a[k],n=b[k];if(e)var r=h?e(n,q,k,b,a,f):e(q,n,k,a,b,f);if(void 0!==r){if(r)continue;p=!1;break}if(m){if(!se(b,function(a,b){if(!m.has(b)&&(q===a||d(q,a,c,e,f)))return m.push(b)})){p=!1;break}}else if(q!==
+n&&!d(q,n,c,e,f)){p=!1;break}}f["delete"](a);f["delete"](b);return p},Wc=S.Uint8Array,te=function(a){var b=-1,c=Array(a.size);a.forEach(function(a,d){c[++b]=[d,a]});return c},ue=function(a){var b=-1,c=Array(a.size);a.forEach(function(a){c[++b]=a});return c},Xc=X?X.prototype:void 0,Xa=Xc?Xc.valueOf:void 0,md=function(a,b,c,e,d,f,h){switch(c){case "[object DataView]":if(a.byteLength!=b.byteLength||a.byteOffset!=b.byteOffset)break;a=a.buffer;b=b.buffer;case "[object ArrayBuffer]":if(a.byteLength!=b.byteLength||
+!f(new Wc(a),new Wc(b)))break;return!0;case "[object Boolean]":case "[object Date]":case "[object Number]":return zb(+a,+b);case "[object Error]":return a.name==b.name&&a.message==b.message;case "[object RegExp]":case "[object String]":return a==b+"";case "[object Map]":var g=te;case "[object Set]":g||(g=ue);if(a.size!=b.size&&!(e&1))break;if(c=h.get(a))return c==b;e|=2;h.set(a,b);b=gc(g(a),g(b),e,d,f,h);h["delete"](a);return b;case "[object Symbol]":if(Xa)return Xa.call(a)==Xa.call(b)}return!1},
+ic=function(a,b,c){b=b(a);if(!F(a)){a=c(a);c=-1;for(var e=a.length,d=b.length;++c<e;)b[d+c]=a[c]}return b},ve=function(){return[]},we=Object.prototype.propertyIsEnumerable,Yc=Object.getOwnPropertySymbols,jc=Yc?function(a){if(null==a)return[];a=Object(a);return Uc(Yc(a),function(b){return we.call(a,b)})}:ve,nd=Object.prototype.hasOwnProperty,Ya=ma(S,"DataView"),Za=ma(S,"Promise"),$a=ma(S,"Set"),ab=ma(S,"WeakMap"),xe=la(Ya),ye=la(na),ze=la(Za),Ae=la($a),Be=la(ab),oa=U;if(Ya&&"[object DataView]"!=oa(new Ya(new ArrayBuffer(1)))||
+na&&"[object Map]"!=oa(new na)||Za&&"[object Promise]"!=oa(Za.resolve())||$a&&"[object Set]"!=oa(new $a)||ab&&"[object WeakMap]"!=oa(new ab))oa=function(a){var b=U(a);if(a=(a="[object Object]"==b?a.constructor:void 0)?la(a):"")switch(a){case xe:return"[object DataView]";case ye:return"[object Map]";case ze:return"[object Promise]";case Ae:return"[object Set]";case Be:return"[object WeakMap]"}return b};var Fb=oa,hc=Object.prototype.hasOwnProperty,ob=Ia,Ce=function(a,b,c,e){var d=c.length,f=d,h=!e;
+if(null==a)return!f;for(a=Object(a);d--;){var g=c[d];if(h&&g[2]?g[1]!==a[g[0]]:!(g[0]in a))return!1}for(;++d<f;){g=c[d];var k=g[0],p=a[k],m=g[1];if(h&&g[2]){if(void 0===p&&!(k in a))return!1}else{g=new Ja;if(e)var q=e(p,m,k,a,b,g);if(void 0===q?!ob(m,p,3,e,g):!q)return!1}}return!0},De=function(a){for(var b=Ka(a),c=b.length;c--;){var e=b[c],d=a[e];b[c]=[e,d,d===d&&!N(d)]}return b},Zc=function(a,b){return function(c){return null==c?!1:c[a]===b&&(void 0!==b||a in Object(c))}},Ee=function(a){var b=De(a);
+return 1==b.length&&b[0][2]?Zc(b[0][0],b[0][1]):function(c){return c===a||Ce(c,a,b)}},ba=function(a){return"symbol"==H(a)||T(a)&&"[object Symbol]"==U(a)},Fe=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Ge=/^\w*$/,bb=function(a,b){if(F(a))return!1;var c=H(a);return"number"==c||"symbol"==c||"boolean"==c||null==a||ba(a)?!0:Ge.test(a)||!Fe.test(a)||null!=b&&a in Object(b)};jb.Cache=Ha;var He=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Ie=/\\(\\)?/g,
+Je=function(a){a=jb(a,function(a){500===b.size&&b.clear();return a});var b=a.cache;return a}(function(a){var b=[];46===a.charCodeAt(0)&&b.push("");a.replace(He,function(a,e,d,f){b.push(d?f.replace(Ie,"$1"):e||a)});return b}),lc=function(a,b){for(var c=-1,e=null==a?0:a.length,d=Array(e);++c<e;)d[c]=b(a[c],c,a);return d},od=1/0,$c=X?X.prototype:void 0,mc=$c?$c.toString:void 0,ad=function(a,b){return F(a)?a:bb(a,b)?[a]:Je(null==a?"":kc(a))},Ke=1/0,Ab=function(a){if("string"==typeof a||ba(a))return a;
+var b=a+"";return"0"==b&&1/a==-Ke?"-0":b},bd=function(a,b){b=ad(b,a);for(var c=0,e=b.length;null!=a&&c<e;)a=a[Ab(b[c++])];return c&&c==e?a:void 0},J=function(a,b,c){a=null==a?void 0:bd(a,b);return void 0===a?c:a},Le=function(a,b){return null!=a&&b in Object(a)},pb=function(a,b,c){b=ad(b,a);for(var e=-1,d=b.length,f=!1;++e<d;){var h=Ab(b[e]);if(!(f=null!=a&&c(a,h)))break;a=a[h]}if(f||++e!=d)return f;d=null==a?0:a.length;return!!d&&Qb(d)&&Ta(h,d)&&(F(a)||Nc(a))},Me=function(a,b){return bb(a)&&b===b&&
+!N(b)?Zc(Ab(a),b):function(c){var e=J(c,a);return void 0===e&&e===b?null!=c&&pb(c,a,Le):ob(b,e,3)}},Ne=function(a){return function(b){return null==b?void 0:b[a]}},Oe=function(a){return function(b){return bd(b,a)}},Ea=function(a){return"function"==typeof a?a:null==a?Tc:"object"==H(a)?F(a)?Me(a[0],a[1]):Ee(a):bb(a)?Ne(Ab(a)):Oe(a)},pd=function(a,b){return(F(a)?Uc:le)(a,Ea(b))},oc=function(a){return"string"==typeof a||!F(a)&&T(a)&&"[object String]"==U(a)},Pe=function(a,b){var c=-1,e=Ca(a)?Array(a.length):
+[];Ua(a,function(a,f,h){e[++c]=b(a,f,h)});return e},da=function(a,b){return(F(a)?lc:Pe)(a,Ea(b))},ca=window,va=document,wa=window.localStorage,uc=window.sessionStorage,cd=0/0,Qe=/^\s+|\s+$/g,Re=/^[-+]0x[0-9a-f]+$/i,Se=/^0b[01]+$/i,Te=/^0o[0-7]+$/i,Ue=parseInt,Ve=function(a){if("number"==typeof a)return a;if(ba(a))return cd;N(a)&&(a="function"==typeof a.valueOf?a.valueOf():a,a=N(a)?a+"":a);if("string"!=typeof a)return 0===a?a:+a;a=a.replace(Qe,"");var b=Se.test(a);return b||Te.test(a)?Ue(a.slice(2),
+b?2:8):Re.test(a)?cd:+a},dd=1/0,fc=function(a){a?(a=Ve(a),a=a===dd||a===-dd?1.7976931348623157E308*(0>a?-1:1):a===a?a:0):a=0===a?a:0;var b=a%1;return a===a?b?a-b:a:0},Vd=qa(function(a,b){(function(a){var c=function(){var a=function(a){a=-a.getTimezoneOffset();return null!==a?a:0},b=function(a,b,c){var d=new Date;void 0!==a&&d.setFullYear(a);d.setMonth(b);d.setDate(c);return d};return{determine:function(){var d=a(b(void 0,0,2)),e=a(b(void 0,5,2)),f=d-e;return new c.TimeZone(c.olson.timezones[0>f?d+
+",1":0<f?e+",1,s":d+",0"])},date_is_dst:function(c){var d=7<c.getMonth(),e=d?a(b(c.getFullYear(),5,2)):a(b(c.getFullYear(),0,2));c=a(c);c=e-c;return 0>e||d?0!==c:0>c},dst_start_for:function(a){var b=new Date(2010,6,15,1,0,0,0);return{"America/Denver":new Date(2011,2,13,3,0,0,0),"America/Mazatlan":new Date(2011,3,3,3,0,0,0),"America/Chicago":new Date(2011,2,13,3,0,0,0),"America/Mexico_City":new Date(2011,3,3,3,0,0,0),"America/Asuncion":new Date(2012,9,7,3,0,0,0),"America/Santiago":new Date(2012,9,
+3,3,0,0,0),"America/Campo_Grande":new Date(2012,9,21,5,0,0,0),"America/Montevideo":new Date(2011,9,2,3,0,0,0),"America/Sao_Paulo":new Date(2011,9,16,5,0,0,0),"America/Los_Angeles":new Date(2011,2,13,8,0,0,0),"America/Santa_Isabel":new Date(2011,3,5,8,0,0,0),"America/Havana":new Date(2012,2,10,2,0,0,0),"America/New_York":new Date(2012,2,10,7,0,0,0),"Europe/Helsinki":new Date(2013,2,31,5,0,0,0),"Pacific/Auckland":new Date(2011,8,26,7,0,0,0),"America/Halifax":new Date(2011,2,13,6,0,0,0),"America/Goose_Bay":new Date(2011,
+2,13,2,1,0,0),"America/Miquelon":new Date(2011,2,13,5,0,0,0),"America/Godthab":new Date(2011,2,27,1,0,0,0),"Europe/Moscow":b,"Asia/Amman":new Date(2013,2,29,1,0,0,0),"Asia/Beirut":new Date(2013,2,31,2,0,0,0),"Asia/Damascus":new Date(2013,3,6,2,0,0,0),"Asia/Jerusalem":new Date(2013,2,29,5,0,0,0),"Asia/Yekaterinburg":b,"Asia/Omsk":b,"Asia/Krasnoyarsk":b,"Asia/Irkutsk":b,"Asia/Yakutsk":b,"Asia/Vladivostok":b,"Asia/Baku":new Date(2013,2,31,4,0,0),"Asia/Yerevan":new Date(2013,2,31,3,0,0),"Asia/Kamchatka":b,
+"Asia/Gaza":new Date(2010,2,27,4,0,0),"Africa/Cairo":new Date(2010,4,1,3,0,0),"Europe/Minsk":b,"Pacific/Apia":new Date(2010,10,1,1,0,0,0),"Pacific/Fiji":new Date(2010,11,1,0,0,0),"Australia/Perth":new Date(2008,10,1,1,0,0,0)}[a]}}}();c.TimeZone=function(a){var b={"America/Denver":["America/Denver","America/Mazatlan"],"America/Chicago":["America/Chicago","America/Mexico_City"],"America/Santiago":["America/Santiago","America/Asuncion","America/Campo_Grande"],"America/Montevideo":["America/Montevideo",
+"America/Sao_Paulo"],"Asia/Beirut":["Asia/Amman","Asia/Jerusalem","Asia/Beirut","Europe/Helsinki","Asia/Damascus"],"Pacific/Auckland":["Pacific/Auckland","Pacific/Fiji"],"America/Los_Angeles":["America/Los_Angeles","America/Santa_Isabel"],"America/New_York":["America/Havana","America/New_York"],"America/Halifax":["America/Goose_Bay","America/Halifax"],"America/Godthab":["America/Miquelon","America/Godthab"],"Asia/Dubai":["Europe/Moscow"],"Asia/Dhaka":["Asia/Yekaterinburg"],"Asia/Jakarta":["Asia/Omsk"],
+"Asia/Shanghai":["Asia/Krasnoyarsk","Australia/Perth"],"Asia/Tokyo":["Asia/Irkutsk"],"Australia/Brisbane":["Asia/Yakutsk"],"Pacific/Noumea":["Asia/Vladivostok"],"Pacific/Tarawa":["Asia/Kamchatka","Pacific/Fiji"],"Pacific/Tongatapu":["Pacific/Apia"],"Asia/Baghdad":["Europe/Minsk"],"Asia/Baku":["Asia/Yerevan","Asia/Baku"],"Africa/Johannesburg":["Asia/Gaza","Africa/Cairo"]},d=a;a=function(){for(var a=b[d],e=a.length,f=0,h;f<e;f+=1)if(h=a[f],c.date_is_dst(c.dst_start_for(h))){d=h;break}};"undefined"!==
+typeof b[d]&&a();return{name:function(){return d}}};c.olson={};c.olson.timezones={"-720,0":"Pacific/Majuro","-660,0":"Pacific/Pago_Pago","-600,1":"America/Adak","-600,0":"Pacific/Honolulu","-570,0":"Pacific/Marquesas","-540,0":"Pacific/Gambier","-540,1":"America/Anchorage","-480,1":"America/Los_Angeles","-480,0":"Pacific/Pitcairn","-420,0":"America/Phoenix","-420,1":"America/Denver","-360,0":"America/Guatemala","-360,1":"America/Chicago","-360,1,s":"Pacific/Easter","-300,0":"America/Bogota","-300,1":"America/New_York",
+"-270,0":"America/Caracas","-240,1":"America/Halifax","-240,0":"America/Santo_Domingo","-240,1,s":"America/Santiago","-210,1":"America/St_Johns","-180,1":"America/Godthab","-180,0":"America/Argentina/Buenos_Aires","-180,1,s":"America/Montevideo","-120,0":"America/Noronha","-120,1":"America/Noronha","-60,1":"Atlantic/Azores","-60,0":"Atlantic/Cape_Verde","0,0":"UTC","0,1":"Europe/London","60,1":"Europe/Berlin","60,0":"Africa/Lagos","60,1,s":"Africa/Windhoek","120,1":"Asia/Beirut","120,0":"Africa/Johannesburg",
+"180,0":"Asia/Baghdad","180,1":"Europe/Moscow","210,1":"Asia/Tehran","240,0":"Asia/Dubai","240,1":"Asia/Baku","270,0":"Asia/Kabul","300,1":"Asia/Yekaterinburg","300,0":"Asia/Karachi","330,0":"Asia/Kolkata","345,0":"Asia/Kathmandu","360,0":"Asia/Dhaka","360,1":"Asia/Omsk","390,0":"Asia/Rangoon","420,1":"Asia/Krasnoyarsk","420,0":"Asia/Jakarta","480,0":"Asia/Shanghai","480,1":"Asia/Irkutsk","525,0":"Australia/Eucla","525,1,s":"Australia/Eucla","540,1":"Asia/Yakutsk","540,0":"Asia/Tokyo","570,0":"Australia/Darwin",
+"570,1,s":"Australia/Adelaide","600,0":"Australia/Brisbane","600,1":"Asia/Vladivostok","600,1,s":"Australia/Sydney","630,1,s":"Australia/Lord_Howe","660,1":"Asia/Kamchatka","660,0":"Pacific/Noumea","690,0":"Pacific/Norfolk","720,1,s":"Pacific/Auckland","720,0":"Pacific/Tarawa","765,1,s":"Pacific/Chatham","780,0":"Pacific/Tongatapu","780,1,s":"Pacific/Apia","840,0":"Pacific/Kiritimati"};b.jstz=c})()}),ya=window,R=navigator,nb=screen,Ma=document,cb=qa(function(a){(function(){var b={rotl:function(a,
+b){return a<<b|a>>>32-b},rotr:function(a,b){return a<<32-b|a>>>b},endian:function(a){if(a.constructor==Number)return b.rotl(a,8)&16711935|b.rotl(a,24)&4278255360;for(var c=0;c<a.length;c++)a[c]=b.endian(a[c]);return a},randomBytes:function(a){for(var b=[];0<a;a--)b.push(Math.floor(256*Math.random()));return b},bytesToWords:function(a){for(var b=[],c=0,f=0;c<a.length;c++,f+=8)b[f>>>5]|=a[c]<<24-f%32;return b},wordsToBytes:function(a){for(var b=[],c=0;c<32*a.length;c+=8)b.push(a[c>>>5]>>>24-c%32&255);
+return b},bytesToHex:function(a){for(var b=[],c=0;c<a.length;c++)b.push((a[c]>>>4).toString(16)),b.push((a[c]&15).toString(16));return b.join("")},hexToBytes:function(a){for(var b=[],c=0;c<a.length;c+=2)b.push(parseInt(a.substr(c,2),16));return b},bytesToBase64:function(a){for(var b=[],c=0;c<a.length;c+=3)for(var f=a[c]<<16|a[c+1]<<8|a[c+2],h=0;4>h;h++)8*c+6*h<=8*a.length?b.push("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(f>>>6*(3-h)&63)):b.push("=");return b.join("")},
+base64ToBytes:function(a){a=a.replace(/[^A-Z0-9+\/]/ig,"");for(var b=[],c=0,f=0;c<a.length;f=++c%4)0!=f&&b.push(("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(a.charAt(c-1))&Math.pow(2,-2*f+8)-1)<<2*f|"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(a.charAt(c))>>>6-2*f);return b}};a.exports=b})()}),db={utf8:{stringToBytes:function(a){return db.bin.stringToBytes(unescape(encodeURIComponent(a)))},bytesToString:function(a){return decodeURIComponent(escape(db.bin.bytesToString(a)))}},
+bin:{stringToBytes:function(a){for(var b=[],c=0;c<a.length;c++)b.push(a.charCodeAt(c)&255);return b},bytesToString:function(a){for(var b=[],c=0;c<a.length;c++)b.push(String.fromCharCode(a[c]));return b.join("")}}},ed=db,Ud=qa(function(a){(function(){var b=ed.utf8,c=ed.bin,e=function(a){a.constructor==String&&(a=b.stringToBytes(a));var c=cb.bytesToWords(a),d=8*a.length;a=[];var e=1732584193,f=-271733879,m=-1732584194,q=271733878,n=-1009589776;c[d>>5]|=128<<24-d%32;c[(d+64>>>9<<4)+15]=d;for(d=0;d<c.length;d+=
+16){for(var r=e,t=f,v=m,E=q,F=n,y=0;80>y;y++){if(16>y)a[y]=c[d+y];else{var A=a[y-3]^a[y-8]^a[y-14]^a[y-16];a[y]=A<<1|A>>>31}A=(e<<5|e>>>27)+n+(a[y]>>>0)+(20>y?(f&m|~f&q)+1518500249:40>y?(f^m^q)+1859775393:60>y?(f&m|f&q|m&q)-1894007588:(f^m^q)-899497514);n=q;q=m;m=f<<30|f>>>2;f=e;e=A}e+=r;f+=t;m+=v;q+=E;n+=F}return[e,f,m,q,n]},d=function(a,b){a=cb.wordsToBytes(e(a));return b&&b.asBytes?a:b&&b.asString?c.bytesToString(a):cb.bytesToHex(a)};d._blocksize=16;d._digestsize=20;a.exports=d})()}),We=Math.max,
+zd=function(a){return function(b,c,e){var d=Object(b);if(!Ca(b)){var f=Ea(c);b=Ka(b);c=function(a){return f(d[a],a,d)}}c=a(b,c,e);return-1<c?d[f?b[c]:c]:void 0}}(function(a,b,c){var e=null==a?0:a.length;if(!e)return-1;c=null==c?0:fc(c);0>c&&(c=We(e+c,0));a:{b=Ea(b);e=a.length;for(c+=-1;++c<e;)if(b(a[c],c,a)){a=c;break a}a=-1}return a}),Bd=window,fd=function(){try{var a=ma(Object,"defineProperty");a({},"",{});return a}catch(b){}}(),Cd=function(a,b){var c={};b=Ea(b);Sc(a,function(a,d,f){a=b(a,d,f);
+"__proto__"==d&&fd?fd(c,d,{configurable:!0,enumerable:!0,value:a,writable:!0}):c[d]=a});return c},Ed=function(a){return function(){try{return a.apply(this,arguments)}catch(b){}}},gd=qa(function(a){var b="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof window.msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto);if(b){var c=new Uint8Array(16);a.exports=function(){b(c);return c}}else{var e=Array(16);
+a.exports=function(){for(var a=0,b;16>a;a++)0===(a&3)&&(b=4294967296*Math.random()),e[a]=b>>>((a&3)<<3)&255;return e}}}),r=[],Bb=0;for(;256>Bb;++Bb)r[Bb]=(Bb+256).toString(16).substr(1);var hd=function(a,b){b=b||0;return[r[a[b++]],r[a[b++]],r[a[b++]],r[a[b++]],"-",r[a[b++]],r[a[b++]],"-",r[a[b++]],r[a[b++]],"-",r[a[b++]],r[a[b++]],"-",r[a[b++]],r[a[b++]],r[a[b++]],r[a[b++]],r[a[b++]],r[a[b++]]].join("")},id,eb,fb=0,Cb=0,V=function(a,b,c){c=b&&c||0;"string"==typeof a&&(b="binary"===a?Array(16):null,
+a=null);a=a||{};a=a.random||(a.rng||gd)();a[6]=a[6]&15|64;a[8]=a[8]&63|128;if(b)for(var e=0;16>e;++e)b[c+e]=a[e];return b||hd(a)},gb=V;gb.v1=function(a,b,c){c=b&&c||0;var e=b||[];a=a||{};var d=a.node||id,f=void 0!==a.clockseq?a.clockseq:eb;if(null==d||null==f){var h=gd();null==d&&(d=id=[h[0]|1,h[1],h[2],h[3],h[4],h[5]]);null==f&&(f=eb=(h[6]<<8|h[7])&16383)}h=void 0!==a.msecs?a.msecs:(new Date).getTime();var g=void 0!==a.nsecs?a.nsecs:Cb+1,k=h-fb+(g-Cb)/1E4;0>k&&void 0===a.clockseq&&(f=f+1&16383);
+(0>k||h>fb)&&void 0===a.nsecs&&(g=0);if(1E4<=g)throw Error("uuid.v1(): Can't create more than 10M uuids/sec");fb=h;Cb=g;eb=f;h+=122192928E5;a=(1E4*(h&268435455)+g)%4294967296;e[c++]=a>>>24&255;e[c++]=a>>>16&255;e[c++]=a>>>8&255;e[c++]=a&255;a=h/4294967296*1E4&268435455;e[c++]=a>>>8&255;e[c++]=a&255;e[c++]=a>>>24&15|16;e[c++]=a>>>16&255;e[c++]=f>>>8|128;e[c++]=f&255;for(f=0;6>f;++f)e[c+f]=d[f];return b?b:hd(e)};gb.v4=V;var Sd=gb,Xe=Object.prototype.hasOwnProperty,qb=function(a,b){return null!=a&&Xe.call(a,
+b)},Ye=function(a,b){for(var c=-1,e=null==a?0:a.length;++c<e;)if(!b(a[c],c,a))return!1;return!0},Ze=function(a,b){var c=!0;Ua(a,function(a,d,f){return c=!!b(a,d,f)});return c},rb=function(a,b,c){var e=F(a)?Ye:Ze,d;if(d=c)if(d=b,N(c)){var f=H(d);d=("number"==f?Ca(c)&&Ta(d,c.length):"string"==f&&d in c)?zb(c[d],a):!1}else d=!1;d&&(b=void 0);return e(a,Ea(b))},Gc=function(a){for(var b=-1,c=null==a?0:a.length,e=0,d=[];++b<c;){var f=a[b];f&&(d[e++]=f)}return d},Md=Qc(Object.getPrototypeOf,Object),Ac=Function.prototype.toString,
+Nd=Object.prototype.hasOwnProperty,Od=Ac.call(Object),aa=window;if(aa.GlobalSnowplowNamespace&&0<aa.GlobalSnowplowNamespace.length){var jd=aa.GlobalSnowplowNamespace.shift();var kd=aa[jd];kd.q=new Hc(kd.q,jd)}else aa._snaq=aa._snaq||[],aa._snaq=new Hc(aa._snaq,"_snaq")})()
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 53b13f4c9fe..a2e89886d6d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -845,10 +845,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/at.js/-/at.js-1.5.5.tgz#5f6bfe6baaef360daa9b038fa78798d7a6a916b4"
integrity sha512-282Dn3SPVsUHVDhMsXgfnv+Rzog0uxecjttxGRQvxh25es1+xvkGQFsvJfkSKJ3X1kHVkSjKf+Tt5Rra+Jhp9g==
-"@gitlab/eslint-plugin@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==
+"@gitlab/eslint-plugin@5.0.0":
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-5.0.0.tgz#502eb2bccb55d65d6310ce9ef2da76035b6fc319"
+ integrity sha512-zd4pa6D2OUuhPUD2QmyhfpZh7vuXKsNHaCHJdbTb2ld+mHel5IDqdidAzAshCI9On3e6o9XieD6l7rBTpN6H/g==
dependencies:
babel-eslint "^10.0.3"
eslint-config-airbnb-base "^14.0.0"
@@ -861,21 +861,21 @@
eslint-plugin-vue "^6.2.1"
vue-eslint-parser "^7.0.0"
-"@gitlab/svgs@1.171.0":
- version "1.171.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.171.0.tgz#abc3092bf804f0898301626130e0f3231834924a"
- integrity sha512-TPfdqIxQDda+0CQHhb9XdF50lmqDmADu6yT8R4oZi6BoUtWLdiHbyFt+RnVU6t7EmjIKicNAii7Ga+f2ljCfUA==
+"@gitlab/svgs@1.175.0":
+ version "1.175.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.175.0.tgz#734f341784af1cd1d62d160a17bcdfb61ff7b04d"
+ integrity sha512-gXpc87TGSXIzfAr4QER1Qw1v3P47pBO6BXkma52blgwXVmcFNe3nhQzqsqt66wKNzrIrk3lAcB4GUyPHbPVXpg==
-"@gitlab/ui@21.33.0":
- version "21.33.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-21.33.0.tgz#83dd7e4d65557f7b82ce1f9d7d6e7a1c54cb3dbc"
- integrity sha512-UBLTz5A1z1Usxw2yfjFNuQ1Ccgx7dYD3M+lDfewDYlU48s0PY7Hm/VXsd543XIuIf+4GEJ1b43kptEZI1wtrbQ==
+"@gitlab/ui@23.9.0":
+ version "23.9.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-23.9.0.tgz#e21966130b41e624dbe4505911a79afb731c2d6b"
+ integrity sha512-IfaiIcRw6iKE9Fxx36LQ1Afa/fcdmvRQCJO9igc+wWD3MFZGU/ggsQw3SExkkYI6XYmDUr56CT/o+HYlCDjgZQ==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"
bootstrap-vue "2.13.1"
copy-to-clipboard "^3.0.8"
- dompurify "^2.1.1"
+ dompurify "^2.2.2"
echarts "^4.2.1"
highlight.js "^9.13.1"
js-beautify "^1.8.8"
@@ -1148,10 +1148,10 @@
dependencies:
"@sinonjs/commons" "^1.7.0"
-"@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==
+"@sourcegraph/code-host-integration@0.0.52":
+ version "0.0.52"
+ resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.52.tgz#3668364647b9248a0c43d738f7b046c551311338"
+ integrity sha512-HYmiGuQ3XOQHJIQaRv63Wcdl6y1rgryBrCLzJd/mG5gkkhydTqBuf3wWFKgfL3PCm026OrjXu4PvOYU1fCTZJQ==
"@szmarczak/http-timer@^1.1.2":
version "1.1.2"
@@ -1173,20 +1173,20 @@
dom-accessibility-api "^0.5.1"
pretty-format "^26.4.2"
-"@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==
+"@toast-ui/editor@^2.5.0":
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/@toast-ui/editor/-/editor-2.5.0.tgz#02779b119eaa6dd7601249d75ca031e0b98400f1"
+ integrity sha512-h4LgcGz+oedTqNAaSCp0VpR+k4C6Ag01hdDb1kPvO4aMQ/aTtT8uA34plpmYQgJvM0CWD1mXqWUSPkyJtRzDyA==
dependencies:
"@types/codemirror" "0.0.71"
codemirror "^5.48.4"
-"@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==
+"@toast-ui/vue-editor@^2.5.0":
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/@toast-ui/vue-editor/-/vue-editor-2.5.0.tgz#8094136588b0f726241b5f89d0754a7169f2ffee"
+ integrity sha512-GREAaVOe5esQaQFmFCZLjo6iOtIvqvYhANulvsKpbh4QNnsPLaFRIQoUDSImNPVGkDDQn60wxXBnZVKOl9sMmg==
dependencies:
- "@toast-ui/editor" "^2.4.0"
+ "@toast-ui/editor" "^2.5.0"
"@types/aria-query@^4.2.0":
version "4.2.0"
@@ -1659,6 +1659,13 @@ after@0.8.2:
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
+agent-base@4, agent-base@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
+ integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
+ dependencies:
+ es6-promisify "^5.0.0"
+
aggregate-error@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0"
@@ -3833,7 +3840,14 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
dependencies:
ms "2.0.0"
-debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
+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.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"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
@@ -3847,13 +3861,6 @@ 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"
@@ -4174,10 +4181,10 @@ domhandler@^2.3.0:
dependencies:
domelementtype "1"
-dompurify@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.1.1.tgz#b5aa988676b093a9c836d8b855680a8598af25fe"
- integrity sha512-NijiNVkS/OL8mdQL1hUbCD6uty/cgFpmNiuFxrmJ5YPH2cXrPKIewoixoji56rbZ6XBPmtM8GA8/sf9unlSuwg==
+dompurify@^2.2.2:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.2.2.tgz#cb8c2b1a2f3c8a0b565127504ae4eedec176a972"
+ integrity sha512-BsGR4nDLaC5CNBnyT5I+d5pOeaoWvgVeg6Gq/aqmKYWMPR07131u60I80BvExLAJ0FQEIBQ1BTicw+C5+jOyrg==
domutils@^1.5.1:
version "1.6.2"
@@ -4446,11 +4453,23 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
+es6-promise@^4.0.3:
+ version "4.2.8"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
+ integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
+
es6-promise@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6"
integrity sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=
+es6-promisify@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
+ integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
+ dependencies:
+ es6-promise "^4.0.3"
+
escape-goat@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675"
@@ -5609,17 +5628,15 @@ graphlib@^2.1.7, graphlib@^2.1.8:
dependencies:
lodash "^4.17.15"
-graphql-tag@^2.10.1:
- version "2.10.3"
- resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.3.tgz#ea1baba5eb8fc6339e4c4cf049dabe522b0edf03"
- integrity sha512-4FOv3ZKfA4WdOKJeHdz6B3F/vxBLSgmBcGeAFPf4n1F64ltJUvOOerNj0rsJxONQGdhUMynQIvd6LzB+1J5oKA==
+graphql-tag@^2.11.0:
+ version "2.11.0"
+ resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.11.0.tgz#1deb53a01c46a7eb401d6cb59dec86fa1cccbffd"
+ integrity sha512-VmsD5pJqWJnQZMUeRwrDhfgoyqcfwEkvtpANqcoUG8/tOLkwNgU9mzub/Mc78OJMhHjx7gfAMTxzdG43VGg3bA==
-graphql@^14.7.0:
- version "14.7.0"
- resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.7.0.tgz#7fa79a80a69be4a31c27dda824dc04dac2035a72"
- integrity sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA==
- dependencies:
- iterall "^1.2.2"
+graphql@^15.4.0:
+ version "15.4.0"
+ resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.4.0.tgz#e459dea1150da5a106486ba7276518b5295a4347"
+ integrity sha512-EB3zgGchcabbsU9cFe1j+yxdzKQKAbGUWRb13DsrsMN1yyfmmIq+2+L5MqVWcDCE4V89R5AyUOi7sMOGxdsYtA==
growly@^1.3.0:
version "1.3.0"
@@ -5897,6 +5914,14 @@ http-errors@~1.6.2:
setprototypeof "1.0.3"
statuses ">= 1.3.1 < 2"
+http-proxy-agent@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
+ integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
+ dependencies:
+ agent-base "4"
+ debug "3.1.0"
+
http-proxy-middleware@0.19.1:
version "0.19.1"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a"
@@ -5930,6 +5955,14 @@ https-browserify@^1.0.0:
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
+https-proxy-agent@^2.2.3:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
+ integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
+ dependencies:
+ agent-base "^4.3.0"
+ debug "^3.1.0"
+
human-signals@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
@@ -6684,11 +6717,6 @@ istextorbinary@^2.2.1:
editions "^1.3.3"
textextensions "2"
-iterall@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7"
- integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==
-
jasmine-core@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.9.0.tgz#bfbb56defcd30789adec5a3fbba8504233289c72"
@@ -7166,7 +7194,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.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==
@@ -7305,7 +7333,12 @@ json5@^1.0.1:
dependencies:
minimist "^1.2.0"
-jsonc-parser@^2.2.1, jsonc-parser@~2.2.0:
+jsonc-parser@^2.2.1, jsonc-parser@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.1.tgz#59549150b133f2efacca48fe9ce1ec0659af2342"
+ integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==
+
+jsonc-parser@~2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc"
integrity sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==
@@ -7550,6 +7583,13 @@ linkify-it@^2.0.0:
dependencies:
uc.micro "^1.0.1"
+linkify-it@^3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.2.tgz#f55eeb8bc1d3ae754049e124ab3bb56d97797fb8"
+ integrity sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==
+ dependencies:
+ uc.micro "^1.0.1"
+
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@@ -7931,14 +7971,14 @@ markdown-escapes@^1.0.0:
resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.2.tgz#e639cbde7b99c841c0bacc8a07982873b46d2122"
integrity sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==
-markdown-it@10.0.0:
- version "10.0.0"
- resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc"
- integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==
+markdown-it@11.0.0:
+ version "11.0.0"
+ resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-11.0.0.tgz#dbfc30363e43d756ebc52c38586b91b90046b876"
+ integrity sha512-+CvOnmbSubmQFSA9dKz1BRiaSMV7rhexl3sngKqFyXSagoA3fBdJQ8oZWtRy2knXdpDXaBw44euz37DeJQ9asg==
dependencies:
argparse "^1.0.7"
entities "~2.0.0"
- linkify-it "^2.0.0"
+ linkify-it "^3.0.1"
mdurl "^1.0.1"
uc.micro "^1.0.5"
@@ -7958,10 +7998,10 @@ markdown-table@^1.1.0:
resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.2.tgz#c78db948fa879903a41bce522e3b96f801c63786"
integrity sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==
-markdownlint-cli@0.23.2:
- version "0.23.2"
- resolved "https://registry.yarnpkg.com/markdownlint-cli/-/markdownlint-cli-0.23.2.tgz#43f0a96e2699542b74fb5e6188c025e4934357fc"
- integrity sha512-OSl5OZ8xzGN6z355cqRkiq67zPi3reJimklaF72p0554q85Dng5ToOjjSB9tDKZebSt85jX8cp+ruoQlPqOsPA==
+markdownlint-cli@0.24.0:
+ version "0.24.0"
+ resolved "https://registry.yarnpkg.com/markdownlint-cli/-/markdownlint-cli-0.24.0.tgz#d1c1d43cd53b87aaec93035b3234eef7097139a8"
+ integrity sha512-AusUxaX4sFayUBFTCKeHc8+fq73KFqIUW+ZZZYyQ/BvY0MoGAnE2C/3xiawSE7WXmpmguaWzhrXRuY6IrOLX7A==
dependencies:
commander "~2.9.0"
deep-extend "~0.5.1"
@@ -7972,23 +8012,23 @@ markdownlint-cli@0.23.2:
jsonc-parser "~2.2.0"
lodash.differencewith "~4.5.0"
lodash.flatten "~4.4.0"
- markdownlint "~0.20.4"
- markdownlint-rule-helpers "~0.11.0"
+ markdownlint "~0.21.0"
+ markdownlint-rule-helpers "~0.12.0"
minimatch "~3.0.4"
minimist "~1.2.5"
rc "~1.2.7"
-markdownlint-rule-helpers@~0.11.0:
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.11.0.tgz#faaaae4337771c7d88ca38ef6265afb4fbe0fb3f"
- integrity sha512-PhGii9dOiDJDXxiRMpK8N0FM9powprvRPsXALgkjlSPTwLh6ymH+iF3iUe3nq8KGu26tclFBlLL5xAGy/zb7FA==
+markdownlint-rule-helpers@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.12.0.tgz#c41d9b990c50911572e8eb2fba3e6975a5514b7e"
+ integrity sha512-Q7qfAk+AJvx82ZY52OByC4yjoQYryOZt6D8TKrZJIwCfhZvcj8vCQNuwDqILushtDBTvGFmUPq+uhOb1KIMi6A==
-markdownlint@~0.20.4:
- version "0.20.4"
- resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.20.4.tgz#3b34681494cdad174e14a27182b5cdefaa537823"
- integrity sha512-jpfaPgjT0OpeBbemjYNZbzGG3hCLcAIvrm/pEY3+q/szDScG6ZonDacqySVRJAv9glbo8y4wBPJ0wgW17+9GGA==
+markdownlint@~0.21.0:
+ version "0.21.1"
+ resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.21.1.tgz#9442afcf12bf65ce9d613212028cf85741677421"
+ integrity sha512-8kc88w5dyEzlmOWIElp8J17qBgzouOQfJ0LhCcpBFrwgyYK6JTKvILsk4FCEkiNqHkTxwxopT2RS2DYb/10qqg==
dependencies:
- markdown-it "10.0.0"
+ markdown-it "11.0.0"
marked@^0.3.12, marked@~0.3.6:
version "0.3.19"
@@ -8381,17 +8421,12 @@ monaco-editor@0.20.0, monaco-editor@^0.20.0:
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea"
integrity sha512-hkvf4EtPJRMQlPC3UbMoRs0vTAFAYdzFQ+gpMb8A+9znae1c43q8Mab9iVsgTcg/4PNiLGGn3SlDIa8uvK1FIQ==
-monaco-yaml@^2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-2.4.1.tgz#f0d3384b1f10cc7af2b60e3a30b0adc6683b728a"
- integrity sha512-Q0Yj6FNok97AslptS1OVfyX07rJ5uhOYsHKaVoU0usiUqeL7gzl6l8TL8W3QGdwCKm4WhfKpJ9bqPDtiQvCirg==
+monaco-yaml@^2.5.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-2.5.1.tgz#af9303a4aa6e3b94db62b8a8659362f31944590d"
+ integrity sha512-U+zIAcwnQzlUgy6vdzFdNf5PToFzuz099FxYmUxIeen9GTiq6XYDX9mmXSR31mMrgiSaU5a2bGEyG4p2fbW/7A==
dependencies:
- js-yaml "^3.12.0"
- vscode-json-languageservice "^3.4.11"
- vscode-languageserver "^5.2.1"
- vscode-uri "^2.1.1"
- optionalDependencies:
- prettier "^1.19.1"
+ yaml-language-server "^0.11.1"
mousetrap@1.6.5:
version "1.6.5"
@@ -9501,15 +9536,15 @@ pretender@^3.4.3:
fake-xml-http-request "^2.1.1"
route-recognizer "^0.3.3"
-prettier@1.18.2:
+prettier@1.18.2, prettier@^1.18.2:
version "1.18.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
-prettier@^1.18.2, prettier@^1.19.1:
- version "1.19.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
- integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
+prettier@2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
+ integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
pretty-format@^25.2.1, pretty-format@^25.5.0:
version "25.5.0"
@@ -10175,6 +10210,15 @@ replace-ext@1.0.0:
resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=
+request-light@^0.2.4:
+ version "0.2.5"
+ resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.5.tgz#38a3da7b2e56f7af8cbba57e8a94930ee2380746"
+ integrity sha512-eBEh+GzJAftUnex6tcL6eV2JCifY0+sZMIUpUPOVXbs2nV5hla4ZMmO3icYKGuGVuQ2zHE9evh4OrRcH4iyYYw==
+ dependencies:
+ http-proxy-agent "^2.1.0"
+ https-proxy-agent "^2.2.3"
+ vscode-nls "^4.1.1"
+
request-promise-core@1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
@@ -12247,15 +12291,15 @@ void-elements@^2.0.0:
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
-vscode-json-languageservice@^3.4.11:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.7.0.tgz#0174417f139cf41dd60c84538fd052385bfb46f6"
- integrity sha512-nGLqcBhTjdfkl8Dz9sYGK/ZCTjscYFoIjYw+qqkWB+vyNfM0k/AyIoT73DQvB/PArteCKjEVfQUF72GRZEDSbQ==
+vscode-json-languageservice@^3.6.0:
+ version "3.9.1"
+ resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.9.1.tgz#f72b581f8cd2bd9b47445ccf8b0ddcde6aba7483"
+ integrity sha512-oJkknkdCVitQ5XPSRa0weHjUxt8eSCptaL+MBQQlRsa6Nb8XnEY0S5wYnLUFHzEvKzwt01/LKk8LdOixWEXkNA==
dependencies:
- jsonc-parser "^2.2.1"
+ jsonc-parser "^2.3.1"
vscode-languageserver-textdocument "^1.0.1"
- vscode-languageserver-types "^3.15.1"
- vscode-nls "^4.1.2"
+ vscode-languageserver-types "3.16.0-next.2"
+ vscode-nls "^5.0.0"
vscode-uri "^2.1.2"
vscode-jsonrpc@^4.0.0:
@@ -12281,6 +12325,11 @@ vscode-languageserver-types@3.14.0:
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743"
integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A==
+vscode-languageserver-types@3.16.0-next.2:
+ version "3.16.0-next.2"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz#940bd15c992295a65eae8ab6b8568a1e8daa3083"
+ integrity sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q==
+
vscode-languageserver-types@^3.15.1:
version "3.15.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz#17be71d78d2f6236d414f0001ce1ef4d23e6b6de"
@@ -12294,11 +12343,16 @@ vscode-languageserver@^5.2.1:
vscode-languageserver-protocol "3.14.1"
vscode-uri "^1.0.6"
-vscode-nls@^4.1.2:
+vscode-nls@^4.1.1, vscode-nls@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167"
integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==
+vscode-nls@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840"
+ integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA==
+
vscode-uri@^1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.8.tgz#9769aaececae4026fb6e22359cb38946580ded59"
@@ -12869,6 +12923,28 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+yaml-ast-parser-custom-tags@0.0.43:
+ version "0.0.43"
+ resolved "https://registry.yarnpkg.com/yaml-ast-parser-custom-tags/-/yaml-ast-parser-custom-tags-0.0.43.tgz#46968145ce4e24cb03c3312057f0f141b93a7d02"
+ integrity sha512-R5063FF/JSAN6qXCmylwjt9PcDH6M0ExEme/nJBzLspc6FJDmHHIqM7xh2WfEmsTJqClF79A9VkXjkAqmZw9SQ==
+
+yaml-language-server@^0.11.1:
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/yaml-language-server/-/yaml-language-server-0.11.1.tgz#4ddc72eb9a6dd7dc41f31af2a8f5c72cce456cc9"
+ integrity sha512-N3Tu3g4O6ZWV7W0LVsNk62DtKJDQkbnPZRDd7ntaAeEl8QkxL1vnMunI26uzDU4PwwG4tPJ8g/VRS6U+fVp/6A==
+ dependencies:
+ js-yaml "^3.13.1"
+ jsonc-parser "^2.2.1"
+ request-light "^0.2.4"
+ vscode-json-languageservice "^3.6.0"
+ vscode-languageserver "^5.2.1"
+ vscode-languageserver-types "^3.15.1"
+ vscode-nls "^4.1.2"
+ vscode-uri "^2.1.1"
+ yaml-ast-parser-custom-tags "0.0.43"
+ optionalDependencies:
+ prettier "2.0.5"
+
yargs-parser@20.x:
version "20.2.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.1.tgz#28f3773c546cdd8a69ddae68116b48a5da328e77"